@framers/agentos 0.1.101 → 0.1.102

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.
Files changed (176) hide show
  1. package/README.md +16 -0
  2. package/dist/memory/config.d.ts +39 -0
  3. package/dist/memory/config.d.ts.map +1 -1
  4. package/dist/memory/config.js.map +1 -1
  5. package/dist/memory/consolidation/ConsolidationLoop.d.ts +177 -0
  6. package/dist/memory/consolidation/ConsolidationLoop.d.ts.map +1 -0
  7. package/dist/memory/consolidation/ConsolidationLoop.js +517 -0
  8. package/dist/memory/consolidation/ConsolidationLoop.js.map +1 -0
  9. package/dist/memory/consolidation/ConsolidationPipeline.d.ts.map +1 -1
  10. package/dist/memory/consolidation/ConsolidationPipeline.js +7 -0
  11. package/dist/memory/consolidation/ConsolidationPipeline.js.map +1 -1
  12. package/dist/memory/consolidation/index.d.ts +8 -0
  13. package/dist/memory/consolidation/index.d.ts.map +1 -0
  14. package/dist/memory/consolidation/index.js +7 -0
  15. package/dist/memory/consolidation/index.js.map +1 -0
  16. package/dist/memory/decay/DecayModel.d.ts +33 -0
  17. package/dist/memory/decay/DecayModel.d.ts.map +1 -1
  18. package/dist/memory/decay/DecayModel.js +31 -0
  19. package/dist/memory/decay/DecayModel.js.map +1 -1
  20. package/dist/memory/facade/Memory.d.ts +228 -0
  21. package/dist/memory/facade/Memory.d.ts.map +1 -0
  22. package/dist/memory/facade/Memory.js +823 -0
  23. package/dist/memory/facade/Memory.js.map +1 -0
  24. package/dist/memory/facade/index.d.ts +13 -0
  25. package/dist/memory/facade/index.d.ts.map +1 -0
  26. package/dist/memory/facade/index.js +11 -0
  27. package/dist/memory/facade/index.js.map +1 -0
  28. package/dist/memory/facade/types.d.ts +606 -0
  29. package/dist/memory/facade/types.d.ts.map +1 -0
  30. package/dist/memory/facade/types.js +11 -0
  31. package/dist/memory/facade/types.js.map +1 -0
  32. package/dist/memory/feedback/RetrievalFeedbackSignal.d.ts +132 -0
  33. package/dist/memory/feedback/RetrievalFeedbackSignal.d.ts.map +1 -0
  34. package/dist/memory/feedback/RetrievalFeedbackSignal.js +178 -0
  35. package/dist/memory/feedback/RetrievalFeedbackSignal.js.map +1 -0
  36. package/dist/memory/feedback/index.d.ts +13 -0
  37. package/dist/memory/feedback/index.d.ts.map +1 -0
  38. package/dist/memory/feedback/index.js +12 -0
  39. package/dist/memory/feedback/index.js.map +1 -0
  40. package/dist/memory/index.d.ts +22 -0
  41. package/dist/memory/index.d.ts.map +1 -1
  42. package/dist/memory/index.js +24 -0
  43. package/dist/memory/index.js.map +1 -1
  44. package/dist/memory/ingestion/ChunkingEngine.d.ts +143 -0
  45. package/dist/memory/ingestion/ChunkingEngine.d.ts.map +1 -0
  46. package/dist/memory/ingestion/ChunkingEngine.js +508 -0
  47. package/dist/memory/ingestion/ChunkingEngine.js.map +1 -0
  48. package/dist/memory/ingestion/DoclingLoader.d.ts +44 -0
  49. package/dist/memory/ingestion/DoclingLoader.d.ts.map +1 -0
  50. package/dist/memory/ingestion/DoclingLoader.js +228 -0
  51. package/dist/memory/ingestion/DoclingLoader.js.map +1 -0
  52. package/dist/memory/ingestion/DocxLoader.d.ts +37 -0
  53. package/dist/memory/ingestion/DocxLoader.d.ts.map +1 -0
  54. package/dist/memory/ingestion/DocxLoader.js +111 -0
  55. package/dist/memory/ingestion/DocxLoader.js.map +1 -0
  56. package/dist/memory/ingestion/FolderScanner.d.ts +116 -0
  57. package/dist/memory/ingestion/FolderScanner.d.ts.map +1 -0
  58. package/dist/memory/ingestion/FolderScanner.js +127 -0
  59. package/dist/memory/ingestion/FolderScanner.js.map +1 -0
  60. package/dist/memory/ingestion/HtmlLoader.d.ts +49 -0
  61. package/dist/memory/ingestion/HtmlLoader.d.ts.map +1 -0
  62. package/dist/memory/ingestion/HtmlLoader.js +202 -0
  63. package/dist/memory/ingestion/HtmlLoader.js.map +1 -0
  64. package/dist/memory/ingestion/IDocumentLoader.d.ts +63 -0
  65. package/dist/memory/ingestion/IDocumentLoader.d.ts.map +1 -0
  66. package/dist/memory/ingestion/IDocumentLoader.js +11 -0
  67. package/dist/memory/ingestion/IDocumentLoader.js.map +1 -0
  68. package/dist/memory/ingestion/LoaderRegistry.d.ts +140 -0
  69. package/dist/memory/ingestion/LoaderRegistry.d.ts.map +1 -0
  70. package/dist/memory/ingestion/LoaderRegistry.js +229 -0
  71. package/dist/memory/ingestion/LoaderRegistry.js.map +1 -0
  72. package/dist/memory/ingestion/MarkdownLoader.d.ts +50 -0
  73. package/dist/memory/ingestion/MarkdownLoader.d.ts.map +1 -0
  74. package/dist/memory/ingestion/MarkdownLoader.js +169 -0
  75. package/dist/memory/ingestion/MarkdownLoader.js.map +1 -0
  76. package/dist/memory/ingestion/MultimodalAggregator.d.ts +88 -0
  77. package/dist/memory/ingestion/MultimodalAggregator.d.ts.map +1 -0
  78. package/dist/memory/ingestion/MultimodalAggregator.js +96 -0
  79. package/dist/memory/ingestion/MultimodalAggregator.js.map +1 -0
  80. package/dist/memory/ingestion/OcrPdfLoader.d.ts +41 -0
  81. package/dist/memory/ingestion/OcrPdfLoader.d.ts.map +1 -0
  82. package/dist/memory/ingestion/OcrPdfLoader.js +149 -0
  83. package/dist/memory/ingestion/OcrPdfLoader.js.map +1 -0
  84. package/dist/memory/ingestion/PdfLoader.d.ts +78 -0
  85. package/dist/memory/ingestion/PdfLoader.d.ts.map +1 -0
  86. package/dist/memory/ingestion/PdfLoader.js +179 -0
  87. package/dist/memory/ingestion/PdfLoader.js.map +1 -0
  88. package/dist/memory/ingestion/TextLoader.d.ts +66 -0
  89. package/dist/memory/ingestion/TextLoader.d.ts.map +1 -0
  90. package/dist/memory/ingestion/TextLoader.js +207 -0
  91. package/dist/memory/ingestion/TextLoader.js.map +1 -0
  92. package/dist/memory/ingestion/UrlLoader.d.ts +95 -0
  93. package/dist/memory/ingestion/UrlLoader.d.ts.map +1 -0
  94. package/dist/memory/ingestion/UrlLoader.js +174 -0
  95. package/dist/memory/ingestion/UrlLoader.js.map +1 -0
  96. package/dist/memory/io/ChatGptImporter.d.ts +85 -0
  97. package/dist/memory/io/ChatGptImporter.d.ts.map +1 -0
  98. package/dist/memory/io/ChatGptImporter.js +231 -0
  99. package/dist/memory/io/ChatGptImporter.js.map +1 -0
  100. package/dist/memory/io/JsonExporter.d.ts +67 -0
  101. package/dist/memory/io/JsonExporter.d.ts.map +1 -0
  102. package/dist/memory/io/JsonExporter.js +132 -0
  103. package/dist/memory/io/JsonExporter.js.map +1 -0
  104. package/dist/memory/io/JsonImporter.d.ts +84 -0
  105. package/dist/memory/io/JsonImporter.d.ts.map +1 -0
  106. package/dist/memory/io/JsonImporter.js +234 -0
  107. package/dist/memory/io/JsonImporter.js.map +1 -0
  108. package/dist/memory/io/MarkdownExporter.d.ts +95 -0
  109. package/dist/memory/io/MarkdownExporter.d.ts.map +1 -0
  110. package/dist/memory/io/MarkdownExporter.js +130 -0
  111. package/dist/memory/io/MarkdownExporter.js.map +1 -0
  112. package/dist/memory/io/MarkdownImporter.d.ts +84 -0
  113. package/dist/memory/io/MarkdownImporter.d.ts.map +1 -0
  114. package/dist/memory/io/MarkdownImporter.js +166 -0
  115. package/dist/memory/io/MarkdownImporter.js.map +1 -0
  116. package/dist/memory/io/ObsidianExporter.d.ts +80 -0
  117. package/dist/memory/io/ObsidianExporter.d.ts.map +1 -0
  118. package/dist/memory/io/ObsidianExporter.js +127 -0
  119. package/dist/memory/io/ObsidianExporter.js.map +1 -0
  120. package/dist/memory/io/ObsidianImporter.d.ts +93 -0
  121. package/dist/memory/io/ObsidianImporter.d.ts.map +1 -0
  122. package/dist/memory/io/ObsidianImporter.js +221 -0
  123. package/dist/memory/io/ObsidianImporter.js.map +1 -0
  124. package/dist/memory/io/SqliteExporter.d.ts +47 -0
  125. package/dist/memory/io/SqliteExporter.d.ts.map +1 -0
  126. package/dist/memory/io/SqliteExporter.js +56 -0
  127. package/dist/memory/io/SqliteExporter.js.map +1 -0
  128. package/dist/memory/io/SqliteImporter.d.ts +82 -0
  129. package/dist/memory/io/SqliteImporter.d.ts.map +1 -0
  130. package/dist/memory/io/SqliteImporter.js +232 -0
  131. package/dist/memory/io/SqliteImporter.js.map +1 -0
  132. package/dist/memory/io/index.d.ts +31 -0
  133. package/dist/memory/io/index.d.ts.map +1 -0
  134. package/dist/memory/io/index.js +31 -0
  135. package/dist/memory/io/index.js.map +1 -0
  136. package/dist/memory/store/SqliteBrain.d.ts +125 -0
  137. package/dist/memory/store/SqliteBrain.d.ts.map +1 -0
  138. package/dist/memory/store/SqliteBrain.js +407 -0
  139. package/dist/memory/store/SqliteBrain.js.map +1 -0
  140. package/dist/memory/store/SqliteKnowledgeGraph.d.ts +259 -0
  141. package/dist/memory/store/SqliteKnowledgeGraph.d.ts.map +1 -0
  142. package/dist/memory/store/SqliteKnowledgeGraph.js +1062 -0
  143. package/dist/memory/store/SqliteKnowledgeGraph.js.map +1 -0
  144. package/dist/memory/store/SqliteMemoryGraph.d.ts +251 -0
  145. package/dist/memory/store/SqliteMemoryGraph.d.ts.map +1 -0
  146. package/dist/memory/store/SqliteMemoryGraph.js +637 -0
  147. package/dist/memory/store/SqliteMemoryGraph.js.map +1 -0
  148. package/dist/memory/tools/MemoryAddTool.d.ts +98 -0
  149. package/dist/memory/tools/MemoryAddTool.d.ts.map +1 -0
  150. package/dist/memory/tools/MemoryAddTool.js +131 -0
  151. package/dist/memory/tools/MemoryAddTool.js.map +1 -0
  152. package/dist/memory/tools/MemoryDeleteTool.d.ts +83 -0
  153. package/dist/memory/tools/MemoryDeleteTool.d.ts.map +1 -0
  154. package/dist/memory/tools/MemoryDeleteTool.js +96 -0
  155. package/dist/memory/tools/MemoryDeleteTool.js.map +1 -0
  156. package/dist/memory/tools/MemoryMergeTool.d.ts +95 -0
  157. package/dist/memory/tools/MemoryMergeTool.d.ts.map +1 -0
  158. package/dist/memory/tools/MemoryMergeTool.js +164 -0
  159. package/dist/memory/tools/MemoryMergeTool.js.map +1 -0
  160. package/dist/memory/tools/MemoryReflectTool.d.ts +86 -0
  161. package/dist/memory/tools/MemoryReflectTool.d.ts.map +1 -0
  162. package/dist/memory/tools/MemoryReflectTool.js +102 -0
  163. package/dist/memory/tools/MemoryReflectTool.js.map +1 -0
  164. package/dist/memory/tools/MemorySearchTool.d.ts +117 -0
  165. package/dist/memory/tools/MemorySearchTool.d.ts.map +1 -0
  166. package/dist/memory/tools/MemorySearchTool.js +162 -0
  167. package/dist/memory/tools/MemorySearchTool.js.map +1 -0
  168. package/dist/memory/tools/MemoryUpdateTool.d.ts +92 -0
  169. package/dist/memory/tools/MemoryUpdateTool.d.ts.map +1 -0
  170. package/dist/memory/tools/MemoryUpdateTool.js +125 -0
  171. package/dist/memory/tools/MemoryUpdateTool.js.map +1 -0
  172. package/dist/memory/tools/index.d.ts +32 -0
  173. package/dist/memory/tools/index.d.ts.map +1 -0
  174. package/dist/memory/tools/index.js +26 -0
  175. package/dist/memory/tools/index.js.map +1 -0
  176. package/package.json +6 -1
