Fix npm install failures with automatic retry and silent output (#64)

* Initial plan

* Initial investigation: identified npm install failure issue

Co-authored-by: thedotmack <683968+thedotmack@users.noreply.github.com>

* Add retry logic and better error handling to smart-install

Co-authored-by: thedotmack <683968+thedotmack@users.noreply.github.com>

* Fix spacing inconsistency in log messages

Co-authored-by: thedotmack <683968+thedotmack@users.noreply.github.com>

* Refactor worker startup check for better readability

Co-authored-by: thedotmack <683968+thedotmack@users.noreply.github.com>

* Simplify npm install: use plain npm install without flags

Co-authored-by: thedotmack <683968+thedotmack@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thedotmack <683968+thedotmack@users.noreply.github.com>
This commit is contained in:
Copilot
2025-11-06 17:21:44 -05:00
committed by GitHub
parent b68ea38bcc
commit f7b51a963e
2 changed files with 93 additions and 48 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "claude-mem", "name": "claude-mem",
"version": "5.1.0", "version": "5.1.2",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "claude-mem", "name": "claude-mem",
"version": "5.1.0", "version": "5.1.2",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"dependencies": { "dependencies": {
"@anthropic-ai/claude-agent-sdk": "^0.1.27", "@anthropic-ai/claude-agent-sdk": "^0.1.27",
+63 -18
View File
@@ -164,11 +164,22 @@ function runNpmInstall() {
log('🔨 Installing dependencies...', colors.bright); log('🔨 Installing dependencies...', colors.bright);
log('', colors.reset); log('', colors.reset);
// Try normal install first, then retry with force if it fails
const strategies = [
{ command: 'npm install', label: 'normal' },
{ command: 'npm install --force', label: 'with force flag' },
];
let lastError = null;
for (const { command, label } of strategies) {
try { try {
// Run npm install with error output visible log(`Attempting install ${label}...`, colors.dim);
execSync('npm install --prefer-offline --no-audit --no-fund', {
// Run npm install silently
execSync(command, {
cwd: PLUGIN_ROOT, cwd: PLUGIN_ROOT,
stdio: 'inherit', // Show all output including errors stdio: 'pipe', // Silent output unless error
encoding: 'utf-8', encoding: 'utf-8',
}); });
@@ -188,25 +199,50 @@ function runNpmInstall() {
return true; return true;
} catch (error) { } catch (error) {
lastError = error;
// Continue to next strategy
}
}
// All strategies failed - show error
log('', colors.red); log('', colors.red);
log('❌ Installation failed!', colors.bright); log('❌ Installation failed after retrying!', colors.bright);
log('', colors.reset); log('', colors.reset);
// Provide Windows-specific help // Provide Windows-specific help
if (isWindows && error.message && error.message.includes('better-sqlite3')) { if (isWindows && lastError && lastError.message && lastError.message.includes('better-sqlite3')) {
log(getWindowsErrorHelp(error.message), colors.yellow); log(getWindowsErrorHelp(lastError.message), colors.yellow);
} }
// Show generic error info // Show generic error info with troubleshooting steps
if (error.stderr) { if (lastError) {
if (lastError.stderr) {
log('Error output:', colors.dim); log('Error output:', colors.dim);
log(error.stderr.toString(), colors.red); log(lastError.stderr.toString(), colors.red);
} else if (error.message) { } else if (lastError.message) {
log(error.message, colors.red); log(lastError.message, colors.red);
}
log('', colors.yellow);
log('📋 Troubleshooting Steps:', colors.bright);
log('', colors.reset);
log('1. Check your internet connection', colors.yellow);
log('2. Try running: npm cache clean --force', colors.yellow);
log('3. Try running: npm install (in plugin directory)', colors.yellow);
log('4. Check npm version: npm --version (requires npm 7+)', colors.yellow);
log('5. Try updating npm: npm install -g npm@latest', colors.yellow);
log('', colors.reset);
} }
return false; return false;
} }
/**
* Check if we should fail when worker startup fails
* Returns true if worker failed AND dependencies are missing
*/
function shouldFailOnWorkerStartup(workerStarted) {
return !workerStarted && !existsSync(NODE_MODULES_PATH);
} }
function startWorker() { function startWorker() {
@@ -253,21 +289,30 @@ async function main() {
if (!installSuccess) { if (!installSuccess) {
log('', colors.red); log('', colors.red);
log('⚠️ Installation failed - worker startup may fail', colors.yellow); log(' Installation failed - cannot start worker without dependencies', colors.bright);
log('', colors.reset); log('', colors.reset);
// Don't exit - still try to start worker with existing deps log('Please resolve the installation issues above and try again.', colors.yellow);
log('', colors.reset);
process.exit(1);
} }
} }
// Always start/ensure worker is running // Start/ensure worker is running (only after successful install or if deps already exist)
// This runs whether we installed deps or not const workerStarted = startWorker();
startWorker();
// Success - dependencies installed (if needed) and worker running if (shouldFailOnWorkerStartup(workerStarted)) {
log('', colors.red);
log('❌ Worker failed to start and dependencies are missing', colors.bright);
log('', colors.reset);
process.exit(1);
}
// Success - dependencies installed (if needed) and worker running (or already running)
process.exit(0); process.exit(0);
} catch (error) { } catch (error) {
log(`❌ Unexpected error: ${error.message}`, colors.red); log(`❌ Unexpected error: ${error.message}`, colors.red);
log('', colors.reset);
process.exit(1); process.exit(1);
} }
} }