@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.
Files changed (117) hide show
  1. package/bin/conversational-agent-cli.js +30 -0
  2. package/cli/readme.md +181 -0
  3. package/dist/cjs/base-agent.d.ts +3 -1
  4. package/dist/cjs/conversational-agent.d.ts +64 -13
  5. package/dist/cjs/index.cjs +1 -1
  6. package/dist/cjs/index.cjs.map +1 -1
  7. package/dist/cjs/index.d.ts +6 -3
  8. package/dist/cjs/langchain-agent.d.ts +11 -0
  9. package/dist/cjs/memory/SmartMemoryManager.d.ts +65 -22
  10. package/dist/cjs/memory/TokenCounter.d.ts +1 -1
  11. package/dist/cjs/memory/index.d.ts +1 -1
  12. package/dist/cjs/plugins/hbar/AirdropToolWrapper.d.ts +43 -0
  13. package/dist/{types/plugins/hbar-transfer/HbarTransferPlugin.d.ts → cjs/plugins/hbar/HbarPlugin.d.ts} +2 -1
  14. package/dist/{types/plugins/hbar-transfer → cjs/plugins/hbar}/TransferHbarTool.d.ts +1 -1
  15. package/dist/cjs/plugins/hbar/index.d.ts +3 -0
  16. package/dist/cjs/plugins/index.d.ts +2 -1
  17. package/dist/cjs/services/EntityResolver.d.ts +26 -0
  18. package/dist/cjs/tools/EntityResolverTool.d.ts +104 -0
  19. package/dist/cjs/types/inscription.d.ts +37 -0
  20. package/dist/esm/index.js +16 -2
  21. package/dist/esm/index.js.map +1 -1
  22. package/dist/esm/index12.js +121 -46
  23. package/dist/esm/index12.js.map +1 -1
  24. package/dist/esm/index13.js +177 -13
  25. package/dist/esm/index13.js.map +1 -1
  26. package/dist/esm/index14.js +599 -100
  27. package/dist/esm/index14.js.map +1 -1
  28. package/dist/esm/index15.js +426 -9
  29. package/dist/esm/index15.js.map +1 -1
  30. package/dist/esm/index16.js +119 -160
  31. package/dist/esm/index16.js.map +1 -1
  32. package/dist/esm/index17.js +140 -150
  33. package/dist/esm/index17.js.map +1 -1
  34. package/dist/esm/index18.js +44 -231
  35. package/dist/esm/index18.js.map +1 -1
  36. package/dist/esm/index19.js +86 -643
  37. package/dist/esm/index19.js.map +1 -1
  38. package/dist/esm/index2.js +22 -13
  39. package/dist/esm/index2.js.map +1 -1
  40. package/dist/esm/index20.js +20 -230
  41. package/dist/esm/index20.js.map +1 -1
  42. package/dist/esm/index21.js +9 -179
  43. package/dist/esm/index21.js.map +1 -1
  44. package/dist/esm/index22.js +140 -89
  45. package/dist/esm/index22.js.map +1 -1
  46. package/dist/esm/index23.js +141 -81
  47. package/dist/esm/index23.js.map +1 -1
  48. package/dist/esm/index24.js +4 -4
  49. package/dist/esm/index24.js.map +1 -1
  50. package/dist/esm/index25.js +0 -8
  51. package/dist/esm/index25.js.map +1 -1
  52. package/dist/esm/index26.js +95 -0
  53. package/dist/esm/index26.js.map +1 -0
  54. package/dist/esm/index27.js +242 -0
  55. package/dist/esm/index27.js.map +1 -0
  56. package/dist/esm/index5.js +32 -19
  57. package/dist/esm/index5.js.map +1 -1
  58. package/dist/esm/index6.js +276 -37
  59. package/dist/esm/index6.js.map +1 -1
  60. package/dist/esm/index7.js +2 -2
  61. package/dist/esm/index7.js.map +1 -1
  62. package/dist/esm/index8.js +124 -18
  63. package/dist/esm/index8.js.map +1 -1
  64. package/dist/types/base-agent.d.ts +3 -1
  65. package/dist/types/conversational-agent.d.ts +64 -13
  66. package/dist/types/index.d.ts +6 -3
  67. package/dist/types/langchain-agent.d.ts +11 -0
  68. package/dist/types/memory/SmartMemoryManager.d.ts +65 -22
  69. package/dist/types/memory/TokenCounter.d.ts +1 -1
  70. package/dist/types/memory/index.d.ts +1 -1
  71. package/dist/types/plugins/hbar/AirdropToolWrapper.d.ts +43 -0
  72. package/dist/{cjs/plugins/hbar-transfer/HbarTransferPlugin.d.ts → types/plugins/hbar/HbarPlugin.d.ts} +2 -1
  73. package/dist/{cjs/plugins/hbar-transfer → types/plugins/hbar}/TransferHbarTool.d.ts +1 -1
  74. package/dist/types/plugins/hbar/index.d.ts +3 -0
  75. package/dist/types/plugins/index.d.ts +2 -1
  76. package/dist/types/services/EntityResolver.d.ts +26 -0
  77. package/dist/types/tools/EntityResolverTool.d.ts +104 -0
  78. package/dist/types/types/inscription.d.ts +37 -0
  79. package/package.json +13 -4
  80. package/src/base-agent.ts +14 -9
  81. package/src/config/system-message.ts +11 -2
  82. package/src/context/ReferenceContextManager.ts +10 -5
  83. package/src/context/ReferenceResponseProcessor.ts +3 -4
  84. package/src/conversational-agent.ts +372 -57
  85. package/src/index.ts +19 -3
  86. package/src/langchain/ContentAwareAgentExecutor.ts +0 -1
  87. package/src/langchain-agent.ts +168 -33
  88. package/src/mcp/ContentProcessor.ts +11 -3
  89. package/src/mcp/adapters/langchain.ts +1 -10
  90. package/src/memory/ContentStorage.ts +2 -55
  91. package/src/memory/MemoryWindow.ts +4 -17
  92. package/src/memory/ReferenceIdGenerator.ts +4 -8
  93. package/src/memory/SmartMemoryManager.ts +375 -47
  94. package/src/memory/TokenCounter.ts +15 -22
  95. package/src/memory/index.ts +1 -1
  96. package/src/plugins/hbar/AirdropToolWrapper.ts +157 -0
  97. package/src/plugins/hbar/HbarPlugin.ts +86 -0
  98. package/src/plugins/{hbar-transfer → hbar}/TransferHbarTool.ts +3 -3
  99. package/src/plugins/hbar/index.ts +3 -0
  100. package/src/plugins/hcs-10/HCS10Plugin.ts +44 -14
  101. package/src/plugins/index.ts +2 -1
  102. package/src/services/ContentStoreManager.ts +0 -3
  103. package/src/services/EntityResolver.ts +135 -0
  104. package/src/tools/EntityResolverTool.ts +170 -0
  105. package/src/types/content-reference.ts +8 -8
  106. package/src/types/index.ts +0 -1
  107. package/src/types/inscription.ts +40 -0
  108. package/dist/cjs/plugins/hbar-transfer/index.d.ts +0 -1
  109. package/dist/types/plugins/hbar-transfer/index.d.ts +0 -1
  110. package/src/plugins/hbar-transfer/HbarTransferPlugin.ts +0 -66
  111. package/src/plugins/hbar-transfer/index.ts +0 -1
  112. /package/dist/cjs/plugins/{hbar-transfer → hbar}/AccountBuilder.d.ts +0 -0
  113. /package/dist/cjs/plugins/{hbar-transfer → hbar}/types.d.ts +0 -0
  114. /package/dist/types/plugins/{hbar-transfer → hbar}/AccountBuilder.d.ts +0 -0
  115. /package/dist/types/plugins/{hbar-transfer → hbar}/types.d.ts +0 -0
  116. /package/src/plugins/{hbar-transfer → hbar}/AccountBuilder.ts +0 -0
  117. /package/src/plugins/{hbar-transfer → hbar}/types.ts +0 -0
