@falai/agent 0.9.0 → 1.0.0

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 (654) hide show
  1. package/README.md +304 -72
  2. package/dist/adapters/MemoryAdapter.d.ts.map +1 -0
  3. package/dist/adapters/MemoryAdapter.js.map +1 -0
  4. package/dist/adapters/MongoAdapter.d.ts.map +1 -0
  5. package/dist/adapters/MongoAdapter.js.map +1 -0
  6. package/dist/adapters/OpenSearchAdapter.d.ts.map +1 -0
  7. package/dist/adapters/OpenSearchAdapter.js.map +1 -0
  8. package/dist/adapters/PostgreSQLAdapter.d.ts.map +1 -0
  9. package/dist/adapters/PostgreSQLAdapter.js.map +1 -0
  10. package/dist/adapters/PrismaAdapter.d.ts.map +1 -0
  11. package/dist/{src/adapters → adapters}/PrismaAdapter.js +3 -2
  12. package/dist/adapters/PrismaAdapter.js.map +1 -0
  13. package/dist/adapters/RedisAdapter.d.ts.map +1 -0
  14. package/dist/{src/adapters → adapters}/RedisAdapter.js +3 -3
  15. package/dist/adapters/RedisAdapter.js.map +1 -0
  16. package/dist/adapters/SQLiteAdapter.d.ts.map +1 -0
  17. package/dist/adapters/SQLiteAdapter.js.map +1 -0
  18. package/dist/adapters/index.d.ts.map +1 -0
  19. package/dist/adapters/index.js.map +1 -0
  20. package/dist/cjs/adapters/MemoryAdapter.js.map +1 -0
  21. package/dist/cjs/adapters/MongoAdapter.js.map +1 -0
  22. package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -0
  23. package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -0
  24. package/dist/{src → cjs}/adapters/PrismaAdapter.d.ts.map +1 -1
  25. package/dist/cjs/{src/adapters → adapters}/PrismaAdapter.js +3 -2
  26. package/dist/cjs/adapters/PrismaAdapter.js.map +1 -0
  27. package/dist/cjs/{src/adapters → adapters}/RedisAdapter.js +2 -2
  28. package/dist/cjs/adapters/RedisAdapter.js.map +1 -0
  29. package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -0
  30. package/dist/cjs/adapters/index.js.map +1 -0
  31. package/dist/cjs/constants/index.js.map +1 -0
  32. package/dist/{src → cjs}/core/Agent.d.ts +25 -6
  33. package/dist/cjs/core/Agent.d.ts.map +1 -0
  34. package/dist/cjs/{src/core → core}/Agent.js +121 -37
  35. package/dist/cjs/core/Agent.js.map +1 -0
  36. package/dist/cjs/core/BatchExecutor.d.ts +353 -0
  37. package/dist/cjs/core/BatchExecutor.d.ts.map +1 -0
  38. package/dist/cjs/core/BatchExecutor.js +842 -0
  39. package/dist/cjs/core/BatchExecutor.js.map +1 -0
  40. package/dist/cjs/core/BatchPromptBuilder.d.ts +86 -0
  41. package/dist/cjs/core/BatchPromptBuilder.d.ts.map +1 -0
  42. package/dist/cjs/core/BatchPromptBuilder.js +201 -0
  43. package/dist/cjs/core/BatchPromptBuilder.js.map +1 -0
  44. package/dist/cjs/core/Events.js.map +1 -0
  45. package/dist/cjs/core/PersistenceManager.js.map +1 -0
  46. package/dist/{src → cjs}/core/PromptComposer.d.ts +1 -1
  47. package/dist/cjs/core/PromptComposer.d.ts.map +1 -0
  48. package/dist/cjs/{src/core → core}/PromptComposer.js +44 -7
  49. package/dist/cjs/core/PromptComposer.js.map +1 -0
  50. package/dist/{src → cjs}/core/ResponseEngine.d.ts.map +1 -1
  51. package/dist/cjs/core/ResponseEngine.js +202 -0
  52. package/dist/cjs/core/ResponseEngine.js.map +1 -0
  53. package/dist/{src → cjs}/core/ResponseModal.d.ts +54 -3
  54. package/dist/cjs/core/ResponseModal.d.ts.map +1 -0
  55. package/dist/cjs/{src/core → core}/ResponseModal.js +807 -121
  56. package/dist/cjs/core/ResponseModal.js.map +1 -0
  57. package/dist/{src → cjs}/core/ResponsePipeline.d.ts +10 -6
  58. package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -0
  59. package/dist/cjs/{src/core → core}/ResponsePipeline.js +60 -25
  60. package/dist/cjs/core/ResponsePipeline.js.map +1 -0
  61. package/dist/{src → cjs}/core/Route.d.ts +46 -10
  62. package/dist/cjs/core/Route.d.ts.map +1 -0
  63. package/dist/cjs/core/Route.js +541 -0
  64. package/dist/cjs/core/Route.js.map +1 -0
  65. package/dist/cjs/{src/core → core}/RoutingEngine.d.ts +35 -5
  66. package/dist/cjs/core/RoutingEngine.d.ts.map +1 -0
  67. package/dist/cjs/{src/core → core}/RoutingEngine.js +360 -98
  68. package/dist/cjs/core/RoutingEngine.js.map +1 -0
  69. package/dist/{src → cjs}/core/SessionManager.d.ts +9 -1
  70. package/dist/cjs/core/SessionManager.d.ts.map +1 -0
  71. package/dist/cjs/{src/core → core}/SessionManager.js +27 -5
  72. package/dist/cjs/core/SessionManager.js.map +1 -0
  73. package/dist/cjs/core/Step.d.ts +170 -0
  74. package/dist/cjs/core/Step.d.ts.map +1 -0
  75. package/dist/cjs/core/Step.js +448 -0
  76. package/dist/cjs/core/Step.js.map +1 -0
  77. package/dist/cjs/core/ToolManager.d.ts +234 -0
  78. package/dist/cjs/core/ToolManager.d.ts.map +1 -0
  79. package/dist/cjs/core/ToolManager.js +1117 -0
  80. package/dist/cjs/core/ToolManager.js.map +1 -0
  81. package/dist/{src → cjs}/index.d.ts +5 -3
  82. package/dist/cjs/index.d.ts.map +1 -0
  83. package/dist/cjs/{src/index.js → index.js} +16 -3
  84. package/dist/cjs/index.js.map +1 -0
  85. package/dist/cjs/{src/providers → providers}/AnthropicProvider.js +18 -18
  86. package/dist/cjs/providers/AnthropicProvider.js.map +1 -0
  87. package/dist/{src → cjs}/providers/GeminiProvider.d.ts.map +1 -1
  88. package/dist/cjs/{src/providers → providers}/GeminiProvider.js +123 -51
  89. package/dist/cjs/providers/GeminiProvider.js.map +1 -0
  90. package/dist/cjs/{src/providers → providers}/OpenAIProvider.js +19 -19
  91. package/dist/cjs/providers/OpenAIProvider.js.map +1 -0
  92. package/dist/cjs/{src/providers → providers}/OpenRouterProvider.js +19 -19
  93. package/dist/cjs/providers/OpenRouterProvider.js.map +1 -0
  94. package/dist/cjs/providers/index.js.map +1 -0
  95. package/dist/cjs/{src/types → types}/agent.d.ts +12 -4
  96. package/dist/cjs/types/agent.d.ts.map +1 -0
  97. package/dist/cjs/types/agent.js.map +1 -0
  98. package/dist/{src → cjs}/types/ai.js.map +1 -1
  99. package/dist/cjs/types/history.js.map +1 -0
  100. package/dist/cjs/{src/types → types}/index.d.ts +5 -3
  101. package/dist/{src → cjs}/types/index.d.ts.map +1 -1
  102. package/dist/cjs/{src/types → types}/index.js +8 -1
  103. package/dist/cjs/types/index.js.map +1 -0
  104. package/dist/cjs/types/persistence.js.map +1 -0
  105. package/dist/cjs/{src/types → types}/route.d.ts +116 -15
  106. package/dist/cjs/types/route.d.ts.map +1 -0
  107. package/dist/cjs/{src/types → types}/route.js.map +1 -1
  108. package/dist/cjs/types/session.js.map +1 -0
  109. package/dist/cjs/types/template.d.ts +88 -0
  110. package/dist/cjs/types/template.d.ts.map +1 -0
  111. package/dist/cjs/types/tool.d.ts +130 -0
  112. package/dist/cjs/types/tool.d.ts.map +1 -0
  113. package/dist/cjs/types/tool.js +19 -0
  114. package/dist/cjs/types/tool.js.map +1 -0
  115. package/dist/cjs/utils/clone.js.map +1 -0
  116. package/dist/cjs/utils/condition.d.ts +38 -0
  117. package/dist/cjs/utils/condition.d.ts.map +1 -0
  118. package/dist/cjs/utils/condition.js +168 -0
  119. package/dist/cjs/utils/condition.js.map +1 -0
  120. package/dist/cjs/utils/event.js.map +1 -0
  121. package/dist/cjs/utils/history.js.map +1 -0
  122. package/dist/cjs/utils/id.js.map +1 -0
  123. package/dist/cjs/{src/utils → utils}/index.d.ts +3 -1
  124. package/dist/cjs/utils/index.d.ts.map +1 -0
  125. package/dist/cjs/{src/utils → utils}/index.js +12 -1
  126. package/dist/cjs/utils/index.js.map +1 -0
  127. package/dist/cjs/utils/json.d.ts +16 -0
  128. package/dist/cjs/utils/json.d.ts.map +1 -0
  129. package/dist/cjs/utils/json.js +47 -0
  130. package/dist/cjs/utils/json.js.map +1 -0
  131. package/dist/cjs/utils/logger.js.map +1 -0
  132. package/dist/{src → cjs}/utils/retry.d.ts +0 -3
  133. package/dist/cjs/utils/retry.d.ts.map +1 -0
  134. package/dist/cjs/{src/utils → utils}/retry.js +8 -7
  135. package/dist/cjs/utils/retry.js.map +1 -0
  136. package/dist/cjs/utils/session.js.map +1 -0
  137. package/dist/{src → cjs}/utils/template.d.ts +48 -0
  138. package/dist/cjs/utils/template.d.ts.map +1 -0
  139. package/dist/cjs/{src/utils → utils}/template.js +100 -0
  140. package/dist/cjs/utils/template.js.map +1 -0
  141. package/dist/constants/index.d.ts.map +1 -0
  142. package/dist/constants/index.js.map +1 -0
  143. package/dist/{cjs/src/core → core}/Agent.d.ts +25 -6
  144. package/dist/core/Agent.d.ts.map +1 -0
  145. package/dist/{src/core → core}/Agent.js +122 -38
  146. package/dist/core/Agent.js.map +1 -0
  147. package/dist/core/BatchExecutor.d.ts +353 -0
  148. package/dist/core/BatchExecutor.d.ts.map +1 -0
  149. package/dist/core/BatchExecutor.js +837 -0
  150. package/dist/core/BatchExecutor.js.map +1 -0
  151. package/dist/core/BatchPromptBuilder.d.ts +86 -0
  152. package/dist/core/BatchPromptBuilder.d.ts.map +1 -0
  153. package/dist/core/BatchPromptBuilder.js +197 -0
  154. package/dist/core/BatchPromptBuilder.js.map +1 -0
  155. package/dist/core/Events.d.ts.map +1 -0
  156. package/dist/core/Events.js.map +1 -0
  157. package/dist/core/PersistenceManager.d.ts.map +1 -0
  158. package/dist/core/PersistenceManager.js.map +1 -0
  159. package/dist/{cjs/src/core → core}/PromptComposer.d.ts +1 -1
  160. package/dist/core/PromptComposer.d.ts.map +1 -0
  161. package/dist/{src/core → core}/PromptComposer.js +45 -8
  162. package/dist/core/PromptComposer.js.map +1 -0
  163. package/dist/core/ResponseEngine.d.ts.map +1 -0
  164. package/dist/core/ResponseEngine.js +198 -0
  165. package/dist/core/ResponseEngine.js.map +1 -0
  166. package/dist/{cjs/src/core → core}/ResponseModal.d.ts +54 -3
  167. package/dist/core/ResponseModal.d.ts.map +1 -0
  168. package/dist/{src/core → core}/ResponseModal.js +807 -121
  169. package/dist/core/ResponseModal.js.map +1 -0
  170. package/dist/{cjs/src/core → core}/ResponsePipeline.d.ts +10 -6
  171. package/dist/core/ResponsePipeline.d.ts.map +1 -0
  172. package/dist/{src/core → core}/ResponsePipeline.js +60 -25
  173. package/dist/core/ResponsePipeline.js.map +1 -0
  174. package/dist/{cjs/src/core → core}/Route.d.ts +46 -10
  175. package/dist/core/Route.d.ts.map +1 -0
  176. package/dist/core/Route.js +537 -0
  177. package/dist/core/Route.js.map +1 -0
  178. package/dist/{src/core → core}/RoutingEngine.d.ts +35 -5
  179. package/dist/core/RoutingEngine.d.ts.map +1 -0
  180. package/dist/{src/core → core}/RoutingEngine.js +343 -81
  181. package/dist/core/RoutingEngine.js.map +1 -0
  182. package/dist/{cjs/src/core → core}/SessionManager.d.ts +9 -1
  183. package/dist/core/SessionManager.d.ts.map +1 -0
  184. package/dist/{src/core → core}/SessionManager.js +27 -5
  185. package/dist/core/SessionManager.js.map +1 -0
  186. package/dist/core/Step.d.ts +170 -0
  187. package/dist/core/Step.d.ts.map +1 -0
  188. package/dist/core/Step.js +444 -0
  189. package/dist/core/Step.js.map +1 -0
  190. package/dist/core/ToolManager.d.ts +234 -0
  191. package/dist/core/ToolManager.d.ts.map +1 -0
  192. package/dist/core/ToolManager.js +1111 -0
  193. package/dist/core/ToolManager.js.map +1 -0
  194. package/dist/{cjs/src/index.d.ts → index.d.ts} +5 -3
  195. package/dist/index.d.ts.map +1 -0
  196. package/dist/{src/index.js → index.js} +4 -1
  197. package/dist/index.js.map +1 -0
  198. package/dist/providers/AnthropicProvider.d.ts.map +1 -0
  199. package/dist/{src/providers → providers}/AnthropicProvider.js +17 -17
  200. package/dist/providers/AnthropicProvider.js.map +1 -0
  201. package/dist/providers/GeminiProvider.d.ts.map +1 -0
  202. package/dist/{src/providers → providers}/GeminiProvider.js +123 -51
  203. package/dist/providers/GeminiProvider.js.map +1 -0
  204. package/dist/providers/OpenAIProvider.d.ts.map +1 -0
  205. package/dist/{src/providers → providers}/OpenAIProvider.js +18 -18
  206. package/dist/providers/OpenAIProvider.js.map +1 -0
  207. package/dist/providers/OpenRouterProvider.d.ts.map +1 -0
  208. package/dist/{src/providers → providers}/OpenRouterProvider.js +18 -18
  209. package/dist/providers/OpenRouterProvider.js.map +1 -0
  210. package/dist/providers/index.d.ts.map +1 -0
  211. package/dist/providers/index.js.map +1 -0
  212. package/dist/{src/types → types}/agent.d.ts +12 -4
  213. package/dist/types/agent.d.ts.map +1 -0
  214. package/dist/types/agent.js.map +1 -0
  215. package/dist/types/ai.d.ts.map +1 -0
  216. package/dist/types/ai.js.map +1 -0
  217. package/dist/types/history.d.ts.map +1 -0
  218. package/dist/types/history.js.map +1 -0
  219. package/dist/{src/types → types}/index.d.ts +5 -3
  220. package/dist/types/index.d.ts.map +1 -0
  221. package/dist/{src/types → types}/index.js +2 -0
  222. package/dist/types/index.js.map +1 -0
  223. package/dist/types/persistence.d.ts.map +1 -0
  224. package/dist/types/persistence.js.map +1 -0
  225. package/dist/{src/types → types}/route.d.ts +116 -15
  226. package/dist/types/route.d.ts.map +1 -0
  227. package/dist/{src/types → types}/route.js.map +1 -1
  228. package/dist/types/routing.d.ts.map +1 -0
  229. package/dist/{cjs/src/types → types}/routing.js.map +1 -1
  230. package/dist/types/schema.d.ts.map +1 -0
  231. package/dist/{cjs/src/types → types}/schema.js.map +1 -1
  232. package/dist/types/session.d.ts.map +1 -0
  233. package/dist/{src/types → types}/session.js.map +1 -1
  234. package/dist/types/template.d.ts +88 -0
  235. package/dist/types/template.d.ts.map +1 -0
  236. package/dist/{cjs/src/types → types}/template.js.map +1 -1
  237. package/dist/types/tool.d.ts +130 -0
  238. package/dist/types/tool.d.ts.map +1 -0
  239. package/dist/types/tool.js +16 -0
  240. package/dist/types/tool.js.map +1 -0
  241. package/dist/utils/clone.d.ts.map +1 -0
  242. package/dist/utils/clone.js.map +1 -0
  243. package/dist/utils/condition.d.ts +38 -0
  244. package/dist/utils/condition.d.ts.map +1 -0
  245. package/dist/utils/condition.js +161 -0
  246. package/dist/utils/condition.js.map +1 -0
  247. package/dist/utils/event.d.ts.map +1 -0
  248. package/dist/utils/event.js.map +1 -0
  249. package/dist/utils/history.d.ts.map +1 -0
  250. package/dist/utils/history.js.map +1 -0
  251. package/dist/utils/id.d.ts.map +1 -0
  252. package/dist/utils/id.js.map +1 -0
  253. package/dist/{src/utils → utils}/index.d.ts +3 -1
  254. package/dist/utils/index.d.ts.map +1 -0
  255. package/dist/{src/utils → utils}/index.js +5 -1
  256. package/dist/utils/index.js.map +1 -0
  257. package/dist/utils/json.d.ts +16 -0
  258. package/dist/utils/json.d.ts.map +1 -0
  259. package/dist/utils/json.js +43 -0
  260. package/dist/utils/json.js.map +1 -0
  261. package/dist/utils/logger.d.ts.map +1 -0
  262. package/dist/utils/logger.js.map +1 -0
  263. package/dist/{cjs/src/utils → utils}/retry.d.ts +0 -3
  264. package/dist/utils/retry.d.ts.map +1 -0
  265. package/dist/{src/utils → utils}/retry.js +5 -4
  266. package/dist/utils/retry.js.map +1 -0
  267. package/dist/utils/session.d.ts.map +1 -0
  268. package/dist/utils/session.js.map +1 -0
  269. package/dist/{cjs/src/utils → utils}/template.d.ts +48 -0
  270. package/dist/utils/template.d.ts.map +1 -0
  271. package/dist/{src/utils → utils}/template.js +98 -0
  272. package/dist/utils/template.js.map +1 -0
  273. package/docs/CONTRIBUTING.md +40 -0
  274. package/docs/README.md +12 -5
  275. package/docs/api/README.md +295 -56
  276. package/docs/api/overview.md +272 -31
  277. package/docs/architecture/data-extraction-flow.md +363 -0
  278. package/docs/architecture/multi-step-execution.md +243 -0
  279. package/docs/core/agent/README.md +120 -5
  280. package/docs/core/agent/session-management.md +153 -6
  281. package/docs/core/ai-integration/prompt-composition.md +135 -0
  282. package/docs/core/ai-integration/response-processing.md +261 -4
  283. package/docs/core/conversation-flows/data-collection.md +143 -0
  284. package/docs/core/conversation-flows/routes.md +132 -2
  285. package/docs/core/conversation-flows/step-transitions.md +132 -0
  286. package/docs/core/conversation-flows/steps.md +112 -0
  287. package/docs/core/error-handling.md +831 -0
  288. package/docs/core/routing/intelligent-routing.md +118 -0
  289. package/docs/core/tools/tool-definition.md +684 -60
  290. package/docs/core/tools/tool-scoping.md +244 -53
  291. package/docs/guides/error-handling-patterns.md +578 -0
  292. package/docs/guides/getting-started/README.md +423 -31
  293. package/docs/guides/migration/README.md +23 -0
  294. package/docs/guides/migration/flexible-routing-conditions.md +375 -0
  295. package/docs/guides/migration/multi-step-execution.md +303 -0
  296. package/examples/advanced-patterns/knowledge-based-agent.ts +107 -30
  297. package/examples/advanced-patterns/persistent-onboarding.ts +70 -48
  298. package/examples/advanced-patterns/route-lifecycle-hooks.ts +82 -12
  299. package/examples/advanced-patterns/streaming-responses.ts +2 -2
  300. package/examples/ai-providers/anthropic-integration.ts +13 -9
  301. package/examples/ai-providers/openai-integration.ts +12 -8
  302. package/examples/condition-patterns/function-only-conditions.ts +365 -0
  303. package/examples/condition-patterns/mixed-array-conditions.ts +477 -0
  304. package/examples/condition-patterns/route-skipif-patterns.ts +468 -0
  305. package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
  306. package/examples/condition-patterns/string-only-conditions.ts +296 -0
  307. package/examples/conversation-flows/completion-transitions.ts +48 -7
  308. package/examples/core-concepts/basic-agent.ts +158 -98
  309. package/examples/core-concepts/schema-driven-extraction.ts +43 -16
  310. package/examples/core-concepts/session-management.ts +117 -29
  311. package/examples/integrations/database-integration.ts +6 -6
  312. package/examples/integrations/healthcare-integration.ts +25 -39
  313. package/examples/integrations/search-integration.ts +8 -8
  314. package/examples/integrations/server-session-management.ts +11 -11
  315. package/examples/persistence/database-persistence.ts +15 -15
  316. package/examples/persistence/memory-sessions.ts +6 -6
  317. package/examples/persistence/redis-persistence.ts +7 -9
  318. package/examples/tools/basic-tools.ts +293 -89
  319. package/examples/tools/data-enrichment-tools.ts +189 -79
  320. package/package.json +6 -4
  321. package/src/adapters/PrismaAdapter.ts +3 -2
  322. package/src/adapters/RedisAdapter.ts +3 -3
  323. package/src/core/Agent.ts +152 -46
  324. package/src/core/BatchExecutor.ts +1156 -0
  325. package/src/core/BatchPromptBuilder.ts +275 -0
  326. package/src/core/PromptComposer.ts +53 -16
  327. package/src/core/ResponseEngine.ts +143 -4
  328. package/src/core/ResponseModal.ts +1035 -137
  329. package/src/core/ResponsePipeline.ts +99 -65
  330. package/src/core/Route.ts +262 -34
  331. package/src/core/RoutingEngine.ts +467 -120
  332. package/src/core/SessionManager.ts +39 -7
  333. package/src/core/Step.ts +338 -32
  334. package/src/core/ToolManager.ts +1394 -0
  335. package/src/index.ts +27 -3
  336. package/src/providers/AnthropicProvider.ts +17 -17
  337. package/src/providers/GeminiProvider.ts +129 -60
  338. package/src/providers/OpenAIProvider.ts +18 -18
  339. package/src/providers/OpenRouterProvider.ts +18 -18
  340. package/src/types/agent.ts +12 -4
  341. package/src/types/index.ts +25 -3
  342. package/src/types/route.ts +136 -15
  343. package/src/types/template.ts +70 -2
  344. package/src/types/tool.ts +116 -25
  345. package/src/utils/condition.ts +190 -0
  346. package/src/utils/index.ts +12 -0
  347. package/src/utils/json.ts +46 -0
  348. package/src/utils/retry.ts +5 -4
  349. package/src/utils/template.ts +109 -0
  350. package/dist/cjs/src/adapters/MemoryAdapter.d.ts.map +0 -1
  351. package/dist/cjs/src/adapters/MemoryAdapter.js.map +0 -1
  352. package/dist/cjs/src/adapters/MongoAdapter.d.ts.map +0 -1
  353. package/dist/cjs/src/adapters/MongoAdapter.js.map +0 -1
  354. package/dist/cjs/src/adapters/OpenSearchAdapter.d.ts.map +0 -1
  355. package/dist/cjs/src/adapters/OpenSearchAdapter.js.map +0 -1
  356. package/dist/cjs/src/adapters/PostgreSQLAdapter.d.ts.map +0 -1
  357. package/dist/cjs/src/adapters/PostgreSQLAdapter.js.map +0 -1
  358. package/dist/cjs/src/adapters/PrismaAdapter.d.ts.map +0 -1
  359. package/dist/cjs/src/adapters/PrismaAdapter.js.map +0 -1
  360. package/dist/cjs/src/adapters/RedisAdapter.d.ts.map +0 -1
  361. package/dist/cjs/src/adapters/RedisAdapter.js.map +0 -1
  362. package/dist/cjs/src/adapters/SQLiteAdapter.d.ts.map +0 -1
  363. package/dist/cjs/src/adapters/SQLiteAdapter.js.map +0 -1
  364. package/dist/cjs/src/adapters/index.d.ts.map +0 -1
  365. package/dist/cjs/src/adapters/index.js.map +0 -1
  366. package/dist/cjs/src/constants/index.d.ts.map +0 -1
  367. package/dist/cjs/src/constants/index.js.map +0 -1
  368. package/dist/cjs/src/core/Agent.d.ts.map +0 -1
  369. package/dist/cjs/src/core/Agent.js.map +0 -1
  370. package/dist/cjs/src/core/Events.d.ts.map +0 -1
  371. package/dist/cjs/src/core/Events.js.map +0 -1
  372. package/dist/cjs/src/core/PersistenceManager.d.ts.map +0 -1
  373. package/dist/cjs/src/core/PersistenceManager.js.map +0 -1
  374. package/dist/cjs/src/core/PromptComposer.d.ts.map +0 -1
  375. package/dist/cjs/src/core/PromptComposer.js.map +0 -1
  376. package/dist/cjs/src/core/ResponseEngine.d.ts.map +0 -1
  377. package/dist/cjs/src/core/ResponseEngine.js +0 -84
  378. package/dist/cjs/src/core/ResponseEngine.js.map +0 -1
  379. package/dist/cjs/src/core/ResponseModal.d.ts.map +0 -1
  380. package/dist/cjs/src/core/ResponseModal.js.map +0 -1
  381. package/dist/cjs/src/core/ResponsePipeline.d.ts.map +0 -1
  382. package/dist/cjs/src/core/ResponsePipeline.js.map +0 -1
  383. package/dist/cjs/src/core/Route.d.ts.map +0 -1
  384. package/dist/cjs/src/core/Route.js +0 -343
  385. package/dist/cjs/src/core/Route.js.map +0 -1
  386. package/dist/cjs/src/core/RoutingEngine.d.ts.map +0 -1
  387. package/dist/cjs/src/core/RoutingEngine.js.map +0 -1
  388. package/dist/cjs/src/core/SessionManager.d.ts.map +0 -1
  389. package/dist/cjs/src/core/SessionManager.js.map +0 -1
  390. package/dist/cjs/src/core/Step.d.ts +0 -96
  391. package/dist/cjs/src/core/Step.d.ts.map +0 -1
  392. package/dist/cjs/src/core/Step.js +0 -206
  393. package/dist/cjs/src/core/Step.js.map +0 -1
  394. package/dist/cjs/src/core/ToolExecutor.d.ts +0 -45
  395. package/dist/cjs/src/core/ToolExecutor.d.ts.map +0 -1
  396. package/dist/cjs/src/core/ToolExecutor.js +0 -84
  397. package/dist/cjs/src/core/ToolExecutor.js.map +0 -1
  398. package/dist/cjs/src/index.d.ts.map +0 -1
  399. package/dist/cjs/src/index.js.map +0 -1
  400. package/dist/cjs/src/providers/AnthropicProvider.d.ts.map +0 -1
  401. package/dist/cjs/src/providers/AnthropicProvider.js.map +0 -1
  402. package/dist/cjs/src/providers/GeminiProvider.d.ts.map +0 -1
  403. package/dist/cjs/src/providers/GeminiProvider.js.map +0 -1
  404. package/dist/cjs/src/providers/OpenAIProvider.d.ts.map +0 -1
  405. package/dist/cjs/src/providers/OpenAIProvider.js.map +0 -1
  406. package/dist/cjs/src/providers/OpenRouterProvider.d.ts.map +0 -1
  407. package/dist/cjs/src/providers/OpenRouterProvider.js.map +0 -1
  408. package/dist/cjs/src/providers/index.d.ts.map +0 -1
  409. package/dist/cjs/src/providers/index.js.map +0 -1
  410. package/dist/cjs/src/types/agent.d.ts.map +0 -1
  411. package/dist/cjs/src/types/agent.js.map +0 -1
  412. package/dist/cjs/src/types/ai.d.ts.map +0 -1
  413. package/dist/cjs/src/types/ai.js.map +0 -1
  414. package/dist/cjs/src/types/history.d.ts.map +0 -1
  415. package/dist/cjs/src/types/history.js.map +0 -1
  416. package/dist/cjs/src/types/index.d.ts.map +0 -1
  417. package/dist/cjs/src/types/index.js.map +0 -1
  418. package/dist/cjs/src/types/persistence.d.ts.map +0 -1
  419. package/dist/cjs/src/types/persistence.js.map +0 -1
  420. package/dist/cjs/src/types/route.d.ts.map +0 -1
  421. package/dist/cjs/src/types/routing.d.ts.map +0 -1
  422. package/dist/cjs/src/types/schema.d.ts.map +0 -1
  423. package/dist/cjs/src/types/session.d.ts.map +0 -1
  424. package/dist/cjs/src/types/session.js.map +0 -1
  425. package/dist/cjs/src/types/template.d.ts +0 -30
  426. package/dist/cjs/src/types/template.d.ts.map +0 -1
  427. package/dist/cjs/src/types/tool.d.ts +0 -60
  428. package/dist/cjs/src/types/tool.d.ts.map +0 -1
  429. package/dist/cjs/src/types/tool.js +0 -6
  430. package/dist/cjs/src/types/tool.js.map +0 -1
  431. package/dist/cjs/src/utils/clone.d.ts.map +0 -1
  432. package/dist/cjs/src/utils/clone.js.map +0 -1
  433. package/dist/cjs/src/utils/event.d.ts.map +0 -1
  434. package/dist/cjs/src/utils/event.js.map +0 -1
  435. package/dist/cjs/src/utils/history.d.ts.map +0 -1
  436. package/dist/cjs/src/utils/history.js.map +0 -1
  437. package/dist/cjs/src/utils/id.d.ts.map +0 -1
  438. package/dist/cjs/src/utils/id.js.map +0 -1
  439. package/dist/cjs/src/utils/index.d.ts.map +0 -1
  440. package/dist/cjs/src/utils/index.js.map +0 -1
  441. package/dist/cjs/src/utils/logger.d.ts.map +0 -1
  442. package/dist/cjs/src/utils/logger.js.map +0 -1
  443. package/dist/cjs/src/utils/retry.d.ts.map +0 -1
  444. package/dist/cjs/src/utils/retry.js.map +0 -1
  445. package/dist/cjs/src/utils/session.d.ts.map +0 -1
  446. package/dist/cjs/src/utils/session.js.map +0 -1
  447. package/dist/cjs/src/utils/template.d.ts.map +0 -1
  448. package/dist/cjs/src/utils/template.js.map +0 -1
  449. package/dist/src/adapters/MemoryAdapter.js.map +0 -1
  450. package/dist/src/adapters/MongoAdapter.js.map +0 -1
  451. package/dist/src/adapters/OpenSearchAdapter.js.map +0 -1
  452. package/dist/src/adapters/PostgreSQLAdapter.js.map +0 -1
  453. package/dist/src/adapters/PrismaAdapter.js.map +0 -1
  454. package/dist/src/adapters/RedisAdapter.js.map +0 -1
  455. package/dist/src/adapters/SQLiteAdapter.js.map +0 -1
  456. package/dist/src/adapters/index.js.map +0 -1
  457. package/dist/src/constants/index.js.map +0 -1
  458. package/dist/src/core/Agent.d.ts.map +0 -1
  459. package/dist/src/core/Agent.js.map +0 -1
  460. package/dist/src/core/Events.js.map +0 -1
  461. package/dist/src/core/PersistenceManager.js.map +0 -1
  462. package/dist/src/core/PromptComposer.d.ts.map +0 -1
  463. package/dist/src/core/PromptComposer.js.map +0 -1
  464. package/dist/src/core/ResponseEngine.js +0 -80
  465. package/dist/src/core/ResponseEngine.js.map +0 -1
  466. package/dist/src/core/ResponseModal.d.ts.map +0 -1
  467. package/dist/src/core/ResponseModal.js.map +0 -1
  468. package/dist/src/core/ResponsePipeline.d.ts.map +0 -1
  469. package/dist/src/core/ResponsePipeline.js.map +0 -1
  470. package/dist/src/core/Route.d.ts.map +0 -1
  471. package/dist/src/core/Route.js +0 -339
  472. package/dist/src/core/Route.js.map +0 -1
  473. package/dist/src/core/RoutingEngine.d.ts.map +0 -1
  474. package/dist/src/core/RoutingEngine.js.map +0 -1
  475. package/dist/src/core/SessionManager.d.ts.map +0 -1
  476. package/dist/src/core/SessionManager.js.map +0 -1
  477. package/dist/src/core/Step.d.ts +0 -96
  478. package/dist/src/core/Step.d.ts.map +0 -1
  479. package/dist/src/core/Step.js +0 -202
  480. package/dist/src/core/Step.js.map +0 -1
  481. package/dist/src/core/ToolExecutor.d.ts +0 -45
  482. package/dist/src/core/ToolExecutor.d.ts.map +0 -1
  483. package/dist/src/core/ToolExecutor.js +0 -80
  484. package/dist/src/core/ToolExecutor.js.map +0 -1
  485. package/dist/src/index.d.ts.map +0 -1
  486. package/dist/src/index.js.map +0 -1
  487. package/dist/src/providers/AnthropicProvider.js.map +0 -1
  488. package/dist/src/providers/GeminiProvider.js.map +0 -1
  489. package/dist/src/providers/OpenAIProvider.js.map +0 -1
  490. package/dist/src/providers/OpenRouterProvider.js.map +0 -1
  491. package/dist/src/providers/index.js.map +0 -1
  492. package/dist/src/types/agent.d.ts.map +0 -1
  493. package/dist/src/types/agent.js.map +0 -1
  494. package/dist/src/types/history.js.map +0 -1
  495. package/dist/src/types/index.js.map +0 -1
  496. package/dist/src/types/persistence.js.map +0 -1
  497. package/dist/src/types/route.d.ts.map +0 -1
  498. package/dist/src/types/template.d.ts +0 -30
  499. package/dist/src/types/template.d.ts.map +0 -1
  500. package/dist/src/types/tool.d.ts +0 -60
  501. package/dist/src/types/tool.d.ts.map +0 -1
  502. package/dist/src/types/tool.js +0 -5
  503. package/dist/src/types/tool.js.map +0 -1
  504. package/dist/src/utils/clone.js.map +0 -1
  505. package/dist/src/utils/event.js.map +0 -1
  506. package/dist/src/utils/history.js.map +0 -1
  507. package/dist/src/utils/id.js.map +0 -1
  508. package/dist/src/utils/index.d.ts.map +0 -1
  509. package/dist/src/utils/index.js.map +0 -1
  510. package/dist/src/utils/logger.js.map +0 -1
  511. package/dist/src/utils/retry.d.ts.map +0 -1
  512. package/dist/src/utils/retry.js.map +0 -1
  513. package/dist/src/utils/session.js.map +0 -1
  514. package/dist/src/utils/template.d.ts.map +0 -1
  515. package/dist/src/utils/template.js.map +0 -1
  516. package/docs/core/tools/tool-execution.md +0 -815
  517. package/src/core/ToolExecutor.ts +0 -126
  518. /package/dist/{cjs/src/adapters → adapters}/MemoryAdapter.d.ts +0 -0
  519. /package/dist/{src/adapters → adapters}/MemoryAdapter.js +0 -0
  520. /package/dist/{cjs/src/adapters → adapters}/MongoAdapter.d.ts +0 -0
  521. /package/dist/{src/adapters → adapters}/MongoAdapter.js +0 -0
  522. /package/dist/{cjs/src/adapters → adapters}/OpenSearchAdapter.d.ts +0 -0
  523. /package/dist/{src/adapters → adapters}/OpenSearchAdapter.js +0 -0
  524. /package/dist/{cjs/src/adapters → adapters}/PostgreSQLAdapter.d.ts +0 -0
  525. /package/dist/{src/adapters → adapters}/PostgreSQLAdapter.js +0 -0
  526. /package/dist/{cjs/src/adapters → adapters}/PrismaAdapter.d.ts +0 -0
  527. /package/dist/{cjs/src/adapters → adapters}/RedisAdapter.d.ts +0 -0
  528. /package/dist/{cjs/src/adapters → adapters}/SQLiteAdapter.d.ts +0 -0
  529. /package/dist/{src/adapters → adapters}/SQLiteAdapter.js +0 -0
  530. /package/dist/{cjs/src/adapters → adapters}/index.d.ts +0 -0
  531. /package/dist/{src/adapters → adapters}/index.js +0 -0
  532. /package/dist/{src → cjs}/adapters/MemoryAdapter.d.ts +0 -0
  533. /package/dist/{src → cjs}/adapters/MemoryAdapter.d.ts.map +0 -0
  534. /package/dist/cjs/{src/adapters → adapters}/MemoryAdapter.js +0 -0
  535. /package/dist/{src → cjs}/adapters/MongoAdapter.d.ts +0 -0
  536. /package/dist/{src → cjs}/adapters/MongoAdapter.d.ts.map +0 -0
  537. /package/dist/cjs/{src/adapters → adapters}/MongoAdapter.js +0 -0
  538. /package/dist/{src → cjs}/adapters/OpenSearchAdapter.d.ts +0 -0
  539. /package/dist/{src → cjs}/adapters/OpenSearchAdapter.d.ts.map +0 -0
  540. /package/dist/cjs/{src/adapters → adapters}/OpenSearchAdapter.js +0 -0
  541. /package/dist/{src → cjs}/adapters/PostgreSQLAdapter.d.ts +0 -0
  542. /package/dist/{src → cjs}/adapters/PostgreSQLAdapter.d.ts.map +0 -0
  543. /package/dist/cjs/{src/adapters → adapters}/PostgreSQLAdapter.js +0 -0
  544. /package/dist/{src → cjs}/adapters/PrismaAdapter.d.ts +0 -0
  545. /package/dist/{src → cjs}/adapters/RedisAdapter.d.ts +0 -0
  546. /package/dist/{src → cjs}/adapters/RedisAdapter.d.ts.map +0 -0
  547. /package/dist/{src → cjs}/adapters/SQLiteAdapter.d.ts +0 -0
  548. /package/dist/{src → cjs}/adapters/SQLiteAdapter.d.ts.map +0 -0
  549. /package/dist/cjs/{src/adapters → adapters}/SQLiteAdapter.js +0 -0
  550. /package/dist/{src → cjs}/adapters/index.d.ts +0 -0
  551. /package/dist/{src → cjs}/adapters/index.d.ts.map +0 -0
  552. /package/dist/cjs/{src/adapters → adapters}/index.js +0 -0
  553. /package/dist/cjs/{src/constants → constants}/index.d.ts +0 -0
  554. /package/dist/{src → cjs}/constants/index.d.ts.map +0 -0
  555. /package/dist/cjs/{src/constants → constants}/index.js +0 -0
  556. /package/dist/cjs/{src/core → core}/Events.d.ts +0 -0
  557. /package/dist/{src → cjs}/core/Events.d.ts.map +0 -0
  558. /package/dist/cjs/{src/core → core}/Events.js +0 -0
  559. /package/dist/cjs/{src/core → core}/PersistenceManager.d.ts +0 -0
  560. /package/dist/{src → cjs}/core/PersistenceManager.d.ts.map +0 -0
  561. /package/dist/cjs/{src/core → core}/PersistenceManager.js +0 -0
  562. /package/dist/cjs/{src/core → core}/ResponseEngine.d.ts +0 -0
  563. /package/dist/cjs/{src/providers → providers}/AnthropicProvider.d.ts +0 -0
  564. /package/dist/{src → cjs}/providers/AnthropicProvider.d.ts.map +0 -0
  565. /package/dist/cjs/{src/providers → providers}/GeminiProvider.d.ts +0 -0
  566. /package/dist/cjs/{src/providers → providers}/OpenAIProvider.d.ts +0 -0
  567. /package/dist/{src → cjs}/providers/OpenAIProvider.d.ts.map +0 -0
  568. /package/dist/cjs/{src/providers → providers}/OpenRouterProvider.d.ts +0 -0
  569. /package/dist/{src → cjs}/providers/OpenRouterProvider.d.ts.map +0 -0
  570. /package/dist/cjs/{src/providers → providers}/index.d.ts +0 -0
  571. /package/dist/{src → cjs}/providers/index.d.ts.map +0 -0
  572. /package/dist/cjs/{src/providers → providers}/index.js +0 -0
  573. /package/dist/cjs/{src/types → types}/agent.js +0 -0
  574. /package/dist/cjs/{src/types → types}/ai.d.ts +0 -0
  575. /package/dist/{src → cjs}/types/ai.d.ts.map +0 -0
  576. /package/dist/cjs/{src/types → types}/ai.js +0 -0
  577. /package/dist/cjs/{src/types → types}/history.d.ts +0 -0
  578. /package/dist/{src → cjs}/types/history.d.ts.map +0 -0
  579. /package/dist/cjs/{src/types → types}/history.js +0 -0
  580. /package/dist/cjs/{src/types → types}/persistence.d.ts +0 -0
  581. /package/dist/{src → cjs}/types/persistence.d.ts.map +0 -0
  582. /package/dist/cjs/{src/types → types}/persistence.js +0 -0
  583. /package/dist/cjs/{src/types → types}/route.js +0 -0
  584. /package/dist/cjs/{src/types → types}/routing.d.ts +0 -0
  585. /package/dist/{src → cjs}/types/routing.d.ts.map +0 -0
  586. /package/dist/cjs/{src/types → types}/routing.js +0 -0
  587. /package/dist/{src → cjs}/types/routing.js.map +0 -0
  588. /package/dist/cjs/{src/types → types}/schema.d.ts +0 -0
  589. /package/dist/{src → cjs}/types/schema.d.ts.map +0 -0
  590. /package/dist/cjs/{src/types → types}/schema.js +0 -0
  591. /package/dist/{src → cjs}/types/schema.js.map +0 -0
  592. /package/dist/cjs/{src/types → types}/session.d.ts +0 -0
  593. /package/dist/{src → cjs}/types/session.d.ts.map +0 -0
  594. /package/dist/cjs/{src/types → types}/session.js +0 -0
  595. /package/dist/cjs/{src/types → types}/template.js +0 -0
  596. /package/dist/{src → cjs}/types/template.js.map +0 -0
  597. /package/dist/cjs/{src/utils → utils}/clone.d.ts +0 -0
  598. /package/dist/{src → cjs}/utils/clone.d.ts.map +0 -0
  599. /package/dist/cjs/{src/utils → utils}/clone.js +0 -0
  600. /package/dist/cjs/{src/utils → utils}/event.d.ts +0 -0
  601. /package/dist/{src → cjs}/utils/event.d.ts.map +0 -0
  602. /package/dist/cjs/{src/utils → utils}/event.js +0 -0
  603. /package/dist/cjs/{src/utils → utils}/history.d.ts +0 -0
  604. /package/dist/{src → cjs}/utils/history.d.ts.map +0 -0
  605. /package/dist/cjs/{src/utils → utils}/history.js +0 -0
  606. /package/dist/cjs/{src/utils → utils}/id.d.ts +0 -0
  607. /package/dist/{src → cjs}/utils/id.d.ts.map +0 -0
  608. /package/dist/cjs/{src/utils → utils}/id.js +0 -0
  609. /package/dist/cjs/{src/utils → utils}/logger.d.ts +0 -0
  610. /package/dist/{src → cjs}/utils/logger.d.ts.map +0 -0
  611. /package/dist/cjs/{src/utils → utils}/logger.js +0 -0
  612. /package/dist/cjs/{src/utils → utils}/session.d.ts +0 -0
  613. /package/dist/{src → cjs}/utils/session.d.ts.map +0 -0
  614. /package/dist/cjs/{src/utils → utils}/session.js +0 -0
  615. /package/dist/{src/constants → constants}/index.d.ts +0 -0
  616. /package/dist/{src/constants → constants}/index.js +0 -0
  617. /package/dist/{src/core → core}/Events.d.ts +0 -0
  618. /package/dist/{src/core → core}/Events.js +0 -0
  619. /package/dist/{src/core → core}/PersistenceManager.d.ts +0 -0
  620. /package/dist/{src/core → core}/PersistenceManager.js +0 -0
  621. /package/dist/{src/core → core}/ResponseEngine.d.ts +0 -0
  622. /package/dist/{src/providers → providers}/AnthropicProvider.d.ts +0 -0
  623. /package/dist/{src/providers → providers}/GeminiProvider.d.ts +0 -0
  624. /package/dist/{src/providers → providers}/OpenAIProvider.d.ts +0 -0
  625. /package/dist/{src/providers → providers}/OpenRouterProvider.d.ts +0 -0
  626. /package/dist/{src/providers → providers}/index.d.ts +0 -0
  627. /package/dist/{src/providers → providers}/index.js +0 -0
  628. /package/dist/{src/types → types}/agent.js +0 -0
  629. /package/dist/{src/types → types}/ai.d.ts +0 -0
  630. /package/dist/{src/types → types}/ai.js +0 -0
  631. /package/dist/{src/types → types}/history.d.ts +0 -0
  632. /package/dist/{src/types → types}/history.js +0 -0
  633. /package/dist/{src/types → types}/persistence.d.ts +0 -0
  634. /package/dist/{src/types → types}/persistence.js +0 -0
  635. /package/dist/{src/types → types}/route.js +0 -0
  636. /package/dist/{src/types → types}/routing.d.ts +0 -0
  637. /package/dist/{src/types → types}/routing.js +0 -0
  638. /package/dist/{src/types → types}/schema.d.ts +0 -0
  639. /package/dist/{src/types → types}/schema.js +0 -0
  640. /package/dist/{src/types → types}/session.d.ts +0 -0
  641. /package/dist/{src/types → types}/session.js +0 -0
  642. /package/dist/{src/types → types}/template.js +0 -0
  643. /package/dist/{src/utils → utils}/clone.d.ts +0 -0
  644. /package/dist/{src/utils → utils}/clone.js +0 -0
  645. /package/dist/{src/utils → utils}/event.d.ts +0 -0
  646. /package/dist/{src/utils → utils}/event.js +0 -0
  647. /package/dist/{src/utils → utils}/history.d.ts +0 -0
  648. /package/dist/{src/utils → utils}/history.js +0 -0
  649. /package/dist/{src/utils → utils}/id.d.ts +0 -0
  650. /package/dist/{src/utils → utils}/id.js +0 -0
  651. /package/dist/{src/utils → utils}/logger.d.ts +0 -0
  652. /package/dist/{src/utils → utils}/logger.js +0 -0
  653. /package/dist/{src/utils → utils}/session.d.ts +0 -0
  654. /package/dist/{src/utils → utils}/session.js +0 -0
