fix(openai): align auth picker copy metadata

This commit is contained in:
Peter Steinberger
2026-04-23 05:05:35 +01:00
parent 9937452405
commit 2c25e1d58d
8 changed files with 96 additions and 38 deletions

View File

@@ -0,0 +1,11 @@
export const OPENAI_API_KEY_LABEL = "OpenAI API Key";
export const OPENAI_CODEX_LOGIN_LABEL = "OpenAI Codex Browser Login";
export const OPENAI_CODEX_LOGIN_HINT = "Sign in with OpenAI in your browser";
export const OPENAI_CODEX_DEVICE_PAIRING_LABEL = "OpenAI Codex Device Pairing";
export const OPENAI_CODEX_DEVICE_PAIRING_HINT = "Pair in browser with a device code";
export const OPENAI_WIZARD_GROUP = {
groupId: "openai",
groupLabel: "OpenAI",
groupHint: "API key or Codex sign-in",
} as const;

View File

@@ -117,11 +117,11 @@ describe("openai codex provider", () => {
expect(oauth?.wizard).toMatchObject({
choiceLabel: "OpenAI Codex Browser Login",
groupHint: "API key + Codex auth",
groupHint: "API key or Codex sign-in",
});
expect(deviceCode?.wizard).toMatchObject({
choiceLabel: "OpenAI Codex Device Pairing",
groupHint: "API key + Codex auth",
groupHint: "API key or Codex sign-in",
});
});

View File

