@199-bio/engram 0.6.1 → 0.7.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 +92 -12
- 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 +2 -2
- package/src/index.ts +101 -12
- package/src/retrieval/hybrid.ts +32 -8
- package/src/storage/database.ts +19 -7
package/dist/index.js
CHANGED
|
@@ -59,7 +59,7 @@ const server = new Server({
|
|
|
59
59
|
const TOOLS = [
|
|
60
60
|
{
|
|
61
61
|
name: "remember",
|
|
62
|
-
description: "Store information
|
|
62
|
+
description: "Store NEW information the user shares. Extract entities (people, organizations, places) and relationships. Do NOT use for corrections - use edit_memory instead. Do NOT use before checking if info already exists - use recall first.",
|
|
63
63
|
inputSchema: {
|
|
64
64
|
type: "object",
|
|
65
65
|
properties: {
|
|
@@ -69,14 +69,14 @@ const TOOLS = [
|
|
|
69
69
|
},
|
|
70
70
|
importance: {
|
|
71
71
|
type: "number",
|
|
72
|
-
description: "0-1 score
|
|
72
|
+
description: "0-1 score with anchors: 0.9=core identity (name, birthday, family), 0.8=major preferences/life events, 0.6=notable facts, 0.5=general info (default), 0.3=casual mentions, 0.1=trivial/ephemeral",
|
|
73
73
|
minimum: 0,
|
|
74
74
|
maximum: 1,
|
|
75
75
|
default: 0.5,
|
|
76
76
|
},
|
|
77
77
|
emotional_weight: {
|
|
78
78
|
type: "number",
|
|
79
|
-
description: "0-1 emotional significance
|
|
79
|
+
description: "0-1 emotional significance with anchors: 0.9=major life events (births, deaths, achievements), 0.7=celebrations/disappointments, 0.5=neutral (default), 0.3=mild sentiment, 0.1=purely factual",
|
|
80
80
|
minimum: 0,
|
|
81
81
|
maximum: 1,
|
|
82
82
|
default: 0.5,
|
|
@@ -91,7 +91,7 @@ const TOOLS = [
|
|
|
91
91
|
items: {
|
|
92
92
|
type: "object",
|
|
93
93
|
properties: {
|
|
94
|
-
name: { type: "string", description: "Entity name (e.g., '
|
|
94
|
+
name: { type: "string", description: "Entity name (e.g., 'John Smith', 'Google', 'Paris')" },
|
|
95
95
|
type: { type: "string", enum: ["person", "organization", "place"], description: "Entity type" },
|
|
96
96
|
},
|
|
97
97
|
required: ["name", "type"],
|
|
@@ -123,7 +123,7 @@ const TOOLS = [
|
|
|
123
123
|
},
|
|
124
124
|
{
|
|
125
125
|
name: "recall",
|
|
126
|
-
description: "
|
|
126
|
+
description: "Search stored memories. Use FIRST before answering questions about the user, their preferences, history, or anything previously discussed. Also use before remember to check if information already exists.",
|
|
127
127
|
inputSchema: {
|
|
128
128
|
type: "object",
|
|
129
129
|
properties: {
|
|
@@ -154,13 +154,13 @@ const TOOLS = [
|
|
|
154
154
|
},
|
|
155
155
|
{
|
|
156
156
|
name: "forget",
|
|
157
|
-
description: "Delete a
|
|
157
|
+
description: "Delete a memory by its ID. Use when user explicitly asks to remove or forget specific stored information. Get the memory ID from recall results first.",
|
|
158
158
|
inputSchema: {
|
|
159
159
|
type: "object",
|
|
160
160
|
properties: {
|
|
161
161
|
id: {
|
|
162
162
|
type: "string",
|
|
163
|
-
description: "The memory ID to
|
|
163
|
+
description: "The memory ID to delete (get this from recall results)",
|
|
164
164
|
},
|
|
165
165
|
},
|
|
166
166
|
required: ["id"],
|
|
@@ -173,6 +173,37 @@ const TOOLS = [
|
|
|
173
173
|
openWorldHint: false,
|
|
174
174
|
},
|
|
175
175
|
},
|
|
176
|
+
{
|
|
177
|
+
name: "edit_memory",
|
|
178
|
+
description: "Correct or update an existing memory. Use instead of forget+remember when fixing mistakes, updating outdated info, or adjusting importance. Preserves the memory's history and relationships.",
|
|
179
|
+
inputSchema: {
|
|
180
|
+
type: "object",
|
|
181
|
+
properties: {
|
|
182
|
+
id: {
|
|
183
|
+
type: "string",
|
|
184
|
+
description: "The memory ID to edit (get this from recall results)",
|
|
185
|
+
},
|
|
186
|
+
content: {
|
|
187
|
+
type: "string",
|
|
188
|
+
description: "New content for the memory (replaces existing). Omit to keep current content.",
|
|
189
|
+
},
|
|
190
|
+
importance: {
|
|
191
|
+
type: "number",
|
|
192
|
+
description: "New importance (0-1): 0.9=core identity, 0.8=major, 0.5=normal, 0.3=minor. Omit to keep current.",
|
|
193
|
+
minimum: 0,
|
|
194
|
+
maximum: 1,
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
required: ["id"],
|
|
198
|
+
},
|
|
199
|
+
annotations: {
|
|
200
|
+
title: "Edit Memory",
|
|
201
|
+
readOnlyHint: false,
|
|
202
|
+
destructiveHint: false,
|
|
203
|
+
idempotentHint: true,
|
|
204
|
+
openWorldHint: false,
|
|
205
|
+
},
|
|
206
|
+
},
|
|
176
207
|
{
|
|
177
208
|
name: "engram_web",
|
|
178
209
|
description: "Launch the Engram web interface for browsing, searching, and editing memories visually. Returns a URL to open in your browser.",
|
|
@@ -196,7 +227,7 @@ const TOOLS = [
|
|
|
196
227
|
},
|
|
197
228
|
{
|
|
198
229
|
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.",
|
|
230
|
+
description: "Run memory consolidation to compress episodes into memories and memories into digests. Like sleep for the memory system. Requires ANTHROPIC_API_KEY. Use periodically or when explicitly requested.",
|
|
200
231
|
inputSchema: {
|
|
201
232
|
type: "object",
|
|
202
233
|
properties: {
|
|
@@ -213,7 +244,7 @@ const TOOLS = [
|
|
|
213
244
|
readOnlyHint: false,
|
|
214
245
|
destructiveHint: false,
|
|
215
246
|
idempotentHint: false,
|
|
216
|
-
openWorldHint:
|
|
247
|
+
openWorldHint: true, // Calls Anthropic API for consolidation
|
|
217
248
|
},
|
|
218
249
|
},
|
|
219
250
|
];
|
|
@@ -317,13 +348,62 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
317
348
|
}
|
|
318
349
|
// Remove from semantic index
|
|
319
350
|
await search.removeFromIndex(id);
|
|
320
|
-
//
|
|
321
|
-
db.
|
|
351
|
+
// Soft-delete: mark as disabled instead of hard delete
|
|
352
|
+
db.updateMemory(id, { disabled: true });
|
|
353
|
+
return {
|
|
354
|
+
content: [
|
|
355
|
+
{
|
|
356
|
+
type: "text",
|
|
357
|
+
text: JSON.stringify({ success: true, disabled_id: id, message: "Memory disabled (soft-deleted)" }),
|
|
358
|
+
},
|
|
359
|
+
],
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
case "edit_memory": {
|
|
363
|
+
const { id, content, importance } = args;
|
|
364
|
+
const memory = db.getMemory(id);
|
|
365
|
+
if (!memory) {
|
|
366
|
+
return {
|
|
367
|
+
content: [
|
|
368
|
+
{
|
|
369
|
+
type: "text",
|
|
370
|
+
text: JSON.stringify({ success: false, error: "Memory not found" }),
|
|
371
|
+
},
|
|
372
|
+
],
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
// Build updates object
|
|
376
|
+
const updates = {};
|
|
377
|
+
if (content !== undefined)
|
|
378
|
+
updates.content = content;
|
|
379
|
+
if (importance !== undefined)
|
|
380
|
+
updates.importance = importance;
|
|
381
|
+
if (Object.keys(updates).length === 0) {
|
|
382
|
+
return {
|
|
383
|
+
content: [
|
|
384
|
+
{
|
|
385
|
+
type: "text",
|
|
386
|
+
text: JSON.stringify({ success: false, error: "No updates provided" }),
|
|
387
|
+
},
|
|
388
|
+
],
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
// Update the memory
|
|
392
|
+
const updated = db.updateMemory(id, updates);
|
|
393
|
+
// Re-index if content changed
|
|
394
|
+
if (content !== undefined && updated) {
|
|
395
|
+
await search.removeFromIndex(id);
|
|
396
|
+
await search.indexMemory(updated);
|
|
397
|
+
}
|
|
322
398
|
return {
|
|
323
399
|
content: [
|
|
324
400
|
{
|
|
325
401
|
type: "text",
|
|
326
|
-
text: JSON.stringify({
|
|
402
|
+
text: JSON.stringify({
|
|
403
|
+
success: true,
|
|
404
|
+
memory_id: id,
|
|
405
|
+
updated_fields: Object.keys(updates),
|
|
406
|
+
}),
|
|
327
407
|
},
|
|
328
408
|
],
|
|
329
409
|
};
|
|
@@ -1 +1 @@
|
|
|
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
|
|
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;;;OAGG;IACH,OAAO,CAAC,aAAa;IAQrB;;;OAGG;YACW,WAAW;IA8BzB;;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,IAAI,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,IAAI,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;
|
|
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,IAAI,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,IAAI,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,cAAc,CAAC;IAChE,UAAU,EAAE,IAAI,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,IAAI,CAAC;IACjB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3C,UAAU,EAAE,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,IAAI,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,UAAU,EAAE,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,IAAI,CAAC;IACjB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAC;CAC1B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,SAAS,CAA8C;gBAEnD,MAAM,EAAE,MAAM;IAoB1B,OAAO,CAAC,UAAU;IAgKlB;;OAEG;IACH,OAAO,CAAC,aAAa;IAqBrB,YAAY,CACV,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAuB,EAC/B,UAAU,GAAE,MAAY,EACxB,OAAO,GAAE;QACP,SAAS,CAAC,EAAE,IAAI,CAAC;QACjB,eAAe,CAAC,EAAE,MAAM,CAAC;KACrB,GACL,MAAM;IAkBT,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKpC,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,UAAU,CAAC,CAAC,GAAG,MAAM,GAAG,IAAI;IAyB9G,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAMjC;;;OAGG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAW7B,cAAc,CAAC,KAAK,GAAE,MAAa,EAAE,eAAe,GAAE,OAAe,GAAG,MAAM,EAAE;IAUhF;;OAEG;IACH,aAAa,CACX,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GAAG,WAAW,EAC1B,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO;IAcV,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;IAKtC,OAAO,CAAC,gBAAgB;IAOxB;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE;IAOhD;;OAEG;IACH,yBAAyB,CAAC,KAAK,GAAE,MAAY,GAAG,OAAO,EAAE;IAOzD;;OAEG;IACH,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI;IAOpD;;OAEG;IACH,iBAAiB,CAAC,KAAK,GAAE,MAAW,GAAG,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,IAAI,CAAA;KAAE,CAAC;IAgBhH,OAAO,CAAC,YAAY;IAcpB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,KAAK,CAAC,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAkBhF,OAAO,CAAC,eAAe;IAavB,YAAY,CACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EACpB,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAW,GAC9C,MAAM;IAUT,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKpC,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAU7C;;;OAGG;IACH,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAY,GAAG,MAAM,GAAG,IAAI;IA+BvE;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IA4C/B;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE;IAgCxG;;OAEG;IACH,qBAAqB,IAAI,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAoCjF,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE;IAgB9D,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,GAAE,MAAY,GAAG,MAAM,EAAE;IAiBlE,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAMjC,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;KAAE,GAAG,MAAM,GAAG,IAAI;IAc1F,cAAc,CACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,cAAc,GAAE,MAAM,GAAG,IAAW,EACpC,UAAU,GAAE,MAAY,GACvB,WAAW;IAUd,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAK9C,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,GAAE,OAAe,GAAG,WAAW,EAAE;IAYvF,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAOnC,cAAc,CACZ,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAW,GAChD,QAAQ;IAUX,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAKxC,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,GAAG,IAAI,GAAG,MAAe,GAAG,QAAQ,EAAE;IAiB5F,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IActF,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAQnC,QAAQ,CACN,aAAa,EAAE,MAAM,EACrB,KAAK,GAAE,MAAU,EACjB,aAAa,CAAC,EAAE,MAAM,EAAE,GACvB;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAAC,SAAS,EAAE,QAAQ,EAAE,CAAC;QAAC,YAAY,EAAE,WAAW,EAAE,CAAA;KAAE;IA2C7E,YAAY,CACV,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,MAAM,EAAE,EACzB,OAAO,GAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,IAAI,CAAC;QACnB,SAAS,CAAC,EAAE,IAAI,CAAC;KACb,GACL,MAAM;IA4BT,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKpC,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,MAAY,GAAG,MAAM,EAAE;IAgBzD,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAU5C,yBAAyB,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,GAAE,MAAY,GAAG,MAAM,EAAE;IAoBtE,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAQjC,mBAAmB,CACjB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM,GAChB,aAAa;IAUhB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAKlD,iBAAiB,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,KAAK,GAAE,MAAY,GAAG,aAAa,EAAE;IAgB3E,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO;IAU7D,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAQxC,QAAQ,IAAI;QACV,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC;QACjB,uBAAuB,EAAE,MAAM,CAAC;KACjC;IA4BD,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,OAAO,CAAC,IAAI;IASZ,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,kBAAkB;CAa3B"}
|
package/package.json
CHANGED
|
@@ -74,8 +74,8 @@ const EPISODE_EXTRACTION_SYSTEM = `You are extracting structured memories from a
|
|
|
74
74
|
"importance": 0.5,
|
|
75
75
|
"emotional_weight": 0.5,
|
|
76
76
|
"event_time": "2024-12-01 or null if not mentioned",
|
|
77
|
-
"entities": [{"name": "
|
|
78
|
-
"relationships": [{"from": "
|
|
77
|
+
"entities": [{"name": "John", "type": "person"}],
|
|
78
|
+
"relationships": [{"from": "John", "to": "Acme Corp", "type": "works_at"}]
|
|
79
79
|
}
|
|
80
80
|
]
|
|
81
81
|
}
|
package/src/index.ts
CHANGED
|
@@ -81,7 +81,7 @@ const TOOLS = [
|
|
|
81
81
|
{
|
|
82
82
|
name: "remember",
|
|
83
83
|
description:
|
|
84
|
-
"Store information
|
|
84
|
+
"Store NEW information the user shares. Extract entities (people, organizations, places) and relationships. Do NOT use for corrections - use edit_memory instead. Do NOT use before checking if info already exists - use recall first.",
|
|
85
85
|
inputSchema: {
|
|
86
86
|
type: "object" as const,
|
|
87
87
|
properties: {
|
|
@@ -91,14 +91,14 @@ const TOOLS = [
|
|
|
91
91
|
},
|
|
92
92
|
importance: {
|
|
93
93
|
type: "number",
|
|
94
|
-
description: "0-1 score
|
|
94
|
+
description: "0-1 score with anchors: 0.9=core identity (name, birthday, family), 0.8=major preferences/life events, 0.6=notable facts, 0.5=general info (default), 0.3=casual mentions, 0.1=trivial/ephemeral",
|
|
95
95
|
minimum: 0,
|
|
96
96
|
maximum: 1,
|
|
97
97
|
default: 0.5,
|
|
98
98
|
},
|
|
99
99
|
emotional_weight: {
|
|
100
100
|
type: "number",
|
|
101
|
-
description: "0-1 emotional significance
|
|
101
|
+
description: "0-1 emotional significance with anchors: 0.9=major life events (births, deaths, achievements), 0.7=celebrations/disappointments, 0.5=neutral (default), 0.3=mild sentiment, 0.1=purely factual",
|
|
102
102
|
minimum: 0,
|
|
103
103
|
maximum: 1,
|
|
104
104
|
default: 0.5,
|
|
@@ -113,7 +113,7 @@ const TOOLS = [
|
|
|
113
113
|
items: {
|
|
114
114
|
type: "object",
|
|
115
115
|
properties: {
|
|
116
|
-
name: { type: "string", description: "Entity name (e.g., '
|
|
116
|
+
name: { type: "string", description: "Entity name (e.g., 'John Smith', 'Google', 'Paris')" },
|
|
117
117
|
type: { type: "string", enum: ["person", "organization", "place"], description: "Entity type" },
|
|
118
118
|
},
|
|
119
119
|
required: ["name", "type"],
|
|
@@ -146,7 +146,7 @@ const TOOLS = [
|
|
|
146
146
|
{
|
|
147
147
|
name: "recall",
|
|
148
148
|
description:
|
|
149
|
-
"
|
|
149
|
+
"Search stored memories. Use FIRST before answering questions about the user, their preferences, history, or anything previously discussed. Also use before remember to check if information already exists.",
|
|
150
150
|
inputSchema: {
|
|
151
151
|
type: "object" as const,
|
|
152
152
|
properties: {
|
|
@@ -177,13 +177,13 @@ const TOOLS = [
|
|
|
177
177
|
},
|
|
178
178
|
{
|
|
179
179
|
name: "forget",
|
|
180
|
-
description: "Delete a
|
|
180
|
+
description: "Delete a memory by its ID. Use when user explicitly asks to remove or forget specific stored information. Get the memory ID from recall results first.",
|
|
181
181
|
inputSchema: {
|
|
182
182
|
type: "object" as const,
|
|
183
183
|
properties: {
|
|
184
184
|
id: {
|
|
185
185
|
type: "string",
|
|
186
|
-
description: "The memory ID to
|
|
186
|
+
description: "The memory ID to delete (get this from recall results)",
|
|
187
187
|
},
|
|
188
188
|
},
|
|
189
189
|
required: ["id"],
|
|
@@ -196,6 +196,37 @@ const TOOLS = [
|
|
|
196
196
|
openWorldHint: false,
|
|
197
197
|
},
|
|
198
198
|
},
|
|
199
|
+
{
|
|
200
|
+
name: "edit_memory",
|
|
201
|
+
description: "Correct or update an existing memory. Use instead of forget+remember when fixing mistakes, updating outdated info, or adjusting importance. Preserves the memory's history and relationships.",
|
|
202
|
+
inputSchema: {
|
|
203
|
+
type: "object" as const,
|
|
204
|
+
properties: {
|
|
205
|
+
id: {
|
|
206
|
+
type: "string",
|
|
207
|
+
description: "The memory ID to edit (get this from recall results)",
|
|
208
|
+
},
|
|
209
|
+
content: {
|
|
210
|
+
type: "string",
|
|
211
|
+
description: "New content for the memory (replaces existing). Omit to keep current content.",
|
|
212
|
+
},
|
|
213
|
+
importance: {
|
|
214
|
+
type: "number",
|
|
215
|
+
description: "New importance (0-1): 0.9=core identity, 0.8=major, 0.5=normal, 0.3=minor. Omit to keep current.",
|
|
216
|
+
minimum: 0,
|
|
217
|
+
maximum: 1,
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
required: ["id"],
|
|
221
|
+
},
|
|
222
|
+
annotations: {
|
|
223
|
+
title: "Edit Memory",
|
|
224
|
+
readOnlyHint: false,
|
|
225
|
+
destructiveHint: false,
|
|
226
|
+
idempotentHint: true,
|
|
227
|
+
openWorldHint: false,
|
|
228
|
+
},
|
|
229
|
+
},
|
|
199
230
|
{
|
|
200
231
|
name: "engram_web",
|
|
201
232
|
description: "Launch the Engram web interface for browsing, searching, and editing memories visually. Returns a URL to open in your browser.",
|
|
@@ -219,7 +250,7 @@ const TOOLS = [
|
|
|
219
250
|
},
|
|
220
251
|
{
|
|
221
252
|
name: "consolidate",
|
|
222
|
-
description: "Run memory consolidation to compress episodes into memories and memories into digests. Like sleep for the memory system. Use periodically or when requested.",
|
|
253
|
+
description: "Run memory consolidation to compress episodes into memories and memories into digests. Like sleep for the memory system. Requires ANTHROPIC_API_KEY. Use periodically or when explicitly requested.",
|
|
223
254
|
inputSchema: {
|
|
224
255
|
type: "object" as const,
|
|
225
256
|
properties: {
|
|
@@ -236,7 +267,7 @@ const TOOLS = [
|
|
|
236
267
|
readOnlyHint: false,
|
|
237
268
|
destructiveHint: false,
|
|
238
269
|
idempotentHint: false,
|
|
239
|
-
openWorldHint:
|
|
270
|
+
openWorldHint: true, // Calls Anthropic API for consolidation
|
|
240
271
|
},
|
|
241
272
|
},
|
|
242
273
|
];
|
|
@@ -375,14 +406,72 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
375
406
|
// Remove from semantic index
|
|
376
407
|
await search.removeFromIndex(id);
|
|
377
408
|
|
|
378
|
-
//
|
|
379
|
-
db.
|
|
409
|
+
// Soft-delete: mark as disabled instead of hard delete
|
|
410
|
+
db.updateMemory(id, { disabled: true });
|
|
380
411
|
|
|
381
412
|
return {
|
|
382
413
|
content: [
|
|
383
414
|
{
|
|
384
415
|
type: "text" as const,
|
|
385
|
-
text: JSON.stringify({ success: true,
|
|
416
|
+
text: JSON.stringify({ success: true, disabled_id: id, message: "Memory disabled (soft-deleted)" }),
|
|
417
|
+
},
|
|
418
|
+
],
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
case "edit_memory": {
|
|
423
|
+
const { id, content, importance } = args as {
|
|
424
|
+
id: string;
|
|
425
|
+
content?: string;
|
|
426
|
+
importance?: number;
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
const memory = db.getMemory(id);
|
|
430
|
+
if (!memory) {
|
|
431
|
+
return {
|
|
432
|
+
content: [
|
|
433
|
+
{
|
|
434
|
+
type: "text" as const,
|
|
435
|
+
text: JSON.stringify({ success: false, error: "Memory not found" }),
|
|
436
|
+
},
|
|
437
|
+
],
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Build updates object
|
|
442
|
+
const updates: { content?: string; importance?: number } = {};
|
|
443
|
+
if (content !== undefined) updates.content = content;
|
|
444
|
+
if (importance !== undefined) updates.importance = importance;
|
|
445
|
+
|
|
446
|
+
if (Object.keys(updates).length === 0) {
|
|
447
|
+
return {
|
|
448
|
+
content: [
|
|
449
|
+
{
|
|
450
|
+
type: "text" as const,
|
|
451
|
+
text: JSON.stringify({ success: false, error: "No updates provided" }),
|
|
452
|
+
},
|
|
453
|
+
],
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Update the memory
|
|
458
|
+
const updated = db.updateMemory(id, updates);
|
|
459
|
+
|
|
460
|
+
// Re-index if content changed
|
|
461
|
+
if (content !== undefined && updated) {
|
|
462
|
+
await search.removeFromIndex(id);
|
|
463
|
+
await search.indexMemory(updated);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return {
|
|
467
|
+
content: [
|
|
468
|
+
{
|
|
469
|
+
type: "text" as const,
|
|
470
|
+
text: JSON.stringify({
|
|
471
|
+
success: true,
|
|
472
|
+
memory_id: id,
|
|
473
|
+
updated_fields: Object.keys(updates),
|
|
474
|
+
}),
|
|
386
475
|
},
|
|
387
476
|
],
|
|
388
477
|
};
|
package/src/retrieval/hybrid.ts
CHANGED
|
@@ -102,7 +102,7 @@ export class HybridSearch {
|
|
|
102
102
|
includeGraph = true,
|
|
103
103
|
bm25Weight = 1.0,
|
|
104
104
|
semanticWeight = 1.0,
|
|
105
|
-
graphWeight = 0.
|
|
105
|
+
graphWeight = 0.3,
|
|
106
106
|
useReranking = true, // Default: reranking mode for better quality
|
|
107
107
|
} = options;
|
|
108
108
|
|
|
@@ -257,22 +257,46 @@ export class HybridSearch {
|
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
+
/**
|
|
261
|
+
* Normalize a word for matching: lowercase, strip punctuation, handle possessives
|
|
262
|
+
* "John's" → "john", "Paris!" → "paris", "U.S.A." → "usa"
|
|
263
|
+
*/
|
|
264
|
+
private normalizeWord(word: string): string {
|
|
265
|
+
return word
|
|
266
|
+
.toLowerCase()
|
|
267
|
+
.replace(/'s$/, '') // Remove possessives: john's → john
|
|
268
|
+
.replace(/[^\p{L}\p{N}]/gu, '') // Keep only letters/numbers (Unicode-safe)
|
|
269
|
+
.trim();
|
|
270
|
+
}
|
|
271
|
+
|
|
260
272
|
/**
|
|
261
273
|
* Graph-based search: find known entities in query, traverse graph
|
|
274
|
+
* Uses normalized word matching to handle punctuation and possessives
|
|
262
275
|
*/
|
|
263
276
|
private async searchGraph(query: string): Promise<string[]> {
|
|
264
|
-
//
|
|
265
|
-
const
|
|
277
|
+
// Tokenize and normalize query words
|
|
278
|
+
const queryWords = query.split(/\s+/)
|
|
279
|
+
.map(w => this.normalizeWord(w))
|
|
280
|
+
.filter(w => w.length > 0);
|
|
281
|
+
const queryWordSet = new Set(queryWords);
|
|
282
|
+
|
|
283
|
+
// Find entities whose normalized names match query words
|
|
266
284
|
const allEntities = this.graph.listEntities(undefined, 500);
|
|
267
|
-
const matchedEntities = allEntities.filter(e =>
|
|
268
|
-
|
|
269
|
-
|
|
285
|
+
const matchedEntities = allEntities.filter(e => {
|
|
286
|
+
const entityWords = e.name.split(/\s+/)
|
|
287
|
+
.map(w => this.normalizeWord(w))
|
|
288
|
+
.filter(w => w.length > 0);
|
|
289
|
+
// Entity matches if ALL its words appear in the query
|
|
290
|
+
// e.g., "john" matches entity "John" but not "John Smith"
|
|
291
|
+
// e.g., "john's friend" matches entity "John" (possessive handled)
|
|
292
|
+
return entityWords.every(w => queryWordSet.has(w));
|
|
293
|
+
});
|
|
270
294
|
|
|
271
295
|
const memoryIds = new Set<string>();
|
|
272
296
|
|
|
273
297
|
for (const entity of matchedEntities) {
|
|
274
|
-
//
|
|
275
|
-
const relatedIds = this.graph.findRelatedMemoryIds(entity.name,
|
|
298
|
+
// Depth 1: only directly related memories, not transitive connections
|
|
299
|
+
const relatedIds = this.graph.findRelatedMemoryIds(entity.name, 1);
|
|
276
300
|
relatedIds.forEach(id => memoryIds.add(id));
|
|
277
301
|
}
|
|
278
302
|
|
package/src/storage/database.ts
CHANGED
|
@@ -19,6 +19,7 @@ export interface Memory {
|
|
|
19
19
|
last_accessed: Date | null;
|
|
20
20
|
stability: number; // Ebbinghaus stability score (increases with recalls)
|
|
21
21
|
emotional_weight: number; // Salience: emotional significance 0-1
|
|
22
|
+
disabled: boolean; // Soft-deleted: excluded from search results
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -287,6 +288,9 @@ export class EngramDatabase {
|
|
|
287
288
|
if (!memoryColumns.has("emotional_weight")) {
|
|
288
289
|
this.db.exec("ALTER TABLE memories ADD COLUMN emotional_weight REAL DEFAULT 0.5");
|
|
289
290
|
}
|
|
291
|
+
if (!memoryColumns.has("disabled")) {
|
|
292
|
+
this.db.exec("ALTER TABLE memories ADD COLUMN disabled INTEGER DEFAULT 0");
|
|
293
|
+
}
|
|
290
294
|
}
|
|
291
295
|
|
|
292
296
|
// ============ Memory Operations ============
|
|
@@ -322,7 +326,7 @@ export class EngramDatabase {
|
|
|
322
326
|
return row ? this.rowToMemory(row) : null;
|
|
323
327
|
}
|
|
324
328
|
|
|
325
|
-
updateMemory(id: string, updates: Partial<Pick<Memory, "content" | "importance">>): Memory | null {
|
|
329
|
+
updateMemory(id: string, updates: Partial<Pick<Memory, "content" | "importance" | "disabled">>): Memory | null {
|
|
326
330
|
const sets: string[] = [];
|
|
327
331
|
const values: unknown[] = [];
|
|
328
332
|
|
|
@@ -334,6 +338,10 @@ export class EngramDatabase {
|
|
|
334
338
|
sets.push("importance = ?");
|
|
335
339
|
values.push(updates.importance);
|
|
336
340
|
}
|
|
341
|
+
if (updates.disabled !== undefined) {
|
|
342
|
+
sets.push("disabled = ?");
|
|
343
|
+
values.push(updates.disabled ? 1 : 0);
|
|
344
|
+
}
|
|
337
345
|
|
|
338
346
|
if (sets.length === 0) return this.getMemory(id);
|
|
339
347
|
|
|
@@ -364,8 +372,11 @@ export class EngramDatabase {
|
|
|
364
372
|
`).run(id);
|
|
365
373
|
}
|
|
366
374
|
|
|
367
|
-
getAllMemories(limit: number = 1000): Memory[] {
|
|
368
|
-
const
|
|
375
|
+
getAllMemories(limit: number = 1000, includeDisabled: boolean = false): Memory[] {
|
|
376
|
+
const sql = includeDisabled
|
|
377
|
+
? "SELECT * FROM memories ORDER BY timestamp DESC LIMIT ?"
|
|
378
|
+
: "SELECT * FROM memories WHERE disabled = 0 ORDER BY timestamp DESC LIMIT ?";
|
|
379
|
+
const rows = this.stmt(sql).all(limit) as Record<string, unknown>[];
|
|
369
380
|
return rows.map((row) => this.rowToMemory(row));
|
|
370
381
|
}
|
|
371
382
|
|
|
@@ -475,7 +486,7 @@ export class EngramDatabase {
|
|
|
475
486
|
SELECT m.*, bm25(memories_fts) as score
|
|
476
487
|
FROM memories_fts fts
|
|
477
488
|
JOIN memories m ON fts.rowid = m.rowid
|
|
478
|
-
WHERE memories_fts MATCH ?
|
|
489
|
+
WHERE memories_fts MATCH ? AND m.disabled = 0
|
|
479
490
|
ORDER BY score
|
|
480
491
|
LIMIT ?
|
|
481
492
|
`).all(escapedQuery, limit) as Array<Record<string, unknown>>;
|
|
@@ -530,7 +541,7 @@ export class EngramDatabase {
|
|
|
530
541
|
|
|
531
542
|
/**
|
|
532
543
|
* Find a similar entity using fuzzy matching
|
|
533
|
-
* Catches "
|
|
544
|
+
* Catches "John D" matching "John Doe", "Jane" matching "Jane Smith"
|
|
534
545
|
*/
|
|
535
546
|
findSimilarEntity(name: string, threshold: number = 0.8): Entity | null {
|
|
536
547
|
const normalizedName = name.toLowerCase().trim();
|
|
@@ -576,7 +587,7 @@ export class EngramDatabase {
|
|
|
576
587
|
// Exact match
|
|
577
588
|
if (full1 === full2) return 1.0;
|
|
578
589
|
|
|
579
|
-
// One is prefix of the other (e.g., "
|
|
590
|
+
// One is prefix of the other (e.g., "John" vs "John Doe")
|
|
580
591
|
if (full1.startsWith(full2 + " ") || full2.startsWith(full1 + " ")) {
|
|
581
592
|
return 0.9;
|
|
582
593
|
}
|
|
@@ -589,7 +600,7 @@ export class EngramDatabase {
|
|
|
589
600
|
return 0.7 + (0.2 * shorter / longer);
|
|
590
601
|
}
|
|
591
602
|
|
|
592
|
-
// Check for abbreviated names (e.g., "
|
|
603
|
+
// Check for abbreviated names (e.g., "John D" vs "John Doe")
|
|
593
604
|
if (words1.length >= 2 && words2.length >= 2) {
|
|
594
605
|
const last1 = words1[words1.length - 1];
|
|
595
606
|
const last2 = words2[words2.length - 1];
|
|
@@ -1099,6 +1110,7 @@ export class EngramDatabase {
|
|
|
1099
1110
|
last_accessed: row.last_accessed ? new Date(row.last_accessed as string) : null,
|
|
1100
1111
|
stability: (row.stability as number) ?? 1.0,
|
|
1101
1112
|
emotional_weight: (row.emotional_weight as number) ?? 0.5,
|
|
1113
|
+
disabled: Boolean(row.disabled),
|
|
1102
1114
|
};
|
|
1103
1115
|
}
|
|
1104
1116
|
|