claude-mem-lite 4.0.1 → 4.0.3
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/hook-update.mjs +22 -1
- package/install.mjs +9 -7
- package/lib/binding-probe.mjs +23 -3
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/scripts/binding-probe-cli.mjs +8 -0
- package/scripts/launch.mjs +1 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "claude-mem-lite",
|
|
13
|
-
"version": "4.0.
|
|
13
|
+
"version": "4.0.3",
|
|
14
14
|
"source": "./",
|
|
15
15
|
"description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. Hybrid FTS5 + TF-IDF search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark)."
|
|
16
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-mem-lite",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.3",
|
|
4
4
|
"description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. Hybrid FTS5 + TF-IDF search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark).",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "sdsrss"
|
package/README.md
CHANGED
|
@@ -145,7 +145,7 @@ How claude-mem-lite differs from the major neighbors in the LLM-memory space (ve
|
|
|
145
145
|
|
|
146
146
|
## Requirements
|
|
147
147
|
|
|
148
|
-
- **Node.js** >=
|
|
148
|
+
- **Node.js** >= 22
|
|
149
149
|
- **Claude Code** CLI installed and configured (`claude` command available)
|
|
150
150
|
- **SQLite3** support (provided by `better-sqlite3`, compiled on install)
|
|
151
151
|
- **Platform**: Linux or macOS (see [Platform Support](#platform-support))
|
package/hook-update.mjs
CHANGED
|
@@ -23,6 +23,7 @@ import { pathToFileURL } from 'node:url';
|
|
|
23
23
|
import { tmpdir, homedir } from 'node:os';
|
|
24
24
|
import { DB_DIR, CODE_DIR } from './schema.mjs';
|
|
25
25
|
import { debugCatch, debugLog } from './utils.mjs';
|
|
26
|
+
import { NATIVE_BINDING_SOURCE_BUILD_CMD } from './lib/binding-probe.mjs';
|
|
26
27
|
// Local manifest is fallback only — the active manifest is loaded from the
|
|
27
28
|
// extracted tarball's own source-files.mjs inside installExtractedRelease.
|
|
28
29
|
// See loadReleaseManifest below.
|
|
@@ -877,7 +878,27 @@ function smokeInstalledRelease(targetDir) {
|
|
|
877
878
|
} catch {
|
|
878
879
|
execSync('npm rebuild better-sqlite3', { cwd: targetDir, timeout: 120000, stdio: 'ignore' });
|
|
879
880
|
}
|
|
880
|
-
|
|
881
|
+
try {
|
|
882
|
+
execSync(probeCmd, { timeout: 20000, stdio: 'ignore' });
|
|
883
|
+
} catch {
|
|
884
|
+
// Both npm rebuilds healed nothing — which is what better-sqlite3 13 does on a
|
|
885
|
+
// platform it ships no prebuild for, because there is no install script for them to
|
|
886
|
+
// run. Without this step the re-probe threw, smoke failed, and the caller rolled the
|
|
887
|
+
// whole update back, so auto-update could never land again on those platforms
|
|
888
|
+
// (A20260906-R8b-P2-1, found by independent review of v4.0.0).
|
|
889
|
+
//
|
|
890
|
+
// The source build is `node-gyp clean && node-gyp rebuild`, i.e. it deletes build/
|
|
891
|
+
// first — which is why the SessionStart probe path must NOT run it. Here it is safe
|
|
892
|
+
// for two independent reasons: the binding is ALREADY unusable (the probe above just
|
|
893
|
+
// threw), so clean destroys nothing; and this whole function is a smoke gate whose
|
|
894
|
+
// failure rolls back to the previous, working install.
|
|
895
|
+
execSync(NATIVE_BINDING_SOURCE_BUILD_CMD, {
|
|
896
|
+
cwd: targetDir,
|
|
897
|
+
timeout: 300000,
|
|
898
|
+
stdio: 'ignore',
|
|
899
|
+
});
|
|
900
|
+
execSync(probeCmd, { timeout: 20000, stdio: 'ignore' });
|
|
901
|
+
}
|
|
881
902
|
}
|
|
882
903
|
}
|
|
883
904
|
return true;
|
package/install.mjs
CHANGED
|
@@ -420,6 +420,12 @@ export function patchClaudeMdVersion(text, version) {
|
|
|
420
420
|
* removes the link and leaves the target intact (a link to a populated dir, target still
|
|
421
421
|
* readable afterwards) — following it would delete the developer's own scripts/.
|
|
422
422
|
*
|
|
423
|
+
* It is `recursive`, so it also removes a REAL directory at `p`, not only a link to one.
|
|
424
|
+
* That is deliberate and pre-existing (the dev-mode sites already did this): running
|
|
425
|
+
* `install --dev` after a normal install finds a real `DATA_DIR/node_modules` where a link
|
|
426
|
+
* belongs. Named here because the one-line summary above says "before a symlink is written
|
|
427
|
+
* over it", which undersells what the call can delete.
|
|
428
|
+
*
|
|
423
429
|
* @param {string} p
|
|
424
430
|
* @returns {boolean}
|
|
425
431
|
*/
|
|
@@ -1581,13 +1587,9 @@ async function uninstall() {
|
|
|
1581
1587
|
// 1b. Remove CLI symlink
|
|
1582
1588
|
for (const binDir of [join(homedir(), '.local', 'bin'), '/usr/local/bin']) {
|
|
1583
1589
|
const cliLink = join(binDir, 'claude-mem-lite');
|
|
1584
|
-
try
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
}
|
|
1588
|
-
} catch {
|
|
1589
|
-
/* may not have permissions */
|
|
1590
|
-
}
|
|
1590
|
+
// No try/catch: clearLinkPath swallows a permissions failure and returns false, so the
|
|
1591
|
+
// wrapper this used to have was unreachable once the existsSync gate moved inside it.
|
|
1592
|
+
if (clearLinkPath(cliLink)) ok(`CLI symlink removed: ${cliLink}`);
|
|
1591
1593
|
}
|
|
1592
1594
|
|
|
1593
1595
|
// 2. Remove hooks from settings.json (match both npx and git-clone install paths)
|
package/lib/binding-probe.mjs
CHANGED
|
@@ -48,12 +48,17 @@ export const NATIVE_BINDING_SOURCE_BUILD_CMD = 'npm run --prefix node_modules/be
|
|
|
48
48
|
* `&&`, never `||`: step 1 exits 0 whether or not it did anything, so an `||` chain would
|
|
49
49
|
* never reach step 2 — the no-op is the whole trap. Sequencing unconditionally costs a
|
|
50
50
|
* recompile in the case step 1 already fixed, which is the right trade for a manual repair.
|
|
51
|
+
* Precisely: `build-release` is `node-gyp clean && node-gyp rebuild`, so step 2 DISCARDS a
|
|
52
|
+
* binding step 1 had just produced and rebuilds it. `prebuilds/` is untouched either way, so
|
|
53
|
+
* the end state is a usable binding; the cost is time, not correctness.
|
|
51
54
|
*
|
|
52
55
|
* @param {string} root Directory whose node_modules holds better-sqlite3
|
|
53
56
|
* @returns {string}
|
|
54
57
|
*/
|
|
55
58
|
export function nativeBindingRepairHint(root) {
|
|
56
|
-
|
|
59
|
+
// Quoted: INSTALL_DIR / a plugin-cache root can contain spaces, and an unquoted `cd`
|
|
60
|
+
// hands the user a command that fails on exactly the machines least able to debug it.
|
|
61
|
+
return `cd "${root}" && ${NATIVE_BINDING_REBUILD_CMD} && ${NATIVE_BINDING_SOURCE_BUILD_CMD}`;
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
// Set on a re-exec'd child so one failed heal cannot fork-bomb the CLI.
|
|
@@ -270,9 +275,24 @@ export async function ensureBetterSqlite3Working(installDir, deps = {}) {
|
|
|
270
275
|
// get it appended — otherwise an injected strategy would silently grow a step its owner
|
|
271
276
|
// never asked for, and (as the stub tests caught) a test that stubs `rebuild` without
|
|
272
277
|
// stubbing `exec` would shell out for real.
|
|
278
|
+
//
|
|
279
|
+
// `sourceBuild: false` is the EXPLICIT opt-out, and it exists because the `deps.rebuild`
|
|
280
|
+
// test above was the wrong proxy for "this caller has a budget" (A20260906-R8b-P0-1, found
|
|
281
|
+
// by independent review). The one caller that is genuinely time-boxed — the SessionStart
|
|
282
|
+
// hook probe — injects `exec` with a 20 s cap and does NOT inject `rebuild`, so it landed
|
|
283
|
+
// outside the guard. That matters because this step is `node-gyp clean && node-gyp rebuild`:
|
|
284
|
+
// it DELETES build/ before compiling, so a truncated attempt is not a no-op, it is
|
|
285
|
+
// destructive. Measured on a tree whose compiled binding opened a DB — 20 s cap, SIGTERM at
|
|
286
|
+
// 20.02 s, no `.node` left, `DB opens: YES` → `NO`, repeating on every SessionStart because
|
|
287
|
+
// setup.sh writes its marker only on success. Callers with a time budget must opt out and
|
|
288
|
+
// leave the compile to a foreground path (`rebuild-binding`, `healAndReexec`) that has none.
|
|
273
289
|
const sourceBuild =
|
|
274
|
-
deps.sourceBuild
|
|
275
|
-
|
|
290
|
+
deps.sourceBuild === false
|
|
291
|
+
? null
|
|
292
|
+
: deps.sourceBuild ||
|
|
293
|
+
(deps.rebuild
|
|
294
|
+
? null
|
|
295
|
+
: () => exec(NATIVE_BINDING_SOURCE_BUILD_CMD, { cwd: installDir, stdio: 'pipe' }));
|
|
276
296
|
if (!sourceBuild) return { ok: false, error: second.error || first.error };
|
|
277
297
|
|
|
278
298
|
try {
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-mem-lite",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "claude-mem-lite",
|
|
9
|
-
"version": "4.0.
|
|
9
|
+
"version": "4.0.3",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
12
12
|
"better-sqlite3": "^13.0.3",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-mem-lite",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.3",
|
|
4
4
|
"description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. Hybrid FTS5 + TF-IDF search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@10.9.2",
|
|
@@ -132,6 +132,14 @@ try {
|
|
|
132
132
|
probe: () => first,
|
|
133
133
|
exec: (cmd, opts) => execSync(cmd, { ...opts, timeout: 20000 }),
|
|
134
134
|
verify: () => helpers.probeBindingInFreshProcess(ROOT, { timeoutMs: 8000 }),
|
|
135
|
+
// NOT on this path (A20260906-R8b-P0-1). The source build is
|
|
136
|
+
// `node-gyp clean && node-gyp rebuild`: it deletes build/ before compiling, and a full
|
|
137
|
+
// compile takes ~41 s against the 20 s cap above — so under this budget it does not fail
|
|
138
|
+
// harmlessly, it destroys a binding that was working (measured: DB opens YES → NO, .node
|
|
139
|
+
// gone, SIGTERM at 20.02 s), and repeats every SessionStart because setup.sh writes its
|
|
140
|
+
// marker only on success. The compile belongs on a foreground path with no cap:
|
|
141
|
+
// `claude-mem-lite rebuild-binding`, which is what the repair hints now print.
|
|
142
|
+
sourceBuild: false,
|
|
135
143
|
});
|
|
136
144
|
} finally {
|
|
137
145
|
// process.exit skips finally blocks — every exit below this point, so the
|
package/scripts/launch.mjs
CHANGED
|
@@ -107,7 +107,7 @@ try {
|
|
|
107
107
|
}
|
|
108
108
|
if (!verify.ok) {
|
|
109
109
|
process.stderr.write(`[claude-mem-lite] better-sqlite3 binding unusable: ${verify.error}\n`);
|
|
110
|
-
process.stderr.write(`[claude-mem-lite] Repair: ${nativeBindingRepairHint(
|
|
110
|
+
process.stderr.write(`[claude-mem-lite] Repair: ${nativeBindingRepairHint(ROOT)}\n`);
|
|
111
111
|
process.exit(1);
|
|
112
112
|
}
|
|
113
113
|
if (verify.action === 'rebuilt') {
|