@expiren/opencode-antigravity-auth 1.6.31 → 1.6.33

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.
package/dist/index.js CHANGED
@@ -1825,20 +1825,45 @@ function buildModelBreakdown(accounts) {
1825
1825
  let maxResetMs;
1826
1826
  for (const acc of accounts) {
1827
1827
  if (acc.enabled === false) continue;
1828
- const group = acc.cachedQuota?.[key];
1829
- if (!group || typeof group.remainingFraction !== "number") continue;
1830
- if (group.remainingFraction <= 0) {
1831
- const resetMs = parseResetTimeToMs2(group.resetTime);
1832
- if (resetMs !== null && resetMs > 0) {
1833
- exhaustedCount++;
1834
- if (maxResetMs === void 0 || resetMs > maxResetMs) {
1835
- maxResetMs = resetMs;
1828
+ if (acc.cachedPerModelQuota && acc.cachedPerModelQuota.length > 0) {
1829
+ const modelsInGroup = acc.cachedPerModelQuota.filter((m) => m.group === key);
1830
+ if (modelsInGroup.length === 0) continue;
1831
+ const allExhausted = modelsInGroup.every((m) => m.remainingFraction <= 0);
1832
+ if (allExhausted) {
1833
+ const freshExhausted = modelsInGroup.some((m) => {
1834
+ const resetMs = parseResetTimeToMs2(m.resetTime);
1835
+ return resetMs !== null && resetMs > 0;
1836
+ });
1837
+ if (freshExhausted) {
1838
+ exhaustedCount++;
1839
+ for (const m of modelsInGroup) {
1840
+ const resetMs = parseResetTimeToMs2(m.resetTime);
1841
+ if (resetMs !== null && resetMs > 0 && (maxResetMs === void 0 || resetMs > maxResetMs)) {
1842
+ maxResetMs = resetMs;
1843
+ }
1844
+ }
1845
+ } else {
1846
+ availableCount++;
1836
1847
  }
1837
1848
  } else {
1838
1849
  availableCount++;
1839
1850
  }
1840
1851
  } else {
1841
- availableCount++;
1852
+ const group = acc.cachedQuota?.[key];
1853
+ if (!group || typeof group.remainingFraction !== "number") continue;
1854
+ if (group.remainingFraction <= 0) {
1855
+ const resetMs = parseResetTimeToMs2(group.resetTime);
1856
+ if (resetMs !== null && resetMs > 0) {
1857
+ exhaustedCount++;
1858
+ if (maxResetMs === void 0 || resetMs > maxResetMs) {
1859
+ maxResetMs = resetMs;
1860
+ }
1861
+ } else {
1862
+ availableCount++;
1863
+ }
1864
+ } else {
1865
+ availableCount++;
1866
+ }
1842
1867
  }
1843
1868
  }
1844
1869
  if (exhaustedCount > 0 || availableCount > 0) {
@@ -2370,6 +2395,7 @@ async function promptLoginMode(existingAccounts) {
2370
2395
  cooldownMs: acc.cooldownMs,
2371
2396
  cooldownReason: acc.cooldownReason,
2372
2397
  cachedQuota: acc.cachedQuota,
2398
+ cachedPerModelQuota: acc.cachedPerModelQuota,
2373
2399
  fingerprintHistory: acc.fingerprintHistory
2374
2400
  }));
2375
2401
  console.log("");
@@ -9063,6 +9089,7 @@ var AccountManager = class _AccountManager {
9063
9089
  fingerprintHistory: acc.fingerprintHistory ?? [],
9064
9090
  cachedQuota: acc.cachedQuota,
9065
9091
  cachedQuotaUpdatedAt: acc.cachedQuotaUpdatedAt,
9092
+ dailyRequestCounts: acc.dailyRequestCounts,
9066
9093
  verificationRequired: acc.verificationRequired,
9067
9094
  verificationRequiredAt: acc.verificationRequiredAt,
9068
9095
  verificationRequiredReason: acc.verificationRequiredReason,
@@ -9553,6 +9580,7 @@ var AccountManager = class _AccountManager {
9553
9580
  fingerprintHistory: a.fingerprintHistory?.length ? a.fingerprintHistory : void 0,
9554
9581
  cachedQuota: a.cachedQuota && Object.keys(a.cachedQuota).length > 0 ? a.cachedQuota : void 0,
9555
9582
  cachedQuotaUpdatedAt: a.cachedQuotaUpdatedAt,
9583
+ dailyRequestCounts: a.dailyRequestCounts,
9556
9584
  verificationRequired: a.verificationRequired,
9557
9585
  verificationRequiredAt: a.verificationRequiredAt,
9558
9586
  verificationRequiredReason: a.verificationRequiredReason,
@@ -9675,6 +9703,58 @@ var AccountManager = class _AccountManager {
9675
9703
  account.cachedQuotaUpdatedAt = nowMs();
9676
9704
  }
9677
9705
  }
9706
+ /**
9707
+ * Record a successful API request for an account.
9708
+ * Tracks per model family with daily reset.
9709
+ */
9710
+ recordRequest(accountIndex, family) {
9711
+ const account = this.accounts[accountIndex];
9712
+ if (!account) return;
9713
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
9714
+ if (!account.dailyRequestCounts || account.dailyRequestCounts.date !== today) {
9715
+ account.dailyRequestCounts = { date: today, claude: 0, gemini: 0 };
9716
+ }
9717
+ account.dailyRequestCounts[family]++;
9718
+ account.lastUsed = nowMs();
9719
+ }
9720
+ /**
9721
+ * Get request counts for an account for today.
9722
+ */
9723
+ getDailyRequestCounts(accountIndex) {
9724
+ const account = this.accounts[accountIndex];
9725
+ if (!account?.dailyRequestCounts) return null;
9726
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
9727
+ if (account.dailyRequestCounts.date !== today) return null;
9728
+ return { ...account.dailyRequestCounts };
9729
+ }
9730
+ /**
9731
+ * Get total daily request counts across all accounts for a model family.
9732
+ */
9733
+ getTotalDailyRequests(family) {
9734
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
9735
+ let total = 0;
9736
+ for (const account of this.accounts) {
9737
+ if (account.dailyRequestCounts?.date === today) {
9738
+ total += account.dailyRequestCounts[family];
9739
+ }
9740
+ }
9741
+ return total;
9742
+ }
9743
+ /**
9744
+ * Get a summary of daily request distribution across accounts.
9745
+ * Returns accounts sorted by request count (descending).
9746
+ */
9747
+ getDailyRequestSummary(family) {
9748
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
9749
+ const result = [];
9750
+ for (const account of this.accounts) {
9751
+ const count = account.dailyRequestCounts?.date === today ? account.dailyRequestCounts[family] : 0;
9752
+ if (count > 0) {
9753
+ result.push({ index: account.index, email: account.email, count });
9754
+ }
9755
+ }
9756
+ return result.sort((a, b) => b.count - a.count);
9757
+ }
9678
9758
  isAccountOverSoftQuota(account, family, thresholdPercent, cacheTtlMs, model) {
9679
9759
  return isOverSoftQuotaThreshold(account, family, thresholdPercent, cacheTtlMs, model);
9680
9760
  }
@@ -10394,20 +10474,28 @@ function classifyQuotaGroup(modelName, displayName) {
10394
10474
  }
10395
10475
  function aggregateQuota(models) {
10396
10476
  const groups = {};
10477
+ const perModel = [];
10397
10478
  if (!models) {
10398
- return { groups, modelCount: 0 };
10479
+ return { groups, perModel, modelCount: 0 };
10399
10480
  }
10400
10481
  let totalCount = 0;
10401
10482
  for (const [modelName, entry] of Object.entries(models)) {
10402
10483
  const group = classifyQuotaGroup(modelName, entry.displayName ?? entry.modelName);
10403
- if (!group) {
10404
- continue;
10405
- }
10406
10484
  const quotaInfo = entry.quotaInfo;
10407
10485
  const remainingFraction = quotaInfo ? normalizeRemainingFraction(quotaInfo.remainingFraction) : void 0;
10408
10486
  const resetTime = quotaInfo?.resetTime;
10409
10487
  const resetTimestamp = parseResetTime(resetTime);
10410
10488
  totalCount += 1;
10489
+ perModel.push({
10490
+ modelId: modelName,
10491
+ displayName: entry.displayName ?? entry.modelName,
10492
+ group,
10493
+ remainingFraction: remainingFraction ?? 0,
10494
+ resetTime
10495
+ });
10496
+ if (!group) {
10497
+ continue;
10498
+ }
10411
10499
  const existing = groups[group];
10412
10500
  const nextCount = (existing?.modelCount ?? 0) + 1;
10413
10501
  const nextRemaining = remainingFraction === void 0 ? existing?.remainingFraction : existing?.remainingFraction === void 0 ? remainingFraction : Math.min(existing.remainingFraction, remainingFraction);
@@ -10428,7 +10516,8 @@ function aggregateQuota(models) {
10428
10516
  modelCount: nextCount
10429
10517
  };
10430
10518
  }
10431
- return { groups, modelCount: totalCount };
10519
+ perModel.sort((a, b) => a.modelId.localeCompare(b.modelId));
10520
+ return { groups, perModel, modelCount: totalCount };
10432
10521
  }
10433
10522
  async function fetchWithTimeout2(url, options, timeoutMs = FETCH_TIMEOUT_MS2) {
10434
10523
  const controller = new AbortController();
@@ -10440,51 +10529,85 @@ async function fetchWithTimeout2(url, options, timeoutMs = FETCH_TIMEOUT_MS2) {
10440
10529
  }
10441
10530
  }
10442
10531
  async function fetchAvailableModels(accessToken, projectId) {
10443
- const endpoint = ANTIGRAVITY_ENDPOINT_PROD;
10444
10532
  const quotaUserAgent = getAntigravityHeaders()["User-Agent"] || "antigravity/windows/amd64";
10445
10533
  const errors = [];
10446
- const body = projectId ? { project: projectId } : {};
10447
- const response = await fetchWithTimeout2(`${endpoint}/v1internal:fetchAvailableModels`, {
10448
- method: "POST",
10449
- headers: {
10450
- Authorization: `Bearer ${accessToken}`,
10451
- "Content-Type": "application/json",
10452
- "User-Agent": quotaUserAgent
10453
- },
10454
- body: JSON.stringify(body)
10455
- });
10456
- if (response.ok) {
10457
- return await response.json();
10534
+ for (const endpoint of ANTIGRAVITY_ENDPOINT_FALLBACKS) {
10535
+ const body = projectId ? { project: projectId } : {};
10536
+ try {
10537
+ const response = await fetchWithTimeout2(`${endpoint}/v1internal:fetchAvailableModels`, {
10538
+ method: "POST",
10539
+ headers: {
10540
+ Authorization: `Bearer ${accessToken}`,
10541
+ "Content-Type": "application/json",
10542
+ "User-Agent": quotaUserAgent
10543
+ },
10544
+ body: JSON.stringify(body)
10545
+ });
10546
+ if (response.ok) {
10547
+ return await response.json();
10548
+ }
10549
+ const status = response.status;
10550
+ if (status === 403 && projectId) {
10551
+ try {
10552
+ const retryResponse = await fetchWithTimeout2(`${endpoint}/v1internal:fetchAvailableModels`, {
10553
+ method: "POST",
10554
+ headers: {
10555
+ Authorization: `Bearer ${accessToken}`,
10556
+ "Content-Type": "application/json",
10557
+ "User-Agent": quotaUserAgent
10558
+ },
10559
+ body: JSON.stringify({})
10560
+ });
10561
+ if (retryResponse.ok) {
10562
+ return await retryResponse.json();
10563
+ }
10564
+ } catch {
10565
+ }
10566
+ }
10567
+ if (status === 429 || status >= 500) {
10568
+ const message2 = await response.text().catch(() => "");
10569
+ const snippet2 = message2.trim().slice(0, 200);
10570
+ errors.push(`fetchAvailableModels ${status} at ${endpoint}${snippet2 ? `: ${snippet2}` : ""}`);
10571
+ continue;
10572
+ }
10573
+ const message = await response.text().catch(() => "");
10574
+ const snippet = message.trim().slice(0, 200);
10575
+ errors.push(`fetchAvailableModels ${status} at ${endpoint}${snippet ? `: ${snippet}` : ""}`);
10576
+ break;
10577
+ } catch (error) {
10578
+ errors.push(`fetchAvailableModels network error at ${endpoint}: ${error instanceof Error ? error.message : String(error)}`);
10579
+ continue;
10580
+ }
10458
10581
  }
10459
- const message = await response.text().catch(() => "");
10460
- const snippet = message.trim().slice(0, 200);
10461
- errors.push(
10462
- `fetchAvailableModels ${response.status} at ${endpoint}${snippet ? `: ${snippet}` : ""}`
10463
- );
10464
10582
  throw new Error(errors.join("; ") || "fetchAvailableModels failed");
10465
10583
  }
10466
10584
  async function fetchGeminiCliQuota(accessToken, projectId) {
10467
- const endpoint = ANTIGRAVITY_ENDPOINT_PROD;
10468
10585
  const geminiCliUserAgent = buildGeminiCliUserAgent();
10469
- const body = projectId ? { project: projectId } : {};
10470
- try {
10471
- const response = await fetchWithTimeout2(`${endpoint}/v1internal:retrieveUserQuota`, {
10472
- method: "POST",
10473
- headers: {
10474
- Authorization: `Bearer ${accessToken}`,
10475
- "Content-Type": "application/json",
10476
- "User-Agent": geminiCliUserAgent
10477
- },
10478
- body: JSON.stringify(body)
10479
- });
10480
- if (response.ok) {
10481
- const data = await response.json();
10482
- return data;
10586
+ for (const endpoint of ANTIGRAVITY_ENDPOINT_FALLBACKS) {
10587
+ const body = projectId ? { project: projectId } : {};
10588
+ try {
10589
+ const response = await fetchWithTimeout2(`${endpoint}/v1internal:retrieveUserQuota`, {
10590
+ method: "POST",
10591
+ headers: {
10592
+ Authorization: `Bearer ${accessToken}`,
10593
+ "Content-Type": "application/json",
10594
+ "User-Agent": geminiCliUserAgent
10595
+ },
10596
+ body: JSON.stringify(body)
10597
+ });
10598
+ if (response.ok) {
10599
+ return await response.json();
10600
+ }
10601
+ const status = response.status;
10602
+ if (status === 429 || status >= 500) {
10603
+ continue;
10604
+ }
10605
+ return { buckets: [] };
10606
+ } catch {
10607
+ continue;
10483
10608
  }
10484
- return { buckets: [] };
10485
- } catch {
10486
- return { buckets: [] };
10487
10609
  }
10610
+ return { buckets: [] };
10488
10611
  }
10489
10612
  function aggregateGeminiCliQuota(response) {
10490
10613
  const models = [];
@@ -12523,6 +12646,11 @@ var createAntigravityPlugin = (providerId) => async ({ client, directory }) => {
12523
12646
  }
12524
12647
  const response = await fetch(prepared.request, prepared.init);
12525
12648
  apiRequestCount++;
12649
+ accountManager.recordRequest(account.index, family);
12650
+ const requestCounts = accountManager.getDailyRequestCounts(account.index);
12651
+ if (requestCounts) {
12652
+ pushDebug(`[Quota] account=${account.index} ${family}_today=${requestCounts[family]} total_${family}_today=${accountManager.getTotalDailyRequests(family)}`);
12653
+ }
12526
12654
  pushDebug(`status=${response.status} ${response.statusText} (api_request #${apiRequestCount})`);
12527
12655
  if (response.status === 429 || response.status === 503 || response.status === 529) {
12528
12656
  if (tokenConsumed) {
@@ -12808,6 +12936,12 @@ Alternatively, you can:
12808
12936
  if (apiRequestCount > 1) {
12809
12937
  pushDebug(`[Quota] Total API requests for this user message: ${apiRequestCount} (${apiRequestCount - 1} retries)`);
12810
12938
  }
12939
+ const dailyCounts = accountManager.getDailyRequestCounts(account.index);
12940
+ if (dailyCounts) {
12941
+ pushDebug(`[Quota] Account ${account.index} (${account.email ?? "unknown"}) today: claude=${dailyCounts.claude} gemini=${dailyCounts.gemini}`);
12942
+ }
12943
+ const totalToday = accountManager.getTotalDailyRequests(family);
12944
+ pushDebug(`[Quota] Total ${family} requests today (all accounts): ${totalToday}`);
12811
12945
  return transformedResponse;
12812
12946
  } catch (error) {
12813
12947
  if (tokenConsumed) {
@@ -12969,6 +13103,7 @@ Alternatively, you can:
12969
13103
  cooldownMs,
12970
13104
  cooldownReason: cooldownMs ? acc.cooldownReason : void 0,
12971
13105
  cachedQuota: acc.cachedQuota,
13106
+ cachedPerModelQuota: acc.cachedPerModelQuota,
12972
13107
  fingerprintHistory: acc.fingerprintHistory
12973
13108
  };
12974
13109
  });
@@ -13075,6 +13210,7 @@ Alternatively, you can:
13075
13210
  const acc = existingStorage2.accounts[res.index];
13076
13211
  if (acc) {
13077
13212
  acc.cachedQuota = res.quota.groups;
13213
+ acc.cachedPerModelQuota = res.quota.perModel;
13078
13214
  acc.cachedQuotaUpdatedAt = Date.now();
13079
13215
  storageUpdated = true;
13080
13216
  }
@@ -13083,6 +13219,7 @@ Alternatively, you can:
13083
13219
  existingStorage2.accounts[res.index] = {
13084
13220
  ...res.updatedAccount,
13085
13221
  cachedQuota: res.quota?.groups,
13222
+ cachedPerModelQuota: res.quota?.perModel,
13086
13223
  cachedQuotaUpdatedAt: Date.now()
13087
13224
  };
13088
13225
  storageUpdated = true;