@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.
Files changed (247) hide show
  1. package/ARCHITECTURE.md +547 -547
  2. package/BENCHMARKS.md +238 -238
  3. package/README.md +310 -181
  4. package/dist/ai-sdk/tools.d.ts +2 -2
  5. package/dist/ai-sdk/tools.js +2 -2
  6. package/dist/client/ClientMemoryManager.js +2 -2
  7. package/dist/client/ClientMemoryManager.js.map +1 -1
  8. package/dist/client/PersonalDataWallet.d.ts.map +1 -1
  9. package/dist/client/SimplePDWClient.d.ts +29 -1
  10. package/dist/client/SimplePDWClient.d.ts.map +1 -1
  11. package/dist/client/SimplePDWClient.js +45 -13
  12. package/dist/client/SimplePDWClient.js.map +1 -1
  13. package/dist/client/namespaces/EmbeddingsNamespace.d.ts +1 -1
  14. package/dist/client/namespaces/EmbeddingsNamespace.js +1 -1
  15. package/dist/client/namespaces/MemoryNamespace.d.ts +31 -0
  16. package/dist/client/namespaces/MemoryNamespace.d.ts.map +1 -1
  17. package/dist/client/namespaces/MemoryNamespace.js +272 -39
  18. package/dist/client/namespaces/MemoryNamespace.js.map +1 -1
  19. package/dist/client/namespaces/consolidated/AINamespace.d.ts +2 -2
  20. package/dist/client/namespaces/consolidated/AINamespace.js +2 -2
  21. package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts +12 -2
  22. package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts.map +1 -1
  23. package/dist/client/namespaces/consolidated/BlockchainNamespace.js +62 -4
  24. package/dist/client/namespaces/consolidated/BlockchainNamespace.js.map +1 -1
  25. package/dist/client/namespaces/consolidated/StorageNamespace.d.ts +67 -2
  26. package/dist/client/namespaces/consolidated/StorageNamespace.d.ts.map +1 -1
  27. package/dist/client/namespaces/consolidated/StorageNamespace.js +549 -16
  28. package/dist/client/namespaces/consolidated/StorageNamespace.js.map +1 -1
  29. package/dist/config/ConfigurationHelper.js +61 -61
  30. package/dist/config/defaults.js +2 -2
  31. package/dist/config/defaults.js.map +1 -1
  32. package/dist/graph/GraphService.js +21 -21
  33. package/dist/graph/GraphService.js.map +1 -1
  34. package/dist/index.d.ts +3 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +3 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/infrastructure/seal/EncryptionService.d.ts +9 -5
  39. package/dist/infrastructure/seal/EncryptionService.d.ts.map +1 -1
  40. package/dist/infrastructure/seal/EncryptionService.js +37 -15
  41. package/dist/infrastructure/seal/EncryptionService.js.map +1 -1
  42. package/dist/infrastructure/seal/SealService.d.ts +13 -5
  43. package/dist/infrastructure/seal/SealService.d.ts.map +1 -1
  44. package/dist/infrastructure/seal/SealService.js +36 -34
  45. package/dist/infrastructure/seal/SealService.js.map +1 -1
  46. package/dist/langchain/createPDWRAG.js +30 -30
  47. package/dist/retrieval/MemoryDecryptionPipeline.d.ts.map +1 -1
  48. package/dist/retrieval/MemoryDecryptionPipeline.js +2 -1
  49. package/dist/retrieval/MemoryDecryptionPipeline.js.map +1 -1
  50. package/dist/retrieval/MemoryRetrievalService.d.ts +31 -0
  51. package/dist/retrieval/MemoryRetrievalService.d.ts.map +1 -1
  52. package/dist/retrieval/MemoryRetrievalService.js +44 -4
  53. package/dist/retrieval/MemoryRetrievalService.js.map +1 -1
  54. package/dist/services/CapabilityService.d.ts.map +1 -1
  55. package/dist/services/CapabilityService.js +30 -14
  56. package/dist/services/CapabilityService.js.map +1 -1
  57. package/dist/services/CrossContextPermissionService.d.ts.map +1 -1
  58. package/dist/services/CrossContextPermissionService.js +9 -7
  59. package/dist/services/CrossContextPermissionService.js.map +1 -1
  60. package/dist/services/EmbeddingService.d.ts +28 -1
  61. package/dist/services/EmbeddingService.d.ts.map +1 -1
  62. package/dist/services/EmbeddingService.js +54 -0
  63. package/dist/services/EmbeddingService.js.map +1 -1
  64. package/dist/services/EncryptionService.d.ts.map +1 -1
  65. package/dist/services/EncryptionService.js +6 -5
  66. package/dist/services/EncryptionService.js.map +1 -1
  67. package/dist/services/GeminiAIService.js +309 -309
  68. package/dist/services/IndexManager.d.ts +5 -1
  69. package/dist/services/IndexManager.d.ts.map +1 -1
  70. package/dist/services/IndexManager.js +17 -40
  71. package/dist/services/IndexManager.js.map +1 -1
  72. package/dist/services/QueryService.js +1 -1
  73. package/dist/services/QueryService.js.map +1 -1
  74. package/dist/services/StorageService.d.ts +11 -0
  75. package/dist/services/StorageService.d.ts.map +1 -1
  76. package/dist/services/StorageService.js +73 -10
  77. package/dist/services/StorageService.js.map +1 -1
  78. package/dist/services/TransactionService.d.ts +20 -0
  79. package/dist/services/TransactionService.d.ts.map +1 -1
  80. package/dist/services/TransactionService.js +43 -0
  81. package/dist/services/TransactionService.js.map +1 -1
  82. package/dist/services/ViewService.js +2 -2
  83. package/dist/services/ViewService.js.map +1 -1
  84. package/dist/services/storage/QuiltBatchManager.d.ts +101 -1
  85. package/dist/services/storage/QuiltBatchManager.d.ts.map +1 -1
  86. package/dist/services/storage/QuiltBatchManager.js +410 -20
  87. package/dist/services/storage/QuiltBatchManager.js.map +1 -1
  88. package/dist/services/storage/index.d.ts +1 -1
  89. package/dist/services/storage/index.d.ts.map +1 -1
  90. package/dist/services/storage/index.js.map +1 -1
  91. package/dist/utils/LRUCache.d.ts +106 -0
  92. package/dist/utils/LRUCache.d.ts.map +1 -0
  93. package/dist/utils/LRUCache.js +281 -0
  94. package/dist/utils/LRUCache.js.map +1 -0
  95. package/dist/utils/index.d.ts +1 -0
  96. package/dist/utils/index.d.ts.map +1 -1
  97. package/dist/utils/index.js +2 -0
  98. package/dist/utils/index.js.map +1 -1
  99. package/dist/utils/memoryIndexOnChain.d.ts +212 -0
  100. package/dist/utils/memoryIndexOnChain.d.ts.map +1 -0
  101. package/dist/utils/memoryIndexOnChain.js +312 -0
  102. package/dist/utils/memoryIndexOnChain.js.map +1 -0
  103. package/dist/utils/rebuildIndexNode.d.ts +29 -0
  104. package/dist/utils/rebuildIndexNode.d.ts.map +1 -1
  105. package/dist/utils/rebuildIndexNode.js +366 -98
  106. package/dist/utils/rebuildIndexNode.js.map +1 -1
  107. package/dist/vector/HnswWasmService.d.ts +20 -5
  108. package/dist/vector/HnswWasmService.d.ts.map +1 -1
  109. package/dist/vector/HnswWasmService.js +73 -40
  110. package/dist/vector/HnswWasmService.js.map +1 -1
  111. package/dist/vector/IHnswService.d.ts +10 -1
  112. package/dist/vector/IHnswService.d.ts.map +1 -1
  113. package/dist/vector/IHnswService.js.map +1 -1
  114. package/dist/vector/NodeHnswService.d.ts +16 -0
  115. package/dist/vector/NodeHnswService.d.ts.map +1 -1
  116. package/dist/vector/NodeHnswService.js +84 -5
  117. package/dist/vector/NodeHnswService.js.map +1 -1
  118. package/dist/vector/createHnswService.d.ts +1 -1
  119. package/dist/vector/createHnswService.js +1 -1
  120. package/dist/vector/index.d.ts +1 -1
  121. package/dist/vector/index.js +1 -1
  122. package/package.json +157 -157
  123. package/src/access/PermissionService.ts +635 -635
  124. package/src/aggregation/AggregationService.ts +389 -389
  125. package/src/ai-sdk/PDWVectorStore.ts +715 -715
  126. package/src/ai-sdk/index.ts +65 -65
  127. package/src/ai-sdk/tools.ts +460 -460
  128. package/src/ai-sdk/types.ts +404 -404
  129. package/src/batch/BatchManager.ts +597 -597
  130. package/src/batch/BatchingService.ts +429 -429
  131. package/src/batch/MemoryProcessingCache.ts +492 -492
  132. package/src/batch/index.ts +30 -30
  133. package/src/browser.ts +200 -200
  134. package/src/client/ClientMemoryManager.ts +987 -987
  135. package/src/client/PersonalDataWallet.ts +345 -345
  136. package/src/client/SimplePDWClient.ts +1289 -1222
  137. package/src/client/factory.ts +154 -154
  138. package/src/client/namespaces/AnalyticsNamespace.ts +377 -377
  139. package/src/client/namespaces/BatchNamespace.ts +356 -356
  140. package/src/client/namespaces/CacheNamespace.ts +123 -123
  141. package/src/client/namespaces/CapabilityNamespace.ts +217 -217
  142. package/src/client/namespaces/ClassifyNamespace.ts +169 -169
  143. package/src/client/namespaces/ContextNamespace.ts +297 -297
  144. package/src/client/namespaces/EmbeddingsNamespace.ts +99 -99
  145. package/src/client/namespaces/EncryptionNamespace.ts +221 -221
  146. package/src/client/namespaces/GraphNamespace.ts +468 -468
  147. package/src/client/namespaces/IndexNamespace.ts +361 -361
  148. package/src/client/namespaces/MemoryNamespace.ts +1422 -1135
  149. package/src/client/namespaces/PermissionsNamespace.ts +254 -254
  150. package/src/client/namespaces/PipelineNamespace.ts +220 -220
  151. package/src/client/namespaces/SearchNamespace.ts +1049 -1049
  152. package/src/client/namespaces/StorageNamespace.ts +458 -458
  153. package/src/client/namespaces/TxNamespace.ts +260 -260
  154. package/src/client/namespaces/WalletNamespace.ts +243 -243
  155. package/src/client/namespaces/consolidated/AINamespace.ts +449 -449
  156. package/src/client/namespaces/consolidated/BlockchainNamespace.ts +607 -546
  157. package/src/client/namespaces/consolidated/SecurityNamespace.ts +648 -648
  158. package/src/client/namespaces/consolidated/StorageNamespace.ts +1141 -497
  159. package/src/client/namespaces/consolidated/index.ts +39 -39
  160. package/src/client/signers/KeypairSigner.ts +108 -108
  161. package/src/client/signers/UnifiedSigner.ts +110 -110
  162. package/src/client/signers/WalletAdapterSigner.ts +159 -159
  163. package/src/client/signers/index.ts +26 -26
  164. package/src/config/ConfigurationHelper.ts +412 -412
  165. package/src/config/defaults.ts +51 -51
  166. package/src/config/index.ts +8 -8
  167. package/src/config/validation.ts +70 -70
  168. package/src/core/index.ts +14 -14
  169. package/src/core/interfaces/IService.ts +307 -307
  170. package/src/core/interfaces/index.ts +8 -8
  171. package/src/core/types/capability.ts +297 -297
  172. package/src/core/types/index.ts +870 -870
  173. package/src/core/types/wallet.ts +270 -270
  174. package/src/core/types.ts +9 -9
  175. package/src/core/wallet.ts +222 -222
  176. package/src/embedding/index.ts +19 -19
  177. package/src/embedding/types.ts +357 -357
  178. package/src/errors/index.ts +602 -602
  179. package/src/errors/recovery.ts +461 -461
  180. package/src/errors/validation.ts +567 -567
  181. package/src/generated/pdw/capability.ts +319 -319
  182. package/src/graph/GraphService.ts +887 -887
  183. package/src/graph/KnowledgeGraphManager.ts +728 -728
  184. package/src/graph/index.ts +25 -25
  185. package/src/index.ts +498 -474
  186. package/src/infrastructure/index.ts +22 -22
  187. package/src/infrastructure/seal/EncryptionService.ts +628 -603
  188. package/src/infrastructure/seal/SealService.ts +613 -615
  189. package/src/infrastructure/seal/index.ts +9 -9
  190. package/src/infrastructure/sui/BlockchainManager.ts +627 -627
  191. package/src/infrastructure/sui/SuiService.ts +888 -888
  192. package/src/infrastructure/sui/index.ts +9 -9
  193. package/src/infrastructure/walrus/StorageManager.ts +604 -604
  194. package/src/infrastructure/walrus/WalrusStorageService.ts +612 -612
  195. package/src/infrastructure/walrus/index.ts +9 -9
  196. package/src/langchain/PDWEmbeddings.ts +145 -145
  197. package/src/langchain/PDWVectorStore.ts +456 -456
  198. package/src/langchain/createPDWRAG.ts +303 -303
  199. package/src/langchain/index.ts +47 -47
  200. package/src/permissions/ConsentRepository.browser.ts +249 -249
  201. package/src/permissions/ConsentRepository.ts +364 -364
  202. package/src/pipeline/MemoryPipeline.ts +862 -862
  203. package/src/pipeline/PipelineManager.ts +683 -683
  204. package/src/pipeline/index.ts +26 -26
  205. package/src/retrieval/AdvancedSearchService.ts +629 -629
  206. package/src/retrieval/MemoryAnalyticsService.ts +711 -711
  207. package/src/retrieval/MemoryDecryptionPipeline.ts +825 -824
  208. package/src/retrieval/MemoryRetrievalService.ts +904 -830
  209. package/src/retrieval/index.ts +42 -42
  210. package/src/services/BatchService.ts +352 -352
  211. package/src/services/CapabilityService.ts +464 -448
  212. package/src/services/ClassifierService.ts +465 -465
  213. package/src/services/CrossContextPermissionService.ts +486 -484
  214. package/src/services/EmbeddingService.ts +771 -706
  215. package/src/services/EncryptionService.ts +712 -711
  216. package/src/services/GeminiAIService.ts +753 -753
  217. package/src/services/IndexManager.ts +977 -1004
  218. package/src/services/MemoryIndexService.ts +1003 -1003
  219. package/src/services/MemoryService.ts +369 -369
  220. package/src/services/QueryService.ts +890 -890
  221. package/src/services/StorageService.ts +1182 -1111
  222. package/src/services/TransactionService.ts +838 -790
  223. package/src/services/VectorService.ts +462 -462
  224. package/src/services/ViewService.ts +484 -484
  225. package/src/services/index.ts +25 -25
  226. package/src/services/storage/BlobAttributesManager.ts +333 -333
  227. package/src/services/storage/KnowledgeGraphManager.ts +425 -425
  228. package/src/services/storage/MemorySearchManager.ts +387 -387
  229. package/src/services/storage/QuiltBatchManager.ts +1130 -660
  230. package/src/services/storage/WalrusMetadataManager.ts +268 -268
  231. package/src/services/storage/WalrusStorageManager.ts +287 -287
  232. package/src/services/storage/index.ts +57 -52
  233. package/src/types/index.ts +13 -13
  234. package/src/utils/LRUCache.ts +378 -0
  235. package/src/utils/index.ts +76 -68
  236. package/src/utils/memoryIndexOnChain.ts +507 -0
  237. package/src/utils/rebuildIndex.ts +290 -290
  238. package/src/utils/rebuildIndexNode.ts +771 -424
  239. package/src/vector/BrowserHnswIndexService.ts +758 -758
  240. package/src/vector/HnswWasmService.ts +731 -679
  241. package/src/vector/IHnswService.ts +233 -224
  242. package/src/vector/NodeHnswService.ts +833 -735
  243. package/src/vector/VectorManager.ts +478 -478
  244. package/src/vector/createHnswService.ts +135 -135
  245. package/src/vector/index.ts +56 -56
  246. package/src/wallet/ContextWalletService.ts +656 -656
  247. package/src/wallet/MainWalletService.ts +317 -317
