@hashgraphonline/conversational-agent 0.1.208 → 0.1.210
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 +64 -13
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +6 -3
- package/dist/cjs/langchain-agent.d.ts +11 -0
- package/dist/cjs/memory/SmartMemoryManager.d.ts +65 -22
- package/dist/cjs/memory/TokenCounter.d.ts +1 -1
- package/dist/cjs/memory/index.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 +16 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index12.js +121 -46
- package/dist/esm/index12.js.map +1 -1
- package/dist/esm/index13.js +177 -13
- package/dist/esm/index13.js.map +1 -1
- package/dist/esm/index14.js +599 -100
- package/dist/esm/index14.js.map +1 -1
- package/dist/esm/index15.js +426 -9
- package/dist/esm/index15.js.map +1 -1
- package/dist/esm/index16.js +119 -160
- package/dist/esm/index16.js.map +1 -1
- package/dist/esm/index17.js +140 -150
- package/dist/esm/index17.js.map +1 -1
- package/dist/esm/index18.js +44 -231
- package/dist/esm/index18.js.map +1 -1
- package/dist/esm/index19.js +86 -643
- package/dist/esm/index19.js.map +1 -1
- package/dist/esm/index2.js +22 -13
- package/dist/esm/index2.js.map +1 -1
- package/dist/esm/index20.js +20 -230
- package/dist/esm/index20.js.map +1 -1
- package/dist/esm/index21.js +9 -179
- package/dist/esm/index21.js.map +1 -1
- package/dist/esm/index22.js +140 -89
- package/dist/esm/index22.js.map +1 -1
- package/dist/esm/index23.js +141 -81
- package/dist/esm/index23.js.map +1 -1
- package/dist/esm/index24.js +4 -4
- package/dist/esm/index24.js.map +1 -1
- package/dist/esm/index25.js +0 -8
- 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 +276 -37
- 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 +124 -18
- package/dist/esm/index8.js.map +1 -1
- package/dist/types/base-agent.d.ts +3 -1
- package/dist/types/conversational-agent.d.ts +64 -13
- package/dist/types/index.d.ts +6 -3
- package/dist/types/langchain-agent.d.ts +11 -0
- package/dist/types/memory/SmartMemoryManager.d.ts +65 -22
- package/dist/types/memory/TokenCounter.d.ts +1 -1
- package/dist/types/memory/index.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 +10 -5
- package/src/context/ReferenceResponseProcessor.ts +3 -4
- package/src/conversational-agent.ts +372 -57
- package/src/index.ts +19 -3
- package/src/langchain/ContentAwareAgentExecutor.ts +0 -1
- package/src/langchain-agent.ts +168 -33
- package/src/mcp/ContentProcessor.ts +11 -3
- package/src/mcp/adapters/langchain.ts +1 -10
- package/src/memory/ContentStorage.ts +2 -55
- package/src/memory/MemoryWindow.ts +4 -17
- package/src/memory/ReferenceIdGenerator.ts +4 -8
- package/src/memory/SmartMemoryManager.ts +375 -47
- package/src/memory/TokenCounter.ts +15 -22
- package/src/memory/index.ts +1 -1
- 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/hcs-10/HCS10Plugin.ts +44 -14
- package/src/plugins/index.ts +2 -1
- package/src/services/ContentStoreManager.ts +0 -3
- package/src/services/EntityResolver.ts +135 -0
- package/src/tools/EntityResolverTool.ts +170 -0
- package/src/types/content-reference.ts +8 -8
- package/src/types/index.ts +0 -1
- 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
|
@@ -12,18 +12,39 @@ import { createAgent } from './agent-factory';
|
|
|
12
12
|
import { LangChainProvider } from './providers';
|
|
13
13
|
import type { ChatResponse, ConversationContext } from './base-agent';
|
|
14
14
|
import { ChatOpenAI } from '@langchain/openai';
|
|
15
|
+
import { ChatAnthropic } from '@langchain/anthropic';
|
|
15
16
|
import { HumanMessage, AIMessage } from '@langchain/core/messages';
|
|
16
17
|
import type { AgentOperationalMode, MirrorNodeConfig } from 'hedera-agent-kit';
|
|
17
18
|
import { HCS10Plugin } from './plugins/hcs-10/HCS10Plugin';
|
|
18
19
|
import { HCS2Plugin } from './plugins/hcs-2/HCS2Plugin';
|
|
19
20
|
import { InscribePlugin } from './plugins/inscribe/InscribePlugin';
|
|
20
|
-
import {
|
|
21
|
+
import { HbarPlugin } from './plugins/hbar/HbarPlugin';
|
|
21
22
|
import { OpenConvaiState } from '@hashgraphonline/standards-agent-kit';
|
|
22
23
|
import type { IStateManager } from '@hashgraphonline/standards-agent-kit';
|
|
23
24
|
import { PrivateKey } from '@hashgraph/sdk';
|
|
24
25
|
import { getSystemMessage } from './config/system-message';
|
|
25
|
-
import type { MCPServerConfig } from './mcp/types';
|
|
26
|
+
import type { MCPServerConfig, MCPConnectionStatus } from './mcp/types';
|
|
26
27
|
import { ContentStoreManager } from './services/ContentStoreManager';
|
|
28
|
+
import { SmartMemoryManager, type SmartMemoryConfig } from './memory';
|
|
29
|
+
import {
|
|
30
|
+
createEntityTools,
|
|
31
|
+
ResolveEntitiesTool,
|
|
32
|
+
ExtractEntitiesTool,
|
|
33
|
+
} from './tools/EntityResolverTool';
|
|
34
|
+
|
|
35
|
+
export type ToolDescriptor = {
|
|
36
|
+
name: string;
|
|
37
|
+
namespace?: string;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type ChatHistoryItem = {
|
|
41
|
+
type: 'human' | 'ai';
|
|
42
|
+
content: string;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type AgentInstance = ReturnType<typeof createAgent>;
|
|
46
|
+
|
|
47
|
+
export type MirrorNetwork = 'testnet' | 'mainnet' | 'previewnet';
|
|
27
48
|
|
|
28
49
|
const DEFAULT_MODEL_NAME = 'gpt-4o';
|
|
29
50
|
const DEFAULT_TEMPERATURE = 0.1;
|
|
@@ -36,6 +57,7 @@ export interface ConversationalAgentOptions {
|
|
|
36
57
|
network?: NetworkType;
|
|
37
58
|
openAIApiKey: string;
|
|
38
59
|
openAIModelName?: string;
|
|
60
|
+
llmProvider?: 'openai' | 'anthropic';
|
|
39
61
|
verbose?: boolean;
|
|
40
62
|
operationalMode?: AgentOperationalMode;
|
|
41
63
|
userAccountId?: string;
|
|
@@ -49,6 +71,12 @@ export interface ConversationalAgentOptions {
|
|
|
49
71
|
enabledPlugins?: string[];
|
|
50
72
|
toolFilter?: (tool: { name: string; namespace?: string }) => boolean;
|
|
51
73
|
mcpServers?: MCPServerConfig[];
|
|
74
|
+
|
|
75
|
+
/** Enable automatic entity memory functionality (default: true) */
|
|
76
|
+
entityMemoryEnabled?: boolean;
|
|
77
|
+
|
|
78
|
+
/** Configuration for entity memory system */
|
|
79
|
+
entityMemoryConfig?: SmartMemoryConfig;
|
|
52
80
|
}
|
|
53
81
|
|
|
54
82
|
/**
|
|
@@ -61,15 +89,20 @@ export interface ConversationalAgentOptions {
|
|
|
61
89
|
* @returns A new instance of the ConversationalAgent class.
|
|
62
90
|
*/
|
|
63
91
|
export class ConversationalAgent {
|
|
64
|
-
|
|
92
|
+
protected agent?: AgentInstance;
|
|
65
93
|
public hcs10Plugin: HCS10Plugin;
|
|
66
94
|
public hcs2Plugin: HCS2Plugin;
|
|
67
95
|
public inscribePlugin: InscribePlugin;
|
|
68
|
-
public
|
|
96
|
+
public hbarPlugin: HbarPlugin;
|
|
69
97
|
public stateManager: IStateManager;
|
|
70
98
|
private options: ConversationalAgentOptions;
|
|
71
|
-
|
|
72
|
-
|
|
99
|
+
public logger: Logger;
|
|
100
|
+
protected contentStoreManager?: ContentStoreManager;
|
|
101
|
+
public memoryManager?: SmartMemoryManager | undefined;
|
|
102
|
+
private entityTools?: {
|
|
103
|
+
resolveEntities: ResolveEntitiesTool;
|
|
104
|
+
extractEntities: ExtractEntitiesTool;
|
|
105
|
+
};
|
|
73
106
|
|
|
74
107
|
constructor(options: ConversationalAgentOptions) {
|
|
75
108
|
this.options = options;
|
|
@@ -77,15 +110,31 @@ export class ConversationalAgent {
|
|
|
77
110
|
this.hcs10Plugin = new HCS10Plugin();
|
|
78
111
|
this.hcs2Plugin = new HCS2Plugin();
|
|
79
112
|
this.inscribePlugin = new InscribePlugin();
|
|
80
|
-
this.
|
|
113
|
+
this.hbarPlugin = new HbarPlugin();
|
|
81
114
|
this.logger = new Logger({
|
|
82
115
|
module: 'ConversationalAgent',
|
|
83
116
|
silent: options.disableLogging || false,
|
|
84
117
|
});
|
|
118
|
+
|
|
119
|
+
if (this.options.entityMemoryEnabled !== false) {
|
|
120
|
+
if (!options.openAIApiKey) {
|
|
121
|
+
throw new Error(
|
|
122
|
+
'OpenAI API key is required when entity memory is enabled'
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
this.memoryManager = new SmartMemoryManager(
|
|
127
|
+
this.options.entityMemoryConfig
|
|
128
|
+
);
|
|
129
|
+
this.logger.info('Entity memory initialized');
|
|
130
|
+
|
|
131
|
+
this.entityTools = createEntityTools(options.openAIApiKey, 'gpt-4o-mini');
|
|
132
|
+
this.logger.info('LLM-based entity resolver tools initialized');
|
|
133
|
+
}
|
|
85
134
|
}
|
|
86
135
|
|
|
87
136
|
/**
|
|
88
|
-
* Initialize the conversational agent with Hedera
|
|
137
|
+
* Initialize the conversational agent with Hedera Hashgraph connection and AI configuration
|
|
89
138
|
* @throws {Error} If account ID or private key is missing
|
|
90
139
|
* @throws {Error} If initialization fails
|
|
91
140
|
*/
|
|
@@ -96,6 +145,7 @@ export class ConversationalAgent {
|
|
|
96
145
|
network = DEFAULT_NETWORK,
|
|
97
146
|
openAIApiKey,
|
|
98
147
|
openAIModelName = DEFAULT_MODEL_NAME,
|
|
148
|
+
llmProvider = 'openai',
|
|
99
149
|
} = this.options;
|
|
100
150
|
|
|
101
151
|
this.validateOptions(accountId, privateKey);
|
|
@@ -110,30 +160,72 @@ export class ConversationalAgent {
|
|
|
110
160
|
const serverSigner = new ServerSigner(
|
|
111
161
|
accountId!,
|
|
112
162
|
privateKeyInstance,
|
|
113
|
-
network as
|
|
163
|
+
network as MirrorNetwork
|
|
114
164
|
);
|
|
115
165
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
166
|
+
let llm: ChatOpenAI | ChatAnthropic;
|
|
167
|
+
if (llmProvider === 'anthropic') {
|
|
168
|
+
llm = new ChatAnthropic({
|
|
169
|
+
apiKey: openAIApiKey,
|
|
170
|
+
modelName: openAIModelName || 'claude-3-5-sonnet-20241022',
|
|
171
|
+
temperature: DEFAULT_TEMPERATURE,
|
|
172
|
+
});
|
|
173
|
+
} else {
|
|
174
|
+
const modelName = openAIModelName || 'gpt-4o-mini';
|
|
175
|
+
const isGPT5Model =
|
|
176
|
+
modelName.toLowerCase().includes('gpt-5') ||
|
|
177
|
+
modelName.toLowerCase().includes('gpt5');
|
|
178
|
+
llm = new ChatOpenAI({
|
|
179
|
+
apiKey: openAIApiKey,
|
|
180
|
+
modelName: openAIModelName,
|
|
181
|
+
...(isGPT5Model
|
|
182
|
+
? { temperature: 1 }
|
|
183
|
+
: { temperature: DEFAULT_TEMPERATURE }),
|
|
184
|
+
});
|
|
185
|
+
}
|
|
123
186
|
|
|
187
|
+
const allPlugins = this.preparePlugins();
|
|
124
188
|
const agentConfig = this.createAgentConfig(serverSigner, llm, allPlugins);
|
|
189
|
+
|
|
125
190
|
this.agent = createAgent(agentConfig);
|
|
126
191
|
|
|
127
192
|
this.configureHCS10Plugin(allPlugins);
|
|
128
193
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
194
|
+
this.contentStoreManager = new ContentStoreManager();
|
|
195
|
+
await this.contentStoreManager.initialize();
|
|
196
|
+
this.logger.info(
|
|
197
|
+
'ContentStoreManager initialized for content reference support'
|
|
198
|
+
);
|
|
135
199
|
|
|
136
200
|
await this.agent.boot();
|
|
201
|
+
|
|
202
|
+
if (this.agent) {
|
|
203
|
+
const cfg = agentConfig;
|
|
204
|
+
cfg.filtering = cfg.filtering || {};
|
|
205
|
+
const originalPredicate = cfg.filtering.toolPredicate as
|
|
206
|
+
| ((t: ToolDescriptor) => boolean)
|
|
207
|
+
| undefined;
|
|
208
|
+
const userPredicate = this.options.toolFilter;
|
|
209
|
+
cfg.filtering.toolPredicate = (tool: ToolDescriptor): boolean => {
|
|
210
|
+
if (tool && tool.name === 'hedera-account-transfer-hbar') {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
if (tool && tool.name === 'hedera-hts-airdrop-token') {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
if (originalPredicate && !originalPredicate(tool)) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
if (userPredicate && !userPredicate(tool)) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
return true;
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (this.options.mcpServers && this.options.mcpServers.length > 0) {
|
|
227
|
+
this.connectMCP();
|
|
228
|
+
}
|
|
137
229
|
} catch (error) {
|
|
138
230
|
this.logger.error('Failed to initialize ConversationalAgent:', error);
|
|
139
231
|
throw error;
|
|
@@ -186,33 +278,47 @@ export class ConversationalAgent {
|
|
|
186
278
|
*/
|
|
187
279
|
async processMessage(
|
|
188
280
|
message: string,
|
|
189
|
-
chatHistory:
|
|
190
|
-
type: 'human' | 'ai';
|
|
191
|
-
content: string;
|
|
192
|
-
}[] = []
|
|
281
|
+
chatHistory: ChatHistoryItem[] = []
|
|
193
282
|
): Promise<ChatResponse> {
|
|
194
283
|
if (!this.agent) {
|
|
195
284
|
throw new Error('Agent not initialized. Call initialize() first.');
|
|
196
285
|
}
|
|
197
286
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
287
|
+
try {
|
|
288
|
+
const resolvedMessage = this.memoryManager
|
|
289
|
+
? await this.resolveEntitiesInMessage(message)
|
|
290
|
+
: message;
|
|
291
|
+
|
|
292
|
+
const messages = chatHistory.map((msg) => {
|
|
293
|
+
if (msg.type === 'human') {
|
|
294
|
+
return new HumanMessage(msg.content);
|
|
295
|
+
} else {
|
|
296
|
+
return new AIMessage(msg.content);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const context: ConversationContext = {
|
|
301
|
+
messages,
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
const response = await this.agent.chat(resolvedMessage, context);
|
|
305
|
+
|
|
306
|
+
if (this.memoryManager) {
|
|
307
|
+
await this.extractAndStoreEntities(response, message);
|
|
203
308
|
}
|
|
204
|
-
});
|
|
205
309
|
|
|
206
|
-
|
|
207
|
-
messages,
|
|
208
|
-
};
|
|
310
|
+
this.logger.info('Message processed successfully');
|
|
209
311
|
|
|
210
|
-
|
|
312
|
+
return response;
|
|
313
|
+
} catch (error) {
|
|
314
|
+
this.logger.error('Error processing message:', error);
|
|
315
|
+
throw error;
|
|
316
|
+
}
|
|
211
317
|
}
|
|
212
318
|
|
|
213
319
|
/**
|
|
214
320
|
* Validates initialization options and throws if required fields are missing.
|
|
215
|
-
*
|
|
321
|
+
*
|
|
216
322
|
* @param accountId - The Hedera account ID
|
|
217
323
|
* @param privateKey - The private key for the account
|
|
218
324
|
* @throws {Error} If required fields are missing
|
|
@@ -225,21 +331,21 @@ export class ConversationalAgent {
|
|
|
225
331
|
|
|
226
332
|
/**
|
|
227
333
|
* Prepares the list of plugins to use based on configuration.
|
|
228
|
-
*
|
|
334
|
+
*
|
|
229
335
|
* @returns Array of plugins to initialize with the agent
|
|
230
336
|
*/
|
|
231
337
|
private preparePlugins(): BasePlugin[] {
|
|
232
338
|
const { additionalPlugins = [], enabledPlugins } = this.options;
|
|
233
|
-
|
|
339
|
+
|
|
234
340
|
const standardPlugins = [
|
|
235
341
|
this.hcs10Plugin,
|
|
236
342
|
this.hcs2Plugin,
|
|
237
343
|
this.inscribePlugin,
|
|
238
|
-
this.
|
|
344
|
+
this.hbarPlugin,
|
|
239
345
|
];
|
|
240
|
-
|
|
346
|
+
|
|
241
347
|
const corePlugins = getAllHederaCorePlugins();
|
|
242
|
-
|
|
348
|
+
|
|
243
349
|
if (enabledPlugins) {
|
|
244
350
|
const enabledSet = new Set(enabledPlugins);
|
|
245
351
|
const filteredPlugins = [...standardPlugins, ...corePlugins].filter(
|
|
@@ -247,13 +353,13 @@ export class ConversationalAgent {
|
|
|
247
353
|
);
|
|
248
354
|
return [...filteredPlugins, ...additionalPlugins];
|
|
249
355
|
}
|
|
250
|
-
|
|
356
|
+
|
|
251
357
|
return [...standardPlugins, ...corePlugins, ...additionalPlugins];
|
|
252
358
|
}
|
|
253
359
|
|
|
254
360
|
/**
|
|
255
361
|
* Creates the agent configuration object.
|
|
256
|
-
*
|
|
362
|
+
*
|
|
257
363
|
* @param serverSigner - The server signer instance
|
|
258
364
|
* @param llm - The language model instance
|
|
259
365
|
* @param allPlugins - Array of plugins to use
|
|
@@ -261,7 +367,7 @@ export class ConversationalAgent {
|
|
|
261
367
|
*/
|
|
262
368
|
private createAgentConfig(
|
|
263
369
|
serverSigner: ServerSigner,
|
|
264
|
-
llm: ChatOpenAI,
|
|
370
|
+
llm: ChatOpenAI | ChatAnthropic,
|
|
265
371
|
allPlugins: BasePlugin[]
|
|
266
372
|
): Parameters<typeof createAgent>[0] {
|
|
267
373
|
const {
|
|
@@ -284,6 +390,8 @@ export class ConversationalAgent {
|
|
|
284
390
|
operationalMode: operationalMode,
|
|
285
391
|
...(userAccountId && { userAccountId }),
|
|
286
392
|
...(scheduleUserTransactionsInBytesMode !== undefined && {
|
|
393
|
+
scheduleUserTransactionsInBytesMode:
|
|
394
|
+
scheduleUserTransactionsInBytesMode,
|
|
287
395
|
scheduleUserTransactions: scheduleUserTransactionsInBytesMode,
|
|
288
396
|
}),
|
|
289
397
|
},
|
|
@@ -292,7 +400,7 @@ export class ConversationalAgent {
|
|
|
292
400
|
temperature: DEFAULT_TEMPERATURE,
|
|
293
401
|
},
|
|
294
402
|
filtering: {
|
|
295
|
-
toolPredicate: (tool) => {
|
|
403
|
+
toolPredicate: (tool: ToolDescriptor): boolean => {
|
|
296
404
|
if (tool.name === 'hedera-account-transfer-hbar') return false;
|
|
297
405
|
if (this.options.toolFilter && !this.options.toolFilter(tool)) {
|
|
298
406
|
return false;
|
|
@@ -303,7 +411,9 @@ export class ConversationalAgent {
|
|
|
303
411
|
messaging: {
|
|
304
412
|
systemPreamble:
|
|
305
413
|
customSystemMessagePreamble || getSystemMessage(accountId),
|
|
306
|
-
...(customSystemMessagePostamble && {
|
|
414
|
+
...(customSystemMessagePostamble && {
|
|
415
|
+
systemPostamble: customSystemMessagePostamble,
|
|
416
|
+
}),
|
|
307
417
|
conciseMode: true,
|
|
308
418
|
},
|
|
309
419
|
extensions: {
|
|
@@ -315,7 +425,7 @@ export class ConversationalAgent {
|
|
|
315
425
|
...(this.options.mcpServers && {
|
|
316
426
|
mcp: {
|
|
317
427
|
servers: this.options.mcpServers,
|
|
318
|
-
autoConnect:
|
|
428
|
+
autoConnect: false,
|
|
319
429
|
},
|
|
320
430
|
}),
|
|
321
431
|
debug: {
|
|
@@ -327,13 +437,15 @@ export class ConversationalAgent {
|
|
|
327
437
|
|
|
328
438
|
/**
|
|
329
439
|
* Configures the HCS-10 plugin with the state manager.
|
|
330
|
-
*
|
|
440
|
+
*
|
|
331
441
|
* @param allPlugins - Array of all plugins
|
|
332
442
|
*/
|
|
333
443
|
private configureHCS10Plugin(allPlugins: BasePlugin[]): void {
|
|
334
444
|
const hcs10 = allPlugins.find((p) => p.id === 'hcs-10');
|
|
335
445
|
if (hcs10) {
|
|
336
|
-
(
|
|
446
|
+
(
|
|
447
|
+
hcs10 as BasePlugin & { appConfig?: Record<string, unknown> }
|
|
448
|
+
).appConfig = {
|
|
337
449
|
stateManager: this.stateManager,
|
|
338
450
|
};
|
|
339
451
|
}
|
|
@@ -449,7 +561,7 @@ export class ConversationalAgent {
|
|
|
449
561
|
* Detect the private key type by querying the account info from mirror node
|
|
450
562
|
* @param {string} accountId - The Hedera account ID
|
|
451
563
|
* @param {string} privateKey - The private key string
|
|
452
|
-
* @param {NetworkType} network - The Hedera
|
|
564
|
+
* @param {NetworkType} network - The Hedera Hashgraph
|
|
453
565
|
* @returns {Promise<PrivateKey>} The appropriate PrivateKey instance
|
|
454
566
|
*/
|
|
455
567
|
private async detectPrivateKeyType(
|
|
@@ -469,17 +581,220 @@ export class ConversationalAgent {
|
|
|
469
581
|
}
|
|
470
582
|
}
|
|
471
583
|
|
|
584
|
+
/**
|
|
585
|
+
* Resolve entity references using LLM-based resolver
|
|
586
|
+
* @param content - Message content to resolve
|
|
587
|
+
* @returns Resolved message content with entity IDs replaced
|
|
588
|
+
*/
|
|
589
|
+
private async resolveEntitiesInMessage(content: string): Promise<string> {
|
|
590
|
+
if (!this.memoryManager || !this.entityTools) {
|
|
591
|
+
return content;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
try {
|
|
595
|
+
const entities = this.memoryManager.getEntityAssociations();
|
|
596
|
+
|
|
597
|
+
if (entities.length === 0) {
|
|
598
|
+
this.logger.info('No entities in memory, skipping resolution');
|
|
599
|
+
return content;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
this.logger.info(
|
|
603
|
+
`Starting LLM-based entity resolution for: "${content.substring(
|
|
604
|
+
0,
|
|
605
|
+
100
|
|
606
|
+
)}..."`
|
|
607
|
+
);
|
|
608
|
+
|
|
609
|
+
const resolvedContent = await this.entityTools.resolveEntities.call({
|
|
610
|
+
message: content,
|
|
611
|
+
entities: entities.map((e) => ({
|
|
612
|
+
entityId: e.entityId,
|
|
613
|
+
entityName: e.entityName,
|
|
614
|
+
entityType: e.entityType,
|
|
615
|
+
})),
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
if (resolvedContent !== content) {
|
|
619
|
+
this.logger.info(
|
|
620
|
+
`Entity resolution completed. Original: "${content}" -> Resolved: "${resolvedContent}"`
|
|
621
|
+
);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
return resolvedContent;
|
|
625
|
+
} catch (error) {
|
|
626
|
+
this.logger.error('Entity resolution failed:', error);
|
|
627
|
+
throw error;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
/**
|
|
632
|
+
* Extract and store entities from agent responses
|
|
633
|
+
* @param response - Agent response containing potential entity information
|
|
634
|
+
* @param originalMessage - Original user message for context
|
|
635
|
+
*/
|
|
636
|
+
private async extractAndStoreEntities(
|
|
637
|
+
response: unknown,
|
|
638
|
+
originalMessage: string
|
|
639
|
+
): Promise<void> {
|
|
640
|
+
if (!this.memoryManager || !this.entityTools) {
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
try {
|
|
645
|
+
this.logger.info('Starting LLM-based entity extraction');
|
|
646
|
+
|
|
647
|
+
const responseText = this.extractResponseText(response);
|
|
648
|
+
|
|
649
|
+
const entitiesJson = await this.entityTools.extractEntities.call({
|
|
650
|
+
response: responseText,
|
|
651
|
+
userMessage: originalMessage,
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
try {
|
|
655
|
+
const entities = JSON.parse(entitiesJson);
|
|
656
|
+
|
|
657
|
+
for (const entity of entities) {
|
|
658
|
+
this.logger.info(
|
|
659
|
+
`Storing entity: ${entity.name} (${entity.type}) -> ${entity.id}`
|
|
660
|
+
);
|
|
661
|
+
|
|
662
|
+
const transactionId = this.extractTransactionId(response);
|
|
663
|
+
this.memoryManager.storeEntityAssociation(
|
|
664
|
+
entity.id,
|
|
665
|
+
entity.name,
|
|
666
|
+
entity.type,
|
|
667
|
+
transactionId
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
if (entities.length > 0) {
|
|
672
|
+
this.logger.info(
|
|
673
|
+
`Stored ${entities.length} entities via LLM extraction`
|
|
674
|
+
);
|
|
675
|
+
} else {
|
|
676
|
+
this.logger.info('No entities found in response via LLM extraction');
|
|
677
|
+
}
|
|
678
|
+
} catch (parseError) {
|
|
679
|
+
this.logger.error(
|
|
680
|
+
'Failed to parse extracted entities JSON:',
|
|
681
|
+
parseError
|
|
682
|
+
);
|
|
683
|
+
throw parseError;
|
|
684
|
+
}
|
|
685
|
+
} catch (error) {
|
|
686
|
+
this.logger.error('Entity extraction failed:', error);
|
|
687
|
+
throw error;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Extract transaction ID from response if available
|
|
693
|
+
* @param response - Transaction response
|
|
694
|
+
* @returns Transaction ID or undefined
|
|
695
|
+
*/
|
|
696
|
+
private extractTransactionId(response: unknown): string | undefined {
|
|
697
|
+
try {
|
|
698
|
+
if (
|
|
699
|
+
typeof response === 'object' &&
|
|
700
|
+
response &&
|
|
701
|
+
'transactionId' in response
|
|
702
|
+
) {
|
|
703
|
+
return (response as { transactionId?: string }).transactionId;
|
|
704
|
+
}
|
|
705
|
+
if (typeof response === 'string') {
|
|
706
|
+
const match = response.match(
|
|
707
|
+
/transaction[\s\w]*ID[\s:"]*([0-9a-fA-F@\.\-]+)/i
|
|
708
|
+
);
|
|
709
|
+
return match ? match[1] : undefined;
|
|
710
|
+
}
|
|
711
|
+
return undefined;
|
|
712
|
+
} catch {
|
|
713
|
+
return undefined;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Connect to MCP servers asynchronously
|
|
719
|
+
* @private
|
|
720
|
+
*/
|
|
721
|
+
private connectMCP(): void {
|
|
722
|
+
if (!this.agent || !this.options.mcpServers) {
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
this.agent
|
|
727
|
+
.connectMCPServers()
|
|
728
|
+
.catch((e) => {
|
|
729
|
+
this.logger.error('Failed to connect MCP servers:', e);
|
|
730
|
+
})
|
|
731
|
+
.then(() => {
|
|
732
|
+
this.logger.info('MCP servers connected successfully');
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Get MCP connection status for all servers
|
|
738
|
+
* @returns {Map<string, MCPConnectionStatus>} Connection status map
|
|
739
|
+
*/
|
|
740
|
+
getMCPConnectionStatus(): Map<string, MCPConnectionStatus> {
|
|
741
|
+
if (this.agent) {
|
|
742
|
+
return this.agent.getMCPConnectionStatus();
|
|
743
|
+
}
|
|
744
|
+
return new Map();
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Check if a specific MCP server is connected
|
|
749
|
+
* @param {string} serverName - Name of the server to check
|
|
750
|
+
* @returns {boolean} True if connected, false otherwise
|
|
751
|
+
*/
|
|
752
|
+
isMCPServerConnected(serverName: string): boolean {
|
|
753
|
+
if (this.agent) {
|
|
754
|
+
const statusMap = this.agent.getMCPConnectionStatus();
|
|
755
|
+
const status = statusMap.get(serverName);
|
|
756
|
+
return status?.connected ?? false;
|
|
757
|
+
}
|
|
758
|
+
return false;
|
|
759
|
+
}
|
|
760
|
+
|
|
472
761
|
/**
|
|
473
762
|
* Clean up resources
|
|
474
763
|
*/
|
|
475
764
|
async cleanup(): Promise<void> {
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
765
|
+
try {
|
|
766
|
+
this.logger.info('Cleaning up ConversationalAgent...');
|
|
767
|
+
|
|
768
|
+
if (this.memoryManager) {
|
|
769
|
+
try {
|
|
770
|
+
this.memoryManager.dispose();
|
|
771
|
+
this.logger.info('Memory manager cleaned up successfully');
|
|
772
|
+
} catch (error) {
|
|
773
|
+
this.logger.warn('Error cleaning up memory manager:', error);
|
|
774
|
+
}
|
|
775
|
+
this.memoryManager = undefined;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
if (this.contentStoreManager) {
|
|
779
|
+
await this.contentStoreManager.dispose();
|
|
780
|
+
this.logger.info('ContentStoreManager cleaned up');
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
this.logger.info('ConversationalAgent cleanup completed');
|
|
784
|
+
} catch (error) {
|
|
785
|
+
this.logger.error('Error during cleanup:', error);
|
|
479
786
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
private extractResponseText(response: unknown): string {
|
|
790
|
+
if (typeof response === 'string') {
|
|
791
|
+
return response;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
if (response && typeof response === 'object' && 'output' in response) {
|
|
795
|
+
return String(response.output);
|
|
483
796
|
}
|
|
797
|
+
|
|
798
|
+
return JSON.stringify(response);
|
|
484
799
|
}
|
|
485
800
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { HCS10Plugin } from './plugins/hcs-10/HCS10Plugin';
|
|
2
2
|
export { HCS2Plugin } from './plugins/hcs-2/HCS2Plugin';
|
|
3
3
|
export { InscribePlugin } from './plugins/inscribe/InscribePlugin';
|
|
4
|
-
export {
|
|
4
|
+
export { HbarPlugin } from './plugins/hbar/HbarPlugin';
|
|
5
5
|
export { HCS10Plugin as OpenConvAIPlugin } from './plugins/hcs-10/HCS10Plugin';
|
|
6
6
|
export { ConversationalAgent } from './conversational-agent';
|
|
7
7
|
export type { ConversationalAgentOptions } from './conversational-agent';
|
|
@@ -29,5 +29,21 @@ export * from 'hedera-agent-kit';
|
|
|
29
29
|
|
|
30
30
|
export type { IStateManager } from '@hashgraphonline/standards-agent-kit';
|
|
31
31
|
|
|
32
|
-
export type {
|
|
33
|
-
|
|
32
|
+
export type {
|
|
33
|
+
MCPServerConfig,
|
|
34
|
+
MCPConnectionStatus,
|
|
35
|
+
MCPToolInfo,
|
|
36
|
+
} from './mcp/types';
|
|
37
|
+
export {
|
|
38
|
+
MCPServers,
|
|
39
|
+
createMCPConfig,
|
|
40
|
+
validateServerConfig,
|
|
41
|
+
} from './mcp/helpers';
|
|
42
|
+
|
|
43
|
+
export * from './memory';
|
|
44
|
+
export {
|
|
45
|
+
createEntityTools,
|
|
46
|
+
ResolveEntitiesTool,
|
|
47
|
+
ExtractEntitiesTool,
|
|
48
|
+
} from './tools/EntityResolverTool';
|
|
49
|
+
export { ContentStoreManager } from './services/ContentStoreManager';
|