@@ -0,0 +1,242 @@
1
+ class MCPContentProcessor {
2
+ constructor(contentStorage, logger) {
3
+ this.contentStorage = contentStorage;
4
+ this.logger = logger;
5
+ }
6
+ analyzeResponse(response) {
7
+ const contents = [];
8
+ let totalSize = 0;
9
+ this.extractContentFromResponse(response, contents);
10
+ totalSize = contents.reduce((sum, content) => sum + content.sizeBytes, 0);
11
+ const largestContentSize = contents.reduce((max, content) => Math.max(max, content.sizeBytes), 0);
12
+ const shouldProcess = contents.some(
13
+ (content) => this.contentStorage.shouldUseReference(
14
+ typeof content.content === "string" ? content.content : JSON.stringify(content.content)
15
+ )
16
+ );
17
+ return {
18
+ shouldProcess,
19
+ contents,
20
+ totalSize,
21
+ largestContentSize
22
+ };
23
+ }
24
+ async processResponse(response, serverName, toolName) {
25
+ try {
26
+ const analysis = this.analyzeResponse(response);
27
+ if (!analysis.shouldProcess) {
28
+ return {
29
+ content: response,
30
+ wasProcessed: false
31
+ };
32
+ }
33
+ const processedResponse = await this.createReferencedResponse(
34
+ response,
35
+ analysis,
36
+ serverName,
37
+ toolName
38
+ );
39
+ return processedResponse;
40
+ } catch (error) {
41
+ this.logger.error("Error processing MCP response:", error);
42
+ return {
43
+ content: response,
44
+ wasProcessed: false,
45
+ errors: [error instanceof Error ? error.message : "Unknown processing error"]
46
+ };
47
+ }
48
+ }
49
+ extractContentFromResponse(obj, contents) {
50
+ if (obj === null || obj === void 0) {
51
+ return;
52
+ }
53
+ if (Array.isArray(obj)) {
54
+ obj.forEach((item) => this.extractContentFromResponse(item, contents));
55
+ return;
56
+ }
57
+ if (typeof obj === "object") {
58
+ const record = obj;
59
+ if (record.type === "text" && typeof record.text === "string") {
60
+ contents.push({
61
+ content: record.text,
62
+ type: "text",
63
+ sizeBytes: Buffer.byteLength(record.text, "utf8"),
64
+ mimeType: this.detectMimeType(record.text)
65
+ });
66
+ return;
67
+ }
68
+ if (record.type === "image" && typeof record.data === "string") {
69
+ contents.push({
70
+ content: record.data,
71
+ type: "image",
72
+ sizeBytes: Math.ceil(record.data.length * 0.75),
73
+ mimeType: record.mimeType || "image/jpeg"
74
+ });
75
+ return;
76
+ }
77
+ if (record.type === "resource" && record.resource) {
78
+ const resourceStr = JSON.stringify(record.resource);
79
+ contents.push({
80
+ content: resourceStr,
81
+ type: "resource",
82
+ sizeBytes: Buffer.byteLength(resourceStr, "utf8"),
83
+ mimeType: "application/json"
84
+ });
85
+ return;
86
+ }
87
+ Object.values(record).forEach((value) => this.extractContentFromResponse(value, contents));
88
+ return;
89
+ }
90
+ if (typeof obj === "string") {
91
+ if (obj.length > 1e3) {
92
+ contents.push({
93
+ content: obj,
94
+ type: "text",
95
+ sizeBytes: Buffer.byteLength(obj, "utf8"),
96
+ mimeType: this.detectMimeType(obj)
97
+ });
98
+ }
99
+ }
100
+ }
101
+ async createReferencedResponse(originalResponse, analysis, serverName, toolName) {
102
+ const processedResponse = this.deepClone(originalResponse);
103
+ const errors = [];
104
+ let referenceCreated = false;
105
+ let totalReferenceSize = 0;
106
+ for (const contentInfo of analysis.contents) {
107
+ if (this.contentStorage.shouldUseReference(
108
+ typeof contentInfo.content === "string" ? contentInfo.content : JSON.stringify(contentInfo.content)
109
+ )) {
110
+ try {
111
+ const contentBuffer = Buffer.from(
112
+ typeof contentInfo.content === "string" ? contentInfo.content : JSON.stringify(contentInfo.content),
113
+ "utf8"
114
+ );
115
+ const contentType = this.mapMimeTypeToContentType(contentInfo.mimeType);
116
+ const metadata = {
117
+ contentType,
118
+ source: "mcp_tool",
119
+ mcpToolName: `${serverName}::${toolName}`,
120
+ tags: ["mcp_response", serverName, toolName]
121
+ };
122
+ if (contentInfo.mimeType !== void 0) {
123
+ metadata.mimeType = contentInfo.mimeType;
124
+ }
125
+ const reference = await this.contentStorage.storeContentIfLarge(
126
+ contentBuffer,
127
+ metadata
128
+ );
129
+ if (reference) {
130
+ this.replaceContentInResponse(
131
+ processedResponse,
132
+ contentInfo.content,
133
+ this.createLightweightReference(reference)
134
+ );
135
+ referenceCreated = true;
136
+ totalReferenceSize += contentBuffer.length;
137
+ }
138
+ } catch (error) {
139
+ errors.push(`Failed to create reference: ${error instanceof Error ? error.message : "Unknown error"}`);
140
+ }
141
+ }
142
+ }
143
+ const result = {
144
+ content: processedResponse,
145
+ wasProcessed: true,
146
+ referenceCreated,
147
+ originalSize: totalReferenceSize
148
+ };
149
+ if (errors.length > 0) {
150
+ result.errors = errors;
151
+ }
152
+ return result;
153
+ }
154
+ createLightweightReference(reference) {
155
+ return {
156
+ type: "content_reference",
157
+ referenceId: reference.referenceId,
158
+ preview: reference.preview,
159
+ size: reference.metadata.sizeBytes,
160
+ contentType: reference.metadata.contentType,
161
+ format: "ref://{id}",
162
+ _isReference: true
163
+ };
164
+ }
165
+ replaceContentInResponse(obj, oldContent, newContent) {
166
+ if (obj === null || obj === void 0) {
167
+ return;
168
+ }
169
+ if (Array.isArray(obj)) {
170
+ for (let i = 0; i < obj.length; i++) {
171
+ if (obj[i] === oldContent) {
172
+ obj[i] = newContent;
173
+ } else {
174
+ this.replaceContentInResponse(obj[i], oldContent, newContent);
175
+ }
176
+ }
177
+ return;
178
+ }
179
+ if (typeof obj === "object") {
180
+ const record = obj;
181
+ if (record.type === "text" && record.text === oldContent) {
182
+ for (const key of Object.keys(record)) {
183
+ delete record[key];
184
+ }
185
+ for (const key of Object.keys(newContent)) {
186
+ record[key] = newContent[key];
187
+ }
188
+ return;
189
+ }
190
+ for (const key in record) {
191
+ if (record[key] === oldContent) {
192
+ record[key] = newContent;
193
+ } else {
194
+ this.replaceContentInResponse(record[key], oldContent, newContent);
195
+ }
196
+ }
197
+ }
198
+ }
199
+ detectMimeType(content) {
200
+ if (content.trim().startsWith("{") || content.trim().startsWith("[")) {
201
+ return "application/json";
202
+ }
203
+ if (content.includes("<html>") || content.includes("<!DOCTYPE")) {
204
+ return "text/html";
205
+ }
206
+ if (content.includes("# ") || content.includes("## ")) {
207
+ return "text/markdown";
208
+ }
209
+ return "text/plain";
210
+ }
211
+ mapMimeTypeToContentType(mimeType) {
212
+ if (!mimeType) return "text";
213
+ if (mimeType.startsWith("text/plain")) return "text";
214
+ if (mimeType === "application/json") return "json";
215
+ if (mimeType === "text/html") return "html";
216
+ if (mimeType === "text/markdown") return "markdown";
217
+ if (mimeType.startsWith("text/")) return "text";
218
+ return "binary";
219
+ }
220
+ deepClone(obj) {
221
+ if (obj === null || typeof obj !== "object") {
222
+ return obj;
223
+ }
224
+ if (obj instanceof Date) {
225
+ return new Date(obj.getTime());
226
+ }
227
+ if (Array.isArray(obj)) {
228
+ return obj.map((item) => this.deepClone(item));
229
+ }
230
+ const cloned = {};
231
+ for (const key in obj) {
232
+ if (obj.hasOwnProperty(key)) {
233
+ cloned[key] = this.deepClone(obj[key]);
234
+ }
235
+ }
236
+ return cloned;
237
+ }
238
+ }
239
+ export {
240
+ MCPContentProcessor
241
+ };
242
+ //# sourceMappingURL=index27.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index27.js","sources":["../../src/mcp/ContentProcessor.ts"],"sourcesContent":["import type { ContentType, ContentSource } from '../types/content-reference';\nimport type { ContentStorage } from '../memory/ContentStorage';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\nexport interface MCPResponseContent {\n content: unknown;\n type: 'text' | 'image' | 'resource' | 'text[]' | 'image[]';\n sizeBytes: number;\n mimeType?: string;\n}\n\nexport interface ProcessedResponse {\n content: unknown;\n wasProcessed: boolean;\n referenceCreated?: boolean;\n referenceId?: string;\n originalSize?: number;\n errors?: string[];\n}\n\nexport interface ContentAnalysis {\n shouldProcess: boolean;\n contents: MCPResponseContent[];\n totalSize: number;\n largestContentSize: number;\n}\n\nexport class MCPContentProcessor {\n private contentStorage: ContentStorage;\n private logger: Logger;\n\n constructor(contentStorage: ContentStorage, logger: Logger) {\n this.contentStorage = contentStorage;\n this.logger = logger;\n }\n\n analyzeResponse(response: unknown): ContentAnalysis {\n const contents: MCPResponseContent[] = [];\n let totalSize = 0;\n\n this.extractContentFromResponse(response, contents);\n\n totalSize = contents.reduce((sum, content) => sum + content.sizeBytes, 0);\n const largestContentSize = contents.reduce((max, content) => \n Math.max(max, content.sizeBytes), 0);\n\n const shouldProcess = contents.some(content => \n this.contentStorage.shouldUseReference(\n typeof content.content === 'string' \n ? content.content \n : JSON.stringify(content.content)\n )\n );\n\n return {\n shouldProcess,\n contents,\n totalSize,\n largestContentSize\n };\n }\n\n async processResponse(\n response: unknown,\n serverName: string,\n toolName: string\n ): Promise<ProcessedResponse> {\n try {\n const analysis = this.analyzeResponse(response);\n \n if (!analysis.shouldProcess) {\n return {\n content: response,\n wasProcessed: false\n };\n }\n\n const processedResponse = await this.createReferencedResponse(\n response,\n analysis,\n serverName,\n toolName\n );\n\n return processedResponse;\n } catch (error) {\n this.logger.error('Error processing MCP response:', error);\n return {\n content: response,\n wasProcessed: false,\n errors: [error instanceof Error ? error.message : 'Unknown processing error']\n };\n }\n }\n\n private extractContentFromResponse(obj: unknown, contents: MCPResponseContent[]): void {\n if (obj === null || obj === undefined) {\n return;\n }\n\n if (Array.isArray(obj)) {\n obj.forEach(item => this.extractContentFromResponse(item, contents));\n return;\n }\n\n if (typeof obj === 'object') {\n const record = obj as Record<string, unknown>;\n \n if (record.type === 'text' && typeof record.text === 'string') {\n contents.push({\n content: record.text,\n type: 'text',\n sizeBytes: Buffer.byteLength(record.text, 'utf8'),\n mimeType: this.detectMimeType(record.text as string)\n });\n return;\n }\n\n if (record.type === 'image' && typeof record.data === 'string') {\n contents.push({\n content: record.data,\n type: 'image',\n sizeBytes: Math.ceil(record.data.length * 0.75),\n mimeType: record.mimeType as string || 'image/jpeg'\n });\n return;\n }\n\n if (record.type === 'resource' && record.resource) {\n const resourceStr = JSON.stringify(record.resource);\n contents.push({\n content: resourceStr,\n type: 'resource',\n sizeBytes: Buffer.byteLength(resourceStr, 'utf8'),\n mimeType: 'application/json'\n });\n return;\n }\n\n Object.values(record).forEach(value => \n this.extractContentFromResponse(value, contents));\n return;\n }\n\n if (typeof obj === 'string') {\n if (obj.length > 1000) {\n contents.push({\n content: obj,\n type: 'text',\n sizeBytes: Buffer.byteLength(obj, 'utf8'),\n mimeType: this.detectMimeType(obj)\n });\n }\n }\n }\n\n private async createReferencedResponse(\n originalResponse: unknown,\n analysis: ContentAnalysis,\n serverName: string,\n toolName: string\n ): Promise<ProcessedResponse> {\n const processedResponse = this.deepClone(originalResponse);\n const errors: string[] = [];\n let referenceCreated = false;\n let totalReferenceSize = 0;\n\n for (const contentInfo of analysis.contents) {\n if (this.contentStorage.shouldUseReference(\n typeof contentInfo.content === 'string' \n ? contentInfo.content \n : JSON.stringify(contentInfo.content)\n )) {\n try {\n const contentBuffer = Buffer.from(\n typeof contentInfo.content === 'string' \n ? contentInfo.content \n : JSON.stringify(contentInfo.content),\n 'utf8'\n );\n\n const contentType = this.mapMimeTypeToContentType(contentInfo.mimeType);\n \n const metadata: Parameters<typeof this.contentStorage.storeContentIfLarge>[1] = {\n contentType,\n source: 'mcp_tool' as ContentSource,\n mcpToolName: `${serverName}::${toolName}`,\n tags: ['mcp_response', serverName, toolName]\n };\n \n if (contentInfo.mimeType !== undefined) {\n metadata.mimeType = contentInfo.mimeType;\n }\n \n const reference = await this.contentStorage.storeContentIfLarge(\n contentBuffer,\n metadata\n );\n\n if (reference) {\n this.replaceContentInResponse(\n processedResponse,\n contentInfo.content,\n this.createLightweightReference(reference)\n );\n referenceCreated = true;\n totalReferenceSize += contentBuffer.length;\n }\n } catch (error) {\n errors.push(`Failed to create reference: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n }\n }\n\n const result: ProcessedResponse = {\n content: processedResponse,\n wasProcessed: true,\n referenceCreated,\n originalSize: totalReferenceSize\n };\n \n if (errors.length > 0) {\n result.errors = errors;\n }\n \n return result;\n }\n\n private createLightweightReference(reference: any): Record<string, unknown> {\n return {\n type: 'content_reference',\n referenceId: reference.referenceId,\n preview: reference.preview,\n size: reference.metadata.sizeBytes,\n contentType: reference.metadata.contentType,\n format: 'ref://{id}',\n _isReference: true\n };\n }\n\n private replaceContentInResponse(obj: unknown, oldContent: unknown, newContent: any): void {\n if (obj === null || obj === undefined) {\n return;\n }\n\n if (Array.isArray(obj)) {\n for (let i = 0; i < obj.length; i++) {\n if (obj[i] === oldContent) {\n obj[i] = newContent;\n } else {\n this.replaceContentInResponse(obj[i], oldContent, newContent);\n }\n }\n return;\n }\n\n if (typeof obj === 'object') {\n const record = obj as Record<string, unknown>;\n if (record.type === 'text' && record.text === oldContent) {\n for (const key of Object.keys(record)) {\n delete record[key];\n }\n for (const key of Object.keys(newContent)) {\n record[key] = newContent[key];\n }\n return;\n }\n for (const key in record) {\n if (record[key] === oldContent) {\n record[key] = newContent;\n } else {\n this.replaceContentInResponse(record[key], oldContent, newContent);\n }\n }\n }\n }\n\n private detectMimeType(content: string): string {\n if (content.trim().startsWith('{') || content.trim().startsWith('[')) {\n return 'application/json';\n }\n if (content.includes('<html>') || content.includes('<!DOCTYPE')) {\n return 'text/html';\n }\n if (content.includes('# ') || content.includes('## ')) {\n return 'text/markdown';\n }\n return 'text/plain';\n }\n\n private mapMimeTypeToContentType(mimeType?: string): ContentType {\n if (!mimeType) return 'text';\n \n if (mimeType.startsWith('text/plain')) return 'text';\n if (mimeType === 'application/json') return 'json';\n if (mimeType === 'text/html') return 'html';\n if (mimeType === 'text/markdown') return 'markdown';\n if (mimeType.startsWith('text/')) return 'text';\n \n return 'binary';\n }\n\n private deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n \n if (obj instanceof Date) {\n return new Date(obj.getTime()) as T;\n }\n \n if (Array.isArray(obj)) {\n return obj.map(item => this.deepClone(item)) as T;\n }\n \n const cloned = {} as T;\n for (const key in obj) {\n if (obj.hasOwnProperty(key)) {\n cloned[key] = this.deepClone(obj[key]);\n }\n }\n \n return cloned;\n }\n}"],"names":[],"mappings":"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"}
@@ -1,35 +1,32 @@
1
- import { BasePlugin } from "hedera-agent-kit";
2
- import { TransferHbarTool } from "./index12.js";
3
- class HbarTransferPlugin extends BasePlugin {
1
+ import { BasePlugin, HederaAirdropTokenTool } from "hedera-agent-kit";
2
+ import { TransferHbarTool } from "./index18.js";
3
+ import { AirdropToolWrapper } from "./index19.js";
4
+ class HbarPlugin extends BasePlugin {
4
5
  constructor() {
5
6
  super(...arguments);
6
- this.id = "hbar-transfer";
7
- this.name = "HBAR Transfer Plugin";
8
- this.description = "HBAR transfer tool with proper decimal handling for multi-signature transactions";
7
+ this.id = "hbar";
8
+ this.name = "HBAR Plugin";
9
+ this.description = "HBAR operations: transfer tool with robust decimal handling and compatibility with airdrop improvements";
9
10
  this.version = "1.0.0";
10
11
  this.author = "Hashgraph Online";
11
12
  this.namespace = "account";
12
13
  this.tools = [];
14
+ this.originalAirdropTool = null;
13
15
  }
14
16
  async initialize(context) {
15
17
  await super.initialize(context);
16
18
  const hederaKit = context.config.hederaKit;
17
19
  if (!hederaKit) {
18
20
  this.context.logger.warn(
19
- "HederaKit not found in context. HBAR transfer tools will not be available."
21
+ "HederaKit not found in context. HBAR tools will not be available."
20
22
  );
21
23
  return;
22
24
  }
23
25
  try {
24
26
  this.initializeTools();
25
- this.context.logger.info(
26
- "HBAR Transfer Plugin initialized successfully"
27
- );
27
+ this.context.logger.info("HBAR Plugin initialized successfully");
28
28
  } catch (error) {
29
- this.context.logger.error(
30
- "Failed to initialize HBAR Transfer plugin:",
31
- error
32
- );
29
+ this.context.logger.error("Failed to initialize HBAR plugin:", error);
33
30
  }
34
31
  }
35
32
  initializeTools() {
@@ -37,12 +34,28 @@ class HbarTransferPlugin extends BasePlugin {
37
34
  if (!hederaKit) {
38
35
  throw new Error("HederaKit not found in context config");
39
36
  }
40
- this.tools = [
41
- new TransferHbarTool({
37
+ const transfer = new TransferHbarTool({
38
+ hederaKit,
39
+ logger: this.context.logger
40
+ });
41
+ this.tools = [transfer];
42
+ try {
43
+ this.context.logger.info(
44
+ "Creating wrapper for passed original airdrop tool"
45
+ );
46
+ const airdropTool = new HederaAirdropTokenTool({
42
47
  hederaKit,
43
48
  logger: this.context.logger
44
- })
45
- ];
49
+ });
50
+ const wrappedAirdropTool = new AirdropToolWrapper(airdropTool, hederaKit);
51
+ this.tools.push(wrappedAirdropTool);
52
+ this.context.logger.info("Added wrapped airdrop tool to HBAR Plugin");
53
+ } catch (error) {
54
+ this.context.logger.error("Error creating airdrop tool wrapper:", error);
55
+ }
56
+ this.context.logger.info(
57
+ `HBAR Plugin tools initialized with ${this.tools.length} tools`
58
+ );
46
59
  }
47
60
  getTools() {
48
61
  return this.tools;
@@ -52,6 +65,6 @@ class HbarTransferPlugin extends BasePlugin {
52
65
  }
53
66
  }
54
67
  export {
55
- HbarTransferPlugin
68
+ HbarPlugin
56
69
  };
57
70
  //# sourceMappingURL=index5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index5.js","sources":["../../src/plugins/hbar-transfer/HbarTransferPlugin.ts"],"sourcesContent":["import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n} from 'hedera-agent-kit';\nimport { TransferHbarTool } from './TransferHbarTool';\n\nexport class HbarTransferPlugin extends BasePlugin {\n id = 'hbar-transfer';\n name = 'HBAR Transfer Plugin';\n description =\n 'HBAR transfer tool with proper decimal handling for multi-signature transactions';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'account';\n\n private tools: HederaTool[] = [];\n\n override async initialize(context: GenericPluginContext): Promise<void> {\n await super.initialize(context);\n\n const hederaKit = context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n this.context.logger.warn(\n 'HederaKit not found in context. HBAR transfer tools will not be available.'\n );\n return;\n }\n\n try {\n this.initializeTools();\n\n this.context.logger.info(\n 'HBAR Transfer Plugin initialized successfully'\n );\n } catch (error) {\n this.context.logger.error(\n 'Failed to initialize HBAR Transfer plugin:',\n error\n );\n }\n }\n\n private initializeTools(): void {\n const hederaKit = this.context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n throw new Error('HederaKit not found in context config');\n }\n\n this.tools = [\n new TransferHbarTool({\n hederaKit: hederaKit,\n logger: this.context.logger,\n }),\n ];\n }\n\n override getTools(): HederaTool[] {\n return this.tools;\n }\n\n async shutdown(): Promise<void> {\n this.tools = [];\n }\n}"],"names":[],"mappings":";;AAQO,MAAM,2BAA2B,WAAW;AAAA,EAA5C,cAAA;AAAA,UAAA,GAAA,SAAA;AACL,SAAA,KAAK;AACL,SAAA,OAAO;AACP,SAAA,cACE;AACF,SAAA,UAAU;AACV,SAAA,SAAS;AACT,SAAA,YAAY;AAEZ,SAAQ,QAAsB,CAAA;AAAA,EAAC;AAAA,EAE/B,MAAe,WAAW,SAA8C;AACtE,UAAM,MAAM,WAAW,OAAO;AAE9B,UAAM,YAAY,QAAQ,OAAO;AACjC,QAAI,CAAC,WAAW;AACd,WAAK,QAAQ,OAAO;AAAA,QAClB;AAAA,MAAA;AAEF;AAAA,IACF;AAEA,QAAI;AACF,WAAK,gBAAA;AAEL,WAAK,QAAQ,OAAO;AAAA,QAClB;AAAA,MAAA;AAAA,IAEJ,SAAS,OAAO;AACd,WAAK,QAAQ,OAAO;AAAA,QAClB;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAAA,EAEQ,kBAAwB;AAC9B,UAAM,YAAY,KAAK,QAAQ,OAAO;AACtC,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAEA,SAAK,QAAQ;AAAA,MACX,IAAI,iBAAiB;AAAA,QACnB;AAAA,QACA,QAAQ,KAAK,QAAQ;AAAA,MAAA,CACtB;AAAA,IAAA;AAAA,EAEL;AAAA,EAES,WAAyB;AAChC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,WAA0B;AAC9B,SAAK,QAAQ,CAAA;AAAA,EACf;AACF;"}
1
+ {"version":3,"file":"index5.js","sources":["../../src/plugins/hbar/HbarPlugin.ts"],"sourcesContent":["import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n HederaAirdropTokenTool,\n} from 'hedera-agent-kit';\nimport { TransferHbarTool } from './TransferHbarTool';\nimport { AirdropToolWrapper } from './AirdropToolWrapper';\nimport { StructuredTool } from '@langchain/core/tools';\n\nexport class HbarPlugin extends BasePlugin {\n id = 'hbar';\n name = 'HBAR Plugin';\n description =\n 'HBAR operations: transfer tool with robust decimal handling and compatibility with airdrop improvements';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'account';\n\n private tools: (HederaTool | AirdropToolWrapper)[] = [];\n private originalAirdropTool: StructuredTool | null = null;\n\n override async initialize(context: GenericPluginContext): Promise<void> {\n await super.initialize(context);\n\n const hederaKit = context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n this.context.logger.warn(\n 'HederaKit not found in context. HBAR tools will not be available.'\n );\n return;\n }\n\n try {\n this.initializeTools();\n\n this.context.logger.info('HBAR Plugin initialized successfully');\n } catch (error) {\n this.context.logger.error('Failed to initialize HBAR plugin:', error);\n }\n }\n\n private initializeTools(): void {\n const hederaKit = this.context.config.hederaKit as HederaAgentKit;\n if (!hederaKit) {\n throw new Error('HederaKit not found in context config');\n }\n\n const transfer = new TransferHbarTool({\n hederaKit: hederaKit,\n logger: this.context.logger,\n });\n\n this.tools = [transfer];\n\n try {\n this.context.logger.info(\n 'Creating wrapper for passed original airdrop tool'\n );\n\n const airdropTool = new HederaAirdropTokenTool({\n hederaKit: hederaKit,\n logger: this.context.logger,\n });\n const wrappedAirdropTool = new AirdropToolWrapper(airdropTool, hederaKit);\n this.tools.push(wrappedAirdropTool);\n this.context.logger.info('Added wrapped airdrop tool to HBAR Plugin');\n } catch (error) {\n this.context.logger.error('Error creating airdrop tool wrapper:', error);\n }\n\n this.context.logger.info(\n `HBAR Plugin tools initialized with ${this.tools.length} tools`\n );\n }\n\n override getTools(): HederaTool[] {\n // @ts-ignore\n return this.tools;\n }\n\n async shutdown(): Promise<void> {\n this.tools = [];\n }\n}\n"],"names":[],"mappings":";;;AAWO,MAAM,mBAAmB,WAAW;AAAA,EAApC,cAAA;AAAA,UAAA,GAAA,SAAA;AACL,SAAA,KAAK;AACL,SAAA,OAAO;AACP,SAAA,cACE;AACF,SAAA,UAAU;AACV,SAAA,SAAS;AACT,SAAA,YAAY;AAEZ,SAAQ,QAA6C,CAAA;AACrD,SAAQ,sBAA6C;AAAA,EAAA;AAAA,EAErD,MAAe,WAAW,SAA8C;AACtE,UAAM,MAAM,WAAW,OAAO;AAE9B,UAAM,YAAY,QAAQ,OAAO;AACjC,QAAI,CAAC,WAAW;AACd,WAAK,QAAQ,OAAO;AAAA,QAClB;AAAA,MAAA;AAEF;AAAA,IACF;AAEA,QAAI;AACF,WAAK,gBAAA;AAEL,WAAK,QAAQ,OAAO,KAAK,sCAAsC;AAAA,IACjE,SAAS,OAAO;AACd,WAAK,QAAQ,OAAO,MAAM,qCAAqC,KAAK;AAAA,IACtE;AAAA,EACF;AAAA,EAEQ,kBAAwB;AAC9B,UAAM,YAAY,KAAK,QAAQ,OAAO;AACtC,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAEA,UAAM,WAAW,IAAI,iBAAiB;AAAA,MACpC;AAAA,MACA,QAAQ,KAAK,QAAQ;AAAA,IAAA,CACtB;AAED,SAAK,QAAQ,CAAC,QAAQ;AAEtB,QAAI;AACF,WAAK,QAAQ,OAAO;AAAA,QAClB;AAAA,MAAA;AAGF,YAAM,cAAc,IAAI,uBAAuB;AAAA,QAC7C;AAAA,QACA,QAAQ,KAAK,QAAQ;AAAA,MAAA,CACtB;AACD,YAAM,qBAAqB,IAAI,mBAAmB,aAAa,SAAS;AACxE,WAAK,MAAM,KAAK,kBAAkB;AAClC,WAAK,QAAQ,OAAO,KAAK,2CAA2C;AAAA,IACtE,SAAS,OAAO;AACd,WAAK,QAAQ,OAAO,MAAM,wCAAwC,KAAK;AAAA,IACzE;AAEA,SAAK,QAAQ,OAAO;AAAA,MAClB,sCAAsC,KAAK,MAAM,MAAM;AAAA,IAAA;AAAA,EAE3D;AAAA,EAES,WAAyB;AAEhC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,WAA0B;AAC9B,SAAK,QAAQ,CAAA;AAAA,EACf;AACF;"}