feat(openai): 增加 OAuth 账号 Codex 官方客户端限制开关

新增 codex_cli_only 开关并默认关闭,关闭时完全绕过限制逻辑。
在 OpenAI 网关引入统一检测入口,集中判定账号类型、开关与客户端族。
开启后仅放行 codex_cli_rs、codex_vscode、codex_app 客户端家族。
补充后端判定与网关分支测试,并在前端创建/编辑页增加开关配置与回显。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
yangjianbo
2026-02-12 22:32:59 +08:00
parent 2f190d812a
commit a9518cc5be
13 changed files with 671 additions and 4 deletions

View File

@@ -735,6 +735,36 @@
</div>
</div>
<!-- OpenAI OAuth Codex 官方客户端限制开关 -->
<div
v-if="account?.platform === 'openai' && account?.type === 'oauth'"
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.openai.codexCLIOnly') }}</label>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
{{ t('admin.accounts.openai.codexCLIOnlyDesc') }}
</p>
</div>
<button
type="button"
@click="codexCLIOnlyEnabled = !codexCLIOnlyEnabled"
: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',
codexCLIOnlyEnabled ? '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',
codexCLIOnlyEnabled ? 'translate-x-5' : 'translate-x-0'
]"
/>
</button>
</div>
</div>
<div>
<div class="flex items-center justify-between">
<div>
@@ -1146,6 +1176,7 @@ const sessionIdMaskingEnabled = ref(false)
// OpenAI 自动透传开关OAuth/API Key
const openaiPassthroughEnabled = ref(false)
const codexCLIOnlyEnabled = ref(false)
const isOpenAIModelRestrictionDisabled = computed(() =>
props.account?.platform === 'openai' && openaiPassthroughEnabled.value
)
@@ -1239,8 +1270,12 @@ watch(
// Load OpenAI passthrough toggle (OpenAI OAuth/API Key)
openaiPassthroughEnabled.value = false
codexCLIOnlyEnabled.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
}
}
// Load antigravity model mapping (Antigravity 只支持映射模式)
@@ -1794,6 +1829,13 @@ const handleSubmit = async () => {
delete newExtra.openai_passthrough
delete newExtra.openai_oauth_passthrough
}
if (props.account.type === 'oauth' && codexCLIOnlyEnabled.value) {
newExtra.codex_cli_only = true
} else {
delete newExtra.codex_cli_only
}
updatePayload.extra = newExtra
}