@henrychong-ai/mcp-neo4j-knowledge-graph 2.0.3 → 2.1.1
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/SETUP_AUTOMATION.md +2 -2
- package/dist/KnowledgeGraphManager.js +10 -10
- package/dist/KnowledgeGraphManager.js.map +1 -1
- package/dist/__test-utils__/fixtures.js +1 -1
- package/dist/__test-utils__/fixtures.js.map +1 -1
- package/dist/cli/generate-embeddings.js +3 -3
- package/dist/cli/generate-embeddings.js.map +1 -1
- package/dist/cli/neo4j-setup.js +2 -2
- package/dist/cli/neo4j-setup.js.map +1 -1
- package/dist/embeddings/DefaultEmbeddingService.js +1 -1
- package/dist/embeddings/DefaultEmbeddingService.js.map +1 -1
- package/dist/embeddings/EmbeddingJobManager.js +2 -2
- package/dist/embeddings/EmbeddingJobManager.js.map +1 -1
- package/dist/embeddings/OpenAIEmbeddingService.js +1 -1
- package/dist/embeddings/OpenAIEmbeddingService.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/retrieval/scorers/ConnectionStrengthScorer.js +3 -3
- package/dist/retrieval/scorers/ConnectionStrengthScorer.js.map +1 -1
- package/dist/retrieval/scorers/GraphTraversalScorer.js +5 -5
- package/dist/retrieval/scorers/GraphTraversalScorer.js.map +1 -1
- package/dist/server/handlers/callToolHandler.js +421 -429
- package/dist/server/handlers/callToolHandler.js.map +1 -1
- package/dist/server/setup.js +2 -14
- package/dist/server/setup.js.map +1 -1
- package/dist/storage/SearchResultCache.js +1 -1
- package/dist/storage/SearchResultCache.js.map +1 -1
- package/dist/storage/StorageProviderFactory.js +1 -1
- package/dist/storage/StorageProviderFactory.js.map +1 -1
- package/dist/storage/neo4j/Neo4jSchemaManager.js +4 -4
- package/dist/storage/neo4j/Neo4jSchemaManager.js.map +1 -1
- package/dist/storage/neo4j/Neo4jStorageProvider.js +39 -39
- package/dist/storage/neo4j/Neo4jStorageProvider.js.map +1 -1
- package/dist/storage/neo4j/Neo4jVectorStore.js +3 -3
- package/dist/storage/neo4j/Neo4jVectorStore.js.map +1 -1
- package/package.json +12 -24
|
@@ -25,490 +25,482 @@ knowledgeGraphManager) {
|
|
|
25
25
|
if (!args) {
|
|
26
26
|
throw new Error(`No arguments provided for tool: ${name}`);
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (!relation) {
|
|
56
|
-
return {
|
|
57
|
-
content: [
|
|
58
|
-
{
|
|
59
|
-
type: 'text',
|
|
60
|
-
text: `Relation not found: ${args.from} -> ${args.relationType} -> ${args.to}`,
|
|
61
|
-
},
|
|
62
|
-
],
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
return { content: [{ type: 'text', text: JSON.stringify(relation, null, 2) }] };
|
|
66
|
-
}
|
|
67
|
-
case 'update_relation': {
|
|
68
|
-
await knowledgeGraphManager.updateRelation(args.relation);
|
|
69
|
-
return { content: [{ type: 'text', text: 'Relation updated successfully' }] };
|
|
70
|
-
}
|
|
71
|
-
case 'search_nodes': {
|
|
28
|
+
switch (name) {
|
|
29
|
+
case 'create_entities': {
|
|
30
|
+
return await toolHandlers.handleCreateEntities(args, knowledgeGraphManager);
|
|
31
|
+
}
|
|
32
|
+
case 'read_graph': {
|
|
33
|
+
return await toolHandlers.handleReadGraph(args, knowledgeGraphManager);
|
|
34
|
+
}
|
|
35
|
+
case 'create_relations': {
|
|
36
|
+
return await toolHandlers.handleCreateRelations(args, knowledgeGraphManager);
|
|
37
|
+
}
|
|
38
|
+
case 'add_observations': {
|
|
39
|
+
return await toolHandlers.handleAddObservations(args, knowledgeGraphManager);
|
|
40
|
+
}
|
|
41
|
+
case 'delete_entities': {
|
|
42
|
+
return await toolHandlers.handleDeleteEntities(args, knowledgeGraphManager);
|
|
43
|
+
}
|
|
44
|
+
case 'delete_observations': {
|
|
45
|
+
await knowledgeGraphManager.deleteObservations(args.deletions);
|
|
46
|
+
return { content: [{ type: 'text', text: 'Observations deleted successfully' }] };
|
|
47
|
+
}
|
|
48
|
+
case 'delete_relations': {
|
|
49
|
+
await knowledgeGraphManager.deleteRelations(args.relations);
|
|
50
|
+
return { content: [{ type: 'text', text: 'Relations deleted successfully' }] };
|
|
51
|
+
}
|
|
52
|
+
case 'get_relation': {
|
|
53
|
+
const relation = await knowledgeGraphManager.getRelation(args.from, args.to, args.relationType);
|
|
54
|
+
if (!relation) {
|
|
72
55
|
return {
|
|
73
56
|
content: [
|
|
74
57
|
{
|
|
75
58
|
type: 'text',
|
|
76
|
-
text:
|
|
77
|
-
domain: args.domain,
|
|
78
|
-
includeNullDomain: args.include_null_domain,
|
|
79
|
-
}), null, 2),
|
|
59
|
+
text: `Relation not found: ${args.from} -> ${args.relationType} -> ${args.to}`,
|
|
80
60
|
},
|
|
81
61
|
],
|
|
82
62
|
};
|
|
83
63
|
}
|
|
84
|
-
|
|
64
|
+
return { content: [{ type: 'text', text: JSON.stringify(relation, null, 2) }] };
|
|
65
|
+
}
|
|
66
|
+
case 'update_relation': {
|
|
67
|
+
await knowledgeGraphManager.updateRelation(args.relation);
|
|
68
|
+
return { content: [{ type: 'text', text: 'Relation updated successfully' }] };
|
|
69
|
+
}
|
|
70
|
+
case 'search_nodes': {
|
|
71
|
+
return {
|
|
72
|
+
content: [
|
|
73
|
+
{
|
|
74
|
+
type: 'text',
|
|
75
|
+
text: JSON.stringify(await knowledgeGraphManager.searchNodes(args.query, {
|
|
76
|
+
domain: args.domain,
|
|
77
|
+
includeNullDomain: args.include_null_domain,
|
|
78
|
+
}), null, 2),
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
case 'open_nodes': {
|
|
84
|
+
return {
|
|
85
|
+
content: [
|
|
86
|
+
{
|
|
87
|
+
type: 'text',
|
|
88
|
+
text: JSON.stringify(await knowledgeGraphManager.openNodes(args.names), null, 2),
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
case 'get_entity_history': {
|
|
94
|
+
try {
|
|
95
|
+
const history = await knowledgeGraphManager.getEntityHistory(args.entityName);
|
|
96
|
+
return { content: [{ type: 'text', text: JSON.stringify(history, null, 2) }] };
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
85
100
|
return {
|
|
86
|
-
content: [
|
|
87
|
-
{
|
|
88
|
-
type: 'text',
|
|
89
|
-
text: JSON.stringify(await knowledgeGraphManager.openNodes(args.names), null, 2),
|
|
90
|
-
},
|
|
91
|
-
],
|
|
101
|
+
content: [{ type: 'text', text: `Error retrieving entity history: ${errorMessage}` }],
|
|
92
102
|
};
|
|
93
103
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
}
|
|
104
|
+
}
|
|
105
|
+
case 'get_relation_history': {
|
|
106
|
+
try {
|
|
107
|
+
const history = await knowledgeGraphManager.getRelationHistory(args.from, args.to, args.relationType);
|
|
108
|
+
return { content: [{ type: 'text', text: JSON.stringify(history, null, 2) }] };
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
112
|
+
return {
|
|
113
|
+
content: [{ type: 'text', text: `Error retrieving relation history: ${errorMessage}` }],
|
|
114
|
+
};
|
|
105
115
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
116
|
+
}
|
|
117
|
+
case 'get_graph_at_time': {
|
|
118
|
+
try {
|
|
119
|
+
const graph = await knowledgeGraphManager.getGraphAtTime(args.timestamp);
|
|
120
|
+
return { content: [{ type: 'text', text: JSON.stringify(graph, null, 2) }] };
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
124
|
+
return {
|
|
125
|
+
content: [{ type: 'text', text: `Error retrieving graph at time: ${errorMessage}` }],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
case 'get_decayed_graph': {
|
|
130
|
+
try {
|
|
131
|
+
// Extract optional parameters if provided by client
|
|
132
|
+
const options = {};
|
|
133
|
+
if (args.reference_time) {
|
|
134
|
+
options.referenceTime = Number(args.reference_time);
|
|
110
135
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
content: [{ type: 'text', text: `Error retrieving relation history: ${errorMessage}` }],
|
|
115
|
-
};
|
|
136
|
+
if (args.decay_factor) {
|
|
137
|
+
options.decayFactor = Number(args.decay_factor);
|
|
116
138
|
}
|
|
139
|
+
// Pass options to getDecayedGraph if any are provided
|
|
140
|
+
const graph = Object.keys(options).length > 0
|
|
141
|
+
? await knowledgeGraphManager.getDecayedGraph(options)
|
|
142
|
+
: await knowledgeGraphManager.getDecayedGraph();
|
|
143
|
+
return { content: [{ type: 'text', text: JSON.stringify(graph, null, 2) }] };
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
147
|
+
return {
|
|
148
|
+
content: [{ type: 'text', text: `Error retrieving decayed graph: ${errorMessage}` }],
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
case 'force_generate_embedding': {
|
|
153
|
+
// Validate arguments
|
|
154
|
+
if (!args.entity_name) {
|
|
155
|
+
throw new Error('Missing required parameter: entity_name');
|
|
117
156
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
157
|
+
try {
|
|
158
|
+
// First determine if the input looks like a UUID
|
|
159
|
+
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
160
|
+
const isUUID = uuidPattern.test(String(args.entity_name));
|
|
161
|
+
// Try to get all entities first to locate the correct one
|
|
162
|
+
const allEntities = await knowledgeGraphManager.openNodes([]);
|
|
163
|
+
let entity = null;
|
|
164
|
+
if (allEntities?.entities && allEntities.entities.length > 0) {
|
|
165
|
+
// Try different methods to find the entity
|
|
166
|
+
// 1. Direct match by name
|
|
167
|
+
entity = allEntities.entities.find((e) => e.name === args.entity_name);
|
|
168
|
+
// 2. If not found and input is UUID, try matching by ID
|
|
169
|
+
if (!entity && isUUID) {
|
|
170
|
+
entity = allEntities.entities.find((e) => 'id' in e && e.id === args.entity_name);
|
|
171
|
+
}
|
|
122
172
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
173
|
+
// If still not found, try explicit lookup by name
|
|
174
|
+
if (!entity) {
|
|
175
|
+
const openedEntities = await knowledgeGraphManager.openNodes([String(args.entity_name)]);
|
|
176
|
+
if (openedEntities?.entities && openedEntities.entities.length > 0) {
|
|
177
|
+
entity = openedEntities.entities[0];
|
|
178
|
+
}
|
|
128
179
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
180
|
+
// If still not found, check if we can query by ID through the storage provider
|
|
181
|
+
if (!entity &&
|
|
182
|
+
isUUID &&
|
|
183
|
+
knowledgeGraphManager.storageProvider &&
|
|
184
|
+
typeof knowledgeGraphManager.storageProvider.getEntityById === 'function') {
|
|
185
|
+
try {
|
|
186
|
+
entity = await knowledgeGraphManager.storageProvider.getEntityById(args.entity_name);
|
|
136
187
|
}
|
|
137
|
-
|
|
138
|
-
|
|
188
|
+
catch {
|
|
189
|
+
// Ignore lookup errors, we'll throw entity not found below
|
|
139
190
|
}
|
|
140
|
-
// Pass options to getDecayedGraph if any are provided
|
|
141
|
-
const graph = Object.keys(options).length > 0
|
|
142
|
-
? await knowledgeGraphManager.getDecayedGraph(options)
|
|
143
|
-
: await knowledgeGraphManager.getDecayedGraph();
|
|
144
|
-
return { content: [{ type: 'text', text: JSON.stringify(graph, null, 2) }] };
|
|
145
191
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
content: [{ type: 'text', text: `Error retrieving decayed graph: ${errorMessage}` }],
|
|
150
|
-
};
|
|
192
|
+
// Final check
|
|
193
|
+
if (!entity) {
|
|
194
|
+
throw new Error(`Entity not found: ${args.entity_name}`);
|
|
151
195
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (!args.entity_name) {
|
|
156
|
-
throw new Error('Missing required parameter: entity_name');
|
|
196
|
+
// Check if embedding service and job manager are available
|
|
197
|
+
if (!knowledgeGraphManager.embeddingJobManager) {
|
|
198
|
+
throw new Error('EmbeddingJobManager not initialized');
|
|
157
199
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
]);
|
|
179
|
-
if (openedEntities?.entities && openedEntities.entities.length > 0) {
|
|
180
|
-
entity = openedEntities.entities[0];
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
// If still not found, check if we can query by ID through the storage provider
|
|
184
|
-
if (!entity &&
|
|
185
|
-
isUUID &&
|
|
186
|
-
knowledgeGraphManager.storageProvider &&
|
|
187
|
-
typeof knowledgeGraphManager.storageProvider.getEntityById === 'function') {
|
|
188
|
-
try {
|
|
189
|
-
entity = await knowledgeGraphManager.storageProvider.getEntityById(args.entity_name);
|
|
190
|
-
}
|
|
191
|
-
catch {
|
|
192
|
-
// Ignore lookup errors, we'll throw entity not found below
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
// Final check
|
|
196
|
-
if (!entity) {
|
|
197
|
-
throw new Error(`Entity not found: ${args.entity_name}`);
|
|
200
|
+
// Directly get the text for the entity
|
|
201
|
+
const embeddingText = knowledgeGraphManager.embeddingJobManager._prepareEntityText(entity);
|
|
202
|
+
// Generate embedding directly
|
|
203
|
+
const embeddingService = knowledgeGraphManager.embeddingJobManager.embeddingService;
|
|
204
|
+
if (!embeddingService) {
|
|
205
|
+
throw new Error('Embedding service not available');
|
|
206
|
+
}
|
|
207
|
+
const vector = await embeddingService.generateEmbedding(embeddingText);
|
|
208
|
+
// Store embedding directly
|
|
209
|
+
const embedding = {
|
|
210
|
+
vector,
|
|
211
|
+
model: embeddingService.getModelInfo().name,
|
|
212
|
+
lastUpdated: Date.now(),
|
|
213
|
+
};
|
|
214
|
+
// Store the embedding with both name and ID for redundancy
|
|
215
|
+
await knowledgeGraphManager.storageProvider.storeEntityVector(entity.name, embedding);
|
|
216
|
+
const entityId = entity.id;
|
|
217
|
+
if (entityId && typeof entityId === 'string') {
|
|
218
|
+
try {
|
|
219
|
+
await knowledgeGraphManager.storageProvider.storeEntityVector(entityId, embedding);
|
|
198
220
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
throw new Error('EmbeddingJobManager not initialized');
|
|
221
|
+
catch {
|
|
222
|
+
// Ignore ID storage errors if name storage succeeded
|
|
202
223
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
content: [
|
|
227
|
+
{
|
|
228
|
+
type: 'text',
|
|
229
|
+
text: JSON.stringify({
|
|
230
|
+
success: true,
|
|
231
|
+
entity: entity.name,
|
|
232
|
+
entity_id: entity.id,
|
|
233
|
+
vector_length: vector.length,
|
|
234
|
+
model: embeddingService.getModelInfo().name,
|
|
235
|
+
}, null, 2),
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
};
|
|
239
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
return {
|
|
243
|
+
content: [{ type: 'text', text: `Failed to generate embedding: ${error.message}` }],
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
case 'semantic_search': {
|
|
248
|
+
try {
|
|
249
|
+
// Extract hybrid search configuration if provided
|
|
250
|
+
const hybridConfigRaw = args.hybrid_config;
|
|
251
|
+
const hybridConfig = hybridConfigRaw
|
|
252
|
+
? {
|
|
253
|
+
vectorWeight: hybridConfigRaw.vector_weight,
|
|
254
|
+
graphWeight: hybridConfigRaw.graph_weight,
|
|
255
|
+
temporalWeight: hybridConfigRaw.temporal_weight,
|
|
256
|
+
connectionWeight: hybridConfigRaw.connection_weight,
|
|
257
|
+
enableScoreDebug: hybridConfigRaw.enable_score_debug,
|
|
258
|
+
referenceTime: hybridConfigRaw.reference_time,
|
|
259
|
+
temporalHalfLife: hybridConfigRaw.temporal_half_life,
|
|
209
260
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
261
|
+
: undefined;
|
|
262
|
+
// Extract search options from args
|
|
263
|
+
const searchOptions = {
|
|
264
|
+
limit: args.limit || 10,
|
|
265
|
+
minSimilarity: args.min_similarity || 0.6,
|
|
266
|
+
entityTypes: args.entity_types || [],
|
|
267
|
+
hybridSearch: args.hybrid_search === undefined ? true : args.hybrid_search,
|
|
268
|
+
semanticWeight: args.semantic_weight || 0.6,
|
|
269
|
+
semanticSearch: true,
|
|
270
|
+
hybridConfig,
|
|
271
|
+
enableHybridRetrieval: args.enable_hybrid_retrieval !== false,
|
|
272
|
+
domain: args.domain,
|
|
273
|
+
includeNullDomain: args.include_null_domain,
|
|
274
|
+
};
|
|
275
|
+
// Call the search method with semantic search options
|
|
276
|
+
const results = await knowledgeGraphManager.search(String(args.query), searchOptions);
|
|
277
|
+
return { content: [{ type: 'text', text: JSON.stringify(results, null, 2) }] };
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
281
|
+
return {
|
|
282
|
+
content: [{ type: 'text', text: `Error performing semantic search: ${errorMessage}` }],
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
case 'get_entity_embedding': {
|
|
287
|
+
try {
|
|
288
|
+
// Check if entity exists
|
|
289
|
+
const entity = await knowledgeGraphManager.openNodes([String(args.entity_name)]);
|
|
290
|
+
if (!entity.entities || entity.entities.length === 0) {
|
|
291
|
+
return { content: [{ type: 'text', text: `Entity not found: ${args.entity_name}` }] };
|
|
292
|
+
}
|
|
293
|
+
// Access the embedding using appropriate interface
|
|
294
|
+
if (knowledgeGraphManager.storageProvider &&
|
|
295
|
+
typeof knowledgeGraphManager.storageProvider
|
|
296
|
+
.getEntityEmbedding === 'function') {
|
|
297
|
+
const embedding = await knowledgeGraphManager.storageProvider.getEntityEmbedding(String(args.entity_name));
|
|
298
|
+
if (!embedding) {
|
|
299
|
+
return {
|
|
300
|
+
content: [
|
|
301
|
+
{ type: 'text', text: `No embedding found for entity: ${args.entity_name}` },
|
|
302
|
+
],
|
|
303
|
+
};
|
|
227
304
|
}
|
|
228
305
|
return {
|
|
229
306
|
content: [
|
|
230
307
|
{
|
|
231
308
|
type: 'text',
|
|
232
309
|
text: JSON.stringify({
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
310
|
+
entityName: args.entity_name,
|
|
311
|
+
embedding: embedding.vector,
|
|
312
|
+
model: embedding.model || 'unknown',
|
|
313
|
+
dimensions: embedding.vector ? embedding.vector.length : 0,
|
|
314
|
+
lastUpdated: embedding.lastUpdated || Date.now(),
|
|
238
315
|
}, null, 2),
|
|
239
316
|
},
|
|
240
317
|
],
|
|
241
318
|
};
|
|
242
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
243
319
|
}
|
|
244
|
-
|
|
320
|
+
else {
|
|
245
321
|
return {
|
|
246
|
-
content: [
|
|
322
|
+
content: [
|
|
323
|
+
{
|
|
324
|
+
type: 'text',
|
|
325
|
+
text: `Embedding retrieval not supported by this storage provider`,
|
|
326
|
+
},
|
|
327
|
+
],
|
|
247
328
|
};
|
|
248
329
|
}
|
|
249
330
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
? {
|
|
256
|
-
vectorWeight: hybridConfigRaw.vector_weight,
|
|
257
|
-
graphWeight: hybridConfigRaw.graph_weight,
|
|
258
|
-
temporalWeight: hybridConfigRaw.temporal_weight,
|
|
259
|
-
connectionWeight: hybridConfigRaw.connection_weight,
|
|
260
|
-
enableScoreDebug: hybridConfigRaw.enable_score_debug,
|
|
261
|
-
referenceTime: hybridConfigRaw.reference_time,
|
|
262
|
-
temporalHalfLife: hybridConfigRaw.temporal_half_life,
|
|
263
|
-
}
|
|
264
|
-
: undefined;
|
|
265
|
-
// Extract search options from args
|
|
266
|
-
const searchOptions = {
|
|
267
|
-
limit: args.limit || 10,
|
|
268
|
-
minSimilarity: args.min_similarity || 0.6,
|
|
269
|
-
entityTypes: args.entity_types || [],
|
|
270
|
-
hybridSearch: args.hybrid_search === undefined ? true : args.hybrid_search,
|
|
271
|
-
semanticWeight: args.semantic_weight || 0.6,
|
|
272
|
-
semanticSearch: true,
|
|
273
|
-
hybridConfig,
|
|
274
|
-
enableHybridRetrieval: args.enable_hybrid_retrieval !== false,
|
|
275
|
-
domain: args.domain,
|
|
276
|
-
includeNullDomain: args.include_null_domain,
|
|
277
|
-
};
|
|
278
|
-
// Call the search method with semantic search options
|
|
279
|
-
const results = await knowledgeGraphManager.search(String(args.query), searchOptions);
|
|
280
|
-
return { content: [{ type: 'text', text: JSON.stringify(results, null, 2) }] };
|
|
281
|
-
}
|
|
282
|
-
catch (error) {
|
|
283
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
284
|
-
return {
|
|
285
|
-
content: [{ type: 'text', text: `Error performing semantic search: ${errorMessage}` }],
|
|
286
|
-
};
|
|
287
|
-
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
333
|
+
return {
|
|
334
|
+
content: [{ type: 'text', text: `Error retrieving entity embedding: ${errorMessage}` }],
|
|
335
|
+
};
|
|
288
336
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
337
|
+
}
|
|
338
|
+
case 'debug_embedding_config': {
|
|
339
|
+
// Diagnostic tool to check embedding configuration
|
|
340
|
+
try {
|
|
341
|
+
// Check for OpenAI API key
|
|
342
|
+
const hasOpenAIKey = !!process.env.OPENAI_API_KEY;
|
|
343
|
+
const embeddingModel = process.env.OPENAI_EMBEDDING_MODEL || 'text-embedding-3-small';
|
|
344
|
+
// Check if embedding job manager is initialized
|
|
345
|
+
const hasEmbeddingJobManager = !!knowledgeGraphManager.embeddingJobManager;
|
|
346
|
+
// Get storage provider info
|
|
347
|
+
const storageType = process.env.MEMORY_STORAGE_TYPE || 'neo4j';
|
|
348
|
+
const storageProvider = knowledgeGraphManager.storageProvider;
|
|
349
|
+
// Get Neo4j specific configuration
|
|
350
|
+
const neo4jInfo = {
|
|
351
|
+
uri: process.env.NEO4J_URI || 'default',
|
|
352
|
+
username: process.env.NEO4J_USERNAME ? 'configured' : 'not configured',
|
|
353
|
+
database: process.env.NEO4J_DATABASE || 'neo4j',
|
|
354
|
+
vectorIndex: process.env.NEO4J_VECTOR_INDEX || 'entity_embeddings',
|
|
355
|
+
vectorDimensions: process.env.NEO4J_VECTOR_DIMENSIONS || '1536',
|
|
356
|
+
similarityFunction: process.env.NEO4J_SIMILARITY_FUNCTION || 'cosine',
|
|
357
|
+
connectionStatus: 'unknown',
|
|
358
|
+
};
|
|
359
|
+
// Check if Neo4j connection manager is available
|
|
360
|
+
if (storageProvider && typeof storageProvider.getConnectionManager === 'function') {
|
|
361
|
+
try {
|
|
362
|
+
const connectionManager = storageProvider.getConnectionManager();
|
|
363
|
+
if (connectionManager) {
|
|
364
|
+
neo4jInfo.connectionStatus = 'available';
|
|
365
|
+
// Check if vector store is initialized
|
|
366
|
+
neo4jInfo.vectorStoreStatus = storageProvider.vectorStore
|
|
367
|
+
? 'available'
|
|
368
|
+
: 'not initialized';
|
|
307
369
|
}
|
|
308
|
-
return {
|
|
309
|
-
content: [
|
|
310
|
-
{
|
|
311
|
-
type: 'text',
|
|
312
|
-
text: JSON.stringify({
|
|
313
|
-
entityName: args.entity_name,
|
|
314
|
-
embedding: embedding.vector,
|
|
315
|
-
model: embedding.model || 'unknown',
|
|
316
|
-
dimensions: embedding.vector ? embedding.vector.length : 0,
|
|
317
|
-
lastUpdated: embedding.lastUpdated || Date.now(),
|
|
318
|
-
}, null, 2),
|
|
319
|
-
},
|
|
320
|
-
],
|
|
321
|
-
};
|
|
322
370
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
{
|
|
327
|
-
type: 'text',
|
|
328
|
-
text: `Embedding retrieval not supported by this storage provider`,
|
|
329
|
-
},
|
|
330
|
-
],
|
|
331
|
-
};
|
|
371
|
+
catch (error) {
|
|
372
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
373
|
+
neo4jInfo.connectionStatus = `error: ${errorMessage}`;
|
|
332
374
|
}
|
|
333
375
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
case 'debug_embedding_config': {
|
|
342
|
-
// Diagnostic tool to check embedding configuration
|
|
343
|
-
try {
|
|
344
|
-
// Check for OpenAI API key
|
|
345
|
-
const hasOpenAIKey = !!process.env.OPENAI_API_KEY;
|
|
346
|
-
const embeddingModel = process.env.OPENAI_EMBEDDING_MODEL || 'text-embedding-3-small';
|
|
347
|
-
// Check if embedding job manager is initialized
|
|
348
|
-
const hasEmbeddingJobManager = !!knowledgeGraphManager.embeddingJobManager;
|
|
349
|
-
// Get storage provider info
|
|
350
|
-
const storageType = process.env.MEMORY_STORAGE_TYPE || 'neo4j';
|
|
351
|
-
const storageProvider = knowledgeGraphManager.storageProvider;
|
|
352
|
-
// Get Neo4j specific configuration
|
|
353
|
-
const neo4jInfo = {
|
|
354
|
-
uri: process.env.NEO4J_URI || 'default',
|
|
355
|
-
username: process.env.NEO4J_USERNAME ? 'configured' : 'not configured',
|
|
356
|
-
database: process.env.NEO4J_DATABASE || 'neo4j',
|
|
357
|
-
vectorIndex: process.env.NEO4J_VECTOR_INDEX || 'entity_embeddings',
|
|
358
|
-
vectorDimensions: process.env.NEO4J_VECTOR_DIMENSIONS || '1536',
|
|
359
|
-
similarityFunction: process.env.NEO4J_SIMILARITY_FUNCTION || 'cosine',
|
|
360
|
-
connectionStatus: 'unknown',
|
|
361
|
-
};
|
|
362
|
-
// Check if Neo4j connection manager is available
|
|
363
|
-
if (storageProvider && typeof storageProvider.getConnectionManager === 'function') {
|
|
364
|
-
try {
|
|
365
|
-
const connectionManager = storageProvider.getConnectionManager();
|
|
366
|
-
if (connectionManager) {
|
|
367
|
-
neo4jInfo.connectionStatus = 'available';
|
|
368
|
-
// Check if vector store is initialized
|
|
369
|
-
neo4jInfo.vectorStoreStatus = storageProvider.vectorStore
|
|
370
|
-
? 'available'
|
|
371
|
-
: 'not initialized';
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
catch (error) {
|
|
375
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
376
|
-
neo4jInfo.connectionStatus = `error: ${errorMessage}`;
|
|
377
|
-
}
|
|
376
|
+
// Count entities with embeddings via Neo4j vector store
|
|
377
|
+
let entitiesWithEmbeddings = 0;
|
|
378
|
+
if (storageProvider?.countEntitiesWithEmbeddings) {
|
|
379
|
+
try {
|
|
380
|
+
entitiesWithEmbeddings = await storageProvider.countEntitiesWithEmbeddings();
|
|
378
381
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
if (storageProvider?.countEntitiesWithEmbeddings) {
|
|
382
|
-
try {
|
|
383
|
-
entitiesWithEmbeddings = await storageProvider.countEntitiesWithEmbeddings();
|
|
384
|
-
}
|
|
385
|
-
catch (error) {
|
|
386
|
-
logger.error('Error checking embeddings count', error);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
// Get embedding service information
|
|
390
|
-
let embeddingServiceInfo = null;
|
|
391
|
-
if (hasEmbeddingJobManager &&
|
|
392
|
-
knowledgeGraphManager.embeddingJobManager.embeddingService) {
|
|
393
|
-
try {
|
|
394
|
-
embeddingServiceInfo = knowledgeGraphManager.embeddingJobManager.embeddingService.getModelInfo();
|
|
395
|
-
}
|
|
396
|
-
catch (error) {
|
|
397
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
398
|
-
logger.error(`Error getting embedding service info: ${errorMessage}`);
|
|
399
|
-
}
|
|
382
|
+
catch (error) {
|
|
383
|
+
logger.error('Error checking embeddings count', error);
|
|
400
384
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
catch (error) {
|
|
408
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
409
|
-
logger.error(`Error getting embedding provider info: ${errorMessage}`);
|
|
410
|
-
}
|
|
385
|
+
}
|
|
386
|
+
// Get embedding service information
|
|
387
|
+
let embeddingServiceInfo = null;
|
|
388
|
+
if (hasEmbeddingJobManager && knowledgeGraphManager.embeddingJobManager.embeddingService) {
|
|
389
|
+
try {
|
|
390
|
+
embeddingServiceInfo = knowledgeGraphManager.embeddingJobManager.embeddingService.getModelInfo();
|
|
411
391
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
try {
|
|
416
|
-
pendingJobs = knowledgeGraphManager.embeddingJobManager.getPendingJobs().length;
|
|
417
|
-
}
|
|
418
|
-
catch (error) {
|
|
419
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
420
|
-
logger.error(`Error getting pending jobs: ${errorMessage}`);
|
|
421
|
-
}
|
|
392
|
+
catch (error) {
|
|
393
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
394
|
+
logger.error(`Error getting embedding service info: ${errorMessage}`);
|
|
422
395
|
}
|
|
423
|
-
// Return diagnostic information with proper formatting
|
|
424
|
-
const diagnosticInfo = {
|
|
425
|
-
storage_type: storageType,
|
|
426
|
-
openai_api_key_present: hasOpenAIKey,
|
|
427
|
-
embedding_model: embeddingModel,
|
|
428
|
-
embedding_job_manager_initialized: hasEmbeddingJobManager,
|
|
429
|
-
embedding_service_initialized: !!embeddingProviderInfo,
|
|
430
|
-
embedding_service_info: embeddingServiceInfo,
|
|
431
|
-
embedding_provider_info: embeddingProviderInfo,
|
|
432
|
-
neo4j_config: neo4jInfo,
|
|
433
|
-
entities_with_embeddings: entitiesWithEmbeddings,
|
|
434
|
-
pending_embedding_jobs: pendingJobs,
|
|
435
|
-
environment_variables: {
|
|
436
|
-
DEBUG: process.env.DEBUG === 'true',
|
|
437
|
-
NODE_ENV: process.env.NODE_ENV,
|
|
438
|
-
MEMORY_STORAGE_TYPE: process.env.MEMORY_STORAGE_TYPE || 'neo4j',
|
|
439
|
-
},
|
|
440
|
-
};
|
|
441
|
-
return {
|
|
442
|
-
content: [
|
|
443
|
-
{
|
|
444
|
-
type: 'text',
|
|
445
|
-
text: JSON.stringify(diagnosticInfo, null, 2),
|
|
446
|
-
},
|
|
447
|
-
],
|
|
448
|
-
};
|
|
449
396
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
stack: errorStack,
|
|
461
|
-
}, null, 2),
|
|
462
|
-
},
|
|
463
|
-
],
|
|
464
|
-
};
|
|
397
|
+
// Get embedding service provider info if available
|
|
398
|
+
let embeddingProviderInfo = null;
|
|
399
|
+
if (storageProvider?.embeddingService) {
|
|
400
|
+
try {
|
|
401
|
+
embeddingProviderInfo = storageProvider.embeddingService.getProviderInfo();
|
|
402
|
+
}
|
|
403
|
+
catch (error) {
|
|
404
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
405
|
+
logger.error(`Error getting embedding provider info: ${errorMessage}`);
|
|
406
|
+
}
|
|
465
407
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
? {
|
|
472
|
-
content: [
|
|
473
|
-
{
|
|
474
|
-
type: 'text',
|
|
475
|
-
text: JSON.stringify(await knowledgeGraphManager.storageProvider.diagnoseVectorSearch()),
|
|
476
|
-
},
|
|
477
|
-
],
|
|
408
|
+
// Check pending embedding jobs if available
|
|
409
|
+
let pendingJobs = 0;
|
|
410
|
+
if (hasEmbeddingJobManager && knowledgeGraphManager.embeddingJobManager.getPendingJobs) {
|
|
411
|
+
try {
|
|
412
|
+
pendingJobs = knowledgeGraphManager.embeddingJobManager.getPendingJobs().length;
|
|
478
413
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
414
|
+
catch (error) {
|
|
415
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
416
|
+
logger.error(`Error getting pending jobs: ${errorMessage}`);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
// Return diagnostic information with proper formatting
|
|
420
|
+
const diagnosticInfo = {
|
|
421
|
+
storage_type: storageType,
|
|
422
|
+
openai_api_key_present: hasOpenAIKey,
|
|
423
|
+
embedding_model: embeddingModel,
|
|
424
|
+
embedding_job_manager_initialized: hasEmbeddingJobManager,
|
|
425
|
+
embedding_service_initialized: !!embeddingProviderInfo,
|
|
426
|
+
embedding_service_info: embeddingServiceInfo,
|
|
427
|
+
embedding_provider_info: embeddingProviderInfo,
|
|
428
|
+
neo4j_config: neo4jInfo,
|
|
429
|
+
entities_with_embeddings: entitiesWithEmbeddings,
|
|
430
|
+
pending_embedding_jobs: pendingJobs,
|
|
431
|
+
environment_variables: {
|
|
432
|
+
DEBUG: process.env.DEBUG === 'true',
|
|
433
|
+
NODE_ENV: process.env.NODE_ENV,
|
|
434
|
+
MEMORY_STORAGE_TYPE: process.env.MEMORY_STORAGE_TYPE || 'neo4j',
|
|
435
|
+
},
|
|
436
|
+
};
|
|
437
|
+
return {
|
|
438
|
+
content: [
|
|
439
|
+
{
|
|
440
|
+
type: 'text',
|
|
441
|
+
text: JSON.stringify(diagnosticInfo, null, 2),
|
|
442
|
+
},
|
|
443
|
+
],
|
|
444
|
+
};
|
|
504
445
|
}
|
|
505
|
-
|
|
506
|
-
|
|
446
|
+
catch (error) {
|
|
447
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
448
|
+
const errorStack = error instanceof Error ? error.stack : undefined;
|
|
449
|
+
logger.error(`Error in debug_embedding_config: ${errorMessage}`);
|
|
450
|
+
return {
|
|
451
|
+
content: [
|
|
452
|
+
{
|
|
453
|
+
type: 'text',
|
|
454
|
+
text: JSON.stringify({
|
|
455
|
+
error: errorMessage,
|
|
456
|
+
stack: errorStack,
|
|
457
|
+
}, null, 2),
|
|
458
|
+
},
|
|
459
|
+
],
|
|
460
|
+
};
|
|
507
461
|
}
|
|
508
462
|
}
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
463
|
+
case 'diagnose_vector_search': {
|
|
464
|
+
return knowledgeGraphManager.storageProvider &&
|
|
465
|
+
typeof knowledgeGraphManager.storageProvider
|
|
466
|
+
.diagnoseVectorSearch === 'function'
|
|
467
|
+
? {
|
|
468
|
+
content: [
|
|
469
|
+
{
|
|
470
|
+
type: 'text',
|
|
471
|
+
text: JSON.stringify(await knowledgeGraphManager.storageProvider.diagnoseVectorSearch()),
|
|
472
|
+
},
|
|
473
|
+
],
|
|
474
|
+
}
|
|
475
|
+
: {
|
|
476
|
+
content: [
|
|
477
|
+
{
|
|
478
|
+
type: 'text',
|
|
479
|
+
text: JSON.stringify({
|
|
480
|
+
error: 'Diagnostic method not available',
|
|
481
|
+
storageType: knowledgeGraphManager.storageProvider
|
|
482
|
+
? knowledgeGraphManager.storageProvider.constructor.name
|
|
483
|
+
: 'unknown',
|
|
484
|
+
}, null, 2),
|
|
485
|
+
},
|
|
486
|
+
],
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
case 'create_entities_batch': {
|
|
490
|
+
return await toolHandlers.handleCreateEntitiesBatch(args, knowledgeGraphManager);
|
|
491
|
+
}
|
|
492
|
+
case 'create_relations_batch': {
|
|
493
|
+
return await toolHandlers.handleCreateRelationsBatch(args, knowledgeGraphManager);
|
|
494
|
+
}
|
|
495
|
+
case 'add_observations_batch': {
|
|
496
|
+
return await toolHandlers.handleAddObservationsBatch(args, knowledgeGraphManager);
|
|
497
|
+
}
|
|
498
|
+
case 'update_entities_batch': {
|
|
499
|
+
return await toolHandlers.handleUpdateEntitiesBatch(args, knowledgeGraphManager);
|
|
500
|
+
}
|
|
501
|
+
default: {
|
|
502
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
503
|
+
}
|
|
512
504
|
}
|
|
513
505
|
}
|
|
514
506
|
//# sourceMappingURL=callToolHandler.js.map
|