Add gemini-3.7-flash and its tiered high/medium/low variants to the Antigravity and Gemini registries, with matching capabilities, pricing and Antigravity quota tracking. extractModel now recognises gemini-3.7-flash-tiered alongside 3.6 and derives the version from the request, so thinkingLevel still maps to the right tiered alias. Closes #3286 Closes #3281
This commit is contained in:
committed by
decolua
parent
8af5e752da
commit
86694ed8d0
@@ -53,6 +53,9 @@ const PROVIDER_MODELS = {
|
||||
{ id: "glm-4.7" },
|
||||
],
|
||||
ag: [
|
||||
{ id: "gemini-3.7-flash-high" },
|
||||
{ id: "gemini-3.7-flash-medium" },
|
||||
{ id: "gemini-3.7-flash-low" },
|
||||
{ id: "gemini-3.6-flash-high" },
|
||||
{ id: "gemini-3.6-flash-medium" },
|
||||
{ id: "gemini-3.6-flash-low" },
|
||||
|
||||
@@ -205,6 +205,7 @@ export const PATTERN_CAPABILITIES = [
|
||||
|
||||
// ── Gemini (all 2.0+ multimodal + google_search grounding, 1M ctx) ─
|
||||
{ pattern: "*gemini*image*", caps: { vision: true, imageOutput: true, contextWindow: 1048576 } },
|
||||
{ pattern: "*gemini-3.7*", caps: { vision: true, audioInput: true, videoInput: true, reasoning: true, search: true, thinkingFormat: "gemini-level", thinkingCanDisable: false, contextWindow: 1048576, maxOutput: 65536 } },
|
||||
{ pattern: "*gemini-3*pro*", caps: { vision: true, audioInput: true, videoInput: true, reasoning: true, search: true, thinkingFormat: "gemini-level", thinkingCanDisable: false, contextWindow: 1048576, maxOutput: 65535 } },
|
||||
{ pattern: "*gemini-3*", caps: { vision: true, audioInput: true, videoInput: true, reasoning: true, search: true, thinkingFormat: "gemini-level", thinkingCanDisable: false, contextWindow: 1048576, maxOutput: 65536 } },
|
||||
{ pattern: "*gemini-2.5*", caps: { vision: true, audioInput: true, videoInput: true, reasoning: true, search: true, thinkingFormat: "gemini-budget", thinkingRange: { min: 0, max: 24576 }, contextWindow: 1048576, maxOutput: 65536 } },
|
||||
|
||||
@@ -57,6 +57,10 @@ export const MODEL_PRICING = {
|
||||
"o1-mini": { input: 3.00, output: 12.00, cached: 1.50, reasoning: 18.00, cache_creation: 3.00 },
|
||||
|
||||
// === Gemini ===
|
||||
"gemini-3.7-flash": { input: 1.50, output: 7.50, cached: 0.15, reasoning: 11.25, cache_creation: 1.875 },
|
||||
"gemini-3.7-flash-high": { input: 1.50, output: 7.50, cached: 0.15, reasoning: 11.25, cache_creation: 1.875 },
|
||||
"gemini-3.7-flash-medium": { input: 1.50, output: 7.50, cached: 0.15, reasoning: 11.25, cache_creation: 1.875 },
|
||||
"gemini-3.7-flash-low": { input: 1.50, output: 7.50, cached: 0.15, reasoning: 11.25, cache_creation: 1.875 },
|
||||
"gemini-3.6-flash": { input: 1.50, output: 7.50, cached: 0.15, reasoning: 11.25, cache_creation: 1.875 },
|
||||
"gemini-3.6-flash-high": { input: 1.50, output: 7.50, cached: 0.15, reasoning: 11.25, cache_creation: 1.875 },
|
||||
"gemini-3.6-flash-medium": { input: 1.50, output: 7.50, cached: 0.15, reasoning: 11.25, cache_creation: 1.875 },
|
||||
|
||||
@@ -45,6 +45,9 @@ export default {
|
||||
clientSecret: "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",
|
||||
},
|
||||
models: [
|
||||
{ id: "gemini-3.7-flash-high", name: "Gemini 3.7 Flash (High)", upstreamModelId: "gemini-3.7-flash-tiered(high)" },
|
||||
{ id: "gemini-3.7-flash-medium", name: "Gemini 3.7 Flash (Medium)", upstreamModelId: "gemini-3.7-flash-tiered(medium)" },
|
||||
{ id: "gemini-3.7-flash-low", name: "Gemini 3.7 Flash (Low)", upstreamModelId: "gemini-3.7-flash-tiered(low)" },
|
||||
{ id: "gemini-3.6-flash-high", name: "Gemini 3.6 Flash (High)", upstreamModelId: "gemini-3.6-flash-tiered(high)" },
|
||||
{ id: "gemini-3.6-flash-medium", name: "Gemini 3.6 Flash (Medium)", upstreamModelId: "gemini-3.6-flash-tiered(medium)" },
|
||||
{ id: "gemini-3.6-flash-low", name: "Gemini 3.6 Flash (Low)", upstreamModelId: "gemini-3.6-flash-tiered(low)" },
|
||||
|
||||
@@ -36,6 +36,7 @@ export default {
|
||||
},
|
||||
},
|
||||
models: [
|
||||
{ id: "gemini-3.7-flash", name: "Gemini 3.7 Flash" },
|
||||
{ id: "gemini-3.6-flash", name: "Gemini 3.6 Flash" },
|
||||
{ id: "gemini-3.5-flash-lite", name: "Gemini 3.5 Flash Lite" },
|
||||
{ id: "gemini-3.1-pro-preview", name: "Gemini 3.1 Pro Preview" },
|
||||
|
||||
@@ -161,6 +161,9 @@ export async function getAntigravityUsage(accessToken, providerSpecificData, pro
|
||||
if (data.models) {
|
||||
// Filter only recommended/important models (must match PROVIDER_MODELS ag ids)
|
||||
const importantModels = [
|
||||
'gemini-3.7-flash-high',
|
||||
'gemini-3.7-flash-medium',
|
||||
'gemini-3.7-flash-low',
|
||||
'gemini-3.6-flash-high',
|
||||
'gemini-3.6-flash-medium',
|
||||
'gemini-3.6-flash-low',
|
||||
|
||||
@@ -55,6 +55,9 @@ const MODEL_SYNONYMS = {
|
||||
"gemini-3.5-flash-high": "gemini-3-flash-agent",
|
||||
"gemini-3.5-flash-medium": "gemini-3.5-flash-low",
|
||||
"gemini-3.5-flash-extra-low": "gemini-3.5-flash-extra-low",
|
||||
"gemini-3.7-flash-high": "gemini-3.7-flash-high",
|
||||
"gemini-3.7-flash-medium": "gemini-3.7-flash-medium",
|
||||
"gemini-3.7-flash-low": "gemini-3.7-flash-low",
|
||||
"gemini-3.1-pro-high": "gemini-pro-agent",
|
||||
"gemini-3-pro-high": "gemini-pro-agent",
|
||||
"gemini-3-pro-low": "gemini-3.1-pro-low",
|
||||
@@ -131,13 +134,15 @@ function extractModel(url, body) {
|
||||
return parsed.conversationState.currentMessage?.userInputMessage?.modelId || null;
|
||||
}
|
||||
const model = urlModel || parsed.model || null;
|
||||
if (String(model).replace(/^models\//, "") === "gemini-3.6-flash-tiered") {
|
||||
const cleanModelName = String(model).replace(/^models\//, "");
|
||||
if (cleanModelName === "gemini-3.6-flash-tiered" || cleanModelName === "gemini-3.7-flash-tiered") {
|
||||
const ver = cleanModelName.includes("3.7") ? "3.7" : "3.6";
|
||||
const rawLevel = parsed.request?.generationConfig?.thinkingConfig?.thinkingLevel
|
||||
|| parsed.generationConfig?.thinkingConfig?.thinkingLevel;
|
||||
const level = ["high", "medium", "low"].includes(String(rawLevel).toLowerCase())
|
||||
? String(rawLevel).toLowerCase()
|
||||
: "medium";
|
||||
return `gemini-3.6-flash-${level}`;
|
||||
return `gemini-${ver}-flash-${level}`;
|
||||
}
|
||||
return model;
|
||||
} catch {
|
||||
|
||||
@@ -8,7 +8,7 @@ export const MITM_TOOLS = {
|
||||
description: "Google Antigravity IDE with MITM",
|
||||
configType: "mitm",
|
||||
mitmDomain: "daily-cloudcode-pa.googleapis.com",
|
||||
modelAliases: ["gemini-3.6-flash-high", "gemini-3.6-flash-medium", "gemini-3.6-flash-low", "gemini-3.5-flash-low", "gemini-3-flash-agent", "gemini-3.5-flash-extra-low", "gemini-3.1-pro-low", "gemini-pro-agent", "claude-sonnet-4-6", "claude-opus-4-6-thinking", "gpt-oss-120b-medium", "gemini-3-flash"],
|
||||
modelAliases: ["gemini-3.7-flash-high", "gemini-3.7-flash-medium", "gemini-3.7-flash-low", "gemini-3.6-flash-high", "gemini-3.6-flash-medium", "gemini-3.6-flash-low", "gemini-3.5-flash-low", "gemini-3-flash-agent", "gemini-3.5-flash-extra-low", "gemini-3.1-pro-low", "gemini-pro-agent", "claude-sonnet-4-6", "claude-opus-4-6-thinking", "gpt-oss-120b-medium", "gemini-3-flash"],
|
||||
defaultModels: [
|
||||
{ id: "gemini-3.6-flash-high", name: "Gemini 3.6 Flash (High)", alias: "gemini-3.6-flash-high" },
|
||||
{ id: "gemini-3.6-flash-medium", name: "Gemini 3.6 Flash (Medium)", alias: "gemini-3.6-flash-medium" },
|
||||
|
||||
61
tests/unit/antigravity-quota-gemini-3.7.test.js
Normal file
61
tests/unit/antigravity-quota-gemini-3.7.test.js
Normal file
@@ -0,0 +1,61 @@
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
|
||||
const proxyAwareFetch = vi.fn(async (url) => ({
|
||||
ok: true,
|
||||
status: 200,
|
||||
json: async () => url.includes(":loadCodeAssist")
|
||||
? { cloudaicompanionProject: "project-1", currentTier: { name: "Pro" } }
|
||||
: {
|
||||
models: {
|
||||
"gemini-3.7-flash-high": {
|
||||
displayName: "Gemini 3.7 Flash (High)",
|
||||
quotaInfo: { remainingFraction: 0.85, resetTime: "2026-08-25T12:00:00Z" },
|
||||
},
|
||||
"gemini-3.7-flash-medium": {
|
||||
displayName: "Gemini 3.7 Flash (Medium)",
|
||||
quotaInfo: { remainingFraction: 0.6, resetTime: "2026-08-25T12:00:00Z" },
|
||||
},
|
||||
"gemini-3.7-flash-low": {
|
||||
displayName: "Gemini 3.7 Flash (Low)",
|
||||
quotaInfo: { remainingFraction: 0.35, resetTime: "2026-08-25T12:00:00Z" },
|
||||
},
|
||||
"internal-model": {
|
||||
displayName: "Internal",
|
||||
isInternal: true,
|
||||
quotaInfo: { remainingFraction: 0.5 },
|
||||
},
|
||||
},
|
||||
},
|
||||
text: async () => "{}",
|
||||
}));
|
||||
|
||||
vi.mock("../../open-sse/utils/proxyFetch.js", () => ({
|
||||
proxyAwareFetch,
|
||||
}));
|
||||
|
||||
describe("Antigravity quota tracker: Gemini 3.7 Flash usage bars", () => {
|
||||
beforeEach(() => proxyAwareFetch.mockClear());
|
||||
|
||||
it("returns Gemini 3.7 Flash tier quotas so the dashboard can render usage bars", async () => {
|
||||
const { getAntigravityUsage } = await import("../../open-sse/services/usage/google.js");
|
||||
|
||||
const usage = await getAntigravityUsage("access-token", {});
|
||||
|
||||
expect(usage.quotas["gemini-3.7-flash-high"]).toMatchObject({
|
||||
used: 150,
|
||||
total: 1000,
|
||||
remainingPercentage: 85,
|
||||
displayName: "Gemini 3.7 Flash (High)",
|
||||
});
|
||||
expect(usage.quotas["gemini-3.7-flash-medium"]).toMatchObject({
|
||||
used: 400,
|
||||
total: 1000,
|
||||
remainingPercentage: 60,
|
||||
});
|
||||
expect(usage.quotas["gemini-3.7-flash-low"]).toMatchObject({
|
||||
used: 650,
|
||||
total: 1000,
|
||||
remainingPercentage: 35,
|
||||
});
|
||||
});
|
||||
});
|
||||
36
tests/unit/gemini-3.7-antigravity.test.js
Normal file
36
tests/unit/gemini-3.7-antigravity.test.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { getCapabilitiesForModel } from "../../open-sse/providers/capabilities.js";
|
||||
import antigravityRegistry from "../../open-sse/providers/registry/antigravity.js";
|
||||
import geminiRegistry from "../../open-sse/providers/registry/gemini.js";
|
||||
import { MODEL_PRICING } from "../../open-sse/providers/pricing.js";
|
||||
|
||||
describe("Gemini 3.7 Flash Support & Config (#3286, #3281)", () => {
|
||||
it("registers gemini-3.7-flash tiered models in antigravity provider registry", () => {
|
||||
const agIds = antigravityRegistry.models.map(m => m.id);
|
||||
expect(agIds).toContain("gemini-3.7-flash-high");
|
||||
expect(agIds).toContain("gemini-3.7-flash-medium");
|
||||
expect(agIds).toContain("gemini-3.7-flash-low");
|
||||
expect(agIds).not.toContain("gemini-3.7-flash");
|
||||
});
|
||||
|
||||
it("registers gemini-3.7-flash in gemini provider registry", () => {
|
||||
const geminiIds = geminiRegistry.models.map(m => m.id);
|
||||
expect(geminiIds).toContain("gemini-3.7-flash");
|
||||
});
|
||||
|
||||
it("resolves capabilities correctly for gemini-3.7 models with official limits", () => {
|
||||
const caps = getCapabilitiesForModel("antigravity", "gemini-3.7-flash-high");
|
||||
expect(caps.vision).toBe(true);
|
||||
expect(caps.reasoning).toBe(true);
|
||||
expect(caps.thinkingFormat).toBe("gemini-level");
|
||||
expect(caps.contextWindow).toBe(1048576);
|
||||
expect(caps.maxOutput).toBe(65536);
|
||||
});
|
||||
|
||||
it("defines pricing matching gemini-3.6-flash baseline", () => {
|
||||
expect(MODEL_PRICING["gemini-3.7-flash"]).toEqual(MODEL_PRICING["gemini-3.6-flash"]);
|
||||
expect(MODEL_PRICING["gemini-3.7-flash-high"]).toEqual(MODEL_PRICING["gemini-3.6-flash-high"]);
|
||||
expect(MODEL_PRICING["gemini-3.7-flash-medium"]).toEqual(MODEL_PRICING["gemini-3.6-flash-medium"]);
|
||||
expect(MODEL_PRICING["gemini-3.7-flash-low"]).toEqual(MODEL_PRICING["gemini-3.6-flash-low"]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user