@cmdoss/memwal-sdk 0.6.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/ARCHITECTURE.md +547 -547
  2. package/BENCHMARKS.md +238 -238
  3. package/README.md +310 -181
  4. package/dist/ai-sdk/tools.d.ts +2 -2
  5. package/dist/ai-sdk/tools.js +2 -2
  6. package/dist/client/ClientMemoryManager.js +2 -2
  7. package/dist/client/ClientMemoryManager.js.map +1 -1
  8. package/dist/client/PersonalDataWallet.d.ts.map +1 -1
  9. package/dist/client/SimplePDWClient.d.ts +29 -1
  10. package/dist/client/SimplePDWClient.d.ts.map +1 -1
  11. package/dist/client/SimplePDWClient.js +45 -13
  12. package/dist/client/SimplePDWClient.js.map +1 -1
  13. package/dist/client/namespaces/EmbeddingsNamespace.d.ts +1 -1
  14. package/dist/client/namespaces/EmbeddingsNamespace.js +1 -1
  15. package/dist/client/namespaces/MemoryNamespace.d.ts +31 -0
  16. package/dist/client/namespaces/MemoryNamespace.d.ts.map +1 -1
  17. package/dist/client/namespaces/MemoryNamespace.js +272 -39
  18. package/dist/client/namespaces/MemoryNamespace.js.map +1 -1
  19. package/dist/client/namespaces/consolidated/AINamespace.d.ts +2 -2
  20. package/dist/client/namespaces/consolidated/AINamespace.js +2 -2
  21. package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts +12 -2
  22. package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts.map +1 -1
  23. package/dist/client/namespaces/consolidated/BlockchainNamespace.js +62 -4
  24. package/dist/client/namespaces/consolidated/BlockchainNamespace.js.map +1 -1
  25. package/dist/client/namespaces/consolidated/StorageNamespace.d.ts +67 -2
  26. package/dist/client/namespaces/consolidated/StorageNamespace.d.ts.map +1 -1
  27. package/dist/client/namespaces/consolidated/StorageNamespace.js +549 -16
  28. package/dist/client/namespaces/consolidated/StorageNamespace.js.map +1 -1
  29. package/dist/config/ConfigurationHelper.js +61 -61
  30. package/dist/config/defaults.js +2 -2
  31. package/dist/config/defaults.js.map +1 -1
  32. package/dist/graph/GraphService.js +21 -21
  33. package/dist/graph/GraphService.js.map +1 -1
  34. package/dist/index.d.ts +3 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +3 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/infrastructure/seal/EncryptionService.d.ts +9 -5
  39. package/dist/infrastructure/seal/EncryptionService.d.ts.map +1 -1
  40. package/dist/infrastructure/seal/EncryptionService.js +37 -15
  41. package/dist/infrastructure/seal/EncryptionService.js.map +1 -1
  42. package/dist/infrastructure/seal/SealService.d.ts +13 -5
  43. package/dist/infrastructure/seal/SealService.d.ts.map +1 -1
  44. package/dist/infrastructure/seal/SealService.js +36 -34
  45. package/dist/infrastructure/seal/SealService.js.map +1 -1
  46. package/dist/langchain/createPDWRAG.js +30 -30
  47. package/dist/retrieval/MemoryDecryptionPipeline.d.ts.map +1 -1
  48. package/dist/retrieval/MemoryDecryptionPipeline.js +2 -1
  49. package/dist/retrieval/MemoryDecryptionPipeline.js.map +1 -1
  50. package/dist/retrieval/MemoryRetrievalService.d.ts +31 -0
  51. package/dist/retrieval/MemoryRetrievalService.d.ts.map +1 -1
  52. package/dist/retrieval/MemoryRetrievalService.js +44 -4
  53. package/dist/retrieval/MemoryRetrievalService.js.map +1 -1
  54. package/dist/services/CapabilityService.d.ts.map +1 -1
  55. package/dist/services/CapabilityService.js +30 -14
  56. package/dist/services/CapabilityService.js.map +1 -1
  57. package/dist/services/CrossContextPermissionService.d.ts.map +1 -1
  58. package/dist/services/CrossContextPermissionService.js +9 -7
  59. package/dist/services/CrossContextPermissionService.js.map +1 -1
  60. package/dist/services/EmbeddingService.d.ts +28 -1
  61. package/dist/services/EmbeddingService.d.ts.map +1 -1
  62. package/dist/services/EmbeddingService.js +54 -0
  63. package/dist/services/EmbeddingService.js.map +1 -1
  64. package/dist/services/EncryptionService.d.ts.map +1 -1
  65. package/dist/services/EncryptionService.js +6 -5
  66. package/dist/services/EncryptionService.js.map +1 -1
  67. package/dist/services/GeminiAIService.js +309 -309
  68. package/dist/services/IndexManager.d.ts +5 -1
  69. package/dist/services/IndexManager.d.ts.map +1 -1
  70. package/dist/services/IndexManager.js +17 -40
  71. package/dist/services/IndexManager.js.map +1 -1
  72. package/dist/services/QueryService.js +1 -1
  73. package/dist/services/QueryService.js.map +1 -1
  74. package/dist/services/StorageService.d.ts +11 -0
  75. package/dist/services/StorageService.d.ts.map +1 -1
  76. package/dist/services/StorageService.js +73 -10
  77. package/dist/services/StorageService.js.map +1 -1
  78. package/dist/services/TransactionService.d.ts +20 -0
  79. package/dist/services/TransactionService.d.ts.map +1 -1
  80. package/dist/services/TransactionService.js +43 -0
  81. package/dist/services/TransactionService.js.map +1 -1
  82. package/dist/services/ViewService.js +2 -2
  83. package/dist/services/ViewService.js.map +1 -1
  84. package/dist/services/storage/QuiltBatchManager.d.ts +101 -1
  85. package/dist/services/storage/QuiltBatchManager.d.ts.map +1 -1
  86. package/dist/services/storage/QuiltBatchManager.js +410 -20
  87. package/dist/services/storage/QuiltBatchManager.js.map +1 -1
  88. package/dist/services/storage/index.d.ts +1 -1
  89. package/dist/services/storage/index.d.ts.map +1 -1
  90. package/dist/services/storage/index.js.map +1 -1
  91. package/dist/utils/LRUCache.d.ts +106 -0
  92. package/dist/utils/LRUCache.d.ts.map +1 -0
  93. package/dist/utils/LRUCache.js +281 -0
  94. package/dist/utils/LRUCache.js.map +1 -0
  95. package/dist/utils/index.d.ts +1 -0
  96. package/dist/utils/index.d.ts.map +1 -1
  97. package/dist/utils/index.js +2 -0
  98. package/dist/utils/index.js.map +1 -1
  99. package/dist/utils/memoryIndexOnChain.d.ts +212 -0
  100. package/dist/utils/memoryIndexOnChain.d.ts.map +1 -0
  101. package/dist/utils/memoryIndexOnChain.js +312 -0
  102. package/dist/utils/memoryIndexOnChain.js.map +1 -0
  103. package/dist/utils/rebuildIndexNode.d.ts +29 -0
  104. package/dist/utils/rebuildIndexNode.d.ts.map +1 -1
  105. package/dist/utils/rebuildIndexNode.js +366 -98
  106. package/dist/utils/rebuildIndexNode.js.map +1 -1
  107. package/dist/vector/HnswWasmService.d.ts +20 -5
  108. package/dist/vector/HnswWasmService.d.ts.map +1 -1
  109. package/dist/vector/HnswWasmService.js +73 -40
  110. package/dist/vector/HnswWasmService.js.map +1 -1
  111. package/dist/vector/IHnswService.d.ts +10 -1
  112. package/dist/vector/IHnswService.d.ts.map +1 -1
  113. package/dist/vector/IHnswService.js.map +1 -1
  114. package/dist/vector/NodeHnswService.d.ts +16 -0
  115. package/dist/vector/NodeHnswService.d.ts.map +1 -1
  116. package/dist/vector/NodeHnswService.js +84 -5
  117. package/dist/vector/NodeHnswService.js.map +1 -1
  118. package/dist/vector/createHnswService.d.ts +1 -1
  119. package/dist/vector/createHnswService.js +1 -1
  120. package/dist/vector/index.d.ts +1 -1
  121. package/dist/vector/index.js +1 -1
  122. package/package.json +157 -157
  123. package/src/access/PermissionService.ts +635 -635
  124. package/src/aggregation/AggregationService.ts +389 -389
  125. package/src/ai-sdk/PDWVectorStore.ts +715 -715
  126. package/src/ai-sdk/index.ts +65 -65
  127. package/src/ai-sdk/tools.ts +460 -460
  128. package/src/ai-sdk/types.ts +404 -404
  129. package/src/batch/BatchManager.ts +597 -597
  130. package/src/batch/BatchingService.ts +429 -429
  131. package/src/batch/MemoryProcessingCache.ts +492 -492
  132. package/src/batch/index.ts +30 -30
  133. package/src/browser.ts +200 -200
  134. package/src/client/ClientMemoryManager.ts +987 -987
  135. package/src/client/PersonalDataWallet.ts +345 -345
  136. package/src/client/SimplePDWClient.ts +1289 -1222
  137. package/src/client/factory.ts +154 -154
  138. package/src/client/namespaces/AnalyticsNamespace.ts +377 -377
  139. package/src/client/namespaces/BatchNamespace.ts +356 -356
  140. package/src/client/namespaces/CacheNamespace.ts +123 -123
  141. package/src/client/namespaces/CapabilityNamespace.ts +217 -217
  142. package/src/client/namespaces/ClassifyNamespace.ts +169 -169
  143. package/src/client/namespaces/ContextNamespace.ts +297 -297
  144. package/src/client/namespaces/EmbeddingsNamespace.ts +99 -99
  145. package/src/client/namespaces/EncryptionNamespace.ts +221 -221
  146. package/src/client/namespaces/GraphNamespace.ts +468 -468
  147. package/src/client/namespaces/IndexNamespace.ts +361 -361
  148. package/src/client/namespaces/MemoryNamespace.ts +1422 -1135
  149. package/src/client/namespaces/PermissionsNamespace.ts +254 -254
  150. package/src/client/namespaces/PipelineNamespace.ts +220 -220
  151. package/src/client/namespaces/SearchNamespace.ts +1049 -1049
  152. package/src/client/namespaces/StorageNamespace.ts +458 -458
  153. package/src/client/namespaces/TxNamespace.ts +260 -260
  154. package/src/client/namespaces/WalletNamespace.ts +243 -243
  155. package/src/client/namespaces/consolidated/AINamespace.ts +449 -449
  156. package/src/client/namespaces/consolidated/BlockchainNamespace.ts +607 -546
  157. package/src/client/namespaces/consolidated/SecurityNamespace.ts +648 -648
  158. package/src/client/namespaces/consolidated/StorageNamespace.ts +1141 -497
  159. package/src/client/namespaces/consolidated/index.ts +39 -39
  160. package/src/client/signers/KeypairSigner.ts +108 -108
  161. package/src/client/signers/UnifiedSigner.ts +110 -110
  162. package/src/client/signers/WalletAdapterSigner.ts +159 -159
  163. package/src/client/signers/index.ts +26 -26
  164. package/src/config/ConfigurationHelper.ts +412 -412
  165. package/src/config/defaults.ts +51 -51
  166. package/src/config/index.ts +8 -8
  167. package/src/config/validation.ts +70 -70
  168. package/src/core/index.ts +14 -14
  169. package/src/core/interfaces/IService.ts +307 -307
  170. package/src/core/interfaces/index.ts +8 -8
  171. package/src/core/types/capability.ts +297 -297
  172. package/src/core/types/index.ts +870 -870
  173. package/src/core/types/wallet.ts +270 -270
  174. package/src/core/types.ts +9 -9
  175. package/src/core/wallet.ts +222 -222
  176. package/src/embedding/index.ts +19 -19
  177. package/src/embedding/types.ts +357 -357
  178. package/src/errors/index.ts +602 -602
  179. package/src/errors/recovery.ts +461 -461
  180. package/src/errors/validation.ts +567 -567
  181. package/src/generated/pdw/capability.ts +319 -319
  182. package/src/graph/GraphService.ts +887 -887
  183. package/src/graph/KnowledgeGraphManager.ts +728 -728
  184. package/src/graph/index.ts +25 -25
  185. package/src/index.ts +498 -474
  186. package/src/infrastructure/index.ts +22 -22
  187. package/src/infrastructure/seal/EncryptionService.ts +628 -603
  188. package/src/infrastructure/seal/SealService.ts +613 -615
  189. package/src/infrastructure/seal/index.ts +9 -9
  190. package/src/infrastructure/sui/BlockchainManager.ts +627 -627
  191. package/src/infrastructure/sui/SuiService.ts +888 -888
  192. package/src/infrastructure/sui/index.ts +9 -9
  193. package/src/infrastructure/walrus/StorageManager.ts +604 -604
  194. package/src/infrastructure/walrus/WalrusStorageService.ts +612 -612
  195. package/src/infrastructure/walrus/index.ts +9 -9
  196. package/src/langchain/PDWEmbeddings.ts +145 -145
  197. package/src/langchain/PDWVectorStore.ts +456 -456
  198. package/src/langchain/createPDWRAG.ts +303 -303
  199. package/src/langchain/index.ts +47 -47
  200. package/src/permissions/ConsentRepository.browser.ts +249 -249
  201. package/src/permissions/ConsentRepository.ts +364 -364
  202. package/src/pipeline/MemoryPipeline.ts +862 -862
  203. package/src/pipeline/PipelineManager.ts +683 -683
  204. package/src/pipeline/index.ts +26 -26
  205. package/src/retrieval/AdvancedSearchService.ts +629 -629
  206. package/src/retrieval/MemoryAnalyticsService.ts +711 -711
  207. package/src/retrieval/MemoryDecryptionPipeline.ts +825 -824
  208. package/src/retrieval/MemoryRetrievalService.ts +904 -830
  209. package/src/retrieval/index.ts +42 -42
  210. package/src/services/BatchService.ts +352 -352
  211. package/src/services/CapabilityService.ts +464 -448
  212. package/src/services/ClassifierService.ts +465 -465
  213. package/src/services/CrossContextPermissionService.ts +486 -484
  214. package/src/services/EmbeddingService.ts +771 -706
  215. package/src/services/EncryptionService.ts +712 -711
  216. package/src/services/GeminiAIService.ts +753 -753
  217. package/src/services/IndexManager.ts +977 -1004
  218. package/src/services/MemoryIndexService.ts +1003 -1003
  219. package/src/services/MemoryService.ts +369 -369
  220. package/src/services/QueryService.ts +890 -890
  221. package/src/services/StorageService.ts +1182 -1111
  222. package/src/services/TransactionService.ts +838 -790
  223. package/src/services/VectorService.ts +462 -462
  224. package/src/services/ViewService.ts +484 -484
  225. package/src/services/index.ts +25 -25
  226. package/src/services/storage/BlobAttributesManager.ts +333 -333
  227. package/src/services/storage/KnowledgeGraphManager.ts +425 -425
  228. package/src/services/storage/MemorySearchManager.ts +387 -387
  229. package/src/services/storage/QuiltBatchManager.ts +1130 -660
  230. package/src/services/storage/WalrusMetadataManager.ts +268 -268
  231. package/src/services/storage/WalrusStorageManager.ts +287 -287
  232. package/src/services/storage/index.ts +57 -52
  233. package/src/types/index.ts +13 -13
  234. package/src/utils/LRUCache.ts +378 -0
  235. package/src/utils/index.ts +76 -68
  236. package/src/utils/memoryIndexOnChain.ts +507 -0
  237. package/src/utils/rebuildIndex.ts +290 -290
  238. package/src/utils/rebuildIndexNode.ts +771 -424
  239. package/src/vector/BrowserHnswIndexService.ts +758 -758
  240. package/src/vector/HnswWasmService.ts +731 -679
  241. package/src/vector/IHnswService.ts +233 -224
  242. package/src/vector/NodeHnswService.ts +833 -735
  243. package/src/vector/VectorManager.ts +478 -478
  244. package/src/vector/createHnswService.ts +135 -135
  245. package/src/vector/index.ts +56 -56
  246. package/src/wallet/ContextWalletService.ts +656 -656
  247. package/src/wallet/MainWalletService.ts +317 -317
