jay-code
Version:
Streamlined AI CLI orchestration engine with mathematical rigor and enterprise-grade reliability
249 lines (217 loc) • 7.36 kB
JavaScript
import os from 'node:os';
import path from 'node:path';
import fs from 'node:fs';
import { spawn, exec } from 'node:child_process';
import { promisify } from 'util';
const execAsync = promisify(exec);
console.log('Jay-Code Full Uninstall: Removing Jay-Code and all AI components');
async function removeJayCodePackage() {
console.log('Removing Jay-Code npm package...');
try {
await execAsync('npm uninstall -g jay-code');
console.log('Global package removed');
return true;
} catch (globalError) {
try {
await execAsync('npm uninstall jay-code');
console.log('Local package removed');
return true;
} catch (localError) {
console.log('Package may not be installed');
return false;
}
}
}
async function removeConfiguration() {
const configDir = path.join(os.homedir(), '.jay-code');
try {
if (fs.existsSync(configDir)) {
console.log('Removing Jay-Code configuration...');
await fs.promises.rm(configDir, { recursive: true, force: true });
console.log('Configuration removed');
return true;
}
return true;
} catch (error) {
console.error('Failed to remove configuration:', error.message);
return false;
}
}
async function removeOllamaModels() {
console.log('Removing Ollama models...');
try {
const { stdout } = await execAsync('ollama list');
const models = stdout.split('\n')
.slice(1) // Skip header
.filter(line => line.trim())
.map(line => line.split(/\s+/)[0])
.filter(model => model && model !== 'NAME');
console.log(`Found ${models.length} models to remove`);
for (const model of models) {
try {
await execAsync(`ollama rm ${model}`);
console.log(`Removed model: ${model}`);
} catch (error) {
console.log(`Failed to remove model ${model}: ${error.message}`);
}
}
return true;
} catch (error) {
console.log('Could not list Ollama models (Ollama may not be installed)');
return true;
}
}
async function removeOllama() {
console.log('Removing Ollama installation...');
const platform = process.platform;
try {
if (platform === 'darwin') {
// macOS - check if installed via Homebrew first
try {
await execAsync('brew list ollama');
await execAsync('brew uninstall ollama');
console.log('Ollama removed via Homebrew');
} catch (brewError) {
// Manual installation cleanup
const ollamaPaths = [
'/usr/local/bin/ollama',
'/opt/ollama',
path.join(os.homedir(), '.ollama')
];
for (const ollamaPath of ollamaPaths) {
try {
if (fs.existsSync(ollamaPath)) {
if (fs.lstatSync(ollamaPath).isDirectory()) {
await fs.promises.rm(ollamaPath, { recursive: true, force: true });
} else {
await fs.promises.unlink(ollamaPath);
}
console.log(`Removed: ${ollamaPath}`);
}
} catch (error) {
console.log(`Could not remove ${ollamaPath}: ${error.message}`);
}
}
}
} else if (platform === 'linux') {
// Linux cleanup
const ollamaPaths = [
'/usr/local/bin/ollama',
'/usr/bin/ollama',
path.join(os.homedir(), '.ollama'),
'/etc/systemd/system/ollama.service'
];
// Stop service first
try {
await execAsync('sudo systemctl stop ollama');
await execAsync('sudo systemctl disable ollama');
console.log('Ollama service stopped');
} catch (error) {
// Service may not be running
}
for (const ollamaPath of ollamaPaths) {
try {
if (fs.existsSync(ollamaPath)) {
if (ollamaPath.includes('/etc/systemd/')) {
await execAsync(`sudo rm -f ${ollamaPath}`);
} else if (fs.lstatSync(ollamaPath).isDirectory()) {
await fs.promises.rm(ollamaPath, { recursive: true, force: true });
} else {
await fs.promises.unlink(ollamaPath);
}
console.log(`Removed: ${ollamaPath}`);
}
} catch (error) {
console.log(`Could not remove ${ollamaPath}: ${error.message}`);
}
}
// Reload systemd
try {
await execAsync('sudo systemctl daemon-reload');
} catch (error) {
// Continue
}
}
return true;
} catch (error) {
console.error('Ollama removal failed:', error.message);
return false;
}
}
async function cleanupEnvironment() {
console.log('Cleaning environment variables...');
const shellFiles = [
path.join(os.homedir(), '.bashrc'),
path.join(os.homedir(), '.zshrc'),
path.join(os.homedir(), '.profile')
];
for (const shellFile of shellFiles) {
try {
if (fs.existsSync(shellFile)) {
const content = await fs.promises.readFile(shellFile, 'utf8');
if (content.includes('jay-code') || content.includes('ollama')) {
console.log(`Found references in ${shellFile}`);
console.log('Please manually remove jay-code/ollama PATH additions');
}
}
} catch (error) {
// Continue silently
}
}
}
async function confirmDestruction() {
return new Promise((resolve) => {
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
readline.question('This will remove ALL AI models and data. Continue? (yes/no): ', (answer) => {
readline.close();
resolve(answer.toLowerCase() === 'yes');
});
});
}
async function main() {
console.log('\n=== Jay-Code Full Uninstall ===\n');
console.log('This will remove:');
console.log('- Jay-Code package and configuration');
console.log('- Ollama installation');
console.log('- All downloaded AI models');
console.log('- All related data (IRREVERSIBLE)');
if (process.argv.includes('--force')) {
console.log('\nForce flag detected, proceeding without confirmation...');
} else {
const confirmed = await confirmDestruction();
if (!confirmed) {
console.log('Uninstall cancelled');
process.exit(0);
}
}
console.log('\nProceeding with full uninstall...\n');
const results = {
package: await removeJayCodePackage(),
config: await removeConfiguration(),
models: await removeOllamaModels(),
ollama: await removeOllama()
};
await cleanupEnvironment();
console.log('\n=== Full Uninstall Summary ===');
Object.entries(results).forEach(([step, success]) => {
const status = success ? 'SUCCESS' : 'FAILED';
console.log(`${step}: ${status}`);
});
const overallSuccess = Object.values(results).filter(Boolean).length >= 3;
if (overallSuccess) {
console.log('\nFull uninstall completed successfully');
console.log('All Jay-Code and AI components removed');
console.log('System restored to pre-installation state');
} else {
console.log('\nUninstall completed with some issues');
console.log('Manual cleanup may be required for remaining components');
}
}
main().catch(error => {
console.error('Full uninstall failed:', error.message);
process.exit(1);
});