fix(pi-ai): hide unsupported ChatGPT codex oauth models

ChatGPT-backed Codex sign-in no longer exposes the removed 5.1/5.2 Codex variants. Filter those models from openai-codex OAuth so GSD stops surfacing selections that immediately fail while leaving API-key-backed OpenAI models available.

(cherry picked from commit 1aedba583916826fc5c6129037f61e9802010e46)
This commit is contained in:
Yeon Gil Kang 2026-04-15 11:23:02 +09:00 committed by Mikael Hugo
parent 1914f31342
commit b73763d944
2 changed files with 50 additions and 1 deletions

View file

@ -26,6 +26,14 @@ const TOKEN_URL = "https://auth.openai.com/oauth/token";
const REDIRECT_URI = "http://localhost:1455/auth/callback";
const SCOPE = "openid profile email offline_access";
const JWT_CLAIM_PATH = "https://api.openai.com/auth";
const CHATGPT_UNSUPPORTED_MODEL_IDS = new Set([
"gpt-5.2-codex",
"gpt-5.1-codex-mini",
"gpt-5.1-codex-max",
"gpt-5.1-codex",
"gpt-5.1",
"gpt-5",
]);
const SUCCESS_HTML = `<!doctype html>
<html lang="en">
@ -454,4 +462,11 @@ export const openaiCodexOAuthProvider: OAuthProviderInterface = {
getApiKey(credentials: OAuthCredentials): string {
return credentials.access;
},
modifyModels(models) {
return models.filter((model) => (
model.provider !== "openai-codex"
|| !CHATGPT_UNSUPPORTED_MODEL_IDS.has(model.id)
));
},
};

View file

@ -2,7 +2,7 @@ import assert from "node:assert/strict";
import { describe, it } from "node:test";
import type { Api, Model, SimpleStreamOptions, Context, AssistantMessageEventStream } from "@singularity-forge/pi-ai";
import { getApiProvider } from "@singularity-forge/pi-ai";
import type { AuthStorage } from "./auth-storage.js";
import { AuthStorage, type AuthStorageData } from "./auth-storage.js";
import { ModelRegistry } from "./model-registry.js";
function createRegistry(hasAuthFn?: (provider: string) => boolean): ModelRegistry {
@ -18,6 +18,10 @@ function createRegistry(hasAuthFn?: (provider: string) => boolean): ModelRegistr
return new ModelRegistry(authStorage, undefined);
}
function createInMemoryRegistry(data: AuthStorageData = {}): ModelRegistry {
return new ModelRegistry(AuthStorage.inMemory(data), undefined);
}
function createProviderModel(id: string, api?: string): NonNullable<Parameters<ModelRegistry["registerProvider"]>[1]["models"]>[number] {
return {
id,
@ -389,6 +393,36 @@ describe("ModelRegistry authMode — getAvailable", () => {
const available = registry.getAvailable();
assert.equal(available.length, 0);
});
it("prunes Codex models removed from ChatGPT-backed openai-codex OAuth", () => {
const registry = createInMemoryRegistry({
"openai-codex": {
type: "oauth",
access: "oauth-access",
refresh: "oauth-refresh",
expires: Date.now() + 60_000,
accountId: "acct_123",
},
});
assert.equal(registry.find("openai-codex", "gpt-5.1-codex-max"), undefined);
assert.equal(registry.find("openai-codex", "gpt-5.1"), undefined);
assert.equal(findModel(registry, "openai-codex", "gpt-5.2-codex"), undefined);
assert.ok(registry.find("openai-codex", "gpt-5.4"));
assert.ok(findModel(registry, "openai-codex", "gpt-5.4"));
});
it("keeps API-backed OpenAI Codex-capable models available", () => {
const registry = createInMemoryRegistry({
openai: {
type: "api_key",
key: "sk-test",
},
});
assert.ok(registry.find("openai", "gpt-5.2-codex"));
assert.ok(findModel(registry, "openai", "gpt-5.2-codex"));
});
});
// ─── getApiKey ────────────────────────────────────────────────────────────────