@falai/agent 0.9.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (654) hide show
  1. package/README.md +304 -72
  2. package/dist/adapters/MemoryAdapter.d.ts.map +1 -0
  3. package/dist/adapters/MemoryAdapter.js.map +1 -0
  4. package/dist/adapters/MongoAdapter.d.ts.map +1 -0
  5. package/dist/adapters/MongoAdapter.js.map +1 -0
  6. package/dist/adapters/OpenSearchAdapter.d.ts.map +1 -0
  7. package/dist/adapters/OpenSearchAdapter.js.map +1 -0
  8. package/dist/adapters/PostgreSQLAdapter.d.ts.map +1 -0
  9. package/dist/adapters/PostgreSQLAdapter.js.map +1 -0
  10. package/dist/adapters/PrismaAdapter.d.ts.map +1 -0
  11. package/dist/{src/adapters → adapters}/PrismaAdapter.js +3 -2
  12. package/dist/adapters/PrismaAdapter.js.map +1 -0
  13. package/dist/adapters/RedisAdapter.d.ts.map +1 -0
  14. package/dist/{src/adapters → adapters}/RedisAdapter.js +3 -3
  15. package/dist/adapters/RedisAdapter.js.map +1 -0
  16. package/dist/adapters/SQLiteAdapter.d.ts.map +1 -0
  17. package/dist/adapters/SQLiteAdapter.js.map +1 -0
  18. package/dist/adapters/index.d.ts.map +1 -0
  19. package/dist/adapters/index.js.map +1 -0
  20. package/dist/cjs/adapters/MemoryAdapter.js.map +1 -0
  21. package/dist/cjs/adapters/MongoAdapter.js.map +1 -0
  22. package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -0
  23. package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -0
  24. package/dist/{src → cjs}/adapters/PrismaAdapter.d.ts.map +1 -1
  25. package/dist/cjs/{src/adapters → adapters}/PrismaAdapter.js +3 -2
  26. package/dist/cjs/adapters/PrismaAdapter.js.map +1 -0
  27. package/dist/cjs/{src/adapters → adapters}/RedisAdapter.js +2 -2
  28. package/dist/cjs/adapters/RedisAdapter.js.map +1 -0
  29. package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -0
  30. package/dist/cjs/adapters/index.js.map +1 -0
  31. package/dist/cjs/constants/index.js.map +1 -0
  32. package/dist/{src → cjs}/core/Agent.d.ts +25 -6
  33. package/dist/cjs/core/Agent.d.ts.map +1 -0
  34. package/dist/cjs/{src/core → core}/Agent.js +121 -37
  35. package/dist/cjs/core/Agent.js.map +1 -0
  36. package/dist/cjs/core/BatchExecutor.d.ts +353 -0
  37. package/dist/cjs/core/BatchExecutor.d.ts.map +1 -0
  38. package/dist/cjs/core/BatchExecutor.js +842 -0
  39. package/dist/cjs/core/BatchExecutor.js.map +1 -0
  40. package/dist/cjs/core/BatchPromptBuilder.d.ts +86 -0
  41. package/dist/cjs/core/BatchPromptBuilder.d.ts.map +1 -0
  42. package/dist/cjs/core/BatchPromptBuilder.js +201 -0
  43. package/dist/cjs/core/BatchPromptBuilder.js.map +1 -0
  44. package/dist/cjs/core/Events.js.map +1 -0
  45. package/dist/cjs/core/PersistenceManager.js.map +1 -0
  46. package/dist/{src → cjs}/core/PromptComposer.d.ts +1 -1
  47. package/dist/cjs/core/PromptComposer.d.ts.map +1 -0
  48. package/dist/cjs/{src/core → core}/PromptComposer.js +44 -7
  49. package/dist/cjs/core/PromptComposer.js.map +1 -0
  50. package/dist/{src → cjs}/core/ResponseEngine.d.ts.map +1 -1
  51. package/dist/cjs/core/ResponseEngine.js +202 -0
  52. package/dist/cjs/core/ResponseEngine.js.map +1 -0
  53. package/dist/{src → cjs}/core/ResponseModal.d.ts +54 -3
  54. package/dist/cjs/core/ResponseModal.d.ts.map +1 -0
  55. package/dist/cjs/{src/core → core}/ResponseModal.js +807 -121
  56. package/dist/cjs/core/ResponseModal.js.map +1 -0
  57. package/dist/{src → cjs}/core/ResponsePipeline.d.ts +10 -6
  58. package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -0
  59. package/dist/cjs/{src/core → core}/ResponsePipeline.js +60 -25
  60. package/dist/cjs/core/ResponsePipeline.js.map +1 -0
  61. package/dist/{src → cjs}/core/Route.d.ts +46 -10
  62. package/dist/cjs/core/Route.d.ts.map +1 -0
  63. package/dist/cjs/core/Route.js +541 -0
  64. package/dist/cjs/core/Route.js.map +1 -0
  65. package/dist/cjs/{src/core → core}/RoutingEngine.d.ts +35 -5
  66. package/dist/cjs/core/RoutingEngine.d.ts.map +1 -0
  67. package/dist/cjs/{src/core → core}/RoutingEngine.js +360 -98
  68. package/dist/cjs/core/RoutingEngine.js.map +1 -0
  69. package/dist/{src → cjs}/core/SessionManager.d.ts +9 -1
  70. package/dist/cjs/core/SessionManager.d.ts.map +1 -0
  71. package/dist/cjs/{src/core → core}/SessionManager.js +27 -5
  72. package/dist/cjs/core/SessionManager.js.map +1 -0
  73. package/dist/cjs/core/Step.d.ts +170 -0
  74. package/dist/cjs/core/Step.d.ts.map +1 -0
  75. package/dist/cjs/core/Step.js +448 -0
  76. package/dist/cjs/core/Step.js.map +1 -0
  77. package/dist/cjs/core/ToolManager.d.ts +234 -0
  78. package/dist/cjs/core/ToolManager.d.ts.map +1 -0
  79. package/dist/cjs/core/ToolManager.js +1117 -0
  80. package/dist/cjs/core/ToolManager.js.map +1 -0
  81. package/dist/{src → cjs}/index.d.ts +5 -3
  82. package/dist/cjs/index.d.ts.map +1 -0
  83. package/dist/cjs/{src/index.js → index.js} +16 -3
  84. package/dist/cjs/index.js.map +1 -0
  85. package/dist/cjs/{src/providers → providers}/AnthropicProvider.js +18 -18
  86. package/dist/cjs/providers/AnthropicProvider.js.map +1 -0
  87. package/dist/{src → cjs}/providers/GeminiProvider.d.ts.map +1 -1
  88. package/dist/cjs/{src/providers → providers}/GeminiProvider.js +123 -51
  89. package/dist/cjs/providers/GeminiProvider.js.map +1 -0
  90. package/dist/cjs/{src/providers → providers}/OpenAIProvider.js +19 -19
  91. package/dist/cjs/providers/OpenAIProvider.js.map +1 -0
  92. package/dist/cjs/{src/providers → providers}/OpenRouterProvider.js +19 -19
  93. package/dist/cjs/providers/OpenRouterProvider.js.map +1 -0
  94. package/dist/cjs/providers/index.js.map +1 -0
  95. package/dist/cjs/{src/types → types}/agent.d.ts +12 -4
  96. package/dist/cjs/types/agent.d.ts.map +1 -0
  97. package/dist/cjs/types/agent.js.map +1 -0
  98. package/dist/{src → cjs}/types/ai.js.map +1 -1
  99. package/dist/cjs/types/history.js.map +1 -0
  100. package/dist/cjs/{src/types → types}/index.d.ts +5 -3
  101. package/dist/{src → cjs}/types/index.d.ts.map +1 -1
  102. package/dist/cjs/{src/types → types}/index.js +8 -1
  103. package/dist/cjs/types/index.js.map +1 -0
  104. package/dist/cjs/types/persistence.js.map +1 -0
  105. package/dist/cjs/{src/types → types}/route.d.ts +116 -15
  106. package/dist/cjs/types/route.d.ts.map +1 -0
  107. package/dist/cjs/{src/types → types}/route.js.map +1 -1
  108. package/dist/cjs/types/session.js.map +1 -0
  109. package/dist/cjs/types/template.d.ts +88 -0
  110. package/dist/cjs/types/template.d.ts.map +1 -0
  111. package/dist/cjs/types/tool.d.ts +130 -0
  112. package/dist/cjs/types/tool.d.ts.map +1 -0
  113. package/dist/cjs/types/tool.js +19 -0
  114. package/dist/cjs/types/tool.js.map +1 -0
  115. package/dist/cjs/utils/clone.js.map +1 -0
  116. package/dist/cjs/utils/condition.d.ts +38 -0
  117. package/dist/cjs/utils/condition.d.ts.map +1 -0
  118. package/dist/cjs/utils/condition.js +168 -0
  119. package/dist/cjs/utils/condition.js.map +1 -0
  120. package/dist/cjs/utils/event.js.map +1 -0
  121. package/dist/cjs/utils/history.js.map +1 -0
  122. package/dist/cjs/utils/id.js.map +1 -0
  123. package/dist/cjs/{src/utils → utils}/index.d.ts +3 -1
  124. package/dist/cjs/utils/index.d.ts.map +1 -0
  125. package/dist/cjs/{src/utils → utils}/index.js +12 -1
  126. package/dist/cjs/utils/index.js.map +1 -0
  127. package/dist/cjs/utils/json.d.ts +16 -0
  128. package/dist/cjs/utils/json.d.ts.map +1 -0
  129. package/dist/cjs/utils/json.js +47 -0
  130. package/dist/cjs/utils/json.js.map +1 -0
  131. package/dist/cjs/utils/logger.js.map +1 -0
  132. package/dist/{src → cjs}/utils/retry.d.ts +0 -3
  133. package/dist/cjs/utils/retry.d.ts.map +1 -0
  134. package/dist/cjs/{src/utils → utils}/retry.js +8 -7
  135. package/dist/cjs/utils/retry.js.map +1 -0
  136. package/dist/cjs/utils/session.js.map +1 -0
  137. package/dist/{src → cjs}/utils/template.d.ts +48 -0
  138. package/dist/cjs/utils/template.d.ts.map +1 -0
  139. package/dist/cjs/{src/utils → utils}/template.js +100 -0
  140. package/dist/cjs/utils/template.js.map +1 -0
  141. package/dist/constants/index.d.ts.map +1 -0
  142. package/dist/constants/index.js.map +1 -0
  143. package/dist/{cjs/src/core → core}/Agent.d.ts +25 -6
  144. package/dist/core/Agent.d.ts.map +1 -0
  145. package/dist/{src/core → core}/Agent.js +122 -38
  146. package/dist/core/Agent.js.map +1 -0
  147. package/dist/core/BatchExecutor.d.ts +353 -0
  148. package/dist/core/BatchExecutor.d.ts.map +1 -0
  149. package/dist/core/BatchExecutor.js +837 -0
  150. package/dist/core/BatchExecutor.js.map +1 -0
  151. package/dist/core/BatchPromptBuilder.d.ts +86 -0
  152. package/dist/core/BatchPromptBuilder.d.ts.map +1 -0
  153. package/dist/core/BatchPromptBuilder.js +197 -0
  154. package/dist/core/BatchPromptBuilder.js.map +1 -0
  155. package/dist/core/Events.d.ts.map +1 -0
  156. package/dist/core/Events.js.map +1 -0
  157. package/dist/core/PersistenceManager.d.ts.map +1 -0
  158. package/dist/core/PersistenceManager.js.map +1 -0
  159. package/dist/{cjs/src/core → core}/PromptComposer.d.ts +1 -1
  160. package/dist/core/PromptComposer.d.ts.map +1 -0
  161. package/dist/{src/core → core}/PromptComposer.js +45 -8
  162. package/dist/core/PromptComposer.js.map +1 -0
  163. package/dist/core/ResponseEngine.d.ts.map +1 -0
  164. package/dist/core/ResponseEngine.js +198 -0
  165. package/dist/core/ResponseEngine.js.map +1 -0
  166. package/dist/{cjs/src/core → core}/ResponseModal.d.ts +54 -3
  167. package/dist/core/ResponseModal.d.ts.map +1 -0
  168. package/dist/{src/core → core}/ResponseModal.js +807 -121
  169. package/dist/core/ResponseModal.js.map +1 -0
  170. package/dist/{cjs/src/core → core}/ResponsePipeline.d.ts +10 -6
  171. package/dist/core/ResponsePipeline.d.ts.map +1 -0
  172. package/dist/{src/core → core}/ResponsePipeline.js +60 -25
  173. package/dist/core/ResponsePipeline.js.map +1 -0
  174. package/dist/{cjs/src/core → core}/Route.d.ts +46 -10
  175. package/dist/core/Route.d.ts.map +1 -0
  176. package/dist/core/Route.js +537 -0
  177. package/dist/core/Route.js.map +1 -0
  178. package/dist/{src/core → core}/RoutingEngine.d.ts +35 -5
  179. package/dist/core/RoutingEngine.d.ts.map +1 -0
  180. package/dist/{src/core → core}/RoutingEngine.js +343 -81
  181. package/dist/core/RoutingEngine.js.map +1 -0
  182. package/dist/{cjs/src/core → core}/SessionManager.d.ts +9 -1
  183. package/dist/core/SessionManager.d.ts.map +1 -0
  184. package/dist/{src/core → core}/SessionManager.js +27 -5
  185. package/dist/core/SessionManager.js.map +1 -0
  186. package/dist/core/Step.d.ts +170 -0
  187. package/dist/core/Step.d.ts.map +1 -0
  188. package/dist/core/Step.js +444 -0
  189. package/dist/core/Step.js.map +1 -0
  190. package/dist/core/ToolManager.d.ts +234 -0
  191. package/dist/core/ToolManager.d.ts.map +1 -0
  192. package/dist/core/ToolManager.js +1111 -0
  193. package/dist/core/ToolManager.js.map +1 -0
  194. package/dist/{cjs/src/index.d.ts → index.d.ts} +5 -3
  195. package/dist/index.d.ts.map +1 -0
  196. package/dist/{src/index.js → index.js} +4 -1
  197. package/dist/index.js.map +1 -0
  198. package/dist/providers/AnthropicProvider.d.ts.map +1 -0
  199. package/dist/{src/providers → providers}/AnthropicProvider.js +17 -17
  200. package/dist/providers/AnthropicProvider.js.map +1 -0
  201. package/dist/providers/GeminiProvider.d.ts.map +1 -0
  202. package/dist/{src/providers → providers}/GeminiProvider.js +123 -51
  203. package/dist/providers/GeminiProvider.js.map +1 -0
  204. package/dist/providers/OpenAIProvider.d.ts.map +1 -0
  205. package/dist/{src/providers → providers}/OpenAIProvider.js +18 -18
  206. package/dist/providers/OpenAIProvider.js.map +1 -0
  207. package/dist/providers/OpenRouterProvider.d.ts.map +1 -0
  208. package/dist/{src/providers → providers}/OpenRouterProvider.js +18 -18
  209. package/dist/providers/OpenRouterProvider.js.map +1 -0
  210. package/dist/providers/index.d.ts.map +1 -0
  211. package/dist/providers/index.js.map +1 -0
  212. package/dist/{src/types → types}/agent.d.ts +12 -4
  213. package/dist/types/agent.d.ts.map +1 -0
  214. package/dist/types/agent.js.map +1 -0
  215. package/dist/types/ai.d.ts.map +1 -0
  216. package/dist/types/ai.js.map +1 -0
  217. package/dist/types/history.d.ts.map +1 -0
  218. package/dist/types/history.js.map +1 -0
  219. package/dist/{src/types → types}/index.d.ts +5 -3
  220. package/dist/types/index.d.ts.map +1 -0
  221. package/dist/{src/types → types}/index.js +2 -0
  222. package/dist/types/index.js.map +1 -0
  223. package/dist/types/persistence.d.ts.map +1 -0
  224. package/dist/types/persistence.js.map +1 -0
  225. package/dist/{src/types → types}/route.d.ts +116 -15
  226. package/dist/types/route.d.ts.map +1 -0
  227. package/dist/{src/types → types}/route.js.map +1 -1
  228. package/dist/types/routing.d.ts.map +1 -0
  229. package/dist/{cjs/src/types → types}/routing.js.map +1 -1
  230. package/dist/types/schema.d.ts.map +1 -0
  231. package/dist/{cjs/src/types → types}/schema.js.map +1 -1
  232. package/dist/types/session.d.ts.map +1 -0
  233. package/dist/{src/types → types}/session.js.map +1 -1
  234. package/dist/types/template.d.ts +88 -0
  235. package/dist/types/template.d.ts.map +1 -0
  236. package/dist/{cjs/src/types → types}/template.js.map +1 -1
  237. package/dist/types/tool.d.ts +130 -0
  238. package/dist/types/tool.d.ts.map +1 -0
  239. package/dist/types/tool.js +16 -0
  240. package/dist/types/tool.js.map +1 -0
  241. package/dist/utils/clone.d.ts.map +1 -0
  242. package/dist/utils/clone.js.map +1 -0
  243. package/dist/utils/condition.d.ts +38 -0
  244. package/dist/utils/condition.d.ts.map +1 -0
  245. package/dist/utils/condition.js +161 -0
  246. package/dist/utils/condition.js.map +1 -0
  247. package/dist/utils/event.d.ts.map +1 -0
  248. package/dist/utils/event.js.map +1 -0
  249. package/dist/utils/history.d.ts.map +1 -0
  250. package/dist/utils/history.js.map +1 -0
  251. package/dist/utils/id.d.ts.map +1 -0
  252. package/dist/utils/id.js.map +1 -0
  253. package/dist/{src/utils → utils}/index.d.ts +3 -1
  254. package/dist/utils/index.d.ts.map +1 -0
  255. package/dist/{src/utils → utils}/index.js +5 -1
  256. package/dist/utils/index.js.map +1 -0
  257. package/dist/utils/json.d.ts +16 -0
  258. package/dist/utils/json.d.ts.map +1 -0
  259. package/dist/utils/json.js +43 -0
  260. package/dist/utils/json.js.map +1 -0
  261. package/dist/utils/logger.d.ts.map +1 -0
  262. package/dist/utils/logger.js.map +1 -0
  263. package/dist/{cjs/src/utils → utils}/retry.d.ts +0 -3
  264. package/dist/utils/retry.d.ts.map +1 -0
  265. package/dist/{src/utils → utils}/retry.js +5 -4
  266. package/dist/utils/retry.js.map +1 -0
  267. package/dist/utils/session.d.ts.map +1 -0
  268. package/dist/utils/session.js.map +1 -0
  269. package/dist/{cjs/src/utils → utils}/template.d.ts +48 -0
  270. package/dist/utils/template.d.ts.map +1 -0
  271. package/dist/{src/utils → utils}/template.js +98 -0
  272. package/dist/utils/template.js.map +1 -0
  273. package/docs/CONTRIBUTING.md +40 -0
  274. package/docs/README.md +12 -5
  275. package/docs/api/README.md +295 -56
  276. package/docs/api/overview.md +272 -31
  277. package/docs/architecture/data-extraction-flow.md +363 -0
  278. package/docs/architecture/multi-step-execution.md +243 -0
  279. package/docs/core/agent/README.md +120 -5
  280. package/docs/core/agent/session-management.md +153 -6
  281. package/docs/core/ai-integration/prompt-composition.md +135 -0
  282. package/docs/core/ai-integration/response-processing.md +261 -4
  283. package/docs/core/conversation-flows/data-collection.md +143 -0
  284. package/docs/core/conversation-flows/routes.md +132 -2
  285. package/docs/core/conversation-flows/step-transitions.md +132 -0
  286. package/docs/core/conversation-flows/steps.md +112 -0
  287. package/docs/core/error-handling.md +831 -0
  288. package/docs/core/routing/intelligent-routing.md +118 -0
  289. package/docs/core/tools/tool-definition.md +684 -60
  290. package/docs/core/tools/tool-scoping.md +244 -53
  291. package/docs/guides/error-handling-patterns.md +578 -0
  292. package/docs/guides/getting-started/README.md +423 -31
  293. package/docs/guides/migration/README.md +23 -0
  294. package/docs/guides/migration/flexible-routing-conditions.md +375 -0
  295. package/docs/guides/migration/multi-step-execution.md +303 -0
  296. package/examples/advanced-patterns/knowledge-based-agent.ts +107 -30
  297. package/examples/advanced-patterns/persistent-onboarding.ts +70 -48
  298. package/examples/advanced-patterns/route-lifecycle-hooks.ts +82 -12
  299. package/examples/advanced-patterns/streaming-responses.ts +2 -2
  300. package/examples/ai-providers/anthropic-integration.ts +13 -9
  301. package/examples/ai-providers/openai-integration.ts +12 -8
  302. package/examples/condition-patterns/function-only-conditions.ts +365 -0
  303. package/examples/condition-patterns/mixed-array-conditions.ts +477 -0
  304. package/examples/condition-patterns/route-skipif-patterns.ts +468 -0
  305. package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
  306. package/examples/condition-patterns/string-only-conditions.ts +296 -0
  307. package/examples/conversation-flows/completion-transitions.ts +48 -7
  308. package/examples/core-concepts/basic-agent.ts +158 -98
  309. package/examples/core-concepts/schema-driven-extraction.ts +43 -16
  310. package/examples/core-concepts/session-management.ts +117 -29
  311. package/examples/integrations/database-integration.ts +6 -6
  312. package/examples/integrations/healthcare-integration.ts +25 -39
  313. package/examples/integrations/search-integration.ts +8 -8
  314. package/examples/integrations/server-session-management.ts +11 -11
  315. package/examples/persistence/database-persistence.ts +15 -15
  316. package/examples/persistence/memory-sessions.ts +6 -6
  317. package/examples/persistence/redis-persistence.ts +7 -9
  318. package/examples/tools/basic-tools.ts +293 -89
  319. package/examples/tools/data-enrichment-tools.ts +189 -79
  320. package/package.json +6 -4
  321. package/src/adapters/PrismaAdapter.ts +3 -2
  322. package/src/adapters/RedisAdapter.ts +3 -3
  323. package/src/core/Agent.ts +152 -46
  324. package/src/core/BatchExecutor.ts +1156 -0
  325. package/src/core/BatchPromptBuilder.ts +275 -0
  326. package/src/core/PromptComposer.ts +53 -16
  327. package/src/core/ResponseEngine.ts +143 -4
  328. package/src/core/ResponseModal.ts +1035 -137
  329. package/src/core/ResponsePipeline.ts +99 -65
  330. package/src/core/Route.ts +262 -34
  331. package/src/core/RoutingEngine.ts +467 -120
  332. package/src/core/SessionManager.ts +39 -7
  333. package/src/core/Step.ts +338 -32
  334. package/src/core/ToolManager.ts +1394 -0
  335. package/src/index.ts +27 -3
  336. package/src/providers/AnthropicProvider.ts +17 -17
  337. package/src/providers/GeminiProvider.ts +129 -60
  338. package/src/providers/OpenAIProvider.ts +18 -18
  339. package/src/providers/OpenRouterProvider.ts +18 -18
  340. package/src/types/agent.ts +12 -4
  341. package/src/types/index.ts +25 -3
  342. package/src/types/route.ts +136 -15
  343. package/src/types/template.ts +70 -2
  344. package/src/types/tool.ts +116 -25
  345. package/src/utils/condition.ts +190 -0
  346. package/src/utils/index.ts +12 -0
  347. package/src/utils/json.ts +46 -0
  348. package/src/utils/retry.ts +5 -4
  349. package/src/utils/template.ts +109 -0
  350. package/dist/cjs/src/adapters/MemoryAdapter.d.ts.map +0 -1
  351. package/dist/cjs/src/adapters/MemoryAdapter.js.map +0 -1
  352. package/dist/cjs/src/adapters/MongoAdapter.d.ts.map +0 -1
  353. package/dist/cjs/src/adapters/MongoAdapter.js.map +0 -1
  354. package/dist/cjs/src/adapters/OpenSearchAdapter.d.ts.map +0 -1
  355. package/dist/cjs/src/adapters/OpenSearchAdapter.js.map +0 -1
  356. package/dist/cjs/src/adapters/PostgreSQLAdapter.d.ts.map +0 -1
  357. package/dist/cjs/src/adapters/PostgreSQLAdapter.js.map +0 -1
  358. package/dist/cjs/src/adapters/PrismaAdapter.d.ts.map +0 -1
  359. package/dist/cjs/src/adapters/PrismaAdapter.js.map +0 -1
  360. package/dist/cjs/src/adapters/RedisAdapter.d.ts.map +0 -1
  361. package/dist/cjs/src/adapters/RedisAdapter.js.map +0 -1
  362. package/dist/cjs/src/adapters/SQLiteAdapter.d.ts.map +0 -1
  363. package/dist/cjs/src/adapters/SQLiteAdapter.js.map +0 -1
  364. package/dist/cjs/src/adapters/index.d.ts.map +0 -1
  365. package/dist/cjs/src/adapters/index.js.map +0 -1
  366. package/dist/cjs/src/constants/index.d.ts.map +0 -1
  367. package/dist/cjs/src/constants/index.js.map +0 -1
  368. package/dist/cjs/src/core/Agent.d.ts.map +0 -1
  369. package/dist/cjs/src/core/Agent.js.map +0 -1
  370. package/dist/cjs/src/core/Events.d.ts.map +0 -1
  371. package/dist/cjs/src/core/Events.js.map +0 -1
  372. package/dist/cjs/src/core/PersistenceManager.d.ts.map +0 -1
  373. package/dist/cjs/src/core/PersistenceManager.js.map +0 -1
  374. package/dist/cjs/src/core/PromptComposer.d.ts.map +0 -1
  375. package/dist/cjs/src/core/PromptComposer.js.map +0 -1
  376. package/dist/cjs/src/core/ResponseEngine.d.ts.map +0 -1
  377. package/dist/cjs/src/core/ResponseEngine.js +0 -84
  378. package/dist/cjs/src/core/ResponseEngine.js.map +0 -1
  379. package/dist/cjs/src/core/ResponseModal.d.ts.map +0 -1
  380. package/dist/cjs/src/core/ResponseModal.js.map +0 -1
  381. package/dist/cjs/src/core/ResponsePipeline.d.ts.map +0 -1
  382. package/dist/cjs/src/core/ResponsePipeline.js.map +0 -1
  383. package/dist/cjs/src/core/Route.d.ts.map +0 -1
  384. package/dist/cjs/src/core/Route.js +0 -343
  385. package/dist/cjs/src/core/Route.js.map +0 -1
  386. package/dist/cjs/src/core/RoutingEngine.d.ts.map +0 -1
  387. package/dist/cjs/src/core/RoutingEngine.js.map +0 -1
  388. package/dist/cjs/src/core/SessionManager.d.ts.map +0 -1
  389. package/dist/cjs/src/core/SessionManager.js.map +0 -1
  390. package/dist/cjs/src/core/Step.d.ts +0 -96
  391. package/dist/cjs/src/core/Step.d.ts.map +0 -1
  392. package/dist/cjs/src/core/Step.js +0 -206
  393. package/dist/cjs/src/core/Step.js.map +0 -1
  394. package/dist/cjs/src/core/ToolExecutor.d.ts +0 -45
  395. package/dist/cjs/src/core/ToolExecutor.d.ts.map +0 -1
  396. package/dist/cjs/src/core/ToolExecutor.js +0 -84
  397. package/dist/cjs/src/core/ToolExecutor.js.map +0 -1
  398. package/dist/cjs/src/index.d.ts.map +0 -1
  399. package/dist/cjs/src/index.js.map +0 -1
  400. package/dist/cjs/src/providers/AnthropicProvider.d.ts.map +0 -1
  401. package/dist/cjs/src/providers/AnthropicProvider.js.map +0 -1
  402. package/dist/cjs/src/providers/GeminiProvider.d.ts.map +0 -1
  403. package/dist/cjs/src/providers/GeminiProvider.js.map +0 -1
  404. package/dist/cjs/src/providers/OpenAIProvider.d.ts.map +0 -1
  405. package/dist/cjs/src/providers/OpenAIProvider.js.map +0 -1
  406. package/dist/cjs/src/providers/OpenRouterProvider.d.ts.map +0 -1
  407. package/dist/cjs/src/providers/OpenRouterProvider.js.map +0 -1
  408. package/dist/cjs/src/providers/index.d.ts.map +0 -1
  409. package/dist/cjs/src/providers/index.js.map +0 -1
  410. package/dist/cjs/src/types/agent.d.ts.map +0 -1
  411. package/dist/cjs/src/types/agent.js.map +0 -1
  412. package/dist/cjs/src/types/ai.d.ts.map +0 -1
  413. package/dist/cjs/src/types/ai.js.map +0 -1
  414. package/dist/cjs/src/types/history.d.ts.map +0 -1
  415. package/dist/cjs/src/types/history.js.map +0 -1
  416. package/dist/cjs/src/types/index.d.ts.map +0 -1
  417. package/dist/cjs/src/types/index.js.map +0 -1
  418. package/dist/cjs/src/types/persistence.d.ts.map +0 -1
  419. package/dist/cjs/src/types/persistence.js.map +0 -1
  420. package/dist/cjs/src/types/route.d.ts.map +0 -1
  421. package/dist/cjs/src/types/routing.d.ts.map +0 -1
  422. package/dist/cjs/src/types/schema.d.ts.map +0 -1
  423. package/dist/cjs/src/types/session.d.ts.map +0 -1
  424. package/dist/cjs/src/types/session.js.map +0 -1
  425. package/dist/cjs/src/types/template.d.ts +0 -30
  426. package/dist/cjs/src/types/template.d.ts.map +0 -1
  427. package/dist/cjs/src/types/tool.d.ts +0 -60
  428. package/dist/cjs/src/types/tool.d.ts.map +0 -1
  429. package/dist/cjs/src/types/tool.js +0 -6
  430. package/dist/cjs/src/types/tool.js.map +0 -1
  431. package/dist/cjs/src/utils/clone.d.ts.map +0 -1
  432. package/dist/cjs/src/utils/clone.js.map +0 -1
  433. package/dist/cjs/src/utils/event.d.ts.map +0 -1
  434. package/dist/cjs/src/utils/event.js.map +0 -1
  435. package/dist/cjs/src/utils/history.d.ts.map +0 -1
  436. package/dist/cjs/src/utils/history.js.map +0 -1
  437. package/dist/cjs/src/utils/id.d.ts.map +0 -1
  438. package/dist/cjs/src/utils/id.js.map +0 -1
  439. package/dist/cjs/src/utils/index.d.ts.map +0 -1
  440. package/dist/cjs/src/utils/index.js.map +0 -1
  441. package/dist/cjs/src/utils/logger.d.ts.map +0 -1
  442. package/dist/cjs/src/utils/logger.js.map +0 -1
  443. package/dist/cjs/src/utils/retry.d.ts.map +0 -1
  444. package/dist/cjs/src/utils/retry.js.map +0 -1
  445. package/dist/cjs/src/utils/session.d.ts.map +0 -1
  446. package/dist/cjs/src/utils/session.js.map +0 -1
  447. package/dist/cjs/src/utils/template.d.ts.map +0 -1
  448. package/dist/cjs/src/utils/template.js.map +0 -1
  449. package/dist/src/adapters/MemoryAdapter.js.map +0 -1
  450. package/dist/src/adapters/MongoAdapter.js.map +0 -1
  451. package/dist/src/adapters/OpenSearchAdapter.js.map +0 -1
  452. package/dist/src/adapters/PostgreSQLAdapter.js.map +0 -1
  453. package/dist/src/adapters/PrismaAdapter.js.map +0 -1
  454. package/dist/src/adapters/RedisAdapter.js.map +0 -1
  455. package/dist/src/adapters/SQLiteAdapter.js.map +0 -1
  456. package/dist/src/adapters/index.js.map +0 -1
  457. package/dist/src/constants/index.js.map +0 -1
  458. package/dist/src/core/Agent.d.ts.map +0 -1
  459. package/dist/src/core/Agent.js.map +0 -1
  460. package/dist/src/core/Events.js.map +0 -1
  461. package/dist/src/core/PersistenceManager.js.map +0 -1
  462. package/dist/src/core/PromptComposer.d.ts.map +0 -1
  463. package/dist/src/core/PromptComposer.js.map +0 -1
  464. package/dist/src/core/ResponseEngine.js +0 -80
  465. package/dist/src/core/ResponseEngine.js.map +0 -1
  466. package/dist/src/core/ResponseModal.d.ts.map +0 -1
  467. package/dist/src/core/ResponseModal.js.map +0 -1
  468. package/dist/src/core/ResponsePipeline.d.ts.map +0 -1
  469. package/dist/src/core/ResponsePipeline.js.map +0 -1
  470. package/dist/src/core/Route.d.ts.map +0 -1
  471. package/dist/src/core/Route.js +0 -339
  472. package/dist/src/core/Route.js.map +0 -1
  473. package/dist/src/core/RoutingEngine.d.ts.map +0 -1
  474. package/dist/src/core/RoutingEngine.js.map +0 -1
  475. package/dist/src/core/SessionManager.d.ts.map +0 -1
  476. package/dist/src/core/SessionManager.js.map +0 -1
  477. package/dist/src/core/Step.d.ts +0 -96
  478. package/dist/src/core/Step.d.ts.map +0 -1
  479. package/dist/src/core/Step.js +0 -202
  480. package/dist/src/core/Step.js.map +0 -1
  481. package/dist/src/core/ToolExecutor.d.ts +0 -45
  482. package/dist/src/core/ToolExecutor.d.ts.map +0 -1
  483. package/dist/src/core/ToolExecutor.js +0 -80
  484. package/dist/src/core/ToolExecutor.js.map +0 -1
  485. package/dist/src/index.d.ts.map +0 -1
  486. package/dist/src/index.js.map +0 -1
  487. package/dist/src/providers/AnthropicProvider.js.map +0 -1
  488. package/dist/src/providers/GeminiProvider.js.map +0 -1
  489. package/dist/src/providers/OpenAIProvider.js.map +0 -1
  490. package/dist/src/providers/OpenRouterProvider.js.map +0 -1
  491. package/dist/src/providers/index.js.map +0 -1
  492. package/dist/src/types/agent.d.ts.map +0 -1
  493. package/dist/src/types/agent.js.map +0 -1
  494. package/dist/src/types/history.js.map +0 -1
  495. package/dist/src/types/index.js.map +0 -1
  496. package/dist/src/types/persistence.js.map +0 -1
  497. package/dist/src/types/route.d.ts.map +0 -1
  498. package/dist/src/types/template.d.ts +0 -30
  499. package/dist/src/types/template.d.ts.map +0 -1
  500. package/dist/src/types/tool.d.ts +0 -60
  501. package/dist/src/types/tool.d.ts.map +0 -1
  502. package/dist/src/types/tool.js +0 -5
  503. package/dist/src/types/tool.js.map +0 -1
  504. package/dist/src/utils/clone.js.map +0 -1
  505. package/dist/src/utils/event.js.map +0 -1
  506. package/dist/src/utils/history.js.map +0 -1
  507. package/dist/src/utils/id.js.map +0 -1
  508. package/dist/src/utils/index.d.ts.map +0 -1
  509. package/dist/src/utils/index.js.map +0 -1
  510. package/dist/src/utils/logger.js.map +0 -1
  511. package/dist/src/utils/retry.d.ts.map +0 -1
  512. package/dist/src/utils/retry.js.map +0 -1
  513. package/dist/src/utils/session.js.map +0 -1
  514. package/dist/src/utils/template.d.ts.map +0 -1
  515. package/dist/src/utils/template.js.map +0 -1
  516. package/docs/core/tools/tool-execution.md +0 -815
  517. package/src/core/ToolExecutor.ts +0 -126
  518. /package/dist/{cjs/src/adapters → adapters}/MemoryAdapter.d.ts +0 -0
  519. /package/dist/{src/adapters → adapters}/MemoryAdapter.js +0 -0
  520. /package/dist/{cjs/src/adapters → adapters}/MongoAdapter.d.ts +0 -0
  521. /package/dist/{src/adapters → adapters}/MongoAdapter.js +0 -0
  522. /package/dist/{cjs/src/adapters → adapters}/OpenSearchAdapter.d.ts +0 -0
  523. /package/dist/{src/adapters → adapters}/OpenSearchAdapter.js +0 -0
  524. /package/dist/{cjs/src/adapters → adapters}/PostgreSQLAdapter.d.ts +0 -0
  525. /package/dist/{src/adapters → adapters}/PostgreSQLAdapter.js +0 -0
  526. /package/dist/{cjs/src/adapters → adapters}/PrismaAdapter.d.ts +0 -0
  527. /package/dist/{cjs/src/adapters → adapters}/RedisAdapter.d.ts +0 -0
  528. /package/dist/{cjs/src/adapters → adapters}/SQLiteAdapter.d.ts +0 -0
  529. /package/dist/{src/adapters → adapters}/SQLiteAdapter.js +0 -0
  530. /package/dist/{cjs/src/adapters → adapters}/index.d.ts +0 -0
  531. /package/dist/{src/adapters → adapters}/index.js +0 -0
  532. /package/dist/{src → cjs}/adapters/MemoryAdapter.d.ts +0 -0
  533. /package/dist/{src → cjs}/adapters/MemoryAdapter.d.ts.map +0 -0
  534. /package/dist/cjs/{src/adapters → adapters}/MemoryAdapter.js +0 -0
  535. /package/dist/{src → cjs}/adapters/MongoAdapter.d.ts +0 -0
  536. /package/dist/{src → cjs}/adapters/MongoAdapter.d.ts.map +0 -0
  537. /package/dist/cjs/{src/adapters → adapters}/MongoAdapter.js +0 -0
  538. /package/dist/{src → cjs}/adapters/OpenSearchAdapter.d.ts +0 -0
  539. /package/dist/{src → cjs}/adapters/OpenSearchAdapter.d.ts.map +0 -0
  540. /package/dist/cjs/{src/adapters → adapters}/OpenSearchAdapter.js +0 -0
  541. /package/dist/{src → cjs}/adapters/PostgreSQLAdapter.d.ts +0 -0
  542. /package/dist/{src → cjs}/adapters/PostgreSQLAdapter.d.ts.map +0 -0
  543. /package/dist/cjs/{src/adapters → adapters}/PostgreSQLAdapter.js +0 -0
  544. /package/dist/{src → cjs}/adapters/PrismaAdapter.d.ts +0 -0
  545. /package/dist/{src → cjs}/adapters/RedisAdapter.d.ts +0 -0
  546. /package/dist/{src → cjs}/adapters/RedisAdapter.d.ts.map +0 -0
  547. /package/dist/{src → cjs}/adapters/SQLiteAdapter.d.ts +0 -0
  548. /package/dist/{src → cjs}/adapters/SQLiteAdapter.d.ts.map +0 -0
  549. /package/dist/cjs/{src/adapters → adapters}/SQLiteAdapter.js +0 -0
  550. /package/dist/{src → cjs}/adapters/index.d.ts +0 -0
  551. /package/dist/{src → cjs}/adapters/index.d.ts.map +0 -0
  552. /package/dist/cjs/{src/adapters → adapters}/index.js +0 -0
  553. /package/dist/cjs/{src/constants → constants}/index.d.ts +0 -0
  554. /package/dist/{src → cjs}/constants/index.d.ts.map +0 -0
  555. /package/dist/cjs/{src/constants → constants}/index.js +0 -0
  556. /package/dist/cjs/{src/core → core}/Events.d.ts +0 -0
  557. /package/dist/{src → cjs}/core/Events.d.ts.map +0 -0
  558. /package/dist/cjs/{src/core → core}/Events.js +0 -0
  559. /package/dist/cjs/{src/core → core}/PersistenceManager.d.ts +0 -0
  560. /package/dist/{src → cjs}/core/PersistenceManager.d.ts.map +0 -0
  561. /package/dist/cjs/{src/core → core}/PersistenceManager.js +0 -0
  562. /package/dist/cjs/{src/core → core}/ResponseEngine.d.ts +0 -0
  563. /package/dist/cjs/{src/providers → providers}/AnthropicProvider.d.ts +0 -0
  564. /package/dist/{src → cjs}/providers/AnthropicProvider.d.ts.map +0 -0
  565. /package/dist/cjs/{src/providers → providers}/GeminiProvider.d.ts +0 -0
  566. /package/dist/cjs/{src/providers → providers}/OpenAIProvider.d.ts +0 -0
  567. /package/dist/{src → cjs}/providers/OpenAIProvider.d.ts.map +0 -0
  568. /package/dist/cjs/{src/providers → providers}/OpenRouterProvider.d.ts +0 -0
  569. /package/dist/{src → cjs}/providers/OpenRouterProvider.d.ts.map +0 -0
  570. /package/dist/cjs/{src/providers → providers}/index.d.ts +0 -0
  571. /package/dist/{src → cjs}/providers/index.d.ts.map +0 -0
  572. /package/dist/cjs/{src/providers → providers}/index.js +0 -0
  573. /package/dist/cjs/{src/types → types}/agent.js +0 -0
  574. /package/dist/cjs/{src/types → types}/ai.d.ts +0 -0
  575. /package/dist/{src → cjs}/types/ai.d.ts.map +0 -0
  576. /package/dist/cjs/{src/types → types}/ai.js +0 -0
  577. /package/dist/cjs/{src/types → types}/history.d.ts +0 -0
  578. /package/dist/{src → cjs}/types/history.d.ts.map +0 -0
  579. /package/dist/cjs/{src/types → types}/history.js +0 -0
  580. /package/dist/cjs/{src/types → types}/persistence.d.ts +0 -0
  581. /package/dist/{src → cjs}/types/persistence.d.ts.map +0 -0
  582. /package/dist/cjs/{src/types → types}/persistence.js +0 -0
  583. /package/dist/cjs/{src/types → types}/route.js +0 -0
  584. /package/dist/cjs/{src/types → types}/routing.d.ts +0 -0
  585. /package/dist/{src → cjs}/types/routing.d.ts.map +0 -0
  586. /package/dist/cjs/{src/types → types}/routing.js +0 -0
  587. /package/dist/{src → cjs}/types/routing.js.map +0 -0
  588. /package/dist/cjs/{src/types → types}/schema.d.ts +0 -0
  589. /package/dist/{src → cjs}/types/schema.d.ts.map +0 -0
  590. /package/dist/cjs/{src/types → types}/schema.js +0 -0
  591. /package/dist/{src → cjs}/types/schema.js.map +0 -0
  592. /package/dist/cjs/{src/types → types}/session.d.ts +0 -0
  593. /package/dist/{src → cjs}/types/session.d.ts.map +0 -0
  594. /package/dist/cjs/{src/types → types}/session.js +0 -0
  595. /package/dist/cjs/{src/types → types}/template.js +0 -0
  596. /package/dist/{src → cjs}/types/template.js.map +0 -0
  597. /package/dist/cjs/{src/utils → utils}/clone.d.ts +0 -0
  598. /package/dist/{src → cjs}/utils/clone.d.ts.map +0 -0
  599. /package/dist/cjs/{src/utils → utils}/clone.js +0 -0
  600. /package/dist/cjs/{src/utils → utils}/event.d.ts +0 -0
  601. /package/dist/{src → cjs}/utils/event.d.ts.map +0 -0
  602. /package/dist/cjs/{src/utils → utils}/event.js +0 -0
  603. /package/dist/cjs/{src/utils → utils}/history.d.ts +0 -0
  604. /package/dist/{src → cjs}/utils/history.d.ts.map +0 -0
  605. /package/dist/cjs/{src/utils → utils}/history.js +0 -0
  606. /package/dist/cjs/{src/utils → utils}/id.d.ts +0 -0
  607. /package/dist/{src → cjs}/utils/id.d.ts.map +0 -0
  608. /package/dist/cjs/{src/utils → utils}/id.js +0 -0
  609. /package/dist/cjs/{src/utils → utils}/logger.d.ts +0 -0
  610. /package/dist/{src → cjs}/utils/logger.d.ts.map +0 -0
  611. /package/dist/cjs/{src/utils → utils}/logger.js +0 -0
  612. /package/dist/cjs/{src/utils → utils}/session.d.ts +0 -0
  613. /package/dist/{src → cjs}/utils/session.d.ts.map +0 -0
  614. /package/dist/cjs/{src/utils → utils}/session.js +0 -0
  615. /package/dist/{src/constants → constants}/index.d.ts +0 -0
  616. /package/dist/{src/constants → constants}/index.js +0 -0
  617. /package/dist/{src/core → core}/Events.d.ts +0 -0
  618. /package/dist/{src/core → core}/Events.js +0 -0
  619. /package/dist/{src/core → core}/PersistenceManager.d.ts +0 -0
  620. /package/dist/{src/core → core}/PersistenceManager.js +0 -0
  621. /package/dist/{src/core → core}/ResponseEngine.d.ts +0 -0
  622. /package/dist/{src/providers → providers}/AnthropicProvider.d.ts +0 -0
  623. /package/dist/{src/providers → providers}/GeminiProvider.d.ts +0 -0
  624. /package/dist/{src/providers → providers}/OpenAIProvider.d.ts +0 -0
  625. /package/dist/{src/providers → providers}/OpenRouterProvider.d.ts +0 -0
  626. /package/dist/{src/providers → providers}/index.d.ts +0 -0
  627. /package/dist/{src/providers → providers}/index.js +0 -0
  628. /package/dist/{src/types → types}/agent.js +0 -0
  629. /package/dist/{src/types → types}/ai.d.ts +0 -0
  630. /package/dist/{src/types → types}/ai.js +0 -0
  631. /package/dist/{src/types → types}/history.d.ts +0 -0
  632. /package/dist/{src/types → types}/history.js +0 -0
  633. /package/dist/{src/types → types}/persistence.d.ts +0 -0
  634. /package/dist/{src/types → types}/persistence.js +0 -0
  635. /package/dist/{src/types → types}/route.js +0 -0
  636. /package/dist/{src/types → types}/routing.d.ts +0 -0
  637. /package/dist/{src/types → types}/routing.js +0 -0
  638. /package/dist/{src/types → types}/schema.d.ts +0 -0
  639. /package/dist/{src/types → types}/schema.js +0 -0
  640. /package/dist/{src/types → types}/session.d.ts +0 -0
  641. /package/dist/{src/types → types}/session.js +0 -0
  642. /package/dist/{src/types → types}/template.js +0 -0
  643. /package/dist/{src/utils → utils}/clone.d.ts +0 -0
  644. /package/dist/{src/utils → utils}/clone.js +0 -0
  645. /package/dist/{src/utils → utils}/event.d.ts +0 -0
  646. /package/dist/{src/utils → utils}/event.js +0 -0
  647. /package/dist/{src/utils → utils}/history.d.ts +0 -0
  648. /package/dist/{src/utils → utils}/history.js +0 -0
  649. /package/dist/{src/utils → utils}/id.d.ts +0 -0
  650. /package/dist/{src/utils → utils}/id.js +0 -0
  651. /package/dist/{src/utils → utils}/logger.d.ts +0 -0
  652. /package/dist/{src/utils → utils}/logger.js +0 -0
  653. /package/dist/{src/utils → utils}/session.d.ts +0 -0
  654. /package/dist/{src/utils → utils}/session.js +0 -0