@@ -20,6 +20,13 @@ import {
} from "openclaw/plugin-sdk/provider-model-shared";
import { fetchCodexUsage } from "openclaw/plugin-sdk/provider-usage";
import { normalizeLowercaseStringOrEmpty, readStringValue } from "openclaw/plugin-sdk/text-runtime";
import {
OPENAI_CODEX_DEVICE_PAIRING_HINT,
OPENAI_CODEX_DEVICE_PAIRING_LABEL,
OPENAI_CODEX_LOGIN_HINT,
OPENAI_CODEX_LOGIN_LABEL,
OPENAI_WIZARD_GROUP,
} from "./auth-choice-copy.js";
import { isOpenAIApiBaseUrl, isOpenAICodexBaseUrl } from "./base-url.js";
import { OPENAI_CODEX_DEFAULT_MODEL } from "./default-models.js";
import { resolveCodexAuthIdentity } from "./openai-codex-auth-identity.js";
@@ -35,17 +42,8 @@ import {
const PROVIDER_ID = "openai-codex";
const OPENAI_CODEX_BASE_URL = "https://chatgpt.com/backend-api/codex";
const OPENAI_WIZARD_GROUP = {
groupId: "openai",
groupLabel: "OpenAI",
groupHint: "API key + Codex auth",
} as const;
const OPENAI_CODEX_LOGIN_ASSISTANT_PRIORITY = -30;
const OPENAI_CODEX_DEVICE_PAIRING_ASSISTANT_PRIORITY = -10;
const OPENAI_CODEX_LOGIN_LABEL = "OpenAI Codex Browser Login";
const OPENAI_CODEX_LOGIN_HINT = "Sign in with OpenAI in your browser";
const OPENAI_CODEX_DEVICE_PAIRING_LABEL = "OpenAI Codex Device Pairing";
const OPENAI_CODEX_DEVICE_PAIRING_HINT = "Pair in browser with a device code";
const OPENAI_CODEX_GPT_54_MODEL_ID = "gpt-5.4";
const OPENAI_CODEX_GPT_54_LEGACY_MODEL_ID = "gpt-5.4-codex";
const OPENAI_CODEX_GPT_54_PRO_MODEL_ID = "gpt-5.4-pro";

View File

@@ -55,7 +55,7 @@ describe("buildOpenAIProvider", () => {
expect(apiKey?.wizard).toMatchObject({
choiceLabel: "OpenAI API Key",
groupHint: "API key + Codex auth",
groupHint: "API key or Codex sign-in",
});
});

View File

@@ -10,6 +10,7 @@ import {
type ProviderPlugin,
} from "openclaw/plugin-sdk/provider-model-shared";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import { OPENAI_API_KEY_LABEL, OPENAI_WIZARD_GROUP } from "./auth-choice-copy.js";
import { isOpenAIApiBaseUrl } from "./base-url.js";
import { applyOpenAIConfig, OPENAI_DEFAULT_MODEL } from "./default-models.js";
import {
@@ -185,7 +186,7 @@ export function buildOpenAIProvider(): ProviderPlugin {
createProviderApiKeyAuthMethod({
providerId: PROVIDER_ID,
methodId: "api-key",
label: "OpenAI API Key",
label: OPENAI_API_KEY_LABEL,
hint: "Use your OpenAI API key directly",
optionKey: "openaiApiKey",
flagName: "--openai-api-key",
@@ -196,10 +197,8 @@ export function buildOpenAIProvider(): ProviderPlugin {
applyConfig: (cfg) => applyOpenAIConfig(cfg),
wizard: {
choiceId: "openai-api-key",
choiceLabel: "OpenAI API Key",
groupId: "openai",
groupLabel: "OpenAI",
groupHint: "API key + Codex auth",
choiceLabel: OPENAI_API_KEY_LABEL,
...OPENAI_WIZARD_GROUP,
},
}),
],

View File

@@ -20,7 +20,7 @@
"assistantPriority": -30,
"groupId": "openai",
"groupLabel": "OpenAI",
"groupHint": "API key + Codex auth"
"groupHint": "API key or Codex sign-in"
},
{
"provider": "openai-codex",
@@ -31,7 +31,7 @@
"assistantPriority": -10,
"groupId": "openai",
"groupLabel": "OpenAI",
"groupHint": "API key + Codex auth"
"groupHint": "API key or Codex sign-in"
},
{
"provider": "openai",
@@ -41,7 +41,7 @@
"assistantPriority": -40,
"groupId": "openai",
"groupLabel": "OpenAI",
"groupHint": "API key + Codex auth",
"groupHint": "API key or Codex sign-in",
"optionKey": "openaiApiKey",
"cliFlag": "--openai-api-key",
"cliOption": "--openai-api-key <key>",

View File

@@ -1,5 +1,7 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
import { buildOpenAICodexProviderPlugin } from "./openai-codex-provider.js";
import { buildOpenAIProvider } from "./openai-provider.js";
const manifest = JSON.parse(
readFileSync(new URL("./openclaw.plugin.json", import.meta.url), "utf8"),
@@ -15,6 +17,41 @@ const manifest = JSON.parse(
}>;
};
function manifestComparableWizardFields(choice: {
choiceId?: string;
choiceLabel?: string;
choiceHint?: string;
groupId?: string;
groupLabel?: string;
groupHint?: string;
}) {
return Object.fromEntries(
Object.entries({
choiceId: choice.choiceId,
choiceLabel: choice.choiceLabel,
choiceHint: choice.choiceHint,
groupId: choice.groupId,
groupLabel: choice.groupLabel,
groupHint: choice.groupHint,
}).filter(([, value]) => value !== undefined),
);
}
function providerWizardByKey() {
const providers = [buildOpenAIProvider(), buildOpenAICodexProviderPlugin()];
const wizards = new Map<string, Record<string, unknown>>();
for (const provider of providers) {
for (const authMethod of provider.auth ?? []) {
if (authMethod.wizard) {
wizards.set(`${provider.id}:${authMethod.id}`, authMethod.wizard);
}
}
}
return wizards;
}
describe("OpenAI plugin manifest", () => {
it("keeps removed Codex CLI import auth choice as a deprecated browser-login alias", () => {
const codexBrowserLogin = manifest.providerAuthChoices?.find(
@@ -37,20 +74,30 @@ describe("OpenAI plugin manifest", () => {
expect(codexBrowserLogin).toMatchObject({
choiceLabel: "OpenAI Codex Browser Login",
choiceHint: "Sign in with OpenAI in your browser",
groupHint: "API key + Codex auth",
groupHint: "API key or Codex sign-in",
});
expect(codexDeviceCode).toMatchObject({
choiceLabel: "OpenAI Codex Device Pairing",
choiceHint: "Pair in browser with a device code",
groupHint: "API key + Codex auth",
groupHint: "API key or Codex sign-in",
});
expect(apiKey).toMatchObject({
choiceLabel: "OpenAI API Key",
groupHint: "API key + Codex auth",
groupHint: "API key or Codex sign-in",
});
expect(choices.map((choice) => choice.choiceLabel)).not.toContain(
"OpenAI Codex (ChatGPT OAuth)",
);
expect(choices.map((choice) => choice.groupHint)).not.toContain("Codex OAuth + API key");
});
it("keeps auth choice copy aligned with provider wizard metadata", () => {
const wizards = providerWizardByKey();
for (const choice of manifest.providerAuthChoices ?? []) {
const key = `${choice.provider}:${choice.method}`;
expect(wizards.get(key), key).toMatchObject(manifestComparableWizardFields(choice));
}
});
});

View File

@@ -1,11 +1,14 @@
import type { ProviderPlugin } from "openclaw/plugin-sdk/provider-model-shared";
import {
OPENAI_API_KEY_LABEL,
OPENAI_CODEX_DEVICE_PAIRING_HINT,
OPENAI_CODEX_DEVICE_PAIRING_LABEL,
OPENAI_CODEX_LOGIN_HINT,
OPENAI_CODEX_LOGIN_LABEL,
OPENAI_WIZARD_GROUP,
} from "./auth-choice-copy.js";
const noopAuth = async () => ({ profiles: [] });
const OPENAI_WIZARD_GROUP = {
groupId: "openai",
groupLabel: "OpenAI",
groupHint: "API key + Codex auth",
} as const;
export function createOpenAICodexProvider(): ProviderPlugin {
return {
@@ -22,13 +25,13 @@ export function createOpenAICodexProvider(): ProviderPlugin {
{
id: "oauth",
kind: "oauth",
label: "OpenAI Codex Browser Login",
hint: "Sign in with OpenAI in your browser",
label: OPENAI_CODEX_LOGIN_LABEL,
hint: OPENAI_CODEX_LOGIN_HINT,
run: noopAuth,
wizard: {
choiceId: "openai-codex",
choiceLabel: "OpenAI Codex Browser Login",
choiceHint: "Sign in with OpenAI in your browser",
choiceLabel: OPENAI_CODEX_LOGIN_LABEL,
choiceHint: OPENAI_CODEX_LOGIN_HINT,
assistantPriority: -30,
...OPENAI_WIZARD_GROUP,
},
@@ -36,13 +39,13 @@ export function createOpenAICodexProvider(): ProviderPlugin {
{
id: "device-code",
kind: "device_code",
label: "OpenAI Codex Device Pairing",
hint: "Pair in browser with a device code",
label: OPENAI_CODEX_DEVICE_PAIRING_LABEL,
hint: OPENAI_CODEX_DEVICE_PAIRING_HINT,
run: noopAuth,
wizard: {
choiceId: "openai-codex-device-code",
choiceLabel: "OpenAI Codex Device Pairing",
choiceHint: "Pair in browser with a device code",
choiceLabel: OPENAI_CODEX_DEVICE_PAIRING_LABEL,
choiceHint: OPENAI_CODEX_DEVICE_PAIRING_HINT,
assistantPriority: -10,
...OPENAI_WIZARD_GROUP,
},
@@ -62,12 +65,12 @@ export function createOpenAIProvider(): ProviderPlugin {
{
id: "api-key",
kind: "api_key",
label: "OpenAI API Key",
label: OPENAI_API_KEY_LABEL,
hint: "Use your OpenAI API key directly",
run: noopAuth,
wizard: {
choiceId: "openai-api-key",
choiceLabel: "OpenAI API Key",
choiceLabel: OPENAI_API_KEY_LABEL,
assistantPriority: -40,
...OPENAI_WIZARD_GROUP,
},