@hashgraphonline/conversational-agent 0.1.205 → 0.1.206

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.
Files changed (87) hide show
  1. package/dist/cjs/base-agent.d.ts +6 -0
  2. package/dist/cjs/context/ReferenceContextManager.d.ts +84 -0
  3. package/dist/cjs/context/ReferenceResponseProcessor.d.ts +76 -0
  4. package/dist/cjs/conversational-agent.d.ts +34 -0
  5. package/dist/cjs/index.cjs +1 -1
  6. package/dist/cjs/index.cjs.map +1 -1
  7. package/dist/cjs/langchain-agent.d.ts +1 -0
  8. package/dist/cjs/mcp/ContentProcessor.d.ts +37 -0
  9. package/dist/cjs/mcp/MCPClientManager.d.ts +19 -1
  10. package/dist/cjs/memory/ContentStorage.d.ts +205 -0
  11. package/dist/cjs/memory/MemoryWindow.d.ts +114 -0
  12. package/dist/cjs/memory/ReferenceIdGenerator.d.ts +45 -0
  13. package/dist/cjs/memory/SmartMemoryManager.d.ts +201 -0
  14. package/dist/cjs/memory/TokenCounter.d.ts +61 -0
  15. package/dist/cjs/memory/index.d.ts +7 -0
  16. package/dist/cjs/plugins/hbar-transfer/TransferHbarTool.d.ts +18 -0
  17. package/dist/cjs/services/ContentStoreManager.d.ts +54 -0
  18. package/dist/cjs/types/content-reference.d.ts +213 -0
  19. package/dist/cjs/types/index.d.ts +4 -0
  20. package/dist/esm/index12.js +15 -2
  21. package/dist/esm/index12.js.map +1 -1
  22. package/dist/esm/index14.js +119 -95
  23. package/dist/esm/index14.js.map +1 -1
  24. package/dist/esm/index15.js +159 -114
  25. package/dist/esm/index15.js.map +1 -1
  26. package/dist/esm/index16.js +122 -81
  27. package/dist/esm/index16.js.map +1 -1
  28. package/dist/esm/index17.js +236 -0
  29. package/dist/esm/index17.js.map +1 -0
  30. package/dist/esm/index18.js +95 -0
  31. package/dist/esm/index18.js.map +1 -0
  32. package/dist/esm/index19.js +663 -0
  33. package/dist/esm/index19.js.map +1 -0
  34. package/dist/esm/index2.js +3 -1
  35. package/dist/esm/index2.js.map +1 -1
  36. package/dist/esm/index20.js +233 -0
  37. package/dist/esm/index20.js.map +1 -0
  38. package/dist/esm/index21.js +182 -0
  39. package/dist/esm/index21.js.map +1 -0
  40. package/dist/esm/index22.js +126 -0
  41. package/dist/esm/index22.js.map +1 -0
  42. package/dist/esm/index23.js +68 -0
  43. package/dist/esm/index23.js.map +1 -0
  44. package/dist/esm/index24.js +38 -0
  45. package/dist/esm/index24.js.map +1 -0
  46. package/dist/esm/index6.js +143 -84
  47. package/dist/esm/index6.js.map +1 -1
  48. package/dist/esm/index7.js.map +1 -1
  49. package/dist/esm/index8.js +69 -5
  50. package/dist/esm/index8.js.map +1 -1
  51. package/dist/types/base-agent.d.ts +6 -0
  52. package/dist/types/context/ReferenceContextManager.d.ts +84 -0
  53. package/dist/types/context/ReferenceResponseProcessor.d.ts +76 -0
  54. package/dist/types/conversational-agent.d.ts +34 -0
  55. package/dist/types/langchain-agent.d.ts +1 -0
  56. package/dist/types/mcp/ContentProcessor.d.ts +37 -0
  57. package/dist/types/mcp/MCPClientManager.d.ts +19 -1
  58. package/dist/types/memory/ContentStorage.d.ts +205 -0
  59. package/dist/types/memory/MemoryWindow.d.ts +114 -0
  60. package/dist/types/memory/ReferenceIdGenerator.d.ts +45 -0
  61. package/dist/types/memory/SmartMemoryManager.d.ts +201 -0
  62. package/dist/types/memory/TokenCounter.d.ts +61 -0
  63. package/dist/types/memory/index.d.ts +7 -0
  64. package/dist/types/plugins/hbar-transfer/TransferHbarTool.d.ts +18 -0
  65. package/dist/types/services/ContentStoreManager.d.ts +54 -0
  66. package/dist/types/types/content-reference.d.ts +213 -0
  67. package/dist/types/types/index.d.ts +4 -0
  68. package/package.json +5 -3
  69. package/src/base-agent.ts +6 -0
  70. package/src/context/ReferenceContextManager.ts +345 -0
  71. package/src/context/ReferenceResponseProcessor.ts +296 -0
  72. package/src/conversational-agent.ts +166 -92
  73. package/src/langchain-agent.ts +89 -2
  74. package/src/mcp/ContentProcessor.ts +317 -0
  75. package/src/mcp/MCPClientManager.ts +61 -1
  76. package/src/mcp/adapters/langchain.ts +9 -4
  77. package/src/memory/ContentStorage.ts +954 -0
  78. package/src/memory/MemoryWindow.ts +247 -0
  79. package/src/memory/ReferenceIdGenerator.ts +84 -0
  80. package/src/memory/SmartMemoryManager.ts +323 -0
  81. package/src/memory/TokenCounter.ts +152 -0
  82. package/src/memory/index.ts +8 -0
  83. package/src/plugins/hbar-transfer/TransferHbarTool.ts +19 -1
  84. package/src/plugins/hcs-10/HCS10Plugin.ts +5 -4
  85. package/src/services/ContentStoreManager.ts +199 -0
  86. package/src/types/content-reference.ts +281 -0
  87. package/src/types/index.ts +6 -0
