@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.
- package/ARCHITECTURE.md +547 -547
- package/BENCHMARKS.md +238 -238
- package/README.md +310 -181
- package/dist/ai-sdk/tools.d.ts +2 -2
- package/dist/ai-sdk/tools.js +2 -2
- package/dist/client/ClientMemoryManager.js +2 -2
- package/dist/client/ClientMemoryManager.js.map +1 -1
- package/dist/client/PersonalDataWallet.d.ts.map +1 -1
- package/dist/client/SimplePDWClient.d.ts +29 -1
- package/dist/client/SimplePDWClient.d.ts.map +1 -1
- package/dist/client/SimplePDWClient.js +45 -13
- package/dist/client/SimplePDWClient.js.map +1 -1
- package/dist/client/namespaces/EmbeddingsNamespace.d.ts +1 -1
- package/dist/client/namespaces/EmbeddingsNamespace.js +1 -1
- package/dist/client/namespaces/MemoryNamespace.d.ts +31 -0
- package/dist/client/namespaces/MemoryNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/MemoryNamespace.js +272 -39
- package/dist/client/namespaces/MemoryNamespace.js.map +1 -1
- package/dist/client/namespaces/consolidated/AINamespace.d.ts +2 -2
- package/dist/client/namespaces/consolidated/AINamespace.js +2 -2
- package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts +12 -2
- package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/consolidated/BlockchainNamespace.js +62 -4
- package/dist/client/namespaces/consolidated/BlockchainNamespace.js.map +1 -1
- package/dist/client/namespaces/consolidated/StorageNamespace.d.ts +67 -2
- package/dist/client/namespaces/consolidated/StorageNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/consolidated/StorageNamespace.js +549 -16
- package/dist/client/namespaces/consolidated/StorageNamespace.js.map +1 -1
- package/dist/config/ConfigurationHelper.js +61 -61
- package/dist/config/defaults.js +2 -2
- package/dist/config/defaults.js.map +1 -1
- package/dist/graph/GraphService.js +21 -21
- package/dist/graph/GraphService.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/seal/EncryptionService.d.ts +9 -5
- package/dist/infrastructure/seal/EncryptionService.d.ts.map +1 -1
- package/dist/infrastructure/seal/EncryptionService.js +37 -15
- package/dist/infrastructure/seal/EncryptionService.js.map +1 -1
- package/dist/infrastructure/seal/SealService.d.ts +13 -5
- package/dist/infrastructure/seal/SealService.d.ts.map +1 -1
- package/dist/infrastructure/seal/SealService.js +36 -34
- package/dist/infrastructure/seal/SealService.js.map +1 -1
- package/dist/langchain/createPDWRAG.js +30 -30
- package/dist/retrieval/MemoryDecryptionPipeline.d.ts.map +1 -1
- package/dist/retrieval/MemoryDecryptionPipeline.js +2 -1
- package/dist/retrieval/MemoryDecryptionPipeline.js.map +1 -1
- package/dist/retrieval/MemoryRetrievalService.d.ts +31 -0
- package/dist/retrieval/MemoryRetrievalService.d.ts.map +1 -1
- package/dist/retrieval/MemoryRetrievalService.js +44 -4
- package/dist/retrieval/MemoryRetrievalService.js.map +1 -1
- package/dist/services/CapabilityService.d.ts.map +1 -1
- package/dist/services/CapabilityService.js +30 -14
- package/dist/services/CapabilityService.js.map +1 -1
- package/dist/services/CrossContextPermissionService.d.ts.map +1 -1
- package/dist/services/CrossContextPermissionService.js +9 -7
- package/dist/services/CrossContextPermissionService.js.map +1 -1
- package/dist/services/EmbeddingService.d.ts +28 -1
- package/dist/services/EmbeddingService.d.ts.map +1 -1
- package/dist/services/EmbeddingService.js +54 -0
- package/dist/services/EmbeddingService.js.map +1 -1
- package/dist/services/EncryptionService.d.ts.map +1 -1
- package/dist/services/EncryptionService.js +6 -5
- package/dist/services/EncryptionService.js.map +1 -1
- package/dist/services/GeminiAIService.js +309 -309
- package/dist/services/IndexManager.d.ts +5 -1
- package/dist/services/IndexManager.d.ts.map +1 -1
- package/dist/services/IndexManager.js +17 -40
- package/dist/services/IndexManager.js.map +1 -1
- package/dist/services/QueryService.js +1 -1
- package/dist/services/QueryService.js.map +1 -1
- package/dist/services/StorageService.d.ts +11 -0
- package/dist/services/StorageService.d.ts.map +1 -1
- package/dist/services/StorageService.js +73 -10
- package/dist/services/StorageService.js.map +1 -1
- package/dist/services/TransactionService.d.ts +20 -0
- package/dist/services/TransactionService.d.ts.map +1 -1
- package/dist/services/TransactionService.js +43 -0
- package/dist/services/TransactionService.js.map +1 -1
- package/dist/services/ViewService.js +2 -2
- package/dist/services/ViewService.js.map +1 -1
- package/dist/services/storage/QuiltBatchManager.d.ts +101 -1
- package/dist/services/storage/QuiltBatchManager.d.ts.map +1 -1
- package/dist/services/storage/QuiltBatchManager.js +410 -20
- package/dist/services/storage/QuiltBatchManager.js.map +1 -1
- package/dist/services/storage/index.d.ts +1 -1
- package/dist/services/storage/index.d.ts.map +1 -1
- package/dist/services/storage/index.js.map +1 -1
- package/dist/utils/LRUCache.d.ts +106 -0
- package/dist/utils/LRUCache.d.ts.map +1 -0
- package/dist/utils/LRUCache.js +281 -0
- package/dist/utils/LRUCache.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/memoryIndexOnChain.d.ts +212 -0
- package/dist/utils/memoryIndexOnChain.d.ts.map +1 -0
- package/dist/utils/memoryIndexOnChain.js +312 -0
- package/dist/utils/memoryIndexOnChain.js.map +1 -0
- package/dist/utils/rebuildIndexNode.d.ts +29 -0
- package/dist/utils/rebuildIndexNode.d.ts.map +1 -1
- package/dist/utils/rebuildIndexNode.js +366 -98
- package/dist/utils/rebuildIndexNode.js.map +1 -1
- package/dist/vector/HnswWasmService.d.ts +20 -5
- package/dist/vector/HnswWasmService.d.ts.map +1 -1
- package/dist/vector/HnswWasmService.js +73 -40
- package/dist/vector/HnswWasmService.js.map +1 -1
- package/dist/vector/IHnswService.d.ts +10 -1
- package/dist/vector/IHnswService.d.ts.map +1 -1
- package/dist/vector/IHnswService.js.map +1 -1
- package/dist/vector/NodeHnswService.d.ts +16 -0
- package/dist/vector/NodeHnswService.d.ts.map +1 -1
- package/dist/vector/NodeHnswService.js +84 -5
- package/dist/vector/NodeHnswService.js.map +1 -1
- package/dist/vector/createHnswService.d.ts +1 -1
- package/dist/vector/createHnswService.js +1 -1
- package/dist/vector/index.d.ts +1 -1
- package/dist/vector/index.js +1 -1
- package/package.json +157 -157
- package/src/access/PermissionService.ts +635 -635
- package/src/aggregation/AggregationService.ts +389 -389
- package/src/ai-sdk/PDWVectorStore.ts +715 -715
- package/src/ai-sdk/index.ts +65 -65
- package/src/ai-sdk/tools.ts +460 -460
- package/src/ai-sdk/types.ts +404 -404
- package/src/batch/BatchManager.ts +597 -597
- package/src/batch/BatchingService.ts +429 -429
- package/src/batch/MemoryProcessingCache.ts +492 -492
- package/src/batch/index.ts +30 -30
- package/src/browser.ts +200 -200
- package/src/client/ClientMemoryManager.ts +987 -987
- package/src/client/PersonalDataWallet.ts +345 -345
- package/src/client/SimplePDWClient.ts +1289 -1222
- package/src/client/factory.ts +154 -154
- package/src/client/namespaces/AnalyticsNamespace.ts +377 -377
- package/src/client/namespaces/BatchNamespace.ts +356 -356
- package/src/client/namespaces/CacheNamespace.ts +123 -123
- package/src/client/namespaces/CapabilityNamespace.ts +217 -217
- package/src/client/namespaces/ClassifyNamespace.ts +169 -169
- package/src/client/namespaces/ContextNamespace.ts +297 -297
- package/src/client/namespaces/EmbeddingsNamespace.ts +99 -99
- package/src/client/namespaces/EncryptionNamespace.ts +221 -221
- package/src/client/namespaces/GraphNamespace.ts +468 -468
- package/src/client/namespaces/IndexNamespace.ts +361 -361
- package/src/client/namespaces/MemoryNamespace.ts +1422 -1135
- package/src/client/namespaces/PermissionsNamespace.ts +254 -254
- package/src/client/namespaces/PipelineNamespace.ts +220 -220
- package/src/client/namespaces/SearchNamespace.ts +1049 -1049
- package/src/client/namespaces/StorageNamespace.ts +458 -458
- package/src/client/namespaces/TxNamespace.ts +260 -260
- package/src/client/namespaces/WalletNamespace.ts +243 -243
- package/src/client/namespaces/consolidated/AINamespace.ts +449 -449
- package/src/client/namespaces/consolidated/BlockchainNamespace.ts +607 -546
- package/src/client/namespaces/consolidated/SecurityNamespace.ts +648 -648
- package/src/client/namespaces/consolidated/StorageNamespace.ts +1141 -497
- package/src/client/namespaces/consolidated/index.ts +39 -39
- package/src/client/signers/KeypairSigner.ts +108 -108
- package/src/client/signers/UnifiedSigner.ts +110 -110
- package/src/client/signers/WalletAdapterSigner.ts +159 -159
- package/src/client/signers/index.ts +26 -26
- package/src/config/ConfigurationHelper.ts +412 -412
- package/src/config/defaults.ts +51 -51
- package/src/config/index.ts +8 -8
- package/src/config/validation.ts +70 -70
- package/src/core/index.ts +14 -14
- package/src/core/interfaces/IService.ts +307 -307
- package/src/core/interfaces/index.ts +8 -8
- package/src/core/types/capability.ts +297 -297
- package/src/core/types/index.ts +870 -870
- package/src/core/types/wallet.ts +270 -270
- package/src/core/types.ts +9 -9
- package/src/core/wallet.ts +222 -222
- package/src/embedding/index.ts +19 -19
- package/src/embedding/types.ts +357 -357
- package/src/errors/index.ts +602 -602
- package/src/errors/recovery.ts +461 -461
- package/src/errors/validation.ts +567 -567
- package/src/generated/pdw/capability.ts +319 -319
- package/src/graph/GraphService.ts +887 -887
- package/src/graph/KnowledgeGraphManager.ts +728 -728
- package/src/graph/index.ts +25 -25
- package/src/index.ts +498 -474
- package/src/infrastructure/index.ts +22 -22
- package/src/infrastructure/seal/EncryptionService.ts +628 -603
- package/src/infrastructure/seal/SealService.ts +613 -615
- package/src/infrastructure/seal/index.ts +9 -9
- package/src/infrastructure/sui/BlockchainManager.ts +627 -627
- package/src/infrastructure/sui/SuiService.ts +888 -888
- package/src/infrastructure/sui/index.ts +9 -9
- package/src/infrastructure/walrus/StorageManager.ts +604 -604
- package/src/infrastructure/walrus/WalrusStorageService.ts +612 -612
- package/src/infrastructure/walrus/index.ts +9 -9
- package/src/langchain/PDWEmbeddings.ts +145 -145
- package/src/langchain/PDWVectorStore.ts +456 -456
- package/src/langchain/createPDWRAG.ts +303 -303
- package/src/langchain/index.ts +47 -47
- package/src/permissions/ConsentRepository.browser.ts +249 -249
- package/src/permissions/ConsentRepository.ts +364 -364
- package/src/pipeline/MemoryPipeline.ts +862 -862
- package/src/pipeline/PipelineManager.ts +683 -683
- package/src/pipeline/index.ts +26 -26
- package/src/retrieval/AdvancedSearchService.ts +629 -629
- package/src/retrieval/MemoryAnalyticsService.ts +711 -711
- package/src/retrieval/MemoryDecryptionPipeline.ts +825 -824
- package/src/retrieval/MemoryRetrievalService.ts +904 -830
- package/src/retrieval/index.ts +42 -42
- package/src/services/BatchService.ts +352 -352
- package/src/services/CapabilityService.ts +464 -448
- package/src/services/ClassifierService.ts +465 -465
- package/src/services/CrossContextPermissionService.ts +486 -484
- package/src/services/EmbeddingService.ts +771 -706
- package/src/services/EncryptionService.ts +712 -711
- package/src/services/GeminiAIService.ts +753 -753
- package/src/services/IndexManager.ts +977 -1004
- package/src/services/MemoryIndexService.ts +1003 -1003
- package/src/services/MemoryService.ts +369 -369
- package/src/services/QueryService.ts +890 -890
- package/src/services/StorageService.ts +1182 -1111
- package/src/services/TransactionService.ts +838 -790
- package/src/services/VectorService.ts +462 -462
- package/src/services/ViewService.ts +484 -484
- package/src/services/index.ts +25 -25
- package/src/services/storage/BlobAttributesManager.ts +333 -333
- package/src/services/storage/KnowledgeGraphManager.ts +425 -425
- package/src/services/storage/MemorySearchManager.ts +387 -387
- package/src/services/storage/QuiltBatchManager.ts +1130 -660
- package/src/services/storage/WalrusMetadataManager.ts +268 -268
- package/src/services/storage/WalrusStorageManager.ts +287 -287
- package/src/services/storage/index.ts +57 -52
- package/src/types/index.ts +13 -13
- package/src/utils/LRUCache.ts +378 -0
- package/src/utils/index.ts +76 -68
- package/src/utils/memoryIndexOnChain.ts +507 -0
- package/src/utils/rebuildIndex.ts +290 -290
- package/src/utils/rebuildIndexNode.ts +771 -424
- package/src/vector/BrowserHnswIndexService.ts +758 -758
- package/src/vector/HnswWasmService.ts +731 -679
- package/src/vector/IHnswService.ts +233 -224
- package/src/vector/NodeHnswService.ts +833 -735
- package/src/vector/VectorManager.ts +478 -478
- package/src/vector/createHnswService.ts +135 -135
- package/src/vector/index.ts +56 -56
- package/src/wallet/ContextWalletService.ts +656 -656
- 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
|
}
|