@cmdoss/memwal-sdk 0.7.0 → 0.9.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 (229) hide show
  1. package/README.md +427 -41
  2. package/dist/client/ClientMemoryManager.js +2 -2
  3. package/dist/client/ClientMemoryManager.js.map +1 -1
  4. package/dist/client/PersonalDataWallet.d.ts.map +1 -1
  5. package/dist/client/SimplePDWClient.d.ts +88 -1
  6. package/dist/client/SimplePDWClient.d.ts.map +1 -1
  7. package/dist/client/SimplePDWClient.js +102 -11
  8. package/dist/client/SimplePDWClient.js.map +1 -1
  9. package/dist/client/namespaces/IndexNamespace.d.ts +1 -1
  10. package/dist/client/namespaces/IndexNamespace.d.ts.map +1 -1
  11. package/dist/client/namespaces/IndexNamespace.js +7 -4
  12. package/dist/client/namespaces/IndexNamespace.js.map +1 -1
  13. package/dist/client/namespaces/MemoryNamespace.d.ts +45 -0
  14. package/dist/client/namespaces/MemoryNamespace.d.ts.map +1 -1
  15. package/dist/client/namespaces/MemoryNamespace.js +292 -46
  16. package/dist/client/namespaces/MemoryNamespace.js.map +1 -1
  17. package/dist/client/namespaces/consolidated/AdvancedNamespace.d.ts +215 -0
  18. package/dist/client/namespaces/consolidated/AdvancedNamespace.d.ts.map +1 -0
  19. package/dist/client/namespaces/consolidated/AdvancedNamespace.js +214 -0
  20. package/dist/client/namespaces/consolidated/AdvancedNamespace.js.map +1 -0
  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 +40 -2
  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/client/namespaces/consolidated/index.d.ts +1 -0
  30. package/dist/client/namespaces/consolidated/index.d.ts.map +1 -1
  31. package/dist/client/namespaces/consolidated/index.js +1 -0
  32. package/dist/client/namespaces/consolidated/index.js.map +1 -1
  33. package/dist/config/ConfigurationHelper.js +61 -61
  34. package/dist/config/defaults.d.ts.map +1 -1
  35. package/dist/config/defaults.js +11 -6
  36. package/dist/config/defaults.js.map +1 -1
  37. package/dist/core/types/index.d.ts +4 -0
  38. package/dist/core/types/index.d.ts.map +1 -1
  39. package/dist/core/types/index.js.map +1 -1
  40. package/dist/graph/GraphService.js +20 -20
  41. package/dist/infrastructure/seal/EncryptionService.d.ts +9 -5
  42. package/dist/infrastructure/seal/EncryptionService.d.ts.map +1 -1
  43. package/dist/infrastructure/seal/EncryptionService.js +37 -15
  44. package/dist/infrastructure/seal/EncryptionService.js.map +1 -1
  45. package/dist/infrastructure/seal/SealService.d.ts +13 -5
  46. package/dist/infrastructure/seal/SealService.d.ts.map +1 -1
  47. package/dist/infrastructure/seal/SealService.js +36 -34
  48. package/dist/infrastructure/seal/SealService.js.map +1 -1
  49. package/dist/infrastructure/walrus/WalrusStorageService.d.ts +6 -0
  50. package/dist/infrastructure/walrus/WalrusStorageService.d.ts.map +1 -1
  51. package/dist/infrastructure/walrus/WalrusStorageService.js +23 -4
  52. package/dist/infrastructure/walrus/WalrusStorageService.js.map +1 -1
  53. package/dist/langchain/createPDWRAG.js +30 -30
  54. package/dist/retrieval/MemoryDecryptionPipeline.d.ts.map +1 -1
  55. package/dist/retrieval/MemoryDecryptionPipeline.js +2 -1
  56. package/dist/retrieval/MemoryDecryptionPipeline.js.map +1 -1
  57. package/dist/services/CapabilityService.d.ts.map +1 -1
  58. package/dist/services/CapabilityService.js +30 -14
  59. package/dist/services/CapabilityService.js.map +1 -1
  60. package/dist/services/CrossContextPermissionService.d.ts.map +1 -1
  61. package/dist/services/CrossContextPermissionService.js +9 -7
  62. package/dist/services/CrossContextPermissionService.js.map +1 -1
  63. package/dist/services/EmbeddingService.d.ts +9 -0
  64. package/dist/services/EmbeddingService.d.ts.map +1 -1
  65. package/dist/services/EmbeddingService.js +31 -10
  66. package/dist/services/EmbeddingService.js.map +1 -1
  67. package/dist/services/EncryptionService.d.ts.map +1 -1
  68. package/dist/services/EncryptionService.js +6 -5
  69. package/dist/services/EncryptionService.js.map +1 -1
  70. package/dist/services/GeminiAIService.js +309 -309
  71. package/dist/services/MemoryIndexService.d.ts +2 -0
  72. package/dist/services/MemoryIndexService.d.ts.map +1 -1
  73. package/dist/services/MemoryIndexService.js +11 -4
  74. package/dist/services/MemoryIndexService.js.map +1 -1
  75. package/dist/services/StorageService.d.ts +1 -0
  76. package/dist/services/StorageService.d.ts.map +1 -1
  77. package/dist/services/StorageService.js +60 -10
  78. package/dist/services/StorageService.js.map +1 -1
  79. package/dist/services/TransactionService.d.ts +20 -0
  80. package/dist/services/TransactionService.d.ts.map +1 -1
  81. package/dist/services/TransactionService.js +43 -0
  82. package/dist/services/TransactionService.js.map +1 -1
  83. package/dist/services/VectorService.js +1 -1
  84. package/dist/services/VectorService.js.map +1 -1
  85. package/dist/services/ViewService.js +2 -2
  86. package/dist/services/ViewService.js.map +1 -1
  87. package/dist/vector/BrowserHnswIndexService.js +1 -1
  88. package/dist/vector/BrowserHnswIndexService.js.map +1 -1
  89. package/dist/vector/HnswWasmService.js +1 -1
  90. package/dist/vector/HnswWasmService.js.map +1 -1
  91. package/dist/vector/NodeHnswService.js +1 -1
  92. package/dist/vector/NodeHnswService.js.map +1 -1
  93. package/package.json +1 -1
  94. package/src/access/PermissionService.ts +635 -635
  95. package/src/access/index.ts +8 -8
  96. package/src/aggregation/AggregationService.ts +389 -389
  97. package/src/aggregation/index.ts +8 -8
  98. package/src/ai-sdk/PDWVectorStore.ts +715 -715
  99. package/src/ai-sdk/index.ts +65 -65
  100. package/src/ai-sdk/tools.ts +460 -460
  101. package/src/ai-sdk/types.ts +404 -404
  102. package/src/batch/BatchManager.ts +597 -597
  103. package/src/batch/BatchingService.ts +429 -429
  104. package/src/batch/MemoryProcessingCache.ts +492 -492
  105. package/src/batch/index.ts +30 -30
  106. package/src/browser.ts +200 -200
  107. package/src/client/ClientMemoryManager.ts +987 -987
  108. package/src/client/PersonalDataWallet.ts +345 -345
  109. package/src/client/SimplePDWClient.ts +1369 -1237
  110. package/src/client/factory.ts +154 -154
  111. package/src/client/namespaces/AnalyticsNamespace.ts +377 -377
  112. package/src/client/namespaces/BatchNamespace.ts +356 -356
  113. package/src/client/namespaces/CacheNamespace.ts +123 -123
  114. package/src/client/namespaces/CapabilityNamespace.ts +217 -217
  115. package/src/client/namespaces/ClassifyNamespace.ts +169 -169
  116. package/src/client/namespaces/ContextNamespace.ts +297 -297
  117. package/src/client/namespaces/EmbeddingsNamespace.ts +99 -99
  118. package/src/client/namespaces/EncryptionNamespace.ts +221 -221
  119. package/src/client/namespaces/GraphNamespace.ts +468 -468
  120. package/src/client/namespaces/IndexNamespace.ts +364 -361
  121. package/src/client/namespaces/MemoryNamespace.ts +1569 -1272
  122. package/src/client/namespaces/PermissionsNamespace.ts +254 -254
  123. package/src/client/namespaces/PipelineNamespace.ts +220 -220
  124. package/src/client/namespaces/SearchNamespace.ts +1049 -1049
  125. package/src/client/namespaces/StorageNamespace.ts +458 -458
  126. package/src/client/namespaces/TxNamespace.ts +260 -260
  127. package/src/client/namespaces/WalletNamespace.ts +243 -243
  128. package/src/client/namespaces/consolidated/AINamespace.ts +449 -449
  129. package/src/client/namespaces/consolidated/AdvancedNamespace.ts +264 -0
  130. package/src/client/namespaces/consolidated/BlockchainNamespace.ts +607 -564
  131. package/src/client/namespaces/consolidated/SecurityNamespace.ts +648 -648
  132. package/src/client/namespaces/consolidated/StorageNamespace.ts +1141 -497
  133. package/src/client/namespaces/consolidated/index.ts +41 -39
  134. package/src/client/signers/DappKitSigner.ts +207 -207
  135. package/src/client/signers/KeypairSigner.ts +108 -108
  136. package/src/client/signers/UnifiedSigner.ts +110 -110
  137. package/src/client/signers/WalletAdapterSigner.ts +159 -159
  138. package/src/client/signers/index.ts +26 -26
  139. package/src/config/ConfigurationHelper.ts +412 -412
  140. package/src/config/defaults.ts +56 -51
  141. package/src/config/index.ts +8 -8
  142. package/src/config/validation.ts +70 -70
  143. package/src/core/index.ts +14 -14
  144. package/src/core/interfaces/IService.ts +307 -307
  145. package/src/core/interfaces/index.ts +8 -8
  146. package/src/core/types/capability.ts +297 -297
  147. package/src/core/types/index.ts +874 -870
  148. package/src/core/types/wallet.ts +270 -270
  149. package/src/core/types.ts +9 -9
  150. package/src/core/wallet.ts +222 -222
  151. package/src/embedding/index.ts +19 -19
  152. package/src/embedding/types.ts +357 -357
  153. package/src/errors/index.ts +602 -602
  154. package/src/errors/recovery.ts +461 -461
  155. package/src/errors/validation.ts +567 -567
  156. package/src/generated/pdw/capability.ts +319 -319
  157. package/src/generated/pdw/deps/sui/object.ts +12 -12
  158. package/src/generated/pdw/deps/sui/vec_map.ts +32 -32
  159. package/src/generated/pdw/memory.ts +1087 -1087
  160. package/src/generated/pdw/wallet.ts +123 -123
  161. package/src/generated/utils/index.ts +159 -159
  162. package/src/graph/GraphService.ts +887 -887
  163. package/src/graph/KnowledgeGraphManager.ts +728 -728
  164. package/src/graph/index.ts +25 -25
  165. package/src/index.ts +498 -498
  166. package/src/infrastructure/index.ts +22 -22
  167. package/src/infrastructure/seal/EncryptionService.ts +628 -603
  168. package/src/infrastructure/seal/SealService.ts +613 -615
  169. package/src/infrastructure/seal/index.ts +9 -9
  170. package/src/infrastructure/sui/BlockchainManager.ts +627 -627
  171. package/src/infrastructure/sui/SuiService.ts +888 -888
  172. package/src/infrastructure/sui/index.ts +9 -9
  173. package/src/infrastructure/walrus/StorageManager.ts +604 -604
  174. package/src/infrastructure/walrus/WalrusStorageService.ts +637 -612
  175. package/src/infrastructure/walrus/index.ts +9 -9
  176. package/src/langchain/PDWEmbeddings.ts +145 -145
  177. package/src/langchain/PDWVectorStore.ts +456 -456
  178. package/src/langchain/createPDWRAG.ts +303 -303
  179. package/src/langchain/index.ts +47 -47
  180. package/src/permissions/ConsentRepository.browser.ts +249 -249
  181. package/src/permissions/ConsentRepository.ts +364 -364
  182. package/src/permissions/index.ts +9 -9
  183. package/src/pipeline/MemoryPipeline.ts +862 -862
  184. package/src/pipeline/PipelineManager.ts +683 -683
  185. package/src/pipeline/index.ts +26 -26
  186. package/src/retrieval/AdvancedSearchService.ts +629 -629
  187. package/src/retrieval/MemoryAnalyticsService.ts +711 -711
  188. package/src/retrieval/MemoryDecryptionPipeline.ts +825 -824
  189. package/src/retrieval/MemoryRetrievalService.ts +904 -904
  190. package/src/retrieval/index.ts +42 -42
  191. package/src/services/BatchService.ts +352 -352
  192. package/src/services/CapabilityService.ts +464 -448
  193. package/src/services/ClassifierService.ts +465 -465
  194. package/src/services/CrossContextPermissionService.ts +486 -484
  195. package/src/services/EmbeddingService.ts +796 -771
  196. package/src/services/EncryptionService.ts +712 -711
  197. package/src/services/GeminiAIService.ts +753 -753
  198. package/src/services/IndexManager.ts +977 -977
  199. package/src/services/MemoryIndexService.ts +1009 -1003
  200. package/src/services/MemoryService.ts +369 -369
  201. package/src/services/QueryService.ts +890 -890
  202. package/src/services/StorageService.ts +1182 -1126
  203. package/src/services/TransactionService.ts +838 -790
  204. package/src/services/VectorService.ts +462 -462
  205. package/src/services/ViewService.ts +484 -484
  206. package/src/services/index.ts +25 -25
  207. package/src/services/storage/BlobAttributesManager.ts +333 -333
  208. package/src/services/storage/KnowledgeGraphManager.ts +425 -425
  209. package/src/services/storage/MemorySearchManager.ts +387 -387
  210. package/src/services/storage/QuiltBatchManager.ts +1130 -1130
  211. package/src/services/storage/WalrusMetadataManager.ts +268 -268
  212. package/src/services/storage/WalrusStorageManager.ts +287 -287
  213. package/src/services/storage/index.ts +57 -57
  214. package/src/types/index.ts +13 -13
  215. package/src/utils/LRUCache.ts +378 -378
  216. package/src/utils/index.ts +76 -76
  217. package/src/utils/memoryIndexOnChain.ts +507 -507
  218. package/src/utils/rebuildIndex.ts +290 -290
  219. package/src/utils/rebuildIndexNode.ts +771 -771
  220. package/src/vector/BrowserHnswIndexService.ts +758 -758
  221. package/src/vector/HnswWasmService.ts +731 -731
  222. package/src/vector/IHnswService.ts +233 -233
  223. package/src/vector/NodeHnswService.ts +833 -833
  224. package/src/vector/VectorManager.ts +478 -478
  225. package/src/vector/createHnswService.ts +135 -135
  226. package/src/vector/index.ts +56 -56
  227. package/src/wallet/ContextWalletService.ts +656 -656
  228. package/src/wallet/MainWalletService.ts +317 -317
  229. package/src/wallet/index.ts +17 -17
@@ -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
+ }