@falai/agent 1.2.7 → 2.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 (508) hide show
  1. package/README.md +40 -886
  2. package/dist/adapters/MemoryAdapter.js +2 -2
  3. package/dist/adapters/MemoryAdapter.js.map +1 -1
  4. package/dist/adapters/MongoAdapter.js +2 -2
  5. package/dist/adapters/MongoAdapter.js.map +1 -1
  6. package/dist/adapters/OpenSearchAdapter.d.ts.map +1 -1
  7. package/dist/adapters/OpenSearchAdapter.js +9 -7
  8. package/dist/adapters/OpenSearchAdapter.js.map +1 -1
  9. package/dist/adapters/PostgreSQLAdapter.d.ts +14 -0
  10. package/dist/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  11. package/dist/adapters/PostgreSQLAdapter.js +25 -9
  12. package/dist/adapters/PostgreSQLAdapter.js.map +1 -1
  13. package/dist/adapters/PrismaAdapter.js +5 -5
  14. package/dist/adapters/PrismaAdapter.js.map +1 -1
  15. package/dist/adapters/RedisAdapter.js +2 -2
  16. package/dist/adapters/RedisAdapter.js.map +1 -1
  17. package/dist/adapters/SQLiteAdapter.d.ts +17 -0
  18. package/dist/adapters/SQLiteAdapter.d.ts.map +1 -1
  19. package/dist/adapters/SQLiteAdapter.js +30 -11
  20. package/dist/adapters/SQLiteAdapter.js.map +1 -1
  21. package/dist/cjs/adapters/MemoryAdapter.js +2 -2
  22. package/dist/cjs/adapters/MemoryAdapter.js.map +1 -1
  23. package/dist/cjs/adapters/MongoAdapter.js +2 -2
  24. package/dist/cjs/adapters/MongoAdapter.js.map +1 -1
  25. package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +1 -1
  26. package/dist/cjs/adapters/OpenSearchAdapter.js +9 -7
  27. package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -1
  28. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts +14 -0
  29. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  30. package/dist/cjs/adapters/PostgreSQLAdapter.js +25 -9
  31. package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -1
  32. package/dist/cjs/adapters/PrismaAdapter.js +5 -5
  33. package/dist/cjs/adapters/PrismaAdapter.js.map +1 -1
  34. package/dist/cjs/adapters/RedisAdapter.js +2 -2
  35. package/dist/cjs/adapters/RedisAdapter.js.map +1 -1
  36. package/dist/cjs/adapters/SQLiteAdapter.d.ts +17 -0
  37. package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +1 -1
  38. package/dist/cjs/adapters/SQLiteAdapter.js +30 -11
  39. package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -1
  40. package/dist/cjs/constants/index.d.ts +0 -9
  41. package/dist/cjs/constants/index.d.ts.map +1 -1
  42. package/dist/cjs/constants/index.js +2 -11
  43. package/dist/cjs/constants/index.js.map +1 -1
  44. package/dist/cjs/core/Agent.d.ts +119 -153
  45. package/dist/cjs/core/Agent.d.ts.map +1 -1
  46. package/dist/cjs/core/Agent.js +471 -324
  47. package/dist/cjs/core/Agent.js.map +1 -1
  48. package/dist/cjs/core/AutoChainExecutor.d.ts +107 -0
  49. package/dist/cjs/core/AutoChainExecutor.d.ts.map +1 -0
  50. package/dist/cjs/core/AutoChainExecutor.js +297 -0
  51. package/dist/cjs/core/AutoChainExecutor.js.map +1 -0
  52. package/dist/cjs/core/BranchEvaluator.d.ts +54 -0
  53. package/dist/cjs/core/BranchEvaluator.d.ts.map +1 -0
  54. package/dist/cjs/core/BranchEvaluator.js +130 -0
  55. package/dist/cjs/core/BranchEvaluator.js.map +1 -0
  56. package/dist/cjs/core/DirectiveBus.d.ts +88 -0
  57. package/dist/cjs/core/DirectiveBus.d.ts.map +1 -0
  58. package/dist/cjs/core/DirectiveBus.js +196 -0
  59. package/dist/cjs/core/DirectiveBus.js.map +1 -0
  60. package/dist/cjs/core/DirectiveChainTracker.d.ts +49 -0
  61. package/dist/cjs/core/DirectiveChainTracker.d.ts.map +1 -0
  62. package/dist/cjs/core/DirectiveChainTracker.js +121 -0
  63. package/dist/cjs/core/DirectiveChainTracker.js.map +1 -0
  64. package/dist/cjs/core/Flow.d.ts +186 -0
  65. package/dist/cjs/core/Flow.d.ts.map +1 -0
  66. package/dist/cjs/core/Flow.js +550 -0
  67. package/dist/cjs/core/Flow.js.map +1 -0
  68. package/dist/cjs/core/FlowRouter.d.ts +182 -0
  69. package/dist/cjs/core/FlowRouter.d.ts.map +1 -0
  70. package/dist/cjs/core/{RoutingEngine.js → FlowRouter.js} +323 -306
  71. package/dist/cjs/core/FlowRouter.js.map +1 -0
  72. package/dist/cjs/core/PersistenceManager.d.ts +2 -2
  73. package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
  74. package/dist/cjs/core/PersistenceManager.js +7 -7
  75. package/dist/cjs/core/PersistenceManager.js.map +1 -1
  76. package/dist/cjs/core/PromptComposer.d.ts +21 -8
  77. package/dist/cjs/core/PromptComposer.d.ts.map +1 -1
  78. package/dist/cjs/core/PromptComposer.js +182 -105
  79. package/dist/cjs/core/PromptComposer.js.map +1 -1
  80. package/dist/cjs/core/PromptSectionCache.d.ts +1 -1
  81. package/dist/cjs/core/PromptSectionCache.js +1 -1
  82. package/dist/cjs/core/ResponseEngine.d.ts +18 -8
  83. package/dist/cjs/core/ResponseEngine.d.ts.map +1 -1
  84. package/dist/cjs/core/ResponseEngine.js +38 -36
  85. package/dist/cjs/core/ResponseEngine.js.map +1 -1
  86. package/dist/cjs/core/ResponseModal.d.ts +73 -56
  87. package/dist/cjs/core/ResponseModal.d.ts.map +1 -1
  88. package/dist/cjs/core/ResponseModal.js +1196 -1015
  89. package/dist/cjs/core/ResponseModal.js.map +1 -1
  90. package/dist/cjs/core/ResponsePipeline.d.ts +124 -26
  91. package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -1
  92. package/dist/cjs/core/ResponsePipeline.js +524 -134
  93. package/dist/cjs/core/ResponsePipeline.js.map +1 -1
  94. package/dist/cjs/core/SignalEvaluator.d.ts +86 -0
  95. package/dist/cjs/core/SignalEvaluator.d.ts.map +1 -0
  96. package/dist/cjs/core/SignalEvaluator.js +333 -0
  97. package/dist/cjs/core/SignalEvaluator.js.map +1 -0
  98. package/dist/cjs/core/SignalProcessor.d.ts +152 -0
  99. package/dist/cjs/core/SignalProcessor.d.ts.map +1 -0
  100. package/dist/cjs/core/SignalProcessor.js +562 -0
  101. package/dist/cjs/core/SignalProcessor.js.map +1 -0
  102. package/dist/cjs/core/Step.d.ts +43 -32
  103. package/dist/cjs/core/Step.d.ts.map +1 -1
  104. package/dist/cjs/core/Step.js +221 -126
  105. package/dist/cjs/core/Step.js.map +1 -1
  106. package/dist/cjs/core/StreamingToolExecutor.d.ts +2 -2
  107. package/dist/cjs/core/StreamingToolExecutor.d.ts.map +1 -1
  108. package/dist/cjs/core/StreamingToolExecutor.js.map +1 -1
  109. package/dist/cjs/core/ToolManager.d.ts +44 -13
  110. package/dist/cjs/core/ToolManager.d.ts.map +1 -1
  111. package/dist/cjs/core/ToolManager.js +174 -91
  112. package/dist/cjs/core/ToolManager.js.map +1 -1
  113. package/dist/cjs/core/createAgent.d.ts +35 -0
  114. package/dist/cjs/core/createAgent.d.ts.map +1 -0
  115. package/dist/cjs/core/createAgent.js +39 -0
  116. package/dist/cjs/core/createAgent.js.map +1 -0
  117. package/dist/cjs/core/flow-namespace.d.ts +49 -0
  118. package/dist/cjs/core/flow-namespace.d.ts.map +1 -0
  119. package/dist/cjs/core/flow-namespace.js +171 -0
  120. package/dist/cjs/core/flow-namespace.js.map +1 -0
  121. package/dist/cjs/index.d.ts +11 -14
  122. package/dist/cjs/index.d.ts.map +1 -1
  123. package/dist/cjs/index.js +18 -22
  124. package/dist/cjs/index.js.map +1 -1
  125. package/dist/cjs/providers/GeminiProvider.d.ts +3 -3
  126. package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
  127. package/dist/cjs/providers/GeminiProvider.js +16 -14
  128. package/dist/cjs/providers/GeminiProvider.js.map +1 -1
  129. package/dist/cjs/types/agent.d.ts +183 -54
  130. package/dist/cjs/types/agent.d.ts.map +1 -1
  131. package/dist/cjs/types/agent.js +0 -6
  132. package/dist/cjs/types/agent.js.map +1 -1
  133. package/dist/cjs/types/ai.d.ts +3 -3
  134. package/dist/cjs/types/ai.d.ts.map +1 -1
  135. package/dist/cjs/types/errors.d.ts +15 -0
  136. package/dist/cjs/types/errors.d.ts.map +1 -0
  137. package/dist/cjs/types/errors.js +22 -0
  138. package/dist/cjs/types/errors.js.map +1 -0
  139. package/dist/cjs/types/flow.d.ts +513 -0
  140. package/dist/cjs/types/flow.d.ts.map +1 -0
  141. package/dist/cjs/types/{route.js → flow.js} +2 -2
  142. package/dist/cjs/types/flow.js.map +1 -0
  143. package/dist/cjs/types/index.d.ts +7 -6
  144. package/dist/cjs/types/index.d.ts.map +1 -1
  145. package/dist/cjs/types/index.js +6 -2
  146. package/dist/cjs/types/index.js.map +1 -1
  147. package/dist/cjs/types/persistence.d.ts +11 -7
  148. package/dist/cjs/types/persistence.d.ts.map +1 -1
  149. package/dist/cjs/types/routing.d.ts +1 -1
  150. package/dist/cjs/types/routing.d.ts.map +1 -1
  151. package/dist/cjs/types/session.d.ts +24 -23
  152. package/dist/cjs/types/session.d.ts.map +1 -1
  153. package/dist/cjs/types/signals.d.ts +248 -0
  154. package/dist/cjs/types/signals.d.ts.map +1 -0
  155. package/dist/cjs/types/signals.js +11 -0
  156. package/dist/cjs/types/signals.js.map +1 -0
  157. package/dist/cjs/types/template.d.ts +2 -8
  158. package/dist/cjs/types/template.d.ts.map +1 -1
  159. package/dist/cjs/types/tool.d.ts +36 -29
  160. package/dist/cjs/types/tool.d.ts.map +1 -1
  161. package/dist/cjs/types/tool.js +1 -1
  162. package/dist/cjs/types/tool.js.map +1 -1
  163. package/dist/cjs/utils/condition.d.ts +7 -1
  164. package/dist/cjs/utils/condition.d.ts.map +1 -1
  165. package/dist/cjs/utils/condition.js.map +1 -1
  166. package/dist/cjs/utils/id.d.ts +13 -5
  167. package/dist/cjs/utils/id.d.ts.map +1 -1
  168. package/dist/cjs/utils/id.js +24 -10
  169. package/dist/cjs/utils/id.js.map +1 -1
  170. package/dist/cjs/utils/index.d.ts +2 -2
  171. package/dist/cjs/utils/index.d.ts.map +1 -1
  172. package/dist/cjs/utils/index.js +7 -3
  173. package/dist/cjs/utils/index.js.map +1 -1
  174. package/dist/cjs/utils/session.d.ts +44 -5
  175. package/dist/cjs/utils/session.d.ts.map +1 -1
  176. package/dist/cjs/utils/session.js +197 -38
  177. package/dist/cjs/utils/session.js.map +1 -1
  178. package/dist/constants/index.d.ts +0 -9
  179. package/dist/constants/index.d.ts.map +1 -1
  180. package/dist/constants/index.js +3 -9
  181. package/dist/constants/index.js.map +1 -1
  182. package/dist/core/Agent.d.ts +119 -153
  183. package/dist/core/Agent.d.ts.map +1 -1
  184. package/dist/core/Agent.js +472 -325
  185. package/dist/core/Agent.js.map +1 -1
  186. package/dist/core/AutoChainExecutor.d.ts +107 -0
  187. package/dist/core/AutoChainExecutor.d.ts.map +1 -0
  188. package/dist/core/AutoChainExecutor.js +293 -0
  189. package/dist/core/AutoChainExecutor.js.map +1 -0
  190. package/dist/core/BranchEvaluator.d.ts +54 -0
  191. package/dist/core/BranchEvaluator.d.ts.map +1 -0
  192. package/dist/core/BranchEvaluator.js +126 -0
  193. package/dist/core/BranchEvaluator.js.map +1 -0
  194. package/dist/core/DirectiveBus.d.ts +88 -0
  195. package/dist/core/DirectiveBus.d.ts.map +1 -0
  196. package/dist/core/DirectiveBus.js +192 -0
  197. package/dist/core/DirectiveBus.js.map +1 -0
  198. package/dist/core/DirectiveChainTracker.d.ts +49 -0
  199. package/dist/core/DirectiveChainTracker.d.ts.map +1 -0
  200. package/dist/core/DirectiveChainTracker.js +117 -0
  201. package/dist/core/DirectiveChainTracker.js.map +1 -0
  202. package/dist/core/Flow.d.ts +186 -0
  203. package/dist/core/Flow.d.ts.map +1 -0
  204. package/dist/core/Flow.js +546 -0
  205. package/dist/core/Flow.js.map +1 -0
  206. package/dist/core/FlowRouter.d.ts +182 -0
  207. package/dist/core/FlowRouter.d.ts.map +1 -0
  208. package/dist/core/{RoutingEngine.js → FlowRouter.js} +322 -305
  209. package/dist/core/FlowRouter.js.map +1 -0
  210. package/dist/core/PersistenceManager.d.ts +2 -2
  211. package/dist/core/PersistenceManager.d.ts.map +1 -1
  212. package/dist/core/PersistenceManager.js +7 -7
  213. package/dist/core/PersistenceManager.js.map +1 -1
  214. package/dist/core/PromptComposer.d.ts +21 -8
  215. package/dist/core/PromptComposer.d.ts.map +1 -1
  216. package/dist/core/PromptComposer.js +183 -106
  217. package/dist/core/PromptComposer.js.map +1 -1
  218. package/dist/core/PromptSectionCache.d.ts +1 -1
  219. package/dist/core/PromptSectionCache.js +1 -1
  220. package/dist/core/ResponseEngine.d.ts +18 -8
  221. package/dist/core/ResponseEngine.d.ts.map +1 -1
  222. package/dist/core/ResponseEngine.js +38 -36
  223. package/dist/core/ResponseEngine.js.map +1 -1
  224. package/dist/core/ResponseModal.d.ts +73 -56
  225. package/dist/core/ResponseModal.d.ts.map +1 -1
  226. package/dist/core/ResponseModal.js +1198 -1017
  227. package/dist/core/ResponseModal.js.map +1 -1
  228. package/dist/core/ResponsePipeline.d.ts +124 -26
  229. package/dist/core/ResponsePipeline.d.ts.map +1 -1
  230. package/dist/core/ResponsePipeline.js +524 -135
  231. package/dist/core/ResponsePipeline.js.map +1 -1
  232. package/dist/core/SignalEvaluator.d.ts +86 -0
  233. package/dist/core/SignalEvaluator.d.ts.map +1 -0
  234. package/dist/core/SignalEvaluator.js +326 -0
  235. package/dist/core/SignalEvaluator.js.map +1 -0
  236. package/dist/core/SignalProcessor.d.ts +152 -0
  237. package/dist/core/SignalProcessor.d.ts.map +1 -0
  238. package/dist/core/SignalProcessor.js +555 -0
  239. package/dist/core/SignalProcessor.js.map +1 -0
  240. package/dist/core/Step.d.ts +43 -32
  241. package/dist/core/Step.d.ts.map +1 -1
  242. package/dist/core/Step.js +220 -126
  243. package/dist/core/Step.js.map +1 -1
  244. package/dist/core/StreamingToolExecutor.d.ts +2 -2
  245. package/dist/core/StreamingToolExecutor.d.ts.map +1 -1
  246. package/dist/core/StreamingToolExecutor.js.map +1 -1
  247. package/dist/core/ToolManager.d.ts +44 -13
  248. package/dist/core/ToolManager.d.ts.map +1 -1
  249. package/dist/core/ToolManager.js +174 -91
  250. package/dist/core/ToolManager.js.map +1 -1
  251. package/dist/core/createAgent.d.ts +35 -0
  252. package/dist/core/createAgent.d.ts.map +1 -0
  253. package/dist/core/createAgent.js +36 -0
  254. package/dist/core/createAgent.js.map +1 -0
  255. package/dist/core/flow-namespace.d.ts +49 -0
  256. package/dist/core/flow-namespace.d.ts.map +1 -0
  257. package/dist/core/flow-namespace.js +168 -0
  258. package/dist/core/flow-namespace.js.map +1 -0
  259. package/dist/index.d.ts +11 -14
  260. package/dist/index.d.ts.map +1 -1
  261. package/dist/index.js +9 -12
  262. package/dist/index.js.map +1 -1
  263. package/dist/providers/GeminiProvider.d.ts +3 -3
  264. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  265. package/dist/providers/GeminiProvider.js +16 -14
  266. package/dist/providers/GeminiProvider.js.map +1 -1
  267. package/dist/types/agent.d.ts +183 -54
  268. package/dist/types/agent.d.ts.map +1 -1
  269. package/dist/types/agent.js +0 -6
  270. package/dist/types/agent.js.map +1 -1
  271. package/dist/types/ai.d.ts +3 -3
  272. package/dist/types/ai.d.ts.map +1 -1
  273. package/dist/types/errors.d.ts +15 -0
  274. package/dist/types/errors.d.ts.map +1 -0
  275. package/dist/types/errors.js +18 -0
  276. package/dist/types/errors.js.map +1 -0
  277. package/dist/types/flow.d.ts +513 -0
  278. package/dist/types/flow.d.ts.map +1 -0
  279. package/dist/types/flow.js +5 -0
  280. package/dist/types/flow.js.map +1 -0
  281. package/dist/types/index.d.ts +7 -6
  282. package/dist/types/index.d.ts.map +1 -1
  283. package/dist/types/index.js +4 -1
  284. package/dist/types/index.js.map +1 -1
  285. package/dist/types/persistence.d.ts +11 -7
  286. package/dist/types/persistence.d.ts.map +1 -1
  287. package/dist/types/routing.d.ts +1 -1
  288. package/dist/types/routing.d.ts.map +1 -1
  289. package/dist/types/session.d.ts +24 -23
  290. package/dist/types/session.d.ts.map +1 -1
  291. package/dist/types/signals.d.ts +248 -0
  292. package/dist/types/signals.d.ts.map +1 -0
  293. package/dist/types/signals.js +10 -0
  294. package/dist/types/signals.js.map +1 -0
  295. package/dist/types/template.d.ts +2 -8
  296. package/dist/types/template.d.ts.map +1 -1
  297. package/dist/types/tool.d.ts +36 -29
  298. package/dist/types/tool.d.ts.map +1 -1
  299. package/dist/types/tool.js +1 -1
  300. package/dist/types/tool.js.map +1 -1
  301. package/dist/utils/condition.d.ts +7 -1
  302. package/dist/utils/condition.d.ts.map +1 -1
  303. package/dist/utils/condition.js.map +1 -1
  304. package/dist/utils/id.d.ts +13 -5
  305. package/dist/utils/id.d.ts.map +1 -1
  306. package/dist/utils/id.js +22 -9
  307. package/dist/utils/id.js.map +1 -1
  308. package/dist/utils/index.d.ts +2 -2
  309. package/dist/utils/index.d.ts.map +1 -1
  310. package/dist/utils/index.js +2 -2
  311. package/dist/utils/index.js.map +1 -1
  312. package/dist/utils/session.d.ts +44 -5
  313. package/dist/utils/session.d.ts.map +1 -1
  314. package/dist/utils/session.js +193 -37
  315. package/dist/utils/session.js.map +1 -1
  316. package/docs/README.md +15 -202
  317. package/docs/concepts/architecture.md +281 -0
  318. package/docs/concepts/directives.md +400 -0
  319. package/docs/concepts/pipeline.md +399 -0
  320. package/docs/guides/branching.md +263 -0
  321. package/docs/guides/compaction.md +163 -0
  322. package/docs/guides/conditions.md +167 -0
  323. package/docs/guides/error-handling.md +176 -0
  324. package/docs/guides/flow-control.md +409 -0
  325. package/docs/guides/instructions.md +210 -0
  326. package/docs/guides/persistence.md +182 -0
  327. package/docs/guides/streaming.md +137 -0
  328. package/docs/migration/README.md +15 -0
  329. package/docs/migration/route-to-flow.md +560 -0
  330. package/docs/migration/v1-to-v2.md +909 -0
  331. package/docs/reference/adapters.md +481 -0
  332. package/docs/reference/branches.md +241 -0
  333. package/docs/reference/create-agent.md +186 -0
  334. package/docs/reference/directive.md +243 -0
  335. package/docs/reference/errors.md +122 -0
  336. package/docs/reference/flow.md +238 -0
  337. package/docs/reference/instruction.md +177 -0
  338. package/docs/reference/pre-directive.md +131 -0
  339. package/docs/reference/providers.md +227 -0
  340. package/docs/reference/signals.md +356 -0
  341. package/docs/reference/step.md +339 -0
  342. package/docs/reference/tool.md +269 -0
  343. package/docs/start/01-install.md +81 -0
  344. package/docs/start/02-first-agent.md +196 -0
  345. package/docs/start/03-collect-data.md +222 -0
  346. package/docs/start/04-add-tools.md +276 -0
  347. package/docs/start/05-go-to-production.md +216 -0
  348. package/examples/01-quickstart.ts +20 -0
  349. package/examples/02-data-extraction.ts +90 -0
  350. package/examples/03-tools.ts +136 -0
  351. package/examples/04-instructions.ts +100 -0
  352. package/examples/05-branching.ts +140 -0
  353. package/examples/06-flow-control.ts +103 -0
  354. package/examples/07-streaming.ts +69 -0
  355. package/examples/08-persistence.ts +98 -0
  356. package/examples/09-signals.ts +144 -0
  357. package/examples/tsconfig.json +30 -0
  358. package/package.json +2 -1
  359. package/src/adapters/MemoryAdapter.ts +3 -3
  360. package/src/adapters/MongoAdapter.ts +3 -3
  361. package/src/adapters/OpenSearchAdapter.ts +10 -8
  362. package/src/adapters/PostgreSQLAdapter.ts +26 -10
  363. package/src/adapters/PrismaAdapter.ts +6 -6
  364. package/src/adapters/RedisAdapter.ts +3 -3
  365. package/src/adapters/SQLiteAdapter.ts +31 -12
  366. package/src/constants/index.ts +2 -10
  367. package/src/core/Agent.ts +585 -374
  368. package/src/core/AutoChainExecutor.ts +440 -0
  369. package/src/core/BranchEvaluator.ts +167 -0
  370. package/src/core/DirectiveBus.ts +248 -0
  371. package/src/core/DirectiveChainTracker.ts +144 -0
  372. package/src/core/Flow.ts +666 -0
  373. package/src/core/{RoutingEngine.ts → FlowRouter.ts} +385 -365
  374. package/src/core/PersistenceManager.ts +8 -8
  375. package/src/core/PromptComposer.ts +209 -140
  376. package/src/core/PromptSectionCache.ts +1 -1
  377. package/src/core/ResponseEngine.ts +61 -46
  378. package/src/core/ResponseModal.ts +1458 -1241
  379. package/src/core/ResponsePipeline.ts +675 -173
  380. package/src/core/SignalEvaluator.ts +420 -0
  381. package/src/core/SignalProcessor.ts +723 -0
  382. package/src/core/Step.ts +279 -176
  383. package/src/core/StreamingToolExecutor.ts +4 -4
  384. package/src/core/ToolManager.ts +200 -97
  385. package/src/core/createAgent.ts +40 -0
  386. package/src/core/flow-namespace.ts +219 -0
  387. package/src/index.ts +42 -36
  388. package/src/providers/GeminiProvider.ts +17 -15
  389. package/src/types/agent.ts +182 -53
  390. package/src/types/ai.ts +3 -3
  391. package/src/types/errors.ts +18 -0
  392. package/src/types/flow.ts +590 -0
  393. package/src/types/index.ts +43 -16
  394. package/src/types/persistence.ts +12 -8
  395. package/src/types/routing.ts +1 -1
  396. package/src/types/session.ts +26 -23
  397. package/src/types/signals.ts +321 -0
  398. package/src/types/template.ts +3 -11
  399. package/src/types/tool.ts +50 -42
  400. package/src/utils/condition.ts +13 -4
  401. package/src/utils/id.ts +27 -9
  402. package/src/utils/index.ts +6 -2
  403. package/src/utils/session.ts +238 -42
  404. package/dist/cjs/core/BatchExecutor.d.ts +0 -359
  405. package/dist/cjs/core/BatchExecutor.d.ts.map +0 -1
  406. package/dist/cjs/core/BatchExecutor.js +0 -861
  407. package/dist/cjs/core/BatchExecutor.js.map +0 -1
  408. package/dist/cjs/core/BatchPromptBuilder.d.ts +0 -89
  409. package/dist/cjs/core/BatchPromptBuilder.d.ts.map +0 -1
  410. package/dist/cjs/core/BatchPromptBuilder.js +0 -223
  411. package/dist/cjs/core/BatchPromptBuilder.js.map +0 -1
  412. package/dist/cjs/core/Route.d.ts +0 -180
  413. package/dist/cjs/core/Route.d.ts.map +0 -1
  414. package/dist/cjs/core/Route.js +0 -542
  415. package/dist/cjs/core/Route.js.map +0 -1
  416. package/dist/cjs/core/RoutingEngine.d.ts +0 -185
  417. package/dist/cjs/core/RoutingEngine.d.ts.map +0 -1
  418. package/dist/cjs/core/RoutingEngine.js.map +0 -1
  419. package/dist/cjs/types/route.d.ts +0 -336
  420. package/dist/cjs/types/route.d.ts.map +0 -1
  421. package/dist/cjs/types/route.js.map +0 -1
  422. package/dist/core/BatchExecutor.d.ts +0 -359
  423. package/dist/core/BatchExecutor.d.ts.map +0 -1
  424. package/dist/core/BatchExecutor.js +0 -856
  425. package/dist/core/BatchExecutor.js.map +0 -1
  426. package/dist/core/BatchPromptBuilder.d.ts +0 -89
  427. package/dist/core/BatchPromptBuilder.d.ts.map +0 -1
  428. package/dist/core/BatchPromptBuilder.js +0 -219
  429. package/dist/core/BatchPromptBuilder.js.map +0 -1
  430. package/dist/core/Route.d.ts +0 -180
  431. package/dist/core/Route.d.ts.map +0 -1
  432. package/dist/core/Route.js +0 -538
  433. package/dist/core/Route.js.map +0 -1
  434. package/dist/core/RoutingEngine.d.ts +0 -185
  435. package/dist/core/RoutingEngine.d.ts.map +0 -1
  436. package/dist/core/RoutingEngine.js.map +0 -1
  437. package/dist/types/route.d.ts +0 -336
  438. package/dist/types/route.d.ts.map +0 -1
  439. package/dist/types/route.js +0 -5
  440. package/dist/types/route.js.map +0 -1
  441. package/docs/CONTRIBUTING.md +0 -521
  442. package/docs/api/README.md +0 -3299
  443. package/docs/api/overview.md +0 -1410
  444. package/docs/architecture/data-extraction-flow.md +0 -360
  445. package/docs/architecture/multi-step-execution.md +0 -277
  446. package/docs/core/agent/README.md +0 -938
  447. package/docs/core/agent/context-management.md +0 -796
  448. package/docs/core/agent/rules-and-prohibitions.md +0 -113
  449. package/docs/core/agent/session-management.md +0 -693
  450. package/docs/core/ai-integration/prompt-composition.md +0 -355
  451. package/docs/core/ai-integration/providers.md +0 -515
  452. package/docs/core/ai-integration/response-processing.md +0 -433
  453. package/docs/core/conversation-flows/data-collection.md +0 -772
  454. package/docs/core/conversation-flows/route-dsl.md +0 -509
  455. package/docs/core/conversation-flows/routes.md +0 -249
  456. package/docs/core/conversation-flows/step-transitions.md +0 -731
  457. package/docs/core/conversation-flows/steps.md +0 -268
  458. package/docs/core/error-handling.md +0 -830
  459. package/docs/core/persistence/adapters.md +0 -255
  460. package/docs/core/persistence/session-storage.md +0 -656
  461. package/docs/core/routing/intelligent-routing.md +0 -470
  462. package/docs/core/tools/enhanced-tool.md +0 -186
  463. package/docs/core/tools/streaming-execution.md +0 -161
  464. package/docs/core/tools/tool-definition.md +0 -970
  465. package/docs/core/tools/tool-scoping.md +0 -819
  466. package/docs/guides/advanced-patterns/publishing.md +0 -186
  467. package/docs/guides/context-compaction.md +0 -96
  468. package/docs/guides/error-handling-patterns.md +0 -578
  469. package/docs/guides/getting-started/README.md +0 -795
  470. package/docs/guides/migration/README.md +0 -101
  471. package/docs/guides/migration/flexible-routing-conditions.md +0 -375
  472. package/docs/guides/migration/multi-step-execution.md +0 -393
  473. package/docs/guides/migration/response-modal-refactor.md +0 -518
  474. package/docs/guides/prompt-optimization.md +0 -164
  475. package/examples/advanced-patterns/context-compaction.ts +0 -223
  476. package/examples/advanced-patterns/knowledge-based-agent.ts +0 -735
  477. package/examples/advanced-patterns/persistent-onboarding.ts +0 -728
  478. package/examples/advanced-patterns/route-lifecycle-hooks.ts +0 -556
  479. package/examples/advanced-patterns/streaming-responses.ts +0 -656
  480. package/examples/ai-providers/anthropic-integration.ts +0 -388
  481. package/examples/ai-providers/openai-integration.ts +0 -228
  482. package/examples/condition-patterns/function-only-conditions.ts +0 -365
  483. package/examples/condition-patterns/mixed-array-conditions.ts +0 -477
  484. package/examples/condition-patterns/route-skipif-patterns.ts +0 -468
  485. package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
  486. package/examples/condition-patterns/string-only-conditions.ts +0 -296
  487. package/examples/conversation-flows/completion-transitions.ts +0 -318
  488. package/examples/core-concepts/basic-agent.ts +0 -503
  489. package/examples/core-concepts/modern-streaming-api.ts +0 -309
  490. package/examples/core-concepts/schema-driven-extraction.ts +0 -332
  491. package/examples/core-concepts/session-management.ts +0 -494
  492. package/examples/integrations/database-integration.ts +0 -631
  493. package/examples/integrations/healthcare-integration.ts +0 -595
  494. package/examples/integrations/search-integration.ts +0 -530
  495. package/examples/integrations/server-session-management.ts +0 -307
  496. package/examples/persistence/custom-adapter.ts +0 -526
  497. package/examples/persistence/database-persistence.ts +0 -583
  498. package/examples/persistence/memory-sessions.ts +0 -495
  499. package/examples/persistence/prisma-schema.example.prisma +0 -74
  500. package/examples/persistence/redis-persistence.ts +0 -488
  501. package/examples/tools/basic-tools.ts +0 -765
  502. package/examples/tools/data-enrichment-tools.ts +0 -593
  503. package/examples/tools/enhanced-tool-metadata.ts +0 -268
  504. package/examples/tools/streaming-tool-execution.ts +0 -283
  505. package/src/core/BatchExecutor.ts +0 -1187
  506. package/src/core/BatchPromptBuilder.ts +0 -299
  507. package/src/core/Route.ts +0 -678
  508. package/src/types/route.ts +0 -392
