badri-s commited on
Commit
f7b1814
·
1 Parent(s): d75e09a

feat: Implement intelligent Antigravity version detection and dynamic User-Agent generation with platform-specific logic and tests.

Browse files
src/constants.js CHANGED
@@ -6,6 +6,7 @@
6
  import { homedir, platform, arch } from 'os';
7
  import { join } from 'path';
8
  import { config } from './config.js';
 
9
 
10
  /**
11
  * Get the Antigravity database path based on the current platform.
@@ -31,9 +32,7 @@ function getAntigravityDbPath() {
31
  * @returns {string} User-Agent in format "antigravity/version os/arch"
32
  */
33
  export function getPlatformUserAgent() {
34
- const os = platform();
35
- const architecture = arch();
36
- return `antigravity/1.16.5 ${os}/${architecture}`;
37
  }
38
 
39
  // IDE Type enum (numeric values as expected by Cloud Code API)
 
6
  import { homedir, platform, arch } from 'os';
7
  import { join } from 'path';
8
  import { config } from './config.js';
9
+ import { generateSmartUserAgent } from './utils/version-detector.js';
10
 
11
  /**
12
  * Get the Antigravity database path based on the current platform.
 
32
  * @returns {string} User-Agent in format "antigravity/version os/arch"
33
  */
34
  export function getPlatformUserAgent() {
35
+ return generateSmartUserAgent();
 
 
36
  }
37
 
38
  // IDE Type enum (numeric values as expected by Cloud Code API)
src/utils/version-detector.js ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { execSync } from 'child_process';
2
+ import { platform, homedir } from 'os';
3
+ import { join } from 'path';
4
+ import { existsSync } from 'fs';
5
+
6
+ /**
7
+ * Intelligent Version Detection for Antigravity
8
+ * Attempts to find the local installation and extract its version.
9
+ * Falls back to hard-coded stable versions if detection fails.
10
+ */
11
+
12
+ // Fallback constant
13
+ const FALLBACK_ANTIGRAVITY_VERSION = '1.16.5';
14
+
15
+ // Cache for the generated User-Agent string
16
+ let cachedUserAgent = null;
17
+
18
+ /**
19
+ * Compares two semver-ish version strings (X.Y.Z).
20
+ * @param {string} v1 - Version string 1
21
+ * @param {string} v2 - Version string 2
22
+ * @returns {boolean} True if v1 > v2
23
+ */
24
+ function isVersionHigher(v1, v2) {
25
+ const parts1 = v1.split('.').map(Number);
26
+ const parts2 = v2.split('.').map(Number);
27
+
28
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
29
+ const p1 = parts1[i] || 0;
30
+ const p2 = parts2[i] || 0;
31
+ if (p1 > p2) return true;
32
+ if (p1 < p2) return false;
33
+ }
34
+ return false;
35
+ }
36
+
37
+ /**
38
+ * Gets the version config (version, source)
39
+ * @returns {{ version: string, source: string }}
40
+ */
41
+ function getVersionConfig() {
42
+ const os = platform();
43
+ let detectedVersion = null;
44
+ let finalVersion = FALLBACK_ANTIGRAVITY_VERSION;
45
+ let source = 'fallback';
46
+
47
+ try {
48
+ if (os === 'darwin') {
49
+ detectedVersion = getVersionMacos();
50
+ } else if (os === 'win32') {
51
+ detectedVersion = getVersionWindows();
52
+ }
53
+ } catch (error) {
54
+ // Silently fail and use fallback
55
+ }
56
+
57
+ // Only use detected version if it's higher than the fallback version
58
+ if (detectedVersion && isVersionHigher(detectedVersion, FALLBACK_ANTIGRAVITY_VERSION)) {
59
+ finalVersion = detectedVersion;
60
+ source = 'local';
61
+ }
62
+
63
+ return {
64
+ version: finalVersion,
65
+ source
66
+ };
67
+ }
68
+
69
+ /**
70
+ * Generate a simplified User-Agent string used by the Antigravity binary.
71
+ * Format: "antigravity/version os/arch"
72
+ * @returns {string} The User-Agent string
73
+ */
74
+ export function generateSmartUserAgent() {
75
+ if (cachedUserAgent) return cachedUserAgent;
76
+
77
+ const { version } = getVersionConfig();
78
+ const os = platform();
79
+ const architecture = process.arch;
80
+
81
+ // Map Node.js platform names to binary-friendly names
82
+ const osName = os === 'darwin' ? 'darwin' : (os === 'win32' ? 'win32' : 'linux');
83
+
84
+ cachedUserAgent = `antigravity/${version} ${osName}/${architecture}`;
85
+ return cachedUserAgent;
86
+ }
87
+
88
+ /**
89
+ * MacOS-specific version detection using plutil
90
+ */
91
+ function getVersionMacos() {
92
+ const appPath = '/Applications/Antigravity.app';
93
+ const plistPath = join(appPath, 'Contents/Info.plist');
94
+
95
+ if (!existsSync(plistPath)) return null;
96
+
97
+ try {
98
+ const version = execSync(`plutil -extract CFBundleShortVersionString raw "${plistPath}"`, { encoding: 'utf8' }).trim();
99
+ if (/^\d+\.\d+\.\d+/.test(version)) {
100
+ return version;
101
+ }
102
+ } catch (e) {
103
+ // plutil failed or file not found
104
+ }
105
+ return null;
106
+ }
107
+
108
+ /**
109
+ * Windows-specific version detection using PowerShell
110
+ */
111
+ function getVersionWindows() {
112
+ try {
113
+ const localAppData = process.env.LOCALAPPDATA;
114
+ const programFiles = process.env.ProgramFiles || 'C:\\Program Files';
115
+
116
+ const possiblePaths = [
117
+ join(localAppData, 'Programs', 'Antigravity', 'Antigravity.exe'),
118
+ join(programFiles, 'Antigravity', 'Antigravity.exe')
119
+ ];
120
+
121
+ for (const exePath of possiblePaths) {
122
+ if (existsSync(exePath)) {
123
+ const cmd = `powershell -Command "(Get-Item '${exePath}').VersionInfo.FileVersion"`;
124
+ const version = execSync(cmd, { encoding: 'utf8' }).trim();
125
+ const match = version.match(/^(\d+\.\d+\.\d+)/);
126
+ if (match) return match[1];
127
+ }
128
+ }
129
+ } catch (e) {
130
+ // PowerShell or path issues
131
+ }
132
+ return null;
133
+ }
134
+
tests/run-all.cjs CHANGED
@@ -23,7 +23,8 @@ const tests = [
23
  { name: 'Schema Sanitizer', file: 'test-schema-sanitizer.cjs' },
24
  { name: 'Streaming Whitespace', file: 'test-streaming-whitespace.cjs' },
25
  { name: '403 Account Rotation (Unit)', file: 'test-403-account-rotation.cjs' },
26
- { name: '403 Account Rotation (Integration)', file: 'test-403-integration.cjs' }
 
27
  ];
