feat(openai-ws): add http_bridge ingress mode and account ws selector

(cherry picked from commit 58647ff63d7ff994c7c14c84c4913a8d3ed6be05)
(cherry picked from commit 9f18fb7c24e187fb20e90d1d9e89fcec91c56937)
This commit is contained in:
zy6p
2026-06-30 10:40:05 +08:00
parent 55902d8548
commit 901958ba1b
18 changed files with 201 additions and 17 deletions
@@ -1153,6 +1153,7 @@ import {
OPENAI_WS_MODE_CTX_POOL,
OPENAI_WS_MODE_OFF,
OPENAI_WS_MODE_PASSTHROUGH,
OPENAI_WS_MODE_HTTP_BRIDGE,
isOpenAIWSModeEnabled,
resolveOpenAIWSModeConcurrencyHintKey
} from '@/utils/openaiWsMode'
@@ -1330,7 +1331,8 @@ const isOpenAIModelRestrictionDisabled = computed(
const openAIWSModeOptions = computed(() => [
{ value: OPENAI_WS_MODE_OFF, label: t('admin.accounts.openai.wsModeOff') },
{ value: OPENAI_WS_MODE_CTX_POOL, label: t('admin.accounts.openai.wsModeCtxPool') },
{ value: OPENAI_WS_MODE_PASSTHROUGH, label: t('admin.accounts.openai.wsModePassthrough') }
{ value: OPENAI_WS_MODE_PASSTHROUGH, label: t('admin.accounts.openai.wsModePassthrough') },
{ value: OPENAI_WS_MODE_HTTP_BRIDGE, label: t('admin.accounts.openai.wsModeHttpBridge') }
])
const openAICompactModeOptions = computed(() => [
{ value: 'auto', label: t('admin.accounts.openai.compactModeAuto') },
@@ -3313,6 +3313,7 @@ import {
OPENAI_WS_MODE_CTX_POOL,
OPENAI_WS_MODE_OFF,
OPENAI_WS_MODE_PASSTHROUGH,
OPENAI_WS_MODE_HTTP_BRIDGE,
isOpenAIWSModeEnabled,
resolveOpenAIWSModeConcurrencyHintKey,
type OpenAIWSMode
@@ -3677,7 +3678,8 @@ const geminiSelectedTier = computed(() => {
const openAIWSModeOptions = computed(() => [
{ value: OPENAI_WS_MODE_OFF, label: t('admin.accounts.openai.wsModeOff') },
{ value: OPENAI_WS_MODE_CTX_POOL, label: t('admin.accounts.openai.wsModeCtxPool') },
{ value: OPENAI_WS_MODE_PASSTHROUGH, label: t('admin.accounts.openai.wsModePassthrough') }
{ value: OPENAI_WS_MODE_PASSTHROUGH, label: t('admin.accounts.openai.wsModePassthrough') },
{ value: OPENAI_WS_MODE_HTTP_BRIDGE, label: t('admin.accounts.openai.wsModeHttpBridge') }
])
const openaiResponsesWebSocketV2Mode = computed({
@@ -2424,6 +2424,7 @@ import {
OPENAI_WS_MODE_CTX_POOL,
OPENAI_WS_MODE_OFF,
OPENAI_WS_MODE_PASSTHROUGH,
OPENAI_WS_MODE_HTTP_BRIDGE,
isOpenAIWSModeEnabled,
resolveOpenAIWSModeConcurrencyHintKey,
type OpenAIWSMode,
@@ -2636,7 +2637,8 @@ const editResetTimezone = ref<string | null>(null)
const openAIWSModeOptions = computed(() => [
{ value: OPENAI_WS_MODE_OFF, label: t('admin.accounts.openai.wsModeOff') },
{ value: OPENAI_WS_MODE_CTX_POOL, label: t('admin.accounts.openai.wsModeCtxPool') },
{ value: OPENAI_WS_MODE_PASSTHROUGH, label: t('admin.accounts.openai.wsModePassthrough') }
{ value: OPENAI_WS_MODE_PASSTHROUGH, label: t('admin.accounts.openai.wsModePassthrough') },
{ value: OPENAI_WS_MODE_HTTP_BRIDGE, label: t('admin.accounts.openai.wsModeHttpBridge') }
])
const openaiResponsesWebSocketV2Mode = computed({
get: () => {
@@ -149,21 +149,21 @@ describe('BulkEditAccountModal', () => {
})
})
it('OpenAI OAuth 批量编辑应提交 OAuth 专属 WS mode 字段', async () => {
it('OpenAI OAuth 批量编辑应提交 OAuth 专属 WS mode 字段(含 http_bridge)', async () => {
const wrapper = mountModal({
selectedPlatforms: ['openai'],
selectedTypes: ['oauth']
})
await wrapper.get('#bulk-edit-openai-ws-mode-enabled').setValue(true)
await wrapper.get('[data-testid="bulk-edit-openai-ws-mode-select"]').setValue('passthrough')
await wrapper.get('[data-testid="bulk-edit-openai-ws-mode-select"]').setValue('http_bridge')
await wrapper.get('#bulk-edit-account-form').trigger('submit.prevent')
await flushPromises()
expect(adminAPI.accounts.bulkUpdate).toHaveBeenCalledTimes(1)
expect(adminAPI.accounts.bulkUpdate).toHaveBeenCalledWith([1, 2], {
extra: {
openai_oauth_responses_websockets_v2_mode: 'passthrough',
openai_oauth_responses_websockets_v2_mode: 'http_bridge',
openai_oauth_responses_websockets_v2_enabled: true
}
})
+1
View File
@@ -3425,6 +3425,7 @@ export default {
wsModeOff: 'Off (off)',
wsModeCtxPool: 'Context Pool (ctx_pool)',
wsModePassthrough: 'Passthrough (passthrough)',
wsModeHttpBridge: 'HTTP Bridge (http_bridge)',
wsModeShared: 'Shared (shared)',
wsModeDedicated: 'Dedicated (dedicated)',
wsModeConcurrencyHint:
+1
View File
@@ -3598,6 +3598,7 @@ export default {
wsModeOff: '关闭(off)',
wsModeCtxPool: '上下文池(ctx_pool)',
wsModePassthrough: '透传(passthrough)',
wsModeHttpBridge: 'HTTP 桥接(http_bridge)',
wsModeShared: '共享(shared)',
wsModeDedicated: '独享(dedicated)',
wsModeConcurrencyHint: '启用 WS mode 后,该账号并发数将作为该账号 WS 连接池上限。',
@@ -1,6 +1,7 @@
import { describe, expect, it } from 'vitest'
import {
OPENAI_WS_MODE_CTX_POOL,
OPENAI_WS_MODE_HTTP_BRIDGE,
OPENAI_WS_MODE_OFF,
OPENAI_WS_MODE_PASSTHROUGH,
isOpenAIWSModeEnabled,
@@ -15,6 +16,7 @@ describe('openaiWsMode utils', () => {
expect(normalizeOpenAIWSMode('off')).toBe(OPENAI_WS_MODE_OFF)
expect(normalizeOpenAIWSMode('ctx_pool')).toBe(OPENAI_WS_MODE_CTX_POOL)
expect(normalizeOpenAIWSMode('passthrough')).toBe(OPENAI_WS_MODE_PASSTHROUGH)
expect(normalizeOpenAIWSMode('http_bridge')).toBe(OPENAI_WS_MODE_HTTP_BRIDGE)
expect(normalizeOpenAIWSMode(' Shared ')).toBe(OPENAI_WS_MODE_CTX_POOL)
expect(normalizeOpenAIWSMode('DEDICATED')).toBe(OPENAI_WS_MODE_CTX_POOL)
expect(normalizeOpenAIWSMode('invalid')).toBeNull()
@@ -54,6 +56,7 @@ describe('openaiWsMode utils', () => {
expect(isOpenAIWSModeEnabled(OPENAI_WS_MODE_OFF)).toBe(false)
expect(isOpenAIWSModeEnabled(OPENAI_WS_MODE_CTX_POOL)).toBe(true)
expect(isOpenAIWSModeEnabled(OPENAI_WS_MODE_PASSTHROUGH)).toBe(true)
expect(isOpenAIWSModeEnabled(OPENAI_WS_MODE_HTTP_BRIDGE)).toBe(true)
})
it('resolves concurrency hint key by mode', () => {
@@ -66,5 +69,8 @@ describe('openaiWsMode utils', () => {
expect(resolveOpenAIWSModeConcurrencyHintKey(OPENAI_WS_MODE_PASSTHROUGH)).toBe(
'admin.accounts.openai.wsModePassthroughHint'
)
expect(resolveOpenAIWSModeConcurrencyHintKey(OPENAI_WS_MODE_HTTP_BRIDGE)).toBe(
'admin.accounts.openai.wsModePassthroughHint'
)
})
})
+5 -2
View File
@@ -1,16 +1,19 @@
export const OPENAI_WS_MODE_OFF = 'off'
export const OPENAI_WS_MODE_CTX_POOL = 'ctx_pool'
export const OPENAI_WS_MODE_PASSTHROUGH = 'passthrough'
export const OPENAI_WS_MODE_HTTP_BRIDGE = 'http_bridge'
export type OpenAIWSMode =
| typeof OPENAI_WS_MODE_OFF
| typeof OPENAI_WS_MODE_CTX_POOL
| typeof OPENAI_WS_MODE_PASSTHROUGH
| typeof OPENAI_WS_MODE_HTTP_BRIDGE
const OPENAI_WS_MODES = new Set<OpenAIWSMode>([
OPENAI_WS_MODE_OFF,
OPENAI_WS_MODE_CTX_POOL,
OPENAI_WS_MODE_PASSTHROUGH
OPENAI_WS_MODE_PASSTHROUGH,
OPENAI_WS_MODE_HTTP_BRIDGE
])
export interface ResolveOpenAIWSModeOptions {
@@ -44,7 +47,7 @@ export const isOpenAIWSModeEnabled = (mode: OpenAIWSMode): boolean => {
export const resolveOpenAIWSModeConcurrencyHintKey = (
mode: OpenAIWSMode
): 'admin.accounts.openai.wsModeConcurrencyHint' | 'admin.accounts.openai.wsModePassthroughHint' => {
if (mode === OPENAI_WS_MODE_PASSTHROUGH) {
if (mode === OPENAI_WS_MODE_PASSTHROUGH || mode === OPENAI_WS_MODE_HTTP_BRIDGE) {
return 'admin.accounts.openai.wsModePassthroughHint'
}
return 'admin.accounts.openai.wsModeConcurrencyHint'