chore: bump version to 7.1.2
🐛 Bug Fixes **Windows Installation** - Fixed Bun PATH detection on Windows after fresh install - Added fallback to check common install paths before PATH reload - Improved smart-install.js to use full Bun path when not in PATH - Added proper path quoting for Windows usernames with spaces **Worker Startup** - Fixed worker connection failures in Stop hook - Added health check retry loop (5 attempts, 500ms intervals) - Worker now waits up to 2.5s for responsiveness before returning - Improved error detection for Bun's ConnectionRefused error format 🎯 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
"plugins": [
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "7.1.1",
|
||||
"version": "7.1.2",
|
||||
"source": "./plugin",
|
||||
"description": "Persistent memory system for Claude Code - context compression across sessions"
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
Claude-mem is a Claude Code plugin providing persistent memory across sessions. It captures tool usage, compresses observations using the Claude Agent SDK, and injects relevant context into future sessions.
|
||||
|
||||
**Current Version**: 7.1.1
|
||||
**Current Version**: 7.1.2
|
||||
|
||||
## Architecture
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "7.1.1",
|
||||
"version": "7.1.2",
|
||||
"description": "Memory compression system for Claude Code - persist context across sessions",
|
||||
"keywords": [
|
||||
"claude",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "7.1.1",
|
||||
"version": "7.1.2",
|
||||
"description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions",
|
||||
"author": {
|
||||
"name": "Alex Newman"
|
||||
|
||||
@@ -24,18 +24,56 @@ function isBunInstalled() {
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
shell: IS_WINDOWS
|
||||
});
|
||||
return result.status === 0;
|
||||
if (result.status === 0) return true;
|
||||
} catch {
|
||||
return false;
|
||||
// PATH check failed, try common installation paths
|
||||
}
|
||||
|
||||
// Check common installation paths (handles fresh installs before PATH reload)
|
||||
const bunPaths = IS_WINDOWS
|
||||
? [join(homedir(), '.bun', 'bin', 'bun.exe')]
|
||||
: [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun'];
|
||||
|
||||
return bunPaths.some(existsSync);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Bun executable path (from PATH or common install locations)
|
||||
*/
|
||||
function getBunPath() {
|
||||
// Try PATH first
|
||||
try {
|
||||
const result = spawnSync('bun', ['--version'], {
|
||||
encoding: 'utf-8',
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
shell: IS_WINDOWS
|
||||
});
|
||||
if (result.status === 0) return 'bun';
|
||||
} catch {
|
||||
// Not in PATH
|
||||
}
|
||||
|
||||
// Check common installation paths
|
||||
const bunPaths = IS_WINDOWS
|
||||
? [join(homedir(), '.bun', 'bin', 'bun.exe')]
|
||||
: [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun'];
|
||||
|
||||
for (const bunPath of bunPaths) {
|
||||
if (existsSync(bunPath)) return bunPath;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Bun version if installed
|
||||
*/
|
||||
function getBunVersion() {
|
||||
const bunPath = getBunPath();
|
||||
if (!bunPath) return null;
|
||||
|
||||
try {
|
||||
const result = spawnSync('bun', ['--version'], {
|
||||
const result = spawnSync(bunPath, ['--version'], {
|
||||
encoding: 'utf-8',
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
shell: IS_WINDOWS
|
||||
@@ -56,10 +94,17 @@ function isUvInstalled() {
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
shell: IS_WINDOWS
|
||||
});
|
||||
return result.status === 0;
|
||||
if (result.status === 0) return true;
|
||||
} catch {
|
||||
return false;
|
||||
// PATH check failed, try common installation paths
|
||||
}
|
||||
|
||||
// Check common installation paths (handles fresh installs before PATH reload)
|
||||
const uvPaths = IS_WINDOWS
|
||||
? [join(homedir(), '.local', 'bin', 'uv.exe'), join(homedir(), '.cargo', 'bin', 'uv.exe')]
|
||||
: [join(homedir(), '.local', 'bin', 'uv'), join(homedir(), '.cargo', 'bin', 'uv'), '/usr/local/bin/uv'];
|
||||
|
||||
return uvPaths.some(existsSync);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,12 +271,21 @@ function needsInstall() {
|
||||
* Install dependencies using Bun
|
||||
*/
|
||||
function installDeps() {
|
||||
const bunPath = getBunPath();
|
||||
if (!bunPath) {
|
||||
throw new Error('Bun executable not found');
|
||||
}
|
||||
|
||||
console.error('📦 Installing dependencies with Bun...');
|
||||
|
||||
// Quote path for Windows paths with spaces
|
||||
const bunCmd = IS_WINDOWS && bunPath.includes(' ') ? `"${bunPath}"` : bunPath;
|
||||
|
||||
try {
|
||||
execSync('bun install', { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS });
|
||||
execSync(`${bunCmd} install`, { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS });
|
||||
} catch {
|
||||
// Retry with force flag
|
||||
execSync('bun install --force', { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS });
|
||||
execSync(`${bunCmd} install --force`, { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS });
|
||||
}
|
||||
|
||||
// Write version marker
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
*/
|
||||
export function handleWorkerError(error: any): never {
|
||||
if (error.cause?.code === 'ECONNREFUSED' ||
|
||||
error.code === 'ConnectionRefused' || // Bun-specific error format
|
||||
error.name === 'TimeoutError' ||
|
||||
error.message?.includes('fetch failed')) {
|
||||
error.message?.includes('fetch failed') ||
|
||||
error.message?.includes('Unable to connect')) {
|
||||
throw new Error(
|
||||
"There's a problem with the worker. Try: npm run worker:restart"
|
||||
);
|
||||
|
||||
@@ -194,13 +194,6 @@ export async function ensureWorkerRunning(): Promise<void> {
|
||||
// Try to start the worker
|
||||
const started = await startWorker();
|
||||
|
||||
// Final health check before throwing error
|
||||
// Worker might be already running but was temporarily unresponsive
|
||||
if (!started && await isWorkerHealthy()) {
|
||||
await ensureWorkerVersionMatches();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!started) {
|
||||
const port = getWorkerPort();
|
||||
throw new Error(
|
||||
@@ -209,4 +202,22 @@ export async function ensureWorkerRunning(): Promise<void> {
|
||||
`If already running, try: npm run worker:restart`
|
||||
);
|
||||
}
|
||||
|
||||
// Wait for worker to become responsive after starting
|
||||
// Try up to 5 times with 500ms delays (2.5 seconds total)
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
if (await isWorkerHealthy()) {
|
||||
await ensureWorkerVersionMatches();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Worker started but isn't responding
|
||||
const port = getWorkerPort();
|
||||
logger.error('SYSTEM', 'Worker started but not responding to health checks');
|
||||
throw new Error(
|
||||
`Worker service started but is not responding on port ${port}.\n\n` +
|
||||
`Try: npm run worker:restart`
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user