adaptive-context-memory 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -0
- package/dist/core/llmClient.d.ts +14 -0
- package/dist/core/llmClient.d.ts.map +1 -0
- package/dist/core/llmClient.js +68 -0
- package/dist/core/llmClient.js.map +1 -0
- package/dist/core/retry.d.ts +21 -0
- package/dist/core/retry.d.ts.map +1 -0
- package/dist/core/retry.js +68 -0
- package/dist/core/retry.js.map +1 -0
- package/dist/core/settings.d.ts +46 -0
- package/dist/core/settings.d.ts.map +1 -0
- package/dist/core/settings.js +133 -0
- package/dist/core/settings.js.map +1 -0
- package/dist/db/database.d.ts +50 -0
- package/dist/db/database.d.ts.map +1 -0
- package/dist/db/database.js +157 -0
- package/dist/db/database.js.map +1 -0
- package/dist/demo.d.ts +16 -0
- package/dist/demo.d.ts.map +1 -0
- package/dist/demo.js +305 -0
- package/dist/demo.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/add/extractionPhase.d.ts +17 -0
- package/dist/memory/add/extractionPhase.d.ts.map +1 -0
- package/dist/memory/add/extractionPhase.js +48 -0
- package/dist/memory/add/extractionPhase.js.map +1 -0
- package/dist/memory/add/updatePhase.d.ts +11 -0
- package/dist/memory/add/updatePhase.d.ts.map +1 -0
- package/dist/memory/add/updatePhase.js +133 -0
- package/dist/memory/add/updatePhase.js.map +1 -0
- package/dist/memory/bubbleCreator.d.ts +10 -0
- package/dist/memory/bubbleCreator.d.ts.map +1 -0
- package/dist/memory/bubbleCreator.js +46 -0
- package/dist/memory/bubbleCreator.js.map +1 -0
- package/dist/memory/connectionFinder.d.ts +14 -0
- package/dist/memory/connectionFinder.d.ts.map +1 -0
- package/dist/memory/connectionFinder.js +56 -0
- package/dist/memory/connectionFinder.js.map +1 -0
- package/dist/memory/embeddings.d.ts +27 -0
- package/dist/memory/embeddings.d.ts.map +1 -0
- package/dist/memory/embeddings.js +145 -0
- package/dist/memory/embeddings.js.map +1 -0
- package/dist/memory/extractor.d.ts +20 -0
- package/dist/memory/extractor.d.ts.map +1 -0
- package/dist/memory/extractor.js +60 -0
- package/dist/memory/extractor.js.map +1 -0
- package/dist/memory/memory.d.ts +80 -0
- package/dist/memory/memory.d.ts.map +1 -0
- package/dist/memory/memory.js +342 -0
- package/dist/memory/memory.js.map +1 -0
- package/dist/memory/toolClassifier.d.ts +13 -0
- package/dist/memory/toolClassifier.d.ts.map +1 -0
- package/dist/memory/toolClassifier.js +53 -0
- package/dist/memory/toolClassifier.js.map +1 -0
- package/dist/memory/vectorStore.d.ts +40 -0
- package/dist/memory/vectorStore.d.ts.map +1 -0
- package/dist/memory/vectorStore.js +168 -0
- package/dist/memory/vectorStore.js.map +1 -0
- package/dist/summary/summaryGenerator.d.ts +14 -0
- package/dist/summary/summaryGenerator.d.ts.map +1 -0
- package/dist/summary/summaryGenerator.js +66 -0
- package/dist/summary/summaryGenerator.js.map +1 -0
- package/dist/utils/prompts.d.ts +7 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +133 -0
- package/dist/utils/prompts.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upgraded Update Phase — v2 with:
|
|
3
|
+
* 1. Batch embeddings — embed ALL facts in 1 API call instead of N sequential calls
|
|
4
|
+
* 2. Parallel LLM calls — run all tool classifier decisions concurrently
|
|
5
|
+
* 3. Fast pre-dedup — cosine similarity > 0.95 → NOOP without any LLM call
|
|
6
|
+
* 4. Retry on all LLM calls (via withRetry in toolClassifier)
|
|
7
|
+
* 5. Atomic DB transaction — all updates committed together
|
|
8
|
+
*/
|
|
9
|
+
import type Database from "better-sqlite3";
|
|
10
|
+
export declare function updatePhase(db: Database.Database, candidateFacts: string[], conversationId: number): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=updatePhase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updatePhase.d.ts","sourceRoot":"","sources":["../../../src/memory/add/updatePhase.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAiH3C,wBAAsB,WAAW,CAC/B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,cAAc,EAAE,MAAM,EAAE,EACxB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CA8Df"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Upgraded Update Phase — v2 with:
|
|
4
|
+
* 1. Batch embeddings — embed ALL facts in 1 API call instead of N sequential calls
|
|
5
|
+
* 2. Parallel LLM calls — run all tool classifier decisions concurrently
|
|
6
|
+
* 3. Fast pre-dedup — cosine similarity > 0.95 → NOOP without any LLM call
|
|
7
|
+
* 4. Retry on all LLM calls (via withRetry in toolClassifier)
|
|
8
|
+
* 5. Atomic DB transaction — all updates committed together
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.updatePhase = updatePhase;
|
|
12
|
+
const embeddings_js_1 = require("../embeddings.js");
|
|
13
|
+
const toolClassifier_js_1 = require("../toolClassifier.js");
|
|
14
|
+
const vectorStore_js_1 = require("../vectorStore.js");
|
|
15
|
+
const settings_js_1 = require("../../core/settings.js");
|
|
16
|
+
const FAST_DEDUP_THRESHOLD = 0.95; // cosine score above this → definitely duplicate
|
|
17
|
+
/** Search similar memories via vector store */
|
|
18
|
+
function searchSimilarMemories(db, conversationId, queryEmbedding, limit = 10) {
|
|
19
|
+
let store = (0, vectorStore_js_1.getVectorStore)(conversationId);
|
|
20
|
+
if (store.count === 0)
|
|
21
|
+
store = (0, vectorStore_js_1.rebuildIndexFromDb)(db, conversationId);
|
|
22
|
+
const results = store.search(queryEmbedding, limit);
|
|
23
|
+
if (results.length === 0)
|
|
24
|
+
return [];
|
|
25
|
+
const ids = results.map((r) => r.memoryId);
|
|
26
|
+
const placeholders = ids.map(() => "?").join(",");
|
|
27
|
+
const rows = db
|
|
28
|
+
.prepare(`SELECT * FROM memories WHERE id IN (${placeholders}) AND is_active = 1`)
|
|
29
|
+
.all(...ids);
|
|
30
|
+
const byId = new Map(rows.map((r) => [r.id, r]));
|
|
31
|
+
return ids.filter((id) => byId.has(id)).map((id) => byId.get(id));
|
|
32
|
+
}
|
|
33
|
+
// ─── Apply a single decision to DB + vector store ───────────────────────────
|
|
34
|
+
function applyDecision(db, conversationId, fact, embedding, decision, s) {
|
|
35
|
+
const store = (0, vectorStore_js_1.getVectorStore)(conversationId);
|
|
36
|
+
const now = new Date().toISOString();
|
|
37
|
+
if (decision.action === "ADD") {
|
|
38
|
+
const text = decision.text ?? fact;
|
|
39
|
+
const res = db
|
|
40
|
+
.prepare(`INSERT INTO memories
|
|
41
|
+
(conversation_id, memory_text, embedding, category, is_episodic, importance, is_active, created_at, updated_at)
|
|
42
|
+
VALUES (?, ?, ?, ?, 0, 0.5, 1, ?, ?)`)
|
|
43
|
+
.run(conversationId, text, JSON.stringify(embedding), decision.category ?? null, now, now);
|
|
44
|
+
const newId = res.lastInsertRowid;
|
|
45
|
+
store.add(newId, embedding);
|
|
46
|
+
if (s.debug)
|
|
47
|
+
console.log(`[ContextMemory] ✅ ADD memory ID ${newId}: "${text.slice(0, 60)}"`);
|
|
48
|
+
}
|
|
49
|
+
else if (decision.action === "UPDATE" && decision.memoryId != null) {
|
|
50
|
+
const old = db.prepare("SELECT * FROM memories WHERE id = ?").get(decision.memoryId);
|
|
51
|
+
if (old) {
|
|
52
|
+
const text = decision.text ?? fact;
|
|
53
|
+
db.prepare("UPDATE memories SET memory_text = ?, embedding = ?, category = ?, updated_at = ? WHERE id = ?").run(text, JSON.stringify(embedding), decision.category ?? old.category, now, old.id);
|
|
54
|
+
store.update(old.id, embedding);
|
|
55
|
+
if (s.debug)
|
|
56
|
+
console.log(`[ContextMemory] ✏️ UPDATE memory ID ${old.id}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else if (decision.action === "DELETE" && decision.memoryId != null) {
|
|
60
|
+
const old = db.prepare("SELECT * FROM memories WHERE id = ?").get(decision.memoryId);
|
|
61
|
+
if (old) {
|
|
62
|
+
store.remove(old.id);
|
|
63
|
+
db.prepare("UPDATE memories SET is_active = 0 WHERE id = ?").run(old.id);
|
|
64
|
+
if (s.debug)
|
|
65
|
+
console.log(`[ContextMemory] 🗑 DELETE memory ID ${old.id}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else if (decision.action === "REPLACE" && decision.memoryId != null) {
|
|
69
|
+
const old = db.prepare("SELECT * FROM memories WHERE id = ?").get(decision.memoryId);
|
|
70
|
+
if (old) {
|
|
71
|
+
store.remove(old.id);
|
|
72
|
+
db.prepare("UPDATE memories SET is_active = 0 WHERE id = ?").run(old.id);
|
|
73
|
+
if (s.debug)
|
|
74
|
+
console.log(`[ContextMemory] 🔄 REPLACE — deactivated ID ${old.id}`);
|
|
75
|
+
}
|
|
76
|
+
const text = decision.text ?? fact;
|
|
77
|
+
const res = db
|
|
78
|
+
.prepare(`INSERT INTO memories
|
|
79
|
+
(conversation_id, memory_text, embedding, category, is_episodic, importance, is_active, created_at, updated_at)
|
|
80
|
+
VALUES (?, ?, ?, ?, 0, 0.5, 1, ?, ?)`)
|
|
81
|
+
.run(conversationId, text, JSON.stringify(embedding), decision.category ?? null, now, now);
|
|
82
|
+
const newId = res.lastInsertRowid;
|
|
83
|
+
store.add(newId, embedding);
|
|
84
|
+
if (s.debug)
|
|
85
|
+
console.log(`[ContextMemory] ✅ REPLACE — added new ID ${newId}: "${text.slice(0, 60)}"`);
|
|
86
|
+
}
|
|
87
|
+
else if (decision.action === "NOOP") {
|
|
88
|
+
if (s.debug)
|
|
89
|
+
console.log(`[ContextMemory] ⏭ NOOP for: "${fact.slice(0, 60)}"`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function updatePhase(db, candidateFacts, conversationId) {
|
|
93
|
+
if (candidateFacts.length === 0)
|
|
94
|
+
return;
|
|
95
|
+
const s = (0, settings_js_1.getSettings)();
|
|
96
|
+
// ── Step 1: Batch embed ALL facts in 1 API call ───────────────────────────
|
|
97
|
+
if (s.debug)
|
|
98
|
+
console.log(`[ContextMemory] Batch embedding ${candidateFacts.length} facts...`);
|
|
99
|
+
const embeddings = await (0, embeddings_js_1.batchEmbedTexts)(candidateFacts);
|
|
100
|
+
const workItems = candidateFacts.map((fact, i) => {
|
|
101
|
+
const embedding = embeddings[i];
|
|
102
|
+
const similar = searchSimilarMemories(db, conversationId, embedding, 10);
|
|
103
|
+
// Fast dedup: if top match cosine > threshold, skip LLM call
|
|
104
|
+
let fastNoop = false;
|
|
105
|
+
if (similar.length > 0) {
|
|
106
|
+
const store = (0, vectorStore_js_1.getVectorStore)(conversationId);
|
|
107
|
+
const topResults = store.search(embedding, 1);
|
|
108
|
+
if (topResults.length > 0 && topResults[0].score >= FAST_DEDUP_THRESHOLD) {
|
|
109
|
+
fastNoop = true;
|
|
110
|
+
if (s.debug) {
|
|
111
|
+
console.log(`[ContextMemory] ⚡ Fast-dedup NOOP (score=${topResults[0].score.toFixed(3)}): "${fact.slice(0, 60)}"`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return { fact, embedding, similar, fastNoop };
|
|
116
|
+
});
|
|
117
|
+
// ── Step 3: Parallel LLM calls for non-deduped facts ─────────────────────
|
|
118
|
+
const llmWork = workItems.filter((w) => !w.fastNoop);
|
|
119
|
+
if (s.debug)
|
|
120
|
+
console.log(`[ContextMemory] ${workItems.length - llmWork.length} fast-deduped, ${llmWork.length} sent to LLM (parallel)`);
|
|
121
|
+
const decisions = await Promise.all(llmWork.map((w) => (0, toolClassifier_js_1.llmToolCall)(w.fact, w.similar)));
|
|
122
|
+
// ── Step 4: Apply all decisions in a single DB transaction ───────────────
|
|
123
|
+
const applyAll = db.transaction(() => {
|
|
124
|
+
for (let i = 0; i < llmWork.length; i++) {
|
|
125
|
+
const { fact, embedding } = llmWork[i];
|
|
126
|
+
const decision = decisions[i];
|
|
127
|
+
applyDecision(db, conversationId, fact, embedding, decision, s);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
applyAll();
|
|
131
|
+
(0, vectorStore_js_1.saveVectorStore)(conversationId);
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=updatePhase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updatePhase.js","sourceRoot":"","sources":["../../../src/memory/add/updatePhase.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bubble Creator — TypeScript port of Python bubble_creator.py
|
|
3
|
+
*
|
|
4
|
+
* Creates episodic memory "bubbles" with embeddings and bidirectional connections.
|
|
5
|
+
*/
|
|
6
|
+
import type Database from "better-sqlite3";
|
|
7
|
+
import type { BubbleData } from "./extractor.js";
|
|
8
|
+
import type { MemoryRow } from "../db/database.js";
|
|
9
|
+
export declare function createBubbles(db: Database.Database, bubbles: BubbleData[], conversationId: number, sessionId?: number | null): Promise<MemoryRow[]>;
|
|
10
|
+
//# sourceMappingURL=bubbleCreator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bubbleCreator.d.ts","sourceRoot":"","sources":["../../src/memory/bubbleCreator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAI3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,wBAAsB,aAAa,CACjC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,OAAO,EAAE,UAAU,EAAE,EACrB,cAAc,EAAE,MAAM,EACtB,SAAS,GAAE,MAAM,GAAG,IAAW,GAC9B,OAAO,CAAC,SAAS,EAAE,CAAC,CAqDtB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Bubble Creator — TypeScript port of Python bubble_creator.py
|
|
4
|
+
*
|
|
5
|
+
* Creates episodic memory "bubbles" with embeddings and bidirectional connections.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.createBubbles = createBubbles;
|
|
9
|
+
const embeddings_js_1 = require("./embeddings.js");
|
|
10
|
+
const vectorStore_js_1 = require("./vectorStore.js");
|
|
11
|
+
const connectionFinder_js_1 = require("./connectionFinder.js");
|
|
12
|
+
async function createBubbles(db, bubbles, conversationId, sessionId = null) {
|
|
13
|
+
const store = (0, vectorStore_js_1.getVectorStore)(conversationId);
|
|
14
|
+
const created = [];
|
|
15
|
+
const now = new Date().toISOString();
|
|
16
|
+
for (const bubbleData of bubbles) {
|
|
17
|
+
const text = bubbleData.text?.trim();
|
|
18
|
+
if (!text)
|
|
19
|
+
continue;
|
|
20
|
+
let importance = typeof bubbleData.importance === "number" ? bubbleData.importance : 0.5;
|
|
21
|
+
importance = Math.max(0, Math.min(1, importance)); // clamp to [0, 1]
|
|
22
|
+
// Generate embedding
|
|
23
|
+
const embedding = await (0, embeddings_js_1.embedText)(text);
|
|
24
|
+
// Insert bubble into DB
|
|
25
|
+
const res = db
|
|
26
|
+
.prepare(`INSERT INTO memories
|
|
27
|
+
(conversation_id, memory_text, embedding, memory_metadata, is_episodic,
|
|
28
|
+
occurred_at, session_id, importance, is_active, created_at, updated_at)
|
|
29
|
+
VALUES (?, ?, ?, '{}', 1, ?, ?, ?, 1, ?, ?)`)
|
|
30
|
+
.run(conversationId, text, JSON.stringify(embedding), now, // occurred_at
|
|
31
|
+
sessionId, importance, now, now);
|
|
32
|
+
const bubbleId = res.lastInsertRowid;
|
|
33
|
+
// Add to vector store
|
|
34
|
+
store.add(bubbleId, embedding);
|
|
35
|
+
// Fetch the row we just inserted
|
|
36
|
+
const bubble = db
|
|
37
|
+
.prepare("SELECT * FROM memories WHERE id = ?")
|
|
38
|
+
.get(bubbleId);
|
|
39
|
+
// Find + write connections
|
|
40
|
+
(0, connectionFinder_js_1.findConnections)(db, bubble, embedding, conversationId);
|
|
41
|
+
created.push(bubble);
|
|
42
|
+
}
|
|
43
|
+
(0, vectorStore_js_1.saveVectorStore)(conversationId);
|
|
44
|
+
return created;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=bubbleCreator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bubbleCreator.js","sourceRoot":"","sources":["../../src/memory/bubbleCreator.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AASH,sCA0DC;AAhED,mDAA4C;AAC5C,qDAAmE;AACnE,+DAAwD;AAIjD,KAAK,UAAU,aAAa,CACjC,EAAqB,EACrB,OAAqB,EACrB,cAAsB,EACtB,YAA2B,IAAI;IAE/B,MAAM,KAAK,GAAG,IAAA,+BAAc,EAAC,cAAc,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAgB,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAErC,KAAK,MAAM,UAAU,IAAI,OAAO,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;QACrC,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,IAAI,UAAU,GACZ,OAAO,UAAU,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC;QAC1E,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,kBAAkB;QAErE,qBAAqB;QACrB,MAAM,SAAS,GAAG,MAAM,IAAA,yBAAS,EAAC,IAAI,CAAC,CAAC;QAExC,wBAAwB;QACxB,MAAM,GAAG,GAAG,EAAE;aACX,OAAO,CACN;;;qDAG6C,CAC9C;aACA,GAAG,CACF,cAAc,EACd,IAAI,EACJ,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EACzB,GAAG,EAAE,cAAc;QACnB,SAAS,EACT,UAAU,EACV,GAAG,EACH,GAAG,CACJ,CAAC;QAEJ,MAAM,QAAQ,GAAG,GAAG,CAAC,eAAyB,CAAC;QAE/C,sBAAsB;QACtB,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAE/B,iCAAiC;QACjC,MAAM,MAAM,GAAG,EAAE;aACd,OAAO,CAAC,qCAAqC,CAAC;aAC9C,GAAG,CAAC,QAAQ,CAAc,CAAC;QAE9B,2BAA2B;QAC3B,IAAA,qCAAe,EAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;QAEvD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED,IAAA,gCAAe,EAAC,cAAc,CAAC,CAAC;IAChC,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection Finder — TypeScript port of Python connection_finder.py
|
|
3
|
+
*
|
|
4
|
+
* Finds bidirectional connections between episodic bubbles
|
|
5
|
+
* using cosine similarity from the vector store.
|
|
6
|
+
*/
|
|
7
|
+
import type Database from "better-sqlite3";
|
|
8
|
+
import type { MemoryRow } from "../db/database.js";
|
|
9
|
+
/**
|
|
10
|
+
* Find similar bubbles and write bidirectional connection metadata.
|
|
11
|
+
* Returns an array of connected memory IDs.
|
|
12
|
+
*/
|
|
13
|
+
export declare function findConnections(db: Database.Database, newBubble: MemoryRow, embedding: number[], conversationId: number): number[];
|
|
14
|
+
//# sourceMappingURL=connectionFinder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectionFinder.d.ts","sourceRoot":"","sources":["../../src/memory/connectionFinder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAMnD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,MAAM,EAAE,EACnB,cAAc,EAAE,MAAM,GACrB,MAAM,EAAE,CAoDV"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Connection Finder — TypeScript port of Python connection_finder.py
|
|
4
|
+
*
|
|
5
|
+
* Finds bidirectional connections between episodic bubbles
|
|
6
|
+
* using cosine similarity from the vector store.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.findConnections = findConnections;
|
|
10
|
+
const vectorStore_js_1 = require("./vectorStore.js");
|
|
11
|
+
const database_js_1 = require("../db/database.js");
|
|
12
|
+
const CONNECTION_THRESHOLD = 0.6;
|
|
13
|
+
const MAX_CONNECTIONS = 5;
|
|
14
|
+
/**
|
|
15
|
+
* Find similar bubbles and write bidirectional connection metadata.
|
|
16
|
+
* Returns an array of connected memory IDs.
|
|
17
|
+
*/
|
|
18
|
+
function findConnections(db, newBubble, embedding, conversationId) {
|
|
19
|
+
const store = (0, vectorStore_js_1.getVectorStore)(conversationId);
|
|
20
|
+
const results = store.search(embedding, MAX_CONNECTIONS * 2);
|
|
21
|
+
const connections = [];
|
|
22
|
+
for (const r of results) {
|
|
23
|
+
if (r.memoryId !== newBubble.id && r.score >= CONNECTION_THRESHOLD) {
|
|
24
|
+
connections.push({ id: r.memoryId, score: Math.round(r.score * 1000) / 1000 });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const topConns = connections.slice(0, MAX_CONNECTIONS);
|
|
28
|
+
if (topConns.length === 0)
|
|
29
|
+
return [];
|
|
30
|
+
const connectionIds = topConns.map((c) => c.id);
|
|
31
|
+
const connectionScores = {};
|
|
32
|
+
for (const c of topConns)
|
|
33
|
+
connectionScores[String(c.id)] = c.score;
|
|
34
|
+
// Write to new bubble's metadata
|
|
35
|
+
const newMeta = (0, database_js_1.parseMeta)(newBubble);
|
|
36
|
+
newMeta.connections = { bubble_ids: connectionIds, scores: connectionScores };
|
|
37
|
+
db.prepare("UPDATE memories SET memory_metadata = ? WHERE id = ?").run(JSON.stringify(newMeta), newBubble.id);
|
|
38
|
+
// Write reverse connections (bidirectional)
|
|
39
|
+
for (const conn of topConns) {
|
|
40
|
+
const connRow = db
|
|
41
|
+
.prepare("SELECT * FROM memories WHERE id = ?")
|
|
42
|
+
.get(conn.id);
|
|
43
|
+
if (connRow) {
|
|
44
|
+
const cm = (0, database_js_1.parseMeta)(connRow);
|
|
45
|
+
const cmc = cm.connections ?? { bubble_ids: [], scores: {} };
|
|
46
|
+
if (!cmc.bubble_ids.includes(newBubble.id)) {
|
|
47
|
+
cmc.bubble_ids.push(newBubble.id);
|
|
48
|
+
cmc.scores[String(newBubble.id)] = conn.score;
|
|
49
|
+
cm.connections = cmc;
|
|
50
|
+
db.prepare("UPDATE memories SET memory_metadata = ? WHERE id = ?").run(JSON.stringify(cm), conn.id);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return connectionIds;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=connectionFinder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectionFinder.js","sourceRoot":"","sources":["../../src/memory/connectionFinder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding generation — v2 with LRU cache + batch support + retry.
|
|
3
|
+
*
|
|
4
|
+
* Upgrades over v1:
|
|
5
|
+
* 1. LRU cache — repeated text → zero API calls
|
|
6
|
+
* 2. batchEmbedTexts() — N texts in 1 API call instead of N calls
|
|
7
|
+
* 3. Exponential backoff retry on all calls
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Embed a single text. Cached — identical text never calls the API twice.
|
|
11
|
+
*/
|
|
12
|
+
export declare function embedText(text: string): Promise<number[]>;
|
|
13
|
+
/**
|
|
14
|
+
* Embed multiple texts in a single API call. Much faster than N sequential calls.
|
|
15
|
+
* Results are cached individually for future reuse.
|
|
16
|
+
*/
|
|
17
|
+
export declare function batchEmbedTexts(texts: string[]): Promise<number[][]>;
|
|
18
|
+
/** Clear the embedding cache (useful for testing) */
|
|
19
|
+
export declare function clearEmbeddingCache(): void;
|
|
20
|
+
/** Cache stats for monitoring */
|
|
21
|
+
export declare function getEmbeddingCacheStats(): {
|
|
22
|
+
hits: number;
|
|
23
|
+
misses: number;
|
|
24
|
+
size: number;
|
|
25
|
+
hitRate: string;
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=embeddings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.d.ts","sourceRoot":"","sources":["../../src/memory/embeddings.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuDH;;GAEG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAa/D;AAGD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAuD1E;AAED,qDAAqD;AACrD,wBAAgB,mBAAmB,IAAI,IAAI,CAK1C;AAED,iCAAiC;AACjC,wBAAgB,sBAAsB,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAQxG"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Embedding generation — v2 with LRU cache + batch support + retry.
|
|
4
|
+
*
|
|
5
|
+
* Upgrades over v1:
|
|
6
|
+
* 1. LRU cache — repeated text → zero API calls
|
|
7
|
+
* 2. batchEmbedTexts() — N texts in 1 API call instead of N calls
|
|
8
|
+
* 3. Exponential backoff retry on all calls
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.embedText = embedText;
|
|
12
|
+
exports.batchEmbedTexts = batchEmbedTexts;
|
|
13
|
+
exports.clearEmbeddingCache = clearEmbeddingCache;
|
|
14
|
+
exports.getEmbeddingCacheStats = getEmbeddingCacheStats;
|
|
15
|
+
const llmClient_js_1 = require("../core/llmClient.js");
|
|
16
|
+
const settings_js_1 = require("../core/settings.js");
|
|
17
|
+
const retry_js_1 = require("../core/retry.js");
|
|
18
|
+
// ─── LRU Cache ────────────────────────────────────────────────────────────────
|
|
19
|
+
const MAX_CACHE_SIZE = 512;
|
|
20
|
+
/** Simple LRU map: evicts oldest entry when at capacity */
|
|
21
|
+
class LRUCache {
|
|
22
|
+
map = new Map();
|
|
23
|
+
capacity;
|
|
24
|
+
constructor(capacity) {
|
|
25
|
+
this.capacity = capacity;
|
|
26
|
+
}
|
|
27
|
+
get(key) {
|
|
28
|
+
if (!this.map.has(key))
|
|
29
|
+
return undefined;
|
|
30
|
+
// Move to end (most recently used)
|
|
31
|
+
const val = this.map.get(key);
|
|
32
|
+
this.map.delete(key);
|
|
33
|
+
this.map.set(key, val);
|
|
34
|
+
return val;
|
|
35
|
+
}
|
|
36
|
+
set(key, val) {
|
|
37
|
+
if (this.map.has(key))
|
|
38
|
+
this.map.delete(key);
|
|
39
|
+
this.map.set(key, val);
|
|
40
|
+
// Evict oldest if over capacity
|
|
41
|
+
if (this.map.size > this.capacity) {
|
|
42
|
+
const oldest = this.map.keys().next().value;
|
|
43
|
+
if (oldest !== undefined)
|
|
44
|
+
this.map.delete(oldest);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
get size() { return this.map.size; }
|
|
48
|
+
}
|
|
49
|
+
const _cache = new LRUCache(MAX_CACHE_SIZE);
|
|
50
|
+
let _cacheHits = 0;
|
|
51
|
+
let _cacheMisses = 0;
|
|
52
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
53
|
+
function getModelName() {
|
|
54
|
+
const s = (0, settings_js_1.getSettings)();
|
|
55
|
+
let model = s.embeddingModel;
|
|
56
|
+
if (s.llmProvider === "openrouter" && !model.startsWith("openai/")) {
|
|
57
|
+
model = `openai/${model}`;
|
|
58
|
+
}
|
|
59
|
+
return model;
|
|
60
|
+
}
|
|
61
|
+
// ─── Single embedding (with cache + retry) ───────────────────────────────────
|
|
62
|
+
/**
|
|
63
|
+
* Embed a single text. Cached — identical text never calls the API twice.
|
|
64
|
+
*/
|
|
65
|
+
async function embedText(text) {
|
|
66
|
+
const cached = _cache.get(text);
|
|
67
|
+
if (cached) {
|
|
68
|
+
_cacheHits++;
|
|
69
|
+
if ((0, settings_js_1.getSettings)().debug) {
|
|
70
|
+
console.log(`[ContextMemory] Embedding cache hit (${_cacheHits} hits / ${_cacheMisses} misses)`);
|
|
71
|
+
}
|
|
72
|
+
return cached;
|
|
73
|
+
}
|
|
74
|
+
_cacheMisses++;
|
|
75
|
+
const embedding = await batchEmbedTexts([text]);
|
|
76
|
+
return embedding[0];
|
|
77
|
+
}
|
|
78
|
+
// ─── Batch embedding (core — 1 API call for N texts) ─────────────────────────
|
|
79
|
+
/**
|
|
80
|
+
* Embed multiple texts in a single API call. Much faster than N sequential calls.
|
|
81
|
+
* Results are cached individually for future reuse.
|
|
82
|
+
*/
|
|
83
|
+
async function batchEmbedTexts(texts) {
|
|
84
|
+
if (texts.length === 0)
|
|
85
|
+
return [];
|
|
86
|
+
const s = (0, settings_js_1.getSettings)();
|
|
87
|
+
const model = getModelName();
|
|
88
|
+
// Check cache first — only call API for uncached texts
|
|
89
|
+
const uncachedIndices = [];
|
|
90
|
+
const uncachedTexts = [];
|
|
91
|
+
const result = texts.map((text, i) => {
|
|
92
|
+
const cached = _cache.get(text);
|
|
93
|
+
if (cached) {
|
|
94
|
+
_cacheHits++;
|
|
95
|
+
return cached;
|
|
96
|
+
}
|
|
97
|
+
_cacheMisses++;
|
|
98
|
+
uncachedIndices.push(i);
|
|
99
|
+
uncachedTexts.push(text);
|
|
100
|
+
return null;
|
|
101
|
+
});
|
|
102
|
+
if (uncachedTexts.length > 0) {
|
|
103
|
+
const client = (0, llmClient_js_1.getEmbeddingClient)();
|
|
104
|
+
// OpenAI batch limit is 2048 inputs; chunk if needed
|
|
105
|
+
const BATCH_SIZE = 100;
|
|
106
|
+
const apiEmbeddings = [];
|
|
107
|
+
for (let i = 0; i < uncachedTexts.length; i += BATCH_SIZE) {
|
|
108
|
+
const chunk = uncachedTexts.slice(i, i + BATCH_SIZE);
|
|
109
|
+
const response = await (0, retry_js_1.withRetry)(() => client.embeddings.create({ model, input: chunk }));
|
|
110
|
+
// API returns embeddings sorted by index
|
|
111
|
+
for (const item of response.data) {
|
|
112
|
+
apiEmbeddings.push(item.embedding);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Fill results + update cache
|
|
116
|
+
for (let i = 0; i < uncachedIndices.length; i++) {
|
|
117
|
+
const originalIdx = uncachedIndices[i];
|
|
118
|
+
const embedding = apiEmbeddings[i];
|
|
119
|
+
result[originalIdx] = embedding;
|
|
120
|
+
_cache.set(texts[originalIdx], embedding);
|
|
121
|
+
}
|
|
122
|
+
if (s.debug) {
|
|
123
|
+
console.log(`[ContextMemory] Batch embed: ${uncachedTexts.length} API calls saved by batching. Cache: ${_cacheHits}H/${_cacheMisses}M`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
/** Clear the embedding cache (useful for testing) */
|
|
129
|
+
function clearEmbeddingCache() {
|
|
130
|
+
_cacheHits = 0;
|
|
131
|
+
_cacheMisses = 0;
|
|
132
|
+
// Re-create cache (no clear method on Map-based LRU)
|
|
133
|
+
Object.assign(_cache, new LRUCache(MAX_CACHE_SIZE));
|
|
134
|
+
}
|
|
135
|
+
/** Cache stats for monitoring */
|
|
136
|
+
function getEmbeddingCacheStats() {
|
|
137
|
+
const total = _cacheHits + _cacheMisses;
|
|
138
|
+
return {
|
|
139
|
+
hits: _cacheHits,
|
|
140
|
+
misses: _cacheMisses,
|
|
141
|
+
size: _cache.size,
|
|
142
|
+
hitRate: total > 0 ? `${Math.round((_cacheHits / total) * 100)}%` : "0%",
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=embeddings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddings.js","sourceRoot":"","sources":["../../src/memory/embeddings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory extractor — TypeScript port of Python extractor.py
|
|
3
|
+
*
|
|
4
|
+
* Uses an LLM to extract semantic facts and episodic bubbles
|
|
5
|
+
* from the latest user/assistant interaction.
|
|
6
|
+
*/
|
|
7
|
+
export interface BubbleData {
|
|
8
|
+
text: string;
|
|
9
|
+
importance: number;
|
|
10
|
+
}
|
|
11
|
+
export interface ExtractionResult {
|
|
12
|
+
semantic: string[];
|
|
13
|
+
bubbles: BubbleData[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Ask the LLM to extract semantic facts and episodic bubbles
|
|
17
|
+
* from the latest conversation exchange.
|
|
18
|
+
*/
|
|
19
|
+
export declare function extractMemories(latestPair: string[], summaryText: string, recentMessages: string[]): Promise<ExtractionResult>;
|
|
20
|
+
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/memory/extractor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAmBD;;;GAGG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAAE,EACpB,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAiC3B"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Memory extractor — TypeScript port of Python extractor.py
|
|
4
|
+
*
|
|
5
|
+
* Uses an LLM to extract semantic facts and episodic bubbles
|
|
6
|
+
* from the latest user/assistant interaction.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.extractMemories = extractMemories;
|
|
10
|
+
const llmClient_js_1 = require("../core/llmClient.js");
|
|
11
|
+
const settings_js_1 = require("../core/settings.js");
|
|
12
|
+
const retry_js_1 = require("../core/retry.js");
|
|
13
|
+
const prompts_js_1 = require("../utils/prompts.js");
|
|
14
|
+
/** Parse raw LLM JSON output, stripping any markdown code fences */
|
|
15
|
+
function parseJson(raw) {
|
|
16
|
+
let str = raw.trim();
|
|
17
|
+
const fence = str.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
|
|
18
|
+
if (fence)
|
|
19
|
+
str = fence[1].trim();
|
|
20
|
+
try {
|
|
21
|
+
const parsed = JSON.parse(str);
|
|
22
|
+
return {
|
|
23
|
+
semantic: Array.isArray(parsed.semantic) ? parsed.semantic : [],
|
|
24
|
+
bubbles: Array.isArray(parsed.bubbles) ? parsed.bubbles : [],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return { semantic: [], bubbles: [] };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Ask the LLM to extract semantic facts and episodic bubbles
|
|
33
|
+
* from the latest conversation exchange.
|
|
34
|
+
*/
|
|
35
|
+
async function extractMemories(latestPair, summaryText, recentMessages) {
|
|
36
|
+
const s = (0, settings_js_1.getSettings)();
|
|
37
|
+
const client = (0, llmClient_js_1.getLlmClient)();
|
|
38
|
+
const recentText = recentMessages.join("\n");
|
|
39
|
+
const latestText = latestPair.join("\n");
|
|
40
|
+
const messages = [
|
|
41
|
+
{ role: "system", content: prompts_js_1.EXTRACTION_SYSTEM_PROMPT },
|
|
42
|
+
{
|
|
43
|
+
role: "user",
|
|
44
|
+
content: `Conversation Summary:\n${summaryText}\n\nRecent Messages:\n${recentText}\n\nLatest Interaction:\n${latestText}\n\nExtract memory facts (semantic facts and bubbles).`,
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
const response = await (0, retry_js_1.withRetry)(() => client.chat.completions.create({
|
|
48
|
+
model: s.llmModel,
|
|
49
|
+
messages,
|
|
50
|
+
temperature: 0.1,
|
|
51
|
+
}));
|
|
52
|
+
const raw = response.choices[0].message.content ?? "";
|
|
53
|
+
if (s.debug)
|
|
54
|
+
console.log("[ContextMemory] Extraction raw:", raw.slice(0, 300));
|
|
55
|
+
const result = parseJson(raw);
|
|
56
|
+
if (s.debug)
|
|
57
|
+
console.log(`[ContextMemory] Extracted: ${result.semantic.length} semantic, ${result.bubbles.length} bubbles`);
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/memory/extractor.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAsCH,0CAqCC;AAzED,uDAAoD;AACpD,qDAAkD;AAClD,+CAA6C;AAC7C,oDAA+D;AAY/D,oEAAoE;AACpE,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,GAAG,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACrB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC3D,IAAI,KAAK;QAAE,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAEjC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA8B,CAAC;QAC5D,OAAO;YACL,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;YAC/D,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;SAC7D,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACvC,CAAC;AACH,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,eAAe,CACnC,UAAoB,EACpB,WAAmB,EACnB,cAAwB;IAExB,MAAM,CAAC,GAAG,IAAA,yBAAW,GAAE,CAAC;IACxB,MAAM,MAAM,GAAG,IAAA,2BAAY,GAAE,CAAC;IAE9B,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEzC,MAAM,QAAQ,GAAG;QACf,EAAE,IAAI,EAAE,QAAiB,EAAE,OAAO,EAAE,qCAAwB,EAAE;QAC9D;YACE,IAAI,EAAE,MAAe;YACrB,OAAO,EAAE,0BAA0B,WAAW,yBAAyB,UAAU,4BAA4B,UAAU,wDAAwD;SAChL;KACF,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,IAAA,oBAAS,EAAC,GAAG,EAAE,CACpC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QAC7B,KAAK,EAAE,CAAC,CAAC,QAAQ;QACjB,QAAQ;QACR,WAAW,EAAE,GAAG;KACjB,CAAC,CACH,CAAC;IAEF,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;IACtD,IAAI,CAAC,CAAC,KAAK;QAAE,OAAO,CAAC,GAAG,CAAC,iCAAiC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAE/E,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,CAAC,KAAK;QACT,OAAO,CAAC,GAAG,CACT,8BAA8B,MAAM,CAAC,QAAQ,CAAC,MAAM,cAAc,MAAM,CAAC,OAAO,CAAC,MAAM,UAAU,CAClG,CAAC;IAEJ,OAAO,MAAM,CAAC;AAChB,CAAC"}
|