@hashgraphonline/conversational-agent 0.2.215 → 0.2.217

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 (310) hide show
  1. package/cli/readme.md +181 -0
  2. package/dist/cjs/index.cjs +1 -1
  3. package/dist/cjs/index.cjs.map +1 -1
  4. package/dist/cjs/index.d.ts +1 -0
  5. package/dist/cjs/plugins/community/swarm/SwarmPlugin.d.ts +17 -0
  6. package/dist/cjs/plugins/community/swarm/__tests__/SwarmPlugin.mocks.d.ts +1 -0
  7. package/dist/cjs/plugins/community/swarm/__tests__/SwarmPlugin.test.d.ts +1 -0
  8. package/dist/cjs/plugins/community/swarm/__tests__/tools/CreatePostageStampTool.test.d.ts +1 -0
  9. package/dist/cjs/plugins/community/swarm/__tests__/tools/DownloadDataTool.test.d.ts +1 -0
  10. package/dist/cjs/plugins/community/swarm/__tests__/tools/DownloadFilesTool.test.d.ts +1 -0
  11. package/dist/cjs/plugins/community/swarm/__tests__/tools/ExtendPostageStampTool.test.d.ts +1 -0
  12. package/dist/cjs/plugins/community/swarm/__tests__/tools/GetPostageStampTool.test.d.ts +1 -0
  13. package/dist/cjs/plugins/community/swarm/__tests__/tools/ListPostageStampsTool.test.d.ts +1 -0
  14. package/dist/cjs/plugins/community/swarm/__tests__/tools/QueryUploadProgressTool.test.d.ts +1 -0
  15. package/dist/cjs/plugins/community/swarm/__tests__/tools/ReadFeedTool.test.d.ts +1 -0
  16. package/dist/cjs/plugins/community/swarm/__tests__/tools/SwarmTool.mocks.d.ts +14 -0
  17. package/dist/cjs/plugins/community/swarm/__tests__/tools/UpdateFeedTool.test.d.ts +1 -0
  18. package/dist/cjs/plugins/community/swarm/__tests__/tools/UploadDataTool.test.d.ts +1 -0
  19. package/dist/cjs/plugins/community/swarm/__tests__/tools/UploadFileTool.test.d.ts +1 -0
  20. package/dist/cjs/plugins/community/swarm/__tests__/tools/UploadFolderTool.test.d.ts +1 -0
  21. package/dist/cjs/plugins/community/swarm/config.d.ts +6 -0
  22. package/dist/cjs/plugins/community/swarm/constants.d.ts +8 -0
  23. package/dist/cjs/plugins/community/swarm/index.d.ts +2 -0
  24. package/dist/cjs/plugins/community/swarm/model.d.ts +23 -0
  25. package/dist/cjs/plugins/community/swarm/tools/CreatePostageStampTool.d.ts +47 -0
  26. package/dist/cjs/plugins/community/swarm/tools/DownloadDataTool.d.ts +35 -0
  27. package/dist/cjs/plugins/community/swarm/tools/DownloadFilesTool.d.ts +41 -0
  28. package/dist/cjs/plugins/community/swarm/tools/ExtendPostageStampTool.d.ts +47 -0
  29. package/dist/cjs/plugins/community/swarm/tools/GetPostageStampTool.d.ts +35 -0
  30. package/dist/cjs/plugins/community/swarm/tools/ListPostageStampsTool.d.ts +53 -0
  31. package/dist/cjs/plugins/community/swarm/tools/QueryUploadProgressTool.d.ts +35 -0
  32. package/dist/cjs/plugins/community/swarm/tools/ReadFeedTool.d.ts +41 -0
  33. package/dist/cjs/plugins/community/swarm/tools/UpdateFeedTool.d.ts +47 -0
  34. package/dist/cjs/plugins/community/swarm/tools/UploadDataTool.d.ts +47 -0
  35. package/dist/cjs/plugins/community/swarm/tools/UploadFileTool.d.ts +53 -0
  36. package/dist/cjs/plugins/community/swarm/tools/UploadFolderTool.d.ts +47 -0
  37. package/dist/cjs/plugins/community/swarm/utils.d.ts +22 -0
  38. package/dist/cjs/plugins/index.d.ts +1 -0
  39. package/dist/esm/index.js +33 -31
  40. package/dist/esm/index.js.map +1 -1
  41. package/dist/esm/index10.js +13 -677
  42. package/dist/esm/index10.js.map +1 -1
  43. package/dist/esm/index11.js +601 -234
  44. package/dist/esm/index11.js.map +1 -1
  45. package/dist/esm/index12.js +296 -136
  46. package/dist/esm/index12.js.map +1 -1
  47. package/dist/esm/index13.js +127 -235
  48. package/dist/esm/index13.js.map +1 -1
  49. package/dist/esm/index14.js +247 -84
  50. package/dist/esm/index14.js.map +1 -1
  51. package/dist/esm/index15.js +81 -159
  52. package/dist/esm/index15.js.map +1 -1
  53. package/dist/esm/index16.js +155 -229
  54. package/dist/esm/index16.js.map +1 -1
  55. package/dist/esm/index17.js +238 -140
  56. package/dist/esm/index17.js.map +1 -1
  57. package/dist/esm/index18.js +139 -493
  58. package/dist/esm/index18.js.map +1 -1
  59. package/dist/esm/index19.js +479 -91
  60. package/dist/esm/index19.js.map +1 -1
  61. package/dist/esm/index20.js +88 -147
  62. package/dist/esm/index20.js.map +1 -1
  63. package/dist/esm/index21.js +127 -666
  64. package/dist/esm/index21.js.map +1 -1
  65. package/dist/esm/index22.js +698 -44
  66. package/dist/esm/index22.js.map +1 -1
  67. package/dist/esm/index23.js +45 -304
  68. package/dist/esm/index23.js.map +1 -1
  69. package/dist/esm/index24.js +303 -153
  70. package/dist/esm/index24.js.map +1 -1
  71. package/dist/esm/index25.js +150 -117
  72. package/dist/esm/index25.js.map +1 -1
  73. package/dist/esm/index26.js +154 -18
  74. package/dist/esm/index26.js.map +1 -1
  75. package/dist/esm/index27.js +18 -22
  76. package/dist/esm/index27.js.map +1 -1
  77. package/dist/esm/index28.js +15 -74
  78. package/dist/esm/index28.js.map +1 -1
  79. package/dist/esm/index29.js +70 -295
  80. package/dist/esm/index29.js.map +1 -1
  81. package/dist/esm/index30.js +279 -100
  82. package/dist/esm/index30.js.map +1 -1
  83. package/dist/esm/index31.js +86 -922
  84. package/dist/esm/index31.js.map +1 -1
  85. package/dist/esm/index32.js +904 -189
  86. package/dist/esm/index32.js.map +1 -1
  87. package/dist/esm/index33.js +185 -1169
  88. package/dist/esm/index33.js.map +1 -1
  89. package/dist/esm/index34.js +1218 -112
  90. package/dist/esm/index34.js.map +1 -1
  91. package/dist/esm/index35.js +111 -99
  92. package/dist/esm/index35.js.map +1 -1
  93. package/dist/esm/index36.js +113 -8
  94. package/dist/esm/index36.js.map +1 -1
  95. package/dist/esm/index37.js +8 -45
  96. package/dist/esm/index37.js.map +1 -1
  97. package/dist/esm/index38.js +41 -102
  98. package/dist/esm/index38.js.map +1 -1
  99. package/dist/esm/index39.js +96 -55
  100. package/dist/esm/index39.js.map +1 -1
  101. package/dist/esm/index4.js +1 -1
  102. package/dist/esm/index40.js +58 -71
  103. package/dist/esm/index40.js.map +1 -1
  104. package/dist/esm/index41.js +79 -21
  105. package/dist/esm/index41.js.map +1 -1
  106. package/dist/esm/index42.js +21 -5
  107. package/dist/esm/index42.js.map +1 -1
  108. package/dist/esm/index43.js +4 -11
  109. package/dist/esm/index43.js.map +1 -1
  110. package/dist/esm/index44.js +12 -322
  111. package/dist/esm/index44.js.map +1 -1
  112. package/dist/esm/index45.js +280 -142
  113. package/dist/esm/index45.js.map +1 -1
  114. package/dist/esm/index46.js +181 -24
  115. package/dist/esm/index46.js.map +1 -1
  116. package/dist/esm/index48.js +67 -85
  117. package/dist/esm/index48.js.map +1 -1
  118. package/dist/esm/index49.js +75 -0
  119. package/dist/esm/index49.js.map +1 -0
  120. package/dist/esm/index5.js +2 -2
  121. package/dist/esm/index50.js +57 -0
  122. package/dist/esm/index50.js.map +1 -0
  123. package/dist/esm/index51.js +103 -0
  124. package/dist/esm/index51.js.map +1 -0
  125. package/dist/esm/index52.js +79 -0
  126. package/dist/esm/index52.js.map +1 -0
  127. package/dist/esm/index53.js +75 -0
  128. package/dist/esm/index53.js.map +1 -0
  129. package/dist/esm/index54.js +124 -0
  130. package/dist/esm/index54.js.map +1 -0
  131. package/dist/esm/index55.js +58 -0
  132. package/dist/esm/index55.js.map +1 -0
  133. package/dist/esm/index56.js +83 -0
  134. package/dist/esm/index56.js.map +1 -0
  135. package/dist/esm/index57.js +100 -0
  136. package/dist/esm/index57.js.map +1 -0
  137. package/dist/esm/index58.js +118 -0
  138. package/dist/esm/index58.js.map +1 -0
  139. package/dist/esm/index59.js +108 -0
  140. package/dist/esm/index59.js.map +1 -0
  141. package/dist/esm/index6.js +132 -833
  142. package/dist/esm/index6.js.map +1 -1
  143. package/dist/esm/index60.js +30 -0
  144. package/dist/esm/index60.js.map +1 -0
  145. package/dist/esm/index61.js +98 -0
  146. package/dist/esm/index61.js.map +1 -0
  147. package/dist/esm/index62.js +131 -0
  148. package/dist/esm/index62.js.map +1 -0
  149. package/dist/esm/index63.js +19 -0
  150. package/dist/esm/index63.js.map +1 -0
  151. package/dist/esm/index7.js +826 -75
  152. package/dist/esm/index7.js.map +1 -1
  153. package/dist/esm/index8.js +91 -13
  154. package/dist/esm/index8.js.map +1 -1
  155. package/dist/esm/index9.js +13 -17
  156. package/dist/esm/index9.js.map +1 -1
  157. package/dist/types/index.d.ts +1 -0
  158. package/dist/types/plugins/community/swarm/SwarmPlugin.d.ts +17 -0
  159. package/dist/types/plugins/community/swarm/__tests__/SwarmPlugin.mocks.d.ts +1 -0
  160. package/dist/types/plugins/community/swarm/__tests__/SwarmPlugin.test.d.ts +1 -0
  161. package/dist/types/plugins/community/swarm/__tests__/tools/CreatePostageStampTool.test.d.ts +1 -0
  162. package/dist/types/plugins/community/swarm/__tests__/tools/DownloadDataTool.test.d.ts +1 -0
  163. package/dist/types/plugins/community/swarm/__tests__/tools/DownloadFilesTool.test.d.ts +1 -0
  164. package/dist/types/plugins/community/swarm/__tests__/tools/ExtendPostageStampTool.test.d.ts +1 -0
  165. package/dist/types/plugins/community/swarm/__tests__/tools/GetPostageStampTool.test.d.ts +1 -0
  166. package/dist/types/plugins/community/swarm/__tests__/tools/ListPostageStampsTool.test.d.ts +1 -0
  167. package/dist/types/plugins/community/swarm/__tests__/tools/QueryUploadProgressTool.test.d.ts +1 -0
  168. package/dist/types/plugins/community/swarm/__tests__/tools/ReadFeedTool.test.d.ts +1 -0
  169. package/dist/types/plugins/community/swarm/__tests__/tools/SwarmTool.mocks.d.ts +14 -0
  170. package/dist/types/plugins/community/swarm/__tests__/tools/UpdateFeedTool.test.d.ts +1 -0
  171. package/dist/types/plugins/community/swarm/__tests__/tools/UploadDataTool.test.d.ts +1 -0
  172. package/dist/types/plugins/community/swarm/__tests__/tools/UploadFileTool.test.d.ts +1 -0
  173. package/dist/types/plugins/community/swarm/__tests__/tools/UploadFolderTool.test.d.ts +1 -0
  174. package/dist/types/plugins/community/swarm/config.d.ts +6 -0
  175. package/dist/types/plugins/community/swarm/constants.d.ts +8 -0
  176. package/dist/types/plugins/community/swarm/index.d.ts +2 -0
  177. package/dist/types/plugins/community/swarm/model.d.ts +23 -0
  178. package/dist/types/plugins/community/swarm/tools/CreatePostageStampTool.d.ts +47 -0
  179. package/dist/types/plugins/community/swarm/tools/DownloadDataTool.d.ts +35 -0
  180. package/dist/types/plugins/community/swarm/tools/DownloadFilesTool.d.ts +41 -0
  181. package/dist/types/plugins/community/swarm/tools/ExtendPostageStampTool.d.ts +47 -0
  182. package/dist/types/plugins/community/swarm/tools/GetPostageStampTool.d.ts +35 -0
  183. package/dist/types/plugins/community/swarm/tools/ListPostageStampsTool.d.ts +53 -0
  184. package/dist/types/plugins/community/swarm/tools/QueryUploadProgressTool.d.ts +35 -0
  185. package/dist/types/plugins/community/swarm/tools/ReadFeedTool.d.ts +41 -0
  186. package/dist/types/plugins/community/swarm/tools/UpdateFeedTool.d.ts +47 -0
  187. package/dist/types/plugins/community/swarm/tools/UploadDataTool.d.ts +47 -0
  188. package/dist/types/plugins/community/swarm/tools/UploadFileTool.d.ts +53 -0
  189. package/dist/types/plugins/community/swarm/tools/UploadFolderTool.d.ts +47 -0
  190. package/dist/types/plugins/community/swarm/utils.d.ts +22 -0
  191. package/dist/types/plugins/index.d.ts +1 -0
  192. package/package.json +37 -27
  193. package/src/index.ts +1 -0
  194. package/src/plugins/community/swarm/README.md +279 -0
  195. package/src/plugins/community/swarm/SwarmPlugin.ts +178 -0
  196. package/src/plugins/community/swarm/__tests__/SwarmPlugin.mocks.ts +105 -0
  197. package/src/plugins/community/swarm/__tests__/SwarmPlugin.test.ts +93 -0
  198. package/src/plugins/community/swarm/__tests__/tools/CreatePostageStampTool.test.ts +152 -0
  199. package/src/plugins/community/swarm/__tests__/tools/DownloadDataTool.test.ts +93 -0
  200. package/src/plugins/community/swarm/__tests__/tools/DownloadFilesTool.test.ts +163 -0
  201. package/src/plugins/community/swarm/__tests__/tools/ExtendPostageStampTool.test.ts +132 -0
  202. package/src/plugins/community/swarm/__tests__/tools/GetPostageStampTool.test.ts +83 -0
  203. package/src/plugins/community/swarm/__tests__/tools/ListPostageStampsTool.test.ts +219 -0
  204. package/src/plugins/community/swarm/__tests__/tools/QueryUploadProgressTool.test.ts +169 -0
  205. package/src/plugins/community/swarm/__tests__/tools/ReadFeedTool.test.ts +133 -0
  206. package/src/plugins/community/swarm/__tests__/tools/SwarmTool.mocks.ts +67 -0
  207. package/src/plugins/community/swarm/__tests__/tools/UpdateFeedTool.test.ts +148 -0
  208. package/src/plugins/community/swarm/__tests__/tools/UploadDataTool.test.ts +125 -0
  209. package/src/plugins/community/swarm/__tests__/tools/UploadFileTool.test.ts +194 -0
  210. package/src/plugins/community/swarm/__tests__/tools/UploadFolderTool.test.ts +118 -0
  211. package/src/plugins/community/swarm/config.ts +6 -0
  212. package/src/plugins/community/swarm/constants.ts +12 -0
  213. package/src/plugins/community/swarm/index.ts +2 -0
  214. package/src/plugins/community/swarm/model.ts +23 -0
  215. package/src/plugins/community/swarm/tools/CreatePostageStampTool.ts +137 -0
  216. package/src/plugins/community/swarm/tools/DownloadDataTool.ts +79 -0
  217. package/src/plugins/community/swarm/tools/DownloadFilesTool.ts +155 -0
  218. package/src/plugins/community/swarm/tools/ExtendPostageStampTool.ts +112 -0
  219. package/src/plugins/community/swarm/tools/GetPostageStampTool.ts +92 -0
  220. package/src/plugins/community/swarm/tools/ListPostageStampsTool.ts +124 -0
  221. package/src/plugins/community/swarm/tools/QueryUploadProgressTool.ts +109 -0
  222. package/src/plugins/community/swarm/tools/ReadFeedTool.ts +110 -0
  223. package/src/plugins/community/swarm/tools/UpdateFeedTool.ts +149 -0
  224. package/src/plugins/community/swarm/tools/UploadDataTool.ts +109 -0
  225. package/src/plugins/community/swarm/tools/UploadFileTool.ts +163 -0
  226. package/src/plugins/community/swarm/tools/UploadFolderTool.ts +150 -0
  227. package/src/plugins/community/swarm/utils.ts +172 -0
  228. package/src/plugins/index.ts +1 -0
  229. package/cli/dist/CLIApp.d.ts +0 -11
  230. package/cli/dist/CLIApp.d.ts.map +0 -1
  231. package/cli/dist/CLIApp.js +0 -128
  232. package/cli/dist/CLIApp.js.map +0 -1
  233. package/cli/dist/LocalConversationalAgent.d.ts +0 -37
  234. package/cli/dist/LocalConversationalAgent.js +0 -58
  235. package/cli/dist/app.d.ts +0 -18
  236. package/cli/dist/app.d.ts.map +0 -1
  237. package/cli/dist/app.js +0 -14
  238. package/cli/dist/app.js.map +0 -1
  239. package/cli/dist/cli.d.ts +0 -3
  240. package/cli/dist/cli.d.ts.map +0 -1
  241. package/cli/dist/cli.js +0 -87
  242. package/cli/dist/cli.js.map +0 -1
  243. package/cli/dist/components/AppContainer.d.ts +0 -16
  244. package/cli/dist/components/AppContainer.js +0 -24
  245. package/cli/dist/components/AppScreens.d.ts +0 -2
  246. package/cli/dist/components/AppScreens.js +0 -259
  247. package/cli/dist/components/ChatScreen.d.ts +0 -21
  248. package/cli/dist/components/ChatScreen.d.ts.map +0 -1
  249. package/cli/dist/components/ChatScreen.js +0 -40
  250. package/cli/dist/components/ChatScreen.js.map +0 -1
  251. package/cli/dist/components/DebugLoadingScreen.d.ts +0 -5
  252. package/cli/dist/components/DebugLoadingScreen.js +0 -31
  253. package/cli/dist/components/LoadingScreen.d.ts +0 -3
  254. package/cli/dist/components/LoadingScreen.d.ts.map +0 -1
  255. package/cli/dist/components/LoadingScreen.js +0 -17
  256. package/cli/dist/components/LoadingScreen.js.map +0 -1
  257. package/cli/dist/components/LoadingScreenDebug.d.ts +0 -5
  258. package/cli/dist/components/LoadingScreenDebug.js +0 -27
  259. package/cli/dist/components/MCPConfigScreen.d.ts +0 -28
  260. package/cli/dist/components/MCPConfigScreen.d.ts.map +0 -1
  261. package/cli/dist/components/MCPConfigScreen.js +0 -186
  262. package/cli/dist/components/MCPConfigScreen.js.map +0 -1
  263. package/cli/dist/components/ScreenRouter.d.ts +0 -13
  264. package/cli/dist/components/ScreenRouter.d.ts.map +0 -1
  265. package/cli/dist/components/ScreenRouter.js +0 -23
  266. package/cli/dist/components/ScreenRouter.js.map +0 -1
  267. package/cli/dist/components/SetupScreen.d.ts +0 -16
  268. package/cli/dist/components/SetupScreen.d.ts.map +0 -1
  269. package/cli/dist/components/SetupScreen.js +0 -67
  270. package/cli/dist/components/SetupScreen.js.map +0 -1
  271. package/cli/dist/components/SingleLoadingScreen.d.ts +0 -5
  272. package/cli/dist/components/SingleLoadingScreen.js +0 -27
  273. package/cli/dist/components/StatusBadge.d.ts +0 -10
  274. package/cli/dist/components/StatusBadge.d.ts.map +0 -1
  275. package/cli/dist/components/StatusBadge.js +0 -24
  276. package/cli/dist/components/StatusBadge.js.map +0 -1
  277. package/cli/dist/components/TerminalWindow.d.ts +0 -9
  278. package/cli/dist/components/TerminalWindow.d.ts.map +0 -1
  279. package/cli/dist/components/TerminalWindow.js +0 -19
  280. package/cli/dist/components/TerminalWindow.js.map +0 -1
  281. package/cli/dist/components/WelcomeScreen.d.ts +0 -12
  282. package/cli/dist/components/WelcomeScreen.d.ts.map +0 -1
  283. package/cli/dist/components/WelcomeScreen.js +0 -47
  284. package/cli/dist/components/WelcomeScreen.js.map +0 -1
  285. package/cli/dist/context/AppContext.d.ts +0 -68
  286. package/cli/dist/context/AppContext.js +0 -363
  287. package/cli/dist/headless-runner.d.ts +0 -17
  288. package/cli/dist/headless-runner.d.ts.map +0 -1
  289. package/cli/dist/headless-runner.js +0 -128
  290. package/cli/dist/headless-runner.js.map +0 -1
  291. package/cli/dist/hooks/useInitializeAgent.d.ts +0 -19
  292. package/cli/dist/hooks/useInitializeAgent.d.ts.map +0 -1
  293. package/cli/dist/hooks/useInitializeAgent.js +0 -29
  294. package/cli/dist/hooks/useInitializeAgent.js.map +0 -1
  295. package/cli/dist/hooks/useStableState.d.ts +0 -38
  296. package/cli/dist/hooks/useStableState.d.ts.map +0 -1
  297. package/cli/dist/hooks/useStableState.js +0 -69
  298. package/cli/dist/hooks/useStableState.js.map +0 -1
  299. package/cli/dist/managers/AgentManager.d.ts +0 -58
  300. package/cli/dist/managers/AgentManager.d.ts.map +0 -1
  301. package/cli/dist/managers/AgentManager.js +0 -121
  302. package/cli/dist/managers/AgentManager.js.map +0 -1
  303. package/cli/dist/managers/ConfigManager.d.ts +0 -54
  304. package/cli/dist/managers/ConfigManager.d.ts.map +0 -1
  305. package/cli/dist/managers/ConfigManager.js +0 -188
  306. package/cli/dist/managers/ConfigManager.js.map +0 -1
  307. package/cli/dist/types.d.ts +0 -52
  308. package/cli/dist/types.d.ts.map +0 -1
  309. package/cli/dist/types.js +0 -34
  310. package/cli/dist/types.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/plugins/hcs-10/HCS10Plugin.ts","../../src/plugins/hcs-2/HCS2Plugin.ts","../../src/forms/field-guidance-registry.ts","../../src/plugins/inscribe/InscribePlugin.ts","../../src/plugins/hbar/AccountBuilder.ts","../../src/plugins/hbar/TransferHbarTool.ts","../../src/plugins/hbar/AirdropToolWrapper.ts","../../src/plugins/hbar/HbarPlugin.ts","../../src/forms/field-type-registry.ts","../../src/constants/messages.ts","../../src/services/formatters/types.ts","../../src/constants/entity-references.ts","../../src/constants/form-priorities.ts","../../src/forms/form-generator.ts","../../src/forms/form-engine.ts","../../src/utils/response-formatter.ts","../../src/langchain/form-aware-agent-executor.ts","../../src/base-agent.ts","../../src/mcp/content-processor.ts","../../src/mcp/mcp-client-manager.ts","../../src/mcp/adapters/langchain.ts","../../src/memory/token-counter.ts","../../src/memory/memory-window.ts","../../src/memory/reference-id-generator.ts","../../src/types/content-reference.ts","../../src/memory/content-storage.ts","../../src/memory/smart-memory-manager.ts","../../src/langchain/form-validating-tool-wrapper.ts","../../src/core/tool-registry.ts","../../src/execution/execution-pipeline.ts","../../src/langchain/langchain-agent.ts","../../src/agent-factory.ts","../../src/signers/browser-signer.ts","../../src/providers.ts","../../src/runtime/wallet-bridge.ts","../../src/plugins/web-browser/WebBrowserPlugin.ts","../../src/config/system-message.ts","../../src/services/content-store-manager.ts","../../src/tools/entity-resolver-tool.ts","../../src/services/formatters/format-converter-registry.ts","../../src/services/formatters/converters/topic-id-to-hrl-converter.ts","../../src/services/formatters/converters/string-normalization-converter.ts","../../src/services/parameter-service.ts","../../src/conversational-agent.ts","../../src/services/attachment-processor.ts","../../src/services/entity-resolver.ts","../../src/mcp/helpers.ts"],"sourcesContent":["import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n} from 'hedera-agent-kit';\nimport {\n IStateManager,\n OpenConvaiState,\n HCS10Builder,\n RegisterAgentTool,\n FindRegistrationsTool,\n InitiateConnectionTool,\n ListConnectionsTool,\n SendMessageToConnectionTool,\n CheckMessagesTool,\n ConnectionMonitorTool,\n ManageConnectionRequestsTool,\n AcceptConnectionRequestTool,\n RetrieveProfileTool,\n ListUnapprovedConnectionRequestsTool,\n RegisteredAgent,\n} from '@hashgraphonline/standards-agent-kit';\nimport { HCS10Client } from '@hashgraphonline/standards-sdk';\nimport { PrivateKey } from 'node_modules/@hashgraph/sdk/lib/Mnemonic';\n\ninterface HCS10ClientManager {\n initializeConnectionsManager(client: HCS10Client): void;\n}\n\nfunction hasInitializeConnectionsManager(\n stateManager: IStateManager\n): stateManager is IStateManager & HCS10ClientManager {\n return (\n typeof stateManager === 'object' &&\n stateManager !== null &&\n 'initializeConnectionsManager' in stateManager &&\n typeof stateManager.initializeConnectionsManager === 'function'\n );\n}\n\nexport class HCS10Plugin extends BasePlugin {\n id = 'hcs-10';\n name = 'HCS-10 Plugin';\n description =\n 'HCS-10 agent tools for decentralized agent registration, connections, and messaging on Hedera';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'hcs10';\n\n private stateManager?: IStateManager;\n private tools: any[] = [];\n appConfig?: Record<string, unknown>;\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. HCS-10 tools will not be available.'\n );\n return;\n }\n\n try {\n this.stateManager =\n (context.stateManager as IStateManager) ||\n (context.config.stateManager as IStateManager) ||\n (this.appConfig?.stateManager as IStateManager) ||\n new OpenConvaiState();\n\n const accountId = hederaKit.signer.getAccountId().toString();\n const isBytesMode =\n String(hederaKit.operationalMode || 'returnBytes') === 'returnBytes';\n let inboundTopicId = '';\n let outboundTopicId = '';\n\n let operatorPrivateKeyRef: PrivateKey =\n hederaKit.signer.getOperatorPrivateKey();\n let operatorPrivateKeySerialized: string | undefined;\n\n try {\n const resolved =\n typeof operatorPrivateKeyRef?.toString === 'function'\n ? operatorPrivateKeyRef.toString()\n : '';\n\n operatorPrivateKeySerialized = resolved;\n\n const hcs10Client = new HCS10Client({\n network: hederaKit.network as 'mainnet' | 'testnet',\n operatorId: accountId,\n operatorPrivateKey: operatorPrivateKeyRef,\n logLevel: 'error',\n });\n\n const profileResponse = await hcs10Client.retrieveProfile(accountId);\n if (profileResponse.success && profileResponse.topicInfo) {\n inboundTopicId = profileResponse.topicInfo.inboundTopic;\n outboundTopicId = profileResponse.topicInfo.outboundTopic;\n }\n } catch (profileError) {\n this.context.logger.warn(\n 'Skipping profile topic discovery',\n profileError\n );\n }\n\n const agentRecord: Record<string, unknown> = {\n name: `Agent ${accountId}`,\n accountId: accountId,\n inboundTopicId,\n outboundTopicId,\n };\n if (!isBytesMode && operatorPrivateKeySerialized) {\n agentRecord.privateKey = operatorPrivateKeySerialized;\n }\n this.stateManager.setCurrentAgent(\n agentRecord as unknown as RegisteredAgent\n );\n\n this.context.logger.info(\n `Set current agent: ${accountId} with topics ${inboundTopicId}/${outboundTopicId}`\n );\n\n if (\n !isBytesMode &&\n this.stateManager &&\n !this.stateManager.getConnectionsManager()\n ) {\n try {\n const hcs10Client = new HCS10Client({\n network: hederaKit.network as 'mainnet' | 'testnet',\n operatorId: accountId,\n operatorPrivateKey: operatorPrivateKeyRef ?? '',\n logLevel: 'error',\n });\n\n if (hasInitializeConnectionsManager(this.stateManager)) {\n this.stateManager.initializeConnectionsManager(hcs10Client);\n } else {\n this.context.logger.warn(\n 'StateManager does not support connection manager initialization'\n );\n }\n this.context.logger.info(\n 'ConnectionsManager initialized in HCS10Plugin'\n );\n } catch (cmError) {\n this.context.logger.warn(\n 'Could not initialize ConnectionsManager:',\n cmError\n );\n }\n }\n\n this.initializeTools();\n this.context.logger.info('HCS-10 Plugin initialized successfully');\n } catch (error) {\n this.context.logger.error('Failed to initialize HCS-10 plugin:', error);\n }\n }\n\n private initializeTools(): void {\n if (!this.stateManager) {\n throw new Error('StateManager must be initialized before creating tools');\n }\n\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 hcs10Builder = new HCS10Builder(hederaKit, this.stateManager);\n\n this.tools = [\n new RegisterAgentTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new FindRegistrationsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new RetrieveProfileTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new InitiateConnectionTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ListConnectionsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new SendMessageToConnectionTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new CheckMessagesTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ConnectionMonitorTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ManageConnectionRequestsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new AcceptConnectionRequestTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ListUnapprovedConnectionRequestsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n ];\n }\n\n getTools(): HederaTool[] {\n return this.tools;\n }\n\n getStateManager(): IStateManager | undefined {\n return this.stateManager;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n delete this.stateManager;\n if (this.context?.logger) {\n this.context.logger.info('HCS-10 Plugin cleaned up');\n }\n }\n}\n","import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n} from 'hedera-agent-kit';\nimport {\n HCS2Builder,\n CreateRegistryTool,\n RegisterEntryTool,\n UpdateEntryTool,\n DeleteEntryTool,\n MigrateRegistryTool,\n QueryRegistryTool,\n} from '@hashgraphonline/standards-agent-kit';\n\n/**\n * Plugin providing HCS-2 registry management tools\n */\nexport class HCS2Plugin extends BasePlugin {\n id = 'hcs-2';\n name = 'HCS-2 Plugin';\n description =\n 'HCS-2 registry management tools for decentralized registries on Hedera';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'hcs2';\n\n private tools: any[] = [];\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. HCS-2 tools will not be available.'\n );\n return;\n }\n\n try {\n this.initializeTools();\n\n this.context.logger.info(\n 'HCS-2 Plugin initialized successfully'\n );\n } catch (error) {\n this.context.logger.error(\n 'Failed to initialize HCS-2 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 const hcs2Builder = new HCS2Builder(hederaKit);\n\n this.tools = [\n new CreateRegistryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new RegisterEntryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new UpdateEntryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new DeleteEntryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new MigrateRegistryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new QueryRegistryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n ];\n }\n\n getTools(): HederaTool[] {\n return this.tools;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n if (this.context?.logger) {\n this.context.logger.info('HCS-2 Plugin cleaned up');\n }\n }\n}\n","import type { FormFieldType, FieldOption } from './types';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * Field guidance configuration for providing contextual help and suggestions\n */\nexport interface FieldGuidance {\n /**\n * Suggestions to show as placeholder or examples\n */\n suggestions?: string[];\n\n /**\n * Predefined options for select fields\n */\n predefinedOptions?: FieldOption[];\n\n /**\n * Warning messages for specific patterns to avoid\n */\n warnings?: {\n pattern: RegExp;\n message: string;\n }[];\n\n /**\n * Validation rules specific to the field context\n */\n validationRules?: {\n /**\n * Patterns that should be rejected\n */\n rejectPatterns?: {\n pattern: RegExp;\n reason: string;\n }[];\n\n /**\n * Minimum quality requirements\n */\n qualityChecks?: {\n minNonTechnicalWords?: number;\n requireSpecificTerms?: string[];\n forbidTechnicalTerms?: string[];\n };\n };\n\n /**\n * Field type override for specific contexts\n */\n fieldTypeOverride?: FormFieldType;\n\n /**\n * Help text specific to the tool context\n */\n contextualHelpText?: string;\n}\n\n/**\n * Tool-specific field configurations\n */\nexport interface ToolFieldConfiguration {\n /**\n * Tool name or pattern to match\n */\n toolPattern: string | RegExp;\n\n /**\n * Field-specific guidance\n */\n fields: Record<string, FieldGuidance>;\n\n /**\n * Global guidance for all fields in this tool\n */\n globalGuidance?: {\n /**\n * General warnings to show\n */\n warnings?: string[];\n\n /**\n * Quality standards for this tool\n */\n qualityStandards?: string[];\n };\n}\n\n/**\n * Registry for field guidance configurations\n */\nclass FieldGuidanceRegistry {\n private configurations: ToolFieldConfiguration[] = [];\n private providers: Array<{\n id: string;\n priority: number;\n pattern: string | RegExp;\n provider: FieldGuidanceProvider;\n order: number;\n }> = [];\n private registerOrderCounter = 0;\n private logger: Logger;\n\n constructor() {\n this.logger = new Logger({ module: 'FieldGuidanceRegistry' });\n }\n\n /**\n * Register field guidance for a specific tool\n */\n registerToolConfiguration(config: ToolFieldConfiguration): void {\n this.configurations.push(config);\n }\n\n /**\n * Register a provider for dynamic field/global guidance\n */\n registerToolProvider(\n toolPattern: string | RegExp,\n provider: FieldGuidanceProvider,\n options?: { id?: string; priority?: number }\n ): string {\n const id = options?.id ?? `provider-${this.providers.length + 1}`;\n const priority = options?.priority ?? 0;\n if (this.providers.some((p) => p.id === id)) {\n this.logger.error('Duplicate provider id', { id });\n throw new Error('DUPLICATE_PROVIDER_ID');\n }\n this.providers.push({\n id,\n priority,\n pattern: toolPattern,\n provider,\n order: this.registerOrderCounter++,\n });\n return id;\n }\n\n /** Unregister a provider by id */\n unregisterProvider(id: string): void {\n this.providers = this.providers.filter((p) => p.id !== id);\n }\n\n /** List registered providers */\n listProviders(): Array<{\n id: string;\n priority: number;\n pattern: string | RegExp;\n }> {\n return this.providers.map(({ id, priority, pattern }) => ({\n id,\n priority,\n pattern,\n }));\n }\n\n /**\n * Get field guidance for a specific tool and field\n */\n getFieldGuidance(toolName: string, fieldName: string): FieldGuidance | null {\n if (process.env.CA_FORM_GUIDANCE_ENABLED === 'false') {\n return null;\n }\n for (const config of this.configurations) {\n const matches =\n typeof config.toolPattern === 'string'\n ? toolName.toLowerCase().includes(config.toolPattern.toLowerCase())\n : config.toolPattern.test(toolName);\n\n if (matches && config.fields[fieldName]) {\n const staticGuidance = config.fields[fieldName];\n const providers = this.pickMatchingProviders(toolName);\n if (providers.length === 0) return staticGuidance;\n let merged: FieldGuidance = { ...staticGuidance };\n for (const p of [...providers].reverse()) {\n const fromProvider = this.safeGetFieldGuidance(\n p,\n fieldName,\n toolName\n );\n if (fromProvider) {\n merged = this.mergeGuidance(merged, fromProvider);\n }\n }\n return merged;\n }\n }\n const providers = this.pickMatchingProviders(toolName);\n if (providers.length > 0) {\n let merged: FieldGuidance = {};\n for (const p of [...providers].reverse()) {\n const g = this.safeGetFieldGuidance(p, fieldName, toolName);\n if (g) merged = this.mergeGuidance(merged, g);\n }\n return Object.keys(merged).length > 0 ? merged : null;\n }\n return null;\n }\n\n /**\n * Get global guidance for a tool\n */\n getGlobalGuidance(\n toolName: string\n ): ToolFieldConfiguration['globalGuidance'] | null {\n if (process.env.CA_FORM_GUIDANCE_ENABLED === 'false') {\n return null;\n }\n for (const config of this.configurations) {\n const matches =\n typeof config.toolPattern === 'string'\n ? toolName.toLowerCase().includes(config.toolPattern.toLowerCase())\n : config.toolPattern.test(toolName);\n\n if (matches && config.globalGuidance) {\n const base = config.globalGuidance;\n const providers = this.pickMatchingProviders(toolName);\n if (providers.length === 0) return base;\n let mergedWarnings: string[] | undefined = base.warnings;\n let mergedQuality: string[] | undefined = base.qualityStandards;\n for (const p of [...providers].reverse()) {\n const fromProvider = this.safeGetGlobalGuidance(p, toolName);\n if (fromProvider) {\n mergedWarnings = fromProvider.warnings ?? mergedWarnings;\n mergedQuality = fromProvider.qualityStandards ?? mergedQuality;\n }\n }\n const result: NonNullable<ToolFieldConfiguration['globalGuidance']> =\n {};\n if (mergedWarnings !== undefined) result.warnings = mergedWarnings;\n if (mergedQuality !== undefined)\n result.qualityStandards = mergedQuality;\n return result;\n }\n }\n const providers = this.pickMatchingProviders(toolName);\n if (providers.length > 0) {\n let mergedWarnings: string[] | undefined;\n let mergedQuality: string[] | undefined;\n for (const p of [...providers].reverse()) {\n const g = this.safeGetGlobalGuidance(p, toolName);\n if (g) {\n mergedWarnings = g.warnings ?? mergedWarnings;\n mergedQuality = g.qualityStandards ?? mergedQuality;\n }\n }\n const result: NonNullable<ToolFieldConfiguration['globalGuidance']> = {};\n if (mergedWarnings !== undefined) result.warnings = mergedWarnings;\n if (mergedQuality !== undefined) result.qualityStandards = mergedQuality;\n return Object.keys(result).length > 0 ? result : null;\n }\n return null;\n }\n\n /**\n * Validate field value against guidance rules\n */\n validateFieldValue(\n toolName: string,\n fieldName: string,\n value: unknown\n ): {\n isValid: boolean;\n warnings: string[];\n errors: string[];\n } {\n const guidance = this.getFieldGuidance(toolName, fieldName);\n const warnings: string[] = [];\n const errors: string[] = [];\n\n if (!guidance || typeof value !== 'string') {\n return { isValid: true, warnings, errors };\n }\n\n if (guidance.warnings) {\n for (const warning of guidance.warnings) {\n if (warning.pattern.test(value)) {\n warnings.push(warning.message);\n }\n }\n }\n\n if (guidance.validationRules) {\n const { rejectPatterns, qualityChecks } = guidance.validationRules;\n\n if (rejectPatterns) {\n for (const reject of rejectPatterns) {\n if (reject.pattern.test(value)) {\n errors.push(`Rejected: ${reject.reason}`);\n }\n }\n }\n\n if (qualityChecks) {\n if (qualityChecks.forbidTechnicalTerms) {\n const lowerValue = value.toLowerCase();\n for (const term of qualityChecks.forbidTechnicalTerms) {\n if (lowerValue.includes(term.toLowerCase())) {\n errors.push(\n `Avoid technical terms like \"${term}\" in NFT metadata`\n );\n }\n }\n }\n\n if (qualityChecks.requireSpecificTerms) {\n const lowerValue = value.toLowerCase();\n const hasRequired = qualityChecks.requireSpecificTerms.some((term) =>\n lowerValue.includes(term.toLowerCase())\n );\n if (!hasRequired) {\n warnings.push(\n `Consider including terms like: ${qualityChecks.requireSpecificTerms.join(\n ', '\n )}`\n );\n }\n }\n\n if (qualityChecks.minNonTechnicalWords) {\n const words = value.split(/\\s+/).filter((word) => word.length > 2);\n if (words.length < qualityChecks.minNonTechnicalWords) {\n warnings.push(\n `Consider providing more descriptive content (at least ${qualityChecks.minNonTechnicalWords} meaningful words)`\n );\n }\n }\n }\n }\n\n return {\n isValid: errors.length === 0,\n warnings,\n errors,\n };\n }\n\n /**\n * Clear all configurations (useful for testing)\n */\n clear(): void {\n this.configurations = [];\n this.providers = [];\n this.registerOrderCounter = 0;\n }\n\n /** Choose matching provider by priority then last-in wins */\n private pickMatchingProviders(toolName: string): Array<{\n id: string;\n provider: FieldGuidanceProvider;\n priority: number;\n order: number;\n }> {\n const matches = this.providers.filter((p) =>\n typeof p.pattern === 'string'\n ? toolName.toLowerCase().includes((p.pattern as string).toLowerCase())\n : (p.pattern as RegExp).test(toolName)\n );\n const sorted = matches.sort((a, b) => {\n if (b.priority !== a.priority) return b.priority - a.priority;\n return b.order - a.order; // last-in wins when equal priority\n });\n return sorted.map((m) => ({\n id: m.id,\n provider: m.provider,\n priority: m.priority,\n order: m.order,\n }));\n }\n\n private safeGetFieldGuidance(\n winner: { id: string; provider: FieldGuidanceProvider },\n fieldName: string,\n toolName: string\n ): FieldGuidance | null {\n try {\n return winner.provider.getFieldGuidance(fieldName, { toolName }) ?? null;\n } catch (err) {\n this.logger.warn('Provider getFieldGuidance failed', {\n id: winner.id,\n err,\n });\n return null;\n }\n }\n\n private safeGetGlobalGuidance(\n winner: { id: string; provider: FieldGuidanceProvider },\n toolName: string\n ): ToolFieldConfiguration['globalGuidance'] | null {\n try {\n return winner.provider.getGlobalGuidance?.(toolName) ?? null;\n } catch (err) {\n this.logger.warn('Provider getGlobalGuidance failed', {\n id: winner.id,\n err,\n });\n return null;\n }\n }\n\n private mergeGuidance(\n base: FieldGuidance,\n over: FieldGuidance\n ): FieldGuidance {\n const out: FieldGuidance = {};\n const suggestions = over.suggestions ?? base.suggestions;\n if (suggestions !== undefined) out.suggestions = suggestions;\n const predefinedOptions = over.predefinedOptions ?? base.predefinedOptions;\n if (predefinedOptions !== undefined)\n out.predefinedOptions = predefinedOptions;\n const warnings = over.warnings ?? base.warnings;\n if (warnings !== undefined) out.warnings = warnings;\n const validationRules = over.validationRules ?? base.validationRules;\n if (validationRules !== undefined) out.validationRules = validationRules;\n const fieldTypeOverride = over.fieldTypeOverride ?? base.fieldTypeOverride;\n if (fieldTypeOverride !== undefined)\n out.fieldTypeOverride = fieldTypeOverride;\n const contextualHelpText =\n over.contextualHelpText ?? base.contextualHelpText;\n if (contextualHelpText !== undefined)\n out.contextualHelpText = contextualHelpText;\n return out;\n }\n}\n\nexport const fieldGuidanceRegistry = new FieldGuidanceRegistry();\n\n/**\n * Provider interface (optional, for dynamic guidance)\n */\nexport interface FieldGuidanceProvider {\n getFieldGuidance(\n fieldName: string,\n ctx: { toolName: string }\n ): FieldGuidance | null;\n getGlobalGuidance?(\n toolName: string\n ): ToolFieldConfiguration['globalGuidance'] | null;\n}\n","import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n} from 'hedera-agent-kit';\nimport {\n InscriberBuilder,\n InscribeFromUrlTool,\n InscribeFromFileTool,\n InscribeFromBufferTool,\n InscribeHashinalTool,\n RetrieveInscriptionTool,\n} from '@hashgraphonline/standards-agent-kit';\nimport { fieldGuidanceRegistry, type FieldGuidance } from '../../forms/field-guidance-registry';\n\n/**\n * Plugin providing content inscription tools for Hedera\n */\nexport class InscribePlugin extends BasePlugin {\n id = 'inscribe';\n name = 'Inscribe Plugin';\n description =\n 'Content inscription tools for storing data on Hedera Consensus Service';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'inscribe';\n\n private tools: any[] = [];\n private providerId: string | 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. Inscription tools will not be available.'\n );\n return;\n }\n\n try {\n this.initializeTools();\n\n try {\n const provider = {\n getFieldGuidance: (fieldName: string): FieldGuidance | null => {\n if (fieldName === 'name') {\n return {\n suggestions: [\n 'Sunset Landscape #42',\n 'Digital Abstract Art',\n ],\n contextualHelpText:\n 'Create a distinctive name that collectors will find appealing',\n };\n }\n if (fieldName === 'description') {\n return {\n fieldTypeOverride: 'textarea',\n suggestions: ['A beautiful piece representing...'],\n };\n }\n return null;\n },\n getGlobalGuidance: () => ({\n qualityStandards: [\n 'Use meaningful names that describe the artwork or content',\n ],\n }),\n };\n this.providerId = fieldGuidanceRegistry.registerToolProvider(\n /hashinal/i,\n provider,\n { id: 'inscribe:hashinal:provider', priority: 1 }\n );\n } catch (e) {\n this.context.logger.warn('Could not register Inscribe field guidance provider');\n }\n\n this.context.logger.info(\n 'Inscribe Plugin initialized successfully'\n );\n } catch (error) {\n this.context.logger.error(\n 'Failed to initialize Inscribe 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 const inscriberBuilder = new InscriberBuilder(hederaKit);\n\n this.tools = [\n new InscribeFromUrlTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new InscribeFromFileTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new InscribeFromBufferTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new InscribeHashinalTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new RetrieveInscriptionTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n ];\n }\n\n getTools(): HederaTool[] {\n return this.tools;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n if (this.providerId) {\n try {\n fieldGuidanceRegistry.unregisterProvider(this.providerId);\n } catch {}\n this.providerId = null;\n }\n if (this.context?.logger) {\n this.context.logger.info('Inscribe Plugin cleaned up');\n }\n }\n}\n","import { AccountId, Hbar, TransferTransaction } from '@hashgraph/sdk';\nimport BigNumber from 'bignumber.js';\nimport { HederaAgentKit, BaseServiceBuilder } from 'hedera-agent-kit';\nimport { HbarTransferParams } from './types';\n\n/**\n * Custom AccountBuilder that properly handles HBAR decimal conversion\n */\nexport class AccountBuilder extends BaseServiceBuilder {\n constructor(hederaKit: HederaAgentKit) {\n super(hederaKit);\n }\n\n /**\n * Transfers HBAR between accounts with proper decimal handling\n */\n public transferHbar(\n params: HbarTransferParams,\n isUserInitiated: boolean = true\n ): this {\n this.clearNotes();\n const transaction = new TransferTransaction();\n\n if (!params.transfers || params.transfers.length === 0) {\n throw new Error('HbarTransferParams must include at least one transfer.');\n }\n\n let netZeroInTinybars = new BigNumber(0);\n let userTransferProcessedForScheduling = false;\n\n if (\n isUserInitiated &&\n this.kit.userAccountId &&\n (this.kit.operationalMode as string) === 'provideBytes' &&\n params.transfers.length === 1\n ) {\n const receiverTransfer = params.transfers[0];\n const amountValue =\n typeof receiverTransfer.amount === 'string' ||\n typeof receiverTransfer.amount === 'number'\n ? receiverTransfer.amount\n : receiverTransfer.amount.toString();\n\n const amountBigNum = new BigNumber(amountValue);\n\n if (amountBigNum.isPositive()) {\n const recipientAccountId =\n typeof receiverTransfer.accountId === 'string'\n ? AccountId.fromString(receiverTransfer.accountId)\n : receiverTransfer.accountId;\n\n const roundedAmount = amountBigNum.toFixed(8, BigNumber.ROUND_DOWN);\n const sdkHbarAmount = Hbar.fromString(roundedAmount);\n\n this.logger.info(\n `[AccountBuilder.transferHbar] Configuring user-initiated scheduled transfer: ${sdkHbarAmount.toString()} from ${\n this.kit.userAccountId\n } to ${recipientAccountId.toString()}`\n );\n\n this.addNote(\n `Configured HBAR transfer from your account (${\n this.kit.userAccountId\n }) to ${recipientAccountId.toString()} for ${sdkHbarAmount.toString()}.`\n );\n\n transaction.addHbarTransfer(recipientAccountId, sdkHbarAmount);\n transaction.addHbarTransfer(\n AccountId.fromString(this.kit.userAccountId),\n sdkHbarAmount.negated()\n );\n\n userTransferProcessedForScheduling = true;\n }\n }\n\n if (!userTransferProcessedForScheduling) {\n const processedTransfers: Array<{\n accountId: AccountId;\n amount: BigNumber;\n hbar: Hbar;\n }> = [];\n\n for (const transferInput of params.transfers) {\n const accountId =\n typeof transferInput.accountId === 'string'\n ? AccountId.fromString(transferInput.accountId)\n : transferInput.accountId;\n\n const amountValue =\n typeof transferInput.amount === 'string' ||\n typeof transferInput.amount === 'number'\n ? transferInput.amount\n : transferInput.amount.toString();\n\n const amountBigNum = new BigNumber(amountValue);\n const roundedAmount = amountBigNum.toFixed(8, BigNumber.ROUND_DOWN);\n\n this.logger.info(\n `Processing transfer: ${amountValue} HBAR (rounded to ${roundedAmount}) for account ${accountId.toString()}`\n );\n\n const sdkHbarAmount = Hbar.fromString(roundedAmount);\n processedTransfers.push({\n accountId,\n amount: amountBigNum,\n hbar: sdkHbarAmount,\n });\n\n const tinybarsContribution = sdkHbarAmount.toTinybars();\n netZeroInTinybars = netZeroInTinybars.plus(\n tinybarsContribution.toString()\n );\n }\n\n if (!netZeroInTinybars.isZero()) {\n this.logger.warn(\n `Transfer sum not zero: ${netZeroInTinybars.toString()} tinybars off. Adjusting last transfer.`\n );\n\n if (processedTransfers.length > 0) {\n const lastTransfer =\n processedTransfers[processedTransfers.length - 1];\n const adjustment = netZeroInTinybars.dividedBy(-100000000);\n const adjustedAmount = lastTransfer.amount.plus(adjustment);\n const adjustedRounded = adjustedAmount.toFixed(\n 8,\n BigNumber.ROUND_DOWN\n );\n lastTransfer.hbar = Hbar.fromString(adjustedRounded);\n\n this.logger.info(\n `Adjusted last transfer for ${lastTransfer.accountId.toString()} to ${adjustedRounded} HBAR`\n );\n }\n }\n\n for (const transfer of processedTransfers) {\n transaction.addHbarTransfer(transfer.accountId, transfer.hbar);\n }\n }\n\n if (typeof params.memo !== 'undefined') {\n if (params.memo === null) {\n this.logger.warn('Received null for memo in transferHbar.');\n } else {\n transaction.setTransactionMemo(params.memo);\n }\n }\n\n this.setCurrentTransaction(transaction);\n return this;\n }\n}\n","import { z } from 'zod';\nimport { HbarTransferParams } from './types';\nimport { AccountBuilder } from './AccountBuilder';\nimport { BaseHederaTransactionTool, BaseServiceBuilder } from 'hedera-agent-kit';\n\nconst HbarTransferInputSchema = z.object({\n accountId: z\n .string()\n .describe('Account ID for the transfer (e.g., \"0.0.xxxx\").'),\n amount: z\n .union([z.number(), z.string()])\n .describe(\n 'HBAR amount in decimal format (e.g., 1 for 1 HBAR, 0.5 for 0.5 HBAR). Positive for credit, negative for debit. DO NOT multiply by 10^8 for tinybars - just use the HBAR amount directly.'\n ),\n});\n\nconst TransferHbarZodSchemaCore = z.object({\n transfers: z\n .array(HbarTransferInputSchema)\n .min(1)\n .describe(\n 'Array of transfers. For simple transfers from your operator account, just include the recipient with positive amount: [{accountId: \"0.0.800\", amount: 1}]. For complex multi-party transfers, include all parties with negative amounts for senders and positive for receivers.'\n ),\n memo: z.string().optional().describe('Optional. Memo for the transaction.'),\n});\n\n/**\n * A Hedera transaction tool for transferring HBAR between accounts.\n * Supports single and multi-party transfers with automatic balance validation.\n * Extends BaseHederaTransactionTool to handle HBAR transfer transactions on the Hedera Hashgraph.\n */\nexport class TransferHbarTool extends BaseHederaTransactionTool<\n typeof TransferHbarZodSchemaCore\n> {\n name = 'hedera-account-transfer-hbar-v2';\n description =\n 'PRIMARY TOOL FOR HBAR TRANSFERS: Transfers HBAR between accounts. For simple transfers from the operator account, just specify the recipient with a positive amount (e.g., [{accountId: \"0.0.800\", amount: 1}] to send 1 HBAR to 0.0.800). The sender will be automatically added. For multi-party transfers (e.g., \"A sends 5 HBAR to C and B sends 3 HBAR to C\"), include ALL transfers with their amounts (negative for senders, positive for receivers).';\n specificInputSchema = TransferHbarZodSchemaCore;\n namespace = 'account';\n\n\n /**\n * Creates and returns the service builder for account operations.\n * \n * @returns BaseServiceBuilder instance configured for account operations\n */\n protected getServiceBuilder(): BaseServiceBuilder {\n return new AccountBuilder(this.hederaKit) as BaseServiceBuilder;\n }\n\n /**\n * Executes the HBAR transfer using the provided builder and arguments.\n * Validates that all transfers sum to zero before execution.\n * \n * @param builder - The service builder instance for executing transactions\n * @param specificArgs - The validated transfer parameters including transfers array and optional memo\n * @returns Promise that resolves when the transfer is complete\n */\n protected async callBuilderMethod(\n builder: BaseServiceBuilder,\n specificArgs: z.infer<typeof TransferHbarZodSchemaCore>\n ): Promise<void> {\n await (builder as AccountBuilder).transferHbar(\n specificArgs as unknown as HbarTransferParams\n );\n }\n}","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HederaAgentKit } from 'hedera-agent-kit';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\ninterface TokenInfo {\n decimals: number;\n [key: string]: unknown;\n}\n\ninterface ToolWithCall {\n _call(input: unknown): Promise<string>;\n}\n\ninterface AgentKitWithMirrorNode {\n mirrorNode?: {\n getTokenInfo(tokenId: string): Promise<TokenInfo>;\n };\n network: string;\n}\n\nexport class AirdropToolWrapper extends StructuredTool {\n name = 'hedera-hts-airdrop-token';\n description =\n 'Airdrops fungible tokens to multiple recipients. Automatically converts human-readable amounts to smallest units based on token decimals.';\n\n schema = z.object({\n tokenId: z\n .string()\n .describe('The ID of the fungible token to airdrop (e.g., \"0.0.yyyy\").'),\n recipients: z\n .array(\n z.object({\n accountId: z\n .string()\n .describe('Recipient account ID (e.g., \"0.0.xxxx\").'),\n amount: z\n .union([z.number(), z.string()])\n .describe(\n 'Amount in human-readable format (e.g., \"10\" for 10 tokens).'\n ),\n })\n )\n .min(1)\n .describe('Array of recipient objects, each with accountId and amount.'),\n memo: z.string().optional().describe('Optional. Memo for the transaction.'),\n });\n\n private originalTool: StructuredTool & ToolWithCall;\n private agentKit: HederaAgentKit & AgentKitWithMirrorNode;\n private logger: Logger;\n\n constructor(originalTool: StructuredTool, agentKit: unknown) {\n super();\n this.originalTool = originalTool as StructuredTool & ToolWithCall;\n this.agentKit = agentKit as HederaAgentKit & AgentKitWithMirrorNode;\n this.logger = new Logger({ module: 'AirdropToolWrapper' });\n }\n\n async _call(input: z.infer<typeof this.schema>): Promise<string> {\n try {\n this.logger.info(\n `Processing airdrop request for token ${input.tokenId} with ${input.recipients.length} recipients`\n );\n\n const tokenInfo = await this.getTokenInfo(input.tokenId);\n const decimals = tokenInfo.decimals || 0;\n\n this.logger.info(`Token ${input.tokenId} has ${decimals} decimal places`);\n\n const convertedRecipients = input.recipients.map((recipient) => {\n const humanAmount =\n typeof recipient.amount === 'string'\n ? parseFloat(recipient.amount)\n : recipient.amount;\n const smallestUnitAmount = this.convertToSmallestUnits(\n humanAmount,\n decimals\n );\n\n this.logger.info(\n `Converting amount for ${recipient.accountId}: ${humanAmount} tokens → ${smallestUnitAmount} smallest units`\n );\n\n return {\n ...recipient,\n amount: smallestUnitAmount.toString(),\n };\n });\n\n const convertedInput = {\n ...input,\n recipients: convertedRecipients,\n };\n\n this.logger.info(`Calling original airdrop tool with converted amounts`);\n return await this.originalTool._call(convertedInput);\n } catch (error) {\n this.logger.error('Error in airdrop tool wrapper:', error);\n throw error;\n }\n }\n\n private convertToSmallestUnits(amount: number, decimals: number): number {\n return Math.floor(amount * Math.pow(10, decimals));\n }\n\n private async getTokenInfo(tokenId: string): Promise<TokenInfo> {\n try {\n return await this.queryTokenInfo(tokenId);\n } catch (error) {\n throw error;\n }\n }\n\n private async queryTokenInfo(tokenId: string): Promise<TokenInfo> {\n try {\n this.logger.info('Querying token info using mirror node');\n const mirrorNode = this.agentKit.mirrorNode;\n if (!mirrorNode) {\n this.logger.info(\n 'MirrorNode not found in agentKit, attempting to access via fetch'\n );\n const network = this.agentKit.network || 'testnet';\n const mirrorNodeUrl =\n network === 'mainnet'\n ? 'https://mainnet.mirrornode.hedera.com'\n : 'https://testnet.mirrornode.hedera.com';\n\n const response = await fetch(\n `${mirrorNodeUrl}/api/v1/tokens/${tokenId}`\n );\n if (response.ok) {\n const tokenData = (await response.json()) as Record<string, unknown>;\n const decimals = parseInt(String(tokenData.decimals || '0'));\n this.logger.info(\n `Token ${tokenId} found with ${decimals} decimals via API`\n );\n return { ...tokenData, decimals };\n }\n } else {\n const tokenData = await mirrorNode.getTokenInfo(tokenId);\n\n if (tokenData && typeof tokenData.decimals !== 'undefined') {\n const decimals = parseInt(tokenData.decimals.toString()) || 0;\n this.logger.info(`Token ${tokenId} found with ${decimals} decimals`);\n return { ...tokenData, decimals };\n }\n }\n\n throw new Error(`Token data not found or missing decimals field`);\n } catch (error) {\n this.logger.warn(`Failed to query token info for ${tokenId}:`, error);\n\n this.logger.info(\n 'Falling back to assumed 0 decimal places (smallest units)'\n );\n return { decimals: 0 };\n }\n }\n}\n","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 return this.tools as unknown as HederaTool[];\n }\n\n async shutdown(): Promise<void> {\n this.tools = [];\n }\n}\n","/**\n * Registry for field type detection patterns\n * @module FieldTypeRegistry\n */\n\nimport type { FormFieldType } from './types';\n\n/**\n * Pattern-based field type detection rule\n */\nexport interface FieldTypePattern {\n pattern: RegExp | string[];\n type: FormFieldType;\n priority?: number;\n}\n\n/**\n * Registry for managing field type detection patterns\n */\nexport class FieldTypeRegistry {\n private static instance: FieldTypeRegistry;\n private patterns: Map<string, FieldTypePattern> = new Map();\n\n private constructor() {\n this.initializeDefaultPatterns();\n }\n\n /**\n * Get singleton instance\n */\n static getInstance(): FieldTypeRegistry {\n if (!FieldTypeRegistry.instance) {\n FieldTypeRegistry.instance = new FieldTypeRegistry();\n }\n return FieldTypeRegistry.instance;\n }\n\n /**\n * Initialize default field type patterns\n */\n private initializeDefaultPatterns(): void {\n this.register('numeric-supply-exact', {\n pattern: ['maxSupply', 'minSupply', 'totalSupply'],\n type: 'number',\n priority: 15,\n });\n\n this.register('numeric-supply', {\n pattern: /supply$/i,\n type: 'number',\n priority: 10,\n });\n\n this.register('numeric-amounts', {\n pattern: /(?:amount|quantity|count|total|sum|value)$/i,\n type: 'number',\n priority: 8,\n });\n\n this.register('numeric-time', {\n pattern: /(?:period|duration|time|timeout|delay|interval)$/i,\n type: 'number',\n priority: 8,\n });\n\n this.register('numeric-limits', {\n pattern: /(?:limit|max|min|threshold|size|length)$/i,\n type: 'number',\n priority: 7,\n });\n\n this.register('currency', {\n pattern: /(?:price|cost|fee|payment|balance|amount)$/i,\n type: 'currency',\n priority: 9,\n });\n\n this.register('percentage', {\n pattern: /(?:percent|percentage|rate|ratio)$/i,\n type: 'percentage',\n priority: 9,\n });\n\n this.register('boolean-freeze', {\n pattern: ['freezeDefault', 'freeze'],\n type: 'checkbox',\n priority: 10,\n });\n\n this.register('boolean-flags', {\n pattern:\n /(?:is|has|can|should|enable|disable|active|default|allow)(?:[A-Z]|$)/,\n type: 'checkbox',\n priority: 8,\n });\n\n this.register('textarea', {\n pattern: /(?:memo|description|notes|comment|message|content|body|text)$/i,\n type: 'textarea',\n priority: 8,\n });\n\n this.register('array-fees', {\n pattern: ['customFees', 'fees'],\n type: 'array',\n priority: 10,\n });\n\n this.register('array-general', {\n pattern: /(?:list|items|array|collection)$/i,\n type: 'array',\n priority: 7,\n });\n\n this.register('object-options', {\n pattern: ['metaOptions', 'options'],\n type: 'object',\n priority: 10,\n });\n\n this.register('object-config', {\n pattern: /(?:config|settings|configuration|metadata|data|info)$/i,\n type: 'object',\n priority: 7,\n });\n\n this.register('select-type', {\n pattern: /(?:type|kind|category|status|state|mode)$/i,\n type: 'select',\n priority: 7,\n });\n }\n\n /**\n * Register a field type pattern\n */\n register(key: string, pattern: FieldTypePattern): void {\n this.patterns.set(key, pattern);\n }\n\n /**\n * Unregister a field type pattern\n */\n unregister(key: string): boolean {\n return this.patterns.delete(key);\n }\n\n /**\n * Detect field type based on field name\n */\n detectType(fieldName: string): FormFieldType | null {\n const matches: Array<{ type: FormFieldType; priority: number }> = [];\n\n for (const pattern of this.patterns.values()) {\n let isMatch = false;\n\n if (Array.isArray(pattern.pattern)) {\n isMatch = pattern.pattern.some(\n (p) => fieldName === p || fieldName.toLowerCase() === p.toLowerCase()\n );\n } else if (pattern.pattern instanceof RegExp) {\n isMatch = pattern.pattern.test(fieldName);\n }\n\n if (isMatch) {\n matches.push({\n type: pattern.type,\n priority: pattern.priority ?? 5,\n });\n }\n }\n\n if (matches.length > 0) {\n matches.sort((a, b) => b.priority - a.priority);\n return matches[0].type;\n }\n\n return null;\n }\n\n /**\n * Get all registered patterns\n */\n getPatterns(): Map<string, FieldTypePattern> {\n return new Map(this.patterns);\n }\n\n /**\n * Clear all patterns\n */\n clear(): void {\n this.patterns.clear();\n }\n\n /**\n * Reset to default patterns\n */\n reset(): void {\n this.clear();\n this.initializeDefaultPatterns();\n }\n}\n\nexport const fieldTypeRegistry = FieldTypeRegistry.getInstance();\n","/**\n * Common error messages and user feedback strings\n */\nexport const ERROR_MESSAGES = {\n TOO_MANY_REQUESTS: 'Too many requests. Please wait a moment and try again.',\n RATE_LIMITED: \"I'm receiving too many requests right now. Please wait a moment and try again.\",\n SYSTEM_ERROR: 'System error occurred',\n INVALID_INPUT: 'Invalid input provided',\n NETWORK_ERROR: 'Network error occurred',\n} as const;\n\n/**\n * Common success and status messages\n */\nexport const STATUS_MESSAGES = {\n OPERATION_SUCCESSFUL: 'Operation completed successfully',\n PROCESSING: 'Processing your request...',\n READY: 'Ready to process requests',\n INITIALIZING: 'Initializing...',\n} as const;","import { NetworkType } from '@hashgraphonline/standards-sdk';\n\nexport enum EntityFormat {\n TOPIC_ID = 'topicId',\n HRL = 'hrl',\n SCHEDULE_ID = 'scheduleId',\n TOKEN_ID = 'tokenId',\n ADDRESS = 'address',\n SYMBOL = 'symbol',\n SERIAL_NUMBER = 'serialNumber',\n METADATA = 'metadata',\n ACCOUNT_ID = 'accountId',\n ALIAS = 'alias',\n EVM_ADDRESS = 'evmAddress',\n CONTRACT_ID = 'contractId',\n FILE_ID = 'fileId',\n ANY = 'any'\n}\n\nexport interface ConversionContext {\n networkType?: NetworkType;\n sessionId?: string;\n toolName?: string;\n toolPreferences?: Record<string, string>;\n [key: string]: unknown;\n}\n\nexport interface FormatConverter<TSource = string, TTarget = string> {\n sourceFormat: EntityFormat;\n targetFormat: EntityFormat;\n canConvert(source: string, context: ConversionContext): boolean;\n convert(entity: TSource, context: ConversionContext): Promise<TTarget>;\n}","/**\n * Common entity reference patterns used across the application\n */\nexport const ENTITY_PATTERNS = {\n TOPIC_REFERENCE: 'the topic',\n TOKEN_REFERENCE: 'the token',\n ACCOUNT_REFERENCE: 'the account',\n TRANSACTION_REFERENCE: 'the transaction',\n CONTRACT_REFERENCE: 'the contract',\n} as const;\n\n/**\n * Entity type identifiers\n */\nimport { EntityFormat } from '../services/formatters/types';\n\nexport const ENTITY_TYPES = {\n TOPIC: EntityFormat.TOPIC_ID,\n TOKEN: EntityFormat.TOKEN_ID,\n ACCOUNT: EntityFormat.ACCOUNT_ID,\n TRANSACTION: 'transaction',\n CONTRACT: EntityFormat.CONTRACT_ID,\n} as const;\n","/**\n * Form field priorities for progressive disclosure\n */\nexport const FIELD_PRIORITIES = {\n ESSENTIAL: 'essential',\n COMMON: 'common', \n ADVANCED: 'advanced',\n EXPERT: 'expert'\n} as const;\n\n/**\n * Form field types\n */\nexport const FORM_FIELD_TYPES = {\n TEXT: 'text',\n NUMBER: 'number',\n SELECT: 'select',\n CHECKBOX: 'checkbox',\n TEXTAREA: 'textarea',\n FILE: 'file',\n ARRAY: 'array',\n OBJECT: 'object',\n CURRENCY: 'currency',\n PERCENTAGE: 'percentage',\n} as const;","import { z, ZodError } from 'zod';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport type {\n FormConfig,\n FormField,\n ValidationError,\n FormMessage,\n FormFieldType,\n} from './types';\nimport {\n extractRenderConfigs,\n generateFieldOrdering,\n type RenderConfigSchema,\n type ZodSchemaWithRender,\n type ExtractedRenderConfig,\n} from '@hashgraphonline/standards-agent-kit';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport { fieldTypeRegistry } from './field-type-registry';\nimport { fieldGuidanceRegistry } from './field-guidance-registry';\nimport { FIELD_PRIORITIES } from '../constants';\n\ninterface ZodObjectSchema extends z.ZodSchema {\n shape?: Record<string, z.ZodSchema>;\n}\n\nfunction isZodObjectSchema(schema: z.ZodSchema): schema is ZodObjectSchema {\n return typeof schema === 'object' && schema !== null && 'shape' in schema;\n}\n\ntype FieldPriority = 'essential' | 'common' | 'advanced' | 'expert';\n\n/**\n * Generates forms from Zod validation failures\n */\nexport class FormGenerator {\n private logger: Logger;\n\n constructor() {\n this.logger = new Logger({ module: 'FormGenerator' });\n }\n\n /**\n * Creates a form message from a Zod validation error\n * @param error The Zod validation error\n * @param schema The original Zod schema\n * @param toolName Name of the tool that failed validation\n * @param originalPrompt The user's original request\n * @returns FormMessage to send to the chat UI\n */\n generateFormFromError(\n error: ZodError,\n schema: z.ZodSchema,\n toolName: string,\n originalPrompt: string\n ): FormMessage {\n const validationErrors = this.extractValidationErrors(error);\n const missingFields = this.identifyMissingFields(validationErrors, schema);\n const formConfig = this.createFormConfig(schema, missingFields, toolName);\n\n return {\n type: 'form',\n id: `form_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n formConfig,\n originalPrompt,\n toolName,\n validationErrors,\n };\n }\n\n /**\n * Generates a form from a schema and partial input\n * @param schema The Zod schema to generate a form from\n * @param partialInput Any partial input already provided\n * @param context Additional context about the tool\n * @param preCalculatedMissingFields Optional pre-calculated missing fields set. If undefined, includes all fields from schema.\n * @returns FormMessage to send to the chat UI\n */\n async generateFormFromSchema(\n schema: z.ZodSchema,\n partialInput: unknown,\n context: { toolName: string; toolDescription?: string },\n preCalculatedMissingFields?: Set<string>\n ): Promise<FormMessage> {\n let missingFields: Set<string>;\n\n this.logger.info(`🏁 FormGenerator.generateFormFromSchema starting`, {\n toolName: context.toolName,\n partialInput,\n hasSchema: !!schema,\n hasShape: !!(schema && isZodObjectSchema(schema)),\n hasPreCalculatedFields: preCalculatedMissingFields !== undefined,\n preCalculatedFieldsSize: preCalculatedMissingFields?.size || 0,\n });\n\n if (preCalculatedMissingFields !== undefined) {\n missingFields = preCalculatedMissingFields;\n this.logger.info(`📋 Using pre-calculated missing fields`, {\n missingFieldsCount: missingFields.size,\n missingFields: Array.from(missingFields),\n });\n } else {\n missingFields = new Set<string>();\n\n const zodObject = this.extractZodObject(schema);\n if (zodObject) {\n const shape = zodObject.shape;\n for (const fieldName of Object.keys(shape)) {\n missingFields.add(fieldName);\n this.logger.info(\n `⭐ Including all fields from focused schema: ${fieldName}`\n );\n }\n }\n\n this.logger.info(`📋 Using ALL fields from focused schema`, {\n totalFields: zodObject ? Object.keys(zodObject.shape).length : 0,\n missingFieldsCount: missingFields.size,\n missingFields: Array.from(missingFields),\n });\n }\n\n const formConfig = this.createFormConfig(\n schema,\n missingFields,\n context.toolName,\n preCalculatedMissingFields\n );\n\n return {\n type: 'form',\n id: `form_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n formConfig,\n originalPrompt: context.toolDescription || `Complete ${context.toolName}`,\n toolName: context.toolName,\n validationErrors: [],\n };\n }\n\n /**\n * Extracts validation errors from ZodError\n */\n private extractValidationErrors(error: ZodError): ValidationError[] {\n return error.issues.map((issue) => ({\n path: issue.path.map((p) => String(p)),\n message: issue.message,\n code: issue.code,\n }));\n }\n\n /**\n * Identifies which fields are missing or invalid from validation errors\n */\n private identifyMissingFields(\n errors: ValidationError[],\n _schema: z.ZodSchema\n ): Set<string> {\n const missingFields = new Set<string>();\n\n errors.forEach((error) => {\n const fieldPath = error.path.join('.');\n if (fieldPath) {\n missingFields.add(fieldPath);\n }\n });\n\n return missingFields;\n }\n\n /**\n * Creates form configuration from schema\n */\n private createFormConfig(\n schema: z.ZodSchema,\n missingFields: Set<string>,\n toolName: string,\n preCalculatedMissingFields?: Set<string>\n ): FormConfig {\n const extractedConfig = this.extractRenderConfigsSafely(schema);\n const fieldOrdering = this.generateFieldOrderingSafely(schema);\n const fields = this.generateFormFields(\n schema,\n extractedConfig,\n missingFields,\n fieldOrdering,\n preCalculatedMissingFields,\n toolName\n );\n\n const globalGuidance = fieldGuidanceRegistry.getGlobalGuidance(toolName);\n let description = this.generateFormDescription(\n toolName,\n missingFields.size\n );\n\n if (globalGuidance?.qualityStandards) {\n description +=\n '\\n\\nQuality Guidelines:\\n' +\n globalGuidance.qualityStandards\n .map((standard) => `• ${standard}`)\n .join('\\n');\n }\n\n return {\n title: this.generateFormTitle(toolName),\n description,\n fields,\n submitLabel: 'Continue',\n cancelLabel: 'Cancel',\n metadata: {\n toolName,\n missingFieldCount: missingFields.size,\n globalGuidance,\n },\n };\n }\n\n /**\n * Safely extracts render configs from schema\n */\n private extractRenderConfigsSafely(\n schema: z.ZodSchema\n ): ExtractedRenderConfig {\n try {\n if (typeof extractRenderConfigs === 'function') {\n return extractRenderConfigs(schema as unknown as ZodSchemaWithRender);\n }\n } catch (error) {\n this.logger.warn('Could not extract render configs:', error);\n }\n return {\n fields: {},\n groups: {},\n order: [],\n metadata: {},\n };\n }\n\n /**\n * Safely generates field ordering from schema\n */\n private generateFieldOrderingSafely(schema: z.ZodSchema): {\n sections: Array<{ fields: string[] }>;\n } {\n try {\n if (typeof generateFieldOrdering === 'function') {\n const ordering = generateFieldOrdering(\n schema as unknown as ZodSchemaWithRender\n );\n\n const sections = Object.values(ordering.sections).map((section) => ({\n fields: section.fields,\n }));\n return { sections };\n }\n } catch (error) {\n this.logger.warn('Could not generate field ordering:', error);\n }\n return { sections: [] };\n }\n\n /**\n * Determines field priority for progressive disclosure\n */\n private getFieldPriority(\n name: string,\n renderConfig?: RenderConfigSchema,\n isRequired?: boolean\n ): FieldPriority {\n if (renderConfig?.ui?.priority) {\n const priority = renderConfig.ui.priority as string;\n if (Object.values(FIELD_PRIORITIES).includes(priority as FieldPriority)) {\n return priority as FieldPriority;\n }\n }\n\n if (isRequired === true) {\n return FIELD_PRIORITIES.ESSENTIAL;\n }\n\n const ui = renderConfig?.ui as Record<string, unknown> | undefined;\n if (ui?.advanced === true) {\n return FIELD_PRIORITIES.ADVANCED;\n }\n\n if (ui?.expert === true) {\n return FIELD_PRIORITIES.EXPERT;\n }\n\n return FIELD_PRIORITIES.COMMON;\n }\n\n /**\n * Determines which fields should be included in the form\n */\n private determineFieldsToInclude(\n schema: z.ZodSchema,\n missingFields: Set<string>,\n preCalculatedMissingFields?: Set<string>\n ): Set<string> {\n const fieldsToInclude = new Set<string>();\n\n if (preCalculatedMissingFields === undefined) {\n this.logger.info(\n `⭐ Focused schema mode - including ALL fields from schema`\n );\n const allSchemaFields = this.extractFieldsFromSchema(schema);\n allSchemaFields.forEach((fieldName) => {\n fieldsToInclude.add(fieldName);\n this.logger.info(`✅ Including focused schema field: ${fieldName}`);\n });\n } else if (preCalculatedMissingFields.size > 0) {\n this.logger.info(\n `📋 Using ONLY pre-calculated missing fields (${preCalculatedMissingFields.size} fields)`,\n { fields: Array.from(preCalculatedMissingFields) }\n );\n preCalculatedMissingFields.forEach((fieldName) => {\n fieldsToInclude.add(fieldName);\n this.logger.info(`✅ Including pre-calculated field: ${fieldName}`);\n });\n } else {\n this.logger.info(\n '⚠️ No pre-calculated fields, falling back to schema analysis'\n );\n this.includeRequiredMissingFields(schema, missingFields, fieldsToInclude);\n }\n\n return fieldsToInclude;\n }\n\n /**\n * Includes required fields that are missing\n */\n private includeRequiredMissingFields(\n schema: z.ZodSchema,\n missingFields: Set<string>,\n fieldsToInclude: Set<string>\n ): void {\n const allSchemaFields = this.extractFieldsFromSchema(schema);\n allSchemaFields.forEach((fieldName) => {\n const isRequired = this.isFieldRequired(schema, fieldName);\n const isMissing = missingFields.has(fieldName);\n const shouldInclude = isMissing && isRequired;\n\n this.logger.info(`🔍 FormGenerator field inclusion check: ${fieldName}`, {\n isRequired,\n isMissing,\n shouldInclude,\n });\n\n if (shouldInclude) {\n fieldsToInclude.add(fieldName);\n }\n });\n }\n\n /**\n * Creates form fields from ordered field names\n */\n private createOrderedFields(\n fieldsToInclude: Set<string>,\n fieldOrdering: { sections: Array<{ fields: string[] }> },\n extractedConfig: ExtractedRenderConfig,\n schema: z.ZodSchema,\n toolName?: string\n ): FormField[] {\n const fields: FormField[] = [];\n const processedFields = new Set<string>();\n\n if (fieldOrdering.sections.length > 0) {\n const orderedFieldNames = fieldOrdering.sections.flatMap((s) => s.fields);\n orderedFieldNames.forEach((fieldName) => {\n if (fieldsToInclude.has(fieldName) && !processedFields.has(fieldName)) {\n const field = this.createFormField(\n fieldName,\n extractedConfig.fields[fieldName],\n schema,\n fieldName,\n toolName\n );\n if (field) {\n fields.push(field);\n processedFields.add(fieldName);\n }\n }\n });\n }\n\n fieldsToInclude.forEach((fieldName) => {\n if (!processedFields.has(fieldName)) {\n const field = this.createFormField(\n fieldName,\n extractedConfig.fields[fieldName],\n schema,\n fieldName,\n toolName\n );\n if (field) {\n fields.push(field);\n }\n }\n });\n\n return fields;\n }\n\n /**\n * Generates form fields from schema and validation errors\n */\n private generateFormFields(\n schema: z.ZodSchema,\n extractedConfig: ExtractedRenderConfig,\n missingFields: Set<string>,\n fieldOrdering: { sections: Array<{ fields: string[] }> },\n preCalculatedMissingFields?: Set<string>,\n toolName?: string\n ): FormField[] {\n const fieldsToInclude = this.determineFieldsToInclude(\n schema,\n missingFields,\n preCalculatedMissingFields\n );\n\n let fields = this.createOrderedFields(\n fieldsToInclude,\n fieldOrdering,\n extractedConfig,\n schema,\n toolName\n );\n\n if (fields.length === 0 && missingFields.size > 0) {\n fields = Array.from(missingFields)\n .map((fieldName) =>\n this.createFormField(\n fieldName,\n extractedConfig.fields[fieldName],\n schema,\n fieldName,\n toolName\n )\n )\n .filter(\n (field): field is FormField => field !== null && field !== undefined\n );\n }\n\n return fields;\n }\n\n /**\n * Creates a single form field\n */\n private createFormField(\n fieldName: string,\n renderConfig?: RenderConfigSchema,\n schema?: z.ZodSchema,\n fieldPath?: string,\n toolName?: string\n ): FormField {\n const type = this.mapFieldType(renderConfig?.fieldType, schema, fieldPath);\n const isRequired = this.isFieldRequired(schema, fieldPath || fieldName);\n\n const guidance = toolName\n ? fieldGuidanceRegistry.getFieldGuidance(toolName, fieldName)\n : null;\n const finalType = guidance?.fieldTypeOverride || type;\n\n const field: FormField = {\n name: fieldName,\n label: renderConfig?.ui?.label || this.humanizeFieldName(fieldName),\n type: finalType,\n required: isRequired,\n priority: this.getFieldPriority(fieldName, renderConfig, isRequired),\n };\n\n if (guidance) {\n if (guidance.suggestions && guidance.suggestions.length > 0) {\n field.suggestions = guidance.suggestions;\n if (!field.placeholder) {\n field.placeholder = `e.g., ${guidance.suggestions[0]}`;\n }\n }\n\n if (guidance.predefinedOptions) {\n field.options = [\n ...(field.options || []),\n ...guidance.predefinedOptions,\n ];\n }\n\n if (guidance.contextualHelpText) {\n field.helpText = guidance.contextualHelpText;\n }\n\n if (guidance.warnings) {\n field.warnings = guidance.warnings.map((w) => w.message);\n }\n\n if (guidance.validationRules) {\n const { qualityChecks } = guidance.validationRules;\n if (qualityChecks) {\n field.contextualGuidance = {\n qualityStandards: [],\n examples: guidance.suggestions || [],\n avoidPatterns: qualityChecks.forbidTechnicalTerms || [],\n };\n\n if (qualityChecks.minNonTechnicalWords) {\n field.contextualGuidance.qualityStandards?.push(\n `Use at least ${qualityChecks.minNonTechnicalWords} meaningful words`\n );\n }\n\n if (qualityChecks.forbidTechnicalTerms) {\n field.contextualGuidance.qualityStandards?.push(\n `Avoid technical terms like: ${qualityChecks.forbidTechnicalTerms.join(\n ', '\n )}`\n );\n }\n }\n }\n }\n\n if (renderConfig) {\n field.renderConfig = renderConfig;\n }\n\n if (renderConfig?.ui?.placeholder) {\n field.placeholder = renderConfig.ui.placeholder;\n }\n\n if (renderConfig?.ui?.helpText) {\n field.helpText = renderConfig.ui.helpText;\n }\n\n if (renderConfig?.constraints) {\n const validation: Record<string, unknown> = {};\n if (renderConfig.constraints.min !== undefined)\n validation.min = renderConfig.constraints.min;\n if (renderConfig.constraints.max !== undefined)\n validation.max = renderConfig.constraints.max;\n if (renderConfig.constraints.minLength !== undefined)\n validation.minLength = renderConfig.constraints.minLength;\n if (renderConfig.constraints.maxLength !== undefined)\n validation.maxLength = renderConfig.constraints.maxLength;\n if (renderConfig.constraints.pattern !== undefined)\n validation.pattern = renderConfig.constraints.pattern;\n\n if (Object.keys(validation).length > 0) {\n field.validation = validation;\n }\n }\n\n if (renderConfig?.options) {\n field.options = renderConfig.options.map((opt) => ({\n value: String(opt.value),\n label: opt.label,\n ...(opt.disabled !== undefined && { disabled: opt.disabled }),\n }));\n }\n\n return field;\n }\n\n /**\n * Maps render config field type to form field type with fallback inference\n */\n private mapFieldType(\n fieldType?: string,\n schema?: z.ZodSchema,\n fieldPath?: string\n ): FormFieldType {\n if (!fieldType && schema && fieldPath) {\n const inferredType = this.inferTypeFromSchema(schema, fieldPath);\n if (inferredType) {\n return inferredType;\n }\n }\n\n if (!fieldType && fieldPath) {\n const registryType = fieldTypeRegistry.detectType(fieldPath);\n if (registryType) {\n return registryType;\n }\n }\n\n if (!fieldType) {\n return 'text';\n }\n\n const normalizedType = fieldType.toLowerCase();\n\n if (['text', 'string'].includes(normalizedType)) return 'text';\n if (['number', 'integer', 'float', 'decimal'].includes(normalizedType))\n return 'number';\n if (['select', 'enum', 'dropdown'].includes(normalizedType))\n return 'select';\n if (['checkbox', 'boolean', 'bool'].includes(normalizedType))\n return 'checkbox';\n if (['textarea', 'longtext', 'multiline'].includes(normalizedType))\n return 'textarea';\n if (['file', 'upload', 'attachment'].includes(normalizedType))\n return 'file';\n if (['array', 'list'].includes(normalizedType)) return 'array';\n if (['object', 'json'].includes(normalizedType)) return 'object';\n if (['currency', 'money', 'price'].includes(normalizedType))\n return 'currency';\n if (['percentage', 'percent'].includes(normalizedType)) return 'percentage';\n\n return 'text';\n }\n\n /**\n * Converts field name to human-readable label\n */\n private humanizeFieldName(fieldName: string): string {\n return fieldName\n .replace(/([A-Z])/g, ' $1')\n .replace(/_/g, ' ')\n .replace(/\\./g, ' ')\n .trim()\n .split(' ')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n }\n\n /**\n * Generates a title for the form\n */\n private generateFormTitle(toolName: string): string {\n const cleanName = toolName\n .replace(/Tool$/, '')\n .replace(/Hedera/g, '')\n .replace(/([A-Z])/g, ' $1')\n .trim();\n\n return `Complete ${cleanName} Information`;\n }\n\n /**\n * Safely extracts ZodObject from a schema, returns null if not an object schema\n */\n private extractZodObject(\n schema: z.ZodSchema\n ): z.ZodObject<z.ZodRawShape> | null {\n try {\n const def = (schema as z.ZodType)._def as { typeName?: string };\n if (def && def.typeName === 'ZodObject') {\n return schema as z.ZodObject<z.ZodRawShape>;\n }\n } catch (error) {\n this.logger.debug('Could not extract ZodObject from schema:', error);\n }\n return null;\n }\n\n /**\n * Extracts field names from Zod schema structure\n */\n private extractFieldsFromSchema(schema: z.ZodSchema): string[] {\n const fields: string[] = [];\n\n const zodObject = this.extractZodObject(schema);\n if (zodObject) {\n fields.push(...Object.keys(zodObject.shape));\n return fields;\n }\n\n try {\n const def = (schema as z.ZodType)._def as {\n typeName?: string;\n options?: z.ZodType[];\n };\n if (def && def.typeName === 'ZodUnion' && def.options) {\n const firstOption = def.options[0];\n const firstOptionObject = this.extractZodObject(firstOption);\n if (firstOptionObject) {\n fields.push(...Object.keys(firstOptionObject.shape));\n }\n }\n } catch (error) {\n this.logger.debug(\n 'Could not extract fields from schema structure:',\n error\n );\n }\n\n return fields;\n }\n\n /**\n * Infers field type from Zod schema\n */\n private inferTypeFromSchema(\n schema: z.ZodSchema,\n fieldPath: string\n ): FormFieldType | null {\n try {\n const zodObject = this.extractZodObject(schema);\n if (!zodObject) return null;\n\n const shape = zodObject.shape;\n if (!shape) return null;\n\n let fieldSchema = shape[fieldPath] as z.ZodType | undefined;\n if (!fieldSchema) return null;\n\n const fieldDef = fieldSchema._def as {\n typeName?: string;\n innerType?: z.ZodType;\n };\n if (\n fieldDef &&\n fieldDef.typeName === 'ZodOptional' &&\n fieldDef.innerType\n ) {\n fieldSchema = fieldDef.innerType;\n }\n\n if (!fieldSchema || !fieldSchema._def) return null;\n\n const typeDef = fieldSchema._def as { typeName?: string };\n const fieldTypeName = typeDef.typeName;\n const lowerPath = fieldPath.toLowerCase();\n\n switch (fieldTypeName) {\n case 'ZodString':\n if (lowerPath.includes('memo') || lowerPath.includes('description')) {\n return 'textarea';\n }\n return 'text';\n case 'ZodNumber':\n if (lowerPath.includes('percent')) {\n return 'percentage';\n }\n if (lowerPath.includes('price') || lowerPath.includes('cost')) {\n return 'currency';\n }\n return 'number';\n case 'ZodBoolean':\n return 'checkbox';\n case 'ZodEnum':\n case 'ZodNativeEnum':\n return 'select';\n case 'ZodArray':\n return 'array';\n case 'ZodObject':\n return 'object';\n default:\n return 'text';\n }\n } catch (error) {\n this.logger.debug('Could not infer type from schema:', error);\n }\n return null;\n }\n\n /**\n * Determines if a field is required based on the Zod schema\n */\n private isFieldRequired(schema?: z.ZodSchema, fieldPath?: string): boolean {\n if (!schema || !fieldPath) {\n return false;\n }\n\n try {\n const zodObject = this.extractZodObject(schema);\n if (!zodObject) return false;\n\n const shape = zodObject.shape;\n if (!shape || !shape[fieldPath]) return false;\n\n const fieldSchema = shape[fieldPath] as z.ZodType;\n if (!fieldSchema || !fieldSchema._def) return true;\n\n const fieldDef = fieldSchema._def as {\n typeName?: string;\n defaultValue?: unknown;\n };\n const typeName = fieldDef.typeName;\n\n if (typeName === 'ZodOptional') {\n return false;\n }\n\n if (typeName === 'ZodDefault') {\n return false;\n }\n\n if (fieldDef.defaultValue !== undefined) {\n return false;\n }\n\n return true;\n } catch (error) {\n this.logger.debug(\n `Could not determine if field ${fieldPath} is required:`,\n error\n );\n }\n\n return false;\n }\n\n /**\n * Generates a description for the form\n */\n private generateFormDescription(\n toolName: string,\n fieldCount: number\n ): string {\n if (fieldCount === 0) {\n return 'Please provide the required information to continue with your request.';\n }\n\n return `Please provide the following ${fieldCount} required field${\n fieldCount !== 1 ? 's' : ''\n } to continue with your request.`;\n }\n\n /**\n * Generates JSON Schema and uiSchema from a Zod schema for use with @rjsf/core\n * @param zodSchema The Zod schema to convert\n * @param partialInput Existing input data to filter out fields that already have values\n * @param missingFields Set of fields that are missing and should be shown\n * @returns Object containing jsonSchema and uiSchema\n */\n public generateJsonSchemaForm(\n zodSchema: z.ZodObject<z.ZodRawShape>,\n partialInput?: Record<string, unknown>,\n missingFields?: Set<string>\n ): {\n jsonSchema: Record<string, unknown>;\n uiSchema: Record<string, unknown>;\n } {\n const fullJsonSchema = zodToJsonSchema(zodSchema, {\n target: 'jsonSchema7',\n });\n\n const uiSchema: Record<string, Record<string, unknown>> = {};\n\n let jsonSchema = fullJsonSchema;\n if (missingFields && missingFields.size > 0) {\n const fullSchemaAsObject = fullJsonSchema as {\n properties?: Record<string, unknown>;\n required?: string[];\n [key: string]: unknown;\n };\n if (\n fullSchemaAsObject.properties &&\n typeof fullSchemaAsObject.properties === 'object'\n ) {\n const filteredSchema = {\n ...fullSchemaAsObject,\n type: 'object' as const,\n properties: {} as Record<string, unknown>,\n required: [] as string[],\n };\n\n let fieldsAdded = 0;\n missingFields.forEach((fieldName) => {\n if (\n fullSchemaAsObject.properties &&\n fullSchemaAsObject.properties[fieldName]\n ) {\n filteredSchema.properties[fieldName] =\n fullSchemaAsObject.properties[fieldName];\n fieldsAdded++;\n }\n });\n\n if (Array.isArray(fullSchemaAsObject.required)) {\n filteredSchema.required = fullSchemaAsObject.required.filter(\n (field: string) => missingFields.has(field)\n );\n }\n\n if (fieldsAdded > 0) {\n jsonSchema = filteredSchema;\n }\n }\n }\n\n const fieldNames = this.extractFieldsFromSchema(zodSchema);\n\n fieldNames.forEach((fieldName) => {\n const isRequired = this.isFieldRequired(zodSchema, fieldName);\n const priority = this.getFieldPriority(fieldName, undefined, isRequired);\n const lower = fieldName.toLowerCase();\n\n if (\n lower === 'attributes' ||\n lower === 'metadata' ||\n lower === 'properties'\n ) {\n uiSchema[fieldName] = {\n 'ui:options': {\n collapsible: true,\n collapsed: true,\n },\n };\n }\n\n switch (priority) {\n case 'essential':\n if (isRequired) {\n uiSchema[fieldName] = {\n ...uiSchema[fieldName],\n 'ui:help': 'Required field',\n };\n }\n break;\n case 'advanced':\n case 'expert':\n uiSchema[fieldName] = {\n ...uiSchema[fieldName],\n 'ui:options': {\n ...(uiSchema[fieldName]?.['ui:options'] as\n | Record<string, unknown>\n | undefined),\n collapsed: true,\n },\n };\n break;\n }\n });\n\n return { jsonSchema, uiSchema };\n }\n}\n","import { StructuredTool } from '@langchain/core/tools';\nimport { ZodError, z } from 'zod';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport { FormGenerator } from './form-generator';\nimport { isFormValidatable } from '@hashgraphonline/standards-agent-kit';\nimport type { FormMessage, FormSubmission } from './types';\n\n/**\n * Tool execution result with optional form requirement\n */\nexport interface ToolExecutionResult {\n success: boolean;\n output: string;\n metadata?: Record<string, unknown>;\n requiresForm?: boolean;\n formMessage?: FormMessage;\n error?: string;\n}\n\n/**\n * Context for form generation operations\n */\nexport interface FormGenerationContext {\n tool: StructuredTool;\n input: unknown;\n sessionId?: string;\n userId?: string;\n missingFields?: Set<string>;\n}\n\n/**\n * FormEngine handles all form generation and validation logic\n */\nexport class FormEngine {\n private formGenerator: FormGenerator;\n private logger: Logger;\n\n constructor(logger?: Logger) {\n this.formGenerator = new FormGenerator();\n this.logger = logger || new Logger({ module: 'FormEngine' });\n }\n\n /**\n * Generate a form for a tool with the given input\n */\n async generateForm(\n toolName: string,\n tool: StructuredTool,\n input: unknown,\n context?: Partial<FormGenerationContext>\n ): Promise<FormMessage | null> {\n const fullContext: FormGenerationContext = {\n tool,\n input,\n ...context,\n };\n\n try {\n if (isFormValidatable(tool)) {\n return await this.generateFormValidatableForm(tool, input, fullContext);\n }\n\n if (input instanceof ZodError) {\n return await this.generateErrorBasedForm(tool, input, fullContext);\n }\n\n if (this.hasRenderConfig(tool)) {\n return await this.generateRenderConfigForm(tool, input, fullContext);\n }\n\n if (this.isZodObject(tool.schema)) {\n return await this.generateSchemaBasedForm(tool, input, fullContext);\n }\n\n return null;\n } catch (error) {\n this.logger.error(`Failed to generate form for tool: ${toolName}`, {\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n /**\n * Process a form submission\n */\n async processSubmission(\n submission: FormSubmission,\n context?: {\n originalInput?: Record<string, unknown>;\n schema?: unknown;\n }\n ): Promise<Record<string, unknown>> {\n this.validateSubmission(submission);\n\n const baseToolInput = this.extractBaseToolInput(context);\n const submissionData = this.extractSubmissionData(submission);\n\n return this.mergeInputData(baseToolInput, submissionData);\n }\n\n /**\n * Check if a tool requires form generation based on input\n */\n shouldGenerateForm(tool: StructuredTool, input: unknown): boolean {\n const inputRecord = input as Record<string, unknown>;\n if (inputRecord?.__fromForm === true || inputRecord?.renderForm === false) {\n return false;\n }\n\n if (isFormValidatable(tool)) {\n try {\n const formValidatableTool = tool as {\n shouldGenerateForm: (input: unknown) => boolean;\n };\n return formValidatableTool.shouldGenerateForm(input);\n } catch (error) {\n this.logger.error(\n `Error calling shouldGenerateForm() on ${tool.name}:`,\n error\n );\n return false;\n }\n }\n\n const validation = this.validateInput(tool, input);\n return !validation.isValid;\n }\n\n /**\n * Generate form from error context\n */\n async generateFormFromError(\n error: ZodError,\n toolName: string,\n toolSchema: z.ZodSchema,\n originalPrompt: string\n ): Promise<FormMessage> {\n return this.formGenerator.generateFormFromError(\n error,\n toolSchema as z.ZodType<unknown, z.ZodTypeDef, unknown>,\n toolName,\n originalPrompt\n );\n }\n\n /**\n * Generate form for FormValidatable tools\n */\n private async generateFormValidatableForm(\n tool: StructuredTool,\n input: unknown,\n _context: FormGenerationContext\n ): Promise<FormMessage> {\n const { schemaToUse, isFocusedSchema } = this.resolveFormSchema(tool);\n const missingFields = this.determineMissingFields(\n tool,\n input,\n schemaToUse,\n isFocusedSchema\n );\n\n return this.generateFormWithSchema(tool, input, schemaToUse, missingFields);\n }\n\n /**\n * Generate form based on schema validation\n */\n private async generateSchemaBasedForm(\n tool: StructuredTool,\n input: unknown,\n context: FormGenerationContext\n ): Promise<FormMessage> {\n const schema = tool.schema;\n\n const formMessage = await this.formGenerator.generateFormFromSchema(\n schema as z.ZodType<unknown, z.ZodTypeDef, unknown>,\n input,\n {\n toolName: tool.name,\n toolDescription: tool.description,\n },\n context.missingFields\n );\n\n if (this.isZodObject(schema)) {\n try {\n const { jsonSchema, uiSchema } =\n this.formGenerator.generateJsonSchemaForm(\n schema,\n input as Record<string, unknown> | undefined,\n context.missingFields || new Set()\n );\n formMessage.jsonSchema = jsonSchema;\n formMessage.uiSchema = uiSchema;\n } catch (error) {\n this.logger.warn(\n 'Failed to generate JSON Schema for schema-based tool:',\n error\n );\n }\n }\n\n formMessage.partialInput = input;\n return formMessage;\n }\n\n /**\n * Generate form based on render config\n */\n private async generateRenderConfigForm(\n tool: StructuredTool,\n input: unknown,\n context: FormGenerationContext\n ): Promise<FormMessage> {\n const schema = tool.schema;\n const renderConfig = this.extractRenderConfig(tool);\n\n const formMessage = await this.formGenerator.generateFormFromSchema(\n schema as z.ZodType<unknown, z.ZodTypeDef, unknown>,\n input,\n {\n toolName: tool.name,\n toolDescription: tool.description,\n },\n context.missingFields\n );\n\n if (renderConfig) {\n formMessage.formConfig.metadata = {\n ...formMessage.formConfig.metadata,\n renderConfig,\n };\n }\n\n formMessage.partialInput = input;\n return formMessage;\n }\n\n /**\n * Generate form from Zod validation error\n */\n private async generateErrorBasedForm(\n tool: StructuredTool,\n error: ZodError,\n context: FormGenerationContext\n ): Promise<FormMessage> {\n return this.formGenerator.generateFormFromError(\n error,\n tool.schema as z.ZodType<unknown, z.ZodTypeDef, unknown>,\n tool.name,\n context.input ? String(context.input) : ''\n );\n }\n\n /**\n * Validate input against tool schema\n */\n private validateInput(\n tool: StructuredTool,\n input: unknown\n ): { isValid: boolean; errors?: string[] } {\n try {\n const zodSchema = tool.schema as z.ZodType<\n unknown,\n z.ZodTypeDef,\n unknown\n >;\n zodSchema.parse(input);\n return { isValid: true };\n } catch (error) {\n if (error instanceof ZodError) {\n const errors = error.errors.map(\n (err) => `${err.path.join('.')}: ${err.message}`\n );\n return { isValid: false, errors };\n }\n return { isValid: false, errors: ['Validation failed'] };\n }\n }\n\n /**\n * Check if schema is ZodObject\n */\n private isZodObject(schema: unknown): schema is z.ZodObject<z.ZodRawShape> {\n if (!schema || typeof schema !== 'object') {\n return false;\n }\n const candidate = schema as { _def?: { typeName?: string } };\n return Boolean(candidate._def && candidate._def.typeName === 'ZodObject');\n }\n\n /**\n * Check if tool has render configuration\n */\n private hasRenderConfig(tool: StructuredTool): boolean {\n const schema = tool.schema as Record<string, unknown>;\n return !!(schema && schema._renderConfig);\n }\n\n /**\n * Extract render configuration from tool\n */\n private extractRenderConfig(\n tool: StructuredTool\n ): Record<string, unknown> | undefined {\n const schema = tool.schema as Record<string, unknown>;\n return schema?._renderConfig as Record<string, unknown> | undefined;\n }\n\n /**\n * Resolve form schema for FormValidatable tools\n */\n private resolveFormSchema(tool: StructuredTool): {\n schemaToUse: z.ZodSchema;\n isFocusedSchema: boolean;\n } {\n const formValidatableTool = tool as {\n getFormSchema?: () => z.ZodSchema | null;\n };\n\n if (formValidatableTool.getFormSchema) {\n const focusedSchema = formValidatableTool.getFormSchema();\n if (focusedSchema) {\n return { schemaToUse: focusedSchema, isFocusedSchema: true };\n }\n }\n\n return { schemaToUse: tool.schema as z.ZodSchema, isFocusedSchema: false };\n }\n\n /**\n * Determine missing fields for form generation\n */\n private determineMissingFields(\n tool: StructuredTool,\n input: unknown,\n _schema: z.ZodSchema,\n _isFocusedSchema: boolean\n ): Set<string> {\n const missingFields = new Set<string>();\n\n if (!input || typeof input !== 'object') {\n return missingFields;\n }\n\n const inputRecord = input as Record<string, unknown>;\n const formValidatableTool = tool as {\n isFieldEmpty?: (fieldName: string, value: unknown) => boolean;\n getEssentialFields?: () => string[];\n };\n\n if (formValidatableTool.getEssentialFields) {\n const essentialFields = formValidatableTool.getEssentialFields();\n for (const field of essentialFields) {\n if (\n !(field in inputRecord) ||\n (formValidatableTool.isFieldEmpty &&\n formValidatableTool.isFieldEmpty(field, inputRecord[field]))\n ) {\n missingFields.add(field);\n }\n }\n }\n\n return missingFields;\n }\n\n /**\n * Generate form with resolved schema\n */\n private async generateFormWithSchema(\n tool: StructuredTool,\n input: unknown,\n schema: z.ZodSchema,\n missingFields: Set<string>\n ): Promise<FormMessage> {\n const formMessage = await this.formGenerator.generateFormFromSchema(\n schema as z.ZodType<unknown, z.ZodTypeDef, unknown>,\n input,\n {\n toolName: tool.name,\n toolDescription: tool.description,\n },\n missingFields\n );\n\n if (this.isZodObject(schema)) {\n try {\n const { jsonSchema, uiSchema } =\n this.formGenerator.generateJsonSchemaForm(\n schema,\n input as Record<string, unknown> | undefined,\n missingFields\n );\n formMessage.jsonSchema = jsonSchema;\n formMessage.uiSchema = uiSchema;\n } catch (error) {\n this.logger.warn('Failed to generate JSON Schema:', error);\n }\n }\n\n formMessage.partialInput = input;\n return formMessage;\n }\n\n /**\n * Validate form submission\n */\n private validateSubmission(submission: FormSubmission): void {\n if (!submission.toolName) {\n throw new Error('Tool name is required in form submission');\n }\n if (!submission.parameters) {\n throw new Error('Parameters are required in form submission');\n }\n }\n\n /**\n * Extract base tool input from context\n */\n private extractBaseToolInput(context?: {\n originalInput?: Record<string, unknown>;\n }): Record<string, unknown> {\n return context?.originalInput || {};\n }\n\n /**\n * Extract submission data\n */\n private extractSubmissionData(\n submission: FormSubmission\n ): Record<string, unknown> {\n return {\n ...submission.parameters,\n __fromForm: true,\n };\n }\n\n /**\n * Merge input data\n */\n private mergeInputData(\n baseInput: Record<string, unknown>,\n submissionData: Record<string, unknown>\n ): Record<string, unknown> {\n return {\n ...baseInput,\n ...submissionData,\n };\n }\n\n /**\n * Get registered strategies\n */\n getRegisteredStrategies(): string[] {\n return ['FormValidatable', 'SchemaBased', 'RenderConfig', 'ZodErrorBased'];\n }\n\n /**\n * Get registered middleware\n */\n getRegisteredMiddleware(): string[] {\n return ['FormSubmissionValidator'];\n }\n}\n","/**\n * HCS-12 HashLink block structure for interactive content rendering\n */\ninterface HCS12BlockResult {\n blockId: string;\n hashLink: string;\n template: string;\n attributes: Record<string, unknown>;\n}\n\n/**\n * Utility class for formatting tool responses into user-friendly messages\n */\nexport class ResponseFormatter {\n /**\n * Checks if a parsed response contains HashLink block data for interactive rendering\n */\n static isHashLinkResponse(parsed: unknown): boolean {\n if (!parsed || typeof parsed !== 'object') {\n return false;\n }\n\n const responseObj = parsed as Record<string, unknown>;\n return !!(\n responseObj.success === true &&\n responseObj.type === 'inscription' &&\n responseObj.hashLinkBlock &&\n typeof responseObj.hashLinkBlock === 'object'\n );\n }\n\n /**\n * Formats HashLink block response with simple text confirmation\n * HTML template rendering is handled by HashLinkBlockRenderer component via metadata\n */\n static formatHashLinkResponse(parsed: Record<string, unknown>): string {\n const hashLinkBlock = parsed.hashLinkBlock as HCS12BlockResult;\n const metadata = parsed.metadata as Record<string, unknown> || {};\n const inscription = parsed.inscription as Record<string, unknown> || {};\n\n let message = '✅ Interactive content created successfully!\\n\\n';\n\n if (metadata.name) {\n message += `**${metadata.name}**\\n`;\n }\n\n if (metadata.description) {\n message += `${metadata.description}\\n\\n`;\n }\n\n if (inscription.topicId || hashLinkBlock.attributes.topicId) {\n message += `📍 **Topic ID:** ${inscription.topicId || hashLinkBlock.attributes.topicId}\\n`;\n }\n\n if (inscription.hrl || hashLinkBlock.attributes.hrl) {\n message += `🔗 **HRL:** ${inscription.hrl || hashLinkBlock.attributes.hrl}\\n`;\n }\n\n if (inscription.cdnUrl) {\n message += `🌐 **CDN URL:** ${inscription.cdnUrl}\\n`;\n }\n\n if (metadata.creator) {\n message += `👤 **Creator:** ${metadata.creator}\\n`;\n }\n\n message += '\\n⚡ Interactive content will load below';\n\n return message.trim();\n }\n\n /**\n * Checks if a parsed response is an inscription response that needs formatting\n */\n static isInscriptionResponse(parsed: unknown): boolean {\n if (!parsed || typeof parsed !== 'object') {\n return false;\n }\n\n const responseObj = parsed as Record<string, unknown>;\n return !!(\n responseObj.success === true &&\n responseObj.type === 'inscription' &&\n responseObj.inscription &&\n typeof responseObj.inscription === 'object'\n );\n }\n\n /**\n * Formats inscription response into user-friendly message\n */\n static formatInscriptionResponse(parsed: Record<string, unknown>): string {\n const inscription = parsed.inscription as Record<string, unknown>;\n const metadata = parsed.metadata as Record<string, unknown> || {};\n const title = parsed.title as string || 'Inscription Complete';\n\n let message = `✅ ${title}\\n\\n`;\n\n if (metadata.name) {\n message += `**${metadata.name}**\\n`;\n }\n\n if (metadata.description) {\n message += `${metadata.description}\\n\\n`;\n }\n\n if (inscription.topicId) {\n message += `📍 **Topic ID:** ${inscription.topicId}\\n`;\n }\n\n if (inscription.hrl) {\n message += `🔗 **HRL:** ${inscription.hrl}\\n`;\n }\n\n if (inscription.cdnUrl) {\n message += `🌐 **CDN URL:** ${inscription.cdnUrl}\\n`;\n }\n\n if (metadata.creator) {\n message += `👤 **Creator:** ${metadata.creator}\\n`;\n }\n\n return message.trim();\n }\n\n /**\n * Main formatting method that determines the best response format\n */\n static formatResponse(toolOutput: string): string {\n try {\n const parsed = JSON.parse(toolOutput);\n \n if (ResponseFormatter.isHashLinkResponse(parsed)) {\n return ResponseFormatter.formatHashLinkResponse(parsed);\n }\n \n if (ResponseFormatter.isInscriptionResponse(parsed)) {\n return ResponseFormatter.formatInscriptionResponse(parsed);\n }\n \n return toolOutput;\n } catch {\n return toolOutput;\n }\n }\n}","import { AgentExecutor } from 'langchain/agents';\nimport { ZodError, z } from 'zod';\nimport { FormGenerator } from '../forms/form-generator';\nimport type { FormMessage, FormSubmission } from '../forms/types';\nimport { FormEngine } from '../forms/form-engine';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport type { AgentAction, AgentFinish, AgentStep } from 'langchain/agents';\nimport type { ToolInterface } from '@langchain/core/tools';\nimport { isFormValidatable } from '@hashgraphonline/standards-agent-kit';\nimport type { ChainValues } from '@langchain/core/utils/types';\nimport type { CallbackManagerForChainRun } from '@langchain/core/callbacks/manager';\nimport type { RunnableConfig } from '@langchain/core/runnables';\nimport { ResponseFormatter } from '../utils/response-formatter';\n\ntype BasicFieldType = 'text' | 'number' | 'select' | 'checkbox' | 'textarea';\n\nconst globalPendingForms: Map<string, PendingFormData> = new Map();\n\ninterface HashLinkBlock {\n blockId: string;\n hashLink: string;\n template: string;\n attributes: Record<string, unknown>;\n}\n\ninterface HashLinkResponse {\n hasHashLinkBlocks: boolean;\n hashLinkBlock?: HashLinkBlock;\n message: string;\n}\n\ninterface ToolWithOriginal {\n originalTool?: {\n call?: (args: Record<string, unknown>) => Promise<string>;\n };\n}\n\ninterface ActionWithToolInput {\n toolInput?: Record<string, unknown>;\n}\n\ninterface ZodSchemaDefinition {\n _def?: {\n typeName?: string;\n shape?: (() => Record<string, z.ZodTypeAny>) | Record<string, z.ZodTypeAny>;\n innerType?: z.ZodTypeAny;\n defaultValue?: unknown;\n };\n}\n\ninterface ToolWrapper {\n executeOriginal?: (args: Record<string, unknown>) => Promise<string>;\n getOriginalTool?: () => {\n _call?: (args: Record<string, unknown>) => Promise<string>;\n call?: (args: Record<string, unknown>) => Promise<string>;\n };\n originalTool?: {\n _call?: (args: Record<string, unknown>) => Promise<string>;\n call?: (args: Record<string, unknown>) => Promise<string>;\n };\n call?: (args: Record<string, unknown>) => Promise<string>;\n}\n\ninterface CallableTool {\n _call?: (args: Record<string, unknown>) => Promise<string>;\n call?: (args: Record<string, unknown>) => Promise<string>;\n}\n\ninterface ToolWithSchema {\n schema?: Record<string, unknown>;\n}\n\ninterface PendingFormData {\n toolName: string;\n originalInput: unknown;\n originalToolInput?: unknown;\n schema: unknown;\n toolRef?: ToolInterface | undefined;\n originalToolRef?: ToolWithOriginal['originalTool'];\n}\n\ninterface ToolResponse {\n requiresForm?: boolean;\n formMessage?: {\n id: string;\n [key: string]: unknown;\n };\n message?: string;\n hashLinkBlock?: HashLinkBlock;\n success?: boolean;\n inscription?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\ninterface IntermediateStepData {\n action?: {\n tool?: string;\n [key: string]: unknown;\n };\n observation?: unknown;\n}\n\ninterface HashLinkBlock {\n blockId: string;\n hashLink: string;\n template: string;\n attributes: Record<string, unknown>;\n}\n\ninterface ResponseMetadataWithHashLink {\n hashLinkBlock?: HashLinkBlock;\n [key: string]: unknown;\n}\n\n/**\n * Parameter preprocessing callback interface\n */\nexport interface ParameterPreprocessingCallback {\n (toolName: string, parameters: Record<string, unknown>): Promise<\n Record<string, unknown>\n >;\n}\n\n/**\n * Agent executor that intercepts Zod validation errors and generates forms,\n * and processes HashLink block responses for rich UI rendering\n */\nexport class FormAwareAgentExecutor extends AgentExecutor {\n private formGenerator: FormGenerator;\n private formEngine: FormEngine;\n private formLogger: Logger;\n private pendingForms: Map<string, PendingFormData> = new Map();\n private parameterPreprocessingCallback:\n | ParameterPreprocessingCallback\n | undefined;\n\n /**\n * Type guard to check if a Zod type is a ZodObject\n */\n private isZodObject(schema: unknown): schema is z.ZodObject<z.ZodRawShape> {\n return schema instanceof z.ZodObject;\n }\n\n /**\n * Type guard to check if metadata has hashLinkBlock\n */\n private hasHashLinkBlock(\n metadata: unknown\n ): metadata is ResponseMetadataWithHashLink & {\n hashLinkBlock: HashLinkBlock;\n } {\n return (\n typeof metadata === 'object' &&\n metadata !== null &&\n 'hashLinkBlock' in metadata &&\n typeof (metadata as Record<string, unknown>).hashLinkBlock === 'object' &&\n (metadata as Record<string, unknown>).hashLinkBlock !== null\n );\n }\n\n constructor(...args: ConstructorParameters<typeof AgentExecutor>) {\n super(...args);\n this.formGenerator = new FormGenerator();\n this.formEngine = new FormEngine(\n new Logger({ module: 'FormAwareAgentExecutor.FormEngine' })\n );\n this.formLogger = new Logger({ module: 'FormAwareAgentExecutor' });\n this.parameterPreprocessingCallback = undefined;\n }\n\n /**\n * Set parameter preprocessing callback\n */\n setParameterPreprocessingCallback(\n callback: ParameterPreprocessingCallback | undefined\n ): void {\n this.parameterPreprocessingCallback = callback;\n }\n\n /**\n * BULLETPROOF TOOL INTERCEPTION\n * Override the single-step execution to intercept tool calls BEFORE LangChain processes them\n */\n override async _takeNextStep(\n nameToolMap: Record<string, ToolInterface>,\n inputs: ChainValues,\n intermediateSteps: AgentStep[],\n runManager?: CallbackManagerForChainRun,\n config?: RunnableConfig\n ): Promise<AgentFinish | AgentStep[]> {\n this.formLogger.info('🛡️ BULLETPROOF INTERCEPTION: _takeNextStep called', {\n availableTools: Object.keys(nameToolMap),\n inputKeys: Object.keys(inputs),\n });\n\n const result = await this.agent.plan(\n intermediateSteps,\n inputs,\n runManager?.getChild()\n );\n\n if ('returnValues' in result) {\n this.formLogger.info('Agent returned finish action, passing through');\n return result;\n }\n\n const action = result as AgentAction;\n const toolName = action.tool;\n const toolInput = action.toolInput;\n\n this.formLogger.info(`🎯 INTERCEPTING TOOL CALL: ${toolName}`, {\n toolInput,\n hasInNameToolMap: toolName in nameToolMap,\n toolInputKeys: Object.keys(toolInput || {}),\n });\n\n const tool =\n nameToolMap[toolName] || this.tools.find((t) => t.name === toolName);\n\n if (!tool) {\n this.formLogger.error(`Tool ${toolName} not found in registry`);\n throw new Error(`Tool \"${toolName}\" not found`);\n }\n\n let shouldGenerateForm = false;\n\n if (isFormValidatable(tool)) {\n this.formLogger.info(\n `🔍 Tool ${toolName} implements FormValidatable, checking shouldGenerateForm()`,\n {\n toolInput,\n }\n );\n\n try {\n shouldGenerateForm = tool.shouldGenerateForm(toolInput);\n this.formLogger.info(\n `FormValidatable.shouldGenerateForm() result: ${shouldGenerateForm}`,\n {\n toolName,\n toolInput,\n }\n );\n } catch (error) {\n this.formLogger.error(\n `Error calling shouldGenerateForm() on ${toolName}:`,\n error\n );\n shouldGenerateForm = false;\n }\n }\n\n if (shouldGenerateForm) {\n this.formLogger.info(`🚨 FORM GENERATION TRIGGERED for ${toolName}`);\n\n try {\n let schemaToUse: z.ZodSchema;\n let isFocusedSchema = false;\n\n if (isFormValidatable(tool)) {\n this.formLogger.info(\n `🎯 Tool ${toolName} is FormValidatable, attempting to get focused schema`\n );\n try {\n const focusedSchema = tool.getFormSchema();\n if (focusedSchema) {\n schemaToUse = focusedSchema;\n isFocusedSchema = true;\n this.formLogger.info(\n `✅ Successfully obtained focused schema for ${toolName}`\n );\n } else {\n this.formLogger.warn(\n `getFormSchema() returned null/undefined for ${toolName}, using default schema`\n );\n schemaToUse = tool.schema;\n isFocusedSchema = false;\n }\n } catch (error) {\n this.formLogger.error(\n `Failed to get focused schema from ${toolName}:`,\n error\n );\n this.formLogger.info(\n `Falling back to default schema for ${toolName}`\n );\n schemaToUse = tool.schema;\n isFocusedSchema = false;\n }\n } else {\n this.formLogger.info(\n `Tool ${toolName} is not FormValidatable, using default schema`\n );\n schemaToUse = tool.schema;\n isFocusedSchema = false;\n }\n\n let schemaFieldCount = 'unknown';\n try {\n if (this.isZodObject(schemaToUse)) {\n const zodObject = schemaToUse as z.ZodObject<z.ZodRawShape>;\n const shape = zodObject.shape;\n if (shape && typeof shape === 'object') {\n schemaFieldCount = Object.keys(shape).length.toString();\n }\n }\n } catch {}\n\n this.formLogger.info(\n `📋 Generating form with ${\n isFocusedSchema ? 'FOCUSED' : 'DEFAULT'\n } schema`,\n {\n toolName,\n schemaType: schemaToUse?.constructor?.name,\n estimatedFieldCount: schemaFieldCount,\n isFocusedSchema,\n }\n );\n\n let missingFields: Set<string> | undefined;\n\n if (isFocusedSchema) {\n this.formLogger.info(\n `⭐ Using focused schema - letting FormGenerator determine fields from schema`\n );\n missingFields = undefined;\n } else {\n missingFields = new Set<string>();\n if (this.isZodObject(schemaToUse)) {\n const zodObject = schemaToUse as z.ZodObject<z.ZodRawShape>;\n const shape = zodObject.shape || {};\n for (const fieldName of Object.keys(shape)) {\n const value = (toolInput || {})[fieldName];\n\n const isEmpty =\n isFormValidatable(tool) && tool.isFieldEmpty\n ? tool.isFieldEmpty(fieldName, value)\n : value === undefined ||\n value === '' ||\n value === null ||\n (Array.isArray(value) && value.length === 0);\n\n const isRequired = this.isFieldRequired(schemaToUse, fieldName);\n\n const isEssential =\n isFormValidatable(tool) && tool.getEssentialFields\n ? tool.getEssentialFields().includes(fieldName)\n : false;\n\n this.formLogger.info(`🔍 Field analysis: ${fieldName}`, {\n value: value,\n isEmpty: isEmpty,\n isRequired: isRequired,\n isEssential: isEssential,\n willAddToMissingFields: isEmpty && (isRequired || isEssential),\n });\n\n if (isEmpty && (isRequired || isEssential)) {\n missingFields.add(fieldName);\n }\n }\n }\n\n this.formLogger.info(`📋 Missing fields analysis complete`, {\n totalFields: this.isZodObject(schemaToUse)\n ? Object.keys(schemaToUse.shape).length\n : 0,\n missingFieldsCount: missingFields.size,\n missingFields: Array.from(missingFields),\n });\n }\n\n const formMessage = await this.formGenerator.generateFormFromSchema(\n schemaToUse,\n toolInput,\n {\n toolName: toolName,\n toolDescription: tool.description,\n },\n missingFields\n );\n\n if (this.isZodObject(schemaToUse)) {\n try {\n const { jsonSchema, uiSchema } =\n this.formGenerator.generateJsonSchemaForm(\n schemaToUse,\n toolInput as Record<string, unknown> | undefined,\n missingFields\n );\n formMessage.jsonSchema = jsonSchema;\n formMessage.uiSchema = uiSchema;\n } catch (error) {\n this.formLogger.warn(\n 'Failed to generate JSON Schema for RJSF:',\n error\n );\n }\n }\n\n formMessage.partialInput = toolInput;\n\n const formData: PendingFormData = {\n toolName: toolName,\n originalInput: inputs,\n originalToolInput: toolInput,\n schema: schemaToUse,\n toolRef: tool as ToolInterface | undefined,\n originalToolRef: (tool as ToolWithOriginal).originalTool,\n };\n this.pendingForms.set(formMessage.id, formData);\n globalPendingForms.set(formMessage.id, formData);\n\n this.formLogger.info(`✅ FORM INTERCEPT SUCCESS for ${toolName}`);\n\n const formResult = {\n requiresForm: true,\n formMessage,\n };\n\n return [\n {\n action: action,\n observation: JSON.stringify(formResult),\n },\n ];\n } catch (error) {\n this.formLogger.error(`Form generation failed for ${toolName}:`, error);\n }\n }\n\n this.formLogger.info(\n `⚪ Passing through to normal tool execution for ${toolName}`\n );\n\n if (this.parameterPreprocessingCallback && toolInput) {\n this.formLogger.info(\n `🔄 Applying parameter preprocessing for ${toolName}`\n );\n try {\n const preprocessedInput = await this.parameterPreprocessingCallback(\n toolName,\n toolInput as Record<string, unknown>\n );\n\n if (\n preprocessedInput &&\n typeof preprocessedInput === 'object' &&\n '__requestForm' in (preprocessedInput as Record<string, unknown>)\n ) {\n const rf = (preprocessedInput as Record<string, unknown>)\n .__requestForm as {\n id?: string;\n title?: string;\n description?: string;\n fields?: Array<{\n name: string;\n label: string;\n type: string;\n required?: boolean;\n options?: Array<{ value: string; label: string }>;\n }>;\n submitLabel?: string;\n };\n\n const formId =\n rf.id ||\n `form_${Date.now()}_${Math.random().toString(36).slice(2)}`;\n const formMessage = {\n type: 'form',\n id: formId,\n originalPrompt: 'Parameter validation required',\n toolName,\n formConfig: {\n title: rf.title || 'Complete required parameters',\n description:\n rf.description ||\n 'One or more parameters require confirmation. Please review and submit.',\n submitLabel: rf.submitLabel || 'Continue',\n fields: (rf.fields || []).map((f) => {\n const allowedTypes: BasicFieldType[] = [\n 'text',\n 'number',\n 'select',\n 'checkbox',\n 'textarea',\n ];\n const resolvedType: BasicFieldType = allowedTypes.includes(\n f.type as BasicFieldType\n )\n ? (f.type as BasicFieldType)\n : 'text';\n\n return {\n name: f.name,\n label: f.label,\n type: resolvedType,\n required: f.required ?? true,\n options: f.options,\n };\n }),\n },\n };\n\n const resolvedSchema = isFormValidatable(tool)\n ? (() => {\n try {\n const s = tool.getFormSchema();\n return s || tool.schema;\n } catch {\n return tool.schema;\n }\n })()\n : tool.schema;\n\n this.pendingForms.set(formId, {\n toolName,\n originalInput: inputs,\n originalToolInput: toolInput,\n schema: resolvedSchema,\n toolRef: tool as ToolInterface | undefined,\n originalToolRef: (tool as ToolWithOriginal).originalTool,\n });\n globalPendingForms.set(formId, {\n toolName,\n originalInput: inputs,\n originalToolInput: toolInput,\n schema: resolvedSchema,\n });\n\n return [\n {\n action,\n observation: JSON.stringify({ requiresForm: true, formMessage }),\n },\n ];\n }\n\n if (JSON.stringify(preprocessedInput) !== JSON.stringify(toolInput)) {\n this.formLogger.info(`📝 Parameters preprocessed for ${toolName}:`, {\n original: Object.keys(toolInput as Record<string, unknown>),\n preprocessed: Object.keys(preprocessedInput),\n hasChanges: true,\n });\n\n try {\n (action as ActionWithToolInput).toolInput = preprocessedInput;\n } catch {}\n } else {\n this.formLogger.debug(`No parameter changes needed for ${toolName}`);\n }\n } catch (preprocessError) {\n this.formLogger.warn(\n `Parameter preprocessing failed for ${toolName}, using original parameters:`,\n preprocessError\n );\n }\n }\n\n return super._takeNextStep(\n nameToolMap,\n inputs,\n intermediateSteps,\n runManager,\n config\n );\n }\n\n /**\n * Helper to determine if a field is required in the schema\n */\n private isFieldRequired(schema: unknown, fieldPath: string): boolean {\n if (!schema || !fieldPath) {\n return false;\n }\n\n try {\n const obj = schema as ZodSchemaDefinition;\n const def = obj._def;\n if (!def || def.typeName !== 'ZodObject') {\n return false;\n }\n const rawShape: unknown =\n typeof def.shape === 'function' ? def.shape() : def.shape;\n if (!rawShape || typeof rawShape !== 'object') {\n return false;\n }\n const shape = rawShape as Record<string, z.ZodTypeAny>;\n const fieldSchema = shape[fieldPath];\n if (!fieldSchema) {\n return false;\n }\n const unwrapOptional = (s: z.ZodTypeAny): z.ZodTypeAny => {\n const inner = (s as ZodSchemaDefinition)._def;\n if (inner && inner.typeName === 'ZodOptional' && inner.innerType) {\n return inner.innerType;\n }\n return s;\n };\n const unwrapped = unwrapOptional(fieldSchema);\n const fdef = (unwrapped as ZodSchemaDefinition)._def;\n if (!fdef) {\n return true;\n }\n if (fdef.typeName === 'ZodOptional' || fdef.typeName === 'ZodDefault') {\n return false;\n }\n if (fdef.defaultValue !== undefined) {\n return false;\n }\n return true;\n } catch (error) {\n this.formLogger.debug(\n `Could not determine if field ${fieldPath} is required:`,\n error\n );\n }\n return false;\n }\n\n /**\n * Override _call to intercept Zod validation errors at the execution level\n */\n override async _call(\n inputs: Record<string, unknown>\n ): Promise<Record<string, unknown>> {\n try {\n const result = await super._call(inputs);\n\n if (result.intermediateSteps && Array.isArray(result.intermediateSteps)) {\n for (const step of result.intermediateSteps) {\n if (step.observation) {\n try {\n const parsed: ToolResponse =\n typeof step.observation === 'string'\n ? JSON.parse(step.observation)\n : (step.observation as ToolResponse);\n\n if (parsed.requiresForm && parsed.formMessage) {\n this.formLogger.info('Tool requested form generation', {\n toolName: step.action?.tool,\n hasForm: true,\n });\n\n const actionToolName =\n (step as IntermediateStepData).action?.tool || 'unknown';\n const toolInstance = this.tools.find(\n (t) => t.name === actionToolName\n ) as ToolInterface | undefined;\n const originalToolCandidate =\n (toolInstance as ToolWithOriginal) || {};\n const pf: PendingFormData = {\n toolName: actionToolName,\n originalInput: inputs,\n originalToolInput: (step as IntermediateStepData).action\n ?.toolInput as Record<string, unknown> | undefined,\n schema: null,\n toolRef: toolInstance,\n originalToolRef: originalToolCandidate?.originalTool,\n };\n this.pendingForms.set(parsed.formMessage.id, pf);\n globalPendingForms.set(parsed.formMessage.id, pf);\n\n return {\n ...result,\n requiresForm: true,\n formMessage: parsed.formMessage,\n output:\n parsed.message || 'Please complete the form to continue.',\n };\n }\n\n if (\n parsed.hashLinkBlock ||\n (parsed.success && parsed.inscription && parsed.hashLinkBlock)\n ) {\n this.formLogger.info('Tool returned HashLink blocks', {\n toolName: (step as IntermediateStepData).action?.tool,\n hasHashLink: true,\n blockId: parsed.hashLinkBlock?.blockId,\n });\n\n const hashLinkResponse = this.processHashLinkResponse(parsed);\n\n return {\n ...result,\n hasHashLinkBlocks: true,\n hashLinkBlock: hashLinkResponse.hashLinkBlock,\n output: hashLinkResponse.message,\n };\n }\n } catch {}\n }\n }\n }\n\n return result;\n } catch (error) {\n if (error instanceof ZodError) {\n this.formLogger.info('Intercepted ZodError during agent execution');\n return this.handleValidationError(error, inputs, []);\n }\n throw error;\n }\n }\n\n /**\n * Handles Zod validation errors by generating forms\n */\n private async handleValidationError(\n error: ZodError,\n inputs: Record<string, unknown>,\n intermediateSteps: AgentStep[]\n ): Promise<Record<string, unknown>> {\n this.formLogger.info('Zod validation error detected, generating form', {\n errorIssues: error.issues.length,\n inputKeys: Object.keys(inputs),\n });\n\n let toolInfo = this.extractToolInfoFromError(\n error,\n inputs,\n intermediateSteps\n );\n\n if (!toolInfo) {\n this.formLogger.warn(\n 'Could not extract tool info from validation error, trying fallback detection'\n );\n const fallbackTool = this.detectToolFromErrorContext(error);\n if (!fallbackTool) {\n this.formLogger.error(\n 'No tool detected for form generation, rethrowing error'\n );\n throw error;\n }\n toolInfo = fallbackTool;\n }\n\n this.formLogger.info('Generating form for tool:', {\n toolName: toolInfo.toolName,\n hasSchema: !!toolInfo.schema,\n });\n\n const formMessage = this.formGenerator.generateFormFromError(\n error,\n toolInfo.schema as z.ZodType<unknown, z.ZodTypeDef, unknown>,\n toolInfo.toolName,\n (inputs.input as string) || ''\n );\n\n this.pendingForms.set(formMessage.id, {\n toolName: toolInfo.toolName,\n originalInput: inputs,\n schema: toolInfo.schema,\n });\n\n globalPendingForms.set(formMessage.id, {\n toolName: toolInfo.toolName,\n originalInput: inputs,\n schema: toolInfo.schema,\n });\n\n return {\n output: this.formatFormResponse(formMessage),\n formMessage,\n requiresForm: true,\n intermediateSteps: intermediateSteps || [],\n };\n }\n\n /**\n * Get a copy of pending forms for preservation during executor recreation\n */\n getPendingForms(): Map<string, PendingFormData> {\n return new Map(this.pendingForms);\n }\n\n /**\n * Restore pending forms from a previous executor instance\n */\n restorePendingForms(forms: Map<string, PendingFormData>): void {\n for (const [formId, formData] of forms) {\n this.pendingForms.set(formId, formData);\n }\n }\n\n /**\n * Processes form submission and continues tool execution\n */\n async processFormSubmission(\n submission: FormSubmission\n ): Promise<Record<string, unknown>> {\n this.formLogger.info(\n '🚀 FormAwareAgentExecutor.processFormSubmission called!',\n {\n submissionFormId: submission.formId,\n submissionToolName: submission.toolName,\n }\n );\n if (!submission) {\n throw new Error('Form submission is null or undefined');\n }\n\n if (!submission.formId) {\n throw new Error('Form submission missing formId');\n }\n\n if (\n !submission.parameters ||\n submission.parameters === null ||\n typeof submission.parameters !== 'object' ||\n Array.isArray(submission.parameters)\n ) {\n throw new Error(\n `Form submission parameters are invalid: ${typeof submission.parameters}, isNull: ${\n submission.parameters === null\n }, isArray: ${Array.isArray(\n submission.parameters\n )}, parameters: ${JSON.stringify(submission.parameters)}`\n );\n }\n\n this.formLogger.info('Processing form submission:', {\n formId: submission.formId,\n toolName: submission.toolName,\n parameterKeys: Object.keys(submission.parameters),\n parametersType: typeof submission.parameters,\n parametersIsNull: submission.parameters === null,\n parametersIsUndefined: submission.parameters === undefined,\n hasContext: !!submission.context,\n });\n\n let pendingForm = this.pendingForms.get(submission.formId);\n\n if (!pendingForm) {\n pendingForm = globalPendingForms.get(submission.formId);\n if (!pendingForm) {\n throw new Error(`No pending form found for ID: ${submission.formId}`);\n }\n }\n\n this.pendingForms.delete(submission.formId);\n globalPendingForms.delete(submission.formId);\n\n const tool =\n pendingForm.toolRef ||\n this.tools.find((t) => t.name === pendingForm.toolName);\n if (!tool) {\n throw new Error(\n `Tool not found for form submission: ${pendingForm.toolName}`\n );\n }\n\n let baseToolInput: Record<string, unknown> = {};\n try {\n if (\n pendingForm.originalToolInput &&\n typeof pendingForm.originalToolInput === 'object'\n ) {\n baseToolInput = {\n ...(pendingForm.originalToolInput as Record<string, unknown>),\n };\n }\n } catch (error) {\n this.formLogger.warn(\n 'Failed to extract base tool input, using empty object:',\n error\n );\n baseToolInput = {};\n }\n\n let submissionData: Record<string, unknown> = {};\n try {\n if (submission.parameters && typeof submission.parameters === 'object') {\n submissionData = {\n ...(submission.parameters as Record<string, unknown>),\n };\n }\n } catch (error) {\n this.formLogger.warn(\n 'Failed to extract submission parameters, using empty object:',\n error\n );\n submissionData = {};\n }\n\n const mergedToolInput: Record<string, unknown> = {};\n try {\n Object.keys(baseToolInput).forEach((key) => {\n const value = baseToolInput[key];\n if (value !== undefined && value !== null) {\n mergedToolInput[key] = value;\n }\n });\n\n Object.keys(submissionData).forEach((key) => {\n const value = submissionData[key];\n if (value !== undefined && value !== null) {\n mergedToolInput[key] = value;\n }\n });\n\n mergedToolInput.renderForm = false;\n mergedToolInput.__fromForm = true;\n\n this.formLogger.info('Successfully merged tool input:', {\n baseKeys: Object.keys(baseToolInput),\n submissionKeys: Object.keys(submissionData),\n mergedKeys: Object.keys(mergedToolInput),\n });\n } catch (error) {\n this.formLogger.error('Failed to merge tool input data:', error);\n throw new Error(\n `Failed to merge tool input data: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\n }\n\n try {\n const maybeWrapper = tool as ToolWrapper;\n let toolOutput: string;\n if (typeof maybeWrapper.executeOriginal === 'function') {\n toolOutput = await maybeWrapper.executeOriginal(mergedToolInput);\n } else if (typeof maybeWrapper.getOriginalTool === 'function') {\n const ot = maybeWrapper.getOriginalTool();\n const otCall = ot as CallableTool;\n if (ot && typeof otCall._call === 'function') {\n toolOutput = await otCall._call(mergedToolInput);\n } else if (ot && typeof otCall.call === 'function') {\n toolOutput = await otCall.call(mergedToolInput);\n } else {\n const tcall = tool as CallableTool;\n if (typeof tcall.call === 'function') {\n toolOutput = await tcall.call(mergedToolInput);\n } else {\n throw new Error(\n 'No callable tool implementation found for form submission'\n );\n }\n }\n } else if (\n maybeWrapper.originalTool &&\n typeof maybeWrapper.originalTool._call === 'function'\n ) {\n toolOutput = await maybeWrapper.originalTool._call(mergedToolInput);\n } else if (\n maybeWrapper.originalTool &&\n typeof maybeWrapper.originalTool.call === 'function'\n ) {\n toolOutput = await maybeWrapper.originalTool.call(mergedToolInput);\n } else if (typeof (tool as CallableTool).call === 'function') {\n toolOutput = await (tool as CallableTool).call!(mergedToolInput);\n } else {\n throw new Error(\n 'No callable tool implementation found for form submission'\n );\n }\n\n let responseMetadata: Record<string, unknown> = {};\n let formattedOutput: string;\n\n try {\n const parsed = JSON.parse(toolOutput);\n this.formLogger.info(\n '✅ METADATA EXTRACTION: Successfully parsed JSON',\n {\n jsonKeys: Object.keys(parsed),\n hasHashLinkBlock: !!(parsed as Record<string, unknown>)\n .hashLinkBlock,\n }\n );\n\n if (parsed && typeof parsed === 'object') {\n if (ResponseFormatter.isHashLinkResponse(parsed)) {\n this.formLogger.info(\n '🔗 HASHLINK DETECTED: Processing HashLink response separately to preserve metadata'\n );\n\n const parsedRecord = parsed as Record<string, unknown>;\n responseMetadata = {\n ...responseMetadata,\n hashLinkBlock: parsedRecord.hashLinkBlock,\n ...parsedRecord,\n };\n\n formattedOutput = ResponseFormatter.formatHashLinkResponse(parsed);\n\n this.formLogger.info(\n '🔗 METADATA PRESERVED: HashLink metadata extracted for component rendering',\n {\n blockId: this.hasHashLinkBlock(responseMetadata)\n ? responseMetadata.hashLinkBlock.blockId\n : undefined,\n hasTemplate: this.hasHashLinkBlock(responseMetadata)\n ? !!responseMetadata.hashLinkBlock.template\n : false,\n }\n );\n } else {\n formattedOutput = ResponseFormatter.formatResponse(toolOutput);\n\n responseMetadata = {\n ...responseMetadata,\n hashLinkBlock: (parsed as Record<string, unknown>).hashLinkBlock,\n ...parsed,\n };\n }\n } else {\n formattedOutput = ResponseFormatter.formatResponse(toolOutput);\n }\n } catch (error) {\n this.formLogger.warn(\n '❌ METADATA EXTRACTION: Tool output is not JSON',\n {\n error: error instanceof Error ? error.message : 'unknown error',\n outputSample:\n typeof toolOutput === 'string'\n ? toolOutput.substring(0, 200)\n : 'not-string',\n }\n );\n\n formattedOutput = ResponseFormatter.formatResponse(toolOutput);\n }\n\n return {\n output: formattedOutput,\n formCompleted: true,\n originalFormId: submission.formId,\n intermediateSteps: [],\n metadata: responseMetadata,\n rawToolOutput: toolOutput,\n toolName: pendingForm.toolName,\n };\n } catch (error) {\n if (error instanceof ZodError) {\n return this.handleValidationError(error, mergedToolInput, []);\n }\n throw error;\n }\n }\n\n /**\n * Extracts tool information from the execution context\n */\n private extractToolInfoFromError(\n error: ZodError,\n inputs: Record<string, unknown>,\n intermediateSteps: AgentStep[]\n ): { toolName: string; schema: unknown } | null {\n try {\n if (intermediateSteps.length > 0) {\n const lastStep = intermediateSteps[intermediateSteps.length - 1];\n if (lastStep.action && lastStep.action.tool) {\n const tool = this.tools.find((t) => t.name === lastStep.action.tool);\n if (tool && 'schema' in tool) {\n this.formLogger.info(\n 'Found tool from intermediate steps:',\n lastStep.action.tool\n );\n return {\n toolName: lastStep.action.tool,\n schema: (tool as ToolWithSchema).schema,\n };\n }\n }\n }\n\n const inputSteps = (inputs.intermediateSteps as unknown[]) || [];\n if (inputSteps.length > 0) {\n const lastStep = inputSteps[inputSteps.length - 1];\n let action: AgentAction;\n\n if (Array.isArray(lastStep) && lastStep.length > 0) {\n action = lastStep[0] as AgentAction;\n } else if ((lastStep as Record<string, unknown>).action) {\n action = (lastStep as Record<string, unknown>).action as AgentAction;\n } else {\n action = lastStep as AgentAction;\n }\n\n if (action && action.tool) {\n const tool = this.tools.find((t) => t.name === action.tool);\n if (tool && 'schema' in tool) {\n this.formLogger.info('Found tool from input steps:', action.tool);\n return {\n toolName: action.tool,\n schema: (tool as ToolWithSchema).schema,\n };\n }\n }\n }\n\n const toolFromContext = this.findToolFromContext(inputs);\n if (toolFromContext) {\n this.formLogger.info(\n 'Found tool from context:',\n toolFromContext.toolName\n );\n return toolFromContext;\n }\n\n return null;\n } catch (err) {\n this.formLogger.error('Error extracting tool info:', err);\n return null;\n }\n }\n\n /**\n * Attempts to find tool from execution context\n */\n private findToolFromContext(inputs: Record<string, unknown>): {\n toolName: string;\n schema: unknown;\n } | null {\n const inputText = (inputs.input as string) || '';\n\n for (const tool of this.tools) {\n const keywords = this.extractToolKeywords(tool.name);\n\n if (\n keywords.some((keyword) =>\n inputText.toLowerCase().includes(keyword.toLowerCase())\n )\n ) {\n if ('schema' in tool) {\n return {\n toolName: tool.name,\n schema: (tool as ToolWithSchema).schema,\n };\n }\n }\n }\n\n return null;\n }\n\n /**\n * Additional fallback to detect tool from error context\n */\n private detectToolFromErrorContext(\n error: ZodError\n ): { toolName: string; schema: unknown } | null {\n const errorPaths = error.issues.map((issue) => issue.path.join('.'));\n\n for (const tool of this.tools) {\n if ('schema' in tool) {\n const toolSchema = (tool as ToolWithSchema).schema;\n if (this.schemaMatchesErrorPaths(toolSchema, errorPaths)) {\n this.formLogger.info(\n 'Detected tool from error path analysis:',\n tool.name\n );\n return {\n toolName: tool.name,\n schema: toolSchema,\n };\n }\n }\n }\n\n return null;\n }\n\n /**\n * Checks if a schema structure matches error paths\n */\n private schemaMatchesErrorPaths(\n schema: unknown,\n errorPaths: string[]\n ): boolean {\n const schemaRecord = schema as Record<string, unknown>;\n if (!schemaRecord || !schemaRecord._def) return false;\n\n try {\n const def = schemaRecord._def as Record<string, unknown>;\n if (def.typeName === 'ZodObject') {\n const shape = def.shape as Record<string, unknown>;\n const schemaKeys = Object.keys(shape || {});\n return errorPaths.some((path) => {\n const topLevelKey = path.split('.')[0];\n return schemaKeys.includes(topLevelKey);\n });\n }\n } catch (err) {\n this.formLogger.debug('Error analyzing schema structure:', err);\n }\n\n return false;\n }\n\n /**\n * Extracts keywords from tool name for matching\n */\n private extractToolKeywords(toolName: string): string[] {\n const words = toolName\n .replace(/([A-Z])/g, ' $1')\n .toLowerCase()\n .split(/[\\s_-]+/)\n .filter((w) => w.length > 2);\n\n return [...words, toolName.toLowerCase()];\n }\n\n /**\n * Formats the form message for display\n */\n private formatFormResponse(formMessage: FormMessage): string {\n const fieldCount = formMessage.formConfig.fields.length;\n const fieldList = formMessage.formConfig.fields\n .slice(0, 3)\n .map((f) => `• ${f.label}`)\n .join('\\n');\n\n return `I need some additional information to complete your request.\n\n${formMessage.formConfig.description}\n\nRequired fields:\n${fieldList}${fieldCount > 3 ? `\\n... and ${fieldCount - 3} more` : ''}\n\nPlease fill out the form below to continue.`;\n }\n\n /**\n * Check if there are pending forms\n */\n hasPendingForms(): boolean {\n return this.pendingForms.size > 0;\n }\n\n /**\n * Get information about pending forms\n */\n getPendingFormsInfo(): Array<{ formId: string; toolName: string }> {\n return Array.from(this.pendingForms.entries()).map(([formId, info]) => ({\n formId,\n toolName: info.toolName,\n }));\n }\n\n\n /**\n * Processes HashLink block responses from tools\n */\n private processHashLinkResponse(\n toolResponse: ToolResponse\n ): HashLinkResponse {\n try {\n let hashLinkBlock: HashLinkBlock | undefined;\n\n if (toolResponse.hashLinkBlock) {\n hashLinkBlock = toolResponse.hashLinkBlock;\n } else if (toolResponse.success && toolResponse.hashLinkBlock) {\n hashLinkBlock = toolResponse.hashLinkBlock;\n }\n\n if (!hashLinkBlock) {\n throw new Error('HashLink block data not found in response');\n }\n\n if (\n !hashLinkBlock.blockId ||\n !hashLinkBlock.hashLink ||\n !hashLinkBlock.attributes\n ) {\n throw new Error(\n 'Invalid HashLink block structure - missing required fields'\n );\n }\n\n let message = 'Content processed successfully!';\n\n if (toolResponse.success && toolResponse.inscription) {\n const inscription = toolResponse.inscription;\n const metadata = toolResponse.metadata || {};\n\n message = `✅ ${inscription.standard} Hashinal inscription completed!\\n\\n`;\n\n if (metadata.name) {\n message += `**${metadata.name}**\\n`;\n }\n\n if (metadata.description) {\n message += `${metadata.description}\\n\\n`;\n }\n\n message += `📍 **Topic ID:** ${inscription.topicId}\\n`;\n message += `🔗 **HRL:** ${inscription.hrl}\\n`;\n\n if (inscription.cdnUrl) {\n message += `🌐 **CDN URL:** ${inscription.cdnUrl}\\n`;\n }\n\n if (metadata.creator) {\n message += `👤 **Creator:** ${metadata.creator}\\n`;\n }\n }\n\n this.formLogger.info('Processed HashLink response', {\n blockId: hashLinkBlock.blockId,\n hashLink: hashLinkBlock.hashLink,\n hasTemplate: !!hashLinkBlock.template,\n attributeCount: Object.keys(hashLinkBlock.attributes || {}).length,\n });\n\n return {\n hasHashLinkBlocks: true,\n hashLinkBlock,\n message,\n };\n } catch (error) {\n this.formLogger.error('Error processing HashLink response:', error);\n\n return {\n hasHashLinkBlocks: false,\n message: 'Content processed, but interactive display is not available.',\n };\n }\n }\n\n /**\n * Get FormEngine statistics for debugging\n */\n getFormEngineStatistics(): {\n strategies: string[];\n middleware: string[];\n } {\n return {\n strategies: this.formEngine.getRegisteredStrategies(),\n middleware: this.formEngine.getRegisteredMiddleware(),\n };\n }\n}\n","import type { BaseMessage } from '@langchain/core/messages';\nimport type { StructuredTool } from '@langchain/core/tools';\nimport type { TransactionReceipt } from '@hashgraph/sdk';\nimport {\n HederaAgentKit,\n ServerSigner,\n TokenUsageCallbackHandler,\n TokenUsage,\n BasePlugin,\n} from 'hedera-agent-kit';\nimport type { CostCalculation } from 'hedera-agent-kit';\nimport type { AIProvider, VercelAIProvider, BAMLProvider } from './providers';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport type { MCPServerConfig, MCPConnectionStatus } from './mcp/types';\nimport type { FormSubmission } from './forms/types';\n\nexport interface ToolFilterConfig {\n namespaceWhitelist?: string[];\n toolBlacklist?: string[];\n toolPredicate?: (tool: StructuredTool) => boolean;\n}\n\nexport type ExecutionMode = 'direct' | 'bytes';\nexport type OperationalMode = 'autonomous' | 'returnBytes';\n\nexport interface HederaAgentConfiguration {\n signer: ServerSigner;\n execution?: {\n mode?: ExecutionMode;\n operationalMode?: OperationalMode;\n userAccountId?: string;\n scheduleUserTransactions?: boolean;\n scheduleUserTransactionsInBytesMode?: boolean;\n };\n ai?: {\n provider?: AIProvider;\n llm?: unknown;\n apiKey?: string;\n modelName?: string;\n temperature?: number;\n };\n filtering?: ToolFilterConfig;\n messaging?: {\n systemPreamble?: string;\n systemPostamble?: string;\n conciseMode?: boolean;\n };\n extensions?: {\n plugins?: BasePlugin[];\n mirrorConfig?: Record<string, unknown>;\n modelCapability?: string;\n };\n mcp?: {\n servers?: MCPServerConfig[];\n autoConnect?: boolean;\n };\n debug?: {\n verbose?: boolean;\n silent?: boolean;\n };\n}\n\nexport interface ConversationContext {\n messages: BaseMessage[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface ChatResponse {\n output: string;\n message?: string;\n transactionBytes?: string;\n receipt?: TransactionReceipt | object;\n scheduleId?: string;\n transactionId?: string;\n notes?: string[];\n error?: string;\n intermediateSteps?: unknown;\n rawToolOutput?: unknown;\n tokenUsage?: TokenUsage;\n cost?: CostCalculation;\n metadata?: Record<string, unknown>;\n tool_calls?: Array<{\n id: string;\n name: string;\n args: Record<string, unknown>;\n output?: string;\n }>;\n formMessage?: unknown;\n requiresForm?: boolean;\n [key: string]: unknown;\n}\n\nexport interface UsageStats extends TokenUsage {\n cost: CostCalculation;\n}\n\nexport abstract class BaseAgent {\n protected logger: Logger;\n protected agentKit: HederaAgentKit | undefined;\n protected tools: StructuredTool[] = [];\n protected initialized = false;\n protected tokenTracker: TokenUsageCallbackHandler | undefined;\n\n constructor(protected config: HederaAgentConfiguration) {\n this.logger = new Logger({\n module: 'BaseAgent',\n silent: config.debug?.silent || false,\n });\n }\n\n abstract boot(): Promise<void>;\n abstract chat(\n message: string,\n context?: ConversationContext\n ): Promise<ChatResponse>;\n abstract processFormSubmission(\n submission: FormSubmission\n ): Promise<ChatResponse>;\n abstract shutdown(): Promise<void>;\n abstract switchMode(mode: OperationalMode): void;\n abstract getUsageStats(): UsageStats;\n abstract getUsageLog(): UsageStats[];\n abstract clearUsageStats(): void;\n abstract connectMCPServers(): Promise<void>;\n abstract getMCPConnectionStatus(): Map<string, MCPConnectionStatus>;\n\n public getCore(): HederaAgentKit | undefined {\n return this.agentKit;\n }\n\n protected filterTools(tools: StructuredTool[]): StructuredTool[] {\n let filtered = [...tools];\n const filter = this.config.filtering;\n\n if (!filter) return filtered;\n\n if (filter.namespaceWhitelist?.length) {\n filtered = filtered.filter((tool) => {\n const namespace = (tool as StructuredTool & { namespace?: string })\n .namespace;\n return !namespace || filter.namespaceWhitelist!.includes(namespace);\n });\n }\n\n if (filter.toolBlacklist?.length) {\n filtered = filtered.filter(\n (tool) => !filter.toolBlacklist!.includes(tool.name)\n );\n }\n\n if (filter.toolPredicate) {\n filtered = filtered.filter(filter.toolPredicate);\n }\n\n this.logger.debug(`Filtered tools: ${tools.length} → ${filtered.length}`);\n return filtered;\n }\n\n protected buildSystemPrompt(): string {\n const parts: string[] = [];\n const operatorId = this.config.signer.getAccountId().toString();\n const userAccId = this.config.execution?.userAccountId;\n\n if (this.config.messaging?.systemPreamble) {\n parts.push(this.config.messaging.systemPreamble);\n }\n\n parts.push(\n `You are a helpful Hedera assistant. Your primary operator account is ${operatorId}. ` +\n `You have tools to interact with the Hedera Hashgraph. ` +\n `When using any tool, provide all necessary parameters as defined by that tool's schema and description.`\n );\n\n parts.push(\n `\\nMETADATA QUALITY PRINCIPLES: When collecting user input for metadata creation across any tool:` +\n `\\n• Prioritize meaningful, valuable content over technical file information` +\n `\\n• Focus on attributes that add value for end users and collectors` +\n `\\n• Avoid auto-generating meaningless technical attributes as user-facing metadata` +\n `\\n• When fields are missing or inadequate, use forms to collect quality metadata` +\n `\\n• Encourage descriptive names, collectible traits, and storytelling elements`\n );\n\n if (userAccId) {\n parts.push(\n `The user you are assisting has a personal Hedera account ID: ${userAccId}. ` +\n `IMPORTANT: When the user says things like \"I want to send HBAR\" or \"transfer my tokens\", you MUST use ${userAccId} as the sender/from account. ` +\n `For example, if user says \"I want to send 2 HBAR to 0.0.800\", you must set up a transfer where ${userAccId} sends the HBAR, not your operator account.`\n );\n }\n\n const operationalMode =\n this.config.execution?.operationalMode || 'returnBytes';\n if (operationalMode === 'autonomous') {\n parts.push(\n `\\nOPERATIONAL MODE: 'autonomous'. Your goal is to execute transactions directly using your tools. ` +\n `Your account ${operatorId} will be the payer for these transactions. ` +\n `Even if the user's account (${\n userAccId || 'a specified account'\n }) is the actor in the transaction body (e.g., sender of HBAR), ` +\n `you (the agent with operator ${operatorId}) are still executing and paying. For HBAR transfers, ensure the amounts in the 'transfers' array sum to zero (as per tool schema), balancing with your operator account if necessary.`\n );\n } else {\n if (\n this.config.execution?.scheduleUserTransactionsInBytesMode &&\n userAccId\n ) {\n parts.push(\n `\\nOPERATIONAL MODE: 'returnBytes' with scheduled transactions for user actions. ` +\n `When a user asks for a transaction to be prepared (e.g., creating a token, topic, transferring assets for them to sign, etc), ` +\n `you MUST default to creating a Scheduled Transaction using the appropriate tool with the metaOption 'schedule: true'. ` +\n `The user (with account ID ${userAccId}) will be the one to ultimately pay for and (if needed) sign the inner transaction. ` +\n `Your operator account (${operatorId}) will pay for creating the schedule entity itself. ` +\n `You MUST return the ScheduleId and details of the scheduled operation in a structured JSON format with these fields: success, op, schedule_id, description, payer_account_id_scheduled_tx, and scheduled_transaction_details.`\n );\n } else {\n parts.push(\n `\\nOPERATIONAL MODE: 'returnBytes'. Your goal is to provide transaction bytes when possible. ` +\n `When a user asks for a transaction to be prepared (e.g., for them to sign, or for scheduling without the default scheduling flow), ` +\n `you MUST call the appropriate tool. ` +\n `IMPORTANT: Only use metaOption 'returnBytes: true' for tools that explicitly support it (like HBAR transfers, token operations). ` +\n `Many tools (inscriptions, HCS-2, HCS-20, etc.) do NOT support returnBytes and will execute directly - this is expected behavior. ` +\n `For tools without returnBytes support, simply call them with their standard parameters. ` +\n `If you need raw bytes for the user to sign for their own account ${\n userAccId || 'if specified'\n }, ensure the tool constructs the transaction body accordingly when returnBytes IS supported.`\n );\n }\n }\n\n if (this.config.messaging?.conciseMode !== false) {\n parts.push(\n '\\nAlways be concise. If the tool provides a JSON string as its primary output (especially in returnBytes mode), make your accompanying text brief. If the tool does not provide JSON output or an error occurs, your narrative becomes primary; if notes were generated by the tool in such cases, append them to your textual response.'\n );\n }\n\n if (this.config.messaging?.systemPostamble) {\n parts.push(this.config.messaging.systemPostamble);\n }\n\n return parts.join('\\n');\n }\n\n isReady(): boolean {\n return this.initialized;\n }\n}\n\nexport type { AIProvider, VercelAIProvider, BAMLProvider };\n","import type { ContentType, ContentSource } from '../types/content-reference';\nimport type { ContentStorage } from '../memory/content-storage';\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\n/**\n * Content reference interface\n */\ninterface ContentReference {\n referenceId: string;\n preview?: string;\n metadata: {\n sizeBytes: number;\n contentType?: string;\n [key: string]: unknown;\n };\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(\n (max, content) => Math.max(max, content.sizeBytes),\n 0\n );\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: [\n error instanceof Error ? error.message : 'Unknown processing error',\n ],\n };\n }\n }\n\n private extractContentFromResponse(\n obj: unknown,\n contents: MCPResponseContent[]\n ): 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 );\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 (\n this.contentStorage.shouldUseReference(\n typeof contentInfo.content === 'string'\n ? contentInfo.content\n : JSON.stringify(contentInfo.content)\n )\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(\n contentInfo.mimeType\n );\n\n const metadata: Parameters<\n typeof this.contentStorage.storeContentIfLarge\n >[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(\n `Failed to create reference: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\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(\n reference: ContentReference\n ): 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(\n obj: unknown,\n oldContent: unknown,\n newContent: unknown\n ): 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 if (typeof newContent === 'object' && newContent !== null) {\n const newContentRecord = newContent as Record<string, unknown>;\n for (const key of Object.keys(newContentRecord)) {\n record[key] = newContentRecord[key];\n }\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}\n","import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';\nimport type { MCPServerConfig, MCPToolInfo, MCPConnectionStatus } from './types';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport type { ContentStorage } from '../memory/content-storage';\nimport { MCPContentProcessor } from './content-processor';\n\n/**\n * Manages connections to MCP servers and tool discovery\n */\nexport class MCPClientManager {\n private clients: Map<string, Client> = new Map();\n private tools: Map<string, MCPToolInfo[]> = new Map();\n private logger: Logger;\n private contentProcessor?: MCPContentProcessor;\n\n constructor(logger: Logger, contentStorage?: ContentStorage) {\n this.logger = logger;\n if (contentStorage) {\n this.contentProcessor = new MCPContentProcessor(contentStorage, logger);\n }\n }\n\n /**\n * Connect to an MCP server and discover its tools\n */\n async connectServer(config: MCPServerConfig): Promise<MCPConnectionStatus> {\n try {\n if (this.isServerConnected(config.name)) {\n return {\n serverName: config.name,\n connected: false,\n error: `Server ${config.name} is already connected`,\n tools: [],\n };\n }\n\n if (config.transport && config.transport !== 'stdio') {\n throw new Error(`Transport ${config.transport} not yet supported`);\n }\n\n const transport = new StdioClientTransport({\n command: config.command,\n args: config.args,\n ...(config.env && { env: config.env }),\n });\n\n const client = new Client({\n name: `conversational-agent-${config.name}`,\n version: '1.0.0',\n }, {\n capabilities: {},\n });\n\n await client.connect(transport);\n this.clients.set(config.name, client);\n\n const toolsResponse = await client.listTools();\n const toolsWithServer: MCPToolInfo[] = toolsResponse.tools.map((tool: unknown) => {\n const t = tool as { description?: string } & Record<string, unknown>;\n const { description, ...rest } = t;\n const base = description !== undefined && typeof description === 'string'\n ? { ...rest, description }\n : { ...rest };\n return {\n ...(base as Omit<MCPToolInfo, 'serverName'>),\n serverName: config.name,\n } as MCPToolInfo;\n });\n\n this.tools.set(config.name, toolsWithServer);\n this.logger.info(`Connected to MCP server ${config.name} with ${toolsWithServer.length} tools`);\n\n return {\n serverName: config.name,\n connected: true,\n tools: toolsWithServer,\n };\n } catch (error) {\n this.logger.error(`Failed to connect to MCP server ${config.name}:`, error);\n return {\n serverName: config.name,\n connected: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n tools: [],\n };\n }\n }\n\n /**\n * Execute a tool on a specific MCP server\n */\n async executeTool(serverName: string, toolName: string, args: Record<string, unknown>): Promise<unknown> {\n const client = this.clients.get(serverName);\n if (!client) {\n throw new Error(`MCP server ${serverName} not connected`);\n }\n\n this.logger.debug(`Executing MCP tool ${toolName} on server ${serverName}`, args);\n\n try {\n const result = await client.callTool({\n name: toolName,\n arguments: args,\n });\n\n if (this.contentProcessor) {\n const processed = await this.contentProcessor.processResponse(result, serverName, toolName);\n \n if (processed.wasProcessed) {\n this.logger.debug(\n `Processed MCP response from ${serverName}::${toolName}`,\n {\n referenceCreated: processed.referenceCreated,\n originalSize: processed.originalSize,\n errors: processed.errors\n }\n );\n\n if (processed.errors && processed.errors.length > 0) {\n this.logger.warn(`Content processing warnings for ${serverName}::${toolName}:`, processed.errors);\n }\n }\n\n return processed.content;\n }\n\n return result;\n } catch (error) {\n this.logger.error(`Error executing MCP tool ${toolName}:`, error);\n throw error;\n }\n }\n\n /**\n * Disconnect all MCP servers\n */\n async disconnectAll(): Promise<void> {\n for (const [name, client] of this.clients) {\n try {\n await client.close();\n this.logger.info(`Disconnected from MCP server ${name}`);\n } catch (error) {\n this.logger.error(`Error disconnecting MCP server ${name}:`, error);\n }\n }\n this.clients.clear();\n this.tools.clear();\n }\n\n /**\n * Get all discovered tools from all connected servers\n */\n getAllTools(): MCPToolInfo[] {\n const allTools: MCPToolInfo[] = [];\n for (const tools of this.tools.values()) {\n allTools.push(...tools);\n }\n return allTools;\n }\n\n /**\n * Get tools from a specific server\n */\n getServerTools(serverName: string): MCPToolInfo[] {\n return this.tools.get(serverName) || [];\n }\n\n /**\n * Check if a server is connected\n */\n isServerConnected(serverName: string): boolean {\n return this.clients.has(serverName);\n }\n\n /**\n * Get list of connected server names\n */\n getConnectedServers(): string[] {\n return Array.from(this.clients.keys());\n }\n\n /**\n * Enable content processing with content storage\n */\n enableContentProcessing(contentStorage: ContentStorage): void {\n this.contentProcessor = new MCPContentProcessor(contentStorage, this.logger);\n this.logger.info('Content processing enabled for MCP responses');\n }\n\n /**\n * Disable content processing\n */\n disableContentProcessing(): void {\n delete this.contentProcessor;\n this.logger.info('Content processing disabled for MCP responses');\n }\n\n /**\n * Check if content processing is enabled\n */\n isContentProcessingEnabled(): boolean {\n return this.contentProcessor !== undefined;\n }\n\n /**\n * Analyze a response without processing it (for testing/debugging)\n */\n analyzeResponseContent(response: unknown): unknown {\n if (!this.contentProcessor) {\n throw new Error('Content processing is not enabled');\n }\n return this.contentProcessor.analyzeResponse(response);\n }\n}\n","import { DynamicStructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport type { MCPToolInfo, MCPServerConfig } from '../types';\nimport type { MCPClientManager } from '../mcp-client-manager';\nimport {\n ContentStoreService,\n shouldUseReference,\n} from '@hashgraphonline/standards-sdk';\nimport type { ContentSource } from '../../types/content-reference';\n\n/**\n * Convert an MCP tool to a LangChain DynamicStructuredTool\n */\nexport function convertMCPToolToLangChain(\n tool: MCPToolInfo,\n mcpManager: MCPClientManager,\n serverConfig?: MCPServerConfig\n): DynamicStructuredTool {\n const zodSchema = jsonSchemaToZod(tool.inputSchema);\n\n const sanitizedName = `${tool.serverName}_${tool.name}`.replace(\n /[^a-zA-Z0-9_]/g,\n '_'\n );\n\n let description =\n tool.description || `MCP tool ${tool.name} from ${tool.serverName}`;\n\n if (serverConfig?.toolDescriptions?.[tool.name]) {\n description = `${description}\\n\\n${\n serverConfig.toolDescriptions[tool.name]\n }`;\n }\n\n if (serverConfig?.additionalContext) {\n description = `${description}\\n\\nContext: ${serverConfig.additionalContext}`;\n }\n\n return new DynamicStructuredTool({\n name: sanitizedName,\n description,\n schema: zodSchema,\n func: async (input) => {\n try {\n const result = await mcpManager.executeTool(\n tool.serverName,\n tool.name,\n input\n );\n\n let responseText = '';\n\n if (typeof result === 'string') {\n responseText = result;\n } else if (\n result &&\n typeof result === 'object' &&\n 'content' in result\n ) {\n const content = (result as { content: unknown }).content;\n if (Array.isArray(content)) {\n const textParts = content\n .filter(\n (item): item is { type: string; text: string } =>\n typeof item === 'object' &&\n item !== null &&\n 'type' in item &&\n item.type === 'text' &&\n 'text' in item\n )\n .map((item) => item.text);\n responseText = textParts.join('\\n');\n } else {\n responseText = JSON.stringify(content);\n }\n } else {\n responseText = JSON.stringify(result);\n }\n\n const responseBuffer = Buffer.from(responseText, 'utf8');\n\n const MCP_REFERENCE_THRESHOLD = 10 * 1024;\n const shouldStoreMCPContent =\n responseBuffer.length > MCP_REFERENCE_THRESHOLD;\n\n if (shouldStoreMCPContent || shouldUseReference(responseBuffer)) {\n const contentStore = ContentStoreService.getInstance();\n if (contentStore) {\n try {\n const referenceId = await contentStore.storeContent(\n responseBuffer,\n {\n contentType: 'text' as ContentSource,\n source: 'mcp',\n mcpToolName: `${tool.serverName}_${tool.name}`,\n originalSize: responseBuffer.length,\n }\n );\n return `content-ref:${referenceId}`;\n } catch {}\n }\n }\n\n return responseText;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n return `Error executing MCP tool ${tool.name}: ${errorMessage}`;\n }\n },\n });\n}\n\n/**\n * Convert JSON Schema to Zod schema\n * This is a simplified converter that handles common cases\n */\nfunction jsonSchemaToZod(schema: unknown): z.ZodTypeAny {\n if (!schema || typeof schema !== 'object') {\n return z.object({});\n }\n\n const schemaObj = schema as Record<string, unknown>;\n\n if (schemaObj.type && schemaObj.type !== 'object') {\n return convertType(schemaObj);\n }\n\n if (!schemaObj.properties || typeof schemaObj.properties !== 'object') {\n return z.object({});\n }\n\n const shape: Record<string, z.ZodTypeAny> = {};\n\n for (const [key, value] of Object.entries(schemaObj.properties)) {\n let zodType = convertType(value);\n\n const isRequired =\n Array.isArray(schemaObj.required) && schemaObj.required.includes(key);\n if (!isRequired) {\n zodType = zodType.optional();\n }\n\n shape[key] = zodType;\n }\n\n return z.object(shape);\n}\n\n/**\n * Convert a single JSON Schema type to Zod\n */\nfunction convertType(schema: unknown): z.ZodTypeAny {\n if (!schema || typeof schema !== 'object' || !('type' in schema)) {\n return z.unknown();\n }\n\n const schemaObj = schema as {\n type: string;\n enum?: unknown[];\n items?: unknown;\n };\n let zodType: z.ZodTypeAny;\n\n switch (schemaObj.type) {\n case 'string':\n zodType = z.string();\n if (schemaObj.enum && Array.isArray(schemaObj.enum)) {\n zodType = z.enum(schemaObj.enum as [string, ...string[]]);\n }\n break;\n\n case 'number':\n zodType = z.number();\n if ('minimum' in schemaObj && typeof schemaObj.minimum === 'number') {\n zodType = (zodType as z.ZodNumber).min(schemaObj.minimum);\n }\n if ('maximum' in schemaObj && typeof schemaObj.maximum === 'number') {\n zodType = (zodType as z.ZodNumber).max(schemaObj.maximum);\n }\n break;\n\n case 'integer':\n zodType = z.number().int();\n if ('minimum' in schemaObj && typeof schemaObj.minimum === 'number') {\n zodType = (zodType as z.ZodNumber).min(schemaObj.minimum);\n }\n if ('maximum' in schemaObj && typeof schemaObj.maximum === 'number') {\n zodType = (zodType as z.ZodNumber).max(schemaObj.maximum);\n }\n break;\n\n case 'boolean':\n zodType = z.boolean();\n break;\n\n case 'array':\n if (schemaObj.items) {\n zodType = z.array(convertType(schemaObj.items));\n } else {\n zodType = z.array(z.unknown());\n }\n break;\n\n case 'object':\n if ('properties' in schemaObj) {\n zodType = jsonSchemaToZod(schemaObj);\n } else {\n zodType = z.object({}).passthrough();\n }\n break;\n\n default:\n zodType = z.unknown();\n }\n\n if ('description' in schemaObj && typeof schemaObj.description === 'string') {\n zodType = zodType.describe(schemaObj.description);\n }\n\n return zodType;\n}\n","import { encoding_for_model } from 'tiktoken';\nimport type { TiktokenModel } from 'tiktoken';\nimport type { BaseMessage } from '@langchain/core/messages';\n\n/**\n * Token counter utility for OpenAI models using tiktoken encoding\n * Provides accurate token counting for text content and chat messages\n */\nexport class TokenCounter {\n private encoding: ReturnType<typeof encoding_for_model>;\n private modelName: string;\n\n private static readonly MESSAGE_OVERHEAD = 3;\n private static readonly ROLE_OVERHEAD = 1;\n\n constructor(modelName: string | TiktokenModel = 'gpt-4o') {\n this.modelName = String(modelName);\n try {\n this.encoding = encoding_for_model(modelName as TiktokenModel);\n } catch {\n this.encoding = encoding_for_model('gpt-4o');\n this.modelName = 'gpt-4o';\n }\n }\n\n /**\n * Count tokens in raw text content\n * @param text - The text to count tokens for\n * @returns Number of tokens\n */\n countTokens(text: string): number {\n if (!text || text.trim() === '') {\n return 0;\n }\n\n try {\n const tokens = this.encoding.encode(text);\n return tokens.length;\n } catch {\n return Math.ceil(text.split(/\\s+/).length * 1.3);\n }\n }\n\n /**\n * Count tokens for a single chat message including role overhead\n * @param message - The message to count tokens for\n * @returns Number of tokens including message formatting overhead\n */\n countMessageTokens(message: BaseMessage): number {\n const contentTokens = this.countTokens(String(message.content ?? ''));\n const roleTokens = this.countTokens(this.getMessageRole(message));\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Count tokens for multiple messages\n * @param messages - Array of messages to count\n * @returns Total token count for all messages\n */\n countMessagesTokens(messages: BaseMessage[]): number {\n if (!messages || messages.length === 0) {\n return 0;\n }\n\n let total = 0;\n for (const message of messages) {\n total += this.countMessageTokens(message);\n }\n return total;\n }\n\n /**\n * Estimate tokens for system prompt\n * System prompts have slightly different overhead in chat completions\n * @param systemPrompt - The system prompt text\n * @returns Estimated token count\n */\n estimateSystemPromptTokens(systemPrompt: string): number {\n if (!systemPrompt || systemPrompt.trim() === '') {\n return 0;\n }\n\n const contentTokens = this.countTokens(systemPrompt);\n const roleTokens = this.countTokens('system');\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Get total context size estimate including system prompt and messages\n * @param systemPrompt - System prompt text\n * @param messages - Conversation messages\n * @returns Total estimated token count\n */\n estimateContextSize(systemPrompt: string, messages: BaseMessage[]): number {\n const systemTokens = this.estimateSystemPromptTokens(systemPrompt);\n const messageTokens = this.countMessagesTokens(messages);\n \n const completionOverhead = 10;\n \n return systemTokens + messageTokens + completionOverhead;\n }\n\n /**\n * Get the role string for a message\n * @param message - The message to get the role for\n * @returns Role string ('user', 'assistant', 'system', etc.)\n */\n private getMessageRole(message: BaseMessage): string {\n const messageType = message._getType();\n switch (messageType) {\n case 'human':\n return 'user';\n case 'ai':\n return 'assistant';\n case 'system':\n return 'system';\n case 'function':\n return 'function';\n case 'tool':\n return 'tool';\n default:\n return 'user';\n }\n }\n\n /**\n * Get the model name being used for token counting\n * @returns The tiktoken model name\n */\n getModelName(): string {\n return this.modelName;\n }\n\n /**\n * Clean up encoding resources\n */\n dispose(): void {\n try {\n this.encoding.free();\n } catch {\n }\n }\n}","import type { BaseMessage } from '@langchain/core/messages';\nimport { TokenCounter } from './token-counter';\n\n/**\n * Result of adding a message to the memory window\n */\nexport interface AddMessageResult {\n /** Whether the message was successfully added */\n added: boolean;\n /** Messages that were pruned to make room */\n prunedMessages: BaseMessage[];\n /** Current token count after operation */\n currentTokenCount: number;\n /** Remaining token capacity */\n remainingCapacity: number;\n}\n\n/**\n * Memory window that manages conversation history with token-based size limits\n * Automatically prunes old messages to stay within token limits while preserving conversational context\n */\nexport class MemoryWindow {\n private messages: BaseMessage[] = [];\n private maxTokens: number;\n private reserveTokens: number;\n private tokenCounter: TokenCounter;\n private systemPrompt: string = '';\n private systemPromptTokens: number = 0;\n\n public static readonly DEFAULT_MAX_TOKENS = 8000;\n public static readonly DEFAULT_RESERVE_TOKENS = 1000;\n public static readonly PRUNING_BATCH_SIZE = 2;\n\n constructor(\n maxTokens: number = MemoryWindow.DEFAULT_MAX_TOKENS,\n reserveTokens: number = MemoryWindow.DEFAULT_RESERVE_TOKENS,\n tokenCounter?: TokenCounter\n ) {\n if (reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n this.reserveTokens = reserveTokens;\n this.tokenCounter = tokenCounter || new TokenCounter();\n }\n\n /**\n * Add a message to the memory window, pruning old messages if necessary\n * @param message - The message to add\n * @returns Result of the add operation including any pruned messages\n */\n addMessage(message: BaseMessage): AddMessageResult {\n this.tokenCounter.countMessageTokens(message);\n\n this.messages.push(message);\n\n const currentTokens = this.getCurrentTokenCount();\n const availableTokens = this.maxTokens - this.reserveTokens;\n\n let prunedMessages: BaseMessage[] = [];\n\n if (currentTokens > availableTokens) {\n this.messages.pop();\n\n prunedMessages = this.pruneToFit();\n\n this.messages.push(message);\n }\n\n return {\n added: true,\n prunedMessages,\n currentTokenCount: this.getCurrentTokenCount(),\n remainingCapacity: this.getRemainingTokenCapacity(),\n };\n }\n\n /**\n * Prune old messages to fit within token limits\n * Removes messages in pairs to maintain conversational flow\n * @returns Array of pruned messages\n */\n pruneToFit(): BaseMessage[] {\n const prunedMessages: BaseMessage[] = [];\n const targetTokens = this.maxTokens - this.reserveTokens;\n\n while (\n this.getCurrentTokenCount() > targetTokens &&\n this.messages.length > 0\n ) {\n const batchSize = Math.min(\n MemoryWindow.PRUNING_BATCH_SIZE,\n this.messages.length\n );\n\n for (let i = 0; i < batchSize; i++) {\n const prunedMessage = this.messages.shift();\n if (prunedMessage) {\n prunedMessages.push(prunedMessage);\n }\n }\n\n if (prunedMessages.length > 1000) {\n break;\n }\n }\n\n return prunedMessages;\n }\n\n /**\n * Get current token count including system prompt and messages\n * @returns Current token count\n */\n getCurrentTokenCount(): number {\n const messageTokens = this.tokenCounter.countMessagesTokens(this.messages);\n return this.systemPromptTokens + messageTokens;\n }\n\n /**\n * Get remaining token capacity before hitting the reserve limit\n * @returns Remaining tokens that can be used\n */\n getRemainingTokenCapacity(): number {\n return Math.max(0, this.maxTokens - this.getCurrentTokenCount());\n }\n\n /**\n * Check if a message can be added without exceeding limits\n * @param message - The message to check\n * @returns True if message can be added within reserve limits\n */\n canAddMessage(message: BaseMessage): boolean {\n const messageTokens = this.tokenCounter.countMessageTokens(message);\n const currentTokens = this.getCurrentTokenCount();\n const wouldExceedReserve =\n currentTokens + messageTokens > this.maxTokens - this.reserveTokens;\n\n if (messageTokens > this.maxTokens) {\n return false;\n }\n\n return !wouldExceedReserve || this.messages.length > 0;\n }\n\n /**\n * Get all messages in the memory window\n * @returns Copy of current messages array\n */\n getMessages(): BaseMessage[] {\n return [...this.messages];\n }\n\n /**\n * Clear all messages from the memory window\n */\n clear(): void {\n this.messages = [];\n }\n\n /**\n * Set the system prompt and update token calculations\n * @param systemPrompt - The system prompt text\n */\n setSystemPrompt(systemPrompt: string): void {\n this.systemPrompt = systemPrompt;\n this.systemPromptTokens =\n this.tokenCounter.estimateSystemPromptTokens(systemPrompt);\n }\n\n /**\n * Get the current system prompt\n * @returns Current system prompt\n */\n getSystemPrompt(): string {\n return this.systemPrompt;\n }\n\n /**\n * Get current configuration\n * @returns Memory window configuration\n */\n getConfig(): {\n maxTokens: number;\n reserveTokens: number;\n currentTokens: number;\n messageCount: number;\n systemPromptTokens: number;\n } {\n return {\n maxTokens: this.maxTokens,\n reserveTokens: this.reserveTokens,\n currentTokens: this.getCurrentTokenCount(),\n messageCount: this.messages.length,\n systemPromptTokens: this.systemPromptTokens,\n };\n }\n\n /**\n * Update token limits\n * @param maxTokens - New maximum token limit\n * @param reserveTokens - New reserve token amount\n */\n updateLimits(maxTokens: number, reserveTokens?: number): void {\n if (reserveTokens !== undefined && reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n if (reserveTokens !== undefined) {\n this.reserveTokens = reserveTokens;\n }\n\n if (this.getCurrentTokenCount() > this.maxTokens - this.reserveTokens) {\n this.pruneToFit();\n }\n }\n\n /**\n * Get statistics about the memory window\n * @returns Memory usage statistics\n */\n getStats(): {\n totalMessages: number;\n currentTokens: number;\n maxTokens: number;\n reserveTokens: number;\n systemPromptTokens: number;\n usagePercentage: number;\n remainingCapacity: number;\n canAcceptMore: boolean;\n } {\n const currentTokens = this.getCurrentTokenCount();\n const capacity = this.maxTokens;\n const usagePercentage = (currentTokens / capacity) * 100;\n\n return {\n totalMessages: this.messages.length,\n currentTokens,\n maxTokens: capacity,\n reserveTokens: this.reserveTokens,\n systemPromptTokens: this.systemPromptTokens,\n usagePercentage: Math.round(usagePercentage * 100) / 100,\n remainingCapacity: this.getRemainingTokenCapacity(),\n canAcceptMore: this.getRemainingTokenCapacity() > this.reserveTokens,\n };\n }\n\n /**\n * Clean up resources\n */\n dispose(): void {\n this.clear();\n this.tokenCounter.dispose();\n }\n}\n","import { createHash } from 'crypto';\nimport { ReferenceId } from '../types/content-reference';\n\n/**\n * Content-based reference ID generator using SHA-256 (HCS-1 style)\n * \n * Generates deterministic reference IDs based on content hashing.\n * Same content always produces the same reference ID.\n */\nexport class ReferenceIdGenerator {\n /**\n * Generate a content-based reference ID using SHA-256 hashing\n * \n * @param content The content to generate a reference ID for\n * @returns Deterministic reference ID based on content hash\n */\n static generateId(content: Buffer): ReferenceId {\n const hash = createHash('sha256');\n hash.update(content);\n return hash.digest('hex');\n }\n \n /**\n * Validate that a string is a properly formatted reference ID\n * \n * @param id The ID to validate\n * @returns true if the ID is valid format\n */\n static isValidReferenceId(id: string): id is ReferenceId {\n if (!id || typeof id !== 'string') {\n return false;\n }\n \n if (id.length !== 64) {\n return false;\n }\n \n return /^[a-f0-9]+$/.test(id);\n }\n \n /**\n * Extract reference ID from ref:// format\n * \n * @param input Input string that may contain a reference ID\n * @returns Extracted reference ID or null if not found\n */\n static extractReferenceId(input: string): ReferenceId | null {\n if (!input || typeof input !== 'string') {\n return null;\n }\n \n const refFormatMatch = input.match(/^ref:\\/\\/([a-f0-9]{64})$/);\n if (refFormatMatch) {\n return refFormatMatch[1] as ReferenceId;\n }\n \n return this.isValidReferenceId(input) ? input : null;\n }\n \n /**\n * Format a reference ID in the standard ref:// format\n * \n * @param referenceId The reference ID to format\n * @returns Formatted reference string\n */\n static formatReference(referenceId: ReferenceId): string {\n return `ref://${referenceId}`;\n }\n \n /**\n * Generate a test reference ID (for testing purposes only)\n * \n * @param testSeed A test seed to generate a fake but valid ID format\n * @returns A valid format reference ID for testing\n */\n static generateTestId(testSeed: string): ReferenceId {\n const content = Buffer.from(`test-${testSeed}-${Date.now()}`);\n return this.generateId(content);\n }\n}","/**\n * Content Reference System Types\n *\n * Shared interfaces for the Reference-Based Content System that handles\n * large content storage with unique reference IDs to optimize context window usage.\n */\n\n/**\n * Unique identifier for stored content references\n * Format: Cryptographically secure 32-byte identifier with base64url encoding\n */\nexport type ReferenceId = string;\n\n/**\n * Lifecycle state of a content reference\n */\nexport type ReferenceLifecycleState =\n | 'active'\n | 'expired'\n | 'cleanup_pending'\n | 'invalid';\n\n/**\n * Content types supported by the reference system\n */\nexport type ContentType =\n | 'text'\n | 'json'\n | 'html'\n | 'markdown'\n | 'binary'\n | 'unknown';\n\n/**\n * Sources that created the content reference\n */\nexport type ContentSource =\n | 'mcp_tool'\n | 'user_upload'\n | 'agent_generated'\n | 'system';\n\n/**\n * Metadata associated with stored content\n */\nexport interface ContentMetadata {\n /** Content type classification */\n contentType: ContentType;\n\n /** MIME type of the original content */\n mimeType?: string;\n\n /** Size in bytes of the stored content */\n sizeBytes: number;\n\n /** When the content was originally stored */\n createdAt: Date;\n\n /** Last time the content was accessed via reference resolution */\n lastAccessedAt: Date;\n\n /** Source that created this content reference */\n source: ContentSource;\n\n /** Name of the MCP tool that generated the content (if applicable) */\n mcpToolName?: string;\n\n /** Original filename or suggested name for the content */\n fileName?: string;\n\n /** Number of times this reference has been resolved */\n accessCount: number;\n\n /** Tags for categorization and cleanup policies */\n tags?: string[];\n\n /** Custom metadata from the source */\n customMetadata?: Record<string, unknown>;\n}\n\n/**\n * Core content reference object passed through agent context\n * Designed to be lightweight (<100 tokens) while providing enough\n * information for agent decision-making\n */\nexport interface ContentReference {\n /** Unique identifier for resolving the content */\n referenceId: ReferenceId;\n\n /** Current lifecycle state */\n state: ReferenceLifecycleState;\n\n /** Brief description or preview of the content (max 200 chars) */\n preview: string;\n\n /** Essential metadata for agent decision-making */\n metadata: Pick<\n ContentMetadata,\n 'contentType' | 'sizeBytes' | 'source' | 'fileName' | 'mimeType'\n >;\n\n /** When this reference was created */\n createdAt: Date;\n\n /** Special format indicator for reference IDs in content */\n readonly format: 'ref://{id}';\n}\n\n/**\n * Result of attempting to resolve a content reference\n */\nexport interface ReferenceResolutionResult {\n /** Whether the resolution was successful */\n success: boolean;\n\n /** The resolved content if successful */\n content?: Buffer;\n\n /** Complete metadata if successful */\n metadata?: ContentMetadata;\n\n /** Error message if resolution failed */\n error?: string;\n\n /** Specific error type for targeted error handling */\n errorType?:\n | 'not_found'\n | 'expired'\n | 'corrupted'\n | 'access_denied'\n | 'system_error';\n\n /** Suggested actions for recovery */\n suggestedActions?: string[];\n}\n\n/**\n * Configuration for content reference storage and lifecycle\n */\nexport interface ContentReferenceConfig {\n /** Size threshold above which content should be stored as references (default: 10KB) */\n sizeThresholdBytes: number;\n\n /** Maximum age for unused references before cleanup (default: 1 hour) */\n maxAgeMs: number;\n\n /** Maximum number of references to store simultaneously */\n maxReferences: number;\n\n /** Maximum total storage size for all references */\n maxTotalStorageBytes: number;\n\n /** Whether to enable automatic cleanup */\n enableAutoCleanup: boolean;\n\n /** Interval for cleanup checks in milliseconds */\n cleanupIntervalMs: number;\n\n /** Whether to persist references across restarts */\n enablePersistence: boolean;\n\n /** Storage backend configuration */\n storageBackend: 'memory' | 'filesystem' | 'hybrid';\n\n /** Cleanup policies for different content types */\n cleanupPolicies: {\n /** Policy for content marked as \"recent\" from MCP tools */\n recent: { maxAgeMs: number; priority: number };\n\n /** Policy for user-uploaded content */\n userContent: { maxAgeMs: number; priority: number };\n\n /** Policy for agent-generated content */\n agentGenerated: { maxAgeMs: number; priority: number };\n\n /** Default policy for other content */\n default: { maxAgeMs: number; priority: number };\n };\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONTENT_REFERENCE_CONFIG: ContentReferenceConfig = {\n sizeThresholdBytes: 10 * 1024,\n maxAgeMs: 60 * 60 * 1000,\n maxReferences: 100,\n maxTotalStorageBytes: 100 * 1024 * 1024,\n enableAutoCleanup: true,\n cleanupIntervalMs: 5 * 60 * 1000,\n enablePersistence: false,\n storageBackend: 'memory',\n cleanupPolicies: {\n recent: { maxAgeMs: 30 * 60 * 1000, priority: 1 },\n userContent: { maxAgeMs: 2 * 60 * 60 * 1000, priority: 2 },\n agentGenerated: { maxAgeMs: 60 * 60 * 1000, priority: 3 },\n default: { maxAgeMs: 60 * 60 * 1000, priority: 4 },\n },\n};\n\n/**\n * Statistics about content reference usage and storage\n */\nexport interface ContentReferenceStats {\n /** Total number of active references */\n activeReferences: number;\n\n /** Total storage used by all references in bytes */\n totalStorageBytes: number;\n\n /** Number of references cleaned up in last cleanup cycle */\n recentlyCleanedUp: number;\n\n /** Number of successful reference resolutions since startup */\n totalResolutions: number;\n\n /** Number of failed resolution attempts */\n failedResolutions: number;\n\n /** Average content size in bytes */\n averageContentSize: number;\n\n /** Most frequently accessed reference ID */\n mostAccessedReferenceId?: ReferenceId;\n\n /** Storage utilization percentage */\n storageUtilization: number;\n\n /** Performance metrics */\n performanceMetrics: {\n /** Average time to create a reference in milliseconds */\n averageCreationTimeMs: number;\n\n /** Average time to resolve a reference in milliseconds */\n averageResolutionTimeMs: number;\n\n /** Average cleanup time in milliseconds */\n averageCleanupTimeMs: number;\n };\n}\n\n/**\n * Error types for content reference operations\n */\nexport class ContentReferenceError extends Error {\n constructor(\n message: string,\n public readonly type: ReferenceResolutionResult['errorType'],\n public readonly referenceId?: ReferenceId,\n public readonly suggestedActions?: string[]\n ) {\n super(message);\n this.name = 'ContentReferenceError';\n }\n}\n\n/**\n * Interface for content reference storage implementations\n */\nexport interface ContentReferenceStore {\n /**\n * Store content and return a reference\n */\n storeContent(\n content: Buffer,\n metadata: Omit<\n ContentMetadata,\n 'createdAt' | 'lastAccessedAt' | 'accessCount'\n >\n ): Promise<ContentReference>;\n\n /**\n * Resolve a reference to its content\n */\n resolveReference(\n referenceId: ReferenceId\n ): Promise<ReferenceResolutionResult>;\n\n /**\n * Check if a reference exists and is valid\n */\n hasReference(referenceId: ReferenceId): Promise<boolean>;\n\n /**\n * Mark a reference for cleanup\n */\n cleanupReference(referenceId: ReferenceId): Promise<boolean>;\n\n /**\n * Get current storage statistics\n */\n getStats(): Promise<ContentReferenceStats>;\n\n /**\n * Update configuration\n */\n updateConfig(config: Partial<ContentReferenceConfig>): Promise<void>;\n\n /**\n * Perform cleanup based on current policies\n */\n performCleanup(): Promise<{ cleanedUp: number; errors: string[] }>;\n\n /**\n * Dispose of resources\n */\n dispose(): Promise<void>;\n}\n","import type { BaseMessage } from '@langchain/core/messages';\nimport { ReferenceIdGenerator } from './reference-id-generator';\nimport {\n ReferenceId,\n ContentReference,\n ContentMetadata,\n ReferenceResolutionResult,\n ContentReferenceConfig,\n ContentReferenceStore,\n ContentReferenceStats,\n ContentReferenceError,\n ContentType,\n ContentSource,\n ReferenceLifecycleState,\n DEFAULT_CONTENT_REFERENCE_CONFIG,\n} from '../types/content-reference';\n\n/**\n * Stored message with metadata\n */\ninterface StoredMessage {\n message: BaseMessage;\n storedAt: Date;\n id: string;\n}\n\n/**\n * Search options for message queries\n */\ninterface SearchOptions {\n /** Whether to perform case-sensitive search */\n caseSensitive?: boolean;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use regex pattern matching */\n useRegex?: boolean;\n}\n\n/**\n * Result of storing messages\n */\ninterface StoreResult {\n /** Number of messages successfully stored */\n stored: number;\n /** Number of old messages dropped to make room */\n dropped: number;\n}\n\n/**\n * Storage statistics\n */\nexport interface StorageStats {\n /** Total number of messages currently stored */\n totalMessages: number;\n /** Maximum storage capacity */\n maxStorageLimit: number;\n /** Percentage of storage used */\n usagePercentage: number;\n /** Timestamp of oldest message */\n oldestMessageTime: Date | undefined;\n /** Timestamp of newest message */\n newestMessageTime: Date | undefined;\n}\n\n/**\n * Stored content with reference metadata\n */\ninterface StoredContent {\n /** The actual content buffer */\n content: Buffer;\n\n /** Complete metadata */\n metadata: ContentMetadata;\n\n /** Current lifecycle state */\n state: ReferenceLifecycleState;\n\n /** When this reference expires (if applicable) */\n expiresAt?: Date;\n}\n\n/**\n * Content storage for managing pruned conversation messages and large content references\n * Provides searchable storage with time-based querying and automatic cleanup.\n *\n * Extended to support reference-based storage for large content to optimize context window usage.\n */\nexport class ContentStorage implements ContentReferenceStore {\n private messages: StoredMessage[] = [];\n private maxStorage: number;\n private idCounter: number = 0;\n\n private contentStore: Map<ReferenceId, StoredContent> = new Map();\n private referenceConfig: ContentReferenceConfig;\n private cleanupTimer?: NodeJS.Timeout;\n private referenceStats: Omit<ContentReferenceStats, 'performanceMetrics'> & {\n performanceMetrics: ContentReferenceStats['performanceMetrics'] & {\n creationTimes: number[];\n resolutionTimes: number[];\n cleanupTimes: number[];\n };\n };\n\n public static readonly DEFAULT_MAX_STORAGE = 1000;\n\n constructor(\n maxStorage: number = ContentStorage.DEFAULT_MAX_STORAGE,\n referenceConfig?: Partial<ContentReferenceConfig>\n ) {\n this.maxStorage = maxStorage;\n\n this.referenceConfig = {\n ...DEFAULT_CONTENT_REFERENCE_CONFIG,\n ...referenceConfig,\n };\n this.referenceStats = {\n activeReferences: 0,\n totalStorageBytes: 0,\n recentlyCleanedUp: 0,\n totalResolutions: 0,\n failedResolutions: 0,\n averageContentSize: 0,\n storageUtilization: 0,\n performanceMetrics: {\n averageCreationTimeMs: 0,\n averageResolutionTimeMs: 0,\n averageCleanupTimeMs: 0,\n creationTimes: [],\n resolutionTimes: [],\n cleanupTimes: [],\n },\n };\n\n if (this.referenceConfig.enableAutoCleanup) {\n this.startReferenceCleanupTimer();\n }\n }\n\n /**\n * Store messages in the content storage\n * Automatically drops oldest messages if storage limit is exceeded\n * @param messages - Messages to store\n * @returns Result indicating how many messages were stored and dropped\n */\n storeMessages(messages: BaseMessage[]): StoreResult {\n if (messages.length === 0) {\n return { stored: 0, dropped: 0 };\n }\n\n const now = new Date();\n let dropped = 0;\n\n const storedMessages: StoredMessage[] = messages.map((message) => ({\n message,\n storedAt: now,\n id: this.generateId(),\n }));\n\n this.messages.push(...storedMessages);\n\n while (this.messages.length > this.maxStorage) {\n this.messages.shift();\n dropped++;\n }\n\n return {\n stored: storedMessages.length,\n dropped,\n };\n }\n\n /**\n * Get the most recent messages from storage\n * @param count - Number of recent messages to retrieve\n * @returns Array of recent messages in chronological order\n */\n getRecentMessages(count: number): BaseMessage[] {\n if (count <= 0 || this.messages.length === 0) {\n return [];\n }\n\n const startIndex = Math.max(0, this.messages.length - count);\n return this.messages.slice(startIndex).map((stored) => stored.message);\n }\n\n /**\n * Search for messages containing specific text or patterns\n * @param query - Search term or regex pattern\n * @param options - Search configuration options\n * @returns Array of matching messages\n */\n searchMessages(query: string, options: SearchOptions = {}): BaseMessage[] {\n if (!query || this.messages.length === 0) {\n return [];\n }\n\n const { caseSensitive = false, limit, useRegex = false } = options;\n\n let matches: BaseMessage[] = [];\n\n if (useRegex) {\n try {\n const regex = new RegExp(query, caseSensitive ? 'g' : 'gi');\n matches = this.messages\n .filter((stored) => regex.test(stored.message.content as string))\n .map((stored) => stored.message);\n } catch {\n return [];\n }\n } else {\n const searchTerm = caseSensitive ? query : query.toLowerCase();\n matches = this.messages\n .filter((stored) => {\n const content = stored.message.content as string;\n const searchContent = caseSensitive ? content : content.toLowerCase();\n return searchContent.includes(searchTerm);\n })\n .map((stored) => stored.message);\n }\n\n return limit ? matches.slice(0, limit) : matches;\n }\n\n /**\n * Get messages from a specific time range\n * @param startTime - Start of time range (inclusive)\n * @param endTime - End of time range (inclusive)\n * @returns Array of messages within the time range\n */\n getMessagesFromTimeRange(startTime: Date, endTime: Date): BaseMessage[] {\n if (startTime > endTime || this.messages.length === 0) {\n return [];\n }\n\n return this.messages\n .filter(\n (stored) => stored.storedAt >= startTime && stored.storedAt <= endTime\n )\n .map((stored) => stored.message);\n }\n\n /**\n * Get storage statistics and usage information\n * @returns Current storage statistics\n */\n getStorageStats(): StorageStats {\n const totalMessages = this.messages.length;\n const usagePercentage =\n totalMessages > 0\n ? Math.round((totalMessages / this.maxStorage) * 100)\n : 0;\n\n let oldestMessageTime: Date | undefined;\n let newestMessageTime: Date | undefined;\n\n if (totalMessages > 0) {\n oldestMessageTime = this.messages[0].storedAt;\n newestMessageTime = this.messages[totalMessages - 1].storedAt;\n }\n\n return {\n totalMessages,\n maxStorageLimit: this.maxStorage,\n usagePercentage,\n oldestMessageTime,\n newestMessageTime,\n };\n }\n\n /**\n * Clear all stored messages\n */\n clear(): void {\n this.messages = [];\n this.idCounter = 0;\n }\n\n /**\n * Get total number of stored messages\n * @returns Number of messages currently in storage\n */\n getTotalStoredMessages(): number {\n return this.messages.length;\n }\n\n /**\n * Update the maximum storage limit\n * @param newLimit - New maximum storage limit\n */\n updateStorageLimit(newLimit: number): void {\n if (newLimit <= 0) {\n throw new Error('Storage limit must be greater than 0');\n }\n\n this.maxStorage = newLimit;\n\n while (this.messages.length > this.maxStorage) {\n this.messages.shift();\n }\n }\n\n /**\n * Get messages by message type\n * @param messageType - Type of messages to retrieve ('human', 'ai', 'system', etc.)\n * @param limit - Maximum number of messages to return\n * @returns Array of messages of the specified type\n */\n getMessagesByType(messageType: string, limit?: number): BaseMessage[] {\n const filtered = this.messages\n .filter((stored) => stored.message._getType() === messageType)\n .map((stored) => stored.message);\n\n return limit ? filtered.slice(0, limit) : filtered;\n }\n\n /**\n * Get the current storage configuration\n * @returns Storage configuration object\n */\n getConfig(): {\n maxStorage: number;\n currentUsage: number;\n utilizationPercentage: number;\n } {\n return {\n maxStorage: this.maxStorage,\n currentUsage: this.messages.length,\n utilizationPercentage: (this.messages.length / this.maxStorage) * 100,\n };\n }\n\n /**\n * Generate a unique ID for stored messages\n * @returns Unique string identifier\n */\n private generateId(): string {\n return `msg_${++this.idCounter}_${Date.now()}`;\n }\n\n /**\n * Get messages stored within the last N minutes\n * @param minutes - Number of minutes to look back\n * @returns Array of messages from the last N minutes\n */\n getRecentMessagesByTime(minutes: number): BaseMessage[] {\n if (minutes <= 0 || this.messages.length === 0) {\n return [];\n }\n\n const cutoffTime = new Date(Date.now() - minutes * 60 * 1000);\n\n return this.messages\n .filter((stored) => stored.storedAt >= cutoffTime)\n .map((stored) => stored.message);\n }\n\n /**\n * Export messages to a JSON-serializable format\n * @returns Serializable representation of stored messages\n */\n exportMessages(): Array<{\n content: string;\n type: string;\n storedAt: string;\n id: string;\n }> {\n return this.messages.map((stored) => ({\n content:\n typeof stored.message.content === 'string'\n ? stored.message.content\n : JSON.stringify(stored.message.content),\n type: stored.message._getType(),\n storedAt: stored.storedAt.toISOString(),\n id: stored.id,\n }));\n }\n\n /**\n * Determine if content should be stored as a reference based on size\n */\n shouldUseReference(content: Buffer | string): boolean {\n const size = Buffer.isBuffer(content)\n ? content.length\n : Buffer.byteLength(content, 'utf8');\n return size > this.referenceConfig.sizeThresholdBytes;\n }\n\n /**\n * Store content and return a reference if it exceeds the size threshold\n * Otherwise returns null to indicate direct content should be used\n *\n * Special case: Image files are ALWAYS stored as references regardless of size\n * because they need special handling for inscription tools\n */\n async storeContentIfLarge(\n content: Buffer | string,\n metadata: {\n contentType?: ContentType;\n mimeType?: string;\n source: ContentSource;\n mcpToolName?: string;\n fileName?: string;\n tags?: string[];\n customMetadata?: Record<string, unknown>;\n }\n ): Promise<ContentReference | null> {\n const buffer = Buffer.isBuffer(content)\n ? content\n : Buffer.from(content, 'utf8');\n\n const isImageFile = this.isImageContent(\n metadata.mimeType,\n metadata.fileName\n );\n\n if (!isImageFile && !this.shouldUseReference(buffer)) {\n return null;\n }\n\n const storeMetadata: Omit<\n ContentMetadata,\n 'createdAt' | 'lastAccessedAt' | 'accessCount'\n > = {\n contentType:\n metadata.contentType ||\n this.detectContentType(buffer, metadata.mimeType),\n sizeBytes: buffer.length,\n source: metadata.source,\n tags: [],\n };\n\n if (metadata.mimeType !== undefined) {\n storeMetadata.mimeType = metadata.mimeType;\n }\n if (metadata.mcpToolName !== undefined) {\n storeMetadata.mcpToolName = metadata.mcpToolName;\n }\n if (metadata.fileName !== undefined) {\n storeMetadata.fileName = metadata.fileName;\n }\n if (metadata.tags !== undefined) {\n storeMetadata.tags = metadata.tags;\n }\n if (metadata.customMetadata !== undefined) {\n storeMetadata.customMetadata = metadata.customMetadata;\n }\n\n return await this.storeContent(buffer, storeMetadata);\n }\n\n /**\n * Store content and return a reference (implements ContentReferenceStore)\n */\n async storeContent(\n content: Buffer,\n metadata: Omit<\n ContentMetadata,\n 'createdAt' | 'lastAccessedAt' | 'accessCount'\n >\n ): Promise<ContentReference> {\n const startTime = Date.now();\n\n try {\n const now = new Date();\n const referenceId = ReferenceIdGenerator.generateId(content);\n\n const fullMetadata: ContentMetadata = {\n ...metadata,\n createdAt: now,\n lastAccessedAt: now,\n accessCount: 0,\n };\n\n const storedContent: StoredContent = {\n content,\n metadata: fullMetadata,\n state: 'active',\n };\n\n const expirationTime = this.calculateExpirationTime(metadata.source);\n if (expirationTime !== undefined) {\n storedContent.expiresAt = expirationTime;\n }\n\n this.contentStore.set(referenceId, storedContent);\n\n this.updateStatsAfterStore(content.length);\n\n await this.enforceReferenceStorageLimits();\n\n const preview = this.createContentPreview(\n content,\n fullMetadata.contentType\n );\n\n const referenceMetadata: Pick<\n ContentMetadata,\n 'contentType' | 'sizeBytes' | 'source' | 'fileName' | 'mimeType'\n > = {\n contentType: fullMetadata.contentType,\n sizeBytes: fullMetadata.sizeBytes,\n source: fullMetadata.source,\n };\n\n if (fullMetadata.fileName !== undefined) {\n referenceMetadata.fileName = fullMetadata.fileName;\n }\n if (fullMetadata.mimeType !== undefined) {\n referenceMetadata.mimeType = fullMetadata.mimeType;\n }\n\n const reference: ContentReference = {\n referenceId,\n state: 'active',\n preview,\n metadata: referenceMetadata,\n createdAt: now,\n format: 'ref://{id}' as const,\n };\n\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('creation', duration);\n\n return reference;\n } catch (error) {\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('creation', duration);\n\n throw new ContentReferenceError(\n `Failed to store content: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n 'system_error',\n undefined,\n ['Try again', 'Check storage limits', 'Contact administrator']\n );\n }\n }\n\n /**\n * Resolve a reference to its content (implements ContentReferenceStore)\n */\n async resolveReference(\n referenceId: ReferenceId\n ): Promise<ReferenceResolutionResult> {\n const startTime = Date.now();\n\n try {\n if (!ReferenceIdGenerator.isValidReferenceId(referenceId)) {\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: 'Invalid reference ID format',\n errorType: 'not_found',\n suggestedActions: [\n 'Check the reference ID format',\n 'Ensure the reference ID is complete',\n ],\n };\n }\n\n const storedContent = this.contentStore.get(referenceId);\n\n if (!storedContent) {\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: 'Reference not found',\n errorType: 'not_found',\n suggestedActions: [\n 'Verify the reference ID',\n 'Check if the content has expired',\n 'Request fresh content',\n ],\n };\n }\n\n if (storedContent.expiresAt && storedContent.expiresAt < new Date()) {\n storedContent.state = 'expired';\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: 'Reference has expired',\n errorType: 'expired',\n suggestedActions: [\n 'Request fresh content',\n 'Use alternative content source',\n ],\n };\n }\n\n if (storedContent.state !== 'active') {\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: `Reference is ${storedContent.state}`,\n errorType:\n storedContent.state === 'expired' ? 'expired' : 'corrupted',\n suggestedActions: [\n 'Request fresh content',\n 'Check reference validity',\n ],\n };\n }\n\n storedContent.metadata.lastAccessedAt = new Date();\n storedContent.metadata.accessCount++;\n\n this.referenceStats.totalResolutions++;\n\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('resolution', duration);\n\n return {\n success: true,\n content: storedContent.content,\n metadata: storedContent.metadata,\n };\n } catch (error) {\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('resolution', duration);\n\n this.referenceStats.failedResolutions++;\n\n return {\n success: false,\n error: `System error resolving reference: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n errorType: 'system_error',\n suggestedActions: ['Try again', 'Contact administrator'],\n };\n }\n }\n\n /**\n * Check if a reference exists and is valid\n */\n async hasReference(referenceId: ReferenceId): Promise<boolean> {\n if (!ReferenceIdGenerator.isValidReferenceId(referenceId)) {\n return false;\n }\n\n const storedContent = this.contentStore.get(referenceId);\n if (!storedContent) {\n return false;\n }\n\n if (storedContent.expiresAt && storedContent.expiresAt < new Date()) {\n storedContent.state = 'expired';\n return false;\n }\n\n return storedContent.state === 'active';\n }\n\n /**\n * Mark a reference for cleanup\n */\n async cleanupReference(referenceId: ReferenceId): Promise<boolean> {\n const storedContent = this.contentStore.get(referenceId);\n if (!storedContent) {\n return false;\n }\n\n this.referenceStats.totalStorageBytes -= storedContent.content.length;\n this.referenceStats.activeReferences--;\n this.referenceStats.recentlyCleanedUp++;\n\n this.contentStore.delete(referenceId);\n\n return true;\n }\n\n /**\n * Get current reference storage statistics (implements ContentReferenceStore)\n */\n async getStats(): Promise<ContentReferenceStats> {\n this.updateReferenceStorageStats();\n\n return {\n ...this.referenceStats,\n performanceMetrics: {\n averageCreationTimeMs: this.calculateAverage(\n this.referenceStats.performanceMetrics.creationTimes\n ),\n averageResolutionTimeMs: this.calculateAverage(\n this.referenceStats.performanceMetrics.resolutionTimes\n ),\n averageCleanupTimeMs: this.calculateAverage(\n this.referenceStats.performanceMetrics.cleanupTimes\n ),\n },\n };\n }\n\n /**\n * Update reference configuration\n */\n async updateConfig(config: Partial<ContentReferenceConfig>): Promise<void> {\n this.referenceConfig = { ...this.referenceConfig, ...config };\n\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n delete this.cleanupTimer;\n }\n\n if (this.referenceConfig.enableAutoCleanup) {\n this.startReferenceCleanupTimer();\n }\n }\n\n /**\n * Perform cleanup based on current policies (implements ContentReferenceStore)\n */\n async performCleanup(): Promise<{ cleanedUp: number; errors: string[] }> {\n const startTime = Date.now();\n const errors: string[] = [];\n let cleanedUp = 0;\n\n try {\n const now = new Date();\n const toCleanup: ReferenceId[] = [];\n\n for (const [referenceId, storedContent] of this.contentStore.entries()) {\n let shouldCleanup = false;\n\n if (storedContent.expiresAt && storedContent.expiresAt < now) {\n shouldCleanup = true;\n storedContent.state = 'expired';\n }\n\n const ageMs =\n now.getTime() - storedContent.metadata.createdAt.getTime();\n const policy = this.getCleanupPolicy(storedContent.metadata.source);\n\n if (ageMs > policy.maxAgeMs) {\n shouldCleanup = true;\n }\n\n if (storedContent.state === 'cleanup_pending') {\n shouldCleanup = true;\n }\n\n if (shouldCleanup) {\n toCleanup.push(referenceId);\n }\n }\n\n toCleanup.sort((a, b) => {\n const aContent = this.contentStore.get(a)!;\n const bContent = this.contentStore.get(b)!;\n const aPriority = this.getCleanupPolicy(\n aContent.metadata.source\n ).priority;\n const bPriority = this.getCleanupPolicy(\n bContent.metadata.source\n ).priority;\n return bPriority - aPriority;\n });\n\n for (const referenceId of toCleanup) {\n try {\n const success = await this.cleanupReference(referenceId);\n if (success) {\n cleanedUp++;\n }\n } catch (error) {\n errors.push(\n `Failed to cleanup ${referenceId}: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\n }\n }\n\n if (this.contentStore.size > this.referenceConfig.maxReferences) {\n const sortedByAge = Array.from(this.contentStore.entries()).sort(\n ([, a], [, b]) =>\n a.metadata.lastAccessedAt.getTime() -\n b.metadata.lastAccessedAt.getTime()\n );\n\n const excessCount =\n this.contentStore.size - this.referenceConfig.maxReferences;\n for (let i = 0; i < excessCount && i < sortedByAge.length; i++) {\n const [referenceId] = sortedByAge[i];\n try {\n const success = await this.cleanupReference(referenceId);\n if (success) {\n cleanedUp++;\n }\n } catch (error) {\n errors.push(\n `Failed to cleanup excess reference ${referenceId}: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\n }\n }\n }\n\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('cleanup', duration);\n\n return { cleanedUp, errors };\n } catch (error) {\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('cleanup', duration);\n\n const errorMessage = `Cleanup process failed: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`;\n errors.push(errorMessage);\n\n return { cleanedUp, errors };\n }\n }\n\n /**\n * Get reference configuration for debugging\n */\n getReferenceConfig(): ContentReferenceConfig {\n return { ...this.referenceConfig };\n }\n\n private async enforceReferenceStorageLimits(): Promise<void> {\n if (this.contentStore.size >= this.referenceConfig.maxReferences) {\n await this.performCleanup();\n }\n\n if (\n this.referenceStats.totalStorageBytes >=\n this.referenceConfig.maxTotalStorageBytes\n ) {\n await this.performCleanup();\n }\n }\n\n private calculateExpirationTime(source: ContentSource): Date | undefined {\n const policy = this.getCleanupPolicy(source);\n return new Date(Date.now() + policy.maxAgeMs);\n }\n\n private getCleanupPolicy(source: ContentSource): {\n maxAgeMs: number;\n priority: number;\n } {\n switch (source) {\n case 'mcp_tool':\n return this.referenceConfig.cleanupPolicies.recent;\n case 'user_upload':\n return this.referenceConfig.cleanupPolicies.userContent;\n case 'agent_generated':\n return this.referenceConfig.cleanupPolicies.agentGenerated;\n default:\n return this.referenceConfig.cleanupPolicies.default;\n }\n }\n\n private detectContentType(content: Buffer, mimeType?: string): ContentType {\n if (mimeType) {\n if (mimeType === 'text/html') return 'html';\n if (mimeType === 'text/markdown') return 'markdown';\n if (mimeType === 'application/json') return 'json';\n if (mimeType.startsWith('text/')) return 'text';\n return 'binary';\n }\n\n const contentStr = content.toString(\n 'utf8',\n 0,\n Math.min(content.length, 1000)\n );\n if (contentStr.startsWith('{') || contentStr.startsWith('[')) return 'json';\n if (contentStr.includes('<html>') || contentStr.includes('<!DOCTYPE'))\n return 'html';\n if (contentStr.includes('#') && contentStr.includes('\\n'))\n return 'markdown';\n\n return 'text';\n }\n\n private createContentPreview(\n content: Buffer,\n contentType: ContentType\n ): string {\n const maxLength = 200;\n let preview = content.toString(\n 'utf8',\n 0,\n Math.min(content.length, maxLength * 2)\n );\n\n if (contentType === 'html') {\n preview = preview\n .replace(/<[^>]*>/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n } else if (contentType === 'json') {\n try {\n const parsed = JSON.parse(preview);\n preview = JSON.stringify(parsed, null, 0);\n } catch {}\n }\n\n preview = preview.trim();\n if (preview.length > maxLength) {\n preview = preview.substring(0, maxLength) + '...';\n }\n\n return preview || '[Binary content]';\n }\n\n private updateStatsAfterStore(sizeBytes: number): void {\n this.referenceStats.activeReferences++;\n this.referenceStats.totalStorageBytes += sizeBytes;\n this.updateReferenceStorageStats();\n }\n\n private updateReferenceStorageStats(): void {\n if (this.referenceStats.activeReferences > 0) {\n this.referenceStats.averageContentSize =\n this.referenceStats.totalStorageBytes /\n this.referenceStats.activeReferences;\n }\n\n this.referenceStats.storageUtilization =\n (this.referenceStats.totalStorageBytes /\n this.referenceConfig.maxTotalStorageBytes) *\n 100;\n\n let mostAccessedId: ReferenceId | undefined;\n let maxAccess = 0;\n\n for (const [referenceId, storedContent] of this.contentStore.entries()) {\n if (storedContent.metadata.accessCount > maxAccess) {\n maxAccess = storedContent.metadata.accessCount;\n mostAccessedId = referenceId;\n }\n }\n\n if (mostAccessedId !== undefined) {\n this.referenceStats.mostAccessedReferenceId = mostAccessedId;\n } else {\n delete this.referenceStats.mostAccessedReferenceId;\n }\n }\n\n /**\n * Check if content is an image file based on MIME type or filename\n */\n private isImageContent(mimeType?: string, fileName?: string): boolean {\n if (mimeType && mimeType.startsWith('image/')) {\n return true;\n }\n\n if (fileName) {\n const lowerFileName = fileName.toLowerCase();\n const imageExtensions = [\n '.png',\n '.jpg',\n '.jpeg',\n '.gif',\n '.bmp',\n '.webp',\n '.svg',\n '.tiff',\n '.ico',\n ];\n return imageExtensions.some((ext) => lowerFileName.endsWith(ext));\n }\n\n return false;\n }\n\n private recordPerformanceMetric(\n type: 'creation' | 'resolution' | 'cleanup',\n timeMs: number\n ): void {\n const metrics = this.referenceStats.performanceMetrics;\n const maxRecords = 100;\n\n switch (type) {\n case 'creation':\n metrics.creationTimes.push(timeMs);\n if (metrics.creationTimes.length > maxRecords) {\n metrics.creationTimes.shift();\n }\n break;\n case 'resolution':\n metrics.resolutionTimes.push(timeMs);\n if (metrics.resolutionTimes.length > maxRecords) {\n metrics.resolutionTimes.shift();\n }\n break;\n case 'cleanup':\n metrics.cleanupTimes.push(timeMs);\n if (metrics.cleanupTimes.length > maxRecords) {\n metrics.cleanupTimes.shift();\n }\n break;\n }\n }\n\n private calculateAverage(times: number[]): number {\n if (times.length === 0) return 0;\n return times.reduce((sum, time) => sum + time, 0) / times.length;\n }\n\n private startReferenceCleanupTimer(): void {\n this.cleanupTimer = setInterval(async () => {\n try {\n await this.performCleanup();\n } catch {}\n }, this.referenceConfig.cleanupIntervalMs);\n }\n\n /**\n * Clean up resources (enhanced to include reference cleanup)\n */\n async dispose(): Promise<void> {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n delete this.cleanupTimer;\n }\n\n this.contentStore.clear();\n\n this.clear();\n }\n}\n","import type { BaseMessage } from '@langchain/core/messages';\nimport { SystemMessage } from '@langchain/core/messages';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport { MemoryWindow } from './memory-window';\nimport { ContentStorage } from './content-storage';\nimport { TokenCounter } from './token-counter';\n\n/**\n * Entity association for storing blockchain entity contexts\n */\nexport interface EntityAssociation {\n /** The blockchain entity ID (e.g., tokenId, accountId, topicId) */\n entityId: string;\n /** User-provided or derived friendly name */\n entityName: string;\n /** Type of entity (token, account, topic, schedule, etc.) */\n entityType: string;\n /** When the entity was created/associated */\n createdAt: Date;\n /** Transaction ID that created this entity */\n transactionId?: string;\n /** Optional session identifier to scope associations */\n sessionId?: string;\n}\n\n/**\n * Options for resolving entity references\n */\nexport interface EntityResolutionOptions {\n /** Filter by specific entity type */\n entityType?: string;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use fuzzy matching for natural language queries */\n fuzzyMatch?: boolean;\n}\n\n/**\n * Configuration for SmartMemoryManager\n */\nexport interface SmartMemoryConfig {\n /** Maximum tokens for active memory window */\n maxTokens?: number;\n /** Reserve tokens for response generation */\n reserveTokens?: number;\n /** Model name for token counting */\n modelName?: string;\n /** Maximum messages to store in content storage */\n storageLimit?: number;\n}\n\n/**\n * Search options for history search\n */\nexport interface SearchOptions {\n /** Whether to perform case-sensitive search */\n caseSensitive?: boolean;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use regex pattern matching */\n useRegex?: boolean;\n}\n\n/**\n * Memory statistics for active memory window\n */\nexport interface MemoryStats {\n /** Total active messages in memory window */\n totalActiveMessages: number;\n /** Current token count including system prompt */\n currentTokenCount: number;\n /** Maximum token capacity */\n maxTokens: number;\n /** Remaining token capacity */\n remainingCapacity: number;\n /** System prompt token count */\n systemPromptTokens: number;\n /** Memory usage percentage */\n usagePercentage: number;\n}\n\nconst IS_ENTITY_ASSOCIATION_FLAG = '\"isEntityAssociation\":true';\n\n/**\n * TODO: investigate using chroma / rag for long term memory\n * Smart memory manager that combines active memory window with long-term storage\n * Provides context-aware memory management with automatic pruning and searchable history\n */\nexport class SmartMemoryManager {\n private memoryWindow: MemoryWindow;\n private _contentStorage: ContentStorage;\n private tokenCounter: TokenCounter;\n private config: Required<SmartMemoryConfig>;\n private logger: Logger;\n\n private static readonly DEFAULT_CONFIG: Required<SmartMemoryConfig> = {\n maxTokens: 8000,\n reserveTokens: 1000,\n modelName: 'gpt-4o',\n storageLimit: 1000,\n };\n\n constructor(config: SmartMemoryConfig = {}) {\n this.config = { ...SmartMemoryManager.DEFAULT_CONFIG, ...config };\n this.logger = new Logger({ module: 'SmartMemoryManager' });\n\n this.tokenCounter = new TokenCounter(this.config.modelName);\n this._contentStorage = new ContentStorage(this.config.storageLimit);\n this.memoryWindow = new MemoryWindow(\n this.config.maxTokens,\n this.config.reserveTokens,\n this.tokenCounter\n );\n }\n\n /**\n * Get the content storage instance for file/content reference operations\n * @returns ContentStorage instance\n */\n get contentStorage(): ContentStorage {\n return this._contentStorage;\n }\n\n /**\n * Add a message to the active memory window\n * Automatically handles pruning and storage of displaced messages\n * @param message - Message to add\n */\n addMessage(message: BaseMessage): void {\n const result = this.memoryWindow.addMessage(message);\n\n if (result.prunedMessages.length > 0) {\n this._contentStorage.storeMessages(result.prunedMessages);\n }\n }\n\n /**\n * Get all active messages from the memory window\n * @returns Array of active messages in chronological order\n */\n getMessages(): BaseMessage[] {\n return this.memoryWindow.getMessages();\n }\n\n /**\n * Clear active memory window\n * @param clearStorage - Whether to also clear the content storage (default: false)\n */\n clear(clearStorage: boolean = false): void {\n this.memoryWindow.clear();\n\n if (clearStorage) {\n this._contentStorage.clear();\n }\n }\n\n /**\n * Set the system prompt for the memory window\n * @param systemPrompt - System prompt text\n */\n setSystemPrompt(systemPrompt: string): void {\n this.memoryWindow.setSystemPrompt(systemPrompt);\n }\n\n /**\n * Get the current system prompt\n * @returns Current system prompt text\n */\n getSystemPrompt(): string {\n return this.memoryWindow.getSystemPrompt();\n }\n\n /**\n * Search through stored message history\n * @param query - Search term or pattern\n * @param options - Search configuration\n * @returns Array of matching messages from history\n */\n searchHistory(query: string, options: SearchOptions = {}): BaseMessage[] {\n return this._contentStorage.searchMessages(query, options);\n }\n\n /**\n * Get recent messages from storage history\n * @param count - Number of recent messages to retrieve\n * @returns Array of recent messages from storage\n */\n getRecentHistory(count: number): BaseMessage[] {\n return this._contentStorage.getRecentMessages(count);\n }\n\n /**\n * Check if a message can be added without exceeding limits\n * @param message - Message to test\n * @returns True if message can be added\n */\n canAddMessage(message: BaseMessage): boolean {\n return this.memoryWindow.canAddMessage(message);\n }\n\n /**\n * Get statistics about the active memory window\n * @returns Memory usage statistics\n */\n getMemoryStats(): MemoryStats {\n const windowStats = this.memoryWindow.getStats();\n\n return {\n totalActiveMessages: windowStats.totalMessages,\n currentTokenCount: windowStats.currentTokens,\n maxTokens: windowStats.maxTokens,\n remainingCapacity: windowStats.remainingCapacity,\n systemPromptTokens: windowStats.systemPromptTokens,\n usagePercentage: windowStats.usagePercentage,\n };\n }\n\n /**\n * Get statistics about the content storage\n * @returns Storage usage statistics\n */\n getStorageStats(): ReturnType<ContentStorage['getStorageStats']> {\n return this._contentStorage.getStorageStats();\n }\n\n /**\n * Get combined statistics for both active memory and storage\n * @returns Combined memory and storage statistics\n */\n getOverallStats(): {\n activeMemory: MemoryStats;\n storage: ReturnType<ContentStorage['getStorageStats']>;\n totalMessagesManaged: number;\n activeMemoryUtilization: number;\n storageUtilization: number;\n } {\n const memoryStats = this.getMemoryStats();\n const storageStats = this.getStorageStats();\n\n return {\n activeMemory: memoryStats,\n storage: storageStats,\n totalMessagesManaged:\n memoryStats.totalActiveMessages + storageStats.totalMessages,\n activeMemoryUtilization: memoryStats.usagePercentage,\n storageUtilization: storageStats.usagePercentage,\n };\n }\n\n /**\n * Update the configuration and apply changes\n * @param newConfig - New configuration options\n */\n updateConfig(newConfig: Partial<SmartMemoryConfig>): void {\n this.config = { ...this.config, ...newConfig };\n\n if (\n newConfig.maxTokens !== undefined ||\n newConfig.reserveTokens !== undefined\n ) {\n this.memoryWindow.updateLimits(\n this.config.maxTokens,\n this.config.reserveTokens\n );\n }\n\n if (newConfig.storageLimit !== undefined) {\n this._contentStorage.updateStorageLimit(this.config.storageLimit);\n }\n }\n\n /**\n * Get current configuration\n * @returns Current configuration settings\n */\n getConfig(): Required<SmartMemoryConfig> {\n return { ...this.config };\n }\n\n /**\n * Get messages from storage within a time range\n * @param startTime - Start of time range\n * @param endTime - End of time range\n * @returns Messages within the specified time range\n */\n getHistoryFromTimeRange(startTime: Date, endTime: Date): BaseMessage[] {\n return this._contentStorage.getMessagesFromTimeRange(startTime, endTime);\n }\n\n /**\n * Get messages from storage by message type\n * @param messageType - Type of messages to retrieve ('human', 'ai', 'system', etc.)\n * @param limit - Maximum number of messages to return\n * @returns Messages of the specified type\n */\n getHistoryByType(messageType: string, limit?: number): BaseMessage[] {\n return this._contentStorage.getMessagesByType(messageType, limit);\n }\n\n /**\n * Get recent messages from storage within the last N minutes\n * @param minutes - Number of minutes to look back\n * @returns Messages from the last N minutes\n */\n getRecentHistoryByTime(minutes: number): BaseMessage[] {\n return this._contentStorage.getRecentMessagesByTime(minutes);\n }\n\n /**\n * Export the current state for persistence or analysis\n * @returns Serializable representation of memory state\n */\n exportState(): {\n config: Required<SmartMemoryConfig>;\n activeMessages: Array<{ content: unknown; type: string }>;\n systemPrompt: string;\n memoryStats: MemoryStats;\n storageStats: ReturnType<ContentStorage['getStorageStats']>;\n storedMessages: ReturnType<ContentStorage['exportMessages']>;\n } {\n return {\n config: this.config,\n activeMessages: this.memoryWindow.getMessages().map((msg) => ({\n content: msg.content,\n type: msg._getType(),\n })),\n systemPrompt: this.memoryWindow.getSystemPrompt(),\n memoryStats: this.getMemoryStats(),\n storageStats: this.getStorageStats(),\n storedMessages: this._contentStorage.exportMessages(),\n };\n }\n\n /**\n * Get a summary of conversation context for external use\n * Useful for providing context to other systems or for logging\n * @param includeStoredContext - Whether to include recent stored messages\n * @returns Context summary object\n */\n getContextSummary(includeStoredContext: boolean = false): {\n activeMessageCount: number;\n systemPrompt: string;\n recentMessages: BaseMessage[];\n memoryUtilization: number;\n hasStoredHistory: boolean;\n recentStoredMessages?: BaseMessage[];\n storageStats?: ReturnType<ContentStorage['getStorageStats']>;\n } {\n const activeMessages = this.getMessages();\n const summary = {\n activeMessageCount: activeMessages.length,\n systemPrompt: this.getSystemPrompt(),\n recentMessages: activeMessages.slice(-5),\n memoryUtilization: this.getMemoryStats().usagePercentage,\n hasStoredHistory: this.getStorageStats().totalMessages > 0,\n };\n\n if (includeStoredContext) {\n return {\n ...summary,\n recentStoredMessages: this.getRecentHistory(10),\n storageStats: this.getStorageStats(),\n };\n }\n\n return summary;\n }\n\n /**\n * Perform maintenance operations\n * Optimizes storage and cleans up resources\n */\n performMaintenance(): void {}\n\n /**\n * Store an entity association for later resolution\n * @param entityId - The blockchain entity ID\n * @param entityName - User-provided or derived friendly name\n * @param entityType - Type of entity (token, account, topic, etc.)\n * @param transactionId - Optional transaction ID that created this entity\n */\n storeEntityAssociation(\n entityId: string,\n entityName: string,\n entityType: string,\n transactionId?: string,\n sessionId?: string\n ): void {\n try {\n if (\n !entityId ||\n typeof entityId !== 'string' ||\n entityId.trim().length === 0\n ) {\n return;\n }\n\n if (\n !entityName ||\n typeof entityName !== 'string' ||\n entityName.trim().length === 0\n ) {\n return;\n }\n\n if (\n !entityType ||\n typeof entityType !== 'string' ||\n entityType.trim().length === 0\n ) {\n return;\n }\n\n const sanitizedEntityId = entityId.trim();\n const sanitizedEntityName = entityName.trim().substring(0, 100);\n const sanitizedEntityType = this.normalizeEntityType(entityType);\n\n let usageHint = '';\n if (sanitizedEntityType === 'tokenid') {\n usageHint = 'Use this as tokenId for HTS operations';\n } else if (sanitizedEntityType === 'topicid') {\n usageHint =\n 'Can be used for HCS operations, HRLs for minting with the format hcs://1/<topicId>, etc.';\n } else if (sanitizedEntityType === 'accountid') {\n usageHint = 'Can be used for account based operations';\n }\n\n const association: EntityAssociation & {\n isEntityAssociation: boolean;\n usage?: string;\n hrl?: string;\n } = {\n entityId: sanitizedEntityId,\n entityName: sanitizedEntityName,\n entityType: sanitizedEntityType,\n createdAt: new Date(),\n isEntityAssociation: true,\n ...(usageHint ? { usage: usageHint } : {}),\n ...(sanitizedEntityType === 'topicId'\n ? { hrl: `hcs://1/${sanitizedEntityId}` }\n : {}),\n ...(transactionId !== undefined &&\n transactionId !== null &&\n transactionId.trim() !== ''\n ? { transactionId: transactionId.trim() }\n : {}),\n ...(sessionId && sessionId.trim() !== '' ? { sessionId: sessionId.trim() } : {}),\n };\n\n const content = JSON.stringify(association);\n type LangChainLikeMessage = {\n _getType: () => string;\n content: unknown;\n id: string;\n name?: string;\n additional_kwargs?: Record<string, unknown>;\n };\n\n const entityMessage: LangChainLikeMessage = {\n _getType: () => 'system',\n content: content,\n id: `entity_${sanitizedEntityId}_${Date.now()}`,\n name: 'entity_association',\n additional_kwargs: {\n entityId: sanitizedEntityId,\n entityName: sanitizedEntityName,\n entityType: sanitizedEntityType,\n isEntityAssociation: true,\n ...(sessionId && sessionId.trim() !== '' ? { sessionId: sessionId.trim() } : {}),\n },\n };\n\n try {\n this.memoryWindow.addMessage(new SystemMessage(content));\n } catch {}\n\n this._contentStorage.storeMessages([entityMessage as BaseMessage]);\n } catch (error) {\n this.logger.error('Failed to store entity association', {\n entityId,\n entityName,\n entityType,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n /**\n * Normalize various type aliases to canonical EntityFormat strings using a registry.\n */\n private normalizeEntityType(input: string): string {\n const raw = (input || '').trim();\n if (raw.length === 0) {\n return '';\n }\n\n const key = raw.replace(/[^a-z]/gi, '').toLowerCase();\n\n const REGISTRY: Record<string, string> = {\n topic: 'topicId',\n topicid: 'topicId',\n token: 'tokenId',\n tokenid: 'tokenId',\n account: 'accountId',\n accountid: 'accountId',\n contract: 'contractId',\n contractid: 'contractId',\n file: 'fileId',\n fileid: 'fileId',\n schedule: 'scheduleId',\n scheduleid: 'scheduleId',\n };\n\n if (Object.prototype.hasOwnProperty.call(REGISTRY, key)) {\n return REGISTRY[key];\n }\n\n if (/^[a-z]+Id$/.test(raw)) {\n return raw;\n }\n\n return raw;\n }\n\n /**\n * Resolve entity references from natural language queries\n * @param query - Search query (entity name or natural language reference)\n * @param options - Resolution options for filtering and fuzzy matching\n * @returns Array of matching entity associations\n */\n resolveEntityReference(\n query: string,\n options: EntityResolutionOptions = {}\n ): EntityAssociation[] {\n try {\n if (!query || typeof query !== 'string') {\n return [];\n }\n\n const sanitizedQuery = query.trim();\n if (sanitizedQuery.length === 0) {\n return [];\n }\n\n if (sanitizedQuery.length > 200) {\n }\n\n const { entityType, limit = 10, fuzzyMatch = true } = options;\n\n const safeLimit = Math.max(1, Math.min(limit || 10, 100));\n\n const isEntityIdQuery = /^0\\.0\\.\\d+$/.test(sanitizedQuery);\n\n const searchResults = this._contentStorage.searchMessages(\n sanitizedQuery.substring(0, 200),\n {\n caseSensitive: false,\n limit: safeLimit * 2,\n }\n );\n\n const associations: EntityAssociation[] = [];\n\n for (const message of searchResults) {\n try {\n const content = message.content as string;\n if (\n content.includes(IS_ENTITY_ASSOCIATION_FLAG) ||\n content.includes('entityId')\n ) {\n const parsed = JSON.parse(content);\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (entityType && parsed.entityType !== entityType) {\n continue;\n }\n\n if (isEntityIdQuery) {\n if (parsed.entityId !== sanitizedQuery) {\n continue;\n }\n }\n\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch {\n continue;\n }\n }\n\n if (fuzzyMatch && associations.length === 0 && !isEntityIdQuery) {\n const fuzzyQueries = [\n query.toLowerCase(),\n `token`,\n `account`,\n entityType || '',\n ].filter(Boolean);\n\n for (const fuzzyQuery of fuzzyQueries) {\n if (fuzzyQuery === query.toLowerCase()) continue;\n\n const fuzzyResults = this._contentStorage.searchMessages(fuzzyQuery, {\n caseSensitive: false,\n limit: limit,\n });\n\n for (const message of fuzzyResults) {\n try {\n const content = message.content as string;\n if (content.includes(IS_ENTITY_ASSOCIATION_FLAG)) {\n const parsed = JSON.parse(content);\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (entityType && parsed.entityType !== entityType) {\n continue;\n }\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch {\n continue;\n }\n }\n }\n }\n\n const uniqueAssociations = associations\n .filter(\n (assoc, index, arr) =>\n arr.findIndex((a) => a.entityId === assoc.entityId) === index\n )\n .sort(\n (a, b) =>\n new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n );\n\n const results = uniqueAssociations.slice(0, safeLimit);\n\n return results;\n } catch (error) {\n this.logger.error('Failed to resolve entity reference', {\n query,\n options,\n error: error instanceof Error ? error.message : String(error),\n });\n return [];\n }\n }\n\n /**\n * Get all entity associations, optionally filtered by type\n * @param entityType - Optional filter by entity type\n * @returns Array of entity associations\n */\n getEntityAssociations(entityType?: string): EntityAssociation[] {\n try {\n const rawFilter = entityType ? entityType.trim() : undefined;\n const filterCanonical = rawFilter ? this.normalizeEntityType(rawFilter) : undefined;\n\n if (entityType && (!rawFilter || rawFilter.length === 0)) {\n return [];\n }\n\n const SEARCH_ANY_ENTITY = 'entityId';\n const searchQuery = filterCanonical || SEARCH_ANY_ENTITY;\n const searchResults = this._contentStorage.searchMessages(searchQuery, {\n caseSensitive: false,\n limit: 100,\n });\n\n const associations: EntityAssociation[] = [];\n\n for (const message of searchResults) {\n try {\n const content = message.content as string;\n if (content.includes(IS_ENTITY_ASSOCIATION_FLAG)) {\n const parsed = JSON.parse(content);\n\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (filterCanonical && parsed.entityType !== filterCanonical) {\n continue;\n }\n\n if (parsed.createdAt && typeof parsed.createdAt === 'string') {\n parsed.createdAt = new Date(parsed.createdAt);\n }\n\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch (parseError) {\n this.logger.warn('Failed to parse entity association from message', {\n messageContent:\n typeof message.content === 'string'\n ? message.content.substring(0, 100)\n : 'non-string',\n error:\n parseError instanceof Error\n ? parseError.message\n : String(parseError),\n });\n continue;\n }\n }\n\n const mergedById = new Map<string, EntityAssociation>();\n const getTime = (d: Date | string): number =>\n d instanceof Date ? d.getTime() : new Date(d).getTime();\n\n for (const assoc of associations) {\n const existing = mergedById.get(assoc.entityId);\n if (!existing) {\n mergedById.set(assoc.entityId, assoc);\n continue;\n }\n\n const existingTime = getTime(existing.createdAt);\n const currentTime = getTime(assoc.createdAt);\n\n const preferCurrent =\n currentTime > existingTime ||\n (!!assoc.transactionId && !existing.transactionId);\n\n if (preferCurrent) {\n mergedById.set(assoc.entityId, {\n ...existing,\n ...assoc,\n });\n }\n }\n\n const results = Array.from(mergedById.values()).sort((a, b) =>\n getTime(b.createdAt) - getTime(a.createdAt)\n );\n\n return results;\n } catch (error) {\n this.logger.error('Failed to get entity associations', {\n entityType,\n error: error instanceof Error ? error.message : String(error),\n });\n return [];\n }\n }\n\n /**\n * Clean up resources and dispose of components\n */\n dispose(): void {\n this.memoryWindow.dispose();\n this._contentStorage.dispose();\n this.tokenCounter.dispose();\n }\n}\n","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { CallbackManagerForToolRun } from '@langchain/core/callbacks/manager';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport { FormGenerator } from '../forms/form-generator';\nimport type { FormMessage } from '../forms/types';\nimport { isFormValidatable } from '@hashgraphonline/standards-agent-kit';\n\nexport interface FormValidationConfig {\n requireAllFields?: boolean;\n skipFields?: string[];\n customValidation?: (input: unknown) => boolean;\n}\n\n/**\n * Generic wrapper for StructuredTools that intercepts execution to check for missing required fields\n * and generates forms when validation would benefit from user input.\n *\n * Tools can implement the FormValidatable interface to provide custom validation logic.\n * Otherwise, falls back to schema-based validation.\n */\nexport class FormValidatingToolWrapper<\n TSchema extends z.ZodObject<z.ZodRawShape, z.UnknownKeysParam, z.ZodTypeAny>\n> extends StructuredTool<TSchema> {\n private originalTool: StructuredTool<TSchema>;\n private formGenerator: FormGenerator;\n private validationConfig: FormValidationConfig;\n private logger: Logger;\n\n name: string;\n description: string;\n schema: TSchema;\n\n constructor(\n originalTool: StructuredTool<TSchema>,\n formGenerator: FormGenerator,\n config: FormValidationConfig = {}\n ) {\n super();\n this.originalTool = originalTool;\n this.formGenerator = formGenerator;\n this.validationConfig = config;\n this.logger = new Logger({ module: 'FormValidatingToolWrapper' });\n\n this.name = originalTool.name;\n this.description = originalTool.description;\n this.schema = originalTool.schema;\n \n this.logger.info(`🔧 FormValidatingToolWrapper created for tool: ${this.name}`, {\n originalToolName: originalTool.name,\n originalToolType: originalTool.constructor.name,\n wrapperType: this.constructor.name\n });\n }\n\n /**\n * Validate the input against the schema\n */\n private validateInput(input: Record<string, unknown>): { isValid: boolean; errors?: string[] } {\n try {\n this.schema.parse(input);\n return { isValid: true };\n } catch (error) {\n if (error instanceof z.ZodError) {\n const errors = error.errors\n .filter(err => {\n const fieldName = err.path[0] as string;\n return !this.validationConfig.skipFields?.includes(fieldName);\n })\n .map(err => `${err.path.join('.')}: ${err.message}`);\n return { isValid: false, errors };\n }\n return { isValid: false, errors: ['Validation failed'] };\n }\n }\n\n /**\n * Gets the shape keys from the schema if it's a ZodObject\n */\n private getSchemaShape(): string[] {\n if (this.isZodObject(this.schema)) {\n return Object.keys(this.schema.shape);\n }\n return [];\n }\n\n /**\n * Executes the wrapped tool's original implementation directly, bypassing wrapper logic.\n */\n public async executeOriginal(\n input: Record<string, unknown>,\n runManager?: CallbackManagerForToolRun\n ): Promise<string> {\n type CallableMethod = (\n args: Record<string, unknown>,\n runManager?: CallbackManagerForToolRun\n ) => Promise<string>;\n \n const tool = this.originalTool as unknown as Record<string, unknown>;\n \n if ('_call' in tool && typeof tool._call === 'function') {\n return (tool._call as CallableMethod)(input, runManager);\n }\n if ('call' in tool && typeof tool.call === 'function') {\n return (tool.call as CallableMethod)(input, runManager);\n }\n throw new Error('Original tool has no callable implementation');\n }\n\n /**\n * Provides access to the wrapped tool instance for executors that want to bypass the wrapper.\n */\n public getOriginalTool(): StructuredTool<TSchema> {\n return this.originalTool;\n }\n\n /**\n * Checks if tool implements FormValidatable method\n */\n private hasFormValidatableMethod<T>(\n tool: unknown,\n methodName: string\n ): tool is Record<string, T> {\n return (\n tool !== null &&\n typeof tool === 'object' &&\n methodName in tool &&\n typeof (tool as Record<string, unknown>)[methodName] === 'function'\n );\n }\n\n /**\n * Expose FormValidatable methods by delegating to the underlying tool when available.\n */\n public getFormSchema(): z.ZodSchema {\n if (this.hasFormValidatableMethod<() => z.ZodSchema>(this.originalTool, 'getFormSchema')) {\n return this.originalTool.getFormSchema();\n }\n return this.schema as z.ZodSchema;\n }\n\n public getEssentialFields(): string[] {\n if (this.hasFormValidatableMethod<() => string[]>(this.originalTool, 'getEssentialFields')) {\n return this.originalTool.getEssentialFields();\n }\n return [];\n }\n\n public isFieldEmpty(fieldName: string, value: unknown): boolean {\n if (this.hasFormValidatableMethod<(n: string, v: unknown) => boolean>(this.originalTool, 'isFieldEmpty')) {\n return this.originalTool.isFieldEmpty(fieldName, value);\n }\n if (value === undefined || value === null || value === '') {\n return true;\n }\n if (Array.isArray(value) && value.length === 0) {\n return true;\n }\n return false;\n }\n\n /**\n * Calculates which fields are missing from the input\n */\n private calculateMissingFields(\n input: Record<string, unknown>,\n isCustom: boolean\n ): Set<string> {\n const missingFields = new Set<string>();\n \n if (!isCustom) {\n return missingFields;\n }\n\n const essentialFields = this.getEssentialFields();\n for (const fieldName of essentialFields) {\n const value = input[fieldName];\n if (this.isFieldEmpty(fieldName, value)) {\n missingFields.add(fieldName);\n }\n }\n \n return missingFields;\n }\n\n /**\n * Creates a form message with optional JSON schema\n */\n private async createFormMessage(\n schema: z.ZodSchema,\n input: Record<string, unknown>,\n missingFields: Set<string>\n ): Promise<FormMessage> {\n let formMessage = await this.formGenerator.generateFormFromSchema(\n schema,\n input,\n {\n toolName: this.name,\n toolDescription: this.description\n },\n missingFields\n );\n\n if (this.isZodObject(schema)) {\n try {\n const { jsonSchema, uiSchema } = this.formGenerator.generateJsonSchemaForm(\n schema,\n input,\n missingFields\n );\n formMessage = {\n ...formMessage,\n jsonSchema,\n uiSchema\n };\n } catch (error) {\n this.logger.warn('Failed to generate JSON Schema for RJSF:', error);\n }\n }\n\n formMessage.partialInput = input;\n return formMessage;\n }\n\n /**\n * Type guard to check if a schema is a ZodObject\n */\n private isZodObject(schema: z.ZodSchema): schema is z.ZodObject<z.ZodRawShape> {\n const def = (schema as z.ZodType)._def as { typeName?: string };\n return !!(def && def.typeName === 'ZodObject');\n }\n\n /**\n * Check if we should generate a form for this tool invocation\n */\n private shouldGenerateForm(input: Record<string, unknown>): boolean {\n this.logger.info(`shouldGenerateForm called for ${this.name}/${this.originalTool.name}`, {\n input,\n hasCustomValidation: !!this.validationConfig.customValidation\n });\n\n if (this.validationConfig.customValidation) {\n const result = !this.validationConfig.customValidation(input);\n this.logger.info(`Custom validation result: ${result}`);\n return result;\n }\n\n if (isFormValidatable(this.originalTool)) {\n this.logger.info(`Tool ${this.originalTool.name} implements FormValidatable, using custom logic`);\n return this.originalTool.shouldGenerateForm(input);\n }\n\n this.logger.info(`Tool ${this.originalTool.name} using schema validation only`);\n const validation = this.validateInput(input);\n this.logger.info(`Schema validation for ${this.originalTool.name}:`, {\n isValid: validation.isValid,\n errors: validation.errors\n });\n return !validation.isValid;\n }\n\n /**\n * Checks if input has bypass flags that skip form generation\n */\n private hasFormBypassFlags(input: Record<string, unknown>): boolean {\n return (\n (input.__fromForm === true) ||\n (input.renderForm === false)\n );\n }\n\n /**\n * Override _call to intercept tool execution\n */\n protected async _call(\n input: z.infer<TSchema>,\n runManager?: CallbackManagerForToolRun\n ): Promise<string> {\n this.logger.info(`🚨🚨🚨 FormValidatingToolWrapper._call INTERCEPTING ${this.name} 🚨🚨🚨`, {\n input,\n inputKeys: Object.keys(input as Record<string, unknown>),\n schemaShape: this.getSchemaShape(),\n stackTrace: new Error().stack?.split('\\n').slice(0, 5)\n });\n\n const inputRecord = input as unknown as Record<string, unknown>;\n \n if (this.hasFormBypassFlags(inputRecord)) {\n this.logger.info('Bypassing form generation and executing original tool due to submission flags');\n return this.executeOriginal(inputRecord, runManager);\n }\n\n const shouldGenerate = this.shouldGenerateForm(input as Record<string, unknown>);\n this.logger.info(`FormValidatingToolWrapper decision for ${this.name}:`, {\n shouldGenerateForm: shouldGenerate,\n toolName: this.name,\n originalToolName: this.originalTool.name\n });\n\n if (shouldGenerate) {\n this.logger.info(`Generating form for incomplete input in ${this.name}`);\n\n try {\n const isCustom = isFormValidatable(this.originalTool);\n const schemaToUse = isCustom ? this.getFormSchema() : this.schema;\n const missingFields = this.calculateMissingFields(\n input as Record<string, unknown>,\n isCustom\n );\n\n const schemaFields = this.isZodObject(schemaToUse) \n ? Object.keys(schemaToUse.shape)\n : [];\n \n this.logger.info(`Using ${isCustom ? 'CUSTOM' : 'DEFAULT'} schema for form generation`, {\n toolName: this.originalTool.name,\n schemaType: schemaToUse.constructor?.name,\n schemaFields,\n isCustomSchema: isCustom\n });\n\n const formMessage = await this.createFormMessage(\n schemaToUse,\n input as Record<string, unknown>,\n missingFields\n );\n\n const result = {\n requiresForm: true,\n formMessage,\n message: `Please complete the form to provide the required information for ${this.name}.`\n };\n\n this.logger.info(`FormValidatingToolWrapper returning form result for ${this.name}`);\n return JSON.stringify(result);\n } catch (error) {\n this.logger.error('Failed to generate form:', error);\n }\n }\n\n this.logger.info(`FormValidatingToolWrapper passing through to original tool ${this.name}`);\n return this.executeOriginal(input as Record<string, unknown>, runManager);\n }\n\n}\n\n/**\n * Wrap a tool with form validation capabilities\n */\nexport function wrapToolWithFormValidation<TSchema extends z.ZodObject<z.ZodRawShape, z.UnknownKeysParam, z.ZodTypeAny>>(\n tool: StructuredTool<TSchema>,\n formGenerator: FormGenerator,\n config: FormValidationConfig = {}\n): FormValidatingToolWrapper<TSchema> {\n return new FormValidatingToolWrapper(tool, formGenerator, config);\n}","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport {\n FormValidatingToolWrapper,\n wrapToolWithFormValidation,\n} from '../langchain/form-validating-tool-wrapper';\nimport { FormGenerator } from '../forms/form-generator';\nimport {\n fieldGuidanceRegistry,\n} from '../forms/field-guidance-registry';\nimport type {\n ToolFieldConfiguration as FG_ToolFieldConfiguration,\n FieldGuidanceProvider as FG_FieldGuidanceProvider,\n} from '../forms/field-guidance-registry';\nimport { isFormValidatable } from '@hashgraphonline/standards-agent-kit';\n\n/**\n * Tool capabilities configuration for registry entries\n */\nexport interface ToolCapabilities {\n supportsFormValidation: boolean;\n requiresWrapper: boolean;\n priority: 'low' | 'medium' | 'high' | 'critical';\n category: 'core' | 'extension' | 'mcp';\n}\n\n/**\n * Entity resolution format preferences for tools\n */\nexport interface EntityResolutionPreferences {\n inscription?: 'hrl' | 'topicId' | 'metadata' | 'any';\n token?: 'tokenId' | 'address' | 'symbol' | 'any';\n nft?: 'serialNumber' | 'metadata' | 'hrl' | 'any';\n account?: 'accountId' | 'alias' | 'evmAddress' | 'any';\n}\n\n/**\n * Tool metadata for comprehensive tool information\n */\nexport interface ToolMetadata {\n name: string;\n version: string;\n category: ToolCapabilities['category'];\n description: string;\n capabilities: ToolCapabilities;\n dependencies: string[];\n schema: unknown;\n entityResolutionPreferences?: EntityResolutionPreferences;\n fieldGuidance?: FG_ToolFieldConfiguration;\n fieldGuidanceProvider?: FG_FieldGuidanceProvider;\n}\n\n/**\n * Registry entry containing tool instance and metadata\n */\nexport interface ToolRegistryEntry {\n tool: StructuredTool;\n metadata: ToolMetadata;\n wrapper?: FormValidatingToolWrapper<z.ZodObject<z.ZodRawShape>> | undefined;\n originalTool: StructuredTool;\n options?: {\n priority?: ToolCapabilities['priority'];\n capability?: string;\n enabled?: boolean;\n namespace?: string;\n };\n}\n\n/**\n * Options for tool registration\n */\nexport interface ToolRegistrationOptions {\n forceWrapper?: boolean;\n skipWrapper?: boolean;\n wrapperConfig?: {\n requireAllFields?: boolean;\n skipFields?: string[];\n };\n metadata?: Partial<ToolMetadata>;\n}\n\n/**\n * Query interface for finding tools\n */\nexport interface ToolQuery {\n name?: string;\n category?: ToolMetadata['category'];\n capabilities?: Partial<ToolCapabilities>;\n}\n\n/**\n * Centralized tool registry for managing tool lifecycle\n */\nexport class ToolRegistry {\n private tools = new Map<string, ToolRegistryEntry>();\n private formGenerator: FormGenerator;\n private logger: Logger;\n\n constructor(logger?: Logger) {\n this.formGenerator = new FormGenerator();\n this.logger = logger || new Logger({ module: 'ToolRegistry' });\n }\n\n /**\n * Register a tool with the registry\n */\n registerTool(\n tool: StructuredTool,\n options: ToolRegistrationOptions = {}\n ): void {\n const capabilities = this.analyzeToolCapabilities(tool);\n const metadata: ToolMetadata = {\n name: tool.name,\n version: '1.0.0',\n category: options.metadata?.category || 'core',\n description: tool.description,\n capabilities,\n dependencies: [],\n schema: tool.schema,\n ...options.metadata,\n };\n\n try {\n if (!metadata.entityResolutionPreferences) {\n const schemaRecord = tool.schema as unknown as Record<string, unknown>;\n const rawPrefs =\n schemaRecord &&\n typeof schemaRecord === 'object' &&\n (schemaRecord as Record<string, unknown>)[\n '_entityResolutionPreferences'\n ];\n if (rawPrefs && typeof rawPrefs === 'object') {\n metadata.entityResolutionPreferences = rawPrefs as unknown as EntityResolutionPreferences;\n }\n }\n } catch {\n }\n\n try {\n const schemaRecord = tool.schema as unknown as Record<string, unknown>;\n const schemaDef = (schemaRecord && (schemaRecord as Record<string, unknown>)._def) as\n | { typeName?: string; shape?: unknown }\n | undefined;\n if (schemaDef?.typeName === 'ZodObject') {\n const shape: Record<string, unknown> =\n typeof (schemaDef as { shape?: () => Record<string, unknown> }).shape === 'function'\n ? ((schemaDef as { shape: () => Record<string, unknown> }).shape?.() || {})\n : ((schemaDef as { shape?: Record<string, unknown> }).shape || {});\n\n const metadataField = shape['metadata'] as\n | { _def?: { typeName?: string; type?: { _def?: { typeName?: string } } } }\n | undefined;\n const isStringArray =\n !!metadataField &&\n metadataField._def?.typeName === 'ZodArray' &&\n metadataField._def?.type?._def?.typeName === 'ZodString';\n\n if (isStringArray && typeof tool.description === 'string') {\n if (!metadata.entityResolutionPreferences) {\n metadata.entityResolutionPreferences = {\n inscription: 'hrl',\n } as EntityResolutionPreferences;\n }\n const note =\n ' NOTE: When referencing inscriptions or media, provide canonical Hashlink Resource Locators (e.g., hcs://<standard>/<topicId>) rather than external URLs or embedded JSON.';\n if (!tool.description.includes('Hashlink Resource Locators')) {\n (tool as unknown as { description: string }).description = `${tool.description}${note}`;\n }\n }\n }\n } catch {}\n\n let finalTool: StructuredTool = tool;\n let wrapper:\n | FormValidatingToolWrapper<z.ZodObject<z.ZodRawShape>>\n | undefined;\n\n if (this.shouldWrapTool(tool, capabilities, options)) {\n wrapper = wrapToolWithFormValidation(\n tool as StructuredTool<z.ZodObject<z.ZodRawShape>>,\n this.formGenerator,\n {\n requireAllFields: false,\n skipFields: ['metaOptions'],\n ...options.wrapperConfig,\n }\n ) as FormValidatingToolWrapper<z.ZodObject<z.ZodRawShape>>;\n finalTool = wrapper as StructuredTool;\n }\n\n try {\n if (metadata.entityResolutionPreferences) {\n (finalTool as unknown as Record<string, unknown>)[\n 'entityResolutionPreferences'\n ] = metadata.entityResolutionPreferences;\n }\n } catch {\n }\n\n const entry: ToolRegistryEntry = {\n tool: finalTool,\n metadata,\n wrapper,\n originalTool: tool,\n options: {\n priority: capabilities.priority,\n capability: 'basic', // Default capability\n enabled: true, // All tools are enabled by default\n namespace: metadata.category,\n },\n };\n\n this.tools.set(tool.name, entry);\n\n try {\n const metaFG = metadata.fieldGuidance as FG_ToolFieldConfiguration | undefined;\n if (metaFG) {\n fieldGuidanceRegistry.registerToolConfiguration(metaFG);\n }\n const provider = metadata.fieldGuidanceProvider as FG_FieldGuidanceProvider | undefined;\n if (provider) {\n const pattern = metaFG?.toolPattern ?? tool.name;\n fieldGuidanceRegistry.registerToolProvider(pattern, provider, {\n id: `${tool.name}:field-guidance-provider`,\n priority: 0,\n });\n }\n } catch {}\n }\n\n /**\n * Get a tool by name\n */\n getTool(name: string): ToolRegistryEntry | null {\n return this.tools.get(name) || null;\n }\n\n /**\n * Get tools by capability\n */\n getToolsByCapability(\n capability: keyof ToolCapabilities,\n value?: unknown\n ): ToolRegistryEntry[] {\n const results: ToolRegistryEntry[] = [];\n\n for (const entry of this.tools.values()) {\n if (value !== undefined) {\n if (entry.metadata.capabilities[capability] === value) {\n results.push(entry);\n }\n } else if (entry.metadata.capabilities[capability]) {\n results.push(entry);\n }\n }\n\n return results;\n }\n\n /**\n * Get tools by query\n */\n getToolsByQuery(query: ToolQuery): ToolRegistryEntry[] {\n const results: ToolRegistryEntry[] = [];\n\n for (const entry of this.tools.values()) {\n let matches = true;\n\n if (query.name && entry.metadata.name !== query.name) {\n matches = false;\n }\n\n if (query.category && entry.metadata.category !== query.category) {\n matches = false;\n }\n\n if (query.capabilities) {\n for (const [key, value] of Object.entries(query.capabilities)) {\n if (\n entry.metadata.capabilities[key as keyof ToolCapabilities] !== value\n ) {\n matches = false;\n break;\n }\n }\n }\n\n if (matches) {\n results.push(entry);\n }\n }\n\n return results;\n }\n\n /**\n * Get all registered tools\n */\n getAllTools(): StructuredTool[] {\n return Array.from(this.tools.values()).map((entry) => entry.tool);\n }\n\n /**\n * Get all registry entries\n */\n getAllRegistryEntries(): ToolRegistryEntry[] {\n return Array.from(this.tools.values());\n }\n\n /**\n * Get all tool names\n */\n getToolNames(): string[] {\n return Array.from(this.tools.keys());\n }\n\n /**\n * Get tools by priority\n */\n getToolsByPriority(priority: ToolCapabilities['priority']): ToolRegistryEntry[] {\n return this.getToolsByCapability('priority', priority);\n }\n\n /**\n * Get enabled tools (all tools are considered enabled by default)\n */\n getEnabledTools(): ToolRegistryEntry[] {\n return this.getAllRegistryEntries();\n }\n\n /**\n * Get tools by namespace/category\n */\n getToolsByNamespace(namespace?: string): ToolRegistryEntry[] {\n if (!namespace) {\n return this.getAllRegistryEntries();\n }\n return this.getToolsByQuery({ category: namespace as ToolMetadata['category'] });\n }\n\n /**\n * Check if registry has capability\n */\n hasCapability(capability: keyof ToolCapabilities): boolean {\n for (const entry of this.tools.values()) {\n if (entry.metadata.capabilities[capability]) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Update tool options (metadata)\n */\n updateToolOptions(name: string, options: Partial<ToolMetadata>): boolean {\n const entry = this.tools.get(name);\n if (!entry) {\n return false;\n }\n\n entry.metadata = { ...entry.metadata, ...options };\n return true;\n }\n\n /**\n * Check if a tool is registered\n */\n hasTool(name: string): boolean {\n return this.tools.has(name);\n }\n\n /**\n * Unregister a tool\n */\n unregisterTool(name: string): boolean {\n return this.tools.delete(name);\n }\n\n /**\n * Clear all tools\n */\n clear(): void {\n this.tools.clear();\n }\n\n /**\n * Analyze tool capabilities\n */\n private analyzeToolCapabilities(tool: StructuredTool): ToolCapabilities {\n const implementsFormValidatable = isFormValidatable(tool);\n const hasRenderConfig = this.hasRenderConfig(tool);\n const isZodObjectLike = this.isZodObjectLike(tool.schema);\n\n const supportsFormValidation = implementsFormValidatable || hasRenderConfig;\n const requiresWrapper = supportsFormValidation && isZodObjectLike;\n\n let priority: ToolCapabilities['priority'] = 'medium';\n let category: ToolCapabilities['category'] = 'core';\n\n if (supportsFormValidation && requiresWrapper) {\n priority = 'critical';\n } else if (supportsFormValidation) {\n priority = 'high';\n } else if (\n tool.description?.toLowerCase().includes('query') ||\n tool.description?.toLowerCase().includes('search')\n ) {\n priority = 'low';\n }\n\n const toolAsAny = tool as unknown as Record<string, unknown>;\n if (tool.constructor.name.includes('MCP') || toolAsAny.isMCPTool) {\n category = 'mcp';\n } else if (\n toolAsAny.isExtension ||\n tool.constructor.name.includes('Extension')\n ) {\n category = 'extension';\n }\n\n return {\n supportsFormValidation,\n requiresWrapper,\n priority,\n category,\n };\n }\n\n /**\n * Check if tool has render configuration\n */\n private hasRenderConfig(tool: StructuredTool): boolean {\n const schema = tool.schema as Record<string, unknown>;\n return !!(schema && schema._renderConfig);\n }\n\n /**\n * Determine if tool should be wrapped\n */\n private shouldWrapTool(\n tool: StructuredTool,\n capabilities: ToolCapabilities,\n options: ToolRegistrationOptions\n ): boolean {\n if (options.skipWrapper) {\n return false;\n }\n\n if (options.forceWrapper) {\n return true;\n }\n\n return capabilities.requiresWrapper;\n }\n\n /**\n * Check if schema is ZodObject-like\n */\n private isZodObjectLike(schema: unknown): boolean {\n if (!schema || typeof schema !== 'object') {\n return false;\n }\n\n const schemaRecord = schema as Record<string, unknown>;\n const schemaDef = schemaRecord._def as Record<string, unknown> | undefined;\n\n return (\n schema instanceof z.ZodObject ||\n schemaDef?.typeName === 'ZodObject' ||\n ('shape' in schemaRecord && typeof schemaRecord.shape === 'object')\n );\n }\n\n /**\n * Get statistics about the registry\n */\n getStatistics(): {\n totalTools: number;\n wrappedTools: number;\n unwrappedTools: number;\n categoryCounts: Record<ToolCapabilities['category'], number>;\n priorityCounts: Record<ToolCapabilities['priority'], number>;\n } {\n const stats = {\n totalTools: this.tools.size,\n wrappedTools: 0,\n unwrappedTools: 0,\n categoryCounts: { core: 0, extension: 0, mcp: 0 } as Record<\n ToolCapabilities['category'],\n number\n >,\n priorityCounts: { low: 0, medium: 0, high: 0, critical: 0 } as Record<\n ToolCapabilities['priority'],\n number\n >,\n };\n\n for (const entry of this.tools.values()) {\n if (entry.wrapper) {\n stats.wrappedTools++;\n } else {\n stats.unwrappedTools++;\n }\n\n stats.categoryCounts[entry.metadata.category]++;\n stats.priorityCounts[entry.metadata.capabilities.priority]++;\n }\n\n return stats;\n }\n}\n","import { ZodError } from 'zod';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport { SmartMemoryManager } from '../memory/smart-memory-manager';\nimport { FormEngine, ToolExecutionResult } from '../forms/form-engine';\nimport type { FormMessage, FormSubmission } from '../forms/types';\nimport type { ToolRegistry, ToolRegistryEntry } from '../core/tool-registry';\n\n/**\n * Session context for tool execution\n */\nexport interface SessionContext {\n sessionId: string;\n userId?: string;\n timestamp: number;\n conversationId?: string;\n}\n\n/**\n * Context passed through execution pipeline\n */\nexport interface ExecutionContext {\n toolName: string;\n input: unknown;\n session: SessionContext;\n memory: SmartMemoryManager;\n traceId: string;\n toolEntry: ToolRegistryEntry;\n}\n\n/**\n * Result of tool execution with metadata\n */\nexport interface ExecutionResult extends ToolExecutionResult {\n traceId: string;\n executionTime: number;\n}\n\n/**\n * ExecutionPipeline handles tool execution coordination\n */\nexport class ExecutionPipeline {\n private logger: Logger;\n private toolRegistry: ToolRegistry;\n private formEngine: FormEngine;\n private memory: SmartMemoryManager;\n\n constructor(\n toolRegistry: ToolRegistry,\n formEngine: FormEngine,\n memory: SmartMemoryManager,\n logger?: Logger\n ) {\n this.toolRegistry = toolRegistry;\n this.formEngine = formEngine;\n this.memory = memory;\n this.logger = logger || new Logger({ module: 'ExecutionPipeline' });\n }\n\n /**\n * Execute a tool through the pipeline\n */\n async execute(\n toolName: string,\n input: unknown,\n sessionContext?: SessionContext\n ): Promise<ExecutionResult> {\n const traceId = `trace-${Date.now()}-${Math.random()\n .toString(36)\n .substr(2, 9)}`;\n const startTime = Date.now();\n\n const toolEntry = this.toolRegistry.getTool(toolName);\n if (!toolEntry) {\n throw new Error(`Tool not found in registry: ${toolName}`);\n }\n\n const context: ExecutionContext = {\n toolName,\n input,\n session: sessionContext || this.buildDefaultSession(),\n memory: this.memory,\n traceId,\n toolEntry,\n };\n\n try {\n const shouldGenerateForm = await this.checkFormGeneration(context);\n if (shouldGenerateForm.requiresForm && shouldGenerateForm.formMessage) {\n return {\n success: false,\n output: 'Form generation required',\n requiresForm: true,\n formMessage: shouldGenerateForm.formMessage,\n traceId,\n executionTime: Date.now() - startTime,\n };\n }\n\n const result = await this.executeToolDirect(context);\n\n return {\n success: true,\n output: result,\n traceId,\n executionTime: Date.now() - startTime,\n };\n } catch (error) {\n return this.handleExecutionError(\n error,\n context,\n traceId,\n Date.now() - startTime\n );\n }\n }\n\n /**\n * Execute tool with validation\n */\n async executeWithValidation(\n toolName: string,\n input: unknown,\n sessionContext?: SessionContext\n ): Promise<ExecutionResult> {\n return this.execute(toolName, input, sessionContext);\n }\n\n /**\n * Process form submission\n */\n async processFormSubmission(\n toolName: string,\n formId: string,\n parameters: Record<string, unknown>,\n sessionContext?: SessionContext\n ): Promise<ExecutionResult> {\n const traceId = `form-${Date.now()}-${Math.random()\n .toString(36)\n .substr(2, 9)}`;\n const startTime = Date.now();\n\n try {\n const formSubmission: FormSubmission = {\n formId,\n toolName,\n parameters,\n timestamp: Date.now(),\n };\n\n const processedInput = await this.formEngine.processSubmission(\n formSubmission\n );\n\n return this.execute(toolName, processedInput, sessionContext);\n } catch (error) {\n return {\n success: false,\n output: 'Form submission processing failed',\n error: error instanceof Error ? error.message : String(error),\n traceId,\n executionTime: Date.now() - startTime,\n };\n }\n }\n\n /**\n * Check if form generation is required\n */\n private async checkFormGeneration(context: ExecutionContext): Promise<{\n requiresForm: boolean;\n formMessage?: FormMessage;\n }> {\n const inputRecord = context.input as Record<string, unknown>;\n if (inputRecord?.__fromForm === true || inputRecord?.renderForm === false) {\n return { requiresForm: false };\n }\n\n if (\n !this.formEngine.shouldGenerateForm(context.toolEntry.tool, context.input)\n ) {\n return { requiresForm: false };\n }\n\n const formMessage = await this.formEngine.generateForm(\n context.toolName,\n context.toolEntry.tool,\n context.input\n );\n\n if (formMessage) {\n return { requiresForm: true, formMessage };\n }\n\n return { requiresForm: false };\n }\n\n /**\n * Execute tool directly\n */\n private async executeToolDirect(context: ExecutionContext): Promise<string> {\n const { toolEntry, input } = context;\n const parameters = (input as Record<string, unknown>) || {};\n const mergedArgs = { ...parameters, renderForm: false };\n\n if (toolEntry.wrapper) {\n return this.executeWrappedTool(toolEntry, mergedArgs);\n }\n\n return await toolEntry.tool.call(mergedArgs);\n }\n\n /**\n * Execute wrapped tool\n */\n private async executeWrappedTool(\n toolEntry: ToolRegistryEntry,\n mergedArgs: Record<string, unknown>\n ): Promise<string> {\n const wrapper = toolEntry.wrapper;\n if (!wrapper) {\n throw new Error('Tool wrapper not found');\n }\n\n const wrapperAsAny = wrapper as unknown as {\n executeOriginal?: (args: Record<string, unknown>) => Promise<string>;\n originalTool?: {\n call?: (args: Record<string, unknown>) => Promise<string>;\n };\n };\n\n if (wrapperAsAny.executeOriginal) {\n return await wrapperAsAny.executeOriginal(mergedArgs);\n }\n\n if (wrapperAsAny.originalTool?.call) {\n return await wrapperAsAny.originalTool.call(mergedArgs);\n }\n\n return await toolEntry.originalTool.call(mergedArgs);\n }\n\n /**\n * Handle execution error\n */\n private handleExecutionError(\n error: unknown,\n context: ExecutionContext,\n traceId: string,\n executionTime: number\n ): ExecutionResult {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (error instanceof ZodError) {\n return {\n success: false,\n output: 'Validation error occurred',\n error: errorMessage,\n traceId,\n executionTime,\n };\n }\n\n this.logger.error(`Tool execution failed: ${context.toolName}`, {\n traceId,\n error: errorMessage,\n });\n\n return {\n success: false,\n output: 'Tool execution failed',\n error: errorMessage,\n traceId,\n executionTime,\n };\n }\n\n /**\n * Build default session context\n */\n private buildDefaultSession(): SessionContext {\n return {\n sessionId: `session-${Date.now()}-${Math.random()\n .toString(36)\n .substr(2, 9)}`,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Get statistics about the pipeline\n */\n getStatistics(): {\n totalMiddleware: number;\n registeredMiddleware: string[];\n } {\n return {\n totalMiddleware: 0,\n registeredMiddleware: [],\n };\n }\n}\n","import type { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport type { StructuredTool } from '@langchain/core/tools';\nimport { createOpenAIToolsAgent } from 'langchain/agents';\nimport {\n FormAwareAgentExecutor,\n type ParameterPreprocessingCallback,\n} from './form-aware-agent-executor';\nimport {\n ChatPromptTemplate,\n MessagesPlaceholder,\n} from '@langchain/core/prompts';\nimport { ChatOpenAI } from '@langchain/openai';\nimport {\n calculateTokenCostSync,\n getAllHederaCorePlugins,\n HederaAgentKit,\n TokenUsageCallbackHandler,\n} from 'hedera-agent-kit';\nimport type { TokenUsage, CostCalculation } from 'hedera-agent-kit';\nimport {\n BaseAgent,\n type ConversationContext,\n type ChatResponse,\n type OperationalMode,\n type UsageStats,\n} from '../base-agent';\nimport { MCPClientManager } from '../mcp/mcp-client-manager';\nimport { convertMCPToolToLangChain } from '../mcp/adapters/langchain';\nimport { SmartMemoryManager } from '../memory/smart-memory-manager';\nimport type { MCPConnectionStatus, MCPServerConfig } from '../mcp/types';\nimport { ResponseFormatter } from '../utils/response-formatter';\nimport type { FormSubmission } from '../forms/types';\nimport type { ToolRegistrationOptions } from '../core/tool-registry';\nimport { ERROR_MESSAGES } from '../constants';\nimport {\n HumanMessage,\n AIMessage,\n SystemMessage,\n BaseMessage as _BaseMessage,\n} from '@langchain/core/messages';\nimport { ToolRegistry } from '../core/tool-registry';\nimport {\n ExecutionPipeline,\n SessionContext,\n} from '../execution/execution-pipeline';\nimport { FormEngine } from '../forms/form-engine';\nimport type { ChainValues } from '@langchain/core/utils/types';\n\ninterface RenderConfigSchema {\n _renderConfig?: Record<string, unknown>;\n}\n\ninterface ToolExecutionData {\n type: string;\n formId?: string;\n parameters?: Record<string, unknown>;\n toolName?: string;\n}\n\ninterface ToolWithOriginal {\n originalTool?: {\n call?: (args: Record<string, unknown>) => Promise<string>;\n };\n}\n\ninterface ExecutorWithRestore {\n restorePendingForms?: (p: Map<string, unknown>) => void;\n}\n\ninterface ResultWithToolName {\n toolName?: string;\n}\n\ninterface IntermediateStep {\n action?: {\n tool?: string;\n toolInput?: Record<string, unknown>;\n };\n observation?: unknown;\n}\n\ninterface HashLinkBlock {\n blockId: string;\n hashLink: string;\n template: string;\n attributes: Record<string, unknown>;\n}\n\ninterface MetadataWithHashLink {\n hashLinkBlock?: HashLinkBlock;\n memoryStats?: {\n activeMessages: number;\n tokenUsage: number;\n maxTokens: number;\n usagePercentage: number;\n };\n [key: string]: unknown;\n}\n\nfunction _isMetadataWithHashLink(\n metadata: unknown\n): metadata is MetadataWithHashLink {\n if (!metadata || typeof metadata !== 'object') {\n return false;\n }\n const meta = metadata as Record<string, unknown>;\n return 'hashLinkBlock' in meta || 'memoryStats' in meta;\n}\n\nfunction hasHashLinkBlock(\n metadata: unknown\n): metadata is { hashLinkBlock: HashLinkBlock } {\n if (!metadata || typeof metadata !== 'object') {\n return false;\n }\n const meta = metadata as Record<string, unknown>;\n if (\n !('hashLinkBlock' in meta) ||\n !meta.hashLinkBlock ||\n typeof meta.hashLinkBlock !== 'object'\n ) {\n return false;\n }\n const block = meta.hashLinkBlock as Record<string, unknown>;\n return (\n 'blockId' in block &&\n 'hashLink' in block &&\n 'template' in block &&\n 'attributes' in block &&\n typeof block.blockId === 'string' &&\n typeof block.hashLink === 'string' &&\n typeof block.template === 'string' &&\n typeof block.attributes === 'object'\n );\n}\n\nexport class LangChainAgent extends BaseAgent {\n private executor: FormAwareAgentExecutor | undefined;\n private systemMessage = '';\n private mcpManager?: MCPClientManager;\n private smartMemory: SmartMemoryManager | undefined;\n private mcpConnectionStatus: Map<string, MCPConnectionStatus> = new Map();\n private toolRegistry!: ToolRegistry;\n private executionPipeline!: ExecutionPipeline;\n private formEngine!: FormEngine;\n private addToolRawToMemory(name: string, payload: string): void {\n try {\n const content = `[tool-raw:${name}] ${payload}`;\n this.smartMemory!.addMessage(new SystemMessage(content));\n } catch {}\n }\n private persistToolRaw(toolName: string, output: unknown): void {\n try {\n let payload = '';\n if (typeof output === 'string') {\n payload = this.isJSON(output) ? output : JSON.stringify({ output });\n } else if (output !== undefined) {\n try {\n payload = JSON.stringify(output);\n } catch {\n payload = String(output);\n }\n } else {\n payload = JSON.stringify({ observation: null });\n }\n this.addToolRawToMemory(toolName, payload);\n } catch {}\n }\n private persistIntermediateSteps(\n steps: IntermediateStep[] | undefined\n ): void {\n if (!steps || !Array.isArray(steps)) {\n return;\n }\n try {\n for (const step of steps) {\n const name = step?.action?.tool || 'unknown';\n const obs = step?.observation;\n this.persistToolRaw(name, obs);\n }\n } catch {}\n }\n private pendingParameterPreprocessingCallback:\n | ParameterPreprocessingCallback\n | undefined;\n\n /**\n * Get inscription tool by capability instead of hardcoded name\n */\n private getInscriptionTool(): StructuredTool | null {\n const criticalTools = this.toolRegistry.getToolsByCapability(\n 'priority',\n 'critical'\n );\n\n for (const entry of criticalTools) {\n const tool = entry.tool;\n const name = tool.name.toLowerCase();\n const desc = tool.description?.toLowerCase() || '';\n\n if (\n name.includes('inscribe') ||\n name.includes('hashinal') ||\n desc.includes('inscribe') ||\n desc.includes('hashinal')\n ) {\n return tool;\n }\n }\n\n const allTools = this.toolRegistry.getAllRegistryEntries();\n for (const entry of allTools) {\n const tool = entry.tool;\n const name = tool.name.toLowerCase();\n const desc = tool.description?.toLowerCase() || '';\n\n if (\n name.includes('inscribe') ||\n name.includes('hashinal') ||\n desc.includes('inscribe') ||\n desc.includes('hashinal')\n ) {\n return tool;\n }\n }\n\n return null;\n }\n\n /**\n * Execute a tool directly with parameters, optionally using ExecutionPipeline\n */\n private async executeToolDirect(\n toolName: string,\n parameters: Record<string, unknown>,\n useExecutionPipeline = false\n ): Promise<string> {\n if (useExecutionPipeline && this.executionPipeline && this.smartMemory) {\n const sessionContext: SessionContext = {\n sessionId: `session-${Date.now()}`,\n timestamp: Date.now(),\n };\n\n const result = await this.executionPipeline.execute(\n toolName,\n parameters,\n sessionContext\n );\n\n if (!result.success) {\n throw new Error(result.error || 'Pipeline execution failed');\n }\n\n return result.output;\n }\n\n const entry = this.toolRegistry.getTool(toolName);\n if (!entry) {\n throw new Error(`Tool not found: ${toolName}`);\n }\n\n let processedParameters = { ...parameters };\n\n if (this.pendingParameterPreprocessingCallback) {\n this.logger.info(\n 'Applying parameter preprocessing in executeToolDirect',\n {\n toolName,\n hasCallback: true,\n parameterKeys: Object.keys(parameters),\n }\n );\n\n try {\n processedParameters = await this.pendingParameterPreprocessingCallback(\n toolName,\n parameters\n );\n\n if (\n JSON.stringify(processedParameters) !== JSON.stringify(parameters)\n ) {\n this.logger.info('Parameters preprocessed successfully', {\n toolName,\n originalKeys: Object.keys(parameters),\n processedKeys: Object.keys(processedParameters),\n changes: Object.keys(processedParameters).filter(\n (key) => processedParameters[key] !== parameters[key]\n ),\n });\n }\n } catch (error) {\n this.logger.warn(\n 'Parameter preprocessing failed, using original parameters',\n {\n toolName,\n error: error instanceof Error ? error.message : 'Unknown error',\n }\n );\n processedParameters = parameters;\n }\n }\n\n const mergedArgs = { ...processedParameters, renderForm: false };\n\n if (entry.wrapper) {\n const maybeWrapper = entry.tool as ToolWithOriginal;\n if (maybeWrapper.originalTool?.call) {\n return await maybeWrapper.originalTool.call(mergedArgs);\n }\n }\n\n return await entry.tool.call(mergedArgs);\n }\n\n /**\n * Create a standard ChatResponse from tool output\n */\n private createToolResponse(toolOutput: string): ChatResponse {\n return {\n output: toolOutput,\n message: toolOutput,\n notes: [],\n };\n }\n\n /**\n * Handle TOOL_EXECUTION format messages\n */\n private async handleToolExecution(\n message: string,\n context?: ConversationContext\n ): Promise<ChatResponse | null> {\n let isToolExecution = false;\n let toolExecutionData: ToolExecutionData | null = null;\n\n try {\n if (message.includes('TOOL_EXECUTION')) {\n const parsed = JSON.parse(message);\n if (parsed.type === 'TOOL_EXECUTION') {\n isToolExecution = true;\n toolExecutionData = parsed;\n }\n }\n } catch {}\n\n if (!isToolExecution || !toolExecutionData?.formId) {\n return null;\n }\n\n try {\n const params = (toolExecutionData.parameters || {}) as Record<\n string,\n unknown\n >;\n const toolName = toolExecutionData.toolName;\n\n if (toolName) {\n const toolOutput = await this.executeToolDirect(toolName, params);\n try {\n const payload = this.isJSON(toolOutput)\n ? toolOutput\n : JSON.stringify({ output: toolOutput });\n this.addToolRawToMemory(toolName, payload);\n } catch {}\n return this.createToolResponse(toolOutput);\n }\n } catch {}\n\n const formSubmission: FormSubmission = {\n formId: toolExecutionData.formId,\n toolName: toolExecutionData.toolName || '',\n parameters: toolExecutionData.parameters || {},\n timestamp: Date.now(),\n };\n\n if (\n this.executor &&\n 'processFormSubmission' in this.executor &&\n typeof this.executor.processFormSubmission === 'function'\n ) {\n return this.processFormSubmission(formSubmission, context);\n }\n\n return null;\n }\n\n /**\n * Handle direct tool execution commands\n */\n private async handleDirectToolExecution(\n message: string\n ): Promise<ChatResponse | null> {\n if (\n typeof message !== 'string' ||\n !message.includes('Please execute the following tool:')\n ) {\n return null;\n }\n\n try {\n const toolLineMatch = message.match(/Tool:\\s*(.+)/);\n const argsLineIndex = message.indexOf('Arguments:');\n\n if (toolLineMatch && argsLineIndex !== -1) {\n const toolName = toolLineMatch[1].trim();\n const argsText = message\n .slice(argsLineIndex + 'Arguments:'.length)\n .trim();\n\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(argsText);\n } catch {}\n\n const toolOutput = await this.executeToolDirect(toolName, args);\n try {\n const payload = this.isJSON(toolOutput)\n ? toolOutput\n : JSON.stringify({ output: toolOutput });\n this.addToolRawToMemory(toolName, payload);\n } catch {}\n return this.createToolResponse(toolOutput);\n }\n } catch {}\n\n return null;\n }\n\n /**\n * Handle JSON format tool calls and form submissions\n */\n private async handleJsonToolCalls(\n message: string,\n context?: ConversationContext\n ): Promise<ChatResponse | null> {\n if (typeof message !== 'string') {\n return null;\n }\n\n try {\n const trimmed = message.trim();\n if (\n !(trimmed.startsWith('{') && trimmed.endsWith('}')) &&\n !(trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n return null;\n }\n\n const obj = JSON.parse(trimmed) as Record<string, unknown>;\n const formId = obj['formId'] as string | undefined;\n const toolName = (obj['toolName'] as string) || '';\n const parameters = (obj['parameters'] as Record<string, unknown>) || {};\n\n if (\n formId &&\n this.executor &&\n 'processFormSubmission' in this.executor &&\n typeof this.executor.processFormSubmission === 'function'\n ) {\n return this.processFormSubmission(\n { formId, toolName, parameters, timestamp: Date.now() },\n context\n );\n }\n\n if (toolName) {\n const toolOutput = await this.executeToolDirect(toolName, parameters);\n try {\n const payload = this.isJSON(toolOutput)\n ? toolOutput\n : JSON.stringify({ output: toolOutput });\n this.addToolRawToMemory(toolName, payload);\n } catch {}\n return this.createToolResponse(toolOutput);\n }\n } catch {}\n\n return null;\n }\n\n /**\n * Handle content-ref messages for inscription tools\n */\n private async handleContentRefMessages(\n message: string\n ): Promise<ChatResponse | null> {\n if (typeof message !== 'string' || !message.includes('content-ref:')) {\n return null;\n }\n\n try {\n const tool = this.getInscriptionTool();\n if (!tool) {\n return null;\n }\n\n const idMatch =\n message.match(/content-ref:([A-Za-z0-9_\\-]+)/i) ||\n message.match(/content-ref:([^\\s)]+)/i);\n const contentRef =\n idMatch && idMatch[1]\n ? `content-ref:${idMatch[1]}`\n : message.match(/content-ref:[^\\s)]+/i)?.[0] || undefined;\n\n const args = contentRef\n ? ({ contentRef, renderForm: true, withHashLinkBlocks: true } as Record<\n string,\n unknown\n >)\n : ({ renderForm: true, withHashLinkBlocks: true } as Record<\n string,\n unknown\n >);\n\n const toolOutput = await tool.call(args);\n let parsed: Record<string, unknown> | undefined;\n\n try {\n parsed =\n typeof toolOutput === 'string'\n ? (JSON.parse(toolOutput) as Record<string, unknown>)\n : (toolOutput as Record<string, unknown>);\n } catch {}\n\n if (parsed && parsed['requiresForm'] && parsed['formMessage']) {\n const pending = new Map<\n string,\n {\n toolName: string;\n originalInput: Record<string, unknown>;\n originalToolInput?: Record<string, unknown>;\n schema: unknown;\n }\n >();\n\n const originalInput = {\n input: message,\n chat_history: this.smartMemory!.getMessages(),\n } as Record<string, unknown>;\n\n const formMessage = parsed['formMessage'] as { id: string };\n pending.set(formMessage.id, {\n toolName: tool.name,\n originalInput,\n originalToolInput: args,\n schema: null,\n });\n\n const maybeRestore = this.executor as ExecutorWithRestore;\n\n if (typeof maybeRestore.restorePendingForms === 'function') {\n maybeRestore.restorePendingForms!(pending);\n }\n\n const outputMsg =\n (parsed['message'] as string) ||\n 'Please complete the form to continue.';\n\n return {\n output: outputMsg,\n message: outputMsg,\n notes: [],\n requiresForm: true,\n formMessage: formMessage as ChatResponse['formMessage'],\n } as ChatResponse;\n }\n } catch {}\n\n return null;\n }\n\n /**\n * Process executor result and format response\n */\n private async processExecutorResult(\n result: ChainValues\n ): Promise<ChatResponse> {\n let outputStr = '';\n if (typeof result.output === 'string') {\n outputStr = result.output;\n } else if (result.output) {\n try {\n outputStr = JSON.stringify(result.output);\n } catch {\n outputStr = String(result.output);\n }\n }\n\n let response: ChatResponse = {\n output: outputStr,\n message: outputStr,\n notes: [],\n intermediateSteps: result.intermediateSteps,\n };\n\n if (result.requiresForm && result.formMessage) {\n response.formMessage = result.formMessage;\n response.requiresForm = true;\n }\n\n if (result.intermediateSteps && Array.isArray(result.intermediateSteps)) {\n const toolCalls = result.intermediateSteps.map(\n (step: IntermediateStep, index: number) => ({\n id: `call_${index}`,\n name: step.action?.tool || 'unknown',\n args: step.action?.toolInput || {},\n output:\n typeof step.observation === 'string'\n ? step.observation\n : JSON.stringify(step.observation),\n })\n );\n\n if (toolCalls.length > 0) {\n response.tool_calls = toolCalls;\n }\n\n this.persistIntermediateSteps(\n result.intermediateSteps as IntermediateStep[]\n );\n }\n\n const steps = (result?.intermediateSteps as IntermediateStep[]) || [];\n const lastJsonObservation = [...steps]\n .reverse()\n .find(\n (s) => typeof s?.observation === 'string' && this.isJSON(s.observation as string)\n )?.observation as string | undefined;\n\n if (lastJsonObservation) {\n try {\n const parsed = JSON.parse(lastJsonObservation);\n\n if (ResponseFormatter.isInscriptionResponse(parsed)) {\n const formattedMessage = ResponseFormatter.formatInscriptionResponse(parsed);\n response.output = formattedMessage;\n response.message = formattedMessage;\n if (parsed.inscription) {\n response.inscription = parsed.inscription;\n }\n if (parsed.metadata) {\n response.metadata = { ...response.metadata, ...parsed.metadata };\n }\n } else {\n if (typeof parsed.message === 'string' && parsed.message.trim().length > 0) {\n response.message = parsed.message;\n response.output = parsed.message;\n }\n if (parsed.success === true) {\n delete (response as { error?: string }).error;\n }\n if (typeof parsed.transactionBytes === 'string') {\n response.metadata = {\n ...response.metadata,\n transactionBytes: parsed.transactionBytes as string,\n };\n }\n if (typeof parsed.scheduleId === 'string') {\n (response as { scheduleId?: string }).scheduleId = parsed.scheduleId as string;\n }\n }\n\n const blockMetadata = this.processHashLinkBlocks(parsed);\n if (blockMetadata.hashLinkBlock) {\n response.metadata = { ...response.metadata, ...blockMetadata };\n }\n } catch (error) {\n this.logger.error('Error parsing intermediate steps:', error);\n }\n }\n\n\n if (!response.output || response.output.trim() === '') {\n response.output = 'Agent action complete.';\n }\n\n if (response.output) {\n this.smartMemory!.addMessage(new AIMessage(response.output));\n }\n\n if (this.tokenTracker) {\n const tokenUsage = this.tokenTracker.getLatestTokenUsage();\n if (tokenUsage) {\n response.tokenUsage = tokenUsage;\n response.cost = calculateTokenCostSync(tokenUsage);\n }\n }\n\n const finalMemoryStats = this.smartMemory!.getMemoryStats();\n response.metadata = {\n ...response.metadata,\n memoryStats: {\n activeMessages: finalMemoryStats.totalActiveMessages,\n tokenUsage: finalMemoryStats.currentTokenCount,\n maxTokens: finalMemoryStats.maxTokens,\n usagePercentage: finalMemoryStats.usagePercentage,\n },\n };\n\n this.logger.info('LangChainAgent.chat returning response:', response);\n return response;\n }\n\n /**\n * Normalize context messages into LangChain message instances and load into memory\n */\n /**\n * Loads context messages into memory, merging with existing messages\n */\n private loadContextMessages(context?: ConversationContext): void {\n if (\n !this.smartMemory ||\n !context?.messages ||\n context.messages.length === 0\n ) {\n return;\n }\n\n const existingMessages = this.smartMemory.getMessages();\n const existingContent = new Set(\n existingMessages.map((m) => `${m.constructor.name}:${m.content}`)\n );\n\n for (const msg of context.messages as unknown[]) {\n let messageClass:\n | typeof HumanMessage\n | typeof AIMessage\n | typeof SystemMessage;\n let content: string;\n\n if (\n msg instanceof HumanMessage ||\n msg instanceof AIMessage ||\n msg instanceof SystemMessage\n ) {\n messageClass = msg.constructor as\n | typeof HumanMessage\n | typeof AIMessage\n | typeof SystemMessage;\n content = msg.content as string;\n } else if (\n msg &&\n typeof msg === 'object' &&\n 'content' in msg &&\n 'type' in msg\n ) {\n content = String((msg as { content: unknown }).content);\n const type = String((msg as { type: unknown }).type);\n\n if (type === 'human') messageClass = HumanMessage;\n else if (type === 'ai') messageClass = AIMessage;\n else if (type === 'system') messageClass = SystemMessage;\n else continue;\n } else {\n continue;\n }\n\n const key = `${messageClass.name}:${content}`;\n if (!existingContent.has(key)) {\n this.smartMemory.addMessage(new messageClass(content));\n existingContent.add(key);\n }\n }\n }\n\n async boot(): Promise<void> {\n this.logger.info('🚨🚨🚨 LANGCHAIN AGENT BOOT METHOD CALLED 🚨🚨🚨');\n\n if (this.initialized) {\n this.logger.warn('Agent already initialized');\n return;\n }\n\n try {\n this.agentKit = await this.createAgentKit();\n await this.agentKit.initialize();\n\n const modelName =\n this.config.ai?.modelName ||\n process.env.OPENAI_MODEL_NAME ||\n 'gpt-4o-mini';\n try {\n if (typeof (TokenUsageCallbackHandler as unknown as { new (m: string): unknown }) === 'function') {\n this.tokenTracker = new TokenUsageCallbackHandler(modelName);\n } else {\n this.logger.warn('TokenUsageCallbackHandler unavailable or not a constructor; skipping token tracking');\n }\n } catch {\n this.logger.warn('TokenUsageCallbackHandler threw; skipping token tracking');\n }\n\n this.toolRegistry = new ToolRegistry(this.logger);\n\n const allTools = this.agentKit.getAggregatedLangChainTools();\n this.logger.info('=== TOOL REGISTRATION START ===');\n this.logger.info(\n 'All tools from agentKit:',\n allTools.map((t) => t.name)\n );\n\n const filteredTools = this.filterTools(allTools);\n this.logger.info(\n 'Filtered tools for registration:',\n filteredTools.map((t) => t.name)\n );\n\n for (const tool of filteredTools) {\n this.logger.info(`🔧 Registering tool: ${tool.name}`);\n\n const options: ToolRegistrationOptions = {};\n\n const name = tool.name.toLowerCase();\n const desc = tool.description?.toLowerCase() || '';\n\n if (tool.name === 'hedera-hts-mint-nft') {\n const originalCall = tool.call.bind(tool);\n tool.call = async (args: Record<string, unknown>) => {\n if (args.metaOptions && typeof args.metaOptions === 'object') {\n const metaOptions = args.metaOptions as Record<string, unknown>;\n if (metaOptions.transactionMemo) {\n this.logger.warn(\n '🚨 WORKAROUND: Stripping transactionMemo from hedera-hts-mint-nft to avoid bug',\n { originalMemo: metaOptions.transactionMemo }\n );\n delete metaOptions.transactionMemo;\n }\n }\n return originalCall(args);\n };\n }\n\n if (\n name.includes('inscribe') ||\n name.includes('hashinal') ||\n desc.includes('inscribe') ||\n desc.includes('hashinal')\n ) {\n options.forceWrapper = true;\n options.metadata = {\n category: 'core' as const,\n version: '1.0.0',\n dependencies: [],\n };\n\n this.logger.info(`🎯 CRITICAL TOOL DEBUG - ${tool.name} schema:`, {\n hasSchema: !!tool.schema,\n schemaType: tool.schema?.constructor?.name,\n hasRenderConfig: !!(tool.schema as RenderConfigSchema)\n ?._renderConfig,\n renderConfig: (tool.schema as RenderConfigSchema)?._renderConfig,\n });\n }\n\n this.toolRegistry.registerTool(tool, options);\n }\n\n this.tools = this.toolRegistry.getAllTools();\n\n this.logger.info(`🚀 TOOLS REGISTERED: ${this.tools.length} tools`);\n\n const stats = this.toolRegistry.getStatistics();\n this.logger.info('📊 Tool Registry Statistics:', {\n total: stats.totalTools,\n wrapped: stats.wrappedTools,\n unwrapped: stats.unwrappedTools,\n categories: stats.categoryCounts,\n priorities: stats.priorityCounts,\n });\n\n const inscriptionTool = this.getInscriptionTool();\n if (inscriptionTool) {\n const entry = this.toolRegistry.getTool(inscriptionTool.name);\n if (entry) {\n this.logger.info(\n `✅ Inscription tool registered: ${inscriptionTool.name}`\n );\n }\n }\n\n const toolNames = this.toolRegistry.getToolNames();\n const uniqueNames = new Set(toolNames);\n if (toolNames.length !== uniqueNames.size) {\n this.logger.error('DUPLICATE TOOL NAMES DETECTED in registry!');\n const duplicates = toolNames.filter(\n (name, index) => toolNames.indexOf(name) !== index\n );\n throw new Error(\n `Duplicate tool names detected: ${duplicates.join(', ')}`\n );\n }\n\n if (this.config.mcp?.servers && this.config.mcp.servers.length > 0) {\n if (this.config.mcp.autoConnect !== false) {\n await this.initializeMCP();\n } else {\n this.logger.info(\n 'MCP servers configured but autoConnect=false, skipping synchronous connection'\n );\n this.mcpManager = new MCPClientManager(this.logger);\n }\n }\n\n this.smartMemory = new SmartMemoryManager({\n modelName,\n maxTokens: 90000,\n reserveTokens: 10000,\n storageLimit: 1000,\n });\n\n this.logger.info('SmartMemoryManager initialized:', {\n modelName,\n toolsCount: this.tools.length,\n maxTokens: 90000,\n reserveTokens: 10000,\n });\n\n this.formEngine = new FormEngine(this.logger);\n\n this.executionPipeline = new ExecutionPipeline(\n this.toolRegistry,\n this.formEngine,\n this.smartMemory,\n this.logger\n );\n\n this.systemMessage = this.buildSystemPrompt();\n\n this.smartMemory.setSystemPrompt(this.systemMessage);\n\n await this.createExecutor();\n\n this.initialized = true;\n this.logger.info('LangChain Hedera agent initialized with ToolRegistry');\n } catch (error) {\n this.logger.error('Failed to initialize agent:', error);\n throw error;\n }\n }\n\n async chat(\n message: string,\n context?: ConversationContext\n ): Promise<ChatResponse> {\n if (!this.initialized || !this.executor || !this.smartMemory) {\n throw new Error('Agent not initialized. Call boot() first.');\n }\n\n try {\n const toolExecutionResult = await this.handleToolExecution(\n message,\n context\n );\n if (toolExecutionResult) {\n return toolExecutionResult;\n }\n\n const directToolResult = await this.handleDirectToolExecution(message);\n if (directToolResult) {\n return directToolResult;\n }\n\n const jsonToolResult = await this.handleJsonToolCalls(message, context);\n if (jsonToolResult) {\n return jsonToolResult;\n }\n\n const contentRefResult = await this.handleContentRefMessages(message);\n if (contentRefResult) {\n return contentRefResult;\n }\n\n this.logger.info('LangChainAgent.chat called with:', {\n message,\n contextLength: context?.messages?.length || 0,\n });\n\n this.loadContextMessages(context);\n this.smartMemory.addMessage(new HumanMessage(message));\n\n const memoryStats = this.smartMemory.getMemoryStats();\n this.logger.info('Memory stats before execution:', {\n totalMessages: memoryStats.totalActiveMessages,\n currentTokens: memoryStats.currentTokenCount,\n maxTokens: memoryStats.maxTokens,\n usagePercentage: memoryStats.usagePercentage,\n toolsCount: this.tools.length,\n });\n\n const currentMessages = this.smartMemory.getMessages();\n this.logger.info('Current messages in memory:', {\n count: currentMessages.length,\n });\n try {\n const instr = currentMessages\n .map((m) => String((m as { content: unknown }).content || ''))\n .filter(\n (c) =>\n typeof c === 'string' &&\n (c.includes('[instruction:') || c.includes('[tool-next-steps:'))\n );\n if (instr.length > 0) {\n this.logger.info('Instruction/next-steps messages in memory:', {\n messages: instr,\n });\n }\n } catch {}\n\n const result = await this.executor.invoke({\n input: message,\n chat_history: currentMessages,\n });\n\n this.logger.info('LangChainAgent executor result:', result);\n\n return this.processExecutorResult(result);\n } catch (error) {\n this.logger.error('LangChainAgent.chat error:', error);\n return this.handleError(error);\n }\n }\n\n async shutdown(): Promise<void> {\n if (this.mcpManager) {\n await this.mcpManager.disconnectAll();\n }\n\n if (this.smartMemory) {\n this.smartMemory.dispose();\n this.smartMemory = undefined;\n }\n\n if (this.toolRegistry) {\n this.toolRegistry.clear();\n }\n\n this.executor = undefined;\n this.agentKit = undefined;\n this.tools = [];\n this.initialized = false;\n this.logger.info('Agent cleaned up');\n }\n\n switchMode(mode: OperationalMode): void {\n if (this.config.execution) {\n this.config.execution.operationalMode = mode;\n } else {\n this.config.execution = { operationalMode: mode };\n }\n\n if (this.agentKit) {\n this.agentKit.operationalMode = mode;\n }\n\n this.systemMessage = this.buildSystemPrompt();\n this.logger.info(`Operational mode switched to: ${mode}`);\n }\n\n getUsageStats(): UsageStats {\n if (!this.tokenTracker) {\n return {\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n cost: { totalCost: 0 } as CostCalculation,\n };\n }\n\n const usage = this.tokenTracker.getTotalTokenUsage();\n const cost = calculateTokenCostSync(usage);\n return { ...usage, cost };\n }\n\n getUsageLog(): UsageStats[] {\n if (!this.tokenTracker) {\n return [];\n }\n\n return this.tokenTracker.getTokenUsageHistory().map((usage) => ({\n ...usage,\n cost: calculateTokenCostSync(usage),\n }));\n }\n\n clearUsageStats(): void {\n if (this.tokenTracker) {\n this.tokenTracker.reset();\n this.logger.info('Usage statistics cleared');\n }\n }\n\n getMCPConnectionStatus(): Map<string, MCPConnectionStatus> {\n return new Map(this.mcpConnectionStatus);\n }\n\n /**\n * Processes form submission and continues with tool execution\n */\n async processFormSubmission(\n submission: FormSubmission,\n context?: ConversationContext\n ): Promise<ChatResponse> {\n if (!this.initialized || !this.executor || !this.smartMemory) {\n throw new Error('Agent not initialized. Call boot() first.');\n }\n\n try {\n if (!submission.parameters || typeof submission.parameters !== 'object') {\n this.logger.error('Invalid form submission parameters:', {\n parameters: submission.parameters,\n type: typeof submission.parameters,\n });\n const errorInfo = JSON.stringify(submission, null, 2);\n return this.handleError(\n new Error(`Invalid form submission parameters: ${errorInfo}`)\n );\n }\n\n this.loadContextMessages(context);\n\n const safeSubmission = {\n ...submission,\n parameters: submission.parameters || {},\n };\n\n const result = await this.executor.processFormSubmission(safeSubmission);\n\n const preservedMetadata = result?.metadata ? { ...result.metadata } : {};\n\n try {\n const maybeRaw = (\n result as unknown as {\n rawToolOutput?: string;\n toolName?: string;\n }\n ).rawToolOutput;\n const toolName = (result as ResultWithToolName).toolName || 'unknown';\n if (typeof maybeRaw === 'string' && maybeRaw.trim().length > 0) {\n const payload = this.isJSON(maybeRaw)\n ? maybeRaw\n : JSON.stringify({ output: maybeRaw });\n this.addToolRawToMemory(toolName, payload);\n }\n } catch {}\n\n let outputMessage = 'Form processed successfully.';\n if (typeof result.output === 'string') {\n outputMessage = result.output;\n } else if (result.output) {\n try {\n outputMessage = JSON.stringify(result.output);\n } catch {\n outputMessage = String(result.output);\n }\n }\n\n let response: ChatResponse = {\n output: outputMessage,\n message: outputMessage,\n notes: [],\n intermediateSteps: result.intermediateSteps as IntermediateStep[],\n };\n\n if (result.metadata) {\n response.metadata = {\n ...response.metadata,\n ...result.metadata,\n };\n this.logger.info('🔍 DEBUG: Metadata after merge from result:', {\n hasMetadata: !!response.metadata,\n metadataKeys: response.metadata ? Object.keys(response.metadata) : [],\n hasHashLinkBlock: hasHashLinkBlock(response.metadata),\n hashLinkBlockContent: hasHashLinkBlock(response.metadata)\n ? response.metadata.hashLinkBlock\n : undefined,\n });\n }\n\n if (result.requiresForm && result.formMessage) {\n response.formMessage = result.formMessage;\n response.requiresForm = true;\n }\n\n if (result.intermediateSteps && Array.isArray(result.intermediateSteps)) {\n const toolCalls = result.intermediateSteps.map(\n (step: IntermediateStep, index: number) => {\n const name = step?.action?.tool || 'unknown';\n const args = step?.action?.toolInput || {};\n const obs = step?.observation;\n let output = '';\n if (typeof obs === 'string') {\n output = obs;\n } else if (obs && typeof obs === 'object') {\n try {\n output = JSON.stringify(obs);\n } catch {\n output = String(obs);\n }\n } else if (obs !== undefined) {\n output = String(obs);\n }\n return { id: `call_${index}`, name, args, output };\n }\n );\n if (toolCalls.length > 0) {\n response.tool_calls = toolCalls;\n }\n this.persistIntermediateSteps(\n result.intermediateSteps as IntermediateStep[]\n );\n }\n\n const parsedSteps = result?.intermediateSteps?.[0]?.observation;\n if (\n parsedSteps &&\n typeof parsedSteps === 'string' &&\n this.isJSON(parsedSteps)\n ) {\n try {\n const parsed = JSON.parse(parsedSteps);\n response = { ...response, ...parsed };\n\n const blockMetadata = this.processHashLinkBlocks(parsed);\n if (blockMetadata.hashLinkBlock) {\n response.metadata = {\n ...response.metadata,\n ...blockMetadata,\n };\n }\n } catch (error) {\n this.logger.error('Error parsing intermediate steps:', error);\n }\n }\n\n if (response.output) {\n this.smartMemory.addMessage(new AIMessage(response.output));\n }\n\n if (this.tokenTracker) {\n const tokenUsage = this.tokenTracker.getLatestTokenUsage();\n if (tokenUsage) {\n response.tokenUsage = tokenUsage;\n response.cost = calculateTokenCostSync(tokenUsage);\n }\n }\n\n const finalMemoryStats = this.smartMemory.getMemoryStats();\n this.logger.info('🔍 DEBUG: Metadata before memoryStats merge:', {\n hasMetadata: !!response.metadata,\n metadataKeys: response.metadata ? Object.keys(response.metadata) : [],\n hasHashLinkBlock: hasHashLinkBlock(response.metadata),\n });\n\n response.metadata = {\n ...preservedMetadata,\n ...response.metadata,\n memoryStats: {\n activeMessages: finalMemoryStats.totalActiveMessages,\n tokenUsage: finalMemoryStats.currentTokenCount,\n maxTokens: finalMemoryStats.maxTokens,\n usagePercentage: finalMemoryStats.usagePercentage,\n },\n };\n\n this.logger.info('🔍 DEBUG: Final response metadata before return:', {\n hasMetadata: !!response.metadata,\n metadataKeys: response.metadata ? Object.keys(response.metadata) : [],\n hasHashLinkBlock: hasHashLinkBlock(response.metadata),\n fullMetadata: response.metadata,\n });\n\n if (\n hasHashLinkBlock(preservedMetadata) &&\n !hasHashLinkBlock(response.metadata)\n ) {\n this.logger.error(\n '❌ CRITICAL: HashLink metadata was lost during processing!'\n );\n this.logger.error(\n 'Original metadata had hashLinkBlock:',\n preservedMetadata.hashLinkBlock\n );\n this.logger.error('Final metadata missing hashLinkBlock');\n }\n\n return response;\n } catch (error) {\n this.logger.error('Form submission processing error:', error);\n return this.handleError(error);\n }\n }\n\n /**\n * Check if the agent has pending forms that need to be completed\n */\n hasPendingForms(): boolean {\n return this.executor ? this.executor.hasPendingForms() : false;\n }\n\n /**\n * Get information about pending forms\n */\n getPendingFormsInfo(): Array<{ formId: string; toolName: string }> {\n return this.executor ? this.executor.getPendingFormsInfo() : [];\n }\n\n private async createAgentKit(): Promise<HederaAgentKit> {\n const corePlugins = getAllHederaCorePlugins();\n const extensionPlugins = this.config.extensions?.plugins || [];\n const plugins = [...corePlugins, ...extensionPlugins];\n\n const operationalMode =\n this.config.execution?.operationalMode || 'returnBytes';\n const modelName = this.config.ai?.modelName || 'gpt-4o';\n\n return new HederaAgentKit(\n this.config.signer,\n { plugins },\n operationalMode,\n this.config.execution?.userAccountId,\n this.config.execution?.scheduleUserTransactionsInBytesMode ?? false,\n undefined,\n modelName,\n this.config.extensions?.mirrorConfig,\n this.config.debug?.silent ?? false\n );\n }\n\n private async createExecutor(): Promise<void> {\n const existingPendingForms = this.executor?.getPendingForms() || new Map();\n\n let llm: BaseChatModel;\n if (this.config.ai?.provider && this.config.ai.provider.getModel) {\n llm = this.config.ai.provider.getModel() as BaseChatModel;\n } else if (this.config.ai?.llm) {\n llm = this.config.ai.llm as BaseChatModel;\n } else {\n const apiKey = this.config.ai?.apiKey || process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error('OpenAI API key required');\n }\n\n const modelName = this.config.ai?.modelName || 'gpt-4o-mini';\n const isGPT5Model =\n modelName.toLowerCase().includes('gpt-5') ||\n modelName.toLowerCase().includes('gpt5');\n\n llm = new ChatOpenAI({\n apiKey,\n modelName,\n callbacks: this.tokenTracker ? [this.tokenTracker] : [],\n ...(isGPT5Model ? { temperature: 1 } : {}),\n });\n }\n\n const prompt = ChatPromptTemplate.fromMessages([\n ['system', this.systemMessage],\n new MessagesPlaceholder('chat_history'),\n ['human', '{input}'],\n new MessagesPlaceholder('agent_scratchpad'),\n ]);\n\n const langchainTools = this.tools as StructuredTool[];\n\n const inscriptionTool = this.getInscriptionTool();\n if (inscriptionTool) {\n const entry = this.toolRegistry.getTool(inscriptionTool.name);\n if (entry) {\n this.logger.info(\n `✅ Inscription tool registered: ${inscriptionTool.name}`\n );\n }\n }\n\n const stats = this.toolRegistry.getStatistics();\n this.logger.info('🛡️ TOOL SECURITY REPORT:', {\n totalTools: stats.totalTools,\n wrappedTools: stats.wrappedTools,\n unwrappedTools: stats.unwrappedTools,\n categories: stats.categoryCounts,\n priorities: stats.priorityCounts,\n });\n\n this.logger.info(\n `📊 Tool Security Summary: ${stats.wrappedTools} wrapped, ${stats.unwrappedTools} unwrapped`\n );\n\n const agent = await createOpenAIToolsAgent({\n llm,\n tools: langchainTools,\n prompt,\n });\n\n this.executor = new FormAwareAgentExecutor({\n agent,\n tools: langchainTools,\n verbose: this.config.debug?.verbose ?? false,\n returnIntermediateSteps: true,\n });\n\n if (this.pendingParameterPreprocessingCallback) {\n this.executor.setParameterPreprocessingCallback(\n this.pendingParameterPreprocessingCallback\n );\n this.logger.info(\n 'Parameter preprocessing callback re-applied to new executor',\n { hasCallback: true }\n );\n }\n\n if (existingPendingForms.size > 0) {\n this.logger.info(\n `Restoring ${existingPendingForms.size} pending forms to new executor`\n );\n this.executor.restorePendingForms(existingPendingForms);\n }\n\n this.logger.info('FormAwareAgentExecutor initialization complete');\n }\n\n /**\n * Set parameter preprocessing callback for tool parameter format conversion\n */\n setParameterPreprocessingCallback(\n callback: ParameterPreprocessingCallback | undefined\n ): void {\n this.pendingParameterPreprocessingCallback = callback;\n if (this.executor) {\n this.executor.setParameterPreprocessingCallback(callback);\n this.logger.info('Parameter preprocessing callback configured', {\n hasCallback: !!callback,\n });\n } else {\n this.logger.warn(\n 'Cannot set parameter preprocessing callback: executor not initialized'\n );\n }\n }\n\n private handleError(error: unknown): ChatResponse {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n this.logger.error('Chat error:', error);\n\n let tokenUsage: TokenUsage | undefined;\n let cost: CostCalculation | undefined;\n\n if (this.tokenTracker) {\n tokenUsage = this.tokenTracker.getLatestTokenUsage();\n if (tokenUsage) {\n cost = calculateTokenCostSync(tokenUsage);\n }\n }\n\n let userFriendlyMessage = errorMessage;\n let userFriendlyOutput = errorMessage;\n\n if (errorMessage.includes('429')) {\n if (errorMessage.includes('quota')) {\n userFriendlyMessage =\n 'API quota exceeded. Please check your OpenAI billing and usage limits.';\n userFriendlyOutput =\n \"I'm currently unable to respond because the API quota has been exceeded. Please check your OpenAI account billing and usage limits, then try again.\";\n } else {\n userFriendlyMessage = ERROR_MESSAGES.TOO_MANY_REQUESTS;\n userFriendlyOutput = ERROR_MESSAGES.RATE_LIMITED;\n }\n } else if (\n errorMessage.includes('401') ||\n errorMessage.includes('unauthorized')\n ) {\n userFriendlyMessage =\n 'API authentication failed. Please check your API key configuration.';\n userFriendlyOutput =\n \"There's an issue with the API authentication. Please check your OpenAI API key configuration in settings.\";\n } else if (errorMessage.includes('timeout')) {\n userFriendlyMessage = 'Request timed out. Please try again.';\n userFriendlyOutput =\n 'The request took too long to process. Please try again.';\n } else if (\n errorMessage.includes('network') ||\n errorMessage.includes('fetch')\n ) {\n userFriendlyMessage =\n 'Network error. Please check your internet connection and try again.';\n userFriendlyOutput =\n 'There was a network error. Please check your internet connection and try again.';\n } else if (errorMessage.includes('400')) {\n userFriendlyMessage = errorMessage;\n userFriendlyOutput = errorMessage;\n }\n\n const errorResponse: ChatResponse = {\n output: userFriendlyOutput,\n message: userFriendlyMessage,\n error: errorMessage,\n notes: [],\n };\n\n if (tokenUsage) {\n errorResponse.tokenUsage = tokenUsage;\n }\n\n if (cost) {\n errorResponse.cost = cost;\n }\n\n return errorResponse;\n }\n\n private async initializeMCP(): Promise<void> {\n this.mcpManager = new MCPClientManager(this.logger);\n\n for (const serverConfig of this.config.mcp!.servers!) {\n if (serverConfig.autoConnect === false) {\n this.logger.info(\n `Skipping MCP server ${serverConfig.name} (autoConnect=false)`\n );\n continue;\n }\n\n const status = await this.mcpManager.connectServer(serverConfig);\n\n if (status.connected) {\n this.logger.info(\n `Connected to MCP server ${status.serverName} with ${status.tools.length} tools`\n );\n\n for (const mcpTool of status.tools) {\n const langchainTool = convertMCPToolToLangChain(\n mcpTool,\n this.mcpManager,\n serverConfig\n );\n\n this.toolRegistry.registerTool(langchainTool, {\n metadata: {\n category: 'mcp',\n version: '1.0.0',\n dependencies: [serverConfig.name],\n },\n });\n }\n\n this.tools = this.toolRegistry.getAllTools();\n } else {\n this.logger.error(\n `Failed to connect to MCP server ${status.serverName}: ${status.error}`\n );\n }\n }\n }\n\n /**\n * Connect to MCP servers asynchronously after agent boot with background timeout pattern\n */\n async connectMCPServers(): Promise<void> {\n if (!this.config.mcp?.servers || this.config.mcp.servers.length === 0) {\n return;\n }\n\n if (!this.mcpManager) {\n this.mcpManager = new MCPClientManager(this.logger);\n }\n\n this.logger.info(\n `Starting background MCP server connections for ${this.config.mcp.servers.length} servers...`\n );\n\n this.config.mcp.servers.forEach((serverConfig) => {\n this.connectServerInBackground(serverConfig);\n });\n\n this.logger.info('MCP server connections initiated in background');\n }\n\n /**\n * Connect to a single MCP server in background with timeout\n */\n private connectServerInBackground(serverConfig: MCPServerConfig): void {\n const serverName = serverConfig.name;\n\n setTimeout(async () => {\n try {\n this.logger.info(`Background connecting to MCP server: ${serverName}`);\n\n const status = await this.mcpManager!.connectServer(serverConfig);\n this.mcpConnectionStatus.set(serverName, status);\n\n if (status.connected) {\n this.logger.info(\n `Successfully connected to MCP server ${status.serverName} with ${status.tools.length} tools`\n );\n\n for (const mcpTool of status.tools) {\n const langchainTool = convertMCPToolToLangChain(\n mcpTool,\n this.mcpManager!,\n serverConfig\n );\n\n this.toolRegistry.registerTool(langchainTool, {\n metadata: {\n category: 'mcp',\n version: '1.0.0',\n dependencies: [serverConfig.name],\n },\n });\n }\n\n this.tools = this.toolRegistry.getAllTools();\n\n if (this.initialized && this.executor) {\n this.logger.info(\n `Recreating executor with ${this.tools.length} total tools`\n );\n await this.createExecutor();\n }\n } else {\n this.logger.error(\n `Failed to connect to MCP server ${status.serverName}: ${status.error}`\n );\n }\n } catch (error) {\n this.logger.error(\n `Background connection failed for MCP server ${serverName}:`,\n error\n );\n\n this.mcpConnectionStatus.set(serverName, {\n connected: false,\n serverName,\n tools: [],\n error: error instanceof Error ? error.message : 'Connection failed',\n });\n }\n }, 1000);\n }\n\n /**\n * Detects and processes HashLink blocks from tool responses\n * @param parsedResponse - The parsed JSON response from a tool\n * @returns Metadata object containing hashLinkBlock if detected\n */\n private processHashLinkBlocks(parsedResponse: unknown): {\n hashLinkBlock?: Record<string, unknown>;\n } {\n try {\n const responseRecord = parsedResponse as Record<string, unknown>;\n if (\n parsedResponse &&\n typeof parsedResponse === 'object' &&\n responseRecord.hashLinkBlock &&\n typeof responseRecord.hashLinkBlock === 'object'\n ) {\n const block = responseRecord.hashLinkBlock as Record<string, unknown>;\n\n if (\n block.blockId &&\n block.hashLink &&\n block.template &&\n block.attributes &&\n typeof block.blockId === 'string' &&\n typeof block.hashLink === 'string' &&\n typeof block.template === 'string' &&\n typeof block.attributes === 'object'\n ) {\n this.logger.info('HashLink block detected:', {\n blockId: block.blockId,\n hashLink: block.hashLink,\n template: block.template,\n attributeKeys: Object.keys(block.attributes),\n });\n\n return {\n hashLinkBlock: {\n blockId: block.blockId,\n hashLink: block.hashLink,\n template: block.template,\n attributes: block.attributes,\n },\n };\n } else {\n this.logger.warn('Invalid HashLink block structure detected:', block);\n }\n }\n } catch (error) {\n this.logger.error('Error processing HashLink blocks:', error);\n }\n\n return {};\n }\n\n /**\n * Check if a string is valid JSON\n */\n private isJSON(str: string): boolean {\n if (typeof str !== 'string') return false;\n\n const trimmed = str.trim();\n if (!trimmed) return false;\n\n if (\n !(trimmed.startsWith('{') && trimmed.endsWith('}')) &&\n !(trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n return false;\n }\n\n try {\n JSON.parse(trimmed);\n return true;\n } catch {\n return false;\n }\n }\n}\n","import { BaseAgent, type HederaAgentConfiguration } from './base-agent';\nimport { LangChainAgent } from './langchain/langchain-agent';\n\nexport function createAgent(\n config: HederaAgentConfiguration & {\n framework?: 'langchain' | 'vercel' | 'baml';\n }\n): BaseAgent {\n const framework = config.framework || 'langchain';\n\n switch (framework) {\n case 'langchain':\n return new LangChainAgent(config);\n case 'vercel':\n throw new Error('Vercel AI SDK support coming soon');\n case 'baml':\n throw new Error('BAML support coming soon');\n default:\n throw new Error(`Unknown framework: ${framework}`);\n }\n}","import {\n AccountId,\n Client,\n PrivateKey,\n PublicKey,\n Transaction,\n TransactionReceipt,\n} from '@hashgraph/sdk';\nimport { AbstractSigner } from 'hedera-agent-kit';\nimport {\n HederaMirrorNode,\n Logger,\n type NetworkType,\n} from '@hashgraphonline/standards-sdk';\n\n/**\n * BrowserSigner (bytes-only)\n *\n * Minimal signer compatible with HederaAgentKit in bytes/Provide Bytes mode.\n * - Does NOT hold a private key\n * - Cannot execute transactions; only provides identity and network context\n * - getOperatorPrivateKey() throws to signal absence of a local key\n */\nexport class BrowserSigner extends AbstractSigner {\n private readonly account: AccountId;\n private readonly network: 'mainnet' | 'testnet';\n private readonly client: Client;\n private readonly exec: ((\n base64: string,\n network: 'mainnet' | 'testnet'\n ) => Promise<{ transactionId: string }>) | null;\n private readonly ephemeralKey: PrivateKey;\n\n getAccountId(): AccountId {\n return this.account;\n }\n\n getNetwork(): 'mainnet' | 'testnet' {\n return this.network;\n }\n\n constructor(\n accountId: string,\n network: 'mainnet' | 'testnet',\n executor?: (\n base64: string,\n network: 'mainnet' | 'testnet'\n ) => Promise<{ transactionId: string }>\n ) {\n super();\n this.account = AccountId.fromString(accountId);\n this.network = network;\n this.client =\n network === 'mainnet' ? Client.forMainnet() : Client.forTestnet();\n this.exec = executor ?? null;\n this.ephemeralKey = PrivateKey.generateED25519();\n }\n\n /**\n * Returns an auto-generated ED25519 key for client wiring only.\n * Do not use for signing; wallet performs signing in renderer.\n */\n getOperatorPrivateKey(): PrivateKey {\n return this.ephemeralKey;\n }\n\n getClient(): Client {\n return this.client;\n }\n\n async signAndExecuteTransaction(\n tx: Transaction\n ): Promise<TransactionReceipt> {\n if (!this.exec) {\n throw new Error('BrowserSigner executor not available');\n }\n if (!tx.isFrozen()) {\n await tx.freezeWith(this.client);\n }\n const base64 = Buffer.from(tx.toBytes()).toString('base64');\n const { transactionId } = await this.exec(base64, this.network);\n const mirror = new HederaMirrorNode(this.network);\n const deadline = Date.now() + 60000;\n while (Date.now() < deadline) {\n try {\n const details = await mirror.getTransaction(transactionId);\n if (details && details.result) {\n return TransactionReceipt.fromBytes(\n Buffer.from(details.result, 'base64')\n );\n }\n } catch {}\n await new Promise((r) => setTimeout(r, 1200));\n }\n return TransactionReceipt.fromBytes(Buffer.from(''));\n }\n\n override async getPublicKey(): Promise<PublicKey> {\n const network: NetworkType =\n this.network === 'mainnet' ? 'mainnet' : 'testnet';\n const mirror = new HederaMirrorNode(\n network,\n new Logger({ module: 'BrowserSigner' })\n );\n const anyKey: any = await mirror.getPublicKey(this.account.toString());\n const keyStr = typeof anyKey?.toString === 'function' ? anyKey.toString() : String(anyKey);\n return PublicKey.fromString(keyStr);\n }\n}\n\nexport default BrowserSigner;\n","import type { \n BaseLanguageModelCallOptions\n} from '@langchain/core/language_models/base';\nimport type { BaseChatModel } from '@langchain/core/language_models/chat_models';\n\n/**\n * Framework-agnostic AI provider interface for multi-framework support\n */\nexport interface AIProvider {\n /**\n * Generate a response from the AI model\n */\n generate(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): Promise<string>;\n\n /**\n * Stream a response from the AI model\n */\n stream?(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): AsyncGenerator<string>;\n\n /**\n * Get the underlying model if available\n */\n getModel?(): BaseChatModel | unknown;\n}\n\n/**\n * LangChain AI provider implementation\n */\nexport class LangChainProvider implements AIProvider {\n constructor(private model: BaseChatModel) {}\n\n async generate(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): Promise<string> {\n const result = await this.model.invoke(prompt, options);\n return typeof result === 'string' ? result : result.toString();\n }\n\n async *stream(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): AsyncGenerator<string> {\n const stream = await this.model.stream(prompt, options);\n for await (const chunk of stream) {\n yield typeof chunk === 'string' ? chunk : chunk.toString();\n }\n }\n\n getModel(): BaseChatModel {\n return this.model;\n }\n}\n\n/**\n * Vercel AI SDK provider interface (forward-thinking)\n */\nexport interface VercelAIProvider extends AIProvider {\n /**\n * Use Vercel AI SDK's streamText function\n */\n streamText?(prompt: string, options?: unknown): Promise<unknown>;\n}\n\n/**\n * BAML provider interface (forward-thinking)\n */\nexport interface BAMLProvider extends AIProvider {\n /**\n * Execute a BAML function\n */\n executeFunction?(\n name: string,\n args: Record<string, unknown>\n ): Promise<unknown>;\n}","export type WalletNetwork = 'mainnet' | 'testnet';\n\nexport interface WalletStatus {\n connected: boolean;\n accountId?: string;\n network?: WalletNetwork;\n}\n\nexport interface WalletExecutorResult {\n transactionId: string;\n}\n\nexport interface StartInscriptionResult {\n transactionBytes: string;\n tx_id?: string;\n topic_id?: string;\n status?: string;\n completed?: boolean;\n}\n\nexport interface WalletBridgeProvider {\n status: () => Promise<WalletStatus> | WalletStatus;\n executeBytes: (\n base64: string,\n network: WalletNetwork\n ) => Promise<WalletExecutorResult>;\n startInscription?: (\n request: Record<string, unknown>,\n network: WalletNetwork\n ) => Promise<StartInscriptionResult>;\n startHCS?: (\n op: string,\n request: Record<string, unknown>,\n network: WalletNetwork\n ) => Promise<{ transactionBytes: string }>;\n}\n\nlet providerRef: WalletBridgeProvider | null = null;\n\nexport function setWalletBridgeProvider(provider: WalletBridgeProvider): void {\n providerRef = provider;\n}\n\nexport function getWalletBridgeProvider(): WalletBridgeProvider | null {\n return providerRef;\n}\n","import {\n BasePlugin,\n type GenericPluginContext,\n BaseHederaQueryTool,\n type HederaAgentKit,\n type HederaTool,\n} from 'hedera-agent-kit';\nimport { z } from 'zod';\n\nconst PageSnapshotSchema = z.object({\n url: z.string().url(),\n maxCharacters: z\n .number()\n .int()\n .min(256, 'Minimum length is 256 characters')\n .max(8000, 'Maximum length is 8000 characters')\n .optional()\n .default(3000),\n});\n\nclass WebPageSnapshotTool extends BaseHederaQueryTool<typeof PageSnapshotSchema> {\n name = 'web_page_snapshot';\n description = 'Fetches the visible text content of a web page for analysis.';\n namespace = 'browser';\n specificInputSchema = PageSnapshotSchema;\n\n constructor(params: {\n hederaKit: HederaAgentKit;\n logger?: GenericPluginContext['logger'];\n fetchImpl?: typeof fetch;\n }) {\n const { fetchImpl, ...rest } = params;\n super(rest);\n this.fetchImpl = fetchImpl ?? fetch;\n }\n\n private readonly fetchImpl: typeof fetch;\n\n protected async executeQuery(\n input: z.infer<typeof PageSnapshotSchema>\n ): Promise<string> {\n const maxChars = input.maxCharacters ?? 3000;\n\n try {\n const response = await this.fetchImpl(input.url, {\n redirect: 'follow',\n });\n\n if (!response.ok) {\n return `Failed to load ${input.url}: HTTP ${response.status}`;\n }\n\n const html = await response.text();\n const text = this.normalizeHtml(html);\n\n if (!text) {\n return 'The fetched page did not contain readable text.';\n }\n\n return text.length > maxChars ? `${text.slice(0, maxChars)}…` : text;\n } catch (error) {\n this.logger.error('WebPageSnapshotTool failed', error);\n return `Failed to fetch content for ${input.url}: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n private normalizeHtml(html: string): string {\n const withoutScripts = html\n .replace(/<script[\\s\\S]*?<\\/script>/gi, ' ')\n .replace(/<style[\\s\\S]*?<\\/style>/gi, ' ')\n .replace(/<!--([\\s\\S]*?)-->/g, ' ');\n\n const stripped = withoutScripts.replace(/<[^>]+>/g, ' ');\n const decoded = stripped\n .replace(/&nbsp;/gi, ' ')\n .replace(/&amp;/gi, '&')\n .replace(/&lt;/gi, '<')\n .replace(/&gt;/gi, '>')\n .replace(/&quot;/gi, '\"')\n .replace(/&#39;/gi, \"'\");\n\n return decoded.replace(/\\s+/g, ' ').trim();\n }\n}\n\nexport class WebBrowserPlugin extends BasePlugin<GenericPluginContext> {\n id = 'web-browser';\n name = 'Web Browser Plugin';\n description =\n 'Provides tools for fetching live web page content to enrich assistant understanding.';\n version = '0.1.0';\n author = 'Hashgraph Online';\n namespace = 'browser';\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 | undefined;\n\n if (!hederaKit) {\n this.context.logger.warn(\n 'WebBrowserPlugin skipped because HederaAgentKit was not present in plugin context.'\n );\n this.tools = [];\n return;\n }\n\n const tool = new WebPageSnapshotTool({\n hederaKit,\n logger: this.context.logger,\n });\n\n this.tools = [tool];\n this.context.logger.info('Web Browser Plugin initialized with snapshot tool');\n }\n\n override getTools(): HederaTool[] {\n return this.tools;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n }\n}\n","export const getSystemMessage = (\n accountId?: string\n): string => `You are a helpful assistant managing Hashgraph Online HCS-10 connections, messages, HCS-2 registries, content inscription, and Hedera Hashgraph operations.\n\nYou have access to tools for:\n- HCS-10: registering agents, finding registered agents, initiating connections, listing active connections, sending messages over connections, and checking for new messages\n- HCS-2: creating registries, registering entries, updating entries, deleting entries, migrating registries, and querying registry contents\n- Inscription: inscribing content from URLs, files, or buffers, creating Hashinal NFTs, and retrieving inscriptions\n- Hedera Token Service (HTS): creating tokens, transferring tokens, airdropping tokens, and managing token operations\n\n\n*** IMPORTANT CONTEXT ***\nYou are currently operating as agent: ${accountId || 'unknown'} on the Hedera Hashgraph\nWhen users ask about \"my profile\", \"my account\", \"my connections\", etc., use this account ID: ${accountId || 'unknown'}\n\n*** CRITICAL ENTITY HANDLING RULES ***\n- When users refer to entities (tokens, topics, accounts) with pronouns like \"it\", \"that\", \"the token/topic\", etc., ALWAYS use the most recently created entity of that type\n- Entity IDs look like \"0.0.XXXXXX\" and are stored in memory after creation\n- NEVER use example or placeholder IDs like \"0.0.123456\" - always use actual created entity IDs\n- Account ID ${accountId} is NOT a token - tokens and accounts are different entities\n\n Remember the connection numbers when listing connections, as users might refer to them.`;\n","import { ContentStorage } from '../memory/content-storage';\nimport {\n ContentStoreService,\n extractReferenceId,\n shouldUseReference,\n ContentResolverRegistry,\n type ContentStoreInterface,\n type ContentResolverInterface,\n type ReferenceResolutionResult,\n} from '@hashgraphonline/standards-sdk';\nimport type {\n ContentReference,\n ContentReferenceConfig,\n ContentReferenceStats,\n} from '../types/content-reference';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * Content metadata interface for adapter compatibility\n */\ninterface AdapterContentMetadata {\n mimeType?: string;\n fileName?: string;\n sizeBytes?: number;\n [key: string]: unknown;\n}\n\n/**\n * Configuration interface for content storage\n */\ninterface ContentStoreConfig {\n maxSize?: number;\n enableCompression?: boolean;\n [key: string]: unknown;\n}\n\n/**\n * Adapter to make ContentStorage compatible with ContentStoreInterface\n */\nclass ContentStorageAdapter implements ContentStoreInterface {\n constructor(private storage: ContentStorage) {}\n\n async storeContent(\n content: Buffer,\n metadata: AdapterContentMetadata\n ): Promise<string> {\n const storeMetadata = {\n contentType: 'binary' as const,\n sizeBytes: content.length,\n source: 'system' as const,\n ...metadata,\n };\n const contentRef = await this.storage.storeContent(content, storeMetadata);\n return contentRef.referenceId;\n }\n\n async resolveReference(\n referenceId: string\n ): Promise<ReferenceResolutionResult> {\n const result = await this.storage.resolveReference(referenceId);\n if (result.success && result.content) {\n const response: ReferenceResolutionResult = {\n content: result.content,\n };\n if (result.metadata) {\n response.metadata = {\n ...(result.metadata.mimeType !== undefined && {\n mimeType: result.metadata.mimeType,\n }),\n ...(result.metadata.fileName !== undefined && {\n fileName: result.metadata.fileName,\n }),\n originalSize: result.metadata.sizeBytes,\n };\n }\n return response;\n } else {\n throw new Error(result.error || 'Reference not found');\n }\n }\n\n async hasReference(referenceId: string): Promise<boolean> {\n return await this.storage.hasReference(referenceId);\n }\n\n async cleanupReference(referenceId: string): Promise<void> {\n await this.storage.cleanupReference(referenceId);\n }\n\n async getStats(): Promise<unknown> {\n return await this.storage.getStats();\n }\n\n async updateConfig(config: ContentStoreConfig): Promise<void> {\n const referenceConfig = {\n sizeThresholdBytes: config.maxSize || 10240,\n enableAutoCleanup: config.enableCompression || true,\n ...config,\n };\n return await this.storage.updateConfig(referenceConfig);\n }\n\n async performCleanup(): Promise<void> {\n await this.storage.performCleanup();\n }\n\n async dispose(): Promise<void> {\n return Promise.resolve(this.storage.dispose());\n }\n}\n\n/**\n * Content resolver implementation for dependency injection\n */\nclass ContentResolver implements ContentResolverInterface {\n constructor(private adapter: ContentStorageAdapter) {}\n\n async resolveReference(\n referenceId: string\n ): Promise<ReferenceResolutionResult> {\n return await this.adapter.resolveReference(referenceId);\n }\n\n shouldUseReference(content: string | Buffer): boolean {\n return shouldUseReference(content);\n }\n\n extractReferenceId(input: string): string | null {\n return extractReferenceId(input);\n }\n}\n\n/**\n * Manages content store lifecycle and cross-package registration\n */\nexport class ContentStoreManager {\n private contentStorage: ContentStorage;\n private adapter: ContentStorageAdapter;\n private resolver: ContentResolver;\n private logger: Logger;\n protected isRegistered = false;\n\n constructor(\n maxMessageStorage: number = 1000,\n referenceConfig?: Partial<ContentReferenceConfig>,\n logger?: Logger\n ) {\n this.logger = logger || new Logger({ module: 'ContentStoreManager' });\n\n this.contentStorage = new ContentStorage(\n maxMessageStorage,\n referenceConfig\n );\n this.adapter = new ContentStorageAdapter(this.contentStorage);\n this.resolver = new ContentResolver(this.adapter);\n }\n\n /**\n * Initialize and register content storage for cross-package access\n */\n async initialize(): Promise<void> {\n if (this.isRegistered) {\n this.logger.warn('ContentStoreManager is already initialized');\n return;\n }\n\n try {\n if (\n ContentStoreService &&\n typeof (ContentStoreService as unknown as { setInstance?: Function }).setInstance === 'function'\n ) {\n await (ContentStoreService as unknown as { setInstance: (adapter: unknown) => Promise<void> }).setInstance(\n this.adapter\n );\n } else {\n this.logger.warn('ContentStoreService.setInstance is unavailable; skipping registration');\n }\n if (\n ContentResolverRegistry &&\n typeof (ContentResolverRegistry as unknown as { register?: Function }).register === 'function'\n ) {\n (ContentResolverRegistry as unknown as { register: (resolver: unknown) => void }).register(\n this.resolver\n );\n } else {\n this.logger.warn('ContentResolverRegistry.register is unavailable; skipping registration');\n }\n this.isRegistered = true;\n this.logger.info(\n 'ContentStoreManager initialized and registered for cross-package access'\n );\n } catch (error) {\n this.logger.error('Failed to initialize ContentStoreManager:', error);\n throw error;\n }\n }\n\n /**\n * Get the underlying ContentStorage instance\n */\n getContentStorage(): ContentStorage {\n return this.contentStorage;\n }\n\n /**\n * Get storage statistics\n */\n async getStats(): Promise<ContentReferenceStats> {\n return await this.contentStorage.getStats();\n }\n\n /**\n * Update configuration\n */\n async updateConfig(config: Partial<ContentReferenceConfig>): Promise<void> {\n return await this.contentStorage.updateConfig(config);\n }\n\n /**\n * Perform manual cleanup\n */\n async performCleanup(): Promise<{ cleanedUp: number; errors: string[] }> {\n return await this.contentStorage.performCleanup();\n }\n\n /**\n * Check if content should be stored as reference\n */\n shouldUseReference(content: Buffer | string): boolean {\n return this.contentStorage.shouldUseReference(content);\n }\n\n /**\n * Store content if it's large enough\n */\n async storeContentIfLarge(\n content: Buffer | string,\n metadata: AdapterContentMetadata\n ): Promise<ContentReference | null> {\n const storeMetadata = {\n source: 'system' as const,\n contentType: 'binary' as const,\n ...metadata,\n };\n return await this.contentStorage.storeContentIfLarge(\n content,\n storeMetadata\n );\n }\n\n /**\n * Cleanup and unregister\n */\n async dispose(): Promise<void> {\n if (this.isRegistered) {\n this.contentStorage.dispose();\n if (\n ContentStoreService &&\n typeof (ContentStoreService as unknown as { dispose?: Function }).dispose === 'function'\n ) {\n (ContentStoreService as unknown as { dispose: () => void }).dispose();\n }\n if (\n ContentResolverRegistry &&\n typeof (ContentResolverRegistry as unknown as { unregister?: Function }).unregister === 'function'\n ) {\n (ContentResolverRegistry as unknown as { unregister: () => void }).unregister();\n }\n this.isRegistered = false;\n this.logger.info('ContentStoreManager disposed and unregistered');\n }\n }\n\n /**\n * Check if the manager is initialized\n */\n isInitialized(): boolean {\n return this.isRegistered;\n }\n}\n","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { ChatOpenAI } from '@langchain/openai';\nimport { ChatAnthropic } from '@langchain/anthropic';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\nconst logger = new Logger({ module: 'EntityResolverTool' });\n\nconst ResolveEntitiesSchema = z.object({\n message: z.string().describe('The message containing entity references to resolve'),\n entities: z.array(z.object({\n entityId: z.string(),\n entityName: z.string(),\n entityType: z.string(),\n })).describe('Available entities in memory'),\n});\n\nconst ExtractEntitiesSchema = z.object({\n response: z.string().describe('Agent response text to extract entities from'),\n userMessage: z.string().describe('Original user message for context'),\n});\n\nexport class ResolveEntitiesTool extends StructuredTool {\n name = 'resolve_entities';\n description = 'Resolves entity references like \"the topic\", \"it\", \"that\" to actual entity IDs';\n schema = ResolveEntitiesSchema;\n \n private llm: ChatOpenAI | ChatAnthropic;\n \n constructor(llm: ChatOpenAI | ChatAnthropic) {\n super();\n this.llm = llm;\n }\n \n async _call(input: z.infer<typeof ResolveEntitiesSchema>): Promise<string> {\n const { message, entities } = input;\n \n if (!entities || entities.length === 0) {\n return message;\n }\n \n const byType = this.groupEntitiesByType(entities);\n const context = this.buildEntityContext(byType);\n \n const prompt = `Task: Replace entity references with IDs.\n\n${context}\n\nMessage: \"${message}\"\n\nRules:\n- \"the topic\" or \"that topic\" → replace with most recent topic ID\n- \"the token\" or \"that token\" → replace with most recent token ID\n- \"it\" or \"that\" after action verb → replace with most recent entity ID\n- \"airdrop X\" without token ID → add most recent token ID as first parameter\n- Token operations without explicit token → use most recent token ID\n\nExamples:\n- \"submit on the topic\" → \"submit on 0.0.6543472\"\n- \"airdrop the token\" → \"airdrop 0.0.123456\"\n- \"airdrop 10 to 0.0.5842697\" → \"airdrop 0.0.123456 10 to 0.0.5842697\"\n- \"mint 100\" → \"mint 0.0.123456 100\"\n\nReturn ONLY the resolved message:`;\n \n try {\n const response = await this.llm.invoke(prompt);\n return (response.content as string).trim();\n } catch (error) {\n logger.error('ResolveEntitiesTool failed:', error);\n return message;\n }\n }\n \n private groupEntitiesByType(entities: EntityGroup): GroupedEntities {\n return entities.reduce((acc, entity) => {\n if (!acc[entity.entityType]) {\n acc[entity.entityType] = [];\n }\n acc[entity.entityType].push(entity);\n return acc;\n }, {} as GroupedEntities);\n }\n \n private buildEntityContext(groupedEntities: GroupedEntities): string {\n let context = 'Available entities:\\n';\n for (const [type, list] of Object.entries(groupedEntities)) {\n const recent = list[0];\n context += `- Most recent ${type}: \"${recent.entityName}\" = ${recent.entityId}\\n`;\n }\n return context;\n }\n}\n\nexport class ExtractEntitiesTool extends StructuredTool {\n name = 'extract_entities';\n description = 'Extracts newly created entities from agent responses';\n schema = ExtractEntitiesSchema;\n \n private llm: ChatOpenAI | ChatAnthropic;\n \n constructor(llm: ChatOpenAI | ChatAnthropic) {\n super();\n this.llm = llm;\n }\n \n async _call(input: z.infer<typeof ExtractEntitiesSchema>): Promise<string> {\n const { response, userMessage } = input;\n \n const prompt = `Extract ONLY newly created entities from this response.\n\nUser asked: \"${userMessage.substring(0, 200)}\"\nResponse: ${response.substring(0, 3000)}\n\nLook for:\n- Success messages with new entity IDs\n- Words like \"created\", \"new\", \"successfully\" followed by entity IDs\n\nReturn JSON array of created entities:\n[{\"id\": \"0.0.XXX\", \"name\": \"name\", \"type\": \"topic|token|account\"}]\n\nIf none created, return: []\n\nJSON:`;\n \n try {\n const llmResponse = await this.llm.invoke(prompt);\n const content = llmResponse.content as string;\n const match = content.match(/\\[[\\s\\S]*?\\]/);\n if (match) {\n return match[0];\n }\n return '[]';\n } catch (error) {\n logger.error('ExtractEntitiesTool failed:', error);\n return '[]';\n }\n }\n}\n\nexport function createEntityTools(\n llm: ChatOpenAI | ChatAnthropic\n): {\n resolveEntities: ResolveEntitiesTool;\n extractEntities: ExtractEntitiesTool;\n} {\n return {\n resolveEntities: new ResolveEntitiesTool(llm),\n extractEntities: new ExtractEntitiesTool(llm),\n };\n}\n\ninterface EntityReference {\n entityId: string;\n entityName: string;\n entityType: string;\n}\n\ntype EntityGroup = EntityReference[];\n\ntype GroupedEntities = Record<string, EntityGroup>;\n","import { EntityFormat, FormatConverter, ConversionContext } from './types';\nimport {\n HederaMirrorNode,\n Logger,\n NetworkType,\n} from '@hashgraphonline/standards-sdk';\n\ninterface CacheEntry {\n format: EntityFormat;\n timestamp: number;\n ttl: number;\n}\n\n/**\n * Registry for format converters that handles entity transformation\n */\nexport class FormatConverterRegistry {\n private converters = new Map<string, FormatConverter<unknown, unknown>>();\n private entityTypeCache = new Map<string, CacheEntry>();\n private logger = new Logger({ module: 'FormatConverterRegistry' });\n private defaultCacheTTL = 5 * 60 * 1000;\n\n /**\n * Register a format converter\n */\n register<TSource, TTarget>(\n converter: FormatConverter<TSource, TTarget>\n ): void {\n const key = `${converter.sourceFormat}→${converter.targetFormat}`;\n this.converters.set(key, converter as FormatConverter<unknown, unknown>);\n }\n\n /**\n * Find a converter for the given source and target formats\n */\n findConverter(\n source: EntityFormat,\n target: EntityFormat\n ): FormatConverter<unknown, unknown> | null {\n const key = `${source}→${target}`;\n return this.converters.get(key) || null;\n }\n\n /**\n * Convert an entity to the target format\n */\n async convertEntity(\n entity: string,\n target: EntityFormat,\n context: ConversionContext\n ): Promise<string> {\n const sourceFormat = await this.detectFormatWithFallback(entity, context);\n if (sourceFormat === target) {\n return entity;\n }\n\n const converter = this.findConverter(sourceFormat, target);\n if (!converter) {\n throw new Error(`No converter found for ${sourceFormat} → ${target}`);\n }\n\n if (!converter.canConvert(entity, context)) {\n throw new Error(`Converter cannot handle entity: ${entity}`);\n }\n\n const result = await converter.convert(entity, context);\n return result as string;\n }\n\n /**\n * Detect the format of an entity string with API-based verification and fallback\n */\n private async detectFormatWithFallback(\n entity: string,\n context?: ConversionContext\n ): Promise<EntityFormat> {\n if (entity.startsWith('hcs://')) {\n return EntityFormat.HRL;\n }\n\n if (/^0\\.0\\.\\d+$/.test(entity)) {\n const cached = this.getCachedFormat(entity);\n if (cached) {\n return cached;\n }\n\n try {\n const detected = await this.detectFormat(entity, context || {});\n if (detected !== EntityFormat.ANY) {\n this.setCachedFormat(entity, detected);\n return detected;\n }\n } catch (error) {\n this.logger.warn(\n `Entity detection failed for ${entity}, using fallback: ${\n (error as Error).message\n }`\n );\n }\n\n return EntityFormat.ANY;\n }\n\n return EntityFormat.ANY;\n }\n\n /**\n * Public helper: detect entity format (ACCOUNT_ID, TOKEN_ID, TOPIC_ID, HRL, or ANY)\n */\n async detectEntityFormat(\n entity: string,\n context?: ConversionContext\n ): Promise<EntityFormat> {\n return this.detectFormatWithFallback(entity, context);\n }\n\n /**\n * Detect entity format via Hedera Mirror Node API calls\n */\n private async detectFormat(\n entity: string,\n context: ConversionContext\n ): Promise<EntityFormat> {\n const networkType = (context.networkType as NetworkType) || 'testnet';\n const mirrorNode = new HederaMirrorNode(networkType, this.logger);\n\n mirrorNode.configureRetry({\n maxRetries: 3,\n maxDelayMs: 1000,\n });\n\n const checks = await Promise.allSettled([\n mirrorNode\n .getAccountBalance(entity)\n .then((result) => (result !== null ? EntityFormat.ACCOUNT_ID : null))\n .catch(() => null),\n\n mirrorNode\n .getTokenInfo(entity)\n .then((result) => (result !== null ? EntityFormat.TOKEN_ID : null))\n .catch(() => null),\n\n mirrorNode\n .getTopicInfo(entity)\n .then((result) => (result !== null ? EntityFormat.TOPIC_ID : null))\n .catch(() => null),\n\n mirrorNode\n .getContract(entity)\n .then((result) => (result !== null ? EntityFormat.CONTRACT_ID : null))\n .catch(() => null),\n ]);\n\n const successful = checks.find(\n (result) => result.status === 'fulfilled' && result.value !== null\n );\n\n return successful && successful.status === 'fulfilled'\n ? (successful.value as EntityFormat)\n : EntityFormat.ANY;\n }\n\n /**\n * Get cached entity format if valid\n */\n private getCachedFormat(entity: string): EntityFormat | null {\n const entry = this.entityTypeCache.get(entity);\n if (!entry || this.isCacheExpired(entry)) {\n this.entityTypeCache.delete(entity);\n return null;\n }\n return entry.format;\n }\n\n /**\n * Set cached entity format\n */\n private setCachedFormat(entity: string, format: EntityFormat): void {\n this.entityTypeCache.set(entity, {\n format,\n timestamp: Date.now(),\n ttl: this.defaultCacheTTL,\n });\n }\n\n /**\n * Check if cache entry is expired\n */\n private isCacheExpired(entry: CacheEntry): boolean {\n return Date.now() - entry.timestamp > entry.ttl;\n }\n\n /**\n * Get all registered converters\n */\n getRegisteredConverters(): Array<{\n source: EntityFormat;\n target: EntityFormat;\n }> {\n return Array.from(this.converters.keys()).map((key) => {\n const [source, target] = key.split('→');\n return {\n source: source as EntityFormat,\n target: target as EntityFormat,\n };\n });\n }\n\n /**\n * Check if a converter exists for the given formats\n */\n hasConverter(source: EntityFormat, target: EntityFormat): boolean {\n return this.findConverter(source, target) !== null;\n }\n\n /**\n * Clear all registered converters\n */\n clear(): void {\n this.converters.clear();\n }\n\n /**\n * Clear entity type cache\n */\n clearCache(): void {\n this.entityTypeCache.clear();\n }\n}\n","import { EntityFormat, FormatConverter, ConversionContext } from '../types';\n\n/**\n * Converts Hedera topic IDs to HRL format for consensus service messages\n */\nexport class TopicIdToHrlConverter implements FormatConverter<string, string> {\n sourceFormat = EntityFormat.TOPIC_ID;\n targetFormat = EntityFormat.HRL;\n\n /**\n * Check if the source string is a valid topic ID\n */\n canConvert(source: string, _context: ConversionContext): boolean {\n return /^0\\.0\\.\\d+$/.test(source);\n }\n\n /**\n * Convert topic ID to HRL format based on network type\n */\n async convert(topicId: string, context: ConversionContext): Promise<string> {\n const networkType = context.networkType || 'testnet';\n const networkId = networkType === 'mainnet' ? '0' : '1';\n return `hcs://${networkId}/${topicId}`;\n }\n}\n","import {\n EntityFormat,\n type FormatConverter,\n type ConversionContext,\n} from '../types';\nimport {\n HederaMirrorNode,\n HRLResolver,\n type NetworkType,\n} from '@hashgraphonline/standards-sdk';\n\n/**\n * Generic converter that normalizes various string entity references (cdn urls, content-ref, raw topic id)\n * into canonical HRL. It declares source ANY -> HRL and internally short-circuits if unsupported.\n */\nexport class StringNormalizationConverter\n implements FormatConverter<string, string>\n{\n sourceFormat = EntityFormat.ANY;\n targetFormat = EntityFormat.HRL;\n\n private static standardCache: Map<string, string> = new Map();\n\n canConvert(source: string, _context: ConversionContext): boolean {\n if (typeof source !== 'string') {\n return false;\n }\n if (/^hcs:\\/\\/\\d\\/0\\.0\\.\\d+$/i.test(source)) {\n return false;\n }\n if (/inscription-cdn\\/(0\\.0\\.\\d+)/i.test(source)) {\n return true;\n }\n if (/^content-ref:(0\\.0\\.\\d+)$/i.test(source)) {\n return true;\n }\n if (/^0\\.0\\.\\d+$/.test(source)) {\n const hasPreference = Boolean(\n (_context as unknown as { toolPreferences?: Record<string, string> })\n ?.toolPreferences?.inscription === 'hrl' ||\n (_context as unknown as { toolPreferences?: Record<string, string> })\n ?.toolPreferences?.topic === 'hrl'\n );\n return hasPreference;\n }\n return false;\n }\n\n async convert(source: string, context: ConversionContext): Promise<string> {\n const toolPrefs = (\n context as unknown as { toolPreferences?: Record<string, string> }\n ).toolPreferences;\n const fallbackStandard =\n toolPrefs?.hrlStandard || toolPrefs?.inscriptionHrlStandard || '1';\n const networkType = (context.networkType as string) || 'testnet';\n\n const resolver = new HRLResolver();\n\n const cdnMatch = source.match(/inscription-cdn\\/(0\\.0\\.\\d+)/i);\n if (cdnMatch && cdnMatch[1]) {\n try {\n const mirror = new HederaMirrorNode(networkType as NetworkType);\n mirror.configureRetry({\n maxRetries: 3,\n maxDelayMs: 1000,\n });\n const resolved = await mirror.getTopicInfo(cdnMatch[1]);\n const memo = (resolved && (resolved as { memo?: string }).memo) || '';\n const match = memo.match(/^hcs-(\\d+)/);\n const standard = match && match[1] ? match[1] : '1';\n return `hcs://${standard}/${cdnMatch[1]}`;\n } catch {\n return `hcs://${fallbackStandard}/${cdnMatch[1]}`;\n }\n }\n\n const contentRefMatch = source.match(/^content-ref:(0\\.0\\.\\d+)$/i);\n if (contentRefMatch && contentRefMatch[1]) {\n try {\n const resolved = await resolver.resolve(contentRefMatch[1], {\n network: networkType as NetworkType,\n });\n const parsed = resolver.parseHRL(`hcs://1/${resolved.topicId}`);\n const std = parsed?.standard || fallbackStandard;\n return `hcs://${std}/${resolved.topicId}`;\n } catch {\n return `hcs://${fallbackStandard}/${contentRefMatch[1]}`;\n }\n }\n\n if (/^0\\.0\\.\\d+$/.test(source)) {\n try {\n const resolved = await resolver.resolve(source, {\n network: networkType as NetworkType,\n });\n const parsed = resolver.parseHRL(`hcs://1/${resolved.topicId}`);\n const std = parsed?.standard || fallbackStandard;\n return `hcs://${std}/${resolved.topicId}`;\n } catch {\n return `hcs://${fallbackStandard}/${source}`;\n }\n }\n\n return source;\n }\n}\n","import { Logger, type NetworkType } from '@hashgraphonline/standards-sdk';\nimport { EntityFormat, FormatConverterRegistry } from './formatters';\nimport type { EntityAssociation } from '../memory/smart-memory-manager';\n\n/**\n * Service for processing tool parameters and applying entity format conversions\n */\nexport class ParameterService {\n private logger: Logger;\n private formatConverterRegistry: FormatConverterRegistry;\n private networkType: NetworkType;\n\n constructor(\n formatConverterRegistry: FormatConverterRegistry,\n networkType: NetworkType\n ) {\n this.logger = new Logger({ module: 'ParameterService' });\n this.formatConverterRegistry = formatConverterRegistry;\n this.networkType = networkType;\n }\n\n /**\n * Unified preprocessing entrypoint (DRY):\n * - Optional AI-driven resolution via provided entityResolver\n * - Deterministic post-pass for safe format enforcement\n */\n async preprocessParameters(\n toolName: string,\n parameters: Record<string, unknown>,\n entities: EntityAssociation[] = [],\n options?: {\n entityResolver?: {\n resolveReferences: (\n message: string,\n entities: EntityAssociation[]\n ) => Promise<string>;\n };\n sessionId?: string;\n preferences?: Record<string, string>;\n }\n ): Promise<Record<string, unknown>> {\n const sessionId = options?.sessionId;\n const entityResolver = options?.entityResolver;\n const preferences = options?.preferences;\n\n let working: Record<string, unknown> = { ...parameters };\n\n if (entityResolver && entities.length > 0) {\n try {\n this.logger.info('AI-driven preprocessing phase', {\n toolName,\n entityCount: entities.length,\n sessionId,\n });\n\n const aiProcessed: Record<string, unknown> = { ...working };\n for (const [paramName, paramValue] of Object.entries(working)) {\n if (typeof paramValue === 'string') {\n const resolved = await entityResolver.resolveReferences(\n paramValue,\n entities\n );\n const converted = await this.convertParameterEntities(\n resolved,\n entities,\n preferences\n );\n aiProcessed[paramName] = converted;\n } else if (Array.isArray(paramValue)) {\n const out: unknown[] = [];\n for (const item of paramValue) {\n if (typeof item === 'string') {\n const resolved = await entityResolver.resolveReferences(\n item,\n entities\n );\n const converted = await this.convertParameterEntities(\n resolved,\n entities,\n preferences\n );\n out.push(converted);\n } else {\n out.push(item);\n }\n }\n aiProcessed[paramName] = out;\n }\n }\n working = aiProcessed;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'unknown';\n this.logger.warn(\n 'AI phase failed; continuing with deterministic pass',\n {\n toolName,\n error: message,\n }\n );\n }\n }\n\n try {\n const processed: Record<string, unknown> = { ...working };\n for (const [paramName, paramValue] of Object.entries(working)) {\n if (typeof paramValue === 'string') {\n const converted = await this.convertParameterEntities(\n paramValue,\n entities,\n preferences\n );\n processed[paramName] = converted;\n } else if (Array.isArray(paramValue)) {\n const out: unknown[] = [];\n for (const item of paramValue) {\n if (typeof item === 'string') {\n const converted = await this.convertParameterEntities(\n item,\n entities,\n preferences\n );\n out.push(converted);\n } else {\n out.push(item);\n }\n }\n processed[paramName] = out;\n }\n }\n working = processed;\n } catch (e) {\n this.logger.warn('Deterministic post-pass failed', {\n toolName,\n error: e instanceof Error ? e.message : 'unknown',\n });\n }\n\n return working;\n }\n\n /**\n * Attach unified preprocessing callback directly to the agent.\n */\n attachToAgent(\n agent: unknown,\n deps?: {\n getSessionId?: () => string | null;\n getEntities?: (sessionId: string | null) => Promise<EntityAssociation[]>;\n entityResolver?: {\n resolveReferences: (\n message: string,\n entities: EntityAssociation[]\n ) => Promise<string>;\n };\n }\n ): void {\n const getSessionId = deps?.getSessionId ?? (() => null);\n const getEntities =\n deps?.getEntities ?? (async () => [] as EntityAssociation[]);\n const entityResolver = deps?.entityResolver;\n\n const maybe = agent as {\n setParameterPreprocessingCallback?: (\n callback: (\n toolName: string,\n parameters: Record<string, unknown>,\n toolContext?: {\n entityResolutionPreferences?: Record<string, string>;\n }\n ) => Promise<Record<string, unknown>>\n ) => void;\n getAgent?: () => unknown;\n };\n\n const attach = (target: unknown): boolean => {\n const t = target as {\n setParameterPreprocessingCallback?: (\n callback: (\n toolName: string,\n parameters: Record<string, unknown>,\n toolContext?: {\n entityResolutionPreferences?: Record<string, string>;\n }\n ) => Promise<Record<string, unknown>>\n ) => void;\n };\n if (typeof t.setParameterPreprocessingCallback === 'function') {\n t.setParameterPreprocessingCallback(\n async (\n toolName: string,\n parameters: Record<string, unknown>\n ): Promise<Record<string, unknown>> => {\n const sessionId = getSessionId();\n const entities = await getEntities(sessionId);\n const opts: {\n entityResolver?: {\n resolveReferences: (\n message: string,\n entities: EntityAssociation[]\n ) => Promise<string>;\n };\n sessionId?: string;\n preferences?: Record<string, string>;\n } = {};\n if (entityResolver) {\n opts.entityResolver = entityResolver;\n }\n if (sessionId) {\n opts.sessionId = sessionId;\n }\n return this.preprocessParameters(toolName, parameters, entities, opts);\n }\n );\n this.logger.info('Parameter preprocessing callback attached');\n return true;\n }\n return false;\n };\n\n if (!attach(agent) && typeof maybe.getAgent === 'function') {\n const underlying = maybe.getAgent();\n if (underlying) {\n void attach(underlying);\n }\n }\n }\n\n /**\n * Preprocess tool parameters by applying format conversions based on tool's entity resolution preferences\n */\n async preprocessToolParameters(\n toolName: string,\n parameters: Record<string, unknown>,\n entities?: EntityAssociation[],\n sessionId?: string\n ): Promise<Record<string, unknown>> {\n try {\n if (!entities || entities.length === 0) {\n this.logger.info(\n 'Tool parameter preprocessing skipped - no entities provided:',\n {\n toolName,\n originalParams: Object.keys(parameters),\n }\n );\n return parameters;\n }\n\n const processedParameters = { ...parameters };\n const preferences: Record<string, string> | undefined = undefined;\n let hasChanges = false;\n\n for (const [paramName, paramValue] of Object.entries(parameters)) {\n if (typeof paramValue === 'string') {\n const convertedValue = await this.convertParameterEntities(\n paramValue,\n entities,\n preferences\n );\n\n if (convertedValue !== paramValue) {\n processedParameters[paramName] = convertedValue;\n hasChanges = true;\n\n this.logger.info('Parameter entity conversion applied:', {\n toolName,\n paramName,\n original: paramValue,\n converted: convertedValue,\n });\n }\n } else if (Array.isArray(paramValue)) {\n const originalArray = paramValue as unknown[];\n const convertedArray: unknown[] = [];\n let arrayChanged = false;\n\n for (const item of originalArray) {\n if (typeof item === 'string') {\n const convertedItem = await this.convertParameterEntities(\n item,\n entities,\n preferences\n );\n\n convertedArray.push(convertedItem);\n\n if (convertedItem !== item) {\n arrayChanged = true;\n this.logger.info('Parameter array item conversion applied:', {\n toolName,\n paramName,\n original: item,\n converted: convertedItem,\n });\n }\n } else {\n convertedArray.push(item);\n }\n }\n\n if (arrayChanged) {\n processedParameters[paramName] = convertedArray;\n hasChanges = true;\n }\n }\n }\n\n this.logger.info('Tool parameter preprocessing completed:', {\n toolName,\n originalParams: Object.keys(parameters),\n hasChanges,\n sessionId,\n });\n\n return processedParameters;\n } catch (error) {\n this.logger.warn('Tool parameter preprocessing failed:', {\n toolName,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n return parameters;\n }\n }\n\n /**\n * Convert entity references in a parameter value based on tool preferences\n */\n async convertParameterEntities(\n parameterValue: string,\n entities: EntityAssociation[],\n preferences?: Record<string, string>\n ): Promise<string> {\n let convertedValue = parameterValue;\n\n for (const entity of entities) {\n const containsEntityId = convertedValue.includes(entity.entityId);\n const containsEntityName = convertedValue.includes(entity.entityName);\n\n if (!containsEntityId && !containsEntityName) {\n continue;\n }\n\n let targetFormat: EntityFormat | null = null;\n\n if (entity.entityType === EntityFormat.TOPIC_ID) {\n if (\n preferences?.inscription === 'hrl' ||\n preferences?.topic === 'hrl'\n ) {\n targetFormat = EntityFormat.HRL;\n } else if (\n preferences?.inscription === 'topicId' ||\n preferences?.topic === 'topicId'\n ) {\n targetFormat = EntityFormat.TOPIC_ID;\n }\n } else if (entity.entityType === EntityFormat.TOKEN_ID) {\n if (preferences?.token === 'tokenId') {\n targetFormat = EntityFormat.TOKEN_ID;\n } else if (preferences?.token === 'symbol') {\n targetFormat = EntityFormat.SYMBOL;\n }\n } else if (entity.entityType === EntityFormat.ACCOUNT_ID) {\n if (\n preferences?.account === 'accountId' ||\n preferences?.supplyKey === 'accountId' ||\n preferences?.adminKey === 'accountId'\n ) {\n targetFormat = EntityFormat.ACCOUNT_ID;\n } else if (preferences?.account === 'alias') {\n targetFormat = EntityFormat.ALIAS;\n }\n }\n\n if (targetFormat) {\n try {\n const context: {\n networkType?: string | NetworkType;\n sessionId?: string;\n toolPreferences?: Record<string, string>;\n } = {\n networkType: this.networkType,\n sessionId: 'unknown',\n };\n if (preferences) {\n context.toolPreferences = preferences;\n }\n const convertedEntityValue = await this.formatConverterRegistry.convertEntity(\n entity.entityId,\n targetFormat,\n context as never\n );\n\n if (containsEntityId) {\n convertedValue = convertedValue.replace(\n new RegExp(`\\\\b${entity.entityId.replace(/\\./g, '\\\\.')}\\\\b`, 'g'),\n convertedEntityValue\n );\n }\n\n if (containsEntityName) {\n convertedValue = convertedValue.replace(\n new RegExp(\n `\\\\b${entity.entityName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\b`,\n 'g'\n ),\n convertedEntityValue\n );\n }\n\n this.logger.info('Applied format conversion to parameter:', {\n entityId: entity.entityId,\n entityType: entity.entityType,\n targetFormat,\n convertedValue: convertedEntityValue,\n parameterValue: convertedValue,\n });\n } catch (error) {\n this.logger.warn('Format conversion failed for parameter:', {\n entityId: entity.entityId,\n targetFormat,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n }\n\n return convertedValue;\n }\n}\n","import {\n ServerSigner,\n getAllHederaCorePlugins,\n BasePlugin,\n AbstractSigner,\n} from 'hedera-agent-kit';\nimport { Logger, type NetworkType } from '@hashgraphonline/standards-sdk';\nimport { createAgent } from './agent-factory';\nimport BrowserSigner from './signers/browser-signer';\nimport { LangChainProvider } from './providers';\nimport type { ChatResponse, ConversationContext } from './base-agent';\nimport { ChatOpenAI } from '@langchain/openai';\nimport { ChatAnthropic } from '@langchain/anthropic';\nimport {\n HumanMessage,\n AIMessage,\n SystemMessage,\n} from '@langchain/core/messages';\nimport type { AgentOperationalMode, MirrorNodeConfig } from 'hedera-agent-kit';\nimport { HCS10Plugin } from './plugins/hcs-10/HCS10Plugin';\nimport { HCS2Plugin } from './plugins/hcs-2/HCS2Plugin';\nimport { InscribePlugin } from './plugins/inscribe/InscribePlugin';\nimport { getWalletBridgeProvider } from './runtime/wallet-bridge';\nimport {\n InscriberBuilder,\n SignerProviderRegistry,\n} from '@hashgraphonline/standards-agent-kit';\nimport { HbarPlugin } from './plugins/hbar/HbarPlugin';\nimport { WebBrowserPlugin } from './plugins/web-browser/WebBrowserPlugin';\nimport { OpenConvaiState } from '@hashgraphonline/standards-agent-kit';\nimport type { IStateManager } from '@hashgraphonline/standards-agent-kit';\nimport { getSystemMessage } from './config/system-message';\nimport type { MCPServerConfig, MCPConnectionStatus } from './mcp/types';\nimport { ContentStoreManager } from './services/content-store-manager';\nimport { SmartMemoryManager, type SmartMemoryConfig } from './memory';\nimport {\n createEntityTools,\n ResolveEntitiesTool,\n ExtractEntitiesTool,\n} from './tools/entity-resolver-tool';\nimport type { FormSubmission } from './forms/types';\nimport { ParameterService } from './services/parameter-service';\nimport { FormatConverterRegistry } from './services/formatters/format-converter-registry';\nimport { TopicIdToHrlConverter } from './services/formatters/converters/topic-id-to-hrl-converter';\nimport { StringNormalizationConverter } from './services/formatters/converters/string-normalization-converter';\n\nexport type ToolDescriptor = {\n name: string;\n namespace?: string;\n};\n\nexport type ChatHistoryItem = {\n type: 'human' | 'ai' | 'system';\n content: string;\n};\n\nexport type AgentInstance = ReturnType<typeof createAgent>;\n\nexport type MirrorNetwork = 'testnet' | 'mainnet' | 'previewnet';\n\nconst DEFAULT_MODEL_NAME = 'gpt-4o';\nconst DEFAULT_OPENAI_MODEL = 'gpt-4o-mini';\nconst DEFAULT_OPENROUTER_MODEL = 'openai/gpt-4o-mini';\nconst DEFAULT_CLAUDE_MODEL = 'claude-3-7-sonnet-latest';\nconst DEFAULT_TEMPERATURE = 0.1;\nconst DEFAULT_NETWORK = 'testnet';\nconst DEFAULT_OPERATIONAL_MODE: AgentOperationalMode = 'autonomous';\n\nexport interface ConversationalAgentOptions {\n accountId: string;\n privateKey: string;\n network?: NetworkType;\n openAIApiKey: string;\n openAIModelName?: string;\n llmProvider?: 'openai' | 'anthropic' | 'openrouter';\n verbose?: boolean;\n operationalMode?: AgentOperationalMode;\n userAccountId?: string;\n customSystemMessagePreamble?: string;\n customSystemMessagePostamble?: string;\n additionalPlugins?: BasePlugin[];\n stateManager?: IStateManager;\n scheduleUserTransactionsInBytesMode?: boolean;\n mirrorNodeConfig?: MirrorNodeConfig;\n disableLogging?: boolean;\n enabledPlugins?: string[];\n disabledPlugins?: string[];\n toolFilter?: (tool: { name: string; namespace?: string }) => boolean;\n mcpServers?: MCPServerConfig[];\n walletExecutor?: (\n base64: string,\n network: 'mainnet' | 'testnet'\n ) => Promise<{ transactionId: string }>;\n /** Optional: provide a signer factory to override default signer selection */\n customSignerFactory?: (args: {\n operationalMode: AgentOperationalMode;\n accountId: string;\n network: NetworkType;\n }) => AbstractSigner;\n\n /** Enable automatic entity memory functionality (default: true) */\n entityMemoryEnabled?: boolean;\n\n /** Configuration for entity memory system */\n entityMemoryConfig?: SmartMemoryConfig;\n\n /**\n * Provider used for entity extraction/resolution tools (defaults to llmProvider or 'openai')\n */\n entityMemoryProvider?: 'openai' | 'anthropic' | 'openrouter';\n\n /**\n * Model name for entity extraction/resolution tools (defaults per provider)\n */\n entityMemoryModelName?: string;\n\n openRouterApiKey?: string;\n openRouterBaseURL?: string;\n}\n\n/**\n * The ConversationalAgent class is an optional wrapper around the HederaConversationalAgent class,\n * which includes the OpenConvAIPlugin and the OpenConvaiState by default.\n * If you want to use a different plugin or state manager, you can pass them in the options.\n * This class is not required and the plugin can be used directly with the HederaConversationalAgent class.\n *\n * @param options - The options for the ConversationalAgent.\n * @returns A new instance of the ConversationalAgent class.\n */\nexport class ConversationalAgent {\n private static readonly NOT_INITIALIZED_ERROR =\n 'Agent not initialized. Call initialize() first.';\n protected agent?: AgentInstance;\n public hcs10Plugin: HCS10Plugin;\n public hcs2Plugin: HCS2Plugin;\n public inscribePlugin: InscribePlugin;\n public hbarPlugin: HbarPlugin;\n public webBrowserPlugin: WebBrowserPlugin;\n public stateManager: IStateManager;\n private options: ConversationalAgentOptions;\n public logger: Logger;\n public contentStoreManager?: ContentStoreManager;\n public memoryManager?: SmartMemoryManager | undefined;\n private entityTools?: {\n resolveEntities: ResolveEntitiesTool;\n extractEntities: ExtractEntitiesTool;\n };\n\n constructor(options: ConversationalAgentOptions) {\n this.options = options;\n this.stateManager = options.stateManager || new OpenConvaiState();\n this.hcs10Plugin = new HCS10Plugin();\n this.hcs2Plugin = new HCS2Plugin();\n this.inscribePlugin = new InscribePlugin();\n this.hbarPlugin = new HbarPlugin();\n this.webBrowserPlugin = new WebBrowserPlugin();\n this.logger = new Logger({\n module: 'ConversationalAgent',\n silent: options.disableLogging || false,\n });\n\n if (this.options.entityMemoryEnabled !== false) {\n if (!options.openAIApiKey) {\n throw new Error(\n 'OpenAI/Anthropic API key is required when entity memory is enabled'\n );\n }\n\n this.memoryManager = new SmartMemoryManager(\n this.options.entityMemoryConfig\n );\n this.logger.info('Entity memory initialized');\n\n const provider =\n options.entityMemoryProvider || options.llmProvider || 'openai';\n let modelName = options.entityMemoryModelName;\n if (!modelName) {\n if (provider === 'anthropic') {\n modelName = DEFAULT_CLAUDE_MODEL;\n } else if (provider === 'openrouter') {\n modelName = DEFAULT_OPENROUTER_MODEL;\n } else {\n modelName = DEFAULT_OPENAI_MODEL;\n }\n }\n\n let resolverLLM: ChatOpenAI | ChatAnthropic;\n if (provider === 'anthropic') {\n resolverLLM = new ChatAnthropic({\n apiKey: options.openAIApiKey,\n model: modelName,\n temperature: 0,\n });\n } else if (provider === 'openrouter') {\n const baseURL =\n options.openRouterBaseURL || 'https://openrouter.ai/api/v1';\n const apiKey = options.openRouterApiKey || options.openAIApiKey;\n resolverLLM = new ChatOpenAI({\n apiKey,\n model: modelName,\n temperature: 0,\n configuration: {\n baseURL,\n defaultHeaders: {\n 'HTTP-Referer':\n process.env.OPENROUTER_REFERRER ||\n 'https://hashgraphonline.com',\n 'X-Title':\n process.env.OPENROUTER_TITLE ||\n 'Hashgraph Online Conversational Agent',\n },\n },\n });\n } else {\n resolverLLM = new ChatOpenAI({\n apiKey: options.openAIApiKey,\n model: modelName,\n temperature: 0,\n });\n }\n\n this.entityTools = createEntityTools(resolverLLM);\n this.logger.info('LLM-based entity resolver tools initialized');\n }\n }\n\n /**\n * Initialize the conversational agent with Hedera Hashgraph connection and AI configuration\n * @throws {Error} If account ID or private key is missing\n * @throws {Error} If initialization fails\n */\n async initialize(): Promise<void> {\n const {\n accountId,\n privateKey,\n network = DEFAULT_NETWORK,\n openAIApiKey,\n openAIModelName = DEFAULT_MODEL_NAME,\n llmProvider = 'openai',\n } = this.options;\n\n this.validateOptions(accountId, privateKey);\n\n try {\n const opMode = (this.options.operationalMode ||\n DEFAULT_OPERATIONAL_MODE) as string;\n const bytesMode = opMode !== 'autonomous';\n let signer: AbstractSigner;\n\n try {\n type InscriberBuilderWithWalletMethods = typeof InscriberBuilder & {\n setPreferWalletOnly?: (prefer: boolean) => void;\n setWalletInfoResolver?: (\n fn: () => Promise<{ accountId: string; network: string } | null>\n ) => void;\n setWalletExecutor?: (\n fn: (\n base64: string,\n network: 'mainnet' | 'testnet'\n ) => Promise<{ transactionId: string }>\n ) => void;\n setStartInscriptionDelegate?: (\n fn: (\n request: Record<string, unknown>,\n network: 'mainnet' | 'testnet'\n ) => Promise<unknown>\n ) => void;\n };\n const IB = InscriberBuilder as InscriberBuilderWithWalletMethods;\n if (typeof IB.setPreferWalletOnly === 'function') {\n IB.setPreferWalletOnly(false);\n }\n } catch (e) {\n this.logger.warn('Failed to set wallet-only preference', e as Error);\n }\n if (!bytesMode) {\n signer = new ServerSigner(\n accountId!,\n privateKey!,\n network as MirrorNetwork\n );\n } else {\n const chain: 'mainnet' | 'testnet' =\n String(network || 'testnet') === 'mainnet' ? 'mainnet' : 'testnet';\n const effectiveAccount = (this.options.userAccountId || accountId)!;\n signer = new BrowserSigner(\n effectiveAccount,\n chain,\n this.options.walletExecutor\n );\n }\n\n this.logger.info('Signer configured', {\n operationalMode: opMode,\n bytesMode,\n signerClass:\n Object.getPrototypeOf(signer)?.constructor?.name || 'unknown',\n });\n\n try {\n const bridge = getWalletBridgeProvider();\n if (bridge) {\n type InscriberBuilderWithWalletMethods = typeof InscriberBuilder & {\n setWalletInfoResolver?: (\n fn: () => Promise<{ accountId: string; network: string } | null>\n ) => void;\n setWalletExecutor?: (\n fn: (\n base64: string,\n network: 'mainnet' | 'testnet'\n ) => Promise<{ transactionId: string }>\n ) => void;\n setStartInscriptionDelegate?: (\n fn: (\n request: Record<string, unknown>,\n network: 'mainnet' | 'testnet'\n ) => Promise<unknown>\n ) => void;\n };\n const IB = InscriberBuilder as InscriberBuilderWithWalletMethods;\n if (typeof IB.setWalletInfoResolver === 'function') {\n IB.setWalletInfoResolver(async () => {\n const status = await bridge.status();\n if (status.connected && status.accountId && status.network) {\n return { accountId: status.accountId, network: status.network };\n }\n return null;\n });\n }\n if (typeof IB.setWalletExecutor === 'function') {\n IB.setWalletExecutor(\n async (base64: string, network: 'mainnet' | 'testnet') => {\n return await bridge.executeBytes(base64, network);\n }\n );\n }\n if (\n typeof IB.setStartInscriptionDelegate === 'function' &&\n bridge.startInscription\n ) {\n IB.setStartInscriptionDelegate(\n async (\n request: Record<string, unknown>,\n network: 'mainnet' | 'testnet'\n ) => {\n return await bridge.startInscription!(request, network);\n }\n );\n }\n\n try {\n type HCSOp =\n | 'submitConnectionRequest'\n | 'handleConnectionRequest'\n | 'sendMessage'\n | 'hcs2.createRegistry'\n | 'hcs2.migrateRegistry'\n | 'hcs2.registerEntry'\n | 'hcs2.updateEntry'\n | 'hcs2.deleteEntry'\n | 'hcs2.submitMessage'\n | 'hcs6.createRegistry'\n | 'hcs6.registerEntry'\n | 'hcs6.submitMessage';\n type WalletBridgeProviderExt = ReturnType<\n typeof getWalletBridgeProvider\n > & {\n startHCS?: (\n op: HCSOp,\n request: Record<string, unknown>,\n network: 'mainnet' | 'testnet'\n ) => Promise<{ transactionBytes: string }>;\n };\n\n const status = await bridge.status();\n const enforceWallet = !!(bytesMode && status.connected);\n\n SignerProviderRegistry.setWalletInfoResolver(async () => {\n const s = await bridge.status();\n if (s.connected && s.accountId && s.network) {\n return {\n accountId: s.accountId,\n network: s.network as 'mainnet' | 'testnet',\n };\n }\n return null;\n });\n\n SignerProviderRegistry.setWalletExecutor(\n async (base64: string, network: 'mainnet' | 'testnet') => {\n return await bridge.executeBytes(base64, network);\n }\n );\n\n const extended = bridge as WalletBridgeProviderExt;\n if (typeof extended?.startHCS === 'function') {\n SignerProviderRegistry.setStartHCSDelegate(\n async (op, request, network) => {\n return await extended.startHCS!(\n op as HCSOp,\n request,\n network\n );\n }\n );\n } else {\n SignerProviderRegistry.setStartHCSDelegate(null);\n }\n\n SignerProviderRegistry.setPreferWalletOnly(enforceWallet);\n\n type InscriberBuilderWithWalletMethods = typeof InscriberBuilder & {\n setPreferWalletOnly?: (prefer: boolean) => void;\n };\n const IB2 = InscriberBuilder as InscriberBuilderWithWalletMethods;\n if (typeof IB2.setPreferWalletOnly === 'function') {\n IB2.setPreferWalletOnly(enforceWallet);\n }\n } catch (sakWireErr) {\n this.logger.warn(\n 'Failed to wire SAK SignerProviderRegistry wallet delegates',\n sakWireErr as Error\n );\n }\n }\n } catch (e) {\n this.logger.warn(\n 'Failed to register wallet bridge providers',\n e as Error\n );\n }\n\n let llm: ChatOpenAI | ChatAnthropic;\n let providerInfo: Record<string, unknown> = { provider: llmProvider };\n if (llmProvider === 'anthropic') {\n llm = new ChatAnthropic({\n apiKey: openAIApiKey,\n model: openAIModelName || DEFAULT_CLAUDE_MODEL,\n temperature: DEFAULT_TEMPERATURE,\n });\n providerInfo = {\n ...providerInfo,\n model: openAIModelName || DEFAULT_CLAUDE_MODEL,\n keyPresent: !!openAIApiKey,\n };\n } else if (llmProvider === 'openrouter') {\n const baseURL =\n this.options.openRouterBaseURL || 'https://openrouter.ai/api/v1';\n const apiKey = this.options.openRouterApiKey || openAIApiKey;\n const modelName =\n openAIModelName || 'anthropic/claude-3-haiku-20240307';\n llm = new ChatOpenAI({\n apiKey,\n model: modelName,\n temperature: DEFAULT_TEMPERATURE,\n configuration: {\n baseURL,\n defaultHeaders: {\n 'HTTP-Referer':\n process.env.OPENROUTER_REFERRER ||\n 'https://hashgraphonline.com',\n 'X-Title':\n process.env.OPENROUTER_TITLE ||\n 'Hashgraph Online Conversational Agent',\n },\n },\n });\n providerInfo = {\n ...providerInfo,\n model: modelName,\n baseURL,\n keyPresent: !!apiKey,\n };\n } else {\n const modelName2 = openAIModelName || DEFAULT_OPENAI_MODEL;\n const isGPT5Model =\n modelName2.toLowerCase().includes('gpt-5') ||\n modelName2.toLowerCase().includes('gpt5');\n llm = new ChatOpenAI({\n apiKey: openAIApiKey,\n model: modelName2,\n ...(isGPT5Model\n ? { temperature: 1 }\n : { temperature: DEFAULT_TEMPERATURE }),\n });\n providerInfo = {\n ...providerInfo,\n model: modelName2,\n keyPresent: !!openAIApiKey,\n };\n }\n\n this.logger.info('AI provider configured', providerInfo);\n\n this.logger.info('Preparing plugins...');\n const allPlugins = this.preparePlugins();\n this.logger.info('Creating agent config...');\n const agentConfig = this.createAgentConfig(\n signer as ServerSigner,\n llm,\n allPlugins\n );\n\n this.logger.info('Creating agent...');\n this.agent = createAgent(agentConfig);\n this.logger.info('Agent created');\n\n this.logger.info('Configuring HCS10 plugin...');\n this.configureHCS10Plugin(allPlugins);\n this.logger.info('HCS10 plugin configured');\n\n this.contentStoreManager = new ContentStoreManager();\n await this.contentStoreManager.initialize();\n this.logger.info(\n 'ContentStoreManager initialized for content reference support'\n );\n\n this.logger.info('About to call agent.boot()');\n this.logger.info('🔥 About to call agent.boot()');\n await this.agent.boot();\n this.logger.info('agent.boot() completed');\n this.logger.info('🔥 agent.boot() completed');\n\n if (this.agent) {\n try {\n const registry = new FormatConverterRegistry();\n registry.register(new TopicIdToHrlConverter());\n registry.register(new StringNormalizationConverter());\n const paramService = new ParameterService(\n registry,\n (this.options.network as unknown as NetworkType) || 'testnet'\n );\n paramService.attachToAgent(this.agent, {\n getEntities: async () =>\n this.memoryManager?.getEntityAssociations() || [],\n });\n this.logger.info(\n 'Parameter preprocessing callback attached (internal)'\n );\n } catch (e) {\n this.logger.warn(\n 'Failed to attach internal parameter preprocessing callback',\n e\n );\n }\n\n const cfg = agentConfig;\n cfg.filtering = cfg.filtering || {};\n const originalPredicate = cfg.filtering.toolPredicate as\n | ((t: ToolDescriptor) => boolean)\n | undefined;\n const userPredicate = this.options.toolFilter;\n cfg.filtering.toolPredicate = (tool: ToolDescriptor): boolean => {\n if (tool && tool.name === 'hedera-account-transfer-hbar') {\n return false;\n }\n if (tool && tool.name === 'hedera-hts-airdrop-token') {\n return false;\n }\n if (originalPredicate && !originalPredicate(tool)) {\n return false;\n }\n if (userPredicate && !userPredicate(tool)) {\n return false;\n }\n return true;\n };\n }\n\n if (this.options.mcpServers && this.options.mcpServers.length > 0) {\n this.connectMCP();\n }\n } catch (error) {\n this.logger.error('Failed to initialize ConversationalAgent:', error);\n throw error;\n }\n }\n\n /**\n * Get the HCS-10 plugin instance\n * @returns {HCS10Plugin} The HCS-10 plugin instance\n */\n getPlugin(): HCS10Plugin {\n return this.hcs10Plugin;\n }\n\n /**\n * Get the state manager instance\n * @returns {IStateManager} The state manager instance\n */\n getStateManager(): IStateManager {\n return this.stateManager;\n }\n\n /**\n * Get the underlying agent instance\n * @returns {ReturnType<typeof createAgent>} The agent instance\n * @throws {Error} If agent is not initialized\n */\n getAgent(): ReturnType<typeof createAgent> {\n if (!this.agent) {\n throw new Error(ConversationalAgent.NOT_INITIALIZED_ERROR);\n }\n return this.agent;\n }\n\n /**\n * Get the conversational agent instance (alias for getAgent)\n * @returns {ReturnType<typeof createAgent>} The agent instance\n * @throws {Error} If agent is not initialized\n */\n getConversationalAgent(): ReturnType<typeof createAgent> {\n return this.getAgent();\n }\n\n /**\n * Process a message through the conversational agent\n * @param {string} message - The message to process\n * @param {Array<{type: 'human' | 'ai'; content: string}>} chatHistory - Previous chat history\n * @returns {Promise<ChatResponse>} The agent's response\n * @throws {Error} If agent is not initialized\n */\n async processMessage(\n message: string,\n chatHistory: ChatHistoryItem[] = []\n ): Promise<ChatResponse> {\n if (!this.agent) {\n throw new Error('Agent not initialized. Call initialize() first.');\n }\n\n try {\n const resolvedMessage = message;\n\n const messages = chatHistory.map((msg) => {\n const content = msg.content;\n if (msg.type === 'system') {\n return new SystemMessage(content);\n }\n return msg.type === 'human'\n ? new HumanMessage(content)\n : new AIMessage(content);\n });\n\n const context: ConversationContext = { messages };\n const response = await this.agent.chat(resolvedMessage, context);\n\n if (\n this.memoryManager &&\n this.options.operationalMode !== 'returnBytes'\n ) {\n await this.extractAndStoreEntities(response, message);\n }\n\n this.logger.info('Message processed successfully');\n return response;\n } catch (error) {\n this.logger.error('Error processing message:', error);\n throw error;\n }\n }\n\n /**\n * Process form submission through the conversational agent\n * @param {FormSubmission} submission - The form submission data\n * @returns {Promise<ChatResponse>} The agent's response after processing the form\n * @throws {Error} If agent is not initialized or doesn't support form processing\n */\n async processFormSubmission(\n submission: FormSubmission\n ): Promise<ChatResponse> {\n if (!this.agent) {\n throw new Error(ConversationalAgent.NOT_INITIALIZED_ERROR);\n }\n\n try {\n this.logger.info('Processing form submission:', {\n formId: submission.formId,\n toolName: submission.toolName,\n parameterKeys: Object.keys(submission.parameters || {}),\n hasContext: !!submission.context,\n });\n const response = await this.agent.processFormSubmission(submission);\n this.logger.info('Form submission processed successfully');\n return response;\n } catch (error) {\n this.logger.error('Error processing form submission:', error);\n throw error;\n }\n }\n\n /**\n * Validates initialization options and throws if required fields are missing.\n *\n * @param accountId - The Hedera account ID\n * @param privateKey - The private key for the account\n * @throws {Error} If required fields are missing\n */\n private validateOptions(accountId?: string, privateKey?: string): void {\n const opMode = (this.options.operationalMode ||\n DEFAULT_OPERATIONAL_MODE) as string;\n const bytesMode = opMode !== 'autonomous';\n if (!accountId) {\n throw new Error('Account ID is required');\n }\n if (!privateKey && !bytesMode) {\n throw new Error('Private key is required in autonomous mode');\n }\n\n if (typeof accountId !== 'string') {\n throw new Error(\n `Account ID must be a string, received ${typeof accountId}`\n );\n }\n\n if (!bytesMode && typeof privateKey !== 'string') {\n throw new Error(\n `Private key must be a string, received ${typeof privateKey}: ${JSON.stringify(\n privateKey\n )}`\n );\n }\n if (\n !bytesMode &&\n typeof privateKey === 'string' &&\n privateKey.length < 10\n ) {\n throw new Error('Private key appears to be invalid (too short)');\n }\n }\n\n /**\n * Prepares the list of plugins to use based on configuration.\n *\n * @returns Array of plugins to initialize with the agent\n */\n private preparePlugins(): BasePlugin[] {\n const { additionalPlugins = [], enabledPlugins, disabledPlugins } = this.options;\n\n const standardPlugins: BasePlugin[] = [\n this.hcs10Plugin,\n this.hcs2Plugin,\n this.inscribePlugin,\n this.hbarPlugin,\n ];\n standardPlugins.push(this.webBrowserPlugin);\n\n const corePlugins = getAllHederaCorePlugins();\n let pluginPool = [...standardPlugins, ...corePlugins];\n\n if (enabledPlugins) {\n const enabledSet = new Set(enabledPlugins);\n pluginPool = pluginPool.filter((plugin) => enabledSet.has(plugin.id));\n }\n\n if (disabledPlugins && disabledPlugins.length > 0) {\n const disabledSet = new Set(disabledPlugins);\n pluginPool = pluginPool.filter((plugin) => !disabledSet.has(plugin.id));\n }\n\n const additional = disabledPlugins && disabledPlugins.length > 0\n ? additionalPlugins.filter((plugin) => !disabledPlugins.includes(plugin.id))\n : additionalPlugins;\n\n return [...pluginPool, ...additional];\n }\n\n /**\n * Creates the agent configuration object.\n *\n * @param signer - The signer instance\n * @param llm - The language model instance\n * @param allPlugins - Array of plugins to use\n * @returns Configuration object for creating the agent\n */\n private createAgentConfig(\n signer: ServerSigner,\n llm: ChatOpenAI | ChatAnthropic,\n allPlugins: BasePlugin[]\n ): Parameters<typeof createAgent>[0] {\n const {\n operationalMode = DEFAULT_OPERATIONAL_MODE,\n userAccountId,\n scheduleUserTransactionsInBytesMode,\n customSystemMessagePreamble,\n customSystemMessagePostamble,\n verbose = false,\n mirrorNodeConfig,\n disableLogging,\n accountId = '',\n } = this.options;\n\n return {\n framework: 'langchain',\n signer,\n execution: {\n mode: operationalMode === 'autonomous' ? 'direct' : 'bytes',\n operationalMode: operationalMode,\n ...(userAccountId && { userAccountId }),\n ...(scheduleUserTransactionsInBytesMode !== undefined && {\n scheduleUserTransactionsInBytesMode:\n scheduleUserTransactionsInBytesMode,\n scheduleUserTransactions: scheduleUserTransactionsInBytesMode,\n }),\n },\n ai: {\n provider: new LangChainProvider(llm),\n temperature: DEFAULT_TEMPERATURE,\n },\n filtering: {\n toolPredicate: (tool: ToolDescriptor): boolean => {\n if (tool.name === 'hedera-account-transfer-hbar') return false;\n if (this.options.toolFilter && !this.options.toolFilter(tool)) {\n return false;\n }\n return true;\n },\n },\n messaging: {\n systemPreamble:\n customSystemMessagePreamble || getSystemMessage(accountId),\n ...(customSystemMessagePostamble && {\n systemPostamble: customSystemMessagePostamble,\n }),\n conciseMode: true,\n },\n extensions: {\n plugins: allPlugins,\n ...(mirrorNodeConfig && {\n mirrorConfig: mirrorNodeConfig as Record<string, unknown>,\n }),\n },\n ...(this.options.mcpServers && {\n mcp: {\n servers: this.options.mcpServers,\n autoConnect: false,\n },\n }),\n debug: {\n verbose,\n silent: disableLogging ?? false,\n },\n };\n }\n\n /**\n * Configures the HCS-10 plugin with the state manager.\n *\n * @param allPlugins - Array of all plugins\n */\n private configureHCS10Plugin(allPlugins: BasePlugin[]): void {\n const hcs10 = allPlugins.find((p) => p.id === 'hcs-10');\n if (hcs10) {\n (\n hcs10 as BasePlugin & { appConfig?: Record<string, unknown> }\n ).appConfig = {\n stateManager: this.stateManager,\n };\n }\n }\n\n /**\n * Create a ConversationalAgent with specific plugins enabled\n */\n private static withPlugins(\n options: ConversationalAgentOptions,\n plugins: string[]\n ): ConversationalAgent {\n return new ConversationalAgent({\n ...options,\n enabledPlugins: plugins,\n });\n }\n\n /**\n * Create a ConversationalAgent with only HTS (Hedera Token Service) tools enabled\n */\n static withHTS(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['hts-token']);\n }\n\n /**\n * Create a ConversationalAgent with only HCS-2 tools enabled\n */\n static withHCS2(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['hcs-2']);\n }\n\n /**\n * Create a ConversationalAgent with only HCS-10 tools enabled\n */\n static withHCS10(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['hcs-10']);\n }\n\n /**\n * Create a ConversationalAgent with only inscription tools enabled\n */\n static withInscribe(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['inscribe']);\n }\n\n /**\n * Create a ConversationalAgent with only account management tools enabled\n */\n static withAccount(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['account']);\n }\n\n /**\n * Create a ConversationalAgent with only file service tools enabled\n */\n static withFileService(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['file-service']);\n }\n\n /**\n * Create a ConversationalAgent with only consensus service tools enabled\n */\n static withConsensusService(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['consensus-service']);\n }\n\n /**\n * Create a ConversationalAgent with only smart contract tools enabled\n */\n static withSmartContract(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['smart-contract']);\n }\n\n /**\n * Create a ConversationalAgent with all HCS standards plugins\n */\n static withAllStandards(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['hcs-10', 'hcs-2', 'inscribe']);\n }\n\n /**\n * Create a ConversationalAgent with minimal Hedera tools (no HCS standards)\n */\n static minimal(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, []);\n }\n\n /**\n * Create a ConversationalAgent with MCP servers configured\n */\n static withMCP(\n options: ConversationalAgentOptions,\n mcpServers: MCPServerConfig[]\n ): ConversationalAgent {\n return new ConversationalAgent({\n ...options,\n mcpServers,\n });\n }\n\n /**\n * Extract and store entities from agent responses\n * @param response - Agent response containing potential entity information\n * @param originalMessage - Original user message for context\n */\n private async extractAndStoreEntities(\n response: unknown,\n originalMessage: string\n ): Promise<void> {\n if (!this.memoryManager || !this.entityTools) {\n return;\n }\n\n try {\n this.logger.info('Starting LLM-based entity extraction');\n\n const responseText = this.extractResponseText(response);\n\n const entitiesJson = await this.entityTools.extractEntities.call({\n response: responseText,\n userMessage: originalMessage,\n });\n\n try {\n const entities = JSON.parse(entitiesJson);\n\n for (const entity of entities) {\n if (\n entity &&\n typeof entity === 'object' &&\n 'name' in entity &&\n 'type' in entity &&\n 'id' in entity\n ) {\n this.logger.info(\n `Storing entity: ${entity.name} (${entity.type}) -> ${entity.id}`\n );\n\n const transactionId = this.extractTransactionId(response);\n const idStr = String(entity.id);\n const isHederaId = /^0\\.0\\.[0-9]+$/.test(idStr);\n if (!isHederaId) {\n this.logger.warn('Skipping non-ID entity from extraction', {\n id: idStr,\n name: String(entity.name),\n type: String(entity.type),\n });\n } else {\n this.memoryManager.storeEntityAssociation(\n idStr,\n String(entity.name),\n String(entity.type),\n transactionId\n );\n }\n }\n }\n\n if (entities.length > 0) {\n this.logger.info(\n `Stored ${entities.length} entities via LLM extraction`\n );\n } else {\n this.logger.info('No entities found in response via LLM extraction');\n }\n } catch (parseError) {\n this.logger.error(\n 'Failed to parse extracted entities JSON:',\n parseError\n );\n throw parseError;\n }\n } catch (error) {\n this.logger.error('Entity extraction failed:', error);\n throw error;\n }\n }\n\n /**\n * Extract transaction ID from response if available\n * @param response - Transaction response\n * @returns Transaction ID or undefined\n */\n private extractTransactionId(response: unknown): string | undefined {\n try {\n if (\n typeof response === 'object' &&\n response &&\n 'transactionId' in response\n ) {\n const responseWithTxId = response as { transactionId?: unknown };\n return typeof responseWithTxId.transactionId === 'string'\n ? responseWithTxId.transactionId\n : undefined;\n }\n if (typeof response === 'string') {\n const match = response.match(\n /transaction[\\s\\w]*ID[\\s:\"]*([0-9a-fA-F@._-]+)/i\n );\n return match ? match[1] : undefined;\n }\n return undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Connect to MCP servers asynchronously\n * @private\n */\n private connectMCP(): void {\n if (!this.agent || !this.options.mcpServers) {\n return;\n }\n\n this.agent\n .connectMCPServers()\n .catch((e) => {\n this.logger.error('Failed to connect MCP servers:', e);\n })\n .then(() => {\n this.logger.info('MCP servers connected successfully');\n });\n }\n\n /**\n * Get MCP connection status for all servers\n * @returns {Map<string, MCPConnectionStatus>} Connection status map\n */\n getMCPConnectionStatus(): Map<string, MCPConnectionStatus> {\n if (this.agent) {\n return this.agent.getMCPConnectionStatus();\n }\n return new Map();\n }\n\n /**\n * Check if a specific MCP server is connected\n * @param {string} serverName - Name of the server to check\n * @returns {boolean} True if connected, false otherwise\n */\n isMCPServerConnected(serverName: string): boolean {\n if (this.agent) {\n const statusMap = this.agent.getMCPConnectionStatus();\n const status = statusMap.get(serverName);\n return status?.connected ?? false;\n }\n return false;\n }\n\n /**\n * Clean up resources\n */\n async cleanup(): Promise<void> {\n try {\n this.logger.info('Cleaning up ConversationalAgent...');\n\n if (this.memoryManager) {\n try {\n this.memoryManager.dispose();\n this.logger.info('Memory manager cleaned up successfully');\n } catch (error) {\n this.logger.warn('Error cleaning up memory manager:', error);\n }\n this.memoryManager = undefined;\n }\n\n if (this.contentStoreManager) {\n await this.contentStoreManager.dispose();\n this.logger.info('ContentStoreManager cleaned up');\n }\n\n this.logger.info('ConversationalAgent cleanup completed');\n } catch (error) {\n this.logger.error('Error during cleanup:', error);\n }\n }\n\n /**\n * Switch operational mode\n */\n switchMode(mode?: AgentOperationalMode): void {\n if (this.agent?.switchMode) {\n this.agent.switchMode(mode || 'autonomous');\n }\n }\n\n /**\n * Get usage statistics\n */\n getUsageStats(): unknown {\n return this.agent?.getUsageStats?.() ?? {};\n }\n\n /**\n * Clear usage statistics\n */\n clearUsageStats(): void {\n if (this.agent?.clearUsageStats) {\n this.agent.clearUsageStats();\n }\n }\n\n /**\n * Shutdown the agent\n */\n shutdown(): Promise<void> {\n return this.agent?.shutdown?.() ?? Promise.resolve();\n }\n\n private extractResponseText(response: unknown): string {\n if (typeof response === 'string') {\n return response;\n }\n\n if (response && typeof response === 'object' && 'output' in response) {\n const responseWithOutput = response as { output: unknown };\n return String(responseWithOutput.output);\n }\n\n return JSON.stringify(response);\n }\n}\n","import { Logger } from '@hashgraphonline/standards-sdk';\nimport type { ContentStoreManager as PackageContentStoreManager } from './content-store-manager';\n\nexport interface AttachmentData {\n name: string;\n data: string;\n type: string;\n size: number;\n}\n\nexport type ContentStoreManager = PackageContentStoreManager;\n\n/**\n * Utility for processing file attachments and content references\n */\nexport class AttachmentProcessor {\n private logger: Logger;\n\n constructor() {\n this.logger = new Logger({ module: 'AttachmentProcessor' });\n }\n\n /**\n * Process attachments and create content references\n */\n async processAttachments(\n content: string,\n attachments: AttachmentData[],\n contentStoreManager?: ContentStoreManager\n ): Promise<string> {\n if (attachments.length === 0) {\n return content;\n }\n\n this.logger.info('Processing attachments with content reference system:', {\n attachmentCount: attachments.length,\n totalSize: attachments.reduce((sum, att) => sum + att.size, 0),\n });\n\n if (contentStoreManager && contentStoreManager.isInitialized()) {\n return this.processWithContentStore(content, attachments, contentStoreManager);\n } else {\n this.logger.warn('Content storage not available, creating simple file references');\n return this.processWithSimpleReferences(content, attachments);\n }\n }\n\n /**\n * Process attachments using content store manager\n */\n private async processWithContentStore(\n content: string,\n attachments: AttachmentData[],\n contentStoreManager: ContentStoreManager\n ): Promise<string> {\n const contentReferences: string[] = [];\n\n for (const attachment of attachments) {\n try {\n const base64Data = attachment.data.includes('base64,')\n ? attachment.data.split('base64,')[1]\n : attachment.data;\n const buffer = Buffer.from(base64Data, 'base64');\n\n const contentRef = await contentStoreManager.storeContentIfLarge(\n buffer,\n {\n mimeType: attachment.type,\n source: 'user_upload',\n fileName: attachment.name,\n tags: ['attachment', 'user_file'],\n }\n );\n\n if (contentRef) {\n if (attachment.type.startsWith('image/')) {\n contentReferences.push(\n `[Image File: ${attachment.name}] (content-ref:${contentRef.referenceId})`\n );\n } else {\n contentReferences.push(\n `[File: ${attachment.name}] (content-ref:${contentRef.referenceId})`\n );\n }\n } else {\n contentReferences.push(\n this.createInlineReference(attachment, base64Data)\n );\n }\n } catch (error) {\n this.logger.error('Failed to process attachment:', {\n fileName: attachment.name,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n contentReferences.push(\n `[File: ${attachment.name} - Error processing file: ${\n error instanceof Error ? error.message : 'Unknown error'\n }]`\n );\n }\n }\n\n const fileList = this.createFileList(attachments);\n return content\n ? `${content}\\n\\nAttached files:\\n${fileList}\\n\\n${contentReferences.join('\\n')}`\n : `Attached files:\\n${fileList}\\n\\n${contentReferences.join('\\n')}`;\n }\n\n /**\n * Process attachments with simple file references\n */\n private processWithSimpleReferences(content: string, attachments: AttachmentData[]): string {\n const fileReferences = attachments.map((attachment) => {\n const sizeStr = this.formatFileSize(attachment.size);\n\n if (attachment.type.startsWith('image/')) {\n return `📎 Image: ${attachment.name} (${sizeStr}, ${attachment.type})`;\n } else {\n return `📎 File: ${attachment.name} (${sizeStr}, ${attachment.type})`;\n }\n });\n\n return content\n ? `${content}\\n\\nAttached files:\\n${fileReferences.join('\\n')}`\n : `Attached files:\\n${fileReferences.join('\\n')}`;\n }\n\n /**\n * Create inline reference for small files\n */\n private createInlineReference(attachment: AttachmentData, base64Data: string): string {\n if (attachment.size < 50000) {\n if (attachment.type.startsWith('image/')) {\n return `![${attachment.name}](data:${attachment.type};base64,${base64Data})`;\n } else {\n return `[File: ${attachment.name} (${this.formatFileSize(attachment.size)})]\\nContent: ${base64Data}`;\n }\n } else {\n return `[File: ${attachment.name} (${this.formatFileSize(attachment.size)}) - Content too large to include inline]`;\n }\n }\n\n /**\n * Create formatted file list\n */\n private createFileList(attachments: AttachmentData[]): string {\n return attachments\n .map((file) => {\n const sizeStr = this.formatFileSize(file.size);\n return `📎 ${file.name} (${sizeStr})`;\n })\n .join('\\n');\n }\n\n /**\n * Format file size for display\n */\n private formatFileSize(size: number): string {\n return size >= 1024 * 1024\n ? `${(size / (1024 * 1024)).toFixed(1)}MB`\n : `${(size / 1024).toFixed(1)}KB`;\n }\n}\n","import { ChatOpenAI } from '@langchain/openai';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport type { EntityAssociation } from '../memory/smart-memory-manager';\nimport { ENTITY_PATTERNS } from '../constants';\nimport { EntityFormat } from '..';\n\nexport interface EntityResolverConfig {\n apiKey: string;\n modelName?: string;\n}\n\ninterface EntityIdValue {\n toString(): string;\n}\n\ninterface TransactionReceipt {\n tokenId?: EntityIdValue | string;\n topicId?: EntityIdValue | string;\n accountId?: EntityIdValue | string;\n contractId?: EntityIdValue | string;\n fileId?: EntityIdValue | string;\n scheduleId?: EntityIdValue | string;\n}\n\ninterface TransactionResponse {\n success?: boolean;\n receipt?: TransactionReceipt;\n result?: {\n receipt?: TransactionReceipt;\n transactionId?: string;\n };\n data?: {\n receipt?: TransactionReceipt;\n };\n transactionId?: string;\n}\n\ninterface ExtractedEntity {\n id: string;\n name: string;\n type: EntityFormat;\n transactionId?: string;\n}\n\n/**\n * LLM-based entity resolver that replaces brittle regex patterns\n */\nexport class EntityResolver {\n private llm: ChatOpenAI;\n private logger: Logger;\n\n constructor(config: EntityResolverConfig) {\n this.llm = new ChatOpenAI({\n apiKey: config.apiKey,\n modelName: config.modelName || 'gpt-4o-mini',\n temperature: 0,\n });\n this.logger = new Logger({ module: 'EntityResolver' });\n }\n\n /**\n * Resolve entity references using LLM instead of regex\n */\n async resolveReferences(\n message: string,\n entities: EntityAssociation[]\n ): Promise<string> {\n if (!entities || entities.length === 0) {\n return message;\n }\n\n const byType = entities.reduce((acc, e) => {\n if (!acc[e.entityType]) acc[e.entityType] = [];\n acc[e.entityType].push(e);\n return acc;\n }, {} as Record<string, EntityAssociation[]>);\n\n try {\n const stats = Object.fromEntries(\n Object.entries(byType).map(([type, list]) => [\n type,\n {\n count: list.length,\n mostRecent: list[0]?.entityId,\n },\n ])\n );\n this.logger.info('resolveReferences: input summary', {\n messagePreview: message.substring(0, 200),\n entityStats: stats,\n });\n } catch {}\n\n let context = 'Available entities in memory:\\n';\n for (const [type, list] of Object.entries(byType)) {\n const recent = list[0];\n context += `Most recent ${type}: \"${recent.entityName}\" = ${recent.entityId}\\n`;\n if (list.length > 1) {\n context += ` (${list.length - 1} other ${type}s in memory)\\n`;\n }\n }\n\n const prompt = `Task: Replace entity references with their IDs from memory. STRICT TYPE RULES:\n\n- For phrases referring to \"${ENTITY_PATTERNS.TOKEN_REFERENCE}\" or actions that clearly require a token (create/mint/airdrop/associate/etc.), resolve to the most recent TOKEN entity ID (never a topic or account).\n- For phrases referring to \"${ENTITY_PATTERNS.TOPIC_REFERENCE}\" or actions that clearly require a topic (inscribe/publish/consensus/etc.), resolve to the most recent TOPIC entity ID (never a token or account).\n- Do not infer or invent entity IDs. Only use those present in the provided context.\n\n${context}\n\nUser message: \"${message}\"\n\nInstructions:\n- If the user says \"${ENTITY_PATTERNS.TOPIC_REFERENCE}\" or \"that topic\" → replace with the most recent topic ID\n- If the user says \"${ENTITY_PATTERNS.TOKEN_REFERENCE}\" or \"that token\" → replace with the most recent token ID (never a topic)\n- If the user says \"it\" or \"that\" after an action verb → replace with the most recent entity ID\n- Examples:\n * \"submit on ${ENTITY_PATTERNS.TOPIC_REFERENCE}\" → \"submit on 0.0.6543472\"\n * \"airdrop ${ENTITY_PATTERNS.TOKEN_REFERENCE}\" → \"airdrop 0.0.123456\"\n * \"send a message to it\" → \"send a message to 0.0.6543472\"\n\nReturn ONLY the message with replacements made. Do not add any explanations.\nResolved message:`;\n\n try {\n const response = await this.llm.invoke(prompt);\n const resolved = (response.content as string).trim();\n\n const changed = resolved !== message;\n try {\n this.logger.info('resolveReferences: resolution result', {\n changed,\n hasEntityId: /\\b0\\.0\\.\\d+\\b/.test(resolved),\n resolvedPreview: resolved.substring(0, 200),\n });\n } catch {}\n\n if (changed && resolved.includes('0.0.')) {\n return resolved;\n }\n\n return message;\n } catch {\n return message;\n }\n }\n\n /**\n * Extract entities from agent response using receipt data (preferred) or LLM fallback\n */\n async extractEntities(\n response: unknown,\n userMessage: string\n ): Promise<ExtractedEntity[]> {\n const receiptEntities = this.extractFromReceipt(response, userMessage);\n if (receiptEntities.length > 0) {\n return receiptEntities;\n }\n\n return this.extractWithLLM(response, userMessage);\n }\n\n /**\n * Extract entities from transaction receipt data (primary method)\n */\n private extractFromReceipt(\n response: unknown,\n userMessage: string\n ): ExtractedEntity[] {\n const entities: ExtractedEntity[] = [];\n\n let parsedResponse: TransactionResponse;\n try {\n parsedResponse =\n typeof response === 'string'\n ? JSON.parse(response)\n : (response as TransactionResponse);\n } catch {\n parsedResponse = response as TransactionResponse;\n }\n\n if (!parsedResponse || parsedResponse.success === false) {\n return entities;\n }\n\n const receipt =\n parsedResponse.receipt ||\n parsedResponse.result?.receipt ||\n parsedResponse.data?.receipt;\n\n if (!receipt) {\n return entities;\n }\n\n const entityName = this.extractNameFromMessage(userMessage);\n\n const transactionId =\n parsedResponse.transactionId ||\n parsedResponse.result?.transactionId ||\n undefined;\n\n const extractEntityId = (entityId: EntityIdValue | string): string => {\n if (typeof entityId === 'string') {\n return entityId;\n }\n if (\n entityId &&\n typeof entityId === 'object' &&\n typeof entityId.toString === 'function'\n ) {\n if (entityId.toString !== Object.prototype.toString) {\n return entityId.toString();\n }\n }\n return String(entityId);\n };\n\n if (receipt.tokenId) {\n const entity: ExtractedEntity = {\n id: extractEntityId(receipt.tokenId),\n name: entityName,\n type: EntityFormat.TOKEN_ID,\n };\n if (transactionId) {\n entity.transactionId = transactionId;\n }\n entities.push(entity);\n }\n\n if (receipt.topicId) {\n const entity: ExtractedEntity = {\n id: extractEntityId(receipt.topicId),\n name: entityName,\n type: EntityFormat.TOPIC_ID,\n };\n if (transactionId) {\n entity.transactionId = transactionId;\n }\n entities.push(entity);\n }\n\n if (receipt.accountId) {\n const entity: ExtractedEntity = {\n id: extractEntityId(receipt.accountId),\n name: entityName,\n type: EntityFormat.ACCOUNT_ID,\n };\n if (transactionId) {\n entity.transactionId = transactionId;\n }\n entities.push(entity);\n }\n\n if (receipt.contractId) {\n const entity: ExtractedEntity = {\n id: extractEntityId(receipt.contractId),\n name: entityName,\n type: EntityFormat.CONTRACT_ID,\n };\n if (transactionId) {\n entity.transactionId = transactionId;\n }\n entities.push(entity);\n }\n\n if (receipt.fileId) {\n const entity: ExtractedEntity = {\n id: extractEntityId(receipt.fileId),\n name: entityName,\n type: EntityFormat.FILE_ID,\n };\n if (transactionId) {\n entity.transactionId = transactionId;\n }\n entities.push(entity);\n }\n\n if (receipt.scheduleId) {\n const entity: ExtractedEntity = {\n id: extractEntityId(receipt.scheduleId),\n name: entityName,\n type: EntityFormat.SCHEDULE_ID,\n };\n if (transactionId) {\n entity.transactionId = transactionId;\n }\n entities.push(entity);\n }\n\n return entities;\n }\n\n /**\n * Extract entity name from user message\n */\n private extractNameFromMessage(message: string): string {\n const quotedMatch = message.match(/\"([^\"]+)\"/);\n if (quotedMatch) return quotedMatch[1];\n\n const calledMatch = message.match(/called\\s+([A-Za-z0-9#\\s_-]+?)(?:\\s|$)/i);\n if (calledMatch) return calledMatch[1].trim();\n\n const forMatch = message.match(/for\\s+([A-Za-z0-9#\\s_-]+)/i);\n if (forMatch) return forMatch[1].trim();\n\n const namedMatch = message.match(\n /(?:token|topic|account|contract)\\s+([A-Za-z0-9#_-]+)/i\n );\n if (namedMatch) return namedMatch[1].trim();\n\n if (message.includes('new account')) return 'new account';\n\n return 'unnamed_entity';\n }\n\n /**\n * Extract entities using LLM (fallback method)\n */\n private async extractWithLLM(\n response: unknown,\n userMessage: string\n ): Promise<ExtractedEntity[]> {\n const text =\n typeof response === 'string' ? response : JSON.stringify(response);\n\n const prompt = `Analyze this agent response and extract ONLY newly created entities.\n\nUser asked: \"${userMessage.substring(0, 200)}\"\n\nAgent response: ${text.substring(0, 3000)}\n\nCRITICAL: Only extract Hedera entity IDs in the format 0.0.XXXXX (shard.realm.number).\nDO NOT extract:\n- Token symbols (e.g., \"FOREV\", \"USDC\", \"HBAR\")\n- Token names (e.g., \"Forever\", \"My Token\")\n- Transaction IDs (format: 0.0.XXX@timestamp)\n- Account aliases or mnemonics\n\nLook for:\n1. Success messages with entity IDs (e.g., \"Successfully created topic 0.0.6543472\")\n2. Transaction confirmations that created new entities\n3. Entity IDs that appear after words like \"created\", \"new\", \"successfully\"\n\nDO NOT include:\n- Token symbols or names (these are NOT entity IDs)\n- Account IDs that already existed (like sender/receiver accounts)\n- Entity IDs that were parameters to the operation\n- Failed operations\n- Anything that doesn't match the 0.0.XXXXX format\n\nReturn a JSON array of newly created entities:\n[{\"id\": \"0.0.XXX\", \"name\": \"descriptive_name\", \"type\": \"topic|token|account\"}]\n\nIf no entities were created, return: []\n\nJSON:`;\n\n try {\n const response = await this.llm.invoke(prompt);\n const content = response.content as string;\n const match = content.match(/\\[[\\s\\S]*?\\]/);\n if (match) {\n const entities = JSON.parse(match[0]);\n return entities;\n }\n } catch {}\n return [];\n }\n\n /**\n * Validate that an entity matches the expected type\n */\n validateEntityType(\n entityId: string,\n expectedType: string,\n entities: EntityAssociation[]\n ): boolean {\n const stored = entities.find((e) => e.entityId === entityId);\n return !!stored && stored.entityType === expectedType;\n }\n\n /**\n * Resolve entity references with type validation\n */\n async resolveWithTypeValidation(\n query: string,\n entities: EntityAssociation[],\n expectedType?: string\n ): Promise<EntityAssociation[]> {\n await this.resolveReferences(query, entities);\n\n if (!expectedType) {\n return entities;\n }\n\n return entities.filter((entity) => entity.entityType === expectedType);\n }\n\n /**\n * Get entities filtered by type\n */\n getEntitiesByType(\n entities: EntityAssociation[],\n entityType: string\n ): EntityAssociation[] {\n return entities.filter((entity) => entity.entityType === entityType);\n }\n\n /**\n * Find the most recent entity of a specific type\n */\n getMostRecentEntityByType(\n entities: EntityAssociation[],\n entityType: string\n ): EntityAssociation | null {\n const filtered = entities.filter(\n (entity) => entity.entityType === entityType\n );\n if (filtered.length === 0) return null;\n\n return filtered.reduce((most, current) =>\n current.createdAt > most.createdAt ? current : most\n );\n }\n}\n","import type { MCPServerConfig } from './types';\n\n/**\n * Common MCP server configurations for easy setup\n */\nexport const MCPServers = {\n /**\n * Filesystem server for file operations\n */\n filesystem: (path: string): MCPServerConfig => ({\n name: 'filesystem',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-filesystem', path],\n transport: 'stdio',\n autoConnect: true,\n additionalContext: 'This server provides access to files and directories in the current working directory.',\n toolDescriptions: {\n list_directory: 'Use this tool when users ask about files in the \"current directory\" or \"working directory\".',\n read_file: 'Use this tool when users ask to see or check files in the current directory.',\n },\n }),\n\n /**\n * GitHub server for repository operations\n */\n github: (token?: string): MCPServerConfig => ({\n name: 'github',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-github'],\n ...(token && { env: { GITHUB_TOKEN: token } }),\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * Slack server for messaging operations\n */\n slack: (token: string): MCPServerConfig => ({\n name: 'slack',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-slack'],\n env: { SLACK_TOKEN: token },\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * Google Drive server for document operations\n */\n googleDrive: (credentials: string): MCPServerConfig => ({\n name: 'google-drive',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-google-drive'],\n env: { GOOGLE_CREDENTIALS: credentials },\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * PostgreSQL server for database operations\n */\n postgres: (connectionString: string): MCPServerConfig => ({\n name: 'postgres',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-postgres', connectionString],\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * SQLite server for database operations\n */\n sqlite: (dbPath: string): MCPServerConfig => ({\n name: 'sqlite',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-sqlite', dbPath],\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * Custom server configuration\n */\n custom: (config: MCPServerConfig): MCPServerConfig => config,\n};\n\n/**\n * Validate MCP server configuration\n */\nexport function validateServerConfig(config: MCPServerConfig): string[] {\n const errors: string[] = [];\n\n if (!config.name) {\n errors.push('Server name is required');\n }\n\n if (!config.command) {\n errors.push('Server command is required');\n }\n\n if (!config.args || !Array.isArray(config.args)) {\n errors.push('Server args must be an array');\n }\n\n if (config.transport && !['stdio', 'http', 'websocket'].includes(config.transport)) {\n errors.push('Invalid transport type. Must be stdio, http, or websocket');\n }\n\n return errors;\n}\n\n/**\n * Create a typed MCP configuration for ConversationalAgent\n */\nexport function createMCPConfig(servers: MCPServerConfig[], autoConnect = true): { mcpServers: MCPServerConfig[] } {\n return {\n mcpServers: servers.map(server => ({\n ...server,\n autoConnect: server.autoConnect ?? autoConnect,\n })),\n };\n}"],"names":["HCS10Plugin","BasePlugin","constructor","super","arguments","this","id","name","description","version","author","namespace","tools","initialize","context","hederaKit","config","stateManager","appConfig","OpenConvaiState","accountId","signer","getAccountId","toString","isBytesMode","String","operationalMode","operatorPrivateKeySerialized","inboundTopicId","outboundTopicId","operatorPrivateKeyRef","getOperatorPrivateKey","hcs10Client","HCS10Client","network","operatorId","operatorPrivateKey","logLevel","profileResponse","retrieveProfile","success","topicInfo","inboundTopic","outboundTopic","profileError","logger","warn","agentRecord","privateKey","setCurrentAgent","info","getConnectionsManager","initializeConnectionsManager","cmError","initializeTools","error","Error","hcs10Builder","HCS10Builder","RegisterAgentTool","FindRegistrationsTool","RetrieveProfileTool","InitiateConnectionTool","ListConnectionsTool","SendMessageToConnectionTool","CheckMessagesTool","ConnectionMonitorTool","ManageConnectionRequestsTool","AcceptConnectionRequestTool","ListUnapprovedConnectionRequestsTool","getTools","getStateManager","cleanup","HCS2Plugin","hcs2Builder","HCS2Builder","CreateRegistryTool","RegisterEntryTool","UpdateEntryTool","DeleteEntryTool","MigrateRegistryTool","QueryRegistryTool","fieldGuidanceRegistry","configurations","providers","registerOrderCounter","Logger","module","registerToolConfiguration","push","registerToolProvider","toolPattern","provider","options","length","priority","some","p","pattern","order","unregisterProvider","filter","listProviders","map","getFieldGuidance","toolName","fieldName","process","env","CA_FORM_GUIDANCE_ENABLED","toLowerCase","includes","test","fields","staticGuidance","pickMatchingProviders","merged","reverse","fromProvider","safeGetFieldGuidance","mergeGuidance","g","Object","keys","getGlobalGuidance","globalGuidance","base","mergedWarnings","warnings","mergedQuality","qualityStandards","safeGetGlobalGuidance","result","validateFieldValue","value","guidance","errors","isValid","warning","message","validationRules","rejectPatterns","qualityChecks","reject","reason","forbidTechnicalTerms","lowerValue","term","requireSpecificTerms","join","minNonTechnicalWords","split","word","clear","sort","a","b","m","winner","err","over","out","suggestions","predefinedOptions","fieldTypeOverride","contextualHelpText","InscribePlugin","providerId","e","inscriberBuilder","InscriberBuilder","InscribeFromUrlTool","InscribeFromFileTool","InscribeFromBufferTool","InscribeHashinalTool","RetrieveInscriptionTool","AccountBuilder","BaseServiceBuilder","transferHbar","params","isUserInitiated","clearNotes","transaction","TransferTransaction","transfers","netZeroInTinybars","BigNumber","userTransferProcessedForScheduling","kit","userAccountId","receiverTransfer","amountValue","amount","amountBigNum","isPositive","recipientAccountId","AccountId","fromString","roundedAmount","toFixed","ROUND_DOWN","sdkHbarAmount","Hbar","addNote","addHbarTransfer","negated","processedTransfers","transferInput","hbar","tinybarsContribution","toTinybars","plus","isZero","lastTransfer","adjustment","dividedBy","adjustedRounded","transfer","memo","setTransactionMemo","setCurrentTransaction","HbarTransferInputSchema","z","object","string","describe","union","number","TransferHbarZodSchemaCore","array","min","optional","TransferHbarTool","BaseHederaTransactionTool","specificInputSchema","getServiceBuilder","callBuilderMethod","builder","specificArgs","AirdropToolWrapper","StructuredTool","originalTool","agentKit","schema","tokenId","recipients","_call","input","decimals","getTokenInfo","convertedRecipients","recipient","humanAmount","parseFloat","smallestUnitAmount","convertToSmallestUnits","convertedInput","Math","floor","pow","queryTokenInfo","mirrorNode","tokenData","parseInt","mirrorNodeUrl","response","fetch","ok","json","HbarPlugin","originalAirdropTool","airdropTool","HederaAirdropTokenTool","wrappedAirdropTool","shutdown","FieldTypeRegistry","patterns","Map","initializeDefaultPatterns","getInstance","instance","register","type","key","set","unregister","delete","detectType","matches","values","isMatch","Array","isArray","RegExp","getPatterns","reset","fieldTypeRegistry","ERROR_MESSAGES","EntityFormat","ENTITY_PATTERNS","TOPIC_ID","TOKEN_ID","ACCOUNT_ID","CONTRACT_ID","FIELD_PRIORITIES","ESSENTIAL","COMMON","ADVANCED","EXPERT","isZodObjectSchema","FormGenerator","generateFormFromError","originalPrompt","validationErrors","extractValidationErrors","missingFields","identifyMissingFields","formConfig","createFormConfig","Date","now","random","substr","generateFormFromSchema","partialInput","preCalculatedMissingFields","hasSchema","hasShape","hasPreCalculatedFields","preCalculatedFieldsSize","size","missingFieldsCount","from","Set","zodObject","extractZodObject","shape","add","totalFields","toolDescription","issues","issue","path","code","_schema","forEach","fieldPath","extractedConfig","extractRenderConfigsSafely","fieldOrdering","generateFieldOrderingSafely","generateFormFields","generateFormDescription","standard","title","generateFormTitle","submitLabel","cancelLabel","metadata","missingFieldCount","extractRenderConfigs","groups","generateFieldOrdering","ordering","sections","section","getFieldPriority","renderConfig","isRequired","ui","advanced","expert","determineFieldsToInclude","fieldsToInclude","extractFieldsFromSchema","includeRequiredMissingFields","isFieldRequired","isMissing","has","shouldInclude","createOrderedFields","processedFields","flatMap","s","field","createFormField","mapFieldType","fieldType","finalType","label","humanizeFieldName","required","placeholder","helpText","w","contextualGuidance","examples","avoidPatterns","constraints","validation","max","minLength","maxLength","opt","disabled","inferredType","inferTypeFromSchema","registryType","normalizedType","replace","trim","charAt","toUpperCase","slice","def","_def","typeName","debug","firstOption","firstOptionObject","fieldSchema","fieldDef","innerType","fieldTypeName","lowerPath","defaultValue","fieldCount","generateJsonSchemaForm","zodSchema","fullJsonSchema","zodToJsonSchema","target","uiSchema","jsonSchema","fullSchemaAsObject","properties","filteredSchema","fieldsAdded","lower","collapsible","collapsed","FormEngine","formGenerator","generateForm","tool","fullContext","isFormValidatable","generateFormValidatableForm","ZodError","generateErrorBasedForm","hasRenderConfig","generateRenderConfigForm","isZodObject","generateSchemaBasedForm","processSubmission","submission","validateSubmission","baseToolInput","extractBaseToolInput","submissionData","extractSubmissionData","mergeInputData","shouldGenerateForm","inputRecord","__fromForm","renderForm","validateInput","toolSchema","_context","schemaToUse","isFocusedSchema","resolveFormSchema","determineMissingFields","generateFormWithSchema","formMessage","extractRenderConfig","parse","candidate","Boolean","_renderConfig","formValidatableTool","getFormSchema","focusedSchema","_isFocusedSchema","getEssentialFields","essentialFields","isFieldEmpty","parameters","originalInput","baseInput","getRegisteredStrategies","getRegisteredMiddleware","ResponseFormatter","isHashLinkResponse","parsed","responseObj","hashLinkBlock","formatHashLinkResponse","inscription","topicId","attributes","hrl","cdnUrl","creator","isInscriptionResponse","formatInscriptionResponse","formatResponse","toolOutput","JSON","globalPendingForms","FormAwareAgentExecutor","AgentExecutor","args","pendingForms","formEngine","formLogger","parameterPreprocessingCallback","ZodObject","hasHashLinkBlock","setParameterPreprocessingCallback","callback","_takeNextStep","nameToolMap","inputs","intermediateSteps","runManager","availableTools","inputKeys","agent","plan","getChild","action","toolInput","hasInNameToolMap","toolInputKeys","find","t","schemaFieldCount","schemaType","estimatedFieldCount","isEmpty","isEssential","willAddToMissingFields","formData","originalToolInput","toolRef","originalToolRef","formResult","requiresForm","observation","stringify","preprocessedInput","rf","__requestForm","formId","f","resolvedType","resolvedSchema","original","preprocessed","hasChanges","preprocessError","rawShape","fdef","inner","unwrapOptional","step","hasForm","actionToolName","toolInstance","originalToolCandidate","pf","output","hasHashLink","blockId","hashLinkResponse","processHashLinkResponse","hasHashLinkBlocks","handleValidationError","errorIssues","toolInfo","extractToolInfoFromError","fallbackTool","detectToolFromErrorContext","formatFormResponse","getPendingForms","restorePendingForms","forms","processFormSubmission","submissionFormId","submissionToolName","parameterKeys","parametersType","parametersIsNull","parametersIsUndefined","hasContext","pendingForm","get","mergedToolInput","baseKeys","submissionKeys","mergedKeys","maybeWrapper","executeOriginal","getOriginalTool","ot","otCall","call","tcall","formattedOutput","responseMetadata","jsonKeys","parsedRecord","hasTemplate","template","outputSample","substring","formCompleted","originalFormId","rawToolOutput","lastStep","inputSteps","toolFromContext","findToolFromContext","inputText","extractToolKeywords","keyword","errorPaths","schemaMatchesErrorPaths","schemaRecord","schemaKeys","topLevelKey","fieldList","hasPendingForms","getPendingFormsInfo","entries","toolResponse","hashLink","attributeCount","getFormEngineStatistics","strategies","middleware","BaseAgent","initialized","silent","getCore","filterTools","filtered","filtering","namespaceWhitelist","toolBlacklist","toolPredicate","buildSystemPrompt","parts","userAccId","execution","messaging","systemPreamble","scheduleUserTransactionsInBytesMode","conciseMode","systemPostamble","isReady","MCPContentProcessor","contentStorage","analyzeResponse","contents","totalSize","extractContentFromResponse","reduce","sum","content","sizeBytes","largestContentSize","shouldProcess","shouldUseReference","processResponse","serverName","analysis","wasProcessed","createReferencedResponse","obj","item","record","text","globalThis","Buffer","byteLength","mimeType","detectMimeType","data","ceil","resource","resourceStr","originalResponse","processedResponse","deepClone","referenceCreated","totalReferenceSize","contentInfo","contentBuffer","contentType","mapMimeTypeToContentType","source","mcpToolName","tags","reference","storeContentIfLarge","replaceContentInResponse","createLightweightReference","originalSize","referenceId","preview","format","_isReference","oldContent","newContent","i","newContentRecord","startsWith","getTime","cloned","hasOwnProperty","MCPClientManager","clients","contentProcessor","connectServer","isServerConnected","connected","transport","StdioClientTransport","command","client","Client","capabilities","connect","toolsWithServer","listTools","rest","executeTool","callTool","processed","disconnectAll","close","getAllTools","allTools","getServerTools","getConnectedServers","enableContentProcessing","disableContentProcessing","isContentProcessingEnabled","analyzeResponseContent","convertMCPToolToLangChain","mcpManager","serverConfig","jsonSchemaToZod","inputSchema","sanitizedName","toolDescriptions","additionalContext","DynamicStructuredTool","func","async","responseText","responseBuffer","MCP_REFERENCE_THRESHOLD","contentStore","ContentStoreService","storeContent","errorMessage","schemaObj","convertType","zodType","unknown","enum","minimum","maximum","int","boolean","items","passthrough","_TokenCounter","modelName","encoding","encoding_for_model","countTokens","encode","countMessageTokens","getMessageRole","MESSAGE_OVERHEAD","ROLE_OVERHEAD","countMessagesTokens","messages","total","estimateSystemPromptTokens","systemPrompt","estimateContextSize","_getType","getModelName","dispose","free","TokenCounter","_MemoryWindow","maxTokens","DEFAULT_MAX_TOKENS","reserveTokens","DEFAULT_RESERVE_TOKENS","tokenCounter","systemPromptTokens","addMessage","prunedMessages","getCurrentTokenCount","pop","pruneToFit","added","currentTokenCount","remainingCapacity","getRemainingTokenCapacity","targetTokens","batchSize","PRUNING_BATCH_SIZE","prunedMessage","shift","messageTokens","canAddMessage","wouldExceedReserve","getMessages","setSystemPrompt","getSystemPrompt","getConfig","currentTokens","messageCount","updateLimits","getStats","capacity","usagePercentage","totalMessages","round","canAcceptMore","MemoryWindow","ReferenceIdGenerator","generateId","hash","createHash","update","digest","isValidReferenceId","extractReferenceId","refFormatMatch","match","formatReference","generateTestId","testSeed","DEFAULT_CONTENT_REFERENCE_CONFIG","sizeThresholdBytes","maxAgeMs","maxReferences","maxTotalStorageBytes","enableAutoCleanup","cleanupIntervalMs","enablePersistence","storageBackend","cleanupPolicies","recent","userContent","agentGenerated","default","ContentReferenceError","suggestedActions","_ContentStorage","maxStorage","DEFAULT_MAX_STORAGE","referenceConfig","idCounter","referenceStats","activeReferences","totalStorageBytes","recentlyCleanedUp","totalResolutions","failedResolutions","averageContentSize","storageUtilization","performanceMetrics","averageCreationTimeMs","averageResolutionTimeMs","averageCleanupTimeMs","creationTimes","resolutionTimes","cleanupTimes","startReferenceCleanupTimer","storeMessages","stored","dropped","storedMessages","storedAt","getRecentMessages","count","startIndex","searchMessages","query","caseSensitive","limit","useRegex","regex","searchTerm","getMessagesFromTimeRange","startTime","endTime","getStorageStats","oldestMessageTime","newestMessageTime","maxStorageLimit","getTotalStoredMessages","updateStorageLimit","newLimit","getMessagesByType","messageType","currentUsage","utilizationPercentage","getRecentMessagesByTime","minutes","cutoffTime","exportMessages","toISOString","isBuffer","buffer","isImageContent","fileName","storeMetadata","detectContentType","customMetadata","fullMetadata","createdAt","lastAccessedAt","accessCount","storedContent","state","expirationTime","calculateExpirationTime","expiresAt","updateStatsAfterStore","enforceReferenceStorageLimits","createContentPreview","referenceMetadata","duration","recordPerformanceMetric","resolveReference","errorType","hasReference","cleanupReference","updateReferenceStorageStats","calculateAverage","updateConfig","cleanupTimer","clearInterval","performCleanup","cleanedUp","toCleanup","shouldCleanup","ageMs","getCleanupPolicy","aContent","bContent","aPriority","sortedByAge","excessCount","getReferenceConfig","policy","contentStr","mostAccessedId","maxAccess","mostAccessedReferenceId","lowerFileName","ext","endsWith","timeMs","metrics","times","time","setInterval","ContentStorage","IS_ENTITY_ASSOCIATION_FLAG","_SmartMemoryManager","DEFAULT_CONFIG","_contentStorage","storageLimit","memoryWindow","clearStorage","searchHistory","getRecentHistory","getMemoryStats","windowStats","totalActiveMessages","getOverallStats","memoryStats","storageStats","activeMemory","storage","totalMessagesManaged","activeMemoryUtilization","newConfig","getHistoryFromTimeRange","getHistoryByType","getRecentHistoryByTime","exportState","activeMessages","msg","getContextSummary","includeStoredContext","summary","activeMessageCount","recentMessages","memoryUtilization","hasStoredHistory","recentStoredMessages","performMaintenance","storeEntityAssociation","entityId","entityName","entityType","transactionId","sessionId","sanitizedEntityId","sanitizedEntityName","sanitizedEntityType","normalizeEntityType","usageHint","association","isEntityAssociation","usage","entityMessage","additional_kwargs","SystemMessage","raw","REGISTRY","topic","topicid","token","tokenid","account","accountid","contract","contractid","file","fileid","schedule","scheduleid","prototype","resolveEntityReference","sanitizedQuery","fuzzyMatch","safeLimit","isEntityIdQuery","searchResults","associations","fuzzyQueries","fuzzyQuery","fuzzyResults","uniqueAssociations","assoc","index","arr","findIndex","getEntityAssociations","rawFilter","filterCanonical","searchQuery","parseError","messageContent","mergedById","d","existing","existingTime","currentTime","SmartMemoryManager","FormValidatingToolWrapper","validationConfig","originalToolName","originalToolType","wrapperType","skipFields","getSchemaShape","hasFormValidatableMethod","methodName","calculateMissingFields","isCustom","createFormMessage","hasCustomValidation","customValidation","hasFormBypassFlags","schemaShape","stackTrace","stack","shouldGenerate","schemaFields","isCustomSchema","wrapToolWithFormValidation","ToolRegistry","registerTool","analyzeToolCapabilities","category","dependencies","entityResolutionPreferences","rawPrefs","schemaDef","metadataField","note","wrapper","finalTool","shouldWrapTool","requireAllFields","wrapperConfig","entry","capability","enabled","metaFG","fieldGuidance","fieldGuidanceProvider","getTool","getToolsByCapability","results","getToolsByQuery","getAllRegistryEntries","getToolNames","getToolsByPriority","getEnabledTools","getToolsByNamespace","hasCapability","updateToolOptions","hasTool","unregisterTool","implementsFormValidatable","isZodObjectLike","supportsFormValidation","requiresWrapper","toolAsAny","isMCPTool","isExtension","skipWrapper","forceWrapper","getStatistics","stats","totalTools","wrappedTools","unwrappedTools","categoryCounts","core","extension","mcp","priorityCounts","low","medium","high","critical","ExecutionPipeline","toolRegistry","memory","execute","sessionContext","traceId","toolEntry","session","buildDefaultSession","checkFormGeneration","executionTime","executeToolDirect","handleExecutionError","executeWithValidation","formSubmission","timestamp","processedInput","mergedArgs","executeWrappedTool","wrapperAsAny","totalMiddleware","registeredMiddleware","meta","block","LangChainAgent","systemMessage","mcpConnectionStatus","addToolRawToMemory","payload","smartMemory","persistToolRaw","isJSON","persistIntermediateSteps","steps","obs","getInscriptionTool","criticalTools","desc","useExecutionPipeline","executionPipeline","processedParameters","pendingParameterPreprocessingCallback","hasCallback","originalKeys","processedKeys","changes","createToolResponse","notes","handleToolExecution","isToolExecution","toolExecutionData","executor","handleDirectToolExecution","toolLineMatch","argsLineIndex","indexOf","argsText","handleJsonToolCalls","trimmed","handleContentRefMessages","idMatch","contentRef","withHashLinkBlocks","pending","chat_history","maybeRestore","outputMsg","processExecutorResult","outputStr","toolCalls","tool_calls","lastJsonObservation","formattedMessage","transactionBytes","scheduleId","blockMetadata","processHashLinkBlocks","AIMessage","tokenTracker","tokenUsage","getLatestTokenUsage","cost","calculateTokenCostSync","finalMemoryStats","loadContextMessages","existingMessages","existingContent","messageClass","HumanMessage","boot","createAgentKit","ai","OPENAI_MODEL_NAME","TokenUsageCallbackHandler","getAggregatedLangChainTools","filteredTools","originalCall","bind","metaOptions","transactionMemo","originalMemo","wrapped","unwrapped","categories","priorities","inscriptionTool","toolNames","uniqueNames","duplicates","servers","autoConnect","initializeMCP","toolsCount","createExecutor","chat","toolExecutionResult","directToolResult","jsonToolResult","contentRefResult","contextLength","currentMessages","instr","c","invoke","handleError","switchMode","mode","getUsageStats","promptTokens","completionTokens","totalTokens","totalCost","getTotalTokenUsage","getUsageLog","getTokenUsageHistory","clearUsageStats","getMCPConnectionStatus","errorInfo","safeSubmission","preservedMetadata","maybeRaw","outputMessage","hasMetadata","metadataKeys","hashLinkBlockContent","parsedSteps","plugins","getAllHederaCorePlugins","extensions","HederaAgentKit","mirrorConfig","existingPendingForms","llm","getModel","apiKey","OPENAI_API_KEY","isGPT5Model","ChatOpenAI","callbacks","temperature","prompt","ChatPromptTemplate","fromMessages","MessagesPlaceholder","langchainTools","createOpenAIToolsAgent","verbose","returnIntermediateSteps","userFriendlyMessage","userFriendlyOutput","errorResponse","status","mcpTool","langchainTool","connectMCPServers","connectServerInBackground","setTimeout","parsedResponse","responseRecord","attributeKeys","str","createAgent","framework","BrowserSigner","AbstractSigner","getNetwork","forMainnet","forTestnet","exec","ephemeralKey","PrivateKey","generateED25519","getClient","signAndExecuteTransaction","tx","isFrozen","freezeWith","base64","toBytes","mirror","HederaMirrorNode","deadline","details","getTransaction","TransactionReceipt","fromBytes","Promise","r","getPublicKey","anyKey","keyStr","PublicKey","LangChainProvider","model","generate","stream","chunk","providerRef","getWalletBridgeProvider","PageSnapshotSchema","url","maxCharacters","WebPageSnapshotTool","BaseHederaQueryTool","fetchImpl","executeQuery","maxChars","redirect","html","normalizeHtml","WebBrowserPlugin","getSystemMessage","ContentStorageAdapter","maxSize","enableCompression","resolve","ContentResolver","adapter","ContentStoreManager","maxMessageStorage","isRegistered","resolver","setInstance","ContentResolverRegistry","getContentStorage","isInitialized","ResolveEntitiesSchema","entities","ExtractEntitiesSchema","userMessage","ResolveEntitiesTool","byType","groupEntitiesByType","buildEntityContext","acc","entity","groupedEntities","list","ExtractEntitiesTool","llmResponse","createEntityTools","resolveEntities","extractEntities","FormatConverterRegistry","converters","entityTypeCache","defaultCacheTTL","converter","sourceFormat","targetFormat","findConverter","convertEntity","detectFormatWithFallback","canConvert","convert","HRL","cached","getCachedFormat","detected","detectFormat","ANY","setCachedFormat","detectEntityFormat","networkType","configureRetry","maxRetries","maxDelayMs","successful","allSettled","getAccountBalance","then","catch","getTopicInfo","getContract","isCacheExpired","ttl","getRegisteredConverters","hasConverter","clearCache","TopicIdToHrlConverter","_StringNormalizationConverter","toolPreferences","toolPrefs","fallbackStandard","hrlStandard","inscriptionHrlStandard","HRLResolver","cdnMatch","resolved","contentRefMatch","parseHRL","standardCache","StringNormalizationConverter","ParameterService","formatConverterRegistry","preprocessParameters","entityResolver","preferences","working","entityCount","aiProcessed","paramName","paramValue","resolveReferences","converted","convertParameterEntities","attachToAgent","deps","getSessionId","getEntities","maybe","attach","opts","getAgent","underlying","preprocessToolParameters","originalParams","convertedValue","originalArray","convertedArray","arrayChanged","convertedItem","parameterValue","containsEntityId","containsEntityName","SYMBOL","supplyKey","adminKey","ALIAS","convertedEntityValue","DEFAULT_MODEL_NAME","DEFAULT_OPENAI_MODEL","DEFAULT_CLAUDE_MODEL","DEFAULT_TEMPERATURE","DEFAULT_NETWORK","DEFAULT_OPERATIONAL_MODE","_ConversationalAgent","hcs10Plugin","hcs2Plugin","inscribePlugin","hbarPlugin","webBrowserPlugin","disableLogging","entityMemoryEnabled","openAIApiKey","memoryManager","entityMemoryConfig","entityMemoryProvider","llmProvider","resolverLLM","entityMemoryModelName","ChatAnthropic","baseURL","openRouterBaseURL","openRouterApiKey","configuration","defaultHeaders","OPENROUTER_REFERRER","OPENROUTER_TITLE","entityTools","openAIModelName","validateOptions","opMode","bytesMode","IB","setPreferWalletOnly","chain","effectiveAccount","walletExecutor","ServerSigner","signerClass","getPrototypeOf","bridge","setWalletInfoResolver","setWalletExecutor","executeBytes","setStartInscriptionDelegate","startInscription","request","enforceWallet","SignerProviderRegistry","extended","startHCS","setStartHCSDelegate","op","IB2","sakWireErr","providerInfo","keyPresent","modelName2","allPlugins","preparePlugins","agentConfig","createAgentConfig","configureHCS10Plugin","contentStoreManager","registry","cfg","originalPredicate","userPredicate","toolFilter","mcpServers","connectMCP","getPlugin","NOT_INITIALIZED_ERROR","getConversationalAgent","processMessage","chatHistory","resolvedMessage","extractAndStoreEntities","additionalPlugins","enabledPlugins","disabledPlugins","standardPlugins","corePlugins","pluginPool","enabledSet","plugin","disabledSet","additional","customSystemMessagePreamble","customSystemMessagePostamble","mirrorNodeConfig","scheduleUserTransactions","hcs10","withPlugins","withHTS","withHCS2","withHCS10","withInscribe","withAccount","withFileService","withConsensusService","withSmartContract","withAllStandards","minimal","withMCP","originalMessage","extractResponseText","entitiesJson","extractTransactionId","idStr","responseWithTxId","isMCPServerConnected","ConversationalAgent","processAttachments","attachments","attachmentCount","att","processWithContentStore","processWithSimpleReferences","contentReferences","attachment","base64Data","createInlineReference","fileList","createFileList","fileReferences","sizeStr","formatFileSize","fromEntries","mostRecent","messagePreview","entityStats","changed","hasEntityId","resolvedPreview","receiptEntities","extractFromReceipt","extractWithLLM","receipt","extractNameFromMessage","extractEntityId","contractId","fileId","FILE_ID","SCHEDULE_ID","quotedMatch","calledMatch","forMatch","namedMatch","validateEntityType","expectedType","resolveWithTypeValidation","getEntitiesByType","getMostRecentEntityByType","most","current","filesystem","list_directory","read_file","github","GITHUB_TOKEN","slack","SLACK_TOKEN","googleDrive","credentials","GOOGLE_CREDENTIALS","postgres","connectionString","sqlite","dbPath","custom","server"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/plugins/hcs-10/HCS10Plugin.ts","../../src/plugins/hcs-2/HCS2Plugin.ts","../../src/forms/field-guidance-registry.ts","../../src/plugins/inscribe/InscribePlugin.ts","../../src/plugins/hbar/AccountBuilder.ts","../../src/plugins/hbar/TransferHbarTool.ts","../../src/plugins/hbar/AirdropToolWrapper.ts","../../src/plugins/hbar/HbarPlugin.ts","../../src/plugins/community/swarm/constants.ts","../../src/plugins/community/swarm/utils.ts","../../src/plugins/community/swarm/tools/ListPostageStampsTool.ts","../../src/plugins/community/swarm/tools/UploadDataTool.ts","../../src/plugins/community/swarm/tools/DownloadDataTool.ts","../../src/plugins/community/swarm/tools/CreatePostageStampTool.ts","../../src/plugins/community/swarm/tools/ExtendPostageStampTool.ts","../../src/plugins/community/swarm/tools/QueryUploadProgressTool.ts","../../src/plugins/community/swarm/tools/DownloadFilesTool.ts","../../src/plugins/community/swarm/tools/GetPostageStampTool.ts","../../src/plugins/community/swarm/tools/ReadFeedTool.ts","../../src/plugins/community/swarm/tools/UpdateFeedTool.ts","../../src/plugins/community/swarm/tools/UploadFileTool.ts","../../src/plugins/community/swarm/tools/UploadFolderTool.ts","../../src/plugins/community/swarm/SwarmPlugin.ts","../../src/forms/field-type-registry.ts","../../src/constants/messages.ts","../../src/services/formatters/types.ts","../../src/constants/entity-references.ts","../../src/constants/form-priorities.ts","../../src/forms/form-generator.ts","../../src/forms/form-engine.ts","../../src/utils/response-formatter.ts","../../src/langchain/form-aware-agent-executor.ts","../../src/base-agent.ts","../../src/mcp/content-processor.ts","../../src/mcp/mcp-client-manager.ts","../../src/mcp/adapters/langchain.ts","../../src/memory/token-counter.ts","../../src/memory/memory-window.ts","../../src/memory/reference-id-generator.ts","../../src/types/content-reference.ts","../../src/memory/content-storage.ts","../../src/memory/smart-memory-manager.ts","../../src/langchain/form-validating-tool-wrapper.ts","../../src/core/tool-registry.ts","../../src/execution/execution-pipeline.ts","../../src/langchain/langchain-agent.ts","../../src/agent-factory.ts","../../src/signers/browser-signer.ts","../../src/providers.ts","../../src/runtime/wallet-bridge.ts","../../src/plugins/web-browser/WebBrowserPlugin.ts","../../src/config/system-message.ts","../../src/services/content-store-manager.ts","../../src/tools/entity-resolver-tool.ts","../../src/services/formatters/format-converter-registry.ts","../../src/services/formatters/converters/topic-id-to-hrl-converter.ts","../../src/services/formatters/converters/string-normalization-converter.ts","../../src/services/parameter-service.ts","../../src/conversational-agent.ts","../../src/services/attachment-processor.ts","../../src/services/entity-resolver.ts","../../src/mcp/helpers.ts"],"sourcesContent":["import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n} from 'hedera-agent-kit';\nimport {\n IStateManager,\n OpenConvaiState,\n HCS10Builder,\n RegisterAgentTool,\n FindRegistrationsTool,\n InitiateConnectionTool,\n ListConnectionsTool,\n SendMessageToConnectionTool,\n CheckMessagesTool,\n ConnectionMonitorTool,\n ManageConnectionRequestsTool,\n AcceptConnectionRequestTool,\n RetrieveProfileTool,\n ListUnapprovedConnectionRequestsTool,\n RegisteredAgent,\n} from '@hashgraphonline/standards-agent-kit';\nimport { HCS10Client } from '@hashgraphonline/standards-sdk';\nimport { PrivateKey } from 'node_modules/@hashgraph/sdk/lib/Mnemonic';\n\ninterface HCS10ClientManager {\n initializeConnectionsManager(client: HCS10Client): void;\n}\n\nfunction hasInitializeConnectionsManager(\n stateManager: IStateManager\n): stateManager is IStateManager & HCS10ClientManager {\n return (\n typeof stateManager === 'object' &&\n stateManager !== null &&\n 'initializeConnectionsManager' in stateManager &&\n typeof stateManager.initializeConnectionsManager === 'function'\n );\n}\n\nexport class HCS10Plugin extends BasePlugin {\n id = 'hcs-10';\n name = 'HCS-10 Plugin';\n description =\n 'HCS-10 agent tools for decentralized agent registration, connections, and messaging on Hedera';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'hcs10';\n\n private stateManager?: IStateManager;\n private tools: any[] = [];\n appConfig?: Record<string, unknown>;\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. HCS-10 tools will not be available.'\n );\n return;\n }\n\n try {\n this.stateManager =\n (context.stateManager as IStateManager) ||\n (context.config.stateManager as IStateManager) ||\n (this.appConfig?.stateManager as IStateManager) ||\n new OpenConvaiState();\n\n const accountId = hederaKit.signer.getAccountId().toString();\n const isBytesMode =\n String(hederaKit.operationalMode || 'returnBytes') === 'returnBytes';\n let inboundTopicId = '';\n let outboundTopicId = '';\n\n let operatorPrivateKeyRef: PrivateKey =\n hederaKit.signer.getOperatorPrivateKey();\n let operatorPrivateKeySerialized: string | undefined;\n\n try {\n const resolved =\n typeof operatorPrivateKeyRef?.toString === 'function'\n ? operatorPrivateKeyRef.toString()\n : '';\n\n operatorPrivateKeySerialized = resolved;\n\n const hcs10Client = new HCS10Client({\n network: hederaKit.network as 'mainnet' | 'testnet',\n operatorId: accountId,\n operatorPrivateKey: operatorPrivateKeyRef,\n logLevel: 'error',\n });\n\n const profileResponse = await hcs10Client.retrieveProfile(accountId);\n if (profileResponse.success && profileResponse.topicInfo) {\n inboundTopicId = profileResponse.topicInfo.inboundTopic;\n outboundTopicId = profileResponse.topicInfo.outboundTopic;\n }\n } catch (profileError) {\n this.context.logger.warn(\n 'Skipping profile topic discovery',\n profileError\n );\n }\n\n const agentRecord: Record<string, unknown> = {\n name: `Agent ${accountId}`,\n accountId: accountId,\n inboundTopicId,\n outboundTopicId,\n };\n if (!isBytesMode && operatorPrivateKeySerialized) {\n agentRecord.privateKey = operatorPrivateKeySerialized;\n }\n this.stateManager.setCurrentAgent(\n agentRecord as unknown as RegisteredAgent\n );\n\n this.context.logger.info(\n `Set current agent: ${accountId} with topics ${inboundTopicId}/${outboundTopicId}`\n );\n\n if (\n !isBytesMode &&\n this.stateManager &&\n !this.stateManager.getConnectionsManager()\n ) {\n try {\n const hcs10Client = new HCS10Client({\n network: hederaKit.network as 'mainnet' | 'testnet',\n operatorId: accountId,\n operatorPrivateKey: operatorPrivateKeyRef ?? '',\n logLevel: 'error',\n });\n\n if (hasInitializeConnectionsManager(this.stateManager)) {\n this.stateManager.initializeConnectionsManager(hcs10Client);\n } else {\n this.context.logger.warn(\n 'StateManager does not support connection manager initialization'\n );\n }\n this.context.logger.info(\n 'ConnectionsManager initialized in HCS10Plugin'\n );\n } catch (cmError) {\n this.context.logger.warn(\n 'Could not initialize ConnectionsManager:',\n cmError\n );\n }\n }\n\n this.initializeTools();\n this.context.logger.info('HCS-10 Plugin initialized successfully');\n } catch (error) {\n this.context.logger.error('Failed to initialize HCS-10 plugin:', error);\n }\n }\n\n private initializeTools(): void {\n if (!this.stateManager) {\n throw new Error('StateManager must be initialized before creating tools');\n }\n\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 hcs10Builder = new HCS10Builder(hederaKit, this.stateManager);\n\n this.tools = [\n new RegisterAgentTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new FindRegistrationsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new RetrieveProfileTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new InitiateConnectionTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ListConnectionsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new SendMessageToConnectionTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new CheckMessagesTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ConnectionMonitorTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ManageConnectionRequestsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new AcceptConnectionRequestTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n new ListUnapprovedConnectionRequestsTool({\n hederaKit: hederaKit,\n hcs10Builder: hcs10Builder,\n logger: this.context.logger,\n }),\n ];\n }\n\n getTools(): HederaTool[] {\n return this.tools;\n }\n\n getStateManager(): IStateManager | undefined {\n return this.stateManager;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n delete this.stateManager;\n if (this.context?.logger) {\n this.context.logger.info('HCS-10 Plugin cleaned up');\n }\n }\n}\n","import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n} from 'hedera-agent-kit';\nimport {\n HCS2Builder,\n CreateRegistryTool,\n RegisterEntryTool,\n UpdateEntryTool,\n DeleteEntryTool,\n MigrateRegistryTool,\n QueryRegistryTool,\n} from '@hashgraphonline/standards-agent-kit';\n\n/**\n * Plugin providing HCS-2 registry management tools\n */\nexport class HCS2Plugin extends BasePlugin {\n id = 'hcs-2';\n name = 'HCS-2 Plugin';\n description =\n 'HCS-2 registry management tools for decentralized registries on Hedera';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'hcs2';\n\n private tools: any[] = [];\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. HCS-2 tools will not be available.'\n );\n return;\n }\n\n try {\n this.initializeTools();\n\n this.context.logger.info(\n 'HCS-2 Plugin initialized successfully'\n );\n } catch (error) {\n this.context.logger.error(\n 'Failed to initialize HCS-2 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 const hcs2Builder = new HCS2Builder(hederaKit);\n\n this.tools = [\n new CreateRegistryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new RegisterEntryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new UpdateEntryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new DeleteEntryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new MigrateRegistryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n new QueryRegistryTool({\n hederaKit: hederaKit,\n hcs2Builder: hcs2Builder,\n logger: this.context.logger,\n }),\n ];\n }\n\n getTools(): HederaTool[] {\n return this.tools;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n if (this.context?.logger) {\n this.context.logger.info('HCS-2 Plugin cleaned up');\n }\n }\n}\n","import type { FormFieldType, FieldOption } from './types';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * Field guidance configuration for providing contextual help and suggestions\n */\nexport interface FieldGuidance {\n /**\n * Suggestions to show as placeholder or examples\n */\n suggestions?: string[];\n\n /**\n * Predefined options for select fields\n */\n predefinedOptions?: FieldOption[];\n\n /**\n * Warning messages for specific patterns to avoid\n */\n warnings?: {\n pattern: RegExp;\n message: string;\n }[];\n\n /**\n * Validation rules specific to the field context\n */\n validationRules?: {\n /**\n * Patterns that should be rejected\n */\n rejectPatterns?: {\n pattern: RegExp;\n reason: string;\n }[];\n\n /**\n * Minimum quality requirements\n */\n qualityChecks?: {\n minNonTechnicalWords?: number;\n requireSpecificTerms?: string[];\n forbidTechnicalTerms?: string[];\n };\n };\n\n /**\n * Field type override for specific contexts\n */\n fieldTypeOverride?: FormFieldType;\n\n /**\n * Help text specific to the tool context\n */\n contextualHelpText?: string;\n}\n\n/**\n * Tool-specific field configurations\n */\nexport interface ToolFieldConfiguration {\n /**\n * Tool name or pattern to match\n */\n toolPattern: string | RegExp;\n\n /**\n * Field-specific guidance\n */\n fields: Record<string, FieldGuidance>;\n\n /**\n * Global guidance for all fields in this tool\n */\n globalGuidance?: {\n /**\n * General warnings to show\n */\n warnings?: string[];\n\n /**\n * Quality standards for this tool\n */\n qualityStandards?: string[];\n };\n}\n\n/**\n * Registry for field guidance configurations\n */\nclass FieldGuidanceRegistry {\n private configurations: ToolFieldConfiguration[] = [];\n private providers: Array<{\n id: string;\n priority: number;\n pattern: string | RegExp;\n provider: FieldGuidanceProvider;\n order: number;\n }> = [];\n private registerOrderCounter = 0;\n private logger: Logger;\n\n constructor() {\n this.logger = new Logger({ module: 'FieldGuidanceRegistry' });\n }\n\n /**\n * Register field guidance for a specific tool\n */\n registerToolConfiguration(config: ToolFieldConfiguration): void {\n this.configurations.push(config);\n }\n\n /**\n * Register a provider for dynamic field/global guidance\n */\n registerToolProvider(\n toolPattern: string | RegExp,\n provider: FieldGuidanceProvider,\n options?: { id?: string; priority?: number }\n ): string {\n const id = options?.id ?? `provider-${this.providers.length + 1}`;\n const priority = options?.priority ?? 0;\n if (this.providers.some((p) => p.id === id)) {\n this.logger.error('Duplicate provider id', { id });\n throw new Error('DUPLICATE_PROVIDER_ID');\n }\n this.providers.push({\n id,\n priority,\n pattern: toolPattern,\n provider,\n order: this.registerOrderCounter++,\n });\n return id;\n }\n\n /** Unregister a provider by id */\n unregisterProvider(id: string): void {\n this.providers = this.providers.filter((p) => p.id !== id);\n }\n\n /** List registered providers */\n listProviders(): Array<{\n id: string;\n priority: number;\n pattern: string | RegExp;\n }> {\n return this.providers.map(({ id, priority, pattern }) => ({\n id,\n priority,\n pattern,\n }));\n }\n\n /**\n * Get field guidance for a specific tool and field\n */\n getFieldGuidance(toolName: string, fieldName: string): FieldGuidance | null {\n if (process.env.CA_FORM_GUIDANCE_ENABLED === 'false') {\n return null;\n }\n for (const config of this.configurations) {\n const matches =\n typeof config.toolPattern === 'string'\n ? toolName.toLowerCase().includes(config.toolPattern.toLowerCase())\n : config.toolPattern.test(toolName);\n\n if (matches && config.fields[fieldName]) {\n const staticGuidance = config.fields[fieldName];\n const providers = this.pickMatchingProviders(toolName);\n if (providers.length === 0) return staticGuidance;\n let merged: FieldGuidance = { ...staticGuidance };\n for (const p of [...providers].reverse()) {\n const fromProvider = this.safeGetFieldGuidance(\n p,\n fieldName,\n toolName\n );\n if (fromProvider) {\n merged = this.mergeGuidance(merged, fromProvider);\n }\n }\n return merged;\n }\n }\n const providers = this.pickMatchingProviders(toolName);\n if (providers.length > 0) {\n let merged: FieldGuidance = {};\n for (const p of [...providers].reverse()) {\n const g = this.safeGetFieldGuidance(p, fieldName, toolName);\n if (g) merged = this.mergeGuidance(merged, g);\n }\n return Object.keys(merged).length > 0 ? merged : null;\n }\n return null;\n }\n\n /**\n * Get global guidance for a tool\n */\n getGlobalGuidance(\n toolName: string\n ): ToolFieldConfiguration['globalGuidance'] | null {\n if (process.env.CA_FORM_GUIDANCE_ENABLED === 'false') {\n return null;\n }\n for (const config of this.configurations) {\n const matches =\n typeof config.toolPattern === 'string'\n ? toolName.toLowerCase().includes(config.toolPattern.toLowerCase())\n : config.toolPattern.test(toolName);\n\n if (matches && config.globalGuidance) {\n const base = config.globalGuidance;\n const providers = this.pickMatchingProviders(toolName);\n if (providers.length === 0) return base;\n let mergedWarnings: string[] | undefined = base.warnings;\n let mergedQuality: string[] | undefined = base.qualityStandards;\n for (const p of [...providers].reverse()) {\n const fromProvider = this.safeGetGlobalGuidance(p, toolName);\n if (fromProvider) {\n mergedWarnings = fromProvider.warnings ?? mergedWarnings;\n mergedQuality = fromProvider.qualityStandards ?? mergedQuality;\n }\n }\n const result: NonNullable<ToolFieldConfiguration['globalGuidance']> =\n {};\n if (mergedWarnings !== undefined) result.warnings = mergedWarnings;\n if (mergedQuality !== undefined)\n result.qualityStandards = mergedQuality;\n return result;\n }\n }\n const providers = this.pickMatchingProviders(toolName);\n if (providers.length > 0) {\n let mergedWarnings: string[] | undefined;\n let mergedQuality: string[] | undefined;\n for (const p of [...providers].reverse()) {\n const g = this.safeGetGlobalGuidance(p, toolName);\n if (g) {\n mergedWarnings = g.warnings ?? mergedWarnings;\n mergedQuality = g.qualityStandards ?? mergedQuality;\n }\n }\n const result: NonNullable<ToolFieldConfiguration['globalGuidance']> = {};\n if (mergedWarnings !== undefined) result.warnings = mergedWarnings;\n if (mergedQuality !== undefined) result.qualityStandards = mergedQuality;\n return Object.keys(result).length > 0 ? result : null;\n }\n return null;\n }\n\n /**\n * Validate field value against guidance rules\n */\n validateFieldValue(\n toolName: string,\n fieldName: string,\n value: unknown\n ): {\n isValid: boolean;\n warnings: string[];\n errors: string[];\n } {\n const guidance = this.getFieldGuidance(toolName, fieldName);\n const warnings: string[] = [];\n const errors: string[] = [];\n\n if (!guidance || typeof value !== 'string') {\n return { isValid: true, warnings, errors };\n }\n\n if (guidance.warnings) {\n for (const warning of guidance.warnings) {\n if (warning.pattern.test(value)) {\n warnings.push(warning.message);\n }\n }\n }\n\n if (guidance.validationRules) {\n const { rejectPatterns, qualityChecks } = guidance.validationRules;\n\n if (rejectPatterns) {\n for (const reject of rejectPatterns) {\n if (reject.pattern.test(value)) {\n errors.push(`Rejected: ${reject.reason}`);\n }\n }\n }\n\n if (qualityChecks) {\n if (qualityChecks.forbidTechnicalTerms) {\n const lowerValue = value.toLowerCase();\n for (const term of qualityChecks.forbidTechnicalTerms) {\n if (lowerValue.includes(term.toLowerCase())) {\n errors.push(\n `Avoid technical terms like \"${term}\" in NFT metadata`\n );\n }\n }\n }\n\n if (qualityChecks.requireSpecificTerms) {\n const lowerValue = value.toLowerCase();\n const hasRequired = qualityChecks.requireSpecificTerms.some((term) =>\n lowerValue.includes(term.toLowerCase())\n );\n if (!hasRequired) {\n warnings.push(\n `Consider including terms like: ${qualityChecks.requireSpecificTerms.join(\n ', '\n )}`\n );\n }\n }\n\n if (qualityChecks.minNonTechnicalWords) {\n const words = value.split(/\\s+/).filter((word) => word.length > 2);\n if (words.length < qualityChecks.minNonTechnicalWords) {\n warnings.push(\n `Consider providing more descriptive content (at least ${qualityChecks.minNonTechnicalWords} meaningful words)`\n );\n }\n }\n }\n }\n\n return {\n isValid: errors.length === 0,\n warnings,\n errors,\n };\n }\n\n /**\n * Clear all configurations (useful for testing)\n */\n clear(): void {\n this.configurations = [];\n this.providers = [];\n this.registerOrderCounter = 0;\n }\n\n /** Choose matching provider by priority then last-in wins */\n private pickMatchingProviders(toolName: string): Array<{\n id: string;\n provider: FieldGuidanceProvider;\n priority: number;\n order: number;\n }> {\n const matches = this.providers.filter((p) =>\n typeof p.pattern === 'string'\n ? toolName.toLowerCase().includes((p.pattern as string).toLowerCase())\n : (p.pattern as RegExp).test(toolName)\n );\n const sorted = matches.sort((a, b) => {\n if (b.priority !== a.priority) return b.priority - a.priority;\n return b.order - a.order; // last-in wins when equal priority\n });\n return sorted.map((m) => ({\n id: m.id,\n provider: m.provider,\n priority: m.priority,\n order: m.order,\n }));\n }\n\n private safeGetFieldGuidance(\n winner: { id: string; provider: FieldGuidanceProvider },\n fieldName: string,\n toolName: string\n ): FieldGuidance | null {\n try {\n return winner.provider.getFieldGuidance(fieldName, { toolName }) ?? null;\n } catch (err) {\n this.logger.warn('Provider getFieldGuidance failed', {\n id: winner.id,\n err,\n });\n return null;\n }\n }\n\n private safeGetGlobalGuidance(\n winner: { id: string; provider: FieldGuidanceProvider },\n toolName: string\n ): ToolFieldConfiguration['globalGuidance'] | null {\n try {\n return winner.provider.getGlobalGuidance?.(toolName) ?? null;\n } catch (err) {\n this.logger.warn('Provider getGlobalGuidance failed', {\n id: winner.id,\n err,\n });\n return null;\n }\n }\n\n private mergeGuidance(\n base: FieldGuidance,\n over: FieldGuidance\n ): FieldGuidance {\n const out: FieldGuidance = {};\n const suggestions = over.suggestions ?? base.suggestions;\n if (suggestions !== undefined) out.suggestions = suggestions;\n const predefinedOptions = over.predefinedOptions ?? base.predefinedOptions;\n if (predefinedOptions !== undefined)\n out.predefinedOptions = predefinedOptions;\n const warnings = over.warnings ?? base.warnings;\n if (warnings !== undefined) out.warnings = warnings;\n const validationRules = over.validationRules ?? base.validationRules;\n if (validationRules !== undefined) out.validationRules = validationRules;\n const fieldTypeOverride = over.fieldTypeOverride ?? base.fieldTypeOverride;\n if (fieldTypeOverride !== undefined)\n out.fieldTypeOverride = fieldTypeOverride;\n const contextualHelpText =\n over.contextualHelpText ?? base.contextualHelpText;\n if (contextualHelpText !== undefined)\n out.contextualHelpText = contextualHelpText;\n return out;\n }\n}\n\nexport const fieldGuidanceRegistry = new FieldGuidanceRegistry();\n\n/**\n * Provider interface (optional, for dynamic guidance)\n */\nexport interface FieldGuidanceProvider {\n getFieldGuidance(\n fieldName: string,\n ctx: { toolName: string }\n ): FieldGuidance | null;\n getGlobalGuidance?(\n toolName: string\n ): ToolFieldConfiguration['globalGuidance'] | null;\n}\n","import {\n GenericPluginContext,\n HederaTool,\n BasePlugin,\n HederaAgentKit,\n} from 'hedera-agent-kit';\nimport {\n InscriberBuilder,\n InscribeFromUrlTool,\n InscribeFromFileTool,\n InscribeFromBufferTool,\n InscribeHashinalTool,\n RetrieveInscriptionTool,\n} from '@hashgraphonline/standards-agent-kit';\nimport { fieldGuidanceRegistry, type FieldGuidance } from '../../forms/field-guidance-registry';\n\n/**\n * Plugin providing content inscription tools for Hedera\n */\nexport class InscribePlugin extends BasePlugin {\n id = 'inscribe';\n name = 'Inscribe Plugin';\n description =\n 'Content inscription tools for storing data on Hedera Consensus Service';\n version = '1.0.0';\n author = 'Hashgraph Online';\n namespace = 'inscribe';\n\n private tools: any[] = [];\n private providerId: string | 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. Inscription tools will not be available.'\n );\n return;\n }\n\n try {\n this.initializeTools();\n\n try {\n const provider = {\n getFieldGuidance: (fieldName: string): FieldGuidance | null => {\n if (fieldName === 'name') {\n return {\n suggestions: [\n 'Sunset Landscape #42',\n 'Digital Abstract Art',\n ],\n contextualHelpText:\n 'Create a distinctive name that collectors will find appealing',\n };\n }\n if (fieldName === 'description') {\n return {\n fieldTypeOverride: 'textarea',\n suggestions: ['A beautiful piece representing...'],\n };\n }\n return null;\n },\n getGlobalGuidance: () => ({\n qualityStandards: [\n 'Use meaningful names that describe the artwork or content',\n ],\n }),\n };\n this.providerId = fieldGuidanceRegistry.registerToolProvider(\n /hashinal/i,\n provider,\n { id: 'inscribe:hashinal:provider', priority: 1 }\n );\n } catch (e) {\n this.context.logger.warn('Could not register Inscribe field guidance provider');\n }\n\n this.context.logger.info(\n 'Inscribe Plugin initialized successfully'\n );\n } catch (error) {\n this.context.logger.error(\n 'Failed to initialize Inscribe 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 const inscriberBuilder = new InscriberBuilder(hederaKit);\n\n this.tools = [\n new InscribeFromUrlTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new InscribeFromFileTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new InscribeFromBufferTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new InscribeHashinalTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n new RetrieveInscriptionTool({\n hederaKit: hederaKit,\n inscriberBuilder: inscriberBuilder,\n logger: this.context.logger,\n }),\n ];\n }\n\n getTools(): HederaTool[] {\n return this.tools;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n if (this.providerId) {\n try {\n fieldGuidanceRegistry.unregisterProvider(this.providerId);\n } catch {}\n this.providerId = null;\n }\n if (this.context?.logger) {\n this.context.logger.info('Inscribe Plugin cleaned up');\n }\n }\n}\n","import { AccountId, Hbar, TransferTransaction } from '@hashgraph/sdk';\nimport BigNumber from 'bignumber.js';\nimport { HederaAgentKit, BaseServiceBuilder } from 'hedera-agent-kit';\nimport { HbarTransferParams } from './types';\n\n/**\n * Custom AccountBuilder that properly handles HBAR decimal conversion\n */\nexport class AccountBuilder extends BaseServiceBuilder {\n constructor(hederaKit: HederaAgentKit) {\n super(hederaKit);\n }\n\n /**\n * Transfers HBAR between accounts with proper decimal handling\n */\n public transferHbar(\n params: HbarTransferParams,\n isUserInitiated: boolean = true\n ): this {\n this.clearNotes();\n const transaction = new TransferTransaction();\n\n if (!params.transfers || params.transfers.length === 0) {\n throw new Error('HbarTransferParams must include at least one transfer.');\n }\n\n let netZeroInTinybars = new BigNumber(0);\n let userTransferProcessedForScheduling = false;\n\n if (\n isUserInitiated &&\n this.kit.userAccountId &&\n (this.kit.operationalMode as string) === 'provideBytes' &&\n params.transfers.length === 1\n ) {\n const receiverTransfer = params.transfers[0];\n const amountValue =\n typeof receiverTransfer.amount === 'string' ||\n typeof receiverTransfer.amount === 'number'\n ? receiverTransfer.amount\n : receiverTransfer.amount.toString();\n\n const amountBigNum = new BigNumber(amountValue);\n\n if (amountBigNum.isPositive()) {\n const recipientAccountId =\n typeof receiverTransfer.accountId === 'string'\n ? AccountId.fromString(receiverTransfer.accountId)\n : receiverTransfer.accountId;\n\n const roundedAmount = amountBigNum.toFixed(8, BigNumber.ROUND_DOWN);\n const sdkHbarAmount = Hbar.fromString(roundedAmount);\n\n this.logger.info(\n `[AccountBuilder.transferHbar] Configuring user-initiated scheduled transfer: ${sdkHbarAmount.toString()} from ${\n this.kit.userAccountId\n } to ${recipientAccountId.toString()}`\n );\n\n this.addNote(\n `Configured HBAR transfer from your account (${\n this.kit.userAccountId\n }) to ${recipientAccountId.toString()} for ${sdkHbarAmount.toString()}.`\n );\n\n transaction.addHbarTransfer(recipientAccountId, sdkHbarAmount);\n transaction.addHbarTransfer(\n AccountId.fromString(this.kit.userAccountId),\n sdkHbarAmount.negated()\n );\n\n userTransferProcessedForScheduling = true;\n }\n }\n\n if (!userTransferProcessedForScheduling) {\n const processedTransfers: Array<{\n accountId: AccountId;\n amount: BigNumber;\n hbar: Hbar;\n }> = [];\n\n for (const transferInput of params.transfers) {\n const accountId =\n typeof transferInput.accountId === 'string'\n ? AccountId.fromString(transferInput.accountId)\n : transferInput.accountId;\n\n const amountValue =\n typeof transferInput.amount === 'string' ||\n typeof transferInput.amount === 'number'\n ? transferInput.amount\n : transferInput.amount.toString();\n\n const amountBigNum = new BigNumber(amountValue);\n const roundedAmount = amountBigNum.toFixed(8, BigNumber.ROUND_DOWN);\n\n this.logger.info(\n `Processing transfer: ${amountValue} HBAR (rounded to ${roundedAmount}) for account ${accountId.toString()}`\n );\n\n const sdkHbarAmount = Hbar.fromString(roundedAmount);\n processedTransfers.push({\n accountId,\n amount: amountBigNum,\n hbar: sdkHbarAmount,\n });\n\n const tinybarsContribution = sdkHbarAmount.toTinybars();\n netZeroInTinybars = netZeroInTinybars.plus(\n tinybarsContribution.toString()\n );\n }\n\n if (!netZeroInTinybars.isZero()) {\n this.logger.warn(\n `Transfer sum not zero: ${netZeroInTinybars.toString()} tinybars off. Adjusting last transfer.`\n );\n\n if (processedTransfers.length > 0) {\n const lastTransfer =\n processedTransfers[processedTransfers.length - 1];\n const adjustment = netZeroInTinybars.dividedBy(-100000000);\n const adjustedAmount = lastTransfer.amount.plus(adjustment);\n const adjustedRounded = adjustedAmount.toFixed(\n 8,\n BigNumber.ROUND_DOWN\n );\n lastTransfer.hbar = Hbar.fromString(adjustedRounded);\n\n this.logger.info(\n `Adjusted last transfer for ${lastTransfer.accountId.toString()} to ${adjustedRounded} HBAR`\n );\n }\n }\n\n for (const transfer of processedTransfers) {\n transaction.addHbarTransfer(transfer.accountId, transfer.hbar);\n }\n }\n\n if (typeof params.memo !== 'undefined') {\n if (params.memo === null) {\n this.logger.warn('Received null for memo in transferHbar.');\n } else {\n transaction.setTransactionMemo(params.memo);\n }\n }\n\n this.setCurrentTransaction(transaction);\n return this;\n }\n}\n","import { z } from 'zod';\nimport { HbarTransferParams } from './types';\nimport { AccountBuilder } from './AccountBuilder';\nimport { BaseHederaTransactionTool, BaseServiceBuilder } from 'hedera-agent-kit';\n\nconst HbarTransferInputSchema = z.object({\n accountId: z\n .string()\n .describe('Account ID for the transfer (e.g., \"0.0.xxxx\").'),\n amount: z\n .union([z.number(), z.string()])\n .describe(\n 'HBAR amount in decimal format (e.g., 1 for 1 HBAR, 0.5 for 0.5 HBAR). Positive for credit, negative for debit. DO NOT multiply by 10^8 for tinybars - just use the HBAR amount directly.'\n ),\n});\n\nconst TransferHbarZodSchemaCore = z.object({\n transfers: z\n .array(HbarTransferInputSchema)\n .min(1)\n .describe(\n 'Array of transfers. For simple transfers from your operator account, just include the recipient with positive amount: [{accountId: \"0.0.800\", amount: 1}]. For complex multi-party transfers, include all parties with negative amounts for senders and positive for receivers.'\n ),\n memo: z.string().optional().describe('Optional. Memo for the transaction.'),\n});\n\n/**\n * A Hedera transaction tool for transferring HBAR between accounts.\n * Supports single and multi-party transfers with automatic balance validation.\n * Extends BaseHederaTransactionTool to handle HBAR transfer transactions on the Hedera Hashgraph.\n */\nexport class TransferHbarTool extends BaseHederaTransactionTool<\n typeof TransferHbarZodSchemaCore\n> {\n name = 'hedera-account-transfer-hbar-v2';\n description =\n 'PRIMARY TOOL FOR HBAR TRANSFERS: Transfers HBAR between accounts. For simple transfers from the operator account, just specify the recipient with a positive amount (e.g., [{accountId: \"0.0.800\", amount: 1}] to send 1 HBAR to 0.0.800). The sender will be automatically added. For multi-party transfers (e.g., \"A sends 5 HBAR to C and B sends 3 HBAR to C\"), include ALL transfers with their amounts (negative for senders, positive for receivers).';\n specificInputSchema = TransferHbarZodSchemaCore;\n namespace = 'account';\n\n\n /**\n * Creates and returns the service builder for account operations.\n * \n * @returns BaseServiceBuilder instance configured for account operations\n */\n protected getServiceBuilder(): BaseServiceBuilder {\n return new AccountBuilder(this.hederaKit) as BaseServiceBuilder;\n }\n\n /**\n * Executes the HBAR transfer using the provided builder and arguments.\n * Validates that all transfers sum to zero before execution.\n * \n * @param builder - The service builder instance for executing transactions\n * @param specificArgs - The validated transfer parameters including transfers array and optional memo\n * @returns Promise that resolves when the transfer is complete\n */\n protected async callBuilderMethod(\n builder: BaseServiceBuilder,\n specificArgs: z.infer<typeof TransferHbarZodSchemaCore>\n ): Promise<void> {\n await (builder as AccountBuilder).transferHbar(\n specificArgs as unknown as HbarTransferParams\n );\n }\n}","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { HederaAgentKit } from 'hedera-agent-kit';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\ninterface TokenInfo {\n decimals: number;\n [key: string]: unknown;\n}\n\ninterface ToolWithCall {\n _call(input: unknown): Promise<string>;\n}\n\ninterface AgentKitWithMirrorNode {\n mirrorNode?: {\n getTokenInfo(tokenId: string): Promise<TokenInfo>;\n };\n network: string;\n}\n\nexport class AirdropToolWrapper extends StructuredTool {\n name = 'hedera-hts-airdrop-token';\n description =\n 'Airdrops fungible tokens to multiple recipients. Automatically converts human-readable amounts to smallest units based on token decimals.';\n\n schema = z.object({\n tokenId: z\n .string()\n .describe('The ID of the fungible token to airdrop (e.g., \"0.0.yyyy\").'),\n recipients: z\n .array(\n z.object({\n accountId: z\n .string()\n .describe('Recipient account ID (e.g., \"0.0.xxxx\").'),\n amount: z\n .union([z.number(), z.string()])\n .describe(\n 'Amount in human-readable format (e.g., \"10\" for 10 tokens).'\n ),\n })\n )\n .min(1)\n .describe('Array of recipient objects, each with accountId and amount.'),\n memo: z.string().optional().describe('Optional. Memo for the transaction.'),\n });\n\n private originalTool: StructuredTool & ToolWithCall;\n private agentKit: HederaAgentKit & AgentKitWithMirrorNode;\n private logger: Logger;\n\n constructor(originalTool: StructuredTool, agentKit: unknown) {\n super();\n this.originalTool = originalTool as StructuredTool & ToolWithCall;\n this.agentKit = agentKit as HederaAgentKit & AgentKitWithMirrorNode;\n this.logger = new Logger({ module: 'AirdropToolWrapper' });\n }\n\n async _call(input: z.infer<typeof this.schema>): Promise<string> {\n try {\n this.logger.info(\n `Processing airdrop request for token ${input.tokenId} with ${input.recipients.length} recipients`\n );\n\n const tokenInfo = await this.getTokenInfo(input.tokenId);\n const decimals = tokenInfo.decimals || 0;\n\n this.logger.info(`Token ${input.tokenId} has ${decimals} decimal places`);\n\n const convertedRecipients = input.recipients.map((recipient) => {\n const humanAmount =\n typeof recipient.amount === 'string'\n ? parseFloat(recipient.amount)\n : recipient.amount;\n const smallestUnitAmount = this.convertToSmallestUnits(\n humanAmount,\n decimals\n );\n\n this.logger.info(\n `Converting amount for ${recipient.accountId}: ${humanAmount} tokens → ${smallestUnitAmount} smallest units`\n );\n\n return {\n ...recipient,\n amount: smallestUnitAmount.toString(),\n };\n });\n\n const convertedInput = {\n ...input,\n recipients: convertedRecipients,\n };\n\n this.logger.info(`Calling original airdrop tool with converted amounts`);\n return await this.originalTool._call(convertedInput);\n } catch (error) {\n this.logger.error('Error in airdrop tool wrapper:', error);\n throw error;\n }\n }\n\n private convertToSmallestUnits(amount: number, decimals: number): number {\n return Math.floor(amount * Math.pow(10, decimals));\n }\n\n private async getTokenInfo(tokenId: string): Promise<TokenInfo> {\n try {\n return await this.queryTokenInfo(tokenId);\n } catch (error) {\n throw error;\n }\n }\n\n private async queryTokenInfo(tokenId: string): Promise<TokenInfo> {\n try {\n this.logger.info('Querying token info using mirror node');\n const mirrorNode = this.agentKit.mirrorNode;\n if (!mirrorNode) {\n this.logger.info(\n 'MirrorNode not found in agentKit, attempting to access via fetch'\n );\n const network = this.agentKit.network || 'testnet';\n const mirrorNodeUrl =\n network === 'mainnet'\n ? 'https://mainnet.mirrornode.hedera.com'\n : 'https://testnet.mirrornode.hedera.com';\n\n const response = await fetch(\n `${mirrorNodeUrl}/api/v1/tokens/${tokenId}`\n );\n if (response.ok) {\n const tokenData = (await response.json()) as Record<string, unknown>;\n const decimals = parseInt(String(tokenData.decimals || '0'));\n this.logger.info(\n `Token ${tokenId} found with ${decimals} decimals via API`\n );\n return { ...tokenData, decimals };\n }\n } else {\n const tokenData = await mirrorNode.getTokenInfo(tokenId);\n\n if (tokenData && typeof tokenData.decimals !== 'undefined') {\n const decimals = parseInt(tokenData.decimals.toString()) || 0;\n this.logger.info(`Token ${tokenId} found with ${decimals} decimals`);\n return { ...tokenData, decimals };\n }\n }\n\n throw new Error(`Token data not found or missing decimals field`);\n } catch (error) {\n this.logger.warn(`Failed to query token info for ${tokenId}:`, error);\n\n this.logger.info(\n 'Falling back to assumed 0 decimal places (smallest units)'\n );\n return { decimals: 0 };\n }\n }\n}\n","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 return this.tools as unknown as HederaTool[];\n }\n\n async shutdown(): Promise<void> {\n this.tools = [];\n }\n}\n","export const NOT_FOUND_STATUS = 404;\r\nexport const BAD_REQUEST_STATUS = 400;\r\nexport const GATEWAY_STAMP_ERROR_MESSAGE =\r\n \"Endpoint not found. If using Swarm Gateway, postage stamp management endpoints are not available.\";\r\nexport const GATEWAY_TAG_ERROR_MESSAGE =\r\n \"If using Swarm Gateway, tag endpoints are not available.\";\r\nexport const POSTAGE_CREATE_TIMEOUT_MESSAGE =\r\n \"Purchase of postage batch is in progress, it may take a few minutes. Please list you batches after a few minutes to find it.\";\r\nexport const CALL_TIMEOUT = 30000;\r\nexport const DEFAULT_DEFERRED_UPLOAD_SIZE_THRESHOLD_MB = 5;\r\nexport const DEFAULT_GATEWAY_BATCH_ID =\r\n \"0000000000000000000000000000000000000000000000000000000000000000\";\r\n","import { Bee, PostageBatch } from \"@ethersphere/bee-js\";\r\nimport { PostageBatchCurated, PostageBatchSummary } from \"./model\";\r\nimport { SwarmConfig } from \"./config\";\r\nimport { DEFAULT_GATEWAY_BATCH_ID, NOT_FOUND_STATUS } from \"./constants\";\r\n\r\nexport interface ToolResponse {\r\n [x: string]: unknown;\r\n tools?: { [x: string]: unknown; name: string /* other properties */ };\r\n _meta?: { [x: string]: unknown };\r\n}\r\n\r\nexport function hexToBytes(hex: string): Uint8Array {\r\n const bytes = new Uint8Array(hex.length / 2);\r\n for (let i = 0; i < hex.length; i += 2) {\r\n bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);\r\n }\r\n return bytes;\r\n}\r\n\r\nexport const getBatchSummary = (\r\n batch: PostageBatch | PostageBatchCurated\r\n): PostageBatchSummary => ({\r\n stampID:\r\n typeof batch.batchID === \"string\" ? batch.batchID : batch.batchID.toHex(),\r\n usage: batch.usageText,\r\n capacity: `${batch.remainingSize.toFormattedString()} remaining out of ${batch.size.toFormattedString()}`,\r\n immutable: batch.immutableFlag,\r\n ttl: `${batch.duration.represent()} (${batch.duration\r\n .toEndDate()\r\n .toDateString()})`,\r\n});\r\n\r\nexport const getResponseWithStructuredContent = <T>(data: T): ToolResponse => ({\r\n content: [\r\n {\r\n type: \"text\",\r\n text: JSON.stringify(data, null, 2),\r\n },\r\n ],\r\n structuredContent: data,\r\n});\r\n\r\nexport const errorHasStatus = (error: unknown, status: number) => {\r\n if (typeof error === \"object\" && error !== null && \"status\" in error) {\r\n return error.status === status;\r\n }\r\n\r\n return false;\r\n};\r\n\r\nexport const getErrorMessage = (error: unknown) => {\r\n if (\r\n typeof error === \"object\" &&\r\n error !== null &&\r\n \"responseBody\" in error &&\r\n typeof error.responseBody === \"object\" &&\r\n error.responseBody !== null &&\r\n \"message\" in error.responseBody\r\n ) {\r\n return error.responseBody.message as string;\r\n }\r\n\r\n return \"\";\r\n};\r\n\r\nexport const runWithTimeout = async <T>(\r\n asyncAction: Promise<T>,\r\n timeout: number\r\n): Promise<[unknown, boolean]> => {\r\n let hasTimedOut = false;\r\n\r\n const timeoutPromise = new Promise((resolve) =>\r\n setTimeout(() => {\r\n hasTimedOut = true;\r\n resolve(true);\r\n }, timeout)\r\n );\r\n\r\n const response = await Promise.race([asyncAction, timeoutPromise]);\r\n\r\n return [response, hasTimedOut];\r\n};\r\n\r\nexport const getUploadPostageBatchId = async (\r\n argsPostageBatchId: string | undefined,\r\n bee: Bee,\r\n config: SwarmConfig,\r\n): Promise<string> => {\r\n let postageBatchId = argsPostageBatchId;\r\n const autoAssignStamp = config.autoAssignStamp ?? true;\r\n let maxRemainingSize = 0;\r\n\r\n if (!postageBatchId && !autoAssignStamp) {\r\n throw new Error('No postageBatchId was provided. Please repeat the prompt and also specify the usable postage batch id.');\r\n } else if (!postageBatchId) {\r\n try {\r\n const rawPostageBatches = await bee.getPostageBatches();\r\n\r\n rawPostageBatches.forEach((batch) => {\r\n if (!batch.usable) {\r\n return;\r\n }\r\n\r\n const remainingSize = batch.remainingSize.toBytes();\r\n\r\n if (remainingSize > maxRemainingSize) {\r\n maxRemainingSize = remainingSize;\r\n postageBatchId = batch.batchID.toHex();\r\n }\r\n });\r\n } catch (error) {\r\n if (errorHasStatus(error, NOT_FOUND_STATUS)) {\r\n postageBatchId = DEFAULT_GATEWAY_BATCH_ID;\r\n } else {\r\n throw new Error('Retrieval of postage batches failed.');\r\n }\r\n }\r\n }\r\n\r\n if (!postageBatchId) {\r\n throw new Error('There is no usable postage batch with capacity.');\r\n }\r\n\r\n return postageBatchId!;\r\n};\r\n\r\nconst dateUnits: Record<string, number | undefined> = {\r\n ms: 1,\r\n milli: 1,\r\n millis: 1,\r\n millisecond: 1,\r\n milliseconds: 1,\r\n s: 1000,\r\n sec: 1000,\r\n second: 1000,\r\n seconds: 1000,\r\n m: 60_000,\r\n min: 60_000,\r\n minute: 60_000,\r\n minutes: 60_000,\r\n h: 3_600_000,\r\n hour: 3_600_000,\r\n hours: 3_600_000,\r\n d: 86_400_000,\r\n day: 86_400_000,\r\n days: 86_400_000,\r\n w: 604_800_000,\r\n week: 604_800_000,\r\n weeks: 604_800_000,\r\n month: 2_592_000_000,\r\n months: 2_592_000_000,\r\n y: 31_536_000_000,\r\n year: 31_536_000_000,\r\n years: 31_536_000_000,\r\n};\r\n\r\n// From bee.js\r\nexport function makeDate(numberWithUnit: string): number {\r\n const number = parseFloat(numberWithUnit);\r\n if (isNaN(number)) {\r\n throw Error(\"makeDate got NaN for input\");\r\n }\r\n const unit = numberWithUnit\r\n .replace(/^-?[0-9.]+/, \"\")\r\n .trim()\r\n .toLowerCase();\r\n const multiplier = dateUnits[unit];\r\n if (!multiplier) {\r\n throw Error(`Unknown unit: \"${unit}\"`);\r\n }\r\n return number * multiplier;\r\n}\r\n","import {\r\n type GenericPluginContext,\r\n BaseHederaQueryTool,\r\n type HederaAgentKit,\r\n} from \"hedera-agent-kit\";\r\nimport { Bee } from \"@ethersphere/bee-js\";\r\nimport { z } from \"zod\";\r\nimport {\r\n PostageBatchCurated,\r\n PostageBatchSummary,\r\n ResponseContent,\r\n} from \"../model\";\r\nimport {\r\n errorHasStatus,\r\n getBatchSummary,\r\n getResponseWithStructuredContent,\r\n ToolResponse,\r\n} from \"../utils\";\r\nimport { GATEWAY_STAMP_ERROR_MESSAGE, NOT_FOUND_STATUS } from \"../constants\";\r\nimport { SwarmConfig } from \"../config\";\r\n\r\nconst ListPostageStampsSchema = z.object({\r\n leastUsed: z.boolean().optional(),\r\n limit: z.number().optional(),\r\n minUsage: z.number().optional(),\r\n maxUsage: z.number().optional(),\r\n});\r\n\r\nexport class ListPostageStampsTool extends BaseHederaQueryTool<typeof ListPostageStampsSchema> {\r\n name = \"swarm-list-postage-stamps\";\r\n description =`\r\n List the available postage stamps.\r\n leastUsed: A boolean value that tells if stamps are sorted so least used comes first.\r\n limit: Limit is the maximum number of returned stamps.\r\n minUsage: Only list stamps with at least this usage percentage.\r\n maxUsage: Only list stamps with at most this usage percentage. \r\n `;\r\n namespace = \"swarm\";\r\n specificInputSchema = ListPostageStampsSchema;\r\n bee: Bee;\r\n config: SwarmConfig;\r\n \r\n constructor(params: {\r\n hederaKit: HederaAgentKit;\r\n config: SwarmConfig;\r\n logger?: GenericPluginContext['logger'];\r\n bee: Bee;\r\n }) {\r\n const { bee, config, ...rest } = params;\r\n super(rest);\r\n this.bee = bee;\r\n this.config = config;\r\n }\r\n\r\n protected async executeQuery(\r\n input: z.infer<typeof ListPostageStampsSchema>\r\n ): Promise<ToolResponse | string> {\r\n const { leastUsed, limit, minUsage, maxUsage } = input;\r\n\r\n let rawPostageBatches;\r\n\r\n try {\r\n rawPostageBatches = await this.bee.getPostageBatches();\r\n } catch (error) {\r\n let errorMessage = 'Retrieval of postage batches failed.';\r\n\r\n if (errorHasStatus(error, NOT_FOUND_STATUS)) {\r\n errorMessage = GATEWAY_STAMP_ERROR_MESSAGE;\r\n }\r\n \r\n this.logger.error(\r\n errorMessage,\r\n error\r\n );\r\n \r\n throw new Error(errorMessage);\r\n }\r\n\r\n const batches: PostageBatchCurated[] = rawPostageBatches.map((batch) => ({\r\n ...batch,\r\n batchID: batch.batchID.toHex(),\r\n }));\r\n let filteredPostageBatches = batches.filter((batch) => {\r\n if (!batch.usable) {\r\n return false;\r\n }\r\n\r\n const usagePercentage = batch.usage * 100;\r\n\r\n if (minUsage !== undefined && usagePercentage < minUsage) {\r\n return false;\r\n }\r\n\r\n if (maxUsage !== undefined && usagePercentage > maxUsage) {\r\n return false;\r\n }\r\n\r\n return true;\r\n });\r\n\r\n if (Boolean(leastUsed) && filteredPostageBatches.length) {\r\n filteredPostageBatches = filteredPostageBatches.sort(\r\n (batch1, batch2) => batch1.usage - batch2.usage\r\n );\r\n }\r\n\r\n if (limit !== undefined && limit < filteredPostageBatches.length) {\r\n filteredPostageBatches = filteredPostageBatches.slice(0, limit);\r\n }\r\n\r\n const computedPostageBatches: PostageBatchSummary[] =\r\n filteredPostageBatches.map((batch) => getBatchSummary(batch));\r\n\r\n const content: ResponseContent<\r\n PostageBatchCurated[],\r\n PostageBatchSummary[]\r\n > = {\r\n raw: filteredPostageBatches,\r\n summary: computedPostageBatches,\r\n };\r\n\r\n return getResponseWithStructuredContent(content);\r\n }\r\n}\r\n","import {\r\n BaseHederaQueryTool,\r\n HederaAgentKit,\r\n type GenericPluginContext,\r\n} from \"hedera-agent-kit\";\r\nimport { Bee } from \"@ethersphere/bee-js\";\r\nimport { z } from \"zod\";\r\nimport {\r\n errorHasStatus,\r\n getErrorMessage,\r\n getResponseWithStructuredContent,\r\n getUploadPostageBatchId,\r\n ToolResponse,\r\n} from \"../utils\";\r\nimport { BAD_REQUEST_STATUS } from \"../constants\";\r\nimport { SwarmConfig } from \"../config\";\r\n\r\nconst UploadDataSchema = z.object({\r\n data: z.string(),\r\n redundancyLevel: z.number().optional(),\r\n postageBatchId: z.string().optional(),\r\n});\r\n\r\nexport class UploadDataTool extends BaseHederaQueryTool<typeof UploadDataSchema> {\r\n name = \"swarm-upload-data\";\r\n description = `\r\n Upload text data to Swarm.\r\n data: Arbitrary string to upload.\r\n redundancyLevel: Redundancy level for fault tolerance: 0 - none, 1 - medium, 2 - strong, 3 - insane, 4 - paranoid (higher values provide better fault tolerance but increase storage overhead). Optional, value is 0 if not requested.\r\n postageBatchId: The postage stamp batch ID which will be used to perform the upload, if it is provided.\r\n `;\r\n namespace = \"swarm\";\r\n specificInputSchema = UploadDataSchema;\r\n bee: Bee;\r\n config: SwarmConfig;\r\n \r\n constructor(params: {\r\n hederaKit: HederaAgentKit;\r\n config: SwarmConfig;\r\n logger?: GenericPluginContext['logger'];\r\n bee: Bee;\r\n }) {\r\n const { bee, config, ...rest } = params;\r\n super(rest);\r\n this.bee = bee;\r\n this.config = config;\r\n }\r\n \r\n protected async executeQuery(\r\n input: z.infer<typeof UploadDataSchema>\r\n ): Promise<ToolResponse | string> {\r\n const { data, redundancyLevel, postageBatchId: inputPostageBatchId } = input;\r\n\r\n if (!data) {\r\n this.logger.error(\r\n 'Missing required parameter: data.'\r\n );\r\n\r\n throw new Error('Missing required parameter: data.');\r\n }\r\n\r\n let postageBatchId = \"\";\r\n\r\n try {\r\n postageBatchId = await getUploadPostageBatchId(\r\n inputPostageBatchId,\r\n this.bee,\r\n this.config,\r\n );\r\n } catch (error) {\r\n let errorMessage = 'Upload data failed.';\r\n if (error instanceof Error) {\r\n errorMessage = error.message;\r\n }\r\n this.logger.error(errorMessage);\r\n\r\n throw new Error(errorMessage);\r\n }\r\n\r\n const binaryData = Buffer.from(data);\r\n\r\n const options = redundancyLevel ? { redundancyLevel } : undefined;\r\n\r\n let result;\r\n\r\n try {\r\n result = await this.bee.uploadData(postageBatchId, binaryData, options);\r\n } catch (error) {\r\n let errorMessage = 'Unable to upload data.';\r\n\r\n if (errorHasStatus(error, BAD_REQUEST_STATUS)) {\r\n errorMessage = getErrorMessage(error);\r\n }\r\n\r\n this.logger.error(\r\n errorMessage,\r\n error\r\n );\r\n \r\n throw new Error(errorMessage);\r\n }\r\n\r\n return getResponseWithStructuredContent({\r\n reference: result.reference.toString(),\r\n url: this.bee.url + \"/bytes/\" + result.reference.toString(),\r\n message: 'Data successfully uploaded to Swarm',\r\n });\r\n }\r\n}\r\n","import { Bee } from \"@ethersphere/bee-js\";\r\nimport { z } from \"zod\";\r\nimport { errorHasStatus, getErrorMessage, getResponseWithStructuredContent, ToolResponse } from \"../utils\";\r\nimport { BaseHederaQueryTool, GenericPluginContext, HederaAgentKit } from \"hedera-agent-kit\";\r\nimport { SwarmConfig } from \"../config\";\r\nimport { BAD_REQUEST_STATUS } from \"../constants\";\r\n\r\nconst DownloadDataSchema = z.object({\r\n reference: z.string(),\r\n});\r\n\r\nexport class DownloadDataTool extends BaseHederaQueryTool<typeof DownloadDataSchema> {\r\n name = \"swarm-download-data\";\r\n description = `\r\n Downloads immutable data from a Swarm content address hash.\r\n reference: Swarm reference hash.\r\n `;\r\n namespace = \"swarm\";\r\n specificInputSchema = DownloadDataSchema;\r\n bee: Bee;\r\n config: SwarmConfig;\r\n \r\n constructor(params: {\r\n hederaKit: HederaAgentKit;\r\n config: SwarmConfig;\r\n logger?: GenericPluginContext['logger'];\r\n bee: Bee;\r\n }) {\r\n const { bee, config, ...rest } = params;\r\n super(rest);\r\n this.bee = bee;\r\n this.config = config;\r\n }\r\n\r\n protected async executeQuery(\r\n input: z.infer<typeof DownloadDataSchema>\r\n ): Promise<ToolResponse | string> {\r\n const { reference } = input;\r\n\r\n if (!reference) {\r\n this.logger.error(\r\n 'Missing required parameter: reference.'\r\n );\r\n\r\n throw new Error(\"Missing required parameter: reference.\");\r\n }\r\n\r\n const isRefNotSwarmHash =\r\n reference.length !== 64 && reference.length !== 66;\r\n\r\n if (isRefNotSwarmHash) {\r\n this.logger.error(\r\n 'Invalid Swarm content address hash value for reference.'\r\n );\r\n\r\n throw new Error(\"Invalid Swarm content address hash value for reference.\");\r\n }\r\n\r\n let data;\r\n try {\r\n data = await this.bee.downloadData(reference);\r\n } catch (error) {\r\n let errorMessage = 'Downloading data failed.';\r\n\r\n if (errorHasStatus(error, BAD_REQUEST_STATUS)) {\r\n errorMessage = getErrorMessage(error);\r\n }\r\n\r\n this.logger.error(errorMessage, error);\r\n throw new Error(errorMessage);\r\n }\r\n\r\n const textData = data.toUtf8();\r\n\r\n return getResponseWithStructuredContent({\r\n textData,\r\n });\r\n }\r\n}\r\n","import {\r\n BaseHederaQueryTool,\r\n HederaAgentKit,\r\n type GenericPluginContext,\r\n} from \"hedera-agent-kit\";\r\nimport { BatchId, Bee, Duration, Size } from \"@ethersphere/bee-js\";\r\nimport { z } from \"zod\";\r\nimport {\r\n errorHasStatus,\r\n getErrorMessage,\r\n makeDate,\r\n runWithTimeout,\r\n ToolResponse,\r\n} from \"../utils\";\r\nimport { BAD_REQUEST_STATUS, CALL_TIMEOUT, GATEWAY_STAMP_ERROR_MESSAGE, NOT_FOUND_STATUS, POSTAGE_CREATE_TIMEOUT_MESSAGE } from \"../constants\";\r\nimport { SwarmConfig } from \"../config\";\r\n\r\nconst CreatePostageStampSchema = z.object({\r\n size: z.number(),\r\n duration: z.string(),\r\n label: z.string().optional(),\r\n});\r\n\r\nexport class CreatePostageStampTool extends BaseHederaQueryTool<typeof CreatePostageStampSchema> {\r\n name = \"swarm-create-postage-stamp\";\r\n description = `\r\n Buy postage stamp based on size in megabytes and duration.\r\n size: The storage size in MB (Megabytes). These other size units convert like this to MB: 1 byte = 0.000001 MB, 1 KB = 0.001 MB, 1GB= 1000MB.\r\n duration: Duration for which the data should be stored. Time to live of the postage stamp, e.g. 1d - 1 day, 1w - 1 week, 1month - 1 month.\r\n label: Sets label for the postage batch (omit if the user didn't ask for one). Do not set a label with with specific capacity values because they can get misleading.\r\n `;\r\n namespace = \"swarm\";\r\n specificInputSchema = CreatePostageStampSchema;\r\n bee: Bee;\r\n config: SwarmConfig;\r\n \r\n constructor(params: {\r\n hederaKit: HederaAgentKit;\r\n config: SwarmConfig;\r\n logger?: GenericPluginContext['logger'];\r\n bee: Bee;\r\n }) {\r\n const { bee, config, ...rest } = params;\r\n super(rest);\r\n this.bee = bee;\r\n this.config = config;\r\n }\r\n \r\n protected async executeQuery(\r\n input: z.infer<typeof CreatePostageStampSchema>\r\n ): Promise<ToolResponse | string> {\r\n const { size, duration, label } = input;\r\n\r\n if (!size) {\r\n this.logger.error(\r\n 'Missing required parameter: size.'\r\n );\r\n \r\n throw new Error('Missing required parameter: size.');\r\n } else if (!duration) {\r\n this.logger.error(\r\n 'Missing required parameter: duration.'\r\n );\r\n \r\n throw new Error('Missing required parameter: duration.');\r\n }\r\n\r\n let durationMs;\r\n\r\n try {\r\n durationMs = makeDate(duration);\r\n } catch (makeDateError) {\r\n this.logger.error(\r\n 'Invalid parameter: duration.'\r\n );\r\n\r\n throw new Error('Invalid parameter: duration.');\r\n }\r\n\r\n let buyStorageResponse: BatchId;\r\n\r\n try {\r\n let options = {};\r\n if (label !== undefined) {\r\n options = {\r\n label\r\n };\r\n }\r\n const buyStoragePromise = this.bee.buyStorage(\r\n Size.fromMegabytes(size),\r\n Duration.fromMilliseconds(durationMs),\r\n options\r\n );\r\n const [response, hasTimedOut] = await runWithTimeout(\r\n buyStoragePromise,\r\n CALL_TIMEOUT\r\n );\r\n\r\n if (hasTimedOut) {\r\n return JSON.stringify({\r\n content: [\r\n {\r\n type: 'text',\r\n text: POSTAGE_CREATE_TIMEOUT_MESSAGE,\r\n },\r\n ],\r\n });\r\n }\r\n\r\n buyStorageResponse = response as BatchId;\r\n } catch (error) {\r\n let errorMessage = 'Unable to buy storage.';\r\n\r\n if (errorHasStatus(error, NOT_FOUND_STATUS)) {\r\n errorMessage = GATEWAY_STAMP_ERROR_MESSAGE;\r\n } else if (errorHasStatus(error, BAD_REQUEST_STATUS)) {\r\n errorMessage = getErrorMessage(error);\r\n }\r\n\r\n this.logger.error(\r\n errorMessage,\r\n error\r\n );\r\n\r\n throw new Error(errorMessage);\r\n }\r\n\r\n return {\r\n content: [\r\n {\r\n type: 'text',\r\n text: `Postage batch ID: ${buyStorageResponse.toHex()}`,\r\n },\r\n ],\r\n };\r\n }\r\n}\r\n","import {\r\n BaseHederaQueryTool,\r\n HederaAgentKit,\r\n type GenericPluginContext,\r\n} from \"hedera-agent-kit\";\r\nimport { BatchId, Bee, Duration, Size } from \"@ethersphere/bee-js\";\r\nimport { z } from \"zod\";\r\nimport {\r\n errorHasStatus,\r\n getErrorMessage,\r\n getResponseWithStructuredContent,\r\n makeDate,\r\n ToolResponse,\r\n} from \"../utils\";\r\nimport { BAD_REQUEST_STATUS, GATEWAY_STAMP_ERROR_MESSAGE, NOT_FOUND_STATUS } from \"../constants\";\r\nimport { SwarmConfig } from \"../config\";\r\n\r\nconst ExtendPostageStampSchema = z.object({\r\n postageBatchId: z.string(),\r\n duration: z.string().optional(),\r\n size: z.number().optional(),\r\n});\r\n\r\nexport class ExtendPostageStampTool extends BaseHederaQueryTool<typeof ExtendPostageStampSchema> {\r\n name = \"swarm-extend-postage-stamp\";\r\n description = `Increase the duration (relative to current duration) or size (in megabytes) of a postage stamp.\r\n postageBatchId: The id of the batch for which extend is performed.\r\n size: The storage size in MB (Megabytes). These other size units convert like this to MB: 1 byte = 0.000001 MB, 1 KB = 0.001 MB, 1GB= 1000MB.\r\n duration: Duration for which the data should be stored. Time to live of the postage stamp, e.g. 1d - 1 day, 1w - 1 week, 1month - 1 month.\r\n `;\r\n namespace = \"swarm\";\r\n specificInputSchema = ExtendPostageStampSchema;\r\n bee: Bee;\r\n config: SwarmConfig;\r\n \r\n constructor(params: {\r\n hederaKit: HederaAgentKit;\r\n config: SwarmConfig;\r\n logger?: GenericPluginContext['logger'];\r\n bee: Bee;\r\n }) {\r\n const { bee, config, ...rest } = params;\r\n super(rest);\r\n this.bee = bee;\r\n this.config = config;\r\n }\r\n \r\n protected async executeQuery(\r\n input: z.infer<typeof ExtendPostageStampSchema>\r\n ): Promise<ToolResponse | string> {\r\n const { postageBatchId, duration, size } = input;\r\n\r\n if (!postageBatchId) {\r\n this.logger.error(\r\n 'Missing required parameter: postageBatchId.'\r\n );\r\n\r\n throw new Error('Missing required parameter: postageBatchId.');\r\n } else if (!duration && !size) {\r\n this.logger.error(\r\n 'You need at least one parameter from duration and size.'\r\n );\r\n\r\n throw new Error('You need at least one parameter from duration and size.');\r\n }\r\n\r\n // If size is missing, Size.fromBytes(1) will get smallest depth and not increase size.\r\n const extendSize = !!size ? Size.fromMegabytes(size) : Size.fromBytes(1); \r\n let extendDuration = Duration.ZERO;\r\n\r\n try {\r\n if (duration) {\r\n extendDuration = Duration.fromMilliseconds(makeDate(duration));\r\n }\r\n } catch (makeDateError) {\r\n this.logger.error(\r\n 'Invalid parameter: duration.'\r\n );\r\n\r\n throw new Error('Invalid parameter: duration.');\r\n }\r\n\r\n let extendStorageResponse;\r\n\r\n try {\r\n extendStorageResponse = await this.bee.extendStorage(\r\n postageBatchId,\r\n extendSize,\r\n extendDuration\r\n );\r\n } catch (error) {\r\n let errorMessage = 'Extend failed.';\r\n\r\n if (errorHasStatus(error, NOT_FOUND_STATUS)) {\r\n errorMessage = GATEWAY_STAMP_ERROR_MESSAGE;\r\n } else if (errorHasStatus(error, BAD_REQUEST_STATUS)) {\r\n errorMessage = getErrorMessage(error);\r\n }\r\n\r\n this.logger.error(\r\n errorMessage,\r\n error\r\n );\r\n\r\n throw new Error(errorMessage);\r\n }\r\n\r\n return getResponseWithStructuredContent({\r\n postageBatchId: extendStorageResponse.toHex(),\r\n });\r\n }\r\n}\r\n","import {\r\n type GenericPluginContext,\r\n BaseHederaQueryTool,\r\n type HederaAgentKit,\r\n} from \"hedera-agent-kit\";\r\nimport { Bee } from \"@ethersphere/bee-js\";\r\nimport { z } from \"zod\";\r\nimport {\r\n errorHasStatus,\r\n getResponseWithStructuredContent,\r\n ToolResponse,\r\n} from \"../utils\";\r\nimport { GATEWAY_TAG_ERROR_MESSAGE } from \"../constants\";\r\nimport { SwarmConfig } from \"../config\";\r\n\r\nconst QueryUploadProgressSchema = z.object({\r\n tagId: z.string(),\r\n});\r\n\r\nexport class QueryUploadProgressTool extends BaseHederaQueryTool<typeof QueryUploadProgressSchema> {\r\n name = \"swarm-query-upload-progress\";\r\n description = `Query upload progress for a specific upload session identified with the returned Tag ID.\r\n tagId: Tag ID returned by swarm-upload-file and swarm-upload-folder tools to track upload progress.\r\n `;\r\n namespace = \"swarm\";\r\n specificInputSchema = QueryUploadProgressSchema;\r\n bee: Bee;\r\n config: SwarmConfig;\r\n \r\n constructor(params: {\r\n hederaKit: HederaAgentKit;\r\n config: SwarmConfig;\r\n logger?: GenericPluginContext['logger'];\r\n bee: Bee;\r\n }) {\r\n const { bee, config, ...rest } = params;\r\n super(rest);\r\n this.bee = bee;\r\n this.config = config;\r\n }\r\n\r\n protected async executeQuery(\r\n input: z.infer<typeof QueryUploadProgressSchema>\r\n ): Promise<ToolResponse | string> {\r\n if (!input?.tagId) {\r\n this.logger.error(\r\n 'Missing required parameter: tagId.'\r\n );\r\n\r\n throw new Error('Missing required parameter: tagId.');\r\n }\r\n\r\n const tagUid = Number.parseInt(input.tagId, 10);\r\n if (Number.isNaN(tagUid)) {\r\n this.logger.error(\r\n 'Invalid tagId format. Expected a numeric string.'\r\n );\r\n\r\n throw new Error('Invalid tagId format. Expected a numeric string.');\r\n }\r\n\r\n try {\r\n const tag = await this.bee.retrieveTag(tagUid);\r\n\r\n const synced = tag.synced ?? 0;\r\n const seen = tag.seen ?? 0;\r\n const processed = synced + seen;\r\n const total = tag.split ?? 0;\r\n const startedAt = tag.startedAt;\r\n\r\n const processedPercentage =\r\n total > 0 ? Math.round((processed / total) * 100) : 0;\r\n const isComplete = processedPercentage === 100;\r\n\r\n let tagDeleted = false;\r\n if (isComplete) {\r\n try {\r\n await this.bee.deleteTag(tagUid);\r\n tagDeleted = true;\r\n } catch {\r\n // Non-fatal: if deletion fails we still return progress\r\n }\r\n }\r\n\r\n return getResponseWithStructuredContent({\r\n processedPercentage,\r\n message: isComplete\r\n ? \"Upload completed successfully.\"\r\n : `Upload progress: ${processedPercentage}% processed`,\r\n startedAt,\r\n tagAddress: tag.address,\r\n });\r\n } catch (error: any) {\r\n let errorMessage = `Failed to retrieve upload progress: ${error?.message ?? \"Unknown error\"}`;\r\n \r\n const status = error?.status ?? error?.response?.status;\r\n if (status === 404) {\r\n errorMessage = `Tag with ID ${input.tagId} does not exist or has been deleted. ` + GATEWAY_TAG_ERROR_MESSAGE;\r\n }\r\n \r\n this.logger.error(\r\n errorMessage,\r\n error\r\n );\r\n \r\n throw new Error(errorMessage);\r\n }\r\n }\r\n}\r\n","import { Bee, MantarayNode } from \"@ethersphere/bee-js\";\r\nimport { z } from \"zod\";\r\nimport fs from \"fs\";\r\nimport path from \"path\";\r\nimport { BaseHederaQueryTool, GenericPluginContext, HederaAgentKit } from \"hedera-agent-kit\";\r\nimport { promisify } from \"util\";\r\nimport { ToolResponse } from \"../utils\";\r\nimport { SwarmConfig } from \"../config\";\r\n\r\nconst DownloadFilesSchema = z.object({\r\n reference: z.string(),\r\n filePath: z.string().optional()\r\n});\r\n\r\nexport class DownloadFilesTool extends BaseHederaQueryTool<typeof DownloadFilesSchema> {\r\n name = \"swarm-download-files\";\r\n description = `Download folder, files from a Swarm reference and save to file path or return file list of the reference.\r\n Prioritizes this tool over swarm-download-data if there is no assumption about the data type.\r\n reference: Swarm reference hash.\r\n filePath: Optional file path to save the downloaded content (only available in stdio mode). If not provided list of files in the manifest will be returned.\r\n `;\r\n namespace = \"swarm\";\r\n specificInputSchema = DownloadFilesSchema;\r\n bee: Bee; \r\n config: SwarmConfig;\r\n\r\n constructor(params: {\r\n hederaKit: HederaAgentKit;\r\n config: SwarmConfig;\r\n logger?: GenericPluginContext['logger'];\r\n bee: Bee;\r\n }) {\r\n const { bee, config, ...rest } = params;\r\n super(rest);\r\n this.bee = bee;\r\n this.config = config;\r\n }\r\n\r\n protected async executeQuery(\r\n input: z.infer<typeof DownloadFilesSchema>\r\n ): Promise<ToolResponse | string> {\r\n const { reference, filePath } = input;\r\n \r\n if (!reference) {\r\n this.logger.error(\r\n 'Missing required parameter: reference.'\r\n );\r\n \r\n throw new Error(\"Missing required parameter: reference.\");\r\n }\r\n\r\n this.logger.info(`[API] Downloading folder from Swarm with reference: ${reference}.`);\r\n\r\n // Check if the reference is a manifest\r\n let isManifest = false;\r\n let node: MantarayNode;\r\n\r\n try {\r\n node = await MantarayNode.unmarshal(this.bee, reference);\r\n await node.loadRecursively(this.bee);\r\n isManifest = true;\r\n } catch (error) {\r\n // ignore\r\n }\r\n\r\n if (isManifest) {\r\n if (filePath) {\r\n const destinationFolder = filePath;\r\n\r\n if (!fs.existsSync(destinationFolder)) {\r\n await promisify(fs.mkdir)(destinationFolder, { recursive: true });\r\n }\r\n\r\n const nodes = node!.collect();\r\n\r\n if (nodes.length === 1) {\r\n const node = nodes[0];\r\n const data = await this.bee.downloadData(node.targetAddress);\r\n await promisify(fs.writeFile)(\r\n path.join(\r\n destinationFolder,\r\n node.fullPathString.split(\"\\\\\").slice(-1)[0]\r\n ),\r\n data.toUint8Array()\r\n );\r\n } else {\r\n // Download each node\r\n for (const node of nodes) {\r\n const parsedPath = path.parse(node.fullPathString);\r\n const nodeDestFolder = path.join(destinationFolder, parsedPath.dir);\r\n // Create subdirectories if necessary\r\n if (!fs.existsSync(nodeDestFolder)) {\r\n await promisify(fs.mkdir)(nodeDestFolder, { recursive: true });\r\n }\r\n\r\n const data = await this.bee.downloadData(node.targetAddress);\r\n await promisify(fs.writeFile)(\r\n path.join(destinationFolder, node.fullPathString),\r\n data.toUint8Array()\r\n );\r\n }\r\n }\r\n\r\n return {\r\n content: [\r\n {\r\n type: \"text\",\r\n text: JSON.stringify(\r\n {\r\n reference: reference,\r\n manifestNodeCount: nodes.length,\r\n savedTo: destinationFolder,\r\n message: `Manifest content (${nodes.length} files) successfully downloaded to ${destinationFolder}`,\r\n },\r\n null,\r\n 2\r\n ),\r\n },\r\n ],\r\n };\r\n } else {\r\n // regular file\r\n const nodes = node!.collect();\r\n const filesList = nodes.map((node) => ({\r\n path: node.fullPathString || \"/\",\r\n targetAddress: Array.from(node.targetAddress)\r\n .map((e) => e.toString(16).padStart(2, \"0\"))\r\n .join(\"\"),\r\n metadata: node.metadata,\r\n }));\r\n\r\n return {\r\n content: [\r\n {\r\n type: \"text\",\r\n text: JSON.stringify(\r\n {\r\n reference: reference,\r\n type: \"manifest\",\r\n files: filesList,\r\n message:\r\n \"This is a manifest with multiple files. Provide a filePath to download all files or download individual files using their specific references.\",\r\n },\r\n null,\r\n 2\r\n ),\r\n },\r\n ],\r\n };\r\n }\r\n } else {\r\n return \"Try swarm-download-data tool instead since the given reference is not a manifest.\";\r\n }\r\n }\r\n}\r\n","import {\r\n type GenericPluginContext,\r\n BaseHederaQueryTool,\r\n type HederaAgentKit,\r\n} from \"hedera-agent-kit\";\r\nimport { Bee } from \"@ethersphere/bee-js\";\r\nimport { z } from \"zod\";\r\nimport {\r\n PostageBatchCurated,\r\n PostageBatchSummary,\r\n ResponseContent,\r\n} from \"../model\";\r\nimport {\r\n errorHasStatus,\r\n getBatchSummary,\r\n getResponseWithStructuredContent,\r\n ToolResponse,\r\n} from \"../utils\";\r\nimport { GATEWAY_STAMP_ERROR_MESSAGE, NOT_FOUND_STATUS } from \"../constants\";\r\nimport { SwarmConfig } from \"../config\";\r\n\r\nconst GetPostageStampSchema = z.object({\r\n postageBatchId: z.string(),\r\n});\r\n\r\nexport class GetPostageStampTool extends BaseHederaQueryTool<typeof GetPostageStampSchema> {\r\n name = \"swarm-get-postage-stamp\";\r\n description = `Get a specific postage stamp based on postageBatchId.\r\n postageBatchId: The id of the stamp which is requested.\r\n `;\r\n namespace = \"swarm\";\r\n specificInputSchema = GetPostageStampSchema;\r\n bee: Bee;\r\n config: SwarmConfig;\r\n \r\n constructor(params: {\r\n hederaKit: HederaAgentKit;\r\n config: SwarmConfig;\r\n logger?: GenericPluginContext['logger'];\r\n bee: Bee;\r\n }) {\r\n const { bee, config, ...rest } = params;\r\n super(rest);\r\n this.bee = bee;\r\n this.config = config;\r\n }\r\n\r\n protected async executeQuery(\r\n input: z.infer<typeof GetPostageStampSchema>\r\n ): Promise<ToolResponse | string> {\r\n const { postageBatchId } = input;\r\n if (!postageBatchId) {\r\n this.logger.error(\r\n 'Missing required parameter: postageBatchId.'\r\n );\r\n\r\n throw new Error(\"Missing required parameter: postageBatchId.\");\r\n }\r\n\r\n let rawPostageBatch;\r\n\r\n try {\r\n rawPostageBatch = await this.bee.getPostageBatch(postageBatchId);\r\n } catch (error) {\r\n let errorMessage = 'Retrieval of postage batch failed.';\r\n \r\n if (errorHasStatus(error, NOT_FOUND_STATUS)) {\r\n errorMessage = GATEWAY_STAMP_ERROR_MESSAGE;\r\n }\r\n\r\n this.logger.error(\r\n errorMessage,\r\n error\r\n );\r\n\r\n throw new Error(errorMessage);\r\n }\r\n\r\n const batch: PostageBatchCurated = {\r\n ...rawPostageBatch,\r\n batchID: rawPostageBatch.batchID.toHex(),\r\n };\r\n const batchSummary: PostageBatchSummary = getBatchSummary(rawPostageBatch);\r\n\r\n const content: ResponseContent<PostageBatchCurated, PostageBatchSummary> = {\r\n raw: batch,\r\n summary: batchSummary,\r\n };\r\n\r\n return getResponseWithStructuredContent(content);\r\n }\r\n}\r\n","import { Bee } from \"@ethersphere/bee-js\";\r\nimport { Wallet } from \"@ethereumjs/wallet\";\r\nimport { z } from \"zod\";\r\nimport crypto from \"crypto\";\r\nimport { errorHasStatus, getErrorMessage, getResponseWithStructuredContent, hexToBytes, ToolResponse } from \"../utils\";\r\nimport { BaseHederaQueryTool, GenericPluginContext, HederaAgentKit } from \"hedera-agent-kit\";\r\nimport { SwarmConfig } from \"../config\";\r\nimport { BAD_REQUEST_STATUS } from \"../constants\";\r\n\r\nconst ReadFeedSchema = z.object({\r\n memoryTopic: z.string(),\r\n owner: z.string().optional()\r\n});\r\n\r\nexport class ReadFeedTool extends BaseHederaQueryTool<typeof ReadFeedSchema> {\r\n name = \"swarm-read-feed\";\r\n description = `Retrieve the latest data from the feed of a given topic.\r\n memoryTopic: Feed topic.\r\n owner: When accessing external memory or feed, ethereum address of the owner must be set.\r\n `;\r\n namespace = \"swarm\";\r\n specificInputSchema = ReadFeedSchema;\r\n bee: Bee;\r\n config: SwarmConfig;\r\n \r\n constructor(params: {\r\n hederaKit: HederaAgentKit;\r\n config: SwarmConfig;\r\n logger?: GenericPluginContext['logger'];\r\n bee: Bee;\r\n }) {\r\n const { bee, config, ...rest } = params;\r\n super(rest);\r\n this.bee = bee;\r\n this.config = config;\r\n }\r\n\r\n protected async executeQuery(\r\n input: z.infer<typeof ReadFeedSchema>\r\n ): Promise<ToolResponse | string> {\r\n const { memoryTopic, owner } = input;\r\n\r\n if (!memoryTopic) {\r\n this.logger.error(\r\n 'Missing required parameter: memoryTopic.'\r\n );\r\n\r\n throw new Error('Missing required parameter: memoryTopic.');\r\n }\r\n\r\n this.logger.info(`[API] Downloading text from Swarm feed with topic: ${memoryTopic}.`);\r\n\r\n if (!this.config.beeFeedPK) {\r\n this.logger.error('Feed private key not configured.');\r\n\r\n throw new Error('Feed private key not configured.');\r\n }\r\n\r\n // Process topic - if not a hex string, hash it\r\n let topic = memoryTopic;\r\n if (topic.startsWith(\"0x\")) {\r\n topic = topic.slice(2);\r\n }\r\n const isHexString = /^[0-9a-fA-F]{64}$/.test(topic);\r\n\r\n if (!isHexString) {\r\n // Hash the topic string using SHA-256\r\n const hash = crypto.createHash(\"sha256\").update(memoryTopic).digest(\"hex\");\r\n topic = hash;\r\n }\r\n\r\n // Convert topic string to bytes\r\n const topicBytes = hexToBytes(topic);\r\n\r\n let feedOwner = owner;\r\n if (!feedOwner) {\r\n const feedPrivateKey = hexToBytes(this.config.beeFeedPK);\r\n const signer = new Wallet(feedPrivateKey);\r\n feedOwner = signer.getAddressString().slice(2);\r\n } else {\r\n if (feedOwner.startsWith(\"0x\")) {\r\n feedOwner = feedOwner.slice(2);\r\n }\r\n if (feedOwner.length !== 40) {\r\n this.logger.error('Owner must be a valid Ethereum address.');\r\n\r\n throw new Error('Owner must be a valid Ethereum address.');\r\n }\r\n }\r\n\r\n let textData;\r\n \r\n try {\r\n const feedReader = this.bee.makeFeedReader(topicBytes, feedOwner);\r\n const latestUpdate = await feedReader.downloadPayload();\r\n textData = latestUpdate.payload.toUtf8();\r\n } catch (error) {\r\n let errorMessage = 'Reading feed failed.';\r\n if (errorHasStatus(error, BAD_REQUEST_STATUS)) {\r\n errorMessage = getErrorMessage(error);\r\n }\r\n this.logger.error(errorMessage, error);\r\n throw new Error(errorMessage);\r\n }\r\n \r\n return getResponseWithStructuredContent({\r\n textData,\r\n });\r\n }\r\n}\r\n","import {\r\n BaseHederaQueryTool,\r\n HederaAgentKit,\r\n type GenericPluginContext,\r\n} from \"hedera-agent-kit\";\r\nimport { Bee } from \"@ethersphere/bee-js\";\r\nimport { z } from \"zod\";\r\nimport crypto from \"crypto\";\r\nimport {\r\n errorHasStatus,\r\n getErrorMessage,\r\n getResponseWithStructuredContent,\r\n getUploadPostageBatchId,\r\n hexToBytes,\r\n ToolResponse,\r\n} from \"../utils\";\r\nimport { BAD_REQUEST_STATUS } from \"../constants\";\r\nimport { Wallet } from \"@ethereumjs/wallet\";\r\nimport { SwarmConfig } from \"../config\";\r\n\r\nconst UpdateFeedSchema = z.object({\r\n data: z.string(),\r\n memoryTopic: z.string(),\r\n postageBatchId: z.string().optional(),\r\n});\r\n\r\nexport class UpdateFeedTool extends BaseHederaQueryTool<typeof UpdateFeedSchema> {\r\n name = \"swarm-update-feed\";\r\n description = `Update the feed of a given topic with new data.\r\n data: Arbitrary string to upload.\r\n memoryTopic: If provided, uploads the data to a feed with this topic. It is the label of the memory that can be used later to retrieve the data instead of its content hash. If not a hex string, it will be hashed to create a feed topic.\r\n postageBatchId: The postage stamp batch ID which will be used to perform the upload, if it is provided.`;\r\n namespace = \"swarm\";\r\n specificInputSchema = UpdateFeedSchema;\r\n bee: Bee;\r\n config: SwarmConfig;\r\n \r\n constructor(params: {\r\n hederaKit: HederaAgentKit;\r\n config: SwarmConfig;\r\n logger?: GenericPluginContext['logger'];\r\n bee: Bee;\r\n }) {\r\n const { bee, config, ...rest } = params;\r\n super(rest);\r\n this.bee = bee;\r\n this.config = config;\r\n }\r\n \r\n protected async executeQuery(\r\n input: z.infer<typeof UpdateFeedSchema>\r\n ): Promise<ToolResponse | string> {\r\n const { data, memoryTopic, postageBatchId: inputPostageBatchId } = input;\r\n if (!data) {\r\n this.logger.error(\r\n 'Missing required parameter: data.'\r\n );\r\n\r\n throw new Error('Missing required parameter: data.');\r\n } else if (!memoryTopic) {\r\n this.logger.error(\r\n 'Missing required parameter: topic.'\r\n );\r\n\r\n throw new Error('Missing required parameter: topic.');\r\n }\r\n \r\n let postageBatchId = \"\";\r\n\r\n try {\r\n postageBatchId = await getUploadPostageBatchId(\r\n inputPostageBatchId,\r\n this.bee,\r\n this.config,\r\n );\r\n } catch (error) {\r\n let errorMessage = 'Update feed failed.';\r\n if (error instanceof Error) {\r\n errorMessage = error.message;\r\n }\r\n this.logger.error(errorMessage);\r\n\r\n throw new Error(errorMessage);\r\n }\r\n\r\n const binaryData = Buffer.from(data);\r\n\r\n // Feed upload if memoryTopic is specified\r\n if (!this.config.beeFeedPK) {\r\n this.logger.error('Feed private key not configured.');\r\n\r\n throw new Error('Feed private key not configured.');\r\n }\r\n\r\n // Process topic - if not a hex string, hash it\r\n let topic = memoryTopic;\r\n if (topic.startsWith(\"0x\")) {\r\n topic = topic.slice(2);\r\n }\r\n const isHexString = /^[0-9a-fA-F]{64}$/.test(memoryTopic);\r\n\r\n if (!isHexString) {\r\n // Hash the topic string using SHA-256\r\n const hash = crypto\r\n .createHash(\"sha256\")\r\n .update(memoryTopic)\r\n .digest(\"hex\");\r\n topic = hash;\r\n }\r\n\r\n // Convert topic string to bytes\r\n const topicBytes = hexToBytes(topic);\r\n\r\n const feedPrivateKey = hexToBytes(this.config.beeFeedPK);\r\n const signer = new Wallet(feedPrivateKey);\r\n const owner = signer.getAddressString().slice(2);\r\n\r\n let result;\r\n\r\n try {\r\n const feedWriter = this.bee.makeFeedWriter(topicBytes, feedPrivateKey);\r\n\r\n result = await feedWriter.uploadPayload(postageBatchId!, binaryData);\r\n } catch (error) {\r\n let errorMessage = 'Unable to update feed.';\r\n\r\n if (errorHasStatus(error, BAD_REQUEST_STATUS)) {\r\n errorMessage = getErrorMessage(error);\r\n }\r\n\r\n this.logger.error(\r\n errorMessage,\r\n error\r\n );\r\n \r\n throw new Error(errorMessage);\r\n }\r\n\r\n const reference = result.reference.toString();\r\n\r\n return getResponseWithStructuredContent({\r\n reference,\r\n topicString: memoryTopic,\r\n topic: topic,\r\n feedUrl: `${this.bee.url}/feeds/${owner}/${topic}`,\r\n message: 'Data successfully uploaded to Swarm and linked to feed.',\r\n });\r\n }\r\n}\r\n","import {\r\n BaseHederaQueryTool,\r\n HederaAgentKit,\r\n type GenericPluginContext,\r\n} from \"hedera-agent-kit\";\r\nimport { Bee, FileUploadOptions } from \"@ethersphere/bee-js\";\r\nimport { z } from \"zod\";\r\nimport { promisify } from \"util\";\r\nimport fs from \"fs\";\r\nimport {\r\n errorHasStatus,\r\n getErrorMessage,\r\n getResponseWithStructuredContent,\r\n getUploadPostageBatchId,\r\n ToolResponse,\r\n} from \"../utils\";\r\nimport { BAD_REQUEST_STATUS, DEFAULT_DEFERRED_UPLOAD_SIZE_THRESHOLD_MB, GATEWAY_TAG_ERROR_MESSAGE, NOT_FOUND_STATUS } from \"../constants\";\r\nimport { SwarmConfig } from \"../config\";\r\n\r\nconst UploadFileSchema = z.object({\r\n data: z.string(),\r\n isPath: z.boolean(),\r\n redundancyLevel: z.number().optional(),\r\n postageBatchId: z.string().optional(),\r\n});\r\n\r\nexport class UploadFileTool extends BaseHederaQueryTool<typeof UploadFileSchema> {\r\n name = \"swarm-upload-file\";\r\n description = `Upload a file to Swarm.\r\n data: base64 encoded file content or file path.\r\n isPath: Wether the data parameter is a path.\r\n redundancyLevel: Redundancy level for fault tolerance (higher values provide better fault tolerance but increase storage overhead). 0 - none, 1 - medium, 2 - strong, 3 - insane, 4 - paranoid.\r\n postageBatchId: The postage stamp batch ID which will be used to perform the upload, if it is provided.`;\r\n namespace = \"swarm\";\r\n specificInputSchema = UploadFileSchema;\r\n bee: Bee;\r\n config: SwarmConfig;\r\n\r\n constructor(params: {\r\n hederaKit: HederaAgentKit;\r\n config: SwarmConfig;\r\n logger?: GenericPluginContext['logger'];\r\n bee: Bee;\r\n }) {\r\n const { bee, config, ...rest } = params;\r\n super(rest);\r\n this.bee = bee;\r\n this.config = config;\r\n }\r\n \r\n protected async executeQuery(\r\n input: z.infer<typeof UploadFileSchema>\r\n ): Promise<ToolResponse | string> {\r\n const { data, isPath, redundancyLevel: inputRedundancyLevel, postageBatchId: inputPostageBatchId } = input;\r\n\r\n if (!data) {\r\n this.logger.error(\r\n 'Missing required parameter: data.'\r\n );\r\n\r\n throw new Error('Missing required parameter: data.');\r\n }\r\n\r\n let postageBatchId = \"\";\r\n\r\n try {\r\n postageBatchId = await getUploadPostageBatchId(\r\n inputPostageBatchId,\r\n this.bee,\r\n this.config,\r\n );\r\n } catch (error) {\r\n let errorMessage = 'Upload file failed.';\r\n if (error instanceof Error) {\r\n errorMessage = error.message;\r\n }\r\n this.logger.error(errorMessage);\r\n\r\n throw new Error(errorMessage);\r\n }\r\n\r\n let binaryData: Buffer;\r\n let name: string | undefined;\r\n\r\n if (isPath) {\r\n // Read file from path\r\n try {\r\n binaryData = await promisify(fs.readFile)(data);\r\n } catch (fileError) {\r\n this.logger.error(\r\n `Unable to read file at path: ${data}.`,\r\n fileError\r\n );\r\n\r\n throw new Error(`Unable to read file at path: ${data}.`);\r\n }\r\n\r\n name = data.split(\"/\").pop();\r\n } else {\r\n binaryData = Buffer.from(data, \"base64\");\r\n }\r\n\r\n const redundancyLevel = inputRedundancyLevel;\r\n const options: FileUploadOptions = {};\r\n const deferredUploadSizeThreshold = Number(this.config.deferredUploadSizeThresholdMB) ||\r\n DEFAULT_DEFERRED_UPLOAD_SIZE_THRESHOLD_MB;\r\n const deferred =\r\n binaryData.length > deferredUploadSizeThreshold * 1024 * 1024;\r\n options.deferred = deferred;\r\n if (redundancyLevel) {\r\n options.redundancyLevel = redundancyLevel;\r\n }\r\n\r\n let message = \"File successfully uploaded to Swarm\";\r\n let tagId: string | undefined = undefined;\r\n // Create tag for deferred uploads or when explicitly requested\r\n if (deferred) {\r\n try {\r\n const tag = await this.bee.createTag();\r\n options.tag = tag.uid;\r\n tagId = tag.uid.toString();\r\n message =\r\n \"File upload started in deferred mode. Use query_upload_progress to track progress.\";\r\n } catch (error) {\r\n if (errorHasStatus(error, NOT_FOUND_STATUS)) {\r\n this.logger.error(\r\n GATEWAY_TAG_ERROR_MESSAGE,\r\n error\r\n );\r\n\r\n throw new Error(GATEWAY_TAG_ERROR_MESSAGE);\r\n }\r\n }\r\n }\r\n\r\n let result;\r\n\r\n try {\r\n // Start the deferred upload\r\n result = await this.bee.uploadFile(postageBatchId, binaryData, name, options);\r\n } catch (error) {\r\n let errorMessage = 'Unable to upload file.';\r\n\r\n if (errorHasStatus(error, BAD_REQUEST_STATUS)) {\r\n errorMessage = getErrorMessage(error);\r\n }\r\n\r\n this.logger.error(\r\n errorMessage,\r\n error\r\n );\r\n \r\n throw new Error(errorMessage);\r\n }\r\n\r\n return getResponseWithStructuredContent({\r\n reference: result.reference.toString(),\r\n url: this.bee.url + \"/bzz/\" + result.reference.toString(),\r\n message,\r\n tagId,\r\n });\r\n }\r\n}\r\n","import {\r\n BaseHederaQueryTool,\r\n HederaAgentKit,\r\n type GenericPluginContext,\r\n} from \"hedera-agent-kit\";\r\nimport { Bee, CollectionUploadOptions } from \"@ethersphere/bee-js\";\r\nimport { z } from \"zod\";\r\nimport { promisify } from \"util\";\r\nimport fs from \"fs\";\r\nimport {\r\n errorHasStatus,\r\n getErrorMessage,\r\n getResponseWithStructuredContent,\r\n getUploadPostageBatchId,\r\n ToolResponse,\r\n} from \"../utils\";\r\nimport { BAD_REQUEST_STATUS } from \"../constants\";\r\nimport { SwarmConfig } from \"../config\";\r\n\r\nconst UploadFolderSchema = z.object({\r\n folderPath: z.string(),\r\n redundancyLevel: z.number().optional(),\r\n postageBatchId: z.string().optional(),\r\n});\r\n\r\nexport class UploadFolderTool extends BaseHederaQueryTool<typeof UploadFolderSchema> {\r\n name = \"swarm-upload-folder\";\r\n description = `Upload a folder to Swarm.\r\n folderPath: Path to the folder to upload. \r\n redundancyLevel: Redundancy level for fault tolerance (higher values provide better fault tolerance but increase storage overhead). 0 - none, 1 - medium, 2 - strong, 3 - insane, 4 - paranoid. \r\n postageBatchId: The postage stamp batch ID which will be used to perform the upload, if it is provided.`;\r\n namespace = \"swarm\";\r\n specificInputSchema = UploadFolderSchema;\r\n bee: Bee;\r\n config: SwarmConfig;\r\n \r\n constructor(params: {\r\n hederaKit: HederaAgentKit;\r\n config: SwarmConfig;\r\n logger?: GenericPluginContext['logger'];\r\n bee: Bee;\r\n }) {\r\n const { bee, config, ...rest } = params;\r\n super(rest);\r\n this.bee = bee;\r\n this.config = config;\r\n }\r\n \r\n protected async executeQuery(\r\n input: z.infer<typeof UploadFolderSchema>\r\n ): Promise<ToolResponse | string> {\r\n const { folderPath, redundancyLevel: inputRedundancyLevel, postageBatchId: inputPostageBatchId } = input;\r\n\r\n if (!folderPath) {\r\n this.logger.error(\r\n 'Missing required parameter: folderPath.'\r\n );\r\n\r\n throw new Error('Missing required parameter: folderPath.');\r\n }\r\n\r\n // Check if folder exists\r\n const stats = await promisify(fs.stat)(folderPath);\r\n if (!stats.isDirectory()) {\r\n this.logger.error(\r\n `Path is not a directory: ${folderPath}.`\r\n );\r\n\r\n throw new Error(`Path is not a directory: ${folderPath}.`);\r\n }\r\n\r\n let postageBatchId = \"\";\r\n\r\n try {\r\n postageBatchId = await getUploadPostageBatchId(\r\n inputPostageBatchId,\r\n this.bee,\r\n this.config,\r\n );\r\n } catch (error) {\r\n let errorMessage = 'Upload folder failed.';\r\n if (error instanceof Error) {\r\n errorMessage = error.message;\r\n }\r\n this.logger.error(errorMessage);\r\n\r\n throw new Error(errorMessage);\r\n }\r\n \r\n const redundancyLevel = inputRedundancyLevel;\r\n const options: CollectionUploadOptions = {};\r\n\r\n if (redundancyLevel) {\r\n options.redundancyLevel = redundancyLevel;\r\n }\r\n\r\n const deferred = true;\r\n options.deferred = deferred;\r\n let message = 'Folder successfully uploaded to Swarm';\r\n\r\n let tagId: string | undefined = undefined;\r\n\r\n if (deferred) {\r\n try {\r\n const tag = await this.bee.createTag();\r\n tagId = tag.uid.toString();\r\n options.tag = tag.uid;\r\n message =\r\n 'Folder upload started in deferred mode. Use swarm-query-upload-progress to track progress.';\r\n } catch (error) {\r\n this.logger.error(\r\n 'Failed to create tag',\r\n error\r\n );\r\n options.deferred = false;\r\n }\r\n }\r\n\r\n let result;\r\n\r\n try {\r\n // Start the deferred upload\r\n result = await this.bee.uploadFilesFromDirectory(\r\n postageBatchId,\r\n folderPath,\r\n options\r\n );\r\n } catch (error) {\r\n let errorMessage = 'Unable to upload folder.';\r\n\r\n if (errorHasStatus(error, BAD_REQUEST_STATUS)) {\r\n errorMessage = getErrorMessage(error);\r\n }\r\n\r\n this.logger.error(\r\n errorMessage,\r\n error\r\n );\r\n \r\n throw new Error(errorMessage);\r\n }\r\n\r\n return getResponseWithStructuredContent({\r\n reference: result.reference.toString(),\r\n url: this.bee.url + \"/bzz/\" + result.reference.toString(),\r\n message,\r\n tagId,\r\n });\r\n }\r\n}\r\n","import {\n BasePlugin,\n type GenericPluginContext,\n type HederaAgentKit,\n type HederaTool,\n} from \"hedera-agent-kit\";\nimport { Bee } from \"@ethersphere/bee-js\";\nimport { ListPostageStampsTool } from \"./tools/ListPostageStampsTool\";\nimport { UploadDataTool } from \"./tools/UploadDataTool\";\nimport { DownloadDataTool } from \"./tools/DownloadDataTool\";\nimport { CreatePostageStampTool } from \"./tools/CreatePostageStampTool\";\nimport { ExtendPostageStampTool } from \"./tools/ExtendPostageStampTool\";\nimport { QueryUploadProgressTool } from \"./tools/QueryUploadProgressTool\";\nimport { DownloadFilesTool } from \"./tools/DownloadFilesTool\";\nimport { GetPostageStampTool } from \"./tools/GetPostageStampTool\";\nimport { ReadFeedTool } from \"./tools/ReadFeedTool\";\nimport { UpdateFeedTool } from \"./tools/UpdateFeedTool\";\nimport { UploadFileTool } from \"./tools/UploadFileTool\";\nimport { UploadFolderTool } from \"./tools/UploadFolderTool\";\nimport { SwarmConfig } from \"./config\";\n\nexport class SwarmPlugin extends BasePlugin<GenericPluginContext> {\n id = \"swarm\";\n name = \"Swarm Plugin\";\n description =\n \"Swarm operations: tools for interacting with the Swarm decentralized storage.\";\n version = \"1.0.0\";\n author = \"Solar Punk\";\n namespace = \"swarm\";\n\n private config: SwarmConfig | null;\n private tools: HederaTool[] = [];\n\n constructor(\n config?: SwarmConfig\n ) {\n super();\n this.config = config || null;\n }\n\n override async initialize(context: GenericPluginContext): Promise<void> {\n \n await super.initialize(context);\n\n const hederaKit = context.config.hederaKit as HederaAgentKit | undefined;\n\n if (!hederaKit) {\n this.context.logger.warn(\n 'SwarmPlugin skipped because HederaAgentKit was not present in plugin context.'\n );\n this.tools = [];\n return;\n }\n \n if (!this.config) {\n this.context.logger.warn(\n 'SwarmPlugin skipped because Swarm config was not present.'\n );\n this.tools = [];\n return;\n }\n \n const beeURL = this.config.beeApiUrl;\n \n const bee = new Bee(beeURL);\n\n const createPostageStampTool = new CreatePostageStampTool({\n hederaKit,\n bee,\n config: this.config,\n logger: this.context.logger,\n });\n\n const downloadDataTool = new DownloadDataTool({\n hederaKit,\n bee,\n config: this.config,\n logger: this.context.logger,\n });\n \n const downloadFilesTool = new DownloadFilesTool({\n hederaKit,\n bee,\n config: this.config,\n logger: this.context.logger,\n });\n \n const extendPostageStampTool = new ExtendPostageStampTool({\n hederaKit,\n bee,\n config: this.config,\n logger: this.context.logger,\n });\n\n const getPostageStampsTool = new GetPostageStampTool({\n hederaKit,\n bee,\n config: this.config,\n logger: this.context.logger,\n });\n \n const listPostageStampsTool = new ListPostageStampsTool({\n hederaKit,\n bee,\n config: this.config,\n logger: this.context.logger,\n });\n \n const queryUploadProgressTool = new QueryUploadProgressTool({\n hederaKit,\n bee,\n config: this.config,\n logger: this.context.logger,\n });\n \n const readFeedTool = new ReadFeedTool({\n hederaKit,\n bee,\n config: this.config,\n logger: this.context.logger,\n });\n \n const updateFeedTool = new UpdateFeedTool({\n hederaKit,\n bee,\n config: this.config,\n logger: this.context.logger,\n });\n \n const uploadDataTool = new UploadDataTool({\n hederaKit,\n bee,\n config: this.config,\n logger: this.context.logger,\n });\n \n const uploadFileTool = new UploadFileTool({\n hederaKit,\n bee,\n config: this.config,\n logger: this.context.logger,\n });\n \n const uploadFolderTool = new UploadFolderTool({\n hederaKit,\n bee,\n config: this.config,\n logger: this.context.logger,\n });\n \n this.tools = [\n createPostageStampTool,\n downloadDataTool,\n downloadFilesTool,\n extendPostageStampTool,\n getPostageStampsTool,\n listPostageStampsTool,\n queryUploadProgressTool,\n readFeedTool,\n updateFeedTool,\n uploadDataTool,\n uploadFileTool,\n uploadFolderTool\n ];\n\n this.context.logger.info(\n \"Swarm Plugin initialized.\"\n );\n }\n\n override getTools(): HederaTool[] {\n return this.tools;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n }\n}\n","/**\n * Registry for field type detection patterns\n * @module FieldTypeRegistry\n */\n\nimport type { FormFieldType } from './types';\n\n/**\n * Pattern-based field type detection rule\n */\nexport interface FieldTypePattern {\n pattern: RegExp | string[];\n type: FormFieldType;\n priority?: number;\n}\n\n/**\n * Registry for managing field type detection patterns\n */\nexport class FieldTypeRegistry {\n private static instance: FieldTypeRegistry;\n private patterns: Map<string, FieldTypePattern> = new Map();\n\n private constructor() {\n this.initializeDefaultPatterns();\n }\n\n /**\n * Get singleton instance\n */\n static getInstance(): FieldTypeRegistry {\n if (!FieldTypeRegistry.instance) {\n FieldTypeRegistry.instance = new FieldTypeRegistry();\n }\n return FieldTypeRegistry.instance;\n }\n\n /**\n * Initialize default field type patterns\n */\n private initializeDefaultPatterns(): void {\n this.register('numeric-supply-exact', {\n pattern: ['maxSupply', 'minSupply', 'totalSupply'],\n type: 'number',\n priority: 15,\n });\n\n this.register('numeric-supply', {\n pattern: /supply$/i,\n type: 'number',\n priority: 10,\n });\n\n this.register('numeric-amounts', {\n pattern: /(?:amount|quantity|count|total|sum|value)$/i,\n type: 'number',\n priority: 8,\n });\n\n this.register('numeric-time', {\n pattern: /(?:period|duration|time|timeout|delay|interval)$/i,\n type: 'number',\n priority: 8,\n });\n\n this.register('numeric-limits', {\n pattern: /(?:limit|max|min|threshold|size|length)$/i,\n type: 'number',\n priority: 7,\n });\n\n this.register('currency', {\n pattern: /(?:price|cost|fee|payment|balance|amount)$/i,\n type: 'currency',\n priority: 9,\n });\n\n this.register('percentage', {\n pattern: /(?:percent|percentage|rate|ratio)$/i,\n type: 'percentage',\n priority: 9,\n });\n\n this.register('boolean-freeze', {\n pattern: ['freezeDefault', 'freeze'],\n type: 'checkbox',\n priority: 10,\n });\n\n this.register('boolean-flags', {\n pattern:\n /(?:is|has|can|should|enable|disable|active|default|allow)(?:[A-Z]|$)/,\n type: 'checkbox',\n priority: 8,\n });\n\n this.register('textarea', {\n pattern: /(?:memo|description|notes|comment|message|content|body|text)$/i,\n type: 'textarea',\n priority: 8,\n });\n\n this.register('array-fees', {\n pattern: ['customFees', 'fees'],\n type: 'array',\n priority: 10,\n });\n\n this.register('array-general', {\n pattern: /(?:list|items|array|collection)$/i,\n type: 'array',\n priority: 7,\n });\n\n this.register('object-options', {\n pattern: ['metaOptions', 'options'],\n type: 'object',\n priority: 10,\n });\n\n this.register('object-config', {\n pattern: /(?:config|settings|configuration|metadata|data|info)$/i,\n type: 'object',\n priority: 7,\n });\n\n this.register('select-type', {\n pattern: /(?:type|kind|category|status|state|mode)$/i,\n type: 'select',\n priority: 7,\n });\n }\n\n /**\n * Register a field type pattern\n */\n register(key: string, pattern: FieldTypePattern): void {\n this.patterns.set(key, pattern);\n }\n\n /**\n * Unregister a field type pattern\n */\n unregister(key: string): boolean {\n return this.patterns.delete(key);\n }\n\n /**\n * Detect field type based on field name\n */\n detectType(fieldName: string): FormFieldType | null {\n const matches: Array<{ type: FormFieldType; priority: number }> = [];\n\n for (const pattern of this.patterns.values()) {\n let isMatch = false;\n\n if (Array.isArray(pattern.pattern)) {\n isMatch = pattern.pattern.some(\n (p) => fieldName === p || fieldName.toLowerCase() === p.toLowerCase()\n );\n } else if (pattern.pattern instanceof RegExp) {\n isMatch = pattern.pattern.test(fieldName);\n }\n\n if (isMatch) {\n matches.push({\n type: pattern.type,\n priority: pattern.priority ?? 5,\n });\n }\n }\n\n if (matches.length > 0) {\n matches.sort((a, b) => b.priority - a.priority);\n return matches[0].type;\n }\n\n return null;\n }\n\n /**\n * Get all registered patterns\n */\n getPatterns(): Map<string, FieldTypePattern> {\n return new Map(this.patterns);\n }\n\n /**\n * Clear all patterns\n */\n clear(): void {\n this.patterns.clear();\n }\n\n /**\n * Reset to default patterns\n */\n reset(): void {\n this.clear();\n this.initializeDefaultPatterns();\n }\n}\n\nexport const fieldTypeRegistry = FieldTypeRegistry.getInstance();\n","/**\n * Common error messages and user feedback strings\n */\nexport const ERROR_MESSAGES = {\n TOO_MANY_REQUESTS: 'Too many requests. Please wait a moment and try again.',\n RATE_LIMITED: \"I'm receiving too many requests right now. Please wait a moment and try again.\",\n SYSTEM_ERROR: 'System error occurred',\n INVALID_INPUT: 'Invalid input provided',\n NETWORK_ERROR: 'Network error occurred',\n} as const;\n\n/**\n * Common success and status messages\n */\nexport const STATUS_MESSAGES = {\n OPERATION_SUCCESSFUL: 'Operation completed successfully',\n PROCESSING: 'Processing your request...',\n READY: 'Ready to process requests',\n INITIALIZING: 'Initializing...',\n} as const;","import { NetworkType } from '@hashgraphonline/standards-sdk';\n\nexport enum EntityFormat {\n TOPIC_ID = 'topicId',\n HRL = 'hrl',\n SCHEDULE_ID = 'scheduleId',\n TOKEN_ID = 'tokenId',\n ADDRESS = 'address',\n SYMBOL = 'symbol',\n SERIAL_NUMBER = 'serialNumber',\n METADATA = 'metadata',\n ACCOUNT_ID = 'accountId',\n ALIAS = 'alias',\n EVM_ADDRESS = 'evmAddress',\n CONTRACT_ID = 'contractId',\n FILE_ID = 'fileId',\n ANY = 'any'\n}\n\nexport interface ConversionContext {\n networkType?: NetworkType;\n sessionId?: string;\n toolName?: string;\n toolPreferences?: Record<string, string>;\n [key: string]: unknown;\n}\n\nexport interface FormatConverter<TSource = string, TTarget = string> {\n sourceFormat: EntityFormat;\n targetFormat: EntityFormat;\n canConvert(source: string, context: ConversionContext): boolean;\n convert(entity: TSource, context: ConversionContext): Promise<TTarget>;\n}","/**\n * Common entity reference patterns used across the application\n */\nexport const ENTITY_PATTERNS = {\n TOPIC_REFERENCE: 'the topic',\n TOKEN_REFERENCE: 'the token',\n ACCOUNT_REFERENCE: 'the account',\n TRANSACTION_REFERENCE: 'the transaction',\n CONTRACT_REFERENCE: 'the contract',\n} as const;\n\n/**\n * Entity type identifiers\n */\nimport { EntityFormat } from '../services/formatters/types';\n\nexport const ENTITY_TYPES = {\n TOPIC: EntityFormat.TOPIC_ID,\n TOKEN: EntityFormat.TOKEN_ID,\n ACCOUNT: EntityFormat.ACCOUNT_ID,\n TRANSACTION: 'transaction',\n CONTRACT: EntityFormat.CONTRACT_ID,\n} as const;\n","/**\n * Form field priorities for progressive disclosure\n */\nexport const FIELD_PRIORITIES = {\n ESSENTIAL: 'essential',\n COMMON: 'common', \n ADVANCED: 'advanced',\n EXPERT: 'expert'\n} as const;\n\n/**\n * Form field types\n */\nexport const FORM_FIELD_TYPES = {\n TEXT: 'text',\n NUMBER: 'number',\n SELECT: 'select',\n CHECKBOX: 'checkbox',\n TEXTAREA: 'textarea',\n FILE: 'file',\n ARRAY: 'array',\n OBJECT: 'object',\n CURRENCY: 'currency',\n PERCENTAGE: 'percentage',\n} as const;","import { z, ZodError } from 'zod';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport type {\n FormConfig,\n FormField,\n ValidationError,\n FormMessage,\n FormFieldType,\n} from './types';\nimport {\n extractRenderConfigs,\n generateFieldOrdering,\n type RenderConfigSchema,\n type ZodSchemaWithRender,\n type ExtractedRenderConfig,\n} from '@hashgraphonline/standards-agent-kit';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport { fieldTypeRegistry } from './field-type-registry';\nimport { fieldGuidanceRegistry } from './field-guidance-registry';\nimport { FIELD_PRIORITIES } from '../constants';\n\ninterface ZodObjectSchema extends z.ZodSchema {\n shape?: Record<string, z.ZodSchema>;\n}\n\nfunction isZodObjectSchema(schema: z.ZodSchema): schema is ZodObjectSchema {\n return typeof schema === 'object' && schema !== null && 'shape' in schema;\n}\n\ntype FieldPriority = 'essential' | 'common' | 'advanced' | 'expert';\n\n/**\n * Generates forms from Zod validation failures\n */\nexport class FormGenerator {\n private logger: Logger;\n\n constructor() {\n this.logger = new Logger({ module: 'FormGenerator' });\n }\n\n /**\n * Creates a form message from a Zod validation error\n * @param error The Zod validation error\n * @param schema The original Zod schema\n * @param toolName Name of the tool that failed validation\n * @param originalPrompt The user's original request\n * @returns FormMessage to send to the chat UI\n */\n generateFormFromError(\n error: ZodError,\n schema: z.ZodSchema,\n toolName: string,\n originalPrompt: string\n ): FormMessage {\n const validationErrors = this.extractValidationErrors(error);\n const missingFields = this.identifyMissingFields(validationErrors, schema);\n const formConfig = this.createFormConfig(schema, missingFields, toolName);\n\n return {\n type: 'form',\n id: `form_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n formConfig,\n originalPrompt,\n toolName,\n validationErrors,\n };\n }\n\n /**\n * Generates a form from a schema and partial input\n * @param schema The Zod schema to generate a form from\n * @param partialInput Any partial input already provided\n * @param context Additional context about the tool\n * @param preCalculatedMissingFields Optional pre-calculated missing fields set. If undefined, includes all fields from schema.\n * @returns FormMessage to send to the chat UI\n */\n async generateFormFromSchema(\n schema: z.ZodSchema,\n partialInput: unknown,\n context: { toolName: string; toolDescription?: string },\n preCalculatedMissingFields?: Set<string>\n ): Promise<FormMessage> {\n let missingFields: Set<string>;\n\n this.logger.info(`🏁 FormGenerator.generateFormFromSchema starting`, {\n toolName: context.toolName,\n partialInput,\n hasSchema: !!schema,\n hasShape: !!(schema && isZodObjectSchema(schema)),\n hasPreCalculatedFields: preCalculatedMissingFields !== undefined,\n preCalculatedFieldsSize: preCalculatedMissingFields?.size || 0,\n });\n\n if (preCalculatedMissingFields !== undefined) {\n missingFields = preCalculatedMissingFields;\n this.logger.info(`📋 Using pre-calculated missing fields`, {\n missingFieldsCount: missingFields.size,\n missingFields: Array.from(missingFields),\n });\n } else {\n missingFields = new Set<string>();\n\n const zodObject = this.extractZodObject(schema);\n if (zodObject) {\n const shape = zodObject.shape;\n for (const fieldName of Object.keys(shape)) {\n missingFields.add(fieldName);\n this.logger.info(\n `⭐ Including all fields from focused schema: ${fieldName}`\n );\n }\n }\n\n this.logger.info(`📋 Using ALL fields from focused schema`, {\n totalFields: zodObject ? Object.keys(zodObject.shape).length : 0,\n missingFieldsCount: missingFields.size,\n missingFields: Array.from(missingFields),\n });\n }\n\n const formConfig = this.createFormConfig(\n schema,\n missingFields,\n context.toolName,\n preCalculatedMissingFields\n );\n\n return {\n type: 'form',\n id: `form_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n formConfig,\n originalPrompt: context.toolDescription || `Complete ${context.toolName}`,\n toolName: context.toolName,\n validationErrors: [],\n };\n }\n\n /**\n * Extracts validation errors from ZodError\n */\n private extractValidationErrors(error: ZodError): ValidationError[] {\n return error.issues.map((issue) => ({\n path: issue.path.map((p) => String(p)),\n message: issue.message,\n code: issue.code,\n }));\n }\n\n /**\n * Identifies which fields are missing or invalid from validation errors\n */\n private identifyMissingFields(\n errors: ValidationError[],\n _schema: z.ZodSchema\n ): Set<string> {\n const missingFields = new Set<string>();\n\n errors.forEach((error) => {\n const fieldPath = error.path.join('.');\n if (fieldPath) {\n missingFields.add(fieldPath);\n }\n });\n\n return missingFields;\n }\n\n /**\n * Creates form configuration from schema\n */\n private createFormConfig(\n schema: z.ZodSchema,\n missingFields: Set<string>,\n toolName: string,\n preCalculatedMissingFields?: Set<string>\n ): FormConfig {\n const extractedConfig = this.extractRenderConfigsSafely(schema);\n const fieldOrdering = this.generateFieldOrderingSafely(schema);\n const fields = this.generateFormFields(\n schema,\n extractedConfig,\n missingFields,\n fieldOrdering,\n preCalculatedMissingFields,\n toolName\n );\n\n const globalGuidance = fieldGuidanceRegistry.getGlobalGuidance(toolName);\n let description = this.generateFormDescription(\n toolName,\n missingFields.size\n );\n\n if (globalGuidance?.qualityStandards) {\n description +=\n '\\n\\nQuality Guidelines:\\n' +\n globalGuidance.qualityStandards\n .map((standard) => `• ${standard}`)\n .join('\\n');\n }\n\n return {\n title: this.generateFormTitle(toolName),\n description,\n fields,\n submitLabel: 'Continue',\n cancelLabel: 'Cancel',\n metadata: {\n toolName,\n missingFieldCount: missingFields.size,\n globalGuidance,\n },\n };\n }\n\n /**\n * Safely extracts render configs from schema\n */\n private extractRenderConfigsSafely(\n schema: z.ZodSchema\n ): ExtractedRenderConfig {\n try {\n if (typeof extractRenderConfigs === 'function') {\n return extractRenderConfigs(schema as unknown as ZodSchemaWithRender);\n }\n } catch (error) {\n this.logger.warn('Could not extract render configs:', error);\n }\n return {\n fields: {},\n groups: {},\n order: [],\n metadata: {},\n };\n }\n\n /**\n * Safely generates field ordering from schema\n */\n private generateFieldOrderingSafely(schema: z.ZodSchema): {\n sections: Array<{ fields: string[] }>;\n } {\n try {\n if (typeof generateFieldOrdering === 'function') {\n const ordering = generateFieldOrdering(\n schema as unknown as ZodSchemaWithRender\n );\n\n const sections = Object.values(ordering.sections).map((section) => ({\n fields: section.fields,\n }));\n return { sections };\n }\n } catch (error) {\n this.logger.warn('Could not generate field ordering:', error);\n }\n return { sections: [] };\n }\n\n /**\n * Determines field priority for progressive disclosure\n */\n private getFieldPriority(\n name: string,\n renderConfig?: RenderConfigSchema,\n isRequired?: boolean\n ): FieldPriority {\n if (renderConfig?.ui?.priority) {\n const priority = renderConfig.ui.priority as string;\n if (Object.values(FIELD_PRIORITIES).includes(priority as FieldPriority)) {\n return priority as FieldPriority;\n }\n }\n\n if (isRequired === true) {\n return FIELD_PRIORITIES.ESSENTIAL;\n }\n\n const ui = renderConfig?.ui as Record<string, unknown> | undefined;\n if (ui?.advanced === true) {\n return FIELD_PRIORITIES.ADVANCED;\n }\n\n if (ui?.expert === true) {\n return FIELD_PRIORITIES.EXPERT;\n }\n\n return FIELD_PRIORITIES.COMMON;\n }\n\n /**\n * Determines which fields should be included in the form\n */\n private determineFieldsToInclude(\n schema: z.ZodSchema,\n missingFields: Set<string>,\n preCalculatedMissingFields?: Set<string>\n ): Set<string> {\n const fieldsToInclude = new Set<string>();\n\n if (preCalculatedMissingFields === undefined) {\n this.logger.info(\n `⭐ Focused schema mode - including ALL fields from schema`\n );\n const allSchemaFields = this.extractFieldsFromSchema(schema);\n allSchemaFields.forEach((fieldName) => {\n fieldsToInclude.add(fieldName);\n this.logger.info(`✅ Including focused schema field: ${fieldName}`);\n });\n } else if (preCalculatedMissingFields.size > 0) {\n this.logger.info(\n `📋 Using ONLY pre-calculated missing fields (${preCalculatedMissingFields.size} fields)`,\n { fields: Array.from(preCalculatedMissingFields) }\n );\n preCalculatedMissingFields.forEach((fieldName) => {\n fieldsToInclude.add(fieldName);\n this.logger.info(`✅ Including pre-calculated field: ${fieldName}`);\n });\n } else {\n this.logger.info(\n '⚠️ No pre-calculated fields, falling back to schema analysis'\n );\n this.includeRequiredMissingFields(schema, missingFields, fieldsToInclude);\n }\n\n return fieldsToInclude;\n }\n\n /**\n * Includes required fields that are missing\n */\n private includeRequiredMissingFields(\n schema: z.ZodSchema,\n missingFields: Set<string>,\n fieldsToInclude: Set<string>\n ): void {\n const allSchemaFields = this.extractFieldsFromSchema(schema);\n allSchemaFields.forEach((fieldName) => {\n const isRequired = this.isFieldRequired(schema, fieldName);\n const isMissing = missingFields.has(fieldName);\n const shouldInclude = isMissing && isRequired;\n\n this.logger.info(`🔍 FormGenerator field inclusion check: ${fieldName}`, {\n isRequired,\n isMissing,\n shouldInclude,\n });\n\n if (shouldInclude) {\n fieldsToInclude.add(fieldName);\n }\n });\n }\n\n /**\n * Creates form fields from ordered field names\n */\n private createOrderedFields(\n fieldsToInclude: Set<string>,\n fieldOrdering: { sections: Array<{ fields: string[] }> },\n extractedConfig: ExtractedRenderConfig,\n schema: z.ZodSchema,\n toolName?: string\n ): FormField[] {\n const fields: FormField[] = [];\n const processedFields = new Set<string>();\n\n if (fieldOrdering.sections.length > 0) {\n const orderedFieldNames = fieldOrdering.sections.flatMap((s) => s.fields);\n orderedFieldNames.forEach((fieldName) => {\n if (fieldsToInclude.has(fieldName) && !processedFields.has(fieldName)) {\n const field = this.createFormField(\n fieldName,\n extractedConfig.fields[fieldName],\n schema,\n fieldName,\n toolName\n );\n if (field) {\n fields.push(field);\n processedFields.add(fieldName);\n }\n }\n });\n }\n\n fieldsToInclude.forEach((fieldName) => {\n if (!processedFields.has(fieldName)) {\n const field = this.createFormField(\n fieldName,\n extractedConfig.fields[fieldName],\n schema,\n fieldName,\n toolName\n );\n if (field) {\n fields.push(field);\n }\n }\n });\n\n return fields;\n }\n\n /**\n * Generates form fields from schema and validation errors\n */\n private generateFormFields(\n schema: z.ZodSchema,\n extractedConfig: ExtractedRenderConfig,\n missingFields: Set<string>,\n fieldOrdering: { sections: Array<{ fields: string[] }> },\n preCalculatedMissingFields?: Set<string>,\n toolName?: string\n ): FormField[] {\n const fieldsToInclude = this.determineFieldsToInclude(\n schema,\n missingFields,\n preCalculatedMissingFields\n );\n\n let fields = this.createOrderedFields(\n fieldsToInclude,\n fieldOrdering,\n extractedConfig,\n schema,\n toolName\n );\n\n if (fields.length === 0 && missingFields.size > 0) {\n fields = Array.from(missingFields)\n .map((fieldName) =>\n this.createFormField(\n fieldName,\n extractedConfig.fields[fieldName],\n schema,\n fieldName,\n toolName\n )\n )\n .filter(\n (field): field is FormField => field !== null && field !== undefined\n );\n }\n\n return fields;\n }\n\n /**\n * Creates a single form field\n */\n private createFormField(\n fieldName: string,\n renderConfig?: RenderConfigSchema,\n schema?: z.ZodSchema,\n fieldPath?: string,\n toolName?: string\n ): FormField {\n const type = this.mapFieldType(renderConfig?.fieldType, schema, fieldPath);\n const isRequired = this.isFieldRequired(schema, fieldPath || fieldName);\n\n const guidance = toolName\n ? fieldGuidanceRegistry.getFieldGuidance(toolName, fieldName)\n : null;\n const finalType = guidance?.fieldTypeOverride || type;\n\n const field: FormField = {\n name: fieldName,\n label: renderConfig?.ui?.label || this.humanizeFieldName(fieldName),\n type: finalType,\n required: isRequired,\n priority: this.getFieldPriority(fieldName, renderConfig, isRequired),\n };\n\n if (guidance) {\n if (guidance.suggestions && guidance.suggestions.length > 0) {\n field.suggestions = guidance.suggestions;\n if (!field.placeholder) {\n field.placeholder = `e.g., ${guidance.suggestions[0]}`;\n }\n }\n\n if (guidance.predefinedOptions) {\n field.options = [\n ...(field.options || []),\n ...guidance.predefinedOptions,\n ];\n }\n\n if (guidance.contextualHelpText) {\n field.helpText = guidance.contextualHelpText;\n }\n\n if (guidance.warnings) {\n field.warnings = guidance.warnings.map((w) => w.message);\n }\n\n if (guidance.validationRules) {\n const { qualityChecks } = guidance.validationRules;\n if (qualityChecks) {\n field.contextualGuidance = {\n qualityStandards: [],\n examples: guidance.suggestions || [],\n avoidPatterns: qualityChecks.forbidTechnicalTerms || [],\n };\n\n if (qualityChecks.minNonTechnicalWords) {\n field.contextualGuidance.qualityStandards?.push(\n `Use at least ${qualityChecks.minNonTechnicalWords} meaningful words`\n );\n }\n\n if (qualityChecks.forbidTechnicalTerms) {\n field.contextualGuidance.qualityStandards?.push(\n `Avoid technical terms like: ${qualityChecks.forbidTechnicalTerms.join(\n ', '\n )}`\n );\n }\n }\n }\n }\n\n if (renderConfig) {\n field.renderConfig = renderConfig;\n }\n\n if (renderConfig?.ui?.placeholder) {\n field.placeholder = renderConfig.ui.placeholder;\n }\n\n if (renderConfig?.ui?.helpText) {\n field.helpText = renderConfig.ui.helpText;\n }\n\n if (renderConfig?.constraints) {\n const validation: Record<string, unknown> = {};\n if (renderConfig.constraints.min !== undefined)\n validation.min = renderConfig.constraints.min;\n if (renderConfig.constraints.max !== undefined)\n validation.max = renderConfig.constraints.max;\n if (renderConfig.constraints.minLength !== undefined)\n validation.minLength = renderConfig.constraints.minLength;\n if (renderConfig.constraints.maxLength !== undefined)\n validation.maxLength = renderConfig.constraints.maxLength;\n if (renderConfig.constraints.pattern !== undefined)\n validation.pattern = renderConfig.constraints.pattern;\n\n if (Object.keys(validation).length > 0) {\n field.validation = validation;\n }\n }\n\n if (renderConfig?.options) {\n field.options = renderConfig.options.map((opt) => ({\n value: String(opt.value),\n label: opt.label,\n ...(opt.disabled !== undefined && { disabled: opt.disabled }),\n }));\n }\n\n return field;\n }\n\n /**\n * Maps render config field type to form field type with fallback inference\n */\n private mapFieldType(\n fieldType?: string,\n schema?: z.ZodSchema,\n fieldPath?: string\n ): FormFieldType {\n if (!fieldType && schema && fieldPath) {\n const inferredType = this.inferTypeFromSchema(schema, fieldPath);\n if (inferredType) {\n return inferredType;\n }\n }\n\n if (!fieldType && fieldPath) {\n const registryType = fieldTypeRegistry.detectType(fieldPath);\n if (registryType) {\n return registryType;\n }\n }\n\n if (!fieldType) {\n return 'text';\n }\n\n const normalizedType = fieldType.toLowerCase();\n\n if (['text', 'string'].includes(normalizedType)) return 'text';\n if (['number', 'integer', 'float', 'decimal'].includes(normalizedType))\n return 'number';\n if (['select', 'enum', 'dropdown'].includes(normalizedType))\n return 'select';\n if (['checkbox', 'boolean', 'bool'].includes(normalizedType))\n return 'checkbox';\n if (['textarea', 'longtext', 'multiline'].includes(normalizedType))\n return 'textarea';\n if (['file', 'upload', 'attachment'].includes(normalizedType))\n return 'file';\n if (['array', 'list'].includes(normalizedType)) return 'array';\n if (['object', 'json'].includes(normalizedType)) return 'object';\n if (['currency', 'money', 'price'].includes(normalizedType))\n return 'currency';\n if (['percentage', 'percent'].includes(normalizedType)) return 'percentage';\n\n return 'text';\n }\n\n /**\n * Converts field name to human-readable label\n */\n private humanizeFieldName(fieldName: string): string {\n return fieldName\n .replace(/([A-Z])/g, ' $1')\n .replace(/_/g, ' ')\n .replace(/\\./g, ' ')\n .trim()\n .split(' ')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n }\n\n /**\n * Generates a title for the form\n */\n private generateFormTitle(toolName: string): string {\n const cleanName = toolName\n .replace(/Tool$/, '')\n .replace(/Hedera/g, '')\n .replace(/([A-Z])/g, ' $1')\n .trim();\n\n return `Complete ${cleanName} Information`;\n }\n\n /**\n * Safely extracts ZodObject from a schema, returns null if not an object schema\n */\n private extractZodObject(\n schema: z.ZodSchema\n ): z.ZodObject<z.ZodRawShape> | null {\n try {\n const def = (schema as z.ZodType)._def as { typeName?: string };\n if (def && def.typeName === 'ZodObject') {\n return schema as z.ZodObject<z.ZodRawShape>;\n }\n } catch (error) {\n this.logger.debug('Could not extract ZodObject from schema:', error);\n }\n return null;\n }\n\n /**\n * Extracts field names from Zod schema structure\n */\n private extractFieldsFromSchema(schema: z.ZodSchema): string[] {\n const fields: string[] = [];\n\n const zodObject = this.extractZodObject(schema);\n if (zodObject) {\n fields.push(...Object.keys(zodObject.shape));\n return fields;\n }\n\n try {\n const def = (schema as z.ZodType)._def as {\n typeName?: string;\n options?: z.ZodType[];\n };\n if (def && def.typeName === 'ZodUnion' && def.options) {\n const firstOption = def.options[0];\n const firstOptionObject = this.extractZodObject(firstOption);\n if (firstOptionObject) {\n fields.push(...Object.keys(firstOptionObject.shape));\n }\n }\n } catch (error) {\n this.logger.debug(\n 'Could not extract fields from schema structure:',\n error\n );\n }\n\n return fields;\n }\n\n /**\n * Infers field type from Zod schema\n */\n private inferTypeFromSchema(\n schema: z.ZodSchema,\n fieldPath: string\n ): FormFieldType | null {\n try {\n const zodObject = this.extractZodObject(schema);\n if (!zodObject) return null;\n\n const shape = zodObject.shape;\n if (!shape) return null;\n\n let fieldSchema = shape[fieldPath] as z.ZodType | undefined;\n if (!fieldSchema) return null;\n\n const fieldDef = fieldSchema._def as {\n typeName?: string;\n innerType?: z.ZodType;\n };\n if (\n fieldDef &&\n fieldDef.typeName === 'ZodOptional' &&\n fieldDef.innerType\n ) {\n fieldSchema = fieldDef.innerType;\n }\n\n if (!fieldSchema || !fieldSchema._def) return null;\n\n const typeDef = fieldSchema._def as { typeName?: string };\n const fieldTypeName = typeDef.typeName;\n const lowerPath = fieldPath.toLowerCase();\n\n switch (fieldTypeName) {\n case 'ZodString':\n if (lowerPath.includes('memo') || lowerPath.includes('description')) {\n return 'textarea';\n }\n return 'text';\n case 'ZodNumber':\n if (lowerPath.includes('percent')) {\n return 'percentage';\n }\n if (lowerPath.includes('price') || lowerPath.includes('cost')) {\n return 'currency';\n }\n return 'number';\n case 'ZodBoolean':\n return 'checkbox';\n case 'ZodEnum':\n case 'ZodNativeEnum':\n return 'select';\n case 'ZodArray':\n return 'array';\n case 'ZodObject':\n return 'object';\n default:\n return 'text';\n }\n } catch (error) {\n this.logger.debug('Could not infer type from schema:', error);\n }\n return null;\n }\n\n /**\n * Determines if a field is required based on the Zod schema\n */\n private isFieldRequired(schema?: z.ZodSchema, fieldPath?: string): boolean {\n if (!schema || !fieldPath) {\n return false;\n }\n\n try {\n const zodObject = this.extractZodObject(schema);\n if (!zodObject) return false;\n\n const shape = zodObject.shape;\n if (!shape || !shape[fieldPath]) return false;\n\n const fieldSchema = shape[fieldPath] as z.ZodType;\n if (!fieldSchema || !fieldSchema._def) return true;\n\n const fieldDef = fieldSchema._def as {\n typeName?: string;\n defaultValue?: unknown;\n };\n const typeName = fieldDef.typeName;\n\n if (typeName === 'ZodOptional') {\n return false;\n }\n\n if (typeName === 'ZodDefault') {\n return false;\n }\n\n if (fieldDef.defaultValue !== undefined) {\n return false;\n }\n\n return true;\n } catch (error) {\n this.logger.debug(\n `Could not determine if field ${fieldPath} is required:`,\n error\n );\n }\n\n return false;\n }\n\n /**\n * Generates a description for the form\n */\n private generateFormDescription(\n toolName: string,\n fieldCount: number\n ): string {\n if (fieldCount === 0) {\n return 'Please provide the required information to continue with your request.';\n }\n\n return `Please provide the following ${fieldCount} required field${\n fieldCount !== 1 ? 's' : ''\n } to continue with your request.`;\n }\n\n /**\n * Generates JSON Schema and uiSchema from a Zod schema for use with @rjsf/core\n * @param zodSchema The Zod schema to convert\n * @param partialInput Existing input data to filter out fields that already have values\n * @param missingFields Set of fields that are missing and should be shown\n * @returns Object containing jsonSchema and uiSchema\n */\n public generateJsonSchemaForm(\n zodSchema: z.ZodObject<z.ZodRawShape>,\n partialInput?: Record<string, unknown>,\n missingFields?: Set<string>\n ): {\n jsonSchema: Record<string, unknown>;\n uiSchema: Record<string, unknown>;\n } {\n const fullJsonSchema = zodToJsonSchema(zodSchema, {\n target: 'jsonSchema7',\n });\n\n const uiSchema: Record<string, Record<string, unknown>> = {};\n\n let jsonSchema = fullJsonSchema;\n if (missingFields && missingFields.size > 0) {\n const fullSchemaAsObject = fullJsonSchema as {\n properties?: Record<string, unknown>;\n required?: string[];\n [key: string]: unknown;\n };\n if (\n fullSchemaAsObject.properties &&\n typeof fullSchemaAsObject.properties === 'object'\n ) {\n const filteredSchema = {\n ...fullSchemaAsObject,\n type: 'object' as const,\n properties: {} as Record<string, unknown>,\n required: [] as string[],\n };\n\n let fieldsAdded = 0;\n missingFields.forEach((fieldName) => {\n if (\n fullSchemaAsObject.properties &&\n fullSchemaAsObject.properties[fieldName]\n ) {\n filteredSchema.properties[fieldName] =\n fullSchemaAsObject.properties[fieldName];\n fieldsAdded++;\n }\n });\n\n if (Array.isArray(fullSchemaAsObject.required)) {\n filteredSchema.required = fullSchemaAsObject.required.filter(\n (field: string) => missingFields.has(field)\n );\n }\n\n if (fieldsAdded > 0) {\n jsonSchema = filteredSchema;\n }\n }\n }\n\n const fieldNames = this.extractFieldsFromSchema(zodSchema);\n\n fieldNames.forEach((fieldName) => {\n const isRequired = this.isFieldRequired(zodSchema, fieldName);\n const priority = this.getFieldPriority(fieldName, undefined, isRequired);\n const lower = fieldName.toLowerCase();\n\n if (\n lower === 'attributes' ||\n lower === 'metadata' ||\n lower === 'properties'\n ) {\n uiSchema[fieldName] = {\n 'ui:options': {\n collapsible: true,\n collapsed: true,\n },\n };\n }\n\n switch (priority) {\n case 'essential':\n if (isRequired) {\n uiSchema[fieldName] = {\n ...uiSchema[fieldName],\n 'ui:help': 'Required field',\n };\n }\n break;\n case 'advanced':\n case 'expert':\n uiSchema[fieldName] = {\n ...uiSchema[fieldName],\n 'ui:options': {\n ...(uiSchema[fieldName]?.['ui:options'] as\n | Record<string, unknown>\n | undefined),\n collapsed: true,\n },\n };\n break;\n }\n });\n\n return { jsonSchema, uiSchema };\n }\n}\n","import { StructuredTool } from '@langchain/core/tools';\nimport { ZodError, z } from 'zod';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport { FormGenerator } from './form-generator';\nimport { isFormValidatable } from '@hashgraphonline/standards-agent-kit';\nimport type { FormMessage, FormSubmission } from './types';\n\n/**\n * Tool execution result with optional form requirement\n */\nexport interface ToolExecutionResult {\n success: boolean;\n output: string;\n metadata?: Record<string, unknown>;\n requiresForm?: boolean;\n formMessage?: FormMessage;\n error?: string;\n}\n\n/**\n * Context for form generation operations\n */\nexport interface FormGenerationContext {\n tool: StructuredTool;\n input: unknown;\n sessionId?: string;\n userId?: string;\n missingFields?: Set<string>;\n}\n\n/**\n * FormEngine handles all form generation and validation logic\n */\nexport class FormEngine {\n private formGenerator: FormGenerator;\n private logger: Logger;\n\n constructor(logger?: Logger) {\n this.formGenerator = new FormGenerator();\n this.logger = logger || new Logger({ module: 'FormEngine' });\n }\n\n /**\n * Generate a form for a tool with the given input\n */\n async generateForm(\n toolName: string,\n tool: StructuredTool,\n input: unknown,\n context?: Partial<FormGenerationContext>\n ): Promise<FormMessage | null> {\n const fullContext: FormGenerationContext = {\n tool,\n input,\n ...context,\n };\n\n try {\n if (isFormValidatable(tool)) {\n return await this.generateFormValidatableForm(tool, input, fullContext);\n }\n\n if (input instanceof ZodError) {\n return await this.generateErrorBasedForm(tool, input, fullContext);\n }\n\n if (this.hasRenderConfig(tool)) {\n return await this.generateRenderConfigForm(tool, input, fullContext);\n }\n\n if (this.isZodObject(tool.schema)) {\n return await this.generateSchemaBasedForm(tool, input, fullContext);\n }\n\n return null;\n } catch (error) {\n this.logger.error(`Failed to generate form for tool: ${toolName}`, {\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n /**\n * Process a form submission\n */\n async processSubmission(\n submission: FormSubmission,\n context?: {\n originalInput?: Record<string, unknown>;\n schema?: unknown;\n }\n ): Promise<Record<string, unknown>> {\n this.validateSubmission(submission);\n\n const baseToolInput = this.extractBaseToolInput(context);\n const submissionData = this.extractSubmissionData(submission);\n\n return this.mergeInputData(baseToolInput, submissionData);\n }\n\n /**\n * Check if a tool requires form generation based on input\n */\n shouldGenerateForm(tool: StructuredTool, input: unknown): boolean {\n const inputRecord = input as Record<string, unknown>;\n if (inputRecord?.__fromForm === true || inputRecord?.renderForm === false) {\n return false;\n }\n\n if (isFormValidatable(tool)) {\n try {\n const formValidatableTool = tool as {\n shouldGenerateForm: (input: unknown) => boolean;\n };\n return formValidatableTool.shouldGenerateForm(input);\n } catch (error) {\n this.logger.error(\n `Error calling shouldGenerateForm() on ${tool.name}:`,\n error\n );\n return false;\n }\n }\n\n const validation = this.validateInput(tool, input);\n return !validation.isValid;\n }\n\n /**\n * Generate form from error context\n */\n async generateFormFromError(\n error: ZodError,\n toolName: string,\n toolSchema: z.ZodSchema,\n originalPrompt: string\n ): Promise<FormMessage> {\n return this.formGenerator.generateFormFromError(\n error,\n toolSchema as z.ZodType<unknown, z.ZodTypeDef, unknown>,\n toolName,\n originalPrompt\n );\n }\n\n /**\n * Generate form for FormValidatable tools\n */\n private async generateFormValidatableForm(\n tool: StructuredTool,\n input: unknown,\n _context: FormGenerationContext\n ): Promise<FormMessage> {\n const { schemaToUse, isFocusedSchema } = this.resolveFormSchema(tool);\n const missingFields = this.determineMissingFields(\n tool,\n input,\n schemaToUse,\n isFocusedSchema\n );\n\n return this.generateFormWithSchema(tool, input, schemaToUse, missingFields);\n }\n\n /**\n * Generate form based on schema validation\n */\n private async generateSchemaBasedForm(\n tool: StructuredTool,\n input: unknown,\n context: FormGenerationContext\n ): Promise<FormMessage> {\n const schema = tool.schema;\n\n const formMessage = await this.formGenerator.generateFormFromSchema(\n schema as z.ZodType<unknown, z.ZodTypeDef, unknown>,\n input,\n {\n toolName: tool.name,\n toolDescription: tool.description,\n },\n context.missingFields\n );\n\n if (this.isZodObject(schema)) {\n try {\n const { jsonSchema, uiSchema } =\n this.formGenerator.generateJsonSchemaForm(\n schema,\n input as Record<string, unknown> | undefined,\n context.missingFields || new Set()\n );\n formMessage.jsonSchema = jsonSchema;\n formMessage.uiSchema = uiSchema;\n } catch (error) {\n this.logger.warn(\n 'Failed to generate JSON Schema for schema-based tool:',\n error\n );\n }\n }\n\n formMessage.partialInput = input;\n return formMessage;\n }\n\n /**\n * Generate form based on render config\n */\n private async generateRenderConfigForm(\n tool: StructuredTool,\n input: unknown,\n context: FormGenerationContext\n ): Promise<FormMessage> {\n const schema = tool.schema;\n const renderConfig = this.extractRenderConfig(tool);\n\n const formMessage = await this.formGenerator.generateFormFromSchema(\n schema as z.ZodType<unknown, z.ZodTypeDef, unknown>,\n input,\n {\n toolName: tool.name,\n toolDescription: tool.description,\n },\n context.missingFields\n );\n\n if (renderConfig) {\n formMessage.formConfig.metadata = {\n ...formMessage.formConfig.metadata,\n renderConfig,\n };\n }\n\n formMessage.partialInput = input;\n return formMessage;\n }\n\n /**\n * Generate form from Zod validation error\n */\n private async generateErrorBasedForm(\n tool: StructuredTool,\n error: ZodError,\n context: FormGenerationContext\n ): Promise<FormMessage> {\n return this.formGenerator.generateFormFromError(\n error,\n tool.schema as z.ZodType<unknown, z.ZodTypeDef, unknown>,\n tool.name,\n context.input ? String(context.input) : ''\n );\n }\n\n /**\n * Validate input against tool schema\n */\n private validateInput(\n tool: StructuredTool,\n input: unknown\n ): { isValid: boolean; errors?: string[] } {\n try {\n const zodSchema = tool.schema as z.ZodType<\n unknown,\n z.ZodTypeDef,\n unknown\n >;\n zodSchema.parse(input);\n return { isValid: true };\n } catch (error) {\n if (error instanceof ZodError) {\n const errors = error.errors.map(\n (err) => `${err.path.join('.')}: ${err.message}`\n );\n return { isValid: false, errors };\n }\n return { isValid: false, errors: ['Validation failed'] };\n }\n }\n\n /**\n * Check if schema is ZodObject\n */\n private isZodObject(schema: unknown): schema is z.ZodObject<z.ZodRawShape> {\n if (!schema || typeof schema !== 'object') {\n return false;\n }\n const candidate = schema as { _def?: { typeName?: string } };\n return Boolean(candidate._def && candidate._def.typeName === 'ZodObject');\n }\n\n /**\n * Check if tool has render configuration\n */\n private hasRenderConfig(tool: StructuredTool): boolean {\n const schema = tool.schema as Record<string, unknown>;\n return !!(schema && schema._renderConfig);\n }\n\n /**\n * Extract render configuration from tool\n */\n private extractRenderConfig(\n tool: StructuredTool\n ): Record<string, unknown> | undefined {\n const schema = tool.schema as Record<string, unknown>;\n return schema?._renderConfig as Record<string, unknown> | undefined;\n }\n\n /**\n * Resolve form schema for FormValidatable tools\n */\n private resolveFormSchema(tool: StructuredTool): {\n schemaToUse: z.ZodSchema;\n isFocusedSchema: boolean;\n } {\n const formValidatableTool = tool as {\n getFormSchema?: () => z.ZodSchema | null;\n };\n\n if (formValidatableTool.getFormSchema) {\n const focusedSchema = formValidatableTool.getFormSchema();\n if (focusedSchema) {\n return { schemaToUse: focusedSchema, isFocusedSchema: true };\n }\n }\n\n return { schemaToUse: tool.schema as z.ZodSchema, isFocusedSchema: false };\n }\n\n /**\n * Determine missing fields for form generation\n */\n private determineMissingFields(\n tool: StructuredTool,\n input: unknown,\n _schema: z.ZodSchema,\n _isFocusedSchema: boolean\n ): Set<string> {\n const missingFields = new Set<string>();\n\n if (!input || typeof input !== 'object') {\n return missingFields;\n }\n\n const inputRecord = input as Record<string, unknown>;\n const formValidatableTool = tool as {\n isFieldEmpty?: (fieldName: string, value: unknown) => boolean;\n getEssentialFields?: () => string[];\n };\n\n if (formValidatableTool.getEssentialFields) {\n const essentialFields = formValidatableTool.getEssentialFields();\n for (const field of essentialFields) {\n if (\n !(field in inputRecord) ||\n (formValidatableTool.isFieldEmpty &&\n formValidatableTool.isFieldEmpty(field, inputRecord[field]))\n ) {\n missingFields.add(field);\n }\n }\n }\n\n return missingFields;\n }\n\n /**\n * Generate form with resolved schema\n */\n private async generateFormWithSchema(\n tool: StructuredTool,\n input: unknown,\n schema: z.ZodSchema,\n missingFields: Set<string>\n ): Promise<FormMessage> {\n const formMessage = await this.formGenerator.generateFormFromSchema(\n schema as z.ZodType<unknown, z.ZodTypeDef, unknown>,\n input,\n {\n toolName: tool.name,\n toolDescription: tool.description,\n },\n missingFields\n );\n\n if (this.isZodObject(schema)) {\n try {\n const { jsonSchema, uiSchema } =\n this.formGenerator.generateJsonSchemaForm(\n schema,\n input as Record<string, unknown> | undefined,\n missingFields\n );\n formMessage.jsonSchema = jsonSchema;\n formMessage.uiSchema = uiSchema;\n } catch (error) {\n this.logger.warn('Failed to generate JSON Schema:', error);\n }\n }\n\n formMessage.partialInput = input;\n return formMessage;\n }\n\n /**\n * Validate form submission\n */\n private validateSubmission(submission: FormSubmission): void {\n if (!submission.toolName) {\n throw new Error('Tool name is required in form submission');\n }\n if (!submission.parameters) {\n throw new Error('Parameters are required in form submission');\n }\n }\n\n /**\n * Extract base tool input from context\n */\n private extractBaseToolInput(context?: {\n originalInput?: Record<string, unknown>;\n }): Record<string, unknown> {\n return context?.originalInput || {};\n }\n\n /**\n * Extract submission data\n */\n private extractSubmissionData(\n submission: FormSubmission\n ): Record<string, unknown> {\n return {\n ...submission.parameters,\n __fromForm: true,\n };\n }\n\n /**\n * Merge input data\n */\n private mergeInputData(\n baseInput: Record<string, unknown>,\n submissionData: Record<string, unknown>\n ): Record<string, unknown> {\n return {\n ...baseInput,\n ...submissionData,\n };\n }\n\n /**\n * Get registered strategies\n */\n getRegisteredStrategies(): string[] {\n return ['FormValidatable', 'SchemaBased', 'RenderConfig', 'ZodErrorBased'];\n }\n\n /**\n * Get registered middleware\n */\n getRegisteredMiddleware(): string[] {\n return ['FormSubmissionValidator'];\n }\n}\n","/**\n * HCS-12 HashLink block structure for interactive content rendering\n */\ninterface HCS12BlockResult {\n blockId: string;\n hashLink: string;\n template: string;\n attributes: Record<string, unknown>;\n}\n\n/**\n * Utility class for formatting tool responses into user-friendly messages\n */\nexport class ResponseFormatter {\n /**\n * Checks if a parsed response contains HashLink block data for interactive rendering\n */\n static isHashLinkResponse(parsed: unknown): boolean {\n if (!parsed || typeof parsed !== 'object') {\n return false;\n }\n\n const responseObj = parsed as Record<string, unknown>;\n return !!(\n responseObj.success === true &&\n responseObj.type === 'inscription' &&\n responseObj.hashLinkBlock &&\n typeof responseObj.hashLinkBlock === 'object'\n );\n }\n\n /**\n * Formats HashLink block response with simple text confirmation\n * HTML template rendering is handled by HashLinkBlockRenderer component via metadata\n */\n static formatHashLinkResponse(parsed: Record<string, unknown>): string {\n const hashLinkBlock = parsed.hashLinkBlock as HCS12BlockResult;\n const metadata = parsed.metadata as Record<string, unknown> || {};\n const inscription = parsed.inscription as Record<string, unknown> || {};\n\n let message = '✅ Interactive content created successfully!\\n\\n';\n\n if (metadata.name) {\n message += `**${metadata.name}**\\n`;\n }\n\n if (metadata.description) {\n message += `${metadata.description}\\n\\n`;\n }\n\n if (inscription.topicId || hashLinkBlock.attributes.topicId) {\n message += `📍 **Topic ID:** ${inscription.topicId || hashLinkBlock.attributes.topicId}\\n`;\n }\n\n if (inscription.hrl || hashLinkBlock.attributes.hrl) {\n message += `🔗 **HRL:** ${inscription.hrl || hashLinkBlock.attributes.hrl}\\n`;\n }\n\n if (inscription.cdnUrl) {\n message += `🌐 **CDN URL:** ${inscription.cdnUrl}\\n`;\n }\n\n if (metadata.creator) {\n message += `👤 **Creator:** ${metadata.creator}\\n`;\n }\n\n message += '\\n⚡ Interactive content will load below';\n\n return message.trim();\n }\n\n /**\n * Checks if a parsed response is an inscription response that needs formatting\n */\n static isInscriptionResponse(parsed: unknown): boolean {\n if (!parsed || typeof parsed !== 'object') {\n return false;\n }\n\n const responseObj = parsed as Record<string, unknown>;\n return !!(\n responseObj.success === true &&\n responseObj.type === 'inscription' &&\n responseObj.inscription &&\n typeof responseObj.inscription === 'object'\n );\n }\n\n /**\n * Formats inscription response into user-friendly message\n */\n static formatInscriptionResponse(parsed: Record<string, unknown>): string {\n const inscription = parsed.inscription as Record<string, unknown>;\n const metadata = parsed.metadata as Record<string, unknown> || {};\n const title = parsed.title as string || 'Inscription Complete';\n\n let message = `✅ ${title}\\n\\n`;\n\n if (metadata.name) {\n message += `**${metadata.name}**\\n`;\n }\n\n if (metadata.description) {\n message += `${metadata.description}\\n\\n`;\n }\n\n if (inscription.topicId) {\n message += `📍 **Topic ID:** ${inscription.topicId}\\n`;\n }\n\n if (inscription.hrl) {\n message += `🔗 **HRL:** ${inscription.hrl}\\n`;\n }\n\n if (inscription.cdnUrl) {\n message += `🌐 **CDN URL:** ${inscription.cdnUrl}\\n`;\n }\n\n if (metadata.creator) {\n message += `👤 **Creator:** ${metadata.creator}\\n`;\n }\n\n return message.trim();\n }\n\n /**\n * Main formatting method that determines the best response format\n */\n static formatResponse(toolOutput: string): string {\n try {\n const parsed = JSON.parse(toolOutput);\n \n if (ResponseFormatter.isHashLinkResponse(parsed)) {\n return ResponseFormatter.formatHashLinkResponse(parsed);\n }\n \n if (ResponseFormatter.isInscriptionResponse(parsed)) {\n return ResponseFormatter.formatInscriptionResponse(parsed);\n }\n \n return toolOutput;\n } catch {\n return toolOutput;\n }\n }\n}","import { AgentExecutor } from 'langchain/agents';\nimport { ZodError, z } from 'zod';\nimport { FormGenerator } from '../forms/form-generator';\nimport type { FormMessage, FormSubmission } from '../forms/types';\nimport { FormEngine } from '../forms/form-engine';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport type { AgentAction, AgentFinish, AgentStep } from 'langchain/agents';\nimport type { ToolInterface } from '@langchain/core/tools';\nimport { isFormValidatable } from '@hashgraphonline/standards-agent-kit';\nimport type { ChainValues } from '@langchain/core/utils/types';\nimport type { CallbackManagerForChainRun } from '@langchain/core/callbacks/manager';\nimport type { RunnableConfig } from '@langchain/core/runnables';\nimport { ResponseFormatter } from '../utils/response-formatter';\n\ntype BasicFieldType = 'text' | 'number' | 'select' | 'checkbox' | 'textarea';\n\nconst globalPendingForms: Map<string, PendingFormData> = new Map();\n\ninterface HashLinkBlock {\n blockId: string;\n hashLink: string;\n template: string;\n attributes: Record<string, unknown>;\n}\n\ninterface HashLinkResponse {\n hasHashLinkBlocks: boolean;\n hashLinkBlock?: HashLinkBlock;\n message: string;\n}\n\ninterface ToolWithOriginal {\n originalTool?: {\n call?: (args: Record<string, unknown>) => Promise<string>;\n };\n}\n\ninterface ActionWithToolInput {\n toolInput?: Record<string, unknown>;\n}\n\ninterface ZodSchemaDefinition {\n _def?: {\n typeName?: string;\n shape?: (() => Record<string, z.ZodTypeAny>) | Record<string, z.ZodTypeAny>;\n innerType?: z.ZodTypeAny;\n defaultValue?: unknown;\n };\n}\n\ninterface ToolWrapper {\n executeOriginal?: (args: Record<string, unknown>) => Promise<string>;\n getOriginalTool?: () => {\n _call?: (args: Record<string, unknown>) => Promise<string>;\n call?: (args: Record<string, unknown>) => Promise<string>;\n };\n originalTool?: {\n _call?: (args: Record<string, unknown>) => Promise<string>;\n call?: (args: Record<string, unknown>) => Promise<string>;\n };\n call?: (args: Record<string, unknown>) => Promise<string>;\n}\n\ninterface CallableTool {\n _call?: (args: Record<string, unknown>) => Promise<string>;\n call?: (args: Record<string, unknown>) => Promise<string>;\n}\n\ninterface ToolWithSchema {\n schema?: Record<string, unknown>;\n}\n\ninterface PendingFormData {\n toolName: string;\n originalInput: unknown;\n originalToolInput?: unknown;\n schema: unknown;\n toolRef?: ToolInterface | undefined;\n originalToolRef?: ToolWithOriginal['originalTool'];\n}\n\ninterface ToolResponse {\n requiresForm?: boolean;\n formMessage?: {\n id: string;\n [key: string]: unknown;\n };\n message?: string;\n hashLinkBlock?: HashLinkBlock;\n success?: boolean;\n inscription?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n}\n\ninterface IntermediateStepData {\n action?: {\n tool?: string;\n [key: string]: unknown;\n };\n observation?: unknown;\n}\n\ninterface HashLinkBlock {\n blockId: string;\n hashLink: string;\n template: string;\n attributes: Record<string, unknown>;\n}\n\ninterface ResponseMetadataWithHashLink {\n hashLinkBlock?: HashLinkBlock;\n [key: string]: unknown;\n}\n\n/**\n * Parameter preprocessing callback interface\n */\nexport interface ParameterPreprocessingCallback {\n (toolName: string, parameters: Record<string, unknown>): Promise<\n Record<string, unknown>\n >;\n}\n\n/**\n * Agent executor that intercepts Zod validation errors and generates forms,\n * and processes HashLink block responses for rich UI rendering\n */\nexport class FormAwareAgentExecutor extends AgentExecutor {\n private formGenerator: FormGenerator;\n private formEngine: FormEngine;\n private formLogger: Logger;\n private pendingForms: Map<string, PendingFormData> = new Map();\n private parameterPreprocessingCallback:\n | ParameterPreprocessingCallback\n | undefined;\n\n /**\n * Type guard to check if a Zod type is a ZodObject\n */\n private isZodObject(schema: unknown): schema is z.ZodObject<z.ZodRawShape> {\n return schema instanceof z.ZodObject;\n }\n\n /**\n * Type guard to check if metadata has hashLinkBlock\n */\n private hasHashLinkBlock(\n metadata: unknown\n ): metadata is ResponseMetadataWithHashLink & {\n hashLinkBlock: HashLinkBlock;\n } {\n return (\n typeof metadata === 'object' &&\n metadata !== null &&\n 'hashLinkBlock' in metadata &&\n typeof (metadata as Record<string, unknown>).hashLinkBlock === 'object' &&\n (metadata as Record<string, unknown>).hashLinkBlock !== null\n );\n }\n\n constructor(...args: ConstructorParameters<typeof AgentExecutor>) {\n super(...args);\n this.formGenerator = new FormGenerator();\n this.formEngine = new FormEngine(\n new Logger({ module: 'FormAwareAgentExecutor.FormEngine' })\n );\n this.formLogger = new Logger({ module: 'FormAwareAgentExecutor' });\n this.parameterPreprocessingCallback = undefined;\n }\n\n /**\n * Set parameter preprocessing callback\n */\n setParameterPreprocessingCallback(\n callback: ParameterPreprocessingCallback | undefined\n ): void {\n this.parameterPreprocessingCallback = callback;\n }\n\n /**\n * BULLETPROOF TOOL INTERCEPTION\n * Override the single-step execution to intercept tool calls BEFORE LangChain processes them\n */\n override async _takeNextStep(\n nameToolMap: Record<string, ToolInterface>,\n inputs: ChainValues,\n intermediateSteps: AgentStep[],\n runManager?: CallbackManagerForChainRun,\n config?: RunnableConfig\n ): Promise<AgentFinish | AgentStep[]> {\n this.formLogger.info('🛡️ BULLETPROOF INTERCEPTION: _takeNextStep called', {\n availableTools: Object.keys(nameToolMap),\n inputKeys: Object.keys(inputs),\n });\n\n const result = await this.agent.plan(\n intermediateSteps,\n inputs,\n runManager?.getChild()\n );\n\n if ('returnValues' in result) {\n this.formLogger.info('Agent returned finish action, passing through');\n return result;\n }\n\n const action = result as AgentAction;\n const toolName = action.tool;\n const toolInput = action.toolInput;\n\n this.formLogger.info(`🎯 INTERCEPTING TOOL CALL: ${toolName}`, {\n toolInput,\n hasInNameToolMap: toolName in nameToolMap,\n toolInputKeys: Object.keys(toolInput || {}),\n });\n\n const tool =\n nameToolMap[toolName] || this.tools.find((t) => t.name === toolName);\n\n if (!tool) {\n this.formLogger.error(`Tool ${toolName} not found in registry`);\n throw new Error(`Tool \"${toolName}\" not found`);\n }\n\n let shouldGenerateForm = false;\n\n if (isFormValidatable(tool)) {\n this.formLogger.info(\n `🔍 Tool ${toolName} implements FormValidatable, checking shouldGenerateForm()`,\n {\n toolInput,\n }\n );\n\n try {\n shouldGenerateForm = tool.shouldGenerateForm(toolInput);\n this.formLogger.info(\n `FormValidatable.shouldGenerateForm() result: ${shouldGenerateForm}`,\n {\n toolName,\n toolInput,\n }\n );\n } catch (error) {\n this.formLogger.error(\n `Error calling shouldGenerateForm() on ${toolName}:`,\n error\n );\n shouldGenerateForm = false;\n }\n }\n\n if (shouldGenerateForm) {\n this.formLogger.info(`🚨 FORM GENERATION TRIGGERED for ${toolName}`);\n\n try {\n let schemaToUse: z.ZodSchema;\n let isFocusedSchema = false;\n\n if (isFormValidatable(tool)) {\n this.formLogger.info(\n `🎯 Tool ${toolName} is FormValidatable, attempting to get focused schema`\n );\n try {\n const focusedSchema = tool.getFormSchema();\n if (focusedSchema) {\n schemaToUse = focusedSchema;\n isFocusedSchema = true;\n this.formLogger.info(\n `✅ Successfully obtained focused schema for ${toolName}`\n );\n } else {\n this.formLogger.warn(\n `getFormSchema() returned null/undefined for ${toolName}, using default schema`\n );\n schemaToUse = tool.schema;\n isFocusedSchema = false;\n }\n } catch (error) {\n this.formLogger.error(\n `Failed to get focused schema from ${toolName}:`,\n error\n );\n this.formLogger.info(\n `Falling back to default schema for ${toolName}`\n );\n schemaToUse = tool.schema;\n isFocusedSchema = false;\n }\n } else {\n this.formLogger.info(\n `Tool ${toolName} is not FormValidatable, using default schema`\n );\n schemaToUse = tool.schema;\n isFocusedSchema = false;\n }\n\n let schemaFieldCount = 'unknown';\n try {\n if (this.isZodObject(schemaToUse)) {\n const zodObject = schemaToUse as z.ZodObject<z.ZodRawShape>;\n const shape = zodObject.shape;\n if (shape && typeof shape === 'object') {\n schemaFieldCount = Object.keys(shape).length.toString();\n }\n }\n } catch {}\n\n this.formLogger.info(\n `📋 Generating form with ${\n isFocusedSchema ? 'FOCUSED' : 'DEFAULT'\n } schema`,\n {\n toolName,\n schemaType: schemaToUse?.constructor?.name,\n estimatedFieldCount: schemaFieldCount,\n isFocusedSchema,\n }\n );\n\n let missingFields: Set<string> | undefined;\n\n if (isFocusedSchema) {\n this.formLogger.info(\n `⭐ Using focused schema - letting FormGenerator determine fields from schema`\n );\n missingFields = undefined;\n } else {\n missingFields = new Set<string>();\n if (this.isZodObject(schemaToUse)) {\n const zodObject = schemaToUse as z.ZodObject<z.ZodRawShape>;\n const shape = zodObject.shape || {};\n for (const fieldName of Object.keys(shape)) {\n const value = (toolInput || {})[fieldName];\n\n const isEmpty =\n isFormValidatable(tool) && tool.isFieldEmpty\n ? tool.isFieldEmpty(fieldName, value)\n : value === undefined ||\n value === '' ||\n value === null ||\n (Array.isArray(value) && value.length === 0);\n\n const isRequired = this.isFieldRequired(schemaToUse, fieldName);\n\n const isEssential =\n isFormValidatable(tool) && tool.getEssentialFields\n ? tool.getEssentialFields().includes(fieldName)\n : false;\n\n this.formLogger.info(`🔍 Field analysis: ${fieldName}`, {\n value: value,\n isEmpty: isEmpty,\n isRequired: isRequired,\n isEssential: isEssential,\n willAddToMissingFields: isEmpty && (isRequired || isEssential),\n });\n\n if (isEmpty && (isRequired || isEssential)) {\n missingFields.add(fieldName);\n }\n }\n }\n\n this.formLogger.info(`📋 Missing fields analysis complete`, {\n totalFields: this.isZodObject(schemaToUse)\n ? Object.keys(schemaToUse.shape).length\n : 0,\n missingFieldsCount: missingFields.size,\n missingFields: Array.from(missingFields),\n });\n }\n\n const formMessage = await this.formGenerator.generateFormFromSchema(\n schemaToUse,\n toolInput,\n {\n toolName: toolName,\n toolDescription: tool.description,\n },\n missingFields\n );\n\n if (this.isZodObject(schemaToUse)) {\n try {\n const { jsonSchema, uiSchema } =\n this.formGenerator.generateJsonSchemaForm(\n schemaToUse,\n toolInput as Record<string, unknown> | undefined,\n missingFields\n );\n formMessage.jsonSchema = jsonSchema;\n formMessage.uiSchema = uiSchema;\n } catch (error) {\n this.formLogger.warn(\n 'Failed to generate JSON Schema for RJSF:',\n error\n );\n }\n }\n\n formMessage.partialInput = toolInput;\n\n const formData: PendingFormData = {\n toolName: toolName,\n originalInput: inputs,\n originalToolInput: toolInput,\n schema: schemaToUse,\n toolRef: tool as ToolInterface | undefined,\n originalToolRef: (tool as ToolWithOriginal).originalTool,\n };\n this.pendingForms.set(formMessage.id, formData);\n globalPendingForms.set(formMessage.id, formData);\n\n this.formLogger.info(`✅ FORM INTERCEPT SUCCESS for ${toolName}`);\n\n const formResult = {\n requiresForm: true,\n formMessage,\n };\n\n return [\n {\n action: action,\n observation: JSON.stringify(formResult),\n },\n ];\n } catch (error) {\n this.formLogger.error(`Form generation failed for ${toolName}:`, error);\n }\n }\n\n this.formLogger.info(\n `⚪ Passing through to normal tool execution for ${toolName}`\n );\n\n if (this.parameterPreprocessingCallback && toolInput) {\n this.formLogger.info(\n `🔄 Applying parameter preprocessing for ${toolName}`\n );\n try {\n const preprocessedInput = await this.parameterPreprocessingCallback(\n toolName,\n toolInput as Record<string, unknown>\n );\n\n if (\n preprocessedInput &&\n typeof preprocessedInput === 'object' &&\n '__requestForm' in (preprocessedInput as Record<string, unknown>)\n ) {\n const rf = (preprocessedInput as Record<string, unknown>)\n .__requestForm as {\n id?: string;\n title?: string;\n description?: string;\n fields?: Array<{\n name: string;\n label: string;\n type: string;\n required?: boolean;\n options?: Array<{ value: string; label: string }>;\n }>;\n submitLabel?: string;\n };\n\n const formId =\n rf.id ||\n `form_${Date.now()}_${Math.random().toString(36).slice(2)}`;\n const formMessage = {\n type: 'form',\n id: formId,\n originalPrompt: 'Parameter validation required',\n toolName,\n formConfig: {\n title: rf.title || 'Complete required parameters',\n description:\n rf.description ||\n 'One or more parameters require confirmation. Please review and submit.',\n submitLabel: rf.submitLabel || 'Continue',\n fields: (rf.fields || []).map((f) => {\n const allowedTypes: BasicFieldType[] = [\n 'text',\n 'number',\n 'select',\n 'checkbox',\n 'textarea',\n ];\n const resolvedType: BasicFieldType = allowedTypes.includes(\n f.type as BasicFieldType\n )\n ? (f.type as BasicFieldType)\n : 'text';\n\n return {\n name: f.name,\n label: f.label,\n type: resolvedType,\n required: f.required ?? true,\n options: f.options,\n };\n }),\n },\n };\n\n const resolvedSchema = isFormValidatable(tool)\n ? (() => {\n try {\n const s = tool.getFormSchema();\n return s || tool.schema;\n } catch {\n return tool.schema;\n }\n })()\n : tool.schema;\n\n this.pendingForms.set(formId, {\n toolName,\n originalInput: inputs,\n originalToolInput: toolInput,\n schema: resolvedSchema,\n toolRef: tool as ToolInterface | undefined,\n originalToolRef: (tool as ToolWithOriginal).originalTool,\n });\n globalPendingForms.set(formId, {\n toolName,\n originalInput: inputs,\n originalToolInput: toolInput,\n schema: resolvedSchema,\n });\n\n return [\n {\n action,\n observation: JSON.stringify({ requiresForm: true, formMessage }),\n },\n ];\n }\n\n if (JSON.stringify(preprocessedInput) !== JSON.stringify(toolInput)) {\n this.formLogger.info(`📝 Parameters preprocessed for ${toolName}:`, {\n original: Object.keys(toolInput as Record<string, unknown>),\n preprocessed: Object.keys(preprocessedInput),\n hasChanges: true,\n });\n\n try {\n (action as ActionWithToolInput).toolInput = preprocessedInput;\n } catch {}\n } else {\n this.formLogger.debug(`No parameter changes needed for ${toolName}`);\n }\n } catch (preprocessError) {\n this.formLogger.warn(\n `Parameter preprocessing failed for ${toolName}, using original parameters:`,\n preprocessError\n );\n }\n }\n\n return super._takeNextStep(\n nameToolMap,\n inputs,\n intermediateSteps,\n runManager,\n config\n );\n }\n\n /**\n * Helper to determine if a field is required in the schema\n */\n private isFieldRequired(schema: unknown, fieldPath: string): boolean {\n if (!schema || !fieldPath) {\n return false;\n }\n\n try {\n const obj = schema as ZodSchemaDefinition;\n const def = obj._def;\n if (!def || def.typeName !== 'ZodObject') {\n return false;\n }\n const rawShape: unknown =\n typeof def.shape === 'function' ? def.shape() : def.shape;\n if (!rawShape || typeof rawShape !== 'object') {\n return false;\n }\n const shape = rawShape as Record<string, z.ZodTypeAny>;\n const fieldSchema = shape[fieldPath];\n if (!fieldSchema) {\n return false;\n }\n const unwrapOptional = (s: z.ZodTypeAny): z.ZodTypeAny => {\n const inner = (s as ZodSchemaDefinition)._def;\n if (inner && inner.typeName === 'ZodOptional' && inner.innerType) {\n return inner.innerType;\n }\n return s;\n };\n const unwrapped = unwrapOptional(fieldSchema);\n const fdef = (unwrapped as ZodSchemaDefinition)._def;\n if (!fdef) {\n return true;\n }\n if (fdef.typeName === 'ZodOptional' || fdef.typeName === 'ZodDefault') {\n return false;\n }\n if (fdef.defaultValue !== undefined) {\n return false;\n }\n return true;\n } catch (error) {\n this.formLogger.debug(\n `Could not determine if field ${fieldPath} is required:`,\n error\n );\n }\n return false;\n }\n\n /**\n * Override _call to intercept Zod validation errors at the execution level\n */\n override async _call(\n inputs: Record<string, unknown>\n ): Promise<Record<string, unknown>> {\n try {\n const result = await super._call(inputs);\n\n if (result.intermediateSteps && Array.isArray(result.intermediateSteps)) {\n for (const step of result.intermediateSteps) {\n if (step.observation) {\n try {\n const parsed: ToolResponse =\n typeof step.observation === 'string'\n ? JSON.parse(step.observation)\n : (step.observation as ToolResponse);\n\n if (parsed.requiresForm && parsed.formMessage) {\n this.formLogger.info('Tool requested form generation', {\n toolName: step.action?.tool,\n hasForm: true,\n });\n\n const actionToolName =\n (step as IntermediateStepData).action?.tool || 'unknown';\n const toolInstance = this.tools.find(\n (t) => t.name === actionToolName\n ) as ToolInterface | undefined;\n const originalToolCandidate =\n (toolInstance as ToolWithOriginal) || {};\n const pf: PendingFormData = {\n toolName: actionToolName,\n originalInput: inputs,\n originalToolInput: (step as IntermediateStepData).action\n ?.toolInput as Record<string, unknown> | undefined,\n schema: null,\n toolRef: toolInstance,\n originalToolRef: originalToolCandidate?.originalTool,\n };\n this.pendingForms.set(parsed.formMessage.id, pf);\n globalPendingForms.set(parsed.formMessage.id, pf);\n\n return {\n ...result,\n requiresForm: true,\n formMessage: parsed.formMessage,\n output:\n parsed.message || 'Please complete the form to continue.',\n };\n }\n\n if (\n parsed.hashLinkBlock ||\n (parsed.success && parsed.inscription && parsed.hashLinkBlock)\n ) {\n this.formLogger.info('Tool returned HashLink blocks', {\n toolName: (step as IntermediateStepData).action?.tool,\n hasHashLink: true,\n blockId: parsed.hashLinkBlock?.blockId,\n });\n\n const hashLinkResponse = this.processHashLinkResponse(parsed);\n\n return {\n ...result,\n hasHashLinkBlocks: true,\n hashLinkBlock: hashLinkResponse.hashLinkBlock,\n output: hashLinkResponse.message,\n };\n }\n } catch {}\n }\n }\n }\n\n return result;\n } catch (error) {\n if (error instanceof ZodError) {\n this.formLogger.info('Intercepted ZodError during agent execution');\n return this.handleValidationError(error, inputs, []);\n }\n throw error;\n }\n }\n\n /**\n * Handles Zod validation errors by generating forms\n */\n private async handleValidationError(\n error: ZodError,\n inputs: Record<string, unknown>,\n intermediateSteps: AgentStep[]\n ): Promise<Record<string, unknown>> {\n this.formLogger.info('Zod validation error detected, generating form', {\n errorIssues: error.issues.length,\n inputKeys: Object.keys(inputs),\n });\n\n let toolInfo = this.extractToolInfoFromError(\n error,\n inputs,\n intermediateSteps\n );\n\n if (!toolInfo) {\n this.formLogger.warn(\n 'Could not extract tool info from validation error, trying fallback detection'\n );\n const fallbackTool = this.detectToolFromErrorContext(error);\n if (!fallbackTool) {\n this.formLogger.error(\n 'No tool detected for form generation, rethrowing error'\n );\n throw error;\n }\n toolInfo = fallbackTool;\n }\n\n this.formLogger.info('Generating form for tool:', {\n toolName: toolInfo.toolName,\n hasSchema: !!toolInfo.schema,\n });\n\n const formMessage = this.formGenerator.generateFormFromError(\n error,\n toolInfo.schema as z.ZodType<unknown, z.ZodTypeDef, unknown>,\n toolInfo.toolName,\n (inputs.input as string) || ''\n );\n\n this.pendingForms.set(formMessage.id, {\n toolName: toolInfo.toolName,\n originalInput: inputs,\n schema: toolInfo.schema,\n });\n\n globalPendingForms.set(formMessage.id, {\n toolName: toolInfo.toolName,\n originalInput: inputs,\n schema: toolInfo.schema,\n });\n\n return {\n output: this.formatFormResponse(formMessage),\n formMessage,\n requiresForm: true,\n intermediateSteps: intermediateSteps || [],\n };\n }\n\n /**\n * Get a copy of pending forms for preservation during executor recreation\n */\n getPendingForms(): Map<string, PendingFormData> {\n return new Map(this.pendingForms);\n }\n\n /**\n * Restore pending forms from a previous executor instance\n */\n restorePendingForms(forms: Map<string, PendingFormData>): void {\n for (const [formId, formData] of forms) {\n this.pendingForms.set(formId, formData);\n }\n }\n\n /**\n * Processes form submission and continues tool execution\n */\n async processFormSubmission(\n submission: FormSubmission\n ): Promise<Record<string, unknown>> {\n this.formLogger.info(\n '🚀 FormAwareAgentExecutor.processFormSubmission called!',\n {\n submissionFormId: submission.formId,\n submissionToolName: submission.toolName,\n }\n );\n if (!submission) {\n throw new Error('Form submission is null or undefined');\n }\n\n if (!submission.formId) {\n throw new Error('Form submission missing formId');\n }\n\n if (\n !submission.parameters ||\n submission.parameters === null ||\n typeof submission.parameters !== 'object' ||\n Array.isArray(submission.parameters)\n ) {\n throw new Error(\n `Form submission parameters are invalid: ${typeof submission.parameters}, isNull: ${\n submission.parameters === null\n }, isArray: ${Array.isArray(\n submission.parameters\n )}, parameters: ${JSON.stringify(submission.parameters)}`\n );\n }\n\n this.formLogger.info('Processing form submission:', {\n formId: submission.formId,\n toolName: submission.toolName,\n parameterKeys: Object.keys(submission.parameters),\n parametersType: typeof submission.parameters,\n parametersIsNull: submission.parameters === null,\n parametersIsUndefined: submission.parameters === undefined,\n hasContext: !!submission.context,\n });\n\n let pendingForm = this.pendingForms.get(submission.formId);\n\n if (!pendingForm) {\n pendingForm = globalPendingForms.get(submission.formId);\n if (!pendingForm) {\n throw new Error(`No pending form found for ID: ${submission.formId}`);\n }\n }\n\n this.pendingForms.delete(submission.formId);\n globalPendingForms.delete(submission.formId);\n\n const tool =\n pendingForm.toolRef ||\n this.tools.find((t) => t.name === pendingForm.toolName);\n if (!tool) {\n throw new Error(\n `Tool not found for form submission: ${pendingForm.toolName}`\n );\n }\n\n let baseToolInput: Record<string, unknown> = {};\n try {\n if (\n pendingForm.originalToolInput &&\n typeof pendingForm.originalToolInput === 'object'\n ) {\n baseToolInput = {\n ...(pendingForm.originalToolInput as Record<string, unknown>),\n };\n }\n } catch (error) {\n this.formLogger.warn(\n 'Failed to extract base tool input, using empty object:',\n error\n );\n baseToolInput = {};\n }\n\n let submissionData: Record<string, unknown> = {};\n try {\n if (submission.parameters && typeof submission.parameters === 'object') {\n submissionData = {\n ...(submission.parameters as Record<string, unknown>),\n };\n }\n } catch (error) {\n this.formLogger.warn(\n 'Failed to extract submission parameters, using empty object:',\n error\n );\n submissionData = {};\n }\n\n const mergedToolInput: Record<string, unknown> = {};\n try {\n Object.keys(baseToolInput).forEach((key) => {\n const value = baseToolInput[key];\n if (value !== undefined && value !== null) {\n mergedToolInput[key] = value;\n }\n });\n\n Object.keys(submissionData).forEach((key) => {\n const value = submissionData[key];\n if (value !== undefined && value !== null) {\n mergedToolInput[key] = value;\n }\n });\n\n mergedToolInput.renderForm = false;\n mergedToolInput.__fromForm = true;\n\n this.formLogger.info('Successfully merged tool input:', {\n baseKeys: Object.keys(baseToolInput),\n submissionKeys: Object.keys(submissionData),\n mergedKeys: Object.keys(mergedToolInput),\n });\n } catch (error) {\n this.formLogger.error('Failed to merge tool input data:', error);\n throw new Error(\n `Failed to merge tool input data: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\n }\n\n try {\n const maybeWrapper = tool as ToolWrapper;\n let toolOutput: string;\n if (typeof maybeWrapper.executeOriginal === 'function') {\n toolOutput = await maybeWrapper.executeOriginal(mergedToolInput);\n } else if (typeof maybeWrapper.getOriginalTool === 'function') {\n const ot = maybeWrapper.getOriginalTool();\n const otCall = ot as CallableTool;\n if (ot && typeof otCall._call === 'function') {\n toolOutput = await otCall._call(mergedToolInput);\n } else if (ot && typeof otCall.call === 'function') {\n toolOutput = await otCall.call(mergedToolInput);\n } else {\n const tcall = tool as CallableTool;\n if (typeof tcall.call === 'function') {\n toolOutput = await tcall.call(mergedToolInput);\n } else {\n throw new Error(\n 'No callable tool implementation found for form submission'\n );\n }\n }\n } else if (\n maybeWrapper.originalTool &&\n typeof maybeWrapper.originalTool._call === 'function'\n ) {\n toolOutput = await maybeWrapper.originalTool._call(mergedToolInput);\n } else if (\n maybeWrapper.originalTool &&\n typeof maybeWrapper.originalTool.call === 'function'\n ) {\n toolOutput = await maybeWrapper.originalTool.call(mergedToolInput);\n } else if (typeof (tool as CallableTool).call === 'function') {\n toolOutput = await (tool as CallableTool).call!(mergedToolInput);\n } else {\n throw new Error(\n 'No callable tool implementation found for form submission'\n );\n }\n\n let responseMetadata: Record<string, unknown> = {};\n let formattedOutput: string;\n\n try {\n const parsed = JSON.parse(toolOutput);\n this.formLogger.info(\n '✅ METADATA EXTRACTION: Successfully parsed JSON',\n {\n jsonKeys: Object.keys(parsed),\n hasHashLinkBlock: !!(parsed as Record<string, unknown>)\n .hashLinkBlock,\n }\n );\n\n if (parsed && typeof parsed === 'object') {\n if (ResponseFormatter.isHashLinkResponse(parsed)) {\n this.formLogger.info(\n '🔗 HASHLINK DETECTED: Processing HashLink response separately to preserve metadata'\n );\n\n const parsedRecord = parsed as Record<string, unknown>;\n responseMetadata = {\n ...responseMetadata,\n hashLinkBlock: parsedRecord.hashLinkBlock,\n ...parsedRecord,\n };\n\n formattedOutput = ResponseFormatter.formatHashLinkResponse(parsed);\n\n this.formLogger.info(\n '🔗 METADATA PRESERVED: HashLink metadata extracted for component rendering',\n {\n blockId: this.hasHashLinkBlock(responseMetadata)\n ? responseMetadata.hashLinkBlock.blockId\n : undefined,\n hasTemplate: this.hasHashLinkBlock(responseMetadata)\n ? !!responseMetadata.hashLinkBlock.template\n : false,\n }\n );\n } else {\n formattedOutput = ResponseFormatter.formatResponse(toolOutput);\n\n responseMetadata = {\n ...responseMetadata,\n hashLinkBlock: (parsed as Record<string, unknown>).hashLinkBlock,\n ...parsed,\n };\n }\n } else {\n formattedOutput = ResponseFormatter.formatResponse(toolOutput);\n }\n } catch (error) {\n this.formLogger.warn(\n '❌ METADATA EXTRACTION: Tool output is not JSON',\n {\n error: error instanceof Error ? error.message : 'unknown error',\n outputSample:\n typeof toolOutput === 'string'\n ? toolOutput.substring(0, 200)\n : 'not-string',\n }\n );\n\n formattedOutput = ResponseFormatter.formatResponse(toolOutput);\n }\n\n return {\n output: formattedOutput,\n formCompleted: true,\n originalFormId: submission.formId,\n intermediateSteps: [],\n metadata: responseMetadata,\n rawToolOutput: toolOutput,\n toolName: pendingForm.toolName,\n };\n } catch (error) {\n if (error instanceof ZodError) {\n return this.handleValidationError(error, mergedToolInput, []);\n }\n throw error;\n }\n }\n\n /**\n * Extracts tool information from the execution context\n */\n private extractToolInfoFromError(\n error: ZodError,\n inputs: Record<string, unknown>,\n intermediateSteps: AgentStep[]\n ): { toolName: string; schema: unknown } | null {\n try {\n if (intermediateSteps.length > 0) {\n const lastStep = intermediateSteps[intermediateSteps.length - 1];\n if (lastStep.action && lastStep.action.tool) {\n const tool = this.tools.find((t) => t.name === lastStep.action.tool);\n if (tool && 'schema' in tool) {\n this.formLogger.info(\n 'Found tool from intermediate steps:',\n lastStep.action.tool\n );\n return {\n toolName: lastStep.action.tool,\n schema: (tool as ToolWithSchema).schema,\n };\n }\n }\n }\n\n const inputSteps = (inputs.intermediateSteps as unknown[]) || [];\n if (inputSteps.length > 0) {\n const lastStep = inputSteps[inputSteps.length - 1];\n let action: AgentAction;\n\n if (Array.isArray(lastStep) && lastStep.length > 0) {\n action = lastStep[0] as AgentAction;\n } else if ((lastStep as Record<string, unknown>).action) {\n action = (lastStep as Record<string, unknown>).action as AgentAction;\n } else {\n action = lastStep as AgentAction;\n }\n\n if (action && action.tool) {\n const tool = this.tools.find((t) => t.name === action.tool);\n if (tool && 'schema' in tool) {\n this.formLogger.info('Found tool from input steps:', action.tool);\n return {\n toolName: action.tool,\n schema: (tool as ToolWithSchema).schema,\n };\n }\n }\n }\n\n const toolFromContext = this.findToolFromContext(inputs);\n if (toolFromContext) {\n this.formLogger.info(\n 'Found tool from context:',\n toolFromContext.toolName\n );\n return toolFromContext;\n }\n\n return null;\n } catch (err) {\n this.formLogger.error('Error extracting tool info:', err);\n return null;\n }\n }\n\n /**\n * Attempts to find tool from execution context\n */\n private findToolFromContext(inputs: Record<string, unknown>): {\n toolName: string;\n schema: unknown;\n } | null {\n const inputText = (inputs.input as string) || '';\n\n for (const tool of this.tools) {\n const keywords = this.extractToolKeywords(tool.name);\n\n if (\n keywords.some((keyword) =>\n inputText.toLowerCase().includes(keyword.toLowerCase())\n )\n ) {\n if ('schema' in tool) {\n return {\n toolName: tool.name,\n schema: (tool as ToolWithSchema).schema,\n };\n }\n }\n }\n\n return null;\n }\n\n /**\n * Additional fallback to detect tool from error context\n */\n private detectToolFromErrorContext(\n error: ZodError\n ): { toolName: string; schema: unknown } | null {\n const errorPaths = error.issues.map((issue) => issue.path.join('.'));\n\n for (const tool of this.tools) {\n if ('schema' in tool) {\n const toolSchema = (tool as ToolWithSchema).schema;\n if (this.schemaMatchesErrorPaths(toolSchema, errorPaths)) {\n this.formLogger.info(\n 'Detected tool from error path analysis:',\n tool.name\n );\n return {\n toolName: tool.name,\n schema: toolSchema,\n };\n }\n }\n }\n\n return null;\n }\n\n /**\n * Checks if a schema structure matches error paths\n */\n private schemaMatchesErrorPaths(\n schema: unknown,\n errorPaths: string[]\n ): boolean {\n const schemaRecord = schema as Record<string, unknown>;\n if (!schemaRecord || !schemaRecord._def) return false;\n\n try {\n const def = schemaRecord._def as Record<string, unknown>;\n if (def.typeName === 'ZodObject') {\n const shape = def.shape as Record<string, unknown>;\n const schemaKeys = Object.keys(shape || {});\n return errorPaths.some((path) => {\n const topLevelKey = path.split('.')[0];\n return schemaKeys.includes(topLevelKey);\n });\n }\n } catch (err) {\n this.formLogger.debug('Error analyzing schema structure:', err);\n }\n\n return false;\n }\n\n /**\n * Extracts keywords from tool name for matching\n */\n private extractToolKeywords(toolName: string): string[] {\n const words = toolName\n .replace(/([A-Z])/g, ' $1')\n .toLowerCase()\n .split(/[\\s_-]+/)\n .filter((w) => w.length > 2);\n\n return [...words, toolName.toLowerCase()];\n }\n\n /**\n * Formats the form message for display\n */\n private formatFormResponse(formMessage: FormMessage): string {\n const fieldCount = formMessage.formConfig.fields.length;\n const fieldList = formMessage.formConfig.fields\n .slice(0, 3)\n .map((f) => `• ${f.label}`)\n .join('\\n');\n\n return `I need some additional information to complete your request.\n\n${formMessage.formConfig.description}\n\nRequired fields:\n${fieldList}${fieldCount > 3 ? `\\n... and ${fieldCount - 3} more` : ''}\n\nPlease fill out the form below to continue.`;\n }\n\n /**\n * Check if there are pending forms\n */\n hasPendingForms(): boolean {\n return this.pendingForms.size > 0;\n }\n\n /**\n * Get information about pending forms\n */\n getPendingFormsInfo(): Array<{ formId: string; toolName: string }> {\n return Array.from(this.pendingForms.entries()).map(([formId, info]) => ({\n formId,\n toolName: info.toolName,\n }));\n }\n\n\n /**\n * Processes HashLink block responses from tools\n */\n private processHashLinkResponse(\n toolResponse: ToolResponse\n ): HashLinkResponse {\n try {\n let hashLinkBlock: HashLinkBlock | undefined;\n\n if (toolResponse.hashLinkBlock) {\n hashLinkBlock = toolResponse.hashLinkBlock;\n } else if (toolResponse.success && toolResponse.hashLinkBlock) {\n hashLinkBlock = toolResponse.hashLinkBlock;\n }\n\n if (!hashLinkBlock) {\n throw new Error('HashLink block data not found in response');\n }\n\n if (\n !hashLinkBlock.blockId ||\n !hashLinkBlock.hashLink ||\n !hashLinkBlock.attributes\n ) {\n throw new Error(\n 'Invalid HashLink block structure - missing required fields'\n );\n }\n\n let message = 'Content processed successfully!';\n\n if (toolResponse.success && toolResponse.inscription) {\n const inscription = toolResponse.inscription;\n const metadata = toolResponse.metadata || {};\n\n message = `✅ ${inscription.standard} Hashinal inscription completed!\\n\\n`;\n\n if (metadata.name) {\n message += `**${metadata.name}**\\n`;\n }\n\n if (metadata.description) {\n message += `${metadata.description}\\n\\n`;\n }\n\n message += `📍 **Topic ID:** ${inscription.topicId}\\n`;\n message += `🔗 **HRL:** ${inscription.hrl}\\n`;\n\n if (inscription.cdnUrl) {\n message += `🌐 **CDN URL:** ${inscription.cdnUrl}\\n`;\n }\n\n if (metadata.creator) {\n message += `👤 **Creator:** ${metadata.creator}\\n`;\n }\n }\n\n this.formLogger.info('Processed HashLink response', {\n blockId: hashLinkBlock.blockId,\n hashLink: hashLinkBlock.hashLink,\n hasTemplate: !!hashLinkBlock.template,\n attributeCount: Object.keys(hashLinkBlock.attributes || {}).length,\n });\n\n return {\n hasHashLinkBlocks: true,\n hashLinkBlock,\n message,\n };\n } catch (error) {\n this.formLogger.error('Error processing HashLink response:', error);\n\n return {\n hasHashLinkBlocks: false,\n message: 'Content processed, but interactive display is not available.',\n };\n }\n }\n\n /**\n * Get FormEngine statistics for debugging\n */\n getFormEngineStatistics(): {\n strategies: string[];\n middleware: string[];\n } {\n return {\n strategies: this.formEngine.getRegisteredStrategies(),\n middleware: this.formEngine.getRegisteredMiddleware(),\n };\n }\n}\n","import type { BaseMessage } from '@langchain/core/messages';\nimport type { StructuredTool } from '@langchain/core/tools';\nimport type { TransactionReceipt } from '@hashgraph/sdk';\nimport {\n HederaAgentKit,\n ServerSigner,\n TokenUsageCallbackHandler,\n TokenUsage,\n BasePlugin,\n} from 'hedera-agent-kit';\nimport type { CostCalculation } from 'hedera-agent-kit';\nimport type { AIProvider, VercelAIProvider, BAMLProvider } from './providers';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport type { MCPServerConfig, MCPConnectionStatus } from './mcp/types';\nimport type { FormSubmission } from './forms/types';\n\nexport interface ToolFilterConfig {\n namespaceWhitelist?: string[];\n toolBlacklist?: string[];\n toolPredicate?: (tool: StructuredTool) => boolean;\n}\n\nexport type ExecutionMode = 'direct' | 'bytes';\nexport type OperationalMode = 'autonomous' | 'returnBytes';\n\nexport interface HederaAgentConfiguration {\n signer: ServerSigner;\n execution?: {\n mode?: ExecutionMode;\n operationalMode?: OperationalMode;\n userAccountId?: string;\n scheduleUserTransactions?: boolean;\n scheduleUserTransactionsInBytesMode?: boolean;\n };\n ai?: {\n provider?: AIProvider;\n llm?: unknown;\n apiKey?: string;\n modelName?: string;\n temperature?: number;\n };\n filtering?: ToolFilterConfig;\n messaging?: {\n systemPreamble?: string;\n systemPostamble?: string;\n conciseMode?: boolean;\n };\n extensions?: {\n plugins?: BasePlugin[];\n mirrorConfig?: Record<string, unknown>;\n modelCapability?: string;\n };\n mcp?: {\n servers?: MCPServerConfig[];\n autoConnect?: boolean;\n };\n debug?: {\n verbose?: boolean;\n silent?: boolean;\n };\n}\n\nexport interface ConversationContext {\n messages: BaseMessage[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface ChatResponse {\n output: string;\n message?: string;\n transactionBytes?: string;\n receipt?: TransactionReceipt | object;\n scheduleId?: string;\n transactionId?: string;\n notes?: string[];\n error?: string;\n intermediateSteps?: unknown;\n rawToolOutput?: unknown;\n tokenUsage?: TokenUsage;\n cost?: CostCalculation;\n metadata?: Record<string, unknown>;\n tool_calls?: Array<{\n id: string;\n name: string;\n args: Record<string, unknown>;\n output?: string;\n }>;\n formMessage?: unknown;\n requiresForm?: boolean;\n [key: string]: unknown;\n}\n\nexport interface UsageStats extends TokenUsage {\n cost: CostCalculation;\n}\n\nexport abstract class BaseAgent {\n protected logger: Logger;\n protected agentKit: HederaAgentKit | undefined;\n protected tools: StructuredTool[] = [];\n protected initialized = false;\n protected tokenTracker: TokenUsageCallbackHandler | undefined;\n\n constructor(protected config: HederaAgentConfiguration) {\n this.logger = new Logger({\n module: 'BaseAgent',\n silent: config.debug?.silent || false,\n });\n }\n\n abstract boot(): Promise<void>;\n abstract chat(\n message: string,\n context?: ConversationContext\n ): Promise<ChatResponse>;\n abstract processFormSubmission(\n submission: FormSubmission\n ): Promise<ChatResponse>;\n abstract shutdown(): Promise<void>;\n abstract switchMode(mode: OperationalMode): void;\n abstract getUsageStats(): UsageStats;\n abstract getUsageLog(): UsageStats[];\n abstract clearUsageStats(): void;\n abstract connectMCPServers(): Promise<void>;\n abstract getMCPConnectionStatus(): Map<string, MCPConnectionStatus>;\n\n public getCore(): HederaAgentKit | undefined {\n return this.agentKit;\n }\n\n protected filterTools(tools: StructuredTool[]): StructuredTool[] {\n let filtered = [...tools];\n const filter = this.config.filtering;\n\n if (!filter) return filtered;\n\n if (filter.namespaceWhitelist?.length) {\n filtered = filtered.filter((tool) => {\n const namespace = (tool as StructuredTool & { namespace?: string })\n .namespace;\n return !namespace || filter.namespaceWhitelist!.includes(namespace);\n });\n }\n\n if (filter.toolBlacklist?.length) {\n filtered = filtered.filter(\n (tool) => !filter.toolBlacklist!.includes(tool.name)\n );\n }\n\n if (filter.toolPredicate) {\n filtered = filtered.filter(filter.toolPredicate);\n }\n\n this.logger.debug(`Filtered tools: ${tools.length} → ${filtered.length}`);\n return filtered;\n }\n\n protected buildSystemPrompt(): string {\n const parts: string[] = [];\n const operatorId = this.config.signer.getAccountId().toString();\n const userAccId = this.config.execution?.userAccountId;\n\n if (this.config.messaging?.systemPreamble) {\n parts.push(this.config.messaging.systemPreamble);\n }\n\n parts.push(\n `You are a helpful Hedera assistant. Your primary operator account is ${operatorId}. ` +\n `You have tools to interact with the Hedera Hashgraph. ` +\n `When using any tool, provide all necessary parameters as defined by that tool's schema and description.`\n );\n\n parts.push(\n `\\nMETADATA QUALITY PRINCIPLES: When collecting user input for metadata creation across any tool:` +\n `\\n• Prioritize meaningful, valuable content over technical file information` +\n `\\n• Focus on attributes that add value for end users and collectors` +\n `\\n• Avoid auto-generating meaningless technical attributes as user-facing metadata` +\n `\\n• When fields are missing or inadequate, use forms to collect quality metadata` +\n `\\n• Encourage descriptive names, collectible traits, and storytelling elements`\n );\n\n if (userAccId) {\n parts.push(\n `The user you are assisting has a personal Hedera account ID: ${userAccId}. ` +\n `IMPORTANT: When the user says things like \"I want to send HBAR\" or \"transfer my tokens\", you MUST use ${userAccId} as the sender/from account. ` +\n `For example, if user says \"I want to send 2 HBAR to 0.0.800\", you must set up a transfer where ${userAccId} sends the HBAR, not your operator account.`\n );\n }\n\n const operationalMode =\n this.config.execution?.operationalMode || 'returnBytes';\n if (operationalMode === 'autonomous') {\n parts.push(\n `\\nOPERATIONAL MODE: 'autonomous'. Your goal is to execute transactions directly using your tools. ` +\n `Your account ${operatorId} will be the payer for these transactions. ` +\n `Even if the user's account (${\n userAccId || 'a specified account'\n }) is the actor in the transaction body (e.g., sender of HBAR), ` +\n `you (the agent with operator ${operatorId}) are still executing and paying. For HBAR transfers, ensure the amounts in the 'transfers' array sum to zero (as per tool schema), balancing with your operator account if necessary.`\n );\n } else {\n if (\n this.config.execution?.scheduleUserTransactionsInBytesMode &&\n userAccId\n ) {\n parts.push(\n `\\nOPERATIONAL MODE: 'returnBytes' with scheduled transactions for user actions. ` +\n `When a user asks for a transaction to be prepared (e.g., creating a token, topic, transferring assets for them to sign, etc), ` +\n `you MUST default to creating a Scheduled Transaction using the appropriate tool with the metaOption 'schedule: true'. ` +\n `The user (with account ID ${userAccId}) will be the one to ultimately pay for and (if needed) sign the inner transaction. ` +\n `Your operator account (${operatorId}) will pay for creating the schedule entity itself. ` +\n `You MUST return the ScheduleId and details of the scheduled operation in a structured JSON format with these fields: success, op, schedule_id, description, payer_account_id_scheduled_tx, and scheduled_transaction_details.`\n );\n } else {\n parts.push(\n `\\nOPERATIONAL MODE: 'returnBytes'. Your goal is to provide transaction bytes when possible. ` +\n `When a user asks for a transaction to be prepared (e.g., for them to sign, or for scheduling without the default scheduling flow), ` +\n `you MUST call the appropriate tool. ` +\n `IMPORTANT: Only use metaOption 'returnBytes: true' for tools that explicitly support it (like HBAR transfers, token operations). ` +\n `Many tools (inscriptions, HCS-2, HCS-20, etc.) do NOT support returnBytes and will execute directly - this is expected behavior. ` +\n `For tools without returnBytes support, simply call them with their standard parameters. ` +\n `If you need raw bytes for the user to sign for their own account ${\n userAccId || 'if specified'\n }, ensure the tool constructs the transaction body accordingly when returnBytes IS supported.`\n );\n }\n }\n\n if (this.config.messaging?.conciseMode !== false) {\n parts.push(\n '\\nAlways be concise. If the tool provides a JSON string as its primary output (especially in returnBytes mode), make your accompanying text brief. If the tool does not provide JSON output or an error occurs, your narrative becomes primary; if notes were generated by the tool in such cases, append them to your textual response.'\n );\n }\n\n if (this.config.messaging?.systemPostamble) {\n parts.push(this.config.messaging.systemPostamble);\n }\n\n return parts.join('\\n');\n }\n\n isReady(): boolean {\n return this.initialized;\n }\n}\n\nexport type { AIProvider, VercelAIProvider, BAMLProvider };\n","import type { ContentType, ContentSource } from '../types/content-reference';\nimport type { ContentStorage } from '../memory/content-storage';\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\n/**\n * Content reference interface\n */\ninterface ContentReference {\n referenceId: string;\n preview?: string;\n metadata: {\n sizeBytes: number;\n contentType?: string;\n [key: string]: unknown;\n };\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(\n (max, content) => Math.max(max, content.sizeBytes),\n 0\n );\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: [\n error instanceof Error ? error.message : 'Unknown processing error',\n ],\n };\n }\n }\n\n private extractContentFromResponse(\n obj: unknown,\n contents: MCPResponseContent[]\n ): 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 );\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 (\n this.contentStorage.shouldUseReference(\n typeof contentInfo.content === 'string'\n ? contentInfo.content\n : JSON.stringify(contentInfo.content)\n )\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(\n contentInfo.mimeType\n );\n\n const metadata: Parameters<\n typeof this.contentStorage.storeContentIfLarge\n >[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(\n `Failed to create reference: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\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(\n reference: ContentReference\n ): 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(\n obj: unknown,\n oldContent: unknown,\n newContent: unknown\n ): 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 if (typeof newContent === 'object' && newContent !== null) {\n const newContentRecord = newContent as Record<string, unknown>;\n for (const key of Object.keys(newContentRecord)) {\n record[key] = newContentRecord[key];\n }\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}\n","import { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';\nimport type { MCPServerConfig, MCPToolInfo, MCPConnectionStatus } from './types';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport type { ContentStorage } from '../memory/content-storage';\nimport { MCPContentProcessor } from './content-processor';\n\n/**\n * Manages connections to MCP servers and tool discovery\n */\nexport class MCPClientManager {\n private clients: Map<string, Client> = new Map();\n private tools: Map<string, MCPToolInfo[]> = new Map();\n private logger: Logger;\n private contentProcessor?: MCPContentProcessor;\n\n constructor(logger: Logger, contentStorage?: ContentStorage) {\n this.logger = logger;\n if (contentStorage) {\n this.contentProcessor = new MCPContentProcessor(contentStorage, logger);\n }\n }\n\n /**\n * Connect to an MCP server and discover its tools\n */\n async connectServer(config: MCPServerConfig): Promise<MCPConnectionStatus> {\n try {\n if (this.isServerConnected(config.name)) {\n return {\n serverName: config.name,\n connected: false,\n error: `Server ${config.name} is already connected`,\n tools: [],\n };\n }\n\n if (config.transport && config.transport !== 'stdio') {\n throw new Error(`Transport ${config.transport} not yet supported`);\n }\n\n const transport = new StdioClientTransport({\n command: config.command,\n args: config.args,\n ...(config.env && { env: config.env }),\n });\n\n const client = new Client({\n name: `conversational-agent-${config.name}`,\n version: '1.0.0',\n }, {\n capabilities: {},\n });\n\n await client.connect(transport);\n this.clients.set(config.name, client);\n\n const toolsResponse = await client.listTools();\n const toolsWithServer: MCPToolInfo[] = toolsResponse.tools.map((tool: unknown) => {\n const t = tool as { description?: string } & Record<string, unknown>;\n const { description, ...rest } = t;\n const base = description !== undefined && typeof description === 'string'\n ? { ...rest, description }\n : { ...rest };\n return {\n ...(base as Omit<MCPToolInfo, 'serverName'>),\n serverName: config.name,\n } as MCPToolInfo;\n });\n\n this.tools.set(config.name, toolsWithServer);\n this.logger.info(`Connected to MCP server ${config.name} with ${toolsWithServer.length} tools`);\n\n return {\n serverName: config.name,\n connected: true,\n tools: toolsWithServer,\n };\n } catch (error) {\n this.logger.error(`Failed to connect to MCP server ${config.name}:`, error);\n return {\n serverName: config.name,\n connected: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n tools: [],\n };\n }\n }\n\n /**\n * Execute a tool on a specific MCP server\n */\n async executeTool(serverName: string, toolName: string, args: Record<string, unknown>): Promise<unknown> {\n const client = this.clients.get(serverName);\n if (!client) {\n throw new Error(`MCP server ${serverName} not connected`);\n }\n\n this.logger.debug(`Executing MCP tool ${toolName} on server ${serverName}`, args);\n\n try {\n const result = await client.callTool({\n name: toolName,\n arguments: args,\n });\n\n if (this.contentProcessor) {\n const processed = await this.contentProcessor.processResponse(result, serverName, toolName);\n \n if (processed.wasProcessed) {\n this.logger.debug(\n `Processed MCP response from ${serverName}::${toolName}`,\n {\n referenceCreated: processed.referenceCreated,\n originalSize: processed.originalSize,\n errors: processed.errors\n }\n );\n\n if (processed.errors && processed.errors.length > 0) {\n this.logger.warn(`Content processing warnings for ${serverName}::${toolName}:`, processed.errors);\n }\n }\n\n return processed.content;\n }\n\n return result;\n } catch (error) {\n this.logger.error(`Error executing MCP tool ${toolName}:`, error);\n throw error;\n }\n }\n\n /**\n * Disconnect all MCP servers\n */\n async disconnectAll(): Promise<void> {\n for (const [name, client] of this.clients) {\n try {\n await client.close();\n this.logger.info(`Disconnected from MCP server ${name}`);\n } catch (error) {\n this.logger.error(`Error disconnecting MCP server ${name}:`, error);\n }\n }\n this.clients.clear();\n this.tools.clear();\n }\n\n /**\n * Get all discovered tools from all connected servers\n */\n getAllTools(): MCPToolInfo[] {\n const allTools: MCPToolInfo[] = [];\n for (const tools of this.tools.values()) {\n allTools.push(...tools);\n }\n return allTools;\n }\n\n /**\n * Get tools from a specific server\n */\n getServerTools(serverName: string): MCPToolInfo[] {\n return this.tools.get(serverName) || [];\n }\n\n /**\n * Check if a server is connected\n */\n isServerConnected(serverName: string): boolean {\n return this.clients.has(serverName);\n }\n\n /**\n * Get list of connected server names\n */\n getConnectedServers(): string[] {\n return Array.from(this.clients.keys());\n }\n\n /**\n * Enable content processing with content storage\n */\n enableContentProcessing(contentStorage: ContentStorage): void {\n this.contentProcessor = new MCPContentProcessor(contentStorage, this.logger);\n this.logger.info('Content processing enabled for MCP responses');\n }\n\n /**\n * Disable content processing\n */\n disableContentProcessing(): void {\n delete this.contentProcessor;\n this.logger.info('Content processing disabled for MCP responses');\n }\n\n /**\n * Check if content processing is enabled\n */\n isContentProcessingEnabled(): boolean {\n return this.contentProcessor !== undefined;\n }\n\n /**\n * Analyze a response without processing it (for testing/debugging)\n */\n analyzeResponseContent(response: unknown): unknown {\n if (!this.contentProcessor) {\n throw new Error('Content processing is not enabled');\n }\n return this.contentProcessor.analyzeResponse(response);\n }\n}\n","import { DynamicStructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport type { MCPToolInfo, MCPServerConfig } from '../types';\nimport type { MCPClientManager } from '../mcp-client-manager';\nimport {\n ContentStoreService,\n shouldUseReference,\n} from '@hashgraphonline/standards-sdk';\nimport type { ContentSource } from '../../types/content-reference';\n\n/**\n * Convert an MCP tool to a LangChain DynamicStructuredTool\n */\nexport function convertMCPToolToLangChain(\n tool: MCPToolInfo,\n mcpManager: MCPClientManager,\n serverConfig?: MCPServerConfig\n): DynamicStructuredTool {\n const zodSchema = jsonSchemaToZod(tool.inputSchema);\n\n const sanitizedName = `${tool.serverName}_${tool.name}`.replace(\n /[^a-zA-Z0-9_]/g,\n '_'\n );\n\n let description =\n tool.description || `MCP tool ${tool.name} from ${tool.serverName}`;\n\n if (serverConfig?.toolDescriptions?.[tool.name]) {\n description = `${description}\\n\\n${\n serverConfig.toolDescriptions[tool.name]\n }`;\n }\n\n if (serverConfig?.additionalContext) {\n description = `${description}\\n\\nContext: ${serverConfig.additionalContext}`;\n }\n\n return new DynamicStructuredTool({\n name: sanitizedName,\n description,\n schema: zodSchema,\n func: async (input) => {\n try {\n const result = await mcpManager.executeTool(\n tool.serverName,\n tool.name,\n input\n );\n\n let responseText = '';\n\n if (typeof result === 'string') {\n responseText = result;\n } else if (\n result &&\n typeof result === 'object' &&\n 'content' in result\n ) {\n const content = (result as { content: unknown }).content;\n if (Array.isArray(content)) {\n const textParts = content\n .filter(\n (item): item is { type: string; text: string } =>\n typeof item === 'object' &&\n item !== null &&\n 'type' in item &&\n item.type === 'text' &&\n 'text' in item\n )\n .map((item) => item.text);\n responseText = textParts.join('\\n');\n } else {\n responseText = JSON.stringify(content);\n }\n } else {\n responseText = JSON.stringify(result);\n }\n\n const responseBuffer = Buffer.from(responseText, 'utf8');\n\n const MCP_REFERENCE_THRESHOLD = 10 * 1024;\n const shouldStoreMCPContent =\n responseBuffer.length > MCP_REFERENCE_THRESHOLD;\n\n if (shouldStoreMCPContent || shouldUseReference(responseBuffer)) {\n const contentStore = ContentStoreService.getInstance();\n if (contentStore) {\n try {\n const referenceId = await contentStore.storeContent(\n responseBuffer,\n {\n contentType: 'text' as ContentSource,\n source: 'mcp',\n mcpToolName: `${tool.serverName}_${tool.name}`,\n originalSize: responseBuffer.length,\n }\n );\n return `content-ref:${referenceId}`;\n } catch {}\n }\n }\n\n return responseText;\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n return `Error executing MCP tool ${tool.name}: ${errorMessage}`;\n }\n },\n });\n}\n\n/**\n * Convert JSON Schema to Zod schema\n * This is a simplified converter that handles common cases\n */\nfunction jsonSchemaToZod(schema: unknown): z.ZodTypeAny {\n if (!schema || typeof schema !== 'object') {\n return z.object({});\n }\n\n const schemaObj = schema as Record<string, unknown>;\n\n if (schemaObj.type && schemaObj.type !== 'object') {\n return convertType(schemaObj);\n }\n\n if (!schemaObj.properties || typeof schemaObj.properties !== 'object') {\n return z.object({});\n }\n\n const shape: Record<string, z.ZodTypeAny> = {};\n\n for (const [key, value] of Object.entries(schemaObj.properties)) {\n let zodType = convertType(value);\n\n const isRequired =\n Array.isArray(schemaObj.required) && schemaObj.required.includes(key);\n if (!isRequired) {\n zodType = zodType.optional();\n }\n\n shape[key] = zodType;\n }\n\n return z.object(shape);\n}\n\n/**\n * Convert a single JSON Schema type to Zod\n */\nfunction convertType(schema: unknown): z.ZodTypeAny {\n if (!schema || typeof schema !== 'object' || !('type' in schema)) {\n return z.unknown();\n }\n\n const schemaObj = schema as {\n type: string;\n enum?: unknown[];\n items?: unknown;\n };\n let zodType: z.ZodTypeAny;\n\n switch (schemaObj.type) {\n case 'string':\n zodType = z.string();\n if (schemaObj.enum && Array.isArray(schemaObj.enum)) {\n zodType = z.enum(schemaObj.enum as [string, ...string[]]);\n }\n break;\n\n case 'number':\n zodType = z.number();\n if ('minimum' in schemaObj && typeof schemaObj.minimum === 'number') {\n zodType = (zodType as z.ZodNumber).min(schemaObj.minimum);\n }\n if ('maximum' in schemaObj && typeof schemaObj.maximum === 'number') {\n zodType = (zodType as z.ZodNumber).max(schemaObj.maximum);\n }\n break;\n\n case 'integer':\n zodType = z.number().int();\n if ('minimum' in schemaObj && typeof schemaObj.minimum === 'number') {\n zodType = (zodType as z.ZodNumber).min(schemaObj.minimum);\n }\n if ('maximum' in schemaObj && typeof schemaObj.maximum === 'number') {\n zodType = (zodType as z.ZodNumber).max(schemaObj.maximum);\n }\n break;\n\n case 'boolean':\n zodType = z.boolean();\n break;\n\n case 'array':\n if (schemaObj.items) {\n zodType = z.array(convertType(schemaObj.items));\n } else {\n zodType = z.array(z.unknown());\n }\n break;\n\n case 'object':\n if ('properties' in schemaObj) {\n zodType = jsonSchemaToZod(schemaObj);\n } else {\n zodType = z.object({}).passthrough();\n }\n break;\n\n default:\n zodType = z.unknown();\n }\n\n if ('description' in schemaObj && typeof schemaObj.description === 'string') {\n zodType = zodType.describe(schemaObj.description);\n }\n\n return zodType;\n}\n","import { encoding_for_model } from 'tiktoken';\nimport type { TiktokenModel } from 'tiktoken';\nimport type { BaseMessage } from '@langchain/core/messages';\n\n/**\n * Token counter utility for OpenAI models using tiktoken encoding\n * Provides accurate token counting for text content and chat messages\n */\nexport class TokenCounter {\n private encoding: ReturnType<typeof encoding_for_model>;\n private modelName: string;\n\n private static readonly MESSAGE_OVERHEAD = 3;\n private static readonly ROLE_OVERHEAD = 1;\n\n constructor(modelName: string | TiktokenModel = 'gpt-4o') {\n this.modelName = String(modelName);\n try {\n this.encoding = encoding_for_model(modelName as TiktokenModel);\n } catch {\n this.encoding = encoding_for_model('gpt-4o');\n this.modelName = 'gpt-4o';\n }\n }\n\n /**\n * Count tokens in raw text content\n * @param text - The text to count tokens for\n * @returns Number of tokens\n */\n countTokens(text: string): number {\n if (!text || text.trim() === '') {\n return 0;\n }\n\n try {\n const tokens = this.encoding.encode(text);\n return tokens.length;\n } catch {\n return Math.ceil(text.split(/\\s+/).length * 1.3);\n }\n }\n\n /**\n * Count tokens for a single chat message including role overhead\n * @param message - The message to count tokens for\n * @returns Number of tokens including message formatting overhead\n */\n countMessageTokens(message: BaseMessage): number {\n const contentTokens = this.countTokens(String(message.content ?? ''));\n const roleTokens = this.countTokens(this.getMessageRole(message));\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Count tokens for multiple messages\n * @param messages - Array of messages to count\n * @returns Total token count for all messages\n */\n countMessagesTokens(messages: BaseMessage[]): number {\n if (!messages || messages.length === 0) {\n return 0;\n }\n\n let total = 0;\n for (const message of messages) {\n total += this.countMessageTokens(message);\n }\n return total;\n }\n\n /**\n * Estimate tokens for system prompt\n * System prompts have slightly different overhead in chat completions\n * @param systemPrompt - The system prompt text\n * @returns Estimated token count\n */\n estimateSystemPromptTokens(systemPrompt: string): number {\n if (!systemPrompt || systemPrompt.trim() === '') {\n return 0;\n }\n\n const contentTokens = this.countTokens(systemPrompt);\n const roleTokens = this.countTokens('system');\n \n return contentTokens + roleTokens + TokenCounter.MESSAGE_OVERHEAD + TokenCounter.ROLE_OVERHEAD;\n }\n\n /**\n * Get total context size estimate including system prompt and messages\n * @param systemPrompt - System prompt text\n * @param messages - Conversation messages\n * @returns Total estimated token count\n */\n estimateContextSize(systemPrompt: string, messages: BaseMessage[]): number {\n const systemTokens = this.estimateSystemPromptTokens(systemPrompt);\n const messageTokens = this.countMessagesTokens(messages);\n \n const completionOverhead = 10;\n \n return systemTokens + messageTokens + completionOverhead;\n }\n\n /**\n * Get the role string for a message\n * @param message - The message to get the role for\n * @returns Role string ('user', 'assistant', 'system', etc.)\n */\n private getMessageRole(message: BaseMessage): string {\n const messageType = message._getType();\n switch (messageType) {\n case 'human':\n return 'user';\n case 'ai':\n return 'assistant';\n case 'system':\n return 'system';\n case 'function':\n return 'function';\n case 'tool':\n return 'tool';\n default:\n return 'user';\n }\n }\n\n /**\n * Get the model name being used for token counting\n * @returns The tiktoken model name\n */\n getModelName(): string {\n return this.modelName;\n }\n\n /**\n * Clean up encoding resources\n */\n dispose(): void {\n try {\n this.encoding.free();\n } catch {\n }\n }\n}","import type { BaseMessage } from '@langchain/core/messages';\nimport { TokenCounter } from './token-counter';\n\n/**\n * Result of adding a message to the memory window\n */\nexport interface AddMessageResult {\n /** Whether the message was successfully added */\n added: boolean;\n /** Messages that were pruned to make room */\n prunedMessages: BaseMessage[];\n /** Current token count after operation */\n currentTokenCount: number;\n /** Remaining token capacity */\n remainingCapacity: number;\n}\n\n/**\n * Memory window that manages conversation history with token-based size limits\n * Automatically prunes old messages to stay within token limits while preserving conversational context\n */\nexport class MemoryWindow {\n private messages: BaseMessage[] = [];\n private maxTokens: number;\n private reserveTokens: number;\n private tokenCounter: TokenCounter;\n private systemPrompt: string = '';\n private systemPromptTokens: number = 0;\n\n public static readonly DEFAULT_MAX_TOKENS = 8000;\n public static readonly DEFAULT_RESERVE_TOKENS = 1000;\n public static readonly PRUNING_BATCH_SIZE = 2;\n\n constructor(\n maxTokens: number = MemoryWindow.DEFAULT_MAX_TOKENS,\n reserveTokens: number = MemoryWindow.DEFAULT_RESERVE_TOKENS,\n tokenCounter?: TokenCounter\n ) {\n if (reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n this.reserveTokens = reserveTokens;\n this.tokenCounter = tokenCounter || new TokenCounter();\n }\n\n /**\n * Add a message to the memory window, pruning old messages if necessary\n * @param message - The message to add\n * @returns Result of the add operation including any pruned messages\n */\n addMessage(message: BaseMessage): AddMessageResult {\n this.tokenCounter.countMessageTokens(message);\n\n this.messages.push(message);\n\n const currentTokens = this.getCurrentTokenCount();\n const availableTokens = this.maxTokens - this.reserveTokens;\n\n let prunedMessages: BaseMessage[] = [];\n\n if (currentTokens > availableTokens) {\n this.messages.pop();\n\n prunedMessages = this.pruneToFit();\n\n this.messages.push(message);\n }\n\n return {\n added: true,\n prunedMessages,\n currentTokenCount: this.getCurrentTokenCount(),\n remainingCapacity: this.getRemainingTokenCapacity(),\n };\n }\n\n /**\n * Prune old messages to fit within token limits\n * Removes messages in pairs to maintain conversational flow\n * @returns Array of pruned messages\n */\n pruneToFit(): BaseMessage[] {\n const prunedMessages: BaseMessage[] = [];\n const targetTokens = this.maxTokens - this.reserveTokens;\n\n while (\n this.getCurrentTokenCount() > targetTokens &&\n this.messages.length > 0\n ) {\n const batchSize = Math.min(\n MemoryWindow.PRUNING_BATCH_SIZE,\n this.messages.length\n );\n\n for (let i = 0; i < batchSize; i++) {\n const prunedMessage = this.messages.shift();\n if (prunedMessage) {\n prunedMessages.push(prunedMessage);\n }\n }\n\n if (prunedMessages.length > 1000) {\n break;\n }\n }\n\n return prunedMessages;\n }\n\n /**\n * Get current token count including system prompt and messages\n * @returns Current token count\n */\n getCurrentTokenCount(): number {\n const messageTokens = this.tokenCounter.countMessagesTokens(this.messages);\n return this.systemPromptTokens + messageTokens;\n }\n\n /**\n * Get remaining token capacity before hitting the reserve limit\n * @returns Remaining tokens that can be used\n */\n getRemainingTokenCapacity(): number {\n return Math.max(0, this.maxTokens - this.getCurrentTokenCount());\n }\n\n /**\n * Check if a message can be added without exceeding limits\n * @param message - The message to check\n * @returns True if message can be added within reserve limits\n */\n canAddMessage(message: BaseMessage): boolean {\n const messageTokens = this.tokenCounter.countMessageTokens(message);\n const currentTokens = this.getCurrentTokenCount();\n const wouldExceedReserve =\n currentTokens + messageTokens > this.maxTokens - this.reserveTokens;\n\n if (messageTokens > this.maxTokens) {\n return false;\n }\n\n return !wouldExceedReserve || this.messages.length > 0;\n }\n\n /**\n * Get all messages in the memory window\n * @returns Copy of current messages array\n */\n getMessages(): BaseMessage[] {\n return [...this.messages];\n }\n\n /**\n * Clear all messages from the memory window\n */\n clear(): void {\n this.messages = [];\n }\n\n /**\n * Set the system prompt and update token calculations\n * @param systemPrompt - The system prompt text\n */\n setSystemPrompt(systemPrompt: string): void {\n this.systemPrompt = systemPrompt;\n this.systemPromptTokens =\n this.tokenCounter.estimateSystemPromptTokens(systemPrompt);\n }\n\n /**\n * Get the current system prompt\n * @returns Current system prompt\n */\n getSystemPrompt(): string {\n return this.systemPrompt;\n }\n\n /**\n * Get current configuration\n * @returns Memory window configuration\n */\n getConfig(): {\n maxTokens: number;\n reserveTokens: number;\n currentTokens: number;\n messageCount: number;\n systemPromptTokens: number;\n } {\n return {\n maxTokens: this.maxTokens,\n reserveTokens: this.reserveTokens,\n currentTokens: this.getCurrentTokenCount(),\n messageCount: this.messages.length,\n systemPromptTokens: this.systemPromptTokens,\n };\n }\n\n /**\n * Update token limits\n * @param maxTokens - New maximum token limit\n * @param reserveTokens - New reserve token amount\n */\n updateLimits(maxTokens: number, reserveTokens?: number): void {\n if (reserveTokens !== undefined && reserveTokens >= maxTokens) {\n throw new Error('Reserve tokens must be less than max tokens');\n }\n\n this.maxTokens = maxTokens;\n if (reserveTokens !== undefined) {\n this.reserveTokens = reserveTokens;\n }\n\n if (this.getCurrentTokenCount() > this.maxTokens - this.reserveTokens) {\n this.pruneToFit();\n }\n }\n\n /**\n * Get statistics about the memory window\n * @returns Memory usage statistics\n */\n getStats(): {\n totalMessages: number;\n currentTokens: number;\n maxTokens: number;\n reserveTokens: number;\n systemPromptTokens: number;\n usagePercentage: number;\n remainingCapacity: number;\n canAcceptMore: boolean;\n } {\n const currentTokens = this.getCurrentTokenCount();\n const capacity = this.maxTokens;\n const usagePercentage = (currentTokens / capacity) * 100;\n\n return {\n totalMessages: this.messages.length,\n currentTokens,\n maxTokens: capacity,\n reserveTokens: this.reserveTokens,\n systemPromptTokens: this.systemPromptTokens,\n usagePercentage: Math.round(usagePercentage * 100) / 100,\n remainingCapacity: this.getRemainingTokenCapacity(),\n canAcceptMore: this.getRemainingTokenCapacity() > this.reserveTokens,\n };\n }\n\n /**\n * Clean up resources\n */\n dispose(): void {\n this.clear();\n this.tokenCounter.dispose();\n }\n}\n","import { createHash } from 'crypto';\nimport { ReferenceId } from '../types/content-reference';\n\n/**\n * Content-based reference ID generator using SHA-256 (HCS-1 style)\n * \n * Generates deterministic reference IDs based on content hashing.\n * Same content always produces the same reference ID.\n */\nexport class ReferenceIdGenerator {\n /**\n * Generate a content-based reference ID using SHA-256 hashing\n * \n * @param content The content to generate a reference ID for\n * @returns Deterministic reference ID based on content hash\n */\n static generateId(content: Buffer): ReferenceId {\n const hash = createHash('sha256');\n hash.update(content);\n return hash.digest('hex');\n }\n \n /**\n * Validate that a string is a properly formatted reference ID\n * \n * @param id The ID to validate\n * @returns true if the ID is valid format\n */\n static isValidReferenceId(id: string): id is ReferenceId {\n if (!id || typeof id !== 'string') {\n return false;\n }\n \n if (id.length !== 64) {\n return false;\n }\n \n return /^[a-f0-9]+$/.test(id);\n }\n \n /**\n * Extract reference ID from ref:// format\n * \n * @param input Input string that may contain a reference ID\n * @returns Extracted reference ID or null if not found\n */\n static extractReferenceId(input: string): ReferenceId | null {\n if (!input || typeof input !== 'string') {\n return null;\n }\n \n const refFormatMatch = input.match(/^ref:\\/\\/([a-f0-9]{64})$/);\n if (refFormatMatch) {\n return refFormatMatch[1] as ReferenceId;\n }\n \n return this.isValidReferenceId(input) ? input : null;\n }\n \n /**\n * Format a reference ID in the standard ref:// format\n * \n * @param referenceId The reference ID to format\n * @returns Formatted reference string\n */\n static formatReference(referenceId: ReferenceId): string {\n return `ref://${referenceId}`;\n }\n \n /**\n * Generate a test reference ID (for testing purposes only)\n * \n * @param testSeed A test seed to generate a fake but valid ID format\n * @returns A valid format reference ID for testing\n */\n static generateTestId(testSeed: string): ReferenceId {\n const content = Buffer.from(`test-${testSeed}-${Date.now()}`);\n return this.generateId(content);\n }\n}","/**\n * Content Reference System Types\n *\n * Shared interfaces for the Reference-Based Content System that handles\n * large content storage with unique reference IDs to optimize context window usage.\n */\n\n/**\n * Unique identifier for stored content references\n * Format: Cryptographically secure 32-byte identifier with base64url encoding\n */\nexport type ReferenceId = string;\n\n/**\n * Lifecycle state of a content reference\n */\nexport type ReferenceLifecycleState =\n | 'active'\n | 'expired'\n | 'cleanup_pending'\n | 'invalid';\n\n/**\n * Content types supported by the reference system\n */\nexport type ContentType =\n | 'text'\n | 'json'\n | 'html'\n | 'markdown'\n | 'binary'\n | 'unknown';\n\n/**\n * Sources that created the content reference\n */\nexport type ContentSource =\n | 'mcp_tool'\n | 'user_upload'\n | 'agent_generated'\n | 'system';\n\n/**\n * Metadata associated with stored content\n */\nexport interface ContentMetadata {\n /** Content type classification */\n contentType: ContentType;\n\n /** MIME type of the original content */\n mimeType?: string;\n\n /** Size in bytes of the stored content */\n sizeBytes: number;\n\n /** When the content was originally stored */\n createdAt: Date;\n\n /** Last time the content was accessed via reference resolution */\n lastAccessedAt: Date;\n\n /** Source that created this content reference */\n source: ContentSource;\n\n /** Name of the MCP tool that generated the content (if applicable) */\n mcpToolName?: string;\n\n /** Original filename or suggested name for the content */\n fileName?: string;\n\n /** Number of times this reference has been resolved */\n accessCount: number;\n\n /** Tags for categorization and cleanup policies */\n tags?: string[];\n\n /** Custom metadata from the source */\n customMetadata?: Record<string, unknown>;\n}\n\n/**\n * Core content reference object passed through agent context\n * Designed to be lightweight (<100 tokens) while providing enough\n * information for agent decision-making\n */\nexport interface ContentReference {\n /** Unique identifier for resolving the content */\n referenceId: ReferenceId;\n\n /** Current lifecycle state */\n state: ReferenceLifecycleState;\n\n /** Brief description or preview of the content (max 200 chars) */\n preview: string;\n\n /** Essential metadata for agent decision-making */\n metadata: Pick<\n ContentMetadata,\n 'contentType' | 'sizeBytes' | 'source' | 'fileName' | 'mimeType'\n >;\n\n /** When this reference was created */\n createdAt: Date;\n\n /** Special format indicator for reference IDs in content */\n readonly format: 'ref://{id}';\n}\n\n/**\n * Result of attempting to resolve a content reference\n */\nexport interface ReferenceResolutionResult {\n /** Whether the resolution was successful */\n success: boolean;\n\n /** The resolved content if successful */\n content?: Buffer;\n\n /** Complete metadata if successful */\n metadata?: ContentMetadata;\n\n /** Error message if resolution failed */\n error?: string;\n\n /** Specific error type for targeted error handling */\n errorType?:\n | 'not_found'\n | 'expired'\n | 'corrupted'\n | 'access_denied'\n | 'system_error';\n\n /** Suggested actions for recovery */\n suggestedActions?: string[];\n}\n\n/**\n * Configuration for content reference storage and lifecycle\n */\nexport interface ContentReferenceConfig {\n /** Size threshold above which content should be stored as references (default: 10KB) */\n sizeThresholdBytes: number;\n\n /** Maximum age for unused references before cleanup (default: 1 hour) */\n maxAgeMs: number;\n\n /** Maximum number of references to store simultaneously */\n maxReferences: number;\n\n /** Maximum total storage size for all references */\n maxTotalStorageBytes: number;\n\n /** Whether to enable automatic cleanup */\n enableAutoCleanup: boolean;\n\n /** Interval for cleanup checks in milliseconds */\n cleanupIntervalMs: number;\n\n /** Whether to persist references across restarts */\n enablePersistence: boolean;\n\n /** Storage backend configuration */\n storageBackend: 'memory' | 'filesystem' | 'hybrid';\n\n /** Cleanup policies for different content types */\n cleanupPolicies: {\n /** Policy for content marked as \"recent\" from MCP tools */\n recent: { maxAgeMs: number; priority: number };\n\n /** Policy for user-uploaded content */\n userContent: { maxAgeMs: number; priority: number };\n\n /** Policy for agent-generated content */\n agentGenerated: { maxAgeMs: number; priority: number };\n\n /** Default policy for other content */\n default: { maxAgeMs: number; priority: number };\n };\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONTENT_REFERENCE_CONFIG: ContentReferenceConfig = {\n sizeThresholdBytes: 10 * 1024,\n maxAgeMs: 60 * 60 * 1000,\n maxReferences: 100,\n maxTotalStorageBytes: 100 * 1024 * 1024,\n enableAutoCleanup: true,\n cleanupIntervalMs: 5 * 60 * 1000,\n enablePersistence: false,\n storageBackend: 'memory',\n cleanupPolicies: {\n recent: { maxAgeMs: 30 * 60 * 1000, priority: 1 },\n userContent: { maxAgeMs: 2 * 60 * 60 * 1000, priority: 2 },\n agentGenerated: { maxAgeMs: 60 * 60 * 1000, priority: 3 },\n default: { maxAgeMs: 60 * 60 * 1000, priority: 4 },\n },\n};\n\n/**\n * Statistics about content reference usage and storage\n */\nexport interface ContentReferenceStats {\n /** Total number of active references */\n activeReferences: number;\n\n /** Total storage used by all references in bytes */\n totalStorageBytes: number;\n\n /** Number of references cleaned up in last cleanup cycle */\n recentlyCleanedUp: number;\n\n /** Number of successful reference resolutions since startup */\n totalResolutions: number;\n\n /** Number of failed resolution attempts */\n failedResolutions: number;\n\n /** Average content size in bytes */\n averageContentSize: number;\n\n /** Most frequently accessed reference ID */\n mostAccessedReferenceId?: ReferenceId;\n\n /** Storage utilization percentage */\n storageUtilization: number;\n\n /** Performance metrics */\n performanceMetrics: {\n /** Average time to create a reference in milliseconds */\n averageCreationTimeMs: number;\n\n /** Average time to resolve a reference in milliseconds */\n averageResolutionTimeMs: number;\n\n /** Average cleanup time in milliseconds */\n averageCleanupTimeMs: number;\n };\n}\n\n/**\n * Error types for content reference operations\n */\nexport class ContentReferenceError extends Error {\n constructor(\n message: string,\n public readonly type: ReferenceResolutionResult['errorType'],\n public readonly referenceId?: ReferenceId,\n public readonly suggestedActions?: string[]\n ) {\n super(message);\n this.name = 'ContentReferenceError';\n }\n}\n\n/**\n * Interface for content reference storage implementations\n */\nexport interface ContentReferenceStore {\n /**\n * Store content and return a reference\n */\n storeContent(\n content: Buffer,\n metadata: Omit<\n ContentMetadata,\n 'createdAt' | 'lastAccessedAt' | 'accessCount'\n >\n ): Promise<ContentReference>;\n\n /**\n * Resolve a reference to its content\n */\n resolveReference(\n referenceId: ReferenceId\n ): Promise<ReferenceResolutionResult>;\n\n /**\n * Check if a reference exists and is valid\n */\n hasReference(referenceId: ReferenceId): Promise<boolean>;\n\n /**\n * Mark a reference for cleanup\n */\n cleanupReference(referenceId: ReferenceId): Promise<boolean>;\n\n /**\n * Get current storage statistics\n */\n getStats(): Promise<ContentReferenceStats>;\n\n /**\n * Update configuration\n */\n updateConfig(config: Partial<ContentReferenceConfig>): Promise<void>;\n\n /**\n * Perform cleanup based on current policies\n */\n performCleanup(): Promise<{ cleanedUp: number; errors: string[] }>;\n\n /**\n * Dispose of resources\n */\n dispose(): Promise<void>;\n}\n","import type { BaseMessage } from '@langchain/core/messages';\nimport { ReferenceIdGenerator } from './reference-id-generator';\nimport {\n ReferenceId,\n ContentReference,\n ContentMetadata,\n ReferenceResolutionResult,\n ContentReferenceConfig,\n ContentReferenceStore,\n ContentReferenceStats,\n ContentReferenceError,\n ContentType,\n ContentSource,\n ReferenceLifecycleState,\n DEFAULT_CONTENT_REFERENCE_CONFIG,\n} from '../types/content-reference';\n\n/**\n * Stored message with metadata\n */\ninterface StoredMessage {\n message: BaseMessage;\n storedAt: Date;\n id: string;\n}\n\n/**\n * Search options for message queries\n */\ninterface SearchOptions {\n /** Whether to perform case-sensitive search */\n caseSensitive?: boolean;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use regex pattern matching */\n useRegex?: boolean;\n}\n\n/**\n * Result of storing messages\n */\ninterface StoreResult {\n /** Number of messages successfully stored */\n stored: number;\n /** Number of old messages dropped to make room */\n dropped: number;\n}\n\n/**\n * Storage statistics\n */\nexport interface StorageStats {\n /** Total number of messages currently stored */\n totalMessages: number;\n /** Maximum storage capacity */\n maxStorageLimit: number;\n /** Percentage of storage used */\n usagePercentage: number;\n /** Timestamp of oldest message */\n oldestMessageTime: Date | undefined;\n /** Timestamp of newest message */\n newestMessageTime: Date | undefined;\n}\n\n/**\n * Stored content with reference metadata\n */\ninterface StoredContent {\n /** The actual content buffer */\n content: Buffer;\n\n /** Complete metadata */\n metadata: ContentMetadata;\n\n /** Current lifecycle state */\n state: ReferenceLifecycleState;\n\n /** When this reference expires (if applicable) */\n expiresAt?: Date;\n}\n\n/**\n * Content storage for managing pruned conversation messages and large content references\n * Provides searchable storage with time-based querying and automatic cleanup.\n *\n * Extended to support reference-based storage for large content to optimize context window usage.\n */\nexport class ContentStorage implements ContentReferenceStore {\n private messages: StoredMessage[] = [];\n private maxStorage: number;\n private idCounter: number = 0;\n\n private contentStore: Map<ReferenceId, StoredContent> = new Map();\n private referenceConfig: ContentReferenceConfig;\n private cleanupTimer?: NodeJS.Timeout;\n private referenceStats: Omit<ContentReferenceStats, 'performanceMetrics'> & {\n performanceMetrics: ContentReferenceStats['performanceMetrics'] & {\n creationTimes: number[];\n resolutionTimes: number[];\n cleanupTimes: number[];\n };\n };\n\n public static readonly DEFAULT_MAX_STORAGE = 1000;\n\n constructor(\n maxStorage: number = ContentStorage.DEFAULT_MAX_STORAGE,\n referenceConfig?: Partial<ContentReferenceConfig>\n ) {\n this.maxStorage = maxStorage;\n\n this.referenceConfig = {\n ...DEFAULT_CONTENT_REFERENCE_CONFIG,\n ...referenceConfig,\n };\n this.referenceStats = {\n activeReferences: 0,\n totalStorageBytes: 0,\n recentlyCleanedUp: 0,\n totalResolutions: 0,\n failedResolutions: 0,\n averageContentSize: 0,\n storageUtilization: 0,\n performanceMetrics: {\n averageCreationTimeMs: 0,\n averageResolutionTimeMs: 0,\n averageCleanupTimeMs: 0,\n creationTimes: [],\n resolutionTimes: [],\n cleanupTimes: [],\n },\n };\n\n if (this.referenceConfig.enableAutoCleanup) {\n this.startReferenceCleanupTimer();\n }\n }\n\n /**\n * Store messages in the content storage\n * Automatically drops oldest messages if storage limit is exceeded\n * @param messages - Messages to store\n * @returns Result indicating how many messages were stored and dropped\n */\n storeMessages(messages: BaseMessage[]): StoreResult {\n if (messages.length === 0) {\n return { stored: 0, dropped: 0 };\n }\n\n const now = new Date();\n let dropped = 0;\n\n const storedMessages: StoredMessage[] = messages.map((message) => ({\n message,\n storedAt: now,\n id: this.generateId(),\n }));\n\n this.messages.push(...storedMessages);\n\n while (this.messages.length > this.maxStorage) {\n this.messages.shift();\n dropped++;\n }\n\n return {\n stored: storedMessages.length,\n dropped,\n };\n }\n\n /**\n * Get the most recent messages from storage\n * @param count - Number of recent messages to retrieve\n * @returns Array of recent messages in chronological order\n */\n getRecentMessages(count: number): BaseMessage[] {\n if (count <= 0 || this.messages.length === 0) {\n return [];\n }\n\n const startIndex = Math.max(0, this.messages.length - count);\n return this.messages.slice(startIndex).map((stored) => stored.message);\n }\n\n /**\n * Search for messages containing specific text or patterns\n * @param query - Search term or regex pattern\n * @param options - Search configuration options\n * @returns Array of matching messages\n */\n searchMessages(query: string, options: SearchOptions = {}): BaseMessage[] {\n if (!query || this.messages.length === 0) {\n return [];\n }\n\n const { caseSensitive = false, limit, useRegex = false } = options;\n\n let matches: BaseMessage[] = [];\n\n if (useRegex) {\n try {\n const regex = new RegExp(query, caseSensitive ? 'g' : 'gi');\n matches = this.messages\n .filter((stored) => regex.test(stored.message.content as string))\n .map((stored) => stored.message);\n } catch {\n return [];\n }\n } else {\n const searchTerm = caseSensitive ? query : query.toLowerCase();\n matches = this.messages\n .filter((stored) => {\n const content = stored.message.content as string;\n const searchContent = caseSensitive ? content : content.toLowerCase();\n return searchContent.includes(searchTerm);\n })\n .map((stored) => stored.message);\n }\n\n return limit ? matches.slice(0, limit) : matches;\n }\n\n /**\n * Get messages from a specific time range\n * @param startTime - Start of time range (inclusive)\n * @param endTime - End of time range (inclusive)\n * @returns Array of messages within the time range\n */\n getMessagesFromTimeRange(startTime: Date, endTime: Date): BaseMessage[] {\n if (startTime > endTime || this.messages.length === 0) {\n return [];\n }\n\n return this.messages\n .filter(\n (stored) => stored.storedAt >= startTime && stored.storedAt <= endTime\n )\n .map((stored) => stored.message);\n }\n\n /**\n * Get storage statistics and usage information\n * @returns Current storage statistics\n */\n getStorageStats(): StorageStats {\n const totalMessages = this.messages.length;\n const usagePercentage =\n totalMessages > 0\n ? Math.round((totalMessages / this.maxStorage) * 100)\n : 0;\n\n let oldestMessageTime: Date | undefined;\n let newestMessageTime: Date | undefined;\n\n if (totalMessages > 0) {\n oldestMessageTime = this.messages[0].storedAt;\n newestMessageTime = this.messages[totalMessages - 1].storedAt;\n }\n\n return {\n totalMessages,\n maxStorageLimit: this.maxStorage,\n usagePercentage,\n oldestMessageTime,\n newestMessageTime,\n };\n }\n\n /**\n * Clear all stored messages\n */\n clear(): void {\n this.messages = [];\n this.idCounter = 0;\n }\n\n /**\n * Get total number of stored messages\n * @returns Number of messages currently in storage\n */\n getTotalStoredMessages(): number {\n return this.messages.length;\n }\n\n /**\n * Update the maximum storage limit\n * @param newLimit - New maximum storage limit\n */\n updateStorageLimit(newLimit: number): void {\n if (newLimit <= 0) {\n throw new Error('Storage limit must be greater than 0');\n }\n\n this.maxStorage = newLimit;\n\n while (this.messages.length > this.maxStorage) {\n this.messages.shift();\n }\n }\n\n /**\n * Get messages by message type\n * @param messageType - Type of messages to retrieve ('human', 'ai', 'system', etc.)\n * @param limit - Maximum number of messages to return\n * @returns Array of messages of the specified type\n */\n getMessagesByType(messageType: string, limit?: number): BaseMessage[] {\n const filtered = this.messages\n .filter((stored) => stored.message._getType() === messageType)\n .map((stored) => stored.message);\n\n return limit ? filtered.slice(0, limit) : filtered;\n }\n\n /**\n * Get the current storage configuration\n * @returns Storage configuration object\n */\n getConfig(): {\n maxStorage: number;\n currentUsage: number;\n utilizationPercentage: number;\n } {\n return {\n maxStorage: this.maxStorage,\n currentUsage: this.messages.length,\n utilizationPercentage: (this.messages.length / this.maxStorage) * 100,\n };\n }\n\n /**\n * Generate a unique ID for stored messages\n * @returns Unique string identifier\n */\n private generateId(): string {\n return `msg_${++this.idCounter}_${Date.now()}`;\n }\n\n /**\n * Get messages stored within the last N minutes\n * @param minutes - Number of minutes to look back\n * @returns Array of messages from the last N minutes\n */\n getRecentMessagesByTime(minutes: number): BaseMessage[] {\n if (minutes <= 0 || this.messages.length === 0) {\n return [];\n }\n\n const cutoffTime = new Date(Date.now() - minutes * 60 * 1000);\n\n return this.messages\n .filter((stored) => stored.storedAt >= cutoffTime)\n .map((stored) => stored.message);\n }\n\n /**\n * Export messages to a JSON-serializable format\n * @returns Serializable representation of stored messages\n */\n exportMessages(): Array<{\n content: string;\n type: string;\n storedAt: string;\n id: string;\n }> {\n return this.messages.map((stored) => ({\n content:\n typeof stored.message.content === 'string'\n ? stored.message.content\n : JSON.stringify(stored.message.content),\n type: stored.message._getType(),\n storedAt: stored.storedAt.toISOString(),\n id: stored.id,\n }));\n }\n\n /**\n * Determine if content should be stored as a reference based on size\n */\n shouldUseReference(content: Buffer | string): boolean {\n const size = Buffer.isBuffer(content)\n ? content.length\n : Buffer.byteLength(content, 'utf8');\n return size > this.referenceConfig.sizeThresholdBytes;\n }\n\n /**\n * Store content and return a reference if it exceeds the size threshold\n * Otherwise returns null to indicate direct content should be used\n *\n * Special case: Image files are ALWAYS stored as references regardless of size\n * because they need special handling for inscription tools\n */\n async storeContentIfLarge(\n content: Buffer | string,\n metadata: {\n contentType?: ContentType;\n mimeType?: string;\n source: ContentSource;\n mcpToolName?: string;\n fileName?: string;\n tags?: string[];\n customMetadata?: Record<string, unknown>;\n }\n ): Promise<ContentReference | null> {\n const buffer = Buffer.isBuffer(content)\n ? content\n : Buffer.from(content, 'utf8');\n\n const isImageFile = this.isImageContent(\n metadata.mimeType,\n metadata.fileName\n );\n\n if (!isImageFile && !this.shouldUseReference(buffer)) {\n return null;\n }\n\n const storeMetadata: Omit<\n ContentMetadata,\n 'createdAt' | 'lastAccessedAt' | 'accessCount'\n > = {\n contentType:\n metadata.contentType ||\n this.detectContentType(buffer, metadata.mimeType),\n sizeBytes: buffer.length,\n source: metadata.source,\n tags: [],\n };\n\n if (metadata.mimeType !== undefined) {\n storeMetadata.mimeType = metadata.mimeType;\n }\n if (metadata.mcpToolName !== undefined) {\n storeMetadata.mcpToolName = metadata.mcpToolName;\n }\n if (metadata.fileName !== undefined) {\n storeMetadata.fileName = metadata.fileName;\n }\n if (metadata.tags !== undefined) {\n storeMetadata.tags = metadata.tags;\n }\n if (metadata.customMetadata !== undefined) {\n storeMetadata.customMetadata = metadata.customMetadata;\n }\n\n return await this.storeContent(buffer, storeMetadata);\n }\n\n /**\n * Store content and return a reference (implements ContentReferenceStore)\n */\n async storeContent(\n content: Buffer,\n metadata: Omit<\n ContentMetadata,\n 'createdAt' | 'lastAccessedAt' | 'accessCount'\n >\n ): Promise<ContentReference> {\n const startTime = Date.now();\n\n try {\n const now = new Date();\n const referenceId = ReferenceIdGenerator.generateId(content);\n\n const fullMetadata: ContentMetadata = {\n ...metadata,\n createdAt: now,\n lastAccessedAt: now,\n accessCount: 0,\n };\n\n const storedContent: StoredContent = {\n content,\n metadata: fullMetadata,\n state: 'active',\n };\n\n const expirationTime = this.calculateExpirationTime(metadata.source);\n if (expirationTime !== undefined) {\n storedContent.expiresAt = expirationTime;\n }\n\n this.contentStore.set(referenceId, storedContent);\n\n this.updateStatsAfterStore(content.length);\n\n await this.enforceReferenceStorageLimits();\n\n const preview = this.createContentPreview(\n content,\n fullMetadata.contentType\n );\n\n const referenceMetadata: Pick<\n ContentMetadata,\n 'contentType' | 'sizeBytes' | 'source' | 'fileName' | 'mimeType'\n > = {\n contentType: fullMetadata.contentType,\n sizeBytes: fullMetadata.sizeBytes,\n source: fullMetadata.source,\n };\n\n if (fullMetadata.fileName !== undefined) {\n referenceMetadata.fileName = fullMetadata.fileName;\n }\n if (fullMetadata.mimeType !== undefined) {\n referenceMetadata.mimeType = fullMetadata.mimeType;\n }\n\n const reference: ContentReference = {\n referenceId,\n state: 'active',\n preview,\n metadata: referenceMetadata,\n createdAt: now,\n format: 'ref://{id}' as const,\n };\n\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('creation', duration);\n\n return reference;\n } catch (error) {\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('creation', duration);\n\n throw new ContentReferenceError(\n `Failed to store content: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n 'system_error',\n undefined,\n ['Try again', 'Check storage limits', 'Contact administrator']\n );\n }\n }\n\n /**\n * Resolve a reference to its content (implements ContentReferenceStore)\n */\n async resolveReference(\n referenceId: ReferenceId\n ): Promise<ReferenceResolutionResult> {\n const startTime = Date.now();\n\n try {\n if (!ReferenceIdGenerator.isValidReferenceId(referenceId)) {\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: 'Invalid reference ID format',\n errorType: 'not_found',\n suggestedActions: [\n 'Check the reference ID format',\n 'Ensure the reference ID is complete',\n ],\n };\n }\n\n const storedContent = this.contentStore.get(referenceId);\n\n if (!storedContent) {\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: 'Reference not found',\n errorType: 'not_found',\n suggestedActions: [\n 'Verify the reference ID',\n 'Check if the content has expired',\n 'Request fresh content',\n ],\n };\n }\n\n if (storedContent.expiresAt && storedContent.expiresAt < new Date()) {\n storedContent.state = 'expired';\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: 'Reference has expired',\n errorType: 'expired',\n suggestedActions: [\n 'Request fresh content',\n 'Use alternative content source',\n ],\n };\n }\n\n if (storedContent.state !== 'active') {\n this.referenceStats.failedResolutions++;\n return {\n success: false,\n error: `Reference is ${storedContent.state}`,\n errorType:\n storedContent.state === 'expired' ? 'expired' : 'corrupted',\n suggestedActions: [\n 'Request fresh content',\n 'Check reference validity',\n ],\n };\n }\n\n storedContent.metadata.lastAccessedAt = new Date();\n storedContent.metadata.accessCount++;\n\n this.referenceStats.totalResolutions++;\n\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('resolution', duration);\n\n return {\n success: true,\n content: storedContent.content,\n metadata: storedContent.metadata,\n };\n } catch (error) {\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('resolution', duration);\n\n this.referenceStats.failedResolutions++;\n\n return {\n success: false,\n error: `System error resolving reference: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n errorType: 'system_error',\n suggestedActions: ['Try again', 'Contact administrator'],\n };\n }\n }\n\n /**\n * Check if a reference exists and is valid\n */\n async hasReference(referenceId: ReferenceId): Promise<boolean> {\n if (!ReferenceIdGenerator.isValidReferenceId(referenceId)) {\n return false;\n }\n\n const storedContent = this.contentStore.get(referenceId);\n if (!storedContent) {\n return false;\n }\n\n if (storedContent.expiresAt && storedContent.expiresAt < new Date()) {\n storedContent.state = 'expired';\n return false;\n }\n\n return storedContent.state === 'active';\n }\n\n /**\n * Mark a reference for cleanup\n */\n async cleanupReference(referenceId: ReferenceId): Promise<boolean> {\n const storedContent = this.contentStore.get(referenceId);\n if (!storedContent) {\n return false;\n }\n\n this.referenceStats.totalStorageBytes -= storedContent.content.length;\n this.referenceStats.activeReferences--;\n this.referenceStats.recentlyCleanedUp++;\n\n this.contentStore.delete(referenceId);\n\n return true;\n }\n\n /**\n * Get current reference storage statistics (implements ContentReferenceStore)\n */\n async getStats(): Promise<ContentReferenceStats> {\n this.updateReferenceStorageStats();\n\n return {\n ...this.referenceStats,\n performanceMetrics: {\n averageCreationTimeMs: this.calculateAverage(\n this.referenceStats.performanceMetrics.creationTimes\n ),\n averageResolutionTimeMs: this.calculateAverage(\n this.referenceStats.performanceMetrics.resolutionTimes\n ),\n averageCleanupTimeMs: this.calculateAverage(\n this.referenceStats.performanceMetrics.cleanupTimes\n ),\n },\n };\n }\n\n /**\n * Update reference configuration\n */\n async updateConfig(config: Partial<ContentReferenceConfig>): Promise<void> {\n this.referenceConfig = { ...this.referenceConfig, ...config };\n\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n delete this.cleanupTimer;\n }\n\n if (this.referenceConfig.enableAutoCleanup) {\n this.startReferenceCleanupTimer();\n }\n }\n\n /**\n * Perform cleanup based on current policies (implements ContentReferenceStore)\n */\n async performCleanup(): Promise<{ cleanedUp: number; errors: string[] }> {\n const startTime = Date.now();\n const errors: string[] = [];\n let cleanedUp = 0;\n\n try {\n const now = new Date();\n const toCleanup: ReferenceId[] = [];\n\n for (const [referenceId, storedContent] of this.contentStore.entries()) {\n let shouldCleanup = false;\n\n if (storedContent.expiresAt && storedContent.expiresAt < now) {\n shouldCleanup = true;\n storedContent.state = 'expired';\n }\n\n const ageMs =\n now.getTime() - storedContent.metadata.createdAt.getTime();\n const policy = this.getCleanupPolicy(storedContent.metadata.source);\n\n if (ageMs > policy.maxAgeMs) {\n shouldCleanup = true;\n }\n\n if (storedContent.state === 'cleanup_pending') {\n shouldCleanup = true;\n }\n\n if (shouldCleanup) {\n toCleanup.push(referenceId);\n }\n }\n\n toCleanup.sort((a, b) => {\n const aContent = this.contentStore.get(a)!;\n const bContent = this.contentStore.get(b)!;\n const aPriority = this.getCleanupPolicy(\n aContent.metadata.source\n ).priority;\n const bPriority = this.getCleanupPolicy(\n bContent.metadata.source\n ).priority;\n return bPriority - aPriority;\n });\n\n for (const referenceId of toCleanup) {\n try {\n const success = await this.cleanupReference(referenceId);\n if (success) {\n cleanedUp++;\n }\n } catch (error) {\n errors.push(\n `Failed to cleanup ${referenceId}: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\n }\n }\n\n if (this.contentStore.size > this.referenceConfig.maxReferences) {\n const sortedByAge = Array.from(this.contentStore.entries()).sort(\n ([, a], [, b]) =>\n a.metadata.lastAccessedAt.getTime() -\n b.metadata.lastAccessedAt.getTime()\n );\n\n const excessCount =\n this.contentStore.size - this.referenceConfig.maxReferences;\n for (let i = 0; i < excessCount && i < sortedByAge.length; i++) {\n const [referenceId] = sortedByAge[i];\n try {\n const success = await this.cleanupReference(referenceId);\n if (success) {\n cleanedUp++;\n }\n } catch (error) {\n errors.push(\n `Failed to cleanup excess reference ${referenceId}: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`\n );\n }\n }\n }\n\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('cleanup', duration);\n\n return { cleanedUp, errors };\n } catch (error) {\n const duration = Date.now() - startTime;\n this.recordPerformanceMetric('cleanup', duration);\n\n const errorMessage = `Cleanup process failed: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`;\n errors.push(errorMessage);\n\n return { cleanedUp, errors };\n }\n }\n\n /**\n * Get reference configuration for debugging\n */\n getReferenceConfig(): ContentReferenceConfig {\n return { ...this.referenceConfig };\n }\n\n private async enforceReferenceStorageLimits(): Promise<void> {\n if (this.contentStore.size >= this.referenceConfig.maxReferences) {\n await this.performCleanup();\n }\n\n if (\n this.referenceStats.totalStorageBytes >=\n this.referenceConfig.maxTotalStorageBytes\n ) {\n await this.performCleanup();\n }\n }\n\n private calculateExpirationTime(source: ContentSource): Date | undefined {\n const policy = this.getCleanupPolicy(source);\n return new Date(Date.now() + policy.maxAgeMs);\n }\n\n private getCleanupPolicy(source: ContentSource): {\n maxAgeMs: number;\n priority: number;\n } {\n switch (source) {\n case 'mcp_tool':\n return this.referenceConfig.cleanupPolicies.recent;\n case 'user_upload':\n return this.referenceConfig.cleanupPolicies.userContent;\n case 'agent_generated':\n return this.referenceConfig.cleanupPolicies.agentGenerated;\n default:\n return this.referenceConfig.cleanupPolicies.default;\n }\n }\n\n private detectContentType(content: Buffer, mimeType?: string): ContentType {\n if (mimeType) {\n if (mimeType === 'text/html') return 'html';\n if (mimeType === 'text/markdown') return 'markdown';\n if (mimeType === 'application/json') return 'json';\n if (mimeType.startsWith('text/')) return 'text';\n return 'binary';\n }\n\n const contentStr = content.toString(\n 'utf8',\n 0,\n Math.min(content.length, 1000)\n );\n if (contentStr.startsWith('{') || contentStr.startsWith('[')) return 'json';\n if (contentStr.includes('<html>') || contentStr.includes('<!DOCTYPE'))\n return 'html';\n if (contentStr.includes('#') && contentStr.includes('\\n'))\n return 'markdown';\n\n return 'text';\n }\n\n private createContentPreview(\n content: Buffer,\n contentType: ContentType\n ): string {\n const maxLength = 200;\n let preview = content.toString(\n 'utf8',\n 0,\n Math.min(content.length, maxLength * 2)\n );\n\n if (contentType === 'html') {\n preview = preview\n .replace(/<[^>]*>/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n } else if (contentType === 'json') {\n try {\n const parsed = JSON.parse(preview);\n preview = JSON.stringify(parsed, null, 0);\n } catch {}\n }\n\n preview = preview.trim();\n if (preview.length > maxLength) {\n preview = preview.substring(0, maxLength) + '...';\n }\n\n return preview || '[Binary content]';\n }\n\n private updateStatsAfterStore(sizeBytes: number): void {\n this.referenceStats.activeReferences++;\n this.referenceStats.totalStorageBytes += sizeBytes;\n this.updateReferenceStorageStats();\n }\n\n private updateReferenceStorageStats(): void {\n if (this.referenceStats.activeReferences > 0) {\n this.referenceStats.averageContentSize =\n this.referenceStats.totalStorageBytes /\n this.referenceStats.activeReferences;\n }\n\n this.referenceStats.storageUtilization =\n (this.referenceStats.totalStorageBytes /\n this.referenceConfig.maxTotalStorageBytes) *\n 100;\n\n let mostAccessedId: ReferenceId | undefined;\n let maxAccess = 0;\n\n for (const [referenceId, storedContent] of this.contentStore.entries()) {\n if (storedContent.metadata.accessCount > maxAccess) {\n maxAccess = storedContent.metadata.accessCount;\n mostAccessedId = referenceId;\n }\n }\n\n if (mostAccessedId !== undefined) {\n this.referenceStats.mostAccessedReferenceId = mostAccessedId;\n } else {\n delete this.referenceStats.mostAccessedReferenceId;\n }\n }\n\n /**\n * Check if content is an image file based on MIME type or filename\n */\n private isImageContent(mimeType?: string, fileName?: string): boolean {\n if (mimeType && mimeType.startsWith('image/')) {\n return true;\n }\n\n if (fileName) {\n const lowerFileName = fileName.toLowerCase();\n const imageExtensions = [\n '.png',\n '.jpg',\n '.jpeg',\n '.gif',\n '.bmp',\n '.webp',\n '.svg',\n '.tiff',\n '.ico',\n ];\n return imageExtensions.some((ext) => lowerFileName.endsWith(ext));\n }\n\n return false;\n }\n\n private recordPerformanceMetric(\n type: 'creation' | 'resolution' | 'cleanup',\n timeMs: number\n ): void {\n const metrics = this.referenceStats.performanceMetrics;\n const maxRecords = 100;\n\n switch (type) {\n case 'creation':\n metrics.creationTimes.push(timeMs);\n if (metrics.creationTimes.length > maxRecords) {\n metrics.creationTimes.shift();\n }\n break;\n case 'resolution':\n metrics.resolutionTimes.push(timeMs);\n if (metrics.resolutionTimes.length > maxRecords) {\n metrics.resolutionTimes.shift();\n }\n break;\n case 'cleanup':\n metrics.cleanupTimes.push(timeMs);\n if (metrics.cleanupTimes.length > maxRecords) {\n metrics.cleanupTimes.shift();\n }\n break;\n }\n }\n\n private calculateAverage(times: number[]): number {\n if (times.length === 0) return 0;\n return times.reduce((sum, time) => sum + time, 0) / times.length;\n }\n\n private startReferenceCleanupTimer(): void {\n this.cleanupTimer = setInterval(async () => {\n try {\n await this.performCleanup();\n } catch {}\n }, this.referenceConfig.cleanupIntervalMs);\n }\n\n /**\n * Clean up resources (enhanced to include reference cleanup)\n */\n async dispose(): Promise<void> {\n if (this.cleanupTimer) {\n clearInterval(this.cleanupTimer);\n delete this.cleanupTimer;\n }\n\n this.contentStore.clear();\n\n this.clear();\n }\n}\n","import type { BaseMessage } from '@langchain/core/messages';\nimport { SystemMessage } from '@langchain/core/messages';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport { MemoryWindow } from './memory-window';\nimport { ContentStorage } from './content-storage';\nimport { TokenCounter } from './token-counter';\n\n/**\n * Entity association for storing blockchain entity contexts\n */\nexport interface EntityAssociation {\n /** The blockchain entity ID (e.g., tokenId, accountId, topicId) */\n entityId: string;\n /** User-provided or derived friendly name */\n entityName: string;\n /** Type of entity (token, account, topic, schedule, etc.) */\n entityType: string;\n /** When the entity was created/associated */\n createdAt: Date;\n /** Transaction ID that created this entity */\n transactionId?: string;\n /** Optional session identifier to scope associations */\n sessionId?: string;\n}\n\n/**\n * Options for resolving entity references\n */\nexport interface EntityResolutionOptions {\n /** Filter by specific entity type */\n entityType?: string;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use fuzzy matching for natural language queries */\n fuzzyMatch?: boolean;\n}\n\n/**\n * Configuration for SmartMemoryManager\n */\nexport interface SmartMemoryConfig {\n /** Maximum tokens for active memory window */\n maxTokens?: number;\n /** Reserve tokens for response generation */\n reserveTokens?: number;\n /** Model name for token counting */\n modelName?: string;\n /** Maximum messages to store in content storage */\n storageLimit?: number;\n}\n\n/**\n * Search options for history search\n */\nexport interface SearchOptions {\n /** Whether to perform case-sensitive search */\n caseSensitive?: boolean;\n /** Maximum number of results to return */\n limit?: number;\n /** Whether to use regex pattern matching */\n useRegex?: boolean;\n}\n\n/**\n * Memory statistics for active memory window\n */\nexport interface MemoryStats {\n /** Total active messages in memory window */\n totalActiveMessages: number;\n /** Current token count including system prompt */\n currentTokenCount: number;\n /** Maximum token capacity */\n maxTokens: number;\n /** Remaining token capacity */\n remainingCapacity: number;\n /** System prompt token count */\n systemPromptTokens: number;\n /** Memory usage percentage */\n usagePercentage: number;\n}\n\nconst IS_ENTITY_ASSOCIATION_FLAG = '\"isEntityAssociation\":true';\n\n/**\n * TODO: investigate using chroma / rag for long term memory\n * Smart memory manager that combines active memory window with long-term storage\n * Provides context-aware memory management with automatic pruning and searchable history\n */\nexport class SmartMemoryManager {\n private memoryWindow: MemoryWindow;\n private _contentStorage: ContentStorage;\n private tokenCounter: TokenCounter;\n private config: Required<SmartMemoryConfig>;\n private logger: Logger;\n\n private static readonly DEFAULT_CONFIG: Required<SmartMemoryConfig> = {\n maxTokens: 8000,\n reserveTokens: 1000,\n modelName: 'gpt-4o',\n storageLimit: 1000,\n };\n\n constructor(config: SmartMemoryConfig = {}) {\n this.config = { ...SmartMemoryManager.DEFAULT_CONFIG, ...config };\n this.logger = new Logger({ module: 'SmartMemoryManager' });\n\n this.tokenCounter = new TokenCounter(this.config.modelName);\n this._contentStorage = new ContentStorage(this.config.storageLimit);\n this.memoryWindow = new MemoryWindow(\n this.config.maxTokens,\n this.config.reserveTokens,\n this.tokenCounter\n );\n }\n\n /**\n * Get the content storage instance for file/content reference operations\n * @returns ContentStorage instance\n */\n get contentStorage(): ContentStorage {\n return this._contentStorage;\n }\n\n /**\n * Add a message to the active memory window\n * Automatically handles pruning and storage of displaced messages\n * @param message - Message to add\n */\n addMessage(message: BaseMessage): void {\n const result = this.memoryWindow.addMessage(message);\n\n if (result.prunedMessages.length > 0) {\n this._contentStorage.storeMessages(result.prunedMessages);\n }\n }\n\n /**\n * Get all active messages from the memory window\n * @returns Array of active messages in chronological order\n */\n getMessages(): BaseMessage[] {\n return this.memoryWindow.getMessages();\n }\n\n /**\n * Clear active memory window\n * @param clearStorage - Whether to also clear the content storage (default: false)\n */\n clear(clearStorage: boolean = false): void {\n this.memoryWindow.clear();\n\n if (clearStorage) {\n this._contentStorage.clear();\n }\n }\n\n /**\n * Set the system prompt for the memory window\n * @param systemPrompt - System prompt text\n */\n setSystemPrompt(systemPrompt: string): void {\n this.memoryWindow.setSystemPrompt(systemPrompt);\n }\n\n /**\n * Get the current system prompt\n * @returns Current system prompt text\n */\n getSystemPrompt(): string {\n return this.memoryWindow.getSystemPrompt();\n }\n\n /**\n * Search through stored message history\n * @param query - Search term or pattern\n * @param options - Search configuration\n * @returns Array of matching messages from history\n */\n searchHistory(query: string, options: SearchOptions = {}): BaseMessage[] {\n return this._contentStorage.searchMessages(query, options);\n }\n\n /**\n * Get recent messages from storage history\n * @param count - Number of recent messages to retrieve\n * @returns Array of recent messages from storage\n */\n getRecentHistory(count: number): BaseMessage[] {\n return this._contentStorage.getRecentMessages(count);\n }\n\n /**\n * Check if a message can be added without exceeding limits\n * @param message - Message to test\n * @returns True if message can be added\n */\n canAddMessage(message: BaseMessage): boolean {\n return this.memoryWindow.canAddMessage(message);\n }\n\n /**\n * Get statistics about the active memory window\n * @returns Memory usage statistics\n */\n getMemoryStats(): MemoryStats {\n const windowStats = this.memoryWindow.getStats();\n\n return {\n totalActiveMessages: windowStats.totalMessages,\n currentTokenCount: windowStats.currentTokens,\n maxTokens: windowStats.maxTokens,\n remainingCapacity: windowStats.remainingCapacity,\n systemPromptTokens: windowStats.systemPromptTokens,\n usagePercentage: windowStats.usagePercentage,\n };\n }\n\n /**\n * Get statistics about the content storage\n * @returns Storage usage statistics\n */\n getStorageStats(): ReturnType<ContentStorage['getStorageStats']> {\n return this._contentStorage.getStorageStats();\n }\n\n /**\n * Get combined statistics for both active memory and storage\n * @returns Combined memory and storage statistics\n */\n getOverallStats(): {\n activeMemory: MemoryStats;\n storage: ReturnType<ContentStorage['getStorageStats']>;\n totalMessagesManaged: number;\n activeMemoryUtilization: number;\n storageUtilization: number;\n } {\n const memoryStats = this.getMemoryStats();\n const storageStats = this.getStorageStats();\n\n return {\n activeMemory: memoryStats,\n storage: storageStats,\n totalMessagesManaged:\n memoryStats.totalActiveMessages + storageStats.totalMessages,\n activeMemoryUtilization: memoryStats.usagePercentage,\n storageUtilization: storageStats.usagePercentage,\n };\n }\n\n /**\n * Update the configuration and apply changes\n * @param newConfig - New configuration options\n */\n updateConfig(newConfig: Partial<SmartMemoryConfig>): void {\n this.config = { ...this.config, ...newConfig };\n\n if (\n newConfig.maxTokens !== undefined ||\n newConfig.reserveTokens !== undefined\n ) {\n this.memoryWindow.updateLimits(\n this.config.maxTokens,\n this.config.reserveTokens\n );\n }\n\n if (newConfig.storageLimit !== undefined) {\n this._contentStorage.updateStorageLimit(this.config.storageLimit);\n }\n }\n\n /**\n * Get current configuration\n * @returns Current configuration settings\n */\n getConfig(): Required<SmartMemoryConfig> {\n return { ...this.config };\n }\n\n /**\n * Get messages from storage within a time range\n * @param startTime - Start of time range\n * @param endTime - End of time range\n * @returns Messages within the specified time range\n */\n getHistoryFromTimeRange(startTime: Date, endTime: Date): BaseMessage[] {\n return this._contentStorage.getMessagesFromTimeRange(startTime, endTime);\n }\n\n /**\n * Get messages from storage by message type\n * @param messageType - Type of messages to retrieve ('human', 'ai', 'system', etc.)\n * @param limit - Maximum number of messages to return\n * @returns Messages of the specified type\n */\n getHistoryByType(messageType: string, limit?: number): BaseMessage[] {\n return this._contentStorage.getMessagesByType(messageType, limit);\n }\n\n /**\n * Get recent messages from storage within the last N minutes\n * @param minutes - Number of minutes to look back\n * @returns Messages from the last N minutes\n */\n getRecentHistoryByTime(minutes: number): BaseMessage[] {\n return this._contentStorage.getRecentMessagesByTime(minutes);\n }\n\n /**\n * Export the current state for persistence or analysis\n * @returns Serializable representation of memory state\n */\n exportState(): {\n config: Required<SmartMemoryConfig>;\n activeMessages: Array<{ content: unknown; type: string }>;\n systemPrompt: string;\n memoryStats: MemoryStats;\n storageStats: ReturnType<ContentStorage['getStorageStats']>;\n storedMessages: ReturnType<ContentStorage['exportMessages']>;\n } {\n return {\n config: this.config,\n activeMessages: this.memoryWindow.getMessages().map((msg) => ({\n content: msg.content,\n type: msg._getType(),\n })),\n systemPrompt: this.memoryWindow.getSystemPrompt(),\n memoryStats: this.getMemoryStats(),\n storageStats: this.getStorageStats(),\n storedMessages: this._contentStorage.exportMessages(),\n };\n }\n\n /**\n * Get a summary of conversation context for external use\n * Useful for providing context to other systems or for logging\n * @param includeStoredContext - Whether to include recent stored messages\n * @returns Context summary object\n */\n getContextSummary(includeStoredContext: boolean = false): {\n activeMessageCount: number;\n systemPrompt: string;\n recentMessages: BaseMessage[];\n memoryUtilization: number;\n hasStoredHistory: boolean;\n recentStoredMessages?: BaseMessage[];\n storageStats?: ReturnType<ContentStorage['getStorageStats']>;\n } {\n const activeMessages = this.getMessages();\n const summary = {\n activeMessageCount: activeMessages.length,\n systemPrompt: this.getSystemPrompt(),\n recentMessages: activeMessages.slice(-5),\n memoryUtilization: this.getMemoryStats().usagePercentage,\n hasStoredHistory: this.getStorageStats().totalMessages > 0,\n };\n\n if (includeStoredContext) {\n return {\n ...summary,\n recentStoredMessages: this.getRecentHistory(10),\n storageStats: this.getStorageStats(),\n };\n }\n\n return summary;\n }\n\n /**\n * Perform maintenance operations\n * Optimizes storage and cleans up resources\n */\n performMaintenance(): void {}\n\n /**\n * Store an entity association for later resolution\n * @param entityId - The blockchain entity ID\n * @param entityName - User-provided or derived friendly name\n * @param entityType - Type of entity (token, account, topic, etc.)\n * @param transactionId - Optional transaction ID that created this entity\n */\n storeEntityAssociation(\n entityId: string,\n entityName: string,\n entityType: string,\n transactionId?: string,\n sessionId?: string\n ): void {\n try {\n if (\n !entityId ||\n typeof entityId !== 'string' ||\n entityId.trim().length === 0\n ) {\n return;\n }\n\n if (\n !entityName ||\n typeof entityName !== 'string' ||\n entityName.trim().length === 0\n ) {\n return;\n }\n\n if (\n !entityType ||\n typeof entityType !== 'string' ||\n entityType.trim().length === 0\n ) {\n return;\n }\n\n const sanitizedEntityId = entityId.trim();\n const sanitizedEntityName = entityName.trim().substring(0, 100);\n const sanitizedEntityType = this.normalizeEntityType(entityType);\n\n let usageHint = '';\n if (sanitizedEntityType === 'tokenid') {\n usageHint = 'Use this as tokenId for HTS operations';\n } else if (sanitizedEntityType === 'topicid') {\n usageHint =\n 'Can be used for HCS operations, HRLs for minting with the format hcs://1/<topicId>, etc.';\n } else if (sanitizedEntityType === 'accountid') {\n usageHint = 'Can be used for account based operations';\n }\n\n const association: EntityAssociation & {\n isEntityAssociation: boolean;\n usage?: string;\n hrl?: string;\n } = {\n entityId: sanitizedEntityId,\n entityName: sanitizedEntityName,\n entityType: sanitizedEntityType,\n createdAt: new Date(),\n isEntityAssociation: true,\n ...(usageHint ? { usage: usageHint } : {}),\n ...(sanitizedEntityType === 'topicId'\n ? { hrl: `hcs://1/${sanitizedEntityId}` }\n : {}),\n ...(transactionId !== undefined &&\n transactionId !== null &&\n transactionId.trim() !== ''\n ? { transactionId: transactionId.trim() }\n : {}),\n ...(sessionId && sessionId.trim() !== '' ? { sessionId: sessionId.trim() } : {}),\n };\n\n const content = JSON.stringify(association);\n type LangChainLikeMessage = {\n _getType: () => string;\n content: unknown;\n id: string;\n name?: string;\n additional_kwargs?: Record<string, unknown>;\n };\n\n const entityMessage: LangChainLikeMessage = {\n _getType: () => 'system',\n content: content,\n id: `entity_${sanitizedEntityId}_${Date.now()}`,\n name: 'entity_association',\n additional_kwargs: {\n entityId: sanitizedEntityId,\n entityName: sanitizedEntityName,\n entityType: sanitizedEntityType,\n isEntityAssociation: true,\n ...(sessionId && sessionId.trim() !== '' ? { sessionId: sessionId.trim() } : {}),\n },\n };\n\n try {\n this.memoryWindow.addMessage(new SystemMessage(content));\n } catch {}\n\n this._contentStorage.storeMessages([entityMessage as BaseMessage]);\n } catch (error) {\n this.logger.error('Failed to store entity association', {\n entityId,\n entityName,\n entityType,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n /**\n * Normalize various type aliases to canonical EntityFormat strings using a registry.\n */\n private normalizeEntityType(input: string): string {\n const raw = (input || '').trim();\n if (raw.length === 0) {\n return '';\n }\n\n const key = raw.replace(/[^a-z]/gi, '').toLowerCase();\n\n const REGISTRY: Record<string, string> = {\n topic: 'topicId',\n topicid: 'topicId',\n token: 'tokenId',\n tokenid: 'tokenId',\n account: 'accountId',\n accountid: 'accountId',\n contract: 'contractId',\n contractid: 'contractId',\n file: 'fileId',\n fileid: 'fileId',\n schedule: 'scheduleId',\n scheduleid: 'scheduleId',\n };\n\n if (Object.prototype.hasOwnProperty.call(REGISTRY, key)) {\n return REGISTRY[key];\n }\n\n if (/^[a-z]+Id$/.test(raw)) {\n return raw;\n }\n\n return raw;\n }\n\n /**\n * Resolve entity references from natural language queries\n * @param query - Search query (entity name or natural language reference)\n * @param options - Resolution options for filtering and fuzzy matching\n * @returns Array of matching entity associations\n */\n resolveEntityReference(\n query: string,\n options: EntityResolutionOptions = {}\n ): EntityAssociation[] {\n try {\n if (!query || typeof query !== 'string') {\n return [];\n }\n\n const sanitizedQuery = query.trim();\n if (sanitizedQuery.length === 0) {\n return [];\n }\n\n if (sanitizedQuery.length > 200) {\n }\n\n const { entityType, limit = 10, fuzzyMatch = true } = options;\n\n const safeLimit = Math.max(1, Math.min(limit || 10, 100));\n\n const isEntityIdQuery = /^0\\.0\\.\\d+$/.test(sanitizedQuery);\n\n const searchResults = this._contentStorage.searchMessages(\n sanitizedQuery.substring(0, 200),\n {\n caseSensitive: false,\n limit: safeLimit * 2,\n }\n );\n\n const associations: EntityAssociation[] = [];\n\n for (const message of searchResults) {\n try {\n const content = message.content as string;\n if (\n content.includes(IS_ENTITY_ASSOCIATION_FLAG) ||\n content.includes('entityId')\n ) {\n const parsed = JSON.parse(content);\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (entityType && parsed.entityType !== entityType) {\n continue;\n }\n\n if (isEntityIdQuery) {\n if (parsed.entityId !== sanitizedQuery) {\n continue;\n }\n }\n\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch {\n continue;\n }\n }\n\n if (fuzzyMatch && associations.length === 0 && !isEntityIdQuery) {\n const fuzzyQueries = [\n query.toLowerCase(),\n `token`,\n `account`,\n entityType || '',\n ].filter(Boolean);\n\n for (const fuzzyQuery of fuzzyQueries) {\n if (fuzzyQuery === query.toLowerCase()) continue;\n\n const fuzzyResults = this._contentStorage.searchMessages(fuzzyQuery, {\n caseSensitive: false,\n limit: limit,\n });\n\n for (const message of fuzzyResults) {\n try {\n const content = message.content as string;\n if (content.includes(IS_ENTITY_ASSOCIATION_FLAG)) {\n const parsed = JSON.parse(content);\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (entityType && parsed.entityType !== entityType) {\n continue;\n }\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch {\n continue;\n }\n }\n }\n }\n\n const uniqueAssociations = associations\n .filter(\n (assoc, index, arr) =>\n arr.findIndex((a) => a.entityId === assoc.entityId) === index\n )\n .sort(\n (a, b) =>\n new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n );\n\n const results = uniqueAssociations.slice(0, safeLimit);\n\n return results;\n } catch (error) {\n this.logger.error('Failed to resolve entity reference', {\n query,\n options,\n error: error instanceof Error ? error.message : String(error),\n });\n return [];\n }\n }\n\n /**\n * Get all entity associations, optionally filtered by type\n * @param entityType - Optional filter by entity type\n * @returns Array of entity associations\n */\n getEntityAssociations(entityType?: string): EntityAssociation[] {\n try {\n const rawFilter = entityType ? entityType.trim() : undefined;\n const filterCanonical = rawFilter ? this.normalizeEntityType(rawFilter) : undefined;\n\n if (entityType && (!rawFilter || rawFilter.length === 0)) {\n return [];\n }\n\n const SEARCH_ANY_ENTITY = 'entityId';\n const searchQuery = filterCanonical || SEARCH_ANY_ENTITY;\n const searchResults = this._contentStorage.searchMessages(searchQuery, {\n caseSensitive: false,\n limit: 100,\n });\n\n const associations: EntityAssociation[] = [];\n\n for (const message of searchResults) {\n try {\n const content = message.content as string;\n if (content.includes(IS_ENTITY_ASSOCIATION_FLAG)) {\n const parsed = JSON.parse(content);\n\n if (parsed.entityId && parsed.entityName && parsed.entityType) {\n if (filterCanonical && parsed.entityType !== filterCanonical) {\n continue;\n }\n\n if (parsed.createdAt && typeof parsed.createdAt === 'string') {\n parsed.createdAt = new Date(parsed.createdAt);\n }\n\n associations.push(parsed as EntityAssociation);\n }\n }\n } catch (parseError) {\n this.logger.warn('Failed to parse entity association from message', {\n messageContent:\n typeof message.content === 'string'\n ? message.content.substring(0, 100)\n : 'non-string',\n error:\n parseError instanceof Error\n ? parseError.message\n : String(parseError),\n });\n continue;\n }\n }\n\n const mergedById = new Map<string, EntityAssociation>();\n const getTime = (d: Date | string): number =>\n d instanceof Date ? d.getTime() : new Date(d).getTime();\n\n for (const assoc of associations) {\n const existing = mergedById.get(assoc.entityId);\n if (!existing) {\n mergedById.set(assoc.entityId, assoc);\n continue;\n }\n\n const existingTime = getTime(existing.createdAt);\n const currentTime = getTime(assoc.createdAt);\n\n const preferCurrent =\n currentTime > existingTime ||\n (!!assoc.transactionId && !existing.transactionId);\n\n if (preferCurrent) {\n mergedById.set(assoc.entityId, {\n ...existing,\n ...assoc,\n });\n }\n }\n\n const results = Array.from(mergedById.values()).sort((a, b) =>\n getTime(b.createdAt) - getTime(a.createdAt)\n );\n\n return results;\n } catch (error) {\n this.logger.error('Failed to get entity associations', {\n entityType,\n error: error instanceof Error ? error.message : String(error),\n });\n return [];\n }\n }\n\n /**\n * Clean up resources and dispose of components\n */\n dispose(): void {\n this.memoryWindow.dispose();\n this._contentStorage.dispose();\n this.tokenCounter.dispose();\n }\n}\n","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { CallbackManagerForToolRun } from '@langchain/core/callbacks/manager';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport { FormGenerator } from '../forms/form-generator';\nimport type { FormMessage } from '../forms/types';\nimport { isFormValidatable } from '@hashgraphonline/standards-agent-kit';\n\nexport interface FormValidationConfig {\n requireAllFields?: boolean;\n skipFields?: string[];\n customValidation?: (input: unknown) => boolean;\n}\n\n/**\n * Generic wrapper for StructuredTools that intercepts execution to check for missing required fields\n * and generates forms when validation would benefit from user input.\n *\n * Tools can implement the FormValidatable interface to provide custom validation logic.\n * Otherwise, falls back to schema-based validation.\n */\nexport class FormValidatingToolWrapper<\n TSchema extends z.ZodObject<z.ZodRawShape, z.UnknownKeysParam, z.ZodTypeAny>\n> extends StructuredTool<TSchema> {\n private originalTool: StructuredTool<TSchema>;\n private formGenerator: FormGenerator;\n private validationConfig: FormValidationConfig;\n private logger: Logger;\n\n name: string;\n description: string;\n schema: TSchema;\n\n constructor(\n originalTool: StructuredTool<TSchema>,\n formGenerator: FormGenerator,\n config: FormValidationConfig = {}\n ) {\n super();\n this.originalTool = originalTool;\n this.formGenerator = formGenerator;\n this.validationConfig = config;\n this.logger = new Logger({ module: 'FormValidatingToolWrapper' });\n\n this.name = originalTool.name;\n this.description = originalTool.description;\n this.schema = originalTool.schema;\n \n this.logger.info(`🔧 FormValidatingToolWrapper created for tool: ${this.name}`, {\n originalToolName: originalTool.name,\n originalToolType: originalTool.constructor.name,\n wrapperType: this.constructor.name\n });\n }\n\n /**\n * Validate the input against the schema\n */\n private validateInput(input: Record<string, unknown>): { isValid: boolean; errors?: string[] } {\n try {\n this.schema.parse(input);\n return { isValid: true };\n } catch (error) {\n if (error instanceof z.ZodError) {\n const errors = error.errors\n .filter(err => {\n const fieldName = err.path[0] as string;\n return !this.validationConfig.skipFields?.includes(fieldName);\n })\n .map(err => `${err.path.join('.')}: ${err.message}`);\n return { isValid: false, errors };\n }\n return { isValid: false, errors: ['Validation failed'] };\n }\n }\n\n /**\n * Gets the shape keys from the schema if it's a ZodObject\n */\n private getSchemaShape(): string[] {\n if (this.isZodObject(this.schema)) {\n return Object.keys(this.schema.shape);\n }\n return [];\n }\n\n /**\n * Executes the wrapped tool's original implementation directly, bypassing wrapper logic.\n */\n public async executeOriginal(\n input: Record<string, unknown>,\n runManager?: CallbackManagerForToolRun\n ): Promise<string> {\n type CallableMethod = (\n args: Record<string, unknown>,\n runManager?: CallbackManagerForToolRun\n ) => Promise<string>;\n \n const tool = this.originalTool as unknown as Record<string, unknown>;\n \n if ('_call' in tool && typeof tool._call === 'function') {\n return (tool._call as CallableMethod)(input, runManager);\n }\n if ('call' in tool && typeof tool.call === 'function') {\n return (tool.call as CallableMethod)(input, runManager);\n }\n throw new Error('Original tool has no callable implementation');\n }\n\n /**\n * Provides access to the wrapped tool instance for executors that want to bypass the wrapper.\n */\n public getOriginalTool(): StructuredTool<TSchema> {\n return this.originalTool;\n }\n\n /**\n * Checks if tool implements FormValidatable method\n */\n private hasFormValidatableMethod<T>(\n tool: unknown,\n methodName: string\n ): tool is Record<string, T> {\n return (\n tool !== null &&\n typeof tool === 'object' &&\n methodName in tool &&\n typeof (tool as Record<string, unknown>)[methodName] === 'function'\n );\n }\n\n /**\n * Expose FormValidatable methods by delegating to the underlying tool when available.\n */\n public getFormSchema(): z.ZodSchema {\n if (this.hasFormValidatableMethod<() => z.ZodSchema>(this.originalTool, 'getFormSchema')) {\n return this.originalTool.getFormSchema();\n }\n return this.schema as z.ZodSchema;\n }\n\n public getEssentialFields(): string[] {\n if (this.hasFormValidatableMethod<() => string[]>(this.originalTool, 'getEssentialFields')) {\n return this.originalTool.getEssentialFields();\n }\n return [];\n }\n\n public isFieldEmpty(fieldName: string, value: unknown): boolean {\n if (this.hasFormValidatableMethod<(n: string, v: unknown) => boolean>(this.originalTool, 'isFieldEmpty')) {\n return this.originalTool.isFieldEmpty(fieldName, value);\n }\n if (value === undefined || value === null || value === '') {\n return true;\n }\n if (Array.isArray(value) && value.length === 0) {\n return true;\n }\n return false;\n }\n\n /**\n * Calculates which fields are missing from the input\n */\n private calculateMissingFields(\n input: Record<string, unknown>,\n isCustom: boolean\n ): Set<string> {\n const missingFields = new Set<string>();\n \n if (!isCustom) {\n return missingFields;\n }\n\n const essentialFields = this.getEssentialFields();\n for (const fieldName of essentialFields) {\n const value = input[fieldName];\n if (this.isFieldEmpty(fieldName, value)) {\n missingFields.add(fieldName);\n }\n }\n \n return missingFields;\n }\n\n /**\n * Creates a form message with optional JSON schema\n */\n private async createFormMessage(\n schema: z.ZodSchema,\n input: Record<string, unknown>,\n missingFields: Set<string>\n ): Promise<FormMessage> {\n let formMessage = await this.formGenerator.generateFormFromSchema(\n schema,\n input,\n {\n toolName: this.name,\n toolDescription: this.description\n },\n missingFields\n );\n\n if (this.isZodObject(schema)) {\n try {\n const { jsonSchema, uiSchema } = this.formGenerator.generateJsonSchemaForm(\n schema,\n input,\n missingFields\n );\n formMessage = {\n ...formMessage,\n jsonSchema,\n uiSchema\n };\n } catch (error) {\n this.logger.warn('Failed to generate JSON Schema for RJSF:', error);\n }\n }\n\n formMessage.partialInput = input;\n return formMessage;\n }\n\n /**\n * Type guard to check if a schema is a ZodObject\n */\n private isZodObject(schema: z.ZodSchema): schema is z.ZodObject<z.ZodRawShape> {\n const def = (schema as z.ZodType)._def as { typeName?: string };\n return !!(def && def.typeName === 'ZodObject');\n }\n\n /**\n * Check if we should generate a form for this tool invocation\n */\n private shouldGenerateForm(input: Record<string, unknown>): boolean {\n this.logger.info(`shouldGenerateForm called for ${this.name}/${this.originalTool.name}`, {\n input,\n hasCustomValidation: !!this.validationConfig.customValidation\n });\n\n if (this.validationConfig.customValidation) {\n const result = !this.validationConfig.customValidation(input);\n this.logger.info(`Custom validation result: ${result}`);\n return result;\n }\n\n if (isFormValidatable(this.originalTool)) {\n this.logger.info(`Tool ${this.originalTool.name} implements FormValidatable, using custom logic`);\n return this.originalTool.shouldGenerateForm(input);\n }\n\n this.logger.info(`Tool ${this.originalTool.name} using schema validation only`);\n const validation = this.validateInput(input);\n this.logger.info(`Schema validation for ${this.originalTool.name}:`, {\n isValid: validation.isValid,\n errors: validation.errors\n });\n return !validation.isValid;\n }\n\n /**\n * Checks if input has bypass flags that skip form generation\n */\n private hasFormBypassFlags(input: Record<string, unknown>): boolean {\n return (\n (input.__fromForm === true) ||\n (input.renderForm === false)\n );\n }\n\n /**\n * Override _call to intercept tool execution\n */\n protected async _call(\n input: z.infer<TSchema>,\n runManager?: CallbackManagerForToolRun\n ): Promise<string> {\n this.logger.info(`🚨🚨🚨 FormValidatingToolWrapper._call INTERCEPTING ${this.name} 🚨🚨🚨`, {\n input,\n inputKeys: Object.keys(input as Record<string, unknown>),\n schemaShape: this.getSchemaShape(),\n stackTrace: new Error().stack?.split('\\n').slice(0, 5)\n });\n\n const inputRecord = input as unknown as Record<string, unknown>;\n \n if (this.hasFormBypassFlags(inputRecord)) {\n this.logger.info('Bypassing form generation and executing original tool due to submission flags');\n return this.executeOriginal(inputRecord, runManager);\n }\n\n const shouldGenerate = this.shouldGenerateForm(input as Record<string, unknown>);\n this.logger.info(`FormValidatingToolWrapper decision for ${this.name}:`, {\n shouldGenerateForm: shouldGenerate,\n toolName: this.name,\n originalToolName: this.originalTool.name\n });\n\n if (shouldGenerate) {\n this.logger.info(`Generating form for incomplete input in ${this.name}`);\n\n try {\n const isCustom = isFormValidatable(this.originalTool);\n const schemaToUse = isCustom ? this.getFormSchema() : this.schema;\n const missingFields = this.calculateMissingFields(\n input as Record<string, unknown>,\n isCustom\n );\n\n const schemaFields = this.isZodObject(schemaToUse) \n ? Object.keys(schemaToUse.shape)\n : [];\n \n this.logger.info(`Using ${isCustom ? 'CUSTOM' : 'DEFAULT'} schema for form generation`, {\n toolName: this.originalTool.name,\n schemaType: schemaToUse.constructor?.name,\n schemaFields,\n isCustomSchema: isCustom\n });\n\n const formMessage = await this.createFormMessage(\n schemaToUse,\n input as Record<string, unknown>,\n missingFields\n );\n\n const result = {\n requiresForm: true,\n formMessage,\n message: `Please complete the form to provide the required information for ${this.name}.`\n };\n\n this.logger.info(`FormValidatingToolWrapper returning form result for ${this.name}`);\n return JSON.stringify(result);\n } catch (error) {\n this.logger.error('Failed to generate form:', error);\n }\n }\n\n this.logger.info(`FormValidatingToolWrapper passing through to original tool ${this.name}`);\n return this.executeOriginal(input as Record<string, unknown>, runManager);\n }\n\n}\n\n/**\n * Wrap a tool with form validation capabilities\n */\nexport function wrapToolWithFormValidation<TSchema extends z.ZodObject<z.ZodRawShape, z.UnknownKeysParam, z.ZodTypeAny>>(\n tool: StructuredTool<TSchema>,\n formGenerator: FormGenerator,\n config: FormValidationConfig = {}\n): FormValidatingToolWrapper<TSchema> {\n return new FormValidatingToolWrapper(tool, formGenerator, config);\n}","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport {\n FormValidatingToolWrapper,\n wrapToolWithFormValidation,\n} from '../langchain/form-validating-tool-wrapper';\nimport { FormGenerator } from '../forms/form-generator';\nimport {\n fieldGuidanceRegistry,\n} from '../forms/field-guidance-registry';\nimport type {\n ToolFieldConfiguration as FG_ToolFieldConfiguration,\n FieldGuidanceProvider as FG_FieldGuidanceProvider,\n} from '../forms/field-guidance-registry';\nimport { isFormValidatable } from '@hashgraphonline/standards-agent-kit';\n\n/**\n * Tool capabilities configuration for registry entries\n */\nexport interface ToolCapabilities {\n supportsFormValidation: boolean;\n requiresWrapper: boolean;\n priority: 'low' | 'medium' | 'high' | 'critical';\n category: 'core' | 'extension' | 'mcp';\n}\n\n/**\n * Entity resolution format preferences for tools\n */\nexport interface EntityResolutionPreferences {\n inscription?: 'hrl' | 'topicId' | 'metadata' | 'any';\n token?: 'tokenId' | 'address' | 'symbol' | 'any';\n nft?: 'serialNumber' | 'metadata' | 'hrl' | 'any';\n account?: 'accountId' | 'alias' | 'evmAddress' | 'any';\n}\n\n/**\n * Tool metadata for comprehensive tool information\n */\nexport interface ToolMetadata {\n name: string;\n version: string;\n category: ToolCapabilities['category'];\n description: string;\n capabilities: ToolCapabilities;\n dependencies: string[];\n schema: unknown;\n entityResolutionPreferences?: EntityResolutionPreferences;\n fieldGuidance?: FG_ToolFieldConfiguration;\n fieldGuidanceProvider?: FG_FieldGuidanceProvider;\n}\n\n/**\n * Registry entry containing tool instance and metadata\n */\nexport interface ToolRegistryEntry {\n tool: StructuredTool;\n metadata: ToolMetadata;\n wrapper?: FormValidatingToolWrapper<z.ZodObject<z.ZodRawShape>> | undefined;\n originalTool: StructuredTool;\n options?: {\n priority?: ToolCapabilities['priority'];\n capability?: string;\n enabled?: boolean;\n namespace?: string;\n };\n}\n\n/**\n * Options for tool registration\n */\nexport interface ToolRegistrationOptions {\n forceWrapper?: boolean;\n skipWrapper?: boolean;\n wrapperConfig?: {\n requireAllFields?: boolean;\n skipFields?: string[];\n };\n metadata?: Partial<ToolMetadata>;\n}\n\n/**\n * Query interface for finding tools\n */\nexport interface ToolQuery {\n name?: string;\n category?: ToolMetadata['category'];\n capabilities?: Partial<ToolCapabilities>;\n}\n\n/**\n * Centralized tool registry for managing tool lifecycle\n */\nexport class ToolRegistry {\n private tools = new Map<string, ToolRegistryEntry>();\n private formGenerator: FormGenerator;\n private logger: Logger;\n\n constructor(logger?: Logger) {\n this.formGenerator = new FormGenerator();\n this.logger = logger || new Logger({ module: 'ToolRegistry' });\n }\n\n /**\n * Register a tool with the registry\n */\n registerTool(\n tool: StructuredTool,\n options: ToolRegistrationOptions = {}\n ): void {\n const capabilities = this.analyzeToolCapabilities(tool);\n const metadata: ToolMetadata = {\n name: tool.name,\n version: '1.0.0',\n category: options.metadata?.category || 'core',\n description: tool.description,\n capabilities,\n dependencies: [],\n schema: tool.schema,\n ...options.metadata,\n };\n\n try {\n if (!metadata.entityResolutionPreferences) {\n const schemaRecord = tool.schema as unknown as Record<string, unknown>;\n const rawPrefs =\n schemaRecord &&\n typeof schemaRecord === 'object' &&\n (schemaRecord as Record<string, unknown>)[\n '_entityResolutionPreferences'\n ];\n if (rawPrefs && typeof rawPrefs === 'object') {\n metadata.entityResolutionPreferences = rawPrefs as unknown as EntityResolutionPreferences;\n }\n }\n } catch {\n }\n\n try {\n const schemaRecord = tool.schema as unknown as Record<string, unknown>;\n const schemaDef = (schemaRecord && (schemaRecord as Record<string, unknown>)._def) as\n | { typeName?: string; shape?: unknown }\n | undefined;\n if (schemaDef?.typeName === 'ZodObject') {\n const shape: Record<string, unknown> =\n typeof (schemaDef as { shape?: () => Record<string, unknown> }).shape === 'function'\n ? ((schemaDef as { shape: () => Record<string, unknown> }).shape?.() || {})\n : ((schemaDef as { shape?: Record<string, unknown> }).shape || {});\n\n const metadataField = shape['metadata'] as\n | { _def?: { typeName?: string; type?: { _def?: { typeName?: string } } } }\n | undefined;\n const isStringArray =\n !!metadataField &&\n metadataField._def?.typeName === 'ZodArray' &&\n metadataField._def?.type?._def?.typeName === 'ZodString';\n\n if (isStringArray && typeof tool.description === 'string') {\n if (!metadata.entityResolutionPreferences) {\n metadata.entityResolutionPreferences = {\n inscription: 'hrl',\n } as EntityResolutionPreferences;\n }\n const note =\n ' NOTE: When referencing inscriptions or media, provide canonical Hashlink Resource Locators (e.g., hcs://<standard>/<topicId>) rather than external URLs or embedded JSON.';\n if (!tool.description.includes('Hashlink Resource Locators')) {\n (tool as unknown as { description: string }).description = `${tool.description}${note}`;\n }\n }\n }\n } catch {}\n\n let finalTool: StructuredTool = tool;\n let wrapper:\n | FormValidatingToolWrapper<z.ZodObject<z.ZodRawShape>>\n | undefined;\n\n if (this.shouldWrapTool(tool, capabilities, options)) {\n wrapper = wrapToolWithFormValidation(\n tool as StructuredTool<z.ZodObject<z.ZodRawShape>>,\n this.formGenerator,\n {\n requireAllFields: false,\n skipFields: ['metaOptions'],\n ...options.wrapperConfig,\n }\n ) as FormValidatingToolWrapper<z.ZodObject<z.ZodRawShape>>;\n finalTool = wrapper as StructuredTool;\n }\n\n try {\n if (metadata.entityResolutionPreferences) {\n (finalTool as unknown as Record<string, unknown>)[\n 'entityResolutionPreferences'\n ] = metadata.entityResolutionPreferences;\n }\n } catch {\n }\n\n const entry: ToolRegistryEntry = {\n tool: finalTool,\n metadata,\n wrapper,\n originalTool: tool,\n options: {\n priority: capabilities.priority,\n capability: 'basic', // Default capability\n enabled: true, // All tools are enabled by default\n namespace: metadata.category,\n },\n };\n\n this.tools.set(tool.name, entry);\n\n try {\n const metaFG = metadata.fieldGuidance as FG_ToolFieldConfiguration | undefined;\n if (metaFG) {\n fieldGuidanceRegistry.registerToolConfiguration(metaFG);\n }\n const provider = metadata.fieldGuidanceProvider as FG_FieldGuidanceProvider | undefined;\n if (provider) {\n const pattern = metaFG?.toolPattern ?? tool.name;\n fieldGuidanceRegistry.registerToolProvider(pattern, provider, {\n id: `${tool.name}:field-guidance-provider`,\n priority: 0,\n });\n }\n } catch {}\n }\n\n /**\n * Get a tool by name\n */\n getTool(name: string): ToolRegistryEntry | null {\n return this.tools.get(name) || null;\n }\n\n /**\n * Get tools by capability\n */\n getToolsByCapability(\n capability: keyof ToolCapabilities,\n value?: unknown\n ): ToolRegistryEntry[] {\n const results: ToolRegistryEntry[] = [];\n\n for (const entry of this.tools.values()) {\n if (value !== undefined) {\n if (entry.metadata.capabilities[capability] === value) {\n results.push(entry);\n }\n } else if (entry.metadata.capabilities[capability]) {\n results.push(entry);\n }\n }\n\n return results;\n }\n\n /**\n * Get tools by query\n */\n getToolsByQuery(query: ToolQuery): ToolRegistryEntry[] {\n const results: ToolRegistryEntry[] = [];\n\n for (const entry of this.tools.values()) {\n let matches = true;\n\n if (query.name && entry.metadata.name !== query.name) {\n matches = false;\n }\n\n if (query.category && entry.metadata.category !== query.category) {\n matches = false;\n }\n\n if (query.capabilities) {\n for (const [key, value] of Object.entries(query.capabilities)) {\n if (\n entry.metadata.capabilities[key as keyof ToolCapabilities] !== value\n ) {\n matches = false;\n break;\n }\n }\n }\n\n if (matches) {\n results.push(entry);\n }\n }\n\n return results;\n }\n\n /**\n * Get all registered tools\n */\n getAllTools(): StructuredTool[] {\n return Array.from(this.tools.values()).map((entry) => entry.tool);\n }\n\n /**\n * Get all registry entries\n */\n getAllRegistryEntries(): ToolRegistryEntry[] {\n return Array.from(this.tools.values());\n }\n\n /**\n * Get all tool names\n */\n getToolNames(): string[] {\n return Array.from(this.tools.keys());\n }\n\n /**\n * Get tools by priority\n */\n getToolsByPriority(priority: ToolCapabilities['priority']): ToolRegistryEntry[] {\n return this.getToolsByCapability('priority', priority);\n }\n\n /**\n * Get enabled tools (all tools are considered enabled by default)\n */\n getEnabledTools(): ToolRegistryEntry[] {\n return this.getAllRegistryEntries();\n }\n\n /**\n * Get tools by namespace/category\n */\n getToolsByNamespace(namespace?: string): ToolRegistryEntry[] {\n if (!namespace) {\n return this.getAllRegistryEntries();\n }\n return this.getToolsByQuery({ category: namespace as ToolMetadata['category'] });\n }\n\n /**\n * Check if registry has capability\n */\n hasCapability(capability: keyof ToolCapabilities): boolean {\n for (const entry of this.tools.values()) {\n if (entry.metadata.capabilities[capability]) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Update tool options (metadata)\n */\n updateToolOptions(name: string, options: Partial<ToolMetadata>): boolean {\n const entry = this.tools.get(name);\n if (!entry) {\n return false;\n }\n\n entry.metadata = { ...entry.metadata, ...options };\n return true;\n }\n\n /**\n * Check if a tool is registered\n */\n hasTool(name: string): boolean {\n return this.tools.has(name);\n }\n\n /**\n * Unregister a tool\n */\n unregisterTool(name: string): boolean {\n return this.tools.delete(name);\n }\n\n /**\n * Clear all tools\n */\n clear(): void {\n this.tools.clear();\n }\n\n /**\n * Analyze tool capabilities\n */\n private analyzeToolCapabilities(tool: StructuredTool): ToolCapabilities {\n const implementsFormValidatable = isFormValidatable(tool);\n const hasRenderConfig = this.hasRenderConfig(tool);\n const isZodObjectLike = this.isZodObjectLike(tool.schema);\n\n const supportsFormValidation = implementsFormValidatable || hasRenderConfig;\n const requiresWrapper = supportsFormValidation && isZodObjectLike;\n\n let priority: ToolCapabilities['priority'] = 'medium';\n let category: ToolCapabilities['category'] = 'core';\n\n if (supportsFormValidation && requiresWrapper) {\n priority = 'critical';\n } else if (supportsFormValidation) {\n priority = 'high';\n } else if (\n tool.description?.toLowerCase().includes('query') ||\n tool.description?.toLowerCase().includes('search')\n ) {\n priority = 'low';\n }\n\n const toolAsAny = tool as unknown as Record<string, unknown>;\n if (tool.constructor.name.includes('MCP') || toolAsAny.isMCPTool) {\n category = 'mcp';\n } else if (\n toolAsAny.isExtension ||\n tool.constructor.name.includes('Extension')\n ) {\n category = 'extension';\n }\n\n return {\n supportsFormValidation,\n requiresWrapper,\n priority,\n category,\n };\n }\n\n /**\n * Check if tool has render configuration\n */\n private hasRenderConfig(tool: StructuredTool): boolean {\n const schema = tool.schema as Record<string, unknown>;\n return !!(schema && schema._renderConfig);\n }\n\n /**\n * Determine if tool should be wrapped\n */\n private shouldWrapTool(\n tool: StructuredTool,\n capabilities: ToolCapabilities,\n options: ToolRegistrationOptions\n ): boolean {\n if (options.skipWrapper) {\n return false;\n }\n\n if (options.forceWrapper) {\n return true;\n }\n\n return capabilities.requiresWrapper;\n }\n\n /**\n * Check if schema is ZodObject-like\n */\n private isZodObjectLike(schema: unknown): boolean {\n if (!schema || typeof schema !== 'object') {\n return false;\n }\n\n const schemaRecord = schema as Record<string, unknown>;\n const schemaDef = schemaRecord._def as Record<string, unknown> | undefined;\n\n return (\n schema instanceof z.ZodObject ||\n schemaDef?.typeName === 'ZodObject' ||\n ('shape' in schemaRecord && typeof schemaRecord.shape === 'object')\n );\n }\n\n /**\n * Get statistics about the registry\n */\n getStatistics(): {\n totalTools: number;\n wrappedTools: number;\n unwrappedTools: number;\n categoryCounts: Record<ToolCapabilities['category'], number>;\n priorityCounts: Record<ToolCapabilities['priority'], number>;\n } {\n const stats = {\n totalTools: this.tools.size,\n wrappedTools: 0,\n unwrappedTools: 0,\n categoryCounts: { core: 0, extension: 0, mcp: 0 } as Record<\n ToolCapabilities['category'],\n number\n >,\n priorityCounts: { low: 0, medium: 0, high: 0, critical: 0 } as Record<\n ToolCapabilities['priority'],\n number\n >,\n };\n\n for (const entry of this.tools.values()) {\n if (entry.wrapper) {\n stats.wrappedTools++;\n } else {\n stats.unwrappedTools++;\n }\n\n stats.categoryCounts[entry.metadata.category]++;\n stats.priorityCounts[entry.metadata.capabilities.priority]++;\n }\n\n return stats;\n }\n}\n","import { ZodError } from 'zod';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport { SmartMemoryManager } from '../memory/smart-memory-manager';\nimport { FormEngine, ToolExecutionResult } from '../forms/form-engine';\nimport type { FormMessage, FormSubmission } from '../forms/types';\nimport type { ToolRegistry, ToolRegistryEntry } from '../core/tool-registry';\n\n/**\n * Session context for tool execution\n */\nexport interface SessionContext {\n sessionId: string;\n userId?: string;\n timestamp: number;\n conversationId?: string;\n}\n\n/**\n * Context passed through execution pipeline\n */\nexport interface ExecutionContext {\n toolName: string;\n input: unknown;\n session: SessionContext;\n memory: SmartMemoryManager;\n traceId: string;\n toolEntry: ToolRegistryEntry;\n}\n\n/**\n * Result of tool execution with metadata\n */\nexport interface ExecutionResult extends ToolExecutionResult {\n traceId: string;\n executionTime: number;\n}\n\n/**\n * ExecutionPipeline handles tool execution coordination\n */\nexport class ExecutionPipeline {\n private logger: Logger;\n private toolRegistry: ToolRegistry;\n private formEngine: FormEngine;\n private memory: SmartMemoryManager;\n\n constructor(\n toolRegistry: ToolRegistry,\n formEngine: FormEngine,\n memory: SmartMemoryManager,\n logger?: Logger\n ) {\n this.toolRegistry = toolRegistry;\n this.formEngine = formEngine;\n this.memory = memory;\n this.logger = logger || new Logger({ module: 'ExecutionPipeline' });\n }\n\n /**\n * Execute a tool through the pipeline\n */\n async execute(\n toolName: string,\n input: unknown,\n sessionContext?: SessionContext\n ): Promise<ExecutionResult> {\n const traceId = `trace-${Date.now()}-${Math.random()\n .toString(36)\n .substr(2, 9)}`;\n const startTime = Date.now();\n\n const toolEntry = this.toolRegistry.getTool(toolName);\n if (!toolEntry) {\n throw new Error(`Tool not found in registry: ${toolName}`);\n }\n\n const context: ExecutionContext = {\n toolName,\n input,\n session: sessionContext || this.buildDefaultSession(),\n memory: this.memory,\n traceId,\n toolEntry,\n };\n\n try {\n const shouldGenerateForm = await this.checkFormGeneration(context);\n if (shouldGenerateForm.requiresForm && shouldGenerateForm.formMessage) {\n return {\n success: false,\n output: 'Form generation required',\n requiresForm: true,\n formMessage: shouldGenerateForm.formMessage,\n traceId,\n executionTime: Date.now() - startTime,\n };\n }\n\n const result = await this.executeToolDirect(context);\n\n return {\n success: true,\n output: result,\n traceId,\n executionTime: Date.now() - startTime,\n };\n } catch (error) {\n return this.handleExecutionError(\n error,\n context,\n traceId,\n Date.now() - startTime\n );\n }\n }\n\n /**\n * Execute tool with validation\n */\n async executeWithValidation(\n toolName: string,\n input: unknown,\n sessionContext?: SessionContext\n ): Promise<ExecutionResult> {\n return this.execute(toolName, input, sessionContext);\n }\n\n /**\n * Process form submission\n */\n async processFormSubmission(\n toolName: string,\n formId: string,\n parameters: Record<string, unknown>,\n sessionContext?: SessionContext\n ): Promise<ExecutionResult> {\n const traceId = `form-${Date.now()}-${Math.random()\n .toString(36)\n .substr(2, 9)}`;\n const startTime = Date.now();\n\n try {\n const formSubmission: FormSubmission = {\n formId,\n toolName,\n parameters,\n timestamp: Date.now(),\n };\n\n const processedInput = await this.formEngine.processSubmission(\n formSubmission\n );\n\n return this.execute(toolName, processedInput, sessionContext);\n } catch (error) {\n return {\n success: false,\n output: 'Form submission processing failed',\n error: error instanceof Error ? error.message : String(error),\n traceId,\n executionTime: Date.now() - startTime,\n };\n }\n }\n\n /**\n * Check if form generation is required\n */\n private async checkFormGeneration(context: ExecutionContext): Promise<{\n requiresForm: boolean;\n formMessage?: FormMessage;\n }> {\n const inputRecord = context.input as Record<string, unknown>;\n if (inputRecord?.__fromForm === true || inputRecord?.renderForm === false) {\n return { requiresForm: false };\n }\n\n if (\n !this.formEngine.shouldGenerateForm(context.toolEntry.tool, context.input)\n ) {\n return { requiresForm: false };\n }\n\n const formMessage = await this.formEngine.generateForm(\n context.toolName,\n context.toolEntry.tool,\n context.input\n );\n\n if (formMessage) {\n return { requiresForm: true, formMessage };\n }\n\n return { requiresForm: false };\n }\n\n /**\n * Execute tool directly\n */\n private async executeToolDirect(context: ExecutionContext): Promise<string> {\n const { toolEntry, input } = context;\n const parameters = (input as Record<string, unknown>) || {};\n const mergedArgs = { ...parameters, renderForm: false };\n\n if (toolEntry.wrapper) {\n return this.executeWrappedTool(toolEntry, mergedArgs);\n }\n\n return await toolEntry.tool.call(mergedArgs);\n }\n\n /**\n * Execute wrapped tool\n */\n private async executeWrappedTool(\n toolEntry: ToolRegistryEntry,\n mergedArgs: Record<string, unknown>\n ): Promise<string> {\n const wrapper = toolEntry.wrapper;\n if (!wrapper) {\n throw new Error('Tool wrapper not found');\n }\n\n const wrapperAsAny = wrapper as unknown as {\n executeOriginal?: (args: Record<string, unknown>) => Promise<string>;\n originalTool?: {\n call?: (args: Record<string, unknown>) => Promise<string>;\n };\n };\n\n if (wrapperAsAny.executeOriginal) {\n return await wrapperAsAny.executeOriginal(mergedArgs);\n }\n\n if (wrapperAsAny.originalTool?.call) {\n return await wrapperAsAny.originalTool.call(mergedArgs);\n }\n\n return await toolEntry.originalTool.call(mergedArgs);\n }\n\n /**\n * Handle execution error\n */\n private handleExecutionError(\n error: unknown,\n context: ExecutionContext,\n traceId: string,\n executionTime: number\n ): ExecutionResult {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (error instanceof ZodError) {\n return {\n success: false,\n output: 'Validation error occurred',\n error: errorMessage,\n traceId,\n executionTime,\n };\n }\n\n this.logger.error(`Tool execution failed: ${context.toolName}`, {\n traceId,\n error: errorMessage,\n });\n\n return {\n success: false,\n output: 'Tool execution failed',\n error: errorMessage,\n traceId,\n executionTime,\n };\n }\n\n /**\n * Build default session context\n */\n private buildDefaultSession(): SessionContext {\n return {\n sessionId: `session-${Date.now()}-${Math.random()\n .toString(36)\n .substr(2, 9)}`,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Get statistics about the pipeline\n */\n getStatistics(): {\n totalMiddleware: number;\n registeredMiddleware: string[];\n } {\n return {\n totalMiddleware: 0,\n registeredMiddleware: [],\n };\n }\n}\n","import type { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport type { StructuredTool } from '@langchain/core/tools';\nimport { createOpenAIToolsAgent } from 'langchain/agents';\nimport {\n FormAwareAgentExecutor,\n type ParameterPreprocessingCallback,\n} from './form-aware-agent-executor';\nimport {\n ChatPromptTemplate,\n MessagesPlaceholder,\n} from '@langchain/core/prompts';\nimport { ChatOpenAI } from '@langchain/openai';\nimport {\n calculateTokenCostSync,\n getAllHederaCorePlugins,\n HederaAgentKit,\n TokenUsageCallbackHandler,\n} from 'hedera-agent-kit';\nimport type { TokenUsage, CostCalculation } from 'hedera-agent-kit';\nimport {\n BaseAgent,\n type ConversationContext,\n type ChatResponse,\n type OperationalMode,\n type UsageStats,\n} from '../base-agent';\nimport { MCPClientManager } from '../mcp/mcp-client-manager';\nimport { convertMCPToolToLangChain } from '../mcp/adapters/langchain';\nimport { SmartMemoryManager } from '../memory/smart-memory-manager';\nimport type { MCPConnectionStatus, MCPServerConfig } from '../mcp/types';\nimport { ResponseFormatter } from '../utils/response-formatter';\nimport type { FormSubmission } from '../forms/types';\nimport type { ToolRegistrationOptions } from '../core/tool-registry';\nimport { ERROR_MESSAGES } from '../constants';\nimport {\n HumanMessage,\n AIMessage,\n SystemMessage,\n BaseMessage as _BaseMessage,\n} from '@langchain/core/messages';\nimport { ToolRegistry } from '../core/tool-registry';\nimport {\n ExecutionPipeline,\n SessionContext,\n} from '../execution/execution-pipeline';\nimport { FormEngine } from '../forms/form-engine';\nimport type { ChainValues } from '@langchain/core/utils/types';\n\ninterface RenderConfigSchema {\n _renderConfig?: Record<string, unknown>;\n}\n\ninterface ToolExecutionData {\n type: string;\n formId?: string;\n parameters?: Record<string, unknown>;\n toolName?: string;\n}\n\ninterface ToolWithOriginal {\n originalTool?: {\n call?: (args: Record<string, unknown>) => Promise<string>;\n };\n}\n\ninterface ExecutorWithRestore {\n restorePendingForms?: (p: Map<string, unknown>) => void;\n}\n\ninterface ResultWithToolName {\n toolName?: string;\n}\n\ninterface IntermediateStep {\n action?: {\n tool?: string;\n toolInput?: Record<string, unknown>;\n };\n observation?: unknown;\n}\n\ninterface HashLinkBlock {\n blockId: string;\n hashLink: string;\n template: string;\n attributes: Record<string, unknown>;\n}\n\ninterface MetadataWithHashLink {\n hashLinkBlock?: HashLinkBlock;\n memoryStats?: {\n activeMessages: number;\n tokenUsage: number;\n maxTokens: number;\n usagePercentage: number;\n };\n [key: string]: unknown;\n}\n\nfunction _isMetadataWithHashLink(\n metadata: unknown\n): metadata is MetadataWithHashLink {\n if (!metadata || typeof metadata !== 'object') {\n return false;\n }\n const meta = metadata as Record<string, unknown>;\n return 'hashLinkBlock' in meta || 'memoryStats' in meta;\n}\n\nfunction hasHashLinkBlock(\n metadata: unknown\n): metadata is { hashLinkBlock: HashLinkBlock } {\n if (!metadata || typeof metadata !== 'object') {\n return false;\n }\n const meta = metadata as Record<string, unknown>;\n if (\n !('hashLinkBlock' in meta) ||\n !meta.hashLinkBlock ||\n typeof meta.hashLinkBlock !== 'object'\n ) {\n return false;\n }\n const block = meta.hashLinkBlock as Record<string, unknown>;\n return (\n 'blockId' in block &&\n 'hashLink' in block &&\n 'template' in block &&\n 'attributes' in block &&\n typeof block.blockId === 'string' &&\n typeof block.hashLink === 'string' &&\n typeof block.template === 'string' &&\n typeof block.attributes === 'object'\n );\n}\n\nexport class LangChainAgent extends BaseAgent {\n private executor: FormAwareAgentExecutor | undefined;\n private systemMessage = '';\n private mcpManager?: MCPClientManager;\n private smartMemory: SmartMemoryManager | undefined;\n private mcpConnectionStatus: Map<string, MCPConnectionStatus> = new Map();\n private toolRegistry!: ToolRegistry;\n private executionPipeline!: ExecutionPipeline;\n private formEngine!: FormEngine;\n private addToolRawToMemory(name: string, payload: string): void {\n try {\n const content = `[tool-raw:${name}] ${payload}`;\n this.smartMemory!.addMessage(new SystemMessage(content));\n } catch {}\n }\n private persistToolRaw(toolName: string, output: unknown): void {\n try {\n let payload = '';\n if (typeof output === 'string') {\n payload = this.isJSON(output) ? output : JSON.stringify({ output });\n } else if (output !== undefined) {\n try {\n payload = JSON.stringify(output);\n } catch {\n payload = String(output);\n }\n } else {\n payload = JSON.stringify({ observation: null });\n }\n this.addToolRawToMemory(toolName, payload);\n } catch {}\n }\n private persistIntermediateSteps(\n steps: IntermediateStep[] | undefined\n ): void {\n if (!steps || !Array.isArray(steps)) {\n return;\n }\n try {\n for (const step of steps) {\n const name = step?.action?.tool || 'unknown';\n const obs = step?.observation;\n this.persistToolRaw(name, obs);\n }\n } catch {}\n }\n private pendingParameterPreprocessingCallback:\n | ParameterPreprocessingCallback\n | undefined;\n\n /**\n * Get inscription tool by capability instead of hardcoded name\n */\n private getInscriptionTool(): StructuredTool | null {\n const criticalTools = this.toolRegistry.getToolsByCapability(\n 'priority',\n 'critical'\n );\n\n for (const entry of criticalTools) {\n const tool = entry.tool;\n const name = tool.name.toLowerCase();\n const desc = tool.description?.toLowerCase() || '';\n\n if (\n name.includes('inscribe') ||\n name.includes('hashinal') ||\n desc.includes('inscribe') ||\n desc.includes('hashinal')\n ) {\n return tool;\n }\n }\n\n const allTools = this.toolRegistry.getAllRegistryEntries();\n for (const entry of allTools) {\n const tool = entry.tool;\n const name = tool.name.toLowerCase();\n const desc = tool.description?.toLowerCase() || '';\n\n if (\n name.includes('inscribe') ||\n name.includes('hashinal') ||\n desc.includes('inscribe') ||\n desc.includes('hashinal')\n ) {\n return tool;\n }\n }\n\n return null;\n }\n\n /**\n * Execute a tool directly with parameters, optionally using ExecutionPipeline\n */\n private async executeToolDirect(\n toolName: string,\n parameters: Record<string, unknown>,\n useExecutionPipeline = false\n ): Promise<string> {\n if (useExecutionPipeline && this.executionPipeline && this.smartMemory) {\n const sessionContext: SessionContext = {\n sessionId: `session-${Date.now()}`,\n timestamp: Date.now(),\n };\n\n const result = await this.executionPipeline.execute(\n toolName,\n parameters,\n sessionContext\n );\n\n if (!result.success) {\n throw new Error(result.error || 'Pipeline execution failed');\n }\n\n return result.output;\n }\n\n const entry = this.toolRegistry.getTool(toolName);\n if (!entry) {\n throw new Error(`Tool not found: ${toolName}`);\n }\n\n let processedParameters = { ...parameters };\n\n if (this.pendingParameterPreprocessingCallback) {\n this.logger.info(\n 'Applying parameter preprocessing in executeToolDirect',\n {\n toolName,\n hasCallback: true,\n parameterKeys: Object.keys(parameters),\n }\n );\n\n try {\n processedParameters = await this.pendingParameterPreprocessingCallback(\n toolName,\n parameters\n );\n\n if (\n JSON.stringify(processedParameters) !== JSON.stringify(parameters)\n ) {\n this.logger.info('Parameters preprocessed successfully', {\n toolName,\n originalKeys: Object.keys(parameters),\n processedKeys: Object.keys(processedParameters),\n changes: Object.keys(processedParameters).filter(\n (key) => processedParameters[key] !== parameters[key]\n ),\n });\n }\n } catch (error) {\n this.logger.warn(\n 'Parameter preprocessing failed, using original parameters',\n {\n toolName,\n error: error instanceof Error ? error.message : 'Unknown error',\n }\n );\n processedParameters = parameters;\n }\n }\n\n const mergedArgs = { ...processedParameters, renderForm: false };\n\n if (entry.wrapper) {\n const maybeWrapper = entry.tool as ToolWithOriginal;\n if (maybeWrapper.originalTool?.call) {\n return await maybeWrapper.originalTool.call(mergedArgs);\n }\n }\n\n return await entry.tool.call(mergedArgs);\n }\n\n /**\n * Create a standard ChatResponse from tool output\n */\n private createToolResponse(toolOutput: string): ChatResponse {\n return {\n output: toolOutput,\n message: toolOutput,\n notes: [],\n };\n }\n\n /**\n * Handle TOOL_EXECUTION format messages\n */\n private async handleToolExecution(\n message: string,\n context?: ConversationContext\n ): Promise<ChatResponse | null> {\n let isToolExecution = false;\n let toolExecutionData: ToolExecutionData | null = null;\n\n try {\n if (message.includes('TOOL_EXECUTION')) {\n const parsed = JSON.parse(message);\n if (parsed.type === 'TOOL_EXECUTION') {\n isToolExecution = true;\n toolExecutionData = parsed;\n }\n }\n } catch {}\n\n if (!isToolExecution || !toolExecutionData?.formId) {\n return null;\n }\n\n try {\n const params = (toolExecutionData.parameters || {}) as Record<\n string,\n unknown\n >;\n const toolName = toolExecutionData.toolName;\n\n if (toolName) {\n const toolOutput = await this.executeToolDirect(toolName, params);\n try {\n const payload = this.isJSON(toolOutput)\n ? toolOutput\n : JSON.stringify({ output: toolOutput });\n this.addToolRawToMemory(toolName, payload);\n } catch {}\n return this.createToolResponse(toolOutput);\n }\n } catch {}\n\n const formSubmission: FormSubmission = {\n formId: toolExecutionData.formId,\n toolName: toolExecutionData.toolName || '',\n parameters: toolExecutionData.parameters || {},\n timestamp: Date.now(),\n };\n\n if (\n this.executor &&\n 'processFormSubmission' in this.executor &&\n typeof this.executor.processFormSubmission === 'function'\n ) {\n return this.processFormSubmission(formSubmission, context);\n }\n\n return null;\n }\n\n /**\n * Handle direct tool execution commands\n */\n private async handleDirectToolExecution(\n message: string\n ): Promise<ChatResponse | null> {\n if (\n typeof message !== 'string' ||\n !message.includes('Please execute the following tool:')\n ) {\n return null;\n }\n\n try {\n const toolLineMatch = message.match(/Tool:\\s*(.+)/);\n const argsLineIndex = message.indexOf('Arguments:');\n\n if (toolLineMatch && argsLineIndex !== -1) {\n const toolName = toolLineMatch[1].trim();\n const argsText = message\n .slice(argsLineIndex + 'Arguments:'.length)\n .trim();\n\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(argsText);\n } catch {}\n\n const toolOutput = await this.executeToolDirect(toolName, args);\n try {\n const payload = this.isJSON(toolOutput)\n ? toolOutput\n : JSON.stringify({ output: toolOutput });\n this.addToolRawToMemory(toolName, payload);\n } catch {}\n return this.createToolResponse(toolOutput);\n }\n } catch {}\n\n return null;\n }\n\n /**\n * Handle JSON format tool calls and form submissions\n */\n private async handleJsonToolCalls(\n message: string,\n context?: ConversationContext\n ): Promise<ChatResponse | null> {\n if (typeof message !== 'string') {\n return null;\n }\n\n try {\n const trimmed = message.trim();\n if (\n !(trimmed.startsWith('{') && trimmed.endsWith('}')) &&\n !(trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n return null;\n }\n\n const obj = JSON.parse(trimmed) as Record<string, unknown>;\n const formId = obj['formId'] as string | undefined;\n const toolName = (obj['toolName'] as string) || '';\n const parameters = (obj['parameters'] as Record<string, unknown>) || {};\n\n if (\n formId &&\n this.executor &&\n 'processFormSubmission' in this.executor &&\n typeof this.executor.processFormSubmission === 'function'\n ) {\n return this.processFormSubmission(\n { formId, toolName, parameters, timestamp: Date.now() },\n context\n );\n }\n\n if (toolName) {\n const toolOutput = await this.executeToolDirect(toolName, parameters);\n try {\n const payload = this.isJSON(toolOutput)\n ? toolOutput\n : JSON.stringify({ output: toolOutput });\n this.addToolRawToMemory(toolName, payload);\n } catch {}\n return this.createToolResponse(toolOutput);\n }\n } catch {}\n\n return null;\n }\n\n /**\n * Handle content-ref messages for inscription tools\n */\n private async handleContentRefMessages(\n message: string\n ): Promise<ChatResponse | null> {\n if (typeof message !== 'string' || !message.includes('content-ref:')) {\n return null;\n }\n\n try {\n const tool = this.getInscriptionTool();\n if (!tool) {\n return null;\n }\n\n const idMatch =\n message.match(/content-ref:([A-Za-z0-9_\\-]+)/i) ||\n message.match(/content-ref:([^\\s)]+)/i);\n const contentRef =\n idMatch && idMatch[1]\n ? `content-ref:${idMatch[1]}`\n : message.match(/content-ref:[^\\s)]+/i)?.[0] || undefined;\n\n const args = contentRef\n ? ({ contentRef, renderForm: true, withHashLinkBlocks: true } as Record<\n string,\n unknown\n >)\n : ({ renderForm: true, withHashLinkBlocks: true } as Record<\n string,\n unknown\n >);\n\n const toolOutput = await tool.call(args);\n let parsed: Record<string, unknown> | undefined;\n\n try {\n parsed =\n typeof toolOutput === 'string'\n ? (JSON.parse(toolOutput) as Record<string, unknown>)\n : (toolOutput as Record<string, unknown>);\n } catch {}\n\n if (parsed && parsed['requiresForm'] && parsed['formMessage']) {\n const pending = new Map<\n string,\n {\n toolName: string;\n originalInput: Record<string, unknown>;\n originalToolInput?: Record<string, unknown>;\n schema: unknown;\n }\n >();\n\n const originalInput = {\n input: message,\n chat_history: this.smartMemory!.getMessages(),\n } as Record<string, unknown>;\n\n const formMessage = parsed['formMessage'] as { id: string };\n pending.set(formMessage.id, {\n toolName: tool.name,\n originalInput,\n originalToolInput: args,\n schema: null,\n });\n\n const maybeRestore = this.executor as ExecutorWithRestore;\n\n if (typeof maybeRestore.restorePendingForms === 'function') {\n maybeRestore.restorePendingForms!(pending);\n }\n\n const outputMsg =\n (parsed['message'] as string) ||\n 'Please complete the form to continue.';\n\n return {\n output: outputMsg,\n message: outputMsg,\n notes: [],\n requiresForm: true,\n formMessage: formMessage as ChatResponse['formMessage'],\n } as ChatResponse;\n }\n } catch {}\n\n return null;\n }\n\n /**\n * Process executor result and format response\n */\n private async processExecutorResult(\n result: ChainValues\n ): Promise<ChatResponse> {\n let outputStr = '';\n if (typeof result.output === 'string') {\n outputStr = result.output;\n } else if (result.output) {\n try {\n outputStr = JSON.stringify(result.output);\n } catch {\n outputStr = String(result.output);\n }\n }\n\n let response: ChatResponse = {\n output: outputStr,\n message: outputStr,\n notes: [],\n intermediateSteps: result.intermediateSteps,\n };\n\n if (result.requiresForm && result.formMessage) {\n response.formMessage = result.formMessage;\n response.requiresForm = true;\n }\n\n if (result.intermediateSteps && Array.isArray(result.intermediateSteps)) {\n const toolCalls = result.intermediateSteps.map(\n (step: IntermediateStep, index: number) => ({\n id: `call_${index}`,\n name: step.action?.tool || 'unknown',\n args: step.action?.toolInput || {},\n output:\n typeof step.observation === 'string'\n ? step.observation\n : JSON.stringify(step.observation),\n })\n );\n\n if (toolCalls.length > 0) {\n response.tool_calls = toolCalls;\n }\n\n this.persistIntermediateSteps(\n result.intermediateSteps as IntermediateStep[]\n );\n }\n\n const steps = (result?.intermediateSteps as IntermediateStep[]) || [];\n const lastJsonObservation = [...steps]\n .reverse()\n .find(\n (s) => typeof s?.observation === 'string' && this.isJSON(s.observation as string)\n )?.observation as string | undefined;\n\n if (lastJsonObservation) {\n try {\n const parsed = JSON.parse(lastJsonObservation);\n\n if (ResponseFormatter.isInscriptionResponse(parsed)) {\n const formattedMessage = ResponseFormatter.formatInscriptionResponse(parsed);\n response.output = formattedMessage;\n response.message = formattedMessage;\n if (parsed.inscription) {\n response.inscription = parsed.inscription;\n }\n if (parsed.metadata) {\n response.metadata = { ...response.metadata, ...parsed.metadata };\n }\n } else {\n if (typeof parsed.message === 'string' && parsed.message.trim().length > 0) {\n response.message = parsed.message;\n response.output = parsed.message;\n }\n if (parsed.success === true) {\n delete (response as { error?: string }).error;\n }\n if (typeof parsed.transactionBytes === 'string') {\n response.metadata = {\n ...response.metadata,\n transactionBytes: parsed.transactionBytes as string,\n };\n }\n if (typeof parsed.scheduleId === 'string') {\n (response as { scheduleId?: string }).scheduleId = parsed.scheduleId as string;\n }\n }\n\n const blockMetadata = this.processHashLinkBlocks(parsed);\n if (blockMetadata.hashLinkBlock) {\n response.metadata = { ...response.metadata, ...blockMetadata };\n }\n } catch (error) {\n this.logger.error('Error parsing intermediate steps:', error);\n }\n }\n\n\n if (!response.output || response.output.trim() === '') {\n response.output = 'Agent action complete.';\n }\n\n if (response.output) {\n this.smartMemory!.addMessage(new AIMessage(response.output));\n }\n\n if (this.tokenTracker) {\n const tokenUsage = this.tokenTracker.getLatestTokenUsage();\n if (tokenUsage) {\n response.tokenUsage = tokenUsage;\n response.cost = calculateTokenCostSync(tokenUsage);\n }\n }\n\n const finalMemoryStats = this.smartMemory!.getMemoryStats();\n response.metadata = {\n ...response.metadata,\n memoryStats: {\n activeMessages: finalMemoryStats.totalActiveMessages,\n tokenUsage: finalMemoryStats.currentTokenCount,\n maxTokens: finalMemoryStats.maxTokens,\n usagePercentage: finalMemoryStats.usagePercentage,\n },\n };\n\n this.logger.info('LangChainAgent.chat returning response:', response);\n return response;\n }\n\n /**\n * Normalize context messages into LangChain message instances and load into memory\n */\n /**\n * Loads context messages into memory, merging with existing messages\n */\n private loadContextMessages(context?: ConversationContext): void {\n if (\n !this.smartMemory ||\n !context?.messages ||\n context.messages.length === 0\n ) {\n return;\n }\n\n const existingMessages = this.smartMemory.getMessages();\n const existingContent = new Set(\n existingMessages.map((m) => `${m.constructor.name}:${m.content}`)\n );\n\n for (const msg of context.messages as unknown[]) {\n let messageClass:\n | typeof HumanMessage\n | typeof AIMessage\n | typeof SystemMessage;\n let content: string;\n\n if (\n msg instanceof HumanMessage ||\n msg instanceof AIMessage ||\n msg instanceof SystemMessage\n ) {\n messageClass = msg.constructor as\n | typeof HumanMessage\n | typeof AIMessage\n | typeof SystemMessage;\n content = msg.content as string;\n } else if (\n msg &&\n typeof msg === 'object' &&\n 'content' in msg &&\n 'type' in msg\n ) {\n content = String((msg as { content: unknown }).content);\n const type = String((msg as { type: unknown }).type);\n\n if (type === 'human') messageClass = HumanMessage;\n else if (type === 'ai') messageClass = AIMessage;\n else if (type === 'system') messageClass = SystemMessage;\n else continue;\n } else {\n continue;\n }\n\n const key = `${messageClass.name}:${content}`;\n if (!existingContent.has(key)) {\n this.smartMemory.addMessage(new messageClass(content));\n existingContent.add(key);\n }\n }\n }\n\n async boot(): Promise<void> {\n this.logger.info('🚨🚨🚨 LANGCHAIN AGENT BOOT METHOD CALLED 🚨🚨🚨');\n\n if (this.initialized) {\n this.logger.warn('Agent already initialized');\n return;\n }\n\n try {\n this.agentKit = await this.createAgentKit();\n await this.agentKit.initialize();\n\n const modelName =\n this.config.ai?.modelName ||\n process.env.OPENAI_MODEL_NAME ||\n 'gpt-4o-mini';\n try {\n if (typeof (TokenUsageCallbackHandler as unknown as { new (m: string): unknown }) === 'function') {\n this.tokenTracker = new TokenUsageCallbackHandler(modelName);\n } else {\n this.logger.warn('TokenUsageCallbackHandler unavailable or not a constructor; skipping token tracking');\n }\n } catch {\n this.logger.warn('TokenUsageCallbackHandler threw; skipping token tracking');\n }\n\n this.toolRegistry = new ToolRegistry(this.logger);\n\n const allTools = this.agentKit.getAggregatedLangChainTools();\n this.logger.info('=== TOOL REGISTRATION START ===');\n this.logger.info(\n 'All tools from agentKit:',\n allTools.map((t) => t.name)\n );\n\n const filteredTools = this.filterTools(allTools);\n this.logger.info(\n 'Filtered tools for registration:',\n filteredTools.map((t) => t.name)\n );\n\n for (const tool of filteredTools) {\n this.logger.info(`🔧 Registering tool: ${tool.name}`);\n\n const options: ToolRegistrationOptions = {};\n\n const name = tool.name.toLowerCase();\n const desc = tool.description?.toLowerCase() || '';\n\n if (tool.name === 'hedera-hts-mint-nft') {\n const originalCall = tool.call.bind(tool);\n tool.call = async (args: Record<string, unknown>) => {\n if (args.metaOptions && typeof args.metaOptions === 'object') {\n const metaOptions = args.metaOptions as Record<string, unknown>;\n if (metaOptions.transactionMemo) {\n this.logger.warn(\n '🚨 WORKAROUND: Stripping transactionMemo from hedera-hts-mint-nft to avoid bug',\n { originalMemo: metaOptions.transactionMemo }\n );\n delete metaOptions.transactionMemo;\n }\n }\n return originalCall(args);\n };\n }\n\n if (\n name.includes('inscribe') ||\n name.includes('hashinal') ||\n desc.includes('inscribe') ||\n desc.includes('hashinal')\n ) {\n options.forceWrapper = true;\n options.metadata = {\n category: 'core' as const,\n version: '1.0.0',\n dependencies: [],\n };\n\n this.logger.info(`🎯 CRITICAL TOOL DEBUG - ${tool.name} schema:`, {\n hasSchema: !!tool.schema,\n schemaType: tool.schema?.constructor?.name,\n hasRenderConfig: !!(tool.schema as RenderConfigSchema)\n ?._renderConfig,\n renderConfig: (tool.schema as RenderConfigSchema)?._renderConfig,\n });\n }\n\n this.toolRegistry.registerTool(tool, options);\n }\n\n this.tools = this.toolRegistry.getAllTools();\n\n this.logger.info(`🚀 TOOLS REGISTERED: ${this.tools.length} tools`);\n\n const stats = this.toolRegistry.getStatistics();\n this.logger.info('📊 Tool Registry Statistics:', {\n total: stats.totalTools,\n wrapped: stats.wrappedTools,\n unwrapped: stats.unwrappedTools,\n categories: stats.categoryCounts,\n priorities: stats.priorityCounts,\n });\n\n const inscriptionTool = this.getInscriptionTool();\n if (inscriptionTool) {\n const entry = this.toolRegistry.getTool(inscriptionTool.name);\n if (entry) {\n this.logger.info(\n `✅ Inscription tool registered: ${inscriptionTool.name}`\n );\n }\n }\n\n const toolNames = this.toolRegistry.getToolNames();\n const uniqueNames = new Set(toolNames);\n if (toolNames.length !== uniqueNames.size) {\n this.logger.error('DUPLICATE TOOL NAMES DETECTED in registry!');\n const duplicates = toolNames.filter(\n (name, index) => toolNames.indexOf(name) !== index\n );\n throw new Error(\n `Duplicate tool names detected: ${duplicates.join(', ')}`\n );\n }\n\n if (this.config.mcp?.servers && this.config.mcp.servers.length > 0) {\n if (this.config.mcp.autoConnect !== false) {\n await this.initializeMCP();\n } else {\n this.logger.info(\n 'MCP servers configured but autoConnect=false, skipping synchronous connection'\n );\n this.mcpManager = new MCPClientManager(this.logger);\n }\n }\n\n this.smartMemory = new SmartMemoryManager({\n modelName,\n maxTokens: 90000,\n reserveTokens: 10000,\n storageLimit: 1000,\n });\n\n this.logger.info('SmartMemoryManager initialized:', {\n modelName,\n toolsCount: this.tools.length,\n maxTokens: 90000,\n reserveTokens: 10000,\n });\n\n this.formEngine = new FormEngine(this.logger);\n\n this.executionPipeline = new ExecutionPipeline(\n this.toolRegistry,\n this.formEngine,\n this.smartMemory,\n this.logger\n );\n\n this.systemMessage = this.buildSystemPrompt();\n\n this.smartMemory.setSystemPrompt(this.systemMessage);\n\n await this.createExecutor();\n\n this.initialized = true;\n this.logger.info('LangChain Hedera agent initialized with ToolRegistry');\n } catch (error) {\n this.logger.error('Failed to initialize agent:', error);\n throw error;\n }\n }\n\n async chat(\n message: string,\n context?: ConversationContext\n ): Promise<ChatResponse> {\n if (!this.initialized || !this.executor || !this.smartMemory) {\n throw new Error('Agent not initialized. Call boot() first.');\n }\n\n try {\n const toolExecutionResult = await this.handleToolExecution(\n message,\n context\n );\n if (toolExecutionResult) {\n return toolExecutionResult;\n }\n\n const directToolResult = await this.handleDirectToolExecution(message);\n if (directToolResult) {\n return directToolResult;\n }\n\n const jsonToolResult = await this.handleJsonToolCalls(message, context);\n if (jsonToolResult) {\n return jsonToolResult;\n }\n\n const contentRefResult = await this.handleContentRefMessages(message);\n if (contentRefResult) {\n return contentRefResult;\n }\n\n this.logger.info('LangChainAgent.chat called with:', {\n message,\n contextLength: context?.messages?.length || 0,\n });\n\n this.loadContextMessages(context);\n this.smartMemory.addMessage(new HumanMessage(message));\n\n const memoryStats = this.smartMemory.getMemoryStats();\n this.logger.info('Memory stats before execution:', {\n totalMessages: memoryStats.totalActiveMessages,\n currentTokens: memoryStats.currentTokenCount,\n maxTokens: memoryStats.maxTokens,\n usagePercentage: memoryStats.usagePercentage,\n toolsCount: this.tools.length,\n });\n\n const currentMessages = this.smartMemory.getMessages();\n this.logger.info('Current messages in memory:', {\n count: currentMessages.length,\n });\n try {\n const instr = currentMessages\n .map((m) => String((m as { content: unknown }).content || ''))\n .filter(\n (c) =>\n typeof c === 'string' &&\n (c.includes('[instruction:') || c.includes('[tool-next-steps:'))\n );\n if (instr.length > 0) {\n this.logger.info('Instruction/next-steps messages in memory:', {\n messages: instr,\n });\n }\n } catch {}\n\n const result = await this.executor.invoke({\n input: message,\n chat_history: currentMessages,\n });\n\n this.logger.info('LangChainAgent executor result:', result);\n\n return this.processExecutorResult(result);\n } catch (error) {\n this.logger.error('LangChainAgent.chat error:', error);\n return this.handleError(error);\n }\n }\n\n async shutdown(): Promise<void> {\n if (this.mcpManager) {\n await this.mcpManager.disconnectAll();\n }\n\n if (this.smartMemory) {\n this.smartMemory.dispose();\n this.smartMemory = undefined;\n }\n\n if (this.toolRegistry) {\n this.toolRegistry.clear();\n }\n\n this.executor = undefined;\n this.agentKit = undefined;\n this.tools = [];\n this.initialized = false;\n this.logger.info('Agent cleaned up');\n }\n\n switchMode(mode: OperationalMode): void {\n if (this.config.execution) {\n this.config.execution.operationalMode = mode;\n } else {\n this.config.execution = { operationalMode: mode };\n }\n\n if (this.agentKit) {\n this.agentKit.operationalMode = mode;\n }\n\n this.systemMessage = this.buildSystemPrompt();\n this.logger.info(`Operational mode switched to: ${mode}`);\n }\n\n getUsageStats(): UsageStats {\n if (!this.tokenTracker) {\n return {\n promptTokens: 0,\n completionTokens: 0,\n totalTokens: 0,\n cost: { totalCost: 0 } as CostCalculation,\n };\n }\n\n const usage = this.tokenTracker.getTotalTokenUsage();\n const cost = calculateTokenCostSync(usage);\n return { ...usage, cost };\n }\n\n getUsageLog(): UsageStats[] {\n if (!this.tokenTracker) {\n return [];\n }\n\n return this.tokenTracker.getTokenUsageHistory().map((usage) => ({\n ...usage,\n cost: calculateTokenCostSync(usage),\n }));\n }\n\n clearUsageStats(): void {\n if (this.tokenTracker) {\n this.tokenTracker.reset();\n this.logger.info('Usage statistics cleared');\n }\n }\n\n getMCPConnectionStatus(): Map<string, MCPConnectionStatus> {\n return new Map(this.mcpConnectionStatus);\n }\n\n /**\n * Processes form submission and continues with tool execution\n */\n async processFormSubmission(\n submission: FormSubmission,\n context?: ConversationContext\n ): Promise<ChatResponse> {\n if (!this.initialized || !this.executor || !this.smartMemory) {\n throw new Error('Agent not initialized. Call boot() first.');\n }\n\n try {\n if (!submission.parameters || typeof submission.parameters !== 'object') {\n this.logger.error('Invalid form submission parameters:', {\n parameters: submission.parameters,\n type: typeof submission.parameters,\n });\n const errorInfo = JSON.stringify(submission, null, 2);\n return this.handleError(\n new Error(`Invalid form submission parameters: ${errorInfo}`)\n );\n }\n\n this.loadContextMessages(context);\n\n const safeSubmission = {\n ...submission,\n parameters: submission.parameters || {},\n };\n\n const result = await this.executor.processFormSubmission(safeSubmission);\n\n const preservedMetadata = result?.metadata ? { ...result.metadata } : {};\n\n try {\n const maybeRaw = (\n result as unknown as {\n rawToolOutput?: string;\n toolName?: string;\n }\n ).rawToolOutput;\n const toolName = (result as ResultWithToolName).toolName || 'unknown';\n if (typeof maybeRaw === 'string' && maybeRaw.trim().length > 0) {\n const payload = this.isJSON(maybeRaw)\n ? maybeRaw\n : JSON.stringify({ output: maybeRaw });\n this.addToolRawToMemory(toolName, payload);\n }\n } catch {}\n\n let outputMessage = 'Form processed successfully.';\n if (typeof result.output === 'string') {\n outputMessage = result.output;\n } else if (result.output) {\n try {\n outputMessage = JSON.stringify(result.output);\n } catch {\n outputMessage = String(result.output);\n }\n }\n\n let response: ChatResponse = {\n output: outputMessage,\n message: outputMessage,\n notes: [],\n intermediateSteps: result.intermediateSteps as IntermediateStep[],\n };\n\n if (result.metadata) {\n response.metadata = {\n ...response.metadata,\n ...result.metadata,\n };\n this.logger.info('🔍 DEBUG: Metadata after merge from result:', {\n hasMetadata: !!response.metadata,\n metadataKeys: response.metadata ? Object.keys(response.metadata) : [],\n hasHashLinkBlock: hasHashLinkBlock(response.metadata),\n hashLinkBlockContent: hasHashLinkBlock(response.metadata)\n ? response.metadata.hashLinkBlock\n : undefined,\n });\n }\n\n if (result.requiresForm && result.formMessage) {\n response.formMessage = result.formMessage;\n response.requiresForm = true;\n }\n\n if (result.intermediateSteps && Array.isArray(result.intermediateSteps)) {\n const toolCalls = result.intermediateSteps.map(\n (step: IntermediateStep, index: number) => {\n const name = step?.action?.tool || 'unknown';\n const args = step?.action?.toolInput || {};\n const obs = step?.observation;\n let output = '';\n if (typeof obs === 'string') {\n output = obs;\n } else if (obs && typeof obs === 'object') {\n try {\n output = JSON.stringify(obs);\n } catch {\n output = String(obs);\n }\n } else if (obs !== undefined) {\n output = String(obs);\n }\n return { id: `call_${index}`, name, args, output };\n }\n );\n if (toolCalls.length > 0) {\n response.tool_calls = toolCalls;\n }\n this.persistIntermediateSteps(\n result.intermediateSteps as IntermediateStep[]\n );\n }\n\n const parsedSteps = result?.intermediateSteps?.[0]?.observation;\n if (\n parsedSteps &&\n typeof parsedSteps === 'string' &&\n this.isJSON(parsedSteps)\n ) {\n try {\n const parsed = JSON.parse(parsedSteps);\n response = { ...response, ...parsed };\n\n const blockMetadata = this.processHashLinkBlocks(parsed);\n if (blockMetadata.hashLinkBlock) {\n response.metadata = {\n ...response.metadata,\n ...blockMetadata,\n };\n }\n } catch (error) {\n this.logger.error('Error parsing intermediate steps:', error);\n }\n }\n\n if (response.output) {\n this.smartMemory.addMessage(new AIMessage(response.output));\n }\n\n if (this.tokenTracker) {\n const tokenUsage = this.tokenTracker.getLatestTokenUsage();\n if (tokenUsage) {\n response.tokenUsage = tokenUsage;\n response.cost = calculateTokenCostSync(tokenUsage);\n }\n }\n\n const finalMemoryStats = this.smartMemory.getMemoryStats();\n this.logger.info('🔍 DEBUG: Metadata before memoryStats merge:', {\n hasMetadata: !!response.metadata,\n metadataKeys: response.metadata ? Object.keys(response.metadata) : [],\n hasHashLinkBlock: hasHashLinkBlock(response.metadata),\n });\n\n response.metadata = {\n ...preservedMetadata,\n ...response.metadata,\n memoryStats: {\n activeMessages: finalMemoryStats.totalActiveMessages,\n tokenUsage: finalMemoryStats.currentTokenCount,\n maxTokens: finalMemoryStats.maxTokens,\n usagePercentage: finalMemoryStats.usagePercentage,\n },\n };\n\n this.logger.info('🔍 DEBUG: Final response metadata before return:', {\n hasMetadata: !!response.metadata,\n metadataKeys: response.metadata ? Object.keys(response.metadata) : [],\n hasHashLinkBlock: hasHashLinkBlock(response.metadata),\n fullMetadata: response.metadata,\n });\n\n if (\n hasHashLinkBlock(preservedMetadata) &&\n !hasHashLinkBlock(response.metadata)\n ) {\n this.logger.error(\n '❌ CRITICAL: HashLink metadata was lost during processing!'\n );\n this.logger.error(\n 'Original metadata had hashLinkBlock:',\n preservedMetadata.hashLinkBlock\n );\n this.logger.error('Final metadata missing hashLinkBlock');\n }\n\n return response;\n } catch (error) {\n this.logger.error('Form submission processing error:', error);\n return this.handleError(error);\n }\n }\n\n /**\n * Check if the agent has pending forms that need to be completed\n */\n hasPendingForms(): boolean {\n return this.executor ? this.executor.hasPendingForms() : false;\n }\n\n /**\n * Get information about pending forms\n */\n getPendingFormsInfo(): Array<{ formId: string; toolName: string }> {\n return this.executor ? this.executor.getPendingFormsInfo() : [];\n }\n\n private async createAgentKit(): Promise<HederaAgentKit> {\n const corePlugins = getAllHederaCorePlugins();\n const extensionPlugins = this.config.extensions?.plugins || [];\n const plugins = [...corePlugins, ...extensionPlugins];\n\n const operationalMode =\n this.config.execution?.operationalMode || 'returnBytes';\n const modelName = this.config.ai?.modelName || 'gpt-4o';\n\n return new HederaAgentKit(\n this.config.signer,\n { plugins },\n operationalMode,\n this.config.execution?.userAccountId,\n this.config.execution?.scheduleUserTransactionsInBytesMode ?? false,\n undefined,\n modelName,\n this.config.extensions?.mirrorConfig,\n this.config.debug?.silent ?? false\n );\n }\n\n private async createExecutor(): Promise<void> {\n const existingPendingForms = this.executor?.getPendingForms() || new Map();\n\n let llm: BaseChatModel;\n if (this.config.ai?.provider && this.config.ai.provider.getModel) {\n llm = this.config.ai.provider.getModel() as BaseChatModel;\n } else if (this.config.ai?.llm) {\n llm = this.config.ai.llm as BaseChatModel;\n } else {\n const apiKey = this.config.ai?.apiKey || process.env.OPENAI_API_KEY;\n if (!apiKey) {\n throw new Error('OpenAI API key required');\n }\n\n const modelName = this.config.ai?.modelName || 'gpt-4o-mini';\n const isGPT5Model =\n modelName.toLowerCase().includes('gpt-5') ||\n modelName.toLowerCase().includes('gpt5');\n\n llm = new ChatOpenAI({\n apiKey,\n modelName,\n callbacks: this.tokenTracker ? [this.tokenTracker] : [],\n ...(isGPT5Model ? { temperature: 1 } : {}),\n });\n }\n\n const prompt = ChatPromptTemplate.fromMessages([\n ['system', this.systemMessage],\n new MessagesPlaceholder('chat_history'),\n ['human', '{input}'],\n new MessagesPlaceholder('agent_scratchpad'),\n ]);\n\n const langchainTools = this.tools as StructuredTool[];\n\n const inscriptionTool = this.getInscriptionTool();\n if (inscriptionTool) {\n const entry = this.toolRegistry.getTool(inscriptionTool.name);\n if (entry) {\n this.logger.info(\n `✅ Inscription tool registered: ${inscriptionTool.name}`\n );\n }\n }\n\n const stats = this.toolRegistry.getStatistics();\n this.logger.info('🛡️ TOOL SECURITY REPORT:', {\n totalTools: stats.totalTools,\n wrappedTools: stats.wrappedTools,\n unwrappedTools: stats.unwrappedTools,\n categories: stats.categoryCounts,\n priorities: stats.priorityCounts,\n });\n\n this.logger.info(\n `📊 Tool Security Summary: ${stats.wrappedTools} wrapped, ${stats.unwrappedTools} unwrapped`\n );\n\n const agent = await createOpenAIToolsAgent({\n llm,\n tools: langchainTools,\n prompt,\n });\n\n this.executor = new FormAwareAgentExecutor({\n agent,\n tools: langchainTools,\n verbose: this.config.debug?.verbose ?? false,\n returnIntermediateSteps: true,\n });\n\n if (this.pendingParameterPreprocessingCallback) {\n this.executor.setParameterPreprocessingCallback(\n this.pendingParameterPreprocessingCallback\n );\n this.logger.info(\n 'Parameter preprocessing callback re-applied to new executor',\n { hasCallback: true }\n );\n }\n\n if (existingPendingForms.size > 0) {\n this.logger.info(\n `Restoring ${existingPendingForms.size} pending forms to new executor`\n );\n this.executor.restorePendingForms(existingPendingForms);\n }\n\n this.logger.info('FormAwareAgentExecutor initialization complete');\n }\n\n /**\n * Set parameter preprocessing callback for tool parameter format conversion\n */\n setParameterPreprocessingCallback(\n callback: ParameterPreprocessingCallback | undefined\n ): void {\n this.pendingParameterPreprocessingCallback = callback;\n if (this.executor) {\n this.executor.setParameterPreprocessingCallback(callback);\n this.logger.info('Parameter preprocessing callback configured', {\n hasCallback: !!callback,\n });\n } else {\n this.logger.warn(\n 'Cannot set parameter preprocessing callback: executor not initialized'\n );\n }\n }\n\n private handleError(error: unknown): ChatResponse {\n const errorMessage =\n error instanceof Error ? error.message : 'Unknown error';\n this.logger.error('Chat error:', error);\n\n let tokenUsage: TokenUsage | undefined;\n let cost: CostCalculation | undefined;\n\n if (this.tokenTracker) {\n tokenUsage = this.tokenTracker.getLatestTokenUsage();\n if (tokenUsage) {\n cost = calculateTokenCostSync(tokenUsage);\n }\n }\n\n let userFriendlyMessage = errorMessage;\n let userFriendlyOutput = errorMessage;\n\n if (errorMessage.includes('429')) {\n if (errorMessage.includes('quota')) {\n userFriendlyMessage =\n 'API quota exceeded. Please check your OpenAI billing and usage limits.';\n userFriendlyOutput =\n \"I'm currently unable to respond because the API quota has been exceeded. Please check your OpenAI account billing and usage limits, then try again.\";\n } else {\n userFriendlyMessage = ERROR_MESSAGES.TOO_MANY_REQUESTS;\n userFriendlyOutput = ERROR_MESSAGES.RATE_LIMITED;\n }\n } else if (\n errorMessage.includes('401') ||\n errorMessage.includes('unauthorized')\n ) {\n userFriendlyMessage =\n 'API authentication failed. Please check your API key configuration.';\n userFriendlyOutput =\n \"There's an issue with the API authentication. Please check your OpenAI API key configuration in settings.\";\n } else if (errorMessage.includes('timeout')) {\n userFriendlyMessage = 'Request timed out. Please try again.';\n userFriendlyOutput =\n 'The request took too long to process. Please try again.';\n } else if (\n errorMessage.includes('network') ||\n errorMessage.includes('fetch')\n ) {\n userFriendlyMessage =\n 'Network error. Please check your internet connection and try again.';\n userFriendlyOutput =\n 'There was a network error. Please check your internet connection and try again.';\n } else if (errorMessage.includes('400')) {\n userFriendlyMessage = errorMessage;\n userFriendlyOutput = errorMessage;\n }\n\n const errorResponse: ChatResponse = {\n output: userFriendlyOutput,\n message: userFriendlyMessage,\n error: errorMessage,\n notes: [],\n };\n\n if (tokenUsage) {\n errorResponse.tokenUsage = tokenUsage;\n }\n\n if (cost) {\n errorResponse.cost = cost;\n }\n\n return errorResponse;\n }\n\n private async initializeMCP(): Promise<void> {\n this.mcpManager = new MCPClientManager(this.logger);\n\n for (const serverConfig of this.config.mcp!.servers!) {\n if (serverConfig.autoConnect === false) {\n this.logger.info(\n `Skipping MCP server ${serverConfig.name} (autoConnect=false)`\n );\n continue;\n }\n\n const status = await this.mcpManager.connectServer(serverConfig);\n\n if (status.connected) {\n this.logger.info(\n `Connected to MCP server ${status.serverName} with ${status.tools.length} tools`\n );\n\n for (const mcpTool of status.tools) {\n const langchainTool = convertMCPToolToLangChain(\n mcpTool,\n this.mcpManager,\n serverConfig\n );\n\n this.toolRegistry.registerTool(langchainTool, {\n metadata: {\n category: 'mcp',\n version: '1.0.0',\n dependencies: [serverConfig.name],\n },\n });\n }\n\n this.tools = this.toolRegistry.getAllTools();\n } else {\n this.logger.error(\n `Failed to connect to MCP server ${status.serverName}: ${status.error}`\n );\n }\n }\n }\n\n /**\n * Connect to MCP servers asynchronously after agent boot with background timeout pattern\n */\n async connectMCPServers(): Promise<void> {\n if (!this.config.mcp?.servers || this.config.mcp.servers.length === 0) {\n return;\n }\n\n if (!this.mcpManager) {\n this.mcpManager = new MCPClientManager(this.logger);\n }\n\n this.logger.info(\n `Starting background MCP server connections for ${this.config.mcp.servers.length} servers...`\n );\n\n this.config.mcp.servers.forEach((serverConfig) => {\n this.connectServerInBackground(serverConfig);\n });\n\n this.logger.info('MCP server connections initiated in background');\n }\n\n /**\n * Connect to a single MCP server in background with timeout\n */\n private connectServerInBackground(serverConfig: MCPServerConfig): void {\n const serverName = serverConfig.name;\n\n setTimeout(async () => {\n try {\n this.logger.info(`Background connecting to MCP server: ${serverName}`);\n\n const status = await this.mcpManager!.connectServer(serverConfig);\n this.mcpConnectionStatus.set(serverName, status);\n\n if (status.connected) {\n this.logger.info(\n `Successfully connected to MCP server ${status.serverName} with ${status.tools.length} tools`\n );\n\n for (const mcpTool of status.tools) {\n const langchainTool = convertMCPToolToLangChain(\n mcpTool,\n this.mcpManager!,\n serverConfig\n );\n\n this.toolRegistry.registerTool(langchainTool, {\n metadata: {\n category: 'mcp',\n version: '1.0.0',\n dependencies: [serverConfig.name],\n },\n });\n }\n\n this.tools = this.toolRegistry.getAllTools();\n\n if (this.initialized && this.executor) {\n this.logger.info(\n `Recreating executor with ${this.tools.length} total tools`\n );\n await this.createExecutor();\n }\n } else {\n this.logger.error(\n `Failed to connect to MCP server ${status.serverName}: ${status.error}`\n );\n }\n } catch (error) {\n this.logger.error(\n `Background connection failed for MCP server ${serverName}:`,\n error\n );\n\n this.mcpConnectionStatus.set(serverName, {\n connected: false,\n serverName,\n tools: [],\n error: error instanceof Error ? error.message : 'Connection failed',\n });\n }\n }, 1000);\n }\n\n /**\n * Detects and processes HashLink blocks from tool responses\n * @param parsedResponse - The parsed JSON response from a tool\n * @returns Metadata object containing hashLinkBlock if detected\n */\n private processHashLinkBlocks(parsedResponse: unknown): {\n hashLinkBlock?: Record<string, unknown>;\n } {\n try {\n const responseRecord = parsedResponse as Record<string, unknown>;\n if (\n parsedResponse &&\n typeof parsedResponse === 'object' &&\n responseRecord.hashLinkBlock &&\n typeof responseRecord.hashLinkBlock === 'object'\n ) {\n const block = responseRecord.hashLinkBlock as Record<string, unknown>;\n\n if (\n block.blockId &&\n block.hashLink &&\n block.template &&\n block.attributes &&\n typeof block.blockId === 'string' &&\n typeof block.hashLink === 'string' &&\n typeof block.template === 'string' &&\n typeof block.attributes === 'object'\n ) {\n this.logger.info('HashLink block detected:', {\n blockId: block.blockId,\n hashLink: block.hashLink,\n template: block.template,\n attributeKeys: Object.keys(block.attributes),\n });\n\n return {\n hashLinkBlock: {\n blockId: block.blockId,\n hashLink: block.hashLink,\n template: block.template,\n attributes: block.attributes,\n },\n };\n } else {\n this.logger.warn('Invalid HashLink block structure detected:', block);\n }\n }\n } catch (error) {\n this.logger.error('Error processing HashLink blocks:', error);\n }\n\n return {};\n }\n\n /**\n * Check if a string is valid JSON\n */\n private isJSON(str: string): boolean {\n if (typeof str !== 'string') return false;\n\n const trimmed = str.trim();\n if (!trimmed) return false;\n\n if (\n !(trimmed.startsWith('{') && trimmed.endsWith('}')) &&\n !(trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n return false;\n }\n\n try {\n JSON.parse(trimmed);\n return true;\n } catch {\n return false;\n }\n }\n}\n","import { BaseAgent, type HederaAgentConfiguration } from './base-agent';\nimport { LangChainAgent } from './langchain/langchain-agent';\n\nexport function createAgent(\n config: HederaAgentConfiguration & {\n framework?: 'langchain' | 'vercel' | 'baml';\n }\n): BaseAgent {\n const framework = config.framework || 'langchain';\n\n switch (framework) {\n case 'langchain':\n return new LangChainAgent(config);\n case 'vercel':\n throw new Error('Vercel AI SDK support coming soon');\n case 'baml':\n throw new Error('BAML support coming soon');\n default:\n throw new Error(`Unknown framework: ${framework}`);\n }\n}","import {\n AccountId,\n Client,\n PrivateKey,\n PublicKey,\n Transaction,\n TransactionReceipt,\n} from '@hashgraph/sdk';\nimport { AbstractSigner } from 'hedera-agent-kit';\nimport {\n HederaMirrorNode,\n Logger,\n type NetworkType,\n} from '@hashgraphonline/standards-sdk';\n\n/**\n * BrowserSigner (bytes-only)\n *\n * Minimal signer compatible with HederaAgentKit in bytes/Provide Bytes mode.\n * - Does NOT hold a private key\n * - Cannot execute transactions; only provides identity and network context\n * - getOperatorPrivateKey() throws to signal absence of a local key\n */\nexport class BrowserSigner extends AbstractSigner {\n private readonly account: AccountId;\n private readonly network: 'mainnet' | 'testnet';\n private readonly client: Client;\n private readonly exec: ((\n base64: string,\n network: 'mainnet' | 'testnet'\n ) => Promise<{ transactionId: string }>) | null;\n private readonly ephemeralKey: PrivateKey;\n\n getAccountId(): AccountId {\n return this.account;\n }\n\n getNetwork(): 'mainnet' | 'testnet' {\n return this.network;\n }\n\n constructor(\n accountId: string,\n network: 'mainnet' | 'testnet',\n executor?: (\n base64: string,\n network: 'mainnet' | 'testnet'\n ) => Promise<{ transactionId: string }>\n ) {\n super();\n this.account = AccountId.fromString(accountId);\n this.network = network;\n this.client =\n network === 'mainnet' ? Client.forMainnet() : Client.forTestnet();\n this.exec = executor ?? null;\n this.ephemeralKey = PrivateKey.generateED25519();\n }\n\n /**\n * Returns an auto-generated ED25519 key for client wiring only.\n * Do not use for signing; wallet performs signing in renderer.\n */\n getOperatorPrivateKey(): PrivateKey {\n return this.ephemeralKey;\n }\n\n getClient(): Client {\n return this.client;\n }\n\n async signAndExecuteTransaction(\n tx: Transaction\n ): Promise<TransactionReceipt> {\n if (!this.exec) {\n throw new Error('BrowserSigner executor not available');\n }\n if (!tx.isFrozen()) {\n await tx.freezeWith(this.client);\n }\n const base64 = Buffer.from(tx.toBytes()).toString('base64');\n const { transactionId } = await this.exec(base64, this.network);\n const mirror = new HederaMirrorNode(this.network);\n const deadline = Date.now() + 60000;\n while (Date.now() < deadline) {\n try {\n const details = await mirror.getTransaction(transactionId);\n if (details && details.result) {\n return TransactionReceipt.fromBytes(\n Buffer.from(details.result, 'base64')\n );\n }\n } catch {}\n await new Promise((r) => setTimeout(r, 1200));\n }\n return TransactionReceipt.fromBytes(Buffer.from(''));\n }\n\n override async getPublicKey(): Promise<PublicKey> {\n const network: NetworkType =\n this.network === 'mainnet' ? 'mainnet' : 'testnet';\n const mirror = new HederaMirrorNode(\n network,\n new Logger({ module: 'BrowserSigner' })\n );\n const anyKey: any = await mirror.getPublicKey(this.account.toString());\n const keyStr = typeof anyKey?.toString === 'function' ? anyKey.toString() : String(anyKey);\n return PublicKey.fromString(keyStr);\n }\n}\n\nexport default BrowserSigner;\n","import type { \n BaseLanguageModelCallOptions\n} from '@langchain/core/language_models/base';\nimport type { BaseChatModel } from '@langchain/core/language_models/chat_models';\n\n/**\n * Framework-agnostic AI provider interface for multi-framework support\n */\nexport interface AIProvider {\n /**\n * Generate a response from the AI model\n */\n generate(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): Promise<string>;\n\n /**\n * Stream a response from the AI model\n */\n stream?(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): AsyncGenerator<string>;\n\n /**\n * Get the underlying model if available\n */\n getModel?(): BaseChatModel | unknown;\n}\n\n/**\n * LangChain AI provider implementation\n */\nexport class LangChainProvider implements AIProvider {\n constructor(private model: BaseChatModel) {}\n\n async generate(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): Promise<string> {\n const result = await this.model.invoke(prompt, options);\n return typeof result === 'string' ? result : result.toString();\n }\n\n async *stream(\n prompt: string,\n options?: BaseLanguageModelCallOptions\n ): AsyncGenerator<string> {\n const stream = await this.model.stream(prompt, options);\n for await (const chunk of stream) {\n yield typeof chunk === 'string' ? chunk : chunk.toString();\n }\n }\n\n getModel(): BaseChatModel {\n return this.model;\n }\n}\n\n/**\n * Vercel AI SDK provider interface (forward-thinking)\n */\nexport interface VercelAIProvider extends AIProvider {\n /**\n * Use Vercel AI SDK's streamText function\n */\n streamText?(prompt: string, options?: unknown): Promise<unknown>;\n}\n\n/**\n * BAML provider interface (forward-thinking)\n */\nexport interface BAMLProvider extends AIProvider {\n /**\n * Execute a BAML function\n */\n executeFunction?(\n name: string,\n args: Record<string, unknown>\n ): Promise<unknown>;\n}","export type WalletNetwork = 'mainnet' | 'testnet';\n\nexport interface WalletStatus {\n connected: boolean;\n accountId?: string;\n network?: WalletNetwork;\n}\n\nexport interface WalletExecutorResult {\n transactionId: string;\n}\n\nexport interface StartInscriptionResult {\n transactionBytes: string;\n tx_id?: string;\n topic_id?: string;\n status?: string;\n completed?: boolean;\n}\n\nexport interface WalletBridgeProvider {\n status: () => Promise<WalletStatus> | WalletStatus;\n executeBytes: (\n base64: string,\n network: WalletNetwork\n ) => Promise<WalletExecutorResult>;\n startInscription?: (\n request: Record<string, unknown>,\n network: WalletNetwork\n ) => Promise<StartInscriptionResult>;\n startHCS?: (\n op: string,\n request: Record<string, unknown>,\n network: WalletNetwork\n ) => Promise<{ transactionBytes: string }>;\n}\n\nlet providerRef: WalletBridgeProvider | null = null;\n\nexport function setWalletBridgeProvider(provider: WalletBridgeProvider): void {\n providerRef = provider;\n}\n\nexport function getWalletBridgeProvider(): WalletBridgeProvider | null {\n return providerRef;\n}\n","import {\n BasePlugin,\n type GenericPluginContext,\n BaseHederaQueryTool,\n type HederaAgentKit,\n type HederaTool,\n} from 'hedera-agent-kit';\nimport { z } from 'zod';\n\nconst PageSnapshotSchema = z.object({\n url: z.string().url(),\n maxCharacters: z\n .number()\n .int()\n .min(256, 'Minimum length is 256 characters')\n .max(8000, 'Maximum length is 8000 characters')\n .optional()\n .default(3000),\n});\n\nclass WebPageSnapshotTool extends BaseHederaQueryTool<typeof PageSnapshotSchema> {\n name = 'web_page_snapshot';\n description = 'Fetches the visible text content of a web page for analysis.';\n namespace = 'browser';\n specificInputSchema = PageSnapshotSchema;\n\n constructor(params: {\n hederaKit: HederaAgentKit;\n logger?: GenericPluginContext['logger'];\n fetchImpl?: typeof fetch;\n }) {\n const { fetchImpl, ...rest } = params;\n super(rest);\n this.fetchImpl = fetchImpl ?? fetch;\n }\n\n private readonly fetchImpl: typeof fetch;\n\n protected async executeQuery(\n input: z.infer<typeof PageSnapshotSchema>\n ): Promise<string> {\n const maxChars = input.maxCharacters ?? 3000;\n\n try {\n const response = await this.fetchImpl(input.url, {\n redirect: 'follow',\n });\n\n if (!response.ok) {\n return `Failed to load ${input.url}: HTTP ${response.status}`;\n }\n\n const html = await response.text();\n const text = this.normalizeHtml(html);\n\n if (!text) {\n return 'The fetched page did not contain readable text.';\n }\n\n return text.length > maxChars ? `${text.slice(0, maxChars)}…` : text;\n } catch (error) {\n this.logger.error('WebPageSnapshotTool failed', error);\n return `Failed to fetch content for ${input.url}: ${\n error instanceof Error ? error.message : String(error)\n }`;\n }\n }\n\n private normalizeHtml(html: string): string {\n const withoutScripts = html\n .replace(/<script[\\s\\S]*?<\\/script>/gi, ' ')\n .replace(/<style[\\s\\S]*?<\\/style>/gi, ' ')\n .replace(/<!--([\\s\\S]*?)-->/g, ' ');\n\n const stripped = withoutScripts.replace(/<[^>]+>/g, ' ');\n const decoded = stripped\n .replace(/&nbsp;/gi, ' ')\n .replace(/&amp;/gi, '&')\n .replace(/&lt;/gi, '<')\n .replace(/&gt;/gi, '>')\n .replace(/&quot;/gi, '\"')\n .replace(/&#39;/gi, \"'\");\n\n return decoded.replace(/\\s+/g, ' ').trim();\n }\n}\n\nexport class WebBrowserPlugin extends BasePlugin<GenericPluginContext> {\n id = 'web-browser';\n name = 'Web Browser Plugin';\n description =\n 'Provides tools for fetching live web page content to enrich assistant understanding.';\n version = '0.1.0';\n author = 'Hashgraph Online';\n namespace = 'browser';\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 | undefined;\n\n if (!hederaKit) {\n this.context.logger.warn(\n 'WebBrowserPlugin skipped because HederaAgentKit was not present in plugin context.'\n );\n this.tools = [];\n return;\n }\n\n const tool = new WebPageSnapshotTool({\n hederaKit,\n logger: this.context.logger,\n });\n\n this.tools = [tool];\n this.context.logger.info('Web Browser Plugin initialized with snapshot tool');\n }\n\n override getTools(): HederaTool[] {\n return this.tools;\n }\n\n override async cleanup(): Promise<void> {\n this.tools = [];\n }\n}\n","export const getSystemMessage = (\n accountId?: string\n): string => `You are a helpful assistant managing Hashgraph Online HCS-10 connections, messages, HCS-2 registries, content inscription, and Hedera Hashgraph operations.\n\nYou have access to tools for:\n- HCS-10: registering agents, finding registered agents, initiating connections, listing active connections, sending messages over connections, and checking for new messages\n- HCS-2: creating registries, registering entries, updating entries, deleting entries, migrating registries, and querying registry contents\n- Inscription: inscribing content from URLs, files, or buffers, creating Hashinal NFTs, and retrieving inscriptions\n- Hedera Token Service (HTS): creating tokens, transferring tokens, airdropping tokens, and managing token operations\n\n\n*** IMPORTANT CONTEXT ***\nYou are currently operating as agent: ${accountId || 'unknown'} on the Hedera Hashgraph\nWhen users ask about \"my profile\", \"my account\", \"my connections\", etc., use this account ID: ${accountId || 'unknown'}\n\n*** CRITICAL ENTITY HANDLING RULES ***\n- When users refer to entities (tokens, topics, accounts) with pronouns like \"it\", \"that\", \"the token/topic\", etc., ALWAYS use the most recently created entity of that type\n- Entity IDs look like \"0.0.XXXXXX\" and are stored in memory after creation\n- NEVER use example or placeholder IDs like \"0.0.123456\" - always use actual created entity IDs\n- Account ID ${accountId} is NOT a token - tokens and accounts are different entities\n\n Remember the connection numbers when listing connections, as users might refer to them.`;\n","import { ContentStorage } from '../memory/content-storage';\nimport {\n ContentStoreService,\n extractReferenceId,\n shouldUseReference,\n ContentResolverRegistry,\n type ContentStoreInterface,\n type ContentResolverInterface,\n type ReferenceResolutionResult,\n} from '@hashgraphonline/standards-sdk';\nimport type {\n ContentReference,\n ContentReferenceConfig,\n ContentReferenceStats,\n} from '../types/content-reference';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\n/**\n * Content metadata interface for adapter compatibility\n */\ninterface AdapterContentMetadata {\n mimeType?: string;\n fileName?: string;\n sizeBytes?: number;\n [key: string]: unknown;\n}\n\n/**\n * Configuration interface for content storage\n */\ninterface ContentStoreConfig {\n maxSize?: number;\n enableCompression?: boolean;\n [key: string]: unknown;\n}\n\n/**\n * Adapter to make ContentStorage compatible with ContentStoreInterface\n */\nclass ContentStorageAdapter implements ContentStoreInterface {\n constructor(private storage: ContentStorage) {}\n\n async storeContent(\n content: Buffer,\n metadata: AdapterContentMetadata\n ): Promise<string> {\n const storeMetadata = {\n contentType: 'binary' as const,\n sizeBytes: content.length,\n source: 'system' as const,\n ...metadata,\n };\n const contentRef = await this.storage.storeContent(content, storeMetadata);\n return contentRef.referenceId;\n }\n\n async resolveReference(\n referenceId: string\n ): Promise<ReferenceResolutionResult> {\n const result = await this.storage.resolveReference(referenceId);\n if (result.success && result.content) {\n const response: ReferenceResolutionResult = {\n content: result.content,\n };\n if (result.metadata) {\n response.metadata = {\n ...(result.metadata.mimeType !== undefined && {\n mimeType: result.metadata.mimeType,\n }),\n ...(result.metadata.fileName !== undefined && {\n fileName: result.metadata.fileName,\n }),\n originalSize: result.metadata.sizeBytes,\n };\n }\n return response;\n } else {\n throw new Error(result.error || 'Reference not found');\n }\n }\n\n async hasReference(referenceId: string): Promise<boolean> {\n return await this.storage.hasReference(referenceId);\n }\n\n async cleanupReference(referenceId: string): Promise<void> {\n await this.storage.cleanupReference(referenceId);\n }\n\n async getStats(): Promise<unknown> {\n return await this.storage.getStats();\n }\n\n async updateConfig(config: ContentStoreConfig): Promise<void> {\n const referenceConfig = {\n sizeThresholdBytes: config.maxSize || 10240,\n enableAutoCleanup: config.enableCompression || true,\n ...config,\n };\n return await this.storage.updateConfig(referenceConfig);\n }\n\n async performCleanup(): Promise<void> {\n await this.storage.performCleanup();\n }\n\n async dispose(): Promise<void> {\n return Promise.resolve(this.storage.dispose());\n }\n}\n\n/**\n * Content resolver implementation for dependency injection\n */\nclass ContentResolver implements ContentResolverInterface {\n constructor(private adapter: ContentStorageAdapter) {}\n\n async resolveReference(\n referenceId: string\n ): Promise<ReferenceResolutionResult> {\n return await this.adapter.resolveReference(referenceId);\n }\n\n shouldUseReference(content: string | Buffer): boolean {\n return shouldUseReference(content);\n }\n\n extractReferenceId(input: string): string | null {\n return extractReferenceId(input);\n }\n}\n\n/**\n * Manages content store lifecycle and cross-package registration\n */\nexport class ContentStoreManager {\n private contentStorage: ContentStorage;\n private adapter: ContentStorageAdapter;\n private resolver: ContentResolver;\n private logger: Logger;\n protected isRegistered = false;\n\n constructor(\n maxMessageStorage: number = 1000,\n referenceConfig?: Partial<ContentReferenceConfig>,\n logger?: Logger\n ) {\n this.logger = logger || new Logger({ module: 'ContentStoreManager' });\n\n this.contentStorage = new ContentStorage(\n maxMessageStorage,\n referenceConfig\n );\n this.adapter = new ContentStorageAdapter(this.contentStorage);\n this.resolver = new ContentResolver(this.adapter);\n }\n\n /**\n * Initialize and register content storage for cross-package access\n */\n async initialize(): Promise<void> {\n if (this.isRegistered) {\n this.logger.warn('ContentStoreManager is already initialized');\n return;\n }\n\n try {\n if (\n ContentStoreService &&\n typeof (ContentStoreService as unknown as { setInstance?: Function }).setInstance === 'function'\n ) {\n await (ContentStoreService as unknown as { setInstance: (adapter: unknown) => Promise<void> }).setInstance(\n this.adapter\n );\n } else {\n this.logger.warn('ContentStoreService.setInstance is unavailable; skipping registration');\n }\n if (\n ContentResolverRegistry &&\n typeof (ContentResolverRegistry as unknown as { register?: Function }).register === 'function'\n ) {\n (ContentResolverRegistry as unknown as { register: (resolver: unknown) => void }).register(\n this.resolver\n );\n } else {\n this.logger.warn('ContentResolverRegistry.register is unavailable; skipping registration');\n }\n this.isRegistered = true;\n this.logger.info(\n 'ContentStoreManager initialized and registered for cross-package access'\n );\n } catch (error) {\n this.logger.error('Failed to initialize ContentStoreManager:', error);\n throw error;\n }\n }\n\n /**\n * Get the underlying ContentStorage instance\n */\n getContentStorage(): ContentStorage {\n return this.contentStorage;\n }\n\n /**\n * Get storage statistics\n */\n async getStats(): Promise<ContentReferenceStats> {\n return await this.contentStorage.getStats();\n }\n\n /**\n * Update configuration\n */\n async updateConfig(config: Partial<ContentReferenceConfig>): Promise<void> {\n return await this.contentStorage.updateConfig(config);\n }\n\n /**\n * Perform manual cleanup\n */\n async performCleanup(): Promise<{ cleanedUp: number; errors: string[] }> {\n return await this.contentStorage.performCleanup();\n }\n\n /**\n * Check if content should be stored as reference\n */\n shouldUseReference(content: Buffer | string): boolean {\n return this.contentStorage.shouldUseReference(content);\n }\n\n /**\n * Store content if it's large enough\n */\n async storeContentIfLarge(\n content: Buffer | string,\n metadata: AdapterContentMetadata\n ): Promise<ContentReference | null> {\n const storeMetadata = {\n source: 'system' as const,\n contentType: 'binary' as const,\n ...metadata,\n };\n return await this.contentStorage.storeContentIfLarge(\n content,\n storeMetadata\n );\n }\n\n /**\n * Cleanup and unregister\n */\n async dispose(): Promise<void> {\n if (this.isRegistered) {\n this.contentStorage.dispose();\n if (\n ContentStoreService &&\n typeof (ContentStoreService as unknown as { dispose?: Function }).dispose === 'function'\n ) {\n (ContentStoreService as unknown as { dispose: () => void }).dispose();\n }\n if (\n ContentResolverRegistry &&\n typeof (ContentResolverRegistry as unknown as { unregister?: Function }).unregister === 'function'\n ) {\n (ContentResolverRegistry as unknown as { unregister: () => void }).unregister();\n }\n this.isRegistered = false;\n this.logger.info('ContentStoreManager disposed and unregistered');\n }\n }\n\n /**\n * Check if the manager is initialized\n */\n isInitialized(): boolean {\n return this.isRegistered;\n }\n}\n","import { StructuredTool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport { ChatOpenAI } from '@langchain/openai';\nimport { ChatAnthropic } from '@langchain/anthropic';\nimport { Logger } from '@hashgraphonline/standards-sdk';\n\nconst logger = new Logger({ module: 'EntityResolverTool' });\n\nconst ResolveEntitiesSchema = z.object({\n message: z.string().describe('The message containing entity references to resolve'),\n entities: z.array(z.object({\n entityId: z.string(),\n entityName: z.string(),\n entityType: z.string(),\n })).describe('Available entities in memory'),\n});\n\nconst ExtractEntitiesSchema = z.object({\n response: z.string().describe('Agent response text to extract entities from'),\n userMessage: z.string().describe('Original user message for context'),\n});\n\nexport class ResolveEntitiesTool extends StructuredTool {\n name = 'resolve_entities';\n description = 'Resolves entity references like \"the topic\", \"it\", \"that\" to actual entity IDs';\n schema = ResolveEntitiesSchema;\n \n private llm: ChatOpenAI | ChatAnthropic;\n \n constructor(llm: ChatOpenAI | ChatAnthropic) {\n super();\n this.llm = llm;\n }\n \n async _call(input: z.infer<typeof ResolveEntitiesSchema>): Promise<string> {\n const { message, entities } = input;\n \n if (!entities || entities.length === 0) {\n return message;\n }\n \n const byType = this.groupEntitiesByType(entities);\n const context = this.buildEntityContext(byType);\n \n const prompt = `Task: Replace entity references with IDs.\n\n${context}\n\nMessage: \"${message}\"\n\nRules:\n- \"the topic\" or \"that topic\" → replace with most recent topic ID\n- \"the token\" or \"that token\" → replace with most recent token ID\n- \"it\" or \"that\" after action verb → replace with most recent entity ID\n- \"airdrop X\" without token ID → add most recent token ID as first parameter\n- Token operations without explicit token → use most recent token ID\n\nExamples:\n- \"submit on the topic\" → \"submit on 0.0.6543472\"\n- \"airdrop the token\" → \"airdrop 0.0.123456\"\n- \"airdrop 10 to 0.0.5842697\" → \"airdrop 0.0.123456 10 to 0.0.5842697\"\n- \"mint 100\" → \"mint 0.0.123456 100\"\n\nReturn ONLY the resolved message:`;\n \n try {\n const response = await this.llm.invoke(prompt);\n return (response.content as string).trim();\n } catch (error) {\n logger.error('ResolveEntitiesTool failed:', error);\n return message;\n }\n }\n \n private groupEntitiesByType(entities: EntityGroup): GroupedEntities {\n return entities.reduce((acc, entity) => {\n if (!acc[entity.entityType]) {\n acc[entity.entityType] = [];\n }\n acc[entity.entityType].push(entity);\n return acc;\n }, {} as GroupedEntities);\n }\n \n private buildEntityContext(groupedEntities: GroupedEntities): string {\n let context = 'Available entities:\\n';\n for (const [type, list] of Object.entries(groupedEntities)) {\n const recent = list[0];\n context += `- Most recent ${type}: \"${recent.entityName}\" = ${recent.entityId}\\n`;\n }\n return context;\n }\n}\n\nexport class ExtractEntitiesTool extends StructuredTool {\n name = 'extract_entities';\n description = 'Extracts newly created entities from agent responses';\n schema = ExtractEntitiesSchema;\n \n private llm: ChatOpenAI | ChatAnthropic;\n \n constructor(llm: ChatOpenAI | ChatAnthropic) {\n super();\n this.llm = llm;\n }\n \n async _call(input: z.infer<typeof ExtractEntitiesSchema>): Promise<string> {\n const { response, userMessage } = input;\n \n const prompt = `Extract ONLY newly created entities from this response.\n\nUser asked: \"${userMessage.substring(0, 200)}\"\nResponse: ${response.substring(0, 3000)}\n\nLook for:\n- Success messages with new entity IDs\n- Words like \"created\", \"new\", \"successfully\" followed by entity IDs\n\nReturn JSON array of created entities:\n[{\"id\": \"0.0.XXX\", \"name\": \"name\", \"type\": \"topic|token|account\"}]\n\nIf none created, return: []\n\nJSON:`;\n \n try {\n const llmResponse = await this.llm.invoke(prompt);\n const content = llmResponse.content as string;\n const match = content.match(/\\[[\\s\\S]*?\\]/);\n if (match) {\n return match[0];\n }\n return '[]';\n } catch (error) {\n logger.error('ExtractEntitiesTool failed:', error);\n return '[]';\n }\n }\n}\n\nexport function createEntityTools(\n llm: ChatOpenAI | ChatAnthropic\n): {\n resolveEntities: ResolveEntitiesTool;\n extractEntities: ExtractEntitiesTool;\n} {\n return {\n resolveEntities: new ResolveEntitiesTool(llm),\n extractEntities: new ExtractEntitiesTool(llm),\n };\n}\n\ninterface EntityReference {\n entityId: string;\n entityName: string;\n entityType: string;\n}\n\ntype EntityGroup = EntityReference[];\n\ntype GroupedEntities = Record<string, EntityGroup>;\n","import { EntityFormat, FormatConverter, ConversionContext } from './types';\nimport {\n HederaMirrorNode,\n Logger,\n NetworkType,\n} from '@hashgraphonline/standards-sdk';\n\ninterface CacheEntry {\n format: EntityFormat;\n timestamp: number;\n ttl: number;\n}\n\n/**\n * Registry for format converters that handles entity transformation\n */\nexport class FormatConverterRegistry {\n private converters = new Map<string, FormatConverter<unknown, unknown>>();\n private entityTypeCache = new Map<string, CacheEntry>();\n private logger = new Logger({ module: 'FormatConverterRegistry' });\n private defaultCacheTTL = 5 * 60 * 1000;\n\n /**\n * Register a format converter\n */\n register<TSource, TTarget>(\n converter: FormatConverter<TSource, TTarget>\n ): void {\n const key = `${converter.sourceFormat}→${converter.targetFormat}`;\n this.converters.set(key, converter as FormatConverter<unknown, unknown>);\n }\n\n /**\n * Find a converter for the given source and target formats\n */\n findConverter(\n source: EntityFormat,\n target: EntityFormat\n ): FormatConverter<unknown, unknown> | null {\n const key = `${source}→${target}`;\n return this.converters.get(key) || null;\n }\n\n /**\n * Convert an entity to the target format\n */\n async convertEntity(\n entity: string,\n target: EntityFormat,\n context: ConversionContext\n ): Promise<string> {\n const sourceFormat = await this.detectFormatWithFallback(entity, context);\n if (sourceFormat === target) {\n return entity;\n }\n\n const converter = this.findConverter(sourceFormat, target);\n if (!converter) {\n throw new Error(`No converter found for ${sourceFormat} → ${target}`);\n }\n\n if (!converter.canConvert(entity, context)) {\n throw new Error(`Converter cannot handle entity: ${entity}`);\n }\n\n const result = await converter.convert(entity, context);\n return result as string;\n }\n\n /**\n * Detect the format of an entity string with API-based verification and fallback\n */\n private async detectFormatWithFallback(\n entity: string,\n context?: ConversionContext\n ): Promise<EntityFormat> {\n if (entity.startsWith('hcs://')) {\n return EntityFormat.HRL;\n }\n\n if (/^0\\.0\\.\\d+$/.test(entity)) {\n const cached = this.getCachedFormat(entity);\n if (cached) {\n return cached;\n }\n\n try {\n const detected = await this.detectFormat(entity, context || {});\n if (detected !== EntityFormat.ANY) {\n this.setCachedFormat(entity, detected);\n return detected;\n }\n } catch (error) {\n this.logger.warn(\n `Entity detection failed for ${entity}, using fallback: ${\n (error as Error).message\n }`\n );\n }\n\n return EntityFormat.ANY;\n }\n\n return EntityFormat.ANY;\n }\n\n /**\n * Public helper: detect entity format (ACCOUNT_ID, TOKEN_ID, TOPIC_ID, HRL, or ANY)\n */\n async detectEntityFormat(\n entity: string,\n context?: ConversionContext\n ): Promise<EntityFormat> {\n return this.detectFormatWithFallback(entity, context);\n }\n\n /**\n * Detect entity format via Hedera Mirror Node API calls\n */\n private async detectFormat(\n entity: string,\n context: ConversionContext\n ): Promise<EntityFormat> {\n const networkType = (context.networkType as NetworkType) || 'testnet';\n const mirrorNode = new HederaMirrorNode(networkType, this.logger);\n\n mirrorNode.configureRetry({\n maxRetries: 3,\n maxDelayMs: 1000,\n });\n\n const checks = await Promise.allSettled([\n mirrorNode\n .getAccountBalance(entity)\n .then((result) => (result !== null ? EntityFormat.ACCOUNT_ID : null))\n .catch(() => null),\n\n mirrorNode\n .getTokenInfo(entity)\n .then((result) => (result !== null ? EntityFormat.TOKEN_ID : null))\n .catch(() => null),\n\n mirrorNode\n .getTopicInfo(entity)\n .then((result) => (result !== null ? EntityFormat.TOPIC_ID : null))\n .catch(() => null),\n\n mirrorNode\n .getContract(entity)\n .then((result) => (result !== null ? EntityFormat.CONTRACT_ID : null))\n .catch(() => null),\n ]);\n\n const successful = checks.find(\n (result) => result.status === 'fulfilled' && result.value !== null\n );\n\n return successful && successful.status === 'fulfilled'\n ? (successful.value as EntityFormat)\n : EntityFormat.ANY;\n }\n\n /**\n * Get cached entity format if valid\n */\n private getCachedFormat(entity: string): EntityFormat | null {\n const entry = this.entityTypeCache.get(entity);\n if (!entry || this.isCacheExpired(entry)) {\n this.entityTypeCache.delete(entity);\n return null;\n }\n return entry.format;\n }\n\n /**\n * Set cached entity format\n */\n private setCachedFormat(entity: string, format: EntityFormat): void {\n this.entityTypeCache.set(entity, {\n format,\n timestamp: Date.now(),\n ttl: this.defaultCacheTTL,\n });\n }\n\n /**\n * Check if cache entry is expired\n */\n private isCacheExpired(entry: CacheEntry): boolean {\n return Date.now() - entry.timestamp > entry.ttl;\n }\n\n /**\n * Get all registered converters\n */\n getRegisteredConverters(): Array<{\n source: EntityFormat;\n target: EntityFormat;\n }> {\n return Array.from(this.converters.keys()).map((key) => {\n const [source, target] = key.split('→');\n return {\n source: source as EntityFormat,\n target: target as EntityFormat,\n };\n });\n }\n\n /**\n * Check if a converter exists for the given formats\n */\n hasConverter(source: EntityFormat, target: EntityFormat): boolean {\n return this.findConverter(source, target) !== null;\n }\n\n /**\n * Clear all registered converters\n */\n clear(): void {\n this.converters.clear();\n }\n\n /**\n * Clear entity type cache\n */\n clearCache(): void {\n this.entityTypeCache.clear();\n }\n}\n","import { EntityFormat, FormatConverter, ConversionContext } from '../types';\n\n/**\n * Converts Hedera topic IDs to HRL format for consensus service messages\n */\nexport class TopicIdToHrlConverter implements FormatConverter<string, string> {\n sourceFormat = EntityFormat.TOPIC_ID;\n targetFormat = EntityFormat.HRL;\n\n /**\n * Check if the source string is a valid topic ID\n */\n canConvert(source: string, _context: ConversionContext): boolean {\n return /^0\\.0\\.\\d+$/.test(source);\n }\n\n /**\n * Convert topic ID to HRL format based on network type\n */\n async convert(topicId: string, context: ConversionContext): Promise<string> {\n const networkType = context.networkType || 'testnet';\n const networkId = networkType === 'mainnet' ? '0' : '1';\n return `hcs://${networkId}/${topicId}`;\n }\n}\n","import {\n EntityFormat,\n type FormatConverter,\n type ConversionContext,\n} from '../types';\nimport {\n HederaMirrorNode,\n HRLResolver,\n type NetworkType,\n} from '@hashgraphonline/standards-sdk';\n\n/**\n * Generic converter that normalizes various string entity references (cdn urls, content-ref, raw topic id)\n * into canonical HRL. It declares source ANY -> HRL and internally short-circuits if unsupported.\n */\nexport class StringNormalizationConverter\n implements FormatConverter<string, string>\n{\n sourceFormat = EntityFormat.ANY;\n targetFormat = EntityFormat.HRL;\n\n private static standardCache: Map<string, string> = new Map();\n\n canConvert(source: string, _context: ConversionContext): boolean {\n if (typeof source !== 'string') {\n return false;\n }\n if (/^hcs:\\/\\/\\d\\/0\\.0\\.\\d+$/i.test(source)) {\n return false;\n }\n if (/inscription-cdn\\/(0\\.0\\.\\d+)/i.test(source)) {\n return true;\n }\n if (/^content-ref:(0\\.0\\.\\d+)$/i.test(source)) {\n return true;\n }\n if (/^0\\.0\\.\\d+$/.test(source)) {\n const hasPreference = Boolean(\n (_context as unknown as { toolPreferences?: Record<string, string> })\n ?.toolPreferences?.inscription === 'hrl' ||\n (_context as unknown as { toolPreferences?: Record<string, string> })\n ?.toolPreferences?.topic === 'hrl'\n );\n return hasPreference;\n }\n return false;\n }\n\n async convert(source: string, context: ConversionContext): Promise<string> {\n const toolPrefs = (\n context as unknown as { toolPreferences?: Record<string, string> }\n ).toolPreferences;\n const fallbackStandard =\n toolPrefs?.hrlStandard || toolPrefs?.inscriptionHrlStandard || '1';\n const networkType = (context.networkType as string) || 'testnet';\n\n const resolver = new HRLResolver();\n\n const cdnMatch = source.match(/inscription-cdn\\/(0\\.0\\.\\d+)/i);\n if (cdnMatch && cdnMatch[1]) {\n try {\n const mirror = new HederaMirrorNode(networkType as NetworkType);\n mirror.configureRetry({\n maxRetries: 3,\n maxDelayMs: 1000,\n });\n const resolved = await mirror.getTopicInfo(cdnMatch[1]);\n const memo = (resolved && (resolved as { memo?: string }).memo) || '';\n const match = memo.match(/^hcs-(\\d+)/);\n const standard = match && match[1] ? match[1] : '1';\n return `hcs://${standard}/${cdnMatch[1]}`;\n } catch {\n return `hcs://${fallbackStandard}/${cdnMatch[1]}`;\n }\n }\n\n const contentRefMatch = source.match(/^content-ref:(0\\.0\\.\\d+)$/i);\n if (contentRefMatch && contentRefMatch[1]) {\n try {\n const resolved = await resolver.resolve(contentRefMatch[1], {\n network: networkType as NetworkType,\n });\n const parsed = resolver.parseHRL(`hcs://1/${resolved.topicId}`);\n const std = parsed?.standard || fallbackStandard;\n return `hcs://${std}/${resolved.topicId}`;\n } catch {\n return `hcs://${fallbackStandard}/${contentRefMatch[1]}`;\n }\n }\n\n if (/^0\\.0\\.\\d+$/.test(source)) {\n try {\n const resolved = await resolver.resolve(source, {\n network: networkType as NetworkType,\n });\n const parsed = resolver.parseHRL(`hcs://1/${resolved.topicId}`);\n const std = parsed?.standard || fallbackStandard;\n return `hcs://${std}/${resolved.topicId}`;\n } catch {\n return `hcs://${fallbackStandard}/${source}`;\n }\n }\n\n return source;\n }\n}\n","import { Logger, type NetworkType } from '@hashgraphonline/standards-sdk';\nimport { EntityFormat, FormatConverterRegistry } from './formatters';\nimport type { EntityAssociation } from '../memory/smart-memory-manager';\n\n/**\n * Service for processing tool parameters and applying entity format conversions\n */\nexport class ParameterService {\n private logger: Logger;\n private formatConverterRegistry: FormatConverterRegistry;\n private networkType: NetworkType;\n\n constructor(\n formatConverterRegistry: FormatConverterRegistry,\n networkType: NetworkType\n ) {\n this.logger = new Logger({ module: 'ParameterService' });\n this.formatConverterRegistry = formatConverterRegistry;\n this.networkType = networkType;\n }\n\n /**\n * Unified preprocessing entrypoint (DRY):\n * - Optional AI-driven resolution via provided entityResolver\n * - Deterministic post-pass for safe format enforcement\n */\n async preprocessParameters(\n toolName: string,\n parameters: Record<string, unknown>,\n entities: EntityAssociation[] = [],\n options?: {\n entityResolver?: {\n resolveReferences: (\n message: string,\n entities: EntityAssociation[]\n ) => Promise<string>;\n };\n sessionId?: string;\n preferences?: Record<string, string>;\n }\n ): Promise<Record<string, unknown>> {\n const sessionId = options?.sessionId;\n const entityResolver = options?.entityResolver;\n const preferences = options?.preferences;\n\n let working: Record<string, unknown> = { ...parameters };\n\n if (entityResolver && entities.length > 0) {\n try {\n this.logger.info('AI-driven preprocessing phase', {\n toolName,\n entityCount: entities.length,\n sessionId,\n });\n\n const aiProcessed: Record<string, unknown> = { ...working };\n for (const [paramName, paramValue] of Object.entries(working)) {\n if (typeof paramValue === 'string') {\n const resolved = await entityResolver.resolveReferences(\n paramValue,\n entities\n );\n const converted = await this.convertParameterEntities(\n resolved,\n entities,\n preferences\n );\n aiProcessed[paramName] = converted;\n } else if (Array.isArray(paramValue)) {\n const out: unknown[] = [];\n for (const item of paramValue) {\n if (typeof item === 'string') {\n const resolved = await entityResolver.resolveReferences(\n item,\n entities\n );\n const converted = await this.convertParameterEntities(\n resolved,\n entities,\n preferences\n );\n out.push(converted);\n } else {\n out.push(item);\n }\n }\n aiProcessed[paramName] = out;\n }\n }\n working = aiProcessed;\n } catch (error) {\n const message = error instanceof Error ? error.message : 'unknown';\n this.logger.warn(\n 'AI phase failed; continuing with deterministic pass',\n {\n toolName,\n error: message,\n }\n );\n }\n }\n\n try {\n const processed: Record<string, unknown> = { ...working };\n for (const [paramName, paramValue] of Object.entries(working)) {\n if (typeof paramValue === 'string') {\n const converted = await this.convertParameterEntities(\n paramValue,\n entities,\n preferences\n );\n processed[paramName] = converted;\n } else if (Array.isArray(paramValue)) {\n const out: unknown[] = [];\n for (const item of paramValue) {\n if (typeof item === 'string') {\n const converted = await this.convertParameterEntities(\n item,\n entities,\n preferences\n );\n out.push(converted);\n } else {\n out.push(item);\n }\n }\n processed[paramName] = out;\n }\n }\n working = processed;\n } catch (e) {\n this.logger.warn('Deterministic post-pass failed', {\n toolName,\n error: e instanceof Error ? e.message : 'unknown',\n });\n }\n\n return working;\n }\n\n /**\n * Attach unified preprocessing callback directly to the agent.\n */\n attachToAgent(\n agent: unknown,\n deps?: {\n getSessionId?: () => string | null;\n getEntities?: (sessionId: string | null) => Promise<EntityAssociation[]>;\n entityResolver?: {\n resolveReferences: (\n message: string,\n entities: EntityAssociation[]\n ) => Promise<string>;\n };\n }\n ): void {\n const getSessionId = deps?.getSessionId ?? (() => null);\n const getEntities =\n deps?.getEntities ?? (async () => [] as EntityAssociation[]);\n const entityResolver = deps?.entityResolver;\n\n const maybe = agent as {\n setParameterPreprocessingCallback?: (\n callback: (\n toolName: string,\n parameters: Record<string, unknown>,\n toolContext?: {\n entityResolutionPreferences?: Record<string, string>;\n }\n ) => Promise<Record<string, unknown>>\n ) => void;\n getAgent?: () => unknown;\n };\n\n const attach = (target: unknown): boolean => {\n const t = target as {\n setParameterPreprocessingCallback?: (\n callback: (\n toolName: string,\n parameters: Record<string, unknown>,\n toolContext?: {\n entityResolutionPreferences?: Record<string, string>;\n }\n ) => Promise<Record<string, unknown>>\n ) => void;\n };\n if (typeof t.setParameterPreprocessingCallback === 'function') {\n t.setParameterPreprocessingCallback(\n async (\n toolName: string,\n parameters: Record<string, unknown>\n ): Promise<Record<string, unknown>> => {\n const sessionId = getSessionId();\n const entities = await getEntities(sessionId);\n const opts: {\n entityResolver?: {\n resolveReferences: (\n message: string,\n entities: EntityAssociation[]\n ) => Promise<string>;\n };\n sessionId?: string;\n preferences?: Record<string, string>;\n } = {};\n if (entityResolver) {\n opts.entityResolver = entityResolver;\n }\n if (sessionId) {\n opts.sessionId = sessionId;\n }\n return this.preprocessParameters(toolName, parameters, entities, opts);\n }\n );\n this.logger.info('Parameter preprocessing callback attached');\n return true;\n }\n return false;\n };\n\n if (!attach(agent) && typeof maybe.getAgent === 'function') {\n const underlying = maybe.getAgent();\n if (underlying) {\n void attach(underlying);\n }\n }\n }\n\n /**\n * Preprocess tool parameters by applying format conversions based on tool's entity resolution preferences\n */\n async preprocessToolParameters(\n toolName: string,\n parameters: Record<string, unknown>,\n entities?: EntityAssociation[],\n sessionId?: string\n ): Promise<Record<string, unknown>> {\n try {\n if (!entities || entities.length === 0) {\n this.logger.info(\n 'Tool parameter preprocessing skipped - no entities provided:',\n {\n toolName,\n originalParams: Object.keys(parameters),\n }\n );\n return parameters;\n }\n\n const processedParameters = { ...parameters };\n const preferences: Record<string, string> | undefined = undefined;\n let hasChanges = false;\n\n for (const [paramName, paramValue] of Object.entries(parameters)) {\n if (typeof paramValue === 'string') {\n const convertedValue = await this.convertParameterEntities(\n paramValue,\n entities,\n preferences\n );\n\n if (convertedValue !== paramValue) {\n processedParameters[paramName] = convertedValue;\n hasChanges = true;\n\n this.logger.info('Parameter entity conversion applied:', {\n toolName,\n paramName,\n original: paramValue,\n converted: convertedValue,\n });\n }\n } else if (Array.isArray(paramValue)) {\n const originalArray = paramValue as unknown[];\n const convertedArray: unknown[] = [];\n let arrayChanged = false;\n\n for (const item of originalArray) {\n if (typeof item === 'string') {\n const convertedItem = await this.convertParameterEntities(\n item,\n entities,\n preferences\n );\n\n convertedArray.push(convertedItem);\n\n if (convertedItem !== item) {\n arrayChanged = true;\n this.logger.info('Parameter array item conversion applied:', {\n toolName,\n paramName,\n original: item,\n converted: convertedItem,\n });\n }\n } else {\n convertedArray.push(item);\n }\n }\n\n if (arrayChanged) {\n processedParameters[paramName] = convertedArray;\n hasChanges = true;\n }\n }\n }\n\n this.logger.info('Tool parameter preprocessing completed:', {\n toolName,\n originalParams: Object.keys(parameters),\n hasChanges,\n sessionId,\n });\n\n return processedParameters;\n } catch (error) {\n this.logger.warn('Tool parameter preprocessing failed:', {\n toolName,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n return parameters;\n }\n }\n\n /**\n * Convert entity references in a parameter value based on tool preferences\n */\n async convertParameterEntities(\n parameterValue: string,\n entities: EntityAssociation[],\n preferences?: Record<string, string>\n ): Promise<string> {\n let convertedValue = parameterValue;\n\n for (const entity of entities) {\n const containsEntityId = convertedValue.includes(entity.entityId);\n const containsEntityName = convertedValue.includes(entity.entityName);\n\n if (!containsEntityId && !containsEntityName) {\n continue;\n }\n\n let targetFormat: EntityFormat | null = null;\n\n if (entity.entityType === EntityFormat.TOPIC_ID) {\n if (\n preferences?.inscription === 'hrl' ||\n preferences?.topic === 'hrl'\n ) {\n targetFormat = EntityFormat.HRL;\n } else if (\n preferences?.inscription === 'topicId' ||\n preferences?.topic === 'topicId'\n ) {\n targetFormat = EntityFormat.TOPIC_ID;\n }\n } else if (entity.entityType === EntityFormat.TOKEN_ID) {\n if (preferences?.token === 'tokenId') {\n targetFormat = EntityFormat.TOKEN_ID;\n } else if (preferences?.token === 'symbol') {\n targetFormat = EntityFormat.SYMBOL;\n }\n } else if (entity.entityType === EntityFormat.ACCOUNT_ID) {\n if (\n preferences?.account === 'accountId' ||\n preferences?.supplyKey === 'accountId' ||\n preferences?.adminKey === 'accountId'\n ) {\n targetFormat = EntityFormat.ACCOUNT_ID;\n } else if (preferences?.account === 'alias') {\n targetFormat = EntityFormat.ALIAS;\n }\n }\n\n if (targetFormat) {\n try {\n const context: {\n networkType?: string | NetworkType;\n sessionId?: string;\n toolPreferences?: Record<string, string>;\n } = {\n networkType: this.networkType,\n sessionId: 'unknown',\n };\n if (preferences) {\n context.toolPreferences = preferences;\n }\n const convertedEntityValue = await this.formatConverterRegistry.convertEntity(\n entity.entityId,\n targetFormat,\n context as never\n );\n\n if (containsEntityId) {\n convertedValue = convertedValue.replace(\n new RegExp(`\\\\b${entity.entityId.replace(/\\./g, '\\\\.')}\\\\b`, 'g'),\n convertedEntityValue\n );\n }\n\n if (containsEntityName) {\n convertedValue = convertedValue.replace(\n new RegExp(\n `\\\\b${entity.entityName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\b`,\n 'g'\n ),\n convertedEntityValue\n );\n }\n\n this.logger.info('Applied format conversion to parameter:', {\n entityId: entity.entityId,\n entityType: entity.entityType,\n targetFormat,\n convertedValue: convertedEntityValue,\n parameterValue: convertedValue,\n });\n } catch (error) {\n this.logger.warn('Format conversion failed for parameter:', {\n entityId: entity.entityId,\n targetFormat,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n }\n }\n\n return convertedValue;\n }\n}\n","import {\n ServerSigner,\n getAllHederaCorePlugins,\n BasePlugin,\n AbstractSigner,\n} from 'hedera-agent-kit';\nimport { Logger, type NetworkType } from '@hashgraphonline/standards-sdk';\nimport { createAgent } from './agent-factory';\nimport BrowserSigner from './signers/browser-signer';\nimport { LangChainProvider } from './providers';\nimport type { ChatResponse, ConversationContext } from './base-agent';\nimport { ChatOpenAI } from '@langchain/openai';\nimport { ChatAnthropic } from '@langchain/anthropic';\nimport {\n HumanMessage,\n AIMessage,\n SystemMessage,\n} from '@langchain/core/messages';\nimport type { AgentOperationalMode, MirrorNodeConfig } from 'hedera-agent-kit';\nimport { HCS10Plugin } from './plugins/hcs-10/HCS10Plugin';\nimport { HCS2Plugin } from './plugins/hcs-2/HCS2Plugin';\nimport { InscribePlugin } from './plugins/inscribe/InscribePlugin';\nimport { getWalletBridgeProvider } from './runtime/wallet-bridge';\nimport {\n InscriberBuilder,\n SignerProviderRegistry,\n} from '@hashgraphonline/standards-agent-kit';\nimport { HbarPlugin } from './plugins/hbar/HbarPlugin';\nimport { WebBrowserPlugin } from './plugins/web-browser/WebBrowserPlugin';\nimport { OpenConvaiState } from '@hashgraphonline/standards-agent-kit';\nimport type { IStateManager } from '@hashgraphonline/standards-agent-kit';\nimport { getSystemMessage } from './config/system-message';\nimport type { MCPServerConfig, MCPConnectionStatus } from './mcp/types';\nimport { ContentStoreManager } from './services/content-store-manager';\nimport { SmartMemoryManager, type SmartMemoryConfig } from './memory';\nimport {\n createEntityTools,\n ResolveEntitiesTool,\n ExtractEntitiesTool,\n} from './tools/entity-resolver-tool';\nimport type { FormSubmission } from './forms/types';\nimport { ParameterService } from './services/parameter-service';\nimport { FormatConverterRegistry } from './services/formatters/format-converter-registry';\nimport { TopicIdToHrlConverter } from './services/formatters/converters/topic-id-to-hrl-converter';\nimport { StringNormalizationConverter } from './services/formatters/converters/string-normalization-converter';\n\nexport type ToolDescriptor = {\n name: string;\n namespace?: string;\n};\n\nexport type ChatHistoryItem = {\n type: 'human' | 'ai' | 'system';\n content: string;\n};\n\nexport type AgentInstance = ReturnType<typeof createAgent>;\n\nexport type MirrorNetwork = 'testnet' | 'mainnet' | 'previewnet';\n\nconst DEFAULT_MODEL_NAME = 'gpt-4o';\nconst DEFAULT_OPENAI_MODEL = 'gpt-4o-mini';\nconst DEFAULT_OPENROUTER_MODEL = 'openai/gpt-4o-mini';\nconst DEFAULT_CLAUDE_MODEL = 'claude-3-7-sonnet-latest';\nconst DEFAULT_TEMPERATURE = 0.1;\nconst DEFAULT_NETWORK = 'testnet';\nconst DEFAULT_OPERATIONAL_MODE: AgentOperationalMode = 'autonomous';\n\nexport interface ConversationalAgentOptions {\n accountId: string;\n privateKey: string;\n network?: NetworkType;\n openAIApiKey: string;\n openAIModelName?: string;\n llmProvider?: 'openai' | 'anthropic' | 'openrouter';\n verbose?: boolean;\n operationalMode?: AgentOperationalMode;\n userAccountId?: string;\n customSystemMessagePreamble?: string;\n customSystemMessagePostamble?: string;\n additionalPlugins?: BasePlugin[];\n stateManager?: IStateManager;\n scheduleUserTransactionsInBytesMode?: boolean;\n mirrorNodeConfig?: MirrorNodeConfig;\n disableLogging?: boolean;\n enabledPlugins?: string[];\n disabledPlugins?: string[];\n toolFilter?: (tool: { name: string; namespace?: string }) => boolean;\n mcpServers?: MCPServerConfig[];\n walletExecutor?: (\n base64: string,\n network: 'mainnet' | 'testnet'\n ) => Promise<{ transactionId: string }>;\n /** Optional: provide a signer factory to override default signer selection */\n customSignerFactory?: (args: {\n operationalMode: AgentOperationalMode;\n accountId: string;\n network: NetworkType;\n }) => AbstractSigner;\n\n /** Enable automatic entity memory functionality (default: true) */\n entityMemoryEnabled?: boolean;\n\n /** Configuration for entity memory system */\n entityMemoryConfig?: SmartMemoryConfig;\n\n /**\n * Provider used for entity extraction/resolution tools (defaults to llmProvider or 'openai')\n */\n entityMemoryProvider?: 'openai' | 'anthropic' | 'openrouter';\n\n /**\n * Model name for entity extraction/resolution tools (defaults per provider)\n */\n entityMemoryModelName?: string;\n\n openRouterApiKey?: string;\n openRouterBaseURL?: string;\n}\n\n/**\n * The ConversationalAgent class is an optional wrapper around the HederaConversationalAgent class,\n * which includes the OpenConvAIPlugin and the OpenConvaiState by default.\n * If you want to use a different plugin or state manager, you can pass them in the options.\n * This class is not required and the plugin can be used directly with the HederaConversationalAgent class.\n *\n * @param options - The options for the ConversationalAgent.\n * @returns A new instance of the ConversationalAgent class.\n */\nexport class ConversationalAgent {\n private static readonly NOT_INITIALIZED_ERROR =\n 'Agent not initialized. Call initialize() first.';\n protected agent?: AgentInstance;\n public hcs10Plugin: HCS10Plugin;\n public hcs2Plugin: HCS2Plugin;\n public inscribePlugin: InscribePlugin;\n public hbarPlugin: HbarPlugin;\n public webBrowserPlugin: WebBrowserPlugin;\n public stateManager: IStateManager;\n private options: ConversationalAgentOptions;\n public logger: Logger;\n public contentStoreManager?: ContentStoreManager;\n public memoryManager?: SmartMemoryManager | undefined;\n private entityTools?: {\n resolveEntities: ResolveEntitiesTool;\n extractEntities: ExtractEntitiesTool;\n };\n\n constructor(options: ConversationalAgentOptions) {\n this.options = options;\n this.stateManager = options.stateManager || new OpenConvaiState();\n this.hcs10Plugin = new HCS10Plugin();\n this.hcs2Plugin = new HCS2Plugin();\n this.inscribePlugin = new InscribePlugin();\n this.hbarPlugin = new HbarPlugin();\n this.webBrowserPlugin = new WebBrowserPlugin();\n this.logger = new Logger({\n module: 'ConversationalAgent',\n silent: options.disableLogging || false,\n });\n\n if (this.options.entityMemoryEnabled !== false) {\n if (!options.openAIApiKey) {\n throw new Error(\n 'OpenAI/Anthropic API key is required when entity memory is enabled'\n );\n }\n\n this.memoryManager = new SmartMemoryManager(\n this.options.entityMemoryConfig\n );\n this.logger.info('Entity memory initialized');\n\n const provider =\n options.entityMemoryProvider || options.llmProvider || 'openai';\n let modelName = options.entityMemoryModelName;\n if (!modelName) {\n if (provider === 'anthropic') {\n modelName = DEFAULT_CLAUDE_MODEL;\n } else if (provider === 'openrouter') {\n modelName = DEFAULT_OPENROUTER_MODEL;\n } else {\n modelName = DEFAULT_OPENAI_MODEL;\n }\n }\n\n let resolverLLM: ChatOpenAI | ChatAnthropic;\n if (provider === 'anthropic') {\n resolverLLM = new ChatAnthropic({\n apiKey: options.openAIApiKey,\n model: modelName,\n temperature: 0,\n });\n } else if (provider === 'openrouter') {\n const baseURL =\n options.openRouterBaseURL || 'https://openrouter.ai/api/v1';\n const apiKey = options.openRouterApiKey || options.openAIApiKey;\n resolverLLM = new ChatOpenAI({\n apiKey,\n model: modelName,\n temperature: 0,\n configuration: {\n baseURL,\n defaultHeaders: {\n 'HTTP-Referer':\n process.env.OPENROUTER_REFERRER ||\n 'https://hashgraphonline.com',\n 'X-Title':\n process.env.OPENROUTER_TITLE ||\n 'Hashgraph Online Conversational Agent',\n },\n },\n });\n } else {\n resolverLLM = new ChatOpenAI({\n apiKey: options.openAIApiKey,\n model: modelName,\n temperature: 0,\n });\n }\n\n this.entityTools = createEntityTools(resolverLLM);\n this.logger.info('LLM-based entity resolver tools initialized');\n }\n }\n\n /**\n * Initialize the conversational agent with Hedera Hashgraph connection and AI configuration\n * @throws {Error} If account ID or private key is missing\n * @throws {Error} If initialization fails\n */\n async initialize(): Promise<void> {\n const {\n accountId,\n privateKey,\n network = DEFAULT_NETWORK,\n openAIApiKey,\n openAIModelName = DEFAULT_MODEL_NAME,\n llmProvider = 'openai',\n } = this.options;\n\n this.validateOptions(accountId, privateKey);\n\n try {\n const opMode = (this.options.operationalMode ||\n DEFAULT_OPERATIONAL_MODE) as string;\n const bytesMode = opMode !== 'autonomous';\n let signer: AbstractSigner;\n\n try {\n type InscriberBuilderWithWalletMethods = typeof InscriberBuilder & {\n setPreferWalletOnly?: (prefer: boolean) => void;\n setWalletInfoResolver?: (\n fn: () => Promise<{ accountId: string; network: string } | null>\n ) => void;\n setWalletExecutor?: (\n fn: (\n base64: string,\n network: 'mainnet' | 'testnet'\n ) => Promise<{ transactionId: string }>\n ) => void;\n setStartInscriptionDelegate?: (\n fn: (\n request: Record<string, unknown>,\n network: 'mainnet' | 'testnet'\n ) => Promise<unknown>\n ) => void;\n };\n const IB = InscriberBuilder as InscriberBuilderWithWalletMethods;\n if (typeof IB.setPreferWalletOnly === 'function') {\n IB.setPreferWalletOnly(false);\n }\n } catch (e) {\n this.logger.warn('Failed to set wallet-only preference', e as Error);\n }\n if (!bytesMode) {\n signer = new ServerSigner(\n accountId!,\n privateKey!,\n network as MirrorNetwork\n );\n } else {\n const chain: 'mainnet' | 'testnet' =\n String(network || 'testnet') === 'mainnet' ? 'mainnet' : 'testnet';\n const effectiveAccount = (this.options.userAccountId || accountId)!;\n signer = new BrowserSigner(\n effectiveAccount,\n chain,\n this.options.walletExecutor\n );\n }\n\n this.logger.info('Signer configured', {\n operationalMode: opMode,\n bytesMode,\n signerClass:\n Object.getPrototypeOf(signer)?.constructor?.name || 'unknown',\n });\n\n try {\n const bridge = getWalletBridgeProvider();\n if (bridge) {\n type InscriberBuilderWithWalletMethods = typeof InscriberBuilder & {\n setWalletInfoResolver?: (\n fn: () => Promise<{ accountId: string; network: string } | null>\n ) => void;\n setWalletExecutor?: (\n fn: (\n base64: string,\n network: 'mainnet' | 'testnet'\n ) => Promise<{ transactionId: string }>\n ) => void;\n setStartInscriptionDelegate?: (\n fn: (\n request: Record<string, unknown>,\n network: 'mainnet' | 'testnet'\n ) => Promise<unknown>\n ) => void;\n };\n const IB = InscriberBuilder as InscriberBuilderWithWalletMethods;\n if (typeof IB.setWalletInfoResolver === 'function') {\n IB.setWalletInfoResolver(async () => {\n const status = await bridge.status();\n if (status.connected && status.accountId && status.network) {\n return { accountId: status.accountId, network: status.network };\n }\n return null;\n });\n }\n if (typeof IB.setWalletExecutor === 'function') {\n IB.setWalletExecutor(\n async (base64: string, network: 'mainnet' | 'testnet') => {\n return await bridge.executeBytes(base64, network);\n }\n );\n }\n if (\n typeof IB.setStartInscriptionDelegate === 'function' &&\n bridge.startInscription\n ) {\n IB.setStartInscriptionDelegate(\n async (\n request: Record<string, unknown>,\n network: 'mainnet' | 'testnet'\n ) => {\n return await bridge.startInscription!(request, network);\n }\n );\n }\n\n try {\n type HCSOp =\n | 'submitConnectionRequest'\n | 'handleConnectionRequest'\n | 'sendMessage'\n | 'hcs2.createRegistry'\n | 'hcs2.migrateRegistry'\n | 'hcs2.registerEntry'\n | 'hcs2.updateEntry'\n | 'hcs2.deleteEntry'\n | 'hcs2.submitMessage'\n | 'hcs6.createRegistry'\n | 'hcs6.registerEntry'\n | 'hcs6.submitMessage';\n type WalletBridgeProviderExt = ReturnType<\n typeof getWalletBridgeProvider\n > & {\n startHCS?: (\n op: HCSOp,\n request: Record<string, unknown>,\n network: 'mainnet' | 'testnet'\n ) => Promise<{ transactionBytes: string }>;\n };\n\n const status = await bridge.status();\n const enforceWallet = !!(bytesMode && status.connected);\n\n SignerProviderRegistry.setWalletInfoResolver(async () => {\n const s = await bridge.status();\n if (s.connected && s.accountId && s.network) {\n return {\n accountId: s.accountId,\n network: s.network as 'mainnet' | 'testnet',\n };\n }\n return null;\n });\n\n SignerProviderRegistry.setWalletExecutor(\n async (base64: string, network: 'mainnet' | 'testnet') => {\n return await bridge.executeBytes(base64, network);\n }\n );\n\n const extended = bridge as WalletBridgeProviderExt;\n if (typeof extended?.startHCS === 'function') {\n SignerProviderRegistry.setStartHCSDelegate(\n async (op, request, network) => {\n return await extended.startHCS!(\n op as HCSOp,\n request,\n network\n );\n }\n );\n } else {\n SignerProviderRegistry.setStartHCSDelegate(null);\n }\n\n SignerProviderRegistry.setPreferWalletOnly(enforceWallet);\n\n type InscriberBuilderWithWalletMethods = typeof InscriberBuilder & {\n setPreferWalletOnly?: (prefer: boolean) => void;\n };\n const IB2 = InscriberBuilder as InscriberBuilderWithWalletMethods;\n if (typeof IB2.setPreferWalletOnly === 'function') {\n IB2.setPreferWalletOnly(enforceWallet);\n }\n } catch (sakWireErr) {\n this.logger.warn(\n 'Failed to wire SAK SignerProviderRegistry wallet delegates',\n sakWireErr as Error\n );\n }\n }\n } catch (e) {\n this.logger.warn(\n 'Failed to register wallet bridge providers',\n e as Error\n );\n }\n\n let llm: ChatOpenAI | ChatAnthropic;\n let providerInfo: Record<string, unknown> = { provider: llmProvider };\n if (llmProvider === 'anthropic') {\n llm = new ChatAnthropic({\n apiKey: openAIApiKey,\n model: openAIModelName || DEFAULT_CLAUDE_MODEL,\n temperature: DEFAULT_TEMPERATURE,\n });\n providerInfo = {\n ...providerInfo,\n model: openAIModelName || DEFAULT_CLAUDE_MODEL,\n keyPresent: !!openAIApiKey,\n };\n } else if (llmProvider === 'openrouter') {\n const baseURL =\n this.options.openRouterBaseURL || 'https://openrouter.ai/api/v1';\n const apiKey = this.options.openRouterApiKey || openAIApiKey;\n const modelName =\n openAIModelName || 'anthropic/claude-3-haiku-20240307';\n llm = new ChatOpenAI({\n apiKey,\n model: modelName,\n temperature: DEFAULT_TEMPERATURE,\n configuration: {\n baseURL,\n defaultHeaders: {\n 'HTTP-Referer':\n process.env.OPENROUTER_REFERRER ||\n 'https://hashgraphonline.com',\n 'X-Title':\n process.env.OPENROUTER_TITLE ||\n 'Hashgraph Online Conversational Agent',\n },\n },\n });\n providerInfo = {\n ...providerInfo,\n model: modelName,\n baseURL,\n keyPresent: !!apiKey,\n };\n } else {\n const modelName2 = openAIModelName || DEFAULT_OPENAI_MODEL;\n const isGPT5Model =\n modelName2.toLowerCase().includes('gpt-5') ||\n modelName2.toLowerCase().includes('gpt5');\n llm = new ChatOpenAI({\n apiKey: openAIApiKey,\n model: modelName2,\n ...(isGPT5Model\n ? { temperature: 1 }\n : { temperature: DEFAULT_TEMPERATURE }),\n });\n providerInfo = {\n ...providerInfo,\n model: modelName2,\n keyPresent: !!openAIApiKey,\n };\n }\n\n this.logger.info('AI provider configured', providerInfo);\n\n this.logger.info('Preparing plugins...');\n const allPlugins = this.preparePlugins();\n this.logger.info('Creating agent config...');\n const agentConfig = this.createAgentConfig(\n signer as ServerSigner,\n llm,\n allPlugins\n );\n\n this.logger.info('Creating agent...');\n this.agent = createAgent(agentConfig);\n this.logger.info('Agent created');\n\n this.logger.info('Configuring HCS10 plugin...');\n this.configureHCS10Plugin(allPlugins);\n this.logger.info('HCS10 plugin configured');\n\n this.contentStoreManager = new ContentStoreManager();\n await this.contentStoreManager.initialize();\n this.logger.info(\n 'ContentStoreManager initialized for content reference support'\n );\n\n this.logger.info('About to call agent.boot()');\n this.logger.info('🔥 About to call agent.boot()');\n await this.agent.boot();\n this.logger.info('agent.boot() completed');\n this.logger.info('🔥 agent.boot() completed');\n\n if (this.agent) {\n try {\n const registry = new FormatConverterRegistry();\n registry.register(new TopicIdToHrlConverter());\n registry.register(new StringNormalizationConverter());\n const paramService = new ParameterService(\n registry,\n (this.options.network as unknown as NetworkType) || 'testnet'\n );\n paramService.attachToAgent(this.agent, {\n getEntities: async () =>\n this.memoryManager?.getEntityAssociations() || [],\n });\n this.logger.info(\n 'Parameter preprocessing callback attached (internal)'\n );\n } catch (e) {\n this.logger.warn(\n 'Failed to attach internal parameter preprocessing callback',\n e\n );\n }\n\n const cfg = agentConfig;\n cfg.filtering = cfg.filtering || {};\n const originalPredicate = cfg.filtering.toolPredicate as\n | ((t: ToolDescriptor) => boolean)\n | undefined;\n const userPredicate = this.options.toolFilter;\n cfg.filtering.toolPredicate = (tool: ToolDescriptor): boolean => {\n if (tool && tool.name === 'hedera-account-transfer-hbar') {\n return false;\n }\n if (tool && tool.name === 'hedera-hts-airdrop-token') {\n return false;\n }\n if (originalPredicate && !originalPredicate(tool)) {\n return false;\n }\n if (userPredicate && !userPredicate(tool)) {\n return false;\n }\n return true;\n };\n }\n\n if (this.options.mcpServers && this.options.mcpServers.length > 0) {\n this.connectMCP();\n }\n } catch (error) {\n this.logger.error('Failed to initialize ConversationalAgent:', error);\n throw error;\n }\n }\n\n /**\n * Get the HCS-10 plugin instance\n * @returns {HCS10Plugin} The HCS-10 plugin instance\n */\n getPlugin(): HCS10Plugin {\n return this.hcs10Plugin;\n }\n\n /**\n * Get the state manager instance\n * @returns {IStateManager} The state manager instance\n */\n getStateManager(): IStateManager {\n return this.stateManager;\n }\n\n /**\n * Get the underlying agent instance\n * @returns {ReturnType<typeof createAgent>} The agent instance\n * @throws {Error} If agent is not initialized\n */\n getAgent(): ReturnType<typeof createAgent> {\n if (!this.agent) {\n throw new Error(ConversationalAgent.NOT_INITIALIZED_ERROR);\n }\n return this.agent;\n }\n\n /**\n * Get the conversational agent instance (alias for getAgent)\n * @returns {ReturnType<typeof createAgent>} The agent instance\n * @throws {Error} If agent is not initialized\n */\n getConversationalAgent(): ReturnType<typeof createAgent> {\n return this.getAgent();\n }\n\n /**\n * Process a message through the conversational agent\n * @param {string} message - The message to process\n * @param {Array<{type: 'human' | 'ai'; content: string}>} chatHistory - Previous chat history\n * @returns {Promise<ChatResponse>} The agent's response\n * @throws {Error} If agent is not initialized\n */\n async processMessage(\n message: string,\n chatHistory: ChatHistoryItem[] = []\n ): Promise<ChatResponse> {\n if (!this.agent) {\n throw new Error('Agent not initialized. Call initialize() first.');\n }\n\n try {\n const resolvedMessage = message;\n\n const messages = chatHistory.map((msg) => {\n const content = msg.content;\n if (msg.type === 'system') {\n return new SystemMessage(content);\n }\n return msg.type === 'human'\n ? new HumanMessage(content)\n : new AIMessage(content);\n });\n\n const context: ConversationContext = { messages };\n const response = await this.agent.chat(resolvedMessage, context);\n\n if (\n this.memoryManager &&\n this.options.operationalMode !== 'returnBytes'\n ) {\n await this.extractAndStoreEntities(response, message);\n }\n\n this.logger.info('Message processed successfully');\n return response;\n } catch (error) {\n this.logger.error('Error processing message:', error);\n throw error;\n }\n }\n\n /**\n * Process form submission through the conversational agent\n * @param {FormSubmission} submission - The form submission data\n * @returns {Promise<ChatResponse>} The agent's response after processing the form\n * @throws {Error} If agent is not initialized or doesn't support form processing\n */\n async processFormSubmission(\n submission: FormSubmission\n ): Promise<ChatResponse> {\n if (!this.agent) {\n throw new Error(ConversationalAgent.NOT_INITIALIZED_ERROR);\n }\n\n try {\n this.logger.info('Processing form submission:', {\n formId: submission.formId,\n toolName: submission.toolName,\n parameterKeys: Object.keys(submission.parameters || {}),\n hasContext: !!submission.context,\n });\n const response = await this.agent.processFormSubmission(submission);\n this.logger.info('Form submission processed successfully');\n return response;\n } catch (error) {\n this.logger.error('Error processing form submission:', error);\n throw error;\n }\n }\n\n /**\n * Validates initialization options and throws if required fields are missing.\n *\n * @param accountId - The Hedera account ID\n * @param privateKey - The private key for the account\n * @throws {Error} If required fields are missing\n */\n private validateOptions(accountId?: string, privateKey?: string): void {\n const opMode = (this.options.operationalMode ||\n DEFAULT_OPERATIONAL_MODE) as string;\n const bytesMode = opMode !== 'autonomous';\n if (!accountId) {\n throw new Error('Account ID is required');\n }\n if (!privateKey && !bytesMode) {\n throw new Error('Private key is required in autonomous mode');\n }\n\n if (typeof accountId !== 'string') {\n throw new Error(\n `Account ID must be a string, received ${typeof accountId}`\n );\n }\n\n if (!bytesMode && typeof privateKey !== 'string') {\n throw new Error(\n `Private key must be a string, received ${typeof privateKey}: ${JSON.stringify(\n privateKey\n )}`\n );\n }\n if (\n !bytesMode &&\n typeof privateKey === 'string' &&\n privateKey.length < 10\n ) {\n throw new Error('Private key appears to be invalid (too short)');\n }\n }\n\n /**\n * Prepares the list of plugins to use based on configuration.\n *\n * @returns Array of plugins to initialize with the agent\n */\n private preparePlugins(): BasePlugin[] {\n const { additionalPlugins = [], enabledPlugins, disabledPlugins } = this.options;\n\n const standardPlugins: BasePlugin[] = [\n this.hcs10Plugin,\n this.hcs2Plugin,\n this.inscribePlugin,\n this.hbarPlugin,\n ];\n standardPlugins.push(this.webBrowserPlugin);\n\n const corePlugins = getAllHederaCorePlugins();\n let pluginPool = [...standardPlugins, ...corePlugins];\n\n if (enabledPlugins) {\n const enabledSet = new Set(enabledPlugins);\n pluginPool = pluginPool.filter((plugin) => enabledSet.has(plugin.id));\n }\n\n if (disabledPlugins && disabledPlugins.length > 0) {\n const disabledSet = new Set(disabledPlugins);\n pluginPool = pluginPool.filter((plugin) => !disabledSet.has(plugin.id));\n }\n\n const additional = disabledPlugins && disabledPlugins.length > 0\n ? additionalPlugins.filter((plugin) => !disabledPlugins.includes(plugin.id))\n : additionalPlugins;\n\n return [...pluginPool, ...additional];\n }\n\n /**\n * Creates the agent configuration object.\n *\n * @param signer - The signer instance\n * @param llm - The language model instance\n * @param allPlugins - Array of plugins to use\n * @returns Configuration object for creating the agent\n */\n private createAgentConfig(\n signer: ServerSigner,\n llm: ChatOpenAI | ChatAnthropic,\n allPlugins: BasePlugin[]\n ): Parameters<typeof createAgent>[0] {\n const {\n operationalMode = DEFAULT_OPERATIONAL_MODE,\n userAccountId,\n scheduleUserTransactionsInBytesMode,\n customSystemMessagePreamble,\n customSystemMessagePostamble,\n verbose = false,\n mirrorNodeConfig,\n disableLogging,\n accountId = '',\n } = this.options;\n\n return {\n framework: 'langchain',\n signer,\n execution: {\n mode: operationalMode === 'autonomous' ? 'direct' : 'bytes',\n operationalMode: operationalMode,\n ...(userAccountId && { userAccountId }),\n ...(scheduleUserTransactionsInBytesMode !== undefined && {\n scheduleUserTransactionsInBytesMode:\n scheduleUserTransactionsInBytesMode,\n scheduleUserTransactions: scheduleUserTransactionsInBytesMode,\n }),\n },\n ai: {\n provider: new LangChainProvider(llm),\n temperature: DEFAULT_TEMPERATURE,\n },\n filtering: {\n toolPredicate: (tool: ToolDescriptor): boolean => {\n if (tool.name === 'hedera-account-transfer-hbar') return false;\n if (this.options.toolFilter && !this.options.toolFilter(tool)) {\n return false;\n }\n return true;\n },\n },\n messaging: {\n systemPreamble:\n customSystemMessagePreamble || getSystemMessage(accountId),\n ...(customSystemMessagePostamble && {\n systemPostamble: customSystemMessagePostamble,\n }),\n conciseMode: true,\n },\n extensions: {\n plugins: allPlugins,\n ...(mirrorNodeConfig && {\n mirrorConfig: mirrorNodeConfig as Record<string, unknown>,\n }),\n },\n ...(this.options.mcpServers && {\n mcp: {\n servers: this.options.mcpServers,\n autoConnect: false,\n },\n }),\n debug: {\n verbose,\n silent: disableLogging ?? false,\n },\n };\n }\n\n /**\n * Configures the HCS-10 plugin with the state manager.\n *\n * @param allPlugins - Array of all plugins\n */\n private configureHCS10Plugin(allPlugins: BasePlugin[]): void {\n const hcs10 = allPlugins.find((p) => p.id === 'hcs-10');\n if (hcs10) {\n (\n hcs10 as BasePlugin & { appConfig?: Record<string, unknown> }\n ).appConfig = {\n stateManager: this.stateManager,\n };\n }\n }\n\n /**\n * Create a ConversationalAgent with specific plugins enabled\n */\n private static withPlugins(\n options: ConversationalAgentOptions,\n plugins: string[]\n ): ConversationalAgent {\n return new ConversationalAgent({\n ...options,\n enabledPlugins: plugins,\n });\n }\n\n /**\n * Create a ConversationalAgent with only HTS (Hedera Token Service) tools enabled\n */\n static withHTS(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['hts-token']);\n }\n\n /**\n * Create a ConversationalAgent with only HCS-2 tools enabled\n */\n static withHCS2(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['hcs-2']);\n }\n\n /**\n * Create a ConversationalAgent with only HCS-10 tools enabled\n */\n static withHCS10(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['hcs-10']);\n }\n\n /**\n * Create a ConversationalAgent with only inscription tools enabled\n */\n static withInscribe(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['inscribe']);\n }\n\n /**\n * Create a ConversationalAgent with only account management tools enabled\n */\n static withAccount(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, ['account']);\n }\n\n /**\n * Create a ConversationalAgent with only file service tools enabled\n */\n static withFileService(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['file-service']);\n }\n\n /**\n * Create a ConversationalAgent with only consensus service tools enabled\n */\n static withConsensusService(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['consensus-service']);\n }\n\n /**\n * Create a ConversationalAgent with only smart contract tools enabled\n */\n static withSmartContract(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['smart-contract']);\n }\n\n /**\n * Create a ConversationalAgent with all HCS standards plugins\n */\n static withAllStandards(\n options: ConversationalAgentOptions\n ): ConversationalAgent {\n return this.withPlugins(options, ['hcs-10', 'hcs-2', 'inscribe']);\n }\n\n /**\n * Create a ConversationalAgent with minimal Hedera tools (no HCS standards)\n */\n static minimal(options: ConversationalAgentOptions): ConversationalAgent {\n return this.withPlugins(options, []);\n }\n\n /**\n * Create a ConversationalAgent with MCP servers configured\n */\n static withMCP(\n options: ConversationalAgentOptions,\n mcpServers: MCPServerConfig[]\n ): ConversationalAgent {\n return new ConversationalAgent({\n ...options,\n mcpServers,\n });\n }\n\n /**\n * Extract and store entities from agent responses\n * @param response - Agent response containing potential entity information\n * @param originalMessage - Original user message for context\n */\n private async extractAndStoreEntities(\n response: unknown,\n originalMessage: string\n ): Promise<void> {\n if (!this.memoryManager || !this.entityTools) {\n return;\n }\n\n try {\n this.logger.info('Starting LLM-based entity extraction');\n\n const responseText = this.extractResponseText(response);\n\n const entitiesJson = await this.entityTools.extractEntities.call({\n response: responseText,\n userMessage: originalMessage,\n });\n\n try {\n const entities = JSON.parse(entitiesJson);\n\n for (const entity of entities) {\n if (\n entity &&\n typeof entity === 'object' &&\n 'name' in entity &&\n 'type' in entity &&\n 'id' in entity\n ) {\n this.logger.info(\n `Storing entity: ${entity.name} (${entity.type}) -> ${entity.id}`\n );\n\n const transactionId = this.extractTransactionId(response);\n const idStr = String(entity.id);\n const isHederaId = /^0\\.0\\.[0-9]+$/.test(idStr);\n if (!isHederaId) {\n this.logger.warn('Skipping non-ID entity from extraction', {\n id: idStr,\n name: String(entity.name),\n type: String(entity.type),\n });\n } else {\n this.memoryManager.storeEntityAssociation(\n idStr,\n String(entity.name),\n String(entity.type),\n transactionId\n );\n }\n }\n }\n\n if (entities.length > 0) {\n this.logger.info(\n `Stored ${entities.length} entities via LLM extraction`\n );\n } else {\n this.logger.info('No entities found in response via LLM extraction');\n }\n } catch (parseError) {\n this.logger.error(\n 'Failed to parse extracted entities JSON:',\n parseError\n );\n throw parseError;\n }\n } catch (error) {\n this.logger.error('Entity extraction failed:', error);\n throw error;\n }\n }\n\n /**\n * Extract transaction ID from response if available\n * @param response - Transaction response\n * @returns Transaction ID or undefined\n */\n private extractTransactionId(response: unknown): string | undefined {\n try {\n if (\n typeof response === 'object' &&\n response &&\n 'transactionId' in response\n ) {\n const responseWithTxId = response as { transactionId?: unknown };\n return typeof responseWithTxId.transactionId === 'string'\n ? responseWithTxId.transactionId\n : undefined;\n }\n if (typeof response === 'string') {\n const match = response.match(\n /transaction[\\s\\w]*ID[\\s:\"]*([0-9a-fA-F@._-]+)/i\n );\n return match ? match[1] : undefined;\n }\n return undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Connect to MCP servers asynchronously\n * @private\n */\n private connectMCP(): void {\n if (!this.agent || !this.options.mcpServers) {\n return;\n }\n\n this.agent\n .connectMCPServers()\n .catch((e) => {\n this.logger.error('Failed to connect MCP servers:', e);\n })\n .then(() => {\n this.logger.info('MCP servers connected successfully');\n });\n }\n\n /**\n * Get MCP connection status for all servers\n * @returns {Map<string, MCPConnectionStatus>} Connection status map\n */\n getMCPConnectionStatus(): Map<string, MCPConnectionStatus> {\n if (this.agent) {\n return this.agent.getMCPConnectionStatus();\n }\n return new Map();\n }\n\n /**\n * Check if a specific MCP server is connected\n * @param {string} serverName - Name of the server to check\n * @returns {boolean} True if connected, false otherwise\n */\n isMCPServerConnected(serverName: string): boolean {\n if (this.agent) {\n const statusMap = this.agent.getMCPConnectionStatus();\n const status = statusMap.get(serverName);\n return status?.connected ?? false;\n }\n return false;\n }\n\n /**\n * Clean up resources\n */\n async cleanup(): Promise<void> {\n try {\n this.logger.info('Cleaning up ConversationalAgent...');\n\n if (this.memoryManager) {\n try {\n this.memoryManager.dispose();\n this.logger.info('Memory manager cleaned up successfully');\n } catch (error) {\n this.logger.warn('Error cleaning up memory manager:', error);\n }\n this.memoryManager = undefined;\n }\n\n if (this.contentStoreManager) {\n await this.contentStoreManager.dispose();\n this.logger.info('ContentStoreManager cleaned up');\n }\n\n this.logger.info('ConversationalAgent cleanup completed');\n } catch (error) {\n this.logger.error('Error during cleanup:', error);\n }\n }\n\n /**\n * Switch operational mode\n */\n switchMode(mode?: AgentOperationalMode): void {\n if (this.agent?.switchMode) {\n this.agent.switchMode(mode || 'autonomous');\n }\n }\n\n /**\n * Get usage statistics\n */\n getUsageStats(): unknown {\n return this.agent?.getUsageStats?.() ?? {};\n }\n\n /**\n * Clear usage statistics\n */\n clearUsageStats(): void {\n if (this.agent?.clearUsageStats) {\n this.agent.clearUsageStats();\n }\n }\n\n /**\n * Shutdown the agent\n */\n shutdown(): Promise<void> {\n return this.agent?.shutdown?.() ?? Promise.resolve();\n }\n\n private extractResponseText(response: unknown): string {\n if (typeof response === 'string') {\n return response;\n }\n\n if (response && typeof response === 'object' && 'output' in response) {\n const responseWithOutput = response as { output: unknown };\n return String(responseWithOutput.output);\n }\n\n return JSON.stringify(response);\n }\n}\n","import { Logger } from '@hashgraphonline/standards-sdk';\nimport type { ContentStoreManager as PackageContentStoreManager } from './content-store-manager';\n\nexport interface AttachmentData {\n name: string;\n data: string;\n type: string;\n size: number;\n}\n\nexport type ContentStoreManager = PackageContentStoreManager;\n\n/**\n * Utility for processing file attachments and content references\n */\nexport class AttachmentProcessor {\n private logger: Logger;\n\n constructor() {\n this.logger = new Logger({ module: 'AttachmentProcessor' });\n }\n\n /**\n * Process attachments and create content references\n */\n async processAttachments(\n content: string,\n attachments: AttachmentData[],\n contentStoreManager?: ContentStoreManager\n ): Promise<string> {\n if (attachments.length === 0) {\n return content;\n }\n\n this.logger.info('Processing attachments with content reference system:', {\n attachmentCount: attachments.length,\n totalSize: attachments.reduce((sum, att) => sum + att.size, 0),\n });\n\n if (contentStoreManager && contentStoreManager.isInitialized()) {\n return this.processWithContentStore(content, attachments, contentStoreManager);\n } else {\n this.logger.warn('Content storage not available, creating simple file references');\n return this.processWithSimpleReferences(content, attachments);\n }\n }\n\n /**\n * Process attachments using content store manager\n */\n private async processWithContentStore(\n content: string,\n attachments: AttachmentData[],\n contentStoreManager: ContentStoreManager\n ): Promise<string> {\n const contentReferences: string[] = [];\n\n for (const attachment of attachments) {\n try {\n const base64Data = attachment.data.includes('base64,')\n ? attachment.data.split('base64,')[1]\n : attachment.data;\n const buffer = Buffer.from(base64Data, 'base64');\n\n const contentRef = await contentStoreManager.storeContentIfLarge(\n buffer,\n {\n mimeType: attachment.type,\n source: 'user_upload',\n fileName: attachment.name,\n tags: ['attachment', 'user_file'],\n }\n );\n\n if (contentRef) {\n if (attachment.type.startsWith('image/')) {\n contentReferences.push(\n `[Image File: ${attachment.name}] (content-ref:${contentRef.referenceId})`\n );\n } else {\n contentReferences.push(\n `[File: ${attachment.name}] (content-ref:${contentRef.referenceId})`\n );\n }\n } else {\n contentReferences.push(\n this.createInlineReference(attachment, base64Data)\n );\n }\n } catch (error) {\n this.logger.error('Failed to process attachment:', {\n fileName: attachment.name,\n error: error instanceof Error ? error.message : 'Unknown error',\n });\n contentReferences.push(\n `[File: ${attachment.name} - Error processing file: ${\n error instanceof Error ? error.message : 'Unknown error'\n }]`\n );\n }\n }\n\n const fileList = this.createFileList(attachments);\n return content\n ? `${content}\\n\\nAttached files:\\n${fileList}\\n\\n${contentReferences.join('\\n')}`\n : `Attached files:\\n${fileList}\\n\\n${contentReferences.join('\\n')}`;\n }\n\n /**\n * Process attachments with simple file references\n */\n private processWithSimpleReferences(content: string, attachments: AttachmentData[]): string {\n const fileReferences = attachments.map((attachment) => {\n const sizeStr = this.formatFileSize(attachment.size);\n\n if (attachment.type.startsWith('image/')) {\n return `📎 Image: ${attachment.name} (${sizeStr}, ${attachment.type})`;\n } else {\n return `📎 File: ${attachment.name} (${sizeStr}, ${attachment.type})`;\n }\n });\n\n return content\n ? `${content}\\n\\nAttached files:\\n${fileReferences.join('\\n')}`\n : `Attached files:\\n${fileReferences.join('\\n')}`;\n }\n\n /**\n * Create inline reference for small files\n */\n private createInlineReference(attachment: AttachmentData, base64Data: string): string {\n if (attachment.size < 50000) {\n if (attachment.type.startsWith('image/')) {\n return `![${attachment.name}](data:${attachment.type};base64,${base64Data})`;\n } else {\n return `[File: ${attachment.name} (${this.formatFileSize(attachment.size)})]\\nContent: ${base64Data}`;\n }\n } else {\n return `[File: ${attachment.name} (${this.formatFileSize(attachment.size)}) - Content too large to include inline]`;\n }\n }\n\n /**\n * Create formatted file list\n */\n private createFileList(attachments: AttachmentData[]): string {\n return attachments\n .map((file) => {\n const sizeStr = this.formatFileSize(file.size);\n return `📎 ${file.name} (${sizeStr})`;\n })\n .join('\\n');\n }\n\n /**\n * Format file size for display\n */\n private formatFileSize(size: number): string {\n return size >= 1024 * 1024\n ? `${(size / (1024 * 1024)).toFixed(1)}MB`\n : `${(size / 1024).toFixed(1)}KB`;\n }\n}\n","import { ChatOpenAI } from '@langchain/openai';\nimport { Logger } from '@hashgraphonline/standards-sdk';\nimport type { EntityAssociation } from '../memory/smart-memory-manager';\nimport { ENTITY_PATTERNS } from '../constants';\nimport { EntityFormat } from '..';\n\nexport interface EntityResolverConfig {\n apiKey: string;\n modelName?: string;\n}\n\ninterface EntityIdValue {\n toString(): string;\n}\n\ninterface TransactionReceipt {\n tokenId?: EntityIdValue | string;\n topicId?: EntityIdValue | string;\n accountId?: EntityIdValue | string;\n contractId?: EntityIdValue | string;\n fileId?: EntityIdValue | string;\n scheduleId?: EntityIdValue | string;\n}\n\ninterface TransactionResponse {\n success?: boolean;\n receipt?: TransactionReceipt;\n result?: {\n receipt?: TransactionReceipt;\n transactionId?: string;\n };\n data?: {\n receipt?: TransactionReceipt;\n };\n transactionId?: string;\n}\n\ninterface ExtractedEntity {\n id: string;\n name: string;\n type: EntityFormat;\n transactionId?: string;\n}\n\n/**\n * LLM-based entity resolver that replaces brittle regex patterns\n */\nexport class EntityResolver {\n private llm: ChatOpenAI;\n private logger: Logger;\n\n constructor(config: EntityResolverConfig) {\n this.llm = new ChatOpenAI({\n apiKey: config.apiKey,\n modelName: config.modelName || 'gpt-4o-mini',\n temperature: 0,\n });\n this.logger = new Logger({ module: 'EntityResolver' });\n }\n\n /**\n * Resolve entity references using LLM instead of regex\n */\n async resolveReferences(\n message: string,\n entities: EntityAssociation[]\n ): Promise<string> {\n if (!entities || entities.length === 0) {\n return message;\n }\n\n const byType = entities.reduce((acc, e) => {\n if (!acc[e.entityType]) acc[e.entityType] = [];\n acc[e.entityType].push(e);\n return acc;\n }, {} as Record<string, EntityAssociation[]>);\n\n try {\n const stats = Object.fromEntries(\n Object.entries(byType).map(([type, list]) => [\n type,\n {\n count: list.length,\n mostRecent: list[0]?.entityId,\n },\n ])\n );\n this.logger.info('resolveReferences: input summary', {\n messagePreview: message.substring(0, 200),\n entityStats: stats,\n });\n } catch {}\n\n let context = 'Available entities in memory:\\n';\n for (const [type, list] of Object.entries(byType)) {\n const recent = list[0];\n context += `Most recent ${type}: \"${recent.entityName}\" = ${recent.entityId}\\n`;\n if (list.length > 1) {\n context += ` (${list.length - 1} other ${type}s in memory)\\n`;\n }\n }\n\n const prompt = `Task: Replace entity references with their IDs from memory. STRICT TYPE RULES:\n\n- For phrases referring to \"${ENTITY_PATTERNS.TOKEN_REFERENCE}\" or actions that clearly require a token (create/mint/airdrop/associate/etc.), resolve to the most recent TOKEN entity ID (never a topic or account).\n- For phrases referring to \"${ENTITY_PATTERNS.TOPIC_REFERENCE}\" or actions that clearly require a topic (inscribe/publish/consensus/etc.), resolve to the most recent TOPIC entity ID (never a token or account).\n- Do not infer or invent entity IDs. Only use those present in the provided context.\n\n${context}\n\nUser message: \"${message}\"\n\nInstructions:\n- If the user says \"${ENTITY_PATTERNS.TOPIC_REFERENCE}\" or \"that topic\" → replace with the most recent topic ID\n- If the user says \"${ENTITY_PATTERNS.TOKEN_REFERENCE}\" or \"that token\" → replace with the most recent token ID (never a topic)\n- If the user says \"it\" or \"that\" after an action verb → replace with the most recent entity ID\n- Examples:\n * \"submit on ${ENTITY_PATTERNS.TOPIC_REFERENCE}\" → \"submit on 0.0.6543472\"\n * \"airdrop ${ENTITY_PATTERNS.TOKEN_REFERENCE}\" → \"airdrop 0.0.123456\"\n * \"send a message to it\" → \"send a message to 0.0.6543472\"\n\nReturn ONLY the message with replacements made. Do not add any explanations.\nResolved message:`;\n\n try {\n const response = await this.llm.invoke(prompt);\n const resolved = (response.content as string).trim();\n\n const changed = resolved !== message;\n try {\n this.logger.info('resolveReferences: resolution result', {\n changed,\n hasEntityId: /\\b0\\.0\\.\\d+\\b/.test(resolved),\n resolvedPreview: resolved.substring(0, 200),\n });\n } catch {}\n\n if (changed && resolved.includes('0.0.')) {\n return resolved;\n }\n\n return message;\n } catch {\n return message;\n }\n }\n\n /**\n * Extract entities from agent response using receipt data (preferred) or LLM fallback\n */\n async extractEntities(\n response: unknown,\n userMessage: string\n ): Promise<ExtractedEntity[]> {\n const receiptEntities = this.extractFromReceipt(response, userMessage);\n if (receiptEntities.length > 0) {\n return receiptEntities;\n }\n\n return this.extractWithLLM(response, userMessage);\n }\n\n /**\n * Extract entities from transaction receipt data (primary method)\n */\n private extractFromReceipt(\n response: unknown,\n userMessage: string\n ): ExtractedEntity[] {\n const entities: ExtractedEntity[] = [];\n\n let parsedResponse: TransactionResponse;\n try {\n parsedResponse =\n typeof response === 'string'\n ? JSON.parse(response)\n : (response as TransactionResponse);\n } catch {\n parsedResponse = response as TransactionResponse;\n }\n\n if (!parsedResponse || parsedResponse.success === false) {\n return entities;\n }\n\n const receipt =\n parsedResponse.receipt ||\n parsedResponse.result?.receipt ||\n parsedResponse.data?.receipt;\n\n if (!receipt) {\n return entities;\n }\n\n const entityName = this.extractNameFromMessage(userMessage);\n\n const transactionId =\n parsedResponse.transactionId ||\n parsedResponse.result?.transactionId ||\n undefined;\n\n const extractEntityId = (entityId: EntityIdValue | string): string => {\n if (typeof entityId === 'string') {\n return entityId;\n }\n if (\n entityId &&\n typeof entityId === 'object' &&\n typeof entityId.toString === 'function'\n ) {\n if (entityId.toString !== Object.prototype.toString) {\n return entityId.toString();\n }\n }\n return String(entityId);\n };\n\n if (receipt.tokenId) {\n const entity: ExtractedEntity = {\n id: extractEntityId(receipt.tokenId),\n name: entityName,\n type: EntityFormat.TOKEN_ID,\n };\n if (transactionId) {\n entity.transactionId = transactionId;\n }\n entities.push(entity);\n }\n\n if (receipt.topicId) {\n const entity: ExtractedEntity = {\n id: extractEntityId(receipt.topicId),\n name: entityName,\n type: EntityFormat.TOPIC_ID,\n };\n if (transactionId) {\n entity.transactionId = transactionId;\n }\n entities.push(entity);\n }\n\n if (receipt.accountId) {\n const entity: ExtractedEntity = {\n id: extractEntityId(receipt.accountId),\n name: entityName,\n type: EntityFormat.ACCOUNT_ID,\n };\n if (transactionId) {\n entity.transactionId = transactionId;\n }\n entities.push(entity);\n }\n\n if (receipt.contractId) {\n const entity: ExtractedEntity = {\n id: extractEntityId(receipt.contractId),\n name: entityName,\n type: EntityFormat.CONTRACT_ID,\n };\n if (transactionId) {\n entity.transactionId = transactionId;\n }\n entities.push(entity);\n }\n\n if (receipt.fileId) {\n const entity: ExtractedEntity = {\n id: extractEntityId(receipt.fileId),\n name: entityName,\n type: EntityFormat.FILE_ID,\n };\n if (transactionId) {\n entity.transactionId = transactionId;\n }\n entities.push(entity);\n }\n\n if (receipt.scheduleId) {\n const entity: ExtractedEntity = {\n id: extractEntityId(receipt.scheduleId),\n name: entityName,\n type: EntityFormat.SCHEDULE_ID,\n };\n if (transactionId) {\n entity.transactionId = transactionId;\n }\n entities.push(entity);\n }\n\n return entities;\n }\n\n /**\n * Extract entity name from user message\n */\n private extractNameFromMessage(message: string): string {\n const quotedMatch = message.match(/\"([^\"]+)\"/);\n if (quotedMatch) return quotedMatch[1];\n\n const calledMatch = message.match(/called\\s+([A-Za-z0-9#\\s_-]+?)(?:\\s|$)/i);\n if (calledMatch) return calledMatch[1].trim();\n\n const forMatch = message.match(/for\\s+([A-Za-z0-9#\\s_-]+)/i);\n if (forMatch) return forMatch[1].trim();\n\n const namedMatch = message.match(\n /(?:token|topic|account|contract)\\s+([A-Za-z0-9#_-]+)/i\n );\n if (namedMatch) return namedMatch[1].trim();\n\n if (message.includes('new account')) return 'new account';\n\n return 'unnamed_entity';\n }\n\n /**\n * Extract entities using LLM (fallback method)\n */\n private async extractWithLLM(\n response: unknown,\n userMessage: string\n ): Promise<ExtractedEntity[]> {\n const text =\n typeof response === 'string' ? response : JSON.stringify(response);\n\n const prompt = `Analyze this agent response and extract ONLY newly created entities.\n\nUser asked: \"${userMessage.substring(0, 200)}\"\n\nAgent response: ${text.substring(0, 3000)}\n\nCRITICAL: Only extract Hedera entity IDs in the format 0.0.XXXXX (shard.realm.number).\nDO NOT extract:\n- Token symbols (e.g., \"FOREV\", \"USDC\", \"HBAR\")\n- Token names (e.g., \"Forever\", \"My Token\")\n- Transaction IDs (format: 0.0.XXX@timestamp)\n- Account aliases or mnemonics\n\nLook for:\n1. Success messages with entity IDs (e.g., \"Successfully created topic 0.0.6543472\")\n2. Transaction confirmations that created new entities\n3. Entity IDs that appear after words like \"created\", \"new\", \"successfully\"\n\nDO NOT include:\n- Token symbols or names (these are NOT entity IDs)\n- Account IDs that already existed (like sender/receiver accounts)\n- Entity IDs that were parameters to the operation\n- Failed operations\n- Anything that doesn't match the 0.0.XXXXX format\n\nReturn a JSON array of newly created entities:\n[{\"id\": \"0.0.XXX\", \"name\": \"descriptive_name\", \"type\": \"topic|token|account\"}]\n\nIf no entities were created, return: []\n\nJSON:`;\n\n try {\n const response = await this.llm.invoke(prompt);\n const content = response.content as string;\n const match = content.match(/\\[[\\s\\S]*?\\]/);\n if (match) {\n const entities = JSON.parse(match[0]);\n return entities;\n }\n } catch {}\n return [];\n }\n\n /**\n * Validate that an entity matches the expected type\n */\n validateEntityType(\n entityId: string,\n expectedType: string,\n entities: EntityAssociation[]\n ): boolean {\n const stored = entities.find((e) => e.entityId === entityId);\n return !!stored && stored.entityType === expectedType;\n }\n\n /**\n * Resolve entity references with type validation\n */\n async resolveWithTypeValidation(\n query: string,\n entities: EntityAssociation[],\n expectedType?: string\n ): Promise<EntityAssociation[]> {\n await this.resolveReferences(query, entities);\n\n if (!expectedType) {\n return entities;\n }\n\n return entities.filter((entity) => entity.entityType === expectedType);\n }\n\n /**\n * Get entities filtered by type\n */\n getEntitiesByType(\n entities: EntityAssociation[],\n entityType: string\n ): EntityAssociation[] {\n return entities.filter((entity) => entity.entityType === entityType);\n }\n\n /**\n * Find the most recent entity of a specific type\n */\n getMostRecentEntityByType(\n entities: EntityAssociation[],\n entityType: string\n ): EntityAssociation | null {\n const filtered = entities.filter(\n (entity) => entity.entityType === entityType\n );\n if (filtered.length === 0) return null;\n\n return filtered.reduce((most, current) =>\n current.createdAt > most.createdAt ? current : most\n );\n }\n}\n","import type { MCPServerConfig } from './types';\n\n/**\n * Common MCP server configurations for easy setup\n */\nexport const MCPServers = {\n /**\n * Filesystem server for file operations\n */\n filesystem: (path: string): MCPServerConfig => ({\n name: 'filesystem',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-filesystem', path],\n transport: 'stdio',\n autoConnect: true,\n additionalContext: 'This server provides access to files and directories in the current working directory.',\n toolDescriptions: {\n list_directory: 'Use this tool when users ask about files in the \"current directory\" or \"working directory\".',\n read_file: 'Use this tool when users ask to see or check files in the current directory.',\n },\n }),\n\n /**\n * GitHub server for repository operations\n */\n github: (token?: string): MCPServerConfig => ({\n name: 'github',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-github'],\n ...(token && { env: { GITHUB_TOKEN: token } }),\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * Slack server for messaging operations\n */\n slack: (token: string): MCPServerConfig => ({\n name: 'slack',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-slack'],\n env: { SLACK_TOKEN: token },\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * Google Drive server for document operations\n */\n googleDrive: (credentials: string): MCPServerConfig => ({\n name: 'google-drive',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-google-drive'],\n env: { GOOGLE_CREDENTIALS: credentials },\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * PostgreSQL server for database operations\n */\n postgres: (connectionString: string): MCPServerConfig => ({\n name: 'postgres',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-postgres', connectionString],\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * SQLite server for database operations\n */\n sqlite: (dbPath: string): MCPServerConfig => ({\n name: 'sqlite',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-sqlite', dbPath],\n transport: 'stdio',\n autoConnect: true,\n }),\n\n /**\n * Custom server configuration\n */\n custom: (config: MCPServerConfig): MCPServerConfig => config,\n};\n\n/**\n * Validate MCP server configuration\n */\nexport function validateServerConfig(config: MCPServerConfig): string[] {\n const errors: string[] = [];\n\n if (!config.name) {\n errors.push('Server name is required');\n }\n\n if (!config.command) {\n errors.push('Server command is required');\n }\n\n if (!config.args || !Array.isArray(config.args)) {\n errors.push('Server args must be an array');\n }\n\n if (config.transport && !['stdio', 'http', 'websocket'].includes(config.transport)) {\n errors.push('Invalid transport type. Must be stdio, http, or websocket');\n }\n\n return errors;\n}\n\n/**\n * Create a typed MCP configuration for ConversationalAgent\n */\nexport function createMCPConfig(servers: MCPServerConfig[], autoConnect = true): { mcpServers: MCPServerConfig[] } {\n return {\n mcpServers: servers.map(server => ({\n ...server,\n autoConnect: server.autoConnect ?? autoConnect,\n })),\n };\n}"],"names":["HCS10Plugin","BasePlugin","constructor","super","arguments","this","id","name","description","version","author","namespace","tools","initialize","context","hederaKit","config","stateManager","appConfig","OpenConvaiState","accountId","signer","getAccountId","toString","isBytesMode","String","operationalMode","operatorPrivateKeySerialized","inboundTopicId","outboundTopicId","operatorPrivateKeyRef","getOperatorPrivateKey","hcs10Client","HCS10Client","network","operatorId","operatorPrivateKey","logLevel","profileResponse","retrieveProfile","success","topicInfo","inboundTopic","outboundTopic","profileError","logger","warn","agentRecord","privateKey","setCurrentAgent","info","getConnectionsManager","initializeConnectionsManager","cmError","initializeTools","error","Error","hcs10Builder","HCS10Builder","RegisterAgentTool","FindRegistrationsTool","RetrieveProfileTool","InitiateConnectionTool","ListConnectionsTool","SendMessageToConnectionTool","CheckMessagesTool","ConnectionMonitorTool","ManageConnectionRequestsTool","AcceptConnectionRequestTool","ListUnapprovedConnectionRequestsTool","getTools","getStateManager","cleanup","HCS2Plugin","hcs2Builder","HCS2Builder","CreateRegistryTool","RegisterEntryTool","UpdateEntryTool","DeleteEntryTool","MigrateRegistryTool","QueryRegistryTool","fieldGuidanceRegistry","configurations","providers","registerOrderCounter","Logger","module","registerToolConfiguration","push","registerToolProvider","toolPattern","provider","options","length","priority","some","p","pattern","order","unregisterProvider","filter","listProviders","map","getFieldGuidance","toolName","fieldName","process","env","CA_FORM_GUIDANCE_ENABLED","toLowerCase","includes","test","fields","staticGuidance","pickMatchingProviders","merged","reverse","fromProvider","safeGetFieldGuidance","mergeGuidance","g","Object","keys","getGlobalGuidance","globalGuidance","base","mergedWarnings","warnings","mergedQuality","qualityStandards","safeGetGlobalGuidance","result","validateFieldValue","value","guidance","errors","isValid","warning","message","validationRules","rejectPatterns","qualityChecks","reject","reason","forbidTechnicalTerms","lowerValue","term","requireSpecificTerms","join","minNonTechnicalWords","split","word","clear","sort","a","b","m","winner","err","over","out","suggestions","predefinedOptions","fieldTypeOverride","contextualHelpText","InscribePlugin","providerId","e","inscriberBuilder","InscriberBuilder","InscribeFromUrlTool","InscribeFromFileTool","InscribeFromBufferTool","InscribeHashinalTool","RetrieveInscriptionTool","AccountBuilder","BaseServiceBuilder","transferHbar","params","isUserInitiated","clearNotes","transaction","TransferTransaction","transfers","netZeroInTinybars","BigNumber","userTransferProcessedForScheduling","kit","userAccountId","receiverTransfer","amountValue","amount","amountBigNum","isPositive","recipientAccountId","AccountId","fromString","roundedAmount","toFixed","ROUND_DOWN","sdkHbarAmount","Hbar","addNote","addHbarTransfer","negated","processedTransfers","transferInput","hbar","tinybarsContribution","toTinybars","plus","isZero","lastTransfer","adjustment","dividedBy","adjustedRounded","transfer","memo","setTransactionMemo","setCurrentTransaction","HbarTransferInputSchema","z","object","string","describe","union","number","TransferHbarZodSchemaCore","array","min","optional","TransferHbarTool","BaseHederaTransactionTool","specificInputSchema","getServiceBuilder","callBuilderMethod","builder","specificArgs","AirdropToolWrapper","StructuredTool","originalTool","agentKit","schema","tokenId","recipients","_call","input","decimals","getTokenInfo","convertedRecipients","recipient","humanAmount","parseFloat","smallestUnitAmount","convertToSmallestUnits","convertedInput","Math","floor","pow","queryTokenInfo","mirrorNode","tokenData","parseInt","mirrorNodeUrl","response","fetch","ok","json","HbarPlugin","originalAirdropTool","airdropTool","HederaAirdropTokenTool","wrappedAirdropTool","shutdown","NOT_FOUND_STATUS","BAD_REQUEST_STATUS","GATEWAY_STAMP_ERROR_MESSAGE","GATEWAY_TAG_ERROR_MESSAGE","hexToBytes","hex","bytes","Uint8Array","i","slice","getBatchSummary","batch","stampID","batchID","toHex","usage","usageText","capacity","remainingSize","toFormattedString","size","immutable","immutableFlag","ttl","duration","represent","toEndDate","toDateString","getResponseWithStructuredContent","data","content","type","text","JSON","stringify","structuredContent","errorHasStatus","status","getErrorMessage","responseBody","getUploadPostageBatchId","async","argsPostageBatchId","bee","postageBatchId","autoAssignStamp","maxRemainingSize","getPostageBatches","forEach","usable","toBytes","dateUnits","ms","milli","millis","millisecond","milliseconds","s","sec","second","seconds","minute","minutes","h","hour","hours","d","day","days","w","week","weeks","month","months","y","year","years","makeDate","numberWithUnit","isNaN","unit","replace","trim","multiplier","ListPostageStampsSchema","leastUsed","boolean","limit","minUsage","maxUsage","ListPostageStampsTool","BaseHederaQueryTool","rest","executeQuery","rawPostageBatches","errorMessage","filteredPostageBatches","usagePercentage","Boolean","batch1","batch2","computedPostageBatches","raw","summary","UploadDataSchema","redundancyLevel","UploadDataTool","inputPostageBatchId","binaryData","globalThis","Buffer","from","uploadData","reference","url","DownloadDataSchema","DownloadDataTool","downloadData","textData","toUtf8","CreatePostageStampSchema","label","CreatePostageStampTool","durationMs","buyStorageResponse","makeDateError","buyStoragePromise","buyStorage","Size","fromMegabytes","Duration","fromMilliseconds","hasTimedOut","asyncAction","timeout","timeoutPromise","Promise","resolve","setTimeout","race","runWithTimeout","ExtendPostageStampSchema","ExtendPostageStampTool","extendSize","fromBytes","extendStorageResponse","extendDuration","ZERO","extendStorage","QueryUploadProgressSchema","tagId","QueryUploadProgressTool","tagUid","Number","tag","retrieveTag","synced","processed","seen","total","startedAt","processedPercentage","round","isComplete","tagDeleted","deleteTag","tagAddress","address","DownloadFilesSchema","filePath","DownloadFilesTool","node","isManifest","MantarayNode","unmarshal","loadRecursively","destinationFolder","fs","existsSync","promisify","mkdir","recursive","nodes","collect","targetAddress","writeFile","path","fullPathString","toUint8Array","parsedPath","parse","nodeDestFolder","dir","manifestNodeCount","savedTo","filesList","Array","padStart","metadata","files","GetPostageStampSchema","GetPostageStampTool","rawPostageBatch","getPostageBatch","batchSummary","ReadFeedSchema","memoryTopic","owner","ReadFeedTool","beeFeedPK","topic","startsWith","crypto","createHash","update","digest","topicBytes","feedOwner","feedPrivateKey","Wallet","getAddressString","feedReader","makeFeedReader","downloadPayload","payload","UpdateFeedSchema","UpdateFeedTool","feedWriter","makeFeedWriter","uploadPayload","topicString","feedUrl","UploadFileSchema","isPath","UploadFileTool","inputRedundancyLevel","readFile","fileError","pop","deferredUploadSizeThreshold","deferredUploadSizeThresholdMB","deferred","createTag","uid","uploadFile","UploadFolderSchema","folderPath","UploadFolderTool","stat","isDirectory","uploadFilesFromDirectory","SwarmPlugin","beeURL","beeApiUrl","Bee","createPostageStampTool","downloadDataTool","downloadFilesTool","extendPostageStampTool","getPostageStampsTool","listPostageStampsTool","queryUploadProgressTool","readFeedTool","updateFeedTool","uploadDataTool","uploadFileTool","uploadFolderTool","FieldTypeRegistry","patterns","Map","initializeDefaultPatterns","getInstance","instance","register","key","set","unregister","delete","detectType","matches","values","isMatch","isArray","RegExp","getPatterns","reset","fieldTypeRegistry","ERROR_MESSAGES","EntityFormat","ENTITY_PATTERNS","TOPIC_ID","TOKEN_ID","ACCOUNT_ID","CONTRACT_ID","FIELD_PRIORITIES","ESSENTIAL","COMMON","ADVANCED","EXPERT","isZodObjectSchema","FormGenerator","generateFormFromError","originalPrompt","validationErrors","extractValidationErrors","missingFields","identifyMissingFields","formConfig","createFormConfig","Date","now","random","substr","generateFormFromSchema","partialInput","preCalculatedMissingFields","hasSchema","hasShape","hasPreCalculatedFields","preCalculatedFieldsSize","missingFieldsCount","Set","zodObject","extractZodObject","shape","add","totalFields","toolDescription","issues","issue","code","_schema","fieldPath","extractedConfig","extractRenderConfigsSafely","fieldOrdering","generateFieldOrderingSafely","generateFormFields","generateFormDescription","standard","title","generateFormTitle","submitLabel","cancelLabel","missingFieldCount","extractRenderConfigs","groups","generateFieldOrdering","ordering","sections","section","getFieldPriority","renderConfig","isRequired","ui","advanced","expert","determineFieldsToInclude","fieldsToInclude","extractFieldsFromSchema","includeRequiredMissingFields","isFieldRequired","isMissing","has","shouldInclude","createOrderedFields","processedFields","flatMap","field","createFormField","mapFieldType","fieldType","finalType","humanizeFieldName","required","placeholder","helpText","contextualGuidance","examples","avoidPatterns","constraints","validation","max","minLength","maxLength","opt","disabled","inferredType","inferTypeFromSchema","registryType","normalizedType","charAt","toUpperCase","def","_def","typeName","debug","firstOption","firstOptionObject","fieldSchema","fieldDef","innerType","fieldTypeName","lowerPath","defaultValue","fieldCount","generateJsonSchemaForm","zodSchema","fullJsonSchema","zodToJsonSchema","target","uiSchema","jsonSchema","fullSchemaAsObject","properties","filteredSchema","fieldsAdded","lower","collapsible","collapsed","FormEngine","formGenerator","generateForm","tool","fullContext","isFormValidatable","generateFormValidatableForm","ZodError","generateErrorBasedForm","hasRenderConfig","generateRenderConfigForm","isZodObject","generateSchemaBasedForm","processSubmission","submission","validateSubmission","baseToolInput","extractBaseToolInput","submissionData","extractSubmissionData","mergeInputData","shouldGenerateForm","inputRecord","__fromForm","renderForm","validateInput","toolSchema","_context","schemaToUse","isFocusedSchema","resolveFormSchema","determineMissingFields","generateFormWithSchema","formMessage","extractRenderConfig","candidate","_renderConfig","formValidatableTool","getFormSchema","focusedSchema","_isFocusedSchema","getEssentialFields","essentialFields","isFieldEmpty","parameters","originalInput","baseInput","getRegisteredStrategies","getRegisteredMiddleware","ResponseFormatter","isHashLinkResponse","parsed","responseObj","hashLinkBlock","formatHashLinkResponse","inscription","topicId","attributes","hrl","cdnUrl","creator","isInscriptionResponse","formatInscriptionResponse","formatResponse","toolOutput","globalPendingForms","FormAwareAgentExecutor","AgentExecutor","args","pendingForms","formEngine","formLogger","parameterPreprocessingCallback","ZodObject","hasHashLinkBlock","setParameterPreprocessingCallback","callback","_takeNextStep","nameToolMap","inputs","intermediateSteps","runManager","availableTools","inputKeys","agent","plan","getChild","action","toolInput","hasInNameToolMap","toolInputKeys","find","t","schemaFieldCount","schemaType","estimatedFieldCount","isEmpty","isEssential","willAddToMissingFields","formData","originalToolInput","toolRef","originalToolRef","formResult","requiresForm","observation","preprocessedInput","rf","__requestForm","formId","f","resolvedType","resolvedSchema","original","preprocessed","hasChanges","preprocessError","rawShape","fdef","inner","unwrapOptional","step","hasForm","actionToolName","toolInstance","originalToolCandidate","pf","output","hasHashLink","blockId","hashLinkResponse","processHashLinkResponse","hasHashLinkBlocks","handleValidationError","errorIssues","toolInfo","extractToolInfoFromError","fallbackTool","detectToolFromErrorContext","formatFormResponse","getPendingForms","restorePendingForms","forms","processFormSubmission","submissionFormId","submissionToolName","parameterKeys","parametersType","parametersIsNull","parametersIsUndefined","hasContext","pendingForm","get","mergedToolInput","baseKeys","submissionKeys","mergedKeys","maybeWrapper","executeOriginal","getOriginalTool","ot","otCall","call","tcall","formattedOutput","responseMetadata","jsonKeys","parsedRecord","hasTemplate","template","outputSample","substring","formCompleted","originalFormId","rawToolOutput","lastStep","inputSteps","toolFromContext","findToolFromContext","inputText","extractToolKeywords","keyword","errorPaths","schemaMatchesErrorPaths","schemaRecord","schemaKeys","topLevelKey","fieldList","hasPendingForms","getPendingFormsInfo","entries","toolResponse","hashLink","attributeCount","getFormEngineStatistics","strategies","middleware","BaseAgent","initialized","silent","getCore","filterTools","filtered","filtering","namespaceWhitelist","toolBlacklist","toolPredicate","buildSystemPrompt","parts","userAccId","execution","messaging","systemPreamble","scheduleUserTransactionsInBytesMode","conciseMode","systemPostamble","isReady","MCPContentProcessor","contentStorage","analyzeResponse","contents","totalSize","extractContentFromResponse","reduce","sum","sizeBytes","largestContentSize","shouldProcess","shouldUseReference","processResponse","serverName","analysis","wasProcessed","createReferencedResponse","obj","item","record","byteLength","mimeType","detectMimeType","ceil","resource","resourceStr","originalResponse","processedResponse","deepClone","referenceCreated","totalReferenceSize","contentInfo","contentBuffer","contentType","mapMimeTypeToContentType","source","mcpToolName","tags","storeContentIfLarge","replaceContentInResponse","createLightweightReference","originalSize","referenceId","preview","format","_isReference","oldContent","newContent","newContentRecord","getTime","cloned","hasOwnProperty","MCPClientManager","clients","contentProcessor","connectServer","isServerConnected","connected","transport","StdioClientTransport","command","client","Client","capabilities","connect","toolsWithServer","listTools","executeTool","callTool","disconnectAll","close","getAllTools","allTools","getServerTools","getConnectedServers","enableContentProcessing","disableContentProcessing","isContentProcessingEnabled","analyzeResponseContent","convertMCPToolToLangChain","mcpManager","serverConfig","jsonSchemaToZod","inputSchema","sanitizedName","toolDescriptions","additionalContext","DynamicStructuredTool","func","responseText","responseBuffer","MCP_REFERENCE_THRESHOLD","contentStore","ContentStoreService","storeContent","schemaObj","convertType","zodType","unknown","enum","minimum","maximum","int","items","passthrough","_TokenCounter","modelName","encoding","encoding_for_model","countTokens","encode","countMessageTokens","getMessageRole","MESSAGE_OVERHEAD","ROLE_OVERHEAD","countMessagesTokens","messages","estimateSystemPromptTokens","systemPrompt","estimateContextSize","_getType","getModelName","dispose","free","TokenCounter","_MemoryWindow","maxTokens","DEFAULT_MAX_TOKENS","reserveTokens","DEFAULT_RESERVE_TOKENS","tokenCounter","systemPromptTokens","addMessage","prunedMessages","getCurrentTokenCount","pruneToFit","added","currentTokenCount","remainingCapacity","getRemainingTokenCapacity","targetTokens","batchSize","PRUNING_BATCH_SIZE","prunedMessage","shift","messageTokens","canAddMessage","wouldExceedReserve","getMessages","setSystemPrompt","getSystemPrompt","getConfig","currentTokens","messageCount","updateLimits","getStats","totalMessages","canAcceptMore","MemoryWindow","ReferenceIdGenerator","generateId","hash","isValidReferenceId","extractReferenceId","refFormatMatch","match","formatReference","generateTestId","testSeed","DEFAULT_CONTENT_REFERENCE_CONFIG","sizeThresholdBytes","maxAgeMs","maxReferences","maxTotalStorageBytes","enableAutoCleanup","cleanupIntervalMs","enablePersistence","storageBackend","cleanupPolicies","recent","userContent","agentGenerated","default","ContentReferenceError","suggestedActions","_ContentStorage","maxStorage","DEFAULT_MAX_STORAGE","referenceConfig","idCounter","referenceStats","activeReferences","totalStorageBytes","recentlyCleanedUp","totalResolutions","failedResolutions","averageContentSize","storageUtilization","performanceMetrics","averageCreationTimeMs","averageResolutionTimeMs","averageCleanupTimeMs","creationTimes","resolutionTimes","cleanupTimes","startReferenceCleanupTimer","storeMessages","stored","dropped","storedMessages","storedAt","getRecentMessages","count","startIndex","searchMessages","query","caseSensitive","useRegex","regex","searchTerm","getMessagesFromTimeRange","startTime","endTime","getStorageStats","oldestMessageTime","newestMessageTime","maxStorageLimit","getTotalStoredMessages","updateStorageLimit","newLimit","getMessagesByType","messageType","currentUsage","utilizationPercentage","getRecentMessagesByTime","cutoffTime","exportMessages","toISOString","isBuffer","buffer","isImageContent","fileName","storeMetadata","detectContentType","customMetadata","fullMetadata","createdAt","lastAccessedAt","accessCount","storedContent","state","expirationTime","calculateExpirationTime","expiresAt","updateStatsAfterStore","enforceReferenceStorageLimits","createContentPreview","referenceMetadata","recordPerformanceMetric","resolveReference","errorType","hasReference","cleanupReference","updateReferenceStorageStats","calculateAverage","updateConfig","cleanupTimer","clearInterval","performCleanup","cleanedUp","toCleanup","shouldCleanup","ageMs","getCleanupPolicy","aContent","bContent","aPriority","sortedByAge","excessCount","getReferenceConfig","policy","contentStr","mostAccessedId","maxAccess","mostAccessedReferenceId","lowerFileName","ext","endsWith","timeMs","metrics","times","time","setInterval","ContentStorage","IS_ENTITY_ASSOCIATION_FLAG","_SmartMemoryManager","DEFAULT_CONFIG","_contentStorage","storageLimit","memoryWindow","clearStorage","searchHistory","getRecentHistory","getMemoryStats","windowStats","totalActiveMessages","getOverallStats","memoryStats","storageStats","activeMemory","storage","totalMessagesManaged","activeMemoryUtilization","newConfig","getHistoryFromTimeRange","getHistoryByType","getRecentHistoryByTime","exportState","activeMessages","msg","getContextSummary","includeStoredContext","activeMessageCount","recentMessages","memoryUtilization","hasStoredHistory","recentStoredMessages","performMaintenance","storeEntityAssociation","entityId","entityName","entityType","transactionId","sessionId","sanitizedEntityId","sanitizedEntityName","sanitizedEntityType","normalizeEntityType","usageHint","association","isEntityAssociation","entityMessage","additional_kwargs","SystemMessage","REGISTRY","topicid","token","tokenid","account","accountid","contract","contractid","file","fileid","schedule","scheduleid","prototype","resolveEntityReference","sanitizedQuery","fuzzyMatch","safeLimit","isEntityIdQuery","searchResults","associations","fuzzyQueries","fuzzyQuery","fuzzyResults","uniqueAssociations","assoc","index","arr","findIndex","getEntityAssociations","rawFilter","filterCanonical","searchQuery","parseError","messageContent","mergedById","existing","existingTime","currentTime","SmartMemoryManager","FormValidatingToolWrapper","validationConfig","originalToolName","originalToolType","wrapperType","skipFields","getSchemaShape","hasFormValidatableMethod","methodName","calculateMissingFields","isCustom","createFormMessage","hasCustomValidation","customValidation","hasFormBypassFlags","schemaShape","stackTrace","stack","shouldGenerate","schemaFields","isCustomSchema","wrapToolWithFormValidation","ToolRegistry","registerTool","analyzeToolCapabilities","category","dependencies","entityResolutionPreferences","rawPrefs","schemaDef","metadataField","note","wrapper","finalTool","shouldWrapTool","requireAllFields","wrapperConfig","entry","capability","enabled","metaFG","fieldGuidance","fieldGuidanceProvider","getTool","getToolsByCapability","results","getToolsByQuery","getAllRegistryEntries","getToolNames","getToolsByPriority","getEnabledTools","getToolsByNamespace","hasCapability","updateToolOptions","hasTool","unregisterTool","implementsFormValidatable","isZodObjectLike","supportsFormValidation","requiresWrapper","toolAsAny","isMCPTool","isExtension","skipWrapper","forceWrapper","getStatistics","stats","totalTools","wrappedTools","unwrappedTools","categoryCounts","core","extension","mcp","priorityCounts","low","medium","high","critical","ExecutionPipeline","toolRegistry","memory","execute","sessionContext","traceId","toolEntry","session","buildDefaultSession","checkFormGeneration","executionTime","executeToolDirect","handleExecutionError","executeWithValidation","formSubmission","timestamp","processedInput","mergedArgs","executeWrappedTool","wrapperAsAny","totalMiddleware","registeredMiddleware","meta","block","LangChainAgent","systemMessage","mcpConnectionStatus","addToolRawToMemory","smartMemory","persistToolRaw","isJSON","persistIntermediateSteps","steps","obs","getInscriptionTool","criticalTools","desc","useExecutionPipeline","executionPipeline","processedParameters","pendingParameterPreprocessingCallback","hasCallback","originalKeys","processedKeys","changes","createToolResponse","notes","handleToolExecution","isToolExecution","toolExecutionData","executor","handleDirectToolExecution","toolLineMatch","argsLineIndex","indexOf","argsText","handleJsonToolCalls","trimmed","handleContentRefMessages","idMatch","contentRef","withHashLinkBlocks","pending","chat_history","maybeRestore","outputMsg","processExecutorResult","outputStr","toolCalls","tool_calls","lastJsonObservation","formattedMessage","transactionBytes","scheduleId","blockMetadata","processHashLinkBlocks","AIMessage","tokenTracker","tokenUsage","getLatestTokenUsage","cost","calculateTokenCostSync","finalMemoryStats","loadContextMessages","existingMessages","existingContent","messageClass","HumanMessage","boot","createAgentKit","ai","OPENAI_MODEL_NAME","TokenUsageCallbackHandler","getAggregatedLangChainTools","filteredTools","originalCall","bind","metaOptions","transactionMemo","originalMemo","wrapped","unwrapped","categories","priorities","inscriptionTool","toolNames","uniqueNames","duplicates","servers","autoConnect","initializeMCP","toolsCount","createExecutor","chat","toolExecutionResult","directToolResult","jsonToolResult","contentRefResult","contextLength","currentMessages","instr","c","invoke","handleError","switchMode","mode","getUsageStats","promptTokens","completionTokens","totalTokens","totalCost","getTotalTokenUsage","getUsageLog","getTokenUsageHistory","clearUsageStats","getMCPConnectionStatus","errorInfo","safeSubmission","preservedMetadata","maybeRaw","outputMessage","hasMetadata","metadataKeys","hashLinkBlockContent","parsedSteps","plugins","getAllHederaCorePlugins","extensions","HederaAgentKit","mirrorConfig","existingPendingForms","llm","getModel","apiKey","OPENAI_API_KEY","isGPT5Model","ChatOpenAI","callbacks","temperature","prompt","ChatPromptTemplate","fromMessages","MessagesPlaceholder","langchainTools","createOpenAIToolsAgent","verbose","returnIntermediateSteps","userFriendlyMessage","userFriendlyOutput","errorResponse","mcpTool","langchainTool","connectMCPServers","connectServerInBackground","parsedResponse","responseRecord","attributeKeys","str","createAgent","framework","BrowserSigner","AbstractSigner","getNetwork","forMainnet","forTestnet","exec","ephemeralKey","PrivateKey","generateED25519","getClient","signAndExecuteTransaction","tx","isFrozen","freezeWith","base64","mirror","HederaMirrorNode","deadline","details","getTransaction","TransactionReceipt","r","getPublicKey","anyKey","keyStr","PublicKey","LangChainProvider","model","generate","stream","chunk","providerRef","getWalletBridgeProvider","PageSnapshotSchema","maxCharacters","WebPageSnapshotTool","fetchImpl","maxChars","redirect","html","normalizeHtml","WebBrowserPlugin","getSystemMessage","ContentStorageAdapter","maxSize","enableCompression","ContentResolver","adapter","ContentStoreManager","maxMessageStorage","isRegistered","resolver","setInstance","ContentResolverRegistry","getContentStorage","isInitialized","ResolveEntitiesSchema","entities","ExtractEntitiesSchema","userMessage","ResolveEntitiesTool","byType","groupEntitiesByType","buildEntityContext","acc","entity","groupedEntities","list","ExtractEntitiesTool","llmResponse","createEntityTools","resolveEntities","extractEntities","FormatConverterRegistry","converters","entityTypeCache","defaultCacheTTL","converter","sourceFormat","targetFormat","findConverter","convertEntity","detectFormatWithFallback","canConvert","convert","HRL","cached","getCachedFormat","detected","detectFormat","ANY","setCachedFormat","detectEntityFormat","networkType","configureRetry","maxRetries","maxDelayMs","successful","allSettled","getAccountBalance","then","catch","getTopicInfo","getContract","isCacheExpired","getRegisteredConverters","hasConverter","clearCache","TopicIdToHrlConverter","_StringNormalizationConverter","toolPreferences","toolPrefs","fallbackStandard","hrlStandard","inscriptionHrlStandard","HRLResolver","cdnMatch","resolved","contentRefMatch","parseHRL","standardCache","StringNormalizationConverter","ParameterService","formatConverterRegistry","preprocessParameters","entityResolver","preferences","working","entityCount","aiProcessed","paramName","paramValue","resolveReferences","converted","convertParameterEntities","attachToAgent","deps","getSessionId","getEntities","maybe","attach","opts","getAgent","underlying","preprocessToolParameters","originalParams","convertedValue","originalArray","convertedArray","arrayChanged","convertedItem","parameterValue","containsEntityId","containsEntityName","SYMBOL","supplyKey","adminKey","ALIAS","convertedEntityValue","DEFAULT_MODEL_NAME","DEFAULT_OPENAI_MODEL","DEFAULT_CLAUDE_MODEL","DEFAULT_TEMPERATURE","DEFAULT_NETWORK","DEFAULT_OPERATIONAL_MODE","_ConversationalAgent","hcs10Plugin","hcs2Plugin","inscribePlugin","hbarPlugin","webBrowserPlugin","disableLogging","entityMemoryEnabled","openAIApiKey","memoryManager","entityMemoryConfig","entityMemoryProvider","llmProvider","resolverLLM","entityMemoryModelName","ChatAnthropic","baseURL","openRouterBaseURL","openRouterApiKey","configuration","defaultHeaders","OPENROUTER_REFERRER","OPENROUTER_TITLE","entityTools","openAIModelName","validateOptions","opMode","bytesMode","IB","setPreferWalletOnly","chain","effectiveAccount","walletExecutor","ServerSigner","signerClass","getPrototypeOf","bridge","setWalletInfoResolver","setWalletExecutor","executeBytes","setStartInscriptionDelegate","startInscription","request","enforceWallet","SignerProviderRegistry","extended","startHCS","setStartHCSDelegate","op","IB2","sakWireErr","providerInfo","keyPresent","modelName2","allPlugins","preparePlugins","agentConfig","createAgentConfig","configureHCS10Plugin","contentStoreManager","registry","cfg","originalPredicate","userPredicate","toolFilter","mcpServers","connectMCP","getPlugin","NOT_INITIALIZED_ERROR","getConversationalAgent","processMessage","chatHistory","resolvedMessage","extractAndStoreEntities","additionalPlugins","enabledPlugins","disabledPlugins","standardPlugins","corePlugins","pluginPool","enabledSet","plugin","disabledSet","additional","customSystemMessagePreamble","customSystemMessagePostamble","mirrorNodeConfig","scheduleUserTransactions","hcs10","withPlugins","withHTS","withHCS2","withHCS10","withInscribe","withAccount","withFileService","withConsensusService","withSmartContract","withAllStandards","minimal","withMCP","originalMessage","extractResponseText","entitiesJson","extractTransactionId","idStr","responseWithTxId","isMCPServerConnected","ConversationalAgent","processAttachments","attachments","attachmentCount","att","processWithContentStore","processWithSimpleReferences","contentReferences","attachment","base64Data","createInlineReference","fileList","createFileList","fileReferences","sizeStr","formatFileSize","fromEntries","mostRecent","messagePreview","entityStats","changed","hasEntityId","resolvedPreview","receiptEntities","extractFromReceipt","extractWithLLM","receipt","extractNameFromMessage","extractEntityId","contractId","fileId","FILE_ID","SCHEDULE_ID","quotedMatch","calledMatch","forMatch","namedMatch","validateEntityType","expectedType","resolveWithTypeValidation","getEntitiesByType","getMostRecentEntityByType","most","current","filesystem","list_directory","read_file","github","GITHUB_TOKEN","slack","SLACK_TOKEN","googleDrive","credentials","GOOGLE_CREDENTIALS","postgres","connectionString","sqlite","dbPath","custom","server"],"mappings":"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"}