@falai/agent 2.2.3 → 2.4.1

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 (397) hide show
  1. package/README.md +2 -2
  2. package/dist/adapters/MemoryAdapter.d.ts.map +1 -1
  3. package/dist/adapters/MemoryAdapter.js +10 -1
  4. package/dist/adapters/MemoryAdapter.js.map +1 -1
  5. package/dist/adapters/MongoAdapter.d.ts.map +1 -1
  6. package/dist/adapters/MongoAdapter.js +33 -2
  7. package/dist/adapters/MongoAdapter.js.map +1 -1
  8. package/dist/adapters/OpenSearchAdapter.d.ts.map +1 -1
  9. package/dist/adapters/OpenSearchAdapter.js +15 -1
  10. package/dist/adapters/OpenSearchAdapter.js.map +1 -1
  11. package/dist/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  12. package/dist/adapters/PostgreSQLAdapter.js +35 -5
  13. package/dist/adapters/PostgreSQLAdapter.js.map +1 -1
  14. package/dist/adapters/PrismaAdapter.d.ts.map +1 -1
  15. package/dist/adapters/PrismaAdapter.js +58 -15
  16. package/dist/adapters/PrismaAdapter.js.map +1 -1
  17. package/dist/adapters/RedisAdapter.d.ts.map +1 -1
  18. package/dist/adapters/RedisAdapter.js +10 -1
  19. package/dist/adapters/RedisAdapter.js.map +1 -1
  20. package/dist/adapters/SQLiteAdapter.d.ts.map +1 -1
  21. package/dist/adapters/SQLiteAdapter.js +38 -6
  22. package/dist/adapters/SQLiteAdapter.js.map +1 -1
  23. package/dist/cjs/adapters/MemoryAdapter.d.ts.map +1 -1
  24. package/dist/cjs/adapters/MemoryAdapter.js +10 -1
  25. package/dist/cjs/adapters/MemoryAdapter.js.map +1 -1
  26. package/dist/cjs/adapters/MongoAdapter.d.ts.map +1 -1
  27. package/dist/cjs/adapters/MongoAdapter.js +33 -2
  28. package/dist/cjs/adapters/MongoAdapter.js.map +1 -1
  29. package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +1 -1
  30. package/dist/cjs/adapters/OpenSearchAdapter.js +15 -1
  31. package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -1
  32. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  33. package/dist/cjs/adapters/PostgreSQLAdapter.js +35 -5
  34. package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -1
  35. package/dist/cjs/adapters/PrismaAdapter.d.ts.map +1 -1
  36. package/dist/cjs/adapters/PrismaAdapter.js +58 -15
  37. package/dist/cjs/adapters/PrismaAdapter.js.map +1 -1
  38. package/dist/cjs/adapters/RedisAdapter.d.ts.map +1 -1
  39. package/dist/cjs/adapters/RedisAdapter.js +10 -1
  40. package/dist/cjs/adapters/RedisAdapter.js.map +1 -1
  41. package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +1 -1
  42. package/dist/cjs/adapters/SQLiteAdapter.js +38 -6
  43. package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -1
  44. package/dist/cjs/core/Agent.d.ts +28 -18
  45. package/dist/cjs/core/Agent.d.ts.map +1 -1
  46. package/dist/cjs/core/Agent.js +58 -68
  47. package/dist/cjs/core/Agent.js.map +1 -1
  48. package/dist/cjs/core/AutoChainExecutor.d.ts.map +1 -1
  49. package/dist/cjs/core/AutoChainExecutor.js +14 -20
  50. package/dist/cjs/core/AutoChainExecutor.js.map +1 -1
  51. package/dist/cjs/core/BranchEvaluator.d.ts +4 -3
  52. package/dist/cjs/core/BranchEvaluator.d.ts.map +1 -1
  53. package/dist/cjs/core/BranchEvaluator.js +18 -23
  54. package/dist/cjs/core/BranchEvaluator.js.map +1 -1
  55. package/dist/cjs/core/Flow.d.ts +2 -1
  56. package/dist/cjs/core/Flow.d.ts.map +1 -1
  57. package/dist/cjs/core/Flow.js +10 -3
  58. package/dist/cjs/core/Flow.js.map +1 -1
  59. package/dist/cjs/core/FlowRouter.d.ts +1 -0
  60. package/dist/cjs/core/FlowRouter.d.ts.map +1 -1
  61. package/dist/cjs/core/FlowRouter.js +28 -5
  62. package/dist/cjs/core/FlowRouter.js.map +1 -1
  63. package/dist/cjs/core/PersistenceManager.d.ts +3 -0
  64. package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
  65. package/dist/cjs/core/PersistenceManager.js +57 -5
  66. package/dist/cjs/core/PersistenceManager.js.map +1 -1
  67. package/dist/cjs/core/PromptComposer.d.ts.map +1 -1
  68. package/dist/cjs/core/PromptComposer.js +24 -10
  69. package/dist/cjs/core/PromptComposer.js.map +1 -1
  70. package/dist/cjs/core/ResponseGenerationError.d.ts +30 -0
  71. package/dist/cjs/core/ResponseGenerationError.d.ts.map +1 -0
  72. package/dist/cjs/core/ResponseGenerationError.js +37 -0
  73. package/dist/cjs/core/ResponseGenerationError.js.map +1 -0
  74. package/dist/cjs/core/ResponseModal.d.ts +43 -96
  75. package/dist/cjs/core/ResponseModal.d.ts.map +1 -1
  76. package/dist/cjs/core/ResponseModal.js +184 -1183
  77. package/dist/cjs/core/ResponseModal.js.map +1 -1
  78. package/dist/cjs/core/ResponsePipeline.d.ts +58 -152
  79. package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -1
  80. package/dist/cjs/core/ResponsePipeline.js +408 -457
  81. package/dist/cjs/core/ResponsePipeline.js.map +1 -1
  82. package/dist/cjs/core/SessionFinalizer.d.ts +34 -0
  83. package/dist/cjs/core/SessionFinalizer.d.ts.map +1 -0
  84. package/dist/cjs/core/SessionFinalizer.js +61 -0
  85. package/dist/cjs/core/SessionFinalizer.js.map +1 -0
  86. package/dist/cjs/core/SessionManager.d.ts +1 -1
  87. package/dist/cjs/core/SessionManager.d.ts.map +1 -1
  88. package/dist/cjs/core/SessionManager.js +18 -7
  89. package/dist/cjs/core/SessionManager.js.map +1 -1
  90. package/dist/cjs/core/SignalCoordinator.d.ts +103 -0
  91. package/dist/cjs/core/SignalCoordinator.d.ts.map +1 -0
  92. package/dist/cjs/core/SignalCoordinator.js +207 -0
  93. package/dist/cjs/core/SignalCoordinator.js.map +1 -0
  94. package/dist/cjs/core/SignalEvaluator.d.ts +2 -2
  95. package/dist/cjs/core/SignalEvaluator.d.ts.map +1 -1
  96. package/dist/cjs/core/SignalEvaluator.js +13 -27
  97. package/dist/cjs/core/SignalEvaluator.js.map +1 -1
  98. package/dist/cjs/core/SignalProcessor.d.ts.map +1 -1
  99. package/dist/cjs/core/SignalProcessor.js +1 -3
  100. package/dist/cjs/core/SignalProcessor.js.map +1 -1
  101. package/dist/cjs/core/Step.d.ts +3 -1
  102. package/dist/cjs/core/Step.d.ts.map +1 -1
  103. package/dist/cjs/core/Step.js +10 -3
  104. package/dist/cjs/core/Step.js.map +1 -1
  105. package/dist/cjs/core/StepLifecycle.d.ts +33 -0
  106. package/dist/cjs/core/StepLifecycle.d.ts.map +1 -0
  107. package/dist/cjs/core/StepLifecycle.js +97 -0
  108. package/dist/cjs/core/StepLifecycle.js.map +1 -0
  109. package/dist/cjs/core/ToolLoopExecutor.d.ts +104 -0
  110. package/dist/cjs/core/ToolLoopExecutor.d.ts.map +1 -0
  111. package/dist/cjs/core/ToolLoopExecutor.js +391 -0
  112. package/dist/cjs/core/ToolLoopExecutor.js.map +1 -0
  113. package/dist/cjs/core/ToolManager.d.ts +1 -1
  114. package/dist/cjs/core/ToolManager.d.ts.map +1 -1
  115. package/dist/cjs/core/ToolManager.js.map +1 -1
  116. package/dist/cjs/index.d.ts +4 -5
  117. package/dist/cjs/index.d.ts.map +1 -1
  118. package/dist/cjs/index.js +7 -6
  119. package/dist/cjs/index.js.map +1 -1
  120. package/dist/cjs/providers/AnthropicProvider.d.ts +2 -0
  121. package/dist/cjs/providers/AnthropicProvider.d.ts.map +1 -1
  122. package/dist/cjs/providers/AnthropicProvider.js +28 -56
  123. package/dist/cjs/providers/AnthropicProvider.js.map +1 -1
  124. package/dist/cjs/providers/DeepSeekProvider.d.ts +25 -21
  125. package/dist/cjs/providers/DeepSeekProvider.d.ts.map +1 -1
  126. package/dist/cjs/providers/DeepSeekProvider.js +48 -407
  127. package/dist/cjs/providers/DeepSeekProvider.js.map +1 -1
  128. package/dist/cjs/providers/GeminiProvider.d.ts +2 -0
  129. package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
  130. package/dist/cjs/providers/GeminiProvider.js +27 -56
  131. package/dist/cjs/providers/GeminiProvider.js.map +1 -1
  132. package/dist/cjs/providers/OpenAICompatibleProvider.d.ts +129 -0
  133. package/dist/cjs/providers/OpenAICompatibleProvider.d.ts.map +1 -0
  134. package/dist/cjs/providers/OpenAICompatibleProvider.js +485 -0
  135. package/dist/cjs/providers/OpenAICompatibleProvider.js.map +1 -0
  136. package/dist/cjs/providers/OpenAIProvider.d.ts +9 -28
  137. package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
  138. package/dist/cjs/providers/OpenAIProvider.js +23 -417
  139. package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
  140. package/dist/cjs/providers/OpenRouterProvider.d.ts +10 -27
  141. package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
  142. package/dist/cjs/providers/OpenRouterProvider.js +28 -417
  143. package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
  144. package/dist/cjs/providers/errorClassification.d.ts +61 -0
  145. package/dist/cjs/providers/errorClassification.d.ts.map +1 -0
  146. package/dist/cjs/providers/errorClassification.js +123 -0
  147. package/dist/cjs/providers/errorClassification.js.map +1 -0
  148. package/dist/cjs/providers/index.d.ts +4 -0
  149. package/dist/cjs/providers/index.d.ts.map +1 -1
  150. package/dist/cjs/providers/index.js +7 -1
  151. package/dist/cjs/providers/index.js.map +1 -1
  152. package/dist/cjs/types/agent.d.ts +2 -1
  153. package/dist/cjs/types/agent.d.ts.map +1 -1
  154. package/dist/cjs/types/ai.d.ts +20 -0
  155. package/dist/cjs/types/ai.d.ts.map +1 -1
  156. package/dist/cjs/types/errors.d.ts +33 -0
  157. package/dist/cjs/types/errors.d.ts.map +1 -1
  158. package/dist/cjs/types/errors.js +37 -1
  159. package/dist/cjs/types/errors.js.map +1 -1
  160. package/dist/cjs/types/flow.d.ts +10 -5
  161. package/dist/cjs/types/flow.d.ts.map +1 -1
  162. package/dist/cjs/types/history.d.ts +1 -1
  163. package/dist/cjs/types/history.d.ts.map +1 -1
  164. package/dist/cjs/types/index.d.ts +5 -4
  165. package/dist/cjs/types/index.d.ts.map +1 -1
  166. package/dist/cjs/types/index.js +3 -1
  167. package/dist/cjs/types/index.js.map +1 -1
  168. package/dist/cjs/types/persistence.d.ts +43 -2
  169. package/dist/cjs/types/persistence.d.ts.map +1 -1
  170. package/dist/cjs/types/session.d.ts +8 -0
  171. package/dist/cjs/types/session.d.ts.map +1 -1
  172. package/dist/cjs/types/signals.d.ts +21 -11
  173. package/dist/cjs/types/signals.d.ts.map +1 -1
  174. package/dist/cjs/types/template.d.ts +3 -1
  175. package/dist/cjs/types/template.d.ts.map +1 -1
  176. package/dist/cjs/types/tool.d.ts +4 -4
  177. package/dist/cjs/types/tool.d.ts.map +1 -1
  178. package/dist/cjs/utils/condition.d.ts +19 -0
  179. package/dist/cjs/utils/condition.d.ts.map +1 -1
  180. package/dist/cjs/utils/condition.js +86 -15
  181. package/dist/cjs/utils/condition.js.map +1 -1
  182. package/dist/cjs/utils/session.d.ts +1 -0
  183. package/dist/cjs/utils/session.d.ts.map +1 -1
  184. package/dist/cjs/utils/session.js +1 -0
  185. package/dist/cjs/utils/session.js.map +1 -1
  186. package/dist/core/Agent.d.ts +28 -18
  187. package/dist/core/Agent.d.ts.map +1 -1
  188. package/dist/core/Agent.js +58 -68
  189. package/dist/core/Agent.js.map +1 -1
  190. package/dist/core/AutoChainExecutor.d.ts.map +1 -1
  191. package/dist/core/AutoChainExecutor.js +14 -20
  192. package/dist/core/AutoChainExecutor.js.map +1 -1
  193. package/dist/core/BranchEvaluator.d.ts +4 -3
  194. package/dist/core/BranchEvaluator.d.ts.map +1 -1
  195. package/dist/core/BranchEvaluator.js +18 -23
  196. package/dist/core/BranchEvaluator.js.map +1 -1
  197. package/dist/core/Flow.d.ts +2 -1
  198. package/dist/core/Flow.d.ts.map +1 -1
  199. package/dist/core/Flow.js +10 -3
  200. package/dist/core/Flow.js.map +1 -1
  201. package/dist/core/FlowRouter.d.ts +1 -0
  202. package/dist/core/FlowRouter.d.ts.map +1 -1
  203. package/dist/core/FlowRouter.js +28 -5
  204. package/dist/core/FlowRouter.js.map +1 -1
  205. package/dist/core/PersistenceManager.d.ts +3 -0
  206. package/dist/core/PersistenceManager.d.ts.map +1 -1
  207. package/dist/core/PersistenceManager.js +58 -6
  208. package/dist/core/PersistenceManager.js.map +1 -1
  209. package/dist/core/PromptComposer.d.ts.map +1 -1
  210. package/dist/core/PromptComposer.js +24 -10
  211. package/dist/core/PromptComposer.js.map +1 -1
  212. package/dist/core/ResponseGenerationError.d.ts +30 -0
  213. package/dist/core/ResponseGenerationError.d.ts.map +1 -0
  214. package/dist/core/ResponseGenerationError.js +33 -0
  215. package/dist/core/ResponseGenerationError.js.map +1 -0
  216. package/dist/core/ResponseModal.d.ts +43 -96
  217. package/dist/core/ResponseModal.d.ts.map +1 -1
  218. package/dist/core/ResponseModal.js +177 -1175
  219. package/dist/core/ResponseModal.js.map +1 -1
  220. package/dist/core/ResponsePipeline.d.ts +58 -152
  221. package/dist/core/ResponsePipeline.d.ts.map +1 -1
  222. package/dist/core/ResponsePipeline.js +409 -458
  223. package/dist/core/ResponsePipeline.js.map +1 -1
  224. package/dist/core/SessionFinalizer.d.ts +34 -0
  225. package/dist/core/SessionFinalizer.d.ts.map +1 -0
  226. package/dist/core/SessionFinalizer.js +57 -0
  227. package/dist/core/SessionFinalizer.js.map +1 -0
  228. package/dist/core/SessionManager.d.ts +1 -1
  229. package/dist/core/SessionManager.d.ts.map +1 -1
  230. package/dist/core/SessionManager.js +18 -7
  231. package/dist/core/SessionManager.js.map +1 -1
  232. package/dist/core/SignalCoordinator.d.ts +103 -0
  233. package/dist/core/SignalCoordinator.d.ts.map +1 -0
  234. package/dist/core/SignalCoordinator.js +203 -0
  235. package/dist/core/SignalCoordinator.js.map +1 -0
  236. package/dist/core/SignalEvaluator.d.ts +2 -2
  237. package/dist/core/SignalEvaluator.d.ts.map +1 -1
  238. package/dist/core/SignalEvaluator.js +13 -27
  239. package/dist/core/SignalEvaluator.js.map +1 -1
  240. package/dist/core/SignalProcessor.d.ts.map +1 -1
  241. package/dist/core/SignalProcessor.js +1 -3
  242. package/dist/core/SignalProcessor.js.map +1 -1
  243. package/dist/core/Step.d.ts +3 -1
  244. package/dist/core/Step.d.ts.map +1 -1
  245. package/dist/core/Step.js +10 -3
  246. package/dist/core/Step.js.map +1 -1
  247. package/dist/core/StepLifecycle.d.ts +33 -0
  248. package/dist/core/StepLifecycle.d.ts.map +1 -0
  249. package/dist/core/StepLifecycle.js +93 -0
  250. package/dist/core/StepLifecycle.js.map +1 -0
  251. package/dist/core/ToolLoopExecutor.d.ts +104 -0
  252. package/dist/core/ToolLoopExecutor.d.ts.map +1 -0
  253. package/dist/core/ToolLoopExecutor.js +387 -0
  254. package/dist/core/ToolLoopExecutor.js.map +1 -0
  255. package/dist/core/ToolManager.d.ts +1 -1
  256. package/dist/core/ToolManager.d.ts.map +1 -1
  257. package/dist/core/ToolManager.js.map +1 -1
  258. package/dist/index.d.ts +4 -5
  259. package/dist/index.d.ts.map +1 -1
  260. package/dist/index.js +3 -3
  261. package/dist/index.js.map +1 -1
  262. package/dist/providers/AnthropicProvider.d.ts +2 -0
  263. package/dist/providers/AnthropicProvider.d.ts.map +1 -1
  264. package/dist/providers/AnthropicProvider.js +22 -50
  265. package/dist/providers/AnthropicProvider.js.map +1 -1
  266. package/dist/providers/DeepSeekProvider.d.ts +25 -21
  267. package/dist/providers/DeepSeekProvider.d.ts.map +1 -1
  268. package/dist/providers/DeepSeekProvider.js +49 -408
  269. package/dist/providers/DeepSeekProvider.js.map +1 -1
  270. package/dist/providers/GeminiProvider.d.ts +2 -0
  271. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  272. package/dist/providers/GeminiProvider.js +21 -50
  273. package/dist/providers/GeminiProvider.js.map +1 -1
  274. package/dist/providers/OpenAICompatibleProvider.d.ts +129 -0
  275. package/dist/providers/OpenAICompatibleProvider.d.ts.map +1 -0
  276. package/dist/providers/OpenAICompatibleProvider.js +481 -0
  277. package/dist/providers/OpenAICompatibleProvider.js.map +1 -0
  278. package/dist/providers/OpenAIProvider.d.ts +9 -28
  279. package/dist/providers/OpenAIProvider.d.ts.map +1 -1
  280. package/dist/providers/OpenAIProvider.js +23 -417
  281. package/dist/providers/OpenAIProvider.js.map +1 -1
  282. package/dist/providers/OpenRouterProvider.d.ts +10 -27
  283. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  284. package/dist/providers/OpenRouterProvider.js +28 -417
  285. package/dist/providers/OpenRouterProvider.js.map +1 -1
  286. package/dist/providers/errorClassification.d.ts +61 -0
  287. package/dist/providers/errorClassification.d.ts.map +1 -0
  288. package/dist/providers/errorClassification.js +116 -0
  289. package/dist/providers/errorClassification.js.map +1 -0
  290. package/dist/providers/index.d.ts +4 -0
  291. package/dist/providers/index.d.ts.map +1 -1
  292. package/dist/providers/index.js +2 -0
  293. package/dist/providers/index.js.map +1 -1
  294. package/dist/types/agent.d.ts +2 -1
  295. package/dist/types/agent.d.ts.map +1 -1
  296. package/dist/types/ai.d.ts +20 -0
  297. package/dist/types/ai.d.ts.map +1 -1
  298. package/dist/types/errors.d.ts +33 -0
  299. package/dist/types/errors.d.ts.map +1 -1
  300. package/dist/types/errors.js +34 -0
  301. package/dist/types/errors.js.map +1 -1
  302. package/dist/types/flow.d.ts +10 -5
  303. package/dist/types/flow.d.ts.map +1 -1
  304. package/dist/types/history.d.ts +1 -1
  305. package/dist/types/history.d.ts.map +1 -1
  306. package/dist/types/index.d.ts +5 -4
  307. package/dist/types/index.d.ts.map +1 -1
  308. package/dist/types/index.js +1 -1
  309. package/dist/types/index.js.map +1 -1
  310. package/dist/types/persistence.d.ts +43 -2
  311. package/dist/types/persistence.d.ts.map +1 -1
  312. package/dist/types/session.d.ts +8 -0
  313. package/dist/types/session.d.ts.map +1 -1
  314. package/dist/types/signals.d.ts +21 -11
  315. package/dist/types/signals.d.ts.map +1 -1
  316. package/dist/types/template.d.ts +3 -1
  317. package/dist/types/template.d.ts.map +1 -1
  318. package/dist/types/tool.d.ts +4 -4
  319. package/dist/types/tool.d.ts.map +1 -1
  320. package/dist/utils/condition.d.ts +19 -0
  321. package/dist/utils/condition.d.ts.map +1 -1
  322. package/dist/utils/condition.js +84 -15
  323. package/dist/utils/condition.js.map +1 -1
  324. package/dist/utils/session.d.ts +1 -0
  325. package/dist/utils/session.d.ts.map +1 -1
  326. package/dist/utils/session.js +1 -0
  327. package/dist/utils/session.js.map +1 -1
  328. package/docs/README.md +1 -1
  329. package/docs/guides/branching.md +1 -1
  330. package/docs/guides/compaction.md +12 -5
  331. package/docs/guides/conditions.md +15 -2
  332. package/docs/guides/error-handling.md +59 -9
  333. package/docs/guides/instructions.md +2 -2
  334. package/docs/guides/persistence.md +69 -2
  335. package/docs/guides/streaming.md +3 -1
  336. package/docs/migration/README.md +5 -1
  337. package/docs/migration/v2-3-to-v2-4.md +316 -0
  338. package/docs/reference/adapters.md +55 -7
  339. package/docs/reference/branches.md +2 -2
  340. package/docs/reference/create-agent.md +3 -3
  341. package/docs/reference/errors.md +66 -1
  342. package/docs/reference/flow.md +1 -1
  343. package/docs/reference/instruction.md +4 -4
  344. package/docs/reference/providers.md +100 -3
  345. package/docs/reference/signals.md +18 -8
  346. package/docs/reference/step.md +2 -2
  347. package/docs/reference/tool.md +3 -1
  348. package/docs/start/05-go-to-production.md +3 -0
  349. package/package.json +1 -1
  350. package/src/adapters/MemoryAdapter.ts +15 -1
  351. package/src/adapters/MongoAdapter.ts +41 -2
  352. package/src/adapters/OpenSearchAdapter.ts +24 -1
  353. package/src/adapters/PostgreSQLAdapter.ts +45 -5
  354. package/src/adapters/PrismaAdapter.ts +82 -16
  355. package/src/adapters/RedisAdapter.ts +19 -1
  356. package/src/adapters/SQLiteAdapter.ts +47 -5
  357. package/src/core/Agent.ts +70 -85
  358. package/src/core/AutoChainExecutor.ts +27 -57
  359. package/src/core/BranchEvaluator.ts +24 -30
  360. package/src/core/Flow.ts +10 -3
  361. package/src/core/FlowRouter.ts +36 -4
  362. package/src/core/PersistenceManager.ts +79 -10
  363. package/src/core/PromptComposer.ts +25 -12
  364. package/src/core/ResponseGenerationError.ts +56 -0
  365. package/src/core/ResponseModal.ts +241 -1465
  366. package/src/core/ResponsePipeline.ts +492 -662
  367. package/src/core/SessionFinalizer.ts +78 -0
  368. package/src/core/SessionManager.ts +21 -9
  369. package/src/core/SignalCoordinator.ts +263 -0
  370. package/src/core/SignalEvaluator.ts +14 -30
  371. package/src/core/SignalProcessor.ts +1 -4
  372. package/src/core/Step.ts +11 -3
  373. package/src/core/StepLifecycle.ts +139 -0
  374. package/src/core/ToolLoopExecutor.ts +492 -0
  375. package/src/core/ToolManager.ts +2 -1
  376. package/src/index.ts +7 -5
  377. package/src/providers/AnthropicProvider.ts +30 -72
  378. package/src/providers/DeepSeekProvider.ts +74 -586
  379. package/src/providers/GeminiProvider.ts +29 -70
  380. package/src/providers/OpenAICompatibleProvider.ts +738 -0
  381. package/src/providers/OpenAIProvider.ts +29 -602
  382. package/src/providers/OpenRouterProvider.ts +38 -596
  383. package/src/providers/errorClassification.ts +172 -0
  384. package/src/providers/index.ts +13 -0
  385. package/src/types/agent.ts +2 -1
  386. package/src/types/ai.ts +22 -0
  387. package/src/types/errors.ts +57 -0
  388. package/src/types/flow.ts +10 -5
  389. package/src/types/history.ts +1 -2
  390. package/src/types/index.ts +5 -1
  391. package/src/types/persistence.ts +50 -2
  392. package/src/types/session.ts +9 -0
  393. package/src/types/signals.ts +23 -11
  394. package/src/types/template.ts +3 -1
  395. package/src/types/tool.ts +10 -10
  396. package/src/utils/condition.ts +115 -18
  397. package/src/utils/session.ts +2 -0
