claude-mem-lite 2.53.0 → 2.53.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/install.mjs
CHANGED
|
@@ -524,14 +524,19 @@ async function install() {
|
|
|
524
524
|
try {
|
|
525
525
|
const cacheBase = join(homedir(), '.claude', 'plugins', 'cache', MARKETPLACE_KEY, 'claude-mem-lite');
|
|
526
526
|
if (existsSync(cacheBase)) {
|
|
527
|
-
const
|
|
527
|
+
const launchSyncFiles = ['launch.mjs', 'launch-preflight.mjs'];
|
|
528
528
|
let clearedHooks = 0;
|
|
529
529
|
for (const ver of readdirSync(cacheBase)) {
|
|
530
530
|
const verDir = join(cacheBase, ver);
|
|
531
531
|
|
|
532
|
-
// Sync launch.mjs
|
|
532
|
+
// Sync launch.mjs + its preflight companion (issue #15)
|
|
533
533
|
if (existsSync(join(verDir, 'scripts'))) {
|
|
534
|
-
|
|
534
|
+
for (const f of launchSyncFiles) {
|
|
535
|
+
const src = join(PROJECT_DIR, 'scripts', f);
|
|
536
|
+
if (existsSync(src)) {
|
|
537
|
+
try { copyFileSync(src, join(verDir, 'scripts', f)); } catch { /* keep going */ }
|
|
538
|
+
}
|
|
539
|
+
}
|
|
535
540
|
}
|
|
536
541
|
|
|
537
542
|
// Clear cached hooks.json (runtime reads here, not marketplace source)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-mem-lite",
|
|
3
|
-
"version": "2.53.
|
|
3
|
+
"version": "2.53.1",
|
|
4
4
|
"description": "Lightweight persistent memory system for Claude Code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -98,6 +98,7 @@
|
|
|
98
98
|
"commands/bug.md",
|
|
99
99
|
"hooks/hooks.json",
|
|
100
100
|
"scripts/launch.mjs",
|
|
101
|
+
"scripts/launch-preflight.mjs",
|
|
101
102
|
"scripts/setup.sh",
|
|
102
103
|
"scripts/post-tool-use.sh",
|
|
103
104
|
"scripts/user-prompt-search.js",
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// launch-preflight.mjs — Detect incomplete installs at MCP server launch.
|
|
2
|
+
//
|
|
3
|
+
// Why: issue #15 — published v2.53.0 npm tarball contains all files, but some
|
|
4
|
+
// users end up with a partial install (server.mjs present, search-engine.mjs
|
|
5
|
+
// missing) and the resulting ERR_MODULE_NOT_FOUND has no actionable message.
|
|
6
|
+
// We can't fix every cause (mirror lag / interrupted download / npm cache
|
|
7
|
+
// corruption / permission) on the user side, but we can detect the broken
|
|
8
|
+
// state and either fall back to ~/.claude-mem-lite/ (which hook-update.mjs
|
|
9
|
+
// keeps healthy) or print a clear repair command instead of a Node stack.
|
|
10
|
+
//
|
|
11
|
+
// Pure module — no I/O at import time, all deps injected. Tested in isolation;
|
|
12
|
+
// scripts/launch.mjs wires it to the actual filesystem + stderr.
|
|
13
|
+
|
|
14
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
|
|
17
|
+
// Match relative `.mjs` imports — covers all four ESM forms:
|
|
18
|
+
// from './x.mjs' (static named/default/namespace)
|
|
19
|
+
// import './x.mjs' (side-effect static)
|
|
20
|
+
// await import('./x.mjs') (dynamic)
|
|
21
|
+
// import('./x.mjs') without await (dynamic)
|
|
22
|
+
// Skips 'node:*' / package imports / non-mjs paths.
|
|
23
|
+
const FROM_RE = /\bfrom\s+['"](\.\/[^'"]+\.mjs)['"]/g;
|
|
24
|
+
const IMPORT_RE = /\bimport\s*\(?\s*['"](\.\/[^'"]+\.mjs)['"]/g;
|
|
25
|
+
|
|
26
|
+
export function detectMissingImports(installRoot) {
|
|
27
|
+
const serverPath = join(installRoot, 'server.mjs');
|
|
28
|
+
if (!existsSync(serverPath)) return ['server.mjs'];
|
|
29
|
+
|
|
30
|
+
let src;
|
|
31
|
+
try {
|
|
32
|
+
src = readFileSync(serverPath, 'utf8');
|
|
33
|
+
} catch {
|
|
34
|
+
return ['server.mjs'];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const missing = new Set();
|
|
38
|
+
for (const re of [FROM_RE, IMPORT_RE]) {
|
|
39
|
+
re.lastIndex = 0;
|
|
40
|
+
for (const m of src.matchAll(re)) {
|
|
41
|
+
const rel = m[1].replace(/^\.\//, '');
|
|
42
|
+
if (!existsSync(join(installRoot, rel))) missing.add(rel);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return [...missing];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function resolveLaunchEntry({ primaryRoot, fallbackRoot, warn = () => {} }) {
|
|
49
|
+
const primaryMissing = detectMissingImports(primaryRoot);
|
|
50
|
+
if (primaryMissing.length === 0) {
|
|
51
|
+
return { path: join(primaryRoot, 'server.mjs'), source: 'primary' };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (fallbackRoot && fallbackRoot !== primaryRoot) {
|
|
55
|
+
const fallbackMissing = detectMissingImports(fallbackRoot);
|
|
56
|
+
if (fallbackMissing.length === 0) {
|
|
57
|
+
warn(
|
|
58
|
+
`[claude-mem-lite] Primary install incomplete at ${primaryRoot} ` +
|
|
59
|
+
`(missing: ${primaryMissing.join(', ')}). Falling back to ${fallbackRoot}.`,
|
|
60
|
+
);
|
|
61
|
+
return {
|
|
62
|
+
path: join(fallbackRoot, 'server.mjs'),
|
|
63
|
+
source: 'fallback',
|
|
64
|
+
missingFromPrimary: primaryMissing,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const repairCmd = 'npm install -g claude-mem-lite@latest --force';
|
|
70
|
+
const err = new Error(
|
|
71
|
+
`[claude-mem-lite] Install incomplete at ${primaryRoot}\n` +
|
|
72
|
+
`[claude-mem-lite] Missing: ${primaryMissing.join(', ')}\n` +
|
|
73
|
+
`[claude-mem-lite] Repair: ${repairCmd}\n` +
|
|
74
|
+
`[claude-mem-lite] Or via Claude Code: /plugin uninstall claude-mem-lite && /plugin install claude-mem-lite@sdsrss`,
|
|
75
|
+
);
|
|
76
|
+
err.code = 'INSTALL_INCOMPLETE';
|
|
77
|
+
err.missing = primaryMissing;
|
|
78
|
+
throw err;
|
|
79
|
+
}
|
package/scripts/launch.mjs
CHANGED
|
@@ -45,12 +45,31 @@ try {
|
|
|
45
45
|
// Dev mode: prefer ~/.claude-mem-lite/server.mjs (symlinked to source) over
|
|
46
46
|
// CLAUDE_PLUGIN_ROOT (potentially stale plugin cache). This ensures the MCP
|
|
47
47
|
// server always runs the latest code when installed with `install --dev`.
|
|
48
|
-
const
|
|
48
|
+
const dataDir = join(homedir(), '.claude-mem-lite');
|
|
49
|
+
const devServer = join(dataDir, 'server.mjs');
|
|
49
50
|
let useDevServer = false;
|
|
50
51
|
try { useDevServer = existsSync(devServer) && lstatSync(devServer).isSymbolicLink(); } catch {}
|
|
51
52
|
|
|
52
53
|
if (useDevServer) {
|
|
53
54
|
await import(pathToFileURL(devServer).href);
|
|
54
55
|
} else {
|
|
55
|
-
|
|
56
|
+
// Preflight: detect incomplete primary install (issue #15) — if relative
|
|
57
|
+
// imports referenced by server.mjs are missing on disk, fall back to the
|
|
58
|
+
// hook-update.mjs-maintained ~/.claude-mem-lite/ copy when healthy, or exit
|
|
59
|
+
// with a clear repair command instead of a Node ERR_MODULE_NOT_FOUND stack.
|
|
60
|
+
const { resolveLaunchEntry } = await import('./launch-preflight.mjs');
|
|
61
|
+
try {
|
|
62
|
+
const entry = resolveLaunchEntry({
|
|
63
|
+
primaryRoot: ROOT,
|
|
64
|
+
fallbackRoot: dataDir,
|
|
65
|
+
warn: (msg) => process.stderr.write(msg + '\n'),
|
|
66
|
+
});
|
|
67
|
+
await import(pathToFileURL(entry.path).href);
|
|
68
|
+
} catch (e) {
|
|
69
|
+
if (e.code === 'INSTALL_INCOMPLETE') {
|
|
70
|
+
process.stderr.write(e.message + '\n');
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
throw e;
|
|
74
|
+
}
|
|
56
75
|
}
|