From ed12ea7163c5fd1d946090050a1c6fbeada6fb3c Mon Sep 17 00:00:00 2001 From: chensunlai Date: Sat, 29 Aug 2026 17:29:26 +0800 Subject: [PATCH] fix(frontend): authenticate Codex API key mode inline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 让 Codex API Key 模式在配置文件中正确发送 Bearer 鉴权并保留图像工具授权。 --- frontend/src/components/keys/UseKeyModal.vue | 64 +++++++++---------- .../keys/__tests__/UseKeyModal.spec.ts | 11 +++- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/frontend/src/components/keys/UseKeyModal.vue b/frontend/src/components/keys/UseKeyModal.vue index 0030f7226a..73169ab905 100644 --- a/frontend/src/components/keys/UseKeyModal.vue +++ b/frontend/src/components/keys/UseKeyModal.vue @@ -942,38 +942,47 @@ windows_wsl_setup_acknowledged = true name = "OpenAI" base_url = "${baseUrl}" wire_api = "responses" -${generateCodexProviderAuthConfig()} +${generateCodexProviderAuthConfig(apiKey)} [features] goals = true` - // auth.json content - const authContent = `{ - "OPENAI_API_KEY": "${apiKey}" -}` - - return [ - { - path: `${configDir}/config.toml`, - content: configContent, - hint: t('keys.useKeyModal.openai.configTomlHint') - }, - { - path: `${configDir}/auth.json`, - content: authContent - } - ] + return buildOpenAICodexFileConfigs(configDir, configContent, apiKey) } -function generateCodexProviderAuthConfig(): string { +function generateCodexProviderAuthConfig(apiKey: string): string { if (codexAuthMode.value === 'api-key') { return `requires_openai_auth = false +experimental_bearer_token = "${escapeTomlBasicString(apiKey)}" http_headers = { "x-openai-actor-authorization" = "local-image-extension" }` } return 'requires_openai_auth = true' } +function buildOpenAICodexFileConfigs( + configDir: string, + configContent: string, + apiKey: string +): FileConfig[] { + const files: FileConfig[] = [ + { + path: `${configDir}/config.toml`, + content: configContent, + hint: t('keys.useKeyModal.openai.configTomlHint') + } + ] + + if (codexAuthMode.value === 'legacy') { + files.push({ + path: `${configDir}/auth.json`, + content: JSON.stringify({ OPENAI_API_KEY: apiKey }, null, 2) + }) + } + + return files +} + function joinConfigPath(dir: string, file: string, windows: boolean): string { if (!windows) return `${dir}/${file}` return `${dir}\\${file}` @@ -1279,28 +1288,13 @@ name = "OpenAI" base_url = "${baseUrl}" wire_api = "responses" supports_websockets = true -${generateCodexProviderAuthConfig()} +${generateCodexProviderAuthConfig(apiKey)} [features] responses_websockets_v2 = true goals = true` - // auth.json content - const authContent = `{ - "OPENAI_API_KEY": "${apiKey}" -}` - - return [ - { - path: `${configDir}/config.toml`, - content: configContent, - hint: t('keys.useKeyModal.openai.configTomlHint') - }, - { - path: `${configDir}/auth.json`, - content: authContent - } - ] + return buildOpenAICodexFileConfigs(configDir, configContent, apiKey) } function generateOpenCodeConfig(platform: string, baseUrl: string, apiKey: string, pathLabel?: string): FileConfig { diff --git a/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts b/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts index 414608f0a4..69ad4bc6b4 100644 --- a/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts +++ b/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts @@ -371,6 +371,7 @@ describe('UseKeyModal', () => { expect(configToml).not.toContain('model_context_window') expect(configToml).not.toContain('model_auto_compact_token_limit') expect(configToml).toContain('requires_openai_auth = true') + expect(configToml).not.toContain('experimental_bearer_token') expect(configToml).not.toContain('x-openai-actor-authorization') expect(configToml).not.toContain('env_key') expect(configToml).not.toContain('image_generation') @@ -413,11 +414,12 @@ describe('UseKeyModal', () => { expect(apiKeyMode.attributes('aria-checked')).toBe('true') expect(configToml).toBeDefined() expect(configToml).toContain('requires_openai_auth = false') + expect(configToml).toContain('experimental_bearer_token = "sk-test"') expect(configToml).toContain('http_headers = { "x-openai-actor-authorization" = "local-image-extension" }') expect(configToml).not.toContain('env_key') expect(configToml).not.toContain('image_generation') - expect(codeBlocks).toContain('{\n "OPENAI_API_KEY": "sk-test"\n}') - expect(wrapper.text()).toContain('auth.json') + expect(codeBlocks).not.toContain('{\n "OPENAI_API_KEY": "sk-test"\n}') + expect(wrapper.text()).not.toContain('auth.json') const restartNotice = wrapper.get('[data-testid="codex-api-key-restart-notice"]') expect(restartNotice.text()).toContain( @@ -471,6 +473,7 @@ describe('UseKeyModal', () => { expect(configToml).not.toContain('model_context_window') expect(configToml).not.toContain('model_auto_compact_token_limit') expect(configToml).toContain('requires_openai_auth = true') + expect(configToml).not.toContain('experimental_bearer_token') expect(configToml).not.toContain('x-openai-actor-authorization') expect(configToml).not.toContain('env_key') expect(configToml).not.toContain('image_generation') @@ -516,12 +519,14 @@ describe('UseKeyModal', () => { expect(wrapper.get('[data-testid="codex-auth-mode-api-key"]').attributes('aria-checked')).toBe('true') expect(configToml).toBeDefined() expect(configToml).toContain('requires_openai_auth = false') + expect(configToml).toContain('experimental_bearer_token = "sk-test"') expect(configToml).toContain('http_headers = { "x-openai-actor-authorization" = "local-image-extension" }') expect(configToml).not.toContain('env_key') expect(configToml).not.toContain('image_generation') expect(configToml).toContain('supports_websockets = true') expect(configToml).toContain('[features]\nresponses_websockets_v2 = true\ngoals = true') - expect(codeBlocks).toContain('{\n "OPENAI_API_KEY": "sk-test"\n}') + expect(codeBlocks).not.toContain('{\n "OPENAI_API_KEY": "sk-test"\n}') + expect(wrapper.text()).not.toContain('auth.json') }) it('resets Codex authentication mode when the modal reopens or platform changes', async () => {