@falai/agent 0.1.0-alpha2

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 (499) hide show
  1. package/README.md +797 -0
  2. package/dist/cjs/package.json +1 -0
  3. package/dist/cjs/src/adapters/MemoryAdapter.d.ts +47 -0
  4. package/dist/cjs/src/adapters/MemoryAdapter.d.ts.map +1 -0
  5. package/dist/cjs/src/adapters/MemoryAdapter.js +202 -0
  6. package/dist/cjs/src/adapters/MemoryAdapter.js.map +1 -0
  7. package/dist/cjs/src/adapters/MongoAdapter.d.ts +97 -0
  8. package/dist/cjs/src/adapters/MongoAdapter.d.ts.map +1 -0
  9. package/dist/cjs/src/adapters/MongoAdapter.js +168 -0
  10. package/dist/cjs/src/adapters/MongoAdapter.js.map +1 -0
  11. package/dist/cjs/src/adapters/OpenSearchAdapter.d.ts +169 -0
  12. package/dist/cjs/src/adapters/OpenSearchAdapter.d.ts.map +1 -0
  13. package/dist/cjs/src/adapters/OpenSearchAdapter.js +458 -0
  14. package/dist/cjs/src/adapters/OpenSearchAdapter.js.map +1 -0
  15. package/dist/cjs/src/adapters/PostgreSQLAdapter.d.ts +71 -0
  16. package/dist/cjs/src/adapters/PostgreSQLAdapter.d.ts.map +1 -0
  17. package/dist/cjs/src/adapters/PostgreSQLAdapter.js +260 -0
  18. package/dist/cjs/src/adapters/PostgreSQLAdapter.js.map +1 -0
  19. package/dist/cjs/src/adapters/PrismaAdapter.d.ts +115 -0
  20. package/dist/cjs/src/adapters/PrismaAdapter.d.ts.map +1 -0
  21. package/dist/cjs/src/adapters/PrismaAdapter.js +366 -0
  22. package/dist/cjs/src/adapters/PrismaAdapter.js.map +1 -0
  23. package/dist/cjs/src/adapters/RedisAdapter.d.ts +71 -0
  24. package/dist/cjs/src/adapters/RedisAdapter.d.ts.map +1 -0
  25. package/dist/cjs/src/adapters/RedisAdapter.js +231 -0
  26. package/dist/cjs/src/adapters/RedisAdapter.js.map +1 -0
  27. package/dist/cjs/src/adapters/SQLiteAdapter.d.ts +69 -0
  28. package/dist/cjs/src/adapters/SQLiteAdapter.d.ts.map +1 -0
  29. package/dist/cjs/src/adapters/SQLiteAdapter.js +312 -0
  30. package/dist/cjs/src/adapters/SQLiteAdapter.js.map +1 -0
  31. package/dist/cjs/src/adapters/index.d.ts +17 -0
  32. package/dist/cjs/src/adapters/index.d.ts.map +1 -0
  33. package/dist/cjs/src/adapters/index.js +21 -0
  34. package/dist/cjs/src/adapters/index.js.map +1 -0
  35. package/dist/cjs/src/constants/index.d.ts +10 -0
  36. package/dist/cjs/src/constants/index.d.ts.map +1 -0
  37. package/dist/cjs/src/constants/index.js +13 -0
  38. package/dist/cjs/src/constants/index.js.map +1 -0
  39. package/dist/cjs/src/core/Agent.d.ts +232 -0
  40. package/dist/cjs/src/core/Agent.d.ts.map +1 -0
  41. package/dist/cjs/src/core/Agent.js +741 -0
  42. package/dist/cjs/src/core/Agent.js.map +1 -0
  43. package/dist/cjs/src/core/Events.d.ts +26 -0
  44. package/dist/cjs/src/core/Events.d.ts.map +1 -0
  45. package/dist/cjs/src/core/Events.js +144 -0
  46. package/dist/cjs/src/core/Events.js.map +1 -0
  47. package/dist/cjs/src/core/PersistenceManager.d.ts +98 -0
  48. package/dist/cjs/src/core/PersistenceManager.d.ts.map +1 -0
  49. package/dist/cjs/src/core/PersistenceManager.js +261 -0
  50. package/dist/cjs/src/core/PersistenceManager.js.map +1 -0
  51. package/dist/cjs/src/core/PromptComposer.d.ts +27 -0
  52. package/dist/cjs/src/core/PromptComposer.d.ts.map +1 -0
  53. package/dist/cjs/src/core/PromptComposer.js +194 -0
  54. package/dist/cjs/src/core/PromptComposer.js.map +1 -0
  55. package/dist/cjs/src/core/ResponseEngine.d.ts +32 -0
  56. package/dist/cjs/src/core/ResponseEngine.d.ts.map +1 -0
  57. package/dist/cjs/src/core/ResponseEngine.js +202 -0
  58. package/dist/cjs/src/core/ResponseEngine.js.map +1 -0
  59. package/dist/cjs/src/core/ResponseModal.d.ts +222 -0
  60. package/dist/cjs/src/core/ResponseModal.d.ts.map +1 -0
  61. package/dist/cjs/src/core/ResponseModal.js +1588 -0
  62. package/dist/cjs/src/core/ResponseModal.js.map +1 -0
  63. package/dist/cjs/src/core/ResponsePipeline.d.ts +175 -0
  64. package/dist/cjs/src/core/ResponsePipeline.d.ts.map +1 -0
  65. package/dist/cjs/src/core/ResponsePipeline.js +549 -0
  66. package/dist/cjs/src/core/ResponsePipeline.js.map +1 -0
  67. package/dist/cjs/src/core/Route.d.ts +181 -0
  68. package/dist/cjs/src/core/Route.d.ts.map +1 -0
  69. package/dist/cjs/src/core/Route.js +541 -0
  70. package/dist/cjs/src/core/Route.js.map +1 -0
  71. package/dist/cjs/src/core/RoutingEngine.d.ts +159 -0
  72. package/dist/cjs/src/core/RoutingEngine.d.ts.map +1 -0
  73. package/dist/cjs/src/core/RoutingEngine.js +961 -0
  74. package/dist/cjs/src/core/RoutingEngine.js.map +1 -0
  75. package/dist/cjs/src/core/SessionManager.d.ts +94 -0
  76. package/dist/cjs/src/core/SessionManager.d.ts.map +1 -0
  77. package/dist/cjs/src/core/SessionManager.js +239 -0
  78. package/dist/cjs/src/core/SessionManager.js.map +1 -0
  79. package/dist/cjs/src/core/Step.d.ts +170 -0
  80. package/dist/cjs/src/core/Step.d.ts.map +1 -0
  81. package/dist/cjs/src/core/Step.js +448 -0
  82. package/dist/cjs/src/core/Step.js.map +1 -0
  83. package/dist/cjs/src/core/ToolManager.d.ts +234 -0
  84. package/dist/cjs/src/core/ToolManager.d.ts.map +1 -0
  85. package/dist/cjs/src/core/ToolManager.js +1117 -0
  86. package/dist/cjs/src/core/ToolManager.js.map +1 -0
  87. package/dist/cjs/src/index.d.ts +44 -0
  88. package/dist/cjs/src/index.d.ts.map +1 -0
  89. package/dist/cjs/src/index.js +88 -0
  90. package/dist/cjs/src/index.js.map +1 -0
  91. package/dist/cjs/src/providers/AnthropicProvider.d.ts +43 -0
  92. package/dist/cjs/src/providers/AnthropicProvider.d.ts.map +1 -0
  93. package/dist/cjs/src/providers/AnthropicProvider.js +377 -0
  94. package/dist/cjs/src/providers/AnthropicProvider.js.map +1 -0
  95. package/dist/cjs/src/providers/GeminiProvider.d.ts +58 -0
  96. package/dist/cjs/src/providers/GeminiProvider.d.ts.map +1 -0
  97. package/dist/cjs/src/providers/GeminiProvider.js +489 -0
  98. package/dist/cjs/src/providers/GeminiProvider.js.map +1 -0
  99. package/dist/cjs/src/providers/OpenAIProvider.d.ts +52 -0
  100. package/dist/cjs/src/providers/OpenAIProvider.d.ts.map +1 -0
  101. package/dist/cjs/src/providers/OpenAIProvider.js +395 -0
  102. package/dist/cjs/src/providers/OpenAIProvider.js.map +1 -0
  103. package/dist/cjs/src/providers/OpenRouterProvider.d.ts +56 -0
  104. package/dist/cjs/src/providers/OpenRouterProvider.d.ts.map +1 -0
  105. package/dist/cjs/src/providers/OpenRouterProvider.js +409 -0
  106. package/dist/cjs/src/providers/OpenRouterProvider.js.map +1 -0
  107. package/dist/cjs/src/providers/index.d.ts +13 -0
  108. package/dist/cjs/src/providers/index.d.ts.map +1 -0
  109. package/dist/cjs/src/providers/index.js +16 -0
  110. package/dist/cjs/src/providers/index.js.map +1 -0
  111. package/dist/cjs/src/types/agent.d.ts +181 -0
  112. package/dist/cjs/src/types/agent.d.ts.map +1 -0
  113. package/dist/cjs/src/types/agent.js +21 -0
  114. package/dist/cjs/src/types/agent.js.map +1 -0
  115. package/dist/cjs/src/types/ai.d.ts +143 -0
  116. package/dist/cjs/src/types/ai.d.ts.map +1 -0
  117. package/dist/cjs/src/types/ai.js +6 -0
  118. package/dist/cjs/src/types/ai.js.map +1 -0
  119. package/dist/cjs/src/types/history.d.ts +178 -0
  120. package/dist/cjs/src/types/history.d.ts.map +1 -0
  121. package/dist/cjs/src/types/history.js +33 -0
  122. package/dist/cjs/src/types/history.js.map +1 -0
  123. package/dist/cjs/src/types/index.d.ts +22 -0
  124. package/dist/cjs/src/types/index.d.ts.map +1 -0
  125. package/dist/cjs/src/types/index.js +37 -0
  126. package/dist/cjs/src/types/index.js.map +1 -0
  127. package/dist/cjs/src/types/persistence.d.ts +209 -0
  128. package/dist/cjs/src/types/persistence.d.ts.map +1 -0
  129. package/dist/cjs/src/types/persistence.js +7 -0
  130. package/dist/cjs/src/types/persistence.js.map +1 -0
  131. package/dist/cjs/src/types/route.d.ts +238 -0
  132. package/dist/cjs/src/types/route.d.ts.map +1 -0
  133. package/dist/cjs/src/types/route.js +6 -0
  134. package/dist/cjs/src/types/route.js.map +1 -0
  135. package/dist/cjs/src/types/routing.d.ts +16 -0
  136. package/dist/cjs/src/types/routing.d.ts.map +1 -0
  137. package/dist/cjs/src/types/routing.js +3 -0
  138. package/dist/cjs/src/types/routing.js.map +1 -0
  139. package/dist/cjs/src/types/schema.d.ts +22 -0
  140. package/dist/cjs/src/types/schema.d.ts.map +1 -0
  141. package/dist/cjs/src/types/schema.js +3 -0
  142. package/dist/cjs/src/types/schema.js.map +1 -0
  143. package/dist/cjs/src/types/session.d.ts +65 -0
  144. package/dist/cjs/src/types/session.d.ts.map +1 -0
  145. package/dist/cjs/src/types/session.js +6 -0
  146. package/dist/cjs/src/types/session.js.map +1 -0
  147. package/dist/cjs/src/types/template.d.ts +88 -0
  148. package/dist/cjs/src/types/template.d.ts.map +1 -0
  149. package/dist/cjs/src/types/template.js +3 -0
  150. package/dist/cjs/src/types/template.js.map +1 -0
  151. package/dist/cjs/src/types/tool.d.ts +130 -0
  152. package/dist/cjs/src/types/tool.d.ts.map +1 -0
  153. package/dist/cjs/src/types/tool.js +19 -0
  154. package/dist/cjs/src/types/tool.js.map +1 -0
  155. package/dist/cjs/src/utils/clone.d.ts +8 -0
  156. package/dist/cjs/src/utils/clone.d.ts.map +1 -0
  157. package/dist/cjs/src/utils/clone.js +32 -0
  158. package/dist/cjs/src/utils/clone.js.map +1 -0
  159. package/dist/cjs/src/utils/condition.d.ts +38 -0
  160. package/dist/cjs/src/utils/condition.d.ts.map +1 -0
  161. package/dist/cjs/src/utils/condition.js +168 -0
  162. package/dist/cjs/src/utils/condition.js.map +1 -0
  163. package/dist/cjs/src/utils/event.d.ts +6 -0
  164. package/dist/cjs/src/utils/event.d.ts.map +1 -0
  165. package/dist/cjs/src/utils/event.js +20 -0
  166. package/dist/cjs/src/utils/event.js.map +1 -0
  167. package/dist/cjs/src/utils/history.d.ts +60 -0
  168. package/dist/cjs/src/utils/history.d.ts.map +1 -0
  169. package/dist/cjs/src/utils/history.js +274 -0
  170. package/dist/cjs/src/utils/history.js.map +1 -0
  171. package/dist/cjs/src/utils/id.d.ts +25 -0
  172. package/dist/cjs/src/utils/id.d.ts.map +1 -0
  173. package/dist/cjs/src/utils/id.js +70 -0
  174. package/dist/cjs/src/utils/id.js.map +1 -0
  175. package/dist/cjs/src/utils/index.d.ts +15 -0
  176. package/dist/cjs/src/utils/index.d.ts.map +1 -0
  177. package/dist/cjs/src/utils/index.js +64 -0
  178. package/dist/cjs/src/utils/index.js.map +1 -0
  179. package/dist/cjs/src/utils/json.d.ts +16 -0
  180. package/dist/cjs/src/utils/json.d.ts.map +1 -0
  181. package/dist/cjs/src/utils/json.js +47 -0
  182. package/dist/cjs/src/utils/json.js.map +1 -0
  183. package/dist/cjs/src/utils/logger.d.ts +10 -0
  184. package/dist/cjs/src/utils/logger.d.ts.map +1 -0
  185. package/dist/cjs/src/utils/logger.js +23 -0
  186. package/dist/cjs/src/utils/logger.js.map +1 -0
  187. package/dist/cjs/src/utils/retry.d.ts +10 -0
  188. package/dist/cjs/src/utils/retry.d.ts.map +1 -0
  189. package/dist/cjs/src/utils/retry.js +76 -0
  190. package/dist/cjs/src/utils/retry.js.map +1 -0
  191. package/dist/cjs/src/utils/session.d.ts +51 -0
  192. package/dist/cjs/src/utils/session.d.ts.map +1 -0
  193. package/dist/cjs/src/utils/session.js +170 -0
  194. package/dist/cjs/src/utils/session.js.map +1 -0
  195. package/dist/cjs/src/utils/template.d.ts +155 -0
  196. package/dist/cjs/src/utils/template.d.ts.map +1 -0
  197. package/dist/cjs/src/utils/template.js +383 -0
  198. package/dist/cjs/src/utils/template.js.map +1 -0
  199. package/dist/src/adapters/MemoryAdapter.d.ts +47 -0
  200. package/dist/src/adapters/MemoryAdapter.d.ts.map +1 -0
  201. package/dist/src/adapters/MemoryAdapter.js +198 -0
  202. package/dist/src/adapters/MemoryAdapter.js.map +1 -0
  203. package/dist/src/adapters/MongoAdapter.d.ts +97 -0
  204. package/dist/src/adapters/MongoAdapter.d.ts.map +1 -0
  205. package/dist/src/adapters/MongoAdapter.js +164 -0
  206. package/dist/src/adapters/MongoAdapter.js.map +1 -0
  207. package/dist/src/adapters/OpenSearchAdapter.d.ts +169 -0
  208. package/dist/src/adapters/OpenSearchAdapter.d.ts.map +1 -0
  209. package/dist/src/adapters/OpenSearchAdapter.js +454 -0
  210. package/dist/src/adapters/OpenSearchAdapter.js.map +1 -0
  211. package/dist/src/adapters/PostgreSQLAdapter.d.ts +71 -0
  212. package/dist/src/adapters/PostgreSQLAdapter.d.ts.map +1 -0
  213. package/dist/src/adapters/PostgreSQLAdapter.js +256 -0
  214. package/dist/src/adapters/PostgreSQLAdapter.js.map +1 -0
  215. package/dist/src/adapters/PrismaAdapter.d.ts +115 -0
  216. package/dist/src/adapters/PrismaAdapter.d.ts.map +1 -0
  217. package/dist/src/adapters/PrismaAdapter.js +362 -0
  218. package/dist/src/adapters/PrismaAdapter.js.map +1 -0
  219. package/dist/src/adapters/RedisAdapter.d.ts +71 -0
  220. package/dist/src/adapters/RedisAdapter.d.ts.map +1 -0
  221. package/dist/src/adapters/RedisAdapter.js +227 -0
  222. package/dist/src/adapters/RedisAdapter.js.map +1 -0
  223. package/dist/src/adapters/SQLiteAdapter.d.ts +69 -0
  224. package/dist/src/adapters/SQLiteAdapter.d.ts.map +1 -0
  225. package/dist/src/adapters/SQLiteAdapter.js +308 -0
  226. package/dist/src/adapters/SQLiteAdapter.js.map +1 -0
  227. package/dist/src/adapters/index.d.ts +17 -0
  228. package/dist/src/adapters/index.d.ts.map +1 -0
  229. package/dist/src/adapters/index.js +11 -0
  230. package/dist/src/adapters/index.js.map +1 -0
  231. package/dist/src/constants/index.d.ts +10 -0
  232. package/dist/src/constants/index.d.ts.map +1 -0
  233. package/dist/src/constants/index.js +10 -0
  234. package/dist/src/constants/index.js.map +1 -0
  235. package/dist/src/core/Agent.d.ts +232 -0
  236. package/dist/src/core/Agent.d.ts.map +1 -0
  237. package/dist/src/core/Agent.js +737 -0
  238. package/dist/src/core/Agent.js.map +1 -0
  239. package/dist/src/core/Events.d.ts +26 -0
  240. package/dist/src/core/Events.d.ts.map +1 -0
  241. package/dist/src/core/Events.js +137 -0
  242. package/dist/src/core/Events.js.map +1 -0
  243. package/dist/src/core/PersistenceManager.d.ts +98 -0
  244. package/dist/src/core/PersistenceManager.d.ts.map +1 -0
  245. package/dist/src/core/PersistenceManager.js +257 -0
  246. package/dist/src/core/PersistenceManager.js.map +1 -0
  247. package/dist/src/core/PromptComposer.d.ts +27 -0
  248. package/dist/src/core/PromptComposer.d.ts.map +1 -0
  249. package/dist/src/core/PromptComposer.js +190 -0
  250. package/dist/src/core/PromptComposer.js.map +1 -0
  251. package/dist/src/core/ResponseEngine.d.ts +32 -0
  252. package/dist/src/core/ResponseEngine.d.ts.map +1 -0
  253. package/dist/src/core/ResponseEngine.js +198 -0
  254. package/dist/src/core/ResponseEngine.js.map +1 -0
  255. package/dist/src/core/ResponseModal.d.ts +222 -0
  256. package/dist/src/core/ResponseModal.d.ts.map +1 -0
  257. package/dist/src/core/ResponseModal.js +1583 -0
  258. package/dist/src/core/ResponseModal.js.map +1 -0
  259. package/dist/src/core/ResponsePipeline.d.ts +175 -0
  260. package/dist/src/core/ResponsePipeline.d.ts.map +1 -0
  261. package/dist/src/core/ResponsePipeline.js +545 -0
  262. package/dist/src/core/ResponsePipeline.js.map +1 -0
  263. package/dist/src/core/Route.d.ts +181 -0
  264. package/dist/src/core/Route.d.ts.map +1 -0
  265. package/dist/src/core/Route.js +537 -0
  266. package/dist/src/core/Route.js.map +1 -0
  267. package/dist/src/core/RoutingEngine.d.ts +159 -0
  268. package/dist/src/core/RoutingEngine.d.ts.map +1 -0
  269. package/dist/src/core/RoutingEngine.js +957 -0
  270. package/dist/src/core/RoutingEngine.js.map +1 -0
  271. package/dist/src/core/SessionManager.d.ts +94 -0
  272. package/dist/src/core/SessionManager.d.ts.map +1 -0
  273. package/dist/src/core/SessionManager.js +235 -0
  274. package/dist/src/core/SessionManager.js.map +1 -0
  275. package/dist/src/core/Step.d.ts +170 -0
  276. package/dist/src/core/Step.d.ts.map +1 -0
  277. package/dist/src/core/Step.js +444 -0
  278. package/dist/src/core/Step.js.map +1 -0
  279. package/dist/src/core/ToolManager.d.ts +234 -0
  280. package/dist/src/core/ToolManager.d.ts.map +1 -0
  281. package/dist/src/core/ToolManager.js +1111 -0
  282. package/dist/src/core/ToolManager.js.map +1 -0
  283. package/dist/src/index.d.ts +44 -0
  284. package/dist/src/index.d.ts.map +1 -0
  285. package/dist/src/index.js +37 -0
  286. package/dist/src/index.js.map +1 -0
  287. package/dist/src/providers/AnthropicProvider.d.ts +43 -0
  288. package/dist/src/providers/AnthropicProvider.d.ts.map +1 -0
  289. package/dist/src/providers/AnthropicProvider.js +370 -0
  290. package/dist/src/providers/AnthropicProvider.js.map +1 -0
  291. package/dist/src/providers/GeminiProvider.d.ts +58 -0
  292. package/dist/src/providers/GeminiProvider.d.ts.map +1 -0
  293. package/dist/src/providers/GeminiProvider.js +485 -0
  294. package/dist/src/providers/GeminiProvider.js.map +1 -0
  295. package/dist/src/providers/OpenAIProvider.d.ts +52 -0
  296. package/dist/src/providers/OpenAIProvider.d.ts.map +1 -0
  297. package/dist/src/providers/OpenAIProvider.js +388 -0
  298. package/dist/src/providers/OpenAIProvider.js.map +1 -0
  299. package/dist/src/providers/OpenRouterProvider.d.ts +56 -0
  300. package/dist/src/providers/OpenRouterProvider.d.ts.map +1 -0
  301. package/dist/src/providers/OpenRouterProvider.js +402 -0
  302. package/dist/src/providers/OpenRouterProvider.js.map +1 -0
  303. package/dist/src/providers/index.d.ts +13 -0
  304. package/dist/src/providers/index.d.ts.map +1 -0
  305. package/dist/src/providers/index.js +9 -0
  306. package/dist/src/providers/index.js.map +1 -0
  307. package/dist/src/types/agent.d.ts +181 -0
  308. package/dist/src/types/agent.d.ts.map +1 -0
  309. package/dist/src/types/agent.js +18 -0
  310. package/dist/src/types/agent.js.map +1 -0
  311. package/dist/src/types/ai.d.ts +143 -0
  312. package/dist/src/types/ai.d.ts.map +1 -0
  313. package/dist/src/types/ai.js +5 -0
  314. package/dist/src/types/ai.js.map +1 -0
  315. package/dist/src/types/history.d.ts +178 -0
  316. package/dist/src/types/history.d.ts.map +1 -0
  317. package/dist/src/types/history.js +30 -0
  318. package/dist/src/types/history.js.map +1 -0
  319. package/dist/src/types/index.d.ts +22 -0
  320. package/dist/src/types/index.d.ts.map +1 -0
  321. package/dist/src/types/index.js +12 -0
  322. package/dist/src/types/index.js.map +1 -0
  323. package/dist/src/types/persistence.d.ts +209 -0
  324. package/dist/src/types/persistence.d.ts.map +1 -0
  325. package/dist/src/types/persistence.js +6 -0
  326. package/dist/src/types/persistence.js.map +1 -0
  327. package/dist/src/types/route.d.ts +238 -0
  328. package/dist/src/types/route.d.ts.map +1 -0
  329. package/dist/src/types/route.js +5 -0
  330. package/dist/src/types/route.js.map +1 -0
  331. package/dist/src/types/routing.d.ts +16 -0
  332. package/dist/src/types/routing.d.ts.map +1 -0
  333. package/dist/src/types/routing.js +2 -0
  334. package/dist/src/types/routing.js.map +1 -0
  335. package/dist/src/types/schema.d.ts +22 -0
  336. package/dist/src/types/schema.d.ts.map +1 -0
  337. package/dist/src/types/schema.js +2 -0
  338. package/dist/src/types/schema.js.map +1 -0
  339. package/dist/src/types/session.d.ts +65 -0
  340. package/dist/src/types/session.d.ts.map +1 -0
  341. package/dist/src/types/session.js +5 -0
  342. package/dist/src/types/session.js.map +1 -0
  343. package/dist/src/types/template.d.ts +88 -0
  344. package/dist/src/types/template.d.ts.map +1 -0
  345. package/dist/src/types/template.js +2 -0
  346. package/dist/src/types/template.js.map +1 -0
  347. package/dist/src/types/tool.d.ts +130 -0
  348. package/dist/src/types/tool.d.ts.map +1 -0
  349. package/dist/src/types/tool.js +16 -0
  350. package/dist/src/types/tool.js.map +1 -0
  351. package/dist/src/utils/clone.d.ts +8 -0
  352. package/dist/src/utils/clone.d.ts.map +1 -0
  353. package/dist/src/utils/clone.js +29 -0
  354. package/dist/src/utils/clone.js.map +1 -0
  355. package/dist/src/utils/condition.d.ts +38 -0
  356. package/dist/src/utils/condition.d.ts.map +1 -0
  357. package/dist/src/utils/condition.js +161 -0
  358. package/dist/src/utils/condition.js.map +1 -0
  359. package/dist/src/utils/event.d.ts +6 -0
  360. package/dist/src/utils/event.d.ts.map +1 -0
  361. package/dist/src/utils/event.js +17 -0
  362. package/dist/src/utils/event.js.map +1 -0
  363. package/dist/src/utils/history.d.ts +60 -0
  364. package/dist/src/utils/history.d.ts.map +1 -0
  365. package/dist/src/utils/history.js +263 -0
  366. package/dist/src/utils/history.js.map +1 -0
  367. package/dist/src/utils/id.d.ts +25 -0
  368. package/dist/src/utils/id.d.ts.map +1 -0
  369. package/dist/src/utils/id.js +64 -0
  370. package/dist/src/utils/id.js.map +1 -0
  371. package/dist/src/utils/index.d.ts +15 -0
  372. package/dist/src/utils/index.d.ts.map +1 -0
  373. package/dist/src/utils/index.js +23 -0
  374. package/dist/src/utils/index.js.map +1 -0
  375. package/dist/src/utils/json.d.ts +16 -0
  376. package/dist/src/utils/json.d.ts.map +1 -0
  377. package/dist/src/utils/json.js +43 -0
  378. package/dist/src/utils/json.js.map +1 -0
  379. package/dist/src/utils/logger.d.ts +10 -0
  380. package/dist/src/utils/logger.d.ts.map +1 -0
  381. package/dist/src/utils/logger.js +17 -0
  382. package/dist/src/utils/logger.js.map +1 -0
  383. package/dist/src/utils/retry.d.ts +10 -0
  384. package/dist/src/utils/retry.d.ts.map +1 -0
  385. package/dist/src/utils/retry.js +71 -0
  386. package/dist/src/utils/retry.js.map +1 -0
  387. package/dist/src/utils/session.d.ts +51 -0
  388. package/dist/src/utils/session.d.ts.map +1 -0
  389. package/dist/src/utils/session.js +160 -0
  390. package/dist/src/utils/session.js.map +1 -0
  391. package/dist/src/utils/template.d.ts +155 -0
  392. package/dist/src/utils/template.d.ts.map +1 -0
  393. package/dist/src/utils/template.js +374 -0
  394. package/dist/src/utils/template.js.map +1 -0
  395. package/docs/CONTRIBUTING.md +521 -0
  396. package/docs/README.md +228 -0
  397. package/docs/api/README.md +3258 -0
  398. package/docs/api/overview.md +1134 -0
  399. package/docs/architecture/data-extraction-flow.md +363 -0
  400. package/docs/core/agent/README.md +902 -0
  401. package/docs/core/agent/context-management.md +796 -0
  402. package/docs/core/agent/session-management.md +641 -0
  403. package/docs/core/ai-integration/prompt-composition.md +220 -0
  404. package/docs/core/ai-integration/providers.md +515 -0
  405. package/docs/core/ai-integration/response-processing.md +287 -0
  406. package/docs/core/conversation-flows/data-collection.md +623 -0
  407. package/docs/core/conversation-flows/route-dsl.md +502 -0
  408. package/docs/core/conversation-flows/routes.md +247 -0
  409. package/docs/core/conversation-flows/step-transitions.md +595 -0
  410. package/docs/core/conversation-flows/steps.md +154 -0
  411. package/docs/core/error-handling.md +638 -0
  412. package/docs/core/persistence/adapters.md +255 -0
  413. package/docs/core/persistence/session-storage.md +644 -0
  414. package/docs/core/routing/intelligent-routing.md +466 -0
  415. package/docs/core/tools/tool-definition.md +970 -0
  416. package/docs/core/tools/tool-scoping.md +819 -0
  417. package/docs/guides/advanced-patterns/publishing.md +186 -0
  418. package/docs/guides/error-handling-patterns.md +578 -0
  419. package/docs/guides/getting-started/README.md +696 -0
  420. package/docs/guides/migration/README.md +72 -0
  421. package/docs/guides/migration/flexible-routing-conditions.md +375 -0
  422. package/docs/guides/migration/response-modal-refactor.md +518 -0
  423. package/examples/advanced-patterns/knowledge-based-agent.ts +735 -0
  424. package/examples/advanced-patterns/persistent-onboarding.ts +728 -0
  425. package/examples/advanced-patterns/route-lifecycle-hooks.ts +556 -0
  426. package/examples/advanced-patterns/streaming-responses.ts +578 -0
  427. package/examples/ai-providers/anthropic-integration.ts +388 -0
  428. package/examples/ai-providers/openai-integration.ts +228 -0
  429. package/examples/condition-patterns/function-only-conditions.ts +365 -0
  430. package/examples/condition-patterns/mixed-array-conditions.ts +477 -0
  431. package/examples/condition-patterns/route-skipif-patterns.ts +468 -0
  432. package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
  433. package/examples/condition-patterns/string-only-conditions.ts +296 -0
  434. package/examples/conversation-flows/completion-transitions.ts +318 -0
  435. package/examples/core-concepts/basic-agent.ts +503 -0
  436. package/examples/core-concepts/modern-streaming-api.ts +309 -0
  437. package/examples/core-concepts/schema-driven-extraction.ts +332 -0
  438. package/examples/core-concepts/session-management.ts +494 -0
  439. package/examples/integrations/database-integration.ts +630 -0
  440. package/examples/integrations/healthcare-integration.ts +595 -0
  441. package/examples/integrations/search-integration.ts +530 -0
  442. package/examples/integrations/server-session-management.ts +307 -0
  443. package/examples/persistence/custom-adapter.ts +529 -0
  444. package/examples/persistence/database-persistence.ts +583 -0
  445. package/examples/persistence/memory-sessions.ts +495 -0
  446. package/examples/persistence/prisma-schema.example.prisma +74 -0
  447. package/examples/persistence/redis-persistence.ts +488 -0
  448. package/examples/tools/basic-tools.ts +765 -0
  449. package/examples/tools/data-enrichment-tools.ts +593 -0
  450. package/package.json +125 -0
  451. package/src/adapters/MemoryAdapter.ts +273 -0
  452. package/src/adapters/MongoAdapter.ts +304 -0
  453. package/src/adapters/OpenSearchAdapter.ts +670 -0
  454. package/src/adapters/PostgreSQLAdapter.ts +428 -0
  455. package/src/adapters/PrismaAdapter.ts +553 -0
  456. package/src/adapters/RedisAdapter.ts +377 -0
  457. package/src/adapters/SQLiteAdapter.ts +459 -0
  458. package/src/adapters/index.ts +43 -0
  459. package/src/constants/index.ts +10 -0
  460. package/src/core/Agent.ts +970 -0
  461. package/src/core/Events.ts +164 -0
  462. package/src/core/PersistenceManager.ts +353 -0
  463. package/src/core/PromptComposer.ts +253 -0
  464. package/src/core/ResponseEngine.ts +306 -0
  465. package/src/core/ResponseModal.ts +2050 -0
  466. package/src/core/ResponsePipeline.ts +864 -0
  467. package/src/core/Route.ts +677 -0
  468. package/src/core/RoutingEngine.ts +1396 -0
  469. package/src/core/SessionManager.ts +297 -0
  470. package/src/core/Step.ts +593 -0
  471. package/src/core/ToolManager.ts +1394 -0
  472. package/src/index.ts +155 -0
  473. package/src/providers/AnthropicProvider.ts +560 -0
  474. package/src/providers/GeminiProvider.ts +683 -0
  475. package/src/providers/OpenAIProvider.ts +602 -0
  476. package/src/providers/OpenRouterProvider.ts +613 -0
  477. package/src/providers/index.ts +16 -0
  478. package/src/types/agent.ts +196 -0
  479. package/src/types/ai.ts +158 -0
  480. package/src/types/history.ts +206 -0
  481. package/src/types/index.ts +119 -0
  482. package/src/types/persistence.ts +251 -0
  483. package/src/types/route.ts +272 -0
  484. package/src/types/routing.ts +18 -0
  485. package/src/types/schema.ts +23 -0
  486. package/src/types/session.ts +74 -0
  487. package/src/types/template.ts +104 -0
  488. package/src/types/tool.ts +174 -0
  489. package/src/utils/clone.ts +34 -0
  490. package/src/utils/condition.ts +190 -0
  491. package/src/utils/event.ts +16 -0
  492. package/src/utils/history.ts +306 -0
  493. package/src/utils/id.ts +73 -0
  494. package/src/utils/index.ts +69 -0
  495. package/src/utils/json.ts +46 -0
  496. package/src/utils/logger.ts +19 -0
  497. package/src/utils/retry.ts +97 -0
  498. package/src/utils/session.ts +204 -0
  499. package/src/utils/template.ts +444 -0