@@ -6,8 +6,10 @@ import { EventKind, MessageRole } from "../types";
6
6
  import { Step } from "./Step";
7
7
  import { ResponseEngine } from "./ResponseEngine";
8
8
  import { ResponsePipeline } from "./ResponsePipeline";
9
+ import { BatchExecutor } from "./BatchExecutor";
10
+ import { BatchPromptBuilder } from "./BatchPromptBuilder";
9
11
  import { cloneDeep, mergeCollected, enterStep, getLastMessageFromHistory, render, logger, historyToEvents } from "../utils";
10
- import { ToolExecutor } from "./ToolExecutor";
12
+ import { createTemplateContext } from "../utils/template";
11
13
  import { END_ROUTE_ID } from "../constants";
12
14
  /**
13
15
  * Error class for response generation failures
@@ -47,7 +49,12 @@ export class ResponseModal {
47
49
  // Initialize response engine
48
50
  this.responseEngine = new ResponseEngine();
49
51
  // Initialize response pipeline with agent dependencies
50
- this.responsePipeline = new ResponsePipeline(this.agent.getAgentOptions(), this.agent.getRoutes(), this.agent.getTools(), this.agent.getRoutingEngine(), this.agent.updateContext.bind(this.agent), this.agent.getUpdateDataMethod(), this.agent.updateCollectedData.bind(this.agent));
52
+ this.responsePipeline = new ResponsePipeline(this.agent.getAgentOptions(), () => this.agent.getRoutes(), // Pass a function to get routes dynamically
53
+ this.agent.getTools(), this.agent.getRoutingEngine(), this.agent.updateContext.bind(this.agent), this.agent.getUpdateDataMethod(), this.agent.updateCollectedData.bind(this.agent), this.getToolManager());
54
+ // Initialize batch executor for multi-step execution
55
+ this.batchExecutor = new BatchExecutor();
56
+ // Initialize batch prompt builder for combined prompts
57
+ this.batchPromptBuilder = new BatchPromptBuilder();
51
58
  }
52
59
  /**
53
60
  * Generate a non-streaming response using unified logic
@@ -191,6 +198,19 @@ export class ResponseModal {
191
198
  getResponsePipeline() {
192
199
  return this.responsePipeline;
193
200
  }
201
+ /**
202
+ * Get the ToolManager instance from the agent
203
+ * @private
204
+ */
205
+ getToolManager() {
206
+ // Check if agent has a tool property (ToolManager)
207
+ if (this.agent && 'tool' in this.agent && this.agent.tool) {
208
+ return this.agent.tool;
209
+ }
210
+ // Log warning if ToolManager is not available
211
+ logger.warn(`[ResponseModal] ToolManager not available on agent - tool execution will use fallback methods`);
212
+ return undefined;
213
+ }
194
214
  // UNIFIED RESPONSE LOGIC - Consolidates common logic between streaming and non-streaming