package/src/core/Agent.ts CHANGED
@@ -23,7 +23,7 @@ import type { Signal } from "../types/signals";
23
23
  import { NotImplementedError } from "../types/errors";
24
24
  import { SignalProcessor } from "./SignalProcessor";
25
25
  import { SignalEvaluator } from "./SignalEvaluator";
26
- import type { StreamOptions, GenerateOptions, RespondParams } from "./ResponseModal";
26
+ import type { StreamOptions, GenerateOptions, RespondParams, ResponseModalDeps } from "./ResponseModal";
27
27
  import {
28
28
  mergeCollected,
29
29
  enterFlow,
@@ -68,8 +68,8 @@ class FlowConfigurationError extends Error {
68
68
  /**
69
69
  * Main Agent class with generic context and data support
70
70
  */
71
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
- export class Agent<TContext = any, TData = any> {
71
+
72
+ export class Agent<TContext = unknown, TData = unknown> implements ResponseModalDeps<TContext, TData> {
73
73
  private _terms: Term<TContext, TData>[] = [];
74
74
  private _instructions: Instruction<TContext, TData>[] = [];
75
75
  private _tools: Tool<TContext, TData>[] = [];
@@ -78,10 +78,15 @@ export class Agent<TContext = any, TData = any> {
78
78
  private _persistenceManager: PersistenceManager<TData> | undefined;
79
79
  private _routingEngine: FlowRouter<TContext, TData>;
80
80
  private _responseModal: ResponseModal<TContext, TData>;
81
- private _currentSession?: SessionState<TData>;
82
81
  private _knowledgeBase: Record<string, unknown> = {};
83
82
  private _schema?: StructuredSchema;
84
- private _collectedData: Partial<TData> = {};
83
+ /**
84
+ * Staging buffer for data set before any session exists (initialData and
85
+ * pre-session updateCollectedData calls). Consumed when a session is
86
+ * created; once a session exists, `session.data` is the single source of
87
+ * truth and this buffer stays empty.
88
+ */
89
+ private _pendingData: Partial<TData> = {};
85
90
  private _compactionOptions?: CompactionOptions;
86
91
  private _promptSectionCache: PromptSectionCache;
87
92
 
@@ -232,13 +237,10 @@ export class Agent<TContext = any, TData = any> {
232
237
  );
233
238
  }
234
239
  }
235
- this._collectedData = { ...options.initialData };
236
- logger.debug("[Agent] Initial data set:", this._collectedData);
240
+ this._pendingData = { ...options.initialData };
241
+ logger.debug("[Agent] Initial data set:", this._pendingData);
237
242
  }
238
243
 
239
- // Initialize current session if provided
240
- this._currentSession = options.session;
241
-
242
244
  // Initialize prompt section cache
243
245
  this._promptSectionCache = new PromptSectionCache(options.promptCache);
244
246
 
@@ -338,25 +340,35 @@ export class Agent<TContext = any, TData = any> {
338
340
  logger.debug("[Agent] Compaction options initialized and validated");
339
341
  }
340
342
 
341
- // Initialize session manager with reference to this agent for bidirectional sync
343
+ // Initialize session manager the single owner of the live session
342
344
  this.session = new SessionManager<TData>(this._persistenceManager, this);
343
345
 
346
+ // Adopt an explicitly provided session
347
+ if (options.session) {
348
+ this.session.syncSession(options.session);
349
+ }
350
+
344
351
  // Store sessionId for later use in getOrCreate calls
345
352
  if (options.sessionId) {
346
353
  this.session.setDefaultSessionId(options.sessionId);
347
- // The session will be loaded on first getOrCreate call
348
- this.session.getOrCreate(options.sessionId).then((session) => {
349
- // Sync session data to agent collected data
350
- if (session.data && Object.keys(session.data).length > 0) {
351
- this._collectedData = { ...session.data };
352
- logger.debug("[Agent] Synced session data to collected data:", this._collectedData);
353
- }
354
- }).catch((err) => {
354
+ // The session will be loaded on first getOrCreate call; session.data
355
+ // is the source of truth, so no data sync is needed here
356
+ this.session.getOrCreate(options.sessionId).catch((err) => {
355
357
  logger.error("Failed to start session", err);
356
358
  });
357
359
  }
358
360
  }
359
361
 
362
+ /**
363
+ * Drain the pre-session data staging buffer.
364
+ * @internal Called by SessionManager when a session is created or loaded.
365
+ */
366
+ consumePendingData(): Partial<TData> {
367
+ const pending = this._pendingData;
368
+ this._pendingData = {};
369
+ return pending;
370
+ }
371
+
360
372
  /**
361
373
  * Validate the agent-level schema structure
362
374
  * @private
@@ -523,16 +535,19 @@ export class Agent<TContext = any, TData = any> {
523
535
  }
524
536
 
525
537
  /**
526
- * Get the current collected data
538
+ * Get the current collected data.
539
+ * Reads from the live session when one exists; otherwise from the
540
+ * pre-session staging buffer.
527
541
  */
528
542
  getCollectedData(): Partial<TData> {
529
- // Ensure agent collected data is synced with session
530
- this.syncSessionDataToCollectedData();
531
- return { ...this._collectedData };
543
+ const session = this.session.current;
544
+ return session ? { ...session.data } : { ...this._pendingData };
532
545
  }
533
546
 
534
547
  /**
535
- * Update collected data with validation
548
+ * Update collected data with validation.
549
+ * Writes to the live session when one exists; otherwise stages the data
550
+ * for the session that will be created.
536
551
  */
537
552
  async updateCollectedData(updates: Partial<TData>): Promise<void> {
538
553
  // Validate the updates
@@ -548,31 +563,24 @@ export class Agent<TContext = any, TData = any> {
548
563
  logger.warn(`[Agent] Data validation warnings: ${warningMessages}`);
549
564
  }
550
565
 
551
- // Merge updates with current data
552
- const previousData = { ...this._collectedData };
553
- this._collectedData = {
554
- ...this._collectedData,
566
+ const session = this.session.current;
567
+ const previousData = session ? { ...session.data } : { ...this._pendingData };
568
+
569
+ let newData: Partial<TData> = {
570
+ ...previousData,
555
571
  ...updates
556
572
  };
557
573
 
558
574
  // Trigger agent-level lifecycle hook if configured
559
575
  if (this.options.hooks?.onDataUpdate) {
560
- this._collectedData = await this.options.hooks.onDataUpdate(
561
- this._collectedData,
562
- previousData
563
- );
576
+ newData = await this.options.hooks.onDataUpdate(newData, previousData);
564
577
  }
565
578
 
566
- // Update current session if it exists to keep it in sync
567
- if (this._currentSession) {
568
- this._currentSession = mergeCollected(this._currentSession, this._collectedData);
569
- }
570
-
571
- // Also update the session manager's session data (avoid circular call)
572
- const sessionManagerSession = this.session.current;
573
- if (sessionManagerSession) {
574
- sessionManagerSession.data = { ...this._collectedData };
575
- sessionManagerSession.metadata!.lastUpdatedAt = new Date();
579
+ if (session) {
580
+ session.data = newData;
581
+ session.metadata!.lastUpdatedAt = new Date();
582
+ } else {
583
+ this._pendingData = newData;
576
584
  }
577
585
 
578
586
  logger.debug("[Agent] Collected data updated:", updates);
@@ -743,18 +751,19 @@ export class Agent<TContext = any, TData = any> {
743
751
  }
744
752
 
745
753
  /**
746
- * Get the current session (if set)
754
+ * Get the current session (if set). Delegates to the SessionManager —
755
+ * the single owner of the live session.
747
756
  */
748
- get currentSession(): SessionState | undefined {
749
- return this._currentSession;
757
+ get currentSession(): SessionState<TData> | undefined {
758
+ return this.session.current;
750
759
  }
751
760
 
752
761
  /**
753
762
  * Set the current session for convenience methods
754
763
  * Set to undefined to clear the current session
755
764
  */
756
- set currentSession(value: SessionState | undefined) {
757
- this._currentSession = value;
765
+ set currentSession(value: SessionState<TData> | undefined) {
766
+ this.session.syncSession(value);
758
767
  this._promptSectionCache.invalidateAll();
759
768
  }
760
769
 
@@ -895,8 +904,8 @@ export class Agent<TContext = any, TData = any> {
895
904
  * Add a tool to the agent using the unified Tool interface
896
905
  * Creates and adds the tool to agent scope in one operation
897
906
  */
898
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
899
- addTool<TResult = any>(
907
+
908
+ addTool<TResult = unknown>(
900
909
  tool: Tool<TContext, TData, TResult>
901
910
  ): this {
902
911
  // Validate tool before adding
@@ -913,8 +922,8 @@ export class Agent<TContext = any, TData = any> {
913
922
  /**
914
923
  * Register multiple tools at the agent level
915
924
  */
916
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
917
- registerTools<TResult = any>(tools: Tool<TContext, TData, TResult>[]): this {
925
+
926
+ registerTools<TResult = unknown>(tools: Tool<TContext, TData, TResult>[]): this {
918
927
  tools.forEach((tool) => {
919
928
  // Validate each tool before adding
920
929
  if (!tool || !tool.id || !tool.handler) {
@@ -940,9 +949,10 @@ export class Agent<TContext = any, TData = any> {
940
949
  } as TContext;
941
950
 
942
951
  // Trigger flow-specific lifecycle hook if configured and session has current flow
943
- if (this._currentSession?.currentFlow) {
952
+ const activeSession = this.session.current;
953
+ if (activeSession?.currentFlow) {
944
954
  const currentFlow = this._flows.find(
945
- (r) => r.id === this._currentSession!.currentFlow?.id
955
+ (r) => r.id === activeSession.currentFlow?.id
946
956
  );
947
957
  if (
948
958
  currentFlow?.hooks?.onContextUpdate &&
@@ -1001,10 +1011,8 @@ export class Agent<TContext = any, TData = any> {
1001
1011
  ));
1002
1012
  }
1003
1013
 
1004
- // Update agent's collected data to stay in sync
1005
- this._collectedData = { ...newCollected };
1006
-
1007
- // Return updated session
1014
+ // Return updated session — session.data is the single source of truth,
1015
+ // so no agent-side copy is kept
1008
1016
  return mergeCollected(session, newCollected);
1009
1017
  }
1010
1018
 
@@ -1127,33 +1135,10 @@ export class Agent<TContext = any, TData = any> {
1127
1135
  }
1128
1136
 
1129
1137
  /**
1130
- * Sync session data to agent collected data
1131
- * @internal Used to keep agent and session data in sync
1132
- */
1133
- private syncSessionDataToCollectedData(): void {
1134
- const sessionData = this.session.getData();
1135
- if (sessionData && Object.keys(sessionData).length > 0) {
1136
- this._collectedData = { ...sessionData };
1137
- logger.debug("[Agent] Synced session data to collected data:", this._collectedData);
1138
- }
1139
- }
1140
-
1141
- /**
1142
- * Get collected data from current session or agent-level collected data
1143
- * @returns The collected data from the current session or agent-level data
1138
+ * Get collected data from the current session (or the pre-session staging
1139
+ * buffer when no session exists yet). Alias of getCollectedData().
1144
1140
  */
1145
1141
  getData(): Partial<TData> {
1146
- // Ensure agent collected data is synced with session
1147
- this.syncSessionDataToCollectedData();
1148
-
1149
- // If we have a current session, use session data
1150
- if (this._currentSession) {
1151
- // With agent-level data, all flows share the same data structure
1152
- // No need for flow-specific data access
1153
- return (this._currentSession.data) || {};
1154
- }
1155
-
1156
- // Otherwise, return agent-level collected data
1157
1142
  return this.getCollectedData();
1158
1143
  }
1159
1144
 
@@ -1184,7 +1169,7 @@ export class Agent<TContext = any, TData = any> {
1184
1169
  target: string | Directive<TContext, TData>,
1185
1170
  session?: SessionState<TData>
1186
1171
  ): Promise<SessionState<TData>> {
1187
- const targetSession = session || this._currentSession;
1172
+ const targetSession = session || this.session.current;
1188
1173
 
1189
1174
  if (!targetSession) {
1190
1175
  throw new Error(
@@ -1239,8 +1224,8 @@ export class Agent<TContext = any, TData = any> {
1239
1224
  };
1240
1225
 
1241
1226
  // Update current session in place if no explicit session was passed
1242
- if (!session && this._currentSession) {
1243
- this._currentSession = updatedSession;
1227
+ if (!session && this.session.current) {
1228
+ this.session.syncSession(updatedSession);
1244
1229
  }
1245
1230
 
1246
1231
  logger.debug(
@@ -21,7 +21,13 @@ import { FlowConfigurationError, Step } from "./Step";
21
21
  import { Flow } from "./Flow";
22
22
  import { enterStep, mergeCollected, logger } from "../utils";
23
23
  import { createTemplateContext } from "../utils/template";
24
- import type { StoppedReason } from "../types/flow";
24
+ import type {
25
+ StoppedReason,
26
+ BranchMap,
27
+ BranchEntry,
28
+ BranchPredicateContext,
29
+ } from "../types/flow";
30
+ import { evaluateIfPredicates } from "../utils/condition";
25
31
 
26
32
  /**
27
33
  * The directive-like object that `prepare` may return on auto-steps.
@@ -40,39 +46,6 @@ export interface AutoStepPrepareResult {
40
46
  complete?: boolean;
41
47
  }
42
48
 
43
- /**
44
- * A branch predicate context passed to `if` functions.
45
- */
46
- interface BranchPredicateContext<TContext, TData> {
47
- data: Partial<TData> | undefined;
48
- context: TContext;
49
- session: SessionState<TData>;
50
- history: Event[];
51
- }
52
-
53
- /**
54
- * A branch `then` target — either a string step/flow id or a directive object.
55
- */
56
- type BranchThen = string | { goToStep?: string; goTo?: string } | undefined;
57
-
58
- /**
59
- * A branch entry on a step. Supports code predicates (`if`), AI predicates (`when`),
60
- * and a target (`then`).
61
- */
62
- interface BranchEntry<TContext, TData> {
63
- if?: ((ctx: BranchPredicateContext<TContext, TData>) => boolean | Promise<boolean>) | Array<(ctx: BranchPredicateContext<TContext, TData>) => boolean | Promise<boolean>>;
64
- when?: string;
65
- then?: BranchThen;
66
- }
67
-
68
- /**
69
- * Structural type for a step that may have branches (accessed via cast).
70
- */
71
- interface StepWithBranches<TContext, TData> {
72
- branches?: BranchEntry<TContext, TData>[];
73
- onEnter?: (context: TContext, data: Partial<TData> | undefined) => Promise<unknown>;
74
- }
75
-
76
49
  /**
77
50
  * Result of running the auto-chain.
78
51
  */
@@ -250,10 +223,9 @@ export class AutoChainExecutor<TContext = unknown, TData = unknown> {
250
223
  }
251
224
 
252
225
  // STEP 6: branches resolution (if step has branches)
253
- const stepWithBranches = step as unknown as StepWithBranches<TContext, TData>;
254
- if (stepWithBranches.branches && Array.isArray(stepWithBranches.branches) && stepWithBranches.branches.length > 0) {
226
+ if (step.branches && step.branches.length > 0) {
255
227
  const branchTarget = await this.evaluateBranches(
256
- stepWithBranches.branches,
228
+ step.branches,
257
229
  session,
258
230
  context,
259
231
  history
@@ -302,7 +274,9 @@ export class AutoChainExecutor<TContext = unknown, TData = unknown> {
302
274
  let merged: AutoStepPrepareResult | undefined;
303
275
 
304
276
  // onEnter (future hook — not yet in StepOptions, but handle if present)
305
- const stepWithHooks = step as unknown as StepWithBranches<TContext, TData>;
277
+ const stepWithHooks = step as Step<TContext, TData> & {
278
+ onEnter?: (context: TContext, data: Partial<TData> | undefined) => Promise<unknown>;
279
+ };
306
280
  if (typeof stepWithHooks.onEnter === 'function') {
307
281
  const onEnterResult = await stepWithHooks.onEnter(context, session.data);
308
282
  if (onEnterResult && typeof onEnterResult === 'object') {
@@ -370,7 +344,7 @@ export class AutoChainExecutor<TContext = unknown, TData = unknown> {
370
344
  * context (no LLM call). If a branch entry has only `when`, it is skipped.
371
345
  */
372
346
  private async evaluateBranches(
373
- branches: BranchEntry<TContext, TData>[],
347
+ branches: BranchMap<TContext, TData>,
374
348
  session: SessionState<TData>,
375
349
  context: TContext,
376
350
  history: Event[]
@@ -385,20 +359,12 @@ export class AutoChainExecutor<TContext = unknown, TData = unknown> {
385
359
 
386
360
  // Code predicate evaluation
387
361
  if (entry.if) {
388
- const predicates = Array.isArray(entry.if) ? entry.if : [entry.if];
389
- const predicateContext: BranchPredicateContext<TContext, TData> = { data: session.data, context, session, history };
390
-
391
- let allPassed = true;
392
- for (const predicate of predicates) {
393
- if (typeof predicate === 'function') {
394
- const result = await predicate(predicateContext);
395
- if (!result) {
396
- allPassed = false;
397
- break;
398
- }
399
- }
400
- }
401
-
362
+ const predicateContext: BranchPredicateContext<TContext, TData> = {
363
+ data: session.data, context, session, history,
364
+ };
365
+ const allPassed = await evaluateIfPredicates<BranchPredicateContext<TContext, TData>>(
366
+ entry.if, predicateContext, "AutoChainExecutor"
367
+ );
402
368
  if (!allPassed) continue;
403
369
 
404
370
  // If entry also has `when`, skip it in auto-step context (no LLM available)
@@ -426,14 +392,18 @@ export class AutoChainExecutor<TContext = unknown, TData = unknown> {
426
392
  * Resolve a branch entry's `then` value to a string target.
427
393
  * Handles both string targets and Directive objects.
428
394
  */
429
- private resolveBranchThen(then: BranchThen): string | undefined {
395
+ private resolveBranchThen(then: BranchEntry<TContext, TData>["then"]): string | undefined {
430
396
  if (typeof then === 'string') {
431
397
  return then;
432
398
  }
433
- // Directive object — extract position field
399
+ // Directive object — extract position field (string or object form)
434
400
  if (then && typeof then === 'object') {
435
- if (then.goToStep) return then.goToStep;
436
- if (then.goTo) return then.goTo;
401
+ if (then.goToStep) {
402
+ return typeof then.goToStep === 'string' ? then.goToStep : then.goToStep.step;
403
+ }
404
+ if (then.goTo) {
405
+ return typeof then.goTo === 'string' ? then.goTo : then.goTo.flow;
406
+ }
437
407
  }
438
408
  return undefined;
439
409
  }
@@ -10,23 +10,23 @@
10
10
 
11
11
  import type {
12
12
  BranchMap,
13
- BranchPredicate,
14
13
  BranchPredicateContext,
15
14
  Directive,
16
15
  } from "../types/flow";
17
16
  import type { AiProvider } from "../types/ai";
18
17
  import type { Event } from "../types/history";
19
18
  import { eventsToHistory, logger } from "../utils";
19
+ import { splitWhenConditions, evaluateIfPredicates, type WhenConditionGroups } from "../utils/condition";
20
20
 
21
21
  /**
22
22
  * The AI condition evaluator function signature.
23
- * Accepts an array of condition strings (OR semantics) and returns
24
- * whether any condition is satisfied.
23
+ * Accepts split condition strings and returns whether the condition passes:
24
+ * (no positives OR any positive is satisfied) AND no exclusion is satisfied.
25
25
  *
26
26
  * This is the same evaluation mechanism used by `step.when` — condition
27
27
  * strings are evaluated by the AI provider against the conversation context.
28
28
  */
29
- export type AiConditionEvaluator = (conditions: string[]) => Promise<boolean>;
29
+ export type AiConditionEvaluator = (conditions: WhenConditionGroups) => Promise<boolean>;
30
30
 
31
31
  /**
32
32
  * Creates an `AiConditionEvaluator` bound to a provider and conversation context.
@@ -50,22 +50,28 @@ export function createAiConditionEvaluator<TContext = unknown>(
50
50
  history: Event[],
51
51
  context: TContext,
52
52
  ): AiConditionEvaluator {
53
- return async (conditions: string[]): Promise<boolean> => {
54
- if (conditions.length === 0) {
53
+ return async (conditions: WhenConditionGroups): Promise<boolean> => {
54
+ if (conditions.positive.length === 0 && conditions.negative.length === 0) {
55
55
  return true;
56
56
  }
57
57
 
58
- const conditionText = conditions.length === 1
59
- ? conditions[0]
60
- : conditions.map((c, i) => `${i + 1}. ${c}`).join("\n");
58
+ const positiveText = conditions.positive.length === 0
59
+ ? "None. Treat the positive side as satisfied unless an exclusion matches."
60
+ : conditions.positive.map((c, i) => `${i + 1}. ${c}`).join("\n");
61
+ const negativeText = conditions.negative.length === 0
62
+ ? "None."
63
+ : conditions.negative.map((c, i) => `${i + 1}. ${c}`).join("\n");
61
64
 
62
65
  const prompt = [
63
- "Evaluate whether the following condition(s) are met based on the conversation so far.",
66
+ "Evaluate whether the following condition rule passes based on the conversation so far.",
64
67
  "",
65
- "Condition(s):",
66
- conditionText,
68
+ "Positive condition(s) (OR):",
69
+ positiveText,
67
70
  "",
68
- "Return JSON with a single boolean field `result`: true if ANY condition is satisfied, false otherwise.",
71
+ "Exclusion condition(s) (OR, any match inhibits):",
72
+ negativeText,
73
+ "",
74
+ "Return JSON with a single boolean field `result`: true only when (there are no positive conditions OR ANY positive condition is satisfied) AND NO exclusion condition is satisfied.",
69
75
  ].join("\n");
70
76
 
71
77
  const result = await provider.generateMessage<TContext, { result: boolean }>({
@@ -78,7 +84,7 @@ export function createAiConditionEvaluator<TContext = unknown>(
78
84
  properties: {
79
85
  result: {
80
86
  type: "boolean",
81
- description: "Whether any condition is met based on the conversation context",
87
+ description: "Whether the positive/exclusion condition rule passes based on the conversation context",
82
88
  },
83
89
  },
84
90
  required: ["result"],
@@ -122,19 +128,9 @@ export async function evaluateBranches<TContext = unknown, TData = unknown>(
122
128
 
123
129
  // Code predicate first (free evaluation)
124
130
  if (entry.if) {
125
- const predicates: BranchPredicate<TContext, TData>[] = Array.isArray(entry.if)
126
- ? entry.if
127
- : [entry.if];
128
-
129
- let ifPassed = true;
130
- for (const predicate of predicates) {
131
- const result = await predicate(ctx);
132
- if (!result) {
133
- ifPassed = false;
134
- break;
135
- }
136
- }
137
-
131
+ const ifPassed = await evaluateIfPredicates<BranchPredicateContext<TContext, TData>>(
132
+ entry.if, ctx, "BranchEvaluator"
133
+ );
138
134
  if (!ifPassed) {
139
135
  continue; // skip this entry; do NOT evaluate `when`
140
136
  }
@@ -142,9 +138,7 @@ export async function evaluateBranches<TContext = unknown, TData = unknown>(
142
138
 
143
139
  // AI condition (costs tokens — only reached if `if` passed or was absent)
144
140
  if (entry.when) {
145
- const conditions: string[] = Array.isArray(entry.when)
146
- ? entry.when
147
- : [entry.when];
141
+ const conditions = splitWhenConditions(entry.when);
148
142
 
149
143
  const aiResult = await evaluateAi(conditions);
150
144
  if (!aiResult) {
package/src/core/Flow.ts CHANGED
@@ -19,6 +19,7 @@ import type { StepResult } from "../types/flow";
19
19
  import type { ConditionWhen, ConditionIf } from "../types/flow";
20
20
 
21
21
  import { generateFlowId, logger } from "../utils";
22
+ import { splitWhenConditions } from "../utils/condition";
22
23
 
23
24
  import { Step, FlowConfigurationError } from "./Step";
24
25
  import { Agent } from './Agent'
@@ -246,7 +247,8 @@ export class Flow<TContext = unknown, TData = unknown> {
246
247
  /**
247
248
  * Evaluate when/if conditions using the v2 split logic.
248
249
  * `if` (code predicate) evaluates first (free); `when` (AI) evaluates only when `if` passes.
249
- * `if` predicates use AND semantics. `when` strings use OR semantics.
250
+ * `if` predicates use AND semantics. Non-`!` `when` strings use OR semantics;
251
+ * `!` strings are exclusions where any match inhibits activation.
250
252
  * When both fields are set, the passing `if` gate and AI match are combined with AND.
251
253
  */
252
254
  async evaluateWhen(
@@ -257,6 +259,7 @@ export class Flow<TContext = unknown, TData = unknown> {
257
259
  return {
258
260
  programmaticResult: true,
259
261
  aiContextStrings: [],
262
+ aiExclusionStrings: [],
260
263
  hasProgrammaticConditions: false,
261
264
  };
262
265
  }
@@ -277,6 +280,7 @@ export class Flow<TContext = unknown, TData = unknown> {
277
280
  return {
278
281
  programmaticResult: false,
279
282
  aiContextStrings: [],
283
+ aiExclusionStrings: [],
280
284
  hasProgrammaticConditions: true,
281
285
  };
282
286
  }
@@ -285,6 +289,7 @@ export class Flow<TContext = unknown, TData = unknown> {
285
289
  return {
286
290
  programmaticResult: false,
287
291
  aiContextStrings: [],
292
+ aiExclusionStrings: [],
288
293
  hasProgrammaticConditions: true,
289
294
  };
290
295
  }
@@ -293,10 +298,11 @@ export class Flow<TContext = unknown, TData = unknown> {
293
298
 
294
299
  // `if` passed (or was absent) — now evaluate `when` (AI-evaluated strings)
295
300
  if (this.when) {
296
- const whenStrings = Array.isArray(this.when) ? this.when : [this.when];
301
+ const whenConditions = splitWhenConditions(this.when);
297
302
  return {
298
303
  programmaticResult: true,
299
- aiContextStrings: whenStrings,
304
+ aiContextStrings: whenConditions.positive,
305
+ aiExclusionStrings: whenConditions.negative,
300
306
  hasProgrammaticConditions: !!this.if,
301
307
  };
302
308
  }
@@ -305,6 +311,7 @@ export class Flow<TContext = unknown, TData = unknown> {
305
311
  return {
306
312
  programmaticResult: true,
307
313
  aiContextStrings: [],
314
+ aiExclusionStrings: [],
308
315
  hasProgrammaticConditions: true,
309
316
  };
310
317
  }