fix(qa): restore OpenAI OAuth release contracts

This commit is contained in:
Peter Steinberger
2026-05-31 01:25:38 +01:00
parent 9caefeaf08
commit 94814f3516
4 changed files with 33 additions and 14 deletions

View File

@@ -389,6 +389,15 @@ export function buildOpenAIProvider(): ProviderPlugin {
resolveUsageAuth: codexHooks.resolveUsageAuth,
fetchUsageSnapshot: codexHooks.fetchUsageSnapshot,
refreshOAuth: codexHooks.refreshOAuth,
buildMissingAuthMessage: (ctx) => {
if (normalizeProviderId(ctx.provider) !== PROVIDER_ID) {
return undefined;
}
if (ctx.listProfileIds(PROVIDER_ID).length === 0) {
return undefined;
}
return 'No API key found for provider "openai". You are authenticated with OpenAI ChatGPT/Codex OAuth. Use openai/gpt-5.5 with the ChatGPT/Codex OAuth profile, or set OPENAI_API_KEY for direct OpenAI API access.';
},
matchesContextOverflowError: ({ errorMessage }) =>
/content_filter.*(?:prompt|input).*(?:too long|exceed)/i.test(errorMessage),
resolveReasoningOutputMode: () => "native",

View File

@@ -117,7 +117,7 @@ export function describeOpenAIProviderCatalogContract() {
const { openaiProvider } = await contractDepsPromise;
expectCodexMissingAuthHint(
(params) => openaiProvider.buildMissingAuthMessage?.(params.context) ?? undefined,
"openai/gpt-*",
"openai/gpt-5.5",
);
});

View File

@@ -27,7 +27,9 @@ describe("qa model selection runtime", () => {
vi.clearAllMocks();
resolveEnvApiKey.mockReturnValue(undefined);
loadAuthProfileStoreForRuntime.mockReturnValue({ profiles: {} });
listProfilesForProvider.mockReturnValue([]);
listProfilesForProvider.mockImplementation((store: { profiles?: Record<string, unknown> }) =>
Object.keys(store.profiles ?? {}),
);
});
it("keeps the OpenAI live default when an API key is configured", () => {
@@ -39,9 +41,14 @@ describe("qa model selection runtime", () => {
});
it("prefers the Codex OAuth live default when only Codex auth profiles are available", () => {
listProfilesForProvider.mockImplementation((_store: unknown, provider: string) =>
provider === "openai" ? ["openai:user@example.com"] : [],
);
loadAuthProfileStoreForRuntime.mockReturnValue({
profiles: {
"openai:user@example.com": {
provider: "openai",
mode: "oauth",
},
},
});
expect(resolveQaPreferredLiveModel()).toBe("openai/gpt-5.5");
expect(defaultQaRuntimeModelForMode("live-frontier")).toBe("openai/gpt-5.5");
@@ -53,19 +60,20 @@ describe("qa model selection runtime", () => {
});
it("keeps the OpenAI live default when stored OpenAI profiles are available", () => {
listProfilesForProvider.mockImplementation((_store: unknown, provider: string) =>
provider === "openai" ? [`${provider}:user@example.com`] : [],
);
loadAuthProfileStoreForRuntime.mockReturnValue({
profiles: {
"openai:api-key": {
provider: "openai",
mode: "api_key",
},
},
});
expect(resolveQaPreferredLiveModel()).toBeUndefined();
expect(defaultQaRuntimeModelForMode("live-frontier")).toBe("openai/gpt-5.5");
});
it("leaves mock defaults unchanged", () => {
listProfilesForProvider.mockImplementation((_store: unknown, provider: string) =>
provider === "openai" ? ["openai:user@example.com"] : [],
);
expect(defaultQaRuntimeModelForMode("mock-openai")).toBe("mock-openai/gpt-5.5");
expect(defaultQaRuntimeModelForMode("mock-openai", { alternate: true })).toBe(
"mock-openai/gpt-5.5-alt",

View File

@@ -16,10 +16,12 @@ export function resolveQaLiveFrontierPreferredModel() {
allowKeychainPrompt: false,
externalCliProviderIds: ["openai"],
});
if (listProfilesForProvider(store, "openai").length > 0) {
const openAiProfileIds = listProfilesForProvider(store, "openai");
const openAiProfileModes = openAiProfileIds.map((profileId) => store.profiles[profileId]?.mode);
if (openAiProfileModes.some((mode) => mode === "api_key" || mode === "aws-sdk")) {
return undefined;
}
return listProfilesForProvider(store, "openai").length > 0
return openAiProfileModes.some((mode) => mode === "oauth" || mode === "token")
? QA_CODEX_OAUTH_LIVE_MODEL
: undefined;
} catch {