@hashgraphonline/conversational-agent 0.1.217 → 0.1.218

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 (286) hide show
  1. package/cli/readme.md +181 -0
  2. package/dist/cjs/constants/entity-references.d.ts +18 -0
  3. package/dist/cjs/constants/form-priorities.d.ts +24 -0
  4. package/dist/cjs/constants/index.d.ts +4 -0
  5. package/dist/cjs/constants/messages.d.ts +19 -0
  6. package/dist/cjs/constants/test-constants.d.ts +42 -0
  7. package/dist/cjs/conversational-agent.d.ts +3 -8
  8. package/dist/cjs/core/{ToolRegistry.d.ts → tool-registry.d.ts} +10 -7
  9. package/dist/{types/execution/ExecutionPipeline.d.ts → cjs/execution/execution-pipeline.d.ts} +3 -3
  10. package/dist/cjs/forms/field-guidance-registry.d.ts +108 -0
  11. package/dist/cjs/forms/form-generator.d.ts +2 -7
  12. package/dist/cjs/forms/index.d.ts +3 -0
  13. package/dist/cjs/forms/types.d.ts +9 -1
  14. package/dist/cjs/index.cjs +1 -1
  15. package/dist/cjs/index.cjs.map +1 -1
  16. package/dist/cjs/index.d.ts +7 -12
  17. package/dist/cjs/langchain/external-tool-wrapper.d.ts +101 -0
  18. package/dist/{types/langchain/FormAwareAgentExecutor.d.ts → cjs/langchain/form-aware-agent-executor.d.ts} +19 -12
  19. package/dist/cjs/langchain/index.d.ts +2 -0
  20. package/dist/{types → cjs/langchain}/langchain-agent.d.ts +15 -7
  21. package/dist/cjs/mcp/adapters/index.d.ts +1 -0
  22. package/dist/cjs/mcp/adapters/langchain.d.ts +1 -1
  23. package/dist/{types/mcp/ContentProcessor.d.ts → cjs/mcp/content-processor.d.ts} +1 -1
  24. package/dist/cjs/mcp/index.d.ts +5 -0
  25. package/dist/{types/mcp/MCPClientManager.d.ts → cjs/mcp/mcp-client-manager.d.ts} +1 -1
  26. package/dist/cjs/memory/{ContentStorage.d.ts → content-storage.d.ts} +4 -4
  27. package/dist/cjs/memory/index.d.ts +5 -7
  28. package/dist/{types/memory/MemoryWindow.d.ts → cjs/memory/memory-window.d.ts} +1 -1
  29. package/dist/{types/memory/SmartMemoryManager.d.ts → cjs/memory/smart-memory-manager.d.ts} +1 -1
  30. package/dist/cjs/services/{ContentStoreManager.d.ts → content-store-manager.d.ts} +6 -6
  31. package/dist/cjs/services/context/resolution-context.d.ts +49 -0
  32. package/dist/cjs/services/entity-resolver.d.ts +58 -0
  33. package/dist/cjs/services/formatters/converters/index.d.ts +2 -0
  34. package/dist/cjs/services/formatters/converters/string-normalization-converter.d.ts +13 -0
  35. package/dist/cjs/services/formatters/converters/topic-id-to-hrl-converter.d.ts +17 -0
  36. package/dist/cjs/services/formatters/format-converter-registry.d.ts +66 -0
  37. package/dist/cjs/services/formatters/index.d.ts +3 -0
  38. package/dist/cjs/services/formatters/types.d.ts +29 -0
  39. package/dist/cjs/services/index.d.ts +3 -0
  40. package/dist/cjs/services/resolution/resolution-pipeline.d.ts +44 -0
  41. package/dist/cjs/tools/index.d.ts +1 -0
  42. package/dist/cjs/utils/index.d.ts +1 -0
  43. package/dist/esm/index.js +40 -16
  44. package/dist/esm/index.js.map +1 -1
  45. package/dist/esm/index10.js +669 -13
  46. package/dist/esm/index10.js.map +1 -1
  47. package/dist/esm/index11.js +310 -95
  48. package/dist/esm/index11.js.map +1 -1
  49. package/dist/esm/index12.js +130 -95
  50. package/dist/esm/index12.js.map +1 -1
  51. package/dist/esm/index13.js +262 -153
  52. package/dist/esm/index13.js.map +1 -1
  53. package/dist/esm/index14.js +100 -664
  54. package/dist/esm/index14.js.map +1 -1
  55. package/dist/esm/index15.js +135 -408
  56. package/dist/esm/index15.js.map +1 -1
  57. package/dist/esm/index16.js +240 -122
  58. package/dist/esm/index16.js.map +1 -1
  59. package/dist/esm/index17.js +147 -135
  60. package/dist/esm/index17.js.map +1 -1
  61. package/dist/esm/index18.js +376 -533
  62. package/dist/esm/index18.js.map +1 -1
  63. package/dist/esm/index19.js +87 -214
  64. package/dist/esm/index19.js.map +1 -1
  65. package/dist/esm/index2.js +21 -4
  66. package/dist/esm/index2.js.map +1 -1
  67. package/dist/esm/index20.js +158 -92
  68. package/dist/esm/index20.js.map +1 -1
  69. package/dist/esm/index21.js +717 -44
  70. package/dist/esm/index21.js.map +1 -1
  71. package/dist/esm/index22.js +58 -96
  72. package/dist/esm/index22.js.map +1 -1
  73. package/dist/esm/index23.js +324 -34
  74. package/dist/esm/index23.js.map +1 -1
  75. package/dist/esm/index24.js +125 -712
  76. package/dist/esm/index24.js.map +1 -1
  77. package/dist/esm/index25.js +113 -133
  78. package/dist/esm/index25.js.map +1 -1
  79. package/dist/esm/index26.js +18 -152
  80. package/dist/esm/index26.js.map +1 -1
  81. package/dist/esm/index27.js +14 -210
  82. package/dist/esm/index27.js.map +1 -1
  83. package/dist/esm/index28.js +70 -173
  84. package/dist/esm/index28.js.map +1 -1
  85. package/dist/esm/index29.js +811 -224
  86. package/dist/esm/index29.js.map +1 -1
  87. package/dist/esm/index30.js +1245 -122
  88. package/dist/esm/index30.js.map +1 -1
  89. package/dist/esm/index31.js +126 -56
  90. package/dist/esm/index31.js.map +1 -1
  91. package/dist/esm/index32.js +111 -24
  92. package/dist/esm/index32.js.map +1 -1
  93. package/dist/esm/index33.js +41 -87
  94. package/dist/esm/index33.js.map +1 -1
  95. package/dist/esm/index34.js +88 -227
  96. package/dist/esm/index34.js.map +1 -1
  97. package/dist/esm/index35.js +24 -0
  98. package/dist/esm/index35.js.map +1 -0
  99. package/dist/esm/index36.js +15 -0
  100. package/dist/esm/index36.js.map +1 -0
  101. package/dist/esm/index37.js +10 -0
  102. package/dist/esm/index37.js.map +1 -0
  103. package/dist/esm/index38.js +8 -0
  104. package/dist/esm/index38.js.map +1 -0
  105. package/dist/esm/index39.js +227 -0
  106. package/dist/esm/index39.js.map +1 -0
  107. package/dist/esm/index40.js +187 -0
  108. package/dist/esm/index40.js.map +1 -0
  109. package/dist/esm/index41.js +30 -0
  110. package/dist/esm/index41.js.map +1 -0
  111. package/dist/esm/index42.js +95 -0
  112. package/dist/esm/index42.js.map +1 -0
  113. package/dist/esm/index5.js +2 -2
  114. package/dist/esm/index5.js.map +1 -1
  115. package/dist/esm/index6.js +44 -67
  116. package/dist/esm/index6.js.map +1 -1
  117. package/dist/esm/index7.js +9 -0
  118. package/dist/esm/index7.js.map +1 -1
  119. package/dist/esm/index8.js +13 -1095
  120. package/dist/esm/index8.js.map +1 -1
  121. package/dist/esm/index9.js +17 -13
  122. package/dist/esm/index9.js.map +1 -1
  123. package/dist/types/constants/entity-references.d.ts +18 -0
  124. package/dist/types/constants/form-priorities.d.ts +24 -0
  125. package/dist/types/constants/index.d.ts +4 -0
  126. package/dist/types/constants/messages.d.ts +19 -0
  127. package/dist/types/constants/test-constants.d.ts +42 -0
  128. package/dist/types/conversational-agent.d.ts +3 -8
  129. package/dist/types/core/{ToolRegistry.d.ts → tool-registry.d.ts} +10 -7
  130. package/dist/{cjs/execution/ExecutionPipeline.d.ts → types/execution/execution-pipeline.d.ts} +3 -3
  131. package/dist/types/forms/field-guidance-registry.d.ts +108 -0
  132. package/dist/types/forms/form-generator.d.ts +2 -7
  133. package/dist/types/forms/index.d.ts +3 -0
  134. package/dist/types/forms/types.d.ts +9 -1
  135. package/dist/types/index.d.ts +7 -12
  136. package/dist/types/langchain/external-tool-wrapper.d.ts +101 -0
  137. package/dist/{cjs/langchain/FormAwareAgentExecutor.d.ts → types/langchain/form-aware-agent-executor.d.ts} +19 -12
  138. package/dist/types/langchain/index.d.ts +2 -0
  139. package/dist/{cjs → types/langchain}/langchain-agent.d.ts +15 -7
  140. package/dist/types/mcp/adapters/index.d.ts +1 -0
  141. package/dist/types/mcp/adapters/langchain.d.ts +1 -1
  142. package/dist/{cjs/mcp/ContentProcessor.d.ts → types/mcp/content-processor.d.ts} +1 -1
  143. package/dist/types/mcp/index.d.ts +5 -0
  144. package/dist/{cjs/mcp/MCPClientManager.d.ts → types/mcp/mcp-client-manager.d.ts} +1 -1
  145. package/dist/types/memory/{ContentStorage.d.ts → content-storage.d.ts} +4 -4
  146. package/dist/types/memory/index.d.ts +5 -7
  147. package/dist/{cjs/memory/MemoryWindow.d.ts → types/memory/memory-window.d.ts} +1 -1
  148. package/dist/{cjs/memory/SmartMemoryManager.d.ts → types/memory/smart-memory-manager.d.ts} +1 -1
  149. package/dist/types/services/{ContentStoreManager.d.ts → content-store-manager.d.ts} +6 -6
  150. package/dist/types/services/context/resolution-context.d.ts +49 -0
  151. package/dist/types/services/entity-resolver.d.ts +58 -0
  152. package/dist/types/services/formatters/converters/index.d.ts +2 -0
  153. package/dist/types/services/formatters/converters/string-normalization-converter.d.ts +13 -0
  154. package/dist/types/services/formatters/converters/topic-id-to-hrl-converter.d.ts +17 -0
  155. package/dist/types/services/formatters/format-converter-registry.d.ts +66 -0
  156. package/dist/types/services/formatters/index.d.ts +3 -0
  157. package/dist/types/services/formatters/types.d.ts +29 -0
  158. package/dist/types/services/index.d.ts +3 -0
  159. package/dist/types/services/resolution/resolution-pipeline.d.ts +44 -0
  160. package/dist/types/tools/index.d.ts +1 -0
  161. package/dist/types/utils/index.d.ts +1 -0
  162. package/package.json +30 -27
  163. package/src/agent-factory.ts +1 -1
  164. package/src/base-agent.ts +9 -0
  165. package/src/config/system-message.ts +2 -15
  166. package/src/constants/entity-references.ts +23 -0
  167. package/src/constants/form-priorities.ts +25 -0
  168. package/src/constants/index.ts +4 -0
  169. package/src/constants/messages.ts +20 -0
  170. package/src/constants/test-constants.ts +49 -0
  171. package/src/conversational-agent.ts +42 -69
  172. package/src/core/{ToolRegistry.ts → tool-registry.ts} +70 -44
  173. package/src/examples/external-tool-wrapper-example.ts +56 -0
  174. package/src/execution/{ExecutionPipeline.ts → execution-pipeline.ts} +3 -3
  175. package/src/forms/field-guidance-registry.ts +415 -0
  176. package/src/forms/field-type-registry.ts +49 -48
  177. package/src/forms/{FormEngine.ts → form-engine.ts} +66 -43
  178. package/src/forms/form-generator.ts +91 -17
  179. package/src/forms/index.ts +4 -1
  180. package/src/forms/types.ts +9 -1
  181. package/src/index.ts +7 -37
  182. package/src/langchain/external-tool-wrapper.ts +90 -0
  183. package/src/langchain/{FormAwareAgentExecutor.ts → form-aware-agent-executor.ts} +579 -351
  184. package/src/langchain/index.ts +2 -0
  185. package/src/{langchain-agent.ts → langchain/langchain-agent.ts} +389 -113
  186. package/src/mcp/adapters/index.ts +1 -0
  187. package/src/mcp/adapters/langchain.ts +27 -18
  188. package/src/mcp/{ContentProcessor.ts → content-processor.ts} +71 -47
  189. package/src/mcp/index.ts +5 -0
  190. package/src/mcp/{MCPClientManager.ts → mcp-client-manager.ts} +2 -2
  191. package/src/memory/{ContentStorage.ts → content-storage.ts} +263 -167
  192. package/src/memory/index.ts +5 -8
  193. package/src/memory/{MemoryWindow.ts → memory-window.ts} +47 -24
  194. package/src/memory/{SmartMemoryManager.ts → smart-memory-manager.ts} +49 -22
  195. package/src/plugins/hbar/HbarPlugin.ts +1 -1
  196. package/src/plugins/hcs-10/HCS10Plugin.ts +46 -28
  197. package/src/scripts/test-external-tool-wrapper.ts +6 -6
  198. package/src/scripts/test-inscribe-form-generation.ts +22 -21
  199. package/src/scripts/test-inscribe-wrapper-verification.ts +5 -4
  200. package/src/services/{ContentStoreManager.ts → content-store-manager.ts} +75 -33
  201. package/src/services/context/resolution-context.ts +80 -0
  202. package/src/services/entity-resolver.ts +425 -0
  203. package/src/services/formatters/converters/index.ts +2 -0
  204. package/src/services/formatters/converters/string-normalization-converter.ts +106 -0
  205. package/src/services/formatters/converters/topic-id-to-hrl-converter.ts +25 -0
  206. package/src/services/formatters/format-converter-registry.ts +229 -0
  207. package/src/services/formatters/index.ts +3 -0
  208. package/src/services/formatters/types.ts +31 -0
  209. package/src/services/index.ts +3 -0
  210. package/src/services/resolution/resolution-pipeline.ts +106 -0
  211. package/src/tools/index.ts +1 -0
  212. package/src/types/content-reference.ts +87 -60
  213. package/src/utils/index.ts +1 -0
  214. package/cli/dist/CLIApp.d.ts +0 -9
  215. package/cli/dist/CLIApp.js +0 -127
  216. package/cli/dist/LocalConversationalAgent.d.ts +0 -37
  217. package/cli/dist/LocalConversationalAgent.js +0 -58
  218. package/cli/dist/app.d.ts +0 -16
  219. package/cli/dist/app.js +0 -13
  220. package/cli/dist/cli.d.ts +0 -2
  221. package/cli/dist/cli.js +0 -51
  222. package/cli/dist/components/AppContainer.d.ts +0 -16
  223. package/cli/dist/components/AppContainer.js +0 -24
  224. package/cli/dist/components/AppScreens.d.ts +0 -2
  225. package/cli/dist/components/AppScreens.js +0 -259
  226. package/cli/dist/components/ChatScreen.d.ts +0 -15
  227. package/cli/dist/components/ChatScreen.js +0 -39
  228. package/cli/dist/components/DebugLoadingScreen.d.ts +0 -5
  229. package/cli/dist/components/DebugLoadingScreen.js +0 -31
  230. package/cli/dist/components/LoadingScreen.d.ts +0 -2
  231. package/cli/dist/components/LoadingScreen.js +0 -16
  232. package/cli/dist/components/LoadingScreenDebug.d.ts +0 -5
  233. package/cli/dist/components/LoadingScreenDebug.js +0 -27
  234. package/cli/dist/components/MCPConfigScreen.d.ts +0 -28
  235. package/cli/dist/components/MCPConfigScreen.js +0 -168
  236. package/cli/dist/components/ScreenRouter.d.ts +0 -12
  237. package/cli/dist/components/ScreenRouter.js +0 -22
  238. package/cli/dist/components/SetupScreen.d.ts +0 -15
  239. package/cli/dist/components/SetupScreen.js +0 -65
  240. package/cli/dist/components/SingleLoadingScreen.d.ts +0 -5
  241. package/cli/dist/components/SingleLoadingScreen.js +0 -27
  242. package/cli/dist/components/StatusBadge.d.ts +0 -7
  243. package/cli/dist/components/StatusBadge.js +0 -28
  244. package/cli/dist/components/TerminalWindow.d.ts +0 -8
  245. package/cli/dist/components/TerminalWindow.js +0 -24
  246. package/cli/dist/components/WelcomeScreen.d.ts +0 -11
  247. package/cli/dist/components/WelcomeScreen.js +0 -47
  248. package/cli/dist/context/AppContext.d.ts +0 -68
  249. package/cli/dist/context/AppContext.js +0 -363
  250. package/cli/dist/hooks/useInitializeAgent.d.ts +0 -19
  251. package/cli/dist/hooks/useInitializeAgent.js +0 -28
  252. package/cli/dist/hooks/useStableState.d.ts +0 -38
  253. package/cli/dist/hooks/useStableState.js +0 -68
  254. package/cli/dist/managers/AgentManager.d.ts +0 -57
  255. package/cli/dist/managers/AgentManager.js +0 -119
  256. package/cli/dist/managers/ConfigManager.d.ts +0 -53
  257. package/cli/dist/managers/ConfigManager.js +0 -173
  258. package/cli/dist/types.d.ts +0 -31
  259. package/cli/dist/types.js +0 -19
  260. package/dist/cjs/context/ReferenceContextManager.d.ts +0 -84
  261. package/dist/cjs/context/ReferenceResponseProcessor.d.ts +0 -76
  262. package/dist/cjs/langchain/FormValidatingToolWrapper.d.ts +0 -81
  263. package/dist/cjs/services/EntityResolver.d.ts +0 -26
  264. package/dist/types/context/ReferenceContextManager.d.ts +0 -84
  265. package/dist/types/context/ReferenceResponseProcessor.d.ts +0 -76
  266. package/dist/types/langchain/FormValidatingToolWrapper.d.ts +0 -81
  267. package/dist/types/services/EntityResolver.d.ts +0 -26
  268. package/src/context/ReferenceContextManager.ts +0 -350
  269. package/src/context/ReferenceResponseProcessor.ts +0 -295
  270. package/src/langchain/FormValidatingToolWrapper.ts +0 -355
  271. package/src/scripts/test-hedera-kit-wrapper.ts +0 -265
  272. package/src/services/EntityResolver.ts +0 -128
  273. /package/dist/cjs/forms/{FormEngine.d.ts → form-engine.d.ts} +0 -0
  274. /package/dist/cjs/memory/{ReferenceIdGenerator.d.ts → reference-id-generator.d.ts} +0 -0
  275. /package/dist/cjs/memory/{TokenCounter.d.ts → token-counter.d.ts} +0 -0
  276. /package/dist/cjs/tools/{EntityResolverTool.d.ts → entity-resolver-tool.d.ts} +0 -0
  277. /package/dist/cjs/utils/{ResponseFormatter.d.ts → response-formatter.d.ts} +0 -0
  278. /package/dist/types/forms/{FormEngine.d.ts → form-engine.d.ts} +0 -0
  279. /package/dist/types/memory/{ReferenceIdGenerator.d.ts → reference-id-generator.d.ts} +0 -0
  280. /package/dist/types/memory/{TokenCounter.d.ts → token-counter.d.ts} +0 -0
  281. /package/dist/types/tools/{EntityResolverTool.d.ts → entity-resolver-tool.d.ts} +0 -0
  282. /package/dist/types/utils/{ResponseFormatter.d.ts → response-formatter.d.ts} +0 -0
  283. /package/src/memory/{ReferenceIdGenerator.ts → reference-id-generator.ts} +0 -0
  284. /package/src/memory/{TokenCounter.ts → token-counter.ts} +0 -0
  285. /package/src/tools/{EntityResolverTool.ts → entity-resolver-tool.ts} +0 -0
  286. /package/src/utils/{ResponseFormatter.ts → response-formatter.ts} +0 -0
