From a73256ee72c06cb98a82925fdcb3e073dd117ea4 Mon Sep 17 00:00:00 2001 From: "Alexander (SASh) Alexiev" Date: Fri, 22 May 2026 15:50:07 +0300 Subject: [PATCH] fix(antigravity): strip Claude entries from catalog (ampeco Patch 4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Antigravity's published model catalog includes `claude-opus-4-6-thinking` and `claude-sonnet-4-6` because Google's AI Code Assist tier resells Claude models through `cloudcode-pa.googleapis.com`. With those entries present, an antigravity OAuth is registered as eligible alongside the Anthropic OAuth pool for `claude-*` selector picks. Session-affinity then pins entire Claude Code sessions (parent + child sub-agents like Plan / Explore / code-reviewer / sub-Skills) to the antigravity OAuth whenever the parent request was a Gemini call. The Antigravity Sonnet quota is much smaller than Anthropic's 5h windows and drains within hours, returning: 429 RESOURCE_EXHAUSTED { domain: cloudcode-pa.googleapis.com, model: claude-sonnet-4-6, quotaResetDelay: ~5h } The selector logs from a live battle run on 2026-05-22 show the exact leak path: 14:56 model=gemini-3.5-flash-low auth=antigravity-...json (intended) 15:08 model=claude-sonnet-4-6 auth=antigravity-...json (LEAK) Patch applies in two places: - `internal/registry/models/models.json` — strip Claude entries from the in-tree `antigravity` array so `go test ./...` and local dev builds see the patched shape (8 entries remain: Gemini 3.x + gpt-oss-120b-medium). - `.github/workflows/release.yaml` — add a post-refresh step that re-applies the strip after the upstream catalog fetch from `router-for-me/models`, so tagged builds preserve the patch indefinitely without requiring upstream changes. Filter pattern catches any future Claude variant Google adds to the Antigravity offering: removes entries where `id.startswith("claude-")` OR `type == "claude"` OR `owned_by == "anthropic"`. After deploy, claude-sonnet-4-6 requests can only route to the `claude-Cooperator*@ampeco.global.json` OAuth files; the antigravity OAuth becomes Gemini-only. NB on registry tests: `TestCodexFreeModelsExcludeGPT55` is failing on upstream main as well (the upstream catalog moved `gpt-5.5` into `codex-free` but the test wasn't updated). The failure is pre-existing and unrelated to this patch. README updated with Patch 4 documentation matching the existing patch series style. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/release.yaml | 31 +++++++++++++++++++++++++ README.md | 9 ++++++++ internal/registry/models/models.json | 34 ---------------------------- 3 files changed, 40 insertions(+), 34 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4043e4a5dd..4722e45e76 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -20,6 +20,37 @@ jobs: run: | git fetch --depth 1 https://github.com/router-for-me/models.git main git show FETCH_HEAD:models.json > internal/registry/models/models.json + - name: Strip Claude entries from antigravity catalog (ampeco Patch 4) + # Antigravity's published catalog advertises Claude models served by + # Google's cloudcode-pa.googleapis.com. With those entries present, an + # antigravity OAuth becomes eligible alongside the Anthropic OAuth pool + # for `claude-*` selector picks. Session-affinity then pins entire + # Claude Code sessions (parent + sub-agents) to the antigravity OAuth + # whenever the parent request was a Gemini call, exhausting + # Antigravity's small Sonnet quota within hours. Strip them post-refresh + # so the antigravity OAuth is Gemini-only. + run: | + python3 - <<'PY' + import json + p = "internal/registry/models/models.json" + with open(p) as f: + d = json.load(f) + if "antigravity" in d: + before = len(d["antigravity"]) + d["antigravity"] = [ + m for m in d["antigravity"] + if not ( + m.get("id", "").startswith("claude-") + or m.get("type", "") == "claude" + or m.get("owned_by", "") == "anthropic" + ) + ] + after = len(d["antigravity"]) + print(f"antigravity catalog: {before} -> {after} entries ({before - after} claude stripped)") + with open(p, "w") as f: + json.dump(d, f, indent=2) + f.write("\n") + PY - run: git fetch --force --tags - uses: actions/setup-go@v4 with: diff --git a/README.md b/README.md index 9d6ce7d505..df9e32d00e 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,20 @@ Remove `cache_control` from `messages[].content[]`, `system[]`, `tools[]`, and m When the credential's API key starts with `sk-ant-oat01-`, route via `Authorization: Bearer …` instead of `x-api-key`. Real `sk-ant-api03-*` API keys keep the existing `x-api-key` routing. +### Patch 4 — strip Claude entries from the `antigravity` model catalog + +`internal/registry/models/models.json` and `.github/workflows/release.yaml` (post-refresh step). + +Antigravity's published catalog includes `claude-opus-4-6-thinking` and `claude-sonnet-4-6` because Google's AI Code Assist tier resells Claude models via `cloudcode-pa.googleapis.com`. With those entries present, an antigravity OAuth becomes eligible alongside the Anthropic OAuth pool when the selector picks for `claude-*` routes. Session-affinity then pins entire Claude Code sessions (parent + sub-agents) to the antigravity OAuth whenever the parent request was a Gemini call, exhausting Antigravity's small Sonnet quota within hours. + +Strip every entry whose `id` starts with `claude-`, whose `type` is `claude`, or whose `owned_by` is `anthropic` from the `antigravity` array. Applied both to the in-tree `models.json` (so `go test ./...` and local dev see the patched shape) and to the release workflow's post-refresh step (so upstream catalog refreshes during tagged builds re-apply the strip automatically). After the patch the antigravity OAuth is Gemini-only and Claude requests fall through to the Anthropic OAuth pool. + ## Tests ```bash go test ./internal/translator/openai/claude/... # Patches 1 + 2 go test ./internal/runtime/executor/ -run 'OAuthAccessTokenUsesBearerAuth|ApiKeyStillUsesXApiKey' # Patch 3 +go test ./internal/registry/... # Patch 4 (catalog integrity) ``` ## Rebase diff --git a/internal/registry/models/models.json b/internal/registry/models/models.json index fa56bb42a2..1d374e1f27 100644 --- a/internal/registry/models/models.json +++ b/internal/registry/models/models.json @@ -1874,40 +1874,6 @@ } ], "antigravity": [ - { - "id": "claude-opus-4-6-thinking", - "object": "model", - "owned_by": "antigravity", - "type": "antigravity", - "display_name": "Claude Opus 4.6 (Thinking)", - "name": "claude-opus-4-6-thinking", - "description": "Claude Opus 4.6 (Thinking)", - "context_length": 200000, - "max_completion_tokens": 64000, - "thinking": { - "min": 1024, - "max": 64000, - "zero_allowed": true, - "dynamic_allowed": true - } - }, - { - "id": "claude-sonnet-4-6", - "object": "model", - "owned_by": "antigravity", - "type": "antigravity", - "display_name": "Claude Sonnet 4.6 (Thinking)", - "name": "claude-sonnet-4-6", - "description": "Claude Sonnet 4.6 (Thinking)", - "context_length": 200000, - "max_completion_tokens": 64000, - "thinking": { - "min": 1024, - "max": 64000, - "zero_allowed": true, - "dynamic_allowed": true - } - }, { "id": "gemini-3-flash", "object": "model",