mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-17 20:52:15 +03:00
* fix(antigravity): heal empty-projectId accounts via retryable auto-onboarding 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. * chore(changelog): fragment for #10424 antigravity project autocreate * feat(antigravity): BYOP fast-fail + manual GCP project-id override 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. * chore(changelog): cover BYOP fast-fail + manual override in #10424 fragment * test(antigravity): expect fast 403 GCP_PROJECT_REQUIRED when loadCodeAssist finds no project (#10424) Google now marks accounts without an onboarded project as BYOP (automatic project creation deprecated for standard-tier accounts, #2934). The PR's BYOP fast-fail path returns 403 gcp_project_required instead of the old generic 422 missing_project_id; align the #2334 executor test with that contract so CI unit-test shard 2/4 passes. * fix(antigravity): persist isProjectIdManual, fix BYOP citation, dodge refresh-retry Review follow-up on #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 '#2934' citation for the Google BYOP claim pointed at an unrelated closed issue. Swapped for the real tracking issue #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). * chore(ci): drop unused eslint-disable in EditConnectionModal form hydration 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). * fix(build): bound and retry the opencode-plugin npm install in prepublish 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. * ci(quality): use the npm-ci-retry action on every install step 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. * Merge branch 'release/v3.8.50' into fix/antigravity-project-autocreate * test(fix): refresh expired alibaba quota sample validity and onnxruntime pin for v3.8.50 base - alibaba-free-tier-quota-fetcher.test.ts: sample quotaValidityPeriod (2026-08-16 16:00 UTC) is in the past, making every quota entry classify as expired/not_capable; bump to 2028-01-01 UTC so the text/merge classification tests exercise the intended path again. - optional-transformers-dependency.test.ts: onnxruntime-node pin assertion updated from ~1.24.3 to ~1.27.0 to match package.json (bumped by #10403); the regular-not-optional intent is unchanged. * test(fix): widen modelsDevSync lastSync wait from 200ms default to 2000ms The truthy-spellings loop asserted each enabled case completes its first fetch within waitFor's 200ms default timeout, which trips under CI runner load (observed on PR 10424 shard 2/4). Match the file's other lastSync waits (2000ms) so the sync-completion assertion is load-tolerant. --------- Co-authored-by: Rouzbeh <rqzbeh@users.noreply.github.com>
61 lines
2.7 KiB
TypeScript
61 lines
2.7 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
|
|
const repoRoot = process.cwd();
|
|
|
|
function readJson<T = Record<string, unknown>>(relPath: string): T {
|
|
return JSON.parse(readFileSync(join(repoRoot, relPath), "utf8")) as T;
|
|
}
|
|
|
|
test("@huggingface/transformers is a regular dependency so npm ci never skips it", () => {
|
|
// #9962 deliberately moved @huggingface/transformers out of optionalDependencies:
|
|
// as an optional dep, npm silently skipped the whole subtree on Node 24/26 (old
|
|
// pin dragged onnxruntime-node@1.21.0 whose NAN build no longer compiles), which
|
|
// broke `npm ci`/`next build` with "Can't resolve @huggingface/transformers"
|
|
// (lazy import in src/lib/memory/embedding/transformersLocal.ts). As a regular
|
|
// dep with onnxruntime-node@~1.27.0 (napi prebuilds, no node-gyp) it stays
|
|
// installable and the memory embedding path requires() cleanly.
|
|
const pkg = readJson<{
|
|
dependencies?: Record<string, string>;
|
|
optionalDependencies?: Record<string, string>;
|
|
}>("package.json");
|
|
|
|
assert.equal(
|
|
pkg.dependencies?.["@huggingface/transformers"],
|
|
"^4.2.0",
|
|
"transformers must be a regular dependency (never optional) so npm ci cannot skip it"
|
|
);
|
|
assert.equal(pkg.optionalDependencies?.["@huggingface/transformers"], undefined);
|
|
});
|
|
|
|
test("transformers + onnxruntime-node are regular dependencies (not optional)", () => {
|
|
const pkg = readJson<{
|
|
dependencies?: Record<string, string>;
|
|
optionalDependencies?: Record<string, string>;
|
|
}>("package.json");
|
|
|
|
assert.equal(
|
|
pkg.dependencies?.["onnxruntime-node"],
|
|
"~1.27.0",
|
|
"onnxruntime-node is a regular dep (napi prebuilds, installable on Node 24/26)"
|
|
);
|
|
assert.equal(pkg.optionalDependencies?.["onnxruntime-node"], undefined);
|
|
|
|
const lock = readJson<{
|
|
packages: Record<string, { optional?: boolean; dependencies?: Record<string, string>; optionalDependencies?: Record<string, string> }>;
|
|
}>("package-lock.json");
|
|
|
|
assert.equal(
|
|
lock.packages[""]?.dependencies?.["@huggingface/transformers"],
|
|
"^4.2.0",
|
|
"root lock dependencies must hold transformers as a regular (non-optional) dep"
|
|
);
|
|
// Optional flag is only written `true` for genuinely optional packages;
|
|
// regular deps leave it absent/null. Assert each is NOT optional.
|
|
assert.ok(!lock.packages["node_modules/@huggingface/transformers"]?.optional, "transformers must not be marked optional in the lockfile");
|
|
assert.ok(!lock.packages["node_modules/onnxruntime-node"]?.optional, "onnxruntime-node must not be marked optional in the lockfile");
|
|
assert.ok(!lock.packages["node_modules/onnxruntime-common"]?.optional, "onnxruntime-common must not be marked optional in the lockfile");
|
|
});
|