@hashgraphonline/conversational-agent 0.2.216 → 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 (312) 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/index47.js +7 -95
  117. package/dist/esm/index47.js.map +1 -1
  118. package/dist/esm/index48.js +77 -7
  119. package/dist/esm/index48.js.map +1 -1
  120. package/dist/esm/index49.js +75 -0
  121. package/dist/esm/index49.js.map +1 -0
  122. package/dist/esm/index5.js +2 -2
  123. package/dist/esm/index50.js +57 -0
  124. package/dist/esm/index50.js.map +1 -0
  125. package/dist/esm/index51.js +103 -0
  126. package/dist/esm/index51.js.map +1 -0
  127. package/dist/esm/index52.js +79 -0
  128. package/dist/esm/index52.js.map +1 -0
  129. package/dist/esm/index53.js +75 -0
  130. package/dist/esm/index53.js.map +1 -0
  131. package/dist/esm/index54.js +124 -0
  132. package/dist/esm/index54.js.map +1 -0
  133. package/dist/esm/index55.js +58 -0
  134. package/dist/esm/index55.js.map +1 -0
  135. package/dist/esm/index56.js +83 -0
  136. package/dist/esm/index56.js.map +1 -0
  137. package/dist/esm/index57.js +100 -0
  138. package/dist/esm/index57.js.map +1 -0
  139. package/dist/esm/index58.js +118 -0
  140. package/dist/esm/index58.js.map +1 -0
  141. package/dist/esm/index59.js +108 -0
  142. package/dist/esm/index59.js.map +1 -0
  143. package/dist/esm/index6.js +132 -833
  144. package/dist/esm/index6.js.map +1 -1
  145. package/dist/esm/index60.js +30 -0
  146. package/dist/esm/index60.js.map +1 -0
  147. package/dist/esm/index61.js +98 -0
  148. package/dist/esm/index61.js.map +1 -0
  149. package/dist/esm/index62.js +131 -0
  150. package/dist/esm/index62.js.map +1 -0
  151. package/dist/esm/index63.js +19 -0
  152. package/dist/esm/index63.js.map +1 -0
  153. package/dist/esm/index7.js +826 -75
  154. package/dist/esm/index7.js.map +1 -1
  155. package/dist/esm/index8.js +91 -13
  156. package/dist/esm/index8.js.map +1 -1
  157. package/dist/esm/index9.js +13 -17
  158. package/dist/esm/index9.js.map +1 -1
  159. package/dist/types/index.d.ts +1 -0
  160. package/dist/types/plugins/community/swarm/SwarmPlugin.d.ts +17 -0
  161. package/dist/types/plugins/community/swarm/__tests__/SwarmPlugin.mocks.d.ts +1 -0
  162. package/dist/types/plugins/community/swarm/__tests__/SwarmPlugin.test.d.ts +1 -0
  163. package/dist/types/plugins/community/swarm/__tests__/tools/CreatePostageStampTool.test.d.ts +1 -0
  164. package/dist/types/plugins/community/swarm/__tests__/tools/DownloadDataTool.test.d.ts +1 -0
  165. package/dist/types/plugins/community/swarm/__tests__/tools/DownloadFilesTool.test.d.ts +1 -0
  166. package/dist/types/plugins/community/swarm/__tests__/tools/ExtendPostageStampTool.test.d.ts +1 -0
  167. package/dist/types/plugins/community/swarm/__tests__/tools/GetPostageStampTool.test.d.ts +1 -0
  168. package/dist/types/plugins/community/swarm/__tests__/tools/ListPostageStampsTool.test.d.ts +1 -0
  169. package/dist/types/plugins/community/swarm/__tests__/tools/QueryUploadProgressTool.test.d.ts +1 -0
  170. package/dist/types/plugins/community/swarm/__tests__/tools/ReadFeedTool.test.d.ts +1 -0
  171. package/dist/types/plugins/community/swarm/__tests__/tools/SwarmTool.mocks.d.ts +14 -0
  172. package/dist/types/plugins/community/swarm/__tests__/tools/UpdateFeedTool.test.d.ts +1 -0
  173. package/dist/types/plugins/community/swarm/__tests__/tools/UploadDataTool.test.d.ts +1 -0
  174. package/dist/types/plugins/community/swarm/__tests__/tools/UploadFileTool.test.d.ts +1 -0
  175. package/dist/types/plugins/community/swarm/__tests__/tools/UploadFolderTool.test.d.ts +1 -0
  176. package/dist/types/plugins/community/swarm/config.d.ts +6 -0
  177. package/dist/types/plugins/community/swarm/constants.d.ts +8 -0
  178. package/dist/types/plugins/community/swarm/index.d.ts +2 -0
  179. package/dist/types/plugins/community/swarm/model.d.ts +23 -0
  180. package/dist/types/plugins/community/swarm/tools/CreatePostageStampTool.d.ts +47 -0
  181. package/dist/types/plugins/community/swarm/tools/DownloadDataTool.d.ts +35 -0
  182. package/dist/types/plugins/community/swarm/tools/DownloadFilesTool.d.ts +41 -0
  183. package/dist/types/plugins/community/swarm/tools/ExtendPostageStampTool.d.ts +47 -0
  184. package/dist/types/plugins/community/swarm/tools/GetPostageStampTool.d.ts +35 -0
  185. package/dist/types/plugins/community/swarm/tools/ListPostageStampsTool.d.ts +53 -0
  186. package/dist/types/plugins/community/swarm/tools/QueryUploadProgressTool.d.ts +35 -0
  187. package/dist/types/plugins/community/swarm/tools/ReadFeedTool.d.ts +41 -0
  188. package/dist/types/plugins/community/swarm/tools/UpdateFeedTool.d.ts +47 -0
  189. package/dist/types/plugins/community/swarm/tools/UploadDataTool.d.ts +47 -0
  190. package/dist/types/plugins/community/swarm/tools/UploadFileTool.d.ts +53 -0
  191. package/dist/types/plugins/community/swarm/tools/UploadFolderTool.d.ts +47 -0
  192. package/dist/types/plugins/community/swarm/utils.d.ts +22 -0
  193. package/dist/types/plugins/index.d.ts +1 -0
  194. package/package.json +36 -26
  195. package/src/index.ts +1 -0
  196. package/src/plugins/community/swarm/README.md +279 -0
  197. package/src/plugins/community/swarm/SwarmPlugin.ts +178 -0
  198. package/src/plugins/community/swarm/__tests__/SwarmPlugin.mocks.ts +105 -0
  199. package/src/plugins/community/swarm/__tests__/SwarmPlugin.test.ts +93 -0
  200. package/src/plugins/community/swarm/__tests__/tools/CreatePostageStampTool.test.ts +152 -0
  201. package/src/plugins/community/swarm/__tests__/tools/DownloadDataTool.test.ts +93 -0
  202. package/src/plugins/community/swarm/__tests__/tools/DownloadFilesTool.test.ts +163 -0
  203. package/src/plugins/community/swarm/__tests__/tools/ExtendPostageStampTool.test.ts +132 -0
  204. package/src/plugins/community/swarm/__tests__/tools/GetPostageStampTool.test.ts +83 -0
  205. package/src/plugins/community/swarm/__tests__/tools/ListPostageStampsTool.test.ts +219 -0
  206. package/src/plugins/community/swarm/__tests__/tools/QueryUploadProgressTool.test.ts +169 -0
  207. package/src/plugins/community/swarm/__tests__/tools/ReadFeedTool.test.ts +133 -0
  208. package/src/plugins/community/swarm/__tests__/tools/SwarmTool.mocks.ts +67 -0
  209. package/src/plugins/community/swarm/__tests__/tools/UpdateFeedTool.test.ts +148 -0
  210. package/src/plugins/community/swarm/__tests__/tools/UploadDataTool.test.ts +125 -0
  211. package/src/plugins/community/swarm/__tests__/tools/UploadFileTool.test.ts +194 -0
  212. package/src/plugins/community/swarm/__tests__/tools/UploadFolderTool.test.ts +118 -0
  213. package/src/plugins/community/swarm/config.ts +6 -0
  214. package/src/plugins/community/swarm/constants.ts +12 -0
  215. package/src/plugins/community/swarm/index.ts +2 -0
  216. package/src/plugins/community/swarm/model.ts +23 -0
  217. package/src/plugins/community/swarm/tools/CreatePostageStampTool.ts +137 -0
  218. package/src/plugins/community/swarm/tools/DownloadDataTool.ts +79 -0
  219. package/src/plugins/community/swarm/tools/DownloadFilesTool.ts +155 -0
  220. package/src/plugins/community/swarm/tools/ExtendPostageStampTool.ts +112 -0
  221. package/src/plugins/community/swarm/tools/GetPostageStampTool.ts +92 -0
  222. package/src/plugins/community/swarm/tools/ListPostageStampsTool.ts +124 -0
  223. package/src/plugins/community/swarm/tools/QueryUploadProgressTool.ts +109 -0
  224. package/src/plugins/community/swarm/tools/ReadFeedTool.ts +110 -0
  225. package/src/plugins/community/swarm/tools/UpdateFeedTool.ts +149 -0
  226. package/src/plugins/community/swarm/tools/UploadDataTool.ts +109 -0
  227. package/src/plugins/community/swarm/tools/UploadFileTool.ts +163 -0
  228. package/src/plugins/community/swarm/tools/UploadFolderTool.ts +150 -0
  229. package/src/plugins/community/swarm/utils.ts +172 -0
  230. package/src/plugins/index.ts +1 -0
  231. package/cli/dist/CLIApp.d.ts +0 -11
  232. package/cli/dist/CLIApp.d.ts.map +0 -1
  233. package/cli/dist/CLIApp.js +0 -128
  234. package/cli/dist/CLIApp.js.map +0 -1
  235. package/cli/dist/LocalConversationalAgent.d.ts +0 -37
  236. package/cli/dist/LocalConversationalAgent.js +0 -58
  237. package/cli/dist/app.d.ts +0 -18
  238. package/cli/dist/app.d.ts.map +0 -1
  239. package/cli/dist/app.js +0 -14
  240. package/cli/dist/app.js.map +0 -1
  241. package/cli/dist/cli.d.ts +0 -3
  242. package/cli/dist/cli.d.ts.map +0 -1
  243. package/cli/dist/cli.js +0 -87
  244. package/cli/dist/cli.js.map +0 -1
  245. package/cli/dist/components/AppContainer.d.ts +0 -16
  246. package/cli/dist/components/AppContainer.js +0 -24
  247. package/cli/dist/components/AppScreens.d.ts +0 -2
  248. package/cli/dist/components/AppScreens.js +0 -259
  249. package/cli/dist/components/ChatScreen.d.ts +0 -21
  250. package/cli/dist/components/ChatScreen.d.ts.map +0 -1
  251. package/cli/dist/components/ChatScreen.js +0 -40
  252. package/cli/dist/components/ChatScreen.js.map +0 -1
  253. package/cli/dist/components/DebugLoadingScreen.d.ts +0 -5
  254. package/cli/dist/components/DebugLoadingScreen.js +0 -31
  255. package/cli/dist/components/LoadingScreen.d.ts +0 -3
  256. package/cli/dist/components/LoadingScreen.d.ts.map +0 -1
  257. package/cli/dist/components/LoadingScreen.js +0 -17
  258. package/cli/dist/components/LoadingScreen.js.map +0 -1
  259. package/cli/dist/components/LoadingScreenDebug.d.ts +0 -5
  260. package/cli/dist/components/LoadingScreenDebug.js +0 -27
  261. package/cli/dist/components/MCPConfigScreen.d.ts +0 -28
  262. package/cli/dist/components/MCPConfigScreen.d.ts.map +0 -1
  263. package/cli/dist/components/MCPConfigScreen.js +0 -186
  264. package/cli/dist/components/MCPConfigScreen.js.map +0 -1
  265. package/cli/dist/components/ScreenRouter.d.ts +0 -13
  266. package/cli/dist/components/ScreenRouter.d.ts.map +0 -1
  267. package/cli/dist/components/ScreenRouter.js +0 -23
  268. package/cli/dist/components/ScreenRouter.js.map +0 -1
  269. package/cli/dist/components/SetupScreen.d.ts +0 -16
  270. package/cli/dist/components/SetupScreen.d.ts.map +0 -1
  271. package/cli/dist/components/SetupScreen.js +0 -67
  272. package/cli/dist/components/SetupScreen.js.map +0 -1
  273. package/cli/dist/components/SingleLoadingScreen.d.ts +0 -5
  274. package/cli/dist/components/SingleLoadingScreen.js +0 -27
  275. package/cli/dist/components/StatusBadge.d.ts +0 -10
  276. package/cli/dist/components/StatusBadge.d.ts.map +0 -1
  277. package/cli/dist/components/StatusBadge.js +0 -24
  278. package/cli/dist/components/StatusBadge.js.map +0 -1
  279. package/cli/dist/components/TerminalWindow.d.ts +0 -9
  280. package/cli/dist/components/TerminalWindow.d.ts.map +0 -1
  281. package/cli/dist/components/TerminalWindow.js +0 -19
  282. package/cli/dist/components/TerminalWindow.js.map +0 -1
  283. package/cli/dist/components/WelcomeScreen.d.ts +0 -12
  284. package/cli/dist/components/WelcomeScreen.d.ts.map +0 -1
  285. package/cli/dist/components/WelcomeScreen.js +0 -47
  286. package/cli/dist/components/WelcomeScreen.js.map +0 -1
  287. package/cli/dist/context/AppContext.d.ts +0 -68
  288. package/cli/dist/context/AppContext.js +0 -363
  289. package/cli/dist/headless-runner.d.ts +0 -17
  290. package/cli/dist/headless-runner.d.ts.map +0 -1
  291. package/cli/dist/headless-runner.js +0 -128
  292. package/cli/dist/headless-runner.js.map +0 -1
  293. package/cli/dist/hooks/useInitializeAgent.d.ts +0 -19
  294. package/cli/dist/hooks/useInitializeAgent.d.ts.map +0 -1
  295. package/cli/dist/hooks/useInitializeAgent.js +0 -29
  296. package/cli/dist/hooks/useInitializeAgent.js.map +0 -1
  297. package/cli/dist/hooks/useStableState.d.ts +0 -38
  298. package/cli/dist/hooks/useStableState.d.ts.map +0 -1
  299. package/cli/dist/hooks/useStableState.js +0 -69
  300. package/cli/dist/hooks/useStableState.js.map +0 -1
  301. package/cli/dist/managers/AgentManager.d.ts +0 -58
  302. package/cli/dist/managers/AgentManager.d.ts.map +0 -1
  303. package/cli/dist/managers/AgentManager.js +0 -121
  304. package/cli/dist/managers/AgentManager.js.map +0 -1
  305. package/cli/dist/managers/ConfigManager.d.ts +0 -54
  306. package/cli/dist/managers/ConfigManager.d.ts.map +0 -1
  307. package/cli/dist/managers/ConfigManager.js +0 -188
  308. package/cli/dist/managers/ConfigManager.js.map +0 -1
  309. package/cli/dist/types.d.ts +0 -52
  310. package/cli/dist/types.d.ts.map +0 -1
  311. package/cli/dist/types.js +0 -34
  312. package/cli/dist/types.js.map +0 -1
