diff --git a/open-sse/config/agyModels.ts b/open-sse/config/agyModels.ts index 412e073044..5e9f37b84e 100644 --- a/open-sse/config/agyModels.ts +++ b/open-sse/config/agyModels.ts @@ -41,6 +41,15 @@ export const AGY_PUBLIC_MODELS = Object.freeze([ supportsVision: true, toolCalling: true, }, + { + id: "gemini-3.7-flash-tiered", + name: "Gemini 3.7 Flash (Tiered)", + contextLength: 1048576, + maxOutputTokens: 65536, + supportsReasoning: true, + supportsVision: true, + toolCalling: true, + }, // Gemini 3.1 Pro { id: "gemini-pro-agent", diff --git a/open-sse/config/antigravityModelAliases.ts b/open-sse/config/antigravityModelAliases.ts index 5eab3f4c8e..3946b776d0 100644 --- a/open-sse/config/antigravityModelAliases.ts +++ b/open-sse/config/antigravityModelAliases.ts @@ -29,6 +29,15 @@ export const ANTIGRAVITY_PUBLIC_MODELS = Object.freeze([ supportsVision: true, toolCalling: true, }, + { + id: "gemini-3.7-flash-tiered", + name: "Gemini 3.7 Flash (Tiered)", + contextLength: 1048576, + maxOutputTokens: 65536, + supportsReasoning: true, + supportsVision: true, + toolCalling: true, + }, // Gemini 3.1 Pro budget tiers. Live streamGenerateContent validation uses // `gemini-pro-agent` for High; the separately advertised `gemini-3.1-pro-high` // discovery slot currently returns HTTP 400 and is intentionally not public. @@ -91,6 +100,13 @@ export const ANTIGRAVITY_PUBLIC_MODELS = Object.freeze([ ]); export const ANTIGRAVITY_MODEL_ALIASES = Object.freeze({ + // Gemini 3.7 Flash tiers map to the upstream tiered endpoint model; the thinking + // budget is steered via generationConfig.thinkingConfig.thinkingBudget. + "gemini-3.7-flash": "gemini-3.7-flash-tiered", + "gemini-3.7-flash-high": "gemini-3.7-flash-tiered", + "gemini-3.7-flash-medium": "gemini-3.7-flash-tiered", + "gemini-3.7-flash-low": "gemini-3.7-flash-tiered", + "gpt-oss-120b": "gpt-oss-120b-medium", // gemini-3.1-pro-low is not aliased: the upstream accepts it verbatim. // gemini-3.1-pro-high: the discovery slot returns HTTP 400 on v1internal; // the live upstream id is gemini-pro-agent (see ANTIGRAVITY_PUBLIC_MODELS). diff --git a/src/shared/constants/modelSpecs.ts b/src/shared/constants/modelSpecs.ts index f7342c54f4..653cd2f51e 100644 --- a/src/shared/constants/modelSpecs.ts +++ b/src/shared/constants/modelSpecs.ts @@ -175,12 +175,54 @@ export const MODEL_SPECS: Record = { }, // ── Gemini 3.7 Flash (current Antigravity/AGY live tiers) ───────── - // The model id itself selects the upstream 10k/4k/1k reasoning tier. Antigravity - // still rejects client-supplied thinking parameters, so keep the explicit-parameter - // capability aligned with the existing Gemini Flash tier ids. - "gemini-3.7-flash-high": { ...GEMINI_35_FLASH_MODEL_SPEC }, - "gemini-3.7-flash-medium": { ...GEMINI_35_FLASH_MODEL_SPEC }, - "gemini-3.7-flash-low": { ...GEMINI_35_FLASH_MODEL_SPEC }, + // The tier suffix configures the thinking budget passed to the upstream + // gemini-3.7-flash-tiered backend (high: 24.5k, medium: 8k, low: 1k). + "gemini-3.7-flash-high": { + maxOutputTokens: 65536, + contextWindow: 1048576, + defaultThinkingBudget: 24576, + thinkingBudgetCap: 24576, + supportsThinking: true, + supportsTools: true, + supportsVision: true, + }, + "gemini-3.7-flash-medium": { + maxOutputTokens: 65536, + contextWindow: 1048576, + defaultThinkingBudget: 8192, + thinkingBudgetCap: 24576, + supportsThinking: true, + supportsTools: true, + supportsVision: true, + }, + "gemini-3.7-flash-low": { + maxOutputTokens: 65536, + contextWindow: 1048576, + defaultThinkingBudget: 1024, + thinkingBudgetCap: 24576, + supportsThinking: true, + supportsTools: true, + supportsVision: true, + }, + "gemini-3.7-flash": { + maxOutputTokens: 65536, + contextWindow: 1048576, + defaultThinkingBudget: 8192, + thinkingBudgetCap: 24576, + supportsThinking: true, + supportsTools: true, + supportsVision: true, + aliases: ["gemini-3.7-flash-tiered"], + }, + "gemini-3.7-flash-tiered": { + maxOutputTokens: 65536, + contextWindow: 1048576, + defaultThinkingBudget: 8192, + thinkingBudgetCap: 24576, + supportsThinking: true, + supportsTools: true, + supportsVision: true, + }, // Provider-neutral compatibility for providers that still serve Gemini 3.6. // Antigravity/AGY availability is governed by their own provider catalogs and diff --git a/tests/unit/agy-gemini-3696-tier-passthrough.test.ts b/tests/unit/agy-gemini-3696-tier-passthrough.test.ts index 53f70b5fbc..0092681808 100644 --- a/tests/unit/agy-gemini-3696-tier-passthrough.test.ts +++ b/tests/unit/agy-gemini-3696-tier-passthrough.test.ts @@ -14,10 +14,13 @@ test("(#3696) resolveAntigravityModelId passes gemini-3.1-pro-low through unchan assert.equal(resolveAntigravityModelId("gemini-3.1-pro-low"), "gemini-3.1-pro-low"); }); -test("(#3696) no two ANTIGRAVITY_PUBLIC_MODELS entries resolve to the same upstream id", () => { +test("(#3696) non-tiered ANTIGRAVITY_PUBLIC_MODELS entries resolve to distinct upstream ids", () => { const seen = new Map(); const collisions: string[] = []; for (const model of ANTIGRAVITY_PUBLIC_MODELS) { + // Gemini 3.7 Flash tiers intentionally share the upstream `gemini-3.7-flash-tiered` + // endpoint with different reasoning token budgets. + if (model.id.startsWith("gemini-3.7-flash")) continue; const upstream = resolveAntigravityModelId(model.id); if (seen.has(upstream)) { collisions.push(`${model.id} and ${seen.get(upstream)} both resolve to "${upstream}"`); diff --git a/tests/unit/antigravity-model-aliases.test.ts b/tests/unit/antigravity-model-aliases.test.ts index 542573b3a4..82ad399215 100644 --- a/tests/unit/antigravity-model-aliases.test.ts +++ b/tests/unit/antigravity-model-aliases.test.ts @@ -57,12 +57,11 @@ test("toClientAntigravityQuotaModelId preserves upstream Gemini Flash bucket IDs test("resolveAntigravityModelId maps the documented Antigravity aliases to upstream IDs", () => { assert.equal(resolveAntigravityModelId("gemini-3-pro-image-preview"), "gemini-3-pro-image"); for (const [modelId] of EXPECTED_FLASH_TIERS) { - // Only the collapsed gemini-3.7-flash id is aliased to the live upstream - // gemini-3.7-flash-tiered id; the suffixed gemini-3.7-flash-high/medium tier ids - // (like the 3.6/3.5 tiers) have no alias entry and pass through verbatim. - const expected = modelId === "gemini-3.7-flash" ? "gemini-3.7-flash-tiered" : modelId; - assert.equal(resolveAntigravityModelId(modelId), expected); + assert.equal(resolveAntigravityModelId(modelId), "gemini-3.7-flash-tiered"); } + assert.equal(resolveAntigravityModelId("gemini-3.7-flash"), "gemini-3.7-flash-tiered"); + assert.equal(resolveAntigravityModelId("gemini-3.7-flash-tiered"), "gemini-3.7-flash-tiered"); + assert.equal(resolveAntigravityModelId("gpt-oss-120b"), "gpt-oss-120b-medium"); 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(