@monoes/memory 1.0.1 → 1.0.3

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 (47) hide show
  1. package/README.md +1 -7
  2. package/dist/controller-registry.d.ts +1 -1
  3. package/dist/controller-registry.d.ts.map +1 -1
  4. package/dist/controller-registry.js +3 -3
  5. package/dist/controller-registry.js.map +1 -1
  6. package/dist/database-provider.d.ts +1 -2
  7. package/dist/database-provider.d.ts.map +1 -1
  8. package/dist/database-provider.js +0 -25
  9. package/dist/database-provider.js.map +1 -1
  10. package/dist/index.d.ts +0 -12
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +0 -8
  13. package/dist/index.js.map +1 -1
  14. package/dist/lancedb-backend.d.ts.map +1 -1
  15. package/dist/lancedb-backend.js +40 -12
  16. package/dist/lancedb-backend.js.map +1 -1
  17. package/dist/types.d.ts +1 -1
  18. package/dist/types.d.ts.map +1 -1
  19. package/package.json +10 -11
  20. package/dist/hnsw-lite.d.ts +0 -29
  21. package/dist/hnsw-lite.d.ts.map +0 -1
  22. package/dist/hnsw-lite.js +0 -240
  23. package/dist/hnsw-lite.js.map +0 -1
  24. package/dist/hybrid-backend.d.ts +0 -297
  25. package/dist/hybrid-backend.d.ts.map +0 -1
  26. package/dist/hybrid-backend.js +0 -805
  27. package/dist/hybrid-backend.js.map +0 -1
  28. package/dist/persistent-sona.d.ts +0 -144
  29. package/dist/persistent-sona.d.ts.map +0 -1
  30. package/dist/persistent-sona.js +0 -311
  31. package/dist/persistent-sona.js.map +0 -1
  32. package/dist/procedural/procedure-extractor-worker.d.ts +0 -27
  33. package/dist/procedural/procedure-extractor-worker.d.ts.map +0 -1
  34. package/dist/procedural/procedure-extractor-worker.js +0 -39
  35. package/dist/procedural/procedure-extractor-worker.js.map +0 -1
  36. package/dist/rvf-backend.d.ts +0 -53
  37. package/dist/rvf-backend.d.ts.map +0 -1
  38. package/dist/rvf-backend.js +0 -507
  39. package/dist/rvf-backend.js.map +0 -1
  40. package/dist/rvf-learning-store.d.ts +0 -141
  41. package/dist/rvf-learning-store.d.ts.map +0 -1
  42. package/dist/rvf-learning-store.js +0 -344
  43. package/dist/rvf-learning-store.js.map +0 -1
  44. package/dist/rvf-migration.d.ts +0 -45
  45. package/dist/rvf-migration.d.ts.map +0 -1
  46. package/dist/rvf-migration.js +0 -254
  47. package/dist/rvf-migration.js.map +0 -1
