@falai/agent 0.9.2 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (628) hide show
  1. package/README.md +281 -42
  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/cjs/{src/core → core}/Agent.d.ts +16 -1
  33. package/dist/cjs/core/Agent.d.ts.map +1 -0
  34. package/dist/cjs/{src/core → core}/Agent.js +63 -2
  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 +850 -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 +217 -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 +211 -0
  52. package/dist/cjs/core/ResponseEngine.js.map +1 -0
  53. package/dist/{src → cjs}/core/ResponseModal.d.ts +45 -0
  54. package/dist/cjs/core/ResponseModal.d.ts.map +1 -0
  55. package/dist/cjs/{src/core → core}/ResponseModal.js +752 -74
  56. package/dist/cjs/core/ResponseModal.js.map +1 -0
  57. package/dist/{src → cjs}/core/ResponsePipeline.d.ts +2 -2
  58. package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -0
  59. package/dist/cjs/{src/core → core}/ResponsePipeline.js +13 -6
  60. package/dist/cjs/core/ResponsePipeline.js.map +1 -0
  61. package/dist/{src → cjs}/core/Route.d.ts +34 -5
  62. package/dist/cjs/core/Route.d.ts.map +1 -0
  63. package/dist/cjs/{src/core → core}/Route.js +196 -19
  64. package/dist/cjs/core/Route.js.map +1 -0
  65. package/dist/cjs/{src/core → core}/RoutingEngine.d.ts +30 -5
  66. package/dist/cjs/core/RoutingEngine.d.ts.map +1 -0
  67. package/dist/cjs/{src/core → core}/RoutingEngine.js +330 -80
  68. package/dist/cjs/core/RoutingEngine.js.map +1 -0
  69. package/dist/cjs/core/SessionManager.js.map +1 -0
  70. package/dist/{src → cjs}/core/Step.d.ts +31 -10
  71. package/dist/cjs/core/Step.d.ts.map +1 -0
  72. package/dist/cjs/{src/core → core}/Step.js +105 -10
  73. package/dist/cjs/core/Step.js.map +1 -0
  74. package/dist/cjs/core/ToolManager.js.map +1 -0
  75. package/dist/{src → cjs}/index.d.ts +4 -1
  76. package/dist/cjs/index.d.ts.map +1 -0
  77. package/dist/cjs/{src/index.js → index.js} +12 -1
  78. package/dist/cjs/index.js.map +1 -0
  79. package/dist/cjs/{src/providers → providers}/AnthropicProvider.js +18 -18
  80. package/dist/cjs/providers/AnthropicProvider.js.map +1 -0
  81. package/dist/{src → cjs}/providers/GeminiProvider.d.ts.map +1 -1
  82. package/dist/cjs/{src/providers → providers}/GeminiProvider.js +123 -51
  83. package/dist/cjs/providers/GeminiProvider.js.map +1 -0
  84. package/dist/cjs/{src/providers → providers}/OpenAIProvider.js +19 -19
  85. package/dist/cjs/providers/OpenAIProvider.js.map +1 -0
  86. package/dist/cjs/{src/providers → providers}/OpenRouterProvider.js +19 -19
  87. package/dist/cjs/providers/OpenRouterProvider.js.map +1 -0
  88. package/dist/cjs/providers/index.js.map +1 -0
  89. package/dist/cjs/{src/types → types}/agent.d.ts +15 -3
  90. package/dist/cjs/types/agent.d.ts.map +1 -0
  91. package/dist/cjs/types/agent.js.map +1 -0
  92. package/dist/{src → cjs}/types/ai.js.map +1 -1
  93. package/dist/cjs/types/history.js.map +1 -0
  94. package/dist/cjs/{src/types → types}/index.d.ts +2 -1
  95. package/dist/{src → cjs}/types/index.d.ts.map +1 -1
  96. package/dist/cjs/{src/types → types}/index.js +6 -1
  97. package/dist/cjs/types/index.js.map +1 -0
  98. package/dist/cjs/types/persistence.js.map +1 -0
  99. package/dist/cjs/{src/types → types}/route.d.ts +111 -12
  100. package/dist/cjs/types/route.d.ts.map +1 -0
  101. package/dist/cjs/{src/types → types}/route.js.map +1 -1
  102. package/dist/cjs/types/session.js.map +1 -0
  103. package/dist/cjs/types/template.d.ts +88 -0
  104. package/dist/cjs/types/template.d.ts.map +1 -0
  105. package/dist/cjs/types/tool.js.map +1 -0
  106. package/dist/cjs/utils/clone.js.map +1 -0
  107. package/dist/cjs/utils/condition.d.ts +38 -0
  108. package/dist/cjs/utils/condition.d.ts.map +1 -0
  109. package/dist/cjs/utils/condition.js +168 -0
  110. package/dist/cjs/utils/condition.js.map +1 -0
  111. package/dist/cjs/utils/event.js.map +1 -0
  112. package/dist/cjs/utils/history.js.map +1 -0
  113. package/dist/cjs/utils/id.js.map +1 -0
  114. package/dist/cjs/{src/utils → utils}/index.d.ts +3 -1
  115. package/dist/cjs/utils/index.d.ts.map +1 -0
  116. package/dist/cjs/{src/utils → utils}/index.js +12 -1
  117. package/dist/cjs/utils/index.js.map +1 -0
  118. package/dist/cjs/utils/json.d.ts +16 -0
  119. package/dist/cjs/utils/json.d.ts.map +1 -0
  120. package/dist/cjs/utils/json.js +47 -0
  121. package/dist/cjs/utils/json.js.map +1 -0
  122. package/dist/cjs/utils/logger.js.map +1 -0
  123. package/dist/{src → cjs}/utils/retry.d.ts +0 -3
  124. package/dist/cjs/utils/retry.d.ts.map +1 -0
  125. package/dist/cjs/{src/utils → utils}/retry.js +8 -7
  126. package/dist/cjs/utils/retry.js.map +1 -0
  127. package/dist/cjs/utils/session.js.map +1 -0
  128. package/dist/{src → cjs}/utils/template.d.ts +48 -0
  129. package/dist/cjs/utils/template.d.ts.map +1 -0
  130. package/dist/cjs/{src/utils → utils}/template.js +100 -0
  131. package/dist/cjs/utils/template.js.map +1 -0
  132. package/dist/constants/index.d.ts.map +1 -0
  133. package/dist/constants/index.js.map +1 -0
  134. package/dist/{src/core → core}/Agent.d.ts +16 -1
  135. package/dist/core/Agent.d.ts.map +1 -0
  136. package/dist/{src/core → core}/Agent.js +64 -3
  137. package/dist/core/Agent.js.map +1 -0
  138. package/dist/core/BatchExecutor.d.ts +353 -0
  139. package/dist/core/BatchExecutor.d.ts.map +1 -0
  140. package/dist/core/BatchExecutor.js +845 -0
  141. package/dist/core/BatchExecutor.js.map +1 -0
  142. package/dist/core/BatchPromptBuilder.d.ts +86 -0
  143. package/dist/core/BatchPromptBuilder.d.ts.map +1 -0
  144. package/dist/core/BatchPromptBuilder.js +213 -0
  145. package/dist/core/BatchPromptBuilder.js.map +1 -0
  146. package/dist/core/Events.d.ts.map +1 -0
  147. package/dist/core/Events.js.map +1 -0
  148. package/dist/core/PersistenceManager.d.ts.map +1 -0
  149. package/dist/core/PersistenceManager.js.map +1 -0
  150. package/dist/{cjs/src/core → core}/PromptComposer.d.ts +1 -1
  151. package/dist/core/PromptComposer.d.ts.map +1 -0
  152. package/dist/{src/core → core}/PromptComposer.js +45 -8
  153. package/dist/core/PromptComposer.js.map +1 -0
  154. package/dist/core/ResponseEngine.d.ts.map +1 -0
  155. package/dist/core/ResponseEngine.js +207 -0
  156. package/dist/core/ResponseEngine.js.map +1 -0
  157. package/dist/{cjs/src/core → core}/ResponseModal.d.ts +45 -0
  158. package/dist/core/ResponseModal.d.ts.map +1 -0
  159. package/dist/{src/core → core}/ResponseModal.js +752 -74
  160. package/dist/core/ResponseModal.js.map +1 -0
  161. package/dist/{cjs/src/core → core}/ResponsePipeline.d.ts +2 -2
  162. package/dist/core/ResponsePipeline.d.ts.map +1 -0
  163. package/dist/{src/core → core}/ResponsePipeline.js +13 -6
  164. package/dist/core/ResponsePipeline.js.map +1 -0
  165. package/dist/{cjs/src/core → core}/Route.d.ts +34 -5
  166. package/dist/core/Route.d.ts.map +1 -0
  167. package/dist/{src/core → core}/Route.js +195 -18
  168. package/dist/core/Route.js.map +1 -0
  169. package/dist/{src/core → core}/RoutingEngine.d.ts +30 -5
  170. package/dist/core/RoutingEngine.d.ts.map +1 -0
  171. package/dist/{src/core → core}/RoutingEngine.js +310 -60
  172. package/dist/core/RoutingEngine.js.map +1 -0
  173. package/dist/core/SessionManager.d.ts.map +1 -0
  174. package/dist/core/SessionManager.js.map +1 -0
  175. package/dist/{cjs/src/core → core}/Step.d.ts +31 -10
  176. package/dist/core/Step.d.ts.map +1 -0
  177. package/dist/{src/core → core}/Step.js +104 -9
  178. package/dist/core/Step.js.map +1 -0
  179. package/dist/core/ToolManager.d.ts.map +1 -0
  180. package/dist/core/ToolManager.js.map +1 -0
  181. package/dist/{cjs/src/index.d.ts → index.d.ts} +4 -1
  182. package/dist/index.d.ts.map +1 -0
  183. package/dist/{src/index.js → index.js} +3 -0
  184. package/dist/index.js.map +1 -0
  185. package/dist/providers/AnthropicProvider.d.ts.map +1 -0
  186. package/dist/{src/providers → providers}/AnthropicProvider.js +17 -17
  187. package/dist/providers/AnthropicProvider.js.map +1 -0
  188. package/dist/providers/GeminiProvider.d.ts.map +1 -0
  189. package/dist/{src/providers → providers}/GeminiProvider.js +123 -51
  190. package/dist/providers/GeminiProvider.js.map +1 -0
  191. package/dist/providers/OpenAIProvider.d.ts.map +1 -0
  192. package/dist/{src/providers → providers}/OpenAIProvider.js +18 -18
  193. package/dist/providers/OpenAIProvider.js.map +1 -0
  194. package/dist/providers/OpenRouterProvider.d.ts.map +1 -0
  195. package/dist/{src/providers → providers}/OpenRouterProvider.js +18 -18
  196. package/dist/providers/OpenRouterProvider.js.map +1 -0
  197. package/dist/providers/index.d.ts.map +1 -0
  198. package/dist/providers/index.js.map +1 -0
  199. package/dist/{src/types → types}/agent.d.ts +15 -3
  200. package/dist/types/agent.d.ts.map +1 -0
  201. package/dist/types/agent.js.map +1 -0
  202. package/dist/types/ai.d.ts.map +1 -0
  203. package/dist/types/ai.js.map +1 -0
  204. package/dist/types/history.d.ts.map +1 -0
  205. package/dist/types/history.js.map +1 -0
  206. package/dist/{src/types → types}/index.d.ts +2 -1
  207. package/dist/types/index.d.ts.map +1 -0
  208. package/dist/{src/types → types}/index.js +1 -0
  209. package/dist/types/index.js.map +1 -0
  210. package/dist/types/persistence.d.ts.map +1 -0
  211. package/dist/types/persistence.js.map +1 -0
  212. package/dist/{src/types → types}/route.d.ts +111 -12
  213. package/dist/types/route.d.ts.map +1 -0
  214. package/dist/{src/types → types}/route.js.map +1 -1
  215. package/dist/types/routing.d.ts.map +1 -0
  216. package/dist/{cjs/src/types → types}/routing.js.map +1 -1
  217. package/dist/types/schema.d.ts.map +1 -0
  218. package/dist/{cjs/src/types → types}/schema.js.map +1 -1
  219. package/dist/types/session.d.ts.map +1 -0
  220. package/dist/{src/types → types}/session.js.map +1 -1
  221. package/dist/types/template.d.ts +88 -0
  222. package/dist/types/template.d.ts.map +1 -0
  223. package/dist/{cjs/src/types → types}/template.js.map +1 -1
  224. package/dist/types/tool.d.ts.map +1 -0
  225. package/dist/types/tool.js.map +1 -0
  226. package/dist/utils/clone.d.ts.map +1 -0
  227. package/dist/utils/clone.js.map +1 -0
  228. package/dist/utils/condition.d.ts +38 -0
  229. package/dist/utils/condition.d.ts.map +1 -0
  230. package/dist/utils/condition.js +161 -0
  231. package/dist/utils/condition.js.map +1 -0
  232. package/dist/utils/event.d.ts.map +1 -0
  233. package/dist/utils/event.js.map +1 -0
  234. package/dist/utils/history.d.ts.map +1 -0
  235. package/dist/utils/history.js.map +1 -0
  236. package/dist/utils/id.d.ts.map +1 -0
  237. package/dist/utils/id.js.map +1 -0
  238. package/dist/{src/utils → utils}/index.d.ts +3 -1
  239. package/dist/utils/index.d.ts.map +1 -0
  240. package/dist/{src/utils → utils}/index.js +5 -1
  241. package/dist/utils/index.js.map +1 -0
  242. package/dist/utils/json.d.ts +16 -0
  243. package/dist/utils/json.d.ts.map +1 -0
  244. package/dist/utils/json.js +43 -0
  245. package/dist/utils/json.js.map +1 -0
  246. package/dist/utils/logger.d.ts.map +1 -0
  247. package/dist/utils/logger.js.map +1 -0
  248. package/dist/{cjs/src/utils → utils}/retry.d.ts +0 -3
  249. package/dist/utils/retry.d.ts.map +1 -0
  250. package/dist/{src/utils → utils}/retry.js +5 -4
  251. package/dist/utils/retry.js.map +1 -0
  252. package/dist/utils/session.d.ts.map +1 -0
  253. package/dist/utils/session.js.map +1 -0
  254. package/dist/{cjs/src/utils → utils}/template.d.ts +48 -0
  255. package/dist/utils/template.d.ts.map +1 -0
  256. package/dist/{src/utils → utils}/template.js +98 -0
  257. package/dist/utils/template.js.map +1 -0
  258. package/docs/README.md +1 -0
  259. package/docs/api/README.md +237 -12
  260. package/docs/api/overview.md +206 -3
  261. package/docs/architecture/data-extraction-flow.md +363 -0
  262. package/docs/architecture/multi-step-execution.md +243 -0
  263. package/docs/core/agent/README.md +156 -5
  264. package/docs/core/agent/rules-and-prohibitions.md +113 -0
  265. package/docs/core/agent/session-management.md +1 -1
  266. package/docs/core/ai-integration/prompt-composition.md +135 -0
  267. package/docs/core/ai-integration/response-processing.md +146 -0
  268. package/docs/core/conversation-flows/data-collection.md +143 -0
  269. package/docs/core/conversation-flows/routes.md +2 -2
  270. package/docs/core/conversation-flows/step-transitions.md +132 -0
  271. package/docs/core/conversation-flows/steps.md +112 -0
  272. package/docs/core/error-handling.md +193 -0
  273. package/docs/core/routing/intelligent-routing.md +118 -0
  274. package/docs/guides/getting-started/README.md +284 -3
  275. package/docs/guides/migration/README.md +27 -0
  276. package/docs/guides/migration/flexible-routing-conditions.md +375 -0
  277. package/docs/guides/migration/multi-step-execution.md +373 -0
  278. package/examples/advanced-patterns/knowledge-based-agent.ts +101 -24
  279. package/examples/advanced-patterns/persistent-onboarding.ts +40 -5
  280. package/examples/advanced-patterns/route-lifecycle-hooks.ts +82 -12
  281. package/examples/advanced-patterns/streaming-responses.ts +2 -2
  282. package/examples/ai-providers/anthropic-integration.ts +4 -4
  283. package/examples/ai-providers/openai-integration.ts +1 -1
  284. package/examples/condition-patterns/function-only-conditions.ts +365 -0
  285. package/examples/condition-patterns/mixed-array-conditions.ts +477 -0
  286. package/examples/condition-patterns/route-skipif-patterns.ts +468 -0
  287. package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
  288. package/examples/condition-patterns/string-only-conditions.ts +296 -0
  289. package/examples/conversation-flows/completion-transitions.ts +48 -7
  290. package/examples/core-concepts/basic-agent.ts +54 -33
  291. package/examples/core-concepts/schema-driven-extraction.ts +33 -9
  292. package/examples/core-concepts/session-management.ts +51 -16
  293. package/examples/integrations/database-integration.ts +6 -6
  294. package/examples/integrations/healthcare-integration.ts +10 -10
  295. package/examples/integrations/search-integration.ts +8 -8
  296. package/examples/integrations/server-session-management.ts +8 -8
  297. package/examples/persistence/database-persistence.ts +15 -15
  298. package/examples/persistence/memory-sessions.ts +3 -3
  299. package/examples/persistence/redis-persistence.ts +7 -9
  300. package/examples/tools/data-enrichment-tools.ts +4 -4
  301. package/package.json +6 -4
  302. package/src/adapters/PrismaAdapter.ts +3 -2
  303. package/src/adapters/RedisAdapter.ts +3 -3
  304. package/src/core/Agent.ts +78 -2
  305. package/src/core/BatchExecutor.ts +1166 -0
  306. package/src/core/BatchPromptBuilder.ts +293 -0
  307. package/src/core/PromptComposer.ts +53 -16
  308. package/src/core/ResponseEngine.ts +168 -29
  309. package/src/core/ResponseModal.ts +954 -74
  310. package/src/core/ResponsePipeline.ts +17 -9
  311. package/src/core/Route.ts +223 -22
  312. package/src/core/RoutingEngine.ts +426 -83
  313. package/src/core/Step.ts +144 -16
  314. package/src/index.ts +19 -0
  315. package/src/providers/AnthropicProvider.ts +17 -17
  316. package/src/providers/GeminiProvider.ts +129 -60
  317. package/src/providers/OpenAIProvider.ts +18 -18
  318. package/src/providers/OpenRouterProvider.ts +18 -18
  319. package/src/types/agent.ts +15 -3
  320. package/src/types/index.ts +12 -1
  321. package/src/types/route.ts +131 -12
  322. package/src/types/template.ts +70 -2
  323. package/src/utils/condition.ts +190 -0
  324. package/src/utils/index.ts +12 -0
  325. package/src/utils/json.ts +46 -0
  326. package/src/utils/retry.ts +5 -4
  327. package/src/utils/template.ts +109 -0
  328. package/dist/cjs/src/adapters/MemoryAdapter.d.ts.map +0 -1
  329. package/dist/cjs/src/adapters/MemoryAdapter.js.map +0 -1
  330. package/dist/cjs/src/adapters/MongoAdapter.d.ts.map +0 -1
  331. package/dist/cjs/src/adapters/MongoAdapter.js.map +0 -1
  332. package/dist/cjs/src/adapters/OpenSearchAdapter.d.ts.map +0 -1
  333. package/dist/cjs/src/adapters/OpenSearchAdapter.js.map +0 -1
  334. package/dist/cjs/src/adapters/PostgreSQLAdapter.d.ts.map +0 -1
  335. package/dist/cjs/src/adapters/PostgreSQLAdapter.js.map +0 -1
  336. package/dist/cjs/src/adapters/PrismaAdapter.d.ts.map +0 -1
  337. package/dist/cjs/src/adapters/PrismaAdapter.js.map +0 -1
  338. package/dist/cjs/src/adapters/RedisAdapter.d.ts.map +0 -1
  339. package/dist/cjs/src/adapters/RedisAdapter.js.map +0 -1
  340. package/dist/cjs/src/adapters/SQLiteAdapter.d.ts.map +0 -1
  341. package/dist/cjs/src/adapters/SQLiteAdapter.js.map +0 -1
  342. package/dist/cjs/src/adapters/index.d.ts.map +0 -1
  343. package/dist/cjs/src/adapters/index.js.map +0 -1
  344. package/dist/cjs/src/constants/index.d.ts.map +0 -1
  345. package/dist/cjs/src/constants/index.js.map +0 -1
  346. package/dist/cjs/src/core/Agent.d.ts.map +0 -1
  347. package/dist/cjs/src/core/Agent.js.map +0 -1
  348. package/dist/cjs/src/core/Events.d.ts.map +0 -1
  349. package/dist/cjs/src/core/Events.js.map +0 -1
  350. package/dist/cjs/src/core/PersistenceManager.d.ts.map +0 -1
  351. package/dist/cjs/src/core/PersistenceManager.js.map +0 -1
  352. package/dist/cjs/src/core/PromptComposer.d.ts.map +0 -1
  353. package/dist/cjs/src/core/PromptComposer.js.map +0 -1
  354. package/dist/cjs/src/core/ResponseEngine.d.ts.map +0 -1
  355. package/dist/cjs/src/core/ResponseEngine.js +0 -84
  356. package/dist/cjs/src/core/ResponseEngine.js.map +0 -1
  357. package/dist/cjs/src/core/ResponseModal.d.ts.map +0 -1
  358. package/dist/cjs/src/core/ResponseModal.js.map +0 -1
  359. package/dist/cjs/src/core/ResponsePipeline.d.ts.map +0 -1
  360. package/dist/cjs/src/core/ResponsePipeline.js.map +0 -1
  361. package/dist/cjs/src/core/Route.d.ts.map +0 -1
  362. package/dist/cjs/src/core/Route.js.map +0 -1
  363. package/dist/cjs/src/core/RoutingEngine.d.ts.map +0 -1
  364. package/dist/cjs/src/core/RoutingEngine.js.map +0 -1
  365. package/dist/cjs/src/core/SessionManager.d.ts.map +0 -1
  366. package/dist/cjs/src/core/SessionManager.js.map +0 -1
  367. package/dist/cjs/src/core/Step.d.ts.map +0 -1
  368. package/dist/cjs/src/core/Step.js.map +0 -1
  369. package/dist/cjs/src/core/ToolManager.d.ts.map +0 -1
  370. package/dist/cjs/src/core/ToolManager.js.map +0 -1
  371. package/dist/cjs/src/index.d.ts.map +0 -1
  372. package/dist/cjs/src/index.js.map +0 -1
  373. package/dist/cjs/src/providers/AnthropicProvider.d.ts.map +0 -1
  374. package/dist/cjs/src/providers/AnthropicProvider.js.map +0 -1
  375. package/dist/cjs/src/providers/GeminiProvider.d.ts.map +0 -1
  376. package/dist/cjs/src/providers/GeminiProvider.js.map +0 -1
  377. package/dist/cjs/src/providers/OpenAIProvider.d.ts.map +0 -1
  378. package/dist/cjs/src/providers/OpenAIProvider.js.map +0 -1
  379. package/dist/cjs/src/providers/OpenRouterProvider.d.ts.map +0 -1
  380. package/dist/cjs/src/providers/OpenRouterProvider.js.map +0 -1
  381. package/dist/cjs/src/providers/index.d.ts.map +0 -1
  382. package/dist/cjs/src/providers/index.js.map +0 -1
  383. package/dist/cjs/src/types/agent.d.ts.map +0 -1
  384. package/dist/cjs/src/types/agent.js.map +0 -1
  385. package/dist/cjs/src/types/ai.d.ts.map +0 -1
  386. package/dist/cjs/src/types/ai.js.map +0 -1
  387. package/dist/cjs/src/types/history.d.ts.map +0 -1
  388. package/dist/cjs/src/types/history.js.map +0 -1
  389. package/dist/cjs/src/types/index.d.ts.map +0 -1
  390. package/dist/cjs/src/types/index.js.map +0 -1
  391. package/dist/cjs/src/types/persistence.d.ts.map +0 -1
  392. package/dist/cjs/src/types/persistence.js.map +0 -1
  393. package/dist/cjs/src/types/route.d.ts.map +0 -1
  394. package/dist/cjs/src/types/routing.d.ts.map +0 -1
  395. package/dist/cjs/src/types/schema.d.ts.map +0 -1
  396. package/dist/cjs/src/types/session.d.ts.map +0 -1
  397. package/dist/cjs/src/types/session.js.map +0 -1
  398. package/dist/cjs/src/types/template.d.ts +0 -30
  399. package/dist/cjs/src/types/template.d.ts.map +0 -1
  400. package/dist/cjs/src/types/tool.d.ts.map +0 -1
  401. package/dist/cjs/src/types/tool.js.map +0 -1
  402. package/dist/cjs/src/utils/clone.d.ts.map +0 -1
  403. package/dist/cjs/src/utils/clone.js.map +0 -1
  404. package/dist/cjs/src/utils/event.d.ts.map +0 -1
  405. package/dist/cjs/src/utils/event.js.map +0 -1
  406. package/dist/cjs/src/utils/history.d.ts.map +0 -1
  407. package/dist/cjs/src/utils/history.js.map +0 -1
  408. package/dist/cjs/src/utils/id.d.ts.map +0 -1
  409. package/dist/cjs/src/utils/id.js.map +0 -1
  410. package/dist/cjs/src/utils/index.d.ts.map +0 -1
  411. package/dist/cjs/src/utils/index.js.map +0 -1
  412. package/dist/cjs/src/utils/logger.d.ts.map +0 -1
  413. package/dist/cjs/src/utils/logger.js.map +0 -1
  414. package/dist/cjs/src/utils/retry.d.ts.map +0 -1
  415. package/dist/cjs/src/utils/retry.js.map +0 -1
  416. package/dist/cjs/src/utils/session.d.ts.map +0 -1
  417. package/dist/cjs/src/utils/session.js.map +0 -1
  418. package/dist/cjs/src/utils/template.d.ts.map +0 -1
  419. package/dist/cjs/src/utils/template.js.map +0 -1
  420. package/dist/src/adapters/MemoryAdapter.js.map +0 -1
  421. package/dist/src/adapters/MongoAdapter.js.map +0 -1
  422. package/dist/src/adapters/OpenSearchAdapter.js.map +0 -1
  423. package/dist/src/adapters/PostgreSQLAdapter.js.map +0 -1
  424. package/dist/src/adapters/PrismaAdapter.js.map +0 -1
  425. package/dist/src/adapters/RedisAdapter.js.map +0 -1
  426. package/dist/src/adapters/SQLiteAdapter.js.map +0 -1
  427. package/dist/src/adapters/index.js.map +0 -1
  428. package/dist/src/constants/index.js.map +0 -1
  429. package/dist/src/core/Agent.d.ts.map +0 -1
  430. package/dist/src/core/Agent.js.map +0 -1
  431. package/dist/src/core/Events.js.map +0 -1
  432. package/dist/src/core/PersistenceManager.js.map +0 -1
  433. package/dist/src/core/PromptComposer.d.ts.map +0 -1
  434. package/dist/src/core/PromptComposer.js.map +0 -1
  435. package/dist/src/core/ResponseEngine.js +0 -80
  436. package/dist/src/core/ResponseEngine.js.map +0 -1
  437. package/dist/src/core/ResponseModal.d.ts.map +0 -1
  438. package/dist/src/core/ResponseModal.js.map +0 -1
  439. package/dist/src/core/ResponsePipeline.d.ts.map +0 -1
  440. package/dist/src/core/ResponsePipeline.js.map +0 -1
  441. package/dist/src/core/Route.d.ts.map +0 -1
  442. package/dist/src/core/Route.js.map +0 -1
  443. package/dist/src/core/RoutingEngine.d.ts.map +0 -1
  444. package/dist/src/core/RoutingEngine.js.map +0 -1
  445. package/dist/src/core/SessionManager.js.map +0 -1
  446. package/dist/src/core/Step.d.ts.map +0 -1
  447. package/dist/src/core/Step.js.map +0 -1
  448. package/dist/src/core/ToolManager.js.map +0 -1
  449. package/dist/src/index.d.ts.map +0 -1
  450. package/dist/src/index.js.map +0 -1
  451. package/dist/src/providers/AnthropicProvider.js.map +0 -1
  452. package/dist/src/providers/GeminiProvider.js.map +0 -1
  453. package/dist/src/providers/OpenAIProvider.js.map +0 -1
  454. package/dist/src/providers/OpenRouterProvider.js.map +0 -1
  455. package/dist/src/providers/index.js.map +0 -1
  456. package/dist/src/types/agent.d.ts.map +0 -1
  457. package/dist/src/types/agent.js.map +0 -1
  458. package/dist/src/types/history.js.map +0 -1
  459. package/dist/src/types/index.js.map +0 -1
  460. package/dist/src/types/persistence.js.map +0 -1
  461. package/dist/src/types/route.d.ts.map +0 -1
  462. package/dist/src/types/template.d.ts +0 -30
  463. package/dist/src/types/template.d.ts.map +0 -1
  464. package/dist/src/types/tool.js.map +0 -1
  465. package/dist/src/utils/clone.js.map +0 -1
  466. package/dist/src/utils/event.js.map +0 -1
  467. package/dist/src/utils/history.js.map +0 -1
  468. package/dist/src/utils/id.js.map +0 -1
  469. package/dist/src/utils/index.d.ts.map +0 -1
  470. package/dist/src/utils/index.js.map +0 -1
  471. package/dist/src/utils/logger.js.map +0 -1
  472. package/dist/src/utils/retry.d.ts.map +0 -1
  473. package/dist/src/utils/retry.js.map +0 -1
  474. package/dist/src/utils/session.js.map +0 -1
  475. package/dist/src/utils/template.d.ts.map +0 -1
  476. package/dist/src/utils/template.js.map +0 -1
  477. /package/dist/{cjs/src/adapters → adapters}/MemoryAdapter.d.ts +0 -0
  478. /package/dist/{src/adapters → adapters}/MemoryAdapter.js +0 -0
  479. /package/dist/{cjs/src/adapters → adapters}/MongoAdapter.d.ts +0 -0
  480. /package/dist/{src/adapters → adapters}/MongoAdapter.js +0 -0
  481. /package/dist/{cjs/src/adapters → adapters}/OpenSearchAdapter.d.ts +0 -0
  482. /package/dist/{src/adapters → adapters}/OpenSearchAdapter.js +0 -0
  483. /package/dist/{cjs/src/adapters → adapters}/PostgreSQLAdapter.d.ts +0 -0
  484. /package/dist/{src/adapters → adapters}/PostgreSQLAdapter.js +0 -0
  485. /package/dist/{cjs/src/adapters → adapters}/PrismaAdapter.d.ts +0 -0
  486. /package/dist/{cjs/src/adapters → adapters}/RedisAdapter.d.ts +0 -0
  487. /package/dist/{cjs/src/adapters → adapters}/SQLiteAdapter.d.ts +0 -0
  488. /package/dist/{src/adapters → adapters}/SQLiteAdapter.js +0 -0
  489. /package/dist/{cjs/src/adapters → adapters}/index.d.ts +0 -0
  490. /package/dist/{src/adapters → adapters}/index.js +0 -0
  491. /package/dist/{src → cjs}/adapters/MemoryAdapter.d.ts +0 -0
  492. /package/dist/{src → cjs}/adapters/MemoryAdapter.d.ts.map +0 -0
  493. /package/dist/cjs/{src/adapters → adapters}/MemoryAdapter.js +0 -0
  494. /package/dist/{src → cjs}/adapters/MongoAdapter.d.ts +0 -0
  495. /package/dist/{src → cjs}/adapters/MongoAdapter.d.ts.map +0 -0
  496. /package/dist/cjs/{src/adapters → adapters}/MongoAdapter.js +0 -0
  497. /package/dist/{src → cjs}/adapters/OpenSearchAdapter.d.ts +0 -0
  498. /package/dist/{src → cjs}/adapters/OpenSearchAdapter.d.ts.map +0 -0
  499. /package/dist/cjs/{src/adapters → adapters}/OpenSearchAdapter.js +0 -0
  500. /package/dist/{src → cjs}/adapters/PostgreSQLAdapter.d.ts +0 -0
  501. /package/dist/{src → cjs}/adapters/PostgreSQLAdapter.d.ts.map +0 -0
  502. /package/dist/cjs/{src/adapters → adapters}/PostgreSQLAdapter.js +0 -0
  503. /package/dist/{src → cjs}/adapters/PrismaAdapter.d.ts +0 -0
  504. /package/dist/{src → cjs}/adapters/RedisAdapter.d.ts +0 -0
  505. /package/dist/{src → cjs}/adapters/RedisAdapter.d.ts.map +0 -0
  506. /package/dist/{src → cjs}/adapters/SQLiteAdapter.d.ts +0 -0
  507. /package/dist/{src → cjs}/adapters/SQLiteAdapter.d.ts.map +0 -0
  508. /package/dist/cjs/{src/adapters → adapters}/SQLiteAdapter.js +0 -0
  509. /package/dist/{src → cjs}/adapters/index.d.ts +0 -0
  510. /package/dist/{src → cjs}/adapters/index.d.ts.map +0 -0
  511. /package/dist/cjs/{src/adapters → adapters}/index.js +0 -0
  512. /package/dist/cjs/{src/constants → constants}/index.d.ts +0 -0
  513. /package/dist/{src → cjs}/constants/index.d.ts.map +0 -0
  514. /package/dist/cjs/{src/constants → constants}/index.js +0 -0
  515. /package/dist/cjs/{src/core → core}/Events.d.ts +0 -0
  516. /package/dist/{src → cjs}/core/Events.d.ts.map +0 -0
  517. /package/dist/cjs/{src/core → core}/Events.js +0 -0
  518. /package/dist/cjs/{src/core → core}/PersistenceManager.d.ts +0 -0
  519. /package/dist/{src → cjs}/core/PersistenceManager.d.ts.map +0 -0
  520. /package/dist/cjs/{src/core → core}/PersistenceManager.js +0 -0
  521. /package/dist/cjs/{src/core → core}/ResponseEngine.d.ts +0 -0
  522. /package/dist/cjs/{src/core → core}/SessionManager.d.ts +0 -0
  523. /package/dist/{src → cjs}/core/SessionManager.d.ts.map +0 -0
  524. /package/dist/cjs/{src/core → core}/SessionManager.js +0 -0
  525. /package/dist/cjs/{src/core → core}/ToolManager.d.ts +0 -0
  526. /package/dist/{src → cjs}/core/ToolManager.d.ts.map +0 -0
  527. /package/dist/cjs/{src/core → core}/ToolManager.js +0 -0
  528. /package/dist/cjs/{src/providers → providers}/AnthropicProvider.d.ts +0 -0
  529. /package/dist/{src → cjs}/providers/AnthropicProvider.d.ts.map +0 -0
  530. /package/dist/cjs/{src/providers → providers}/GeminiProvider.d.ts +0 -0
  531. /package/dist/cjs/{src/providers → providers}/OpenAIProvider.d.ts +0 -0
  532. /package/dist/{src → cjs}/providers/OpenAIProvider.d.ts.map +0 -0
  533. /package/dist/cjs/{src/providers → providers}/OpenRouterProvider.d.ts +0 -0
  534. /package/dist/{src → cjs}/providers/OpenRouterProvider.d.ts.map +0 -0
  535. /package/dist/cjs/{src/providers → providers}/index.d.ts +0 -0
  536. /package/dist/{src → cjs}/providers/index.d.ts.map +0 -0
  537. /package/dist/cjs/{src/providers → providers}/index.js +0 -0
  538. /package/dist/cjs/{src/types → types}/agent.js +0 -0
  539. /package/dist/cjs/{src/types → types}/ai.d.ts +0 -0
  540. /package/dist/{src → cjs}/types/ai.d.ts.map +0 -0
  541. /package/dist/cjs/{src/types → types}/ai.js +0 -0
  542. /package/dist/cjs/{src/types → types}/history.d.ts +0 -0
  543. /package/dist/{src → cjs}/types/history.d.ts.map +0 -0
  544. /package/dist/cjs/{src/types → types}/history.js +0 -0
  545. /package/dist/cjs/{src/types → types}/persistence.d.ts +0 -0
  546. /package/dist/{src → cjs}/types/persistence.d.ts.map +0 -0
  547. /package/dist/cjs/{src/types → types}/persistence.js +0 -0
  548. /package/dist/cjs/{src/types → types}/route.js +0 -0
  549. /package/dist/cjs/{src/types → types}/routing.d.ts +0 -0
  550. /package/dist/{src → cjs}/types/routing.d.ts.map +0 -0
  551. /package/dist/cjs/{src/types → types}/routing.js +0 -0
  552. /package/dist/{src → cjs}/types/routing.js.map +0 -0
  553. /package/dist/cjs/{src/types → types}/schema.d.ts +0 -0
  554. /package/dist/{src → cjs}/types/schema.d.ts.map +0 -0
  555. /package/dist/cjs/{src/types → types}/schema.js +0 -0
  556. /package/dist/{src → cjs}/types/schema.js.map +0 -0
  557. /package/dist/cjs/{src/types → types}/session.d.ts +0 -0
  558. /package/dist/{src → cjs}/types/session.d.ts.map +0 -0
  559. /package/dist/cjs/{src/types → types}/session.js +0 -0
  560. /package/dist/cjs/{src/types → types}/template.js +0 -0
  561. /package/dist/{src → cjs}/types/template.js.map +0 -0
  562. /package/dist/cjs/{src/types → types}/tool.d.ts +0 -0
  563. /package/dist/{src → cjs}/types/tool.d.ts.map +0 -0
  564. /package/dist/cjs/{src/types → types}/tool.js +0 -0
  565. /package/dist/cjs/{src/utils → utils}/clone.d.ts +0 -0
  566. /package/dist/{src → cjs}/utils/clone.d.ts.map +0 -0
  567. /package/dist/cjs/{src/utils → utils}/clone.js +0 -0
  568. /package/dist/cjs/{src/utils → utils}/event.d.ts +0 -0
  569. /package/dist/{src → cjs}/utils/event.d.ts.map +0 -0
  570. /package/dist/cjs/{src/utils → utils}/event.js +0 -0
  571. /package/dist/cjs/{src/utils → utils}/history.d.ts +0 -0
  572. /package/dist/{src → cjs}/utils/history.d.ts.map +0 -0
  573. /package/dist/cjs/{src/utils → utils}/history.js +0 -0
  574. /package/dist/cjs/{src/utils → utils}/id.d.ts +0 -0
  575. /package/dist/{src → cjs}/utils/id.d.ts.map +0 -0
  576. /package/dist/cjs/{src/utils → utils}/id.js +0 -0
  577. /package/dist/cjs/{src/utils → utils}/logger.d.ts +0 -0
  578. /package/dist/{src → cjs}/utils/logger.d.ts.map +0 -0
  579. /package/dist/cjs/{src/utils → utils}/logger.js +0 -0
  580. /package/dist/cjs/{src/utils → utils}/session.d.ts +0 -0
  581. /package/dist/{src → cjs}/utils/session.d.ts.map +0 -0
  582. /package/dist/cjs/{src/utils → utils}/session.js +0 -0
  583. /package/dist/{src/constants → constants}/index.d.ts +0 -0
  584. /package/dist/{src/constants → constants}/index.js +0 -0
  585. /package/dist/{src/core → core}/Events.d.ts +0 -0
  586. /package/dist/{src/core → core}/Events.js +0 -0
  587. /package/dist/{src/core → core}/PersistenceManager.d.ts +0 -0
  588. /package/dist/{src/core → core}/PersistenceManager.js +0 -0
  589. /package/dist/{src/core → core}/ResponseEngine.d.ts +0 -0
  590. /package/dist/{src/core → core}/SessionManager.d.ts +0 -0
  591. /package/dist/{src/core → core}/SessionManager.js +0 -0
  592. /package/dist/{src/core → core}/ToolManager.d.ts +0 -0
  593. /package/dist/{src/core → core}/ToolManager.js +0 -0
  594. /package/dist/{src/providers → providers}/AnthropicProvider.d.ts +0 -0
  595. /package/dist/{src/providers → providers}/GeminiProvider.d.ts +0 -0
  596. /package/dist/{src/providers → providers}/OpenAIProvider.d.ts +0 -0
  597. /package/dist/{src/providers → providers}/OpenRouterProvider.d.ts +0 -0
  598. /package/dist/{src/providers → providers}/index.d.ts +0 -0
  599. /package/dist/{src/providers → providers}/index.js +0 -0
  600. /package/dist/{src/types → types}/agent.js +0 -0
  601. /package/dist/{src/types → types}/ai.d.ts +0 -0
  602. /package/dist/{src/types → types}/ai.js +0 -0
  603. /package/dist/{src/types → types}/history.d.ts +0 -0
  604. /package/dist/{src/types → types}/history.js +0 -0
  605. /package/dist/{src/types → types}/persistence.d.ts +0 -0
  606. /package/dist/{src/types → types}/persistence.js +0 -0
  607. /package/dist/{src/types → types}/route.js +0 -0
  608. /package/dist/{src/types → types}/routing.d.ts +0 -0
  609. /package/dist/{src/types → types}/routing.js +0 -0
  610. /package/dist/{src/types → types}/schema.d.ts +0 -0
  611. /package/dist/{src/types → types}/schema.js +0 -0
  612. /package/dist/{src/types → types}/session.d.ts +0 -0
  613. /package/dist/{src/types → types}/session.js +0 -0
  614. /package/dist/{src/types → types}/template.js +0 -0
  615. /package/dist/{src/types → types}/tool.d.ts +0 -0
  616. /package/dist/{src/types → types}/tool.js +0 -0
  617. /package/dist/{src/utils → utils}/clone.d.ts +0 -0
  618. /package/dist/{src/utils → utils}/clone.js +0 -0
  619. /package/dist/{src/utils → utils}/event.d.ts +0 -0
  620. /package/dist/{src/utils → utils}/event.js +0 -0
  621. /package/dist/{src/utils → utils}/history.d.ts +0 -0
  622. /package/dist/{src/utils → utils}/history.js +0 -0
  623. /package/dist/{src/utils → utils}/id.d.ts +0 -0
  624. /package/dist/{src/utils → utils}/id.js +0 -0
  625. /package/dist/{src/utils → utils}/logger.d.ts +0 -0
  626. /package/dist/{src/utils → utils}/logger.js +0 -0
  627. /package/dist/{src/utils → utils}/session.d.ts +0 -0
  628. /package/dist/{src/utils → utils}/session.js +0 -0
