@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,458 +1,458 @@
1
- /**
2
- * Storage Namespace - Direct Walrus Storage Operations
3
- *
4
- * Simple wrapper around StorageService for direct Walrus access.
5
- * Delegates to existing storage managers:
6
- * - WalrusStorageManager (upload/download)
7
- * - QuiltBatchManager (batch operations)
8
- * - WalrusMetadataManager (metadata)
9
- * - BlobAttributesManager (dynamic fields)
10
- *
11
- * @module client/namespaces
12
- */
13
-
14
- import type { ServiceContainer } from '../SimplePDWClient';
15
-
16
- /**
17
- * Upload result
18
- */
19
- export interface UploadResult {
20
- blobId: string;
21
- size: number;
22
- contentType?: string;
23
- metadata?: Record<string, any>;
24
- }
25
-
26
- /**
27
- * Quilt result (batch upload)
28
- */
29
- export interface QuiltResult {
30
- quiltId: string;
31
- files: Array<{
32
- name: string;
33
- blobId: string;
34
- size: number;
35
- }>;
36
- totalSize: number;
37
- }
38
-
39
- /**
40
- * Blob metadata
41
- */
42
- export interface BlobMetadata {
43
- [key: string]: string | number | boolean;
44
- }
45
-
46
- /**
47
- * File for batch upload
48
- */
49
- export interface FileUpload {
50
- name: string;
51
- data: Uint8Array;
52
- contentType?: string;
53
- }
54
-
55
- /**
56
- * Storage statistics
57
- */
58
- export interface StorageStats {
59
- totalBlobs: number;
60
- totalSize: number;
61
- blobsByCategory: Record<string, number>;
62
- }
63
-
64
- /**
65
- * Storage Namespace
66
- *
67
- * Handles direct Walrus storage operations
68
- */
69
- export class StorageNamespace {
70
- constructor(private services: ServiceContainer) {}
71
-
72
- /**
73
- * Upload data to Walrus
74
- *
75
- * Delegates to StorageService.uploadBlob() (WalrusStorageManager)
76
- *
77
- * @param data - Data bytes to upload
78
- * @param metadata - Optional metadata
79
- * @returns Upload result with blob ID
80
- *
81
- * @example
82
- * ```typescript
83
- * const data = new TextEncoder().encode('Hello world');
84
- * const result = await pdw.storage.upload(data, {
85
- * contentType: 'text/plain',
86
- * category: 'document'
87
- * });
88
- * ```
89
- */
90
- async upload(data: Uint8Array, metadata?: BlobMetadata): Promise<UploadResult> {
91
- try {
92
- // Delegate to StorageService (uses WalrusStorageManager internally)
93
- const result = await this.services.storage.uploadBlob(
94
- data,
95
- {
96
- signer: this.services.config.signer,
97
- epochs: 3,
98
- deletable: true,
99
- metadata: metadata as any
100
- }
101
- );
102
-
103
- return {
104
- blobId: result.blobId,
105
- size: data.length,
106
- metadata
107
- };
108
- } catch (error) {
109
- throw new Error(`Upload failed: ${error instanceof Error ? error.message : String(error)}`);
110
- }
111
- }
112
-
113
- /**
114
- * Download data from Walrus
115
- *
116
- * @param blobId - Blob ID to download
117
- * @returns Data bytes
118
- */
119
- async download(blobId: string): Promise<Uint8Array> {
120
- try {
121
- const result = await this.services.storage.retrieve(blobId);
122
-
123
- if (result instanceof Uint8Array) {
124
- return result;
125
- }
126
-
127
- // Convert string to Uint8Array if needed
128
- if (typeof result === 'string') {
129
- return new TextEncoder().encode(result);
130
- }
131
-
132
- throw new Error('Unexpected blob format');
133
- } catch (error) {
134
- throw new Error(`Download failed: ${error instanceof Error ? error.message : String(error)}`);
135
- }
136
- }
137
-
138
- /**
139
- * Delete a blob (soft delete)
140
- *
141
- * Walrus blobs are immutable and cannot be truly deleted.
142
- * This marks the blob as deleted by setting a `deleted_at` attribute on-chain.
143
- * The blob data remains on Walrus but will be filtered out in queries.
144
- *
145
- * @param blobId - Blob ID to mark as deleted
146
- */
147
- async delete(blobId: string): Promise<void> {
148
- try {
149
- if (!blobId) {
150
- throw new Error('Blob ID is required');
151
- }
152
-
153
- // Mark as deleted by setting deleted_at attribute
154
- // This is a soft delete - the blob remains on Walrus but is marked as deleted
155
- await this.services.storage.updateBlobAttributes(
156
- blobId,
157
- {
158
- deleted_at: new Date().toISOString(),
159
- deleted_by: this.services.config.userAddress
160
- },
161
- this.services.config.signer
162
- );
163
-
164
- console.log(`Blob ${blobId} marked as deleted`);
165
- } catch (error) {
166
- throw new Error(`Delete failed: ${error instanceof Error ? error.message : String(error)}`);
167
- }
168
- }
169
-
170
- /**
171
- * Upload multiple files as a Quilt (batch)
172
- *
173
- * @param files - Array of files to upload
174
- * @returns Quilt result with file mappings
175
- */
176
- async uploadBatch(files: FileUpload[]): Promise<QuiltResult> {
177
- try {
178
- // Use uploadMemoryBatch (StorageService has this, not uploadQuilt)
179
- const memories = files.map(f => ({
180
- content: new TextDecoder().decode(f.data),
181
- category: 'general',
182
- importance: 5,
183
- topic: f.name,
184
- embedding: [] as number[],
185
- encryptedContent: f.data, // Use file data as encrypted content
186
- summary: ''
187
- }));
188
-
189
- const result = await this.services.storage.uploadMemoryBatch(
190
- memories,
191
- {
192
- signer: this.services.config.signer,
193
- epochs: 3,
194
- userAddress: this.services.config.userAddress
195
- }
196
- );
197
-
198
- return {
199
- quiltId: result.quiltId,
200
- files: result.files.map((f: any) => ({
201
- name: f.identifier,
202
- blobId: f.blobId,
203
- size: 0 // Size not available in result
204
- })),
205
- totalSize: files.reduce((sum, f) => sum + f.data.length, 0)
206
- };
207
- } catch (error) {
208
- throw new Error(`Batch upload failed: ${error instanceof Error ? error.message : String(error)}`);
209
- }
210
- }
211
-
212
- /**
213
- * Download multiple files from a Quilt
214
- *
215
- * Retrieves all WalrusFiles from a quilt and downloads their content.
216
- * File names are extracted from identifiers or tags.
217
- *
218
- * @param quiltId - Quilt ID
219
- * @returns Array of files with name and data
220
- */
221
- async downloadBatch(quiltId: string): Promise<Array<{ name: string; data: Uint8Array }>> {
222
- try {
223
- if (!quiltId) {
224
- throw new Error('Quilt ID is required');
225
- }
226
-
227
- // Get all WalrusFile objects from quilt
228
- const files = await this.services.storage.getQuiltFiles(quiltId);
229
-
230
- if (!files || files.length === 0) {
231
- console.warn(`No files found in quilt ${quiltId}`);
232
- return [];
233
- }
234
-
235
- // Download each file in parallel
236
- const results = await Promise.all(
237
- files.map(async (file: any, index: number) => {
238
- try {
239
- // Extract name from identifier or tags
240
- let name = `file-${index}`;
241
-
242
- // Try to get identifier (filename)
243
- if (typeof file.getIdentifier === 'function') {
244
- const identifier = file.getIdentifier();
245
- if (identifier) {
246
- name = identifier;
247
- }
248
- }
249
-
250
- // Try to get name from tags as fallback
251
- if (name === `file-${index}` && typeof file.getTags === 'function') {
252
- const tags = await file.getTags();
253
- if (tags?.topic) {
254
- name = tags.topic;
255
- }
256
- }
257
-
258
- // Get blob content - WalrusFile should have blob reference
259
- let data: Uint8Array;
260
-
261
- // Try to read content directly from file if available
262
- if (typeof file.read === 'function') {
263
- data = await file.read();
264
- } else if (file.blobId) {
265
- // Fallback: retrieve via blobId
266
- const result = await this.services.storage.retrieve(file.blobId);
267
- data = result instanceof Uint8Array ? result : new TextEncoder().encode(String(result));
268
- } else if (file.contents) {
269
- // Direct contents access
270
- data = file.contents instanceof Uint8Array
271
- ? file.contents
272
- : new TextEncoder().encode(String(file.contents));
273
- } else {
274
- throw new Error(`Cannot extract content from file at index ${index}`);
275
- }
276
-
277
- return { name, data };
278
- } catch (fileError) {
279
- console.warn(`Failed to download file at index ${index}:`, fileError);
280
- // Return empty data for failed files instead of throwing
281
- return { name: `file-${index}-error`, data: new Uint8Array(0) };
282
- }
283
- })
284
- );
285
-
286
- // Filter out failed downloads (empty data)
287
- return results.filter(r => r.data.length > 0);
288
- } catch (error) {
289
- throw new Error(`Batch download failed: ${error instanceof Error ? error.message : String(error)}`);
290
- }
291
- }
292
-
293
- /**
294
- * Set metadata for a blob
295
- *
296
- * @param blobId - Blob ID
297
- * @param metadata - Metadata to attach
298
- */
299
- async setMetadata(blobId: string, metadata: BlobMetadata): Promise<void> {
300
- try {
301
- // Use attachMetadataToBlob (correct method name)
302
- await this.services.storage.attachMetadataToBlob(
303
- blobId,
304
- metadata as any,
305
- this.services.config.signer
306
- );
307
- } catch (error) {
308
- throw new Error(`Set metadata failed: ${error instanceof Error ? error.message : String(error)}`);
309
- }
310
- }
311
-
312
- /**
313
- * Get metadata for a blob
314
- *
315
- * @param blobId - Blob ID
316
- * @returns Blob metadata
317
- */
318
- async getMetadata(blobId: string): Promise<BlobMetadata> {
319
- try {
320
- // Use retrieveBlobMetadata (correct method name)
321
- const metadata = await this.services.storage.retrieveBlobMetadata(blobId);
322
- return metadata as BlobMetadata;
323
- } catch (error) {
324
- throw new Error(`Get metadata failed: ${error instanceof Error ? error.message : String(error)}`);
325
- }
326
- }
327
-
328
- /**
329
- * List blobs for user
330
- *
331
- * @param filter - Optional filter
332
- * @returns Array of blob info
333
- */
334
- async listBlobs(filter?: { category?: string; limit?: number }): Promise<Array<{ blobId: string; metadata: BlobMetadata }>> {
335
- try {
336
- // Use searchByMetadata
337
- const results = await this.services.storage.searchByMetadata(
338
- this.services.config.userAddress,
339
- {} // MetadataSearchQuery - minimal params
340
- );
341
-
342
- return results.map((r: any) => ({
343
- blobId: r.blobId,
344
- metadata: r.metadata || {}
345
- }));
346
- } catch (error) {
347
- throw new Error(`List blobs failed: ${error instanceof Error ? error.message : String(error)}`);
348
- }
349
- }
350
-
351
- /**
352
- * Get storage statistics
353
- *
354
- * Calculates total size from blob metadata (content_size field).
355
- *
356
- * @returns Storage stats
357
- */
358
- async getStats(): Promise<StorageStats> {
359
- try {
360
- // Get all blobs
361
- const blobs = await this.listBlobs({ limit: 1000 });
362
-
363
- const stats: StorageStats = {
364
- totalBlobs: blobs.length,
365
- totalSize: 0,
366
- blobsByCategory: {}
367
- };
368
-
369
- // Count by category and accumulate size
370
- blobs.forEach(b => {
371
- const category = b.metadata.category as string || 'general';
372
- stats.blobsByCategory[category] = (stats.blobsByCategory[category] || 0) + 1;
373
-
374
- // Sum up content sizes from metadata
375
- const size = Number(b.metadata.content_size || b.metadata.contentSize || b.metadata.size || 0);
376
- if (!isNaN(size)) {
377
- stats.totalSize += size;
378
- }
379
- });
380
-
381
- return stats;
382
- } catch (error) {
383
- throw new Error(`Get storage stats failed: ${error instanceof Error ? error.message : String(error)}`);
384
- }
385
- }
386
-
387
- /**
388
- * Cleanup old or unused blobs
389
- *
390
- * Marks blobs as deleted if they meet cleanup criteria:
391
- * - Already marked as deleted (removes from active queries)
392
- * - Low importance and old (optional aggressive cleanup)
393
- *
394
- * Note: Walrus blobs cannot be truly deleted. This marks them
395
- * as deleted via attributes for filtering in queries.
396
- *
397
- * @param options - Cleanup options
398
- * @returns Number of blobs marked for cleanup
399
- */
400
- async cleanup(options?: {
401
- /** Remove blobs already marked as deleted from listings */
402
- removeDeleted?: boolean;
403
- /** Mark old, low-importance blobs as deleted */
404
- aggressiveCleanup?: boolean;
405
- /** Max age in days for aggressive cleanup (default: 90) */
406
- maxAgeDays?: number;
407
- /** Max importance for aggressive cleanup (default: 3) */
408
- maxImportance?: number;
409
- }): Promise<number> {
410
- try {
411
- const {
412
- removeDeleted = true,
413
- aggressiveCleanup = false,
414
- maxAgeDays = 90,
415
- maxImportance = 3
416
- } = options || {};
417
-
418
- let cleanedCount = 0;
419
- const blobs = await this.listBlobs({ limit: 1000 });
420
-
421
- for (const blob of blobs) {
422
- try {
423
- const metadata = blob.metadata;
424
-
425
- // Skip if already processed
426
- if (metadata.deleted_at) {
427
- continue;
428
- }
429
-
430
- // Aggressive cleanup: mark old, low-importance blobs
431
- if (aggressiveCleanup) {
432
- const importance = Number(metadata.importance) || 5;
433
- const createdAt = metadata.created_at
434
- ? new Date(metadata.created_at as string).getTime()
435
- : Date.now();
436
- const ageInDays = (Date.now() - createdAt) / (1000 * 60 * 60 * 24);
437
-
438
- if (importance <= maxImportance && ageInDays >= maxAgeDays) {
439
- await this.delete(blob.blobId);
440
- cleanedCount++;
441
- console.log(`Cleaned up old blob ${blob.blobId} (age: ${ageInDays.toFixed(0)} days, importance: ${importance})`);
442
- }
443
- }
444
- } catch (blobError) {
445
- console.warn(`Failed to process blob ${blob.blobId} during cleanup:`, blobError);
446
- }
447
- }
448
-
449
- if (cleanedCount > 0) {
450
- console.log(`Storage cleanup completed: ${cleanedCount} blobs marked for cleanup`);
451
- }
452
-
453
- return cleanedCount;
454
- } catch (error) {
455
- throw new Error(`Cleanup failed: ${error instanceof Error ? error.message : String(error)}`);
456
- }
457
- }
458
- }
1
+ /**
2
+ * Storage Namespace - Direct Walrus Storage Operations
3
+ *
4
+ * Simple wrapper around StorageService for direct Walrus access.
5
+ * Delegates to existing storage managers:
6
+ * - WalrusStorageManager (upload/download)
7
+ * - QuiltBatchManager (batch operations)
8
+ * - WalrusMetadataManager (metadata)
9
+ * - BlobAttributesManager (dynamic fields)
10
+ *
11
+ * @module client/namespaces
12
+ */
13
+
14
+ import type { ServiceContainer } from '../SimplePDWClient';
15
+
16
+ /**
17
+ * Upload result
18
+ */
19
+ export interface UploadResult {
20
+ blobId: string;
21
+ size: number;
22
+ contentType?: string;
23
+ metadata?: Record<string, any>;
24
+ }
25
+
26
+ /**
27
+ * Quilt result (batch upload)
28
+ */
29
+ export interface QuiltResult {
30
+ quiltId: string;
31
+ files: Array<{
32
+ name: string;
33
+ blobId: string;
34
+ size: number;
35
+ }>;
36
+ totalSize: number;
37
+ }
38
+
39
+ /**
40
+ * Blob metadata
41
+ */
42
+ export interface BlobMetadata {
43
+ [key: string]: string | number | boolean;
44
+ }
45
+
46
+ /**
47
+ * File for batch upload
48
+ */
49
+ export interface FileUpload {
50
+ name: string;
51
+ data: Uint8Array;
52
+ contentType?: string;
53
+ }
54
+
55
+ /**
56
+ * Storage statistics
57
+ */
58
+ export interface StorageStats {
59
+ totalBlobs: number;
60
+ totalSize: number;
61
+ blobsByCategory: Record<string, number>;
62
+ }
63
+
64
+ /**
65
+ * Storage Namespace
66
+ *
67
+ * Handles direct Walrus storage operations
68
+ */
69
+ export class StorageNamespace {
70
+ constructor(private services: ServiceContainer) {}
71
+
72
+ /**
73
+ * Upload data to Walrus
74
+ *
75
+ * Delegates to StorageService.uploadBlob() (WalrusStorageManager)
76
+ *
77
+ * @param data - Data bytes to upload
78
+ * @param metadata - Optional metadata
79
+ * @returns Upload result with blob ID
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const data = new TextEncoder().encode('Hello world');
84
+ * const result = await pdw.storage.upload(data, {
85
+ * contentType: 'text/plain',
86
+ * category: 'document'
87
+ * });
88
+ * ```
89
+ */
90
+ async upload(data: Uint8Array, metadata?: BlobMetadata): Promise<UploadResult> {
91
+ try {
92
+ // Delegate to StorageService (uses WalrusStorageManager internally)
93
+ const result = await this.services.storage.uploadBlob(
94
+ data,
95
+ {
96
+ signer: this.services.config.signer,
97
+ epochs: 3,
98
+ deletable: true,
99
+ metadata: metadata as any
100
+ }
101
+ );
102
+
103
+ return {
104
+ blobId: result.blobId,
105
+ size: data.length,
106
+ metadata
107
+ };
108
+ } catch (error) {
109
+ throw new Error(`Upload failed: ${error instanceof Error ? error.message : String(error)}`);
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Download data from Walrus
115
+ *
116
+ * @param blobId - Blob ID to download
117
+ * @returns Data bytes
118
+ */
119
+ async download(blobId: string): Promise<Uint8Array> {
120
+ try {
121
+ const result = await this.services.storage.retrieve(blobId);
122
+
123
+ if (result instanceof Uint8Array) {
124
+ return result;
125
+ }
126
+
127
+ // Convert string to Uint8Array if needed
128
+ if (typeof result === 'string') {
129
+ return new TextEncoder().encode(result);
130
+ }
131
+
132
+ throw new Error('Unexpected blob format');
133
+ } catch (error) {
134
+ throw new Error(`Download failed: ${error instanceof Error ? error.message : String(error)}`);
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Delete a blob (soft delete)
140
+ *
141
+ * Walrus blobs are immutable and cannot be truly deleted.
142
+ * This marks the blob as deleted by setting a `deleted_at` attribute on-chain.
143
+ * The blob data remains on Walrus but will be filtered out in queries.
144
+ *
145
+ * @param blobId - Blob ID to mark as deleted
146
+ */
147
+ async delete(blobId: string): Promise<void> {
148
+ try {
149
+ if (!blobId) {
150
+ throw new Error('Blob ID is required');
151
+ }
152
+
153
+ // Mark as deleted by setting deleted_at attribute
154
+ // This is a soft delete - the blob remains on Walrus but is marked as deleted
155
+ await this.services.storage.updateBlobAttributes(
156
+ blobId,
157
+ {
158
+ deleted_at: new Date().toISOString(),
159
+ deleted_by: this.services.config.userAddress
160
+ },
161
+ this.services.config.signer
162
+ );
163
+
164
+ console.log(`Blob ${blobId} marked as deleted`);
165
+ } catch (error) {
166
+ throw new Error(`Delete failed: ${error instanceof Error ? error.message : String(error)}`);
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Upload multiple files as a Quilt (batch)
172
+ *
173
+ * @param files - Array of files to upload
174
+ * @returns Quilt result with file mappings
175
+ */
176
+ async uploadBatch(files: FileUpload[]): Promise<QuiltResult> {
177
+ try {
178
+ // Use uploadMemoryBatch (StorageService has this, not uploadQuilt)
179
+ const memories = files.map(f => ({
180
+ content: new TextDecoder().decode(f.data),
181
+ category: 'general',
182
+ importance: 5,
183
+ topic: f.name,
184
+ embedding: [] as number[],
185
+ encryptedContent: f.data, // Use file data as encrypted content
186
+ summary: ''
187
+ }));
188
+
189
+ const result = await this.services.storage.uploadMemoryBatch(
190
+ memories,
191
+ {
192
+ signer: this.services.config.signer,
193
+ epochs: 3,
194
+ userAddress: this.services.config.userAddress
195
+ }
196
+ );
197
+
198
+ return {
199
+ quiltId: result.quiltId,
200
+ files: result.files.map((f: any) => ({
201
+ name: f.identifier,
202
+ blobId: f.blobId,
203
+ size: 0 // Size not available in result
204
+ })),
205
+ totalSize: files.reduce((sum, f) => sum + f.data.length, 0)
206
+ };
207
+ } catch (error) {
208
+ throw new Error(`Batch upload failed: ${error instanceof Error ? error.message : String(error)}`);
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Download multiple files from a Quilt
214
+ *
215
+ * Retrieves all WalrusFiles from a quilt and downloads their content.
216
+ * File names are extracted from identifiers or tags.
217
+ *
218
+ * @param quiltId - Quilt ID
219
+ * @returns Array of files with name and data
220
+ */
221
+ async downloadBatch(quiltId: string): Promise<Array<{ name: string; data: Uint8Array }>> {
222
+ try {
223
+ if (!quiltId) {
224
+ throw new Error('Quilt ID is required');
225
+ }
226
+
227
+ // Get all WalrusFile objects from quilt
228
+ const files = await this.services.storage.getQuiltFiles(quiltId);
229
+
230
+ if (!files || files.length === 0) {
231
+ console.warn(`No files found in quilt ${quiltId}`);
232
+ return [];
233
+ }
234
+
235
+ // Download each file in parallel
236
+ const results = await Promise.all(
237
+ files.map(async (file: any, index: number) => {
238
+ try {
239
+ // Extract name from identifier or tags
240
+ let name = `file-${index}`;
241
+
242
+ // Try to get identifier (filename)
243
+ if (typeof file.getIdentifier === 'function') {
244
+ const identifier = file.getIdentifier();
245
+ if (identifier) {
246
+ name = identifier;
247
+ }
248
+ }
249
+
250
+ // Try to get name from tags as fallback
251
+ if (name === `file-${index}` && typeof file.getTags === 'function') {
252
+ const tags = await file.getTags();
253
+ if (tags?.topic) {
254
+ name = tags.topic;
255
+ }
256
+ }
257
+
258
+ // Get blob content - WalrusFile should have blob reference
259
+ let data: Uint8Array;
260
+
261
+ // Try to read content directly from file if available
262
+ if (typeof file.read === 'function') {
263
+ data = await file.read();
264
+ } else if (file.blobId) {
265
+ // Fallback: retrieve via blobId
266
+ const result = await this.services.storage.retrieve(file.blobId);
267
+ data = result instanceof Uint8Array ? result : new TextEncoder().encode(String(result));
268
+ } else if (file.contents) {
269
+ // Direct contents access
270
+ data = file.contents instanceof Uint8Array
271
+ ? file.contents
272
+ : new TextEncoder().encode(String(file.contents));
273
+ } else {
274
+ throw new Error(`Cannot extract content from file at index ${index}`);
275
+ }
276
+
277
+ return { name, data };
278
+ } catch (fileError) {
279
+ console.warn(`Failed to download file at index ${index}:`, fileError);
280
+ // Return empty data for failed files instead of throwing
281
+ return { name: `file-${index}-error`, data: new Uint8Array(0) };
282
+ }
283
+ })
284
+ );
285
+
286
+ // Filter out failed downloads (empty data)
287
+ return results.filter(r => r.data.length > 0);
288
+ } catch (error) {
289
+ throw new Error(`Batch download failed: ${error instanceof Error ? error.message : String(error)}`);
290
+ }
291
+ }
292
+
293
+ /**
294
+ * Set metadata for a blob
295
+ *
296
+ * @param blobId - Blob ID
297
+ * @param metadata - Metadata to attach
298
+ */
299
+ async setMetadata(blobId: string, metadata: BlobMetadata): Promise<void> {
300
+ try {
301
+ // Use attachMetadataToBlob (correct method name)
302
+ await this.services.storage.attachMetadataToBlob(
303
+ blobId,
304
+ metadata as any,
305
+ this.services.config.signer
306
+ );
307
+ } catch (error) {
308
+ throw new Error(`Set metadata failed: ${error instanceof Error ? error.message : String(error)}`);
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Get metadata for a blob
314
+ *
315
+ * @param blobId - Blob ID
316
+ * @returns Blob metadata
317
+ */
318
+ async getMetadata(blobId: string): Promise<BlobMetadata> {
319
+ try {
320
+ // Use retrieveBlobMetadata (correct method name)
321
+ const metadata = await this.services.storage.retrieveBlobMetadata(blobId);
322
+ return metadata as BlobMetadata;
323
+ } catch (error) {
324
+ throw new Error(`Get metadata failed: ${error instanceof Error ? error.message : String(error)}`);
325
+ }
326
+ }
327
+
328
+ /**
329
+ * List blobs for user
330
+ *
331
+ * @param filter - Optional filter
332
+ * @returns Array of blob info
333
+ */
334
+ async listBlobs(filter?: { category?: string; limit?: number }): Promise<Array<{ blobId: string; metadata: BlobMetadata }>> {
335
+ try {
336
+ // Use searchByMetadata
337
+ const results = await this.services.storage.searchByMetadata(
338
+ this.services.config.userAddress,
339
+ {} // MetadataSearchQuery - minimal params
340
+ );
341
+
342
+ return results.map((r: any) => ({
343
+ blobId: r.blobId,
344
+ metadata: r.metadata || {}
345
+ }));
346
+ } catch (error) {
347
+ throw new Error(`List blobs failed: ${error instanceof Error ? error.message : String(error)}`);
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Get storage statistics
353
+ *
354
+ * Calculates total size from blob metadata (content_size field).
355
+ *
356
+ * @returns Storage stats
357
+ */
358
+ async getStats(): Promise<StorageStats> {
359
+ try {
360
+ // Get all blobs
361
+ const blobs = await this.listBlobs({ limit: 1000 });
362
+
363
+ const stats: StorageStats = {
364
+ totalBlobs: blobs.length,
365
+ totalSize: 0,
366
+ blobsByCategory: {}
367
+ };
368
+
369
+ // Count by category and accumulate size
370
+ blobs.forEach(b => {
371
+ const category = b.metadata.category as string || 'general';
372
+ stats.blobsByCategory[category] = (stats.blobsByCategory[category] || 0) + 1;
373
+
374
+ // Sum up content sizes from metadata
375
+ const size = Number(b.metadata.content_size || b.metadata.contentSize || b.metadata.size || 0);
376
+ if (!isNaN(size)) {
377
+ stats.totalSize += size;
378
+ }
379
+ });
380
+
381
+ return stats;
382
+ } catch (error) {
383
+ throw new Error(`Get storage stats failed: ${error instanceof Error ? error.message : String(error)}`);
384
+ }
385
+ }
386
+
387
+ /**
388
+ * Cleanup old or unused blobs
389
+ *
390
+ * Marks blobs as deleted if they meet cleanup criteria:
391
+ * - Already marked as deleted (removes from active queries)
392
+ * - Low importance and old (optional aggressive cleanup)
393
+ *
394
+ * Note: Walrus blobs cannot be truly deleted. This marks them
395
+ * as deleted via attributes for filtering in queries.
396
+ *
397
+ * @param options - Cleanup options
398
+ * @returns Number of blobs marked for cleanup
399
+ */
400
+ async cleanup(options?: {
401
+ /** Remove blobs already marked as deleted from listings */
402
+ removeDeleted?: boolean;
403
+ /** Mark old, low-importance blobs as deleted */
404
+ aggressiveCleanup?: boolean;
405
+ /** Max age in days for aggressive cleanup (default: 90) */
406
+ maxAgeDays?: number;
407
+ /** Max importance for aggressive cleanup (default: 3) */
408
+ maxImportance?: number;
409
+ }): Promise<number> {
410
+ try {
411
+ const {
412
+ removeDeleted = true,
413
+ aggressiveCleanup = false,
414
+ maxAgeDays = 90,
415
+ maxImportance = 3
416
+ } = options || {};
417
+
418
+ let cleanedCount = 0;
419
+ const blobs = await this.listBlobs({ limit: 1000 });
420
+
421
+ for (const blob of blobs) {
422
+ try {
423
+ const metadata = blob.metadata;
424
+
425
+ // Skip if already processed
426
+ if (metadata.deleted_at) {
427
+ continue;
428
+ }
429
+
430
+ // Aggressive cleanup: mark old, low-importance blobs
431
+ if (aggressiveCleanup) {
432
+ const importance = Number(metadata.importance) || 5;
433
+ const createdAt = metadata.created_at
434
+ ? new Date(metadata.created_at as string).getTime()
435
+ : Date.now();
436
+ const ageInDays = (Date.now() - createdAt) / (1000 * 60 * 60 * 24);
437
+
438
+ if (importance <= maxImportance && ageInDays >= maxAgeDays) {
439
+ await this.delete(blob.blobId);
440
+ cleanedCount++;
441
+ console.log(`Cleaned up old blob ${blob.blobId} (age: ${ageInDays.toFixed(0)} days, importance: ${importance})`);
442
+ }
443
+ }
444
+ } catch (blobError) {
445
+ console.warn(`Failed to process blob ${blob.blobId} during cleanup:`, blobError);
446
+ }
447
+ }
448
+
449
+ if (cleanedCount > 0) {
450
+ console.log(`Storage cleanup completed: ${cleanedCount} blobs marked for cleanup`);
451
+ }
452
+
453
+ return cleanedCount;
454
+ } catch (error) {
455
+ throw new Error(`Cleanup failed: ${error instanceof Error ? error.message : String(error)}`);
456
+ }
457
+ }
458
+ }