195
215
  // ============================================================================
196
216
  /**
@@ -255,6 +275,7 @@ export class ResponseModal {
255
275
  throw ResponseGenerationError.fromError(error, 'step_preparation', params, { session, effectiveContext });
256
276
  }
257
277
  // PHASE 2: ROUTING + STEP SELECTION - Determine which route and step to use
278
+ // Also performs pre-extraction and batch determination
258
279
  let routingResult;
259
280
  try {
260
281
  routingResult = await this.handleUnifiedRoutingAndStepSelection({
@@ -275,6 +296,9 @@ export class ResponseModal {
275
296
  selectedStep: routingResult.selectedStep,
276
297
  responseDirectives: routingResult.responseDirectives,
277
298
  isRouteComplete: routingResult.isRouteComplete,
299
+ batchSteps: routingResult.batchSteps,
300
+ batchStoppedReason: routingResult.batchStoppedReason,
301
+ batchStoppedAtStep: routingResult.batchStoppedAtStep,
278
302
  };
279
303
  }
280
304
  catch (error) {
@@ -300,31 +324,156 @@ export class ResponseModal {
300
324
  context: params.context,
301
325
  signal: params.signal,
302
326
  });
327
+ let updatedSession = routingResult.session;
328
+ let isRouteComplete = routingResult.isRouteComplete;
329
+ // PRE-EXTRACTION: If entering a route that collects data, extract data from user message first
330
+ // This allows us to skip steps whose data is already provided
331
+ // Requirement 3.1: Perform Pre_Extraction before determining the Batch
332
+ if (routingResult.selectedRoute && !isRouteComplete) {
333
+ // Always pre-extract when route collects data (not just on new route entry)
334
+ // This ensures batch determination has the most up-to-date data
335
+ if (this.shouldPreExtractData(routingResult.selectedRoute)) {
336
+ logger.debug(`[ResponseModal] Pre-extracting data for route: ${routingResult.selectedRoute.title}`);
337
+ const extractedData = await this.preExtractRouteData({
338
+ route: routingResult.selectedRoute,
339
+ history: params.history,
340
+ context: params.context,
341
+ session: updatedSession,
342
+ signal: params.signal,
343
+ });
344
+ if (extractedData && Object.keys(extractedData).length > 0) {
345
+ logger.debug(`[ResponseModal] Pre-extracted data:`, extractedData);
346
+ // Requirement 3.3: Merge pre-extracted data into session before batch determination
347
+ updatedSession = mergeCollected(updatedSession, extractedData);
348
+ // Also update agent's collected data
349
+ await this.agent.updateCollectedData(extractedData);
350
+ // Re-check route completion after pre-extraction
351
+ const allRequiredFieldsCollected = routingResult.selectedRoute.isComplete(updatedSession.data || {});
352
+ if (allRequiredFieldsCollected) {
353
+ logger.debug(`[ResponseModal] Route ${routingResult.selectedRoute.title} completed after pre-extraction`);
354
+ isRouteComplete = true;
355
+ }
356
+ }
357
+ }
358
+ }
359
+ // BATCH DETERMINATION: Use BatchExecutor to determine which steps can execute together
360
+ // Requirement 3.4: Pre-extraction results affect batch determination
361
+ let batchSteps;
362
+ let batchStoppedReason;
363
+ let batchStoppedAtStep;
364
+ if (routingResult.selectedRoute && !isRouteComplete) {
365
+ // Determine current step position for batch determination
366
+ const currentStep = routingResult.selectedStep ||
367
+ (updatedSession.currentStep ? routingResult.selectedRoute.getStep(updatedSession.currentStep.id) : undefined);
368
+ logger.debug(`[ResponseModal] Determining batch starting from step: ${currentStep?.id || 'initial'}`);
369
+ const batchResult = await this.batchExecutor.determineBatch({
370
+ route: routingResult.selectedRoute,
371
+ currentStep,
372
+ sessionData: updatedSession.data || {},
373
+ context: params.context,
374
+ });
375
+ batchSteps = batchResult.steps;
376
+ batchStoppedReason = batchResult.stoppedReason;
377
+ batchStoppedAtStep = batchResult.stoppedAtStep;
378
+ logger.debug(`[ResponseModal] Batch determined: ${batchSteps.length} steps, stopped reason: ${batchStoppedReason}`);
379
+ }
303
380
  // Determine next step using pipeline method for consistency
304
- const stepResult = this.responsePipeline.determineNextStep({
381
+ const stepResult = await this.responsePipeline.determineNextStep({
305
382
  selectedRoute: routingResult.selectedRoute,
306
383
  selectedStep: routingResult.selectedStep,
307
- session: routingResult.session,
308
- isRouteComplete: routingResult.isRouteComplete,
384
+ session: updatedSession, // Use updated session with pre-extracted data
385
+ isRouteComplete, // Use updated completion status
309
386
  });
310
387
  return {
311
388
  selectedRoute: routingResult.selectedRoute,
312
389
  selectedStep: stepResult.nextStep, // Use the determined next step
313
390
  responseDirectives: routingResult.responseDirectives,
314
391
  session: stepResult.session,
315
- isRouteComplete: routingResult.isRouteComplete,
392
+ isRouteComplete, // Use updated completion status
393
+ batchSteps,
394
+ batchStoppedReason,
395
+ batchStoppedAtStep,
316
396
  };
317
397
  }
318
398
  catch (error) {
319
399
  throw ResponseGenerationError.fromError(error, 'routing_optimization', params);
320
400
  }
321
401
  }
402
+ /**
403
+ * Check if a route should pre-extract data before determining the initial step
404
+ * @private
405
+ */
406
+ shouldPreExtractData(route) {
407
+ // Pre-extract if route has declared required or optional fields
408
+ if (route.requiredFields && route.requiredFields.length > 0) {
409
+ return true;
410
+ }
411
+ if (route.optionalFields && route.optionalFields.length > 0) {
412
+ return true;
413
+ }
414
+ // Pre-extract if any step in the route collects data
415
+ const steps = route.getAllSteps();
416
+ const hasDataCollectionSteps = steps.some(step => step.collect && step.collect.length > 0);
417
+ return hasDataCollectionSteps;
418
+ }
419
+ /**
420
+ * Pre-extract data from user message when entering a route
421
+ * This allows skipping steps whose data is already provided
422
+ * @private
423
+ */
424
+ async preExtractRouteData(params) {
425
+ const { route, history, context, signal } = params;
426
+ // Build a schema for data extraction based on route's fields
427
+ const extractionSchema = this.agent.getSchema();
428
+ if (!extractionSchema) {
429
+ logger.warn(`[ResponseModal] No schema available for pre-extraction`);
430
+ return {};
431
+ }
432
+ // Get last user message
433
+ const lastMessage = getLastMessageFromHistory(history);
434
+ // Build extraction prompt
435
+ const extractionPrompt = [
436
+ `Extract any relevant information from the user's message that matches the following data fields.`,
437
+ `Only extract information that is explicitly stated or clearly implied.`,
438
+ ``,
439
+ `User's message: "${lastMessage}"`,
440
+ ``,
441
+ `Extract data for these fields if present:`,
442
+ ];
443
+ // Add field descriptions
444
+ if (route.requiredFields) {
445
+ extractionPrompt.push(`Required fields: ${route.requiredFields.join(', ')}`);
446
+ }
447
+ if (route.optionalFields) {
448
+ extractionPrompt.push(`Optional fields: ${route.optionalFields.join(', ')}`);
449
+ }
450
+ extractionPrompt.push(``, `Return ONLY the extracted data as JSON. If no data can be extracted, return an empty object {}.`);
451
+ // Call AI to extract data
452
+ const agentOptions = this.agent.getAgentOptions();
453
+ try {
454
+ const result = await agentOptions.provider.generateMessage({
455
+ prompt: extractionPrompt.join('\n'),
456
+ history,
457
+ context,
458
+ signal,
459
+ parameters: {
460
+ jsonSchema: extractionSchema,
461
+ schemaName: 'data_extraction',
462
+ },
463
+ });
464
+ return result.structured || {};
465
+ }
466
+ catch (error) {
467
+ logger.error(`[ResponseModal] Pre-extraction failed:`, error);
468
+ return {};
469
+ }
470
+ }
322
471
  /**
323
472
  * Unified response generation for non-streaming responses
324
473
  * @private
325
474
  */
