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.
- package/README.md +25 -0
- package/dist/api.d.ts +183 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +343 -0
- package/dist/api.js.map +1 -0
- package/dist/benchmarks/e1.3/incident-recall-eval.js +74 -0
- package/dist/benchmarks/e1.3/incident-recall-eval.js.map +1 -0
- package/dist/benchmarks/e1.3/scenarios.json +2587 -0
- package/dist/benchmarks/e1.3/slack-1000-event-smoke.js +102 -0
- package/dist/benchmarks/e1.3/slack-1000-event-smoke.js.map +1 -0
- package/dist/cli.js +222 -34
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +54 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +181 -0
- package/dist/client.js.map +1 -0
- package/dist/connectors/slack/backfill.d.ts +42 -0
- package/dist/connectors/slack/backfill.d.ts.map +1 -0
- package/dist/connectors/slack/backfill.js +76 -0
- package/dist/connectors/slack/backfill.js.map +1 -0
- package/dist/connectors/slack/deletion.d.ts +14 -0
- package/dist/connectors/slack/deletion.d.ts.map +1 -0
- package/dist/connectors/slack/deletion.js +46 -0
- package/dist/connectors/slack/deletion.js.map +1 -0
- package/dist/connectors/slack/dlq.d.ts +21 -0
- package/dist/connectors/slack/dlq.d.ts.map +1 -0
- package/dist/connectors/slack/dlq.js +23 -0
- package/dist/connectors/slack/dlq.js.map +1 -0
- package/dist/connectors/slack/idempotency.d.ts +5 -0
- package/dist/connectors/slack/idempotency.d.ts.map +1 -0
- package/dist/connectors/slack/idempotency.js +13 -0
- package/dist/connectors/slack/idempotency.js.map +1 -0
- package/dist/connectors/slack/ingest.d.ts +27 -0
- package/dist/connectors/slack/ingest.d.ts.map +1 -0
- package/dist/connectors/slack/ingest.js +48 -0
- package/dist/connectors/slack/ingest.js.map +1 -0
- package/dist/connectors/slack/ratelimit.d.ts +9 -0
- package/dist/connectors/slack/ratelimit.d.ts.map +1 -0
- package/dist/connectors/slack/ratelimit.js +18 -0
- package/dist/connectors/slack/ratelimit.js.map +1 -0
- package/dist/connectors/slack/scope.d.ts +16 -0
- package/dist/connectors/slack/scope.d.ts.map +1 -0
- package/dist/connectors/slack/scope.js +13 -0
- package/dist/connectors/slack/scope.js.map +1 -0
- package/dist/connectors/slack/signature.d.ts +12 -0
- package/dist/connectors/slack/signature.d.ts.map +1 -0
- package/dist/connectors/slack/signature.js +20 -0
- package/dist/connectors/slack/signature.js.map +1 -0
- package/dist/connectors/slack/tenant-routing.d.ts +13 -0
- package/dist/connectors/slack/tenant-routing.d.ts.map +1 -0
- package/dist/connectors/slack/tenant-routing.js +17 -0
- package/dist/connectors/slack/tenant-routing.js.map +1 -0
- package/dist/connectors/slack/transform.d.ts +20 -0
- package/dist/connectors/slack/transform.d.ts.map +1 -0
- package/dist/connectors/slack/transform.js +31 -0
- package/dist/connectors/slack/transform.js.map +1 -0
- package/dist/connectors/slack/types.d.ts +35 -0
- package/dist/connectors/slack/types.d.ts.map +1 -0
- package/dist/connectors/slack/types.js +23 -0
- package/dist/connectors/slack/types.js.map +1 -0
- package/dist/connectors/slack/web-client.d.ts +12 -0
- package/dist/connectors/slack/web-client.d.ts.map +1 -0
- package/dist/connectors/slack/web-client.js +43 -0
- package/dist/connectors/slack/web-client.js.map +1 -0
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +46 -1
- package/dist/db.js.map +1 -1
- package/dist/importers.js +3 -3
- package/dist/importers.js.map +1 -1
- package/dist/mcp/server.d.ts +46 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +74 -26
- package/dist/mcp/server.js.map +1 -1
- package/dist/server-detect.d.ts +26 -0
- package/dist/server-detect.d.ts.map +1 -0
- package/dist/server-detect.js +70 -0
- package/dist/server-detect.js.map +1 -0
- package/dist/server.d.ts +29 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +784 -0
- package/dist/server.js.map +1 -0
- package/dist/shared.d.ts +3 -1
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +2 -2
- package/dist/shared.js.map +1 -1
- package/dist/src/ambient.js +147 -0
- package/dist/src/ambient.js.map +1 -0
- package/dist/src/api.js +343 -0
- package/dist/src/api.js.map +1 -0
- package/dist/src/audit.js +152 -0
- package/dist/src/audit.js.map +1 -0
- package/dist/src/auth.js +65 -0
- package/dist/src/auth.js.map +1 -0
- package/dist/src/autolearn.js +143 -0
- package/dist/src/autolearn.js.map +1 -0
- package/dist/src/capture.js +512 -0
- package/dist/src/capture.js.map +1 -0
- package/dist/src/cli.js +4971 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/client.js +181 -0
- package/dist/src/client.js.map +1 -0
- package/dist/src/config.js +108 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/connectors/slack/backfill.js +76 -0
- package/dist/src/connectors/slack/backfill.js.map +1 -0
- package/dist/src/connectors/slack/deletion.js +46 -0
- package/dist/src/connectors/slack/deletion.js.map +1 -0
- package/dist/src/connectors/slack/dlq.js +23 -0
- package/dist/src/connectors/slack/dlq.js.map +1 -0
- package/dist/src/connectors/slack/idempotency.js +13 -0
- package/dist/src/connectors/slack/idempotency.js.map +1 -0
- package/dist/src/connectors/slack/ingest.js +48 -0
- package/dist/src/connectors/slack/ingest.js.map +1 -0
- package/dist/src/connectors/slack/ratelimit.js +18 -0
- package/dist/src/connectors/slack/ratelimit.js.map +1 -0
- package/dist/src/connectors/slack/scope.js +13 -0
- package/dist/src/connectors/slack/scope.js.map +1 -0
- package/dist/src/connectors/slack/signature.js +20 -0
- package/dist/src/connectors/slack/signature.js.map +1 -0
- package/dist/src/connectors/slack/tenant-routing.js +17 -0
- package/dist/src/connectors/slack/tenant-routing.js.map +1 -0
- package/dist/src/connectors/slack/transform.js +31 -0
- package/dist/src/connectors/slack/transform.js.map +1 -0
- package/dist/src/connectors/slack/types.js +23 -0
- package/dist/src/connectors/slack/types.js.map +1 -0
- package/dist/src/connectors/slack/web-client.js +43 -0
- package/dist/src/connectors/slack/web-client.js.map +1 -0
- package/dist/src/consolidate.js +517 -0
- package/dist/src/consolidate.js.map +1 -0
- package/dist/src/dag.js +104 -0
- package/dist/src/dag.js.map +1 -0
- package/dist/src/dashboard.js +409 -0
- package/dist/src/dashboard.js.map +1 -0
- package/dist/src/db.js +584 -0
- package/dist/src/db.js.map +1 -0
- package/dist/src/embeddings.js +344 -0
- package/dist/src/embeddings.js.map +1 -0
- package/dist/src/eval-suite.js +289 -0
- package/dist/src/eval-suite.js.map +1 -0
- package/dist/src/eval.js +187 -0
- package/dist/src/eval.js.map +1 -0
- package/dist/src/extract.js +87 -0
- package/dist/src/extract.js.map +1 -0
- package/dist/src/handoff.js +30 -0
- package/dist/src/handoff.js.map +1 -0
- package/dist/src/hooks.js +582 -0
- package/dist/src/hooks.js.map +1 -0
- package/dist/src/importers.js +399 -0
- package/dist/src/importers.js.map +1 -0
- package/dist/src/index.js +25 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/invalidation.js +94 -0
- package/dist/src/invalidation.js.map +1 -0
- package/dist/src/mcp/framing.js +45 -0
- package/dist/src/mcp/framing.js.map +1 -0
- package/dist/src/mcp/server.js +510 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/memory.js +280 -0
- package/dist/src/memory.js.map +1 -0
- package/dist/src/multihop.js +32 -0
- package/dist/src/multihop.js.map +1 -0
- package/dist/src/path-context.js +32 -0
- package/dist/src/path-context.js.map +1 -0
- package/dist/src/physics-config.js +26 -0
- package/dist/src/physics-config.js.map +1 -0
- package/dist/src/physics-state.js +163 -0
- package/dist/src/physics-state.js.map +1 -0
- package/dist/src/physics.js +361 -0
- package/dist/src/physics.js.map +1 -0
- package/dist/src/postinstall.js +68 -0
- package/dist/src/postinstall.js.map +1 -0
- package/dist/src/raw-archive.js +72 -0
- package/dist/src/raw-archive.js.map +1 -0
- package/dist/src/refine-llm.js +147 -0
- package/dist/src/refine-llm.js.map +1 -0
- package/dist/src/replay.js +117 -0
- package/dist/src/replay.js.map +1 -0
- package/dist/src/salience.js +74 -0
- package/dist/src/salience.js.map +1 -0
- package/dist/src/scheduler.js +67 -0
- package/dist/src/scheduler.js.map +1 -0
- package/dist/src/scope.js +35 -0
- package/dist/src/scope.js.map +1 -0
- package/dist/src/search.js +801 -0
- package/dist/src/search.js.map +1 -0
- package/dist/src/server-detect.js +70 -0
- package/dist/src/server-detect.js.map +1 -0
- package/dist/src/server.js +784 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/shared.js +309 -0
- package/dist/src/shared.js.map +1 -0
- package/dist/src/sso.js +22 -0
- package/dist/src/sso.js.map +1 -0
- package/dist/src/store.js +1390 -0
- package/dist/src/store.js.map +1 -0
- package/dist/src/tenant.js +17 -0
- package/dist/src/tenant.js.map +1 -0
- package/dist/src/trace.js +64 -0
- package/dist/src/trace.js.map +1 -0
- package/dist/src/working-memory.js +149 -0
- package/dist/src/working-memory.js.map +1 -0
- package/dist/src/yaml.js +98 -0
- package/dist/src/yaml.js.map +1 -0
- package/dist/store.d.ts +25 -4
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +50 -11
- package/dist/store.js.map +1 -1
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
- package/dist/import.d.ts +0 -31
- package/dist/import.d.ts.map +0 -1
- package/dist/import.js +0 -307
- 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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"}
|