Repository navigation
fix(providers): mark Antigravity connects with no Cloud Code projectId as degraded (#11284) - #11358
Merged
diegosouzapw merged 3 commits intoAug 24, 2026
Conversation
…tId (cheaper-inference#11284) Google BYOP accounts (no automatic GCP project creation, cheaper-inference#8491) and transient discovery failures both ended with postExchangeAntigravity returning an empty projectId that the OAuth route persisted as a testStatus:"active" connection — the dashboard showed "Connected" while every model call failed. - postExchange now classifies WHY discovery failed: BYOP answers 200 without cloudaicompanionProject (requires_manual_project); upstream errors/timeouts/lag classify as discovery_failed. A project id found in the onboardUser body is used directly when loadCodeAssist lags. - The exchange and poll-callback branches reject antigravity/agy connects carrying a failed outcome (422 missing_cloud_code_project) instead of persisting them. - markAntigravityMissingCloudCodeProject disables confirmed-missing rows (isActive=false, testStatus=unavailable — recoverable, not terminal) so selection rotates to healthy siblings; a discovered projectId re-enables the account. - preferAntigravityConnectionsWithStoredProject drops empty-projectId siblings when a healthier account exists (never empties the pool).
check:file-size caps new files at 1000 LOC; the route grew to 1007 with the inline gate. Move antigravityMissingProjectRejection() + AntigravityProjectDiscoveryRejection into src/lib/oauth/antigravityProjectGate.ts (route back to 987). Call sites build the typed 422 via NextResponse.json with a satisfies check. Gate tests now read the extracted module.
rqzbeh
marked this pull request as draft
August 24, 2026 08:20
…projectId Per maintainer direction on cheaper-inference#11284: save the connection with testStatus:"degraded" + typed error markers (errorCode=missing_project_id, lastErrorType=oauth_missing_project_id) instead of rejecting the connect. The refresh token stays stored, so request-time bootstrap self-heals the row via persistDiscoveredAntigravityProjectId; confirmed-BYOP accounts are disabled on first dispatch by markAntigravityMissingCloudCodeProject. - antigravityProjectGate.ts: rejection payload -> antigravityDegradedProjectState() - route.ts exchange/poll-callback: apply degrade fields to update+create payloads, surface success:true with a warning field - connectionPersistence.ts: buildOAuthConnectionCreatePayload accepts the degrade state
rqzbeh
marked this pull request as ready for review
August 24, 2026 08:52
diegosouzapw
merged commit Aug 24, 2026
6de542b
into
cheaper-inference:release/v3.8.50
19 of 24 checks passed
diegosouzapw
added a commit
that referenced
this pull request
Aug 25, 2026
…, antigravity BYOP contract) Two unrelated real reds on the release tip: * fix(providers): flag MiniMax M3 as multimodal on the Volcengine Ark plans. d732cf6 ("feat(volcengine): add Ark plan providers") added volcengine-agent-plan/minimax-m3 and volcengine-coding-plan/minimax-m3 without supportsVision, breaking the LEDGER-4 invariant that every minimax-m3 registry entry except PromptQL (text-only upstream) is flagged multimodal. Every other provider carrying the model (opencode-zen, opencode-go, bazaarlink, ollama-cloud, codebuddy-cn, trae) sets it. Registry metadata defect, not a stale test. * test(antigravity): align the empty-projectId onboarding test to the contract shipped by #11284/#11358 (6de542b). That change made an onboardUser 200 whose body carries NO cloudaicompanionProject mean Google BYOP — no project was created and none ever will be — so it short-circuits before the retry loadCodeAssist. The older test still mocked onboardUser with the bare { done: true } BYOP shape while asserting the retry path, so it pinned a contract that was deliberately moved. The mock now returns a real onboarding-success body; every assertion is kept, and the id in the onboard body deliberately differs from the expected one so the test still proves the projectId came from the retry discovery. Refs #11284
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…d as degraded (cheaper-inference#11284) (cheaper-inference#11358) Merged via consolidated batch validation. Production evidence (VPS docker instance): Antigravity OAuth connects ending without a Cloud Code projectId were persisted as silently active while every model call failed; now persisted as degraded. Own tests pass.
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…, antigravity BYOP contract) Two unrelated real reds on the release tip: * fix(providers): flag MiniMax M3 as multimodal on the Volcengine Ark plans. 0a9cf03 ("feat(volcengine): add Ark plan providers") added volcengine-agent-plan/minimax-m3 and volcengine-coding-plan/minimax-m3 without supportsVision, breaking the LEDGER-4 invariant that every minimax-m3 registry entry except PromptQL (text-only upstream) is flagged multimodal. Every other provider carrying the model (opencode-zen, opencode-go, bazaarlink, ollama-cloud, codebuddy-cn, trae) sets it. Registry metadata defect, not a stale test. * test(antigravity): align the empty-projectId onboarding test to the contract shipped by cheaper-inference#11284/cheaper-inference#11358 (a554154). That change made an onboardUser 200 whose body carries NO cloudaicompanionProject mean Google BYOP — no project was created and none ever will be — so it short-circuits before the retry loadCodeAssist. The older test still mocked onboardUser with the bare { done: true } BYOP shape while asserting the retry path, so it pinned a contract that was deliberately moved. The mock now returns a real onboarding-success body; every assertion is kept, and the id in the onboard body deliberately differs from the expected one so the test still proves the projectId came from the retry discovery. Refs cheaper-inference#11284
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #11284, following the maintainer's suggested direction: Antigravity OAuth connects that end without a Cloud Code
projectIdare now persisted astestStatus:"degraded"instead of a silenttestStatus:"active"row that showed "Connected" while every model call failed.Root cause
Production evidence (VPS docker instance, read-only inspection): 5 of 18 stored antigravity rows had
project_id=""withproviderSpecificData.projectId=""whiletier=g1-pro-tier/subscriptionTier="Google AI Pro"were fully populated — the token exchange and loadCodeAssist round-trips succeeded, but Google returned nocloudaicompanionProject. These are Google BYOP accounts (no automatic GCP project creation for standard-tier accounts, #8491):onboardUseranswers 200 OK without creating a project. The old connect-time path swallowed that outcome (barecatch/.catch(() => {})) and persisted active-with-empty-projectId; request-time selection then excluded those rows → "No active credentials for provider: antigravity".Changes
src/lib/oauth/providers/antigravity.ts):postExchangeAntigravitynow reports why no project was found —requires_manual_project: onboardUser answered 200 withoutcloudaicompanionProjectin the body (BYOP; retrying can never succeed);discovery_failed: loadCodeAssist/onboardUser errored, timed out, or stayed empty after onboarding.A projectId present directly in the onboardUser response is used when discovery lags behind server-side project creation.
src/lib/oauth/antigravityProjectGate.ts+[action]/route.tsexchange/poll-callback +connectionPersistence.ts): the connection IS saved, but withtestStatus:"degraded",errorCode:"missing_project_id",lastErrorType:"oauth_missing_project_id"and a descriptivelastError. Both upsert branches (update-existing and create-new) apply the degrade fields. The response stayssuccess:trueand carries awarningstring so the dashboard can explain the state instead of showing a false green. No rejection, no data loss — the refresh token stays stored.persistDiscoveredAntigravityProjectId()flips the row back to active the moment a projectId is discovered at request time (transient failures recover with zero user action). Confirmed-BYOP accounts get disabled bymarkAntigravityMissingCloudCodeProject()on first dispatch (isActive:false+unavailable— recoverable, not terminal) so selection rotates to healthy siblings.open-sse/services/antigravityProjectPersist.ts): empty-projectId siblings and confirmed-missing rows (even with stale ids) are skipped when a healthier account exists. When NO account has a project, the pool passes through unchanged so the typed runtime 422 (not an empty-selection 404) explains what to fix.User-facing flow after this PR
TDD validation (Hard Rule #18)
New tests (RED→GREEN):
tests/unit/antigravity-oauth-empty-project-rejection.test.ts— outcome classification + mapTokens propagationtests/unit/oauth-route-antigravity-project-gate.test.ts— degrade gate wired into both exchange branches; saved-not-active contract; typed error fieldstests/unit/antigravity-missing-project-autodisable.test.ts— disable on confirm / re-enable on discoverytests/unit/antigravity-empty-project-selection.test.ts— selection rotation semanticsUpdated:
tests/unit/antigravity-missing-project-chat.test.ts(persisted-state assertions).Focused suites: 51/51 new+regression tests pass (run via fleet worker);
typecheck:coreexit 0;check:file-sizeOK (route 979 < cap 1000); dashboard/open-sse typecheck baselines unchanged.