@@ -0,0 +1,1588 @@
1
+ "use strict";
2
+ /**
3
+ * ResponseModal handles all response generation logic for the Agent
4
+ * Provides both streaming and non-streaming response generation with unified logic
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ResponseModal = exports.ResponseGenerationError = void 0;
8
+ const types_1 = require("../types");
9
+ const Step_1 = require("./Step");
10
+ const ResponseEngine_1 = require("./ResponseEngine");
11
+ const ResponsePipeline_1 = require("./ResponsePipeline");
12
+ const utils_1 = require("../utils");
13
+ const template_1 = require("../utils/template");
14
+ const constants_1 = require("../constants");
15
+ /**
16
+ * Error class for response generation failures
17
+ */
18
+ class ResponseGenerationError extends Error {
19
+ constructor(message, details) {
20
+ super(message);
21
+ this.details = details;
22
+ this.name = 'ResponseGenerationError';
23
+ // Preserve stack trace from original error if available
24
+ if (details?.originalError instanceof Error && details.originalError.stack) {
25
+ this.stack = `${this.stack}\nCaused by: ${details.originalError.stack}`;
26
+ }
27
+ }
28
+ /**
29
+ * Create a ResponseGenerationError from an unknown error
30
+ */
31
+ static fromError(error, phase, params, context) {
32
+ const message = error instanceof Error ? error.message : String(error);
33
+ return new ResponseGenerationError(`Response generation failed in ${phase}: ${message}`, { originalError: error, params, phase, context });
34
+ }
35
+ /**
36
+ * Check if an error is a ResponseGenerationError
37
+ */
38
+ static isResponseGenerationError(error) {
39
+ return error instanceof ResponseGenerationError;
40
+ }
41
+ }
42
+ exports.ResponseGenerationError = ResponseGenerationError;
43
+ /**
44
+ * ResponseModal class that encapsulates all response generation logic
45
+ * Uses unified approach for both streaming and non-streaming responses
46
+ */
47
+ class ResponseModal {
48
+ constructor(agent, options) {
49
+ this.agent = agent;
50
+ this.options = options;
51
+ // Initialize response engine
52
+ this.responseEngine = new ResponseEngine_1.ResponseEngine();
53
+ // Initialize response pipeline with agent dependencies
54
+ this.responsePipeline = new ResponsePipeline_1.ResponsePipeline(this.agent.getAgentOptions(), () => this.agent.getRoutes(), // Pass a function to get routes dynamically
55
+ this.agent.getTools(), this.agent.getRoutingEngine(), this.agent.updateContext.bind(this.agent), this.agent.getUpdateDataMethod(), this.agent.updateCollectedData.bind(this.agent), this.getToolManager());
56
+ }
57
+ /**
58
+ * Generate a non-streaming response using unified logic
59
+ */
60
+ async respond(params) {
61
+ try {
62
+ // Use unified response preparation and routing
63
+ const responseContext = await this.prepareUnifiedResponseContext(params);
64
+ // Generate response using unified logic
65
+ const result = await this.generateUnifiedResponse(responseContext);
66
+ // Finalize session
67
+ await this.finalizeSession(result.session, responseContext.effectiveContext);
68
+ return result;
69
+ }
70
+ catch (error) {
71
+ throw new ResponseGenerationError(`Failed to generate response: ${error instanceof Error ? error.message : String(error)}`, { originalError: error, params, phase: 'response_generation' });
72
+ }
73
+ }
74
+ /**
75
+ * Generate a streaming response using unified logic
76
+ */
77
+ async *respondStream(params) {
78
+ try {
79
+ // Use unified response preparation and routing
80
+ const responseContext = await this.prepareUnifiedResponseContext(params);
81
+ // Generate streaming response using unified logic
82
+ yield* this.generateUnifiedStreamingResponse(responseContext);
83
+ }
84
+ catch (error) {
85
+ // Stream error to caller
86
+ yield {
87
+ delta: "",
88
+ accumulated: "",
89
+ done: true,
90
+ session: params.session || await this.agent.session.getOrCreate(),
91
+ error: new ResponseGenerationError(`Streaming response failed: ${error instanceof Error ? error.message : String(error)}`, { originalError: error, params, phase: 'streaming' }),
92
+ };
93
+ }
94
+ }
95
+ /**
96
+ * Modern streaming API - simple interface like chat()
97
+ */
98
+ async *stream(message, options) {
99
+ // Determine which history to use
100
+ let history;
101
+ if (options?.history) {
102
+ // Use provided history for this response only
103
+ history = options.history;
104
+ }
105
+ else {
106
+ // Add user message to session history if provided
107
+ if (message) {
108
+ await this.agent.session.addMessage("user", message);
109
+ }
110
+ history = this.agent.session.getHistory();
111
+ }
112
+ // Get or create session
113
+ let session = await this.agent.session.getOrCreate();
114
+ // Merge agent's collected data into session (agent data takes precedence)
115
+ const collectedData = this.agent.getCollectedData();
116
+ if (Object.keys(collectedData).length > 0) {
117
+ session = (0, utils_1.mergeCollected)(session, collectedData);
118
+ // Update the session manager with the merged data
119
+ await this.agent.session.setData(collectedData);
120
+ utils_1.logger.debug("[ResponseModal] Merged agent collected data into stream session:", collectedData);
121
+ }
122
+ // Stream response using existing respondStream method
123
+ let finalMessage = "";
124
+ for await (const chunk of this.respondStream({
125
+ history,
126
+ session,
127
+ contextOverride: options?.contextOverride,
128
+ signal: options?.signal,
129
+ })) {
130
+ // Accumulate the final message for session history
131
+ if (chunk.done) {
132
+ finalMessage = chunk.accumulated;
133
+ }
134
+ yield chunk;
135
+ }
136
+ // Add agent response to session history (only if not using override history)
137
+ if (!options?.history && finalMessage) {
138
+ await this.agent.session.addMessage("assistant", finalMessage);
139
+ }
140
+ }
141
+ /**
142
+ * Modern non-streaming API - equivalent to chat() but more explicit
143
+ */
144
+ async generate(message, options) {
145
+ // Determine which history to use
146
+ let history;
147
+ if (options?.history) {
148
+ // Use provided history for this response only
149
+ history = options.history;
150
+ }
151
+ else {
152
+ // Add user message to session history if provided
153
+ if (message) {
154
+ await this.agent.session.addMessage("user", message);
155
+ }
156
+ history = this.agent.session.getHistory();
157
+ }
158
+ // Get or create session
159
+ let session = await this.agent.session.getOrCreate();
160
+ // Merge agent's collected data into session (agent data takes precedence)
161
+ const collectedData = this.agent.getCollectedData();
162
+ if (Object.keys(collectedData).length > 0) {
163
+ session = (0, utils_1.mergeCollected)(session, collectedData);
164
+ // Update the session manager with the merged data
165
+ await this.agent.session.setData(collectedData);
166
+ utils_1.logger.debug("[ResponseModal] Merged agent collected data into generate session:", collectedData);
167
+ }
168
+ // Generate response using existing respond method
169
+ const result = await this.respond({
170
+ history,
171
+ session,
172
+ contextOverride: options?.contextOverride,
173
+ signal: options?.signal,
174
+ });
175
+ // Add agent response to session history (only if not using override history)
176
+ if (!options?.history) {
177
+ await this.agent.session.addMessage("assistant", result.message);
178
+ }
179
+ // Ensure the result includes the current session
180
+ return {
181
+ ...result,
182
+ session: result.session || this.agent.session.current,
183
+ };
184
+ }
185
+ /**
186
+ * Get the response engine instance
187
+ * @internal
188
+ */
189
+ getResponseEngine() {
190
+ return this.responseEngine;
191
+ }
192
+ /**
193
+ * Get the response pipeline instance
194
+ * @internal
195
+ */
196
+ getResponsePipeline() {
197
+ return this.responsePipeline;
198
+ }
199
+ /**
200
+ * Get the ToolManager instance from the agent
201
+ * @private
202
+ */
203
+ getToolManager() {
204
+ // Check if agent has a tool property (ToolManager)
205
+ if (this.agent && 'tool' in this.agent && this.agent.tool) {
206
+ return this.agent.tool;
207
+ }
208
+ // Log warning if ToolManager is not available
209
+ utils_1.logger.warn(`[ResponseModal] ToolManager not available on agent - tool execution will use fallback methods`);
210
+ return undefined;
211
+ }
212
+ // UNIFIED RESPONSE LOGIC - Consolidates common logic between streaming and non-streaming
213
+ // ============================================================================
214
+ /**
215
+ * Unified response preparation - handles context setup, session management, and routing
216
+ * This consolidates common logic between streaming and non-streaming responses
217
+ * @private
218
+ */
219
+ async prepareUnifiedResponseContext(params) {
220
+ try {
221
+ const { history: simpleHistory, contextOverride, signal } = params;
222
+ // Validate input parameters
223
+ if (!simpleHistory) {
224
+ throw new ResponseGenerationError('History is required for response generation', { params, phase: 'validation' });
225
+ }
226
+ // Convert HistoryItem[] to Event[] for internal processing
227
+ const historyEvents = (0, utils_1.historyToEvents)(simpleHistory);
228
+ // Keep original HistoryItem[] format for external APIs
229
+ const history = simpleHistory;
230
+ // Use ResponsePipeline for optimized context and session preparation
231
+ // This leverages existing optimizations and avoids code duplication
232
+ let responseContext;
233
+ try {
234
+ // Set current context and session in pipeline for consistency
235
+ this.responsePipeline.setContext(await this.agent.getContext());
236
+ this.responsePipeline.setCurrentSession(this.agent.getCurrentSession());
237
+ responseContext = await this.responsePipeline.prepareResponseContext({
238
+ contextOverride,
239
+ session: params.session ? (0, utils_1.cloneDeep)(params.session) : undefined,
240
+ });
241
+ }
242
+ catch (error) {
243
+ throw ResponseGenerationError.fromError(error, 'pipeline_context_preparation', params);
244
+ }
245
+ const { effectiveContext } = responseContext;
246
+ let session = responseContext.session;
247
+ // Update our stored context if it was modified by beforeRespond hook
248
+ const storedContext = this.responsePipeline.getStoredContext();
249
+ if (storedContext !== undefined) {
250
+ try {
251
+ await this.agent.updateContext(storedContext);
252
+ }
253
+ catch (error) {
254
+ throw ResponseGenerationError.fromError(error, 'context_update_from_pipeline', params, { storedContext });
255
+ }
256
+ }
257
+ // Merge agent's collected data into session (agent data takes precedence)
258
+ const collectedData = this.agent.getCollectedData();
259
+ if (Object.keys(collectedData).length > 0) {
260
+ try {
261
+ session = (0, utils_1.mergeCollected)(session, collectedData);
262
+ utils_1.logger.debug("[ResponseModal] Merged agent collected data into session:", collectedData);
263
+ }
264
+ catch (error) {
265
+ throw ResponseGenerationError.fromError(error, 'data_merging', params, { collectedData });
266
+ }
267
+ }
268
+ // PHASE 1: PREPARE - Execute prepare function if current step has one
269
+ try {
270
+ await this.executeStepPrepare(session, effectiveContext);
271
+ }
272
+ catch (error) {
273
+ throw ResponseGenerationError.fromError(error, 'step_preparation', params, { session, effectiveContext });
274
+ }
275
+ // PHASE 2: ROUTING + STEP SELECTION - Determine which route and step to use
276
+ let routingResult;
277
+ try {
278
+ routingResult = await this.handleUnifiedRoutingAndStepSelection({
279
+ session,
280
+ history: historyEvents,
281
+ context: effectiveContext,
282
+ signal,
283
+ });
284
+ }
285
+ catch (error) {
286
+ throw ResponseGenerationError.fromError(error, 'routing_and_step_selection', params, { session, effectiveContext });
287
+ }
288
+ return {
289
+ effectiveContext,
290
+ session: routingResult.session,
291
+ history,
292
+ selectedRoute: routingResult.selectedRoute,
293
+ selectedStep: routingResult.selectedStep,
294
+ responseDirectives: routingResult.responseDirectives,
295
+ isRouteComplete: routingResult.isRouteComplete,
296
+ };
297
+ }
298
+ catch (error) {
299
+ // Re-throw ResponseGenerationError as-is, wrap others
300
+ if (ResponseGenerationError.isResponseGenerationError(error)) {
301
+ throw error;
302
+ }
303
+ throw ResponseGenerationError.fromError(error, 'preparation', params);
304
+ }
305
+ }
306
+ /**
307
+ * Unified routing and step selection logic using ResponsePipeline for optimization
308
+ * @private
309
+ */
310
+ async handleUnifiedRoutingAndStepSelection(params) {
311
+ try {
312
+ // Use the ResponsePipeline for optimized routing and step selection
313
+ // This avoids duplicate logic and leverages existing optimizations
314
+ // ResponsePipeline expects Event[] for history
315
+ const routingResult = await this.responsePipeline.handleRoutingAndStepSelection({
316
+ session: params.session,
317
+ history: params.history, // Already Event[]
318
+ context: params.context,
319
+ signal: params.signal,
320
+ });
321
+ let updatedSession = routingResult.session;
322
+ let isRouteComplete = routingResult.isRouteComplete;
323
+ // PRE-EXTRACTION: If entering a new route that collects data, extract data from user message first
324
+ // This allows us to skip steps whose data is already provided
325
+ if (routingResult.selectedRoute && !isRouteComplete) {
326
+ const isEnteringNewRoute = !params.session.currentRoute ||
327
+ params.session.currentRoute.id !== routingResult.selectedRoute.id;
328
+ if (isEnteringNewRoute && this.shouldPreExtractData(routingResult.selectedRoute)) {
329
+ utils_1.logger.debug(`[ResponseModal] Pre-extracting data for route: ${routingResult.selectedRoute.title}`);
330
+ const extractedData = await this.preExtractRouteData({
331
+ route: routingResult.selectedRoute,
332
+ history: params.history,
333
+ context: params.context,
334
+ session: updatedSession,
335
+ signal: params.signal,
336
+ });
337
+ if (extractedData && Object.keys(extractedData).length > 0) {
338
+ utils_1.logger.debug(`[ResponseModal] Pre-extracted data:`, extractedData);
339
+ // Update session with pre-extracted data
340
+ updatedSession = (0, utils_1.mergeCollected)(updatedSession, extractedData);
341
+ // Also update agent's collected data
342
+ await this.agent.updateCollectedData(extractedData);
343
+ // Re-check route completion after pre-extraction
344
+ const allRequiredFieldsCollected = routingResult.selectedRoute.isComplete(updatedSession.data || {});
345
+ if (allRequiredFieldsCollected) {
346
+ utils_1.logger.debug(`[ResponseModal] Route ${routingResult.selectedRoute.title} completed after pre-extraction`);
347
+ isRouteComplete = true;
348
+ }
349
+ }
350
+ }
351
+ }
352
+ // Determine next step using pipeline method for consistency
353
+ const stepResult = await this.responsePipeline.determineNextStep({
354
+ selectedRoute: routingResult.selectedRoute,
355
+ selectedStep: routingResult.selectedStep,
356
+ session: updatedSession, // Use updated session with pre-extracted data
357
+ isRouteComplete, // Use updated completion status
358
+ });
359
+ return {
360
+ selectedRoute: routingResult.selectedRoute,
361
+ selectedStep: stepResult.nextStep, // Use the determined next step
362
+ responseDirectives: routingResult.responseDirectives,
363
+ session: stepResult.session,
364
+ isRouteComplete, // Use updated completion status
365
+ };
366
+ }
367
+ catch (error) {
368
+ throw ResponseGenerationError.fromError(error, 'routing_optimization', params);
369
+ }
370
+ }
371
+ /**
372
+ * Check if a route should pre-extract data before determining the initial step
373
+ * @private
374
+ */
375
+ shouldPreExtractData(route) {
376
+ // Pre-extract if route has declared required or optional fields
377
+ if (route.requiredFields && route.requiredFields.length > 0) {
378
+ return true;
379
+ }
380
+ if (route.optionalFields && route.optionalFields.length > 0) {
381
+ return true;
382
+ }
383
+ // Pre-extract if any step in the route collects data
384
+ const steps = route.getAllSteps();
385
+ const hasDataCollectionSteps = steps.some(step => step.collect && step.collect.length > 0);
386
+ return hasDataCollectionSteps;
387
+ }
388
+ /**
389
+ * Pre-extract data from user message when entering a route
390
+ * This allows skipping steps whose data is already provided
391
+ * @private
392
+ */
393
+ async preExtractRouteData(params) {
394
+ const { route, history, context, signal } = params;
395
+ // Build a schema for data extraction based on route's fields
396
+ const extractionSchema = this.agent.getSchema();
397
+ if (!extractionSchema) {
398
+ utils_1.logger.warn(`[ResponseModal] No schema available for pre-extraction`);
399
+ return {};
400
+ }
401
+ // Get last user message
402
+ const lastMessage = (0, utils_1.getLastMessageFromHistory)(history);
403
+ // Build extraction prompt
404
+ const extractionPrompt = [
405
+ `Extract any relevant information from the user's message that matches the following data fields.`,
406
+ `Only extract information that is explicitly stated or clearly implied.`,
407
+ ``,
408
+ `User's message: "${lastMessage}"`,
409
+ ``,
410
+ `Extract data for these fields if present:`,
411
+ ];
412
+ // Add field descriptions
413
+ if (route.requiredFields) {
414
+ extractionPrompt.push(`Required fields: ${route.requiredFields.join(', ')}`);
415
+ }
416
+ if (route.optionalFields) {
417
+ extractionPrompt.push(`Optional fields: ${route.optionalFields.join(', ')}`);
418
+ }
419
+ extractionPrompt.push(``, `Return ONLY the extracted data as JSON. If no data can be extracted, return an empty object {}.`);
420
+ // Call AI to extract data
421
+ const agentOptions = this.agent.getAgentOptions();
422
+ try {
423
+ const result = await agentOptions.provider.generateMessage({
424
+ prompt: extractionPrompt.join('\n'),
425
+ history,
426
+ context,
427
+ signal,
428
+ parameters: {
429
+ jsonSchema: extractionSchema,
430
+ schemaName: 'data_extraction',
431
+ },
432
+ });
433
+ return result.structured || {};
434
+ }
435
+ catch (error) {
436
+ utils_1.logger.error(`[ResponseModal] Pre-extraction failed:`, error);
437
+ return {};
438
+ }
439
+ }
440
+ /**
441
+ * Unified response generation for non-streaming responses
442
+ * @private
443
+ */
444
+ async generateUnifiedResponse(responseContext) {
445
+ const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete } = responseContext;
446
+ let session = initialSession;
447
+ // Get last user message (needed for both route and completion handling)
448
+ // Convert HistoryItem[] to Event[] for internal processing
449
+ const historyEvents = (0, utils_1.historyToEvents)(history);
450
+ const lastMessageText = (0, utils_1.getLastMessageFromHistory)(historyEvents);
451
+ let message;
452
+ let toolCalls = undefined;
453
+ if (selectedRoute && !isRouteComplete) {
454
+ // Handle normal route processing
455
+ const result = await this.processRouteResponse({
456
+ selectedRoute,
457
+ selectedStep,
458
+ responseDirectives,
459
+ session,
460
+ history,
461
+ context: effectiveContext,
462
+ lastMessageText,
463
+ historyEvents,
464
+ signal: responseContext.history ? undefined : undefined, // TODO: Fix signal passing
465
+ });
466
+ message = result.message;
467
+ toolCalls = result.toolCalls;
468
+ session = result.session;
469
+ }
470
+ else if (isRouteComplete && selectedRoute) {
471
+ // Handle route completion
472
+ utils_1.logger.debug(`[ResponseModal] Generating completion message for route: ${selectedRoute.title}`);
473
+ try {
474
+ message = await this.handleRouteCompletion({
475
+ selectedRoute,
476
+ session,
477
+ context: effectiveContext,
478
+ lastMessageText,
479
+ historyEvents,
480
+ signal: undefined, // TODO: Pass signal from responseContext
481
+ });
482
+ // Set step to END_ROUTE marker
483
+ session = (0, utils_1.enterStep)(session, constants_1.END_ROUTE_ID, "Route completed");
484
+ utils_1.logger.debug(`[ResponseModal] Route ${selectedRoute.title} completed. Entered END_ROUTE step.`);
485
+ }
486
+ catch (error) {
487
+ utils_1.logger.error(`[ResponseModal] Error generating completion message:`, error);
488
+ // Fallback to simple completion message
489
+ message = `Thank you! I've recorded all the information for your ${selectedRoute.title.toLowerCase()}.`;
490
+ session = (0, utils_1.enterStep)(session, constants_1.END_ROUTE_ID, "Route completed");
491
+ }
492
+ }
493
+ else {
494
+ // Fallback: No routes defined, generate a simple response
495
+ message = await this.generateFallbackResponse({
496
+ history: historyEvents, // Use Event[] for fallback response
497
+ context: effectiveContext,
498
+ session,
499
+ });
500
+ }
501
+ return {
502
+ message,
503
+ session,
504
+ toolCalls,
505
+ isRouteComplete,
506
+ };
507
+ }
508
+ /**
509
+ * Unified streaming response generation
510
+ * @private
511
+ */
512
+ async *generateUnifiedStreamingResponse(responseContext) {
513
+ const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete } = responseContext;
514
+ const session = initialSession;
515
+ // Get last user message (needed for both route and completion handling)
516
+ // Convert HistoryItem[] to Event[] for internal processing
517
+ const historyEvents = (0, utils_1.historyToEvents)(history);
518
+ const lastMessageText = (0, utils_1.getLastMessageFromHistory)(historyEvents);
519
+ if (selectedRoute && !isRouteComplete) {
520
+ // Handle normal route processing with streaming
521
+ yield* this.processRouteStreamingResponse({
522
+ selectedRoute,
523
+ selectedStep,
524
+ responseDirectives,
525
+ session,
526
+ history,
527
+ context: effectiveContext,
528
+ lastMessageText,
529
+ historyEvents,
530
+ });
531
+ }
532
+ else if (isRouteComplete && selectedRoute) {
533
+ // Handle route completion streaming
534
+ yield* this.streamRouteCompletion({
535
+ selectedRoute,
536
+ session,
537
+ context: effectiveContext,
538
+ lastMessageText,
539
+ historyEvents,
540
+ });
541
+ }
542
+ else {
543
+ // Fallback: No routes defined, stream a simple response
544
+ yield* this.streamFallbackResponse({
545
+ history: historyEvents, // Use Event[] for fallback response
546
+ context: effectiveContext,
547
+ session,
548
+ });
549
+ }
550
+ }
551
+ /**
552
+ * Execute prepare function for current step if available
553
+ * @private
554
+ */
555
+ async executeStepPrepare(session, context) {
556
+ if (session.currentRoute && session.currentStep) {
557
+ const currentRoute = this.agent.getRoutes().find((r) => r.id === session.currentRoute?.id);
558
+ if (currentRoute) {
559
+ const currentStep = currentRoute.getStep(session.currentStep.id);
560
+ if (currentStep?.prepare) {
561
+ utils_1.logger.debug(`[ResponseModal] Executing prepare for step: ${currentStep.id}`);
562
+ await this.executePrepareFinalize(currentStep.prepare, context, session.data, currentRoute, currentStep);
563
+ }
564
+ }
565
+ }
566
+ }
567
+ /**
568
+ * Execute finalize function for current step if available
569
+ * @private
570
+ */
571
+ async executeStepFinalize(session, context) {
572
+ if (session.currentRoute && session.currentStep) {
573
+ const currentRoute = this.agent.getRoutes().find((r) => r.id === session.currentRoute?.id);
574
+ if (currentRoute) {
575
+ const currentStep = currentRoute.getStep(session.currentStep.id);
576
+ if (currentStep?.finalize) {
577
+ utils_1.logger.debug(`[ResponseModal] Executing finalize for step: ${currentStep.id}`);
578
+ await this.executePrepareFinalize(currentStep.finalize, context, session.data, currentRoute, currentStep);
579
+ }
580
+ }
581
+ }
582
+ }
583
+ /**
584
+ * Process route response with unified tool execution and data collection
585
+ * @private
586
+ */
587
+ async processRouteResponse(params) {
588
+ const { selectedRoute, selectedStep, responseDirectives, history, context, lastMessageText, historyEvents, signal } = params;
589
+ let session = params.session;
590
+ // Determine next step
591
+ let nextStep;
592
+ if (selectedStep) {
593
+ nextStep = selectedStep;
594
+ }
595
+ else {
596
+ // Determine current step from session if we're already in this route
597
+ const isInSameRoute = session.currentRoute?.id === selectedRoute.id;
598
+ const currentStep = isInSameRoute && session.currentStep
599
+ ? selectedRoute.getStep(session.currentStep.id)
600
+ : undefined;
601
+ utils_1.logger.debug(`[ResponseModal] Step determination: route match=${isInSameRoute}, currentRoute=${session.currentRoute?.id}, selectedRoute=${selectedRoute.id}, currentStep=${currentStep?.id || 'none'}`);
602
+ // Get candidate steps based on current position in the route
603
+ const routingEngine = this.agent.getRoutingEngine();
604
+ const candidates = await routingEngine.getCandidateStepsWithConditions(selectedRoute, currentStep, // Pass current step instead of undefined to maintain progression
605
+ (0, template_1.createTemplateContext)({ data: session.data, session, context }));
606
+ utils_1.logger.debug(`[ResponseModal] Found ${candidates.length} candidate steps${currentStep ? ' from current step ' + currentStep.id : ' (new route entry)'}`);
607
+ if (candidates.length > 0) {
608
+ nextStep = candidates[0].step;
609
+ utils_1.logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new route'}`);
610
+ }
611
+ else {
612
+ // Fallback to initial step even if it should be skipped
613
+ nextStep = selectedRoute.initialStep;
614
+ utils_1.logger.warn(`[ResponseModal] No valid steps found, using initial step: ${nextStep.id}`);
615
+ }
616
+ }
617
+ // Update session with next step
618
+ session = (0, utils_1.enterStep)(session, nextStep.id, nextStep.description);
619
+ utils_1.logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
620
+ // Build response schema for this route (with collect fields from step)
621
+ const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextStep, this.agent.getSchema());
622
+ // Build response prompt
623
+ const responsePrompt = await this.responseEngine.buildResponsePrompt({
624
+ route: selectedRoute,
625
+ currentStep: nextStep,
626
+ rules: selectedRoute.getRules(),
627
+ prohibitions: selectedRoute.getProhibitions(),
628
+ directives: responseDirectives,
629
+ history: historyEvents, // Use Event[] for buildResponsePrompt
630
+ lastMessage: lastMessageText, // Use string for buildResponsePrompt
631
+ agentOptions: this.agent.getAgentOptions(),
632
+ combinedGuidelines: [...this.agent.getGuidelines(), ...selectedRoute.getGuidelines()],
633
+ combinedTerms: this.mergeTerms(this.agent.getTerms(), selectedRoute.getTerms()),
634
+ context,
635
+ session,
636
+ agentSchema: this.agent.getSchema(),
637
+ });
638
+ // Collect available tools for AI
639
+ const availableTools = this.collectAvailableTools(selectedRoute, nextStep);
640
+ // Generate message using AI provider
641
+ const agentOptions = this.agent.getAgentOptions();
642
+ const result = await agentOptions.provider.generateMessage({
643
+ prompt: responsePrompt,
644
+ history: historyEvents, // Use Event[] for AI provider
645
+ context,
646
+ tools: availableTools,
647
+ signal,
648
+ parameters: responseSchema ? { jsonSchema: responseSchema, schemaName: "response_output" } : undefined,
649
+ });
650
+ let message = result.structured?.message || result.message;
651
+ let toolCalls = result.structured?.toolCalls;
652
+ // Debug: Log initial AI response
653
+ utils_1.logger.debug(`[ResponseModal] Initial AI response:`, {
654
+ hasMessage: !!message,
655
+ messageLength: message?.length || 0,
656
+ hasToolCalls: !!toolCalls,
657
+ toolCallsCount: toolCalls?.length || 0,
658
+ toolNames: toolCalls?.map(tc => tc.toolName) || [],
659
+ });
660
+ // Execute tools with unified loop handling
661
+ const toolResult = await this.executeUnifiedToolLoop({
662
+ toolCalls,
663
+ context,
664
+ session,
665
+ history,
666
+ selectedRoute,
667
+ responsePrompt,
668
+ availableTools,
669
+ responseSchema,
670
+ signal,
671
+ });
672
+ session = toolResult.session;
673
+ toolCalls = toolResult.finalToolCalls;
674
+ if (toolResult.finalMessage) {
675
+ message = toolResult.finalMessage;
676
+ }
677
+ // Collect data from response
678
+ session = await this.collectDataFromResponse({ result, selectedRoute, nextStep, session });
679
+ return { message, toolCalls, session };
680
+ }
681
+ /**
682
+ * Process route streaming response with unified tool execution and data collection
683
+ * @private
684
+ */
685
+ async *processRouteStreamingResponse(params) {
686
+ const { selectedRoute, selectedStep, responseDirectives, history, context, lastMessageText, historyEvents, signal } = params;
687
+ let session = params.session;
688
+ // Determine next step (same logic as non-streaming)
689
+ let nextStep;
690
+ if (selectedStep) {
691
+ nextStep = selectedStep;
692
+ }
693
+ else {
694
+ // Determine current step from session if we're already in this route
695
+ const currentStep = session.currentRoute?.id === selectedRoute.id && session.currentStep
696
+ ? selectedRoute.getStep(session.currentStep.id)
697
+ : undefined;
698
+ // Get candidate steps based on current position in the route
699
+ const routingEngine = this.agent.getRoutingEngine();
700
+ const candidates = await routingEngine.getCandidateStepsWithConditions(selectedRoute, currentStep, // Pass current step instead of undefined to maintain progression
701
+ (0, template_1.createTemplateContext)({ data: session.data, session, context }));
702
+ if (candidates.length > 0) {
703
+ nextStep = candidates[0].step;
704
+ utils_1.logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new route'}`);
705
+ }
706
+ else {
707
+ nextStep = selectedRoute.initialStep;
708
+ utils_1.logger.warn(`[ResponseModal] No valid steps found, using initial step: ${nextStep.id}`);
709
+ }
710
+ }
711
+ // Update session with next step
712
+ session = (0, utils_1.enterStep)(session, nextStep.id, nextStep.description);
713
+ utils_1.logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
714
+ // Build response schema and prompt (same as non-streaming)
715
+ const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextStep, this.agent.getSchema());
716
+ const responsePrompt = await this.responseEngine.buildResponsePrompt({
717
+ route: selectedRoute,
718
+ currentStep: nextStep,
719
+ rules: selectedRoute.getRules(),
720
+ prohibitions: selectedRoute.getProhibitions(),
721
+ directives: responseDirectives,
722
+ history: historyEvents, // Use Event[] for buildResponsePrompt
723
+ lastMessage: lastMessageText, // Use string for buildResponsePrompt
724
+ agentOptions: this.agent.getAgentOptions(),
725
+ combinedGuidelines: [...this.agent.getGuidelines(), ...selectedRoute.getGuidelines()],
726
+ combinedTerms: this.mergeTerms(this.agent.getTerms(), selectedRoute.getTerms()),
727
+ context,
728
+ session,
729
+ agentSchema: this.agent.getSchema(),
730
+ });
731
+ // Collect available tools for AI
732
+ const availableTools = this.collectAvailableTools(selectedRoute, nextStep);
733
+ // Generate message stream using AI provider
734
+ const agentOptions = this.agent.getAgentOptions();
735
+ const stream = agentOptions.provider.generateMessageStream({
736
+ prompt: responsePrompt,
737
+ history: historyEvents, // Use Event[] for AI provider
738
+ context,
739
+ tools: availableTools,
740
+ signal,
741
+ parameters: { jsonSchema: responseSchema, schemaName: "response_stream_output" },
742
+ });
743
+ // Stream chunks with unified tool handling
744
+ for await (const chunk of stream) {
745
+ let toolCalls = undefined;
746
+ // Extract tool calls from AI response on final chunk
747
+ if (chunk.done && chunk.structured?.toolCalls) {
748
+ toolCalls = chunk.structured.toolCalls;
749
+ // Execute tools with unified loop handling
750
+ const toolResult = await this.executeUnifiedToolLoop({
751
+ toolCalls,
752
+ context,
753
+ session,
754
+ history,
755
+ selectedRoute,
756
+ responsePrompt,
757
+ availableTools,
758
+ responseSchema,
759
+ signal,
760
+ });
761
+ session = toolResult.session;
762
+ toolCalls = toolResult.finalToolCalls;
763
+ }
764
+ // Extract collected data on final chunk
765
+ if (chunk.done && chunk.structured && nextStep.collect) {
766
+ session = await this.collectDataFromResponse({
767
+ result: { structured: chunk.structured },
768
+ selectedRoute,
769
+ nextStep,
770
+ session,
771
+ });
772
+ }
773
+ // Handle session finalization on final chunk
774
+ if (chunk.done) {
775
+ await this.finalizeSession(session, context);
776
+ }
777
+ yield {
778
+ delta: chunk.delta,
779
+ accumulated: chunk.accumulated,
780
+ done: chunk.done,
781
+ session,
782
+ toolCalls,
783
+ isRouteComplete: false,
784
+ metadata: chunk.metadata,
785
+ structured: chunk.structured,
786
+ };
787
+ }
788
+ }
789
+ /**
790
+ * Unified tool execution logic with loop handling
791
+ * Consolidates the complex tool execution logic from both streaming and non-streaming responses
792
+ * @private
793
+ */
794
+ async executeUnifiedToolLoop(params) {
795
+ try {
796
+ const { context, history, selectedRoute, responsePrompt, availableTools, responseSchema, signal } = params;
797
+ let { toolCalls, session } = params;
798
+ // Convert HistoryItem[] to Event[] for internal processing
799
+ const historyEvents = (0, utils_1.historyToEvents)(history);
800
+ // Execute initial dynamic tool calls
801
+ if (toolCalls && toolCalls.length > 0) {
802
+ utils_1.logger.debug(`[ResponseModal] Executing ${toolCalls.length} dynamic tool calls:`, toolCalls.map(tc => tc.toolName));
803
+ for (const toolCall of toolCalls) {
804
+ const tool = this.findAvailableTool(toolCall.toolName, selectedRoute);
805
+ if (!tool) {
806
+ utils_1.logger.warn(`[ResponseModal] Tool not found: ${toolCall.toolName}`);
807
+ continue;
808
+ }
809
+ try {
810
+ // Use ToolManager for unified tool execution
811
+ const toolManager = this.getToolManager();
812
+ let toolResult;
813
+ if (toolManager) {
814
+ toolResult = await toolManager.executeTool({
815
+ tool: tool,
816
+ context,
817
+ updateContext: this.agent.updateContext.bind(this.agent),
818
+ updateData: this.agent.updateCollectedData.bind(this.agent),
819
+ history: historyEvents, // Use Event[] for tool execution
820
+ data: session.data,
821
+ toolArguments: toolCall.arguments,
822
+ });
823
+ }
824
+ else {
825
+ // Fallback: execute tool directly if ToolManager not available
826
+ throw new Error(`ToolManager not available for tool execution: ${toolCall.toolName}`);
827
+ }
828
+ // Check if tool execution was successful
829
+ if (!toolResult.success) {
830
+ utils_1.logger.error(`[ResponseModal] Tool execution failed: ${toolCall.toolName} - ${toolResult.error}`);
831
+ // Continue with other tools rather than failing completely
832
+ continue;
833
+ }
834
+ // Update context with tool results
835
+ if (toolResult.contextUpdate) {
836
+ try {
837
+ await this.agent.updateContext(toolResult.contextUpdate);
838
+ }
839
+ catch (error) {
840
+ utils_1.logger.error(`[ResponseModal] Failed to update context from tool ${toolCall.toolName}:`, error);
841
+ // Continue execution but log the error
842
+ }
843
+ }
844
+ // Update collected data with tool results
845
+ if (toolResult.dataUpdate) {
846
+ try {
847
+ const updateDataMethod = this.agent.getUpdateDataMethod();
848
+ session = await updateDataMethod(session, toolResult.dataUpdate);
849
+ utils_1.logger.debug(`[ResponseModal] Tool updated collected data:`, toolResult.dataUpdate);
850
+ }
851
+ catch (error) {
852
+ utils_1.logger.error(`[ResponseModal] Failed to update data from tool ${toolCall.toolName}:`, error);
853
+ // Continue execution but log the error
854
+ }
855
+ }
856
+ utils_1.logger.debug(`[ResponseModal] Executed dynamic tool: ${toolCall.toolName} (success: ${toolResult.success})`);
857
+ }
858
+ catch (error) {
859
+ utils_1.logger.error(`[ResponseModal] Tool execution error for ${toolCall.toolName}:`, error);
860
+ // Continue with other tools rather than failing the entire response
861
+ continue;
862
+ }
863
+ }
864
+ }
865
+ // TOOL LOOP: Allow AI to make follow-up tool calls after initial tool execution
866
+ const MAX_TOOL_LOOPS = this.options?.maxToolLoops || 5;
867
+ let toolLoopCount = 0;
868
+ let hasToolCalls = toolCalls && toolCalls.length > 0;
869
+ let finalMessage;
870
+ while (hasToolCalls && toolLoopCount < MAX_TOOL_LOOPS) {
871
+ toolLoopCount++;
872
+ utils_1.logger.debug(`[ResponseModal] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS} with ${toolCalls?.length || 0} tool calls`);
873
+ // Create tool result events with proper Event format structure
874
+ const toolResultEvents = [];
875
+ for (const toolCall of toolCalls || []) {
876
+ const tool = this.findAvailableTool(toolCall.toolName, selectedRoute);
877
+ if (tool) {
878
+ // Create proper Event format for tool results
879
+ const toolResultEvent = {
880
+ kind: types_1.EventKind.TOOL,
881
+ source: types_1.MessageRole.AGENT,
882
+ timestamp: new Date().toISOString(),
883
+ data: {
884
+ tool_calls: [
885
+ {
886
+ tool_id: toolCall.toolName,
887
+ arguments: toolCall.arguments,
888
+ result: {
889
+ data: "Tool executed successfully",
890
+ },
891
+ },
892
+ ],
893
+ },
894
+ };
895
+ toolResultEvents.push(toolResultEvent);
896
+ }
897
+ }
898
+ // Create updated history with tool results (combine Event arrays)
899
+ const updatedHistoryEvents = [...historyEvents, ...toolResultEvents];
900
+ // Make follow-up AI call to see if more tools are needed
901
+ // After first iteration, don't provide tools to force a text response
902
+ const agentOptions = this.agent.getAgentOptions();
903
+ const shouldProvideTools = toolLoopCount === 1;
904
+ utils_1.logger.debug(`[ResponseModal] Making follow-up AI call (loop ${toolLoopCount}):`, {
905
+ providingTools: shouldProvideTools,
906
+ toolsCount: shouldProvideTools ? availableTools.length : 0,
907
+ addingTextInstruction: toolLoopCount > 1,
908
+ });
909
+ const followUpResult = await agentOptions.provider.generateMessage({
910
+ prompt: responsePrompt + (toolLoopCount > 1 ? "\n\nProvide a text response to the user based on the tool results." : ""),
911
+ history: updatedHistoryEvents, // Use Event[] for AI provider
912
+ context,
913
+ tools: shouldProvideTools ? availableTools : [], // Only provide tools on first iteration
914
+ parameters: responseSchema ? {
915
+ jsonSchema: responseSchema,
916
+ schemaName: "tool_followup",
917
+ } : undefined,
918
+ signal,
919
+ });
920
+ // Check if follow-up call has more tool calls
921
+ const followUpToolCalls = followUpResult.structured?.toolCalls;
922
+ hasToolCalls = followUpToolCalls && followUpToolCalls.length > 0;
923
+ utils_1.logger.debug(`[ResponseModal] Follow-up AI response (loop ${toolLoopCount}):`, {
924
+ hasMessage: !!followUpResult.message,
925
+ messageLength: followUpResult.message?.length || 0,
926
+ hasToolCalls,
927
+ toolCallsCount: followUpToolCalls?.length || 0,
928
+ toolNames: followUpToolCalls?.map(tc => tc.toolName) || [],
929
+ });
930
+ if (hasToolCalls) {
931
+ utils_1.logger.debug(`[ResponseModal] Follow-up call produced ${followUpToolCalls.length} additional tool calls`);
932
+ // Execute the follow-up tool calls
933
+ for (const toolCall of followUpToolCalls) {
934
+ const tool = this.findAvailableTool(toolCall.toolName, selectedRoute);
935
+ if (!tool) {
936
+ utils_1.logger.warn(`[ResponseModal] Tool not found in follow-up: ${toolCall.toolName}`);
937
+ continue;
938
+ }
939
+ try {
940
+ // Use ToolManager for unified tool execution
941
+ const toolManager = this.getToolManager();
942
+ let toolResult;
943
+ if (toolManager) {
944
+ toolResult = await toolManager.executeTool({
945
+ tool: tool,
946
+ context,
947
+ updateContext: this.agent.updateContext.bind(this.agent),
948
+ updateData: this.agent.updateCollectedData.bind(this.agent),
949
+ history: updatedHistoryEvents, // Use Event[] for tool execution
950
+ data: session.data,
951
+ toolArguments: toolCall.arguments,
952
+ });
953
+ }
954
+ else {
955
+ // Fallback: execute tool directly if ToolManager not available
956
+ throw new Error(`ToolManager not available for follow-up tool execution: ${toolCall.toolName}`);
957
+ }
958
+ // Check if tool execution was successful
959
+ if (!toolResult.success) {
960
+ utils_1.logger.error(`[ResponseModal] Follow-up tool execution failed: ${toolCall.toolName} - ${toolResult.error}`);
961
+ continue;
962
+ }
963
+ // Update context with follow-up tool results
964
+ if (toolResult.contextUpdate) {
965
+ try {
966
+ await this.agent.updateContext(toolResult.contextUpdate);
967
+ }
968
+ catch (error) {
969
+ utils_1.logger.error(`[ResponseModal] Failed to update context from follow-up tool ${toolCall.toolName}:`, error);
970
+ }
971
+ }
972
+ if (toolResult.dataUpdate) {
973
+ try {
974
+ const updateDataMethod = this.agent.getUpdateDataMethod();
975
+ session = await updateDataMethod(session, toolResult.dataUpdate);
976
+ utils_1.logger.debug(`[ResponseModal] Follow-up tool updated collected data:`, toolResult.dataUpdate);
977
+ }
978
+ catch (error) {
979
+ utils_1.logger.error(`[ResponseModal] Failed to update data from follow-up tool ${toolCall.toolName}:`, error);
980
+ }
981
+ }
982
+ utils_1.logger.debug(`[ResponseModal] Executed follow-up tool: ${toolCall.toolName} (success: ${toolResult.success})`);
983
+ }
984
+ catch (error) {
985
+ utils_1.logger.error(`[ResponseModal] Follow-up tool execution error for ${toolCall.toolName}:`, error);
986
+ continue;
987
+ }
988
+ }
989
+ // Update toolCalls for next iteration or final response
990
+ toolCalls = followUpToolCalls;
991
+ }
992
+ else {
993
+ utils_1.logger.debug(`[ResponseModal] Tool loop completed after ${toolLoopCount} iterations`);
994
+ // Update final message and toolCalls from follow-up result if no more tools
995
+ finalMessage = followUpResult.structured?.message || followUpResult.message;
996
+ toolCalls = followUpToolCalls || [];
997
+ break;
998
+ }
999
+ }
1000
+ if (toolLoopCount >= MAX_TOOL_LOOPS) {
1001
+ utils_1.logger.warn(`[ResponseModal] Tool loop limit reached (${MAX_TOOL_LOOPS}), stopping`);
1002
+ }
1003
+ utils_1.logger.debug(`[ResponseModal] Tool loop completed:`, {
1004
+ totalIterations: toolLoopCount,
1005
+ hasFinalMessage: !!finalMessage,
1006
+ finalMessageLength: finalMessage?.length || 0,
1007
+ finalToolCallsCount: toolCalls?.length || 0,
1008
+ });
1009
+ return {
1010
+ session,
1011
+ finalToolCalls: toolCalls,
1012
+ finalMessage,
1013
+ };
1014
+ }
1015
+ catch (error) {
1016
+ throw ResponseGenerationError.fromError(error, 'tool_execution', params, {
1017
+ toolCallsCount: params.toolCalls?.length || 0,
1018
+ availableToolsCount: params.availableTools.length
1019
+ });
1020
+ }
1021
+ } /**
1022
+ * Unified data collection from AI response
1023
+ * @private
1024
+ */
1025
+ async collectDataFromResponse(params) {
1026
+ try {
1027
+ const { result, selectedRoute, nextStep, session } = params;
1028
+ let updatedSession = session;
1029
+ // Extract collected data from final response (only for route-based interactions)
1030
+ if (selectedRoute && result.structured) {
1031
+ try {
1032
+ const collectedData = {};
1033
+ // AgentStructuredResponse extends Record<string, unknown>, so we can safely access properties
1034
+ const structuredData = result.structured;
1035
+ // Collect ALL route fields (required + optional) from structured response
1036
+ const allRouteFields = new Set();
1037
+ // Add route required fields
1038
+ if (selectedRoute.requiredFields) {
1039
+ selectedRoute.requiredFields.forEach(field => allRouteFields.add(String(field)));
1040
+ }
1041
+ // Add route optional fields
1042
+ if (selectedRoute.optionalFields) {
1043
+ selectedRoute.optionalFields.forEach(field => allRouteFields.add(String(field)));
1044
+ }
1045
+ // Also include current step's collect fields (in case they're not in route fields)
1046
+ if (nextStep?.collect) {
1047
+ nextStep.collect.forEach(field => allRouteFields.add(String(field)));
1048
+ }
1049
+ // Extract all available fields from structured response
1050
+ for (const field of allRouteFields) {
1051
+ const fieldKey = String(field);
1052
+ if (fieldKey in structuredData && structuredData[fieldKey] !== undefined && structuredData[fieldKey] !== null) {
1053
+ collectedData[fieldKey] = structuredData[fieldKey];
1054
+ }
1055
+ }
1056
+ // Merge collected data into session using agent-level data validation
1057
+ if (Object.keys(collectedData).length > 0) {
1058
+ try {
1059
+ // Update agent-level collected data with validation
1060
+ await this.agent.updateCollectedData(collectedData);
1061
+ // Update session with validated data
1062
+ const updateDataMethod = this.agent.getUpdateDataMethod();
1063
+ updatedSession = await updateDataMethod(updatedSession, collectedData);
1064
+ utils_1.logger.debug(`[ResponseModal] Collected data:`, collectedData);
1065
+ }
1066
+ catch (error) {
1067
+ utils_1.logger.error(`[ResponseModal] Failed to update collected data:`, error);
1068
+ // Continue without updating data rather than failing completely
1069
+ }
1070
+ }
1071
+ }
1072
+ catch (error) {
1073
+ utils_1.logger.error(`[ResponseModal] Error during data collection:`, error);
1074
+ // Continue without collecting data rather than failing completely
1075
+ }
1076
+ }
1077
+ // Extract any additional data from structured response
1078
+ // Since AgentStructuredResponse extends Record<string, unknown>, we can safely check for additional properties
1079
+ if (result.structured && "contextUpdate" in result.structured) {
1080
+ try {
1081
+ const contextUpdate = result.structured.contextUpdate;
1082
+ if (contextUpdate) {
1083
+ await this.agent.updateContext(contextUpdate);
1084
+ }
1085
+ }
1086
+ catch (error) {
1087
+ utils_1.logger.error(`[ResponseModal] Failed to update context from structured response:`, error);
1088
+ // Continue without updating context rather than failing completely
1089
+ }
1090
+ }
1091
+ return updatedSession;
1092
+ }
1093
+ catch (error) {
1094
+ utils_1.logger.error(`[ResponseModal] Error in collectDataFromResponse:`, error);
1095
+ // Return original session if data collection fails completely
1096
+ return params.session;
1097
+ }
1098
+ }
1099
+ /**
1100
+ * Handle route completion logic
1101
+ * @private
1102
+ */
1103
+ async handleRouteCompletion(params) {
1104
+ const { selectedRoute, session, context, lastMessageText, historyEvents, signal } = params;
1105
+ // Get endStep spec from route
1106
+ const endStepSpec = selectedRoute.endStepSpec;
1107
+ // Create a temporary step for completion message generation using endStep configuration
1108
+ const completionStep = new Step_1.Step(selectedRoute.id, {
1109
+ description: endStepSpec.description,
1110
+ id: endStepSpec.id || constants_1.END_ROUTE_ID,
1111
+ collect: endStepSpec.collect,
1112
+ requires: endStepSpec.requires,
1113
+ prompt: endStepSpec.prompt || "Summarize what was accomplished and confirm completion based on the conversation history and collected data",
1114
+ });
1115
+ // Build response schema for completion (message only, no data collection)
1116
+ const completionSchema = {
1117
+ type: "object",
1118
+ properties: {
1119
+ message: {
1120
+ type: "string",
1121
+ description: "Completion message confirming what was accomplished",
1122
+ },
1123
+ },
1124
+ required: ["message"],
1125
+ additionalProperties: false,
1126
+ };
1127
+ const templateContext = (0, template_1.createTemplateContext)({ context, session, history: historyEvents });
1128
+ // Build completion response prompt using ResponseEngine
1129
+ // Filter out conditional guidelines - only include always-active ones
1130
+ const alwaysActiveGuidelines = [
1131
+ ...this.agent.getGuidelines().filter(g => !g.condition),
1132
+ ...selectedRoute.getGuidelines().filter(g => !g.condition),
1133
+ ];
1134
+ let completitionPrompt = "Summarize what was accomplished and confirm completion";
1135
+ if (endStepSpec.prompt) {
1136
+ completitionPrompt = await (0, utils_1.render)(endStepSpec.prompt, templateContext);
1137
+ }
1138
+ const completionPrompt = await this.responseEngine.buildResponsePrompt({
1139
+ route: selectedRoute,
1140
+ currentStep: completionStep,
1141
+ rules: selectedRoute.getRules(),
1142
+ prohibitions: selectedRoute.getProhibitions(),
1143
+ directives: [
1144
+ `Task completed: ${selectedRoute.title}`,
1145
+ `Collected data: ${JSON.stringify(session.data, null, 2)}`,
1146
+ "Do NOT ask for more information - the task is complete",
1147
+ completitionPrompt,
1148
+ ],
1149
+ history: historyEvents,
1150
+ lastMessage: lastMessageText,
1151
+ agentOptions: this.agent.getAgentOptions(),
1152
+ combinedGuidelines: alwaysActiveGuidelines, // Only non-conditional guidelines
1153
+ combinedTerms: this.mergeTerms(this.agent.getTerms(), selectedRoute.getTerms()),
1154
+ context,
1155
+ session,
1156
+ agentSchema: undefined, // No data collection schema for completion
1157
+ });
1158
+ // Generate completion message using AI provider
1159
+ const agentOptions = this.agent.getAgentOptions();
1160
+ utils_1.logger.debug(`[ResponseModal] Calling AI provider for completion message...`);
1161
+ const completionResult = await agentOptions.provider.generateMessage({
1162
+ prompt: completionPrompt,
1163
+ history: historyEvents,
1164
+ context,
1165
+ signal,
1166
+ parameters: { jsonSchema: completionSchema, schemaName: "completion_message" },
1167
+ });
1168
+ utils_1.logger.debug(`[ResponseModal] AI provider returned completion result`);
1169
+ const message = completionResult.structured?.message || completionResult.message;
1170
+ utils_1.logger.debug(`[ResponseModal] Generated completion message for route: ${selectedRoute.title}`);
1171
+ // Check for onComplete transition
1172
+ const transitionConfig = await selectedRoute.evaluateOnComplete({ data: session.data }, context);
1173
+ if (transitionConfig) {
1174
+ // Find target route by ID or title
1175
+ const targetRoute = this.agent.getRoutes().find((r) => r.id === transitionConfig.nextStep || r.title === transitionConfig.nextStep);
1176
+ if (targetRoute) {
1177
+ const renderedCondition = await (0, utils_1.render)(transitionConfig.condition, templateContext);
1178
+ // Set pending transition in session
1179
+ session.pendingTransition = {
1180
+ targetRouteId: targetRoute.id,
1181
+ condition: renderedCondition,
1182
+ reason: "route_complete",
1183
+ };
1184
+ utils_1.logger.debug(`[ResponseModal] Route ${selectedRoute.title} completed with pending transition to: ${targetRoute.title}`);
1185
+ }
1186
+ else {
1187
+ utils_1.logger.warn(`[ResponseModal] Route ${selectedRoute.title} completed but target route not found: ${transitionConfig.nextStep}`);
1188
+ }
1189
+ }
1190
+ return message;
1191
+ }
1192
+ /**
1193
+ * Stream route completion response
1194
+ * @private
1195
+ */
1196
+ async *streamRouteCompletion(params) {
1197
+ const { selectedRoute, context, lastMessageText, historyEvents, signal } = params;
1198
+ let session = params.session;
1199
+ // Get endStep spec from route
1200
+ const endStepSpec = selectedRoute.endStepSpec;
1201
+ // Create a temporary step for completion message generation using endStep configuration
1202
+ const completionStep = new Step_1.Step(selectedRoute.id, {
1203
+ description: endStepSpec.description,
1204
+ id: endStepSpec.id || constants_1.END_ROUTE_ID,
1205
+ collect: endStepSpec.collect,
1206
+ requires: endStepSpec.requires,
1207
+ prompt: endStepSpec.prompt || "Summarize what was accomplished and confirm completion based on the conversation history and collected data",
1208
+ });
1209
+ // Build response schema for completion
1210
+ const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep, this.agent.getSchema());
1211
+ const templateContext = (0, template_1.createTemplateContext)({ context, session, history: historyEvents }); // Use Event[] for template context
1212
+ // Build completion response prompt
1213
+ const completionPrompt = await this.responseEngine.buildResponsePrompt({
1214
+ route: selectedRoute,
1215
+ currentStep: completionStep,
1216
+ rules: selectedRoute.getRules(),
1217
+ prohibitions: selectedRoute.getProhibitions(),
1218
+ directives: undefined, // No directives for completion
1219
+ history: historyEvents, // Use Event[] for buildResponsePrompt
1220
+ lastMessage: lastMessageText, // Use string for buildResponsePrompt
1221
+ agentOptions: this.agent.getAgentOptions(),
1222
+ combinedGuidelines: [...this.agent.getGuidelines(), ...selectedRoute.getGuidelines()],
1223
+ combinedTerms: this.mergeTerms(this.agent.getTerms(), selectedRoute.getTerms()),
1224
+ context,
1225
+ session,
1226
+ agentSchema: this.agent.getSchema(),
1227
+ });
1228
+ // Stream completion message using AI provider
1229
+ const agentOptions = this.agent.getAgentOptions();
1230
+ const stream = agentOptions.provider.generateMessageStream({
1231
+ prompt: completionPrompt,
1232
+ history: historyEvents, // Use Event[] for AI provider
1233
+ context,
1234
+ signal,
1235
+ parameters: { jsonSchema: responseSchema, schemaName: "completion_message_stream" },
1236
+ });
1237
+ utils_1.logger.debug(`[ResponseModal] Streaming completion message for route: ${selectedRoute.title}`);
1238
+ // Check for onComplete transition
1239
+ const transitionConfig = await selectedRoute.evaluateOnComplete({ data: session.data }, context);
1240
+ if (transitionConfig) {
1241
+ // Find target route by ID or title
1242
+ const targetRoute = this.agent.getRoutes().find((r) => r.id === transitionConfig.nextStep || r.title === transitionConfig.nextStep);
1243
+ if (targetRoute) {
1244
+ const renderedCondition = await (0, utils_1.render)(transitionConfig.condition, templateContext);
1245
+ // Set pending transition in session
1246
+ session = {
1247
+ ...session,
1248
+ pendingTransition: {
1249
+ targetRouteId: targetRoute.id,
1250
+ condition: renderedCondition,
1251
+ reason: "route_complete",
1252
+ },
1253
+ };
1254
+ utils_1.logger.debug(`[ResponseModal] Route ${selectedRoute.title} completed with pending transition to: ${targetRoute.title}`);
1255
+ }
1256
+ else {
1257
+ utils_1.logger.warn(`[ResponseModal] Route ${selectedRoute.title} completed but target route not found: ${transitionConfig.nextStep}`);
1258
+ }
1259
+ }
1260
+ // Set step to END_ROUTE marker
1261
+ session = (0, utils_1.enterStep)(session, constants_1.END_ROUTE_ID, "Route completed");
1262
+ utils_1.logger.debug(`[ResponseModal] Route ${selectedRoute.title} completed. Entered END_ROUTE step.`);
1263
+ // Stream completion chunks
1264
+ for await (const chunk of stream) {
1265
+ // Update current session if we have one
1266
+ if (chunk.done) {
1267
+ await this.finalizeSession(session, context);
1268
+ }
1269
+ yield {
1270
+ delta: chunk.delta,
1271
+ accumulated: chunk.accumulated,
1272
+ done: chunk.done,
1273
+ session,
1274
+ toolCalls: undefined,
1275
+ isRouteComplete: true,
1276
+ metadata: chunk.metadata,
1277
+ structured: chunk.structured,
1278
+ };
1279
+ }
1280
+ }
1281
+ /**
1282
+ * Generate fallback response when no routes are available
1283
+ * @private
1284
+ */
1285
+ async generateFallbackResponse(params) {
1286
+ const { history, context, session, signal } = params;
1287
+ utils_1.logger.debug(`[ResponseModal] No route selected, generating basic response`);
1288
+ // Build basic response prompt without route context
1289
+ const fallbackPrompt = await this.responseEngine.buildFallbackPrompt({
1290
+ history,
1291
+ agentOptions: this.agent.getAgentOptions(),
1292
+ terms: this.agent.getTerms(),
1293
+ guidelines: this.agent.getGuidelines(),
1294
+ context,
1295
+ session,
1296
+ });
1297
+ const agentOptions = this.agent.getAgentOptions();
1298
+ const result = await agentOptions.provider.generateMessage({
1299
+ prompt: fallbackPrompt,
1300
+ history,
1301
+ context,
1302
+ signal,
1303
+ parameters: {
1304
+ jsonSchema: {
1305
+ type: "object",
1306
+ properties: { message: { type: "string" } },
1307
+ required: ["message"],
1308
+ additionalProperties: false,
1309
+ },
1310
+ schemaName: "fallback_response",
1311
+ },
1312
+ });
1313
+ return result.structured?.message || result.message;
1314
+ }
1315
+ /**
1316
+ * Stream fallback response when no routes are available
1317
+ * @private
1318
+ */
1319
+ async *streamFallbackResponse(params) {
1320
+ const { history, context, session, signal } = params;
1321
+ const fallbackPrompt = await this.responseEngine.buildFallbackPrompt({
1322
+ history,
1323
+ agentOptions: this.agent.getAgentOptions(),
1324
+ terms: this.agent.getTerms(),
1325
+ guidelines: this.agent.getGuidelines(),
1326
+ context,
1327
+ session,
1328
+ });
1329
+ const agentOptions = this.agent.getAgentOptions();
1330
+ const stream = agentOptions.provider.generateMessageStream({
1331
+ prompt: fallbackPrompt,
1332
+ history,
1333
+ context,
1334
+ signal,
1335
+ parameters: {
1336
+ jsonSchema: {
1337
+ type: "object",
1338
+ properties: { message: { type: "string" } },
1339
+ required: ["message"],
1340
+ additionalProperties: false,
1341
+ },
1342
+ schemaName: "fallback_stream_response",
1343
+ },
1344
+ });
1345
+ for await (const chunk of stream) {
1346
+ // Update current session if we have one
1347
+ if (chunk.done) {
1348
+ await this.finalizeSession(session, context);
1349
+ }
1350
+ yield {
1351
+ delta: chunk.delta,
1352
+ accumulated: chunk.accumulated,
1353
+ done: chunk.done,
1354
+ session,
1355
+ toolCalls: undefined,
1356
+ isRouteComplete: false,
1357
+ metadata: chunk.metadata,
1358
+ structured: chunk.structured,
1359
+ };
1360
+ }
1361
+ }
1362
+ /**
1363
+ * Handle session persistence and finalization
1364
+ * @private
1365
+ */
1366
+ async finalizeSession(session, context) {
1367
+ // Auto-save session step to persistence if configured
1368
+ const persistenceManager = this.agent.getPersistenceManager();
1369
+ const agentOptions = this.agent.getAgentOptions();
1370
+ if (persistenceManager &&
1371
+ session.id &&
1372
+ (this.options?.enableAutoSave !== false && agentOptions.persistence?.autoSave !== false)) {
1373
+ await persistenceManager.saveSessionState(session.id, session);
1374
+ utils_1.logger.debug(`[ResponseModal] Auto-saved session step to persistence: ${session.id}`);
1375
+ }
1376
+ // Execute finalize function
1377
+ await this.executeStepFinalize(session, context);
1378
+ // Update current session if we have one
1379
+ const currentSession = this.agent.getCurrentSession();
1380
+ if (currentSession) {
1381
+ this.agent.setCurrentSession(session);
1382
+ }
1383
+ }
1384
+ // ============================================================================
1385
+ // UTILITY METHODS - Helper methods for tool management and other utilities
1386
+ // ============================================================================
1387
+ /**
1388
+ * Find an available tool by name for the given route using ToolManager
1389
+ * Delegates to ToolManager for unified tool resolution
1390
+ * @private
1391
+ */
1392
+ findAvailableTool(toolName, route) {
1393
+ // Use ToolManager for unified tool resolution
1394
+ const toolManager = this.getToolManager();
1395
+ if (toolManager) {
1396
+ return toolManager.find(toolName, undefined, undefined, route);
1397
+ }
1398
+ // Fallback to legacy resolution if ToolManager not available
1399
+ utils_1.logger.warn(`[ResponseModal] ToolManager not available, using legacy tool resolution for: ${toolName}`);
1400
+ // Check route-level tools first (if route provided)
1401
+ if (route) {
1402
+ const routeTool = route
1403
+ .getTools()
1404
+ .find((tool) => tool.id === toolName || tool.name === toolName);
1405
+ if (routeTool)
1406
+ return routeTool;
1407
+ }
1408
+ // Fall back to agent-level tools
1409
+ const agentTools = this.agent.getTools();
1410
+ return agentTools.find((tool) => tool.id === toolName || tool.name === toolName);
1411
+ }
1412
+ /**
1413
+ * Collect all available tools for the given route and step context using ToolManager
1414
+ * Delegates to ToolManager for unified tool resolution and deduplication
1415
+ * @private
1416
+ */
1417
+ collectAvailableTools(route, step) {
1418
+ // Use ToolManager for unified tool collection if available
1419
+ const toolManager = this.getToolManager();
1420
+ if (toolManager) {
1421
+ const availableTools = toolManager.getAvailable(undefined, step, route);
1422
+ return availableTools.map((tool) => ({
1423
+ id: tool.id,
1424
+ name: tool.name || tool.id,
1425
+ description: tool.description,
1426
+ parameters: tool.parameters,
1427
+ }));
1428
+ }
1429
+ // Fallback to legacy collection logic if ToolManager not available
1430
+ utils_1.logger.warn(`[ResponseModal] ToolManager not available, using legacy tool collection`);
1431
+ const availableTools = new Map();
1432
+ // Add agent-level tools
1433
+ this.agent.getTools().forEach((tool) => {
1434
+ availableTools.set(tool.id, tool);
1435
+ });
1436
+ // Add route-level tools (these take precedence)
1437
+ if (route) {
1438
+ route.getTools().forEach((tool) => {
1439
+ availableTools.set(tool.id, tool);
1440
+ });
1441
+ }
1442
+ // Filter by step-level allowed tools if specified
1443
+ if (step?.tools) {
1444
+ const allowedToolIds = new Set();
1445
+ const stepTools = [];
1446
+ for (const toolRef of step.tools) {
1447
+ if (typeof toolRef === "string") {
1448
+ // Reference to registered tool
1449
+ allowedToolIds.add(toolRef);
1450
+ }
1451
+ else {
1452
+ // Inline tool definition
1453
+ if (toolRef.id) {
1454
+ allowedToolIds.add(toolRef.id);
1455
+ stepTools.push(toolRef);
1456
+ }
1457
+ }
1458
+ }
1459
+ // If step specifies tools, only include those
1460
+ if (allowedToolIds.size > 0) {
1461
+ const filteredTools = new Map();
1462
+ for (const toolId of Array.from(allowedToolIds)) {
1463
+ const tool = availableTools.get(toolId);
1464
+ if (tool) {
1465
+ filteredTools.set(toolId, tool);
1466
+ }
1467
+ }
1468
+ // Add inline tools
1469
+ stepTools.forEach((tool) => {
1470
+ if (tool.id) {
1471
+ filteredTools.set(tool.id, tool);
1472
+ }
1473
+ });
1474
+ availableTools.clear();
1475
+ filteredTools.forEach((tool, id) => availableTools.set(id, tool));
1476
+ }
1477
+ }
1478
+ // Convert to the format expected by AI providers
1479
+ return Array.from(availableTools.values()).map((tool) => ({
1480
+ id: tool.id,
1481
+ name: tool.name || tool.id,
1482
+ description: tool.description,
1483
+ parameters: tool.parameters,
1484
+ }));
1485
+ }
1486
+ /**
1487
+ * Execute a prepare or finalize function/tool
1488
+ * @private
1489
+ */
1490
+ async executePrepareFinalize(prepareOrFinalize, context, data, route, step) {
1491
+ if (!prepareOrFinalize)
1492
+ return;
1493
+ if (typeof prepareOrFinalize === "function") {
1494
+ // It's a function - call it directly
1495
+ await prepareOrFinalize(context, data);
1496
+ }
1497
+ else {
1498
+ // It's a tool reference - find and execute the tool
1499
+ let tool;
1500
+ if (typeof prepareOrFinalize === "string") {
1501
+ // Tool ID - use ToolManager for unified resolution
1502
+ const toolManager = this.getToolManager();
1503
+ if (toolManager) {
1504
+ tool = toolManager.find(prepareOrFinalize, undefined, step, route);
1505
+ }
1506
+ else {
1507
+ // Fallback to legacy resolution if ToolManager not available
1508
+ utils_1.logger.warn(`[ResponseModal] ToolManager not available, using legacy tool resolution for prepare/finalize: ${prepareOrFinalize}`);
1509
+ const availableTools = new Map();
1510
+ // Add agent-level tools
1511
+ this.agent.getTools().forEach((t) => {
1512
+ availableTools.set(t.id, t);
1513
+ });
1514
+ // Add route-level tools
1515
+ if (route) {
1516
+ route.getTools().forEach((t) => {
1517
+ availableTools.set(t.id, t);
1518
+ });
1519
+ }
1520
+ // Add step-level tools
1521
+ if (step?.tools) {
1522
+ for (const toolRef of step.tools) {
1523
+ if (typeof toolRef === "string") {
1524
+ // Keep as is
1525
+ }
1526
+ else if (typeof toolRef === 'object' && 'id' in toolRef && toolRef.id) {
1527
+ availableTools.set(toolRef.id, toolRef);
1528
+ }
1529
+ }
1530
+ }
1531
+ tool = availableTools.get(prepareOrFinalize);
1532
+ }
1533
+ }
1534
+ else {
1535
+ // Tool object - use directly
1536
+ tool = prepareOrFinalize;
1537
+ }
1538
+ if (tool) {
1539
+ // Use ToolManager for unified tool execution
1540
+ const toolManager = this.getToolManager();
1541
+ let result;
1542
+ if (toolManager) {
1543
+ result = await toolManager.executeTool({
1544
+ tool,
1545
+ context,
1546
+ updateContext: this.agent.updateContext.bind(this.agent),
1547
+ updateData: this.agent.updateCollectedData.bind(this.agent),
1548
+ history: [], // Empty history for prepare/finalize
1549
+ data,
1550
+ });
1551
+ }
1552
+ else {
1553
+ // Fallback: execute tool directly if ToolManager not available
1554
+ throw new Error(`ToolManager not available for prepare/finalize tool execution: ${typeof prepareOrFinalize === "string" ? prepareOrFinalize : "inline tool"}`);
1555
+ }
1556
+ if (!result.success) {
1557
+ utils_1.logger.error(`[ResponseModal] Tool execution failed in prepare/finalize: ${result.error}`);
1558
+ throw new Error(`Tool execution failed: ${result.error}`);
1559
+ }
1560
+ }
1561
+ else {
1562
+ utils_1.logger.warn(`[ResponseModal] Tool not found for prepare/finalize: ${typeof prepareOrFinalize === "string"
1563
+ ? prepareOrFinalize
1564
+ : "inline tool"}`);
1565
+ }
1566
+ }
1567
+ }
1568
+ /**
1569
+ * Merge terms with route-specific taking precedence on conflicts
1570
+ * @private
1571
+ */
1572
+ mergeTerms(agentTerms, routeTerms) {
1573
+ const merged = new Map();
1574
+ // Add agent terms first
1575
+ agentTerms.forEach((term) => {
1576
+ const name = typeof term.name === "string" ? term.name : term.name.toString();
1577
+ merged.set(name, term);
1578
+ });
1579
+ // Add route terms (these take precedence)
1580
+ routeTerms.forEach((term) => {
1581
+ const name = typeof term.name === "string" ? term.name : term.name.toString();
1582
+ merged.set(name, term);
1583
+ });
1584
+ return Array.from(merged.values());
1585
+ }
1586
+ }
1587
+ exports.ResponseModal = ResponseModal;
1588
+ //# sourceMappingURL=ResponseModal.js.map