@@ -9,7 +9,10 @@ const types_1 = require("../types");
9
9
  const Step_1 = require("./Step");
10
10
  const ResponseEngine_1 = require("./ResponseEngine");
11
11
  const ResponsePipeline_1 = require("./ResponsePipeline");
12
+ const BatchExecutor_1 = require("./BatchExecutor");
13
+ const BatchPromptBuilder_1 = require("./BatchPromptBuilder");
12
14
  const utils_1 = require("../utils");
15
+ const template_1 = require("../utils/template");
13
16
  const constants_1 = require("../constants");
14
17
  /**
15
18
  * Error class for response generation failures
@@ -52,6 +55,10 @@ class ResponseModal {
52
55
  // Initialize response pipeline with agent dependencies
53
56
  this.responsePipeline = new ResponsePipeline_1.ResponsePipeline(this.agent.getAgentOptions(), () => this.agent.getRoutes(), // Pass a function to get routes dynamically
54
57
  this.agent.getTools(), this.agent.getRoutingEngine(), this.agent.updateContext.bind(this.agent), this.agent.getUpdateDataMethod(), this.agent.updateCollectedData.bind(this.agent), this.getToolManager());
58
+ // Initialize batch executor for multi-step execution
59
+ this.batchExecutor = new BatchExecutor_1.BatchExecutor();
60
+ // Initialize batch prompt builder for combined prompts
61
+ this.batchPromptBuilder = new BatchPromptBuilder_1.BatchPromptBuilder();
55
62
  }
56
63
  /**
57
64
  * Generate a non-streaming response using unified logic
@@ -272,6 +279,7 @@ class ResponseModal {
272
279
  throw ResponseGenerationError.fromError(error, 'step_preparation', params, { session, effectiveContext });
273
280
  }
274
281
  // PHASE 2: ROUTING + STEP SELECTION - Determine which route and step to use
282
+ // Also performs pre-extraction and batch determination
275
283
  let routingResult;
276
284
  try {
277
285
  routingResult = await this.handleUnifiedRoutingAndStepSelection({
@@ -292,6 +300,9 @@ class ResponseModal {
292
300
  selectedStep: routingResult.selectedStep,
293
301
  responseDirectives: routingResult.responseDirectives,
294
302
  isRouteComplete: routingResult.isRouteComplete,
303
+ batchSteps: routingResult.batchSteps,
304
+ batchStoppedReason: routingResult.batchStoppedReason,
305
+ batchStoppedAtStep: routingResult.batchStoppedAtStep,
295
306
  };
296
307
  }
297
308
  catch (error) {
@@ -317,31 +328,156 @@ class ResponseModal {
317
328
  context: params.context,
318
329
  signal: params.signal,
319
330
  });
331
+ let updatedSession = routingResult.session;
332
+ let isRouteComplete = routingResult.isRouteComplete;
333
+ // PRE-EXTRACTION: If entering a route that collects data, extract data from user message first
334
+ // This allows us to skip steps whose data is already provided
335
+ // Requirement 3.1: Perform Pre_Extraction before determining the Batch
336
+ if (routingResult.selectedRoute && !isRouteComplete) {
337
+ // Always pre-extract when route collects data (not just on new route entry)
338
+ // This ensures batch determination has the most up-to-date data
339
+ if (this.shouldPreExtractData(routingResult.selectedRoute)) {
340
+ utils_1.logger.debug(`[ResponseModal] Pre-extracting data for route: ${routingResult.selectedRoute.title}`);
341
+ const extractedData = await this.preExtractRouteData({
342
+ route: routingResult.selectedRoute,
343
+ history: params.history,
344
+ context: params.context,
345
+ session: updatedSession,
346
+ signal: params.signal,
347
+ });
348
+ if (extractedData && Object.keys(extractedData).length > 0) {
349
+ utils_1.logger.debug(`[ResponseModal] Pre-extracted data:`, extractedData);
350
+ // Requirement 3.3: Merge pre-extracted data into session before batch determination
351
+ updatedSession = (0, utils_1.mergeCollected)(updatedSession, extractedData);
352
+ // Also update agent's collected data
353
+ await this.agent.updateCollectedData(extractedData);
354
+ // Re-check route completion after pre-extraction
355
+ const allRequiredFieldsCollected = routingResult.selectedRoute.isComplete(updatedSession.data || {});
356
+ if (allRequiredFieldsCollected) {
357
+ utils_1.logger.debug(`[ResponseModal] Route ${routingResult.selectedRoute.title} completed after pre-extraction`);
358
+ isRouteComplete = true;
359
+ }
360
+ }
361
+ }
362
+ }
363
+ // BATCH DETERMINATION: Use BatchExecutor to determine which steps can execute together
364
+ // Requirement 3.4: Pre-extraction results affect batch determination
365
+ let batchSteps;
366
+ let batchStoppedReason;
367
+ let batchStoppedAtStep;
368
+ if (routingResult.selectedRoute && !isRouteComplete) {
369
+ // Determine current step position for batch determination
370
+ const currentStep = routingResult.selectedStep ||
371
+ (updatedSession.currentStep ? routingResult.selectedRoute.getStep(updatedSession.currentStep.id) : undefined);
372
+ utils_1.logger.debug(`[ResponseModal] Determining batch starting from step: ${currentStep?.id || 'initial'}`);
373
+ const batchResult = await this.batchExecutor.determineBatch({
374
+ route: routingResult.selectedRoute,
375
+ currentStep,
376
+ sessionData: updatedSession.data || {},
377
+ context: params.context,
378
+ });
379
+ batchSteps = batchResult.steps;
380
+ batchStoppedReason = batchResult.stoppedReason;
381
+ batchStoppedAtStep = batchResult.stoppedAtStep;
382
+ utils_1.logger.debug(`[ResponseModal] Batch determined: ${batchSteps.length} steps, stopped reason: ${batchStoppedReason}`);
383
+ }
320
384
  // Determine next step using pipeline method for consistency
321
- const stepResult = this.responsePipeline.determineNextStep({
385
+ const stepResult = await this.responsePipeline.determineNextStep({
322
386
  selectedRoute: routingResult.selectedRoute,
323
387
  selectedStep: routingResult.selectedStep,
324
- session: routingResult.session,
325
- isRouteComplete: routingResult.isRouteComplete,
388
+ session: updatedSession, // Use updated session with pre-extracted data
389
+ isRouteComplete, // Use updated completion status
326
390
  });
327
391
  return {
328
392
  selectedRoute: routingResult.selectedRoute,
329
393
  selectedStep: stepResult.nextStep, // Use the determined next step
330
394
  responseDirectives: routingResult.responseDirectives,
331
395
  session: stepResult.session,
332
- isRouteComplete: routingResult.isRouteComplete,
396
+ isRouteComplete, // Use updated completion status
397
+ batchSteps,
398
+ batchStoppedReason,
399
+ batchStoppedAtStep,
333
400
  };
334
401
  }
335
402
  catch (error) {
336
403
  throw ResponseGenerationError.fromError(error, 'routing_optimization', params);
337
404
  }
338
405
  }
406
+ /**
407
+ * Check if a route should pre-extract data before determining the initial step
408
+ * @private
409
+ */
410
+ shouldPreExtractData(route) {
411
+ // Pre-extract if route has declared required or optional fields
412
+ if (route.requiredFields && route.requiredFields.length > 0) {
413
+ return true;
414
+ }
415
+ if (route.optionalFields && route.optionalFields.length > 0) {
416
+ return true;
417
+ }
418
+ // Pre-extract if any step in the route collects data
419
+ const steps = route.getAllSteps();
420
+ const hasDataCollectionSteps = steps.some(step => step.collect && step.collect.length > 0);
421
+ return hasDataCollectionSteps;
422
+ }
423
+ /**
424
+ * Pre-extract data from user message when entering a route
425
+ * This allows skipping steps whose data is already provided
426
+ * @private
427
+ */
428
+ async preExtractRouteData(params) {
429
+ const { route, history, context, signal } = params;
430
+ // Build a schema for data extraction based on route's fields
431
+ const extractionSchema = this.agent.getSchema();
432
+ if (!extractionSchema) {
433
+ utils_1.logger.warn(`[ResponseModal] No schema available for pre-extraction`);
434
+ return {};
435
+ }
436
+ // Get last user message
437
+ const lastMessage = (0, utils_1.getLastMessageFromHistory)(history);
438
+ // Build extraction prompt
439
+ const extractionPrompt = [
440
+ `Extract any relevant information from the user's message that matches the following data fields.`,
441
+ `Only extract information that is explicitly stated or clearly implied.`,
442
+ ``,
443
+ `User's message: "${lastMessage}"`,
444
+ ``,
445
+ `Extract data for these fields if present:`,
446
+ ];
447
+ // Add field descriptions
448
+ if (route.requiredFields) {
449
+ extractionPrompt.push(`Required fields: ${route.requiredFields.join(', ')}`);
450
+ }
451
+ if (route.optionalFields) {
452
+ extractionPrompt.push(`Optional fields: ${route.optionalFields.join(', ')}`);
453
+ }
454
+ extractionPrompt.push(``, `Return ONLY the extracted data as JSON. If no data can be extracted, return an empty object {}.`);
455
+ // Call AI to extract data
456
+ const agentOptions = this.agent.getAgentOptions();
457
+ try {
458
+ const result = await agentOptions.provider.generateMessage({
459
+ prompt: extractionPrompt.join('\n'),
460
+ history,
461
+ context,
462
+ signal,
463
+ parameters: {
464
+ jsonSchema: extractionSchema,
465
+ schemaName: 'data_extraction',
466
+ },
467
+ });
468
+ return result.structured || {};
469
+ }
470
+ catch (error) {
471
+ utils_1.logger.error(`[ResponseModal] Pre-extraction failed:`, error);
472
+ return {};
473
+ }
474
+ }
339
475
  /**
340
476
  * Unified response generation for non-streaming responses
341
477
  * @private
342
478
  */
