fix(codex-models): keep fallback order so a missing cache degrades exactly

CI: adapter-models.test.ts pins toEqual(codexFallbackModels), including
the static array's original order. The no-key path went through
mergedWithFallback, which sorts; with an empty CLI cache that reordered
the fallback and broke two existing tests. Merge without sorting so a
missing or unusable cache returns the pre-change result bit-for-bit.
This commit is contained in:
馨冉 2026-09-10 11:04:27 +08:00
parent fb556de3ca
commit 8bd517e584
2 changed files with 11 additions and 14 deletions

View File

@ -48,13 +48,9 @@ describe("codex model discovery via the CLI models cache", () => {
else process.env.OPENAI_API_KEY = originalOpenAiKey;
});
it("returns the static fallback when the cache file is missing", async () => {
it("returns the static fallback in its original order when the cache file is missing", async () => {
const models = await listCodexModels();
expect(models.map((m) => m.id)).toEqual(
[...codexFallbackModels.map((m) => m.id)].sort((a, b) =>
a.localeCompare(b, "en", { numeric: true, sensitivity: "base" }),
),
);
expect(models).toEqual(codexFallbackModels);
});
it("lists cache entries with visibility list and keeps internal slugs out", async () => {
@ -88,15 +84,11 @@ describe("codex model discovery via the CLI models cache", () => {
expect(models.find((m) => m.id === "o3-mini")?.label).toBe("o3-mini");
});
it("returns the static fallback when the cache file is malformed", async () => {
it("returns the static fallback in its original order when the cache file is malformed", async () => {
writeCache(tempHome, "{not json");
const models = await refreshCodexModels();
expect(models.map((m) => m.id)).toEqual(
[...codexFallbackModels.map((m) => m.id)].sort((a, b) =>
a.localeCompare(b, "en", { numeric: true, sensitivity: "base" }),
),
);
expect(models).toEqual(codexFallbackModels);
});
it("returns the static fallback when the cache payload has no models array", async () => {

View File

@ -139,8 +139,13 @@ async function loadCodexModels(options?: { forceRefresh?: boolean }): Promise<Ad
if (!apiKey) {
// ChatGPT-authenticated installs have no API key. Their catalog lives in
// the Codex CLI's own models_cache.json, merged over the static fallback
// so no id that shipped in a release disappears.
return mergedWithFallback(readCodexModelsCache({ forceRefresh }));
// so no id that shipped in a release disappears. Keep the fallback's
// original order (no sort) so a missing cache degrades to exactly the
// pre-change result.
return dedupeModels([
...readCodexModelsCache({ forceRefresh }),
...codexFallbackModels,
]);
}
const fallback = dedupeModels(codexFallbackModels);