@cortexkit/opencode-antigravity-auth 1.0.0 → 1.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.
- package/README.md +24 -8
- package/dist/index.js +1450 -467
- package/dist/index.js.map +4 -4
- package/dist/src/plugin/accounts.d.ts +36 -9
- package/dist/src/plugin/accounts.d.ts.map +1 -1
- package/dist/src/plugin/accounts.js +269 -57
- package/dist/src/plugin/accounts.js.map +1 -1
- package/dist/src/plugin/agy-request-metadata.d.ts +2 -0
- package/dist/src/plugin/agy-request-metadata.d.ts.map +1 -0
- package/dist/src/plugin/agy-request-metadata.js +2 -0
- package/dist/src/plugin/agy-request-metadata.js.map +1 -0
- package/dist/src/plugin/auth-doctor.d.ts +1 -1
- package/dist/src/plugin/auth-doctor.d.ts.map +1 -1
- package/dist/src/plugin/auth-doctor.js +9 -0
- package/dist/src/plugin/auth-doctor.js.map +1 -1
- package/dist/src/plugin/debug.d.ts.map +1 -1
- package/dist/src/plugin/debug.js +3 -2
- package/dist/src/plugin/debug.js.map +1 -1
- package/dist/src/plugin/gemini-dump.d.ts.map +1 -1
- package/dist/src/plugin/gemini-dump.js +8 -4
- package/dist/src/plugin/gemini-dump.js.map +1 -1
- package/dist/src/plugin/image-saver.d.ts +2 -21
- package/dist/src/plugin/image-saver.d.ts.map +1 -1
- package/dist/src/plugin/image-saver.js +29 -63
- package/dist/src/plugin/image-saver.js.map +1 -1
- package/dist/src/plugin/request-helpers.d.ts +1 -0
- package/dist/src/plugin/request-helpers.d.ts.map +1 -1
- package/dist/src/plugin/request-helpers.js +9 -4
- package/dist/src/plugin/request-helpers.js.map +1 -1
- package/dist/src/plugin/request.d.ts +15 -4
- package/dist/src/plugin/request.d.ts.map +1 -1
- package/dist/src/plugin/request.js +255 -71
- package/dist/src/plugin/request.js.map +1 -1
- package/dist/src/plugin/session-context.d.ts +21 -0
- package/dist/src/plugin/session-context.d.ts.map +1 -0
- package/dist/src/plugin/session-context.js +63 -0
- package/dist/src/plugin/session-context.js.map +1 -0
- package/dist/src/plugin/storage.d.ts +6 -0
- package/dist/src/plugin/storage.d.ts.map +1 -1
- package/dist/src/plugin/storage.js +27 -6
- package/dist/src/plugin/storage.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 +3 -1
- package/dist/src/plugin/ui/auth-menu.js.map +1 -1
- package/dist/src/plugin/ui/quota-status.d.ts.map +1 -1
- package/dist/src/plugin/ui/quota-status.js +2 -1
- package/dist/src/plugin/ui/quota-status.js.map +1 -1
- package/dist/src/plugin.d.ts +16 -0
- package/dist/src/plugin.d.ts.map +1 -1
- package/dist/src/plugin.js +288 -102
- package/dist/src/plugin.js.map +1 -1
- package/package.json +2 -2
- package/dist/src/plugin/transform/claude.d.ts +0 -92
- package/dist/src/plugin/transform/claude.d.ts.map +0 -1
- package/dist/src/plugin/transform/claude.js +0 -280
- package/dist/src/plugin/transform/claude.js.map +0 -1
- package/dist/src/plugin/transform/gemini.d.ts +0 -100
- package/dist/src/plugin/transform/gemini.d.ts.map +0 -1
- package/dist/src/plugin/transform/gemini.js +0 -446
- package/dist/src/plugin/transform/gemini.js.map +0 -1
package/dist/src/plugin.js
CHANGED
|
@@ -9,9 +9,9 @@ import { fetchWithAgyCliTransport } from "./plugin/agy-transport";
|
|
|
9
9
|
import { buildFingerprintHeaders, getSessionFingerprint } from "./plugin/fingerprint";
|
|
10
10
|
import { clearProvisionFailedKeys, ensureProjectContext } from "./plugin/project";
|
|
11
11
|
import { startAntigravityDebugRequest, logAntigravityDebugResponse, logAccountContext, logRateLimitEvent, logRateLimitSnapshot, logResponseBody, logModelFamily, isDebugEnabled, getLogFilePath, initializeDebug, } from "./plugin/debug";
|
|
12
|
-
import { buildThinkingWarmupBody, getLastCacheStats, isGenerativeLanguageRequest, prepareAntigravityRequest, transformAntigravityResponse, } from "./plugin/request";
|
|
12
|
+
import { buildThinkingWarmupBody, getLastCacheStats, isGenerativeLanguageRequest, getImageModelLocalTitle, prepareAntigravityRequest, transformAntigravityResponse, } from "./plugin/request";
|
|
13
13
|
import { resolveModelWithTier } from "./plugin/transform/model-resolver";
|
|
14
|
-
import { isEmptyResponseBody, createSyntheticErrorResponse, } from "./plugin/request-helpers";
|
|
14
|
+
import { isEmptyResponseBody, createSyntheticErrorResponse, createSyntheticTextResponse, } from "./plugin/request-helpers";
|
|
15
15
|
import { AntigravityTokenRefreshError, refreshAccessToken } from "./plugin/token";
|
|
16
16
|
import { startOAuthListener } from "./plugin/server";
|
|
17
17
|
import { clearAccounts, loadAccounts, saveAccounts, saveAccountsReplace } from "./plugin/storage";
|
|
@@ -30,6 +30,8 @@ import { initHealthTracker, getHealthTracker, initTokenTracker, getTokenTracker
|
|
|
30
30
|
import { getAntigravityVersionResolution, initAntigravityVersion } from "./plugin/version";
|
|
31
31
|
import { executeSearch } from "./plugin/search";
|
|
32
32
|
import { resolvePromptContext } from "./plugin/prompt-context";
|
|
33
|
+
import { AgySessionRegistry, extractOpenCodeSessionIdentity } from "./plugin/session-context";
|
|
34
|
+
import { buildAgyAgentRequestMetadata, createAgyRequestSessionContext, orderAgyRequestPayloadInPlace, } from "./plugin/agy-request-metadata";
|
|
33
35
|
import { dumpGeminiRequest, executeGeminiDumpCommand, GEMINI_DUMP_COMMAND_NAME, noteGeminiDumpResponse, parseGeminiDumpCommandAction, setGeminiDumpEnabled, } from "./plugin/gemini-dump";
|
|
34
36
|
import { getAntigravityOpencodeModelIds, OPENCODE_MODEL_DEFINITIONS } from "./plugin/model-registry";
|
|
35
37
|
const MAX_OAUTH_ACCOUNTS = 10;
|
|
@@ -46,10 +48,6 @@ function getCapacityBackoffDelay(consecutiveFailures) {
|
|
|
46
48
|
}
|
|
47
49
|
const warmupAttemptedSessionIds = new Set();
|
|
48
50
|
const warmupSucceededSessionIds = new Set();
|
|
49
|
-
// Track if this plugin instance is running in a child session (subagent, background task)
|
|
50
|
-
// Used to filter toasts based on toast_scope config
|
|
51
|
-
let isChildSession = false;
|
|
52
|
-
let childSessionParentID = undefined;
|
|
53
51
|
const log = createLogger("plugin");
|
|
54
52
|
// Module-level toast debounce to persist across requests (fixes toast spam)
|
|
55
53
|
const rateLimitToastCooldowns = new Map();
|
|
@@ -264,10 +262,12 @@ function selectBestVerificationUrl(urls) {
|
|
|
264
262
|
});
|
|
265
263
|
return unique[0];
|
|
266
264
|
}
|
|
267
|
-
function
|
|
265
|
+
function extractAccountAccessErrorDetails(bodyText) {
|
|
268
266
|
const decodedBody = decodeEscapedText(bodyText);
|
|
269
267
|
const lowerBody = decodedBody.toLowerCase();
|
|
270
268
|
let validationRequired = lowerBody.includes("validation_required");
|
|
269
|
+
const ineligiblePattern = /(^|[^a-z0-9_])account_ineligible([^a-z0-9_]|$)/i;
|
|
270
|
+
let accountIneligible = ineligiblePattern.test(decodedBody);
|
|
271
271
|
let message;
|
|
272
272
|
const verificationUrls = new Set();
|
|
273
273
|
const collectUrlsFromText = (text) => {
|
|
@@ -312,6 +312,9 @@ function extractVerificationErrorDetails(bodyText) {
|
|
|
312
312
|
if (lowerValue.includes("validation_required")) {
|
|
313
313
|
validationRequired = true;
|
|
314
314
|
}
|
|
315
|
+
if (ineligiblePattern.test(normalizedValue)) {
|
|
316
|
+
accountIneligible = true;
|
|
317
|
+
}
|
|
315
318
|
if (!message &&
|
|
316
319
|
(lowerKey.includes("message") || lowerKey.includes("detail") || lowerKey.includes("description"))) {
|
|
317
320
|
message = normalizedValue;
|
|
@@ -352,17 +355,68 @@ function extractVerificationErrorDetails(bodyText) {
|
|
|
352
355
|
const fallback = decodedBody
|
|
353
356
|
.split("\n")
|
|
354
357
|
.map((line) => line.trim())
|
|
355
|
-
.find((line) => line && !line.startsWith("data:") && /(verify|validation|required)/i.test(line));
|
|
358
|
+
.find((line) => line && !line.startsWith("data:") && /(verify|validation|required|ineligible)/i.test(line));
|
|
356
359
|
if (fallback) {
|
|
357
360
|
message = fallback;
|
|
358
361
|
}
|
|
359
362
|
}
|
|
360
363
|
return {
|
|
361
364
|
validationRequired,
|
|
365
|
+
accountIneligible,
|
|
362
366
|
message,
|
|
363
367
|
verifyUrl: selectBestVerificationUrl([...verificationUrls]),
|
|
364
368
|
};
|
|
365
369
|
}
|
|
370
|
+
function buildAccountAccessProbeRequest(projectId) {
|
|
371
|
+
const wireModel = "gemini-3.5-flash-low";
|
|
372
|
+
const request = {
|
|
373
|
+
contents: [{ role: "user", parts: [{ text: "ping" }] }],
|
|
374
|
+
generationConfig: { maxOutputTokens: 1, temperature: 0 },
|
|
375
|
+
};
|
|
376
|
+
const requestMetadata = buildAgyAgentRequestMetadata(createAgyRequestSessionContext(""), request, wireModel);
|
|
377
|
+
request.labels = requestMetadata.labels;
|
|
378
|
+
request.sessionId = requestMetadata.sessionId;
|
|
379
|
+
orderAgyRequestPayloadInPlace(request);
|
|
380
|
+
return {
|
|
381
|
+
project: projectId,
|
|
382
|
+
requestId: requestMetadata.requestId,
|
|
383
|
+
request,
|
|
384
|
+
model: wireModel,
|
|
385
|
+
userAgent: "antigravity",
|
|
386
|
+
requestType: "agent",
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
async function interpretAccountAccessProbeResponse(response) {
|
|
390
|
+
if (response.ok) {
|
|
391
|
+
await response.body?.cancel().catch(() => { });
|
|
392
|
+
return { status: "ok", message: "Account verification check passed." };
|
|
393
|
+
}
|
|
394
|
+
let responseBody = "";
|
|
395
|
+
try {
|
|
396
|
+
responseBody = await response.text();
|
|
397
|
+
}
|
|
398
|
+
catch {
|
|
399
|
+
responseBody = "";
|
|
400
|
+
}
|
|
401
|
+
const extracted = extractAccountAccessErrorDetails(responseBody);
|
|
402
|
+
if (response.status === 403 && extracted.accountIneligible) {
|
|
403
|
+
return {
|
|
404
|
+
status: "ineligible",
|
|
405
|
+
message: extracted.message ?? "Google marked this account as ineligible for Antigravity.",
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
if (response.status === 403 && extracted.validationRequired) {
|
|
409
|
+
return {
|
|
410
|
+
status: "verification-required",
|
|
411
|
+
message: extracted.message ?? "Google requires additional account verification.",
|
|
412
|
+
verifyUrl: extracted.verifyUrl,
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
return {
|
|
416
|
+
status: "error",
|
|
417
|
+
message: extracted.message ?? `Request failed (${response.status} ${response.statusText}).`,
|
|
418
|
+
};
|
|
419
|
+
}
|
|
366
420
|
async function verifyAccountAccess(account, client, providerId) {
|
|
367
421
|
const parsed = parseRefreshParts(account.refreshToken);
|
|
368
422
|
if (!parsed.refreshToken) {
|
|
@@ -403,18 +457,7 @@ async function verifyAccountAccess(account, client, providerId) {
|
|
|
403
457
|
"Content-Type": "application/json",
|
|
404
458
|
"Accept-Encoding": "gzip",
|
|
405
459
|
};
|
|
406
|
-
const requestBody =
|
|
407
|
-
project: projectId,
|
|
408
|
-
requestId: `agent/${crypto.randomUUID()}/${Date.now()}/${crypto.randomUUID()}/2`,
|
|
409
|
-
request: {
|
|
410
|
-
model: "gemini-3-flash",
|
|
411
|
-
contents: [{ role: "user", parts: [{ text: "ping" }] }],
|
|
412
|
-
generationConfig: { maxOutputTokens: 1, temperature: 0 },
|
|
413
|
-
},
|
|
414
|
-
model: "gemini-3-flash",
|
|
415
|
-
userAgent: "antigravity",
|
|
416
|
-
requestType: "agent",
|
|
417
|
-
};
|
|
460
|
+
const requestBody = buildAccountAccessProbeRequest(projectId);
|
|
418
461
|
const controller = new AbortController();
|
|
419
462
|
const timeoutId = setTimeout(() => controller.abort(), 20000);
|
|
420
463
|
let response;
|
|
@@ -434,29 +477,7 @@ async function verifyAccountAccess(account, client, providerId) {
|
|
|
434
477
|
finally {
|
|
435
478
|
clearTimeout(timeoutId);
|
|
436
479
|
}
|
|
437
|
-
|
|
438
|
-
try {
|
|
439
|
-
responseBody = await response.text();
|
|
440
|
-
}
|
|
441
|
-
catch {
|
|
442
|
-
responseBody = "";
|
|
443
|
-
}
|
|
444
|
-
if (response.ok) {
|
|
445
|
-
return { status: "ok", message: "Account verification check passed." };
|
|
446
|
-
}
|
|
447
|
-
const extracted = extractVerificationErrorDetails(responseBody);
|
|
448
|
-
if (response.status === 403 && extracted.validationRequired) {
|
|
449
|
-
return {
|
|
450
|
-
status: "blocked",
|
|
451
|
-
message: extracted.message ?? "Google requires additional account verification.",
|
|
452
|
-
verifyUrl: extracted.verifyUrl,
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
const fallbackMessage = extracted.message ?? `Request failed (${response.status} ${response.statusText}).`;
|
|
456
|
-
return {
|
|
457
|
-
status: "error",
|
|
458
|
-
message: fallbackMessage,
|
|
459
|
-
};
|
|
480
|
+
return interpretAccountAccessProbeResponse(response);
|
|
460
481
|
}
|
|
461
482
|
async function promptAccountIndexForVerification(accounts) {
|
|
462
483
|
const { createInterface } = await import("node:readline/promises");
|
|
@@ -499,12 +520,22 @@ async function promptOpenVerificationUrl() {
|
|
|
499
520
|
function markStoredAccountVerificationRequired(account, reason, verifyUrl) {
|
|
500
521
|
let changed = false;
|
|
501
522
|
const wasVerificationRequired = account.verificationRequired === true;
|
|
523
|
+
const timestamp = Date.now();
|
|
502
524
|
if (!wasVerificationRequired) {
|
|
503
525
|
account.verificationRequired = true;
|
|
504
526
|
changed = true;
|
|
505
527
|
}
|
|
506
528
|
if (!wasVerificationRequired || account.verificationRequiredAt === undefined) {
|
|
507
|
-
account.verificationRequiredAt =
|
|
529
|
+
account.verificationRequiredAt = timestamp;
|
|
530
|
+
changed = true;
|
|
531
|
+
}
|
|
532
|
+
if (account.accountIneligible === true ||
|
|
533
|
+
account.accountIneligibleAt !== undefined ||
|
|
534
|
+
account.accountIneligibleReason !== undefined) {
|
|
535
|
+
account.accountIneligible = false;
|
|
536
|
+
account.accountIneligibleAt = undefined;
|
|
537
|
+
account.accountIneligibleReason = undefined;
|
|
538
|
+
account.eligibilityStateUpdatedAt = timestamp;
|
|
508
539
|
changed = true;
|
|
509
540
|
}
|
|
510
541
|
const normalizedReason = reason.trim();
|
|
@@ -523,8 +554,31 @@ function markStoredAccountVerificationRequired(account, reason, verifyUrl) {
|
|
|
523
554
|
}
|
|
524
555
|
return changed;
|
|
525
556
|
}
|
|
526
|
-
function
|
|
557
|
+
function markStoredAccountIneligible(account, reason) {
|
|
558
|
+
const timestamp = Date.now();
|
|
559
|
+
const normalizedReason = reason.trim() || "Google marked this account as ineligible.";
|
|
560
|
+
const changed = account.accountIneligible !== true ||
|
|
561
|
+
account.accountIneligibleReason !== normalizedReason ||
|
|
562
|
+
account.verificationRequired === true ||
|
|
563
|
+
account.verificationRequiredAt !== undefined ||
|
|
564
|
+
account.verificationRequiredReason !== undefined ||
|
|
565
|
+
account.verificationUrl !== undefined ||
|
|
566
|
+
account.enabled !== false;
|
|
567
|
+
account.accountIneligible = true;
|
|
568
|
+
account.accountIneligibleAt = timestamp;
|
|
569
|
+
account.accountIneligibleReason = normalizedReason;
|
|
570
|
+
account.eligibilityStateUpdatedAt = timestamp;
|
|
571
|
+
account.verificationRequired = false;
|
|
572
|
+
account.verificationRequiredAt = undefined;
|
|
573
|
+
account.verificationRequiredReason = undefined;
|
|
574
|
+
account.verificationUrl = undefined;
|
|
575
|
+
account.enabled = false;
|
|
576
|
+
return changed;
|
|
577
|
+
}
|
|
578
|
+
function clearStoredAccountAccessBlocks(account, enableIfBlocked = false) {
|
|
527
579
|
const wasVerificationRequired = account.verificationRequired === true;
|
|
580
|
+
const wasIneligible = account.accountIneligible === true;
|
|
581
|
+
const wasAccessBlocked = wasVerificationRequired || wasIneligible;
|
|
528
582
|
let changed = false;
|
|
529
583
|
if (account.verificationRequired !== false) {
|
|
530
584
|
account.verificationRequired = false;
|
|
@@ -542,11 +596,27 @@ function clearStoredAccountVerificationRequired(account, enableIfRequired = fals
|
|
|
542
596
|
account.verificationUrl = undefined;
|
|
543
597
|
changed = true;
|
|
544
598
|
}
|
|
545
|
-
if (
|
|
599
|
+
if (account.accountIneligible !== false) {
|
|
600
|
+
account.accountIneligible = false;
|
|
601
|
+
changed = true;
|
|
602
|
+
}
|
|
603
|
+
if (account.accountIneligibleAt !== undefined) {
|
|
604
|
+
account.accountIneligibleAt = undefined;
|
|
605
|
+
changed = true;
|
|
606
|
+
}
|
|
607
|
+
if (account.accountIneligibleReason !== undefined) {
|
|
608
|
+
account.accountIneligibleReason = undefined;
|
|
609
|
+
changed = true;
|
|
610
|
+
}
|
|
611
|
+
if (wasIneligible || account.eligibilityStateUpdatedAt !== undefined) {
|
|
612
|
+
account.eligibilityStateUpdatedAt = Date.now();
|
|
613
|
+
changed = true;
|
|
614
|
+
}
|
|
615
|
+
if (enableIfBlocked && wasAccessBlocked && account.enabled === false) {
|
|
546
616
|
account.enabled = true;
|
|
547
617
|
changed = true;
|
|
548
618
|
}
|
|
549
|
-
return { changed,
|
|
619
|
+
return { changed, wasAccessBlocked };
|
|
550
620
|
}
|
|
551
621
|
async function promptOAuthCallbackValue(message) {
|
|
552
622
|
const { createInterface } = await import("node:readline/promises");
|
|
@@ -1044,6 +1114,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1044
1114
|
// Load configuration from files and environment variables
|
|
1045
1115
|
const config = loadConfig(directory);
|
|
1046
1116
|
initRuntimeConfig(config);
|
|
1117
|
+
const agySessionRegistry = new AgySessionRegistry(directory);
|
|
1047
1118
|
// Cached getAuth function for tool access
|
|
1048
1119
|
let cachedGetAuth = null;
|
|
1049
1120
|
// Initialize debug with config
|
|
@@ -1087,31 +1158,36 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1087
1158
|
const eventHandler = async (input) => {
|
|
1088
1159
|
// Forward to update checker
|
|
1089
1160
|
await updateChecker.event(input);
|
|
1090
|
-
// Track if this is a child session (subagent, background task)
|
|
1091
|
-
// This is used to filter toasts based on toast_scope config
|
|
1092
1161
|
if (input.event.type === "session.created") {
|
|
1093
|
-
// Log previous session's quota summary before resetting for new session
|
|
1094
|
-
const prevSummary = activeAccountManager?.getSessionSummary();
|
|
1095
|
-
if (prevSummary && (prevSummary.totalClaude > 0 || prevSummary.totalGemini > 0)) {
|
|
1096
|
-
log.debug("prev-session-quota-summary", {
|
|
1097
|
-
durationMinutes: prevSummary.durationMinutes,
|
|
1098
|
-
totalClaude: prevSummary.totalClaude,
|
|
1099
|
-
totalGemini: prevSummary.totalGemini,
|
|
1100
|
-
requestsPerHour: prevSummary.requestsPerHour,
|
|
1101
|
-
accountsUsed: prevSummary.accountsUsed,
|
|
1102
|
-
});
|
|
1103
|
-
}
|
|
1104
1162
|
const props = input.event.properties;
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1163
|
+
const sessionId = props?.info?.id;
|
|
1164
|
+
const parentSessionId = props?.info?.parentID ?? null;
|
|
1165
|
+
if (sessionId) {
|
|
1166
|
+
agySessionRegistry.register(sessionId, parentSessionId);
|
|
1167
|
+
}
|
|
1168
|
+
if (parentSessionId) {
|
|
1169
|
+
log.debug("child-session-detected", { sessionId, parentID: parentSessionId });
|
|
1109
1170
|
}
|
|
1110
1171
|
else {
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1172
|
+
const prevSummary = activeAccountManager?.getSessionSummary();
|
|
1173
|
+
if (prevSummary && (prevSummary.totalClaude > 0 || prevSummary.totalGemini > 0)) {
|
|
1174
|
+
log.debug("prev-session-quota-summary", {
|
|
1175
|
+
durationMinutes: prevSummary.durationMinutes,
|
|
1176
|
+
totalClaude: prevSummary.totalClaude,
|
|
1177
|
+
totalGemini: prevSummary.totalGemini,
|
|
1178
|
+
requestsPerHour: prevSummary.requestsPerHour,
|
|
1179
|
+
accountsUsed: prevSummary.accountsUsed,
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
1182
|
+
log.debug("root-session-detected", { sessionId });
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
if (input.event.type === "session.deleted") {
|
|
1186
|
+
const props = input.event.properties;
|
|
1187
|
+
const sessionId = props?.sessionID ?? props?.info?.id;
|
|
1188
|
+
if (sessionId) {
|
|
1189
|
+
agySessionRegistry.delete(sessionId);
|
|
1190
|
+
activeAccountManager?.deleteSessionState(sessionId);
|
|
1115
1191
|
}
|
|
1116
1192
|
}
|
|
1117
1193
|
// Handle session recovery
|
|
@@ -1140,8 +1216,13 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1140
1216
|
}).catch(() => { });
|
|
1141
1217
|
// Show success toast (respects toast_scope for child sessions)
|
|
1142
1218
|
const successToast = getRecoverySuccessToast();
|
|
1143
|
-
|
|
1144
|
-
|
|
1219
|
+
const isChildRecovery = agySessionRegistry.getParentSessionId(sessionID) !== null;
|
|
1220
|
+
log.debug("recovery-toast", {
|
|
1221
|
+
...successToast,
|
|
1222
|
+
isChildSession: isChildRecovery,
|
|
1223
|
+
toastScope: config.toast_scope,
|
|
1224
|
+
});
|
|
1225
|
+
if (!(config.toast_scope === "root_only" && isChildRecovery)) {
|
|
1145
1226
|
await client.tui.showToast({
|
|
1146
1227
|
body: {
|
|
1147
1228
|
title: successToast.title,
|
|
@@ -1317,6 +1398,46 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1317
1398
|
if (!isOAuthAuth(latestAuth)) {
|
|
1318
1399
|
return fetch(input, init);
|
|
1319
1400
|
}
|
|
1401
|
+
// Normalize Request/URL inputs to (urlString, init) so the
|
|
1402
|
+
// string-based transform pipeline sees the real method/headers/body.
|
|
1403
|
+
// Without this, fetch(new Request(...)) would carry its payload on the
|
|
1404
|
+
// Request object where our string path can't read it.
|
|
1405
|
+
if (typeof input !== "string") {
|
|
1406
|
+
if (input instanceof Request) {
|
|
1407
|
+
const req = input;
|
|
1408
|
+
const headers = new Headers(req.headers);
|
|
1409
|
+
if (init?.headers) {
|
|
1410
|
+
new Headers(init.headers).forEach((v, k) => headers.set(k, v));
|
|
1411
|
+
}
|
|
1412
|
+
const bodyBuffer = req.body ? await req.clone().arrayBuffer() : undefined;
|
|
1413
|
+
init = {
|
|
1414
|
+
method: init?.method ?? req.method,
|
|
1415
|
+
headers,
|
|
1416
|
+
body: init?.body ?? (bodyBuffer ? Buffer.from(bodyBuffer) : undefined),
|
|
1417
|
+
signal: init?.signal ?? req.signal,
|
|
1418
|
+
};
|
|
1419
|
+
input = req.url;
|
|
1420
|
+
}
|
|
1421
|
+
else {
|
|
1422
|
+
input = String(input.href ?? input);
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
const localImageTitle = getImageModelLocalTitle(input, init);
|
|
1426
|
+
if (localImageTitle !== undefined) {
|
|
1427
|
+
return createSyntheticTextResponse(localImageTitle, {
|
|
1428
|
+
"X-Antigravity-Response-Type": "local_title",
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
1431
|
+
const requestSessionIdentity = extractOpenCodeSessionIdentity(init?.headers);
|
|
1432
|
+
const agyRequestScope = agySessionRegistry.beginRequest(requestSessionIdentity);
|
|
1433
|
+
const agyRequestSession = agyRequestScope.session;
|
|
1434
|
+
const accountSessionIdentity = requestSessionIdentity.sessionId
|
|
1435
|
+
? {
|
|
1436
|
+
id: requestSessionIdentity.sessionId,
|
|
1437
|
+
parentId: requestSessionIdentity.parentSessionId,
|
|
1438
|
+
}
|
|
1439
|
+
: undefined;
|
|
1440
|
+
const isChildRequest = requestSessionIdentity.parentSessionId !== null;
|
|
1320
1441
|
if (accountManager.getAccountCount() === 0) {
|
|
1321
1442
|
return createSyntheticErrorResponse("No Antigravity accounts configured. Run `opencode auth login`.", "unknown");
|
|
1322
1443
|
}
|
|
@@ -1330,6 +1451,11 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1330
1451
|
debugLines.push(line);
|
|
1331
1452
|
};
|
|
1332
1453
|
pushDebug(`request=${urlString}`);
|
|
1454
|
+
if (requestSessionIdentity.sessionId) {
|
|
1455
|
+
pushDebug(`[Session] id=${requestSessionIdentity.sessionId}` +
|
|
1456
|
+
` parent=${requestSessionIdentity.parentSessionId ?? "none"}` +
|
|
1457
|
+
` child=${isChildRequest}`);
|
|
1458
|
+
}
|
|
1333
1459
|
const cachedStats = getLastCacheStats();
|
|
1334
1460
|
if (cachedStats) {
|
|
1335
1461
|
const label = cachedStats.hitRate > 0 ? "HIT" : "MISS";
|
|
@@ -1351,14 +1477,18 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1351
1477
|
// Helper to show toast without blocking on abort (respects quiet_mode and toast_scope)
|
|
1352
1478
|
const showToast = async (message, variant) => {
|
|
1353
1479
|
// Always log to debug regardless of toast filtering
|
|
1354
|
-
log.debug("toast", { message, variant, isChildSession, toastScope });
|
|
1480
|
+
log.debug("toast", { message, variant, isChildSession: isChildRequest, toastScope });
|
|
1355
1481
|
if (quietMode)
|
|
1356
1482
|
return;
|
|
1357
1483
|
if (abortSignal?.aborted)
|
|
1358
1484
|
return;
|
|
1359
1485
|
// Filter toasts for child sessions when toast_scope is "root_only"
|
|
1360
|
-
if (toastScope === "root_only" &&
|
|
1361
|
-
log.debug("toast-suppressed-child-session", {
|
|
1486
|
+
if (toastScope === "root_only" && isChildRequest) {
|
|
1487
|
+
log.debug("toast-suppressed-child-session", {
|
|
1488
|
+
message,
|
|
1489
|
+
variant,
|
|
1490
|
+
parentID: requestSessionIdentity.parentSessionId,
|
|
1491
|
+
});
|
|
1362
1492
|
return;
|
|
1363
1493
|
}
|
|
1364
1494
|
if (variant === "warning" && message.toLowerCase().includes("rate")) {
|
|
@@ -1395,10 +1525,10 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1395
1525
|
return createSyntheticErrorResponse("No Antigravity accounts available. Run `opencode auth login`.", model ?? "unknown");
|
|
1396
1526
|
}
|
|
1397
1527
|
const softQuotaCacheTtlMs = computeSoftQuotaCacheTtlMs(config.soft_quota_cache_ttl_minutes, config.quota_refresh_interval_minutes);
|
|
1398
|
-
let account = accountManager.getCurrentOrNextForFamily(family, model, config.account_selection_strategy, preferredHeaderStyle, config.pid_offset_enabled, config.soft_quota_threshold_percent, softQuotaCacheTtlMs);
|
|
1528
|
+
let account = accountManager.getCurrentOrNextForFamily(family, model, config.account_selection_strategy, preferredHeaderStyle, config.pid_offset_enabled, config.soft_quota_threshold_percent, softQuotaCacheTtlMs, accountSessionIdentity);
|
|
1399
1529
|
if (!account && allowQuotaFallback) {
|
|
1400
1530
|
const alternateHeaderStyle = preferredHeaderStyle === "antigravity" ? "gemini-cli" : "antigravity";
|
|
1401
|
-
account = accountManager.getCurrentOrNextForFamily(family, model, config.account_selection_strategy, alternateHeaderStyle, config.pid_offset_enabled, config.soft_quota_threshold_percent, softQuotaCacheTtlMs);
|
|
1531
|
+
account = accountManager.getCurrentOrNextForFamily(family, model, config.account_selection_strategy, alternateHeaderStyle, config.pid_offset_enabled, config.soft_quota_threshold_percent, softQuotaCacheTtlMs, accountSessionIdentity);
|
|
1402
1532
|
if (account) {
|
|
1403
1533
|
pushDebug(`selected-by-fallback idx=${account.index} preferred=${preferredHeaderStyle} alternate=${alternateHeaderStyle}`);
|
|
1404
1534
|
}
|
|
@@ -1464,7 +1594,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1464
1594
|
pushDebug(`account-switch: ${previousAccountIndex} → ${account.index}, warmup=${needsCacheWarmup}`);
|
|
1465
1595
|
}
|
|
1466
1596
|
previousAccountIndex = account.index;
|
|
1467
|
-
accountManager.recordSessionUsage(account.index);
|
|
1597
|
+
accountManager.recordSessionUsage(account.index, accountSessionIdentity);
|
|
1468
1598
|
if (isDebugEnabled()) {
|
|
1469
1599
|
logAccountContext("Selected", {
|
|
1470
1600
|
index: account.index,
|
|
@@ -1515,7 +1645,9 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1515
1645
|
if (removed) {
|
|
1516
1646
|
log.warn("Removed revoked account from pool - reauthenticate via `opencode auth login`");
|
|
1517
1647
|
try {
|
|
1518
|
-
|
|
1648
|
+
// Replace (not merge) so the revoked account is not
|
|
1649
|
+
// resurrected from disk by mergeAccountStorage.
|
|
1650
|
+
await accountManager.saveToDiskReplace();
|
|
1519
1651
|
}
|
|
1520
1652
|
catch (persistError) {
|
|
1521
1653
|
log.error("Failed to persist revoked account removal", { error: String(persistError) });
|
|
@@ -1770,6 +1902,8 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
1770
1902
|
claudeToolHardening: config.claude_tool_hardening,
|
|
1771
1903
|
claudePromptAutoCaching: config.claude_prompt_auto_caching,
|
|
1772
1904
|
fingerprint: account.fingerprint,
|
|
1905
|
+
agySession: agyRequestSession,
|
|
1906
|
+
agyRequestTimestamp: agyRequestScope.timestamp,
|
|
1773
1907
|
});
|
|
1774
1908
|
const originalUrl = toUrlString(input);
|
|
1775
1909
|
const resolvedUrl = toUrlString(prepared.request);
|
|
@@ -2015,7 +2149,23 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
2015
2149
|
resetAccountFailureState(account.index);
|
|
2016
2150
|
if (response.status === 403) {
|
|
2017
2151
|
const errorBodyText = await response.clone().text().catch(() => "");
|
|
2018
|
-
const extracted =
|
|
2152
|
+
const extracted = extractAccountAccessErrorDetails(errorBodyText);
|
|
2153
|
+
if (extracted.accountIneligible) {
|
|
2154
|
+
const ineligibleReason = extracted.message ??
|
|
2155
|
+
"Google marked this account as ineligible for Antigravity.";
|
|
2156
|
+
accountManager.markAccountIneligible(account.index, ineligibleReason);
|
|
2157
|
+
const label = account.email || `Account ${account.index + 1}`;
|
|
2158
|
+
if (accountManager.shouldShowAccountToast(account.index, 60000)) {
|
|
2159
|
+
await showToast(`${label} is not eligible for Antigravity and has been disabled. ` +
|
|
2160
|
+
"Recheck it from opencode auth login > Verify accounts.", "warning");
|
|
2161
|
+
accountManager.markToastShown(account.index);
|
|
2162
|
+
}
|
|
2163
|
+
pushDebug(`account-ineligible: disabled account ${account.index}`);
|
|
2164
|
+
getHealthTracker().recordFailure(account.index);
|
|
2165
|
+
lastFailure = createFailureContext(response);
|
|
2166
|
+
shouldSwitchAccount = true;
|
|
2167
|
+
break;
|
|
2168
|
+
}
|
|
2019
2169
|
if (extracted.validationRequired) {
|
|
2020
2170
|
const verificationReason = extracted.message ?? "Google requires account verification.";
|
|
2021
2171
|
const cooldownMs = 10 * 60 * 1000;
|
|
@@ -2051,13 +2201,14 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
2051
2201
|
// Proactive rotation: if current account quota is low, pre-switch
|
|
2052
2202
|
// to a warm-cache account so the NEXT request avoids a cold cache miss
|
|
2053
2203
|
const proactiveThreshold = config.proactive_rotation_threshold_percent ?? 20;
|
|
2054
|
-
if (proactiveThreshold > 0 && accountManager.shouldProactivelyRotate(family, model, proactiveThreshold, softQuotaCacheTtlMs)) {
|
|
2055
|
-
const rotated = accountManager.proactivelyRotateForFamily(family, model, headerStyle, config.soft_quota_threshold_percent, softQuotaCacheTtlMs);
|
|
2204
|
+
if (proactiveThreshold > 0 && accountManager.shouldProactivelyRotate(family, model, proactiveThreshold, softQuotaCacheTtlMs, accountSessionIdentity)) {
|
|
2205
|
+
const rotated = accountManager.proactivelyRotateForFamily(family, model, headerStyle, config.soft_quota_threshold_percent, softQuotaCacheTtlMs, accountSessionIdentity);
|
|
2056
2206
|
if (rotated) {
|
|
2057
2207
|
const remaining = account.cachedQuota?.[resolveQuotaGroup(family, model)]?.remainingFraction;
|
|
2058
2208
|
const remainingPct = remaining != null ? `${(remaining * 100).toFixed(1)}%` : "?";
|
|
2059
2209
|
pushDebug(`[ProactiveRotation] account ${account.index} quota ${remainingPct} < ${proactiveThreshold}%, pre-switched to account ${rotated.index} for next request`);
|
|
2060
|
-
pushDebug(`[ProactiveRotation] ${account.index} → ${rotated.index}
|
|
2210
|
+
pushDebug(`[ProactiveRotation] ${account.index} → ${rotated.index}` +
|
|
2211
|
+
` (warm=${accountManager.wasUsedInSession(rotated.index, accountSessionIdentity)})`);
|
|
2061
2212
|
}
|
|
2062
2213
|
}
|
|
2063
2214
|
}
|
|
@@ -2131,7 +2282,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
2131
2282
|
// Post-request quota state: show cached remaining quota for this account
|
|
2132
2283
|
const cachedQuota = account.cachedQuota;
|
|
2133
2284
|
if (cachedQuota) {
|
|
2134
|
-
const quotaFamily = family
|
|
2285
|
+
const quotaFamily = resolveQuotaGroup(family, model);
|
|
2135
2286
|
const groupQuota = cachedQuota[quotaFamily];
|
|
2136
2287
|
if (groupQuota?.remainingFraction != null) {
|
|
2137
2288
|
const pct = Math.round(groupQuota.remainingFraction * 100);
|
|
@@ -2247,26 +2398,29 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
2247
2398
|
while (true) {
|
|
2248
2399
|
const now = Date.now();
|
|
2249
2400
|
const existingAccounts = existingStorage.accounts.map((acc, idx) => {
|
|
2250
|
-
let status =
|
|
2251
|
-
if (acc.
|
|
2252
|
-
status =
|
|
2401
|
+
let status = "unknown";
|
|
2402
|
+
if (acc.accountIneligible) {
|
|
2403
|
+
status = "ineligible";
|
|
2404
|
+
}
|
|
2405
|
+
else if (acc.verificationRequired) {
|
|
2406
|
+
status = "verification-required";
|
|
2253
2407
|
}
|
|
2254
2408
|
else {
|
|
2255
2409
|
const rateLimits = acc.rateLimitResetTimes;
|
|
2256
2410
|
if (rateLimits) {
|
|
2257
|
-
const isRateLimited = Object.values(rateLimits).some((resetTime) => typeof resetTime ===
|
|
2411
|
+
const isRateLimited = Object.values(rateLimits).some((resetTime) => typeof resetTime === "number" && resetTime > now);
|
|
2258
2412
|
if (isRateLimited) {
|
|
2259
|
-
status =
|
|
2413
|
+
status = "rate-limited";
|
|
2260
2414
|
}
|
|
2261
2415
|
else {
|
|
2262
|
-
status =
|
|
2416
|
+
status = "active";
|
|
2263
2417
|
}
|
|
2264
2418
|
}
|
|
2265
2419
|
else {
|
|
2266
|
-
status =
|
|
2420
|
+
status = "active";
|
|
2267
2421
|
}
|
|
2268
2422
|
if (acc.coolingDownUntil && acc.coolingDownUntil > now) {
|
|
2269
|
-
status =
|
|
2423
|
+
status = "rate-limited";
|
|
2270
2424
|
}
|
|
2271
2425
|
}
|
|
2272
2426
|
const cooldownMs = (acc.coolingDownUntil && acc.coolingDownUntil > now)
|
|
@@ -2280,11 +2434,11 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
2280
2434
|
|| (now - acc.cachedQuotaUpdatedAt) > DISPLAY_QUOTA_MAX_AGE_MS;
|
|
2281
2435
|
const displayQuota = quotaIsStale ? undefined : acc.cachedQuota;
|
|
2282
2436
|
const displayPerModelQuota = quotaIsStale ? undefined : acc.cachedPerModelQuota;
|
|
2283
|
-
if (status ===
|
|
2437
|
+
if (status === "active" && displayQuota) {
|
|
2284
2438
|
const groups = Object.values(displayQuota);
|
|
2285
2439
|
const allExhausted = groups.length > 0 && groups.every((group) => typeof group.remainingFraction === "number" && group.remainingFraction <= 0);
|
|
2286
2440
|
if (allExhausted) {
|
|
2287
|
-
status =
|
|
2441
|
+
status = "rate-limited";
|
|
2288
2442
|
}
|
|
2289
2443
|
}
|
|
2290
2444
|
return {
|
|
@@ -2404,6 +2558,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
2404
2558
|
{ name: "Claude", data: groups.claude },
|
|
2405
2559
|
{ name: "Gemini 3 Pro", data: groups["gemini-pro"] },
|
|
2406
2560
|
{ name: "Gemini 3 Flash", data: groups["gemini-flash"] },
|
|
2561
|
+
{ name: "GPT-OSS", data: groups["gpt-oss"] },
|
|
2407
2562
|
].filter(g => g.data);
|
|
2408
2563
|
groupEntries.forEach((g, idx) => {
|
|
2409
2564
|
const isLast = idx === groupEntries.length - 1;
|
|
@@ -2461,10 +2616,16 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
2461
2616
|
if (menuResult.toggleAccountIndex !== undefined) {
|
|
2462
2617
|
const acc = existingStorage.accounts[menuResult.toggleAccountIndex];
|
|
2463
2618
|
if (acc) {
|
|
2464
|
-
|
|
2619
|
+
const shouldEnable = acc.enabled === false;
|
|
2620
|
+
if (shouldEnable && acc.accountIneligible) {
|
|
2621
|
+
console.log(`\n${acc.email || `Account ${menuResult.toggleAccountIndex + 1}`} remains disabled. ` +
|
|
2622
|
+
"Use Verify accounts to recheck eligibility.\n");
|
|
2623
|
+
continue;
|
|
2624
|
+
}
|
|
2625
|
+
acc.enabled = shouldEnable;
|
|
2465
2626
|
await saveAccounts(existingStorage);
|
|
2466
2627
|
activeAccountManager?.setAccountEnabled(menuResult.toggleAccountIndex, acc.enabled);
|
|
2467
|
-
console.log(`\nAccount ${acc.email || menuResult.toggleAccountIndex + 1} ${acc.enabled ?
|
|
2628
|
+
console.log(`\nAccount ${acc.email || menuResult.toggleAccountIndex + 1} ${acc.enabled ? "enabled" : "disabled"}.\n`);
|
|
2468
2629
|
}
|
|
2469
2630
|
}
|
|
2470
2631
|
continue;
|
|
@@ -2479,6 +2640,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
2479
2640
|
console.log(`\nChecking verification status for ${existingStorage.accounts.length} account(s)...\n`);
|
|
2480
2641
|
let okCount = 0;
|
|
2481
2642
|
let blockedCount = 0;
|
|
2643
|
+
let ineligibleCount = 0;
|
|
2482
2644
|
let errorCount = 0;
|
|
2483
2645
|
let storageUpdated = false;
|
|
2484
2646
|
const blockedResults = [];
|
|
@@ -2490,16 +2652,16 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
2490
2652
|
process.stdout.write(`- [${i + 1}/${existingStorage.accounts.length}] ${label} ... `);
|
|
2491
2653
|
const verification = await verifyAccountAccess(account, client, providerId);
|
|
2492
2654
|
if (verification.status === "ok") {
|
|
2493
|
-
const { changed,
|
|
2655
|
+
const { changed, wasAccessBlocked } = clearStoredAccountAccessBlocks(account, true);
|
|
2494
2656
|
if (changed) {
|
|
2495
2657
|
storageUpdated = true;
|
|
2496
2658
|
}
|
|
2497
|
-
activeAccountManager?.
|
|
2659
|
+
activeAccountManager?.clearAccountAccessBlocks(i, wasAccessBlocked);
|
|
2498
2660
|
okCount += 1;
|
|
2499
2661
|
console.log("ok");
|
|
2500
2662
|
continue;
|
|
2501
2663
|
}
|
|
2502
|
-
if (verification.status === "
|
|
2664
|
+
if (verification.status === "verification-required") {
|
|
2503
2665
|
const changed = markStoredAccountVerificationRequired(account, verification.message, verification.verifyUrl);
|
|
2504
2666
|
if (changed) {
|
|
2505
2667
|
storageUpdated = true;
|
|
@@ -2515,13 +2677,24 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
2515
2677
|
});
|
|
2516
2678
|
continue;
|
|
2517
2679
|
}
|
|
2680
|
+
if (verification.status === "ineligible") {
|
|
2681
|
+
const changed = markStoredAccountIneligible(account, verification.message);
|
|
2682
|
+
if (changed) {
|
|
2683
|
+
storageUpdated = true;
|
|
2684
|
+
}
|
|
2685
|
+
activeAccountManager?.markAccountIneligible(i, verification.message);
|
|
2686
|
+
ineligibleCount += 1;
|
|
2687
|
+
console.log("ineligible");
|
|
2688
|
+
continue;
|
|
2689
|
+
}
|
|
2518
2690
|
errorCount += 1;
|
|
2519
2691
|
console.log(`error (${verification.message})`);
|
|
2520
2692
|
}
|
|
2521
2693
|
if (storageUpdated) {
|
|
2522
2694
|
await saveAccounts(existingStorage);
|
|
2523
2695
|
}
|
|
2524
|
-
console.log(`\nVerification summary: ${okCount} ready, ${blockedCount} need verification,
|
|
2696
|
+
console.log(`\nVerification summary: ${okCount} ready, ${blockedCount} need verification, ` +
|
|
2697
|
+
`${ineligibleCount} ineligible, ${errorCount} errors.`);
|
|
2525
2698
|
if (blockedResults.length > 0) {
|
|
2526
2699
|
console.log("\nAccounts needing verification:");
|
|
2527
2700
|
for (const result of blockedResults) {
|
|
@@ -2558,12 +2731,12 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
2558
2731
|
console.log(`\nChecking verification status for ${label}...\n`);
|
|
2559
2732
|
const verification = await verifyAccountAccess(account, client, providerId);
|
|
2560
2733
|
if (verification.status === "ok") {
|
|
2561
|
-
const { changed,
|
|
2734
|
+
const { changed, wasAccessBlocked } = clearStoredAccountAccessBlocks(account, true);
|
|
2562
2735
|
if (changed) {
|
|
2563
2736
|
await saveAccounts(existingStorage);
|
|
2564
2737
|
}
|
|
2565
|
-
activeAccountManager?.
|
|
2566
|
-
if (
|
|
2738
|
+
activeAccountManager?.clearAccountAccessBlocks(verifyAccountIndex, wasAccessBlocked);
|
|
2739
|
+
if (wasAccessBlocked) {
|
|
2567
2740
|
console.log(`✓ ${label} is ready for requests and has been re-enabled.\n`);
|
|
2568
2741
|
}
|
|
2569
2742
|
else {
|
|
@@ -2571,7 +2744,7 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
2571
2744
|
}
|
|
2572
2745
|
continue;
|
|
2573
2746
|
}
|
|
2574
|
-
if (verification.status === "
|
|
2747
|
+
if (verification.status === "verification-required") {
|
|
2575
2748
|
const changed = markStoredAccountVerificationRequired(account, verification.message, verification.verifyUrl);
|
|
2576
2749
|
if (changed) {
|
|
2577
2750
|
await saveAccounts(existingStorage);
|
|
@@ -2600,6 +2773,16 @@ export const createAntigravityPlugin = (providerId) => async ({ client, director
|
|
|
2600
2773
|
}
|
|
2601
2774
|
continue;
|
|
2602
2775
|
}
|
|
2776
|
+
if (verification.status === "ineligible") {
|
|
2777
|
+
const changed = markStoredAccountIneligible(account, verification.message);
|
|
2778
|
+
if (changed) {
|
|
2779
|
+
await saveAccounts(existingStorage);
|
|
2780
|
+
}
|
|
2781
|
+
activeAccountManager?.markAccountIneligible(verifyAccountIndex, verification.message);
|
|
2782
|
+
console.log(`⚠ ${label} is not eligible for Antigravity and has been disabled.`);
|
|
2783
|
+
console.log(`${verification.message}\n`);
|
|
2784
|
+
continue;
|
|
2785
|
+
}
|
|
2603
2786
|
console.log(`✗ ${label}: ${verification.message}\n`);
|
|
2604
2787
|
continue;
|
|
2605
2788
|
}
|
|
@@ -3117,6 +3300,9 @@ function isExplicitQuotaFromUrl(urlString) {
|
|
|
3117
3300
|
return explicitQuota ?? false;
|
|
3118
3301
|
}
|
|
3119
3302
|
export const __testExports = {
|
|
3303
|
+
buildAccountAccessProbeRequest,
|
|
3304
|
+
extractAccountAccessErrorDetails,
|
|
3305
|
+
interpretAccountAccessProbeResponse,
|
|
3120
3306
|
getHeaderStyleFromUrl,
|
|
3121
3307
|
isCapacityRetryBudgetExhausted,
|
|
3122
3308
|
resolveHeaderRoutingDecision,
|