343
479
  async generateUnifiedResponse(responseContext) {
344
- const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete } = responseContext;
480
+ const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete, batchSteps, batchStoppedReason, } = responseContext;
345
481
  let session = initialSession;
346
482
  // Get last user message (needed for both route and completion handling)
347
483
  // Convert HistoryItem[] to Event[] for internal processing
@@ -349,35 +485,79 @@ class ResponseModal {
349
485
  const lastMessageText = (0, utils_1.getLastMessageFromHistory)(historyEvents);
350
486
  let message;
351
487
  let toolCalls = undefined;
488
+ let executedSteps;
489
+ let stoppedReason;
352
490
  if (selectedRoute && !isRouteComplete) {
353
- // Handle normal route processing
354
- const result = await this.processRouteResponse({
355
- selectedRoute,
356
- selectedStep,
357
- responseDirectives,
358
- session,
359
- history,
360
- context: effectiveContext,
361
- lastMessageText,
362
- historyEvents,
363
- signal: responseContext.history ? undefined : undefined, // TODO: Fix signal passing
364
- });
365
- message = result.message;
366
- toolCalls = result.toolCalls;
367
- session = result.session;
491
+ // Check if we have batch steps to execute
492
+ if (batchSteps && batchSteps.length > 0) {
493
+ // BATCH EXECUTION: Execute multiple steps in a single LLM call
494
+ utils_1.logger.debug(`[ResponseModal] Executing batch of ${batchSteps.length} steps`);
495
+ const batchResult = await this.executeBatchResponse({
496
+ selectedRoute,
497
+ batchSteps,
498
+ responseDirectives,
499
+ session,
500
+ history,
501
+ context: effectiveContext,
502
+ historyEvents,
503
+ });
504
+ message = batchResult.message;
505
+ toolCalls = batchResult.toolCalls;
506
+ session = batchResult.session;
507
+ executedSteps = batchResult.executedSteps;
508
+ stoppedReason = batchStoppedReason;
509
+ }
510
+ else {
511
+ // SINGLE STEP EXECUTION: Fall back to single-step processing
512
+ // This happens when batch determination returns empty (first step needs input)
513
+ const result = await this.processRouteResponse({
514
+ selectedRoute,
515
+ selectedStep,
516
+ responseDirectives,
517
+ session,
518
+ history,
519
+ context: effectiveContext,
520
+ lastMessageText,
521
+ historyEvents,
522
+ signal: undefined,
523
+ });
524
+ message = result.message;
525
+ toolCalls = result.toolCalls;
526
+ session = result.session;
527
+ // Track executed step for single-step execution
528
+ if (selectedStep) {
529
+ executedSteps = [{
530
+ id: selectedStep.id,
531
+ routeId: selectedRoute.id,
532
+ }];
533
+ }
534
+ stoppedReason = batchStoppedReason || 'needs_input';
535
+ }
368
536
  }
369
537
  else if (isRouteComplete && selectedRoute) {
370
538
  // Handle route completion
371
- message = await this.handleRouteCompletion({
372
- selectedRoute,
373
- session,
374
- context: effectiveContext,
375
- lastMessageText,
376
- historyEvents,
377
- });
378
- // Set step to END_ROUTE marker
379
- session = (0, utils_1.enterStep)(session, constants_1.END_ROUTE_ID, "Route completed");
380
- utils_1.logger.debug(`[ResponseModal] Route ${selectedRoute.title} completed. Entered END_ROUTE step.`);
539
+ utils_1.logger.debug(`[ResponseModal] Generating completion message for route: ${selectedRoute.title}`);
540
+ try {
541
+ message = await this.handleRouteCompletion({
542
+ selectedRoute,
543
+ session,
544
+ context: effectiveContext,
545
+ lastMessageText,
546
+ historyEvents,
547
+ signal: undefined,
548
+ });
549
+ // Set step to END_ROUTE marker
550
+ session = (0, utils_1.enterStep)(session, constants_1.END_ROUTE_ID, "Route completed");
551
+ stoppedReason = 'route_complete';
552
+ utils_1.logger.debug(`[ResponseModal] Route ${selectedRoute.title} completed. Entered END_ROUTE step.`);
553
+ }
554
+ catch (error) {
555
+ utils_1.logger.error(`[ResponseModal] Error generating completion message:`, error);
556
+ // Fallback to simple completion message
557
+ message = `Thank you! I've recorded all the information for your ${selectedRoute.title.toLowerCase()}.`;
558
+ session = (0, utils_1.enterStep)(session, constants_1.END_ROUTE_ID, "Route completed");
559
+ stoppedReason = 'route_complete';
560
+ }
381
561
  }
382
562
  else {
383
563
  // Fallback: No routes defined, generate a simple response
@@ -386,37 +566,275 @@ class ResponseModal {
386
566
  context: effectiveContext,
387
567
  session,
388
568
  });
569
+ // For fallback responses, set empty executedSteps and no stoppedReason
570
+ // since there's no route/step execution happening
571
+ executedSteps = [];
572
+ stoppedReason = undefined;
389
573
  }
