@199-bio/engram 0.8.0 → 0.8.1
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/consolidation/consolidator.d.ts.map +1 -1
- package/dist/index.js +122 -6
- package/dist/retrieval/hybrid.d.ts.map +1 -1
- package/dist/storage/database.d.ts.map +1 -1
- package/dist/web/chat-handler.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/consolidation/consolidator.ts +38 -10
- package/src/index.ts +131 -6
- package/src/retrieval/hybrid.ts +6 -2
- package/src/storage/database.ts +51 -38
- package/src/web/chat-handler.ts +58 -55
|
@@ -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,EAAW,MAAM,wBAAwB,CAAC;AAEjF,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;
|
|
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;AAEjF,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,YAAY,CAAuB;IAC3C,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;IAUvB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAmBpB,YAAY,IAAI,OAAO;IAKvB;;;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;IAyEF;;OAEG;YACW,gBAAgB;IAqE9B;;OAEG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAwHjE;;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;IAyFF;;OAEG;YACW,2BAA2B;IAsDzC;;;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;QAC5B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;CA4BH"}
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
10
10
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
11
11
|
import path from "path";
|
|
12
12
|
import os from "os";
|
|
13
|
+
import fs from "fs";
|
|
13
14
|
import { EngramDatabase } from "./storage/database.js";
|
|
14
15
|
import { KnowledgeGraph } from "./graph/knowledge-graph.js";
|
|
15
16
|
import { createRetriever } from "./retrieval/colbert.js";
|
|
@@ -21,6 +22,94 @@ const DB_PATH = process.env.ENGRAM_DB_PATH
|
|
|
21
22
|
? path.resolve(process.env.ENGRAM_DB_PATH.replace("~", os.homedir()))
|
|
22
23
|
: path.join(os.homedir(), ".engram");
|
|
23
24
|
const DB_FILE = path.join(DB_PATH, "engram.db");
|
|
25
|
+
const PID_FILE = path.join(DB_PATH, "engram.pid");
|
|
26
|
+
// ============ Zombie Prevention ============
|
|
27
|
+
/**
|
|
28
|
+
* Kill any existing engram process and clean up stale PID file
|
|
29
|
+
*/
|
|
30
|
+
function cleanupZombies() {
|
|
31
|
+
try {
|
|
32
|
+
if (fs.existsSync(PID_FILE)) {
|
|
33
|
+
const oldPid = parseInt(fs.readFileSync(PID_FILE, "utf-8").trim(), 10);
|
|
34
|
+
if (oldPid && oldPid !== process.pid) {
|
|
35
|
+
try {
|
|
36
|
+
// Check if process exists
|
|
37
|
+
process.kill(oldPid, 0);
|
|
38
|
+
// It exists, kill it
|
|
39
|
+
console.error(`[Engram] Killing old instance (PID ${oldPid})`);
|
|
40
|
+
process.kill(oldPid, "SIGTERM");
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Process doesn't exist, that's fine
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
fs.unlinkSync(PID_FILE);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.error("[Engram] Error cleaning up zombies:", error);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Write our PID file
|
|
55
|
+
*/
|
|
56
|
+
function writePidFile() {
|
|
57
|
+
try {
|
|
58
|
+
// Ensure directory exists
|
|
59
|
+
if (!fs.existsSync(DB_PATH)) {
|
|
60
|
+
fs.mkdirSync(DB_PATH, { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
fs.writeFileSync(PID_FILE, String(process.pid));
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
console.error("[Engram] Error writing PID file:", error);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Clean up on exit
|
|
70
|
+
*/
|
|
71
|
+
function cleanup() {
|
|
72
|
+
try {
|
|
73
|
+
if (fs.existsSync(PID_FILE)) {
|
|
74
|
+
const storedPid = parseInt(fs.readFileSync(PID_FILE, "utf-8").trim(), 10);
|
|
75
|
+
if (storedPid === process.pid) {
|
|
76
|
+
fs.unlinkSync(PID_FILE);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (webServer) {
|
|
80
|
+
webServer.stop();
|
|
81
|
+
}
|
|
82
|
+
if (db) {
|
|
83
|
+
db.close();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Ignore cleanup errors
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Register signal handlers early
|
|
91
|
+
process.on("SIGTERM", () => {
|
|
92
|
+
console.error("[Engram] Received SIGTERM, shutting down...");
|
|
93
|
+
cleanup();
|
|
94
|
+
process.exit(0);
|
|
95
|
+
});
|
|
96
|
+
process.on("SIGINT", () => {
|
|
97
|
+
console.error("[Engram] Received SIGINT, shutting down...");
|
|
98
|
+
cleanup();
|
|
99
|
+
process.exit(0);
|
|
100
|
+
});
|
|
101
|
+
process.on("exit", cleanup);
|
|
102
|
+
// Detect when parent process (Claude) dies by monitoring stdin
|
|
103
|
+
process.stdin.on("end", () => {
|
|
104
|
+
console.error("[Engram] stdin closed, parent process likely died. Shutting down...");
|
|
105
|
+
cleanup();
|
|
106
|
+
process.exit(0);
|
|
107
|
+
});
|
|
108
|
+
process.stdin.on("close", () => {
|
|
109
|
+
console.error("[Engram] stdin closed, shutting down...");
|
|
110
|
+
cleanup();
|
|
111
|
+
process.exit(0);
|
|
112
|
+
});
|
|
24
113
|
// ============ Initialize Components ============
|
|
25
114
|
let db;
|
|
26
115
|
let graph;
|
|
@@ -540,9 +629,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
540
629
|
}
|
|
541
630
|
case "memory_feedback": {
|
|
542
631
|
const { recall_id, useful_memory_ids, need_more = false } = args;
|
|
543
|
-
//
|
|
544
|
-
const
|
|
545
|
-
if (!
|
|
632
|
+
// First, get the original recall to validate useful_memory_ids
|
|
633
|
+
const retrievalLog = db.getRetrievalLog(recall_id);
|
|
634
|
+
if (!retrievalLog) {
|
|
546
635
|
return {
|
|
547
636
|
content: [
|
|
548
637
|
{
|
|
@@ -555,6 +644,30 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
555
644
|
],
|
|
556
645
|
};
|
|
557
646
|
}
|
|
647
|
+
// Validate: only accept IDs that were in the original recall
|
|
648
|
+
const originalIdSet = new Set(retrievalLog.memory_ids);
|
|
649
|
+
const validUsefulIds = useful_memory_ids.filter(id => originalIdSet.has(id));
|
|
650
|
+
const invalidIds = useful_memory_ids.filter(id => !originalIdSet.has(id));
|
|
651
|
+
if (invalidIds.length > 0) {
|
|
652
|
+
console.error(`[Engram] memory_feedback: ${invalidIds.length} IDs not in original recall, ignored: ${invalidIds.join(", ")}`);
|
|
653
|
+
}
|
|
654
|
+
// Update the retrieval log with validated feedback
|
|
655
|
+
const updated = db.updateRetrievalFeedback(recall_id, validUsefulIds, need_more);
|
|
656
|
+
if (!updated) {
|
|
657
|
+
// Should not happen since we already checked above, but handle gracefully
|
|
658
|
+
console.error(`[Engram] memory_feedback: failed to update retrieval log ${recall_id}`);
|
|
659
|
+
return {
|
|
660
|
+
content: [
|
|
661
|
+
{
|
|
662
|
+
type: "text",
|
|
663
|
+
text: JSON.stringify({
|
|
664
|
+
success: false,
|
|
665
|
+
error: `Failed to update feedback for: ${recall_id}`,
|
|
666
|
+
}),
|
|
667
|
+
},
|
|
668
|
+
],
|
|
669
|
+
};
|
|
670
|
+
}
|
|
558
671
|
// If need_more is set, do an expanded search
|
|
559
672
|
if (need_more) {
|
|
560
673
|
const expandedResponse = await search.expandSearch(recall_id);
|
|
@@ -576,7 +689,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
576
689
|
text: JSON.stringify({
|
|
577
690
|
success: true,
|
|
578
691
|
feedback_recorded: true,
|
|
579
|
-
useful_count:
|
|
692
|
+
useful_count: validUsefulIds.length,
|
|
580
693
|
expanded_search: true,
|
|
581
694
|
additional_results: formatted,
|
|
582
695
|
additional_count: formatted.length,
|
|
@@ -605,7 +718,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
605
718
|
text: JSON.stringify({
|
|
606
719
|
success: true,
|
|
607
720
|
feedback_recorded: true,
|
|
608
|
-
useful_count:
|
|
721
|
+
useful_count: validUsefulIds.length,
|
|
609
722
|
learning_applied: learningApplied > 0,
|
|
610
723
|
connections_strengthened: learningApplied,
|
|
611
724
|
}, null, 2),
|
|
@@ -632,10 +745,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
632
745
|
});
|
|
633
746
|
// ============ Main ============
|
|
634
747
|
async function main() {
|
|
748
|
+
// Kill any zombie instances before starting
|
|
749
|
+
cleanupZombies();
|
|
750
|
+
writePidFile();
|
|
635
751
|
await initialize();
|
|
636
752
|
const transport = new StdioServerTransport();
|
|
637
753
|
await server.connect(transport);
|
|
638
|
-
console.error(
|
|
754
|
+
console.error(`[Engram] MCP server running on stdio (PID ${process.pid})`);
|
|
639
755
|
}
|
|
640
756
|
main().catch((error) => {
|
|
641
757
|
console.error("[Engram] Fatal error:", error);
|
|
@@ -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;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,KAAK,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ;AAwDD,qBAAa,YAAY;IAIrB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,SAAS;IALnB,OAAO,CAAC,SAAS,CAAS;gBAGhB,EAAE,EAAE,cAAc,EAClB,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,gBAAgB,GAAG,eAAe;IAMvD;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;;;;OAKG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;KACnB,GACL,OAAO,CAAC,oBAAoB,CAAC;
|
|
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;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,KAAK,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ;AAwDD,qBAAa,YAAY;IAIrB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,SAAS;IALnB,OAAO,CAAC,SAAS,CAAS;gBAGhB,EAAE,EAAE,cAAc,EAClB,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,gBAAgB,GAAG,eAAe;IAMvD;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;;;;OAKG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;KACnB,GACL,OAAO,CAAC,oBAAoB,CAAC;IA2NhC;;;OAGG;IACG,YAAY,CAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,MAAM,CAAA;KAAO,GACzC,OAAO,CAAC,oBAAoB,CAAC;IAyBhC;;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":"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
|
|
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;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,IAAI,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,SAAS,CAA8C;gBAEnD,MAAM,EAAE,MAAM;IAoB1B,OAAO,CAAC,UAAU;IAuMlB;;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,EAAE,MAAM,GAAE,MAAU,GAAG,MAAM,EAAE;IAUpG;;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;;;OAGG;IACH,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,gBAAgB;IAqBzE,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAKlD;;OAEG;IACH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,GAAE,MAAU,GAAG,gBAAgB,EAAE;IASnF;;OAEG;IACH,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,WAAW,GAAE,MAAY,EAAE,KAAK,GAAE,MAAW,GAAG,MAAM,EAAE;IAoBnG;;;OAGG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IA0B5C;;;;OAIG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAmCzC;;OAEG;IACH,gBAAgB,CAAC,aAAa,GAAE,MAAW,EAAE,WAAW,GAAE,MAAY,GAAG,MAAM;IAkB/E;;OAEG;IACH,kBAAkB,CAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EAAE,GAClB,YAAY;IASf,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAKtD;;OAEG;IACH,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO;IAS1F;;OAEG;IACH,2BAA2B,CAAC,KAAK,GAAE,MAAY,GAAG,YAAY,EAAE;IAUhE;;OAEG;IACH,0BAA0B,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI;IAQ/C;;OAEG;IACH,oBAAoB,CAAC,OAAO,GAAE,MAAU,GAAG,MAAM;IAUjD,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;IAc1B,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,iBAAiB;CAa1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-handler.d.ts","sourceRoot":"","sources":["../../src/web/chat-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAkB,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"chat-handler.d.ts","sourceRoot":"","sources":["../../src/web/chat-handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAkB,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAwQtD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,EAAE,CAAiB;IAC3B,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,mBAAmB,CAAgC;IAC3D,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,YAAY,CAAoG;gBAE5G,OAAO,EAAE;QACnB,EAAE,EAAE,cAAc,CAAC;QACnB,KAAK,EAAE,cAAc,CAAC;QACtB,MAAM,EAAE,YAAY,CAAC;KACtB;IASD;;OAEG;IACH,aAAa,IAAI,IAAI;IAYrB,YAAY,IAAI,OAAO;IAMvB,MAAM,IAAI,OAAO;IAIjB,cAAc,IAAI,MAAM;IAIxB,YAAY,IAAI,IAAI;YAKN,YAAY;IAgBpB,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiBzC,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,CAAC,WAAW,CAAC;YA6GrD,cAAc;YAkFd,WAAW;CAoQ1B"}
|
package/package.json
CHANGED
|
@@ -112,6 +112,7 @@ interface ConsolidateOptions {
|
|
|
112
112
|
|
|
113
113
|
export class Consolidator {
|
|
114
114
|
private client: Anthropic | null = null;
|
|
115
|
+
private cachedApiKey: string | null = null;
|
|
115
116
|
private db: EngramDatabase;
|
|
116
117
|
private graph: KnowledgeGraph | null = null;
|
|
117
118
|
private search: HybridSearch | null = null;
|
|
@@ -125,14 +126,36 @@ export class Consolidator {
|
|
|
125
126
|
this.graph = graph || null;
|
|
126
127
|
this.search = search || null;
|
|
127
128
|
|
|
129
|
+
// Initial check
|
|
130
|
+
this.ensureClient();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Ensure client is configured with latest API key
|
|
135
|
+
* Lazy initialization: checks for new/updated API key each call
|
|
136
|
+
*/
|
|
137
|
+
private ensureClient(): Anthropic | null {
|
|
128
138
|
const apiKey = getAnthropicApiKey();
|
|
129
|
-
|
|
139
|
+
|
|
140
|
+
if (!apiKey) {
|
|
141
|
+
this.client = null;
|
|
142
|
+
this.cachedApiKey = null;
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Only recreate client if API key changed
|
|
147
|
+
if (apiKey !== this.cachedApiKey) {
|
|
148
|
+
console.error(`[Engram] Consolidator: API key ${this.cachedApiKey ? "updated" : "configured"}`);
|
|
130
149
|
this.client = new Anthropic({ apiKey });
|
|
150
|
+
this.cachedApiKey = apiKey;
|
|
131
151
|
}
|
|
152
|
+
|
|
153
|
+
return this.client;
|
|
132
154
|
}
|
|
133
155
|
|
|
134
156
|
isConfigured(): boolean {
|
|
135
|
-
|
|
157
|
+
// Re-check in case API key was added after startup
|
|
158
|
+
return this.ensureClient() !== null;
|
|
136
159
|
}
|
|
137
160
|
|
|
138
161
|
/**
|
|
@@ -144,7 +167,8 @@ export class Consolidator {
|
|
|
144
167
|
contradictionsFound: number;
|
|
145
168
|
memoriesProcessed: number;
|
|
146
169
|
}> {
|
|
147
|
-
|
|
170
|
+
const client = this.ensureClient();
|
|
171
|
+
if (!client) {
|
|
148
172
|
throw new Error("Consolidator not configured - set ANTHROPIC_API_KEY");
|
|
149
173
|
}
|
|
150
174
|
|
|
@@ -221,7 +245,8 @@ export class Consolidator {
|
|
|
221
245
|
private async consolidateBatch(
|
|
222
246
|
memories: Memory[]
|
|
223
247
|
): Promise<ConsolidationResult | null> {
|
|
224
|
-
|
|
248
|
+
const client = this.ensureClient();
|
|
249
|
+
if (!client) return null;
|
|
225
250
|
|
|
226
251
|
// Format memories for the prompt
|
|
227
252
|
const memoriesText = memories
|
|
@@ -246,7 +271,7 @@ ${memoriesText}
|
|
|
246
271
|
Create a detailed digest that preserves all important information. Respond with JSON only.`;
|
|
247
272
|
|
|
248
273
|
try {
|
|
249
|
-
const response = await
|
|
274
|
+
const response = await client.messages.create({
|
|
250
275
|
model: "claude-opus-4-5-20251101",
|
|
251
276
|
max_tokens: 16000,
|
|
252
277
|
temperature: 1, // Required for extended thinking
|
|
@@ -290,7 +315,8 @@ Create a detailed digest that preserves all important information. Respond with
|
|
|
290
315
|
* Create an entity profile by consolidating all observations about an entity
|
|
291
316
|
*/
|
|
292
317
|
async consolidateEntity(entityId: string): Promise<Digest | null> {
|
|
293
|
-
|
|
318
|
+
const client = this.ensureClient();
|
|
319
|
+
if (!client) {
|
|
294
320
|
throw new Error("Consolidator not configured - set ANTHROPIC_API_KEY");
|
|
295
321
|
}
|
|
296
322
|
|
|
@@ -335,7 +361,7 @@ ${memoriesText}
|
|
|
335
361
|
Create a rich, detailed profile. Do not summarize away important nuances. Respond with JSON only.`;
|
|
336
362
|
|
|
337
363
|
try {
|
|
338
|
-
const response = await
|
|
364
|
+
const response = await client.messages.create({
|
|
339
365
|
model: "claude-opus-4-5-20251101",
|
|
340
366
|
max_tokens: 16000,
|
|
341
367
|
temperature: 1, // Required for extended thinking
|
|
@@ -444,7 +470,8 @@ Create a rich, detailed profile. Do not summarize away important nuances. Respon
|
|
|
444
470
|
memoriesCreated: number;
|
|
445
471
|
entitiesCreated: number;
|
|
446
472
|
}> {
|
|
447
|
-
|
|
473
|
+
const client = this.ensureClient();
|
|
474
|
+
if (!client) {
|
|
448
475
|
throw new Error("Consolidator not configured - set ANTHROPIC_API_KEY");
|
|
449
476
|
}
|
|
450
477
|
|
|
@@ -537,7 +564,8 @@ Create a rich, detailed profile. Do not summarize away important nuances. Respon
|
|
|
537
564
|
private async extractMemoriesFromEpisodes(
|
|
538
565
|
episodes: Episode[]
|
|
539
566
|
): Promise<EpisodeExtractionResult | null> {
|
|
540
|
-
|
|
567
|
+
const client = this.ensureClient();
|
|
568
|
+
if (!client) return null;
|
|
541
569
|
|
|
542
570
|
// Format conversation
|
|
543
571
|
const conversationText = episodes
|
|
@@ -555,7 +583,7 @@ Respond with JSON only.`;
|
|
|
555
583
|
|
|
556
584
|
try {
|
|
557
585
|
// Use Haiku for speed/cost (no extended thinking needed)
|
|
558
|
-
const response = await
|
|
586
|
+
const response = await client.messages.create({
|
|
559
587
|
model: "claude-haiku-4-5-20251201",
|
|
560
588
|
max_tokens: 4000,
|
|
561
589
|
messages: [
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
15
15
|
import path from "path";
|
|
16
16
|
import os from "os";
|
|
17
|
+
import fs from "fs";
|
|
17
18
|
|
|
18
19
|
import { EngramDatabase } from "./storage/database.js";
|
|
19
20
|
import { KnowledgeGraph } from "./graph/knowledge-graph.js";
|
|
@@ -29,6 +30,99 @@ const DB_PATH = process.env.ENGRAM_DB_PATH
|
|
|
29
30
|
: path.join(os.homedir(), ".engram");
|
|
30
31
|
|
|
31
32
|
const DB_FILE = path.join(DB_PATH, "engram.db");
|
|
33
|
+
const PID_FILE = path.join(DB_PATH, "engram.pid");
|
|
34
|
+
|
|
35
|
+
// ============ Zombie Prevention ============
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Kill any existing engram process and clean up stale PID file
|
|
39
|
+
*/
|
|
40
|
+
function cleanupZombies(): void {
|
|
41
|
+
try {
|
|
42
|
+
if (fs.existsSync(PID_FILE)) {
|
|
43
|
+
const oldPid = parseInt(fs.readFileSync(PID_FILE, "utf-8").trim(), 10);
|
|
44
|
+
if (oldPid && oldPid !== process.pid) {
|
|
45
|
+
try {
|
|
46
|
+
// Check if process exists
|
|
47
|
+
process.kill(oldPid, 0);
|
|
48
|
+
// It exists, kill it
|
|
49
|
+
console.error(`[Engram] Killing old instance (PID ${oldPid})`);
|
|
50
|
+
process.kill(oldPid, "SIGTERM");
|
|
51
|
+
} catch {
|
|
52
|
+
// Process doesn't exist, that's fine
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
fs.unlinkSync(PID_FILE);
|
|
56
|
+
}
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error("[Engram] Error cleaning up zombies:", error);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Write our PID file
|
|
64
|
+
*/
|
|
65
|
+
function writePidFile(): void {
|
|
66
|
+
try {
|
|
67
|
+
// Ensure directory exists
|
|
68
|
+
if (!fs.existsSync(DB_PATH)) {
|
|
69
|
+
fs.mkdirSync(DB_PATH, { recursive: true });
|
|
70
|
+
}
|
|
71
|
+
fs.writeFileSync(PID_FILE, String(process.pid));
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error("[Engram] Error writing PID file:", error);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Clean up on exit
|
|
79
|
+
*/
|
|
80
|
+
function cleanup(): void {
|
|
81
|
+
try {
|
|
82
|
+
if (fs.existsSync(PID_FILE)) {
|
|
83
|
+
const storedPid = parseInt(fs.readFileSync(PID_FILE, "utf-8").trim(), 10);
|
|
84
|
+
if (storedPid === process.pid) {
|
|
85
|
+
fs.unlinkSync(PID_FILE);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (webServer) {
|
|
89
|
+
webServer.stop();
|
|
90
|
+
}
|
|
91
|
+
if (db) {
|
|
92
|
+
db.close();
|
|
93
|
+
}
|
|
94
|
+
} catch {
|
|
95
|
+
// Ignore cleanup errors
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Register signal handlers early
|
|
100
|
+
process.on("SIGTERM", () => {
|
|
101
|
+
console.error("[Engram] Received SIGTERM, shutting down...");
|
|
102
|
+
cleanup();
|
|
103
|
+
process.exit(0);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
process.on("SIGINT", () => {
|
|
107
|
+
console.error("[Engram] Received SIGINT, shutting down...");
|
|
108
|
+
cleanup();
|
|
109
|
+
process.exit(0);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
process.on("exit", cleanup);
|
|
113
|
+
|
|
114
|
+
// Detect when parent process (Claude) dies by monitoring stdin
|
|
115
|
+
process.stdin.on("end", () => {
|
|
116
|
+
console.error("[Engram] stdin closed, parent process likely died. Shutting down...");
|
|
117
|
+
cleanup();
|
|
118
|
+
process.exit(0);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
process.stdin.on("close", () => {
|
|
122
|
+
console.error("[Engram] stdin closed, shutting down...");
|
|
123
|
+
cleanup();
|
|
124
|
+
process.exit(0);
|
|
125
|
+
});
|
|
32
126
|
|
|
33
127
|
// ============ Initialize Components ============
|
|
34
128
|
|
|
@@ -624,17 +718,44 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
624
718
|
need_more?: boolean;
|
|
625
719
|
};
|
|
626
720
|
|
|
627
|
-
//
|
|
628
|
-
const
|
|
721
|
+
// First, get the original recall to validate useful_memory_ids
|
|
722
|
+
const retrievalLog = db.getRetrievalLog(recall_id);
|
|
723
|
+
if (!retrievalLog) {
|
|
724
|
+
return {
|
|
725
|
+
content: [
|
|
726
|
+
{
|
|
727
|
+
type: "text" as const,
|
|
728
|
+
text: JSON.stringify({
|
|
729
|
+
success: false,
|
|
730
|
+
error: `Recall ID not found: ${recall_id}`,
|
|
731
|
+
}),
|
|
732
|
+
},
|
|
733
|
+
],
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// Validate: only accept IDs that were in the original recall
|
|
738
|
+
const originalIdSet = new Set(retrievalLog.memory_ids);
|
|
739
|
+
const validUsefulIds = useful_memory_ids.filter(id => originalIdSet.has(id));
|
|
740
|
+
const invalidIds = useful_memory_ids.filter(id => !originalIdSet.has(id));
|
|
741
|
+
|
|
742
|
+
if (invalidIds.length > 0) {
|
|
743
|
+
console.error(`[Engram] memory_feedback: ${invalidIds.length} IDs not in original recall, ignored: ${invalidIds.join(", ")}`);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// Update the retrieval log with validated feedback
|
|
747
|
+
const updated = db.updateRetrievalFeedback(recall_id, validUsefulIds, need_more);
|
|
629
748
|
|
|
630
749
|
if (!updated) {
|
|
750
|
+
// Should not happen since we already checked above, but handle gracefully
|
|
751
|
+
console.error(`[Engram] memory_feedback: failed to update retrieval log ${recall_id}`);
|
|
631
752
|
return {
|
|
632
753
|
content: [
|
|
633
754
|
{
|
|
634
755
|
type: "text" as const,
|
|
635
756
|
text: JSON.stringify({
|
|
636
757
|
success: false,
|
|
637
|
-
error: `
|
|
758
|
+
error: `Failed to update feedback for: ${recall_id}`,
|
|
638
759
|
}),
|
|
639
760
|
},
|
|
640
761
|
],
|
|
@@ -664,7 +785,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
664
785
|
text: JSON.stringify({
|
|
665
786
|
success: true,
|
|
666
787
|
feedback_recorded: true,
|
|
667
|
-
useful_count:
|
|
788
|
+
useful_count: validUsefulIds.length,
|
|
668
789
|
expanded_search: true,
|
|
669
790
|
additional_results: formatted,
|
|
670
791
|
additional_count: formatted.length,
|
|
@@ -697,7 +818,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
697
818
|
text: JSON.stringify({
|
|
698
819
|
success: true,
|
|
699
820
|
feedback_recorded: true,
|
|
700
|
-
useful_count:
|
|
821
|
+
useful_count: validUsefulIds.length,
|
|
701
822
|
learning_applied: learningApplied > 0,
|
|
702
823
|
connections_strengthened: learningApplied,
|
|
703
824
|
}, null, 2),
|
|
@@ -726,12 +847,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
726
847
|
// ============ Main ============
|
|
727
848
|
|
|
728
849
|
async function main() {
|
|
850
|
+
// Kill any zombie instances before starting
|
|
851
|
+
cleanupZombies();
|
|
852
|
+
writePidFile();
|
|
853
|
+
|
|
729
854
|
await initialize();
|
|
730
855
|
|
|
731
856
|
const transport = new StdioServerTransport();
|
|
732
857
|
await server.connect(transport);
|
|
733
858
|
|
|
734
|
-
console.error(
|
|
859
|
+
console.error(`[Engram] MCP server running on stdio (PID ${process.pid})`);
|
|
735
860
|
}
|
|
736
861
|
|
|
737
862
|
main().catch((error) => {
|
package/src/retrieval/hybrid.ts
CHANGED
|
@@ -327,8 +327,12 @@ export class HybridSearch {
|
|
|
327
327
|
// Log this retrieval for deferred learning
|
|
328
328
|
try {
|
|
329
329
|
this.db.createRetrievalLog(this.sessionId, recallId, query, allResultIds);
|
|
330
|
-
} catch {
|
|
331
|
-
//
|
|
330
|
+
} catch (error) {
|
|
331
|
+
// Only ignore duplicate recall_id errors (UNIQUE constraint), log all others
|
|
332
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
333
|
+
if (!msg.includes("UNIQUE constraint")) {
|
|
334
|
+
console.error(`[Engram] Failed to create retrieval log: ${msg}`);
|
|
335
|
+
}
|
|
332
336
|
}
|
|
333
337
|
|
|
334
338
|
return {
|
package/src/storage/database.ts
CHANGED
|
@@ -1183,59 +1183,72 @@ export class EngramDatabase {
|
|
|
1183
1183
|
|
|
1184
1184
|
/**
|
|
1185
1185
|
* Record that memories were retrieved together (co-retrieval)
|
|
1186
|
+
* Uses cached statement and transaction for O(n²) efficiency
|
|
1186
1187
|
*/
|
|
1187
1188
|
recordCoRetrieval(memoryIds: string[]): void {
|
|
1188
1189
|
if (memoryIds.length < 2) return;
|
|
1189
1190
|
|
|
1190
|
-
//
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1191
|
+
// Cache statement once (not per iteration)
|
|
1192
|
+
const upsertStmt = this.stmt(`
|
|
1193
|
+
INSERT INTO memory_connections (id, memory_a, memory_b, co_retrievals, last_fired)
|
|
1194
|
+
VALUES (?, ?, ?, 1, CURRENT_TIMESTAMP)
|
|
1195
|
+
ON CONFLICT(memory_a, memory_b) DO UPDATE SET
|
|
1196
|
+
co_retrievals = co_retrievals + 1,
|
|
1197
|
+
last_fired = CURRENT_TIMESTAMP
|
|
1198
|
+
`);
|
|
1199
|
+
|
|
1200
|
+
// Wrap in transaction for batch efficiency
|
|
1201
|
+
this.db.transaction(() => {
|
|
1202
|
+
for (let i = 0; i < memoryIds.length; i++) {
|
|
1203
|
+
for (let j = i + 1; j < memoryIds.length; j++) {
|
|
1204
|
+
const [a, b] = memoryIds[i] < memoryIds[j]
|
|
1205
|
+
? [memoryIds[i], memoryIds[j]]
|
|
1206
|
+
: [memoryIds[j], memoryIds[i]];
|
|
1207
|
+
|
|
1208
|
+
upsertStmt.run(randomUUID(), a, b);
|
|
1209
|
+
}
|
|
1204
1210
|
}
|
|
1205
|
-
}
|
|
1211
|
+
})();
|
|
1206
1212
|
}
|
|
1207
1213
|
|
|
1208
1214
|
/**
|
|
1209
1215
|
* Record that memories were useful together (from LLM feedback)
|
|
1210
1216
|
* This is what actually strengthens connections
|
|
1217
|
+
* Uses cached statement and transaction for O(n²) efficiency
|
|
1211
1218
|
*/
|
|
1212
1219
|
recordCoUseful(memoryIds: string[]): void {
|
|
1213
1220
|
if (memoryIds.length < 2) return;
|
|
1214
1221
|
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1222
|
+
// Cache statement once (not per iteration)
|
|
1223
|
+
const updateStmt = this.stmt(`
|
|
1224
|
+
UPDATE memory_connections
|
|
1225
|
+
SET co_useful = ?, strength = ?, last_fired = CURRENT_TIMESTAMP
|
|
1226
|
+
WHERE memory_a = ? AND memory_b = ?
|
|
1227
|
+
`);
|
|
1228
|
+
|
|
1229
|
+
// Wrap in transaction for batch efficiency
|
|
1230
|
+
this.db.transaction(() => {
|
|
1231
|
+
for (let i = 0; i < memoryIds.length; i++) {
|
|
1232
|
+
for (let j = i + 1; j < memoryIds.length; j++) {
|
|
1233
|
+
const [a, b] = memoryIds[i] < memoryIds[j]
|
|
1234
|
+
? [memoryIds[i], memoryIds[j]]
|
|
1235
|
+
: [memoryIds[j], memoryIds[i]];
|
|
1236
|
+
|
|
1237
|
+
// Get current stats to calculate new strength
|
|
1238
|
+
const conn = this.getOrCreateConnection(a, b);
|
|
1239
|
+
const newCoUseful = conn.co_useful + 1;
|
|
1240
|
+
const newCoRetrievals = Math.max(conn.co_retrievals, newCoUseful);
|
|
1241
|
+
|
|
1242
|
+
// Calculate strength with diminishing returns
|
|
1243
|
+
const usefulRatio = newCoUseful / Math.max(1, newCoRetrievals);
|
|
1244
|
+
const diminished = Math.sqrt(usefulRatio);
|
|
1245
|
+
const confidence = Math.min(1, newCoUseful / 3); // Require 3+ co-useful for strong connection
|
|
1246
|
+
const newStrength = diminished * confidence;
|
|
1247
|
+
|
|
1248
|
+
updateStmt.run(newCoUseful, newStrength, a, b);
|
|
1249
|
+
}
|
|
1237
1250
|
}
|
|
1238
|
-
}
|
|
1251
|
+
})();
|
|
1239
1252
|
}
|
|
1240
1253
|
|
|
1241
1254
|
/**
|
package/src/web/chat-handler.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Chat Handler for Engram Web Interface
|
|
3
|
-
* Uses Claude
|
|
3
|
+
* Uses Claude Opus 4.5 with tools for entity/memory management
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -9,22 +9,22 @@ import { KnowledgeGraph } from "../graph/knowledge-graph.js";
|
|
|
9
9
|
import { HybridSearch } from "../retrieval/hybrid.js";
|
|
10
10
|
import { getAnthropicApiKey } from "../settings.js";
|
|
11
11
|
|
|
12
|
-
// Tool definitions for Claude
|
|
12
|
+
// Tool definitions for Claude - optimized for LLM consumption
|
|
13
13
|
const TOOLS: Anthropic.Tool[] = [
|
|
14
14
|
{
|
|
15
15
|
name: "list_entities",
|
|
16
|
-
description: "
|
|
16
|
+
description: "Returns array of {name, type, id}. Filters: type (person|organization|place), limit. Default limit=50.",
|
|
17
17
|
input_schema: {
|
|
18
18
|
type: "object" as const,
|
|
19
19
|
properties: {
|
|
20
20
|
type: {
|
|
21
21
|
type: "string",
|
|
22
22
|
enum: ["person", "organization", "place"],
|
|
23
|
-
description: "Filter
|
|
23
|
+
description: "Filter: person, organization, or place",
|
|
24
24
|
},
|
|
25
25
|
limit: {
|
|
26
|
-
type: "
|
|
27
|
-
description: "
|
|
26
|
+
type: "integer",
|
|
27
|
+
description: "Max results (default: 50)",
|
|
28
28
|
},
|
|
29
29
|
},
|
|
30
30
|
required: [],
|
|
@@ -32,13 +32,13 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
34
|
name: "get_entity",
|
|
35
|
-
description: "
|
|
35
|
+
description: "Returns {name, type, observations[], relationships_from[], relationships_to[]} or {error}.",
|
|
36
36
|
input_schema: {
|
|
37
37
|
type: "object" as const,
|
|
38
38
|
properties: {
|
|
39
39
|
name: {
|
|
40
40
|
type: "string",
|
|
41
|
-
description: "
|
|
41
|
+
description: "Exact entity name (case-sensitive)",
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
44
|
required: ["name"],
|
|
@@ -46,13 +46,13 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
name: "delete_entity",
|
|
49
|
-
description: "
|
|
49
|
+
description: "Permanently removes entity + all observations + all relationships. Returns {success, deleted} or {error}.",
|
|
50
50
|
input_schema: {
|
|
51
51
|
type: "object" as const,
|
|
52
52
|
properties: {
|
|
53
53
|
name: {
|
|
54
54
|
type: "string",
|
|
55
|
-
description: "
|
|
55
|
+
description: "Exact entity name to delete",
|
|
56
56
|
},
|
|
57
57
|
},
|
|
58
58
|
required: ["name"],
|
|
@@ -60,17 +60,17 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
name: "merge_entities",
|
|
63
|
-
description: "
|
|
63
|
+
description: "Moves all data from 'merge' into 'keep', then deletes 'merge'. Use for deduplication. Returns {success, kept, merged, observations_moved, relations_moved} or {error}.",
|
|
64
64
|
input_schema: {
|
|
65
65
|
type: "object" as const,
|
|
66
66
|
properties: {
|
|
67
67
|
keep: {
|
|
68
68
|
type: "string",
|
|
69
|
-
description: "
|
|
69
|
+
description: "Entity name to preserve (target)",
|
|
70
70
|
},
|
|
71
71
|
merge: {
|
|
72
72
|
type: "string",
|
|
73
|
-
description: "
|
|
73
|
+
description: "Entity name to merge then delete (source)",
|
|
74
74
|
},
|
|
75
75
|
},
|
|
76
76
|
required: ["keep", "merge"],
|
|
@@ -78,17 +78,17 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
80
|
name: "rename_entity",
|
|
81
|
-
description: "
|
|
81
|
+
description: "Changes entity name. Returns {success, old_name, new_name} or {error}.",
|
|
82
82
|
input_schema: {
|
|
83
83
|
type: "object" as const,
|
|
84
84
|
properties: {
|
|
85
85
|
old_name: {
|
|
86
86
|
type: "string",
|
|
87
|
-
description: "Current
|
|
87
|
+
description: "Current exact name",
|
|
88
88
|
},
|
|
89
89
|
new_name: {
|
|
90
90
|
type: "string",
|
|
91
|
-
description: "New
|
|
91
|
+
description: "New name",
|
|
92
92
|
},
|
|
93
93
|
},
|
|
94
94
|
required: ["old_name", "new_name"],
|
|
@@ -96,7 +96,7 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
96
96
|
},
|
|
97
97
|
{
|
|
98
98
|
name: "delete_relationship",
|
|
99
|
-
description: "
|
|
99
|
+
description: "Removes specific relationship. All 3 params must match exactly. Returns {success, deleted} or {error}.",
|
|
100
100
|
input_schema: {
|
|
101
101
|
type: "object" as const,
|
|
102
102
|
properties: {
|
|
@@ -110,7 +110,7 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
110
110
|
},
|
|
111
111
|
type: {
|
|
112
112
|
type: "string",
|
|
113
|
-
description: "Relationship type (e.g.,
|
|
113
|
+
description: "Relationship type (e.g., works_at, knows, lives_in)",
|
|
114
114
|
},
|
|
115
115
|
},
|
|
116
116
|
required: ["from", "to", "type"],
|
|
@@ -118,17 +118,17 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
118
118
|
},
|
|
119
119
|
{
|
|
120
120
|
name: "search_memories",
|
|
121
|
-
description: "
|
|
121
|
+
description: "Hybrid BM25+semantic search. Returns {results[{id, content, timestamp, score}], count}.",
|
|
122
122
|
input_schema: {
|
|
123
123
|
type: "object" as const,
|
|
124
124
|
properties: {
|
|
125
125
|
query: {
|
|
126
126
|
type: "string",
|
|
127
|
-
description: "Search query",
|
|
127
|
+
description: "Search query (keywords or natural language)",
|
|
128
128
|
},
|
|
129
129
|
limit: {
|
|
130
|
-
type: "
|
|
131
|
-
description: "
|
|
130
|
+
type: "integer",
|
|
131
|
+
description: "Max results (default: 10)",
|
|
132
132
|
},
|
|
133
133
|
},
|
|
134
134
|
required: ["query"],
|
|
@@ -136,13 +136,13 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
136
136
|
},
|
|
137
137
|
{
|
|
138
138
|
name: "delete_memory",
|
|
139
|
-
description: "
|
|
139
|
+
description: "Soft-delete (recoverable). Returns {success, disabled_id} or {error}.",
|
|
140
140
|
input_schema: {
|
|
141
141
|
type: "object" as const,
|
|
142
142
|
properties: {
|
|
143
143
|
id: {
|
|
144
144
|
type: "string",
|
|
145
|
-
description: "
|
|
145
|
+
description: "Memory UUID",
|
|
146
146
|
},
|
|
147
147
|
},
|
|
148
148
|
required: ["id"],
|
|
@@ -150,13 +150,13 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
150
150
|
},
|
|
151
151
|
{
|
|
152
152
|
name: "edit_memory",
|
|
153
|
-
description: "
|
|
153
|
+
description: "Updates content and/or importance. Returns {success, memory_id, updated_fields[]} or {error}.",
|
|
154
154
|
input_schema: {
|
|
155
155
|
type: "object" as const,
|
|
156
156
|
properties: {
|
|
157
157
|
id: {
|
|
158
158
|
type: "string",
|
|
159
|
-
description: "
|
|
159
|
+
description: "Memory UUID",
|
|
160
160
|
},
|
|
161
161
|
content: {
|
|
162
162
|
type: "string",
|
|
@@ -164,7 +164,9 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
164
164
|
},
|
|
165
165
|
importance: {
|
|
166
166
|
type: "number",
|
|
167
|
-
|
|
167
|
+
minimum: 0,
|
|
168
|
+
maximum: 1,
|
|
169
|
+
description: "0-1: 0.9=identity, 0.8=major, 0.5=normal, 0.3=minor",
|
|
168
170
|
},
|
|
169
171
|
},
|
|
170
172
|
required: ["id"],
|
|
@@ -172,17 +174,19 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
172
174
|
},
|
|
173
175
|
{
|
|
174
176
|
name: "create_memory",
|
|
175
|
-
description: "
|
|
177
|
+
description: "Stores new memory. Returns {success, memory_id, content}.",
|
|
176
178
|
input_schema: {
|
|
177
179
|
type: "object" as const,
|
|
178
180
|
properties: {
|
|
179
181
|
content: {
|
|
180
182
|
type: "string",
|
|
181
|
-
description: "
|
|
183
|
+
description: "Information to store",
|
|
182
184
|
},
|
|
183
185
|
importance: {
|
|
184
186
|
type: "number",
|
|
185
|
-
|
|
187
|
+
minimum: 0,
|
|
188
|
+
maximum: 1,
|
|
189
|
+
description: "0-1: 0.9=identity, 0.8=major, 0.5=normal (default), 0.3=minor",
|
|
186
190
|
},
|
|
187
191
|
},
|
|
188
192
|
required: ["content"],
|
|
@@ -190,13 +194,13 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
190
194
|
},
|
|
191
195
|
{
|
|
192
196
|
name: "create_entity",
|
|
193
|
-
description: "
|
|
197
|
+
description: "Creates new entity. Returns {success, entity_id, name, type} or {error} if exists.",
|
|
194
198
|
input_schema: {
|
|
195
199
|
type: "object" as const,
|
|
196
200
|
properties: {
|
|
197
201
|
name: {
|
|
198
202
|
type: "string",
|
|
199
|
-
description: "
|
|
203
|
+
description: "Entity name",
|
|
200
204
|
},
|
|
201
205
|
type: {
|
|
202
206
|
type: "string",
|
|
@@ -209,7 +213,7 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
209
213
|
},
|
|
210
214
|
{
|
|
211
215
|
name: "create_relationship",
|
|
212
|
-
description: "
|
|
216
|
+
description: "Links two entities. Auto-creates entities as 'person' if missing. Returns {success, relationship}.",
|
|
213
217
|
input_schema: {
|
|
214
218
|
type: "object" as const,
|
|
215
219
|
properties: {
|
|
@@ -223,7 +227,7 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
223
227
|
},
|
|
224
228
|
type: {
|
|
225
229
|
type: "string",
|
|
226
|
-
description: "Relationship type (e.g.,
|
|
230
|
+
description: "Relationship type (e.g., works_at, lives_in, knows, sibling_of, parent_of)",
|
|
227
231
|
},
|
|
228
232
|
},
|
|
229
233
|
required: ["from", "to", "type"],
|
|
@@ -231,7 +235,7 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
231
235
|
},
|
|
232
236
|
{
|
|
233
237
|
name: "find_duplicates",
|
|
234
|
-
description: "
|
|
238
|
+
description: "Detects similar entity names. Returns {groups[{keep, duplicates[]}], total_duplicates}.",
|
|
235
239
|
input_schema: {
|
|
236
240
|
type: "object" as const,
|
|
237
241
|
properties: {},
|
|
@@ -240,7 +244,7 @@ const TOOLS: Anthropic.Tool[] = [
|
|
|
240
244
|
},
|
|
241
245
|
{
|
|
242
246
|
name: "auto_tidy",
|
|
243
|
-
description: "
|
|
247
|
+
description: "Auto-merges all detected duplicates. Returns {entities_merged, observations_moved, relations_moved}.",
|
|
244
248
|
input_schema: {
|
|
245
249
|
type: "object" as const,
|
|
246
250
|
properties: {},
|
|
@@ -301,6 +305,9 @@ export class ChatHandler {
|
|
|
301
305
|
refreshClient(): void {
|
|
302
306
|
const apiKey = getAnthropicApiKey();
|
|
303
307
|
if (apiKey) {
|
|
308
|
+
if (!this.client) {
|
|
309
|
+
console.error("[Engram] ChatHandler: API key configured");
|
|
310
|
+
}
|
|
304
311
|
this.client = new Anthropic({ apiKey });
|
|
305
312
|
} else {
|
|
306
313
|
this.client = null;
|
|
@@ -308,6 +315,8 @@ export class ChatHandler {
|
|
|
308
315
|
}
|
|
309
316
|
|
|
310
317
|
isConfigured(): boolean {
|
|
318
|
+
// Re-check API key in case it was added after startup
|
|
319
|
+
this.refreshClient();
|
|
311
320
|
return this.client !== null;
|
|
312
321
|
}
|
|
313
322
|
|
|
@@ -341,6 +350,7 @@ export class ChatHandler {
|
|
|
341
350
|
|
|
342
351
|
// Queue-aware chat method
|
|
343
352
|
async chat(userMessage: string): Promise<string> {
|
|
353
|
+
this.refreshClient();
|
|
344
354
|
if (!this.client) {
|
|
345
355
|
return "Chat is not configured. Set ANTHROPIC_API_KEY environment variable.";
|
|
346
356
|
}
|
|
@@ -357,6 +367,7 @@ export class ChatHandler {
|
|
|
357
367
|
|
|
358
368
|
// Streaming chat with callbacks for real-time updates
|
|
359
369
|
async *chatStream(userMessage: string): AsyncGenerator<StreamEvent> {
|
|
370
|
+
this.refreshClient();
|
|
360
371
|
if (!this.client) {
|
|
361
372
|
yield { type: "error", content: "Chat is not configured. Set ANTHROPIC_API_KEY environment variable." };
|
|
362
373
|
return;
|
|
@@ -377,11 +388,10 @@ export class ChatHandler {
|
|
|
377
388
|
}
|
|
378
389
|
|
|
379
390
|
let continueLoop = true;
|
|
380
|
-
let fullResponse = "";
|
|
381
391
|
|
|
382
392
|
while (continueLoop) {
|
|
383
393
|
const stream = this.client.messages.stream({
|
|
384
|
-
model: "claude-
|
|
394
|
+
model: "claude-opus-4-5-20251101",
|
|
385
395
|
max_tokens: 1024,
|
|
386
396
|
system: SYSTEM_PROMPT,
|
|
387
397
|
tools: TOOLS,
|
|
@@ -402,25 +412,13 @@ export class ChatHandler {
|
|
|
402
412
|
}
|
|
403
413
|
} else if (event.type === "content_block_delta") {
|
|
404
414
|
if (event.delta.type === "text_delta") {
|
|
405
|
-
fullResponse += event.delta.text;
|
|
406
415
|
yield { type: "text", content: event.delta.text };
|
|
407
416
|
} else if (event.delta.type === "input_json_delta" && currentToolUse) {
|
|
408
417
|
currentToolUse.input += event.delta.partial_json;
|
|
409
418
|
}
|
|
410
419
|
} else if (event.type === "content_block_stop") {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
let toolInput: Record<string, unknown> = {};
|
|
414
|
-
try {
|
|
415
|
-
toolInput = JSON.parse(currentToolUse.input || "{}");
|
|
416
|
-
} catch {
|
|
417
|
-
toolInput = {};
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
const result = await this.executeTool(currentToolUse.name, toolInput);
|
|
421
|
-
yield { type: "tool_end", tool: currentToolUse.name, result };
|
|
422
|
-
currentToolUse = null;
|
|
423
|
-
}
|
|
420
|
+
// Don't execute tools here - wait for finalMessage to avoid double execution
|
|
421
|
+
currentToolUse = null;
|
|
424
422
|
}
|
|
425
423
|
}
|
|
426
424
|
|
|
@@ -428,7 +426,7 @@ export class ChatHandler {
|
|
|
428
426
|
const finalMessage = await stream.finalMessage();
|
|
429
427
|
|
|
430
428
|
if (finalMessage.stop_reason === "tool_use") {
|
|
431
|
-
// Process tool results
|
|
429
|
+
// Process tool results (execute only once, here)
|
|
432
430
|
const toolUseBlocks = finalMessage.content.filter(
|
|
433
431
|
(block): block is Anthropic.ToolUseBlock => block.type === "tool_use"
|
|
434
432
|
);
|
|
@@ -436,10 +434,13 @@ export class ChatHandler {
|
|
|
436
434
|
const toolResults: Anthropic.ToolResultBlockParam[] = [];
|
|
437
435
|
for (const toolUse of toolUseBlocks) {
|
|
438
436
|
const result = await this.executeTool(toolUse.name, toolUse.input as Record<string, unknown>);
|
|
437
|
+
const isError = typeof result === "object" && result !== null && "error" in result;
|
|
438
|
+
yield { type: "tool_end", tool: toolUse.name, result };
|
|
439
439
|
toolResults.push({
|
|
440
440
|
type: "tool_result",
|
|
441
441
|
tool_use_id: toolUse.id,
|
|
442
442
|
content: JSON.stringify(result),
|
|
443
|
+
is_error: isError,
|
|
443
444
|
});
|
|
444
445
|
}
|
|
445
446
|
|
|
@@ -492,7 +493,7 @@ export class ChatHandler {
|
|
|
492
493
|
}
|
|
493
494
|
|
|
494
495
|
let response = await this.client.messages.create({
|
|
495
|
-
model: "claude-
|
|
496
|
+
model: "claude-opus-4-5-20251101",
|
|
496
497
|
max_tokens: 1024,
|
|
497
498
|
system: SYSTEM_PROMPT,
|
|
498
499
|
tools: TOOLS,
|
|
@@ -508,10 +509,12 @@ export class ChatHandler {
|
|
|
508
509
|
const toolResults: Anthropic.ToolResultBlockParam[] = [];
|
|
509
510
|
for (const toolUse of toolUseBlocks) {
|
|
510
511
|
const result = await this.executeTool(toolUse.name, toolUse.input as Record<string, unknown>);
|
|
512
|
+
const isError = typeof result === "object" && result !== null && "error" in result;
|
|
511
513
|
toolResults.push({
|
|
512
514
|
type: "tool_result",
|
|
513
515
|
tool_use_id: toolUse.id,
|
|
514
516
|
content: JSON.stringify(result),
|
|
517
|
+
is_error: isError,
|
|
515
518
|
});
|
|
516
519
|
}
|
|
517
520
|
|
|
@@ -527,7 +530,7 @@ export class ChatHandler {
|
|
|
527
530
|
|
|
528
531
|
// Continue the conversation
|
|
529
532
|
response = await this.client.messages.create({
|
|
530
|
-
model: "claude-
|
|
533
|
+
model: "claude-opus-4-5-20251101",
|
|
531
534
|
max_tokens: 1024,
|
|
532
535
|
system: SYSTEM_PROMPT,
|
|
533
536
|
tools: TOOLS,
|