fix: sync codex cli auth into default profile

This commit is contained in:
George Pickett
2026-03-14 15:29:19 -07:00
parent 268e24e84c
commit e5432ec4e1
4 changed files with 21 additions and 6 deletions

View File

@@ -100,6 +100,7 @@ Docs: https://docs.openclaw.ai
- Gateway/websocket pairing bypass for disabled auth: skip device-pairing enforcement when `gateway.auth.mode=none` so Control UI connections behind reverse proxies no longer get stuck on `pairing required` (code 1008) despite auth being explicitly disabled. (#42931)
- Auth/login lockout recovery: clear stale `auth_permanent` and `billing` disabled state for all profiles matching the target provider when `openclaw models auth login` is invoked, so users locked out by expired or revoked OAuth tokens can recover by re-authenticating instead of waiting for the cooldown timer to expire. (#43057)
- Auto-reply/context-engine compaction: persist the exact embedded-run metadata compaction count for main and followup runner session accounting, so metadata-only auto-compactions no longer undercount multi-compaction runs. (#42629) thanks @uf-hy.
- Auth/Codex CLI reuse: sync reused Codex CLI credentials into the supported `openai-codex:default` OAuth profile instead of reviving the deprecated `openai-codex:codex-cli` slot, so doctor cleanup no longer loops. (#45353) thanks @Gugu-sugar.
## 2026.3.12

View File

@@ -16,8 +16,10 @@ vi.mock("./cli-credentials.js", () => ({
const { syncExternalCliCredentials } = await import("./auth-profiles/external-cli-sync.js");
const { CODEX_CLI_PROFILE_ID } = await import("./auth-profiles/constants.js");
const OPENAI_CODEX_DEFAULT_PROFILE_ID = "openai-codex:default";
describe("syncExternalCliCredentials", () => {
it("syncs Codex CLI credentials into the compatibility auth profile", () => {
it("syncs Codex CLI credentials into the supported default auth profile", () => {
const expires = Date.now() + 60_000;
mocks.readCodexCliCredentialsCached.mockReturnValue({
type: "oauth",
@@ -39,7 +41,7 @@ describe("syncExternalCliCredentials", () => {
expect(mocks.readCodexCliCredentialsCached).toHaveBeenCalledWith(
expect.objectContaining({ ttlMs: expect.any(Number) }),
);
expect(store.profiles[CODEX_CLI_PROFILE_ID]).toMatchObject({
expect(store.profiles[OPENAI_CODEX_DEFAULT_PROFILE_ID]).toMatchObject({
type: "oauth",
provider: "openai-codex",
access: "access-token",
@@ -47,5 +49,6 @@ describe("syncExternalCliCredentials", () => {
expires,
accountId: "acct_123",
});
expect(store.profiles[CODEX_CLI_PROFILE_ID]).toBeUndefined();
});
});

View File

@@ -4,7 +4,6 @@ import {
readMiniMaxCliCredentialsCached,
} from "../cli-credentials.js";
import {
CODEX_CLI_PROFILE_ID,
EXTERNAL_CLI_NEAR_EXPIRY_MS,
EXTERNAL_CLI_SYNC_TTL_MS,
QWEN_CLI_PROFILE_ID,
@@ -13,6 +12,8 @@ import {
} from "./constants.js";
import type { AuthProfileCredential, AuthProfileStore, OAuthCredential } from "./types.js";
const OPENAI_CODEX_DEFAULT_PROFILE_ID = "openai-codex:default";
function shallowEqualOAuthCredentials(a: OAuthCredential | undefined, b: OAuthCredential): boolean {
if (!a) {
return false;
@@ -140,7 +141,7 @@ export function syncExternalCliCredentials(store: AuthProfileStore): boolean {
if (
syncExternalCliCredentialsForProvider(
store,
CODEX_CLI_PROFILE_ID,
OPENAI_CODEX_DEFAULT_PROFILE_ID,
"openai-codex",
() => readCodexCliCredentialsCached({ ttlMs: EXTERNAL_CLI_SYNC_TTL_MS }),
now,

View File

@@ -63,6 +63,13 @@ describe("maybeRemoveDeprecatedCliAuthProfiles", () => {
refresh: "token-r2",
expires: Date.now() + 60_000,
},
"openai-codex:default": {
type: "oauth",
provider: "openai-codex",
access: "token-c",
refresh: "token-r3",
expires: Date.now() + 60_000,
},
},
},
null,
@@ -76,10 +83,11 @@ describe("maybeRemoveDeprecatedCliAuthProfiles", () => {
profiles: {
"anthropic:claude-cli": { provider: "anthropic", mode: "oauth" },
"openai-codex:codex-cli": { provider: "openai-codex", mode: "oauth" },
"openai-codex:default": { provider: "openai-codex", mode: "oauth" },
},
order: {
anthropic: ["anthropic:claude-cli"],
"openai-codex": ["openai-codex:codex-cli"],
"openai-codex": ["openai-codex:codex-cli", "openai-codex:default"],
},
},
} as const;
@@ -94,10 +102,12 @@ describe("maybeRemoveDeprecatedCliAuthProfiles", () => {
};
expect(raw.profiles?.["anthropic:claude-cli"]).toBeUndefined();
expect(raw.profiles?.["openai-codex:codex-cli"]).toBeUndefined();
expect(raw.profiles?.["openai-codex:default"]).toBeDefined();
expect(next.auth?.profiles?.["anthropic:claude-cli"]).toBeUndefined();
expect(next.auth?.profiles?.["openai-codex:codex-cli"]).toBeUndefined();
expect(next.auth?.profiles?.["openai-codex:default"]).toBeDefined();
expect(next.auth?.order?.anthropic).toBeUndefined();
expect(next.auth?.order?.["openai-codex"]).toBeUndefined();
expect(next.auth?.order?.["openai-codex"]).toEqual(["openai-codex:default"]);
});
});