574
+ // Ensure response structure completeness (Requirement 8.1, 8.2, 8.3)
575
+ // - executedSteps: array of steps executed (empty array if none)
576
+ // - stoppedReason: why execution stopped (undefined for fallback)
577
+ // - session.currentStep: reflects final step position
390
578
  return {
391
579
  message,
392
580
  session,
393
581
  toolCalls,
394
582
  isRouteComplete,
583
+ executedSteps: executedSteps || [],
584
+ stoppedReason,
585
+ };
586
+ }
587
+ /**
588
+ * Execute a batch of steps with a single LLM call
589
+ *
590
+ * This method:
591
+ * 1. Executes all prepare hooks for steps in the batch (in order)
592
+ * 2. Builds a combined prompt using BatchPromptBuilder
593
+ * 3. Makes a single LLM call
594
+ * 4. Collects data from the response for all steps
595
+ * 5. Executes all finalize hooks for steps in the batch (in order)
596
+ *
597
+ * @private
598
+ * **Validates: Requirements 1.1, 4.4, 5.1, 5.2**
599
+ */
600
+ async executeBatchResponse(params) {
601
+ const { selectedRoute, batchSteps, history, context, historyEvents, signal } = params;
602
+ let session = params.session;
603
+ utils_1.logger.debug(`[ResponseModal] Starting batch execution for ${batchSteps.length} steps`);
604
+ // Create hook executor function
605
+ const executeHook = async (hook, hookContext, data, step) => {
606
+ // Find the route for this step
607
+ const route = selectedRoute;
608
+ // Convert StepOptions to Step if needed for executePrepareFinalize
609
+ const stepInstance = step?.id ? route.getStep(step.id) : undefined;
610
+ await this.executePrepareFinalize(hook, hookContext, data, route, stepInstance);
611
+ };
612
+ // PHASE 1: Execute all prepare hooks (Requirement 5.1)
613
+ utils_1.logger.debug(`[ResponseModal] Executing prepare hooks for batch`);
614
+ const prepareResult = await this.batchExecutor.executePrepareHooks({
615
+ steps: batchSteps,
616
+ context,
617
+ data: session.data,
618
+ executeHook,
619
+ });
620
+ if (!prepareResult.success) {
621
+ // Prepare hook failed - return error response
622
+ utils_1.logger.error(`[ResponseModal] Prepare hook failed:`, prepareResult.error);
623
+ throw new ResponseGenerationError(`Prepare hook failed: ${prepareResult.error?.message}`, {
624
+ phase: 'prepare_hooks',
625
+ context: {
626
+ stepId: prepareResult.error?.stepId,
627
+ executedSteps: prepareResult.executedSteps,
628
+ }
629
+ });
630
+ }
631
+ // PHASE 2: Build combined prompt using BatchPromptBuilder (Requirement 4.4)
632
+ utils_1.logger.debug(`[ResponseModal] Building batch prompt`);
633
+ const batchPromptResult = await this.batchPromptBuilder.buildBatchPrompt({
634
+ steps: batchSteps,
635
+ route: selectedRoute,
636
+ history: historyEvents,
637
+ context,
638
+ session,
639
+ agentOptions: this.agent.getAgentOptions(),
640
+ });
641
+ utils_1.logger.debug(`[ResponseModal] Batch prompt built with ${batchPromptResult.stepCount} steps, collecting: ${batchPromptResult.collectFields.join(', ')}`);
642
+ // Build response schema for batch (includes all collect fields)
643
+ const responseSchema = this.buildBatchResponseSchema(batchPromptResult.collectFields);
644
+ // Collect available tools for AI (from all steps in batch)
645
+ const availableTools = this.collectBatchAvailableTools(selectedRoute, batchSteps);
646
+ // PHASE 3: Make single LLM call (Requirement 4.4)
647
+ utils_1.logger.debug(`[ResponseModal] Making LLM call for batch`);
648
+ const agentOptions = this.agent.getAgentOptions();
649
+ const result = await agentOptions.provider.generateMessage({
650
+ prompt: batchPromptResult.prompt,
651
+ history: historyEvents,
652
+ context,
653
+ tools: availableTools,
654
+ signal,
655
+ parameters: responseSchema ? { jsonSchema: responseSchema, schemaName: "batch_response" } : undefined,
656
+ });
657
+ let message = result.structured?.message || result.message;
658
+ let toolCalls = result.structured?.toolCalls;
659
+ utils_1.logger.debug(`[ResponseModal] LLM response received for batch`);
660
+ // Execute tools if any
661
+ if (toolCalls && toolCalls.length > 0) {
662
+ const toolResult = await this.executeUnifiedToolLoop({
663
+ toolCalls,
664
+ context,
665
+ session,
666
+ history,
667
+ selectedRoute,
668
+ responsePrompt: batchPromptResult.prompt,
669
+ availableTools,
670
+ responseSchema,
671
+ signal,
672
+ });
673
+ session = toolResult.session;
674
+ toolCalls = toolResult.finalToolCalls;
675
+ if (toolResult.finalMessage) {
676
+ message = toolResult.finalMessage;
677
+ }
678
+ }
679
+ // PHASE 4: Collect data from response for all steps (Requirement 6.1, 6.2, 6.3)
680
+ utils_1.logger.debug(`[ResponseModal] Collecting batch data`);
681
+ const collectResult = this.batchExecutor.collectBatchData({
682
+ steps: batchSteps,
683
+ llmResponse: result.structured || {},
684
+ session,
685
+ schema: this.agent.getSchema(),
686
+ });
687
+ session = collectResult.session;
688
+ if (collectResult.collectedData && Object.keys(collectResult.collectedData).length > 0) {
689
+ // Update agent's collected data
690
+ await this.agent.updateCollectedData(collectResult.collectedData);
691
+ utils_1.logger.debug(`[ResponseModal] Batch collected data:`, collectResult.collectedData);
692
+ }
693
+ if (collectResult.validationErrors && collectResult.validationErrors.length > 0) {
694
+ utils_1.logger.warn(`[ResponseModal] Batch data validation errors:`, collectResult.validationErrors);
695
+ }
696
+ // Update session to final step position
697
+ const lastStep = batchSteps[batchSteps.length - 1];
698
+ if (lastStep?.id) {
699
+ session = (0, utils_1.enterStep)(session, lastStep.id, lastStep.description);
700
+ utils_1.logger.debug(`[ResponseModal] Updated session to final batch step: ${lastStep.id}`);
701
+ }
702
+ // PHASE 5: Execute all finalize hooks (Requirement 5.2)
703
+ utils_1.logger.debug(`[ResponseModal] Executing finalize hooks for batch`);
704
+ const finalizeResult = await this.batchExecutor.executeFinalizeHooks({
705
+ steps: batchSteps,
706
+ context,
707
+ data: session.data,
708
+ executeHook,
709
+ });
710
+ if (finalizeResult.errors && finalizeResult.errors.length > 0) {
711
+ // Log finalize errors but don't fail (Requirement 5.5)
712
+ utils_1.logger.warn(`[ResponseModal] Some finalize hooks failed:`, finalizeResult.errors);
713
+ }
714
+ // Build executed steps list
715
+ const executedSteps = batchSteps
716
+ .filter(step => step.id)
717
+ .map(step => ({
718
+ id: step.id,
719
+ routeId: selectedRoute.id,
720
+ }));
721
+ utils_1.logger.debug(`[ResponseModal] Batch execution complete. Executed ${executedSteps.length} steps`);
722
+ return {
723
+ message,
724
+ toolCalls,
725
+ session,
726
+ executedSteps,
727
+ };
728
+ }
729
+ /**
730
+ * Build response schema for batch execution
731
+ * @private
732
+ */
733
+ buildBatchResponseSchema(collectFields) {
734
+ const properties = {
735
+ message: {
736
+ type: "string",
737
+ description: "Your response to the user",
738
+ },
739
+ };
740
+ const agentSchema = this.agent.getSchema();
741
+ // Add collect fields to schema, using agent schema definitions when available
742
+ for (const field of collectFields) {
743
+ if (agentSchema?.properties && agentSchema.properties[field]) {
744
+ properties[field] = agentSchema.properties[field];
745
+ }
746
+ else {
747
+ // Dynamic fallback when no agent schema is defined
748
+ properties[field] = {
749
+ type: "string",
750
+ description: `Collected value for ${field}`,
751
+ };
752
+ }
753
+ }
754
+ return {
755
+ type: "object",
756
+ properties,
757
+ required: ["message"],
758
+ additionalProperties: true,
395
759
  };
396
760
  }
