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:
zhi
2026-03-05 11:34:19 +00:00
parent 62044ab948
commit 1c84b4d6a0

View File

@@ -12,8 +12,8 @@
* node install.mjs --uninstall --prefix /usr/local
*/
import { execSync, spawn } from 'child_process';
import { existsSync, mkdirSync, copyFileSync, writeFileSync, readFileSync, chmodSync } from 'fs';
import { execSync } from 'child_process';
import { existsSync, mkdirSync, copyFileSync, writeFileSync, chmodSync } from 'fs';
import { dirname, join, resolve } from 'path';
import { fileURLToPath } from 'url';
import { homedir, platform } from 'os';
@@ -53,7 +53,7 @@ function log(message, color = 'reset') {
}
function logStep(step, message) {
log(`[${step}/7] ${message}`, 'cyan');
log(`[${step}/6] ${message}`, 'cyan');
}
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
// ============================================================================
@@ -248,7 +218,6 @@ async function buildComponents(env) {
silent: !options.verbose
});
// Verify binary exists
const binaryPath = join(passMgrDir, 'dist', 'pass_mgr');
if (!existsSync(binaryPath)) {
throw new Error('pass_mgr binary not found after build');
@@ -308,16 +277,14 @@ async function installComponents(env) {
logStep(4, 'Installing components...');
// Determine install paths
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');
log(` Install directory: ${installDir}`, 'blue');
log(` Binary directory: ${binDir}`, 'blue');
log(` Skills directory: ${skillsDir}`, 'blue');
// Create directories
mkdirSync(binDir, { recursive: true });
mkdirSync(skillsDir, { recursive: true });
@@ -370,12 +337,6 @@ async function installComponents(env) {
JSON.stringify(manifest, null, 2)
);
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) {
@@ -399,12 +360,10 @@ function copyModule(source, dest) {
} else {
copyFileSync(srcPath, destPath);
}
} catch (err) {
// Fallback: try to copy as file first, then directory
} catch {
try {
copyFileSync(srcPath, destPath);
} catch {
// If file copy fails, try directory copy
execSync(`cp -r "${srcPath}" "${destPath}"`, { cwd: __dirname });
}
}
@@ -423,9 +382,8 @@ async function configure(env) {
logStep(5, 'Configuration...');
const passMgrPath = options.prefix
? join(options.prefix, 'bin', 'pass_mgr')
: join(env.openclawDir, 'bin', 'pass_mgr');
const installDir = env.openclawDir || join(homedir(), '.openclaw');
const passMgrPath = join(installDir, 'bin', 'pass_mgr');
// Check if already initialized
const adminKeyDir = join(homedir(), '.pass_mgr');
@@ -435,27 +393,9 @@ async function configure(env) {
logSuccess('pass_mgr already initialized');
} else {
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
log('\n Updating OpenClaw plugin configuration...', 'blue');
@@ -492,72 +432,14 @@ async function configure(env) {
}
// ============================================================================
// Step 6: Verify Installation
// ============================================================================
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
// Step 6: Print Summary
// ============================================================================
function printSummary(env) {
logStep(7, 'Installation Summary');
logStep(6, 'Installation Summary');
const installDir = options.prefix || env.openclawDir;
const passMgrPath = join(installDir, 'bin', 'pass_mgr');
console.log('');
log('╔════════════════════════════════════════════════════════╗', 'cyan');
@@ -574,22 +456,19 @@ function printSummary(env) {
log(` • safe-restart: ${join(__dirname, 'safe-restart', 'dist')}`, 'reset');
} else {
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(` • safe-restart module: ${join(installDir, 'skills', 'paddedcell', 'safe-restart')}`, 'reset');
console.log('');
log('Next steps:', 'blue');
console.log('');
log('1. Reload your shell or run:', 'yellow');
log(` source ${join(installDir, 'paddedcell.env')}`, 'cyan');
log('1. Initialize pass_mgr (required before first use):', 'yellow');
log(` ${passMgrPath} admin init`, 'cyan');
console.log('');
log('2. Initialize pass_mgr (required before first use):', 'yellow');
log(' pass_mgr admin init', 'cyan');
console.log('');
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');
log('2. Test pass_mgr:', 'yellow');
log(` ${passMgrPath} set test_key mypass # Set a test password`, 'cyan');
log(` ${passMgrPath} get test_key # Retrieve password`, 'cyan');
}
console.log('');
@@ -609,7 +488,6 @@ async function uninstall(env) {
const installDir = options.prefix || env.openclawDir || join(homedir(), '.openclaw');
const binDir = join(installDir, 'bin');
const skillsDir = join(installDir, 'skills', 'paddedcell');
const envFile = join(installDir, 'paddedcell.env');
const itemsToRemove = [];
@@ -623,10 +501,6 @@ async function uninstall(env) {
itemsToRemove.push(skillsDir);
}
if (existsSync(envFile)) {
itemsToRemove.push(envFile);
}
if (itemsToRemove.length === 0) {
log('No installed components found.', 'yellow');
return;
@@ -647,7 +521,7 @@ async function uninstall(env) {
// Perform uninstall
for (const item of itemsToRemove) {
try {
if (item === passMgrBinary || item === envFile) {
if (item === passMgrBinary) {
execSync(`rm -f "${item}"`, { silent: true });
logSuccess(`Removed: ${item}`);
} else {
@@ -704,12 +578,12 @@ async function uninstall(env) {
log('║ PaddedCell Uninstall Complete ║', 'cyan');
log('╚════════════════════════════════════════════════════════╝', 'cyan');
console.log('');
log('Remember to remove the following from your shell profile:', 'yellow');
log(` source ${envFile}`, 'cyan');
console.log('');
}
// ============================================================================
// Main
// ============================================================================
async function main() {
console.log('');
log('╔════════════════════════════════════════════════════════╗', 'cyan');
@@ -730,12 +604,6 @@ async function main() {
await buildComponents(env);
await installComponents(env);
await configure(env);
const verified = await verifyInstallation(env);
if (!verified && !options.buildOnly) {
log('\nInstallation completed with warnings.', 'yellow');
}
printSummary(env);
process.exit(0);
} catch (err) {