@cortexkit/opencode-antigravity-auth 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +3 -8
  2. package/dist/cli.js +330 -83
  3. package/dist/cli.js.map +4 -4
  4. package/dist/index.js +17039 -15773
  5. package/dist/index.js.map +4 -4
  6. package/dist/src/plugin/account-command-oauth.d.ts +34 -0
  7. package/dist/src/plugin/account-command-oauth.d.ts.map +1 -0
  8. package/dist/src/plugin/account-command-oauth.js +156 -0
  9. package/dist/src/plugin/account-command-oauth.js.map +1 -0
  10. package/dist/src/plugin/auth-loader.d.ts +16 -1
  11. package/dist/src/plugin/auth-loader.d.ts.map +1 -1
  12. package/dist/src/plugin/auth-loader.js +113 -32
  13. package/dist/src/plugin/auth-loader.js.map +1 -1
  14. package/dist/src/plugin/background-quota-refresh.d.ts +146 -0
  15. package/dist/src/plugin/background-quota-refresh.d.ts.map +1 -0
  16. package/dist/src/plugin/background-quota-refresh.js +347 -0
  17. package/dist/src/plugin/background-quota-refresh.js.map +1 -0
  18. package/dist/src/plugin/command-data.d.ts +61 -8
  19. package/dist/src/plugin/command-data.d.ts.map +1 -1
  20. package/dist/src/plugin/command-data.js +231 -39
  21. package/dist/src/plugin/command-data.js.map +1 -1
  22. package/dist/src/plugin/commands.d.ts +12 -9
  23. package/dist/src/plugin/commands.d.ts.map +1 -1
  24. package/dist/src/plugin/commands.js +140 -33
  25. package/dist/src/plugin/commands.js.map +1 -1
  26. package/dist/src/plugin/config/schema.d.ts +2 -0
  27. package/dist/src/plugin/config/schema.d.ts.map +1 -1
  28. package/dist/src/plugin/config/schema.js +24 -0
  29. package/dist/src/plugin/config/schema.js.map +1 -1
  30. package/dist/src/plugin/debug.d.ts +7 -0
  31. package/dist/src/plugin/debug.d.ts.map +1 -1
  32. package/dist/src/plugin/debug.js +25 -0
  33. package/dist/src/plugin/debug.js.map +1 -1
  34. package/dist/src/plugin/fetch-interceptor.d.ts.map +1 -1
  35. package/dist/src/plugin/fetch-interceptor.js +13 -1
  36. package/dist/src/plugin/fetch-interceptor.js.map +1 -1
  37. package/dist/src/plugin/index.d.ts +7 -0
  38. package/dist/src/plugin/index.d.ts.map +1 -1
  39. package/dist/src/plugin/index.js +127 -24
  40. package/dist/src/plugin/index.js.map +1 -1
  41. package/dist/src/plugin/killswitch.d.ts.map +1 -1
  42. package/dist/src/plugin/killswitch.js +12 -9
  43. package/dist/src/plugin/killswitch.js.map +1 -1
  44. package/dist/src/plugin/oauth-methods.d.ts.map +1 -1
  45. package/dist/src/plugin/oauth-methods.js +2 -10
  46. package/dist/src/plugin/oauth-methods.js.map +1 -1
  47. package/dist/src/plugin/quota.d.ts +42 -1
  48. package/dist/src/plugin/quota.d.ts.map +1 -1
  49. package/dist/src/plugin/quota.js +185 -41
  50. package/dist/src/plugin/quota.js.map +1 -1
  51. package/dist/src/plugin/request.d.ts.map +1 -1
  52. package/dist/src/plugin/request.js +6 -2
  53. package/dist/src/plugin/request.js.map +1 -1
  54. package/dist/src/plugin/ui/auth-menu.d.ts.map +1 -1
  55. package/dist/src/plugin/ui/auth-menu.js +2 -4
  56. package/dist/src/plugin/ui/auth-menu.js.map +1 -1
  57. package/dist/src/plugin/ui/quota-status.d.ts.map +1 -1
  58. package/dist/src/plugin/ui/quota-status.js +3 -5
  59. package/dist/src/plugin/ui/quota-status.js.map +1 -1
  60. package/dist/src/sidebar-state.d.ts +126 -9
  61. package/dist/src/sidebar-state.d.ts.map +1 -1
  62. package/dist/src/sidebar-state.js +185 -25
  63. package/dist/src/sidebar-state.js.map +1 -1
  64. package/dist/src/tui/command-dialogs.js +101 -3
  65. package/dist/src/tui/command-dialogs.js.map +1 -1
  66. package/dist/src/tui.d.ts.map +1 -1
  67. package/dist/src/tui.js +55 -20
  68. package/dist/src/tui.js.map +1 -1
  69. package/package.json +6 -6
  70. package/src/plugin/command-data.ts +331 -51
  71. package/src/sidebar-state.ts +306 -32
  72. package/src/tui/command-dialogs.tsx +136 -3
  73. package/src/tui-compiled/plugin/command-data.ts +331 -51
  74. package/src/tui-compiled/sidebar-state.ts +306 -32
  75. package/src/tui-compiled/tui/command-dialogs.tsx +189 -69
  76. package/src/tui-compiled/tui.tsx +73 -30
  77. package/src/tui.tsx +82 -28
