@hashgraphonline/conversational-agent 0.1.209 → 0.1.211
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/bin/conversational-agent-cli.js +30 -0
- package/cli/readme.md +181 -0
- package/dist/cjs/base-agent.d.ts +3 -1
- package/dist/cjs/conversational-agent.d.ts +14 -22
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +5 -3
- package/dist/cjs/langchain-agent.d.ts +6 -3
- package/dist/cjs/memory/SmartMemoryManager.d.ts +7 -1
- package/dist/cjs/memory/TokenCounter.d.ts +1 -1
- package/dist/cjs/plugins/hbar/AirdropToolWrapper.d.ts +43 -0
- package/dist/{types/plugins/hbar-transfer/HbarTransferPlugin.d.ts → cjs/plugins/hbar/HbarPlugin.d.ts} +2 -1
- package/dist/{types/plugins/hbar-transfer → cjs/plugins/hbar}/TransferHbarTool.d.ts +1 -1
- package/dist/cjs/plugins/hbar/index.d.ts +3 -0
- package/dist/cjs/plugins/index.d.ts +2 -1
- package/dist/cjs/services/EntityResolver.d.ts +26 -0
- package/dist/cjs/tools/EntityResolverTool.d.ts +104 -0
- package/dist/cjs/types/inscription.d.ts +37 -0
- package/dist/esm/index.js +8 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index12.js +1 -4
- package/dist/esm/index12.js.map +1 -1
- package/dist/esm/index13.js +0 -1
- package/dist/esm/index13.js.map +1 -1
- package/dist/esm/index14.js +2 -7
- package/dist/esm/index14.js.map +1 -1
- package/dist/esm/index15.js +31 -69
- package/dist/esm/index15.js.map +1 -1
- package/dist/esm/index16.js +126 -39
- package/dist/esm/index16.js.map +1 -1
- package/dist/esm/index17.js +148 -13
- package/dist/esm/index17.js.map +1 -1
- package/dist/esm/index18.js +44 -146
- package/dist/esm/index18.js.map +1 -1
- package/dist/esm/index19.js +100 -6
- package/dist/esm/index19.js.map +1 -1
- package/dist/esm/index20.js +20 -174
- package/dist/esm/index20.js.map +1 -1
- package/dist/esm/index21.js +7 -151
- package/dist/esm/index21.js.map +1 -1
- package/dist/esm/index22.js +154 -45
- package/dist/esm/index22.js.map +1 -1
- package/dist/esm/index23.js +149 -24
- package/dist/esm/index23.js.map +1 -1
- package/dist/esm/index24.js +56 -83
- package/dist/esm/index24.js.map +1 -1
- package/dist/esm/index25.js +24 -236
- package/dist/esm/index25.js.map +1 -1
- package/dist/esm/index26.js +95 -0
- package/dist/esm/index26.js.map +1 -0
- package/dist/esm/index27.js +242 -0
- package/dist/esm/index27.js.map +1 -0
- package/dist/esm/index5.js +32 -19
- package/dist/esm/index5.js.map +1 -1
- package/dist/esm/index6.js +156 -195
- package/dist/esm/index6.js.map +1 -1
- package/dist/esm/index7.js +2 -2
- package/dist/esm/index7.js.map +1 -1
- package/dist/esm/index8.js +80 -48
- package/dist/esm/index8.js.map +1 -1
- package/dist/types/base-agent.d.ts +3 -1
- package/dist/types/conversational-agent.d.ts +14 -22
- package/dist/types/index.d.ts +5 -3
- package/dist/types/langchain-agent.d.ts +6 -3
- package/dist/types/memory/SmartMemoryManager.d.ts +7 -1
- package/dist/types/memory/TokenCounter.d.ts +1 -1
- package/dist/types/plugins/hbar/AirdropToolWrapper.d.ts +43 -0
- package/dist/{cjs/plugins/hbar-transfer/HbarTransferPlugin.d.ts → types/plugins/hbar/HbarPlugin.d.ts} +2 -1
- package/dist/{cjs/plugins/hbar-transfer → types/plugins/hbar}/TransferHbarTool.d.ts +1 -1
- package/dist/types/plugins/hbar/index.d.ts +3 -0
- package/dist/types/plugins/index.d.ts +2 -1
- package/dist/types/services/EntityResolver.d.ts +26 -0
- package/dist/types/tools/EntityResolverTool.d.ts +104 -0
- package/dist/types/types/inscription.d.ts +37 -0
- package/package.json +13 -4
- package/src/base-agent.ts +14 -9
- package/src/config/system-message.ts +11 -2
- package/src/context/ReferenceContextManager.ts +1 -1
- package/src/conversational-agent.ts +221 -254
- package/src/index.ts +17 -3
- package/src/langchain-agent.ts +130 -78
- package/src/mcp/ContentProcessor.ts +0 -2
- package/src/mcp/adapters/langchain.ts +0 -1
- package/src/memory/ContentStorage.ts +0 -5
- package/src/memory/MemoryWindow.ts +0 -1
- package/src/memory/ReferenceIdGenerator.ts +4 -4
- package/src/memory/SmartMemoryManager.ts +53 -92
- package/src/memory/TokenCounter.ts +4 -7
- package/src/plugins/hbar/AirdropToolWrapper.ts +157 -0
- package/src/plugins/hbar/HbarPlugin.ts +86 -0
- package/src/plugins/{hbar-transfer → hbar}/TransferHbarTool.ts +3 -3
- package/src/plugins/hbar/index.ts +3 -0
- package/src/plugins/index.ts +2 -1
- package/src/services/EntityResolver.ts +135 -0
- package/src/tools/EntityResolverTool.ts +170 -0
- package/src/types/inscription.ts +40 -0
- package/dist/cjs/plugins/hbar-transfer/index.d.ts +0 -1
- package/dist/types/plugins/hbar-transfer/index.d.ts +0 -1
- package/src/plugins/hbar-transfer/HbarTransferPlugin.ts +0 -66
- package/src/plugins/hbar-transfer/index.ts +0 -1
- /package/dist/cjs/plugins/{hbar-transfer → hbar}/AccountBuilder.d.ts +0 -0
- /package/dist/cjs/plugins/{hbar-transfer → hbar}/types.d.ts +0 -0
- /package/dist/types/plugins/{hbar-transfer → hbar}/AccountBuilder.d.ts +0 -0
- /package/dist/types/plugins/{hbar-transfer → hbar}/types.d.ts +0 -0
- /package/src/plugins/{hbar-transfer → hbar}/AccountBuilder.ts +0 -0
- /package/src/plugins/{hbar-transfer → hbar}/types.ts +0 -0
package/dist/esm/index6.js
CHANGED
|
@@ -3,43 +3,53 @@ import { Logger, HederaMirrorNode } from "@hashgraphonline/standards-sdk";
|
|
|
3
3
|
import { createAgent } from "./index9.js";
|
|
4
4
|
import { LangChainProvider } from "./index10.js";
|
|
5
5
|
import { ChatOpenAI } from "@langchain/openai";
|
|
6
|
+
import { ChatAnthropic } from "@langchain/anthropic";
|
|
6
7
|
import { HumanMessage, AIMessage } from "@langchain/core/messages";
|
|
7
8
|
import { HCS10Plugin } from "./index2.js";
|
|
8
9
|
import { HCS2Plugin } from "./index3.js";
|
|
9
10
|
import { InscribePlugin } from "./index4.js";
|
|
10
|
-
import {
|
|
11
|
+
import { HbarPlugin } from "./index5.js";
|
|
11
12
|
import { OpenConvaiState } from "@hashgraphonline/standards-agent-kit";
|
|
12
13
|
import { PrivateKey } from "@hashgraph/sdk";
|
|
13
|
-
import { getSystemMessage } from "./
|
|
14
|
-
import { ContentStoreManager } from "./
|
|
14
|
+
import { getSystemMessage } from "./index20.js";
|
|
15
|
+
import { ContentStoreManager } from "./index17.js";
|
|
15
16
|
import "./index12.js";
|
|
16
17
|
import "./index13.js";
|
|
17
18
|
import "./index14.js";
|
|
18
19
|
import { SmartMemoryManager } from "./index15.js";
|
|
20
|
+
import { createEntityTools } from "./index16.js";
|
|
19
21
|
const DEFAULT_MODEL_NAME = "gpt-4o";
|
|
20
22
|
const DEFAULT_TEMPERATURE = 0.1;
|
|
21
23
|
const DEFAULT_NETWORK = "testnet";
|
|
22
24
|
const DEFAULT_OPERATIONAL_MODE = "autonomous";
|
|
23
25
|
class ConversationalAgent {
|
|
24
26
|
constructor(options) {
|
|
25
|
-
this.mcpConnectionStatus = /* @__PURE__ */ new Map();
|
|
26
27
|
this.options = options;
|
|
27
28
|
this.stateManager = options.stateManager || new OpenConvaiState();
|
|
28
29
|
this.hcs10Plugin = new HCS10Plugin();
|
|
29
30
|
this.hcs2Plugin = new HCS2Plugin();
|
|
30
31
|
this.inscribePlugin = new InscribePlugin();
|
|
31
|
-
this.
|
|
32
|
+
this.hbarPlugin = new HbarPlugin();
|
|
32
33
|
this.logger = new Logger({
|
|
33
34
|
module: "ConversationalAgent",
|
|
34
35
|
silent: options.disableLogging || false
|
|
35
36
|
});
|
|
36
37
|
if (this.options.entityMemoryEnabled !== false) {
|
|
37
|
-
|
|
38
|
+
if (!options.openAIApiKey) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
"OpenAI API key is required when entity memory is enabled"
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
this.memoryManager = new SmartMemoryManager(
|
|
44
|
+
this.options.entityMemoryConfig
|
|
45
|
+
);
|
|
38
46
|
this.logger.info("Entity memory initialized");
|
|
47
|
+
this.entityTools = createEntityTools(options.openAIApiKey, "gpt-4o-mini");
|
|
48
|
+
this.logger.info("LLM-based entity resolver tools initialized");
|
|
39
49
|
}
|
|
40
50
|
}
|
|
41
51
|
/**
|
|
42
|
-
* Initialize the conversational agent with Hedera
|
|
52
|
+
* Initialize the conversational agent with Hedera Hashgraph connection and AI configuration
|
|
43
53
|
* @throws {Error} If account ID or private key is missing
|
|
44
54
|
* @throws {Error} If initialization fails
|
|
45
55
|
*/
|
|
@@ -49,7 +59,8 @@ class ConversationalAgent {
|
|
|
49
59
|
privateKey,
|
|
50
60
|
network = DEFAULT_NETWORK,
|
|
51
61
|
openAIApiKey,
|
|
52
|
-
openAIModelName = DEFAULT_MODEL_NAME
|
|
62
|
+
openAIModelName = DEFAULT_MODEL_NAME,
|
|
63
|
+
llmProvider = "openai"
|
|
53
64
|
} = this.options;
|
|
54
65
|
this.validateOptions(accountId, privateKey);
|
|
55
66
|
try {
|
|
@@ -63,21 +74,53 @@ class ConversationalAgent {
|
|
|
63
74
|
privateKeyInstance,
|
|
64
75
|
network
|
|
65
76
|
);
|
|
77
|
+
let llm;
|
|
78
|
+
if (llmProvider === "anthropic") {
|
|
79
|
+
llm = new ChatAnthropic({
|
|
80
|
+
apiKey: openAIApiKey,
|
|
81
|
+
modelName: openAIModelName || "claude-3-5-sonnet-20241022",
|
|
82
|
+
temperature: DEFAULT_TEMPERATURE
|
|
83
|
+
});
|
|
84
|
+
} else {
|
|
85
|
+
const modelName = openAIModelName || "gpt-4o-mini";
|
|
86
|
+
const isGPT5Model = modelName.toLowerCase().includes("gpt-5") || modelName.toLowerCase().includes("gpt5");
|
|
87
|
+
llm = new ChatOpenAI({
|
|
88
|
+
apiKey: openAIApiKey,
|
|
89
|
+
modelName: openAIModelName,
|
|
90
|
+
...isGPT5Model ? { temperature: 1 } : { temperature: DEFAULT_TEMPERATURE }
|
|
91
|
+
});
|
|
92
|
+
}
|
|
66
93
|
const allPlugins = this.preparePlugins();
|
|
67
|
-
const llm = new ChatOpenAI({
|
|
68
|
-
apiKey: openAIApiKey,
|
|
69
|
-
modelName: openAIModelName,
|
|
70
|
-
temperature: DEFAULT_TEMPERATURE
|
|
71
|
-
});
|
|
72
94
|
const agentConfig = this.createAgentConfig(serverSigner, llm, allPlugins);
|
|
73
95
|
this.agent = createAgent(agentConfig);
|
|
74
96
|
this.configureHCS10Plugin(allPlugins);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
97
|
+
this.contentStoreManager = new ContentStoreManager();
|
|
98
|
+
await this.contentStoreManager.initialize();
|
|
99
|
+
this.logger.info(
|
|
100
|
+
"ContentStoreManager initialized for content reference support"
|
|
101
|
+
);
|
|
80
102
|
await this.agent.boot();
|
|
103
|
+
if (this.agent) {
|
|
104
|
+
const cfg = agentConfig;
|
|
105
|
+
cfg.filtering = cfg.filtering || {};
|
|
106
|
+
const originalPredicate = cfg.filtering.toolPredicate;
|
|
107
|
+
const userPredicate = this.options.toolFilter;
|
|
108
|
+
cfg.filtering.toolPredicate = (tool) => {
|
|
109
|
+
if (tool && tool.name === "hedera-account-transfer-hbar") {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
if (tool && tool.name === "hedera-hts-airdrop-token") {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
if (originalPredicate && !originalPredicate(tool)) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
if (userPredicate && !userPredicate(tool)) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
return true;
|
|
122
|
+
};
|
|
123
|
+
}
|
|
81
124
|
if (this.options.mcpServers && this.options.mcpServers.length > 0) {
|
|
82
125
|
this.connectMCP();
|
|
83
126
|
}
|
|
@@ -155,7 +198,7 @@ class ConversationalAgent {
|
|
|
155
198
|
}
|
|
156
199
|
/**
|
|
157
200
|
* Validates initialization options and throws if required fields are missing.
|
|
158
|
-
*
|
|
201
|
+
*
|
|
159
202
|
* @param accountId - The Hedera account ID
|
|
160
203
|
* @param privateKey - The private key for the account
|
|
161
204
|
* @throws {Error} If required fields are missing
|
|
@@ -167,7 +210,7 @@ class ConversationalAgent {
|
|
|
167
210
|
}
|
|
168
211
|
/**
|
|
169
212
|
* Prepares the list of plugins to use based on configuration.
|
|
170
|
-
*
|
|
213
|
+
*
|
|
171
214
|
* @returns Array of plugins to initialize with the agent
|
|
172
215
|
*/
|
|
173
216
|
preparePlugins() {
|
|
@@ -176,7 +219,7 @@ class ConversationalAgent {
|
|
|
176
219
|
this.hcs10Plugin,
|
|
177
220
|
this.hcs2Plugin,
|
|
178
221
|
this.inscribePlugin,
|
|
179
|
-
this.
|
|
222
|
+
this.hbarPlugin
|
|
180
223
|
];
|
|
181
224
|
const corePlugins = getAllHederaCorePlugins();
|
|
182
225
|
if (enabledPlugins) {
|
|
@@ -190,7 +233,7 @@ class ConversationalAgent {
|
|
|
190
233
|
}
|
|
191
234
|
/**
|
|
192
235
|
* Creates the agent configuration object.
|
|
193
|
-
*
|
|
236
|
+
*
|
|
194
237
|
* @param serverSigner - The server signer instance
|
|
195
238
|
* @param llm - The language model instance
|
|
196
239
|
* @param allPlugins - Array of plugins to use
|
|
@@ -235,7 +278,9 @@ class ConversationalAgent {
|
|
|
235
278
|
},
|
|
236
279
|
messaging: {
|
|
237
280
|
systemPreamble: customSystemMessagePreamble || getSystemMessage(accountId),
|
|
238
|
-
...customSystemMessagePostamble && {
|
|
281
|
+
...customSystemMessagePostamble && {
|
|
282
|
+
systemPostamble: customSystemMessagePostamble
|
|
283
|
+
},
|
|
239
284
|
conciseMode: true
|
|
240
285
|
},
|
|
241
286
|
extensions: {
|
|
@@ -258,7 +303,7 @@ class ConversationalAgent {
|
|
|
258
303
|
}
|
|
259
304
|
/**
|
|
260
305
|
* Configures the HCS-10 plugin with the state manager.
|
|
261
|
-
*
|
|
306
|
+
*
|
|
262
307
|
* @param allPlugins - Array of all plugins
|
|
263
308
|
*/
|
|
264
309
|
configureHCS10Plugin(allPlugins) {
|
|
@@ -351,7 +396,7 @@ class ConversationalAgent {
|
|
|
351
396
|
* Detect the private key type by querying the account info from mirror node
|
|
352
397
|
* @param {string} accountId - The Hedera account ID
|
|
353
398
|
* @param {string} privateKey - The private key string
|
|
354
|
-
* @param {NetworkType} network - The Hedera
|
|
399
|
+
* @param {NetworkType} network - The Hedera Hashgraph
|
|
355
400
|
* @returns {Promise<PrivateKey>} The appropriate PrivateKey instance
|
|
356
401
|
*/
|
|
357
402
|
async detectPrivateKeyType(accountId, privateKey, network) {
|
|
@@ -365,144 +410,92 @@ class ConversationalAgent {
|
|
|
365
410
|
}
|
|
366
411
|
}
|
|
367
412
|
/**
|
|
368
|
-
* Resolve entity references
|
|
413
|
+
* Resolve entity references using LLM-based resolver
|
|
369
414
|
* @param content - Message content to resolve
|
|
370
415
|
* @returns Resolved message content with entity IDs replaced
|
|
371
416
|
*/
|
|
372
417
|
async resolveEntitiesInMessage(content) {
|
|
373
|
-
if (!this.memoryManager) {
|
|
418
|
+
if (!this.memoryManager || !this.entityTools) {
|
|
374
419
|
return content;
|
|
375
420
|
}
|
|
376
421
|
try {
|
|
377
|
-
|
|
378
|
-
if (
|
|
379
|
-
this.logger.
|
|
380
|
-
return content
|
|
381
|
-
}
|
|
382
|
-
if (content.length > 5e3) {
|
|
383
|
-
this.logger.warn("Content too long for entity resolution, truncating");
|
|
384
|
-
content = content.substring(0, 5e3);
|
|
385
|
-
}
|
|
386
|
-
let resolvedContent = content;
|
|
387
|
-
const patterns = [
|
|
388
|
-
/\b(my|the|our)\s+(token|account|topic|schedule)\b/gi,
|
|
389
|
-
/'([^']+)'/g,
|
|
390
|
-
/"([^"]+)"/g,
|
|
391
|
-
/\b([A-Z][A-Za-z0-9_-]{2,})\b/g
|
|
392
|
-
];
|
|
393
|
-
for (const pattern of patterns) {
|
|
394
|
-
try {
|
|
395
|
-
let match;
|
|
396
|
-
const matches = [];
|
|
397
|
-
while ((match = pattern.exec(resolvedContent)) !== null) {
|
|
398
|
-
matches.push(match);
|
|
399
|
-
if (!pattern.global) break;
|
|
400
|
-
}
|
|
401
|
-
for (const match2 of matches) {
|
|
402
|
-
try {
|
|
403
|
-
const originalRef = match2[0];
|
|
404
|
-
const entityName = match2[1] || match2[0];
|
|
405
|
-
if (entityName.length > 50) {
|
|
406
|
-
this.logger.debug(`Skipping overly long entity name: ${entityName.substring(0, 20)}...`);
|
|
407
|
-
continue;
|
|
408
|
-
}
|
|
409
|
-
const commonWords = ["the", "my", "our", "this", "that", "it", "is", "are", "was", "will"];
|
|
410
|
-
if (commonWords.includes(entityName.toLowerCase())) {
|
|
411
|
-
continue;
|
|
412
|
-
}
|
|
413
|
-
let entityAssociations = [];
|
|
414
|
-
if (match2[1] && ["token", "account", "topic", "schedule"].includes(match2[1].toLowerCase())) {
|
|
415
|
-
const entityType = match2[1].toLowerCase();
|
|
416
|
-
entityAssociations = this.memoryManager.resolveEntityReference(
|
|
417
|
-
entityName,
|
|
418
|
-
{ entityType, limit: 1, fuzzyMatch: true }
|
|
419
|
-
);
|
|
420
|
-
} else {
|
|
421
|
-
entityAssociations = this.memoryManager.resolveEntityReference(
|
|
422
|
-
entityName,
|
|
423
|
-
{ limit: 1, fuzzyMatch: false }
|
|
424
|
-
);
|
|
425
|
-
}
|
|
426
|
-
if (entityAssociations.length > 0) {
|
|
427
|
-
const entity = entityAssociations[0];
|
|
428
|
-
if (entity.entityId && entity.entityId.trim().length > 0) {
|
|
429
|
-
if (entityAssociations.length > 1) {
|
|
430
|
-
this.logger.info(`Multiple entities found for "${originalRef}", using most recent: ${entity.entityName}`);
|
|
431
|
-
}
|
|
432
|
-
resolvedContent = resolvedContent.replace(originalRef, entity.entityId);
|
|
433
|
-
this.logger.info(`Resolved entity reference: "${originalRef}" -> ${entity.entityId}`);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
} catch (matchError) {
|
|
437
|
-
this.logger.debug("Error processing entity match:", matchError);
|
|
438
|
-
continue;
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
} catch (patternError) {
|
|
442
|
-
this.logger.debug("Error processing pattern:", patternError);
|
|
443
|
-
continue;
|
|
444
|
-
}
|
|
422
|
+
const entities = this.memoryManager.getEntityAssociations();
|
|
423
|
+
if (entities.length === 0) {
|
|
424
|
+
this.logger.info("No entities in memory, skipping resolution");
|
|
425
|
+
return content;
|
|
445
426
|
}
|
|
427
|
+
this.logger.info(
|
|
428
|
+
`Starting LLM-based entity resolution for: "${content.substring(
|
|
429
|
+
0,
|
|
430
|
+
100
|
|
431
|
+
)}..."`
|
|
432
|
+
);
|
|
433
|
+
const resolvedContent = await this.entityTools.resolveEntities.call({
|
|
434
|
+
message: content,
|
|
435
|
+
entities: entities.map((e) => ({
|
|
436
|
+
entityId: e.entityId,
|
|
437
|
+
entityName: e.entityName,
|
|
438
|
+
entityType: e.entityType
|
|
439
|
+
}))
|
|
440
|
+
});
|
|
446
441
|
if (resolvedContent !== content) {
|
|
447
|
-
this.logger.info(
|
|
448
|
-
|
|
449
|
-
|
|
442
|
+
this.logger.info(
|
|
443
|
+
`Entity resolution completed. Original: "${content}" -> Resolved: "${resolvedContent}"`
|
|
444
|
+
);
|
|
450
445
|
}
|
|
451
446
|
return resolvedContent;
|
|
452
447
|
} catch (error) {
|
|
453
|
-
this.logger.
|
|
454
|
-
|
|
448
|
+
this.logger.error("Entity resolution failed:", error);
|
|
449
|
+
throw error;
|
|
455
450
|
}
|
|
456
451
|
}
|
|
457
452
|
/**
|
|
458
|
-
* Extract and store
|
|
453
|
+
* Extract and store entities from agent responses
|
|
459
454
|
* @param response - Agent response containing potential entity information
|
|
460
455
|
* @param originalMessage - Original user message for context
|
|
461
456
|
*/
|
|
462
457
|
async extractAndStoreEntities(response, originalMessage) {
|
|
463
|
-
if (!this.memoryManager) {
|
|
458
|
+
if (!this.memoryManager || !this.entityTools) {
|
|
464
459
|
return;
|
|
465
460
|
}
|
|
466
461
|
try {
|
|
467
|
-
this.logger.info("Starting entity extraction
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
const
|
|
480
|
-
let entityName = `${entityType}-${entityId}`;
|
|
481
|
-
const namePatterns = [
|
|
482
|
-
new RegExp(`(?:called|named)\\s+([\\w\\d_-]+)`, "i"),
|
|
483
|
-
new RegExp(`(?:token|account|topic|schedule)\\s+([\\w\\d_-]+)`, "i"),
|
|
484
|
-
new RegExp(`([\\w\\d_-]+)\\s+${entityType}`, "i")
|
|
485
|
-
];
|
|
486
|
-
for (const namePattern of namePatterns) {
|
|
487
|
-
const nameMatch = originalMessage.match(namePattern);
|
|
488
|
-
if (nameMatch && nameMatch[1]) {
|
|
489
|
-
entityName = nameMatch[1].trim();
|
|
490
|
-
break;
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
this.logger.info(`Extracting entity: ${entityName} (${entityType}) -> ${entityId}`);
|
|
462
|
+
this.logger.info("Starting LLM-based entity extraction");
|
|
463
|
+
const responseText = this.extractResponseText(response);
|
|
464
|
+
const entitiesJson = await this.entityTools.extractEntities.call({
|
|
465
|
+
response: responseText,
|
|
466
|
+
userMessage: originalMessage
|
|
467
|
+
});
|
|
468
|
+
try {
|
|
469
|
+
const entities = JSON.parse(entitiesJson);
|
|
470
|
+
for (const entity of entities) {
|
|
471
|
+
this.logger.info(
|
|
472
|
+
`Storing entity: ${entity.name} (${entity.type}) -> ${entity.id}`
|
|
473
|
+
);
|
|
474
|
+
const transactionId = this.extractTransactionId(response);
|
|
494
475
|
this.memoryManager.storeEntityAssociation(
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
476
|
+
entity.id,
|
|
477
|
+
entity.name,
|
|
478
|
+
entity.type,
|
|
479
|
+
transactionId
|
|
499
480
|
);
|
|
500
|
-
this.logger.info(`Stored entity association: ${entityName} (${entityId})`);
|
|
501
481
|
}
|
|
482
|
+
if (entities.length > 0) {
|
|
483
|
+
this.logger.info(
|
|
484
|
+
`Stored ${entities.length} entities via LLM extraction`
|
|
485
|
+
);
|
|
486
|
+
} else {
|
|
487
|
+
this.logger.info("No entities found in response via LLM extraction");
|
|
488
|
+
}
|
|
489
|
+
} catch (parseError) {
|
|
490
|
+
this.logger.error(
|
|
491
|
+
"Failed to parse extracted entities JSON:",
|
|
492
|
+
parseError
|
|
493
|
+
);
|
|
494
|
+
throw parseError;
|
|
502
495
|
}
|
|
503
|
-
this.logger.info("Entity extraction completed");
|
|
504
496
|
} catch (error) {
|
|
505
|
-
this.logger.
|
|
497
|
+
this.logger.error("Entity extraction failed:", error);
|
|
498
|
+
throw error;
|
|
506
499
|
}
|
|
507
500
|
}
|
|
508
501
|
/**
|
|
@@ -512,11 +505,13 @@ class ConversationalAgent {
|
|
|
512
505
|
*/
|
|
513
506
|
extractTransactionId(response) {
|
|
514
507
|
try {
|
|
515
|
-
if (typeof response === "object" && response
|
|
508
|
+
if (typeof response === "object" && response && "transactionId" in response) {
|
|
516
509
|
return response.transactionId;
|
|
517
510
|
}
|
|
518
511
|
if (typeof response === "string") {
|
|
519
|
-
const match = response.match(
|
|
512
|
+
const match = response.match(
|
|
513
|
+
/transaction[\s\w]*ID[\s:"]*([0-9a-fA-F@\.\-]+)/i
|
|
514
|
+
);
|
|
520
515
|
return match ? match[1] : void 0;
|
|
521
516
|
}
|
|
522
517
|
return void 0;
|
|
@@ -532,68 +527,21 @@ class ConversationalAgent {
|
|
|
532
527
|
if (!this.agent || !this.options.mcpServers) {
|
|
533
528
|
return;
|
|
534
529
|
}
|
|
535
|
-
this.
|
|
536
|
-
this.
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
tools: []
|
|
540
|
-
});
|
|
530
|
+
this.agent.connectMCPServers().catch((e) => {
|
|
531
|
+
this.logger.error("Failed to connect MCP servers:", e);
|
|
532
|
+
}).then(() => {
|
|
533
|
+
this.logger.info("MCP servers connected successfully");
|
|
541
534
|
});
|
|
542
|
-
if (typeof this.agent.connectMCPServers === "function") {
|
|
543
|
-
this.agent.connectMCPServers().catch((error) => {
|
|
544
|
-
this.logger.error("Failed to connect MCP servers:", error);
|
|
545
|
-
});
|
|
546
|
-
} else {
|
|
547
|
-
this.startConnections();
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
/**
|
|
551
|
-
* Start MCP connections without blocking initialization
|
|
552
|
-
* @private
|
|
553
|
-
*/
|
|
554
|
-
async startConnections() {
|
|
555
|
-
if (!this.agent || !this.options.mcpServers) {
|
|
556
|
-
return;
|
|
557
|
-
}
|
|
558
|
-
try {
|
|
559
|
-
this.logger.info("Starting MCP server connections asynchronously...");
|
|
560
|
-
for (const server of this.options.mcpServers) {
|
|
561
|
-
this.connectServer(server);
|
|
562
|
-
}
|
|
563
|
-
} catch (error) {
|
|
564
|
-
this.logger.error("Error starting MCP connections:", error);
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
/**
|
|
568
|
-
* Connect to a single MCP server
|
|
569
|
-
* @param {MCPServerConfig} server - Server configuration
|
|
570
|
-
* @private
|
|
571
|
-
*/
|
|
572
|
-
async connectServer(server) {
|
|
573
|
-
try {
|
|
574
|
-
this.logger.info(`Connecting to MCP server: ${server.name}`);
|
|
575
|
-
const status = this.mcpConnectionStatus.get(server.name);
|
|
576
|
-
if (status) {
|
|
577
|
-
setTimeout(() => {
|
|
578
|
-
status.connected = true;
|
|
579
|
-
this.logger.info(`MCP server ${server.name} connected successfully`);
|
|
580
|
-
}, Math.random() * 2e3 + 1e3);
|
|
581
|
-
}
|
|
582
|
-
} catch (error) {
|
|
583
|
-
this.logger.error(`Failed to connect to MCP server ${server.name}:`, error);
|
|
584
|
-
const status = this.mcpConnectionStatus.get(server.name);
|
|
585
|
-
if (status) {
|
|
586
|
-
status.connected = false;
|
|
587
|
-
status.error = error instanceof Error ? error.message : "Unknown error";
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
535
|
}
|
|
591
536
|
/**
|
|
592
537
|
* Get MCP connection status for all servers
|
|
593
538
|
* @returns {Map<string, MCPConnectionStatus>} Connection status map
|
|
594
539
|
*/
|
|
595
540
|
getMCPConnectionStatus() {
|
|
596
|
-
|
|
541
|
+
if (this.agent) {
|
|
542
|
+
return this.agent.getMCPConnectionStatus();
|
|
543
|
+
}
|
|
544
|
+
return /* @__PURE__ */ new Map();
|
|
597
545
|
}
|
|
598
546
|
/**
|
|
599
547
|
* Check if a specific MCP server is connected
|
|
@@ -601,8 +549,12 @@ class ConversationalAgent {
|
|
|
601
549
|
* @returns {boolean} True if connected, false otherwise
|
|
602
550
|
*/
|
|
603
551
|
isMCPServerConnected(serverName) {
|
|
604
|
-
|
|
605
|
-
|
|
552
|
+
if (this.agent) {
|
|
553
|
+
const statusMap = this.agent.getMCPConnectionStatus();
|
|
554
|
+
const status = statusMap.get(serverName);
|
|
555
|
+
return status?.connected ?? false;
|
|
556
|
+
}
|
|
557
|
+
return false;
|
|
606
558
|
}
|
|
607
559
|
/**
|
|
608
560
|
* Clean up resources
|
|
@@ -628,6 +580,15 @@ class ConversationalAgent {
|
|
|
628
580
|
this.logger.error("Error during cleanup:", error);
|
|
629
581
|
}
|
|
630
582
|
}
|
|
583
|
+
extractResponseText(response) {
|
|
584
|
+
if (typeof response === "string") {
|
|
585
|
+
return response;
|
|
586
|
+
}
|
|
587
|
+
if (response && typeof response === "object" && "output" in response) {
|
|
588
|
+
return String(response.output);
|
|
589
|
+
}
|
|
590
|
+
return JSON.stringify(response);
|
|
591
|
+
}
|
|
631
592
|
}
|
|
632
593
|
export {
|
|
633
594
|
ConversationalAgent
|