@cmdoss/memwal-sdk 0.6.0 → 0.6.2

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 (273) hide show
  1. package/ARCHITECTURE.md +547 -463
  2. package/BENCHMARKS.md +238 -238
  3. package/README.md +181 -142
  4. package/dist/ai-sdk/PDWVectorStore.d.ts.map +1 -1
  5. package/dist/ai-sdk/PDWVectorStore.js +4 -1
  6. package/dist/ai-sdk/PDWVectorStore.js.map +1 -1
  7. package/dist/ai-sdk/types.d.ts +2 -2
  8. package/dist/ai-sdk/types.d.ts.map +1 -1
  9. package/dist/browser.d.ts +12 -13
  10. package/dist/browser.d.ts.map +1 -1
  11. package/dist/browser.js +18 -12
  12. package/dist/browser.js.map +1 -1
  13. package/dist/client/ClientMemoryManager.d.ts +1 -0
  14. package/dist/client/ClientMemoryManager.d.ts.map +1 -1
  15. package/dist/client/ClientMemoryManager.js +5 -1
  16. package/dist/client/ClientMemoryManager.js.map +1 -1
  17. package/dist/client/SimplePDWClient.d.ts +23 -0
  18. package/dist/client/SimplePDWClient.d.ts.map +1 -1
  19. package/dist/client/SimplePDWClient.js +19 -6
  20. package/dist/client/SimplePDWClient.js.map +1 -1
  21. package/dist/client/namespaces/BatchNamespace.js +2 -2
  22. package/dist/client/namespaces/BatchNamespace.js.map +1 -1
  23. package/dist/client/namespaces/IndexNamespace.d.ts +38 -9
  24. package/dist/client/namespaces/IndexNamespace.d.ts.map +1 -1
  25. package/dist/client/namespaces/IndexNamespace.js +77 -10
  26. package/dist/client/namespaces/IndexNamespace.js.map +1 -1
  27. package/dist/client/namespaces/MemoryNamespace.js +3 -3
  28. package/dist/client/namespaces/MemoryNamespace.js.map +1 -1
  29. package/dist/client/namespaces/SearchNamespace.d.ts.map +1 -1
  30. package/dist/client/namespaces/SearchNamespace.js +25 -14
  31. package/dist/client/namespaces/SearchNamespace.js.map +1 -1
  32. package/dist/client/namespaces/StorageNamespace.js +4 -4
  33. package/dist/client/namespaces/StorageNamespace.js.map +1 -1
  34. package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts.map +1 -1
  35. package/dist/client/namespaces/consolidated/BlockchainNamespace.js +49 -1
  36. package/dist/client/namespaces/consolidated/BlockchainNamespace.js.map +1 -1
  37. package/dist/client/namespaces/consolidated/StorageNamespace.d.ts +46 -0
  38. package/dist/client/namespaces/consolidated/StorageNamespace.d.ts.map +1 -1
  39. package/dist/client/namespaces/consolidated/StorageNamespace.js +36 -2
  40. package/dist/client/namespaces/consolidated/StorageNamespace.js.map +1 -1
  41. package/dist/client/signers/DappKitSigner.d.ts +136 -0
  42. package/dist/client/signers/DappKitSigner.d.ts.map +1 -0
  43. package/dist/client/signers/DappKitSigner.js +128 -0
  44. package/dist/client/signers/DappKitSigner.js.map +1 -0
  45. package/dist/client/signers/KeypairSigner.d.ts +4 -0
  46. package/dist/client/signers/KeypairSigner.d.ts.map +1 -1
  47. package/dist/client/signers/KeypairSigner.js +6 -0
  48. package/dist/client/signers/KeypairSigner.js.map +1 -1
  49. package/dist/client/signers/UnifiedSigner.d.ts +10 -0
  50. package/dist/client/signers/UnifiedSigner.d.ts.map +1 -1
  51. package/dist/client/signers/WalletAdapterSigner.d.ts +7 -0
  52. package/dist/client/signers/WalletAdapterSigner.d.ts.map +1 -1
  53. package/dist/client/signers/WalletAdapterSigner.js +9 -0
  54. package/dist/client/signers/WalletAdapterSigner.js.map +1 -1
  55. package/dist/client/signers/index.d.ts +3 -0
  56. package/dist/client/signers/index.d.ts.map +1 -1
  57. package/dist/client/signers/index.js +2 -0
  58. package/dist/client/signers/index.js.map +1 -1
  59. package/dist/generated/utils/index.js +1 -1
  60. package/dist/generated/utils/index.js.map +1 -1
  61. package/dist/graph/GraphService.js +1 -1
  62. package/dist/index.d.ts +2 -0
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +2 -0
  65. package/dist/index.js.map +1 -1
  66. package/dist/permissions/ConsentRepository.browser.d.ts +56 -0
  67. package/dist/permissions/ConsentRepository.browser.d.ts.map +1 -0
  68. package/dist/permissions/ConsentRepository.browser.js +198 -0
  69. package/dist/permissions/ConsentRepository.browser.js.map +1 -0
  70. package/dist/services/CapabilityService.js +1 -1
  71. package/dist/services/CapabilityService.js.map +1 -1
  72. package/dist/services/EncryptionService.js +1 -1
  73. package/dist/services/EncryptionService.js.map +1 -1
  74. package/dist/services/GeminiAIService.d.ts.map +1 -1
  75. package/dist/services/GeminiAIService.js +283 -27
  76. package/dist/services/GeminiAIService.js.map +1 -1
  77. package/dist/services/MemoryIndexService.d.ts +31 -2
  78. package/dist/services/MemoryIndexService.d.ts.map +1 -1
  79. package/dist/services/MemoryIndexService.js +75 -3
  80. package/dist/services/MemoryIndexService.js.map +1 -1
  81. package/dist/services/StorageService.d.ts +8 -8
  82. package/dist/services/StorageService.d.ts.map +1 -1
  83. package/dist/services/StorageService.js.map +1 -1
  84. package/dist/services/VectorService.js +2 -2
  85. package/dist/services/VectorService.js.map +1 -1
  86. package/dist/services/storage/BlobAttributesManager.d.ts +4 -4
  87. package/dist/services/storage/BlobAttributesManager.d.ts.map +1 -1
  88. package/dist/services/storage/BlobAttributesManager.js +6 -15
  89. package/dist/services/storage/BlobAttributesManager.js.map +1 -1
  90. package/dist/services/storage/QuiltBatchManager.d.ts +33 -8
  91. package/dist/services/storage/QuiltBatchManager.d.ts.map +1 -1
  92. package/dist/services/storage/QuiltBatchManager.js +153 -48
  93. package/dist/services/storage/QuiltBatchManager.js.map +1 -1
  94. package/dist/services/storage/WalrusMetadataManager.d.ts +2 -2
  95. package/dist/services/storage/WalrusMetadataManager.d.ts.map +1 -1
  96. package/dist/services/storage/WalrusMetadataManager.js +2 -5
  97. package/dist/services/storage/WalrusMetadataManager.js.map +1 -1
  98. package/dist/services/storage/WalrusStorageManager.d.ts +2 -2
  99. package/dist/services/storage/WalrusStorageManager.d.ts.map +1 -1
  100. package/dist/services/storage/WalrusStorageManager.js +7 -11
  101. package/dist/services/storage/WalrusStorageManager.js.map +1 -1
  102. package/dist/utils/rebuildIndexNode.d.ts.map +1 -1
  103. package/dist/utils/rebuildIndexNode.js +109 -35
  104. package/dist/utils/rebuildIndexNode.js.map +1 -1
  105. package/dist/vector/NodeHnswService.d.ts.map +1 -1
  106. package/dist/vector/NodeHnswService.js +26 -7
  107. package/dist/vector/NodeHnswService.js.map +1 -1
  108. package/dist/wallet/MainWalletService.js +1 -1
  109. package/dist/wallet/MainWalletService.js.map +1 -1
  110. package/package.json +10 -3
  111. package/src/access/index.ts +8 -8
  112. package/src/aggregation/index.ts +8 -8
  113. package/src/ai-sdk/PDWVectorStore.ts +4 -1
  114. package/src/ai-sdk/types.ts +2 -2
  115. package/src/browser.ts +28 -24
  116. package/src/client/ClientMemoryManager.ts +6 -1
  117. package/src/client/SimplePDWClient.ts +57 -15
  118. package/src/client/namespaces/BatchNamespace.ts +2 -2
  119. package/src/client/namespaces/IndexNamespace.ts +89 -11
  120. package/src/client/namespaces/MemoryNamespace.ts +3 -3
  121. package/src/client/namespaces/SearchNamespace.ts +27 -14
  122. package/src/client/namespaces/StorageNamespace.ts +4 -4
  123. package/src/client/namespaces/consolidated/BlockchainNamespace.ts +55 -1
  124. package/src/client/namespaces/consolidated/StorageNamespace.ts +59 -2
  125. package/src/client/signers/DappKitSigner.ts +207 -0
  126. package/src/client/signers/KeypairSigner.ts +7 -0
  127. package/src/client/signers/UnifiedSigner.ts +11 -0
  128. package/src/client/signers/WalletAdapterSigner.ts +10 -0
  129. package/src/client/signers/index.ts +7 -0
  130. package/src/generated/pdw/capability.ts +319 -319
  131. package/src/generated/utils/index.ts +1 -1
  132. package/src/graph/GraphService.ts +1 -1
  133. package/src/index.ts +16 -0
  134. package/src/permissions/ConsentRepository.browser.ts +249 -0
  135. package/src/permissions/index.ts +9 -9
  136. package/src/services/CapabilityService.ts +1 -1
  137. package/src/services/EncryptionService.ts +1 -1
  138. package/src/services/GeminiAIService.ts +283 -27
  139. package/src/services/MemoryIndexService.ts +85 -3
  140. package/src/services/StorageService.ts +8 -8
  141. package/src/services/VectorService.ts +2 -2
  142. package/src/services/storage/BlobAttributesManager.ts +10 -19
  143. package/src/services/storage/QuiltBatchManager.ts +178 -50
  144. package/src/services/storage/WalrusMetadataManager.ts +4 -7
  145. package/src/services/storage/WalrusStorageManager.ts +10 -13
  146. package/src/utils/rebuildIndexNode.ts +126 -43
  147. package/src/vector/NodeHnswService.ts +29 -7
  148. package/src/wallet/MainWalletService.ts +1 -1
  149. package/src/wallet/index.ts +17 -17
  150. package/dist/api/client.d.ts +0 -43
  151. package/dist/api/client.d.ts.map +0 -1
  152. package/dist/api/client.js +0 -136
  153. package/dist/api/client.js.map +0 -1
  154. package/dist/chat/index.d.ts +0 -13
  155. package/dist/chat/index.d.ts.map +0 -1
  156. package/dist/chat/index.js +0 -14
  157. package/dist/chat/index.js.map +0 -1
  158. package/dist/client/namespaces/ChatNamespace.d.ts +0 -110
  159. package/dist/client/namespaces/ChatNamespace.d.ts.map +0 -1
  160. package/dist/client/namespaces/ChatNamespace.js +0 -123
  161. package/dist/client/namespaces/ChatNamespace.js.map +0 -1
  162. package/dist/encryption/index.d.ts +0 -14
  163. package/dist/encryption/index.d.ts.map +0 -1
  164. package/dist/encryption/index.js +0 -14
  165. package/dist/encryption/index.js.map +0 -1
  166. package/dist/graph/BrowserKnowledgeGraphManager.d.ts +0 -101
  167. package/dist/graph/BrowserKnowledgeGraphManager.d.ts.map +0 -1
  168. package/dist/graph/BrowserKnowledgeGraphManager.js +0 -411
  169. package/dist/graph/BrowserKnowledgeGraphManager.js.map +0 -1
  170. package/dist/hooks.wip/index.d.ts +0 -55
  171. package/dist/hooks.wip/index.d.ts.map +0 -1
  172. package/dist/hooks.wip/index.js +0 -58
  173. package/dist/hooks.wip/index.js.map +0 -1
  174. package/dist/hooks.wip/useCreateMemory.d.ts +0 -111
  175. package/dist/hooks.wip/useCreateMemory.d.ts.map +0 -1
  176. package/dist/hooks.wip/useCreateMemory.js +0 -149
  177. package/dist/hooks.wip/useCreateMemory.js.map +0 -1
  178. package/dist/hooks.wip/useCreateMemoryBatch.d.ts +0 -122
  179. package/dist/hooks.wip/useCreateMemoryBatch.d.ts.map +0 -1
  180. package/dist/hooks.wip/useCreateMemoryBatch.js +0 -221
  181. package/dist/hooks.wip/useCreateMemoryBatch.js.map +0 -1
  182. package/dist/hooks.wip/useKnowledgeGraph.d.ts +0 -66
  183. package/dist/hooks.wip/useKnowledgeGraph.d.ts.map +0 -1
  184. package/dist/hooks.wip/useKnowledgeGraph.js +0 -229
  185. package/dist/hooks.wip/useKnowledgeGraph.js.map +0 -1
  186. package/dist/hooks.wip/useMemoryChat.d.ts +0 -106
  187. package/dist/hooks.wip/useMemoryChat.d.ts.map +0 -1
  188. package/dist/hooks.wip/useMemoryChat.js +0 -284
  189. package/dist/hooks.wip/useMemoryChat.js.map +0 -1
  190. package/dist/hooks.wip/useMemoryIndex.d.ts +0 -90
  191. package/dist/hooks.wip/useMemoryIndex.d.ts.map +0 -1
  192. package/dist/hooks.wip/useMemoryIndex.js +0 -218
  193. package/dist/hooks.wip/useMemoryIndex.js.map +0 -1
  194. package/dist/hooks.wip/useMemoryManager.d.ts +0 -35
  195. package/dist/hooks.wip/useMemoryManager.d.ts.map +0 -1
  196. package/dist/hooks.wip/useMemoryManager.js +0 -86
  197. package/dist/hooks.wip/useMemoryManager.js.map +0 -1
  198. package/dist/hooks.wip/useMemorySearch.d.ts +0 -100
  199. package/dist/hooks.wip/useMemorySearch.d.ts.map +0 -1
  200. package/dist/hooks.wip/useMemorySearch.js +0 -278
  201. package/dist/hooks.wip/useMemorySearch.js.map +0 -1
  202. package/dist/hooks.wip/useMemoryServices.d.ts +0 -80
  203. package/dist/hooks.wip/useMemoryServices.d.ts.map +0 -1
  204. package/dist/hooks.wip/useMemoryServices.js +0 -264
  205. package/dist/hooks.wip/useMemoryServices.js.map +0 -1
  206. package/dist/hooks.wip/usePDWRAG.d.ts +0 -112
  207. package/dist/hooks.wip/usePDWRAG.d.ts.map +0 -1
  208. package/dist/hooks.wip/usePDWRAG.js +0 -121
  209. package/dist/hooks.wip/usePDWRAG.js.map +0 -1
  210. package/dist/hooks.wip/usePDWVectorStore.d.ts +0 -68
  211. package/dist/hooks.wip/usePDWVectorStore.d.ts.map +0 -1
  212. package/dist/hooks.wip/usePDWVectorStore.js +0 -102
  213. package/dist/hooks.wip/usePDWVectorStore.js.map +0 -1
  214. package/dist/hooks.wip/useRetrieveEmbedding.d.ts +0 -138
  215. package/dist/hooks.wip/useRetrieveEmbedding.d.ts.map +0 -1
  216. package/dist/hooks.wip/useRetrieveEmbedding.js +0 -121
  217. package/dist/hooks.wip/useRetrieveEmbedding.js.map +0 -1
  218. package/dist/hooks.wip/useSearchMemories.d.ts +0 -103
  219. package/dist/hooks.wip/useSearchMemories.d.ts.map +0 -1
  220. package/dist/hooks.wip/useSearchMemories.js +0 -146
  221. package/dist/hooks.wip/useSearchMemories.js.map +0 -1
  222. package/dist/hooks.wip/useStoreEmbedding.d.ts +0 -174
  223. package/dist/hooks.wip/useStoreEmbedding.d.ts.map +0 -1
  224. package/dist/hooks.wip/useStoreEmbedding.js +0 -167
  225. package/dist/hooks.wip/useStoreEmbedding.js.map +0 -1
  226. package/dist/hooks.wip/useWalletMemories.d.ts +0 -119
  227. package/dist/hooks.wip/useWalletMemories.d.ts.map +0 -1
  228. package/dist/hooks.wip/useWalletMemories.js +0 -166
  229. package/dist/hooks.wip/useWalletMemories.js.map +0 -1
  230. package/dist/hooks.wip/utils/cache.d.ts +0 -25
  231. package/dist/hooks.wip/utils/cache.d.ts.map +0 -1
  232. package/dist/hooks.wip/utils/cache.js +0 -38
  233. package/dist/hooks.wip/utils/cache.js.map +0 -1
  234. package/dist/hooks.wip/utils/types.d.ts +0 -138
  235. package/dist/hooks.wip/utils/types.d.ts.map +0 -1
  236. package/dist/hooks.wip/utils/types.js +0 -5
  237. package/dist/hooks.wip/utils/types.js.map +0 -1
  238. package/dist/infrastructure/ai/EmbeddingService.d.ts +0 -101
  239. package/dist/infrastructure/ai/EmbeddingService.d.ts.map +0 -1
  240. package/dist/infrastructure/ai/EmbeddingService.js +0 -242
  241. package/dist/infrastructure/ai/EmbeddingService.js.map +0 -1
  242. package/dist/infrastructure/ai/GeminiAIService.d.ts +0 -84
  243. package/dist/infrastructure/ai/GeminiAIService.d.ts.map +0 -1
  244. package/dist/infrastructure/ai/GeminiAIService.js +0 -300
  245. package/dist/infrastructure/ai/GeminiAIService.js.map +0 -1
  246. package/dist/infrastructure/ai/index.d.ts +0 -8
  247. package/dist/infrastructure/ai/index.d.ts.map +0 -1
  248. package/dist/infrastructure/ai/index.js +0 -8
  249. package/dist/infrastructure/ai/index.js.map +0 -1
  250. package/dist/memory/index.d.ts +0 -13
  251. package/dist/memory/index.d.ts.map +0 -1
  252. package/dist/memory/index.js +0 -14
  253. package/dist/memory/index.js.map +0 -1
  254. package/dist/services/ChatService.d.ts +0 -89
  255. package/dist/services/ChatService.d.ts.map +0 -1
  256. package/dist/services/ChatService.js +0 -319
  257. package/dist/services/ChatService.js.map +0 -1
  258. package/dist/transactions/index.d.ts +0 -13
  259. package/dist/transactions/index.d.ts.map +0 -1
  260. package/dist/transactions/index.js +0 -14
  261. package/dist/transactions/index.js.map +0 -1
  262. package/dist/types/wallet.d.ts +0 -12
  263. package/dist/types/wallet.d.ts.map +0 -1
  264. package/dist/types/wallet.js +0 -13
  265. package/dist/types/wallet.js.map +0 -1
  266. package/dist/view/ViewService.d.ts +0 -136
  267. package/dist/view/ViewService.d.ts.map +0 -1
  268. package/dist/view/ViewService.js +0 -325
  269. package/dist/view/ViewService.js.map +0 -1
  270. package/dist/view/index.d.ts +0 -7
  271. package/dist/view/index.d.ts.map +0 -1
  272. package/dist/view/index.js +0 -7
  273. package/dist/view/index.js.map +0 -1