@@ -1,159 +1,1282 @@
1
- class FieldTypeRegistry {
1
+ import { createOpenAIToolsAgent } from "langchain/agents";
2
+ import { FormAwareAgentExecutor } from "./index29.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 "./index32.js";
11
+ import { ERROR_MESSAGES } from "./index38.js";
12
+ import "./index36.js";
13
+ import { SystemMessage, AIMessage, HumanMessage } from "@langchain/core/messages";
14
+ import { ToolRegistry } from "./index39.js";
15
+ import { ExecutionPipeline } from "./index40.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 {
2
29
  constructor() {
3
- this.patterns = /* @__PURE__ */ new Map();
4
- this.initializeDefaultPatterns();
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
+ }
5
71
  }
6
72
  /**
7
- * Get singleton instance
73
+ * Get inscription tool by capability instead of hardcoded name
8
74
  */
9
- static getInstance() {
10
- if (!FieldTypeRegistry.instance) {
11
- FieldTypeRegistry.instance = new FieldTypeRegistry();
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
+ }
12
87
  }
13
- return FieldTypeRegistry.instance;
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;
95
+ }
96
+ }
97
+ return null;
14
98
  }
15
99
  /**
16
- * Initialize default field type patterns
100
+ * Execute a tool directly with parameters, optionally using ExecutionPipeline
17
101
  */
