@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,468 +1,468 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Graph Namespace - Knowledge Graph Operations
|
|
3
|
-
*
|
|
4
|
-
* Provides knowledge graph extraction and querying:
|
|
5
|
-
* - Extract entities and relationships from text
|
|
6
|
-
* - Query entities
|
|
7
|
-
* - Traverse relationship graphs
|
|
8
|
-
* - Get statistics
|
|
9
|
-
*
|
|
10
|
-
* @module client/namespaces
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import type { ServiceContainer } from '../SimplePDWClient';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Entity in knowledge graph
|
|
17
|
-
*/
|
|
18
|
-
export interface Entity {
|
|
19
|
-
id: string;
|
|
20
|
-
name: string;
|
|
21
|
-
type: string;
|
|
22
|
-
confidence: number;
|
|
23
|
-
metadata?: Record<string, any>;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Relationship between entities
|
|
28
|
-
*/
|
|
29
|
-
export interface Relationship {
|
|
30
|
-
id: string;
|
|
31
|
-
source: string;
|
|
32
|
-
target: string;
|
|
33
|
-
type: string;
|
|
34
|
-
confidence: number;
|
|
35
|
-
metadata?: Record<string, any>;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Knowledge graph structure
|
|
40
|
-
*/
|
|
41
|
-
export interface KnowledgeGraph {
|
|
42
|
-
entities: Entity[];
|
|
43
|
-
relationships: Relationship[];
|
|
44
|
-
confidence: number;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Graph query result
|
|
49
|
-
*/
|
|
50
|
-
export interface GraphQueryResult {
|
|
51
|
-
entity: Entity;
|
|
52
|
-
relationships: Relationship[];
|
|
53
|
-
connectedEntities: Entity[];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Graph path (for traversal)
|
|
58
|
-
*/
|
|
59
|
-
export interface GraphPath {
|
|
60
|
-
nodes: Entity[];
|
|
61
|
-
edges: Relationship[];
|
|
62
|
-
totalConfidence: number;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Graph statistics
|
|
67
|
-
*/
|
|
68
|
-
export interface GraphStats {
|
|
69
|
-
totalEntities: number;
|
|
70
|
-
totalRelationships: number;
|
|
71
|
-
entityTypes: Record<string, number>;
|
|
72
|
-
relationshipTypes: Record<string, number>;
|
|
73
|
-
avgConfidence: number;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Entity filter
|
|
78
|
-
*/
|
|
79
|
-
export interface EntityFilter {
|
|
80
|
-
type?: string;
|
|
81
|
-
minConfidence?: number;
|
|
82
|
-
limit?: number;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Relationship filter
|
|
87
|
-
*/
|
|
88
|
-
export interface RelationshipFilter {
|
|
89
|
-
type?: string;
|
|
90
|
-
sourceId?: string;
|
|
91
|
-
targetId?: string;
|
|
92
|
-
minConfidence?: number;
|
|
93
|
-
limit?: number;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Traverse options
|
|
98
|
-
*/
|
|
99
|
-
export interface TraverseOptions {
|
|
100
|
-
maxDepth?: number;
|
|
101
|
-
relationshipTypes?: string[];
|
|
102
|
-
minConfidence?: number;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Graph Namespace
|
|
107
|
-
*
|
|
108
|
-
* Handles knowledge graph operations
|
|
109
|
-
*/
|
|
110
|
-
export class GraphNamespace {
|
|
111
|
-
constructor(private services: ServiceContainer) {}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Extract knowledge graph from text
|
|
115
|
-
*
|
|
116
|
-
* Uses AI to extract entities and relationships.
|
|
117
|
-
*
|
|
118
|
-
* @param content - Text content to analyze
|
|
119
|
-
* @returns Extracted knowledge graph
|
|
120
|
-
*
|
|
121
|
-
* @example
|
|
122
|
-
* ```typescript
|
|
123
|
-
* const graph = await pdw.graph.extract('Alice works at Google in California');
|
|
124
|
-
* // Returns: {
|
|
125
|
-
* // entities: [
|
|
126
|
-
* // { id: '1', name: 'Alice', type: 'PERSON', confidence: 0.95 },
|
|
127
|
-
* // { id: '2', name: 'Google', type: 'ORG', confidence: 0.98 },
|
|
128
|
-
* // { id: '3', name: 'California', type: 'LOCATION', confidence: 0.92 }
|
|
129
|
-
* // ],
|
|
130
|
-
* // relationships: [
|
|
131
|
-
* // { source: '1', target: '2', type: 'WORKS_AT', confidence: 0.90 }
|
|
132
|
-
* // ]
|
|
133
|
-
* // }
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
136
|
-
async extract(content: string): Promise<KnowledgeGraph> {
|
|
137
|
-
try {
|
|
138
|
-
const result = await this.services.storage.extractKnowledgeGraph(
|
|
139
|
-
content,
|
|
140
|
-
'', // blobId (optional for extraction only)
|
|
141
|
-
{ confidenceThreshold: 0.6 }
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
return {
|
|
145
|
-
entities: result.entities.map((e: any) => ({
|
|
146
|
-
id: e.id,
|
|
147
|
-
name: e.label || e.label,
|
|
148
|
-
type: e.type,
|
|
149
|
-
confidence: e.confidence || 0
|
|
150
|
-
})),
|
|
151
|
-
relationships: result.relationships.map((r: any) => ({
|
|
152
|
-
id: `${r.source}-${r.target}`,
|
|
153
|
-
source: r.source,
|
|
154
|
-
target: r.target,
|
|
155
|
-
type: r.type || 'related',
|
|
156
|
-
confidence: r.confidence || 0
|
|
157
|
-
})),
|
|
158
|
-
confidence: result.confidence || 0
|
|
159
|
-
};
|
|
160
|
-
} catch (error) {
|
|
161
|
-
throw new Error(`Graph extraction failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Query graph for a specific entity
|
|
167
|
-
*
|
|
168
|
-
* Gets entity and its relationships.
|
|
169
|
-
*
|
|
170
|
-
* @param entityId - Entity ID to query
|
|
171
|
-
* @returns Entity with relationships and connected entities
|
|
172
|
-
*/
|
|
173
|
-
async query(entityId: string): Promise<GraphQueryResult> {
|
|
174
|
-
try {
|
|
175
|
-
// Search by entity ID using searchText (StorageService doesn't have entityId param)
|
|
176
|
-
const graphData = await this.services.storage.searchKnowledgeGraph(
|
|
177
|
-
this.services.config.userAddress,
|
|
178
|
-
{ searchText: entityId, limit: 50 }
|
|
179
|
-
);
|
|
180
|
-
|
|
181
|
-
const entity = graphData.entities.find((e: any) => e.id === entityId);
|
|
182
|
-
if (!entity) {
|
|
183
|
-
throw new Error(`Entity ${entityId} not found`);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Get relationships involving this entity
|
|
187
|
-
const relationships = graphData.relationships.filter((r: any) =>
|
|
188
|
-
r.source === entityId || r.target === entityId
|
|
189
|
-
);
|
|
190
|
-
|
|
191
|
-
// Get connected entity IDs
|
|
192
|
-
const connectedIds = new Set<string>();
|
|
193
|
-
relationships.forEach((r: any) => {
|
|
194
|
-
if (r.source === entityId) connectedIds.add(r.target);
|
|
195
|
-
if (r.target === entityId) connectedIds.add(r.source);
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
const connectedEntities = graphData.entities.filter((e: any) =>
|
|
199
|
-
connectedIds.has(e.id)
|
|
200
|
-
);
|
|
201
|
-
|
|
202
|
-
return {
|
|
203
|
-
entity: {
|
|
204
|
-
id: entity.id,
|
|
205
|
-
name: entity.label, // Entity has 'label' not 'name'
|
|
206
|
-
type: entity.type,
|
|
207
|
-
confidence: entity.confidence || 0
|
|
208
|
-
},
|
|
209
|
-
relationships: relationships.map((r: any) => ({
|
|
210
|
-
id: `${r.source}-${r.target}`,
|
|
211
|
-
source: r.source,
|
|
212
|
-
target: r.target,
|
|
213
|
-
type: r.type || 'related',
|
|
214
|
-
confidence: r.confidence || 0
|
|
215
|
-
})),
|
|
216
|
-
connectedEntities: connectedEntities.map((e: any) => ({
|
|
217
|
-
id: e.id,
|
|
218
|
-
name: e.label || '', // Entity has 'label' not 'name'
|
|
219
|
-
type: e.type,
|
|
220
|
-
confidence: e.confidence || 0
|
|
221
|
-
}))
|
|
222
|
-
};
|
|
223
|
-
} catch (error) {
|
|
224
|
-
throw new Error(`Graph query failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Traverse graph from a starting entity
|
|
230
|
-
*
|
|
231
|
-
* Follows relationships to discover connected entities.
|
|
232
|
-
*
|
|
233
|
-
* @param startEntity - Entity ID to start from
|
|
234
|
-
* @param options - Traversal options
|
|
235
|
-
* @returns Array of paths through the graph
|
|
236
|
-
*/
|
|
237
|
-
async traverse(
|
|
238
|
-
startEntity: string,
|
|
239
|
-
options: TraverseOptions = {}
|
|
240
|
-
): Promise<GraphPath[]> {
|
|
241
|
-
try {
|
|
242
|
-
const { maxDepth = 3, relationshipTypes, minConfidence = 0.5 } = options;
|
|
243
|
-
|
|
244
|
-
// Get graph data
|
|
245
|
-
const graphData = await this.services.storage.searchKnowledgeGraph(
|
|
246
|
-
this.services.config.userAddress,
|
|
247
|
-
{ searchText: startEntity, limit: 100 }
|
|
248
|
-
);
|
|
249
|
-
|
|
250
|
-
const paths: GraphPath[] = [];
|
|
251
|
-
const visited = new Set<string>();
|
|
252
|
-
|
|
253
|
-
// BFS traversal
|
|
254
|
-
const queue: Array<{
|
|
255
|
-
currentEntity: string;
|
|
256
|
-
path: Entity[];
|
|
257
|
-
edges: Relationship[];
|
|
258
|
-
depth: number;
|
|
259
|
-
}> = [{
|
|
260
|
-
currentEntity: startEntity,
|
|
261
|
-
path: [],
|
|
262
|
-
edges: [],
|
|
263
|
-
depth: 0
|
|
264
|
-
}];
|
|
265
|
-
|
|
266
|
-
while (queue.length > 0 && paths.length < 20) {
|
|
267
|
-
const { currentEntity, path, edges, depth } = queue.shift()!;
|
|
268
|
-
|
|
269
|
-
if (depth >= maxDepth || visited.has(currentEntity)) {
|
|
270
|
-
if (path.length > 0) {
|
|
271
|
-
const totalConfidence = edges.reduce((sum, e) => sum + e.confidence, 0) / edges.length;
|
|
272
|
-
paths.push({ nodes: path, edges, totalConfidence });
|
|
273
|
-
}
|
|
274
|
-
continue;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
visited.add(currentEntity);
|
|
278
|
-
|
|
279
|
-
// Find entity
|
|
280
|
-
const entity = graphData.entities.find((e: any) => e.id === currentEntity);
|
|
281
|
-
if (!entity) continue;
|
|
282
|
-
|
|
283
|
-
const entityObj: Entity = {
|
|
284
|
-
id: entity.id,
|
|
285
|
-
name: entity.label || '', // Entity only has 'label'
|
|
286
|
-
type: entity.type,
|
|
287
|
-
confidence: entity.confidence || 0
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
// Find outgoing relationships
|
|
291
|
-
const outgoing = graphData.relationships.filter((r: any) => {
|
|
292
|
-
const matches = r.source === currentEntity;
|
|
293
|
-
const typeMatch = !relationshipTypes || relationshipTypes.includes(r.type);
|
|
294
|
-
const confMatch = (r.confidence || 0) >= minConfidence;
|
|
295
|
-
return matches && typeMatch && confMatch;
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
// Add to queue
|
|
299
|
-
outgoing.forEach((r: any) => {
|
|
300
|
-
queue.push({
|
|
301
|
-
currentEntity: r.target,
|
|
302
|
-
path: [...path, entityObj],
|
|
303
|
-
edges: [...edges, {
|
|
304
|
-
id: `${r.source}-${r.target}`,
|
|
305
|
-
source: r.source,
|
|
306
|
-
target: r.target,
|
|
307
|
-
type: r.type || 'related',
|
|
308
|
-
confidence: r.confidence || 0
|
|
309
|
-
}],
|
|
310
|
-
depth: depth + 1
|
|
311
|
-
});
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
return paths.slice(0, 20); // Limit results
|
|
316
|
-
} catch (error) {
|
|
317
|
-
throw new Error(`Graph traversal failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* Get all entities matching filter
|
|
323
|
-
*
|
|
324
|
-
* @param filter - Entity filter options
|
|
325
|
-
* @returns Array of entities
|
|
326
|
-
*/
|
|
327
|
-
async getEntities(filter: EntityFilter = {}): Promise<Entity[]> {
|
|
328
|
-
try {
|
|
329
|
-
const graphData = await this.services.storage.searchKnowledgeGraph(
|
|
330
|
-
this.services.config.userAddress,
|
|
331
|
-
{ limit: filter.limit || 100 }
|
|
332
|
-
);
|
|
333
|
-
|
|
334
|
-
let entities = graphData.entities;
|
|
335
|
-
|
|
336
|
-
// Apply filters
|
|
337
|
-
if (filter.type) {
|
|
338
|
-
entities = entities.filter((e: any) => e.type === filter.type);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
if (filter.minConfidence) {
|
|
342
|
-
entities = entities.filter((e: any) => (e.confidence || 0) >= filter.minConfidence!);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
return entities.map((e: any) => ({
|
|
346
|
-
id: e.id,
|
|
347
|
-
name: e.label, // Entity only has 'label', not 'name'
|
|
348
|
-
type: e.type,
|
|
349
|
-
confidence: e.confidence || 0,
|
|
350
|
-
metadata: e.metadata
|
|
351
|
-
}));
|
|
352
|
-
} catch (error) {
|
|
353
|
-
throw new Error(`Get entities failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Get all relationships matching filter
|
|
359
|
-
*
|
|
360
|
-
* @param filter - Relationship filter options
|
|
361
|
-
* @returns Array of relationships
|
|
362
|
-
*/
|
|
363
|
-
async getRelationships(filter: RelationshipFilter = {}): Promise<Relationship[]> {
|
|
364
|
-
try {
|
|
365
|
-
const graphData = await this.services.storage.searchKnowledgeGraph(
|
|
366
|
-
this.services.config.userAddress,
|
|
367
|
-
{
|
|
368
|
-
searchText: filter.sourceId || filter.targetId || '',
|
|
369
|
-
limit: filter.limit || 100
|
|
370
|
-
}
|
|
371
|
-
);
|
|
372
|
-
|
|
373
|
-
let relationships = graphData.relationships;
|
|
374
|
-
|
|
375
|
-
// Apply filters
|
|
376
|
-
if (filter.type) {
|
|
377
|
-
relationships = relationships.filter((r: any) => r.type === filter.type);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
if (filter.sourceId) {
|
|
381
|
-
relationships = relationships.filter((r: any) => r.source === filter.sourceId);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
if (filter.targetId) {
|
|
385
|
-
relationships = relationships.filter((r: any) => r.target === filter.targetId);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
if (filter.minConfidence) {
|
|
389
|
-
relationships = relationships.filter((r: any) =>
|
|
390
|
-
(r.confidence || 0) >= filter.minConfidence!
|
|
391
|
-
);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
return relationships.map((r: any) => ({
|
|
395
|
-
id: `${r.source}-${r.target}`,
|
|
396
|
-
source: r.source,
|
|
397
|
-
target: r.target,
|
|
398
|
-
type: r.type || 'related',
|
|
399
|
-
confidence: r.confidence || 0,
|
|
400
|
-
metadata: r.metadata
|
|
401
|
-
}));
|
|
402
|
-
} catch (error) {
|
|
403
|
-
throw new Error(`Get relationships failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
* Get knowledge graph statistics
|
|
409
|
-
*
|
|
410
|
-
* Calculates average confidence from entity and relationship confidence scores.
|
|
411
|
-
*
|
|
412
|
-
* @returns Graph statistics
|
|
413
|
-
*/
|
|
414
|
-
async stats(): Promise<GraphStats> {
|
|
415
|
-
try {
|
|
416
|
-
const stats = await this.services.storage.getGraphStatistics(
|
|
417
|
-
this.services.config.userAddress
|
|
418
|
-
);
|
|
419
|
-
|
|
420
|
-
// Calculate average confidence from graph entities and relationships
|
|
421
|
-
let avgConfidence = 0;
|
|
422
|
-
|
|
423
|
-
if (stats.totalEntities > 0 || stats.totalRelationships > 0) {
|
|
424
|
-
// Get graph data to calculate average confidence
|
|
425
|
-
try {
|
|
426
|
-
const graphData = await this.services.storage.searchKnowledgeGraph(
|
|
427
|
-
this.services.config.userAddress,
|
|
428
|
-
{ limit: 1000 }
|
|
429
|
-
);
|
|
430
|
-
|
|
431
|
-
const confidences: number[] = [];
|
|
432
|
-
|
|
433
|
-
// Collect entity confidences
|
|
434
|
-
for (const entity of graphData.entities || []) {
|
|
435
|
-
if (typeof entity.confidence === 'number') {
|
|
436
|
-
confidences.push(entity.confidence);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// Collect relationship confidences
|
|
441
|
-
for (const rel of graphData.relationships || []) {
|
|
442
|
-
if (typeof rel.confidence === 'number') {
|
|
443
|
-
confidences.push(rel.confidence);
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// Calculate average
|
|
448
|
-
if (confidences.length > 0) {
|
|
449
|
-
avgConfidence = confidences.reduce((sum, c) => sum + c, 0) / confidences.length;
|
|
450
|
-
}
|
|
451
|
-
} catch {
|
|
452
|
-
// If we can't get graph data for confidence calculation, use 0
|
|
453
|
-
avgConfidence = 0;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
return {
|
|
458
|
-
totalEntities: stats.totalEntities,
|
|
459
|
-
totalRelationships: stats.totalRelationships,
|
|
460
|
-
entityTypes: stats.entityTypes,
|
|
461
|
-
relationshipTypes: stats.relationshipTypes,
|
|
462
|
-
avgConfidence
|
|
463
|
-
};
|
|
464
|
-
} catch (error) {
|
|
465
|
-
throw new Error(`Get graph stats failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Graph Namespace - Knowledge Graph Operations
|
|
3
|
+
*
|
|
4
|
+
* Provides knowledge graph extraction and querying:
|
|
5
|
+
* - Extract entities and relationships from text
|
|
6
|
+
* - Query entities
|
|
7
|
+
* - Traverse relationship graphs
|
|
8
|
+
* - Get statistics
|
|
9
|
+
*
|
|
10
|
+
* @module client/namespaces
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { ServiceContainer } from '../SimplePDWClient';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Entity in knowledge graph
|
|
17
|
+
*/
|
|
18
|
+
export interface Entity {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
type: string;
|
|
22
|
+
confidence: number;
|
|
23
|
+
metadata?: Record<string, any>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Relationship between entities
|
|
28
|
+
*/
|
|
29
|
+
export interface Relationship {
|
|
30
|
+
id: string;
|
|
31
|
+
source: string;
|
|
32
|
+
target: string;
|
|
33
|
+
type: string;
|
|
34
|
+
confidence: number;
|
|
35
|
+
metadata?: Record<string, any>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Knowledge graph structure
|
|
40
|
+
*/
|
|
41
|
+
export interface KnowledgeGraph {
|
|
42
|
+
entities: Entity[];
|
|
43
|
+
relationships: Relationship[];
|
|
44
|
+
confidence: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Graph query result
|
|
49
|
+
*/
|
|
50
|
+
export interface GraphQueryResult {
|
|
51
|
+
entity: Entity;
|
|
52
|
+
relationships: Relationship[];
|
|
53
|
+
connectedEntities: Entity[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Graph path (for traversal)
|
|
58
|
+
*/
|
|
59
|
+
export interface GraphPath {
|
|
60
|
+
nodes: Entity[];
|
|
61
|
+
edges: Relationship[];
|
|
62
|
+
totalConfidence: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Graph statistics
|
|
67
|
+
*/
|
|
68
|
+
export interface GraphStats {
|
|
69
|
+
totalEntities: number;
|
|
70
|
+
totalRelationships: number;
|
|
71
|
+
entityTypes: Record<string, number>;
|
|
72
|
+
relationshipTypes: Record<string, number>;
|
|
73
|
+
avgConfidence: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Entity filter
|
|
78
|
+
*/
|
|
79
|
+
export interface EntityFilter {
|
|
80
|
+
type?: string;
|
|
81
|
+
minConfidence?: number;
|
|
82
|
+
limit?: number;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Relationship filter
|
|
87
|
+
*/
|
|
88
|
+
export interface RelationshipFilter {
|
|
89
|
+
type?: string;
|
|
90
|
+
sourceId?: string;
|
|
91
|
+
targetId?: string;
|
|
92
|
+
minConfidence?: number;
|
|
93
|
+
limit?: number;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Traverse options
|
|
98
|
+
*/
|
|
99
|
+
export interface TraverseOptions {
|
|
100
|
+
maxDepth?: number;
|
|
101
|
+
relationshipTypes?: string[];
|
|
102
|
+
minConfidence?: number;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Graph Namespace
|
|
107
|
+
*
|
|
108
|
+
* Handles knowledge graph operations
|
|
109
|
+
*/
|
|
110
|
+
export class GraphNamespace {
|
|
111
|
+
constructor(private services: ServiceContainer) {}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Extract knowledge graph from text
|
|
115
|
+
*
|
|
116
|
+
* Uses AI to extract entities and relationships.
|
|
117
|
+
*
|
|
118
|
+
* @param content - Text content to analyze
|
|
119
|
+
* @returns Extracted knowledge graph
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```typescript
|
|
123
|
+
* const graph = await pdw.graph.extract('Alice works at Google in California');
|
|
124
|
+
* // Returns: {
|
|
125
|
+
* // entities: [
|
|
126
|
+
* // { id: '1', name: 'Alice', type: 'PERSON', confidence: 0.95 },
|
|
127
|
+
* // { id: '2', name: 'Google', type: 'ORG', confidence: 0.98 },
|
|
128
|
+
* // { id: '3', name: 'California', type: 'LOCATION', confidence: 0.92 }
|
|
129
|
+
* // ],
|
|
130
|
+
* // relationships: [
|
|
131
|
+
* // { source: '1', target: '2', type: 'WORKS_AT', confidence: 0.90 }
|
|
132
|
+
* // ]
|
|
133
|
+
* // }
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
async extract(content: string): Promise<KnowledgeGraph> {
|
|
137
|
+
try {
|
|
138
|
+
const result = await this.services.storage.extractKnowledgeGraph(
|
|
139
|
+
content,
|
|
140
|
+
'', // blobId (optional for extraction only)
|
|
141
|
+
{ confidenceThreshold: 0.6 }
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
entities: result.entities.map((e: any) => ({
|
|
146
|
+
id: e.id,
|
|
147
|
+
name: e.label || e.label,
|
|
148
|
+
type: e.type,
|
|
149
|
+
confidence: e.confidence || 0
|
|
150
|
+
})),
|
|
151
|
+
relationships: result.relationships.map((r: any) => ({
|
|
152
|
+
id: `${r.source}-${r.target}`,
|
|
153
|
+
source: r.source,
|
|
154
|
+
target: r.target,
|
|
155
|
+
type: r.type || 'related',
|
|
156
|
+
confidence: r.confidence || 0
|
|
157
|
+
})),
|
|
158
|
+
confidence: result.confidence || 0
|
|
159
|
+
};
|
|
160
|
+
} catch (error) {
|
|
161
|
+
throw new Error(`Graph extraction failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Query graph for a specific entity
|
|
167
|
+
*
|
|
168
|
+
* Gets entity and its relationships.
|
|
169
|
+
*
|
|
170
|
+
* @param entityId - Entity ID to query
|
|
171
|
+
* @returns Entity with relationships and connected entities
|
|
172
|
+
*/
|
|
173
|
+
async query(entityId: string): Promise<GraphQueryResult> {
|
|
174
|
+
try {
|
|
175
|
+
// Search by entity ID using searchText (StorageService doesn't have entityId param)
|
|
176
|
+
const graphData = await this.services.storage.searchKnowledgeGraph(
|
|
177
|
+
this.services.config.userAddress,
|
|
178
|
+
{ searchText: entityId, limit: 50 }
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
const entity = graphData.entities.find((e: any) => e.id === entityId);
|
|
182
|
+
if (!entity) {
|
|
183
|
+
throw new Error(`Entity ${entityId} not found`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Get relationships involving this entity
|
|
187
|
+
const relationships = graphData.relationships.filter((r: any) =>
|
|
188
|
+
r.source === entityId || r.target === entityId
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
// Get connected entity IDs
|
|
192
|
+
const connectedIds = new Set<string>();
|
|
193
|
+
relationships.forEach((r: any) => {
|
|
194
|
+
if (r.source === entityId) connectedIds.add(r.target);
|
|
195
|
+
if (r.target === entityId) connectedIds.add(r.source);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const connectedEntities = graphData.entities.filter((e: any) =>
|
|
199
|
+
connectedIds.has(e.id)
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
entity: {
|
|
204
|
+
id: entity.id,
|
|
205
|
+
name: entity.label, // Entity has 'label' not 'name'
|
|
206
|
+
type: entity.type,
|
|
207
|
+
confidence: entity.confidence || 0
|
|
208
|
+
},
|
|
209
|
+
relationships: relationships.map((r: any) => ({
|
|
210
|
+
id: `${r.source}-${r.target}`,
|
|
211
|
+
source: r.source,
|
|
212
|
+
target: r.target,
|
|
213
|
+
type: r.type || 'related',
|
|
214
|
+
confidence: r.confidence || 0
|
|
215
|
+
})),
|
|
216
|
+
connectedEntities: connectedEntities.map((e: any) => ({
|
|
217
|
+
id: e.id,
|
|
218
|
+
name: e.label || '', // Entity has 'label' not 'name'
|
|
219
|
+
type: e.type,
|
|
220
|
+
confidence: e.confidence || 0
|
|
221
|
+
}))
|
|
222
|
+
};
|
|
223
|
+
} catch (error) {
|
|
224
|
+
throw new Error(`Graph query failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Traverse graph from a starting entity
|
|
230
|
+
*
|
|
231
|
+
* Follows relationships to discover connected entities.
|
|
232
|
+
*
|
|
233
|
+
* @param startEntity - Entity ID to start from
|
|
234
|
+
* @param options - Traversal options
|
|
235
|
+
* @returns Array of paths through the graph
|
|
236
|
+
*/
|
|
237
|
+
async traverse(
|
|
238
|
+
startEntity: string,
|
|
239
|
+
options: TraverseOptions = {}
|
|
240
|
+
): Promise<GraphPath[]> {
|
|
241
|
+
try {
|
|
242
|
+
const { maxDepth = 3, relationshipTypes, minConfidence = 0.5 } = options;
|
|
243
|
+
|
|
244
|
+
// Get graph data
|
|
245
|
+
const graphData = await this.services.storage.searchKnowledgeGraph(
|
|
246
|
+
this.services.config.userAddress,
|
|
247
|
+
{ searchText: startEntity, limit: 100 }
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
const paths: GraphPath[] = [];
|
|
251
|
+
const visited = new Set<string>();
|
|
252
|
+
|
|
253
|
+
// BFS traversal
|
|
254
|
+
const queue: Array<{
|
|
255
|
+
currentEntity: string;
|
|
256
|
+
path: Entity[];
|
|
257
|
+
edges: Relationship[];
|
|
258
|
+
depth: number;
|
|
259
|
+
}> = [{
|
|
260
|
+
currentEntity: startEntity,
|
|
261
|
+
path: [],
|
|
262
|
+
edges: [],
|
|
263
|
+
depth: 0
|
|
264
|
+
}];
|
|
265
|
+
|
|
266
|
+
while (queue.length > 0 && paths.length < 20) {
|
|
267
|
+
const { currentEntity, path, edges, depth } = queue.shift()!;
|
|
268
|
+
|
|
269
|
+
if (depth >= maxDepth || visited.has(currentEntity)) {
|
|
270
|
+
if (path.length > 0) {
|
|
271
|
+
const totalConfidence = edges.reduce((sum, e) => sum + e.confidence, 0) / edges.length;
|
|
272
|
+
paths.push({ nodes: path, edges, totalConfidence });
|
|
273
|
+
}
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
visited.add(currentEntity);
|
|
278
|
+
|
|
279
|
+
// Find entity
|
|
280
|
+
const entity = graphData.entities.find((e: any) => e.id === currentEntity);
|
|
281
|
+
if (!entity) continue;
|
|
282
|
+
|
|
283
|
+
const entityObj: Entity = {
|
|
284
|
+
id: entity.id,
|
|
285
|
+
name: entity.label || '', // Entity only has 'label'
|
|
286
|
+
type: entity.type,
|
|
287
|
+
confidence: entity.confidence || 0
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// Find outgoing relationships
|
|
291
|
+
const outgoing = graphData.relationships.filter((r: any) => {
|
|
292
|
+
const matches = r.source === currentEntity;
|
|
293
|
+
const typeMatch = !relationshipTypes || relationshipTypes.includes(r.type);
|
|
294
|
+
const confMatch = (r.confidence || 0) >= minConfidence;
|
|
295
|
+
return matches && typeMatch && confMatch;
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// Add to queue
|
|
299
|
+
outgoing.forEach((r: any) => {
|
|
300
|
+
queue.push({
|
|
301
|
+
currentEntity: r.target,
|
|
302
|
+
path: [...path, entityObj],
|
|
303
|
+
edges: [...edges, {
|
|
304
|
+
id: `${r.source}-${r.target}`,
|
|
305
|
+
source: r.source,
|
|
306
|
+
target: r.target,
|
|
307
|
+
type: r.type || 'related',
|
|
308
|
+
confidence: r.confidence || 0
|
|
309
|
+
}],
|
|
310
|
+
depth: depth + 1
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return paths.slice(0, 20); // Limit results
|
|
316
|
+
} catch (error) {
|
|
317
|
+
throw new Error(`Graph traversal failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Get all entities matching filter
|
|
323
|
+
*
|
|
324
|
+
* @param filter - Entity filter options
|
|
325
|
+
* @returns Array of entities
|
|
326
|
+
*/
|
|
327
|
+
async getEntities(filter: EntityFilter = {}): Promise<Entity[]> {
|
|
328
|
+
try {
|
|
329
|
+
const graphData = await this.services.storage.searchKnowledgeGraph(
|
|
330
|
+
this.services.config.userAddress,
|
|
331
|
+
{ limit: filter.limit || 100 }
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
let entities = graphData.entities;
|
|
335
|
+
|
|
336
|
+
// Apply filters
|
|
337
|
+
if (filter.type) {
|
|
338
|
+
entities = entities.filter((e: any) => e.type === filter.type);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (filter.minConfidence) {
|
|
342
|
+
entities = entities.filter((e: any) => (e.confidence || 0) >= filter.minConfidence!);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return entities.map((e: any) => ({
|
|
346
|
+
id: e.id,
|
|
347
|
+
name: e.label, // Entity only has 'label', not 'name'
|
|
348
|
+
type: e.type,
|
|
349
|
+
confidence: e.confidence || 0,
|
|
350
|
+
metadata: e.metadata
|
|
351
|
+
}));
|
|
352
|
+
} catch (error) {
|
|
353
|
+
throw new Error(`Get entities failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Get all relationships matching filter
|
|
359
|
+
*
|
|
360
|
+
* @param filter - Relationship filter options
|
|
361
|
+
* @returns Array of relationships
|
|
362
|
+
*/
|
|
363
|
+
async getRelationships(filter: RelationshipFilter = {}): Promise<Relationship[]> {
|
|
364
|
+
try {
|
|
365
|
+
const graphData = await this.services.storage.searchKnowledgeGraph(
|
|
366
|
+
this.services.config.userAddress,
|
|
367
|
+
{
|
|
368
|
+
searchText: filter.sourceId || filter.targetId || '',
|
|
369
|
+
limit: filter.limit || 100
|
|
370
|
+
}
|
|
371
|
+
);
|
|
372
|
+
|
|
373
|
+
let relationships = graphData.relationships;
|
|
374
|
+
|
|
375
|
+
// Apply filters
|
|
376
|
+
if (filter.type) {
|
|
377
|
+
relationships = relationships.filter((r: any) => r.type === filter.type);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (filter.sourceId) {
|
|
381
|
+
relationships = relationships.filter((r: any) => r.source === filter.sourceId);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (filter.targetId) {
|
|
385
|
+
relationships = relationships.filter((r: any) => r.target === filter.targetId);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (filter.minConfidence) {
|
|
389
|
+
relationships = relationships.filter((r: any) =>
|
|
390
|
+
(r.confidence || 0) >= filter.minConfidence!
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return relationships.map((r: any) => ({
|
|
395
|
+
id: `${r.source}-${r.target}`,
|
|
396
|
+
source: r.source,
|
|
397
|
+
target: r.target,
|
|
398
|
+
type: r.type || 'related',
|
|
399
|
+
confidence: r.confidence || 0,
|
|
400
|
+
metadata: r.metadata
|
|
401
|
+
}));
|
|
402
|
+
} catch (error) {
|
|
403
|
+
throw new Error(`Get relationships failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Get knowledge graph statistics
|
|
409
|
+
*
|
|
410
|
+
* Calculates average confidence from entity and relationship confidence scores.
|
|
411
|
+
*
|
|
412
|
+
* @returns Graph statistics
|
|
413
|
+
*/
|
|
414
|
+
async stats(): Promise<GraphStats> {
|
|
415
|
+
try {
|
|
416
|
+
const stats = await this.services.storage.getGraphStatistics(
|
|
417
|
+
this.services.config.userAddress
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
// Calculate average confidence from graph entities and relationships
|
|
421
|
+
let avgConfidence = 0;
|
|
422
|
+
|
|
423
|
+
if (stats.totalEntities > 0 || stats.totalRelationships > 0) {
|
|
424
|
+
// Get graph data to calculate average confidence
|
|
425
|
+
try {
|
|
426
|
+
const graphData = await this.services.storage.searchKnowledgeGraph(
|
|
427
|
+
this.services.config.userAddress,
|
|
428
|
+
{ limit: 1000 }
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
const confidences: number[] = [];
|
|
432
|
+
|
|
433
|
+
// Collect entity confidences
|
|
434
|
+
for (const entity of graphData.entities || []) {
|
|
435
|
+
if (typeof entity.confidence === 'number') {
|
|
436
|
+
confidences.push(entity.confidence);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Collect relationship confidences
|
|
441
|
+
for (const rel of graphData.relationships || []) {
|
|
442
|
+
if (typeof rel.confidence === 'number') {
|
|
443
|
+
confidences.push(rel.confidence);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Calculate average
|
|
448
|
+
if (confidences.length > 0) {
|
|
449
|
+
avgConfidence = confidences.reduce((sum, c) => sum + c, 0) / confidences.length;
|
|
450
|
+
}
|
|
451
|
+
} catch {
|
|
452
|
+
// If we can't get graph data for confidence calculation, use 0
|
|
453
|
+
avgConfidence = 0;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return {
|
|
458
|
+
totalEntities: stats.totalEntities,
|
|
459
|
+
totalRelationships: stats.totalRelationships,
|
|
460
|
+
entityTypes: stats.entityTypes,
|
|
461
|
+
relationshipTypes: stats.relationshipTypes,
|
|
462
|
+
avgConfidence
|
|
463
|
+
};
|
|
464
|
+
} catch (error) {
|
|
465
|
+
throw new Error(`Get graph stats failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|