@robota-sdk/agent-core 3.0.0-beta.1

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 (508) hide show
  1. package/CHANGELOG.md +180 -0
  2. package/LICENSE +21 -0
  3. package/README.md +230 -0
  4. package/dist/abstracts/abstract-agent.d.ts +56 -0
  5. package/dist/abstracts/abstract-agent.d.ts.map +1 -0
  6. package/dist/abstracts/abstract-agent.js +55 -0
  7. package/dist/abstracts/abstract-agent.js.map +1 -0
  8. package/dist/abstracts/abstract-ai-provider.d.ts +187 -0
  9. package/dist/abstracts/abstract-ai-provider.d.ts.map +1 -0
  10. package/dist/abstracts/abstract-ai-provider.js +252 -0
  11. package/dist/abstracts/abstract-ai-provider.js.map +1 -0
  12. package/dist/abstracts/abstract-executor.d.ts +110 -0
  13. package/dist/abstracts/abstract-executor.d.ts.map +1 -0
  14. package/dist/abstracts/abstract-executor.js +156 -0
  15. package/dist/abstracts/abstract-executor.js.map +1 -0
  16. package/dist/abstracts/abstract-manager.d.ts +42 -0
  17. package/dist/abstracts/abstract-manager.d.ts.map +1 -0
  18. package/dist/abstracts/abstract-manager.js +49 -0
  19. package/dist/abstracts/abstract-manager.js.map +1 -0
  20. package/dist/abstracts/abstract-module.d.ts +365 -0
  21. package/dist/abstracts/abstract-module.d.ts.map +1 -0
  22. package/dist/abstracts/abstract-module.js +474 -0
  23. package/dist/abstracts/abstract-module.js.map +1 -0
  24. package/dist/abstracts/abstract-plugin.d.ts +369 -0
  25. package/dist/abstracts/abstract-plugin.d.ts.map +1 -0
  26. package/dist/abstracts/abstract-plugin.js +258 -0
  27. package/dist/abstracts/abstract-plugin.js.map +1 -0
  28. package/dist/abstracts/abstract-tool.d.ts +175 -0
  29. package/dist/abstracts/abstract-tool.d.ts.map +1 -0
  30. package/dist/abstracts/abstract-tool.js +140 -0
  31. package/dist/abstracts/abstract-tool.js.map +1 -0
  32. package/dist/abstracts/abstract-workflow-converter.d.ts +136 -0
  33. package/dist/abstracts/abstract-workflow-converter.d.ts.map +1 -0
  34. package/dist/abstracts/abstract-workflow-converter.js +252 -0
  35. package/dist/abstracts/abstract-workflow-converter.js.map +1 -0
  36. package/dist/abstracts/abstract-workflow-validator.d.ts +203 -0
  37. package/dist/abstracts/abstract-workflow-validator.d.ts.map +1 -0
  38. package/dist/abstracts/abstract-workflow-validator.js +447 -0
  39. package/dist/abstracts/abstract-workflow-validator.js.map +1 -0
  40. package/dist/abstracts/index.d.ts +6 -0
  41. package/dist/abstracts/index.d.ts.map +1 -0
  42. package/dist/abstracts/index.js +9 -0
  43. package/dist/abstracts/index.js.map +1 -0
  44. package/dist/agents/constants.d.ts +23 -0
  45. package/dist/agents/constants.d.ts.map +1 -0
  46. package/dist/agents/constants.js +22 -0
  47. package/dist/agents/constants.js.map +1 -0
  48. package/dist/agents/index.d.ts +1 -0
  49. package/dist/agents/index.d.ts.map +1 -0
  50. package/dist/agents/index.js +4 -0
  51. package/dist/agents/index.js.map +1 -0
  52. package/dist/agents/robota.test.d.ts +2 -0
  53. package/dist/agents/robota.test.d.ts.map +1 -0
  54. package/dist/agents/robota.test.js +416 -0
  55. package/dist/agents/robota.test.js.map +1 -0
  56. package/dist/browser/builtin-templates.json +107 -0
  57. package/dist/browser/index.d.ts +4237 -0
  58. package/dist/browser/index.js +4 -0
  59. package/dist/core/robota.d.ts +694 -0
  60. package/dist/core/robota.d.ts.map +1 -0
  61. package/dist/core/robota.js +1277 -0
  62. package/dist/core/robota.js.map +1 -0
  63. package/dist/executors/local-executor.d.ts +96 -0
  64. package/dist/executors/local-executor.d.ts.map +1 -0
  65. package/dist/executors/local-executor.js +197 -0
  66. package/dist/executors/local-executor.js.map +1 -0
  67. package/dist/executors/local-executor.test.d.ts +2 -0
  68. package/dist/executors/local-executor.test.d.ts.map +1 -0
  69. package/dist/executors/local-executor.test.js +192 -0
  70. package/dist/executors/local-executor.test.js.map +1 -0
  71. package/dist/index.d.ts +274 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +235 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/interfaces/agent.d.ts +198 -0
  76. package/dist/interfaces/agent.d.ts.map +1 -0
  77. package/dist/interfaces/agent.js +2 -0
  78. package/dist/interfaces/agent.js.map +1 -0
  79. package/dist/interfaces/event-service.d.ts +79 -0
  80. package/dist/interfaces/event-service.d.ts.map +1 -0
  81. package/dist/interfaces/event-service.js +2 -0
  82. package/dist/interfaces/event-service.js.map +1 -0
  83. package/dist/interfaces/executor.d.ts +128 -0
  84. package/dist/interfaces/executor.d.ts.map +1 -0
  85. package/dist/interfaces/executor.js +2 -0
  86. package/dist/interfaces/executor.js.map +1 -0
  87. package/dist/interfaces/history-module.d.ts +19 -0
  88. package/dist/interfaces/history-module.d.ts.map +1 -0
  89. package/dist/interfaces/history-module.js +2 -0
  90. package/dist/interfaces/history-module.js.map +1 -0
  91. package/dist/interfaces/index.d.ts +13 -0
  92. package/dist/interfaces/index.d.ts.map +1 -0
  93. package/dist/interfaces/index.js +4 -0
  94. package/dist/interfaces/index.js.map +1 -0
  95. package/dist/interfaces/manager.d.ts +142 -0
  96. package/dist/interfaces/manager.d.ts.map +1 -0
  97. package/dist/interfaces/manager.js +2 -0
  98. package/dist/interfaces/manager.js.map +1 -0
  99. package/dist/interfaces/messages.d.ts +75 -0
  100. package/dist/interfaces/messages.d.ts.map +1 -0
  101. package/dist/interfaces/messages.js +29 -0
  102. package/dist/interfaces/messages.js.map +1 -0
  103. package/dist/interfaces/progress-reporting.d.ts +86 -0
  104. package/dist/interfaces/progress-reporting.d.ts.map +1 -0
  105. package/dist/interfaces/progress-reporting.js +37 -0
  106. package/dist/interfaces/progress-reporting.js.map +1 -0
  107. package/dist/interfaces/provider.d.ts +217 -0
  108. package/dist/interfaces/provider.d.ts.map +1 -0
  109. package/dist/interfaces/provider.js +2 -0
  110. package/dist/interfaces/provider.js.map +1 -0
  111. package/dist/interfaces/service.d.ts +205 -0
  112. package/dist/interfaces/service.d.ts.map +1 -0
  113. package/dist/interfaces/service.js +6 -0
  114. package/dist/interfaces/service.js.map +1 -0
  115. package/dist/interfaces/tool.d.ts +248 -0
  116. package/dist/interfaces/tool.d.ts.map +1 -0
  117. package/dist/interfaces/tool.js +2 -0
  118. package/dist/interfaces/tool.js.map +1 -0
  119. package/dist/interfaces/types.d.ts +71 -0
  120. package/dist/interfaces/types.d.ts.map +1 -0
  121. package/dist/interfaces/types.js +33 -0
  122. package/dist/interfaces/types.js.map +1 -0
  123. package/dist/interfaces/workflow-converter.d.ts +193 -0
  124. package/dist/interfaces/workflow-converter.d.ts.map +1 -0
  125. package/dist/interfaces/workflow-converter.js +11 -0
  126. package/dist/interfaces/workflow-converter.js.map +1 -0
  127. package/dist/interfaces/workflow-validator.d.ts +209 -0
  128. package/dist/interfaces/workflow-validator.d.ts.map +1 -0
  129. package/dist/interfaces/workflow-validator.js +16 -0
  130. package/dist/interfaces/workflow-validator.js.map +1 -0
  131. package/dist/managers/agent-factory.d.ts +132 -0
  132. package/dist/managers/agent-factory.d.ts.map +1 -0
  133. package/dist/managers/agent-factory.js +284 -0
  134. package/dist/managers/agent-factory.js.map +1 -0
  135. package/dist/managers/agent-factory.test.d.ts +2 -0
  136. package/dist/managers/agent-factory.test.d.ts.map +1 -0
  137. package/dist/managers/agent-factory.test.js +249 -0
  138. package/dist/managers/agent-factory.test.js.map +1 -0
  139. package/dist/managers/agent-templates.d.ts +84 -0
  140. package/dist/managers/agent-templates.d.ts.map +1 -0
  141. package/dist/managers/agent-templates.js +159 -0
  142. package/dist/managers/agent-templates.js.map +1 -0
  143. package/dist/managers/ai-provider-manager.d.ts +80 -0
  144. package/dist/managers/ai-provider-manager.d.ts.map +1 -0
  145. package/dist/managers/ai-provider-manager.js +226 -0
  146. package/dist/managers/ai-provider-manager.js.map +1 -0
  147. package/dist/managers/conversation-history-manager.d.ts +455 -0
  148. package/dist/managers/conversation-history-manager.d.ts.map +1 -0
  149. package/dist/managers/conversation-history-manager.js +578 -0
  150. package/dist/managers/conversation-history-manager.js.map +1 -0
  151. package/dist/managers/conversation-history-manager.test.d.ts +2 -0
  152. package/dist/managers/conversation-history-manager.test.d.ts.map +1 -0
  153. package/dist/managers/conversation-history-manager.test.js +374 -0
  154. package/dist/managers/conversation-history-manager.test.js.map +1 -0
  155. package/dist/managers/index.d.ts +8 -0
  156. package/dist/managers/index.d.ts.map +1 -0
  157. package/dist/managers/index.js +8 -0
  158. package/dist/managers/index.js.map +1 -0
  159. package/dist/managers/module-registry.d.ts +161 -0
  160. package/dist/managers/module-registry.d.ts.map +1 -0
  161. package/dist/managers/module-registry.js +519 -0
  162. package/dist/managers/module-registry.js.map +1 -0
  163. package/dist/managers/module-type-registry.d.ts +113 -0
  164. package/dist/managers/module-type-registry.d.ts.map +1 -0
  165. package/dist/managers/module-type-registry.js +439 -0
  166. package/dist/managers/module-type-registry.js.map +1 -0
  167. package/dist/managers/plugins.d.ts +166 -0
  168. package/dist/managers/plugins.d.ts.map +1 -0
  169. package/dist/managers/plugins.js +339 -0
  170. package/dist/managers/plugins.js.map +1 -0
  171. package/dist/managers/tool-manager.d.ts +70 -0
  172. package/dist/managers/tool-manager.d.ts.map +1 -0
  173. package/dist/managers/tool-manager.js +138 -0
  174. package/dist/managers/tool-manager.js.map +1 -0
  175. package/dist/managers/tool-manager.test.d.ts +2 -0
  176. package/dist/managers/tool-manager.test.d.ts.map +1 -0
  177. package/dist/managers/tool-manager.test.js +186 -0
  178. package/dist/managers/tool-manager.test.js.map +1 -0
  179. package/dist/node/builtin-templates.json +107 -0
  180. package/dist/node/index.cjs +4 -0
  181. package/dist/node/index.d.cts +4237 -0
  182. package/dist/node/index.d.ts +4237 -0
  183. package/dist/node/index.js +4 -0
  184. package/dist/plugins/conversation-history/conversation-history-plugin.d.ts +67 -0
  185. package/dist/plugins/conversation-history/conversation-history-plugin.d.ts.map +1 -0
  186. package/dist/plugins/conversation-history/conversation-history-plugin.js +270 -0
  187. package/dist/plugins/conversation-history/conversation-history-plugin.js.map +1 -0
  188. package/dist/plugins/conversation-history/index.d.ts +3 -0
  189. package/dist/plugins/conversation-history/index.d.ts.map +1 -0
  190. package/dist/plugins/conversation-history/index.js +2 -0
  191. package/dist/plugins/conversation-history/index.js.map +1 -0
  192. package/dist/plugins/conversation-history/storages/database-storage.d.ts +19 -0
  193. package/dist/plugins/conversation-history/storages/database-storage.d.ts.map +1 -0
  194. package/dist/plugins/conversation-history/storages/database-storage.js +94 -0
  195. package/dist/plugins/conversation-history/storages/database-storage.js.map +1 -0
  196. package/dist/plugins/conversation-history/storages/file-storage.d.ts +15 -0
  197. package/dist/plugins/conversation-history/storages/file-storage.d.ts.map +1 -0
  198. package/dist/plugins/conversation-history/storages/file-storage.js +94 -0
  199. package/dist/plugins/conversation-history/storages/file-storage.js.map +1 -0
  200. package/dist/plugins/conversation-history/storages/index.d.ts +4 -0
  201. package/dist/plugins/conversation-history/storages/index.d.ts.map +1 -0
  202. package/dist/plugins/conversation-history/storages/index.js +4 -0
  203. package/dist/plugins/conversation-history/storages/index.js.map +1 -0
  204. package/dist/plugins/conversation-history/storages/memory-storage.d.ts +15 -0
  205. package/dist/plugins/conversation-history/storages/memory-storage.d.ts.map +1 -0
  206. package/dist/plugins/conversation-history/storages/memory-storage.js +33 -0
  207. package/dist/plugins/conversation-history/storages/memory-storage.js.map +1 -0
  208. package/dist/plugins/conversation-history/types.d.ts +61 -0
  209. package/dist/plugins/conversation-history/types.d.ts.map +1 -0
  210. package/dist/plugins/conversation-history/types.js +2 -0
  211. package/dist/plugins/conversation-history/types.js.map +1 -0
  212. package/dist/plugins/error-handling/context-adapter.d.ts +30 -0
  213. package/dist/plugins/error-handling/context-adapter.d.ts.map +1 -0
  214. package/dist/plugins/error-handling/context-adapter.js +41 -0
  215. package/dist/plugins/error-handling/context-adapter.js.map +1 -0
  216. package/dist/plugins/error-handling/error-handling-plugin.d.ts +49 -0
  217. package/dist/plugins/error-handling/error-handling-plugin.d.ts.map +1 -0
  218. package/dist/plugins/error-handling/error-handling-plugin.js +229 -0
  219. package/dist/plugins/error-handling/error-handling-plugin.js.map +1 -0
  220. package/dist/plugins/error-handling/index.d.ts +10 -0
  221. package/dist/plugins/error-handling/index.d.ts.map +1 -0
  222. package/dist/plugins/error-handling/index.js +10 -0
  223. package/dist/plugins/error-handling/index.js.map +1 -0
  224. package/dist/plugins/error-handling/types.d.ts +73 -0
  225. package/dist/plugins/error-handling/types.d.ts.map +1 -0
  226. package/dist/plugins/error-handling/types.js +14 -0
  227. package/dist/plugins/error-handling/types.js.map +1 -0
  228. package/dist/plugins/event-emitter/metrics.d.ts +17 -0
  229. package/dist/plugins/event-emitter/metrics.d.ts.map +1 -0
  230. package/dist/plugins/event-emitter/metrics.js +17 -0
  231. package/dist/plugins/event-emitter/metrics.js.map +1 -0
  232. package/dist/plugins/event-emitter/types.d.ts +112 -0
  233. package/dist/plugins/event-emitter/types.d.ts.map +1 -0
  234. package/dist/plugins/event-emitter/types.js +65 -0
  235. package/dist/plugins/event-emitter/types.js.map +1 -0
  236. package/dist/plugins/event-emitter-plugin.d.ts +222 -0
  237. package/dist/plugins/event-emitter-plugin.d.ts.map +1 -0
  238. package/dist/plugins/event-emitter-plugin.js +432 -0
  239. package/dist/plugins/event-emitter-plugin.js.map +1 -0
  240. package/dist/plugins/event-emitter-plugin.test.d.ts +2 -0
  241. package/dist/plugins/event-emitter-plugin.test.d.ts.map +1 -0
  242. package/dist/plugins/event-emitter-plugin.test.js +94 -0
  243. package/dist/plugins/event-emitter-plugin.test.js.map +1 -0
  244. package/dist/plugins/execution/execution-analytics-plugin.d.ts +129 -0
  245. package/dist/plugins/execution/execution-analytics-plugin.d.ts.map +1 -0
  246. package/dist/plugins/execution/execution-analytics-plugin.js +517 -0
  247. package/dist/plugins/execution/execution-analytics-plugin.js.map +1 -0
  248. package/dist/plugins/execution/index.d.ts +3 -0
  249. package/dist/plugins/execution/index.d.ts.map +1 -0
  250. package/dist/plugins/execution/index.js +2 -0
  251. package/dist/plugins/execution/index.js.map +1 -0
  252. package/dist/plugins/execution/types.d.ts +90 -0
  253. package/dist/plugins/execution/types.d.ts.map +1 -0
  254. package/dist/plugins/execution/types.js +2 -0
  255. package/dist/plugins/execution/types.js.map +1 -0
  256. package/dist/plugins/index.d.ts +10 -0
  257. package/dist/plugins/index.d.ts.map +1 -0
  258. package/dist/plugins/index.js +11 -0
  259. package/dist/plugins/index.js.map +1 -0
  260. package/dist/plugins/limits/types.d.ts +61 -0
  261. package/dist/plugins/limits/types.d.ts.map +1 -0
  262. package/dist/plugins/limits/types.js +2 -0
  263. package/dist/plugins/limits/types.js.map +1 -0
  264. package/dist/plugins/limits-plugin.d.ts +113 -0
  265. package/dist/plugins/limits-plugin.d.ts.map +1 -0
  266. package/dist/plugins/limits-plugin.js +380 -0
  267. package/dist/plugins/limits-plugin.js.map +1 -0
  268. package/dist/plugins/logging/formatters.d.ts +14 -0
  269. package/dist/plugins/logging/formatters.d.ts.map +1 -0
  270. package/dist/plugins/logging/formatters.js +24 -0
  271. package/dist/plugins/logging/formatters.js.map +1 -0
  272. package/dist/plugins/logging/index.d.ts +3 -0
  273. package/dist/plugins/logging/index.d.ts.map +1 -0
  274. package/dist/plugins/logging/index.js +2 -0
  275. package/dist/plugins/logging/index.js.map +1 -0
  276. package/dist/plugins/logging/logging-plugin.d.ts +91 -0
  277. package/dist/plugins/logging/logging-plugin.d.ts.map +1 -0
  278. package/dist/plugins/logging/logging-plugin.js +335 -0
  279. package/dist/plugins/logging/logging-plugin.js.map +1 -0
  280. package/dist/plugins/logging/storages/console-storage.d.ts +14 -0
  281. package/dist/plugins/logging/storages/console-storage.d.ts.map +1 -0
  282. package/dist/plugins/logging/storages/console-storage.js +38 -0
  283. package/dist/plugins/logging/storages/console-storage.js.map +1 -0
  284. package/dist/plugins/logging/storages/file-storage.d.ts +14 -0
  285. package/dist/plugins/logging/storages/file-storage.d.ts.map +1 -0
  286. package/dist/plugins/logging/storages/file-storage.js +41 -0
  287. package/dist/plugins/logging/storages/file-storage.js.map +1 -0
  288. package/dist/plugins/logging/storages/index.d.ts +5 -0
  289. package/dist/plugins/logging/storages/index.d.ts.map +1 -0
  290. package/dist/plugins/logging/storages/index.js +5 -0
  291. package/dist/plugins/logging/storages/index.js.map +1 -0
  292. package/dist/plugins/logging/storages/remote-storage.d.ts +20 -0
  293. package/dist/plugins/logging/storages/remote-storage.d.ts.map +1 -0
  294. package/dist/plugins/logging/storages/remote-storage.js +61 -0
  295. package/dist/plugins/logging/storages/remote-storage.js.map +1 -0
  296. package/dist/plugins/logging/storages/silent-storage.d.ts +10 -0
  297. package/dist/plugins/logging/storages/silent-storage.d.ts.map +1 -0
  298. package/dist/plugins/logging/storages/silent-storage.js +15 -0
  299. package/dist/plugins/logging/storages/silent-storage.js.map +1 -0
  300. package/dist/plugins/logging/types.d.ts +84 -0
  301. package/dist/plugins/logging/types.d.ts.map +1 -0
  302. package/dist/plugins/logging/types.js +2 -0
  303. package/dist/plugins/logging/types.js.map +1 -0
  304. package/dist/plugins/performance/collectors/system-metrics-collector.d.ts +12 -0
  305. package/dist/plugins/performance/collectors/system-metrics-collector.d.ts.map +1 -0
  306. package/dist/plugins/performance/collectors/system-metrics-collector.js +65 -0
  307. package/dist/plugins/performance/collectors/system-metrics-collector.js.map +1 -0
  308. package/dist/plugins/performance/index.d.ts +5 -0
  309. package/dist/plugins/performance/index.d.ts.map +1 -0
  310. package/dist/plugins/performance/index.js +4 -0
  311. package/dist/plugins/performance/index.js.map +1 -0
  312. package/dist/plugins/performance/performance-plugin.d.ts +49 -0
  313. package/dist/plugins/performance/performance-plugin.d.ts.map +1 -0
  314. package/dist/plugins/performance/performance-plugin.js +293 -0
  315. package/dist/plugins/performance/performance-plugin.js.map +1 -0
  316. package/dist/plugins/performance/storages/index.d.ts +2 -0
  317. package/dist/plugins/performance/storages/index.d.ts.map +1 -0
  318. package/dist/plugins/performance/storages/index.js +4 -0
  319. package/dist/plugins/performance/storages/index.js.map +1 -0
  320. package/dist/plugins/performance/storages/memory-storage.d.ts +19 -0
  321. package/dist/plugins/performance/storages/memory-storage.d.ts.map +1 -0
  322. package/dist/plugins/performance/storages/memory-storage.js +69 -0
  323. package/dist/plugins/performance/storages/memory-storage.js.map +1 -0
  324. package/dist/plugins/performance/types.d.ts +154 -0
  325. package/dist/plugins/performance/types.d.ts.map +1 -0
  326. package/dist/plugins/performance/types.js +2 -0
  327. package/dist/plugins/performance/types.js.map +1 -0
  328. package/dist/plugins/usage/aggregate-usage-stats.d.ts +12 -0
  329. package/dist/plugins/usage/aggregate-usage-stats.d.ts.map +1 -0
  330. package/dist/plugins/usage/aggregate-usage-stats.js +115 -0
  331. package/dist/plugins/usage/aggregate-usage-stats.js.map +1 -0
  332. package/dist/plugins/usage/index.d.ts +5 -0
  333. package/dist/plugins/usage/index.d.ts.map +1 -0
  334. package/dist/plugins/usage/index.js +4 -0
  335. package/dist/plugins/usage/index.js.map +1 -0
  336. package/dist/plugins/usage/storages/file-storage.d.ts +22 -0
  337. package/dist/plugins/usage/storages/file-storage.d.ts.map +1 -0
  338. package/dist/plugins/usage/storages/file-storage.js +111 -0
  339. package/dist/plugins/usage/storages/file-storage.js.map +1 -0
  340. package/dist/plugins/usage/storages/index.d.ts +5 -0
  341. package/dist/plugins/usage/storages/index.d.ts.map +1 -0
  342. package/dist/plugins/usage/storages/index.js +5 -0
  343. package/dist/plugins/usage/storages/index.js.map +1 -0
  344. package/dist/plugins/usage/storages/memory-storage.d.ts +22 -0
  345. package/dist/plugins/usage/storages/memory-storage.d.ts.map +1 -0
  346. package/dist/plugins/usage/storages/memory-storage.js +42 -0
  347. package/dist/plugins/usage/storages/memory-storage.js.map +1 -0
  348. package/dist/plugins/usage/storages/remote-storage.d.ts +26 -0
  349. package/dist/plugins/usage/storages/remote-storage.d.ts.map +1 -0
  350. package/dist/plugins/usage/storages/remote-storage.js +115 -0
  351. package/dist/plugins/usage/storages/remote-storage.js.map +1 -0
  352. package/dist/plugins/usage/storages/silent-storage.d.ts +19 -0
  353. package/dist/plugins/usage/storages/silent-storage.d.ts.map +1 -0
  354. package/dist/plugins/usage/storages/silent-storage.js +26 -0
  355. package/dist/plugins/usage/storages/silent-storage.js.map +1 -0
  356. package/dist/plugins/usage/types.d.ts +127 -0
  357. package/dist/plugins/usage/types.d.ts.map +1 -0
  358. package/dist/plugins/usage/types.js +2 -0
  359. package/dist/plugins/usage/types.js.map +1 -0
  360. package/dist/plugins/usage/usage-plugin.d.ts +67 -0
  361. package/dist/plugins/usage/usage-plugin.d.ts.map +1 -0
  362. package/dist/plugins/usage/usage-plugin.js +309 -0
  363. package/dist/plugins/usage/usage-plugin.js.map +1 -0
  364. package/dist/plugins/webhook/http-client.d.ts +30 -0
  365. package/dist/plugins/webhook/http-client.d.ts.map +1 -0
  366. package/dist/plugins/webhook/http-client.js +110 -0
  367. package/dist/plugins/webhook/http-client.js.map +1 -0
  368. package/dist/plugins/webhook/index.d.ts +9 -0
  369. package/dist/plugins/webhook/index.d.ts.map +1 -0
  370. package/dist/plugins/webhook/index.js +9 -0
  371. package/dist/plugins/webhook/index.js.map +1 -0
  372. package/dist/plugins/webhook/transformer.d.ts +63 -0
  373. package/dist/plugins/webhook/transformer.d.ts.map +1 -0
  374. package/dist/plugins/webhook/transformer.js +157 -0
  375. package/dist/plugins/webhook/transformer.js.map +1 -0
  376. package/dist/plugins/webhook/types.d.ts +183 -0
  377. package/dist/plugins/webhook/types.d.ts.map +1 -0
  378. package/dist/plugins/webhook/types.js +2 -0
  379. package/dist/plugins/webhook/types.js.map +1 -0
  380. package/dist/plugins/webhook/webhook-plugin.d.ts +92 -0
  381. package/dist/plugins/webhook/webhook-plugin.d.ts.map +1 -0
  382. package/dist/plugins/webhook/webhook-plugin.js +328 -0
  383. package/dist/plugins/webhook/webhook-plugin.js.map +1 -0
  384. package/dist/schemas/agent-template-schema.d.ts +137 -0
  385. package/dist/schemas/agent-template-schema.d.ts.map +1 -0
  386. package/dist/schemas/agent-template-schema.js +87 -0
  387. package/dist/schemas/agent-template-schema.js.map +1 -0
  388. package/dist/services/conversation-service/index.d.ts +88 -0
  389. package/dist/services/conversation-service/index.d.ts.map +1 -0
  390. package/dist/services/conversation-service/index.js +441 -0
  391. package/dist/services/conversation-service/index.js.map +1 -0
  392. package/dist/services/conversation-service/types.d.ts +32 -0
  393. package/dist/services/conversation-service/types.d.ts.map +1 -0
  394. package/dist/services/conversation-service/types.js +8 -0
  395. package/dist/services/conversation-service/types.js.map +1 -0
  396. package/dist/services/event-service.d.ts +61 -0
  397. package/dist/services/event-service.d.ts.map +1 -0
  398. package/dist/services/event-service.js +110 -0
  399. package/dist/services/event-service.js.map +1 -0
  400. package/dist/services/event-service.test.d.ts +2 -0
  401. package/dist/services/event-service.test.d.ts.map +1 -0
  402. package/dist/services/event-service.test.js +86 -0
  403. package/dist/services/event-service.test.js.map +1 -0
  404. package/dist/services/execution-service.d.ts +151 -0
  405. package/dist/services/execution-service.d.ts.map +1 -0
  406. package/dist/services/execution-service.js +1262 -0
  407. package/dist/services/execution-service.js.map +1 -0
  408. package/dist/services/execution-service.test.d.ts +2 -0
  409. package/dist/services/execution-service.test.d.ts.map +1 -0
  410. package/dist/services/execution-service.test.js +338 -0
  411. package/dist/services/execution-service.test.js.map +1 -0
  412. package/dist/services/history-module.d.ts +15 -0
  413. package/dist/services/history-module.d.ts.map +1 -0
  414. package/dist/services/history-module.js +42 -0
  415. package/dist/services/history-module.js.map +1 -0
  416. package/dist/services/in-memory-history-store.d.ts +12 -0
  417. package/dist/services/in-memory-history-store.d.ts.map +1 -0
  418. package/dist/services/in-memory-history-store.js +41 -0
  419. package/dist/services/in-memory-history-store.js.map +1 -0
  420. package/dist/services/index.d.ts +7 -0
  421. package/dist/services/index.d.ts.map +1 -0
  422. package/dist/services/index.js +13 -0
  423. package/dist/services/index.js.map +1 -0
  424. package/dist/services/task-events.d.ts +6 -0
  425. package/dist/services/task-events.d.ts.map +1 -0
  426. package/dist/services/task-events.js +6 -0
  427. package/dist/services/task-events.js.map +1 -0
  428. package/dist/services/tool-execution-service.d.ts +74 -0
  429. package/dist/services/tool-execution-service.d.ts.map +1 -0
  430. package/dist/services/tool-execution-service.js +189 -0
  431. package/dist/services/tool-execution-service.js.map +1 -0
  432. package/dist/services/user-events.d.ts +7 -0
  433. package/dist/services/user-events.d.ts.map +1 -0
  434. package/dist/services/user-events.js +6 -0
  435. package/dist/services/user-events.js.map +1 -0
  436. package/dist/tools/implementations/function-tool/index.d.ts +9 -0
  437. package/dist/tools/implementations/function-tool/index.d.ts.map +1 -0
  438. package/dist/tools/implementations/function-tool/index.js +13 -0
  439. package/dist/tools/implementations/function-tool/index.js.map +1 -0
  440. package/dist/tools/implementations/function-tool/schema-converter.d.ts +32 -0
  441. package/dist/tools/implementations/function-tool/schema-converter.d.ts.map +1 -0
  442. package/dist/tools/implementations/function-tool/schema-converter.js +164 -0
  443. package/dist/tools/implementations/function-tool/schema-converter.js.map +1 -0
  444. package/dist/tools/implementations/function-tool/types.d.ts +72 -0
  445. package/dist/tools/implementations/function-tool/types.d.ts.map +1 -0
  446. package/dist/tools/implementations/function-tool/types.js +14 -0
  447. package/dist/tools/implementations/function-tool/types.js.map +1 -0
  448. package/dist/tools/implementations/function-tool.d.ts +49 -0
  449. package/dist/tools/implementations/function-tool.d.ts.map +1 -0
  450. package/dist/tools/implementations/function-tool.js +223 -0
  451. package/dist/tools/implementations/function-tool.js.map +1 -0
  452. package/dist/tools/implementations/index.d.ts +4 -0
  453. package/dist/tools/implementations/index.d.ts.map +1 -0
  454. package/dist/tools/implementations/index.js +5 -0
  455. package/dist/tools/implementations/index.js.map +1 -0
  456. package/dist/tools/implementations/mcp-tool.d.ts +72 -0
  457. package/dist/tools/implementations/mcp-tool.d.ts.map +1 -0
  458. package/dist/tools/implementations/mcp-tool.js +246 -0
  459. package/dist/tools/implementations/mcp-tool.js.map +1 -0
  460. package/dist/tools/implementations/openapi-tool.d.ts +56 -0
  461. package/dist/tools/implementations/openapi-tool.d.ts.map +1 -0
  462. package/dist/tools/implementations/openapi-tool.js +324 -0
  463. package/dist/tools/implementations/openapi-tool.js.map +1 -0
  464. package/dist/tools/implementations/relay-mcp-tool.d.ts +38 -0
  465. package/dist/tools/implementations/relay-mcp-tool.d.ts.map +1 -0
  466. package/dist/tools/implementations/relay-mcp-tool.js +46 -0
  467. package/dist/tools/implementations/relay-mcp-tool.js.map +1 -0
  468. package/dist/tools/index.d.ts +3 -0
  469. package/dist/tools/index.d.ts.map +1 -0
  470. package/dist/tools/index.js +4 -0
  471. package/dist/tools/index.js.map +1 -0
  472. package/dist/tools/registry/index.d.ts +2 -0
  473. package/dist/tools/registry/index.d.ts.map +1 -0
  474. package/dist/tools/registry/index.js +3 -0
  475. package/dist/tools/registry/index.js.map +1 -0
  476. package/dist/tools/registry/tool-registry.d.ts +54 -0
  477. package/dist/tools/registry/tool-registry.d.ts.map +1 -0
  478. package/dist/tools/registry/tool-registry.js +146 -0
  479. package/dist/tools/registry/tool-registry.js.map +1 -0
  480. package/dist/utils/errors.d.ts +155 -0
  481. package/dist/utils/errors.d.ts.map +1 -0
  482. package/dist/utils/errors.js +203 -0
  483. package/dist/utils/errors.js.map +1 -0
  484. package/dist/utils/execution-proxy.d.ts +75 -0
  485. package/dist/utils/execution-proxy.d.ts.map +1 -0
  486. package/dist/utils/execution-proxy.js +230 -0
  487. package/dist/utils/execution-proxy.js.map +1 -0
  488. package/dist/utils/index.d.ts +11 -0
  489. package/dist/utils/index.d.ts.map +1 -0
  490. package/dist/utils/index.js +7 -0
  491. package/dist/utils/index.js.map +1 -0
  492. package/dist/utils/logger.d.ts +74 -0
  493. package/dist/utils/logger.d.ts.map +1 -0
  494. package/dist/utils/logger.js +143 -0
  495. package/dist/utils/logger.js.map +1 -0
  496. package/dist/utils/message-converter.d.ts +68 -0
  497. package/dist/utils/message-converter.d.ts.map +1 -0
  498. package/dist/utils/message-converter.js +87 -0
  499. package/dist/utils/message-converter.js.map +1 -0
  500. package/dist/utils/periodic-task.d.ts +14 -0
  501. package/dist/utils/periodic-task.d.ts.map +1 -0
  502. package/dist/utils/periodic-task.js +26 -0
  503. package/dist/utils/periodic-task.js.map +1 -0
  504. package/dist/utils/validation.d.ts +40 -0
  505. package/dist/utils/validation.d.ts.map +1 -0
  506. package/dist/utils/validation.js +162 -0
  507. package/dist/utils/validation.js.map +1 -0
  508. package/package.json +101 -0
