@monoes/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 +902 -0
- package/dist/agent-memory-scope.d.ts +131 -0
- package/dist/agent-memory-scope.d.ts.map +1 -0
- package/dist/agent-memory-scope.js +230 -0
- package/dist/agent-memory-scope.js.map +1 -0
- package/dist/agentdb-adapter.d.ts +165 -0
- package/dist/agentdb-adapter.d.ts.map +1 -0
- package/dist/agentdb-adapter.js +836 -0
- package/dist/agentdb-adapter.js.map +1 -0
- package/dist/agentdb-backend.d.ts +218 -0
- package/dist/agentdb-backend.d.ts.map +1 -0
- package/dist/agentdb-backend.js +879 -0
- package/dist/agentdb-backend.js.map +1 -0
- package/dist/auto-memory-bridge.d.ts +230 -0
- package/dist/auto-memory-bridge.d.ts.map +1 -0
- package/dist/auto-memory-bridge.js +730 -0
- package/dist/auto-memory-bridge.js.map +1 -0
- package/dist/cache-manager.d.ts +134 -0
- package/dist/cache-manager.d.ts.map +1 -0
- package/dist/cache-manager.js +410 -0
- package/dist/cache-manager.js.map +1 -0
- package/dist/checkpointer.d.ts +78 -0
- package/dist/checkpointer.d.ts.map +1 -0
- package/dist/checkpointer.js +174 -0
- package/dist/checkpointer.js.map +1 -0
- package/dist/controller-registry.d.ts +216 -0
- package/dist/controller-registry.d.ts.map +1 -0
- package/dist/controller-registry.js +897 -0
- package/dist/controller-registry.js.map +1 -0
- package/dist/database-provider.d.ts +87 -0
- package/dist/database-provider.d.ts.map +1 -0
- package/dist/database-provider.js +434 -0
- package/dist/database-provider.js.map +1 -0
- package/dist/diskann-backend.d.ts +126 -0
- package/dist/diskann-backend.d.ts.map +1 -0
- package/dist/diskann-backend.js +324 -0
- package/dist/diskann-backend.js.map +1 -0
- package/dist/episodic-store.d.ts +58 -0
- package/dist/episodic-store.d.ts.map +1 -0
- package/dist/episodic-store.js +160 -0
- package/dist/episodic-store.js.map +1 -0
- package/dist/hnsw-index.d.ts +111 -0
- package/dist/hnsw-index.d.ts.map +1 -0
- package/dist/hnsw-index.js +778 -0
- package/dist/hnsw-index.js.map +1 -0
- package/dist/hnsw-lite.d.ts +29 -0
- package/dist/hnsw-lite.d.ts.map +1 -0
- package/dist/hnsw-lite.js +236 -0
- package/dist/hnsw-lite.js.map +1 -0
- package/dist/hybrid-backend.d.ts +299 -0
- package/dist/hybrid-backend.d.ts.map +1 -0
- package/dist/hybrid-backend.js +804 -0
- package/dist/hybrid-backend.js.map +1 -0
- package/dist/index.d.ts +228 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +379 -0
- package/dist/index.js.map +1 -0
- package/dist/knowledge/document-chunker.d.ts +22 -0
- package/dist/knowledge/document-chunker.d.ts.map +1 -0
- package/dist/knowledge/document-chunker.js +52 -0
- package/dist/knowledge/document-chunker.js.map +1 -0
- package/dist/knowledge/index.d.ts +12 -0
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/knowledge/index.js +9 -0
- package/dist/knowledge/index.js.map +1 -0
- package/dist/knowledge/knowledge-retriever.d.ts +48 -0
- package/dist/knowledge/knowledge-retriever.d.ts.map +1 -0
- package/dist/knowledge/knowledge-retriever.js +80 -0
- package/dist/knowledge/knowledge-retriever.js.map +1 -0
- package/dist/knowledge/knowledge-store.d.ts +58 -0
- package/dist/knowledge/knowledge-store.d.ts.map +1 -0
- package/dist/knowledge/knowledge-store.js +121 -0
- package/dist/knowledge/knowledge-store.js.map +1 -0
- package/dist/learning-bridge.d.ts +162 -0
- package/dist/learning-bridge.d.ts.map +1 -0
- package/dist/learning-bridge.js +522 -0
- package/dist/learning-bridge.js.map +1 -0
- package/dist/memory-graph.d.ts +123 -0
- package/dist/memory-graph.d.ts.map +1 -0
- package/dist/memory-graph.js +412 -0
- package/dist/memory-graph.js.map +1 -0
- package/dist/migration.d.ts +68 -0
- package/dist/migration.d.ts.map +1 -0
- package/dist/migration.js +513 -0
- package/dist/migration.js.map +1 -0
- package/dist/partitioned-hnsw.d.ts +65 -0
- package/dist/partitioned-hnsw.d.ts.map +1 -0
- package/dist/partitioned-hnsw.js +209 -0
- package/dist/partitioned-hnsw.js.map +1 -0
- package/dist/persistent-sona.d.ts +144 -0
- package/dist/persistent-sona.d.ts.map +1 -0
- package/dist/persistent-sona.js +333 -0
- package/dist/persistent-sona.js.map +1 -0
- package/dist/procedural/action-record.d.ts +19 -0
- package/dist/procedural/action-record.d.ts.map +1 -0
- package/dist/procedural/action-record.js +51 -0
- package/dist/procedural/action-record.js.map +1 -0
- package/dist/procedural/action-sequence-extractor.d.ts +25 -0
- package/dist/procedural/action-sequence-extractor.d.ts.map +1 -0
- package/dist/procedural/action-sequence-extractor.js +91 -0
- package/dist/procedural/action-sequence-extractor.js.map +1 -0
- package/dist/procedural/index.d.ts +14 -0
- package/dist/procedural/index.d.ts.map +1 -0
- package/dist/procedural/index.js +13 -0
- package/dist/procedural/index.js.map +1 -0
- package/dist/procedural/learned-skill.d.ts +17 -0
- package/dist/procedural/learned-skill.d.ts.map +1 -0
- package/dist/procedural/learned-skill.js +73 -0
- package/dist/procedural/learned-skill.js.map +1 -0
- package/dist/procedural/procedure-extractor-worker.d.ts +27 -0
- package/dist/procedural/procedure-extractor-worker.d.ts.map +1 -0
- package/dist/procedural/procedure-extractor-worker.js +39 -0
- package/dist/procedural/procedure-extractor-worker.js.map +1 -0
- package/dist/procedural/skill-registry.d.ts +25 -0
- package/dist/procedural/skill-registry.d.ts.map +1 -0
- package/dist/procedural/skill-registry.js +56 -0
- package/dist/procedural/skill-registry.js.map +1 -0
- package/dist/procedural/types.d.ts +67 -0
- package/dist/procedural/types.d.ts.map +1 -0
- package/dist/procedural/types.js +15 -0
- package/dist/procedural/types.js.map +1 -0
- package/dist/prompt-version-store.d.ts +59 -0
- package/dist/prompt-version-store.d.ts.map +1 -0
- package/dist/prompt-version-store.js +175 -0
- package/dist/prompt-version-store.js.map +1 -0
- package/dist/query-builder.d.ts +52 -0
- package/dist/query-builder.d.ts.map +1 -0
- package/dist/query-builder.js +134 -0
- package/dist/query-builder.js.map +1 -0
- package/dist/rvf-backend.d.ts +51 -0
- package/dist/rvf-backend.d.ts.map +1 -0
- package/dist/rvf-backend.js +499 -0
- package/dist/rvf-backend.js.map +1 -0
- package/dist/rvf-learning-store.d.ts +141 -0
- package/dist/rvf-learning-store.d.ts.map +1 -0
- package/dist/rvf-learning-store.js +344 -0
- package/dist/rvf-learning-store.js.map +1 -0
- package/dist/rvf-migration.d.ts +45 -0
- package/dist/rvf-migration.d.ts.map +1 -0
- package/dist/rvf-migration.js +254 -0
- package/dist/rvf-migration.js.map +1 -0
- package/dist/sqlite-backend.d.ts +127 -0
- package/dist/sqlite-backend.d.ts.map +1 -0
- package/dist/sqlite-backend.js +618 -0
- package/dist/sqlite-backend.js.map +1 -0
- package/dist/sqljs-backend.d.ts +128 -0
- package/dist/sqljs-backend.d.ts.map +1 -0
- package/dist/sqljs-backend.js +611 -0
- package/dist/sqljs-backend.js.map +1 -0
- package/dist/tier-manager.d.ts +79 -0
- package/dist/tier-manager.d.ts.map +1 -0
- package/dist/tier-manager.js +169 -0
- package/dist/tier-manager.js.map +1 -0
- package/dist/tiers/contextual.d.ts +43 -0
- package/dist/tiers/contextual.d.ts.map +1 -0
- package/dist/tiers/contextual.js +102 -0
- package/dist/tiers/contextual.js.map +1 -0
- package/dist/tiers/entity.d.ts +46 -0
- package/dist/tiers/entity.d.ts.map +1 -0
- package/dist/tiers/entity.js +106 -0
- package/dist/tiers/entity.js.map +1 -0
- package/dist/tiers/index.d.ts +4 -0
- package/dist/tiers/index.d.ts.map +1 -0
- package/dist/tiers/index.js +4 -0
- package/dist/tiers/index.js.map +1 -0
- package/dist/tiers/short-term.d.ts +42 -0
- package/dist/tiers/short-term.d.ts.map +1 -0
- package/dist/tiers/short-term.js +89 -0
- package/dist/tiers/short-term.js.map +1 -0
- package/dist/types/checkpoint.d.ts +44 -0
- package/dist/types/checkpoint.d.ts.map +1 -0
- package/dist/types/checkpoint.js +8 -0
- package/dist/types/checkpoint.js.map +1 -0
- package/dist/types.d.ts +526 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +58 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,902 @@
|
|
|
1
|
+
# @monomind/memory
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@monomind/memory)
|
|
4
|
+
[](https://www.npmjs.com/package/@monomind/memory)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://github.com/nokhodian/monomind)
|
|
8
|
+
|
|
9
|
+
> High-performance memory module for Monomind V1 - AgentDB unification, HNSW indexing, vector search, self-learning knowledge graph, and hybrid SQLite+AgentDB backend (ADR-009).
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **150x-12,500x Faster Search** - HNSW (Hierarchical Navigable Small World) vector index for ultra-fast similarity search
|
|
14
|
+
- **Hybrid Backend** - SQLite for structured data + AgentDB for vectors (ADR-009)
|
|
15
|
+
- **Auto Memory Bridge** - Bidirectional sync between Claude Code auto memory and AgentDB (ADR-048)
|
|
16
|
+
- **Self-Learning** - LearningBridge connects insights to SONA/ReasoningBank neural pipeline (ADR-049)
|
|
17
|
+
- **Knowledge Graph** - PageRank + label propagation community detection + HippoRAG PPR re-ranking (ADR-049)
|
|
18
|
+
- **Agent-Scoped Memory** - 3-scope agent memory (project/local/user) with cross-agent knowledge transfer (ADR-049)
|
|
19
|
+
- **Vector Quantization** - Binary, scalar, and product quantization for 4-32x memory reduction
|
|
20
|
+
- **Multiple Distance Metrics** - Cosine, Euclidean, dot product, and Manhattan distance
|
|
21
|
+
- **Query Builder** - Fluent API for building complex memory queries
|
|
22
|
+
- **Cache Manager** - LRU caching with configurable size and TTL
|
|
23
|
+
- **Migration Tools** - Seamless migration from V2 memory systems
|
|
24
|
+
- **DiskANN Backend** - SSD-resident Vamana ANN graph for million-scale entry search (arXiv:2305.04359)
|
|
25
|
+
- **A-MEM Auto-Linking** - Bidirectional reference edges auto-created on store (arXiv:2409.11987)
|
|
26
|
+
- **GraphRAG Community Retrieval** - Community-level summaries annotate semantic search results (arXiv:2404.16130)
|
|
27
|
+
- **HippoRAG PPR Re-ranking** - Personalised PageRank re-ranks semantic results via knowledge graph (arXiv:2405.14831)
|
|
28
|
+
- **Collaborative Memory Promotion** - Entries auto-promoted to team scope after 3+ agent reads/24 h (arXiv:2505.18279)
|
|
29
|
+
- **Temporal Knowledge Graph** - Causal/temporal edge typing inspired by Zep/Graphiti (arXiv:2501.13956)
|
|
30
|
+
- **Injection Filter** - Structural prompt-injection detection on semantic search results (arXiv:2302.12173, arXiv:2310.12815)
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install @monomind/memory
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { HNSWIndex, AgentDBAdapter, CacheManager } from '@monomind/memory';
|
|
42
|
+
|
|
43
|
+
// Create HNSW index for vector search
|
|
44
|
+
const index = new HNSWIndex({
|
|
45
|
+
dimensions: 1536, // OpenAI embedding size
|
|
46
|
+
M: 16, // Max connections per node
|
|
47
|
+
efConstruction: 200,
|
|
48
|
+
metric: 'cosine'
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Add vectors
|
|
52
|
+
await index.addPoint('memory-1', new Float32Array(embedding));
|
|
53
|
+
await index.addPoint('memory-2', new Float32Array(embedding2));
|
|
54
|
+
|
|
55
|
+
// Search for similar vectors
|
|
56
|
+
const results = await index.search(queryVector, 10);
|
|
57
|
+
// [{ id: 'memory-1', distance: 0.05 }, { id: 'memory-2', distance: 0.12 }]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## API Reference
|
|
61
|
+
|
|
62
|
+
### HNSW Index
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { HNSWIndex } from '@monomind/memory';
|
|
66
|
+
|
|
67
|
+
const index = new HNSWIndex({
|
|
68
|
+
dimensions: 1536,
|
|
69
|
+
M: 16, // Max connections per layer
|
|
70
|
+
efConstruction: 200, // Construction-time search depth
|
|
71
|
+
maxElements: 1000000, // Max vectors
|
|
72
|
+
metric: 'cosine', // 'cosine' | 'euclidean' | 'dot' | 'manhattan'
|
|
73
|
+
quantization: { // Optional quantization
|
|
74
|
+
type: 'scalar', // 'binary' | 'scalar' | 'product'
|
|
75
|
+
bits: 8
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Add vectors
|
|
80
|
+
await index.addPoint(id: string, vector: Float32Array);
|
|
81
|
+
|
|
82
|
+
// Search
|
|
83
|
+
const results = await index.search(
|
|
84
|
+
query: Float32Array,
|
|
85
|
+
k: number,
|
|
86
|
+
ef?: number // Search-time depth (higher = more accurate)
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
// Search with filters
|
|
90
|
+
const filtered = await index.searchWithFilters(
|
|
91
|
+
query,
|
|
92
|
+
k,
|
|
93
|
+
(id) => id.startsWith('session-')
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
// Remove vectors
|
|
97
|
+
await index.removePoint(id);
|
|
98
|
+
|
|
99
|
+
// Get statistics
|
|
100
|
+
const stats = index.getStats();
|
|
101
|
+
// { vectorCount, memoryUsage, avgSearchTime, compressionRatio }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### AgentDB Adapter
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { AgentDBAdapter } from '@monomind/memory';
|
|
108
|
+
|
|
109
|
+
const adapter = new AgentDBAdapter({
|
|
110
|
+
dimensions: 1536, // vector dimensions
|
|
111
|
+
hnswM: 16, // max connections per HNSW layer
|
|
112
|
+
hnswEfConstruction: 200, // construction-time search depth
|
|
113
|
+
cacheEnabled: true, // LRU result cache
|
|
114
|
+
cacheSize: 10000, // max cached entries
|
|
115
|
+
cacheTtl: 300000, // 5 minutes
|
|
116
|
+
defaultNamespace: 'default',
|
|
117
|
+
embeddingGenerator: async (text) => myEmbedder.embed(text),
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
await adapter.initialize();
|
|
121
|
+
|
|
122
|
+
// Store memory — namespace is normalised to defaultNamespace when empty
|
|
123
|
+
await adapter.store({
|
|
124
|
+
id: 'mem-123',
|
|
125
|
+
key: 'user-preference',
|
|
126
|
+
content: 'User prefers dark mode',
|
|
127
|
+
type: 'semantic',
|
|
128
|
+
namespace: 'preferences',
|
|
129
|
+
tags: ['ui'],
|
|
130
|
+
metadata: {},
|
|
131
|
+
accessLevel: 'private',
|
|
132
|
+
createdAt: Date.now(),
|
|
133
|
+
updatedAt: Date.now(),
|
|
134
|
+
version: 1,
|
|
135
|
+
references: [],
|
|
136
|
+
accessCount: 0,
|
|
137
|
+
lastAccessedAt: Date.now(),
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Semantic search
|
|
141
|
+
const results = await adapter.semanticSearch('dark mode preference', 10, 0.7);
|
|
142
|
+
// [{ entry: MemoryEntry, score: number, distance: number }, ...]
|
|
143
|
+
|
|
144
|
+
// Convenience: store from plain input (auto-generates id, timestamps)
|
|
145
|
+
const entry = await adapter.storeEntry({
|
|
146
|
+
key: 'my-fact',
|
|
147
|
+
content: 'TypeScript 5+ required',
|
|
148
|
+
namespace: 'learnings',
|
|
149
|
+
type: 'semantic',
|
|
150
|
+
tags: ['setup'],
|
|
151
|
+
metadata: {},
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Cache Manager
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { CacheManager } from '@monomind/memory';
|
|
159
|
+
|
|
160
|
+
const cache = new CacheManager<MemoryEntry>({
|
|
161
|
+
maxSize: 1000, // max entries before LRU eviction
|
|
162
|
+
ttl: 3_600_000, // entry TTL in ms (1 hour)
|
|
163
|
+
maxMemory: 50 * 1024 * 1024, // optional memory cap (50 MB)
|
|
164
|
+
lruEnabled: true, // enable LRU ordering (default: true)
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Cache operations
|
|
168
|
+
cache.set('key', entry);
|
|
169
|
+
const entry = cache.get('key'); // null if missing or expired
|
|
170
|
+
const exists = cache.has('key');
|
|
171
|
+
cache.delete('key');
|
|
172
|
+
cache.clear(); // emits 'cache:cleared' with correct previousSize
|
|
173
|
+
|
|
174
|
+
// Batch prefetch
|
|
175
|
+
await cache.prefetch(['k1', 'k2'], async (keys) => loadFromDB(keys));
|
|
176
|
+
|
|
177
|
+
// Statistics
|
|
178
|
+
const stats = cache.getStats();
|
|
179
|
+
// { size, hits, misses, hitRate, evictions, memoryUsage }
|
|
180
|
+
|
|
181
|
+
// Cleanup — call on process exit to stop the internal cleanup timer
|
|
182
|
+
cache.shutdown();
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Query Builder
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
import { query, QueryTemplates } from '@monomind/memory';
|
|
189
|
+
|
|
190
|
+
// Fluent query construction — produces a MemoryQuery object
|
|
191
|
+
const q = query()
|
|
192
|
+
.semantic('authentication patterns') // type = semantic, embeds content
|
|
193
|
+
.inNamespace('security')
|
|
194
|
+
.withTags(['auth', 'patterns'])
|
|
195
|
+
.ofType('semantic')
|
|
196
|
+
.threshold(0.7)
|
|
197
|
+
.limit(20)
|
|
198
|
+
.sortByNewest() // sortField: createdAt, sortDirection: desc
|
|
199
|
+
.build();
|
|
200
|
+
|
|
201
|
+
// Exact-key lookup
|
|
202
|
+
const exact = query().exact('my-key', 'my-namespace').build();
|
|
203
|
+
|
|
204
|
+
// Prefix search
|
|
205
|
+
const prefix = query().prefix('session-').inNamespace('sessions').build();
|
|
206
|
+
|
|
207
|
+
// Sorting options
|
|
208
|
+
query().semantic('...').sortBy('accessCount', 'desc').build(); // most-accessed first
|
|
209
|
+
query().semantic('...').oldestFirst().build(); // createdAt asc
|
|
210
|
+
query().semantic('...').recentlyAccessed().build(); // lastAccessedAt desc
|
|
211
|
+
|
|
212
|
+
// sortField and sortDirection are passed through to all backends that support them
|
|
213
|
+
// (agentdb-adapter, rvf-backend, sqlite-backend, sqljs-backend, JsonBackend)
|
|
214
|
+
|
|
215
|
+
// Predefined templates
|
|
216
|
+
const recent = QueryTemplates.recentInNamespace('learnings', 10);
|
|
217
|
+
const stale = QueryTemplates.staleEntries('session-cache', 10);
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Migration
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
import { MemoryMigrator, createMigrator } from '@monomind/memory';
|
|
224
|
+
|
|
225
|
+
// Migrate from a legacy SQLite, JSON, or Markdown source
|
|
226
|
+
const migrator = createMigrator(targetAdapter, {
|
|
227
|
+
source: 'sqlite', // 'sqlite' | 'json' | 'markdown' | 'memory-manager' | 'swarm-memory'
|
|
228
|
+
sourcePath: './data/v2-memory.db',
|
|
229
|
+
batchSize: 100,
|
|
230
|
+
generateEmbeddings: true, // generate vector embeddings for each entry
|
|
231
|
+
continueOnError: true, // skip bad entries instead of aborting
|
|
232
|
+
validateData: true,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
const result = await migrator.migrate();
|
|
236
|
+
console.log(`Migrated ${result.progress.migrated} entries`);
|
|
237
|
+
console.log(`Failed: ${result.progress.failed}`);
|
|
238
|
+
|
|
239
|
+
// RVF ↔ JSON bidirectional migration
|
|
240
|
+
import { RvfMigrator } from '@monomind/memory';
|
|
241
|
+
|
|
242
|
+
await RvfMigrator.fromSqlite('./old.db', './new.rvf');
|
|
243
|
+
await RvfMigrator.fromJsonFile('./export.json', './new.rvf');
|
|
244
|
+
await RvfMigrator.toJsonFile('./store.rvf', './export.json');
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Quantization Options
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
// Binary quantization (32x compression)
|
|
251
|
+
const binaryIndex = new HNSWIndex({
|
|
252
|
+
dimensions: 1536,
|
|
253
|
+
quantization: { type: 'binary' }
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
// Scalar quantization (4x compression)
|
|
257
|
+
const scalarIndex = new HNSWIndex({
|
|
258
|
+
dimensions: 1536,
|
|
259
|
+
quantization: { type: 'scalar', bits: 8 }
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// Product quantization (8x compression)
|
|
263
|
+
const productIndex = new HNSWIndex({
|
|
264
|
+
dimensions: 1536,
|
|
265
|
+
quantization: { type: 'product', subquantizers: 8 }
|
|
266
|
+
});
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Auto Memory Bridge (ADR-048)
|
|
270
|
+
|
|
271
|
+
Bidirectional sync between Claude Code's [auto memory](https://code.claude.com/docs/en/memory) files and AgentDB. Auto memory is a persistent directory (`~/.claude/projects/<project>/memory/`) where Claude writes learnings as markdown. `MEMORY.md` (first 200 lines) is loaded into the system prompt; topic files are read on demand.
|
|
272
|
+
|
|
273
|
+
### Quick Start
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
import { AutoMemoryBridge } from '@monomind/memory';
|
|
277
|
+
|
|
278
|
+
const bridge = new AutoMemoryBridge(memoryBackend, {
|
|
279
|
+
workingDir: '/workspaces/my-project',
|
|
280
|
+
syncMode: 'on-session-end', // 'on-write' | 'on-session-end' | 'periodic'
|
|
281
|
+
pruneStrategy: 'confidence-weighted', // 'confidence-weighted' | 'fifo' | 'lru'
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// Record an insight (stores in AgentDB + optionally writes to files)
|
|
285
|
+
await bridge.recordInsight({
|
|
286
|
+
category: 'debugging',
|
|
287
|
+
summary: 'HNSW index requires initialization before search',
|
|
288
|
+
source: 'agent:tester',
|
|
289
|
+
confidence: 0.95,
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// Sync buffered insights to auto memory files
|
|
293
|
+
const syncResult = await bridge.syncToAutoMemory();
|
|
294
|
+
|
|
295
|
+
// Import existing auto memory files into AgentDB (on session start)
|
|
296
|
+
const importResult = await bridge.importFromAutoMemory();
|
|
297
|
+
|
|
298
|
+
// Curate MEMORY.md index (stays under 200-line limit)
|
|
299
|
+
await bridge.curateIndex();
|
|
300
|
+
|
|
301
|
+
// Check status
|
|
302
|
+
const status = bridge.getStatus();
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Sync Modes
|
|
306
|
+
|
|
307
|
+
| Mode | Behavior |
|
|
308
|
+
|------|----------|
|
|
309
|
+
| `on-write` | Writes to files immediately on `recordInsight()` |
|
|
310
|
+
| `on-session-end` | Buffers insights, flushes on `syncToAutoMemory()` |
|
|
311
|
+
| `periodic` | Auto-syncs on a configurable interval |
|
|
312
|
+
|
|
313
|
+
### Insight Categories
|
|
314
|
+
|
|
315
|
+
| Category | Topic File | Description |
|
|
316
|
+
|----------|-----------|-------------|
|
|
317
|
+
| `project-patterns` | `patterns.md` | Code patterns and conventions |
|
|
318
|
+
| `debugging` | `debugging.md` | Bug fixes and debugging insights |
|
|
319
|
+
| `architecture` | `architecture.md` | Design decisions and module relationships |
|
|
320
|
+
| `performance` | `performance.md` | Benchmarks and optimization results |
|
|
321
|
+
| `security` | `security.md` | Security findings and CVE notes |
|
|
322
|
+
| `preferences` | `preferences.md` | User and project preferences |
|
|
323
|
+
| `swarm-results` | `swarm-results.md` | Multi-agent swarm outcomes |
|
|
324
|
+
|
|
325
|
+
### Key Optimizations
|
|
326
|
+
|
|
327
|
+
- **Batch import** - `bulkInsert()` instead of individual `store()` calls
|
|
328
|
+
- **Pre-fetched hashes** - Single query for content-hash dedup during import
|
|
329
|
+
- **Async I/O** - `node:fs/promises` for non-blocking writes
|
|
330
|
+
- **Exact dedup** - `hasSummaryLine()` uses bullet-prefix matching, not substring
|
|
331
|
+
- **O(1) sync tracking** - `syncedInsightKeys` Set prevents double-write race
|
|
332
|
+
- **Prune-before-build** - Avoids O(n^2) index rebuild loop
|
|
333
|
+
|
|
334
|
+
### Utility Functions
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
import {
|
|
338
|
+
resolveAutoMemoryDir, // Derive auto memory path from working dir
|
|
339
|
+
findGitRoot, // Walk up to find .git root
|
|
340
|
+
parseMarkdownEntries, // Parse ## headings into structured entries
|
|
341
|
+
extractSummaries, // Extract bullet summaries, strip metadata
|
|
342
|
+
formatInsightLine, // Format insight as markdown bullet
|
|
343
|
+
hashContent, // SHA-256 truncated to 16 hex chars
|
|
344
|
+
pruneTopicFile, // Keep topic files under line limit
|
|
345
|
+
hasSummaryLine, // Exact bullet-prefix dedup check
|
|
346
|
+
} from '@monomind/memory';
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Types
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
import type {
|
|
353
|
+
AutoMemoryBridgeConfig,
|
|
354
|
+
MemoryInsight,
|
|
355
|
+
InsightCategory,
|
|
356
|
+
SyncDirection,
|
|
357
|
+
SyncMode,
|
|
358
|
+
PruneStrategy,
|
|
359
|
+
SyncResult,
|
|
360
|
+
ImportResult,
|
|
361
|
+
} from '@monomind/memory';
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
## Self-Learning Bridge (ADR-049)
|
|
365
|
+
|
|
366
|
+
Connects insights to the `@monomind/neural` learning pipeline. When neural is unavailable, all operations degrade to no-ops.
|
|
367
|
+
|
|
368
|
+
### Quick Start
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
import { AutoMemoryBridge, LearningBridge } from '@monomind/memory';
|
|
372
|
+
|
|
373
|
+
const bridge = new AutoMemoryBridge(backend, {
|
|
374
|
+
workingDir: '/workspaces/my-project',
|
|
375
|
+
learning: {
|
|
376
|
+
sonaMode: 'balanced',
|
|
377
|
+
confidenceDecayRate: 0.005, // Per-hour decay
|
|
378
|
+
accessBoostAmount: 0.03, // Boost per access
|
|
379
|
+
consolidationThreshold: 10, // Min insights before consolidation
|
|
380
|
+
},
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// Insights now trigger learning trajectories automatically
|
|
384
|
+
await bridge.recordInsight({
|
|
385
|
+
category: 'debugging',
|
|
386
|
+
summary: 'Connection pool exhaustion on high load',
|
|
387
|
+
source: 'agent:tester',
|
|
388
|
+
confidence: 0.9,
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// Consolidation runs JUDGE/DISTILL/CONSOLIDATE pipeline
|
|
392
|
+
await bridge.syncToAutoMemory(); // Calls consolidate() first
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### Standalone Usage
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
import { LearningBridge } from '@monomind/memory';
|
|
399
|
+
|
|
400
|
+
const lb = new LearningBridge(backend, {
|
|
401
|
+
// Optional: inject neural loader for custom setups
|
|
402
|
+
neuralLoader: async () => {
|
|
403
|
+
const { NeuralLearningSystem } = await import('@monomind/neural');
|
|
404
|
+
return new NeuralLearningSystem();
|
|
405
|
+
},
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
// Boost confidence when insight is accessed
|
|
409
|
+
await lb.onInsightAccessed('entry-123'); // +0.03 confidence
|
|
410
|
+
|
|
411
|
+
// Apply time-based decay
|
|
412
|
+
const decayed = await lb.decayConfidences('default'); // -0.005/hour
|
|
413
|
+
|
|
414
|
+
// Find similar patterns via ReasoningBank
|
|
415
|
+
const patterns = await lb.findSimilarPatterns('connection pooling');
|
|
416
|
+
|
|
417
|
+
// Get learning statistics
|
|
418
|
+
const stats = lb.getStats();
|
|
419
|
+
// { totalTrajectories, activeTrajectories, completedTrajectories,
|
|
420
|
+
// totalConsolidations, accessBoosts, ... }
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Confidence Lifecycle
|
|
424
|
+
|
|
425
|
+
| Event | Effect | Range |
|
|
426
|
+
|-------|--------|-------|
|
|
427
|
+
| Insight recorded | Initial confidence from source | 0.1 - 1.0 |
|
|
428
|
+
| Insight accessed | +0.03 per access | Capped at 1.0 |
|
|
429
|
+
| Time decay | -0.005 per hour since last access | Floored at 0.1 |
|
|
430
|
+
| Consolidation | Neural pipeline may adjust | 0.1 - 1.0 |
|
|
431
|
+
|
|
432
|
+
## Knowledge Graph (ADR-049)
|
|
433
|
+
|
|
434
|
+
Pure TypeScript knowledge graph with PageRank and community detection. No external graph libraries required.
|
|
435
|
+
|
|
436
|
+
### Quick Start
|
|
437
|
+
|
|
438
|
+
```typescript
|
|
439
|
+
import { AutoMemoryBridge, MemoryGraph } from '@monomind/memory';
|
|
440
|
+
|
|
441
|
+
const bridge = new AutoMemoryBridge(backend, {
|
|
442
|
+
workingDir: '/workspaces/my-project',
|
|
443
|
+
graph: {
|
|
444
|
+
similarityThreshold: 0.8,
|
|
445
|
+
pageRankDamping: 0.85,
|
|
446
|
+
maxNodes: 5000,
|
|
447
|
+
},
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
// Graph builds automatically on import
|
|
451
|
+
await bridge.importFromAutoMemory();
|
|
452
|
+
|
|
453
|
+
// Curation uses PageRank to prioritize influential insights
|
|
454
|
+
await bridge.curateIndex();
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Standalone Usage
|
|
458
|
+
|
|
459
|
+
```typescript
|
|
460
|
+
import { MemoryGraph } from '@monomind/memory';
|
|
461
|
+
|
|
462
|
+
const graph = new MemoryGraph({
|
|
463
|
+
pageRankDamping: 0.85,
|
|
464
|
+
pageRankIterations: 50,
|
|
465
|
+
pageRankConvergence: 1e-6,
|
|
466
|
+
maxNodes: 5000,
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
// Build from backend entries
|
|
470
|
+
await graph.buildFromBackend(backend, 'my-namespace');
|
|
471
|
+
|
|
472
|
+
// Or build manually
|
|
473
|
+
graph.addNode(entry);
|
|
474
|
+
graph.addEdge('entry-1', 'entry-2', 'reference', 1.0);
|
|
475
|
+
graph.addEdge('entry-1', 'entry-3', 'similar', 0.9);
|
|
476
|
+
|
|
477
|
+
// Compute PageRank (power iteration)
|
|
478
|
+
const ranks = graph.computePageRank();
|
|
479
|
+
|
|
480
|
+
// Detect communities (label propagation)
|
|
481
|
+
const communities = graph.detectCommunities();
|
|
482
|
+
|
|
483
|
+
// Graph-aware ranking: blend vector score + PageRank
|
|
484
|
+
const ranked = graph.rankWithGraph(searchResults, 0.7);
|
|
485
|
+
// alpha=0.7 means 70% vector score + 30% PageRank
|
|
486
|
+
|
|
487
|
+
// Get most influential insights for MEMORY.md
|
|
488
|
+
const topNodes = graph.getTopNodes(20);
|
|
489
|
+
|
|
490
|
+
// BFS traversal for related insights
|
|
491
|
+
const neighbors = graph.getNeighbors('entry-1', 2); // depth=2
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### Edge Types
|
|
495
|
+
|
|
496
|
+
| Type | Source | Description |
|
|
497
|
+
|------|--------|-------------|
|
|
498
|
+
| `reference` | `MemoryEntry.references` | Explicit cross-references between entries |
|
|
499
|
+
| `similar` | HNSW search | Auto-created when similarity > threshold |
|
|
500
|
+
| `temporal` | Timestamps | Entries created in same time window |
|
|
501
|
+
| `co-accessed` | Access patterns | Entries frequently accessed together |
|
|
502
|
+
| `causal` | Learning pipeline | Cause-effect relationships |
|
|
503
|
+
|
|
504
|
+
### Performance
|
|
505
|
+
|
|
506
|
+
| Operation | Result | Target |
|
|
507
|
+
|-----------|--------|--------|
|
|
508
|
+
| Graph build (1k nodes) | 2.78 ms | <200 ms |
|
|
509
|
+
| PageRank (1k nodes) | 12.21 ms | <100 ms |
|
|
510
|
+
| Community detection (1k) | 19.62 ms | — |
|
|
511
|
+
| `rankWithGraph(10)` | 0.006 ms | — |
|
|
512
|
+
| `getTopNodes(20)` | 0.308 ms | — |
|
|
513
|
+
| `getNeighbors(d=2)` | 0.005 ms | — |
|
|
514
|
+
|
|
515
|
+
## Agent-Scoped Memory (ADR-049)
|
|
516
|
+
|
|
517
|
+
Maps Claude Code's 3-scope agent memory directories for per-agent knowledge isolation and cross-agent transfer.
|
|
518
|
+
|
|
519
|
+
### Quick Start
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
import { createAgentBridge, transferKnowledge } from '@monomind/memory';
|
|
523
|
+
|
|
524
|
+
// Create a bridge for a specific agent scope
|
|
525
|
+
const agentBridge = createAgentBridge(backend, {
|
|
526
|
+
agentName: 'my-coder',
|
|
527
|
+
scope: 'project', // 'project' | 'local' | 'user'
|
|
528
|
+
workingDir: '/workspaces/my-project',
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
// Record insights scoped to this agent
|
|
532
|
+
await agentBridge.recordInsight({
|
|
533
|
+
category: 'debugging',
|
|
534
|
+
summary: 'Use connection pooling for DB calls',
|
|
535
|
+
source: 'agent:my-coder',
|
|
536
|
+
confidence: 0.95,
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
// Transfer high-confidence insights between agents
|
|
540
|
+
const result = await transferKnowledge(sourceBackend, targetBridge, {
|
|
541
|
+
sourceNamespace: 'learnings',
|
|
542
|
+
minConfidence: 0.8, // Only transfer confident insights
|
|
543
|
+
maxEntries: 20,
|
|
544
|
+
categories: ['debugging', 'architecture'],
|
|
545
|
+
});
|
|
546
|
+
// { transferred: 15, skipped: 5 }
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
### Scope Paths
|
|
550
|
+
|
|
551
|
+
| Scope | Directory | Use Case |
|
|
552
|
+
|-------|-----------|----------|
|
|
553
|
+
| `project` | `<gitRoot>/.claude/agent-memory/<agent>/` | Project-specific learnings |
|
|
554
|
+
| `local` | `<gitRoot>/.claude/agent-memory-local/<agent>/` | Machine-local data |
|
|
555
|
+
| `user` | `~/.claude/agent-memory/<agent>/` | Cross-project user knowledge |
|
|
556
|
+
|
|
557
|
+
### Utilities
|
|
558
|
+
|
|
559
|
+
```typescript
|
|
560
|
+
import {
|
|
561
|
+
resolveAgentMemoryDir, // Get scope directory path
|
|
562
|
+
createAgentBridge, // Create scoped AutoMemoryBridge
|
|
563
|
+
transferKnowledge, // Cross-agent knowledge sharing
|
|
564
|
+
listAgentScopes, // Discover existing agent scopes
|
|
565
|
+
} from '@monomind/memory';
|
|
566
|
+
|
|
567
|
+
// Resolve path for an agent scope
|
|
568
|
+
const dir = resolveAgentMemoryDir('my-agent', 'project');
|
|
569
|
+
// → /workspaces/my-project/.claude/agent-memory/my-agent/
|
|
570
|
+
|
|
571
|
+
// List all agent scopes in a directory
|
|
572
|
+
const scopes = await listAgentScopes('/workspaces/my-project');
|
|
573
|
+
// [{ agentName: 'coder', scope: 'project', path: '...' }, ...]
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
## A-MEM Auto-Linking (arXiv:2409.11987)
|
|
577
|
+
|
|
578
|
+
When `HybridBackend` is configured with an `embeddingGenerator`, every stored entry
|
|
579
|
+
automatically discovers its top-3 semantic neighbors and creates bidirectional
|
|
580
|
+
`references` edges — implementing the Zettelkasten note-linking structure from A-MEM.
|
|
581
|
+
|
|
582
|
+
```typescript
|
|
583
|
+
const backend = new HybridBackend({
|
|
584
|
+
embeddingGenerator: async (text) => myEmbeddingModel.embed(text),
|
|
585
|
+
// A-MEM auto-linking is automatically active when embeddingGenerator is set
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
// Store any entry — references are linked asynchronously, best-effort
|
|
589
|
+
await backend.store(entry);
|
|
590
|
+
|
|
591
|
+
// After linking, querySemantic PPR re-ranking propagates scores through the
|
|
592
|
+
// newly created reference graph, improving recall for connected knowledge.
|
|
593
|
+
backend.on('amem:linked', ({ id, linkedTo }) =>
|
|
594
|
+
console.log(`Linked ${id} to ${linkedTo.join(', ')}`));
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
## Injection-Safe Semantic Search
|
|
598
|
+
|
|
599
|
+
Set `filterInjection: true` to remove entries containing prompt-injection patterns
|
|
600
|
+
from semantic search results before they reach the agent context:
|
|
601
|
+
|
|
602
|
+
```typescript
|
|
603
|
+
const backend = new HybridBackend({
|
|
604
|
+
embeddingGenerator: myEmbedder,
|
|
605
|
+
filterInjection: true, // Screen RAG results for indirect injection
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
// Filtered result — entries matching injection patterns are silently dropped
|
|
609
|
+
const entries = await backend.querySemantic({ content: 'OAuth patterns', k: 10 });
|
|
610
|
+
|
|
611
|
+
// Blocked entries are observable via event
|
|
612
|
+
backend.on('injection:blocked', ({ id, namespace }) =>
|
|
613
|
+
securityLogger.warn(`Injection blocked from entry ${id}`));
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
Source: arXiv:2302.12173, arXiv:2310.12815 — indirect prompt injection in RAG pipelines.
|
|
617
|
+
|
|
618
|
+
## GraphRAG Community Retrieval (arXiv:2404.16130)
|
|
619
|
+
|
|
620
|
+
`querySemantic()` now captures community summaries from `MemoryGraph.getCommunitySummaries()`
|
|
621
|
+
and annotates each returned entry with its GraphRAG community metadata. This implements
|
|
622
|
+
the community-level summarisation strategy from Microsoft GraphRAG.
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
const entries = await backend.querySemantic({ content: 'authentication patterns', k: 10 });
|
|
626
|
+
// Each entry now carries:
|
|
627
|
+
// entry.community — community ID string
|
|
628
|
+
// entry.communityNodeCount — number of nodes in that community
|
|
629
|
+
// entry.communityAvgPageRank — mean PageRank of community members
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
PPR re-ranking is handled by HippoRAG-style personalised PageRank (arXiv:2405.14831),
|
|
633
|
+
which propagates query-node scores through the knowledge graph before returning results.
|
|
634
|
+
|
|
635
|
+
## Collaborative Memory Promotion (arXiv:2505.18279)
|
|
636
|
+
|
|
637
|
+
`HybridBackend.get(id, agentId?)` accepts an optional `agentId` parameter. When
|
|
638
|
+
provided, it fires a read-tracking call to the SQLite backend, which promotes the
|
|
639
|
+
entry's `AccessLevel` from `'private'` to `'team'` once **3 or more distinct agents**
|
|
640
|
+
have accessed it within a 24-hour window.
|
|
641
|
+
|
|
642
|
+
```typescript
|
|
643
|
+
// Each agent reads with its own ID — no other change required
|
|
644
|
+
const entry = await backend.get('entry-id-123', 'coder-agent');
|
|
645
|
+
|
|
646
|
+
// After the third distinct agent reads it within 24 h:
|
|
647
|
+
// entry.accessLevel === 'team'
|
|
648
|
+
// (auto-promoted, visible to peer agents in the same namespace)
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
Collaborative promotion is transparent to callers that don't pass `agentId` —
|
|
652
|
+
`get(id)` continues to work exactly as before (backwards-compatible).
|
|
653
|
+
|
|
654
|
+
## Knowledge Graph & Temporal Edges (arXiv:2501.13956)
|
|
655
|
+
|
|
656
|
+
`MemoryGraph` models causal and temporal relationships between entries as typed
|
|
657
|
+
edges, inspired by the Zep/Graphiti episodic knowledge graph (arXiv:2501.13956).
|
|
658
|
+
Edge types include `REFERENCES`, `CAUSES`, `PRECEDED_BY`, `RELATED_TO`, and
|
|
659
|
+
`CONTRADICTS`, enabling episodic reasoning over the agent's memory history.
|
|
660
|
+
|
|
661
|
+
```typescript
|
|
662
|
+
import { MemoryGraph, type EdgeType } from '@monomind/memory';
|
|
663
|
+
|
|
664
|
+
const graph = new MemoryGraph();
|
|
665
|
+
graph.addEdge('plan-123', 'code-456', EdgeType.CAUSES, 0.9);
|
|
666
|
+
graph.addEdge('code-456', 'test-789', EdgeType.PRECEDED_BY, 1.0);
|
|
667
|
+
|
|
668
|
+
const ranked = graph.pprRerank(['plan-123'], candidates, 0.85);
|
|
669
|
+
// Entries causally downstream of 'plan-123' score higher in PPR
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
## μACP Learning-Bridge Integration (arXiv:2601.03938)
|
|
673
|
+
|
|
674
|
+
`LearningBridge` integrates with the μACP coordination substrate: when consolidation
|
|
675
|
+
detects a pattern conflict between agents, it initiates a μACP round to resolve which
|
|
676
|
+
variant to promote. The result is stored as a causal edge in `MemoryGraph`.
|
|
677
|
+
|
|
678
|
+
```typescript
|
|
679
|
+
// Conflict resolution is automatic during consolidation:
|
|
680
|
+
await learningBridge.consolidate();
|
|
681
|
+
// Internally calls MuACP.coordinate() when divergent patterns are detected,
|
|
682
|
+
// then records the winning pattern as a CAUSES edge.
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
Source: arXiv:2601.03938.
|
|
686
|
+
|
|
687
|
+
## Bi-Temporal Query Filtering (arXiv:2501.13956)
|
|
688
|
+
|
|
689
|
+
`MemoryQuery` now supports `eventAfter` and `eventBefore` filters that operate on the
|
|
690
|
+
`eventAt` field — the timestamp of *when the event occurred* (T), as opposed to
|
|
691
|
+
`createdAt` which records *when the entry was ingested* (T'). This is the bi-temporal
|
|
692
|
+
model from Zep/Graphiti that prevents retrieval failures when data arrives out-of-order
|
|
693
|
+
or is backdated.
|
|
694
|
+
|
|
695
|
+
```typescript
|
|
696
|
+
const entries = await backend.query({
|
|
697
|
+
type: 'hybrid',
|
|
698
|
+
namespace: 'incidents',
|
|
699
|
+
limit: 50,
|
|
700
|
+
// Filter by WHEN THE INCIDENT HAPPENED — not when it was logged
|
|
701
|
+
eventAfter: new Date('2026-01-01').getTime(),
|
|
702
|
+
eventBefore: new Date('2026-04-01').getTime(),
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
// Store with explicit event time (e.g. a past incident being recorded now)
|
|
706
|
+
await backend.store({
|
|
707
|
+
key: 'outage-2026-02-14',
|
|
708
|
+
content: 'DB connection pool exhausted during peak traffic',
|
|
709
|
+
type: 'episodic',
|
|
710
|
+
namespace: 'incidents',
|
|
711
|
+
eventAt: new Date('2026-02-14T03:22:00Z').getTime(), // event time
|
|
712
|
+
// createdAt is auto-set to Date.now() (ingestion time)
|
|
713
|
+
// ...
|
|
714
|
+
});
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
Source: arXiv:2501.13956 — Zep/Graphiti bi-temporal knowledge graph.
|
|
718
|
+
|
|
719
|
+
## MemoRAG Query Rewriting (arXiv:2409.05591)
|
|
720
|
+
|
|
721
|
+
`HybridBackend` supports a `memoragRewriter` configuration option that adds a
|
|
722
|
+
"draft clue" query-expansion stage before HNSW search. When configured, `querySemantic()`
|
|
723
|
+
calls the rewriter to generate 2-3 reformulated sub-queries, searches HNSW independently
|
|
724
|
+
for each, then fuses all ranked result lists using **Reciprocal Rank Fusion (RRF)** before
|
|
725
|
+
continuing with HippoRAG PPR re-ranking and GraphRAG community annotation.
|
|
726
|
+
|
|
727
|
+
This addresses the MemoRAG insight that naive RAG fails when the user query does not
|
|
728
|
+
directly match any retrievable chunk — paraphrased sub-queries dramatically improve recall.
|
|
729
|
+
|
|
730
|
+
```typescript
|
|
731
|
+
import { HybridBackend } from '@monomind/memory';
|
|
732
|
+
|
|
733
|
+
const backend = new HybridBackend({
|
|
734
|
+
embeddingGenerator: myEmbedder,
|
|
735
|
+
memoragRewriter: async (query) => {
|
|
736
|
+
// Use a cheap LLM (Haiku) or deterministic rules to produce sub-queries
|
|
737
|
+
const reformulated = await callClaude({
|
|
738
|
+
model: 'claude-haiku-4-5',
|
|
739
|
+
prompt: `Generate 3 alternative search queries for: "${query}"\nRespond with a JSON array of strings.`,
|
|
740
|
+
});
|
|
741
|
+
return JSON.parse(reformulated); // e.g. ["...", "...", "..."]
|
|
742
|
+
},
|
|
743
|
+
});
|
|
744
|
+
|
|
745
|
+
// querySemantic() now automatically expands + fuses results
|
|
746
|
+
const results = await backend.querySemantic({ content: 'memory leak in production' });
|
|
747
|
+
// RRF-fused results from sub-queries: "heap usage spike", "GC pressure", "OOM error"
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
Source: arXiv:2409.05591 — MemoRAG (TheWebConf 2025).
|
|
751
|
+
|
|
752
|
+
## DiskANN Backend — Large-Scale ANN at Disk Scale (arXiv:2305.04359)
|
|
753
|
+
|
|
754
|
+
`DiskAnnBackend` is an `IMemoryBackend` decorator that activates SSD-resident Vamana ANN search above entry-count thresholds. Wraps any existing backend (typically the long-term SQLite/AgentDB backend in `TierManager`).
|
|
755
|
+
|
|
756
|
+
### Architecture
|
|
757
|
+
|
|
758
|
+
- **Disk-persisted adjacency list** — Vamana graph written to `graphPath` as JSON
|
|
759
|
+
- **In-memory Int8-quantised vectors** — `Map<string, Int8Array>` for fast beam search
|
|
760
|
+
- **Beam search** — BFS traversal using Int8 dot-product as the candidate scorer
|
|
761
|
+
- **Full-precision cosine re-ranking** — fetches raw embeddings from the delegate backend
|
|
762
|
+
|
|
763
|
+
### Quick Start
|
|
764
|
+
|
|
765
|
+
```typescript
|
|
766
|
+
import { DiskAnnBackend, type DiskAnnBackendConfig } from '@monomind/memory';
|
|
767
|
+
|
|
768
|
+
// Wrap any IMemoryBackend
|
|
769
|
+
const diskann = new DiskAnnBackend(existingBackend, {
|
|
770
|
+
graphPath: './data/diskann.graph.json',
|
|
771
|
+
R: 32, // Max graph degree (default: 32)
|
|
772
|
+
L: 64, // Beam width (default: 64)
|
|
773
|
+
beamWidth: 10, // Search beam candidates (default: 10)
|
|
774
|
+
dimensions: 128, // Vector dimensions (default: 128)
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
// All CRUD proxies through to the wrapped backend
|
|
778
|
+
await diskann.store(entry);
|
|
779
|
+
await diskann.get(id);
|
|
780
|
+
|
|
781
|
+
// ANN search uses beam traversal + cosine re-ranking
|
|
782
|
+
const results = await diskann.search(queryVector, { k: 5 });
|
|
783
|
+
// [{ entry: MemoryEntry, score: number }, ...]
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
### TierManager Integration
|
|
787
|
+
|
|
788
|
+
Pass `diskAnnConfig` to activate DiskANN on the long-term backend:
|
|
789
|
+
|
|
790
|
+
```typescript
|
|
791
|
+
import { TierManager } from '@monomind/memory';
|
|
792
|
+
|
|
793
|
+
const tier = new TierManager(
|
|
794
|
+
longTermBackend,
|
|
795
|
+
{ shortTermCapacity: 1000 },
|
|
796
|
+
{}, // PartitionedHNSW config
|
|
797
|
+
{ // DiskAnnBackendConfig — activates DiskANN
|
|
798
|
+
graphPath: './data/diskann.graph.json',
|
|
799
|
+
R: 32,
|
|
800
|
+
beamWidth: 12,
|
|
801
|
+
},
|
|
802
|
+
);
|
|
803
|
+
|
|
804
|
+
// tier.diskann is now populated — search() includes DiskANN results
|
|
805
|
+
const results = await tier.search('authentication patterns', 10);
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
### DiskAnnBackendConfig
|
|
809
|
+
|
|
810
|
+
| Field | Default | Description |
|
|
811
|
+
|-------|---------|-------------|
|
|
812
|
+
| `graphPath` | `'./diskann.graph.json'` | Path for persisted Vamana adjacency list |
|
|
813
|
+
| `R` | `32` | Max out-degree per node |
|
|
814
|
+
| `L` | `64` | Beam width during construction |
|
|
815
|
+
| `beamWidth` | `10` | Beam width during search |
|
|
816
|
+
| `dimensions` | `128` | Vector dimensions |
|
|
817
|
+
|
|
818
|
+
## Performance Benchmarks
|
|
819
|
+
|
|
820
|
+
| Operation | V2 Performance | V1 Performance | Improvement |
|
|
821
|
+
|-----------|---------------|----------------|-------------|
|
|
822
|
+
| Vector Search | 150ms | <1ms | **150x** |
|
|
823
|
+
| Bulk Insert | 500ms | 5ms | **100x** |
|
|
824
|
+
| Memory Write | 50ms | <5ms | **10x** |
|
|
825
|
+
| Cache Hit | 5ms | <0.1ms | **50x** |
|
|
826
|
+
| Index Build | 10s | 800ms | **12.5x** |
|
|
827
|
+
|
|
828
|
+
### ADR-049 Benchmarks
|
|
829
|
+
|
|
830
|
+
| Operation | Actual | Target | Headroom |
|
|
831
|
+
|-----------|--------|--------|----------|
|
|
832
|
+
| Graph build (1k nodes) | 2.78 ms | <200 ms | **71.9x** |
|
|
833
|
+
| PageRank (1k nodes) | 12.21 ms | <100 ms | **8.2x** |
|
|
834
|
+
| Insight recording | 0.12 ms/each | <5 ms/each | **41.0x** |
|
|
835
|
+
| Consolidation | 0.26 ms | <500 ms | **1,955x** |
|
|
836
|
+
| Confidence decay (1k) | 0.23 ms | <50 ms | **215x** |
|
|
837
|
+
| Knowledge transfer | 1.25 ms | <100 ms | **80.0x** |
|
|
838
|
+
|
|
839
|
+
## TypeScript Types
|
|
840
|
+
|
|
841
|
+
```typescript
|
|
842
|
+
import type {
|
|
843
|
+
// Core entry and query types
|
|
844
|
+
MemoryEntry, MemoryEntryInput, MemoryEntryUpdate,
|
|
845
|
+
MemoryQuery, MemoryType, AccessLevel,
|
|
846
|
+
SearchResult, SearchOptions,
|
|
847
|
+
|
|
848
|
+
// Query builder sort fields
|
|
849
|
+
SortField, // 'createdAt' | 'updatedAt' | 'lastAccessedAt' | 'accessCount' | 'key' | 'score'
|
|
850
|
+
SortDirection, // 'asc' | 'desc'
|
|
851
|
+
|
|
852
|
+
// HNSW
|
|
853
|
+
HNSWConfig, HNSWStats, QuantizationConfig, DistanceMetric,
|
|
854
|
+
|
|
855
|
+
// Backend interfaces
|
|
856
|
+
IMemoryBackend, BackendStats, HealthCheckResult,
|
|
857
|
+
|
|
858
|
+
// Cache
|
|
859
|
+
CacheConfig, CacheStats,
|
|
860
|
+
|
|
861
|
+
// Auto Memory Bridge (ADR-048)
|
|
862
|
+
AutoMemoryBridgeConfig, MemoryInsight, InsightCategory,
|
|
863
|
+
SyncMode, SyncResult, ImportResult,
|
|
864
|
+
|
|
865
|
+
// Agent Scope (ADR-049)
|
|
866
|
+
AgentMemoryScope, AgentScopedConfig,
|
|
867
|
+
TransferOptions, TransferResult,
|
|
868
|
+
|
|
869
|
+
// Learning Bridge (ADR-049)
|
|
870
|
+
LearningBridgeConfig, ConsolidateResult, PatternMatch,
|
|
871
|
+
|
|
872
|
+
// Knowledge Graph (ADR-049)
|
|
873
|
+
MemoryGraphConfig, GraphNode, GraphEdge,
|
|
874
|
+
GraphStats, RankedResult,
|
|
875
|
+
|
|
876
|
+
// Tiers
|
|
877
|
+
MemoryTier, EntityFact, SessionSummary,
|
|
878
|
+
|
|
879
|
+
// Migration
|
|
880
|
+
MigrationSource, MigrationConfig, MigrationResult,
|
|
881
|
+
|
|
882
|
+
// Checkpointing
|
|
883
|
+
AgentState, SwarmCheckpoint, CheckpointMeta,
|
|
884
|
+
} from '@monomind/memory';
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
## Dependencies
|
|
888
|
+
|
|
889
|
+
- `agentdb` - Vector database engine
|
|
890
|
+
- `better-sqlite3` - SQLite driver (native)
|
|
891
|
+
- `sql.js` - SQLite driver (WASM fallback)
|
|
892
|
+
- `@monomind/neural` - **Optional peer dependency** for self-learning (graceful fallback when unavailable)
|
|
893
|
+
|
|
894
|
+
## Related Packages
|
|
895
|
+
|
|
896
|
+
- [@monomind/neural](../neural) - Neural learning integration (SONA, ReasoningBank, EWC++)
|
|
897
|
+
- [@monomind/shared](../shared) - Shared types and utilities
|
|
898
|
+
- [@monomind/hooks](../hooks) - Session lifecycle hooks for auto memory sync
|
|
899
|
+
|
|
900
|
+
## License
|
|
901
|
+
|
|
902
|
+
MIT
|