#!/usr/bin/env node const { spawn, execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); const RESET = '\x1b[0m'; const BOLD = '\x1b[1m'; const GREEN = '\x1b[32m'; const YELLOW = '\x1b[33m'; const RED = '\x1b[31m'; const CYAN = '\x1b[36m'; const DIM = '\x1b[90m'; function log(msg) { console.log(msg); } function logSuccess(msg) { console.log(`${GREEN}✓${RESET} ${msg}`); } function logError(msg) { console.error(`${RED}✗${RESET} ${msg}`); } function logInfo(msg) { console.log(`${CYAN}ℹ${RESET} ${msg}`); } function logWarning(msg) { console.log(`${YELLOW}!${RESET} ${msg}`); } function checkPython() { const commands = ['python3', 'python']; for (const cmd of commands) { try { const result = execSync(`${cmd} --version`, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }); const match = result.match(/Python (\d+)\.(\d+)/); if (match) { const major = parseInt(match[1]); const minor = parseInt(match[2]); if (major >= 3 && minor >= 10) { return { cmd, version: result.trim() }; } } } catch {} } return null; } function installPythonDeps(pythonCmd) { return new Promise((resolve, reject) => { const packages = ['toothfairyai', 'pydantic', 'httpx', 'rich']; log(`${DIM}Installing Python packages: ${packages.join(', ')}...${RESET}`); // Try with --user first, then --break-system-packages if needed const args = ['-m', 'pip', 'install', '--user', ...packages]; const proc = spawn(pythonCmd, args, { stdio: 'inherit', shell: process.platform === 'win32' }); proc.on('close', (code) => { if (code === 0) { resolve(); } else { // Try with --break-system-packages flag log(`${DIM}Retrying with --break-system-packages...${RESET}`); const retryArgs = ['-m', 'pip', 'install', '--user', '--break-system-packages', ...packages]; const retry = spawn(pythonCmd, retryArgs, { stdio: 'inherit', shell: process.platform === 'win32' }); retry.on('close', (retryCode) => { if (retryCode === 0) { resolve(); } else { reject(new Error(`pip install exited with code ${retryCode}`)); } }); retry.on('error', (err) => { reject(err); }); } }); proc.on('error', (err) => { reject(err); }); }); } async function main() { log(''); log(`${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`); log(`${BOLD} tfcode - ToothFairyAI's official coding agent${RESET}`); log(`${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`); log(''); // Check for Python logInfo('Checking Python installation...'); const python = checkPython(); if (!python) { log(''); logError('Python 3.10+ is required but not found.'); log(''); log(`${BOLD}Please install Python 3.10 or later:${RESET}`); log(''); log(` ${CYAN}macOS:${RESET} brew install python@3.12`); log(` ${CYAN}Ubuntu:${RESET} sudo apt-get install python3.12`); log(` ${CYAN}Windows:${RESET} Download from https://python.org/downloads`); log(''); log(`${DIM}After installing Python, run: npm rebuild tfcode${RESET}`); log(''); process.exit(1); } logSuccess(`Found ${python.version} (${python.cmd})`); log(''); // Install Python dependencies logInfo('Installing ToothFairyAI Python SDK...'); try { await installPythonDeps(python.cmd); logSuccess('Python dependencies installed'); } catch (err) { logWarning(`Failed to install Python dependencies: ${err.message}`); log(''); log(`${DIM}You can install them manually with:${RESET}`); log(` ${CYAN}${python.cmd} -m pip install toothfairyai pydantic httpx rich${RESET}`); log(''); // Don't exit - user might install manually later } log(''); log(`${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`); log(`${GREEN}✓ tfcode installed successfully!${RESET}`); log(`${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`); log(''); log(`${BOLD}Quick Start:${RESET}`); log(''); log(` ${CYAN}1.${RESET} Set your ToothFairyAI credentials:`); log(` ${DIM}export TF_WORKSPACE_ID="your-workspace-id"${RESET}`); log(` ${DIM}export TF_API_KEY="your-api-key"${RESET}`); log(''); log(` ${CYAN}2.${RESET} Validate your credentials:`); log(` ${DIM}tfcode validate${RESET}`); log(''); log(` ${CYAN}3.${RESET} Sync tools from your workspace:`); log(` ${DIM}tfcode sync${RESET}`); log(''); log(` ${CYAN}4.${RESET} Start coding:`); log(` ${DIM}tfcode${RESET}`); log(''); log(`${DIM}Documentation: https://toothfairyai.com/developers/tfcode${RESET}`); log(''); } main().catch((err) => { logError(`Installation failed: ${err.message}`); process.exit(1); });