Skip to content

fix(antigravity): retry excluded accounts via fallback LRU - #5222

Merged
diegosouzapw merged 2 commits into
diegosouzapw:release/v3.8.40from
Ardem2025:fix/antigravity-account-retry-v2-release-3.8.39
Jun 28, 2026
Merged

diegosouzapw merged 2 commits into
diegosouzapw:release/v3.8.40from
Ardem2025:fix/antigravity-account-retry-v2-release-3.8.39

Conversation

@Ardem2025

Copy link
Copy Markdown
Contributor

Summary

Builds on the family-scoped Antigravity lockout work in #5180 / release v3.8.39.

The combo same-model retry loop accumulates excluded Antigravity connection ids after account-level failures, but the auth selection path only treated excludeConnectionId !== null as a fallback scenario. Once retries accumulated exclusions through excludedConnectionIds, selection could fall back to normal sticky/priority behavior instead of LRU-selecting the next eligible account for the same model/family.

This patch treats any non-empty accumulated exclude set as fallback mode:

const isFallbackScenario = excludeConnectionId !== null || excludedConnectionIds.size > 0;

and adds safe telemetry for the retry decision:

  • excluded_count
  • redacted excluded account prefixes
  • picked_lru
  • candidate counts: active, excluded, modelLocked, familyLocked, eligible

It also keeps forced/pinned connectionId behavior unchanged: same-model account retry is still gated to Antigravity combo requests without a forced connection id.

While rebasing onto release/v3.8.39, the new test also caught that getQuotaScopeLabelForProvider(...) was referenced in src/sse/services/auth.ts without being imported. This branch includes the minimal import fix so the family-lockout path does not fail at runtime.

Test plan

  • node --import tsx --import ./open-sse/utils/setupPolyfill.ts --import ./tests/_setup/isolateDataDir.ts --test tests/unit/auth-antigravity-account-retry-v2.test.ts
    • verifies accumulated multi-exclude enters fallback LRU and skips all excluded Antigravity accounts
    • verifies inferred Antigravity Gemini-family cooldown is ~30s when no upstream retry hint exists
  • npx eslint src/sse/services/auth.ts tests/unit/auth-antigravity-account-retry-v2.test.ts
  • import smoke: node --import tsx --import ./open-sse/utils/setupPolyfill.ts --eval "await import('./src/sse/services/auth.ts'); console.log('auth_import_ok')"
  • npm run typecheck:core

@Ardem2025
Ardem2025 requested a review from diegosouzapw as a code owner June 28, 2026 10:05

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request enhances logging, tracking, and fallback logic for the 'antigravity' provider's connections, specifically handling Gemini family-level lockouts and cooldowns, and adds corresponding unit tests. The reviewer suggested simplifying the fallback scenario check in the round-robin strategy, pointing out that checking excludeConnectionId !== null is redundant since excludedConnectionIds already incorporates it.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/sse/services/auth.ts
const isFallbackScenario = excludeConnectionId !== null;
// If excluding account(s) (fallback scenario), skip sticky logic and go straight to LRU.
// This prevents same-model retries from getting stuck on a failed account.
const isFallbackScenario = excludeConnectionId !== null || excludedConnectionIds.size > 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Since excludedConnectionIds is constructed using normalizeExcludedConnectionIds(excludeConnectionId, options.excludeConnectionIds), it is guaranteed to already contain excludeConnectionId (if it is a valid non-empty string). Therefore, checking excludeConnectionId !== null is redundant when excludedConnectionIds.size > 0 is checked. We can simplify this expression to just excludedConnectionIds.size > 0.

Suggested change
const isFallbackScenario = excludeConnectionId !== null || excludedConnectionIds.size > 0;
const isFallbackScenario = excludedConnectionIds.size > 0;

@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.39 to release/v3.8.40 June 28, 2026 11:12
marxialee and others added 2 commits June 28, 2026 12:59
Treat accumulated excludedConnectionIds as account fallback mode so same-model Antigravity retries walk non-excluded eligible accounts instead of returning to sticky selection. Add safe candidate logging and Antigravity-family inferred cooldown coverage without changing global OAuth cooldown.
…ion guard; extract inferred cooldown constant