@@ -568,18 +568,34 @@ export class MemoryIndexService {
568
568
  }
569
569
 
570
570
  /**
571
- * Load index from storage
571
+ * Load index from storage (local or Walrus)
572
+ *
573
+ * @param userAddress - User's wallet address
574
+ * @param indexBlobId - Optional Walrus blob ID to load from cloud
572
575
  */
573
576
  async loadIndex(userAddress: string, indexBlobId?: string): Promise<void> {
574
577
  const hnswService = await this.getHnswService();
578
+
579
+ // If blobId provided, try to load from Walrus first
580
+ if (indexBlobId && 'loadFromWalrus' in hnswService) {
581
+ console.log(`📥 Attempting to load index from Walrus: ${indexBlobId}`);
582
+ const walrusLoaded = await (hnswService as any).loadFromWalrus(userAddress, indexBlobId);
583
+ if (walrusLoaded) {
584
+ console.log(`✅ Memory index loaded from Walrus for user ${userAddress}`);
585
+ return;
586
+ }
587
+ console.log(`⚠️ Walrus load failed, falling back to local storage`);
588
+ }
589
+
590
+ // Fallback to local storage
575
591
  const loaded = await hnswService.loadIndex(userAddress);
576
592
  if (loaded) {
577
- console.log(`✅ Memory index loaded for user ${userAddress}`);
593
+ console.log(`✅ Memory index loaded from local storage for user ${userAddress}`);
578
594
  }
579
595
  }
