diff --git a/cli/src/cli/menus/providers.js b/cli/src/cli/menus/providers.js index 92d10a04..42fbed6f 100644 --- a/cli/src/cli/menus/providers.js +++ b/cli/src/cli/menus/providers.js @@ -53,6 +53,9 @@ const PROVIDER_MODELS = { { id: "glm-4.7" }, ], ag: [ + { id: "gemini-3.8-flash-high" }, + { id: "gemini-3.8-flash-medium" }, + { id: "gemini-3.8-flash-low" }, { id: "gemini-3.7-flash-high" }, { id: "gemini-3.7-flash-medium" }, { id: "gemini-3.7-flash-low" }, @@ -101,6 +104,8 @@ const PROVIDER_MODELS = { { id: "claude-3-5-sonnet-20241022" }, ], gemini: [ + { id: "gemini-3.8-flash" }, + { id: "gemini-3.7-flash" }, { id: "gemini-3.6-flash" }, { id: "gemini-3.5-flash-lite" }, { id: "gemini-3-pro-preview" }, diff --git a/open-sse/providers/capabilities.js b/open-sse/providers/capabilities.js index 25e0048c..cdb6bae9 100644 --- a/open-sse/providers/capabilities.js +++ b/open-sse/providers/capabilities.js @@ -226,6 +226,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.8*", caps: { vision: true, audioInput: true, videoInput: true, reasoning: true, search: true, thinkingFormat: "gemini-level", thinkingCanDisable: false, contextWindow: 1048576, maxOutput: 65536 } }, { 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 } }, diff --git a/open-sse/providers/pricing.js b/open-sse/providers/pricing.js index cf6ffd55..1855964a 100644 --- a/open-sse/providers/pricing.js +++ b/open-sse/providers/pricing.js @@ -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.8-flash": { input: 1.50, output: 7.50, cached: 0.15, reasoning: 11.25, cache_creation: 1.875 }, + "gemini-3.8-flash-high": { input: 1.50, output: 7.50, cached: 0.15, reasoning: 11.25, cache_creation: 1.875 }, + "gemini-3.8-flash-medium": { input: 1.50, output: 7.50, cached: 0.15, reasoning: 11.25, cache_creation: 1.875 }, + "gemini-3.8-flash-low": { input: 1.50, output: 7.50, cached: 0.15, reasoning: 11.25, cache_creation: 1.875 }, "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 }, diff --git a/open-sse/providers/registry/antigravity.js b/open-sse/providers/registry/antigravity.js index 1f14f415..ab1ee574 100644 --- a/open-sse/providers/registry/antigravity.js +++ b/open-sse/providers/registry/antigravity.js @@ -36,8 +36,7 @@ export default { }, }, usage: { - // Discovery (quota/project) on PROD; daily host rejects these. - quotaApiUrl: "https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels", + quotaApiUrl: `${ANTIGRAVITY_IDE_BASE_URL}/v1internal:fetchAvailableModels`, loadProjectApiUrl: "https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist", tokenUrl: "https://oauth2.googleapis.com/token", }, @@ -45,6 +44,10 @@ export default { clientSecret: "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", }, models: [ + { id: "gemini-3.8-flash-high", name: "Gemini 3.8 Flash (High)", upstreamModelId: "gemini-3.8-flash-high(high)" }, + { id: "gemini-3.8-flash-medium", name: "Gemini 3.8 Flash (Medium)", upstreamModelId: "gemini-3.8-flash-medium(medium)" }, + { id: "gemini-3.8-flash-low", name: "Gemini 3.8 Flash (Low)", upstreamModelId: "gemini-3.8-flash-low(low)" }, + { id: "gemini-3.8-flash", name: "Gemini 3.8 Flash", upstreamModelId: "gemini-3.8-flash-medium(medium)" }, { 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)" }, diff --git a/open-sse/providers/registry/gemini.js b/open-sse/providers/registry/gemini.js index df643556..590bf48e 100644 --- a/open-sse/providers/registry/gemini.js +++ b/open-sse/providers/registry/gemini.js @@ -36,6 +36,7 @@ export default { }, }, models: [ + { id: "gemini-3.8-flash", name: "Gemini 3.8 Flash" }, { 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" }, diff --git a/open-sse/providers/shared.js b/open-sse/providers/shared.js index 7cce572f..88488499 100644 --- a/open-sse/providers/shared.js +++ b/open-sse/providers/shared.js @@ -75,10 +75,10 @@ export const KIMI_CODING_BASE_URL = "https://api.kimi.com/coding/v1/messages"; export const OPENAI_COMPAT_BASE = "https://api.openai.com/v1"; export const ANTHROPIC_COMPAT_BASE = "https://api.anthropic.com/v1"; -// Official Antigravity IDE Desktop 2.1.1 fingerprint captured from macOS arm64. +// Official Antigravity IDE Desktop 2.11.0 fingerprint captured from macOS arm64. // Keep this static even when 9router runs on Linux: the provider profile is // intentionally matching the IDE client, not the server host. -export const ANTIGRAVITY_IDE_VERSION = "2.1.1"; +export const ANTIGRAVITY_IDE_VERSION = "2.11.0"; export const ANTIGRAVITY_IDE_BASE_URL = "https://daily-cloudcode-pa.googleapis.com"; export const ANTIGRAVITY_IDE_USER_AGENT = `antigravity/ide/${ANTIGRAVITY_IDE_VERSION} darwin/arm64`; diff --git a/open-sse/services/usage/google.js b/open-sse/services/usage/google.js index c7564c00..9afbe4ca 100644 --- a/open-sse/services/usage/google.js +++ b/open-sse/services/usage/google.js @@ -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.8-flash-high', + 'gemini-3.8-flash-medium', + 'gemini-3.8-flash-low', 'gemini-3.7-flash-high', 'gemini-3.7-flash-medium', 'gemini-3.7-flash-low', diff --git a/src/mitm/antigravityIdeVersion.js b/src/mitm/antigravityIdeVersion.js index e5fe3113..a8656030 100644 --- a/src/mitm/antigravityIdeVersion.js +++ b/src/mitm/antigravityIdeVersion.js @@ -4,7 +4,7 @@ // backend accepts them. Catalog and other passthrough requests retain the // client's current identity. Hardcoded MVP — toggle/version configurable later. -const ANTIGRAVITY_IDE_VERSION = "1.23.2"; +const ANTIGRAVITY_IDE_VERSION = "2.11.0"; const ANTIGRAVITY_IDE_VERSION_OVERRIDE_ENABLED = true; function shouldRewriteMetadata(metadata) { diff --git a/src/mitm/config.js b/src/mitm/config.js index 73653a3c..cab3c621 100644 --- a/src/mitm/config.js +++ b/src/mitm/config.js @@ -55,7 +55,11 @@ 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.8-flash": "gemini-3.8-flash-medium", + "gemini-3.8-flash-high": "gemini-3.8-flash-high", + "gemini-3.8-flash-medium": "gemini-3.8-flash-medium", + "gemini-3.8-flash-low": "gemini-3.8-flash-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", @@ -135,8 +139,8 @@ function extractModel(url, body) { } const model = urlModel || parsed.model || null; 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"; + if (cleanModelName === "gemini-3.6-flash-tiered" || cleanModelName === "gemini-3.7-flash-tiered" || cleanModelName === "gemini-3.8-flash-tiered") { + const ver = cleanModelName.includes("3.8") ? "3.8" : 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()) diff --git a/src/shared/constants/cliTools.js b/src/shared/constants/cliTools.js index 35e1bf03..9a388866 100644 --- a/src/shared/constants/cliTools.js +++ b/src/shared/constants/cliTools.js @@ -8,8 +8,11 @@ export const MITM_TOOLS = { description: "Google Antigravity IDE with MITM", configType: "mitm", mitmDomain: "daily-cloudcode-pa.googleapis.com", - 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"], + modelAliases: ["gemini-3.8-flash-high", "gemini-3.8-flash-medium", "gemini-3.8-flash-low", "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.8-flash-high", name: "Gemini 3.8 Flash (High)", alias: "gemini-3.8-flash-high" }, + { id: "gemini-3.8-flash-medium", name: "Gemini 3.8 Flash (Medium)", alias: "gemini-3.8-flash-medium" }, + { id: "gemini-3.8-flash-low", name: "Gemini 3.8 Flash (Low)", alias: "gemini-3.8-flash-low" }, { id: "gemini-3.7-flash-high", name: "Gemini 3.7 Flash (High)", alias: "gemini-3.7-flash-high" }, { id: "gemini-3.7-flash-medium", name: "Gemini 3.7 Flash (Medium)", alias: "gemini-3.7-flash-medium" }, { id: "gemini-3.7-flash-low", name: "Gemini 3.7 Flash (Low)", alias: "gemini-3.7-flash-low" }, diff --git a/tests/__baseline__/providers-baseline.json b/tests/__baseline__/providers-baseline.json index 3ab6982c..db0b8bad 100644 --- a/tests/__baseline__/providers-baseline.json +++ b/tests/__baseline__/providers-baseline.json @@ -29,7 +29,7 @@ ], "format": "antigravity", "headers": { - "User-Agent": "antigravity/ide/2.1.1 darwin/arm64" + "User-Agent": "antigravity/ide/2.11.0 darwin/arm64" }, "retry": { "429": { @@ -43,7 +43,7 @@ } }, "usage": { - "quotaApiUrl": "https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels", + "quotaApiUrl": "https://daily-cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels", "loadProjectApiUrl": "https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist", "tokenUrl": "https://oauth2.googleapis.com/token" }, diff --git a/tests/unit/antigravity-quota-gemini-3.8.test.js b/tests/unit/antigravity-quota-gemini-3.8.test.js new file mode 100644 index 00000000..cb8637e5 --- /dev/null +++ b/tests/unit/antigravity-quota-gemini-3.8.test.js @@ -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.8-flash-high": { + displayName: "Gemini 3.8 Flash (High)", + quotaInfo: { remainingFraction: 0.85, resetTime: "2026-08-25T12:00:00Z" }, + }, + "gemini-3.8-flash-medium": { + displayName: "Gemini 3.8 Flash (Medium)", + quotaInfo: { remainingFraction: 0.6, resetTime: "2026-08-25T12:00:00Z" }, + }, + "gemini-3.8-flash-low": { + displayName: "Gemini 3.8 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.8 Flash usage bars", () => { + beforeEach(() => proxyAwareFetch.mockClear()); + + it("returns Gemini 3.8 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.8-flash-high"]).toMatchObject({ + used: 150, + total: 1000, + remainingPercentage: 85, + displayName: "Gemini 3.8 Flash (High)", + }); + expect(usage.quotas["gemini-3.8-flash-medium"]).toMatchObject({ + used: 400, + total: 1000, + remainingPercentage: 60, + }); + expect(usage.quotas["gemini-3.8-flash-low"]).toMatchObject({ + used: 650, + total: 1000, + remainingPercentage: 35, + }); + }); +}); diff --git a/tests/unit/antigravity-retry-hook.test.js b/tests/unit/antigravity-retry-hook.test.js index adb8bd25..11985b2c 100644 --- a/tests/unit/antigravity-retry-hook.test.js +++ b/tests/unit/antigravity-retry-hook.test.js @@ -69,13 +69,13 @@ describe("antigravity computeRetryDelay hook (D3)", () => { it("registry uses the daily IDE cloudcode host and user agent", () => { expect(antigravity.transport.baseUrls).toEqual(["https://daily-cloudcode-pa.googleapis.com"]); - expect(antigravity.transport.headers["User-Agent"]).toBe("antigravity/ide/2.1.1 darwin/arm64"); + expect(antigravity.transport.headers["User-Agent"]).toBe("antigravity/ide/2.11.0 darwin/arm64"); }); it("buildHeaders matches official IDE stream headers", () => { ag._lastSessionId = "sess-123"; const h = ag.buildHeaders({ accessToken: "tok" }, true); - expect(h["User-Agent"]).toBe("antigravity/ide/2.1.1 darwin/arm64"); + expect(h["User-Agent"]).toBe("antigravity/ide/2.11.0 darwin/arm64"); expect(h["Content-Type"]).toBe("application/json"); expect(h["Authorization"]).toBe("Bearer tok"); expect(h).not.toHaveProperty("X-Machine-Session-Id"); diff --git a/tests/unit/antigravity-usage-headers.test.js b/tests/unit/antigravity-usage-headers.test.js index 96087552..74cf5287 100644 --- a/tests/unit/antigravity-usage-headers.test.js +++ b/tests/unit/antigravity-usage-headers.test.js @@ -23,7 +23,7 @@ describe("Antigravity usage headers", () => { expect(proxyAwareFetch).toHaveBeenCalledTimes(2); for (const [, options] of proxyAwareFetch.mock.calls) { - expect(options.headers["User-Agent"]).toBe("antigravity/ide/2.1.1 darwin/arm64"); + expect(options.headers["User-Agent"]).toBe("antigravity/ide/2.11.0 darwin/arm64"); expect(options.headers).not.toHaveProperty("x-request-source"); } }); diff --git a/tests/unit/gemini-3.8-antigravity.test.js b/tests/unit/gemini-3.8-antigravity.test.js new file mode 100644 index 00000000..dd5c396e --- /dev/null +++ b/tests/unit/gemini-3.8-antigravity.test.js @@ -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.8 Flash Support & Config", () => { + it("registers gemini-3.8-flash tiered models in antigravity provider registry", () => { + const agIds = antigravityRegistry.models.map(m => m.id); + expect(agIds).toContain("gemini-3.8-flash-high"); + expect(agIds).toContain("gemini-3.8-flash-medium"); + expect(agIds).toContain("gemini-3.8-flash-low"); + expect(agIds).toContain("gemini-3.8-flash"); + }); + + it("registers gemini-3.8-flash in gemini provider registry", () => { + const geminiIds = geminiRegistry.models.map(m => m.id); + expect(geminiIds).toContain("gemini-3.8-flash"); + }); + + it("resolves capabilities correctly for gemini-3.8 models with official limits", () => { + const caps = getCapabilitiesForModel("antigravity", "gemini-3.8-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.7-flash baseline", () => { + expect(MODEL_PRICING["gemini-3.8-flash"]).toEqual(MODEL_PRICING["gemini-3.7-flash"]); + expect(MODEL_PRICING["gemini-3.8-flash-high"]).toEqual(MODEL_PRICING["gemini-3.7-flash-high"]); + expect(MODEL_PRICING["gemini-3.8-flash-medium"]).toEqual(MODEL_PRICING["gemini-3.7-flash-medium"]); + expect(MODEL_PRICING["gemini-3.8-flash-low"]).toEqual(MODEL_PRICING["gemini-3.7-flash-low"]); + }); +}); diff --git a/tests/unit/gemini-38-integration.test.js b/tests/unit/gemini-38-integration.test.js new file mode 100644 index 00000000..b4ca9c5d --- /dev/null +++ b/tests/unit/gemini-38-integration.test.js @@ -0,0 +1,100 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import { createRequire } from "node:module"; +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import { dirname, join } from "node:path"; + +import { getModelUpstreamId } from "../../open-sse/config/providerModels.js"; +import { AntigravityExecutor } from "../../open-sse/executors/antigravity.js"; +import { applyThinking, stripThinkingSuffix } from "../../open-sse/translator/concerns/thinkingUnified.js"; +import gemini from "../../open-sse/providers/registry/gemini.js"; +import { MODEL_PRICING } from "../../open-sse/providers/pricing.js"; +import { MITM_TOOLS } from "../../src/shared/constants/cliTools.js"; + +const require = createRequire(import.meta.url); +const mitmConfig = require("../../src/mitm/config.js"); +const here = dirname(fileURLToPath(import.meta.url)); + +afterEach(() => { + vi.restoreAllMocks(); +}); + +describe("Gemini 3.8 Antigravity tiers", () => { + it.each(["high", "medium", "low"])( + "maps the %s tier to the shared upstream model with matching thinking level", + (tier) => { + const publicModel = `gemini-3.8-flash-${tier}`; + const upstreamModel = getModelUpstreamId("ag", publicModel); + const body = { + model: stripThinkingSuffix(upstreamModel), + request: { + contents: [{ role: "user", parts: [{ text: "hello" }] }], + generationConfig: {}, + }, + }; + + applyThinking("antigravity", upstreamModel, body, "antigravity"); + const finalBody = new AntigravityExecutor().transformRequest( + publicModel, + body, + true, + { projectId: "project", connectionId: "connection" } + ); + + expect(upstreamModel).toBe(`gemini-3.8-flash-${tier}(${tier})`); + expect(finalBody.model).toBe(`gemini-3.8-flash-${tier}`); + expect(finalBody.request.generationConfig.thinkingConfig).toEqual({ + thinkingLevel: tier, + includeThoughts: true, + }); + } + ); +}); + +describe("Gemini 3.8 MITM model extraction", () => { + it.each(["high", "medium", "low"])("extracts the %s thinking tier for gemini-3.8-flash-tiered", (tier) => { + const body = Buffer.from(JSON.stringify({ + request: { generationConfig: { thinkingConfig: { thinkingLevel: tier } } }, + })); + + expect(mitmConfig.extractModel( + "/v1internal/models/gemini-3.8-flash-tiered:streamGenerateContent", + body + )).toBe(`gemini-3.8-flash-${tier}`); + }); + + it("defaults invalid or missing thinking levels to medium", () => { + const body = Buffer.from(JSON.stringify({ + request: { generationConfig: { thinkingConfig: { thinkingLevel: "unknown" } } }, + })); + + expect(mitmConfig.extractModel( + "/v1internal/models/gemini-3.8-flash-tiered:streamGenerateContent", + body + )).toBe("gemini-3.8-flash-medium"); + }); +}); + +describe("Gemini 3.8 MITM tools and catalog", () => { + it("includes gemini-3.8-flash tiers in MITM_TOOLS defaultModels", () => { + const defaultModelIds = MITM_TOOLS.antigravity.defaultModels.map((m) => m.id); + expect(defaultModelIds).toContain("gemini-3.8-flash-high"); + expect(defaultModelIds).toContain("gemini-3.8-flash-medium"); + expect(defaultModelIds).toContain("gemini-3.8-flash-low"); + }); + + it("exposes the direct Gemini 3.8 API models and pricing", () => { + const ids = gemini.models.map((model) => model.id); + expect(ids).toContain("gemini-3.8-flash"); + expect(MODEL_PRICING["gemini-3.8-flash"]).toMatchObject({ input: 1.5, output: 7.5 }); + }); + + it("keeps the standalone CLI Antigravity catalog synchronized", () => { + const source = readFileSync(join(here, "../../cli/src/cli/menus/providers.js"), "utf8"); + const agCatalog = source.match(/\n ag: \[([\s\S]*?)\n \],/)?.[1] || ""; + + expect(agCatalog).toContain("gemini-3.8-flash-high"); + expect(agCatalog).toContain("gemini-3.8-flash-medium"); + expect(agCatalog).toContain("gemini-3.8-flash-low"); + }); +});