@cmdoss/memwal-sdk 0.6.2 → 0.8.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/ARCHITECTURE.md +547 -547
- package/BENCHMARKS.md +238 -238
- package/README.md +310 -181
- package/dist/ai-sdk/tools.d.ts +2 -2
- package/dist/ai-sdk/tools.js +2 -2
- package/dist/client/ClientMemoryManager.js +2 -2
- package/dist/client/ClientMemoryManager.js.map +1 -1
- package/dist/client/PersonalDataWallet.d.ts.map +1 -1
- package/dist/client/SimplePDWClient.d.ts +29 -1
- package/dist/client/SimplePDWClient.d.ts.map +1 -1
- package/dist/client/SimplePDWClient.js +45 -13
- package/dist/client/SimplePDWClient.js.map +1 -1
- package/dist/client/namespaces/EmbeddingsNamespace.d.ts +1 -1
- package/dist/client/namespaces/EmbeddingsNamespace.js +1 -1
- package/dist/client/namespaces/MemoryNamespace.d.ts +31 -0
- package/dist/client/namespaces/MemoryNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/MemoryNamespace.js +272 -39
- package/dist/client/namespaces/MemoryNamespace.js.map +1 -1
- package/dist/client/namespaces/consolidated/AINamespace.d.ts +2 -2
- package/dist/client/namespaces/consolidated/AINamespace.js +2 -2
- package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts +12 -2
- package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/consolidated/BlockchainNamespace.js +62 -4
- package/dist/client/namespaces/consolidated/BlockchainNamespace.js.map +1 -1
- package/dist/client/namespaces/consolidated/StorageNamespace.d.ts +67 -2
- package/dist/client/namespaces/consolidated/StorageNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/consolidated/StorageNamespace.js +549 -16
- package/dist/client/namespaces/consolidated/StorageNamespace.js.map +1 -1
- package/dist/config/ConfigurationHelper.js +61 -61
- package/dist/config/defaults.js +2 -2
- package/dist/config/defaults.js.map +1 -1
- package/dist/graph/GraphService.js +21 -21
- package/dist/graph/GraphService.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/seal/EncryptionService.d.ts +9 -5
- package/dist/infrastructure/seal/EncryptionService.d.ts.map +1 -1
- package/dist/infrastructure/seal/EncryptionService.js +37 -15
- package/dist/infrastructure/seal/EncryptionService.js.map +1 -1
- package/dist/infrastructure/seal/SealService.d.ts +13 -5
- package/dist/infrastructure/seal/SealService.d.ts.map +1 -1
- package/dist/infrastructure/seal/SealService.js +36 -34
- package/dist/infrastructure/seal/SealService.js.map +1 -1
- package/dist/langchain/createPDWRAG.js +30 -30
- package/dist/retrieval/MemoryDecryptionPipeline.d.ts.map +1 -1
- package/dist/retrieval/MemoryDecryptionPipeline.js +2 -1
- package/dist/retrieval/MemoryDecryptionPipeline.js.map +1 -1
- package/dist/retrieval/MemoryRetrievalService.d.ts +31 -0
- package/dist/retrieval/MemoryRetrievalService.d.ts.map +1 -1
- package/dist/retrieval/MemoryRetrievalService.js +44 -4
- package/dist/retrieval/MemoryRetrievalService.js.map +1 -1
- package/dist/services/CapabilityService.d.ts.map +1 -1
- package/dist/services/CapabilityService.js +30 -14
- package/dist/services/CapabilityService.js.map +1 -1
- package/dist/services/CrossContextPermissionService.d.ts.map +1 -1
- package/dist/services/CrossContextPermissionService.js +9 -7
- package/dist/services/CrossContextPermissionService.js.map +1 -1
- package/dist/services/EmbeddingService.d.ts +28 -1
- package/dist/services/EmbeddingService.d.ts.map +1 -1
- package/dist/services/EmbeddingService.js +54 -0
- package/dist/services/EmbeddingService.js.map +1 -1
- package/dist/services/EncryptionService.d.ts.map +1 -1
- package/dist/services/EncryptionService.js +6 -5
- package/dist/services/EncryptionService.js.map +1 -1
- package/dist/services/GeminiAIService.js +309 -309
- package/dist/services/IndexManager.d.ts +5 -1
- package/dist/services/IndexManager.d.ts.map +1 -1
- package/dist/services/IndexManager.js +17 -40
- package/dist/services/IndexManager.js.map +1 -1
- package/dist/services/QueryService.js +1 -1
- package/dist/services/QueryService.js.map +1 -1
- package/dist/services/StorageService.d.ts +11 -0
- package/dist/services/StorageService.d.ts.map +1 -1
- package/dist/services/StorageService.js +73 -10
- package/dist/services/StorageService.js.map +1 -1
- package/dist/services/TransactionService.d.ts +20 -0
- package/dist/services/TransactionService.d.ts.map +1 -1
- package/dist/services/TransactionService.js +43 -0
- package/dist/services/TransactionService.js.map +1 -1
- package/dist/services/ViewService.js +2 -2
- package/dist/services/ViewService.js.map +1 -1
- package/dist/services/storage/QuiltBatchManager.d.ts +101 -1
- package/dist/services/storage/QuiltBatchManager.d.ts.map +1 -1
- package/dist/services/storage/QuiltBatchManager.js +410 -20
- package/dist/services/storage/QuiltBatchManager.js.map +1 -1
- package/dist/services/storage/index.d.ts +1 -1
- package/dist/services/storage/index.d.ts.map +1 -1
- package/dist/services/storage/index.js.map +1 -1
- package/dist/utils/LRUCache.d.ts +106 -0
- package/dist/utils/LRUCache.d.ts.map +1 -0
- package/dist/utils/LRUCache.js +281 -0
- package/dist/utils/LRUCache.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/memoryIndexOnChain.d.ts +212 -0
- package/dist/utils/memoryIndexOnChain.d.ts.map +1 -0
- package/dist/utils/memoryIndexOnChain.js +312 -0
- package/dist/utils/memoryIndexOnChain.js.map +1 -0
- package/dist/utils/rebuildIndexNode.d.ts +29 -0
- package/dist/utils/rebuildIndexNode.d.ts.map +1 -1
- package/dist/utils/rebuildIndexNode.js +366 -98
- package/dist/utils/rebuildIndexNode.js.map +1 -1
- package/dist/vector/HnswWasmService.d.ts +20 -5
- package/dist/vector/HnswWasmService.d.ts.map +1 -1
- package/dist/vector/HnswWasmService.js +73 -40
- package/dist/vector/HnswWasmService.js.map +1 -1
- package/dist/vector/IHnswService.d.ts +10 -1
- package/dist/vector/IHnswService.d.ts.map +1 -1
- package/dist/vector/IHnswService.js.map +1 -1
- package/dist/vector/NodeHnswService.d.ts +16 -0
- package/dist/vector/NodeHnswService.d.ts.map +1 -1
- package/dist/vector/NodeHnswService.js +84 -5
- package/dist/vector/NodeHnswService.js.map +1 -1
- package/dist/vector/createHnswService.d.ts +1 -1
- package/dist/vector/createHnswService.js +1 -1
- package/dist/vector/index.d.ts +1 -1
- package/dist/vector/index.js +1 -1
- package/package.json +157 -157
- package/src/access/PermissionService.ts +635 -635
- package/src/aggregation/AggregationService.ts +389 -389
- package/src/ai-sdk/PDWVectorStore.ts +715 -715
- package/src/ai-sdk/index.ts +65 -65
- package/src/ai-sdk/tools.ts +460 -460
- package/src/ai-sdk/types.ts +404 -404
- package/src/batch/BatchManager.ts +597 -597
- package/src/batch/BatchingService.ts +429 -429
- package/src/batch/MemoryProcessingCache.ts +492 -492
- package/src/batch/index.ts +30 -30
- package/src/browser.ts +200 -200
- package/src/client/ClientMemoryManager.ts +987 -987
- package/src/client/PersonalDataWallet.ts +345 -345
- package/src/client/SimplePDWClient.ts +1289 -1222
- package/src/client/factory.ts +154 -154
- package/src/client/namespaces/AnalyticsNamespace.ts +377 -377
- package/src/client/namespaces/BatchNamespace.ts +356 -356
- package/src/client/namespaces/CacheNamespace.ts +123 -123
- package/src/client/namespaces/CapabilityNamespace.ts +217 -217
- package/src/client/namespaces/ClassifyNamespace.ts +169 -169
- package/src/client/namespaces/ContextNamespace.ts +297 -297
- package/src/client/namespaces/EmbeddingsNamespace.ts +99 -99
- package/src/client/namespaces/EncryptionNamespace.ts +221 -221
- package/src/client/namespaces/GraphNamespace.ts +468 -468
- package/src/client/namespaces/IndexNamespace.ts +361 -361
- package/src/client/namespaces/MemoryNamespace.ts +1422 -1135
- package/src/client/namespaces/PermissionsNamespace.ts +254 -254
- package/src/client/namespaces/PipelineNamespace.ts +220 -220
- package/src/client/namespaces/SearchNamespace.ts +1049 -1049
- package/src/client/namespaces/StorageNamespace.ts +458 -458
- package/src/client/namespaces/TxNamespace.ts +260 -260
- package/src/client/namespaces/WalletNamespace.ts +243 -243
- package/src/client/namespaces/consolidated/AINamespace.ts +449 -449
- package/src/client/namespaces/consolidated/BlockchainNamespace.ts +607 -546
- package/src/client/namespaces/consolidated/SecurityNamespace.ts +648 -648
- package/src/client/namespaces/consolidated/StorageNamespace.ts +1141 -497
- package/src/client/namespaces/consolidated/index.ts +39 -39
- package/src/client/signers/KeypairSigner.ts +108 -108
- package/src/client/signers/UnifiedSigner.ts +110 -110
- package/src/client/signers/WalletAdapterSigner.ts +159 -159
- package/src/client/signers/index.ts +26 -26
- package/src/config/ConfigurationHelper.ts +412 -412
- package/src/config/defaults.ts +51 -51
- package/src/config/index.ts +8 -8
- package/src/config/validation.ts +70 -70
- package/src/core/index.ts +14 -14
- package/src/core/interfaces/IService.ts +307 -307
- package/src/core/interfaces/index.ts +8 -8
- package/src/core/types/capability.ts +297 -297
- package/src/core/types/index.ts +870 -870
- package/src/core/types/wallet.ts +270 -270
- package/src/core/types.ts +9 -9
- package/src/core/wallet.ts +222 -222
- package/src/embedding/index.ts +19 -19
- package/src/embedding/types.ts +357 -357
- package/src/errors/index.ts +602 -602
- package/src/errors/recovery.ts +461 -461
- package/src/errors/validation.ts +567 -567
- package/src/generated/pdw/capability.ts +319 -319
- package/src/graph/GraphService.ts +887 -887
- package/src/graph/KnowledgeGraphManager.ts +728 -728
- package/src/graph/index.ts +25 -25
- package/src/index.ts +498 -474
- package/src/infrastructure/index.ts +22 -22
- package/src/infrastructure/seal/EncryptionService.ts +628 -603
- package/src/infrastructure/seal/SealService.ts +613 -615
- package/src/infrastructure/seal/index.ts +9 -9
- package/src/infrastructure/sui/BlockchainManager.ts +627 -627
- package/src/infrastructure/sui/SuiService.ts +888 -888
- package/src/infrastructure/sui/index.ts +9 -9
- package/src/infrastructure/walrus/StorageManager.ts +604 -604
- package/src/infrastructure/walrus/WalrusStorageService.ts +612 -612
- package/src/infrastructure/walrus/index.ts +9 -9
- package/src/langchain/PDWEmbeddings.ts +145 -145
- package/src/langchain/PDWVectorStore.ts +456 -456
- package/src/langchain/createPDWRAG.ts +303 -303
- package/src/langchain/index.ts +47 -47
- package/src/permissions/ConsentRepository.browser.ts +249 -249
- package/src/permissions/ConsentRepository.ts +364 -364
- package/src/pipeline/MemoryPipeline.ts +862 -862
- package/src/pipeline/PipelineManager.ts +683 -683
- package/src/pipeline/index.ts +26 -26
- package/src/retrieval/AdvancedSearchService.ts +629 -629
- package/src/retrieval/MemoryAnalyticsService.ts +711 -711
- package/src/retrieval/MemoryDecryptionPipeline.ts +825 -824
- package/src/retrieval/MemoryRetrievalService.ts +904 -830
- package/src/retrieval/index.ts +42 -42
- package/src/services/BatchService.ts +352 -352
- package/src/services/CapabilityService.ts +464 -448
- package/src/services/ClassifierService.ts +465 -465
- package/src/services/CrossContextPermissionService.ts +486 -484
- package/src/services/EmbeddingService.ts +771 -706
- package/src/services/EncryptionService.ts +712 -711
- package/src/services/GeminiAIService.ts +753 -753
- package/src/services/IndexManager.ts +977 -1004
- package/src/services/MemoryIndexService.ts +1003 -1003
- package/src/services/MemoryService.ts +369 -369
- package/src/services/QueryService.ts +890 -890
- package/src/services/StorageService.ts +1182 -1111
- package/src/services/TransactionService.ts +838 -790
- package/src/services/VectorService.ts +462 -462
- package/src/services/ViewService.ts +484 -484
- package/src/services/index.ts +25 -25
- package/src/services/storage/BlobAttributesManager.ts +333 -333
- package/src/services/storage/KnowledgeGraphManager.ts +425 -425
- package/src/services/storage/MemorySearchManager.ts +387 -387
- package/src/services/storage/QuiltBatchManager.ts +1130 -660
- package/src/services/storage/WalrusMetadataManager.ts +268 -268
- package/src/services/storage/WalrusStorageManager.ts +287 -287
- package/src/services/storage/index.ts +57 -52
- package/src/types/index.ts +13 -13
- package/src/utils/LRUCache.ts +378 -0
- package/src/utils/index.ts +76 -68
- package/src/utils/memoryIndexOnChain.ts +507 -0
- package/src/utils/rebuildIndex.ts +290 -290
- package/src/utils/rebuildIndexNode.ts +771 -424
- package/src/vector/BrowserHnswIndexService.ts +758 -758
- package/src/vector/HnswWasmService.ts +731 -679
- package/src/vector/IHnswService.ts +233 -224
- package/src/vector/NodeHnswService.ts +833 -735
- package/src/vector/VectorManager.ts +478 -478
- package/src/vector/createHnswService.ts +135 -135
- package/src/vector/index.ts +56 -56
- package/src/wallet/ContextWalletService.ts +656 -656
- package/src/wallet/MainWalletService.ts +317 -317
|
@@ -1,493 +1,493 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MemoryProcessingCache - Specialized caching for memory processing
|
|
3
|
-
*
|
|
4
|
-
* Optimized caching service for memory data with intelligent eviction,
|
|
5
|
-
* embedding similarity, and memory-specific optimization patterns.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
Memory,
|
|
10
|
-
ProcessedMemory,
|
|
11
|
-
EmbeddingResult,
|
|
12
|
-
MemoryMetadata,
|
|
13
|
-
SimilarityResult
|
|
14
|
-
} from '../embedding/types';
|
|
15
|
-
import { BatchingService, CacheConfig } from './BatchingService';
|
|
16
|
-
|
|
17
|
-
export interface MemoryCacheConfig extends CacheConfig {
|
|
18
|
-
embeddingCacheSize?: number;
|
|
19
|
-
memoryCacheSize?: number;
|
|
20
|
-
metadataCacheSize?: number;
|
|
21
|
-
similarityThreshold?: number;
|
|
22
|
-
enableSimilarityIndex?: boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface CachedMemory extends Memory {
|
|
26
|
-
cachedAt: Date;
|
|
27
|
-
accessCount: number;
|
|
28
|
-
lastAccessed: Date;
|
|
29
|
-
embedding?: number[];
|
|
30
|
-
processingState?: 'pending' | 'processing' | 'completed' | 'failed';
|
|
31
|
-
errorInfo?: {
|
|
32
|
-
lastError: string;
|
|
33
|
-
errorCount: number;
|
|
34
|
-
lastErrorAt: Date;
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface CachedEmbedding {
|
|
39
|
-
content: string;
|
|
40
|
-
embedding: number[];
|
|
41
|
-
model: string;
|
|
42
|
-
createdAt: Date;
|
|
43
|
-
accessCount: number;
|
|
44
|
-
contentHash: string;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export interface MemoryCacheStats {
|
|
48
|
-
memories: {
|
|
49
|
-
total: number;
|
|
50
|
-
byState: Record<string, number>;
|
|
51
|
-
averageAccessCount: number;
|
|
52
|
-
};
|
|
53
|
-
embeddings: {
|
|
54
|
-
total: number;
|
|
55
|
-
uniqueContent: number;
|
|
56
|
-
averageReuseCount: number;
|
|
57
|
-
};
|
|
58
|
-
performance: {
|
|
59
|
-
hitRateMemories: number;
|
|
60
|
-
hitRateEmbeddings: number;
|
|
61
|
-
averageRetrievalTime: number;
|
|
62
|
-
};
|
|
63
|
-
similarity: {
|
|
64
|
-
indexSize: number;
|
|
65
|
-
averageSimilarityScore: number;
|
|
66
|
-
queryCount: number;
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Specialized caching service for memory processing operations
|
|
72
|
-
*/
|
|
73
|
-
export class MemoryProcessingCache {
|
|
74
|
-
private memoryCache = new Map<string, CachedMemory>();
|
|
75
|
-
private embeddingCache = new Map<string, CachedEmbedding>();
|
|
76
|
-
private metadataCache = new Map<string, MemoryMetadata>();
|
|
77
|
-
private similarityIndex = new Map<string, Set<string>>(); // Content hash -> similar memory IDs
|
|
78
|
-
private batchingService: BatchingService;
|
|
79
|
-
|
|
80
|
-
private readonly config: Required<MemoryCacheConfig>;
|
|
81
|
-
private metrics = {
|
|
82
|
-
memoryHits: 0,
|
|
83
|
-
memoryMisses: 0,
|
|
84
|
-
embeddingHits: 0,
|
|
85
|
-
embeddingMisses: 0,
|
|
86
|
-
totalQueries: 0,
|
|
87
|
-
averageRetrievalTime: 0
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
constructor(config: Partial<MemoryCacheConfig> = {}) {
|
|
91
|
-
this.config = {
|
|
92
|
-
maxSize: config.maxSize || 5000,
|
|
93
|
-
ttlMs: config.ttlMs || 60 * 60 * 1000, // 1 hour
|
|
94
|
-
cleanupIntervalMs: config.cleanupIntervalMs || 10 * 60 * 1000, // 10 minutes
|
|
95
|
-
enableMetrics: config.enableMetrics !== false,
|
|
96
|
-
embeddingCacheSize: config.embeddingCacheSize || 1000,
|
|
97
|
-
memoryCacheSize: config.memoryCacheSize || 3000,
|
|
98
|
-
metadataCacheSize: config.metadataCacheSize || 1000,
|
|
99
|
-
similarityThreshold: config.similarityThreshold || 0.85,
|
|
100
|
-
enableSimilarityIndex: config.enableSimilarityIndex !== false
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
this.batchingService = new BatchingService(
|
|
104
|
-
{
|
|
105
|
-
maxBatchSize: 50,
|
|
106
|
-
batchDelayMs: 3000,
|
|
107
|
-
maxCacheSize: this.config.maxSize
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
maxSize: this.config.maxSize,
|
|
111
|
-
ttlMs: this.config.ttlMs,
|
|
112
|
-
enableMetrics: true
|
|
113
|
-
}
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// ==================== MEMORY CACHING ====================
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Cache processed memory
|
|
121
|
-
*/
|
|
122
|
-
cacheMemory(memory: Memory, processed?: Partial<ProcessedMemory>): void {
|
|
123
|
-
const cachedMemory: CachedMemory = {
|
|
124
|
-
...memory,
|
|
125
|
-
...processed,
|
|
126
|
-
cachedAt: new Date(),
|
|
127
|
-
accessCount: 0,
|
|
128
|
-
lastAccessed: new Date(),
|
|
129
|
-
processingState: processed?.embedding ? 'completed' : 'pending'
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
// Check memory cache size
|
|
133
|
-
if (this.memoryCache.size >= this.config.memoryCacheSize) {
|
|
134
|
-
this.evictLeastAccessedMemories(Math.floor(this.config.memoryCacheSize * 0.1));
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
this.memoryCache.set(memory.id, cachedMemory);
|
|
138
|
-
|
|
139
|
-
// Update similarity index if enabled and embedding available
|
|
140
|
-
if (this.config.enableSimilarityIndex && processed?.embedding) {
|
|
141
|
-
this.updateSimilarityIndex(memory.id, memory.content, processed.embedding);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Get cached memory
|
|
147
|
-
*/
|
|
148
|
-
getCachedMemory(memoryId: string): CachedMemory | undefined {
|
|
149
|
-
const memory = this.memoryCache.get(memoryId);
|
|
150
|
-
|
|
151
|
-
if (memory) {
|
|
152
|
-
memory.lastAccessed = new Date();
|
|
153
|
-
memory.accessCount++;
|
|
154
|
-
this.metrics.memoryHits++;
|
|
155
|
-
return memory;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
this.metrics.memoryMisses++;
|
|
159
|
-
return undefined;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Update memory processing state
|
|
164
|
-
*/
|
|
165
|
-
updateMemoryState(
|
|
166
|
-
memoryId: string,
|
|
167
|
-
state: CachedMemory['processingState'],
|
|
168
|
-
error?: string
|
|
169
|
-
): void {
|
|
170
|
-
const memory = this.memoryCache.get(memoryId);
|
|
171
|
-
if (memory) {
|
|
172
|
-
memory.processingState = state;
|
|
173
|
-
memory.lastAccessed = new Date();
|
|
174
|
-
|
|
175
|
-
if (error) {
|
|
176
|
-
memory.errorInfo = {
|
|
177
|
-
lastError: error,
|
|
178
|
-
errorCount: (memory.errorInfo?.errorCount || 0) + 1,
|
|
179
|
-
lastErrorAt: new Date()
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Get memories by processing state
|
|
187
|
-
*/
|
|
188
|
-
getMemoriesByState(state: CachedMemory['processingState']): CachedMemory[] {
|
|
189
|
-
return Array.from(this.memoryCache.values())
|
|
190
|
-
.filter(memory => memory.processingState === state);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// ==================== EMBEDDING CACHING ====================
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Cache embedding result
|
|
197
|
-
*/
|
|
198
|
-
cacheEmbedding(content: string, embedding: number[], model: string): string {
|
|
199
|
-
const contentHash = this.hashContent(content);
|
|
200
|
-
|
|
201
|
-
const cachedEmbedding: CachedEmbedding = {
|
|
202
|
-
content,
|
|
203
|
-
embedding,
|
|
204
|
-
model,
|
|
205
|
-
createdAt: new Date(),
|
|
206
|
-
accessCount: 1,
|
|
207
|
-
contentHash
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
// Check embedding cache size
|
|
211
|
-
if (this.embeddingCache.size >= this.config.embeddingCacheSize) {
|
|
212
|
-
this.evictLeastUsedEmbeddings(Math.floor(this.config.embeddingCacheSize * 0.1));
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
this.embeddingCache.set(contentHash, cachedEmbedding);
|
|
216
|
-
return contentHash;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Get cached embedding
|
|
221
|
-
*/
|
|
222
|
-
getCachedEmbedding(content: string): CachedEmbedding | undefined {
|
|
223
|
-
const contentHash = this.hashContent(content);
|
|
224
|
-
const cached = this.embeddingCache.get(contentHash);
|
|
225
|
-
|
|
226
|
-
if (cached) {
|
|
227
|
-
cached.accessCount++;
|
|
228
|
-
this.metrics.embeddingHits++;
|
|
229
|
-
return cached;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
this.metrics.embeddingMisses++;
|
|
233
|
-
return undefined;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Find similar content by embedding
|
|
238
|
-
*/
|
|
239
|
-
findSimilarContent(
|
|
240
|
-
content: string,
|
|
241
|
-
threshold?: number
|
|
242
|
-
): Array<{ content: string; similarity: number; embedding: number[] }> {
|
|
243
|
-
const similarityThreshold = threshold || this.config.similarityThreshold;
|
|
244
|
-
const results: Array<{ content: string; similarity: number; embedding: number[] }> = [];
|
|
245
|
-
|
|
246
|
-
const targetEmbedding = this.getCachedEmbedding(content);
|
|
247
|
-
if (!targetEmbedding) return results;
|
|
248
|
-
|
|
249
|
-
for (const cached of this.embeddingCache.values()) {
|
|
250
|
-
if (cached.contentHash === targetEmbedding.contentHash) continue;
|
|
251
|
-
|
|
252
|
-
const similarity = this.calculateCosineSimilarity(
|
|
253
|
-
targetEmbedding.embedding,
|
|
254
|
-
cached.embedding
|
|
255
|
-
);
|
|
256
|
-
|
|
257
|
-
if (similarity >= similarityThreshold) {
|
|
258
|
-
results.push({
|
|
259
|
-
content: cached.content,
|
|
260
|
-
similarity,
|
|
261
|
-
embedding: cached.embedding
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
return results.sort((a, b) => b.similarity - a.similarity);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// ==================== METADATA CACHING ====================
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Cache memory metadata
|
|
273
|
-
*/
|
|
274
|
-
cacheMetadata(memoryId: string, metadata: MemoryMetadata): void {
|
|
275
|
-
// Check metadata cache size
|
|
276
|
-
if (this.metadataCache.size >= this.config.metadataCacheSize) {
|
|
277
|
-
this.evictRandomMetadata(Math.floor(this.config.metadataCacheSize * 0.1));
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
this.metadataCache.set(memoryId, metadata);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Get cached metadata
|
|
285
|
-
*/
|
|
286
|
-
getCachedMetadata(memoryId: string): MemoryMetadata | undefined {
|
|
287
|
-
return this.metadataCache.get(memoryId);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// ==================== BATCH PROCESSING ====================
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Add memory to processing batch
|
|
294
|
-
*/
|
|
295
|
-
addToProcessingBatch(memory: Memory, priority: 'low' | 'normal' | 'high' = 'normal'): void {
|
|
296
|
-
const priorityMap = { low: 0, normal: 1, high: 2 };
|
|
297
|
-
|
|
298
|
-
this.batchingService.addToBatch('memory-processing', {
|
|
299
|
-
id: memory.id,
|
|
300
|
-
data: memory,
|
|
301
|
-
timestamp: new Date(),
|
|
302
|
-
priority: priorityMap[priority],
|
|
303
|
-
metadata: { type: 'memory', priority }
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
// Cache as pending
|
|
307
|
-
this.cacheMemory(memory);
|
|
308
|
-
this.updateMemoryState(memory.id, 'pending');
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Process memory batch
|
|
313
|
-
*/
|
|
314
|
-
async processMemoryBatch(): Promise<void> {
|
|
315
|
-
await this.batchingService.processAllBatches();
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// ==================== SIMILARITY INDEX ====================
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Find similar memories by content
|
|
322
|
-
*/
|
|
323
|
-
findSimilarMemories(
|
|
324
|
-
memoryId: string,
|
|
325
|
-
limit: number = 10
|
|
326
|
-
): Array<{ memoryId: string; similarity: number; memory?: CachedMemory }> {
|
|
327
|
-
if (!this.config.enableSimilarityIndex) return [];
|
|
328
|
-
|
|
329
|
-
const memory = this.getCachedMemory(memoryId);
|
|
330
|
-
if (!memory?.embedding) return [];
|
|
331
|
-
|
|
332
|
-
const results: Array<{ memoryId: string; similarity: number; memory?: CachedMemory }> = [];
|
|
333
|
-
|
|
334
|
-
for (const [id, cachedMemory] of this.memoryCache.entries()) {
|
|
335
|
-
if (id === memoryId || !cachedMemory.embedding) continue;
|
|
336
|
-
|
|
337
|
-
const similarity = this.calculateCosineSimilarity(
|
|
338
|
-
memory.embedding,
|
|
339
|
-
cachedMemory.embedding
|
|
340
|
-
);
|
|
341
|
-
|
|
342
|
-
if (similarity >= this.config.similarityThreshold) {
|
|
343
|
-
results.push({ memoryId: id, similarity, memory: cachedMemory });
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
return results
|
|
348
|
-
.sort((a, b) => b.similarity - a.similarity)
|
|
349
|
-
.slice(0, limit);
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// ==================== STATISTICS & MONITORING ====================
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* Get comprehensive cache statistics
|
|
356
|
-
*/
|
|
357
|
-
getStats(): MemoryCacheStats {
|
|
358
|
-
const memories = Array.from(this.memoryCache.values());
|
|
359
|
-
const embeddings = Array.from(this.embeddingCache.values());
|
|
360
|
-
|
|
361
|
-
// Group memories by state
|
|
362
|
-
const stateGroups = memories.reduce((groups, memory) => {
|
|
363
|
-
const state = memory.processingState || 'unknown';
|
|
364
|
-
groups[state] = (groups[state] || 0) + 1;
|
|
365
|
-
return groups;
|
|
366
|
-
}, {} as Record<string, number>);
|
|
367
|
-
|
|
368
|
-
return {
|
|
369
|
-
memories: {
|
|
370
|
-
total: memories.length,
|
|
371
|
-
byState: stateGroups,
|
|
372
|
-
averageAccessCount: memories.length > 0
|
|
373
|
-
? memories.reduce((sum, m) => sum + m.accessCount, 0) / memories.length
|
|
374
|
-
: 0
|
|
375
|
-
},
|
|
376
|
-
embeddings: {
|
|
377
|
-
total: embeddings.length,
|
|
378
|
-
uniqueContent: new Set(embeddings.map(e => e.contentHash)).size,
|
|
379
|
-
averageReuseCount: embeddings.length > 0
|
|
380
|
-
? embeddings.reduce((sum, e) => sum + e.accessCount, 0) / embeddings.length
|
|
381
|
-
: 0
|
|
382
|
-
},
|
|
383
|
-
performance: {
|
|
384
|
-
hitRateMemories: this.getHitRate(this.metrics.memoryHits, this.metrics.memoryMisses),
|
|
385
|
-
hitRateEmbeddings: this.getHitRate(this.metrics.embeddingHits, this.metrics.embeddingMisses),
|
|
386
|
-
averageRetrievalTime: this.metrics.averageRetrievalTime
|
|
387
|
-
},
|
|
388
|
-
similarity: {
|
|
389
|
-
indexSize: this.similarityIndex.size,
|
|
390
|
-
averageSimilarityScore: 0, // TODO: Calculate from recent queries
|
|
391
|
-
queryCount: this.metrics.totalQueries
|
|
392
|
-
}
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* Clear all caches
|
|
398
|
-
*/
|
|
399
|
-
clearAll(): void {
|
|
400
|
-
this.memoryCache.clear();
|
|
401
|
-
this.embeddingCache.clear();
|
|
402
|
-
this.metadataCache.clear();
|
|
403
|
-
this.similarityIndex.clear();
|
|
404
|
-
|
|
405
|
-
// Reset metrics
|
|
406
|
-
Object.keys(this.metrics).forEach(key => {
|
|
407
|
-
(this.metrics as any)[key] = 0;
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
/**
|
|
412
|
-
* Cleanup and destroy cache
|
|
413
|
-
*/
|
|
414
|
-
destroy(): void {
|
|
415
|
-
this.clearAll();
|
|
416
|
-
this.batchingService.destroy();
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// ==================== PRIVATE METHODS ====================
|
|
420
|
-
|
|
421
|
-
private updateSimilarityIndex(memoryId: string, content: string, embedding: number[]): void {
|
|
422
|
-
const contentHash = this.hashContent(content);
|
|
423
|
-
|
|
424
|
-
if (!this.similarityIndex.has(contentHash)) {
|
|
425
|
-
this.similarityIndex.set(contentHash, new Set());
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
this.similarityIndex.get(contentHash)!.add(memoryId);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
private evictLeastAccessedMemories(count: number): void {
|
|
432
|
-
const memories = Array.from(this.memoryCache.entries())
|
|
433
|
-
.sort(([, a], [, b]) => a.accessCount - b.accessCount)
|
|
434
|
-
.slice(0, count);
|
|
435
|
-
|
|
436
|
-
for (const [id] of memories) {
|
|
437
|
-
this.memoryCache.delete(id);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
private evictLeastUsedEmbeddings(count: number): void {
|
|
442
|
-
const embeddings = Array.from(this.embeddingCache.entries())
|
|
443
|
-
.sort(([, a], [, b]) => a.accessCount - b.accessCount)
|
|
444
|
-
.slice(0, count);
|
|
445
|
-
|
|
446
|
-
for (const [hash] of embeddings) {
|
|
447
|
-
this.embeddingCache.delete(hash);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
private evictRandomMetadata(count: number): void {
|
|
452
|
-
const keys = Array.from(this.metadataCache.keys()).slice(0, count);
|
|
453
|
-
for (const key of keys) {
|
|
454
|
-
this.metadataCache.delete(key);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
private hashContent(content: string): string {
|
|
459
|
-
// Simple hash function - replace with crypto hash if needed
|
|
460
|
-
let hash = 0;
|
|
461
|
-
for (let i = 0; i < content.length; i++) {
|
|
462
|
-
const char = content.charCodeAt(i);
|
|
463
|
-
hash = ((hash << 5) - hash) + char;
|
|
464
|
-
hash = hash & hash; // Convert to 32bit integer
|
|
465
|
-
}
|
|
466
|
-
return hash.toString(36);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
private calculateCosineSimilarity(vecA: number[], vecB: number[]): number {
|
|
470
|
-
if (vecA.length !== vecB.length) return 0;
|
|
471
|
-
|
|
472
|
-
let dotProduct = 0;
|
|
473
|
-
let normA = 0;
|
|
474
|
-
let normB = 0;
|
|
475
|
-
|
|
476
|
-
for (let i = 0; i < vecA.length; i++) {
|
|
477
|
-
dotProduct += vecA[i] * vecB[i];
|
|
478
|
-
normA += vecA[i] * vecA[i];
|
|
479
|
-
normB += vecB[i] * vecB[i];
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
if (normA === 0 || normB === 0) return 0;
|
|
483
|
-
|
|
484
|
-
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
private getHitRate(hits: number, misses: number): number {
|
|
488
|
-
const total = hits + misses;
|
|
489
|
-
return total > 0 ? hits / total : 0;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
|
|
1
|
+
/**
|
|
2
|
+
* MemoryProcessingCache - Specialized caching for memory processing
|
|
3
|
+
*
|
|
4
|
+
* Optimized caching service for memory data with intelligent eviction,
|
|
5
|
+
* embedding similarity, and memory-specific optimization patterns.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
Memory,
|
|
10
|
+
ProcessedMemory,
|
|
11
|
+
EmbeddingResult,
|
|
12
|
+
MemoryMetadata,
|
|
13
|
+
SimilarityResult
|
|
14
|
+
} from '../embedding/types';
|
|
15
|
+
import { BatchingService, CacheConfig } from './BatchingService';
|
|
16
|
+
|
|
17
|
+
export interface MemoryCacheConfig extends CacheConfig {
|
|
18
|
+
embeddingCacheSize?: number;
|
|
19
|
+
memoryCacheSize?: number;
|
|
20
|
+
metadataCacheSize?: number;
|
|
21
|
+
similarityThreshold?: number;
|
|
22
|
+
enableSimilarityIndex?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface CachedMemory extends Memory {
|
|
26
|
+
cachedAt: Date;
|
|
27
|
+
accessCount: number;
|
|
28
|
+
lastAccessed: Date;
|
|
29
|
+
embedding?: number[];
|
|
30
|
+
processingState?: 'pending' | 'processing' | 'completed' | 'failed';
|
|
31
|
+
errorInfo?: {
|
|
32
|
+
lastError: string;
|
|
33
|
+
errorCount: number;
|
|
34
|
+
lastErrorAt: Date;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface CachedEmbedding {
|
|
39
|
+
content: string;
|
|
40
|
+
embedding: number[];
|
|
41
|
+
model: string;
|
|
42
|
+
createdAt: Date;
|
|
43
|
+
accessCount: number;
|
|
44
|
+
contentHash: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface MemoryCacheStats {
|
|
48
|
+
memories: {
|
|
49
|
+
total: number;
|
|
50
|
+
byState: Record<string, number>;
|
|
51
|
+
averageAccessCount: number;
|
|
52
|
+
};
|
|
53
|
+
embeddings: {
|
|
54
|
+
total: number;
|
|
55
|
+
uniqueContent: number;
|
|
56
|
+
averageReuseCount: number;
|
|
57
|
+
};
|
|
58
|
+
performance: {
|
|
59
|
+
hitRateMemories: number;
|
|
60
|
+
hitRateEmbeddings: number;
|
|
61
|
+
averageRetrievalTime: number;
|
|
62
|
+
};
|
|
63
|
+
similarity: {
|
|
64
|
+
indexSize: number;
|
|
65
|
+
averageSimilarityScore: number;
|
|
66
|
+
queryCount: number;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Specialized caching service for memory processing operations
|
|
72
|
+
*/
|
|
73
|
+
export class MemoryProcessingCache {
|
|
74
|
+
private memoryCache = new Map<string, CachedMemory>();
|
|
75
|
+
private embeddingCache = new Map<string, CachedEmbedding>();
|
|
76
|
+
private metadataCache = new Map<string, MemoryMetadata>();
|
|
77
|
+
private similarityIndex = new Map<string, Set<string>>(); // Content hash -> similar memory IDs
|
|
78
|
+
private batchingService: BatchingService;
|
|
79
|
+
|
|
80
|
+
private readonly config: Required<MemoryCacheConfig>;
|
|
81
|
+
private metrics = {
|
|
82
|
+
memoryHits: 0,
|
|
83
|
+
memoryMisses: 0,
|
|
84
|
+
embeddingHits: 0,
|
|
85
|
+
embeddingMisses: 0,
|
|
86
|
+
totalQueries: 0,
|
|
87
|
+
averageRetrievalTime: 0
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
constructor(config: Partial<MemoryCacheConfig> = {}) {
|
|
91
|
+
this.config = {
|
|
92
|
+
maxSize: config.maxSize || 5000,
|
|
93
|
+
ttlMs: config.ttlMs || 60 * 60 * 1000, // 1 hour
|
|
94
|
+
cleanupIntervalMs: config.cleanupIntervalMs || 10 * 60 * 1000, // 10 minutes
|
|
95
|
+
enableMetrics: config.enableMetrics !== false,
|
|
96
|
+
embeddingCacheSize: config.embeddingCacheSize || 1000,
|
|
97
|
+
memoryCacheSize: config.memoryCacheSize || 3000,
|
|
98
|
+
metadataCacheSize: config.metadataCacheSize || 1000,
|
|
99
|
+
similarityThreshold: config.similarityThreshold || 0.85,
|
|
100
|
+
enableSimilarityIndex: config.enableSimilarityIndex !== false
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
this.batchingService = new BatchingService(
|
|
104
|
+
{
|
|
105
|
+
maxBatchSize: 50,
|
|
106
|
+
batchDelayMs: 3000,
|
|
107
|
+
maxCacheSize: this.config.maxSize
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
maxSize: this.config.maxSize,
|
|
111
|
+
ttlMs: this.config.ttlMs,
|
|
112
|
+
enableMetrics: true
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ==================== MEMORY CACHING ====================
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Cache processed memory
|
|
121
|
+
*/
|
|
122
|
+
cacheMemory(memory: Memory, processed?: Partial<ProcessedMemory>): void {
|
|
123
|
+
const cachedMemory: CachedMemory = {
|
|
124
|
+
...memory,
|
|
125
|
+
...processed,
|
|
126
|
+
cachedAt: new Date(),
|
|
127
|
+
accessCount: 0,
|
|
128
|
+
lastAccessed: new Date(),
|
|
129
|
+
processingState: processed?.embedding ? 'completed' : 'pending'
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// Check memory cache size
|
|
133
|
+
if (this.memoryCache.size >= this.config.memoryCacheSize) {
|
|
134
|
+
this.evictLeastAccessedMemories(Math.floor(this.config.memoryCacheSize * 0.1));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
this.memoryCache.set(memory.id, cachedMemory);
|
|
138
|
+
|
|
139
|
+
// Update similarity index if enabled and embedding available
|
|
140
|
+
if (this.config.enableSimilarityIndex && processed?.embedding) {
|
|
141
|
+
this.updateSimilarityIndex(memory.id, memory.content, processed.embedding);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Get cached memory
|
|
147
|
+
*/
|
|
148
|
+
getCachedMemory(memoryId: string): CachedMemory | undefined {
|
|
149
|
+
const memory = this.memoryCache.get(memoryId);
|
|
150
|
+
|
|
151
|
+
if (memory) {
|
|
152
|
+
memory.lastAccessed = new Date();
|
|
153
|
+
memory.accessCount++;
|
|
154
|
+
this.metrics.memoryHits++;
|
|
155
|
+
return memory;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
this.metrics.memoryMisses++;
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Update memory processing state
|
|
164
|
+
*/
|
|
165
|
+
updateMemoryState(
|
|
166
|
+
memoryId: string,
|
|
167
|
+
state: CachedMemory['processingState'],
|
|
168
|
+
error?: string
|
|
169
|
+
): void {
|
|
170
|
+
const memory = this.memoryCache.get(memoryId);
|
|
171
|
+
if (memory) {
|
|
172
|
+
memory.processingState = state;
|
|
173
|
+
memory.lastAccessed = new Date();
|
|
174
|
+
|
|
175
|
+
if (error) {
|
|
176
|
+
memory.errorInfo = {
|
|
177
|
+
lastError: error,
|
|
178
|
+
errorCount: (memory.errorInfo?.errorCount || 0) + 1,
|
|
179
|
+
lastErrorAt: new Date()
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Get memories by processing state
|
|
187
|
+
*/
|
|
188
|
+
getMemoriesByState(state: CachedMemory['processingState']): CachedMemory[] {
|
|
189
|
+
return Array.from(this.memoryCache.values())
|
|
190
|
+
.filter(memory => memory.processingState === state);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ==================== EMBEDDING CACHING ====================
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Cache embedding result
|
|
197
|
+
*/
|
|
198
|
+
cacheEmbedding(content: string, embedding: number[], model: string): string {
|
|
199
|
+
const contentHash = this.hashContent(content);
|
|
200
|
+
|
|
201
|
+
const cachedEmbedding: CachedEmbedding = {
|
|
202
|
+
content,
|
|
203
|
+
embedding,
|
|
204
|
+
model,
|
|
205
|
+
createdAt: new Date(),
|
|
206
|
+
accessCount: 1,
|
|
207
|
+
contentHash
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
// Check embedding cache size
|
|
211
|
+
if (this.embeddingCache.size >= this.config.embeddingCacheSize) {
|
|
212
|
+
this.evictLeastUsedEmbeddings(Math.floor(this.config.embeddingCacheSize * 0.1));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
this.embeddingCache.set(contentHash, cachedEmbedding);
|
|
216
|
+
return contentHash;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Get cached embedding
|
|
221
|
+
*/
|
|
222
|
+
getCachedEmbedding(content: string): CachedEmbedding | undefined {
|
|
223
|
+
const contentHash = this.hashContent(content);
|
|
224
|
+
const cached = this.embeddingCache.get(contentHash);
|
|
225
|
+
|
|
226
|
+
if (cached) {
|
|
227
|
+
cached.accessCount++;
|
|
228
|
+
this.metrics.embeddingHits++;
|
|
229
|
+
return cached;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
this.metrics.embeddingMisses++;
|
|
233
|
+
return undefined;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Find similar content by embedding
|
|
238
|
+
*/
|
|
239
|
+
findSimilarContent(
|
|
240
|
+
content: string,
|
|
241
|
+
threshold?: number
|
|
242
|
+
): Array<{ content: string; similarity: number; embedding: number[] }> {
|
|
243
|
+
const similarityThreshold = threshold || this.config.similarityThreshold;
|
|
244
|
+
const results: Array<{ content: string; similarity: number; embedding: number[] }> = [];
|
|
245
|
+
|
|
246
|
+
const targetEmbedding = this.getCachedEmbedding(content);
|
|
247
|
+
if (!targetEmbedding) return results;
|
|
248
|
+
|
|
249
|
+
for (const cached of this.embeddingCache.values()) {
|
|
250
|
+
if (cached.contentHash === targetEmbedding.contentHash) continue;
|
|
251
|
+
|
|
252
|
+
const similarity = this.calculateCosineSimilarity(
|
|
253
|
+
targetEmbedding.embedding,
|
|
254
|
+
cached.embedding
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
if (similarity >= similarityThreshold) {
|
|
258
|
+
results.push({
|
|
259
|
+
content: cached.content,
|
|
260
|
+
similarity,
|
|
261
|
+
embedding: cached.embedding
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return results.sort((a, b) => b.similarity - a.similarity);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// ==================== METADATA CACHING ====================
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Cache memory metadata
|
|
273
|
+
*/
|
|
274
|
+
cacheMetadata(memoryId: string, metadata: MemoryMetadata): void {
|
|
275
|
+
// Check metadata cache size
|
|
276
|
+
if (this.metadataCache.size >= this.config.metadataCacheSize) {
|
|
277
|
+
this.evictRandomMetadata(Math.floor(this.config.metadataCacheSize * 0.1));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
this.metadataCache.set(memoryId, metadata);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Get cached metadata
|
|
285
|
+
*/
|
|
286
|
+
getCachedMetadata(memoryId: string): MemoryMetadata | undefined {
|
|
287
|
+
return this.metadataCache.get(memoryId);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// ==================== BATCH PROCESSING ====================
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Add memory to processing batch
|
|
294
|
+
*/
|
|
295
|
+
addToProcessingBatch(memory: Memory, priority: 'low' | 'normal' | 'high' = 'normal'): void {
|
|
296
|
+
const priorityMap = { low: 0, normal: 1, high: 2 };
|
|
297
|
+
|
|
298
|
+
this.batchingService.addToBatch('memory-processing', {
|
|
299
|
+
id: memory.id,
|
|
300
|
+
data: memory,
|
|
301
|
+
timestamp: new Date(),
|
|
302
|
+
priority: priorityMap[priority],
|
|
303
|
+
metadata: { type: 'memory', priority }
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// Cache as pending
|
|
307
|
+
this.cacheMemory(memory);
|
|
308
|
+
this.updateMemoryState(memory.id, 'pending');
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Process memory batch
|
|
313
|
+
*/
|
|
314
|
+
async processMemoryBatch(): Promise<void> {
|
|
315
|
+
await this.batchingService.processAllBatches();
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// ==================== SIMILARITY INDEX ====================
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Find similar memories by content
|
|
322
|
+
*/
|
|
323
|
+
findSimilarMemories(
|
|
324
|
+
memoryId: string,
|
|
325
|
+
limit: number = 10
|
|
326
|
+
): Array<{ memoryId: string; similarity: number; memory?: CachedMemory }> {
|
|
327
|
+
if (!this.config.enableSimilarityIndex) return [];
|
|
328
|
+
|
|
329
|
+
const memory = this.getCachedMemory(memoryId);
|
|
330
|
+
if (!memory?.embedding) return [];
|
|
331
|
+
|
|
332
|
+
const results: Array<{ memoryId: string; similarity: number; memory?: CachedMemory }> = [];
|
|
333
|
+
|
|
334
|
+
for (const [id, cachedMemory] of this.memoryCache.entries()) {
|
|
335
|
+
if (id === memoryId || !cachedMemory.embedding) continue;
|
|
336
|
+
|
|
337
|
+
const similarity = this.calculateCosineSimilarity(
|
|
338
|
+
memory.embedding,
|
|
339
|
+
cachedMemory.embedding
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
if (similarity >= this.config.similarityThreshold) {
|
|
343
|
+
results.push({ memoryId: id, similarity, memory: cachedMemory });
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return results
|
|
348
|
+
.sort((a, b) => b.similarity - a.similarity)
|
|
349
|
+
.slice(0, limit);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// ==================== STATISTICS & MONITORING ====================
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Get comprehensive cache statistics
|
|
356
|
+
*/
|
|
357
|
+
getStats(): MemoryCacheStats {
|
|
358
|
+
const memories = Array.from(this.memoryCache.values());
|
|
359
|
+
const embeddings = Array.from(this.embeddingCache.values());
|
|
360
|
+
|
|
361
|
+
// Group memories by state
|
|
362
|
+
const stateGroups = memories.reduce((groups, memory) => {
|
|
363
|
+
const state = memory.processingState || 'unknown';
|
|
364
|
+
groups[state] = (groups[state] || 0) + 1;
|
|
365
|
+
return groups;
|
|
366
|
+
}, {} as Record<string, number>);
|
|
367
|
+
|
|
368
|
+
return {
|
|
369
|
+
memories: {
|
|
370
|
+
total: memories.length,
|
|
371
|
+
byState: stateGroups,
|
|
372
|
+
averageAccessCount: memories.length > 0
|
|
373
|
+
? memories.reduce((sum, m) => sum + m.accessCount, 0) / memories.length
|
|
374
|
+
: 0
|
|
375
|
+
},
|
|
376
|
+
embeddings: {
|
|
377
|
+
total: embeddings.length,
|
|
378
|
+
uniqueContent: new Set(embeddings.map(e => e.contentHash)).size,
|
|
379
|
+
averageReuseCount: embeddings.length > 0
|
|
380
|
+
? embeddings.reduce((sum, e) => sum + e.accessCount, 0) / embeddings.length
|
|
381
|
+
: 0
|
|
382
|
+
},
|
|
383
|
+
performance: {
|
|
384
|
+
hitRateMemories: this.getHitRate(this.metrics.memoryHits, this.metrics.memoryMisses),
|
|
385
|
+
hitRateEmbeddings: this.getHitRate(this.metrics.embeddingHits, this.metrics.embeddingMisses),
|
|
386
|
+
averageRetrievalTime: this.metrics.averageRetrievalTime
|
|
387
|
+
},
|
|
388
|
+
similarity: {
|
|
389
|
+
indexSize: this.similarityIndex.size,
|
|
390
|
+
averageSimilarityScore: 0, // TODO: Calculate from recent queries
|
|
391
|
+
queryCount: this.metrics.totalQueries
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Clear all caches
|
|
398
|
+
*/
|
|
399
|
+
clearAll(): void {
|
|
400
|
+
this.memoryCache.clear();
|
|
401
|
+
this.embeddingCache.clear();
|
|
402
|
+
this.metadataCache.clear();
|
|
403
|
+
this.similarityIndex.clear();
|
|
404
|
+
|
|
405
|
+
// Reset metrics
|
|
406
|
+
Object.keys(this.metrics).forEach(key => {
|
|
407
|
+
(this.metrics as any)[key] = 0;
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Cleanup and destroy cache
|
|
413
|
+
*/
|
|
414
|
+
destroy(): void {
|
|
415
|
+
this.clearAll();
|
|
416
|
+
this.batchingService.destroy();
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// ==================== PRIVATE METHODS ====================
|
|
420
|
+
|
|
421
|
+
private updateSimilarityIndex(memoryId: string, content: string, embedding: number[]): void {
|
|
422
|
+
const contentHash = this.hashContent(content);
|
|
423
|
+
|
|
424
|
+
if (!this.similarityIndex.has(contentHash)) {
|
|
425
|
+
this.similarityIndex.set(contentHash, new Set());
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
this.similarityIndex.get(contentHash)!.add(memoryId);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
private evictLeastAccessedMemories(count: number): void {
|
|
432
|
+
const memories = Array.from(this.memoryCache.entries())
|
|
433
|
+
.sort(([, a], [, b]) => a.accessCount - b.accessCount)
|
|
434
|
+
.slice(0, count);
|
|
435
|
+
|
|
436
|
+
for (const [id] of memories) {
|
|
437
|
+
this.memoryCache.delete(id);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
private evictLeastUsedEmbeddings(count: number): void {
|
|
442
|
+
const embeddings = Array.from(this.embeddingCache.entries())
|
|
443
|
+
.sort(([, a], [, b]) => a.accessCount - b.accessCount)
|
|
444
|
+
.slice(0, count);
|
|
445
|
+
|
|
446
|
+
for (const [hash] of embeddings) {
|
|
447
|
+
this.embeddingCache.delete(hash);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
private evictRandomMetadata(count: number): void {
|
|
452
|
+
const keys = Array.from(this.metadataCache.keys()).slice(0, count);
|
|
453
|
+
for (const key of keys) {
|
|
454
|
+
this.metadataCache.delete(key);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
private hashContent(content: string): string {
|
|
459
|
+
// Simple hash function - replace with crypto hash if needed
|
|
460
|
+
let hash = 0;
|
|
461
|
+
for (let i = 0; i < content.length; i++) {
|
|
462
|
+
const char = content.charCodeAt(i);
|
|
463
|
+
hash = ((hash << 5) - hash) + char;
|
|
464
|
+
hash = hash & hash; // Convert to 32bit integer
|
|
465
|
+
}
|
|
466
|
+
return hash.toString(36);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
private calculateCosineSimilarity(vecA: number[], vecB: number[]): number {
|
|
470
|
+
if (vecA.length !== vecB.length) return 0;
|
|
471
|
+
|
|
472
|
+
let dotProduct = 0;
|
|
473
|
+
let normA = 0;
|
|
474
|
+
let normB = 0;
|
|
475
|
+
|
|
476
|
+
for (let i = 0; i < vecA.length; i++) {
|
|
477
|
+
dotProduct += vecA[i] * vecB[i];
|
|
478
|
+
normA += vecA[i] * vecA[i];
|
|
479
|
+
normB += vecB[i] * vecB[i];
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (normA === 0 || normB === 0) return 0;
|
|
483
|
+
|
|
484
|
+
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
private getHitRate(hits: number, misses: number): number {
|
|
488
|
+
const total = hits + misses;
|
|
489
|
+
return total > 0 ? hits / total : 0;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
493
|
export default MemoryProcessingCache;
|