feat(anthropic): 支持 API Key 自动透传并优化透传链路性能

- 新增 Anthropic API Key 自动透传开关与后端透传分支(仅替换认证)

- 账号编辑页新增自动透传开关,默认关闭

- 优化透传性能:SSE usage 解析 gjson 快路径、减少请求体重复拷贝、优化流式写回与非流式 usage 解析

- 补充单元测试与 benchmark,确保 Claude OAuth 路径不受影响
This commit is contained in:
yangjianbo
2026-02-21 14:16:18 +08:00
parent 80510e5f16
commit bde9dbc57a
8 changed files with 1548 additions and 2 deletions

View File

@@ -735,6 +735,36 @@
</div>
</div>
<!-- Anthropic API Key 自动透传开关 -->
<div
v-if="account?.platform === 'anthropic' && account?.type === 'apikey'"
class="border-t border-gray-200 pt-4 dark:border-dark-600"
>
<div class="flex items-center justify-between">
<div>
<label class="input-label mb-0">{{ t('admin.accounts.anthropic.apiKeyPassthrough') }}</label>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
{{ t('admin.accounts.anthropic.apiKeyPassthroughDesc') }}
</p>
</div>
<button
type="button"
@click="anthropicPassthroughEnabled = !anthropicPassthroughEnabled"
:class="[
'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2',
anthropicPassthroughEnabled ? 'bg-primary-600' : 'bg-gray-200 dark:bg-dark-600'
]"
>
<span
:class="[
'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out',
anthropicPassthroughEnabled ? 'translate-x-5' : 'translate-x-0'
]"
/>
</button>
</div>
</div>
<!-- OpenAI OAuth Codex 官方客户端限制开关 -->
<div
v-if="account?.platform === 'openai' && account?.type === 'oauth'"
@@ -1223,6 +1253,7 @@ const cacheTTLOverrideTarget = ref<string>('5m')
// OpenAI 自动透传开关OAuth/API Key
const openaiPassthroughEnabled = ref(false)
const codexCLIOnlyEnabled = ref(false)
const anthropicPassthroughEnabled = ref(false)
const isOpenAIModelRestrictionDisabled = computed(() =>
props.account?.platform === 'openai' && openaiPassthroughEnabled.value
)
@@ -1317,12 +1348,16 @@ watch(
// Load OpenAI passthrough toggle (OpenAI OAuth/API Key)
openaiPassthroughEnabled.value = false
codexCLIOnlyEnabled.value = false
anthropicPassthroughEnabled.value = false
if (newAccount.platform === 'openai' && (newAccount.type === 'oauth' || newAccount.type === 'apikey')) {
openaiPassthroughEnabled.value = extra?.openai_passthrough === true || extra?.openai_oauth_passthrough === true
if (newAccount.type === 'oauth') {
codexCLIOnlyEnabled.value = extra?.codex_cli_only === true
}
}
if (newAccount.platform === 'anthropic' && newAccount.type === 'apikey') {
anthropicPassthroughEnabled.value = extra?.anthropic_passthrough === true
}
// Load antigravity model mapping (Antigravity 只支持映射模式)
if (newAccount.platform === 'antigravity') {
@@ -1882,6 +1917,18 @@ const handleSubmit = async () => {
updatePayload.extra = newExtra
}
// For Anthropic API Key accounts, handle passthrough mode in extra
if (props.account.platform === 'anthropic' && props.account.type === 'apikey') {
const currentExtra = (props.account.extra as Record<string, unknown>) || {}
const newExtra: Record<string, unknown> = { ...currentExtra }
if (anthropicPassthroughEnabled.value) {
newExtra.anthropic_passthrough = true
} else {
delete newExtra.anthropic_passthrough
}
updatePayload.extra = newExtra
}
// For OpenAI OAuth/API Key accounts, handle passthrough mode in extra
if (props.account.platform === 'openai' && (props.account.type === 'oauth' || props.account.type === 'apikey')) {
const currentExtra = (props.account.extra as Record<string, unknown>) || {}

View File

@@ -1546,6 +1546,11 @@ export default {
enableSora: 'Enable Sora simultaneously',
enableSoraHint: 'Sora uses the same OpenAI account. Enable to create Sora account simultaneously.'
},
anthropic: {
apiKeyPassthrough: 'Auto passthrough (auth only)',
apiKeyPassthroughDesc:
'Only applies to Anthropic API Key accounts. When enabled, messages/count_tokens are forwarded in passthrough mode with auth replacement only, while billing/concurrency/audit and safety filtering are preserved. Disable to roll back immediately.'
},
modelRestriction: 'Model Restriction (Optional)',
modelWhitelist: 'Model Whitelist',
modelMapping: 'Model Mapping',

View File

@@ -1694,6 +1694,11 @@ export default {
enableSora: '同时启用 Sora',
enableSoraHint: 'Sora 使用相同的 OpenAI 账号,开启后将同时创建 Sora 平台账号'
},
anthropic: {
apiKeyPassthrough: '自动透传(仅替换认证)',
apiKeyPassthroughDesc:
'仅对 Anthropic API Key 生效。开启后messages/count_tokens 请求将透传上游并仅替换认证,保留计费/并发/审计及必要安全过滤;关闭即可回滚到现有兼容链路。'
},
modelRestriction: '模型限制(可选)',
modelWhitelist: '模型白名单',
modelMapping: '模型映射',