@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,387 +1,387 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MemorySearchManager - Memory Indexing and Search Operations
|
|
3
|
-
*
|
|
4
|
-
* Handles HNSW vector indexing and semantic search for memories.
|
|
5
|
-
* Extracted from StorageService for better separation of concerns.
|
|
6
|
-
*
|
|
7
|
-
* Features:
|
|
8
|
-
* - Automatic memory indexing with embeddings
|
|
9
|
-
* - Semantic search via HNSW
|
|
10
|
-
* - Metadata-based filtering
|
|
11
|
-
* - Category and temporal search
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import type { MemoryIndexService, MemorySearchQuery } from '../MemoryIndexService';
|
|
15
|
-
import type { EmbeddingService } from '../EmbeddingService';
|
|
16
|
-
|
|
17
|
-
export interface MemoryMetadata {
|
|
18
|
-
contentType: string;
|
|
19
|
-
contentSize: number;
|
|
20
|
-
contentHash: string;
|
|
21
|
-
category: string;
|
|
22
|
-
topic: string;
|
|
23
|
-
importance: number;
|
|
24
|
-
embeddingBlobId?: string;
|
|
25
|
-
embeddingDimension: number;
|
|
26
|
-
createdTimestamp: number;
|
|
27
|
-
updatedTimestamp?: number;
|
|
28
|
-
customMetadata?: Record<string, string>;
|
|
29
|
-
isEncrypted?: boolean;
|
|
30
|
-
encryptionType?: string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface MetadataSearchQuery {
|
|
34
|
-
query?: string;
|
|
35
|
-
vector?: number[];
|
|
36
|
-
filters?: {
|
|
37
|
-
category?: string | string[];
|
|
38
|
-
topic?: string | string[];
|
|
39
|
-
importance?: { min?: number; max?: number };
|
|
40
|
-
contentType?: string | string[];
|
|
41
|
-
dateRange?: { start?: Date; end?: Date };
|
|
42
|
-
tags?: string[];
|
|
43
|
-
contentSize?: { min?: number; max?: number };
|
|
44
|
-
};
|
|
45
|
-
k?: number;
|
|
46
|
-
threshold?: number;
|
|
47
|
-
includeContent?: boolean;
|
|
48
|
-
useCache?: boolean;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface MetadataSearchResult {
|
|
52
|
-
blobId: string;
|
|
53
|
-
content?: string | Uint8Array;
|
|
54
|
-
metadata: MemoryMetadata;
|
|
55
|
-
similarity: number;
|
|
56
|
-
relevanceScore: number;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export interface IndexingResult {
|
|
60
|
-
vectorId: number;
|
|
61
|
-
blobId: string;
|
|
62
|
-
memoryId: string;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* MemorySearchManager - Manages memory indexing and semantic search
|
|
67
|
-
*
|
|
68
|
-
* Coordinates between:
|
|
69
|
-
* - EmbeddingService for vector generation
|
|
70
|
-
* - MemoryIndexService for HNSW indexing
|
|
71
|
-
* - Metadata filtering and relevance scoring
|
|
72
|
-
*/
|
|
73
|
-
export class MemorySearchManager {
|
|
74
|
-
private memoryIndexService?: MemoryIndexService;
|
|
75
|
-
private embeddingService?: EmbeddingService;
|
|
76
|
-
|
|
77
|
-
constructor() {
|
|
78
|
-
// Services will be initialized via initializeSearch()
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Initialize search capabilities
|
|
83
|
-
*/
|
|
84
|
-
initializeSearch(
|
|
85
|
-
embeddingService: EmbeddingService,
|
|
86
|
-
memoryIndexService?: MemoryIndexService
|
|
87
|
-
) {
|
|
88
|
-
this.embeddingService = embeddingService;
|
|
89
|
-
this.memoryIndexService = memoryIndexService;
|
|
90
|
-
|
|
91
|
-
if (this.memoryIndexService) {
|
|
92
|
-
this.memoryIndexService.initialize(embeddingService, undefined as any);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
console.log('✅ MemorySearchManager: Search capabilities initialized');
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Index a memory for semantic search
|
|
100
|
-
*
|
|
101
|
-
* @param userAddress - Owner address
|
|
102
|
-
* @param memoryId - Unique memory identifier
|
|
103
|
-
* @param blobId - Walrus blob ID
|
|
104
|
-
* @param textContent - Content for embedding generation
|
|
105
|
-
* @param metadata - Memory metadata
|
|
106
|
-
* @returns Indexing result with vector ID
|
|
107
|
-
*/
|
|
108
|
-
async indexMemory(
|
|
109
|
-
userAddress: string,
|
|
110
|
-
memoryId: string,
|
|
111
|
-
blobId: string,
|
|
112
|
-
textContent: string,
|
|
113
|
-
metadata: MemoryMetadata
|
|
114
|
-
): Promise<IndexingResult> {
|
|
115
|
-
if (!this.embeddingService || !this.memoryIndexService) {
|
|
116
|
-
throw new Error('Search capabilities not initialized. Call initializeSearch() first.');
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Option A+: Pass isEncrypted flag to control content storage in index
|
|
120
|
-
// When encrypted, content is NOT stored locally (security consideration)
|
|
121
|
-
const indexResult = await this.memoryIndexService.indexMemory(
|
|
122
|
-
userAddress,
|
|
123
|
-
memoryId,
|
|
124
|
-
blobId,
|
|
125
|
-
textContent,
|
|
126
|
-
metadata,
|
|
127
|
-
undefined, // embedding - let MemoryIndexService generate it
|
|
128
|
-
{ isEncrypted: metadata.isEncrypted ?? false }
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
console.log(`✅ Indexed memory ${memoryId} → vector ${indexResult.vectorId}`);
|
|
132
|
-
|
|
133
|
-
return {
|
|
134
|
-
vectorId: indexResult.vectorId,
|
|
135
|
-
blobId,
|
|
136
|
-
memoryId
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Search memories by metadata with semantic understanding
|
|
142
|
-
*
|
|
143
|
-
* @param userAddress - Owner address
|
|
144
|
-
* @param searchQuery - Search query with filters
|
|
145
|
-
* @returns Array of matching memories with relevance scores
|
|
146
|
-
*/
|
|
147
|
-
async searchByMetadata(
|
|
148
|
-
userAddress: string,
|
|
149
|
-
searchQuery: MetadataSearchQuery
|
|
150
|
-
): Promise<MetadataSearchResult[]> {
|
|
151
|
-
if (!this.embeddingService || !this.memoryIndexService) {
|
|
152
|
-
throw new Error('Search capabilities not initialized. Call initializeSearch() first.');
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
try {
|
|
156
|
-
console.log(`🔍 Searching memories for user ${userAddress}`);
|
|
157
|
-
|
|
158
|
-
// Convert to MemoryIndexService query format
|
|
159
|
-
const memoryQuery: MemorySearchQuery = {
|
|
160
|
-
query: searchQuery.query,
|
|
161
|
-
vector: searchQuery.vector,
|
|
162
|
-
userAddress,
|
|
163
|
-
k: searchQuery.k || 10,
|
|
164
|
-
threshold: searchQuery.threshold,
|
|
165
|
-
categories: searchQuery.filters?.category
|
|
166
|
-
? (Array.isArray(searchQuery.filters.category)
|
|
167
|
-
? searchQuery.filters.category
|
|
168
|
-
: [searchQuery.filters.category])
|
|
169
|
-
: undefined,
|
|
170
|
-
dateRange: searchQuery.filters?.dateRange,
|
|
171
|
-
importanceRange: searchQuery.filters?.importance,
|
|
172
|
-
tags: searchQuery.filters?.tags,
|
|
173
|
-
includeContent: searchQuery.includeContent
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
const results = await this.memoryIndexService.searchMemories(memoryQuery);
|
|
177
|
-
|
|
178
|
-
// Convert to MetadataSearchResult format
|
|
179
|
-
const metadataResults: MetadataSearchResult[] = results.map(result => ({
|
|
180
|
-
blobId: result.blobId,
|
|
181
|
-
content: result.content,
|
|
182
|
-
metadata: result.metadata,
|
|
183
|
-
similarity: result.similarity,
|
|
184
|
-
relevanceScore: result.relevanceScore
|
|
185
|
-
}));
|
|
186
|
-
|
|
187
|
-
console.log(`✅ Found ${metadataResults.length} matching memories`);
|
|
188
|
-
return metadataResults;
|
|
189
|
-
|
|
190
|
-
} catch (error) {
|
|
191
|
-
console.error('❌ Metadata search failed:', error);
|
|
192
|
-
throw error;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Get all indexed memories for a user with optional filtering
|
|
198
|
-
*/
|
|
199
|
-
async getUserMemoriesWithMetadata(
|
|
200
|
-
userAddress: string,
|
|
201
|
-
filters?: MetadataSearchQuery['filters']
|
|
202
|
-
): Promise<MetadataSearchResult[]> {
|
|
203
|
-
if (!this.memoryIndexService) {
|
|
204
|
-
throw new Error('Memory indexing not initialized. Call initializeSearch() first.');
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Convert filters to MemoryIndexService format
|
|
208
|
-
const indexFilters = filters ? {
|
|
209
|
-
categories: filters.category
|
|
210
|
-
? (Array.isArray(filters.category) ? filters.category : [filters.category])
|
|
211
|
-
: undefined,
|
|
212
|
-
dateRange: filters.dateRange,
|
|
213
|
-
importanceRange: filters.importance
|
|
214
|
-
} : undefined;
|
|
215
|
-
|
|
216
|
-
const memories = await this.memoryIndexService.getUserMemories(userAddress, indexFilters);
|
|
217
|
-
|
|
218
|
-
// Convert to MetadataSearchResult format
|
|
219
|
-
return memories.map(memory => ({
|
|
220
|
-
blobId: memory.blobId,
|
|
221
|
-
metadata: memory.metadata,
|
|
222
|
-
similarity: memory.similarity,
|
|
223
|
-
relevanceScore: memory.relevanceScore
|
|
224
|
-
}));
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Search by category with additional filtering
|
|
229
|
-
*/
|
|
230
|
-
async searchByCategory(
|
|
231
|
-
userAddress: string,
|
|
232
|
-
category: string,
|
|
233
|
-
additionalFilters?: Omit<MetadataSearchQuery['filters'], 'category'>
|
|
234
|
-
): Promise<MetadataSearchResult[]> {
|
|
235
|
-
return this.searchByMetadata(userAddress, {
|
|
236
|
-
filters: {
|
|
237
|
-
category,
|
|
238
|
-
...additionalFilters
|
|
239
|
-
},
|
|
240
|
-
k: 50,
|
|
241
|
-
includeContent: false
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Search memories within time range
|
|
247
|
-
*/
|
|
248
|
-
async searchByTimeRange(
|
|
249
|
-
userAddress: string,
|
|
250
|
-
startDate: Date,
|
|
251
|
-
endDate: Date,
|
|
252
|
-
additionalFilters?: Omit<MetadataSearchQuery['filters'], 'dateRange'>
|
|
253
|
-
): Promise<MetadataSearchResult[]> {
|
|
254
|
-
return this.searchByMetadata(userAddress, {
|
|
255
|
-
filters: {
|
|
256
|
-
dateRange: { start: startDate, end: endDate },
|
|
257
|
-
...additionalFilters
|
|
258
|
-
},
|
|
259
|
-
k: 100,
|
|
260
|
-
includeContent: false
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Get search analytics and statistics
|
|
266
|
-
*/
|
|
267
|
-
getSearchAnalytics(userAddress: string): {
|
|
268
|
-
totalMemories: number;
|
|
269
|
-
categoryCounts: Record<string, number>;
|
|
270
|
-
averageImportance: number;
|
|
271
|
-
timeRange: { earliest: Date; latest: Date } | null;
|
|
272
|
-
topTags: Array<{ tag: string; count: number }>;
|
|
273
|
-
} {
|
|
274
|
-
if (!this.memoryIndexService) {
|
|
275
|
-
return {
|
|
276
|
-
totalMemories: 0,
|
|
277
|
-
categoryCounts: {},
|
|
278
|
-
averageImportance: 0,
|
|
279
|
-
timeRange: null,
|
|
280
|
-
topTags: []
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
const stats = this.memoryIndexService.getIndexStats(userAddress);
|
|
285
|
-
|
|
286
|
-
return {
|
|
287
|
-
totalMemories: stats.totalMemories,
|
|
288
|
-
categoryCounts: stats.categoryCounts,
|
|
289
|
-
averageImportance: stats.averageImportance,
|
|
290
|
-
timeRange: stats.oldestMemory && stats.newestMemory ? {
|
|
291
|
-
earliest: stats.oldestMemory,
|
|
292
|
-
latest: stats.newestMemory
|
|
293
|
-
} : null,
|
|
294
|
-
topTags: [] // TODO: Implement tag extraction
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Get service statistics
|
|
300
|
-
*/
|
|
301
|
-
getServiceStats() {
|
|
302
|
-
return this.memoryIndexService?.getServiceStats() || {
|
|
303
|
-
totalUsers: 0,
|
|
304
|
-
totalMemories: 0,
|
|
305
|
-
averageMemoriesPerUser: 0
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* Calculate relevance score combining similarity, importance, and recency
|
|
311
|
-
*/
|
|
312
|
-
private calculateRelevanceScore(
|
|
313
|
-
similarity: number,
|
|
314
|
-
metadata: MemoryMetadata,
|
|
315
|
-
query: MetadataSearchQuery
|
|
316
|
-
): number {
|
|
317
|
-
let score = similarity * 0.6; // Base similarity weight
|
|
318
|
-
|
|
319
|
-
// Boost by importance
|
|
320
|
-
score += (metadata.importance || 5) * 0.1;
|
|
321
|
-
|
|
322
|
-
// Recent content boost
|
|
323
|
-
const ageInDays = (Date.now() - (metadata.createdTimestamp || 0)) / (1000 * 60 * 60 * 24);
|
|
324
|
-
const recencyBoost = Math.max(0, (30 - ageInDays) / 30) * 0.2;
|
|
325
|
-
score += recencyBoost;
|
|
326
|
-
|
|
327
|
-
// Category exact match boost
|
|
328
|
-
if (query.filters?.category && metadata.category === query.filters.category) {
|
|
329
|
-
score += 0.1;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
return Math.min(1.0, score);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* Check if memory matches filters
|
|
337
|
-
*/
|
|
338
|
-
private matchesFilters(
|
|
339
|
-
metadata: MemoryMetadata,
|
|
340
|
-
filters: NonNullable<MetadataSearchQuery['filters']>
|
|
341
|
-
): boolean {
|
|
342
|
-
// Category filter
|
|
343
|
-
if (filters.category) {
|
|
344
|
-
const categories = Array.isArray(filters.category) ? filters.category : [filters.category];
|
|
345
|
-
if (!categories.includes(metadata.category)) return false;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// Topic filter
|
|
349
|
-
if (filters.topic) {
|
|
350
|
-
const topics = Array.isArray(filters.topic) ? filters.topic : [filters.topic];
|
|
351
|
-
if (!topics.includes(metadata.topic)) return false;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// Importance range
|
|
355
|
-
if (filters.importance) {
|
|
356
|
-
const importance = metadata.importance || 5;
|
|
357
|
-
if (filters.importance.min && importance < filters.importance.min) return false;
|
|
358
|
-
if (filters.importance.max && importance > filters.importance.max) return false;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
// Content type filter
|
|
362
|
-
if (filters.contentType) {
|
|
363
|
-
const contentTypes = Array.isArray(filters.contentType)
|
|
364
|
-
? filters.contentType
|
|
365
|
-
: [filters.contentType];
|
|
366
|
-
if (!contentTypes.includes(metadata.contentType)) return false;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
// Content size filter
|
|
370
|
-
if (filters.contentSize) {
|
|
371
|
-
const size = metadata.contentSize || 0;
|
|
372
|
-
if (filters.contentSize.min && size < filters.contentSize.min) return false;
|
|
373
|
-
if (filters.contentSize.max && size > filters.contentSize.max) return false;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// Custom tag filtering
|
|
377
|
-
if (filters.tags && filters.tags.length > 0) {
|
|
378
|
-
const metadataText = JSON.stringify(metadata).toLowerCase();
|
|
379
|
-
const hasMatchingTag = filters.tags.some(tag =>
|
|
380
|
-
metadataText.includes(tag.toLowerCase())
|
|
381
|
-
);
|
|
382
|
-
if (!hasMatchingTag) return false;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
return true;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* MemorySearchManager - Memory Indexing and Search Operations
|
|
3
|
+
*
|
|
4
|
+
* Handles HNSW vector indexing and semantic search for memories.
|
|
5
|
+
* Extracted from StorageService for better separation of concerns.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Automatic memory indexing with embeddings
|
|
9
|
+
* - Semantic search via HNSW
|
|
10
|
+
* - Metadata-based filtering
|
|
11
|
+
* - Category and temporal search
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { MemoryIndexService, MemorySearchQuery } from '../MemoryIndexService';
|
|
15
|
+
import type { EmbeddingService } from '../EmbeddingService';
|
|
16
|
+
|
|
17
|
+
export interface MemoryMetadata {
|
|
18
|
+
contentType: string;
|
|
19
|
+
contentSize: number;
|
|
20
|
+
contentHash: string;
|
|
21
|
+
category: string;
|
|
22
|
+
topic: string;
|
|
23
|
+
importance: number;
|
|
24
|
+
embeddingBlobId?: string;
|
|
25
|
+
embeddingDimension: number;
|
|
26
|
+
createdTimestamp: number;
|
|
27
|
+
updatedTimestamp?: number;
|
|
28
|
+
customMetadata?: Record<string, string>;
|
|
29
|
+
isEncrypted?: boolean;
|
|
30
|
+
encryptionType?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface MetadataSearchQuery {
|
|
34
|
+
query?: string;
|
|
35
|
+
vector?: number[];
|
|
36
|
+
filters?: {
|
|
37
|
+
category?: string | string[];
|
|
38
|
+
topic?: string | string[];
|
|
39
|
+
importance?: { min?: number; max?: number };
|
|
40
|
+
contentType?: string | string[];
|
|
41
|
+
dateRange?: { start?: Date; end?: Date };
|
|
42
|
+
tags?: string[];
|
|
43
|
+
contentSize?: { min?: number; max?: number };
|
|
44
|
+
};
|
|
45
|
+
k?: number;
|
|
46
|
+
threshold?: number;
|
|
47
|
+
includeContent?: boolean;
|
|
48
|
+
useCache?: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface MetadataSearchResult {
|
|
52
|
+
blobId: string;
|
|
53
|
+
content?: string | Uint8Array;
|
|
54
|
+
metadata: MemoryMetadata;
|
|
55
|
+
similarity: number;
|
|
56
|
+
relevanceScore: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface IndexingResult {
|
|
60
|
+
vectorId: number;
|
|
61
|
+
blobId: string;
|
|
62
|
+
memoryId: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* MemorySearchManager - Manages memory indexing and semantic search
|
|
67
|
+
*
|
|
68
|
+
* Coordinates between:
|
|
69
|
+
* - EmbeddingService for vector generation
|
|
70
|
+
* - MemoryIndexService for HNSW indexing
|
|
71
|
+
* - Metadata filtering and relevance scoring
|
|
72
|
+
*/
|
|
73
|
+
export class MemorySearchManager {
|
|
74
|
+
private memoryIndexService?: MemoryIndexService;
|
|
75
|
+
private embeddingService?: EmbeddingService;
|
|
76
|
+
|
|
77
|
+
constructor() {
|
|
78
|
+
// Services will be initialized via initializeSearch()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Initialize search capabilities
|
|
83
|
+
*/
|
|
84
|
+
initializeSearch(
|
|
85
|
+
embeddingService: EmbeddingService,
|
|
86
|
+
memoryIndexService?: MemoryIndexService
|
|
87
|
+
) {
|
|
88
|
+
this.embeddingService = embeddingService;
|
|
89
|
+
this.memoryIndexService = memoryIndexService;
|
|
90
|
+
|
|
91
|
+
if (this.memoryIndexService) {
|
|
92
|
+
this.memoryIndexService.initialize(embeddingService, undefined as any);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.log('✅ MemorySearchManager: Search capabilities initialized');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Index a memory for semantic search
|
|
100
|
+
*
|
|
101
|
+
* @param userAddress - Owner address
|
|
102
|
+
* @param memoryId - Unique memory identifier
|
|
103
|
+
* @param blobId - Walrus blob ID
|
|
104
|
+
* @param textContent - Content for embedding generation
|
|
105
|
+
* @param metadata - Memory metadata
|
|
106
|
+
* @returns Indexing result with vector ID
|
|
107
|
+
*/
|
|
108
|
+
async indexMemory(
|
|
109
|
+
userAddress: string,
|
|
110
|
+
memoryId: string,
|
|
111
|
+
blobId: string,
|
|
112
|
+
textContent: string,
|
|
113
|
+
metadata: MemoryMetadata
|
|
114
|
+
): Promise<IndexingResult> {
|
|
115
|
+
if (!this.embeddingService || !this.memoryIndexService) {
|
|
116
|
+
throw new Error('Search capabilities not initialized. Call initializeSearch() first.');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Option A+: Pass isEncrypted flag to control content storage in index
|
|
120
|
+
// When encrypted, content is NOT stored locally (security consideration)
|
|
121
|
+
const indexResult = await this.memoryIndexService.indexMemory(
|
|
122
|
+
userAddress,
|
|
123
|
+
memoryId,
|
|
124
|
+
blobId,
|
|
125
|
+
textContent,
|
|
126
|
+
metadata,
|
|
127
|
+
undefined, // embedding - let MemoryIndexService generate it
|
|
128
|
+
{ isEncrypted: metadata.isEncrypted ?? false }
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
console.log(`✅ Indexed memory ${memoryId} → vector ${indexResult.vectorId}`);
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
vectorId: indexResult.vectorId,
|
|
135
|
+
blobId,
|
|
136
|
+
memoryId
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Search memories by metadata with semantic understanding
|
|
142
|
+
*
|
|
143
|
+
* @param userAddress - Owner address
|
|
144
|
+
* @param searchQuery - Search query with filters
|
|
145
|
+
* @returns Array of matching memories with relevance scores
|
|
146
|
+
*/
|
|
147
|
+
async searchByMetadata(
|
|
148
|
+
userAddress: string,
|
|
149
|
+
searchQuery: MetadataSearchQuery
|
|
150
|
+
): Promise<MetadataSearchResult[]> {
|
|
151
|
+
if (!this.embeddingService || !this.memoryIndexService) {
|
|
152
|
+
throw new Error('Search capabilities not initialized. Call initializeSearch() first.');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
console.log(`🔍 Searching memories for user ${userAddress}`);
|
|
157
|
+
|
|
158
|
+
// Convert to MemoryIndexService query format
|
|
159
|
+
const memoryQuery: MemorySearchQuery = {
|
|
160
|
+
query: searchQuery.query,
|
|
161
|
+
vector: searchQuery.vector,
|
|
162
|
+
userAddress,
|
|
163
|
+
k: searchQuery.k || 10,
|
|
164
|
+
threshold: searchQuery.threshold,
|
|
165
|
+
categories: searchQuery.filters?.category
|
|
166
|
+
? (Array.isArray(searchQuery.filters.category)
|
|
167
|
+
? searchQuery.filters.category
|
|
168
|
+
: [searchQuery.filters.category])
|
|
169
|
+
: undefined,
|
|
170
|
+
dateRange: searchQuery.filters?.dateRange,
|
|
171
|
+
importanceRange: searchQuery.filters?.importance,
|
|
172
|
+
tags: searchQuery.filters?.tags,
|
|
173
|
+
includeContent: searchQuery.includeContent
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const results = await this.memoryIndexService.searchMemories(memoryQuery);
|
|
177
|
+
|
|
178
|
+
// Convert to MetadataSearchResult format
|
|
179
|
+
const metadataResults: MetadataSearchResult[] = results.map(result => ({
|
|
180
|
+
blobId: result.blobId,
|
|
181
|
+
content: result.content,
|
|
182
|
+
metadata: result.metadata,
|
|
183
|
+
similarity: result.similarity,
|
|
184
|
+
relevanceScore: result.relevanceScore
|
|
185
|
+
}));
|
|
186
|
+
|
|
187
|
+
console.log(`✅ Found ${metadataResults.length} matching memories`);
|
|
188
|
+
return metadataResults;
|
|
189
|
+
|
|
190
|
+
} catch (error) {
|
|
191
|
+
console.error('❌ Metadata search failed:', error);
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Get all indexed memories for a user with optional filtering
|
|
198
|
+
*/
|
|
199
|
+
async getUserMemoriesWithMetadata(
|
|
200
|
+
userAddress: string,
|
|
201
|
+
filters?: MetadataSearchQuery['filters']
|
|
202
|
+
): Promise<MetadataSearchResult[]> {
|
|
203
|
+
if (!this.memoryIndexService) {
|
|
204
|
+
throw new Error('Memory indexing not initialized. Call initializeSearch() first.');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Convert filters to MemoryIndexService format
|
|
208
|
+
const indexFilters = filters ? {
|
|
209
|
+
categories: filters.category
|
|
210
|
+
? (Array.isArray(filters.category) ? filters.category : [filters.category])
|
|
211
|
+
: undefined,
|
|
212
|
+
dateRange: filters.dateRange,
|
|
213
|
+
importanceRange: filters.importance
|
|
214
|
+
} : undefined;
|
|
215
|
+
|
|
216
|
+
const memories = await this.memoryIndexService.getUserMemories(userAddress, indexFilters);
|
|
217
|
+
|
|
218
|
+
// Convert to MetadataSearchResult format
|
|
219
|
+
return memories.map(memory => ({
|
|
220
|
+
blobId: memory.blobId,
|
|
221
|
+
metadata: memory.metadata,
|
|
222
|
+
similarity: memory.similarity,
|
|
223
|
+
relevanceScore: memory.relevanceScore
|
|
224
|
+
}));
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Search by category with additional filtering
|
|
229
|
+
*/
|
|
230
|
+
async searchByCategory(
|
|
231
|
+
userAddress: string,
|
|
232
|
+
category: string,
|
|
233
|
+
additionalFilters?: Omit<MetadataSearchQuery['filters'], 'category'>
|
|
234
|
+
): Promise<MetadataSearchResult[]> {
|
|
235
|
+
return this.searchByMetadata(userAddress, {
|
|
236
|
+
filters: {
|
|
237
|
+
category,
|
|
238
|
+
...additionalFilters
|
|
239
|
+
},
|
|
240
|
+
k: 50,
|
|
241
|
+
includeContent: false
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Search memories within time range
|
|
247
|
+
*/
|
|
248
|
+
async searchByTimeRange(
|
|
249
|
+
userAddress: string,
|
|
250
|
+
startDate: Date,
|
|
251
|
+
endDate: Date,
|
|
252
|
+
additionalFilters?: Omit<MetadataSearchQuery['filters'], 'dateRange'>
|
|
253
|
+
): Promise<MetadataSearchResult[]> {
|
|
254
|
+
return this.searchByMetadata(userAddress, {
|
|
255
|
+
filters: {
|
|
256
|
+
dateRange: { start: startDate, end: endDate },
|
|
257
|
+
...additionalFilters
|
|
258
|
+
},
|
|
259
|
+
k: 100,
|
|
260
|
+
includeContent: false
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Get search analytics and statistics
|
|
266
|
+
*/
|
|
267
|
+
getSearchAnalytics(userAddress: string): {
|
|
268
|
+
totalMemories: number;
|
|
269
|
+
categoryCounts: Record<string, number>;
|
|
270
|
+
averageImportance: number;
|
|
271
|
+
timeRange: { earliest: Date; latest: Date } | null;
|
|
272
|
+
topTags: Array<{ tag: string; count: number }>;
|
|
273
|
+
} {
|
|
274
|
+
if (!this.memoryIndexService) {
|
|
275
|
+
return {
|
|
276
|
+
totalMemories: 0,
|
|
277
|
+
categoryCounts: {},
|
|
278
|
+
averageImportance: 0,
|
|
279
|
+
timeRange: null,
|
|
280
|
+
topTags: []
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const stats = this.memoryIndexService.getIndexStats(userAddress);
|
|
285
|
+
|
|
286
|
+
return {
|
|
287
|
+
totalMemories: stats.totalMemories,
|
|
288
|
+
categoryCounts: stats.categoryCounts,
|
|
289
|
+
averageImportance: stats.averageImportance,
|
|
290
|
+
timeRange: stats.oldestMemory && stats.newestMemory ? {
|
|
291
|
+
earliest: stats.oldestMemory,
|
|
292
|
+
latest: stats.newestMemory
|
|
293
|
+
} : null,
|
|
294
|
+
topTags: [] // TODO: Implement tag extraction
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Get service statistics
|
|
300
|
+
*/
|
|
301
|
+
getServiceStats() {
|
|
302
|
+
return this.memoryIndexService?.getServiceStats() || {
|
|
303
|
+
totalUsers: 0,
|
|
304
|
+
totalMemories: 0,
|
|
305
|
+
averageMemoriesPerUser: 0
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Calculate relevance score combining similarity, importance, and recency
|
|
311
|
+
*/
|
|
312
|
+
private calculateRelevanceScore(
|
|
313
|
+
similarity: number,
|
|
314
|
+
metadata: MemoryMetadata,
|
|
315
|
+
query: MetadataSearchQuery
|
|
316
|
+
): number {
|
|
317
|
+
let score = similarity * 0.6; // Base similarity weight
|
|
318
|
+
|
|
319
|
+
// Boost by importance
|
|
320
|
+
score += (metadata.importance || 5) * 0.1;
|
|
321
|
+
|
|
322
|
+
// Recent content boost
|
|
323
|
+
const ageInDays = (Date.now() - (metadata.createdTimestamp || 0)) / (1000 * 60 * 60 * 24);
|
|
324
|
+
const recencyBoost = Math.max(0, (30 - ageInDays) / 30) * 0.2;
|
|
325
|
+
score += recencyBoost;
|
|
326
|
+
|
|
327
|
+
// Category exact match boost
|
|
328
|
+
if (query.filters?.category && metadata.category === query.filters.category) {
|
|
329
|
+
score += 0.1;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return Math.min(1.0, score);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Check if memory matches filters
|
|
337
|
+
*/
|
|
338
|
+
private matchesFilters(
|
|
339
|
+
metadata: MemoryMetadata,
|
|
340
|
+
filters: NonNullable<MetadataSearchQuery['filters']>
|
|
341
|
+
): boolean {
|
|
342
|
+
// Category filter
|
|
343
|
+
if (filters.category) {
|
|
344
|
+
const categories = Array.isArray(filters.category) ? filters.category : [filters.category];
|
|
345
|
+
if (!categories.includes(metadata.category)) return false;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Topic filter
|
|
349
|
+
if (filters.topic) {
|
|
350
|
+
const topics = Array.isArray(filters.topic) ? filters.topic : [filters.topic];
|
|
351
|
+
if (!topics.includes(metadata.topic)) return false;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Importance range
|
|
355
|
+
if (filters.importance) {
|
|
356
|
+
const importance = metadata.importance || 5;
|
|
357
|
+
if (filters.importance.min && importance < filters.importance.min) return false;
|
|
358
|
+
if (filters.importance.max && importance > filters.importance.max) return false;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Content type filter
|
|
362
|
+
if (filters.contentType) {
|
|
363
|
+
const contentTypes = Array.isArray(filters.contentType)
|
|
364
|
+
? filters.contentType
|
|
365
|
+
: [filters.contentType];
|
|
366
|
+
if (!contentTypes.includes(metadata.contentType)) return false;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Content size filter
|
|
370
|
+
if (filters.contentSize) {
|
|
371
|
+
const size = metadata.contentSize || 0;
|
|
372
|
+
if (filters.contentSize.min && size < filters.contentSize.min) return false;
|
|
373
|
+
if (filters.contentSize.max && size > filters.contentSize.max) return false;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Custom tag filtering
|
|
377
|
+
if (filters.tags && filters.tags.length > 0) {
|
|
378
|
+
const metadataText = JSON.stringify(metadata).toLowerCase();
|
|
379
|
+
const hasMatchingTag = filters.tags.some(tag =>
|
|
380
|
+
metadataText.includes(tag.toLowerCase())
|
|
381
|
+
);
|
|
382
|
+
if (!hasMatchingTag) return false;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return true;
|
|
386
|
+
}
|
|
387
|
+
}
|