@falai/agent 2.6.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (611) hide show
  1. package/README.md +2 -2
  2. package/dist/adapters/MemoryAdapter.d.ts +1 -1
  3. package/dist/adapters/MemoryAdapter.d.ts.map +1 -1
  4. package/dist/adapters/MemoryAdapter.js +32 -36
  5. package/dist/adapters/MemoryAdapter.js.map +1 -1
  6. package/dist/adapters/MongoAdapter.d.ts +1 -1
  7. package/dist/adapters/MongoAdapter.d.ts.map +1 -1
  8. package/dist/adapters/MongoAdapter.js +2 -2
  9. package/dist/adapters/MongoAdapter.js.map +1 -1
  10. package/dist/adapters/OpenSearchAdapter.d.ts +1 -1
  11. package/dist/adapters/OpenSearchAdapter.d.ts.map +1 -1
  12. package/dist/adapters/OpenSearchAdapter.js +3 -3
  13. package/dist/adapters/OpenSearchAdapter.js.map +1 -1
  14. package/dist/adapters/PostgreSQLAdapter.d.ts +1 -1
  15. package/dist/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  16. package/dist/adapters/PostgreSQLAdapter.js +18 -13
  17. package/dist/adapters/PostgreSQLAdapter.js.map +1 -1
  18. package/dist/adapters/PrismaAdapter.d.ts +1 -1
  19. package/dist/adapters/PrismaAdapter.d.ts.map +1 -1
  20. package/dist/adapters/PrismaAdapter.js +3 -3
  21. package/dist/adapters/PrismaAdapter.js.map +1 -1
  22. package/dist/adapters/RedisAdapter.d.ts +2 -1
  23. package/dist/adapters/RedisAdapter.d.ts.map +1 -1
  24. package/dist/adapters/RedisAdapter.js +77 -27
  25. package/dist/adapters/RedisAdapter.js.map +1 -1
  26. package/dist/adapters/SQLiteAdapter.d.ts +1 -1
  27. package/dist/adapters/SQLiteAdapter.d.ts.map +1 -1
  28. package/dist/adapters/SQLiteAdapter.js +9 -31
  29. package/dist/adapters/SQLiteAdapter.js.map +1 -1
  30. package/dist/adapters/index.d.ts +13 -13
  31. package/dist/adapters/index.d.ts.map +1 -1
  32. package/dist/adapters/index.js +7 -7
  33. package/dist/adapters/index.js.map +1 -1
  34. package/dist/adapters/sessionRow.d.ts +22 -0
  35. package/dist/adapters/sessionRow.d.ts.map +1 -0
  36. package/dist/adapters/sessionRow.js +48 -0
  37. package/dist/adapters/sessionRow.js.map +1 -0
  38. package/dist/cjs/adapters/MemoryAdapter.d.ts +1 -1
  39. package/dist/cjs/adapters/MemoryAdapter.d.ts.map +1 -1
  40. package/dist/cjs/adapters/MemoryAdapter.js +39 -43
  41. package/dist/cjs/adapters/MemoryAdapter.js.map +1 -1
  42. package/dist/cjs/adapters/MongoAdapter.d.ts +1 -1
  43. package/dist/cjs/adapters/MongoAdapter.d.ts.map +1 -1
  44. package/dist/cjs/adapters/MongoAdapter.js +4 -4
  45. package/dist/cjs/adapters/MongoAdapter.js.map +1 -1
  46. package/dist/cjs/adapters/OpenSearchAdapter.d.ts +1 -1
  47. package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +1 -1
  48. package/dist/cjs/adapters/OpenSearchAdapter.js +6 -6
  49. package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -1
  50. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts +1 -1
  51. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  52. package/dist/cjs/adapters/PostgreSQLAdapter.js +20 -15
  53. package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -1
  54. package/dist/cjs/adapters/PrismaAdapter.d.ts +1 -1
  55. package/dist/cjs/adapters/PrismaAdapter.d.ts.map +1 -1
  56. package/dist/cjs/adapters/PrismaAdapter.js +7 -7
  57. package/dist/cjs/adapters/PrismaAdapter.js.map +1 -1
  58. package/dist/cjs/adapters/RedisAdapter.d.ts +2 -1
  59. package/dist/cjs/adapters/RedisAdapter.d.ts.map +1 -1
  60. package/dist/cjs/adapters/RedisAdapter.js +81 -31
  61. package/dist/cjs/adapters/RedisAdapter.js.map +1 -1
  62. package/dist/cjs/adapters/SQLiteAdapter.d.ts +1 -1
  63. package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +1 -1
  64. package/dist/cjs/adapters/SQLiteAdapter.js +11 -33
  65. package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -1
  66. package/dist/cjs/adapters/index.d.ts +13 -13
  67. package/dist/cjs/adapters/index.d.ts.map +1 -1
  68. package/dist/cjs/adapters/index.js +14 -14
  69. package/dist/cjs/adapters/index.js.map +1 -1
  70. package/dist/cjs/adapters/sessionRow.d.ts +22 -0
  71. package/dist/cjs/adapters/sessionRow.d.ts.map +1 -0
  72. package/dist/cjs/adapters/sessionRow.js +52 -0
  73. package/dist/cjs/adapters/sessionRow.js.map +1 -0
  74. package/dist/cjs/core/Agent.d.ts +19 -11
  75. package/dist/cjs/core/Agent.d.ts.map +1 -1
  76. package/dist/cjs/core/Agent.js +102 -64
  77. package/dist/cjs/core/Agent.js.map +1 -1
  78. package/dist/cjs/core/AutoChainExecutor.d.ts +12 -22
  79. package/dist/cjs/core/AutoChainExecutor.d.ts.map +1 -1
  80. package/dist/cjs/core/AutoChainExecutor.js +46 -49
  81. package/dist/cjs/core/AutoChainExecutor.js.map +1 -1
  82. package/dist/cjs/core/BranchEvaluator.d.ts +4 -4
  83. package/dist/cjs/core/BranchEvaluator.d.ts.map +1 -1
  84. package/dist/cjs/core/BranchEvaluator.js +6 -6
  85. package/dist/cjs/core/BranchEvaluator.js.map +1 -1
  86. package/dist/cjs/core/CompactionEngine.d.ts +16 -3
  87. package/dist/cjs/core/CompactionEngine.d.ts.map +1 -1
  88. package/dist/cjs/core/CompactionEngine.js +30 -6
  89. package/dist/cjs/core/CompactionEngine.js.map +1 -1
  90. package/dist/cjs/core/DirectiveChainTracker.d.ts +1 -1
  91. package/dist/cjs/core/DirectiveChainTracker.d.ts.map +1 -1
  92. package/dist/cjs/core/DirectiveChainTracker.js +5 -5
  93. package/dist/cjs/core/DirectiveChainTracker.js.map +1 -1
  94. package/dist/cjs/core/Events.d.ts +1 -1
  95. package/dist/cjs/core/Events.d.ts.map +1 -1
  96. package/dist/cjs/core/Events.js +15 -15
  97. package/dist/cjs/core/Events.js.map +1 -1
  98. package/dist/cjs/core/Flow.d.ts +4 -4
  99. package/dist/cjs/core/Flow.d.ts.map +1 -1
  100. package/dist/cjs/core/Flow.js +15 -15
  101. package/dist/cjs/core/Flow.js.map +1 -1
  102. package/dist/cjs/core/FlowRouter.d.ts +4 -4
  103. package/dist/cjs/core/FlowRouter.d.ts.map +1 -1
  104. package/dist/cjs/core/FlowRouter.js +92 -70
  105. package/dist/cjs/core/FlowRouter.js.map +1 -1
  106. package/dist/cjs/core/PersistenceManager.d.ts +1 -1
  107. package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
  108. package/dist/cjs/core/PersistenceManager.js +10 -10
  109. package/dist/cjs/core/PersistenceManager.js.map +1 -1
  110. package/dist/cjs/core/PromptComposer.d.ts +4 -4
  111. package/dist/cjs/core/PromptComposer.d.ts.map +1 -1
  112. package/dist/cjs/core/PromptComposer.js +13 -13
  113. package/dist/cjs/core/PromptComposer.js.map +1 -1
  114. package/dist/cjs/core/PromptSectionCache.d.ts +2 -2
  115. package/dist/cjs/core/PromptSectionCache.d.ts.map +1 -1
  116. package/dist/cjs/core/ResponseEngine.d.ts +4 -4
  117. package/dist/cjs/core/ResponseEngine.d.ts.map +1 -1
  118. package/dist/cjs/core/ResponseEngine.js +7 -7
  119. package/dist/cjs/core/ResponseEngine.js.map +1 -1
  120. package/dist/cjs/core/ResponseGenerationError.d.ts.map +1 -1
  121. package/dist/cjs/core/ResponseGenerationError.js +3 -5
  122. package/dist/cjs/core/ResponseGenerationError.js.map +1 -1
  123. package/dist/cjs/core/ResponseModal.d.ts +39 -10
  124. package/dist/cjs/core/ResponseModal.d.ts.map +1 -1
  125. package/dist/cjs/core/ResponseModal.js +195 -72
  126. package/dist/cjs/core/ResponseModal.js.map +1 -1
  127. package/dist/cjs/core/ResponsePipeline.d.ts +50 -12
  128. package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -1
  129. package/dist/cjs/core/ResponsePipeline.js +301 -158
  130. package/dist/cjs/core/ResponsePipeline.js.map +1 -1
  131. package/dist/cjs/core/SessionFinalizer.d.ts +4 -4
  132. package/dist/cjs/core/SessionFinalizer.d.ts.map +1 -1
  133. package/dist/cjs/core/SessionFinalizer.js +36 -9
  134. package/dist/cjs/core/SessionFinalizer.js.map +1 -1
  135. package/dist/cjs/core/SessionManager.d.ts +15 -6
  136. package/dist/cjs/core/SessionManager.d.ts.map +1 -1
  137. package/dist/cjs/core/SessionManager.js +49 -22
  138. package/dist/cjs/core/SessionManager.js.map +1 -1
  139. package/dist/cjs/core/SignalCoordinator.d.ts +5 -5
  140. package/dist/cjs/core/SignalCoordinator.d.ts.map +1 -1
  141. package/dist/cjs/core/SignalCoordinator.js +12 -12
  142. package/dist/cjs/core/SignalCoordinator.js.map +1 -1
  143. package/dist/cjs/core/SignalEvaluator.d.ts +4 -4
  144. package/dist/cjs/core/SignalEvaluator.d.ts.map +1 -1
  145. package/dist/cjs/core/SignalEvaluator.js +6 -6
  146. package/dist/cjs/core/SignalEvaluator.js.map +1 -1
  147. package/dist/cjs/core/SignalProcessor.d.ts +6 -6
  148. package/dist/cjs/core/SignalProcessor.d.ts.map +1 -1
  149. package/dist/cjs/core/SignalProcessor.js +17 -89
  150. package/dist/cjs/core/SignalProcessor.js.map +1 -1
  151. package/dist/cjs/core/Step.d.ts +5 -5
  152. package/dist/cjs/core/Step.d.ts.map +1 -1
  153. package/dist/cjs/core/Step.js +65 -17
  154. package/dist/cjs/core/Step.js.map +1 -1
  155. package/dist/cjs/core/StepLifecycle.d.ts +18 -8
  156. package/dist/cjs/core/StepLifecycle.d.ts.map +1 -1
  157. package/dist/cjs/core/StepLifecycle.js +103 -20
  158. package/dist/cjs/core/StepLifecycle.js.map +1 -1
  159. package/dist/cjs/core/StreamingToolExecutor.d.ts +1 -1
  160. package/dist/cjs/core/StreamingToolExecutor.d.ts.map +1 -1
  161. package/dist/cjs/core/StreamingToolExecutor.js +30 -6
  162. package/dist/cjs/core/StreamingToolExecutor.js.map +1 -1
  163. package/dist/cjs/core/ToolLoopExecutor.d.ts +8 -4
  164. package/dist/cjs/core/ToolLoopExecutor.d.ts.map +1 -1
  165. package/dist/cjs/core/ToolLoopExecutor.js +189 -97
  166. package/dist/cjs/core/ToolLoopExecutor.js.map +1 -1
  167. package/dist/cjs/core/ToolManager.d.ts +6 -6
  168. package/dist/cjs/core/ToolManager.d.ts.map +1 -1
  169. package/dist/cjs/core/ToolManager.js +102 -79
  170. package/dist/cjs/core/ToolManager.js.map +1 -1
  171. package/dist/cjs/core/createAgent.d.ts +2 -2
  172. package/dist/cjs/core/createAgent.d.ts.map +1 -1
  173. package/dist/cjs/core/createAgent.js +2 -2
  174. package/dist/cjs/core/createAgent.js.map +1 -1
  175. package/dist/cjs/core/flow-namespace.d.ts +16 -1
  176. package/dist/cjs/core/flow-namespace.d.ts.map +1 -1
  177. package/dist/cjs/core/flow-namespace.js +26 -4
  178. package/dist/cjs/core/flow-namespace.js.map +1 -1
  179. package/dist/cjs/core/toolGates.d.ts +1 -1
  180. package/dist/cjs/core/toolGates.d.ts.map +1 -1
  181. package/dist/cjs/core/toolGates.js +3 -3
  182. package/dist/cjs/core/toolGates.js.map +1 -1
  183. package/dist/cjs/index.d.ts +50 -45
  184. package/dist/cjs/index.d.ts.map +1 -1
  185. package/dist/cjs/index.js +96 -88
  186. package/dist/cjs/index.js.map +1 -1
  187. package/dist/cjs/providers/AnthropicProvider.d.ts +25 -35
  188. package/dist/cjs/providers/AnthropicProvider.d.ts.map +1 -1
  189. package/dist/cjs/providers/AnthropicProvider.js +30 -426
  190. package/dist/cjs/providers/AnthropicProvider.js.map +1 -1
  191. package/dist/cjs/providers/DeepSeekProvider.d.ts +13 -34
  192. package/dist/cjs/providers/DeepSeekProvider.d.ts.map +1 -1
  193. package/dist/cjs/providers/DeepSeekProvider.js +17 -51
  194. package/dist/cjs/providers/DeepSeekProvider.js.map +1 -1
  195. package/dist/cjs/providers/GeminiProvider.d.ts +22 -75
  196. package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
  197. package/dist/cjs/providers/GeminiProvider.js +32 -558
  198. package/dist/cjs/providers/GeminiProvider.js.map +1 -1
  199. package/dist/cjs/providers/GenericOpenAICompatibleProvider.d.ts +9 -10
  200. package/dist/cjs/providers/GenericOpenAICompatibleProvider.d.ts.map +1 -1
  201. package/dist/cjs/providers/GenericOpenAICompatibleProvider.js +14 -20
  202. package/dist/cjs/providers/GenericOpenAICompatibleProvider.js.map +1 -1
  203. package/dist/cjs/providers/OpenAICompatibleProvider.d.ts +26 -135
  204. package/dist/cjs/providers/OpenAICompatibleProvider.d.ts.map +1 -1
  205. package/dist/cjs/providers/OpenAICompatibleProvider.js +40 -496
  206. package/dist/cjs/providers/OpenAICompatibleProvider.js.map +1 -1
  207. package/dist/cjs/providers/OpenAIProvider.d.ts +14 -20
  208. package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
  209. package/dist/cjs/providers/OpenAIProvider.js +21 -28
  210. package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
  211. package/dist/cjs/providers/OpenRouterProvider.d.ts +20 -24
  212. package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
  213. package/dist/cjs/providers/OpenRouterProvider.js +22 -38
  214. package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
  215. package/dist/cjs/providers/ProviderAdapter.d.ts +94 -0
  216. package/dist/cjs/providers/ProviderAdapter.d.ts.map +1 -0
  217. package/dist/cjs/providers/ProviderAdapter.js +257 -0
  218. package/dist/cjs/providers/ProviderAdapter.js.map +1 -0
  219. package/dist/cjs/providers/index.d.ts +21 -18
  220. package/dist/cjs/providers/index.d.ts.map +1 -1
  221. package/dist/cjs/providers/index.js +23 -21
  222. package/dist/cjs/providers/index.js.map +1 -1
  223. package/dist/cjs/types/agent.d.ts +37 -11
  224. package/dist/cjs/types/agent.d.ts.map +1 -1
  225. package/dist/cjs/types/ai.d.ts +11 -21
  226. package/dist/cjs/types/ai.d.ts.map +1 -1
  227. package/dist/cjs/types/compaction.d.ts +2 -2
  228. package/dist/cjs/types/compaction.d.ts.map +1 -1
  229. package/dist/cjs/types/errors.d.ts +16 -20
  230. package/dist/cjs/types/errors.d.ts.map +1 -1
  231. package/dist/cjs/types/errors.js +17 -18
  232. package/dist/cjs/types/errors.js.map +1 -1
  233. package/dist/cjs/types/flow.d.ts +56 -39
  234. package/dist/cjs/types/flow.d.ts.map +1 -1
  235. package/dist/cjs/types/history.d.ts +1 -1
  236. package/dist/cjs/types/history.d.ts.map +1 -1
  237. package/dist/cjs/types/index.d.ts +17 -17
  238. package/dist/cjs/types/index.d.ts.map +1 -1
  239. package/dist/cjs/types/index.js +14 -14
  240. package/dist/cjs/types/index.js.map +1 -1
  241. package/dist/cjs/types/persistence.d.ts +2 -2
  242. package/dist/cjs/types/persistence.d.ts.map +1 -1
  243. package/dist/cjs/types/session.d.ts +4 -4
  244. package/dist/cjs/types/session.d.ts.map +1 -1
  245. package/dist/cjs/types/signals.d.ts +3 -3
  246. package/dist/cjs/types/signals.d.ts.map +1 -1
  247. package/dist/cjs/types/template.d.ts +2 -2
  248. package/dist/cjs/types/template.d.ts.map +1 -1
  249. package/dist/cjs/types/tool.d.ts +4 -2
  250. package/dist/cjs/types/tool.d.ts.map +1 -1
  251. package/dist/cjs/types/tool.js.map +1 -1
  252. package/dist/cjs/utils/condition.d.ts +1 -1
  253. package/dist/cjs/utils/condition.d.ts.map +1 -1
  254. package/dist/cjs/utils/condition.js +6 -6
  255. package/dist/cjs/utils/condition.js.map +1 -1
  256. package/dist/cjs/utils/event.d.ts +1 -1
  257. package/dist/cjs/utils/event.d.ts.map +1 -1
  258. package/dist/cjs/utils/event.js +2 -2
  259. package/dist/cjs/utils/event.js.map +1 -1
  260. package/dist/cjs/utils/history.d.ts +2 -2
  261. package/dist/cjs/utils/history.d.ts.map +1 -1
  262. package/dist/cjs/utils/history.js +15 -15
  263. package/dist/cjs/utils/history.js.map +1 -1
  264. package/dist/cjs/utils/index.d.ts +11 -13
  265. package/dist/cjs/utils/index.d.ts.map +1 -1
  266. package/dist/cjs/utils/index.js +57 -58
  267. package/dist/cjs/utils/index.js.map +1 -1
  268. package/dist/cjs/utils/serialize.d.ts +17 -0
  269. package/dist/cjs/utils/serialize.d.ts.map +1 -1
  270. package/dist/cjs/utils/serialize.js +33 -0
  271. package/dist/cjs/utils/serialize.js.map +1 -1
  272. package/dist/cjs/utils/session.d.ts +23 -3
  273. package/dist/cjs/utils/session.d.ts.map +1 -1
  274. package/dist/cjs/utils/session.js +40 -8
  275. package/dist/cjs/utils/session.js.map +1 -1
  276. package/dist/cjs/utils/template.d.ts +3 -3
  277. package/dist/cjs/utils/template.d.ts.map +1 -1
  278. package/dist/cjs/utils/template.js +5 -5
  279. package/dist/cjs/utils/template.js.map +1 -1
  280. package/dist/constants/index.d.ts +1 -0
  281. package/dist/constants/index.js +1 -1
  282. package/dist/core/Agent.d.ts +19 -11
  283. package/dist/core/Agent.d.ts.map +1 -1
  284. package/dist/core/Agent.js +53 -15
  285. package/dist/core/Agent.js.map +1 -1
  286. package/dist/core/AutoChainExecutor.d.ts +12 -22
  287. package/dist/core/AutoChainExecutor.d.ts.map +1 -1
  288. package/dist/core/AutoChainExecutor.js +27 -30
  289. package/dist/core/AutoChainExecutor.js.map +1 -1
  290. package/dist/core/BranchEvaluator.d.ts +4 -4
  291. package/dist/core/BranchEvaluator.d.ts.map +1 -1
  292. package/dist/core/BranchEvaluator.js +2 -2
  293. package/dist/core/BranchEvaluator.js.map +1 -1
  294. package/dist/core/CompactionEngine.d.ts +16 -3
  295. package/dist/core/CompactionEngine.d.ts.map +1 -1
  296. package/dist/core/CompactionEngine.js +30 -6
  297. package/dist/core/CompactionEngine.js.map +1 -1
  298. package/dist/core/DirectiveChainTracker.d.ts +1 -1
  299. package/dist/core/DirectiveChainTracker.d.ts.map +1 -1
  300. package/dist/core/DirectiveChainTracker.js +2 -2
  301. package/dist/core/DirectiveChainTracker.js.map +1 -1
  302. package/dist/core/Events.d.ts +1 -1
  303. package/dist/core/Events.d.ts.map +1 -1
  304. package/dist/core/Events.js +1 -1
  305. package/dist/core/Events.js.map +1 -1
  306. package/dist/core/Flow.d.ts +4 -4
  307. package/dist/core/Flow.d.ts.map +1 -1
  308. package/dist/core/Flow.js +3 -3
  309. package/dist/core/Flow.js.map +1 -1
  310. package/dist/core/FlowRouter.d.ts +4 -4
  311. package/dist/core/FlowRouter.d.ts.map +1 -1
  312. package/dist/core/FlowRouter.js +36 -14
  313. package/dist/core/FlowRouter.js.map +1 -1
  314. package/dist/core/PersistenceManager.d.ts +1 -1
  315. package/dist/core/PersistenceManager.d.ts.map +1 -1
  316. package/dist/core/PersistenceManager.js +3 -3
  317. package/dist/core/PersistenceManager.js.map +1 -1
  318. package/dist/core/PromptComposer.d.ts +4 -4
  319. package/dist/core/PromptComposer.d.ts.map +1 -1
  320. package/dist/core/PromptComposer.js +3 -3
  321. package/dist/core/PromptComposer.js.map +1 -1
  322. package/dist/core/PromptSectionCache.d.ts +2 -2
  323. package/dist/core/PromptSectionCache.d.ts.map +1 -1
  324. package/dist/core/ResponseEngine.d.ts +4 -4
  325. package/dist/core/ResponseEngine.d.ts.map +1 -1
  326. package/dist/core/ResponseEngine.js +2 -2
  327. package/dist/core/ResponseEngine.js.map +1 -1
  328. package/dist/core/ResponseGenerationError.d.ts.map +1 -1
  329. package/dist/core/ResponseGenerationError.js +3 -5
  330. package/dist/core/ResponseGenerationError.js.map +1 -1
  331. package/dist/core/ResponseModal.d.ts +39 -10
  332. package/dist/core/ResponseModal.d.ts.map +1 -1
  333. package/dist/core/ResponseModal.js +152 -29
  334. package/dist/core/ResponseModal.js.map +1 -1
  335. package/dist/core/ResponsePipeline.d.ts +50 -12
  336. package/dist/core/ResponsePipeline.d.ts.map +1 -1
  337. package/dist/core/ResponsePipeline.js +232 -89
  338. package/dist/core/ResponsePipeline.js.map +1 -1
  339. package/dist/core/SessionFinalizer.d.ts +4 -4
  340. package/dist/core/SessionFinalizer.d.ts.map +1 -1
  341. package/dist/core/SessionFinalizer.js +32 -5
  342. package/dist/core/SessionFinalizer.js.map +1 -1
  343. package/dist/core/SessionManager.d.ts +15 -6
  344. package/dist/core/SessionManager.d.ts.map +1 -1
  345. package/dist/core/SessionManager.js +46 -19
  346. package/dist/core/SessionManager.js.map +1 -1
  347. package/dist/core/SignalCoordinator.d.ts +5 -5
  348. package/dist/core/SignalCoordinator.d.ts.map +1 -1
  349. package/dist/core/SignalCoordinator.js +2 -2
  350. package/dist/core/SignalCoordinator.js.map +1 -1
  351. package/dist/core/SignalEvaluator.d.ts +4 -4
  352. package/dist/core/SignalEvaluator.d.ts.map +1 -1
  353. package/dist/core/SignalEvaluator.js +2 -2
  354. package/dist/core/SignalEvaluator.js.map +1 -1
  355. package/dist/core/SignalProcessor.d.ts +6 -6
  356. package/dist/core/SignalProcessor.d.ts.map +1 -1
  357. package/dist/core/SignalProcessor.js +7 -79
  358. package/dist/core/SignalProcessor.js.map +1 -1
  359. package/dist/core/Step.d.ts +5 -5
  360. package/dist/core/Step.d.ts.map +1 -1
  361. package/dist/core/Step.js +53 -5
  362. package/dist/core/Step.js.map +1 -1
  363. package/dist/core/StepLifecycle.d.ts +18 -8
  364. package/dist/core/StepLifecycle.d.ts.map +1 -1
  365. package/dist/core/StepLifecycle.js +98 -15
  366. package/dist/core/StepLifecycle.js.map +1 -1
  367. package/dist/core/StreamingToolExecutor.d.ts +1 -1
  368. package/dist/core/StreamingToolExecutor.d.ts.map +1 -1
  369. package/dist/core/StreamingToolExecutor.js +29 -5
  370. package/dist/core/StreamingToolExecutor.js.map +1 -1
  371. package/dist/core/ToolLoopExecutor.d.ts +8 -4
  372. package/dist/core/ToolLoopExecutor.d.ts.map +1 -1
  373. package/dist/core/ToolLoopExecutor.js +157 -65
  374. package/dist/core/ToolLoopExecutor.js.map +1 -1
  375. package/dist/core/ToolManager.d.ts +6 -6
  376. package/dist/core/ToolManager.d.ts.map +1 -1
  377. package/dist/core/ToolManager.js +44 -21
  378. package/dist/core/ToolManager.js.map +1 -1
  379. package/dist/core/createAgent.d.ts +2 -2
  380. package/dist/core/createAgent.d.ts.map +1 -1
  381. package/dist/core/createAgent.js +1 -1
  382. package/dist/core/createAgent.js.map +1 -1
  383. package/dist/core/flow-namespace.d.ts +16 -1
  384. package/dist/core/flow-namespace.d.ts.map +1 -1
  385. package/dist/core/flow-namespace.js +23 -1
  386. package/dist/core/flow-namespace.js.map +1 -1
  387. package/dist/core/toolGates.d.ts +1 -1
  388. package/dist/core/toolGates.d.ts.map +1 -1
  389. package/dist/core/toolGates.js +1 -1
  390. package/dist/core/toolGates.js.map +1 -1
  391. package/dist/index.d.ts +50 -45
  392. package/dist/index.d.ts.map +1 -1
  393. package/dist/index.js +34 -30
  394. package/dist/index.js.map +1 -1
  395. package/dist/providers/AnthropicProvider.d.ts +25 -35
  396. package/dist/providers/AnthropicProvider.d.ts.map +1 -1
  397. package/dist/providers/AnthropicProvider.js +30 -423
  398. package/dist/providers/AnthropicProvider.js.map +1 -1
  399. package/dist/providers/DeepSeekProvider.d.ts +13 -34
  400. package/dist/providers/DeepSeekProvider.d.ts.map +1 -1
  401. package/dist/providers/DeepSeekProvider.js +16 -47
  402. package/dist/providers/DeepSeekProvider.js.map +1 -1
  403. package/dist/providers/GeminiProvider.d.ts +22 -75
  404. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  405. package/dist/providers/GeminiProvider.js +32 -558
  406. package/dist/providers/GeminiProvider.js.map +1 -1
  407. package/dist/providers/GenericOpenAICompatibleProvider.d.ts +9 -10
  408. package/dist/providers/GenericOpenAICompatibleProvider.d.ts.map +1 -1
  409. package/dist/providers/GenericOpenAICompatibleProvider.js +13 -16
  410. package/dist/providers/GenericOpenAICompatibleProvider.js.map +1 -1
  411. package/dist/providers/OpenAICompatibleProvider.d.ts +26 -135
  412. package/dist/providers/OpenAICompatibleProvider.d.ts.map +1 -1
  413. package/dist/providers/OpenAICompatibleProvider.js +39 -495
  414. package/dist/providers/OpenAICompatibleProvider.js.map +1 -1
  415. package/dist/providers/OpenAIProvider.d.ts +14 -20
  416. package/dist/providers/OpenAIProvider.d.ts.map +1 -1
  417. package/dist/providers/OpenAIProvider.js +20 -24
  418. package/dist/providers/OpenAIProvider.js.map +1 -1
  419. package/dist/providers/OpenRouterProvider.d.ts +20 -24
  420. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  421. package/dist/providers/OpenRouterProvider.js +21 -34
  422. package/dist/providers/OpenRouterProvider.js.map +1 -1
  423. package/dist/providers/ProviderAdapter.d.ts +94 -0
  424. package/dist/providers/ProviderAdapter.d.ts.map +1 -0
  425. package/dist/providers/ProviderAdapter.js +251 -0
  426. package/dist/providers/ProviderAdapter.js.map +1 -0
  427. package/dist/providers/index.d.ts +21 -18
  428. package/dist/providers/index.d.ts.map +1 -1
  429. package/dist/providers/index.js +13 -10
  430. package/dist/providers/index.js.map +1 -1
  431. package/dist/types/agent.d.ts +37 -11
  432. package/dist/types/agent.d.ts.map +1 -1
  433. package/dist/types/ai.d.ts +11 -21
  434. package/dist/types/ai.d.ts.map +1 -1
  435. package/dist/types/compaction.d.ts +2 -2
  436. package/dist/types/compaction.d.ts.map +1 -1
  437. package/dist/types/errors.d.ts +16 -20
  438. package/dist/types/errors.d.ts.map +1 -1
  439. package/dist/types/errors.js +15 -16
  440. package/dist/types/errors.js.map +1 -1
  441. package/dist/types/flow.d.ts +56 -39
  442. package/dist/types/flow.d.ts.map +1 -1
  443. package/dist/types/history.d.ts +1 -1
  444. package/dist/types/history.d.ts.map +1 -1
  445. package/dist/types/index.d.ts +17 -17
  446. package/dist/types/index.d.ts.map +1 -1
  447. package/dist/types/index.js +4 -4
  448. package/dist/types/index.js.map +1 -1
  449. package/dist/types/persistence.d.ts +2 -2
  450. package/dist/types/persistence.d.ts.map +1 -1
  451. package/dist/types/session.d.ts +4 -4
  452. package/dist/types/session.d.ts.map +1 -1
  453. package/dist/types/signals.d.ts +3 -3
  454. package/dist/types/signals.d.ts.map +1 -1
  455. package/dist/types/template.d.ts +2 -2
  456. package/dist/types/template.d.ts.map +1 -1
  457. package/dist/types/tool.d.ts +4 -2
  458. package/dist/types/tool.d.ts.map +1 -1
  459. package/dist/types/tool.js.map +1 -1
  460. package/dist/utils/condition.d.ts +1 -1
  461. package/dist/utils/condition.d.ts.map +1 -1
  462. package/dist/utils/condition.js +2 -2
  463. package/dist/utils/condition.js.map +1 -1
  464. package/dist/utils/event.d.ts +1 -1
  465. package/dist/utils/event.d.ts.map +1 -1
  466. package/dist/utils/event.js +1 -1
  467. package/dist/utils/event.js.map +1 -1
  468. package/dist/utils/history.d.ts +2 -2
  469. package/dist/utils/history.d.ts.map +1 -1
  470. package/dist/utils/history.js +1 -1
  471. package/dist/utils/history.js.map +1 -1
  472. package/dist/utils/index.d.ts +11 -13
  473. package/dist/utils/index.d.ts.map +1 -1
  474. package/dist/utils/index.js +11 -12
  475. package/dist/utils/index.js.map +1 -1
  476. package/dist/utils/serialize.d.ts +17 -0
  477. package/dist/utils/serialize.d.ts.map +1 -1
  478. package/dist/utils/serialize.js +31 -0
  479. package/dist/utils/serialize.js.map +1 -1
  480. package/dist/utils/session.d.ts +23 -3
  481. package/dist/utils/session.d.ts.map +1 -1
  482. package/dist/utils/session.js +35 -6
  483. package/dist/utils/session.js.map +1 -1
  484. package/dist/utils/template.d.ts +3 -3
  485. package/dist/utils/template.d.ts.map +1 -1
  486. package/dist/utils/template.js +1 -1
  487. package/dist/utils/template.js.map +1 -1
  488. package/docs/concepts/architecture.md +3 -3
  489. package/docs/concepts/directives.md +1 -1
  490. package/docs/guides/error-handling.md +46 -45
  491. package/docs/guides/flow-control.md +8 -1
  492. package/docs/guides/instructions.md +15 -6
  493. package/docs/guides/persistence.md +12 -5
  494. package/docs/guides/streaming.md +10 -0
  495. package/docs/migration/README.md +4 -0
  496. package/docs/migration/v2-3-to-v2-4.md +4 -0
  497. package/docs/migration/v2-6-to-v2-7.md +246 -0
  498. package/docs/reference/adapters.md +15 -1
  499. package/docs/reference/branches.md +2 -0
  500. package/docs/reference/create-agent.md +28 -0
  501. package/docs/reference/directive.md +1 -1
  502. package/docs/reference/errors.md +30 -32
  503. package/docs/reference/providers.md +63 -60
  504. package/docs/reference/step.md +28 -21
  505. package/docs/reference/tool.md +14 -5
  506. package/docs/start/02-first-agent.md +8 -4
  507. package/docs/start/03-collect-data.md +19 -10
  508. package/examples/01-quickstart.ts +2 -2
  509. package/examples/02-data-extraction.ts +1 -1
  510. package/examples/03-tools.ts +1 -1
  511. package/examples/04-instructions.ts +2 -2
  512. package/examples/05-branching.ts +3 -3
  513. package/examples/06-flow-control.ts +3 -3
  514. package/examples/07-streaming.ts +1 -1
  515. package/examples/08-persistence.ts +2 -2
  516. package/examples/09-signals.ts +1 -1
  517. package/examples/tsconfig.json +6 -3
  518. package/package.json +9 -7
  519. package/src/adapters/MemoryAdapter.ts +33 -37
  520. package/src/adapters/MongoAdapter.ts +3 -3
  521. package/src/adapters/OpenSearchAdapter.ts +4 -4
  522. package/src/adapters/PostgreSQLAdapter.ts +26 -21
  523. package/src/adapters/PrismaAdapter.ts +4 -4
  524. package/src/adapters/RedisAdapter.ts +84 -37
  525. package/src/adapters/SQLiteAdapter.ts +13 -34
  526. package/src/adapters/index.ts +13 -13
  527. package/src/adapters/sessionRow.ts +57 -0
  528. package/src/core/Agent.ts +64 -18
  529. package/src/core/AutoChainExecutor.ts +44 -57
  530. package/src/core/BranchEvaluator.ts +5 -5
  531. package/src/core/CompactionEngine.ts +42 -8
  532. package/src/core/DirectiveChainTracker.ts +3 -3
  533. package/src/core/Events.ts +2 -2
  534. package/src/core/Flow.ts +9 -9
  535. package/src/core/FlowRouter.ts +46 -20
  536. package/src/core/PersistenceManager.ts +4 -4
  537. package/src/core/PromptComposer.ts +8 -8
  538. package/src/core/PromptSectionCache.ts +2 -2
  539. package/src/core/ResponseEngine.ts +6 -6
  540. package/src/core/ResponseGenerationError.ts +3 -6
  541. package/src/core/ResponseModal.ts +205 -39
  542. package/src/core/ResponsePipeline.ts +301 -107
  543. package/src/core/SessionFinalizer.ts +40 -10
  544. package/src/core/SessionManager.ts +61 -27
  545. package/src/core/SignalCoordinator.ts +7 -7
  546. package/src/core/SignalEvaluator.ts +6 -6
  547. package/src/core/SignalProcessor.ts +13 -93
  548. package/src/core/Step.ts +87 -10
  549. package/src/core/StepLifecycle.ts +129 -26
  550. package/src/core/StreamingToolExecutor.ts +33 -8
  551. package/src/core/ToolLoopExecutor.ts +206 -80
  552. package/src/core/ToolManager.ts +53 -26
  553. package/src/core/createAgent.ts +2 -2
  554. package/src/core/flow-namespace.ts +31 -2
  555. package/src/core/toolGates.ts +2 -2
  556. package/src/index.ts +59 -45
  557. package/src/providers/AnthropicProvider.ts +44 -595
  558. package/src/providers/DeepSeekProvider.ts +27 -92
  559. package/src/providers/GeminiProvider.ts +41 -752
  560. package/src/providers/GenericOpenAICompatibleProvider.ts +19 -27
  561. package/src/providers/OpenAICompatibleProvider.ts +58 -764
  562. package/src/providers/OpenAIProvider.ts +31 -55
  563. package/src/providers/OpenRouterProvider.ts +40 -70
  564. package/src/providers/ProviderAdapter.ts +368 -0
  565. package/src/providers/index.ts +21 -23
  566. package/src/types/agent.ts +36 -11
  567. package/src/types/ai.ts +11 -21
  568. package/src/types/compaction.ts +2 -2
  569. package/src/types/errors.ts +17 -35
  570. package/src/types/flow.ts +44 -46
  571. package/src/types/history.ts +1 -1
  572. package/src/types/index.ts +18 -17
  573. package/src/types/persistence.ts +2 -2
  574. package/src/types/session.ts +4 -4
  575. package/src/types/signals.ts +3 -3
  576. package/src/types/template.ts +2 -2
  577. package/src/types/tool.ts +4 -2
  578. package/src/utils/condition.ts +3 -3
  579. package/src/utils/event.ts +1 -1
  580. package/src/utils/history.ts +3 -3
  581. package/src/utils/index.ts +14 -15
  582. package/src/utils/serialize.ts +38 -0
  583. package/src/utils/session.ts +46 -9
  584. package/src/utils/template.ts +3 -3
  585. package/dist/cjs/core/DirectiveBus.d.ts +0 -88
  586. package/dist/cjs/core/DirectiveBus.d.ts.map +0 -1
  587. package/dist/cjs/core/DirectiveBus.js +0 -196
  588. package/dist/cjs/core/DirectiveBus.js.map +0 -1
  589. package/dist/cjs/providers/errorClassification.d.ts +0 -61
  590. package/dist/cjs/providers/errorClassification.d.ts.map +0 -1
  591. package/dist/cjs/providers/errorClassification.js +0 -123
  592. package/dist/cjs/providers/errorClassification.js.map +0 -1
  593. package/dist/cjs/utils/retry.d.ts +0 -67
  594. package/dist/cjs/utils/retry.d.ts.map +0 -1
  595. package/dist/cjs/utils/retry.js +0 -201
  596. package/dist/cjs/utils/retry.js.map +0 -1
  597. package/dist/core/DirectiveBus.d.ts +0 -88
  598. package/dist/core/DirectiveBus.d.ts.map +0 -1
  599. package/dist/core/DirectiveBus.js +0 -192
  600. package/dist/core/DirectiveBus.js.map +0 -1
  601. package/dist/providers/errorClassification.d.ts +0 -61
  602. package/dist/providers/errorClassification.d.ts.map +0 -1
  603. package/dist/providers/errorClassification.js +0 -116
  604. package/dist/providers/errorClassification.js.map +0 -1
  605. package/dist/utils/retry.d.ts +0 -67
  606. package/dist/utils/retry.d.ts.map +0 -1
  607. package/dist/utils/retry.js +0 -193
  608. package/dist/utils/retry.js.map +0 -1
  609. package/src/core/DirectiveBus.ts +0 -248
  610. package/src/providers/errorClassification.ts +0 -172
  611. package/src/utils/retry.ts +0 -274
