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