@199-bio/engram 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/dist/index.js ADDED
@@ -0,0 +1,473 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Engram - High-quality personal memory for AI assistants
4
+ *
5
+ * Local-first MCP server with ColBERT + BM25 hybrid search
6
+ * and a lightweight knowledge graph.
7
+ */
8
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
9
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
10
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
11
+ import path from "path";
12
+ import os from "os";
13
+ import { EngramDatabase } from "./storage/database.js";
14
+ import { KnowledgeGraph } from "./graph/knowledge-graph.js";
15
+ import { createRetriever } from "./retrieval/colbert.js";
16
+ import { HybridSearch } from "./retrieval/hybrid.js";
17
+ // ============ Configuration ============
18
+ const DB_PATH = process.env.ENGRAM_DB_PATH
19
+ ? path.resolve(process.env.ENGRAM_DB_PATH.replace("~", os.homedir()))
20
+ : path.join(os.homedir(), ".engram");
21
+ const DB_FILE = path.join(DB_PATH, "engram.db");
22
+ // ============ Initialize Components ============
23
+ let db;
24
+ let graph;
25
+ let search;
26
+ async function initialize() {
27
+ console.error(`[Engram] Initializing with database at ${DB_FILE}`);
28
+ db = new EngramDatabase(DB_FILE);
29
+ graph = new KnowledgeGraph(db);
30
+ const retriever = await createRetriever(DB_PATH);
31
+ search = new HybridSearch(db, graph, retriever);
32
+ // Rebuild index with existing memories
33
+ const stats = db.getStats();
34
+ if (stats.memories > 0) {
35
+ console.error(`[Engram] Indexing ${stats.memories} existing memories...`);
36
+ await search.rebuildIndex();
37
+ }
38
+ console.error(`[Engram] Ready. Stats: ${JSON.stringify(stats)}`);
39
+ }
40
+ // ============ MCP Server ============
41
+ const server = new Server({
42
+ name: "engram",
43
+ version: "0.1.0",
44
+ }, {
45
+ capabilities: {
46
+ tools: {},
47
+ },
48
+ });
49
+ // Tool definitions
50
+ const TOOLS = [
51
+ {
52
+ name: "remember",
53
+ description: "Store a new memory. Automatically extracts entities and relationships for the knowledge graph.",
54
+ inputSchema: {
55
+ type: "object",
56
+ properties: {
57
+ content: {
58
+ type: "string",
59
+ description: "The memory content to store",
60
+ },
61
+ source: {
62
+ type: "string",
63
+ description: "Source of the memory (e.g., 'conversation', 'note', 'import')",
64
+ default: "conversation",
65
+ },
66
+ importance: {
67
+ type: "number",
68
+ description: "Importance score from 0 to 1 (higher = more important)",
69
+ minimum: 0,
70
+ maximum: 1,
71
+ default: 0.5,
72
+ },
73
+ },
74
+ required: ["content"],
75
+ },
76
+ },
77
+ {
78
+ name: "recall",
79
+ description: "Retrieve relevant memories using hybrid search (BM25 keywords + semantic + knowledge graph). Returns the most relevant memories for a query.",
80
+ inputSchema: {
81
+ type: "object",
82
+ properties: {
83
+ query: {
84
+ type: "string",
85
+ description: "What to search for - can be a question, keywords, or natural language",
86
+ },
87
+ limit: {
88
+ type: "number",
89
+ description: "Maximum number of memories to return",
90
+ default: 5,
91
+ },
92
+ include_graph: {
93
+ type: "boolean",
94
+ description: "Whether to expand search using knowledge graph connections",
95
+ default: true,
96
+ },
97
+ },
98
+ required: ["query"],
99
+ },
100
+ },
101
+ {
102
+ name: "forget",
103
+ description: "Remove a specific memory by its ID",
104
+ inputSchema: {
105
+ type: "object",
106
+ properties: {
107
+ id: {
108
+ type: "string",
109
+ description: "The memory ID to remove",
110
+ },
111
+ },
112
+ required: ["id"],
113
+ },
114
+ },
115
+ {
116
+ name: "create_entity",
117
+ description: "Create a new entity in the knowledge graph (person, place, concept, etc.)",
118
+ inputSchema: {
119
+ type: "object",
120
+ properties: {
121
+ name: {
122
+ type: "string",
123
+ description: "Entity name (e.g., 'John', 'Paris', 'Machine Learning')",
124
+ },
125
+ type: {
126
+ type: "string",
127
+ enum: ["person", "place", "concept", "event", "organization"],
128
+ description: "Type of entity",
129
+ },
130
+ },
131
+ required: ["name", "type"],
132
+ },
133
+ },
134
+ {
135
+ name: "observe",
136
+ description: "Add an observation or fact about an entity",
137
+ inputSchema: {
138
+ type: "object",
139
+ properties: {
140
+ entity: {
141
+ type: "string",
142
+ description: "Entity name to add observation to",
143
+ },
144
+ observation: {
145
+ type: "string",
146
+ description: "The fact or observation to record",
147
+ },
148
+ confidence: {
149
+ type: "number",
150
+ description: "Confidence in this observation (0-1)",
151
+ default: 1.0,
152
+ },
153
+ },
154
+ required: ["entity", "observation"],
155
+ },
156
+ },
157
+ {
158
+ name: "relate",
159
+ description: "Create a relationship between two entities in the knowledge graph",
160
+ inputSchema: {
161
+ type: "object",
162
+ properties: {
163
+ from: {
164
+ type: "string",
165
+ description: "Source entity name",
166
+ },
167
+ to: {
168
+ type: "string",
169
+ description: "Target entity name",
170
+ },
171
+ relation: {
172
+ type: "string",
173
+ description: "Type of relationship (e.g., 'sibling', 'works_at', 'knows', 'located_in')",
174
+ },
175
+ },
176
+ required: ["from", "to", "relation"],
177
+ },
178
+ },
179
+ {
180
+ name: "query_entity",
181
+ description: "Get detailed information about an entity including all observations and relationships",
182
+ inputSchema: {
183
+ type: "object",
184
+ properties: {
185
+ entity: {
186
+ type: "string",
187
+ description: "Entity name to query",
188
+ },
189
+ },
190
+ required: ["entity"],
191
+ },
192
+ },
193
+ {
194
+ name: "list_entities",
195
+ description: "List all entities, optionally filtered by type",
196
+ inputSchema: {
197
+ type: "object",
198
+ properties: {
199
+ type: {
200
+ type: "string",
201
+ enum: ["person", "place", "concept", "event", "organization"],
202
+ description: "Filter by entity type (optional)",
203
+ },
204
+ limit: {
205
+ type: "number",
206
+ description: "Maximum number of entities to return",
207
+ default: 50,
208
+ },
209
+ },
210
+ },
211
+ },
212
+ {
213
+ name: "stats",
214
+ description: "Get memory statistics (counts of memories, entities, relations, observations)",
215
+ inputSchema: {
216
+ type: "object",
217
+ properties: {},
218
+ },
219
+ },
220
+ ];
221
+ // List available tools
222
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
223
+ tools: TOOLS,
224
+ }));
225
+ // Handle tool calls
226
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
227
+ const { name, arguments: args } = request.params;
228
+ try {
229
+ switch (name) {
230
+ case "remember": {
231
+ const { content, source = "conversation", importance = 0.5 } = args;
232
+ // Create memory
233
+ const memory = db.createMemory(content, source, importance);
234
+ // Index for semantic search
235
+ await search.indexMemory(memory);
236
+ // Extract and store entities/relationships
237
+ const { entities, observations } = graph.extractAndStore(content, memory.id);
238
+ return {
239
+ content: [
240
+ {
241
+ type: "text",
242
+ text: JSON.stringify({
243
+ success: true,
244
+ memory_id: memory.id,
245
+ entities_extracted: entities.map((e) => e.name),
246
+ observations_created: observations.length,
247
+ }, null, 2),
248
+ },
249
+ ],
250
+ };
251
+ }
252
+ case "recall": {
253
+ const { query, limit = 5, include_graph = true } = args;
254
+ const results = await search.search(query, {
255
+ limit,
256
+ includeGraph: include_graph,
257
+ });
258
+ const formatted = results.map((r) => ({
259
+ id: r.memory.id,
260
+ content: r.memory.content,
261
+ source: r.memory.source,
262
+ timestamp: r.memory.timestamp.toISOString(),
263
+ relevance_score: r.score.toFixed(4),
264
+ matched_via: Object.entries(r.sources)
265
+ .filter(([, v]) => v !== undefined)
266
+ .map(([k]) => k)
267
+ .join(", "),
268
+ }));
269
+ return {
270
+ content: [
271
+ {
272
+ type: "text",
273
+ text: JSON.stringify({
274
+ query,
275
+ results: formatted,
276
+ count: formatted.length,
277
+ }, null, 2),
278
+ },
279
+ ],
280
+ };
281
+ }
282
+ case "forget": {
283
+ const { id } = args;
284
+ const memory = db.getMemory(id);
285
+ if (!memory) {
286
+ return {
287
+ content: [
288
+ {
289
+ type: "text",
290
+ text: JSON.stringify({ success: false, error: "Memory not found" }),
291
+ },
292
+ ],
293
+ };
294
+ }
295
+ // Remove from semantic index
296
+ await search.removeFromIndex(id);
297
+ // Delete from database
298
+ db.deleteMemory(id);
299
+ return {
300
+ content: [
301
+ {
302
+ type: "text",
303
+ text: JSON.stringify({ success: true, deleted_id: id }),
304
+ },
305
+ ],
306
+ };
307
+ }
308
+ case "create_entity": {
309
+ const { name: entityName, type } = args;
310
+ const entity = graph.getOrCreateEntity(entityName, type);
311
+ return {
312
+ content: [
313
+ {
314
+ type: "text",
315
+ text: JSON.stringify({
316
+ success: true,
317
+ entity: {
318
+ id: entity.id,
319
+ name: entity.name,
320
+ type: entity.type,
321
+ },
322
+ }, null, 2),
323
+ },
324
+ ],
325
+ };
326
+ }
327
+ case "observe": {
328
+ const { entity: entityName, observation, confidence = 1.0 } = args;
329
+ // Ensure entity exists
330
+ const entity = graph.getOrCreateEntity(entityName, "person");
331
+ // Add observation
332
+ const obs = graph.addObservation(entity.id, observation, undefined, confidence);
333
+ return {
334
+ content: [
335
+ {
336
+ type: "text",
337
+ text: JSON.stringify({
338
+ success: true,
339
+ entity: entity.name,
340
+ observation_id: obs.id,
341
+ }, null, 2),
342
+ },
343
+ ],
344
+ };
345
+ }
346
+ case "relate": {
347
+ const { from, to, relation } = args;
348
+ // Ensure both entities exist
349
+ const fromEntity = graph.getOrCreateEntity(from, "person");
350
+ const toEntity = graph.getOrCreateEntity(to, "person");
351
+ // Create relation
352
+ const rel = graph.relate(fromEntity.id, toEntity.id, relation);
353
+ return {
354
+ content: [
355
+ {
356
+ type: "text",
357
+ text: JSON.stringify({
358
+ success: true,
359
+ relation: {
360
+ id: rel.id,
361
+ from: fromEntity.name,
362
+ to: toEntity.name,
363
+ type: rel.type,
364
+ },
365
+ }, null, 2),
366
+ },
367
+ ],
368
+ };
369
+ }
370
+ case "query_entity": {
371
+ const { entity: entityName } = args;
372
+ const details = graph.getEntityDetails(entityName);
373
+ if (!details) {
374
+ return {
375
+ content: [
376
+ {
377
+ type: "text",
378
+ text: JSON.stringify({ success: false, error: "Entity not found" }),
379
+ },
380
+ ],
381
+ };
382
+ }
383
+ return {
384
+ content: [
385
+ {
386
+ type: "text",
387
+ text: JSON.stringify({
388
+ entity: {
389
+ id: details.id,
390
+ name: details.name,
391
+ type: details.type,
392
+ created_at: details.created_at.toISOString(),
393
+ },
394
+ observations: details.observations.map((o) => ({
395
+ content: o.content.substring(0, 200) + (o.content.length > 200 ? "..." : ""),
396
+ confidence: o.confidence,
397
+ valid_from: o.valid_from.toISOString(),
398
+ })),
399
+ relations_from: details.relationsFrom.map((r) => ({
400
+ type: r.type,
401
+ to: r.targetEntity.name,
402
+ })),
403
+ relations_to: details.relationsTo.map((r) => ({
404
+ type: r.type,
405
+ from: r.sourceEntity.name,
406
+ })),
407
+ }, null, 2),
408
+ },
409
+ ],
410
+ };
411
+ }
412
+ case "list_entities": {
413
+ const { type, limit = 50 } = args;
414
+ const entities = graph.listEntities(type, limit);
415
+ return {
416
+ content: [
417
+ {
418
+ type: "text",
419
+ text: JSON.stringify({
420
+ entities: entities.map((e) => ({
421
+ id: e.id,
422
+ name: e.name,
423
+ type: e.type,
424
+ })),
425
+ count: entities.length,
426
+ }, null, 2),
427
+ },
428
+ ],
429
+ };
430
+ }
431
+ case "stats": {
432
+ const stats = db.getStats();
433
+ return {
434
+ content: [
435
+ {
436
+ type: "text",
437
+ text: JSON.stringify({
438
+ ...stats,
439
+ database_path: DB_FILE,
440
+ }, null, 2),
441
+ },
442
+ ],
443
+ };
444
+ }
445
+ default:
446
+ throw new Error(`Unknown tool: ${name}`);
447
+ }
448
+ }
449
+ catch (error) {
450
+ const message = error instanceof Error ? error.message : String(error);
451
+ return {
452
+ content: [
453
+ {
454
+ type: "text",
455
+ text: JSON.stringify({ success: false, error: message }),
456
+ },
457
+ ],
458
+ isError: true,
459
+ };
460
+ }
461
+ });
462
+ // ============ Main ============
463
+ async function main() {
464
+ await initialize();
465
+ const transport = new StdioServerTransport();
466
+ await server.connect(transport);
467
+ console.error("[Engram] MCP server running on stdio");
468
+ }
469
+ main().catch((error) => {
470
+ console.error("[Engram] Fatal error:", error);
471
+ process.exit(1);
472
+ });
473
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colbert.d.ts","sourceRoot":"","sources":["../../src/retrieval/colbert.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAUD,qBAAa,gBAAgB;IAaf,OAAO,CAAC,SAAS;IAZ7B,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,eAAe,CAGR;IACf,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,MAAM,CAAM;gBAEA,SAAS,EAAE,MAAM;IAMrC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoC5B,OAAO,CAAC,UAAU;YAuBJ,IAAI;IAclB;;OAEG;IACG,KAAK,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAYhF;;OAEG;IACG,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAY9E;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,GAAE,MAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAUpE;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,CAAC,GAAE,MAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAW3F;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAYzE;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAS9B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAa5B;AAED;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAAoC;IAE/C,KAAK,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAO1E,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAIxE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,GAAE,MAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAwB9D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,CAAC,GAAE,MAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAcrF,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAS1E;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,eAAe,CAAC,CAepG"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hybrid.d.ts","sourceRoot":"","sources":["../../src/retrieval/hybrid.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAA0B,MAAM,cAAc,CAAC;AAGzF,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,qBAAa,YAAY;IAErB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,SAAS;gBAFT,EAAE,EAAE,cAAc,EAClB,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,gBAAgB,GAAG,eAAe;IAGvD;;OAEG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;KACjB,GACL,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAyGhC;;OAEG;YACW,UAAU;IASxB;;OAEG;YACW,cAAc;IAS5B;;OAEG;YACW,WAAW;IAezB;;OAEG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOhD;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAYhD;;OAEG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGvD"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/retrieval/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/storage/database.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC"}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@199-bio/engram",
3
+ "version": "0.1.0",
4
+ "description": "Give Claude a perfect memory. Local-first MCP server with hybrid search.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "engram": "./dist/index.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsc --watch",
14
+ "start": "node dist/index.js",
15
+ "test": "vitest",
16
+ "test:run": "vitest run",
17
+ "download-models": "node scripts/download-models.js",
18
+ "lint": "eslint src/",
19
+ "format": "prettier --write src/"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/199-biotechnologies/engram.git"
24
+ },
25
+ "keywords": [
26
+ "mcp",
27
+ "memory",
28
+ "ai",
29
+ "claude",
30
+ "colbert",
31
+ "rag",
32
+ "knowledge-graph",
33
+ "semantic-search",
34
+ "local-first"
35
+ ],
36
+ "author": {
37
+ "name": "Boris Djordjevic",
38
+ "url": "https://199bio.com"
39
+ },
40
+ "license": "MIT",
41
+ "bugs": {
42
+ "url": "https://github.com/199-biotechnologies/engram/issues"
43
+ },
44
+ "homepage": "https://github.com/199-biotechnologies/engram#readme",
45
+ "engines": {
46
+ "node": ">=18.0.0"
47
+ },
48
+ "dependencies": {
49
+ "@modelcontextprotocol/sdk": "^1.0.0",
50
+ "better-sqlite3": "^11.0.0",
51
+ "chrono-node": "^2.7.0",
52
+ "uuid": "^10.0.0",
53
+ "zod": "^3.23.0"
54
+ },
55
+ "devDependencies": {
56
+ "@types/better-sqlite3": "^7.6.0",
57
+ "@types/node": "^22.0.0",
58
+ "@types/uuid": "^10.0.0",
59
+ "typescript": "^5.6.0",
60
+ "vitest": "^2.0.0"
61
+ }
62
+ }