326
475
  async generateUnifiedResponse(responseContext) {
327
- const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete } = responseContext;
476
+ const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete, batchSteps, batchStoppedReason, } = responseContext;
328
477
  let session = initialSession;
329
478
  // Get last user message (needed for both route and completion handling)
330
479
  // Convert HistoryItem[] to Event[] for internal processing
@@ -332,35 +481,79 @@ export class ResponseModal {
332
481
  const lastMessageText = getLastMessageFromHistory(historyEvents);
333
482
  let message;
334
483
  let toolCalls = undefined;
484
+ let executedSteps;
485
+ let stoppedReason;
335
486
  if (selectedRoute && !isRouteComplete) {
336
- // Handle normal route processing
337
- const result = await this.processRouteResponse({
338
- selectedRoute,
339
- selectedStep,
340
- responseDirectives,
341
- session,
342
- history,
343
- context: effectiveContext,
344
- lastMessageText,
345
- historyEvents,
346
- signal: responseContext.history ? undefined : undefined, // TODO: Fix signal passing
347
- });
348
- message = result.message;
349
- toolCalls = result.toolCalls;
350
- session = result.session;
487
+ // Check if we have batch steps to execute
488
+ if (batchSteps && batchSteps.length > 0) {
489
+ // BATCH EXECUTION: Execute multiple steps in a single LLM call
490
+ logger.debug(`[ResponseModal] Executing batch of ${batchSteps.length} steps`);
491
+ const batchResult = await this.executeBatchResponse({
492
+ selectedRoute,
493
+ batchSteps,
494
+ responseDirectives,
495
+ session,
496
+ history,
497
+ context: effectiveContext,
498
+ historyEvents,
499
+ });
500
+ message = batchResult.message;
501
+ toolCalls = batchResult.toolCalls;
502
+ session = batchResult.session;
503
+ executedSteps = batchResult.executedSteps;
504
+ stoppedReason = batchStoppedReason;
505
+ }
506
+ else {
507
+ // SINGLE STEP EXECUTION: Fall back to single-step processing
508
+ // This happens when batch determination returns empty (first step needs input)
509
+ const result = await this.processRouteResponse({
510
+ selectedRoute,
511
+ selectedStep,
512
+ responseDirectives,
513
+ session,
514
+ history,
515
+ context: effectiveContext,
516
+ lastMessageText,
517
+ historyEvents,
518
+ signal: undefined,
519
+ });
520
+ message = result.message;
521
+ toolCalls = result.toolCalls;
522
+ session = result.session;
523
+ // Track executed step for single-step execution
524
+ if (selectedStep) {
525
+ executedSteps = [{
526
+ id: selectedStep.id,
527
+ routeId: selectedRoute.id,
528
+ }];
529
+ }
530
+ stoppedReason = batchStoppedReason || 'needs_input';
531
+ }
351
532
  }
352
533
  else if (isRouteComplete && selectedRoute) {
353
534
  // Handle route completion
354
- message = await this.handleRouteCompletion({
355
- selectedRoute,
356
- session,
357
- context: effectiveContext,
358
- lastMessageText,
359
- historyEvents,
360
- });
361
- // Set step to END_ROUTE marker
362
- session = enterStep(session, END_ROUTE_ID, "Route completed");
363
- logger.debug(`[ResponseModal] Route ${selectedRoute.title} completed. Entered END_ROUTE step.`);
535
+ logger.debug(`[ResponseModal] Generating completion message for route: ${selectedRoute.title}`);
536
+ try {
537
+ message = await this.handleRouteCompletion({
538
+ selectedRoute,
539
+ session,
540
+ context: effectiveContext,
541
+ lastMessageText,
542
+ historyEvents,
543
+ signal: undefined,
544
+ });
545
+ // Set step to END_ROUTE marker
546
+ session = enterStep(session, END_ROUTE_ID, "Route completed");
547
+ stoppedReason = 'route_complete';
548
+ logger.debug(`[ResponseModal] Route ${selectedRoute.title} completed. Entered END_ROUTE step.`);
549
+ }
550
+ catch (error) {
551
+ logger.error(`[ResponseModal] Error generating completion message:`, error);
552
+ // Fallback to simple completion message
553
+ message = `Thank you! I've recorded all the information for your ${selectedRoute.title.toLowerCase()}.`;
554
+ session = enterStep(session, END_ROUTE_ID, "Route completed");
555
+ stoppedReason = 'route_complete';
556
+ }
364
557
  }
365
558
  else {
366
559
  // Fallback: No routes defined, generate a simple response
@@ -369,37 +562,268 @@ export class ResponseModal {
369
562
  context: effectiveContext,
370
563
  session,
371
564
  });
565
+ // For fallback responses, set empty executedSteps and no stoppedReason
566
+ // since there's no route/step execution happening
567
+ executedSteps = [];
568
+ stoppedReason = undefined;
372
569
  }
