@falai/agent 3.4.5 → 4.0.0-alpha.10

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