chore: 统一所有 provider 的 User-Agent 为 csc/${VERSION}

- getUserAgent() 简化为 csc/${VERSION},去除 USER_TYPE/entrypoint 等附加信息
- OpenAI/Grok client 通过 defaultHeaders 覆盖 SDK 自带的 User-Agent
- CoStrict 主查询和 sideQuery 的 OpenAI client 同步添加 defaultHeaders
- CoStrict fetch 的 X-Costrict-Version 同步更新为 csc/${VERSION} 格式

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Askhz 2026-04-29 18:23:57 +08:00
parent 2f7fc7959d
commit 307b025dea
6 changed files with 11 additions and 2 deletions

View File

@ -89,6 +89,7 @@ export function createCoStrictFetch(): CoStrictFetch {
// ========== 步骤 3: 构建 headers ==========
const headers = new Headers(init?.headers)
headers.set('Authorization', `Bearer ${creds.access_token}`)
headers.set('User-Agent', `csc/${VERSION}`)
headers.set('HTTP-Referer', 'https://github.com/zgsm-ai/costrict-cli')
headers.set('X-Title', 'CoStrict-CLI')
headers.set('X-Costrict-Version', `costrict-cli-${VERSION}`)

View File

@ -16,6 +16,7 @@ import type { Tools } from '../../Tool.js'
import type { Options } from '../../services/api/claude.js'
import OpenAI from 'openai'
import { getProxyFetchOptions } from '../../utils/proxy.js'
import { getUserAgent } from '../../utils/http.js'
import { anthropicMessagesToOpenAI, anthropicToolsToOpenAI, anthropicToolChoiceToOpenAI, adaptOpenAIStreamToAnthropic } from '@ant/model-provider'
import { normalizeMessagesForAPI } from '../../utils/messages.js'
import { toolToAPISchema } from '../../utils/api.js'
@ -103,6 +104,7 @@ export async function* queryModelCoStrict(
forAnthropicAPI: false,
}) as any,
fetch: costrictFetch as any,
defaultHeaders: { 'User-Agent': getUserAgent() },
})
logForDebugging(

View File

@ -1,5 +1,6 @@
import OpenAI from 'openai'
import { getProxyFetchOptions } from 'src/utils/proxy.js'
import { getUserAgent } from 'src/utils/http.js'
/**
* Environment variables:
@ -30,6 +31,7 @@ export function getGrokClient(options?: {
dangerouslyAllowBrowser: true,
fetchOptions: getProxyFetchOptions({ forAnthropicAPI: false }),
...(options?.fetchOverride && { fetch: options.fetchOverride }),
defaultHeaders: { 'User-Agent': getUserAgent() },
})
if (!options?.fetchOverride) {

View File

@ -3,6 +3,7 @@ import { openaiAdapter } from 'src/services/providerUsage/adapters/openai.js'
import { updateProviderBuckets } from 'src/services/providerUsage/store.js'
import { getProxyFetchOptions } from 'src/utils/proxy.js'
import { isEnvTruthy } from 'src/utils/envUtils.js'
import { getUserAgent } from 'src/utils/http.js'
/**
* Environment variables:
@ -60,6 +61,7 @@ export function getOpenAIClient(options?: {
...(process.env.OPENAI_PROJECT_ID && { project: process.env.OPENAI_PROJECT_ID }),
fetchOptions: getProxyFetchOptions({ forAnthropicAPI: false }),
fetch: wrappedFetch,
defaultHeaders: { 'User-Agent': getUserAgent() },
})
if (!options?.fetchOverride) {

View File

@ -31,7 +31,7 @@ export function getUserAgent(): string {
// so the read picks up the same setWorkload() value as getAttributionHeader.
const workload = getWorkload()
const workloadSuffix = workload ? `, workload/${workload}` : ''
return `claude-cli/${MACRO.VERSION} (${process.env.USER_TYPE}, ${process.env.CLAUDE_CODE_ENTRYPOINT ?? 'cli'}${agentSdkVersion}${clientApp}${workloadSuffix})`
return `csc/${MACRO.VERSION}`
}
export function getMCPUserAgent(): string {
@ -46,7 +46,7 @@ export function getMCPUserAgent(): string {
parts.push(`client-app/${process.env.CLAUDE_AGENT_SDK_CLIENT_APP}`)
}
const suffix = parts.length > 0 ? ` (${parts.join(', ')})` : ''
return `claude-code/${MACRO.VERSION}${suffix}`
return `csc/${MACRO.VERSION}${suffix}`
}
// User-Agent for WebFetch requests to arbitrary sites. `Claude-User` is

View File

@ -32,6 +32,7 @@ import { resolveCoStrictModel } from '../costrict/provider/modelMapping.js'
import { getCoStrictBaseURL } from '../costrict/provider/auth.js'
import { loadCoStrictCredentials } from '../costrict/provider/credentials.js'
import { getProxyFetchOptions } from './proxy.js'
import { getUserAgent } from './http.js'
import { getMainLoopModel } from './model/model.js'
import OpenAI from 'openai'
@ -145,6 +146,7 @@ export async function sideQuery(opts: SideQueryOptions): Promise<BetaMessage> {
dangerouslyAllowBrowser: true,
fetchOptions: getProxyFetchOptions({ forAnthropicAPI: false }) as Record<string, unknown>,
fetch: createCoStrictFetch() as unknown as typeof fetch,
defaultHeaders: { 'User-Agent': getUserAgent() },
})
return sideQueryOpenAICompat(opts, client, resolveCoStrictModel(getMainLoopModel()), 'CoStrict')
}