18
- initializeDefaultPatterns() {
19
- this.register("numeric-supply-exact", {
20
- pattern: ["maxSupply", "minSupply", "totalSupply"],
21
- type: "number",
22
- priority: 15
23
- });
24
- this.register("numeric-supply", {
25
- pattern: /supply$/i,
26
- type: "number",
27
- priority: 10
28
- });
29
- this.register("numeric-amounts", {
30
- pattern: /(?:amount|quantity|count|total|sum|value)$/i,
31
- type: "number",
32
- priority: 8
33
- });
34
- this.register("numeric-time", {
35
- pattern: /(?:period|duration|time|timeout|delay|interval)$/i,
36
- type: "number",
37
- priority: 8
38
- });
39
- this.register("numeric-limits", {
40
- pattern: /(?:limit|max|min|threshold|size|length)$/i,
41
- type: "number",
42
- priority: 7
43
- });
44
- this.register("currency", {
45
- pattern: /(?:price|cost|fee|payment|balance|amount)$/i,
46
- type: "currency",
47
- priority: 9
48
- });
49
- this.register("percentage", {
50
- pattern: /(?:percent|percentage|rate|ratio)$/i,
51
- type: "percentage",
52
- priority: 9
53
- });
54
- this.register("boolean-freeze", {
55
- pattern: ["freezeDefault", "freeze"],
56
- type: "checkbox",
57
- priority: 10
58
- });
59
- this.register("boolean-flags", {
60
- pattern: /(?:is|has|can|should|enable|disable|active|default|allow)(?:[A-Z]|$)/,
61
- type: "checkbox",
62
- priority: 8
63
- });
64
- this.register("textarea", {
65
- pattern: /(?:memo|description|notes|comment|message|content|body|text)$/i,
66
- type: "textarea",
67
- priority: 8
68
- });
69
- this.register("array-fees", {
70
- pattern: ["customFees", "fees"],
71
- type: "array",
72
- priority: 10
73
- });
74
- this.register("array-general", {
75
- pattern: /(?:list|items|array|collection)$/i,
76
- type: "array",
77
- priority: 7
78
- });
79
- this.register("object-options", {
80
- pattern: ["metaOptions", "options"],
81
- type: "object",
82
- priority: 10
83
- });
84
- this.register("object-config", {
85
- pattern: /(?:config|settings|configuration|metadata|data|info)$/i,
86
- type: "object",
87
- priority: 7
88
- });
89
- this.register("select-type", {
90
- pattern: /(?:type|kind|category|status|state|mode)$/i,
91
- type: "select",
92
- priority: 7
93
- });
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}`);
121
+ }
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);
94
166
  }
95
167
  /**
96
- * Register a field type pattern
168
+ * Create a standard ChatResponse from tool output
97
169
  */
98
- register(key, pattern) {
99
- this.patterns.set(key, pattern);
170
+ createToolResponse(toolOutput) {
171
+ return {
172
+ output: toolOutput,
173
+ message: toolOutput,
174
+ notes: []
175
+ };
100
176
  }
101
177
  /**
102
- * Unregister a field type pattern
178
+ * Handle TOOL_EXECUTION format messages
103
179
  */
104
- unregister(key) {
105
- return this.patterns.delete(key);
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 {
192
+ }
193
+ if (!isToolExecution || !toolExecutionData?.formId) {
194
+ return null;
195
+ }
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;
106
220
  }
107
221
  /**
108
- * Detect field type based on field name
222
+ * Handle direct tool execution commands
109
223
  */
110
- detectType(fieldName) {
111
- const matches = [];
112
- for (const pattern of this.patterns.values()) {
113
- let isMatch = false;
114
- if (Array.isArray(pattern.pattern)) {
115
- isMatch = pattern.pattern.some(
116
- (p) => fieldName === p || fieldName.toLowerCase() === p.toLowerCase()
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;
250
+ }
251
+ /**
252
+ * Handle JSON format tool calls and form submissions
253
+ */
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
117
271
  );
118
- } else if (pattern.pattern instanceof RegExp) {
119
- isMatch = pattern.pattern.test(fieldName);
120
272
  }
121
- if (isMatch) {
122
- matches.push({
123
- type: pattern.type,
124
- priority: pattern.priority ?? 5
125
- });
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);
126
281
  }
282
+ } catch {
127
283
  }
128
- if (matches.length > 0) {
129
- matches.sort((a, b) => b.priority - a.priority);
130
- return matches[0].type;
284
+ return null;
285
+ }
286
+ /**
287
+ * Handle content-ref messages for inscription tools
288
+ */
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 {
131
334
  }
132
335
  return null;
133
336
  }
134
337
  /**
135
- * Get all registered patterns
338
+ * Process executor result and format response
136
339
  */
137
- getPatterns() {
138
- return new Map(this.patterns);
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 parsedSteps = result?.intermediateSteps?.[0]?.observation;
378
+ if (parsedSteps && typeof parsedSteps === "string" && this.isJSON(parsedSteps)) {
379
+ try {
380
+ const parsed = JSON.parse(parsedSteps);
381
+ if (ResponseFormatter.isInscriptionResponse(parsed)) {
382
+ const formattedMessage = ResponseFormatter.formatInscriptionResponse(parsed);
383
+ response.output = formattedMessage;
384
+ response.message = formattedMessage;
385
+ if (parsed.inscription) {
386
+ response.inscription = parsed.inscription;
387
+ }
388
+ if (parsed.metadata) {
389
+ response.metadata = {
390
+ ...response.metadata,
391
+ ...parsed.metadata
392
+ };
393
+ }
394
+ } else {
395
+ response = { ...response, ...parsed };
396
+ }
397
+ const blockMetadata = this.processHashLinkBlocks(parsed);
398
+ if (blockMetadata.hashLinkBlock) {
399
+ response.metadata = {
400
+ ...response.metadata,
401
+ ...blockMetadata
402
+ };
403
+ }
404
+ } catch (error) {
405
+ this.logger.error("Error parsing intermediate steps:", error);
406
+ }
407
+ }
408
+ if (!response.output || response.output.trim() === "") {
409
+ response.output = "Agent action complete.";
410
+ }
411
+ if (response.output) {
412
+ this.smartMemory.addMessage(new AIMessage(response.output));
413
+ }
414
+ if (this.tokenTracker) {
415
+ const tokenUsage = this.tokenTracker.getLatestTokenUsage();
416
+ if (tokenUsage) {
417
+ response.tokenUsage = tokenUsage;
418
+ response.cost = calculateTokenCostSync(tokenUsage);
419
+ }
420
+ }
421
+ const finalMemoryStats = this.smartMemory.getMemoryStats();
422
+ response.metadata = {
423
+ ...response.metadata,
424
+ memoryStats: {
425
+ activeMessages: finalMemoryStats.totalActiveMessages,
426
+ tokenUsage: finalMemoryStats.currentTokenCount,
427
+ maxTokens: finalMemoryStats.maxTokens,
428
+ usagePercentage: finalMemoryStats.usagePercentage
429
+ }
430
+ };
431
+ this.logger.info("LangChainAgent.chat returning response:", response);
432
+ return response;
139
433
  }
140
434
  /**
141
- * Clear all patterns
435
+ * Normalize context messages into LangChain message instances and load into memory
142
436
  */
143
- clear() {
144
- this.patterns.clear();
437
+ /**
438
+ * Loads context messages into memory, merging with existing messages
439
+ */
440
+ loadContextMessages(context) {
441
+ if (!this.smartMemory || !context?.messages || context.messages.length === 0) {
442
+ return;
443
+ }
444
+ const existingMessages = this.smartMemory.getMessages();
445
+ const existingContent = new Set(
446
+ existingMessages.map((m) => `${m.constructor.name}:${m.content}`)
447
+ );
448
+ for (const msg of context.messages) {
449
+ let messageClass;
450
+ let content;
451
+ if (msg instanceof HumanMessage || msg instanceof AIMessage || msg instanceof SystemMessage) {
452
+ messageClass = msg.constructor;
453
+ content = msg.content;
454
+ } else if (msg && typeof msg === "object" && "content" in msg && "type" in msg) {
455
+ content = String(msg.content);
456
+ const type = String(msg.type);
457
+ if (type === "human") messageClass = HumanMessage;
458
+ else if (type === "ai") messageClass = AIMessage;
459
+ else if (type === "system") messageClass = SystemMessage;
460
+ else continue;
461
+ } else {
462
+ continue;
463
+ }
464
+ const key = `${messageClass.name}:${content}`;
465
+ if (!existingContent.has(key)) {
466
+ this.smartMemory.addMessage(new messageClass(content));
467
+ existingContent.add(key);
468
+ }
469
+ }
470
+ }
471
+ async boot() {
472
+ this.logger.info("🚨🚨🚨 LANGCHAIN AGENT BOOT METHOD CALLED 🚨🚨🚨");
473
+ if (this.initialized) {
474
+ this.logger.warn("Agent already initialized");
475
+ return;
476
+ }
477
+ try {
478
+ this.agentKit = await this.createAgentKit();
479
+ await this.agentKit.initialize();
480
+ const modelName = this.config.ai?.modelName || process.env.OPENAI_MODEL_NAME || "gpt-4o-mini";
481
+ this.tokenTracker = new TokenUsageCallbackHandler(modelName);
482
+ this.toolRegistry = new ToolRegistry(this.logger);
483
+ const allTools = this.agentKit.getAggregatedLangChainTools();
484
+ this.logger.info("=== TOOL REGISTRATION START ===");
485
+ this.logger.info(
486
+ "All tools from agentKit:",
487
+ allTools.map((t) => t.name)
488
+ );
489
+ const filteredTools = this.filterTools(allTools);
490
+ this.logger.info(
491
+ "Filtered tools for registration:",
492
+ filteredTools.map((t) => t.name)
493
+ );
494
+ for (const tool of filteredTools) {
495
+ this.logger.info(`🔧 Registering tool: ${tool.name}`);
496
+ const options = {};
497
+ const name = tool.name.toLowerCase();
498
+ const desc = tool.description?.toLowerCase() || "";
499
+ if (tool.name === "hedera-hts-mint-nft") {
500
+ const originalCall = tool.call.bind(tool);
501
+ tool.call = async (args) => {
502
+ if (args.metaOptions && typeof args.metaOptions === "object") {
503
+ const metaOptions = args.metaOptions;
504
+ if (metaOptions.transactionMemo) {
505
+ console.warn(
506
+ "🚨 WORKAROUND: Stripping transactionMemo from hedera-hts-mint-nft to avoid bug",
507
+ { originalMemo: metaOptions.transactionMemo }
508
+ );
509
+ delete metaOptions.transactionMemo;
510
+ }
511
+ }
512
+ return originalCall(args);
513
+ };
514
+ }
515
+ if (name.includes("inscribe") || name.includes("hashinal") || desc.includes("inscribe") || desc.includes("hashinal")) {
516
+ options.forceWrapper = true;
517
+ options.metadata = {
518
+ category: "core",
519
+ version: "1.0.0",
520
+ dependencies: []
521
+ };
522
+ this.logger.info(`🎯 CRITICAL TOOL DEBUG - ${tool.name} schema:`, {
523
+ hasSchema: !!tool.schema,
524
+ schemaType: tool.schema?.constructor?.name,
525
+ hasRenderConfig: !!tool.schema?._renderConfig,
526
+ renderConfig: tool.schema?._renderConfig
527
+ });
528
+ }
529
+ this.toolRegistry.registerTool(tool, options);
530
+ }
531
+ this.tools = this.toolRegistry.getAllTools();
532
+ this.logger.info(`🚀 TOOLS REGISTERED: ${this.tools.length} tools`);
533
+ const stats = this.toolRegistry.getStatistics();
534
+ this.logger.info("📊 Tool Registry Statistics:", {
535
+ total: stats.totalTools,
536
+ wrapped: stats.wrappedTools,
537
+ unwrapped: stats.unwrappedTools,
538
+ categories: stats.categoryCounts,
539
+ priorities: stats.priorityCounts
540
+ });
541
+ const inscriptionTool = this.getInscriptionTool();
542
+ if (inscriptionTool) {
543
+ const entry = this.toolRegistry.getTool(inscriptionTool.name);
544
+ if (entry) {
545
+ this.logger.info(
546
+ `✅ Inscription tool registered: ${inscriptionTool.name}`
547
+ );
548
+ }
549
+ }
550
+ const toolNames = this.toolRegistry.getToolNames();
551
+ const uniqueNames = new Set(toolNames);
552
+ if (toolNames.length !== uniqueNames.size) {
553
+ this.logger.error("DUPLICATE TOOL NAMES DETECTED in registry!");
554
+ const duplicates = toolNames.filter(
555
+ (name, index) => toolNames.indexOf(name) !== index
556
+ );
557
+ throw new Error(
558
+ `Duplicate tool names detected: ${duplicates.join(", ")}`
559
+ );
560
+ }
561
+ if (this.config.mcp?.servers && this.config.mcp.servers.length > 0) {
562
+ if (this.config.mcp.autoConnect !== false) {
563
+ await this.initializeMCP();
564
+ } else {
565
+ this.logger.info(
566
+ "MCP servers configured but autoConnect=false, skipping synchronous connection"
567
+ );
568
+ this.mcpManager = new MCPClientManager(this.logger);
569
+ }
570
+ }
571
+ this.smartMemory = new SmartMemoryManager({
572
+ modelName,
573
+ maxTokens: 9e4,
574
+ reserveTokens: 1e4,
575
+ storageLimit: 1e3
576
+ });
577
+ this.logger.info("SmartMemoryManager initialized:", {
578
+ modelName,
579
+ toolsCount: this.tools.length,
580
+ maxTokens: 9e4,
581
+ reserveTokens: 1e4
582
+ });
583
+ this.formEngine = new FormEngine(this.logger);
584
+ this.executionPipeline = new ExecutionPipeline(
585
+ this.toolRegistry,
586
+ this.formEngine,
587
+ this.smartMemory,
588
+ this.logger
589
+ );
590
+ this.systemMessage = this.buildSystemPrompt();
591
+ this.smartMemory.setSystemPrompt(this.systemMessage);
592
+ await this.createExecutor();
593
+ this.initialized = true;
594
+ this.logger.info("LangChain Hedera agent initialized with ToolRegistry");
595
+ } catch (error) {
596
+ this.logger.error("Failed to initialize agent:", error);
597
+ throw error;
598
+ }
599
+ }
600
+ async chat(message, context) {
601
+ if (!this.initialized || !this.executor || !this.smartMemory) {
602
+ throw new Error("Agent not initialized. Call boot() first.");
603
+ }
604
+ try {
605
+ const toolExecutionResult = await this.handleToolExecution(
606
+ message,
607
+ context
608
+ );
609
+ if (toolExecutionResult) {
610
+ return toolExecutionResult;
611
+ }
612
+ const directToolResult = await this.handleDirectToolExecution(message);
613
+ if (directToolResult) {
614
+ return directToolResult;
615
+ }
616
+ const jsonToolResult = await this.handleJsonToolCalls(message, context);
617
+ if (jsonToolResult) {
618
+ return jsonToolResult;
619
+ }
620
+ const contentRefResult = await this.handleContentRefMessages(message);
621
+ if (contentRefResult) {
622
+ return contentRefResult;
623
+ }
624
+ this.logger.info("LangChainAgent.chat called with:", {
625
+ message,
626
+ contextLength: context?.messages?.length || 0
627
+ });
628
+ this.loadContextMessages(context);
629
+ this.smartMemory.addMessage(new HumanMessage(message));
630
+ const memoryStats = this.smartMemory.getMemoryStats();
631
+ this.logger.info("Memory stats before execution:", {
632
+ totalMessages: memoryStats.totalActiveMessages,
633
+ currentTokens: memoryStats.currentTokenCount,
634
+ maxTokens: memoryStats.maxTokens,
635
+ usagePercentage: memoryStats.usagePercentage,
636
+ toolsCount: this.tools.length
637
+ });
638
+ const currentMessages = this.smartMemory.getMessages();
639
+ this.logger.info("Current messages in memory:", {
640
+ count: currentMessages.length
641
+ });
642
+ try {
643
+ const instr = currentMessages.map((m) => String(m.content || "")).filter(
644
+ (c) => typeof c === "string" && (c.includes("[instruction:") || c.includes("[tool-next-steps:"))
645
+ );
646
+ if (instr.length > 0) {
647
+ this.logger.info("Instruction/next-steps messages in memory:", {
648
+ messages: instr
649
+ });
650
+ }
651
+ } catch {
652
+ }
653
+ const result = await this.executor.invoke({
654
+ input: message,
655
+ chat_history: currentMessages
656
+ });
657
+ this.logger.info("LangChainAgent executor result:", result);
658
+ return this.processExecutorResult(result);
659
+ } catch (error) {
660
+ this.logger.error("LangChainAgent.chat error:", error);
661
+ return this.handleError(error);
662
+ }
663
+ }
664
+ async shutdown() {
665
+ if (this.mcpManager) {
666
+ await this.mcpManager.disconnectAll();
667
+ }
668
+ if (this.smartMemory) {
669
+ this.smartMemory.dispose();
670
+ this.smartMemory = void 0;
671
+ }
672
+ if (this.toolRegistry) {
673
+ this.toolRegistry.clear();
674
+ }
675
+ this.executor = void 0;
676
+ this.agentKit = void 0;
677
+ this.tools = [];
678
+ this.initialized = false;
679
+ this.logger.info("Agent cleaned up");
680
+ }
681
+ switchMode(mode) {
682
+ if (this.config.execution) {
683
+ this.config.execution.operationalMode = mode;
684
+ } else {
685
+ this.config.execution = { operationalMode: mode };
686
+ }
687
+ if (this.agentKit) {
688
+ this.agentKit.operationalMode = mode;
689
+ }
690
+ this.systemMessage = this.buildSystemPrompt();
691
+ this.logger.info(`Operational mode switched to: ${mode}`);
692
+ }
693
+ getUsageStats() {
694
+ if (!this.tokenTracker) {
695
+ return {
696
+ promptTokens: 0,
697
+ completionTokens: 0,
698
+ totalTokens: 0,
699
+ cost: { totalCost: 0 }
700
+ };
701
+ }
702
+ const usage = this.tokenTracker.getTotalTokenUsage();
703
+ const cost = calculateTokenCostSync(usage);
704
+ return { ...usage, cost };
705
+ }
706
+ getUsageLog() {
707
+ if (!this.tokenTracker) {
708
+ return [];
709
+ }
710
+ return this.tokenTracker.getTokenUsageHistory().map((usage) => ({
711
+ ...usage,
712
+ cost: calculateTokenCostSync(usage)
713
+ }));
714
+ }
715
+ clearUsageStats() {
716
+ if (this.tokenTracker) {
717
+ this.tokenTracker.reset();
718
+ this.logger.info("Usage statistics cleared");
719
+ }
720
+ }
721
+ getMCPConnectionStatus() {
722
+ return new Map(this.mcpConnectionStatus);
723
+ }
724
+ /**
725
+ * Processes form submission and continues with tool execution
726
+ */
727
+ async processFormSubmission(submission, context) {
728
+ this.logger.info("🔥 LangChainAgent.processFormSubmission START");
729
+ if (!this.initialized || !this.executor || !this.smartMemory) {
730
+ this.logger.error(
731
+ "🔥 LangChainAgent.processFormSubmission - Agent not initialized"
732
+ );
733
+ throw new Error("Agent not initialized. Call boot() first.");
734
+ }
735
+ this.logger.info(
736
+ "🔥 LangChainAgent.processFormSubmission - After initialization check"
737
+ );
738
+ try {
739
+ this.logger.info(
740
+ "🔥 LangChainAgent.processFormSubmission - About to log submission info"
741
+ );
742
+ this.logger.info("Processing form submission:", {
743
+ formId: submission.formId,
744
+ toolName: submission.toolName,
745
+ parameterKeys: Object.keys(submission.parameters || {}),
746
+ hasParameters: !!submission.parameters,
747
+ parametersType: typeof submission.parameters,
748
+ parametersIsNull: submission.parameters === null,
749
+ parametersIsUndefined: submission.parameters === void 0,
750
+ hasContext: !!submission.context
751
+ });
752
+ this.logger.info(
753
+ "🔥 LangChainAgent.processFormSubmission - After submission info logged"
754
+ );
755
+ if (!submission.parameters || typeof submission.parameters !== "object") {
756
+ this.logger.error("Invalid form submission parameters:", {
757
+ parameters: submission.parameters,
758
+ type: typeof submission.parameters
759
+ });
760
+ const errorInfo = JSON.stringify(submission, null, 2);
761
+ return this.handleError(
762
+ new Error(`Invalid form submission parameters: ${errorInfo}`)
763
+ );
764
+ }
765
+ this.logger.info(
766
+ "🔥 LangChainAgent.processFormSubmission - Parameters validated"
767
+ );
768
+ this.loadContextMessages(context);
769
+ this.logger.info(
770
+ "🔥 LangChainAgent.processFormSubmission - Context loaded"
771
+ );
772
+ try {
773
+ const currentMessages = this.smartMemory.getMessages();
774
+ this.logger.info("Current messages in memory (form path):", {
775
+ count: currentMessages.length,
776
+ messages: currentMessages.map((m) => m.content)
777
+ });
778
+ } catch {
779
+ }
780
+ const safeSubmission = {
781
+ ...submission,
782
+ parameters: submission.parameters || {}
783
+ };
784
+ this.logger.info(
785
+ "🔥 LangChainAgent.processFormSubmission - Safe submission created"
786
+ );
787
+ this.logger.info("About to call executor.processFormSubmission with:", {
788
+ formId: safeSubmission.formId,
789
+ toolName: safeSubmission.toolName,
790
+ parameterKeys: Object.keys(safeSubmission.parameters),
791
+ parameterCount: Object.keys(safeSubmission.parameters).length
792
+ });
793
+ const result = await this.executor.processFormSubmission(safeSubmission);
794
+ this.logger.info("🔍 DEBUG: Raw result from FormAwareAgentExecutor:", {
795
+ hasResult: !!result,
796
+ resultKeys: result ? Object.keys(result) : [],
797
+ hasMetadata: !!result?.metadata,
798
+ metadataKeys: result?.metadata ? Object.keys(result.metadata) : [],
799
+ hasHashLinkBlock: hasHashLinkBlock(result?.metadata),
800
+ hashLinkBlockContent: hasHashLinkBlock(result?.metadata) ? result.metadata.hashLinkBlock : void 0
801
+ });
802
+ if (result?.metadata) {
803
+ this.logger.info(
804
+ "🔍 DEBUG: Full metadata from executor:",
805
+ JSON.stringify(result.metadata)
806
+ );
807
+ }
808
+ const preservedMetadata = result?.metadata ? { ...result.metadata } : {};
809
+ this.logger.info("Executor processFormSubmission result:", {
810
+ hasResult: !!result,
811
+ hasOutput: !!result.output,
812
+ hasError: !!result.error,
813
+ hasMetadata: !!result.metadata,
814
+ outputType: typeof result.output
815
+ });
816
+ try {
817
+ const maybeRaw = result.rawToolOutput;
818
+ const toolName = result.toolName || "unknown";
819
+ if (typeof maybeRaw === "string" && maybeRaw.trim().length > 0) {
820
+ const payload = this.isJSON(maybeRaw) ? maybeRaw : JSON.stringify({ output: maybeRaw });
821
+ this.addToolRawToMemory(toolName, payload);
822
+ }
823
+ } catch {
824
+ }
825
+ let outputMessage = "Form processed successfully.";
826
+ if (typeof result.output === "string") {
827
+ outputMessage = result.output;
828
+ } else if (result.output) {
829
+ try {
830
+ outputMessage = JSON.stringify(result.output);
831
+ } catch {
832
+ outputMessage = String(result.output);
833
+ }
834
+ }
835
+ let response = {
836
+ output: outputMessage,
837
+ message: outputMessage,
838
+ notes: [],
839
+ intermediateSteps: result.intermediateSteps
840
+ };
841
+ if (result.metadata) {
842
+ response.metadata = {
843
+ ...response.metadata,
844
+ ...result.metadata
845
+ };
846
+ this.logger.info("🔍 DEBUG: Metadata after merge from result:", {
847
+ hasMetadata: !!response.metadata,
848
+ metadataKeys: response.metadata ? Object.keys(response.metadata) : [],
849
+ hasHashLinkBlock: hasHashLinkBlock(response.metadata),
850
+ hashLinkBlockContent: hasHashLinkBlock(response.metadata) ? response.metadata.hashLinkBlock : void 0
851
+ });
852
+ }
853
+ if (result.requiresForm && result.formMessage) {
854
+ response.formMessage = result.formMessage;
855
+ response.requiresForm = true;
856
+ }
857
+ if (result.intermediateSteps && Array.isArray(result.intermediateSteps)) {
858
+ const toolCalls = result.intermediateSteps.map(
859
+ (step, index) => {
860
+ const name = step?.action?.tool || "unknown";
861
+ const args = step?.action?.toolInput || {};
862
+ const obs = step?.observation;
863
+ let output = "";
864
+ if (typeof obs === "string") {
865
+ output = obs;
866
+ } else if (obs && typeof obs === "object") {
867
+ try {
868
+ output = JSON.stringify(obs);
869
+ } catch {
870
+ output = String(obs);
871
+ }
872
+ } else if (obs !== void 0) {
873
+ output = String(obs);
874
+ }
875
+ return { id: `call_${index}`, name, args, output };
876
+ }
877
+ );
878
+ if (toolCalls.length > 0) {
879
+ response.tool_calls = toolCalls;
880
+ }
881
+ this.persistIntermediateSteps(
882
+ result.intermediateSteps
883
+ );
884
+ }
885
+ const parsedSteps = result?.intermediateSteps?.[0]?.observation;
886
+ if (parsedSteps && typeof parsedSteps === "string" && this.isJSON(parsedSteps)) {
887
+ try {
888
+ const parsed = JSON.parse(parsedSteps);
889
+ response = { ...response, ...parsed };
890
+ const blockMetadata = this.processHashLinkBlocks(parsed);
891
+ if (blockMetadata.hashLinkBlock) {
892
+ response.metadata = {
893
+ ...response.metadata,
894
+ ...blockMetadata
895
+ };
896
+ }
897
+ } catch (error) {
898
+ this.logger.error("Error parsing intermediate steps:", error);
899
+ }
900
+ }
901
+ if (response.output) {
902
+ this.smartMemory.addMessage(new AIMessage(response.output));
903
+ }
904
+ if (this.tokenTracker) {
905
+ const tokenUsage = this.tokenTracker.getLatestTokenUsage();
906
+ if (tokenUsage) {
907
+ response.tokenUsage = tokenUsage;
908
+ response.cost = calculateTokenCostSync(tokenUsage);
909
+ }
910
+ }
911
+ const finalMemoryStats = this.smartMemory.getMemoryStats();
912
+ this.logger.info("🔍 DEBUG: Metadata before memoryStats merge:", {
913
+ hasMetadata: !!response.metadata,
914
+ metadataKeys: response.metadata ? Object.keys(response.metadata) : [],
915
+ hasHashLinkBlock: hasHashLinkBlock(response.metadata)
916
+ });
917
+ response.metadata = {
918
+ ...preservedMetadata,
919
+ ...response.metadata,
920
+ memoryStats: {
921
+ activeMessages: finalMemoryStats.totalActiveMessages,
922
+ tokenUsage: finalMemoryStats.currentTokenCount,
923
+ maxTokens: finalMemoryStats.maxTokens,
924
+ usagePercentage: finalMemoryStats.usagePercentage
925
+ }
926
+ };
927
+ this.logger.info("🔍 DEBUG: Final response metadata before return:", {
928
+ hasMetadata: !!response.metadata,
929
+ metadataKeys: response.metadata ? Object.keys(response.metadata) : [],
930
+ hasHashLinkBlock: hasHashLinkBlock(response.metadata),
931
+ fullMetadata: response.metadata
932
+ });
933
+ if (hasHashLinkBlock(preservedMetadata) && !hasHashLinkBlock(response.metadata)) {
934
+ this.logger.error(
935
+ "❌ CRITICAL: HashLink metadata was lost during processing!"
936
+ );
937
+ this.logger.error(
938
+ "Original metadata had hashLinkBlock:",
939
+ preservedMetadata.hashLinkBlock
940
+ );
941
+ this.logger.error("Final metadata missing hashLinkBlock");
942
+ }
943
+ return response;
944
+ } catch (error) {
945
+ this.logger.error("Form submission processing error:", error);
946
+ return this.handleError(error);
947
+ }
948
+ }
949
+ /**
950
+ * Check if the agent has pending forms that need to be completed
951
+ */
952
+ hasPendingForms() {
953
+ return this.executor ? this.executor.hasPendingForms() : false;
954
+ }
955
+ /**
956
+ * Get information about pending forms
957
+ */
958
+ getPendingFormsInfo() {
959
+ return this.executor ? this.executor.getPendingFormsInfo() : [];
960
+ }
961
+ async createAgentKit() {
962
+ const corePlugins = getAllHederaCorePlugins();
963
+ const extensionPlugins = this.config.extensions?.plugins || [];
964
+ const plugins = [...corePlugins, ...extensionPlugins];
965
+ const operationalMode = this.config.execution?.operationalMode || "returnBytes";
966
+ const modelName = this.config.ai?.modelName || "gpt-4o";
967
+ return new HederaAgentKit(
968
+ this.config.signer,
969
+ { plugins },
970
+ operationalMode,
971
+ this.config.execution?.userAccountId,
972
+ this.config.execution?.scheduleUserTransactionsInBytesMode ?? false,
973
+ void 0,
974
+ modelName,
975
+ this.config.extensions?.mirrorConfig,
976
+ this.config.debug?.silent ?? false
977
+ );
978
+ }
979
+ async createExecutor() {
980
+ const existingPendingForms = this.executor?.getPendingForms() || /* @__PURE__ */ new Map();
981
+ let llm;
982
+ if (this.config.ai?.provider && this.config.ai.provider.getModel) {
983
+ llm = this.config.ai.provider.getModel();
984
+ } else if (this.config.ai?.llm) {
985
+ llm = this.config.ai.llm;
986
+ } else {
987
+ const apiKey = this.config.ai?.apiKey || process.env.OPENAI_API_KEY;
988
+ if (!apiKey) {
989
+ throw new Error("OpenAI API key required");
990
+ }
991
+ const modelName = this.config.ai?.modelName || "gpt-4o-mini";
992
+ const isGPT5Model = modelName.toLowerCase().includes("gpt-5") || modelName.toLowerCase().includes("gpt5");
993
+ llm = new ChatOpenAI({
994
+ apiKey,
995
+ modelName,
996
+ callbacks: this.tokenTracker ? [this.tokenTracker] : [],
997
+ ...isGPT5Model ? { temperature: 1 } : {}
998
+ });
999
+ }
1000
+ const prompt = ChatPromptTemplate.fromMessages([
1001
+ ["system", this.systemMessage],
1002
+ new MessagesPlaceholder("chat_history"),
1003
+ ["human", "{input}"],
1004
+ new MessagesPlaceholder("agent_scratchpad")
1005
+ ]);
1006
+ const langchainTools = this.tools;
1007
+ const inscriptionTool = this.getInscriptionTool();
1008
+ if (inscriptionTool) {
1009
+ const entry = this.toolRegistry.getTool(inscriptionTool.name);
1010
+ if (entry) {
1011
+ this.logger.info(
1012
+ `✅ Inscription tool registered: ${inscriptionTool.name}`
1013
+ );
1014
+ }
1015
+ }
1016
+ const stats = this.toolRegistry.getStatistics();
1017
+ this.logger.info("🛡️ TOOL SECURITY REPORT:", {
1018
+ totalTools: stats.totalTools,
1019
+ wrappedTools: stats.wrappedTools,
1020
+ unwrappedTools: stats.unwrappedTools,
1021
+ categories: stats.categoryCounts,
1022
+ priorities: stats.priorityCounts
1023
+ });
1024
+ this.logger.info(
1025
+ `📊 Tool Security Summary: ${stats.wrappedTools} wrapped, ${stats.unwrappedTools} unwrapped`
1026
+ );
1027
+ const agent = await createOpenAIToolsAgent({
1028
+ llm,
1029
+ tools: langchainTools,
1030
+ prompt
1031
+ });
1032
+ this.executor = new FormAwareAgentExecutor({
1033
+ agent,
1034
+ tools: langchainTools,
1035
+ verbose: this.config.debug?.verbose ?? false,
1036
+ returnIntermediateSteps: true
1037
+ });
1038
+ if (this.pendingParameterPreprocessingCallback) {
1039
+ this.executor.setParameterPreprocessingCallback(
1040
+ this.pendingParameterPreprocessingCallback
1041
+ );
1042
+ this.logger.info(
1043
+ "Parameter preprocessing callback re-applied to new executor",
1044
+ { hasCallback: true }
1045
+ );
1046
+ }
1047
+ if (existingPendingForms.size > 0) {
1048
+ this.logger.info(
1049
+ `Restoring ${existingPendingForms.size} pending forms to new executor`
1050
+ );
1051
+ this.executor.restorePendingForms(existingPendingForms);
1052
+ }
1053
+ this.logger.info("FormAwareAgentExecutor initialization complete");
145
1054
  }
146
1055
  /**
147
- * Reset to default patterns
1056
+ * Set parameter preprocessing callback for tool parameter format conversion
148
1057
  */
149
- reset() {
150
- this.clear();
151
- this.initializeDefaultPatterns();
1058
+ setParameterPreprocessingCallback(callback) {
1059
+ this.pendingParameterPreprocessingCallback = callback;
1060
+ if (this.executor) {
1061
+ this.executor.setParameterPreprocessingCallback(callback);
1062
+ this.logger.info("Parameter preprocessing callback configured", {
1063
+ hasCallback: !!callback
1064
+ });
1065
+ } else {
1066
+ this.logger.warn(
1067
+ "Cannot set parameter preprocessing callback: executor not initialized"
1068
+ );
1069
+ }
1070
+ }
1071
+ handleError(error) {
1072
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
1073
+ this.logger.error("Chat error:", error);
1074
+ let tokenUsage;
1075
+ let cost;
1076
+ if (this.tokenTracker) {
1077
+ tokenUsage = this.tokenTracker.getLatestTokenUsage();
1078
+ if (tokenUsage) {
1079
+ cost = calculateTokenCostSync(tokenUsage);
1080
+ }
1081
+ }
1082
+ let userFriendlyMessage = errorMessage;
1083
+ let userFriendlyOutput = errorMessage;
1084
+ if (errorMessage.includes("429")) {
1085
+ if (errorMessage.includes("quota")) {
1086
+ userFriendlyMessage = "API quota exceeded. Please check your OpenAI billing and usage limits.";
1087
+ 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.";
1088
+ } else {
1089
+ userFriendlyMessage = ERROR_MESSAGES.TOO_MANY_REQUESTS;
1090
+ userFriendlyOutput = ERROR_MESSAGES.RATE_LIMITED;
1091
+ }
1092
+ } else if (errorMessage.includes("401") || errorMessage.includes("unauthorized")) {
1093
+ userFriendlyMessage = "API authentication failed. Please check your API key configuration.";
1094
+ userFriendlyOutput = "There's an issue with the API authentication. Please check your OpenAI API key configuration in settings.";
1095
+ } else if (errorMessage.includes("timeout")) {
1096
+ userFriendlyMessage = "Request timed out. Please try again.";
1097
+ userFriendlyOutput = "The request took too long to process. Please try again.";
1098
+ } else if (errorMessage.includes("network") || errorMessage.includes("fetch")) {
1099
+ userFriendlyMessage = "Network error. Please check your internet connection and try again.";
1100
+ userFriendlyOutput = "There was a network error. Please check your internet connection and try again.";
1101
+ } else if (errorMessage.includes("400")) {
1102
+ userFriendlyMessage = errorMessage;
1103
+ userFriendlyOutput = errorMessage;
1104
+ }
1105
+ const errorResponse = {
1106
+ output: userFriendlyOutput,
1107
+ message: userFriendlyMessage,
1108
+ error: errorMessage,
1109
+ notes: []
1110
+ };
1111
+ if (tokenUsage) {
1112
+ errorResponse.tokenUsage = tokenUsage;
1113
+ }
1114
+ if (cost) {
1115
+ errorResponse.cost = cost;
1116
+ }
1117
+ return errorResponse;
1118
+ }
1119
+ async initializeMCP() {
1120
+ this.mcpManager = new MCPClientManager(this.logger);
1121
+ for (const serverConfig of this.config.mcp.servers) {
1122
+ if (serverConfig.autoConnect === false) {
1123
+ this.logger.info(
1124
+ `Skipping MCP server ${serverConfig.name} (autoConnect=false)`
1125
+ );
1126
+ continue;
1127
+ }
1128
+ const status = await this.mcpManager.connectServer(serverConfig);
1129
+ if (status.connected) {
1130
+ this.logger.info(
1131
+ `Connected to MCP server ${status.serverName} with ${status.tools.length} tools`
1132
+ );
1133
+ for (const mcpTool of status.tools) {
1134
+ const langchainTool = convertMCPToolToLangChain(
1135
+ mcpTool,
1136
+ this.mcpManager,
1137
+ serverConfig
1138
+ );
1139
+ this.toolRegistry.registerTool(langchainTool, {
1140
+ metadata: {
1141
+ category: "mcp",
1142
+ version: "1.0.0",
1143
+ dependencies: [serverConfig.name]
1144
+ }
1145
+ });
1146
+ }
1147
+ this.tools = this.toolRegistry.getAllTools();
1148
+ } else {
1149
+ this.logger.error(
1150
+ `Failed to connect to MCP server ${status.serverName}: ${status.error}`
1151
+ );
1152
+ }
1153
+ }
1154
+ }
1155
+ /**
1156
+ * Connect to MCP servers asynchronously after agent boot with background timeout pattern
1157
+ */
1158
+ async connectMCPServers() {
1159
+ if (!this.config.mcp?.servers || this.config.mcp.servers.length === 0) {
1160
+ return;
1161
+ }
1162
+ if (!this.mcpManager) {
1163
+ this.mcpManager = new MCPClientManager(this.logger);
1164
+ }
1165
+ this.logger.info(
1166
+ `Starting background MCP server connections for ${this.config.mcp.servers.length} servers...`
1167
+ );
1168
+ this.config.mcp.servers.forEach((serverConfig) => {
1169
+ this.connectServerInBackground(serverConfig);
1170
+ });
1171
+ this.logger.info("MCP server connections initiated in background");
1172
+ }
1173
+ /**
1174
+ * Connect to a single MCP server in background with timeout
1175
+ */
1176
+ connectServerInBackground(serverConfig) {
1177
+ const serverName = serverConfig.name;
1178
+ setTimeout(async () => {
1179
+ try {
1180
+ this.logger.info(`Background connecting to MCP server: ${serverName}`);
1181
+ const status = await this.mcpManager.connectServer(serverConfig);
1182
+ this.mcpConnectionStatus.set(serverName, status);
1183
+ if (status.connected) {
1184
+ this.logger.info(
1185
+ `Successfully connected to MCP server ${status.serverName} with ${status.tools.length} tools`
1186
+ );
1187
+ for (const mcpTool of status.tools) {
1188
+ const langchainTool = convertMCPToolToLangChain(
1189
+ mcpTool,
1190
+ this.mcpManager,
1191
+ serverConfig
1192
+ );
1193
+ this.toolRegistry.registerTool(langchainTool, {
1194
+ metadata: {
1195
+ category: "mcp",
1196
+ version: "1.0.0",
1197
+ dependencies: [serverConfig.name]
1198
+ }
1199
+ });
1200
+ }
1201
+ this.tools = this.toolRegistry.getAllTools();
1202
+ if (this.initialized && this.executor) {
1203
+ this.logger.info(
1204
+ `Recreating executor with ${this.tools.length} total tools`
1205
+ );
1206
+ await this.createExecutor();
1207
+ }
1208
+ } else {
1209
+ this.logger.error(
1210
+ `Failed to connect to MCP server ${status.serverName}: ${status.error}`
1211
+ );
1212
+ }
1213
+ } catch (error) {
1214
+ this.logger.error(
1215
+ `Background connection failed for MCP server ${serverName}:`,
1216
+ error
1217
+ );
1218
+ this.mcpConnectionStatus.set(serverName, {
1219
+ connected: false,
1220
+ serverName,
1221
+ tools: [],
1222
+ error: error instanceof Error ? error.message : "Connection failed"
1223
+ });
1224
+ }
1225
+ }, 1e3);
1226
+ }
1227
+ /**
1228
+ * Detects and processes HashLink blocks from tool responses
1229
+ * @param parsedResponse - The parsed JSON response from a tool
1230
+ * @returns Metadata object containing hashLinkBlock if detected
1231
+ */
1232
+ processHashLinkBlocks(parsedResponse) {
1233
+ try {
1234
+ const responseRecord = parsedResponse;
1235
+ if (parsedResponse && typeof parsedResponse === "object" && responseRecord.hashLinkBlock && typeof responseRecord.hashLinkBlock === "object") {
1236
+ const block = responseRecord.hashLinkBlock;
1237
+ 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") {
1238
+ this.logger.info("HashLink block detected:", {
1239
+ blockId: block.blockId,
1240
+ hashLink: block.hashLink,
1241
+ template: block.template,
1242
+ attributeKeys: Object.keys(block.attributes)
1243
+ });
1244
+ return {
1245
+ hashLinkBlock: {
1246
+ blockId: block.blockId,
1247
+ hashLink: block.hashLink,
1248
+ template: block.template,
1249
+ attributes: block.attributes
1250
+ }
1251
+ };
1252
+ } else {
1253
+ this.logger.warn("Invalid HashLink block structure detected:", block);
1254
+ }
1255
+ }
1256
+ } catch (error) {
1257
+ this.logger.error("Error processing HashLink blocks:", error);
1258
+ }
1259
+ return {};
1260
+ }
1261
+ /**
1262
+ * Check if a string is valid JSON
1263
+ */
1264
+ isJSON(str) {
1265
+ if (typeof str !== "string") return false;
1266
+ const trimmed = str.trim();
1267
+ if (!trimmed) return false;
1268
+ if (!(trimmed.startsWith("{") && trimmed.endsWith("}")) && !(trimmed.startsWith("[") && trimmed.endsWith("]"))) {
1269
+ return false;
1270
+ }
1271
+ try {
1272
+ JSON.parse(trimmed);
1273
+ return true;
1274
+ } catch {
1275
+ return false;
1276
+ }
152
1277
  }
153
1278
  }
154
- const fieldTypeRegistry = FieldTypeRegistry.getInstance();
155
1279
  export {
156
- FieldTypeRegistry,
157
- fieldTypeRegistry
1280
+ LangChainAgent
158
1281
  };
159
1282
  //# sourceMappingURL=index30.js.map