@@ -1,1235 +1,251 @@
1
- import { createOpenAIToolsAgent } from "langchain/agents";
2
- import { FormAwareAgentExecutor } from "./index31.js";
3
- import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts";
4
- import { ChatOpenAI } from "@langchain/openai";
5
- import { calculateTokenCostSync, TokenUsageCallbackHandler, getAllHederaCorePlugins, HederaAgentKit } from "hedera-agent-kit";
6
- import { BaseAgent } from "./index7.js";
7
- import { MCPClientManager } from "./index15.js";
8
- import { convertMCPToolToLangChain } from "./index17.js";
9
- import { SmartMemoryManager } from "./index18.js";
10
- import { ResponseFormatter } from "./index35.js";
11
- import { ERROR_MESSAGES } from "./index42.js";
12
- import "./index43.js";
13
- import { SystemMessage, AIMessage, HumanMessage } from "@langchain/core/messages";
14
- import { ToolRegistry } from "./index44.js";
15
- import { ExecutionPipeline } from "./index45.js";
16
- import { FormEngine } from "./index11.js";
17
- function hasHashLinkBlock(metadata) {
18
- if (!metadata || typeof metadata !== "object") {
19
- return false;
20
- }
21
- const meta = metadata;
22
- if (!("hashLinkBlock" in meta) || !meta.hashLinkBlock || typeof meta.hashLinkBlock !== "object") {
23
- return false;
24
- }
25
- const block = meta.hashLinkBlock;
26
- return "blockId" in block && "hashLink" in block && "template" in block && "attributes" in block && typeof block.blockId === "string" && typeof block.hashLink === "string" && typeof block.template === "string" && typeof block.attributes === "object";
27
- }
28
- class LangChainAgent extends BaseAgent {
29
- constructor() {
30
- super(...arguments);
31
- this.systemMessage = "";
32
- this.mcpConnectionStatus = /* @__PURE__ */ new Map();
33
- }
34
- addToolRawToMemory(name, payload) {
35
- try {
36
- const content = `[tool-raw:${name}] ${payload}`;
37
- this.smartMemory.addMessage(new SystemMessage(content));
38
- } catch {
39
- }
40
- }
41
- persistToolRaw(toolName, output) {
42
- try {
43
- let payload = "";
44
- if (typeof output === "string") {
45
- payload = this.isJSON(output) ? output : JSON.stringify({ output });
46
- } else if (output !== void 0) {
47
- try {
48
- payload = JSON.stringify(output);
49
- } catch {
50
- payload = String(output);
51
- }
52
- } else {
53
- payload = JSON.stringify({ observation: null });
54
- }
55
- this.addToolRawToMemory(toolName, payload);
56
- } catch {
57
- }
58
- }
59
- persistIntermediateSteps(steps) {
60
- if (!steps || !Array.isArray(steps)) {
61
- return;
62
- }
63
- try {
64
- for (const step of steps) {
65
- const name = step?.action?.tool || "unknown";
66
- const obs = step?.observation;
67
- this.persistToolRaw(name, obs);
68
- }
69
- } catch {
70
- }
1
+ import { StructuredTool } from "@langchain/core/tools";
2
+ import { z } from "zod";
3
+ import { Logger } from "@hashgraphonline/standards-sdk";
4
+ import { isFormValidatable } from "@hashgraphonline/standards-agent-kit";
5
+ class FormValidatingToolWrapper extends StructuredTool {
6
+ constructor(originalTool, formGenerator, config = {}) {
7
+ super();
8
+ this.originalTool = originalTool;
9
+ this.formGenerator = formGenerator;
10
+ this.validationConfig = config;
11
+ this.logger = new Logger({ module: "FormValidatingToolWrapper" });
12
+ this.name = originalTool.name;
13
+ this.description = originalTool.description;
14
+ this.schema = originalTool.schema;
15
+ this.logger.info(`🔧 FormValidatingToolWrapper created for tool: ${this.name}`, {
16
+ originalToolName: originalTool.name,
17
+ originalToolType: originalTool.constructor.name,
18
+ wrapperType: this.constructor.name
19
+ });
71
20
  }
72
21
  /**
73
- * Get inscription tool by capability instead of hardcoded name
22
+ * Validate the input against the schema
74
23
  */
75
- getInscriptionTool() {
76
- const criticalTools = this.toolRegistry.getToolsByCapability(
77
- "priority",
78
- "critical"
79
- );
80
- for (const entry of criticalTools) {
81
- const tool = entry.tool;
82
- const name = tool.name.toLowerCase();
83
- const desc = tool.description?.toLowerCase() || "";
84
- if (name.includes("inscribe") || name.includes("hashinal") || desc.includes("inscribe") || desc.includes("hashinal")) {
85
- return tool;
86
- }
87
- }
88
- const allTools = this.toolRegistry.getAllRegistryEntries();
89
- for (const entry of allTools) {
90
- const tool = entry.tool;
91
- const name = tool.name.toLowerCase();
92
- const desc = tool.description?.toLowerCase() || "";
93
- if (name.includes("inscribe") || name.includes("hashinal") || desc.includes("inscribe") || desc.includes("hashinal")) {
94
- return tool;
24
+ validateInput(input) {
25
+ try {
26
+ this.schema.parse(input);
27
+ return { isValid: true };
28
+ } catch (error) {
29
+ if (error instanceof z.ZodError) {
30
+ const errors = error.errors.filter((err) => {
31
+ const fieldName = err.path[0];
32
+ return !this.validationConfig.skipFields?.includes(fieldName);
33
+ }).map((err) => `${err.path.join(".")}: ${err.message}`);
34
+ return { isValid: false, errors };
95
35
  }
36
+ return { isValid: false, errors: ["Validation failed"] };
96
37
  }
97
- return null;
98
38
  }
99
39
  /**
100
- * Execute a tool directly with parameters, optionally using ExecutionPipeline
40
+ * Gets the shape keys from the schema if it's a ZodObject
101
41
  */
102
- async executeToolDirect(toolName, parameters, useExecutionPipeline = false) {
103
- if (useExecutionPipeline && this.executionPipeline && this.smartMemory) {
104
- const sessionContext = {
105
- sessionId: `session-${Date.now()}`,
106
- timestamp: Date.now()
107
- };
108
- const result = await this.executionPipeline.execute(
109
- toolName,
110
- parameters,
111
- sessionContext
112
- );
113
- if (!result.success) {
114
- throw new Error(result.error || "Pipeline execution failed");
115
- }
116
- return result.output;
117
- }
118
- const entry = this.toolRegistry.getTool(toolName);
119
- if (!entry) {
120
- throw new Error(`Tool not found: ${toolName}`);
42
+ getSchemaShape() {
43
+ if (this.isZodObject(this.schema)) {
44
+ return Object.keys(this.schema.shape);
121
45
  }
122
- let processedParameters = { ...parameters };
123
- if (this.pendingParameterPreprocessingCallback) {
124
- this.logger.info(
125
- "Applying parameter preprocessing in executeToolDirect",
126
- {
127
- toolName,
128
- hasCallback: true,
129
- parameterKeys: Object.keys(parameters)
130
- }
131
- );
132
- try {
133
- processedParameters = await this.pendingParameterPreprocessingCallback(
134
- toolName,
135
- parameters
136
- );
137
- if (JSON.stringify(processedParameters) !== JSON.stringify(parameters)) {
138
- this.logger.info("Parameters preprocessed successfully", {
139
- toolName,
140
- originalKeys: Object.keys(parameters),
141
- processedKeys: Object.keys(processedParameters),
142
- changes: Object.keys(processedParameters).filter(
143
- (key) => processedParameters[key] !== parameters[key]
144
- )
145
- });
146
- }
147
- } catch (error) {
148
- this.logger.warn(
149
- "Parameter preprocessing failed, using original parameters",
150
- {
151
- toolName,
152
- error: error instanceof Error ? error.message : "Unknown error"
153
- }
154
- );
155
- processedParameters = parameters;
156
- }
157
- }
158
- const mergedArgs = { ...processedParameters, renderForm: false };
159
- if (entry.wrapper) {
160
- const maybeWrapper = entry.tool;
161
- if (maybeWrapper.originalTool?.call) {
162
- return await maybeWrapper.originalTool.call(mergedArgs);
163
- }
164
- }
165
- return await entry.tool.call(mergedArgs);
166
- }
167
- /**
168
- * Create a standard ChatResponse from tool output
169
- */
170
- createToolResponse(toolOutput) {
171
- return {
172
- output: toolOutput,
173
- message: toolOutput,
174
- notes: []
175
- };
46
+ return [];
176
47
  }
177
48
  /**
178
- * Handle TOOL_EXECUTION format messages
49
+ * Executes the wrapped tool's original implementation directly, bypassing wrapper logic.
179
50
  */
180
- async handleToolExecution(message, context) {
181
- let isToolExecution = false;
182
- let toolExecutionData = null;
183
- try {
184
- if (message.includes("TOOL_EXECUTION")) {
185
- const parsed = JSON.parse(message);
186
- if (parsed.type === "TOOL_EXECUTION") {
187
- isToolExecution = true;
188
- toolExecutionData = parsed;
189
- }
190
- }
191
- } catch {
51
+ async executeOriginal(input, runManager) {
52
+ const tool = this.originalTool;
53
+ if ("_call" in tool && typeof tool._call === "function") {
54
+ return tool._call(input, runManager);
192
55
  }
193
- if (!isToolExecution || !toolExecutionData?.formId) {
194
- return null;
56
+ if ("call" in tool && typeof tool.call === "function") {
57
+ return tool.call(input, runManager);
195
58
  }
196
- try {
197
- const params = toolExecutionData.parameters || {};
198
- const toolName = toolExecutionData.toolName;
199
- if (toolName) {
200
- const toolOutput = await this.executeToolDirect(toolName, params);
201
- try {
202
- const payload = this.isJSON(toolOutput) ? toolOutput : JSON.stringify({ output: toolOutput });
203
- this.addToolRawToMemory(toolName, payload);
204
- } catch {
205
- }
206
- return this.createToolResponse(toolOutput);
207
- }
208
- } catch {
209
- }
210
- const formSubmission = {
211
- formId: toolExecutionData.formId,
212
- toolName: toolExecutionData.toolName || "",
213
- parameters: toolExecutionData.parameters || {},
214
- timestamp: Date.now()
215
- };
216
- if (this.executor && "processFormSubmission" in this.executor && typeof this.executor.processFormSubmission === "function") {
217
- return this.processFormSubmission(formSubmission, context);
218
- }
219
- return null;
59
+ throw new Error("Original tool has no callable implementation");
220
60
  }
221
61
  /**
222
- * Handle direct tool execution commands
62
+ * Provides access to the wrapped tool instance for executors that want to bypass the wrapper.
223
63
  */
224
- async handleDirectToolExecution(message) {
225
- if (typeof message !== "string" || !message.includes("Please execute the following tool:")) {
226
- return null;
227
- }
228
- try {
229
- const toolLineMatch = message.match(/Tool:\s*(.+)/);
230
- const argsLineIndex = message.indexOf("Arguments:");
231
- if (toolLineMatch && argsLineIndex !== -1) {
232
- const toolName = toolLineMatch[1].trim();
233
- const argsText = message.slice(argsLineIndex + "Arguments:".length).trim();
234
- let args = {};
235
- try {
236
- args = JSON.parse(argsText);
237
- } catch {
238
- }
239
- const toolOutput = await this.executeToolDirect(toolName, args);
240
- try {
241
- const payload = this.isJSON(toolOutput) ? toolOutput : JSON.stringify({ output: toolOutput });
242
- this.addToolRawToMemory(toolName, payload);
243
- } catch {
244
- }
245
- return this.createToolResponse(toolOutput);
246
- }
247
- } catch {
248
- }
249
- return null;
64
+ getOriginalTool() {
65
+ return this.originalTool;
250
66
  }
251
67
  /**
252
- * Handle JSON format tool calls and form submissions
68
+ * Checks if tool implements FormValidatable method
253
69
  */
254
- async handleJsonToolCalls(message, context) {
255
- if (typeof message !== "string") {
256
- return null;
257
- }
258
- try {
259
- const trimmed = message.trim();
260
- if (!(trimmed.startsWith("{") && trimmed.endsWith("}")) && !(trimmed.startsWith("[") && trimmed.endsWith("]"))) {
261
- return null;
262
- }
263
- const obj = JSON.parse(trimmed);
264
- const formId = obj["formId"];
265
- const toolName = obj["toolName"] || "";
266
- const parameters = obj["parameters"] || {};
267
- if (formId && this.executor && "processFormSubmission" in this.executor && typeof this.executor.processFormSubmission === "function") {
268
- return this.processFormSubmission(
269
- { formId, toolName, parameters, timestamp: Date.now() },
270
- context
271
- );
272
- }
273
- if (toolName) {
274
- const toolOutput = await this.executeToolDirect(toolName, parameters);
275
- try {
276
- const payload = this.isJSON(toolOutput) ? toolOutput : JSON.stringify({ output: toolOutput });
277
- this.addToolRawToMemory(toolName, payload);
278
- } catch {
279
- }
280
- return this.createToolResponse(toolOutput);
281
- }
282
- } catch {
283
- }
284
- return null;
70
+ hasFormValidatableMethod(tool, methodName) {
71
+ return tool !== null && typeof tool === "object" && methodName in tool && typeof tool[methodName] === "function";
285
72
  }
286
73
  /**
287
- * Handle content-ref messages for inscription tools
74
+ * Expose FormValidatable methods by delegating to the underlying tool when available.
288
75
  */
289
- async handleContentRefMessages(message) {
290
- if (typeof message !== "string" || !message.includes("content-ref:")) {
291
- return null;
292
- }
293
- try {
294
- const tool = this.getInscriptionTool();
295
- if (!tool) {
296
- return null;
297
- }
298
- const idMatch = message.match(/content-ref:([A-Za-z0-9_\-]+)/i) || message.match(/content-ref:([^\s)]+)/i);
299
- const contentRef = idMatch && idMatch[1] ? `content-ref:${idMatch[1]}` : message.match(/content-ref:[^\s)]+/i)?.[0] || void 0;
300
- const args = contentRef ? { contentRef, renderForm: true, withHashLinkBlocks: true } : { renderForm: true, withHashLinkBlocks: true };
301
- const toolOutput = await tool.call(args);
302
- let parsed;
303
- try {
304
- parsed = typeof toolOutput === "string" ? JSON.parse(toolOutput) : toolOutput;
305
- } catch {
306
- }
307
- if (parsed && parsed["requiresForm"] && parsed["formMessage"]) {
308
- const pending = /* @__PURE__ */ new Map();
309
- const originalInput = {
310
- input: message,
311
- chat_history: this.smartMemory.getMessages()
312
- };
313
- const formMessage = parsed["formMessage"];
314
- pending.set(formMessage.id, {
315
- toolName: tool.name,
316
- originalInput,
317
- originalToolInput: args,
318
- schema: null
319
- });
320
- const maybeRestore = this.executor;
321
- if (typeof maybeRestore.restorePendingForms === "function") {
322
- maybeRestore.restorePendingForms(pending);
323
- }
324
- const outputMsg = parsed["message"] || "Please complete the form to continue.";
325
- return {
326
- output: outputMsg,
327
- message: outputMsg,
328
- notes: [],
329
- requiresForm: true,
330
- formMessage
331
- };
332
- }
333
- } catch {
76
+ getFormSchema() {
77
+ if (this.hasFormValidatableMethod(this.originalTool, "getFormSchema")) {
78
+ return this.originalTool.getFormSchema();
334
79
  }
335
- return null;
80
+ return this.schema;
336
81
  }
337
- /**
338
- * Process executor result and format response
339
- */
340
- async processExecutorResult(result) {
341
- let outputStr = "";
342
- if (typeof result.output === "string") {
343
- outputStr = result.output;
344
- } else if (result.output) {
345
- try {
346
- outputStr = JSON.stringify(result.output);
347
- } catch {
348
- outputStr = String(result.output);
349
- }
350
- }
351
- let response = {
352
- output: outputStr,
353
- message: outputStr,
354
- notes: [],
355
- intermediateSteps: result.intermediateSteps
356
- };
357
- if (result.requiresForm && result.formMessage) {
358
- response.formMessage = result.formMessage;
359
- response.requiresForm = true;
360
- }
361
- if (result.intermediateSteps && Array.isArray(result.intermediateSteps)) {
362
- const toolCalls = result.intermediateSteps.map(
363
- (step, index) => ({
364
- id: `call_${index}`,
365
- name: step.action?.tool || "unknown",
366
- args: step.action?.toolInput || {},
367
- output: typeof step.observation === "string" ? step.observation : JSON.stringify(step.observation)
368
- })
369
- );
370
- if (toolCalls.length > 0) {
371
- response.tool_calls = toolCalls;
372
- }
373
- this.persistIntermediateSteps(
374
- result.intermediateSteps
375
- );
376
- }
377
- const steps = result?.intermediateSteps || [];
378
- const lastJsonObservation = [...steps].reverse().find(
379
- (s) => typeof s?.observation === "string" && this.isJSON(s.observation)
380
- )?.observation;
381
- if (lastJsonObservation) {
382
- try {
383
- const parsed = JSON.parse(lastJsonObservation);
384
- if (ResponseFormatter.isInscriptionResponse(parsed)) {
385
- const formattedMessage = ResponseFormatter.formatInscriptionResponse(parsed);
386
- response.output = formattedMessage;
387
- response.message = formattedMessage;
388
- if (parsed.inscription) {
389
- response.inscription = parsed.inscription;
390
- }
391
- if (parsed.metadata) {
392
- response.metadata = { ...response.metadata, ...parsed.metadata };
393
- }
394
- } else {
395
- if (typeof parsed.message === "string" && parsed.message.trim().length > 0) {
396
- response.message = parsed.message;
397
- response.output = parsed.message;
398
- }
399
- if (parsed.success === true) {
400
- delete response.error;
401
- }
402
- if (typeof parsed.transactionBytes === "string") {
403
- response.metadata = {
404
- ...response.metadata,
405
- transactionBytes: parsed.transactionBytes
406
- };
407
- }
408
- if (typeof parsed.scheduleId === "string") {
409
- response.scheduleId = parsed.scheduleId;
410
- }
411
- }
412
- const blockMetadata = this.processHashLinkBlocks(parsed);
413
- if (blockMetadata.hashLinkBlock) {
414
- response.metadata = { ...response.metadata, ...blockMetadata };
415
- }
416
- } catch (error) {
417
- this.logger.error("Error parsing intermediate steps:", error);
418
- }
82
+ getEssentialFields() {
83
+ if (this.hasFormValidatableMethod(this.originalTool, "getEssentialFields")) {
84
+ return this.originalTool.getEssentialFields();
419
85
  }
420
- if (!response.output || response.output.trim() === "") {
421
- response.output = "Agent action complete.";
86
+ return [];
87
+ }
88
+ isFieldEmpty(fieldName, value) {
89
+ if (this.hasFormValidatableMethod(this.originalTool, "isFieldEmpty")) {
90
+ return this.originalTool.isFieldEmpty(fieldName, value);
422
91
  }
423
- if (response.output) {
424
- this.smartMemory.addMessage(new AIMessage(response.output));
92
+ if (value === void 0 || value === null || value === "") {
93
+ return true;
425
94
  }
426
- if (this.tokenTracker) {
427
- const tokenUsage = this.tokenTracker.getLatestTokenUsage();
428
- if (tokenUsage) {
429
- response.tokenUsage = tokenUsage;
430
- response.cost = calculateTokenCostSync(tokenUsage);
431
- }
95
+ if (Array.isArray(value) && value.length === 0) {
96
+ return true;
432
97
  }
433
- const finalMemoryStats = this.smartMemory.getMemoryStats();
434
- response.metadata = {
435
- ...response.metadata,
436
- memoryStats: {
437
- activeMessages: finalMemoryStats.totalActiveMessages,
438
- tokenUsage: finalMemoryStats.currentTokenCount,
439
- maxTokens: finalMemoryStats.maxTokens,
440
- usagePercentage: finalMemoryStats.usagePercentage
441
- }
442
- };
443
- this.logger.info("LangChainAgent.chat returning response:", response);
444
- return response;
98
+ return false;
445
99
  }
446
100
  /**
447
- * Normalize context messages into LangChain message instances and load into memory
448
- */
449
- /**
450
- * Loads context messages into memory, merging with existing messages
101
+ * Calculates which fields are missing from the input
451
102
  */
452
- loadContextMessages(context) {
453
- if (!this.smartMemory || !context?.messages || context.messages.length === 0) {
454
- return;
455
- }
456
- const existingMessages = this.smartMemory.getMessages();
457
- const existingContent = new Set(
458
- existingMessages.map((m) => `${m.constructor.name}:${m.content}`)
459
- );
460
- for (const msg of context.messages) {
461
- let messageClass;
462
- let content;
463
- if (msg instanceof HumanMessage || msg instanceof AIMessage || msg instanceof SystemMessage) {
464
- messageClass = msg.constructor;
465
- content = msg.content;
466
- } else if (msg && typeof msg === "object" && "content" in msg && "type" in msg) {
467
- content = String(msg.content);
468
- const type = String(msg.type);
469
- if (type === "human") messageClass = HumanMessage;
470
- else if (type === "ai") messageClass = AIMessage;
471
- else if (type === "system") messageClass = SystemMessage;
472
- else continue;
473
- } else {
474
- continue;
475
- }
476
- const key = `${messageClass.name}:${content}`;
477
- if (!existingContent.has(key)) {
478
- this.smartMemory.addMessage(new messageClass(content));
479
- existingContent.add(key);
480
- }
481
- }
482
- }
483
- async boot() {
484
- this.logger.info("🚨🚨🚨 LANGCHAIN AGENT BOOT METHOD CALLED 🚨🚨🚨");
485
- if (this.initialized) {
486
- this.logger.warn("Agent already initialized");
487
- return;
488
- }
489
- try {
490
- this.agentKit = await this.createAgentKit();
491
- await this.agentKit.initialize();
492
- const modelName = this.config.ai?.modelName || process.env.OPENAI_MODEL_NAME || "gpt-4o-mini";
493
- try {
494
- if (typeof TokenUsageCallbackHandler === "function") {
495
- this.tokenTracker = new TokenUsageCallbackHandler(modelName);
496
- } else {
497
- this.logger.warn("TokenUsageCallbackHandler unavailable or not a constructor; skipping token tracking");
498
- }
499
- } catch {
500
- this.logger.warn("TokenUsageCallbackHandler threw; skipping token tracking");
501
- }
502
- this.toolRegistry = new ToolRegistry(this.logger);
503
- const allTools = this.agentKit.getAggregatedLangChainTools();
504
- this.logger.info("=== TOOL REGISTRATION START ===");
505
- this.logger.info(
506
- "All tools from agentKit:",
507
- allTools.map((t) => t.name)
508
- );
509
- const filteredTools = this.filterTools(allTools);
510
- this.logger.info(
511
- "Filtered tools for registration:",
512
- filteredTools.map((t) => t.name)
513
- );
514
- for (const tool of filteredTools) {
515
- this.logger.info(`🔧 Registering tool: ${tool.name}`);
516
- const options = {};
517
- const name = tool.name.toLowerCase();
518
- const desc = tool.description?.toLowerCase() || "";
519
- if (tool.name === "hedera-hts-mint-nft") {
520
- const originalCall = tool.call.bind(tool);
521
- tool.call = async (args) => {
522
- if (args.metaOptions && typeof args.metaOptions === "object") {
523
- const metaOptions = args.metaOptions;
524
- if (metaOptions.transactionMemo) {
525
- this.logger.warn(
526
- "🚨 WORKAROUND: Stripping transactionMemo from hedera-hts-mint-nft to avoid bug",
527
- { originalMemo: metaOptions.transactionMemo }
528
- );
529
- delete metaOptions.transactionMemo;
530
- }
531
- }
532
- return originalCall(args);
533
- };
534
- }
535
- if (name.includes("inscribe") || name.includes("hashinal") || desc.includes("inscribe") || desc.includes("hashinal")) {
536
- options.forceWrapper = true;
537
- options.metadata = {
538
- category: "core",
539
- version: "1.0.0",
540
- dependencies: []
541
- };
542
- this.logger.info(`🎯 CRITICAL TOOL DEBUG - ${tool.name} schema:`, {
543
- hasSchema: !!tool.schema,
544
- schemaType: tool.schema?.constructor?.name,
545
- hasRenderConfig: !!tool.schema?._renderConfig,
546
- renderConfig: tool.schema?._renderConfig
547
- });
548
- }
549
- this.toolRegistry.registerTool(tool, options);
550
- }
551
- this.tools = this.toolRegistry.getAllTools();
552
- this.logger.info(`🚀 TOOLS REGISTERED: ${this.tools.length} tools`);
553
- const stats = this.toolRegistry.getStatistics();
554
- this.logger.info("📊 Tool Registry Statistics:", {
555
- total: stats.totalTools,
556
- wrapped: stats.wrappedTools,
557
- unwrapped: stats.unwrappedTools,
558
- categories: stats.categoryCounts,
559
- priorities: stats.priorityCounts
560
- });
561
- const inscriptionTool = this.getInscriptionTool();
562
- if (inscriptionTool) {
563
- const entry = this.toolRegistry.getTool(inscriptionTool.name);
564
- if (entry) {
565
- this.logger.info(
566
- `✅ Inscription tool registered: ${inscriptionTool.name}`
567
- );
568
- }
569
- }
570
- const toolNames = this.toolRegistry.getToolNames();
571
- const uniqueNames = new Set(toolNames);
572
- if (toolNames.length !== uniqueNames.size) {
573
- this.logger.error("DUPLICATE TOOL NAMES DETECTED in registry!");
574
- const duplicates = toolNames.filter(
575
- (name, index) => toolNames.indexOf(name) !== index
576
- );
577
- throw new Error(
578
- `Duplicate tool names detected: ${duplicates.join(", ")}`
579
- );
580
- }
581
- if (this.config.mcp?.servers && this.config.mcp.servers.length > 0) {
582
- if (this.config.mcp.autoConnect !== false) {
583
- await this.initializeMCP();
584
- } else {
585
- this.logger.info(
586
- "MCP servers configured but autoConnect=false, skipping synchronous connection"
587
- );
588
- this.mcpManager = new MCPClientManager(this.logger);
589
- }
590
- }
591
- this.smartMemory = new SmartMemoryManager({
592
- modelName,
593
- maxTokens: 9e4,
594
- reserveTokens: 1e4,
595
- storageLimit: 1e3
596
- });
597
- this.logger.info("SmartMemoryManager initialized:", {
598
- modelName,
599
- toolsCount: this.tools.length,
600
- maxTokens: 9e4,
601
- reserveTokens: 1e4
602
- });
603
- this.formEngine = new FormEngine(this.logger);
604
- this.executionPipeline = new ExecutionPipeline(
605
- this.toolRegistry,
606
- this.formEngine,
607
- this.smartMemory,
608
- this.logger
609
- );
610
- this.systemMessage = this.buildSystemPrompt();
611
- this.smartMemory.setSystemPrompt(this.systemMessage);
612
- await this.createExecutor();
613
- this.initialized = true;
614
- this.logger.info("LangChain Hedera agent initialized with ToolRegistry");
615
- } catch (error) {
616
- this.logger.error("Failed to initialize agent:", error);
617
- throw error;
103
+ calculateMissingFields(input, isCustom) {
104
+ const missingFields = /* @__PURE__ */ new Set();
105
+ if (!isCustom) {
106
+ return missingFields;
618
107
  }
619
- }
620
- async chat(message, context) {
621
- if (!this.initialized || !this.executor || !this.smartMemory) {
622
- throw new Error("Agent not initialized. Call boot() first.");
623
- }
624
- try {
625
- const toolExecutionResult = await this.handleToolExecution(
626
- message,
627
- context
628
- );
629
- if (toolExecutionResult) {
630
- return toolExecutionResult;
631
- }
632
- const directToolResult = await this.handleDirectToolExecution(message);
633
- if (directToolResult) {
634
- return directToolResult;
108
+ const essentialFields = this.getEssentialFields();
109
+ for (const fieldName of essentialFields) {
110
+ const value = input[fieldName];
111
+ if (this.isFieldEmpty(fieldName, value)) {
112
+ missingFields.add(fieldName);
635
113
  }
636
- const jsonToolResult = await this.handleJsonToolCalls(message, context);
637
- if (jsonToolResult) {
638
- return jsonToolResult;
639
- }
640
- const contentRefResult = await this.handleContentRefMessages(message);
641
- if (contentRefResult) {
642
- return contentRefResult;
643
- }
644
- this.logger.info("LangChainAgent.chat called with:", {
645
- message,
646
- contextLength: context?.messages?.length || 0
647
- });
648
- this.loadContextMessages(context);
649
- this.smartMemory.addMessage(new HumanMessage(message));
650
- const memoryStats = this.smartMemory.getMemoryStats();
651
- this.logger.info("Memory stats before execution:", {
652
- totalMessages: memoryStats.totalActiveMessages,
653
- currentTokens: memoryStats.currentTokenCount,
654
- maxTokens: memoryStats.maxTokens,
655
- usagePercentage: memoryStats.usagePercentage,
656
- toolsCount: this.tools.length
657
- });
658
- const currentMessages = this.smartMemory.getMessages();
659
- this.logger.info("Current messages in memory:", {
660
- count: currentMessages.length
661
- });
662
- try {
663
- const instr = currentMessages.map((m) => String(m.content || "")).filter(
664
- (c) => typeof c === "string" && (c.includes("[instruction:") || c.includes("[tool-next-steps:"))
665
- );
666
- if (instr.length > 0) {
667
- this.logger.info("Instruction/next-steps messages in memory:", {
668
- messages: instr
669
- });
670
- }
671
- } catch {
672
- }
673
- const result = await this.executor.invoke({
674
- input: message,
675
- chat_history: currentMessages
676
- });
677
- this.logger.info("LangChainAgent executor result:", result);
678
- return this.processExecutorResult(result);
679
- } catch (error) {
680
- this.logger.error("LangChainAgent.chat error:", error);
681
- return this.handleError(error);
682
114
  }
683
- }
684
- async shutdown() {
685
- if (this.mcpManager) {
686
- await this.mcpManager.disconnectAll();
687
- }
688
- if (this.smartMemory) {
689
- this.smartMemory.dispose();
690
- this.smartMemory = void 0;
691
- }
692
- if (this.toolRegistry) {
693
- this.toolRegistry.clear();
694
- }
695
- this.executor = void 0;
696
- this.agentKit = void 0;
697
- this.tools = [];
698
- this.initialized = false;
699
- this.logger.info("Agent cleaned up");
700
- }
701
- switchMode(mode) {
702
- if (this.config.execution) {
703
- this.config.execution.operationalMode = mode;
704
- } else {
705
- this.config.execution = { operationalMode: mode };
706
- }
707
- if (this.agentKit) {
708
- this.agentKit.operationalMode = mode;
709
- }
710
- this.systemMessage = this.buildSystemPrompt();
711
- this.logger.info(`Operational mode switched to: ${mode}`);
712
- }
713
- getUsageStats() {
714
- if (!this.tokenTracker) {
715
- return {
716
- promptTokens: 0,
717
- completionTokens: 0,
718
- totalTokens: 0,
719
- cost: { totalCost: 0 }
720
- };
721
- }
722
- const usage = this.tokenTracker.getTotalTokenUsage();
723
- const cost = calculateTokenCostSync(usage);
724
- return { ...usage, cost };
725
- }
726
- getUsageLog() {
727
- if (!this.tokenTracker) {
728
- return [];
729
- }
730
- return this.tokenTracker.getTokenUsageHistory().map((usage) => ({
731
- ...usage,
732
- cost: calculateTokenCostSync(usage)
733
- }));
734
- }
735
- clearUsageStats() {
736
- if (this.tokenTracker) {
737
- this.tokenTracker.reset();
738
- this.logger.info("Usage statistics cleared");
739
- }
740
- }
741
- getMCPConnectionStatus() {
742
- return new Map(this.mcpConnectionStatus);
115
+ return missingFields;
743
116
  }
744
117
  /**
745
- * Processes form submission and continues with tool execution
118
+ * Creates a form message with optional JSON schema
746
119
  */
747
- async processFormSubmission(submission, context) {
748
- if (!this.initialized || !this.executor || !this.smartMemory) {
749
- throw new Error("Agent not initialized. Call boot() first.");
750
- }
751
- try {
752
- if (!submission.parameters || typeof submission.parameters !== "object") {
753
- this.logger.error("Invalid form submission parameters:", {
754
- parameters: submission.parameters,
755
- type: typeof submission.parameters
756
- });
757
- const errorInfo = JSON.stringify(submission, null, 2);
758
- return this.handleError(
759
- new Error(`Invalid form submission parameters: ${errorInfo}`)
760
- );
761
- }
762
- this.loadContextMessages(context);
763
- const safeSubmission = {
764
- ...submission,
765
- parameters: submission.parameters || {}
766
- };
767
- const result = await this.executor.processFormSubmission(safeSubmission);
768
- const preservedMetadata = result?.metadata ? { ...result.metadata } : {};
120
+ async createFormMessage(schema, input, missingFields) {
121
+ let formMessage = await this.formGenerator.generateFormFromSchema(
122
+ schema,
123
+ input,
124
+ {
125
+ toolName: this.name,
126
+ toolDescription: this.description
127
+ },
128
+ missingFields
129
+ );
130
+ if (this.isZodObject(schema)) {
769
131
  try {
770
- const maybeRaw = result.rawToolOutput;
771
- const toolName = result.toolName || "unknown";
772
- if (typeof maybeRaw === "string" && maybeRaw.trim().length > 0) {
773
- const payload = this.isJSON(maybeRaw) ? maybeRaw : JSON.stringify({ output: maybeRaw });
774
- this.addToolRawToMemory(toolName, payload);
775
- }
776
- } catch {
777
- }
778
- let outputMessage = "Form processed successfully.";
779
- if (typeof result.output === "string") {
780
- outputMessage = result.output;
781
- } else if (result.output) {
782
- try {
783
- outputMessage = JSON.stringify(result.output);
784
- } catch {
785
- outputMessage = String(result.output);
786
- }
787
- }
788
- let response = {
789
- output: outputMessage,
790
- message: outputMessage,
791
- notes: [],
792
- intermediateSteps: result.intermediateSteps
793
- };
794
- if (result.metadata) {
795
- response.metadata = {
796
- ...response.metadata,
797
- ...result.metadata
132
+ const { jsonSchema, uiSchema } = this.formGenerator.generateJsonSchemaForm(
133
+ schema,
134
+ input,
135
+ missingFields
136
+ );
137
+ formMessage = {
138
+ ...formMessage,
139
+ jsonSchema,
140
+ uiSchema
798
141
  };
799
- this.logger.info("🔍 DEBUG: Metadata after merge from result:", {
800
- hasMetadata: !!response.metadata,
801
- metadataKeys: response.metadata ? Object.keys(response.metadata) : [],
802
- hasHashLinkBlock: hasHashLinkBlock(response.metadata),
803
- hashLinkBlockContent: hasHashLinkBlock(response.metadata) ? response.metadata.hashLinkBlock : void 0
804
- });
805
- }
806
- if (result.requiresForm && result.formMessage) {
807
- response.formMessage = result.formMessage;
808
- response.requiresForm = true;
809
- }
810
- if (result.intermediateSteps && Array.isArray(result.intermediateSteps)) {
811
- const toolCalls = result.intermediateSteps.map(
812
- (step, index) => {
813
- const name = step?.action?.tool || "unknown";
814
- const args = step?.action?.toolInput || {};
815
- const obs = step?.observation;
816
- let output = "";
817
- if (typeof obs === "string") {
818
- output = obs;
819
- } else if (obs && typeof obs === "object") {
820
- try {
821
- output = JSON.stringify(obs);
822
- } catch {
823
- output = String(obs);
824
- }
825
- } else if (obs !== void 0) {
826
- output = String(obs);
827
- }
828
- return { id: `call_${index}`, name, args, output };
829
- }
830
- );
831
- if (toolCalls.length > 0) {
832
- response.tool_calls = toolCalls;
833
- }
834
- this.persistIntermediateSteps(
835
- result.intermediateSteps
836
- );
837
- }
838
- const parsedSteps = result?.intermediateSteps?.[0]?.observation;
839
- if (parsedSteps && typeof parsedSteps === "string" && this.isJSON(parsedSteps)) {
840
- try {
841
- const parsed = JSON.parse(parsedSteps);
842
- response = { ...response, ...parsed };
843
- const blockMetadata = this.processHashLinkBlocks(parsed);
844
- if (blockMetadata.hashLinkBlock) {
845
- response.metadata = {
846
- ...response.metadata,
847
- ...blockMetadata
848
- };
849
- }
850
- } catch (error) {
851
- this.logger.error("Error parsing intermediate steps:", error);
852
- }
853
- }
854
- if (response.output) {
855
- this.smartMemory.addMessage(new AIMessage(response.output));
856
- }
857
- if (this.tokenTracker) {
858
- const tokenUsage = this.tokenTracker.getLatestTokenUsage();
859
- if (tokenUsage) {
860
- response.tokenUsage = tokenUsage;
861
- response.cost = calculateTokenCostSync(tokenUsage);
862
- }
863
- }
864
- const finalMemoryStats = this.smartMemory.getMemoryStats();
865
- this.logger.info("🔍 DEBUG: Metadata before memoryStats merge:", {
866
- hasMetadata: !!response.metadata,
867
- metadataKeys: response.metadata ? Object.keys(response.metadata) : [],
868
- hasHashLinkBlock: hasHashLinkBlock(response.metadata)
869
- });
870
- response.metadata = {
871
- ...preservedMetadata,
872
- ...response.metadata,
873
- memoryStats: {
874
- activeMessages: finalMemoryStats.totalActiveMessages,
875
- tokenUsage: finalMemoryStats.currentTokenCount,
876
- maxTokens: finalMemoryStats.maxTokens,
877
- usagePercentage: finalMemoryStats.usagePercentage
878
- }
879
- };
880
- this.logger.info("🔍 DEBUG: Final response metadata before return:", {
881
- hasMetadata: !!response.metadata,
882
- metadataKeys: response.metadata ? Object.keys(response.metadata) : [],
883
- hasHashLinkBlock: hasHashLinkBlock(response.metadata),
884
- fullMetadata: response.metadata
885
- });
886
- if (hasHashLinkBlock(preservedMetadata) && !hasHashLinkBlock(response.metadata)) {
887
- this.logger.error(
888
- "❌ CRITICAL: HashLink metadata was lost during processing!"
889
- );
890
- this.logger.error(
891
- "Original metadata had hashLinkBlock:",
892
- preservedMetadata.hashLinkBlock
893
- );
894
- this.logger.error("Final metadata missing hashLinkBlock");
142
+ } catch (error) {
143
+ this.logger.warn("Failed to generate JSON Schema for RJSF:", error);
895
144
  }
896
- return response;
897
- } catch (error) {
898
- this.logger.error("Form submission processing error:", error);
899
- return this.handleError(error);
900
145
  }
146
+ formMessage.partialInput = input;
147
+ return formMessage;
901
148
  }
902
149
  /**
903
- * Check if the agent has pending forms that need to be completed
150
+ * Type guard to check if a schema is a ZodObject
904
151
  */
905
- hasPendingForms() {
906
- return this.executor ? this.executor.hasPendingForms() : false;
152
+ isZodObject(schema) {
153
+ const def = schema._def;
154
+ return !!(def && def.typeName === "ZodObject");
907
155
  }
908
156
  /**
909
- * Get information about pending forms
157
+ * Check if we should generate a form for this tool invocation
910
158
  */
911
- getPendingFormsInfo() {
912
- return this.executor ? this.executor.getPendingFormsInfo() : [];
913
- }
914
- async createAgentKit() {
915
- const corePlugins = getAllHederaCorePlugins();
916
- const extensionPlugins = this.config.extensions?.plugins || [];
917
- const plugins = [...corePlugins, ...extensionPlugins];
918
- const operationalMode = this.config.execution?.operationalMode || "returnBytes";
919
- const modelName = this.config.ai?.modelName || "gpt-4o";
920
- return new HederaAgentKit(
921
- this.config.signer,
922
- { plugins },
923
- operationalMode,
924
- this.config.execution?.userAccountId,
925
- this.config.execution?.scheduleUserTransactionsInBytesMode ?? false,
926
- void 0,
927
- modelName,
928
- this.config.extensions?.mirrorConfig,
929
- this.config.debug?.silent ?? false
930
- );
931
- }
932
- async createExecutor() {
933
- const existingPendingForms = this.executor?.getPendingForms() || /* @__PURE__ */ new Map();
934
- let llm;
935
- if (this.config.ai?.provider && this.config.ai.provider.getModel) {
936
- llm = this.config.ai.provider.getModel();
937
- } else if (this.config.ai?.llm) {
938
- llm = this.config.ai.llm;
939
- } else {
940
- const apiKey = this.config.ai?.apiKey || process.env.OPENAI_API_KEY;
941
- if (!apiKey) {
942
- throw new Error("OpenAI API key required");
943
- }
944
- const modelName = this.config.ai?.modelName || "gpt-4o-mini";
945
- const isGPT5Model = modelName.toLowerCase().includes("gpt-5") || modelName.toLowerCase().includes("gpt5");
946
- llm = new ChatOpenAI({
947
- apiKey,
948
- modelName,
949
- callbacks: this.tokenTracker ? [this.tokenTracker] : [],
950
- ...isGPT5Model ? { temperature: 1 } : {}
951
- });
952
- }
953
- const prompt = ChatPromptTemplate.fromMessages([
954
- ["system", this.systemMessage],
955
- new MessagesPlaceholder("chat_history"),
956
- ["human", "{input}"],
957
- new MessagesPlaceholder("agent_scratchpad")
958
- ]);
959
- const langchainTools = this.tools;
960
- const inscriptionTool = this.getInscriptionTool();
961
- if (inscriptionTool) {
962
- const entry = this.toolRegistry.getTool(inscriptionTool.name);
963
- if (entry) {
964
- this.logger.info(
965
- `✅ Inscription tool registered: ${inscriptionTool.name}`
966
- );
967
- }
968
- }
969
- const stats = this.toolRegistry.getStatistics();
970
- this.logger.info("🛡️ TOOL SECURITY REPORT:", {
971
- totalTools: stats.totalTools,
972
- wrappedTools: stats.wrappedTools,
973
- unwrappedTools: stats.unwrappedTools,
974
- categories: stats.categoryCounts,
975
- priorities: stats.priorityCounts
159
+ shouldGenerateForm(input) {
160
+ this.logger.info(`shouldGenerateForm called for ${this.name}/${this.originalTool.name}`, {
161
+ input,
162
+ hasCustomValidation: !!this.validationConfig.customValidation
976
163
  });
977
- this.logger.info(
978
- `📊 Tool Security Summary: ${stats.wrappedTools} wrapped, ${stats.unwrappedTools} unwrapped`
979
- );
980
- const agent = await createOpenAIToolsAgent({
981
- llm,
982
- tools: langchainTools,
983
- prompt
164
+ if (this.validationConfig.customValidation) {
165
+ const result = !this.validationConfig.customValidation(input);
166
+ this.logger.info(`Custom validation result: ${result}`);
167
+ return result;
168
+ }
169
+ if (isFormValidatable(this.originalTool)) {
170
+ this.logger.info(`Tool ${this.originalTool.name} implements FormValidatable, using custom logic`);
171
+ return this.originalTool.shouldGenerateForm(input);
172
+ }
173
+ this.logger.info(`Tool ${this.originalTool.name} using schema validation only`);
174
+ const validation = this.validateInput(input);
175
+ this.logger.info(`Schema validation for ${this.originalTool.name}:`, {
176
+ isValid: validation.isValid,
177
+ errors: validation.errors
984
178
  });
985
- this.executor = new FormAwareAgentExecutor({
986
- agent,
987
- tools: langchainTools,
988
- verbose: this.config.debug?.verbose ?? false,
989
- returnIntermediateSteps: true
990
- });
991
- if (this.pendingParameterPreprocessingCallback) {
992
- this.executor.setParameterPreprocessingCallback(
993
- this.pendingParameterPreprocessingCallback
994
- );
995
- this.logger.info(
996
- "Parameter preprocessing callback re-applied to new executor",
997
- { hasCallback: true }
998
- );
999
- }
1000
- if (existingPendingForms.size > 0) {
1001
- this.logger.info(
1002
- `Restoring ${existingPendingForms.size} pending forms to new executor`
1003
- );
1004
- this.executor.restorePendingForms(existingPendingForms);
1005
- }
1006
- this.logger.info("FormAwareAgentExecutor initialization complete");
179
+ return !validation.isValid;
1007
180
  }
1008
181
  /**
1009
- * Set parameter preprocessing callback for tool parameter format conversion
182
+ * Checks if input has bypass flags that skip form generation
1010
183
  */
1011
- setParameterPreprocessingCallback(callback) {
1012
- this.pendingParameterPreprocessingCallback = callback;
1013
- if (this.executor) {
1014
- this.executor.setParameterPreprocessingCallback(callback);
1015
- this.logger.info("Parameter preprocessing callback configured", {
1016
- hasCallback: !!callback
1017
- });
1018
- } else {
1019
- this.logger.warn(
1020
- "Cannot set parameter preprocessing callback: executor not initialized"
1021
- );
1022
- }
1023
- }
1024
- handleError(error) {
1025
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
1026
- this.logger.error("Chat error:", error);
1027
- let tokenUsage;
1028
- let cost;
1029
- if (this.tokenTracker) {
1030
- tokenUsage = this.tokenTracker.getLatestTokenUsage();
1031
- if (tokenUsage) {
1032
- cost = calculateTokenCostSync(tokenUsage);
1033
- }
1034
- }
1035
- let userFriendlyMessage = errorMessage;
1036
- let userFriendlyOutput = errorMessage;
1037
- if (errorMessage.includes("429")) {
1038
- if (errorMessage.includes("quota")) {
1039
- userFriendlyMessage = "API quota exceeded. Please check your OpenAI billing and usage limits.";
1040
- userFriendlyOutput = "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.";
1041
- } else {
1042
- userFriendlyMessage = ERROR_MESSAGES.TOO_MANY_REQUESTS;
1043
- userFriendlyOutput = ERROR_MESSAGES.RATE_LIMITED;
1044
- }
1045
- } else if (errorMessage.includes("401") || errorMessage.includes("unauthorized")) {
1046
- userFriendlyMessage = "API authentication failed. Please check your API key configuration.";
1047
- userFriendlyOutput = "There's an issue with the API authentication. Please check your OpenAI API key configuration in settings.";
1048
- } else if (errorMessage.includes("timeout")) {
1049
- userFriendlyMessage = "Request timed out. Please try again.";
1050
- userFriendlyOutput = "The request took too long to process. Please try again.";
1051
- } else if (errorMessage.includes("network") || errorMessage.includes("fetch")) {
1052
- userFriendlyMessage = "Network error. Please check your internet connection and try again.";
1053
- userFriendlyOutput = "There was a network error. Please check your internet connection and try again.";
1054
- } else if (errorMessage.includes("400")) {
1055
- userFriendlyMessage = errorMessage;
1056
- userFriendlyOutput = errorMessage;
1057
- }
1058
- const errorResponse = {
1059
- output: userFriendlyOutput,
1060
- message: userFriendlyMessage,
1061
- error: errorMessage,
1062
- notes: []
1063
- };
1064
- if (tokenUsage) {
1065
- errorResponse.tokenUsage = tokenUsage;
1066
- }
1067
- if (cost) {
1068
- errorResponse.cost = cost;
1069
- }
1070
- return errorResponse;
1071
- }
1072
- async initializeMCP() {
1073
- this.mcpManager = new MCPClientManager(this.logger);
1074
- for (const serverConfig of this.config.mcp.servers) {
1075
- if (serverConfig.autoConnect === false) {
1076
- this.logger.info(
1077
- `Skipping MCP server ${serverConfig.name} (autoConnect=false)`
1078
- );
1079
- continue;
1080
- }
1081
- const status = await this.mcpManager.connectServer(serverConfig);
1082
- if (status.connected) {
1083
- this.logger.info(
1084
- `Connected to MCP server ${status.serverName} with ${status.tools.length} tools`
1085
- );
1086
- for (const mcpTool of status.tools) {
1087
- const langchainTool = convertMCPToolToLangChain(
1088
- mcpTool,
1089
- this.mcpManager,
1090
- serverConfig
1091
- );
1092
- this.toolRegistry.registerTool(langchainTool, {
1093
- metadata: {
1094
- category: "mcp",
1095
- version: "1.0.0",
1096
- dependencies: [serverConfig.name]
1097
- }
1098
- });
1099
- }
1100
- this.tools = this.toolRegistry.getAllTools();
1101
- } else {
1102
- this.logger.error(
1103
- `Failed to connect to MCP server ${status.serverName}: ${status.error}`
1104
- );
1105
- }
1106
- }
184
+ hasFormBypassFlags(input) {
185
+ return input.__fromForm === true || input.renderForm === false;
1107
186
  }
1108
187
  /**
1109
- * Connect to MCP servers asynchronously after agent boot with background timeout pattern
188
+ * Override _call to intercept tool execution
1110
189
  */
1111
- async connectMCPServers() {
1112
- if (!this.config.mcp?.servers || this.config.mcp.servers.length === 0) {
1113
- return;
1114
- }
1115
- if (!this.mcpManager) {
1116
- this.mcpManager = new MCPClientManager(this.logger);
1117
- }
1118
- this.logger.info(
1119
- `Starting background MCP server connections for ${this.config.mcp.servers.length} servers...`
1120
- );
1121
- this.config.mcp.servers.forEach((serverConfig) => {
1122
- this.connectServerInBackground(serverConfig);
190
+ async _call(input, runManager) {
191
+ this.logger.info(`🚨🚨🚨 FormValidatingToolWrapper._call INTERCEPTING ${this.name} 🚨🚨🚨`, {
192
+ input,
193
+ inputKeys: Object.keys(input),
194
+ schemaShape: this.getSchemaShape(),
195
+ stackTrace: new Error().stack?.split("\n").slice(0, 5)
1123
196
  });
1124
- this.logger.info("MCP server connections initiated in background");
1125
- }
1126
- /**
1127
- * Connect to a single MCP server in background with timeout
1128
- */
1129
- connectServerInBackground(serverConfig) {
1130
- const serverName = serverConfig.name;
1131
- setTimeout(async () => {
197
+ const inputRecord = input;
198
+ if (this.hasFormBypassFlags(inputRecord)) {
199
+ this.logger.info("Bypassing form generation and executing original tool due to submission flags");
200
+ return this.executeOriginal(inputRecord, runManager);
201
+ }
202
+ const shouldGenerate = this.shouldGenerateForm(input);
203
+ this.logger.info(`FormValidatingToolWrapper decision for ${this.name}:`, {
204
+ shouldGenerateForm: shouldGenerate,
205
+ toolName: this.name,
206
+ originalToolName: this.originalTool.name
207
+ });
208
+ if (shouldGenerate) {
209
+ this.logger.info(`Generating form for incomplete input in ${this.name}`);
1132
210
  try {
1133
- this.logger.info(`Background connecting to MCP server: ${serverName}`);
1134
- const status = await this.mcpManager.connectServer(serverConfig);
1135
- this.mcpConnectionStatus.set(serverName, status);
1136
- if (status.connected) {
1137
- this.logger.info(
1138
- `Successfully connected to MCP server ${status.serverName} with ${status.tools.length} tools`
1139
- );
1140
- for (const mcpTool of status.tools) {
1141
- const langchainTool = convertMCPToolToLangChain(
1142
- mcpTool,
1143
- this.mcpManager,
1144
- serverConfig
1145
- );
1146
- this.toolRegistry.registerTool(langchainTool, {
1147
- metadata: {
1148
- category: "mcp",
1149
- version: "1.0.0",
1150
- dependencies: [serverConfig.name]
1151
- }
1152
- });
1153
- }
1154
- this.tools = this.toolRegistry.getAllTools();
1155
- if (this.initialized && this.executor) {
1156
- this.logger.info(
1157
- `Recreating executor with ${this.tools.length} total tools`
1158
- );
1159
- await this.createExecutor();
1160
- }
1161
- } else {
1162
- this.logger.error(
1163
- `Failed to connect to MCP server ${status.serverName}: ${status.error}`
1164
- );
1165
- }
1166
- } catch (error) {
1167
- this.logger.error(
1168
- `Background connection failed for MCP server ${serverName}:`,
1169
- error
1170
- );
1171
- this.mcpConnectionStatus.set(serverName, {
1172
- connected: false,
1173
- serverName,
1174
- tools: [],
1175
- error: error instanceof Error ? error.message : "Connection failed"
211
+ const isCustom = isFormValidatable(this.originalTool);
212
+ const schemaToUse = isCustom ? this.getFormSchema() : this.schema;
213
+ const missingFields = this.calculateMissingFields(
214
+ input,
215
+ isCustom
216
+ );
217
+ const schemaFields = this.isZodObject(schemaToUse) ? Object.keys(schemaToUse.shape) : [];
218
+ this.logger.info(`Using ${isCustom ? "CUSTOM" : "DEFAULT"} schema for form generation`, {
219
+ toolName: this.originalTool.name,
220
+ schemaType: schemaToUse.constructor?.name,
221
+ schemaFields,
222
+ isCustomSchema: isCustom
1176
223
  });
224
+ const formMessage = await this.createFormMessage(
225
+ schemaToUse,
226
+ input,
227
+ missingFields
228
+ );
229
+ const result = {
230
+ requiresForm: true,
231
+ formMessage,
232
+ message: `Please complete the form to provide the required information for ${this.name}.`
233
+ };
234
+ this.logger.info(`FormValidatingToolWrapper returning form result for ${this.name}`);
235
+ return JSON.stringify(result);
236
+ } catch (error) {
237
+ this.logger.error("Failed to generate form:", error);
1177
238
  }
1178
- }, 1e3);
1179
- }
1180
- /**
1181
- * Detects and processes HashLink blocks from tool responses
1182
- * @param parsedResponse - The parsed JSON response from a tool
1183
- * @returns Metadata object containing hashLinkBlock if detected
1184
- */
1185
- processHashLinkBlocks(parsedResponse) {
1186
- try {
1187
- const responseRecord = parsedResponse;
1188
- if (parsedResponse && typeof parsedResponse === "object" && responseRecord.hashLinkBlock && typeof responseRecord.hashLinkBlock === "object") {
1189
- const block = responseRecord.hashLinkBlock;
1190
- if (block.blockId && block.hashLink && block.template && block.attributes && typeof block.blockId === "string" && typeof block.hashLink === "string" && typeof block.template === "string" && typeof block.attributes === "object") {
1191
- this.logger.info("HashLink block detected:", {
1192
- blockId: block.blockId,
1193
- hashLink: block.hashLink,
1194
- template: block.template,
1195
- attributeKeys: Object.keys(block.attributes)
1196
- });
1197
- return {
1198
- hashLinkBlock: {
1199
- blockId: block.blockId,
1200
- hashLink: block.hashLink,
1201
- template: block.template,
1202
- attributes: block.attributes
1203
- }
1204
- };
1205
- } else {
1206
- this.logger.warn("Invalid HashLink block structure detected:", block);
1207
- }
1208
- }
1209
- } catch (error) {
1210
- this.logger.error("Error processing HashLink blocks:", error);
1211
- }
1212
- return {};
1213
- }
1214
- /**
1215
- * Check if a string is valid JSON
1216
- */
1217
- isJSON(str) {
1218
- if (typeof str !== "string") return false;
1219
- const trimmed = str.trim();
1220
- if (!trimmed) return false;
1221
- if (!(trimmed.startsWith("{") && trimmed.endsWith("}")) && !(trimmed.startsWith("[") && trimmed.endsWith("]"))) {
1222
- return false;
1223
- }
1224
- try {
1225
- JSON.parse(trimmed);
1226
- return true;
1227
- } catch {
1228
- return false;
1229
239
  }
240
+ this.logger.info(`FormValidatingToolWrapper passing through to original tool ${this.name}`);
241
+ return this.executeOriginal(input, runManager);
1230
242
  }
1231
243
  }
244
+ function wrapToolWithFormValidation(tool, formGenerator, config = {}) {
245
+ return new FormValidatingToolWrapper(tool, formGenerator, config);
246
+ }
1232
247
  export {
1233
- LangChainAgent
248
+ FormValidatingToolWrapper,
249
+ wrapToolWithFormValidation
1234
250
  };
1235
251
  //# sourceMappingURL=index33.js.map