package/README.md CHANGED
@@ -116,19 +116,14 @@ The model registry lives at `packages/core/src/model-registry.ts`; the OpenCode
116
116
 
117
117
  | Model | Variants | Quota group |
118
118
  | --- | --- | --- |
119
+ | `antigravity-gemini-3.7-flash` | `low`, `high` | `gemini-flash` |
119
120
  | `antigravity-gemini-3.6-flash` | `low`, `high` | `gemini-flash` |
120
121
  | `antigravity-gemini-3.5-flash` | `low`, `high` | `gemini-flash` |
121
122
  | `antigravity-gemini-3.1-pro` | `low`, `high` | `gemini-pro` |
122
123
  | `antigravity-gemini-3.1-flash-image` | — | `gemini-flash` |
123
- | `antigravity-claude-sonnet-4-6` | — | `claude` |
124
- | `antigravity-claude-opus-4-6-thinking` | `low`, `max` | `claude` |
124
+ | `antigravity-claude-sonnet-4-6-thinking` | — | `claude` |
125
+ | `antigravity-claude-opus-4-6-thinking` | — | `claude` |
125
126
  | `antigravity-gpt-oss-120b-medium` | — | `gpt-oss` |
126
- | `gemini-2.5-flash` | — | `gemini-flash` (CLI pool) |
127
- | `gemini-2.5-pro` | — | `gemini-pro` (CLI pool) |
128
- | `gemini-3-flash-preview` | — | `gemini-flash` (CLI pool) |
129
- | `gemini-3-pro-preview` | — | `gemini-pro` (CLI pool) |
130
- | `gemini-3.1-pro-preview` | — | `gemini-pro` (CLI pool) |
131
- | `gemini-3.1-pro-preview-customtools` | — | `gemini-pro` (CLI pool) |
132
127
 
133
128
  > Gemini 3.5 Flash-Lite is not in the AGY 1.1.5 Antigravity or Gemini CLI quota catalogs, and Gemini 3.5 Flash Cyber is restricted to a limited-access CodeMender pilot — neither is exposed by this plugin.
134
129
 
package/dist/cli.js CHANGED
@@ -862,7 +862,8 @@ function calculateTokenExpiry(requestTimeMs, expiresInSeconds) {
862
862
  }
863
863
 
864
864
  // ../core/dist/fingerprint.js
865
- var AGY_CLI_VERSION = "1.1.6";
865
+ var AGY_CLI_VERSION = "1.1.13";
866
+ var AGY_CLI_CHANGE_LIST = "964361259";
866
867
  function normalizeHarnessPlatform(platform = process.platform) {
867
868
  return platform === "win32" ? "windows" : platform || "unknown";
868
869
  }
@@ -879,7 +880,8 @@ function normalizeHarnessArch(arch = process.arch) {
879
880
  function buildAntigravityHarnessUserAgent(version = AGY_CLI_VERSION, platform = process.platform, arch = process.arch, authMethod = "consumer") {
880
881
  const osType = normalizeHarnessPlatform(platform);
881
882
  const normalizedArch = normalizeHarnessArch(arch);
882
- return `antigravity/cli/${version} (aidev_client; os_type=${osType}; arch=${normalizedArch}; auth_method=${authMethod})`;
883
+ const changeList = version === AGY_CLI_VERSION ? `; cl=${AGY_CLI_CHANGE_LIST}` : "";
884
+ return `antigravity/cli/${version} (aidev_client; os_type=${osType}; arch=${normalizedArch}${changeList}; auth_method=${authMethod})`;
883
885
  }
884
886
  function buildAntigravityHarnessLoadCodeAssistUserAgent(version = AGY_CLI_VERSION) {
885
887
  return buildAntigravityHarnessUserAgent(version);
@@ -927,6 +929,16 @@ var ALL_MODEL_DEFINITIONS = {
927
929
  high: { thinkingLevel: "high" }
928
930
  }
929
931
  }),
