hippo-memory 0.8.0 → 0.9.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.
Files changed (43) hide show
  1. package/README.md +99 -13
  2. package/dist/cli.d.ts +5 -2
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +589 -209
  5. package/dist/cli.js.map +1 -1
  6. package/dist/consolidate.d.ts.map +1 -1
  7. package/dist/consolidate.js +12 -5
  8. package/dist/consolidate.js.map +1 -1
  9. package/dist/dashboard.d.ts +8 -0
  10. package/dist/dashboard.d.ts.map +1 -0
  11. package/dist/dashboard.js +306 -0
  12. package/dist/dashboard.js.map +1 -0
  13. package/dist/db.d.ts.map +1 -1
  14. package/dist/db.js +149 -100
  15. package/dist/db.js.map +1 -1
  16. package/dist/handoff.d.ts +29 -0
  17. package/dist/handoff.d.ts.map +1 -0
  18. package/dist/handoff.js +30 -0
  19. package/dist/handoff.js.map +1 -0
  20. package/dist/index.d.ts +4 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +4 -2
  23. package/dist/index.js.map +1 -1
  24. package/dist/mcp/server.js +78 -2
  25. package/dist/mcp/server.js.map +1 -1
  26. package/dist/search.d.ts +19 -0
  27. package/dist/search.d.ts.map +1 -1
  28. package/dist/search.js +35 -1
  29. package/dist/search.js.map +1 -1
  30. package/dist/store.d.ts +18 -0
  31. package/dist/store.d.ts.map +1 -1
  32. package/dist/store.js +209 -99
  33. package/dist/store.js.map +1 -1
  34. package/dist/working-memory.d.ts +59 -0
  35. package/dist/working-memory.d.ts.map +1 -0
  36. package/dist/working-memory.js +149 -0
  37. package/dist/working-memory.js.map +1 -0
  38. package/extensions/openclaw-plugin/README.md +6 -2
  39. package/extensions/openclaw-plugin/index.ts +569 -370
  40. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  41. package/extensions/openclaw-plugin/package.json +1 -1
  42. package/openclaw.plugin.json +1 -1
  43. package/package.json +1 -1
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Hippo Dashboard — local web UI for memory health visualization.
3
+ * Serves a single-page app with memory stats, decay curves, and conflict status.
4
+ *
5
+ * Usage: hippo dashboard [--port 3333]
6
+ */
7
+ import * as http from 'http';
8
+ import { loadAllEntries, listMemoryConflicts } from './store.js';
9
+ import { calculateStrength, resolveConfidence } from './memory.js';
10
+ import { loadConfig } from './config.js';
11
+ import { listPeers } from './shared.js';
12
+ import { loadEmbeddingIndex } from './embeddings.js';
13
+ function buildDashboardData(hippoRoot) {
14
+ const entries = loadAllEntries(hippoRoot);
15
+ const now = new Date();
16
+ const config = loadConfig(hippoRoot);
17
+ const conflicts = listMemoryConflicts(hippoRoot, 'open');
18
+ const peers = listPeers();
19
+ const embeddingIndex = loadEmbeddingIndex(hippoRoot);
20
+ const embeddedCount = Object.keys(embeddingIndex).length;
21
+ let totalStrength = 0;
22
+ let totalHalfLife = 0;
23
+ let atRisk = 0;
24
+ const byLayer = {};
25
+ const byConfidence = {};
26
+ const memories = entries.map((e) => {
27
+ const strength = calculateStrength(e, now);
28
+ const confidence = resolveConfidence(e, now);
29
+ const ageDays = (now.getTime() - new Date(e.created).getTime()) / (1000 * 60 * 60 * 24);
30
+ totalStrength += strength;
31
+ totalHalfLife += e.half_life_days;
32
+ if (strength < 0.1 && !e.pinned)
33
+ atRisk++;
34
+ byLayer[e.layer] = (byLayer[e.layer] ?? 0) + 1;
35
+ byConfidence[confidence] = (byConfidence[confidence] ?? 0) + 1;
36
+ // Project strength at +7d and +30d
37
+ const future7 = { ...e, last_retrieved: e.last_retrieved };
38
+ const future30 = { ...e, last_retrieved: e.last_retrieved };
39
+ const in7d = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
40
+ const in30d = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000);
41
+ return {
42
+ id: e.id,
43
+ content: e.content,
44
+ tags: e.tags,
45
+ layer: e.layer,
46
+ strength,
47
+ half_life_days: e.half_life_days,
48
+ retrieval_count: e.retrieval_count,
49
+ schema_fit: e.schema_fit,
50
+ emotional_valence: e.emotional_valence,
51
+ confidence,
52
+ pinned: e.pinned,
53
+ created: e.created,
54
+ last_retrieved: e.last_retrieved,
55
+ age_days: Math.round(ageDays * 10) / 10,
56
+ projected_strength_7d: calculateStrength(future7, in7d),
57
+ projected_strength_30d: calculateStrength(future30, in30d),
58
+ };
59
+ });
60
+ return {
61
+ memories,
62
+ conflicts: conflicts.map((c) => ({
63
+ id: c.id,
64
+ memory_a_id: c.memory_a_id,
65
+ memory_b_id: c.memory_b_id,
66
+ reason: c.reason,
67
+ score: c.score,
68
+ status: c.status,
69
+ })),
70
+ stats: {
71
+ total: entries.length,
72
+ pinned: entries.filter((e) => e.pinned).length,
73
+ errors: entries.filter((e) => e.tags.includes('error')).length,
74
+ at_risk: atRisk,
75
+ avg_strength: entries.length > 0 ? totalStrength / entries.length : 0,
76
+ avg_half_life: entries.length > 0 ? totalHalfLife / entries.length : 0,
77
+ by_layer: byLayer,
78
+ by_confidence: byConfidence,
79
+ embedding_coverage: entries.length > 0 ? embeddedCount / entries.length : 0,
80
+ open_conflicts: conflicts.length,
81
+ },
82
+ peers,
83
+ config: {
84
+ defaultHalfLifeDays: config.defaultHalfLifeDays,
85
+ defaultBudget: config.defaultBudget,
86
+ embeddingsEnabled: config.embeddings.enabled,
87
+ },
88
+ };
89
+ }
90
+ function dashboardHTML(data) {
91
+ return `<!DOCTYPE html>
92
+ <html lang="en">
93
+ <head>
94
+ <meta charset="utf-8">
95
+ <meta name="viewport" content="width=device-width, initial-scale=1">
96
+ <title>Hippo Dashboard</title>
97
+ <style>
98
+ :root {
99
+ --bg: #0f1117; --surface: #1a1d27; --border: #2a2d3a;
100
+ --text: #e1e4ed; --muted: #8b8fa3; --accent: #6c8cff;
101
+ --green: #4ade80; --yellow: #fbbf24; --red: #f87171; --purple: #a78bfa;
102
+ }
103
+ * { box-sizing: border-box; margin: 0; padding: 0; }
104
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif; background: var(--bg); color: var(--text); padding: 24px; max-width: 1200px; margin: 0 auto; }
105
+ h1 { font-size: 24px; margin-bottom: 4px; }
106
+ h1 span { font-size: 14px; color: var(--muted); font-weight: normal; margin-left: 8px; }
107
+ h2 { font-size: 16px; color: var(--muted); margin-bottom: 12px; text-transform: uppercase; letter-spacing: 0.5px; }
108
+ .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-bottom: 24px; }
109
+ .card { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 16px; }
110
+ .card .label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
111
+ .card .value { font-size: 28px; font-weight: 600; margin-top: 4px; }
112
+ .card .sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
113
+ .bar-chart { display: flex; gap: 4px; align-items: flex-end; height: 120px; margin-top: 8px; }
114
+ .bar { flex: 1; min-width: 4px; background: var(--accent); border-radius: 2px 2px 0 0; position: relative; transition: background 0.2s; cursor: default; }
115
+ .bar:hover { background: #8aa4ff; }
116
+ .bar .tooltip { display: none; position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); background: var(--surface); border: 1px solid var(--border); padding: 4px 8px; border-radius: 4px; font-size: 11px; white-space: nowrap; z-index: 10; }
117
+ .bar:hover .tooltip { display: block; }
118
+ .strength-high { background: var(--green); }
119
+ .strength-mid { background: var(--yellow); }
120
+ .strength-low { background: var(--red); }
121
+ table { width: 100%; border-collapse: collapse; font-size: 13px; }
122
+ th { text-align: left; padding: 8px; border-bottom: 2px solid var(--border); color: var(--muted); font-size: 11px; text-transform: uppercase; }
123
+ td { padding: 8px; border-bottom: 1px solid var(--border); vertical-align: top; }
124
+ tr:hover { background: rgba(108, 140, 255, 0.05); }
125
+ .tag { display: inline-block; padding: 2px 6px; border-radius: 4px; font-size: 11px; background: var(--border); color: var(--muted); margin: 1px; }
126
+ .tag-error { background: rgba(248, 113, 113, 0.15); color: var(--red); }
127
+ .strength-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 4px; }
128
+ .pill { display: inline-block; padding: 2px 8px; border-radius: 10px; font-size: 11px; }
129
+ .pill-pinned { background: rgba(167, 139, 250, 0.15); color: var(--purple); }
130
+ .pill-stale { background: rgba(251, 191, 36, 0.15); color: var(--yellow); }
131
+ .content-preview { max-width: 400px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
132
+ .section { margin-bottom: 32px; }
133
+ .conflict-card { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 12px; margin-bottom: 8px; }
134
+ .conflict-card .reason { color: var(--muted); font-size: 12px; }
135
+ .search { width: 100%; padding: 8px 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 6px; color: var(--text); font-size: 14px; margin-bottom: 12px; outline: none; }
136
+ .search:focus { border-color: var(--accent); }
137
+ .tabs { display: flex; gap: 4px; margin-bottom: 16px; }
138
+ .tab { padding: 6px 14px; border-radius: 6px; font-size: 13px; cursor: pointer; background: var(--surface); border: 1px solid var(--border); color: var(--muted); }
139
+ .tab.active { background: var(--accent); color: #fff; border-color: var(--accent); }
140
+ .footer { text-align: center; color: var(--muted); font-size: 12px; margin-top: 40px; padding-top: 16px; border-top: 1px solid var(--border); }
141
+ </style>
142
+ </head>
143
+ <body>
144
+ <h1>Hippo Dashboard <span>v0.8.0</span></h1>
145
+ <p style="color: var(--muted); margin-bottom: 24px;">Memory health at a glance. Auto-refreshes on page load.</p>
146
+
147
+ <div class="section">
148
+ <h2>Overview</h2>
149
+ <div class="grid" id="stats-grid"></div>
150
+ </div>
151
+
152
+ <div class="section">
153
+ <h2>Strength Distribution</h2>
154
+ <div class="card">
155
+ <div class="bar-chart" id="strength-chart"></div>
156
+ <div style="display: flex; justify-content: space-between; margin-top: 8px; font-size: 11px; color: var(--muted);">
157
+ <span>Weakest</span><span>Strongest</span>
158
+ </div>
159
+ </div>
160
+ </div>
161
+
162
+ <div class="section" id="conflicts-section" style="display:none;">
163
+ <h2>Open Conflicts</h2>
164
+ <div id="conflicts-list"></div>
165
+ </div>
166
+
167
+ <div class="section" id="peers-section" style="display:none;">
168
+ <h2>Shared Memory Peers</h2>
169
+ <div id="peers-list"></div>
170
+ </div>
171
+
172
+ <div class="section">
173
+ <h2>Memories</h2>
174
+ <input type="text" class="search" id="search" placeholder="Filter by content or tag...">
175
+ <div class="tabs" id="tabs">
176
+ <div class="tab active" data-filter="all">All</div>
177
+ <div class="tab" data-filter="strong">Strong (&gt;0.5)</div>
178
+ <div class="tab" data-filter="atrisk">At Risk (&lt;0.1)</div>
179
+ <div class="tab" data-filter="pinned">Pinned</div>
180
+ <div class="tab" data-filter="errors">Errors</div>
181
+ </div>
182
+ <table>
183
+ <thead><tr><th></th><th>Content</th><th>Tags</th><th>Strength</th><th>Half-life</th><th>Retrievals</th><th>Age</th></tr></thead>
184
+ <tbody id="memory-table"></tbody>
185
+ </table>
186
+ </div>
187
+
188
+ <div class="footer">Hippo Memory — biologically-inspired memory for AI agents</div>
189
+
190
+ <script>
191
+ const DATA = ${JSON.stringify(data)};
192
+
193
+ function strengthColor(s) {
194
+ if (s >= 0.5) return 'var(--green)';
195
+ if (s >= 0.1) return 'var(--yellow)';
196
+ return 'var(--red)';
197
+ }
198
+ function strengthClass(s) {
199
+ if (s >= 0.5) return 'strength-high';
200
+ if (s >= 0.1) return 'strength-mid';
201
+ return 'strength-low';
202
+ }
203
+
204
+ // Stats grid
205
+ const statsGrid = document.getElementById('stats-grid');
206
+ const stats = DATA.stats;
207
+ const cards = [
208
+ { label: 'Total Memories', value: stats.total, sub: stats.pinned + ' pinned' },
209
+ { label: 'Avg Strength', value: stats.avg_strength.toFixed(2), sub: stats.at_risk + ' at risk' },
210
+ { label: 'Avg Half-life', value: stats.avg_half_life.toFixed(1) + 'd', sub: 'default: ' + DATA.config.defaultHalfLifeDays + 'd' },
211
+ { label: 'Error Memories', value: stats.errors, sub: Math.round(stats.errors / Math.max(1, stats.total) * 100) + '% of total' },
212
+ { label: 'Embedding Coverage', value: Math.round(stats.embedding_coverage * 100) + '%', sub: DATA.config.embeddingsEnabled === 'auto' ? 'auto mode' : String(DATA.config.embeddingsEnabled) },
213
+ { label: 'Open Conflicts', value: stats.open_conflicts, sub: stats.open_conflicts > 0 ? 'needs resolution' : 'all clear' },
214
+ ];
215
+ statsGrid.innerHTML = cards.map(c => '<div class="card"><div class="label">' + c.label + '</div><div class="value">' + c.value + '</div><div class="sub">' + c.sub + '</div></div>').join('');
216
+
217
+ // Strength chart
218
+ const chart = document.getElementById('strength-chart');
219
+ const sorted = [...DATA.memories].sort((a, b) => a.strength - b.strength);
220
+ if (sorted.length > 0) {
221
+ const maxBars = Math.min(sorted.length, 100);
222
+ const step = Math.max(1, Math.floor(sorted.length / maxBars));
223
+ const sampled = [];
224
+ for (let i = 0; i < sorted.length; i += step) sampled.push(sorted[i]);
225
+ chart.innerHTML = sampled.map(m => {
226
+ const h = Math.max(2, Math.round(m.strength * 100));
227
+ return '<div class="bar ' + strengthClass(m.strength) + '" style="height:' + h + '%"><div class="tooltip">' + m.id + ': ' + m.strength.toFixed(2) + '</div></div>';
228
+ }).join('');
229
+ }
230
+
231
+ // Conflicts
232
+ if (DATA.conflicts.length > 0) {
233
+ document.getElementById('conflicts-section').style.display = '';
234
+ document.getElementById('conflicts-list').innerHTML = DATA.conflicts.map(c =>
235
+ '<div class="conflict-card"><strong>conflict_' + c.id + '</strong> (score: ' + c.score.toFixed(2) + ')<br>' +
236
+ '<code>' + c.memory_a_id + '</code> vs <code>' + c.memory_b_id + '</code><br>' +
237
+ '<span class="reason">' + c.reason + '</span></div>'
238
+ ).join('');
239
+ }
240
+
241
+ // Peers
242
+ if (DATA.peers.length > 0) {
243
+ document.getElementById('peers-section').style.display = '';
244
+ document.getElementById('peers-list').innerHTML = '<div class="card"><table><thead><tr><th>Project</th><th>Memories</th><th>Latest</th></tr></thead><tbody>' +
245
+ DATA.peers.map(p => '<tr><td>' + p.project + '</td><td>' + p.count + '</td><td>' + p.latest.slice(0, 10) + '</td></tr>').join('') +
246
+ '</tbody></table></div>';
247
+ }
248
+
249
+ // Memory table
250
+ function renderTable(filter, search) {
251
+ const tbody = document.getElementById('memory-table');
252
+ let mems = DATA.memories;
253
+ if (filter === 'strong') mems = mems.filter(m => m.strength >= 0.5);
254
+ else if (filter === 'atrisk') mems = mems.filter(m => m.strength < 0.1 && !m.pinned);
255
+ else if (filter === 'pinned') mems = mems.filter(m => m.pinned);
256
+ else if (filter === 'errors') mems = mems.filter(m => m.tags.includes('error'));
257
+ if (search) {
258
+ const q = search.toLowerCase();
259
+ mems = mems.filter(m => m.content.toLowerCase().includes(q) || m.tags.some(t => t.includes(q)));
260
+ }
261
+ mems.sort((a, b) => b.strength - a.strength);
262
+ tbody.innerHTML = mems.slice(0, 200).map(m => {
263
+ const dot = '<span class="strength-dot" style="background:' + strengthColor(m.strength) + '"></span>';
264
+ const pills = [];
265
+ if (m.pinned) pills.push('<span class="pill pill-pinned">pinned</span>');
266
+ if (m.confidence === 'stale') pills.push('<span class="pill pill-stale">stale</span>');
267
+ const tags = m.tags.map(t => '<span class="tag' + (t === 'error' ? ' tag-error' : '') + '">' + t + '</span>').join(' ');
268
+ return '<tr><td>' + dot + pills.join(' ') + '</td>' +
269
+ '<td class="content-preview" title="' + m.content.replace(/"/g, '&quot;') + '">' + m.content.slice(0, 80) + (m.content.length > 80 ? '...' : '') + '</td>' +
270
+ '<td>' + tags + '</td>' +
271
+ '<td>' + m.strength.toFixed(2) + '</td>' +
272
+ '<td>' + m.half_life_days + 'd</td>' +
273
+ '<td>' + m.retrieval_count + '</td>' +
274
+ '<td>' + m.age_days + 'd</td></tr>';
275
+ }).join('');
276
+ }
277
+
278
+ let activeFilter = 'all';
279
+ document.getElementById('tabs').addEventListener('click', e => {
280
+ const tab = e.target.closest('.tab');
281
+ if (!tab) return;
282
+ document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
283
+ tab.classList.add('active');
284
+ activeFilter = tab.dataset.filter;
285
+ renderTable(activeFilter, document.getElementById('search').value);
286
+ });
287
+ document.getElementById('search').addEventListener('input', e => {
288
+ renderTable(activeFilter, e.target.value);
289
+ });
290
+ renderTable('all', '');
291
+ </script>
292
+ </body>
293
+ </html>`;
294
+ }
295
+ export function serveDashboard(hippoRoot, port = 3333) {
296
+ const server = http.createServer((_req, res) => {
297
+ const data = buildDashboardData(hippoRoot);
298
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
299
+ res.end(dashboardHTML(data));
300
+ });
301
+ server.listen(port, '127.0.0.1', () => {
302
+ console.log(`Hippo Dashboard running at http://localhost:${port}`);
303
+ console.log('Press Ctrl+C to stop.');
304
+ });
305
+ }
306
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"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"}
package/dist/db.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAMA,UAAU,iBAAiB;IACzB,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG;QAAE,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnF,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACnC,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACxC,KAAK,IAAI,IAAI,CAAC;CACf;AA8HD,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAgB/D;AAkCD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,gBAAgB,GAAG,MAAM,CAI7D;AAoDD,wBAAgB,YAAY,CAAC,EAAE,EAAE,gBAAgB,GAAG,IAAI,CAEvD;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,MAAM,CAGhF;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAE9E;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAE5D;AAED,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,gBAAgB,EAAE,IAAI,SAAK,GAAG,IAAI,CAS5E"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAMA,UAAU,iBAAiB;IACzB,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG;QAAE,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnF,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACnC,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACxC,KAAK,IAAI,IAAI,CAAC;CACf;AA2KD,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAmB/D;AAkCD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,gBAAgB,GAAG,MAAM,CAI7D;AAoDD,wBAAgB,YAAY,CAAC,EAAE,EAAE,gBAAgB,GAAG,IAAI,CAEvD;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,MAAM,CAGhF;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAE9E;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAE5D;AAED,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,gBAAgB,EAAE,IAAI,SAAK,GAAG,IAAI,CAS5E"}
package/dist/db.js CHANGED
@@ -3,83 +3,83 @@ import * as path from 'path';
3
3
  import { createRequire } from 'module';
