hippo-memory 0.35.0 → 0.37.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 (215) hide show
  1. package/README.md +25 -0
  2. package/dist/api.d.ts +183 -0
  3. package/dist/api.d.ts.map +1 -0
  4. package/dist/api.js +343 -0
  5. package/dist/api.js.map +1 -0
  6. package/dist/benchmarks/e1.3/incident-recall-eval.js +74 -0
  7. package/dist/benchmarks/e1.3/incident-recall-eval.js.map +1 -0
  8. package/dist/benchmarks/e1.3/scenarios.json +2587 -0
  9. package/dist/benchmarks/e1.3/slack-1000-event-smoke.js +102 -0
  10. package/dist/benchmarks/e1.3/slack-1000-event-smoke.js.map +1 -0
  11. package/dist/cli.js +222 -34
  12. package/dist/cli.js.map +1 -1
  13. package/dist/client.d.ts +54 -0
  14. package/dist/client.d.ts.map +1 -0
  15. package/dist/client.js +181 -0
  16. package/dist/client.js.map +1 -0
  17. package/dist/connectors/slack/backfill.d.ts +42 -0
  18. package/dist/connectors/slack/backfill.d.ts.map +1 -0
  19. package/dist/connectors/slack/backfill.js +76 -0
  20. package/dist/connectors/slack/backfill.js.map +1 -0
  21. package/dist/connectors/slack/deletion.d.ts +14 -0
  22. package/dist/connectors/slack/deletion.d.ts.map +1 -0
  23. package/dist/connectors/slack/deletion.js +46 -0
  24. package/dist/connectors/slack/deletion.js.map +1 -0
  25. package/dist/connectors/slack/dlq.d.ts +21 -0
  26. package/dist/connectors/slack/dlq.d.ts.map +1 -0
  27. package/dist/connectors/slack/dlq.js +23 -0
  28. package/dist/connectors/slack/dlq.js.map +1 -0
  29. package/dist/connectors/slack/idempotency.d.ts +5 -0
  30. package/dist/connectors/slack/idempotency.d.ts.map +1 -0
  31. package/dist/connectors/slack/idempotency.js +13 -0
  32. package/dist/connectors/slack/idempotency.js.map +1 -0
  33. package/dist/connectors/slack/ingest.d.ts +27 -0
  34. package/dist/connectors/slack/ingest.d.ts.map +1 -0
  35. package/dist/connectors/slack/ingest.js +48 -0
  36. package/dist/connectors/slack/ingest.js.map +1 -0
  37. package/dist/connectors/slack/ratelimit.d.ts +9 -0
  38. package/dist/connectors/slack/ratelimit.d.ts.map +1 -0
  39. package/dist/connectors/slack/ratelimit.js +18 -0
  40. package/dist/connectors/slack/ratelimit.js.map +1 -0
  41. package/dist/connectors/slack/scope.d.ts +16 -0
  42. package/dist/connectors/slack/scope.d.ts.map +1 -0
  43. package/dist/connectors/slack/scope.js +13 -0
  44. package/dist/connectors/slack/scope.js.map +1 -0
  45. package/dist/connectors/slack/signature.d.ts +12 -0
  46. package/dist/connectors/slack/signature.d.ts.map +1 -0
  47. package/dist/connectors/slack/signature.js +20 -0
  48. package/dist/connectors/slack/signature.js.map +1 -0
  49. package/dist/connectors/slack/tenant-routing.d.ts +13 -0
  50. package/dist/connectors/slack/tenant-routing.d.ts.map +1 -0
  51. package/dist/connectors/slack/tenant-routing.js +17 -0
  52. package/dist/connectors/slack/tenant-routing.js.map +1 -0
  53. package/dist/connectors/slack/transform.d.ts +20 -0
  54. package/dist/connectors/slack/transform.d.ts.map +1 -0
  55. package/dist/connectors/slack/transform.js +31 -0
  56. package/dist/connectors/slack/transform.js.map +1 -0
  57. package/dist/connectors/slack/types.d.ts +35 -0
  58. package/dist/connectors/slack/types.d.ts.map +1 -0
  59. package/dist/connectors/slack/types.js +23 -0
  60. package/dist/connectors/slack/types.js.map +1 -0
  61. package/dist/connectors/slack/web-client.d.ts +12 -0
  62. package/dist/connectors/slack/web-client.d.ts.map +1 -0
  63. package/dist/connectors/slack/web-client.js +43 -0
  64. package/dist/connectors/slack/web-client.js.map +1 -0
  65. package/dist/db.d.ts.map +1 -1
  66. package/dist/db.js +46 -1
  67. package/dist/db.js.map +1 -1
  68. package/dist/importers.js +3 -3
  69. package/dist/importers.js.map +1 -1
  70. package/dist/mcp/server.d.ts +46 -1
  71. package/dist/mcp/server.d.ts.map +1 -1
  72. package/dist/mcp/server.js +74 -26
  73. package/dist/mcp/server.js.map +1 -1
  74. package/dist/server-detect.d.ts +26 -0
  75. package/dist/server-detect.d.ts.map +1 -0
  76. package/dist/server-detect.js +70 -0
  77. package/dist/server-detect.js.map +1 -0
  78. package/dist/server.d.ts +29 -0
  79. package/dist/server.d.ts.map +1 -0
  80. package/dist/server.js +784 -0
  81. package/dist/server.js.map +1 -0
  82. package/dist/shared.d.ts +3 -1
  83. package/dist/shared.d.ts.map +1 -1
  84. package/dist/shared.js +2 -2
  85. package/dist/shared.js.map +1 -1
  86. package/dist/src/ambient.js +147 -0
  87. package/dist/src/ambient.js.map +1 -0
  88. package/dist/src/api.js +343 -0
  89. package/dist/src/api.js.map +1 -0
  90. package/dist/src/audit.js +152 -0
  91. package/dist/src/audit.js.map +1 -0
  92. package/dist/src/auth.js +65 -0
  93. package/dist/src/auth.js.map +1 -0
  94. package/dist/src/autolearn.js +143 -0
  95. package/dist/src/autolearn.js.map +1 -0
  96. package/dist/src/capture.js +512 -0
  97. package/dist/src/capture.js.map +1 -0
  98. package/dist/src/cli.js +4971 -0
  99. package/dist/src/cli.js.map +1 -0
  100. package/dist/src/client.js +181 -0
  101. package/dist/src/client.js.map +1 -0
  102. package/dist/src/config.js +108 -0
  103. package/dist/src/config.js.map +1 -0
  104. package/dist/src/connectors/slack/backfill.js +76 -0
  105. package/dist/src/connectors/slack/backfill.js.map +1 -0
  106. package/dist/src/connectors/slack/deletion.js +46 -0
  107. package/dist/src/connectors/slack/deletion.js.map +1 -0
  108. package/dist/src/connectors/slack/dlq.js +23 -0
  109. package/dist/src/connectors/slack/dlq.js.map +1 -0
  110. package/dist/src/connectors/slack/idempotency.js +13 -0
  111. package/dist/src/connectors/slack/idempotency.js.map +1 -0
  112. package/dist/src/connectors/slack/ingest.js +48 -0
  113. package/dist/src/connectors/slack/ingest.js.map +1 -0
  114. package/dist/src/connectors/slack/ratelimit.js +18 -0
  115. package/dist/src/connectors/slack/ratelimit.js.map +1 -0
  116. package/dist/src/connectors/slack/scope.js +13 -0
  117. package/dist/src/connectors/slack/scope.js.map +1 -0
  118. package/dist/src/connectors/slack/signature.js +20 -0
  119. package/dist/src/connectors/slack/signature.js.map +1 -0
  120. package/dist/src/connectors/slack/tenant-routing.js +17 -0
  121. package/dist/src/connectors/slack/tenant-routing.js.map +1 -0
  122. package/dist/src/connectors/slack/transform.js +31 -0
  123. package/dist/src/connectors/slack/transform.js.map +1 -0
  124. package/dist/src/connectors/slack/types.js +23 -0
  125. package/dist/src/connectors/slack/types.js.map +1 -0
  126. package/dist/src/connectors/slack/web-client.js +43 -0
  127. package/dist/src/connectors/slack/web-client.js.map +1 -0
  128. package/dist/src/consolidate.js +517 -0
  129. package/dist/src/consolidate.js.map +1 -0
  130. package/dist/src/dag.js +104 -0
  131. package/dist/src/dag.js.map +1 -0
  132. package/dist/src/dashboard.js +409 -0
  133. package/dist/src/dashboard.js.map +1 -0
  134. package/dist/src/db.js +584 -0
  135. package/dist/src/db.js.map +1 -0
  136. package/dist/src/embeddings.js +344 -0
  137. package/dist/src/embeddings.js.map +1 -0
  138. package/dist/src/eval-suite.js +289 -0
  139. package/dist/src/eval-suite.js.map +1 -0
  140. package/dist/src/eval.js +187 -0
  141. package/dist/src/eval.js.map +1 -0
  142. package/dist/src/extract.js +87 -0
  143. package/dist/src/extract.js.map +1 -0
  144. package/dist/src/handoff.js +30 -0
  145. package/dist/src/handoff.js.map +1 -0
  146. package/dist/src/hooks.js +582 -0
  147. package/dist/src/hooks.js.map +1 -0
  148. package/dist/src/importers.js +399 -0
  149. package/dist/src/importers.js.map +1 -0
  150. package/dist/src/index.js +25 -0
  151. package/dist/src/index.js.map +1 -0
  152. package/dist/src/invalidation.js +94 -0
  153. package/dist/src/invalidation.js.map +1 -0
  154. package/dist/src/mcp/framing.js +45 -0
  155. package/dist/src/mcp/framing.js.map +1 -0
  156. package/dist/src/mcp/server.js +510 -0
  157. package/dist/src/mcp/server.js.map +1 -0
  158. package/dist/src/memory.js +280 -0
  159. package/dist/src/memory.js.map +1 -0
  160. package/dist/src/multihop.js +32 -0
  161. package/dist/src/multihop.js.map +1 -0
  162. package/dist/src/path-context.js +32 -0
  163. package/dist/src/path-context.js.map +1 -0
  164. package/dist/src/physics-config.js +26 -0
  165. package/dist/src/physics-config.js.map +1 -0
  166. package/dist/src/physics-state.js +163 -0
  167. package/dist/src/physics-state.js.map +1 -0
  168. package/dist/src/physics.js +361 -0
  169. package/dist/src/physics.js.map +1 -0
  170. package/dist/src/postinstall.js +68 -0
  171. package/dist/src/postinstall.js.map +1 -0
  172. package/dist/src/raw-archive.js +72 -0
  173. package/dist/src/raw-archive.js.map +1 -0
  174. package/dist/src/refine-llm.js +147 -0
  175. package/dist/src/refine-llm.js.map +1 -0
  176. package/dist/src/replay.js +117 -0
  177. package/dist/src/replay.js.map +1 -0
  178. package/dist/src/salience.js +74 -0
  179. package/dist/src/salience.js.map +1 -0
  180. package/dist/src/scheduler.js +67 -0
  181. package/dist/src/scheduler.js.map +1 -0
  182. package/dist/src/scope.js +35 -0
  183. package/dist/src/scope.js.map +1 -0
  184. package/dist/src/search.js +801 -0
  185. package/dist/src/search.js.map +1 -0
  186. package/dist/src/server-detect.js +70 -0
  187. package/dist/src/server-detect.js.map +1 -0
  188. package/dist/src/server.js +784 -0
  189. package/dist/src/server.js.map +1 -0
  190. package/dist/src/shared.js +309 -0
  191. package/dist/src/shared.js.map +1 -0
  192. package/dist/src/sso.js +22 -0
  193. package/dist/src/sso.js.map +1 -0
  194. package/dist/src/store.js +1390 -0
  195. package/dist/src/store.js.map +1 -0
  196. package/dist/src/tenant.js +17 -0
  197. package/dist/src/tenant.js.map +1 -0
  198. package/dist/src/trace.js +64 -0
  199. package/dist/src/trace.js.map +1 -0
  200. package/dist/src/working-memory.js +149 -0
  201. package/dist/src/working-memory.js.map +1 -0
  202. package/dist/src/yaml.js +98 -0
  203. package/dist/src/yaml.js.map +1 -0
  204. package/dist/store.d.ts +25 -4
  205. package/dist/store.d.ts.map +1 -1
  206. package/dist/store.js +50 -11
  207. package/dist/store.js.map +1 -1
  208. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  209. package/extensions/openclaw-plugin/package.json +1 -1
  210. package/openclaw.plugin.json +1 -1
  211. package/package.json +2 -2
  212. package/dist/import.d.ts +0 -31
  213. package/dist/import.d.ts.map +0 -1
  214. package/dist/import.js +0 -307
  215. package/dist/import.js.map +0 -1