932
+ "antigravity-gemini-3.7-flash": defineModel("antigravity-gemini-3.7-flash", {
933
+ name: "Gemini 3.7 Flash (Antigravity)",
934
+ reasoning: true,
935
+ limit: { context: 1048576, output: 65536 },
936
+ modalities: DEFAULT_MODALITIES,
937
+ variants: {
938
+ low: { thinkingLevel: "low" },
939
+ high: { thinkingLevel: "high" }
940
+ }
941
+ }),
930
942
  "antigravity-gemini-3.6-flash": defineModel("antigravity-gemini-3.6-flash", {
931
943
  name: "Gemini 3.6 Flash (Antigravity)",
932
944
  reasoning: true,
@@ -1049,6 +1061,9 @@ var RESOLVER_ALIASES = {
1049
1061
  "gemini-3.6-flash-low": "gemini-3.6-flash",
1050
1062
  "gemini-3.6-flash-medium": "gemini-3.6-flash",
1051
1063
  "gemini-3.6-flash-high": "gemini-3.6-flash",
1064
+ "gemini-3.7-flash-low": "gemini-3.7-flash",
1065
+ "gemini-3.7-flash-medium": "gemini-3.7-flash",
1066
+ "gemini-3.7-flash-high": "gemini-3.7-flash",
1052
1067
  "gemini-claude-opus-4-6-thinking-low": "claude-opus-4-6-thinking",
1053
1068
  "gemini-claude-opus-4-6-thinking-medium": "claude-opus-4-6-thinking",
1054
1069
  "gemini-claude-opus-4-6-thinking-high": "claude-opus-4-6-thinking",
@@ -1063,27 +1078,32 @@ var RESOLVER_ALIASES = {
1063
1078
  "gpt-oss-120b": "gpt-oss-120b-medium"
1064
1079
  };
1065
1080
  var QUOTA_GROUP_BY_MODEL_ID = {
1066
- "claude-opus-4-6-thinking": "claude",
1067
- "claude-opus-4-6": "claude",
1068
- "claude-sonnet-4-6-thinking": "claude",
1069
- "claude-sonnet-4-6": "claude",
1070
- "gemini-pro-agent": "gemini-pro",
1071
- "gemini-3.1-pro": "gemini-pro",
1072
- "gemini-3.1-pro-low": "gemini-pro",
1073
- "gemini-3.1-pro-high": "gemini-pro",
1074
- "gemini-3-flash": "gemini-flash",
1075
- "gemini-3-flash-agent": "gemini-flash",
1076
- "gemini-3.5-flash-low": "gemini-flash",
1077
- "gemini-3.5-flash-extra-low": "gemini-flash",
1078
- "gemini-3.6-flash-low": "gemini-flash",
1079
- "gemini-3.6-flash-medium": "gemini-flash",
1080
- "gemini-3.6-flash-high": "gemini-flash",
1081
- "gemini-3.6-flash-tiered": "gemini-flash",
1082
- "gemini-3.1-flash-image": "gemini-flash",
1083
- "gpt-oss-120b": "gpt-oss",
1084
- "gpt-oss-120b-medium": "gpt-oss"
1081
+ "claude-opus-4-6-thinking": "non-gemini",
1082
+ "claude-opus-4-6": "non-gemini",
1083
+ "claude-sonnet-4-6-thinking": "non-gemini",
1084
+ "claude-sonnet-4-6": "non-gemini",
1085
+ "gemini-pro-agent": "gemini",
1086
+ "gemini-3.1-pro": "gemini",
1087
+ "gemini-3.1-pro-low": "gemini",
1088
+ "gemini-3.1-pro-high": "gemini",
1089
+ "gemini-3-flash": "gemini",
1090
+ "gemini-3-flash-agent": "gemini",
1091
+ "gemini-3.5-flash-low": "gemini",
1092
+ "gemini-3.5-flash-extra-low": "gemini",
1093
+ "gemini-3.6-flash-low": "gemini",
1094
+ "gemini-3.6-flash-medium": "gemini",
1095
+ "gemini-3.6-flash-high": "gemini",
1096
+ "gemini-3.6-flash-tiered": "gemini",
1097
+ "gemini-3.7-flash-low": "gemini",
1098
+ "gemini-3.7-flash-medium": "gemini",
1099
+ "gemini-3.7-flash-high": "gemini",
1100
+ "gemini-3.7-flash-tiered": "gemini",
1101
+ "gemini-3.1-flash-image": "gemini",
1102
+ "gpt-oss-120b": "non-gemini",
1103
+ "gpt-oss-120b-medium": "non-gemini"
1085
1104
  };
1086
1105
  var ANTIGRAVITY_OPENCODE_MODEL_IDS = [
1106
+ "antigravity-gemini-3.7-flash",
1087
1107
  "antigravity-gemini-3.6-flash",
1088
1108
  "antigravity-gemini-3.5-flash",
1089
1109
  "antigravity-gemini-3.1-pro",
@@ -1100,20 +1120,13 @@ function getResolverAliasMap() {
1100
1120
  return RESOLVER_ALIASES;
1101
1121
  }
1102
1122
  function getQuotaGroupForModel(modelId) {
1103
- return QUOTA_GROUP_BY_MODEL_ID[modelId.toLowerCase()];
1104
- }
1105
-
1106
- // ../core/dist/transform/model-resolver.js
1107
- var MODEL_ALIASES = getResolverAliasMap();
1108
- function getModelFamily(model) {
1109
- const lower = model.toLowerCase();
1110
- if (lower.includes("claude")) {
1111
- return "claude";
1112
- }
1113
- if (lower.includes("flash")) {
1114
- return "gemini-flash";
1115
- }
1116
- return "gemini-pro";
1123
+ const normalized = modelId.toLowerCase();
1124
+ return QUOTA_GROUP_BY_MODEL_ID[normalized] ?? // Check Claude / GPT-OSS substrings BEFORE the `gemini` substring so
1125
+ // a `gemini-claude-*` alias (which is a Claude route exposed under
1126
+ // a `gemini-` namespace) attributes to the non-gemini pool rather
1127
+ // than the gemini pool. Substring matching is required because the
1128
+ // alias IDs start with `gemini-` but contain `claude`.
1129
+ (normalized.includes("claude") || normalized.includes("gpt-oss") ? "non-gemini" : normalized.startsWith("gemini") || normalized.startsWith("tab_") ? "gemini" : void 0);
1117
1130
  }
1118
1131
 
1119
1132
  // ../core/dist/account-manager.js
@@ -1946,7 +1959,7 @@ async function ensureProjectContext(auth) {
1946
1959
  const effectiveProjectId = parts.projectId || fallbackProjectId;
1947
1960
  return { auth, effectiveProjectId };
1948
1961
  }
1949
- const persistManagedProject = async (managedProjectId) => {
1962
+ const persistManagedProject = async (managedProjectId, capturedTier) => {
1950
1963
  const updatedAuth = {
1951
1964
  ...auth,
1952
1965
  refresh: formatRefreshParts({
@@ -1955,12 +1968,23 @@ async function ensureProjectContext(auth) {
1955
1968
  managedProjectId
1956
1969
  })
1957
1970
  };
1958
- return { auth: updatedAuth, effectiveProjectId: managedProjectId };
1971
+ return {
1972
+ auth: updatedAuth,
1973
+ effectiveProjectId: managedProjectId,
1974
+ capturedTier
1975
+ };
1959
1976
  };
1960
1977
  const loadPayload = await loadManagedProject(accessToken, parts.projectId ?? fallbackProjectId);
1978
+ const capturedTierId = loadPayload?.currentTier?.id;
1979
+ const paidTierId = typeof loadPayload?.paidTier === "string" ? loadPayload.paidTier : loadPayload?.paidTier?.id;
1980
+ const tierFromPayload = capturedTierId ? {
1981
+ id: capturedTierId,
1982
+ ...paidTierId ? { paidId: paidTierId } : {},
1983
+ capturedAt: Date.now()
1984
+ } : void 0;
1961
1985
  const resolvedManagedProjectId = extractManagedProjectId(loadPayload);
1962
1986
  if (resolvedManagedProjectId) {
1963
- return persistManagedProject(resolvedManagedProjectId);
1987
+ return persistManagedProject(resolvedManagedProjectId, tierFromPayload);
1964
1988
  }
1965
1989
  const tierId = getDefaultTierId(loadPayload?.allowedTiers) ?? "free-tier";
1966
1990
  log3.debug("Auto-provisioning managed project", {
@@ -1972,7 +1996,7 @@ async function ensureProjectContext(auth) {
1972
1996
  log3.debug("Successfully provisioned managed project", {
1973
1997
  provisionedProjectId
1974
1998
  });
1975
- return persistManagedProject(provisionedProjectId);
1999
+ return persistManagedProject(provisionedProjectId, tierFromPayload);
1976
2000
  }
1977
2001
  log3.warn("Failed to provision managed project - account may not work correctly", {
1978
2002
  hasProjectId: !!parts.projectId
@@ -1981,9 +2005,17 @@ async function ensureProjectContext(auth) {
1981
2005
  provisionFailedKeys.add(cacheKey);
1982
2006
  }
1983
2007
  if (parts.projectId) {
1984
- return { auth, effectiveProjectId: parts.projectId };
2008
+ return {
2009
+ auth,
2010
+ effectiveProjectId: parts.projectId,
2011
+ capturedTier: tierFromPayload
2012
+ };
1985
2013
  }
1986
- return { auth, effectiveProjectId: fallbackProjectId };
2014
+ return {
2015
+ auth,
2016
+ effectiveProjectId: fallbackProjectId,
2017
+ capturedTier: tierFromPayload
2018
+ };
1987
2019
  };
1988
2020
  if (!cacheKey) {
1989
2021
  return resolveContext();
@@ -2225,15 +2257,13 @@ function classifyQuotaGroup(modelName, displayName) {
2225
2257
  return registryGroup;
2226
2258
  }
2227
2259
  const combined = `${modelName} ${displayName ?? ""}`.toLowerCase();
2228
- if (combined.includes("claude")) {
2229
- return "claude";
2260
+ if (combined.includes("claude") || combined.includes("gpt-oss")) {
2261
+ return "non-gemini";
2230
2262
  }
2231
- const isGemini3 = combined.includes("gemini-3") || combined.includes("gemini 3");
2232
- if (!isGemini3) {
2233
- return null;
2263
+ if (combined.includes("gemini")) {
2264
+ return "gemini";
2234
2265
  }
2235
- const family = getModelFamily(modelName);
2236
- return family === "gemini-flash" ? "gemini-flash" : "gemini-pro";
2266
+ return null;
2237
2267
  }
2238
2268
  function normalizeRemainingFraction(value) {
2239
2269
  if (typeof value !== "number" || !Number.isFinite(value)) {
@@ -2301,6 +2331,147 @@ function aggregateQuota(models) {
2301
2331
  perModel.sort((a, b) => a.modelId.localeCompare(b.modelId));
2302
2332
  return { groups, perModel, modelCount: totalCount };
2303
2333
  }
2334
+ function mostConstrainedWindow(windows) {
2335
+ if (windows.length === 0)
2336
+ return void 0;
2337
+ let best = windows[0];
2338
+ for (let i = 1; i < windows.length; i++) {
2339
+ if (windows[i].remainingFraction < best.remainingFraction) {
2340
+ best = windows[i];
2341
+ }
2342
+ }
2343
+ return {
2344
+ remainingFraction: best.remainingFraction,
2345
+ resetTime: best.resetTime
2346
+ };
2347
+ }
2348
+ function poolForBucketId(bucketId) {
2349
+ if (bucketId.startsWith("gemini-"))
2350
+ return "gemini";
2351
+ if (bucketId.startsWith("3p-"))
2352
+ return "non-gemini";
2353
+ return null;
2354
+ }
2355
+ function parseDescriptionModelCount(description) {
2356
+ const prefixMatch = description.match(/^[^:]+:\s*/);
2357
+ const payload = prefixMatch ? description.slice(prefixMatch[0].length) : description;
2358
+ if (!payload)
2359
+ return 0;
2360
+ const entries = payload.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
2361
+ return entries.length;
2362
+ }
2363
+ function windowDurationMs(window) {
2364
+ switch (window) {
2365
+ case "5h":
2366
+ return 5 * 60 * 60 * 1e3;
2367
+ case "weekly":
2368
+ return 7 * 24 * 60 * 60 * 1e3;
2369
+ default:
2370
+ return Number.MAX_SAFE_INTEGER;
2371
+ }
2372
+ }
2373
+ function aggregateQuotaSummary(response) {
2374
+ const groups = {};
2375
+ let totalCount = 0;
2376
+ for (const group of response.groups) {
2377
+ const windows = [];
2378
+ for (const bucket of group.buckets) {
2379
+ const pool2 = poolForBucketId(bucket.bucketId);
2380
+ if (!pool2)
2381
+ continue;
2382
+ windows.push({
2383
+ window: bucket.window,
2384
+ remainingFraction: normalizeRemainingFraction(bucket.remainingFraction),
2385
+ resetTime: bucket.resetTime
2386
+ });
2387
+ }
2388
+ if (windows.length === 0)
2389
+ continue;
2390
+ windows.sort((a, b) => windowDurationMs(a.window) - windowDurationMs(b.window));
2391
+ const constrained = mostConstrainedWindow(windows);
2392
+ const recognizedBucket = group.buckets.find((bucket) => poolForBucketId(bucket.bucketId));
2393
+ if (!recognizedBucket)
2394
+ continue;
2395
+ const pool = poolForBucketId(recognizedBucket.bucketId);
2396
+ if (!pool || !constrained)
2397
+ continue;
2398
+ const modelCount = group.description ? parseDescriptionModelCount(group.description) : 0;
2399
+ groups[pool] = {
2400
+ remainingFraction: constrained.remainingFraction,
2401
+ resetTime: constrained.resetTime,
2402
+ modelCount,
2403
+ windows
2404
+ };
2405
+ totalCount += modelCount;
2406
+ }
2407
+ return { groups, modelCount: totalCount };
2408
+ }
2409
+ async function fetchQuotaSummary(options) {
2410
+ const timeoutMs = options.timeoutMs ?? QUOTA_MANAGER_DEFAULT_TIMEOUT_MS;
2411
+ const userAgent = options.userAgent ?? buildAntigravityHarnessUserAgent();
2412
+ const transport = options.fetchVia ?? defaultTransport;
2413
+ const errors = [];
2414
+ if (options.endpoints.length === 0) {
2415
+ throw new Error("No endpoints configured for fetchQuotaSummary");
2416
+ }
2417
+ const tryBody = async (endpoint, projectId) => {
2418
+ const body = { project: projectId };
2419
+ try {
2420
+ const response = await transport(`${endpoint}/v1internal:retrieveUserQuotaSummary`, {
2421
+ method: "POST",
2422
+ headers: {
2423
+ "User-Agent": userAgent,
2424
+ Authorization: `Bearer ${options.accessToken}`,
2425
+ "Content-Type": "application/json",
2426
+ "Accept-Encoding": "gzip"
2427
+ },
2428
+ body: JSON.stringify(body)
2429
+ }, { timeoutMs });
2430
+ if (response.ok) {
2431
+ return {
2432
+ ok: true,
2433
+ summary: await response.json()
2434
+ };
2435
+ }
2436
+ const status = response.status;
2437
+ if (status === 403) {
2438
+ errors.push(`retrieveUserQuotaSummary 403 at ${endpoint} (project=${projectId.slice(0, 12)}\u2026)`);
2439
+ return { ok: false, reason: "403" };
2440
+ }
2441
+ if (status === 429 || status >= 500) {
2442
+ const message2 = await response.text().catch(() => "");
2443
+ errors.push(`retrieveUserQuotaSummary ${status} at ${endpoint}${message2 ? `: ${message2.trim().slice(0, 200)}` : ""}`);
2444
+ return { ok: false, reason: "transient" };
2445
+ }
2446
+ const message = await response.text().catch(() => "");
2447
+ errors.push(`retrieveUserQuotaSummary ${status} at ${endpoint}${message ? `: ${message.trim().slice(0, 200)}` : ""}`);
2448
+ return { ok: false, reason: "transient" };
2449
+ } catch (error) {
2450
+ errors.push(`retrieveUserQuotaSummary network error at ${endpoint}: ${error instanceof Error ? error.message : String(error)}`);
2451
+ return { ok: false, reason: "transient" };
2452
+ }
2453
+ };
2454
+ const primary = options.managedProjectId ?? options.projectId;
2455
+ let primaryGot403 = false;
2456
+ if (primary) {
2457
+ for (const endpoint of options.endpoints) {
2458
+ const result = await tryBody(endpoint, primary);
2459
+ if (result.ok)
2460
+ return { summary: result.summary };
2461
+ if (result.reason === "403")
2462
+ primaryGot403 = true;
2463
+ }
2464
+ }
2465
+ const fallbackId = primaryGot403 && options.managedProjectId && options.projectId && options.managedProjectId !== options.projectId ? options.projectId : void 0;
2466
+ if (fallbackId) {
2467
+ for (const endpoint of options.endpoints) {
2468
+ const result = await tryBody(endpoint, fallbackId);
2469
+ if (result.ok)
2470
+ return { summary: result.summary };
2471
+ }
2472
+ }
2473
+ throw new Error(errors.join("; ") || "fetchQuotaSummary failed: no project ID available");
2474
+ }
2304
2475
  function aggregateGeminiCliQuota(response) {
2305
2476
  const models = [];
2306
2477
  if (!response.buckets || response.buckets.length === 0) {
@@ -2383,10 +2554,12 @@ async function fetchAvailableModels(options) {
2383
2554
  async function fetchGeminiCliQuota(options) {
2384
2555
  const timeoutMs = options.timeoutMs ?? QUOTA_MANAGER_DEFAULT_TIMEOUT_MS;
2385
2556
  const userAgent = options.userAgent ?? buildAntigravityHarnessUserAgent();
2557
+ const transport = options.fetchVia ?? defaultTransport;
2558
+ const errors = [];
2386
2559
  for (const endpoint of options.endpoints) {
2387
2560
  const body = options.projectId ? { project: options.projectId } : {};
2388
2561
  try {
2389
- const response = await defaultTransport(`${endpoint}/v1internal:retrieveUserQuota`, {
2562
+ const response = await transport(`${endpoint}/v1internal:retrieveUserQuota`, {
2390
2563
  method: "POST",
2391
2564
  headers: {
2392
2565
  Authorization: `Bearer ${options.accessToken}`,
@@ -2400,18 +2573,26 @@ async function fetchGeminiCliQuota(options) {
2400
2573
  }
2401
2574
  const status = response.status;
2402
2575
  if (status === 429 || status >= 500) {
2576
+ errors.push(`fetchGeminiCliQuota ${status} at ${endpoint}`);
2403
2577
  continue;
2404
2578
  }
2405
2579
  return { buckets: [] };
2406
- } catch {
2580
+ } catch (error) {
2581
+ errors.push(error instanceof Error ? error.message : String(error));
2407
2582
  }
2408
2583
  }
2584
+ if (errors.length > 0) {
2585
+ throw new Error(errors.join("; ") || "fetchGeminiCliQuota failed");
2586
+ }
2409
2587
  return { buckets: [] };
2410
2588
  }
2411
2589
  async function defaultTransport(url, init, options) {
2412
2590
  return fetchWithActiveTimeout(url, init, { timeoutMs: options.timeoutMs });
2413
2591
  }
2414
2592
 
2593
+ // ../core/dist/transform/model-resolver.js
2594
+ var MODEL_ALIASES = getResolverAliasMap();
2595
+
2415
2596
  // src/plugin/oauth-login.ts
2416
2597
  function expectedState(authorizationUrl) {
2417
2598
  try {
@@ -3127,6 +3308,32 @@ async function checkAccountsQuotaStandalone(accounts, options) {
3127
3308
  makeFetchAccountQuota(void 0, ANTIGRAVITY_PROVIDER_ID)
3128
3309
  );
3129
3310
  }
3311
+ async function fetchLegacyModelsFallback(options) {
3312
+ try {
3313
+ const modelsResponse = await fetchAvailableModels({
3314
+ accessToken: options.accessToken,
3315
+ projectId: options.projectId,
3316
+ endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
3317
+ userAgent: buildAntigravityHarnessUserAgent(),
3318
+ timeoutMs: 1e4,
3319
+ ...options.fetchVia ? { fetchVia: options.fetchVia } : {}
3320
+ });
3321
+ if (modelsResponse.models) {
3322
+ return aggregateQuota(modelsResponse.models);
3323
+ }
3324
+ return {
3325
+ groups: {},
3326
+ modelCount: 0,
3327
+ error: "Failed to fetch Antigravity quota (legacy fallback)"
3328
+ };
3329
+ } catch {
3330
+ return {
3331
+ groups: {},
3332
+ modelCount: 0,
3333
+ error: "Failed to fetch Antigravity quota"
3334
+ };
3335
+ }
3336
+ }
3130
3337
  function makeFetchAccountQuota(client, providerId, fetchVia) {
3131
3338
  return async (account, signal) => {
3132
3339
  const index = 0;
@@ -3166,49 +3373,79 @@ function makeFetchAccountQuota(client, providerId, fetchVia) {
3166
3373
  }
3167
3374
  const projectContext = await ensureProjectContext(auth);
3168
3375
  auth = projectContext.auth;
3169
- const updatedAccount = applyAccountUpdates(account, auth);
3376
+ const updatedAccount = applyAccountUpdates(
3377
+ account,
3378
+ auth,
3379
+ projectContext.capturedTier
3380
+ );
3170
3381
  if (rotatedRefresh && client) {
3171
3382
  await persistRotatedRefresh(client, providerId, auth).catch(() => {
3172
3383
  });
3173
3384
  }
3174
- const [antigravityResponse, geminiCliResponse] = await Promise.all([
3175
- fetchAvailableModels({
3176
- accessToken: auth.access ?? "",
3177
- projectId: projectContext.effectiveProjectId,
3178
- endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
3179
- userAgent: buildAntigravityHarnessUserAgent(),
3180
- timeoutMs: 1e4,
3181
- ...fetchVia ? { fetchVia } : {}
3182
- }).catch(() => ({ models: void 0 })),
3183
- fetchGeminiCliQuota({
3184
- accessToken: auth.access ?? "",
3185
- projectId: projectContext.effectiveProjectId,
3186
- endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
3187
- userAgent: buildGeminiCliUserAgent(),
3188
- timeoutMs: 1e4,
3189
- ...fetchVia ? { fetchVia } : {}
3190
- })
3191
- ]);
3192
3385
  let quotaResult;
3193
- if (antigravityResponse.models === void 0) {
3194
- quotaResult = {
3195
- groups: {},
3196
- modelCount: 0,
3197
- error: "Failed to fetch Antigravity quota"
3198
- };
3199
- } else {
3200
- quotaResult = aggregateQuota(antigravityResponse.models);
3201
- }
3386
+ let fellBackToLegacy = false;
3387
+ const authParts = parseRefreshParts(auth.refresh);
3388
+ const managedProjectId = authParts.managedProjectId ?? account.managedProjectId;
3389
+ const fetchSummaryPayload = (async () => {
3390
+ try {
3391
+ const summaryResult = await fetchQuotaSummary({
3392
+ accessToken: auth.access ?? "",
3393
+ managedProjectId,
3394
+ projectId: projectContext.effectiveProjectId,
3395
+ endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
3396
+ userAgent: buildAntigravityHarnessUserAgent(),
3397
+ timeoutMs: 1e4,
3398
+ ...fetchVia ? { fetchVia } : {}
3399
+ });
3400
+ return {
3401
+ result: aggregateQuotaSummary(summaryResult.summary),
3402
+ fellBackToLegacy: summaryResult.fellBackToLegacy ?? false
3403
+ };
3404
+ } catch {
3405
+ return {
3406
+ result: await fetchLegacyModelsFallback({
3407
+ accessToken: auth.access ?? "",
3408
+ projectId: projectContext.effectiveProjectId,
3409
+ fetchVia
3410
+ }),
3411
+ fellBackToLegacy: true
3412
+ };
3413
+ }
3414
+ })();
3415
+ let geminiCliFetchError;
3416
+ const fetchGeminiCliPayload = fetchGeminiCliQuota({
3417
+ accessToken: auth.access ?? "",
3418
+ projectId: projectContext.effectiveProjectId,
3419
+ endpoints: ANTIGRAVITY_ENDPOINT_FALLBACKS,
3420
+ userAgent: buildGeminiCliUserAgent(),
3421
+ timeoutMs: 1e4,
3422
+ ...fetchVia ? { fetchVia } : {}
3423
+ }).catch((error) => {
3424
+ geminiCliFetchError = error instanceof Error ? error.message : String(error);
3425
+ log7.debug("fetchGeminiCliQuota failed", { error: geminiCliFetchError });
3426
+ return { buckets: void 0 };
3427
+ });
3428
+ const [summary, geminiCliResponse] = await Promise.all([
3429
+ fetchSummaryPayload,
3430
+ fetchGeminiCliPayload
3431
+ ]);
3432
+ quotaResult = summary.result;
3433
+ fellBackToLegacy = summary.fellBackToLegacy;
3202
3434
  const geminiCliQuotaResult = aggregateGeminiCliQuota(geminiCliResponse);
3203
3435
  const annotated = geminiCliResponse.buckets === void 0 || geminiCliResponse.buckets.length === 0 ? {
3204
3436
  ...geminiCliQuotaResult,
3205
- error: geminiCliQuotaResult.models.length === 0 ? "No Gemini CLI quota available" : void 0
3437
+ error: (
3438
+ // A real fetch exception is a transient failure, not a
3439
+ // "no CLI configured" scenario — propagate the actual message.
3440
+ geminiCliFetchError ?? (geminiCliQuotaResult.models.length === 0 ? "No Gemini CLI quota available" : void 0)
3441
+ )
3206
3442
  } : geminiCliQuotaResult;
3207
3443
  for (const [family, groupQuota] of Object.entries(quotaResult.groups)) {
3208
3444
  const remainingPercent = (groupQuota.remainingFraction ?? 0) * 100;
3209
3445
  logQuotaStatus(account.email, index, remainingPercent, family);
3210
3446
  }
3211
- logQuotaFetch("complete", 1, "ok=1 errors=0");
3447
+ const legacyTag = fellBackToLegacy ? " legacy=1" : "";
3448
+ logQuotaFetch("complete", 1, `ok=1 errors=0${legacyTag}`);
3212
3449
  return {
3213
3450
  index,
3214
3451
  email: account.email,
@@ -3246,7 +3483,7 @@ function buildAuthFromAccount(account) {
3246
3483
  expires: void 0
3247
3484
  };
3248
3485
  }
3249
- function applyAccountUpdates(account, auth) {
3486
+ function applyAccountUpdates(account, auth, capturedTier) {
3250
3487
  const parts = parseRefreshParts(auth.refresh);
3251
3488
  if (!parts.refreshToken) {
3252
3489
  return void 0;
@@ -3255,9 +3492,19 @@ function applyAccountUpdates(account, auth) {
3255
3492
  ...account,
3256
3493
  refreshToken: parts.refreshToken,
3257
3494
  projectId: parts.projectId ?? account.projectId,
3258
- managedProjectId: parts.managedProjectId ?? account.managedProjectId
3495
+ managedProjectId: parts.managedProjectId ?? account.managedProjectId,
3496
+ // Persist the captured tier alongside the project-context write. Only
3497
+ // present when the loadCodeAssist payload returned a non-empty currentTier.id.
3498
+ ...capturedTier ? {
3499
+ capturedTierId: capturedTier.id,
3500
+ ...capturedTier.paidId !== void 0 ? { capturedPaidTierId: capturedTier.paidId } : {},
3501
+ capturedTierAt: capturedTier.capturedAt
3502
+ } : {}
3259
3503
  };
3260
- const changed = updated.refreshToken !== account.refreshToken || updated.projectId !== account.projectId || updated.managedProjectId !== account.managedProjectId;
3504
+ const changed = updated.refreshToken !== account.refreshToken || updated.projectId !== account.projectId || updated.managedProjectId !== account.managedProjectId || updated.capturedTierId !== account.capturedTierId || updated.capturedPaidTierId !== account.capturedPaidTierId || // capturedAt represents when the tier was LAST CONFIRMED, not when it
3505
+ // changed -- always update it on a successful observation so consumers
3506
+ // can gate staleness on that timestamp even when the id stays the same.
3507
+ capturedTier !== void 0 && updated.capturedTierAt !== account.capturedTierAt;
3261
3508
  return changed ? updated : void 0;
3262
3509
  }
3263
3510
  async function persistRotatedRefresh(client, providerId, auth) {