@falai/agent 2.2.4 → 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 (390) 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 -102
  75. package/dist/cjs/core/ResponseModal.d.ts.map +1 -1
  76. package/dist/cjs/core/ResponseModal.js +178 -1194
  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 +11 -26
  97. package/dist/cjs/core/SignalEvaluator.js.map +1 -1
  98. package/dist/cjs/core/Step.d.ts +3 -1
  99. package/dist/cjs/core/Step.d.ts.map +1 -1
  100. package/dist/cjs/core/Step.js +10 -3
  101. package/dist/cjs/core/Step.js.map +1 -1
  102. package/dist/cjs/core/StepLifecycle.d.ts +33 -0
  103. package/dist/cjs/core/StepLifecycle.d.ts.map +1 -0
  104. package/dist/cjs/core/StepLifecycle.js +97 -0
  105. package/dist/cjs/core/StepLifecycle.js.map +1 -0
  106. package/dist/cjs/core/ToolLoopExecutor.d.ts +104 -0
  107. package/dist/cjs/core/ToolLoopExecutor.d.ts.map +1 -0
  108. package/dist/cjs/core/ToolLoopExecutor.js +391 -0
  109. package/dist/cjs/core/ToolLoopExecutor.js.map +1 -0
  110. package/dist/cjs/core/ToolManager.d.ts +1 -1
  111. package/dist/cjs/core/ToolManager.d.ts.map +1 -1
  112. package/dist/cjs/core/ToolManager.js.map +1 -1
  113. package/dist/cjs/index.d.ts +4 -5
  114. package/dist/cjs/index.d.ts.map +1 -1
  115. package/dist/cjs/index.js +7 -6
  116. package/dist/cjs/index.js.map +1 -1
  117. package/dist/cjs/providers/AnthropicProvider.d.ts +2 -0
  118. package/dist/cjs/providers/AnthropicProvider.d.ts.map +1 -1
  119. package/dist/cjs/providers/AnthropicProvider.js +28 -56
  120. package/dist/cjs/providers/AnthropicProvider.js.map +1 -1
  121. package/dist/cjs/providers/DeepSeekProvider.d.ts +25 -21
  122. package/dist/cjs/providers/DeepSeekProvider.d.ts.map +1 -1
  123. package/dist/cjs/providers/DeepSeekProvider.js +48 -407
  124. package/dist/cjs/providers/DeepSeekProvider.js.map +1 -1
  125. package/dist/cjs/providers/GeminiProvider.d.ts +2 -0
  126. package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
  127. package/dist/cjs/providers/GeminiProvider.js +27 -56
  128. package/dist/cjs/providers/GeminiProvider.js.map +1 -1
  129. package/dist/cjs/providers/OpenAICompatibleProvider.d.ts +129 -0
  130. package/dist/cjs/providers/OpenAICompatibleProvider.d.ts.map +1 -0
  131. package/dist/cjs/providers/OpenAICompatibleProvider.js +485 -0
  132. package/dist/cjs/providers/OpenAICompatibleProvider.js.map +1 -0
  133. package/dist/cjs/providers/OpenAIProvider.d.ts +9 -28
  134. package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
  135. package/dist/cjs/providers/OpenAIProvider.js +23 -417
  136. package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
  137. package/dist/cjs/providers/OpenRouterProvider.d.ts +10 -27
  138. package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
  139. package/dist/cjs/providers/OpenRouterProvider.js +28 -417
  140. package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
  141. package/dist/cjs/providers/errorClassification.d.ts +61 -0
  142. package/dist/cjs/providers/errorClassification.d.ts.map +1 -0
  143. package/dist/cjs/providers/errorClassification.js +123 -0
  144. package/dist/cjs/providers/errorClassification.js.map +1 -0
  145. package/dist/cjs/providers/index.d.ts +4 -0
  146. package/dist/cjs/providers/index.d.ts.map +1 -1
  147. package/dist/cjs/providers/index.js +7 -1
  148. package/dist/cjs/providers/index.js.map +1 -1
  149. package/dist/cjs/types/agent.d.ts +2 -1
  150. package/dist/cjs/types/agent.d.ts.map +1 -1
  151. package/dist/cjs/types/ai.d.ts +20 -0
  152. package/dist/cjs/types/ai.d.ts.map +1 -1
  153. package/dist/cjs/types/errors.d.ts +33 -0
  154. package/dist/cjs/types/errors.d.ts.map +1 -1
  155. package/dist/cjs/types/errors.js +37 -1
  156. package/dist/cjs/types/errors.js.map +1 -1
  157. package/dist/cjs/types/flow.d.ts +10 -5
  158. package/dist/cjs/types/flow.d.ts.map +1 -1
  159. package/dist/cjs/types/history.d.ts +1 -1
  160. package/dist/cjs/types/history.d.ts.map +1 -1
  161. package/dist/cjs/types/index.d.ts +5 -4
  162. package/dist/cjs/types/index.d.ts.map +1 -1
  163. package/dist/cjs/types/index.js +3 -1
  164. package/dist/cjs/types/index.js.map +1 -1
  165. package/dist/cjs/types/persistence.d.ts +43 -2
  166. package/dist/cjs/types/persistence.d.ts.map +1 -1
  167. package/dist/cjs/types/session.d.ts +8 -0
  168. package/dist/cjs/types/session.d.ts.map +1 -1
  169. package/dist/cjs/types/signals.d.ts +12 -2
  170. package/dist/cjs/types/signals.d.ts.map +1 -1
  171. package/dist/cjs/types/template.d.ts +3 -1
  172. package/dist/cjs/types/template.d.ts.map +1 -1
  173. package/dist/cjs/types/tool.d.ts +4 -4
  174. package/dist/cjs/types/tool.d.ts.map +1 -1
  175. package/dist/cjs/utils/condition.d.ts +19 -0
  176. package/dist/cjs/utils/condition.d.ts.map +1 -1
  177. package/dist/cjs/utils/condition.js +86 -15
  178. package/dist/cjs/utils/condition.js.map +1 -1
  179. package/dist/cjs/utils/session.d.ts +1 -0
  180. package/dist/cjs/utils/session.d.ts.map +1 -1
  181. package/dist/cjs/utils/session.js +1 -0
  182. package/dist/cjs/utils/session.js.map +1 -1
  183. package/dist/core/Agent.d.ts +28 -18
  184. package/dist/core/Agent.d.ts.map +1 -1
  185. package/dist/core/Agent.js +58 -68
  186. package/dist/core/Agent.js.map +1 -1
  187. package/dist/core/AutoChainExecutor.d.ts.map +1 -1
  188. package/dist/core/AutoChainExecutor.js +14 -20
  189. package/dist/core/AutoChainExecutor.js.map +1 -1
  190. package/dist/core/BranchEvaluator.d.ts +4 -3
  191. package/dist/core/BranchEvaluator.d.ts.map +1 -1
  192. package/dist/core/BranchEvaluator.js +18 -23
  193. package/dist/core/BranchEvaluator.js.map +1 -1
  194. package/dist/core/Flow.d.ts +2 -1
  195. package/dist/core/Flow.d.ts.map +1 -1
  196. package/dist/core/Flow.js +10 -3
  197. package/dist/core/Flow.js.map +1 -1
  198. package/dist/core/FlowRouter.d.ts +1 -0
  199. package/dist/core/FlowRouter.d.ts.map +1 -1
  200. package/dist/core/FlowRouter.js +28 -5
  201. package/dist/core/FlowRouter.js.map +1 -1
  202. package/dist/core/PersistenceManager.d.ts +3 -0
  203. package/dist/core/PersistenceManager.d.ts.map +1 -1
  204. package/dist/core/PersistenceManager.js +58 -6
  205. package/dist/core/PersistenceManager.js.map +1 -1
  206. package/dist/core/PromptComposer.d.ts.map +1 -1
  207. package/dist/core/PromptComposer.js +24 -10
  208. package/dist/core/PromptComposer.js.map +1 -1
  209. package/dist/core/ResponseGenerationError.d.ts +30 -0
  210. package/dist/core/ResponseGenerationError.d.ts.map +1 -0
  211. package/dist/core/ResponseGenerationError.js +33 -0
  212. package/dist/core/ResponseGenerationError.js.map +1 -0
  213. package/dist/core/ResponseModal.d.ts +43 -102
  214. package/dist/core/ResponseModal.d.ts.map +1 -1
  215. package/dist/core/ResponseModal.js +171 -1186
  216. package/dist/core/ResponseModal.js.map +1 -1
  217. package/dist/core/ResponsePipeline.d.ts +58 -152
  218. package/dist/core/ResponsePipeline.d.ts.map +1 -1
  219. package/dist/core/ResponsePipeline.js +409 -458
  220. package/dist/core/ResponsePipeline.js.map +1 -1
  221. package/dist/core/SessionFinalizer.d.ts +34 -0
  222. package/dist/core/SessionFinalizer.d.ts.map +1 -0
  223. package/dist/core/SessionFinalizer.js +57 -0
  224. package/dist/core/SessionFinalizer.js.map +1 -0
  225. package/dist/core/SessionManager.d.ts +1 -1
  226. package/dist/core/SessionManager.d.ts.map +1 -1
  227. package/dist/core/SessionManager.js +18 -7
  228. package/dist/core/SessionManager.js.map +1 -1
  229. package/dist/core/SignalCoordinator.d.ts +103 -0
  230. package/dist/core/SignalCoordinator.d.ts.map +1 -0
  231. package/dist/core/SignalCoordinator.js +203 -0
  232. package/dist/core/SignalCoordinator.js.map +1 -0
  233. package/dist/core/SignalEvaluator.d.ts +2 -2
  234. package/dist/core/SignalEvaluator.d.ts.map +1 -1
  235. package/dist/core/SignalEvaluator.js +11 -26
  236. package/dist/core/SignalEvaluator.js.map +1 -1
  237. package/dist/core/Step.d.ts +3 -1
  238. package/dist/core/Step.d.ts.map +1 -1
  239. package/dist/core/Step.js +10 -3
  240. package/dist/core/Step.js.map +1 -1
  241. package/dist/core/StepLifecycle.d.ts +33 -0
  242. package/dist/core/StepLifecycle.d.ts.map +1 -0
  243. package/dist/core/StepLifecycle.js +93 -0
  244. package/dist/core/StepLifecycle.js.map +1 -0
  245. package/dist/core/ToolLoopExecutor.d.ts +104 -0
  246. package/dist/core/ToolLoopExecutor.d.ts.map +1 -0
  247. package/dist/core/ToolLoopExecutor.js +387 -0
  248. package/dist/core/ToolLoopExecutor.js.map +1 -0
  249. package/dist/core/ToolManager.d.ts +1 -1
  250. package/dist/core/ToolManager.d.ts.map +1 -1
  251. package/dist/core/ToolManager.js.map +1 -1
  252. package/dist/index.d.ts +4 -5
  253. package/dist/index.d.ts.map +1 -1
  254. package/dist/index.js +3 -3
  255. package/dist/index.js.map +1 -1
  256. package/dist/providers/AnthropicProvider.d.ts +2 -0
  257. package/dist/providers/AnthropicProvider.d.ts.map +1 -1
  258. package/dist/providers/AnthropicProvider.js +22 -50
  259. package/dist/providers/AnthropicProvider.js.map +1 -1
  260. package/dist/providers/DeepSeekProvider.d.ts +25 -21
  261. package/dist/providers/DeepSeekProvider.d.ts.map +1 -1
  262. package/dist/providers/DeepSeekProvider.js +49 -408
  263. package/dist/providers/DeepSeekProvider.js.map +1 -1
  264. package/dist/providers/GeminiProvider.d.ts +2 -0
  265. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  266. package/dist/providers/GeminiProvider.js +21 -50
  267. package/dist/providers/GeminiProvider.js.map +1 -1
  268. package/dist/providers/OpenAICompatibleProvider.d.ts +129 -0
  269. package/dist/providers/OpenAICompatibleProvider.d.ts.map +1 -0
  270. package/dist/providers/OpenAICompatibleProvider.js +481 -0
  271. package/dist/providers/OpenAICompatibleProvider.js.map +1 -0
  272. package/dist/providers/OpenAIProvider.d.ts +9 -28
  273. package/dist/providers/OpenAIProvider.d.ts.map +1 -1
  274. package/dist/providers/OpenAIProvider.js +23 -417
  275. package/dist/providers/OpenAIProvider.js.map +1 -1
  276. package/dist/providers/OpenRouterProvider.d.ts +10 -27
  277. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  278. package/dist/providers/OpenRouterProvider.js +28 -417
  279. package/dist/providers/OpenRouterProvider.js.map +1 -1
  280. package/dist/providers/errorClassification.d.ts +61 -0
  281. package/dist/providers/errorClassification.d.ts.map +1 -0
  282. package/dist/providers/errorClassification.js +116 -0
  283. package/dist/providers/errorClassification.js.map +1 -0
  284. package/dist/providers/index.d.ts +4 -0
  285. package/dist/providers/index.d.ts.map +1 -1
  286. package/dist/providers/index.js +2 -0
  287. package/dist/providers/index.js.map +1 -1
  288. package/dist/types/agent.d.ts +2 -1
  289. package/dist/types/agent.d.ts.map +1 -1
  290. package/dist/types/ai.d.ts +20 -0
  291. package/dist/types/ai.d.ts.map +1 -1
  292. package/dist/types/errors.d.ts +33 -0
  293. package/dist/types/errors.d.ts.map +1 -1
  294. package/dist/types/errors.js +34 -0
  295. package/dist/types/errors.js.map +1 -1
  296. package/dist/types/flow.d.ts +10 -5
  297. package/dist/types/flow.d.ts.map +1 -1
  298. package/dist/types/history.d.ts +1 -1
  299. package/dist/types/history.d.ts.map +1 -1
  300. package/dist/types/index.d.ts +5 -4
  301. package/dist/types/index.d.ts.map +1 -1
  302. package/dist/types/index.js +1 -1
  303. package/dist/types/index.js.map +1 -1
  304. package/dist/types/persistence.d.ts +43 -2
  305. package/dist/types/persistence.d.ts.map +1 -1
  306. package/dist/types/session.d.ts +8 -0
  307. package/dist/types/session.d.ts.map +1 -1
  308. package/dist/types/signals.d.ts +12 -2
  309. package/dist/types/signals.d.ts.map +1 -1
  310. package/dist/types/template.d.ts +3 -1
  311. package/dist/types/template.d.ts.map +1 -1
  312. package/dist/types/tool.d.ts +4 -4
  313. package/dist/types/tool.d.ts.map +1 -1
  314. package/dist/utils/condition.d.ts +19 -0
  315. package/dist/utils/condition.d.ts.map +1 -1
  316. package/dist/utils/condition.js +84 -15
  317. package/dist/utils/condition.js.map +1 -1
  318. package/dist/utils/session.d.ts +1 -0
  319. package/dist/utils/session.d.ts.map +1 -1
  320. package/dist/utils/session.js +1 -0
  321. package/dist/utils/session.js.map +1 -1
  322. package/docs/README.md +1 -1
  323. package/docs/guides/branching.md +1 -1
  324. package/docs/guides/compaction.md +12 -5
  325. package/docs/guides/conditions.md +15 -2
  326. package/docs/guides/error-handling.md +59 -9
  327. package/docs/guides/instructions.md +2 -2
  328. package/docs/guides/persistence.md +69 -2
  329. package/docs/guides/streaming.md +2 -0
  330. package/docs/migration/README.md +5 -1
  331. package/docs/migration/v2-3-to-v2-4.md +316 -0
  332. package/docs/reference/adapters.md +55 -7
  333. package/docs/reference/branches.md +2 -2
  334. package/docs/reference/create-agent.md +3 -3
  335. package/docs/reference/errors.md +66 -1
  336. package/docs/reference/flow.md +1 -1
  337. package/docs/reference/instruction.md +4 -4
  338. package/docs/reference/providers.md +100 -3
  339. package/docs/reference/signals.md +11 -3
  340. package/docs/reference/step.md +2 -2
  341. package/docs/reference/tool.md +3 -1
  342. package/docs/start/05-go-to-production.md +3 -0
  343. package/package.json +1 -1
  344. package/src/adapters/MemoryAdapter.ts +15 -1
  345. package/src/adapters/MongoAdapter.ts +41 -2
  346. package/src/adapters/OpenSearchAdapter.ts +24 -1
  347. package/src/adapters/PostgreSQLAdapter.ts +45 -5
  348. package/src/adapters/PrismaAdapter.ts +82 -16
  349. package/src/adapters/RedisAdapter.ts +19 -1
  350. package/src/adapters/SQLiteAdapter.ts +47 -5
  351. package/src/core/Agent.ts +70 -85
  352. package/src/core/AutoChainExecutor.ts +27 -57
  353. package/src/core/BranchEvaluator.ts +24 -30
  354. package/src/core/Flow.ts +10 -3
  355. package/src/core/FlowRouter.ts +36 -4
  356. package/src/core/PersistenceManager.ts +79 -10
  357. package/src/core/PromptComposer.ts +25 -12
  358. package/src/core/ResponseGenerationError.ts +56 -0
  359. package/src/core/ResponseModal.ts +233 -1482
  360. package/src/core/ResponsePipeline.ts +492 -662
  361. package/src/core/SessionFinalizer.ts +78 -0
  362. package/src/core/SessionManager.ts +21 -9
  363. package/src/core/SignalCoordinator.ts +263 -0
  364. package/src/core/SignalEvaluator.ts +12 -29
  365. package/src/core/Step.ts +11 -3
  366. package/src/core/StepLifecycle.ts +139 -0
  367. package/src/core/ToolLoopExecutor.ts +492 -0
  368. package/src/core/ToolManager.ts +2 -1
  369. package/src/index.ts +7 -5
  370. package/src/providers/AnthropicProvider.ts +30 -72
  371. package/src/providers/DeepSeekProvider.ts +74 -586
  372. package/src/providers/GeminiProvider.ts +29 -70
  373. package/src/providers/OpenAICompatibleProvider.ts +738 -0
  374. package/src/providers/OpenAIProvider.ts +29 -602
  375. package/src/providers/OpenRouterProvider.ts +38 -596
  376. package/src/providers/errorClassification.ts +172 -0
  377. package/src/providers/index.ts +13 -0
  378. package/src/types/agent.ts +2 -1
  379. package/src/types/ai.ts +22 -0
  380. package/src/types/errors.ts +57 -0
  381. package/src/types/flow.ts +10 -5
  382. package/src/types/history.ts +1 -2
  383. package/src/types/index.ts +5 -1
  384. package/src/types/persistence.ts +50 -2
  385. package/src/types/session.ts +9 -0
  386. package/src/types/signals.ts +14 -2
  387. package/src/types/template.ts +3 -1
  388. package/src/types/tool.ts +10 -10
  389. package/src/utils/condition.ts +115 -18
  390. package/src/utils/session.ts +2 -0