@@ -1,47 +1,59 @@
1
1
  import { enterRoute, mergeCollected } from "../utils";
2
2
  import { PromptComposer } from "./PromptComposer";
3
- import { getLastMessageFromHistory } from "../utils/event";
4
- import { logger } from "../utils/logger";
5
- import { render } from "../utils/template";
6
3
  import { END_ROUTE_ID } from "../constants";
4
+ import { createTemplateContext, getLastMessageFromHistory, logger } from "../utils";
7
5
  export class RoutingEngine {
8
6
  constructor(options) {
9
7
  this.options = options;
10
8
  }
11
9
  /**
12
- * Optimized decision for single-route scenarios
13
- * Skips route scoring and only does step selection
10
+ * Enter a route if not already in it, merging initial data
14
11
  * @private
15
12
  */
16
- async decideSingleRouteStep(params) {
17
- const { route, session, history, agentOptions, provider, context, signal } = params;
18
- let updatedSession = session;
19
- const selectedRoute = route;
20
- // Check if this single route is complete
21
- const completedRoutes = route.isComplete(session.data || {}) ? [route] : [];
22
- // Enter route if not already in it
13
+ enterRouteIfNeeded(session, route) {
23
14
  if (!session.currentRoute || session.currentRoute.id !== route.id) {
24
- updatedSession = enterRoute(session, route.id, route.title);
15
+ let updatedSession = enterRoute(session, route.id, route.title);
25
16
  if (route.initialData) {
26
17
  updatedSession = mergeCollected(updatedSession, route.initialData);
27
- logger.debug(`[RoutingEngine] Single-route: Merged initial data:`, route.initialData);
18
+ logger.debug(`[RoutingEngine] Merged initial data for route ${route.title}:`, route.initialData);
28
19
  }
29
- logger.debug(`[RoutingEngine] Single-route: Entered route: ${route.title}`);
20
+ logger.debug(`[RoutingEngine] Entered route: ${route.title}`);
21
+ return updatedSession;
30
22
  }
31
- // Get candidate steps
23
+ return session;
24
+ }
25
+ /**
26
+ * Optimized decision for single-route scenarios
27
+ * Skips route scoring and only does step selection
28
+ * @private
29
+ */
30
+ async decideSingleRouteStep(params) {
31
+ const { route, session, history, agentOptions, provider, context, signal } = params;
32
+ const selectedRoute = route;
33
+ // Enter route if not already in it (this may merge initial data)
34
+ const updatedSession = this.enterRouteIfNeeded(session, route);
35
+ // Check if this single route is complete (use updated session data)
36
+ const completedRoutes = route.isComplete(updatedSession.data || {}) ? [route] : [];
37
+ // Get candidate steps using new condition evaluation
38
+ const templateContext = createTemplateContext({
39
+ context,
40
+ session: updatedSession,
41
+ history,
42
+ data: updatedSession.data
43
+ });
32
44
  const currentStep = updatedSession.currentStep
33
45
  ? route.getStep(updatedSession.currentStep.id)
34
46
  : undefined;
35
- const candidates = this.getCandidateSteps(route, currentStep, updatedSession.data || {});
47
+ const candidates = await this.getCandidateStepsWithConditions(route, currentStep, templateContext);
36
48
  if (candidates.length === 0) {
37
49
  logger.warn(`[RoutingEngine] Single-route: No valid steps found`);
38
50
  return { selectedRoute, session: updatedSession };
39
51
  }
40
- // If only one candidate, check if route is complete
52
+ // If only one candidate, check if it's a completion marker
41
53
  if (candidates.length === 1) {
42
- const isRouteComplete = candidates[0].isRouteComplete;
43
- if (isRouteComplete) {
44
- logger.debug(`[RoutingEngine] Single-route: Route complete - all data collected, END_ROUTE reached`);
54
+ const candidate = candidates[0];
55
+ if (candidate.isRouteComplete) {
56
+ logger.debug(`[RoutingEngine] Single-route: Route complete - all required fields collected or END_ROUTE reached`);
45
57
  // Don't return a selectedStep when route is complete - there's no step to enter
46
58
  return {
47
59
  selectedRoute,
@@ -52,18 +64,39 @@ export class RoutingEngine {
52
64
  };
53
65
  }
54
66
  else {
55
- logger.debug(`[RoutingEngine] Single-route: Only one valid step: ${candidates[0].step.id}`);
67
+ logger.debug(`[RoutingEngine] Single-route: Only one valid step: ${candidate.step.id}`);
56
68
  return {
57
69
  selectedRoute,
58
- selectedStep: candidates[0].step,
70
+ selectedStep: candidate.step,
59
71
  session: updatedSession,
60
72
  isRouteComplete: false,
61
73
  completedRoutes,
62
74
  };
63
75
  }
64
76
  }
77
+ // No candidates means route is likely complete or has no valid next steps
78
+ if (candidates.length === 0) {
79
+ const dataComplete = route.isComplete(updatedSession.data || {});
80
+ logger.debug(`[RoutingEngine] Single-route: No valid steps found - ` +
81
+ `(data: ${dataComplete ? 'complete' : 'incomplete'}, marking as ${dataComplete ? 'complete' : 'incomplete'})`);
82
+ return {
83
+ selectedRoute,
84
+ selectedStep: undefined,
85
+ session: updatedSession,
86
+ isRouteComplete: dataComplete,
87
+ completedRoutes,
88
+ };
89
+ }
65
90
  // Multiple candidates - use AI to select best step
66
91
  const lastUserMessage = getLastMessageFromHistory(history);
92
+ // Collect AI context strings from step conditions
93
+ const stepConditionContext = [];
94
+ for (const candidate of candidates) {
95
+ const whenResult = await candidate.step.evaluateWhen(templateContext);
96
+ stepConditionContext.push(...whenResult.aiContextStrings);
97
+ }
98
+ // Check if any candidate is a completion marker (isRouteComplete = true)
99
+ const hasCompletionOption = candidates.some(c => c.isRouteComplete);
67
100
  const stepPrompt = await this.buildStepSelectionPrompt({
68
101
  route,
69
102
  currentStep,
@@ -74,8 +107,10 @@ export class RoutingEngine {
74
107
  agentOptions,
75
108
  context,
76
109
  session: updatedSession,
110
+ stepConditionContext,
111
+ includeEndRoute: hasCompletionOption,
77
112
  });
78
- const stepSchema = this.buildStepSelectionSchema(candidates.map((c) => c.step));
113
+ const stepSchema = this.buildStepSelectionSchema(candidates.filter(c => !c.isRouteComplete).map((c) => c.step), hasCompletionOption);
79
114
  const stepResult = await provider.generateMessage({
80
115
  prompt: stepPrompt,
81
116
  history,
@@ -87,6 +122,19 @@ export class RoutingEngine {
87
122
  },
88
123
  });
89
124
  const selectedStepId = stepResult.structured?.selectedStepId;
125
+ // Check if AI selected END_ROUTE
126
+ if (selectedStepId === END_ROUTE_ID) {
127
+ logger.debug(`[RoutingEngine] Single-route: AI selected END_ROUTE - completing route`);
128
+ logger.debug(`[RoutingEngine] Single-route: Reasoning: ${stepResult.structured?.reasoning}`);
129
+ return {
130
+ selectedRoute,
131
+ selectedStep: undefined,
132
+ responseDirectives: stepResult.structured?.responseDirectives,
133
+ session: updatedSession,
134
+ isRouteComplete: true,
135
+ completedRoutes,
136
+ };
137
+ }
90
138
  const selectedStep = candidates.find((c) => c.step.id === selectedStepId);
91
139
  if (selectedStep) {
92
140
  logger.debug(`[RoutingEngine] Single-route: AI selected step: ${selectedStep.step.id}`);
@@ -104,16 +152,17 @@ export class RoutingEngine {
104
152
  };
105
153
  }
106
154
  /**
107
- * Recursively traverse step chain to find first non-skipped step or END_ROUTE
155
+ * Recursively traverse step chain to find first non-skipped step or END_ROUTE using new condition evaluation
108
156
  * @private
109
157
  */
110
- findFirstValidStepRecursive(currentStep, data, visited) {
158
+ async findFirstValidStepRecursiveWithConditions(currentStep, templateContext, visited) {
111
159
  // Prevent infinite loops
112
160
  if (visited.has(currentStep.id)) {
113
- return {};
161
+ return { aiContextStrings: [] };
114
162
  }
115
163
  visited.add(currentStep.id);
116
164
  const transitions = currentStep.getTransitions();
165
+ const allAiContextStrings = [];
117
166
  for (const transition of transitions) {
118
167
  const target = transition;
119
168
  // Check for END_ROUTE transition
@@ -121,40 +170,69 @@ export class RoutingEngine {
121
170
  // Found END_ROUTE - route is complete
122
171
  return {
123
172
  isRouteComplete: true,
173
+ aiContextStrings: allAiContextStrings,
124
174
  };
125
175
  }
126
176
  if (!target)
127
177
  continue;
178
+ // Evaluate skipIf condition using new system
179
+ const skipResult = await target.evaluateSkipIf(templateContext);
180
+ allAiContextStrings.push(...skipResult.aiContextStrings);
128
181
  // If target should NOT be skipped, we found our step
129
- if (!target.shouldSkip(data)) {
182
+ if (!skipResult.shouldSkip) {
130
183
  logger.debug(`[RoutingEngine] Found valid step after skipping: ${target.id}`);
131
184
  return {
132
185
  step: target,
133
186
  isRouteComplete: false,
187
+ aiContextStrings: allAiContextStrings,
134
188
  };
135
189
  }
136
190
  // Target should be skipped too - recurse deeper
137
191
  logger.debug(`[RoutingEngine] Skipping step ${target.id} (skipIf condition met), continuing traversal...`);
138
- const result = this.findFirstValidStepRecursive(target, data, visited);
192
+ const result = await this.findFirstValidStepRecursiveWithConditions(target, templateContext, visited);
193
+ // Collect AI context from recursive call
194
+ if (result.aiContextStrings) {
195
+ allAiContextStrings.push(...result.aiContextStrings);
196
+ }
139
197
  // If we found something (a valid step or END_ROUTE), return it
140
198
  if (result.step || result.isRouteComplete) {
141
- return result;
199
+ return {
200
+ ...result,
201
+ aiContextStrings: allAiContextStrings,
202
+ };
142
203
  }
143
204
  }
144
205
  // No valid steps or END_ROUTE found in this branch
145
- return {};
206
+ return { aiContextStrings: allAiContextStrings };
146
207
  }
147
208
  /**
148
- * Identify valid next candidate steps based on current step and collected data
209
+ * Identify valid next candidate steps using new condition evaluation system
149
210
  * Returns step with isRouteComplete flag if route is complete (all steps skipped + has END_ROUTE transition)
211
+ *
212
+ * NEW: Automatically completes route when all required fields are collected
150
213
  */
151
- getCandidateSteps(route, currentStep, data) {
214
+ async getCandidateStepsWithConditions(route, currentStep, templateContext) {
152
215
  const candidates = [];
216
+ const data = templateContext.data || {};
217
+ // Check if all required fields are collected
218
+ const allRequiredFieldsCollected = route.isComplete(data);
153
219
  if (!currentStep) {
220
+ // Entering route for the first time
221
+ // If all required fields already collected, route is immediately complete
222
+ if (allRequiredFieldsCollected) {
223
+ logger.debug(`[RoutingEngine] Route ${route.title} complete on entry: all required fields already collected`);
224
+ // Return a completion marker - use initial step with completion flag
225
+ candidates.push({
226
+ step: route.initialStep,
227
+ isRouteComplete: true,
228
+ });
229
+ return candidates;
230
+ }
154
231
  const initialStep = route.initialStep;
155
- if (initialStep.shouldSkip(data)) {
232
+ const skipResult = await initialStep.evaluateSkipIf(templateContext);
233
+ if (skipResult.shouldSkip) {
156
234
  // Initial step should be skipped - recursively traverse to find first non-skipped step or END_ROUTE
157
- const result = this.findFirstValidStepRecursive(initialStep, data, new Set());
235
+ const result = await this.findFirstValidStepRecursiveWithConditions(initialStep, templateContext, new Set());
158
236
  if (result.isRouteComplete) {
159
237
  // All steps are skipped and we reached END_ROUTE
160
238
  logger.debug(`[RoutingEngine] Route complete on entry: all steps skipped, END_ROUTE reached`);
@@ -180,6 +258,55 @@ export class RoutingEngine {
180
258
  }
181
259
  return candidates;
182
260
  }
261
+ // Check if all required fields are now collected (may have been collected during this step)
262
+ if (allRequiredFieldsCollected) {
263
+ // Required fields are complete - check if we should continue for optional fields
264
+ const transitions = currentStep.getTransitions();
265
+ const optionalFieldCandidates = [];
266
+ for (const transition of transitions) {
267
+ const target = transition;
268
+ // Check for END_ROUTE transition
269
+ if (target && target.id === END_ROUTE_ID) {
270
+ continue;
271
+ }
272
+ if (!target)
273
+ continue;
274
+ // Check if this step collects only optional fields
275
+ const collectsOnlyOptional = target.collect && target.collect.length > 0 &&
276
+ target.collect.every(field => route.optionalFields?.includes(field));
277
+ if (collectsOnlyOptional) {
278
+ // This step collects optional fields - it's a candidate
279
+ const skipResult = await target.evaluateSkipIf(templateContext);
280
+ if (!skipResult.shouldSkip) {
281
+ optionalFieldCandidates.push({
282
+ step: target,
283
+ isRouteComplete: false,
284
+ });
285
+ }
286
+ }
287
+ }
288
+ // If we have optional field candidates, include them along with END_ROUTE option
289
+ if (optionalFieldCandidates.length > 0) {
290
+ logger.debug(`[RoutingEngine] Required fields complete, but ${optionalFieldCandidates.length} optional field steps available`);
291
+ // Add optional field steps as candidates
292
+ candidates.push(...optionalFieldCandidates);
293
+ // Also add END_ROUTE as a candidate (AI can choose to skip optional fields)
294
+ candidates.push({
295
+ step: currentStep,
296
+ isRouteComplete: true,
297
+ });
298
+ return candidates;
299
+ }
300
+ // No optional fields to collect - route is complete
301
+ logger.debug(`[RoutingEngine] Route ${route.title} complete: all required fields collected, no optional fields remain`);
302
+ return [
303
+ {
304
+ step: currentStep,
305
+ isRouteComplete: true,
306
+ },
307
+ ];
308
+ }
309
+ // Required fields not yet complete - continue normal step progression
183
310
  const transitions = currentStep.getTransitions();
184
311
  let hasEndRoute = false;
185
312
  for (const transition of transitions) {
@@ -191,10 +318,11 @@ export class RoutingEngine {
191
318
  }
192
319
  if (!target)
193
320
  continue;
194
- if (target.shouldSkip(data)) {
321
+ const skipResult = await target.evaluateSkipIf(templateContext);
322
+ if (skipResult.shouldSkip) {
195
323
  logger.debug(`[RoutingEngine] Skipping step ${target.id} (skipIf condition met)`);
196
324
  // Recursively traverse to find next valid step or END_ROUTE
197
- const result = this.findFirstValidStepRecursive(target, data, new Set([currentStep.id]) // Already visited current step
325
+ const result = await this.findFirstValidStepRecursiveWithConditions(target, templateContext, new Set([currentStep.id]) // Already visited current step
198
326
  );
199
327
  if (result.isRouteComplete) {
200
328
  hasEndRoute = true;
@@ -227,7 +355,8 @@ export class RoutingEngine {
227
355
  ];
228
356
  }
229
357
  // Otherwise, stay in current step if it's still valid
230
- if (!currentStep.shouldSkip(data)) {
358
+ const currentSkipResult = await currentStep.evaluateSkipIf(templateContext);
359
+ if (!currentSkipResult.shouldSkip) {
231
360
  candidates.push({
232
361
  step: currentStep,
233
362
  isRouteComplete: hasEndRoute || false,
@@ -271,38 +400,69 @@ export class RoutingEngine {
271
400
  };
272
401
  }
273
402
  const lastUserMessage = getLastMessageFromHistory(history);
403
+ const templateContext = createTemplateContext({
404
+ context,
405
+ session,
406
+ history,
407
+ data: session.data
408
+ });
409
+ // Apply route filtering with new condition evaluation system
410
+ const skipIfResult = await this.filterRoutesBySkipIf(routes, templateContext);
411
+ const whenResult = await this.filterRoutesByWhen(skipIfResult.eligibleRoutes, templateContext);
412
+ // Collect all AI context strings from route conditions
413
+ const routeConditionContext = [...skipIfResult.aiContextStrings, ...whenResult.aiContextStrings];
414
+ // Use filtered routes for further processing
415
+ const eligibleRoutes = whenResult.eligibleRoutes;
416
+ logger.debug(`[RoutingEngine] Route filtering: ${routes.length} total → ${skipIfResult.eligibleRoutes.length} after skipIf → ${eligibleRoutes.length} after when`);
274
417
  let activeRouteSteps;
275
418
  let activeRoute;
276
419
  let isRouteComplete = false;
420
+ let updatedSession = session;
277
421
  if (session.currentRoute) {
278
- activeRoute = routes.find((r) => r.id === session.currentRoute?.id);
422
+ activeRoute = eligibleRoutes.find((r) => r.id === session.currentRoute?.id);
279
423
  if (activeRoute) {
280
424
  const currentStep = session.currentStep
281
425
  ? activeRoute.getStep(session.currentStep.id)
282
426
  : undefined;
283
- const candidates = this.getCandidateSteps(activeRoute, currentStep, session.data || {});
427
+ const activeTemplateContext = createTemplateContext({
428
+ ...templateContext,
429
+ session: updatedSession,
430
+ data: updatedSession.data
431
+ });
432
+ const candidates = await this.getCandidateStepsWithConditions(activeRoute, currentStep, activeTemplateContext);
284
433
  // Check if route is complete
434
+ // getCandidateStepsWithConditions now automatically handles completion when required fields are collected
285
435
  if (candidates.length === 1 && candidates[0].isRouteComplete) {
286
436
  isRouteComplete = true;
287
- logger.debug(`[RoutingEngine] Route ${activeRoute.title} is complete - all data collected`);
437
+ logger.debug(`[RoutingEngine] Route ${activeRoute.title} is complete - all required fields collected or END_ROUTE reached`);
288
438
  // Don't include steps in routing if route is complete
289
439
  activeRouteSteps = undefined;
290
440
  }
441
+ else if (candidates.length === 0) {
442
+ // No candidates - check if data is complete
443
+ const dataComplete = activeRoute.isComplete(updatedSession.data || {});
444
+ isRouteComplete = dataComplete;
445
+ logger.debug(`[RoutingEngine] Route ${activeRoute.title} has no valid steps - ` +
446
+ `marking as ${isRouteComplete ? 'complete' : 'incomplete'}`);
447
+ activeRouteSteps = undefined;
448
+ }
291
449
  else {
450
+ // Multiple candidates or single non-complete candidate
292
451
  activeRouteSteps = candidates.map((c) => c.step);
293
452
  logger.debug(`[RoutingEngine] Found ${activeRouteSteps.length} candidate steps for active route`);
294
453
  }
295
454
  }
296
455
  }
297
- const routingSchema = this.buildDynamicRoutingSchema(routes, undefined, activeRouteSteps);
456
+ const routingSchema = this.buildDynamicRoutingSchema(eligibleRoutes, undefined, activeRouteSteps);
298
457
  const routingPrompt = await this.buildRoutingPrompt({
299
458
  history,
300
- routes,
459
+ routes: eligibleRoutes,
301
460
  lastMessage: lastUserMessage,
302
461
  agentOptions,
303
462
  session,
304
463
  activeRouteSteps,
305
464
  context,
465
+ routeConditionContext, // Pass AI context strings from route conditions
306
466
  });
307
467
  const routingResult = await provider.generateMessage({
308
468
  prompt: routingPrompt,
@@ -317,19 +477,26 @@ export class RoutingEngine {
317
477
  let selectedRoute;
318
478
  let selectedStep;
319
479
  let responseDirectives;
320
- let updatedSession = session;
321
480
  if (routingResult.structured?.routes) {
322
481
  // Use cross-route completion evaluation to select optimal route
323
- const optimalRoute = this.selectOptimalRoute(routes, updatedSession.data || {}, routingResult.structured.routes);
324
- // Fall back to traditional scoring if no optimal route found
325
- selectedRoute = optimalRoute || (() => {
326
- const decision = this.decideRouteFromScores({
327
- context: routingResult.structured.context,
328
- routes: routingResult.structured.routes,
329
- responseDirectives: routingResult.structured.responseDirectives,
330
- });
331
- return routes.find((r) => r.id === decision.routeId);
332
- })();
482
+ const optimalRoute = this.selectOptimalRoute(eligibleRoutes, updatedSession.data || {}, routingResult.structured.routes);
483
+ // If no optimal route found, check why
484
+ if (!optimalRoute) {
485
+ if (eligibleRoutes.length === 0) {
486
+ // No routes passed filtering
487
+ logger.debug(`[RoutingEngine] No eligible routes available - all routes filtered out`);
488
+ selectedRoute = undefined;
489
+ }
490
+ else {
491
+ // Routes exist but selectOptimalRoute returned undefined
492
+ // This means all routes are 100% complete
493
+ logger.debug(`[RoutingEngine] No optimal route found - all ${eligibleRoutes.length} eligible routes are complete`);
494
+ selectedRoute = undefined;
495
+ }
496
+ }
497
+ else {
498
+ selectedRoute = optimalRoute;
499
+ }
333
500
  responseDirectives = routingResult.structured.responseDirectives;
334
501
  if (selectedRoute === activeRoute &&
335
502
  routingResult.structured.selectedStepId &&
@@ -342,15 +509,7 @@ export class RoutingEngine {
342
509
  }
343
510
  if (selectedRoute) {
344
511
  logger.debug(`[RoutingEngine] Selected route: ${selectedRoute.title}`);
345
- if (!session.currentRoute ||
346
- session.currentRoute.id !== selectedRoute.id) {
347
- updatedSession = enterRoute(session, selectedRoute.id, selectedRoute.title);
348
- if (selectedRoute.initialData) {
349
- updatedSession = mergeCollected(updatedSession, selectedRoute.initialData);
350
- logger.debug(`[RoutingEngine] Merged initial data:`, selectedRoute.initialData);
351
- }
352
- logger.debug(`[RoutingEngine] Entered route: ${selectedRoute.title}`);
353
- }
512
+ updatedSession = this.enterRouteIfNeeded(updatedSession, selectedRoute);
354
513
  }
355
514
  }
356
515
  return {
@@ -362,6 +521,52 @@ export class RoutingEngine {
362
521
  completedRoutes,
363
522
  };
364
523
  }
524
+ /**
525
+ * Filter routes based on skipIf conditions
526
+ * @param routes - All available routes
527
+ * @param templateContext - Context for condition evaluation
528
+ * @returns Object with eligible routes and collected AI context strings
529
+ */
530
+ async filterRoutesBySkipIf(routes, templateContext) {
531
+ const eligibleRoutes = [];
532
+ const aiContextStrings = [];
533
+ for (const route of routes) {
534
+ const skipResult = await route.evaluateSkipIf(templateContext);
535
+ // Collect AI context strings from skipIf conditions
536
+ aiContextStrings.push(...skipResult.aiContextStrings);
537
+ // If route should not be skipped, it's eligible
538
+ if (!skipResult.programmaticResult) {
539
+ eligibleRoutes.push(route);
540
+ }
541
+ else {
542
+ logger.debug(`[RoutingEngine] Skipping route ${route.title} (skipIf condition met)`);
543
+ }
544
+ }
545
+ return { eligibleRoutes, aiContextStrings };
546
+ }
547
+ /**
548
+ * Filter routes based on when conditions
549
+ * @param routes - Routes that passed skipIf filtering
550
+ * @param templateContext - Context for condition evaluation
551
+ * @returns Object with eligible routes and collected AI context strings
552
+ */
553
+ async filterRoutesByWhen(routes, templateContext) {
554
+ const eligibleRoutes = [];
555
+ const aiContextStrings = [];
556
+ for (const route of routes) {
557
+ const whenResult = await route.evaluateWhen(templateContext);
558
+ // Collect AI context strings from when conditions
559
+ aiContextStrings.push(...whenResult.aiContextStrings);
560
+ // If route has no programmatic conditions or they evaluate to true, it's eligible
561
+ if (!whenResult.hasProgrammaticConditions || whenResult.programmaticResult) {
562
+ eligibleRoutes.push(route);
563
+ }
564
+ else {
565
+ logger.debug(`[RoutingEngine] Route ${route.title} not eligible (when condition not met)`);
566
+ }
567
+ }
568
+ return { eligibleRoutes, aiContextStrings };
569
+ }
365
570
  /**
366
571
  * Evaluate all routes for completion based on collected data
367
572
  * @param routes - All available routes
@@ -388,6 +593,7 @@ export class RoutingEngine {
388
593
  /**
389
594
  * Find the best route to continue based on completion status and user intent
390
595
  * Prioritizes routes that are partially complete but not finished
596
+ * IMPORTANT: Completed routes are excluded to prevent re-entering finished tasks
391
597
  * @param routes - All available routes
392
598
  * @param data - Currently collected agent-level data
393
599
  * @param routeScores - AI-generated route scores from routing decision
@@ -400,8 +606,10 @@ export class RoutingEngine {
400
606
  for (const route of routes) {
401
607
  const aiScore = routeScores[route.id] || 0;
402
608
  const completionProgress = completionStatus.get(route.id) || 0;
403
- // Skip fully completed routes unless they have very high AI scores
404
- if (completionProgress >= 1.0 && aiScore < 80) {
609
+ // ALWAYS skip fully completed routes to prevent re-entering finished tasks
610
+ // Users should not be forced back into completed routes
611
+ if (completionProgress >= 1.0) {
612
+ logger.debug(`[RoutingEngine] Excluding completed route: ${route.title} (100% complete)`);
405
613
  continue;
406
614
  }
407
615
  // Boost partially complete routes that match user intent
@@ -428,8 +636,8 @@ export class RoutingEngine {
428
636
  * @private
429
637
  */
430
638
  async buildStepSelectionPrompt(params) {
431
- const { route, currentStep, candidates, data, history, lastMessage, agentOptions, context, session, } = params;
432
- const templateContext = { context, session, history };
639
+ const { route, currentStep, candidates, data, history, lastMessage, agentOptions, context, session, stepConditionContext, includeEndRoute = false, } = params;
640
+ const templateContext = createTemplateContext({ context, session, history });
433
641
  const pc = new PromptComposer(templateContext);
434
642
  // Add agent metadata
435
643
  if (agentOptions) {
@@ -454,7 +662,7 @@ export class RoutingEngine {
454
662
  // Add conversation history
455
663
  await pc.addInteractionHistory(history);
456
664
  await pc.addLastMessage(lastMessage);
457
- // Add candidate steps
665
+ // Add candidate steps with condition context
458
666
  const stepDescriptions = [];
459
667
  for (const candidate of candidates) {
460
668
  const idx = candidates.indexOf(candidate);
@@ -462,9 +670,15 @@ export class RoutingEngine {
462
670
  `${idx + 1}. Step ID: ${candidate.step.id}`,
463
671
  ` Description: ${candidate.step.description || "N/A"}`,
464
672
  ];
673
+ // Add when condition context
465
674
  if (candidate.step.when) {
466
- const renderedWhen = await render(candidate.step.when, templateContext);
467
- parts.push(` When this step should be completed: ${renderedWhen}`);
675
+ const whenResult = await candidate.step.evaluateWhen(templateContext);
676
+ if (whenResult.aiContextStrings.length > 0) {
677
+ parts.push(` When conditions: ${whenResult.aiContextStrings.join(", ")}`);
678
+ }
679
+ else if (typeof candidate.step.when === 'string') {
680
+ parts.push(` When this step should be completed: ${candidate.step.when}`);
681
+ }
468
682
  }
469
683
  if (candidate.step.requires && candidate.step.requires.length > 0) {
470
684
  parts.push(` Required Data: ${candidate.step.requires.join(", ")}`);
@@ -475,8 +689,18 @@ export class RoutingEngine {
475
689
  stepDescriptions.push(parts.join("\n"));
476
690
  }
477
691
  await pc.addInstruction(`Available Steps to Transition To:\n${stepDescriptions.join("\n\n")}`);
692
+ // Add step condition context if available
693
+ if (stepConditionContext && stepConditionContext.length > 0) {
694
+ await pc.addInstruction([
695
+ "",
696
+ "Additional step context from conditions:",
697
+ ...stepConditionContext.map(ctx => `- ${ctx}`),
698
+ "",
699
+ "Consider this context when selecting the most appropriate step.",
700
+ ].join("\n"));
701
+ }
478
702
  // Add decision prompt
479
- await pc.addInstruction([
703
+ const decisionRules = [
480
704
  "Task: Decide which step to transition to based on:",
481
705
  "1. The user's current message and intent",
482
706
  "2. The conversation history and context",
@@ -489,16 +713,24 @@ export class RoutingEngine {
489
713
  "- If a step requires data we don't have, consider if we should collect it now",
490
714
  "- Choose the step that makes the most sense for moving the conversation forward",
491
715
  "- Steps with skipIf conditions that are met have already been filtered out",
492
- "",
493
- "Return ONLY JSON matching the provided schema.",
494
- ].join("\n"));
716
+ ];
717
+ if (includeEndRoute) {
718
+ decisionRules.push("", `- You can select '${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");
719
+ }
720
+ decisionRules.push("", "Return ONLY JSON matching the provided schema.");
721
+ await pc.addInstruction(decisionRules.join("\n"));
495
722
  return pc.build();
496
723
  }
497
724
  /**
498
725
  * Build schema for step selection
499
726
  * @private
500
727
  */
501
- buildStepSelectionSchema(validSteps) {
728
+ buildStepSelectionSchema(validSteps, includeEndRoute = false) {
729
+ const stepIds = validSteps.map((s) => s.id);
730
+ // Add END_ROUTE as an option if requested (when required fields are complete)
731
+ if (includeEndRoute) {
732
+ stepIds.push(END_ROUTE_ID);
733
+ }
502
734
  return {
503
735
  description: "Step transition decision based on conversation context and collected data",
504
736
  type: "object",
@@ -511,8 +743,10 @@ export class RoutingEngine {
511
743
  selectedStepId: {
512
744
  type: "string",
513
745
  nullable: false,
514
- description: "The ID of the selected step to transition to",
515
- enum: validSteps.map((s) => s.id),
746
+ description: includeEndRoute
747
+ ? `The ID of the selected step to transition to, or '${END_ROUTE_ID}' to complete the route`
748
+ : "The ID of the selected step to transition to",
749
+ enum: stepIds,
516
750
  },
517
751
  responseDirectives: {
518
752
  type: "array",
@@ -588,8 +822,8 @@ export class RoutingEngine {
588
822
  return base;
589
823
  }
590
824
  async buildRoutingPrompt(params) {
591
- const { history, routes, lastMessage, agentOptions, session, activeRouteSteps, context, } = params;
592
- const templateContext = { context, session, history };
825
+ const { history, routes, lastMessage, agentOptions, session, activeRouteSteps, context, routeConditionContext, } = params;
826
+ const templateContext = createTemplateContext({ context, session, history });
593
827
  const pc = new PromptComposer(templateContext);
594
828
  if (agentOptions) {
595
829
  await pc.addAgentMeta(agentOptions);
@@ -641,15 +875,23 @@ export class RoutingEngine {
641
875
  "",
642
876
  "Available steps in active route (choose one to transition to):",
643
877
  ];
878
+ const activeStepConditionContext = [];
644
879
  for (const step of activeRouteSteps) {
645
880
  const idx = activeRouteSteps.indexOf(step);
646
881
  stepInfo.push(`${idx + 1}. Step: ${step.id}`);
647
882
  if (step.description) {
648
883
  stepInfo.push(` Description: ${step.description}`);
649
884
  }
650
- const renderedWhen = await render(step.when, templateContext);
885
+ // Collect AI context from step conditions
651
886
  if (step.when) {
652
- stepInfo.push(` When this step should be completed: ${renderedWhen}`);
887
+ const whenResult = await step.evaluateWhen(templateContext);
888
+ if (whenResult.aiContextStrings.length > 0) {
889
+ stepInfo.push(` When conditions: ${whenResult.aiContextStrings.join(", ")}`);
890
+ activeStepConditionContext.push(...whenResult.aiContextStrings);
891
+ }
892
+ else if (typeof step.when === 'string') {
893
+ stepInfo.push(` When this step should be completed: ${step.when}`);
894
+ }
653
895
  }
654
896
  if (step.requires && step.requires.length > 0) {
655
897
  stepInfo.push(` Required data: ${step.requires.join(", ")}`);
@@ -665,11 +907,31 @@ export class RoutingEngine {
665
907
  stepInfo.push("- The logical next step in the conversation");
666
908
  stepInfo.push("- Whether conditions for steps are met");
667
909
  await pc.addInstruction(stepInfo.join("\n"));
910
+ // Add active step condition context if available
911
+ if (activeStepConditionContext.length > 0) {
912
+ await pc.addInstruction([
913
+ "",
914
+ "Additional context from step conditions:",
915
+ ...activeStepConditionContext.map(ctx => `- ${ctx}`),
916
+ "",
917
+ "Use this context to inform your step selection decision.",
918
+ ].join("\n"));
919
+ }
668
920
  }
669
921
  }
670
922
  await pc.addInteractionHistory(history);
671
923
  await pc.addLastMessage(lastMessage);
672
924
  await pc.addRoutingOverview(routes);
925
+ // Add route condition context if available
926
+ if (routeConditionContext && routeConditionContext.length > 0) {
927
+ await pc.addInstruction([
928
+ "",
929
+ "Additional routing context from route conditions:",
930
+ ...routeConditionContext.map(ctx => `- ${ctx}`),
931
+ "",
932
+ "Consider this context when scoring routes for relevance.",
933
+ ].join("\n"));
934
+ }
673
935
  await pc.addInstruction([
674
936
  "Scoring rules:",
675
937
  "- 90-100: explicit keywords + clear intent",