761
+ /**
762
+ * Collect available tools from all steps in the batch
763
+ * @private
764
+ */
765
+ collectBatchAvailableTools(route, batchSteps) {
766
+ const availableTools = new Map();
767
+ // Add agent-level tools
768
+ this.agent.getTools().forEach((tool) => {
769
+ availableTools.set(tool.id, tool);
770
+ });
771
+ // Add route-level tools
772
+ route.getTools().forEach((tool) => {
773
+ availableTools.set(tool.id, tool);
774
+ });
775
+ // Add step-level tools from all batch steps
776
+ for (const step of batchSteps) {
777
+ if (step.tools) {
778
+ for (const toolRef of step.tools) {
779
+ if (typeof toolRef === "string") {
780
+ // Reference to registered tool - already in availableTools
781
+ }
782
+ else if (typeof toolRef === 'object' && 'id' in toolRef && toolRef.id) {
783
+ // Inline tool definition
784
+ availableTools.set(toolRef.id, toolRef);
785
+ }
786
+ }
787
+ }
788
+ }
789
+ // Convert to the format expected by AI providers
790
+ return Array.from(availableTools.values()).map((tool) => ({
791
+ id: tool.id,
792
+ name: tool.name || tool.id,
793
+ description: tool.description,
794
+ parameters: tool.parameters,
795
+ }));
796
+ }
397
797
  /**
398
798
  * Unified streaming response generation
399
799
  * @private
400
800
  */
