opencode-antigravity-auth-tweaked 1.9.4 → 1.9.5
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.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/src/antigravity/oauth.d.ts.map +1 -1
- package/dist/src/antigravity/oauth.js +4 -4
- package/dist/src/antigravity/oauth.js.map +1 -1
- package/dist/src/constants.d.ts +1 -1
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +29 -29
- package/dist/src/constants.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/cache.js +1 -1
- package/dist/src/hooks/auto-update-checker/cache.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/checker.d.ts +1 -1
- package/dist/src/hooks/auto-update-checker/checker.d.ts.map +1 -1
- package/dist/src/hooks/auto-update-checker/checker.js +2 -2
- package/dist/src/hooks/auto-update-checker/checker.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/constants.d.ts.map +1 -1
- package/dist/src/hooks/auto-update-checker/constants.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/index.d.ts +4 -4
- package/dist/src/hooks/auto-update-checker/index.d.ts.map +1 -1
- package/dist/src/hooks/auto-update-checker/index.js +6 -6
- package/dist/src/hooks/auto-update-checker/index.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/logging.js +1 -1
- package/dist/src/hooks/auto-update-checker/logging.js.map +1 -1
- package/dist/src/hooks/auto-update-checker/types.d.ts.map +1 -1
- package/dist/src/plugin/accounts.d.ts +16 -9
- package/dist/src/plugin/accounts.d.ts.map +1 -1
- package/dist/src/plugin/accounts.js +106 -29
- package/dist/src/plugin/accounts.js.map +1 -1
- package/dist/src/plugin/auth.d.ts +1 -1
- package/dist/src/plugin/auth.d.ts.map +1 -1
- package/dist/src/plugin/auth.js.map +1 -1
- package/dist/src/plugin/cache/index.d.ts +1 -1
- package/dist/src/plugin/cache/index.d.ts.map +1 -1
- package/dist/src/plugin/cache/index.js +1 -1
- package/dist/src/plugin/cache/index.js.map +1 -1
- package/dist/src/plugin/cache/signature-cache.d.ts +1 -1
- package/dist/src/plugin/cache/signature-cache.d.ts.map +1 -1
- package/dist/src/plugin/cache/signature-cache.js +1 -1
- package/dist/src/plugin/cache/signature-cache.js.map +1 -1
- package/dist/src/plugin/cache.d.ts +5 -5
- package/dist/src/plugin/cache.d.ts.map +1 -1
- package/dist/src/plugin/cache.js +3 -3
- package/dist/src/plugin/cache.js.map +1 -1
- package/dist/src/plugin/cli.d.ts +3 -3
- package/dist/src/plugin/cli.d.ts.map +1 -1
- package/dist/src/plugin/cli.js +3 -3
- package/dist/src/plugin/cli.js.map +1 -1
- package/dist/src/plugin/concurrency.d.ts.map +1 -1
- package/dist/src/plugin/concurrency.js.map +1 -1
- package/dist/src/plugin/config/index.d.ts +4 -4
- package/dist/src/plugin/config/index.d.ts.map +1 -1
- package/dist/src/plugin/config/index.js +4 -4
- package/dist/src/plugin/config/index.js.map +1 -1
- package/dist/src/plugin/config/loader.d.ts +1 -1
- package/dist/src/plugin/config/loader.d.ts.map +1 -1
- package/dist/src/plugin/config/loader.js +3 -3
- package/dist/src/plugin/config/loader.js.map +1 -1
- package/dist/src/plugin/config/models.d.ts +1 -1
- package/dist/src/plugin/config/models.d.ts.map +1 -1
- package/dist/src/plugin/config/models.js.map +1 -1
- package/dist/src/plugin/config/schema.d.ts +18 -0
- package/dist/src/plugin/config/schema.d.ts.map +1 -1
- package/dist/src/plugin/config/schema.js +21 -0
- package/dist/src/plugin/config/schema.js.map +1 -1
- package/dist/src/plugin/config/updater.d.ts.map +1 -1
- package/dist/src/plugin/config/updater.js +1 -1
- package/dist/src/plugin/config/updater.js.map +1 -1
- package/dist/src/plugin/core/streaming/index.d.ts +2 -2
- package/dist/src/plugin/core/streaming/index.d.ts.map +1 -1
- package/dist/src/plugin/core/streaming/index.js +2 -2
- package/dist/src/plugin/core/streaming/index.js.map +1 -1
- package/dist/src/plugin/core/streaming/transformer.d.ts +1 -1
- package/dist/src/plugin/core/streaming/transformer.d.ts.map +1 -1
- package/dist/src/plugin/core/streaming/transformer.js +1 -1
- package/dist/src/plugin/core/streaming/transformer.js.map +1 -1
- package/dist/src/plugin/core/streaming/types.d.ts.map +1 -1
- package/dist/src/plugin/debug.d.ts +1 -1
- package/dist/src/plugin/debug.d.ts.map +1 -1
- package/dist/src/plugin/debug.js +2 -2
- package/dist/src/plugin/debug.js.map +1 -1
- package/dist/src/plugin/error-extraction.js +1 -1
- package/dist/src/plugin/error-extraction.js.map +1 -1
- package/dist/src/plugin/errors.d.ts.map +1 -1
- package/dist/src/plugin/errors.js.map +1 -1
- package/dist/src/plugin/fingerprint.d.ts.map +1 -1
- package/dist/src/plugin/fingerprint.js +1 -1
- package/dist/src/plugin/fingerprint.js.map +1 -1
- package/dist/src/plugin/image-saver.js.map +1 -1
- package/dist/src/plugin/logger.d.ts +4 -4
- package/dist/src/plugin/logger.d.ts.map +1 -1
- package/dist/src/plugin/logger.js +5 -5
- package/dist/src/plugin/logger.js.map +1 -1
- package/dist/src/plugin/project.d.ts +1 -1
- package/dist/src/plugin/project.d.ts.map +1 -1
- package/dist/src/plugin/project.js +4 -4
- package/dist/src/plugin/project.js.map +1 -1
- package/dist/src/plugin/quota-sync.d.ts +42 -0
- package/dist/src/plugin/quota-sync.d.ts.map +1 -0
- package/dist/src/plugin/quota-sync.js +170 -0
- package/dist/src/plugin/quota-sync.js.map +1 -0
- package/dist/src/plugin/quota.d.ts +2 -2
- package/dist/src/plugin/quota.d.ts.map +1 -1
- package/dist/src/plugin/quota.js +6 -6
- package/dist/src/plugin/quota.js.map +1 -1
- package/dist/src/plugin/recovery/constants.d.ts.map +1 -1
- package/dist/src/plugin/recovery/constants.js.map +1 -1
- package/dist/src/plugin/recovery/index.d.ts +3 -3
- package/dist/src/plugin/recovery/index.d.ts.map +1 -1
- package/dist/src/plugin/recovery/index.js +3 -3
- package/dist/src/plugin/recovery/index.js.map +1 -1
- package/dist/src/plugin/recovery/storage.d.ts +1 -1
- package/dist/src/plugin/recovery/storage.d.ts.map +1 -1
- package/dist/src/plugin/recovery/storage.js +1 -1
- package/dist/src/plugin/recovery/storage.js.map +1 -1
- package/dist/src/plugin/recovery/types.d.ts.map +1 -1
- package/dist/src/plugin/recovery.d.ts +3 -3
- package/dist/src/plugin/recovery.d.ts.map +1 -1
- package/dist/src/plugin/recovery.js +7 -12
- package/dist/src/plugin/recovery.js.map +1 -1
- package/dist/src/plugin/refresh-queue.d.ts +2 -2
- package/dist/src/plugin/refresh-queue.d.ts.map +1 -1
- package/dist/src/plugin/refresh-queue.js +2 -2
- package/dist/src/plugin/refresh-queue.js.map +1 -1
- package/dist/src/plugin/request-helpers.d.ts +121 -15
- package/dist/src/plugin/request-helpers.d.ts.map +1 -1
- package/dist/src/plugin/request-helpers.js +130 -92
- package/dist/src/plugin/request-helpers.js.map +1 -1
- package/dist/src/plugin/request.d.ts +19 -18
- package/dist/src/plugin/request.d.ts.map +1 -1
- package/dist/src/plugin/request.js +80 -78
- package/dist/src/plugin/request.js.map +1 -1
- package/dist/src/plugin/rotation.d.ts +2 -2
- package/dist/src/plugin/rotation.d.ts.map +1 -1
- package/dist/src/plugin/rotation.js +7 -5
- package/dist/src/plugin/rotation.js.map +1 -1
- package/dist/src/plugin/search.d.ts.map +1 -1
- package/dist/src/plugin/search.js +2 -2
- package/dist/src/plugin/search.js.map +1 -1
- package/dist/src/plugin/server.d.ts.map +1 -1
- package/dist/src/plugin/server.js +125 -125
- package/dist/src/plugin/server.js.map +1 -1
- package/dist/src/plugin/sessions.d.ts.map +1 -1
- package/dist/src/plugin/sessions.js.map +1 -1
- package/dist/src/plugin/storage.d.ts +3 -3
- package/dist/src/plugin/storage.d.ts.map +1 -1
- package/dist/src/plugin/storage.js +2 -2
- package/dist/src/plugin/storage.js.map +1 -1
- package/dist/src/plugin/stores/signature-store.d.ts +1 -1
- package/dist/src/plugin/stores/signature-store.d.ts.map +1 -1
- package/dist/src/plugin/stores/signature-store.js.map +1 -1
- package/dist/src/plugin/thinking-recovery.d.ts.map +1 -1
- package/dist/src/plugin/thinking-recovery.js.map +1 -1
- package/dist/src/plugin/token.d.ts +1 -1
- package/dist/src/plugin/token.d.ts.map +1 -1
- package/dist/src/plugin/token.js +6 -6
- package/dist/src/plugin/token.js.map +1 -1
- package/dist/src/plugin/transform/claude.d.ts +1 -1
- package/dist/src/plugin/transform/claude.d.ts.map +1 -1
- package/dist/src/plugin/transform/claude.js +1 -1
- package/dist/src/plugin/transform/claude.js.map +1 -1
- package/dist/src/plugin/transform/cross-model-sanitizer.d.ts.map +1 -1
- package/dist/src/plugin/transform/cross-model-sanitizer.js +2 -2
- package/dist/src/plugin/transform/cross-model-sanitizer.js.map +1 -1
- package/dist/src/plugin/transform/gemini.d.ts +1 -1
- package/dist/src/plugin/transform/gemini.d.ts.map +1 -1
- package/dist/src/plugin/transform/gemini.js.map +1 -1
- package/dist/src/plugin/transform/index.d.ts +9 -9
- package/dist/src/plugin/transform/index.d.ts.map +1 -1
- package/dist/src/plugin/transform/index.js +4 -4
- package/dist/src/plugin/transform/index.js.map +1 -1
- package/dist/src/plugin/transform/model-resolver.d.ts +1 -1
- package/dist/src/plugin/transform/model-resolver.d.ts.map +1 -1
- package/dist/src/plugin/transform/model-resolver.js.map +1 -1
- package/dist/src/plugin/transform/types.d.ts +1 -1
- package/dist/src/plugin/transform/types.d.ts.map +1 -1
- package/dist/src/plugin/types.d.ts +1 -1
- package/dist/src/plugin/types.d.ts.map +1 -1
- package/dist/src/plugin/ui/ansi.d.ts.map +1 -1
- package/dist/src/plugin/ui/ansi.js.map +1 -1
- package/dist/src/plugin/ui/auth-menu.d.ts +1 -1
- package/dist/src/plugin/ui/auth-menu.d.ts.map +1 -1
- package/dist/src/plugin/ui/auth-menu.js +4 -4
- package/dist/src/plugin/ui/auth-menu.js.map +1 -1
- package/dist/src/plugin/ui/confirm.js +1 -1
- package/dist/src/plugin/ui/confirm.js.map +1 -1
- package/dist/src/plugin/ui/select.d.ts.map +1 -1
- package/dist/src/plugin/ui/select.js +1 -1
- package/dist/src/plugin/ui/select.js.map +1 -1
- package/dist/src/plugin/ui/toast.d.ts +22 -1
- package/dist/src/plugin/ui/toast.d.ts.map +1 -1
- package/dist/src/plugin/ui/toast.js +59 -5
- package/dist/src/plugin/ui/toast.js.map +1 -1
- package/dist/src/plugin/version.js +2 -2
- package/dist/src/plugin/version.js.map +1 -1
- package/dist/src/plugin.d.ts +4 -4
- package/dist/src/plugin.d.ts.map +1 -1
- package/dist/src/plugin.js +97 -143
- package/dist/src/plugin.js.map +1 -1
- package/package.json +1 -1
package/dist/src/plugin.js
CHANGED
|
@@ -1,33 +1,35 @@
|
|
|
1
1
|
import { exec } from "node:child_process";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
2
3
|
import { tool } from "@opencode-ai/plugin";
|
|
3
|
-
import { ANTIGRAVITY_DEFAULT_PROJECT_ID, ANTIGRAVITY_ENDPOINT_FALLBACKS, ANTIGRAVITY_ENDPOINT_PROD, ANTIGRAVITY_PROVIDER_ID, getAntigravityHeaders, } from "./constants";
|
|
4
|
-
import { authorizeAntigravity, exchangeAntigravity } from "./antigravity/oauth";
|
|
5
|
-
import { accessTokenExpired, isOAuthAuth, parseRefreshParts, formatRefreshParts } from "./plugin/auth";
|
|
6
|
-
import { promptAddAnotherAccount, promptLoginMode } from "./plugin/cli";
|
|
7
|
-
import { ensureProjectContext } from "./plugin/project";
|
|
8
|
-
import { startAntigravityDebugRequest, logAntigravityDebugResponse, logAccountContext, logRateLimitEvent, logRateLimitSnapshot, logResponseBody, logModelFamily, isDebugEnabled, getLogFilePath, initializeDebug, } from "./plugin/debug";
|
|
9
|
-
import { buildThinkingWarmupBody, isGenerativeLanguageRequest, prepareAntigravityRequest, transformAntigravityResponse, } from "./plugin/request";
|
|
10
|
-
import { decodeEscapedText, normalizeGoogleVerificationUrl, selectBestVerificationUrl, extractVerificationErrorDetails, parseDurationToMs, extractRateLimitBodyInfo, extractRetryInfoFromBody, extractMessageFromRawBody, retryAfterMsFromResponse, } from "./plugin/error-extraction";
|
|
11
|
-
import { resolveModelWithTier } from "./plugin/transform/model-resolver";
|
|
12
|
-
import { isEmptyResponseBody, createSyntheticErrorResponse, } from "./plugin/request-helpers";
|
|
13
|
-
import { EmptyResponseError } from "./plugin/errors";
|
|
14
|
-
import { AntigravityTokenRefreshError, refreshAccessToken } from "./plugin/token";
|
|
15
|
-
import { startOAuthListener } from "./plugin/server";
|
|
16
|
-
import { clearAccounts, loadAccounts, saveAccounts, saveAccountsReplace } from "./plugin/storage";
|
|
17
|
-
import { AccountManager, parseRateLimitReason, calculateBackoffMs, computeSoftQuotaCacheTtlMs } from "./plugin/accounts";
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
4
|
+
import { ANTIGRAVITY_DEFAULT_PROJECT_ID, ANTIGRAVITY_ENDPOINT_FALLBACKS, ANTIGRAVITY_ENDPOINT_PROD, ANTIGRAVITY_PROVIDER_ID, getAntigravityHeaders, } from "./constants.js";
|
|
5
|
+
import { authorizeAntigravity, exchangeAntigravity } from "./antigravity/oauth.js";
|
|
6
|
+
import { accessTokenExpired, isOAuthAuth, parseRefreshParts, formatRefreshParts } from "./plugin/auth.js";
|
|
7
|
+
import { promptAddAnotherAccount, promptLoginMode } from "./plugin/cli.js";
|
|
8
|
+
import { ensureProjectContext } from "./plugin/project.js";
|
|
9
|
+
import { startAntigravityDebugRequest, logAntigravityDebugResponse, logAccountContext, logRateLimitEvent, logRateLimitSnapshot, logResponseBody, logModelFamily, isDebugEnabled, getLogFilePath, initializeDebug, } from "./plugin/debug.js";
|
|
10
|
+
import { buildThinkingWarmupBody, isGenerativeLanguageRequest, prepareAntigravityRequest, transformAntigravityResponse, } from "./plugin/request.js";
|
|
11
|
+
import { decodeEscapedText, normalizeGoogleVerificationUrl, selectBestVerificationUrl, extractVerificationErrorDetails, parseDurationToMs, extractRateLimitBodyInfo, extractRetryInfoFromBody, extractMessageFromRawBody, retryAfterMsFromResponse, } from "./plugin/error-extraction.js";
|
|
12
|
+
import { resolveModelWithTier } from "./plugin/transform/model-resolver.js";
|
|
13
|
+
import { isEmptyResponseBody, createSyntheticErrorResponse, } from "./plugin/request-helpers.js";
|
|
14
|
+
import { EmptyResponseError } from "./plugin/errors.js";
|
|
15
|
+
import { AntigravityTokenRefreshError, refreshAccessToken } from "./plugin/token.js";
|
|
16
|
+
import { startOAuthListener } from "./plugin/server.js";
|
|
17
|
+
import { clearAccounts, loadAccounts, saveAccounts, saveAccountsReplace } from "./plugin/storage.js";
|
|
18
|
+
import { AccountManager, parseRateLimitReason, calculateBackoffMs, computeSoftQuotaCacheTtlMs } from "./plugin/accounts.js";
|
|
19
|
+
import { ProactiveQuotaSync } from "./plugin/quota-sync.js";
|
|
20
|
+
import { createAutoUpdateCheckerHook } from "./hooks/auto-update-checker/index.js";
|
|
21
|
+
import { loadConfig, initRuntimeConfig, wasConfigCreated, getUserConfigPath } from "./plugin/config/index.js";
|
|
22
|
+
import { createSessionRecoveryHook, getRecoverySuccessToast } from "./plugin/recovery.js";
|
|
23
|
+
import { checkAccountsQuota } from "./plugin/quota.js";
|
|
24
|
+
import { initDiskSignatureCache } from "./plugin/cache.js";
|
|
25
|
+
import { createProactiveRefreshQueue } from "./plugin/refresh-queue.js";
|
|
26
|
+
import { initLogger, createLogger } from "./plugin/logger.js";
|
|
27
|
+
import { initHealthTracker, getHealthTracker, initTokenTracker, getTokenTracker } from "./plugin/rotation.js";
|
|
28
|
+
import { getConcurrencyTracker } from "./plugin/concurrency.js";
|
|
29
|
+
import { getSessionAccountManager } from "./plugin/sessions.js";
|
|
30
|
+
import { initAntigravityVersion } from "./plugin/version.js";
|
|
31
|
+
import { executeSearch } from "./plugin/search.js";
|
|
32
|
+
import { initToastService, toast, setChildSession } from "./plugin/ui/toast.js";
|
|
31
33
|
const MAX_OAUTH_ACCOUNTS = 10;
|
|
32
34
|
const MAX_WARMUP_SESSIONS = 1000;
|
|
33
35
|
const MAX_WARMUP_RETRIES = 2;
|
|
@@ -36,6 +38,25 @@ function getCapacityBackoffDelay(consecutiveFailures) {
|
|
|
36
38
|
const index = Math.min(consecutiveFailures, CAPACITY_BACKOFF_TIERS_MS.length - 1);
|
|
37
39
|
return CAPACITY_BACKOFF_TIERS_MS[Math.max(0, index)] ?? 5000;
|
|
38
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Map RateLimitReason to health score penalty.
|
|
43
|
+
*/
|
|
44
|
+
function getPenaltyForReason(reason) {
|
|
45
|
+
switch (reason) {
|
|
46
|
+
case "QUOTA_EXHAUSTED":
|
|
47
|
+
return -15;
|
|
48
|
+
case "ACCESS_DENIED":
|
|
49
|
+
return -50;
|
|
50
|
+
case "VERIFICATION_REQUIRED":
|
|
51
|
+
return -50;
|
|
52
|
+
case "SAFETY_BLOCKED":
|
|
53
|
+
return -30;
|
|
54
|
+
case "RATE_LIMIT_EXCEEDED":
|
|
55
|
+
return -10;
|
|
56
|
+
default:
|
|
57
|
+
return -10;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
39
60
|
/**
|
|
40
61
|
* Extracts sessionId from a Generative Language request payload if possible.
|
|
41
62
|
*/
|
|
@@ -55,78 +76,8 @@ function preparedRequestSessionId(input) {
|
|
|
55
76
|
const warmupAttemptedSessionIds = new Set();
|
|
56
77
|
const warmupSucceededSessionIds = new Set();
|
|
57
78
|
const log = createLogger("plugin");
|
|
58
|
-
// Module-level toast debounce to persist across requests (fixes toast spam)
|
|
59
|
-
const rateLimitToastCooldowns = new Map();
|
|
60
|
-
const RATE_LIMIT_TOAST_COOLDOWN_MS = 5000;
|
|
61
|
-
const MAX_TOAST_COOLDOWN_ENTRIES = 100;
|
|
62
|
-
// Track if "all accounts blocked" toasts were shown to prevent spam in while loop
|
|
63
|
-
let softQuotaToastShown = false;
|
|
64
|
-
let rateLimitToastShown = false;
|
|
65
79
|
// Module-level reference to AccountManager for access from auth.login
|
|
66
80
|
let activeAccountManager = null;
|
|
67
|
-
function cleanupToastCooldowns() {
|
|
68
|
-
if (rateLimitToastCooldowns.size > MAX_TOAST_COOLDOWN_ENTRIES) {
|
|
69
|
-
const now = Date.now();
|
|
70
|
-
for (const [key, time] of rateLimitToastCooldowns) {
|
|
71
|
-
if (now - time > RATE_LIMIT_TOAST_COOLDOWN_MS * 2) {
|
|
72
|
-
rateLimitToastCooldowns.delete(key);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
function shouldShowRateLimitToast(message) {
|
|
78
|
-
cleanupToastCooldowns();
|
|
79
|
-
const toastKey = message.replace(/\d+/g, "X");
|
|
80
|
-
const lastShown = rateLimitToastCooldowns.get(toastKey) ?? 0;
|
|
81
|
-
const now = Date.now();
|
|
82
|
-
if (now - lastShown < RATE_LIMIT_TOAST_COOLDOWN_MS) {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
rateLimitToastCooldowns.set(toastKey, now);
|
|
86
|
-
return true;
|
|
87
|
-
}
|
|
88
|
-
function resetAllAccountsBlockedToasts() {
|
|
89
|
-
softQuotaToastShown = false;
|
|
90
|
-
rateLimitToastShown = false;
|
|
91
|
-
}
|
|
92
|
-
const quotaRefreshInProgressByEmail = new Set();
|
|
93
|
-
async function triggerAsyncQuotaRefreshForAccount(accountManager, accountIndex, client, providerId, intervalMinutes) {
|
|
94
|
-
if (intervalMinutes <= 0)
|
|
95
|
-
return;
|
|
96
|
-
const accounts = accountManager.getAccounts();
|
|
97
|
-
const account = accounts[accountIndex];
|
|
98
|
-
if (!account || account.enabled === false)
|
|
99
|
-
return;
|
|
100
|
-
const accountKey = account.email ?? `idx-${accountIndex}`;
|
|
101
|
-
if (quotaRefreshInProgressByEmail.has(accountKey))
|
|
102
|
-
return;
|
|
103
|
-
const intervalMs = intervalMinutes * 60 * 1000;
|
|
104
|
-
const age = account.cachedQuotaUpdatedAt != null
|
|
105
|
-
? Date.now() - account.cachedQuotaUpdatedAt
|
|
106
|
-
: Infinity;
|
|
107
|
-
if (age < intervalMs)
|
|
108
|
-
return;
|
|
109
|
-
quotaRefreshInProgressByEmail.add(accountKey);
|
|
110
|
-
try {
|
|
111
|
-
const accountsForCheck = accountManager.getAccountsForQuotaCheck();
|
|
112
|
-
const singleAccount = accountsForCheck[accountIndex];
|
|
113
|
-
if (!singleAccount) {
|
|
114
|
-
quotaRefreshInProgressByEmail.delete(accountKey);
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
const results = await checkAccountsQuota([singleAccount], client, providerId);
|
|
118
|
-
if (results[0]?.status === "ok" && results[0]?.quota?.groups) {
|
|
119
|
-
accountManager.updateQuotaCache(accountIndex, results[0].quota.groups);
|
|
120
|
-
accountManager.requestSaveToDisk();
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
catch (err) {
|
|
124
|
-
log.debug(`quota-refresh-failed email=${accountKey}`, { error: String(err) });
|
|
125
|
-
}
|
|
126
|
-
finally {
|
|
127
|
-
quotaRefreshInProgressByEmail.delete(accountKey);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
81
|
function trackWarmupAttempt(sessionId) {
|
|
131
82
|
if (warmupSucceededSessionIds.has(sessionId)) {
|
|
132
83
|
return false;
|
|
@@ -163,7 +114,6 @@ function isWSL() {
|
|
|
163
114
|
if (process.platform !== "linux")
|
|
164
115
|
return false;
|
|
165
116
|
try {
|
|
166
|
-
const { readFileSync } = require("node:fs");
|
|
167
117
|
const release = readFileSync("/proc/version", "utf8").toLowerCase();
|
|
168
118
|
return release.includes("microsoft") || release.includes("wsl");
|
|
169
119
|
}
|
|
@@ -175,7 +125,6 @@ function isWSL2() {
|
|
|
175
125
|
if (!isWSL())
|
|
176
126
|
return false;
|
|
177
127
|
try {
|
|
178
|
-
const { readFileSync } = require("node:fs");
|
|
179
128
|
const version = readFileSync("/proc/version", "utf8").toLowerCase();
|
|
180
129
|
return version.includes("wsl2") || version.includes("microsoft-standard");
|
|
181
130
|
}
|
|
@@ -889,6 +838,10 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
889
838
|
// Note: AccountManager now ensures the current auth is always included in accounts
|
|
890
839
|
const accountManager = await AccountManager.loadFromDisk(auth);
|
|
891
840
|
activeAccountManager = accountManager;
|
|
841
|
+
const quotaSync = new ProactiveQuotaSync(accountManager, client, providerId);
|
|
842
|
+
if (config.quota_refresh_interval_minutes > 0) {
|
|
843
|
+
quotaSync.startPeriodicSync(config.quota_refresh_interval_minutes * 60 * 1000);
|
|
844
|
+
}
|
|
892
845
|
if (accountManager.getAccountCount() > 0) {
|
|
893
846
|
accountManager.requestSaveToDisk();
|
|
894
847
|
}
|
|
@@ -953,9 +906,9 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
953
906
|
const quietMode = config.quiet_mode;
|
|
954
907
|
const toastScope = config.toast_scope;
|
|
955
908
|
// Helper to show toast without blocking on abort (respects quiet_mode and toast_scope via ToastService)
|
|
956
|
-
const showToast = async (message, variant) => {
|
|
957
|
-
// ToastService handles quiet_mode, toast_scope, and
|
|
958
|
-
await toast.info(message, { variant, signal: abortSignal });
|
|
909
|
+
const showToast = async (message, variant, verbosity = "normal", debounceMs, debounceKey) => {
|
|
910
|
+
// ToastService handles quiet_mode, toast_scope, isChildSession, and debouncing
|
|
911
|
+
await toast.info(message, { variant, signal: abortSignal, verbosity, debounceMs, debounceKey });
|
|
959
912
|
};
|
|
960
913
|
const hasOtherAccountWithAntigravity = (currentAccount) => {
|
|
961
914
|
if (family !== "gemini")
|
|
@@ -964,7 +917,10 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
964
917
|
return accountManager.hasOtherAccountWithAntigravityAvailable(currentAccount.index, family, model);
|
|
965
918
|
};
|
|
966
919
|
let shouldSwitchAccount = false;
|
|
967
|
-
|
|
920
|
+
let retryCount = 0;
|
|
921
|
+
const maxRetries = 20;
|
|
922
|
+
while (retryCount < maxRetries) {
|
|
923
|
+
retryCount++;
|
|
968
924
|
// Check for abort at the start of each iteration
|
|
969
925
|
checkAborted();
|
|
970
926
|
const accountCount = accountManager.getAccountCount();
|
|
@@ -989,7 +945,8 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
989
945
|
if (!account) {
|
|
990
946
|
if (accountManager.areAllAccountsOverSoftQuota(family, config.soft_quota_threshold_percent, softQuotaCacheTtlMs, model)) {
|
|
991
947
|
const threshold = config.soft_quota_threshold_percent;
|
|
992
|
-
const
|
|
948
|
+
const softQuotaInfo = accountManager.getDetailedMinWaitTimeForSoftQuota(family, threshold, softQuotaCacheTtlMs, model);
|
|
949
|
+
const softQuotaWaitMs = softQuotaInfo?.waitMs ?? null;
|
|
993
950
|
const maxWaitMs = (config.max_rate_limit_wait_seconds ?? 300) * 1000;
|
|
994
951
|
if (softQuotaWaitMs === null || (maxWaitMs > 0 && softQuotaWaitMs > maxWaitMs)) {
|
|
995
952
|
const waitTimeFormatted = softQuotaWaitMs ? formatWaitTime(softQuotaWaitMs) : "unknown";
|
|
@@ -998,18 +955,16 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
998
955
|
`Quota resets in ${waitTimeFormatted}. ` +
|
|
999
956
|
`Add more accounts, wait for quota reset, or set soft_quota_threshold_percent: 100 to disable.`);
|
|
1000
957
|
}
|
|
1001
|
-
const waitSecValue = Math.max(1, Math.ceil(softQuotaWaitMs / 1000));
|
|
1002
958
|
pushDebug(`all-over-soft-quota family=${family} accounts=${accountCount} waitMs=${softQuotaWaitMs}`);
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
softQuotaToastShown = true;
|
|
1006
|
-
}
|
|
959
|
+
const earliestLabel = softQuotaInfo?.accountLabel ? ` (Account ${softQuotaInfo.accountLabel})` : "";
|
|
960
|
+
await showToast(`All ${accountCount} account(s) over ${threshold}% quota for ${family}. Earliest reset in ${formatWaitTime(softQuotaWaitMs)}${earliestLabel}.`, "warning", "normal", 60000, `soft-quota-${family}`);
|
|
1007
961
|
await sleep(softQuotaWaitMs, abortSignal);
|
|
1008
962
|
continue;
|
|
1009
963
|
}
|
|
1010
964
|
const strictWait = !allowQuotaFallback;
|
|
1011
965
|
// All accounts are rate-limited - wait and retry
|
|
1012
|
-
const
|
|
966
|
+
const waitInfo = accountManager.getDetailedMinWaitTimeForFamily(family, model, preferredHeaderStyle, strictWait);
|
|
967
|
+
const waitMs = waitInfo?.waitMs ?? 60_000;
|
|
1013
968
|
const waitSecValue = Math.max(1, Math.ceil(waitMs / 1000));
|
|
1014
969
|
pushDebug(`all-rate-limited family=${family} accounts=${accountCount} waitMs=${waitMs}`);
|
|
1015
970
|
if (isDebugEnabled()) {
|
|
@@ -1031,16 +986,18 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1031
986
|
`Quota resets in ${waitTimeFormatted}. ` +
|
|
1032
987
|
`Add more accounts with \`opencode auth login\` or wait and retry.`);
|
|
1033
988
|
}
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
rateLimitToastShown = true;
|
|
1037
|
-
}
|
|
989
|
+
const earliestLabel = waitInfo?.accountLabel ? ` (Account ${waitInfo.accountLabel})` : "";
|
|
990
|
+
await showToast(`All ${accountCount} account(s) rate-limited for ${family}. Earliest reset in ${formatWaitTime(waitMs)}${earliestLabel}.`, "warning", "normal", 60000, `rate-limit-${family}`);
|
|
1038
991
|
// Wait for the rate-limit cooldown to expire, then retry
|
|
1039
992
|
await sleep(waitMs, abortSignal);
|
|
1040
993
|
continue;
|
|
1041
994
|
}
|
|
1042
|
-
// Account is available
|
|
1043
|
-
|
|
995
|
+
// Account is available
|
|
996
|
+
if (account.verificationRequired) {
|
|
997
|
+
const reason = account.verificationRequiredReason || "Google requires account verification.";
|
|
998
|
+
const urlMsg = account.verificationUrl ? ` URL: ${account.verificationUrl}` : "";
|
|
999
|
+
await showToast(`⚠ Account ${account.email || account.index + 1} needs verification: ${reason}${urlMsg}. Run 'opencode auth login' and use 'Verify accounts'.`, "warning", "minimal", 60000, `verify-needed-${account.index}`);
|
|
1000
|
+
}
|
|
1044
1001
|
pushDebug(`selected idx=${account.index} email=${account.email ?? ""} family=${family} accounts=${accountCount} strategy=${config.account_selection_strategy}`);
|
|
1045
1002
|
if (isDebugEnabled()) {
|
|
1046
1003
|
logAccountContext("Selected", {
|
|
@@ -1052,13 +1009,12 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1052
1009
|
});
|
|
1053
1010
|
}
|
|
1054
1011
|
// Show toast when switching to a different account (debounced, quiet_mode handled by showToast)
|
|
1055
|
-
if (accountCount > 1
|
|
1012
|
+
if (accountCount > 1) {
|
|
1056
1013
|
const accountLabel = account.email || `Account ${account.index + 1}`;
|
|
1057
1014
|
// Calculate position among enabled accounts (not absolute index)
|
|
1058
1015
|
const enabledAccounts = accountManager.getEnabledAccounts();
|
|
1059
1016
|
const enabledPosition = enabledAccounts.findIndex(a => a.index === account.index) + 1;
|
|
1060
|
-
await showToast(`Using ${accountLabel} (${enabledPosition}/${accountCount})`, "info");
|
|
1061
|
-
accountManager.markToastShown(account.index);
|
|
1017
|
+
await showToast(`Using ${accountLabel} (${enabledPosition}/${accountCount})`, "info", "normal", 30000, `account-switch-${account.index}`);
|
|
1062
1018
|
}
|
|
1063
1019
|
accountManager.requestSaveToDisk();
|
|
1064
1020
|
let authRecord = accountManager.toAuthDetails(account);
|
|
@@ -1241,7 +1197,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1241
1197
|
alternateStyle,
|
|
1242
1198
|
});
|
|
1243
1199
|
if (fallbackStyle) {
|
|
1244
|
-
await toast.info(`Antigravity quota exhausted on all accounts. Using Gemini CLI quota.`, { variant: "warning" });
|
|
1200
|
+
await toast.info(`Antigravity quota exhausted on all accounts. Using Gemini CLI quota.`, { variant: "warning", verbosity: "normal" });
|
|
1245
1201
|
headerStyle = fallbackStyle;
|
|
1246
1202
|
pushDebug(`all-accounts antigravity exhausted, quota fallback: ${headerStyle}`);
|
|
1247
1203
|
}
|
|
@@ -1262,7 +1218,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1262
1218
|
if (fallbackStyle) {
|
|
1263
1219
|
const quotaName = headerStyle === "gemini-cli" ? "Gemini CLI" : "Antigravity";
|
|
1264
1220
|
const altQuotaName = fallbackStyle === "gemini-cli" ? "Gemini CLI" : "Antigravity";
|
|
1265
|
-
await toast.info(`${quotaName} quota exhausted, using ${altQuotaName} quota`, { variant: "warning" });
|
|
1221
|
+
await toast.info(`${quotaName} quota exhausted, using ${altQuotaName} quota`, { variant: "warning", verbosity: "normal" });
|
|
1266
1222
|
headerStyle = fallbackStyle;
|
|
1267
1223
|
pushDebug(`quota fallback: ${headerStyle}`);
|
|
1268
1224
|
}
|
|
@@ -1428,7 +1384,8 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1428
1384
|
pushDebug(`429/5xx NO MESSAGE - rawBody preview: ${bodyInfo.rawBody.slice(0, 200)}`);
|
|
1429
1385
|
logRateLimitEvent(account.index, account.email, family, response.status, effectiveDelayMs, bodyInfo);
|
|
1430
1386
|
await logResponseBody(debugContext, response, response.status);
|
|
1431
|
-
|
|
1387
|
+
const penalty = getPenaltyForReason(rateLimitReason);
|
|
1388
|
+
getHealthTracker().recordRateLimit(account.index, penalty);
|
|
1432
1389
|
// Define display reason for user feedback
|
|
1433
1390
|
// Never show "UNKNOWN" - show the actual server message or "NO_BODY" instead
|
|
1434
1391
|
let displayReason;
|
|
@@ -1457,7 +1414,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1457
1414
|
const totalWaitMs = effectiveDelayMs + extraWaitMs;
|
|
1458
1415
|
const waitSec = Math.ceil(totalWaitMs / 1000);
|
|
1459
1416
|
pushDebug(`Rate limited (${rateLimitReason}), waiting ${totalWaitMs}ms (${effectiveDelayMs} + ${extraWaitMs} jitter)`);
|
|
1460
|
-
await showToast(`⏳ Rate limited (${displayReason}). Waiting ${waitSec}s to retry same account...`, "warning");
|
|
1417
|
+
await showToast(`⏳ Rate limited (${displayReason}). Waiting ${waitSec}s to retry same account...`, "warning", "verbose", 30000, `retry-same-account-${account.index}`);
|
|
1461
1418
|
// If this is a repeated hit, try regenerating fingerprint as a mitigation
|
|
1462
1419
|
if (attempt > 1) {
|
|
1463
1420
|
pushDebug(`Regenerating fingerprint for account ${account.index} after ${attempt} consecutive hits`);
|
|
@@ -1478,7 +1435,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1478
1435
|
// Check if any other account has Antigravity quota for this model
|
|
1479
1436
|
if (hasOtherAccountWithAntigravity(account)) {
|
|
1480
1437
|
pushDebug(`antigravity exhausted on account ${account.index}, but available on others. Switching account.`);
|
|
1481
|
-
await showToast(`Quota exhausted. Switching account in 5s...`, "warning");
|
|
1438
|
+
await showToast(`Quota exhausted. Switching account in 5s...`, "warning", "normal", 30000, "quota-exhausted-switch");
|
|
1482
1439
|
await sleep(SWITCH_ACCOUNT_DELAY_MS, abortSignal);
|
|
1483
1440
|
shouldSwitchAccount = true;
|
|
1484
1441
|
currentAccountDone = true;
|
|
@@ -1496,7 +1453,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1496
1453
|
});
|
|
1497
1454
|
if (fallbackStyle) {
|
|
1498
1455
|
const safeModelName = model || "this model";
|
|
1499
|
-
await toast.info(`Antigravity quota exhausted for ${safeModelName}. Switching to Gemini CLI quota...`, { variant: "warning" });
|
|
1456
|
+
await toast.info(`Antigravity quota exhausted for ${safeModelName}. Switching to Gemini CLI quota...`, { variant: "warning", verbosity: "normal", debounceMs: 30000, debounceKey: "quota-fallback" });
|
|
1500
1457
|
headerStyle = fallbackStyle;
|
|
1501
1458
|
pushDebug(`quota fallback: ${headerStyle}`);
|
|
1502
1459
|
continue;
|
|
@@ -1513,7 +1470,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1513
1470
|
});
|
|
1514
1471
|
if (fallbackStyle) {
|
|
1515
1472
|
const safeModelName = model || "this model";
|
|
1516
|
-
await toast.info(`Gemini CLI quota exhausted for ${safeModelName}. Switching to Antigravity quota...`, { variant: "warning" });
|
|
1473
|
+
await toast.info(`Gemini CLI quota exhausted for ${safeModelName}. Switching to Antigravity quota...`, { variant: "warning", verbosity: "normal", debounceMs: 30000, debounceKey: "quota-fallback" });
|
|
1517
1474
|
headerStyle = fallbackStyle;
|
|
1518
1475
|
pushDebug(`quota fallback: ${headerStyle}`);
|
|
1519
1476
|
continue;
|
|
@@ -1529,7 +1486,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1529
1486
|
const toastMsg = rateLimitReason === "QUOTA_EXHAUSTED"
|
|
1530
1487
|
? `Quota exhausted${quotaMsg}. Switching account in 5s...`
|
|
1531
1488
|
: `Quota reached (${displayReason}) for ${accountLabel}. Switching account in 5s...${quotaMsg}`;
|
|
1532
|
-
await showToast(toastMsg, "error");
|
|
1489
|
+
await showToast(toastMsg, "error", "normal", 30000, "quota-reached-switch");
|
|
1533
1490
|
await sleep(SWITCH_ACCOUNT_DELAY_MS, abortSignal);
|
|
1534
1491
|
}
|
|
1535
1492
|
else {
|
|
@@ -1539,7 +1496,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1539
1496
|
const quotaMsg = bodyInfo.quotaResetTime
|
|
1540
1497
|
? ` (quota resets ${bodyInfo.quotaResetTime})`
|
|
1541
1498
|
: ``;
|
|
1542
|
-
await showToast(`Quota exhausted${quotaMsg}. Add another account or wait until quota resets.`, "error");
|
|
1499
|
+
await showToast(`Quota exhausted${quotaMsg}. Add another account or wait until quota resets.`, "error", "minimal");
|
|
1543
1500
|
// Don't retry - just fail and let the user handle it
|
|
1544
1501
|
lastFailure = createFailureContext(response);
|
|
1545
1502
|
break;
|
|
@@ -1548,7 +1505,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1548
1505
|
// Other errors - use exponential backoff (1s, 2s, 4s, 8s... max 60s)
|
|
1549
1506
|
const expBackoffMs = Math.min(FIRST_RETRY_DELAY_MS * Math.pow(2, attempt - 1), 60000);
|
|
1550
1507
|
const expBackoffFormatted = expBackoffMs >= 1000 ? `${Math.round(expBackoffMs / 1000)}s` : `${expBackoffMs}ms`;
|
|
1551
|
-
await showToast(`Quota reached (${displayReason}). Retrying in ${expBackoffFormatted} (attempt ${attempt})...`, "error");
|
|
1508
|
+
await showToast(`Quota reached (${displayReason}). Retrying in ${expBackoffFormatted} (attempt ${attempt})...`, "error", "verbose");
|
|
1552
1509
|
await sleep(expBackoffMs, abortSignal);
|
|
1553
1510
|
}
|
|
1554
1511
|
}
|
|
@@ -1565,18 +1522,15 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1565
1522
|
const errorBodyText = await response.clone().text().catch(() => "");
|
|
1566
1523
|
const extracted = extractVerificationErrorDetails(errorBodyText);
|
|
1567
1524
|
if (extracted.validationRequired) {
|
|
1568
|
-
const verificationReason = extracted.message
|
|
1525
|
+
const verificationReason = extracted.message || "Google requires account verification.";
|
|
1569
1526
|
const cooldownMs = 10 * 60 * 1000;
|
|
1570
1527
|
accountManager.markAccountVerificationRequired(account.index, verificationReason, extracted.verifyUrl);
|
|
1571
1528
|
accountManager.markAccountCoolingDown(account, cooldownMs, "validation-required");
|
|
1572
1529
|
accountManager.markRateLimited(account, cooldownMs, family, headerStyle, model);
|
|
1573
1530
|
const label = account.email || `Account ${account.index + 1}`;
|
|
1574
|
-
|
|
1575
|
-
await toast.info(`⚠ ${label} needs verification. Run 'opencode auth login' and use Verify accounts.`, { variant: "warning" });
|
|
1576
|
-
accountManager.markToastShown(account.index);
|
|
1577
|
-
}
|
|
1531
|
+
await toast.info(`🚨 Verification Required for ${label}: ${verificationReason}. Please run 'opencode auth login' and follow the 'Verify accounts' flow to restore access.`, { variant: "error", force: true, verbosity: "minimal" });
|
|
1578
1532
|
pushDebug(`verification-required: disabled account ${account.index}`);
|
|
1579
|
-
getHealthTracker().recordFailure(account.index);
|
|
1533
|
+
getHealthTracker().recordFailure(account.index, getPenaltyForReason("VERIFICATION_REQUIRED"));
|
|
1580
1534
|
lastFailure = createFailureContext(response);
|
|
1581
1535
|
shouldSwitchAccount = true;
|
|
1582
1536
|
currentAccountDone = true;
|
|
@@ -1596,7 +1550,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1596
1550
|
account.consecutiveFailures = 0;
|
|
1597
1551
|
getHealthTracker().recordSuccess(account.index);
|
|
1598
1552
|
accountManager.markAccountUsed(account.index);
|
|
1599
|
-
|
|
1553
|
+
quotaSync.enqueue(account.index);
|
|
1600
1554
|
}
|
|
1601
1555
|
logAntigravityDebugResponse(debugContext, response, {
|
|
1602
1556
|
note: response.ok ? "Success" : `Error ${response.status}`,
|
|
@@ -1611,7 +1565,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1611
1565
|
const cloned = response.clone();
|
|
1612
1566
|
const bodyText = await cloned.text();
|
|
1613
1567
|
if (bodyText.includes("Prompt is too long") || bodyText.includes("prompt_too_long")) {
|
|
1614
|
-
await toast.info("Context too long - use /compact to reduce size", { variant: "warning" });
|
|
1568
|
+
await toast.info("Context too long - use /compact to reduce size", { variant: "warning", debounceMs: 10000, debounceKey: "context-too-long" });
|
|
1615
1569
|
const errorMessage = `[Antigravity Error] Context is too long for this model.\n\nPlease use /compact to reduce context size, then retry your request.\n\nAlternatively, you can:\n- Use /clear to start fresh\n- Use /undo to remove recent messages\n- Switch to a model with larger context window`;
|
|
1616
1570
|
return createSyntheticErrorResponse(errorMessage, prepared.requestedModel);
|
|
1617
1571
|
}
|
|
@@ -1633,7 +1587,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1633
1587
|
emptyResponseAttempts.set(emptyAttemptKey, currentAttempts);
|
|
1634
1588
|
pushDebug(`empty-response: attempt ${currentAttempts}/${maxAttempts}`);
|
|
1635
1589
|
if (currentAttempts < maxAttempts) {
|
|
1636
|
-
await toast.info(`Empty response received. Retrying (${currentAttempts}/${maxAttempts})...`, { variant: "warning" });
|
|
1590
|
+
await toast.info(`Empty response received. Retrying (${currentAttempts}/${maxAttempts})...`, { variant: "warning", verbosity: "verbose" });
|
|
1637
1591
|
await sleep(retryDelayMs, abortSignal);
|
|
1638
1592
|
continue; // Retry the endpoint loop
|
|
1639
1593
|
}
|
|
@@ -1650,10 +1604,10 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1650
1604
|
const contextError = transformedResponse.headers.get("x-antigravity-context-error");
|
|
1651
1605
|
if (contextError) {
|
|
1652
1606
|
if (contextError === "prompt_too_long") {
|
|
1653
|
-
await toast.info("Context too long - use /compact to reduce size, or trim your request", { variant: "warning" });
|
|
1607
|
+
await toast.info("Context too long - use /compact to reduce size, or trim your request", { variant: "warning", debounceMs: 10000, debounceKey: "context-too-long" });
|
|
1654
1608
|
}
|
|
1655
1609
|
else if (contextError === "tool_pairing") {
|
|
1656
|
-
await toast.info("Tool call/result mismatch - use /compact to fix, or /undo last message", { variant: "warning" });
|
|
1610
|
+
await toast.info("Tool call/result mismatch - use /compact to fix, or /undo last message", { variant: "warning", debounceMs: 10000, debounceKey: "tool-pairing-error" });
|
|
1657
1611
|
}
|
|
1658
1612
|
}
|
|
1659
1613
|
return transformedResponse;
|
|
@@ -1703,11 +1657,11 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1703
1657
|
pushDebug(`endpoint-error: cooldown ${cooldownMs}ms after ${failures} failures`);
|
|
1704
1658
|
}
|
|
1705
1659
|
if (accountCount > 1) {
|
|
1706
|
-
await showToast(`Request failed for ${accountLabel} (${errorMsg}). Switching account in 5s...`, "error");
|
|
1660
|
+
await showToast(`Request failed for ${accountLabel} (${errorMsg}). Switching account in 5s...`, "error", "normal");
|
|
1707
1661
|
await sleep(SWITCH_ACCOUNT_DELAY_MS, abortSignal);
|
|
1708
1662
|
}
|
|
1709
1663
|
else {
|
|
1710
|
-
await showToast(`Request failed: ${errorMsg}. Retrying in 5s...`, "error");
|
|
1664
|
+
await showToast(`Request failed: ${errorMsg}. Retrying in 5s...`, "error", "verbose");
|
|
1711
1665
|
await sleep(SWITCH_ACCOUNT_DELAY_MS, abortSignal);
|
|
1712
1666
|
}
|
|
1713
1667
|
shouldSwitchAccount = true;
|