From edea0cba7a4dfefea1152b625756f8fadaf76cbb Mon Sep 17 00:00:00 2001 From: "tm.lxrd" <62334097+tmlxrd@users.noreply.github.com> Date: Thu, 23 Apr 2026 05:48:55 +0200 Subject: [PATCH] fix(openai): align auth picker labels for API key vs Codex OAuth Lock regression coverage for current OpenAI API key, Codex browser login, and Codex device pairing auth picker labels.\n\nThanks @tmlxrd. --- CHANGELOG.md | 1 + .../openai/openai-codex-provider.test.ts | 15 ++++++++ extensions/openai/openai-provider.test.ts | 10 ++++++ extensions/openai/openclaw.plugin.test.ts | 35 +++++++++++++++++++ 4 files changed, 61 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2324c8b1127..27f056d0aac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- Providers/OpenAI: lock the auth picker wording for OpenAI API key, Codex browser login, and Codex device pairing so the setup choices no longer imply a mixed Codex/API-key auth path. (#67848) Thanks @tmlxrd. - Agents/BTW: route `/btw` side questions through provider stream registration with the session workspace, so Ollama provider URL construction and workspace-scoped hooks apply correctly. Fixes #68336. (#70413) Thanks @suboss87. - Memory search: use sqlite-vec KNN for vector recall while preserving full post-filter result limits in multi-model indexes. Fixes #69666. (#69680) Thanks @aalekh-sarvam. - Providers/OpenAI Codex: stop stale per-agent `openai-codex:default` OAuth profiles from shadowing a newer main-agent identity-scoped profile, and let `openclaw doctor` offer the matching cleanup. (#70393) Thanks @pashpashpash. diff --git a/extensions/openai/openai-codex-provider.test.ts b/extensions/openai/openai-codex-provider.test.ts index dc37afa504a..7aea2fa7934 100644 --- a/extensions/openai/openai-codex-provider.test.ts +++ b/extensions/openai/openai-codex-provider.test.ts @@ -110,6 +110,21 @@ describe("openai codex provider", () => { }); }); + it("exposes grouped model/auth picker labels for Codex auth methods", () => { + const provider = buildOpenAICodexProviderPlugin(); + const oauth = provider.auth?.find((method) => method.id === "oauth"); + const deviceCode = provider.auth?.find((method) => method.id === "device-code"); + + expect(oauth?.wizard).toMatchObject({ + choiceLabel: "OpenAI Codex Browser Login", + groupHint: "API key + Codex auth", + }); + expect(deviceCode?.wizard).toMatchObject({ + choiceLabel: "OpenAI Codex Device Pairing", + groupHint: "API key + Codex auth", + }); + }); + it("returns deprecated-profile doctor guidance for legacy Codex CLI ids", () => { const provider = buildOpenAICodexProviderPlugin(); diff --git a/extensions/openai/openai-provider.test.ts b/extensions/openai/openai-provider.test.ts index 47de078e9fe..2314001b0b5 100644 --- a/extensions/openai/openai-provider.test.ts +++ b/extensions/openai/openai-provider.test.ts @@ -49,6 +49,16 @@ function runWrappedPayloadCase(params: { } describe("buildOpenAIProvider", () => { + it("exposes grouped model/auth picker labels for API key setup", () => { + const provider = buildOpenAIProvider(); + const apiKey = provider.auth.find((method) => method.id === "api-key"); + + expect(apiKey?.wizard).toMatchObject({ + choiceLabel: "OpenAI API Key", + groupHint: "API key + Codex auth", + }); + }); + it("resolves gpt-5.4 mini and nano from GPT-5 small-model templates", () => { const provider = buildOpenAIProvider(); const registry = { diff --git a/extensions/openai/openclaw.plugin.test.ts b/extensions/openai/openclaw.plugin.test.ts index 53518a64a3d..114715bfbd6 100644 --- a/extensions/openai/openclaw.plugin.test.ts +++ b/extensions/openai/openclaw.plugin.test.ts @@ -5,8 +5,13 @@ const manifest = JSON.parse( readFileSync(new URL("./openclaw.plugin.json", import.meta.url), "utf8"), ) as { providerAuthChoices?: Array<{ + provider?: string; + method?: string; + choiceLabel?: string; + choiceHint?: string; choiceId?: string; deprecatedChoiceIds?: string[]; + groupHint?: string; }>; }; @@ -18,4 +23,34 @@ describe("OpenAI plugin manifest", () => { expect(codexBrowserLogin?.deprecatedChoiceIds).toContain("openai-codex-import"); }); + + it("labels OpenAI API key and Codex auth choices without stale mixed OAuth wording", () => { + const choices = manifest.providerAuthChoices ?? []; + const codexBrowserLogin = choices.find((choice) => choice.choiceId === "openai-codex"); + const codexDeviceCode = choices.find( + (choice) => choice.choiceId === "openai-codex-device-code", + ); + const apiKey = choices.find( + (choice) => choice.provider === "openai" && choice.method === "api-key", + ); + + expect(codexBrowserLogin).toMatchObject({ + choiceLabel: "OpenAI Codex Browser Login", + choiceHint: "Sign in with OpenAI in your browser", + groupHint: "API key + Codex auth", + }); + expect(codexDeviceCode).toMatchObject({ + choiceLabel: "OpenAI Codex Device Pairing", + choiceHint: "Pair in browser with a device code", + groupHint: "API key + Codex auth", + }); + expect(apiKey).toMatchObject({ + choiceLabel: "OpenAI API Key", + groupHint: "API key + Codex auth", + }); + expect(choices.map((choice) => choice.choiceLabel)).not.toContain( + "OpenAI Codex (ChatGPT OAuth)", + ); + expect(choices.map((choice) => choice.groupHint)).not.toContain("Codex OAuth + API key"); + }); });