agent-bridge / server /cliDetector.ts
algorembrant's picture
Upload 18 files
b9a3ef2 verified
// ---------------------------------------------------------------------------
// CLI Detector -- Real auto-detection of Google Antigravity CLI
// ---------------------------------------------------------------------------
// Multi-strategy detection:
// 1. ANTIGRAVITY_CLI_PATH env var
// 2. Search system PATH
// 3. Check common install locations
// 4. Check npm global installs
// 5. Probe for Gemini CLI as alternative
// ---------------------------------------------------------------------------
import { execSync } from 'child_process';
import fs from 'fs';
import path from 'path';
import os from 'os';
export interface CLIDetectionResult {
detected: boolean;
path: string | null;
version: string | null;
method: string;
candidates: string[];
}
const CLI_NAMES = [
'antigravity',
'antigravity.exe',
'antigravity.cmd',
'gemini',
'gemini.exe',
'gemini.cmd',
];
export async function detectCLI(): Promise<CLIDetectionResult> {
const candidates: string[] = [];
const result: CLIDetectionResult = {
detected: false,
path: null,
version: null,
method: 'none',
candidates,
};
// Strategy 1: Environment variable
const envPath = process.env.ANTIGRAVITY_CLI_PATH;
if (envPath) {
candidates.push(`[env] ${envPath}`);
const version = tryGetVersion(envPath);
if (version) {
result.detected = true;
result.path = envPath;
result.version = version;
result.method = 'env:ANTIGRAVITY_CLI_PATH';
return result;
}
}
// Strategy 2: Search system PATH using `where` (Windows) or `which` (Unix)
for (const name of CLI_NAMES) {
const found = findOnPath(name);
if (found) {
candidates.push(`[PATH] ${found}`);
const version = tryGetVersion(found);
if (version) {
result.detected = true;
result.path = found;
result.version = version;
result.method = `PATH:${name}`;
return result;
}
}
}
// Strategy 3: Common install locations
const commonPaths = getCommonInstallPaths();
for (const candidate of commonPaths) {
candidates.push(`[common] ${candidate}`);
if (fs.existsSync(candidate)) {
const version = tryGetVersion(candidate);
if (version) {
result.detected = true;
result.path = candidate;
result.version = version;
result.method = 'common-path';
return result;
}
}
}
// Strategy 4: npm global bin
try {
const npmBin = execSync('npm root -g', { timeout: 5000 }).toString().trim();
const npmParent = path.dirname(npmBin);
for (const name of CLI_NAMES) {
const candidate = path.join(npmParent, name);
candidates.push(`[npm-global] ${candidate}`);
if (fs.existsSync(candidate)) {
const version = tryGetVersion(candidate);
if (version) {
result.detected = true;
result.path = candidate;
result.version = version;
result.method = 'npm-global';
return result;
}
}
}
} catch {
// npm not available
}
// Strategy 5: Try bare command execution as last resort
for (const name of ['antigravity', 'gemini']) {
candidates.push(`[bare] ${name}`);
const version = tryGetVersion(name);
if (version) {
result.detected = true;
result.path = name;
result.version = version;
result.method = `bare:${name}`;
return result;
}
}
return result;
}
function findOnPath(name: string): string | null {
try {
const cmd = process.platform === 'win32' ? `where ${name}` : `which ${name}`;
const result = execSync(cmd, { timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] })
.toString()
.trim()
.split('\n')[0]
.trim();
return result || null;
} catch {
return null;
}
}
function tryGetVersion(cliPath: string): string | null {
const commands = [
`"${cliPath}" --version`,
`"${cliPath}" -v`,
`"${cliPath}" version`,
];
for (const cmd of commands) {
try {
const output = execSync(cmd, {
timeout: 8000,
stdio: ['pipe', 'pipe', 'pipe'],
env: { ...process.env },
}).toString().trim();
if (output && output.length < 200) {
return output;
}
} catch {
// continue to next command variant
}
}
return null;
}
function getCommonInstallPaths(): string[] {
const home = os.homedir();
const paths: string[] = [];
if (process.platform === 'win32') {
paths.push(
path.join(home, 'AppData', 'Local', 'Programs', 'antigravity', 'antigravity.exe'),
path.join(home, 'AppData', 'Local', 'antigravity', 'antigravity.exe'),
path.join(home, 'AppData', 'Roaming', 'npm', 'antigravity.cmd'),
'C:\\Program Files\\Google\\Antigravity\\antigravity.exe',
'C:\\Program Files (x86)\\Google\\Antigravity\\antigravity.exe',
path.join(home, '.local', 'bin', 'antigravity'),
// Gemini CLI alternatives
path.join(home, 'AppData', 'Local', 'Programs', 'gemini', 'gemini.exe'),
path.join(home, 'AppData', 'Roaming', 'npm', 'gemini.cmd'),
);
} else {
paths.push(
'/usr/local/bin/antigravity',
'/usr/bin/antigravity',
path.join(home, '.local', 'bin', 'antigravity'),
path.join(home, '.npm-global', 'bin', 'antigravity'),
'/usr/local/bin/gemini',
path.join(home, '.local', 'bin', 'gemini'),
);
}
return paths;
}