diff --git a/src/auth/codex-oauth.js b/src/auth/codex-oauth.js index 9e8af37..3d276c0 100644 --- a/src/auth/codex-oauth.js +++ b/src/auth/codex-oauth.js @@ -5,6 +5,7 @@ import axios from 'axios'; import { promises as fs } from 'fs'; import path from 'path'; import os from 'os'; +import { getProxyConfigForProvider } from '../utils/proxy-utils.js'; /** * Codex OAuth 配置 @@ -25,9 +26,17 @@ const CODEX_CONFIG = { export class CodexAuth { constructor(config) { this.config = config; - this.httpClient = axios.create({ - timeout: 30000 - }); + + // 配置代理支持 + const axiosConfig = { timeout: 30000 }; + const proxyConfig = getProxyConfigForProvider(config, 'openai-codex-oauth'); + if (proxyConfig) { + axiosConfig.httpAgent = proxyConfig.httpAgent; + axiosConfig.httpsAgent = proxyConfig.httpsAgent; + console.log('[Codex Auth] Proxy enabled for OAuth requests'); + } + + this.httpClient = axios.create(axiosConfig); this.server = null; // 存储服务器实例 } diff --git a/src/auth/oauth-handlers.js b/src/auth/oauth-handlers.js index 068d996..6ef2695 100644 --- a/src/auth/oauth-handlers.js +++ b/src/auth/oauth-handlers.js @@ -2358,6 +2358,13 @@ export async function handleCodexOAuth(currentConfig, options = {}) { } const sessionId = state; // 使用 state 作为 session ID + + // 轮询计数器 + let pollCount = 0; + const maxPollCount = 60; // 最多轮询 60 次(60秒) + let pollTimer = null; + let isCompleted = false; + global.codexOAuthSessions.set(sessionId, { auth, state, @@ -2366,8 +2373,35 @@ export async function handleCodexOAuth(currentConfig, options = {}) { createdAt: Date.now() }); + // 启动轮询日志 + pollTimer = setInterval(() => { + pollCount++; + if (pollCount <= maxPollCount && !isCompleted) { + console.log(`[Codex Auth] Waiting for callback... (${pollCount}/${maxPollCount}s)`); + } + + if (pollCount >= maxPollCount && !isCompleted) { + clearInterval(pollTimer); + console.log('[Codex Auth] Polling timeout (60s), releasing session for next authorization'); + + // 清理会话和服务器 + if (global.codexOAuthSessions.has(sessionId)) { + const session = global.codexOAuthSessions.get(sessionId); + if (session.server) { + session.server.close(); + } + global.codexOAuthSessions.delete(sessionId); + } + } + }, 1000); + // 监听回调服务器的 auth-success 事件,自动完成 OAuth 流程 server.once('auth-success', async (result) => { + isCompleted = true; + if (pollTimer) { + clearInterval(pollTimer); + } + try { console.log('[Codex Auth] Received auth callback, completing OAuth flow...'); @@ -2410,6 +2444,11 @@ export async function handleCodexOAuth(currentConfig, options = {}) { // 监听 auth-error 事件 server.once('auth-error', (error) => { + isCompleted = true; + if (pollTimer) { + clearInterval(pollTimer); + } + console.error('[Codex Auth] Auth error:', error.message); global.codexOAuthSessions.delete(sessionId); @@ -2419,18 +2458,6 @@ export async function handleCodexOAuth(currentConfig, options = {}) { }); }); - // 10 分钟后自动清理会话 - setTimeout(() => { - if (global.codexOAuthSessions.has(sessionId)) { - const session = global.codexOAuthSessions.get(sessionId); - if (session.server) { - session.server.close(); - } - global.codexOAuthSessions.delete(sessionId); - console.log('[Codex Auth] Session expired and cleaned up'); - } - }, 10 * 60 * 1000); - return { success: true, authUrl: authUrl,