fix(pricing): default cost rows for Antigravity Gemini 3.5 Flash tiers + gemini-pro-agent (#4508)

Rebuilt onto release/v3.8.33 (squash-base-stale). Integrated into release/v3.8.33.
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-06-21 14:14:53 -03:00
committed by GitHub
parent 840413faa2
commit 34d9335c5f
3 changed files with 73 additions and 0 deletions

View File

@@ -63,6 +63,7 @@ _In development — bullets added per PR; finalized at release._
- **fix(combo): model lockout now honors a long upstream quota reset instead of retrying within minutes** — when a combo target returned a quota error carrying an explicit long reset (e.g. Antigravity `Resets in 160h27m24s`, a `Retry-After` header), the per-model lockout capped at the short base cooldown (~minutes) and discarded the parsed reset, so the exhausted model kept being retried far too early. The lockout now applies the parsed reset when it exceeds the base cooldown, and the Antigravity error-message parser also matches the plural `Resets in …` phrasing. (thanks @Ansh7473)
- **fix(antigravity): Claude models no longer 400 with `Unknown name "output_config"`** — Anthropic/Claude-Code-only fields (`output_config`, legacy `output_format`) leaked into the Google Cloud Code request envelope via its top-level field passthrough, and Google rejects unknown envelope fields with `400 Invalid JSON payload received. Unknown name "output_config"` — breaking every Claude model served through Antigravity in IDEs. Those fields are now dropped before the envelope is built. (thanks @Duongkhanhtool)
- **fix(combo): round-robin members fail over faster under concurrency saturation via a configurable queue depth** — when a round-robin combo member was saturated, requests sat in the per-model semaphore's **unbounded** queue and only failed over to the next member after the full `queueTimeoutMs` (default 30s) elapsed — so a burst of agentic requests deep-queued one hot member instead of spilling to healthy ones. The per-model semaphore now accepts a bounded queue depth and emits `SEMAPHORE_QUEUE_FULL` once it is full (the round-robin loop already cascades on that code), so a configured low depth fails over immediately. A new `queueDepth` combo-config knob (global default / provider override / per-combo, default **20** for backward compatibility; **0** = never queue → fail over now) is exposed in Settings → Combo Defaults. ([#3872](https://github.com/diegosouzapw/OmniRoute/issues/3872) — thanks @KooshaPari)
- **fix(pricing): default cost rows for Antigravity's Gemini 3.5 Flash tiers + `gemini-pro-agent`** — the Antigravity public catalog (`ANTIGRAVITY_PUBLIC_MODELS`) ships `gemini-3-flash-agent`, `gemini-3.5-flash-low`, and `gemini-pro-agent` as user-callable client ids, but the `ag` block in the default pricing table only carried rows for `gemini-3-flash` / `gemini-3.1-pro-high`, so `getPricingForModel("ag", id)` returned `null` and cost / quota accounting silently fell back to `$0` for those three models. The missing rows are now seeded with the per-MTok rates the upstream quota tier bills at (Flash High/Medium share the legacy `gemini-3-flash` rate; `gemini-pro-agent` shares `gemini-3.1-pro-high`). (thanks @Ansh7473)
- **fix(pricing): align Claude Code (`cc`) pricing with current Anthropic per-MTok rates** — the `cc` provider block in the default pricing table had stale numbers across every Claude 4.x family entry — most visibly, `claude-opus-4-5-20251101` was billed at the deprecated Opus 4.1 rate (`input $15` / `output $75`), and `claude-haiku-4-5-20251001` was at half the current Haiku 4.5 rate. The `cached` (cache hit) and `cache_creation` (5-minute cache write) multipliers were also off across Opus 4.6/4.7/4.8, Sonnet 4.5/4.6, Haiku 4.5, and Fable 5. All eight entries now match the rates Anthropic publishes (input, 5m cache write at 1.25x input, cache hit at 0.1x input, output; reasoning billed at the output rate), so cost accounting on the dashboard and per-request usage events stop under- or over-reporting Claude Code spend. (thanks @chulanpro5)
- **fix(executors): sanitize Anthropic-shape content parts before GitHub Copilot `/chat/completions`** — Claude models on GitHub Copilot driven from clients like Cursor IDE (e.g. `gh/claude-sonnet-4.6`) failed with `Provider returned error: type has to be either 'image_url' or 'text' (reset after 30s)` because the client passed through Anthropic-shape content parts (`tool_use`, `tool_result`, `thinking`) untouched, and the Copilot chat-completions endpoint only accepts `text`/`image_url`. `GithubExecutor.transformRequest` now serializes any unsupported part type as `text` (preserving the model's context), drops empty parts, and collapses to `null` when an assistant message's only content was tool_calls — `tool_calls` ride alongside untouched. Codex-family models still route through `/responses` unchanged. (thanks @cngznNN)
- **fix(sse):** refactor stall detection to reduce false positives on slow but progressing streams. (thanks @zakirkun)

View File

@@ -548,6 +548,36 @@ export const DEFAULT_PRICING = {
reasoning: 4.5,
cache_creation: 0.5,
},
// Antigravity 2.0.4+ exposes Gemini 3.5 Flash as three public client ids
// (see ANTIGRAVITY_PUBLIC_MODELS in open-sse/config/antigravityModelAliases.ts):
// gemini-3-flash-agent → "Gemini 3.5 Flash (High)"
// gemini-3.5-flash-low → "Gemini 3.5 Flash (Medium)"
// Both bill at the same per-MTok rates as legacy `gemini-3-flash` above —
// without these rows, getPricingForModel("ag", id) returned null and downstream
// cost / quota calculations silently fell back to $0.
"gemini-3-flash-agent": {
input: 0.5,
output: 3.0,
cached: 0.03,
reasoning: 4.5,
cache_creation: 0.5,
},
"gemini-3.5-flash-low": {
input: 0.5,
output: 3.0,
cached: 0.03,
reasoning: 4.5,
cache_creation: 0.5,
},
// `gemini-pro-agent` is the Antigravity v1.23+ Agent-mode alias for the
// Gemini 3.1 Pro (High) tier — bills at the same rates as `gemini-3.1-pro-high`.
"gemini-pro-agent": {
input: 4.0,
output: 18.0,
cached: 0.5,
reasoning: 27.0,
cache_creation: 4.0,
},
"claude-sonnet-4-6": {
input: 3.0,
output: 15.0,

View File

@@ -0,0 +1,42 @@
import test from "node:test";
import assert from "node:assert/strict";
import { getDefaultPricing } from "../../src/shared/constants/pricing.ts";
// Antigravity exposes Gemini 3.5 Flash via three public client IDs in
// ANTIGRAVITY_PUBLIC_MODELS (`open-sse/config/antigravityModelAliases.ts`):
// - gemini-3-flash-agent → "Gemini 3.5 Flash (High)" — upstream High tier
// - gemini-3.5-flash-low → "Gemini 3.5 Flash (Medium)" — upstream Medium tier
// - gemini-pro-agent → "Gemini 3.1 Pro (High)" — upstream Pro High alias
// All three were missing pricing rows in `ag` (DEFAULT_PRICING.ag), so
// getPricingForModel("ag", id) returned null and downstream cost / quota
// calculations silently fell back to $0. The same pricing schedule used for
// the legacy `gemini-3-flash` and `gemini-3.1-pro-high` rows applies (same
// per-MTok rates as the upstream quota tier they map to).
test("ag/gemini-3-flash-agent matches the Gemini 3.5 Flash (High) tier", () => {
const p = getDefaultPricing().ag["gemini-3-flash-agent"];
assert.equal(p.input, 0.5);
assert.equal(p.output, 3.0);
assert.equal(p.cached, 0.03);
assert.equal(p.reasoning, 4.5);
assert.equal(p.cache_creation, 0.5);
});
test("ag/gemini-3.5-flash-low matches the Gemini 3.5 Flash (Medium) tier", () => {
const p = getDefaultPricing().ag["gemini-3.5-flash-low"];
assert.equal(p.input, 0.5);
assert.equal(p.output, 3.0);
assert.equal(p.cached, 0.03);
assert.equal(p.reasoning, 4.5);
assert.equal(p.cache_creation, 0.5);
});
test("ag/gemini-pro-agent matches the Gemini 3.1 Pro (High) tier", () => {
const p = getDefaultPricing().ag["gemini-pro-agent"];
assert.equal(p.input, 4.0);
assert.equal(p.output, 18.0);
assert.equal(p.cached, 0.5);
assert.equal(p.reasoning, 27.0);
assert.equal(p.cache_creation, 4.0);
});