@@ -18,15 +18,41 @@ import type {
18
18
  AgentOptions,
19
19
  AgentResponseStreamChunk,
20
20
  AgentStructuredResponse,
21
+ Directive,
21
22
  HistoryItem,
22
23
  SessionState,
23
24
  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, assistantMessage, toolMessage } from "../utils";
25
+ } from "../types/index.js";
26
+ import type { Flow } from "./Flow.js";
27
+ import type { Step } from "./Step.js";
28
+ import type { ToolManager } from "./ToolManager.js";
29
+ import { ResponseGenerationError } from "./ResponseGenerationError.js";
30
+ import { flow } from "./flow-namespace.js";
31
+ import { historyToEvents, logger, serializeToolResult, assistantMessage, toolMessage } from "../utils/index.js";
32
+
33
+ /**
34
+ * One attempted tool execution, keyed by CALL (not tool name): parallel or
35
+ * repeated calls to the same tool in one turn keep their own results instead
36
+ * of overwriting each other.
37
+ */
38
+ interface ToolExecutionRecord {
39
+ requestId: string;
40
+ toolName: string;
41
+ arguments: Record<string, unknown>;
42
+ /** Which loop round produced this call (0 = the initial streamed batch). */
43
+ round: number;
44
+ /** Serialized result fed back to the model; set EVEN on failure. */
45
+ result?: string;
46
+ }
47
+
48
+ const executionFailure = (toolName: string, error: unknown): string =>
49
+ JSON.stringify({
50
+ success: false,
51
+ error: `${toolName}: ${error instanceof Error ? error.message : String(error)}`,
52
+ });
53
+
54
+ const toolNotFoundFailure = (toolName: string): string =>
55
+ JSON.stringify({ success: false, error: `Tool "${toolName}" is not registered in any scope.` });
30
56
 
