mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-03-31 14:22:27 +00:00
feat: sync
This commit is contained in:
171
packages/tfcode/scripts/postinstall.cjs
Normal file
171
packages/tfcode/scripts/postinstall.cjs
Normal file
@@ -0,0 +1,171 @@
|
||||
#!/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);
|
||||
});
|
||||
Reference in New Issue
Block a user