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:
Generated
+2
-2
@@ -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",
|
||||||
|
|||||||
+91
-46
@@ -164,49 +164,85 @@ function runNpmInstall() {
|
|||||||
log('🔨 Installing dependencies...', colors.bright);
|
log('🔨 Installing dependencies...', colors.bright);
|
||||||
log('', colors.reset);
|
log('', colors.reset);
|
||||||
|
|
||||||
try {
|
// Try normal install first, then retry with force if it fails
|
||||||
// Run npm install with error output visible
|
const strategies = [
|
||||||
execSync('npm install --prefer-offline --no-audit --no-fund', {
|
{ command: 'npm install', label: 'normal' },
|
||||||
cwd: PLUGIN_ROOT,
|
{ command: 'npm install --force', label: 'with force flag' },
|
||||||
stdio: 'inherit', // Show all output including errors
|
];
|
||||||
encoding: 'utf-8',
|
|
||||||
});
|
|
||||||
|
|
||||||
// Verify better-sqlite3 was installed
|
let lastError = null;
|
||||||
if (!existsSync(BETTER_SQLITE3_PATH)) {
|
|
||||||
throw new Error('better-sqlite3 installation verification failed');
|
for (const { command, label } of strategies) {
|
||||||
|
try {
|
||||||
|
log(`Attempting install ${label}...`, colors.dim);
|
||||||
|
|
||||||
|
// Run npm install silently
|
||||||
|
execSync(command, {
|
||||||
|
cwd: PLUGIN_ROOT,
|
||||||
|
stdio: 'pipe', // Silent output unless error
|
||||||
|
encoding: 'utf-8',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify better-sqlite3 was installed
|
||||||
|
if (!existsSync(BETTER_SQLITE3_PATH)) {
|
||||||
|
throw new Error('better-sqlite3 installation verification failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
const version = getPackageVersion();
|
||||||
|
setInstalledVersion(version);
|
||||||
|
|
||||||
|
log('', colors.green);
|
||||||
|
log('✅ Dependencies installed successfully!', colors.bright);
|
||||||
|
log(` Version: ${version}`, colors.dim);
|
||||||
|
log('', colors.reset);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
lastError = error;
|
||||||
|
// Continue to next strategy
|
||||||
}
|
}
|
||||||
|
|
||||||
const version = getPackageVersion();
|
|
||||||
setInstalledVersion(version);
|
|
||||||
|
|
||||||
log('', colors.green);
|
|
||||||
log('✅ Dependencies installed successfully!', colors.bright);
|
|
||||||
log(` Version: ${version}`, colors.dim);
|
|
||||||
log('', colors.reset);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
log('', colors.red);
|
|
||||||
log('❌ Installation failed!', colors.bright);
|
|
||||||
log('', colors.reset);
|
|
||||||
|
|
||||||
// Provide Windows-specific help
|
|
||||||
if (isWindows && error.message && error.message.includes('better-sqlite3')) {
|
|
||||||
log(getWindowsErrorHelp(error.message), colors.yellow);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show generic error info
|
|
||||||
if (error.stderr) {
|
|
||||||
log('Error output:', colors.dim);
|
|
||||||
log(error.stderr.toString(), colors.red);
|
|
||||||
} else if (error.message) {
|
|
||||||
log(error.message, colors.red);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All strategies failed - show error
|
||||||
|
log('', colors.red);
|
||||||
|
log('❌ Installation failed after retrying!', colors.bright);
|
||||||
|
log('', colors.reset);
|
||||||
|
|
||||||
|
// Provide Windows-specific help
|
||||||
|
if (isWindows && lastError && lastError.message && lastError.message.includes('better-sqlite3')) {
|
||||||
|
log(getWindowsErrorHelp(lastError.message), colors.yellow);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show generic error info with troubleshooting steps
|
||||||
|
if (lastError) {
|
||||||
|
if (lastError.stderr) {
|
||||||
|
log('Error output:', colors.dim);
|
||||||
|
log(lastError.stderr.toString(), colors.red);
|
||||||
|
} else if (lastError.message) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user