580
596
 
581
597
  /**
582
- * Save index to storage
598
+ * Save index to local storage
583
599
  */
584
600
  async saveIndex(userAddress: string): Promise<void> {
585
601
  const hnswService = await this.getHnswService();
@@ -587,6 +603,72 @@ export class MemoryIndexService {
587
603
  console.log(`✅ Memory index saved for user ${userAddress}`);
588
604
  }
589
605
 
606
+ /**
607
+ * Sync index to Walrus cloud storage
608
+ *
609
+ * @param userAddress - User's wallet address
610
+ * @returns Walrus blob ID if successful, null if Walrus is disabled
611
+ */
612
+ async syncToWalrus(userAddress: string): Promise<string | null> {
613
+ const hnswService = await this.getHnswService();
614
+
615
+ if (!('syncToWalrus' in hnswService)) {
616
+ console.warn('⚠️ HNSW service does not support Walrus sync');
617
+ return null;
618
+ }
619
+
620
+ const blobId = await (hnswService as any).syncToWalrus(userAddress);
621
+ if (blobId) {
622
+ console.log(`☁️ Memory index synced to Walrus: ${blobId}`);
623
+ }
624
+ return blobId;
625
+ }
626
+
627
+ /**
628
+ * Load index directly from Walrus cloud storage
629
+ *
630
+ * @param userAddress - User's wallet address
631
+ * @param blobId - Walrus blob ID
632
+ * @returns true if successfully loaded
633
+ */
634
+ async loadFromWalrus(userAddress: string, blobId: string): Promise<boolean> {
635
+ const hnswService = await this.getHnswService();
636
+
637
+ if (!('loadFromWalrus' in hnswService)) {
638
+ console.warn('⚠️ HNSW service does not support Walrus load');
639
+ return false;
640
+ }
641
+
642
+ const loaded = await (hnswService as any).loadFromWalrus(userAddress, blobId);
643
+ if (loaded) {
644
+ console.log(`☁️ Memory index loaded from Walrus: ${blobId}`);
645
+ }
646
+ return loaded;
647
+ }
648
+
649
+ /**
650
+ * Get the Walrus blob ID for a user's index (if backed up)
651
+ *
652
+ * @param userAddress - User's wallet address
653
+ * @returns Blob ID or null if not backed up
654
+ */
655
+ getWalrusBlobId(userAddress: string): string | null {
656
+ if (this.hnswService && 'getWalrusBlobId' in this.hnswService) {
657
+ return (this.hnswService as any).getWalrusBlobId(userAddress);
658
+ }
659
+ return null;
660
+ }
661
+
662
+ /**
663
+ * Check if Walrus backup is enabled
664
+ */
665
+ isWalrusEnabled(): boolean {
666
+ if (this.hnswService && 'isWalrusEnabled' in this.hnswService) {
667
+ return (this.hnswService as any).isWalrusEnabled();
668
+ }
669
+ return false;
670
+ }
671
+
590
672
  /**
591
673
  * Clear user's index
592
674
  */
@@ -15,7 +15,7 @@
15
15
  import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
16
16
  import { Transaction } from '@mysten/sui/transactions';
17
17
  import { WalrusClient, WalrusFile } from '@mysten/walrus';
18
- import type { Signer } from '@mysten/sui/cryptography';
18
+ import type { UnifiedSigner } from '../client/signers/UnifiedSigner';
19
19
  import type { ClientWithExtensions } from '@mysten/sui/experimental';
20
20
  import type { SealService } from '../infrastructure/seal/SealService';
21
21
  import type { BatchService } from './BatchService';
@@ -71,7 +71,7 @@ export interface WalrusUploadResult {
71
71
  }
72
72
 
73
73
  export interface BlobUploadOptions {
74
- signer: Signer;
74
+ signer: UnifiedSigner;
75
75
  epochs?: number;
76
76
  deletable?: boolean;
77
77
  useUploadRelay?: boolean;
@@ -817,7 +817,7 @@ export class StorageService {
817
817
  summary?: string;
818
818
  }>,
819
819
  options: {
820
- signer: Signer;
820
+ signer: UnifiedSigner;
821
821
  epochs?: number;
822
822
  userAddress: string;
823
823
  }
@@ -856,7 +856,7 @@ export class StorageService {
856
856
  tags?: Record<string, string>;
857
857
  }>,
858
858
  options: {
859
- signer: Signer;
859
+ signer: UnifiedSigner;
860
860
  epochs?: number;
861
861
  userAddress: string;
862
862
  }
@@ -924,7 +924,7 @@ export class StorageService {
924
924
  async setBlobAttributes(
925
925
  blobObjectId: string,
926
926
  attributes: Record<string, string>,
927
- signer: Signer
927
+ signer: UnifiedSigner
928
928
  ): Promise<string> {
929
929
  return this.blobAttributes.setBlobAttributes(blobObjectId, attributes, signer);
930
930
  }
@@ -945,7 +945,7 @@ export class StorageService {
945
945
  async updateBlobAttributes(
946
946
  blobObjectId: string,
947
947
  attributes: Record<string, string>,
948
- signer: Signer
948
+ signer: UnifiedSigner
949
949
  ): Promise<string> {
950
950
  return this.blobAttributes.updateBlobAttributes(blobObjectId, attributes, signer);
951
951
  }
@@ -956,7 +956,7 @@ export class StorageService {
956
956
  async removeBlobAttributes(
957
957
  blobObjectId: string,
958
958
  attributeKeys: string[],
959
- signer: Signer
959
+ signer: UnifiedSigner
960
960
  ): Promise<string> {
961
961
  return this.blobAttributes.removeBlobAttributes(blobObjectId, attributeKeys, signer);
962
962
  }
@@ -1009,7 +1009,7 @@ export class StorageService {
1009
1009
  async attachMetadataToBlob(
1010
1010
  blobId: string,
1011
1011
  metadata: WalrusMemoryMetadata,
1012
- signer: Signer
1012
+ signer: UnifiedSigner
1013
1013
  ): Promise<{ digest: string; effects: any }> {
1014
1014
  const walrusPackageId = this.config.network === 'mainnet'
1015
1015
  ? '0x<mainnet-walrus-package-id>'
@@ -238,14 +238,14 @@ export class VectorService {
238
238
 
239
239
  const searchTime = performance.now() - startTime;
240
240
 
241
- // Get metadata from local cache
241
+ // Get metadata - prefer HNSW service metadata (loaded from disk) over local cache
242
242
  return {
243
243
  results: searchResults.map((result) => ({
244
244
  memoryId: result.vectorId.toString(),
245
245
  vectorId: result.vectorId,
246
246
  similarity: result.score,
247
247
  distance: result.distance,
248
- metadata: entry?.metadata.get(result.vectorId) || result.metadata
248
+ metadata: result.metadata || entry?.metadata.get(result.vectorId)
249
249
  })),
250
250
  searchStats: {
251
251
  searchTime,
@@ -12,8 +12,8 @@
12
12
  */
13
13
 
14
14
  import type { SuiClient } from '@mysten/sui/client';
15
- import type { Signer } from '@mysten/sui/cryptography';
16
15
  import { Transaction } from '@mysten/sui/transactions';
16
+ import type { UnifiedSigner } from '../../client/signers/UnifiedSigner';
17
17
 
18
18
  export interface BlobQueryResult {
19
19
  blobObjectId: string;
@@ -44,7 +44,7 @@ export class BlobAttributesManager {
44
44
  async setBlobAttributes(
45
45
  blobObjectId: string,
46
46
  attributes: Record<string, string>,
47
- signer: Signer
47
+ signer: UnifiedSigner
48
48
  ): Promise<string> {
49
49
  try {
50
50
  console.log(`🏷️ Setting ${Object.keys(attributes).length} attributes on blob ${blobObjectId.slice(0, 10)}...`);
@@ -69,12 +69,9 @@ export class BlobAttributesManager {
69
69
  console.log(` ✓ ${key}: ${value.slice(0, 50)}${value.length > 50 ? '...' : ''}`);
70
70
  }
71
71
 
72
- tx.setSender(signer.toSuiAddress());
72
+ tx.setSender(signer.getAddress());
73
73
 
74
- const result = await signer.signAndExecuteTransaction({
75
- transaction: tx,
76
- client: this.suiClient,
77
- });
74
+ const result = await signer.signAndExecuteTransaction(tx);
78
75
 
79
76
  console.log(`✅ Attributes set successfully!`);
80
77
  console.log(` Transaction: ${result.digest}`);
@@ -163,7 +160,7 @@ export class BlobAttributesManager {
163
160
  async updateBlobAttributes(
164
161
  blobObjectId: string,
165
162
  attributes: Record<string, string>,
166
- signer: Signer
163
+ signer: UnifiedSigner
167
164
  ): Promise<string> {
168
165
  try {
169
166
  console.log(`📝 Updating ${Object.keys(attributes).length} attributes on blob ${blobObjectId.slice(0, 10)}...`);
@@ -202,12 +199,9 @@ export class BlobAttributesManager {
202
199
  console.log(` ✓ Updated ${key}: ${value.slice(0, 50)}${value.length > 50 ? '...' : ''}`);
203
200
  }
204
201
 
205
- tx.setSender(signer.toSuiAddress());
202
+ tx.setSender(signer.getAddress());
206
203
 
207
- const result = await signer.signAndExecuteTransaction({
208
- transaction: tx,
209
- client: this.suiClient,
210
- });
204
+ const result = await signer.signAndExecuteTransaction(tx);
211
205
 
212
206
  console.log(`✅ Attributes updated successfully!`);
213
207
  console.log(` Transaction: ${result.digest}`);
@@ -226,7 +220,7 @@ export class BlobAttributesManager {
226
220
  async removeBlobAttributes(
227
221
  blobObjectId: string,
228
222
  attributeKeys: string[],
229
- signer: Signer
223
+ signer: UnifiedSigner
230
224
  ): Promise<string> {
231
225
  try {
232
226
  console.log(`🗑️ Removing ${attributeKeys.length} attributes from blob ${blobObjectId.slice(0, 10)}...`);
@@ -249,12 +243,9 @@ export class BlobAttributesManager {
249
243
  console.log(` ✓ Removed ${key}`);
250
244
  }
251
245
 
252
- tx.setSender(signer.toSuiAddress());
246
+ tx.setSender(signer.getAddress());
253
247
 
254
- const result = await signer.signAndExecuteTransaction({
255
- transaction: tx,
256
- client: this.suiClient,
257
- });
248
+ const result = await signer.signAndExecuteTransaction(tx);
258
249
 
259
250
  console.log(`✅ Attributes removed successfully!`);
260
251
  console.log(` Transaction: ${result.digest}`);
@@ -8,7 +8,7 @@
8
8
  * - Batch upload with ~90% gas savings (single transaction for multiple files)
9
9
  * - Tag-based filtering at the Walrus level
10
10
  * - Multi-file retrieval via quiltPatchId
11
- * - Browser-compatible using writeFilesFlow
11
+ * - Browser-compatible using writeFilesFlow (2 user signatures)
12
12
  *
13
13
  * Quilt Structure:
14
14
  * - quiltId: ID of the entire batch (blob containing all files)
@@ -16,13 +16,19 @@
16
16
  * - identifier: Human-readable name for each file
17
17
  * - tags: Metadata for filtering (category, importance, etc.)
18
18
  *
19
+ * Upload Flow (writeFilesFlow - works with DappKitSigner):
20
+ * 1. encode() - Encode files into blob format (no signature)
21
+ * 2. register() - Register blob on-chain (USER SIGNS - Transaction 1)
22
+ * 3. upload() - Upload to Walrus storage nodes (no signature)
23
+ * 4. certify() - Certify upload on-chain (USER SIGNS - Transaction 2)
24
+ *
19
25
  * @see https://sdk.mystenlabs.com/walrus/index
20
26
  */
21
27
 
22
28
  import { WalrusClient, WalrusFile } from '@mysten/walrus';
23
- import type { Signer } from '@mysten/sui/cryptography';
24
29
  import type { ClientWithExtensions } from '@mysten/sui/experimental';
25
30
  import type { SuiClient } from '@mysten/sui/client';
31
+ import type { UnifiedSigner } from '../../client/signers/UnifiedSigner';
26
32
 
27
33
  // ============================================================================
28
34
  // Types
@@ -40,7 +46,7 @@ export interface BatchMemory {
40
46
  }
41
47
 
42
48
  export interface QuiltUploadOptions {
43
- signer: Signer;
49
+ signer: UnifiedSigner;
44
50
  epochs?: number;
45
51
  userAddress: string;
46
52
  deletable?: boolean;
@@ -119,7 +125,13 @@ export class QuiltBatchManager {
119
125
  // ==========================================================================
120
126
 
121
127
  /**
122
- * Upload batch of memories as a Quilt
128
+ * Upload batch of memories as a Quilt using writeFilesFlow
129
+ *
130
+ * Uses the writeFilesFlow pattern which works with DappKitSigner:
131
+ * 1. encode() - Encode files (no signature)
132
+ * 2. register() - Register blob on-chain (USER SIGNS)
133
+ * 3. upload() - Upload to storage nodes (no signature)
134
+ * 4. certify() - Certify upload on-chain (USER SIGNS)
123
135
  *
124
136
  * Each memory becomes a WalrusFile with:
125
137
  * - Identifier: unique file name (memory-{timestamp}-{index}-{random}.json)
@@ -137,7 +149,7 @@ export class QuiltBatchManager {
137
149
  const startTime = performance.now();
138
150
  let totalSize = 0;
139
151
 
140
- console.log(`📦 Uploading batch of ${memories.length} memories as Quilt...`);
152
+ console.log(`📦 Uploading batch of ${memories.length} memories as Quilt (writeFilesFlow)...`);
141
153
 
142
154
  try {
143
155
  // Create WalrusFile for each memory with plaintext tags
@@ -181,42 +193,78 @@ export class QuiltBatchManager {
181
193
  console.log(` Total size: ${(totalSize / 1024).toFixed(2)} KB`);
182
194
  console.log(` Using upload relay: ${this.useUploadRelay}`);
183
195
 
184
- // Upload as Quilt using writeFiles
196
+ // Use writeFilesFlow pattern (works with DappKitSigner)
185
197
  const walrusClient = this.useUploadRelay
186
198
  ? this.walrusWithRelay
187
199
  : this.walrusWithoutRelay;
188
200
 
189
- const results = await walrusClient.writeFiles({
190
- files,
201
+ // Step 1: Create flow and encode files (no signature needed)
202
+ console.log(` Step 1/4: Encoding files...`);
203
+ const flow = walrusClient.writeFilesFlow({ files });
204
+ await flow.encode();
205
+ console.log(` ✓ Files encoded`);
206
+
207
+ // Step 2: Register blob on-chain (USER SIGNS - Transaction 1)
208
+ console.log(` Step 2/4: Registering blob (requires signature)...`);
209
+ const registerTx = flow.register({
191
210
  epochs: options.epochs || this.epochs,
192
- deletable: options.deletable ?? true,
193
- signer: options.signer
211
+ owner: options.userAddress,
212
+ deletable: options.deletable ?? true
194
213
  });
195
214
 
215
+ const registerResult = await options.signer.signAndExecuteTransaction(registerTx);
216
+ console.log(` ✓ Blob registered, digest: ${registerResult.digest}`);
217
+
218
+ // Step 3: Upload to Walrus storage nodes (no signature needed)
219
+ console.log(` Step 3/4: Uploading to storage nodes...`);
220
+ await flow.upload({ digest: registerResult.digest });
221
+ console.log(` ✓ Uploaded to storage nodes`);
222
+
223
+ // Step 4: Certify upload on-chain (USER SIGNS - Transaction 2)
224
+ console.log(` Step 4/4: Certifying upload (requires signature)...`);
225
+ const certifyTx = flow.certify();
226
+
227
+ if (certifyTx) {
228
+ const certifyResult = await options.signer.signAndExecuteTransaction(certifyTx);
229
+ console.log(` ✓ Upload certified, digest: ${certifyResult.digest}`);
230
+ } else {
231
+ console.log(` ✓ No certification needed (already certified)`);
232
+ }
233
+
234
+ // Get uploaded files info from flow
235
+ const uploadedFilesInfo = await flow.listFiles();
236
+
196
237
  const uploadTimeMs = performance.now() - startTime;
197
238
  const gasSaved = memories.length > 1
198
239
  ? `~${((1 - 1 / memories.length) * 100).toFixed(0)}%`
199
240
  : '0%';
200
241
 
201
242
  console.log(`✅ Quilt upload successful!`);
202
- console.log(` Quilt ID: ${results[0]?.id || 'N/A'}`);
203
- console.log(` Blob ID: ${results[0]?.blobId || 'N/A'}`);
204
- console.log(` Files uploaded: ${results.length}`);
243
+ console.log(` Files uploaded: ${uploadedFilesInfo.length}`);
205
244
  console.log(` Upload time: ${uploadTimeMs.toFixed(1)}ms`);
206
245
  console.log(` Gas saved: ${gasSaved} vs individual uploads`);
207
246
 
208
- // Build file results with identifiers (use original files array, not WalrusFile objects)
247
+ // Build file results using original WalrusFile objects for metadata
248
+ // Use shared quiltId as blobId - SDK can only read via getBlob(quiltId).files()
249
+ // Match files by identifier when reading
250
+ const quiltId = uploadedFilesInfo[0]?.blobId || '';
251
+
209
252
  const fileResults: QuiltFileResult[] = await Promise.all(
210
- results.map(async (r, i) => {
211
- // Get identifier from original WalrusFile object
212
- const file = files[i];
213
- const identifier = await file?.getIdentifier() || `file-${i}`;
214
- const tags = await file?.getTags() || {};
253
+ files.map(async (originalFile, i) => {
254
+ const identifier = await originalFile.getIdentifier() || `file-${i}`;
255
+ const tags = await originalFile.getTags() || {};
256
+ const fileInfo = uploadedFilesInfo[i];
257
+
258
+ // quiltPatchId is stored for reference but not used for retrieval
259
+ const quiltPatchId = fileInfo?.id || '';
260
+
261
+ console.log(` File ${i}: identifier=${identifier}, quiltId=${quiltId.substring(0, 20)}...`);
215
262
 
216
263
  return {
217
264
  identifier,
218
- blobId: r.blobId,
219
- quiltPatchId: undefined, // Not available from writeFiles result
265
+ // Use shared quiltId as blobId - read via getBlob(quiltId).files()
266
+ blobId: quiltId,
267
+ quiltPatchId,
220
268
  tags: Object.fromEntries(
221
269
  Object.entries(tags).map(([k, v]) => [k, String(v)])
222
270
  ),
@@ -226,8 +274,8 @@ export class QuiltBatchManager {
226
274
  );
227
275
 
228
276
  return {
229
- quiltId: results[0]?.id || results[0]?.blobId,
230
- blobObjectId: results[0]?.blobObject?.id?.id,
277
+ quiltId,
278
+ blobObjectId: undefined, // Not available from flow
231
279
  files: fileResults,
232
280
  uploadTimeMs,
233
281
  totalSize,
@@ -241,7 +289,13 @@ export class QuiltBatchManager {
241
289
  }
242
290
 
243
291
  /**
244
- * Upload raw files as a Quilt (non-memory data)
292
+ * Upload raw files as a Quilt using writeFilesFlow
293
+ *
294
+ * Uses the writeFilesFlow pattern which works with DappKitSigner:
295
+ * 1. encode() - Encode files (no signature)
296
+ * 2. register() - Register blob on-chain (USER SIGNS)
297
+ * 3. upload() - Upload to storage nodes (no signature)
298
+ * 4. certify() - Certify upload on-chain (USER SIGNS)
245
299
  *
246
300
  * @param files - Array of { identifier, data, tags }
247
301
  * @param options - Upload options
@@ -258,7 +312,7 @@ export class QuiltBatchManager {
258
312
  const startTime = performance.now();
259
313
  let totalSize = 0;
260
314
 
261
- console.log(`📁 Uploading ${files.length} files as Quilt...`);
315
+ console.log(`📁 Uploading ${files.length} files as Quilt (writeFilesFlow)...`);
262
316
 
263
317
  try {
264
318
  const walrusFiles = files.map(file => {
@@ -276,28 +330,86 @@ export class QuiltBatchManager {
276
330
  });
277
331
  });
278
332
 
333
+ // Use writeFilesFlow pattern (works with DappKitSigner)
279
334
  const walrusClient = this.useUploadRelay
280
335
  ? this.walrusWithRelay
281
336
  : this.walrusWithoutRelay;
282
337
 
283
- const results = await walrusClient.writeFiles({
284
- files: walrusFiles,
338
+ // Step 1: Create flow and encode files (no signature needed)
339
+ console.log(` Step 1/4: Encoding files...`);
340
+ const flow = walrusClient.writeFilesFlow({ files: walrusFiles });
341
+ await flow.encode();
342
+ console.log(` ✓ Files encoded`);
343
+
344
+ // Step 2: Register blob on-chain (USER SIGNS - Transaction 1)
345
+ console.log(` Step 2/4: Registering blob (requires signature)...`);
346
+ const registerTx = flow.register({
285
347
  epochs: options.epochs || this.epochs,
286
- deletable: options.deletable ?? true,
287
- signer: options.signer
348
+ owner: options.userAddress,
349
+ deletable: options.deletable ?? true
288
350
  });
289
351
 
352
+ const registerResult = await options.signer.signAndExecuteTransaction(registerTx);
353
+ console.log(` ✓ Blob registered, digest: ${registerResult.digest}`);
354
+
355
+ // Step 3: Upload to Walrus storage nodes (no signature needed)
356
+ console.log(` Step 3/4: Uploading to storage nodes...`);
357
+ await flow.upload({ digest: registerResult.digest });
358
+ console.log(` ✓ Uploaded to storage nodes`);
359
+
360
+ // Step 4: Certify upload on-chain (USER SIGNS - Transaction 2)
361
+ console.log(` Step 4/4: Certifying upload (requires signature)...`);
362
+ const certifyTx = flow.certify();
363
+
364
+ if (certifyTx) {
365
+ const certifyResult = await options.signer.signAndExecuteTransaction(certifyTx);
366
+ console.log(` ✓ Upload certified, digest: ${certifyResult.digest}`);
367
+ } else {
368
+ console.log(` ✓ No certification needed (already certified)`);
369
+ }
370
+
371
+ // Get uploaded files info from flow
372
+ const uploadedFilesInfo = await flow.listFiles();
373
+
290
374
  const uploadTimeMs = performance.now() - startTime;
291
375
 
376
+ console.log(`✅ Files batch upload successful!`);
377
+ console.log(` Files uploaded: ${uploadedFilesInfo.length}`);
378
+ console.log(` Upload time: ${uploadTimeMs.toFixed(1)}ms`);
379
+
380
+ // Build file results using original WalrusFile objects for metadata
381
+ // Use shared quiltId as blobId - SDK can only read via getBlob(quiltId).files()
382
+ // Match files by identifier when reading
383
+ const quiltId = uploadedFilesInfo[0]?.blobId || '';
384
+
385
+ const fileResults: QuiltFileResult[] = await Promise.all(
386
+ walrusFiles.map(async (originalFile, i) => {
387
+ const identifier = await originalFile.getIdentifier() || files[i]?.identifier || `file-${i}`;
388
+ const tags = await originalFile.getTags() || {};
389
+ const fileInfo = uploadedFilesInfo[i];
390
+
391
+ // quiltPatchId is stored for reference but not used for retrieval
392
+ const quiltPatchId = fileInfo?.id || '';
393
+
394
+ console.log(` File ${i}: identifier=${identifier}, quiltId=${quiltId.substring(0, 20)}...`);
395
+
396
+ return {
397
+ identifier,
398
+ // Use shared quiltId as blobId - read via getBlob(quiltId).files()
399
+ blobId: quiltId,
400
+ quiltPatchId,
401
+ tags: Object.fromEntries(
402
+ Object.entries(tags).map(([k, v]) => [k, String(v)])
403
+ ),
404
+ size: files[i]?.data.length || 0
405
+ };
406
+ })
407
+ );
408
+
292
409
  return {
293
- quiltId: results[0]?.id || results[0]?.blobId,
294
- blobObjectId: results[0]?.blobObject?.id?.id,
295
- files: results.map((r, i) => ({
296
- identifier: files[i].identifier,
297
- blobId: r.blobId,
298
- tags: files[i].tags || {},
299
- size: files[i].data.length
300
- })),
410
+ quiltId,
411
+ blobObjectId: undefined, // Not available from flow
412
+ files: fileResults,
301
413
  uploadTimeMs,
302
414
  totalSize,
303
415
  gasSaved: files.length > 1 ? `~${((1 - 1 / files.length) * 100).toFixed(0)}%` : '0%'
@@ -316,14 +428,19 @@ export class QuiltBatchManager {
316
428
  /**
317
429
  * Retrieve all files from a Quilt
318
430
  *
319
- * @param quiltId - The Quilt blob ID
431
+ * Uses getBlob().files() pattern which correctly parses Quilt structure
432
+ * and returns individual files with their identifiers and tags.
433
+ *
434
+ * @param quiltId - The Quilt blob ID (shared blobId)
320
435
  * @returns Array of WalrusFile objects
321
436
  */
322
437
  async getQuiltFiles(quiltId: string): Promise<Array<WalrusFile>> {
323
438
  try {
324
439
  console.log(`📂 Retrieving files from Quilt ${quiltId}...`);
325
440
 
326
- const files = await this.suiClient.walrus.getFiles({ ids: [quiltId] });
441
+ // Use getBlob().files() to correctly parse Quilt and get individual files
442
+ const blob = await this.suiClient.walrus.getBlob({ blobId: quiltId });
443
+ const files = await blob.files();
327
444
 
328
445
  console.log(`✅ Retrieved ${files.length} files from Quilt`);
329
446
 
@@ -338,7 +455,9 @@ export class QuiltBatchManager {
338
455
  /**
339
456
  * Retrieve a specific file by identifier from a Quilt
340
457
  *
341
- * @param quiltId - The Quilt blob ID
458
+ * Uses getBlob().files() to get all files then matches by identifier.
459
+ *
460
+ * @param quiltId - The Quilt blob ID (shared blobId)
342
461
  * @param identifier - The file identifier within the quilt
343
462
  * @returns QuiltRetrieveResult with content and metadata
344
463
  */
@@ -351,21 +470,26 @@ export class QuiltBatchManager {
351
470
  try {
352
471
  console.log(`📄 Retrieving file "${identifier}" from Quilt ${quiltId}...`);
353
472
 
354
- // Get all files from quilt
355
- const files = await this.suiClient.walrus.getFiles({ ids: [quiltId] });
473
+ // Get all files from quilt using getBlob().files()
474
+ const blob = await this.suiClient.walrus.getBlob({ blobId: quiltId });
475
+ const files = await blob.files();
356
476
 
357
477
  // Find file by identifier
358
- const file = files.find(async f => {
478
+ let matchingFile: WalrusFile | undefined;
479
+ for (const f of files) {
359
480
  const fileIdentifier = await f.getIdentifier();
360
- return fileIdentifier === identifier;
361
- });
481
+ if (fileIdentifier === identifier) {
482
+ matchingFile = f;
483
+ break;
484
+ }
485
+ }
362
486
 
363
- if (!file) {
487
+ if (!matchingFile) {
364
488
  throw new Error(`File "${identifier}" not found in Quilt`);
365
489
  }
366
490
 
367
- const content = await file.bytes();
368
- const tags = await file.getTags();
491
+ const content = await matchingFile.bytes();
492
+ const tags = await matchingFile.getTags();
369
493
  const retrievalTimeMs = performance.now() - startTime;
370
494
 
371
495
  console.log(`✅ Retrieved file "${identifier}" (${content.length} bytes)`);
@@ -386,14 +510,18 @@ export class QuiltBatchManager {
386
510
  /**
387
511
  * List all patches in a Quilt with their metadata
388
512
  *
389
- * @param quiltId - The Quilt blob ID
513
+ * Uses getBlob().files() to correctly parse Quilt structure.
514
+ *
515
+ * @param quiltId - The Quilt blob ID (shared blobId)
390
516
  * @returns Array of QuiltListResult with identifiers and tags
391
517
  */
392
518
  async listQuiltPatches(quiltId: string): Promise<QuiltListResult[]> {
393
519
  try {
394
520
  console.log(`📋 Listing patches in Quilt ${quiltId}...`);
395
521
 
396
- const files = await this.suiClient.walrus.getFiles({ ids: [quiltId] });
522
+ // Use getBlob().files() to correctly parse Quilt
523
+ const blob = await this.suiClient.walrus.getBlob({ blobId: quiltId });
524
+ const files = await blob.files();
397
525
 
398
526
  const results: QuiltListResult[] = await Promise.all(
399
527
  files.map(async (file) => {