From f2f02b365fca45588adb093f99e5d86b102430d7 Mon Sep 17 00:00:00 2001 From: hex2077 Date: Mon, 9 Mar 2026 19:00:15 +0800 Subject: [PATCH] =?UTF-8?q?refactor(providers):=20=E9=87=8D=E6=9E=84=20Cod?= =?UTF-8?q?ex=20=E8=AE=A4=E8=AF=81=E5=88=B7=E6=96=B0=E6=9C=BA=E5=88=B6?= =?UTF-8?q?=E4=BB=A5=E6=94=AF=E6=8C=81=E5=90=8E=E5=8F=B0=E5=BC=82=E6=AD=A5?= =?UTF-8?q?=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将直接调用 refreshAccessToken 改为调用 initializeAuth(true) 以统一认证流程 - 新增 triggerBackgroundRefresh 方法,在 token 即将过期或收到 401 时异步触发刷新 - 移除多处重复的 PoolManager 标记逻辑,统一由 triggerBackgroundRefresh 处理 - 优化 initializeAuth 方法,仅在需要时加载凭证,避免不必要的阻塞 - 更新版本号至 2.11.0 --- VERSION | 2 +- src/providers/adapter.js | 4 +- src/providers/openai/codex-core.js | 87 ++++++++++++------------------ 3 files changed, 38 insertions(+), 55 deletions(-) diff --git a/VERSION b/VERSION index a25a7c7..46b81d8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.10.9.3 +2.11.0 diff --git a/src/providers/adapter.js b/src/providers/adapter.js index 1943953..bfaceac 100644 --- a/src/providers/adapter.js +++ b/src/providers/adapter.js @@ -574,7 +574,7 @@ export class CodexApiServiceAdapter extends ApiServiceAdapter { } if (this.isExpiryDateNear()) { logger.info(`[Codex] Expiry date is near, refreshing token...`); - await this.codexApiService.refreshAccessToken(); + await this.codexApiService.initializeAuth(true); } return Promise.resolve(); } @@ -584,7 +584,7 @@ export class CodexApiServiceAdapter extends ApiServiceAdapter { await this.codexApiService.initialize(); } logger.info(`[Codex] Force refreshing token...`); - return this.codexApiService.refreshAccessToken(); + return this.codexApiService.initializeAuth(true); } isExpiryDateNear() { diff --git a/src/providers/openai/codex-core.js b/src/providers/openai/codex-core.js index 8997622..a29b67d 100644 --- a/src/providers/openai/codex-core.js +++ b/src/providers/openai/codex-core.js @@ -99,10 +99,9 @@ export class CodexApiService { this.last_refresh = creds.last_refresh || this.last_refresh; this.expiresAt = new Date(creds.expired); // 注意:字段名是 expired - // 检查 token 是否需要刷新 + // 检查 token 是否需要刷新(异步触发,不阻塞加载) if (this.isExpiryDateNear()) { - logger.info('[Codex] Token expiring soon, refreshing...'); - await this.refreshAccessToken(); + this.triggerBackgroundRefresh(); } this.isInitialized = true; @@ -116,9 +115,6 @@ export class CodexApiService { * 初始化认证并执行必要刷新 */ async initializeAuth(forceRefresh = false) { - // 首先执行基础凭证加载 - await this.loadCredentials(); - // 检查 token 是否需要刷新 const needsRefresh = forceRefresh; @@ -126,7 +122,11 @@ export class CodexApiService { return; } + // 首先执行基础凭证加载 + await this.loadCredentials(); + // 只有在明确要求刷新,或者 AccessToken 缺失时,才执行刷新 + // 注意:在 V2 架构下,此方法主要由 PoolManager 的后台队列调用 if (needsRefresh || !this.accessToken) { if (!this.refreshToken) { throw new Error('Codex credentials not found. Please authenticate first using OAuth.'); @@ -136,6 +136,19 @@ export class CodexApiService { } } + /** + * 后台异步刷新 token(不阻塞当前请求) + */ + triggerBackgroundRefresh() { + const poolManager = getProviderPoolManager(); + if (poolManager && this.uuid) { + logger.info(`[Codex] Token is near expiry, marking credential ${this.uuid} for background refresh`); + poolManager.markProviderNeedRefresh(MODEL_PROVIDER.CODEX_API, { + uuid: this.uuid + }); + } + } + /** * 生成内容(非流式) */ @@ -160,15 +173,9 @@ export class CodexApiService { delete requestBody._requestBaseUrl; } - // 检查 token 是否即将过期,如果是则推送到刷新队列 + // 检查 token 是否即将过期,如果是则触发后台异步刷新 if (this.isExpiryDateNear()) { - const poolManager = getProviderPoolManager(); - if (poolManager && this.uuid) { - logger.info(`[Codex] Token is near expiry, marking credential ${this.uuid} for refresh`); - poolManager.markProviderNeedRefresh(MODEL_PROVIDER.CODEX_API, { - uuid: this.uuid - }); - } + this.triggerBackgroundRefresh(); } const url = `${this.baseUrl}/responses`; @@ -194,17 +201,11 @@ export class CodexApiService { return this.parseNonStreamResponse(response.data); } catch (error) { if (error.response?.status === 401) { - logger.info('[Codex] Received 401. Triggering background refresh via PoolManager...'); + logger.info('[Codex] Received 401. Triggering background refresh...'); - // 标记当前凭证为不健康(会自动进入刷新队列) - const poolManager = getProviderPoolManager(); - if (poolManager && this.uuid) { - logger.info(`[Codex] Marking credential ${this.uuid} as needs refresh. Reason: 401 Unauthorized`); - poolManager.markProviderNeedRefresh(MODEL_PROVIDER.CODEX_API, { - uuid: this.uuid - }); - error.credentialMarkedUnhealthy = true; - } + // 触发后台异步刷新 + this.triggerBackgroundRefresh(); + error.credentialMarkedUnhealthy = true; // Mark error for credential switch without recording error count error.shouldSwitchCredential = true; @@ -241,15 +242,9 @@ export class CodexApiService { delete requestBody._requestBaseUrl; } - // 检查 token 是否即将过期,如果是则推送到刷新队列 + // 检查 token 是否即将过期,如果是则触发后台异步刷新 if (this.isExpiryDateNear()) { - const poolManager = getProviderPoolManager(); - if (poolManager && this.uuid) { - logger.info(`[Codex] Token is near expiry, marking credential ${this.uuid} for refresh`); - poolManager.markProviderNeedRefresh(MODEL_PROVIDER.CODEX_API, { - uuid: this.uuid - }); - } + this.triggerBackgroundRefresh(); } const url = `${this.baseUrl}/responses`; @@ -275,17 +270,11 @@ export class CodexApiService { yield* this.parseSSEStream(response.data); } catch (error) { if (error.response?.status === 401) { - logger.info('[Codex] Received 401 during stream. Triggering background refresh via PoolManager...'); + logger.info('[Codex] Received 401 during stream. Triggering background refresh...'); - // 标记当前凭证为不健康 - const poolManager = getProviderPoolManager(); - if (poolManager && this.uuid) { - logger.info(`[Codex] Marking credential ${this.uuid} as needs refresh. Reason: 401 Unauthorized in stream`); - poolManager.markProviderNeedRefresh(MODEL_PROVIDER.CODEX_API, { - uuid: this.uuid - }); - error.credentialMarkedUnhealthy = true; - } + // 触发后台异步刷新 + this.triggerBackgroundRefresh(); + error.credentialMarkedUnhealthy = true; // Mark error for credential switch without recording error count error.shouldSwitchCredential = true; @@ -731,17 +720,11 @@ export class CodexApiService { return result; } catch (error) { if (error.response?.status === 401) { - logger.info('[Codex] Received 401 during getUsageLimits. Triggering background refresh via PoolManager...'); + logger.info('[Codex] Received 401 during getUsageLimits. Triggering background refresh...'); - // 标记当前凭证为不健康 - const poolManager = getProviderPoolManager(); - if (poolManager && this.uuid) { - logger.info(`[Codex] Marking credential ${this.uuid} as needs refresh. Reason: 401 Unauthorized in getUsageLimits`); - poolManager.markProviderNeedRefresh(MODEL_PROVIDER.CODEX_API, { - uuid: this.uuid - }); - error.credentialMarkedUnhealthy = true; - } + // 触发后台异步刷新 + this.triggerBackgroundRefresh(); + error.credentialMarkedUnhealthy = true; // Mark error for credential switch without recording error count error.shouldSwitchCredential = true;