antigravity-auth 1.6.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 +61 -0
- package/dist/antigravity/oauth.d.ts +30 -0
- package/dist/antigravity/oauth.js +170 -0
- package/dist/claude/login.d.ts +7 -0
- package/dist/claude/login.js +480 -0
- package/dist/claude/menu-helpers.d.ts +22 -0
- package/dist/claude/menu-helpers.js +281 -0
- package/dist/claude/proxy-manager.d.ts +11 -0
- package/dist/claude/proxy-manager.js +129 -0
- package/dist/claude/proxy.d.ts +1 -0
- package/dist/claude/proxy.js +733 -0
- package/dist/constants.d.ts +138 -0
- package/dist/constants.js +216 -0
- package/dist/hooks/auto-update-checker/cache.d.ts +2 -0
- package/dist/hooks/auto-update-checker/cache.js +70 -0
- package/dist/hooks/auto-update-checker/checker.d.ts +15 -0
- package/dist/hooks/auto-update-checker/checker.js +233 -0
- package/dist/hooks/auto-update-checker/constants.d.ts +8 -0
- package/dist/hooks/auto-update-checker/constants.js +22 -0
- package/dist/hooks/auto-update-checker/index.d.ts +33 -0
- package/dist/hooks/auto-update-checker/index.js +121 -0
- package/dist/hooks/auto-update-checker/logging.d.ts +2 -0
- package/dist/hooks/auto-update-checker/logging.js +8 -0
- package/dist/hooks/auto-update-checker/types.d.ts +24 -0
- package/dist/hooks/auto-update-checker/types.js +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/opencode/hooks/auto-update-checker/cache.d.ts +2 -0
- package/dist/opencode/hooks/auto-update-checker/cache.js +70 -0
- package/dist/opencode/hooks/auto-update-checker/checker.d.ts +15 -0
- package/dist/opencode/hooks/auto-update-checker/checker.js +233 -0
- package/dist/opencode/hooks/auto-update-checker/constants.d.ts +8 -0
- package/dist/opencode/hooks/auto-update-checker/constants.js +22 -0
- package/dist/opencode/hooks/auto-update-checker/index.d.ts +33 -0
- package/dist/opencode/hooks/auto-update-checker/index.js +121 -0
- package/dist/opencode/hooks/auto-update-checker/logging.d.ts +2 -0
- package/dist/opencode/hooks/auto-update-checker/logging.js +8 -0
- package/dist/opencode/hooks/auto-update-checker/types.d.ts +24 -0
- package/dist/opencode/hooks/auto-update-checker/types.js +1 -0
- package/dist/opencode/plugin.d.ts +29 -0
- package/dist/opencode/plugin.js +2954 -0
- package/dist/plugin/accounts.d.ts +173 -0
- package/dist/plugin/accounts.js +966 -0
- package/dist/plugin/auth.d.ts +20 -0
- package/dist/plugin/auth.js +44 -0
- package/dist/plugin/cache/index.d.ts +4 -0
- package/dist/plugin/cache/index.js +4 -0
- package/dist/plugin/cache/signature-cache.d.ts +110 -0
- package/dist/plugin/cache/signature-cache.js +347 -0
- package/dist/plugin/cache.d.ts +43 -0
- package/dist/plugin/cache.js +180 -0
- package/dist/plugin/cli.d.ts +26 -0
- package/dist/plugin/cli.js +126 -0
- package/dist/plugin/config/index.d.ts +15 -0
- package/dist/plugin/config/index.js +15 -0
- package/dist/plugin/config/loader.d.ts +38 -0
- package/dist/plugin/config/loader.js +150 -0
- package/dist/plugin/config/models.d.ts +26 -0
- package/dist/plugin/config/models.js +95 -0
- package/dist/plugin/config/schema.d.ts +144 -0
- package/dist/plugin/config/schema.js +458 -0
- package/dist/plugin/config/updater.d.ts +76 -0
- package/dist/plugin/config/updater.js +205 -0
- package/dist/plugin/core/streaming/index.d.ts +2 -0
- package/dist/plugin/core/streaming/index.js +2 -0
- package/dist/plugin/core/streaming/transformer.d.ts +9 -0
- package/dist/plugin/core/streaming/transformer.js +301 -0
- package/dist/plugin/core/streaming/types.d.ts +28 -0
- package/dist/plugin/core/streaming/types.js +1 -0
- package/dist/plugin/debug.d.ts +93 -0
- package/dist/plugin/debug.js +375 -0
- package/dist/plugin/errors.d.ts +27 -0
- package/dist/plugin/errors.js +41 -0
- package/dist/plugin/fingerprint.d.ts +69 -0
- package/dist/plugin/fingerprint.js +137 -0
- package/dist/plugin/image-saver.d.ts +24 -0
- package/dist/plugin/image-saver.js +78 -0
- package/dist/plugin/logger.d.ts +35 -0
- package/dist/plugin/logger.js +67 -0
- package/dist/plugin/logging-utils.d.ts +22 -0
- package/dist/plugin/logging-utils.js +91 -0
- package/dist/plugin/project.d.ts +32 -0
- package/dist/plugin/project.js +229 -0
- package/dist/plugin/quota.d.ts +34 -0
- package/dist/plugin/quota.js +261 -0
- package/dist/plugin/recovery/constants.d.ts +21 -0
- package/dist/plugin/recovery/constants.js +42 -0
- package/dist/plugin/recovery/index.d.ts +11 -0
- package/dist/plugin/recovery/index.js +11 -0
- package/dist/plugin/recovery/storage.d.ts +23 -0
- package/dist/plugin/recovery/storage.js +340 -0
- package/dist/plugin/recovery/types.d.ts +115 -0
- package/dist/plugin/recovery/types.js +6 -0
- package/dist/plugin/recovery.d.ts +60 -0
- package/dist/plugin/recovery.js +360 -0
- package/dist/plugin/refresh-queue.d.ts +99 -0
- package/dist/plugin/refresh-queue.js +235 -0
- package/dist/plugin/request-helpers.d.ts +281 -0
- package/dist/plugin/request-helpers.js +2200 -0
- package/dist/plugin/request.d.ts +110 -0
- package/dist/plugin/request.js +1489 -0
- package/dist/plugin/rotation.d.ts +182 -0
- package/dist/plugin/rotation.js +364 -0
- package/dist/plugin/search.d.ts +31 -0
- package/dist/plugin/search.js +185 -0
- package/dist/plugin/server.d.ts +22 -0
- package/dist/plugin/server.js +306 -0
- package/dist/plugin/storage.d.ts +136 -0
- package/dist/plugin/storage.js +599 -0
- package/dist/plugin/stores/signature-store.d.ts +4 -0
- package/dist/plugin/stores/signature-store.js +24 -0
- package/dist/plugin/thinking-recovery.d.ts +89 -0
- package/dist/plugin/thinking-recovery.js +289 -0
- package/dist/plugin/token.d.ts +18 -0
- package/dist/plugin/token.js +127 -0
- package/dist/plugin/transform/claude.d.ts +79 -0
- package/dist/plugin/transform/claude.js +256 -0
- package/dist/plugin/transform/cross-model-sanitizer.d.ts +34 -0
- package/dist/plugin/transform/cross-model-sanitizer.js +224 -0
- package/dist/plugin/transform/gemini.d.ts +132 -0
- package/dist/plugin/transform/gemini.js +659 -0
- package/dist/plugin/transform/index.d.ts +14 -0
- package/dist/plugin/transform/index.js +9 -0
- package/dist/plugin/transform/model-resolver.d.ts +98 -0
- package/dist/plugin/transform/model-resolver.js +320 -0
- package/dist/plugin/transform/types.d.ts +110 -0
- package/dist/plugin/transform/types.js +1 -0
- package/dist/plugin/types.d.ts +95 -0
- package/dist/plugin/types.js +1 -0
- package/dist/plugin/ui/ansi.d.ts +31 -0
- package/dist/plugin/ui/ansi.js +45 -0
- package/dist/plugin/ui/auth-menu.d.ts +47 -0
- package/dist/plugin/ui/auth-menu.js +199 -0
- package/dist/plugin/ui/confirm.d.ts +1 -0
- package/dist/plugin/ui/confirm.js +14 -0
- package/dist/plugin/ui/select.d.ts +22 -0
- package/dist/plugin/ui/select.js +243 -0
- package/dist/plugin/version.d.ts +18 -0
- package/dist/plugin/version.js +79 -0
- package/dist/src/antigravity/oauth.d.ts +30 -0
- package/dist/src/antigravity/oauth.js +170 -0
- package/dist/src/constants.d.ts +138 -0
- package/dist/src/constants.js +216 -0
- package/dist/src/hooks/auto-update-checker/cache.d.ts +2 -0
- package/dist/src/hooks/auto-update-checker/cache.js +70 -0
- package/dist/src/hooks/auto-update-checker/checker.d.ts +15 -0
- package/dist/src/hooks/auto-update-checker/checker.js +233 -0
- package/dist/src/hooks/auto-update-checker/constants.d.ts +8 -0
- package/dist/src/hooks/auto-update-checker/constants.js +22 -0
- package/dist/src/hooks/auto-update-checker/index.d.ts +33 -0
- package/dist/src/hooks/auto-update-checker/index.js +121 -0
- package/dist/src/hooks/auto-update-checker/logging.d.ts +2 -0
- package/dist/src/hooks/auto-update-checker/logging.js +8 -0
- package/dist/src/hooks/auto-update-checker/types.d.ts +24 -0
- package/dist/src/hooks/auto-update-checker/types.js +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +5 -0
- package/dist/src/plugin/accounts.d.ts +173 -0
- package/dist/src/plugin/accounts.js +966 -0
- package/dist/src/plugin/auth.d.ts +20 -0
- package/dist/src/plugin/auth.js +44 -0
- package/dist/src/plugin/cache/index.d.ts +4 -0
- package/dist/src/plugin/cache/index.js +4 -0
- package/dist/src/plugin/cache/signature-cache.d.ts +110 -0
- package/dist/src/plugin/cache/signature-cache.js +347 -0
- package/dist/src/plugin/cache.d.ts +43 -0
- package/dist/src/plugin/cache.js +180 -0
- package/dist/src/plugin/cli.d.ts +26 -0
- package/dist/src/plugin/cli.js +126 -0
- package/dist/src/plugin/config/index.d.ts +15 -0
- package/dist/src/plugin/config/index.js +15 -0
- package/dist/src/plugin/config/loader.d.ts +38 -0
- package/dist/src/plugin/config/loader.js +150 -0
- package/dist/src/plugin/config/models.d.ts +26 -0
- package/dist/src/plugin/config/models.js +95 -0
- package/dist/src/plugin/config/schema.d.ts +144 -0
- package/dist/src/plugin/config/schema.js +458 -0
- package/dist/src/plugin/config/updater.d.ts +76 -0
- package/dist/src/plugin/config/updater.js +205 -0
- package/dist/src/plugin/core/streaming/index.d.ts +2 -0
- package/dist/src/plugin/core/streaming/index.js +2 -0
- package/dist/src/plugin/core/streaming/transformer.d.ts +9 -0
- package/dist/src/plugin/core/streaming/transformer.js +301 -0
- package/dist/src/plugin/core/streaming/types.d.ts +28 -0
- package/dist/src/plugin/core/streaming/types.js +1 -0
- package/dist/src/plugin/debug.d.ts +93 -0
- package/dist/src/plugin/debug.js +375 -0
- package/dist/src/plugin/errors.d.ts +27 -0
- package/dist/src/plugin/errors.js +41 -0
- package/dist/src/plugin/fingerprint.d.ts +69 -0
- package/dist/src/plugin/fingerprint.js +137 -0
- package/dist/src/plugin/image-saver.d.ts +24 -0
- package/dist/src/plugin/image-saver.js +78 -0
- package/dist/src/plugin/logger.d.ts +35 -0
- package/dist/src/plugin/logger.js +67 -0
- package/dist/src/plugin/logging-utils.d.ts +22 -0
- package/dist/src/plugin/logging-utils.js +91 -0
- package/dist/src/plugin/project.d.ts +32 -0
- package/dist/src/plugin/project.js +229 -0
- package/dist/src/plugin/quota.d.ts +34 -0
- package/dist/src/plugin/quota.js +261 -0
- package/dist/src/plugin/recovery/constants.d.ts +21 -0
- package/dist/src/plugin/recovery/constants.js +42 -0
- package/dist/src/plugin/recovery/index.d.ts +11 -0
- package/dist/src/plugin/recovery/index.js +11 -0
- package/dist/src/plugin/recovery/storage.d.ts +23 -0
- package/dist/src/plugin/recovery/storage.js +340 -0
- package/dist/src/plugin/recovery/types.d.ts +115 -0
- package/dist/src/plugin/recovery/types.js +6 -0
- package/dist/src/plugin/recovery.d.ts +60 -0
- package/dist/src/plugin/recovery.js +360 -0
- package/dist/src/plugin/refresh-queue.d.ts +99 -0
- package/dist/src/plugin/refresh-queue.js +235 -0
- package/dist/src/plugin/request-helpers.d.ts +281 -0
- package/dist/src/plugin/request-helpers.js +2200 -0
- package/dist/src/plugin/request.d.ts +110 -0
- package/dist/src/plugin/request.js +1489 -0
- package/dist/src/plugin/rotation.d.ts +182 -0
- package/dist/src/plugin/rotation.js +364 -0
- package/dist/src/plugin/search.d.ts +31 -0
- package/dist/src/plugin/search.js +185 -0
- package/dist/src/plugin/server.d.ts +22 -0
- package/dist/src/plugin/server.js +306 -0
- package/dist/src/plugin/storage.d.ts +136 -0
- package/dist/src/plugin/storage.js +599 -0
- package/dist/src/plugin/stores/signature-store.d.ts +4 -0
- package/dist/src/plugin/stores/signature-store.js +24 -0
- package/dist/src/plugin/thinking-recovery.d.ts +89 -0
- package/dist/src/plugin/thinking-recovery.js +289 -0
- package/dist/src/plugin/token.d.ts +18 -0
- package/dist/src/plugin/token.js +127 -0
- package/dist/src/plugin/transform/claude.d.ts +79 -0
- package/dist/src/plugin/transform/claude.js +256 -0
- package/dist/src/plugin/transform/cross-model-sanitizer.d.ts +34 -0
- package/dist/src/plugin/transform/cross-model-sanitizer.js +224 -0
- package/dist/src/plugin/transform/gemini.d.ts +132 -0
- package/dist/src/plugin/transform/gemini.js +659 -0
- package/dist/src/plugin/transform/index.d.ts +14 -0
- package/dist/src/plugin/transform/index.js +9 -0
- package/dist/src/plugin/transform/model-resolver.d.ts +98 -0
- package/dist/src/plugin/transform/model-resolver.js +320 -0
- package/dist/src/plugin/transform/types.d.ts +110 -0
- package/dist/src/plugin/transform/types.js +1 -0
- package/dist/src/plugin/types.d.ts +95 -0
- package/dist/src/plugin/types.js +1 -0
- package/dist/src/plugin/ui/ansi.d.ts +31 -0
- package/dist/src/plugin/ui/ansi.js +45 -0
- package/dist/src/plugin/ui/auth-menu.d.ts +47 -0
- package/dist/src/plugin/ui/auth-menu.js +199 -0
- package/dist/src/plugin/ui/confirm.d.ts +1 -0
- package/dist/src/plugin/ui/confirm.js +14 -0
- package/dist/src/plugin/ui/select.d.ts +22 -0
- package/dist/src/plugin/ui/select.js +243 -0
- package/dist/src/plugin/version.d.ts +18 -0
- package/dist/src/plugin/version.js +79 -0
- package/package.json +54 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { getAntigravityHeaders, ANTIGRAVITY_ENDPOINT_PROD, ANTIGRAVITY_DEFAULT_PROJECT_ID } from "../src/constants";
|
|
2
|
+
import { parseRefreshParts, formatRefreshParts } from "../src/plugin/auth";
|
|
3
|
+
import { refreshAccessToken, AntigravityTokenRefreshError } from "../src/plugin/token";
|
|
4
|
+
// --- Inlined helpers (from opencode-antigravity-auth/src/plugin.ts, not in core submodule) ---
|
|
5
|
+
function decodeEscapedText(input) {
|
|
6
|
+
return input
|
|
7
|
+
.replace(/&/g, "&")
|
|
8
|
+
.replace(/\\u([0-9a-fA-F]{4})/g, (_, hex) => String.fromCharCode(Number.parseInt(hex, 16)));
|
|
9
|
+
}
|
|
10
|
+
function normalizeGoogleVerificationUrl(rawUrl) {
|
|
11
|
+
const normalized = decodeEscapedText(rawUrl).trim();
|
|
12
|
+
if (!normalized)
|
|
13
|
+
return undefined;
|
|
14
|
+
try {
|
|
15
|
+
const parsed = new URL(normalized);
|
|
16
|
+
if (parsed.hostname !== "accounts.google.com")
|
|
17
|
+
return undefined;
|
|
18
|
+
return parsed.toString();
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function selectBestVerificationUrl(urls) {
|
|
25
|
+
const unique = Array.from(new Set(urls.map((url) => normalizeGoogleVerificationUrl(url)).filter(Boolean)));
|
|
26
|
+
if (unique.length === 0)
|
|
27
|
+
return undefined;
|
|
28
|
+
unique.sort((a, b) => {
|
|
29
|
+
const score = (value) => {
|
|
30
|
+
let total = 0;
|
|
31
|
+
if (value.includes("plt="))
|
|
32
|
+
total += 4;
|
|
33
|
+
if (value.includes("/signin/continue"))
|
|
34
|
+
total += 3;
|
|
35
|
+
if (value.includes("continue="))
|
|
36
|
+
total += 2;
|
|
37
|
+
if (value.includes("service=cloudcode"))
|
|
38
|
+
total += 1;
|
|
39
|
+
return total;
|
|
40
|
+
};
|
|
41
|
+
return score(b) - score(a);
|
|
42
|
+
});
|
|
43
|
+
return unique[0];
|
|
44
|
+
}
|
|
45
|
+
function extractVerificationErrorDetails(bodyText) {
|
|
46
|
+
const decodedBody = decodeEscapedText(bodyText);
|
|
47
|
+
const lowerBody = decodedBody.toLowerCase();
|
|
48
|
+
let validationRequired = lowerBody.includes("validation_required");
|
|
49
|
+
let message;
|
|
50
|
+
const verificationUrls = new Set();
|
|
51
|
+
const collectUrlsFromText = (text) => {
|
|
52
|
+
for (const match of text.matchAll(/https:\/\/accounts\.google\.com\/[^\s"'<>]+/gi)) {
|
|
53
|
+
if (match[0])
|
|
54
|
+
verificationUrls.add(match[0]);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
collectUrlsFromText(decodedBody);
|
|
58
|
+
const payloads = [];
|
|
59
|
+
const trimmed = decodedBody.trim();
|
|
60
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
61
|
+
try {
|
|
62
|
+
payloads.push(JSON.parse(trimmed));
|
|
63
|
+
}
|
|
64
|
+
catch { }
|
|
65
|
+
}
|
|
66
|
+
for (const rawLine of decodedBody.split("\n")) {
|
|
67
|
+
const line = rawLine.trim();
|
|
68
|
+
if (!line.startsWith("data:"))
|
|
69
|
+
continue;
|
|
70
|
+
const payloadText = line.slice(5).trim();
|
|
71
|
+
if (!payloadText || payloadText === "[DONE]")
|
|
72
|
+
continue;
|
|
73
|
+
try {
|
|
74
|
+
payloads.push(JSON.parse(payloadText));
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
collectUrlsFromText(payloadText);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const visited = new Set();
|
|
81
|
+
const walk = (value, key) => {
|
|
82
|
+
if (typeof value === "string") {
|
|
83
|
+
const normalizedValue = decodeEscapedText(value);
|
|
84
|
+
const lowerValue = normalizedValue.toLowerCase();
|
|
85
|
+
const lowerKey = key?.toLowerCase() ?? "";
|
|
86
|
+
if (lowerValue.includes("validation_required"))
|
|
87
|
+
validationRequired = true;
|
|
88
|
+
if (!message && (lowerKey.includes("message") || lowerKey.includes("detail") || lowerKey.includes("description"))) {
|
|
89
|
+
message = normalizedValue;
|
|
90
|
+
}
|
|
91
|
+
if (lowerKey.includes("validation_url") || lowerKey.includes("verify_url") || lowerKey.includes("verification_url") || lowerKey === "url") {
|
|
92
|
+
verificationUrls.add(normalizedValue);
|
|
93
|
+
}
|
|
94
|
+
collectUrlsFromText(normalizedValue);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (!value || typeof value !== "object" || visited.has(value))
|
|
98
|
+
return;
|
|
99
|
+
visited.add(value);
|
|
100
|
+
if (Array.isArray(value)) {
|
|
101
|
+
for (const item of value)
|
|
102
|
+
walk(item);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
for (const [childKey, childValue] of Object.entries(value)) {
|
|
106
|
+
walk(childValue, childKey);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
for (const payload of payloads)
|
|
110
|
+
walk(payload);
|
|
111
|
+
if (!validationRequired) {
|
|
112
|
+
validationRequired =
|
|
113
|
+
lowerBody.includes("verification required") ||
|
|
114
|
+
lowerBody.includes("verify your account") ||
|
|
115
|
+
lowerBody.includes("account verification");
|
|
116
|
+
}
|
|
117
|
+
if (!message) {
|
|
118
|
+
const fallback = decodedBody
|
|
119
|
+
.split("\n")
|
|
120
|
+
.map((line) => line.trim())
|
|
121
|
+
.find((line) => line && !line.startsWith("data:") && /(verify|validation|required)/i.test(line));
|
|
122
|
+
if (fallback)
|
|
123
|
+
message = fallback;
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
validationRequired,
|
|
127
|
+
message,
|
|
128
|
+
verifyUrl: selectBestVerificationUrl([...verificationUrls]),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export async function verifyAccountAccess(account, client, providerId) {
|
|
132
|
+
const parsed = parseRefreshParts(account.refreshToken);
|
|
133
|
+
if (!parsed.refreshToken) {
|
|
134
|
+
return { status: "error", message: "Missing refresh token for selected account." };
|
|
135
|
+
}
|
|
136
|
+
const auth = {
|
|
137
|
+
type: "oauth",
|
|
138
|
+
refresh: formatRefreshParts({
|
|
139
|
+
refreshToken: parsed.refreshToken,
|
|
140
|
+
projectId: parsed.projectId ?? account.projectId,
|
|
141
|
+
managedProjectId: parsed.managedProjectId ?? account.managedProjectId,
|
|
142
|
+
}),
|
|
143
|
+
access: "",
|
|
144
|
+
expires: 0,
|
|
145
|
+
};
|
|
146
|
+
let refreshedAuth;
|
|
147
|
+
try {
|
|
148
|
+
refreshedAuth = await refreshAccessToken(auth, client, providerId);
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
if (error instanceof AntigravityTokenRefreshError) {
|
|
152
|
+
return { status: "error", message: error.message };
|
|
153
|
+
}
|
|
154
|
+
return { status: "error", message: `Token refresh failed: ${String(error)}` };
|
|
155
|
+
}
|
|
156
|
+
if (!refreshedAuth?.access) {
|
|
157
|
+
return { status: "error", message: "Could not refresh access token for this account." };
|
|
158
|
+
}
|
|
159
|
+
const projectId = parsed.managedProjectId ??
|
|
160
|
+
parsed.projectId ??
|
|
161
|
+
account.managedProjectId ??
|
|
162
|
+
account.projectId ??
|
|
163
|
+
ANTIGRAVITY_DEFAULT_PROJECT_ID;
|
|
164
|
+
const headers = {
|
|
165
|
+
...getAntigravityHeaders(),
|
|
166
|
+
Authorization: `Bearer ${refreshedAuth.access}`,
|
|
167
|
+
"Content-Type": "application/json",
|
|
168
|
+
};
|
|
169
|
+
if (projectId) {
|
|
170
|
+
headers["x-goog-user-project"] = projectId;
|
|
171
|
+
}
|
|
172
|
+
const requestBody = {
|
|
173
|
+
model: "gemini-3-flash",
|
|
174
|
+
request: {
|
|
175
|
+
model: "gemini-3-flash",
|
|
176
|
+
contents: [{ role: "user", parts: [{ text: "ping" }] }],
|
|
177
|
+
generationConfig: { maxOutputTokens: 1, temperature: 0 },
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
const controller = new AbortController();
|
|
181
|
+
const timeoutId = setTimeout(() => controller.abort(), 20000);
|
|
182
|
+
let response;
|
|
183
|
+
try {
|
|
184
|
+
response = await fetch(`${ANTIGRAVITY_ENDPOINT_PROD}/v1internal:streamGenerateContent?alt=sse`, {
|
|
185
|
+
method: "POST",
|
|
186
|
+
headers,
|
|
187
|
+
body: JSON.stringify(requestBody),
|
|
188
|
+
signal: controller.signal,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
193
|
+
return { status: "error", message: "Verification check timed out." };
|
|
194
|
+
}
|
|
195
|
+
return { status: "error", message: `Verification check failed: ${String(error)}` };
|
|
196
|
+
}
|
|
197
|
+
finally {
|
|
198
|
+
clearTimeout(timeoutId);
|
|
199
|
+
}
|
|
200
|
+
let responseBody = "";
|
|
201
|
+
try {
|
|
202
|
+
responseBody = await response.text();
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
responseBody = "";
|
|
206
|
+
}
|
|
207
|
+
if (response.ok) {
|
|
208
|
+
return { status: "ok", message: "Account verification check passed." };
|
|
209
|
+
}
|
|
210
|
+
const extracted = extractVerificationErrorDetails(responseBody);
|
|
211
|
+
if (response.status === 403 && extracted.validationRequired) {
|
|
212
|
+
return {
|
|
213
|
+
status: "blocked",
|
|
214
|
+
message: extracted.message ?? "Google requires additional account verification.",
|
|
215
|
+
verifyUrl: extracted.verifyUrl,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
const fallbackMessage = extracted.message ?? `Request failed (${response.status} ${response.statusText}).`;
|
|
219
|
+
return {
|
|
220
|
+
status: "error",
|
|
221
|
+
message: fallbackMessage,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
export async function promptAccountIndexForVerification(accounts) {
|
|
225
|
+
const { createInterface } = await import("node:readline/promises");
|
|
226
|
+
const { stdin, stdout } = await import("node:process");
|
|
227
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
228
|
+
try {
|
|
229
|
+
console.log("\nSelect an account to verify:");
|
|
230
|
+
for (const account of accounts) {
|
|
231
|
+
const label = account.email || `Account ${account.index + 1}`;
|
|
232
|
+
console.log(` ${account.index + 1}. ${label}`);
|
|
233
|
+
}
|
|
234
|
+
console.log("");
|
|
235
|
+
while (true) {
|
|
236
|
+
const answer = (await rl.question("Account number (leave blank to cancel): ")).trim();
|
|
237
|
+
if (!answer) {
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
const parsedIndex = Number(answer);
|
|
241
|
+
if (!Number.isInteger(parsedIndex)) {
|
|
242
|
+
console.log("Please enter a valid account number.");
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
const normalizedIndex = parsedIndex - 1;
|
|
246
|
+
const selected = accounts.find((account) => account.index === normalizedIndex);
|
|
247
|
+
if (!selected) {
|
|
248
|
+
console.log("Please enter a number from the list above.");
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
return selected.index;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
finally {
|
|
255
|
+
rl.close();
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
export function markStoredAccountVerificationRequired(account, message, verifyUrl) {
|
|
259
|
+
if (account.verificationRequired && account.verificationMessage === message && account.verificationUrl === verifyUrl) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
account.verificationRequired = true;
|
|
263
|
+
account.verificationMessage = message;
|
|
264
|
+
account.verificationUrl = verifyUrl;
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
export function clearStoredAccountVerificationRequired(account, reEnable = false) {
|
|
268
|
+
const wasVerificationRequired = !!account.verificationRequired;
|
|
269
|
+
let changed = false;
|
|
270
|
+
if (account.verificationRequired) {
|
|
271
|
+
delete account.verificationRequired;
|
|
272
|
+
delete account.verificationMessage;
|
|
273
|
+
delete account.verificationUrl;
|
|
274
|
+
changed = true;
|
|
275
|
+
}
|
|
276
|
+
if (reEnable && account.enabled === false && wasVerificationRequired) {
|
|
277
|
+
delete account.enabled;
|
|
278
|
+
changed = true;
|
|
279
|
+
}
|
|
280
|
+
return { changed, wasVerificationRequired };
|
|
281
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface ProxyInfo {
|
|
2
|
+
url: string;
|
|
3
|
+
provider: string;
|
|
4
|
+
weight: number;
|
|
5
|
+
latency?: number;
|
|
6
|
+
failures: number;
|
|
7
|
+
lastTested?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function loadHotPool(): ProxyInfo[];
|
|
10
|
+
export declare function saveHotPool(pool: ProxyInfo[]): void;
|
|
11
|
+
export declare function runDaemon(): Promise<void>;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import { loadProxyConfig } from '../src/plugin/proxy-config';
|
|
5
|
+
const HOT_POOL_FILE = path.join(os.homedir(), '.claude', 'cache', 'proxy-hot-pool.json');
|
|
6
|
+
const TARGET_POOL_SIZE = 10;
|
|
7
|
+
const TEST_URL = 'https://google.com';
|
|
8
|
+
export function loadHotPool() {
|
|
9
|
+
try {
|
|
10
|
+
if (fs.existsSync(HOT_POOL_FILE)) {
|
|
11
|
+
return JSON.parse(fs.readFileSync(HOT_POOL_FILE, 'utf8'));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
console.error('Failed to load hot pool', e);
|
|
16
|
+
}
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
export function saveHotPool(pool) {
|
|
20
|
+
const dir = path.dirname(HOT_POOL_FILE);
|
|
21
|
+
if (!fs.existsSync(dir))
|
|
22
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
23
|
+
fs.writeFileSync(HOT_POOL_FILE, JSON.stringify(pool, null, 2));
|
|
24
|
+
}
|
|
25
|
+
async function checkHealth(proxyUrl) {
|
|
26
|
+
const start = Date.now();
|
|
27
|
+
try {
|
|
28
|
+
const res = await fetch(TEST_URL, {
|
|
29
|
+
method: 'HEAD',
|
|
30
|
+
// @ts-ignore - bun specific extension
|
|
31
|
+
proxy: proxyUrl,
|
|
32
|
+
signal: AbortSignal.timeout(5000)
|
|
33
|
+
});
|
|
34
|
+
if (res.ok || res.status < 400) {
|
|
35
|
+
return Date.now() - start;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
async function fetchProxyScrape(config) {
|
|
43
|
+
if (!config.enabled)
|
|
44
|
+
return [];
|
|
45
|
+
try {
|
|
46
|
+
const res = await fetch('https://api.proxyscrape.com/v2/?request=displayproxies&protocol=http&timeout=5000&country=all&ssl=all&anonymity=all');
|
|
47
|
+
const text = await res.text();
|
|
48
|
+
return text.split('\n').map(p => p.trim()).filter(p => p).map(p => ({
|
|
49
|
+
url: `http://${p}`, provider: 'proxyscrape', weight: config.weight || 1, failures: 0
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async function fetchWebshare(config) { return []; }
|
|
57
|
+
async function fetchBrightData(config) { return []; }
|
|
58
|
+
async function fetchOxylabs(config) { return []; }
|
|
59
|
+
async function fetchProxifly(config) { return []; }
|
|
60
|
+
async function fetchGeonix(config) { return []; }
|
|
61
|
+
async function fetchLitport(config) { return []; }
|
|
62
|
+
async function fetchIPLocate(config) { return []; }
|
|
63
|
+
export async function runDaemon() {
|
|
64
|
+
console.log('Starting Antigravity Proxy Manager Daemon...');
|
|
65
|
+
setInterval(async () => {
|
|
66
|
+
const config = loadProxyConfig();
|
|
67
|
+
if (config.strategy !== 'automatic')
|
|
68
|
+
return;
|
|
69
|
+
let pool = loadHotPool();
|
|
70
|
+
// 1. Prune dead proxies (failures > 3)
|
|
71
|
+
pool = pool.filter(p => p.failures < 3);
|
|
72
|
+
// 2. Health check existing
|
|
73
|
+
for (const proxy of pool) {
|
|
74
|
+
const latency = await checkHealth(proxy.url);
|
|
75
|
+
proxy.lastTested = Date.now();
|
|
76
|
+
if (latency === null) {
|
|
77
|
+
proxy.failures++;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
proxy.latency = latency;
|
|
81
|
+
proxy.failures = 0; // reset
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
pool = pool.filter(p => p.failures < 3);
|
|
85
|
+
// 3. Replenish if needed
|
|
86
|
+
if (pool.length < TARGET_POOL_SIZE) {
|
|
87
|
+
let newProxies = [];
|
|
88
|
+
if (config.providers.webshare?.enabled)
|
|
89
|
+
newProxies.push(...await fetchWebshare(config.providers.webshare));
|
|
90
|
+
if (config.providers.proxyscrape?.enabled)
|
|
91
|
+
newProxies.push(...await fetchProxyScrape(config.providers.proxyscrape));
|
|
92
|
+
if (config.providers.brightdata?.enabled)
|
|
93
|
+
newProxies.push(...await fetchBrightData(config.providers.brightdata));
|
|
94
|
+
if (config.providers.oxylabs?.enabled)
|
|
95
|
+
newProxies.push(...await fetchOxylabs(config.providers.oxylabs));
|
|
96
|
+
if (config.providers.proxifly?.enabled)
|
|
97
|
+
newProxies.push(...await fetchProxifly(config.providers.proxifly));
|
|
98
|
+
if (config.providers.geonix?.enabled)
|
|
99
|
+
newProxies.push(...await fetchGeonix(config.providers.geonix));
|
|
100
|
+
if (config.providers.litport?.enabled)
|
|
101
|
+
newProxies.push(...await fetchLitport(config.providers.litport));
|
|
102
|
+
if (config.providers.iplocate?.enabled)
|
|
103
|
+
newProxies.push(...await fetchIPLocate(config.providers.iplocate));
|
|
104
|
+
newProxies = newProxies.sort(() => Math.random() - 0.5);
|
|
105
|
+
for (const np of newProxies) {
|
|
106
|
+
if (pool.length >= TARGET_POOL_SIZE)
|
|
107
|
+
break;
|
|
108
|
+
if (!pool.find(p => p.url === np.url)) {
|
|
109
|
+
const latency = await checkHealth(np.url);
|
|
110
|
+
if (latency !== null) {
|
|
111
|
+
np.latency = latency;
|
|
112
|
+
np.lastTested = Date.now();
|
|
113
|
+
pool.push(np);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// 4. Sort pool by latency relative to provider weight (lower is better)
|
|
119
|
+
pool.sort((a, b) => {
|
|
120
|
+
const scoreA = (a.latency || 9999) / a.weight;
|
|
121
|
+
const scoreB = (b.latency || 9999) / b.weight;
|
|
122
|
+
return scoreA - scoreB;
|
|
123
|
+
});
|
|
124
|
+
saveHotPool(pool);
|
|
125
|
+
}, 60000);
|
|
126
|
+
}
|
|
127
|
+
if (import.meta.url === `file://${process.argv[1]}` || process.argv[1].endsWith('proxy-manager.ts')) {
|
|
128
|
+
runDaemon();
|
|
129
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|