@199-bio/engram 0.3.1 → 0.4.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/graph/extractor.d.ts.map +1 -1
- package/dist/index.js +1 -285
- package/dist/storage/database.d.ts.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/graph/extractor.ts +49 -1
- package/src/index.ts +1 -319
- package/src/storage/database.ts +35 -0
- package/src/web/server.ts +41 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/graph/extractor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,cAAc,CAAC;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACtC;
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/graph/extractor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,cAAc,CAAC;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACtC;AAwID,qBAAa,eAAe;IAC1B;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE;IA8D3C;;OAEG;IACH,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE;IAuFrD;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE;IAe/C;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAyC/B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAuC9B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAiC5B;;OAEG;IACH,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;QACxC,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CA4BH;AAGD,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -42,7 +42,7 @@ async function initialize() {
|
|
|
42
42
|
// ============ MCP Server ============
|
|
43
43
|
const server = new Server({
|
|
44
44
|
name: "engram",
|
|
45
|
-
version: "0.
|
|
45
|
+
version: "0.4.0",
|
|
46
46
|
}, {
|
|
47
47
|
capabilities: {
|
|
48
48
|
tools: {},
|
|
@@ -136,153 +136,6 @@ const TOOLS = [
|
|
|
136
136
|
openWorldHint: false,
|
|
137
137
|
},
|
|
138
138
|
},
|
|
139
|
-
{
|
|
140
|
-
name: "create_entity",
|
|
141
|
-
description: "ADVANCED: Manually create an entity. Rarely needed - remember auto-extracts entities. Only use when: (1) creating an entity that won't appear in any memory content, or (2) correcting entity type after auto-extraction.",
|
|
142
|
-
inputSchema: {
|
|
143
|
-
type: "object",
|
|
144
|
-
properties: {
|
|
145
|
-
name: {
|
|
146
|
-
type: "string",
|
|
147
|
-
description: "Entity name (e.g., 'John Smith', 'Paris', 'Machine Learning')",
|
|
148
|
-
},
|
|
149
|
-
type: {
|
|
150
|
-
type: "string",
|
|
151
|
-
enum: ["person", "place", "concept", "event", "organization"],
|
|
152
|
-
description: "Type of entity",
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
required: ["name", "type"],
|
|
156
|
-
},
|
|
157
|
-
annotations: {
|
|
158
|
-
title: "Create Entity",
|
|
159
|
-
readOnlyHint: false,
|
|
160
|
-
destructiveHint: false,
|
|
161
|
-
idempotentHint: true,
|
|
162
|
-
openWorldHint: false,
|
|
163
|
-
},
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
name: "observe",
|
|
167
|
-
description: "ADVANCED: Add a fact to an EXISTING entity without creating a memory. Rarely needed - use remember instead, which stores the content AND links it to entities. Only use observe for adding metadata or corrections to entities.",
|
|
168
|
-
inputSchema: {
|
|
169
|
-
type: "object",
|
|
170
|
-
properties: {
|
|
171
|
-
entity: {
|
|
172
|
-
type: "string",
|
|
173
|
-
description: "Entity name to add observation to (must already exist)",
|
|
174
|
-
},
|
|
175
|
-
observation: {
|
|
176
|
-
type: "string",
|
|
177
|
-
description: "The fact or observation to record",
|
|
178
|
-
},
|
|
179
|
-
confidence: {
|
|
180
|
-
type: "number",
|
|
181
|
-
description: "Confidence in this observation (0-1)",
|
|
182
|
-
default: 1.0,
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
required: ["entity", "observation"],
|
|
186
|
-
},
|
|
187
|
-
annotations: {
|
|
188
|
-
title: "Add Observation",
|
|
189
|
-
readOnlyHint: false,
|
|
190
|
-
destructiveHint: false,
|
|
191
|
-
idempotentHint: false,
|
|
192
|
-
openWorldHint: false,
|
|
193
|
-
},
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
name: "relate",
|
|
197
|
-
description: "ADVANCED: Manually create a relationship between two entities. Rarely needed - remember auto-extracts relationships from text. Only use when: (1) the relationship wasn't captured by auto-extraction, or (2) you need to add a relationship not mentioned in any memory.",
|
|
198
|
-
inputSchema: {
|
|
199
|
-
type: "object",
|
|
200
|
-
properties: {
|
|
201
|
-
from: {
|
|
202
|
-
type: "string",
|
|
203
|
-
description: "Source entity name",
|
|
204
|
-
},
|
|
205
|
-
to: {
|
|
206
|
-
type: "string",
|
|
207
|
-
description: "Target entity name",
|
|
208
|
-
},
|
|
209
|
-
relation: {
|
|
210
|
-
type: "string",
|
|
211
|
-
description: "Type of relationship (e.g., 'sibling', 'works_at', 'knows', 'located_in')",
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
required: ["from", "to", "relation"],
|
|
215
|
-
},
|
|
216
|
-
annotations: {
|
|
217
|
-
title: "Create Relationship",
|
|
218
|
-
readOnlyHint: false,
|
|
219
|
-
destructiveHint: false,
|
|
220
|
-
idempotentHint: true,
|
|
221
|
-
openWorldHint: false,
|
|
222
|
-
},
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
name: "query_entity",
|
|
226
|
-
description: "Get all stored information about a specific person, place, or organization. Use after recall to get deeper details about an entity mentioned in search results.",
|
|
227
|
-
inputSchema: {
|
|
228
|
-
type: "object",
|
|
229
|
-
properties: {
|
|
230
|
-
entity: {
|
|
231
|
-
type: "string",
|
|
232
|
-
description: "Entity name to query",
|
|
233
|
-
},
|
|
234
|
-
},
|
|
235
|
-
required: ["entity"],
|
|
236
|
-
},
|
|
237
|
-
annotations: {
|
|
238
|
-
title: "Query Entity",
|
|
239
|
-
readOnlyHint: true,
|
|
240
|
-
destructiveHint: false,
|
|
241
|
-
idempotentHint: true,
|
|
242
|
-
openWorldHint: false,
|
|
243
|
-
},
|
|
244
|
-
},
|
|
245
|
-
{
|
|
246
|
-
name: "list_entities",
|
|
247
|
-
description: "List all known entities (people, places, organizations, etc.). Use to browse the knowledge graph or find entity names for query_entity.",
|
|
248
|
-
inputSchema: {
|
|
249
|
-
type: "object",
|
|
250
|
-
properties: {
|
|
251
|
-
type: {
|
|
252
|
-
type: "string",
|
|
253
|
-
enum: ["person", "place", "concept", "event", "organization"],
|
|
254
|
-
description: "Filter by entity type (optional)",
|
|
255
|
-
},
|
|
256
|
-
limit: {
|
|
257
|
-
type: "number",
|
|
258
|
-
description: "Maximum number of entities to return",
|
|
259
|
-
default: 50,
|
|
260
|
-
},
|
|
261
|
-
},
|
|
262
|
-
},
|
|
263
|
-
annotations: {
|
|
264
|
-
title: "List Entities",
|
|
265
|
-
readOnlyHint: true,
|
|
266
|
-
destructiveHint: false,
|
|
267
|
-
idempotentHint: true,
|
|
268
|
-
openWorldHint: false,
|
|
269
|
-
},
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
name: "stats",
|
|
273
|
-
description: "Get memory statistics (counts of memories, entities, relations, observations)",
|
|
274
|
-
inputSchema: {
|
|
275
|
-
type: "object",
|
|
276
|
-
properties: {},
|
|
277
|
-
},
|
|
278
|
-
annotations: {
|
|
279
|
-
title: "Get Statistics",
|
|
280
|
-
readOnlyHint: true,
|
|
281
|
-
destructiveHint: false,
|
|
282
|
-
idempotentHint: true,
|
|
283
|
-
openWorldHint: false,
|
|
284
|
-
},
|
|
285
|
-
},
|
|
286
139
|
{
|
|
287
140
|
name: "engram_web",
|
|
288
141
|
description: "Launch the Engram web interface for browsing, searching, and editing memories visually. Returns a URL to open in your browser.",
|
|
@@ -392,143 +245,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
392
245
|
],
|
|
393
246
|
};
|
|
394
247
|
}
|
|
395
|
-
case "create_entity": {
|
|
396
|
-
const { name: entityName, type } = args;
|
|
397
|
-
const entity = graph.getOrCreateEntity(entityName, type);
|
|
398
|
-
return {
|
|
399
|
-
content: [
|
|
400
|
-
{
|
|
401
|
-
type: "text",
|
|
402
|
-
text: JSON.stringify({
|
|
403
|
-
success: true,
|
|
404
|
-
entity: {
|
|
405
|
-
id: entity.id,
|
|
406
|
-
name: entity.name,
|
|
407
|
-
type: entity.type,
|
|
408
|
-
},
|
|
409
|
-
}, null, 2),
|
|
410
|
-
},
|
|
411
|
-
],
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
case "observe": {
|
|
415
|
-
const { entity: entityName, observation, confidence = 1.0 } = args;
|
|
416
|
-
// Ensure entity exists
|
|
417
|
-
const entity = graph.getOrCreateEntity(entityName, "person");
|
|
418
|
-
// Add observation
|
|
419
|
-
const obs = graph.addObservation(entity.id, observation, undefined, confidence);
|
|
420
|
-
return {
|
|
421
|
-
content: [
|
|
422
|
-
{
|
|
423
|
-
type: "text",
|
|
424
|
-
text: JSON.stringify({
|
|
425
|
-
success: true,
|
|
426
|
-
entity: entity.name,
|
|
427
|
-
observation_id: obs.id,
|
|
428
|
-
}, null, 2),
|
|
429
|
-
},
|
|
430
|
-
],
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
case "relate": {
|
|
434
|
-
const { from, to, relation } = args;
|
|
435
|
-
// Ensure both entities exist
|
|
436
|
-
const fromEntity = graph.getOrCreateEntity(from, "person");
|
|
437
|
-
const toEntity = graph.getOrCreateEntity(to, "person");
|
|
438
|
-
// Create relation
|
|
439
|
-
const rel = graph.relate(fromEntity.id, toEntity.id, relation);
|
|
440
|
-
return {
|
|
441
|
-
content: [
|
|
442
|
-
{
|
|
443
|
-
type: "text",
|
|
444
|
-
text: JSON.stringify({
|
|
445
|
-
success: true,
|
|
446
|
-
relation: {
|
|
447
|
-
id: rel.id,
|
|
448
|
-
from: fromEntity.name,
|
|
449
|
-
to: toEntity.name,
|
|
450
|
-
type: rel.type,
|
|
451
|
-
},
|
|
452
|
-
}, null, 2),
|
|
453
|
-
},
|
|
454
|
-
],
|
|
455
|
-
};
|
|
456
|
-
}
|
|
457
|
-
case "query_entity": {
|
|
458
|
-
const { entity: entityName } = args;
|
|
459
|
-
const details = graph.getEntityDetails(entityName);
|
|
460
|
-
if (!details) {
|
|
461
|
-
return {
|
|
462
|
-
content: [
|
|
463
|
-
{
|
|
464
|
-
type: "text",
|
|
465
|
-
text: JSON.stringify({ success: false, error: "Entity not found" }),
|
|
466
|
-
},
|
|
467
|
-
],
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
return {
|
|
471
|
-
content: [
|
|
472
|
-
{
|
|
473
|
-
type: "text",
|
|
474
|
-
text: JSON.stringify({
|
|
475
|
-
entity: {
|
|
476
|
-
id: details.id,
|
|
477
|
-
name: details.name,
|
|
478
|
-
type: details.type,
|
|
479
|
-
created_at: details.created_at.toISOString(),
|
|
480
|
-
},
|
|
481
|
-
observations: details.observations.map((o) => ({
|
|
482
|
-
content: o.content.substring(0, 200) + (o.content.length > 200 ? "..." : ""),
|
|
483
|
-
confidence: o.confidence,
|
|
484
|
-
valid_from: o.valid_from.toISOString(),
|
|
485
|
-
})),
|
|
486
|
-
relations_from: details.relationsFrom.map((r) => ({
|
|
487
|
-
type: r.type,
|
|
488
|
-
to: r.targetEntity.name,
|
|
489
|
-
})),
|
|
490
|
-
relations_to: details.relationsTo.map((r) => ({
|
|
491
|
-
type: r.type,
|
|
492
|
-
from: r.sourceEntity.name,
|
|
493
|
-
})),
|
|
494
|
-
}, null, 2),
|
|
495
|
-
},
|
|
496
|
-
],
|
|
497
|
-
};
|
|
498
|
-
}
|
|
499
|
-
case "list_entities": {
|
|
500
|
-
const { type, limit = 50 } = args;
|
|
501
|
-
const entities = graph.listEntities(type, limit);
|
|
502
|
-
return {
|
|
503
|
-
content: [
|
|
504
|
-
{
|
|
505
|
-
type: "text",
|
|
506
|
-
text: JSON.stringify({
|
|
507
|
-
entities: entities.map((e) => ({
|
|
508
|
-
id: e.id,
|
|
509
|
-
name: e.name,
|
|
510
|
-
type: e.type,
|
|
511
|
-
})),
|
|
512
|
-
count: entities.length,
|
|
513
|
-
}, null, 2),
|
|
514
|
-
},
|
|
515
|
-
],
|
|
516
|
-
};
|
|
517
|
-
}
|
|
518
|
-
case "stats": {
|
|
519
|
-
const stats = db.getStats();
|
|
520
|
-
return {
|
|
521
|
-
content: [
|
|
522
|
-
{
|
|
523
|
-
type: "text",
|
|
524
|
-
text: JSON.stringify({
|
|
525
|
-
...stats,
|
|
526
|
-
database_path: DB_FILE,
|
|
527
|
-
}, null, 2),
|
|
528
|
-
},
|
|
529
|
-
],
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
248
|
case "engram_web": {
|
|
533
249
|
const { port = 3847 } = args;
|
|
534
250
|
// Create or reuse web server
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/storage/database.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/storage/database.ts"],"names":[],"mappings":"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"}
|
package/dist/web/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAiBtD,UAAU,gBAAgB;IACxB,EAAE,EAAE,cAAc,CAAC;IACnB,KAAK,EAAE,cAAc,CAAC;IACtB,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,IAAI,CAAS;gBAET,OAAO,EAAE,gBAAgB;IAO/B,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAkB9B,IAAI,IAAI,IAAI;YAOE,aAAa;YA+Bb,SAAS;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/web/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAiBtD,UAAU,gBAAgB;IACxB,EAAE,EAAE,cAAc,CAAC;IACnB,KAAK,EAAE,cAAc,CAAC;IACtB,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,IAAI,CAAS;gBAET,OAAO,EAAE,gBAAgB;IAO/B,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAkB9B,IAAI,IAAI,IAAI;YAOE,aAAa;YA+Bb,SAAS;YAyKT,WAAW;IAgCzB,OAAO,CAAC,SAAS;CAclB"}
|
package/package.json
CHANGED
package/src/graph/extractor.ts
CHANGED
|
@@ -10,25 +10,73 @@ export interface ExtractedEntity {
|
|
|
10
10
|
span: { start: number; end: number };
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
// Common words that look like names but aren't
|
|
13
|
+
// Common words that look like names but aren't (including verbs, adjectives, common nouns)
|
|
14
14
|
const STOPWORDS = new Set([
|
|
15
|
+
// Articles, conjunctions, prepositions
|
|
15
16
|
"the", "a", "an", "and", "or", "but", "in", "on", "at", "to", "for",
|
|
16
17
|
"of", "with", "by", "from", "as", "is", "was", "are", "were", "been",
|
|
17
18
|
"be", "have", "has", "had", "do", "does", "did", "will", "would",
|
|
18
19
|
"could", "should", "may", "might", "must", "shall", "can", "need",
|
|
20
|
+
// Pronouns
|
|
19
21
|
"this", "that", "these", "those", "i", "you", "he", "she", "it",
|
|
20
22
|
"we", "they", "what", "which", "who", "whom", "whose", "where",
|
|
21
23
|
"when", "why", "how", "all", "each", "every", "both", "few", "more",
|
|
22
24
|
"most", "other", "some", "such", "no", "not", "only", "same", "so",
|
|
23
25
|
"than", "too", "very", "just", "also", "now", "here", "there", "then",
|
|
26
|
+
// Conjunctions
|
|
24
27
|
"if", "because", "while", "although", "though", "after", "before",
|
|
25
28
|
"since", "until", "unless", "however", "therefore", "thus", "hence",
|
|
29
|
+
// Days and months
|
|
26
30
|
"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday",
|
|
27
31
|
"january", "february", "march", "april", "may", "june", "july",
|
|
28
32
|
"august", "september", "october", "november", "december",
|
|
33
|
+
// Time words
|
|
29
34
|
"today", "tomorrow", "yesterday", "morning", "afternoon", "evening", "night",
|
|
35
|
+
// Common verbs (often capitalized at sentence start)
|
|
30
36
|
"said", "says", "told", "asked", "replied", "answered", "mentioned",
|
|
31
37
|
"think", "know", "believe", "feel", "want", "need", "like", "love",
|
|
38
|
+
"crashed", "gets", "getting", "got", "planning", "planned", "plans",
|
|
39
|
+
"working", "worked", "works", "going", "went", "gone", "coming", "came",
|
|
40
|
+
"looking", "looked", "looks", "trying", "tried", "tries", "using", "used",
|
|
41
|
+
"making", "made", "makes", "taking", "took", "takes", "giving", "gave",
|
|
42
|
+
"seeing", "saw", "seen", "being", "having", "doing", "saying", "getting",
|
|
43
|
+
"finding", "found", "keeping", "kept", "letting", "let", "putting", "put",
|
|
44
|
+
"running", "ran", "calling", "called", "moving", "moved", "living", "lived",
|
|
45
|
+
"starting", "started", "seems", "seemed", "showing", "showed", "hearing",
|
|
46
|
+
"playing", "played", "standing", "stood", "understanding", "understood",
|
|
47
|
+
"turning", "turned", "following", "followed", "watching", "watched",
|
|
48
|
+
"adding", "added", "changing", "changed", "writing", "wrote", "reading",
|
|
49
|
+
"learning", "learned", "growing", "grew", "opening", "opened", "walking",
|
|
50
|
+
"winning", "won", "offering", "offered", "remembering", "remembered",
|
|
51
|
+
"considering", "considered", "appearing", "appeared", "buying", "bought",
|
|
52
|
+
"waiting", "waited", "serving", "served", "dying", "died", "sending", "sent",
|
|
53
|
+
"building", "built", "staying", "stayed", "falling", "fell", "cutting", "cut",
|
|
54
|
+
"reaching", "reached", "killing", "killed", "raising", "raised", "passing",
|
|
55
|
+
"selling", "sold", "deciding", "decided", "returning", "returned",
|
|
56
|
+
// Common adjectives (often capitalized at sentence start)
|
|
57
|
+
"good", "bad", "great", "small", "large", "big", "little", "old", "young",
|
|
58
|
+
"new", "first", "last", "long", "short", "high", "low", "right", "wrong",
|
|
59
|
+
"next", "early", "late", "hard", "easy", "clear", "full", "empty", "ready",
|
|
60
|
+
"sure", "open", "closed", "free", "busy", "hot", "cold", "warm", "cool",
|
|
61
|
+
"fast", "slow", "strong", "weak", "deep", "wide", "near", "far", "dark",
|
|
62
|
+
"light", "heavy", "simple", "complex", "real", "true", "false", "best",
|
|
63
|
+
"worst", "happy", "sad", "angry", "afraid", "sorry", "glad", "nice",
|
|
64
|
+
"fine", "okay", "different", "similar", "same", "special", "important",
|
|
65
|
+
"interesting", "beautiful", "wonderful", "terrible", "amazing", "awesome",
|
|
66
|
+
// Common nouns (sentence starters)
|
|
67
|
+
"people", "time", "year", "years", "way", "day", "days", "man", "woman",
|
|
68
|
+
"child", "children", "world", "life", "hand", "part", "place", "case",
|
|
69
|
+
"week", "weeks", "company", "system", "program", "question", "work",
|
|
70
|
+
"government", "number", "point", "home", "water", "room", "mother",
|
|
71
|
+
"area", "money", "story", "fact", "month", "months", "lot", "right",
|
|
72
|
+
"study", "book", "books", "eye", "eyes", "job", "word", "words",
|
|
73
|
+
"business", "issue", "issues", "side", "kind", "head", "house", "service",
|
|
74
|
+
"friend", "friends", "power", "hour", "hours", "game", "line", "end",
|
|
75
|
+
"member", "members", "law", "car", "city", "community", "name", "names",
|
|
76
|
+
"team", "minute", "minutes", "idea", "ideas", "body", "information",
|
|
77
|
+
"back", "parent", "parents", "face", "others", "level", "office", "door",
|
|
78
|
+
"health", "person", "art", "war", "history", "party", "result", "change",
|
|
79
|
+
"reason", "research", "girl", "guy", "moment", "air", "teacher", "force",
|
|
32
80
|
]);
|
|
33
81
|
|
|
34
82
|
// Common titles that precede names
|
package/src/index.ts
CHANGED
|
@@ -60,7 +60,7 @@ async function initialize(): Promise<void> {
|
|
|
60
60
|
const server = new Server(
|
|
61
61
|
{
|
|
62
62
|
name: "engram",
|
|
63
|
-
version: "0.
|
|
63
|
+
version: "0.4.0",
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
66
|
capabilities: {
|
|
@@ -159,153 +159,6 @@ const TOOLS = [
|
|
|
159
159
|
openWorldHint: false,
|
|
160
160
|
},
|
|
161
161
|
},
|
|
162
|
-
{
|
|
163
|
-
name: "create_entity",
|
|
164
|
-
description: "ADVANCED: Manually create an entity. Rarely needed - remember auto-extracts entities. Only use when: (1) creating an entity that won't appear in any memory content, or (2) correcting entity type after auto-extraction.",
|
|
165
|
-
inputSchema: {
|
|
166
|
-
type: "object" as const,
|
|
167
|
-
properties: {
|
|
168
|
-
name: {
|
|
169
|
-
type: "string",
|
|
170
|
-
description: "Entity name (e.g., 'John Smith', 'Paris', 'Machine Learning')",
|
|
171
|
-
},
|
|
172
|
-
type: {
|
|
173
|
-
type: "string",
|
|
174
|
-
enum: ["person", "place", "concept", "event", "organization"],
|
|
175
|
-
description: "Type of entity",
|
|
176
|
-
},
|
|
177
|
-
},
|
|
178
|
-
required: ["name", "type"],
|
|
179
|
-
},
|
|
180
|
-
annotations: {
|
|
181
|
-
title: "Create Entity",
|
|
182
|
-
readOnlyHint: false,
|
|
183
|
-
destructiveHint: false,
|
|
184
|
-
idempotentHint: true,
|
|
185
|
-
openWorldHint: false,
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
{
|
|
189
|
-
name: "observe",
|
|
190
|
-
description: "ADVANCED: Add a fact to an EXISTING entity without creating a memory. Rarely needed - use remember instead, which stores the content AND links it to entities. Only use observe for adding metadata or corrections to entities.",
|
|
191
|
-
inputSchema: {
|
|
192
|
-
type: "object" as const,
|
|
193
|
-
properties: {
|
|
194
|
-
entity: {
|
|
195
|
-
type: "string",
|
|
196
|
-
description: "Entity name to add observation to (must already exist)",
|
|
197
|
-
},
|
|
198
|
-
observation: {
|
|
199
|
-
type: "string",
|
|
200
|
-
description: "The fact or observation to record",
|
|
201
|
-
},
|
|
202
|
-
confidence: {
|
|
203
|
-
type: "number",
|
|
204
|
-
description: "Confidence in this observation (0-1)",
|
|
205
|
-
default: 1.0,
|
|
206
|
-
},
|
|
207
|
-
},
|
|
208
|
-
required: ["entity", "observation"],
|
|
209
|
-
},
|
|
210
|
-
annotations: {
|
|
211
|
-
title: "Add Observation",
|
|
212
|
-
readOnlyHint: false,
|
|
213
|
-
destructiveHint: false,
|
|
214
|
-
idempotentHint: false,
|
|
215
|
-
openWorldHint: false,
|
|
216
|
-
},
|
|
217
|
-
},
|
|
218
|
-
{
|
|
219
|
-
name: "relate",
|
|
220
|
-
description: "ADVANCED: Manually create a relationship between two entities. Rarely needed - remember auto-extracts relationships from text. Only use when: (1) the relationship wasn't captured by auto-extraction, or (2) you need to add a relationship not mentioned in any memory.",
|
|
221
|
-
inputSchema: {
|
|
222
|
-
type: "object" as const,
|
|
223
|
-
properties: {
|
|
224
|
-
from: {
|
|
225
|
-
type: "string",
|
|
226
|
-
description: "Source entity name",
|
|
227
|
-
},
|
|
228
|
-
to: {
|
|
229
|
-
type: "string",
|
|
230
|
-
description: "Target entity name",
|
|
231
|
-
},
|
|
232
|
-
relation: {
|
|
233
|
-
type: "string",
|
|
234
|
-
description: "Type of relationship (e.g., 'sibling', 'works_at', 'knows', 'located_in')",
|
|
235
|
-
},
|
|
236
|
-
},
|
|
237
|
-
required: ["from", "to", "relation"],
|
|
238
|
-
},
|
|
239
|
-
annotations: {
|
|
240
|
-
title: "Create Relationship",
|
|
241
|
-
readOnlyHint: false,
|
|
242
|
-
destructiveHint: false,
|
|
243
|
-
idempotentHint: true,
|
|
244
|
-
openWorldHint: false,
|
|
245
|
-
},
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
name: "query_entity",
|
|
249
|
-
description: "Get all stored information about a specific person, place, or organization. Use after recall to get deeper details about an entity mentioned in search results.",
|
|
250
|
-
inputSchema: {
|
|
251
|
-
type: "object" as const,
|
|
252
|
-
properties: {
|
|
253
|
-
entity: {
|
|
254
|
-
type: "string",
|
|
255
|
-
description: "Entity name to query",
|
|
256
|
-
},
|
|
257
|
-
},
|
|
258
|
-
required: ["entity"],
|
|
259
|
-
},
|
|
260
|
-
annotations: {
|
|
261
|
-
title: "Query Entity",
|
|
262
|
-
readOnlyHint: true,
|
|
263
|
-
destructiveHint: false,
|
|
264
|
-
idempotentHint: true,
|
|
265
|
-
openWorldHint: false,
|
|
266
|
-
},
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
name: "list_entities",
|
|
270
|
-
description: "List all known entities (people, places, organizations, etc.). Use to browse the knowledge graph or find entity names for query_entity.",
|
|
271
|
-
inputSchema: {
|
|
272
|
-
type: "object" as const,
|
|
273
|
-
properties: {
|
|
274
|
-
type: {
|
|
275
|
-
type: "string",
|
|
276
|
-
enum: ["person", "place", "concept", "event", "organization"],
|
|
277
|
-
description: "Filter by entity type (optional)",
|
|
278
|
-
},
|
|
279
|
-
limit: {
|
|
280
|
-
type: "number",
|
|
281
|
-
description: "Maximum number of entities to return",
|
|
282
|
-
default: 50,
|
|
283
|
-
},
|
|
284
|
-
},
|
|
285
|
-
},
|
|
286
|
-
annotations: {
|
|
287
|
-
title: "List Entities",
|
|
288
|
-
readOnlyHint: true,
|
|
289
|
-
destructiveHint: false,
|
|
290
|
-
idempotentHint: true,
|
|
291
|
-
openWorldHint: false,
|
|
292
|
-
},
|
|
293
|
-
},
|
|
294
|
-
{
|
|
295
|
-
name: "stats",
|
|
296
|
-
description: "Get memory statistics (counts of memories, entities, relations, observations)",
|
|
297
|
-
inputSchema: {
|
|
298
|
-
type: "object" as const,
|
|
299
|
-
properties: {},
|
|
300
|
-
},
|
|
301
|
-
annotations: {
|
|
302
|
-
title: "Get Statistics",
|
|
303
|
-
readOnlyHint: true,
|
|
304
|
-
destructiveHint: false,
|
|
305
|
-
idempotentHint: true,
|
|
306
|
-
openWorldHint: false,
|
|
307
|
-
},
|
|
308
|
-
},
|
|
309
162
|
{
|
|
310
163
|
name: "engram_web",
|
|
311
164
|
description: "Launch the Engram web interface for browsing, searching, and editing memories visually. Returns a URL to open in your browser.",
|
|
@@ -440,177 +293,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
440
293
|
};
|
|
441
294
|
}
|
|
442
295
|
|
|
443
|
-
case "create_entity": {
|
|
444
|
-
const { name: entityName, type } = args as {
|
|
445
|
-
name: string;
|
|
446
|
-
type: "person" | "place" | "concept" | "event" | "organization";
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
const entity = graph.getOrCreateEntity(entityName, type);
|
|
450
|
-
|
|
451
|
-
return {
|
|
452
|
-
content: [
|
|
453
|
-
{
|
|
454
|
-
type: "text" as const,
|
|
455
|
-
text: JSON.stringify({
|
|
456
|
-
success: true,
|
|
457
|
-
entity: {
|
|
458
|
-
id: entity.id,
|
|
459
|
-
name: entity.name,
|
|
460
|
-
type: entity.type,
|
|
461
|
-
},
|
|
462
|
-
}, null, 2),
|
|
463
|
-
},
|
|
464
|
-
],
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
case "observe": {
|
|
469
|
-
const { entity: entityName, observation, confidence = 1.0 } = args as {
|
|
470
|
-
entity: string;
|
|
471
|
-
observation: string;
|
|
472
|
-
confidence?: number;
|
|
473
|
-
};
|
|
474
|
-
|
|
475
|
-
// Ensure entity exists
|
|
476
|
-
const entity = graph.getOrCreateEntity(entityName, "person");
|
|
477
|
-
|
|
478
|
-
// Add observation
|
|
479
|
-
const obs = graph.addObservation(entity.id, observation, undefined, confidence);
|
|
480
|
-
|
|
481
|
-
return {
|
|
482
|
-
content: [
|
|
483
|
-
{
|
|
484
|
-
type: "text" as const,
|
|
485
|
-
text: JSON.stringify({
|
|
486
|
-
success: true,
|
|
487
|
-
entity: entity.name,
|
|
488
|
-
observation_id: obs.id,
|
|
489
|
-
}, null, 2),
|
|
490
|
-
},
|
|
491
|
-
],
|
|
492
|
-
};
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
case "relate": {
|
|
496
|
-
const { from, to, relation } = args as {
|
|
497
|
-
from: string;
|
|
498
|
-
to: string;
|
|
499
|
-
relation: string;
|
|
500
|
-
};
|
|
501
|
-
|
|
502
|
-
// Ensure both entities exist
|
|
503
|
-
const fromEntity = graph.getOrCreateEntity(from, "person");
|
|
504
|
-
const toEntity = graph.getOrCreateEntity(to, "person");
|
|
505
|
-
|
|
506
|
-
// Create relation
|
|
507
|
-
const rel = graph.relate(fromEntity.id, toEntity.id, relation);
|
|
508
|
-
|
|
509
|
-
return {
|
|
510
|
-
content: [
|
|
511
|
-
{
|
|
512
|
-
type: "text" as const,
|
|
513
|
-
text: JSON.stringify({
|
|
514
|
-
success: true,
|
|
515
|
-
relation: {
|
|
516
|
-
id: rel.id,
|
|
517
|
-
from: fromEntity.name,
|
|
518
|
-
to: toEntity.name,
|
|
519
|
-
type: rel.type,
|
|
520
|
-
},
|
|
521
|
-
}, null, 2),
|
|
522
|
-
},
|
|
523
|
-
],
|
|
524
|
-
};
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
case "query_entity": {
|
|
528
|
-
const { entity: entityName } = args as { entity: string };
|
|
529
|
-
|
|
530
|
-
const details = graph.getEntityDetails(entityName);
|
|
531
|
-
|
|
532
|
-
if (!details) {
|
|
533
|
-
return {
|
|
534
|
-
content: [
|
|
535
|
-
{
|
|
536
|
-
type: "text" as const,
|
|
537
|
-
text: JSON.stringify({ success: false, error: "Entity not found" }),
|
|
538
|
-
},
|
|
539
|
-
],
|
|
540
|
-
};
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
return {
|
|
544
|
-
content: [
|
|
545
|
-
{
|
|
546
|
-
type: "text" as const,
|
|
547
|
-
text: JSON.stringify({
|
|
548
|
-
entity: {
|
|
549
|
-
id: details.id,
|
|
550
|
-
name: details.name,
|
|
551
|
-
type: details.type,
|
|
552
|
-
created_at: details.created_at.toISOString(),
|
|
553
|
-
},
|
|
554
|
-
observations: details.observations.map((o) => ({
|
|
555
|
-
content: o.content.substring(0, 200) + (o.content.length > 200 ? "..." : ""),
|
|
556
|
-
confidence: o.confidence,
|
|
557
|
-
valid_from: o.valid_from.toISOString(),
|
|
558
|
-
})),
|
|
559
|
-
relations_from: details.relationsFrom.map((r) => ({
|
|
560
|
-
type: r.type,
|
|
561
|
-
to: r.targetEntity.name,
|
|
562
|
-
})),
|
|
563
|
-
relations_to: details.relationsTo.map((r) => ({
|
|
564
|
-
type: r.type,
|
|
565
|
-
from: r.sourceEntity.name,
|
|
566
|
-
})),
|
|
567
|
-
}, null, 2),
|
|
568
|
-
},
|
|
569
|
-
],
|
|
570
|
-
};
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
case "list_entities": {
|
|
574
|
-
const { type, limit = 50 } = args as {
|
|
575
|
-
type?: "person" | "place" | "concept" | "event" | "organization";
|
|
576
|
-
limit?: number;
|
|
577
|
-
};
|
|
578
|
-
|
|
579
|
-
const entities = graph.listEntities(type, limit);
|
|
580
|
-
|
|
581
|
-
return {
|
|
582
|
-
content: [
|
|
583
|
-
{
|
|
584
|
-
type: "text" as const,
|
|
585
|
-
text: JSON.stringify({
|
|
586
|
-
entities: entities.map((e) => ({
|
|
587
|
-
id: e.id,
|
|
588
|
-
name: e.name,
|
|
589
|
-
type: e.type,
|
|
590
|
-
})),
|
|
591
|
-
count: entities.length,
|
|
592
|
-
}, null, 2),
|
|
593
|
-
},
|
|
594
|
-
],
|
|
595
|
-
};
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
case "stats": {
|
|
599
|
-
const stats = db.getStats();
|
|
600
|
-
|
|
601
|
-
return {
|
|
602
|
-
content: [
|
|
603
|
-
{
|
|
604
|
-
type: "text" as const,
|
|
605
|
-
text: JSON.stringify({
|
|
606
|
-
...stats,
|
|
607
|
-
database_path: DB_FILE,
|
|
608
|
-
}, null, 2),
|
|
609
|
-
},
|
|
610
|
-
],
|
|
611
|
-
};
|
|
612
|
-
}
|
|
613
|
-
|
|
614
296
|
case "engram_web": {
|
|
615
297
|
const { port = 3847 } = args as { port?: number };
|
|
616
298
|
|
package/src/storage/database.ts
CHANGED
|
@@ -358,6 +358,41 @@ export class EngramDatabase {
|
|
|
358
358
|
return shared / total * 0.7;
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
+
/**
|
|
362
|
+
* Merge two entities: transfers all observations and relations from source to target, then deletes source
|
|
363
|
+
*/
|
|
364
|
+
mergeEntities(targetId: string, sourceId: string): { observationsMoved: number; relationsMoved: number } {
|
|
365
|
+
// Move observations from source to target
|
|
366
|
+
const obsResult = this.db.prepare(
|
|
367
|
+
"UPDATE observations SET entity_id = ? WHERE entity_id = ?"
|
|
368
|
+
).run(targetId, sourceId);
|
|
369
|
+
|
|
370
|
+
// Move relations where source is from_entity
|
|
371
|
+
const relFromResult = this.db.prepare(
|
|
372
|
+
"UPDATE relations SET from_entity = ? WHERE from_entity = ?"
|
|
373
|
+
).run(targetId, sourceId);
|
|
374
|
+
|
|
375
|
+
// Move relations where source is to_entity
|
|
376
|
+
const relToResult = this.db.prepare(
|
|
377
|
+
"UPDATE relations SET to_entity = ? WHERE to_entity = ?"
|
|
378
|
+
).run(targetId, sourceId);
|
|
379
|
+
|
|
380
|
+
// Delete duplicate relations (same from, to, type)
|
|
381
|
+
this.db.prepare(`
|
|
382
|
+
DELETE FROM relations WHERE id NOT IN (
|
|
383
|
+
SELECT MIN(id) FROM relations GROUP BY from_entity, to_entity, type
|
|
384
|
+
)
|
|
385
|
+
`).run();
|
|
386
|
+
|
|
387
|
+
// Delete the source entity
|
|
388
|
+
this.deleteEntity(sourceId);
|
|
389
|
+
|
|
390
|
+
return {
|
|
391
|
+
observationsMoved: obsResult.changes,
|
|
392
|
+
relationsMoved: relFromResult.changes + relToResult.changes,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
|
|
361
396
|
/**
|
|
362
397
|
* Find all potential duplicate entities
|
|
363
398
|
*/
|
package/src/web/server.ts
CHANGED
|
@@ -226,6 +226,47 @@ export class EngramWebServer {
|
|
|
226
226
|
return;
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
+
// GET /api/tidy - analyze duplicates
|
|
230
|
+
if (pathname === "/api/tidy" && method === "GET") {
|
|
231
|
+
const duplicates = this.db.findDuplicateEntities();
|
|
232
|
+
res.end(JSON.stringify({
|
|
233
|
+
duplicate_groups: duplicates.map((d) => ({
|
|
234
|
+
keep: { id: d.entity.id, name: d.entity.name, type: d.entity.type },
|
|
235
|
+
merge: d.potentialDuplicates.map((p) => ({
|
|
236
|
+
id: p.id,
|
|
237
|
+
name: p.name,
|
|
238
|
+
type: p.type,
|
|
239
|
+
})),
|
|
240
|
+
})),
|
|
241
|
+
total_duplicates: duplicates.reduce((sum, d) => sum + d.potentialDuplicates.length, 0),
|
|
242
|
+
}));
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// POST /api/tidy - merge duplicates
|
|
247
|
+
if (pathname === "/api/tidy" && method === "POST") {
|
|
248
|
+
const duplicates = this.db.findDuplicateEntities();
|
|
249
|
+
let totalMerged = 0;
|
|
250
|
+
let observationsMoved = 0;
|
|
251
|
+
let relationsMoved = 0;
|
|
252
|
+
|
|
253
|
+
for (const group of duplicates) {
|
|
254
|
+
for (const dupe of group.potentialDuplicates) {
|
|
255
|
+
const result = this.db.mergeEntities(group.entity.id, dupe.id);
|
|
256
|
+
totalMerged++;
|
|
257
|
+
observationsMoved += result.observationsMoved;
|
|
258
|
+
relationsMoved += result.relationsMoved;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
res.end(JSON.stringify({
|
|
263
|
+
entities_merged: totalMerged,
|
|
264
|
+
observations_moved: observationsMoved,
|
|
265
|
+
relations_moved: relationsMoved,
|
|
266
|
+
}));
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
|
|
229
270
|
// 404 for unknown API routes
|
|
230
271
|
res.writeHead(404);
|
|
231
272
|
res.end(JSON.stringify({ error: "Not found" }));
|