@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
@@ -1,18 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RoutingEngine = void 0;
3
+ exports.FlowRouter = void 0;
4
4
  const types_1 = require("../types");
5
5
  const utils_1 = require("../utils");
6
6
  const PromptComposer_1 = require("./PromptComposer");
7
- const constants_1 = require("../constants");
8
7
  const utils_2 = require("../utils");
9
- class RoutingEngine {
8
+ class FlowRouter {
10
9
  constructor(options) {
11
10
  this.options = options;
12
11
  }
13
12
  /**
14
13
  * Check whether the history contains any user messages.
15
- * Used to detect "session resume" scenarios where a route/step was
14
+ * Used to detect "session resume" scenarios where a flow/step was
16
15
  * pre-set programmatically and the conversation starts with only
17
16
  * system messages (or no messages at all).
18
17
  * @private
@@ -22,46 +21,46 @@ class RoutingEngine {
22
21
  }
23
22
  /**
24
23
  * Handle the "session resume" fast-path: when a session already has a
25
- * pre-set currentRoute (and optionally currentStep) and the conversation
24
+ * pre-set currentFlow (and optionally currentStep) and the conversation
26
25
  * history contains no user messages, honor the pre-set position instead
27
- * of running AI route/step selection.
26
+ * of running AI flow/step selection.
28
27
  *
29
28
  * Returns `undefined` when the fast-path does not apply.
30
29
  * @private
31
30
  */
32
31
  async handleSessionResume(params) {
33
- const { routes, session, history, context } = params;
32
+ const { flows, session, history, context } = params;
34
33
  // Fast-path only applies when:
35
- // 1. Session already has a currentRoute set
34
+ // 1. Session already has a currentFlow set
36
35
  // 2. There are no user messages in the history (system-only or empty)
37
- if (!session.currentRoute || this.hasUserMessages(history)) {
36
+ if (!session.currentFlow || this.hasUserMessages(history)) {
38
37
  return undefined;
39
38
  }
40
- // Find the pre-set route among available routes
41
- const presetRoute = routes.find((r) => r.id === session.currentRoute.id);
42
- if (!presetRoute) {
43
- utils_2.logger.warn(`[RoutingEngine] Session resume: pre-set route '${session.currentRoute.id}' not found among available routes, falling back to normal routing`);
39
+ // Find the pre-set flow among available flows
40
+ const presetFlow = flows.find((r) => r.id === session.currentFlow.id);
41
+ if (!presetFlow) {
42
+ utils_2.logger.warn(`[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.`);
44
43
  return undefined;
45
44
  }
46
- utils_2.logger.debug(`[RoutingEngine] Session resume: honoring pre-set route '${presetRoute.title}' (no user messages in history)`);
47
- // Enter route if needed (merges initialData, no-op if already entered)
48
- const updatedSession = this.enterRouteIfNeeded(session, presetRoute);
49
- // Evaluate cross-route completions
50
- const completedRoutes = this.evaluateRouteCompletions(routes, updatedSession.data || {});
45
+ utils_2.logger.debug(`[FlowRouter] Session resume: honoring pre-set flow '${presetFlow.title}' (no user messages in history)`);
46
+ // Enter flow if needed (merges initialData, no-op if already entered)
47
+ const updatedSession = this.enterFlowIfNeeded(session, presetFlow);
48
+ // Evaluate cross-flow completions
49
+ const completedFlows = this.evaluateFlowCompletions(flows, updatedSession.data || {});
51
50
  // If a currentStep is also pre-set, honor it — stay on that step
52
51
  if (session.currentStep) {
53
- const presetStep = presetRoute.getStep(session.currentStep.id);
52
+ const presetStep = presetFlow.getStep(session.currentStep.id);
54
53
  if (presetStep) {
55
- utils_2.logger.debug(`[RoutingEngine] Session resume: honoring pre-set step '${presetStep.id}'`);
54
+ utils_2.logger.debug(`[FlowRouter] Session resume: honoring pre-set step '${presetStep.id}'`);
56
55
  return {
57
- selectedRoute: presetRoute,
56
+ selectedFlow: presetFlow,
58
57
  selectedStep: presetStep,
59
58
  session: updatedSession,
60
- isRouteComplete: false,
61
- completedRoutes,
59
+ isFlowComplete: false,
60
+ completedFlows,
62
61
  };
63
62
  }
64
- utils_2.logger.warn(`[RoutingEngine] Session resume: pre-set step '${session.currentStep.id}' not found in route '${presetRoute.title}', resolving from initial step`);
63
+ utils_2.logger.warn(`[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.`);
65
64
  }
66
65
  // No currentStep pre-set (or it wasn't found) — resolve from initialStep
67
66
  // using the standard candidate logic (handles skipIf, etc.)
@@ -71,67 +70,97 @@ class RoutingEngine {
71
70
  history,
72
71
  data: updatedSession.data,
73
72
  });
74
- const candidates = await this.getCandidateStepsWithConditions(presetRoute, undefined, // No current step — start from beginning
73
+ const candidates = await this.getCandidateStepsWithConditions(presetFlow, undefined, // No current step — start from beginning
75
74
  templateContext);
76
75
  if (candidates.length === 0) {
77
- utils_2.logger.warn(`[RoutingEngine] Session resume: no valid steps found for route '${presetRoute.title}'`);
76
+ utils_2.logger.warn(`[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.`);
78
77
  return {
79
- selectedRoute: presetRoute,
78
+ selectedFlow: presetFlow,
80
79
  selectedStep: undefined,
81
80
  session: updatedSession,
82
- isRouteComplete: false,
83
- completedRoutes,
81
+ isFlowComplete: false,
82
+ completedFlows,
84
83
  };
85
84
  }
86
85
  const candidate = candidates[0];
87
- if (candidate.isRouteComplete) {
88
- utils_2.logger.debug(`[RoutingEngine] Session resume: route '${presetRoute.title}' is already complete`);
86
+ if (candidate.isFlowComplete) {
87
+ utils_2.logger.debug(`[FlowRouter] Session resume: flow '${presetFlow.title}' is already complete`);
89
88
  return {
90
- selectedRoute: presetRoute,
89
+ selectedFlow: presetFlow,
91
90
  selectedStep: undefined,
92
91
  session: updatedSession,
93
- isRouteComplete: true,
94
- completedRoutes,
92
+ isFlowComplete: true,
93
+ completedFlows,
95
94
  };
96
95
  }
97
- utils_2.logger.debug(`[RoutingEngine] Session resume: resolved initial step '${candidate.step.id}'`);
96
+ utils_2.logger.debug(`[FlowRouter] Session resume: resolved initial step '${candidate.step.id}'`);
98
97
  return {
99
- selectedRoute: presetRoute,
98
+ selectedFlow: presetFlow,
100
99
  selectedStep: candidate.step,
101
100
  session: updatedSession,
102
- isRouteComplete: false,
103
- completedRoutes,
101
+ isFlowComplete: false,
102
+ completedFlows,
104
103
  };
105
104
  }
106
105
  /**
107
- * Enter a route if not already in it, merging initial data
106
+ * Enter a flow if not already in it, merging initial data.
107
+ *
108
+ * When the flow is `reentrant` and was previously completed in this
109
+ * session, clears every field declared in the flow's `requiredFields`
110
+ * and `optionalFields` before entering — so the flow starts fresh from
111
+ * its initial step instead of being instantly marked complete by stale
112
+ * data. Fields not owned by this flow are preserved.
113
+ *
108
114
  * @private
109
115
  */
110
- enterRouteIfNeeded(session, route) {
111
- if (!session.currentRoute || session.currentRoute.id !== route.id) {
112
- let updatedSession = (0, utils_1.enterRoute)(session, route.id, route.title);
116
+ enterFlowIfNeeded(session, route) {
117
+ if (!session.currentFlow || session.currentFlow.id !== route.id) {
118
+ let workingSession = session;
119
+ // Re-entry into a `reentrant` flow that previously completed:
120
+ // clear owned fields so completion logic doesn't short-circuit on
121
+ // stale data from the prior run.
122
+ const previouslyCompleted = (0, utils_1.isFlowCompletedThisSession)(session, route.id);
123
+ if (previouslyCompleted && route.reentrant) {
124
+ const ownedFields = [
125
+ ...(route.requiredFields ?? []),
126
+ ...(route.optionalFields ?? []),
127
+ ];
128
+ if (ownedFields.length > 0) {
129
+ const owned = new Set(ownedFields);
130
+ const filtered = {};
131
+ for (const key of Object.keys(session.data ?? {})) {
132
+ if (!owned.has(key)) {
133
+ filtered[key] =
134
+ session.data[key];
135
+ }
136
+ }
137
+ workingSession = { ...session, data: filtered };
138
+ utils_2.logger.debug(`[FlowRouter] Re-entering reentrant flow ${route.title}: cleared ${ownedFields.length} owned field(s)`);
139
+ }
140
+ }
141
+ let updatedSession = (0, utils_1.enterFlow)(workingSession, route.id, route.title);
113
142
  if (route.initialData) {
114
143
  updatedSession = (0, utils_1.mergeCollected)(updatedSession, route.initialData);
115
- utils_2.logger.debug(`[RoutingEngine] Merged initial data for route ${route.title}:`, route.initialData);
144
+ utils_2.logger.debug(`[FlowRouter] Merged initial data for flow ${route.title}:`, route.initialData);
116
145
  }
117
- utils_2.logger.debug(`[RoutingEngine] Entered route: ${route.title}`);
118
- this.options?.onRouteSwitch?.();
146
+ utils_2.logger.debug(`[FlowRouter] Entered flow: ${route.title}`);
147
+ this.options?.onFlowSwitch?.();
119
148
  return updatedSession;
120
149
  }
121
150
  return session;
122
151
  }
123
152
  /**
124
- * Optimized decision for single-route scenarios
125
- * Skips route scoring and only does step selection
153
+ * Optimized decision for single-flow scenarios
154
+ * Skips flow scoring and only does step selection
126
155
  * @private
127
156
  */
128
- async decideSingleRouteStep(params) {
157
+ async decideSingleFlowStep(params) {
129
158
  const { route, session, history, agentOptions, provider, context, signal } = params;
130
- const selectedRoute = route;
131
- // Enter route if not already in it (this may merge initial data)
132
- const updatedSession = this.enterRouteIfNeeded(session, route);
133
- // Check if this single route is complete (use updated session data)
134
- const completedRoutes = route.isComplete(updatedSession.data || {}) ? [route] : [];
159
+ const selectedFlow = route;
160
+ // Enter flow if not already in it (this may merge initial data)
161
+ const updatedSession = this.enterFlowIfNeeded(session, route);
162
+ // Check if this single flow is complete (use updated session data)
163
+ const completedFlows = route.isComplete(updatedSession.data || {}) ? [route] : [];
135
164
  // Get candidate steps using new condition evaluation
136
165
  const templateContext = (0, utils_2.createTemplateContext)({
137
166
  context,
@@ -144,44 +173,43 @@ class RoutingEngine {
144
173
  : undefined;
145
174
  const candidates = await this.getCandidateStepsWithConditions(route, currentStep, templateContext);
146
175
  if (candidates.length === 0) {
147
- utils_2.logger.warn(`[RoutingEngine] Single-route: No valid steps found`);
148
- return { selectedRoute, session: updatedSession };
176
+ utils_2.logger.warn(`[FlowConfigurationError] No valid steps found: all candidates in the single-flow agent are skipped. Check step skip/when conditions.`);
177
+ return { selectedFlow, session: updatedSession };
149
178
  }
150
179
  // If only one candidate, check if it's a completion marker
151
180
  if (candidates.length === 1) {
152
181
  const candidate = candidates[0];
153
- if (candidate.isRouteComplete) {
154
- utils_2.logger.debug(`[RoutingEngine] Single-route: Route complete - all required fields collected or END_ROUTE reached`);
155
- // Don't return a selectedStep when route is complete - there's no step to enter
182
+ if (candidate.isFlowComplete) {
183
+ utils_2.logger.debug(`[FlowRouter] Single-flow: Flow complete - all required fields collected or last step reached`);
184
+ // Don't return a selectedStep when flow is complete - there's no step to enter
156
185
  return {
157
- selectedRoute,
186
+ selectedFlow,
158
187
  selectedStep: undefined,
159
188
  session: updatedSession,
160
- isRouteComplete: true,
161
- completedRoutes,
189
+ isFlowComplete: true,
190
+ completedFlows,
162
191
  };
163
192
  }
164
193
  else {
165
- utils_2.logger.debug(`[RoutingEngine] Single-route: Only one valid step: ${candidate.step.id}`);
194
+ utils_2.logger.debug(`[FlowRouter] Single-flow: Only one valid step: ${candidate.step.id}`);
166
195
  return {
167
- selectedRoute,
196
+ selectedFlow,
168
197
  selectedStep: candidate.step,
169
198
  session: updatedSession,
170
- isRouteComplete: false,
171
- completedRoutes,
199
+ isFlowComplete: false,
200
+ completedFlows,
172
201
  };
173
202
  }
174
203
  }
175
- // No candidates means route has no valid next steps (edge case)
176
- // Don't mark as complete based on data alone — only END_ROUTE completes a route
204
+ // No candidates means flow has no valid next steps (edge case)
177
205
  if (candidates.length === 0) {
178
- utils_2.logger.debug(`[RoutingEngine] Single-route: No valid candidate steps found`);
206
+ utils_2.logger.debug(`[FlowRouter] Single-flow: No valid candidate steps found`);
179
207
  return {
180
- selectedRoute,
208
+ selectedFlow,
181
209
  selectedStep: undefined,
182
210
  session: updatedSession,
183
- isRouteComplete: false,
184
- completedRoutes,
211
+ isFlowComplete: false,
212
+ completedFlows,
185
213
  };
186
214
  }
187
215
  // Multiple candidates - use AI to select best step
@@ -192,10 +220,10 @@ class RoutingEngine {
192
220
  const whenResult = await candidate.step.evaluateWhen(templateContext);
193
221
  stepConditionContext.push(...whenResult.aiContextStrings);
194
222
  }
195
- // Check if any candidate is a completion marker (isRouteComplete = true)
196
- const hasCompletionOption = candidates.some(c => c.isRouteComplete);
223
+ // Check if any candidate is a completion marker (isFlowComplete = true)
224
+ const hasCompletionOption = candidates.some(c => c.isFlowComplete);
197
225
  const stepPrompt = await this.buildStepSelectionPrompt({
198
- route,
226
+ flow: route,
199
227
  currentStep,
200
228
  candidates,
201
229
  data: updatedSession.data || {},
@@ -205,9 +233,9 @@ class RoutingEngine {
205
233
  context,
206
234
  session: updatedSession,
207
235
  stepConditionContext,
208
- includeEndRoute: hasCompletionOption,
236
+ includeCompletion: hasCompletionOption,
209
237
  });
210
- const stepSchema = this.buildStepSelectionSchema(candidates.filter(c => !c.isRouteComplete).map((c) => c.step), hasCompletionOption);
238
+ const stepSchema = this.buildStepSelectionSchema(candidates.filter(c => !c.isFlowComplete).map((c) => c.step), hasCompletionOption);
211
239
  const stepResult = await provider.generateMessage({
212
240
  prompt: stepPrompt,
213
241
  history: (0, utils_2.eventsToHistory)(history),
@@ -219,37 +247,37 @@ class RoutingEngine {
219
247
  },
220
248
  });
221
249
  const selectedStepId = stepResult.structured?.selectedStepId;
222
- // Check if AI selected END_ROUTE
223
- if (selectedStepId === constants_1.END_ROUTE_ID) {
224
- utils_2.logger.debug(`[RoutingEngine] Single-route: AI selected END_ROUTE - completing route`);
225
- utils_2.logger.debug(`[RoutingEngine] Single-route: Reasoning: ${stepResult.structured?.reasoning}`);
250
+ // Check if AI selected flow completion
251
+ if (selectedStepId === '__COMPLETE__') {
252
+ utils_2.logger.debug(`[FlowRouter] Single-flow: AI selected flow completion`);
253
+ utils_2.logger.debug(`[FlowRouter] Single-flow: Reasoning: ${stepResult.structured?.reasoning}`);
226
254
  return {
227
- selectedRoute,
255
+ selectedFlow,
228
256
  selectedStep: undefined,
229
257
  responseDirectives: stepResult.structured?.responseDirectives,
230
258
  session: updatedSession,
231
- isRouteComplete: true,
232
- completedRoutes,
259
+ isFlowComplete: true,
260
+ completedFlows,
233
261
  };
234
262
  }
235
263
  const selectedStep = candidates.find((c) => c.step.id === selectedStepId);
236
264
  if (selectedStep) {
237
- utils_2.logger.debug(`[RoutingEngine] Single-route: AI selected step: ${selectedStep.step.id}`);
238
- utils_2.logger.debug(`[RoutingEngine] Single-route: Reasoning: ${stepResult.structured?.reasoning}`);
265
+ utils_2.logger.debug(`[FlowRouter] Single-flow: AI selected step: ${selectedStep.step.id}`);
266
+ utils_2.logger.debug(`[FlowRouter] Single-flow: Reasoning: ${stepResult.structured?.reasoning}`);
239
267
  }
240
268
  else {
241
- utils_2.logger.warn(`[RoutingEngine] Single-route: Invalid step ID returned, using first candidate`);
269
+ utils_2.logger.warn(`[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.`);
242
270
  }
243
271
  return {
244
- selectedRoute,
272
+ selectedFlow,
245
273
  selectedStep: selectedStep?.step || candidates[0].step,
246
274
  responseDirectives: stepResult.structured?.responseDirectives,
247
275
  session: updatedSession,
248
- completedRoutes,
276
+ completedFlows,
249
277
  };
250
278
  }
251
279
  /**
252
- * Recursively traverse step chain to find first non-skipped step or END_ROUTE using new condition evaluation
280
+ * Recursively traverse step chain to find first non-skipped step using new condition evaluation
253
281
  * @private
254
282
  */
255
283
  async findFirstValidStepRecursiveWithConditions(currentStep, templateContext, visited) {
@@ -260,76 +288,78 @@ class RoutingEngine {
260
288
  visited.add(currentStep.id);
261
289
  const transitions = currentStep.getTransitions();
262
290
  const allAiContextStrings = [];
291
+ // No transitions means implicit terminus — flow is complete
292
+ if (transitions.length === 0) {
293
+ return {
294
+ isFlowComplete: true,
295
+ aiContextStrings: allAiContextStrings,
296
+ };
297
+ }
263
298
  for (const transition of transitions) {
264
299
  const target = transition;
265
- // Check for END_ROUTE transition
266
- if (target && target.id === constants_1.END_ROUTE_ID) {
267
- // Found END_ROUTE - route is complete
268
- return {
269
- isRouteComplete: true,
270
- aiContextStrings: allAiContextStrings,
271
- };
272
- }
273
300
  if (!target)
274
301
  continue;
275
- // Evaluate skipIf condition using new system
276
- const skipResult = await target.evaluateSkipIf(templateContext);
302
+ // Evaluate skip condition (code-only, if-shape)
303
+ const skipResult = await target.evaluateSkip(templateContext);
277
304
  allAiContextStrings.push(...skipResult.aiContextStrings);
278
305
  // If target should NOT be skipped, we found our step
279
306
  if (!skipResult.shouldSkip) {
280
- utils_2.logger.debug(`[RoutingEngine] Found valid step after skipping: ${target.id}`);
307
+ utils_2.logger.debug(`[FlowRouter] Found valid step after skipping: ${target.id}`);
281
308
  return {
282
309
  step: target,
283
- isRouteComplete: false,
310
+ isFlowComplete: false,
284
311
  aiContextStrings: allAiContextStrings,
285
312
  };
286
313
  }
287
314
  // Target should be skipped too - recurse deeper
288
- utils_2.logger.debug(`[RoutingEngine] Skipping step ${target.id} (skipIf condition met), continuing traversal...`);
315
+ utils_2.logger.debug(`[FlowRouter] Skipping step ${target.id} (skipIf condition met), continuing traversal...`);
289
316
  const result = await this.findFirstValidStepRecursiveWithConditions(target, templateContext, visited);
290
317
  // Collect AI context from recursive call
291
318
  if (result.aiContextStrings) {
292
319
  allAiContextStrings.push(...result.aiContextStrings);
293
320
  }
294
- // If we found something (a valid step or END_ROUTE), return it
295
- if (result.step || result.isRouteComplete) {
321
+ // If we found something (a valid step or flow complete), return it
322
+ if (result.step || result.isFlowComplete) {
296
323
  return {
297
324
  ...result,
298
325
  aiContextStrings: allAiContextStrings,
299
326
  };
300
327
  }
301
328
  }
302
- // No valid steps or END_ROUTE found in this branch
303
- return { aiContextStrings: allAiContextStrings };
329
+ // No valid steps found in this branch — all skipped with no further transitions
330
+ return {
331
+ isFlowComplete: true,
332
+ aiContextStrings: allAiContextStrings,
333
+ };
304
334
  }
305
335
  /**
306
336
  * Identify valid next candidate steps using new condition evaluation system
307
- * Returns step with isRouteComplete flag if route is complete (all steps skipped + has END_ROUTE transition)
337
+ * Returns step with isFlowComplete flag if flow is complete (all steps skipped or no transitions remain)
308
338
  *
309
- * NEW: Automatically completes route when all required fields are collected
339
+ * Flow completion is implicit: when the last step has no transitions, the flow is done.
310
340
  */
311
341
  async getCandidateStepsWithConditions(route, currentStep, templateContext) {
312
342
  const candidates = [];
313
343
  if (!currentStep) {
314
- // Entering route for the first time — always start the step flow
344
+ // Entering flow for the first time — always start the step flow
315
345
  const initialStep = route.initialStep;
316
- const skipResult = await initialStep.evaluateSkipIf(templateContext);
346
+ const skipResult = await initialStep.evaluateSkip(templateContext);
317
347
  if (skipResult.shouldSkip) {
318
- // Initial step should be skipped - recursively traverse to find first non-skipped step or END_ROUTE
348
+ // Initial step should be skipped - recursively traverse to find first non-skipped step
319
349
  const result = await this.findFirstValidStepRecursiveWithConditions(initialStep, templateContext, new Set());
320
- if (result.isRouteComplete) {
321
- // All steps are skipped and we reached END_ROUTE
322
- utils_2.logger.debug(`[RoutingEngine] Route complete on entry: all steps skipped, END_ROUTE reached`);
350
+ if (result.isFlowComplete) {
351
+ // All steps are skipped and no transitions remain
352
+ utils_2.logger.debug(`[FlowRouter] Flow complete on entry: all steps skipped, no transitions remain`);
323
353
  candidates.push({
324
354
  step: initialStep,
325
- isRouteComplete: true,
355
+ isFlowComplete: true,
326
356
  });
327
357
  }
328
358
  else if (result.step) {
329
359
  // Found a non-skipped step
330
360
  candidates.push({
331
361
  step: result.step,
332
- isRouteComplete: result.isRouteComplete || false,
362
+ isFlowComplete: result.isFlowComplete || false,
333
363
  });
334
364
  }
335
365
  // If no step found and not complete, fall through to return empty candidates
@@ -337,87 +367,84 @@ class RoutingEngine {
337
367
  else {
338
368
  candidates.push({
339
369
  step: initialStep,
340
- isRouteComplete: false,
370
+ isFlowComplete: false,
341
371
  });
342
372
  }
343
373
  return candidates;
344
374
  }
345
- // Continue normal step progression — routes complete via END_ROUTE, not via data collection
375
+ // Continue normal step progression — flows complete when last step has no transitions (implicit terminus)
346
376
  const transitions = currentStep.getTransitions();
347
- let hasEndRoute = false;
377
+ // No transitions means this is the last step — flow is complete
378
+ if (transitions.length === 0) {
379
+ utils_2.logger.debug(`[FlowRouter] Flow complete: current step has no transitions (implicit terminus)`);
380
+ return [
381
+ {
382
+ step: currentStep,
383
+ isFlowComplete: true,
384
+ },
385
+ ];
386
+ }
348
387
  for (const transition of transitions) {
349
388
  const target = transition;
350
- // Check for END_ROUTE transition (no target step)
351
- if (target && target.id === constants_1.END_ROUTE_ID) {
352
- hasEndRoute = true;
353
- continue;
354
- }
355
389
  if (!target)
356
390
  continue;
357
- const skipResult = await target.evaluateSkipIf(templateContext);
391
+ const skipResult = await target.evaluateSkip(templateContext);
358
392
  if (skipResult.shouldSkip) {
359
- utils_2.logger.debug(`[RoutingEngine] Skipping step ${target.id} (skipIf condition met)`);
360
- // Recursively traverse to find next valid step or END_ROUTE
393
+ utils_2.logger.debug(`[FlowRouter] Skipping step ${target.id} (skip condition met)`);
394
+ // Recursively traverse to find next valid step
361
395
  const result = await this.findFirstValidStepRecursiveWithConditions(target, templateContext, new Set([currentStep.id]) // Already visited current step
362
396
  );
363
- if (result.isRouteComplete) {
364
- hasEndRoute = true;
397
+ if (result.isFlowComplete) {
398
+ // All forward paths lead to terminus
399
+ candidates.push({
400
+ step: currentStep,
401
+ isFlowComplete: true,
402
+ });
365
403
  }
366
404
  else if (result.step) {
367
405
  // Found a non-skipped step deeper in the chain
368
406
  candidates.push({
369
407
  step: result.step,
370
- isRouteComplete: result.isRouteComplete || false,
408
+ isFlowComplete: false,
371
409
  });
372
410
  }
373
411
  continue;
374
412
  }
375
413
  candidates.push({
376
414
  step: target,
377
- isRouteComplete: hasEndRoute || false,
415
+ isFlowComplete: false,
378
416
  });
379
417
  }
380
- // If no valid candidates found
418
+ // If no valid candidates found after evaluating all transitions
381
419
  if (candidates.length === 0) {
382
- // If current step has END_ROUTE transition, the route is complete
383
- if (hasEndRoute) {
384
- utils_2.logger.debug(`[RoutingEngine] Route complete: all steps processed, END_ROUTE reached`);
385
- // Return current step with completion flag
386
- return [
387
- {
388
- step: currentStep,
389
- isRouteComplete: true,
390
- },
391
- ];
392
- }
393
- // Otherwise, stay in current step if it's still valid
394
- const currentSkipResult = await currentStep.evaluateSkipIf(templateContext);
395
- if (!currentSkipResult.shouldSkip) {
396
- candidates.push({
420
+ // All transitions were skipped flow is complete
421
+ utils_2.logger.debug(`[FlowRouter] Flow complete: all transitions skipped`);
422
+ return [
423
+ {
397
424
  step: currentStep,
398
- isRouteComplete: hasEndRoute || false,
399
- });
400
- }
425
+ isFlowComplete: true,
426
+ },
427
+ ];
401
428
  }
402
429
  return candidates;
403
430
  }
404
431
  /**
405
432
  * Full routing orchestration: builds prompt and schema, calls AI, selects route/step,
406
- * and updates the session (including initialData merge when entering a new route).
433
+ * and updates the session (including initialData merge when entering a new flow).
407
434
  *
408
435
  * OPTIMIZATION: If there's only 1 route, skips route scoring and only does step selection.
409
- * CROSS-ROUTE COMPLETION: Evaluates all routes for completion based on collected data.
436
+ * CROSS-FLOW COMPLETION: Evaluates all flows for completion based on collected data.
410
437
  */
411
- async decideRouteAndStep(params) {
412
- const { routes, session, history, agentOptions, provider, context, signal, } = params;
413
- if (routes.length === 0) {
438
+ async decideFlowAndStep(params) {
439
+ const { flows, session, history, agentOptions, provider, context, signal, } = params;
440
+ if (flows.length === 0) {
414
441
  return { session };
415
442
  }
416
- // SESSION RESUME: If the session has a pre-set route and there are no user
443
+ // SESSION RESUME: If the session has a pre-set flow and there are no user
417
444
  // messages in the history, honor the pre-set position without AI routing.
418
445
  // This supports programmatic session setup and persistence-based resume.
419
446
  const resumeResult = await this.handleSessionResume({
420
- routes,
447
+ flows,
421
448
  session,
422
449
  history,
423
450
  context,
@@ -425,16 +452,24 @@ class RoutingEngine {
425
452
  if (resumeResult) {
426
453
  return resumeResult;
427
454
  }
428
- // CROSS-ROUTE COMPLETION EVALUATION: Check all routes for completion
429
- const completedRoutes = this.evaluateRouteCompletions(routes, session.data || {});
430
- // Log completed routes
431
- if (completedRoutes.length > 0) {
432
- utils_2.logger.debug(`[RoutingEngine] Found ${completedRoutes.length} completed routes: ${completedRoutes.map(r => r.title).join(', ')}`);
433
- }
434
- // OPTIMIZATION: Single route - skip route scoring, only do step selection
435
- if (routes.length === 1) {
436
- const result = await this.decideSingleRouteStep({
437
- route: routes[0],
455
+ // Exclude flows that completed earlier in this session unless explicitly
456
+ // re-entrant. A completed flow surrenders the conversation back to
457
+ // routing it cannot be re-selected without `flow.reentrant: true`.
458
+ const reEntryFiltered = flows.filter((f) => !(0, utils_1.isFlowCompletedThisSession)(session, f.id) || f.reentrant === true);
459
+ const excludedFlows = flows.length - reEntryFiltered.length;
460
+ if (excludedFlows > 0) {
461
+ utils_2.logger.debug(`[FlowRouter] Excluded ${excludedFlows} completed (non-reentrant) flow(s) from routing candidates`);
462
+ }
463
+ // CROSS-FLOW COMPLETION EVALUATION: Check all eligible flows for completion
464
+ const completedFlows = this.evaluateFlowCompletions(reEntryFiltered, session.data || {});
465
+ // Log completed flows
466
+ if (completedFlows.length > 0) {
467
+ utils_2.logger.debug(`[FlowRouter] Found ${completedFlows.length} completed routes: ${completedFlows.map(r => r.title).join(', ')}`);
468
+ }
469
+ // OPTIMIZATION: Single flow - skip flow scoring, only do step selection
470
+ if (reEntryFiltered.length === 1) {
471
+ const result = await this.decideSingleFlowStep({
472
+ route: reEntryFiltered[0],
438
473
  session,
439
474
  history,
440
475
  agentOptions,
@@ -444,9 +479,15 @@ class RoutingEngine {
444
479
  });
445
480
  return {
446
481
  ...result,
447
- completedRoutes,
482
+ completedFlows,
448
483
  };
449
484
  }
485
+ // No eligible flows after re-entry filtering — caller falls back to the
486
+ // generic non-flow response path.
487
+ if (reEntryFiltered.length === 0) {
488
+ utils_2.logger.debug(`[FlowRouter] All flows completed and none are reentrant — releasing session to fallback`);
489
+ return { session, completedFlows };
490
+ }
450
491
  const lastUserMessage = (0, utils_2.getLastMessageFromHistory)(history);
451
492
  const templateContext = (0, utils_2.createTemplateContext)({
452
493
  context,
@@ -454,56 +495,55 @@ class RoutingEngine {
454
495
  history,
455
496
  data: session.data
456
497
  });
457
- // Apply route filtering with new condition evaluation system
458
- const skipIfResult = await this.filterRoutesBySkipIf(routes, templateContext);
459
- const whenResult = await this.filterRoutesByWhen(skipIfResult.eligibleRoutes, templateContext);
460
- // Use filtered routes for further processing
498
+ // Apply flow filtering with new condition evaluation system
499
+ const whenResult = await this.filterFlowsByWhen(reEntryFiltered, templateContext);
500
+ // Use filtered flows for further processing
461
501
  const eligibleRoutes = whenResult.eligibleRoutes;
462
- utils_2.logger.debug(`[RoutingEngine] Route filtering: ${routes.length} total → ${skipIfResult.eligibleRoutes.length} after skipIf → ${eligibleRoutes.length} after when`);
463
- let activeRouteSteps;
464
- let activeRoute;
465
- let isRouteComplete = false;
502
+ utils_2.logger.debug(`[FlowRouter] Flow filtering: ${flows.length} total → ${reEntryFiltered.length} after re-entry filter → ${eligibleRoutes.length} after when`);
503
+ let activeFlowSteps;
504
+ let activeFlow;
505
+ let isFlowComplete = false;
466
506
  let updatedSession = session;
467
- if (session.currentRoute) {
468
- activeRoute = eligibleRoutes.find((r) => r.id === session.currentRoute?.id);
469
- if (activeRoute) {
507
+ if (session.currentFlow) {
508
+ activeFlow = eligibleRoutes.find((r) => r.id === session.currentFlow?.id);
509
+ if (activeFlow) {
470
510
  const currentStep = session.currentStep
471
- ? activeRoute.getStep(session.currentStep.id)
511
+ ? activeFlow.getStep(session.currentStep.id)
472
512
  : undefined;
473
513
  const activeTemplateContext = (0, utils_2.createTemplateContext)({
474
514
  ...templateContext,
475
515
  session: updatedSession,
476
516
  data: updatedSession.data
477
517
  });
478
- const candidates = await this.getCandidateStepsWithConditions(activeRoute, currentStep, activeTemplateContext);
479
- // Check if route is complete
518
+ const candidates = await this.getCandidateStepsWithConditions(activeFlow, currentStep, activeTemplateContext);
519
+ // Check if flow is complete
480
520
  // getCandidateStepsWithConditions now automatically handles completion when required fields are collected
481
- if (candidates.length === 1 && candidates[0].isRouteComplete) {
482
- isRouteComplete = true;
483
- utils_2.logger.debug(`[RoutingEngine] Route ${activeRoute.title} is complete - all required fields collected or END_ROUTE reached`);
521
+ if (candidates.length === 1 && candidates[0].isFlowComplete) {
522
+ isFlowComplete = true;
523
+ utils_2.logger.debug(`[FlowRouter] Flow ${activeFlow.title} is complete - all required fields collected or last step reached`);
484
524
  // Don't include steps in routing if route is complete
485
- activeRouteSteps = undefined;
525
+ activeFlowSteps = undefined;
486
526
  }
487
527
  else if (candidates.length === 0) {
488
- // No candidates available — don't end route based on data alone
489
- utils_2.logger.debug(`[RoutingEngine] Route ${activeRoute.title} has no valid candidate steps`);
490
- activeRouteSteps = undefined;
528
+ // No candidates available — don't end flow based on data alone
529
+ utils_2.logger.debug(`[FlowRouter] Flow ${activeFlow.title} has no valid candidate steps`);
530
+ activeFlowSteps = undefined;
491
531
  }
492
532
  else {
493
533
  // Multiple candidates or single non-complete candidate
494
- activeRouteSteps = candidates.map((c) => c.step);
495
- utils_2.logger.debug(`[RoutingEngine] Found ${activeRouteSteps.length} candidate steps for active route`);
534
+ activeFlowSteps = candidates.map((c) => c.step);
535
+ utils_2.logger.debug(`[FlowRouter] Found ${activeFlowSteps.length} candidate steps for active route`);
496
536
  }
497
537
  }
498
538
  }
499
- const routingSchema = this.buildDynamicRoutingSchema(eligibleRoutes, undefined, activeRouteSteps);
539
+ const routingSchema = this.buildDynamicFlowSchema(eligibleRoutes, undefined, activeFlowSteps);
500
540
  const routingPrompt = await this.buildRoutingPrompt({
501
541
  history,
502
- routes: eligibleRoutes,
542
+ flows: eligibleRoutes,
503
543
  lastMessage: lastUserMessage,
504
544
  agentOptions,
505
545
  session,
506
- activeRouteSteps,
546
+ activeFlowSteps,
507
547
  context,
508
548
  });
509
549
  const routingResult = await provider.generateMessage({
@@ -516,115 +556,92 @@ class RoutingEngine {
516
556
  schemaName: "routing_output",
517
557
  },
518
558
  });
519
- let selectedRoute;
559
+ let selectedFlow;
520
560
  let selectedStep;
521
561
  let responseDirectives;
522
- if (routingResult.structured?.routes) {
523
- // Use cross-route completion evaluation to select optimal route
524
- const optimalRoute = this.selectOptimalRoute(eligibleRoutes, updatedSession.data || {}, routingResult.structured.routes, updatedSession.currentRoute?.id);
525
- // If no optimal route found, check why
562
+ if (routingResult.structured?.flows) {
563
+ // Use cross-flow completion evaluation to select optimal flow
564
+ const optimalRoute = this.selectOptimalFlow(eligibleRoutes, updatedSession.data || {}, routingResult.structured.flows, updatedSession.currentFlow?.id);
565
+ // If no optimal flow found, check why
526
566
  if (!optimalRoute) {
527
567
  if (eligibleRoutes.length === 0) {
528
- // No routes passed filtering
529
- utils_2.logger.debug(`[RoutingEngine] No eligible routes available - all routes filtered out`);
530
- selectedRoute = undefined;
568
+ // No flows passed filtering
569
+ utils_2.logger.debug(`[FlowRouter] No eligible flows available - all flows filtered out`);
570
+ selectedFlow = undefined;
531
571
  }
532
572
  else {
533
- // Routes exist but selectOptimalRoute returned undefined
534
- // This means all routes are 100% complete
535
- utils_2.logger.debug(`[RoutingEngine] No optimal route found - all ${eligibleRoutes.length} eligible routes are complete`);
536
- selectedRoute = undefined;
573
+ // Routes exist but selectOptimalFlow returned undefined
574
+ // This means all flows are 100% complete
575
+ utils_2.logger.debug(`[FlowRouter] No optimal route found - all ${eligibleRoutes.length} eligible routes are complete`);
576
+ selectedFlow = undefined;
537
577
  }
538
578
  }
539
579
  else {
540
- selectedRoute = optimalRoute;
580
+ selectedFlow = optimalRoute;
541
581
  }
542
582
  responseDirectives = routingResult.structured.responseDirectives;
543
- if (selectedRoute === activeRoute &&
583
+ if (selectedFlow === activeFlow &&
544
584
  routingResult.structured.selectedStepId &&
545
- activeRoute) {
546
- selectedStep = activeRoute.getStep(routingResult.structured.selectedStepId);
585
+ activeFlow) {
586
+ selectedStep = activeFlow.getStep(routingResult.structured.selectedStepId);
547
587
  if (selectedStep) {
548
- utils_2.logger.debug(`[RoutingEngine] AI selected step: ${selectedStep.id} in active route`);
549
- utils_2.logger.debug(`[RoutingEngine] Step reasoning: ${routingResult.structured.stepReasoning}`);
588
+ utils_2.logger.debug(`[FlowRouter] AI selected step: ${selectedStep.id} in active route`);
589
+ utils_2.logger.debug(`[FlowRouter] Step reasoning: ${routingResult.structured.stepReasoning}`);
550
590
  }
551
591
  }
552
- if (selectedRoute) {
553
- utils_2.logger.debug(`[RoutingEngine] Selected route: ${selectedRoute.title}`);
554
- updatedSession = this.enterRouteIfNeeded(updatedSession, selectedRoute);
592
+ if (selectedFlow) {
593
+ utils_2.logger.debug(`[FlowRouter] Selected route: ${selectedFlow.title}`);
594
+ updatedSession = this.enterFlowIfNeeded(updatedSession, selectedFlow);
555
595
  }
556
596
  }
557
597
  return {
558
- selectedRoute,
598
+ selectedFlow,
559
599
  selectedStep,
560
600
  responseDirectives,
561
601
  session: updatedSession,
562
- isRouteComplete,
563
- completedRoutes,
602
+ isFlowComplete,
603
+ completedFlows,
564
604
  };
565
605
  }
566
606
  /**
567
- * Filter routes based on skipIf conditions
568
- * @param routes - All available routes
569
- * @param templateContext - Context for condition evaluation
570
- * @returns Object with eligible routes and collected AI context strings
571
- */
572
- async filterRoutesBySkipIf(routes, templateContext) {
573
- const eligibleRoutes = [];
574
- const aiContextStrings = [];
575
- for (const route of routes) {
576
- const skipResult = await route.evaluateSkipIf(templateContext);
577
- // Collect AI context strings from skipIf conditions
578
- aiContextStrings.push(...skipResult.aiContextStrings);
579
- // If route should not be skipped, it's eligible
580
- if (!skipResult.programmaticResult) {
581
- eligibleRoutes.push(route);
582
- }
583
- else {
584
- utils_2.logger.debug(`[RoutingEngine] Skipping route ${route.title} (skipIf condition met)`);
585
- }
586
- }
587
- return { eligibleRoutes, aiContextStrings };
588
- }
589
- /**
590
- * Filter routes based on when conditions
591
- * @param routes - Routes that passed skipIf filtering
607
+ * Filter flows based on when conditions
608
+ * @param routes - Flows that passed skipIf filtering
592
609
  * @param templateContext - Context for condition evaluation
593
- * @returns Object with eligible routes and collected AI context strings
610
+ * @returns Object with eligible flows and collected AI context strings
594
611
  */
595
- async filterRoutesByWhen(routes, templateContext) {
612
+ async filterFlowsByWhen(routes, templateContext) {
596
613
  const eligibleRoutes = [];
597
614
  const aiContextStrings = [];
598
615
  for (const route of routes) {
599
616
  const whenResult = await route.evaluateWhen(templateContext);
600
617
  // Collect AI context strings from when conditions
601
618
  aiContextStrings.push(...whenResult.aiContextStrings);
602
- // If route has no programmatic conditions or they evaluate to true, it's eligible
619
+ // If flow has no programmatic conditions or they evaluate to true, it's eligible
603
620
  if (!whenResult.hasProgrammaticConditions || whenResult.programmaticResult) {
604
621
  eligibleRoutes.push(route);
605
622
  }
606
623
  else {
607
- utils_2.logger.debug(`[RoutingEngine] Route ${route.title} not eligible (when condition not met)`);
624
+ utils_2.logger.debug(`[FlowRouter] Flow ${route.title} not eligible (when condition not met)`);
608
625
  }
609
626
  }
610
627
  return { eligibleRoutes, aiContextStrings };
611
628
  }
612
629
  /**
613
- * Evaluate all routes for completion based on collected data
614
- * @param routes - All available routes
630
+ * Evaluate all flows for completion based on collected data
631
+ * @param routes - All available flows
615
632
  * @param data - Currently collected agent-level data
616
- * @returns Array of routes that are complete
633
+ * @returns Array of flows that are complete
617
634
  */
618
- evaluateRouteCompletions(routes, data) {
635
+ evaluateFlowCompletions(routes, data) {
619
636
  return routes.filter(route => route.isComplete(data));
620
637
  }
621
638
  /**
622
- * Get completion status for all routes
623
- * @param routes - All available routes
639
+ * Get completion status for all flows
640
+ * @param routes - All available flows
624
641
  * @param data - Currently collected agent-level data
625
- * @returns Map of route ID to completion progress (0-1)
642
+ * @returns Map of flow ID to completion progress (0-1)
626
643
  */
627
- getRouteCompletionStatus(routes, data) {
644
+ getFlowCompletionStatus(routes, data) {
628
645
  const completionStatus = new Map();
629
646
  for (const route of routes) {
630
647
  const progress = route.getCompletionProgress(data);
@@ -633,28 +650,28 @@ class RoutingEngine {
633
650
  return completionStatus;
634
651
  }
635
652
  /**
636
- * Find the best route to continue based on completion status and user intent
637
- * Prioritizes routes that are partially complete but not finished
638
- * IMPORTANT: Completed routes are excluded to prevent re-entering finished tasks
639
- * @param routes - All available routes
653
+ * Find the best flow to continue based on completion status and user intent
654
+ * Prioritizes flows that are partially complete but not finished
655
+ * IMPORTANT: Completed flows are excluded to prevent re-entering finished tasks
656
+ * @param routes - All available flows
640
657
  * @param data - Currently collected agent-level data
641
658
  * @param routeScores - AI-generated route scores from routing decision
642
- * @returns Route that should be prioritized for continuation
659
+ * @returns Flow that should be prioritized for continuation
643
660
  */
644
- selectOptimalRoute(routes, data, routeScores, currentRouteId) {
645
- const completionStatus = this.getRouteCompletionStatus(routes, data);
646
- const switchMargin = this.options?.routeSwitchMargin ?? 15;
661
+ selectOptimalFlow(routes, data, routeScores, currentRouteId) {
662
+ const completionStatus = this.getFlowCompletionStatus(routes, data);
663
+ const switchMargin = this.options?.flowSwitchMargin ?? 15;
647
664
  // Create weighted scores combining AI intent scores with completion progress
648
665
  const weightedScores = [];
649
666
  for (const route of routes) {
650
667
  const aiScore = routeScores[route.id] || 0;
651
668
  const completionProgress = completionStatus.get(route.id) || 0;
652
- // ALWAYS skip fully completed routes to prevent re-entering finished tasks
669
+ // ALWAYS skip fully completed flows to prevent re-entering finished tasks
653
670
  if (completionProgress >= 1.0) {
654
- utils_2.logger.debug(`[RoutingEngine] Excluding completed route: ${route.title} (100% complete)`);
671
+ utils_2.logger.debug(`[FlowRouter] Excluding completed flow: ${route.title} (100% complete)`);
655
672
  continue;
656
673
  }
657
- // Boost partially complete routes that match user intent
674
+ // Boost partially complete flows that match user intent
658
675
  let weightedScore = aiScore;
659
676
  if (completionProgress > 0 && completionProgress < 1.0) {
660
677
  weightedScore += (completionProgress * 20); // Up to 20 point boost
@@ -667,48 +684,48 @@ class RoutingEngine {
667
684
  return undefined;
668
685
  }
669
686
  // Apply sticky routing: if there's a current route, only switch if the
670
- // best alternative exceeds the current route's score by the configured margin
687
+ // best alternative exceeds the current flow's score by the configured margin
671
688
  if (currentRouteId) {
672
689
  const currentEntry = weightedScores.find(e => e.route.id === currentRouteId);
673
690
  const bestEntry = weightedScores[0];
674
691
  if (currentEntry && bestEntry.route.id !== currentRouteId) {
675
692
  if (bestEntry.score < currentEntry.score + switchMargin) {
676
- utils_2.logger.debug(`[RoutingEngine] Staying on current route: ${currentEntry.route.title} ` +
693
+ utils_2.logger.debug(`[FlowRouter] Staying on current flow: ${currentEntry.route.title} ` +
677
694
  `(current: ${currentEntry.score}, best alternative: ${bestEntry.score}, ` +
678
695
  `margin required: ${switchMargin})`);
679
696
  return currentEntry.route;
680
697
  }
681
- utils_2.logger.debug(`[RoutingEngine] Switching route: ${currentEntry.route.title} → ${bestEntry.route.title} ` +
698
+ utils_2.logger.debug(`[FlowRouter] Switching flow: ${currentEntry.route.title} → ${bestEntry.route.title} ` +
682
699
  `(current: ${currentEntry.score}, alternative: ${bestEntry.score}, ` +
683
700
  `margin: ${switchMargin})`);
684
701
  }
685
702
  }
686
- utils_2.logger.debug(`[RoutingEngine] Selected optimal route: ${weightedScores[0].route.title} ` +
703
+ utils_2.logger.debug(`[FlowRouter] Selected optimal route: ${weightedScores[0].route.title} ` +
687
704
  `(AI: ${routeScores[weightedScores[0].route.id]}, ` +
688
705
  `Completion: ${(completionStatus.get(weightedScores[0].route.id) || 0) * 100}%, ` +
689
706
  `Weighted: ${weightedScores[0].score})`);
690
707
  return weightedScores[0].route;
691
708
  }
692
709
  /**
693
- * Build prompt for step selection within a single route
710
+ * Build prompt for step selection within a single flow
694
711
  * @private
695
712
  */
696
713
  async buildStepSelectionPrompt(params) {
697
- const { route, currentStep, candidates, data, history, lastMessage, agentOptions, context, session, stepConditionContext, includeEndRoute = false, } = params;
714
+ const { flow: route, currentStep, candidates, data, history, lastMessage, agentOptions, context, session, stepConditionContext, includeCompletion = false, } = params;
698
715
  const templateContext = (0, utils_2.createTemplateContext)({ context, session, history });
699
716
  const pc = new PromptComposer_1.PromptComposer(templateContext, this.options?.promptSectionCache);
700
717
  // Add agent metadata
701
718
  if (agentOptions) {
702
719
  await pc.addAgentMeta(agentOptions);
703
720
  }
704
- // Add route context
705
- await pc.addInstruction(`Active Route: ${route.title}\nDescription: ${route.description || "N/A"}`);
721
+ // Add flow context
722
+ await pc.addInstruction(`Active Flow: ${route.title}\nDescription: ${route.description || "N/A"}`);
706
723
  // Add current step context
707
724
  if (currentStep) {
708
725
  await pc.addInstruction(`Current Step: ${currentStep.id}\nDescription: ${currentStep.description || "N/A"}`);
709
726
  }
710
727
  else {
711
- await pc.addInstruction("Current Step: None (entering route)");
728
+ await pc.addInstruction("Current Step: None (entering flow)");
712
729
  }
713
730
  // Add collected data context
714
731
  if (Object.keys(data).length > 0) {
@@ -772,8 +789,8 @@ class RoutingEngine {
772
789
  "- Choose the step that makes the most sense for moving the conversation forward",
773
790
  "- Steps with skipIf conditions that are met have already been filtered out",
774
791
  ];
775
- if (includeEndRoute) {
776
- decisionRules.push("", `- You can select '${constants_1.END_ROUTE_ID}' to complete this route if:`, " * All required data has been collected", " * The user's intent suggests they're done with this task", " * No further steps are needed to fulfill the user's request");
792
+ if (includeCompletion) {
793
+ decisionRules.push("", `- You can select '__COMPLETE__' to complete this flow if:`, " * All required data has been collected", " * The user's intent suggests they're done with this task", " * No further steps are needed to fulfill the user's request");
777
794
  }
778
795
  decisionRules.push("", "Return ONLY JSON matching the provided schema.");
779
796
  await pc.addInstruction(decisionRules.join("\n"));
@@ -783,11 +800,11 @@ class RoutingEngine {
783
800
  * Build schema for step selection
784
801
  * @private
785
802
  */
786
- buildStepSelectionSchema(validSteps, includeEndRoute = false) {
803
+ buildStepSelectionSchema(validSteps, includeCompletion = false) {
787
804
  const stepIds = validSteps.map((s) => s.id);
788
- // Add END_ROUTE as an option if requested (when required fields are complete)
789
- if (includeEndRoute) {
790
- stepIds.push(constants_1.END_ROUTE_ID);
805
+ // Add completion option if requested (when required fields are complete)
806
+ if (includeCompletion) {
807
+ stepIds.push('__COMPLETE__');
791
808
  }
792
809
  return {
793
810
  description: "Step transition decision based on conversation context and collected data",
@@ -801,8 +818,8 @@ class RoutingEngine {
801
818
  selectedStepId: {
802
819
  type: "string",
803
820
  nullable: false,
804
- description: includeEndRoute
805
- ? `The ID of the selected step to transition to, or '${constants_1.END_ROUTE_ID}' to complete the route`
821
+ description: includeCompletion
822
+ ? "The ID of the selected step to transition to, or '__COMPLETE__' to complete the flow"
806
823
  : "The ID of the selected step to transition to",
807
824
  enum: stepIds,
808
825
  },
@@ -816,20 +833,20 @@ class RoutingEngine {
816
833
  additionalProperties: false,
817
834
  };
818
835
  }
819
- buildDynamicRoutingSchema(routes, extrasSchema, activeRouteSteps) {
836
+ buildDynamicFlowSchema(routes, extrasSchema, activeFlowSteps) {
820
837
  const routeIds = routes.map((r) => r.id);
821
838
  const routeProperties = {};
822
839
  for (const id of routeIds) {
823
840
  routeProperties[id] = {
824
841
  type: "number",
825
842
  nullable: false,
826
- description: `Score for route ${id} based on direct evidence, context and semantic fit (0-100)`,
843
+ description: `Score for flow ${id} based on direct evidence, context and semantic fit (0-100)`,
827
844
  minimum: 0,
828
845
  maximum: 100,
829
846
  };
830
847
  }
831
848
  const base = {
832
- description: "Full intent analysis: score ALL available routes (0-100) using evidence and context",
849
+ description: "Full intent analysis: score ALL available flows (0-100) using evidence and context",
833
850
  type: "object",
834
851
  properties: {
835
852
  context: {
@@ -837,12 +854,12 @@ class RoutingEngine {
837
854
  nullable: false,
838
855
  description: "Brief summary of the user's intent/context",
839
856
  },
840
- routes: {
857
+ flows: {
841
858
  type: "object",
842
859
  properties: routeProperties,
843
860
  required: routeIds,
844
861
  nullable: false,
845
- description: "Mapping of routeId to score (0-100)",
862
+ description: "Mapping of flowId to score (0-100)",
846
863
  },
847
864
  responseDirectives: {
848
865
  type: "array",
@@ -850,17 +867,17 @@ class RoutingEngine {
850
867
  description: "Optional bullet points the response should address (concise)",
851
868
  },
852
869
  },
853
- required: ["context", "routes"],
870
+ required: ["context", "flows"],
854
871
  additionalProperties: false,
855
872
  };
856
- // Add step selection fields if there's an active route with steps
857
- if (activeRouteSteps && activeRouteSteps.length > 0) {
873
+ // Add step selection fields if there's an active flow with steps
874
+ if (activeFlowSteps && activeFlowSteps.length > 0) {
858
875
  base.properties = base.properties || {};
859
876
  base.properties.selectedStepId = {
860
877
  type: "string",
861
878
  nullable: false,
862
- description: "The step ID to transition to within the active route (required if continuing in current route)",
863
- enum: activeRouteSteps.map((s) => s.id),
879
+ description: "The step ID to transition to within the active flow (required if continuing in current flow)",
880
+ enum: activeFlowSteps.map((s) => s.id),
864
881
  };
865
882
  base.properties.stepReasoning = {
866
883
  type: "string",
@@ -880,7 +897,7 @@ class RoutingEngine {
880
897
  return base;
881
898
  }
882
899
  async buildRoutingPrompt(params) {
883
- const { history, routes, lastMessage, agentOptions, session, activeRouteSteps, context, } = params;
900
+ const { history, flows: routes, lastMessage, agentOptions, session, activeFlowSteps, context, } = params;
884
901
  const templateContext = (0, utils_2.createTemplateContext)({ context, session, history });
885
902
  const pc = new PromptComposer_1.PromptComposer(templateContext, this.options?.promptSectionCache);
886
903
  if (agentOptions) {
@@ -888,10 +905,10 @@ class RoutingEngine {
888
905
  }
889
906
  await pc.addInstruction("Task: Intent analysis and route scoring (0-100). Score ALL listed routes.");
890
907
  // Add session context if available
891
- if (session?.currentRoute) {
908
+ if (session?.currentFlow) {
892
909
  const sessionInfo = [
893
910
  "Current conversation context:",
894
- `- Active route: ${session.currentRoute.title} (${session.currentRoute.id})`,
911
+ `- Active route: ${session.currentFlow.title} (${session.currentFlow.id})`,
895
912
  ];
896
913
  if (session.currentStep) {
897
914
  sessionInfo.push(`- Current step: ${session.currentStep.id}`);
@@ -905,16 +922,16 @@ class RoutingEngine {
905
922
  sessionInfo.push("Note: User is mid-conversation. They may want to continue current route or switch to a new one based on their intent.");
906
923
  await pc.addInstruction(sessionInfo.join("\n"));
907
924
  // Add cross-route completion status
908
- const completionStatus = this.getRouteCompletionStatus(routes, session.data || {});
909
- const completedRoutes = this.evaluateRouteCompletions(routes, session.data || {});
925
+ const completionStatus = this.getFlowCompletionStatus(routes, session.data || {});
926
+ const completedFlows = this.evaluateFlowCompletions(routes, session.data || {});
910
927
  if (completionStatus.size > 0) {
911
928
  const statusInfo = [
912
929
  "",
913
- "Route completion status based on collected data:",
930
+ "Flow completion status based on collected data:",
914
931
  ];
915
932
  for (const route of routes) {
916
933
  const progress = completionStatus.get(route.id) || 0;
917
- const isComplete = completedRoutes.includes(route);
934
+ const isComplete = completedFlows.includes(route);
918
935
  const progressPercent = Math.round(progress * 100);
919
936
  statusInfo.push(`- ${route.title}: ${progressPercent}% complete${isComplete ? ' ✓ COMPLETE' : ''}`);
920
937
  if (!isComplete && route.requiredFields) {
@@ -928,14 +945,14 @@ class RoutingEngine {
928
945
  await pc.addInstruction(statusInfo.join("\n"));
929
946
  }
930
947
  // Add available steps for the active route
931
- if (activeRouteSteps && activeRouteSteps.length > 0) {
948
+ if (activeFlowSteps && activeFlowSteps.length > 0) {
932
949
  const stepInfo = [
933
950
  "",
934
951
  "Available steps in active route (choose one to transition to):",
935
952
  ];
936
953
  const activeStepConditionContext = [];
937
- for (const step of activeRouteSteps) {
938
- const idx = activeRouteSteps.indexOf(step);
954
+ for (const step of activeFlowSteps) {
955
+ const idx = activeFlowSteps.indexOf(step);
939
956
  stepInfo.push(`${idx + 1}. Step: ${step.id}`);
940
957
  if (step.description) {
941
958
  stepInfo.push(` Description: ${step.description}`);
@@ -979,7 +996,7 @@ class RoutingEngine {
979
996
  }
980
997
  await pc.addInteractionHistory(history);
981
998
  await pc.addLastMessage(lastMessage);
982
- await pc.addRoutingOverview(routes);
999
+ await pc.addFlowOverview(routes);
983
1000
  await pc.addInstruction([
984
1001
  "Scoring rules:",
985
1002
  "- 90-100: explicit keywords + clear intent",
@@ -992,5 +1009,5 @@ class RoutingEngine {
992
1009
  return pc.build();
993
1010
  }
994
1011
  }
995
- exports.RoutingEngine = RoutingEngine;
996
- //# sourceMappingURL=RoutingEngine.js.map
1012
+ exports.FlowRouter = FlowRouter;
1013
+ //# sourceMappingURL=FlowRouter.js.map