hippo-memory 1.11.2 → 1.11.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.
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Store-level deduplication. Scans for near-duplicate memories by content
3
+ * Jaccard overlap, keeps the stronger copy (by strength + retrieval count),
4
+ * removes the rest.
5
+ *
6
+ * Extracted from cli.ts in Episode A (v1.11.3) so `api.sleep` can dedupe
7
+ * during the consolidation pipeline without violating the cli -> api
8
+ * dependency direction. `cmdDedup` in cli.ts continues to import and use
9
+ * this function unchanged.
10
+ */
11
+ import { textOverlap } from './search.js';
12
+ import { loadAllEntries, deleteEntry } from './store.js';
13
+ /**
14
+ * Scan the store for near-duplicate memories and remove the weaker copy.
15
+ * Two memories are duplicates if their content has > threshold Jaccard overlap.
16
+ * Keeps the one with higher strength (or more retrievals if tied).
17
+ */
18
+ export function deduplicateStore(hippoRoot, options = {}) {
19
+ const threshold = options.threshold ?? 0.7;
20
+ const dryRun = options.dryRun ?? false;
21
+ const entries = loadAllEntries(hippoRoot);
22
+ // Sort by strength desc, then retrieval count, so we keep the most valuable copy
23
+ entries.sort((a, b) => {
24
+ const sDiff = (b.strength ?? 0) - (a.strength ?? 0);
25
+ if (Math.abs(sDiff) > 0.01)
26
+ return sDiff;
27
+ return (b.retrieval_count ?? 0) - (a.retrieval_count ?? 0);
28
+ });
29
+ const removed = new Set();
30
+ const pairs = [];
31
+ for (let i = 0; i < entries.length; i++) {
32
+ if (removed.has(entries[i].id))
33
+ continue;
34
+ for (let j = i + 1; j < entries.length; j++) {
35
+ if (removed.has(entries[j].id))
36
+ continue;
37
+ const similarity = textOverlap(entries[i].content, entries[j].content);
38
+ if (similarity <= threshold)
39
+ continue;
40
+ removed.add(entries[j].id);
41
+ pairs.push({
42
+ kept: entries[i].id,
43
+ keptContent: entries[i].content,
44
+ keptLayer: entries[i].layer,
45
+ keptStrength: entries[i].strength ?? 0,
46
+ removed: entries[j].id,
47
+ removedContent: entries[j].content,
48
+ removedLayer: entries[j].layer,
49
+ removedStrength: entries[j].strength ?? 0,
50
+ similarity,
51
+ });
52
+ }
53
+ }
54
+ if (!dryRun) {
55
+ for (const id of removed) {
56
+ deleteEntry(hippoRoot, id);
57
+ }
58
+ }
59
+ return { removed: removed.size, pairs };
60
+ }
61
+ //# sourceMappingURL=dedupe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedupe.js","sourceRoot":"","sources":["../../src/dedupe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAczD;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,SAAiB,EACjB,UAAoD,EAAE;IAEtD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,GAAG,CAAC;IAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC;IACvC,MAAM,OAAO,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAE1C,iFAAiF;IACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACpB,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;QACpD,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI;YAAE,OAAO,KAAK,CAAC;QACzC,OAAO,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,KAAK,GAAgB,EAAE,CAAC;IAE9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAAE,SAAS;QACzC,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAAE,SAAS;YAEzC,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACvE,IAAI,UAAU,IAAI,SAAS;gBAAE,SAAS;YAEtC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;gBACnB,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;gBAC/B,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK;gBAC3B,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC;gBACtC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;gBACtB,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;gBAClC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK;gBAC9B,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC;gBACzC,UAAU;aACX,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;YACzB,WAAW,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;AAC1C,CAAC"}
@@ -18,7 +18,7 @@
18
18
  * an ESM `import` can resolve cleanly, and a hardcoded constant survives
19
19
  * any packager that drops .json files.
20
20
  */
21
- export const PACKAGE_VERSION = '1.11.2';
21
+ export const PACKAGE_VERSION = '1.11.3';
22
22
  // Bump on every release alongside the 4 other manifests + lockfile.
23
23
  /**
24
24
  * Compare two semver strings. Returns positive if a > b, 0 if equal, negative
package/dist/version.d.ts CHANGED
@@ -18,7 +18,7 @@
18
18
  * an ESM `import` can resolve cleanly, and a hardcoded constant survives
19
19
  * any packager that drops .json files.
20
20
  */
21
- export declare const PACKAGE_VERSION = "1.11.2";
21
+ export declare const PACKAGE_VERSION = "1.11.3";
22
22
  /**
23
23
  * Compare two semver strings. Returns positive if a > b, 0 if equal, negative
24
24
  * if a < b.
package/dist/version.js CHANGED
@@ -18,7 +18,7 @@
18
18
  * an ESM `import` can resolve cleanly, and a hardcoded constant survives
19
19
  * any packager that drops .json files.
20
20
  */
21
- export const PACKAGE_VERSION = '1.11.2';
21
+ export const PACKAGE_VERSION = '1.11.3';
22
22
  // Bump on every release alongside the 4 other manifests + lockfile.
23
23
  /**
24
24
  * Compare two semver strings. Returns positive if a > b, 0 if equal, negative
@@ -2,7 +2,7 @@
2
2
  "id": "hippo-memory",
3
3
  "name": "Hippo Memory",
4
4
  "description": "Biologically-inspired memory for AI agents. Decay by default, retrieval strengthening, sleep consolidation.",
5
- "version": "1.11.2",
5
+ "version": "1.11.3",
6
6
 
7
7
  "configSchema": {
8
8
  "type": "object",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hippo-memory",
3
- "version": "1.11.2",
3
+ "version": "1.11.3",
4
4
  "description": "Hippo Memory plugin for OpenClaw - biologically-inspired agent memory",
5
5
  "main": "index.ts",
6
6
  "openclaw": {
@@ -2,7 +2,7 @@
2
2
  "id": "hippo-memory",
3
3
  "name": "Hippo Memory",
4
4
  "description": "Biologically-inspired memory for AI agents. Decay by default, retrieval strengthening, sleep consolidation.",
5
- "version": "1.11.2",
5
+ "version": "1.11.3",
6
6
  "configSchema": {
7
7
  "type": "object",
8
8
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hippo-memory",
3
- "version": "1.11.2",
3
+ "version": "1.11.3",
4
4
  "description": "Biologically-inspired memory system for AI agents. Decay by default, strength through use.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",