claude-mem-lite 2.63.0 → 2.64.0
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/cli/fts-check.mjs +1 -1
- package/install.mjs +41 -14
- package/lib/doctor-drift.mjs +1 -0
- package/lib/save-observation.mjs +1 -1
- package/mem-cli.mjs +12 -12
- package/package.json +1 -1
package/cli/fts-check.mjs
CHANGED
|
@@ -8,7 +8,7 @@ export function cmdFtsCheck(db, args) {
|
|
|
8
8
|
const { positional } = parseArgs(args);
|
|
9
9
|
const action = positional[0];
|
|
10
10
|
if (!action || !['check', 'rebuild'].includes(action)) {
|
|
11
|
-
fail('[mem] Usage: mem fts-check <check|rebuild>');
|
|
11
|
+
fail('[mem] Usage: claude-mem-lite fts-check <check|rebuild>');
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
14
|
|
package/install.mjs
CHANGED
|
@@ -1295,14 +1295,29 @@ async function doctor() {
|
|
|
1295
1295
|
dwarn('Database: not found (will be created)');
|
|
1296
1296
|
}
|
|
1297
1297
|
|
|
1298
|
-
// Check for stale processes
|
|
1298
|
+
// Check for stale processes — extends beyond legacy chroma/worker to
|
|
1299
|
+
// catch MCP launchers / servers from cached old plugin versions. Auto-update
|
|
1300
|
+
// bumps installed_plugins.json but cannot kill the MCP process spawned for
|
|
1301
|
+
// an active session, so v2.60.0/v2.61.0 launchers commonly outlive their
|
|
1302
|
+
// version (recurrent pattern, see #2580 for the gsd analogue). Filtering
|
|
1303
|
+
// strategy: legacy chroma/worker = always stale; cache-path launchers = only
|
|
1304
|
+
// when their version segment ≠ current package.json version; dev-install
|
|
1305
|
+
// paths (no version segment) are never flagged.
|
|
1299
1306
|
try {
|
|
1300
|
-
const procs = execFileSync('pgrep', ['-af', 'chroma|claude-mem.*worker'], { encoding: 'utf8', timeout: 5000, stdio: 'pipe' }).trim();
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1307
|
+
const procs = execFileSync('pgrep', ['-af', 'chroma|claude-mem-lite.*(scripts/launch|server)\\.mjs|claude-mem.*worker'], { encoding: 'utf8', timeout: 5000, stdio: 'pipe' }).trim();
|
|
1308
|
+
const lines = procs.split('\n').filter(l => l && !l.includes('pgrep'));
|
|
1309
|
+
let currentVersion = '';
|
|
1310
|
+
try { currentVersion = JSON.parse(readFileSync(join(PROJECT_DIR, 'package.json'), 'utf8')).version; } catch { /* fall through with empty version */ }
|
|
1311
|
+
const stale = lines.filter(l => {
|
|
1312
|
+
if (/chroma|claude-mem.*worker/.test(l)) return true;
|
|
1313
|
+
const m = l.match(/claude-mem-lite\/(\d+\.\d+\.\d+)\/(scripts\/launch|server)\.mjs/);
|
|
1314
|
+
return m && currentVersion && m[1] !== currentVersion;
|
|
1315
|
+
});
|
|
1316
|
+
if (stale.length > 0) {
|
|
1317
|
+
warn(`Old processes running${currentVersion ? ` (current: v${currentVersion})` : ''}:\n ` + stale.join('\n '));
|
|
1305
1318
|
issues++;
|
|
1319
|
+
} else {
|
|
1320
|
+
ok('No stale processes');
|
|
1306
1321
|
}
|
|
1307
1322
|
} catch {
|
|
1308
1323
|
ok('No stale processes');
|
|
@@ -1333,19 +1348,31 @@ async function doctor() {
|
|
|
1333
1348
|
}
|
|
1334
1349
|
|
|
1335
1350
|
// Dev drift: in dev-mode installs, all SOURCE_FILES entries should be
|
|
1336
|
-
// symlinks. A plain file means an earlier install (or manual cp) copied it
|
|
1337
|
-
//
|
|
1338
|
-
//
|
|
1351
|
+
// symlinks. A plain file means an earlier install (or manual cp) copied it
|
|
1352
|
+
// (edits in the repo won't propagate). A missing entry (neither symlink nor
|
|
1353
|
+
// plain) means an earlier install never wrote the file — same divergence
|
|
1354
|
+
// class. Per #8043: "is this file present ≠ is this install consistent" —
|
|
1355
|
+
// missing is tracked separately by checkDevDrift but the caller MUST surface
|
|
1356
|
+
// it to honour #8268's "gate the all-green string on every counter" rule.
|
|
1339
1357
|
try {
|
|
1340
1358
|
const { checkDevDrift } = await import('./lib/doctor-drift.mjs');
|
|
1341
1359
|
const r = checkDevDrift(INSTALL_DIR, SOURCE_FILES);
|
|
1342
|
-
if (r.drift) {
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1345
|
-
|
|
1360
|
+
if (r.drift || (r.devMode && r.missingCount > 0)) {
|
|
1361
|
+
const parts = [];
|
|
1362
|
+
if (r.plainCount > 0) {
|
|
1363
|
+
const names = r.plainFiles.slice(0, 5).join(', ');
|
|
1364
|
+
const suffix = r.plainCount > 5 ? ` +${r.plainCount - 5} more` : '';
|
|
1365
|
+
parts.push(`${r.plainCount} non-symlink: ${names}${suffix}`);
|
|
1366
|
+
}
|
|
1367
|
+
if (r.missingCount > 0) {
|
|
1368
|
+
const names = r.missingFiles.join(', ');
|
|
1369
|
+
const suffix = r.missingCount > r.missingFiles.length ? ` +${r.missingCount - r.missingFiles.length} more` : '';
|
|
1370
|
+
parts.push(`${r.missingCount} missing: ${names}${suffix}`);
|
|
1371
|
+
}
|
|
1372
|
+
warn(`Dev drift: ${parts.join('; ')} (re-run: node ${join(PROJECT_DIR, 'install.mjs')} install --dev)`);
|
|
1346
1373
|
issues++;
|
|
1347
1374
|
} else if (r.devMode) {
|
|
1348
|
-
ok(`Dev drift: clean (${r.symlinkCount} symlinks, 0 plain)`);
|
|
1375
|
+
ok(`Dev drift: clean (${r.symlinkCount} symlinks, 0 plain, 0 missing)`);
|
|
1349
1376
|
}
|
|
1350
1377
|
// Prod (all plain) install: no message — dev-drift is a dev-only concern.
|
|
1351
1378
|
} catch (e) {
|
package/lib/doctor-drift.mjs
CHANGED
package/lib/save-observation.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Shared "save one observation" pipeline — used by both mem-cli.mjs::cmdSave
|
|
2
|
-
// (CLI `mem save`) and server.mjs::mem_save (MCP tool).
|
|
2
|
+
// (CLI `claude-mem-lite save`) and server.mjs::mem_save (MCP tool).
|
|
3
3
|
//
|
|
4
4
|
// Pre-extraction (v2.60.0) the same dedup → scrub → minhash → CJK-bigram →
|
|
5
5
|
// transactional INSERT block lived inline in both call sites (~110 lines × 2,
|
package/mem-cli.mjs
CHANGED
|
@@ -34,7 +34,7 @@ function cmdSearch(db, args) {
|
|
|
34
34
|
const { positional, flags } = parseArgs(args);
|
|
35
35
|
const query = positional.join(' ');
|
|
36
36
|
if (!query) {
|
|
37
|
-
fail('[mem] Usage: mem search <query> [--type TYPE] [--source SOURCE] [--limit N] [--project P] [--from DATE] [--to DATE] [--importance N] [--branch B] [--offset N] [--sort relevance|time|importance] [--include-noise]');
|
|
37
|
+
fail('[mem] Usage: claude-mem-lite search <query> [--type TYPE] [--source SOURCE] [--limit N] [--project P] [--from DATE] [--to DATE] [--importance N] [--branch B] [--offset N] [--sort relevance|time|importance] [--include-noise]');
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -400,7 +400,7 @@ function cmdRecall(db, args) {
|
|
|
400
400
|
const { positional, flags } = parseArgs(args);
|
|
401
401
|
const file = positional.join(' ');
|
|
402
402
|
if (!file) {
|
|
403
|
-
fail('[mem] Usage: mem recall <file> [--limit N] [--include-noise]');
|
|
403
|
+
fail('[mem] Usage: claude-mem-lite recall <file> [--limit N] [--include-noise]');
|
|
404
404
|
return;
|
|
405
405
|
}
|
|
406
406
|
|
|
@@ -530,7 +530,7 @@ function cmdGet(db, args) {
|
|
|
530
530
|
const { positional, flags } = parseArgs(args);
|
|
531
531
|
const idStr = positional.join(',');
|
|
532
532
|
if (!idStr) {
|
|
533
|
-
fail('[mem] Usage: mem get <id1,id2,...> [--source obs|session|prompt] [--fields f1,f2,...]\n' +
|
|
533
|
+
fail('[mem] Usage: claude-mem-lite get <id1,id2,...> [--source obs|session|prompt] [--fields f1,f2,...]\n' +
|
|
534
534
|
' IDs accept prefix from search output: #123 (obs), P#123 (prompt), S#123 (session).');
|
|
535
535
|
return;
|
|
536
536
|
}
|
|
@@ -785,7 +785,7 @@ function cmdSave(db, args) {
|
|
|
785
785
|
const { positional, flags } = parseArgs(args);
|
|
786
786
|
const text = positional.join(' ');
|
|
787
787
|
if (!text) {
|
|
788
|
-
fail('[mem] Usage: mem save "<text>" [--type T] [--title T] [--importance N] [--project P] [--files f1,f2] [--lesson T]');
|
|
788
|
+
fail('[mem] Usage: claude-mem-lite save "<text>" [--type T] [--title T] [--importance N] [--project P] [--files f1,f2] [--lesson T]');
|
|
789
789
|
return;
|
|
790
790
|
}
|
|
791
791
|
|
|
@@ -1137,7 +1137,7 @@ function cmdDelete(db, args) {
|
|
|
1137
1137
|
const { positional, flags } = parseArgs(args);
|
|
1138
1138
|
const idStr = positional.join(',');
|
|
1139
1139
|
if (!idStr) {
|
|
1140
|
-
fail('[mem] Usage: mem delete <id1,id2,...> [--confirm]');
|
|
1140
|
+
fail('[mem] Usage: claude-mem-lite delete <id1,id2,...> [--confirm]');
|
|
1141
1141
|
return;
|
|
1142
1142
|
}
|
|
1143
1143
|
|
|
@@ -1147,7 +1147,7 @@ function cmdDelete(db, args) {
|
|
|
1147
1147
|
const nonObs = tokens.filter(t => /^[PpSs]#?\d+$/.test(t));
|
|
1148
1148
|
if (nonObs.length > 0) {
|
|
1149
1149
|
fail(`[mem] delete only works on observations. Rejected: ${nonObs.join(', ')}. ` +
|
|
1150
|
-
`Prompts and sessions are append-only — inspect with \`mem get P#N --source prompt\` / \`--source session\`.`);
|
|
1150
|
+
`Prompts and sessions are append-only — inspect with \`claude-mem-lite get P#N --source prompt\` / \`--source session\`.`);
|
|
1151
1151
|
return;
|
|
1152
1152
|
}
|
|
1153
1153
|
const ids = tokens.map(t => {
|
|
@@ -1215,7 +1215,7 @@ function cmdUpdate(db, args) {
|
|
|
1215
1215
|
const parsed = raw ? parseIdToken(raw) : null;
|
|
1216
1216
|
const id = parsed && parsed.source === null ? parsed.id : parseInt(raw, 10);
|
|
1217
1217
|
if (!id || isNaN(id)) {
|
|
1218
|
-
fail('[mem] Usage: mem update <id> [--title T] [--type T] [--importance N] [--lesson T] [--narrative T] [--concepts T]');
|
|
1218
|
+
fail('[mem] Usage: claude-mem-lite update <id> [--title T] [--type T] [--importance N] [--lesson T] [--narrative T] [--concepts T]');
|
|
1219
1219
|
return;
|
|
1220
1220
|
}
|
|
1221
1221
|
|
|
@@ -1442,7 +1442,7 @@ function cmdMaintain(db, args) {
|
|
|
1442
1442
|
const { positional, flags } = parseArgs(args);
|
|
1443
1443
|
const action = positional[0];
|
|
1444
1444
|
if (!action || !['scan', 'execute'].includes(action)) {
|
|
1445
|
-
fail('[mem] Usage: mem maintain <scan|execute> [--ops cleanup,decay,boost,dedup,purge_stale,rebuild_vectors] [--project P] [--retain-days N] [--merge-ids keepId:removeId,...]');
|
|
1445
|
+
fail('[mem] Usage: claude-mem-lite maintain <scan|execute> [--ops cleanup,decay,boost,dedup,purge_stale,rebuild_vectors] [--project P] [--retain-days N] [--merge-ids keepId:removeId,...]');
|
|
1446
1446
|
return;
|
|
1447
1447
|
}
|
|
1448
1448
|
|
|
@@ -1722,7 +1722,7 @@ function cmdRegistry(_memDb, args) {
|
|
|
1722
1722
|
const { positional, flags } = parseArgs(args);
|
|
1723
1723
|
const action = positional[0];
|
|
1724
1724
|
if (!action || !['list', 'stats', 'search', 'import', 'remove', 'reindex'].includes(action)) {
|
|
1725
|
-
fail('[mem] Usage: mem registry <list|stats|search|import|remove|reindex> [--type skill|agent] [--query Q] [--name N] [--resource-type T]');
|
|
1725
|
+
fail('[mem] Usage: claude-mem-lite registry <list|stats|search|import|remove|reindex> [--type skill|agent] [--query Q] [--name N] [--resource-type T]');
|
|
1726
1726
|
return;
|
|
1727
1727
|
}
|
|
1728
1728
|
|
|
@@ -1738,7 +1738,7 @@ function cmdRegistry(_memDb, args) {
|
|
|
1738
1738
|
try {
|
|
1739
1739
|
if (action === 'search') {
|
|
1740
1740
|
const query = flags.query || positional.slice(1).join(' ');
|
|
1741
|
-
if (!query) { fail('[mem] Usage: mem registry search <query> [--type skill|agent] [--category C] [--quality Q]'); return; }
|
|
1741
|
+
if (!query) { fail('[mem] Usage: claude-mem-lite registry search <query> [--type skill|agent] [--category C] [--quality Q]'); return; }
|
|
1742
1742
|
let results = searchResources(rdb, query, {
|
|
1743
1743
|
type: flags.type || undefined,
|
|
1744
1744
|
limit: (flags.category || flags.quality) ? 20 : 10,
|
|
@@ -1828,7 +1828,7 @@ function cmdRegistry(_memDb, args) {
|
|
|
1828
1828
|
if (action === 'import') {
|
|
1829
1829
|
const name = flags.name;
|
|
1830
1830
|
const resourceType = flags['resource-type'];
|
|
1831
|
-
if (!name || !resourceType) { fail('[mem] Usage: mem registry import --name N --resource-type skill|agent [--invocation-name I] [--capability-summary S]'); return; }
|
|
1831
|
+
if (!name || !resourceType) { fail('[mem] Usage: claude-mem-lite registry import --name N --resource-type skill|agent [--invocation-name I] [--capability-summary S]'); return; }
|
|
1832
1832
|
const fields = { name, type: resourceType, status: 'active', source: flags.source || 'user' };
|
|
1833
1833
|
for (const f of ['repo-url', 'local-path', 'invocation-name', 'intent-tags', 'domain-tags', 'trigger-patterns', 'capability-summary', 'keywords', 'tech-stack', 'use-cases']) {
|
|
1834
1834
|
const camel = f.replace(/-([a-z])/g, (_, c) => '_' + c);
|
|
@@ -1849,7 +1849,7 @@ function cmdRegistry(_memDb, args) {
|
|
|
1849
1849
|
if (action === 'remove') {
|
|
1850
1850
|
const name = flags.name;
|
|
1851
1851
|
const resourceType = flags['resource-type'];
|
|
1852
|
-
if (!name || !resourceType) { fail('[mem] Usage: mem registry remove --name N --resource-type skill|agent'); return; }
|
|
1852
|
+
if (!name || !resourceType) { fail('[mem] Usage: claude-mem-lite registry remove --name N --resource-type skill|agent'); return; }
|
|
1853
1853
|
const result = rdb.prepare('DELETE FROM resources WHERE type = ? AND name = ?').run(resourceType, name);
|
|
1854
1854
|
out(result.changes > 0 ? `[mem] Removed: ${resourceType}:${name}` : '[mem] Not found.');
|
|
1855
1855
|
return;
|