@hasna/mementos 0.10.15 → 0.10.16
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/dist/mcp/index.js +67 -0
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -9826,6 +9826,73 @@ ${lines.join(`
|
|
|
9826
9826
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
9827
9827
|
}
|
|
9828
9828
|
});
|
|
9829
|
+
server.tool("memory_health", "Comprehensive health check for memories. Detects: stale (old + 0 access), high-importance-forgotten (importance>=7 + not accessed in 60d), and possibly-superseded (newer memory with similar key). Returns actionable summary.", {
|
|
9830
|
+
stale_days: exports_external.coerce.number().optional().describe("Days with no access to consider a memory stale (default: 30)"),
|
|
9831
|
+
forgotten_days: exports_external.coerce.number().optional().describe("Days since access for high-importance memories (default: 60)"),
|
|
9832
|
+
project_id: exports_external.string().optional(),
|
|
9833
|
+
agent_id: exports_external.string().optional(),
|
|
9834
|
+
limit: exports_external.coerce.number().optional().describe("Max per category (default: 10)")
|
|
9835
|
+
}, async (args) => {
|
|
9836
|
+
try {
|
|
9837
|
+
const db = getDatabase();
|
|
9838
|
+
const staleDays = args.stale_days ?? 30;
|
|
9839
|
+
const forgottenDays = args.forgotten_days ?? 60;
|
|
9840
|
+
const limit = args.limit ?? 10;
|
|
9841
|
+
const extraWhere = [
|
|
9842
|
+
...args.project_id ? ["project_id = ?"] : [],
|
|
9843
|
+
...args.agent_id ? ["agent_id = ?"] : []
|
|
9844
|
+
].join(" AND ");
|
|
9845
|
+
const extraParams = [
|
|
9846
|
+
...args.project_id ? [args.project_id] : [],
|
|
9847
|
+
...args.agent_id ? [args.agent_id] : []
|
|
9848
|
+
];
|
|
9849
|
+
const base = `status = 'active' AND pinned = 0${extraWhere ? " AND " + extraWhere : ""}`;
|
|
9850
|
+
const stale = db.prepare(`SELECT id, key, value, importance, scope, created_at FROM memories
|
|
9851
|
+
WHERE ${base} AND access_count = 0 AND created_at < datetime('now', '-${staleDays} days')
|
|
9852
|
+
ORDER BY created_at ASC LIMIT ?`).all(...extraParams, limit);
|
|
9853
|
+
const forgotten = db.prepare(`SELECT id, key, value, importance, scope, accessed_at FROM memories
|
|
9854
|
+
WHERE ${base} AND importance >= 7
|
|
9855
|
+
AND (accessed_at IS NULL OR accessed_at < datetime('now', '-${forgottenDays} days'))
|
|
9856
|
+
ORDER BY importance DESC, COALESCE(accessed_at, created_at) ASC LIMIT ?`).all(...extraParams, limit);
|
|
9857
|
+
const dupes = db.prepare(`SELECT key, COUNT(*) as cnt, MAX(updated_at) as latest, MIN(created_at) as oldest
|
|
9858
|
+
FROM memories WHERE ${base}
|
|
9859
|
+
GROUP BY key HAVING cnt > 1
|
|
9860
|
+
ORDER BY cnt DESC LIMIT ?`).all(...extraParams, limit);
|
|
9861
|
+
const parts = [`Memory Health Report
|
|
9862
|
+
`];
|
|
9863
|
+
if (stale.length > 0) {
|
|
9864
|
+
parts.push(`\u26A0\uFE0F STALE (${stale.length}) \u2014 created ${staleDays}d+ ago, never accessed:`);
|
|
9865
|
+
for (const m of stale) {
|
|
9866
|
+
parts.push(` \u2022 [${m.importance}] ${m.key} (${m.scope}) \u2014 created ${m.created_at.slice(0, 10)}`);
|
|
9867
|
+
}
|
|
9868
|
+
parts.push("");
|
|
9869
|
+
}
|
|
9870
|
+
if (forgotten.length > 0) {
|
|
9871
|
+
parts.push(`\uD83D\uDD14 HIGH-IMPORTANCE FORGOTTEN (${forgotten.length}) \u2014 importance\u22657, not accessed in ${forgottenDays}d+:`);
|
|
9872
|
+
for (const m of forgotten) {
|
|
9873
|
+
parts.push(` \u2022 [${m.importance}] ${m.key} (${m.scope}) \u2014 last: ${m.accessed_at?.slice(0, 10) || "never"}`);
|
|
9874
|
+
}
|
|
9875
|
+
parts.push("");
|
|
9876
|
+
}
|
|
9877
|
+
if (dupes.length > 0) {
|
|
9878
|
+
parts.push(`\uD83D\uDD04 POSSIBLY SUPERSEDED (${dupes.length}) \u2014 same key with multiple versions:`);
|
|
9879
|
+
for (const d of dupes) {
|
|
9880
|
+
parts.push(` \u2022 ${d.key} \xD7 ${d.cnt} copies \u2014 newest: ${d.latest.slice(0, 10)}`);
|
|
9881
|
+
}
|
|
9882
|
+
parts.push("");
|
|
9883
|
+
}
|
|
9884
|
+
if (stale.length === 0 && forgotten.length === 0 && dupes.length === 0) {
|
|
9885
|
+
parts.push("\u2713 No health issues found. All memories look fresh.");
|
|
9886
|
+
} else {
|
|
9887
|
+
parts.push(`Summary: ${stale.length} stale, ${forgotten.length} forgotten, ${dupes.length} possibly-superseded.`);
|
|
9888
|
+
parts.push("Suggested actions: archive stale memories, review forgotten ones, merge duplicates.");
|
|
9889
|
+
}
|
|
9890
|
+
return { content: [{ type: "text", text: parts.join(`
|
|
9891
|
+
`) }] };
|
|
9892
|
+
} catch (e) {
|
|
9893
|
+
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
9894
|
+
}
|
|
9895
|
+
});
|
|
9829
9896
|
server.tool("memory_search", "Search memories by keyword across key, value, summary, and tags", {
|
|
9830
9897
|
query: exports_external.string(),
|
|
9831
9898
|
scope: exports_external.enum(["global", "shared", "private"]).optional(),
|