@falai/agent 1.2.8 → 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 (499) 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 +1191 -1014
  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 +509 -136
  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/types/agent.d.ts +183 -54
  126. package/dist/cjs/types/agent.d.ts.map +1 -1
  127. package/dist/cjs/types/agent.js +0 -6
  128. package/dist/cjs/types/agent.js.map +1 -1
  129. package/dist/cjs/types/ai.d.ts +3 -3
  130. package/dist/cjs/types/ai.d.ts.map +1 -1
  131. package/dist/cjs/types/errors.d.ts +15 -0
  132. package/dist/cjs/types/errors.d.ts.map +1 -0
  133. package/dist/cjs/types/errors.js +22 -0
  134. package/dist/cjs/types/errors.js.map +1 -0
  135. package/dist/cjs/types/flow.d.ts +513 -0
  136. package/dist/cjs/types/flow.d.ts.map +1 -0
  137. package/dist/cjs/types/{route.js → flow.js} +2 -2
  138. package/dist/cjs/types/flow.js.map +1 -0
  139. package/dist/cjs/types/index.d.ts +7 -6
  140. package/dist/cjs/types/index.d.ts.map +1 -1
  141. package/dist/cjs/types/index.js +6 -2
  142. package/dist/cjs/types/index.js.map +1 -1
  143. package/dist/cjs/types/persistence.d.ts +11 -7
  144. package/dist/cjs/types/persistence.d.ts.map +1 -1
  145. package/dist/cjs/types/routing.d.ts +1 -1
  146. package/dist/cjs/types/routing.d.ts.map +1 -1
  147. package/dist/cjs/types/session.d.ts +24 -23
  148. package/dist/cjs/types/session.d.ts.map +1 -1
  149. package/dist/cjs/types/signals.d.ts +248 -0
  150. package/dist/cjs/types/signals.d.ts.map +1 -0
  151. package/dist/cjs/types/signals.js +11 -0
  152. package/dist/cjs/types/signals.js.map +1 -0
  153. package/dist/cjs/types/template.d.ts +2 -8
  154. package/dist/cjs/types/template.d.ts.map +1 -1
  155. package/dist/cjs/types/tool.d.ts +36 -29
  156. package/dist/cjs/types/tool.d.ts.map +1 -1
  157. package/dist/cjs/types/tool.js +1 -1
  158. package/dist/cjs/types/tool.js.map +1 -1
  159. package/dist/cjs/utils/condition.d.ts +7 -1
  160. package/dist/cjs/utils/condition.d.ts.map +1 -1
  161. package/dist/cjs/utils/condition.js.map +1 -1
  162. package/dist/cjs/utils/id.d.ts +13 -5
  163. package/dist/cjs/utils/id.d.ts.map +1 -1
  164. package/dist/cjs/utils/id.js +24 -10
  165. package/dist/cjs/utils/id.js.map +1 -1
  166. package/dist/cjs/utils/index.d.ts +2 -2
  167. package/dist/cjs/utils/index.d.ts.map +1 -1
  168. package/dist/cjs/utils/index.js +7 -3
  169. package/dist/cjs/utils/index.js.map +1 -1
  170. package/dist/cjs/utils/session.d.ts +44 -5
  171. package/dist/cjs/utils/session.d.ts.map +1 -1
  172. package/dist/cjs/utils/session.js +197 -38
  173. package/dist/cjs/utils/session.js.map +1 -1
  174. package/dist/constants/index.d.ts +0 -9
  175. package/dist/constants/index.d.ts.map +1 -1
  176. package/dist/constants/index.js +3 -9
  177. package/dist/constants/index.js.map +1 -1
  178. package/dist/core/Agent.d.ts +119 -153
  179. package/dist/core/Agent.d.ts.map +1 -1
  180. package/dist/core/Agent.js +472 -325
  181. package/dist/core/Agent.js.map +1 -1
  182. package/dist/core/AutoChainExecutor.d.ts +107 -0
  183. package/dist/core/AutoChainExecutor.d.ts.map +1 -0
  184. package/dist/core/AutoChainExecutor.js +293 -0
  185. package/dist/core/AutoChainExecutor.js.map +1 -0
  186. package/dist/core/BranchEvaluator.d.ts +54 -0
  187. package/dist/core/BranchEvaluator.d.ts.map +1 -0
  188. package/dist/core/BranchEvaluator.js +126 -0
  189. package/dist/core/BranchEvaluator.js.map +1 -0
  190. package/dist/core/DirectiveBus.d.ts +88 -0
  191. package/dist/core/DirectiveBus.d.ts.map +1 -0
  192. package/dist/core/DirectiveBus.js +192 -0
  193. package/dist/core/DirectiveBus.js.map +1 -0
  194. package/dist/core/DirectiveChainTracker.d.ts +49 -0
  195. package/dist/core/DirectiveChainTracker.d.ts.map +1 -0
  196. package/dist/core/DirectiveChainTracker.js +117 -0
  197. package/dist/core/DirectiveChainTracker.js.map +1 -0
  198. package/dist/core/Flow.d.ts +186 -0
  199. package/dist/core/Flow.d.ts.map +1 -0
  200. package/dist/core/Flow.js +546 -0
  201. package/dist/core/Flow.js.map +1 -0
  202. package/dist/core/FlowRouter.d.ts +182 -0
  203. package/dist/core/FlowRouter.d.ts.map +1 -0
  204. package/dist/core/{RoutingEngine.js → FlowRouter.js} +322 -305
  205. package/dist/core/FlowRouter.js.map +1 -0
  206. package/dist/core/PersistenceManager.d.ts +2 -2
  207. package/dist/core/PersistenceManager.d.ts.map +1 -1
  208. package/dist/core/PersistenceManager.js +7 -7
  209. package/dist/core/PersistenceManager.js.map +1 -1
  210. package/dist/core/PromptComposer.d.ts +21 -8
  211. package/dist/core/PromptComposer.d.ts.map +1 -1
  212. package/dist/core/PromptComposer.js +183 -106
  213. package/dist/core/PromptComposer.js.map +1 -1
  214. package/dist/core/PromptSectionCache.d.ts +1 -1
  215. package/dist/core/PromptSectionCache.js +1 -1
  216. package/dist/core/ResponseEngine.d.ts +18 -8
  217. package/dist/core/ResponseEngine.d.ts.map +1 -1
  218. package/dist/core/ResponseEngine.js +38 -36
  219. package/dist/core/ResponseEngine.js.map +1 -1
  220. package/dist/core/ResponseModal.d.ts +73 -56
  221. package/dist/core/ResponseModal.d.ts.map +1 -1
  222. package/dist/core/ResponseModal.js +1193 -1016
  223. package/dist/core/ResponseModal.js.map +1 -1
  224. package/dist/core/ResponsePipeline.d.ts +124 -26
  225. package/dist/core/ResponsePipeline.d.ts.map +1 -1
  226. package/dist/core/ResponsePipeline.js +509 -137
  227. package/dist/core/ResponsePipeline.js.map +1 -1
  228. package/dist/core/SignalEvaluator.d.ts +86 -0
  229. package/dist/core/SignalEvaluator.d.ts.map +1 -0
  230. package/dist/core/SignalEvaluator.js +326 -0
  231. package/dist/core/SignalEvaluator.js.map +1 -0
  232. package/dist/core/SignalProcessor.d.ts +152 -0
  233. package/dist/core/SignalProcessor.d.ts.map +1 -0
  234. package/dist/core/SignalProcessor.js +555 -0
  235. package/dist/core/SignalProcessor.js.map +1 -0
  236. package/dist/core/Step.d.ts +43 -32
  237. package/dist/core/Step.d.ts.map +1 -1
  238. package/dist/core/Step.js +220 -126
  239. package/dist/core/Step.js.map +1 -1
  240. package/dist/core/StreamingToolExecutor.d.ts +2 -2
  241. package/dist/core/StreamingToolExecutor.d.ts.map +1 -1
  242. package/dist/core/StreamingToolExecutor.js.map +1 -1
  243. package/dist/core/ToolManager.d.ts +44 -13
  244. package/dist/core/ToolManager.d.ts.map +1 -1
  245. package/dist/core/ToolManager.js +174 -91
  246. package/dist/core/ToolManager.js.map +1 -1
  247. package/dist/core/createAgent.d.ts +35 -0
  248. package/dist/core/createAgent.d.ts.map +1 -0
  249. package/dist/core/createAgent.js +36 -0
  250. package/dist/core/createAgent.js.map +1 -0
  251. package/dist/core/flow-namespace.d.ts +49 -0
  252. package/dist/core/flow-namespace.d.ts.map +1 -0
  253. package/dist/core/flow-namespace.js +168 -0
  254. package/dist/core/flow-namespace.js.map +1 -0
  255. package/dist/index.d.ts +11 -14
  256. package/dist/index.d.ts.map +1 -1
  257. package/dist/index.js +9 -12
  258. package/dist/index.js.map +1 -1
  259. package/dist/types/agent.d.ts +183 -54
  260. package/dist/types/agent.d.ts.map +1 -1
  261. package/dist/types/agent.js +0 -6
  262. package/dist/types/agent.js.map +1 -1
  263. package/dist/types/ai.d.ts +3 -3
  264. package/dist/types/ai.d.ts.map +1 -1
  265. package/dist/types/errors.d.ts +15 -0
  266. package/dist/types/errors.d.ts.map +1 -0
  267. package/dist/types/errors.js +18 -0
  268. package/dist/types/errors.js.map +1 -0
  269. package/dist/types/flow.d.ts +513 -0
  270. package/dist/types/flow.d.ts.map +1 -0
  271. package/dist/types/flow.js +5 -0
  272. package/dist/types/flow.js.map +1 -0
  273. package/dist/types/index.d.ts +7 -6
  274. package/dist/types/index.d.ts.map +1 -1
  275. package/dist/types/index.js +4 -1
  276. package/dist/types/index.js.map +1 -1
  277. package/dist/types/persistence.d.ts +11 -7
  278. package/dist/types/persistence.d.ts.map +1 -1
  279. package/dist/types/routing.d.ts +1 -1
  280. package/dist/types/routing.d.ts.map +1 -1
  281. package/dist/types/session.d.ts +24 -23
  282. package/dist/types/session.d.ts.map +1 -1
  283. package/dist/types/signals.d.ts +248 -0
  284. package/dist/types/signals.d.ts.map +1 -0
  285. package/dist/types/signals.js +10 -0
  286. package/dist/types/signals.js.map +1 -0
  287. package/dist/types/template.d.ts +2 -8
  288. package/dist/types/template.d.ts.map +1 -1
  289. package/dist/types/tool.d.ts +36 -29
  290. package/dist/types/tool.d.ts.map +1 -1
  291. package/dist/types/tool.js +1 -1
  292. package/dist/types/tool.js.map +1 -1
  293. package/dist/utils/condition.d.ts +7 -1
  294. package/dist/utils/condition.d.ts.map +1 -1
  295. package/dist/utils/condition.js.map +1 -1
  296. package/dist/utils/id.d.ts +13 -5
  297. package/dist/utils/id.d.ts.map +1 -1
  298. package/dist/utils/id.js +22 -9
  299. package/dist/utils/id.js.map +1 -1
  300. package/dist/utils/index.d.ts +2 -2
  301. package/dist/utils/index.d.ts.map +1 -1
  302. package/dist/utils/index.js +2 -2
  303. package/dist/utils/index.js.map +1 -1
  304. package/dist/utils/session.d.ts +44 -5
  305. package/dist/utils/session.d.ts.map +1 -1
  306. package/dist/utils/session.js +193 -37
  307. package/dist/utils/session.js.map +1 -1
  308. package/docs/README.md +15 -202
  309. package/docs/concepts/architecture.md +281 -0
  310. package/docs/concepts/directives.md +400 -0
  311. package/docs/concepts/pipeline.md +399 -0
  312. package/docs/guides/branching.md +263 -0
  313. package/docs/guides/compaction.md +163 -0
  314. package/docs/guides/conditions.md +167 -0
  315. package/docs/guides/error-handling.md +176 -0
  316. package/docs/guides/flow-control.md +409 -0
  317. package/docs/guides/instructions.md +210 -0
  318. package/docs/guides/persistence.md +182 -0
  319. package/docs/guides/streaming.md +137 -0
  320. package/docs/migration/README.md +15 -0
  321. package/docs/migration/route-to-flow.md +560 -0
  322. package/docs/migration/v1-to-v2.md +909 -0
  323. package/docs/reference/adapters.md +481 -0
  324. package/docs/reference/branches.md +241 -0
  325. package/docs/reference/create-agent.md +186 -0
  326. package/docs/reference/directive.md +243 -0
  327. package/docs/reference/errors.md +122 -0
  328. package/docs/reference/flow.md +238 -0
  329. package/docs/reference/instruction.md +177 -0
  330. package/docs/reference/pre-directive.md +131 -0
  331. package/docs/reference/providers.md +227 -0
  332. package/docs/reference/signals.md +356 -0
  333. package/docs/reference/step.md +339 -0
  334. package/docs/reference/tool.md +269 -0
  335. package/docs/start/01-install.md +81 -0
  336. package/docs/start/02-first-agent.md +196 -0
  337. package/docs/start/03-collect-data.md +222 -0
  338. package/docs/start/04-add-tools.md +276 -0
  339. package/docs/start/05-go-to-production.md +216 -0
  340. package/examples/01-quickstart.ts +20 -0
  341. package/examples/02-data-extraction.ts +90 -0
  342. package/examples/03-tools.ts +136 -0
  343. package/examples/04-instructions.ts +100 -0
  344. package/examples/05-branching.ts +140 -0
  345. package/examples/06-flow-control.ts +103 -0
  346. package/examples/07-streaming.ts +69 -0
  347. package/examples/08-persistence.ts +98 -0
  348. package/examples/09-signals.ts +144 -0
  349. package/examples/tsconfig.json +30 -0
  350. package/package.json +2 -1
  351. package/src/adapters/MemoryAdapter.ts +3 -3
  352. package/src/adapters/MongoAdapter.ts +3 -3
  353. package/src/adapters/OpenSearchAdapter.ts +10 -8
  354. package/src/adapters/PostgreSQLAdapter.ts +26 -10
  355. package/src/adapters/PrismaAdapter.ts +6 -6
  356. package/src/adapters/RedisAdapter.ts +3 -3
  357. package/src/adapters/SQLiteAdapter.ts +31 -12
  358. package/src/constants/index.ts +2 -10
  359. package/src/core/Agent.ts +585 -374
  360. package/src/core/AutoChainExecutor.ts +440 -0
  361. package/src/core/BranchEvaluator.ts +167 -0
  362. package/src/core/DirectiveBus.ts +248 -0
  363. package/src/core/DirectiveChainTracker.ts +144 -0
  364. package/src/core/Flow.ts +666 -0
  365. package/src/core/{RoutingEngine.ts → FlowRouter.ts} +385 -365
  366. package/src/core/PersistenceManager.ts +8 -8
  367. package/src/core/PromptComposer.ts +209 -140
  368. package/src/core/PromptSectionCache.ts +1 -1
  369. package/src/core/ResponseEngine.ts +61 -46
  370. package/src/core/ResponseModal.ts +1453 -1240
  371. package/src/core/ResponsePipeline.ts +655 -175
  372. package/src/core/SignalEvaluator.ts +420 -0
  373. package/src/core/SignalProcessor.ts +723 -0
  374. package/src/core/Step.ts +279 -176
  375. package/src/core/StreamingToolExecutor.ts +4 -4
  376. package/src/core/ToolManager.ts +200 -97
  377. package/src/core/createAgent.ts +40 -0
  378. package/src/core/flow-namespace.ts +219 -0
  379. package/src/index.ts +42 -36
  380. package/src/types/agent.ts +182 -53
  381. package/src/types/ai.ts +3 -3
  382. package/src/types/errors.ts +18 -0
  383. package/src/types/flow.ts +590 -0
  384. package/src/types/index.ts +43 -16
  385. package/src/types/persistence.ts +12 -8
  386. package/src/types/routing.ts +1 -1
  387. package/src/types/session.ts +26 -23
  388. package/src/types/signals.ts +321 -0
  389. package/src/types/template.ts +3 -11
  390. package/src/types/tool.ts +50 -42
  391. package/src/utils/condition.ts +13 -4
  392. package/src/utils/id.ts +27 -9
  393. package/src/utils/index.ts +6 -2
  394. package/src/utils/session.ts +238 -42
  395. package/dist/cjs/core/BatchExecutor.d.ts +0 -359
  396. package/dist/cjs/core/BatchExecutor.d.ts.map +0 -1
  397. package/dist/cjs/core/BatchExecutor.js +0 -861
  398. package/dist/cjs/core/BatchExecutor.js.map +0 -1
  399. package/dist/cjs/core/BatchPromptBuilder.d.ts +0 -89
  400. package/dist/cjs/core/BatchPromptBuilder.d.ts.map +0 -1
  401. package/dist/cjs/core/BatchPromptBuilder.js +0 -223
  402. package/dist/cjs/core/BatchPromptBuilder.js.map +0 -1
  403. package/dist/cjs/core/Route.d.ts +0 -180
  404. package/dist/cjs/core/Route.d.ts.map +0 -1
  405. package/dist/cjs/core/Route.js +0 -542
  406. package/dist/cjs/core/Route.js.map +0 -1
  407. package/dist/cjs/core/RoutingEngine.d.ts +0 -185
  408. package/dist/cjs/core/RoutingEngine.d.ts.map +0 -1
  409. package/dist/cjs/core/RoutingEngine.js.map +0 -1
  410. package/dist/cjs/types/route.d.ts +0 -336
  411. package/dist/cjs/types/route.d.ts.map +0 -1
  412. package/dist/cjs/types/route.js.map +0 -1
  413. package/dist/core/BatchExecutor.d.ts +0 -359
  414. package/dist/core/BatchExecutor.d.ts.map +0 -1
  415. package/dist/core/BatchExecutor.js +0 -856
  416. package/dist/core/BatchExecutor.js.map +0 -1
  417. package/dist/core/BatchPromptBuilder.d.ts +0 -89
  418. package/dist/core/BatchPromptBuilder.d.ts.map +0 -1
  419. package/dist/core/BatchPromptBuilder.js +0 -219
  420. package/dist/core/BatchPromptBuilder.js.map +0 -1
  421. package/dist/core/Route.d.ts +0 -180
  422. package/dist/core/Route.d.ts.map +0 -1
  423. package/dist/core/Route.js +0 -538
  424. package/dist/core/Route.js.map +0 -1
  425. package/dist/core/RoutingEngine.d.ts +0 -185
  426. package/dist/core/RoutingEngine.d.ts.map +0 -1
  427. package/dist/core/RoutingEngine.js.map +0 -1
  428. package/dist/types/route.d.ts +0 -336
  429. package/dist/types/route.d.ts.map +0 -1
  430. package/dist/types/route.js +0 -5
  431. package/dist/types/route.js.map +0 -1
  432. package/docs/CONTRIBUTING.md +0 -521
  433. package/docs/api/README.md +0 -3299
  434. package/docs/api/overview.md +0 -1410
  435. package/docs/architecture/data-extraction-flow.md +0 -360
  436. package/docs/architecture/multi-step-execution.md +0 -277
  437. package/docs/core/agent/README.md +0 -938
  438. package/docs/core/agent/context-management.md +0 -796
  439. package/docs/core/agent/rules-and-prohibitions.md +0 -113
  440. package/docs/core/agent/session-management.md +0 -693
  441. package/docs/core/ai-integration/prompt-composition.md +0 -355
  442. package/docs/core/ai-integration/providers.md +0 -515
  443. package/docs/core/ai-integration/response-processing.md +0 -433
  444. package/docs/core/conversation-flows/data-collection.md +0 -772
  445. package/docs/core/conversation-flows/route-dsl.md +0 -509
  446. package/docs/core/conversation-flows/routes.md +0 -249
  447. package/docs/core/conversation-flows/step-transitions.md +0 -731
  448. package/docs/core/conversation-flows/steps.md +0 -268
  449. package/docs/core/error-handling.md +0 -830
  450. package/docs/core/persistence/adapters.md +0 -255
  451. package/docs/core/persistence/session-storage.md +0 -656
  452. package/docs/core/routing/intelligent-routing.md +0 -470
  453. package/docs/core/tools/enhanced-tool.md +0 -186
  454. package/docs/core/tools/streaming-execution.md +0 -161
  455. package/docs/core/tools/tool-definition.md +0 -970
  456. package/docs/core/tools/tool-scoping.md +0 -819
  457. package/docs/guides/advanced-patterns/publishing.md +0 -186
  458. package/docs/guides/context-compaction.md +0 -96
  459. package/docs/guides/error-handling-patterns.md +0 -578
  460. package/docs/guides/getting-started/README.md +0 -795
  461. package/docs/guides/migration/README.md +0 -101
  462. package/docs/guides/migration/flexible-routing-conditions.md +0 -375
  463. package/docs/guides/migration/multi-step-execution.md +0 -393
  464. package/docs/guides/migration/response-modal-refactor.md +0 -518
  465. package/docs/guides/prompt-optimization.md +0 -164
  466. package/examples/advanced-patterns/context-compaction.ts +0 -223
  467. package/examples/advanced-patterns/knowledge-based-agent.ts +0 -735
  468. package/examples/advanced-patterns/persistent-onboarding.ts +0 -728
  469. package/examples/advanced-patterns/route-lifecycle-hooks.ts +0 -556
  470. package/examples/advanced-patterns/streaming-responses.ts +0 -656
  471. package/examples/ai-providers/anthropic-integration.ts +0 -388
  472. package/examples/ai-providers/openai-integration.ts +0 -228
  473. package/examples/condition-patterns/function-only-conditions.ts +0 -365
  474. package/examples/condition-patterns/mixed-array-conditions.ts +0 -477
  475. package/examples/condition-patterns/route-skipif-patterns.ts +0 -468
  476. package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
  477. package/examples/condition-patterns/string-only-conditions.ts +0 -296
  478. package/examples/conversation-flows/completion-transitions.ts +0 -318
  479. package/examples/core-concepts/basic-agent.ts +0 -503
  480. package/examples/core-concepts/modern-streaming-api.ts +0 -309
  481. package/examples/core-concepts/schema-driven-extraction.ts +0 -332
  482. package/examples/core-concepts/session-management.ts +0 -494
  483. package/examples/integrations/database-integration.ts +0 -631
  484. package/examples/integrations/healthcare-integration.ts +0 -595
  485. package/examples/integrations/search-integration.ts +0 -530
  486. package/examples/integrations/server-session-management.ts +0 -307
  487. package/examples/persistence/custom-adapter.ts +0 -526
  488. package/examples/persistence/database-persistence.ts +0 -583
  489. package/examples/persistence/memory-sessions.ts +0 -495
  490. package/examples/persistence/prisma-schema.example.prisma +0 -74
  491. package/examples/persistence/redis-persistence.ts +0 -488
  492. package/examples/tools/basic-tools.ts +0 -765
  493. package/examples/tools/data-enrichment-tools.ts +0 -593
  494. package/examples/tools/enhanced-tool-metadata.ts +0 -268
  495. package/examples/tools/streaming-tool-execution.ts +0 -283
  496. package/src/core/BatchExecutor.ts +0 -1187
  497. package/src/core/BatchPromptBuilder.ts +0 -299
  498. package/src/core/Route.ts +0 -678
  499. package/src/types/route.ts +0 -392