@@ -0,0 +1,1262 @@
1
+ import { ToolExecutionService, TOOL_EVENT_PREFIX } from './tool-execution-service';
2
+ import { createLogger } from '../utils/logger';
3
+ import { isDefaultEventService, bindWithOwnerPath } from './event-service';
4
+ /**
5
+ * ExecutionService owned events
6
+ * Local event names only (no dots). Full names are composed at emit time.
7
+ */
8
+ export const EXECUTION_EVENTS = {
9
+ START: 'start',
10
+ COMPLETE: 'complete',
11
+ ERROR: 'error',
12
+ ASSISTANT_MESSAGE_START: 'assistant_message_start',
13
+ ASSISTANT_MESSAGE_COMPLETE: 'assistant_message_complete',
14
+ USER_MESSAGE: 'user_message',
15
+ TOOL_RESULTS_TO_LLM: 'tool_results_to_llm',
16
+ TOOL_RESULTS_READY: 'tool_results_ready'
17
+ };
18
+ export const EXECUTION_EVENT_PREFIX = 'execution';
19
+ // Type guard to check if error has execution properties
20
+ function isExecutionError(error) {
21
+ return 'executionId' in error || 'toolName' in error;
22
+ }
23
+ /**
24
+ * Service that orchestrates the entire execution pipeline
25
+ * Coordinates AI provider execution, tool execution service, and plugin lifecycle
26
+ * Uses centralized conversation history management
27
+ */
28
+ export class ExecutionService {
29
+ toolExecutionService;
30
+ aiProviders;
31
+ tools;
32
+ conversationHistory;
33
+ plugins = [];
34
+ logger;
35
+ baseEventService;
36
+ executionContext; // 🎯 [CONTEXT-INJECTION] Parent execution context
37
+ ownerPathBase;
38
+ toolEventServices;
39
+ agentOwnerPathBase;
40
+ // Path-only: remove lastResponseExecutionId tracking
41
+ lastResponseExecutionId;
42
+ constructor(aiProviders, tools, conversationHistory, eventService, executionContext // 🎯 [CONTEXT-INJECTION] Accept parent context
43
+ ) {
44
+ this.toolExecutionService = new ToolExecutionService(tools);
45
+ this.aiProviders = aiProviders;
46
+ this.tools = tools;
47
+ this.conversationHistory = conversationHistory;
48
+ this.plugins = [];
49
+ this.logger = createLogger('ExecutionService');
50
+ if (!eventService) {
51
+ throw new Error('[EXECUTION] EventService is required');
52
+ }
53
+ this.baseEventService = eventService;
54
+ this.executionContext = executionContext; // 🎯 [CONTEXT-INJECTION] Store parent context
55
+ this.ownerPathBase = this.buildBaseOwnerPath(executionContext);
56
+ this.toolEventServices = new Map();
57
+ this.agentOwnerPathBase = [];
58
+ }
59
+ /**
60
+ * Register a plugin
61
+ */
62
+ registerPlugin(plugin) {
63
+ this.plugins.push(plugin);
64
+ this.logger.debug('Plugin registered', {
65
+ pluginName: plugin.name,
66
+ hasBeforeRun: typeof plugin.beforeRun,
67
+ hasAfterRun: typeof plugin.afterRun,
68
+ hasBeforeProviderCall: typeof plugin.beforeProviderCall,
69
+ hasAfterProviderCall: typeof plugin.afterProviderCall
70
+ });
71
+ }
72
+ /**
73
+ * Remove a plugin
74
+ */
75
+ removePlugin(pluginName) {
76
+ const index = this.plugins.findIndex(p => p.name === pluginName);
77
+ if (index !== -1) {
78
+ this.plugins.splice(index, 1);
79
+ this.logger.debug('Plugin removed', { pluginName });
80
+ return true;
81
+ }
82
+ return false;
83
+ }
84
+ /**
85
+ * Get a plugin by name
86
+ */
87
+ getPlugin(pluginName) {
88
+ return this.plugins.find(p => p.name === pluginName) ?? null;
89
+ }
90
+ /**
91
+ * Get all registered plugins
92
+ */
93
+ getPlugins() {
94
+ return [...this.plugins];
95
+ }
96
+ /**
97
+ * Execute the full pipeline with centralized history management
98
+ */
99
+ async execute(input, messages, config, context) {
100
+ // [EXECUTION-DEBUG] ExecutionService.execute entrypoint
101
+ // Avoid console usage; use injected logger only.
102
+ const executionId = this.generateExecutionId();
103
+ const startTime = new Date();
104
+ const conversationId = this.requireConversationId(context, 'execute');
105
+ const fullContext = {
106
+ messages,
107
+ config,
108
+ startTime,
109
+ executionId,
110
+ conversationId,
111
+ ...(context?.sessionId && { sessionId: context.sessionId }),
112
+ ...(context?.userId && { userId: context.userId }),
113
+ ...(context?.metadata && { metadata: context.metadata })
114
+ };
115
+ this.prepareOwnerPathBases(conversationId);
116
+ this.logger.debug('Starting execution pipeline', {
117
+ executionId,
118
+ conversationId,
119
+ messageCount: messages.length,
120
+ hasContext: !!context
121
+ });
122
+ // Get current provider info and tools for rich data
123
+ const currentInfo = this.aiProviders.getCurrentProvider();
124
+ const provider = currentInfo ? this.aiProviders.getProvider(currentInfo.provider) : null;
125
+ if (!currentInfo || !currentInfo.provider || !provider) {
126
+ throw new Error('[EXECUTION] Provider is required');
127
+ }
128
+ const availableTools = this.tools.getTools();
129
+ // Emit execution start event
130
+ const rootId = conversationId;
131
+ const aiProviderInfo = {
132
+ providerName: currentInfo.provider,
133
+ model: config.defaultModel.model,
134
+ temperature: config.defaultModel.temperature,
135
+ maxTokens: config.defaultModel.maxTokens
136
+ };
137
+ const toolsInfo = availableTools.map((tool) => {
138
+ const paramSchema = tool.parameters;
139
+ const props = paramSchema?.properties;
140
+ if (!tool.description || tool.description.length === 0) {
141
+ throw new Error(`[EXECUTION] Tool "${tool.name}" is missing description`);
142
+ }
143
+ return {
144
+ name: tool.name,
145
+ description: tool.description,
146
+ parameters: props && typeof props === 'object' ? Object.keys(props) : []
147
+ };
148
+ });
149
+ this.emitExecution(EXECUTION_EVENTS.START, {
150
+ parameters: {
151
+ input,
152
+ agentConfiguration: aiProviderInfo,
153
+ availableTools: toolsInfo,
154
+ toolCount: toolsInfo.length,
155
+ hasTools: toolsInfo.length > 0,
156
+ systemMessage: config.defaultModel.systemMessage,
157
+ provider: config.defaultModel.provider,
158
+ model: config.defaultModel.model,
159
+ temperature: config.defaultModel.temperature,
160
+ maxTokens: config.defaultModel.maxTokens
161
+ },
162
+ metadata: {
163
+ method: 'execute',
164
+ inputLength: input.length,
165
+ messageCount: messages.length,
166
+ aiProvider: aiProviderInfo.providerName,
167
+ model: aiProviderInfo.model,
168
+ toolsAvailable: toolsInfo.map((t) => t.name),
169
+ agentCapabilities: {
170
+ canUseTools: toolsInfo.length > 0,
171
+ supportedActions: toolsInfo.map((t) => t.name)
172
+ }
173
+ }
174
+ }, rootId, executionId);
175
+ try {
176
+ // Get conversation session for this conversation
177
+ const conversationSession = this.conversationHistory.getConversationSession(conversationId);
178
+ // Initialize conversation history with existing messages if this is first time
179
+ if (conversationSession.getMessageCount() === 0 && messages.length > 0) {
180
+ // Add all messages in the order they appear in the messages array
181
+ // This preserves the original order including multiple system messages
182
+ messages.forEach(msg => {
183
+ if (msg.role === 'user') {
184
+ conversationSession.addUserMessage(msg.content, msg.metadata);
185
+ }
186
+ else if (msg.role === 'assistant') {
187
+ conversationSession.addAssistantMessage(msg.content, msg.toolCalls, msg.metadata);
188
+ }
189
+ else if (msg.role === 'system') {
190
+ conversationSession.addSystemMessage(msg.content, msg.metadata);
191
+ }
192
+ else if (msg.role === 'tool') {
193
+ const toolName = msg.metadata?.['toolName'];
194
+ if (typeof toolName !== 'string' || toolName.length === 0) {
195
+ throw new Error('[EXECUTION] Tool message missing toolName metadata');
196
+ }
197
+ conversationSession.addToolMessageWithId(msg.content, msg.toolCallId, toolName, msg.metadata);
198
+ }
199
+ });
200
+ }
201
+ // Add system message from config if provided and not already present
202
+ // This allows for additional system messages during execution but prevents duplicates
203
+ if (config.systemMessage) {
204
+ const existingMessages = conversationSession.getMessages();
205
+ const hasConfigSystemMessage = existingMessages.some(msg => msg.role === 'system' && msg.content === config.systemMessage);
206
+ if (!hasConfigSystemMessage) {
207
+ conversationSession.addSystemMessage(config.systemMessage, { executionId });
208
+ }
209
+ }
210
+ // Only add the current input if it's not already the last message in the conversation
211
+ const existingMessages = conversationSession.getMessages();
212
+ const lastMessage = existingMessages[existingMessages.length - 1];
213
+ const shouldAddInput = !lastMessage ||
214
+ lastMessage.role !== 'user' ||
215
+ lastMessage.content !== input;
216
+ if (shouldAddInput) {
217
+ conversationSession.addUserMessage(input, { executionId });
218
+ const rootId = conversationId;
219
+ this.emitExecution(EXECUTION_EVENTS.USER_MESSAGE, {
220
+ parameters: {
221
+ input,
222
+ userPrompt: input,
223
+ userMessageContent: input,
224
+ messageLength: input.length,
225
+ wordCount: input.split(/\s+/).filter(word => word.length > 0).length,
226
+ characterCount: input.length
227
+ },
228
+ metadata: {
229
+ messageRole: 'user',
230
+ inputLength: input.length,
231
+ messageType: 'user_message',
232
+ hasQuestions: input.includes('?'),
233
+ containsUrgency: /urgent|asap|critical|emergency/i.test(input),
234
+ estimatedComplexity: input.length > 200 ? 'high' : input.length > 50 ? 'medium' : 'low'
235
+ }
236
+ }, rootId, executionId);
237
+ }
238
+ // Call beforeRun hook on all plugins
239
+ await this.callPluginHook('beforeRun', {
240
+ input,
241
+ ...(context?.metadata ? { metadata: context.metadata } : {})
242
+ });
243
+ // Use already retrieved provider info from rich data collection above
244
+ if (!currentInfo) {
245
+ throw new Error('No AI provider configured');
246
+ }
247
+ if (!provider) {
248
+ throw new Error(`AI provider '${currentInfo.provider}' not found`);
249
+ }
250
+ // Provider implements IAIProvider, so chat() must exist.
251
+ if (typeof provider.chat !== 'function') {
252
+ throw new Error('Provider must have chat method to support execution');
253
+ }
254
+ // Process with conversation loop - now delegated to provider
255
+ let toolsExecuted = [];
256
+ let maxRounds = 10; // Increased limit for complex team delegation scenarios
257
+ let currentRound = 0;
258
+ while (currentRound < maxRounds) {
259
+ currentRound++;
260
+ // [ROUND-DEBUG] Round start logging
261
+ this.logger.info(`🔄 [ROUND-DEBUG] Starting Round ${currentRound} for agent ${fullContext.conversationId}`);
262
+ this.logger.debug(`🔄 [ROUND-${currentRound}] Starting execution round ${currentRound}`, {
263
+ executionId,
264
+ conversationId: fullContext.conversationId,
265
+ round: currentRound,
266
+ maxRounds: maxRounds
267
+ });
268
+ // Generate the thinking node id for this round at round start.
269
+ const rootId = conversationId;
270
+ // Path-only stable thinking id: conversation-level round (next assistant turn)
271
+ const historyMessages = conversationSession.getMessages();
272
+ if (!Array.isArray(historyMessages)) {
273
+ throw new Error('[EXECUTION] Conversation messages must be an array');
274
+ }
275
+ const assistantMessages = historyMessages.filter((message) => message.role === 'assistant');
276
+ const assistantMessageCount = assistantMessages.length;
277
+ const latestAssistantMessage = assistantMessages.length > 0
278
+ ? assistantMessages[assistantMessages.length - 1]
279
+ : undefined;
280
+ const shouldChainFromPreviousToolResult = Array.isArray(latestAssistantMessage?.toolCalls) &&
281
+ latestAssistantMessage.toolCalls.length > 0;
282
+ const thinkingNodeId = `thinking_${rootId}_round${assistantMessageCount + 1}`;
283
+ const previousThinkingNodeId = shouldChainFromPreviousToolResult
284
+ ? `thinking_${rootId}_round${assistantMessageCount}`
285
+ : undefined;
286
+ // Get messages from conversation history
287
+ const conversationMessages = historyMessages;
288
+ this.logger.debug('Current conversation messages', {
289
+ round: currentRound,
290
+ messageCount: conversationMessages.length,
291
+ fullHistory: conversationMessages.map((m, index) => ({
292
+ index,
293
+ role: m.role,
294
+ content: m.content?.substring(0, 100),
295
+ hasToolCalls: 'toolCalls' in m ? !!m.toolCalls?.length : false,
296
+ toolCallId: 'toolCallId' in m ? m.toolCallId : undefined,
297
+ toolCallsCount: 'toolCalls' in m ? m.toolCalls?.length : 0
298
+ }))
299
+ });
300
+ // Call beforeProviderCall hook
301
+ await this.callPluginHook('beforeProviderCall', {
302
+ messages: conversationMessages
303
+ });
304
+ this.logger.debug('Sending messages to AI provider', {
305
+ round: currentRound,
306
+ messageCount: conversationMessages.length,
307
+ lastFewMessages: conversationMessages.slice(-5).map(m => ({
308
+ role: m.role,
309
+ content: m.content?.substring(0, 50),
310
+ hasToolCalls: 'toolCalls' in m ? !!m.toolCalls?.length : false,
311
+ toolCallId: 'toolCallId' in m ? m.toolCallId : undefined
312
+ }))
313
+ });
314
+ // Validate required model configuration - use new defaultModel format
315
+ if (!config.defaultModel?.model) {
316
+ throw new Error('Model is required in defaultModel configuration. Please specify a model.');
317
+ }
318
+ if (typeof config.defaultModel.model !== 'string' || config.defaultModel.model.trim() === '') {
319
+ throw new Error('Model must be a non-empty string in defaultModel configuration.');
320
+ }
321
+ // Delegate entire execution to provider
322
+ const availableTools = this.tools.getTools();
323
+ const chatOptions = {
324
+ model: config.defaultModel.model,
325
+ ...(config.defaultModel.maxTokens !== undefined && { maxTokens: config.defaultModel.maxTokens }),
326
+ ...(config.defaultModel.temperature !== undefined && { temperature: config.defaultModel.temperature }),
327
+ ...(availableTools.length > 0 && { tools: availableTools })
328
+ };
329
+ // Emit assistant message start event for each thinking phase.
330
+ // Absolute path-only: the path tail must be the thinking node id for this round.
331
+ this.emitWithContext(EXECUTION_EVENTS.ASSISTANT_MESSAGE_START, {
332
+ parameters: {
333
+ round: currentRound,
334
+ messageCount: conversationMessages.length
335
+ },
336
+ metadata: {
337
+ round: currentRound,
338
+ thinkingNodeId
339
+ }
340
+ }, () => this.buildThinkingOwnerContext(rootId, executionId, thinkingNodeId, previousThinkingNodeId), ctx => {
341
+ if (!ctx.ownerType || !ctx.ownerId) {
342
+ throw new Error('[EXECUTION] Missing owner context for thinking event');
343
+ }
344
+ return bindWithOwnerPath(this.baseEventService, {
345
+ ownerType: ctx.ownerType,
346
+ ownerId: ctx.ownerId,
347
+ ownerPath: ctx.ownerPath
348
+ });
349
+ });
350
+ const response = await provider.chat(conversationMessages, chatOptions);
351
+ const assistantToolCallsFromResponse = response.role === 'assistant'
352
+ ? response.toolCalls
353
+ : undefined;
354
+ if (typeof response.content !== 'string') {
355
+ throw new Error('[EXECUTION] Provider response content is required');
356
+ }
357
+ if (assistantToolCallsFromResponse && !Array.isArray(assistantToolCallsFromResponse)) {
358
+ throw new Error('[EXECUTION] assistant toolCalls must be an array');
359
+ }
360
+ this.logger.debug(`🤖 [ROUND-${currentRound}] Provider response completed`, {
361
+ executionId,
362
+ conversationId: fullContext.conversationId,
363
+ round: currentRound,
364
+ responseLength: response.content.length,
365
+ hasToolCalls: Array.isArray(assistantToolCallsFromResponse) && assistantToolCallsFromResponse.length > 0,
366
+ toolCallsCount: Array.isArray(assistantToolCallsFromResponse) ? assistantToolCallsFromResponse.length : 0
367
+ });
368
+ // Call afterProviderCall hook
369
+ await this.callPluginHook('afterProviderCall', {
370
+ messages: conversationMessages,
371
+ responseMessage: response
372
+ });
373
+ // Add assistant response to history
374
+ // Response from AI provider should always be assistant message
375
+ if (response.role !== 'assistant') {
376
+ throw new Error(`Unexpected response role: ${response.role}`);
377
+ }
378
+ const assistantResponse = response;
379
+ if (typeof assistantResponse.content !== 'string') {
380
+ throw new Error('[EXECUTION] assistant response content is required');
381
+ }
382
+ const assistantToolCalls = assistantResponse.toolCalls ?? [];
383
+ if (!Array.isArray(assistantToolCalls)) {
384
+ throw new Error('[EXECUTION] assistantResponse.toolCalls must be an array');
385
+ }
386
+ conversationSession.addAssistantMessage(assistantResponse.content, assistantToolCalls, {
387
+ round: currentRound,
388
+ ...(assistantResponse.metadata?.['usage'] && { usage: assistantResponse.metadata['usage'] })
389
+ });
390
+ this.logger.debug(`[RULE-9-DEBUG] Round ${currentRound} response check: toolCalls=${assistantToolCalls.length}`, {
391
+ round: currentRound,
392
+ hasToolCalls: assistantToolCalls.length > 0,
393
+ toolCallsLength: assistantToolCalls.length,
394
+ responseContent: assistantResponse.content.substring(0, 100) + '...'
395
+ });
396
+ // [ROUND2-DEBUG] Extra diagnostics for Round 2 response
397
+ if (currentRound === 2) {
398
+ this.logger.info(`🔍 [ROUND2-DEBUG] Round 2 AI Response for agent ${fullContext.conversationId}:`);
399
+ this.logger.info(`🔍 [ROUND2-DEBUG] - Content: ${assistantResponse.content.substring(0, 200)}...`);
400
+ this.logger.info(`🔍 [ROUND2-DEBUG] - Tool Calls: ${assistantToolCalls.length}`);
401
+ if (assistantToolCalls.length > 0) {
402
+ this.logger.info(`🔍 [ROUND2-DEBUG] - Tool Call Details: ${JSON.stringify(assistantToolCalls.map(tc => ({ id: tc.id, name: tc.function?.name })))}`);
403
+ }
404
+ }
405
+ if (assistantToolCalls.length === 0) {
406
+ // No tools to execute, we're done
407
+ this.logger.info(`🔄 [ROUND-DEBUG] Round ${currentRound} ENDING - no tool calls for agent ${fullContext.conversationId}`);
408
+ this.logger.debug(`[AGENT-FLOW-CONTROL] Round ${currentRound} completed - no tool calls, execution finished for agent ${fullContext.conversationId}`);
409
+ // [VERIFICATION] Validate ExecutionService flow-control logic
410
+ this.logger.info(`🔍 [EXECUTION-VERIFICATION] Agent ${fullContext.conversationId} - Round ${currentRound} - No tool calls detected`);
411
+ this.logger.info(`🔍 [EXECUTION-VERIFICATION] ExecutionContext exists: ${!!this.executionContext}`);
412
+ if (this.executionContext) {
413
+ this.logger.info(`🔍 [EXECUTION-VERIFICATION] Parent ID: ${this.executionContext.parentExecutionId}`);
414
+ this.logger.info(`🔍 [EXECUTION-VERIFICATION] Execution Level: ${this.executionContext.executionLevel}`);
415
+ }
416
+ // [EVENT-ORTHODOXY] Emit events consistently; do not conditionally suppress emission.
417
+ // The handler decides whether to process the event based on context.
418
+ this.logger.info(`🔧 [EVENT-ORTHODOXY] Emitting assistant_message_complete for Round ${currentRound} completion (no tool calls)`);
419
+ if (typeof assistantResponse.content !== 'string' || assistantResponse.content.length === 0) {
420
+ throw new Error('[EXECUTION] assistant response content is required');
421
+ }
422
+ if (!(assistantResponse.timestamp instanceof Date)) {
423
+ throw new Error('[EXECUTION] assistant response timestamp is required');
424
+ }
425
+ const responseContent = assistantResponse.content;
426
+ const responseStartTime = assistantResponse.timestamp;
427
+ const responseDuration = new Date().getTime() - responseStartTime.getTime();
428
+ this.emitWithContext(EXECUTION_EVENTS.ASSISTANT_MESSAGE_COMPLETE, {
429
+ parameters: {
430
+ assistantMessage: responseContent,
431
+ responseLength: responseContent.length,
432
+ wordCount: responseContent.split(/\s+/).filter(word => word.length > 0).length,
433
+ responseTime: responseDuration,
434
+ contentPreview: responseContent.length > 200
435
+ ? responseContent.substring(0, 200) + '...'
436
+ : responseContent
437
+ },
438
+ result: {
439
+ success: true,
440
+ data: responseContent.substring(0, 100) + '...',
441
+ fullResponse: responseContent,
442
+ responseMetrics: {
443
+ length: responseContent.length,
444
+ estimatedReadTime: Math.ceil(responseContent.split(/\s+/).length / 200),
445
+ hasCodeBlocks: /```/.test(responseContent),
446
+ hasLinks: /https?:\/\//.test(responseContent),
447
+ complexity: responseContent.length > 1000 ? 'high' : responseContent.length > 300 ? 'medium' : 'low'
448
+ }
449
+ },
450
+ metadata: {
451
+ executionId,
452
+ round: currentRound,
453
+ completed: true,
454
+ reason: 'no_tool_calls',
455
+ responseCharacteristics: {
456
+ hasQuestions: responseContent.includes('?'),
457
+ isError: /error|fail|wrong/i.test(responseContent),
458
+ isComplete: /complete|done|finish/i.test(responseContent),
459
+ containsNumbers: /\d/.test(responseContent)
460
+ }
461
+ }
462
+ }, () => this.buildResponseOwnerContext(rootId, executionId, thinkingNodeId, previousThinkingNodeId), ctx => {
463
+ if (!ctx.ownerType || !ctx.ownerId) {
464
+ throw new Error('[EXECUTION] Missing owner context for response event');
465
+ }
466
+ return bindWithOwnerPath(this.baseEventService, {
467
+ ownerType: ctx.ownerType,
468
+ ownerId: ctx.ownerId,
469
+ ownerPath: ctx.ownerPath
470
+ });
471
+ });
472
+ this.logger.info(`🔍 [EXECUTION-VERIFICATION] Breaking execution loop - should prevent Round ${currentRound + 1}`);
473
+ break;
474
+ }
475
+ else {
476
+ // Tools are triggered in this round. Do not emit assistant_message_complete yet.
477
+ // Completion will be emitted when a subsequent assistant turn finishes without tool calls.
478
+ }
479
+ // [ROUND-DEBUG] Continue round: tool calls present
480
+ this.logger.info(`🔄 [ROUND-DEBUG] Round ${currentRound} CONTINUING - ${assistantToolCalls.length} tool calls for agent ${fullContext.conversationId}`);
481
+ this.logger.info(`🔄 [ROUND-DEBUG] Agent instance conversationId=${fullContext.conversationId}`);
482
+ this.logger.debug('Tool calls detected, executing tools', {
483
+ toolCallCount: assistantToolCalls.length,
484
+ round: currentRound,
485
+ toolCalls: assistantToolCalls.map((tc) => ({ id: tc.id, name: tc.function?.name }))
486
+ });
487
+ // Execute tools
488
+ // Ensure proper ID hierarchy for tool execution
489
+ const toolRootId = conversationId;
490
+ const rootForTools = toolRootId;
491
+ // Absolute path-only: tool calls must be children of the thinking node (fork point).
492
+ const toolOwnerPathBase = this.buildThinkingOwnerContext(rootForTools, executionId, thinkingNodeId, previousThinkingNodeId).ownerPath;
493
+ const expectedCountForBatch = assistantToolCalls.length;
494
+ const batchId = `${thinkingNodeId}`;
495
+ const toolRequestsBase = this.toolExecutionService.createExecutionRequestsWithContext(assistantToolCalls, {
496
+ ownerPathBase: toolOwnerPathBase,
497
+ metadataFactory: toolCall => ({
498
+ conversationId: toolRootId,
499
+ round: currentRound,
500
+ directParentId: thinkingNodeId,
501
+ batchId,
502
+ expectedCount: expectedCountForBatch,
503
+ toolCallId: toolCall.id
504
+ })
505
+ });
506
+ const toolRequests = toolRequestsBase.map(request => {
507
+ if (!request.ownerId) {
508
+ throw new Error('[EXECUTION] Tool request missing ownerId');
509
+ }
510
+ return {
511
+ ...request,
512
+ eventService: this.ensureToolEventService(request.ownerId, request.ownerPath),
513
+ baseEventService: this.baseEventService
514
+ };
515
+ });
516
+ const toolContext = {
517
+ requests: toolRequests,
518
+ mode: 'parallel',
519
+ maxConcurrency: 5,
520
+ continueOnError: true
521
+ };
522
+ const toolSummary = await this.toolExecutionService.executeTools(toolContext);
523
+ toolsExecuted.push(...toolSummary.results.map(r => {
524
+ if (!r.toolName || r.toolName.length === 0) {
525
+ throw new Error('[EXECUTION] Tool result missing toolName');
526
+ }
527
+ return r.toolName;
528
+ }));
529
+ // Add tool results to history in the order they were called
530
+ // This ensures proper conversation flow and prevents any duplicate entries
531
+ for (const toolCall of assistantToolCalls) {
532
+ if (!toolCall.id) {
533
+ throw new Error(`Tool call missing ID: ${JSON.stringify(toolCall)}`);
534
+ }
535
+ const toolCallName = toolCall.function?.name;
536
+ if (!toolCallName || toolCallName.length === 0) {
537
+ throw new Error(`[EXECUTION] Tool call "${toolCall.id}" missing function name`);
538
+ }
539
+ // Find the corresponding result for this tool call
540
+ const result = toolSummary.results.find(r => r.executionId === toolCall.id);
541
+ const error = toolSummary.errors.find(e => isExecutionError(e) && e.executionId === toolCall.id);
542
+ let content;
543
+ let metadata = { round: currentRound };
544
+ if (result && result.success) {
545
+ if (typeof result.result === 'undefined') {
546
+ throw new Error('[EXECUTION] Tool result missing result payload');
547
+ }
548
+ content = typeof result.result === 'string'
549
+ ? result.result
550
+ : JSON.stringify(result.result);
551
+ metadata['success'] = true;
552
+ if (result.toolName) {
553
+ metadata['toolName'] = result.toolName;
554
+ }
555
+ }
556
+ else if (result && !result.success) {
557
+ // Tool execution failed (result is still present to preserve deterministic ordering)
558
+ if (!result.error || result.error.length === 0) {
559
+ throw new Error('[EXECUTION] Tool result missing error message');
560
+ }
561
+ content = `Error: ${result.error}`;
562
+ metadata['success'] = false;
563
+ metadata['error'] = result.error;
564
+ if (result.toolName) {
565
+ metadata['toolName'] = result.toolName;
566
+ }
567
+ }
568
+ else if (error) {
569
+ // Tool execution failed
570
+ const execError = error;
571
+ const execMessage = (() => {
572
+ if (execError.error?.message)
573
+ return execError.error.message;
574
+ if (execError.message)
575
+ return execError.message;
576
+ return '';
577
+ })();
578
+ if (!execMessage || execMessage.length === 0) {
579
+ throw new Error('[EXECUTION] Tool execution error missing message');
580
+ }
581
+ content = `Error: ${execMessage}`;
582
+ metadata['success'] = false;
583
+ metadata['error'] = execMessage;
584
+ if (execError.toolName) {
585
+ metadata['toolName'] = execError.toolName;
586
+ }
587
+ }
588
+ else {
589
+ // No result found for this tool call
590
+ throw new Error(`No execution result found for tool call ID: ${toolCall.id}`);
591
+ }
592
+ // Add tool result to conversation history
593
+ // This will throw an error if duplicate toolCallId is detected
594
+ this.logger.debug('Adding tool result to conversation', {
595
+ toolCallId: toolCall.id,
596
+ toolName: toolCallName,
597
+ content: content.substring(0, 100),
598
+ round: currentRound,
599
+ currentHistoryLength: conversationSession.getMessages().length
600
+ });
601
+ conversationSession.addToolMessageWithId(content, toolCall.id, toolCallName, metadata);
602
+ this.logger.debug('Tool result added to history', {
603
+ toolCallId: toolCall.id,
604
+ newHistoryLength: conversationSession.getMessages().length,
605
+ round: currentRound
606
+ });
607
+ }
608
+ // Emit tool results ready (join trigger) and then delivery to LLM
609
+ const toolResultsRootId = rootId;
610
+ const toolCallIds = assistantToolCalls.map(toolCall => {
611
+ if (!toolCall.id || toolCall.id.length === 0) {
612
+ throw new Error('[EXECUTION] Tool call missing id for tool results ready payload');
613
+ }
614
+ return toolCall.id;
615
+ });
616
+ if (toolCallIds.length === 0) {
617
+ throw new Error('[EXECUTION] Tool results ready requires toolCallIds');
618
+ }
619
+ this.emitWithContext(EXECUTION_EVENTS.TOOL_RESULTS_READY, {
620
+ parameters: {
621
+ toolCallIds,
622
+ round: currentRound
623
+ },
624
+ metadata: {
625
+ round: currentRound
626
+ }
627
+ }, () => this.buildThinkingOwnerContext(rootId, executionId, thinkingNodeId, previousThinkingNodeId), ctx => {
628
+ if (!ctx.ownerType || !ctx.ownerId) {
629
+ throw new Error('[EXECUTION] Missing owner context for tool results ready');
630
+ }
631
+ return bindWithOwnerPath(this.baseEventService, {
632
+ ownerType: ctx.ownerType,
633
+ ownerId: ctx.ownerId,
634
+ ownerPath: ctx.ownerPath
635
+ });
636
+ });
637
+ this.emitWithContext(EXECUTION_EVENTS.TOOL_RESULTS_TO_LLM, {
638
+ parameters: {
639
+ toolsExecuted: toolsExecuted.length,
640
+ round: currentRound
641
+ },
642
+ metadata: {
643
+ toolsExecuted: toolSummary.results.map(r => {
644
+ if (!r.toolName || r.toolName.length === 0) {
645
+ throw new Error('[EXECUTION] Tool result missing toolName');
646
+ }
647
+ return r.toolName;
648
+ }),
649
+ round: currentRound
650
+ }
651
+ }, () => this.buildThinkingOwnerContext(toolResultsRootId, executionId, thinkingNodeId, previousThinkingNodeId), ctx => {
652
+ if (!ctx.ownerType || !ctx.ownerId) {
653
+ throw new Error('[EXECUTION] Missing owner context for tool results to llm');
654
+ }
655
+ return bindWithOwnerPath(this.baseEventService, {
656
+ ownerType: ctx.ownerType,
657
+ ownerId: ctx.ownerId,
658
+ ownerPath: ctx.ownerPath
659
+ });
660
+ });
661
+ // Continue to next round - let the AI decide if more tools are needed
662
+ // The AI will see the tool results and can either:
663
+ // 1. Call more tools if needed
664
+ // 2. Provide a final response without tool calls
665
+ this.logger.info(`🔄 [ROUND-DEBUG] Round ${currentRound} COMPLETED - continuing to Round ${currentRound + 1} for agent ${fullContext.conversationId}`);
666
+ }
667
+ // Check if we hit the round limit
668
+ if (currentRound >= maxRounds) {
669
+ this.logger.warn('Maximum execution rounds reached', {
670
+ maxRounds,
671
+ conversationId
672
+ });
673
+ }
674
+ // Get final messages from history
675
+ const finalMessages = conversationSession.getMessages();
676
+ const lastAssistantMessage = finalMessages
677
+ .filter(msg => msg.role === 'assistant')
678
+ .pop();
679
+ if (!lastAssistantMessage || typeof lastAssistantMessage.content !== 'string' || lastAssistantMessage.content.length === 0) {
680
+ throw new Error('[EXECUTION] Final assistant message is required');
681
+ }
682
+ const duration = Date.now() - startTime.getTime();
683
+ const result = {
684
+ response: lastAssistantMessage.content,
685
+ messages: finalMessages.map(msg => {
686
+ if (typeof msg.content !== 'string') {
687
+ throw new Error('[EXECUTION] Message content is required');
688
+ }
689
+ return {
690
+ role: msg.role,
691
+ content: msg.content,
692
+ timestamp: msg.timestamp,
693
+ metadata: msg.metadata,
694
+ ...(msg.role === 'assistant' && 'toolCalls' in msg ? { toolCalls: msg.toolCalls } : {}),
695
+ ...(msg.role === 'tool' && 'toolCallId' in msg ? { toolCallId: msg.toolCallId } : {})
696
+ };
697
+ }),
698
+ executionId,
699
+ duration,
700
+ tokensUsed: finalMessages
701
+ .filter(msg => msg.metadata?.['usage'])
702
+ .reduce((sum, msg) => {
703
+ const usage = msg.metadata?.['usage'];
704
+ if (usage && typeof usage === 'object' && 'totalTokens' in usage) {
705
+ const totalTokens = Number(usage.totalTokens);
706
+ if (Number.isNaN(totalTokens)) {
707
+ throw new Error('[EXECUTION] totalTokens must be a number');
708
+ }
709
+ return sum + totalTokens;
710
+ }
711
+ return sum;
712
+ }, 0),
713
+ toolsExecuted,
714
+ success: true
715
+ };
716
+ // Call afterRun hook on all plugins
717
+ await this.callPluginHook('afterRun', { input, response: result.response, metadata: context?.metadata });
718
+ this.logger.debug('Execution pipeline completed successfully', {
719
+ executionId,
720
+ conversationId,
721
+ duration,
722
+ tokensUsed: result.tokensUsed,
723
+ toolsExecuted: result.toolsExecuted.length,
724
+ rounds: currentRound
725
+ });
726
+ // Emit assistant message complete event
727
+ // execution.assistant_message_complete emission is handled in the main execution loop.
728
+ // Emit execution complete event
729
+ const rootIdComplete = conversationId;
730
+ this.emitExecution(EXECUTION_EVENTS.COMPLETE, {
731
+ result: {
732
+ success: true,
733
+ data: result.response.substring(0, 100) + '...'
734
+ },
735
+ metadata: {
736
+ method: 'execute',
737
+ success: true,
738
+ duration,
739
+ tokensUsed: result.tokensUsed,
740
+ toolsExecuted: result.toolsExecuted
741
+ }
742
+ }, rootIdComplete, executionId);
743
+ return result;
744
+ }
745
+ catch (error) {
746
+ const duration = Date.now() - startTime.getTime();
747
+ // Call onError hook on all plugins
748
+ await this.callPluginHook('onError', {
749
+ error: error,
750
+ executionContext: this.convertExecutionContextToPluginFormat(fullContext)
751
+ });
752
+ this.logger.error('Execution pipeline failed', {
753
+ executionId,
754
+ conversationId,
755
+ duration,
756
+ error: error instanceof Error ? error.message : String(error)
757
+ });
758
+ // Emit execution error event
759
+ this.emitExecution(EXECUTION_EVENTS.ERROR, {
760
+ error: error instanceof Error ? error.message : String(error),
761
+ metadata: {
762
+ method: 'execute',
763
+ success: false,
764
+ duration,
765
+ // Identity/hierarchy fields are derived from EventContext.ownerPath.
766
+ }
767
+ }, conversationId, executionId);
768
+ throw error;
769
+ }
770
+ finally {
771
+ this.resetOwnerPathBases();
772
+ }
773
+ }
774
+ /**
775
+ * Execute with streaming response
776
+ */
777
+ async *executeStream(input, messages, config, context) {
778
+ this.logger.debug('ExecutionService.executeStream called');
779
+ const executionId = this.generateExecutionId();
780
+ const startTime = Date.now();
781
+ if (!context?.conversationId || context.conversationId.length === 0) {
782
+ throw new Error('[EXECUTION] conversationId is required for streaming');
783
+ }
784
+ const streamingConversationId = this.requireConversationId(context, 'streaming');
785
+ this.prepareOwnerPathBases(streamingConversationId);
786
+ try {
787
+ // Create conversation session for this execution
788
+ const conversationSession = this.conversationHistory.getConversationSession(context.conversationId);
789
+ // Add user input to conversation
790
+ if (input) {
791
+ conversationSession.addUserMessage(input, { executionId });
792
+ }
793
+ // Call beforeRun hook on all plugins
794
+ await this.callPluginHook('beforeRun', {
795
+ input,
796
+ ...(context?.metadata ? { metadata: context.metadata } : {})
797
+ });
798
+ // Get current provider info
799
+ const currentInfo = this.aiProviders.getCurrentProvider();
800
+ if (!currentInfo) {
801
+ throw new Error('No AI provider configured');
802
+ }
803
+ // Get actual provider instance
804
+ const provider = this.aiProviders.getProvider(currentInfo.provider);
805
+ if (!provider) {
806
+ throw new Error(`AI provider '${currentInfo.provider}' not found`);
807
+ }
808
+ // Ensure provider has chatStream method (streaming is optional on IAIProvider)
809
+ if (typeof provider.chatStream !== 'function') {
810
+ throw new Error('Provider must have chatStream method to support streaming execution');
811
+ }
812
+ this.logger.debug('ExecutionService calling provider.chatStream');
813
+ // Get conversation messages for provider
814
+ const conversationMessages = conversationSession.getMessages();
815
+ // Create chat options
816
+ const configToolsLength = Array.isArray(config.tools) ? config.tools.length : undefined;
817
+ this.logger.debug('🔍 [EXECUTION-SERVICE] config.tools:', { length: configToolsLength });
818
+ const toolSchemas = this.tools.getTools();
819
+ const toolSchemasLength = Array.isArray(toolSchemas) ? toolSchemas.length : undefined;
820
+ this.logger.debug('🔍 [EXECUTION-SERVICE] this.tools.getTools():', { length: toolSchemasLength });
821
+ this.logger.debug('🔍 [EXECUTION-SERVICE] config.tools exists:', { exists: !!config.tools });
822
+ this.logger.debug('🔍 [EXECUTION-SERVICE] config.tools.length > 0:', { hasTools: config.tools && config.tools.length > 0 });
823
+ const chatOptions = {
824
+ model: config.defaultModel.model,
825
+ ...(config.tools && config.tools.length > 0 && { tools: this.tools.getTools() })
826
+ };
827
+ this.logger.debug('🔍 [EXECUTION-SERVICE] Final chatOptions has tools:', { hasTools: !!chatOptions.tools });
828
+ const chatOptionsToolsLength = Array.isArray(chatOptions.tools) ? chatOptions.tools.length : undefined;
829
+ this.logger.debug('🔍 [EXECUTION-SERVICE] Final chatOptions.tools length:', { length: chatOptionsToolsLength });
830
+ const chatStream = provider.chatStream;
831
+ if (!chatStream) {
832
+ throw new Error('Provider does not support streaming');
833
+ }
834
+ const stream = chatStream.call(provider, conversationMessages, chatOptions);
835
+ let fullResponse = '';
836
+ let toolCalls = [];
837
+ let currentToolCallIndex = -1; // Index of the currently active tool call during streaming
838
+ // Collect streaming chunks and tool calls
839
+ for await (const chunk of stream) {
840
+ if (chunk.content) {
841
+ fullResponse += chunk.content;
842
+ yield { chunk: chunk.content, isComplete: false };
843
+ }
844
+ // Collect tool calls from streaming chunks (type assertion for AssistantMessage)
845
+ if (chunk.role === 'assistant') {
846
+ const assistantChunk = chunk;
847
+ if (Array.isArray(assistantChunk.toolCalls) && assistantChunk.toolCalls.length > 0) {
848
+ // Manage tool call state while streaming
849
+ for (const chunkToolCall of assistantChunk.toolCalls) {
850
+ if (chunkToolCall.id && chunkToolCall.id !== '') {
851
+ // ✅ Tool call id present: start a new tool call
852
+ if (!chunkToolCall.type || chunkToolCall.type.length === 0) {
853
+ throw new Error(`[EXECUTION] Tool call "${chunkToolCall.id}" missing type in stream`);
854
+ }
855
+ if (!chunkToolCall.function?.name || chunkToolCall.function.name.length === 0) {
856
+ throw new Error(`[EXECUTION] Tool call "${chunkToolCall.id}" missing function name in stream`);
857
+ }
858
+ if (typeof chunkToolCall.function.arguments !== 'string') {
859
+ throw new Error(`[EXECUTION] Tool call "${chunkToolCall.id}" missing arguments in stream`);
860
+ }
861
+ currentToolCallIndex = toolCalls.length;
862
+ toolCalls.push({
863
+ id: chunkToolCall.id,
864
+ type: chunkToolCall.type,
865
+ function: {
866
+ name: chunkToolCall.function.name,
867
+ arguments: chunkToolCall.function.arguments
868
+ }
869
+ });
870
+ this.logger.debug(`🆕 [TOOL-STREAM] New tool call started: ${chunkToolCall.id} (${chunkToolCall.function?.name})`);
871
+ }
872
+ else if (currentToolCallIndex >= 0) {
873
+ // ✅ Tool call id missing: append fragments to the current tool call
874
+ const hasNameFragment = typeof chunkToolCall.function?.name === 'string' && chunkToolCall.function.name.length > 0;
875
+ const hasArgumentsFragment = typeof chunkToolCall.function?.arguments === 'string' && chunkToolCall.function.arguments.length > 0;
876
+ if (!hasNameFragment && !hasArgumentsFragment) {
877
+ throw new Error(`[EXECUTION] Tool call fragment missing name/arguments for ${toolCalls[currentToolCallIndex].id}`);
878
+ }
879
+ if (hasNameFragment) {
880
+ toolCalls[currentToolCallIndex].function.name += chunkToolCall.function.name;
881
+ }
882
+ if (hasArgumentsFragment) {
883
+ toolCalls[currentToolCallIndex].function.arguments += chunkToolCall.function.arguments;
884
+ }
885
+ const fragmentPreview = hasArgumentsFragment
886
+ ? chunkToolCall.function.arguments
887
+ : chunkToolCall.function.name;
888
+ this.logger.debug(`📝 [TOOL-STREAM] Adding fragment to tool ${toolCalls[currentToolCallIndex].id}: "${fragmentPreview}"`);
889
+ }
890
+ }
891
+ }
892
+ }
893
+ }
894
+ this.logger.debug('🔥 [EXECUTION-SERVICE-STREAM] Stream completed, toolCalls detected:', { count: toolCalls.length });
895
+ if (typeof fullResponse !== 'string') {
896
+ throw new Error('[EXECUTION] Streaming response content is required');
897
+ }
898
+ conversationSession.addAssistantMessage(fullResponse, toolCalls, { executionId });
899
+ // Execute tools if detected
900
+ if (toolCalls.length > 0) {
901
+ this.logger.debug('🔥 [EXECUTION-SERVICE-STREAM] Executing tools:', { tools: toolCalls.map(tc => tc.function.name) });
902
+ // Execute tools with hierarchical context
903
+ const streamingRootId = streamingConversationId;
904
+ // Generate thinking node ID for streaming mode (direct provision)
905
+ const streamingThinkingNodeId = `thinking_${streamingRootId}_${Date.now()}_${executionId}`;
906
+ const streamingOwnerPathBase = [...this.buildExecutionOwnerContext(streamingRootId, executionId).ownerPath, { type: 'thinking', id: streamingThinkingNodeId }];
907
+ const toolRequests = this.toolExecutionService.createExecutionRequestsWithContext(toolCalls, {
908
+ ownerPathBase: streamingOwnerPathBase
909
+ });
910
+ const toolContext = {
911
+ requests: toolRequests,
912
+ mode: 'parallel',
913
+ maxConcurrency: 5,
914
+ continueOnError: true
915
+ };
916
+ const toolSummary = await this.toolExecutionService.executeTools(toolContext);
917
+ // Add tool results to conversation in the order they were called
918
+ for (const toolCall of toolCalls) {
919
+ if (!toolCall.id) {
920
+ throw new Error('[EXECUTION] Tool call missing id in streaming mode');
921
+ }
922
+ if (!toolCall.function?.name || toolCall.function.name.length === 0) {
923
+ throw new Error(`[EXECUTION] Tool call "${toolCall.id}" missing function name in streaming mode`);
924
+ }
925
+ // Find the corresponding result for this tool call
926
+ const result = toolSummary.results.find(r => r.executionId === toolCall.id);
927
+ const error = toolSummary.errors.find(e => isExecutionError(e) && e.executionId === toolCall.id);
928
+ let content;
929
+ let metadata = { executionId };
930
+ if (result && result.success) {
931
+ if (typeof result.result === 'undefined') {
932
+ throw new Error('[EXECUTION] Tool result missing result payload in streaming mode');
933
+ }
934
+ content = typeof result.result === 'string'
935
+ ? result.result
936
+ : JSON.stringify(result.result);
937
+ metadata['success'] = true;
938
+ if (result.toolName) {
939
+ metadata['toolName'] = result.toolName;
940
+ }
941
+ // Yield tool result as streaming chunk
942
+ yield { chunk: `\n[Tool: ${toolCall.function.name} executed successfully]`, isComplete: false };
943
+ }
944
+ else if (error) {
945
+ // Tool execution failed
946
+ const execError = error;
947
+ const execMessage = (() => {
948
+ if (execError.error?.message)
949
+ return execError.error.message;
950
+ if (execError.message)
951
+ return execError.message;
952
+ return '';
953
+ })();
954
+ if (!execMessage || execMessage.length === 0) {
955
+ throw new Error('[EXECUTION] Tool execution error missing message in streaming mode');
956
+ }
957
+ content = `Error: ${execMessage}`;
958
+ metadata['success'] = false;
959
+ metadata['error'] = execMessage;
960
+ if (execError.toolName) {
961
+ metadata['toolName'] = execError.toolName;
962
+ }
963
+ // Yield error as streaming chunk
964
+ yield { chunk: `\n[Tool: ${toolCall.function.name} failed: ${execMessage}]`, isComplete: false };
965
+ }
966
+ else {
967
+ throw new Error(`[EXECUTION] Missing tool result for tool call "${toolCall.id}" in streaming mode`);
968
+ }
969
+ // Add tool result to conversation history
970
+ conversationSession.addToolMessageWithId(content, toolCall.id, toolCall.function.name, metadata);
971
+ }
972
+ // After all tool responses are emitted and recorded, trigger aggregation join
973
+ const streamingRoot = streamingConversationId;
974
+ const streamingToolCallIds = toolCalls.map(toolCall => {
975
+ if (!toolCall.id || toolCall.id.length === 0) {
976
+ throw new Error('[EXECUTION] Tool call missing id for streaming tool results ready payload');
977
+ }
978
+ return toolCall.id;
979
+ });
980
+ if (streamingToolCallIds.length === 0) {
981
+ throw new Error('[EXECUTION] Tool results ready requires toolCallIds in streaming mode');
982
+ }
983
+ this.emitExecution(EXECUTION_EVENTS.TOOL_RESULTS_READY, {
984
+ parameters: {
985
+ toolCallIds: streamingToolCallIds,
986
+ round: 1
987
+ },
988
+ metadata: {
989
+ toolsExecuted: toolSummary.results.map(r => {
990
+ if (!r.toolName || r.toolName.length === 0) {
991
+ throw new Error('[EXECUTION] Tool result missing toolName');
992
+ }
993
+ return r.toolName;
994
+ }),
995
+ round: 1,
996
+ }
997
+ }, streamingRoot, executionId);
998
+ }
999
+ // Call afterRun hook
1000
+ await this.callPluginHook('afterRun', {
1001
+ input,
1002
+ response: fullResponse,
1003
+ ...(context?.metadata ? { metadata: context.metadata } : {})
1004
+ });
1005
+ yield { chunk: '', isComplete: true };
1006
+ }
1007
+ catch (error) {
1008
+ this.logger.error('ExecutionService streaming execution failed', {
1009
+ error: error instanceof Error ? error.message : String(error),
1010
+ executionTime: Date.now() - startTime
1011
+ });
1012
+ // Call error hook
1013
+ await this.callPluginHook('onError', {
1014
+ input,
1015
+ error: error instanceof Error ? error : new Error(String(error)),
1016
+ ...(context?.metadata ? { metadata: context.metadata } : {})
1017
+ });
1018
+ throw error;
1019
+ }
1020
+ finally {
1021
+ this.resetOwnerPathBases();
1022
+ }
1023
+ }
1024
+ /**
1025
+ * Generate a unique execution ID
1026
+ */
1027
+ generateExecutionId() {
1028
+ return `exec_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
1029
+ }
1030
+ /**
1031
+ * Get execution statistics from plugins
1032
+ */
1033
+ async getStats() {
1034
+ const stats = {
1035
+ pluginCount: this.plugins.length,
1036
+ pluginNames: this.plugins.map(p => p.name),
1037
+ historyStats: this.conversationHistory.getStats()
1038
+ };
1039
+ // Note: Plugin-specific stats are not included here to avoid type conflicts
1040
+ // Plugins can implement their own getStats() method returning their specific stat types
1041
+ return stats;
1042
+ }
1043
+ /**
1044
+ * Clear all plugins
1045
+ */
1046
+ clearPlugins() {
1047
+ this.plugins = [];
1048
+ this.logger.debug('All plugins cleared');
1049
+ }
1050
+ /**
1051
+ * Call a hook method on all plugins that implement it
1052
+ * Handles different hook signatures properly
1053
+ */
1054
+ async callPluginHook(hookName, context) {
1055
+ for (const plugin of this.plugins) {
1056
+ try {
1057
+ // Use type assertion to access the hook methods
1058
+ const pluginWithHooks = plugin;
1059
+ // Call the appropriate hook method with correct parameters
1060
+ switch (hookName) {
1061
+ case 'beforeRun':
1062
+ if (pluginWithHooks.beforeRun && context.input) {
1063
+ await pluginWithHooks.beforeRun(context.input, context.metadata);
1064
+ }
1065
+ break;
1066
+ case 'afterRun':
1067
+ if (pluginWithHooks.afterRun && context.input && context.response) {
1068
+ await pluginWithHooks.afterRun(context.input, context.response, context.metadata);
1069
+ }
1070
+ break;
1071
+ case 'beforeProviderCall':
1072
+ if (pluginWithHooks.beforeProviderCall && context.messages) {
1073
+ await pluginWithHooks.beforeProviderCall(context.messages);
1074
+ }
1075
+ break;
1076
+ case 'afterProviderCall':
1077
+ if (pluginWithHooks.afterProviderCall && context.messages && context.responseMessage) {
1078
+ await pluginWithHooks.afterProviderCall(context.messages, context.responseMessage);
1079
+ }
1080
+ break;
1081
+ case 'onError':
1082
+ if (pluginWithHooks.onError && context.error) {
1083
+ const errorContext = {
1084
+ action: `${EXECUTION_EVENT_PREFIX}.${EXECUTION_EVENTS.ERROR}`,
1085
+ metadata: {}
1086
+ };
1087
+ const executionIdValue = context.executionContext?.['executionId'];
1088
+ if (typeof executionIdValue === 'string' && executionIdValue.length > 0) {
1089
+ errorContext.executionId = executionIdValue;
1090
+ }
1091
+ const sessionIdValue = context.executionContext?.['sessionId'];
1092
+ if (typeof sessionIdValue === 'string' && sessionIdValue.length > 0) {
1093
+ errorContext.sessionId = sessionIdValue;
1094
+ }
1095
+ const userIdValue = context.executionContext?.['userId'];
1096
+ if (typeof userIdValue === 'string' && userIdValue.length > 0) {
1097
+ errorContext.userId = userIdValue;
1098
+ }
1099
+ await pluginWithHooks.onError(context.error, errorContext);
1100
+ }
1101
+ break;
1102
+ }
1103
+ }
1104
+ catch (error) {
1105
+ this.logger.warn('Plugin hook failed', {
1106
+ pluginName: plugin.name,
1107
+ hookName,
1108
+ error: error instanceof Error ? error.message : String(error)
1109
+ });
1110
+ }
1111
+ }
1112
+ }
1113
+ ensureToolEventService(ownerId, ownerPath) {
1114
+ if (isDefaultEventService(this.baseEventService)) {
1115
+ return this.baseEventService;
1116
+ }
1117
+ if (!ownerId) {
1118
+ throw new Error('[EVENT-SERVICE] Missing ownerId for tool event context');
1119
+ }
1120
+ if (!ownerPath || ownerPath.length === 0) {
1121
+ throw new Error('[EVENT-SERVICE] Missing ownerPath for tool event context');
1122
+ }
1123
+ if (this.toolEventServices.has(ownerId)) {
1124
+ return this.toolEventServices.get(ownerId);
1125
+ }
1126
+ const scoped = bindWithOwnerPath(this.baseEventService, {
1127
+ ownerType: TOOL_EVENT_PREFIX,
1128
+ ownerId,
1129
+ ownerPath: ownerPath.map(segment => ({ ...segment })),
1130
+ });
1131
+ this.toolEventServices.set(ownerId, scoped);
1132
+ return scoped;
1133
+ }
1134
+ prepareOwnerPathBases(conversationId) {
1135
+ this.toolEventServices.clear();
1136
+ const ownerPath = [...this.ownerPathBase, { type: 'agent', id: conversationId }];
1137
+ this.agentOwnerPathBase = ownerPath;
1138
+ }
1139
+ resetOwnerPathBases() {
1140
+ this.toolEventServices.clear();
1141
+ this.agentOwnerPathBase = [];
1142
+ }
1143
+ buildBaseOwnerPath(executionContext) {
1144
+ if (!executionContext?.ownerPath?.length) {
1145
+ return [];
1146
+ }
1147
+ return executionContext.ownerPath.map(segment => ({ ...segment }));
1148
+ }
1149
+ buildExecutionOwnerContext(rootId, executionId) {
1150
+ if (!rootId || rootId.length === 0) {
1151
+ throw new Error('[EXECUTION] Missing rootId for execution owner context');
1152
+ }
1153
+ if (!executionId || executionId.length === 0) {
1154
+ throw new Error('[EXECUTION] Missing executionId for execution owner context');
1155
+ }
1156
+ const basePath = this.agentOwnerPathBase.length ? this.agentOwnerPathBase : this.ownerPathBase;
1157
+ const path = [...basePath];
1158
+ if (rootId && !path.some(segment => segment.type === 'agent' && segment.id === rootId)) {
1159
+ path.push({ type: 'agent', id: rootId });
1160
+ }
1161
+ path.push({ type: 'execution', id: executionId });
1162
+ return {
1163
+ ownerType: EXECUTION_EVENT_PREFIX,
1164
+ ownerId: executionId,
1165
+ ownerPath: path
1166
+ };
1167
+ }
1168
+ buildThinkingOwnerContext(rootId, executionId, thinkingNodeId, previousThinkingNodeId) {
1169
+ if (!thinkingNodeId || thinkingNodeId.length === 0) {
1170
+ throw new Error('[EXECUTION] Missing thinkingNodeId for thinking owner context');
1171
+ }
1172
+ const base = this.buildExecutionOwnerContext(rootId, executionId).ownerPath;
1173
+ const path = [...base];
1174
+ if (previousThinkingNodeId) {
1175
+ path.push({ type: 'thinking', id: previousThinkingNodeId });
1176
+ path.push({ type: 'tool_result', id: `tool_result_${previousThinkingNodeId}` });
1177
+ }
1178
+ path.push({ type: 'thinking', id: thinkingNodeId });
1179
+ return {
1180
+ ownerType: EXECUTION_EVENT_PREFIX,
1181
+ ownerId: executionId,
1182
+ ownerPath: path
1183
+ };
1184
+ }
1185
+ buildToolOwnerContext(rootId, executionId, toolCallId) {
1186
+ // Tool calls are always children of a specific thinking phase (fork point).
1187
+ // The caller must provide an ownerPathBase that already includes `{ type: 'thinking', id }`.
1188
+ if (!toolCallId || toolCallId.length === 0) {
1189
+ throw new Error('[EXECUTION] Missing toolCallId for tool owner context');
1190
+ }
1191
+ const base = this.buildExecutionOwnerContext(rootId, executionId).ownerPath;
1192
+ const path = [...base, { type: 'tool', id: toolCallId }];
1193
+ return {
1194
+ ownerType: TOOL_EVENT_PREFIX,
1195
+ ownerId: toolCallId,
1196
+ ownerPath: path
1197
+ };
1198
+ }
1199
+ buildResponseOwnerContext(rootId, executionId, thinkingNodeId, previousThinkingNodeId) {
1200
+ const thinkingPath = this.buildThinkingOwnerContext(rootId, executionId, thinkingNodeId, previousThinkingNodeId).ownerPath;
1201
+ const responseNodeId = `response_${thinkingNodeId}`;
1202
+ const path = [...thinkingPath, { type: 'response', id: responseNodeId }];
1203
+ return {
1204
+ ownerType: EXECUTION_EVENT_PREFIX,
1205
+ ownerId: executionId,
1206
+ ownerPath: path
1207
+ };
1208
+ }
1209
+ emitExecution(eventType, data, rootId, executionId) {
1210
+ this.emitWithContext(eventType, data, () => this.buildExecutionOwnerContext(rootId, executionId), context => {
1211
+ if (!context.ownerType || !context.ownerId) {
1212
+ throw new Error('[EXECUTION] Missing owner context for execution event');
1213
+ }
1214
+ return bindWithOwnerPath(this.baseEventService, {
1215
+ ownerType: context.ownerType,
1216
+ ownerId: context.ownerId,
1217
+ ownerPath: context.ownerPath
1218
+ });
1219
+ });
1220
+ }
1221
+ emitTool(eventType, data, rootId, executionId, toolCallId) {
1222
+ this.emitWithContext(eventType, data, () => this.buildToolOwnerContext(rootId, executionId, toolCallId), context => this.ensureToolEventService(context.ownerId, context.ownerPath));
1223
+ }
1224
+ emitWithContext(eventType, data, buildContext, resolveService) {
1225
+ if (isDefaultEventService(this.baseEventService)) {
1226
+ return;
1227
+ }
1228
+ const context = buildContext();
1229
+ const service = resolveService(context);
1230
+ const payload = {
1231
+ timestamp: new Date(),
1232
+ ...data,
1233
+ };
1234
+ service.emit(eventType, payload, context);
1235
+ }
1236
+ requireConversationId(context, label) {
1237
+ if (!context?.conversationId || context.conversationId.length === 0) {
1238
+ throw new Error(`[EXECUTION] conversationId is required for ${label}`);
1239
+ }
1240
+ return context.conversationId;
1241
+ }
1242
+ /**
1243
+ * Convert IExecutionContext to IPluginContext compatible format
1244
+ */
1245
+ convertExecutionContextToPluginFormat(context) {
1246
+ const conversationId = this.requireConversationId(context, 'plugin-context');
1247
+ const payload = {
1248
+ conversationId: conversationId,
1249
+ executionId: context.executionId,
1250
+ startTime: context.startTime.toISOString(),
1251
+ messageCount: context.messages.length
1252
+ };
1253
+ if (context.sessionId) {
1254
+ payload.sessionId = context.sessionId;
1255
+ }
1256
+ if (context.userId) {
1257
+ payload.userId = context.userId;
1258
+ }
1259
+ return payload;
1260
+ }
1261
+ }
1262
+ //# sourceMappingURL=execution-service.js.map