claude-gemini-multimodal-bridge
Version:
Enterprise-grade AI integration bridge connecting Claude Code, Gemini CLI, and Google AI Studio with intelligent routing and advanced multimodal processing capabilities
138 lines (137 loc) • 4.06 kB
JavaScript
import { execSync } from 'child_process';
import { existsSync, mkdirSync } from 'fs';
import { join, normalize } from 'path';
import { homedir } from 'os';
const isWindows = process.platform === 'win32';
export function findExecutable(command) {
try {
const cmd = isWindows
? `where ${command} 2>nul`
: `which ${command} 2>/dev/null`;
const output = execSync(cmd, {
encoding: 'utf8',
timeout: 5000,
stdio: ['pipe', 'pipe', 'pipe']
});
return output.split('\n')[0]?.trim() || undefined;
}
catch {
return undefined;
}
}
export function commandExists(command) {
try {
const cmd = isWindows
? `where ${command} 2>nul`
: `which ${command} 2>/dev/null`;
execSync(cmd, { stdio: 'ignore', timeout: 5000 });
return true;
}
catch {
return false;
}
}
export function getHomeDir() {
const home = homedir();
if (home) {
return home;
}
if (isWindows) {
return process.env.USERPROFILE || process.env.HOME || 'C:\\Users\\Default';
}
return process.env.HOME || '/home';
}
export function getConfigDir() {
if (isWindows) {
const appData = process.env.APPDATA;
if (appData) {
return join(appData, 'claude-code');
}
return join(getHomeDir(), '.config', 'claude-code');
}
return join(getHomeDir(), '.config', 'claude-code');
}
export function ensureDirectory(dir) {
const normalizedDir = normalize(dir);
if (!existsSync(normalizedDir)) {
mkdirSync(normalizedDir, { recursive: true });
}
}
export function ensureOutputDirectory(type) {
const baseDir = process.cwd();
const outputDir = join(baseDir, 'output', type);
ensureDirectory(outputDir);
return outputDir;
}
export function normalizeOutputPath(relativePath) {
return normalize(join(process.cwd(), relativePath));
}
export function getDefaultExecutablePath(tool) {
if (isWindows) {
return tool === 'gemini' ? 'gemini' : 'claude';
}
const unixDefaults = {
gemini: ['/usr/local/bin/gemini', '/opt/homebrew/bin/gemini'],
claude: ['claude', '/opt/homebrew/bin/claude']
};
const paths = unixDefaults[tool] || [];
for (const p of paths) {
if (existsSync(p)) {
return p;
}
}
return tool;
}
export function getSpawnOptions(additionalOptions = {}) {
return {
...additionalOptions,
shell: isWindows
};
}
export function findProcesses(processName) {
try {
if (isWindows) {
const output = execSync(`tasklist /FI "IMAGENAME eq node.exe" /FO CSV 2>nul`, { encoding: 'utf8', timeout: 5000 });
return output
.split('\n')
.filter(line => line.toLowerCase().includes(processName.toLowerCase()));
}
else {
const output = execSync(`pgrep -f "${processName}" || true`, { encoding: 'utf8', timeout: 5000 });
return output.split('\n').filter(line => line.trim());
}
}
catch {
return [];
}
}
export function isPlatformWindows() {
return isWindows;
}
export function getNpmGlobalDir() {
if (isWindows) {
return join(process.env.APPDATA || '', 'npm');
}
return '/usr/local/lib/node_modules';
}
export function normalizeCrossPlatformPath(filePath) {
return filePath.replace(/\\/g, '/');
}
export function toPlatformPath(filePath) {
if (isWindows) {
return filePath.replace(/\//g, '\\');
}
return filePath;
}
export function resolveOutputPath(relativePath) {
const normalizedRelative = normalizeCrossPlatformPath(relativePath);
const absolutePath = join(process.cwd(), ...normalizedRelative.split('/'));
return {
normalized: normalizedRelative,
absolute: absolutePath,
native: absolutePath
};
}
export function isUrl(path) {
return path.startsWith('http://') || path.startsWith('https://');
}