@@ -1,22 +1,120 @@
1
1
  /**
2
2
  * Response processing utilities shared between respond() and respondStream() methods
3
3
  */
4
- import { createSession, enterRoute, enterStep, mergeCollected, logger, render, historyToEvents, serializeToolResult, } from "../utils";
4
+ import { createSession, enterStep, mergeCollected, completeCurrentFlow, logger, historyToEvents, serializeToolResult, } from "../utils";
5
+ import { enterFlow } from "../utils/session";
5
6
  import { createTemplateContext } from "../utils/template";
6
- import { END_ROUTE_ID } from "../constants";
7
+ import { FlowConfigurationError } from "../core/Step";
8
+ import { evaluateBranches, createAiConditionEvaluator } from "./BranchEvaluator";
9
+ import { DirectiveChainTracker } from "./DirectiveChainTracker";
10
+ import { DirectiveBus } from "./DirectiveBus";
11
+ /**
12
+ * Position fields on a Directive that represent a navigation decision.
13
+ * When any of these is set, the directive "wins" the turn's position decision
14
+ * and downstream resolution (branches, linear, AI) must not run.
15
+ */
16
+ const DIRECTIVE_POSITION_FIELDS = ['goTo', 'goToStep', 'complete', 'abort', 'reset'];
17
+ /**
18
+ * Returns `true` if the given directive has at least one position field set.
19
+ * Used as the guard at the directive-bus / branch-evaluation seam:
20
+ * if the bus produced a winner with a position field, `evaluateStepBranches`
21
+ * (and linear/AI selection) must not run.
22
+ */
23
+ export function hasDirectivePositionField(directive) {
24
+ if (!directive)
25
+ return false;
26
+ return DIRECTIVE_POSITION_FIELDS.some((field) => directive[field] !== undefined);
27
+ }
7
28
  /**
8
29
  * Shared response processing logic between respond() and respondStream() methods
9
30
  */
