refactor: remove env file creation, use full path in examples
- Remove creation of paddedcell.env file - Update post-install instructions to use full pass_mgr path - Simplify to 6 steps (remove verification step) - Update uninstall to not reference env file
This commit is contained in:
176
install.mjs
176
install.mjs
@@ -12,8 +12,8 @@
|
|||||||
* node install.mjs --uninstall --prefix /usr/local
|
* node install.mjs --uninstall --prefix /usr/local
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { execSync, spawn } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
import { existsSync, mkdirSync, copyFileSync, writeFileSync, readFileSync, chmodSync } from 'fs';
|
import { existsSync, mkdirSync, copyFileSync, writeFileSync, chmodSync } from 'fs';
|
||||||
import { dirname, join, resolve } from 'path';
|
import { dirname, join, resolve } from 'path';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { homedir, platform } from 'os';
|
import { homedir, platform } from 'os';
|
||||||
@@ -53,7 +53,7 @@ function log(message, color = 'reset') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function logStep(step, message) {
|
function logStep(step, message) {
|
||||||
log(`[${step}/7] ${message}`, 'cyan');
|
log(`[${step}/6] ${message}`, 'cyan');
|
||||||
}
|
}
|
||||||
|
|
||||||
function logSuccess(message) {
|
function logSuccess(message) {
|
||||||
@@ -90,36 +90,6 @@ async function prompt(question) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function promptPassword(question) {
|
|
||||||
const rl = readline.createInterface({
|
|
||||||
input: process.stdin,
|
|
||||||
output: process.stdout,
|
|
||||||
});
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
// Hide password input
|
|
||||||
const stdin = process.stdin;
|
|
||||||
stdin.on('data', (char) => {
|
|
||||||
char = char.toString();
|
|
||||||
switch (char) {
|
|
||||||
case '\n':
|
|
||||||
case '\r':
|
|
||||||
case '\u0004':
|
|
||||||
stdin.pause();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
process.stdout.write('*');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
rl.question(question, (answer) => {
|
|
||||||
rl.close();
|
|
||||||
console.log(); // New line after password
|
|
||||||
resolve(answer.trim());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Step 1: Environment Detection
|
// Step 1: Environment Detection
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -248,7 +218,6 @@ async function buildComponents(env) {
|
|||||||
silent: !options.verbose
|
silent: !options.verbose
|
||||||
});
|
});
|
||||||
|
|
||||||
// Verify binary exists
|
|
||||||
const binaryPath = join(passMgrDir, 'dist', 'pass_mgr');
|
const binaryPath = join(passMgrDir, 'dist', 'pass_mgr');
|
||||||
if (!existsSync(binaryPath)) {
|
if (!existsSync(binaryPath)) {
|
||||||
throw new Error('pass_mgr binary not found after build');
|
throw new Error('pass_mgr binary not found after build');
|
||||||
@@ -308,16 +277,14 @@ async function installComponents(env) {
|
|||||||
|
|
||||||
logStep(4, 'Installing components...');
|
logStep(4, 'Installing components...');
|
||||||
|
|
||||||
// Determine install paths
|
|
||||||
const installDir = options.prefix || env.openclawDir;
|
const installDir = options.prefix || env.openclawDir;
|
||||||
const binDir = options.prefix ? join(installDir, 'bin') : join(installDir, 'bin');
|
const binDir = join(installDir, 'bin');
|
||||||
const skillsDir = join(installDir, 'skills', 'paddedcell');
|
const skillsDir = join(installDir, 'skills', 'paddedcell');
|
||||||
|
|
||||||
log(` Install directory: ${installDir}`, 'blue');
|
log(` Install directory: ${installDir}`, 'blue');
|
||||||
log(` Binary directory: ${binDir}`, 'blue');
|
log(` Binary directory: ${binDir}`, 'blue');
|
||||||
log(` Skills directory: ${skillsDir}`, 'blue');
|
log(` Skills directory: ${skillsDir}`, 'blue');
|
||||||
|
|
||||||
// Create directories
|
|
||||||
mkdirSync(binDir, { recursive: true });
|
mkdirSync(binDir, { recursive: true });
|
||||||
mkdirSync(skillsDir, { recursive: true });
|
mkdirSync(skillsDir, { recursive: true });
|
||||||
|
|
||||||
@@ -370,12 +337,6 @@ async function installComponents(env) {
|
|||||||
JSON.stringify(manifest, null, 2)
|
JSON.stringify(manifest, null, 2)
|
||||||
);
|
);
|
||||||
logSuccess('Skill manifest created');
|
logSuccess('Skill manifest created');
|
||||||
|
|
||||||
// Add to PATH if needed
|
|
||||||
if (options.prefix) {
|
|
||||||
log('\n To use pass_mgr, add the following to your shell profile:', 'yellow');
|
|
||||||
log(` export PATH="${binDir}:$PATH"`, 'cyan');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyModule(source, dest) {
|
function copyModule(source, dest) {
|
||||||
@@ -399,12 +360,10 @@ function copyModule(source, dest) {
|
|||||||
} else {
|
} else {
|
||||||
copyFileSync(srcPath, destPath);
|
copyFileSync(srcPath, destPath);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch {
|
||||||
// Fallback: try to copy as file first, then directory
|
|
||||||
try {
|
try {
|
||||||
copyFileSync(srcPath, destPath);
|
copyFileSync(srcPath, destPath);
|
||||||
} catch {
|
} catch {
|
||||||
// If file copy fails, try directory copy
|
|
||||||
execSync(`cp -r "${srcPath}" "${destPath}"`, { cwd: __dirname });
|
execSync(`cp -r "${srcPath}" "${destPath}"`, { cwd: __dirname });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -423,9 +382,8 @@ async function configure(env) {
|
|||||||
|
|
||||||
logStep(5, 'Configuration...');
|
logStep(5, 'Configuration...');
|
||||||
|
|
||||||
const passMgrPath = options.prefix
|
const installDir = env.openclawDir || join(homedir(), '.openclaw');
|
||||||
? join(options.prefix, 'bin', 'pass_mgr')
|
const passMgrPath = join(installDir, 'bin', 'pass_mgr');
|
||||||
: join(env.openclawDir, 'bin', 'pass_mgr');
|
|
||||||
|
|
||||||
// Check if already initialized
|
// Check if already initialized
|
||||||
const adminKeyDir = join(homedir(), '.pass_mgr');
|
const adminKeyDir = join(homedir(), '.pass_mgr');
|
||||||
@@ -435,27 +393,9 @@ async function configure(env) {
|
|||||||
logSuccess('pass_mgr already initialized');
|
logSuccess('pass_mgr already initialized');
|
||||||
} else {
|
} else {
|
||||||
log(' pass_mgr not initialized yet.', 'yellow');
|
log(' pass_mgr not initialized yet.', 'yellow');
|
||||||
log(' Run "pass_mgr admin init" manually after installation.', 'cyan');
|
log(` Run "${passMgrPath} admin init" manually after installation.`, 'cyan');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create environment config
|
|
||||||
log(' Creating environment configuration...', 'blue');
|
|
||||||
const installDir = env.openclawDir || join(homedir(), '.openclaw');
|
|
||||||
const envConfig = [
|
|
||||||
'# PaddedCell Environment Configuration',
|
|
||||||
`export PATH="${dirname(passMgrPath)}:$PATH"`,
|
|
||||||
'export PASS_MGR_PATH="pass_mgr"',
|
|
||||||
'',
|
|
||||||
'# PaddedCell skills',
|
|
||||||
].join('\n');
|
|
||||||
|
|
||||||
const envFile = join(installDir, 'paddedcell.env');
|
|
||||||
writeFileSync(envFile, envConfig);
|
|
||||||
logSuccess(`Environment config written to ${envFile}`);
|
|
||||||
|
|
||||||
log('\n Add the following to your shell profile:', 'yellow');
|
|
||||||
log(` source ${envFile}`, 'cyan');
|
|
||||||
|
|
||||||
// Update OpenClaw plugins.load.paths configuration
|
// Update OpenClaw plugins.load.paths configuration
|
||||||
log('\n Updating OpenClaw plugin configuration...', 'blue');
|
log('\n Updating OpenClaw plugin configuration...', 'blue');
|
||||||
|
|
||||||
@@ -492,72 +432,14 @@ async function configure(env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Step 6: Verify Installation
|
// Step 6: Print Summary
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
async function verifyInstallation(env) {
|
|
||||||
if (options.buildOnly) {
|
|
||||||
logStep(6, 'Skipping verification (--build-only)');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
logStep(6, 'Verifying installation...');
|
|
||||||
|
|
||||||
let allOk = true;
|
|
||||||
|
|
||||||
// Check pass_mgr
|
|
||||||
try {
|
|
||||||
const passMgrPath = options.prefix
|
|
||||||
? join(options.prefix, 'bin', 'pass_mgr')
|
|
||||||
: join(env.openclawDir, 'bin', 'pass_mgr');
|
|
||||||
|
|
||||||
if (existsSync(passMgrPath)) {
|
|
||||||
execSync(`"${passMgrPath}" --help`, { silent: true });
|
|
||||||
logSuccess('pass_mgr is working');
|
|
||||||
} else {
|
|
||||||
logError('pass_mgr binary not found');
|
|
||||||
allOk = false;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
logError('pass_mgr test failed');
|
|
||||||
allOk = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check pcexec
|
|
||||||
const pcexecPath = join(
|
|
||||||
options.prefix || env.openclawDir,
|
|
||||||
'skills', 'paddedcell', 'pcexec', 'dist', 'index.js'
|
|
||||||
);
|
|
||||||
if (existsSync(pcexecPath)) {
|
|
||||||
logSuccess('pcexec module installed');
|
|
||||||
} else {
|
|
||||||
logError('pcexec module not found');
|
|
||||||
allOk = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check safe-restart
|
|
||||||
const safeRestartPath = join(
|
|
||||||
options.prefix || env.openclawDir,
|
|
||||||
'skills', 'paddedcell', 'safe-restart', 'dist', 'index.js'
|
|
||||||
);
|
|
||||||
if (existsSync(safeRestartPath)) {
|
|
||||||
logSuccess('safe-restart module installed');
|
|
||||||
} else {
|
|
||||||
logError('safe-restart module not found');
|
|
||||||
allOk = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return allOk;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// Step 7: Print Summary
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
function printSummary(env) {
|
function printSummary(env) {
|
||||||
logStep(7, 'Installation Summary');
|
logStep(6, 'Installation Summary');
|
||||||
|
|
||||||
const installDir = options.prefix || env.openclawDir;
|
const installDir = options.prefix || env.openclawDir;
|
||||||
|
const passMgrPath = join(installDir, 'bin', 'pass_mgr');
|
||||||
|
|
||||||
console.log('');
|
console.log('');
|
||||||
log('╔════════════════════════════════════════════════════════╗', 'cyan');
|
log('╔════════════════════════════════════════════════════════╗', 'cyan');
|
||||||
@@ -574,22 +456,19 @@ function printSummary(env) {
|
|||||||
log(` • safe-restart: ${join(__dirname, 'safe-restart', 'dist')}`, 'reset');
|
log(` • safe-restart: ${join(__dirname, 'safe-restart', 'dist')}`, 'reset');
|
||||||
} else {
|
} else {
|
||||||
log('Installed components:', 'blue');
|
log('Installed components:', 'blue');
|
||||||
log(` • pass_mgr binary: ${join(installDir, 'bin', 'pass_mgr')}`, 'reset');
|
log(` • pass_mgr binary: ${passMgrPath}`, 'reset');
|
||||||
log(` • pcexec module: ${join(installDir, 'skills', 'paddedcell', 'pcexec')}`, 'reset');
|
log(` • pcexec module: ${join(installDir, 'skills', 'paddedcell', 'pcexec')}`, 'reset');
|
||||||
log(` • safe-restart module: ${join(installDir, 'skills', 'paddedcell', 'safe-restart')}`, 'reset');
|
log(` • safe-restart module: ${join(installDir, 'skills', 'paddedcell', 'safe-restart')}`, 'reset');
|
||||||
console.log('');
|
console.log('');
|
||||||
|
|
||||||
log('Next steps:', 'blue');
|
log('Next steps:', 'blue');
|
||||||
console.log('');
|
console.log('');
|
||||||
log('1. Reload your shell or run:', 'yellow');
|
log('1. Initialize pass_mgr (required before first use):', 'yellow');
|
||||||
log(` source ${join(installDir, 'paddedcell.env')}`, 'cyan');
|
log(` ${passMgrPath} admin init`, 'cyan');
|
||||||
console.log('');
|
console.log('');
|
||||||
log('2. Initialize pass_mgr (required before first use):', 'yellow');
|
log('2. Test pass_mgr:', 'yellow');
|
||||||
log(' pass_mgr admin init', 'cyan');
|
log(` ${passMgrPath} set test_key mypass # Set a test password`, 'cyan');
|
||||||
console.log('');
|
log(` ${passMgrPath} get test_key # Retrieve password`, 'cyan');
|
||||||
log('3. Test pass_mgr:', 'yellow');
|
|
||||||
log(' pass_mgr set test_key mypass # Set a test password', 'cyan');
|
|
||||||
log(' pass_mgr get test_key # Retrieve password', 'cyan');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('');
|
console.log('');
|
||||||
@@ -609,7 +488,6 @@ async function uninstall(env) {
|
|||||||
const installDir = options.prefix || env.openclawDir || join(homedir(), '.openclaw');
|
const installDir = options.prefix || env.openclawDir || join(homedir(), '.openclaw');
|
||||||
const binDir = join(installDir, 'bin');
|
const binDir = join(installDir, 'bin');
|
||||||
const skillsDir = join(installDir, 'skills', 'paddedcell');
|
const skillsDir = join(installDir, 'skills', 'paddedcell');
|
||||||
const envFile = join(installDir, 'paddedcell.env');
|
|
||||||
|
|
||||||
const itemsToRemove = [];
|
const itemsToRemove = [];
|
||||||
|
|
||||||
@@ -623,10 +501,6 @@ async function uninstall(env) {
|
|||||||
itemsToRemove.push(skillsDir);
|
itemsToRemove.push(skillsDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existsSync(envFile)) {
|
|
||||||
itemsToRemove.push(envFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itemsToRemove.length === 0) {
|
if (itemsToRemove.length === 0) {
|
||||||
log('No installed components found.', 'yellow');
|
log('No installed components found.', 'yellow');
|
||||||
return;
|
return;
|
||||||
@@ -647,7 +521,7 @@ async function uninstall(env) {
|
|||||||
// Perform uninstall
|
// Perform uninstall
|
||||||
for (const item of itemsToRemove) {
|
for (const item of itemsToRemove) {
|
||||||
try {
|
try {
|
||||||
if (item === passMgrBinary || item === envFile) {
|
if (item === passMgrBinary) {
|
||||||
execSync(`rm -f "${item}"`, { silent: true });
|
execSync(`rm -f "${item}"`, { silent: true });
|
||||||
logSuccess(`Removed: ${item}`);
|
logSuccess(`Removed: ${item}`);
|
||||||
} else {
|
} else {
|
||||||
@@ -704,12 +578,12 @@ async function uninstall(env) {
|
|||||||
log('║ PaddedCell Uninstall Complete ║', 'cyan');
|
log('║ PaddedCell Uninstall Complete ║', 'cyan');
|
||||||
log('╚════════════════════════════════════════════════════════╝', 'cyan');
|
log('╚════════════════════════════════════════════════════════╝', 'cyan');
|
||||||
console.log('');
|
console.log('');
|
||||||
|
|
||||||
log('Remember to remove the following from your shell profile:', 'yellow');
|
|
||||||
log(` source ${envFile}`, 'cyan');
|
|
||||||
console.log('');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Main
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
console.log('');
|
console.log('');
|
||||||
log('╔════════════════════════════════════════════════════════╗', 'cyan');
|
log('╔════════════════════════════════════════════════════════╗', 'cyan');
|
||||||
@@ -730,12 +604,6 @@ async function main() {
|
|||||||
await buildComponents(env);
|
await buildComponents(env);
|
||||||
await installComponents(env);
|
await installComponents(env);
|
||||||
await configure(env);
|
await configure(env);
|
||||||
const verified = await verifyInstallation(env);
|
|
||||||
|
|
||||||
if (!verified && !options.buildOnly) {
|
|
||||||
log('\nInstallation completed with warnings.', 'yellow');
|
|
||||||
}
|
|
||||||
|
|
||||||
printSummary(env);
|
printSummary(env);
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
Reference in New Issue
Block a user