hmem-mcp 7.0.5 → 7.1.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/README.md +1 -1
- package/dist/cli-stats.d.ts +9 -0
- package/dist/cli-stats.js +101 -0
- package/dist/cli-stats.js.map +1 -0
- package/dist/cli.js +5 -0
- package/dist/cli.js.map +1 -1
- package/dist/hmem-store.d.ts +11 -0
- package/dist/hmem-store.js +43 -2
- package/dist/hmem-store.js.map +1 -1
- package/dist/mcp-server.js +24 -23
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -1
- package/skills/hmem-activate/SKILL.md +9 -0
- package/skills/hmem-curate/SKILL.md +7 -0
- package/skills/hmem-dispatch/SKILL.md +7 -0
- package/skills/hmem-session-start/SKILL.md +22 -1
- package/skills/hmem-update/SKILL.md +20 -0
- package/skills/hmem-write/SKILL.md +18 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Your AI forgets everything between sessions. **hmem fixes that.**
|
|
4
4
|
|
|
5
|
-
One `
|
|
5
|
+
One `load_project()` call. 5k tokens. Your agent knows everything important about a project, every past mistake, every decision you ever made together — across sessions, devices, and AI providers. No setup per conversation. No "let me re-read the codebase." It just *remembers*.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cli-stats.ts
|
|
3
|
+
*
|
|
4
|
+
* Shows per-project token size estimates and global memory stats.
|
|
5
|
+
* Helps identify projects approaching the curation threshold (R0018: >4k tokens = trigger).
|
|
6
|
+
*
|
|
7
|
+
* Usage: hmem stats [project-id]
|
|
8
|
+
*/
|
|
9
|
+
export declare function printStats(filterProject?: string): Promise<void>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cli-stats.ts
|
|
3
|
+
*
|
|
4
|
+
* Shows per-project token size estimates and global memory stats.
|
|
5
|
+
* Helps identify projects approaching the curation threshold (R0018: >4k tokens = trigger).
|
|
6
|
+
*
|
|
7
|
+
* Usage: hmem stats [project-id]
|
|
8
|
+
*/
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import { resolveEnvDefaults } from "./cli-env.js";
|
|
11
|
+
import { HmemStore } from "./hmem-store.js";
|
|
12
|
+
import { loadHmemConfig } from "./hmem-config.js";
|
|
13
|
+
const C = {
|
|
14
|
+
green: "\x1b[01;32m",
|
|
15
|
+
yellow: "\x1b[01;33m",
|
|
16
|
+
red: "\x1b[01;31m",
|
|
17
|
+
cyan: "\x1b[00;36m",
|
|
18
|
+
gray: "\x1b[00;90m",
|
|
19
|
+
white: "\x1b[00;37m",
|
|
20
|
+
bold: "\x1b[01m",
|
|
21
|
+
reset: "\x1b[00m",
|
|
22
|
+
};
|
|
23
|
+
// R0018 thresholds (chars, not tokens — 1 token ≈ 4 chars)
|
|
24
|
+
const RED_THRESHOLD = 16_000; // ~4k tokens
|
|
25
|
+
const YELLOW_THRESHOLD = 14_000; // ~3.5k tokens
|
|
26
|
+
function sizeColor(chars) {
|
|
27
|
+
if (chars >= RED_THRESHOLD)
|
|
28
|
+
return C.red;
|
|
29
|
+
if (chars >= YELLOW_THRESHOLD)
|
|
30
|
+
return C.yellow;
|
|
31
|
+
return C.green;
|
|
32
|
+
}
|
|
33
|
+
function sizeLabel(chars) {
|
|
34
|
+
const tokens = Math.round(chars / 4);
|
|
35
|
+
if (tokens >= 1000)
|
|
36
|
+
return `~${(tokens / 1000).toFixed(1)}k tokens`;
|
|
37
|
+
return `~${tokens} tokens`;
|
|
38
|
+
}
|
|
39
|
+
function relativeDate(iso) {
|
|
40
|
+
if (!iso)
|
|
41
|
+
return "never";
|
|
42
|
+
const diff = Date.now() - new Date(iso).getTime();
|
|
43
|
+
const days = Math.floor(diff / 86_400_000);
|
|
44
|
+
if (days === 0)
|
|
45
|
+
return "today";
|
|
46
|
+
if (days === 1)
|
|
47
|
+
return "yesterday";
|
|
48
|
+
if (days < 30)
|
|
49
|
+
return `${days}d ago`;
|
|
50
|
+
return `${Math.floor(days / 30)}mo ago`;
|
|
51
|
+
}
|
|
52
|
+
export async function printStats(filterProject) {
|
|
53
|
+
resolveEnvDefaults();
|
|
54
|
+
const hmemPath = process.env.HMEM_PATH;
|
|
55
|
+
if (!hmemPath) {
|
|
56
|
+
console.error("HMEM_PATH not set.");
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
const dir = path.dirname(hmemPath);
|
|
60
|
+
const config = loadHmemConfig(dir);
|
|
61
|
+
const store = new HmemStore(hmemPath, config);
|
|
62
|
+
const global = store.stats();
|
|
63
|
+
const projects = store.projectTokenStats();
|
|
64
|
+
const totalTokens = Math.round(global.totalChars / 4);
|
|
65
|
+
console.log(`\n${C.bold}hmem stats${C.reset} ${C.gray}${path.basename(hmemPath)}${C.reset}`);
|
|
66
|
+
console.log(`${C.gray}${"─".repeat(60)}${C.reset}`);
|
|
67
|
+
console.log(` Total entries : ${C.white}${global.total}${C.reset}`);
|
|
68
|
+
console.log(` Total size : ${C.white}${totalTokens >= 1000 ? (totalTokens / 1000).toFixed(0) + "k" : totalTokens} tokens${C.reset} ${C.gray}(${(global.totalChars / 1024).toFixed(0)} KB)${C.reset}`);
|
|
69
|
+
if (global.staleCount > 0) {
|
|
70
|
+
console.log(` Stale (60d+) : ${C.yellow}${global.staleCount} entries${C.reset}`);
|
|
71
|
+
}
|
|
72
|
+
const prefixOrder = ["P", "L", "T", "E", "D", "R", "O", "I", "H", "M", "S", "N", "C", "A"];
|
|
73
|
+
const prefixLine = prefixOrder
|
|
74
|
+
.filter(p => global.byPrefix[p])
|
|
75
|
+
.map(p => `${C.gray}${p}${C.reset}${C.white}${global.byPrefix[p]}${C.reset}`)
|
|
76
|
+
.join(" ");
|
|
77
|
+
console.log(` By prefix : ${prefixLine}`);
|
|
78
|
+
const filtered = filterProject
|
|
79
|
+
? projects.filter(p => p.id.toLowerCase() === filterProject.toLowerCase())
|
|
80
|
+
: projects;
|
|
81
|
+
if (filtered.length === 0) {
|
|
82
|
+
console.log(`\n ${C.gray}No matching projects.${C.reset}\n`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
console.log(`\n${C.bold}Projects — load_project size estimate${C.reset} ${C.gray}(R0018: >4k = curate)${C.reset}`);
|
|
86
|
+
console.log(`${C.gray}${"─".repeat(60)}${C.reset}`);
|
|
87
|
+
for (const p of filtered) {
|
|
88
|
+
const color = sizeColor(p.estChars);
|
|
89
|
+
const flag = p.estChars >= RED_THRESHOLD ? " 🔴" : p.estChars >= YELLOW_THRESHOLD ? " 🟡" : "";
|
|
90
|
+
const activeMarker = p.active ? ` ${C.cyan}●${C.reset}` : "";
|
|
91
|
+
const label = sizeLabel(p.estChars);
|
|
92
|
+
const date = relativeDate(p.lastAccessed);
|
|
93
|
+
const idPart = `${C.cyan}${p.id}${C.reset}`;
|
|
94
|
+
const namePart = p.title.length > 28 ? p.title.substring(0, 27) + "…" : p.title.padEnd(28);
|
|
95
|
+
const sizePart = `${color}${label}${C.reset}${flag}`;
|
|
96
|
+
const datePart = `${C.gray}${date}${C.reset}`;
|
|
97
|
+
console.log(` ${idPart}${activeMarker} ${namePart} ${sizePart} ${datePart}`);
|
|
98
|
+
}
|
|
99
|
+
console.log(`\n${C.gray}Thresholds: 🟡 ~3.5k tokens 🔴 ~4k tokens${C.reset}\n`);
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=cli-stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-stats.js","sourceRoot":"","sources":["../src/cli-stats.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -62,6 +62,11 @@ switch (command) {
|
|
|
62
62
|
await summarizeSession(process.argv[3] || "");
|
|
63
63
|
break;
|
|
64
64
|
}
|
|
65
|
+
case "stats": {
|
|
66
|
+
const { printStats } = await import("./cli-stats.js");
|
|
67
|
+
await printStats(process.argv[3]);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
65
70
|
case "delete": {
|
|
66
71
|
const { deleteEntry } = await import("./cli-delete.js");
|
|
67
72
|
await deleteEntry(process.argv.slice(3));
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/hmem-store.d.ts
CHANGED
|
@@ -309,6 +309,17 @@ export declare class HmemStore {
|
|
|
309
309
|
totalChars: number;
|
|
310
310
|
staleCount: number;
|
|
311
311
|
};
|
|
312
|
+
/**
|
|
313
|
+
* Per-project token size estimates for `hmem stats`.
|
|
314
|
+
* Measures load_project payload size: level_1 + all node content/titles at depth ≤ 3.
|
|
315
|
+
*/
|
|
316
|
+
projectTokenStats(): Array<{
|
|
317
|
+
id: string;
|
|
318
|
+
title: string;
|
|
319
|
+
estChars: number;
|
|
320
|
+
lastAccessed: string | null;
|
|
321
|
+
active: number;
|
|
322
|
+
}>;
|
|
312
323
|
/**
|
|
313
324
|
* Update specific fields of an existing root entry (curator use only).
|
|
314
325
|
*/
|
package/dist/hmem-store.js
CHANGED
|
@@ -655,8 +655,21 @@ export class HmemStore {
|
|
|
655
655
|
const searchTerm = opts.search.replace(/"/g, "").trim();
|
|
656
656
|
if (!searchTerm)
|
|
657
657
|
return [];
|
|
658
|
-
//
|
|
659
|
-
const
|
|
658
|
+
// Stopwords that pollute BM25 rankings in code/memory context
|
|
659
|
+
const FTS_STOPWORDS = new Set([
|
|
660
|
+
"the", "a", "an", "and", "or", "in", "of", "to", "with", "on", "for", "is", "are", "was", "were", "be", "been",
|
|
661
|
+
"add", "added", "fix", "fixed", "update", "updates", "updated", "run", "running", "using", "use", "used",
|
|
662
|
+
"test", "tests", "done", "make", "made", "new", "get", "set", "has", "have", "had", "its",
|
|
663
|
+
"der", "die", "das", "ein", "eine", "und", "oder", "von", "zu", "mit", "auf", "ist", "sind", "hat", "haben",
|
|
664
|
+
]);
|
|
665
|
+
const words = searchTerm.split(/\s+/)
|
|
666
|
+
.map(w => w.replace(/[^a-zA-Z0-9äöüÄÖÜß_-]/g, ""))
|
|
667
|
+
.filter(w => w.length > 1 && !FTS_STOPWORDS.has(w.toLowerCase()));
|
|
668
|
+
// Multi-word: AND match on individual tokens (better recall than phrase match)
|
|
669
|
+
// Single-word or all-stopwords: fall back to phrase match on original term
|
|
670
|
+
const ftsMatch = words.length >= 2
|
|
671
|
+
? words.map(w => `"${w}"`).join(" ")
|
|
672
|
+
: `"${searchTerm}"`;
|
|
660
673
|
const ftsRows = this.db.prepare("SELECT rm.root_id, rm.node_id FROM hmem_fts_rowid_map rm " +
|
|
661
674
|
"JOIN hmem_fts fts ON fts.rowid = rm.fts_rowid " +
|
|
662
675
|
"WHERE hmem_fts MATCH ?").all(ftsMatch);
|
|
@@ -1673,6 +1686,34 @@ export class HmemStore {
|
|
|
1673
1686
|
const staleCount = this.db.prepare("SELECT COUNT(*) as c FROM memories WHERE seq > 0 AND prefix != 'O' AND irrelevant != 1 AND obsolete != 1 AND last_accessed < datetime('now', '-60 days')").get().c;
|
|
1674
1687
|
return { total, byPrefix, totalChars: memChars + nodeChars, staleCount };
|
|
1675
1688
|
}
|
|
1689
|
+
/**
|
|
1690
|
+
* Per-project token size estimates for `hmem stats`.
|
|
1691
|
+
* Measures load_project payload size: level_1 + all node content/titles at depth ≤ 3.
|
|
1692
|
+
*/
|
|
1693
|
+
projectTokenStats() {
|
|
1694
|
+
const rows = this.db.prepare(`
|
|
1695
|
+
SELECT
|
|
1696
|
+
m.id,
|
|
1697
|
+
m.title,
|
|
1698
|
+
m.last_accessed,
|
|
1699
|
+
m.active,
|
|
1700
|
+
COALESCE(LENGTH(m.level_1), 0) + COALESCE((
|
|
1701
|
+
SELECT SUM(LENGTH(COALESCE(n.title,'')) + LENGTH(COALESCE(n.content,'')))
|
|
1702
|
+
FROM memory_nodes n
|
|
1703
|
+
WHERE n.root_id = m.id AND n.depth <= 3
|
|
1704
|
+
), 0) AS est_chars
|
|
1705
|
+
FROM memories m
|
|
1706
|
+
WHERE m.prefix = 'P' AND m.obsolete != 1 AND m.irrelevant != 1 AND m.seq > 0
|
|
1707
|
+
ORDER BY m.last_accessed DESC NULLS LAST
|
|
1708
|
+
`).all();
|
|
1709
|
+
return rows.map(r => ({
|
|
1710
|
+
id: r.id,
|
|
1711
|
+
title: (r.title ?? "").split("|")[0].trim(),
|
|
1712
|
+
estChars: r.est_chars ?? 0,
|
|
1713
|
+
lastAccessed: r.last_accessed ?? null,
|
|
1714
|
+
active: r.active ?? 0,
|
|
1715
|
+
}));
|
|
1716
|
+
}
|
|
1676
1717
|
/**
|
|
1677
1718
|
* Update specific fields of an existing root entry (curator use only).
|
|
1678
1719
|
*/
|