@@ -1,297 +0,0 @@
1
- /**
2
- * HybridBackend - Combines SQLite (structured queries) + LanceDB (vector search)
3
- *
4
- * Per ADR-009: "HybridBackend (SQLite + LanceDB) as default"
5
- * - SQLite for: Structured queries, ACID transactions, exact matches
6
- * - LanceDB for: Semantic search, vector similarity, RAG
7
- *
8
- * @module v1/memory/hybrid-backend
9
- */
10
- import { EventEmitter } from 'node:events';
11
- import { IMemoryBackend, MemoryEntry, MemoryEntryUpdate, MemoryQuery, SearchOptions, SearchResult, BackendStats, HealthCheckResult, EmbeddingGenerator } from './types.js';
12
- import { SQLiteBackendConfig } from './sqlite-backend.js';
13
- import { LanceDBBackendConfig } from './lancedb-backend.js';
14
- /**
15
- * Configuration for HybridBackend
16
- */
17
- export interface HybridBackendConfig {
18
- /** SQLite configuration */
19
- sqlite?: Partial<SQLiteBackendConfig>;
20
- /** LanceDB configuration override */
21
- /**
22
- * LanceDB configuration (used when semanticBackend is 'lancedb').
23
- * Requires: npm install @lancedb/lancedb apache-arrow
24
- */
25
- lancedb?: LanceDBBackendConfig;
26
- /** Which backend handles semantic (vector) search. Always 'lancedb'. */
27
- semanticBackend?: 'lancedb';
28
- /** Default namespace */
29
- defaultNamespace?: string;
30
- /** Embedding generator function */
31
- embeddingGenerator?: EmbeddingGenerator;
32
- /** Query routing strategy */
33
- routingStrategy?: 'auto' | 'sqlite-first' | 'semantic-first';
34
- /** Enable dual-write (write to both backends) */
35
- dualWrite?: boolean;
36
- /** Semantic search threshold for hybrid queries */
37
- semanticThreshold?: number;
38
- /** Maximum results to fetch from each backend in hybrid queries */
39
- hybridMaxResults?: number;
40
- /**
41
- * Filter semantic search results for prompt-injection patterns.
42
- * When true, entries whose content matches known injection signatures are
43
- * removed from results and an `injection:blocked` event is emitted.
44
- * Source: newinnovation.md §5 — Semantic injection detection
45
- */
46
- filterInjection?: boolean;
47
- /**
48
- * MemoRAG query rewriter — generates 2-3 reformulated sub-queries before HNSW.
49
- *
50
- * When provided, `querySemantic()` calls this function on the original query text
51
- * to produce alternative formulations (e.g. more specific, paraphrased, or
52
- * keyword-expanded variants). Each sub-query is embedded and searched independently;
53
- * results are fused using Reciprocal Rank Fusion (RRF).
54
- *
55
- * Use a cheap LLM call (Haiku) or a deterministic paraphrase function.
56
- * Source: arXiv:2409.05591 — MemoRAG (TheWebConf 2025)
57
- */
58
- memoragRewriter?: (query: string) => Promise<string[]>;
59
- }
60
- /**
61
- * Structured Query Interface
62
- * Optimized for SQLite's strengths
63
- */
64
- export interface StructuredQuery {
65
- /** Exact key match */
66
- key?: string;
67
- /** Key prefix match */
68
- keyPrefix?: string;
69
- /** Namespace filter */
70
- namespace?: string;
71
- /** Owner filter */
72
- ownerId?: string;
73
- /** Type filter */
74
- type?: string;
75
- /** Time range filters */
76
- createdAfter?: number;
77
- createdBefore?: number;
78
- updatedAfter?: number;
79
- updatedBefore?: number;
80
- /** Pagination */
81
- limit?: number;
82
- offset?: number;
83
- }
84
- /**
85
- * Semantic Query Interface
86
- * Optimized for LanceDB's vector search
87
- */
88
- export interface SemanticQuery {
89
- /** Content to search for (will be embedded) */
90
- content?: string;
91
- /** Pre-computed embedding */
92
- embedding?: Float32Array;
93
- /** Number of results */
94
- k?: number;
95
- /** Similarity threshold (0-1) */
96
- threshold?: number;
97
- /** Additional filters */
98
- filters?: Partial<MemoryQuery>;
99
- }
100
- /**
101
- * Hybrid Query Interface
102
- * Combines structured + semantic search
103
- */
104
- export interface HybridQuery {
105
- /** Semantic component */
106
- semantic: SemanticQuery;
107
- /** Structured component */
108
- structured?: StructuredQuery;
109
- /** How to combine results */
110
- combineStrategy?: 'union' | 'intersection' | 'semantic-first' | 'structured-first';
111
- /** Weights for score combination */
112
- weights?: {
113
- semantic: number;
114
- structured: number;
115
- };
116
- }
117
- /**
118
- * HybridBackend Implementation
119
- *
120
- * Intelligently routes queries between SQLite and LanceDB:
121
- * - Exact matches, prefix queries → SQLite
122
- * - Semantic search, similarity → LanceDB
123
- * - Complex hybrid queries → Both backends with intelligent merging
124
- */
125
- export declare class HybridBackend extends EventEmitter implements IMemoryBackend {
126
- private sqlite;
127
- private semantic;
128
- private config;
129
- private initialized;
130
- /** Lazy MemoryGraph for HippoRAG PPR re-ranking */
131
- private memoryGraph;
132
- private stats;
133
- constructor(config?: HybridBackendConfig);
134
- /**
135
- * Initialize both backends
136
- */
137
- initialize(): Promise<void>;
138
- /**
139
- * Shutdown both backends
140
- */
141
- shutdown(): Promise<void>;
142
- /**
143
- * Store in both backends (dual-write for consistency).
144
- *
145
- * A-MEM auto-linking: after writing, HNSW-searches for the top-3 most similar
146
- * existing entries and adds bidirectional `references` edges between them and
147
- * the new entry. Only runs when an `embeddingGenerator` is configured.
148
- * Source: arXiv:2409.11987 (A-MEM — Zettelkasten-style agent memory)
149
- */
150
- store(entry: MemoryEntry): Promise<void>;
151
- /**
152
- * A-MEM bidirectional reference linking.
153
- * Finds the top-3 semantically similar existing entries and creates
154
- * `references` edges in both directions.
155
- */
156
- private aMemAutoLink;
157
- /**
158
- * Get from semantic backend.
159
- *
160
- * Collaborative memory promotion: when `agentId` is supplied, also notifies
161
- * the SQLite backend so it can track the read and promote the entry's
162
- * AccessLevel to 'team' once 3+ distinct agents have accessed it.
163
- * Source: newinnovation.md §2.7 — memory access-level promotion.
164
- */
165
- get(id: string, agentId?: string): Promise<MemoryEntry | null>;
166
- /**
167
- * Get by key (SQLite optimized for exact matches)
168
- */
169
- getByKey(namespace: string, key: string): Promise<MemoryEntry | null>;
170
- /**
171
- * Update in both backends
172
- */
173
- update(id: string, update: MemoryEntryUpdate): Promise<MemoryEntry | null>;
174
- /**
175
- * Delete from both backends
176
- */
177
- delete(id: string): Promise<boolean>;
178
- /**
179
- * Query routing — semantic goes to LanceDB, structured to SQLite
180
- */
181
- query(query: MemoryQuery): Promise<MemoryEntry[]>;
182
- /**
183
- * Structured queries (SQL)
184
- * Routes to SQLite for optimal performance
185
- */
186
- queryStructured(query: StructuredQuery): Promise<MemoryEntry[]>;
187
- /**
188
- * Apply injection filtering and structured field filters to a set of entries.
189
- * Used by the MemoRAG path (RRF-fused results) and as a shared post-processing step.
190
- */
191
- private postProcessSemanticResults;
192
- /**
193
- * Reciprocal Rank Fusion — merge multiple ranked result lists.
194
- * Score for entry i in list j: 1 / (k + rank_j(i)) where k=60 (standard).
195
- * Source: Cormack et al., "Reciprocal Rank Fusion outperforms Condorcet and individual
196
- * Rank Learning Methods" (SIGIR 2009). Used by MemoRAG sub-query fusion.
197
- */
198
- private rrfFuse;
199
- /**
200
- * Semantic queries (vector)
201
- * Routes to semantic backend for ANN vector search.
202
- *
203
- * MemoRAG query rewriting (arXiv:2409.05591): when `memoragRewriter` is configured
204
- * and `query.content` is present, generates 2-3 reformulated sub-queries, embeds
205
- * each, searches HNSW independently, then fuses with Reciprocal Rank Fusion (RRF)
206
- * before HippoRAG PPR re-ranking.
207
- */
208
- querySemantic(query: SemanticQuery): Promise<MemoryEntry[]>;
209
- /**
210
- * Hybrid queries (combine both)
211
- * Intelligently merges results from both backends
212
- */
213
- queryHybrid(query: HybridQuery): Promise<MemoryEntry[]>;
214
- /**
215
- * Semantic vector search (routes to LanceDB)
216
- */
217
- search(embedding: Float32Array, options: SearchOptions): Promise<SearchResult[]>;
218
- /**
219
- * Bulk insert to both backends
220
- */
221
- bulkInsert(entries: MemoryEntry[]): Promise<void>;
222
- /**
223
- * Bulk delete from both backends
224
- */
225
- bulkDelete(ids: string[]): Promise<number>;
226
- /**
227
- * Count entries (use SQLite for efficiency)
228
- */
229
- count(namespace?: string): Promise<number>;
230
- /**
231
- * List namespaces (use SQLite)
232
- */
233
- listNamespaces(): Promise<string[]>;
234
- /**
235
- * Clear namespace in both backends
236
- */
237
- clearNamespace(namespace: string): Promise<number>;
238
- /**
239
- * Get combined statistics from both backends
240
- */
241
- getStats(): Promise<BackendStats>;
242
- /**
243
- * Health check for both backends
244
- */
245
- healthCheck(): Promise<HealthCheckResult>;
246
- /**
247
- * Auto-route queries based on properties
248
- */
249
- private autoRoute;
250
- /**
251
- * Internal hybrid query implementation
252
- */
253
- private queryHybridInternal;
254
- /**
255
- * Combine results using union (all unique results)
256
- */
257
- private combineUnion;
258
- /**
259
- * Combine results using intersection (only common results)
260
- */
261
- private combineIntersection;
262
- /**
263
- * Semantic-first: Prefer semantic results, add structured if not present
264
- */
265
- private combineSemanticFirst;
266
- /**
267
- * Structured-first: Prefer structured results, add semantic if not present
268
- */
269
- private combineStructuredFirst;
270
- /**
271
- * Record feedback for a memory entry.
272
- * Delegates to semantic backend's recordFeedback when available.
273
- * Gracefully degrades to no-op when unavailable.
274
- */
275
- recordFeedback(_entryId: string, _feedback: {
276
- score: number;
277
- label?: string;
278
- context?: Record<string, unknown>;
279
- }): Promise<boolean>;
280
- verifyWitnessChain(_entryId: string): Promise<{
281
- valid: boolean;
282
- chainLength: number;
283
- errors: string[];
284
- }>;
285
- getWitnessChain(_entryId: string): Promise<Array<{
286
- hash: string;
287
- timestamp: number;
288
- operation: string;
289
- }>>;
290
- /**
291
- * Get underlying backends for advanced operations
292
- */
293
- getSQLiteBackend(): IMemoryBackend;
294
- getSemanticBackend(): IMemoryBackend;
295
- }
296
- export default HybridBackend;
297
- //# sourceMappingURL=hybrid-backend.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hybrid-backend.d.ts","sourceRoot":"","sources":["../src/hybrid-backend.ts"],"names":[],"mappings":"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"}