@@ -1,390 +1,390 @@
1
- /**
2
- * AggregationService - Cross-app data query with permission filtering
3
- *
4
- * Enables querying data across multiple app contexts while respecting
5
- * OAuth-style permissions and access control policies.
6
- */
7
-
8
- import { SuiClient } from '@mysten/sui/client';
9
- import { normalizeSuiAddress } from '@mysten/sui/utils';
10
-
11
- import {
12
- AggregatedQueryOptions,
13
- PermissionScope
14
- } from '../core/types/wallet.js';
15
- import { PermissionService } from '../access/PermissionService.js';
16
- import { CapabilityService } from '../services/CapabilityService.js';
17
- import { ContextWalletService } from '../wallet/ContextWalletService.js';
18
-
19
- /**
20
- * Configuration for AggregationService
21
- */
22
- export interface AggregationServiceConfig {
23
- /** Sui client instance */
24
- suiClient: SuiClient;
25
- /** Package ID for Move contracts */
26
- packageId: string;
27
- /** Permission service for access validation */
28
- permissionService: PermissionService;
29
- /** Capability service for capability-based access (preferred) */
30
- capabilityService?: CapabilityService;
31
- /**
32
- * @deprecated Use capabilityService and a ContextNamespace implementation instead
33
- * Context wallet service for data access (legacy)
34
- */
35
- contextWalletService: ContextWalletService;
36
- }
37
-
38
- /**
39
- * Result of an aggregated query
40
- */
41
- export interface AggregatedQueryResult {
42
- /** Query results organized by app context */
43
- results: Array<{
44
- contextId: string;
45
- targetWallet: string;
46
- appId: string;
47
- data: Array<{
48
- id: string;
49
- content: string;
50
- category?: string;
51
- metadata?: Record<string, any>;
52
- createdAt: number;
53
- }>;
54
- hasMore: boolean;
55
- }>;
56
- /** Total number of results across all contexts */
57
- totalResults: number;
58
- /** Contexts that were queried */
59
- queriedContexts: string[];
60
- /** Contexts that were skipped due to permissions */
61
- skippedContexts: string[];
62
- /** Query performance metrics */
63
- metrics: {
64
- queryTime: number;
65
- contextsChecked: number;
66
- permissionChecks: number;
67
- };
68
- }
69
-
70
- /**
71
- * AggregationService handles cross-app queries with permission filtering
72
- */
73
- export class AggregationService {
74
- private suiClient: SuiClient;
75
- private packageId: string;
76
- private permissionService: PermissionService;
77
- private capabilityService?: CapabilityService;
78
- /** @deprecated Use capabilityService instead */
79
- private contextWalletService: ContextWalletService;
80
-
81
- constructor(config: AggregationServiceConfig) {
82
- this.suiClient = config.suiClient;
83
- this.packageId = config.packageId;
84
- this.permissionService = config.permissionService;
85
- this.capabilityService = config.capabilityService;
86
- this.contextWalletService = config.contextWalletService;
87
- }
88
-
89
- /**
90
- * Query data across multiple app contexts with permission enforcement
91
- * @param options - Query options
92
- * @returns Aggregated query results
93
- */
94
- async query(options: AggregatedQueryOptions): Promise<AggregatedQueryResult> {
95
- const startTime = Date.now();
96
- const result: AggregatedQueryResult = {
97
- results: [],
98
- totalResults: 0,
99
- queriedContexts: [],
100
- skippedContexts: [],
101
- metrics: {
102
- queryTime: 0,
103
- contextsChecked: 0,
104
- permissionChecks: 0
105
- }
106
- };
107
-
108
- const normalizedRequester = normalizeSuiAddress(options.requestingWallet);
109
- const normalizedTargets = options.targetWallets?.map(id => id.toLowerCase());
110
-
111
- const userContexts = await this.contextWalletService.listUserContexts(options.userAddress);
112
- const candidateContexts = normalizedTargets?.length
113
- ? userContexts.filter(ctx => {
114
- const contextIdLower = ctx.contextId.toLowerCase();
115
- const walletIdLower = ctx.id.toLowerCase();
116
- return normalizedTargets.includes(contextIdLower) || normalizedTargets.includes(walletIdLower);
117
- })
118
- : userContexts;
119
-
120
- result.metrics.contextsChecked = candidateContexts.length;
121
-
122
- // Check permissions and query allowed contexts
123
- for (const context of candidateContexts) {
124
- try {
125
- // Check if the requesting entity has permission to access this context
126
- const hasPermission = await this.permissionService.hasWalletPermission(
127
- normalizedRequester,
128
- context.id,
129
- options.scope
130
- );
131
-
132
- result.metrics.permissionChecks++;
133
-
134
- if (!hasPermission) {
135
- result.skippedContexts.push(context.id);
136
- continue;
137
- }
138
-
139
- // Query data from this context
140
- const perContextLimit = options.limit
141
- ? Math.ceil(options.limit / Math.max(candidateContexts.length, 1))
142
- : undefined;
143
-
144
- const contextData = await this.contextWalletService.listData(context.id, {
145
- limit: perContextLimit
146
- });
147
-
148
- // Filter results based on query
149
- const filteredData = this.filterDataByQuery(contextData, options.query);
150
-
151
- if (filteredData.length > 0) {
152
- result.results.push({
153
- contextId: context.contextId,
154
- targetWallet: context.id,
155
- appId: context.appId,
156
- data: filteredData,
157
- hasMore: false // TODO: Implement pagination
158
- });
159
-
160
- result.totalResults += filteredData.length;
161
- result.queriedContexts.push(context.id);
162
- }
163
- } catch (error) {
164
- console.error(`Error querying context ${context.id}:`, error);
165
- result.skippedContexts.push(context.id);
166
- }
167
- }
168
-
169
- // Apply global limit if specified
170
- if (options.limit && result.totalResults > options.limit) {
171
- result.results = this.applyGlobalLimit(result.results, options.limit);
172
- result.totalResults = options.limit;
173
- }
174
-
175
- result.metrics.queryTime = Date.now() - startTime;
176
- return result;
177
- }
178
-
179
- /**
180
- * Query with scope-based filtering
181
- * @param userAddress - User address
182
- * @param query - Search query
183
- * @param scopes - Required permission scopes
184
- * @returns Filtered aggregated results
185
- */
186
- async queryWithScopes(
187
- requestingWallet: string,
188
- userAddress: string,
189
- query: string,
190
- scopes: PermissionScope[]
191
- ): Promise<AggregatedQueryResult> {
192
- // Get all user contexts
193
- const userContexts = await this.contextWalletService.listUserContexts(userAddress);
194
-
195
- // Filter contexts by permission scopes
196
- const allowedWallets: string[] = [];
197
-
198
- for (const context of userContexts) {
199
- let hasAllScopes = true;
200
-
201
- for (const scope of scopes) {
202
- const hasScope = await this.permissionService.hasWalletPermission(
203
- requestingWallet,
204
- context.id,
205
- scope
206
- );
207
-
208
- if (!hasScope) {
209
- hasAllScopes = false;
210
- break;
211
- }
212
- }
213
-
214
- if (hasAllScopes) {
215
- allowedWallets.push(context.id);
216
- }
217
- }
218
-
219
- return await this.query({
220
- requestingWallet,
221
- userAddress,
222
- query,
223
- scope: scopes[0],
224
- targetWallets: allowedWallets
225
- });
226
- }
227
-
228
- /**
229
- * Get aggregated statistics across contexts
230
- * @param userAddress - User address
231
- * @param appIds - Apps to include in statistics
232
- * @returns Aggregated statistics
233
- */
234
- async getAggregatedStats(userAddress: string, targetWallets: string[]): Promise<{
235
- totalContexts: number;
236
- totalItems: number;
237
- totalSize: number;
238
- categoryCounts: Record<string, number>;
239
- contextBreakdown: Record<string, {
240
- items: number;
241
- size: number;
242
- lastActivity: number;
243
- }>;
244
- appBreakdown?: Record<string, {
245
- items: number;
246
- size: number;
247
- lastActivity: number;
248
- }>;
249
- }> {
250
- const stats = {
251
- totalContexts: 0,
252
- totalItems: 0,
253
- totalSize: 0,
254
- categoryCounts: {} as Record<string, number>,
255
- contextBreakdown: {} as Record<string, {
256
- items: number;
257
- size: number;
258
- lastActivity: number;
259
- }>,
260
- appBreakdown: {} as Record<string, {
261
- items: number;
262
- size: number;
263
- lastActivity: number;
264
- }>
265
- };
266
-
267
- for (const walletId of targetWallets) {
268
- try {
269
- const contextStats = await this.contextWalletService.getContextStats(walletId);
270
-
271
- stats.totalContexts++;
272
- stats.totalItems += contextStats.itemCount;
273
- stats.totalSize += contextStats.totalSize;
274
-
275
- // Merge category counts
276
- for (const [category, count] of Object.entries(contextStats.categories)) {
277
- stats.categoryCounts[category] = (stats.categoryCounts[category] || 0) + count;
278
- }
279
-
280
- // Context breakdown
281
- stats.contextBreakdown[walletId] = {
282
- items: contextStats.itemCount,
283
- size: contextStats.totalSize,
284
- lastActivity: contextStats.lastActivity
285
- };
286
-
287
- // Legacy alias
288
- stats.appBreakdown[walletId] = {
289
- items: contextStats.itemCount,
290
- size: contextStats.totalSize,
291
- lastActivity: contextStats.lastActivity
292
- };
293
- } catch (error) {
294
- console.error(`Error getting stats for wallet ${walletId}:`, error);
295
- }
296
- }
297
-
298
- return stats;
299
- }
300
-
301
- /**
302
- * Search across contexts with permission validation
303
- * @param userAddress - User address
304
- * @param searchQuery - Search query
305
- * @param options - Search options
306
- * @returns Search results
307
- */
308
- async search(
309
- requestingWallet: string,
310
- userAddress: string,
311
- searchQuery: string,
312
- options?: {
313
- targetWallets?: string[];
314
- categories?: string[];
315
- limit?: number;
316
- minPermissionScope?: PermissionScope;
317
- }): Promise<AggregatedQueryResult> {
318
- const targetWallets = options?.targetWallets ? [...options.targetWallets] : [];
319
-
320
- // If no contexts specified, get all user contexts
321
- if (targetWallets.length === 0) {
322
- const userContexts = await this.contextWalletService.listUserContexts(userAddress);
323
- targetWallets.push(...userContexts.map(c => c.id));
324
- }
325
-
326
- return await this.query({
327
- requestingWallet,
328
- userAddress,
329
- query: searchQuery,
330
- scope: options?.minPermissionScope || 'read:memories' as PermissionScope,
331
- limit: options?.limit,
332
- targetWallets
333
- });
334
- }
335
-
336
- /**
337
- * Filter data by search query
338
- * @private
339
- */
340
- private filterDataByQuery(
341
- data: Array<{
342
- id: string;
343
- content: string;
344
- category?: string;
345
- metadata?: Record<string, any>;
346
- createdAt: number;
347
- }>,
348
- query: string
349
- ): typeof data {
350
- if (!query) return data;
351
-
352
- const lowerQuery = query.toLowerCase();
353
-
354
- return data.filter(item =>
355
- item.content.toLowerCase().includes(lowerQuery) ||
356
- item.category?.toLowerCase().includes(lowerQuery) ||
357
- Object.values(item.metadata || {}).some(value =>
358
- String(value).toLowerCase().includes(lowerQuery)
359
- )
360
- );
361
- }
362
-
363
- /**
364
- * Apply global result limit across contexts
365
- * @private
366
- */
367
- private applyGlobalLimit<T extends { data: any[] }>(
368
- results: T[],
369
- limit: number
370
- ): T[] {
371
- let totalCount = 0;
372
- const limitedResults: T[] = [];
373
-
374
- for (const result of results) {
375
- if (totalCount >= limit) break;
376
-
377
- const remainingLimit = limit - totalCount;
378
- const limitedData = result.data.slice(0, remainingLimit);
379
-
380
- limitedResults.push({
381
- ...result,
382
- data: limitedData
383
- });
384
-
385
- totalCount += limitedData.length;
386
- }
387
-
388
- return limitedResults;
389
- }
1
+ /**
2
+ * AggregationService - Cross-app data query with permission filtering
3
+ *
4
+ * Enables querying data across multiple app contexts while respecting
5
+ * OAuth-style permissions and access control policies.
6
+ */
7
+
8
+ import { SuiClient } from '@mysten/sui/client';
9
+ import { normalizeSuiAddress } from '@mysten/sui/utils';
10
+
11
+ import {
12
+ AggregatedQueryOptions,
13
+ PermissionScope
14
+ } from '../core/types/wallet.js';
15
+ import { PermissionService } from '../access/PermissionService.js';
16
+ import { CapabilityService } from '../services/CapabilityService.js';
17
+ import { ContextWalletService } from '../wallet/ContextWalletService.js';
18
+
19
+ /**
20
+ * Configuration for AggregationService
21
+ */
22
+ export interface AggregationServiceConfig {
23
+ /** Sui client instance */
24
+ suiClient: SuiClient;
25
+ /** Package ID for Move contracts */
26
+ packageId: string;
27
+ /** Permission service for access validation */
28
+ permissionService: PermissionService;
29
+ /** Capability service for capability-based access (preferred) */
30
+ capabilityService?: CapabilityService;
31
+ /**
32
+ * @deprecated Use capabilityService and a ContextNamespace implementation instead
33
+ * Context wallet service for data access (legacy)
34
+ */
35
+ contextWalletService: ContextWalletService;
36
+ }
37
+
38
+ /**
39
+ * Result of an aggregated query
40
+ */
41
+ export interface AggregatedQueryResult {
42
+ /** Query results organized by app context */
43
+ results: Array<{
44
+ contextId: string;
45
+ targetWallet: string;
46
+ appId: string;
47
+ data: Array<{
48
+ id: string;
49
+ content: string;
50
+ category?: string;
51
+ metadata?: Record<string, any>;
52
+ createdAt: number;
53
+ }>;
54
+ hasMore: boolean;
55
+ }>;
56
+ /** Total number of results across all contexts */
57
+ totalResults: number;
58
+ /** Contexts that were queried */
59
+ queriedContexts: string[];
60
+ /** Contexts that were skipped due to permissions */
61
+ skippedContexts: string[];
62
+ /** Query performance metrics */
63
+ metrics: {
64
+ queryTime: number;
65
+ contextsChecked: number;
66
+ permissionChecks: number;
67
+ };
68
+ }
69
+
70
+ /**
71
+ * AggregationService handles cross-app queries with permission filtering
72
+ */
73
+ export class AggregationService {
74
+ private suiClient: SuiClient;
75
+ private packageId: string;
76
+ private permissionService: PermissionService;
77
+ private capabilityService?: CapabilityService;
78
+ /** @deprecated Use capabilityService instead */
79
+ private contextWalletService: ContextWalletService;
80
+
81
+ constructor(config: AggregationServiceConfig) {
82
+ this.suiClient = config.suiClient;
83
+ this.packageId = config.packageId;
84
+ this.permissionService = config.permissionService;
85
+ this.capabilityService = config.capabilityService;
86
+ this.contextWalletService = config.contextWalletService;
87
+ }
88
+
89
+ /**
90
+ * Query data across multiple app contexts with permission enforcement
91
+ * @param options - Query options
92
+ * @returns Aggregated query results
93
+ */
94
+ async query(options: AggregatedQueryOptions): Promise<AggregatedQueryResult> {
95
+ const startTime = Date.now();
96
+ const result: AggregatedQueryResult = {
97
+ results: [],
98
+ totalResults: 0,
99
+ queriedContexts: [],
100
+ skippedContexts: [],
101
+ metrics: {
102
+ queryTime: 0,
103
+ contextsChecked: 0,
104
+ permissionChecks: 0
105
+ }
106
+ };
107
+
108
+ const normalizedRequester = normalizeSuiAddress(options.requestingWallet);
109
+ const normalizedTargets = options.targetWallets?.map(id => id.toLowerCase());
110
+
111
+ const userContexts = await this.contextWalletService.listUserContexts(options.userAddress);
112
+ const candidateContexts = normalizedTargets?.length
113
+ ? userContexts.filter(ctx => {
114
+ const contextIdLower = ctx.contextId.toLowerCase();
115
+ const walletIdLower = ctx.id.toLowerCase();
116
+ return normalizedTargets.includes(contextIdLower) || normalizedTargets.includes(walletIdLower);
117
+ })
118
+ : userContexts;
119
+
120
+ result.metrics.contextsChecked = candidateContexts.length;
121
+
122
+ // Check permissions and query allowed contexts
123
+ for (const context of candidateContexts) {
124
+ try {
125
+ // Check if the requesting entity has permission to access this context
126
+ const hasPermission = await this.permissionService.hasWalletPermission(
127
+ normalizedRequester,
128
+ context.id,
129
+ options.scope
130
+ );
131
+
132
+ result.metrics.permissionChecks++;
133
+
134
+ if (!hasPermission) {
135
+ result.skippedContexts.push(context.id);
136
+ continue;
137
+ }
138
+
139
+ // Query data from this context
140
+ const perContextLimit = options.limit
141
+ ? Math.ceil(options.limit / Math.max(candidateContexts.length, 1))
142
+ : undefined;
143
+
144
+ const contextData = await this.contextWalletService.listData(context.id, {
145
+ limit: perContextLimit
146
+ });
147
+
148
+ // Filter results based on query
149
+ const filteredData = this.filterDataByQuery(contextData, options.query);
150
+
151
+ if (filteredData.length > 0) {
152
+ result.results.push({
153
+ contextId: context.contextId,
154
+ targetWallet: context.id,
155
+ appId: context.appId,
156
+ data: filteredData,
157
+ hasMore: false // TODO: Implement pagination
158
+ });
159
+
160
+ result.totalResults += filteredData.length;
161
+ result.queriedContexts.push(context.id);
162
+ }
163
+ } catch (error) {
164
+ console.error(`Error querying context ${context.id}:`, error);
165
+ result.skippedContexts.push(context.id);
166
+ }
167
+ }
168
+
169
+ // Apply global limit if specified
170
+ if (options.limit && result.totalResults > options.limit) {
171
+ result.results = this.applyGlobalLimit(result.results, options.limit);
172
+ result.totalResults = options.limit;
173
+ }
174
+
175
+ result.metrics.queryTime = Date.now() - startTime;
176
+ return result;
177
+ }
178
+
179
+ /**
180
+ * Query with scope-based filtering
181
+ * @param userAddress - User address
182
+ * @param query - Search query
183
+ * @param scopes - Required permission scopes
184
+ * @returns Filtered aggregated results
185
+ */
186
+ async queryWithScopes(
187
+ requestingWallet: string,
188
+ userAddress: string,
189
+ query: string,
190
+ scopes: PermissionScope[]
191
+ ): Promise<AggregatedQueryResult> {
192
+ // Get all user contexts
193
+ const userContexts = await this.contextWalletService.listUserContexts(userAddress);
194
+
195
+ // Filter contexts by permission scopes
196
+ const allowedWallets: string[] = [];
197
+
198
+ for (const context of userContexts) {
199
+ let hasAllScopes = true;
200
+
201
+ for (const scope of scopes) {
202
+ const hasScope = await this.permissionService.hasWalletPermission(
203
+ requestingWallet,
204
+ context.id,
205
+ scope
206
+ );
207
+
208
+ if (!hasScope) {
209
+ hasAllScopes = false;
210
+ break;
211
+ }
212
+ }
213
+
214
+ if (hasAllScopes) {
215
+ allowedWallets.push(context.id);
216
+ }
217
+ }
218
+
219
+ return await this.query({
220
+ requestingWallet,
221
+ userAddress,
222
+ query,
223
+ scope: scopes[0],
224
+ targetWallets: allowedWallets
225
+ });
226
+ }
227
+
228
+ /**
229
+ * Get aggregated statistics across contexts
230
+ * @param userAddress - User address
231
+ * @param appIds - Apps to include in statistics
232
+ * @returns Aggregated statistics
233
+ */
234
+ async getAggregatedStats(userAddress: string, targetWallets: string[]): Promise<{
235
+ totalContexts: number;
236
+ totalItems: number;
237
+ totalSize: number;
238
+ categoryCounts: Record<string, number>;
239
+ contextBreakdown: Record<string, {
240
+ items: number;
241
+ size: number;
242
+ lastActivity: number;
243
+ }>;
244
+ appBreakdown?: Record<string, {
245
+ items: number;
246
+ size: number;
247
+ lastActivity: number;
248
+ }>;
249
+ }> {
250
+ const stats = {
251
+ totalContexts: 0,
252
+ totalItems: 0,
253
+ totalSize: 0,
254
+ categoryCounts: {} as Record<string, number>,
255
+ contextBreakdown: {} as Record<string, {
256
+ items: number;
257
+ size: number;
258
+ lastActivity: number;
259
+ }>,
260
+ appBreakdown: {} as Record<string, {
261
+ items: number;
262
+ size: number;
263
+ lastActivity: number;
264
+ }>
265
+ };
266
+
267
+ for (const walletId of targetWallets) {
268
+ try {
269
+ const contextStats = await this.contextWalletService.getContextStats(walletId);
270
+
271
+ stats.totalContexts++;
272
+ stats.totalItems += contextStats.itemCount;
273
+ stats.totalSize += contextStats.totalSize;
274
+
275
+ // Merge category counts
276
+ for (const [category, count] of Object.entries(contextStats.categories)) {
277
+ stats.categoryCounts[category] = (stats.categoryCounts[category] || 0) + count;
278
+ }
279
+
280
+ // Context breakdown
281
+ stats.contextBreakdown[walletId] = {
282
+ items: contextStats.itemCount,
283
+ size: contextStats.totalSize,
284
+ lastActivity: contextStats.lastActivity
285
+ };
286
+
287
+ // Legacy alias
288
+ stats.appBreakdown[walletId] = {
289
+ items: contextStats.itemCount,
290
+ size: contextStats.totalSize,
291
+ lastActivity: contextStats.lastActivity
292
+ };
293
+ } catch (error) {
294
+ console.error(`Error getting stats for wallet ${walletId}:`, error);
295
+ }
296
+ }
297
+
298
+ return stats;
299
+ }
300
+
301
+ /**
302
+ * Search across contexts with permission validation
303
+ * @param userAddress - User address
304
+ * @param searchQuery - Search query
305
+ * @param options - Search options
306
+ * @returns Search results
307
+ */
308
+ async search(
309
+ requestingWallet: string,
310
+ userAddress: string,
311
+ searchQuery: string,
312
+ options?: {
313
+ targetWallets?: string[];
314
+ categories?: string[];
315
+ limit?: number;
316
+ minPermissionScope?: PermissionScope;
317
+ }): Promise<AggregatedQueryResult> {
318
+ const targetWallets = options?.targetWallets ? [...options.targetWallets] : [];
319
+
320
+ // If no contexts specified, get all user contexts
321
+ if (targetWallets.length === 0) {
322
+ const userContexts = await this.contextWalletService.listUserContexts(userAddress);
323
+ targetWallets.push(...userContexts.map(c => c.id));
324
+ }
325
+
326
+ return await this.query({
327
+ requestingWallet,
328
+ userAddress,
329
+ query: searchQuery,
330
+ scope: options?.minPermissionScope || 'read:memories' as PermissionScope,
331
+ limit: options?.limit,
332
+ targetWallets
333
+ });
334
+ }
335
+
336
+ /**
337
+ * Filter data by search query
338
+ * @private
339
+ */
340
+ private filterDataByQuery(
341
+ data: Array<{
342
+ id: string;
343
+ content: string;
344
+ category?: string;
345
+ metadata?: Record<string, any>;
346
+ createdAt: number;
347
+ }>,
348
+ query: string
349
+ ): typeof data {
350
+ if (!query) return data;
351
+
352
+ const lowerQuery = query.toLowerCase();
353
+
354
+ return data.filter(item =>
355
+ item.content.toLowerCase().includes(lowerQuery) ||
356
+ item.category?.toLowerCase().includes(lowerQuery) ||
357
+ Object.values(item.metadata || {}).some(value =>
358
+ String(value).toLowerCase().includes(lowerQuery)
359
+ )
360
+ );
361
+ }
362
+
363
+ /**
364
+ * Apply global result limit across contexts
365
+ * @private
366
+ */
367
+ private applyGlobalLimit<T extends { data: any[] }>(
368
+ results: T[],
369
+ limit: number
370
+ ): T[] {
371
+ let totalCount = 0;
372
+ const limitedResults: T[] = [];
373
+
374
+ for (const result of results) {
375
+ if (totalCount >= limit) break;
376
+
377
+ const remainingLimit = limit - totalCount;
378
+ const limitedData = result.data.slice(0, remainingLimit);
379
+
380
+ limitedResults.push({
381
+ ...result,
382
+ data: limitedData
383
+ });
384
+
385
+ totalCount += limitedData.length;
386
+ }
387
+
388
+ return limitedResults;
389
+ }
390
390
  }