fix(antigravity): heal empty-projectId accounts via retryable auto-onboarding - #10424
fix(antigravity): heal empty-projectId accounts via retryable auto-onboarding#10424rqzbeh wants to merge 19 commits into
Conversation
…boarding Accounts with an empty Cloud Code projectId get a permanent 422 "Missing Google projectId" when loadCodeAssist returns no project. The 3.8.50 bootstrap attempts to CREATE the project via onboardUser, but a single failed attempt (transient network/upstream error) was memoized forever in onboardAttemptedCache: every later request in the process skipped onboarding and 422'd, even though a retry would succeed. Replace the permanent per-token Set with a failure-backoff map: failed onboard attempts are retried after a 5-minute backoff (bounded, self-healing), the in-flight lock still dedupes concurrent calls, and success clears the failure marker and memoizes the project as before. Accounts that CAN be onboarded now heal automatically on a later request or token refresh — no user action. Tests: the existing "does not retry" case is now framed as the backoff window; a new case proves the account heals (retries onboarding and recovers the project) once the backoff expires.
Port decolua/9router#2934 + VansRouter 802a859: - tryOnboardUser now returns a three-way status; a 200 onboardUser response WITHOUT cloudaicompanionProject means Google deprecated automatic project creation for standard-tier (personal) accounts (BYOP). Such accounts are cached permanently (no pointless ~18s re-onboard) and the executor fails fast with 403 GCP_PROJECT_REQUIRED + actionable 'enter your project id' message instead of the generic 422 or a delayed 429. - Transient onboard failures keep the existing 5-min backoff heal. - Manual project-id override: the EditConnectionModal now stamps providerSpecificData.isProjectIdManual when the operator enters a project id, and tokenRefresh skips auto-discovery for flagged accounts so the manual value is never overwritten.
…Assist finds no project (diegosouzapw#10424) Google now marks accounts without an onboarded project as BYOP (automatic project creation deprecated for standard-tier accounts, diegosouzapw#2934). The PR's BYOP fast-fail path returns 403 gcp_project_required instead of the old generic 422 missing_project_id; align the diegosouzapw#2334 executor test with that contract so CI unit-test shard 2/4 passes.
…avity-project-autocreate
…avity-project-autocreate
…avity-project-autocreate
…(#project-autocreatefix/antigravity-project-autocreate)
|
Thanks for this — the failure-backoff redesign in Two things I'd like fixed before merge:
One more thing worth a look, not blocking: returning Happy to take another look once these land. |
…avity-project-autocreate
… refresh-retry Review follow-up on diegosouzapw#10424: 1. EditConnectionModal: isProjectIdManual was set on updates.providerSpecificData right after the project-id field, then the OAuth path (Antigravity is always OAuth) rebuilt providerSpecificData from connection.providerSpecificData before the request went out, discarding the flag — tokenRefresh.ts was guarding a field never actually persisted. The flag now lands in the single surviving antigravity merge, with a jsdom regression test (modeled on edit-connection-modal-openai-store-toggle). 2. The 'diegosouzapw#2934' citation for the Google BYOP claim pointed at an unrelated closed issue. Swapped for the real tracking issue diegosouzapw#8491 (empty Google projectId -> 422 class) across bootstrap/executor/test comments. 3. BYOP fast-fail now returns 422 instead of 403: chatCore's generic 401/403 -> refresh-and-retry path was hitting Google's OAuth token endpoint on every request from an affected account (pointless — refreshing cannot create a GCP project), and 422 matches the sibling missing_project_id error the client already maps to an action-needed prompt. Also: eslint-disable-next-line for the pre-existing react-hooks/set-state-in-effect baseline noise in the modal (repo convention, same pattern as 11 other dashboard files).
|
Thanks for the detailed review — all three points are addressed in commit 1. 2. Citation swapped for the real source. All 3. BYOP fast-fail no longer triggers the pointless refresh. The executor now returns 422 for One note for transparency: the commit also carries an Verified locally before pushing: 88/88 node:test (executor, missing-project-chat, discovery-bootstrap, token-refresh-service, streaming-sanitize), 5/5 vitest including the new regression test, |
|
Follow-up on the "one more thing worth a look" note from this review (the 403 → 401/403 refresh-retry interaction): the account-rotation piece is now a separate PR — #10470 (feat(antigravity): auto-rotate BYOP accounts to siblings on GCP_PROJECT_REQUIRED). Quick summary of the design decision: a It's stacked on this branch (the 422 fast-fail only exists here), so it reduces to its own delta once #10424 merges. This PR keeps the two review fixes as-is. |
…ration The react-hooks/set-state-in-effect disable added in the previous commit is unused under the repo's pinned eslint-plugin-react-hooks (7.0.1) — the rule does not fire on this line at that version, so the unused directive tripped the whole-repo 'No new ESLint warnings' gate (max-warnings 0). Verified with the lockfile-pinned plugin: lint:json is clean (0 errors, 0 warnings).
…lish The plugin's node_modules is gitignored, so every fresh CI checkout runs a full npm install inside @omniroute/opencode-plugin during build:cli. npm's unbounded fetch retries turn a stalled registry CDN connection (the recurring onnxruntime-class ETIMEDOUT flake) into a 20-30 minute hang — the DAST 'Build CLI bundle' step has been cancelled at the 30m cap repeatedly. - Bound npm fetch: --fetch-timeout 60s, 2 retries with capped backoff — a stalled connection now fails fast instead of hanging the job. - Retry the install up to 3 times with a 10s pause between attempts, so transient CDN failures recover in-build. Net effect: the step either completes (network OK) or fails quickly with a clear error (network down) — it can no longer eat the whole job budget.
Fast Quality Gates failed on the recurring onnxruntime-node postinstall ETIMEDOUT (Microsoft CDN 150.171.x.x) - the same transient flake that has hit Vitest and dast-smoke today. Only the Build job used the retry action; the other five jobs (Docs, Fast Quality Gates, Vitest, Unit Tests, changelog) still ran a bare install and die on any CDN hiccup. Use the existing retry action (3 attempts, exponential backoff) on every install step for consistency.
…avity-project-autocreate
…avity-project-autocreate
…avity-project-autocreate
…avity-project-autocreate
Summary
Accounts with an empty Google Cloud Code
projectIdfail every requestwith
422 Missing Google projectId. The 3.8.50 bootstrap already tries toauto-create the missing project via Google's
onboardUserendpoint (thenre-discovers it via
loadCodeAssist) — but a single failed attempt wasmemoized forever in
onboardAttemptedCache(a plainSet), so every laterrequest in the same process skipped onboarding and 422'd, even when a retry
would have succeeded.
This PR makes auto-onboarding retryable and self-healing:
a failed onboard attempt is retried once the 5-minute backoff expires, so a
transient failure (network blip, upstream 5xx) no longer poisons the account
for the process lifetime.
attempt at a time per token).
exactly as before (
projectCacheLRU,persistDiscoveredAntigravityProjectId).Net effect: accounts that CAN be onboarded (have a refresh token) heal
automatically on a later request or token refresh — the Google project is
created without any user action. Accounts without a refresh token still
require a one-time OAuth re-auth (Google-side limitation, cannot be fixed in
code).
Related Issues
422 Missing Google projectId ... loadCodeAssist found no Cloud Code project)Validation
npm run lint— no issues in changed filesFocused tests run:
Tests Added Or Updated
tests/unit/antigravity-discovery-bootstrap.test.ts:window" (was: "does not retry onboardUser for the same token" — behavior
within the window is unchanged, name now matches the backoff semantics)
heals itself)" — first attempt fails, backoff blocks an immediate retry,
after the backoff expires the account re-onboards and recovers the project
Coverage Notes
open-sse/services/antigravityProjectBootstrap.ts(one cache data structure + its gate/finally bookkeeping) plus the test
suite; no routing, executor, or wire-format behavior changes.
clearAntigravityProjectCache(test export) now clears the failure map too;a new test-only
clearAntigravityOnboardBackoff(key?)simulates backoffexpiry.
Reviewer Notes
ONBOARD_RETRY_BACKOFF_MS = 5 minbounds Google-side retry load: at most oneonboard attempt per token per 5 minutes, plus the existing LRU cap
(
MAX_CACHE_SIZE = 256).unchanged); this PR only changes the FAILURE path.
(fix(antigravity): classify geo-blocked egress, exclude account, real connection probe #10420): accounts whose egress location is refused still 422/400 until
egress is routed through a supported region — auto-onboarding cannot create a
working project from a blocked region.