diff --git a/open-sse/config/agyModels.ts b/open-sse/config/agyModels.ts index 8ba930782a..d836888b7f 100644 --- a/open-sse/config/agyModels.ts +++ b/open-sse/config/agyModels.ts @@ -1,10 +1,10 @@ // Antigravity CLI (`agy`) model catalog. // -// These IDs were pinned directly from the live `:fetchAvailableModels` endpoint +// These models are pinned from the live `:fetchAvailableModels` endpoint // (https://daily-cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels) using a -// real `agy` consumer-OAuth token on 2026-05-29. They are the exact upstream model IDs -// the Antigravity backend accepts — no alias remapping is required (unlike the -// `antigravity` provider, whose catalog used display IDs that needed remapping). +// real `agy` consumer-OAuth token. The public catalog exposes the same clean Gemini +// 3.5 Flash tier names as the Antigravity IDE provider; the shared Antigravity executor +// maps those names to the legacy upstream IDs immediately before dispatch. // // The `agy` provider reuses the `antigravity` executor/translator (identical backend), // but ships its OWN catalog so it can expose models the `antigravity` provider's static @@ -62,24 +62,6 @@ export const AGY_PUBLIC_MODELS = Object.freeze([ supportsVision: true, toolCalling: true, }, - { - id: "gemini-3-flash-agent", - name: "Gemini 3.5 Flash (Agent)", - contextLength: 1048576, - maxOutputTokens: 65536, - supportsReasoning: true, - supportsVision: true, - toolCalling: true, - }, - { - id: "gemini-3-flash", - name: "Gemini 3 Flash", - contextLength: 1048576, - maxOutputTokens: 65536, - supportsReasoning: true, - supportsVision: true, - toolCalling: true, - }, { id: "gemini-3.5-flash-low", name: "Gemini 3.5 Flash (Low)", @@ -89,10 +71,20 @@ export const AGY_PUBLIC_MODELS = Object.freeze([ toolCalling: true, }, { - id: "gemini-3.5-flash-extra-low", - name: "Gemini 3.5 Flash (Extra Low)", + id: "gemini-3.5-flash-medium", + name: "Gemini 3.5 Flash (Medium)", contextLength: 1048576, maxOutputTokens: 65536, + supportsReasoning: true, + supportsVision: true, + toolCalling: true, + }, + { + id: "gemini-3.5-flash-high", + name: "Gemini 3.5 Flash (High)", + contextLength: 1048576, + maxOutputTokens: 65536, + supportsReasoning: true, supportsVision: true, toolCalling: true, }, diff --git a/open-sse/config/antigravityModelAliases.ts b/open-sse/config/antigravityModelAliases.ts index 970fd44ac2..2685962069 100644 --- a/open-sse/config/antigravityModelAliases.ts +++ b/open-sse/config/antigravityModelAliases.ts @@ -22,10 +22,16 @@ export const ANTIGRAVITY_PUBLIC_MODELS = Object.freeze([ supportsVision: true, toolCalling: true, }, - // Gemini 3.5 Flash — flagship model in Antigravity 2.0 (May 2026) + // Gemini 3.5 Flash tiers exposed by Antigravity 2.0.4's model selector. + // The user-facing names are Low / Medium / High, but fetchAvailableModels reports + // legacy upstream IDs for two of them: + // Low -> gemini-3.5-flash-extra-low (displayName: Gemini 3.5 Flash (Low)) + // Medium -> gemini-3.5-flash-low (displayName: Gemini 3.5 Flash (Medium)) + // High -> gemini-3-flash-agent (displayName: Gemini 3.5 Flash (High)) + // Keep the clean public IDs here and map them below for routing/quota. { - id: "gemini-3.5-flash-preview", - name: "Gemini 3.5 Flash", + id: "gemini-3.5-flash-low", + name: "Gemini 3.5 Flash (Low)", contextLength: 1048576, maxOutputTokens: 65536, supportsReasoning: true, @@ -33,8 +39,17 @@ export const ANTIGRAVITY_PUBLIC_MODELS = Object.freeze([ toolCalling: true, }, { - id: "gemini-3-flash-agent", - name: "Gemini 3.5 Flash Agent", + id: "gemini-3.5-flash-medium", + name: "Gemini 3.5 Flash (Medium)", + contextLength: 1048576, + maxOutputTokens: 65536, + supportsReasoning: true, + supportsVision: true, + toolCalling: true, + }, + { + id: "gemini-3.5-flash-high", + name: "Gemini 3.5 Flash (High)", contextLength: 1048576, maxOutputTokens: 65536, supportsReasoning: true, @@ -71,33 +86,6 @@ export const ANTIGRAVITY_PUBLIC_MODELS = Object.freeze([ supportsVision: true, toolCalling: true, }, - { - id: "gemini-3-flash-preview", - name: "Gemini 3 Flash", - contextLength: 1048576, - maxOutputTokens: 65536, - supportsReasoning: true, - supportsVision: true, - toolCalling: true, - }, - // Gemini 3.5 Flash budget tiers — agy ships these as exact upstream ids; #3184 verified - // they work via the antigravity OAuth provider (no alias remapping required). - { - id: "gemini-3.5-flash-low", - name: "Gemini 3.5 Flash (Low)", - contextLength: 1048576, - maxOutputTokens: 65536, - supportsVision: true, - toolCalling: true, - }, - { - id: "gemini-3.5-flash-extra-low", - name: "Gemini 3.5 Flash (Extra Low)", - contextLength: 1048576, - maxOutputTokens: 65536, - supportsVision: true, - toolCalling: true, - }, { id: "gemini-3.1-flash-lite", name: "Gemini 3.1 Flash Lite", @@ -160,17 +148,20 @@ export const ANTIGRAVITY_PUBLIC_MODELS = Object.freeze([ }, ]); -// The Antigravity upstream API uses plain model IDs (no -high/-low suffix). -// The -high/-low suffix convention was speculative and caused 404 for all -// gemini-3.x models. Only plain IDs like "gemini-2.5-flash" are proven working. export const ANTIGRAVITY_MODEL_ALIASES = Object.freeze({ + "gemini-3.5-flash-low": "gemini-3.5-flash-extra-low", + "gemini-3.5-flash-medium": "gemini-3.5-flash-low", + "gemini-3.5-flash-high": "gemini-3-flash-agent", + // Backward-compat: the retired flagship public id `gemini-3.5-flash-preview` + // (Antigravity 2.0's "Gemini 3.5 Flash") is kept as a HIDDEN alias so saved + // combos/configs keep routing — it maps to the reasoning-capable High tier + // (upstream `gemini-3-flash-agent`). It is NOT re-added to the public catalog. + "gemini-3.5-flash-preview": "gemini-3-flash-agent", "gemini-3-pro-preview": "gemini-3.1-pro", // agy catalog exposes -high/-low budget tiers, but the upstream rejects the suffix // for gemini-3.x (#3229) — map them to the plain proven id. "gemini-3.1-pro-high": "gemini-3.1-pro", "gemini-3.1-pro-low": "gemini-3.1-pro", - "gemini-3.5-flash-preview": "gemini-3.5-flash", - "gemini-3-flash-preview": "gemini-3-flash", "gemini-3-pro-image-preview": "gemini-3-pro-image", "gemini-2.5-computer-use-preview-10-2025": "rev19-uic3-1p", // Legacy Claude display ids → current upstream ids. NOTE: an earlier comment here @@ -186,10 +177,9 @@ export const ANTIGRAVITY_MODEL_ALIASES = Object.freeze({ type AntigravityModelAliasMap = Record; export const ANTIGRAVITY_REVERSE_MODEL_ALIASES: AntigravityModelAliasMap = Object.freeze({ + "gemini-3.5-flash-extra-low": "gemini-3.5-flash-low", + "gemini-3-flash-agent": "gemini-3.5-flash-high", "gemini-3.1-pro": "gemini-3-pro-preview", - "gemini-3.5-flash": "gemini-3.5-flash-preview", - "gemini-3-flash-agent": "gemini-3.5-flash-preview", - "gemini-3-flash": "gemini-3-flash-preview", "gemini-3-pro-image": "gemini-3-pro-image-preview", "rev19-uic3-1p": "gemini-2.5-computer-use-preview-10-2025", }); diff --git a/open-sse/executors/antigravity.ts b/open-sse/executors/antigravity.ts index d9267e0a7e..13969a4313 100644 --- a/open-sse/executors/antigravity.ts +++ b/open-sse/executors/antigravity.ts @@ -194,7 +194,7 @@ function addAntigravityTextualToolCall( type AntigravityRequestEnvelope = Record & { project: string; - model: string; + model?: string; userAgent: "antigravity" | "jetski"; requestType: "agent" | "image_gen"; requestId: string; @@ -336,6 +336,15 @@ function processAntigravitySSEPayload( if (!payload || payload === "[DONE]") return; try { const parsed = JSON.parse(payload); + const markdown = + typeof parsed?.markdown === "string" + ? parsed.markdown + : typeof parsed?.response?.markdown === "string" + ? parsed.response.markdown + : null; + if (markdown) { + collected.textContent += markdown; + } const candidate = parsed?.response?.candidates?.[0]; if (candidate?.content?.parts) { for (const part of candidate.content.parts) { @@ -661,9 +670,14 @@ export class AntigravityExecutor extends BaseExecutor { if (typeof p.text === "string" && p.text === "") return false; if (p.functionCall && !p.functionCall.name) return false; - // Only strip if it's NOT our bypass sentinel. + // Only strip if it's NOT our bypass sentinel. // Antigravity models (like Gemini) need this sentinel to bypass 400 errors. - return !p.thought && (hasFunctionCall || !p.thoughtSignature || p.thoughtSignature === "skip_thought_signature_validator"); + return ( + !p.thought && + (hasFunctionCall || + !p.thoughtSignature || + p.thoughtSignature === "skip_thought_signature_validator") + ); }) || []; return { ...c, role, parts }; }) || []; diff --git a/open-sse/services/model.ts b/open-sse/services/model.ts index e870f708f3..ec0f0844ff 100644 --- a/open-sse/services/model.ts +++ b/open-sse/services/model.ts @@ -1,5 +1,4 @@ import { PROVIDER_ID_TO_ALIAS, PROVIDER_MODELS } from "../config/providerModels.ts"; -import { ANTIGRAVITY_MODEL_ALIASES } from "../config/antigravityModelAliases.ts"; import { resolveWildcardAlias } from "./wildcardRouter.ts"; type ProviderModelAliasMap = Record>; @@ -76,7 +75,12 @@ const PROVIDER_MODEL_ALIASES: ProviderModelAliasMap = { "gpt-oss-20b": "openai/gpt-oss-20b", "nvidia/gpt-oss-20b": "openai/gpt-oss-20b", }, - antigravity: { ...ANTIGRAVITY_MODEL_ALIASES }, + // Antigravity model aliases must be applied by the Antigravity executor, not by + // the global model resolver. Applying them here rewrites the client-visible model + // before credential/account routing and before UI/logging, causing clean IDs like + // gemini-3.5-flash-high to be exposed and retried as upstream-only legacy ids such + // as gemini-3-flash-agent. The executor owns provider-wire normalization. + antigravity: {}, kiro: { "claude-opus-4-7": "claude-opus-4.7", "claude-opus-4-6": "claude-opus-4.6", diff --git a/tests/unit/account-fallback-service.test.ts b/tests/unit/account-fallback-service.test.ts index f47d9d0a02..3b52caa560 100644 --- a/tests/unit/account-fallback-service.test.ts +++ b/tests/unit/account-fallback-service.test.ts @@ -108,7 +108,7 @@ test("checkFallbackError locks Antigravity quota-reached 429 for the full reset 429, message, 0, - "gemini-3-flash-agent", + "gemini-3.5-flash-high", "antigravity", null, makeProfile() @@ -124,7 +124,7 @@ test("checkFallbackError locks Antigravity quota-reached 429 for the full reset test("recordModelLockoutFailure honors a multi-day exactCooldownMs (under 30-day cap)", () => { const provider = "antigravity"; const connectionId = "conn-quota-window"; - const model = "gemini-3-flash-agent"; + const model = "gemini-3.5-flash-high"; const exactCooldownMs = (164 * 3600 + 27 * 60 + 24) * 1000; clearModelLock(provider, connectionId, model); diff --git a/tests/unit/agy-provider.test.ts b/tests/unit/agy-provider.test.ts index b7c922e4f5..13ed8097c1 100644 --- a/tests/unit/agy-provider.test.ts +++ b/tests/unit/agy-provider.test.ts @@ -4,7 +4,10 @@ import assert from "node:assert/strict"; import { AI_PROVIDERS, USAGE_SUPPORTED_PROVIDERS } from "../../src/shared/constants/providers.ts"; import { REGISTRY } from "../../open-sse/config/providerRegistry.ts"; import { PROVIDERS as LEGACY_PROVIDERS } from "../../open-sse/config/constants.ts"; -import { PROVIDERS as OAUTH_PROVIDER_IDS, AGY_CONFIG } from "../../src/lib/oauth/constants/oauth.ts"; +import { + PROVIDERS as OAUTH_PROVIDER_IDS, + AGY_CONFIG, +} from "../../src/lib/oauth/constants/oauth.ts"; import { supportsTokenRefresh, REFRESH_LEAD_MS } from "../../open-sse/services/tokenRefresh.ts"; import { AGY_PUBLIC_MODELS, @@ -47,6 +50,12 @@ test("agy ships its own catalog including the Claude models antigravity omits", const ids = REGISTRY.agy.models.map((m) => m.id); assert.ok(ids.includes("claude-opus-4-6-thinking"), "must expose Claude Opus 4.6 Thinking"); assert.ok(ids.includes("claude-sonnet-4-6"), "must expose Claude Sonnet 4.6"); + assert.ok(ids.includes("gemini-3.5-flash-low"), "must expose clean Flash Low tier"); + assert.ok(ids.includes("gemini-3.5-flash-medium"), "must expose clean Flash Medium tier"); + assert.ok(ids.includes("gemini-3.5-flash-high"), "must expose clean Flash High tier"); + assert.ok(!ids.includes("gemini-3-flash-agent")); + assert.ok(!ids.includes("gemini-3-flash")); + assert.ok(!ids.includes("gemini-3.5-flash-extra-low")); // Tab-completion models are not chat-callable and must be excluded. assert.ok(!ids.includes("tab_flash_lite_preview")); assert.ok(!ids.includes("tab_jump_flash_lite_preview")); diff --git a/tests/unit/antigravity-model-aliases.test.ts b/tests/unit/antigravity-model-aliases.test.ts index 511ac5dc9c..06b238a703 100644 --- a/tests/unit/antigravity-model-aliases.test.ts +++ b/tests/unit/antigravity-model-aliases.test.ts @@ -17,13 +17,16 @@ function getPublicModel(id: string) { test("resolveAntigravityModelId maps the documented Antigravity aliases to upstream IDs", () => { assert.equal(resolveAntigravityModelId("gemini-3-pro-preview"), "gemini-3.1-pro"); - assert.equal(resolveAntigravityModelId("gemini-3.5-flash-preview"), "gemini-3.5-flash"); - assert.equal(resolveAntigravityModelId("gemini-3-flash-preview"), "gemini-3-flash"); assert.equal(resolveAntigravityModelId("gemini-3-pro-image-preview"), "gemini-3-pro-image"); assert.equal( resolveAntigravityModelId("gemini-2.5-computer-use-preview-10-2025"), "rev19-uic3-1p" ); + assert.equal(resolveAntigravityModelId("gemini-3.5-flash-low"), "gemini-3.5-flash-extra-low"); + assert.equal(resolveAntigravityModelId("gemini-3.5-flash-medium"), "gemini-3.5-flash-low"); + assert.equal(resolveAntigravityModelId("gemini-3.5-flash-high"), "gemini-3-flash-agent"); + // Backward-compat: retired flagship public id routes to the High tier upstream. + assert.equal(resolveAntigravityModelId("gemini-3.5-flash-preview"), "gemini-3-flash-agent"); assert.equal(resolveAntigravityModelId("gemini-claude-sonnet-4-5"), "claude-sonnet-4-6"); assert.equal(resolveAntigravityModelId("gemini-claude-sonnet-4-5-thinking"), "claude-sonnet-4-6"); assert.equal( @@ -35,8 +38,8 @@ test("resolveAntigravityModelId maps the documented Antigravity aliases to upstr test("toClientAntigravityModelId exposes client-visible aliases for known upstream IDs", () => { assert.equal(toClientAntigravityModelId("gemini-3.1-pro"), "gemini-3-pro-preview"); - assert.equal(toClientAntigravityModelId("gemini-3-flash-agent"), "gemini-3.5-flash-preview"); - assert.equal(toClientAntigravityModelId("gemini-3-flash"), "gemini-3-flash-preview"); + assert.equal(toClientAntigravityModelId("gemini-3.5-flash-extra-low"), "gemini-3.5-flash-low"); + assert.equal(toClientAntigravityModelId("gemini-3-flash-agent"), "gemini-3.5-flash-high"); assert.equal(toClientAntigravityModelId("gpt-oss-120b-medium"), "gpt-oss-120b-medium"); assert.equal(toClientAntigravityModelId("claude-sonnet-4-6"), "claude-sonnet-4-6"); assert.equal(toClientAntigravityModelId("claude-opus-4-6-thinking"), "claude-opus-4-6-thinking"); @@ -45,6 +48,8 @@ test("toClientAntigravityModelId exposes client-visible aliases for known upstre test("isUserCallableAntigravityModelId only allows public chat-capable model IDs", () => { assert.equal(isUserCallableAntigravityModelId("gemini-3-pro-preview"), true); assert.equal(isUserCallableAntigravityModelId("gemini-3.1-pro"), true); + // Retired flagship id stays callable as a hidden backward-compat alias (routes to High), + // even though it is no longer exposed in the public catalog. assert.equal(isUserCallableAntigravityModelId("gemini-3.5-flash-preview"), true); assert.equal(isUserCallableAntigravityModelId("gemini-3-flash-agent"), true); assert.equal(isUserCallableAntigravityModelId("gemini-3.1-flash-lite"), true); @@ -58,10 +63,12 @@ test("isUserCallableAntigravityModelId only allows public chat-capable model IDs // 2.0 was wrong. assert.equal(isUserCallableAntigravityModelId("claude-opus-4-6-thinking"), true); assert.equal(isUserCallableAntigravityModelId("claude-sonnet-4-6"), true); - // #3184: Gemini budget tiers now exposed (agy parity). + // Antigravity 2.0.4 exposes Gemini 3.5 Flash as separate UI tiers. assert.equal(isUserCallableAntigravityModelId("gemini-3.1-pro-high"), true); assert.equal(isUserCallableAntigravityModelId("gemini-3.1-pro-low"), true); assert.equal(isUserCallableAntigravityModelId("gemini-3.5-flash-low"), true); + assert.equal(isUserCallableAntigravityModelId("gemini-3.5-flash-medium"), true); + assert.equal(isUserCallableAntigravityModelId("gemini-3.5-flash-high"), true); assert.equal(isUserCallableAntigravityModelId("gemini-3.5-flash-extra-low"), true); assert.equal(isUserCallableAntigravityModelId("tab_flash_lite_preview"), false); assert.equal(isUserCallableAntigravityModelId("unknown-model"), false); @@ -79,9 +86,9 @@ test("ANTIGRAVITY_PUBLIC_MODELS exposes captured Antigravity 2.0.1 names and cap toolCalling: true, }); assert.equal(getPublicModel("claude-sonnet-4-6").name, "Claude Sonnet 4.6 (Thinking)"); - assert.deepEqual(getPublicModel("gemini-3.5-flash-preview"), { - id: "gemini-3.5-flash-preview", - name: "Gemini 3.5 Flash", + assert.deepEqual(getPublicModel("gemini-3.5-flash-high"), { + id: "gemini-3.5-flash-high", + name: "Gemini 3.5 Flash (High)", contextLength: 1048576, maxOutputTokens: 65536, supportsReasoning: true, @@ -89,8 +96,8 @@ test("ANTIGRAVITY_PUBLIC_MODELS exposes captured Antigravity 2.0.1 names and cap toolCalling: true, }); assert.equal( - getClientVisibleAntigravityModelName("gemini-3.5-flash-preview"), - "Gemini 3.5 Flash" + getClientVisibleAntigravityModelName("gemini-3.5-flash-medium"), + "Gemini 3.5 Flash (Medium)" ); assert.equal(getClientVisibleAntigravityModelName("gemini-2.5-flash"), "Gemini 2.5 Flash"); assert.equal( @@ -127,15 +134,6 @@ test("ANTIGRAVITY_PUBLIC_MODELS has no duplicate model IDs", () => { assert.deepEqual(duplicates, [], `duplicate model IDs found: ${duplicates.join(", ")}`); }); -test("gemini-3-flash-agent keeps its Agent display name (not the Flash High duplicate)", () => { - // A duplicate entry previously overwrote this name with "Gemini 3.5 Flash (High)" - // because the id-keyed name map kept the last occurrence. - assert.equal( - getClientVisibleAntigravityModelName("gemini-3-flash-agent"), - "Gemini 3.5 Flash Agent" - ); -}); - test("AntigravityExecutor.transformRequest resolves alias models before dispatching upstream", async () => { const executor = new AntigravityExecutor(); const result = await executor.transformRequest( @@ -153,10 +151,10 @@ test("AntigravityExecutor.transformRequest resolves alias models before dispatch assert.equal(result.model, "gemini-3.1-pro"); }); -test("AntigravityExecutor.transformRequest resolves Gemini 3.5 Flash alias upstream", async () => { +test("AntigravityExecutor.transformRequest maps Gemini 3.5 Flash tiers to live upstream IDs", async () => { const executor = new AntigravityExecutor(); const result = await executor.transformRequest( - "antigravity/gemini-3.5-flash-preview", + "antigravity/gemini-3.5-flash-high", { request: { contents: [{ role: "user", parts: [{ text: "Hello" }] }], @@ -167,7 +165,11 @@ test("AntigravityExecutor.transformRequest resolves Gemini 3.5 Flash alias upstr ); if (result instanceof Response) throw new Error("Unexpected Response from transformRequest"); - assert.equal(result.model, "gemini-3.5-flash"); + assert.equal(result.model, "gemini-3-flash-agent"); + assert.equal(result.modelConfigId, undefined); + assert.equal(result.model_config_id, undefined); + assert.equal(result.request.modelConfigId, undefined); + assert.equal(result.request.model_config_id, undefined); }); test("AntigravityExecutor.transformRequest sends Claude through Gemini-compatible Cloud Code schema", async () => { diff --git a/tests/unit/executor-agy.test.ts b/tests/unit/executor-agy.test.ts index 07975cb18d..96f35ba844 100644 --- a/tests/unit/executor-agy.test.ts +++ b/tests/unit/executor-agy.test.ts @@ -10,12 +10,15 @@ test("getExecutor('agy') returns AntigravityExecutor (not DefaultExecutor)", () test("getExecutor('antigravity') returns AntigravityExecutor", () => { const executor = getExecutor("antigravity"); - assert.ok(executor instanceof AntigravityExecutor, "antigravity provider should use AntigravityExecutor"); + assert.ok( + executor instanceof AntigravityExecutor, + "antigravity provider should use AntigravityExecutor" + ); }); test("getExecutor('agy') builds valid streaming URL", () => { const executor = getExecutor("agy"); - const url = executor.buildUrl("gemini-3-flash", true); + const url = executor.buildUrl("gemini-3.5-flash-high", true); assert.ok( url.includes("streamGenerateContent?alt=sse"), `expected streaming endpoint URL, got: ${url}` @@ -24,7 +27,7 @@ test("getExecutor('agy') builds valid streaming URL", () => { test("getExecutor('agy') builds valid non-streaming URL", () => { const executor = getExecutor("agy"); - const url = executor.buildUrl("gemini-3-flash", false); + const url = executor.buildUrl("gemini-3.5-flash-high", false); // Antigravity executor always uses streaming endpoint (buildUrl ignores stream flag) assert.ok( url.includes("streamGenerateContent?alt=sse"), diff --git a/tests/unit/managed-model-import.test.ts b/tests/unit/managed-model-import.test.ts index a0e9ea5c22..5df2d935a3 100644 --- a/tests/unit/managed-model-import.test.ts +++ b/tests/unit/managed-model-import.test.ts @@ -91,7 +91,7 @@ test("pruning stale connection available models during import", async () => { db.prepare( "INSERT INTO provider_connections (id, provider, auth_type, name, is_active, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)" ).run("conn-active", "openrouter", "apikey", "Active Connection", 1, "2026-05-29", "2026-05-29"); - + db.prepare( "INSERT INTO provider_connections (id, provider, auth_type, name, is_active, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)" ).run("conn-stale", "openrouter", "apikey", "Stale Connection", 0, "2026-05-29", "2026-05-29"); @@ -114,7 +114,7 @@ test("pruning stale connection available models during import", async () => { // Check models for "openrouter" const allSyncedModels = await modelsDb.getSyncedAvailableModels("openrouter"); - + // Stale connection should be pruned. Active connection and the new syncing connection should be kept. const ids = allSyncedModels.map((m) => m.id); assert.ok(ids.includes("shared/model-active")); @@ -149,11 +149,7 @@ test("antigravity sync dynamically builds and saves mitmAlias mappings", async ( assert.equal(mitmMappings["gemini-3.5-flash"], "antigravity/gemini-3.5-flash"); assert.equal(mitmMappings["custom-antigravity-model"], "antigravity/custom-antigravity-model"); - // Should contain reverse alias mappings (gemini-3.5-flash-preview maps to gemini-3.5-flash) - assert.equal(mitmMappings["gemini-3.5-flash-preview"], "antigravity/gemini-3.5-flash"); - assert.equal(mitmMappings["gemini-3-flash-agent"], "antigravity/gemini-3.5-flash"); - - // Should contain forward alias mappings (gemini-3.5-flash-preview maps to gemini-3.5-flash) - assert.equal(mitmMappings["gemini-3.5-flash-preview"], "antigravity/gemini-3.5-flash"); + // Removed Antigravity 2.0 preview/agent aliases must not be reintroduced. + assert.equal(mitmMappings["gemini-3.5-flash-preview"], undefined); + assert.equal(mitmMappings["gemini-3-flash-agent"], undefined); }); - diff --git a/tests/unit/models-catalog-route.test.ts b/tests/unit/models-catalog-route.test.ts index 14d88393ca..34ee03ce00 100644 --- a/tests/unit/models-catalog-route.test.ts +++ b/tests/unit/models-catalog-route.test.ts @@ -690,11 +690,13 @@ test("v1 models catalog exposes Antigravity client-visible preview aliases inste assert.equal(response.status, 200); assert.ok(ids.has("antigravity/gemini-3-pro-preview")); - assert.ok(ids.has("antigravity/gemini-3-flash-preview")); - // #3184/#3303: the Gemini budget tiers (`-high`/`-low`) are user-callable - // client-visible aliases on the Antigravity OAuth backend (agy parity), so - // they ARE now exposed in the catalog. (They alias to the plain - // `gemini-3.1-pro` upstream id — see ANTIGRAVITY_MODEL_ALIASES.) + assert.ok(ids.has("antigravity/gemini-3.5-flash-low")); + assert.ok(ids.has("antigravity/gemini-3.5-flash-medium")); + assert.ok(ids.has("antigravity/gemini-3.5-flash-high")); + assert.equal(ids.has("antigravity/gemini-3-flash-preview"), false); + assert.equal(ids.has("antigravity/gemini-3-flash-agent"), false); + // Gemini 3.1 Pro budget tiers remain client-visible aliases for the plain + // `gemini-3.1-pro` upstream id — see ANTIGRAVITY_MODEL_ALIASES. assert.ok(ids.has("antigravity/gemini-3.1-pro-high")); // The legacy `gemini-claude-*` ids are alias KEYS (remapped to live upstream // ids), not public catalog entries, so they stay unexposed. diff --git a/tests/unit/t28-model-catalog-updates.test.ts b/tests/unit/t28-model-catalog-updates.test.ts index de6d68655a..2dfa9d4089 100644 --- a/tests/unit/t28-model-catalog-updates.test.ts +++ b/tests/unit/t28-model-catalog-updates.test.ts @@ -24,18 +24,19 @@ test("T28: gemini AI Studio catalog includes current preview models", () => { assert.ok(geminiCliIds.includes("gemini-3-flash-preview")); }); -test("T28: antigravity static catalog exposes client-visible Gemini preview IDs", () => { +test("T28: antigravity static catalog exposes client-visible Gemini tier IDs", () => { const staticIds = (getStaticModelsForProvider("antigravity") || []).map((m) => m.id); assert.ok(staticIds.includes("gemini-3-pro-preview")); - assert.ok(staticIds.includes("gemini-3-flash-preview")); - // #3303 (agy parity, discussion #3184): the Gemini budget tiers ARE - // client-visible on the Antigravity OAuth backend — restoring tiers an - // earlier assumption had wrongly hidden. + assert.ok(staticIds.includes("gemini-3.5-flash-low")); + assert.ok(staticIds.includes("gemini-3.5-flash-medium")); + assert.ok(staticIds.includes("gemini-3.5-flash-high")); assert.ok(staticIds.includes("gemini-3.1-pro-low")); assert.ok(staticIds.includes("gemini-3.1-pro-high")); // Legacy aliases that were never client-visible stay absent. assert.ok(!staticIds.includes("gemini-3-pro-high")); + assert.ok(!staticIds.includes("gemini-3-flash-preview")); + assert.ok(!staticIds.includes("gemini-3-flash-agent")); assert.ok(!staticIds.includes("gemini-claude-sonnet-4-5")); assert.ok(!staticIds.includes("gemini-claude-sonnet-4-5-thinking")); assert.ok(!staticIds.includes("gemini-claude-opus-4-5-thinking"));