31
57
  export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
32
58
  constructor(
@@ -69,6 +95,8 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
69
95
  finalToolCalls?: Array<{ toolName: string; arguments: Record<string, unknown> }>;
70
96
  finalMessage?: string;
71
97
  structured?: AgentStructuredResponse;
98
+ /** Directives emitted by tools this turn (ctx.dispatch / `{directive}` returns), merged. */
99
+ directives?: Directive<TContext, TData>;
72
100
  }> {
73
101
  try {
74
102
  const { context, history, selectedFlow, responsePrompt, availableTools, responseSchema, signal } = params;
@@ -77,22 +105,32 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
77
105
  const { toolCalls } = params;
78
106
  let { session } = params;
79
107
 
108
+ // Directives emitted by tools this turn — consumed by the caller
109
+ const collectedDirectives: Directive<TContext, TData>[] = [];
110
+
80
111
  // Convert HistoryItem[] to Event[] for internal processing
81
112
  const historyEvents = historyToEvents(history);
82
113
 
83
- // Map to store tool execution results for history
84
- const toolResultsMap = new Map<string, string>();
85
- // Map to store tool call arguments for history reconstruction
86
- const toolArgsMap = new Map<string, Record<string, unknown>>();
114
+ // Execution records keyed by call shared with the follow-up loop
115
+ const records: ToolExecutionRecord[] = [];
87
116
 
88
117
  // Execute initial dynamic tool calls
89
118
  if (toolCalls && toolCalls.length > 0) {
90
119
  logger.debug(`[ToolLoopExecutor] Executing ${toolCalls.length} dynamic tool calls:`, toolCalls.map(tc => tc.toolName));
91
120
 
92
- for (const toolCall of toolCalls) {
121
+ for (const [callIndex, toolCall] of toolCalls.entries()) {
122
+ const record: ToolExecutionRecord = {
123
+ requestId: `init-${callIndex}-${toolCall.toolName}`,
124
+ toolName: toolCall.toolName,
125
+ arguments: toolCall.arguments,
126
+ round: 0,
127
+ };
128
+ records.push(record);
129
+
93
130
  const tool = this.findAvailableTool(toolCall.toolName, selectedFlow);
94
131
  if (!tool) {
95
- 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.`);
132
+ logger.warn(`[ToolExecutionError] Tool not found: "${toolCall.toolName}" is not registered in any scope. Register the tool or check the tool name.`);
133
+ record.result = toolNotFoundFailure(toolCall.toolName);
96
134
  continue;
97
135
  }
98
136
 
@@ -109,8 +147,12 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
109
147
  });
110
148
 
111
149
  // Store the actual tool result data for history
112
- toolResultsMap.set(toolCall.toolName, serializeToolResult(toolResult));
113
- toolArgsMap.set(toolCall.toolName, toolCall.arguments);
150
+ record.result = serializeToolResult(toolResult);
151
+
152
+ // Collect tool-emitted directives (ctx.dispatch / {directive})
153
+ if (toolResult.directives?.length) {
154
+ collectedDirectives.push(...toolResult.directives as Directive<TContext, TData>[]);
155
+ }
114
156
 
115
157
  // Check if tool execution was successful
116
158
  if (!toolResult.success) {
@@ -143,20 +185,37 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
143
185
  logger.debug(`[ToolLoopExecutor] Executed dynamic tool: ${toolCall.toolName} (success: ${toolResult.success})`);
144
186
  } catch (error) {
145
187
  logger.error(`[ToolLoopExecutor] Tool execution error for ${toolCall.toolName}:`, error);
146
- // Continue with other tools rather than failing the entire response
188
+ // A thrown handler must be visible to the model as a FAILED
189
+ // tool call — reporting success makes it confirm actions
190
+ // that never happened.
191
+ record.result = executionFailure(toolCall.toolName, error);
147
192
  continue;
148
193
  }
149
194
  }
150
195
  }
151
196
 
197
+ // A tool spoke verbatim this turn: its reply IS the final message —
198
+ // skip the follow-up LLM call (documented dispatch semantics).
199
+ const preLoopDirectives = flow.mergeAll(collectedDirectives);
200
+ if (preLoopDirectives?.reply) {
201
+ logger.debug("[ToolLoopExecutor] Tool directive reply short-circuits follow-up LLM call");
202
+ return {
203
+ session,
204
+ finalToolCalls: toolCalls,
205
+ finalMessage: preLoopDirectives.reply,
206
+ structured: { message: preLoopDirectives.reply },
207
+ directives: preLoopDirectives,
208
+ };
209
+ }
210
+
152
211
  // Hand off to the multi-round follow-up loop shared with the
153
212
  // streaming path. The initial batch above already executed
154
213
  // sequentially and populated the result maps.
155
214
  return await this.runFollowUpLoop({
156
215
  toolCalls,
157
216
  session,
158
- toolResultsMap,
159
- toolArgsMap,
217
+ records,
218
+ collectedDirectives,
160
219
  context,
161
220
  history,
162
221
  selectedFlow,
@@ -186,8 +245,10 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
186
245
  private async runFollowUpLoop(params: {
187
246
  toolCalls?: Array<{ toolName: string; arguments: Record<string, unknown> }>;
188
247
  session: SessionState<TData>;
189
- toolResultsMap: Map<string, string>;
190
- toolArgsMap: Map<string, Record<string, unknown>>;
248
+ /** Execution records from prior rounds (initial batch = round 0). */
249
+ records: ToolExecutionRecord[];
250
+ /** Shared directive collector — initial-batch emissions land here too. */
251
+ collectedDirectives?: Directive<TContext, TData>[];
191
252
  context: TContext;
192
253
  history: HistoryItem[];
193
254
  selectedFlow?: Flow<TContext, TData>;
@@ -205,8 +266,9 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
205
266
  finalToolCalls?: Array<{ toolName: string; arguments: Record<string, unknown> }>;
206
267
  finalMessage?: string;
207
268
  structured?: AgentStructuredResponse;
269
+ directives?: Directive<TContext, TData>;
208
270
  }> {
209
- const { context, history, selectedFlow, responsePrompt, availableTools, responseSchema, signal, toolResultsMap, toolArgsMap } = params;
271
+ const { context, history, selectedFlow, responsePrompt, availableTools, responseSchema, signal, records, collectedDirectives = [] } = params;
210
272
  let { toolCalls, session } = params;
211
273
  try {
212
274
  // TOOL LOOP: Allow AI to make follow-up tool calls after initial tool execution
@@ -222,45 +284,43 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
222
284
  toolLoopCount++;
223
285
  logger.debug(`[ToolLoopExecutor] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS} with ${toolCalls?.length || 0} tool calls`);
224
286
 
225
- // Create tool result history items
287
+ // Create tool result history items for the PREVIOUS round's
288
+ // calls. Failures are reported as failures — never as success.
289
+ const previousRound = toolLoopCount - 1;
290
+ const roundRecords = records.filter((r) => r.round === previousRound);
226
291
  const toolResultHistoryItems: HistoryItem[] = [];
227
- for (const toolCall of toolCalls || []) {
228
- const tool = this.findAvailableTool(toolCall.toolName, selectedFlow);
229
- if (tool) {
230
- // assistant tool_call + tool result pair, via the shared
231
- // history factories (same as forceFinalTextFromTools).
232
- toolResultHistoryItems.push(
233
- assistantMessage(null, [
234
- { id: toolCall.toolName, name: toolCall.toolName, arguments: toolCall.arguments },
235
- ]),
236
- toolMessage(
237
- toolCall.toolName,
238
- toolCall.toolName,
239
- toolResultsMap.get(toolCall.toolName) || "Tool executed successfully",
240
- ),
241
- );
242
- }
292
+ for (const record of roundRecords) {
293
+ toolResultHistoryItems.push(
294
+ assistantMessage(null, [
295
+ { id: record.requestId, name: record.toolName, arguments: record.arguments },
296
+ ]),
297
+ toolMessage(
298
+ record.toolName,
299
+ record.requestId,
300
+ record.result ?? toolNotFoundFailure(record.toolName),
301
+ ),
302
+ );
243
303
  }
244
304
 
245
305
  // Create updated history with tool results
246
306
  const updatedHistory = [...history, ...toolResultHistoryItems];
247
307
 
248
- // Make follow-up AI call to see if more tools are needed
249
- // After first iteration, don't provide tools to force a text response
308
+ // Make follow-up AI call to see if more tools are needed.
309
+ // Tools are offered EVERY iteration the loop is already bounded
310
+ // by MAX_TOOL_LOOPS, so withholding them after round only made
311
+ // maxToolLoops values above 2 unreachable.
250
312
  const agentOptions = this.deps.getAgentOptions();
251
- const shouldProvideTools = toolLoopCount === 1;
252
313
 
253
314
  logger.debug(`[ToolLoopExecutor] Making follow-up AI call (loop ${toolLoopCount}):`, {
254
- providingTools: shouldProvideTools,
255
- toolsCount: shouldProvideTools ? availableTools.length : 0,
256
- addingTextInstruction: toolLoopCount > 1,
315
+ providingTools: true,
316
+ toolsCount: availableTools.length,
257
317
  });
258
318
 
259
319
  const followUpResult = await agentOptions.provider.generateMessage({
260
- prompt: responsePrompt + (toolLoopCount > 1 ? "\n\nProvide a text response to the user based on the tool results." : ""),
320
+ prompt: responsePrompt,
261
321
  history: updatedHistory, // Use HistoryItem[] for AI provider
262
322
  context,
263
- tools: shouldProvideTools ? availableTools : [], // Only provide tools on first iteration
323
+ tools: availableTools,
264
324
  parameters: responseSchema ? {
265
325
  jsonSchema: responseSchema,
266
326
  schemaName: "tool_followup",
@@ -284,10 +344,19 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
284
344
  logger.debug(`[ToolLoopExecutor] Follow-up call produced ${followUpToolCalls!.length} additional tool calls`);
285
345
 
286
346
  // Execute the follow-up tool calls
287
- for (const toolCall of followUpToolCalls!) {
347
+ for (const [callIndex, toolCall] of followUpToolCalls!.entries()) {
348
+ const record: ToolExecutionRecord = {
349
+ requestId: `fup-${toolLoopCount}-${callIndex}-${toolCall.toolName}`,
350
+ toolName: toolCall.toolName,
351
+ arguments: toolCall.arguments,
352
+ round: toolLoopCount,
353
+ };
354
+ records.push(record);
355
+
288
356
  const tool = this.findAvailableTool(toolCall.toolName, selectedFlow);
289
357
  if (!tool) {
290
- 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.`);
358
+ logger.warn(`[ToolExecutionError] Tool not found in follow-up: "${toolCall.toolName}" is not registered in any scope. Register the tool or check the tool name.`);
359
+ record.result = toolNotFoundFailure(toolCall.toolName);
291
360
  continue;
292
361
  }
293
362
 
@@ -328,16 +397,34 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
328
397
  }
329
398
 
330
399
  // Store the follow-up tool result for potential next loop iteration
331
- toolResultsMap.set(toolCall.toolName, serializeToolResult(toolResult));
332
- toolArgsMap.set(toolCall.toolName, toolCall.arguments);
400
+ record.result = serializeToolResult(toolResult);
401
+
402
+ // Collect tool-emitted directives (ctx.dispatch / {directive})
403
+ if (toolResult.directives?.length) {
404
+ collectedDirectives.push(...toolResult.directives as Directive<TContext, TData>[]);
405
+ }
333
406
 
334
407
  logger.debug(`[ToolLoopExecutor] Executed follow-up tool: ${toolCall.toolName} (success: ${toolResult.success})`);
335
408
  } catch (error) {
336
409
  logger.error(`[ToolLoopExecutor] Follow-up tool execution error for ${toolCall.toolName}:`, error);
410
+ // Visible failure beats a fabricated success.
411
+ record.result = executionFailure(toolCall.toolName, error);
337
412
  continue;
338
413
  }
339
414
  }
