claude-mem-lite 2.95.1 → 2.96.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/install.mjs +72 -2
- package/package.json +1 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "claude-mem-lite",
|
|
13
|
-
"version": "2.
|
|
13
|
+
"version": "2.96.0",
|
|
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": "2.
|
|
3
|
+
"version": "2.96.0",
|
|
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/install.mjs
CHANGED
|
@@ -302,6 +302,43 @@ function isDevInstall() {
|
|
|
302
302
|
}
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
+
// Decide what to check out of a registry repo. We only ever copy the manifest's
|
|
306
|
+
// `entry.path` subdirs into managed/skills|agents, so the working tree never
|
|
307
|
+
// needs the rest of the repo — a partial+sparse clone fetches just those subtrees
|
|
308
|
+
// (e.g. davila7/claude-code-templates: 197MB whole repo → a few MB of 3 paths).
|
|
309
|
+
// Returns { full, paths }: `full` forces a normal checkout when any entry maps to
|
|
310
|
+
// the repo root ('.') — sparse buys nothing there. Unsafe paths ('..'/absolute)
|
|
311
|
+
// are dropped here exactly as the copy loop drops them, so they never reach
|
|
312
|
+
// `sparse-checkout set`. Pure + exported for unit testing.
|
|
313
|
+
export function planRepoSparsePaths(entries) {
|
|
314
|
+
let needsFull = false;
|
|
315
|
+
const paths = [];
|
|
316
|
+
for (const e of entries || []) {
|
|
317
|
+
const p = e && e.path;
|
|
318
|
+
if (!p || p === '.' || p === './') { needsFull = true; continue; }
|
|
319
|
+
if (isAbsolute(p) || String(p).includes('..')) continue; // unsafe — skipped at copy too
|
|
320
|
+
const norm = String(p).replace(/^\.\//, '').replace(/\/+$/, '');
|
|
321
|
+
if (norm && !paths.includes(norm)) paths.push(norm);
|
|
322
|
+
}
|
|
323
|
+
// No usable sparse paths (all root or all unsafe) → a full checkout is the only
|
|
324
|
+
// thing that can produce content; sparse would be an empty, pointless tree.
|
|
325
|
+
return { full: needsFull || paths.length === 0, paths };
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// True only for a clone this code produced (partial-clone promisor + sparse-checkout
|
|
329
|
+
// both on). A legacy full clone returns false → caller re-clones it slim. Detection
|
|
330
|
+
// erring false only costs a one-time re-clone (the dir is a rebuildable cache), so
|
|
331
|
+
// over-eager migration is safe; under-eager just keeps a fat clone one more cycle.
|
|
332
|
+
function isPartialSparseClone(clonePath) {
|
|
333
|
+
const cfg = (key) => {
|
|
334
|
+
try {
|
|
335
|
+
return execFileSync('git', ['-C', clonePath, 'config', '--get', key],
|
|
336
|
+
{ encoding: 'utf8', stdio: 'pipe' }).trim();
|
|
337
|
+
} catch { return ''; } // missing key → git exits non-zero → treat as unset
|
|
338
|
+
};
|
|
339
|
+
return cfg('remote.origin.promisor') === 'true' && cfg('core.sparseCheckout') === 'true';
|
|
340
|
+
}
|
|
341
|
+
|
|
305
342
|
// ─── Install ────────────────────────────────────────────────────────────────
|
|
306
343
|
|
|
307
344
|
async function install() {
|
|
@@ -748,11 +785,39 @@ async function install() {
|
|
|
748
785
|
const clonePath = join(managedDir, 'repos', repoName);
|
|
749
786
|
let repoReady = false;
|
|
750
787
|
|
|
788
|
+
const plan = planRepoSparsePaths(entries);
|
|
789
|
+
const cloneUrl = `${repoUrl.replace(/\.git$/, '')}.git`;
|
|
790
|
+
// Clone only what we extract: a partial (blob:none) + sparse clone fetches
|
|
791
|
+
// just the manifest subpaths' subtrees instead of the whole repo. Falls
|
|
792
|
+
// back to a plain shallow clone if partial-clone/sparse-checkout is
|
|
793
|
+
// unsupported (old git/server) — identical to the prior behavior.
|
|
794
|
+
const cloneSlim = () => {
|
|
795
|
+
if (plan.full) {
|
|
796
|
+
execFileSync('git', ['clone', '--depth', '1', cloneUrl, clonePath], { stdio: 'pipe', timeout: 30000 });
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
try {
|
|
800
|
+
execFileSync('git', ['clone', '--depth', '1', '--filter=blob:none', '--no-checkout', cloneUrl, clonePath], { stdio: 'pipe', timeout: 30000 });
|
|
801
|
+
execFileSync('git', ['-C', clonePath, 'sparse-checkout', 'set', '--no-cone', ...plan.paths], { stdio: 'pipe', timeout: 30000 });
|
|
802
|
+
execFileSync('git', ['-C', clonePath, 'checkout'], { stdio: 'pipe', timeout: 30000 });
|
|
803
|
+
} catch {
|
|
804
|
+
try { rmSync(clonePath, { recursive: true, force: true }); } catch {}
|
|
805
|
+
execFileSync('git', ['clone', '--depth', '1', cloneUrl, clonePath], { stdio: 'pipe', timeout: 30000 });
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
|
|
809
|
+
// Migrate a legacy full clone: drop it so the fresh-clone path below
|
|
810
|
+
// rebuilds it slim. managed/repos is a rebuildable cache, so this loses
|
|
811
|
+
// nothing and reclaims the bulk of its footprint on the next install run.
|
|
812
|
+
if (!plan.full && existsSync(clonePath) && !isPartialSparseClone(clonePath)) {
|
|
813
|
+
try { rmSync(clonePath, { recursive: true, force: true }); } catch {}
|
|
814
|
+
}
|
|
815
|
+
|
|
751
816
|
if (!existsSync(clonePath)) {
|
|
752
|
-
// Fresh clone
|
|
817
|
+
// Fresh clone (also the rebuild path for a just-migrated legacy clone)
|
|
753
818
|
try {
|
|
754
819
|
mkdirSync(join(managedDir, 'repos'), { recursive: true });
|
|
755
|
-
|
|
820
|
+
cloneSlim();
|
|
756
821
|
cloned++;
|
|
757
822
|
repoReady = true;
|
|
758
823
|
} catch (err) {
|
|
@@ -767,6 +832,11 @@ async function install() {
|
|
|
767
832
|
} else {
|
|
768
833
|
// Update existing: fetch latest and fast-forward
|
|
769
834
|
try {
|
|
835
|
+
// Re-assert the sparse set so a newer manifest that adds a subpath to
|
|
836
|
+
// an already-slim clone checks it out (idempotent; no-op for full clones).
|
|
837
|
+
if (!plan.full && isPartialSparseClone(clonePath)) {
|
|
838
|
+
try { execFileSync('git', ['-C', clonePath, 'sparse-checkout', 'set', '--no-cone', ...plan.paths], { stdio: 'pipe', timeout: 30000 }); } catch {}
|
|
839
|
+
}
|
|
770
840
|
const localHash = execFileSync('git', ['-C', clonePath, 'rev-parse', 'HEAD'], { encoding: 'utf8', stdio: 'pipe' }).trim();
|
|
771
841
|
execFileSync('git', ['-C', clonePath, 'fetch', '--depth', '1', 'origin'], { stdio: 'pipe', timeout: 30000 });
|
|
772
842
|
const remoteHash = execFileSync('git', ['-C', clonePath, 'rev-parse', 'FETCH_HEAD'], { encoding: 'utf8', stdio: 'pipe' }).trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-mem-lite",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.96.0",
|
|
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",
|