401
801
  async *generateUnifiedStreamingResponse(responseContext) {
402
- const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete } = responseContext;
802
+ const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete, batchSteps, batchStoppedReason, } = responseContext;
403
803
  const session = initialSession;
404
804
  // Get last user message (needed for both route and completion handling)
405
805
  // Convert HistoryItem[] to Event[] for internal processing
406
806
  const historyEvents = (0, utils_1.historyToEvents)(history);
407
807
  const lastMessageText = (0, utils_1.getLastMessageFromHistory)(historyEvents);
408
808
  if (selectedRoute && !isRouteComplete) {
409
- // Handle normal route processing with streaming
410
- yield* this.processRouteStreamingResponse({
411
- selectedRoute,
412
- selectedStep,
413
- responseDirectives,
414
- session,
415
- history,
416
- context: effectiveContext,
417
- lastMessageText,
418
- historyEvents,
419
- });
809
+ // Check if we have batch steps to execute
810
+ if (batchSteps && batchSteps.length > 0) {
811
+ // BATCH EXECUTION: Execute multiple steps with streaming
812
+ // Note: For streaming, we still use batch execution but stream the response
813
+ utils_1.logger.debug(`[ResponseModal] Streaming batch execution for ${batchSteps.length} steps`);
814
+ yield* this.streamBatchResponse({
815
+ selectedRoute,
816
+ batchSteps,
817
+ responseDirectives,
818
+ session,
819
+ history,
820
+ context: effectiveContext,
821
+ historyEvents,
822
+ batchStoppedReason,
823
+ });
824
+ }
825
+ else {
826
+ // SINGLE STEP EXECUTION: Fall back to single-step streaming
827
+ yield* this.processRouteStreamingResponse({
828
+ selectedRoute,
829
+ selectedStep,
830
+ responseDirectives,
831
+ session,
832
+ history,
833
+ context: effectiveContext,
834
+ lastMessageText,
835
+ historyEvents,
836
+ });
837
+ }
420
838
  }
421
839
  else if (isRouteComplete && selectedRoute) {
422
840
  // Handle route completion streaming
@@ -437,6 +855,114 @@ class ResponseModal {
437
855
  });
438
856
  }
439
857
  }