340
415
 
416
+ // A tool emitted a verbatim reply this round: it IS the final
417
+ // message — stop looping and skip any further LLM call.
418
+ const roundDirectives = flow.mergeAll(collectedDirectives);
419
+ if (roundDirectives?.reply) {
420
+ logger.debug("[ToolLoopExecutor] Tool directive reply short-circuits remaining tool loop");
421
+ finalMessage = roundDirectives.reply;
422
+ followUpStructured = { message: roundDirectives.reply };
423
+ hasToolCalls = false;
424
+ toolCalls = undefined;
425
+ break;
426
+ }
427
+
341
428
  // Update toolCalls for next iteration or final response
342
429
  toolCalls = followUpToolCalls;
343
430
  } else {
@@ -363,8 +450,7 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
363
450
  logger.debug(`[ToolLoopExecutor] No final message after tool loop, making additional LLM call for text response`);
364
451
  const forced = await this.forceFinalTextFromTools({
365
452
  history,
366
- toolResultsMap,
367
- toolArgsMap,
453
+ records,
368
454
  responsePrompt,
369
455
  responseSchema,
370
456
  context,
@@ -390,6 +476,7 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
390
476
  finalToolCalls: toolCalls,
391
477
  finalMessage,
392
478
  structured: followUpStructured,
479
+ directives: flow.mergeAll(collectedDirectives),
393
480
  };
394
481
  } catch (error) {
395
482
  throw ResponseGenerationError.fromError(error, 'tool_execution', params, {
@@ -408,24 +495,25 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
408
495
  */
409
496
  private async forceFinalTextFromTools(params: {
410
497
  history: HistoryItem[];
411
- toolResultsMap: Map<string, string>;
412
- toolArgsMap: Map<string, Record<string, unknown>>;
498
+ records: ToolExecutionRecord[];
413
499
  responsePrompt: string;
414
500
  responseSchema?: Record<string, unknown>;
415
501
  context: TContext;
416
502
  signal?: AbortSignal;
417
503
  }): Promise<{ finalMessage?: string; structured?: AgentStructuredResponse }> {
418
- const { history, toolResultsMap, toolArgsMap, responsePrompt, responseSchema, context, signal } = params;
504
+ const { history, records, responsePrompt, responseSchema, context, signal } = params;
419
505
 
420
506
  // Reconstruct assistant tool_call + tool result pairs so the follow-up
421
- // call can see what the tools returned.
507
+ // call can see what the tools returned — every executed call, keyed by
508
+ // its own request id.
422
509
  const finalToolResultHistoryItems: HistoryItem[] = [];
423
- for (const [toolName, toolResult] of toolResultsMap) {
510
+ for (const record of records) {
511
+ if (!record.result) continue;
424
512
  finalToolResultHistoryItems.push(
425
513
  assistantMessage(null, [
426
- { id: toolName, name: toolName, arguments: toolArgsMap.get(toolName) || {} },
514
+ { id: record.requestId, name: record.toolName, arguments: record.arguments },
427
515
  ]),
428
- toolMessage(toolName, toolName, toolResult),
516
+ toolMessage(record.toolName, record.requestId, record.result),
429
517
  );
430
518
  }
431
519
 
@@ -494,12 +582,17 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
494
582
  /** Closing message forced from the tool results, if one was generated. */
495
583
  finalMessage?: string;
496
584
  structured?: AgentStructuredResponse;
585
+ /** Directives emitted by tools this turn (ctx.dispatch / `{directive}` returns), merged. */
586
+ directives?: Directive<TContext, TData>;
497
587
  }
498
588
  > {
499
589
  const { context, history, selectedFlow, step, accumulated, responsePrompt, availableTools, responseSchema, signal } = params;
500
590
  let { session } = params;
501
591
  let toolCalls: Array<{ toolName: string; arguments: Record<string, unknown> }> | undefined = params.toolCalls;
502
592
 
593
+ // Directives emitted by tools this turn — surfaced to the caller
594
+ const collectedDirectives: Directive<TContext, TData>[] = [];
595
+
503
596
  // Use concurrent execution for the initial batch of tool calls
504
597
  const toolCallRequests: ToolCallRequest[] = params.toolCalls.map((tc, i) => ({
505
598
  id: `${tc.toolName}-${i}-${Date.now()}`,
@@ -508,9 +601,15 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
508
601
  }));
509
602
  // Map request id -> request so completed results can be attributed back
510
603
  // to their tool name/arguments for the forced final-text call.
511
- const requestById = new Map(toolCallRequests.map((r) => [r.id, r]));
512
- const toolResultsMap = new Map<string, string>();
513
- const toolArgsMap = new Map<string, Record<string, unknown>>();
604
+ // Execution records keyed by call id — seeded at queue time so results
605
+ // (and failures) attach to the right call even for same-name calls.
606
+ const records: ToolExecutionRecord[] = toolCallRequests.map((req) => ({
607
+ requestId: req.id,
608
+ toolName: req.toolName,
609
+ arguments: req.arguments,
610
+ round: 0,
611
+ }));
612
+ const recordById = new Map(records.map((r) => [r.requestId, r]));
514
613
 
515
614
  const historyEvents = historyToEvents(history);
516
615
 
@@ -547,10 +646,13 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
547
646
 
548
647
  // Capture tool results for the forced final-text call
549
648
  if (update.result) {
550
- const req = requestById.get(update.toolCallId);
551
- if (req) {
552
- toolResultsMap.set(req.toolName, serializeToolResult(update.result));
553
- toolArgsMap.set(req.toolName, req.arguments);
649
+ const record = recordById.get(update.toolCallId);
650
+ if (record) {
651
+ record.result = serializeToolResult(update.result);
652
+ }
653
+ // Collect tool-emitted directives (ctx.dispatch / {directive})
654
+ if (update.result.directives?.length) {
655
+ collectedDirectives.push(...update.result.directives as Directive<TContext, TData>[]);
554
656
  }
555
657
  }
556
658
 
@@ -578,8 +680,8 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
578
680
  const followUp = await this.runFollowUpLoop({
579
681
  toolCalls,
580
682
  session,
581
- toolResultsMap,
582
- toolArgsMap,
683
+ records,
684
+ collectedDirectives,
583
685
  context,
584
686
  history,
585
687
  selectedFlow,
@@ -593,21 +695,45 @@ export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
593
695
  finalMessage = followUp.finalMessage;
594
696
  structured = followUp.structured;
595
697
  } catch (error) {
596
- logger.error(`[ToolLoopExecutor] Concurrent tool execution failed, falling back to sequential:`, error);
597
- // Fall back to the unified tool loop on failure. runLoop re-executes
598
- // the tools from scratch, so any partial results collected above are
599
- // intentionally discarded (it builds and forces its own).
600
- const toolResult = await this.runLoop({
601
- toolCalls, context, session, history, selectedFlow,
602
- responsePrompt, availableTools, responseSchema, signal,
603
- });
604
- session = toolResult.session;
605
- toolCalls = toolResult.finalToolCalls;
606
- finalMessage = toolResult.finalMessage;
607
- structured = toolResult.structured;
698
+ logger.error(`[ToolLoopExecutor] Concurrent batch failed:`, error);
699
+ const executedRecords = records.filter((r) => r.result !== undefined);
700
+ if (executedRecords.length > 0) {
701
+ // Some tools already executed re-running them would duplicate
702
+ // real-world side effects (sends, writes, charges). Close the
703
+ // turn from the results we have instead.
704
+ logger.warn(
705
+ `[ToolLoopExecutor] ${executedRecords.length} tool(s) already executed; closing the turn from their results rather than re-executing.`
706
+ );
707
+ const forced = await this.forceFinalTextFromTools({
708
+ history,
709
+ records,
710
+ responsePrompt,
711
+ responseSchema,
712
+ context,
713
+ signal,
714
+ });
715
+ if (forced.finalMessage) {
716
+ finalMessage = forced.finalMessage;
717
+ }
718
+ structured = structured ?? forced.structured;
719
+ } else {
720
+ // Nothing executed — safe to fall back to the unified loop.
721
+ const toolResult = await this.runLoop({
722
+ toolCalls, context, session, history, selectedFlow,
723
+ responsePrompt, availableTools, responseSchema, signal,
724
+ });
725
+ session = toolResult.session;
726
+ toolCalls = toolResult.finalToolCalls;
727
+ finalMessage = toolResult.finalMessage;
728
+ structured = toolResult.structured;
729
+ if (toolResult.directives) {
730
+ collectedDirectives.length = 0;
731
+ collectedDirectives.push(toolResult.directives);
732
+ }
733
+ }
608
734
  }
609
735
 
610
- return { session, toolCalls, finalMessage, structured };
736
+ return { session, toolCalls, finalMessage, structured, directives: flow.mergeAll(collectedDirectives) };
611
737
  }
612
738
 
613
739
  /**
@@ -15,16 +15,16 @@ import type {
15
15
  ToolCallRequest,
16
16
  ToolExecutionUpdate,
17
17
  Event,
18
- } from "../types";
19
- import type { Directive } from "../types/flow";
20
- import { ToolScope } from "../types";
21
- import { logger } from "../utils";
18
+ } from "../types/index.js";
19
+ import type { Directive } from "../types/flow.js";
20
+ import { ToolScope } from "../types/index.js";
21
+ import { logger, isToolResultLike, extractResultDirectives } from "../utils/index.js";
22
22
  // Type-only import: ToolManager must not create a runtime cycle with Agent
23
- import type { Agent } from "./Agent";
24
- import { Flow } from "./Flow";
25
- import { Step } from "./Step";
26
- import { StreamingToolExecutor } from "./StreamingToolExecutor";
27
- import { evaluateToolGates } from "./toolGates";
23
+ import type { Agent } from "./Agent.js";
24
+ import { Flow } from "./Flow.js";
25
+ import { Step } from "./Step.js";
26
+ import { StreamingToolExecutor } from "./StreamingToolExecutor.js";
27
+ import { evaluateToolGates } from "./toolGates.js";
28
28
 
29
29
  /**
30
30
  * Error thrown when tool creation fails
@@ -81,7 +81,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
81
81
  * Set the transient tool layer for the current turn.
82
82
  *
83
83
  * Accepts the merged `injectTools` array from pre-LLM emitters
84
- * (already concatenated in outer-to-inner order by the DirectiveBus).
84
+ * (concatenated in outer-to-inner order).
85
85
  * Deduplicates by tool `id` with last-definition-wins.
86
86
  *
87
87
  * Must be paired with `clearTransientTools()` in a try/finally guard
@@ -678,6 +678,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
678
678
  }): Promise<ToolExecutionResult> {
679
679
  const { tool, context, updateContext, updateData, history, data, toolArguments } = params;
680
680
  const startTime = Date.now();
681
+ const executionTimeout = 30000; // 30 seconds default timeout
681
682
 
682
683
  try {
683
684
  // Validate tool before execution
@@ -725,24 +726,40 @@ export class ToolManager<TContext = unknown, TData = unknown> {
725
726
  return gateDenial;
726
727
  }
727
728
 
728
- // Execute tool with timeout protection
729
- const executionTimeout = 30000; // 30 seconds default timeout
729
+ // Execute tool with timeout protection. The timer is cleared when the
730
+ // race settles AND unref'd so a pending timer never delays process
731
+ // shutdown; a handler that loses the race keeps running detached (its
732
+ // result is discarded), which we surface in a warn.
733
+ let timeoutTimer: ReturnType<typeof setTimeout> | undefined;
730
734
  const timeoutPromise = new Promise<never>((_, reject) => {
731
- setTimeout(() => reject(new Error(`Tool execution timeout after ${executionTimeout}ms`)), executionTimeout);
735
+ timeoutTimer = setTimeout(
736
+ () => reject(new Error(`Tool execution timeout after ${executionTimeout}ms`)),
737
+ executionTimeout
738
+ );
739
+ timeoutTimer.unref?.();
732
740
  });
733
741
 
734
- const result = await Promise.race([
735
- tool.handler(toolContext, toolArguments),
736
- timeoutPromise
737
- ]);
742
+ let result: unknown;
743
+ try {
744
+ // Attach a no-op catch to the losing handler promise so a post-timeout
745
+ // rejection can't surface as an unhandled rejection and crash the process.
746
+ const handlerPromise = Promise.resolve(tool.handler(toolContext, toolArguments));
747
+ handlerPromise.catch(() => undefined);
748
+ result = await Promise.race([handlerPromise, timeoutPromise]);
749
+ } finally {
750
+ clearTimeout(timeoutTimer);
751
+ }
738
752
 
739
753
  const executionTime = Date.now() - startTime;
740
754
  logger.debug(`[ToolManager] Tool ${tool.id} completed in ${executionTime}ms`);
741
755
 
742
- // Handle different result types
756
+ // Handle different result types. Only SEMANTIC markers identify a
757
+ // ToolResult — bare `{data}` / `{error}` shapes are indistinguishable
758
+ // from ordinary business payloads (e.g. upstream API envelopes) and are
759
+ // wrapped as raw results instead.
743
760
  let toolResult: ToolResult<unknown, TContext, TData>;
744
761
 
745
- if (result && typeof result === 'object' && ('data' in result || 'success' in result || 'error' in result || 'directive' in result)) {
762
+ if (isToolResultLike(result)) {
746
763
  // It's already a ToolResult-like object
747
764
  toolResult = result as ToolResult<unknown, TContext, TData>;
748
765
  } else {
@@ -753,10 +770,9 @@ export class ToolManager<TContext = unknown, TData = unknown> {
753
770
  };
754
771
  }
755
772
 
756
- // Collect directive from ToolResult.directive (if present)
757
- if (toolResult.directive) {
758
- collectedDirectives.push(toolResult.directive);
759
- }
773
+ // Collect directives from the result — singular and plural forms both
774
+ // count, ordered identically to the concurrent executor.
775
+ collectedDirectives.push(...extractResultDirectives(toolResult));
760
776
 
761
777
  // Apply data updates from tool result with validation
762
778
  if (toolResult.dataUpdate) {
@@ -813,6 +829,15 @@ export class ToolManager<TContext = unknown, TData = unknown> {
813
829
  const executionTime = Date.now() - startTime;
814
830
 
815
831
  logger.error(`[ToolManager] Tool execution error for ${tool.id} after ${executionTime}ms:`, error);
832
+ if (error instanceof Error && error.message.includes("Tool execution timeout")) {
833
+ // The losing handler may still be running with captured callbacks.
834
+ // Its writes are NOT rolled back here — tools should stay idempotent
835
+ // or accept their own cancellation via interruptBehavior/abort.
836
+ logger.warn(
837
+ `[ToolManager] Handler for "${tool.id}" exceeded ${executionTimeout}ms and was abandoned while still running. ` +
838
+ `Its eventual side effects are not cancelled or rolled back.`
839
+ );
840
+ }
816
841
 
817
842
  // Re-throw the error so callers can handle it
818
843
  throw error;
@@ -871,9 +896,11 @@ export class ToolManager<TContext = unknown, TData = unknown> {
871
896
  return data != null && key in (data as Record<string, unknown>);
872
897
  },
873
898
  dispatch: (_directive: Directive<TContext, TData>): void => {
874
- // Directives from concurrent execution are collected by the StreamingToolExecutor
875
- // and surfaced via ToolExecutionUpdate. This is a no-op placeholder;
876
- // full directive bus integration happens in ResponsePipeline (task 1.6).
899
+ // Handlers never see THIS context StreamingToolExecutor.executeTool
900
+ // wraps each call in a per-call context whose dispatch attributes the
901
+ // directive to that tool. Reaching here means a gate or future caller
902
+ // dispatched outside a tool execution; surface it instead of dropping.
903
+ logger.warn("[ToolManager] ctx.dispatch called outside tool execution has no turn to attach to; directive dropped.");
877
904
  },
878
905
  };
879
906
 
@@ -18,8 +18,8 @@
18
18
  * **Validates: Requirements 14.1–14.7**
19
19
  */
20
20
 
21
- import { Agent } from "./Agent";
22
- import type { AgentOptions } from "../types";
21
+ import { Agent } from "./Agent.js";
22
+ import type { AgentOptions } from "../types/index.js";
23
23
 
24
24
  /**
25
25
  * Create an Agent from a single options object.