From c86e86038a0bd457c81bb3ec16d11f0459b3bdaa Mon Sep 17 00:00:00 2001 From: jesieleo Date: Sun, 2 Aug 2026 12:46:00 +0800 Subject: [PATCH] fix(codex): refresh OAuth credentials from local login --- .../gateway/core-runtime/config-compiler.ts | 11 ++--- .../provider-plugin-runtime-identity.test.mjs | 43 +++++++++++++++++++ 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/packages/core/src/gateway/core-runtime/config-compiler.ts b/packages/core/src/gateway/core-runtime/config-compiler.ts index b2c2ca77..3a176026 100644 --- a/packages/core/src/gateway/core-runtime/config-compiler.ts +++ b/packages/core/src/gateway/core-runtime/config-compiler.ts @@ -448,9 +448,9 @@ function withCodexOauthRuntimeDefaults(providerPlugins: unknown[]): unknown[] { const codexOauth = plugin.codexOauth; const nextCodexOauth = { ...codexOauth, - ...(!hasOwn(codexOauth, "accountId") && !hasOwn(codexOauth, "account_id") && codexAuth?.accountId - ? { accountId: codexAuth.accountId } - : {}) + ...(codexAuth?.accessToken ? { accessToken: codexAuth.accessToken } : {}), + ...(codexAuth?.refreshToken ? { refreshToken: codexAuth.refreshToken } : {}), + ...(codexAuth?.accountId ? { accountId: codexAuth.accountId } : {}) }; const nextPlugin: Record = { ...plugin, @@ -787,8 +787,3 @@ function addProviderNameVariants(names: Set, providerName: string | unde names.add(providerName.slice(0, capabilitySeparatorIndex)); } } - - -function hasOwn(value: Record, key: string): boolean { - return Object.prototype.hasOwnProperty.call(value, key); -} diff --git a/packages/core/test/unit/agents/provider-plugin-runtime-identity.test.mjs b/packages/core/test/unit/agents/provider-plugin-runtime-identity.test.mjs index f4178d45..c38c2c7b 100644 --- a/packages/core/test/unit/agents/provider-plugin-runtime-identity.test.mjs +++ b/packages/core/test/unit/agents/provider-plugin-runtime-identity.test.mjs @@ -96,6 +96,49 @@ test("Codex OAuth plugins retain the default base URL after runtime identity nor assert.equal(compiled.providers[0].baseurl, codexDefaultBaseUrl); }); +test("Codex OAuth plugins prefer live login credentials over imported snapshots", async (t) => { + const home = useTemporaryCodexHome(t, "ccr-codex-runtime-live-credentials-"); + fs.mkdirSync(path.join(home, ".codex"), { recursive: true }); + fs.writeFileSync(path.join(home, ".codex", "auth.json"), JSON.stringify({ + tokens: { + access_token: "access-live", + account_id: "acct-live", + refresh_token: "refresh-live" + } + })); + + const config = createDefaultAppConfig(); + config.providerPlugins = [{ + codexOauth: { + accessToken: "access-imported", + accountId: "acct-imported", + refreshToken: "refresh-imported" + }, + key: "ccr-local-agent-codex-api-codex-oauth", + providerName: "Codex API" + }]; + config.Providers = [{ + api_base_url: codexDefaultBaseUrl, + api_key: "ccr-local-agent-login", + id: "codex-api", + models: ["gpt-5.5"], + name: "Codex API", + type: "openai_responses" + }]; + + const compiled = await compileCoreGatewayConfig( + config, + "raw-trace-token", + "billing-usage-token", + "core-auth-token" + ); + const codexPlugin = compiled.providerPlugins.find((item) => item.key === "ccr-local-agent-codex-api-codex-oauth"); + + assert.equal(codexPlugin.codexOauth.accessToken, "access-live"); + assert.equal(codexPlugin.codexOauth.refreshToken, "refresh-live"); + assert.equal(codexPlugin.codexOauth.accountId, "acct-live"); +}); + test("Codex local providers synthesize OAuth plugins when persisted plugins are missing", async (t) => { const home = useTemporaryCodexHome(t, "ccr-codex-runtime-missing-plugins-"); fs.mkdirSync(path.join(home, ".codex"), { recursive: true });