858
+ /**
859
+ * Stream a batch response with multiple steps
860
+ *
861
+ * Similar to executeBatchResponse but streams the LLM response.
862
+ *
863
+ * @private
864
+ */
865
+ async *streamBatchResponse(params) {
866
+ const { selectedRoute, batchSteps, context, historyEvents, batchStoppedReason, signal } = params;
867
+ let session = params.session;
868
+ // Create hook executor function
869
+ const executeHook = async (hook, hookContext, data, step) => {
870
+ const route = selectedRoute;
871
+ const stepInstance = step?.id ? route.getStep(step.id) : undefined;
872
+ await this.executePrepareFinalize(hook, hookContext, data, route, stepInstance);
873
+ };
874
+ // PHASE 1: Execute all prepare hooks
875
+ const prepareResult = await this.batchExecutor.executePrepareHooks({
876
+ steps: batchSteps,
877
+ context,
878
+ data: session.data,
879
+ executeHook,
880
+ });
881
+ if (!prepareResult.success) {
882
+ // Yield error chunk
883
+ yield {
884
+ delta: "",
885
+ accumulated: "",
886
+ done: true,
887
+ session,
888
+ error: new ResponseGenerationError(`Prepare hook failed: ${prepareResult.error?.message}`, { phase: 'prepare_hooks' }),
889
+ };
890
+ return;
891
+ }
892
+ // PHASE 2: Build combined prompt
893
+ const batchPromptResult = await this.batchPromptBuilder.buildBatchPrompt({
894
+ steps: batchSteps,
895
+ route: selectedRoute,
896
+ history: historyEvents,
897
+ context,
898
+ session,
899
+ agentOptions: this.agent.getAgentOptions(),
900
+ });
901
+ const responseSchema = this.buildBatchResponseSchema(batchPromptResult.collectFields);
902
+ const availableTools = this.collectBatchAvailableTools(selectedRoute, batchSteps);
903
+ // PHASE 3: Stream LLM response
904
+ const agentOptions = this.agent.getAgentOptions();
905
+ const stream = agentOptions.provider.generateMessageStream({
906
+ prompt: batchPromptResult.prompt,
907
+ history: historyEvents,
908
+ context,
909
+ tools: availableTools,
910
+ signal,
911
+ parameters: responseSchema ? { jsonSchema: responseSchema, schemaName: "batch_stream_response" } : undefined,
912
+ });
913
+ // Build executed steps list
914
+ const executedSteps = batchSteps
915
+ .filter(step => step.id)
916
+ .map(step => ({
917
+ id: step.id,
918
+ routeId: selectedRoute.id,
919
+ }));
920
+ // Stream chunks
921
+ for await (const chunk of stream) {
922
+ // On final chunk, collect data and execute finalize hooks
923
+ if (chunk.done) {
924
+ // Collect data from response
925
+ if (chunk.structured) {
926
+ const collectResult = this.batchExecutor.collectBatchData({
927
+ steps: batchSteps,
928
+ llmResponse: chunk.structured,
929
+ session,
930
+ schema: this.agent.getSchema(),
931
+ });
932
+ session = collectResult.session;
933
+ if (collectResult.collectedData && Object.keys(collectResult.collectedData).length > 0) {
934
+ await this.agent.updateCollectedData(collectResult.collectedData);
935
+ }
936
+ }
937
+ // Update session to final step position
938
+ const lastStep = batchSteps[batchSteps.length - 1];
939
+ if (lastStep?.id) {
940
+ session = (0, utils_1.enterStep)(session, lastStep.id, lastStep.description);
941
+ }
942
+ // Execute finalize hooks
943
+ await this.batchExecutor.executeFinalizeHooks({
944
+ steps: batchSteps,
945
+ context,
946
+ data: session.data,
947
+ executeHook,
948
+ });
949
+ // Finalize session
950
+ await this.finalizeSession(session, context);
951
+ }
952
+ yield {
953
+ delta: chunk.delta,
954
+ accumulated: chunk.accumulated,
955
+ done: chunk.done,
956
+ session,
957
+ toolCalls: chunk.structured?.toolCalls,
958
+ isRouteComplete: false,
959
+ executedSteps: chunk.done ? executedSteps : undefined,
960
+ stoppedReason: chunk.done ? batchStoppedReason : undefined,
961
+ metadata: chunk.metadata,
962
+ structured: chunk.structured,
963
+ };
964
+ }
965
+ }
440
966
  /**
441
967
  * Execute prepare function for current step if available
442
968
  * @private
@@ -482,12 +1008,20 @@ class ResponseModal {
482
1008
  nextStep = selectedStep;
483
1009
  }
484
1010
  else {
485
- // New route or no step selected - get initial step or first valid step
1011
+ // Determine current step from session if we're already in this route
1012
+ const isInSameRoute = session.currentRoute?.id === selectedRoute.id;
1013
+ const currentStep = isInSameRoute && session.currentStep
1014
+ ? selectedRoute.getStep(session.currentStep.id)
1015
+ : undefined;
1016
+ utils_1.logger.debug(`[ResponseModal] Step determination: route match=${isInSameRoute}, currentRoute=${session.currentRoute?.id}, selectedRoute=${selectedRoute.id}, currentStep=${currentStep?.id || 'none'}`);
1017
+ // Get candidate steps based on current position in the route
486
1018
  const routingEngine = this.agent.getRoutingEngine();
487
- const candidates = routingEngine.getCandidateSteps(selectedRoute, undefined, session.data || {});
1019
+ const candidates = await routingEngine.getCandidateStepsWithConditions(selectedRoute, currentStep, // Pass current step instead of undefined to maintain progression
1020
+ (0, template_1.createTemplateContext)({ data: session.data, session, context }));
1021
+ utils_1.logger.debug(`[ResponseModal] Found ${candidates.length} candidate steps${currentStep ? ' from current step ' + currentStep.id : ' (new route entry)'}`);
488
1022
  if (candidates.length > 0) {
489
1023
  nextStep = candidates[0].step;
490
- utils_1.logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id} for new route`);
1024
+ utils_1.logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new route'}`);
491
1025
  }
492
1026
  else {
493
1027
  // Fallback to initial step even if it should be skipped
@@ -496,16 +1030,42 @@ class ResponseModal {
496
1030
  }
497
1031
  }
498
1032
  // Update session with next step
499
- session = (0, utils_1.enterStep)(session, nextStep.id, nextStep.description);
500
- utils_1.logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
1033
+ // If the next step has requires fields that are missing, stay at the previous step
1034
+ if (nextStep.requires && nextStep.requires.length > 0) {
1035
+ const sessionData = session.data || {};
1036
+ const missingRequires = nextStep.requires.filter(field => sessionData[String(field)] === undefined);
1037
+ if (missingRequires.length > 0) {
1038
+ const warning = `[Agent] Cannot advance to step "${nextStep.description || nextStep.id}": ` +
1039
+ `missing required fields [${missingRequires.join(', ')}]. Staying at current step.`;
1040
+ utils_1.logger.warn(warning);
1041
+ console.warn(warning);
1042
+ // Stay at the current step - don't enter the next one
1043
+ const currentStepId = session.currentStep?.id;
1044
+ if (currentStepId) {
1045
+ const currentStepInstance = selectedRoute.getStep(currentStepId);
1046
+ if (currentStepInstance) {
1047
+ nextStep = currentStepInstance;
1048
+ utils_1.logger.debug(`[ResponseModal] Staying at current step: ${nextStep.id} due to missing requires`);
1049
+ }
1050
+ }
1051
+ }
1052
+ else {
1053
+ session = (0, utils_1.enterStep)(session, nextStep.id, nextStep.description);
1054
+ utils_1.logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
1055
+ }
1056
+ }
1057
+ else {
1058
+ session = (0, utils_1.enterStep)(session, nextStep.id, nextStep.description);
1059
+ utils_1.logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
1060
+ }
501
1061
  // Build response schema for this route (with collect fields from step)
502
1062
  const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextStep, this.agent.getSchema());
503
1063
  // Build response prompt
504
1064
  const responsePrompt = await this.responseEngine.buildResponsePrompt({
505
1065
  route: selectedRoute,
506
1066
  currentStep: nextStep,
507
- rules: selectedRoute.getRules(),
508
- prohibitions: selectedRoute.getProhibitions(),
1067
+ rules: [...this.agent.getRules(), ...selectedRoute.getRules()],
1068
+ prohibitions: [...this.agent.getProhibitions(), ...selectedRoute.getProhibitions()],
509
1069
  directives: responseDirectives,
510
1070
  history: historyEvents, // Use Event[] for buildResponsePrompt
511
1071
  lastMessage: lastMessageText, // Use string for buildResponsePrompt
@@ -530,6 +1090,14 @@ class ResponseModal {
530
1090
  });
531
1091
  let message = result.structured?.message || result.message;
532
1092
  let toolCalls = result.structured?.toolCalls;
1093
+ // Debug: Log initial AI response
1094
+ utils_1.logger.debug(`[ResponseModal] Initial AI response:`, {
1095
+ hasMessage: !!message,
1096
+ messageLength: message?.length || 0,
1097
+ hasToolCalls: !!toolCalls,
1098
+ toolCallsCount: toolCalls?.length || 0,
1099
+ toolNames: toolCalls?.map(tc => tc.toolName) || [],
1100
+ });
533
1101
  // Execute tools with unified loop handling
534
1102
  const toolResult = await this.executeUnifiedToolLoop({
535
1103
  toolCalls,
@@ -564,11 +1132,17 @@ class ResponseModal {
564
1132
  nextStep = selectedStep;
565
1133
  }
566
1134
  else {
1135
+ // Determine current step from session if we're already in this route
1136
+ const currentStep = session.currentRoute?.id === selectedRoute.id && session.currentStep
1137
+ ? selectedRoute.getStep(session.currentStep.id)
1138
+ : undefined;
1139
+ // Get candidate steps based on current position in the route
567
1140
  const routingEngine = this.agent.getRoutingEngine();
568
- const candidates = routingEngine.getCandidateSteps(selectedRoute, undefined, session.data || {});
1141
+ const candidates = await routingEngine.getCandidateStepsWithConditions(selectedRoute, currentStep, // Pass current step instead of undefined to maintain progression
1142
+ (0, template_1.createTemplateContext)({ data: session.data, session, context }));
569
1143
  if (candidates.length > 0) {
570
1144
  nextStep = candidates[0].step;
571
- utils_1.logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id} for new route`);
1145
+ utils_1.logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new route'}`);
572
1146
  }
573
1147
  else {
574
1148
  nextStep = selectedRoute.initialStep;
@@ -576,15 +1150,40 @@ class ResponseModal {
576
1150
  }
577
1151
  }
578
1152
  // Update session with next step
579
- session = (0, utils_1.enterStep)(session, nextStep.id, nextStep.description);
580
- utils_1.logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
1153
+ // If the next step has requires fields that are missing, stay at the previous step
1154
+ if (nextStep.requires && nextStep.requires.length > 0) {
1155
+ const sessionData = session.data || {};
1156
+ const missingRequires = nextStep.requires.filter(field => sessionData[String(field)] === undefined);
1157
+ if (missingRequires.length > 0) {
1158
+ const warning = `[Agent] Cannot advance to step "${nextStep.description || nextStep.id}": ` +
1159
+ `missing required fields [${missingRequires.join(', ')}]. Staying at current step.`;
1160
+ utils_1.logger.warn(warning);
1161
+ console.warn(warning);
1162
+ const currentStepId = session.currentStep?.id;
1163
+ if (currentStepId) {
1164
+ const currentStepInstance = selectedRoute.getStep(currentStepId);
1165
+ if (currentStepInstance) {
1166
+ nextStep = currentStepInstance;
1167
+ utils_1.logger.debug(`[ResponseModal] Staying at current step: ${nextStep.id} due to missing requires`);
1168
+ }
1169
+ }
1170
+ }
1171
+ else {
1172
+ session = (0, utils_1.enterStep)(session, nextStep.id, nextStep.description);
1173
+ utils_1.logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
1174
+ }
1175
+ }
1176
+ else {
1177
+ session = (0, utils_1.enterStep)(session, nextStep.id, nextStep.description);
1178
+ utils_1.logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
1179
+ }
581
1180
  // Build response schema and prompt (same as non-streaming)
582
1181
  const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextStep, this.agent.getSchema());
583
1182
  const responsePrompt = await this.responseEngine.buildResponsePrompt({
584
1183
  route: selectedRoute,
585
1184
  currentStep: nextStep,
586
- rules: selectedRoute.getRules(),
587
- prohibitions: selectedRoute.getProhibitions(),
1185
+ rules: [...this.agent.getRules(), ...selectedRoute.getRules()],
1186
+ prohibitions: [...this.agent.getProhibitions(), ...selectedRoute.getProhibitions()],
588
1187
  directives: responseDirectives,
589
1188
  history: historyEvents, // Use Event[] for buildResponsePrompt
590
1189
  lastMessage: lastMessageText, // Use string for buildResponsePrompt
@@ -641,6 +1240,10 @@ class ResponseModal {
641
1240
  if (chunk.done) {
642
1241
  await this.finalizeSession(session, context);
643
1242
  }
1243
+ // Response structure completeness (Requirement 8.1, 8.2, 8.3)
1244
+ // - executedSteps: single step executed in this response
1245
+ // - stoppedReason: 'needs_input' for single-step execution (waiting for user input)
1246
+ // - session.currentStep: reflects the executed step
644
1247
  yield {
645
1248
  delta: chunk.delta,
646
1249
  accumulated: chunk.accumulated,
@@ -648,6 +1251,8 @@ class ResponseModal {
648
1251
  session,
649
1252
  toolCalls,
650
1253
  isRouteComplete: false,
1254
+ executedSteps: chunk.done ? [{ id: nextStep.id, routeId: selectedRoute.id }] : undefined,
1255
+ stoppedReason: chunk.done ? 'needs_input' : undefined,
651
1256
  metadata: chunk.metadata,
652
1257
  structured: chunk.structured,
653
1258
  };
@@ -666,7 +1271,7 @@ class ResponseModal {
666
1271
  const historyEvents = (0, utils_1.historyToEvents)(history);
667
1272
  // Execute initial dynamic tool calls
668
1273
  if (toolCalls && toolCalls.length > 0) {
669
- utils_1.logger.debug(`[ResponseModal] Executing ${toolCalls.length} dynamic tool calls`);
1274
+ utils_1.logger.debug(`[ResponseModal] Executing ${toolCalls.length} dynamic tool calls:`, toolCalls.map(tc => tc.toolName));
670
1275
  for (const toolCall of toolCalls) {
671
1276
  const tool = this.findAvailableTool(toolCall.toolName, selectedRoute);
672
1277
  if (!tool) {
@@ -736,7 +1341,7 @@ class ResponseModal {
736
1341
  let finalMessage;
737
1342
  while (hasToolCalls && toolLoopCount < MAX_TOOL_LOOPS) {
738
1343
  toolLoopCount++;
739
- utils_1.logger.debug(`[ResponseModal] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS}`);
1344
+ utils_1.logger.debug(`[ResponseModal] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS} with ${toolCalls?.length || 0} tool calls`);
740
1345
  // Create tool result events with proper Event format structure
741
1346
  const toolResultEvents = [];
742
1347
  for (const toolCall of toolCalls || []) {
@@ -765,12 +1370,19 @@ class ResponseModal {
765
1370
  // Create updated history with tool results (combine Event arrays)
766
1371
  const updatedHistoryEvents = [...historyEvents, ...toolResultEvents];
767
1372
  // Make follow-up AI call to see if more tools are needed
1373
+ // After first iteration, don't provide tools to force a text response
768
1374
  const agentOptions = this.agent.getAgentOptions();
1375
+ const shouldProvideTools = toolLoopCount === 1;
1376
+ utils_1.logger.debug(`[ResponseModal] Making follow-up AI call (loop ${toolLoopCount}):`, {
1377
+ providingTools: shouldProvideTools,
1378
+ toolsCount: shouldProvideTools ? availableTools.length : 0,
1379
+ addingTextInstruction: toolLoopCount > 1,
1380
+ });
769
1381
  const followUpResult = await agentOptions.provider.generateMessage({
770
- prompt: responsePrompt,
1382
+ prompt: responsePrompt + (toolLoopCount > 1 ? "\n\nProvide a text response to the user based on the tool results." : ""),
771
1383
  history: updatedHistoryEvents, // Use Event[] for AI provider
772
1384
  context,
773
- tools: availableTools,
1385
+ tools: shouldProvideTools ? availableTools : [], // Only provide tools on first iteration
774
1386
  parameters: responseSchema ? {
775
1387
  jsonSchema: responseSchema,
776
1388
  schemaName: "tool_followup",
@@ -780,6 +1392,13 @@ class ResponseModal {
780
1392
  // Check if follow-up call has more tool calls
781
1393
  const followUpToolCalls = followUpResult.structured?.toolCalls;
782
1394
  hasToolCalls = followUpToolCalls && followUpToolCalls.length > 0;
1395
+ utils_1.logger.debug(`[ResponseModal] Follow-up AI response (loop ${toolLoopCount}):`, {
1396
+ hasMessage: !!followUpResult.message,
1397
+ messageLength: followUpResult.message?.length || 0,
1398
+ hasToolCalls,
1399
+ toolCallsCount: followUpToolCalls?.length || 0,
1400
+ toolNames: followUpToolCalls?.map(tc => tc.toolName) || [],
1401
+ });
783
1402
  if (hasToolCalls) {
784
1403
  utils_1.logger.debug(`[ResponseModal] Follow-up call produced ${followUpToolCalls.length} additional tool calls`);
785
1404
  // Execute the follow-up tool calls
@@ -853,6 +1472,12 @@ class ResponseModal {
853
1472
  if (toolLoopCount >= MAX_TOOL_LOOPS) {
854
1473
  utils_1.logger.warn(`[ResponseModal] Tool loop limit reached (${MAX_TOOL_LOOPS}), stopping`);
855
1474
  }
1475
+ utils_1.logger.debug(`[ResponseModal] Tool loop completed:`, {
1476
+ totalIterations: toolLoopCount,
1477
+ hasFinalMessage: !!finalMessage,
1478
+ finalMessageLength: finalMessage?.length || 0,
1479
+ finalToolCallsCount: toolCalls?.length || 0,
1480
+ });
856
1481
  return {
857
1482
  session,
858
1483
  finalToolCalls: toolCalls,
@@ -874,14 +1499,29 @@ class ResponseModal {
874
1499
  const { result, selectedRoute, nextStep, session } = params;
875
1500
  let updatedSession = session;
876
1501
  // Extract collected data from final response (only for route-based interactions)
877
- if (selectedRoute && result.structured && nextStep?.collect) {
1502
+ if (selectedRoute && result.structured) {
878
1503
  try {
879
1504
  const collectedData = {};
880
1505
  // AgentStructuredResponse extends Record<string, unknown>, so we can safely access properties
881
1506
  const structuredData = result.structured;
882
- for (const field of nextStep.collect) {
1507
+ // Collect ALL route fields (required + optional) from structured response
1508
+ const allRouteFields = new Set();
1509
+ // Add route required fields
1510
+ if (selectedRoute.requiredFields) {
1511
+ selectedRoute.requiredFields.forEach(field => allRouteFields.add(String(field)));
1512
+ }
1513
+ // Add route optional fields
1514
+ if (selectedRoute.optionalFields) {
1515
+ selectedRoute.optionalFields.forEach(field => allRouteFields.add(String(field)));
1516
+ }
1517
+ // Also include current step's collect fields (in case they're not in route fields)
1518
+ if (nextStep?.collect) {
1519
+ nextStep.collect.forEach(field => allRouteFields.add(String(field)));
1520
+ }
1521
+ // Extract all available fields from structured response
1522
+ for (const field of allRouteFields) {
883
1523
  const fieldKey = String(field);
884
- if (fieldKey in structuredData) {
1524
+ if (fieldKey in structuredData && structuredData[fieldKey] !== undefined && structuredData[fieldKey] !== null) {
885
1525
  collectedData[fieldKey] = structuredData[fieldKey];
886
1526
  }
887
1527
  }
@@ -944,34 +1584,60 @@ class ResponseModal {
944
1584
  requires: endStepSpec.requires,
945
1585
  prompt: endStepSpec.prompt || "Summarize what was accomplished and confirm completion based on the conversation history and collected data",
946
1586
  });
947
- // Build response schema for completion
948
- const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep, this.agent.getSchema());
949
- const templateContext = { context, session, history: historyEvents }; // Use Event[] for template context
950
- // Build completion response prompt
1587
+ // Build response schema for completion (message only, no data collection)
1588
+ const completionSchema = {
1589
+ type: "object",
1590
+ properties: {
1591
+ message: {
1592
+ type: "string",
1593
+ description: "Completion message confirming what was accomplished",
1594
+ },
1595
+ },
1596
+ required: ["message"],
1597
+ additionalProperties: false,
1598
+ };
1599
+ const templateContext = (0, template_1.createTemplateContext)({ context, session, history: historyEvents });
1600
+ // Build completion response prompt using ResponseEngine
1601
+ // Filter out conditional guidelines - only include always-active ones
1602
+ const alwaysActiveGuidelines = [
1603
+ ...this.agent.getGuidelines().filter(g => !g.condition),
1604
+ ...selectedRoute.getGuidelines().filter(g => !g.condition),
1605
+ ];
1606
+ let completitionPrompt = "Summarize what was accomplished and confirm completion";
1607
+ if (endStepSpec.prompt) {
1608
+ completitionPrompt = await (0, utils_1.render)(endStepSpec.prompt, templateContext);
1609
+ }
951
1610
  const completionPrompt = await this.responseEngine.buildResponsePrompt({
952
1611
  route: selectedRoute,
953
1612
  currentStep: completionStep,
954
1613
  rules: selectedRoute.getRules(),
955
1614
  prohibitions: selectedRoute.getProhibitions(),
956
- directives: undefined, // No directives for completion
957
- history: historyEvents, // Use Event[] for buildResponsePrompt
958
- lastMessage: lastMessageText, // Use string for buildResponsePrompt
1615
+ directives: [
1616
+ `Task completed: ${selectedRoute.title}`,
1617
+ `Collected data: ${JSON.stringify(session.data, null, 2)}`,
1618
+ "Do NOT ask for more information - the task is complete",
1619
+ completitionPrompt,
1620
+ ],
1621
+ history: historyEvents,
1622
+ lastMessage: lastMessageText,
959
1623
  agentOptions: this.agent.getAgentOptions(),
960
- combinedGuidelines: [...this.agent.getGuidelines(), ...selectedRoute.getGuidelines()],
1624
+ combinedGuidelines: alwaysActiveGuidelines, // Only non-conditional guidelines
961
1625
  combinedTerms: this.mergeTerms(this.agent.getTerms(), selectedRoute.getTerms()),
962
1626
  context,
963
1627
  session,
964
- agentSchema: this.agent.getSchema(),
1628
+ agentSchema: undefined, // No data collection schema for completion
965
1629
  });
966
1630
  // Generate completion message using AI provider
967
1631
  const agentOptions = this.agent.getAgentOptions();
1632
+ utils_1.logger.debug(`[ResponseModal] Calling AI provider for completion message...`);
968
1633
  const completionResult = await agentOptions.provider.generateMessage({
969
1634
  prompt: completionPrompt,
970
- history: historyEvents, // Use Event[] for AI provider
1635
+ history: historyEvents,
971
1636
  context,
972
1637
  signal,
973
- parameters: { jsonSchema: responseSchema, schemaName: "completion_message" },
1638
+ parameters: { jsonSchema: completionSchema, schemaName: "completion_message" },
974
1639
  });
1640
+ utils_1.logger.debug(`[ResponseModal] AI provider returned completion result`);
975
1641
  const message = completionResult.structured?.message || completionResult.message;
976
1642
  utils_1.logger.debug(`[ResponseModal] Generated completion message for route: ${selectedRoute.title}`);
977
1643
  // Check for onComplete transition
@@ -1014,7 +1680,7 @@ class ResponseModal {
1014
1680
  });
1015
1681
  // Build response schema for completion
1016
1682
  const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep, this.agent.getSchema());
1017
- const templateContext = { context, session, history: historyEvents }; // Use Event[] for template context
1683
+ const templateContext = (0, template_1.createTemplateContext)({ context, session, history: historyEvents }); // Use Event[] for template context
1018
1684
  // Build completion response prompt
1019
1685
  const completionPrompt = await this.responseEngine.buildResponsePrompt({
1020
1686
  route: selectedRoute,
@@ -1072,6 +1738,10 @@ class ResponseModal {
1072
1738
  if (chunk.done) {
1073
1739
  await this.finalizeSession(session, context);
1074
1740
  }
1741
+ // Response structure completeness (Requirement 8.1, 8.2, 8.3)
1742
+ // - executedSteps: empty for route completion (no new steps executed)
1743
+ // - stoppedReason: 'route_complete' for completed routes
1744
+ // - session.currentStep: set to END_ROUTE
1075
1745
  yield {
1076
1746
  delta: chunk.delta,
1077
1747
  accumulated: chunk.accumulated,
@@ -1079,6 +1749,8 @@ class ResponseModal {
1079
1749
  session,
1080
1750
  toolCalls: undefined,
1081
1751
  isRouteComplete: true,
1752
+ executedSteps: chunk.done ? [] : undefined,
1753
+ stoppedReason: chunk.done ? 'route_complete' : undefined,
1082
1754
  metadata: chunk.metadata,
1083
1755
  structured: chunk.structured,
1084
1756
  };
@@ -1153,6 +1825,10 @@ class ResponseModal {
1153
1825
  if (chunk.done) {
1154
1826
  await this.finalizeSession(session, context);
1155
1827
  }
1828
+ // Response structure completeness (Requirement 8.1, 8.2, 8.3)
1829
+ // - executedSteps: empty for fallback (no route/step execution)
1830
+ // - stoppedReason: undefined for fallback (no route context)
1831
+ // - session.currentStep: unchanged (no step progression)
1156
1832
  yield {
1157
1833
  delta: chunk.delta,
1158
1834
  accumulated: chunk.accumulated,
@@ -1160,6 +1836,8 @@ class ResponseModal {
1160
1836
  session,
1161
1837
  toolCalls: undefined,
1162
1838
  isRouteComplete: false,
1839
+ executedSteps: chunk.done ? [] : undefined,
1840
+ stoppedReason: undefined,
1163
1841
  metadata: chunk.metadata,
1164
1842
  structured: chunk.structured,
1165
1843
  };