@@ -7,23 +7,22 @@ import type {
7
7
  TemplateContext,
8
8
  } from "../types";
9
9
  import { MessageRole } from "../types";
10
- import { enterRoute, mergeCollected } from "../utils";
11
- import type { Route } from "./Route";
10
+ import { enterFlow, mergeCollected, isFlowCompletedThisSession } from "../utils";
11
+ import type { Flow } from "./Flow";
12
12
  import type { Step } from "./Step";
13
13
  import { PromptComposer } from "./PromptComposer";
14
14
  import { PromptSectionCache } from "./PromptSectionCache";
15
- import { END_ROUTE_ID } from "../constants";
16
15
  import { createTemplateContext, getLastMessageFromHistory, logger, eventsToHistory } from "../utils";
17
16
 
18
17
  export interface CandidateStep<TContext = unknown, TData = unknown> {
19
18
  step: Step<TContext, TData>;
20
- isRouteComplete?: boolean;
19
+ isFlowComplete?: boolean;
21
20
  }
22
21
 
23
- export interface RoutingDecisionOutput {
22
+ export interface FlowRoutingDecisionOutput {
24
23
  context: string;
25
- routes: Record<string, number>;
26
- selectedStepId?: string; // For active route, which step to transition to
24
+ flows: Record<string, number>;
25
+ selectedStepId?: string; // For active flow, which step to transition to
27
26
  stepReasoning?: string; // Why this step was selected
28
27
  responseDirectives?: string[];
29
28
  extractions?: Array<{
@@ -36,18 +35,18 @@ export interface RoutingDecisionOutput {
36
35
  contextUpdate?: Record<string, unknown>;
37
36
  }
38
37
 
39
- export interface RoutingEngineOptions {
38
+ export interface FlowRouterOptions {
40
39
  /**
41
- * Score margin the best alternative route must exceed the current route's score
42
- * by before the agent switches routes. Prevents flip-flopping on marginal differences.
40
+ * Score margin the best alternative flow must exceed the current flow's score
41
+ * by before the agent switches flows. Prevents flip-flopping on marginal differences.
43
42
  * @default 15
44
43
  */
45
- routeSwitchMargin?: number;
44
+ flowSwitchMargin?: number;
46
45
  /**
47
- * Callback invoked when the active route changes.
48
- * Used by Agent to invalidate route-dependent prompt cache sections.
46
+ * Callback invoked when the active flow changes.
47
+ * Used by Agent to invalidate flow-dependent prompt cache sections.
49
48
  */
50
- onRouteSwitch?: () => void;
49
+ onFlowSwitch?: () => void;
51
50
  /**
52
51
  * Shared prompt section cache for memoizing static prompt sections.
53
52
  */
@@ -58,7 +57,7 @@ export interface BuildStepSelectionPromptParams<
58
57
  TContext = unknown,
59
58
  TData = unknown
60
59
  > {
61
- route: Route<TContext, TData>;
60
+ flow: Flow<TContext, TData>;
62
61
  currentStep: Step<TContext, TData> | undefined;
63
62
  candidates: CandidateStep<TContext, TData>[];
64
63
  data: Partial<TData>;
@@ -72,20 +71,20 @@ export interface BuildStepSelectionPromptParams<
72
71
 
73
72
  export interface BuildRoutingPromptParams<TContext = unknown, TData = unknown> {
74
73
  history: Event[];
75
- routes: Route<TContext, TData>[];
74
+ flows: Flow<TContext, TData>[];
76
75
  lastMessage: string;
77
76
  agentOptions?: AgentOptions<TContext, TData>;
78
77
  session?: SessionState<TData>;
79
- activeRouteSteps?: Step<TContext, TData>[];
78
+ activeFlowSteps?: Step<TContext, TData>[];
80
79
  context?: TContext;
81
80
  }
82
81
 
83
- export class RoutingEngine<TContext = unknown, TData = unknown> {
84
- constructor(private readonly options?: RoutingEngineOptions) { }
82
+ export class FlowRouter<TContext = unknown, TData = unknown> {
83
+ constructor(private readonly options?: FlowRouterOptions) { }
85
84
 
86
85
  /**
87
86
  * Check whether the history contains any user messages.
88
- * Used to detect "session resume" scenarios where a route/step was
87
+ * Used to detect "session resume" scenarios where a flow/step was
89
88
  * pre-set programmatically and the conversation starts with only
90
89
  * system messages (or no messages at all).
91
90
  * @private
@@ -98,75 +97,75 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
98
97
 
99
98
  /**
100
99
  * Handle the "session resume" fast-path: when a session already has a
101
- * pre-set currentRoute (and optionally currentStep) and the conversation
100
+ * pre-set currentFlow (and optionally currentStep) and the conversation
102
101
  * history contains no user messages, honor the pre-set position instead
103
- * of running AI route/step selection.
102
+ * of running AI flow/step selection.
104
103
  *
105
104
  * Returns `undefined` when the fast-path does not apply.
106
105
  * @private
107
106
  */
108
107
  private async handleSessionResume(params: {
109
- routes: Route<TContext, TData>[];
108
+ flows: Flow<TContext, TData>[];
110
109
  session: SessionState<TData>;
111
110
  history: Event[];
112
111
  context: TContext;
113
112
  }): Promise<{
114
- selectedRoute?: Route<TContext, TData>;
113
+ selectedFlow?: Flow<TContext, TData>;
115
114
  selectedStep?: Step<TContext, TData>;
116
115
  session: SessionState<TData>;
117
- isRouteComplete?: boolean;
118
- completedRoutes?: Route<TContext, TData>[];
116
+ isFlowComplete?: boolean;
117
+ completedFlows?: Flow<TContext, TData>[];
119
118
  } | undefined> {
120
- const { routes, session, history, context } = params;
119
+ const { flows, session, history, context } = params;
121
120
 
122
121
  // Fast-path only applies when:
123
- // 1. Session already has a currentRoute set
122
+ // 1. Session already has a currentFlow set
124
123
  // 2. There are no user messages in the history (system-only or empty)
125
- if (!session.currentRoute || this.hasUserMessages(history)) {
124
+ if (!session.currentFlow || this.hasUserMessages(history)) {
126
125
  return undefined;
127
126
  }
128
127
 
129
- // Find the pre-set route among available routes
130
- const presetRoute = routes.find(
131
- (r) => r.id === session.currentRoute!.id
128
+ // Find the pre-set flow among available flows
129
+ const presetFlow = flows.find(
130
+ (r) => r.id === session.currentFlow!.id
132
131
  );
133
132
 
134
- if (!presetRoute) {
133
+ if (!presetFlow) {
135
134
  logger.warn(
136
- `[RoutingEngine] Session resume: pre-set route '${session.currentRoute.id}' not found among available routes, falling back to normal routing`
135
+ `[FlowConfigurationError] Pre-set flow not found: session references flow "${session.currentFlow.id}" which does not exist among available flows. Falling back to normal routing. Remove the stale session reference or register the missing flow.`
137
136
  );
138
137
  return undefined;
139
138
  }
140
139
 
141
140
  logger.debug(
142
- `[RoutingEngine] Session resume: honoring pre-set route '${presetRoute.title}' (no user messages in history)`
141
+ `[FlowRouter] Session resume: honoring pre-set flow '${presetFlow.title}' (no user messages in history)`
143
142
  );
144
143
 
145
- // Enter route if needed (merges initialData, no-op if already entered)
146
- const updatedSession = this.enterRouteIfNeeded(session, presetRoute);
144
+ // Enter flow if needed (merges initialData, no-op if already entered)
145
+ const updatedSession = this.enterFlowIfNeeded(session, presetFlow);
147
146
 
148
- // Evaluate cross-route completions
149
- const completedRoutes = this.evaluateRouteCompletions(routes, updatedSession.data || {});
147
+ // Evaluate cross-flow completions
148
+ const completedFlows = this.evaluateFlowCompletions(flows, updatedSession.data || {});
150
149
 
151
150
  // If a currentStep is also pre-set, honor it — stay on that step
152
151
  if (session.currentStep) {
153
- const presetStep = presetRoute.getStep(session.currentStep.id);
152
+ const presetStep = presetFlow.getStep(session.currentStep.id);
154
153
 
155
154
  if (presetStep) {
156
155
  logger.debug(
157
- `[RoutingEngine] Session resume: honoring pre-set step '${presetStep.id}'`
156
+ `[FlowRouter] Session resume: honoring pre-set step '${presetStep.id}'`
158
157
  );
159
158
  return {
160
- selectedRoute: presetRoute,
159
+ selectedFlow: presetFlow,
161
160
  selectedStep: presetStep,
162
161
  session: updatedSession,
163
- isRouteComplete: false,
164
- completedRoutes,
162
+ isFlowComplete: false,
163
+ completedFlows,
165
164
  };
166
165
  }
167
166
 
168
167
  logger.warn(
169
- `[RoutingEngine] Session resume: pre-set step '${session.currentStep.id}' not found in route '${presetRoute.title}', resolving from initial step`
168
+ `[FlowConfigurationError] Pre-set step not found: session references step "${session.currentStep.id}" which does not exist in flow "${presetFlow.title}". Resolving from initial step. Remove the stale step reference or register the missing step.`
170
169
  );
171
170
  }
172
171
 
@@ -180,82 +179,116 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
180
179
  });
181
180
 
182
181
  const candidates = await this.getCandidateStepsWithConditions(
183
- presetRoute,
182
+ presetFlow,
184
183
  undefined, // No current step — start from beginning
185
184
  templateContext
186
185
  );
187
186
 
188
187
  if (candidates.length === 0) {
189
188
  logger.warn(
190
- `[RoutingEngine] Session resume: no valid steps found for route '${presetRoute.title}'`
189
+ `[FlowConfigurationError] No valid steps found: all steps in flow "${presetFlow.title}" are skipped by their conditions. Check skip/when conditions on the flow's steps.`
191
190
  );
192
191
  return {
193
- selectedRoute: presetRoute,
192
+ selectedFlow: presetFlow,
194
193
  selectedStep: undefined,
195
194
  session: updatedSession,
196
- isRouteComplete: false,
197
- completedRoutes,
195
+ isFlowComplete: false,
196
+ completedFlows,
198
197
  };
199
198
  }
200
199
 
201
200
  const candidate = candidates[0];
202
201
 
203
- if (candidate.isRouteComplete) {
202
+ if (candidate.isFlowComplete) {
204
203
  logger.debug(
205
- `[RoutingEngine] Session resume: route '${presetRoute.title}' is already complete`
204
+ `[FlowRouter] Session resume: flow '${presetFlow.title}' is already complete`
206
205
  );
207
206
  return {
208
- selectedRoute: presetRoute,
207
+ selectedFlow: presetFlow,
209
208
  selectedStep: undefined,
210
209
  session: updatedSession,
211
- isRouteComplete: true,
212
- completedRoutes,
210
+ isFlowComplete: true,
211
+ completedFlows,
213
212
  };
214
213
  }
215
214
 
216
215
  logger.debug(
217
- `[RoutingEngine] Session resume: resolved initial step '${candidate.step.id}'`
216
+ `[FlowRouter] Session resume: resolved initial step '${candidate.step.id}'`
218
217
  );
219
218
  return {
220
- selectedRoute: presetRoute,
219
+ selectedFlow: presetFlow,
221
220
  selectedStep: candidate.step,
222
221
  session: updatedSession,
223
- isRouteComplete: false,
224
- completedRoutes,
222
+ isFlowComplete: false,
223
+ completedFlows,
225
224
  };
226
225
  }
227
226
 
228
227
  /**
229
- * Enter a route if not already in it, merging initial data
228
+ * Enter a flow if not already in it, merging initial data.
229
+ *
230
+ * When the flow is `reentrant` and was previously completed in this
231
+ * session, clears every field declared in the flow's `requiredFields`
232
+ * and `optionalFields` before entering — so the flow starts fresh from
233
+ * its initial step instead of being instantly marked complete by stale
234
+ * data. Fields not owned by this flow are preserved.
235
+ *
230
236
  * @private
231
237
  */
232
- private enterRouteIfNeeded(
238
+ private enterFlowIfNeeded(
233
239
  session: SessionState<TData>,
234
- route: Route<TContext, TData>
240
+ route: Flow<TContext, TData>
235
241
  ): SessionState<TData> {
236
- if (!session.currentRoute || session.currentRoute.id !== route.id) {
237
- let updatedSession = enterRoute(session, route.id, route.title);
242
+ if (!session.currentFlow || session.currentFlow.id !== route.id) {
243
+ let workingSession = session;
244
+
245
+ // Re-entry into a `reentrant` flow that previously completed:
246
+ // clear owned fields so completion logic doesn't short-circuit on
247
+ // stale data from the prior run.
248
+ const previouslyCompleted = isFlowCompletedThisSession(session, route.id);
249
+ if (previouslyCompleted && route.reentrant) {
250
+ const ownedFields = [
251
+ ...(route.requiredFields ?? []),
252
+ ...(route.optionalFields ?? []),
253
+ ];
254
+ if (ownedFields.length > 0) {
255
+ const owned = new Set<keyof TData>(ownedFields);
256
+ const filtered: Partial<TData> = {};
257
+ for (const key of Object.keys(session.data ?? {}) as (keyof TData)[]) {
258
+ if (!owned.has(key)) {
259
+ (filtered as Record<keyof TData, unknown>)[key] =
260
+ (session.data as Record<keyof TData, unknown>)[key];
261
+ }
262
+ }
263
+ workingSession = { ...session, data: filtered };
264
+ logger.debug(
265
+ `[FlowRouter] Re-entering reentrant flow ${route.title}: cleared ${ownedFields.length} owned field(s)`
266
+ );
267
+ }
268
+ }
269
+
270
+ let updatedSession = enterFlow(workingSession, route.id, route.title);
238
271
  if (route.initialData) {
239
272
  updatedSession = mergeCollected(updatedSession, route.initialData);
240
273
  logger.debug(
241
- `[RoutingEngine] Merged initial data for route ${route.title}:`,
274
+ `[FlowRouter] Merged initial data for flow ${route.title}:`,
242
275
  route.initialData
243
276
  );
244
277
  }
245
- logger.debug(`[RoutingEngine] Entered route: ${route.title}`);
246
- this.options?.onRouteSwitch?.();
278
+ logger.debug(`[FlowRouter] Entered flow: ${route.title}`);
279
+ this.options?.onFlowSwitch?.();
247
280
  return updatedSession;
248
281
  }
249
282
  return session;
250
283
  }
251
284
 
252
285
  /**
253
- * Optimized decision for single-route scenarios
254
- * Skips route scoring and only does step selection
286
+ * Optimized decision for single-flow scenarios
287
+ * Skips flow scoring and only does step selection
255
288
  * @private
256
289
  */
257
- private async decideSingleRouteStep(params: {
258
- route: Route<TContext, TData>;
290
+ private async decideSingleFlowStep(params: {
291
+ route: Flow<TContext, TData>;
259
292
  session: SessionState<TData>;
260
293
  history: Event[];
261
294
  agentOptions?: AgentOptions<TContext, TData>;
@@ -263,23 +296,23 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
263
296
  context: TContext;
264
297
  signal?: AbortSignal;
265
298
  }): Promise<{
266
- selectedRoute?: Route<TContext, TData>;
299
+ selectedFlow?: Flow<TContext, TData>;
267
300
  selectedStep?: Step<TContext, TData>;
268
301
  responseDirectives?: string[];
269
302
  session: SessionState<TData>;
270
- isRouteComplete?: boolean;
271
- completedRoutes?: Route<TContext, TData>[];
303
+ isFlowComplete?: boolean;
304
+ completedFlows?: Flow<TContext, TData>[];
272
305
  }> {
273
306
  const { route, session, history, agentOptions, provider, context, signal } =
274
307
  params;
275
308
 
276
- const selectedRoute = route;
309
+ const selectedFlow = route;
277
310
 
278
- // Enter route if not already in it (this may merge initial data)
279
- const updatedSession = this.enterRouteIfNeeded(session, route);
311
+ // Enter flow if not already in it (this may merge initial data)
312
+ const updatedSession = this.enterFlowIfNeeded(session, route);
280
313
 
281
- // Check if this single route is complete (use updated session data)
282
- const completedRoutes = route.isComplete(updatedSession.data || {}) ? [route] : [];
314
+ // Check if this single flow is complete (use updated session data)
315
+ const completedFlows = route.isComplete(updatedSession.data || {}) ? [route] : [];
283
316
 
284
317
  // Get candidate steps using new condition evaluation
285
318
  const templateContext = createTemplateContext({
@@ -298,52 +331,51 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
298
331
  );
299
332
 
300
333
  if (candidates.length === 0) {
301
- logger.warn(`[RoutingEngine] Single-route: No valid steps found`);
302
- return { selectedRoute, session: updatedSession };
334
+ logger.warn(`[FlowConfigurationError] No valid steps found: all candidates in the single-flow agent are skipped. Check step skip/when conditions.`);
335
+ return { selectedFlow, session: updatedSession };
303
336
  }
304
337
 
305
338
  // If only one candidate, check if it's a completion marker
306
339
  if (candidates.length === 1) {
307
340
  const candidate = candidates[0];
308
341
 
309
- if (candidate.isRouteComplete) {
342
+ if (candidate.isFlowComplete) {
310
343
  logger.debug(
311
- `[RoutingEngine] Single-route: Route complete - all required fields collected or END_ROUTE reached`
344
+ `[FlowRouter] Single-flow: Flow complete - all required fields collected or last step reached`
312
345
  );
313
- // Don't return a selectedStep when route is complete - there's no step to enter
346
+ // Don't return a selectedStep when flow is complete - there's no step to enter
314
347
  return {
315
- selectedRoute,
348
+ selectedFlow,
316
349
  selectedStep: undefined,
317
350
  session: updatedSession,
318
- isRouteComplete: true,
319
- completedRoutes,
351
+ isFlowComplete: true,
352
+ completedFlows,
320
353
  };
321
354
  } else {
322
355
  logger.debug(
323
- `[RoutingEngine] Single-route: Only one valid step: ${candidate.step.id}`
356
+ `[FlowRouter] Single-flow: Only one valid step: ${candidate.step.id}`
324
357
  );
325
358
  return {
326
- selectedRoute,
359
+ selectedFlow,
327
360
  selectedStep: candidate.step,
328
361
  session: updatedSession,
329
- isRouteComplete: false,
330
- completedRoutes,
362
+ isFlowComplete: false,
363
+ completedFlows,
331
364
  };
332
365
  }
333
366
  }
334
367
 
335
- // No candidates means route has no valid next steps (edge case)
336
- // Don't mark as complete based on data alone — only END_ROUTE completes a route
368
+ // No candidates means flow has no valid next steps (edge case)
337
369
  if (candidates.length === 0) {
338
370
  logger.debug(
339
- `[RoutingEngine] Single-route: No valid candidate steps found`
371
+ `[FlowRouter] Single-flow: No valid candidate steps found`
340
372
  );
341
373
  return {
342
- selectedRoute,
374
+ selectedFlow,
343
375
  selectedStep: undefined,
344
376
  session: updatedSession,
345
- isRouteComplete: false,
346
- completedRoutes,
377
+ isFlowComplete: false,
378
+ completedFlows,
347
379
  };
348
380
  }
349
381
 
@@ -357,11 +389,11 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
357
389
  stepConditionContext.push(...whenResult.aiContextStrings);
358
390
  }
359
391
 
360
- // Check if any candidate is a completion marker (isRouteComplete = true)
361
- const hasCompletionOption = candidates.some(c => c.isRouteComplete);
392
+ // Check if any candidate is a completion marker (isFlowComplete = true)
393
+ const hasCompletionOption = candidates.some(c => c.isFlowComplete);
362
394
 
363
395
  const stepPrompt = await this.buildStepSelectionPrompt({
364
- route,
396
+ flow: route,
365
397
  currentStep,
366
398
  candidates,
367
399
  data: updatedSession.data || {},
@@ -371,11 +403,11 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
371
403
  context,
372
404
  session: updatedSession,
373
405
  stepConditionContext,
374
- includeEndRoute: hasCompletionOption,
406
+ includeCompletion: hasCompletionOption,
375
407
  });
376
408
 
377
409
  const stepSchema = this.buildStepSelectionSchema(
378
- candidates.filter(c => !c.isRouteComplete).map((c) => c.step),
410
+ candidates.filter(c => !c.isFlowComplete).map((c) => c.step),
379
411
  hasCompletionOption
380
412
  );
381
413
 
@@ -399,21 +431,21 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
399
431
 
400
432
  const selectedStepId = stepResult.structured?.selectedStepId;
401
433
 
402
- // Check if AI selected END_ROUTE
403
- if (selectedStepId === END_ROUTE_ID) {
434
+ // Check if AI selected flow completion
435
+ if (selectedStepId === '__COMPLETE__') {
404
436
  logger.debug(
405
- `[RoutingEngine] Single-route: AI selected END_ROUTE - completing route`
437
+ `[FlowRouter] Single-flow: AI selected flow completion`
406
438
  );
407
439
  logger.debug(
408
- `[RoutingEngine] Single-route: Reasoning: ${stepResult.structured?.reasoning}`
440
+ `[FlowRouter] Single-flow: Reasoning: ${stepResult.structured?.reasoning}`
409
441
  );
410
442
  return {
411
- selectedRoute,
443
+ selectedFlow,
412
444
  selectedStep: undefined,
413
445
  responseDirectives: stepResult.structured?.responseDirectives,
414
446
  session: updatedSession,
415
- isRouteComplete: true,
416
- completedRoutes,
447
+ isFlowComplete: true,
448
+ completedFlows,
417
449
  };
418
450
  }
419
451
 
@@ -421,28 +453,28 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
421
453
 
422
454
  if (selectedStep) {
423
455
  logger.debug(
424
- `[RoutingEngine] Single-route: AI selected step: ${selectedStep.step.id}`
456
+ `[FlowRouter] Single-flow: AI selected step: ${selectedStep.step.id}`
425
457
  );
426
458
  logger.debug(
427
- `[RoutingEngine] Single-route: Reasoning: ${stepResult.structured?.reasoning}`
459
+ `[FlowRouter] Single-flow: Reasoning: ${stepResult.structured?.reasoning}`
428
460
  );
429
461
  } else {
430
462
  logger.warn(
431
- `[RoutingEngine] Single-route: Invalid step ID returned, using first candidate`
463
+ `[FlowConfigurationError] Invalid step ID returned: AI router returned a step ID that does not match any candidate. Falling back to first candidate. Check flow step ids and router configuration.`
432
464
  );
433
465
  }
434
466
 
435
467
  return {
436
- selectedRoute,
468
+ selectedFlow,
437
469
  selectedStep: selectedStep?.step || candidates[0].step,
438
470
  responseDirectives: stepResult.structured?.responseDirectives,
439
471
  session: updatedSession,
440
- completedRoutes,
472
+ completedFlows,
441
473
  };
442
474
  }
443
475
 
444
476
  /**
445
- * Recursively traverse step chain to find first non-skipped step or END_ROUTE using new condition evaluation
477
+ * Recursively traverse step chain to find first non-skipped step using new condition evaluation
446
478
  * @private
447
479
  */
448
480
  private async findFirstValidStepRecursiveWithConditions(
@@ -451,7 +483,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
451
483
  visited: Set<string>
452
484
  ): Promise<{
453
485
  step?: Step<TContext, TData>;
454
- isRouteComplete?: boolean;
486
+ isFlowComplete?: boolean;
455
487
  aiContextStrings?: string[];
456
488
  }> {
457
489
  // Prevent infinite loops
@@ -463,39 +495,38 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
463
495
  const transitions = currentStep.getTransitions();
464
496
  const allAiContextStrings: string[] = [];
465
497
 
498
+ // No transitions means implicit terminus — flow is complete
499
+ if (transitions.length === 0) {
500
+ return {
501
+ isFlowComplete: true,
502
+ aiContextStrings: allAiContextStrings,
503
+ };
504
+ }
505
+
466
506
  for (const transition of transitions) {
467
507
  const target = transition;
468
508
 
469
- // Check for END_ROUTE transition
470
- if (target && target.id === END_ROUTE_ID) {
471
- // Found END_ROUTE - route is complete
472
- return {
473
- isRouteComplete: true,
474
- aiContextStrings: allAiContextStrings,
475
- };
476
- }
477
-
478
509
  if (!target) continue;
479
510
 
480
- // Evaluate skipIf condition using new system
481
- const skipResult = await target.evaluateSkipIf(templateContext);
511
+ // Evaluate skip condition (code-only, if-shape)
512
+ const skipResult = await target.evaluateSkip(templateContext);
482
513
  allAiContextStrings.push(...skipResult.aiContextStrings);
483
514
 
484
515
  // If target should NOT be skipped, we found our step
485
516
  if (!skipResult.shouldSkip) {
486
517
  logger.debug(
487
- `[RoutingEngine] Found valid step after skipping: ${target.id}`
518
+ `[FlowRouter] Found valid step after skipping: ${target.id}`
488
519
  );
489
520
  return {
490
521
  step: target,
491
- isRouteComplete: false,
522
+ isFlowComplete: false,
492
523
  aiContextStrings: allAiContextStrings,
493
524
  };
494
525
  }
495
526
 
496
527
  // Target should be skipped too - recurse deeper
497
528
  logger.debug(
498
- `[RoutingEngine] Skipping step ${target.id} (skipIf condition met), continuing traversal...`
529
+ `[FlowRouter] Skipping step ${target.id} (skipIf condition met), continuing traversal...`
499
530
  );
500
531
  const result = await this.findFirstValidStepRecursiveWithConditions(target, templateContext, visited);
501
532
 
@@ -504,8 +535,8 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
504
535
  allAiContextStrings.push(...result.aiContextStrings);
505
536
  }
506
537
 
507
- // If we found something (a valid step or END_ROUTE), return it
508
- if (result.step || result.isRouteComplete) {
538
+ // If we found something (a valid step or flow complete), return it
539
+ if (result.step || result.isFlowComplete) {
509
540
  return {
510
541
  ...result,
511
542
  aiContextStrings: allAiContextStrings,
@@ -513,101 +544,114 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
513
544
  }
514
545
  }
515
546
 
516
- // No valid steps or END_ROUTE found in this branch
517
- return { aiContextStrings: allAiContextStrings };
547
+ // No valid steps found in this branch — all skipped with no further transitions
548
+ return {
549
+ isFlowComplete: true,
550
+ aiContextStrings: allAiContextStrings,
551
+ };
518
552
  }
519
553
 
520
554
 
521
555
 
522
556
  /**
523
557
  * Identify valid next candidate steps using new condition evaluation system
524
- * Returns step with isRouteComplete flag if route is complete (all steps skipped + has END_ROUTE transition)
558
+ * Returns step with isFlowComplete flag if flow is complete (all steps skipped or no transitions remain)
525
559
  *
526
- * NEW: Automatically completes route when all required fields are collected
560
+ * Flow completion is implicit: when the last step has no transitions, the flow is done.
527
561
  */
528
562
  async getCandidateStepsWithConditions(
529
- route: Route<TContext, TData>,
563
+ route: Flow<TContext, TData>,
530
564
  currentStep: Step<TContext, TData> | undefined,
531
565
  templateContext: TemplateContext<TContext, TData>
532
566
  ): Promise<CandidateStep<TContext, TData>[]> {
533
567
  const candidates: CandidateStep<TContext, TData>[] = [];
534
568
 
535
569
  if (!currentStep) {
536
- // Entering route for the first time — always start the step flow
570
+ // Entering flow for the first time — always start the step flow
537
571
 
538
572
  const initialStep = route.initialStep;
539
- const skipResult = await initialStep.evaluateSkipIf(templateContext);
573
+ const skipResult = await initialStep.evaluateSkip(templateContext);
540
574
 
541
575
  if (skipResult.shouldSkip) {
542
- // Initial step should be skipped - recursively traverse to find first non-skipped step or END_ROUTE
576
+ // Initial step should be skipped - recursively traverse to find first non-skipped step
543
577
  const result = await this.findFirstValidStepRecursiveWithConditions(
544
578
  initialStep,
545
579
  templateContext,
546
580
  new Set<string>()
547
581
  );
548
582
 
549
- if (result.isRouteComplete) {
550
- // All steps are skipped and we reached END_ROUTE
583
+ if (result.isFlowComplete) {
584
+ // All steps are skipped and no transitions remain
551
585
  logger.debug(
552
- `[RoutingEngine] Route complete on entry: all steps skipped, END_ROUTE reached`
586
+ `[FlowRouter] Flow complete on entry: all steps skipped, no transitions remain`
553
587
  );
554
588
  candidates.push({
555
589
  step: initialStep,
556
- isRouteComplete: true,
590
+ isFlowComplete: true,
557
591
  });
558
592
  } else if (result.step) {
559
593
  // Found a non-skipped step
560
594
  candidates.push({
561
595
  step: result.step,
562
- isRouteComplete: result.isRouteComplete || false,
596
+ isFlowComplete: result.isFlowComplete || false,
563
597
  });
564
598
  }
565
599
  // If no step found and not complete, fall through to return empty candidates
566
600
  } else {
567
601
  candidates.push({
568
602
  step: initialStep,
569
- isRouteComplete: false,
603
+ isFlowComplete: false,
570
604
  });
571
605
  }
572
606
  return candidates;
573
607
  }
574
608
 
575
- // Continue normal step progression — routes complete via END_ROUTE, not via data collection
609
+ // Continue normal step progression — flows complete when last step has no transitions (implicit terminus)
576
610
  const transitions = currentStep.getTransitions();
577
- let hasEndRoute = false;
611
+
612
+ // No transitions means this is the last step — flow is complete
613
+ if (transitions.length === 0) {
614
+ logger.debug(
615
+ `[FlowRouter] Flow complete: current step has no transitions (implicit terminus)`
616
+ );
617
+ return [
618
+ {
619
+ step: currentStep,
620
+ isFlowComplete: true,
621
+ },
622
+ ];
623
+ }
578
624
 
579
625
  for (const transition of transitions) {
580
626
  const target = transition;
581
627
 
582
- // Check for END_ROUTE transition (no target step)
583
- if (target && target.id === END_ROUTE_ID) {
584
- hasEndRoute = true;
585
- continue;
586
- }
587
-
588
628
  if (!target) continue;
589
629
 
590
- const skipResult = await target.evaluateSkipIf(templateContext);
630
+ const skipResult = await target.evaluateSkip(templateContext);
591
631
 
592
632
  if (skipResult.shouldSkip) {
593
633
  logger.debug(
594
- `[RoutingEngine] Skipping step ${target.id} (skipIf condition met)`
634
+ `[FlowRouter] Skipping step ${target.id} (skip condition met)`
595
635
  );
596
636
 
597
- // Recursively traverse to find next valid step or END_ROUTE
637
+ // Recursively traverse to find next valid step
598
638
  const result = await this.findFirstValidStepRecursiveWithConditions(
599
639
  target,
600
640
  templateContext,
601
641
  new Set<string>([currentStep.id]) // Already visited current step
602
642
  );
603
643
 
604
- if (result.isRouteComplete) {
605
- hasEndRoute = true;
644
+ if (result.isFlowComplete) {
645
+ // All forward paths lead to terminus
646
+ candidates.push({
647
+ step: currentStep,
648
+ isFlowComplete: true,
649
+ });
606
650
  } else if (result.step) {
607
651
  // Found a non-skipped step deeper in the chain
608
652
  candidates.push({
609
653
  step: result.step,
610
- isRouteComplete: result.isRouteComplete || false,
654
+ isFlowComplete: false,
611
655
  });
612
656
  }
613
657
  continue;
@@ -615,34 +659,22 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
615
659
 
616
660
  candidates.push({
617
661
  step: target,
618
- isRouteComplete: hasEndRoute || false,
662
+ isFlowComplete: false,
619
663
  });
620
664
  }
621
665
 
622
- // If no valid candidates found
666
+ // If no valid candidates found after evaluating all transitions
623
667
  if (candidates.length === 0) {
624
- // If current step has END_ROUTE transition, the route is complete
625
- if (hasEndRoute) {
626
- logger.debug(
627
- `[RoutingEngine] Route complete: all steps processed, END_ROUTE reached`
628
- );
629
- // Return current step with completion flag
630
- return [
631
- {
632
- step: currentStep,
633
- isRouteComplete: true,
634
- },
635
- ];
636
- }
637
-
638
- // Otherwise, stay in current step if it's still valid
639
- const currentSkipResult = await currentStep.evaluateSkipIf(templateContext);
640
- if (!currentSkipResult.shouldSkip) {
641
- candidates.push({
668
+ // All transitions were skipped flow is complete
669
+ logger.debug(
670
+ `[FlowRouter] Flow complete: all transitions skipped`
671
+ );
672
+ return [
673
+ {
642
674
  step: currentStep,
643
- isRouteComplete: hasEndRoute || false,
644
- });
645
- }
675
+ isFlowComplete: true,
676
+ },
677
+ ];
646
678
  }
647
679
 
648
680
  return candidates;
@@ -650,13 +682,13 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
650
682
 
651
683
  /**
652
684
  * Full routing orchestration: builds prompt and schema, calls AI, selects route/step,
653
- * and updates the session (including initialData merge when entering a new route).
685
+ * and updates the session (including initialData merge when entering a new flow).
654
686
  *
655
687
  * OPTIMIZATION: If there's only 1 route, skips route scoring and only does step selection.
656
- * CROSS-ROUTE COMPLETION: Evaluates all routes for completion based on collected data.
688
+ * CROSS-FLOW COMPLETION: Evaluates all flows for completion based on collected data.
657
689
  */
658
- async decideRouteAndStep(params: {
659
- routes: Route<TContext, TData>[];
690
+ async decideFlowAndStep(params: {
691
+ flows: Flow<TContext, TData>[];
660
692
  session: SessionState<TData>;
661
693
  history: Event[];
662
694
  agentOptions?: AgentOptions<TContext, TData>;
@@ -664,15 +696,15 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
664
696
  context: TContext;
665
697
  signal?: AbortSignal;
666
698
  }): Promise<{
667
- selectedRoute?: Route<TContext, TData>;
699
+ selectedFlow?: Flow<TContext, TData>;
668
700
  selectedStep?: Step<TContext, TData>;
669
701
  responseDirectives?: string[];
670
702
  session: SessionState<TData>;
671
- isRouteComplete?: boolean;
672
- completedRoutes?: Route<TContext, TData>[];
703
+ isFlowComplete?: boolean;
704
+ completedFlows?: Flow<TContext, TData>[];
673
705
  }> {
674
706
  const {
675
- routes,
707
+ flows,
676
708
  session,
677
709
  history,
678
710
  agentOptions,
@@ -681,15 +713,15 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
681
713
  signal,
682
714
  } = params;
683
715
 
684
- if (routes.length === 0) {
716
+ if (flows.length === 0) {
685
717
  return { session };
686
718
  }
687
719
 
688
- // SESSION RESUME: If the session has a pre-set route and there are no user
720
+ // SESSION RESUME: If the session has a pre-set flow and there are no user
689
721
  // messages in the history, honor the pre-set position without AI routing.
690
722
  // This supports programmatic session setup and persistence-based resume.
691
723
  const resumeResult = await this.handleSessionResume({
692
- routes,
724
+ flows,
693
725
  session,
694
726
  history,
695
727
  context,
@@ -698,20 +730,33 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
698
730
  return resumeResult;
699
731
  }
700
732
 
701
- // CROSS-ROUTE COMPLETION EVALUATION: Check all routes for completion
702
- const completedRoutes = this.evaluateRouteCompletions(routes, session.data || {});
733
+ // Exclude flows that completed earlier in this session unless explicitly
734
+ // re-entrant. A completed flow surrenders the conversation back to
735
+ // routing — it cannot be re-selected without `flow.reentrant: true`.
736
+ const reEntryFiltered = flows.filter(
737
+ (f) => !isFlowCompletedThisSession(session, f.id) || f.reentrant === true
738
+ );
739
+ const excludedFlows = flows.length - reEntryFiltered.length;
740
+ if (excludedFlows > 0) {
741
+ logger.debug(
742
+ `[FlowRouter] Excluded ${excludedFlows} completed (non-reentrant) flow(s) from routing candidates`
743
+ );
744
+ }
745
+
746
+ // CROSS-FLOW COMPLETION EVALUATION: Check all eligible flows for completion
747
+ const completedFlows = this.evaluateFlowCompletions(reEntryFiltered, session.data || {});
703
748
 
704
- // Log completed routes
705
- if (completedRoutes.length > 0) {
749
+ // Log completed flows
750
+ if (completedFlows.length > 0) {
706
751
  logger.debug(
707
- `[RoutingEngine] Found ${completedRoutes.length} completed routes: ${completedRoutes.map(r => r.title).join(', ')}`
752
+ `[FlowRouter] Found ${completedFlows.length} completed routes: ${completedFlows.map(r => r.title).join(', ')}`
708
753
  );
709
754
  }
710
755
 
711
- // OPTIMIZATION: Single route - skip route scoring, only do step selection
712
- if (routes.length === 1) {
713
- const result = await this.decideSingleRouteStep({
714
- route: routes[0],
756
+ // OPTIMIZATION: Single flow - skip flow scoring, only do step selection
757
+ if (reEntryFiltered.length === 1) {
758
+ const result = await this.decideSingleFlowStep({
759
+ route: reEntryFiltered[0],
715
760
  session,
716
761
  history,
717
762
  agentOptions,
@@ -721,10 +766,19 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
721
766
  });
722
767
  return {
723
768
  ...result,
724
- completedRoutes,
769
+ completedFlows,
725
770
  };
726
771
  }
727
772
 
773
+ // No eligible flows after re-entry filtering — caller falls back to the
774
+ // generic non-flow response path.
775
+ if (reEntryFiltered.length === 0) {
776
+ logger.debug(
777
+ `[FlowRouter] All flows completed and none are reentrant — releasing session to fallback`
778
+ );
779
+ return { session, completedFlows };
780
+ }
781
+
728
782
  const lastUserMessage = getLastMessageFromHistory(history);
729
783
  const templateContext = createTemplateContext({
730
784
  context,
@@ -733,25 +787,24 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
733
787
  data: session.data
734
788
  });
735
789
 
736
- // Apply route filtering with new condition evaluation system
737
- const skipIfResult = await this.filterRoutesBySkipIf(routes, templateContext);
738
- const whenResult = await this.filterRoutesByWhen(skipIfResult.eligibleRoutes, templateContext);
790
+ // Apply flow filtering with new condition evaluation system
791
+ const whenResult = await this.filterFlowsByWhen(reEntryFiltered, templateContext);
739
792
 
740
- // Use filtered routes for further processing
793
+ // Use filtered flows for further processing
741
794
  const eligibleRoutes = whenResult.eligibleRoutes;
742
795
 
743
- logger.debug(`[RoutingEngine] Route filtering: ${routes.length} total → ${skipIfResult.eligibleRoutes.length} after skipIf → ${eligibleRoutes.length} after when`);
796
+ logger.debug(`[FlowRouter] Flow filtering: ${flows.length} total → ${reEntryFiltered.length} after re-entry filter → ${eligibleRoutes.length} after when`);
744
797
 
745
- let activeRouteSteps: Step<TContext, TData>[] | undefined;
746
- let activeRoute: Route<TContext, TData> | undefined;
747
- let isRouteComplete = false;
798
+ let activeFlowSteps: Step<TContext, TData>[] | undefined;
799
+ let activeFlow: Flow<TContext, TData> | undefined;
800
+ let isFlowComplete = false;
748
801
  let updatedSession = session;
749
802
 
750
- if (session.currentRoute) {
751
- activeRoute = eligibleRoutes.find((r) => r.id === session.currentRoute?.id);
752
- if (activeRoute) {
803
+ if (session.currentFlow) {
804
+ activeFlow = eligibleRoutes.find((r) => r.id === session.currentFlow?.id);
805
+ if (activeFlow) {
753
806
  const currentStep = session.currentStep
754
- ? activeRoute.getStep(session.currentStep.id)
807
+ ? activeFlow.getStep(session.currentStep.id)
755
808
  : undefined;
756
809
  const activeTemplateContext = createTemplateContext({
757
810
  ...templateContext,
@@ -759,55 +812,55 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
759
812
  data: updatedSession.data
760
813
  });
761
814
  const candidates = await this.getCandidateStepsWithConditions(
762
- activeRoute,
815
+ activeFlow,
763
816
  currentStep,
764
817
  activeTemplateContext
765
818
  );
766
819
 
767
- // Check if route is complete
820
+ // Check if flow is complete
768
821
  // getCandidateStepsWithConditions now automatically handles completion when required fields are collected
769
- if (candidates.length === 1 && candidates[0].isRouteComplete) {
770
- isRouteComplete = true;
822
+ if (candidates.length === 1 && candidates[0].isFlowComplete) {
823
+ isFlowComplete = true;
771
824
  logger.debug(
772
- `[RoutingEngine] Route ${activeRoute.title} is complete - all required fields collected or END_ROUTE reached`
825
+ `[FlowRouter] Flow ${activeFlow.title} is complete - all required fields collected or last step reached`
773
826
  );
774
827
  // Don't include steps in routing if route is complete
775
- activeRouteSteps = undefined;
828
+ activeFlowSteps = undefined;
776
829
  } else if (candidates.length === 0) {
777
- // No candidates available — don't end route based on data alone
830
+ // No candidates available — don't end flow based on data alone
778
831
  logger.debug(
779
- `[RoutingEngine] Route ${activeRoute.title} has no valid candidate steps`
832
+ `[FlowRouter] Flow ${activeFlow.title} has no valid candidate steps`
780
833
  );
781
- activeRouteSteps = undefined;
834
+ activeFlowSteps = undefined;
782
835
  } else {
783
836
  // Multiple candidates or single non-complete candidate
784
- activeRouteSteps = candidates.map((c) => c.step);
837
+ activeFlowSteps = candidates.map((c) => c.step);
785
838
  logger.debug(
786
- `[RoutingEngine] Found ${activeRouteSteps.length} candidate steps for active route`
839
+ `[FlowRouter] Found ${activeFlowSteps.length} candidate steps for active route`
787
840
  );
788
841
  }
789
842
  }
790
843
  }
791
844
 
792
- const routingSchema = this.buildDynamicRoutingSchema(
845
+ const routingSchema = this.buildDynamicFlowSchema(
793
846
  eligibleRoutes,
794
847
  undefined,
795
- activeRouteSteps
848
+ activeFlowSteps
796
849
  );
797
850
 
798
851
  const routingPrompt = await this.buildRoutingPrompt({
799
852
  history,
800
- routes: eligibleRoutes,
853
+ flows: eligibleRoutes,
801
854
  lastMessage: lastUserMessage,
802
855
  agentOptions,
803
856
  session,
804
- activeRouteSteps,
857
+ activeFlowSteps,
805
858
  context,
806
859
  });
807
860
 
808
861
  const routingResult = await provider.generateMessage<
809
862
  TContext,
810
- RoutingDecisionOutput
863
+ FlowRoutingDecisionOutput
811
864
  >({
812
865
  prompt: routingPrompt,
813
866
  history: eventsToHistory(history),
@@ -819,122 +872,89 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
819
872
  },
820
873
  });
821
874
 
822
- let selectedRoute: Route<TContext, TData> | undefined;
875
+ let selectedFlow: Flow<TContext, TData> | undefined;
823
876
  let selectedStep: Step<TContext, TData> | undefined;
824
877
  let responseDirectives: string[] | undefined;
825
878
 
826
- if (routingResult.structured?.routes) {
827
- // Use cross-route completion evaluation to select optimal route
828
- const optimalRoute = this.selectOptimalRoute(
879
+ if (routingResult.structured?.flows) {
880
+ // Use cross-flow completion evaluation to select optimal flow
881
+ const optimalRoute = this.selectOptimalFlow(
829
882
  eligibleRoutes,
830
883
  updatedSession.data || {},
831
- routingResult.structured.routes,
832
- updatedSession.currentRoute?.id
884
+ routingResult.structured.flows,
885
+ updatedSession.currentFlow?.id
833
886
  );
834
887
 
835
- // If no optimal route found, check why
888
+ // If no optimal flow found, check why
836
889
  if (!optimalRoute) {
837
890
  if (eligibleRoutes.length === 0) {
838
- // No routes passed filtering
891
+ // No flows passed filtering
839
892
  logger.debug(
840
- `[RoutingEngine] No eligible routes available - all routes filtered out`
893
+ `[FlowRouter] No eligible flows available - all flows filtered out`
841
894
  );
842
- selectedRoute = undefined;
895
+ selectedFlow = undefined;
843
896
  } else {
844
- // Routes exist but selectOptimalRoute returned undefined
845
- // This means all routes are 100% complete
897
+ // Routes exist but selectOptimalFlow returned undefined
898
+ // This means all flows are 100% complete
846
899
  logger.debug(
847
- `[RoutingEngine] No optimal route found - all ${eligibleRoutes.length} eligible routes are complete`
900
+ `[FlowRouter] No optimal route found - all ${eligibleRoutes.length} eligible routes are complete`
848
901
  );
849
- selectedRoute = undefined;
902
+ selectedFlow = undefined;
850
903
  }
851
904
  } else {
852
- selectedRoute = optimalRoute;
905
+ selectedFlow = optimalRoute;
853
906
  }
854
907
 
855
908
  responseDirectives = routingResult.structured.responseDirectives;
856
909
 
857
910
  if (
858
- selectedRoute === activeRoute &&
911
+ selectedFlow === activeFlow &&
859
912
  routingResult.structured.selectedStepId &&
860
- activeRoute
913
+ activeFlow
861
914
  ) {
862
- selectedStep = activeRoute.getStep(
915
+ selectedStep = activeFlow.getStep(
863
916
  routingResult.structured.selectedStepId
864
917
  );
865
918
  if (selectedStep) {
866
919
  logger.debug(
867
- `[RoutingEngine] AI selected step: ${selectedStep.id} in active route`
920
+ `[FlowRouter] AI selected step: ${selectedStep.id} in active route`
868
921
  );
869
922
  logger.debug(
870
- `[RoutingEngine] Step reasoning: ${routingResult.structured.stepReasoning}`
923
+ `[FlowRouter] Step reasoning: ${routingResult.structured.stepReasoning}`
871
924
  );
872
925
  }
873
926
  }
874
927
 
875
- if (selectedRoute) {
876
- logger.debug(`[RoutingEngine] Selected route: ${selectedRoute.title}`);
877
- updatedSession = this.enterRouteIfNeeded(updatedSession, selectedRoute);
928
+ if (selectedFlow) {
929
+ logger.debug(`[FlowRouter] Selected route: ${selectedFlow.title}`);
930
+ updatedSession = this.enterFlowIfNeeded(updatedSession, selectedFlow);
878
931
  }
879
932
  }
880
933
 
881
934
  return {
882
- selectedRoute,
935
+ selectedFlow,
883
936
  selectedStep,
884
937
  responseDirectives,
885
938
  session: updatedSession,
886
- isRouteComplete,
887
- completedRoutes,
939
+ isFlowComplete,
940
+ completedFlows,
888
941
  };
889
942
  }
890
943
 
891
944
  /**
892
- * Filter routes based on skipIf conditions
893
- * @param routes - All available routes
945
+ * Filter flows based on when conditions
946
+ * @param routes - Flows that passed skipIf filtering
894
947
  * @param templateContext - Context for condition evaluation
895
- * @returns Object with eligible routes and collected AI context strings
948
+ * @returns Object with eligible flows and collected AI context strings
896
949
  */
897
- async filterRoutesBySkipIf(
898
- routes: Route<TContext, TData>[],
950
+ async filterFlowsByWhen(
951
+ routes: Flow<TContext, TData>[],
899
952
  templateContext: TemplateContext<TContext, TData>
900
953
  ): Promise<{
901
- eligibleRoutes: Route<TContext, TData>[];
954
+ eligibleRoutes: Flow<TContext, TData>[];
902
955
  aiContextStrings: string[];
903
956
  }> {
904
- const eligibleRoutes: Route<TContext, TData>[] = [];
905
- const aiContextStrings: string[] = [];
906
-
907
- for (const route of routes) {
908
- const skipResult = await route.evaluateSkipIf(templateContext);
909
-
910
- // Collect AI context strings from skipIf conditions
911
- aiContextStrings.push(...skipResult.aiContextStrings);
912
-
913
- // If route should not be skipped, it's eligible
914
- if (!skipResult.programmaticResult) {
915
- eligibleRoutes.push(route);
916
- } else {
917
- logger.debug(`[RoutingEngine] Skipping route ${route.title} (skipIf condition met)`);
918
- }
919
- }
920
-
921
- return { eligibleRoutes, aiContextStrings };
922
- }
923
-
924
- /**
925
- * Filter routes based on when conditions
926
- * @param routes - Routes that passed skipIf filtering
927
- * @param templateContext - Context for condition evaluation
928
- * @returns Object with eligible routes and collected AI context strings
929
- */
930
- async filterRoutesByWhen(
931
- routes: Route<TContext, TData>[],
932
- templateContext: TemplateContext<TContext, TData>
933
- ): Promise<{
934
- eligibleRoutes: Route<TContext, TData>[];
935
- aiContextStrings: string[];
936
- }> {
937
- const eligibleRoutes: Route<TContext, TData>[] = [];
957
+ const eligibleRoutes: Flow<TContext, TData>[] = [];
938
958
  const aiContextStrings: string[] = [];
939
959
 
940
960
  for (const route of routes) {
@@ -943,11 +963,11 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
943
963
  // Collect AI context strings from when conditions
944
964
  aiContextStrings.push(...whenResult.aiContextStrings);
945
965
 
946
- // If route has no programmatic conditions or they evaluate to true, it's eligible
966
+ // If flow has no programmatic conditions or they evaluate to true, it's eligible
947
967
  if (!whenResult.hasProgrammaticConditions || whenResult.programmaticResult) {
948
968
  eligibleRoutes.push(route);
949
969
  } else {
950
- logger.debug(`[RoutingEngine] Route ${route.title} not eligible (when condition not met)`);
970
+ logger.debug(`[FlowRouter] Flow ${route.title} not eligible (when condition not met)`);
951
971
  }
952
972
  }
953
973
 
@@ -955,22 +975,22 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
955
975
  }
956
976
 
957
977
  /**
958
- * Evaluate all routes for completion based on collected data
959
- * @param routes - All available routes
978
+ * Evaluate all flows for completion based on collected data
979
+ * @param routes - All available flows
960
980
  * @param data - Currently collected agent-level data
961
- * @returns Array of routes that are complete
981
+ * @returns Array of flows that are complete
962
982
  */
963
- evaluateRouteCompletions(routes: Route<TContext, TData>[], data: Partial<TData>): Route<TContext, TData>[] {
983
+ evaluateFlowCompletions(routes: Flow<TContext, TData>[], data: Partial<TData>): Flow<TContext, TData>[] {
964
984
  return routes.filter(route => route.isComplete(data));
965
985
  }
966
986
 
967
987
  /**
968
- * Get completion status for all routes
969
- * @param routes - All available routes
988
+ * Get completion status for all flows
989
+ * @param routes - All available flows
970
990
  * @param data - Currently collected agent-level data
971
- * @returns Map of route ID to completion progress (0-1)
991
+ * @returns Map of flow ID to completion progress (0-1)
972
992
  */
973
- getRouteCompletionStatus(routes: Route<TContext, TData>[], data: Partial<TData>): Map<string, number> {
993
+ getFlowCompletionStatus(routes: Flow<TContext, TData>[], data: Partial<TData>): Map<string, number> {
974
994
  const completionStatus = new Map<string, number>();
975
995
 
976
996
  for (const route of routes) {
@@ -982,39 +1002,39 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
982
1002
  }
983
1003
 
984
1004
  /**
985
- * Find the best route to continue based on completion status and user intent
986
- * Prioritizes routes that are partially complete but not finished
987
- * IMPORTANT: Completed routes are excluded to prevent re-entering finished tasks
988
- * @param routes - All available routes
1005
+ * Find the best flow to continue based on completion status and user intent
1006
+ * Prioritizes flows that are partially complete but not finished
1007
+ * IMPORTANT: Completed flows are excluded to prevent re-entering finished tasks
1008
+ * @param routes - All available flows
989
1009
  * @param data - Currently collected agent-level data
990
1010
  * @param routeScores - AI-generated route scores from routing decision
991
- * @returns Route that should be prioritized for continuation
1011
+ * @returns Flow that should be prioritized for continuation
992
1012
  */
993
- selectOptimalRoute(
994
- routes: Route<TContext, TData>[],
1013
+ selectOptimalFlow(
1014
+ routes: Flow<TContext, TData>[],
995
1015
  data: Partial<TData>,
996
1016
  routeScores: Record<string, number>,
997
1017
  currentRouteId?: string
998
- ): Route<TContext, TData> | undefined {
999
- const completionStatus = this.getRouteCompletionStatus(routes, data);
1000
- const switchMargin = this.options?.routeSwitchMargin ?? 15;
1018
+ ): Flow<TContext, TData> | undefined {
1019
+ const completionStatus = this.getFlowCompletionStatus(routes, data);
1020
+ const switchMargin = this.options?.flowSwitchMargin ?? 15;
1001
1021
 
1002
1022
  // Create weighted scores combining AI intent scores with completion progress
1003
- const weightedScores: Array<{ route: Route<TContext, TData>; score: number }> = [];
1023
+ const weightedScores: Array<{ route: Flow<TContext, TData>; score: number }> = [];
1004
1024
 
1005
1025
  for (const route of routes) {
1006
1026
  const aiScore = routeScores[route.id] || 0;
1007
1027
  const completionProgress = completionStatus.get(route.id) || 0;
1008
1028
 
1009
- // ALWAYS skip fully completed routes to prevent re-entering finished tasks
1029
+ // ALWAYS skip fully completed flows to prevent re-entering finished tasks
1010
1030
  if (completionProgress >= 1.0) {
1011
1031
  logger.debug(
1012
- `[RoutingEngine] Excluding completed route: ${route.title} (100% complete)`
1032
+ `[FlowRouter] Excluding completed flow: ${route.title} (100% complete)`
1013
1033
  );
1014
1034
  continue;
1015
1035
  }
1016
1036
 
1017
- // Boost partially complete routes that match user intent
1037
+ // Boost partially complete flows that match user intent
1018
1038
  let weightedScore = aiScore;
1019
1039
  if (completionProgress > 0 && completionProgress < 1.0) {
1020
1040
  weightedScore += (completionProgress * 20); // Up to 20 point boost
@@ -1031,7 +1051,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1031
1051
  }
1032
1052
 
1033
1053
  // Apply sticky routing: if there's a current route, only switch if the
1034
- // best alternative exceeds the current route's score by the configured margin
1054
+ // best alternative exceeds the current flow's score by the configured margin
1035
1055
  if (currentRouteId) {
1036
1056
  const currentEntry = weightedScores.find(e => e.route.id === currentRouteId);
1037
1057
  const bestEntry = weightedScores[0];
@@ -1039,14 +1059,14 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1039
1059
  if (currentEntry && bestEntry.route.id !== currentRouteId) {
1040
1060
  if (bestEntry.score < currentEntry.score + switchMargin) {
1041
1061
  logger.debug(
1042
- `[RoutingEngine] Staying on current route: ${currentEntry.route.title} ` +
1062
+ `[FlowRouter] Staying on current flow: ${currentEntry.route.title} ` +
1043
1063
  `(current: ${currentEntry.score}, best alternative: ${bestEntry.score}, ` +
1044
1064
  `margin required: ${switchMargin})`
1045
1065
  );
1046
1066
  return currentEntry.route;
1047
1067
  }
1048
1068
  logger.debug(
1049
- `[RoutingEngine] Switching route: ${currentEntry.route.title} → ${bestEntry.route.title} ` +
1069
+ `[FlowRouter] Switching flow: ${currentEntry.route.title} → ${bestEntry.route.title} ` +
1050
1070
  `(current: ${currentEntry.score}, alternative: ${bestEntry.score}, ` +
1051
1071
  `margin: ${switchMargin})`
1052
1072
  );
@@ -1054,7 +1074,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1054
1074
  }
1055
1075
 
1056
1076
  logger.debug(
1057
- `[RoutingEngine] Selected optimal route: ${weightedScores[0].route.title} ` +
1077
+ `[FlowRouter] Selected optimal route: ${weightedScores[0].route.title} ` +
1058
1078
  `(AI: ${routeScores[weightedScores[0].route.id]}, ` +
1059
1079
  `Completion: ${(completionStatus.get(weightedScores[0].route.id) || 0) * 100}%, ` +
1060
1080
  `Weighted: ${weightedScores[0].score})`
@@ -1063,14 +1083,14 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1063
1083
  }
1064
1084
 
1065
1085
  /**
1066
- * Build prompt for step selection within a single route
1086
+ * Build prompt for step selection within a single flow
1067
1087
  * @private
1068
1088
  */
1069
1089
  private async buildStepSelectionPrompt(
1070
- params: BuildStepSelectionPromptParams<TContext, TData> & { includeEndRoute?: boolean }
1090
+ params: BuildStepSelectionPromptParams<TContext, TData> & { includeCompletion?: boolean }
1071
1091
  ): Promise<string> {
1072
1092
  const {
1073
- route,
1093
+ flow: route,
1074
1094
  currentStep,
1075
1095
  candidates,
1076
1096
  data,
@@ -1080,7 +1100,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1080
1100
  context,
1081
1101
  session,
1082
1102
  stepConditionContext,
1083
- includeEndRoute = false,
1103
+ includeCompletion = false,
1084
1104
  } = params;
1085
1105
  const templateContext = createTemplateContext({ context, session, history });
1086
1106
  const pc = new PromptComposer<TContext, TData>(templateContext, this.options?.promptSectionCache);
@@ -1090,9 +1110,9 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1090
1110
  await pc.addAgentMeta(agentOptions);
1091
1111
  }
1092
1112
 
1093
- // Add route context
1113
+ // Add flow context
1094
1114
  await pc.addInstruction(
1095
- `Active Route: ${route.title}\nDescription: ${route.description || "N/A"}`
1115
+ `Active Flow: ${route.title}\nDescription: ${route.description || "N/A"}`
1096
1116
  );
1097
1117
 
1098
1118
  // Add current step context
@@ -1102,7 +1122,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1102
1122
  }`
1103
1123
  );
1104
1124
  } else {
1105
- await pc.addInstruction("Current Step: None (entering route)");
1125
+ await pc.addInstruction("Current Step: None (entering flow)");
1106
1126
  }
1107
1127
 
1108
1128
  // Add collected data context
@@ -1181,10 +1201,10 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1181
1201
  "- Steps with skipIf conditions that are met have already been filtered out",
1182
1202
  ];
1183
1203
 
1184
- if (includeEndRoute) {
1204
+ if (includeCompletion) {
1185
1205
  decisionRules.push(
1186
1206
  "",
1187
- `- You can select '${END_ROUTE_ID}' to complete this route if:`,
1207
+ `- You can select '__COMPLETE__' to complete this flow if:`,
1188
1208
  " * All required data has been collected",
1189
1209
  " * The user's intent suggests they're done with this task",
1190
1210
  " * No further steps are needed to fulfill the user's request"
@@ -1207,13 +1227,13 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1207
1227
  */
1208
1228
  private buildStepSelectionSchema(
1209
1229
  validSteps: Step<TContext, TData>[],
1210
- includeEndRoute: boolean = false
1230
+ includeCompletion: boolean = false
1211
1231
  ): StructuredSchema {
1212
1232
  const stepIds = validSteps.map((s) => s.id);
1213
1233
 
1214
- // Add END_ROUTE as an option if requested (when required fields are complete)
1215
- if (includeEndRoute) {
1216
- stepIds.push(END_ROUTE_ID);
1234
+ // Add completion option if requested (when required fields are complete)
1235
+ if (includeCompletion) {
1236
+ stepIds.push('__COMPLETE__');
1217
1237
  }
1218
1238
 
1219
1239
  return {
@@ -1229,8 +1249,8 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1229
1249
  selectedStepId: {
1230
1250
  type: "string",
1231
1251
  nullable: false,
1232
- description: includeEndRoute
1233
- ? `The ID of the selected step to transition to, or '${END_ROUTE_ID}' to complete the route`
1252
+ description: includeCompletion
1253
+ ? "The ID of the selected step to transition to, or '__COMPLETE__' to complete the flow"
1234
1254
  : "The ID of the selected step to transition to",
1235
1255
  enum: stepIds,
1236
1256
  },
@@ -1246,10 +1266,10 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1246
1266
  };
1247
1267
  }
1248
1268
 
1249
- buildDynamicRoutingSchema(
1250
- routes: Route<TContext, TData>[],
1269
+ buildDynamicFlowSchema(
1270
+ routes: Flow<TContext, TData>[],
1251
1271
  extrasSchema?: StructuredSchema,
1252
- activeRouteSteps?: Step<TContext, TData>[]
1272
+ activeFlowSteps?: Step<TContext, TData>[]
1253
1273
  ): StructuredSchema {
1254
1274
  const routeIds = routes.map((r) => r.id);
1255
1275
  const routeProperties: Record<string, StructuredSchema> = {};
@@ -1257,7 +1277,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1257
1277
  routeProperties[id] = {
1258
1278
  type: "number",
1259
1279
  nullable: false,
1260
- description: `Score for route ${id} based on direct evidence, context and semantic fit (0-100)`,
1280
+ description: `Score for flow ${id} based on direct evidence, context and semantic fit (0-100)`,
1261
1281
  minimum: 0,
1262
1282
  maximum: 100,
1263
1283
  } as StructuredSchema;
@@ -1265,7 +1285,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1265
1285
 
1266
1286
  const base: StructuredSchema = {
1267
1287
  description:
1268
- "Full intent analysis: score ALL available routes (0-100) using evidence and context",
1288
+ "Full intent analysis: score ALL available flows (0-100) using evidence and context",
1269
1289
  type: "object",
1270
1290
  properties: {
1271
1291
  context: {
@@ -1273,12 +1293,12 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1273
1293
  nullable: false,
1274
1294
  description: "Brief summary of the user's intent/context",
1275
1295
  },
1276
- routes: {
1296
+ flows: {
1277
1297
  type: "object",
1278
1298
  properties: routeProperties,
1279
1299
  required: routeIds,
1280
1300
  nullable: false,
1281
- description: "Mapping of routeId to score (0-100)",
1301
+ description: "Mapping of flowId to score (0-100)",
1282
1302
  },
1283
1303
  responseDirectives: {
1284
1304
  type: "array",
@@ -1287,19 +1307,19 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1287
1307
  "Optional bullet points the response should address (concise)",
1288
1308
  },
1289
1309
  },
1290
- required: ["context", "routes"],
1310
+ required: ["context", "flows"],
1291
1311
  additionalProperties: false,
1292
1312
  };
1293
1313
 
1294
- // Add step selection fields if there's an active route with steps
1295
- if (activeRouteSteps && activeRouteSteps.length > 0) {
1314
+ // Add step selection fields if there's an active flow with steps
1315
+ if (activeFlowSteps && activeFlowSteps.length > 0) {
1296
1316
  base.properties = base.properties || {};
1297
1317
  base.properties.selectedStepId = {
1298
1318
  type: "string",
1299
1319
  nullable: false,
1300
1320
  description:
1301
- "The step ID to transition to within the active route (required if continuing in current route)",
1302
- enum: activeRouteSteps.map((s) => s.id),
1321
+ "The step ID to transition to within the active flow (required if continuing in current flow)",
1322
+ enum: activeFlowSteps.map((s) => s.id),
1303
1323
  };
1304
1324
  base.properties.stepReasoning = {
1305
1325
  type: "string",
@@ -1326,11 +1346,11 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1326
1346
  ): Promise<string> {
1327
1347
  const {
1328
1348
  history,
1329
- routes,
1349
+ flows: routes,
1330
1350
  lastMessage,
1331
1351
  agentOptions,
1332
1352
  session,
1333
- activeRouteSteps,
1353
+ activeFlowSteps,
1334
1354
  context,
1335
1355
  } = params;
1336
1356
  const templateContext = createTemplateContext({ context, session, history });
@@ -1343,10 +1363,10 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1343
1363
  );
1344
1364
 
1345
1365
  // Add session context if available
1346
- if (session?.currentRoute) {
1366
+ if (session?.currentFlow) {
1347
1367
  const sessionInfo = [
1348
1368
  "Current conversation context:",
1349
- `- Active route: ${session.currentRoute.title} (${session.currentRoute.id})`,
1369
+ `- Active route: ${session.currentFlow.title} (${session.currentFlow.id})`,
1350
1370
  ];
1351
1371
  if (session.currentStep) {
1352
1372
  sessionInfo.push(`- Current step: ${session.currentStep.id}`);
@@ -1363,18 +1383,18 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1363
1383
  await pc.addInstruction(sessionInfo.join("\n"));
1364
1384
 
1365
1385
  // Add cross-route completion status
1366
- const completionStatus = this.getRouteCompletionStatus(routes, session.data || {});
1367
- const completedRoutes = this.evaluateRouteCompletions(routes, session.data || {});
1386
+ const completionStatus = this.getFlowCompletionStatus(routes, session.data || {});
1387
+ const completedFlows = this.evaluateFlowCompletions(routes, session.data || {});
1368
1388
 
1369
1389
  if (completionStatus.size > 0) {
1370
1390
  const statusInfo = [
1371
1391
  "",
1372
- "Route completion status based on collected data:",
1392
+ "Flow completion status based on collected data:",
1373
1393
  ];
1374
1394
 
1375
1395
  for (const route of routes) {
1376
1396
  const progress = completionStatus.get(route.id) || 0;
1377
- const isComplete = completedRoutes.includes(route);
1397
+ const isComplete = completedFlows.includes(route);
1378
1398
  const progressPercent = Math.round(progress * 100);
1379
1399
 
1380
1400
  statusInfo.push(
@@ -1398,15 +1418,15 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1398
1418
  }
1399
1419
 
1400
1420
  // Add available steps for the active route
1401
- if (activeRouteSteps && activeRouteSteps.length > 0) {
1421
+ if (activeFlowSteps && activeFlowSteps.length > 0) {
1402
1422
  const stepInfo = [
1403
1423
  "",
1404
1424
  "Available steps in active route (choose one to transition to):",
1405
1425
  ];
1406
1426
  const activeStepConditionContext: string[] = [];
1407
1427
 
1408
- for (const step of activeRouteSteps) {
1409
- const idx = activeRouteSteps.indexOf(step);
1428
+ for (const step of activeFlowSteps) {
1429
+ const idx = activeFlowSteps.indexOf(step);
1410
1430
  stepInfo.push(`${idx + 1}. Step: ${step.id}`);
1411
1431
  if (step.description) {
1412
1432
  stepInfo.push(` Description: ${step.description}`);
@@ -1457,7 +1477,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
1457
1477
 
1458
1478
  await pc.addInteractionHistory(history);
1459
1479
  await pc.addLastMessage(lastMessage);
1460
- await pc.addRoutingOverview(routes);
1480
+ await pc.addFlowOverview(routes);
1461
1481
 
1462
1482
  await pc.addInstruction(
1463
1483
  [