4
4
  const require = createRequire(import.meta.url);
5
5
  const { DatabaseSync } = require('node:sqlite');
6
- const CURRENT_SCHEMA_VERSION = 4;
6
+ const CURRENT_SCHEMA_VERSION = 6;
7
7
  const MIGRATIONS = [
8
8
  {
9
9
  version: 1,
10
10
  up: (db) => {
11
- db.exec(`
12
- CREATE TABLE IF NOT EXISTS memories (
13
- id TEXT PRIMARY KEY,
14
- created TEXT NOT NULL,
15
- last_retrieved TEXT NOT NULL,
16
- retrieval_count INTEGER NOT NULL,
17
- strength REAL NOT NULL,
18
- half_life_days REAL NOT NULL,
19
- layer TEXT NOT NULL,
20
- tags_json TEXT NOT NULL,
21
- emotional_valence TEXT NOT NULL,
22
- schema_fit REAL NOT NULL,
23
- source TEXT NOT NULL,
24
- outcome_score REAL,
25
- conflicts_with_json TEXT NOT NULL,
26
- pinned INTEGER NOT NULL,
27
- confidence TEXT NOT NULL,
28
- content TEXT NOT NULL,
29
- updated_at TEXT NOT NULL DEFAULT (datetime('now'))
30
- );
31
-
32
- CREATE INDEX IF NOT EXISTS idx_memories_layer_created ON memories(layer, created);
33
- CREATE INDEX IF NOT EXISTS idx_memories_last_retrieved ON memories(last_retrieved);
34
-
35
- CREATE TABLE IF NOT EXISTS consolidation_runs (
36
- id INTEGER PRIMARY KEY AUTOINCREMENT,
37
- timestamp TEXT NOT NULL,
38
- decayed INTEGER NOT NULL,
39
- merged INTEGER NOT NULL,
40
- removed INTEGER NOT NULL
41
- );
11
+ db.exec(`
12
+ CREATE TABLE IF NOT EXISTS memories (
13
+ id TEXT PRIMARY KEY,
14
+ created TEXT NOT NULL,
15
+ last_retrieved TEXT NOT NULL,
16
+ retrieval_count INTEGER NOT NULL,
17
+ strength REAL NOT NULL,
18
+ half_life_days REAL NOT NULL,
19
+ layer TEXT NOT NULL,
20
+ tags_json TEXT NOT NULL,
21
+ emotional_valence TEXT NOT NULL,
22
+ schema_fit REAL NOT NULL,
23
+ source TEXT NOT NULL,
24
+ outcome_score REAL,
25
+ conflicts_with_json TEXT NOT NULL,
26
+ pinned INTEGER NOT NULL,
27
+ confidence TEXT NOT NULL,
28
+ content TEXT NOT NULL,
29
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
30
+ );
31
+
32
+ CREATE INDEX IF NOT EXISTS idx_memories_layer_created ON memories(layer, created);
33
+ CREATE INDEX IF NOT EXISTS idx_memories_last_retrieved ON memories(last_retrieved);
34
+
35
+ CREATE TABLE IF NOT EXISTS consolidation_runs (
36
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
37
+ timestamp TEXT NOT NULL,
38
+ decayed INTEGER NOT NULL,
39
+ merged INTEGER NOT NULL,
40
+ removed INTEGER NOT NULL
41
+ );
42
42
  `);
43
43
  },
44
44
  },
45
45
  {
46
46
  version: 2,
47
47
  up: (db) => {
48
- db.exec(`
49
- CREATE TABLE IF NOT EXISTS task_snapshots (
50
- id INTEGER PRIMARY KEY AUTOINCREMENT,
51
- task TEXT NOT NULL,
52
- summary TEXT NOT NULL,
53
- next_step TEXT NOT NULL,
54
- status TEXT NOT NULL,
55
- source TEXT NOT NULL,
56
- created_at TEXT NOT NULL,
57
- updated_at TEXT NOT NULL
58
- );
59
-
60
- CREATE INDEX IF NOT EXISTS idx_task_snapshots_status_updated
61
- ON task_snapshots(status, updated_at DESC, id DESC);
48
+ db.exec(`
49
+ CREATE TABLE IF NOT EXISTS task_snapshots (
50
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
51
+ task TEXT NOT NULL,
52
+ summary TEXT NOT NULL,
53
+ next_step TEXT NOT NULL,
54
+ status TEXT NOT NULL,
55
+ source TEXT NOT NULL,
56
+ created_at TEXT NOT NULL,
57
+ updated_at TEXT NOT NULL
58
+ );
59
+
60
+ CREATE INDEX IF NOT EXISTS idx_task_snapshots_status_updated
61
+ ON task_snapshots(status, updated_at DESC, id DESC);
62
62
  `);
63
63
  },
64
64
  },
65
65
  {
66
66
  version: 3,
67
67
  up: (db) => {
68
- db.exec(`
69
- CREATE TABLE IF NOT EXISTS memory_conflicts (
70
- id INTEGER PRIMARY KEY AUTOINCREMENT,
71
- memory_a_id TEXT NOT NULL,
72
- memory_b_id TEXT NOT NULL,
73
- reason TEXT NOT NULL,
74
- score REAL NOT NULL DEFAULT 0,
75
- status TEXT NOT NULL,
76
- detected_at TEXT NOT NULL,
77
- updated_at TEXT NOT NULL,
78
- UNIQUE(memory_a_id, memory_b_id)
79
- );
80
-
81
- CREATE INDEX IF NOT EXISTS idx_memory_conflicts_status_updated
82
- ON memory_conflicts(status, updated_at DESC, id DESC);
68
+ db.exec(`
69
+ CREATE TABLE IF NOT EXISTS memory_conflicts (
70
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
71
+ memory_a_id TEXT NOT NULL,
72
+ memory_b_id TEXT NOT NULL,
73
+ reason TEXT NOT NULL,
74
+ score REAL NOT NULL DEFAULT 0,
75
+ status TEXT NOT NULL,
76
+ detected_at TEXT NOT NULL,
77
+ updated_at TEXT NOT NULL,
78
+ UNIQUE(memory_a_id, memory_b_id)
79
+ );
80
+
81
+ CREATE INDEX IF NOT EXISTS idx_memory_conflicts_status_updated
82
+ ON memory_conflicts(status, updated_at DESC, id DESC);
83
83
  `);
84
84
  },
85
85
  },
@@ -89,28 +89,74 @@ const MIGRATIONS = [
89
89
  if (!tableHasColumn(db, 'task_snapshots', 'session_id')) {
90
90
  db.exec(`ALTER TABLE task_snapshots ADD COLUMN session_id TEXT`);
91
91
  }
92
- db.exec(`
93
- CREATE TABLE IF NOT EXISTS session_events (
94
- id INTEGER PRIMARY KEY AUTOINCREMENT,
95
- session_id TEXT NOT NULL,
96
- task TEXT,
97
- event_type TEXT NOT NULL,
98
- content TEXT NOT NULL,
99
- source TEXT NOT NULL,
100
- metadata_json TEXT NOT NULL,
101
- created_at TEXT NOT NULL
102
- );
103
-
104
- CREATE INDEX IF NOT EXISTS idx_session_events_session_created
105
- ON session_events(session_id, created_at DESC, id DESC);
106
-
107
- CREATE INDEX IF NOT EXISTS idx_session_events_task_created
108
- ON session_events(task, created_at DESC, id DESC);
92
+ db.exec(`
93
+ CREATE TABLE IF NOT EXISTS session_events (
94
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
95
+ session_id TEXT NOT NULL,
96
+ task TEXT,
97
+ event_type TEXT NOT NULL,
98
+ content TEXT NOT NULL,
99
+ source TEXT NOT NULL,
100
+ metadata_json TEXT NOT NULL,
101
+ created_at TEXT NOT NULL
102
+ );
103
+
104
+ CREATE INDEX IF NOT EXISTS idx_session_events_session_created
105
+ ON session_events(session_id, created_at DESC, id DESC);
106
+
107
+ CREATE INDEX IF NOT EXISTS idx_session_events_task_created
108
+ ON session_events(task, created_at DESC, id DESC);
109
+ `);
110
+ },
111
+ },
112
+ {
113
+ version: 5,
114
+ up: (db) => {
115
+ db.exec(`
116
+ CREATE TABLE IF NOT EXISTS session_handoffs (
117
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
118
+ session_id TEXT NOT NULL,
119
+ repo_root TEXT,
120
+ task_id TEXT,
121
+ summary TEXT NOT NULL,
122
+ next_action TEXT,
123
+ artifacts_json TEXT NOT NULL DEFAULT '[]',
124
+ created_at TEXT NOT NULL
125
+ );
126
+
127
+ CREATE INDEX IF NOT EXISTS idx_session_handoffs_session
128
+ ON session_handoffs(session_id, created_at DESC);
129
+ `);
130
+ },
131
+ },
132
+ {
133
+ version: 6,
134
+ up: (db) => {
135
+ db.exec(`
136
+ CREATE TABLE IF NOT EXISTS working_memory (
137
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
138
+ scope TEXT NOT NULL,
139
+ session_id TEXT,
140
+ task_id TEXT,
141
+ importance REAL NOT NULL DEFAULT 0,
142
+ content TEXT NOT NULL,
143
+ metadata_json TEXT NOT NULL DEFAULT '{}',
144
+ created_at TEXT NOT NULL,
145
+ updated_at TEXT NOT NULL
146
+ );
147
+
148
+ CREATE INDEX IF NOT EXISTS idx_working_memory_scope
149
+ ON working_memory(scope, importance DESC, created_at DESC);
150
+
151
+ CREATE INDEX IF NOT EXISTS idx_working_memory_session
152
+ ON working_memory(session_id, created_at DESC);
109
153
  `);
110
154
  },
111
155
  },
112
156
  ];
113
157
  function tableHasColumn(db, tableName, columnName) {
158
+ if (!/^[a-z_]+$/i.test(tableName))
159
+ throw new Error(`Invalid table name: ${tableName}`);
114
160
  const rows = db.prepare(`PRAGMA table_info(${tableName})`).all();
115
161
  return rows.some((row) => row.name === columnName);
116
162
  }
@@ -125,6 +171,9 @@ export function openHippoDb(hippoRoot) {
125
171
  const db = new DatabaseSync(getHippoDbPath(hippoRoot));
126
172
  try {
127
173
  db.exec('PRAGMA journal_mode = WAL');
174
+ db.exec('PRAGMA busy_timeout = 5000');
175
+ db.exec('PRAGMA synchronous = NORMAL');
176
+ db.exec('PRAGMA wal_autocheckpoint = 100');
128
177
  db.exec('PRAGMA foreign_keys = ON');
129
178
  runMigrations(db);
130
179
  return db;
@@ -161,11 +210,11 @@ function runMigrations(db) {
161
210
  ensureOptionalFts(db);
162
211
  }
163
212
  function ensureMetaTable(db) {
164
- db.exec(`
165
- CREATE TABLE IF NOT EXISTS meta (
166
- key TEXT PRIMARY KEY,
167
- value TEXT NOT NULL
168
- );
213
+ db.exec(`
214
+ CREATE TABLE IF NOT EXISTS meta (
215
+ key TEXT PRIMARY KEY,
216
+ value TEXT NOT NULL
217
+ );
169
218
  `);
170
219
  }
171
220
  export function getSchemaVersion(db) {
@@ -204,17 +253,17 @@ function ensureOptionalFts(db) {
204
253
  db.prepare(`INSERT INTO meta(key, value) VALUES('fts5_available', ?) ON CONFLICT(key) DO UPDATE SET value=excluded.value`).run(available ? '1' : '0');
205
254
  }
206
255
  function backfillFtsIndex(db) {
207
- db.exec(`
208
- INSERT INTO memories_fts(id, content, tags)
209
- SELECT m.id, m.content, m.tags_json
210
- FROM memories m
211
- WHERE NOT EXISTS (
212
- SELECT 1 FROM memories_fts f WHERE f.id = m.id
213
- )
256
+ db.exec(`
257
+ INSERT INTO memories_fts(id, content, tags)
258
+ SELECT m.id, m.content, m.tags_json
259
+ FROM memories m
260
+ WHERE NOT EXISTS (
261
+ SELECT 1 FROM memories_fts f WHERE f.id = m.id
262
+ )
214
263
  `);
215
- db.exec(`
216
- DELETE FROM memories_fts
217
- WHERE id NOT IN (SELECT id FROM memories)
264
+ db.exec(`
265
+ DELETE FROM memories_fts
266
+ WHERE id NOT IN (SELECT id FROM memories)
218
267
  `);
219
268
  }
220
269
  export function closeHippoDb(db) {
@@ -231,13 +280,13 @@ export function isFtsAvailable(db) {
231
280
  return getMeta(db, 'fts5_available', '0') === '1';
232
281
  }
233
282
  export function pruneConsolidationRuns(db, keep = 50) {
234
- db.prepare(`
235
- DELETE FROM consolidation_runs
236
- WHERE id NOT IN (
237
- SELECT id FROM consolidation_runs
238
- ORDER BY timestamp DESC, id DESC
239
- LIMIT ?
240
- )
283
+ db.prepare(`
284
+ DELETE FROM consolidation_runs
285
+ WHERE id NOT IN (
286
+ SELECT id FROM consolidation_runs
287
+ ORDER BY timestamp DESC, id DESC
288
+ LIMIT ?
289
+ )
241
290
  `).run(keep);
242
291
  }
243
292
  //# sourceMappingURL=db.js.map
package/dist/db.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}