@@ -1,1111 +1,1182 @@
1
- /**
2
- * StorageService - Refactored with Manager Delegation
3
- *
4
- * This is a coordinator service that delegates to specialized managers:
5
- * - WalrusStorageManager: Core Walrus operations
6
- * - MemorySearchManager: Memory indexing and search
7
- * - KnowledgeGraphManager: Knowledge graph operations
8
- * - WalrusMetadataManager: Metadata operations
9
- * - QuiltBatchManager: Batch uploads
10
- * - BlobAttributesManager: Dynamic field operations
11
- *
12
- * Maintains full backward compatibility with original StorageService API.
13
- */
14
-
15
- import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
16
- import { Transaction } from '@mysten/sui/transactions';
17
- import { WalrusClient, WalrusFile } from '@mysten/walrus';
18
- import type { UnifiedSigner } from '../client/signers/UnifiedSigner';
19
- import type { ClientWithExtensions } from '@mysten/sui/experimental';
20
- import type { SealService } from '../infrastructure/seal/SealService';
21
- import type { BatchService } from './BatchService';
22
- import { PDWConfig } from '../core';
23
- import { MemoryIndexService } from './MemoryIndexService';
24
- import { EmbeddingService, type EmbeddingOptions } from './EmbeddingService';
25
- import { GraphService, type KnowledgeGraph, type Entity, type Relationship, type GraphExtractionResult } from '../graph/GraphService';
26
-
27
- // Import managers
28
- import { WalrusStorageManager } from './storage/WalrusStorageManager';
29
- import { MemorySearchManager } from './storage/MemorySearchManager';
30
- import { KnowledgeGraphManager } from './storage/KnowledgeGraphManager';
31
- import { WalrusMetadataManager } from './storage/WalrusMetadataManager';
32
- import { QuiltBatchManager } from './storage/QuiltBatchManager';
33
- import { BlobAttributesManager } from './storage/BlobAttributesManager';
34
-
35
- // Re-export types for backward compatibility
36
- export interface StorageServiceConfig extends PDWConfig {
37
- suiClient?: SuiClient;
38
- network?: 'testnet' | 'mainnet';
39
- maxFileSize?: number;
40
- timeout?: number;
41
- useUploadRelay?: boolean;
42
- epochs?: number;
43
- sealService?: SealService;
44
- batchService?: BatchService;
45
- }
46
-
47
- export interface MemoryMetadata {
48
- contentType: string;
49
- contentSize: number;
50
- contentHash: string;
51
- category: string;
52
- topic: string;
53
- importance: number;
54
- embeddingBlobId?: string;
55
- embeddingDimension: number;
56
- createdTimestamp: number;
57
- updatedTimestamp?: number;
58
- customMetadata?: Record<string, string>;
59
- isEncrypted?: boolean;
60
- encryptionType?: string;
61
- }
62
-
63
- export interface WalrusUploadResult {
64
- blobId: string;
65
- metadata: MemoryMetadata;
66
- embeddingBlobId?: string;
67
- isEncrypted: boolean;
68
- backupKey?: string;
69
- storageEpochs: number;
70
- uploadTimeMs: number;
71
- }
72
-
73
- export interface BlobUploadOptions {
74
- signer: UnifiedSigner;
75
- epochs?: number;
76
- deletable?: boolean;
77
- useUploadRelay?: boolean;
78
- encrypt?: boolean;
79
- metadata?: Record<string, string>;
80
- }
81
-
82
- export interface FileUploadOptions extends BlobUploadOptions {
83
- files: Array<{
84
- identifier: string;
85
- content: Uint8Array | string;
86
- tags?: Record<string, string>;
87
- }>;
88
- }
89
-
90
- export interface WalrusMemoryMetadata {
91
- content_type: string;
92
- content_size: string;
93
- category: string;
94
- topic: string;
95
- importance: string;
96
- embedding_dimensions: string;
97
- embedding_model: string;
98
- embedding_blob_id?: string;
99
- graph_entity_count: string;
100
- graph_relationship_count: string;
101
- graph_blob_id?: string;
102
- graph_entity_ids?: string;
103
- vector_id: string;
104
- vector_status: string;
105
- created_at: string;
106
- updated_at: string;
107
- deleted_at?: string;
108
- encrypted: string;
109
- encryption_type?: string;
110
- seal_identity?: string;
111
- [key: string]: string | undefined;
112
- }
113
-
114
- export interface WalrusMetadataOptions {
115
- attachMetadata?: boolean;
116
- walrusMetadata?: Partial<WalrusMemoryMetadata>;
117
- embeddingBlobId?: string;
118
- graphBlobId?: string;
119
- vectorId?: number;
120
- graphEntityIds?: string[];
121
- }
122
-
123
- export interface BlobUploadOptionsWithMetadata extends BlobUploadOptions, WalrusMetadataOptions {}
124
-
125
- export interface MetadataSearchQuery {
126
- query?: string;
127
- vector?: number[];
128
- filters?: {
129
- category?: string | string[];
130
- topic?: string | string[];
131
- importance?: { min?: number; max?: number };
132
- contentType?: string | string[];
133
- dateRange?: { start?: Date; end?: Date };
134
- tags?: string[];
135
- contentSize?: { min?: number; max?: number };
136
- };
137
- k?: number;
138
- threshold?: number;
139
- includeContent?: boolean;
140
- useCache?: boolean;
141
- }
142
-
143
- export interface MetadataSearchResult {
144
- blobId: string;
145
- content?: string | Uint8Array;
146
- metadata: MemoryMetadata;
147
- similarity: number;
148
- relevanceScore: number;
149
- }
150
-
151
- export interface IndexedMemoryEntry {
152
- blobId: string;
153
- vectorId: number;
154
- metadata: MemoryMetadata;
155
- vector: number[];
156
- }
157
-
158
- /**
159
- * StorageService - Refactored with Manager Delegation
160
- */
161
- export class StorageService {
162
- // Managers
163
- private walrusStorage: WalrusStorageManager;
164
- private memorySearch: MemorySearchManager;
165
- private knowledgeGraph: KnowledgeGraphManager;
166
- private walrusMetadata: WalrusMetadataManager;
167
- private quiltBatch: QuiltBatchManager;
168
- private blobAttributes: BlobAttributesManager;
169
-
170
- // Legacy properties for backward compatibility
171
- private suiClient: ClientWithExtensions<{ jsonRpc: SuiClient; walrus: WalrusClient }>;
172
- private memoryIndexService?: MemoryIndexService;
173
- private embeddingService?: EmbeddingService;
174
- private graphService?: GraphService;
175
-
176
- constructor(private config: StorageServiceConfig) {
177
- // Initialize WalrusStorageManager
178
- this.walrusStorage = new WalrusStorageManager({
179
- suiClient: config.suiClient,
180
- network: config.network,
181
- maxFileSize: config.maxFileSize,
182
- timeout: config.timeout,
183
- useUploadRelay: config.useUploadRelay,
184
- epochs: config.epochs
185
- });
186
-
187
- // Initialize MemorySearchManager
188
- this.memorySearch = new MemorySearchManager();
189
-
190
- // Initialize KnowledgeGraphManager
191
- this.knowledgeGraph = new KnowledgeGraphManager();
192
-
193
- // Get SuiClient from WalrusStorageManager
194
- this.suiClient = this.walrusStorage.getSuiClient();
195
-
196
- // Initialize WalrusMetadataManager
197
- this.walrusMetadata = new WalrusMetadataManager(this.suiClient.jsonRpc);
198
-
199
- // Initialize QuiltBatchManager
200
- this.quiltBatch = new QuiltBatchManager(
201
- this.walrusStorage.getWalrusClient(true),
202
- this.walrusStorage.getWalrusClient(false),
203
- this.suiClient,
204
- config.useUploadRelay ?? true,
205
- config.epochs || 3
206
- );
207
-
208
- // Initialize BlobAttributesManager
209
- this.blobAttributes = new BlobAttributesManager(this.suiClient.jsonRpc);
210
-
211
- console.log('✅ StorageService initialized with manager delegation');
212
- }
213
-
214
- // ==================== INITIALIZATION METHODS ====================
215
-
216
- /**
217
- * Initialize memory indexing and search capabilities
218
- */
219
- initializeSearch(embeddingService: EmbeddingService, memoryIndexService?: MemoryIndexService) {
220
- this.embeddingService = embeddingService;
221
- this.memoryIndexService = memoryIndexService || new MemoryIndexService(this);
222
-
223
- this.memorySearch.initializeSearch(embeddingService, this.memoryIndexService);
224
-
225
- console.log('✅ StorageService: Memory indexing and search capabilities initialized');
226
- }
227
-
228
- /**
229
- * Initialize Knowledge Graph capabilities
230
- */
231
- async initializeKnowledgeGraph(graphConfig?: any) {
232
- this.graphService = await this.knowledgeGraph.initializeKnowledgeGraph(
233
- this.embeddingService,
234
- graphConfig
235
- );
236
- return this.graphService;
237
- }
238
-
239
- // ==================== CORE WALRUS OPERATIONS (Delegate to WalrusStorageManager) ====================
240
-
241
- /**
242
- * Upload single blob using writeBlobFlow pattern
243
- */
244
- async uploadBlob(
245
- data: Uint8Array,
246
- options: BlobUploadOptions
247
- ): Promise<WalrusUploadResult> {
248
- const result = await this.walrusStorage.uploadBlob(data, options);
249
-
250
- // Convert to legacy format
251
- const metadata: MemoryMetadata = {
252
- contentType: options.metadata?.['content-type'] || 'application/octet-stream',
253
- contentSize: result.contentSize,
254
- contentHash: result.blobId, // Walrus blob_id serves as content hash
255
- category: options.metadata?.category || 'default',
256
- topic: options.metadata?.topic || '',
257
- importance: parseInt(options.metadata?.importance || '5'),
258
- embeddingDimension: parseInt(options.metadata?.['embedding-dimensions'] || '0'),
259
- createdTimestamp: Date.now(),
260
- customMetadata: options.metadata,
261
- isEncrypted: result.isEncrypted,
262
- encryptionType: result.isEncrypted ? 'seal' : undefined,
263
- };
264
-
265
- // Handle metadata attachment if requested
266
- if ((options as BlobUploadOptionsWithMetadata).attachMetadata && result.blobObjectId) {
267
- const metadataOptions = options as BlobUploadOptionsWithMetadata;
268
- const walrusMetadata = this.buildWalrusMetadata(
269
- result.contentSize,
270
- {
271
- category: metadata.category,
272
- topic: metadata.topic,
273
- importance: metadata.importance,
274
- embeddingBlobId: metadataOptions.embeddingBlobId,
275
- graphBlobId: metadataOptions.graphBlobId,
276
- graphEntityIds: metadataOptions.graphEntityIds,
277
- vectorId: metadataOptions.vectorId,
278
- isEncrypted: result.isEncrypted,
279
- encryptionType: metadata.encryptionType,
280
- sealIdentity: options.metadata?.['seal-identity'],
281
- customFields: options.metadata,
282
- }
283
- );
284
-
285
- // Attach as attributes
286
- try {
287
- const attributes: Record<string, string> = {
288
- memory_category: walrusMetadata.category,
289
- memory_topic: walrusMetadata.topic,
290
- memory_importance: walrusMetadata.importance,
291
- memory_encrypted: walrusMetadata.encrypted,
292
- memory_encryption_type: walrusMetadata.encryption_type || 'none',
293
- memory_content_size: walrusMetadata.content_size,
294
- memory_created_at: walrusMetadata.created_at,
295
- };
296
-
297
- if (walrusMetadata.vector_id) {
298
- attributes.memory_vector_id = walrusMetadata.vector_id;
299
- }
300
- if (walrusMetadata.embedding_blob_id) {
301
- attributes.memory_embedding_blob_id = walrusMetadata.embedding_blob_id;
302
- }
303
- if (walrusMetadata.graph_blob_id) {
304
- attributes.memory_graph_blob_id = walrusMetadata.graph_blob_id;
305
- }
306
- if (walrusMetadata.seal_identity) {
307
- attributes.memory_seal_identity = walrusMetadata.seal_identity;
308
- }
309
-
310
- await this.blobAttributes.setBlobAttributes(
311
- result.blobObjectId,
312
- attributes,
313
- options.signer
314
- );
315
- } catch (error) {
316
- console.warn('⚠️ Failed to attach metadata (non-fatal):', error);
317
- }
318
- }
319
-
320
- return {
321
- blobId: result.blobId,
322
- metadata,
323
- isEncrypted: result.isEncrypted,
324
- storageEpochs: result.storageEpochs,
325
- uploadTimeMs: result.uploadTimeMs,
326
- };
327
- }
328
-
329
- /**
330
- * Upload memory package with SEAL encrypted content
331
- */
332
- async uploadMemoryPackage(
333
- memoryData: {
334
- content: string;
335
- embedding: number[];
336
- metadata: Record<string, any>;
337
- encryptedContent?: Uint8Array;
338
- encryptionType?: string;
339
- identity?: string;
340
- },
341
- options: BlobUploadOptions
342
- ): Promise<WalrusUploadResult> {
343
- let dataToUpload: Uint8Array;
344
- let storageApproach: 'direct-binary' | 'json-package';
345
- let uploadMetadata: Record<string, string>;
346
-
347
- if (memoryData.encryptedContent && memoryData.encryptedContent instanceof Uint8Array) {
348
- // Direct binary storage for SEAL encrypted data
349
- dataToUpload = memoryData.encryptedContent;
350
- storageApproach = 'direct-binary';
351
-
352
- uploadMetadata = {
353
- 'content-type': 'application/octet-stream',
354
- 'encryption-type': memoryData.encryptionType || 'seal-real',
355
- 'context-id': `memory-${memoryData.identity || 'unknown'}`,
356
- 'app-id': 'pdw-sdk',
357
- 'encrypted': 'true',
358
- 'seal-identity': memoryData.identity || '',
359
- 'version': '1.0',
360
- 'category': memoryData.metadata.category || 'memory',
361
- 'created-at': new Date().toISOString(),
362
- 'original-content-type': 'text/plain',
363
- 'embedding-dimensions': memoryData.embedding.length.toString(),
364
- 'metadata-title': memoryData.metadata.title || '',
365
- 'metadata-tags': JSON.stringify(memoryData.metadata.tags || []),
366
- 'storage-approach': storageApproach
367
- };
368
- } else {
369
- // JSON package storage
370
- storageApproach = 'json-package';
371
-
372
- const memoryPackage = {
373
- content: memoryData.content,
374
- embedding: memoryData.embedding,
375
- metadata: memoryData.metadata,
376
- encrypted: memoryData.encryptedContent ? {
377
- encryptedContent: memoryData.encryptedContent,
378
- encryptionType: memoryData.encryptionType,
379
- identity: memoryData.identity,
380
- timestamp: Date.now()
381
- } : null,
382
- timestamp: Date.now(),
383
- version: '1.0'
384
- };
385
-
386
- const payloadString = JSON.stringify(memoryPackage);
387
- dataToUpload = new TextEncoder().encode(payloadString);
388
-
389
- uploadMetadata = {
390
- 'content-type': 'application/json',
391
- 'encryption-type': memoryData.encryptionType || 'none',
392
- 'context-id': `memory-${memoryData.identity || 'unknown'}`,
393
- 'app-id': 'pdw-sdk',
394
- 'encrypted': memoryData.encryptionType?.includes('seal') ? 'true' : 'false',
395
- 'version': '1.0',
396
- 'category': memoryData.metadata.category || 'memory',
397
- 'created-at': new Date().toISOString(),
398
- 'storage-approach': storageApproach
399
- };
400
- }
401
-
402
- const result = await this.uploadBlob(dataToUpload, {
403
- ...options,
404
- metadata: uploadMetadata
405
- });
406
-
407
- return {
408
- ...result,
409
- metadata: {
410
- ...result.metadata,
411
- customMetadata: {
412
- ...result.metadata.customMetadata,
413
- 'storage-approach': storageApproach
414
- }
415
- }
416
- };
417
- }
418
-
419
- /**
420
- * Retrieve blob by ID directly from Walrus
421
- */
422
- async getBlob(blobId: string): Promise<Uint8Array> {
423
- return this.walrusStorage.getBlob(blobId);
424
- }
425
-
426
- /**
427
- * Retrieve blob with detailed logging
428
- */
429
- async retrieveFromWalrusOnly(blobId: string): Promise<{
430
- content: Uint8Array;
431
- source: 'walrus';
432
- retrievalTime: number;
433
- blobSize: number;
434
- }> {
435
- return this.walrusStorage.retrieveBlob(blobId);
436
- }
437
-
438
- /**
439
- * Retrieve memory package from Walrus with format detection
440
- */
441
- async retrieveMemoryPackage(blobId: string): Promise<{
442
- content: Uint8Array;
443
- storageApproach: 'direct-binary' | 'json-package' | 'unknown';
444
- metadata: MemoryMetadata;
445
- memoryPackage?: any;
446
- isEncrypted: boolean;
447
- source: 'walrus';
448
- retrievalTime: number;
449
- }> {
450
- const startTime = Date.now();
451
- const content = await this.getBlob(blobId);
452
-
453
- let storageApproach: 'direct-binary' | 'json-package' | 'unknown' = 'unknown';
454
- let memoryPackage: any = null;
455
- let isEncrypted = false;
456
-
457
- // Try to parse as JSON
458
- try {
459
- const contentString = new TextDecoder().decode(content);
460
- memoryPackage = JSON.parse(contentString);
461
-
462
- if (memoryPackage.version && memoryPackage.content && memoryPackage.embedding) {
463
- storageApproach = 'json-package';
464
- isEncrypted = false;
465
- }
466
- } catch (parseError) {
467
- // Not JSON - likely binary SEAL data
468
- const isBinary = content.some(byte => byte < 32 && byte !== 9 && byte !== 10 && byte !== 13);
469
- const hasHighBytes = content.some(byte => byte > 127);
470
-
471
- if (isBinary || hasHighBytes || content.length > 50) {
472
- storageApproach = 'direct-binary';
473
- isEncrypted = true;
474
- }
475
- }
476
-
477
- const metadata: MemoryMetadata = {
478
- contentType: storageApproach === 'json-package' ? 'application/json' : 'application/octet-stream',
479
- contentSize: content.length,
480
- contentHash: '',
481
- category: memoryPackage?.metadata?.category || 'unknown',
482
- topic: memoryPackage?.metadata?.topic || 'unknown',
483
- importance: memoryPackage?.metadata?.importance || 0,
484
- embeddingDimension: memoryPackage?.embedding?.length || 0,
485
- createdTimestamp: memoryPackage?.timestamp || Date.now(),
486
- isEncrypted,
487
- encryptionType: isEncrypted ? 'seal-real' : undefined
488
- };
489
-
490
- return {
491
- content,
492
- storageApproach,
493
- metadata,
494
- memoryPackage,
495
- isEncrypted,
496
- source: 'walrus' as const,
497
- retrievalTime: Date.now() - startTime
498
- };
499
- }
500
-
501
- // ==================== MEMORY SEARCH OPERATIONS (Delegate to MemorySearchManager) ====================
502
-
503
- /**
504
- * Upload with automatic memory indexing
505
- */
506
- async uploadWithIndexing(
507
- content: string | Uint8Array,
508
- metadata: MemoryMetadata,
509
- userAddress: string,
510
- options: BlobUploadOptions
511
- ): Promise<WalrusUploadResult & { vectorId: number }> {
512
- if (!this.embeddingService || !this.memoryIndexService) {
513
- throw new Error('Search capabilities not initialized. Call initializeSearch() first.');
514
- }
515
-
516
- const uploadResult = await this.upload(content, metadata, options);
517
-
518
- let textContent: string;
519
- if (content instanceof Uint8Array) {
520
- textContent = `${metadata.category} ${metadata.topic || ''} ${JSON.stringify(metadata.customMetadata || {})}`.trim();
521
- } else {
522
- textContent = content;
523
- }
524
-
525
- const memoryId = `memory_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
526
- const indexResult = await this.memorySearch.indexMemory(
527
- userAddress,
528
- memoryId,
529
- uploadResult.blobId,
530
- textContent,
531
- metadata
532
- );
533
-
534
- return {
535
- ...uploadResult,
536
- vectorId: indexResult.vectorId
537
- };
538
- }
539
-
540
- /**
541
- * Search memories by metadata
542
- */
543
- async searchByMetadata(
544
- userAddress: string,
545
- searchQuery: MetadataSearchQuery
546
- ): Promise<MetadataSearchResult[]> {
547
- return this.memorySearch.searchByMetadata(userAddress, searchQuery);
548
- }
549
-
550
- /**
551
- * Get all indexed memories for a user
552
- */
553
- async getUserMemoriesWithMetadata(
554
- userAddress: string,
555
- filters?: MetadataSearchQuery['filters']
556
- ): Promise<MetadataSearchResult[]> {
557
- return this.memorySearch.getUserMemoriesWithMetadata(userAddress, filters);
558
- }
559
-
560
- /**
561
- * Search by category
562
- */
563
- async searchByCategory(
564
- userAddress: string,
565
- category: string,
566
- additionalFilters?: Omit<MetadataSearchQuery['filters'], 'category'>
567
- ): Promise<MetadataSearchResult[]> {
568
- return this.memorySearch.searchByCategory(userAddress, category, additionalFilters);
569
- }
570
-
571
- /**
572
- * Search by time range
573
- */
574
- async searchByTimeRange(
575
- userAddress: string,
576
- startDate: Date,
577
- endDate: Date,
578
- additionalFilters?: Omit<MetadataSearchQuery['filters'], 'dateRange'>
579
- ): Promise<MetadataSearchResult[]> {
580
- return this.memorySearch.searchByTimeRange(userAddress, startDate, endDate, additionalFilters);
581
- }
582
-
583
- // ==================== KNOWLEDGE GRAPH OPERATIONS (Delegate to KnowledgeGraphManager) ====================
584
-
585
- /**
586
- * Upload with full indexing (HNSW + knowledge graph)
587
- */
588
- async uploadWithFullIndexing(
589
- content: string | Uint8Array,
590
- metadata: MemoryMetadata,
591
- userAddress: string,
592
- options: BlobUploadOptions
593
- ): Promise<WalrusUploadResult & { vectorId: number; graphExtracted: boolean }> {
594
- const result = await this.uploadWithIndexing(content, metadata, userAddress, options);
595
-
596
- let graphExtracted = false;
597
-
598
- if (this.graphService && typeof content === 'string') {
599
- try {
600
- const extractionResult = await this.knowledgeGraph.extractKnowledgeGraph(
601
- content,
602
- result.blobId,
603
- { confidenceThreshold: 0.6 }
604
- );
605
-
606
- if (extractionResult.confidence > 0.5) {
607
- this.knowledgeGraph.addToUserGraph(
608
- userAddress,
609
- extractionResult.entities,
610
- extractionResult.relationships,
611
- result.blobId
612
- );
613
- graphExtracted = true;
614
- }
615
- } catch (error) {
616
- console.warn('⚠️ Knowledge graph extraction failed:', error);
617
- }
618
- }
619
-
620
- return {
621
- ...result,
622
- graphExtracted
623
- };
624
- }
625
-
626
- /**
627
- * Extract knowledge graph from content
628
- */
629
- async extractKnowledgeGraph(
630
- content: string,
631
- memoryId: string,
632
- options: {
633
- confidenceThreshold?: number;
634
- includeEmbeddings?: boolean;
635
- } = {}
636
- ): Promise<GraphExtractionResult> {
637
- return this.knowledgeGraph.extractKnowledgeGraph(content, memoryId, options);
638
- }
639
-
640
- /**
641
- * Extract knowledge graph and store in user's graph
642
- *
643
- * Combines extraction and storage in one operation.
644
- * Used by memory.create() pipeline.
645
- */
646
- async extractAndStoreKnowledgeGraph(
647
- content: string,
648
- memoryId: string,
649
- userAddress: string,
650
- options: {
651
- confidenceThreshold?: number;
652
- includeEmbeddings?: boolean;
653
- } = {}
654
- ): Promise<GraphExtractionResult> {
655
- // Extract entities and relationships
656
- const result = await this.knowledgeGraph.extractKnowledgeGraph(content, memoryId, options);
657
-
658
- // Store in user's graph if extraction was successful
659
- if (result.confidence > 0.5 && (result.entities.length > 0 || result.relationships.length > 0)) {
660
- try {
661
- // Ensure user graph exists
662
- await this.knowledgeGraph.getUserKnowledgeGraph(userAddress);
663
-
664
- // Add to user's graph
665
- this.knowledgeGraph.addToUserGraph(
666
- userAddress,
667
- result.entities,
668
- result.relationships,
669
- memoryId
670
- );
671
- } catch (storeError) {
672
- console.warn('Failed to store knowledge graph:', storeError);
673
- // Don't throw - extraction was successful, storage is optional
674
- }
675
- }
676
-
677
- return result;
678
- }
679
-
680
- /**
681
- * Search knowledge graph
682
- */
683
- async searchKnowledgeGraph(
684
- userAddress: string,
685
- query: {
686
- keywords?: string[];
687
- entityTypes?: string[];
688
- relationshipTypes?: string[];
689
- searchText?: string;
690
- maxHops?: number;
691
- limit?: number;
692
- }
693
- ) {
694
- return this.knowledgeGraph.searchKnowledgeGraph(userAddress, query);
695
- }
696
-
697
- /**
698
- * Find related entities
699
- */
700
- async findRelatedEntities(
701
- userAddress: string,
702
- seedEntityIds: string[],
703
- options: {
704
- maxHops?: number;
705
- relationshipTypes?: string[];
706
- includeWeights?: boolean;
707
- } = {}
708
- ) {
709
- return this.knowledgeGraph.findRelatedEntities(userAddress, seedEntityIds, options);
710
- }
711
-
712
- /**
713
- * Batch extract knowledge graphs
714
- */
715
- async extractKnowledgeGraphBatch(
716
- memories: Array<{ id: string; content: string }>,
717
- userAddress: string,
718
- options: {
719
- batchSize?: number;
720
- delayMs?: number;
721
- confidenceThreshold?: number;
722
- } = {}
723
- ): Promise<GraphExtractionResult[]> {
724
- return this.knowledgeGraph.extractKnowledgeGraphBatch(memories, userAddress, options);
725
- }
726
-
727
- /**
728
- * Get user's knowledge graph
729
- */
730
- async getUserKnowledgeGraph(userAddress: string): Promise<KnowledgeGraph> {
731
- return this.knowledgeGraph.getUserKnowledgeGraph(userAddress);
732
- }
733
-
734
- /**
735
- * Save knowledge graph to Walrus
736
- */
737
- async saveKnowledgeGraphToWalrus(userAddress: string): Promise<string | null> {
738
- const graph = await this.knowledgeGraph.getUserKnowledgeGraph(userAddress);
739
-
740
- if (!this.knowledgeGraph.isGraphDirty(userAddress)) {
741
- return null;
742
- }
743
-
744
- try {
745
- const graphData = this.knowledgeGraph.serializeGraph(userAddress);
746
- if (!graphData) return null;
747
-
748
- const graphBytes = new TextEncoder().encode(graphData);
749
-
750
- console.log(`💾 Saving knowledge graph for user ${userAddress} to Walrus...`);
751
- console.log(`📊 Graph size: ${graph.entities.length} entities, ${graph.relationships.length} relationships`);
752
-
753
- this.knowledgeGraph.markGraphAsSaved(userAddress);
754
-
755
- return `graph_${userAddress}_${Date.now()}`;
756
- } catch (error) {
757
- console.error('❌ Failed to save knowledge graph:', error);
758
- throw error;
759
- }
760
- }
761
-
762
- /**
763
- * Start background graph persistence
764
- */
765
- startGraphPersistence(intervalMs: number = 5 * 60 * 1000) {
766
- if (!this.graphService) {
767
- console.warn('Knowledge Graph not initialized - skipping persistence setup');
768
- return;
769
- }
770
-
771
- console.log(`🔄 Starting knowledge graph auto-persistence (every ${intervalMs / 1000}s)`);
772
-
773
- setInterval(async () => {
774
- const users = this.knowledgeGraph.getCachedUsers();
775
- for (const userAddress of users) {
776
- if (this.knowledgeGraph.isGraphDirty(userAddress)) {
777
- try {
778
- const blobId = await this.saveKnowledgeGraphToWalrus(userAddress);
779
- if (blobId) {
780
- console.log(`💾 Auto-saved knowledge graph for ${userAddress}: ${blobId}`);
781
- }
782
- } catch (error) {
783
- console.error(`Failed to auto-save knowledge graph for ${userAddress}:`, error);
784
- }
785
- }
786
- }
787
- }, intervalMs);
788
- }
789
-
790
- /**
791
- * Get graph statistics
792
- */
793
- getGraphStatistics(userAddress: string) {
794
- return this.knowledgeGraph.getGraphStatistics(userAddress);
795
- }
796
-
797
- /**
798
- * Get knowledge graph analytics
799
- */
800
- getKnowledgeGraphAnalytics(userAddress: string) {
801
- return this.knowledgeGraph.getKnowledgeGraphAnalytics(userAddress);
802
- }
803
-
804
- // ==================== QUILT BATCH OPERATIONS (Delegate to QuiltBatchManager) ====================
805
-
806
- /**
807
- * Upload multiple memories as a Quilt
808
- */
809
- async uploadMemoryBatch(
810
- memories: Array<{
811
- content: string;
812
- category: string;
813
- importance: number;
814
- topic: string;
815
- embedding: number[];
816
- encryptedContent: Uint8Array;
817
- summary?: string;
818
- }>,
819
- options: {
820
- signer: UnifiedSigner;
821
- epochs?: number;
822
- userAddress: string;
823
- }
824
- ): Promise<{
825
- quiltId: string;
826
- files: Array<{ identifier: string; blobId: string }>;
827
- uploadTimeMs: number;
828
- }> {
829
- return this.quiltBatch.uploadMemoryBatch(memories, options);
830
- }
831
-
832
- /**
833
- * Retrieve all files from a Quilt
834
- */
835
- async getQuiltFiles(quiltId: string): Promise<Array<WalrusFile>> {
836
- return this.quiltBatch.getQuiltFiles(quiltId);
837
- }
838
-
839
- /**
840
- * Query Quilt files by tags
841
- */
842
- async getQuiltFilesByTags(
843
- quiltId: string,
844
- tagFilters: Array<Record<string, string>>
845
- ): Promise<Array<WalrusFile>> {
846
- return this.quiltBatch.getQuiltFilesByTags(quiltId, tagFilters);
847
- }
848
-
849
- /**
850
- * Upload raw files as a Quilt (non-memory data)
851
- */
852
- async uploadFilesBatch(
853
- files: Array<{
854
- identifier: string;
855
- data: Uint8Array;
856
- tags?: Record<string, string>;
857
- }>,
858
- options: {
859
- signer: UnifiedSigner;
860
- epochs?: number;
861
- userAddress: string;
862
- }
863
- ): Promise<{
864
- quiltId: string;
865
- files: Array<{ identifier: string; blobId: string }>;
866
- uploadTimeMs: number;
867
- totalSize: number;
868
- gasSaved: string;
869
- }> {
870
- return this.quiltBatch.uploadFilesBatch(files, options);
871
- }
872
-
873
- /**
874
- * Retrieve a specific file by identifier from a Quilt
875
- */
876
- async getFileByIdentifier(
877
- quiltId: string,
878
- identifier: string
879
- ): Promise<{
880
- identifier: string;
881
- content: Uint8Array;
882
- tags: Record<string, string>;
883
- retrievalTimeMs: number;
884
- }> {
885
- return this.quiltBatch.getFileByIdentifier(quiltId, identifier);
886
- }
887
-
888
- /**
889
- * Query files by category from a Quilt
890
- */
891
- async getFilesByCategory(
892
- quiltId: string,
893
- category: string
894
- ): Promise<Array<WalrusFile>> {
895
- return this.quiltBatch.getFilesByCategory(quiltId, category);
896
- }
897
-
898
- /**
899
- * Query files by importance threshold from a Quilt
900
- */
901
- async getFilesByImportance(
902
- quiltId: string,
903
- minImportance: number
904
- ): Promise<Array<WalrusFile>> {
905
- return this.quiltBatch.getFilesByImportance(quiltId, minImportance);
906
- }
907
-
908
- /**
909
- * List all patches in a Quilt with their metadata
910
- */
911
- async listQuiltPatches(quiltId: string): Promise<Array<{
912
- identifier: string;
913
- quiltPatchId: string;
914
- tags: Record<string, string>;
915
- }>> {
916
- return this.quiltBatch.listQuiltPatches(quiltId);
917
- }
918
-
919
- // ==================== BLOB ATTRIBUTES (Delegate to BlobAttributesManager) ====================
920
-
921
- /**
922
- * Set attributes on a Blob object
923
- */
924
- async setBlobAttributes(
925
- blobObjectId: string,
926
- attributes: Record<string, string>,
927
- signer: UnifiedSigner
928
- ): Promise<string> {
929
- return this.blobAttributes.setBlobAttributes(blobObjectId, attributes, signer);
930
- }
931
-
932
- /**
933
- * Get attributes from a Blob object
934
- */
935
- async getBlobAttributes(
936
- blobObjectId: string,
937
- attributeKeys?: string[]
938
- ): Promise<Record<string, string>> {
939
- return this.blobAttributes.getBlobAttributes(blobObjectId, attributeKeys);
940
- }
941
-
942
- /**
943
- * Update blob attributes
944
- */
945
- async updateBlobAttributes(
946
- blobObjectId: string,
947
- attributes: Record<string, string>,
948
- signer: UnifiedSigner
949
- ): Promise<string> {
950
- return this.blobAttributes.updateBlobAttributes(blobObjectId, attributes, signer);
951
- }
952
-
953
- /**
954
- * Remove blob attributes
955
- */
956
- async removeBlobAttributes(
957
- blobObjectId: string,
958
- attributeKeys: string[],
959
- signer: UnifiedSigner
960
- ): Promise<string> {
961
- return this.blobAttributes.removeBlobAttributes(blobObjectId, attributeKeys, signer);
962
- }
963
-
964
- /**
965
- * Query memories by attributes
966
- */
967
- async queryMemoriesByAttributes(
968
- filters: Record<string, string>,
969
- owner: string,
970
- walrusPackageId: string
971
- ): Promise<Array<{
972
- blobObjectId: string;
973
- blobId: string;
974
- attributes: Record<string, string>;
975
- }>> {
976
- return this.blobAttributes.queryMemoriesByAttributes(filters, owner, walrusPackageId);
977
- }
978
-
979
- // ==================== METADATA OPERATIONS (Delegate to WalrusMetadataManager) ====================
980
-
981
- /**
982
- * Build Walrus metadata structure
983
- */
984
- private buildWalrusMetadata(
985
- contentSize: number,
986
- options: {
987
- category?: string;
988
- topic?: string;
989
- importance?: number;
990
- embedding?: number[];
991
- embeddingBlobId?: string;
992
- graphBlobId?: string;
993
- graphEntityIds?: string[];
994
- graphEntityCount?: number;
995
- graphRelationshipCount?: number;
996
- vectorId?: number;
997
- isEncrypted?: boolean;
998
- encryptionType?: string;
999
- sealIdentity?: string;
1000
- customFields?: Record<string, string>;
1001
- }
1002
- ): WalrusMemoryMetadata {
1003
- return this.walrusMetadata.buildWalrusMetadata(contentSize, options);
1004
- }
1005
-
1006
- /**
1007
- * Attach metadata to a Blob object
1008
- */
1009
- async attachMetadataToBlob(
1010
- blobId: string,
1011
- metadata: WalrusMemoryMetadata,
1012
- signer: UnifiedSigner
1013
- ): Promise<{ digest: string; effects: any }> {
1014
- const walrusPackageId = this.config.network === 'mainnet'
1015
- ? '0x<mainnet-walrus-package-id>'
1016
- : '0x<testnet-walrus-package-id>';
1017
-
1018
- return this.walrusMetadata.attachMetadataToBlob(blobId, metadata, signer, walrusPackageId);
1019
- }
1020
-
1021
- /**
1022
- * Retrieve metadata from a Blob object
1023
- */
1024
- async retrieveBlobMetadata(blobObjectId: string): Promise<WalrusMemoryMetadata | null> {
1025
- return this.walrusMetadata.retrieveBlobMetadata(blobObjectId);
1026
- }
1027
-
1028
- // ==================== ANALYTICS AND STATS ====================
1029
-
1030
- /**
1031
- * Get search analytics
1032
- */
1033
- getSearchAnalytics(userAddress: string) {
1034
- return this.memorySearch.getSearchAnalytics(userAddress);
1035
- }
1036
-
1037
- /**
1038
- * Get storage statistics
1039
- */
1040
- async getStats() {
1041
- const memoryStats = await this.memorySearch.getServiceStats();
1042
-
1043
- return {
1044
- network: this.config.network || 'testnet',
1045
- useUploadRelay: this.config.useUploadRelay ?? true,
1046
- epochs: this.config.epochs || 3,
1047
- hasEncryption: !!this.config.sealService,
1048
- hasBatching: !!this.config.batchService,
1049
- hasSearch: !!(this.embeddingService && this.memoryIndexService),
1050
- indexedUsers: memoryStats?.totalUsers || 0,
1051
- totalIndexedMemories: memoryStats?.totalMemories || 0,
1052
- memoryIndexStats: memoryStats
1053
- };
1054
- }
1055
-
1056
- // ==================== COMPATIBILITY METHODS ====================
1057
-
1058
- /**
1059
- * Legacy upload method for backward compatibility
1060
- */
1061
- async upload(
1062
- content: Uint8Array | string,
1063
- metadata: MemoryMetadata,
1064
- options?: Partial<BlobUploadOptions>
1065
- ): Promise<WalrusUploadResult> {
1066
- const data = typeof content === 'string' ? new TextEncoder().encode(content) : content;
1067
-
1068
- const uploadOptions: BlobUploadOptions = {
1069
- signer: options?.signer!,
1070
- epochs: options?.epochs ?? this.config.epochs ?? 3,
1071
- deletable: options?.deletable ?? true,
1072
- useUploadRelay: options?.useUploadRelay,
1073
- encrypt: options?.encrypt,
1074
- metadata: {
1075
- 'content-type': metadata.contentType,
1076
- 'category': metadata.category,
1077
- 'topic': metadata.topic,
1078
- 'importance': metadata.importance.toString(),
1079
- ...(options?.metadata || {})
1080
- }
1081
- };
1082
-
1083
- return this.uploadBlob(data, uploadOptions);
1084
- }
1085
-
1086
- /**
1087
- * Legacy retrieve method for backward compatibility
1088
- */
1089
- async retrieve(blobId: string): Promise<{
1090
- content: Uint8Array;
1091
- metadata: MemoryMetadata;
1092
- }> {
1093
- const result = await this.retrieveMemoryPackage(blobId);
1094
-
1095
- return {
1096
- content: result.content,
1097
- metadata: result.metadata
1098
- };
1099
- }
1100
-
1101
- /**
1102
- * Legacy list method (not implemented)
1103
- */
1104
- async list(filter?: any): Promise<Array<{
1105
- blobId: string;
1106
- metadata: MemoryMetadata
1107
- }>> {
1108
- console.warn('StorageService.list() not yet implemented - requires metadata storage');
1109
- return [];
1110
- }
1111
- }
1
+ /**
2
+ * StorageService - Refactored with Manager Delegation
3
+ *
4
+ * This is a coordinator service that delegates to specialized managers:
5
+ * - WalrusStorageManager: Core Walrus operations
6
+ * - MemorySearchManager: Memory indexing and search
7
+ * - KnowledgeGraphManager: Knowledge graph operations
8
+ * - WalrusMetadataManager: Metadata operations
9
+ * - QuiltBatchManager: Batch uploads
10
+ * - BlobAttributesManager: Dynamic field operations
11
+ *
12
+ * Maintains full backward compatibility with original StorageService API.
13
+ */
14
+
15
+ import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
16
+ import { Transaction } from '@mysten/sui/transactions';
17
+ import { WalrusClient, WalrusFile } from '@mysten/walrus';
18
+ import type { UnifiedSigner } from '../client/signers/UnifiedSigner';
19
+ import type { ClientWithExtensions } from '@mysten/sui/experimental';
20
+ import type { SealService } from '../infrastructure/seal/SealService';
21
+ import type { BatchService } from './BatchService';
22
+ import { PDWConfig } from '../core';
23
+ import { MemoryIndexService } from './MemoryIndexService';
24
+ import { EmbeddingService, type EmbeddingOptions } from './EmbeddingService';
25
+ import { GraphService, type KnowledgeGraph, type Entity, type Relationship, type GraphExtractionResult } from '../graph/GraphService';
26
+
27
+ // Import managers
28
+ import { WalrusStorageManager } from './storage/WalrusStorageManager';
29
+ import { MemorySearchManager } from './storage/MemorySearchManager';
30
+ import { KnowledgeGraphManager } from './storage/KnowledgeGraphManager';
31
+ import { WalrusMetadataManager } from './storage/WalrusMetadataManager';
32
+ import { QuiltBatchManager } from './storage/QuiltBatchManager';
33
+ import { BlobAttributesManager } from './storage/BlobAttributesManager';
34
+
35
+ // Re-export types for backward compatibility
36
+ export interface StorageServiceConfig extends PDWConfig {
37
+ suiClient?: SuiClient;
38
+ network?: 'testnet' | 'mainnet';
39
+ maxFileSize?: number;
40
+ timeout?: number;
41
+ useUploadRelay?: boolean;
42
+ epochs?: number;
43
+ sealService?: SealService;
44
+ batchService?: BatchService;
45
+ }
46
+
47
+ export interface MemoryMetadata {
48
+ contentType: string;
49
+ contentSize: number;
50
+ contentHash: string;
51
+ category: string;
52
+ topic: string;
53
+ importance: number;
54
+ embeddingBlobId?: string;
55
+ embeddingDimension: number;
56
+ createdTimestamp: number;
57
+ updatedTimestamp?: number;
58
+ customMetadata?: Record<string, string>;
59
+ isEncrypted?: boolean;
60
+ encryptionType?: string;
61
+ }
62
+
63
+ export interface WalrusUploadResult {
64
+ blobId: string;
65
+ metadata: MemoryMetadata;
66
+ embeddingBlobId?: string;
67
+ isEncrypted: boolean;
68
+ backupKey?: string;
69
+ storageEpochs: number;
70
+ uploadTimeMs: number;
71
+ }
72
+
73
+ export interface BlobUploadOptions {
74
+ signer: UnifiedSigner;
75
+ epochs?: number;
76
+ deletable?: boolean;
77
+ useUploadRelay?: boolean;
78
+ encrypt?: boolean;
79
+ metadata?: Record<string, string>;
80
+ }
81
+
82
+ export interface FileUploadOptions extends BlobUploadOptions {
83
+ files: Array<{
84
+ identifier: string;
85
+ content: Uint8Array | string;
86
+ tags?: Record<string, string>;
87
+ }>;
88
+ }
89
+
90
+ export interface WalrusMemoryMetadata {
91
+ content_type: string;
92
+ content_size: string;
93
+ category: string;
94
+ topic: string;
95
+ importance: string;
96
+ embedding_dimensions: string;
97
+ embedding_model: string;
98
+ embedding_blob_id?: string;
99
+ graph_entity_count: string;
100
+ graph_relationship_count: string;
101
+ graph_blob_id?: string;
102
+ graph_entity_ids?: string;
103
+ vector_id: string;
104
+ vector_status: string;
105
+ created_at: string;
106
+ updated_at: string;
107
+ deleted_at?: string;
108
+ encrypted: string;
109
+ encryption_type?: string;
110
+ seal_identity?: string;
111
+ [key: string]: string | undefined;
112
+ }
113
+
114
+ export interface WalrusMetadataOptions {
115
+ attachMetadata?: boolean;
116
+ walrusMetadata?: Partial<WalrusMemoryMetadata>;
117
+ embeddingBlobId?: string;
118
+ graphBlobId?: string;
119
+ vectorId?: number;
120
+ graphEntityIds?: string[];
121
+ }
122
+
123
+ export interface BlobUploadOptionsWithMetadata extends BlobUploadOptions, WalrusMetadataOptions {}
124
+
125
+ export interface MetadataSearchQuery {
126
+ query?: string;
127
+ vector?: number[];
128
+ filters?: {
129
+ category?: string | string[];
130
+ topic?: string | string[];
131
+ importance?: { min?: number; max?: number };
132
+ contentType?: string | string[];
133
+ dateRange?: { start?: Date; end?: Date };
134
+ tags?: string[];
135
+ contentSize?: { min?: number; max?: number };
136
+ };
137
+ k?: number;
138
+ threshold?: number;
139
+ includeContent?: boolean;
140
+ useCache?: boolean;
141
+ }
142
+
143
+ export interface MetadataSearchResult {
144
+ blobId: string;
145
+ content?: string | Uint8Array;
146
+ metadata: MemoryMetadata;
147
+ similarity: number;
148
+ relevanceScore: number;
149
+ }
150
+
151
+ export interface IndexedMemoryEntry {
152
+ blobId: string;
153
+ vectorId: number;
154
+ metadata: MemoryMetadata;
155
+ vector: number[];
156
+ }
157
+
158
+ /**
159
+ * StorageService - Refactored with Manager Delegation
160
+ */
161
+ export class StorageService {
162
+ // Managers
163
+ private walrusStorage: WalrusStorageManager;
164
+ private memorySearch: MemorySearchManager;
165
+ private knowledgeGraph: KnowledgeGraphManager;
166
+ private walrusMetadata: WalrusMetadataManager;
167
+ private quiltBatch: QuiltBatchManager;
168
+ private blobAttributes: BlobAttributesManager;
169
+
170
+ // Legacy properties for backward compatibility
171
+ private suiClient: ClientWithExtensions<{ jsonRpc: SuiClient; walrus: WalrusClient }>;
172
+ private memoryIndexService?: MemoryIndexService;
173
+ private embeddingService?: EmbeddingService;
174
+ private graphService?: GraphService;
175
+
176
+ constructor(private config: StorageServiceConfig) {
177
+ // Initialize WalrusStorageManager
178
+ this.walrusStorage = new WalrusStorageManager({
179
+ suiClient: config.suiClient,
180
+ network: config.network,
181
+ maxFileSize: config.maxFileSize,
182
+ timeout: config.timeout,
183
+ useUploadRelay: config.useUploadRelay,
184
+ epochs: config.epochs
185
+ });
186
+
187
+ // Initialize MemorySearchManager
188
+ this.memorySearch = new MemorySearchManager();
189
+
190
+ // Initialize KnowledgeGraphManager
191
+ this.knowledgeGraph = new KnowledgeGraphManager();
192
+
193
+ // Get SuiClient from WalrusStorageManager
194
+ this.suiClient = this.walrusStorage.getSuiClient();
195
+
196
+ // Initialize WalrusMetadataManager
197
+ this.walrusMetadata = new WalrusMetadataManager(this.suiClient.jsonRpc);
198
+
199
+ // Initialize QuiltBatchManager
200
+ this.quiltBatch = new QuiltBatchManager(
201
+ this.walrusStorage.getWalrusClient(true),
202
+ this.walrusStorage.getWalrusClient(false),
203
+ this.suiClient,
204
+ config.useUploadRelay ?? true,
205
+ config.epochs || 3
206
+ );
207
+
208
+ // Initialize BlobAttributesManager
209
+ this.blobAttributes = new BlobAttributesManager(this.suiClient.jsonRpc);
210
+
211
+ console.log('✅ StorageService initialized with manager delegation');
212
+ }
213
+
214
+ // ==================== INITIALIZATION METHODS ====================
215
+
216
+ /**
217
+ * Initialize memory indexing and search capabilities
218
+ */
219
+ initializeSearch(embeddingService: EmbeddingService, memoryIndexService?: MemoryIndexService) {
220
+ this.embeddingService = embeddingService;
221
+ this.memoryIndexService = memoryIndexService || new MemoryIndexService(this);
222
+
223
+ this.memorySearch.initializeSearch(embeddingService, this.memoryIndexService);
224
+
225
+ console.log('✅ StorageService: Memory indexing and search capabilities initialized');
226
+ }
227
+
228
+ /**
229
+ * Initialize Knowledge Graph capabilities
230
+ */
231
+ async initializeKnowledgeGraph(graphConfig?: any) {
232
+ this.graphService = await this.knowledgeGraph.initializeKnowledgeGraph(
233
+ this.embeddingService,
234
+ graphConfig
235
+ );
236
+ return this.graphService;
237
+ }
238
+
239
+ // ==================== CORE WALRUS OPERATIONS (Delegate to WalrusStorageManager) ====================
240
+
241
+ /**
242
+ * Upload single blob using writeBlobFlow pattern
243
+ */
244
+ async uploadBlob(
245
+ data: Uint8Array,
246
+ options: BlobUploadOptions
247
+ ): Promise<WalrusUploadResult> {
248
+ const result = await this.walrusStorage.uploadBlob(data, options);
249
+
250
+ // Convert to legacy format
251
+ const metadata: MemoryMetadata = {
252
+ contentType: options.metadata?.['content-type'] || 'application/octet-stream',
253
+ contentSize: result.contentSize,
254
+ contentHash: result.blobId, // Walrus blob_id serves as content hash
255
+ category: options.metadata?.category || 'default',
256
+ topic: options.metadata?.topic || '',
257
+ importance: parseInt(options.metadata?.importance || '5'),
258
+ embeddingDimension: parseInt(options.metadata?.['embedding-dimensions'] || '0'),
259
+ createdTimestamp: Date.now(),
260
+ customMetadata: options.metadata,
261
+ isEncrypted: result.isEncrypted,
262
+ encryptionType: result.isEncrypted ? 'seal' : undefined,
263
+ };
264
+
265
+ // Handle metadata attachment if requested
266
+ if ((options as BlobUploadOptionsWithMetadata).attachMetadata && result.blobObjectId) {
267
+ const metadataOptions = options as BlobUploadOptionsWithMetadata;
268
+ const walrusMetadata = this.buildWalrusMetadata(
269
+ result.contentSize,
270
+ {
271
+ category: metadata.category,
272
+ topic: metadata.topic,
273
+ importance: metadata.importance,
274
+ embeddingBlobId: metadataOptions.embeddingBlobId,
275
+ graphBlobId: metadataOptions.graphBlobId,
276
+ graphEntityIds: metadataOptions.graphEntityIds,
277
+ vectorId: metadataOptions.vectorId,
278
+ isEncrypted: result.isEncrypted,
279
+ encryptionType: metadata.encryptionType,
280
+ sealIdentity: options.metadata?.['seal-identity'],
281
+ customFields: options.metadata,
282
+ }
283
+ );
284
+
285
+ // Attach as attributes
286
+ try {
287
+ const attributes: Record<string, string> = {
288
+ memory_category: walrusMetadata.category,
289
+ memory_topic: walrusMetadata.topic,
290
+ memory_importance: walrusMetadata.importance,
291
+ memory_encrypted: walrusMetadata.encrypted,
292
+ memory_encryption_type: walrusMetadata.encryption_type || 'none',
293
+ memory_content_size: walrusMetadata.content_size,
294
+ memory_created_at: walrusMetadata.created_at,
295
+ };
296
+
297
+ if (walrusMetadata.vector_id) {
298
+ attributes.memory_vector_id = walrusMetadata.vector_id;
299
+ }
300
+ if (walrusMetadata.embedding_blob_id) {
301
+ attributes.memory_embedding_blob_id = walrusMetadata.embedding_blob_id;
302
+ }
303
+ if (walrusMetadata.graph_blob_id) {
304
+ attributes.memory_graph_blob_id = walrusMetadata.graph_blob_id;
305
+ }
306
+ if (walrusMetadata.seal_identity) {
307
+ attributes.memory_seal_identity = walrusMetadata.seal_identity;
308
+ }
309
+
310
+ await this.blobAttributes.setBlobAttributes(
311
+ result.blobObjectId,
312
+ attributes,
313
+ options.signer
314
+ );
315
+ } catch (error) {
316
+ console.warn('⚠️ Failed to attach metadata (non-fatal):', error);
317
+ }
318
+ }
319
+
320
+ return {
321
+ blobId: result.blobId,
322
+ metadata,
323
+ isEncrypted: result.isEncrypted,
324
+ storageEpochs: result.storageEpochs,
325
+ uploadTimeMs: result.uploadTimeMs,
326
+ };
327
+ }
328
+
329
+ /**
330
+ * Upload memory package with SEAL encrypted content
331
+ */
332
+ async uploadMemoryPackage(
333
+ memoryData: {
334
+ content: string;
335
+ embedding: number[];
336
+ metadata: Record<string, any>;
337
+ encryptedContent?: Uint8Array;
338
+ encryptedEmbedding?: Uint8Array; // NEW: encrypted embedding for fast index rebuild
339
+ encryptionType?: string;
340
+ identity?: string;
341
+ },
342
+ options: BlobUploadOptions
343
+ ): Promise<WalrusUploadResult> {
344
+ let dataToUpload: Uint8Array;
345
+ let storageApproach: 'direct-binary' | 'json-package';
346
+ let uploadMetadata: Record<string, string>;
347
+
348
+ if (memoryData.encryptedContent && memoryData.encryptedContent instanceof Uint8Array) {
349
+ // Option A v2: Full Encryption - both content AND embedding encrypted
350
+ // Allows fast index rebuild by decrypting embedding (no re-embed API calls)
351
+ // Maximum privacy - no data leakage on Walrus
352
+ storageApproach = 'json-package';
353
+
354
+ // Convert encrypted content to base64
355
+ const encryptedContentBase64 = btoa(String.fromCharCode(...memoryData.encryptedContent));
356
+
357
+ // Convert encrypted embedding to base64 (if available)
358
+ const encryptedEmbeddingBase64 = memoryData.encryptedEmbedding
359
+ ? btoa(String.fromCharCode(...memoryData.encryptedEmbedding))
360
+ : null;
361
+
362
+ const memoryPackage = {
363
+ // Encrypted content as base64 (requires SEAL decrypt to read)
364
+ encryptedContent: encryptedContentBase64,
365
+ // Encrypted embedding as base64 (for fast index rebuild without re-embed)
366
+ encryptedEmbedding: encryptedEmbeddingBase64,
367
+ // Metadata including capability info for decryption
368
+ metadata: {
369
+ ...memoryData.metadata,
370
+ encryptionType: memoryData.encryptionType || 'seal-real',
371
+ identity: memoryData.identity,
372
+ // Store embedding dimension for reference
373
+ embeddingDimension: memoryData.embedding?.length || 0,
374
+ },
375
+ // Package metadata
376
+ encrypted: true,
377
+ timestamp: Date.now(),
378
+ version: '2.2' // v2.2 = Full encryption (content + embedding both encrypted)
379
+ };
380
+
381
+ const payloadString = JSON.stringify(memoryPackage);
382
+ dataToUpload = new TextEncoder().encode(payloadString);
383
+
384
+ uploadMetadata = {
385
+ 'content-type': 'application/json',
386
+ 'encryption-type': memoryData.encryptionType || 'seal-real',
387
+ 'context-id': `memory-${memoryData.identity || 'unknown'}`,
388
+ 'app-id': 'pdw-sdk',
389
+ 'encrypted': 'true',
390
+ 'seal-identity': memoryData.identity || '',
391
+ 'version': '2.2',
392
+ 'category': memoryData.metadata.category || 'memory',
393
+ 'created-at': new Date().toISOString(),
394
+ 'original-content-type': 'text/plain',
395
+ 'embedding-dimensions': (memoryData.embedding?.length || 0).toString(),
396
+ 'embedding-encrypted': memoryData.encryptedEmbedding ? 'true' : 'false',
397
+ 'storage-approach': storageApproach
398
+ };
399
+
400
+ console.log(`🔐 Option A v2: Full encryption - content + embedding encrypted (${memoryData.embedding?.length || 0}D)`);
401
+ } else {
402
+ // JSON package storage
403
+ storageApproach = 'json-package';
404
+
405
+ const memoryPackage = {
406
+ content: memoryData.content,
407
+ embedding: memoryData.embedding,
408
+ metadata: memoryData.metadata,
409
+ encrypted: memoryData.encryptedContent ? {
410
+ encryptedContent: memoryData.encryptedContent,
411
+ encryptionType: memoryData.encryptionType,
412
+ identity: memoryData.identity,
413
+ timestamp: Date.now()
414
+ } : null,
415
+ timestamp: Date.now(),
416
+ version: '1.0'
417
+ };
418
+
419
+ const payloadString = JSON.stringify(memoryPackage);
420
+ dataToUpload = new TextEncoder().encode(payloadString);
421
+
422
+ uploadMetadata = {
423
+ 'content-type': 'application/json',
424
+ 'encryption-type': memoryData.encryptionType || 'none',
425
+ 'context-id': `memory-${memoryData.identity || 'unknown'}`,
426
+ 'app-id': 'pdw-sdk',
427
+ 'encrypted': memoryData.encryptionType?.includes('seal') ? 'true' : 'false',
428
+ 'version': '1.0',
429
+ 'category': memoryData.metadata.category || 'memory',
430
+ 'created-at': new Date().toISOString(),
431
+ 'storage-approach': storageApproach
432
+ };
433
+ }
434
+
435
+ const result = await this.uploadBlob(dataToUpload, {
436
+ ...options,
437
+ metadata: uploadMetadata
438
+ });
439
+
440
+ return {
441
+ ...result,
442
+ metadata: {
443
+ ...result.metadata,
444
+ customMetadata: {
445
+ ...result.metadata.customMetadata,
446
+ 'storage-approach': storageApproach
447
+ }
448
+ }
449
+ };
450
+ }
451
+
452
+ /**
453
+ * Retrieve blob by ID directly from Walrus
454
+ */
455
+ async getBlob(blobId: string): Promise<Uint8Array> {
456
+ return this.walrusStorage.getBlob(blobId);
457
+ }
458
+
459
+ /**
460
+ * Retrieve blob with detailed logging
461
+ */
462
+ async retrieveFromWalrusOnly(blobId: string): Promise<{
463
+ content: Uint8Array;
464
+ source: 'walrus';
465
+ retrievalTime: number;
466
+ blobSize: number;
467
+ }> {
468
+ return this.walrusStorage.retrieveBlob(blobId);
469
+ }
470
+
471
+ /**
472
+ * Retrieve memory package from Walrus with format detection
473
+ */
474
+ async retrieveMemoryPackage(blobId: string): Promise<{
475
+ content: Uint8Array;
476
+ storageApproach: 'direct-binary' | 'json-package' | 'unknown';
477
+ metadata: MemoryMetadata;
478
+ memoryPackage?: any;
479
+ isEncrypted: boolean;
480
+ source: 'walrus';
481
+ retrievalTime: number;
482
+ }> {
483
+ const startTime = Date.now();
484
+ const content = await this.getBlob(blobId);
485
+
486
+ let storageApproach: 'direct-binary' | 'json-package' | 'unknown' = 'unknown';
487
+ let memoryPackage: any = null;
488
+ let isEncrypted = false;
489
+
490
+ // Try to parse as JSON
491
+ try {
492
+ const contentString = new TextDecoder().decode(content);
493
+ memoryPackage = JSON.parse(contentString);
494
+
495
+ // v2.2: JSON package with encrypted content + encrypted embedding
496
+ if (memoryPackage.version === '2.2' && memoryPackage.encryptedContent) {
497
+ storageApproach = 'json-package';
498
+ isEncrypted = true;
499
+ const embDim = memoryPackage.metadata?.embeddingDimension || 0;
500
+ console.log(`🔐 Detected v2.2 JSON package: encrypted content + encrypted embedding (${embDim}D)`);
501
+ }
502
+ // v2.1: JSON package with encrypted content only (no embedding on Walrus)
503
+ else if (memoryPackage.version === '2.1' && memoryPackage.encryptedContent) {
504
+ storageApproach = 'json-package';
505
+ isEncrypted = true;
506
+ const embDim = memoryPackage.metadata?.embeddingDimension || 0;
507
+ console.log(`🔐 Detected v2.1 JSON package: encrypted content only (embedding ${embDim}D stored locally)`);
508
+ }
509
+ // v2.0: JSON package with encrypted content + plaintext embedding (legacy)
510
+ else if (memoryPackage.version === '2.0' && memoryPackage.encryptedContent && memoryPackage.embedding) {
511
+ storageApproach = 'json-package';
512
+ isEncrypted = true;
513
+ console.log(`📦 Detected v2.0 JSON package: encrypted content + ${memoryPackage.embedding.length}D plaintext embedding`);
514
+ }
515
+ // v1.0: JSON package with plaintext content + embedding
516
+ else if (memoryPackage.version && memoryPackage.content && memoryPackage.embedding) {
517
+ storageApproach = 'json-package';
518
+ isEncrypted = false;
519
+ console.log(`📦 Detected v1.0 JSON package: plaintext content + ${memoryPackage.embedding.length}D embedding`);
520
+ }
521
+ } catch (parseError) {
522
+ // Not JSON - likely legacy binary SEAL data (v0)
523
+ const isBinary = content.some(byte => byte < 32 && byte !== 9 && byte !== 10 && byte !== 13);
524
+ const hasHighBytes = content.some(byte => byte > 127);
525
+
526
+ if (isBinary || hasHighBytes || content.length > 50) {
527
+ storageApproach = 'direct-binary';
528
+ isEncrypted = true;
529
+ console.log(`📦 Detected legacy binary format (no embedding stored)`);
530
+ }
531
+ }
532
+
533
+ const metadata: MemoryMetadata = {
534
+ contentType: storageApproach === 'json-package' ? 'application/json' : 'application/octet-stream',
535
+ contentSize: content.length,
536
+ contentHash: '',
537
+ category: memoryPackage?.metadata?.category || 'unknown',
538
+ topic: memoryPackage?.metadata?.topic || 'unknown',
539
+ importance: memoryPackage?.metadata?.importance || 0,
540
+ embeddingDimension: memoryPackage?.embedding?.length || 0,
541
+ createdTimestamp: memoryPackage?.timestamp || Date.now(),
542
+ isEncrypted,
543
+ encryptionType: isEncrypted ? 'seal-real' : undefined
544
+ };
545
+
546
+ return {
547
+ content,
548
+ storageApproach,
549
+ metadata,
550
+ memoryPackage,
551
+ isEncrypted,
552
+ source: 'walrus' as const,
553
+ retrievalTime: Date.now() - startTime
554
+ };
555
+ }
556
+
557
+ // ==================== MEMORY SEARCH OPERATIONS (Delegate to MemorySearchManager) ====================
558
+
559
+ /**
560
+ * Upload with automatic memory indexing
561
+ */
562
+ async uploadWithIndexing(
563
+ content: string | Uint8Array,
564
+ metadata: MemoryMetadata,
565
+ userAddress: string,
566
+ options: BlobUploadOptions
567
+ ): Promise<WalrusUploadResult & { vectorId: number }> {
568
+ if (!this.embeddingService || !this.memoryIndexService) {
569
+ throw new Error('Search capabilities not initialized. Call initializeSearch() first.');
570
+ }
571
+
572
+ const uploadResult = await this.upload(content, metadata, options);
573
+
574
+ let textContent: string;
575
+ if (content instanceof Uint8Array) {
576
+ textContent = `${metadata.category} ${metadata.topic || ''} ${JSON.stringify(metadata.customMetadata || {})}`.trim();
577
+ } else {
578
+ textContent = content;
579
+ }
580
+
581
+ const memoryId = `memory_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
582
+ const indexResult = await this.memorySearch.indexMemory(
583
+ userAddress,
584
+ memoryId,
585
+ uploadResult.blobId,
586
+ textContent,
587
+ metadata
588
+ );
589
+
590
+ return {
591
+ ...uploadResult,
592
+ vectorId: indexResult.vectorId
593
+ };
594
+ }
595
+
596
+ /**
597
+ * Search memories by metadata
598
+ */
599
+ async searchByMetadata(
600
+ userAddress: string,
601
+ searchQuery: MetadataSearchQuery
602
+ ): Promise<MetadataSearchResult[]> {
603
+ return this.memorySearch.searchByMetadata(userAddress, searchQuery);
604
+ }
605
+
606
+ /**
607
+ * Get all indexed memories for a user
608
+ */
609
+ async getUserMemoriesWithMetadata(
610
+ userAddress: string,
611
+ filters?: MetadataSearchQuery['filters']
612
+ ): Promise<MetadataSearchResult[]> {
613
+ return this.memorySearch.getUserMemoriesWithMetadata(userAddress, filters);
614
+ }
615
+
616
+ /**
617
+ * Search by category
618
+ */
619
+ async searchByCategory(
620
+ userAddress: string,
621
+ category: string,
622
+ additionalFilters?: Omit<MetadataSearchQuery['filters'], 'category'>
623
+ ): Promise<MetadataSearchResult[]> {
624
+ return this.memorySearch.searchByCategory(userAddress, category, additionalFilters);
625
+ }
626
+
627
+ /**
628
+ * Search by time range
629
+ */
630
+ async searchByTimeRange(
631
+ userAddress: string,
632
+ startDate: Date,
633
+ endDate: Date,
634
+ additionalFilters?: Omit<MetadataSearchQuery['filters'], 'dateRange'>
635
+ ): Promise<MetadataSearchResult[]> {
636
+ return this.memorySearch.searchByTimeRange(userAddress, startDate, endDate, additionalFilters);
637
+ }
638
+
639
+ // ==================== KNOWLEDGE GRAPH OPERATIONS (Delegate to KnowledgeGraphManager) ====================
640
+
641
+ /**
642
+ * Upload with full indexing (HNSW + knowledge graph)
643
+ */
644
+ async uploadWithFullIndexing(
645
+ content: string | Uint8Array,
646
+ metadata: MemoryMetadata,
647
+ userAddress: string,
648
+ options: BlobUploadOptions
649
+ ): Promise<WalrusUploadResult & { vectorId: number; graphExtracted: boolean }> {
650
+ const result = await this.uploadWithIndexing(content, metadata, userAddress, options);
651
+
652
+ let graphExtracted = false;
653
+
654
+ if (this.graphService && typeof content === 'string') {
655
+ try {
656
+ const extractionResult = await this.knowledgeGraph.extractKnowledgeGraph(
657
+ content,
658
+ result.blobId,
659
+ { confidenceThreshold: 0.6 }
660
+ );
661
+
662
+ if (extractionResult.confidence > 0.5) {
663
+ this.knowledgeGraph.addToUserGraph(
664
+ userAddress,
665
+ extractionResult.entities,
666
+ extractionResult.relationships,
667
+ result.blobId
668
+ );
669
+ graphExtracted = true;
670
+ }
671
+ } catch (error) {
672
+ console.warn('⚠️ Knowledge graph extraction failed:', error);
673
+ }
674
+ }
675
+
676
+ return {
677
+ ...result,
678
+ graphExtracted
679
+ };
680
+ }
681
+
682
+ /**
683
+ * Extract knowledge graph from content
684
+ */
685
+ async extractKnowledgeGraph(
686
+ content: string,
687
+ memoryId: string,
688
+ options: {
689
+ confidenceThreshold?: number;
690
+ includeEmbeddings?: boolean;
691
+ } = {}
692
+ ): Promise<GraphExtractionResult> {
693
+ return this.knowledgeGraph.extractKnowledgeGraph(content, memoryId, options);
694
+ }
695
+
696
+ /**
697
+ * Extract knowledge graph and store in user's graph
698
+ *
699
+ * Combines extraction and storage in one operation.
700
+ * Used by memory.create() pipeline.
701
+ */
702
+ async extractAndStoreKnowledgeGraph(
703
+ content: string,
704
+ memoryId: string,
705
+ userAddress: string,
706
+ options: {
707
+ confidenceThreshold?: number;
708
+ includeEmbeddings?: boolean;
709
+ } = {}
710
+ ): Promise<GraphExtractionResult> {
711
+ // Extract entities and relationships
712
+ const result = await this.knowledgeGraph.extractKnowledgeGraph(content, memoryId, options);
713
+
714
+ // Store in user's graph if extraction was successful
715
+ if (result.confidence > 0.5 && (result.entities.length > 0 || result.relationships.length > 0)) {
716
+ try {
717
+ // Ensure user graph exists
718
+ await this.knowledgeGraph.getUserKnowledgeGraph(userAddress);
719
+
720
+ // Add to user's graph
721
+ this.knowledgeGraph.addToUserGraph(
722
+ userAddress,
723
+ result.entities,
724
+ result.relationships,
725
+ memoryId
726
+ );
727
+ } catch (storeError) {
728
+ console.warn('Failed to store knowledge graph:', storeError);
729
+ // Don't throw - extraction was successful, storage is optional
730
+ }
731
+ }
732
+
733
+ return result;
734
+ }
735
+
736
+ /**
737
+ * Search knowledge graph
738
+ */
739
+ async searchKnowledgeGraph(
740
+ userAddress: string,
741
+ query: {
742
+ keywords?: string[];
743
+ entityTypes?: string[];
744
+ relationshipTypes?: string[];
745
+ searchText?: string;
746
+ maxHops?: number;
747
+ limit?: number;
748
+ }
749
+ ) {
750
+ return this.knowledgeGraph.searchKnowledgeGraph(userAddress, query);
751
+ }
752
+
753
+ /**
754
+ * Find related entities
755
+ */
756
+ async findRelatedEntities(
757
+ userAddress: string,
758
+ seedEntityIds: string[],
759
+ options: {
760
+ maxHops?: number;
761
+ relationshipTypes?: string[];
762
+ includeWeights?: boolean;
763
+ } = {}
764
+ ) {
765
+ return this.knowledgeGraph.findRelatedEntities(userAddress, seedEntityIds, options);
766
+ }
767
+
768
+ /**
769
+ * Batch extract knowledge graphs
770
+ */
771
+ async extractKnowledgeGraphBatch(
772
+ memories: Array<{ id: string; content: string }>,
773
+ userAddress: string,
774
+ options: {
775
+ batchSize?: number;
776
+ delayMs?: number;
777
+ confidenceThreshold?: number;
778
+ } = {}
779
+ ): Promise<GraphExtractionResult[]> {
780
+ return this.knowledgeGraph.extractKnowledgeGraphBatch(memories, userAddress, options);
781
+ }
782
+
783
+ /**
784
+ * Get user's knowledge graph
785
+ */
786
+ async getUserKnowledgeGraph(userAddress: string): Promise<KnowledgeGraph> {
787
+ return this.knowledgeGraph.getUserKnowledgeGraph(userAddress);
788
+ }
789
+
790
+ /**
791
+ * Save knowledge graph to Walrus
792
+ */
793
+ async saveKnowledgeGraphToWalrus(userAddress: string): Promise<string | null> {
794
+ const graph = await this.knowledgeGraph.getUserKnowledgeGraph(userAddress);
795
+
796
+ if (!this.knowledgeGraph.isGraphDirty(userAddress)) {
797
+ return null;
798
+ }
799
+
800
+ try {
801
+ const graphData = this.knowledgeGraph.serializeGraph(userAddress);
802
+ if (!graphData) return null;
803
+
804
+ const graphBytes = new TextEncoder().encode(graphData);
805
+
806
+ console.log(`💾 Saving knowledge graph for user ${userAddress} to Walrus...`);
807
+ console.log(`📊 Graph size: ${graph.entities.length} entities, ${graph.relationships.length} relationships`);
808
+
809
+ this.knowledgeGraph.markGraphAsSaved(userAddress);
810
+
811
+ return `graph_${userAddress}_${Date.now()}`;
812
+ } catch (error) {
813
+ console.error('❌ Failed to save knowledge graph:', error);
814
+ throw error;
815
+ }
816
+ }
817
+
818
+ /**
819
+ * Start background graph persistence
820
+ */
821
+ startGraphPersistence(intervalMs: number = 5 * 60 * 1000) {
822
+ if (!this.graphService) {
823
+ console.warn('Knowledge Graph not initialized - skipping persistence setup');
824
+ return;
825
+ }
826
+
827
+ console.log(`🔄 Starting knowledge graph auto-persistence (every ${intervalMs / 1000}s)`);
828
+
829
+ setInterval(async () => {
830
+ const users = this.knowledgeGraph.getCachedUsers();
831
+ for (const userAddress of users) {
832
+ if (this.knowledgeGraph.isGraphDirty(userAddress)) {
833
+ try {
834
+ const blobId = await this.saveKnowledgeGraphToWalrus(userAddress);
835
+ if (blobId) {
836
+ console.log(`💾 Auto-saved knowledge graph for ${userAddress}: ${blobId}`);
837
+ }
838
+ } catch (error) {
839
+ console.error(`Failed to auto-save knowledge graph for ${userAddress}:`, error);
840
+ }
841
+ }
842
+ }
843
+ }, intervalMs);
844
+ }
845
+
846
+ /**
847
+ * Get graph statistics
848
+ */
849
+ getGraphStatistics(userAddress: string) {
850
+ return this.knowledgeGraph.getGraphStatistics(userAddress);
851
+ }
852
+
853
+ /**
854
+ * Get knowledge graph analytics
855
+ */
856
+ getKnowledgeGraphAnalytics(userAddress: string) {
857
+ return this.knowledgeGraph.getKnowledgeGraphAnalytics(userAddress);
858
+ }
859
+
860
+ // ==================== QUILT BATCH OPERATIONS (Delegate to QuiltBatchManager) ====================
861
+
862
+ /**
863
+ * Upload multiple memories as a Quilt
864
+ */
865
+ async uploadMemoryBatch(
866
+ memories: Array<{
867
+ content: string;
868
+ category: string;
869
+ importance: number;
870
+ topic: string;
871
+ embedding: number[];
872
+ encryptedContent: Uint8Array;
873
+ summary?: string;
874
+ }>,
875
+ options: {
876
+ signer: UnifiedSigner;
877
+ epochs?: number;
878
+ userAddress: string;
879
+ }
880
+ ): Promise<{
881
+ quiltId: string;
882
+ files: Array<{ identifier: string; blobId: string }>;
883
+ uploadTimeMs: number;
884
+ }> {
885
+ return this.quiltBatch.uploadMemoryBatch(memories, options);
886
+ }
887
+
888
+ /**
889
+ * Retrieve all files from a Quilt
890
+ */
891
+ async getQuiltFiles(quiltId: string): Promise<Array<WalrusFile>> {
892
+ return this.quiltBatch.getQuiltFiles(quiltId);
893
+ }
894
+
895
+ /**
896
+ * Query Quilt files by tags
897
+ */
898
+ async getQuiltFilesByTags(
899
+ quiltId: string,
900
+ tagFilters: Array<Record<string, string>>
901
+ ): Promise<Array<WalrusFile>> {
902
+ return this.quiltBatch.getQuiltFilesByTags(quiltId, tagFilters);
903
+ }
904
+
905
+ /**
906
+ * Upload raw files as a Quilt (non-memory data)
907
+ */
908
+ async uploadFilesBatch(
909
+ files: Array<{
910
+ identifier: string;
911
+ data: Uint8Array;
912
+ tags?: Record<string, string>;
913
+ }>,
914
+ options: {
915
+ signer: UnifiedSigner;
916
+ epochs?: number;
917
+ userAddress: string;
918
+ }
919
+ ): Promise<{
920
+ quiltId: string;
921
+ files: Array<{ identifier: string; blobId: string }>;
922
+ uploadTimeMs: number;
923
+ totalSize: number;
924
+ gasSaved: string;
925
+ }> {
926
+ return this.quiltBatch.uploadFilesBatch(files, options);
927
+ }
928
+
929
+ /**
930
+ * Retrieve a specific file by identifier from a Quilt
931
+ */
932
+ async getFileByIdentifier(
933
+ quiltId: string,
934
+ identifier: string
935
+ ): Promise<{
936
+ identifier: string;
937
+ content: Uint8Array;
938
+ tags: Record<string, string>;
939
+ retrievalTimeMs: number;
940
+ }> {
941
+ return this.quiltBatch.getFileByIdentifier(quiltId, identifier);
942
+ }
943
+
944
+ /**
945
+ * Query files by category from a Quilt
946
+ */
947
+ async getFilesByCategory(
948
+ quiltId: string,
949
+ category: string
950
+ ): Promise<Array<WalrusFile>> {
951
+ return this.quiltBatch.getFilesByCategory(quiltId, category);
952
+ }
953
+
954
+ /**
955
+ * Query files by importance threshold from a Quilt
956
+ */
957
+ async getFilesByImportance(
958
+ quiltId: string,
959
+ minImportance: number
960
+ ): Promise<Array<WalrusFile>> {
961
+ return this.quiltBatch.getFilesByImportance(quiltId, minImportance);
962
+ }
963
+
964
+ /**
965
+ * List all patches in a Quilt with their metadata
966
+ */
967
+ async listQuiltPatches(quiltId: string): Promise<Array<{
968
+ identifier: string;
969
+ quiltPatchId: string;
970
+ tags: Record<string, string>;
971
+ }>> {
972
+ return this.quiltBatch.listQuiltPatches(quiltId);
973
+ }
974
+
975
+ /**
976
+ * Get all memory packages from a Quilt as JSON
977
+ * Used for indexing Quilt memories into local HNSW index
978
+ */
979
+ async getAllMemoryPackages(quiltId: string) {
980
+ return this.quiltBatch.getAllMemoryPackages(quiltId);
981
+ }
982
+
983
+ /**
984
+ * Get the QuiltBatchManager instance for advanced operations
985
+ */
986
+ get quiltBatchManager(): QuiltBatchManager {
987
+ return this.quiltBatch;
988
+ }
989
+
990
+ // ==================== BLOB ATTRIBUTES (Delegate to BlobAttributesManager) ====================
991
+
992
+ /**
993
+ * Set attributes on a Blob object
994
+ */
995
+ async setBlobAttributes(
996
+ blobObjectId: string,
997
+ attributes: Record<string, string>,
998
+ signer: UnifiedSigner
999
+ ): Promise<string> {
1000
+ return this.blobAttributes.setBlobAttributes(blobObjectId, attributes, signer);
1001
+ }
1002
+
1003
+ /**
1004
+ * Get attributes from a Blob object
1005
+ */
1006
+ async getBlobAttributes(
1007
+ blobObjectId: string,
1008
+ attributeKeys?: string[]
1009
+ ): Promise<Record<string, string>> {
1010
+ return this.blobAttributes.getBlobAttributes(blobObjectId, attributeKeys);
1011
+ }
1012
+
1013
+ /**
1014
+ * Update blob attributes
1015
+ */
1016
+ async updateBlobAttributes(
1017
+ blobObjectId: string,
1018
+ attributes: Record<string, string>,
1019
+ signer: UnifiedSigner
1020
+ ): Promise<string> {
1021
+ return this.blobAttributes.updateBlobAttributes(blobObjectId, attributes, signer);
1022
+ }
1023
+
1024
+ /**
1025
+ * Remove blob attributes
1026
+ */
1027
+ async removeBlobAttributes(
1028
+ blobObjectId: string,
1029
+ attributeKeys: string[],
1030
+ signer: UnifiedSigner
1031
+ ): Promise<string> {
1032
+ return this.blobAttributes.removeBlobAttributes(blobObjectId, attributeKeys, signer);
1033
+ }
1034
+
1035
+ /**
1036
+ * Query memories by attributes
1037
+ */
1038
+ async queryMemoriesByAttributes(
1039
+ filters: Record<string, string>,
1040
+ owner: string,
1041
+ walrusPackageId: string
1042
+ ): Promise<Array<{
1043
+ blobObjectId: string;
1044
+ blobId: string;
1045
+ attributes: Record<string, string>;
1046
+ }>> {
1047
+ return this.blobAttributes.queryMemoriesByAttributes(filters, owner, walrusPackageId);
1048
+ }
1049
+
1050
+ // ==================== METADATA OPERATIONS (Delegate to WalrusMetadataManager) ====================
1051
+
1052
+ /**
1053
+ * Build Walrus metadata structure
1054
+ */
1055
+ private buildWalrusMetadata(
1056
+ contentSize: number,
1057
+ options: {
1058
+ category?: string;
1059
+ topic?: string;
1060
+ importance?: number;
1061
+ embedding?: number[];
1062
+ embeddingBlobId?: string;
1063
+ graphBlobId?: string;
1064
+ graphEntityIds?: string[];
1065
+ graphEntityCount?: number;
1066
+ graphRelationshipCount?: number;
1067
+ vectorId?: number;
1068
+ isEncrypted?: boolean;
1069
+ encryptionType?: string;
1070
+ sealIdentity?: string;
1071
+ customFields?: Record<string, string>;
1072
+ }
1073
+ ): WalrusMemoryMetadata {
1074
+ return this.walrusMetadata.buildWalrusMetadata(contentSize, options);
1075
+ }
1076
+
1077
+ /**
1078
+ * Attach metadata to a Blob object
1079
+ */
1080
+ async attachMetadataToBlob(
1081
+ blobId: string,
1082
+ metadata: WalrusMemoryMetadata,
1083
+ signer: UnifiedSigner
1084
+ ): Promise<{ digest: string; effects: any }> {
1085
+ const walrusPackageId = this.config.network === 'mainnet'
1086
+ ? '0x<mainnet-walrus-package-id>'
1087
+ : '0x<testnet-walrus-package-id>';
1088
+
1089
+ return this.walrusMetadata.attachMetadataToBlob(blobId, metadata, signer, walrusPackageId);
1090
+ }
1091
+
1092
+ /**
1093
+ * Retrieve metadata from a Blob object
1094
+ */
1095
+ async retrieveBlobMetadata(blobObjectId: string): Promise<WalrusMemoryMetadata | null> {
1096
+ return this.walrusMetadata.retrieveBlobMetadata(blobObjectId);
1097
+ }
1098
+
1099
+ // ==================== ANALYTICS AND STATS ====================
1100
+
1101
+ /**
1102
+ * Get search analytics
1103
+ */
1104
+ getSearchAnalytics(userAddress: string) {
1105
+ return this.memorySearch.getSearchAnalytics(userAddress);
1106
+ }
1107
+
1108
+ /**
1109
+ * Get storage statistics
1110
+ */
1111
+ async getStats() {
1112
+ const memoryStats = await this.memorySearch.getServiceStats();
1113
+
1114
+ return {
1115
+ network: this.config.network || 'testnet',
1116
+ useUploadRelay: this.config.useUploadRelay ?? true,
1117
+ epochs: this.config.epochs || 3,
1118
+ hasEncryption: !!this.config.sealService,
1119
+ hasBatching: !!this.config.batchService,
1120
+ hasSearch: !!(this.embeddingService && this.memoryIndexService),
1121
+ indexedUsers: memoryStats?.totalUsers || 0,
1122
+ totalIndexedMemories: memoryStats?.totalMemories || 0,
1123
+ memoryIndexStats: memoryStats
1124
+ };
1125
+ }
1126
+
1127
+ // ==================== COMPATIBILITY METHODS ====================
1128
+
1129
+ /**
1130
+ * Legacy upload method for backward compatibility
1131
+ */
1132
+ async upload(
1133
+ content: Uint8Array | string,
1134
+ metadata: MemoryMetadata,
1135
+ options?: Partial<BlobUploadOptions>
1136
+ ): Promise<WalrusUploadResult> {
1137
+ const data = typeof content === 'string' ? new TextEncoder().encode(content) : content;
1138
+
1139
+ const uploadOptions: BlobUploadOptions = {
1140
+ signer: options?.signer!,
1141
+ epochs: options?.epochs ?? this.config.epochs ?? 3,
1142
+ deletable: options?.deletable ?? true,
1143
+ useUploadRelay: options?.useUploadRelay,
1144
+ encrypt: options?.encrypt,
1145
+ metadata: {
1146
+ 'content-type': metadata.contentType,
1147
+ 'category': metadata.category,
1148
+ 'topic': metadata.topic,
1149
+ 'importance': metadata.importance.toString(),
1150
+ ...(options?.metadata || {})
1151
+ }
1152
+ };
1153
+
1154
+ return this.uploadBlob(data, uploadOptions);
1155
+ }
1156
+
1157
+ /**
1158
+ * Legacy retrieve method for backward compatibility
1159
+ */
1160
+ async retrieve(blobId: string): Promise<{
1161
+ content: Uint8Array;
1162
+ metadata: MemoryMetadata;
1163
+ }> {
1164
+ const result = await this.retrieveMemoryPackage(blobId);
1165
+
1166
+ return {
1167
+ content: result.content,
1168
+ metadata: result.metadata
1169
+ };
1170
+ }
1171
+
1172
+ /**
1173
+ * Legacy list method (not implemented)
1174
+ */
1175
+ async list(filter?: any): Promise<Array<{
1176
+ blobId: string;
1177
+ metadata: MemoryMetadata
1178
+ }>> {
1179
+ console.warn('StorageService.list() not yet implemented - requires metadata storage');
1180
+ return [];
1181
+ }
1182
+ }