570
+ // Ensure response structure completeness (Requirement 8.1, 8.2, 8.3)
571
+ // - executedSteps: array of steps executed (empty array if none)
572
+ // - stoppedReason: why execution stopped (undefined for fallback)
573
+ // - session.currentStep: reflects final step position
373
574
  return {
374
575
  message,
375
576
  session,
376
577
  toolCalls,
377
578
  isRouteComplete,
579
+ executedSteps: executedSteps || [],
580
+ stoppedReason,
581
+ };
582
+ }
583
+ /**
584
+ * Execute a batch of steps with a single LLM call
585
+ *
586
+ * This method:
587
+ * 1. Executes all prepare hooks for steps in the batch (in order)
588
+ * 2. Builds a combined prompt using BatchPromptBuilder
589
+ * 3. Makes a single LLM call
590
+ * 4. Collects data from the response for all steps
591
+ * 5. Executes all finalize hooks for steps in the batch (in order)
592
+ *
593
+ * @private
594
+ * **Validates: Requirements 1.1, 4.4, 5.1, 5.2**
595
+ */
596
+ async executeBatchResponse(params) {
597
+ const { selectedRoute, batchSteps, history, context, historyEvents, signal } = params;
598
+ let session = params.session;
599
+ logger.debug(`[ResponseModal] Starting batch execution for ${batchSteps.length} steps`);
600
+ // Create hook executor function
601
+ const executeHook = async (hook, hookContext, data, step) => {
602
+ // Find the route for this step
603
+ const route = selectedRoute;
604
+ // Convert StepOptions to Step if needed for executePrepareFinalize
605
+ const stepInstance = step?.id ? route.getStep(step.id) : undefined;
606
+ await this.executePrepareFinalize(hook, hookContext, data, route, stepInstance);
607
+ };
608
+ // PHASE 1: Execute all prepare hooks (Requirement 5.1)
609
+ logger.debug(`[ResponseModal] Executing prepare hooks for batch`);
610
+ const prepareResult = await this.batchExecutor.executePrepareHooks({
611
+ steps: batchSteps,
612
+ context,
613
+ data: session.data,
614
+ executeHook,
615
+ });
616
+ if (!prepareResult.success) {
617
+ // Prepare hook failed - return error response
618
+ logger.error(`[ResponseModal] Prepare hook failed:`, prepareResult.error);
619
+ throw new ResponseGenerationError(`Prepare hook failed: ${prepareResult.error?.message}`, {
620
+ phase: 'prepare_hooks',
621
+ context: {
622
+ stepId: prepareResult.error?.stepId,
623
+ executedSteps: prepareResult.executedSteps,
624
+ }
625
+ });
626
+ }
627
+ // PHASE 2: Build combined prompt using BatchPromptBuilder (Requirement 4.4)
628
+ logger.debug(`[ResponseModal] Building batch prompt`);
629
+ const batchPromptResult = await this.batchPromptBuilder.buildBatchPrompt({
630
+ steps: batchSteps,
631
+ route: selectedRoute,
632
+ history: historyEvents,
633
+ context,
634
+ session,
635
+ agentOptions: this.agent.getAgentOptions(),
636
+ });
637
+ logger.debug(`[ResponseModal] Batch prompt built with ${batchPromptResult.stepCount} steps, collecting: ${batchPromptResult.collectFields.join(', ')}`);
638
+ // Build response schema for batch (includes all collect fields)
639
+ const responseSchema = this.buildBatchResponseSchema(batchPromptResult.collectFields);
640
+ // Collect available tools for AI (from all steps in batch)
641
+ const availableTools = this.collectBatchAvailableTools(selectedRoute, batchSteps);
642
+ // PHASE 3: Make single LLM call (Requirement 4.4)
643
+ logger.debug(`[ResponseModal] Making LLM call for batch`);
644
+ const agentOptions = this.agent.getAgentOptions();
645
+ const result = await agentOptions.provider.generateMessage({
646
+ prompt: batchPromptResult.prompt,
647
+ history: historyEvents,
648
+ context,
649
+ tools: availableTools,
650
+ signal,
651
+ parameters: responseSchema ? { jsonSchema: responseSchema, schemaName: "batch_response" } : undefined,
652
+ });
653
+ let message = result.structured?.message || result.message;
654
+ let toolCalls = result.structured?.toolCalls;
655
+ logger.debug(`[ResponseModal] LLM response received for batch`);
656
+ // Execute tools if any
657
+ if (toolCalls && toolCalls.length > 0) {
658
+ const toolResult = await this.executeUnifiedToolLoop({
659
+ toolCalls,
660
+ context,
661
+ session,
662
+ history,
663
+ selectedRoute,
664
+ responsePrompt: batchPromptResult.prompt,
665
+ availableTools,
666
+ responseSchema,
667
+ signal,
668
+ });
669
+ session = toolResult.session;
670
+ toolCalls = toolResult.finalToolCalls;
671
+ if (toolResult.finalMessage) {
672
+ message = toolResult.finalMessage;
673
+ }
674
+ }
675
+ // PHASE 4: Collect data from response for all steps (Requirement 6.1, 6.2, 6.3)
676
+ logger.debug(`[ResponseModal] Collecting batch data`);
677
+ const collectResult = this.batchExecutor.collectBatchData({
678
+ steps: batchSteps,
679
+ llmResponse: result.structured || {},
680
+ session,
681
+ schema: this.agent.getSchema(),
682
+ });
683
+ session = collectResult.session;
684
+ if (collectResult.collectedData && Object.keys(collectResult.collectedData).length > 0) {
685
+ // Update agent's collected data
686
+ await this.agent.updateCollectedData(collectResult.collectedData);
687
+ logger.debug(`[ResponseModal] Batch collected data:`, collectResult.collectedData);
688
+ }
689
+ if (collectResult.validationErrors && collectResult.validationErrors.length > 0) {
690
+ logger.warn(`[ResponseModal] Batch data validation errors:`, collectResult.validationErrors);
691
+ }
692
+ // Update session to final step position
693
+ const lastStep = batchSteps[batchSteps.length - 1];
694
+ if (lastStep?.id) {
695
+ session = enterStep(session, lastStep.id, lastStep.description);
696
+ logger.debug(`[ResponseModal] Updated session to final batch step: ${lastStep.id}`);
697
+ }
698
+ // PHASE 5: Execute all finalize hooks (Requirement 5.2)
699
+ logger.debug(`[ResponseModal] Executing finalize hooks for batch`);
700
+ const finalizeResult = await this.batchExecutor.executeFinalizeHooks({
701
+ steps: batchSteps,
702
+ context,
703
+ data: session.data,
704
+ executeHook,
705
+ });
706
+ if (finalizeResult.errors && finalizeResult.errors.length > 0) {
707
+ // Log finalize errors but don't fail (Requirement 5.5)
708
+ logger.warn(`[ResponseModal] Some finalize hooks failed:`, finalizeResult.errors);
709
+ }
710
+ // Build executed steps list
711
+ const executedSteps = batchSteps
712
+ .filter(step => step.id)
713
+ .map(step => ({
714
+ id: step.id,
715
+ routeId: selectedRoute.id,
716
+ }));
717
+ logger.debug(`[ResponseModal] Batch execution complete. Executed ${executedSteps.length} steps`);
718
+ return {
719
+ message,
720
+ toolCalls,
721
+ session,
722
+ executedSteps,
723
+ };
724
+ }
725
+ /**
726
+ * Build response schema for batch execution
727
+ * @private
728
+ */
729
+ buildBatchResponseSchema(collectFields) {
730
+ const properties = {
731
+ message: {
732
+ type: "string",
733
+ description: "Your response to the user",
734
+ },
735
+ };
736
+ // Add collect fields to schema
737
+ for (const field of collectFields) {
738
+ properties[field] = {
739
+ type: "string",
740
+ description: `Collected value for ${field}`,
741
+ };
742
+ }
743
+ return {
744
+ type: "object",
745
+ properties,
746
+ required: ["message"],
747
+ additionalProperties: true,
378
748
  };
379
749
  }