package/dist/src/db.js ADDED
@@ -0,0 +1,584 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { createRequire } from 'module';
4
+ import { createPhysicsTable } from './physics-state.js';
5
+ const require = createRequire(import.meta.url);
6
+ const { DatabaseSync } = require('node:sqlite');
7
+ const CURRENT_SCHEMA_VERSION = 17;
8
+ const MIGRATIONS = [
9
+ {
10
+ version: 1,
11
+ up: (db) => {
12
+ db.exec(`
13
+ CREATE TABLE IF NOT EXISTS memories (
14
+ id TEXT PRIMARY KEY,
15
+ created TEXT NOT NULL,
16
+ last_retrieved TEXT NOT NULL,
17
+ retrieval_count INTEGER NOT NULL,
18
+ strength REAL NOT NULL,
19
+ half_life_days REAL NOT NULL,
20
+ layer TEXT NOT NULL,
21
+ tags_json TEXT NOT NULL,
22
+ emotional_valence TEXT NOT NULL,
23
+ schema_fit REAL NOT NULL,
24
+ source TEXT NOT NULL,
25
+ outcome_score REAL,
26
+ conflicts_with_json TEXT NOT NULL,
27
+ pinned INTEGER NOT NULL,
28
+ confidence TEXT NOT NULL,
29
+ content TEXT NOT NULL,
30
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
31
+ );
32
+
33
+ CREATE INDEX IF NOT EXISTS idx_memories_layer_created ON memories(layer, created);
34
+ CREATE INDEX IF NOT EXISTS idx_memories_last_retrieved ON memories(last_retrieved);
35
+
36
+ CREATE TABLE IF NOT EXISTS consolidation_runs (
37
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
38
+ timestamp TEXT NOT NULL,
39
+ decayed INTEGER NOT NULL,
40
+ merged INTEGER NOT NULL,
41
+ removed INTEGER NOT NULL
42
+ );
43
+ `);
44
+ },
45
+ },
46
+ {
47
+ version: 2,
48
+ up: (db) => {
49
+ db.exec(`
50
+ CREATE TABLE IF NOT EXISTS task_snapshots (
51
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
52
+ task TEXT NOT NULL,
53
+ summary TEXT NOT NULL,
54
+ next_step TEXT NOT NULL,
55
+ status TEXT NOT NULL,
56
+ source TEXT NOT NULL,
57
+ created_at TEXT NOT NULL,
58
+ updated_at TEXT NOT NULL
59
+ );
60
+
61
+ CREATE INDEX IF NOT EXISTS idx_task_snapshots_status_updated
62
+ ON task_snapshots(status, updated_at DESC, id DESC);
63
+ `);
64
+ },
65
+ },
66
+ {
67
+ version: 3,
68
+ up: (db) => {
69
+ db.exec(`
70
+ CREATE TABLE IF NOT EXISTS memory_conflicts (
71
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
72
+ memory_a_id TEXT NOT NULL,
73
+ memory_b_id TEXT NOT NULL,
74
+ reason TEXT NOT NULL,
75
+ score REAL NOT NULL DEFAULT 0,
76
+ status TEXT NOT NULL,
77
+ detected_at TEXT NOT NULL,
78
+ updated_at TEXT NOT NULL,
79
+ UNIQUE(memory_a_id, memory_b_id)
80
+ );
81
+
82
+ CREATE INDEX IF NOT EXISTS idx_memory_conflicts_status_updated
83
+ ON memory_conflicts(status, updated_at DESC, id DESC);
84
+ `);
85
+ },
86
+ },
87
+ {
88
+ version: 4,
89
+ up: (db) => {
90
+ if (!tableHasColumn(db, 'task_snapshots', 'session_id')) {
91
+ db.exec(`ALTER TABLE task_snapshots ADD COLUMN session_id TEXT`);
92
+ }
93
+ db.exec(`
94
+ CREATE TABLE IF NOT EXISTS session_events (
95
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
96
+ session_id TEXT NOT NULL,
97
+ task TEXT,
98
+ event_type TEXT NOT NULL,
99
+ content TEXT NOT NULL,
100
+ source TEXT NOT NULL,
101
+ metadata_json TEXT NOT NULL,
102
+ created_at TEXT NOT NULL
103
+ );
104
+
105
+ CREATE INDEX IF NOT EXISTS idx_session_events_session_created
106
+ ON session_events(session_id, created_at DESC, id DESC);
107
+
108
+ CREATE INDEX IF NOT EXISTS idx_session_events_task_created
109
+ ON session_events(task, created_at DESC, id DESC);
110
+ `);
111
+ },
112
+ },
113
+ {
114
+ version: 5,
115
+ up: (db) => {
116
+ db.exec(`
117
+ CREATE TABLE IF NOT EXISTS session_handoffs (
118
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
119
+ session_id TEXT NOT NULL,
120
+ repo_root TEXT,
121
+ task_id TEXT,
122
+ summary TEXT NOT NULL,
123
+ next_action TEXT,
124
+ artifacts_json TEXT NOT NULL DEFAULT '[]',
125
+ created_at TEXT NOT NULL
126
+ );
127
+
128
+ CREATE INDEX IF NOT EXISTS idx_session_handoffs_session
129
+ ON session_handoffs(session_id, created_at DESC);
130
+ `);
131
+ },
132
+ },
133
+ {
134
+ version: 6,
135
+ up: (db) => {
136
+ db.exec(`
137
+ CREATE TABLE IF NOT EXISTS working_memory (
138
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
139
+ scope TEXT NOT NULL,
140
+ session_id TEXT,
141
+ task_id TEXT,
142
+ importance REAL NOT NULL DEFAULT 0,
143
+ content TEXT NOT NULL,
144
+ metadata_json TEXT NOT NULL DEFAULT '{}',
145
+ created_at TEXT NOT NULL,
146
+ updated_at TEXT NOT NULL
147
+ );
148
+
149
+ CREATE INDEX IF NOT EXISTS idx_working_memory_scope
150
+ ON working_memory(scope, importance DESC, created_at DESC);
151
+
152
+ CREATE INDEX IF NOT EXISTS idx_working_memory_session
153
+ ON working_memory(session_id, created_at DESC);
154
+ `);
155
+ },
156
+ },
157
+ {
158
+ version: 7,
159
+ up: (db) => {
160
+ if (!tableHasColumn(db, 'memories', 'outcome_positive')) {
161
+ db.exec(`ALTER TABLE memories ADD COLUMN outcome_positive INTEGER NOT NULL DEFAULT 0`);
162
+ }
163
+ if (!tableHasColumn(db, 'memories', 'outcome_negative')) {
164
+ db.exec(`ALTER TABLE memories ADD COLUMN outcome_negative INTEGER NOT NULL DEFAULT 0`);
165
+ }
166
+ },
167
+ },
168
+ {
169
+ version: 8,
170
+ up: (db) => {
171
+ createPhysicsTable(db);
172
+ },
173
+ },
174
+ {
175
+ version: 9,
176
+ up: (db) => {
177
+ if (!tableHasColumn(db, 'memories', 'parents_json')) {
178
+ db.exec(`ALTER TABLE memories ADD COLUMN parents_json TEXT NOT NULL DEFAULT '[]'`);
179
+ }
180
+ if (!tableHasColumn(db, 'memories', 'starred')) {
181
+ db.exec(`ALTER TABLE memories ADD COLUMN starred INTEGER NOT NULL DEFAULT 0`);
182
+ }
183
+ },
184
+ },
185
+ {
186
+ version: 10,
187
+ up: (db) => {
188
+ if (!tableHasColumn(db, 'memories', 'trace_outcome')) {
189
+ db.exec(`ALTER TABLE memories ADD COLUMN trace_outcome TEXT`);
190
+ }
191
+ if (!tableHasColumn(db, 'memories', 'source_session_id')) {
192
+ db.exec(`ALTER TABLE memories ADD COLUMN source_session_id TEXT`);
193
+ }
194
+ db.exec(`
195
+ CREATE INDEX IF NOT EXISTS idx_memories_source_session_id
196
+ ON memories(source_session_id) WHERE source_session_id IS NOT NULL
197
+ `);
198
+ },
199
+ },
200
+ {
201
+ version: 11,
202
+ up: (db) => {
203
+ if (!tableHasColumn(db, 'memories', 'valid_from')) {
204
+ db.exec(`ALTER TABLE memories ADD COLUMN valid_from TEXT`);
205
+ db.exec(`UPDATE memories SET valid_from = created WHERE valid_from IS NULL`);
206
+ }
207
+ if (!tableHasColumn(db, 'memories', 'superseded_by')) {
208
+ db.exec(`ALTER TABLE memories ADD COLUMN superseded_by TEXT`);
209
+ }
210
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_memories_current ON memories(layer, created) WHERE superseded_by IS NULL`);
211
+ },
212
+ },
213
+ {
214
+ version: 12,
215
+ up: (db) => {
216
+ if (!tableHasColumn(db, 'memories', 'extracted_from')) {
217
+ db.exec(`ALTER TABLE memories ADD COLUMN extracted_from TEXT`);
218
+ }
219
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_memories_extracted_from ON memories(extracted_from) WHERE extracted_from IS NOT NULL`);
220
+ },
221
+ },
222
+ {
223
+ version: 13,
224
+ up: (db) => {
225
+ if (!tableHasColumn(db, 'memories', 'dag_level')) {
226
+ db.exec(`ALTER TABLE memories ADD COLUMN dag_level INTEGER NOT NULL DEFAULT 0`);
227
+ }
228
+ if (!tableHasColumn(db, 'memories', 'dag_parent_id')) {
229
+ db.exec(`ALTER TABLE memories ADD COLUMN dag_parent_id TEXT`);
230
+ }
231
+ db.exec(`UPDATE memories SET dag_level = 1 WHERE extracted_from IS NOT NULL AND dag_level = 0`);
232
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_memories_dag_parent ON memories(dag_parent_id) WHERE dag_parent_id IS NOT NULL`);
233
+ },
234
+ },
235
+ {
236
+ version: 14,
237
+ up: (db) => {
238
+ // A3 provenance envelope: kind, scope, owner, artifact_ref.
239
+ // SQLite ALTER TABLE ADD COLUMN cannot add CHECK; CHECK enforcement lives
240
+ // in INSERT/UPDATE triggers added later in this migration.
241
+ if (!tableHasColumn(db, 'memories', 'kind')) {
242
+ db.exec(`ALTER TABLE memories ADD COLUMN kind TEXT DEFAULT 'distilled'`);
243
+ }
244
+ if (!tableHasColumn(db, 'memories', 'scope')) {
245
+ db.exec(`ALTER TABLE memories ADD COLUMN scope TEXT`);
246
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(scope) WHERE scope IS NOT NULL`);
247
+ }
248
+ if (!tableHasColumn(db, 'memories', 'owner')) {
249
+ db.exec(`ALTER TABLE memories ADD COLUMN owner TEXT`);
250
+ }
251
+ if (!tableHasColumn(db, 'memories', 'artifact_ref')) {
252
+ db.exec(`ALTER TABLE memories ADD COLUMN artifact_ref TEXT`);
253
+ }
254
+ // Backfill kind for any rows where it's NULL (pre-migration data).
255
+ db.exec(`UPDATE memories SET kind = 'superseded' WHERE kind IS NULL AND superseded_by IS NOT NULL`);
256
+ db.exec(`UPDATE memories SET kind = 'distilled' WHERE kind IS NULL`);
257
+ // raw_archive: legitimate path for kind='raw' removal (used by archiveRawMemory).
258
+ db.exec(`
259
+ CREATE TABLE IF NOT EXISTS raw_archive (
260
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
261
+ memory_id TEXT NOT NULL,
262
+ archived_at TEXT NOT NULL,
263
+ reason TEXT NOT NULL,
264
+ archived_by TEXT,
265
+ payload_json TEXT NOT NULL
266
+ )
267
+ `);
268
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_raw_archive_memory_id ON raw_archive(memory_id)`);
269
+ // Append-only invariant: kind='raw' rows cannot be deleted directly.
270
+ // Use raw_archive flow: archive-then-update-then-delete (see src/raw-archive.ts).
271
+ db.exec(`
272
+ CREATE TRIGGER IF NOT EXISTS trg_memories_raw_append_only
273
+ BEFORE DELETE ON memories
274
+ WHEN OLD.kind = 'raw'
275
+ BEGIN
276
+ SELECT RAISE(ABORT, 'raw is append-only');
277
+ END
278
+ `);
279
+ // CHECK substitute: ALTER TABLE cannot add CHECK, so enforce kind allowed-set
280
+ // via INSERT/UPDATE triggers.
281
+ db.exec(`
282
+ CREATE TRIGGER IF NOT EXISTS trg_memories_kind_check_insert
283
+ BEFORE INSERT ON memories
284
+ WHEN NEW.kind IS NOT NULL AND NEW.kind NOT IN ('raw','distilled','superseded','archived')
285
+ BEGIN
286
+ SELECT RAISE(ABORT, 'invalid kind: must be raw|distilled|superseded|archived');
287
+ END
288
+ `);
289
+ db.exec(`
290
+ CREATE TRIGGER IF NOT EXISTS trg_memories_kind_check_update
291
+ BEFORE UPDATE ON memories
292
+ WHEN NEW.kind IS NOT NULL AND NEW.kind NOT IN ('raw','distilled','superseded','archived')
293
+ BEGIN
294
+ SELECT RAISE(ABORT, 'invalid kind: must be raw|distilled|superseded|archived');
295
+ END
296
+ `);
297
+ },
298
+ },
299
+ {
300
+ version: 15,
301
+ up: (db) => {
302
+ // A3 hardening (post-review): close the NULL-kind bypass and add raw_archive
303
+ // dedup safety. Both findings landed in /review on commits 41b1f4d..6456e7d.
304
+ //
305
+ // (1) Original v14 triggers used `WHEN NEW.kind IS NOT NULL AND NEW.kind NOT IN (...)`.
306
+ // A direct INSERT/UPDATE setting kind=NULL bypassed the CHECK substitute. Replace
307
+ // with `WHEN NEW.kind IS NULL OR NEW.kind NOT IN (...)` so NULL is rejected too.
308
+ // (2) Add UNIQUE(memory_id, archived_at) to raw_archive so re-archiving the same id
309
+ // in the same instant cannot produce ambiguous audit rows. Per-id history is still
310
+ // allowed (different timestamps).
311
+ db.exec(`DROP TRIGGER IF EXISTS trg_memories_kind_check_insert`);
312
+ db.exec(`DROP TRIGGER IF EXISTS trg_memories_kind_check_update`);
313
+ db.exec(`
314
+ CREATE TRIGGER trg_memories_kind_check_insert
315
+ BEFORE INSERT ON memories
316
+ WHEN NEW.kind IS NULL OR NEW.kind NOT IN ('raw','distilled','superseded','archived')
317
+ BEGIN
318
+ SELECT RAISE(ABORT, 'invalid kind: must be raw|distilled|superseded|archived (not null)');
319
+ END
320
+ `);
321
+ db.exec(`
322
+ CREATE TRIGGER trg_memories_kind_check_update
323
+ BEFORE UPDATE ON memories
324
+ WHEN NEW.kind IS NULL OR NEW.kind NOT IN ('raw','distilled','superseded','archived')
325
+ BEGIN
326
+ SELECT RAISE(ABORT, 'invalid kind: must be raw|distilled|superseded|archived (not null)');
327
+ END
328
+ `);
329
+ // Defensive: any rows that somehow have NULL kind get fixed (shouldn't exist post-v14
330
+ // backfill, but cheap insurance).
331
+ db.exec(`UPDATE memories SET kind = 'distilled' WHERE kind IS NULL`);
332
+ // raw_archive uniqueness. SQLite cannot ADD CONSTRAINT, but a partial unique index
333
+ // on (memory_id, archived_at) is equivalent for INSERT-time enforcement.
334
+ db.exec(`
335
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_raw_archive_id_at
336
+ ON raw_archive(memory_id, archived_at)
337
+ `);
338
+ },
339
+ },
340
+ {
341
+ version: 16,
342
+ up: (db) => {
343
+ // A5 stub auth: add tenant_id to all data tables. Single-tenant per deployment;
344
+ // multi-tenant enforcement deferred to v2 (full A5). The columns are needed now
345
+ // so future B-track tables don't have to backfill.
346
+ if (!tableHasColumn(db, 'memories', 'tenant_id')) {
347
+ db.exec(`ALTER TABLE memories ADD COLUMN tenant_id TEXT NOT NULL DEFAULT 'default'`);
348
+ }
349
+ if (!tableHasColumn(db, 'working_memory', 'tenant_id')) {
350
+ db.exec(`ALTER TABLE working_memory ADD COLUMN tenant_id TEXT NOT NULL DEFAULT 'default'`);
351
+ }
352
+ if (!tableHasColumn(db, 'consolidation_runs', 'tenant_id')) {
353
+ db.exec(`ALTER TABLE consolidation_runs ADD COLUMN tenant_id TEXT NOT NULL DEFAULT 'default'`);
354
+ }
355
+ if (!tableHasColumn(db, 'task_snapshots', 'tenant_id')) {
356
+ db.exec(`ALTER TABLE task_snapshots ADD COLUMN tenant_id TEXT NOT NULL DEFAULT 'default'`);
357
+ }
358
+ if (!tableHasColumn(db, 'memory_conflicts', 'tenant_id')) {
359
+ db.exec(`ALTER TABLE memory_conflicts ADD COLUMN tenant_id TEXT NOT NULL DEFAULT 'default'`);
360
+ }
361
+ // Composite indexes for recall hot paths. Leading column is tenant_id so
362
+ // single-tenant lookups are O(log n).
363
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_memories_tenant_created ON memories(tenant_id, created)`);
364
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_working_memory_tenant ON working_memory(tenant_id, importance DESC, created_at DESC)`);
365
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_consolidation_runs_tenant_ts ON consolidation_runs(tenant_id, timestamp DESC)`);
366
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_task_snapshots_tenant_status ON task_snapshots(tenant_id, status, updated_at DESC)`);
367
+ // A5 stub auth: api_keys (scrypt-hashed; plaintext returned to caller exactly once)
368
+ // and audit_log (append-only mutation trail). Both carry tenant_id from day 1 so
369
+ // future multi-tenant enforcement is a config flip, not a re-migration.
370
+ db.exec(`
371
+ CREATE TABLE IF NOT EXISTS api_keys (
372
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
373
+ key_id TEXT UNIQUE NOT NULL,
374
+ key_hash TEXT NOT NULL,
375
+ tenant_id TEXT NOT NULL DEFAULT 'default',
376
+ label TEXT,
377
+ created_at TEXT NOT NULL,
378
+ revoked_at TEXT
379
+ )
380
+ `);
381
+ db.exec(`
382
+ CREATE INDEX IF NOT EXISTS idx_api_keys_tenant_active
383
+ ON api_keys(tenant_id) WHERE revoked_at IS NULL
384
+ `);
385
+ db.exec(`
386
+ CREATE TABLE IF NOT EXISTS audit_log (
387
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
388
+ ts TEXT NOT NULL,
389
+ tenant_id TEXT NOT NULL DEFAULT 'default',
390
+ actor TEXT NOT NULL,
391
+ op TEXT NOT NULL,
392
+ target_id TEXT,
393
+ metadata_json TEXT NOT NULL DEFAULT '{}'
394
+ )
395
+ `);
396
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_audit_log_tenant_ts ON audit_log(tenant_id, ts DESC)`);
397
+ },
398
+ },
399
+ {
400
+ version: 17,
401
+ up: (db) => {
402
+ // E1.3 Slack ingestion: idempotency log, per-channel backfill cursors, DLQ.
403
+ // See docs/plans/2026-04-29-e1.3-slack-ingestion.md.
404
+ db.exec(`
405
+ CREATE TABLE IF NOT EXISTS slack_event_log (
406
+ event_id TEXT PRIMARY KEY,
407
+ ingested_at TEXT NOT NULL,
408
+ memory_id TEXT
409
+ )
410
+ `);
411
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_slack_event_log_memory ON slack_event_log(memory_id) WHERE memory_id IS NOT NULL`);
412
+ db.exec(`
413
+ CREATE TABLE IF NOT EXISTS slack_cursors (
414
+ tenant_id TEXT NOT NULL,
415
+ channel_id TEXT NOT NULL,
416
+ latest_ts TEXT NOT NULL,
417
+ updated_at TEXT NOT NULL,
418
+ PRIMARY KEY (tenant_id, channel_id)
419
+ )
420
+ `);
421
+ db.exec(`
422
+ CREATE TABLE IF NOT EXISTS slack_dlq (
423
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
424
+ tenant_id TEXT NOT NULL,
425
+ raw_payload TEXT NOT NULL,
426
+ error TEXT NOT NULL,
427
+ received_at TEXT NOT NULL,
428
+ retried_at TEXT
429
+ )
430
+ `);
431
+ db.exec(`CREATE INDEX IF NOT EXISTS idx_slack_dlq_tenant_received ON slack_dlq(tenant_id, received_at)`);
432
+ // Multi-tenant routing seam (review patch #6). Empty by default — single-
433
+ // tenant deployments resolve via HIPPO_TENANT fallback. Multi-workspace
434
+ // deployments populate this table to map team_id → tenant_id.
435
+ db.exec(`
436
+ CREATE TABLE IF NOT EXISTS slack_workspaces (
437
+ team_id TEXT PRIMARY KEY,
438
+ tenant_id TEXT NOT NULL,
439
+ added_at TEXT NOT NULL
440
+ )
441
+ `);
442
+ },
443
+ },
444
+ ];
445
+ function tableHasColumn(db, tableName, columnName) {
446
+ if (!/^[a-z_]+$/i.test(tableName))
447
+ throw new Error(`Invalid table name: ${tableName}`);
448
+ const rows = db.prepare(`PRAGMA table_info(${tableName})`).all();
449
+ return rows.some((row) => row.name === columnName);
450
+ }
451
+ export function getHippoDbPath(hippoRoot) {
452
+ return path.join(hippoRoot, 'hippo.db');
453
+ }
454
+ export function getCurrentSchemaVersion() {
455
+ return CURRENT_SCHEMA_VERSION;
456
+ }
457
+ export function openHippoDb(hippoRoot) {
458
+ fs.mkdirSync(hippoRoot, { recursive: true });
459
+ const db = new DatabaseSync(getHippoDbPath(hippoRoot));
460
+ try {
461
+ db.exec('PRAGMA journal_mode = WAL');
462
+ db.exec('PRAGMA busy_timeout = 5000');
463
+ db.exec('PRAGMA synchronous = NORMAL');
464
+ db.exec('PRAGMA wal_autocheckpoint = 100');
465
+ db.exec('PRAGMA foreign_keys = ON');
466
+ runMigrations(db);
467
+ return db;
468
+ }
469
+ catch (error) {
470
+ try {
471
+ db.close();
472
+ }
473
+ catch {
474
+ // Best effort only.
475
+ }
476
+ throw error;
477
+ }
478
+ }
479
+ function runMigrations(db) {
480
+ ensureMetaTable(db);
481
+ let currentVersion = getSchemaVersion(db);
482
+ for (const migration of MIGRATIONS) {
483
+ if (migration.version <= currentVersion)
484
+ continue;
485
+ db.exec('BEGIN');
486
+ try {
487
+ migration.up(db);
488
+ setSchemaVersion(db, migration.version);
489
+ db.exec('COMMIT');
490
+ currentVersion = migration.version;
491
+ }
492
+ catch (error) {
493
+ db.exec('ROLLBACK');
494
+ throw error;
495
+ }
496
+ }
497
+ ensureMetaDefaults(db);
498
+ ensureOptionalFts(db);
499
+ }
500
+ function ensureMetaTable(db) {
501
+ db.exec(`
502
+ CREATE TABLE IF NOT EXISTS meta (
503
+ key TEXT PRIMARY KEY,
504
+ value TEXT NOT NULL
505
+ );
506
+ `);
507
+ }
508
+ export function getSchemaVersion(db) {
509
+ const row = db.prepare(`SELECT value FROM meta WHERE key = 'schema_version'`).get();
510
+ const version = Number(row?.value ?? 0);
511
+ return Number.isFinite(version) ? version : 0;
512
+ }
513
+ function setSchemaVersion(db, version) {
514
+ db.prepare(`INSERT INTO meta(key, value) VALUES('schema_version', ?) ON CONFLICT(key) DO UPDATE SET value=excluded.value`).run(String(version));
515
+ db.exec(`PRAGMA user_version = ${Math.max(0, Math.trunc(version))}`);
516
+ }
517
+ function ensureMetaDefaults(db) {
518
+ const defaults = [
519
+ ['schema_version', String(CURRENT_SCHEMA_VERSION)],
520
+ ['last_retrieval_ids', '[]'],
521
+ ['total_remembered', '0'],
522
+ ['total_recalled', '0'],
523
+ ['total_forgotten', '0'],
524
+ ['fts5_available', '0'],
525
+ ];
526
+ const stmt = db.prepare(`INSERT OR IGNORE INTO meta(key, value) VALUES (?, ?)`);
527
+ for (const [key, value] of defaults) {
528
+ stmt.run(key, value);
529
+ }
530
+ }
531
+ function ensureOptionalFts(db) {
532
+ let available = false;
533
+ try {
534
+ db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(id UNINDEXED, content, tags)`);
535
+ backfillFtsIndex(db);
536
+ available = true;
537
+ }
538
+ catch {
539
+ available = false;
540
+ }
541
+ db.prepare(`INSERT INTO meta(key, value) VALUES('fts5_available', ?) ON CONFLICT(key) DO UPDATE SET value=excluded.value`).run(available ? '1' : '0');
542
+ }
543
+ function backfillFtsIndex(db) {
544
+ const memCount = db.prepare(`SELECT COUNT(*) AS c FROM memories`).get()?.c ?? 0;
545
+ const ftsCount = db.prepare(`SELECT COUNT(*) AS c FROM memories_fts`).get()?.c ?? 0;
546
+ if (memCount === ftsCount)
547
+ return;
548
+ db.exec(`
549
+ INSERT INTO memories_fts(id, content, tags)
550
+ SELECT m.id, m.content, m.tags_json
551
+ FROM memories m
552
+ WHERE NOT EXISTS (
553
+ SELECT 1 FROM memories_fts f WHERE f.id = m.id
554
+ )
555
+ `);
556
+ db.exec(`
557
+ DELETE FROM memories_fts
558
+ WHERE id NOT IN (SELECT id FROM memories)
559
+ `);
560
+ }
561
+ export function closeHippoDb(db) {
562
+ db.close();
563
+ }
564
+ export function getMeta(db, key, fallback = '') {
565
+ const row = db.prepare(`SELECT value FROM meta WHERE key = ?`).get(key);
566
+ return row?.value ?? fallback;
567
+ }
568
+ export function setMeta(db, key, value) {
569
+ db.prepare(`INSERT INTO meta(key, value) VALUES(?, ?) ON CONFLICT(key) DO UPDATE SET value=excluded.value`).run(key, value);
570
+ }
571
+ export function isFtsAvailable(db) {
572
+ return getMeta(db, 'fts5_available', '0') === '1';
573
+ }
574
+ export function pruneConsolidationRuns(db, keep = 50) {
575
+ db.prepare(`
576
+ DELETE FROM consolidation_runs
577
+ WHERE id NOT IN (
578
+ SELECT id FROM consolidation_runs
579
+ ORDER BY timestamp DESC, id DESC
580
+ LIMIT ?
581
+ )
582
+ `).run(keep);
583
+ }
584
+ //# sourceMappingURL=db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/db.ts"],"names":[],"mappings":"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"}