28
 
29
  async function runTest(test) {
 
23
  { name: 'Schema Sanitizer', file: 'test-schema-sanitizer.cjs' },
24
  { name: 'Streaming Whitespace', file: 'test-streaming-whitespace.cjs' },
25
  { name: '403 Account Rotation (Unit)', file: 'test-403-account-rotation.cjs' },
26
+ { name: '403 Account Rotation (Integration)', file: 'test-403-integration.cjs' },
27
+ { name: 'Version Detection', file: 'test-version-detection.js' }
28
  ];
29
 
30
  async function runTest(test) {
tests/test-version-detection.js ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { generateSmartUserAgent } from '../src/utils/version-detector.js';
2
+ import { getPlatformUserAgent } from '../src/constants.js';
3
+ import assert from 'assert';
4
+
5
+ async function testVersionDetection() {
6
+ console.log('--- Testing Version Detection ---');
7
+
8
+ // 1. Check User-Agent generation
9
+ const ua = generateSmartUserAgent();
10
+ console.log('Generated User-Agent:', ua);
11
+
12
+ assert.ok(ua.startsWith('antigravity/'), 'UA should start with antigravity/');
13
+ assert.ok(/\d+\.\d+\.\d+/.test(ua), 'UA should contain a version number');
14
+
15
+ // 2. Check integration in constants.js
16
+ const constantsUA = getPlatformUserAgent();
17
+ console.log('Constants User-Agent:', constantsUA);
18
+ assert.strictEqual(ua, constantsUA, 'Constants UA should match generated UA');
19
+
20
+ console.log('\n✓ Version detection tests passed!');
21
+ }
22
+
23
+ testVersionDetection().catch(err => {
24
+ console.error('\n✗ Version detection tests failed:');
25
+ console.error(err);
26
+ process.exit(1);
27
+ });