10
31
  export class ResponsePipeline {
11
- constructor(options, getRoutes, tools, routingEngine, updateContext, updateData, updateCollectedData, toolManager) {
32
+ constructor(options, getFlows, tools, flowRouter, updateContext, updateData, updateCollectedData, toolManager, signalProcessor) {
12
33
  this.options = options;
13
- this.getRoutes = getRoutes;
34
+ this.getFlows = getFlows;
14
35
  this.tools = tools;
15
- this.routingEngine = routingEngine;
36
+ this.flowRouter = flowRouter;
16
37
  this.updateContext = updateContext;
17
38
  this.updateData = updateData;
18
39
  this.updateCollectedData = updateCollectedData;
19
40
  this.toolManager = toolManager;
41
+ this.signalProcessor = signalProcessor;
42
+ }
43
+ /**
44
+ * Create a fresh chain tracker for the current turn.
45
+ * Call at the start of each turn; the tracker is discarded at turn end.
46
+ */
47
+ createChainTracker() {
48
+ const maxChain = this.options.maxDirectiveChain ?? 10;
49
+ this._chainTracker = new DirectiveChainTracker(maxChain);
50
+ return this._chainTracker;
51
+ }
52
+ /**
53
+ * Get the current turn's chain tracker (creates one if none exists).
54
+ */
55
+ get chainTracker() {
56
+ if (!this._chainTracker) {
57
+ return this.createChainTracker();
58
+ }
59
+ return this._chainTracker;
60
+ }
61
+ /**
62
+ * Create a fresh DirectiveBus for a new turn.
63
+ * The bus collects directives from hooks, tools, and branches during the turn
64
+ * and merges them at phase boundaries via Algorithm 4.
65
+ */
66
+ createDirectiveBus() {
67
+ return new DirectiveBus();
68
+ }
69
+ // ──────────────────────────────────────────────────────────────────────────
70
+ // Signal pipeline phases
71
+ // ──────────────────────────────────────────────────────────────────────────
72
+ /**
73
+ * PRE-SIGNAL PHASE — Evaluates pre/both signals in parallel with routing.
74
+ *
75
+ * Delegates to `signalProcessor.runPreSignalPhase(...)` when configured.
76
+ * When no signal processor is present (zero-cost path), returns a stable
77
+ * empty shape so callers don't need to branch.
78
+ *
79
+ * @requirements 2.1, 2.3, 8.6, 13.3
80
+ */
81
+ async runPreSignalPhase(session, context, history) {
82
+ if (!this.signalProcessor) {
83
+ return { firings: [], updatedSession: session, mergedDirective: undefined };
84
+ }
85
+ const result = await this.signalProcessor.runPreSignalPhase({ session, history, context });
86
+ return {
87
+ firings: result.firings,
88
+ updatedSession: result.updatedSession,
89
+ mergedDirective: result.mergedDirective,
90
+ };
91
+ }
92
+ /**
93
+ * POST-SIGNAL PHASE — Evaluates post/both signals after finalize/onComplete.
94
+ *
95
+ * Delegates to `signalProcessor.runPostSignalPhase(...)` when configured.
96
+ * When no signal processor is present, returns a stable empty shape.
97
+ *
98
+ * Post-phase signals see the complete turn result: assistant message in history,
99
+ * collected data, tool results. Position directives from this phase set
100
+ * `session.pendingDirective` (no mid-turn re-entry per D6 decision).
101
+ *
102
+ * Pre-LLM-only fields (`appendPrompt`, `injectTools`, `halt`) are already
103
+ * dropped inside `runPostSignalPhase` per Phase 4.5 — this seam does NOT
104
+ * re-introduce them.
105
+ *
106
+ * @requirements 9.1, 9.2, 9.3, 9.4
107
+ */
108
+ async runPostSignalPhase(session, context, history) {
109
+ if (!this.signalProcessor) {
110
+ return { firings: [], updatedSession: session, mergedDirective: undefined };
111
+ }
112
+ const result = await this.signalProcessor.runPostSignalPhase({ session, history, context });
113
+ return {
114
+ firings: result.firings,
115
+ updatedSession: result.updatedSession,
116
+ mergedDirective: result.mergedDirective,
117
+ };
20
118
  }
21
119
  /**
22
120
  * Prepare context and session for response generation
@@ -48,45 +146,136 @@ export class ResponsePipeline {
48
146
  */
49
147
  async handleRoutingAndStepSelection(params) {
50
148
  const { session, history, context, signal } = params;
51
- // PHASE 2: ROUTING + STEP SELECTION - Determine which route and step to use (combined)
52
- let selectedRoute;
149
+ // PHASE 2: ROUTING + STEP SELECTION - Determine which flow and step to use (combined)
150
+ let selectedFlow;
53
151
  let responseDirectives;
54
152
  let selectedStep;
55
- let isRouteComplete = false;
56
- let completedRoutes = [];
153
+ let isFlowComplete = false;
154
+ let completedFlows = [];
57
155
  let targetSession = session;
58
- // Get routes early since we need them for pending transitions
59
- const routes = this.getRoutes();
60
- // Check for pending transition from previous route completion
61
- if (targetSession.pendingTransition) {
62
- const targetRoute = routes.find((r) => r.id === targetSession.pendingTransition?.targetRouteId);
63
- if (targetRoute) {
64
- logger.debug(`[ResponseHandler] Auto-transitioning from pending transition to route: ${targetRoute.title}`);
65
- // Clear pending transition and enter new route
66
- targetSession = {
67
- ...targetSession,
68
- pendingTransition: undefined,
69
- };
70
- targetSession = enterRoute(targetSession, targetRoute.id, targetRoute.title);
71
- // Merge initial data if available
72
- if (targetRoute.initialData) {
73
- targetSession = mergeCollected(targetSession, targetRoute.initialData);
156
+ // Get flows early since we need them for pending directives
157
+ const flows = this.getFlows();
158
+ // Check for pending directive from previous flow completion or external dispatch
159
+ if (targetSession.pendingDirective) {
160
+ const directive = targetSession.pendingDirective;
161
+ logger.debug(`[ResponseHandler] Applying pending directive at start of turn`);
162
+ // Track directive chain depth (Requirement 22.1)
163
+ const tracker = this.chainTracker;
164
+ tracker.record(directive, "pending");
165
+ // If abort (chain breaker), the tracker stops counting; apply normally below
166
+ // Clear pendingDirective before application (unless complete.next chains another)
167
+ let nextDirective = undefined;
168
+ if (directive.complete &&
169
+ typeof directive.complete === 'object' &&
170
+ directive.complete.next) {
171
+ nextDirective = directive.complete.next;
172
+ }
173
+ targetSession = {
174
+ ...targetSession,
175
+ pendingDirective: nextDirective,
176
+ };
177
+ // Apply the directive: resolve position field to a flow/step
178
+ if (directive.goTo) {
179
+ const flowTarget = typeof directive.goTo === 'string'
180
+ ? directive.goTo
181
+ : directive.goTo.flow;
182
+ if (flowTarget) {
183
+ const targetFlow = flows.find((r) => r.id === flowTarget || r.title === flowTarget);
184
+ if (targetFlow) {
185
+ logger.debug(`[ResponseHandler] Pending directive goTo → flow: ${targetFlow.title}`);
186
+ targetSession = enterFlow(targetSession, targetFlow.id, targetFlow.title);
187
+ // Merge initial data if available
188
+ if (targetFlow.initialData) {
189
+ targetSession = mergeCollected(targetSession, targetFlow.initialData);
190
+ }
191
+ // Merge directive-carried data if present
192
+ if (typeof directive.goTo === 'object' && directive.goTo.data) {
193
+ targetSession = mergeCollected(targetSession, directive.goTo.data);
194
+ }
195
+ selectedFlow = targetFlow;
196
+ // If goTo specifies a step, enter it
197
+ if (typeof directive.goTo === 'object' && directive.goTo.step) {
198
+ const stepTarget = directive.goTo.step;
199
+ const targetStep = targetFlow.getStep(stepTarget);
200
+ if (targetStep) {
201
+ targetSession = enterStep(targetSession, targetStep.id, targetStep.description);
202
+ selectedStep = targetStep;
203
+ }
204
+ }
205
+ }
206
+ else {
207
+ logger.warn(`[FlowConfigurationError] Pending directive goTo target not found: flow "${flowTarget}" does not exist. Falling back to normal routing. Fix the goTo reference or remove the pending directive.`);
208
+ }
74
209
  }
75
- selectedRoute = targetRoute;
76
210
  }
77
- else {
78
- logger.warn(`[ResponseHandler] Pending transition target route not found: ${targetSession.pendingTransition.targetRouteId}`);
79
- // Clear invalid transition
80
- targetSession = {
81
- ...targetSession,
82
- pendingTransition: undefined,
83
- };
211
+ else if (directive.goToStep) {
212
+ const stepTarget = typeof directive.goToStep === 'string'
213
+ ? directive.goToStep
214
+ : directive.goToStep.step;
215
+ const flowTarget = typeof directive.goToStep === 'object'
216
+ ? directive.goToStep.flow
217
+ : undefined;
218
+ if (flowTarget) {
219
+ const targetFlow = flows.find((r) => r.id === flowTarget || r.title === flowTarget);
220
+ if (targetFlow) {
221
+ targetSession = enterFlow(targetSession, targetFlow.id, targetFlow.title);
222
+ selectedFlow = targetFlow;
223
+ const targetStep = targetFlow.getStep(stepTarget);
224
+ if (targetStep) {
225
+ targetSession = enterStep(targetSession, targetStep.id, targetStep.description);
226
+ selectedStep = targetStep;
227
+ }
228
+ }
229
+ }
230
+ else if (targetSession.currentFlow) {
231
+ // Step within current flow
232
+ const currentFlow = flows.find(r => r.id === targetSession.currentFlow?.id);
233
+ if (currentFlow) {
234
+ selectedFlow = currentFlow;
235
+ const targetStep = currentFlow.getStep(stepTarget);
236
+ if (targetStep) {
237
+ targetSession = enterStep(targetSession, targetStep.id, targetStep.description);
238
+ selectedStep = targetStep;
239
+ }
240
+ }
241
+ }
84
242
  }
243
+ else if (directive.reset) {
244
+ // Reset current flow
245
+ if (targetSession.currentFlow) {
246
+ const currentFlow = flows.find(r => r.id === targetSession.currentFlow?.id);
247
+ if (currentFlow) {
248
+ const resetStep = typeof directive.reset === 'object' && directive.reset.step
249
+ ? directive.reset.step
250
+ : undefined;
251
+ selectedFlow = currentFlow;
252
+ if (resetStep) {
253
+ const targetStep = currentFlow.getStep(resetStep);
254
+ if (targetStep) {
255
+ targetSession = enterStep(targetSession, targetStep.id, targetStep.description);
256
+ selectedStep = targetStep;
257
+ }
258
+ }
259
+ else {
260
+ // Reset to initial step
261
+ const initialStep = currentFlow.initialStep;
262
+ targetSession = enterStep(targetSession, initialStep.id, initialStep.description);
263
+ selectedStep = initialStep;
264
+ }
265
+ }
266
+ }
267
+ }
268
+ // For complete/abort, selectedFlow stays undefined → handled downstream
269
+ // Apply state writes from the directive
270
+ if (directive.dataUpdate) {
271
+ targetSession = mergeCollected(targetSession, directive.dataUpdate);
272
+ }
273
+ // Skip FlowRouter.decideFlowAndStep — the directive resolved the position
85
274
  }
86
275
  // If no pending transition or transition handled, do normal routing
87
- if (routes.length > 0 && !selectedRoute) {
88
- const orchestration = await this.routingEngine.decideRouteAndStep({
89
- routes: routes,
276
+ if (flows.length > 0 && !selectedFlow) {
277
+ const orchestration = await this.flowRouter.decideFlowAndStep({
278
+ flows: flows,
90
279
  session: targetSession,
91
280
  history,
92
281
  agentOptions: this.options,
@@ -94,32 +283,60 @@ export class ResponsePipeline {
94
283
  context,
95
284
  signal,
96
285
  });
97
- selectedRoute = orchestration.selectedRoute;
286
+ selectedFlow = orchestration.selectedFlow;
98
287
  selectedStep = orchestration.selectedStep;
99
288
  responseDirectives = orchestration.responseDirectives;
100
289
  targetSession = orchestration.session;
101
- isRouteComplete = orchestration.isRouteComplete || false;
102
- completedRoutes = orchestration.completedRoutes || [];
103
- // Log if route is complete
104
- if (isRouteComplete) {
105
- logger.debug(`[ResponseHandler] Route complete: all required data collected, END_ROUTE reached`);
290
+ isFlowComplete = orchestration.isFlowComplete || false;
291
+ completedFlows = orchestration.completedFlows || [];
292
+ // Log if flow is complete
293
+ if (isFlowComplete) {
294
+ logger.debug(`[ResponseHandler] Flow complete: all required data collected or last step reached`);
106
295
  }
107
296
  }
108
297
  return {
109
- selectedRoute,
298
+ selectedFlow,
110
299
  selectedStep,
111
300
  responseDirectives,
112
301
  session: targetSession,
113
- isRouteComplete,
114
- completedRoutes,
302
+ isFlowComplete,
303
+ completedFlows,
115
304
  };
116
305
  }
117
306
  /**
118
307
  * Determine next step and update session
119
308
  */
120
309
  async determineNextStep(params) {
121
- const { selectedRoute, selectedStep, session, isRouteComplete } = params;
122
- if (!selectedRoute || isRouteComplete) {
310
+ const { selectedFlow, selectedStep, session, isFlowComplete, busDirective } = params;
311
+ if (!selectedFlow) {
312
+ return { nextStep: undefined, session };
313
+ }
314
+ // ─── GUARD: directive bus winner with a position field preempts branches ───
315
+ // Resolution precedence (design.md): bus > branches > linear > AI.
316
+ // If the bus produced a directive with a position field (goTo, goToStep,
317
+ // complete, abort, reset), that decision wins the turn. Do NOT evaluate
318
+ // branches or linear/AI selection — the caller applies the bus directive.
319
+ if (hasDirectivePositionField(busDirective)) {
320
+ logger.debug(`[ResponseHandler] Directive bus winner has position field — skipping branch evaluation and linear/AI selection`);
321
+ return { nextStep: undefined, session };
322
+ }
323
+ // STEP 1 (Algorithm 1): branches win over linear chain AND flow completion.
324
+ // Evaluate branches before checking isFlowComplete — a branch can redirect
325
+ // even from the "last" step (which getCandidateStepsWithConditions marks as complete).
326
+ if (!selectedStep) {
327
+ const currentStep = session.currentFlow?.id === selectedFlow.id && session.currentStep
328
+ ? selectedFlow.getStep(session.currentStep.id)
329
+ : undefined;
330
+ if (currentStep?.branches && currentStep.branches.length > 0) {
331
+ const contextToUse = this.getStoredContext();
332
+ const branchResult = await this.evaluateStepBranches(currentStep, selectedFlow, session, contextToUse);
333
+ if (branchResult) {
334
+ return branchResult;
335
+ }
336
+ // undefined → fall through to linear/AI selection or flow completion
337
+ }
338
+ }
339
+ if (isFlowComplete) {
123
340
  return { nextStep: undefined, session };
124
341
  }
125
342
  let nextStep;
@@ -128,22 +345,39 @@ export class ResponsePipeline {
128
345
  nextStep = selectedStep;
129
346
  }
130
347
  else {
131
- // Determine current step from session if we're already in this route
132
- const currentStep = session.currentRoute?.id === selectedRoute.id && session.currentStep
133
- ? selectedRoute.getStep(session.currentStep.id)
348
+ // Determine current step from session if we're already in this flow
349
+ const currentStep = session.currentFlow?.id === selectedFlow.id && session.currentStep
350
+ ? selectedFlow.getStep(session.currentStep.id)
134
351
  : undefined;
135
352
  const contextToUse = this.getStoredContext();
136
- // Get candidate steps based on current position in the route
137
- const candidates = await this.routingEngine.getCandidateStepsWithConditions(selectedRoute, currentStep, // Pass current step instead of undefined to maintain progression
353
+ // Get candidate steps based on current position in the flow
354
+ const candidates = await this.flowRouter.getCandidateStepsWithConditions(selectedFlow, currentStep, // Pass current step instead of undefined to maintain progression
138
355
  createTemplateContext({ data: session.data, session, context: contextToUse }));
139
356
  if (candidates.length > 0) {
140
357
  nextStep = candidates[0].step;
141
- logger.debug(`[ResponseHandler] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new route'}`);
358
+ logger.debug(`[ResponseHandler] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new flow'}`);
142
359
  }
143
360
  else {
144
361
  // Fallback to initial step even if it should be skipped
145
- nextStep = selectedRoute.initialStep;
146
- logger.warn(`[ResponseHandler] No valid steps found, using initial step: ${nextStep.id}`);
362
+ nextStep = selectedFlow.initialStep;
363
+ logger.warn(`[FlowConfigurationError] No valid steps found in flow "${selectedFlow.title}": all candidates were skipped. Falling back to initial step "${nextStep.id}". Review step skip conditions.`);
364
+ }
365
+ }
366
+ // Before entering the step, check if requires fields are satisfied
367
+ if (nextStep.requires && nextStep.requires.length > 0) {
368
+ const sessionData = session.data || {};
369
+ const missingRequires = nextStep.requires.filter(field => sessionData[String(field)] === undefined);
370
+ if (missingRequires.length > 0) {
371
+ logger.debug(`[ResponseHandler] Cannot enter step "${nextStep.id}": missing required fields [${missingRequires.join(', ')}]. Staying at current step.`);
372
+ // Stay at current step - don't enter the next one
373
+ const currentStepId = session.currentStep?.id;
374
+ if (currentStepId && selectedFlow) {
375
+ const currentStepInstance = selectedFlow.getStep(currentStepId);
376
+ if (currentStepInstance) {
377
+ nextStep = currentStepInstance;
378
+ }
379
+ }
380
+ return { nextStep, session };
147
381
  }
148
382
  }
149
383
  // Update session with next step
@@ -151,11 +385,158 @@ export class ResponsePipeline {
151
385
  logger.debug(`[ResponseHandler] Entered step: ${nextStep.id}`);
152
386
  return { nextStep, session: updatedSession };
153
387
  }
388
+ /**
389
+ * Evaluate branches on a step and resolve the `then` value.
390
+ *
391
+ * Resolution rules (Algorithm 1, STEP 1 + then resolution):
392
+ * - String `then` → look up in current flow's step registry first (local step wins).
393
+ * - Not a local step → look up in agent's flow registry; if found, treat as goTo directive.
394
+ * - Neither → throw FlowConfigurationError.
395
+ * - Directive `then` → apply directly (bypass directive bus merge).
396
+ *
397
+ * Returns the resolved { nextStep, session, flowChanged? } or undefined if no branch matched.
398
+ */
399
+ async evaluateStepBranches(currentStep, selectedFlow, session, context) {
400
+ const history = session.history ? historyToEvents(session.history) : [];
401
+ // Build the BranchPredicateContext
402
+ const branchCtx = {
403
+ data: session.data,
404
+ context,
405
+ session,
406
+ history,
407
+ };
408
+ // Create the AI condition evaluator
409
+ const aiEvaluator = createAiConditionEvaluator(this.options.provider, history, context);
410
+ const result = await evaluateBranches(currentStep.branches, branchCtx, aiEvaluator);
411
+ if (result === undefined) {
412
+ return undefined; // No branch matched → fall through to linear/AI selection
413
+ }
414
+ // Task 4.3: Directive `then` value — apply directly
415
+ if (typeof result === 'object' && result !== null) {
416
+ const directive = result;
417
+ return this.applyBranchDirective(directive, selectedFlow, session);
418
+ }
419
+ // Task 4.2: String `then` resolution
420
+ // 1. Look up in current flow's step registry first (local step wins)
421
+ const localStep = selectedFlow.getStep(result);
422
+ if (localStep) {
423
+ const updatedSession = enterStep(session, localStep.id, localStep.description);
424
+ logger.debug(`[ResponseHandler] Branch resolved to local step: ${localStep.id}`);
425
+ return { nextStep: localStep, session: updatedSession };
426
+ }
427
+ // 2. Look up in agent's flow registry
428
+ const flows = this.getFlows();
429
+ const targetFlow = flows.find(f => f.id === result || f.title === result);
430
+ if (targetFlow) {
431
+ // Treat as applyDirective({ goTo: result }) — enter the target flow
432
+ logger.debug(`[ResponseHandler] Branch resolved to flow: ${targetFlow.title}`);
433
+ const updatedSession = enterFlow(session, targetFlow.id, targetFlow.title);
434
+ return { nextStep: undefined, session: updatedSession, flowChanged: targetFlow };
435
+ }
436
+ // 3. Neither → throw FlowConfigurationError
437
+ throw new FlowConfigurationError(`[FlowConfigurationError] Unresolved branch target: "${result}" does not match any step in flow "${selectedFlow.id}" or any flow in the agent. ` +
438
+ `Source: ${selectedFlow.id}.${currentStep.id}. Fix the branch "then" value to reference a valid step id or flow id/title.`);
439
+ }
440
+ /**
441
+ * Apply a Directive returned by a branch entry's `then` value.
442
+ * Branches bypass the directive bus — the Directive is the position decision.
443
+ */
444
+ applyBranchDirective(directive, selectedFlow, session) {
445
+ // Track directive chain depth (Requirement 22.1)
446
+ const tracker = this.chainTracker;
447
+ tracker.record(directive, `branch:${selectedFlow.id}`);
448
+ let updatedSession = session;
449
+ // Apply state writes first
450
+ if (directive.dataUpdate) {
451
+ updatedSession = mergeCollected(updatedSession, directive.dataUpdate);
452
+ }
453
+ // Handle position fields
454
+ if (directive.goToStep) {
455
+ const stepTarget = typeof directive.goToStep === 'string'
456
+ ? directive.goToStep
457
+ : directive.goToStep.step;
458
+ const flowTarget = typeof directive.goToStep === 'object'
459
+ ? directive.goToStep.flow
460
+ : undefined;
461
+ if (flowTarget) {
462
+ // Cross-flow step reference — enter the target flow first
463
+ const flows = this.getFlows();
464
+ const targetFlow = flows.find(f => f.id === flowTarget || f.title === flowTarget);
465
+ if (targetFlow) {
466
+ updatedSession = enterFlow(updatedSession, targetFlow.id, targetFlow.title);
467
+ updatedSession = enterStep(updatedSession, stepTarget);
468
+ // Try to resolve the target step instance for the caller
469
+ const targetStepInstance = targetFlow.getStep(stepTarget);
470
+ logger.debug(`[ResponseHandler] Branch directive goToStep → ${flowTarget}.${stepTarget}`);
471
+ return { nextStep: targetStepInstance || undefined, session: updatedSession, flowChanged: targetFlow };
472
+ }
473
+ throw new FlowConfigurationError(`[FlowConfigurationError] Branch directive goToStep targets unknown flow: "${flowTarget}" does not match any flow id or title. ` +
474
+ `Fix the goToStep.flow value or use goTo to target a known flow.`);
475
+ }
476
+ // Local step reference
477
+ const targetStep = selectedFlow.getStep(stepTarget);
478
+ if (targetStep) {
479
+ updatedSession = enterStep(updatedSession, targetStep.id, targetStep.description);
480
+ logger.debug(`[ResponseHandler] Branch directive goToStep → ${targetStep.id}`);
481
+ return { nextStep: targetStep, session: updatedSession };
482
+ }
483
+ throw new FlowConfigurationError(`[FlowConfigurationError] Branch directive goToStep targets unknown step: "${stepTarget}" does not exist in flow "${selectedFlow.id}". ` +
484
+ `Fix the goToStep value to reference a valid step id in the current flow.`);
485
+ }
486
+ if (directive.goTo) {
487
+ const flowTarget = typeof directive.goTo === 'string'
488
+ ? directive.goTo
489
+ : directive.goTo.flow ?? directive.goTo.step;
490
+ if (flowTarget) {
491
+ const flows = this.getFlows();
492
+ const targetFlow = flows.find(f => f.id === flowTarget || f.title === flowTarget);
493
+ if (targetFlow) {
494
+ updatedSession = enterFlow(updatedSession, targetFlow.id, targetFlow.title);
495
+ // If goTo is an object with a step field, enter that step too
496
+ if (typeof directive.goTo === 'object' && directive.goTo.step) {
497
+ updatedSession = enterStep(updatedSession, directive.goTo.step);
498
+ }
499
+ logger.debug(`[ResponseHandler] Branch directive goTo → ${targetFlow.title}`);
500
+ return { nextStep: undefined, session: updatedSession, flowChanged: targetFlow };
501
+ }
502
+ throw new FlowConfigurationError(`[FlowConfigurationError] Branch directive goTo targets unknown flow: "${flowTarget}" does not match any flow id or title. ` +
503
+ `Fix the goTo value to reference a valid flow.`);
504
+ }
505
+ }
506
+ if (directive.complete) {
507
+ logger.debug(`[ResponseHandler] Branch directive complete`);
508
+ return { nextStep: undefined, session: updatedSession };
509
+ }
510
+ if (directive.abort) {
511
+ logger.debug(`[ResponseHandler] Branch directive abort`);
512
+ return { nextStep: undefined, session: updatedSession };
513
+ }
514
+ if (directive.reset) {
515
+ const resetStep = typeof directive.reset === 'object' && directive.reset.step
516
+ ? directive.reset.step
517
+ : undefined;
518
+ if (resetStep) {
519
+ const targetStep = selectedFlow.getStep(resetStep);
520
+ if (targetStep) {
521
+ updatedSession = enterStep(updatedSession, targetStep.id, targetStep.description);
522
+ return { nextStep: targetStep, session: updatedSession };
523
+ }
524
+ }
525
+ // Reset to initial step
526
+ const initialStep = selectedFlow.initialStep;
527
+ updatedSession = enterStep(updatedSession, initialStep.id, initialStep.description);
528
+ logger.debug(`[ResponseHandler] Branch directive reset → ${initialStep.id}`);
529
+ return { nextStep: initialStep, session: updatedSession };
530
+ }
531
+ // Directive with only non-position fields (e.g., just dataUpdate/contextUpdate/reply)
532
+ // No position change — fall through to linear selection
533
+ return { nextStep: undefined, session: updatedSession };
534
+ }
154
535
  /**
155
536
  * Execute tool calls and handle results
156
537
  */
157
538
  async executeToolCalls(params) {
158
- const { toolCalls, selectedRoute, context, session, history, isStreaming = false, } = params;
539
+ const { toolCalls, selectedFlow, context, session, history, isStreaming = false, } = params;
159
540
  if (toolCalls.length === 0) {
160
541
  return { session, toolCalls: undefined };
161
542
  }
@@ -164,9 +545,9 @@ export class ResponsePipeline {
164
545
  const executedToolCalls = [];
165
546
  const toolResults = new Map();
166
547
  for (const toolCall of toolCalls) {
167
- const tool = this.findAvailableTool(toolCall.toolName, selectedRoute);
548
+ const tool = this.findAvailableTool(toolCall.toolName, selectedFlow);
168
549
  if (!tool) {
169
- logger.warn(`[ResponseHandler] Tool not found: ${toolCall.toolName}`);
550
+ logger.warn(`[ToolExecutionError] Tool not found: "${toolCall.toolName}" is not registered in any scope (transient, step, flow, or agent). Skipping this tool call. Register the tool or check the tool name.`);
170
551
  continue;
171
552
  }
172
553
  // Use ToolManager for unified tool execution
@@ -197,7 +578,7 @@ export class ResponsePipeline {
197
578
  updatedSession = await this.updateData(updatedSession, result.dataUpdate);
198
579
  logger.debug(`[ResponseHandler] ${isStreaming ? "Streaming " : ""}Tool updated collected data:`, result.dataUpdate);
199
580
  }
200
- logger.debug(`[ResponseHandler] Executed ${isStreaming ? "streaming " : ""}tool: ${String(tool.id || tool.name || 'unknown')} (success: ${result.success})`);
581
+ logger.debug(`[ResponseHandler] Executed ${isStreaming ? "streaming " : ""}tool: ${String(tool.id || tool.id || 'unknown')} (success: ${result.success})`);
201
582
  }
202
583
  return {
203
584
  session: updatedSession,
@@ -209,7 +590,7 @@ export class ResponsePipeline {
209
590
  * Execute tool loop for follow-up tool calls
210
591
  */
211
592
  async executeToolLoop(params) {
212
- const { initialToolCalls, selectedRoute, nextStep, responsePrompt, history, context, session, responseSchema, isStreaming = false, } = params;
593
+ const { initialToolCalls, selectedFlow, nextStep, responsePrompt, history, context, session, responseSchema, isStreaming = false, } = params;
213
594
  const MAX_TOOL_LOOPS = 5;
214
595
  let toolLoopCount = 0;
215
596
  let currentToolCalls = initialToolCalls;
@@ -223,7 +604,7 @@ export class ResponsePipeline {
223
604
  // Add tool execution results to history so AI knows what happened
224
605
  const toolResultItems = [];
225
606
  for (const toolCall of currentToolCalls || []) {
226
- const tool = this.findAvailableTool(toolCall.toolName, selectedRoute);
607
+ const tool = this.findAvailableTool(toolCall.toolName, selectedFlow);
227
608
  if (tool) {
228
609
  toolResultItems.push({
229
610
  role: "assistant",
@@ -249,7 +630,7 @@ export class ResponsePipeline {
249
630
  prompt: responsePrompt,
250
631
  history: updatedHistory,
251
632
  context,
252
- tools: this.collectAvailableTools(selectedRoute, nextStep),
633
+ tools: this.collectAvailableTools(selectedFlow, nextStep),
253
634
  parameters: {
254
635
  jsonSchema: responseSchema,
255
636
  schemaName: isStreaming ? "tool_followup_streaming" : "tool_followup",
@@ -263,7 +644,7 @@ export class ResponsePipeline {
263
644
  // Execute the follow-up tool calls
264
645
  const toolResult = await this.executeToolCalls({
265
646
  toolCalls: followUpToolCalls,
266
- selectedRoute,
647
+ selectedFlow,
267
648
  context,
268
649
  session: currentSession,
269
650
  history: historyToEvents(updatedHistory),
@@ -281,7 +662,7 @@ export class ResponsePipeline {
281
662
  }
282
663
  }
283
664
  if (toolLoopCount >= MAX_TOOL_LOOPS) {
284
- logger.warn(`[ResponseHandler] ${isStreaming ? "Streaming " : ""}Tool loop limit reached (${MAX_TOOL_LOOPS}), stopping`);
665
+ logger.warn(`[ResponseGenerationError] ${isStreaming ? "Streaming t" : "T"}ool loop limit reached: ${toolLoopCount} iterations hit the cap (${MAX_TOOL_LOOPS}). Stopping tool execution. Increase MAX_TOOL_LOOPS or reduce recursive tool calls.`);
285
666
  }
286
667
  return {
287
668
  session: currentSession,
@@ -332,77 +713,85 @@ export class ResponsePipeline {
332
713
  }
333
714
  }
334
715
  /**
335
- * Handle route completion logic
716
+ * Handle flow completion: pure state transition.
717
+ *
718
+ * Releases the session to idle (`currentFlow`/`currentStep` cleared),
719
+ * marks the active `flowHistory` entry completed, and (when `onComplete`
720
+ * is set) wires `pendingDirective` for the next turn. The framework
721
+ * emits no message of its own at the completion boundary; callers that
722
+ * need closing copy should add a final interactive step.
336
723
  */
337
- async handleRouteCompletion(params) {
338
- const { selectedRoute, session, context, history } = params;
724
+ async handleFlowCompletion(params) {
725
+ const { selectedFlow, session, context } = params;
339
726
  // Check for onComplete transition
340
- const transitionConfig = await selectedRoute.evaluateOnComplete({ data: session.data }, context);
727
+ const transitionConfig = await selectedFlow.evaluateOnComplete({ data: session.data }, context);
728
+ // Release to idle. When the flow is reentrant, scrub its owned
729
+ // fields so a future re-selection doesn't short-circuit on stale data.
730
+ const ownedFields = selectedFlow.reentrant
731
+ ? [
732
+ ...(selectedFlow.requiredFields ?? []),
733
+ ...(selectedFlow.optionalFields ?? []),
734
+ ]
735
+ : undefined;
736
+ let updatedSession = completeCurrentFlow(session, {
737
+ clearOwnedFields: ownedFields,
738
+ });
341
739
  if (transitionConfig) {
342
- // Find target route by ID or title
343
- const targetRoute = this.getRoutes().find((r) => r.id === transitionConfig.nextStep ||
344
- r.title === transitionConfig.nextStep);
345
- if (targetRoute) {
346
- const templateContext = createTemplateContext({
347
- context,
348
- session,
349
- history,
350
- });
351
- const renderedCondition = (await render(transitionConfig.condition, templateContext)) ||
352
- (typeof transitionConfig.condition === "string"
353
- ? transitionConfig.condition
354
- : "");
355
- // Set pending transition in session
356
- const updatedSession = {
357
- ...session,
358
- pendingTransition: {
359
- targetRouteId: targetRoute.id,
360
- condition: renderedCondition,
361
- reason: "route_complete",
740
+ // Extract target from directive's goTo field
741
+ const goToTarget = typeof transitionConfig.goTo === 'string'
742
+ ? transitionConfig.goTo
743
+ : transitionConfig.goTo?.flow;
744
+ // Find target flow by ID or title
745
+ const targetFlow = goToTarget ? this.getFlows().find((r) => r.id === goToTarget ||
746
+ r.title === goToTarget) : undefined;
747
+ if (targetFlow) {
748
+ updatedSession = {
749
+ ...updatedSession,
750
+ pendingDirective: {
751
+ goTo: targetFlow.id,
362
752
  },
363
753
  };
364
- logger.debug(`[ResponseHandler] Route ${selectedRoute.title} completed with pending transition to: ${targetRoute.title}`);
754
+ logger.debug(`[ResponseHandler] Flow ${selectedFlow.title} completed with pending directive to: ${targetFlow.title}`);
365
755
  return { session: updatedSession, hasTransition: true };
366
756
  }
367
- else {
368
- logger.warn(`[ResponseHandler] Route ${selectedRoute.title} completed but target route not found: ${transitionConfig.nextStep}`);
757
+ else if (goToTarget) {
758
+ logger.warn(`[FlowConfigurationError] onComplete target not found: flow "${selectedFlow.title}" completed but onComplete target "${goToTarget}" does not match any flow. ` +
759
+ `Fix the onComplete value to reference an existing flow id/title, or remove onComplete to release the session to idle.`);
369
760
  }
370
761
  }
371
- // Set step to END_ROUTE marker
372
- const updatedSession = enterStep(session, END_ROUTE_ID, "Route completed");
373
- logger.debug(`[ResponseHandler] Route ${selectedRoute.title} completed. Entered END_ROUTE step.`);
762
+ logger.debug(`[ResponseHandler] Flow ${selectedFlow.title} completed; session released to idle.`);
374
763
  return { session: updatedSession, hasTransition: false };
375
764
  }
376
765
  /**
377
- * Find an available tool by name for the given route using ToolManager
766
+ * Find an available tool by name for the given flow using ToolManager
378
767
  * Delegates to ToolManager for unified tool resolution
379
768
  */
380
- findAvailableTool(toolName, route) {
769
+ findAvailableTool(toolName, flow) {
381
770
  // Use ToolManager for unified tool resolution if available
382
771
  if (this.toolManager) {
383
- return this.toolManager.find(toolName, undefined, undefined, route);
772
+ return this.toolManager.find(toolName, undefined, undefined, flow);
384
773
  }
385
774
  // Fallback to legacy resolution if ToolManager not available
386
775
  logger.warn(`[ResponsePipeline] ToolManager not available, using legacy tool resolution for: ${toolName}`);
387
- // Check route-level tools first (if route provided)
388
- if (route) {
389
- const routeTool = route
776
+ // Check flow-level tools first (if flow provided)
777
+ if (flow) {
778
+ const flowTool = flow
390
779
  .getTools()
391
- .find((tool) => tool.id === toolName || tool.name === toolName);
392
- if (routeTool)
393
- return routeTool;
780
+ .find((tool) => tool.id === toolName || tool.id === toolName);
781
+ if (flowTool)
782
+ return flowTool;
394
783
  }
395
784
  // Fall back to agent-level tools
396
- return this.tools.find((tool) => tool.id === toolName || tool.name === toolName);
785
+ return this.tools.find((tool) => tool.id === toolName || tool.id === toolName);
397
786
  }
398
787
  /**
399
- * Collect all available tools for the given route and step context using ToolManager
788
+ * Collect all available tools for the given flow and step context using ToolManager
400
789
  * Delegates to ToolManager for unified tool resolution and deduplication
401
790
  */
402
- collectAvailableTools(route, step) {
791
+ collectAvailableTools(flow, step) {
403
792
  // Use ToolManager for unified tool collection if available
404
793
  if (this.toolManager) {
405
- const availableTools = this.toolManager.getAvailable(undefined, step, route);
794
+ const availableTools = this.toolManager.getAvailable(undefined, step, flow);
406
795
  return availableTools.map((tool) => ({
407
796
  id: tool.id,
408
797
  description: tool.description,
@@ -416,9 +805,9 @@ export class ResponsePipeline {
416
805
  this.tools.forEach((tool) => {
417
806
  availableTools.set(tool.id, tool);
418
807
  });
419
- // Add route-level tools (these take precedence)
420
- if (route) {
421
- route.getTools().forEach((tool) => {
808
+ // Add flow-level tools (these take precedence)
809
+ if (flow) {
810
+ flow.getTools().forEach((tool) => {
422
811
  availableTools.set(tool.id, tool);
423
812
  });
424
813
  }
@@ -490,34 +879,34 @@ export class ResponsePipeline {
490
879
  return this.currentSession;
491
880
  }
492
881
  /**
493
- * Handle cross-route completion evaluation and notifications
494
- * This method evaluates all routes for completion and can trigger completion handlers
882
+ * Handle cross-flow completion evaluation and notifications
883
+ * This method evaluates all flows for completion and can trigger completion handlers
495
884
  */
496
- async handleCrossRouteCompletion(params) {
497
- const { routes, session, context } = params;
498
- // Evaluate all routes for completion
499
- const completedRoutes = [];
885
+ async handleCrossFlowCompletion(params) {
886
+ const { flows, session, context } = params;
887
+ // Evaluate all flows for completion
888
+ const completedFlows = [];
500
889
  const pendingTransitions = [];
501
- for (const route of routes) {
502
- if (route.isComplete(session.data || {})) {
503
- completedRoutes.push(route);
890
+ for (const flow of flows) {
891
+ if (flow.isComplete(session.data || {})) {
892
+ completedFlows.push(flow);
504
893
  // Check for onComplete transitions
505
- const transitionConfig = await route.evaluateOnComplete({ data: session.data }, context);
894
+ const transitionConfig = await flow.evaluateOnComplete({ data: session.data }, context);
506
895
  if (transitionConfig) {
507
- pendingTransitions.push({ route, transitionConfig });
896
+ pendingTransitions.push({ flow, transitionConfig });
508
897
  }
509
- logger.debug(`[ResponsePipeline] Route completed: ${route.title} ` +
510
- `(${Math.round(route.getCompletionProgress(session.data || {}) * 100)}%)`);
898
+ logger.debug(`[ResponsePipeline] Flow completed: ${flow.title} ` +
899
+ `(${Math.round(flow.getCompletionProgress(session.data || {}) * 100)}%)`);
511
900
  }
512
901
  }
513
- // Log completion status for all routes
514
- if (completedRoutes.length > 0) {
515
- logger.debug(`[ResponsePipeline] Cross-route completion evaluation: ` +
516
- `${completedRoutes.length}/${routes.length} routes complete`);
902
+ // Log completion status for all flows
903
+ if (completedFlows.length > 0) {
904
+ logger.debug(`[ResponsePipeline] Cross-flow completion evaluation: ` +
905
+ `${completedFlows.length}/${flows.length} flows complete`);
517
906
  }
518
907
  return {
519
908
  session,
520
- completedRoutes,
909
+ completedFlows,
521
910
  pendingTransitions,
522
911
  };
523
912
  }
@@ -526,23 +915,23 @@ export class ResponsePipeline {
526
915
  * This method ensures that data updates are properly validated and propagated
527
916
  */
528
917
  async updateDataFlow(params) {
529
- const { session, dataUpdate, routes } = params;
918
+ const { session, dataUpdate, flows } = params;
530
919
  // Update session data
531
920
  const updatedSession = await this.updateData(session, dataUpdate);
532
921
  // Update agent-level data if handler is available
533
922
  if (this.updateCollectedData) {
534
923
  await this.updateCollectedData(dataUpdate);
535
924
  }
536
- // Evaluate route completions after data update
537
- const completionResults = await this.handleCrossRouteCompletion({
538
- routes,
925
+ // Evaluate flow completions after data update
926
+ const completionResults = await this.handleCrossFlowCompletion({
927
+ flows,
539
928
  session: updatedSession,
540
929
  context: this.context,
541
930
  history: [],
542
931
  });
543
- // Log any newly completed routes
544
- if (completionResults.completedRoutes.length > 0) {
545
- logger.debug(`[ResponsePipeline] Data update resulted in ${completionResults.completedRoutes.length} completed routes`);
932
+ // Log any newly completed flows
933
+ if (completionResults.completedFlows.length > 0) {
934
+ logger.debug(`[ResponsePipeline] Data update resulted in ${completionResults.completedFlows.length} completed flows`);
546
935
  }
547
936
  return completionResults.session;
548
937
  }