Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions src/providers/antigravity-models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ const RETIRED_FLASH_TIERS: Record<string, string> = {
"gemini-3-flash-agent": "high",
};

// Some discovery responses still publish the current Flash thinking levels as
// separate rows. These IDs are picker-visible when the response contains only a
// partial tier set, but CCA accepts them only through the tiered wire ID.
const CURRENT_FLASH_DISCOVERY_TIERS: Record<string, string> = {
"gemini-3.7-flash-low": "low",
"gemini-3.7-flash-medium": "medium",
"gemini-3.7-flash-high": "high",
};

const ANTIGRAVITY_WIRE_MODELS = [
"gemini-3.7-flash-tiered",
"gemini-3.1-pro-low",
Expand Down Expand Up @@ -361,16 +370,24 @@ export function retiredAntigravityFlashTier(modelId: string): string | undefined
* Resolve a picker-visible base model + optional reasoning effort to the CCA wire model ID.
*
* Precedence (evaluated in order):
* 1. Suffix wire ID or compat alias → resolve via `resolveAntigravityWireModelId`, no thinkingConfig.
* 2. Mapped Gemini base with effort → return mapped wire ID + thinkingLevel.
* 3. Mapped Gemini base without effort → return default-effort wire ID, no thinkingConfig.
* 4. Claude Opus with effort → return identity + thinkingLevel (no suffix variants exist).
* 5. All other IDs → return `resolveAntigravityWireModelId(modelId)`, no thinkingConfig.
* 1. Current Flash discovery tier → tiered wire ID + its thinkingLevel.
* 2. Suffix wire ID or compat alias → resolve via `resolveAntigravityWireModelId`, no thinkingConfig.
* 3. Mapped Gemini base with effort → return mapped wire ID + thinkingLevel.
* 4. Mapped Gemini base without effort → return default-effort wire ID, no thinkingConfig.
* 5. Claude Opus with effort → return identity + thinkingLevel (no suffix variants exist).
* 6. All other IDs → return `resolveAntigravityWireModelId(modelId)`, no thinkingConfig.
*/
export function resolveAntigravityEffortWireModel(
modelId: string,
effort?: string,
): { wireModelId: string; thinkingLevel?: string } {
const discoveryTier = Object.hasOwn(CURRENT_FLASH_DISCOVERY_TIERS, modelId)
? CURRENT_FLASH_DISCOVERY_TIERS[modelId]
: undefined;
if (discoveryTier) {
return { wireModelId: GEMINI_FLASH_WIRE_ID, thinkingLevel: discoveryTier };
}
Comment on lines +387 to +389

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Canonicalize partial tier IDs for usage pricing

When live discovery returns a partial Gemini 3.7 tier set and a user selects one of these suffix IDs, this branch makes the request succeed under gemini-3.7-flash-tiered, but the requested suffix remains absent from ANTIGRAVITY_USAGE_BASE_BY_ID. Usage and cost records retain the requested model, and resolveMatchedPrice only falls back to the base price when canonicalAntigravityUsageModel changes that ID, so successful gemini-3.7-flash-low/medium/high calls have no cost estimate despite the existing gemini-3.7-flash price. Map these newly routable IDs to the base model in the usage reverse map and cover the price lookup.

Useful? React with 👍 / 👎.


// Rule 0: retired Flash id — Google has taken the wire id offline, so route to the
// current generation and carry the tier the retired id encoded. This runs BEFORE the
// suffix check because those ids are aliases, and rule 1 would drop the tier.
Expand Down
18 changes: 18 additions & 0 deletions tests/google-antigravity-wire.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,24 @@ describe("antigravity CCA envelope", () => {
}
});

test("routes partial Gemini 3.7 discovery tiers through thinkingLevel", async () => {
for (const [modelId, thinkingLevel] of [
["gemini-3.7-flash-low", "low"],
["gemini-3.7-flash-medium", "medium"],
["gemini-3.7-flash-high", "high"],
] as const) {
expect(resolveAntigravityEffortWireModel(modelId)).toEqual({
wireModelId: "gemini-3.7-flash-tiered",
thinkingLevel,
});

const req = await createGoogleAdapter(effortProvider).buildRequest(parsedWithEffort(modelId));
const env = JSON.parse(req.body);
expect(env.model).toBe("gemini-3.7-flash-tiered");
expect(env.request.generationConfig.thinkingConfig).toEqual({ thinkingLevel });
}
});

test("ignores inherited CCA model and alias properties", () => {
const inheritedModels = Object.create(null) as Record<string, unknown>;
Object.defineProperty(inheritedModels, "__proto__", {
Expand Down
Loading