| author | |
| committer | |
| log | fd25c42ae6e56a82be7219950a746572b1c4d0e9 |
| tree | 843cf5e9cfc7813ba0f939feadfbd5ee940583c5 |
| parent | 805967a878e6804d58c151f29d2a3d0a06828fd1 |
| signature | Signed by PGP key B5690EEEBB952194 |
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) => { | ... | @@ -325,9 +325,7 @@ it.layer(layerTest)("AntigravityDriver", (it) => { |
| 325 | "gemini-test-high", | 325 | "gemini-test-high", |
| 326 | ]); | 326 | ]); |
| 327 | expect(snapshot.models[0]?.aliases).toContain(ANTIGRAVITY_DEFAULT_MODEL); | 327 | expect(snapshot.models[0]?.aliases).toContain(ANTIGRAVITY_DEFAULT_MODEL); |
| 328 | // The mock catalog is not in the manifest's current list, so it folds | 328 | expect(snapshot.models.every((model) => model.isLegacy !== true)).toBe(true); |
| 329 | // under the legacy section like an old Codex model would. | ||
| 330 | expect(snapshot.models.every((model) => model.isLegacy === true)).toBe(true); | ||
| 331 | expect(snapshot.slashCommands.map((command) => command.name)).toEqual(["plan", "logout"]); | 329 | expect(snapshot.slashCommands.map((command) => command.name)).toEqual(["plan", "logout"]); |
| 332 | expect(snapshot.supportsTextGeneration).toBe(true); | 330 | expect(snapshot.supportsTextGeneration).toBe(true); |
| 333 | h.controls.selected = h.second; | 331 | h.controls.selected = h.second; |
apps/server/src/provider/Drivers/AntigravityDriver.ts-3| ... | @@ -150,9 +150,6 @@ export const AntigravityDriver: ProviderDriver<AntigravitySettings, AntigravityD | ... | @@ -150,9 +150,6 @@ export const AntigravityDriver: ProviderDriver<AntigravitySettings, AntigravityD |
| 150 | accentColor, | 150 | accentColor, |
| 151 | continuationGroupKey: continuationIdentity.continuationKey, | 151 | continuationGroupKey: continuationIdentity.continuationKey, |
| 152 | }); | 152 | }); |
| 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. | ||
| 156 | const classifyModels = (draft: ServerProviderDraft) => | 153 | const classifyModels = (draft: ServerProviderDraft) => |
| 157 | modelManifest.current.pipe( | 154 | modelManifest.current.pipe( |
| 158 | Effect.map((manifest) => | 155 | Effect.map((manifest) => |
apps/server/src/provider/ModelManifest.test.ts+29-1| ... | @@ -34,6 +34,12 @@ describe("classifyModels", () => { | ... | @@ -34,6 +34,12 @@ describe("classifyModels", () => { |
| 34 | const manifest: ModelManifest.ModelManifestData = { | 34 | const manifest: ModelManifest.ModelManifestData = { |
| 35 | version: 1, | 35 | version: 1, |
| 36 | currentModels: { codex: ["gpt-test"] }, | 36 | currentModels: { codex: ["gpt-test"] }, |
| 37 | providers: { | ||
| 38 | codex: { | ||
| 39 | profiles: {}, | ||
| 40 | models: [{ slug: "gpt-old", name: "Old", status: "legacy" }], | ||
| 41 | }, | ||
| 42 | }, | ||
| 37 | }; | 43 | }; |
| 38 | const models = [ | 44 | const models = [ |
| 39 | model({ slug: "openai.gpt-test", isLegacy: true }), | 45 | model({ slug: "openai.gpt-test", isLegacy: true }), |
| ... | @@ -50,16 +56,23 @@ describe("classifyModels", () => { | ... | @@ -50,16 +56,23 @@ describe("classifyModels", () => { |
| 50 | ], | 56 | ], |
| 51 | ); | 57 | ); |
| 52 | }); | 58 | }); |
| 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", () => { |
| 54 | const manifest: ModelManifest.ModelManifestData = { | 60 | const manifest: ModelManifest.ModelManifestData = { |
| 55 | version: 1, | 61 | version: 1, |
| 56 | currentModels: { codex: ["current-a", "current-b"] }, | 62 | currentModels: { codex: ["current-a", "current-b"] }, |
| 63 | providers: { | ||
| 64 | codex: { | ||
| 65 | profiles: {}, | ||
| 66 | models: [{ slug: "old-model", name: "Old", status: "legacy" }], | ||
| 67 | }, | ||
| 68 | }, | ||
| 57 | }; | 69 | }; |
| 58 | const models = [ | 70 | const models = [ |
| 59 | model({ slug: "current-a" }), | 71 | model({ slug: "current-a" }), |
| 60 | // Stale flag from a previous classification pass must be cleared. | 72 | // Stale flag from a previous classification pass must be cleared. |
| 61 | model({ slug: "current-b", isLegacy: true }), | 73 | model({ slug: "current-b", isLegacy: true }), |
| 62 | model({ slug: "old-model" }), | 74 | model({ slug: "old-model" }), |
| 75 | model({ slug: "new-release", isLegacy: true }), | ||
| 63 | // Custom models are user-defined and never reclassified. | 76 | // Custom models are user-defined and never reclassified. |
| 64 | model({ slug: "my-own-model", isCustom: true }), | 77 | model({ slug: "my-own-model", isCustom: true }), |
| 65 | ]; | 78 | ]; |
| ... | @@ -72,10 +85,25 @@ describe("classifyModels", () => { | ... | @@ -72,10 +85,25 @@ describe("classifyModels", () => { |
| 72 | ["current-a", false], | 85 | ["current-a", false], |
| 73 | ["current-b", false], | 86 | ["current-b", false], |
| 74 | ["old-model", true], | 87 | ["old-model", true], |
| 88 | ["new-release", false], | ||
| 75 | ["my-own-model", false], | 89 | ["my-own-model", false], |
| 76 | ], | 90 | ], |
| 77 | ); | 91 | ); |
| 78 | }); | 92 | }); |
| 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 | ); | ||
| 79 | }); | 107 | }); |
| 80 | 108 | ||
| 81 | describe("applyManifestDefault", () => { | 109 | describe("applyManifestDefault", () => { |
apps/server/src/provider/ModelManifest.ts+1-4| ... | @@ -221,10 +221,7 @@ function isLegacyModel( | ... | @@ -221,10 +221,7 @@ function isLegacyModel( |
| 221 | const catalogModel = | 221 | const catalogModel = |
| 222 | catalog?.find((model) => model.slug === slug) ?? | 222 | catalog?.find((model) => model.slug === slug) ?? |
| 223 | catalog?.find((model) => model.slug === family); | 223 | catalog?.find((model) => model.slug === family); |
| 224 | if (catalogModel) return catalogModel.status === "legacy"; | 224 | return catalogModel?.status === "legacy"; |
| 225 | const currentModels = manifest.currentModels[driverKind]; | ||
| 226 | if (!currentModels) return false; | ||
| 227 | return !currentModels.includes(slug) && !currentModels.includes(family); | ||
| 228 | } | 225 | } |
| 229 | 226 | ||
| 230 | /** | 227 | /** |
apps/server/src/provider/model-manifest.json+28-2| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | { | 1 | { |
| 2 | "version": 1, | 2 | "version": 1, |
| 3 | "updatedAt": "2026-10-07T19:00:00Z", | 3 | "updatedAt": "2026-10-08T14:44:57Z", |
| 4 | "compatibility": [ | 4 | "compatibility": [ |
| 5 | { | 5 | { |
| 6 | "driver": "codex", | 6 | "driver": "codex", |
| ... | @@ -109,6 +109,16 @@ | ... | @@ -109,6 +109,16 @@ |
| 109 | "antigravity": ["gemini-3.8-flash-high", "gemini-3.8-flash-medium", "gemini-3.8-flash-low"] | 109 | "antigravity": ["gemini-3.8-flash-high", "gemini-3.8-flash-medium", "gemini-3.8-flash-low"] |
| 110 | }, | 110 | }, |
| 111 | "providers": { | 111 | "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 | }, | ||
| 112 | "claudeAgent": { | 122 | "claudeAgent": { |
| 113 | "defaults": { | 123 | "defaults": { |
| 114 | "chat": "claude-fable-5-1" | 124 | "chat": "claude-fable-5-1" |
| ... | @@ -777,7 +787,23 @@ | ... | @@ -777,7 +787,23 @@ |
| 777 | "slug": "gemini-3.8-flash-low", | 787 | "slug": "gemini-3.8-flash-low", |
| 778 | "name": "Gemini 3.8 Flash (Low)", | 788 | "name": "Gemini 3.8 Flash (Low)", |
| 779 | "status": "current" | 789 | "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" } | ||
| 781 | ] | 807 | ] |
| 782 | } | 808 | } |
| 783 | } | 809 | } |