mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-31 00:24:38 +00:00
fix(openai): make Codex fingerprint convergence opt-in and cover passthrough
Default codex_fingerprint_mode to off. v0.1.175 treated a missing key as "session", so upgrading silently rewrote installation/session/thread/turn/ window identifiers for every existing OAuth account that had never configured this field. The quota regressions in #5555, #5556 and #5582 line up with that version boundary, with A/B reports that rolling back to v0.1.173 restores quota. Convergence is now explicit opt-in (#5610). Only accounts that never set the field change behaviour; explicit off / device / session / full keep working exactly as configured. That required flipping the persistence condition in all three account modals from "!== 'session'" to "!== 'off'": the old rule deleted the key when it equalled the default, which after the flip would have silently discarded an administrator's explicit opt-in to session. Also extend convergence to the passthrough path, which previously left client identifiers untouched: - resolve the ids once in forwardOpenAIPassthrough and rewrite client_metadata on the raw bytes (gjson extract + sjson splice) because passthrough is a hot path that must not fully unmarshal multi-MB bodies; a shared core keeps the raw and map variants from drifting - both request builders apply the staged ids at the same relative position (after session isolation, before identity enforcement) so headers and body share one id set and turn_id stays consistent - stage the ids unconditionally, including nil: a failover from a converged account to an off account must not leave the previous account's ids behind
This commit is contained in:
@@ -1535,7 +1535,7 @@ const codexCLIOnlyEnabled = ref(false)
|
||||
const codexCLIOnlyAppServerEnabled = ref(false)
|
||||
type CodexFingerprintMode = 'off' | 'device' | 'session' | 'full'
|
||||
const enableCodexFingerprintMode = ref(false)
|
||||
const codexFingerprintMode = ref<CodexFingerprintMode>('session')
|
||||
const codexFingerprintMode = ref<CodexFingerprintMode>('off')
|
||||
const codexFingerprintModeOptions = computed(() => [
|
||||
{ value: 'off' as CodexFingerprintMode, label: t('admin.accounts.openai.codexFingerprintOff') },
|
||||
{ value: 'device' as CodexFingerprintMode, label: t('admin.accounts.openai.codexFingerprintDevice') },
|
||||
@@ -1829,7 +1829,8 @@ const buildUpdatePayload = (): Record<string, unknown> | null => {
|
||||
|
||||
if (enableCodexFingerprintMode.value) {
|
||||
const extra = ensureExtra()
|
||||
if (codexFingerprintMode.value !== 'session') {
|
||||
// off = 默认值,清键即可;device/session/full 是显式 opt-in,必须落键(#5610)。
|
||||
if (codexFingerprintMode.value !== 'off') {
|
||||
extra.codex_fingerprint_mode = codexFingerprintMode.value
|
||||
} else {
|
||||
delete extra.codex_fingerprint_mode
|
||||
@@ -2082,7 +2083,7 @@ watch(
|
||||
enableCodexCLIOnly.value = false
|
||||
enableCodexCLIOnlyAppServer.value = false
|
||||
enableCodexFingerprintMode.value = false
|
||||
codexFingerprintMode.value = 'session'
|
||||
codexFingerprintMode.value = 'off'
|
||||
enableOpenAICompactMode.value = false
|
||||
enableOpenAICompactModelMapping.value = false
|
||||
enableRpmLimit.value = false
|
||||
|
||||
@@ -3855,7 +3855,7 @@ const openaiAPIKeyResponsesWebSocketV2Mode = ref<OpenAIWSMode>(OPENAI_WS_MODE_OF
|
||||
const codexCLIOnlyEnabled = ref(false)
|
||||
const codexCLIOnlyAppServerEnabled = ref(false)
|
||||
type CodexFingerprintMode = 'off' | 'device' | 'session' | 'full'
|
||||
const codexFingerprintMode = ref<CodexFingerprintMode>('session')
|
||||
const codexFingerprintMode = ref<CodexFingerprintMode>('off')
|
||||
const codexFingerprintModeOptions = computed(() => [
|
||||
{ value: 'off' as CodexFingerprintMode, label: t('admin.accounts.openai.codexFingerprintOff') },
|
||||
{ value: 'device' as CodexFingerprintMode, label: t('admin.accounts.openai.codexFingerprintDevice') },
|
||||
@@ -4741,7 +4741,7 @@ const resetForm = () => {
|
||||
openaiAPIKeyResponsesWebSocketV2Mode.value = OPENAI_WS_MODE_OFF
|
||||
codexCLIOnlyEnabled.value = false
|
||||
codexCLIOnlyAppServerEnabled.value = false
|
||||
codexFingerprintMode.value = 'session'
|
||||
codexFingerprintMode.value = 'off'
|
||||
anthropicPassthroughEnabled.value = false
|
||||
anthropicAPIKeyAuthScheme.value = 'x_api_key'
|
||||
webSearchEmulationMode.value = 'default'
|
||||
@@ -4840,7 +4840,9 @@ const buildOpenAIExtra = (base?: Record<string, unknown>): Record<string, unknow
|
||||
} else {
|
||||
delete extra.codex_cli_only_allow_app_server
|
||||
}
|
||||
if (codexFingerprintMode.value !== 'session') {
|
||||
// 收敛是显式 opt-in:off 即默认值,不落键;device/session/full 必须显式写入,
|
||||
// 否则管理员的选择会被当成默认而丢失(#5610)。
|
||||
if (codexFingerprintMode.value !== 'off') {
|
||||
extra.codex_fingerprint_mode = codexFingerprintMode.value
|
||||
} else {
|
||||
delete extra.codex_fingerprint_mode
|
||||
|
||||
@@ -2980,7 +2980,7 @@ const openaiAPIKeyResponsesWebSocketV2Mode = ref<OpenAIWSMode>(OPENAI_WS_MODE_OF
|
||||
const codexCLIOnlyEnabled = ref(false)
|
||||
const codexCLIOnlyAppServerEnabled = ref(false)
|
||||
type CodexFingerprintMode = 'off' | 'device' | 'session' | 'full'
|
||||
const codexFingerprintMode = ref<CodexFingerprintMode>('session')
|
||||
const codexFingerprintMode = ref<CodexFingerprintMode>('off')
|
||||
type CodexImageToolMode = 'inherit' | 'enabled' | 'disabled' | 'block'
|
||||
const codexImageToolMode = ref<CodexImageToolMode>('inherit')
|
||||
type AnthropicAPIKeyAuthScheme = 'x_api_key' | 'authorization_bearer'
|
||||
@@ -3440,7 +3440,7 @@ const syncFormFromAccount = (newAccount: Account | null) => {
|
||||
openaiAPIKeyResponsesWebSocketV2Mode.value = OPENAI_WS_MODE_OFF
|
||||
codexCLIOnlyEnabled.value = false
|
||||
codexCLIOnlyAppServerEnabled.value = false
|
||||
codexFingerprintMode.value = 'session'
|
||||
codexFingerprintMode.value = 'off'
|
||||
codexImageToolMode.value = 'inherit'
|
||||
anthropicPassthroughEnabled.value = false
|
||||
anthropicAPIKeyAuthScheme.value = 'x_api_key'
|
||||
@@ -3494,9 +3494,10 @@ const syncFormFromAccount = (newAccount: Account | null) => {
|
||||
}
|
||||
if (newAccount.type === 'oauth') {
|
||||
const fpMode = extra?.codex_fingerprint_mode as string | undefined
|
||||
// 缺省/非法值按 off 呈现,与后端 GetCodexFingerprintMode 的 opt-in 语义一致(#5610)
|
||||
codexFingerprintMode.value = (['off', 'device', 'session', 'full'].includes(fpMode || '')
|
||||
? fpMode as CodexFingerprintMode
|
||||
: 'session')
|
||||
: 'off')
|
||||
}
|
||||
const credentials = newAccount.credentials as Record<string, unknown> | undefined
|
||||
const compactMappings = credentials?.compact_model_mapping as Record<string, string> | undefined
|
||||
@@ -4843,9 +4844,10 @@ const handleSubmit = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 指纹收敛模式:默认 session,不写入;非默认值显式写入(包括 off)
|
||||
// 指纹收敛模式:默认 off(不写入);device/session/full 是显式 opt-in,
|
||||
// 必须落键,否则管理员的选择会被后端当作"未设置"而回落到 off(#5610)。
|
||||
if (props.account.type === 'oauth') {
|
||||
if (codexFingerprintMode.value !== 'session') {
|
||||
if (codexFingerprintMode.value !== 'off') {
|
||||
newExtra.codex_fingerprint_mode = codexFingerprintMode.value
|
||||
} else {
|
||||
delete newExtra.codex_fingerprint_mode
|
||||
|
||||
Reference in New Issue
Block a user