750
+ /**
751
+ * Collect available tools from all steps in the batch
752
+ * @private
753
+ */
754
+ collectBatchAvailableTools(route, batchSteps) {
755
+ const availableTools = new Map();
756
+ // Add agent-level tools
757
+ this.agent.getTools().forEach((tool) => {
758
+ availableTools.set(tool.id, tool);
759
+ });
760
+ // Add route-level tools
761
+ route.getTools().forEach((tool) => {
762
+ availableTools.set(tool.id, tool);
763
+ });
764
+ // Add step-level tools from all batch steps
765
+ for (const step of batchSteps) {
766
+ if (step.tools) {
767
+ for (const toolRef of step.tools) {
768
+ if (typeof toolRef === "string") {
769
+ // Reference to registered tool - already in availableTools
770
+ }
771
+ else if (typeof toolRef === 'object' && 'id' in toolRef && toolRef.id) {
772
+ // Inline tool definition
773
+ availableTools.set(toolRef.id, toolRef);
774
+ }
775
+ }
776
+ }
777
+ }
778
+ // Convert to the format expected by AI providers
779
+ return Array.from(availableTools.values()).map((tool) => ({
780
+ id: tool.id,
781
+ name: tool.name || tool.id,
782
+ description: tool.description,
783
+ parameters: tool.parameters,
784
+ }));
785
+ }
380
786
  /**
381
787
  * Unified streaming response generation
382
788
  * @private
383
789
  */
384
790
  async *generateUnifiedStreamingResponse(responseContext) {
385
- const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete } = responseContext;
791
+ const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete, batchSteps, batchStoppedReason, } = responseContext;
386
792
  const session = initialSession;
387
793
  // Get last user message (needed for both route and completion handling)
388
794
  // Convert HistoryItem[] to Event[] for internal processing
389
795
  const historyEvents = historyToEvents(history);
390
796
  const lastMessageText = getLastMessageFromHistory(historyEvents);
391
797
  if (selectedRoute && !isRouteComplete) {
392
- // Handle normal route processing with streaming
393
- yield* this.processRouteStreamingResponse({
394
- selectedRoute,
395
- selectedStep,
396
- responseDirectives,
397
- session,
398
- history,
399
- context: effectiveContext,
400
- lastMessageText,
401
- historyEvents,
402
- });
798
+ // Check if we have batch steps to execute
799
+ if (batchSteps && batchSteps.length > 0) {
800
+ // BATCH EXECUTION: Execute multiple steps with streaming
801
+ // Note: For streaming, we still use batch execution but stream the response
802
+ logger.debug(`[ResponseModal] Streaming batch execution for ${batchSteps.length} steps`);
803
+ yield* this.streamBatchResponse({
804
+ selectedRoute,
805
+ batchSteps,
806
+ responseDirectives,
807
+ session,
808
+ history,
809
+ context: effectiveContext,
810
+ historyEvents,
811
+ batchStoppedReason,
812
+ });
813
+ }
814
+ else {
815
+ // SINGLE STEP EXECUTION: Fall back to single-step streaming
816
+ yield* this.processRouteStreamingResponse({
817
+ selectedRoute,
818
+ selectedStep,
819
+ responseDirectives,
820
+ session,
821
+ history,
822
+ context: effectiveContext,
823
+ lastMessageText,
824
+ historyEvents,
825
+ });
826
+ }
403
827
  }
404
828
  else if (isRouteComplete && selectedRoute) {
405
829
  // Handle route completion streaming
@@ -420,6 +844,114 @@ export class ResponseModal {
420
844
  });
421
845
  }
422
846
  }