@@ -0,0 +1,296 @@
1
+ import type { ContentReference, ReferenceId, ContentMetadata } from '../types/content-reference';
2
+ import type { ReferenceContextManager, ReferenceDisplayOptions } from './ReferenceContextManager';
3
+ import { Logger } from '@hashgraphonline/standards-sdk';
4
+
5
+ export interface ResponseProcessingOptions {
6
+ autoDisplayReferences?: boolean;
7
+ displayOptions?: ReferenceDisplayOptions;
8
+ includeReferenceInstructions?: boolean;
9
+ contextualizeReferences?: boolean;
10
+ }
11
+
12
+ export interface ProcessedResponse {
13
+ content: string;
14
+ hasReferences: boolean;
15
+ referenceCount: number;
16
+ contextIds: string[];
17
+ suggestedActions: string[];
18
+ }
19
+
20
+ export interface ReferenceDetectionResult {
21
+ hasReferences: boolean;
22
+ references: Array<{
23
+ reference: ContentReference;
24
+ position: number;
25
+ originalText: string;
26
+ }>;
27
+ plainReferences: Array<{
28
+ referenceId: ReferenceId;
29
+ position: number;
30
+ originalText: string;
31
+ }>;
32
+ }
33
+
34
+ /**
35
+ * Processes agent responses to detect and display content references
36
+ * Handles both structured references and plain reference IDs
37
+ */
38
+ export class ReferenceResponseProcessor {
39
+ private contextManager: ReferenceContextManager;
40
+ private logger: Logger;
41
+
42
+ constructor(contextManager: ReferenceContextManager, logger: Logger) {
43
+ this.contextManager = contextManager;
44
+ this.logger = logger;
45
+ }
46
+
47
+ /**
48
+ * Process an agent response to handle content references
49
+ */
50
+ async processResponse(
51
+ responseContent: string,
52
+ options: ResponseProcessingOptions = {}
53
+ ): Promise<ProcessedResponse> {
54
+ const {
55
+ autoDisplayReferences = true,
56
+ displayOptions = {},
57
+ includeReferenceInstructions = true,
58
+ contextualizeReferences = true
59
+ } = options;
60
+
61
+ try {
62
+ const detection = this.detectReferences(responseContent);
63
+
64
+ if (!detection.hasReferences) {
65
+ return {
66
+ content: responseContent,
67
+ hasReferences: false,
68
+ referenceCount: 0,
69
+ contextIds: [],
70
+ suggestedActions: []
71
+ };
72
+ }
73
+
74
+ let processedContent = responseContent;
75
+ const contextIds: string[] = [];
76
+ const suggestedActions: string[] = [];
77
+
78
+ if (autoDisplayReferences) {
79
+ for (const { reference, position, originalText } of detection.references) {
80
+ const displayResult = await this.contextManager.displayReference(reference, displayOptions);
81
+
82
+ processedContent = processedContent.replace(originalText, displayResult.displayText);
83
+
84
+ if (displayResult.contextId) {
85
+ contextIds.push(displayResult.contextId);
86
+ }
87
+
88
+ if (displayResult.suggestedActions) {
89
+ suggestedActions.push(...displayResult.suggestedActions);
90
+ }
91
+ }
92
+
93
+ for (const { referenceId, originalText } of detection.plainReferences) {
94
+ try {
95
+ const resolution = await this.contextManager['contentStorage'].resolveReference(referenceId);
96
+ if (resolution.success && resolution.metadata) {
97
+ const referenceMetadata: Pick<ContentMetadata, 'contentType' | 'sizeBytes' | 'source' | 'fileName' | 'mimeType'> = {
98
+ contentType: resolution.metadata.contentType,
99
+ sizeBytes: resolution.metadata.sizeBytes,
100
+ source: resolution.metadata.source
101
+ };
102
+
103
+ if (resolution.metadata.fileName !== undefined) {
104
+ referenceMetadata.fileName = resolution.metadata.fileName;
105
+ }
106
+ if (resolution.metadata.mimeType !== undefined) {
107
+ referenceMetadata.mimeType = resolution.metadata.mimeType;
108
+ }
109
+
110
+ const reference: ContentReference = {
111
+ referenceId,
112
+ state: 'active',
113
+ preview: this.createPreviewFromContent(resolution.content!, resolution.metadata.contentType),
114
+ metadata: referenceMetadata,
115
+ createdAt: resolution.metadata.createdAt,
116
+ format: 'ref://{id}' as const
117
+ };
118
+
119
+ const displayResult = await this.contextManager.displayReference(reference, displayOptions);
120
+ processedContent = processedContent.replace(originalText, displayResult.displayText);
121
+
122
+ if (displayResult.contextId) {
123
+ contextIds.push(displayResult.contextId);
124
+ }
125
+ } else {
126
+ processedContent = processedContent.replace(
127
+ originalText,
128
+ `❌ Reference unavailable: ${referenceId.substring(0, 12)}...`
129
+ );
130
+ suggestedActions.push('Request fresh content');
131
+ }
132
+ } catch (error) {
133
+ this.logger.warn(`Failed to resolve plain reference ${referenceId}:`, error);
134
+ processedContent = processedContent.replace(
135
+ originalText,
136
+ `⚠️ Reference error: ${referenceId.substring(0, 12)}...`
137
+ );
138
+ }
139
+ }
140
+ }
141
+
142
+ if (includeReferenceInstructions && (detection.references.length > 0 || detection.plainReferences.length > 0)) {
143
+ if (contextualizeReferences && contextIds.length === 1) {
144
+ processedContent += `\n\n💡 To inscribe this content, say "inscribe it" or "inscribe the content".`;
145
+ } else if (contextualizeReferences && contextIds.length > 1) {
146
+ processedContent += `\n\n💡 To inscribe any of this content, say "inscribe it" (uses most recent) or specify the reference.`;
147
+ } else {
148
+ processedContent += `\n\n💡 Referenced content can be inscribed using the "inscribe it" command.`;
149
+ }
150
+ }
151
+
152
+ return {
153
+ content: processedContent,
154
+ hasReferences: true,
155
+ referenceCount: detection.references.length + detection.plainReferences.length,
156
+ contextIds,
157
+ suggestedActions: [...new Set(suggestedActions)]
158
+ };
159
+ } catch (error) {
160
+ this.logger.error('Error processing response references:', error);
161
+ return {
162
+ content: responseContent,
163
+ hasReferences: false,
164
+ referenceCount: 0,
165
+ contextIds: [],
166
+ suggestedActions: ['Check reference system', 'Try again']
167
+ };
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Detect references in response content
173
+ */
174
+ private detectReferences(content: string): ReferenceDetectionResult {
175
+ const references: Array<{
176
+ reference: ContentReference;
177
+ position: number;
178
+ originalText: string;
179
+ }> = [];
180
+
181
+ const plainReferences: Array<{
182
+ referenceId: ReferenceId;
183
+ position: number;
184
+ originalText: string;
185
+ }> = [];
186
+
187
+ const contentReferenceRegex = /"type":\s*"content_reference"[^}]*"referenceId":\s*"([^"]+)"[^}]*}/g;
188
+ let match;
189
+
190
+ while ((match = contentReferenceRegex.exec(content)) !== null) {
191
+ try {
192
+ const refObject = JSON.parse(match[0]);
193
+ if (refObject.type === 'content_reference' && refObject.referenceId) {
194
+ const reference: ContentReference = {
195
+ referenceId: refObject.referenceId,
196
+ state: refObject.state || 'active',
197
+ preview: refObject.preview || '',
198
+ metadata: refObject.metadata || {},
199
+ createdAt: new Date(refObject.createdAt || Date.now()),
200
+ format: 'ref://{id}' as const
201
+ };
202
+
203
+ references.push({
204
+ reference,
205
+ position: match.index,
206
+ originalText: match[0]
207
+ });
208
+ }
209
+ } catch (error) {
210
+ this.logger.warn('Failed to parse content reference:', error);
211
+ }
212
+ }
213
+
214
+ const plainRefRegex = /ref:\/\/([A-Za-z0-9_-]{43})|(?:^|\s)([A-Za-z0-9_-]{43})(?=\s|$)/g;
215
+ let plainMatch;
216
+
217
+ while ((plainMatch = plainRefRegex.exec(content)) !== null) {
218
+ const referenceId = plainMatch[1] || plainMatch[2];
219
+ if (referenceId && this.isValidReferenceId(referenceId)) {
220
+ plainReferences.push({
221
+ referenceId,
222
+ position: plainMatch.index,
223
+ originalText: plainMatch[0]
224
+ });
225
+ }
226
+ }
227
+
228
+ return {
229
+ hasReferences: references.length > 0 || plainReferences.length > 0,
230
+ references,
231
+ plainReferences
232
+ };
233
+ }
234
+
235
+ /**
236
+ * Create a preview from content buffer
237
+ */
238
+ private createPreviewFromContent(content: Buffer, contentType: string): string {
239
+ const maxLength = 200;
240
+ let preview = content.toString('utf8', 0, Math.min(content.length, maxLength * 2));
241
+
242
+ if (contentType === 'html') {
243
+ preview = preview.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ');
244
+ } else if (contentType === 'json') {
245
+ try {
246
+ const parsed = JSON.parse(preview);
247
+ preview = JSON.stringify(parsed, null, 0);
248
+ } catch {
249
+ // Keep original if not valid JSON
250
+ }
251
+ }
252
+
253
+ preview = preview.trim();
254
+ if (preview.length > maxLength) {
255
+ preview = preview.substring(0, maxLength) + '...';
256
+ }
257
+
258
+ return preview || '[Binary content]';
259
+ }
260
+
261
+ /**
262
+ * Validate reference ID format
263
+ */
264
+ private isValidReferenceId(id: string): boolean {
265
+ if (!id || typeof id !== 'string') {
266
+ return false;
267
+ }
268
+
269
+ if (id.length !== 43) {
270
+ return false;
271
+ }
272
+
273
+ return /^[A-Za-z0-9_-]+$/.test(id);
274
+ }
275
+
276
+ /**
277
+ * Get reference context statistics
278
+ */
279
+ getContextStats() {
280
+ return this.contextManager.getContextStats();
281
+ }
282
+
283
+ /**
284
+ * Validate all references in context
285
+ */
286
+ async validateAllReferences() {
287
+ return await this.contextManager.validateReferences();
288
+ }
289
+
290
+ /**
291
+ * Clean up old references
292
+ */
293
+ cleanupOldReferences(maxAgeMs?: number) {
294
+ return this.contextManager.cleanupOldReferences(maxAgeMs);
295
+ }
296
+ }
@@ -23,6 +23,7 @@ import type { IStateManager } from '@hashgraphonline/standards-agent-kit';
23
23
  import { PrivateKey } from '@hashgraph/sdk';
