Merge pull request #778 from miraserver/fix/droid-user-agent-and-provider

[fix] Droid: dynamic x-api-provider and custom User-Agent support
This commit is contained in:
Wesley Liddick
2025-12-07 19:25:56 -05:00
committed by GitHub
3 changed files with 72 additions and 8 deletions

View File

@@ -556,7 +556,8 @@ class DroidAccountService {
tokenType = 'Bearer', tokenType = 'Bearer',
authenticationMethod = '', authenticationMethod = '',
expiresIn = null, expiresIn = null,
apiKeys = [] apiKeys = [],
userAgent = '' // 自定义 User-Agent
} = options } = options
const accountId = uuidv4() const accountId = uuidv4()
@@ -832,7 +833,8 @@ class DroidAccountService {
: '', : '',
apiKeys: hasApiKeys ? JSON.stringify(apiKeyEntries) : '', apiKeys: hasApiKeys ? JSON.stringify(apiKeyEntries) : '',
apiKeyCount: hasApiKeys ? String(apiKeyEntries.length) : '0', apiKeyCount: hasApiKeys ? String(apiKeyEntries.length) : '0',
apiKeyStrategy: hasApiKeys ? 'random_sticky' : '' apiKeyStrategy: hasApiKeys ? 'random_sticky' : '',
userAgent: userAgent || '' // 自定义 User-Agent
} }
await redis.setDroidAccount(accountId, accountData) await redis.setDroidAccount(accountId, accountData)
@@ -931,6 +933,11 @@ class DroidAccountService {
sanitizedUpdates.endpointType = this._sanitizeEndpointType(sanitizedUpdates.endpointType) sanitizedUpdates.endpointType = this._sanitizeEndpointType(sanitizedUpdates.endpointType)
} }
// 处理 userAgent 字段
if (typeof sanitizedUpdates.userAgent === 'string') {
sanitizedUpdates.userAgent = sanitizedUpdates.userAgent.trim()
}
const parseProxyConfig = (value) => { const parseProxyConfig = (value) => {
if (!value) { if (!value) {
return null return null

View File

@@ -26,7 +26,7 @@ class DroidRelayService {
comm: '/o/v1/chat/completions' comm: '/o/v1/chat/completions'
} }
this.userAgent = 'factory-cli/0.19.12' this.userAgent = 'factory-cli/0.32.1'
this.systemPrompt = SYSTEM_PROMPT this.systemPrompt = SYSTEM_PROMPT
this.API_KEY_STICKY_PREFIX = 'droid_api_key' this.API_KEY_STICKY_PREFIX = 'droid_api_key'
} }
@@ -241,7 +241,8 @@ class DroidRelayService {
accessToken, accessToken,
normalizedRequestBody, normalizedRequestBody,
normalizedEndpoint, normalizedEndpoint,
clientHeaders clientHeaders,
account
) )
if (selectedApiKey) { 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 = { const headers = {
'content-type': 'application/json', 'content-type': 'application/json',
authorization: `Bearer ${accessToken}`, authorization: `Bearer ${accessToken}`,
'user-agent': this.userAgent, 'user-agent': userAgent,
'x-factory-client': 'cli', 'x-factory-client': 'cli',
connection: 'keep-alive' connection: 'keep-alive'
} }
@@ -1003,9 +1006,15 @@ class DroidRelayService {
} }
} }
// OpenAI 特定头 // OpenAI 特定头 - 根据模型动态选择 provider
if (endpointType === 'openai') { 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 // Comm 端点根据模型动态设置 provider

View File

@@ -1944,6 +1944,22 @@
rows="4" rows="4"
/> />
</div> </div>
<!-- Droid User-Agent 配置 (OAuth/Manual 模式) -->
<div v-if="form.platform === 'droid'">
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
>自定义 User-Agent (可选)</label
>
<input
v-model="form.userAgent"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
placeholder="factory-cli/0.32.1"
type="text"
/>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
留空使用默认值 factory-cli/0.32.1,可根据需要自定义
</p>
</div>
</div> </div>
<!-- API Key 模式输入 --> <!-- API Key 模式输入 -->
@@ -1989,6 +2005,22 @@
</p> </p>
</div> </div>
<!-- Droid User-Agent 配置 -->
<div>
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
>自定义 User-Agent (可选)</label
>
<input
v-model="form.userAgent"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
placeholder="factory-cli/0.32.1"
type="text"
/>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
留空使用默认值 factory-cli/0.32.1,可根据需要自定义
</p>
</div>
<div <div
class="rounded-lg border border-purple-200 bg-white/70 p-3 text-xs text-purple-800 dark:border-purple-700 dark:bg-purple-800/20 dark:text-purple-100" class="rounded-lg border border-purple-200 bg-white/70 p-3 text-xs text-purple-800 dark:border-purple-700 dark:bg-purple-800/20 dark:text-purple-100"
> >
@@ -3639,6 +3671,22 @@
</div> </div>
</div> </div>
<!-- Droid User-Agent 配置 (编辑模式) -->
<div v-if="form.platform === 'droid'">
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
>自定义 User-Agent (可选)</label
>
<input
v-model="form.userAgent"
class="form-input w-full border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
placeholder="factory-cli/0.32.1"
type="text"
/>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
留空使用默认值 factory-cli/0.32.1,可根据需要自定义
</p>
</div>
<!-- 代理设置 --> <!-- 代理设置 -->
<ProxyConfig v-model="form.proxy" /> <ProxyConfig v-model="form.proxy" />