@@ -0,0 +1,139 @@
1
+ /**
2
+ * StepLifecycle executes step `prepare` and `finalize` handlers.
3
+ *
4
+ * A handler may be a function, a registered tool id, or an inline tool.
5
+ * Used by the response prepare phase (prepare) and by SessionFinalizer
6
+ * (finalize).
7
+ */
8
+
9
+ import type { PrepareResult, SessionState, Tool } from "../types";
10
+ import type { Flow } from "./Flow";
11
+ import type { Step } from "./Step";
12
+ import type { ToolManager } from "./ToolManager";
13
+ import { logger } from "../utils";
14
+
15
+ export class StepLifecycle<TContext = unknown, TData = unknown> {
16
+ constructor(
17
+ private readonly deps: {
18
+ getFlows: () => Flow<TContext, TData>[];
19
+ toolManager: ToolManager<TContext, TData>;
20
+ updateContext: (updates: Partial<TContext>) => Promise<void>;
21
+ updateData: (updates: Partial<TData>) => Promise<void>;
22
+ }
23
+ ) { }
24
+
25
+ /**
26
+ * Execute prepare function for the session's current step if available.
27
+ * Auto-steps are skipped — their prepare is handled by AutoChainExecutor.
28
+ */
29
+ async runPrepare(session: SessionState<TData>, context: TContext): Promise<void> {
30
+ if (session.currentFlow && session.currentStep) {
31
+ const currentFlow = this.deps.getFlows().find(
32
+ (r) => r.id === session.currentFlow?.id
33
+ );
34
+ if (currentFlow) {
35
+ const currentStep = currentFlow.getStep(session.currentStep.id);
36
+ // Skip auto-steps — their prepare is handled by AutoChainExecutor
37
+ if (currentStep?.auto) {
38
+ logger.debug(`[StepLifecycle] Skipping pre-routing prepare for auto-step: ${currentStep.id}`);
39
+ return;
40
+ }
41
+ if (currentStep?.prepare) {
42
+ logger.debug(`[StepLifecycle] Executing prepare for step: ${currentStep.id}`);
43
+ await this.executePrepareFinalize(
44
+ currentStep.prepare,
45
+ context,
46
+ session.data,
47
+ currentFlow,
48
+ currentStep
49
+ );
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Execute finalize function for the session's current step if available.
57
+ */
58
+ async runFinalize(session: SessionState<TData>, context: TContext): Promise<void> {
59
+ if (session.currentFlow && session.currentStep) {
60
+ const currentFlow = this.deps.getFlows().find(
61
+ (r) => r.id === session.currentFlow?.id
62
+ );
63
+ if (currentFlow) {
64
+ const currentStep = currentFlow.getStep(session.currentStep.id);
65
+ if (currentStep?.finalize) {
66
+ logger.debug(
67
+ `[StepLifecycle] Executing finalize for step: ${currentStep.id}`
68
+ );
69
+ await this.executePrepareFinalize(
70
+ currentStep.finalize,
71
+ context,
72
+ session.data,
73
+ currentFlow,
74
+ currentStep
75
+ );
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Execute a prepare or finalize function/tool.
83
+ */
84
+ private async executePrepareFinalize(
85
+ prepareOrFinalize:
86
+ | string
87
+ | Tool<TContext, TData>
88
+ | ((context: TContext, data?: Partial<TData>) => void | PrepareResult | Promise<void | PrepareResult>)
89
+ | undefined,
90
+ context: TContext,
91
+ data?: Partial<TData>,
92
+ flow?: Flow<TContext, TData>,
93
+ step?: Step<TContext, TData>
94
+ ): Promise<void> {
95
+ if (!prepareOrFinalize) return;
96
+
97
+ if (typeof prepareOrFinalize === "function") {
98
+ // It's a function - call it directly
99
+ await prepareOrFinalize(context, data);
100
+ } else {
101
+ // It's a tool reference - find and execute the tool
102
+ let tool: Tool<TContext, TData> | undefined;
103
+
104
+ if (typeof prepareOrFinalize === "string") {
105
+ // Tool ID - use ToolManager for unified resolution
106
+ tool = this.deps.toolManager.find(prepareOrFinalize, undefined, step, flow);
107
+ } else {
108
+ // Tool object - use directly
109
+ tool = prepareOrFinalize;
110
+ }
111
+
112
+ if (tool) {
113
+ // Use ToolManager for unified tool execution
114
+ const result = await this.deps.toolManager.executeTool({
115
+ tool,
116
+ context,
117
+ updateContext: this.deps.updateContext,
118
+ updateData: this.deps.updateData,
119
+ history: [], // Empty history for prepare/finalize
120
+ data,
121
+ });
122
+
123
+ if (!result.success) {
124
+ logger.error(
125
+ `[StepLifecycle] Tool execution failed in prepare/finalize: ${result.error}`
126
+ );
127
+ throw new Error(`Tool execution failed: ${result.error}`);
128
+ }
129
+ } else {
130
+ logger.warn(
131
+ `[StepLifecycle] Tool not found for prepare/finalize: ${typeof prepareOrFinalize === "string"
132
+ ? prepareOrFinalize
133
+ : "inline tool"
134
+ }`
135
+ );
136
+ }
137
+ }
138
+ }
139
+ }
@@ -0,0 +1,492 @@
1
+ /**
2
+ * ToolLoopExecutor owns dynamic tool execution during response generation:
3
+ *
4
+ * - `runLoop()` — the run-tools-then-ask-LLM-again follow-up loop used by the
5
+ * non-streaming path (and as the streaming fallback): executes the initial
6
+ * tool calls sequentially, asks the provider whether more tools are needed,
7
+ * reconstructs tool-result history items, and forces a final text response
8
+ * when tools ran but no message was produced.
9
+ * - `runStreamingBatch()` — the streaming path's initial batch execution via
10
+ * ToolManager.executeWithConcurrency (StreamingToolExecutor concurrency
11
+ * rules), yielding tool-progress chunks; falls back to `runLoop()` when
12
+ * concurrent execution fails.
13
+ *
14
+ * ToolManager remains the registry/resolver and single-tool executor.
15
+ */
16
+
17
+ import type {
18
+ AgentOptions,
19
+ AgentResponseStreamChunk,
20
+ AgentStructuredResponse,
21
+ HistoryItem,
22
+ SessionState,
23
+ ToolCallRequest,
24
+ } from "../types";
25
+ import type { Flow } from "./Flow";
26
+ import type { Step } from "./Step";
27
+ import type { ToolManager } from "./ToolManager";
28
+ import { ResponseGenerationError } from "./ResponseGenerationError";
29
+ import { historyToEvents, logger, serializeToolResult } from "../utils";
30
+
31
+ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
32
+ constructor(
33
+ private readonly deps: {
34
+ toolManager: ToolManager<TContext, TData>;
35
+ getAgentOptions: () => AgentOptions<TContext, TData>;
36
+ updateContext: (updates: Partial<TContext>) => Promise<void>;
37
+ updateCollectedData: (updates: Partial<TData>) => Promise<void>;
38
+ updateSessionData: (
39
+ session: SessionState<TData>,
40
+ dataUpdate: Partial<TData>
41
+ ) => Promise<SessionState<TData>>;
42
+ /** Maximum number of tool loops (defaults to 5). */
43
+ maxToolLoops?: number;
44
+ }
45
+ ) { }
46
+
47
+ /**
48
+ * Unified tool execution logic with loop handling.
49
+ * Consolidates the complex tool execution logic from both streaming and
50
+ * non-streaming responses.
51
+ */
52
+ async runLoop(params: {
53
+ toolCalls?: Array<{ toolName: string; arguments: Record<string, unknown> }>;
54
+ context: TContext;
55
+ session: SessionState<TData>;
56
+ history: HistoryItem[];
57
+ selectedFlow?: Flow<TContext, TData>;
58
+ responsePrompt: string;
59
+ availableTools: Array<{
60
+ id: string;
61
+ name: string;
62
+ description?: string;
63
+ parameters?: unknown;
64
+ }>;
65
+ responseSchema?: Record<string, unknown>;
66
+ signal?: AbortSignal;
67
+ }): Promise<{
68
+ session: SessionState<TData>;
69
+ finalToolCalls?: Array<{ toolName: string; arguments: Record<string, unknown> }>;
70
+ finalMessage?: string;
71
+ structured?: AgentStructuredResponse;
72
+ }> {
73
+ try {
74
+ const { context, history, selectedFlow, responsePrompt, availableTools, responseSchema, signal } = params;
75
+ let { toolCalls, session } = params;
76
+
77
+ // Convert HistoryItem[] to Event[] for internal processing
78
+ const historyEvents = historyToEvents(history);
79
+
80
+ // Map to store tool execution results for history
81
+ const toolResultsMap = new Map<string, string>();
82
+ // Map to store tool call arguments for history reconstruction
83
+ const toolArgsMap = new Map<string, Record<string, unknown>>();
84
+
85
+ // Execute initial dynamic tool calls
86
+ if (toolCalls && toolCalls.length > 0) {
87
+ logger.debug(`[ToolLoopExecutor] Executing ${toolCalls.length} dynamic tool calls:`, toolCalls.map(tc => tc.toolName));
88
+
89
+ for (const toolCall of toolCalls) {
90
+ const tool = this.findAvailableTool(toolCall.toolName, selectedFlow);
91
+ if (!tool) {
92
+ logger.warn(`[ToolExecutionError] Tool not found: "${toolCall.toolName}" is not registered in any scope. Skipping this tool call. Register the tool or check the tool name.`);
93
+ continue;
94
+ }
95
+
96
+ try {
97
+ // Use ToolManager for unified tool execution
98
+ const toolResult = await this.deps.toolManager.executeTool({
99
+ tool,
100
+ context,
101
+ updateContext: this.deps.updateContext,
102
+ updateData: this.deps.updateCollectedData,
103
+ history: historyEvents, // Use Event[] for tool execution
104
+ data: session.data,
105
+ toolArguments: toolCall.arguments,
106
+ });
107
+
108
+ // Store the actual tool result data for history
109
+ toolResultsMap.set(toolCall.toolName, serializeToolResult(toolResult));
110
+ toolArgsMap.set(toolCall.toolName, toolCall.arguments);
111
+
112
+ // Check if tool execution was successful
113
+ if (!toolResult.success) {
114
+ logger.error(`[ToolLoopExecutor] Tool execution failed: ${toolCall.toolName} - ${toolResult.error}`);
115
+ // Continue with other tools rather than failing completely
116
+ continue;
117
+ }
118
+
119
+ // Update context with tool results
120
+ if (toolResult.contextUpdate) {
121
+ try {
122
+ await this.deps.updateContext(toolResult.contextUpdate as Partial<TContext>);
123
+ } catch (error) {
124
+ logger.error(`[ToolLoopExecutor] Failed to update context from tool ${toolCall.toolName}:`, error);
125
+ // Continue execution but log the error
126
+ }
127
+ }
128
+
129
+ // Update collected data with tool results
130
+ if (toolResult.dataUpdate) {
131
+ try {
132
+ session = await this.deps.updateSessionData(session, toolResult.dataUpdate as Partial<TData>);
133
+ logger.debug(`[ToolLoopExecutor] Tool updated collected data:`, toolResult.dataUpdate);
134
+ } catch (error) {
135
+ logger.error(`[ToolLoopExecutor] Failed to update data from tool ${toolCall.toolName}:`, error);
136
+ // Continue execution but log the error
137
+ }
138
+ }
139
+
140
+ logger.debug(`[ToolLoopExecutor] Executed dynamic tool: ${toolCall.toolName} (success: ${toolResult.success})`);
141
+ } catch (error) {
142
+ logger.error(`[ToolLoopExecutor] Tool execution error for ${toolCall.toolName}:`, error);
143
+ // Continue with other tools rather than failing the entire response
144
+ continue;
145
+ }
146
+ }
147
+ }
148
+
149
+ // TOOL LOOP: Allow AI to make follow-up tool calls after initial tool execution
150
+ const MAX_TOOL_LOOPS = this.deps.maxToolLoops || 5;
151
+ let toolLoopCount = 0;
152
+ let hasToolCalls = toolCalls && toolCalls.length > 0;
153
+ let finalMessage: string | undefined;
154
+ let followUpStructured: AgentStructuredResponse | undefined;
155
+
156
+ while (hasToolCalls && toolLoopCount < MAX_TOOL_LOOPS) {
157
+ toolLoopCount++;
158
+ logger.debug(`[ToolLoopExecutor] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS} with ${toolCalls?.length || 0} tool calls`);
159
+
160
+ // Create tool result history items
161
+ const toolResultHistoryItems: HistoryItem[] = [];
162
+ for (const toolCall of toolCalls || []) {
163
+ const tool = this.findAvailableTool(toolCall.toolName, selectedFlow);
164
+ if (tool) {
165
+ // Create HistoryItem format for tool results
166
+ // Add assistant message with tool_calls
167
+ toolResultHistoryItems.push({
168
+ role: "assistant" as const,
169
+ content: null,
170
+ tool_calls: [{
171
+ id: toolCall.toolName,
172
+ name: toolCall.toolName,
173
+ arguments: toolCall.arguments,
174
+ }],
175
+ });
176
+ // Add tool result
177
+ toolResultHistoryItems.push({
178
+ role: "tool" as const,
179
+ tool_call_id: toolCall.toolName,
180
+ name: toolCall.toolName,
181
+ content: toolResultsMap.get(toolCall.toolName) || "Tool executed successfully",
182
+ });
183
+ }
184
+ }
185
+
186
+ // Create updated history with tool results
187
+ const updatedHistory = [...history, ...toolResultHistoryItems];
188
+
189
+ // Make follow-up AI call to see if more tools are needed
190
+ // After first iteration, don't provide tools to force a text response
191
+ const agentOptions = this.deps.getAgentOptions();
192
+ const shouldProvideTools = toolLoopCount === 1;
193
+
194
+ logger.debug(`[ToolLoopExecutor] Making follow-up AI call (loop ${toolLoopCount}):`, {
195
+ providingTools: shouldProvideTools,
196
+ toolsCount: shouldProvideTools ? availableTools.length : 0,
197
+ addingTextInstruction: toolLoopCount > 1,
198
+ });
199
+
200
+ const followUpResult = await agentOptions.provider.generateMessage({
201
+ prompt: responsePrompt + (toolLoopCount > 1 ? "\n\nProvide a text response to the user based on the tool results." : ""),
202
+ history: updatedHistory, // Use HistoryItem[] for AI provider
203
+ context,
204
+ tools: shouldProvideTools ? availableTools : [], // Only provide tools on first iteration
205
+ parameters: responseSchema ? {
206
+ jsonSchema: responseSchema,
207
+ schemaName: "tool_followup",
208
+ } : undefined,
209
+ signal,
210
+ });
211
+
212
+ // Check if follow-up call has more tool calls
213
+ const followUpToolCalls = followUpResult.structured?.toolCalls;
214
+ hasToolCalls = followUpToolCalls && followUpToolCalls.length > 0;
215
+
216
+ logger.debug(`[ToolLoopExecutor] Follow-up AI response (loop ${toolLoopCount}):`, {
217
+ hasMessage: !!followUpResult.message,
218
+ messageLength: followUpResult.message?.length || 0,
219
+ hasToolCalls,
220
+ toolCallsCount: followUpToolCalls?.length || 0,
221
+ toolNames: followUpToolCalls?.map(tc => tc.toolName) || [],
222
+ });
223
+
224
+ if (hasToolCalls) {
225
+ logger.debug(`[ToolLoopExecutor] Follow-up call produced ${followUpToolCalls!.length} additional tool calls`);
226
+
227
+ // Execute the follow-up tool calls
228
+ for (const toolCall of followUpToolCalls!) {
229
+ const tool = this.findAvailableTool(toolCall.toolName, selectedFlow);
230
+ if (!tool) {
231
+ logger.warn(`[ToolExecutionError] Tool not found in follow-up: "${toolCall.toolName}" is not registered in any scope. Skipping this tool call. Register the tool or check the tool name.`);
232
+ continue;
233
+ }
234
+
235
+ try {
236
+ // Use ToolManager for unified tool execution
237
+ const toolResult = await this.deps.toolManager.executeTool({
238
+ tool,
239
+ context,
240
+ updateContext: this.deps.updateContext,
241
+ updateData: this.deps.updateCollectedData,
242
+ history: historyToEvents(updatedHistory), // Convert to Event[] for tool execution
243
+ data: session.data,
244
+ toolArguments: toolCall.arguments,
245
+ });
246
+
247
+ // Check if tool execution was successful
248
+ if (!toolResult.success) {
249
+ logger.error(`[ToolLoopExecutor] Follow-up tool execution failed: ${toolCall.toolName} - ${toolResult.error}`);
250
+ continue;
251
+ }
252
+
253
+ // Update context with follow-up tool results
254
+ if (toolResult.contextUpdate) {
255
+ try {
256
+ await this.deps.updateContext(toolResult.contextUpdate as Partial<TContext>);
257
+ } catch (error) {
258
+ logger.error(`[ToolLoopExecutor] Failed to update context from follow-up tool ${toolCall.toolName}:`, error);
259
+ }
260
+ }
261
+
262
+ if (toolResult.dataUpdate) {
263
+ try {
264
+ session = await this.deps.updateSessionData(session, toolResult.dataUpdate as Partial<TData>);
265
+ logger.debug(`[ToolLoopExecutor] Follow-up tool updated collected data:`, toolResult.dataUpdate);
266
+ } catch (error) {
267
+ logger.error(`[ToolLoopExecutor] Failed to update data from follow-up tool ${toolCall.toolName}:`, error);
268
+ }
269
+ }
270
+
271
+ // Store the follow-up tool result for potential next loop iteration
272
+ toolResultsMap.set(toolCall.toolName, serializeToolResult(toolResult));
273
+ toolArgsMap.set(toolCall.toolName, toolCall.arguments);
274
+
275
+ logger.debug(`[ToolLoopExecutor] Executed follow-up tool: ${toolCall.toolName} (success: ${toolResult.success})`);
276
+ } catch (error) {
277
+ logger.error(`[ToolLoopExecutor] Follow-up tool execution error for ${toolCall.toolName}:`, error);
278
+ continue;
279
+ }
280
+ }
281
+
282
+ // Update toolCalls for next iteration or final response
283
+ toolCalls = followUpToolCalls;
284
+ } else {
285
+ logger.debug(`[ToolLoopExecutor] Tool loop completed after ${toolLoopCount} iterations`);
286
+ // Update final message and toolCalls from follow-up result if no more tools
287
+ finalMessage = followUpResult.structured?.message || followUpResult.message;
288
+ followUpStructured = followUpResult.structured;
289
+ toolCalls = followUpToolCalls || [];
290
+ break;
291
+ }
292
+ }
293
+
294
+ if (toolLoopCount >= MAX_TOOL_LOOPS) {
295
+ logger.warn(`[ResponseGenerationError] Tool loop limit reached: ${toolLoopCount} iterations hit the cap (${MAX_TOOL_LOOPS}). Stopping tool execution. Increase MAX_TOOL_LOOPS or reduce recursive tool calls.`);
296
+ }
297
+
298
+ // If tools were executed but no final text message was produced,
299
+ // make one more LLM call to generate a proper text response from tool results.
300
+ // This prevents the original tool-invocation message (e.g. "Let me check...")
301
+ // from being returned as the final user-facing response.
302
+ if (!finalMessage && toolLoopCount > 0) {
303
+ logger.debug(`[ToolLoopExecutor] No final message after tool loop, making additional LLM call for text response`);
304
+
305
+ // Build tool result history from toolResultsMap which contains ALL
306
+ // tool executions (initial + follow-up). We can't use `toolCalls` here
307
+ // because it was reassigned to the (empty) follow-up tool calls when
308
+ // the while loop broke out.
309
+ const finalToolResultHistoryItems: HistoryItem[] = [];
310
+ for (const [toolName, toolResult] of toolResultsMap) {
311
+ finalToolResultHistoryItems.push({
312
+ role: "assistant" as const,
313
+ content: null,
314
+ tool_calls: [{
315
+ id: toolName,
316
+ name: toolName,
317
+ arguments: toolArgsMap.get(toolName) || {},
318
+ }],
319
+ });
320
+ finalToolResultHistoryItems.push({
321
+ role: "tool" as const,
322
+ tool_call_id: toolName,
323
+ name: toolName,
324
+ content: toolResult,
325
+ });
326
+ }
327
+
328
+ const finalHistory = [...history, ...finalToolResultHistoryItems];
329
+ const agentOptions = this.deps.getAgentOptions();
330
+
331
+ try {
332
+ const textResult = await agentOptions.provider.generateMessage({
333
+ prompt: responsePrompt + "\n\nProvide a text response to the user based on the tool results. Do not call any tools.",
334
+ history: finalHistory,
335
+ context,
336
+ tools: [], // No tools - force text response
337
+ parameters: responseSchema ? {
338
+ jsonSchema: responseSchema,
339
+ schemaName: "tool_final_text",
340
+ } : undefined,
341
+ signal,
342
+ });
343
+
344
+ finalMessage = textResult.structured?.message || textResult.message;
345
+ if (textResult.structured) {
346
+ followUpStructured = textResult.structured;
347
+ }
348
+
349
+ logger.debug(`[ToolLoopExecutor] Generated final text response after tool loop:`, {
350
+ hasMessage: !!finalMessage,
351
+ messageLength: finalMessage?.length || 0,
352
+ });
353
+ } catch (error) {
354
+ logger.error(`[ToolLoopExecutor] Failed to generate final text response after tool loop:`, error);
355
+ // finalMessage remains undefined; caller will use original message as fallback
356
+ }
357
+ }
358
+
359
+ logger.debug(`[ToolLoopExecutor] Tool loop completed:`, {
360
+ totalIterations: toolLoopCount,
361
+ hasFinalMessage: !!finalMessage,
362
+ finalMessageLength: finalMessage?.length || 0,
363
+ finalToolCallsCount: toolCalls?.length || 0,
364
+ });
365
+
366
+ return {
367
+ session,
368
+ finalToolCalls: toolCalls,
369
+ finalMessage,
370
+ structured: followUpStructured,
371
+ };
372
+ } catch (error) {
373
+ throw ResponseGenerationError.fromError(error, 'tool_execution', params, {
374
+ toolCallsCount: params.toolCalls?.length || 0,
375
+ availableToolsCount: params.availableTools.length
376
+ });
377
+ }
378
+ }
379
+
380
+ /**
381
+ * Execute the streaming path's initial batch of tool calls concurrently
382
+ * via ToolManager.executeWithConcurrency, yielding tool-progress chunks.
383
+ * Falls back to `runLoop()` when concurrent execution fails.
384
+ *
385
+ * Returns the updated session and the final tool calls.
386
+ */
387
+ async *runStreamingBatch(params: {
388
+ toolCalls: Array<{ toolName: string; arguments: Record<string, unknown> }>;
389
+ context: TContext;
390
+ session: SessionState<TData>;
391
+ history: HistoryItem[];
392
+ selectedFlow: Flow<TContext, TData>;
393
+ step: Step<TContext, TData>;
394
+ /** Accumulated text of the LLM's final chunk, echoed on progress chunks. */
395
+ accumulated: string;
396
+ responsePrompt: string;
397
+ availableTools: Array<{
398
+ id: string;
399
+ name: string;
400
+ description?: string;
401
+ parameters?: unknown;
402
+ }>;
403
+ responseSchema?: Record<string, unknown>;
404
+ signal?: AbortSignal;
405
+ }): AsyncGenerator<
406
+ AgentResponseStreamChunk<TData>,
407
+ {
408
+ session: SessionState<TData>;
409
+ toolCalls: Array<{ toolName: string; arguments: Record<string, unknown> }> | undefined;
410
+ }
411
+ > {
412
+ const { context, history, selectedFlow, step, accumulated, responsePrompt, availableTools, responseSchema, signal } = params;
413
+ let { session } = params;
414
+ let toolCalls: Array<{ toolName: string; arguments: Record<string, unknown> }> | undefined = params.toolCalls;
415
+
416
+ // Use concurrent execution for the initial batch of tool calls
417
+ const toolCallRequests: ToolCallRequest[] = params.toolCalls.map((tc, i) => ({
418
+ id: `${tc.toolName}-${i}-${Date.now()}`,
419
+ toolName: tc.toolName,
420
+ arguments: tc.arguments,
421
+ }));
422
+
423
+ const historyEvents = historyToEvents(history);
424
+
425
+ try {
426
+ for await (const update of this.deps.toolManager.executeWithConcurrency({
427
+ toolCalls: toolCallRequests,
428
+ context,
429
+ data: session.data,
430
+ history: historyEvents,
431
+ signal,
432
+ flow: selectedFlow,
433
+ step,
434
+ })) {
435
+ // Apply context updates
436
+ if (update.contextUpdate) {
437
+ try {
438
+ await this.deps.updateContext(update.contextUpdate as Partial<TContext>);
439
+ } catch (error) {
440
+ logger.error(`[ToolLoopExecutor] Failed to update context from concurrent tool:`, error);
441
+ }
442
+ }
443
+
444
+ // Apply data updates
445
+ if (update.dataUpdate) {
446
+ try {
447
+ session = await this.deps.updateSessionData(session, update.dataUpdate);
448
+ } catch (error) {
449
+ logger.error(`[ToolLoopExecutor] Failed to update data from concurrent tool:`, error);
450
+ }
451
+ }
452
+
453
+ // Yield progress updates immediately
454
+ if (update.progress) {
455
+ yield {
456
+ delta: '',
457
+ accumulated,
458
+ done: false,
459
+ session,
460
+ toolCalls: undefined,
461
+ isFlowComplete: false,
462
+ metadata: { toolProgress: update.progress, toolCallId: update.toolCallId },
463
+ };
464
+ }
465
+ }
466
+
467
+ logger.debug(`[ToolLoopExecutor] Concurrent tool execution completed for ${toolCallRequests.length} tools`);
468
+ } catch (error) {
469
+ logger.error(`[ToolLoopExecutor] Concurrent tool execution failed, falling back to sequential:`, error);
470
+ // Fall back to the unified tool loop on failure
471
+ const toolResult = await this.runLoop({
472
+ toolCalls, context, session, history, selectedFlow,
473
+ responsePrompt, availableTools, responseSchema, signal,
474
+ });
475
+ session = toolResult.session;
476
+ toolCalls = toolResult.finalToolCalls;
477
+ }
478
+
479
+ return { session, toolCalls };
480
+ }
481
+
482
+ /**
483
+ * Find an available tool by name for the given flow.
484
+ * Delegates to ToolManager for unified tool resolution.
485
+ */
486
+ private findAvailableTool(
487
+ toolName: string,
488
+ flow?: Flow<TContext, TData>
489
+ ) {
490
+ return this.deps.toolManager.find(toolName, undefined, undefined, flow);
491
+ }
492
+ }
@@ -19,7 +19,8 @@ import type {
19
19
  import type { Directive } from "../types/flow";
20
20
  import { ToolScope } from "../types";
21
21
  import { logger } from "../utils";
22
- import { Agent } from "./Agent";
22
+ // Type-only import: ToolManager must not create a runtime cycle with Agent
23
+ import type { Agent } from "./Agent";
23
24
  import { Flow } from "./Flow";
24
25
  import { Step } from "./Step";
25
26
  import { StreamingToolExecutor } from "./StreamingToolExecutor";