@@ -0,0 +1,637 @@
1
+ /**
2
+ * @fileoverview SQLite-backed implementation of IMemoryGraph.
3
+ *
4
+ * Stores memory graph nodes in the `knowledge_nodes` table (type = 'memory_graph')
5
+ * and memory association edges in the `knowledge_edges` table — both managed by
6
+ * SqliteBrain. All node metadata is serialised into the `properties` JSON column.
7
+ *
8
+ * ## Algorithms
9
+ *
10
+ * ### Spreading activation (Anderson's ACT-R model)
11
+ * BFS from each seed node. At each hop the activation value is multiplied by
12
+ * `(1 - decayPerHop) * edgeWeight`, modelling the attenuation of priming
13
+ * signals as they propagate through associative memory. Multiple paths to the
14
+ * same node are resolved by keeping the maximum activation reached so far
15
+ * (best-path semantics). The BFS terminates when:
16
+ * - the current activation falls below `activationThreshold`, or
17
+ * - the hop count exceeds `maxDepth`.
18
+ *
19
+ * ### Hebbian co-activation (recordCoActivation)
20
+ * For every unordered pair (A, B) in `memoryIds`, a CO_ACTIVATED edge is
21
+ * upserted. If the edge already exists its weight is incremented by
22
+ * `learningRate` (capped at 1.0). This implements the classic Hebbian rule:
23
+ * "neurons that fire together wire together".
24
+ *
25
+ * ### Connected-component clustering (detectClusters)
26
+ * Union-Find (path-compressed) over all edges in the graph. Each component
27
+ * with at least `minSize` members is returned as a {@link MemoryCluster}.
28
+ * The `centroidId` is chosen as the member with the highest total edge weight
29
+ * (i.e. the most central node in the component's subgraph).
30
+ *
31
+ * @module memory/store/SqliteMemoryGraph
32
+ */
33
+ import crypto from 'node:crypto';
34
+ // ---------------------------------------------------------------------------
35
+ // Defaults
36
+ // ---------------------------------------------------------------------------
37
+ /** Default spreading activation parameters (ACT-R reasonable defaults). */
38
+ const SA_DEFAULTS = {
39
+ maxDepth: 3,
40
+ decayPerHop: 0.5,
41
+ activationThreshold: 0.1,
42
+ maxResults: 20,
43
+ };
44
+ /** Node type discriminator stored in knowledge_nodes.type. */
45
+ const NODE_TYPE = 'memory_graph';
46
+ // ---------------------------------------------------------------------------
47
+ // SqliteMemoryGraph
48
+ // ---------------------------------------------------------------------------
49
+ /**
50
+ * SQLite-backed implementation of {@link IMemoryGraph}.
51
+ *
52
+ * **Thread safety**: inherits `better-sqlite3`'s single-writer model.
53
+ * All synchronous operations (reads) are safe to call from multiple places
54
+ * concurrently; writes serialise automatically through the WAL.
55
+ *
56
+ * **Usage:**
57
+ * ```ts
58
+ * const brain = new SqliteBrain('/path/to/brain.sqlite');
59
+ * const graph = new SqliteMemoryGraph(brain);
60
+ * await graph.initialize();
61
+ *
62
+ * await graph.addNode('mem-1', { type: 'episodic', scope: 'session', scopeId: 's1', strength: 1.0, createdAt: Date.now() });
63
+ * await graph.addEdge({ sourceId: 'mem-1', targetId: 'mem-2', type: 'SAME_TOPIC', weight: 0.8, createdAt: Date.now() });
64
+ *
65
+ * const activated = await graph.spreadingActivation(['mem-1']);
66
+ * ```
67
+ */
68
+ export class SqliteMemoryGraph {
69
+ // ---------------------------------------------------------------------------
70
+ // Constructor
71
+ // ---------------------------------------------------------------------------
72
+ /**
73
+ * @param brain - The shared SqliteBrain connection for this agent.
74
+ * The `knowledge_nodes` and `knowledge_edges` tables must already exist
75
+ * (SqliteBrain creates them in its constructor).
76
+ */
77
+ constructor(brain) {
78
+ this.brain = brain;
79
+ /**
80
+ * In-memory node index: maps memoryId → MemoryGraphNodeMeta.
81
+ *
82
+ * We keep an in-memory cache so that `hasNode()` and `nodeCount()` are O(1)
83
+ * without requiring a synchronous SQLite query (both are called from
84
+ * hot-path retrieval code). The cache is hydrated during `initialize()` and
85
+ * kept in sync through every `addNode` / `removeNode` / `clear` call.
86
+ */
87
+ this._nodes = new Map();
88
+ /**
89
+ * In-memory edge index: maps `${sourceId}:${targetId}` → MemoryEdge.
90
+ *
91
+ * Edges are also kept in-memory for O(1) adjacency lookups used by
92
+ * spreading activation and cluster detection. Persisted to SQLite on every
93
+ * write so the graph survives restarts.
94
+ */
95
+ this._edges = new Map();
96
+ }
97
+ // ---------------------------------------------------------------------------
98
+ // Lifecycle
99
+ // ---------------------------------------------------------------------------
100
+ /**
101
+ * Hydrate the in-memory node and edge caches from the SQLite database.
102
+ *
103
+ * Must be called once before any other method. Safe to call multiple times
104
+ * (idempotent — fully replaces in-memory state each time).
105
+ */
106
+ async initialize() {
107
+ this._nodes.clear();
108
+ this._edges.clear();
109
+ // Load all memory graph nodes.
110
+ const nodeRows = this.brain.db
111
+ .prepare(`SELECT id, properties FROM knowledge_nodes WHERE type = ?`)
112
+ .all(NODE_TYPE);
113
+ for (const row of nodeRows) {
114
+ try {
115
+ const meta = JSON.parse(row.properties);
116
+ this._nodes.set(row.id, meta);
117
+ }
118
+ catch {
119
+ // Skip rows with corrupted JSON — log is intentionally omitted to
120
+ // avoid pulling in a logger dependency here.
121
+ }
122
+ }
123
+ // Load all edges whose source node is a memory graph node.
124
+ // We identify them by checking the source_id against known node IDs.
125
+ // Because the edge type column stores the MemoryEdgeType string directly,
126
+ // we can filter by the set of known types.
127
+ const edgeRows = this.brain.db
128
+ .prepare(`SELECT id, source_id, target_id, type, weight, created_at
129
+ FROM knowledge_edges
130
+ WHERE type IN (
131
+ 'SHARED_ENTITY','TEMPORAL_SEQUENCE','SAME_TOPIC',
132
+ 'CONTRADICTS','SUPERSEDES','CAUSED_BY','CO_ACTIVATED','SCHEMA_INSTANCE'
133
+ )`)
134
+ .all();
135
+ for (const row of edgeRows) {
136
+ const key = `${row.source_id}:${row.target_id}`;
137
+ this._edges.set(key, {
138
+ sourceId: row.source_id,
139
+ targetId: row.target_id,
140
+ type: row.type,
141
+ weight: row.weight,
142
+ createdAt: row.created_at,
143
+ });
144
+ }
145
+ }
146
+ /**
147
+ * Shut down the memory graph.
148
+ *
149
+ * Currently a no-op because SqliteBrain owns the DB connection lifetime.
150
+ * Provided for interface compliance and forward compatibility.
151
+ */
152
+ async shutdown() {
153
+ // No-op: SqliteBrain owns the connection; callers must call brain.close().
154
+ }
155
+ // ---------------------------------------------------------------------------
156
+ // Node operations
157
+ // ---------------------------------------------------------------------------
158
+ /**
159
+ * Add a memory node to the graph.
160
+ *
161
+ * The node is persisted to `knowledge_nodes` (type = 'memory_graph') with
162
+ * the metadata serialised into the `properties` JSON column. If a node with
163
+ * the same `memoryId` already exists it is silently replaced (upsert).
164
+ *
165
+ * @param memoryId - Unique identifier for the memory trace this node represents.
166
+ * @param metadata - Structural metadata describing the memory.
167
+ */
168
+ async addNode(memoryId, metadata) {
169
+ const now = Date.now();
170
+ this.brain.db
171
+ .prepare(`INSERT OR REPLACE INTO knowledge_nodes
172
+ (id, type, label, properties, confidence, source, created_at)
173
+ VALUES (?, ?, ?, ?, ?, ?, ?)`)
174
+ .run(memoryId, NODE_TYPE, memoryId, JSON.stringify(metadata), metadata.strength, JSON.stringify({}), metadata.createdAt ?? now);
175
+ this._nodes.set(memoryId, metadata);
176
+ }
177
+ /**
178
+ * Remove a node and all its incident edges from the graph.
179
+ *
180
+ * Edges referencing the removed node are deleted from both SQLite and the
181
+ * in-memory cache to keep the graph consistent.
182
+ *
183
+ * @param memoryId - ID of the node to remove.
184
+ */
185
+ async removeNode(memoryId) {
186
+ // Delete incident edges first (FK enforcement is ON, but we also want
187
+ // to clean up the in-memory cache).
188
+ const toDelete = [];
189
+ for (const [key, edge] of this._edges) {
190
+ if (edge.sourceId === memoryId || edge.targetId === memoryId) {
191
+ toDelete.push(key);
192
+ }
193
+ }
194
+ if (toDelete.length > 0) {
195
+ const delEdge = this.brain.db.prepare(`DELETE FROM knowledge_edges WHERE source_id = ? OR target_id = ?`);
196
+ delEdge.run(memoryId, memoryId);
197
+ for (const key of toDelete) {
198
+ this._edges.delete(key);
199
+ }
200
+ }
201
+ // Now delete the node itself.
202
+ this.brain.db
203
+ .prepare(`DELETE FROM knowledge_nodes WHERE id = ? AND type = ?`)
204
+ .run(memoryId, NODE_TYPE);
205
+ this._nodes.delete(memoryId);
206
+ }
207
+ /**
208
+ * Check whether a node exists in the graph.
209
+ *
210
+ * O(1) in-memory lookup — does not touch SQLite.
211
+ *
212
+ * @param memoryId - ID to check.
213
+ * @returns `true` if the node is present, `false` otherwise.
214
+ */
215
+ hasNode(memoryId) {
216
+ return this._nodes.has(memoryId);
217
+ }
218
+ // ---------------------------------------------------------------------------
219
+ // Edge operations
220
+ // ---------------------------------------------------------------------------
221
+ /**
222
+ * Add a directed edge between two memory nodes.
223
+ *
224
+ * If an edge with the same `(sourceId, targetId)` pair already exists it is
225
+ * replaced (upsert by composite key). The underlying SQLite row is identified
226
+ * by a deterministic UUID derived from the source/target pair so that
227
+ * repeated upserts land on the same row.
228
+ *
229
+ * @param edge - Edge descriptor including type, weight, and timestamp.
230
+ */
231
+ async addEdge(edge) {
232
+ const edgeId = this._edgeId(edge.sourceId, edge.targetId);
233
+ const key = `${edge.sourceId}:${edge.targetId}`;
234
+ this.brain.db
235
+ .prepare(`INSERT OR REPLACE INTO knowledge_edges
236
+ (id, source_id, target_id, type, weight, bidirectional, metadata, created_at)
237
+ VALUES (?, ?, ?, ?, ?, 0, '{}', ?)`)
238
+ .run(edgeId, edge.sourceId, edge.targetId, edge.type, edge.weight, edge.createdAt);
239
+ this._edges.set(key, { ...edge });
240
+ }
241
+ /**
242
+ * Retrieve all edges incident to a memory node.
243
+ *
244
+ * Returns edges where `memoryId` appears as either source or target.
245
+ * Optionally filters by edge type.
246
+ *
247
+ * O(E) scan over the in-memory edge map — acceptable for typical graph sizes
248
+ * (< 10k edges).
249
+ *
250
+ * @param memoryId - Node ID to query.
251
+ * @param type - Optional edge type filter.
252
+ * @returns Array of matching {@link MemoryEdge} objects.
253
+ */
254
+ getEdges(memoryId, type) {
255
+ const result = [];
256
+ for (const edge of this._edges.values()) {
257
+ if (edge.sourceId !== memoryId && edge.targetId !== memoryId)
258
+ continue;
259
+ if (type !== undefined && edge.type !== type)
260
+ continue;
261
+ result.push({ ...edge });
262
+ }
263
+ return result;
264
+ }
265
+ /**
266
+ * Remove a directed edge from the graph.
267
+ *
268
+ * @param sourceId - Source node ID.
269
+ * @param targetId - Target node ID.
270
+ */
271
+ async removeEdge(sourceId, targetId) {
272
+ const edgeId = this._edgeId(sourceId, targetId);
273
+ this.brain.db
274
+ .prepare(`DELETE FROM knowledge_edges WHERE id = ?`)
275
+ .run(edgeId);
276
+ this._edges.delete(`${sourceId}:${targetId}`);
277
+ }
278
+ // ---------------------------------------------------------------------------
279
+ // Spreading activation (ACT-R)
280
+ // ---------------------------------------------------------------------------
281
+ /**
282
+ * Run spreading activation from a set of seed nodes.
283
+ *
284
+ * Implements Anderson's ACT-R spreading activation model using BFS:
285
+ *
286
+ * 1. Each seed node starts with activation = 1.0.
287
+ * 2. When a node propagates to a neighbour, the neighbour's activation
288
+ * receives: `parentActivation * (1 - decayPerHop) * edgeWeight`.
289
+ * 3. If a node is reached by multiple paths, the maximum activation is kept.
290
+ * 4. Nodes below `activationThreshold` are not expanded further.
291
+ * 5. BFS stops at depth `maxDepth`.
292
+ *
293
+ * Seed nodes are excluded from the returned list (they are the query, not
294
+ * the result).
295
+ *
296
+ * @param seedIds - IDs of the memory nodes that trigger the activation.
297
+ * @param config - Optional tuning parameters.
298
+ * @returns Activated nodes sorted by activation descending, capped at `maxResults`.
299
+ */
300
+ async spreadingActivation(seedIds, config) {
301
+ const { maxDepth, decayPerHop, activationThreshold, maxResults } = {
302
+ ...SA_DEFAULTS,
303
+ ...config,
304
+ };
305
+ const seedSet = new Set(seedIds);
306
+ /**
307
+ * Maps memoryId → best (activation, depth, activatedBy set) seen so far.
308
+ * We track activatedBy to attribute which seeds contributed.
309
+ */
310
+ const visited = new Map();
311
+ const queue = [];
312
+ // Initialise the queue with each seed at full activation.
313
+ for (const seedId of seedIds) {
314
+ if (!this._nodes.has(seedId))
315
+ continue;
316
+ queue.push({ nodeId: seedId, activation: 1.0, depth: 0, seedOrigin: seedId });
317
+ }
318
+ // Process the queue.
319
+ while (queue.length > 0) {
320
+ const { nodeId, activation, depth, seedOrigin } = queue.shift();
321
+ // Propagate to neighbours if we have headroom.
322
+ if (depth < maxDepth && activation >= activationThreshold) {
323
+ for (const edge of this._edges.values()) {
324
+ let neighbourId = null;
325
+ if (edge.sourceId === nodeId) {
326
+ neighbourId = edge.targetId;
327
+ }
328
+ else if (edge.targetId === nodeId) {
329
+ // Treat all edges as bidirectional for spreading activation —
330
+ // associative priming flows both ways in memory research.
331
+ neighbourId = edge.sourceId;
332
+ }
333
+ if (neighbourId === null)
334
+ continue;
335
+ if (seedSet.has(neighbourId))
336
+ continue; // don't activate seeds
337
+ const newActivation = activation * (1 - decayPerHop) * edge.weight;
338
+ if (newActivation < activationThreshold)
339
+ continue;
340
+ const existing = visited.get(neighbourId);
341
+ if (existing) {
342
+ if (newActivation > existing.activation) {
343
+ // Better path found — update and re-enqueue.
344
+ existing.activation = newActivation;
345
+ existing.depth = depth + 1;
346
+ existing.activatedBy.add(seedOrigin);
347
+ queue.push({
348
+ nodeId: neighbourId,
349
+ activation: newActivation,
350
+ depth: depth + 1,
351
+ seedOrigin,
352
+ });
353
+ }
354
+ else {
355
+ // Just attribute this seed to the existing entry.
356
+ existing.activatedBy.add(seedOrigin);
357
+ }
358
+ }
359
+ else {
360
+ visited.set(neighbourId, {
361
+ activation: newActivation,
362
+ depth: depth + 1,
363
+ activatedBy: new Set([seedOrigin]),
364
+ });
365
+ queue.push({
366
+ nodeId: neighbourId,
367
+ activation: newActivation,
368
+ depth: depth + 1,
369
+ seedOrigin,
370
+ });
371
+ }
372
+ }
373
+ }
374
+ }
375
+ // Convert to ActivatedNode[], sort descending by activation, cap at maxResults.
376
+ const results = [];
377
+ for (const [memoryId, { activation, depth, activatedBy }] of visited) {
378
+ results.push({
379
+ memoryId,
380
+ activation,
381
+ depth,
382
+ activatedBy: Array.from(activatedBy),
383
+ });
384
+ }
385
+ results.sort((a, b) => b.activation - a.activation);
386
+ return results.slice(0, maxResults);
387
+ }
388
+ // ---------------------------------------------------------------------------
389
+ // Hebbian co-activation
390
+ // ---------------------------------------------------------------------------
391
+ /**
392
+ * Record that a set of memories were activated together (Hebbian learning).
393
+ *
394
+ * For every unordered pair (A, B) in `memoryIds`, a CO_ACTIVATED edge is
395
+ * upserted:
396
+ * - If no edge exists, it is created with `weight = learningRate`.
397
+ * - If an edge already exists, its weight is incremented by `learningRate`
398
+ * and capped at 1.0.
399
+ *
400
+ * This implements the Hebbian rule "neurons that fire together wire together"
401
+ * at the memory graph level, gradually strengthening associations between
402
+ * memories that are frequently retrieved in the same context.
403
+ *
404
+ * @param memoryIds - IDs of co-activated memories.
405
+ * @param learningRate - Weight increment per co-activation event. @default 0.1
406
+ */
407
+ async recordCoActivation(memoryIds, learningRate = 0.1) {
408
+ if (memoryIds.length < 2)
409
+ return;
410
+ const now = Date.now();
411
+ // Process all unordered pairs.
412
+ for (let i = 0; i < memoryIds.length; i++) {
413
+ for (let j = i + 1; j < memoryIds.length; j++) {
414
+ const sourceId = memoryIds[i];
415
+ const targetId = memoryIds[j];
416
+ const key = `${sourceId}:${targetId}`;
417
+ const existing = this._edges.get(key);
418
+ if (existing && existing.type === 'CO_ACTIVATED') {
419
+ // Increment weight, capped at 1.0.
420
+ const newWeight = Math.min(1.0, existing.weight + learningRate);
421
+ existing.weight = newWeight;
422
+ // Update SQLite row weight in-place.
423
+ const edgeId = this._edgeId(sourceId, targetId);
424
+ this.brain.db
425
+ .prepare(`UPDATE knowledge_edges SET weight = ? WHERE id = ?`)
426
+ .run(newWeight, edgeId);
427
+ }
428
+ else {
429
+ // Create a new CO_ACTIVATED edge.
430
+ await this.addEdge({
431
+ sourceId,
432
+ targetId,
433
+ type: 'CO_ACTIVATED',
434
+ weight: learningRate,
435
+ createdAt: now,
436
+ });
437
+ }
438
+ }
439
+ }
440
+ }
441
+ // ---------------------------------------------------------------------------
442
+ // Conflict detection
443
+ // ---------------------------------------------------------------------------
444
+ /**
445
+ * Return all CONTRADICTS edges incident to a given memory node.
446
+ *
447
+ * A CONTRADICTS edge signals that two memories express mutually incompatible
448
+ * beliefs or facts. The consolidation engine uses this to trigger
449
+ * conflict-resolution passes.
450
+ *
451
+ * @param memoryId - The memory node to check for contradictions.
452
+ * @returns Array of CONTRADICTS edges (may be empty).
453
+ */
454
+ getConflicts(memoryId) {
455
+ return this.getEdges(memoryId, 'CONTRADICTS');
456
+ }
457
+ // ---------------------------------------------------------------------------
458
+ // Cluster detection (Union-Find)
459
+ // ---------------------------------------------------------------------------
460
+ /**
461
+ * Detect connected components (clusters) in the memory graph.
462
+ *
463
+ * Uses path-compressed Union-Find over all edges. Components are filtered
464
+ * to those with at least `minSize` members.
465
+ *
466
+ * The `centroidId` of each cluster is the member with the highest total
467
+ * incident edge weight (most central node). If the cluster has only one
468
+ * member, `centroidId` equals that member.
469
+ *
470
+ * The `density` of a cluster is computed as:
471
+ * `actualEdges / maxPossibleEdges` where `maxPossibleEdges = n*(n-1)`.
472
+ * For single-member clusters, density = 0.
473
+ *
474
+ * @param minSize - Minimum component size to include. @default 2
475
+ * @returns Array of {@link MemoryCluster} objects.
476
+ */
477
+ async detectClusters(minSize = 2) {
478
+ const nodeIds = Array.from(this._nodes.keys());
479
+ if (nodeIds.length === 0)
480
+ return [];
481
+ // ---------------------------------------------------------------------------
482
+ // Union-Find with path compression + union by rank.
483
+ // ---------------------------------------------------------------------------
484
+ const parent = new Map();
485
+ const rank = new Map();
486
+ const find = (id) => {
487
+ if (!parent.has(id)) {
488
+ parent.set(id, id);
489
+ rank.set(id, 0);
490
+ }
491
+ if (parent.get(id) !== id) {
492
+ parent.set(id, find(parent.get(id)));
493
+ }
494
+ return parent.get(id);
495
+ };
496
+ const union = (a, b) => {
497
+ const ra = find(a);
498
+ const rb = find(b);
499
+ if (ra === rb)
500
+ return;
501
+ const rankA = rank.get(ra) ?? 0;
502
+ const rankB = rank.get(rb) ?? 0;
503
+ if (rankA < rankB) {
504
+ parent.set(ra, rb);
505
+ }
506
+ else if (rankA > rankB) {
507
+ parent.set(rb, ra);
508
+ }
509
+ else {
510
+ parent.set(rb, ra);
511
+ rank.set(ra, rankA + 1);
512
+ }
513
+ };
514
+ // Initialise every known node.
515
+ for (const id of nodeIds) {
516
+ find(id);
517
+ }
518
+ // Merge components using all edges.
519
+ for (const edge of this._edges.values()) {
520
+ // Only union nodes that exist in the graph.
521
+ if (this._nodes.has(edge.sourceId) && this._nodes.has(edge.targetId)) {
522
+ union(edge.sourceId, edge.targetId);
523
+ }
524
+ }
525
+ // ---------------------------------------------------------------------------
526
+ // Collect members per root.
527
+ // ---------------------------------------------------------------------------
528
+ const components = new Map();
529
+ for (const id of nodeIds) {
530
+ const root = find(id);
531
+ if (!components.has(root))
532
+ components.set(root, []);
533
+ components.get(root).push(id);
534
+ }
535
+ // ---------------------------------------------------------------------------
536
+ // Build cluster objects for components >= minSize.
537
+ // ---------------------------------------------------------------------------
538
+ const clusters = [];
539
+ for (const [, members] of components) {
540
+ if (members.length < minSize)
541
+ continue;
542
+ // Compute per-member total edge weight to find the centroid.
543
+ const weightSum = new Map();
544
+ for (const m of members)
545
+ weightSum.set(m, 0);
546
+ const memberSet = new Set(members);
547
+ let internalEdgeCount = 0;
548
+ for (const edge of this._edges.values()) {
549
+ if (memberSet.has(edge.sourceId) && memberSet.has(edge.targetId)) {
550
+ weightSum.set(edge.sourceId, (weightSum.get(edge.sourceId) ?? 0) + edge.weight);
551
+ weightSum.set(edge.targetId, (weightSum.get(edge.targetId) ?? 0) + edge.weight);
552
+ internalEdgeCount++;
553
+ }
554
+ }
555
+ // Centroid = member with highest total incident weight.
556
+ let centroidId = members[0];
557
+ let maxWeight = -Infinity;
558
+ for (const m of members) {
559
+ const w = weightSum.get(m) ?? 0;
560
+ if (w > maxWeight) {
561
+ maxWeight = w;
562
+ centroidId = m;
563
+ }
564
+ }
565
+ // Density = actualEdges / (n * (n-1)) — directed graph formula.
566
+ const n = members.length;
567
+ const maxEdges = n * (n - 1);
568
+ const density = maxEdges > 0 ? internalEdgeCount / maxEdges : 0;
569
+ clusters.push({
570
+ clusterId: centroidId,
571
+ memberIds: members,
572
+ density,
573
+ });
574
+ }
575
+ return clusters;
576
+ }
577
+ // ---------------------------------------------------------------------------
578
+ // Stats & lifecycle
579
+ // ---------------------------------------------------------------------------
580
+ /**
581
+ * Return the number of nodes currently in the graph.
582
+ * O(1) — backed by the in-memory Map size.
583
+ */
584
+ nodeCount() {
585
+ return this._nodes.size;
586
+ }
587
+ /**
588
+ * Return the number of edges currently in the graph.
589
+ * O(1) — backed by the in-memory Map size.
590
+ */
591
+ edgeCount() {
592
+ return this._edges.size;
593
+ }
594
+ /**
595
+ * Remove all nodes and edges from the graph (both in-memory and SQLite).
596
+ *
597
+ * This is a destructive, irreversible operation. Intended for tests and
598
+ * administrative resets only.
599
+ */
600
+ clear() {
601
+ // Delete all knowledge_edges whose type is a MemoryEdgeType value.
602
+ this.brain.db.exec(`DELETE FROM knowledge_edges
603
+ WHERE type IN (
604
+ 'SHARED_ENTITY','TEMPORAL_SEQUENCE','SAME_TOPIC',
605
+ 'CONTRADICTS','SUPERSEDES','CAUSED_BY','CO_ACTIVATED','SCHEMA_INSTANCE'
606
+ )`);
607
+ // Delete all memory_graph nodes.
608
+ this.brain.db
609
+ .prepare(`DELETE FROM knowledge_nodes WHERE type = ?`)
610
+ .run(NODE_TYPE);
611
+ this._nodes.clear();
612
+ this._edges.clear();
613
+ }
614
+ // ---------------------------------------------------------------------------
615
+ // Private helpers
616
+ // ---------------------------------------------------------------------------
617
+ /**
618
+ * Derive a deterministic, stable UUID for a directed edge from
619
+ * `sourceId` to `targetId`.
620
+ *
621
+ * Using a deterministic ID means that calling `addEdge` twice with the same
622
+ * source/target lands on the same SQLite row — enabling the `INSERT OR REPLACE`
623
+ * upsert semantics.
624
+ *
625
+ * @param sourceId - Edge source node ID.
626
+ * @param targetId - Edge target node ID.
627
+ * @returns A UUID v5-style hex string.
628
+ */
629
+ _edgeId(sourceId, targetId) {
630
+ return crypto
631
+ .createHash('sha256')
632
+ .update(`mem_edge:${sourceId}:${targetId}`)
633
+ .digest('hex')
634
+ .slice(0, 32);
635
+ }
636
+ }
637
+ //# sourceMappingURL=SqliteMemoryGraph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SqliteMemoryGraph.js","sourceRoot":"","sources":["../../../src/memory/store/SqliteMemoryGraph.ts"],"names":[],"mappings":"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"}