antigravity-claude-proxy 2.7.1 → 2.7.3

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.
@@ -292,6 +292,15 @@ export function mountWebUI(app, dirname, accountManager) {
292
292
  const { email } = req.params;
293
293
  accountManager.clearTokenCache(email);
294
294
  accountManager.clearProjectCache(email);
295
+
296
+ // For verification errors (403 VALIDATION_REQUIRED), clear isInvalid on refresh.
297
+ // The user has completed verification on Google's site and clicks Refresh to re-enable.
298
+ // Auth errors (no verifyUrl) still require OAuth re-auth via FIX button.
299
+ const account = accountManager.getAllAccounts().find(a => a.email === email);
300
+ if (account && account.isInvalid && account.verifyUrl) {
301
+ accountManager.clearInvalid(email);
302
+ }
303
+
295
304
  res.json({
296
305
  status: 'ok',
297
306
  message: `Token cache cleared for ${email}`
@@ -347,78 +356,6 @@ export function mountWebUI(app, dirname, accountManager) {
347
356
  }
348
357
  });
349
358
 
350
- /**
351
- * POST /api/accounts/:email/fingerprint/regenerate - Regenerate fingerprint
352
- */
353
- app.post('/api/accounts/:email/fingerprint/regenerate', async (req, res) => {
354
- try {
355
- const { email } = req.params;
356
- const fingerprint = accountManager.regenerateFingerprint(email);
357
-
358
- if (!fingerprint) {
359
- return res.status(404).json({ status: 'error', error: 'Account not found' });
360
- }
361
-
362
- res.json({
363
- status: 'ok',
364
- message: 'Fingerprint regenerated',
365
- fingerprint
366
- });
367
- } catch (error) {
368
- res.status(500).json({ status: 'error', error: error.message });
369
- }
370
- });
371
-
372
- /**
373
- * GET /api/accounts/:email/fingerprint - Get fingerprint details and history
374
- */
375
- app.get('/api/accounts/:email/fingerprint', async (req, res) => {
376
- try {
377
- const { email } = req.params;
378
- const account = accountManager.getAllAccounts().find(a => a.email === email);
379
-
380
- if (!account) {
381
- return res.status(404).json({ status: 'error', error: 'Account not found' });
382
- }
383
-
384
- res.json({
385
- status: 'ok',
386
- fingerprint: account.fingerprint,
387
- history: account.fingerprintHistory || []
388
- });
389
- } catch (error) {
390
- res.status(500).json({ status: 'error', error: error.message });
391
- }
392
- });
393
-
394
- /**
395
- * POST /api/accounts/:email/fingerprint/restore - Restore fingerprint from history
396
- */
397
- app.post('/api/accounts/:email/fingerprint/restore', async (req, res) => {
398
- try {
399
- const { email } = req.params;
400
- const { index } = req.body;
401
-
402
- if (typeof index !== 'number') {
403
- return res.status(400).json({ status: 'error', error: 'History index required' });
404
- }
405
-
406
- const fingerprint = accountManager.restoreFingerprint(email, index);
407
-
408
- if (!fingerprint) {
409
- return res.status(404).json({ status: 'error', error: 'Account or history entry not found' });
410
- }
411
-
412
- res.json({
413
- status: 'ok',
414
- message: 'Fingerprint restored',
415
- fingerprint
416
- });
417
- } catch (error) {
418
- res.status(500).json({ status: 'error', error: error.message });
419
- }
420
- });
421
-
422
359
  /**
423
360
  * PATCH /api/accounts/:email - Update account settings (thresholds)
424
361
  */
@@ -644,7 +581,7 @@ export function mountWebUI(app, dirname, accountManager) {
644
581
  */
645
582
  app.post('/api/config', async (req, res) => {
646
583
  try {
647
- const { debug, devMode, logLevel, persistTokenCache } = req.body;
584
+ const { debug, devMode, logLevel, persistTokenCache, requestThrottlingEnabled, requestDelayMs } = req.body;
648
585
 
649
586
  // Validate tunable config fields via shared helper
650
587
  const updates = validateConfigFields(req.body);
@@ -665,6 +602,12 @@ export function mountWebUI(app, dirname, accountManager) {
665
602
  if (typeof persistTokenCache === 'boolean') {
666
603
  updates.persistTokenCache = persistTokenCache;
667
604
  }
605
+ if (typeof requestThrottlingEnabled === 'boolean') {
606
+ updates.requestThrottlingEnabled = requestThrottlingEnabled;
607
+ }
608
+ if (typeof requestDelayMs === 'number' && requestDelayMs >= 100 && requestDelayMs <= 5000) {
609
+ updates.requestDelayMs = requestDelayMs;
610
+ }
668
611
 
669
612
  if (Object.keys(updates).length === 0) {
670
613
  return res.status(400).json({
@@ -1,133 +0,0 @@
1
- /**
2
- * Device Fingerprint Generator for Rate Limit Mitigation
3
- *
4
- * Generates randomized device fingerprints to help distribute API usage
5
- * across different apparent device identities.
6
- *
7
- * Based on: https://github.com/NoeFabris/opencode-antigravity-auth
8
- */
9
-
10
- import crypto from 'crypto';
11
- import { IDE_TYPE, PLATFORM, PLUGIN_TYPE, ANTIGRAVITY_VERSION } from '../constants.js';
12
-
13
- const OS_VERSIONS = {
14
- darwin: ['10.15.7', '11.6.8', '12.6.3', '13.5.2', '14.2.1', '14.5'],
15
- win32: ['10.0.19041', '10.0.19042', '10.0.19043', '10.0.22000', '10.0.22621', '10.0.22631'],
16
- linux: ['5.15.0', '5.19.0', '6.1.0', '6.2.0', '6.5.0', '6.6.0']
17
- };
18
-
19
- const ARCHITECTURES = ['x64', 'arm64'];
20
-
21
- const IDE_TYPES = [
22
- 'IDE_UNSPECIFIED',
23
- 'VSCODE',
24
- 'INTELLIJ',
25
- 'ANDROID_STUDIO',
26
- 'CLOUD_SHELL_EDITOR'
27
- ];
28
-
29
- const SDK_CLIENTS = [
30
- 'google-cloud-sdk vscode_cloudshelleditor/0.1',
31
- 'google-cloud-sdk vscode/1.86.0',
32
- 'google-cloud-sdk vscode/1.87.0',
33
- 'google-cloud-sdk intellij/2024.1',
34
- 'google-cloud-sdk android-studio/2024.1',
35
- 'gcloud-python/1.2.0 grpc-google-iam-v1/0.12.6'
36
- ];
37
-
38
- /**
39
- * Maximum number of fingerprint versions to keep in history
40
- */
41
- export const MAX_FINGERPRINT_HISTORY = 5;
42
-
43
- /**
44
- * Pick a random item from an array
45
- * @template T
46
- * @param {T[]} arr
47
- * @returns {T}
48
- */
49
- function randomFrom(arr) {
50
- return arr[Math.floor(Math.random() * arr.length)];
51
- }
52
-
53
- function generateDeviceId() {
54
- return crypto.randomUUID();
55
- }
56
-
57
- function generateSessionToken() {
58
- return crypto.randomBytes(16).toString('hex');
59
- }
60
-
61
- /**
62
- * Generate a randomized device fingerprint.
63
- * Each fingerprint represents a unique "device" identity.
64
- * @returns {Object} Fingerprint object
65
- */
66
- export function generateFingerprint() {
67
- const platform = randomFrom(['darwin', 'win32', 'linux']);
68
- const arch = randomFrom(ARCHITECTURES);
69
- const osVersion = randomFrom(OS_VERSIONS[platform] || OS_VERSIONS.linux);
70
-
71
- let matchingPlatform;
72
- if (platform === 'darwin') matchingPlatform = PLATFORM.MACOS;
73
- else if (platform === 'win32') matchingPlatform = PLATFORM.WINDOWS;
74
- else if (platform === 'linux') matchingPlatform = PLATFORM.LINUX;
75
- else matchingPlatform = PLATFORM.UNSPECIFIED;
76
-
77
- return {
78
- deviceId: generateDeviceId(),
79
- sessionToken: generateSessionToken(),
80
- userAgent: `antigravity/${ANTIGRAVITY_VERSION} ${platform}/${arch}`,
81
- apiClient: randomFrom(SDK_CLIENTS),
82
- clientMetadata: {
83
- ideType: randomFrom(IDE_TYPES),
84
- platform: matchingPlatform,
85
- pluginType: PLUGIN_TYPE.GEMINI,
86
- osVersion: osVersion,
87
- arch: arch,
88
- sqmId: `{${crypto.randomUUID().toUpperCase()}}`
89
- },
90
- quotaUser: `device-${crypto.randomBytes(8).toString('hex')}`,
91
- createdAt: Date.now()
92
- };
93
- }
94
-
95
- /**
96
- * Build HTTP headers from a fingerprint object.
97
- * These headers are used to identify the "device" making API requests.
98
- * @param {Object} fingerprint - The fingerprint object
99
- * @returns {Object} Headers object
100
- */
101
- export function buildFingerprintHeaders(fingerprint) {
102
- if (!fingerprint) {
103
- return {};
104
- }
105
-
106
- return {
107
- 'User-Agent': fingerprint.userAgent,
108
- 'X-Goog-Api-Client': fingerprint.apiClient,
109
- 'Client-Metadata': JSON.stringify(fingerprint.clientMetadata),
110
- 'X-Goog-QuotaUser': fingerprint.quotaUser,
111
- 'X-Client-Device-Id': fingerprint.deviceId
112
- };
113
- }
114
-
115
- /**
116
- * Update fingerprint userAgent to current version if outdated.
117
- * Extracts platform/arch from existing userAgent and rebuilds with current version.
118
- * @param {Object} fingerprint
119
- * @returns {Object} Updated fingerprint
120
- */
121
- export function updateFingerprintVersion(fingerprint) {
122
- if (!fingerprint || !fingerprint.userAgent) return fingerprint;
123
-
124
- const match = fingerprint.userAgent.match(/^antigravity\/\S+ (.+)$/);
125
- if (match) {
126
- const platformArch = match[1];
127
- const expectedUserAgent = `antigravity/${ANTIGRAVITY_VERSION} ${platformArch}`;
128
- if (fingerprint.userAgent !== expectedUserAgent) {
129
- return { ...fingerprint, userAgent: expectedUserAgent };
130
- }
131
- }
132
- return fingerprint;
133
- }