From 01f0d5cb5914b6e8481c957eb2593510f7aaf273 Mon Sep 17 00:00:00 2001 From: Yoahoug Date: Fri, 16 Jan 2026 17:54:05 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Codex=20OAuth?= =?UTF-8?q?=20=E5=9B=9E=E8=B0=83=E7=9B=91=E5=90=AC=EF=BC=8C=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=87=AA=E5=8A=A8=E5=AE=8C=E6=88=90=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/auth/oauth-handlers.js | 54 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/auth/oauth-handlers.js b/src/auth/oauth-handlers.js index 9f71665..068d996 100644 --- a/src/auth/oauth-handlers.js +++ b/src/auth/oauth-handlers.js @@ -2366,6 +2366,59 @@ export async function handleCodexOAuth(currentConfig, options = {}) { createdAt: Date.now() }); + // 监听回调服务器的 auth-success 事件,自动完成 OAuth 流程 + server.once('auth-success', async (result) => { + try { + console.log('[Codex Auth] Received auth callback, completing OAuth flow...'); + + const session = global.codexOAuthSessions.get(sessionId); + if (!session) { + console.error('[Codex Auth] Session not found'); + return; + } + + // 完成 OAuth 流程 + const credentials = await auth.completeOAuthFlow(result.code, result.state, session.state, session.pkce); + + // 清理会话 + global.codexOAuthSessions.delete(sessionId); + + // 广播认证成功事件 + broadcastEvent('oauth_success', { + provider: 'openai-codex-oauth', + credPath: credentials.credPath, + relativePath: credentials.relativePath, + timestamp: new Date().toISOString(), + email: credentials.email, + accountId: credentials.account_id + }); + + // 自动关联新生成的凭据到 Pools + await autoLinkProviderConfigs(CONFIG); + + console.log('[Codex Auth] OAuth flow completed successfully'); + } catch (error) { + console.error('[Codex Auth] Failed to complete OAuth flow:', error.message); + + // 广播认证失败事件 + broadcastEvent('oauth_error', { + provider: 'openai-codex-oauth', + error: error.message + }); + } + }); + + // 监听 auth-error 事件 + server.once('auth-error', (error) => { + console.error('[Codex Auth] Auth error:', error.message); + global.codexOAuthSessions.delete(sessionId); + + broadcastEvent('oauth_error', { + provider: 'openai-codex-oauth', + error: error.message + }); + }); + // 10 分钟后自动清理会话 setTimeout(() => { if (global.codexOAuthSessions.has(sessionId)) { @@ -2386,6 +2439,7 @@ export async function handleCodexOAuth(currentConfig, options = {}) { method: 'oauth2-pkce', sessionId: sessionId, redirectUri: 'http://localhost:1455/auth/callback', + port: 1455, instructions: [ '1. 点击下方按钮在浏览器中打开授权链接', '2. 使用您的 OpenAI 账户登录', From 7b45c6f8762ae7777a8d6e77855bbb4751fe6bdb Mon Sep 17 00:00:00 2001 From: Yoahoug Date: Fri, 16 Jan 2026 18:09:57 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=E5=AE=8C=E5=96=84=20Codex=20OAuth?= =?UTF-8?q?=20=E6=94=AF=E6=8C=81=20-=20=E5=9B=9E=E8=B0=83=E7=9B=91?= =?UTF-8?q?=E5=90=AC=E3=80=81=E6=89=8B=E5=8A=A8=E6=B7=BB=E5=8A=A0=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E3=80=81=E7=AB=AF=E5=8F=A3=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/app/app.js | 4 +++- static/app/modal.js | 28 ++++++++++++++++++++++++++++ static/app/provider-manager.js | 1 + static/app/utils.js | 8 +++++++- 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/static/app/app.js b/static/app/app.js index 5f39562..967d22f 100644 --- a/static/app/app.js +++ b/static/app/app.js @@ -40,7 +40,8 @@ import { loadProviders, openProviderManager, showAuthModal, - executeGenerateAuthUrl + executeGenerateAuthUrl, + handleGenerateAuthUrl } from './provider-manager.js'; import { @@ -226,6 +227,7 @@ window.refreshProviderConfig = refreshProviderConfig; window.fileUploadHandler = fileUploadHandler; window.showAuthModal = showAuthModal; window.executeGenerateAuthUrl = executeGenerateAuthUrl; +window.handleGenerateAuthUrl = handleGenerateAuthUrl; // 配置管理相关全局函数 window.viewConfig = viewConfig; diff --git a/static/app/modal.js b/static/app/modal.js index c20f83d..bc839cc 100644 --- a/static/app/modal.js +++ b/static/app/modal.js @@ -1039,6 +1039,34 @@ function showAddProviderForm(providerType) { return; } + // Codex OAuth 只支持授权添加,不支持手动添加 + if (providerType === 'openai-codex-oauth') { + const form = document.createElement('div'); + form.className = 'add-provider-form'; + form.innerHTML = ` +

添加新提供商配置

+
+
+ + Codex 仅支持 OAuth 授权添加 +
+

+ OpenAI Codex 需要通过 OAuth 授权获取访问令牌,无法手动填写凭据。请点击下方按钮进行授权。 +

+ + +
+ `; + + const providerList = modal.querySelector('.provider-list'); + providerList.parentNode.insertBefore(form, providerList); + return; + } + const form = document.createElement('div'); form.className = 'add-provider-form'; form.innerHTML = ` diff --git a/static/app/provider-manager.js b/static/app/provider-manager.js index 712223d..1d426d8 100644 --- a/static/app/provider-manager.js +++ b/static/app/provider-manager.js @@ -2198,6 +2198,7 @@ export { openProviderManager, showAuthModal, executeGenerateAuthUrl, + handleGenerateAuthUrl, checkUpdate, performUpdate }; \ No newline at end of file diff --git a/static/app/utils.js b/static/app/utils.js index a75f019..6236e2f 100644 --- a/static/app/utils.js +++ b/static/app/utils.js @@ -254,6 +254,12 @@ function getProviderTypeFields(providerType) { } ], 'openai-codex-oauth': [ + { + id: 'CODEX_OAUTH_CREDS_FILE_PATH', + label: isEn ? 'OAuth Credentials File Path' : 'OAuth凭据文件路径', + type: 'text', + placeholder: isEn ? 'e.g.: configs/codex/oauth_creds.json' : '例如: configs/codex/oauth_creds.json' + }, { id: 'CODEX_EMAIL', label: isEn ? 'Email (Optional)' : '邮箱 (选填)', @@ -264,7 +270,7 @@ function getProviderTypeFields(providerType) { id: 'CODEX_BASE_URL', label: `Codex Base URL ${t('config.optional')}`, type: 'text', - placeholder: 'https://chatgpt.com/backend-api/codex' + placeholder: 'https://api.openai.com/v1/codex' } ] };