engram-sdk 0.1.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/CONTRIBUTING.md +65 -0
- package/Dockerfile +21 -0
- package/EVAL-FRAMEWORK.md +70 -0
- package/EVAL.md +127 -0
- package/LICENSE +17 -0
- package/README.md +309 -0
- package/ROADMAP.md +113 -0
- package/deploy/fly.toml +26 -0
- package/dist/auto-ingest.d.ts +3 -0
- package/dist/auto-ingest.d.ts.map +1 -0
- package/dist/auto-ingest.js +334 -0
- package/dist/auto-ingest.js.map +1 -0
- package/dist/brief.d.ts +45 -0
- package/dist/brief.d.ts.map +1 -0
- package/dist/brief.js +183 -0
- package/dist/brief.js.map +1 -0
- package/dist/claude-watcher.d.ts +3 -0
- package/dist/claude-watcher.d.ts.map +1 -0
- package/dist/claude-watcher.js +385 -0
- package/dist/claude-watcher.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +764 -0
- package/dist/cli.js.map +1 -0
- package/dist/embeddings.d.ts +42 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +145 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/eval.d.ts +2 -0
- package/dist/eval.d.ts.map +1 -0
- package/dist/eval.js +281 -0
- package/dist/eval.js.map +1 -0
- package/dist/extract.d.ts +11 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +139 -0
- package/dist/extract.js.map +1 -0
- package/dist/hosted.d.ts +3 -0
- package/dist/hosted.d.ts.map +1 -0
- package/dist/hosted.js +144 -0
- package/dist/hosted.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest.d.ts +28 -0
- package/dist/ingest.d.ts.map +1 -0
- package/dist/ingest.js +192 -0
- package/dist/ingest.js.map +1 -0
- package/dist/mcp.d.ts +3 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +349 -0
- package/dist/mcp.js.map +1 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +515 -0
- package/dist/server.js.map +1 -0
- package/dist/store.d.ts +87 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +548 -0
- package/dist/store.js.map +1 -0
- package/dist/types.d.ts +204 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +77 -0
- package/dist/types.js.map +1 -0
- package/dist/vault.d.ts +116 -0
- package/dist/vault.d.ts.map +1 -0
- package/dist/vault.js +1234 -0
- package/dist/vault.js.map +1 -0
- package/package.json +61 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Vault } from './vault.js';
|
|
3
|
+
import { OpenAIEmbeddings, GeminiEmbeddings } from './embeddings.js';
|
|
4
|
+
import { createServer } from 'node:http';
|
|
5
|
+
// Active vault instances
|
|
6
|
+
const vaultCache = new Map();
|
|
7
|
+
function getOrCreateVault(config) {
|
|
8
|
+
const key = `${config.owner}:${config.dbPath ?? 'default'}`;
|
|
9
|
+
let vault = vaultCache.get(key);
|
|
10
|
+
if (!vault) {
|
|
11
|
+
let embedder;
|
|
12
|
+
if (config.llm) {
|
|
13
|
+
if (config.llm.provider === 'gemini') {
|
|
14
|
+
embedder = new GeminiEmbeddings(config.llm.apiKey, config.llm.embeddingModel ?? 'gemini-embedding-001');
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
embedder = new OpenAIEmbeddings(config.llm.apiKey, config.llm.embeddingModel ?? 'text-embedding-3-small');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
vault = new Vault(config, embedder);
|
|
21
|
+
vaultCache.set(key, vault);
|
|
22
|
+
}
|
|
23
|
+
return vault;
|
|
24
|
+
}
|
|
25
|
+
// ============================================================
|
|
26
|
+
// Request parsing helpers
|
|
27
|
+
// ============================================================
|
|
28
|
+
async function readBody(req) {
|
|
29
|
+
const chunks = [];
|
|
30
|
+
for await (const chunk of req) {
|
|
31
|
+
chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
|
|
32
|
+
}
|
|
33
|
+
return Buffer.concat(chunks).toString('utf-8');
|
|
34
|
+
}
|
|
35
|
+
function json(res, status, data) {
|
|
36
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
37
|
+
res.end(JSON.stringify(data));
|
|
38
|
+
}
|
|
39
|
+
function error(res, status, message) {
|
|
40
|
+
json(res, status, { error: message });
|
|
41
|
+
}
|
|
42
|
+
const routes = [];
|
|
43
|
+
function route(method, path, handler) {
|
|
44
|
+
// Convert /v1/memories/:id to a regex with named groups
|
|
45
|
+
const paramNames = [];
|
|
46
|
+
const regexStr = path.replace(/:(\w+)/g, (_, name) => {
|
|
47
|
+
paramNames.push(name);
|
|
48
|
+
return '([^/]+)';
|
|
49
|
+
});
|
|
50
|
+
routes.push({ method, pattern: new RegExp(`^${regexStr}$`), paramNames, handler });
|
|
51
|
+
}
|
|
52
|
+
// ============================================================
|
|
53
|
+
// API Routes
|
|
54
|
+
// ============================================================
|
|
55
|
+
// POST /v1/memories — remember()
|
|
56
|
+
route('POST', '/v1/memories', async (req, res, vault) => {
|
|
57
|
+
const body = JSON.parse(await readBody(req));
|
|
58
|
+
const memory = vault.remember(body);
|
|
59
|
+
json(res, 201, memory);
|
|
60
|
+
});
|
|
61
|
+
// GET /v1/memories/recall?context=...&entities=...&topics=...&types=...&limit=...&spread=...
|
|
62
|
+
route('GET', '/v1/memories/recall', async (req, res, vault) => {
|
|
63
|
+
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
64
|
+
const context = url.searchParams.get('context');
|
|
65
|
+
if (!context) {
|
|
66
|
+
error(res, 400, 'context query parameter is required');
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const input = { context };
|
|
70
|
+
const entities = url.searchParams.get('entities');
|
|
71
|
+
if (entities)
|
|
72
|
+
input.entities = entities.split(',');
|
|
73
|
+
const topics = url.searchParams.get('topics');
|
|
74
|
+
if (topics)
|
|
75
|
+
input.topics = topics.split(',');
|
|
76
|
+
const types = url.searchParams.get('types');
|
|
77
|
+
if (types)
|
|
78
|
+
input.types = types.split(',');
|
|
79
|
+
const limit = url.searchParams.get('limit');
|
|
80
|
+
if (limit)
|
|
81
|
+
input.limit = parseInt(limit, 10);
|
|
82
|
+
// Spreading activation params
|
|
83
|
+
const spread = url.searchParams.get('spread');
|
|
84
|
+
if (spread !== null)
|
|
85
|
+
input.spread = spread !== 'false' && spread !== '0';
|
|
86
|
+
const spreadHops = url.searchParams.get('spreadHops');
|
|
87
|
+
if (spreadHops)
|
|
88
|
+
input.spreadHops = parseInt(spreadHops, 10);
|
|
89
|
+
const spreadDecay = url.searchParams.get('spreadDecay');
|
|
90
|
+
if (spreadDecay)
|
|
91
|
+
input.spreadDecay = parseFloat(spreadDecay);
|
|
92
|
+
const spreadEntityHops = url.searchParams.get('spreadEntityHops');
|
|
93
|
+
if (spreadEntityHops !== null)
|
|
94
|
+
input.spreadEntityHops = spreadEntityHops !== 'false' && spreadEntityHops !== '0';
|
|
95
|
+
const memories = await vault.recall(input);
|
|
96
|
+
json(res, 200, { memories, count: memories.length });
|
|
97
|
+
});
|
|
98
|
+
// POST /v1/memories/recall — recall() with body (for complex queries)
|
|
99
|
+
route('POST', '/v1/memories/recall', async (req, res, vault) => {
|
|
100
|
+
const body = JSON.parse(await readBody(req));
|
|
101
|
+
const memories = await vault.recall(body);
|
|
102
|
+
json(res, 200, { memories, count: memories.length });
|
|
103
|
+
});
|
|
104
|
+
// DELETE /v1/memories/:id — forget()
|
|
105
|
+
route('DELETE', '/v1/memories/:id', (req, res, vault, params) => {
|
|
106
|
+
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
107
|
+
const hard = url.searchParams.get('hard') === 'true';
|
|
108
|
+
vault.forget(params.id, hard);
|
|
109
|
+
json(res, 200, { deleted: params.id, hard });
|
|
110
|
+
});
|
|
111
|
+
// GET /v1/memories/:id/neighbors — neighbors()
|
|
112
|
+
route('GET', '/v1/memories/:id/neighbors', (req, res, vault, params) => {
|
|
113
|
+
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
114
|
+
const depth = parseInt(url.searchParams.get('depth') ?? '1', 10);
|
|
115
|
+
const memories = vault.neighbors(params.id, depth);
|
|
116
|
+
json(res, 200, { memories, count: memories.length });
|
|
117
|
+
});
|
|
118
|
+
// POST /v1/connections — connect()
|
|
119
|
+
route('POST', '/v1/connections', async (req, res, vault) => {
|
|
120
|
+
const body = JSON.parse(await readBody(req));
|
|
121
|
+
const { sourceId, targetId, type, strength } = body;
|
|
122
|
+
if (!sourceId || !targetId || !type) {
|
|
123
|
+
error(res, 400, 'sourceId, targetId, and type are required');
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const edge = vault.connect(sourceId, targetId, type, strength);
|
|
127
|
+
json(res, 201, edge);
|
|
128
|
+
});
|
|
129
|
+
// POST /v1/consolidate — consolidate()
|
|
130
|
+
route('POST', '/v1/consolidate', async (req, res, vault) => {
|
|
131
|
+
const report = await vault.consolidate();
|
|
132
|
+
json(res, 200, report);
|
|
133
|
+
});
|
|
134
|
+
// GET /v1/entities — entities()
|
|
135
|
+
route('GET', '/v1/entities', (req, res, vault) => {
|
|
136
|
+
const entities = vault.entities();
|
|
137
|
+
json(res, 200, { entities, count: entities.length });
|
|
138
|
+
});
|
|
139
|
+
// GET /v1/stats — stats()
|
|
140
|
+
route('GET', '/v1/stats', (req, res, vault) => {
|
|
141
|
+
const stats = vault.stats();
|
|
142
|
+
json(res, 200, stats);
|
|
143
|
+
});
|
|
144
|
+
// POST /v1/export — export()
|
|
145
|
+
route('POST', '/v1/export', (req, res, vault) => {
|
|
146
|
+
const data = vault.export();
|
|
147
|
+
json(res, 200, data);
|
|
148
|
+
});
|
|
149
|
+
// POST /v1/embeddings/backfill — compute embeddings for all memories
|
|
150
|
+
route('POST', '/v1/embeddings/backfill', async (req, res, vault) => {
|
|
151
|
+
const count = await vault.backfillEmbeddings();
|
|
152
|
+
json(res, 200, { backfilled: count });
|
|
153
|
+
});
|
|
154
|
+
// POST /v1/ingest — auto-extract memories from raw conversation text
|
|
155
|
+
route('POST', '/v1/ingest', async (req, res, vault) => {
|
|
156
|
+
const body = JSON.parse(await readBody(req));
|
|
157
|
+
const { text, content, transcript } = body;
|
|
158
|
+
const rawText = text ?? content ?? transcript;
|
|
159
|
+
if (!rawText || typeof rawText !== 'string') {
|
|
160
|
+
error(res, 400, 'text, content, or transcript field is required (string)');
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
// Simple mode: just remember() with auto-extraction (no LLM needed)
|
|
164
|
+
const memory = vault.remember({ content: rawText });
|
|
165
|
+
json(res, 201, memory);
|
|
166
|
+
});
|
|
167
|
+
// POST /v1/surface — proactive memory surfacing (memories pushed, not pulled)
|
|
168
|
+
route('POST', '/v1/surface', async (req, res, vault) => {
|
|
169
|
+
const body = JSON.parse(await readBody(req));
|
|
170
|
+
const { context, activeEntities, activeTopics, seen, minSalience, minHoursSinceAccess, limit, relevanceThreshold } = body;
|
|
171
|
+
if (!context || typeof context !== 'string') {
|
|
172
|
+
error(res, 400, 'context field is required (string)');
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const results = await vault.surface({
|
|
176
|
+
context,
|
|
177
|
+
activeEntities,
|
|
178
|
+
activeTopics,
|
|
179
|
+
seen,
|
|
180
|
+
minSalience,
|
|
181
|
+
minHoursSinceAccess,
|
|
182
|
+
limit,
|
|
183
|
+
relevanceThreshold,
|
|
184
|
+
});
|
|
185
|
+
json(res, 200, { surfaced: results, count: results.length });
|
|
186
|
+
});
|
|
187
|
+
// POST /v1/briefing — session briefing: structured context summary for session start
|
|
188
|
+
route('POST', '/v1/briefing', async (req, res, vault) => {
|
|
189
|
+
const body = JSON.parse(await readBody(req));
|
|
190
|
+
const context = body.context ?? body.topic ?? '';
|
|
191
|
+
const limit = body.limit ?? 20;
|
|
192
|
+
const briefing = await vault.briefing(context, limit);
|
|
193
|
+
json(res, 200, briefing);
|
|
194
|
+
});
|
|
195
|
+
// GET /v1/briefing — session briefing with optional context
|
|
196
|
+
route('GET', '/v1/briefing', async (req, res, vault) => {
|
|
197
|
+
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
198
|
+
const context = url.searchParams.get('context') ?? '';
|
|
199
|
+
const limit = parseInt(url.searchParams.get('limit') ?? '20', 10);
|
|
200
|
+
const briefing = await vault.briefing(context, limit);
|
|
201
|
+
json(res, 200, briefing);
|
|
202
|
+
});
|
|
203
|
+
// POST /v1/shadow/compare — compare Engram briefing vs a memory file
|
|
204
|
+
// Shadow mode: run Engram alongside existing memory, see what each catches
|
|
205
|
+
route('POST', '/v1/shadow/compare', async (req, res, vault) => {
|
|
206
|
+
const body = JSON.parse(await readBody(req));
|
|
207
|
+
const memoryFileContent = body.memoryFile ?? '';
|
|
208
|
+
const context = body.context ?? '';
|
|
209
|
+
const limit = body.limit ?? 20;
|
|
210
|
+
if (!memoryFileContent) {
|
|
211
|
+
return error(res, 400, 'memoryFile is required (paste your CLAUDE.md / MEMORY.md content)');
|
|
212
|
+
}
|
|
213
|
+
// Get Engram briefing
|
|
214
|
+
const briefing = await vault.briefing(context, limit);
|
|
215
|
+
// Collect all surfaced items from briefing sections
|
|
216
|
+
const surfacedItems = [
|
|
217
|
+
...briefing.keyFacts.map((f) => f.content),
|
|
218
|
+
...briefing.activeCommitments.map((c) => c.content),
|
|
219
|
+
...briefing.recentActivity.map((a) => a.content),
|
|
220
|
+
];
|
|
221
|
+
// Simple line-level analysis: what does Engram surface that the file doesn't mention?
|
|
222
|
+
const fileLower = memoryFileContent.toLowerCase();
|
|
223
|
+
const engramOnly = [];
|
|
224
|
+
const bothHave = [];
|
|
225
|
+
for (const item of surfacedItems) {
|
|
226
|
+
const keywords = item
|
|
227
|
+
.toLowerCase()
|
|
228
|
+
.split(/\s+/)
|
|
229
|
+
.filter((w) => w.length > 4)
|
|
230
|
+
.slice(0, 5);
|
|
231
|
+
const matchCount = keywords.filter((kw) => fileLower.includes(kw)).length;
|
|
232
|
+
const matchRatio = keywords.length > 0 ? matchCount / keywords.length : 0;
|
|
233
|
+
if (matchRatio < 0.4) {
|
|
234
|
+
engramOnly.push(item.slice(0, 150));
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
bothHave.push(item.slice(0, 150));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
// Check what's in the file but Engram didn't surface
|
|
241
|
+
const fileLines = memoryFileContent
|
|
242
|
+
.split('\n')
|
|
243
|
+
.map((l) => l.replace(/^[\s\-*#>]+/, '').trim())
|
|
244
|
+
.filter((l) => l.length > 20);
|
|
245
|
+
const fileOnly = [];
|
|
246
|
+
const briefingText = surfacedItems.map((s) => s.toLowerCase()).join(' ');
|
|
247
|
+
for (const line of fileLines) {
|
|
248
|
+
const lineKeywords = line.toLowerCase().split(/\s+/).filter((w) => w.length > 4).slice(0, 5);
|
|
249
|
+
const matchCount = lineKeywords.filter((kw) => briefingText.includes(kw)).length;
|
|
250
|
+
const matchRatio = lineKeywords.length > 0 ? matchCount / lineKeywords.length : 0;
|
|
251
|
+
if (matchRatio < 0.3) {
|
|
252
|
+
fileOnly.push(line.slice(0, 150));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
json(res, 200, {
|
|
256
|
+
summary: {
|
|
257
|
+
engramSurfaced: surfacedItems.length,
|
|
258
|
+
engramOnly: engramOnly.length,
|
|
259
|
+
fileOnly: fileOnly.length,
|
|
260
|
+
overlap: bothHave.length,
|
|
261
|
+
},
|
|
262
|
+
engramOnly: engramOnly.slice(0, 20),
|
|
263
|
+
fileOnly: fileOnly.slice(0, 20),
|
|
264
|
+
overlap: bothHave.slice(0, 10),
|
|
265
|
+
briefing: briefing.summary,
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
// POST /v1/ingest/realtime — Real-time memory extraction from conversation text
|
|
269
|
+
// Send a message or conversation snippet, get memories extracted and stored instantly
|
|
270
|
+
route('POST', '/v1/ingest/realtime', async (req, res, vault) => {
|
|
271
|
+
const body = JSON.parse(await readBody(req));
|
|
272
|
+
const text = body.text ?? '';
|
|
273
|
+
const geminiKey = process.env.GEMINI_API_KEY ?? process.env.ENGRAM_LLM_API_KEY;
|
|
274
|
+
if (!text) {
|
|
275
|
+
return error(res, 400, 'text is required');
|
|
276
|
+
}
|
|
277
|
+
if (!geminiKey) {
|
|
278
|
+
// Fallback: store as single memory using rule-based extraction
|
|
279
|
+
const { extract } = await import('./extract.js');
|
|
280
|
+
const extracted = extract(text);
|
|
281
|
+
const mem = await vault.remember({
|
|
282
|
+
content: text.slice(0, 500),
|
|
283
|
+
type: 'episodic',
|
|
284
|
+
entities: extracted.entities,
|
|
285
|
+
topics: extracted.topics,
|
|
286
|
+
salience: extracted.suggestedSalience,
|
|
287
|
+
source: { type: 'conversation' },
|
|
288
|
+
});
|
|
289
|
+
return json(res, 200, { created: 1, memories: [{ id: mem.id, content: mem.content }] });
|
|
290
|
+
}
|
|
291
|
+
// LLM-powered extraction
|
|
292
|
+
const prompt = `You are a memory extraction engine for an AI agent. Analyze this conversation segment and extract structured memories worth keeping long-term.
|
|
293
|
+
|
|
294
|
+
CONVERSATION:
|
|
295
|
+
${text}
|
|
296
|
+
|
|
297
|
+
Extract memories that would be valuable to recall days or weeks from now. For each, provide:
|
|
298
|
+
- content: A clear, standalone statement (should make sense without the conversation)
|
|
299
|
+
- type: "episodic" (specific events), "semantic" (facts/preferences), or "procedural" (how-to/lessons)
|
|
300
|
+
- entities: People, projects, tools, places mentioned
|
|
301
|
+
- topics: Relevant topic tags
|
|
302
|
+
- salience: 0.0-1.0 (how important for future recall?)
|
|
303
|
+
- status: "active" (default), "pending" (if it's a commitment/plan not yet done)
|
|
304
|
+
|
|
305
|
+
Be SELECTIVE. Only extract what matters. Skip small talk and trivial exchanges.
|
|
306
|
+
|
|
307
|
+
Respond as JSON:
|
|
308
|
+
{"memories": [{"content": "...", "type": "...", "entities": ["..."], "topics": ["..."], "salience": 0.0-1.0, "status": "active|pending"}]}`;
|
|
309
|
+
try {
|
|
310
|
+
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${geminiKey}`, {
|
|
311
|
+
method: 'POST',
|
|
312
|
+
headers: { 'Content-Type': 'application/json' },
|
|
313
|
+
body: JSON.stringify({
|
|
314
|
+
contents: [{ parts: [{ text: prompt }] }],
|
|
315
|
+
generationConfig: { responseMimeType: 'application/json', maxOutputTokens: 2048 },
|
|
316
|
+
}),
|
|
317
|
+
});
|
|
318
|
+
if (!response.ok) {
|
|
319
|
+
return error(res, 502, `LLM extraction failed: ${response.status}`);
|
|
320
|
+
}
|
|
321
|
+
const data = await response.json();
|
|
322
|
+
const llmText = data.candidates?.[0]?.content?.parts?.[0]?.text ?? '{}';
|
|
323
|
+
const parsed = JSON.parse(llmText);
|
|
324
|
+
const created = [];
|
|
325
|
+
for (const mem of parsed.memories ?? []) {
|
|
326
|
+
if (mem.salience < 0.2)
|
|
327
|
+
continue;
|
|
328
|
+
// Security: never store secrets
|
|
329
|
+
if (/(?:sk-|api[_-]?key|password|token|secret)[:\s=]+\S{10,}/i.test(mem.content))
|
|
330
|
+
continue;
|
|
331
|
+
if (/AIza[a-zA-Z0-9_-]{30,}/.test(mem.content))
|
|
332
|
+
continue;
|
|
333
|
+
const stored = await vault.remember({
|
|
334
|
+
content: mem.content,
|
|
335
|
+
type: mem.type ?? 'episodic',
|
|
336
|
+
entities: mem.entities ?? [],
|
|
337
|
+
topics: [...(mem.topics ?? []), 'realtime'],
|
|
338
|
+
salience: mem.salience ?? 0.5,
|
|
339
|
+
status: mem.status ?? 'active',
|
|
340
|
+
source: { type: 'conversation' },
|
|
341
|
+
});
|
|
342
|
+
created.push({ id: stored.id, content: stored.content });
|
|
343
|
+
}
|
|
344
|
+
json(res, 200, { created: created.length, memories: created });
|
|
345
|
+
}
|
|
346
|
+
catch (err) {
|
|
347
|
+
error(res, 500, `Extraction error: ${err.message}`);
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
// GET /v1/contradictions — list unresolved contradictions
|
|
351
|
+
route('GET', '/v1/contradictions', (req, res, vault) => {
|
|
352
|
+
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
353
|
+
const limit = parseInt(url.searchParams.get('limit') ?? '50', 10);
|
|
354
|
+
const contradictions = vault.contradictions(limit);
|
|
355
|
+
json(res, 200, { contradictions, count: contradictions.length });
|
|
356
|
+
});
|
|
357
|
+
// GET /health — health check
|
|
358
|
+
route('GET', '/health', (req, res) => {
|
|
359
|
+
json(res, 200, { status: 'ok', version: '0.1.0', timestamp: new Date().toISOString() });
|
|
360
|
+
});
|
|
361
|
+
// ============================================================
|
|
362
|
+
// Server
|
|
363
|
+
// ============================================================
|
|
364
|
+
export function createEngramServer(config) {
|
|
365
|
+
const preferredPort = config.port ?? 3800;
|
|
366
|
+
const host = config.host ?? '127.0.0.1';
|
|
367
|
+
// Optional auth token for single-tenant mode (set ENGRAM_AUTH_TOKEN to enable)
|
|
368
|
+
const authToken = process.env.ENGRAM_AUTH_TOKEN;
|
|
369
|
+
function resolveVault(req) {
|
|
370
|
+
// Single-tenant mode
|
|
371
|
+
if (config.defaultVault) {
|
|
372
|
+
// If auth token is set, enforce it
|
|
373
|
+
if (authToken) {
|
|
374
|
+
const authHeader = req.headers.authorization;
|
|
375
|
+
if (!authHeader?.startsWith('Bearer ') || authHeader.slice(7) !== authToken) {
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return getOrCreateVault(config.defaultVault);
|
|
380
|
+
}
|
|
381
|
+
// Multi-tenant: resolve from Authorization header
|
|
382
|
+
const authHeader = req.headers.authorization;
|
|
383
|
+
if (!authHeader?.startsWith('Bearer '))
|
|
384
|
+
return null;
|
|
385
|
+
const apiKey = authHeader.slice(7);
|
|
386
|
+
const vaultConfig = config.vaults[apiKey];
|
|
387
|
+
if (!vaultConfig)
|
|
388
|
+
return null;
|
|
389
|
+
return getOrCreateVault(vaultConfig);
|
|
390
|
+
}
|
|
391
|
+
const server = createServer(async (req, res) => {
|
|
392
|
+
// CORS — restrict to localhost by default, configurable via ENGRAM_CORS_ORIGIN
|
|
393
|
+
const allowedOrigin = process.env.ENGRAM_CORS_ORIGIN ?? 'http://localhost:*';
|
|
394
|
+
const requestOrigin = req.headers.origin ?? '';
|
|
395
|
+
if (allowedOrigin === '*' || requestOrigin.startsWith('http://localhost') || requestOrigin.startsWith('http://127.0.0.1')) {
|
|
396
|
+
res.setHeader('Access-Control-Allow-Origin', requestOrigin || 'http://localhost');
|
|
397
|
+
}
|
|
398
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
|
|
399
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
400
|
+
if (req.method === 'OPTIONS') {
|
|
401
|
+
res.writeHead(204);
|
|
402
|
+
res.end();
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
406
|
+
const pathname = url.pathname;
|
|
407
|
+
// Match route
|
|
408
|
+
for (const r of routes) {
|
|
409
|
+
if (req.method !== r.method)
|
|
410
|
+
continue;
|
|
411
|
+
const match = pathname.match(r.pattern);
|
|
412
|
+
if (!match)
|
|
413
|
+
continue;
|
|
414
|
+
// Extract params
|
|
415
|
+
const params = {};
|
|
416
|
+
r.paramNames.forEach((name, i) => { params[name] = match[i + 1]; });
|
|
417
|
+
// Health check doesn't need a vault
|
|
418
|
+
if (pathname === '/health') {
|
|
419
|
+
try {
|
|
420
|
+
await r.handler(req, res, null, params);
|
|
421
|
+
}
|
|
422
|
+
catch (err) {
|
|
423
|
+
error(res, 500, err.message ?? 'Internal server error');
|
|
424
|
+
}
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
// Resolve vault
|
|
428
|
+
const vault = resolveVault(req);
|
|
429
|
+
if (!vault) {
|
|
430
|
+
error(res, 401, 'Invalid or missing API key');
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
try {
|
|
434
|
+
await r.handler(req, res, vault, params);
|
|
435
|
+
}
|
|
436
|
+
catch (err) {
|
|
437
|
+
console.error(`Error handling ${req.method} ${pathname}:`, err);
|
|
438
|
+
error(res, 500, err.message ?? 'Internal server error');
|
|
439
|
+
}
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
error(res, 404, `Not found: ${req.method} ${pathname}`);
|
|
443
|
+
});
|
|
444
|
+
return {
|
|
445
|
+
listen: () => new Promise((resolve) => {
|
|
446
|
+
server.listen(preferredPort, host, () => {
|
|
447
|
+
const addr = server.address();
|
|
448
|
+
console.log(`🧠 Engram API server listening on http://${host}:${addr.port}`);
|
|
449
|
+
resolve();
|
|
450
|
+
});
|
|
451
|
+
}),
|
|
452
|
+
close: async () => {
|
|
453
|
+
// Flush and close all vaults (await pending embeddings)
|
|
454
|
+
const closePromises = [...vaultCache.values()].map(v => v.close());
|
|
455
|
+
await Promise.allSettled(closePromises);
|
|
456
|
+
vaultCache.clear();
|
|
457
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
458
|
+
},
|
|
459
|
+
server,
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
// ============================================================
|
|
463
|
+
// CLI entry point
|
|
464
|
+
// ============================================================
|
|
465
|
+
if (process.argv[1]?.endsWith('server.ts') || process.argv[1]?.endsWith('server.js')) {
|
|
466
|
+
const owner = process.env.ENGRAM_OWNER ?? 'default';
|
|
467
|
+
const dbPath = process.env.ENGRAM_DB_PATH;
|
|
468
|
+
const port = parseInt(process.env.ENGRAM_PORT ?? '0', 10);
|
|
469
|
+
const host = process.env.ENGRAM_HOST ?? '127.0.0.1';
|
|
470
|
+
const llmProvider = process.env.ENGRAM_LLM_PROVIDER;
|
|
471
|
+
const llmApiKey = process.env.ENGRAM_LLM_API_KEY ?? (llmProvider === 'gemini' ? process.env.GEMINI_API_KEY : undefined);
|
|
472
|
+
const llmModel = process.env.ENGRAM_LLM_MODEL;
|
|
473
|
+
const vaultConfig = {
|
|
474
|
+
owner,
|
|
475
|
+
...(dbPath ? { dbPath } : {}),
|
|
476
|
+
...(llmProvider && llmApiKey ? {
|
|
477
|
+
llm: { provider: llmProvider, apiKey: llmApiKey, model: llmModel },
|
|
478
|
+
} : {}),
|
|
479
|
+
};
|
|
480
|
+
const srv = createEngramServer({
|
|
481
|
+
port,
|
|
482
|
+
host,
|
|
483
|
+
vaults: {},
|
|
484
|
+
defaultVault: vaultConfig,
|
|
485
|
+
});
|
|
486
|
+
srv.listen().then(() => {
|
|
487
|
+
console.log(`Vault owner: ${owner}`);
|
|
488
|
+
console.log(`Database: ${dbPath ?? `engram-${owner}.db`}`);
|
|
489
|
+
if (llmProvider)
|
|
490
|
+
console.log(`LLM: ${llmProvider} (${llmModel ?? 'default'})`);
|
|
491
|
+
console.log('\nEndpoints:');
|
|
492
|
+
console.log(' POST /v1/memories — Store a memory');
|
|
493
|
+
console.log(' GET /v1/memories/recall — Recall memories');
|
|
494
|
+
console.log(' POST /v1/memories/recall — Recall (complex query)');
|
|
495
|
+
console.log(' DELETE /v1/memories/:id — Forget a memory');
|
|
496
|
+
console.log(' GET /v1/memories/:id/neighbors — Graph traversal');
|
|
497
|
+
console.log(' POST /v1/connections — Connect memories');
|
|
498
|
+
console.log(' POST /v1/consolidate — Run consolidation');
|
|
499
|
+
console.log(' GET /v1/entities — List entities');
|
|
500
|
+
console.log(' GET /v1/stats — Vault statistics');
|
|
501
|
+
console.log(' POST /v1/export — Export vault');
|
|
502
|
+
console.log(' GET /health — Health check');
|
|
503
|
+
});
|
|
504
|
+
// Graceful shutdown
|
|
505
|
+
process.on('SIGINT', async () => {
|
|
506
|
+
console.log('\nShutting down...');
|
|
507
|
+
await srv.close();
|
|
508
|
+
process.exit(0);
|
|
509
|
+
});
|
|
510
|
+
process.on('SIGTERM', async () => {
|
|
511
|
+
await srv.close();
|
|
512
|
+
process.exit(0);
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { Memory, Edge, Entity, RememberParsed } from './types.js';
|
|
2
|
+
export declare class MemoryStore {
|
|
3
|
+
private db;
|
|
4
|
+
private vecEnabled;
|
|
5
|
+
private embeddingDimensions;
|
|
6
|
+
constructor(dbPath: string, embeddingDimensions?: number);
|
|
7
|
+
private migrate;
|
|
8
|
+
createMemory(input: RememberParsed): Memory;
|
|
9
|
+
getMemory(id: string): Memory | null;
|
|
10
|
+
/** Read a memory without updating access stats (for graph traversal, activation spreading) */
|
|
11
|
+
getMemoryDirect(id: string): Memory | null;
|
|
12
|
+
/** Get all memories by a list of IDs without updating access stats */
|
|
13
|
+
getMemoriesDirect(ids: string[]): Memory[];
|
|
14
|
+
updateMemory(id: string, updates: Partial<Pick<Memory, 'content' | 'summary' | 'salience' | 'confidence' | 'entities' | 'topics'>>): void;
|
|
15
|
+
/** Update a memory's status (active, pending, fulfilled, superseded, archived) */
|
|
16
|
+
updateStatus(id: string, status: string): void;
|
|
17
|
+
deleteMemory(id: string): void;
|
|
18
|
+
/** Get recent memories, ordered by creation time */
|
|
19
|
+
getRecent(limit?: number): Memory[];
|
|
20
|
+
/** Get memories by entity */
|
|
21
|
+
getByEntity(entityName: string, limit?: number): Memory[];
|
|
22
|
+
/** Get memories by topic */
|
|
23
|
+
getByTopic(topic: string, limit?: number): Memory[];
|
|
24
|
+
/** Get memories by status */
|
|
25
|
+
getByStatus(status: string, limit?: number): Memory[];
|
|
26
|
+
/** Get memories by type */
|
|
27
|
+
getByType(type: string, limit?: number): Memory[];
|
|
28
|
+
/** Full-text search on content */
|
|
29
|
+
search(query: string, limit?: number): Memory[];
|
|
30
|
+
/** Get all memories (for consolidation) */
|
|
31
|
+
getEpisodicSince(since: string, limit?: number): Memory[];
|
|
32
|
+
/** Get memories below stability threshold (candidates for archival) */
|
|
33
|
+
getDecayedMemories(threshold?: number): Memory[];
|
|
34
|
+
/** Count memories by type */
|
|
35
|
+
getStats(): {
|
|
36
|
+
total: number;
|
|
37
|
+
episodic: number;
|
|
38
|
+
semantic: number;
|
|
39
|
+
procedural: number;
|
|
40
|
+
entities: number;
|
|
41
|
+
};
|
|
42
|
+
createEdge(sourceId: string, targetId: string, type: Edge['type'] | string, strength?: number): Edge;
|
|
43
|
+
getEdgesFrom(memoryId: string): Edge[];
|
|
44
|
+
getEdgesTo(memoryId: string): Edge[];
|
|
45
|
+
/** Get all edges connected to a memory (both directions) */
|
|
46
|
+
getEdgesBidirectional(memoryId: string): Edge[];
|
|
47
|
+
/** Batch: get all edges for a set of memory IDs (both directions) */
|
|
48
|
+
getEdgesForMemories(memoryIds: string[]): Edge[];
|
|
49
|
+
/** Get memories that share entities with the given memory */
|
|
50
|
+
getCoEntityMemories(memoryId: string, limit?: number): Array<{
|
|
51
|
+
memory: Memory;
|
|
52
|
+
sharedEntities: string[];
|
|
53
|
+
}>;
|
|
54
|
+
getNeighbors(memoryId: string, depth?: number): Memory[];
|
|
55
|
+
upsertEntity(name: string, type?: string): Entity;
|
|
56
|
+
getEntity(name: string): Entity | null;
|
|
57
|
+
getAllEntities(): Entity[];
|
|
58
|
+
/** Store an embedding for a memory */
|
|
59
|
+
storeEmbedding(memoryId: string, embedding: number[]): void;
|
|
60
|
+
/** Find nearest neighbors by embedding vector */
|
|
61
|
+
searchByVector(embedding: number[], limit?: number): Array<{
|
|
62
|
+
memoryId: string;
|
|
63
|
+
distance: number;
|
|
64
|
+
}>;
|
|
65
|
+
/** Check if vector search is available */
|
|
66
|
+
hasVectorSearch(): boolean;
|
|
67
|
+
/** Get the stored embedding for a memory (for dedup checks) */
|
|
68
|
+
getEmbedding(memoryId: string): number[] | null;
|
|
69
|
+
/** Find memories with very high semantic similarity (for dedup) */
|
|
70
|
+
findSimilar(embedding: number[], threshold?: number, limit?: number): Array<{
|
|
71
|
+
memoryId: string;
|
|
72
|
+
distance: number;
|
|
73
|
+
similarity: number;
|
|
74
|
+
}>;
|
|
75
|
+
/** Apply time-based decay to all memories */
|
|
76
|
+
applyDecay(halfLifeHours?: number): number;
|
|
77
|
+
exportAll(): {
|
|
78
|
+
memories: Memory[];
|
|
79
|
+
edges: Edge[];
|
|
80
|
+
entities: Entity[];
|
|
81
|
+
};
|
|
82
|
+
private rowToMemory;
|
|
83
|
+
private rowToEdge;
|
|
84
|
+
private rowToEntity;
|
|
85
|
+
close(): void;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|