The v2 multi-exclude test left only one eligible account, so sticky and LRU
both picked it — it passed with or without the fallback change. Rewritten with
two non-excluded accounts whose lastUsedAt diverge, so it fails without the
`excludedConnectionIds.size > 0` fallback trigger and passes with it. Also
extracts the inferred 30s antigravity-family 429 base to a named constant and
documents that real upstream Retry-After hints still win via exactCooldownMs.

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
@diegosouzapw
diegosouzapw force-pushed the fix/antigravity-account-retry-v2-release-3.8.39 branch from 7d07296 to 3bda790 Compare June 28, 2026 16:05
@diegosouzapw

Copy link
Copy Markdown
Owner

Thanks @Ardem2025! Rebased onto the current release tip and merging. Two adjustments before merge (co-authored):

  1. Strengthened the multi-exclude test into a real regression guard. The original v2 test excluded all-but-one account, so sticky and LRU both picked the survivor — it passed with or without the excludedConnectionIds.size > 0 fallback trigger. It now keeps two non-excluded accounts with diverging lastUsedAt, so it fails without the fallback change and passes with it (verified both ways via TDD).
  2. Extracted the inferred 30s antigravity-family 429 base to a named constant with a note that real upstream Retry-After hints still win (they flow through exactCooldownMs / usedUpstreamRetryHint, not this base — confirmed the ?? ordering is correct).

The fallback LRU change correctly never re-selects excluded/terminal accounts (they're filtered out of orderedConnections upstream). Integrated into release/v3.8.40.

@diegosouzapw
diegosouzapw merged commit 6f150cf into diegosouzapw:release/v3.8.40 Jun 28, 2026
2 of 3 checks passed
diegosouzapw added a commit to backryun/OmniRoute that referenced this pull request Jun 28, 2026
… gates

Review fixes on top of the impersonation-UA refresh:
- perplexity-web.ts: revert the Firefox UA bump 152 -> 148. The perplexity
  TLS profile is firefox_148 (no firefox_152 profile exists in the TLS
  client), and a UA-vs-JA3 mismatch is itself a Cloudflare bot signal
  (diegosouzapw#2459). The UA must stay matched to the TLS fingerprint we actually send.
- translate-path golden snapshot: regenerate so the committed snapshot tracks
  the real output (the hand-edited copy still had the stale Cursor/3.3 UA;
  cursorVersionDetector now emits Cursor/3.9).
- file-size baseline: rebaseline grok-web (1871->1873), muse-spark (1284->1302),
  perplexity-web (1013->1032) — the growth is unavoidable Prettier reflow that
  lint-staged applies to these grandfathered long-line files on any touch; the
  net semantic change is one UA constant each. Also reconcile auth.ts
  (2336->2401), a diegosouzapw#5222 antigravity-LRU growth that merged via --admin without
  a baseline bump.

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
diegosouzapw added a commit to backryun/OmniRoute that referenced this pull request Jun 28, 2026
… gates

Review fixes on top of the impersonation-UA refresh:
- perplexity-web.ts: revert the Firefox UA bump 152 -> 148. The perplexity
  TLS profile is firefox_148 (no firefox_152 profile exists in the TLS
  client), and a UA-vs-JA3 mismatch is itself a Cloudflare bot signal
  (diegosouzapw#2459). The UA must stay matched to the TLS fingerprint we actually send.
- translate-path golden snapshot: regenerate so the committed snapshot tracks
  the real output (the hand-edited copy still had the stale Cursor/3.3 UA;
  cursorVersionDetector now emits Cursor/3.9).
- file-size baseline: rebaseline grok-web (1871->1873), muse-spark (1284->1302),
  perplexity-web (1013->1032) — the growth is unavoidable Prettier reflow that
  lint-staged applies to these grandfathered long-line files on any touch; the
  net semantic change is one UA constant each. Also reconcile auth.ts
  (2336->2401), a diegosouzapw#5222 antigravity-LRU growth that merged via --admin without
  a baseline bump.

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
@diegosouzapw diegosouzapw mentioned this pull request Jun 29, 2026
tkgo11 pushed a commit to tkgo11/OmniRoute that referenced this pull request Sep 23, 2026
…apw#5222)

Antigravity: retry excluded accounts via fallback LRU + family-inferred 429 cooldown. Test strengthened into a real LRU regression guard; cooldown constant extracted. Integrated into release/v3.8.40.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants