mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-24 16:05:44 +08:00
fix(frontend): enable ws mode editing for openai setup-token accounts
(cherry picked from commit 73031d1ba8079b2f369a11b3de9542f27bd61405) (cherry picked from commit acdbb9ce0471e5ab1009dc25e171a6497222347c)
This commit is contained in:
@@ -1195,7 +1195,7 @@ const allOpenAIPassthroughCapable = computed(() => {
|
||||
targetSelectedPlatforms.value.length === 1 &&
|
||||
targetSelectedPlatforms.value[0] === 'openai' &&
|
||||
targetSelectedTypes.value.length > 0 &&
|
||||
targetSelectedTypes.value.every(t => t === 'oauth' || t === 'apikey')
|
||||
targetSelectedTypes.value.every(t => t === 'oauth' || t === 'setup-token' || t === 'apikey')
|
||||
)
|
||||
})
|
||||
|
||||
@@ -1204,7 +1204,7 @@ const allOpenAIOAuth = computed(() => {
|
||||
targetSelectedPlatforms.value.length === 1 &&
|
||||
targetSelectedPlatforms.value[0] === 'openai' &&
|
||||
targetSelectedTypes.value.length > 0 &&
|
||||
targetSelectedTypes.value.every(t => t === 'oauth')
|
||||
targetSelectedTypes.value.every(t => t === 'oauth' || t === 'setup-token')
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -1342,7 +1342,7 @@
|
||||
|
||||
<!-- OpenAI 自动透传开关(OAuth/API Key) -->
|
||||
<div
|
||||
v-if="account?.platform === 'openai' && (account?.type === 'oauth' || account?.type === 'apikey')"
|
||||
v-if="account?.platform === 'openai' && (account?.type === 'oauth' || account?.type === 'setup-token' || account?.type === 'apikey')"
|
||||
class="border-t border-gray-200 pt-4 dark:border-dark-600"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
@@ -1372,7 +1372,7 @@
|
||||
|
||||
<!-- OpenAI Codex 图片生成桥接账号级覆盖 -->
|
||||
<div
|
||||
v-if="account?.platform === 'openai' && (account?.type === 'oauth' || account?.type === 'apikey')"
|
||||
v-if="account?.platform === 'openai' && (account?.type === 'oauth' || account?.type === 'setup-token' || account?.type === 'apikey')"
|
||||
class="border-t border-gray-200 pt-4 dark:border-dark-600"
|
||||
>
|
||||
<div class="overflow-hidden rounded-lg border border-sky-100 bg-sky-50/60 shadow-sm dark:border-sky-900/50 dark:bg-sky-950/20">
|
||||
@@ -1432,7 +1432,7 @@
|
||||
|
||||
<!-- OpenAI WS Mode 三态(off/ctx_pool/passthrough) -->
|
||||
<div
|
||||
v-if="account?.platform === 'openai' && (account?.type === 'oauth' || account?.type === 'apikey')"
|
||||
v-if="account?.platform === 'openai' && (account?.type === 'oauth' || account?.type === 'setup-token' || account?.type === 'apikey')"
|
||||
class="border-t border-gray-200 pt-4 dark:border-dark-600"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
@@ -1446,7 +1446,7 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="w-52">
|
||||
<Select v-model="openaiResponsesWebSocketV2Mode" :options="openAIWSModeOptions" />
|
||||
<Select v-model="openaiResponsesWebSocketV2Mode" data-testid="edit-openai-ws-mode-select" :options="openAIWSModeOptions" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1662,7 +1662,7 @@
|
||||
|
||||
<!-- OpenAI OAuth Codex 官方客户端限制开关 -->
|
||||
<div
|
||||
v-if="account?.platform === 'openai' && account?.type === 'oauth'"
|
||||
v-if="account?.platform === 'openai' && (account?.type === 'oauth' || account?.type === 'setup-token')"
|
||||
class="border-t border-gray-200 pt-4 dark:border-dark-600"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
@@ -1717,7 +1717,7 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="account?.platform === 'openai' && (account?.type === 'oauth' || account?.type === 'apikey')"
|
||||
v-if="account?.platform === 'openai' && (account?.type === 'oauth' || account?.type === 'setup-token' || account?.type === 'apikey')"
|
||||
class="border-t border-gray-200 pt-4 dark:border-dark-600 space-y-4"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
@@ -2979,7 +2979,7 @@ const syncFormFromAccount = (newAccount: Account | null) => {
|
||||
autoPause5hDisabled.value = extra?.auto_pause_5h_disabled === true
|
||||
autoPause7dDisabled.value = extra?.auto_pause_7d_disabled === true
|
||||
|
||||
// Load OpenAI passthrough toggle (OpenAI OAuth/API Key)
|
||||
// Load OpenAI passthrough toggle (OpenAI OAuth/SetupToken/API Key)
|
||||
openaiPassthroughEnabled.value = false
|
||||
openAICompactMode.value = 'auto'
|
||||
openAIResponsesMode.value = 'auto'
|
||||
@@ -2992,7 +2992,7 @@ const syncFormFromAccount = (newAccount: Account | null) => {
|
||||
codexImageGenerationBridgeMode.value = 'inherit'
|
||||
anthropicPassthroughEnabled.value = false
|
||||
webSearchEmulationMode.value = 'default'
|
||||
if (newAccount.platform === 'openai' && (newAccount.type === 'oauth' || newAccount.type === 'apikey')) {
|
||||
if (newAccount.platform === 'openai' && (newAccount.type === 'oauth' || newAccount.type === 'setup-token' || newAccount.type === 'apikey')) {
|
||||
openaiPassthroughEnabled.value = extra?.openai_passthrough === true || extra?.openai_oauth_passthrough === true
|
||||
openAICompactMode.value = (extra?.openai_compact_mode as OpenAICompactMode) || 'auto'
|
||||
if (newAccount.type === 'apikey') {
|
||||
@@ -3024,7 +3024,7 @@ const syncFormFromAccount = (newAccount: Account | null) => {
|
||||
fallbackEnabledKeys: ['responses_websockets_v2_enabled', 'openai_ws_enabled'],
|
||||
defaultMode: OPENAI_WS_MODE_OFF
|
||||
})
|
||||
if (newAccount.type === 'oauth') {
|
||||
if (newAccount.type === 'oauth' || newAccount.type === 'setup-token') {
|
||||
codexCLIOnlyEnabled.value = extra?.codex_cli_only === true
|
||||
codexCLIOnlyAppServerEnabled.value =
|
||||
extra?.codex_cli_only_allow_app_server === true
|
||||
@@ -4101,12 +4101,12 @@ const handleSubmit = async () => {
|
||||
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>) || {}
|
||||
const newExtra: Record<string, unknown> = { ...currentExtra }
|
||||
// For OpenAI OAuth/SetupToken/API Key accounts, handle passthrough mode in extra
|
||||
if (props.account.platform === 'openai' && (props.account.type === 'oauth' || props.account.type === 'setup-token' || props.account.type === 'apikey')) {
|
||||
const currentExtra = (props.account.extra as Record<string, unknown>) || {}
|
||||
const newExtra: Record<string, unknown> = { ...currentExtra }
|
||||
const hadCodexCLIOnlyEnabled = currentExtra.codex_cli_only === true
|
||||
if (props.account.type === 'oauth') {
|
||||
if (props.account.type === 'oauth' || props.account.type === 'setup-token') {
|
||||
newExtra.openai_oauth_responses_websockets_v2_mode = openaiOAuthResponsesWebSocketV2Mode.value
|
||||
newExtra.openai_oauth_responses_websockets_v2_enabled = isOpenAIWSModeEnabled(openaiOAuthResponsesWebSocketV2Mode.value)
|
||||
} else if (props.account.type === 'apikey') {
|
||||
@@ -4161,7 +4161,7 @@ const handleSubmit = async () => {
|
||||
newExtra.codex_image_generation_bridge = codexImageGenerationBridgeMode.value === 'enabled'
|
||||
}
|
||||
|
||||
if (props.account.type === 'oauth') {
|
||||
if (props.account.type === 'oauth' || props.account.type === 'setup-token') {
|
||||
if (codexCLIOnlyEnabled.value) {
|
||||
newExtra.codex_cli_only = true
|
||||
} else if (hadCodexCLIOnlyEnabled) {
|
||||
|
||||
@@ -192,6 +192,17 @@ function buildAntigravityAccount(projectId = 'configured-project') {
|
||||
} as any
|
||||
}
|
||||
|
||||
function buildOpenAISetupTokenAccount() {
|
||||
return {
|
||||
...buildAccount(),
|
||||
type: 'setup-token',
|
||||
extra: {
|
||||
openai_oauth_responses_websockets_v2_mode: 'ctx_pool',
|
||||
openai_oauth_responses_websockets_v2_enabled: true
|
||||
}
|
||||
} as any
|
||||
}
|
||||
|
||||
function mountModal(account = buildAccount()) {
|
||||
return mount(EditAccountModal, {
|
||||
props: {
|
||||
@@ -487,6 +498,23 @@ describe('EditAccountModal', () => {
|
||||
expect(updateAccountMock.mock.calls[0]?.[1]?.extra).not.toHaveProperty('codex_image_generation_bridge_enabled')
|
||||
})
|
||||
|
||||
it('setup-token account can select and submit OAuth WS mode', async () => {
|
||||
const account = buildOpenAISetupTokenAccount()
|
||||
updateAccountMock.mockReset()
|
||||
checkMixedChannelRiskMock.mockReset()
|
||||
checkMixedChannelRiskMock.mockResolvedValue({ has_risk: false })
|
||||
updateAccountMock.mockResolvedValue(account)
|
||||
|
||||
const wrapper = mountModal(account)
|
||||
|
||||
await wrapper.get('[data-testid="edit-openai-ws-mode-select"]').setValue('http_bridge')
|
||||
await wrapper.get('form#edit-account-form').trigger('submit.prevent')
|
||||
|
||||
expect(updateAccountMock).toHaveBeenCalledTimes(1)
|
||||
expect(updateAccountMock.mock.calls[0]?.[1]?.extra?.openai_oauth_responses_websockets_v2_mode).toBe('http_bridge')
|
||||
expect(updateAccountMock.mock.calls[0]?.[1]?.extra?.openai_oauth_responses_websockets_v2_enabled).toBe(true)
|
||||
})
|
||||
|
||||
it('allows saving apikey account when backend redacted api_key but credentials_status reports it exists', async () => {
|
||||
// 新前端 + 新后端:响应已脱敏,credentials 里没有 api_key,credentials_status.has_api_key=true
|
||||
const account = buildAccount()
|
||||
|
||||
Reference in New Issue
Block a user