847
+ /**
848
+ * Stream a batch response with multiple steps
849
+ *
850
+ * Similar to executeBatchResponse but streams the LLM response.
851
+ *
852
+ * @private
853
+ */
854
+ async *streamBatchResponse(params) {
855
+ const { selectedRoute, batchSteps, context, historyEvents, batchStoppedReason, signal } = params;
856
+ let session = params.session;
857
+ // Create hook executor function
858
+ const executeHook = async (hook, hookContext, data, step) => {
859
+ const route = selectedRoute;
860
+ const stepInstance = step?.id ? route.getStep(step.id) : undefined;
861
+ await this.executePrepareFinalize(hook, hookContext, data, route, stepInstance);
862
+ };
863
+ // PHASE 1: Execute all prepare hooks
864
+ const prepareResult = await this.batchExecutor.executePrepareHooks({
865
+ steps: batchSteps,
866
+ context,
867
+ data: session.data,
868
+ executeHook,
869
+ });
870
+ if (!prepareResult.success) {
871
+ // Yield error chunk
872
+ yield {
873
+ delta: "",
874
+ accumulated: "",
875
+ done: true,
876
+ session,
877
+ error: new ResponseGenerationError(`Prepare hook failed: ${prepareResult.error?.message}`, { phase: 'prepare_hooks' }),
878
+ };
879
+ return;
880
+ }
881
+ // PHASE 2: Build combined prompt
882
+ const batchPromptResult = await this.batchPromptBuilder.buildBatchPrompt({
883
+ steps: batchSteps,
884
+ route: selectedRoute,
885
+ history: historyEvents,
886
+ context,
887
+ session,
888
+ agentOptions: this.agent.getAgentOptions(),
889
+ });
890
+ const responseSchema = this.buildBatchResponseSchema(batchPromptResult.collectFields);
891
+ const availableTools = this.collectBatchAvailableTools(selectedRoute, batchSteps);
892
+ // PHASE 3: Stream LLM response
893
+ const agentOptions = this.agent.getAgentOptions();
894
+ const stream = agentOptions.provider.generateMessageStream({
895
+ prompt: batchPromptResult.prompt,
896
+ history: historyEvents,
897
+ context,
898
+ tools: availableTools,
899
+ signal,
900
+ parameters: responseSchema ? { jsonSchema: responseSchema, schemaName: "batch_stream_response" } : undefined,
901
+ });
902
+ // Build executed steps list
903
+ const executedSteps = batchSteps
904
+ .filter(step => step.id)
905
+ .map(step => ({
906
+ id: step.id,
907
+ routeId: selectedRoute.id,
908
+ }));
909
+ // Stream chunks
910
+ for await (const chunk of stream) {
911
+ // On final chunk, collect data and execute finalize hooks
912
+ if (chunk.done) {
913
+ // Collect data from response
914
+ if (chunk.structured) {
915
+ const collectResult = this.batchExecutor.collectBatchData({
916
+ steps: batchSteps,
917
+ llmResponse: chunk.structured,
918
+ session,
919
+ schema: this.agent.getSchema(),
920
+ });
921
+ session = collectResult.session;
922
+ if (collectResult.collectedData && Object.keys(collectResult.collectedData).length > 0) {
923
+ await this.agent.updateCollectedData(collectResult.collectedData);
924
+ }
925
+ }
926
+ // Update session to final step position
927
+ const lastStep = batchSteps[batchSteps.length - 1];
928
+ if (lastStep?.id) {
929
+ session = enterStep(session, lastStep.id, lastStep.description);
930
+ }
931
+ // Execute finalize hooks
932
+ await this.batchExecutor.executeFinalizeHooks({
933
+ steps: batchSteps,
934
+ context,
935
+ data: session.data,
936
+ executeHook,
937
+ });
938
+ // Finalize session
939
+ await this.finalizeSession(session, context);
940
+ }
941
+ yield {
942
+ delta: chunk.delta,
943
+ accumulated: chunk.accumulated,
944
+ done: chunk.done,
945
+ session,
946
+ toolCalls: chunk.structured?.toolCalls,
947
+ isRouteComplete: false,
948
+ executedSteps: chunk.done ? executedSteps : undefined,
949
+ stoppedReason: chunk.done ? batchStoppedReason : undefined,
950
+ metadata: chunk.metadata,
951
+ structured: chunk.structured,
952
+ };
953
+ }
954
+ }
423
955
  /**
424
956
  * Execute prepare function for current step if available
425
957
  * @private
@@ -465,12 +997,20 @@ export class ResponseModal {
465
997
  nextStep = selectedStep;
466
998
  }
467
999
  else {
468
- // New route or no step selected - get initial step or first valid step
1000
+ // Determine current step from session if we're already in this route
1001
+ const isInSameRoute = session.currentRoute?.id === selectedRoute.id;
1002
+ const currentStep = isInSameRoute && session.currentStep
1003
+ ? selectedRoute.getStep(session.currentStep.id)
1004
+ : undefined;
1005
+ logger.debug(`[ResponseModal] Step determination: route match=${isInSameRoute}, currentRoute=${session.currentRoute?.id}, selectedRoute=${selectedRoute.id}, currentStep=${currentStep?.id || 'none'}`);
1006
+ // Get candidate steps based on current position in the route
469
1007
  const routingEngine = this.agent.getRoutingEngine();
470
- const candidates = routingEngine.getCandidateSteps(selectedRoute, undefined, session.data || {});
1008
+ const candidates = await routingEngine.getCandidateStepsWithConditions(selectedRoute, currentStep, // Pass current step instead of undefined to maintain progression
1009
+ createTemplateContext({ data: session.data, session, context }));
1010
+ logger.debug(`[ResponseModal] Found ${candidates.length} candidate steps${currentStep ? ' from current step ' + currentStep.id : ' (new route entry)'}`);
471
1011
  if (candidates.length > 0) {
472
1012
  nextStep = candidates[0].step;
473
- logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id} for new route`);
1013
+ logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new route'}`);
474
1014
  }
475
1015
  else {
476
1016
  // Fallback to initial step even if it should be skipped
@@ -513,6 +1053,14 @@ export class ResponseModal {
513
1053
  });
514
1054
  let message = result.structured?.message || result.message;
515
1055
  let toolCalls = result.structured?.toolCalls;
1056
+ // Debug: Log initial AI response
1057
+ logger.debug(`[ResponseModal] Initial AI response:`, {
1058
+ hasMessage: !!message,
1059
+ messageLength: message?.length || 0,
1060
+ hasToolCalls: !!toolCalls,
1061
+ toolCallsCount: toolCalls?.length || 0,
1062
+ toolNames: toolCalls?.map(tc => tc.toolName) || [],
1063
+ });
516
1064
  // Execute tools with unified loop handling
517
1065
  const toolResult = await this.executeUnifiedToolLoop({
518
1066
  toolCalls,
@@ -547,11 +1095,17 @@ export class ResponseModal {
547
1095
  nextStep = selectedStep;
548
1096
  }
549
1097
  else {
1098
+ // Determine current step from session if we're already in this route
1099
+ const currentStep = session.currentRoute?.id === selectedRoute.id && session.currentStep
1100
+ ? selectedRoute.getStep(session.currentStep.id)
1101
+ : undefined;
1102
+ // Get candidate steps based on current position in the route
550
1103
  const routingEngine = this.agent.getRoutingEngine();
551
- const candidates = routingEngine.getCandidateSteps(selectedRoute, undefined, session.data || {});
1104
+ const candidates = await routingEngine.getCandidateStepsWithConditions(selectedRoute, currentStep, // Pass current step instead of undefined to maintain progression
1105
+ createTemplateContext({ data: session.data, session, context }));
552
1106
  if (candidates.length > 0) {
553
1107
  nextStep = candidates[0].step;
554
- logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id} for new route`);
1108
+ logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new route'}`);
555
1109
  }
556
1110
  else {
557
1111
  nextStep = selectedRoute.initialStep;
@@ -624,6 +1178,10 @@ export class ResponseModal {
624
1178
  if (chunk.done) {
625
1179
  await this.finalizeSession(session, context);
626
1180
  }
1181
+ // Response structure completeness (Requirement 8.1, 8.2, 8.3)
1182
+ // - executedSteps: single step executed in this response
1183
+ // - stoppedReason: 'needs_input' for single-step execution (waiting for user input)
1184
+ // - session.currentStep: reflects the executed step
627
1185
  yield {
628
1186
  delta: chunk.delta,
629
1187
  accumulated: chunk.accumulated,
@@ -631,6 +1189,8 @@ export class ResponseModal {
631
1189
  session,
632
1190
  toolCalls,
633
1191
  isRouteComplete: false,
1192
+ executedSteps: chunk.done ? [{ id: nextStep.id, routeId: selectedRoute.id }] : undefined,
1193
+ stoppedReason: chunk.done ? 'needs_input' : undefined,
634
1194
  metadata: chunk.metadata,
635
1195
  structured: chunk.structured,
636
1196
  };
@@ -649,7 +1209,7 @@ export class ResponseModal {
649
1209
  const historyEvents = historyToEvents(history);
650
1210
  // Execute initial dynamic tool calls
651
1211
  if (toolCalls && toolCalls.length > 0) {
652
- logger.debug(`[ResponseModal] Executing ${toolCalls.length} dynamic tool calls`);
1212
+ logger.debug(`[ResponseModal] Executing ${toolCalls.length} dynamic tool calls:`, toolCalls.map(tc => tc.toolName));
653
1213
  for (const toolCall of toolCalls) {
654
1214
  const tool = this.findAvailableTool(toolCall.toolName, selectedRoute);
655
1215
  if (!tool) {
@@ -657,16 +1217,24 @@ export class ResponseModal {
657
1217
  continue;
658
1218
  }
659
1219
  try {
660
- const toolExecutor = new ToolExecutor();
661
- const toolResult = await toolExecutor.executeTool({
662
- tool: tool,
663
- context,
664
- updateContext: this.agent.updateContext.bind(this.agent),
665
- updateData: this.agent.updateCollectedData.bind(this.agent),
666
- history: historyEvents, // Use Event[] for tool execution
667
- data: session.data,
668
- toolArguments: toolCall.arguments,
669
- });
1220
+ // Use ToolManager for unified tool execution
1221
+ const toolManager = this.getToolManager();
1222
+ let toolResult;
1223
+ if (toolManager) {
1224
+ toolResult = await toolManager.executeTool({
1225
+ tool: tool,
1226
+ context,
1227
+ updateContext: this.agent.updateContext.bind(this.agent),
1228
+ updateData: this.agent.updateCollectedData.bind(this.agent),
1229
+ history: historyEvents, // Use Event[] for tool execution
1230
+ data: session.data,
1231
+ toolArguments: toolCall.arguments,
1232
+ });
1233
+ }
1234
+ else {
1235
+ // Fallback: execute tool directly if ToolManager not available
1236
+ throw new Error(`ToolManager not available for tool execution: ${toolCall.toolName}`);
1237
+ }
670
1238
  // Check if tool execution was successful
671
1239
  if (!toolResult.success) {
672
1240
  logger.error(`[ResponseModal] Tool execution failed: ${toolCall.toolName} - ${toolResult.error}`);
@@ -695,7 +1263,7 @@ export class ResponseModal {
695
1263
  // Continue execution but log the error
696
1264
  }
697
1265
  }
698
- logger.debug(`[ResponseModal] Executed dynamic tool: ${toolResult.toolName} (success: ${toolResult.success})`);
1266
+ logger.debug(`[ResponseModal] Executed dynamic tool: ${toolCall.toolName} (success: ${toolResult.success})`);
699
1267
  }
700
1268
  catch (error) {
701
1269
  logger.error(`[ResponseModal] Tool execution error for ${toolCall.toolName}:`, error);
@@ -711,7 +1279,7 @@ export class ResponseModal {
711
1279
  let finalMessage;
712
1280
  while (hasToolCalls && toolLoopCount < MAX_TOOL_LOOPS) {
713
1281
  toolLoopCount++;
714
- logger.debug(`[ResponseModal] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS}`);
1282
+ logger.debug(`[ResponseModal] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS} with ${toolCalls?.length || 0} tool calls`);
715
1283
  // Create tool result events with proper Event format structure
716
1284
  const toolResultEvents = [];
717
1285
  for (const toolCall of toolCalls || []) {
@@ -740,12 +1308,19 @@ export class ResponseModal {
740
1308
  // Create updated history with tool results (combine Event arrays)
741
1309
  const updatedHistoryEvents = [...historyEvents, ...toolResultEvents];
742
1310
  // Make follow-up AI call to see if more tools are needed
1311
+ // After first iteration, don't provide tools to force a text response
743
1312
  const agentOptions = this.agent.getAgentOptions();
1313
+ const shouldProvideTools = toolLoopCount === 1;
1314
+ logger.debug(`[ResponseModal] Making follow-up AI call (loop ${toolLoopCount}):`, {
1315
+ providingTools: shouldProvideTools,
1316
+ toolsCount: shouldProvideTools ? availableTools.length : 0,
1317
+ addingTextInstruction: toolLoopCount > 1,
1318
+ });
744
1319
  const followUpResult = await agentOptions.provider.generateMessage({
745
- prompt: responsePrompt,
1320
+ prompt: responsePrompt + (toolLoopCount > 1 ? "\n\nProvide a text response to the user based on the tool results." : ""),
746
1321
  history: updatedHistoryEvents, // Use Event[] for AI provider
747
1322
  context,
748
- tools: availableTools,
1323
+ tools: shouldProvideTools ? availableTools : [], // Only provide tools on first iteration
749
1324
  parameters: responseSchema ? {
750
1325
  jsonSchema: responseSchema,
751
1326
  schemaName: "tool_followup",
@@ -755,6 +1330,13 @@ export class ResponseModal {
755
1330
  // Check if follow-up call has more tool calls
756
1331
  const followUpToolCalls = followUpResult.structured?.toolCalls;
757
1332
  hasToolCalls = followUpToolCalls && followUpToolCalls.length > 0;
1333
+ logger.debug(`[ResponseModal] Follow-up AI response (loop ${toolLoopCount}):`, {
1334
+ hasMessage: !!followUpResult.message,
1335
+ messageLength: followUpResult.message?.length || 0,
1336
+ hasToolCalls,
1337
+ toolCallsCount: followUpToolCalls?.length || 0,
1338
+ toolNames: followUpToolCalls?.map(tc => tc.toolName) || [],
1339
+ });
758
1340
  if (hasToolCalls) {
759
1341
  logger.debug(`[ResponseModal] Follow-up call produced ${followUpToolCalls.length} additional tool calls`);
760
1342
  // Execute the follow-up tool calls
@@ -765,16 +1347,24 @@ export class ResponseModal {
765
1347
  continue;
766
1348
  }
767
1349
  try {
768
- const toolExecutor = new ToolExecutor();
769
- const toolResult = await toolExecutor.executeTool({
770
- tool: tool,
771
- context,
772
- updateContext: this.agent.updateContext.bind(this.agent),
773
- updateData: this.agent.updateCollectedData.bind(this.agent),
774
- history: updatedHistoryEvents, // Use Event[] for tool execution
775
- data: session.data,
776
- toolArguments: toolCall.arguments,
777
- });
1350
+ // Use ToolManager for unified tool execution
1351
+ const toolManager = this.getToolManager();
1352
+ let toolResult;
1353
+ if (toolManager) {
1354
+ toolResult = await toolManager.executeTool({
1355
+ tool: tool,
1356
+ context,
1357
+ updateContext: this.agent.updateContext.bind(this.agent),
1358
+ updateData: this.agent.updateCollectedData.bind(this.agent),
1359
+ history: updatedHistoryEvents, // Use Event[] for tool execution
1360
+ data: session.data,
1361
+ toolArguments: toolCall.arguments,
1362
+ });
1363
+ }
1364
+ else {
1365
+ // Fallback: execute tool directly if ToolManager not available
1366
+ throw new Error(`ToolManager not available for follow-up tool execution: ${toolCall.toolName}`);
1367
+ }
778
1368
  // Check if tool execution was successful
779
1369
  if (!toolResult.success) {
780
1370
  logger.error(`[ResponseModal] Follow-up tool execution failed: ${toolCall.toolName} - ${toolResult.error}`);
@@ -799,7 +1389,7 @@ export class ResponseModal {
799
1389
  logger.error(`[ResponseModal] Failed to update data from follow-up tool ${toolCall.toolName}:`, error);
800
1390
  }
801
1391
  }
802
- logger.debug(`[ResponseModal] Executed follow-up tool: ${toolResult.toolName} (success: ${toolResult.success})`);
1392
+ logger.debug(`[ResponseModal] Executed follow-up tool: ${toolCall.toolName} (success: ${toolResult.success})`);
803
1393
  }
804
1394
  catch (error) {
805
1395
  logger.error(`[ResponseModal] Follow-up tool execution error for ${toolCall.toolName}:`, error);
@@ -820,6 +1410,12 @@ export class ResponseModal {
820
1410
  if (toolLoopCount >= MAX_TOOL_LOOPS) {
821
1411
  logger.warn(`[ResponseModal] Tool loop limit reached (${MAX_TOOL_LOOPS}), stopping`);
822
1412
  }
1413
+ logger.debug(`[ResponseModal] Tool loop completed:`, {
1414
+ totalIterations: toolLoopCount,
1415
+ hasFinalMessage: !!finalMessage,
1416
+ finalMessageLength: finalMessage?.length || 0,
1417
+ finalToolCallsCount: toolCalls?.length || 0,
1418
+ });
823
1419
  return {
824
1420
  session,
825
1421
  finalToolCalls: toolCalls,
@@ -841,14 +1437,29 @@ export class ResponseModal {
841
1437
  const { result, selectedRoute, nextStep, session } = params;
842
1438
  let updatedSession = session;
843
1439
  // Extract collected data from final response (only for route-based interactions)
844
- if (selectedRoute && result.structured && nextStep?.collect) {
1440
+ if (selectedRoute && result.structured) {
845
1441
  try {
846
1442
  const collectedData = {};
847
1443
  // AgentStructuredResponse extends Record<string, unknown>, so we can safely access properties
848
1444
  const structuredData = result.structured;
849
- for (const field of nextStep.collect) {
1445
+ // Collect ALL route fields (required + optional) from structured response
1446
+ const allRouteFields = new Set();
1447
+ // Add route required fields
1448
+ if (selectedRoute.requiredFields) {
1449
+ selectedRoute.requiredFields.forEach(field => allRouteFields.add(String(field)));
1450
+ }
1451
+ // Add route optional fields
1452
+ if (selectedRoute.optionalFields) {
1453
+ selectedRoute.optionalFields.forEach(field => allRouteFields.add(String(field)));
1454
+ }
1455
+ // Also include current step's collect fields (in case they're not in route fields)
1456
+ if (nextStep?.collect) {
1457
+ nextStep.collect.forEach(field => allRouteFields.add(String(field)));
1458
+ }
1459
+ // Extract all available fields from structured response
1460
+ for (const field of allRouteFields) {
850
1461
  const fieldKey = String(field);
851
- if (fieldKey in structuredData) {
1462
+ if (fieldKey in structuredData && structuredData[fieldKey] !== undefined && structuredData[fieldKey] !== null) {
852
1463
  collectedData[fieldKey] = structuredData[fieldKey];
853
1464
  }
854
1465
  }
@@ -911,34 +1522,60 @@ export class ResponseModal {
911
1522
  requires: endStepSpec.requires,
912
1523
  prompt: endStepSpec.prompt || "Summarize what was accomplished and confirm completion based on the conversation history and collected data",
913
1524
  });
914
- // Build response schema for completion
915
- const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep, this.agent.getSchema());
916
- const templateContext = { context, session, history: historyEvents }; // Use Event[] for template context
917
- // Build completion response prompt
1525
+ // Build response schema for completion (message only, no data collection)
1526
+ const completionSchema = {
1527
+ type: "object",
1528
+ properties: {
1529
+ message: {
1530
+ type: "string",
1531
+ description: "Completion message confirming what was accomplished",
1532
+ },
1533
+ },
1534
+ required: ["message"],
1535
+ additionalProperties: false,
1536
+ };
1537
+ const templateContext = createTemplateContext({ context, session, history: historyEvents });
1538
+ // Build completion response prompt using ResponseEngine
1539
+ // Filter out conditional guidelines - only include always-active ones
1540
+ const alwaysActiveGuidelines = [
1541
+ ...this.agent.getGuidelines().filter(g => !g.condition),
1542
+ ...selectedRoute.getGuidelines().filter(g => !g.condition),
1543
+ ];
1544
+ let completitionPrompt = "Summarize what was accomplished and confirm completion";
1545
+ if (endStepSpec.prompt) {
1546
+ completitionPrompt = await render(endStepSpec.prompt, templateContext);
1547
+ }
918
1548
  const completionPrompt = await this.responseEngine.buildResponsePrompt({
919
1549
  route: selectedRoute,
920
1550
  currentStep: completionStep,
921
1551
  rules: selectedRoute.getRules(),
922
1552
  prohibitions: selectedRoute.getProhibitions(),
923
- directives: undefined, // No directives for completion
924
- history: historyEvents, // Use Event[] for buildResponsePrompt
925
- lastMessage: lastMessageText, // Use string for buildResponsePrompt
1553
+ directives: [
1554
+ `Task completed: ${selectedRoute.title}`,
1555
+ `Collected data: ${JSON.stringify(session.data, null, 2)}`,
1556
+ "Do NOT ask for more information - the task is complete",
1557
+ completitionPrompt,
1558
+ ],
1559
+ history: historyEvents,
1560
+ lastMessage: lastMessageText,
926
1561
  agentOptions: this.agent.getAgentOptions(),
927
- combinedGuidelines: [...this.agent.getGuidelines(), ...selectedRoute.getGuidelines()],
1562
+ combinedGuidelines: alwaysActiveGuidelines, // Only non-conditional guidelines
928
1563
  combinedTerms: this.mergeTerms(this.agent.getTerms(), selectedRoute.getTerms()),
929
1564
  context,
930
1565
  session,
931
- agentSchema: this.agent.getSchema(),
1566
+ agentSchema: undefined, // No data collection schema for completion
932
1567
  });
933
1568
  // Generate completion message using AI provider
934
1569
  const agentOptions = this.agent.getAgentOptions();
1570
+ logger.debug(`[ResponseModal] Calling AI provider for completion message...`);
935
1571
  const completionResult = await agentOptions.provider.generateMessage({
936
1572
  prompt: completionPrompt,
937
- history: historyEvents, // Use Event[] for AI provider
1573
+ history: historyEvents,
938
1574
  context,
939
1575
  signal,
940
- parameters: { jsonSchema: responseSchema, schemaName: "completion_message" },
1576
+ parameters: { jsonSchema: completionSchema, schemaName: "completion_message" },
941
1577
  });
1578
+ logger.debug(`[ResponseModal] AI provider returned completion result`);
942
1579
  const message = completionResult.structured?.message || completionResult.message;
943
1580
  logger.debug(`[ResponseModal] Generated completion message for route: ${selectedRoute.title}`);
944
1581
  // Check for onComplete transition
@@ -981,7 +1618,7 @@ export class ResponseModal {
981
1618
  });
982
1619
  // Build response schema for completion
983
1620
  const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep, this.agent.getSchema());
984
- const templateContext = { context, session, history: historyEvents }; // Use Event[] for template context
1621
+ const templateContext = createTemplateContext({ context, session, history: historyEvents }); // Use Event[] for template context
985
1622
  // Build completion response prompt
986
1623
  const completionPrompt = await this.responseEngine.buildResponsePrompt({
987
1624
  route: selectedRoute,
@@ -1039,6 +1676,10 @@ export class ResponseModal {
1039
1676
  if (chunk.done) {
1040
1677
  await this.finalizeSession(session, context);
1041
1678
  }
1679
+ // Response structure completeness (Requirement 8.1, 8.2, 8.3)
1680
+ // - executedSteps: empty for route completion (no new steps executed)
1681
+ // - stoppedReason: 'route_complete' for completed routes
1682
+ // - session.currentStep: set to END_ROUTE
1042
1683
  yield {
1043
1684
  delta: chunk.delta,
1044
1685
  accumulated: chunk.accumulated,
@@ -1046,6 +1687,8 @@ export class ResponseModal {
1046
1687
  session,
1047
1688
  toolCalls: undefined,
1048
1689
  isRouteComplete: true,
1690
+ executedSteps: chunk.done ? [] : undefined,
1691
+ stoppedReason: chunk.done ? 'route_complete' : undefined,
1049
1692
  metadata: chunk.metadata,
1050
1693
  structured: chunk.structured,
1051
1694
  };
@@ -1120,6 +1763,10 @@ export class ResponseModal {
1120
1763
  if (chunk.done) {
1121
1764
  await this.finalizeSession(session, context);
1122
1765
  }
1766
+ // Response structure completeness (Requirement 8.1, 8.2, 8.3)
1767
+ // - executedSteps: empty for fallback (no route/step execution)
1768
+ // - stoppedReason: undefined for fallback (no route context)
1769
+ // - session.currentStep: unchanged (no step progression)
1123
1770
  yield {
1124
1771
  delta: chunk.delta,
1125
1772
  accumulated: chunk.accumulated,
@@ -1127,6 +1774,8 @@ export class ResponseModal {
1127
1774
  session,
1128
1775
  toolCalls: undefined,
1129
1776
  isRouteComplete: false,
1777
+ executedSteps: chunk.done ? [] : undefined,
1778
+ stoppedReason: undefined,
1130
1779
  metadata: chunk.metadata,
1131
1780
  structured: chunk.structured,
1132
1781
  };
@@ -1158,11 +1807,18 @@ export class ResponseModal {
1158
1807
  // UTILITY METHODS - Helper methods for tool management and other utilities
1159
1808
  // ============================================================================
1160
1809
  /**
1161
- * Find an available tool by name for the given route
1162
- * Route-level tools take precedence over agent-level tools
1810
+ * Find an available tool by name for the given route using ToolManager
1811
+ * Delegates to ToolManager for unified tool resolution
1163
1812
  * @private
1164
1813
  */
