/** * Workspace Fleet Manager * * Manages dynamic GCP workers for workspaces tasks. */ import { spawnSync } from 'child_process'; import path from 'path'; import fs from 'fs'; import { fileURLToPath } from 'url'; import { ProviderFactory } from './providers/ProviderFactory.ts'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = path.resolve(__dirname, '../../../..'); const USER = process.env.USER || 'mattkorwel'; const INSTANCE_PREFIX = `gcli-workspace-${USER}`; const DEFAULT_ZONE = 'us-west1-a'; function getProjectId(): string { const settingsPath = path.join(REPO_ROOT, '.gemini/workspaces/settings.json'); if (fs.existsSync(settingsPath)) { try { const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8')); return settings.workspace?.projectId; } catch (e) {} } return process.env.GOOGLE_CLOUD_PROJECT || ''; } async function listWorkers() { const projectId = getProjectId(); if (!projectId) { console.error('❌ Project ID not found. Run "npm run workspace:setup" first.'); return; } console.log(`🔍 Listing Workspace Workers for ${USER} in ${projectId}...`); spawnSync('gcloud', [ 'compute', 'instances', 'list', '--project', projectId, '--filter', `name~^${INSTANCE_PREFIX}`, '--format', 'table(name,zone,status,networkInterfaces[0].networkIP:label=INTERNAL_IP,creationTimestamp)' ], { stdio: 'inherit' }); } async function provisionWorker() { const projectId = getProjectId(); if (!projectId) { console.error('❌ Project ID not found. Run "npm run workspace:setup" first.'); return; } const provider = ProviderFactory.getProvider({ projectId: projectId, zone: DEFAULT_ZONE, instanceName: INSTANCE_PREFIX }); const status = await provider.getStatus(); if (status.status !== 'UNKNOWN' && status.status !== 'ERROR') { console.log(`✅ Worker ${INSTANCE_PREFIX} already exists and is ${status.status}.`); return; } await provider.provision(); } async function stopWorker() { const projectId = getProjectId(); const provider = ProviderFactory.getProvider({ projectId: projectId, zone: DEFAULT_ZONE, instanceName: INSTANCE_PREFIX }); console.log(`🛑 Stopping workspace worker: ${INSTANCE_PREFIX}...`); await provider.stop(); } async function rebuildWorker() { const projectId = getProjectId(); console.log(`🔥 Rebuilding worker ${INSTANCE_PREFIX}...`); const knownHostsPath = path.join(REPO_ROOT, '.gemini/workspaces_known_hosts'); if (fs.existsSync(knownHostsPath)) { console.log(` - Clearing isolated known_hosts...`); fs.unlinkSync(knownHostsPath); } spawnSync('gcloud', ['compute', 'instances', 'delete', INSTANCE_PREFIX, '--project', projectId, '--zone', DEFAULT_ZONE, '--quiet'], { stdio: 'inherit' }); await provisionWorker(); } async function main() { const action = process.argv[2] || 'list'; switch (action) { case 'list': await listWorkers(); break; case 'provision': await provisionWorker(); break; case 'rebuild': await rebuildWorker(); break; case 'stop': await stopWorker(); break; default: console.error(`❌ Unknown fleet action: ${action}`); process.exit(1); } } main().catch(console.error);