authorgravatar for 62337003+Bil0000@users.noreply.github.comBilal Bakr <62337003+Bil0000@users.noreply.github.com> 2026-10-08 22:26:35+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-09 00:56:35+05:30
logfd25c42ae6e56a82be7219950a746572b1c4d0e9
tree843cf5e9cfc7813ba0f939feadfbd5ee940583c5
parent805967a878e6804d58c151f29d2a3d0a06828fd1
signature Signed by PGP key B5690EEEBB952194

fix(server): keep newly discovered models out of legacy groups (#14314)

Co-authored-by: PR Batch Tester <agent@local.test> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

5 files changed, 59 insertions(+), 13 deletions(-)

apps/server/src/provider/Drivers/AntigravityDriver.test.ts+1-3
......@@ -325,9 +325,7 @@ it.layer(layerTest)("AntigravityDriver", (it) => {
325325 "gemini-test-high",
326326 ]);
327327 expect(snapshot.models[0]?.aliases).toContain(ANTIGRAVITY_DEFAULT_MODEL);
328 // The mock catalog is not in the manifest's current list, so it folds
329 // under the legacy section like an old Codex model would.
330 expect(snapshot.models.every((model) => model.isLegacy === true)).toBe(true);
328 expect(snapshot.models.every((model) => model.isLegacy !== true)).toBe(true);
331329 expect(snapshot.slashCommands.map((command) => command.name)).toEqual(["plan", "logout"]);
332330 expect(snapshot.supportsTextGeneration).toBe(true);
333331 h.controls.selected = h.second;
apps/server/src/provider/Drivers/AntigravityDriver.ts-3
......@@ -150,9 +150,6 @@ export const AntigravityDriver: ProviderDriver<AntigravitySettings, AntigravityD
150150 accentColor,
151151 continuationGroupKey: continuationIdentity.continuationKey,
152152 });
153 // Google returns every model the account can use, including older
154 // Gemini generations. The manifest names the current ones so the picker
155 // folds the rest under its legacy section, as it does for Codex.
156153 const classifyModels = (draft: ServerProviderDraft) =>
157154 modelManifest.current.pipe(
158155 Effect.map((manifest) =>
apps/server/src/provider/ModelManifest.test.ts+29-1
......@@ -34,6 +34,12 @@ describe("classifyModels", () => {
3434 const manifest: ModelManifest.ModelManifestData = {
3535 version: 1,
3636 currentModels: { codex: ["gpt-test"] },
37 providers: {
38 codex: {
39 profiles: {},
40 models: [{ slug: "gpt-old", name: "Old", status: "legacy" }],
41 },
42 },
3743 };
3844 const models = [
3945 model({ slug: "openai.gpt-test", isLegacy: true }),
......@@ -50,16 +56,23 @@ describe("classifyModels", () => {
5056 ],
5157 );
5258 });
53 it("flags non-current models, clears stale flags, and skips custom models", () => {
59 it("flags only known legacy models, clears stale flags, and skips custom models", () => {
5460 const manifest: ModelManifest.ModelManifestData = {
5561 version: 1,
5662 currentModels: { codex: ["current-a", "current-b"] },
63 providers: {
64 codex: {
65 profiles: {},
66 models: [{ slug: "old-model", name: "Old", status: "legacy" }],
67 },
68 },
5769 };
5870 const models = [
5971 model({ slug: "current-a" }),
6072 // Stale flag from a previous classification pass must be cleared.
6173 model({ slug: "current-b", isLegacy: true }),
6274 model({ slug: "old-model" }),
75 model({ slug: "new-release", isLegacy: true }),
6376 // Custom models are user-defined and never reclassified.
6477 model({ slug: "my-own-model", isCustom: true }),
6578 ];
......@@ -72,10 +85,25 @@ describe("classifyModels", () => {
7285 ["current-a", false],
7386 ["current-b", false],
7487 ["old-model", true],
88 ["new-release", false],
7589 ["my-own-model", false],
7690 ],
7791 );
7892 });
93 it.each(["codex", "antigravity"])(
94 "keeps newly discovered %s models current when the manifest has no catalog",
95 (driverKind) => {
96 const models = [model({ slug: "new-release", isLegacy: true })];
97 assert.deepStrictEqual(
98 ModelManifest.classifyModels(
99 models,
100 { version: 1, currentModels: { [driverKind]: ["known-current"] } },
101 ProviderDriverKind.make(driverKind),
102 ),
103 [model({ slug: "new-release" })],
104 );
105 },
106 );
79107});
80108
81109describe("applyManifestDefault", () => {
apps/server/src/provider/ModelManifest.ts+1-4
......@@ -221,10 +221,7 @@ function isLegacyModel(
221221 const catalogModel =
222222 catalog?.find((model) => model.slug === slug) ??
223223 catalog?.find((model) => model.slug === family);
224 if (catalogModel) return catalogModel.status === "legacy";
225 const currentModels = manifest.currentModels[driverKind];
226 if (!currentModels) return false;
227 return !currentModels.includes(slug) && !currentModels.includes(family);
224 return catalogModel?.status === "legacy";
228225}
229226
230227/**
apps/server/src/provider/model-manifest.json+28-2
......@@ -1,6 +1,6 @@
11{
22 "version": 1,
3 "updatedAt": "2026-10-07T19:00:00Z",
3 "updatedAt": "2026-10-08T14:44:57Z",
44 "compatibility": [
55 {
66 "driver": "codex",
......@@ -109,6 +109,16 @@
109109 "antigravity": ["gemini-3.8-flash-high", "gemini-3.8-flash-medium", "gemini-3.8-flash-low"]
110110 },
111111 "providers": {
112 "codex": {
113 "profiles": {},
114 "models": [
115 { "slug": "gpt-6-sol", "name": "GPT-6 Sol", "status": "legacy" },
116 { "slug": "gpt-5.6-sol", "name": "GPT-5.6 Sol", "status": "legacy" },
117 { "slug": "gpt-5.6-terra", "name": "GPT-5.6 Terra", "status": "legacy" },
118 { "slug": "gpt-5.6-luna", "name": "GPT-5.6 Luna", "status": "legacy" },
119 { "slug": "gpt-5.5", "name": "GPT-5.5", "status": "legacy" }
120 ]
121 },
112122 "claudeAgent": {
113123 "defaults": {
114124 "chat": "claude-fable-5-1"
......@@ -777,7 +787,23 @@
777787 "slug": "gemini-3.8-flash-low",
778788 "name": "Gemini 3.8 Flash (Low)",
779789 "status": "current"
780 }
790 },
791 { "slug": "gemini-3.7-flash-high", "name": "Gemini 3.7 Flash (High)", "status": "legacy" },
792 {
793 "slug": "gemini-3.7-flash-medium",
794 "name": "Gemini 3.7 Flash (Medium)",
795 "status": "legacy"
796 },
797 { "slug": "gemini-3.7-flash-low", "name": "Gemini 3.7 Flash (Low)", "status": "legacy" },
798 { "slug": "gemini-3.6-flash-high", "name": "Gemini 3.6 Flash (High)", "status": "legacy" },
799 {
800 "slug": "gemini-3.6-flash-medium",
801 "name": "Gemini 3.6 Flash (Medium)",
802 "status": "legacy"
803 },
804 { "slug": "gemini-3.6-flash-low", "name": "Gemini 3.6 Flash (Low)", "status": "legacy" },
805 { "slug": "gemini-pro-agent", "name": "Gemini 3.1 Pro (High)", "status": "legacy" },
806 { "slug": "gemini-3.1-pro-low", "name": "Gemini 3.1 Pro (Low)", "status": "legacy" }
781807 ]
782808 }
783809 }