@199-bio/engram 0.5.0 → 0.6.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 +205 -46
- package/dist/consolidation/consolidator.d.ts.map +1 -1
- package/dist/index.js +89 -4
- package/dist/retrieval/hybrid.d.ts.map +1 -1
- package/dist/storage/database.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/consolidation/consolidator.ts +291 -24
- package/src/index.ts +96 -3
- package/src/retrieval/hybrid.ts +83 -7
- package/src/storage/database.ts +198 -9
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Give your AI a perfect memory.**
|
|
4
4
|
|
|
5
|
-
Engram remembers everything you tell it—names, relationships, preferences, conversations—and recalls exactly what's relevant when you need it.
|
|
5
|
+
Engram remembers everything you tell it—names, relationships, preferences, conversations—and recalls exactly what's relevant when you need it. Memories naturally fade over time unless they're important or frequently accessed, just like real memory.
|
|
6
6
|
|
|
7
7
|
Works with any LLM that supports MCP (Model Context Protocol)—Claude, GPT, Gemini, local models, and more.
|
|
8
8
|
|
|
@@ -43,7 +43,10 @@ npm install -g @199-bio/engram
|
|
|
43
43
|
"mcpServers": {
|
|
44
44
|
"engram": {
|
|
45
45
|
"command": "npx",
|
|
46
|
-
"args": ["-y", "@199-bio/engram"]
|
|
46
|
+
"args": ["-y", "@199-bio/engram"],
|
|
47
|
+
"env": {
|
|
48
|
+
"ANTHROPIC_API_KEY": "sk-ant-..."
|
|
49
|
+
}
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
52
|
}
|
|
@@ -61,6 +64,108 @@ That's it. Your AI now has memory.
|
|
|
61
64
|
|
|
62
65
|
---
|
|
63
66
|
|
|
67
|
+
## How Memory Works
|
|
68
|
+
|
|
69
|
+
Engram models memory like your brain does—important things stick, unimportant things fade, and everything connects.
|
|
70
|
+
|
|
71
|
+
```mermaid
|
|
72
|
+
flowchart LR
|
|
73
|
+
subgraph Input
|
|
74
|
+
A[Your Message] --> B[Remember]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
subgraph Storage
|
|
78
|
+
B --> C[Memory Store]
|
|
79
|
+
B --> D[Knowledge Graph]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
subgraph Retrieval
|
|
83
|
+
E[Your Question] --> F[Recall]
|
|
84
|
+
F --> G[Keyword Search]
|
|
85
|
+
F --> H[Semantic Search]
|
|
86
|
+
F --> I[Graph Traversal]
|
|
87
|
+
G & H & I --> J[Combine Results]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
C --> F
|
|
91
|
+
D --> F
|
|
92
|
+
J --> K[Relevant Memories]
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Three Key Ideas
|
|
96
|
+
|
|
97
|
+
**1. Memories Fade Over Time**
|
|
98
|
+
|
|
99
|
+
Just like real memory, things you haven't thought about recently become harder to recall. But important or emotional memories resist fading.
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
Fresh memory (today) → Easy to recall
|
|
103
|
+
Old but important memory → Still accessible
|
|
104
|
+
Old, trivial memory → Fades away
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**2. Accessing Memories Strengthens Them**
|
|
108
|
+
|
|
109
|
+
Every time a memory is recalled, it becomes stronger and lasts longer. Frequently accessed memories become permanent.
|
|
110
|
+
|
|
111
|
+
**3. Everything Connects**
|
|
112
|
+
|
|
113
|
+
People, places, and things form a web of relationships. When you ask about Sarah, Engram also knows she works at Acme Corp and is leading the Q1 launch.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## The Memory Lifecycle
|
|
118
|
+
|
|
119
|
+
```mermaid
|
|
120
|
+
flowchart TD
|
|
121
|
+
subgraph "1. Capture"
|
|
122
|
+
A[Conversation] --> B[Extract Key Info]
|
|
123
|
+
B --> C[Store Memory]
|
|
124
|
+
B --> D[Create Entities]
|
|
125
|
+
B --> E[Link Relationships]
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
subgraph "2. Search"
|
|
129
|
+
F[Query] --> G[Find by Keywords]
|
|
130
|
+
F --> H[Find by Meaning]
|
|
131
|
+
F --> I[Follow Connections]
|
|
132
|
+
G & H & I --> J[Rank by Relevance + Recency]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
subgraph "3. Consolidate"
|
|
136
|
+
K[Raw Memories] --> L[Compress & Summarize]
|
|
137
|
+
L --> M[Detect Contradictions]
|
|
138
|
+
M --> N[Update Knowledge]
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
C --> F
|
|
142
|
+
J --> K
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Consolidation (Optional)
|
|
146
|
+
|
|
147
|
+
With an API key, Engram can periodically compress old memories into summaries—like how sleep consolidates your memories. This keeps important information while reducing storage.
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Run consolidation manually
|
|
151
|
+
consolidate # Compresses old memories, finds contradictions
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## What Makes It Special
|
|
157
|
+
|
|
158
|
+
| Feature | Why It Matters |
|
|
159
|
+
|---------|----------------|
|
|
160
|
+
| **Hybrid Search** | Finds memories by keywords AND meaning |
|
|
161
|
+
| **Knowledge Graph** | Understands relationships between people, places, things |
|
|
162
|
+
| **Natural Forgetting** | Old, unimportant memories fade; important ones persist |
|
|
163
|
+
| **Strengthening** | Frequently recalled memories become permanent |
|
|
164
|
+
| **Consolidation** | Compresses old memories, detects contradictions |
|
|
165
|
+
| **Fast** | ~50ms to recall, feels instant |
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
64
169
|
## How to Use
|
|
65
170
|
|
|
66
171
|
Just talk naturally. Your AI will remember what matters.
|
|
@@ -72,6 +177,11 @@ Say things like:
|
|
|
72
177
|
- "My anniversary is March 15th"
|
|
73
178
|
- "I prefer morning meetings, never schedule anything before 9am"
|
|
74
179
|
|
|
180
|
+
The AI automatically extracts:
|
|
181
|
+
- **Importance**: Key facts get higher priority
|
|
182
|
+
- **Entities**: People, places, organizations mentioned
|
|
183
|
+
- **Relationships**: How entities connect to each other
|
|
184
|
+
|
|
75
185
|
### Recalling
|
|
76
186
|
|
|
77
187
|
Just ask:
|
|
@@ -79,7 +189,10 @@ Just ask:
|
|
|
79
189
|
- "When is my anniversary?"
|
|
80
190
|
- "What are my meeting preferences?"
|
|
81
191
|
|
|
82
|
-
|
|
192
|
+
Results are ranked by:
|
|
193
|
+
- **Relevance**: How well it matches your question
|
|
194
|
+
- **Recency**: Recent memories surface first
|
|
195
|
+
- **Importance**: High-priority info stays accessible
|
|
83
196
|
|
|
84
197
|
### The Knowledge Graph
|
|
85
198
|
|
|
@@ -95,26 +208,14 @@ This means when you ask about Sarah's work, Engram knows to also surface relevan
|
|
|
95
208
|
|
|
96
209
|
---
|
|
97
210
|
|
|
98
|
-
##
|
|
99
|
-
|
|
100
|
-
| Feature | Why It Matters |
|
|
101
|
-
|---------|----------------|
|
|
102
|
-
| **Hybrid Search** | Finds memories by keywords AND meaning |
|
|
103
|
-
| **Knowledge Graph** | Understands relationships between people, places, things |
|
|
104
|
-
| **100% Local** | Your memories never leave your computer |
|
|
105
|
-
| **No API Keys** | Works offline, no subscriptions |
|
|
106
|
-
| **Fast** | ~50ms to recall, feels instant |
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
|
|
110
|
-
## The Nine Tools
|
|
211
|
+
## The Tools
|
|
111
212
|
|
|
112
213
|
Your AI gets these capabilities:
|
|
113
214
|
|
|
114
215
|
| Tool | What It Does |
|
|
115
216
|
|------|--------------|
|
|
116
|
-
| `remember` | Store something new |
|
|
117
|
-
| `recall` | Find relevant memories |
|
|
217
|
+
| `remember` | Store something new (with importance, emotions, timing) |
|
|
218
|
+
| `recall` | Find relevant memories (ranked by relevance + recency) |
|
|
118
219
|
| `forget` | Remove a memory |
|
|
119
220
|
| `create_entity` | Add a person, place, or concept |
|
|
120
221
|
| `observe` | Note something about an entity |
|
|
@@ -122,6 +223,8 @@ Your AI gets these capabilities:
|
|
|
122
223
|
| `query_entity` | Get everything about someone/something |
|
|
123
224
|
| `list_entities` | See all people, places, etc. |
|
|
124
225
|
| `stats` | Check memory statistics |
|
|
226
|
+
| `consolidate` | Compress old memories, find contradictions |
|
|
227
|
+
| `engram_web` | Launch visual memory browser |
|
|
125
228
|
|
|
126
229
|
---
|
|
127
230
|
|
|
@@ -167,8 +270,8 @@ Claude: Given John's preferences, I'd suggest a late morning slot, maybe 11:30am
|
|
|
167
270
|
**Your memories stay on your machine.**
|
|
168
271
|
|
|
169
272
|
- All data stored locally in `~/.engram/`
|
|
170
|
-
- No
|
|
171
|
-
-
|
|
273
|
+
- No external APIs required for core functionality
|
|
274
|
+
- Consolidation uses Anthropic API (optional, requires key)
|
|
172
275
|
- You own your data completely
|
|
173
276
|
|
|
174
277
|
---
|
|
@@ -176,25 +279,75 @@ Claude: Given John's preferences, I'd suggest a late morning slot, maybe 11:30am
|
|
|
176
279
|
## Technical Details
|
|
177
280
|
|
|
178
281
|
<details>
|
|
179
|
-
<summary>How
|
|
282
|
+
<summary>How Search Works</summary>
|
|
180
283
|
|
|
181
284
|
Engram uses a three-layer retrieval system:
|
|
182
285
|
|
|
183
286
|
1. **BM25 (Keyword Search)**: SQLite FTS5 finds exact matches—names, dates, specific phrases
|
|
184
|
-
2. **
|
|
287
|
+
2. **Semantic Search**: Neural embeddings find conceptually related memories
|
|
185
288
|
3. **Knowledge Graph**: Entity relationships expand context
|
|
186
289
|
|
|
187
|
-
These are fused using Reciprocal Rank Fusion (RRF)
|
|
290
|
+
These are fused using Reciprocal Rank Fusion (RRF), then adjusted for:
|
|
291
|
+
- **Retention**: How fresh is this memory?
|
|
292
|
+
- **Salience**: How important/emotional is it?
|
|
293
|
+
|
|
294
|
+
```mermaid
|
|
295
|
+
flowchart LR
|
|
296
|
+
Q[Query] --> BM25
|
|
297
|
+
Q --> Semantic
|
|
298
|
+
Q --> Graph
|
|
188
299
|
|
|
300
|
+
BM25 --> RRF[Rank Fusion]
|
|
301
|
+
Semantic --> RRF
|
|
302
|
+
Graph --> RRF
|
|
303
|
+
|
|
304
|
+
RRF --> Decay[Apply Time Decay]
|
|
305
|
+
Decay --> Salience[Weight by Importance]
|
|
306
|
+
Salience --> Results[Final Ranking]
|
|
189
307
|
```
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
308
|
+
|
|
309
|
+
</details>
|
|
310
|
+
|
|
311
|
+
<details>
|
|
312
|
+
<summary>How Forgetting Works</summary>
|
|
313
|
+
|
|
314
|
+
Memories follow an exponential decay curve (inspired by the Ebbinghaus forgetting curve):
|
|
315
|
+
|
|
197
316
|
```
|
|
317
|
+
Retention = e^(-time / stability)
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Where:
|
|
321
|
+
- **time**: Days since last access
|
|
322
|
+
- **stability**: Memory strength (increases each time you recall it)
|
|
323
|
+
|
|
324
|
+
High-importance and high-emotion memories decay slower. Frequently accessed memories become essentially permanent.
|
|
325
|
+
|
|
326
|
+
</details>
|
|
327
|
+
|
|
328
|
+
<details>
|
|
329
|
+
<summary>How Consolidation Works</summary>
|
|
330
|
+
|
|
331
|
+
```mermaid
|
|
332
|
+
flowchart TD
|
|
333
|
+
A[Old Memories] --> B{Important?}
|
|
334
|
+
B -->|Yes| C[Keep as-is]
|
|
335
|
+
B -->|No| D[Group Similar]
|
|
336
|
+
D --> E[Summarize with AI]
|
|
337
|
+
E --> F[Create Digest]
|
|
338
|
+
F --> G[Archive Originals]
|
|
339
|
+
|
|
340
|
+
H[All Memories] --> I[Find Contradictions]
|
|
341
|
+
I --> J[Flag for Review]
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
Consolidation:
|
|
345
|
+
1. Groups related low-importance memories
|
|
346
|
+
2. Creates AI-generated summaries (digests)
|
|
347
|
+
3. Detects contradictory information
|
|
348
|
+
4. Archives original memories
|
|
349
|
+
|
|
350
|
+
Requires `ANTHROPIC_API_KEY` environment variable.
|
|
198
351
|
|
|
199
352
|
</details>
|
|
200
353
|
|
|
@@ -204,16 +357,18 @@ Query: "What should I know about Sarah?"
|
|
|
204
357
|
```
|
|
205
358
|
engram/
|
|
206
359
|
├── src/
|
|
207
|
-
│ ├── index.ts
|
|
360
|
+
│ ├── index.ts # MCP server entry
|
|
208
361
|
│ ├── storage/
|
|
209
|
-
│ │ └── database.ts
|
|
362
|
+
│ │ └── database.ts # SQLite + FTS5 + temporal fields
|
|
210
363
|
│ ├── graph/
|
|
211
|
-
│ │ ├── extractor.ts # Entity extraction
|
|
212
364
|
│ │ └── knowledge-graph.ts
|
|
213
|
-
│
|
|
214
|
-
│
|
|
215
|
-
│
|
|
216
|
-
│
|
|
365
|
+
│ ├── retrieval/
|
|
366
|
+
│ │ ├── colbert.ts # Semantic search
|
|
367
|
+
│ │ └── hybrid.ts # RRF + decay + salience
|
|
368
|
+
│ ├── consolidation/
|
|
369
|
+
│ │ └── consolidator.ts # Memory compression
|
|
370
|
+
│ └── web/
|
|
371
|
+
│ └── server.ts # Visual browser
|
|
217
372
|
```
|
|
218
373
|
|
|
219
374
|
</details>
|
|
@@ -231,12 +386,12 @@ npm run build
|
|
|
231
386
|
npm install -g .
|
|
232
387
|
```
|
|
233
388
|
|
|
234
|
-
**Python Dependencies** (for
|
|
389
|
+
**Python Dependencies** (for semantic search):
|
|
235
390
|
```bash
|
|
236
391
|
pip install ragatouille torch
|
|
237
392
|
```
|
|
238
393
|
|
|
239
|
-
If Python
|
|
394
|
+
If Python isn't available, Engram falls back to a simpler retriever automatically.
|
|
240
395
|
|
|
241
396
|
</details>
|
|
242
397
|
|
|
@@ -244,7 +399,8 @@ If Python/ColBERT isn't available, Engram falls back to a simpler retriever auto
|
|
|
244
399
|
<summary>Configuration</summary>
|
|
245
400
|
|
|
246
401
|
Environment variables:
|
|
247
|
-
- `ENGRAM_DB_PATH`: Database location (default: `~/.engram
|
|
402
|
+
- `ENGRAM_DB_PATH`: Database location (default: `~/.engram/`)
|
|
403
|
+
- `ANTHROPIC_API_KEY`: Required for consolidation features
|
|
248
404
|
|
|
249
405
|
Claude Desktop full config:
|
|
250
406
|
```json
|
|
@@ -253,7 +409,8 @@ Claude Desktop full config:
|
|
|
253
409
|
"engram": {
|
|
254
410
|
"command": "engram",
|
|
255
411
|
"env": {
|
|
256
|
-
"ENGRAM_DB_PATH": "/custom/path/
|
|
412
|
+
"ENGRAM_DB_PATH": "/custom/path/",
|
|
413
|
+
"ANTHROPIC_API_KEY": "sk-ant-..."
|
|
257
414
|
}
|
|
258
415
|
}
|
|
259
416
|
}
|
|
@@ -267,8 +424,9 @@ Claude Desktop full config:
|
|
|
267
424
|
|
|
268
425
|
On M1 MacBook Air:
|
|
269
426
|
- **remember**: ~100ms
|
|
270
|
-
- **recall**: ~50ms
|
|
427
|
+
- **recall**: ~50ms (includes decay calculation)
|
|
271
428
|
- **graph queries**: ~5ms
|
|
429
|
+
- **consolidate**: ~2-5s per batch (API call)
|
|
272
430
|
|
|
273
431
|
Database size: ~1KB per memory (text + embeddings + graph data)
|
|
274
432
|
|
|
@@ -279,13 +437,14 @@ Database size: ~1KB per memory (text + embeddings + graph data)
|
|
|
279
437
|
## Roadmap
|
|
280
438
|
|
|
281
439
|
- [x] Core MCP server
|
|
282
|
-
- [x] Hybrid search (BM25 +
|
|
440
|
+
- [x] Hybrid search (BM25 + Semantic)
|
|
283
441
|
- [x] Knowledge graph
|
|
284
442
|
- [x] Entity extraction
|
|
285
|
-
- [
|
|
286
|
-
- [
|
|
443
|
+
- [x] Temporal memory decay
|
|
444
|
+
- [x] Memory consolidation
|
|
445
|
+
- [x] Web dashboard
|
|
287
446
|
- [ ] Export/import
|
|
288
|
-
- [ ]
|
|
447
|
+
- [ ] Scheduled consolidation
|
|
289
448
|
|
|
290
449
|
---
|
|
291
450
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consolidator.d.ts","sourceRoot":"","sources":["../../src/consolidation/consolidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,cAAc,EAAU,MAAM,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"consolidator.d.ts","sourceRoot":"","sources":["../../src/consolidation/consolidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,cAAc,EAAU,MAAM,EAAW,MAAM,wBAAwB,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AA0FtD,UAAU,kBAAkB;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,MAAM,CAA6B;gBAGzC,EAAE,EAAE,cAAc,EAClB,KAAK,CAAC,EAAE,cAAc,EACtB,MAAM,CAAC,EAAE,YAAY;IAYvB,YAAY,IAAI,OAAO;IAIvB;;;OAGG;IACG,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC;QAC3D,cAAc,EAAE,MAAM,CAAC;QACvB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,iBAAiB,EAAE,MAAM,CAAC;KAC3B,CAAC;IAwEF;;OAEG;YACW,gBAAgB;IAoE9B;;OAEG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAuHjE;;OAEG;IACH,SAAS,IAAI;QACX,UAAU,EAAE,OAAO,CAAC;QACpB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,sBAAsB,EAAE,MAAM,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC;QACrB,wBAAwB,EAAE,MAAM,CAAC;KAClC;IAeD;;;OAGG;IACG,mBAAmB,CAAC,OAAO,GAAE;QACjC,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC;QACf,iBAAiB,EAAE,MAAM,CAAC;QAC1B,eAAe,EAAE,MAAM,CAAC;QACxB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;IAwFF;;OAEG;YACW,2BAA2B;IAqDzC;;;OAGG;IACG,aAAa,IAAI,OAAO,CAAC;QAC7B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,eAAe,EAAE,MAAM,CAAC;QACxB,cAAc,EAAE,MAAM,CAAC;QACvB,mBAAmB,EAAE,MAAM,CAAC;KAC7B,CAAC;CAkBH"}
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import { KnowledgeGraph } from "./graph/knowledge-graph.js";
|
|
|
15
15
|
import { createRetriever } from "./retrieval/colbert.js";
|
|
16
16
|
import { HybridSearch } from "./retrieval/hybrid.js";
|
|
17
17
|
import { EngramWebServer } from "./web/server.js";
|
|
18
|
+
import { Consolidator } from "./consolidation/consolidator.js";
|
|
18
19
|
// ============ Configuration ============
|
|
19
20
|
const DB_PATH = process.env.ENGRAM_DB_PATH
|
|
20
21
|
? path.resolve(process.env.ENGRAM_DB_PATH.replace("~", os.homedir()))
|
|
@@ -24,6 +25,7 @@ const DB_FILE = path.join(DB_PATH, "engram.db");
|
|
|
24
25
|
let db;
|
|
25
26
|
let graph;
|
|
26
27
|
let search;
|
|
28
|
+
let consolidator;
|
|
27
29
|
let webServer = null;
|
|
28
30
|
async function initialize() {
|
|
29
31
|
console.error(`[Engram] Initializing with database at ${DB_FILE}`);
|
|
@@ -31,6 +33,7 @@ async function initialize() {
|
|
|
31
33
|
graph = new KnowledgeGraph(db);
|
|
32
34
|
const retriever = await createRetriever(DB_PATH);
|
|
33
35
|
search = new HybridSearch(db, graph, retriever);
|
|
36
|
+
consolidator = new Consolidator(db, graph, search);
|
|
34
37
|
// Rebuild index with existing memories
|
|
35
38
|
const stats = db.getStats();
|
|
36
39
|
if (stats.memories > 0) {
|
|
@@ -38,11 +41,14 @@ async function initialize() {
|
|
|
38
41
|
await search.rebuildIndex();
|
|
39
42
|
}
|
|
40
43
|
console.error(`[Engram] Ready. Stats: ${JSON.stringify(stats)}`);
|
|
44
|
+
if (consolidator.isConfigured()) {
|
|
45
|
+
console.error(`[Engram] Consolidation enabled (ANTHROPIC_API_KEY found)`);
|
|
46
|
+
}
|
|
41
47
|
}
|
|
42
48
|
// ============ MCP Server ============
|
|
43
49
|
const server = new Server({
|
|
44
50
|
name: "engram",
|
|
45
|
-
version: "0.
|
|
51
|
+
version: "0.6.0",
|
|
46
52
|
}, {
|
|
47
53
|
capabilities: {
|
|
48
54
|
tools: {},
|
|
@@ -68,6 +74,17 @@ const TOOLS = [
|
|
|
68
74
|
maximum: 1,
|
|
69
75
|
default: 0.5,
|
|
70
76
|
},
|
|
77
|
+
emotional_weight: {
|
|
78
|
+
type: "number",
|
|
79
|
+
description: "0-1 emotional significance. Use 0.8+ for emotionally charged content, celebrations, losses. Affects memory retention.",
|
|
80
|
+
minimum: 0,
|
|
81
|
+
maximum: 1,
|
|
82
|
+
default: 0.5,
|
|
83
|
+
},
|
|
84
|
+
event_time: {
|
|
85
|
+
type: "string",
|
|
86
|
+
description: "When the event actually happened (ISO 8601), if different from now. E.g., 'Last week I went to Paris' → set event_time to that date.",
|
|
87
|
+
},
|
|
71
88
|
entities: {
|
|
72
89
|
type: "array",
|
|
73
90
|
description: "Key entities mentioned (people, organizations, places). Only include clear, specific named entities.",
|
|
@@ -177,6 +194,28 @@ const TOOLS = [
|
|
|
177
194
|
openWorldHint: true,
|
|
178
195
|
},
|
|
179
196
|
},
|
|
197
|
+
{
|
|
198
|
+
name: "consolidate",
|
|
199
|
+
description: "Run memory consolidation to compress episodes into memories and memories into digests. Like sleep for the memory system. Use periodically or when requested.",
|
|
200
|
+
inputSchema: {
|
|
201
|
+
type: "object",
|
|
202
|
+
properties: {
|
|
203
|
+
mode: {
|
|
204
|
+
type: "string",
|
|
205
|
+
enum: ["full", "episodes_only", "memories_only"],
|
|
206
|
+
description: "What to consolidate: 'full' (default) runs everything, 'episodes_only' just processes conversation history, 'memories_only' creates digests",
|
|
207
|
+
default: "full",
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
annotations: {
|
|
212
|
+
title: "Consolidate Memories",
|
|
213
|
+
readOnlyHint: false,
|
|
214
|
+
destructiveHint: false,
|
|
215
|
+
idempotentHint: false,
|
|
216
|
+
openWorldHint: false,
|
|
217
|
+
},
|
|
218
|
+
},
|
|
180
219
|
];
|
|
181
220
|
// List available tools
|
|
182
221
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
@@ -188,9 +227,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
188
227
|
try {
|
|
189
228
|
switch (name) {
|
|
190
229
|
case "remember": {
|
|
191
|
-
const { content, source = "conversation", importance = 0.5, entities: providedEntities = [], relationships: providedRelationships = [], } = args;
|
|
192
|
-
// Create memory
|
|
193
|
-
const memory = db.createMemory(content, source, importance
|
|
230
|
+
const { content, source = "conversation", importance = 0.5, emotional_weight = 0.5, event_time, entities: providedEntities = [], relationships: providedRelationships = [], } = args;
|
|
231
|
+
// Create memory with new temporal and salience fields
|
|
232
|
+
const memory = db.createMemory(content, source, importance, {
|
|
233
|
+
eventTime: event_time ? new Date(event_time) : undefined,
|
|
234
|
+
emotionalWeight: emotional_weight,
|
|
235
|
+
});
|
|
194
236
|
// Index for semantic search
|
|
195
237
|
await search.indexMemory(memory);
|
|
196
238
|
// Store Claude-provided entities and link to memory
|
|
@@ -241,6 +283,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
241
283
|
source: r.memory.source,
|
|
242
284
|
timestamp: r.memory.timestamp.toISOString(),
|
|
243
285
|
relevance_score: r.score.toFixed(4),
|
|
286
|
+
retention: r.retention.toFixed(2), // How well-retained (0-1)
|
|
244
287
|
matched_via: Object.entries(r.sources)
|
|
245
288
|
.filter(([, v]) => v !== undefined)
|
|
246
289
|
.map(([k]) => k)
|
|
@@ -305,6 +348,48 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
305
348
|
],
|
|
306
349
|
};
|
|
307
350
|
}
|
|
351
|
+
case "consolidate": {
|
|
352
|
+
const { mode = "full" } = args;
|
|
353
|
+
if (!consolidator.isConfigured()) {
|
|
354
|
+
return {
|
|
355
|
+
content: [
|
|
356
|
+
{
|
|
357
|
+
type: "text",
|
|
358
|
+
text: JSON.stringify({
|
|
359
|
+
success: false,
|
|
360
|
+
error: "Consolidation requires ANTHROPIC_API_KEY environment variable",
|
|
361
|
+
}),
|
|
362
|
+
},
|
|
363
|
+
],
|
|
364
|
+
isError: true,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
let result;
|
|
368
|
+
switch (mode) {
|
|
369
|
+
case "episodes_only":
|
|
370
|
+
result = await consolidator.consolidateEpisodes();
|
|
371
|
+
break;
|
|
372
|
+
case "memories_only":
|
|
373
|
+
result = await consolidator.consolidate();
|
|
374
|
+
break;
|
|
375
|
+
case "full":
|
|
376
|
+
default:
|
|
377
|
+
result = await consolidator.runSleepCycle();
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
content: [
|
|
382
|
+
{
|
|
383
|
+
type: "text",
|
|
384
|
+
text: JSON.stringify({
|
|
385
|
+
success: true,
|
|
386
|
+
mode,
|
|
387
|
+
...result,
|
|
388
|
+
}, null, 2),
|
|
389
|
+
},
|
|
390
|
+
],
|
|
391
|
+
};
|
|
392
|
+
}
|
|
308
393
|
default:
|
|
309
394
|
throw new Error(`Unknown tool: ${name}`);
|
|
310
395
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hybrid.d.ts","sourceRoot":"","sources":["../../src/retrieval/hybrid.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hybrid.d.ts","sourceRoot":"","sources":["../../src/retrieval/hybrid.ts"],"names":[],"mappings":"AAAA;;;;GAIG;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;AAEzF,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAwDD,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;;;;;OAKG;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;QACrB,YAAY,CAAC,EAAE,OAAO,CAAC;KACnB,GACL,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAyIhC;;OAEG;YACW,UAAU;IASxB;;OAEG;YACW,cAAc;IAS5B;;OAEG;YACW,WAAW;IAmBzB;;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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/storage/database.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,IAAI,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/storage/database.ts"],"names":[],"mappings":"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"}
|