merge: resolve upstream main conflicts for bulk OpenAI passthrough
This commit is contained in:
@@ -661,6 +661,43 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- OpenAI OAuth WS mode -->
|
||||
<div v-if="allOpenAIOAuth" class="border-t border-gray-200 pt-4 dark:border-dark-600">
|
||||
<div class="mb-3 flex items-center justify-between">
|
||||
<label
|
||||
id="bulk-edit-openai-ws-mode-label"
|
||||
class="input-label mb-0"
|
||||
for="bulk-edit-openai-ws-mode-enabled"
|
||||
>
|
||||
{{ t('admin.accounts.openai.wsMode') }}
|
||||
</label>
|
||||
<input
|
||||
v-model="enableOpenAIWSMode"
|
||||
id="bulk-edit-openai-ws-mode-enabled"
|
||||
type="checkbox"
|
||||
aria-controls="bulk-edit-openai-ws-mode"
|
||||
class="rounded border-gray-300 text-primary-600 focus:ring-primary-500"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
id="bulk-edit-openai-ws-mode"
|
||||
:class="!enableOpenAIWSMode && 'pointer-events-none opacity-50'"
|
||||
>
|
||||
<p class="mb-3 text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ t('admin.accounts.openai.wsModeDesc') }}
|
||||
</p>
|
||||
<p class="mb-3 text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ t(openAIWSModeConcurrencyHintKey) }}
|
||||
</p>
|
||||
<Select
|
||||
v-model="openaiOAuthResponsesWebSocketV2Mode"
|
||||
data-testid="bulk-edit-openai-ws-mode-select"
|
||||
:options="openAIWSModeOptions"
|
||||
aria-labelledby="bulk-edit-openai-ws-mode-label"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- RPM Limit (仅全部为 Anthropic OAuth/SetupToken 时显示) -->
|
||||
<div v-if="allAnthropicOAuthOrSetupToken" class="border-t border-gray-200 pt-4 dark:border-dark-600">
|
||||
<div class="mb-3 flex items-center justify-between">
|
||||
@@ -883,6 +920,13 @@ import {
|
||||
buildModelMappingObject as buildModelMappingPayload,
|
||||
getPresetMappingsByPlatform
|
||||
} from '@/composables/useModelWhitelist'
|
||||
import {
|
||||
OPENAI_WS_MODE_OFF,
|
||||
OPENAI_WS_MODE_PASSTHROUGH,
|
||||
isOpenAIWSModeEnabled,
|
||||
resolveOpenAIWSModeConcurrencyHintKey
|
||||
} from '@/utils/openaiWsMode'
|
||||
import type { OpenAIWSMode } from '@/utils/openaiWsMode'
|
||||
interface Props {
|
||||
show: boolean
|
||||
accountIds: number[]
|
||||
@@ -913,6 +957,15 @@ const allOpenAIPassthroughCapable = computed(() => {
|
||||
)
|
||||
})
|
||||
|
||||
const allOpenAIOAuth = computed(() => {
|
||||
return (
|
||||
props.selectedPlatforms.length === 1 &&
|
||||
props.selectedPlatforms[0] === 'openai' &&
|
||||
props.selectedTypes.length > 0 &&
|
||||
props.selectedTypes.every(t => t === 'oauth')
|
||||
)
|
||||
})
|
||||
|
||||
// 是否全部为 Anthropic OAuth/SetupToken(RPM 配置仅在此条件下显示)
|
||||
const allAnthropicOAuthOrSetupToken = computed(() => {
|
||||
return (
|
||||
@@ -957,6 +1010,7 @@ const enableRateMultiplier = ref(false)
|
||||
const enableStatus = ref(false)
|
||||
const enableGroups = ref(false)
|
||||
const enableOpenAIPassthrough = ref(false)
|
||||
const enableOpenAIWSMode = ref(false)
|
||||
const enableRpmLimit = ref(false)
|
||||
|
||||
// State - field values
|
||||
@@ -979,6 +1033,7 @@ const rateMultiplier = ref(1)
|
||||
const status = ref<'active' | 'inactive'>('active')
|
||||
const groupIds = ref<number[]>([])
|
||||
const openaiPassthroughEnabled = ref(false)
|
||||
const openaiOAuthResponsesWebSocketV2Mode = ref<OpenAIWSMode>(OPENAI_WS_MODE_OFF)
|
||||
const rpmLimitEnabled = ref(false)
|
||||
const bulkBaseRpm = ref<number | null>(null)
|
||||
const bulkRpmStrategy = ref<'tiered' | 'sticky_exempt'>('tiered')
|
||||
@@ -1005,10 +1060,19 @@ const statusOptions = computed(() => [
|
||||
{ value: 'active', label: t('common.active') },
|
||||
{ value: 'inactive', label: t('common.inactive') }
|
||||
])
|
||||
const isOpenAIModelRestrictionDisabled = computed(() =>
|
||||
allOpenAIPassthroughCapable.value &&
|
||||
enableOpenAIPassthrough.value &&
|
||||
openaiPassthroughEnabled.value
|
||||
const isOpenAIModelRestrictionDisabled = computed(
|
||||
() =>
|
||||
allOpenAIPassthroughCapable.value &&
|
||||
enableOpenAIPassthrough.value &&
|
||||
openaiPassthroughEnabled.value
|
||||
)
|
||||
|
||||
const openAIWSModeOptions = computed(() => [
|
||||
{ value: OPENAI_WS_MODE_OFF, label: t('admin.accounts.openai.wsModeOff') },
|
||||
{ value: OPENAI_WS_MODE_PASSTHROUGH, label: t('admin.accounts.openai.wsModePassthrough') }
|
||||
])
|
||||
const openAIWSModeConcurrencyHintKey = computed(() =>
|
||||
resolveOpenAIWSModeConcurrencyHintKey(openaiOAuthResponsesWebSocketV2Mode.value)
|
||||
)
|
||||
|
||||
// Model mapping helpers
|
||||
@@ -1180,6 +1244,14 @@ const buildUpdatePayload = (): Record<string, unknown> | null => {
|
||||
updates.credentials = credentials
|
||||
}
|
||||
|
||||
if (enableOpenAIWSMode.value) {
|
||||
const extra = ensureExtra()
|
||||
extra.openai_oauth_responses_websockets_v2_mode = openaiOAuthResponsesWebSocketV2Mode.value
|
||||
extra.openai_oauth_responses_websockets_v2_enabled = isOpenAIWSModeEnabled(
|
||||
openaiOAuthResponsesWebSocketV2Mode.value
|
||||
)
|
||||
}
|
||||
|
||||
// RPM limit settings (写入 extra 字段)
|
||||
if (enableRpmLimit.value) {
|
||||
const extra = ensureExtra()
|
||||
@@ -1269,6 +1341,7 @@ const handleSubmit = async () => {
|
||||
enableRateMultiplier.value ||
|
||||
enableStatus.value ||
|
||||
enableGroups.value ||
|
||||
enableOpenAIWSMode.value ||
|
||||
enableRpmLimit.value ||
|
||||
userMsgQueueMode.value !== null
|
||||
|
||||
@@ -1361,6 +1434,7 @@ watch(
|
||||
enableStatus.value = false
|
||||
enableGroups.value = false
|
||||
enableOpenAIPassthrough.value = false
|
||||
enableOpenAIWSMode.value = false
|
||||
enableRpmLimit.value = false
|
||||
|
||||
// Reset all values
|
||||
@@ -1379,6 +1453,7 @@ watch(
|
||||
rateMultiplier.value = 1
|
||||
status.value = 'active'
|
||||
groupIds.value = []
|
||||
openaiOAuthResponsesWebSocketV2Mode.value = OPENAI_WS_MODE_OFF
|
||||
rpmLimitEnabled.value = false
|
||||
bulkBaseRpm.value = null
|
||||
bulkRpmStrategy.value = 'tiered'
|
||||
|
||||
Reference in New Issue
Block a user