24
24
  import { getSystemMessage } from './config/system-message';
25
25
  import type { MCPServerConfig } from './mcp/types';
26
+ import { ContentStoreManager } from './services/ContentStoreManager';
26
27
 
27
28
  const DEFAULT_MODEL_NAME = 'gpt-4o';
28
29
  const DEFAULT_TEMPERATURE = 0.1;
@@ -68,6 +69,7 @@ export class ConversationalAgent {
68
69
  public stateManager: IStateManager;
69
70
  private options: ConversationalAgentOptions;
70
71
  private logger: Logger;
72
+ private contentStoreManager?: ContentStoreManager;
71
73
 
72
74
  constructor(options: ConversationalAgentOptions) {
73
75
  this.options = options;
@@ -94,54 +96,24 @@ export class ConversationalAgent {
94
96
  network = DEFAULT_NETWORK,
95
97
  openAIApiKey,
96
98
  openAIModelName = DEFAULT_MODEL_NAME,
97
- verbose = false,
98
- operationalMode = DEFAULT_OPERATIONAL_MODE,
99
- userAccountId,
100
- customSystemMessagePreamble,
101
- customSystemMessagePostamble,
102
- additionalPlugins = [],
103
- mirrorNodeConfig,
104
- disableLogging,
105
- scheduleUserTransactionsInBytesMode,
106
99
  } = this.options;
107
100
 
108
- if (!accountId || !privateKey) {
109
- throw new Error('Account ID and private key are required');
110
- }
101
+ this.validateOptions(accountId, privateKey);
111
102
 
112
103
  try {
113
104
  const privateKeyInstance = await this.detectPrivateKeyType(
114
- accountId,
115
- privateKey,
105
+ accountId!,
106
+ privateKey!,
116
107
  network
117
108
  );
118
109
 
119
110
  const serverSigner = new ServerSigner(
120
- accountId,
111
+ accountId!,
121
112
  privateKeyInstance,
122
113
  network as 'testnet' | 'mainnet' | 'previewnet'
123
114
  );
124
115
 
125
- const standardPlugins = [
126
- this.hcs10Plugin,
127
- this.hcs2Plugin,
128
- this.inscribePlugin,
129
- this.hbarTransferPlugin,
130
- ];
131
-
132
- const corePlugins = getAllHederaCorePlugins();
133
-
134
- let allPlugins: BasePlugin[];
135
-
136
- if (this.options.enabledPlugins) {
137
- const enabledSet = new Set(this.options.enabledPlugins);
138
- const filteredPlugins = [...standardPlugins, ...corePlugins].filter(
139
- (plugin) => enabledSet.has(plugin.id)
140
- );
141
- allPlugins = [...filteredPlugins, ...additionalPlugins];
142
- } else {
143
- allPlugins = [...standardPlugins, ...corePlugins, ...additionalPlugins];
144
- }
116
+ const allPlugins = this.preparePlugins();
145
117
 
146
118
  const llm = new ChatOpenAI({
147
119
  apiKey: openAIApiKey,
@@ -149,59 +121,16 @@ export class ConversationalAgent {
149
121
  temperature: DEFAULT_TEMPERATURE,
150
122
  });
151
123
 
152
- this.agent = createAgent({
153
- framework: 'langchain',
154
- signer: serverSigner,
155
- execution: {
156
- mode: operationalMode === 'autonomous' ? 'direct' : 'bytes',
157
- operationalMode: operationalMode,
158
- ...(userAccountId && { userAccountId }),
159
- ...(scheduleUserTransactionsInBytesMode !== undefined && {
160
- scheduleUserTransactions: scheduleUserTransactionsInBytesMode,
161
- }),
162
- },
163
- ai: {
164
- provider: new LangChainProvider(llm),
165
- temperature: DEFAULT_TEMPERATURE,
166
- },
167
- filtering: {
168
- toolPredicate: (tool) => {
169
- if (tool.name === 'hedera-account-transfer-hbar') return false;
170
- if (this.options.toolFilter && !this.options.toolFilter(tool)) {
171
- return false;
172
- }
173
- return true;
174
- },
175
- },
176
- messaging: {
177
- systemPreamble:
178
- customSystemMessagePreamble || getSystemMessage(accountId),
179
- ...(customSystemMessagePostamble && { systemPostamble: customSystemMessagePostamble }),
180
- conciseMode: true,
181
- },
182
- extensions: {
183
- plugins: allPlugins,
184
- ...(mirrorNodeConfig && {
185
- mirrorConfig: mirrorNodeConfig as Record<string, unknown>,
186
- }),
187
- },
188
- ...(this.options.mcpServers && {
189
- mcp: {
190
- servers: this.options.mcpServers,
191
- autoConnect: true,
192
- },
193
- }),
194
- debug: {
195
- verbose,
196
- silent: disableLogging ?? false,
197
- },
198
- });
124
+ const agentConfig = this.createAgentConfig(serverSigner, llm, allPlugins);
125
+ this.agent = createAgent(agentConfig);
199
126
 
200
- const hcs10 = allPlugins.find((p) => p.id === 'hcs-10');
201
- if (hcs10) {
202
- (hcs10 as { appConfig?: Record<string, unknown> }).appConfig = {
203
- stateManager: this.stateManager,
204
- };
127
+ this.configureHCS10Plugin(allPlugins);
128
+
129
+ // Initialize ContentStoreManager if MCP servers are configured
130
+ if (this.options.mcpServers && this.options.mcpServers.length > 0) {
131
+ this.contentStoreManager = new ContentStoreManager();
132
+ await this.contentStoreManager.initialize();
133
+ this.logger.info('ContentStoreManager initialized for MCP content reference support');
205
134
  }
206
135
 
207
136
  await this.agent.boot();
@@ -266,11 +195,13 @@ export class ConversationalAgent {
266
195
  throw new Error('Agent not initialized. Call initialize() first.');
267
196
  }
268
197
 
269
- const messages = chatHistory.map((msg) =>
270
- msg.type === 'human'
271
- ? new HumanMessage(msg.content)
272
- : new AIMessage(msg.content)
273
- );
198
+ const messages = chatHistory.map((msg) => {
199
+ if (msg.type === 'human') {
200
+ return new HumanMessage(msg.content);
201
+ } else {
202
+ return new AIMessage(msg.content);
203
+ }
204
+ });
274
205
 
275
206
  const context: ConversationContext = {
276
207
  messages,
@@ -279,6 +210,135 @@ export class ConversationalAgent {
279
210
  return this.agent.chat(message, context);
280
211
  }
281
212
 
213
+ /**
214
+ * Validates initialization options and throws if required fields are missing.
215
+ *
216
+ * @param accountId - The Hedera account ID
217
+ * @param privateKey - The private key for the account
218
+ * @throws {Error} If required fields are missing
219
+ */
220
+ private validateOptions(accountId?: string, privateKey?: string): void {
221
+ if (!accountId || !privateKey) {
222
+ throw new Error('Account ID and private key are required');
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Prepares the list of plugins to use based on configuration.
228
+ *
229
+ * @returns Array of plugins to initialize with the agent
230
+ */
231
+ private preparePlugins(): BasePlugin[] {
232
+ const { additionalPlugins = [], enabledPlugins } = this.options;
233
+
234
+ const standardPlugins = [
235
+ this.hcs10Plugin,
236
+ this.hcs2Plugin,
237
+ this.inscribePlugin,
238
+ this.hbarTransferPlugin,
239
+ ];
240
+
241
+ const corePlugins = getAllHederaCorePlugins();
242
+
243
+ if (enabledPlugins) {
244
+ const enabledSet = new Set(enabledPlugins);
245
+ const filteredPlugins = [...standardPlugins, ...corePlugins].filter(
246
+ (plugin) => enabledSet.has(plugin.id)
247
+ );
248
+ return [...filteredPlugins, ...additionalPlugins];
249
+ }
250
+
251
+ return [...standardPlugins, ...corePlugins, ...additionalPlugins];
252
+ }
253
+
254
+ /**
255
+ * Creates the agent configuration object.
256
+ *
257
+ * @param serverSigner - The server signer instance
258
+ * @param llm - The language model instance
259
+ * @param allPlugins - Array of plugins to use
260
+ * @returns Configuration object for creating the agent
261
+ */
262
+ private createAgentConfig(
263
+ serverSigner: ServerSigner,
264
+ llm: ChatOpenAI,
265
+ allPlugins: BasePlugin[]
266
+ ): Parameters<typeof createAgent>[0] {
267
+ const {
268
+ operationalMode = DEFAULT_OPERATIONAL_MODE,
269
+ userAccountId,
270
+ scheduleUserTransactionsInBytesMode,
271
+ customSystemMessagePreamble,
272
+ customSystemMessagePostamble,
273
+ verbose = false,
274
+ mirrorNodeConfig,
275
+ disableLogging,
276
+ accountId = '',
277
+ } = this.options;
278
+
279
+ return {
280
+ framework: 'langchain',
281
+ signer: serverSigner,
282
+ execution: {
283
+ mode: operationalMode === 'autonomous' ? 'direct' : 'bytes',
284
+ operationalMode: operationalMode,
285
+ ...(userAccountId && { userAccountId }),
286
+ ...(scheduleUserTransactionsInBytesMode !== undefined && {
287
+ scheduleUserTransactions: scheduleUserTransactionsInBytesMode,
288
+ }),
289
+ },
290
+ ai: {
291
+ provider: new LangChainProvider(llm),
292
+ temperature: DEFAULT_TEMPERATURE,
293
+ },
294
+ filtering: {
295
+ toolPredicate: (tool) => {
296
+ if (tool.name === 'hedera-account-transfer-hbar') return false;
297
+ if (this.options.toolFilter && !this.options.toolFilter(tool)) {
298
+ return false;
299
+ }
300
+ return true;
301
+ },
302
+ },
303
+ messaging: {
304
+ systemPreamble:
305
+ customSystemMessagePreamble || getSystemMessage(accountId),
306
+ ...(customSystemMessagePostamble && { systemPostamble: customSystemMessagePostamble }),
307
+ conciseMode: true,
308
+ },
309
+ extensions: {
310
+ plugins: allPlugins,
311
+ ...(mirrorNodeConfig && {
312
+ mirrorConfig: mirrorNodeConfig as Record<string, unknown>,
313
+ }),
314
+ },
315
+ ...(this.options.mcpServers && {
316
+ mcp: {
317
+ servers: this.options.mcpServers,
318
+ autoConnect: true,
319
+ },
320
+ }),
321
+ debug: {
322
+ verbose,
323
+ silent: disableLogging ?? false,
324
+ },
325
+ };
326
+ }
327
+
328
+ /**
329
+ * Configures the HCS-10 plugin with the state manager.
330
+ *
331
+ * @param allPlugins - Array of all plugins
332
+ */
333
+ private configureHCS10Plugin(allPlugins: BasePlugin[]): void {
334
+ const hcs10 = allPlugins.find((p) => p.id === 'hcs-10');
335
+ if (hcs10) {
336
+ (hcs10 as { appConfig?: Record<string, unknown> }).appConfig = {
337
+ stateManager: this.stateManager,
338
+ };
339
+ }
340
+ }
341
+
282
342
  /**
283
343
  * Create a ConversationalAgent with specific plugins enabled
284
344
  */
@@ -408,4 +468,18 @@ export class ConversationalAgent {
408
468
  return PrivateKey.fromStringED25519(privateKey);
409
469
  }
410
470
  }
471
+
472
+ /**
473
+ * Clean up resources
474
+ */
475
+ async cleanup(): Promise<void> {
476
+ if (this.contentStoreManager) {
477
+ await this.contentStoreManager.dispose();
478
+ this.logger.info('ContentStoreManager cleaned up');
479
+ }
480
+ // Agent cleanup if needed
481
+ if (this.agent) {
482
+ // Add agent cleanup if available
483
+ }
484
+ }
411
485
  }