1165
1814
  findAvailableTool(toolName, route) {
1815
+ // Use ToolManager for unified tool resolution
1816
+ const toolManager = this.getToolManager();
1817
+ if (toolManager) {
1818
+ return toolManager.find(toolName, undefined, undefined, route);
1819
+ }
1820
+ // Fallback to legacy resolution if ToolManager not available
1821
+ logger.warn(`[ResponseModal] ToolManager not available, using legacy tool resolution for: ${toolName}`);
1166
1822
  // Check route-level tools first (if route provided)
1167
1823
  if (route) {
1168
1824
  const routeTool = route
@@ -1176,10 +1832,24 @@ export class ResponseModal {
1176
1832
  return agentTools.find((tool) => tool.id === toolName || tool.name === toolName);
1177
1833
  }
1178
1834
  /**
1179
- * Collect all available tools for the given route and step context
1835
+ * Collect all available tools for the given route and step context using ToolManager
1836
+ * Delegates to ToolManager for unified tool resolution and deduplication
1180
1837
  * @private
1181
1838
  */
1182
1839
  collectAvailableTools(route, step) {
1840
+ // Use ToolManager for unified tool collection if available
1841
+ const toolManager = this.getToolManager();
1842
+ if (toolManager) {
1843
+ const availableTools = toolManager.getAvailable(undefined, step, route);
1844
+ return availableTools.map((tool) => ({
1845
+ id: tool.id,
1846
+ name: tool.name || tool.id,
1847
+ description: tool.description,
1848
+ parameters: tool.parameters,
1849
+ }));
1850
+ }
1851
+ // Fallback to legacy collection logic if ToolManager not available
1852
+ logger.warn(`[ResponseModal] ToolManager not available, using legacy tool collection`);
1183
1853
  const availableTools = new Map();
1184
1854
  // Add agent-level tools
1185
1855
  this.agent.getTools().forEach((tool) => {
@@ -1250,45 +1920,61 @@ export class ResponseModal {
1250
1920
  // It's a tool reference - find and execute the tool
1251
1921
  let tool;
1252
1922
  if (typeof prepareOrFinalize === "string") {
1253
- // Tool ID - find it in available tools
1254
- const availableTools = new Map();
1255
- // Add agent-level tools
1256
- this.agent.getTools().forEach((t) => {
1257
- availableTools.set(t.id, t);
1258
- });
1259
- // Add route-level tools
1260
- if (route) {
1261
- route.getTools().forEach((t) => {
1923
+ // Tool ID - use ToolManager for unified resolution
1924
+ const toolManager = this.getToolManager();
1925
+ if (toolManager) {
1926
+ tool = toolManager.find(prepareOrFinalize, undefined, step, route);
1927
+ }
1928
+ else {
1929
+ // Fallback to legacy resolution if ToolManager not available
1930
+ logger.warn(`[ResponseModal] ToolManager not available, using legacy tool resolution for prepare/finalize: ${prepareOrFinalize}`);
1931
+ const availableTools = new Map();
1932
+ // Add agent-level tools
1933
+ this.agent.getTools().forEach((t) => {
1262
1934
  availableTools.set(t.id, t);
1263
1935
  });
1264
- }
1265
- // Add step-level tools
1266
- if (step?.tools) {
1267
- for (const toolRef of step.tools) {
1268
- if (typeof toolRef === "string") {
1269
- // Keep as is
1270
- }
1271
- else if (typeof toolRef === 'object' && 'id' in toolRef && toolRef.id) {
1272
- availableTools.set(toolRef.id, toolRef);
1936
+ // Add route-level tools
1937
+ if (route) {
1938
+ route.getTools().forEach((t) => {
1939
+ availableTools.set(t.id, t);
1940
+ });
1941
+ }
1942
+ // Add step-level tools
1943
+ if (step?.tools) {
1944
+ for (const toolRef of step.tools) {
1945
+ if (typeof toolRef === "string") {
1946
+ // Keep as is
1947
+ }
1948
+ else if (typeof toolRef === 'object' && 'id' in toolRef && toolRef.id) {
1949
+ availableTools.set(toolRef.id, toolRef);
1950
+ }
1273
1951
  }
1274
1952
  }
1953
+ tool = availableTools.get(prepareOrFinalize);
1275
1954
  }
1276
- tool = availableTools.get(prepareOrFinalize);
1277
1955
  }
1278
1956
  else {
1279
1957
  // Tool object - use directly
1280
1958
  tool = prepareOrFinalize;
1281
1959
  }
1282
1960
  if (tool) {
1283
- const toolExecutor = new ToolExecutor();
1284
- const result = await toolExecutor.executeTool({
1285
- tool,
1286
- context,
1287
- updateContext: this.agent.updateContext.bind(this.agent),
1288
- updateData: this.agent.updateCollectedData.bind(this.agent),
1289
- history: [], // Empty history for prepare/finalize
1290
- data,
1291
- });
1961
+ // Use ToolManager for unified tool execution
1962
+ const toolManager = this.getToolManager();
1963
+ let result;
1964
+ if (toolManager) {
1965
+ result = await toolManager.executeTool({
1966
+ tool,
1967
+ context,
1968
+ updateContext: this.agent.updateContext.bind(this.agent),
1969
+ updateData: this.agent.updateCollectedData.bind(this.agent),
1970
+ history: [], // Empty history for prepare/finalize
1971
+ data,
1972
+ });
1973
+ }
1974
+ else {
1975
+ // Fallback: execute tool directly if ToolManager not available
1976
+ throw new Error(`ToolManager not available for prepare/finalize tool execution: ${typeof prepareOrFinalize === "string" ? prepareOrFinalize : "inline tool"}`);
1977
+ }
1292
1978
  if (!result.success) {
1293
1979
  logger.error(`[ResponseModal] Tool execution failed in prepare/finalize: ${result.error}`);
1294
1980
  throw new Error(`Tool execution failed: ${result.error}`);