@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.
- package/dist/cjs/base-agent.d.ts +6 -0
- package/dist/cjs/context/ReferenceContextManager.d.ts +84 -0
- package/dist/cjs/context/ReferenceResponseProcessor.d.ts +76 -0
- package/dist/cjs/conversational-agent.d.ts +34 -0
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/langchain-agent.d.ts +1 -0
- package/dist/cjs/mcp/ContentProcessor.d.ts +37 -0
- package/dist/cjs/mcp/MCPClientManager.d.ts +19 -1
- package/dist/cjs/memory/ContentStorage.d.ts +205 -0
- package/dist/cjs/memory/MemoryWindow.d.ts +114 -0
- package/dist/cjs/memory/ReferenceIdGenerator.d.ts +45 -0
- package/dist/cjs/memory/SmartMemoryManager.d.ts +201 -0
- package/dist/cjs/memory/TokenCounter.d.ts +61 -0
- package/dist/cjs/memory/index.d.ts +7 -0
- package/dist/cjs/plugins/hbar-transfer/TransferHbarTool.d.ts +18 -0
- package/dist/cjs/services/ContentStoreManager.d.ts +54 -0
- package/dist/cjs/types/content-reference.d.ts +213 -0
- package/dist/cjs/types/index.d.ts +4 -0
- package/dist/esm/index12.js +15 -2
- package/dist/esm/index12.js.map +1 -1
- package/dist/esm/index14.js +119 -95
- package/dist/esm/index14.js.map +1 -1
- package/dist/esm/index15.js +159 -114
- package/dist/esm/index15.js.map +1 -1
- package/dist/esm/index16.js +122 -81
- package/dist/esm/index16.js.map +1 -1
- package/dist/esm/index17.js +236 -0
- package/dist/esm/index17.js.map +1 -0
- package/dist/esm/index18.js +95 -0
- package/dist/esm/index18.js.map +1 -0
- package/dist/esm/index19.js +663 -0
- package/dist/esm/index19.js.map +1 -0
- package/dist/esm/index2.js +3 -1
- package/dist/esm/index2.js.map +1 -1
- package/dist/esm/index20.js +233 -0
- package/dist/esm/index20.js.map +1 -0
- package/dist/esm/index21.js +182 -0
- package/dist/esm/index21.js.map +1 -0
- package/dist/esm/index22.js +126 -0
- package/dist/esm/index22.js.map +1 -0
- package/dist/esm/index23.js +68 -0
- package/dist/esm/index23.js.map +1 -0
- package/dist/esm/index24.js +38 -0
- package/dist/esm/index24.js.map +1 -0
- package/dist/esm/index6.js +143 -84
- package/dist/esm/index6.js.map +1 -1
- package/dist/esm/index7.js.map +1 -1
- package/dist/esm/index8.js +69 -5
- package/dist/esm/index8.js.map +1 -1
- package/dist/types/base-agent.d.ts +6 -0
- package/dist/types/context/ReferenceContextManager.d.ts +84 -0
- package/dist/types/context/ReferenceResponseProcessor.d.ts +76 -0
- package/dist/types/conversational-agent.d.ts +34 -0
- package/dist/types/langchain-agent.d.ts +1 -0
- package/dist/types/mcp/ContentProcessor.d.ts +37 -0
- package/dist/types/mcp/MCPClientManager.d.ts +19 -1
- package/dist/types/memory/ContentStorage.d.ts +205 -0
- package/dist/types/memory/MemoryWindow.d.ts +114 -0
- package/dist/types/memory/ReferenceIdGenerator.d.ts +45 -0
- package/dist/types/memory/SmartMemoryManager.d.ts +201 -0
- package/dist/types/memory/TokenCounter.d.ts +61 -0
- package/dist/types/memory/index.d.ts +7 -0
- package/dist/types/plugins/hbar-transfer/TransferHbarTool.d.ts +18 -0
- package/dist/types/services/ContentStoreManager.d.ts +54 -0
- package/dist/types/types/content-reference.d.ts +213 -0
- package/dist/types/types/index.d.ts +4 -0
- package/package.json +5 -3
- package/src/base-agent.ts +6 -0
- package/src/context/ReferenceContextManager.ts +345 -0
- package/src/context/ReferenceResponseProcessor.ts +296 -0
- package/src/conversational-agent.ts +166 -92
- package/src/langchain-agent.ts +89 -2
- package/src/mcp/ContentProcessor.ts +317 -0
- package/src/mcp/MCPClientManager.ts +61 -1
- package/src/mcp/adapters/langchain.ts +9 -4
- package/src/memory/ContentStorage.ts +954 -0
- package/src/memory/MemoryWindow.ts +247 -0
- package/src/memory/ReferenceIdGenerator.ts +84 -0
- package/src/memory/SmartMemoryManager.ts +323 -0
- package/src/memory/TokenCounter.ts +152 -0
- package/src/memory/index.ts +8 -0
- package/src/plugins/hbar-transfer/TransferHbarTool.ts +19 -1
- package/src/plugins/hcs-10/HCS10Plugin.ts +5 -4
- package/src/services/ContentStoreManager.ts +199 -0
- package/src/types/content-reference.ts +281 -0
- 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
|
-
|
|
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
|
|
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.
|
|
153
|
-
|
|
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
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|
-
|
|
272
|
-
|
|
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
|
}
|