antigravity-claude-proxy 1.2.7 → 1.2.8
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 +1 -1
- package/package.json +1 -1
- package/src/auth/database.js +79 -3
- package/src/auth/oauth.js +8 -8
- package/src/constants.js +1 -1
- package/src/errors.js +18 -0
- package/src/utils/native-module-helper.js +162 -0
package/README.md
CHANGED
|
@@ -400,4 +400,4 @@ MIT
|
|
|
400
400
|
|
|
401
401
|
## Star History
|
|
402
402
|
|
|
403
|
-
[](https://www.star-history.com/#badrisnarayanan/antigravity-claude-proxy&type=date&legend=top-left)
|
package/package.json
CHANGED
package/src/auth/database.js
CHANGED
|
@@ -6,10 +6,80 @@
|
|
|
6
6
|
* - Windows compatibility (no CLI dependency)
|
|
7
7
|
* - Native performance
|
|
8
8
|
* - Synchronous API (simple error handling)
|
|
9
|
+
*
|
|
10
|
+
* Includes auto-rebuild capability for handling Node.js version updates
|
|
11
|
+
* that cause native module incompatibility.
|
|
9
12
|
*/
|
|
10
13
|
|
|
11
|
-
import
|
|
14
|
+
import { createRequire } from 'module';
|
|
12
15
|
import { ANTIGRAVITY_DB_PATH } from '../constants.js';
|
|
16
|
+
import { isModuleVersionError, attemptAutoRebuild, clearRequireCache } from '../utils/native-module-helper.js';
|
|
17
|
+
import { logger } from '../utils/logger.js';
|
|
18
|
+
import { NativeModuleError } from '../errors.js';
|
|
19
|
+
|
|
20
|
+
const require = createRequire(import.meta.url);
|
|
21
|
+
|
|
22
|
+
// Lazy-loaded Database constructor
|
|
23
|
+
let Database = null;
|
|
24
|
+
let moduleLoadError = null;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Load the better-sqlite3 module with auto-rebuild on version mismatch
|
|
28
|
+
* Uses synchronous require to maintain API compatibility
|
|
29
|
+
* @returns {Function} The Database constructor
|
|
30
|
+
* @throws {Error} If module cannot be loaded even after rebuild
|
|
31
|
+
*/
|
|
32
|
+
function loadDatabaseModule() {
|
|
33
|
+
// Return cached module if already loaded
|
|
34
|
+
if (Database) return Database;
|
|
35
|
+
|
|
36
|
+
// Re-throw cached error if previous load failed permanently
|
|
37
|
+
if (moduleLoadError) throw moduleLoadError;
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
Database = require('better-sqlite3');
|
|
41
|
+
return Database;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
if (isModuleVersionError(error)) {
|
|
44
|
+
logger.warn('[Database] Native module version mismatch detected');
|
|
45
|
+
|
|
46
|
+
if (attemptAutoRebuild(error)) {
|
|
47
|
+
// Clear require cache and retry
|
|
48
|
+
try {
|
|
49
|
+
const resolvedPath = require.resolve('better-sqlite3');
|
|
50
|
+
// Clear the module and all its dependencies from cache
|
|
51
|
+
clearRequireCache(resolvedPath, require.cache);
|
|
52
|
+
|
|
53
|
+
Database = require('better-sqlite3');
|
|
54
|
+
logger.success('[Database] Module reloaded successfully after rebuild');
|
|
55
|
+
return Database;
|
|
56
|
+
} catch (retryError) {
|
|
57
|
+
// Rebuild succeeded but reload failed - user needs to restart
|
|
58
|
+
moduleLoadError = new NativeModuleError(
|
|
59
|
+
'Native module rebuild completed. Please restart the server to apply the fix.',
|
|
60
|
+
true, // rebuildSucceeded
|
|
61
|
+
true // restartRequired
|
|
62
|
+
);
|
|
63
|
+
logger.info('[Database] Rebuild succeeded - server restart required');
|
|
64
|
+
throw moduleLoadError;
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
moduleLoadError = new NativeModuleError(
|
|
68
|
+
'Failed to auto-rebuild native module. Please run manually:\n' +
|
|
69
|
+
' npm rebuild better-sqlite3\n' +
|
|
70
|
+
'Or if using npx, find the package location in the error and run:\n' +
|
|
71
|
+
' cd /path/to/better-sqlite3 && npm rebuild',
|
|
72
|
+
false, // rebuildSucceeded
|
|
73
|
+
false // restartRequired
|
|
74
|
+
);
|
|
75
|
+
throw moduleLoadError;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Non-version-mismatch error, just throw it
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
13
83
|
|
|
14
84
|
/**
|
|
15
85
|
* Query Antigravity database for authentication status
|
|
@@ -18,10 +88,11 @@ import { ANTIGRAVITY_DB_PATH } from '../constants.js';
|
|
|
18
88
|
* @throws {Error} If database doesn't exist, query fails, or no auth status found
|
|
19
89
|
*/
|
|
20
90
|
export function getAuthStatus(dbPath = ANTIGRAVITY_DB_PATH) {
|
|
91
|
+
const Db = loadDatabaseModule();
|
|
21
92
|
let db;
|
|
22
93
|
try {
|
|
23
94
|
// Open database in read-only mode
|
|
24
|
-
db = new
|
|
95
|
+
db = new Db(dbPath, {
|
|
25
96
|
readonly: true,
|
|
26
97
|
fileMustExist: true
|
|
27
98
|
});
|
|
@@ -56,6 +127,10 @@ export function getAuthStatus(dbPath = ANTIGRAVITY_DB_PATH) {
|
|
|
56
127
|
if (error.message.includes('No auth status') || error.message.includes('missing apiKey')) {
|
|
57
128
|
throw error;
|
|
58
129
|
}
|
|
130
|
+
// Re-throw native module errors from loadDatabaseModule without wrapping
|
|
131
|
+
if (error instanceof NativeModuleError) {
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
59
134
|
throw new Error(`Failed to read Antigravity database: ${error.message}`);
|
|
60
135
|
} finally {
|
|
61
136
|
// Always close database connection
|
|
@@ -73,7 +148,8 @@ export function getAuthStatus(dbPath = ANTIGRAVITY_DB_PATH) {
|
|
|
73
148
|
export function isDatabaseAccessible(dbPath = ANTIGRAVITY_DB_PATH) {
|
|
74
149
|
let db;
|
|
75
150
|
try {
|
|
76
|
-
|
|
151
|
+
const Db = loadDatabaseModule();
|
|
152
|
+
db = new Db(dbPath, {
|
|
77
153
|
readonly: true,
|
|
78
154
|
fileMustExist: true
|
|
79
155
|
});
|
package/src/auth/oauth.js
CHANGED
|
@@ -131,10 +131,10 @@ export function startCallbackServer(expectedState, timeoutMs = 120000) {
|
|
|
131
131
|
const error = url.searchParams.get('error');
|
|
132
132
|
|
|
133
133
|
if (error) {
|
|
134
|
-
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
134
|
+
res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
135
135
|
res.end(`
|
|
136
136
|
<html>
|
|
137
|
-
<head><title>Authentication Failed</title></head>
|
|
137
|
+
<head><meta charset="UTF-8"><title>Authentication Failed</title></head>
|
|
138
138
|
<body style="font-family: system-ui; padding: 40px; text-align: center;">
|
|
139
139
|
<h1 style="color: #dc3545;">❌ Authentication Failed</h1>
|
|
140
140
|
<p>Error: ${error}</p>
|
|
@@ -148,10 +148,10 @@ export function startCallbackServer(expectedState, timeoutMs = 120000) {
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
if (state !== expectedState) {
|
|
151
|
-
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
151
|
+
res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
152
152
|
res.end(`
|
|
153
153
|
<html>
|
|
154
|
-
<head><title>Authentication Failed</title></head>
|
|
154
|
+
<head><meta charset="UTF-8"><title>Authentication Failed</title></head>
|
|
155
155
|
<body style="font-family: system-ui; padding: 40px; text-align: center;">
|
|
156
156
|
<h1 style="color: #dc3545;">❌ Authentication Failed</h1>
|
|
157
157
|
<p>State mismatch - possible CSRF attack.</p>
|
|
@@ -165,10 +165,10 @@ export function startCallbackServer(expectedState, timeoutMs = 120000) {
|
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
if (!code) {
|
|
168
|
-
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
168
|
+
res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
169
169
|
res.end(`
|
|
170
170
|
<html>
|
|
171
|
-
<head><title>Authentication Failed</title></head>
|
|
171
|
+
<head><meta charset="UTF-8"><title>Authentication Failed</title></head>
|
|
172
172
|
<body style="font-family: system-ui; padding: 40px; text-align: center;">
|
|
173
173
|
<h1 style="color: #dc3545;">❌ Authentication Failed</h1>
|
|
174
174
|
<p>No authorization code received.</p>
|
|
@@ -182,10 +182,10 @@ export function startCallbackServer(expectedState, timeoutMs = 120000) {
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
// Success!
|
|
185
|
-
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
185
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
186
186
|
res.end(`
|
|
187
187
|
<html>
|
|
188
|
-
<head><title>Authentication Successful</title></head>
|
|
188
|
+
<head><meta charset="UTF-8"><title>Authentication Successful</title></head>
|
|
189
189
|
<body style="font-family: system-ui; padding: 40px; text-align: center;">
|
|
190
190
|
<h1 style="color: #28a745;">✅ Authentication Successful!</h1>
|
|
191
191
|
<p>You can close this window and return to the terminal.</p>
|
package/src/constants.js
CHANGED
|
@@ -74,7 +74,7 @@ export const ACCOUNT_CONFIG_PATH = join(
|
|
|
74
74
|
// Uses platform-specific path detection
|
|
75
75
|
export const ANTIGRAVITY_DB_PATH = getAntigravityDbPath();
|
|
76
76
|
|
|
77
|
-
export const DEFAULT_COOLDOWN_MS =
|
|
77
|
+
export const DEFAULT_COOLDOWN_MS = 10 * 1000; // 10 second default cooldown
|
|
78
78
|
export const MAX_RETRIES = 5; // Max retry attempts across accounts
|
|
79
79
|
export const MAX_ACCOUNTS = 10; // Maximum number of accounts allowed
|
|
80
80
|
|
package/src/errors.js
CHANGED
|
@@ -118,6 +118,23 @@ export class ApiError extends AntigravityError {
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Native module error (version mismatch, rebuild required)
|
|
123
|
+
*/
|
|
124
|
+
export class NativeModuleError extends AntigravityError {
|
|
125
|
+
/**
|
|
126
|
+
* @param {string} message - Error message
|
|
127
|
+
* @param {boolean} rebuildSucceeded - Whether auto-rebuild succeeded
|
|
128
|
+
* @param {boolean} restartRequired - Whether server restart is needed
|
|
129
|
+
*/
|
|
130
|
+
constructor(message, rebuildSucceeded = false, restartRequired = false) {
|
|
131
|
+
super(message, 'NATIVE_MODULE_ERROR', false, { rebuildSucceeded, restartRequired });
|
|
132
|
+
this.name = 'NativeModuleError';
|
|
133
|
+
this.rebuildSucceeded = rebuildSucceeded;
|
|
134
|
+
this.restartRequired = restartRequired;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
121
138
|
/**
|
|
122
139
|
* Check if an error is a rate limit error
|
|
123
140
|
* Works with both custom error classes and legacy string-based errors
|
|
@@ -154,6 +171,7 @@ export default {
|
|
|
154
171
|
NoAccountsError,
|
|
155
172
|
MaxRetriesError,
|
|
156
173
|
ApiError,
|
|
174
|
+
NativeModuleError,
|
|
157
175
|
isRateLimitError,
|
|
158
176
|
isAuthError
|
|
159
177
|
};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Module Helper
|
|
3
|
+
* Detects and auto-rebuilds native Node.js modules when they become
|
|
4
|
+
* incompatible after a Node.js version update.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
import { dirname, join } from 'path';
|
|
9
|
+
import { existsSync } from 'fs';
|
|
10
|
+
import { logger } from './logger.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Check if an error is a NODE_MODULE_VERSION mismatch error
|
|
14
|
+
* @param {Error} error - The error to check
|
|
15
|
+
* @returns {boolean} True if it's a version mismatch error
|
|
16
|
+
*/
|
|
17
|
+
export function isModuleVersionError(error) {
|
|
18
|
+
const message = error?.message || '';
|
|
19
|
+
return message.includes('NODE_MODULE_VERSION') &&
|
|
20
|
+
message.includes('was compiled against a different Node.js version');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Extract the module path from a NODE_MODULE_VERSION error message
|
|
25
|
+
* @param {Error} error - The error containing the module path
|
|
26
|
+
* @returns {string|null} The path to the .node file, or null if not found
|
|
27
|
+
*/
|
|
28
|
+
export function extractModulePath(error) {
|
|
29
|
+
const message = error?.message || '';
|
|
30
|
+
// Match pattern like: "The module '/path/to/module.node'"
|
|
31
|
+
const match = message.match(/The module '([^']+\.node)'/);
|
|
32
|
+
return match ? match[1] : null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Find the package root directory from a .node file path
|
|
37
|
+
* @param {string} nodeFilePath - Path to the .node file
|
|
38
|
+
* @returns {string|null} Path to the package root, or null if not found
|
|
39
|
+
*/
|
|
40
|
+
export function findPackageRoot(nodeFilePath) {
|
|
41
|
+
// Walk up from the .node file to find package.json
|
|
42
|
+
let dir = dirname(nodeFilePath);
|
|
43
|
+
while (dir) {
|
|
44
|
+
const packageJsonPath = join(dir, 'package.json');
|
|
45
|
+
if (existsSync(packageJsonPath)) {
|
|
46
|
+
return dir;
|
|
47
|
+
}
|
|
48
|
+
const parentDir = dirname(dir);
|
|
49
|
+
// Stop when we've reached the filesystem root (dirname returns same path)
|
|
50
|
+
if (parentDir === dir) {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
dir = parentDir;
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Attempt to rebuild a native module
|
|
60
|
+
* @param {string} packagePath - Path to the package root directory
|
|
61
|
+
* @returns {boolean} True if rebuild succeeded, false otherwise
|
|
62
|
+
*/
|
|
63
|
+
export function rebuildModule(packagePath) {
|
|
64
|
+
try {
|
|
65
|
+
logger.info(`[NativeModule] Rebuilding native module at: ${packagePath}`);
|
|
66
|
+
|
|
67
|
+
// Run npm rebuild in the package directory
|
|
68
|
+
const output = execSync('npm rebuild', {
|
|
69
|
+
cwd: packagePath,
|
|
70
|
+
stdio: 'pipe', // Capture output instead of printing
|
|
71
|
+
timeout: 120000 // 2 minute timeout
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Log rebuild output for debugging
|
|
75
|
+
const outputStr = output?.toString().trim();
|
|
76
|
+
if (outputStr) {
|
|
77
|
+
logger.debug(`[NativeModule] Rebuild output:\n${outputStr}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
logger.success('[NativeModule] Rebuild completed successfully');
|
|
81
|
+
return true;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
// Include stdout/stderr from the failed command for troubleshooting
|
|
84
|
+
const stdout = error.stdout?.toString().trim();
|
|
85
|
+
const stderr = error.stderr?.toString().trim();
|
|
86
|
+
let errorDetails = `[NativeModule] Rebuild failed: ${error.message}`;
|
|
87
|
+
if (stdout) {
|
|
88
|
+
errorDetails += `\n[NativeModule] stdout: ${stdout}`;
|
|
89
|
+
}
|
|
90
|
+
if (stderr) {
|
|
91
|
+
errorDetails += `\n[NativeModule] stderr: ${stderr}`;
|
|
92
|
+
}
|
|
93
|
+
logger.error(errorDetails);
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Attempt to auto-rebuild a native module from an error
|
|
100
|
+
* @param {Error} error - The NODE_MODULE_VERSION error
|
|
101
|
+
* @returns {boolean} True if rebuild succeeded, false otherwise
|
|
102
|
+
*/
|
|
103
|
+
export function attemptAutoRebuild(error) {
|
|
104
|
+
const nodePath = extractModulePath(error);
|
|
105
|
+
if (!nodePath) {
|
|
106
|
+
logger.error('[NativeModule] Could not extract module path from error');
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const packagePath = findPackageRoot(nodePath);
|
|
111
|
+
if (!packagePath) {
|
|
112
|
+
logger.error('[NativeModule] Could not find package root');
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
logger.warn('[NativeModule] Native module version mismatch detected');
|
|
117
|
+
logger.info('[NativeModule] Attempting automatic rebuild...');
|
|
118
|
+
|
|
119
|
+
return rebuildModule(packagePath);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Recursively clear a module and its dependencies from the require cache
|
|
124
|
+
* This is needed after rebuilding a native module to force re-import
|
|
125
|
+
* @param {string} modulePath - Resolved path to the module
|
|
126
|
+
* @param {object} cache - The require.cache object
|
|
127
|
+
* @param {Set} [visited] - Set of already-visited paths to prevent cycles
|
|
128
|
+
*/
|
|
129
|
+
export function clearRequireCache(modulePath, cache, visited = new Set()) {
|
|
130
|
+
if (visited.has(modulePath)) return;
|
|
131
|
+
visited.add(modulePath);
|
|
132
|
+
|
|
133
|
+
const mod = cache[modulePath];
|
|
134
|
+
if (!mod) return;
|
|
135
|
+
|
|
136
|
+
// Recursively clear children first
|
|
137
|
+
if (mod.children) {
|
|
138
|
+
for (const child of mod.children) {
|
|
139
|
+
clearRequireCache(child.id, cache, visited);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Remove from parent's children array
|
|
144
|
+
if (mod.parent && mod.parent.children) {
|
|
145
|
+
const idx = mod.parent.children.indexOf(mod);
|
|
146
|
+
if (idx !== -1) {
|
|
147
|
+
mod.parent.children.splice(idx, 1);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Delete from cache
|
|
152
|
+
delete cache[modulePath];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export default {
|
|
156
|
+
isModuleVersionError,
|
|
157
|
+
extractModulePath,
|
|
158
|
+
findPackageRoot,
|
|
159
|
+
rebuildModule,
|
|
160
|
+
attemptAutoRebuild,
|
|
161
|
+
clearRequireCache
|
|
162
|
+
};
|