@falai/agent 3.4.5 → 4.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (865) hide show
  1. package/README.md +41 -34
  2. package/dist/cjs/core/Agent.d.ts +29 -378
  3. package/dist/cjs/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/core/Agent.js +113 -1178
  5. package/dist/cjs/core/Agent.js.map +1 -1
  6. package/dist/cjs/core/CompactionEngine.d.ts.map +1 -1
  7. package/dist/cjs/core/CompactionEngine.js +5 -3
  8. package/dist/cjs/core/CompactionEngine.js.map +1 -1
  9. package/dist/cjs/core/FlowSpec.d.ts +136 -0
  10. package/dist/cjs/core/FlowSpec.d.ts.map +1 -0
  11. package/dist/cjs/core/FlowSpec.js +573 -0
  12. package/dist/cjs/core/FlowSpec.js.map +1 -0
  13. package/dist/cjs/core/Migrate.d.ts +38 -0
  14. package/dist/cjs/core/Migrate.d.ts.map +1 -0
  15. package/dist/cjs/core/Migrate.js +270 -0
  16. package/dist/cjs/core/Migrate.js.map +1 -0
  17. package/dist/cjs/core/Prompt.d.ts +54 -0
  18. package/dist/cjs/core/Prompt.d.ts.map +1 -0
  19. package/dist/cjs/core/Prompt.js +149 -0
  20. package/dist/cjs/core/Prompt.js.map +1 -0
  21. package/dist/cjs/core/Runner.d.ts +171 -0
  22. package/dist/cjs/core/Runner.d.ts.map +1 -0
  23. package/dist/cjs/core/Runner.js +1158 -0
  24. package/dist/cjs/core/Runner.js.map +1 -0
  25. package/dist/cjs/core/Speak.d.ts +37 -0
  26. package/dist/cjs/core/Speak.d.ts.map +1 -0
  27. package/dist/cjs/core/Speak.js +373 -0
  28. package/dist/cjs/core/Speak.js.map +1 -0
  29. package/dist/cjs/core/Understand.d.ts +28 -0
  30. package/dist/cjs/core/Understand.d.ts.map +1 -0
  31. package/dist/cjs/core/Understand.js +357 -0
  32. package/dist/cjs/core/Understand.js.map +1 -0
  33. package/dist/cjs/core/contracts.d.ts +122 -0
  34. package/dist/cjs/core/contracts.d.ts.map +1 -0
  35. package/dist/cjs/core/contracts.js +11 -0
  36. package/dist/cjs/core/contracts.js.map +1 -0
  37. package/dist/cjs/core/falai.d.ts +57 -0
  38. package/dist/cjs/core/falai.d.ts.map +1 -0
  39. package/dist/cjs/core/falai.js +43 -0
  40. package/dist/cjs/core/falai.js.map +1 -0
  41. package/dist/cjs/core/predicate.d.ts +9 -0
  42. package/dist/cjs/core/predicate.d.ts.map +1 -0
  43. package/dist/cjs/core/predicate.js +58 -0
  44. package/dist/cjs/core/predicate.js.map +1 -0
  45. package/dist/cjs/index.d.ts +26 -31
  46. package/dist/cjs/index.d.ts.map +1 -1
  47. package/dist/cjs/index.js +46 -68
  48. package/dist/cjs/index.js.map +1 -1
  49. package/dist/cjs/persistence/MemoryStore.d.ts +15 -0
  50. package/dist/cjs/persistence/MemoryStore.d.ts.map +1 -0
  51. package/dist/cjs/persistence/MemoryStore.js +39 -0
  52. package/dist/cjs/persistence/MemoryStore.js.map +1 -0
  53. package/dist/cjs/persistence/MongoStore.d.ts +42 -0
  54. package/dist/cjs/persistence/MongoStore.d.ts.map +1 -0
  55. package/dist/cjs/persistence/MongoStore.js +60 -0
  56. package/dist/cjs/persistence/MongoStore.js.map +1 -0
  57. package/dist/cjs/persistence/OpenSearchStore.d.ts +86 -0
  58. package/dist/cjs/persistence/OpenSearchStore.d.ts.map +1 -0
  59. package/dist/cjs/persistence/OpenSearchStore.js +120 -0
  60. package/dist/cjs/persistence/OpenSearchStore.js.map +1 -0
  61. package/dist/cjs/persistence/PostgresStore.d.ts +41 -0
  62. package/dist/cjs/persistence/PostgresStore.d.ts.map +1 -0
  63. package/dist/cjs/persistence/PostgresStore.js +58 -0
  64. package/dist/cjs/persistence/PostgresStore.js.map +1 -0
  65. package/dist/cjs/persistence/PrismaStore.d.ts +65 -0
  66. package/dist/cjs/persistence/PrismaStore.d.ts.map +1 -0
  67. package/dist/cjs/persistence/PrismaStore.js +95 -0
  68. package/dist/cjs/persistence/PrismaStore.js.map +1 -0
  69. package/dist/cjs/persistence/RedisStore.d.ts +34 -0
  70. package/dist/cjs/persistence/RedisStore.d.ts.map +1 -0
  71. package/dist/cjs/persistence/RedisStore.js +61 -0
  72. package/dist/cjs/persistence/RedisStore.js.map +1 -0
  73. package/dist/cjs/persistence/SQLiteStore.d.ts +45 -0
  74. package/dist/cjs/persistence/SQLiteStore.d.ts.map +1 -0
  75. package/dist/cjs/persistence/SQLiteStore.js +74 -0
  76. package/dist/cjs/persistence/SQLiteStore.js.map +1 -0
  77. package/dist/cjs/persistence/sessionRow.d.ts +14 -0
  78. package/dist/cjs/persistence/sessionRow.d.ts.map +1 -0
  79. package/dist/cjs/persistence/sessionRow.js +50 -0
  80. package/dist/cjs/persistence/sessionRow.js.map +1 -0
  81. package/dist/cjs/providers/DeepSeekProvider.d.ts.map +1 -1
  82. package/dist/cjs/providers/DeepSeekProvider.js +8 -3
  83. package/dist/cjs/providers/DeepSeekProvider.js.map +1 -1
  84. package/dist/cjs/providers/GeminiProvider.d.ts +4 -3
  85. package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
  86. package/dist/cjs/providers/GeminiProvider.js +4 -3
  87. package/dist/cjs/providers/GeminiProvider.js.map +1 -1
  88. package/dist/cjs/providers/OpenAICompatibleProvider.d.ts +4 -0
  89. package/dist/cjs/providers/OpenAICompatibleProvider.d.ts.map +1 -1
  90. package/dist/cjs/providers/OpenAICompatibleProvider.js +2 -0
  91. package/dist/cjs/providers/OpenAICompatibleProvider.js.map +1 -1
  92. package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
  93. package/dist/cjs/providers/OpenRouterProvider.js +2 -4
  94. package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
  95. package/dist/cjs/providers/ProviderAdapter.d.ts +11 -6
  96. package/dist/cjs/providers/ProviderAdapter.d.ts.map +1 -1
  97. package/dist/cjs/providers/ProviderAdapter.js +33 -10
  98. package/dist/cjs/providers/ProviderAdapter.js.map +1 -1
  99. package/dist/cjs/providers/ZaiProvider.d.ts +6 -4
  100. package/dist/cjs/providers/ZaiProvider.d.ts.map +1 -1
  101. package/dist/cjs/providers/ZaiProvider.js +6 -4
  102. package/dist/cjs/providers/ZaiProvider.js.map +1 -1
  103. package/dist/cjs/types/agent.d.ts +163 -383
  104. package/dist/cjs/types/agent.d.ts.map +1 -1
  105. package/dist/cjs/types/agent.js +1 -1
  106. package/dist/cjs/types/ai.d.ts +32 -1
  107. package/dist/cjs/types/ai.d.ts.map +1 -1
  108. package/dist/cjs/types/compaction.d.ts +3 -1
  109. package/dist/cjs/types/compaction.d.ts.map +1 -1
  110. package/dist/cjs/types/errors.d.ts +9 -12
  111. package/dist/cjs/types/errors.d.ts.map +1 -1
  112. package/dist/cjs/types/errors.js +14 -17
  113. package/dist/cjs/types/errors.js.map +1 -1
  114. package/dist/cjs/types/flow.d.ts +265 -513
  115. package/dist/cjs/types/flow.d.ts.map +1 -1
  116. package/dist/cjs/types/flow.js +7 -1
  117. package/dist/cjs/types/flow.js.map +1 -1
  118. package/dist/cjs/types/history.d.ts +7 -18
  119. package/dist/cjs/types/history.d.ts.map +1 -1
  120. package/dist/cjs/types/history.js.map +1 -1
  121. package/dist/cjs/types/index.d.ts +9 -15
  122. package/dist/cjs/types/index.d.ts.map +1 -1
  123. package/dist/cjs/types/index.js +4 -14
  124. package/dist/cjs/types/index.js.map +1 -1
  125. package/dist/cjs/types/session.d.ts +94 -64
  126. package/dist/cjs/types/session.d.ts.map +1 -1
  127. package/dist/cjs/types/session.js +5 -1
  128. package/dist/cjs/types/session.js.map +1 -1
  129. package/dist/cjs/types/tool.d.ts +37 -207
  130. package/dist/cjs/types/tool.d.ts.map +1 -1
  131. package/dist/cjs/types/tool.js +5 -14
  132. package/dist/cjs/types/tool.js.map +1 -1
  133. package/dist/cjs/utils/clock.d.ts +28 -0
  134. package/dist/cjs/utils/clock.d.ts.map +1 -0
  135. package/dist/cjs/utils/clock.js +64 -0
  136. package/dist/cjs/utils/clock.js.map +1 -0
  137. package/dist/cjs/utils/duration.d.ts +11 -0
  138. package/dist/cjs/utils/duration.d.ts.map +1 -0
  139. package/dist/cjs/utils/duration.js +31 -0
  140. package/dist/cjs/utils/duration.js.map +1 -0
  141. package/dist/cjs/utils/history.d.ts +4 -1
  142. package/dist/cjs/utils/history.d.ts.map +1 -1
  143. package/dist/cjs/utils/history.js +2 -2
  144. package/dist/cjs/utils/history.js.map +1 -1
  145. package/dist/cjs/utils/index.d.ts +4 -10
  146. package/dist/cjs/utils/index.d.ts.map +1 -1
  147. package/dist/cjs/utils/index.js +14 -61
  148. package/dist/cjs/utils/index.js.map +1 -1
  149. package/dist/cjs/utils/json.d.ts +2 -0
  150. package/dist/cjs/utils/json.d.ts.map +1 -1
  151. package/dist/cjs/utils/json.js +5 -0
  152. package/dist/cjs/utils/json.js.map +1 -1
  153. package/dist/cjs/utils/outcomes.d.ts +48 -0
  154. package/dist/cjs/utils/outcomes.d.ts.map +1 -0
  155. package/dist/cjs/utils/outcomes.js +51 -0
  156. package/dist/cjs/utils/outcomes.js.map +1 -0
  157. package/dist/cjs/utils/phrases.d.ts +25 -0
  158. package/dist/cjs/utils/phrases.d.ts.map +1 -0
  159. package/dist/cjs/utils/phrases.js +38 -0
  160. package/dist/cjs/utils/phrases.js.map +1 -0
  161. package/dist/cjs/utils/schema.d.ts +50 -0
  162. package/dist/cjs/utils/schema.d.ts.map +1 -0
  163. package/dist/cjs/utils/schema.js +138 -0
  164. package/dist/cjs/utils/schema.js.map +1 -0
  165. package/dist/cjs/utils/streamingMessage.d.ts +3 -2
  166. package/dist/cjs/utils/streamingMessage.d.ts.map +1 -1
  167. package/dist/cjs/utils/streamingMessage.js +38 -4
  168. package/dist/cjs/utils/streamingMessage.js.map +1 -1
  169. package/dist/cjs/utils/template.d.ts +22 -150
  170. package/dist/cjs/utils/template.d.ts.map +1 -1
  171. package/dist/cjs/utils/template.js +64 -359
  172. package/dist/cjs/utils/template.js.map +1 -1
  173. package/dist/cjs/utils/usage.d.ts +19 -0
  174. package/dist/cjs/utils/usage.d.ts.map +1 -0
  175. package/dist/cjs/utils/usage.js +35 -0
  176. package/dist/cjs/utils/usage.js.map +1 -0
  177. package/dist/core/Agent.d.ts +29 -378
  178. package/dist/core/Agent.d.ts.map +1 -1
  179. package/dist/core/Agent.js +116 -1181
  180. package/dist/core/Agent.js.map +1 -1
  181. package/dist/core/CompactionEngine.d.ts.map +1 -1
  182. package/dist/core/CompactionEngine.js +5 -3
  183. package/dist/core/CompactionEngine.js.map +1 -1
  184. package/dist/core/FlowSpec.d.ts +136 -0
  185. package/dist/core/FlowSpec.d.ts.map +1 -0
  186. package/dist/core/FlowSpec.js +567 -0
  187. package/dist/core/FlowSpec.js.map +1 -0
  188. package/dist/core/Migrate.d.ts +38 -0
  189. package/dist/core/Migrate.d.ts.map +1 -0
  190. package/dist/core/Migrate.js +264 -0
  191. package/dist/core/Migrate.js.map +1 -0
  192. package/dist/core/Prompt.d.ts +54 -0
  193. package/dist/core/Prompt.d.ts.map +1 -0
  194. package/dist/core/Prompt.js +139 -0
  195. package/dist/core/Prompt.js.map +1 -0
  196. package/dist/core/Runner.d.ts +171 -0
  197. package/dist/core/Runner.d.ts.map +1 -0
  198. package/dist/core/Runner.js +1154 -0
  199. package/dist/core/Runner.js.map +1 -0
  200. package/dist/core/Speak.d.ts +37 -0
  201. package/dist/core/Speak.d.ts.map +1 -0
  202. package/dist/core/Speak.js +369 -0
  203. package/dist/core/Speak.js.map +1 -0
  204. package/dist/core/Understand.d.ts +28 -0
  205. package/dist/core/Understand.d.ts.map +1 -0
  206. package/dist/core/Understand.js +353 -0
  207. package/dist/core/Understand.js.map +1 -0
  208. package/dist/core/contracts.d.ts +122 -0
  209. package/dist/core/contracts.d.ts.map +1 -0
  210. package/dist/core/contracts.js +10 -0
  211. package/dist/core/contracts.js.map +1 -0
  212. package/dist/core/falai.d.ts +57 -0
  213. package/dist/core/falai.d.ts.map +1 -0
  214. package/dist/core/falai.js +40 -0
  215. package/dist/core/falai.js.map +1 -0
  216. package/dist/core/predicate.d.ts +9 -0
  217. package/dist/core/predicate.d.ts.map +1 -0
  218. package/dist/core/predicate.js +54 -0
  219. package/dist/core/predicate.js.map +1 -0
  220. package/dist/index.d.ts +26 -31
  221. package/dist/index.d.ts.map +1 -1
  222. package/dist/index.js +19 -24
  223. package/dist/index.js.map +1 -1
  224. package/dist/persistence/MemoryStore.d.ts +15 -0
  225. package/dist/persistence/MemoryStore.d.ts.map +1 -0
  226. package/dist/persistence/MemoryStore.js +35 -0
  227. package/dist/persistence/MemoryStore.js.map +1 -0
  228. package/dist/persistence/MongoStore.d.ts +42 -0
  229. package/dist/persistence/MongoStore.d.ts.map +1 -0
  230. package/dist/persistence/MongoStore.js +56 -0
  231. package/dist/persistence/MongoStore.js.map +1 -0
  232. package/dist/persistence/OpenSearchStore.d.ts +86 -0
  233. package/dist/persistence/OpenSearchStore.d.ts.map +1 -0
  234. package/dist/persistence/OpenSearchStore.js +116 -0
  235. package/dist/persistence/OpenSearchStore.js.map +1 -0
  236. package/dist/persistence/PostgresStore.d.ts +41 -0
  237. package/dist/persistence/PostgresStore.d.ts.map +1 -0
  238. package/dist/persistence/PostgresStore.js +54 -0
  239. package/dist/persistence/PostgresStore.js.map +1 -0
  240. package/dist/persistence/PrismaStore.d.ts +65 -0
  241. package/dist/persistence/PrismaStore.d.ts.map +1 -0
  242. package/dist/persistence/PrismaStore.js +91 -0
  243. package/dist/persistence/PrismaStore.js.map +1 -0
  244. package/dist/persistence/RedisStore.d.ts +34 -0
  245. package/dist/persistence/RedisStore.d.ts.map +1 -0
  246. package/dist/persistence/RedisStore.js +57 -0
  247. package/dist/persistence/RedisStore.js.map +1 -0
  248. package/dist/persistence/SQLiteStore.d.ts +45 -0
  249. package/dist/persistence/SQLiteStore.d.ts.map +1 -0
  250. package/dist/persistence/SQLiteStore.js +70 -0
  251. package/dist/persistence/SQLiteStore.js.map +1 -0
  252. package/dist/persistence/sessionRow.d.ts +14 -0
  253. package/dist/persistence/sessionRow.d.ts.map +1 -0
  254. package/dist/persistence/sessionRow.js +45 -0
  255. package/dist/persistence/sessionRow.js.map +1 -0
  256. package/dist/providers/DeepSeekProvider.d.ts.map +1 -1
  257. package/dist/providers/DeepSeekProvider.js +8 -3
  258. package/dist/providers/DeepSeekProvider.js.map +1 -1
  259. package/dist/providers/GeminiProvider.d.ts +4 -3
  260. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  261. package/dist/providers/GeminiProvider.js +4 -3
  262. package/dist/providers/GeminiProvider.js.map +1 -1
  263. package/dist/providers/OpenAICompatibleProvider.d.ts +4 -0
  264. package/dist/providers/OpenAICompatibleProvider.d.ts.map +1 -1
  265. package/dist/providers/OpenAICompatibleProvider.js +2 -0
  266. package/dist/providers/OpenAICompatibleProvider.js.map +1 -1
  267. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  268. package/dist/providers/OpenRouterProvider.js +2 -4
  269. package/dist/providers/OpenRouterProvider.js.map +1 -1
  270. package/dist/providers/ProviderAdapter.d.ts +11 -6
  271. package/dist/providers/ProviderAdapter.d.ts.map +1 -1
  272. package/dist/providers/ProviderAdapter.js +34 -11
  273. package/dist/providers/ProviderAdapter.js.map +1 -1
  274. package/dist/providers/ZaiProvider.d.ts +6 -4
  275. package/dist/providers/ZaiProvider.d.ts.map +1 -1
  276. package/dist/providers/ZaiProvider.js +6 -4
  277. package/dist/providers/ZaiProvider.js.map +1 -1
  278. package/dist/types/agent.d.ts +163 -383
  279. package/dist/types/agent.d.ts.map +1 -1
  280. package/dist/types/agent.js +1 -1
  281. package/dist/types/ai.d.ts +32 -1
  282. package/dist/types/ai.d.ts.map +1 -1
  283. package/dist/types/compaction.d.ts +3 -1
  284. package/dist/types/compaction.d.ts.map +1 -1
  285. package/dist/types/errors.d.ts +9 -12
  286. package/dist/types/errors.d.ts.map +1 -1
  287. package/dist/types/errors.js +12 -15
  288. package/dist/types/errors.js.map +1 -1
  289. package/dist/types/flow.d.ts +265 -513
  290. package/dist/types/flow.d.ts.map +1 -1
  291. package/dist/types/flow.js +7 -1
  292. package/dist/types/flow.js.map +1 -1
  293. package/dist/types/history.d.ts +7 -18
  294. package/dist/types/history.d.ts.map +1 -1
  295. package/dist/types/history.js.map +1 -1
  296. package/dist/types/index.d.ts +9 -15
  297. package/dist/types/index.d.ts.map +1 -1
  298. package/dist/types/index.js +2 -7
  299. package/dist/types/index.js.map +1 -1
  300. package/dist/types/session.d.ts +94 -64
  301. package/dist/types/session.d.ts.map +1 -1
  302. package/dist/types/session.js +5 -1
  303. package/dist/types/session.js.map +1 -1
  304. package/dist/types/tool.d.ts +37 -207
  305. package/dist/types/tool.d.ts.map +1 -1
  306. package/dist/types/tool.js +6 -13
  307. package/dist/types/tool.js.map +1 -1
  308. package/dist/utils/clock.d.ts +28 -0
  309. package/dist/utils/clock.d.ts.map +1 -0
  310. package/dist/utils/clock.js +59 -0
  311. package/dist/utils/clock.js.map +1 -0
  312. package/dist/utils/duration.d.ts +11 -0
  313. package/dist/utils/duration.d.ts.map +1 -0
  314. package/dist/utils/duration.js +26 -0
  315. package/dist/utils/duration.js.map +1 -0
  316. package/dist/utils/history.d.ts +4 -1
  317. package/dist/utils/history.d.ts.map +1 -1
  318. package/dist/utils/history.js +2 -2
  319. package/dist/utils/history.js.map +1 -1
  320. package/dist/utils/index.d.ts +4 -10
  321. package/dist/utils/index.d.ts.map +1 -1
  322. package/dist/utils/index.js +4 -21
  323. package/dist/utils/index.js.map +1 -1
  324. package/dist/utils/json.d.ts +2 -0
  325. package/dist/utils/json.d.ts.map +1 -1
  326. package/dist/utils/json.js +4 -0
  327. package/dist/utils/json.js.map +1 -1
  328. package/dist/utils/outcomes.d.ts +48 -0
  329. package/dist/utils/outcomes.d.ts.map +1 -0
  330. package/dist/utils/outcomes.js +48 -0
  331. package/dist/utils/outcomes.js.map +1 -0
  332. package/dist/utils/phrases.d.ts +25 -0
  333. package/dist/utils/phrases.d.ts.map +1 -0
  334. package/dist/utils/phrases.js +35 -0
  335. package/dist/utils/phrases.js.map +1 -0
  336. package/dist/utils/schema.d.ts +50 -0
  337. package/dist/utils/schema.d.ts.map +1 -0
  338. package/dist/utils/schema.js +129 -0
  339. package/dist/utils/schema.js.map +1 -0
  340. package/dist/utils/streamingMessage.d.ts +3 -2
  341. package/dist/utils/streamingMessage.d.ts.map +1 -1
  342. package/dist/utils/streamingMessage.js +38 -4
  343. package/dist/utils/streamingMessage.js.map +1 -1
  344. package/dist/utils/template.d.ts +22 -150
  345. package/dist/utils/template.d.ts.map +1 -1
  346. package/dist/utils/template.js +61 -351
  347. package/dist/utils/template.js.map +1 -1
  348. package/dist/utils/usage.d.ts +19 -0
  349. package/dist/utils/usage.d.ts.map +1 -0
  350. package/dist/utils/usage.js +31 -0
  351. package/dist/utils/usage.js.map +1 -0
  352. package/docs/README.md +37 -19
  353. package/docs/concepts/architecture.md +117 -239
  354. package/docs/concepts/collection.md +170 -0
  355. package/docs/concepts/pipeline.md +132 -378
  356. package/docs/concepts/runs-and-waits.md +192 -0
  357. package/docs/guides/actions-and-events.md +276 -0
  358. package/docs/guides/branching.md +119 -208
  359. package/docs/guides/compaction.md +63 -158
  360. package/docs/guides/conditions.md +164 -128
  361. package/docs/guides/error-handling.md +170 -164
  362. package/docs/guides/flow-control.md +210 -349
  363. package/docs/guides/flows-from-json.md +224 -0
  364. package/docs/guides/instructions.md +125 -161
  365. package/docs/guides/persistence.md +182 -206
  366. package/docs/guides/streaming.md +50 -114
  367. package/docs/guides/testing.md +284 -0
  368. package/docs/guides/triggers.md +401 -0
  369. package/docs/migration/README.md +8 -15
  370. package/docs/migration/v1-to-v2.md +1 -1
  371. package/docs/migration/v2-3-to-v2-4.md +2 -2
  372. package/docs/migration/v2-6-to-v2-7.md +4 -4
  373. package/docs/migration/v3-to-v4.md +457 -0
  374. package/docs/reference/actions-events-conditions.md +396 -0
  375. package/docs/reference/agent.md +248 -0
  376. package/docs/reference/branches.md +75 -203
  377. package/docs/reference/errors.md +188 -144
  378. package/docs/reference/fields.md +125 -0
  379. package/docs/reference/flow-spec.md +248 -0
  380. package/docs/reference/flow.md +104 -192
  381. package/docs/reference/instruction.md +83 -137
  382. package/docs/reference/outcomes.md +273 -0
  383. package/docs/reference/providers.md +525 -302
  384. package/docs/reference/session.md +210 -0
  385. package/docs/reference/step.md +194 -312
  386. package/docs/reference/stores.md +496 -0
  387. package/docs/reference/tool.md +162 -231
  388. package/docs/reference/trigger.md +200 -0
  389. package/docs/rfc/v4-one-flow.md +477 -0
  390. package/docs/start/01-install.md +59 -44
  391. package/docs/start/02-first-agent.md +97 -147
  392. package/docs/start/03-collect-data.md +78 -183
  393. package/docs/start/04-add-tools.md +159 -227
  394. package/docs/start/05-go-to-production.md +181 -163
  395. package/examples/01-quickstart.ts +26 -16
  396. package/examples/02-fields.ts +75 -0
  397. package/examples/03-tools.ts +79 -119
  398. package/examples/04-instructions.ts +60 -87
  399. package/examples/05-branches.ts +78 -0
  400. package/examples/06-triggers-and-waits.ts +149 -0
  401. package/examples/07-streaming.ts +34 -60
  402. package/examples/08-store-and-migration.ts +97 -0
  403. package/examples/09-flows-from-json.ts +107 -0
  404. package/package.json +11 -6
  405. package/src/core/Agent.ts +126 -1512
  406. package/src/core/CompactionEngine.ts +7 -4
  407. package/src/core/FlowSpec.ts +778 -0
  408. package/src/core/Migrate.ts +256 -0
  409. package/src/core/Prompt.ts +162 -0
  410. package/src/core/Runner.ts +1214 -0
  411. package/src/core/Speak.ts +460 -0
  412. package/src/core/Understand.ts +423 -0
  413. package/src/core/contracts.ts +111 -0
  414. package/src/core/falai.ts +86 -0
  415. package/src/core/predicate.ts +56 -0
  416. package/src/index.ts +120 -147
  417. package/src/persistence/MemoryStore.ts +37 -0
  418. package/src/persistence/MongoStore.ts +89 -0
  419. package/src/persistence/OpenSearchStore.ts +153 -0
  420. package/src/persistence/PostgresStore.ts +89 -0
  421. package/src/persistence/PrismaStore.ts +127 -0
  422. package/src/persistence/RedisStore.ts +90 -0
  423. package/src/persistence/SQLiteStore.ts +103 -0
  424. package/src/persistence/sessionRow.ts +45 -0
  425. package/src/providers/DeepSeekProvider.ts +8 -3
  426. package/src/providers/GeminiProvider.ts +4 -3
  427. package/src/providers/OpenAICompatibleProvider.ts +6 -0
  428. package/src/providers/OpenRouterProvider.ts +2 -4
  429. package/src/providers/ProviderAdapter.ts +46 -13
  430. package/src/providers/ZaiProvider.ts +6 -4
  431. package/src/types/agent.ts +135 -397
  432. package/src/types/ai.ts +33 -1
  433. package/src/types/compaction.ts +3 -1
  434. package/src/types/errors.ts +13 -16
  435. package/src/types/flow.ts +249 -550
  436. package/src/types/history.ts +7 -20
  437. package/src/types/index.ts +88 -139
  438. package/src/types/session.ts +135 -70
  439. package/src/types/tool.ts +42 -267
  440. package/src/utils/clock.ts +70 -0
  441. package/src/utils/duration.ts +33 -0
  442. package/src/utils/history.ts +3 -2
  443. package/src/utils/index.ts +8 -66
  444. package/src/utils/json.ts +5 -0
  445. package/src/utils/outcomes.ts +56 -0
  446. package/src/utils/phrases.ts +40 -0
  447. package/src/utils/schema.ts +145 -0
  448. package/src/utils/streamingMessage.ts +34 -4
  449. package/src/utils/template.ts +63 -418
  450. package/src/utils/usage.ts +37 -0
  451. package/dist/adapters/MemoryAdapter.d.ts +0 -47
  452. package/dist/adapters/MemoryAdapter.d.ts.map +0 -1
  453. package/dist/adapters/MemoryAdapter.js +0 -204
  454. package/dist/adapters/MemoryAdapter.js.map +0 -1
  455. package/dist/adapters/MongoAdapter.d.ts +0 -97
  456. package/dist/adapters/MongoAdapter.d.ts.map +0 -1
  457. package/dist/adapters/MongoAdapter.js +0 -196
  458. package/dist/adapters/MongoAdapter.js.map +0 -1
  459. package/dist/adapters/OpenSearchAdapter.d.ts +0 -169
  460. package/dist/adapters/OpenSearchAdapter.d.ts.map +0 -1
  461. package/dist/adapters/OpenSearchAdapter.js +0 -471
  462. package/dist/adapters/OpenSearchAdapter.js.map +0 -1
  463. package/dist/adapters/PostgreSQLAdapter.d.ts +0 -85
  464. package/dist/adapters/PostgreSQLAdapter.d.ts.map +0 -1
  465. package/dist/adapters/PostgreSQLAdapter.js +0 -308
  466. package/dist/adapters/PostgreSQLAdapter.js.map +0 -1
  467. package/dist/adapters/PrismaAdapter.d.ts +0 -115
  468. package/dist/adapters/PrismaAdapter.d.ts.map +0 -1
  469. package/dist/adapters/PrismaAdapter.js +0 -406
  470. package/dist/adapters/PrismaAdapter.js.map +0 -1
  471. package/dist/adapters/RedisAdapter.d.ts +0 -72
  472. package/dist/adapters/RedisAdapter.d.ts.map +0 -1
  473. package/dist/adapters/RedisAdapter.js +0 -286
  474. package/dist/adapters/RedisAdapter.js.map +0 -1
  475. package/dist/adapters/SQLiteAdapter.d.ts +0 -86
  476. package/dist/adapters/SQLiteAdapter.d.ts.map +0 -1
  477. package/dist/adapters/SQLiteAdapter.js +0 -337
  478. package/dist/adapters/SQLiteAdapter.js.map +0 -1
  479. package/dist/adapters/index.d.ts +0 -17
  480. package/dist/adapters/index.d.ts.map +0 -1
  481. package/dist/adapters/index.js +0 -11
  482. package/dist/adapters/index.js.map +0 -1
  483. package/dist/adapters/sessionRow.d.ts +0 -22
  484. package/dist/adapters/sessionRow.d.ts.map +0 -1
  485. package/dist/adapters/sessionRow.js +0 -48
  486. package/dist/adapters/sessionRow.js.map +0 -1
  487. package/dist/cjs/adapters/MemoryAdapter.d.ts +0 -47
  488. package/dist/cjs/adapters/MemoryAdapter.d.ts.map +0 -1
  489. package/dist/cjs/adapters/MemoryAdapter.js +0 -208
  490. package/dist/cjs/adapters/MemoryAdapter.js.map +0 -1
  491. package/dist/cjs/adapters/MongoAdapter.d.ts +0 -97
  492. package/dist/cjs/adapters/MongoAdapter.d.ts.map +0 -1
  493. package/dist/cjs/adapters/MongoAdapter.js +0 -200
  494. package/dist/cjs/adapters/MongoAdapter.js.map +0 -1
  495. package/dist/cjs/adapters/OpenSearchAdapter.d.ts +0 -169
  496. package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +0 -1
  497. package/dist/cjs/adapters/OpenSearchAdapter.js +0 -475
  498. package/dist/cjs/adapters/OpenSearchAdapter.js.map +0 -1
  499. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts +0 -85
  500. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +0 -1
  501. package/dist/cjs/adapters/PostgreSQLAdapter.js +0 -312
  502. package/dist/cjs/adapters/PostgreSQLAdapter.js.map +0 -1
  503. package/dist/cjs/adapters/PrismaAdapter.d.ts +0 -115
  504. package/dist/cjs/adapters/PrismaAdapter.d.ts.map +0 -1
  505. package/dist/cjs/adapters/PrismaAdapter.js +0 -410
  506. package/dist/cjs/adapters/PrismaAdapter.js.map +0 -1
  507. package/dist/cjs/adapters/RedisAdapter.d.ts +0 -72
  508. package/dist/cjs/adapters/RedisAdapter.d.ts.map +0 -1
  509. package/dist/cjs/adapters/RedisAdapter.js +0 -290
  510. package/dist/cjs/adapters/RedisAdapter.js.map +0 -1
  511. package/dist/cjs/adapters/SQLiteAdapter.d.ts +0 -86
  512. package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +0 -1
  513. package/dist/cjs/adapters/SQLiteAdapter.js +0 -341
  514. package/dist/cjs/adapters/SQLiteAdapter.js.map +0 -1
  515. package/dist/cjs/adapters/index.d.ts +0 -17
  516. package/dist/cjs/adapters/index.d.ts.map +0 -1
  517. package/dist/cjs/adapters/index.js +0 -21
  518. package/dist/cjs/adapters/index.js.map +0 -1
  519. package/dist/cjs/adapters/sessionRow.d.ts +0 -22
  520. package/dist/cjs/adapters/sessionRow.d.ts.map +0 -1
  521. package/dist/cjs/adapters/sessionRow.js +0 -52
  522. package/dist/cjs/adapters/sessionRow.js.map +0 -1
  523. package/dist/cjs/constants/index.d.ts +0 -1
  524. package/dist/cjs/constants/index.d.ts.map +0 -1
  525. package/dist/cjs/constants/index.js +0 -4
  526. package/dist/cjs/constants/index.js.map +0 -1
  527. package/dist/cjs/core/AutoChainExecutor.d.ts +0 -97
  528. package/dist/cjs/core/AutoChainExecutor.d.ts.map +0 -1
  529. package/dist/cjs/core/AutoChainExecutor.js +0 -288
  530. package/dist/cjs/core/AutoChainExecutor.js.map +0 -1
  531. package/dist/cjs/core/BranchEvaluator.d.ts +0 -55
  532. package/dist/cjs/core/BranchEvaluator.d.ts.map +0 -1
  533. package/dist/cjs/core/BranchEvaluator.js +0 -125
  534. package/dist/cjs/core/BranchEvaluator.js.map +0 -1
  535. package/dist/cjs/core/DirectiveChainTracker.d.ts +0 -49
  536. package/dist/cjs/core/DirectiveChainTracker.d.ts.map +0 -1
  537. package/dist/cjs/core/DirectiveChainTracker.js +0 -121
  538. package/dist/cjs/core/DirectiveChainTracker.js.map +0 -1
  539. package/dist/cjs/core/Events.d.ts +0 -26
  540. package/dist/cjs/core/Events.d.ts.map +0 -1
  541. package/dist/cjs/core/Events.js +0 -144
  542. package/dist/cjs/core/Events.js.map +0 -1
  543. package/dist/cjs/core/Flow.d.ts +0 -183
  544. package/dist/cjs/core/Flow.d.ts.map +0 -1
  545. package/dist/cjs/core/Flow.js +0 -551
  546. package/dist/cjs/core/Flow.js.map +0 -1
  547. package/dist/cjs/core/FlowRouter.d.ts +0 -183
  548. package/dist/cjs/core/FlowRouter.d.ts.map +0 -1
  549. package/dist/cjs/core/FlowRouter.js +0 -1047
  550. package/dist/cjs/core/FlowRouter.js.map +0 -1
  551. package/dist/cjs/core/PersistenceManager.d.ts +0 -114
  552. package/dist/cjs/core/PersistenceManager.d.ts.map +0 -1
  553. package/dist/cjs/core/PersistenceManager.js +0 -336
  554. package/dist/cjs/core/PersistenceManager.js.map +0 -1
  555. package/dist/cjs/core/PromptComposer.d.ts +0 -47
  556. package/dist/cjs/core/PromptComposer.d.ts.map +0 -1
  557. package/dist/cjs/core/PromptComposer.js +0 -397
  558. package/dist/cjs/core/PromptComposer.js.map +0 -1
  559. package/dist/cjs/core/PromptSectionCache.d.ts +0 -48
  560. package/dist/cjs/core/PromptSectionCache.d.ts.map +0 -1
  561. package/dist/cjs/core/PromptSectionCache.js +0 -108
  562. package/dist/cjs/core/PromptSectionCache.js.map +0 -1
  563. package/dist/cjs/core/ResponseEngine.d.ts +0 -43
  564. package/dist/cjs/core/ResponseEngine.d.ts.map +0 -1
  565. package/dist/cjs/core/ResponseEngine.js +0 -235
  566. package/dist/cjs/core/ResponseEngine.js.map +0 -1
  567. package/dist/cjs/core/ResponseGenerationError.d.ts +0 -30
  568. package/dist/cjs/core/ResponseGenerationError.d.ts.map +0 -1
  569. package/dist/cjs/core/ResponseGenerationError.js +0 -35
  570. package/dist/cjs/core/ResponseGenerationError.js.map +0 -1
  571. package/dist/cjs/core/ResponseModal.d.ts +0 -305
  572. package/dist/cjs/core/ResponseModal.d.ts.map +0 -1
  573. package/dist/cjs/core/ResponseModal.js +0 -1414
  574. package/dist/cjs/core/ResponseModal.js.map +0 -1
  575. package/dist/cjs/core/ResponsePipeline.d.ts +0 -220
  576. package/dist/cjs/core/ResponsePipeline.d.ts.map +0 -1
  577. package/dist/cjs/core/ResponsePipeline.js +0 -1040
  578. package/dist/cjs/core/ResponsePipeline.js.map +0 -1
  579. package/dist/cjs/core/SessionFinalizer.d.ts +0 -34
  580. package/dist/cjs/core/SessionFinalizer.d.ts.map +0 -1
  581. package/dist/cjs/core/SessionFinalizer.js +0 -88
  582. package/dist/cjs/core/SessionFinalizer.js.map +0 -1
  583. package/dist/cjs/core/SessionManager.d.ts +0 -112
  584. package/dist/cjs/core/SessionManager.d.ts.map +0 -1
  585. package/dist/cjs/core/SessionManager.js +0 -308
  586. package/dist/cjs/core/SessionManager.js.map +0 -1
  587. package/dist/cjs/core/SignalCoordinator.d.ts +0 -103
  588. package/dist/cjs/core/SignalCoordinator.d.ts.map +0 -1
  589. package/dist/cjs/core/SignalCoordinator.js +0 -207
  590. package/dist/cjs/core/SignalCoordinator.js.map +0 -1
  591. package/dist/cjs/core/SignalEvaluator.d.ts +0 -86
  592. package/dist/cjs/core/SignalEvaluator.d.ts.map +0 -1
  593. package/dist/cjs/core/SignalEvaluator.js +0 -319
  594. package/dist/cjs/core/SignalEvaluator.js.map +0 -1
  595. package/dist/cjs/core/SignalProcessor.d.ts +0 -152
  596. package/dist/cjs/core/SignalProcessor.d.ts.map +0 -1
  597. package/dist/cjs/core/SignalProcessor.js +0 -505
  598. package/dist/cjs/core/SignalProcessor.js.map +0 -1
  599. package/dist/cjs/core/Step.d.ts +0 -184
  600. package/dist/cjs/core/Step.d.ts.map +0 -1
  601. package/dist/cjs/core/Step.js +0 -599
  602. package/dist/cjs/core/Step.js.map +0 -1
  603. package/dist/cjs/core/StepLifecycle.d.ts +0 -43
  604. package/dist/cjs/core/StepLifecycle.d.ts.map +0 -1
  605. package/dist/cjs/core/StepLifecycle.js +0 -180
  606. package/dist/cjs/core/StepLifecycle.js.map +0 -1
  607. package/dist/cjs/core/StreamingToolExecutor.d.ts +0 -142
  608. package/dist/cjs/core/StreamingToolExecutor.d.ts.map +0 -1
  609. package/dist/cjs/core/StreamingToolExecutor.js +0 -490
  610. package/dist/cjs/core/StreamingToolExecutor.js.map +0 -1
  611. package/dist/cjs/core/ToolLoopExecutor.d.ts +0 -133
  612. package/dist/cjs/core/ToolLoopExecutor.d.ts.map +0 -1
  613. package/dist/cjs/core/ToolLoopExecutor.js +0 -568
  614. package/dist/cjs/core/ToolLoopExecutor.js.map +0 -1
  615. package/dist/cjs/core/ToolManager.d.ts +0 -250
  616. package/dist/cjs/core/ToolManager.d.ts.map +0 -1
  617. package/dist/cjs/core/ToolManager.js +0 -1104
  618. package/dist/cjs/core/ToolManager.js.map +0 -1
  619. package/dist/cjs/core/createAgent.d.ts +0 -35
  620. package/dist/cjs/core/createAgent.d.ts.map +0 -1
  621. package/dist/cjs/core/createAgent.js +0 -39
  622. package/dist/cjs/core/createAgent.js.map +0 -1
  623. package/dist/cjs/core/flow-namespace.d.ts +0 -64
  624. package/dist/cjs/core/flow-namespace.d.ts.map +0 -1
  625. package/dist/cjs/core/flow-namespace.js +0 -182
  626. package/dist/cjs/core/flow-namespace.js.map +0 -1
  627. package/dist/cjs/core/toolGates.d.ts +0 -24
  628. package/dist/cjs/core/toolGates.d.ts.map +0 -1
  629. package/dist/cjs/core/toolGates.js +0 -52
  630. package/dist/cjs/core/toolGates.js.map +0 -1
  631. package/dist/cjs/types/persistence.d.ts +0 -254
  632. package/dist/cjs/types/persistence.d.ts.map +0 -1
  633. package/dist/cjs/types/persistence.js +0 -7
  634. package/dist/cjs/types/persistence.js.map +0 -1
  635. package/dist/cjs/types/prompt-cache.d.ts +0 -15
  636. package/dist/cjs/types/prompt-cache.d.ts.map +0 -1
  637. package/dist/cjs/types/prompt-cache.js +0 -6
  638. package/dist/cjs/types/prompt-cache.js.map +0 -1
  639. package/dist/cjs/types/signals.d.ts +0 -263
  640. package/dist/cjs/types/signals.d.ts.map +0 -1
  641. package/dist/cjs/types/signals.js +0 -11
  642. package/dist/cjs/types/signals.js.map +0 -1
  643. package/dist/cjs/types/template.d.ts +0 -84
  644. package/dist/cjs/types/template.d.ts.map +0 -1
  645. package/dist/cjs/types/template.js +0 -3
  646. package/dist/cjs/types/template.js.map +0 -1
  647. package/dist/cjs/utils/condition.d.ts +0 -63
  648. package/dist/cjs/utils/condition.d.ts.map +0 -1
  649. package/dist/cjs/utils/condition.js +0 -239
  650. package/dist/cjs/utils/condition.js.map +0 -1
  651. package/dist/cjs/utils/event.d.ts +0 -6
  652. package/dist/cjs/utils/event.d.ts.map +0 -1
  653. package/dist/cjs/utils/event.js +0 -20
  654. package/dist/cjs/utils/event.js.map +0 -1
  655. package/dist/cjs/utils/id.d.ts +0 -33
  656. package/dist/cjs/utils/id.d.ts.map +0 -1
  657. package/dist/cjs/utils/id.js +0 -84
  658. package/dist/cjs/utils/id.js.map +0 -1
  659. package/dist/cjs/utils/serialize.d.ts +0 -36
  660. package/dist/cjs/utils/serialize.d.ts.map +0 -1
  661. package/dist/cjs/utils/serialize.js +0 -77
  662. package/dist/cjs/utils/serialize.js.map +0 -1
  663. package/dist/cjs/utils/session.d.ts +0 -124
  664. package/dist/cjs/utils/session.d.ts.map +0 -1
  665. package/dist/cjs/utils/session.js +0 -396
  666. package/dist/cjs/utils/session.js.map +0 -1
  667. package/dist/constants/index.d.ts +0 -2
  668. package/dist/constants/index.d.ts.map +0 -1
  669. package/dist/constants/index.js +0 -4
  670. package/dist/constants/index.js.map +0 -1
  671. package/dist/core/AutoChainExecutor.d.ts +0 -97
  672. package/dist/core/AutoChainExecutor.d.ts.map +0 -1
  673. package/dist/core/AutoChainExecutor.js +0 -284
  674. package/dist/core/AutoChainExecutor.js.map +0 -1
  675. package/dist/core/BranchEvaluator.d.ts +0 -55
  676. package/dist/core/BranchEvaluator.d.ts.map +0 -1
  677. package/dist/core/BranchEvaluator.js +0 -121
  678. package/dist/core/BranchEvaluator.js.map +0 -1
  679. package/dist/core/DirectiveChainTracker.d.ts +0 -49
  680. package/dist/core/DirectiveChainTracker.d.ts.map +0 -1
  681. package/dist/core/DirectiveChainTracker.js +0 -117
  682. package/dist/core/DirectiveChainTracker.js.map +0 -1
  683. package/dist/core/Events.d.ts +0 -26
  684. package/dist/core/Events.d.ts.map +0 -1
  685. package/dist/core/Events.js +0 -137
  686. package/dist/core/Events.js.map +0 -1
  687. package/dist/core/Flow.d.ts +0 -183
  688. package/dist/core/Flow.d.ts.map +0 -1
  689. package/dist/core/Flow.js +0 -547
  690. package/dist/core/Flow.js.map +0 -1
  691. package/dist/core/FlowRouter.d.ts +0 -183
  692. package/dist/core/FlowRouter.d.ts.map +0 -1
  693. package/dist/core/FlowRouter.js +0 -1043
  694. package/dist/core/FlowRouter.js.map +0 -1
  695. package/dist/core/PersistenceManager.d.ts +0 -114
  696. package/dist/core/PersistenceManager.d.ts.map +0 -1
  697. package/dist/core/PersistenceManager.js +0 -332
  698. package/dist/core/PersistenceManager.js.map +0 -1
  699. package/dist/core/PromptComposer.d.ts +0 -47
  700. package/dist/core/PromptComposer.d.ts.map +0 -1
  701. package/dist/core/PromptComposer.js +0 -393
  702. package/dist/core/PromptComposer.js.map +0 -1
  703. package/dist/core/PromptSectionCache.d.ts +0 -48
  704. package/dist/core/PromptSectionCache.d.ts.map +0 -1
  705. package/dist/core/PromptSectionCache.js +0 -104
  706. package/dist/core/PromptSectionCache.js.map +0 -1
  707. package/dist/core/ResponseEngine.d.ts +0 -43
  708. package/dist/core/ResponseEngine.d.ts.map +0 -1
  709. package/dist/core/ResponseEngine.js +0 -231
  710. package/dist/core/ResponseEngine.js.map +0 -1
  711. package/dist/core/ResponseGenerationError.d.ts +0 -30
  712. package/dist/core/ResponseGenerationError.d.ts.map +0 -1
  713. package/dist/core/ResponseGenerationError.js +0 -31
  714. package/dist/core/ResponseGenerationError.js.map +0 -1
  715. package/dist/core/ResponseModal.d.ts +0 -305
  716. package/dist/core/ResponseModal.d.ts.map +0 -1
  717. package/dist/core/ResponseModal.js +0 -1410
  718. package/dist/core/ResponseModal.js.map +0 -1
  719. package/dist/core/ResponsePipeline.d.ts +0 -220
  720. package/dist/core/ResponsePipeline.d.ts.map +0 -1
  721. package/dist/core/ResponsePipeline.js +0 -1035
  722. package/dist/core/ResponsePipeline.js.map +0 -1
  723. package/dist/core/SessionFinalizer.d.ts +0 -34
  724. package/dist/core/SessionFinalizer.d.ts.map +0 -1
  725. package/dist/core/SessionFinalizer.js +0 -84
  726. package/dist/core/SessionFinalizer.js.map +0 -1
  727. package/dist/core/SessionManager.d.ts +0 -112
  728. package/dist/core/SessionManager.d.ts.map +0 -1
  729. package/dist/core/SessionManager.js +0 -301
  730. package/dist/core/SessionManager.js.map +0 -1
  731. package/dist/core/SignalCoordinator.d.ts +0 -103
  732. package/dist/core/SignalCoordinator.d.ts.map +0 -1
  733. package/dist/core/SignalCoordinator.js +0 -203
  734. package/dist/core/SignalCoordinator.js.map +0 -1
  735. package/dist/core/SignalEvaluator.d.ts +0 -86
  736. package/dist/core/SignalEvaluator.d.ts.map +0 -1
  737. package/dist/core/SignalEvaluator.js +0 -312
  738. package/dist/core/SignalEvaluator.js.map +0 -1
  739. package/dist/core/SignalProcessor.d.ts +0 -152
  740. package/dist/core/SignalProcessor.d.ts.map +0 -1
  741. package/dist/core/SignalProcessor.js +0 -498
  742. package/dist/core/SignalProcessor.js.map +0 -1
  743. package/dist/core/Step.d.ts +0 -184
  744. package/dist/core/Step.d.ts.map +0 -1
  745. package/dist/core/Step.js +0 -594
  746. package/dist/core/Step.js.map +0 -1
  747. package/dist/core/StepLifecycle.d.ts +0 -43
  748. package/dist/core/StepLifecycle.d.ts.map +0 -1
  749. package/dist/core/StepLifecycle.js +0 -176
  750. package/dist/core/StepLifecycle.js.map +0 -1
  751. package/dist/core/StreamingToolExecutor.d.ts +0 -142
  752. package/dist/core/StreamingToolExecutor.d.ts.map +0 -1
  753. package/dist/core/StreamingToolExecutor.js +0 -483
  754. package/dist/core/StreamingToolExecutor.js.map +0 -1
  755. package/dist/core/ToolLoopExecutor.d.ts +0 -133
  756. package/dist/core/ToolLoopExecutor.d.ts.map +0 -1
  757. package/dist/core/ToolLoopExecutor.js +0 -564
  758. package/dist/core/ToolLoopExecutor.js.map +0 -1
  759. package/dist/core/ToolManager.d.ts +0 -250
  760. package/dist/core/ToolManager.d.ts.map +0 -1
  761. package/dist/core/ToolManager.js +0 -1098
  762. package/dist/core/ToolManager.js.map +0 -1
  763. package/dist/core/createAgent.d.ts +0 -35
  764. package/dist/core/createAgent.d.ts.map +0 -1
  765. package/dist/core/createAgent.js +0 -36
  766. package/dist/core/createAgent.js.map +0 -1
  767. package/dist/core/flow-namespace.d.ts +0 -64
  768. package/dist/core/flow-namespace.d.ts.map +0 -1
  769. package/dist/core/flow-namespace.js +0 -179
  770. package/dist/core/flow-namespace.js.map +0 -1
  771. package/dist/core/toolGates.d.ts +0 -24
  772. package/dist/core/toolGates.d.ts.map +0 -1
  773. package/dist/core/toolGates.js +0 -49
  774. package/dist/core/toolGates.js.map +0 -1
  775. package/dist/types/persistence.d.ts +0 -254
  776. package/dist/types/persistence.d.ts.map +0 -1
  777. package/dist/types/persistence.js +0 -6
  778. package/dist/types/persistence.js.map +0 -1
  779. package/dist/types/prompt-cache.d.ts +0 -15
  780. package/dist/types/prompt-cache.d.ts.map +0 -1
  781. package/dist/types/prompt-cache.js +0 -5
  782. package/dist/types/prompt-cache.js.map +0 -1
  783. package/dist/types/signals.d.ts +0 -263
  784. package/dist/types/signals.d.ts.map +0 -1
  785. package/dist/types/signals.js +0 -10
  786. package/dist/types/signals.js.map +0 -1
  787. package/dist/types/template.d.ts +0 -84
  788. package/dist/types/template.d.ts.map +0 -1
  789. package/dist/types/template.js +0 -2
  790. package/dist/types/template.js.map +0 -1
  791. package/dist/utils/condition.d.ts +0 -63
  792. package/dist/utils/condition.d.ts.map +0 -1
  793. package/dist/utils/condition.js +0 -230
  794. package/dist/utils/condition.js.map +0 -1
  795. package/dist/utils/event.d.ts +0 -6
  796. package/dist/utils/event.d.ts.map +0 -1
  797. package/dist/utils/event.js +0 -17
  798. package/dist/utils/event.js.map +0 -1
  799. package/dist/utils/id.d.ts +0 -33
  800. package/dist/utils/id.d.ts.map +0 -1
  801. package/dist/utils/id.js +0 -77
  802. package/dist/utils/id.js.map +0 -1
  803. package/dist/utils/serialize.d.ts +0 -36
  804. package/dist/utils/serialize.d.ts.map +0 -1
  805. package/dist/utils/serialize.js +0 -72
  806. package/dist/utils/serialize.js.map +0 -1
  807. package/dist/utils/session.d.ts +0 -124
  808. package/dist/utils/session.d.ts.map +0 -1
  809. package/dist/utils/session.js +0 -379
  810. package/dist/utils/session.js.map +0 -1
  811. package/docs/concepts/directives.md +0 -369
  812. package/docs/reference/adapters.md +0 -543
  813. package/docs/reference/create-agent.md +0 -216
  814. package/docs/reference/directive.md +0 -242
  815. package/docs/reference/signals.md +0 -368
  816. package/examples/02-data-extraction.ts +0 -90
  817. package/examples/05-branching.ts +0 -140
  818. package/examples/06-flow-control.ts +0 -103
  819. package/examples/08-persistence.ts +0 -98
  820. package/examples/09-signals.ts +0 -144
  821. package/src/adapters/MemoryAdapter.ts +0 -281
  822. package/src/adapters/MongoAdapter.ts +0 -341
  823. package/src/adapters/OpenSearchAdapter.ts +0 -693
  824. package/src/adapters/PostgreSQLAdapter.ts +0 -487
  825. package/src/adapters/PrismaAdapter.ts +0 -617
  826. package/src/adapters/RedisAdapter.ts +0 -439
  827. package/src/adapters/SQLiteAdapter.ts +0 -496
  828. package/src/adapters/index.ts +0 -43
  829. package/src/adapters/sessionRow.ts +0 -57
  830. package/src/constants/index.ts +0 -2
  831. package/src/core/AutoChainExecutor.ts +0 -397
  832. package/src/core/BranchEvaluator.ts +0 -161
  833. package/src/core/DirectiveChainTracker.ts +0 -144
  834. package/src/core/Events.ts +0 -164
  835. package/src/core/Flow.ts +0 -665
  836. package/src/core/FlowRouter.ts +0 -1540
  837. package/src/core/PersistenceManager.ts +0 -446
  838. package/src/core/PromptComposer.ts +0 -448
  839. package/src/core/PromptSectionCache.ts +0 -125
  840. package/src/core/ResponseEngine.ts +0 -338
  841. package/src/core/ResponseGenerationError.ts +0 -53
  842. package/src/core/ResponseModal.ts +0 -1902
  843. package/src/core/ResponsePipeline.ts +0 -1404
  844. package/src/core/SessionFinalizer.ts +0 -108
  845. package/src/core/SessionManager.ts +0 -372
  846. package/src/core/SignalCoordinator.ts +0 -263
  847. package/src/core/SignalEvaluator.ts +0 -404
  848. package/src/core/SignalProcessor.ts +0 -663
  849. package/src/core/Step.ts +0 -782
  850. package/src/core/StepLifecycle.ts +0 -242
  851. package/src/core/StreamingToolExecutor.ts +0 -609
  852. package/src/core/ToolLoopExecutor.ts +0 -749
  853. package/src/core/ToolManager.ts +0 -1379
  854. package/src/core/createAgent.ts +0 -40
  855. package/src/core/flow-namespace.ts +0 -227
  856. package/src/core/toolGates.ts +0 -72
  857. package/src/types/persistence.ts +0 -303
  858. package/src/types/prompt-cache.ts +0 -17
  859. package/src/types/signals.ts +0 -338
  860. package/src/types/template.ts +0 -98
  861. package/src/utils/condition.ts +0 -296
  862. package/src/utils/event.ts +0 -16
  863. package/src/utils/id.ts +0 -91
  864. package/src/utils/serialize.ts +0 -86
  865. package/src/utils/session.ts +0 -501
@@ -1,149 +1,85 @@
1
1
  ---
2
2
  title: "Streaming"
3
- description: "Stream the assistant's reply token by token, surface tool calls in flight, and cancel mid-turn with an `AbortSignal`."
3
+ description: "turnStream: the reply arrives as text deltas, the full turn result arrives last, and everything else works exactly as in turn()."
4
4
  type: guide
5
- order: 6
5
+ order: 9
6
6
  ---
7
7
 
8
8
  # Streaming
9
9
 
10
- `agent.respond` returns a single `AgentResponse` after the LLM and any tool calls have finished. That works for batch work, but a chat UI feels dead until the first character lands. `agent.respondStream` returns an `AsyncGenerator<AgentResponseStreamChunk>`, yielding the assistant's reply incrementally and finishing with one terminal chunk that carries all the metadata.
10
+ `agent.turnStream()` is `agent.turn()` that yields the reply while the model writes it.
11
11
 
12
- This guide is a recipe: take a non-streaming call site, swap to `respondStream`, render tokens as they arrive, expose a "thinking" indicator while tools run, read instruction and signal telemetry off the final chunk, and wire an `AbortSignal` so the user can stop mid-turn.
12
+ ```ts
13
+ import { falai, GeminiProvider } from "@falai/agent";
13
14
 
14
- ## The shape
15
-
16
- `respondStream` takes the same `RespondParams` as `respond` — `history`, optional `session`, optional `contextOverride`, optional `signal` — and returns an async iterable of chunks.
17
-
18
- ```typescript
19
- const stream = agent.respondStream({
20
- history: [{ role: "user", content: "Book me a hotel in Lisbon." }],
15
+ const f = falai().fields({
16
+ nome: { type: "string", ask: "Pergunte o nome." },
21
17
  });
22
18
 
23
- for await (const chunk of stream) {
24
- process.stdout.write(chunk.delta);
25
- }
26
- ```
27
-
28
- Every chunk has the same shape:
29
-
30
- ```typescript
31
- interface AgentResponseStreamChunk<TData> {
32
- delta: string; // Text added since the previous chunk
33
- accumulated: string; // Full text so far
34
- done: boolean; // True only on the terminal chunk
35
- // ...metadata fields, populated on the final chunk
36
- }
37
- ```
38
-
39
- `delta` is the new token(s); concatenating every `delta` reproduces the final reply unless a post-phase signal replaces the message on the terminal chunk. `accumulated` is the authoritative running total — useful when your renderer needs the full string each tick (e.g., a Markdown view that re-parses on every update). `done` flips to `true` exactly once, on the terminal chunk.
40
-
41
- ## Render incrementally
42
-
43
- The simplest renderer prints every `delta` as it arrives and clears the line on `done`:
19
+ const agent = f.agent({
20
+ name: "Ana",
21
+ provider: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY ?? "", model: "gemini-2.5-flash" }),
22
+ flows: [
23
+ f.flow({
24
+ id: "boas-vindas",
25
+ name: "Boas-vindas",
26
+ on: [{ message: [] }],
27
+ steps: [{ id: "nome", collect: ["nome"] }],
28
+ }),
29
+ ],
30
+ });
44
31
 
45
- ```typescript
46
- for await (const chunk of agent.respondStream({ history })) {
47
- if (chunk.delta) {
32
+ for await (const chunk of agent.turnStream({ sessionId: "demo", message: "oi, sou o Rui" })) {
33
+ if ("delta" in chunk) {
48
34
  process.stdout.write(chunk.delta);
35
+ continue;
49
36
  }
50
- if (chunk.done) {
51
- process.stdout.write("\n");
52
- }
53
- }
54
- ```
55
-
56
- For a UI, push the latest `accumulated` into your component state. React, Solid, Svelte — they all re-render off whichever value you give them, and `accumulated` is the cheapest to consume because it never requires the renderer to track partial state.
57
-
58
- A common rendering rule of thumb:
59
-
60
- - Plain text view → append `delta`.
61
- - Markdown view that re-parses each frame → bind to `accumulated`.
62
- - Server-Sent Events transport → forward `{ delta, done }` per chunk; let the client reassemble.
63
-
64
- ## Surface tool calls in flight
65
-
66
- Streaming works through tool calls transparently. When the LLM emits a tool call mid-reply, `respondStream` runs the tool, then resumes streaming the post-tool tokens — the consumer never sees the call boundary in the text. What you do get is a quiet gap while the tool executes, which is the right moment to show a "thinking" indicator.
67
-
68
- Detect the gap by watching for empty `delta` chunks after some text has already arrived, or — more robustly — toggle the indicator off as soon as the first non-empty `delta` lands:
69
-
70
- ```typescript
71
- let thinking = true;
72
- let firstToken = true;
73
-
74
- for await (const chunk of agent.respondStream({ history })) {
75
- if (chunk.delta) {
76
- if (firstToken) {
77
- thinking = false;
78
- firstToken = false;
79
- ui.hideSpinner();
80
- }
81
- ui.appendText(chunk.delta);
82
- }
37
+ process.stdout.write("\n");
38
+ console.log(chunk.result.llmCalls, chunk.result.session.data); // 1 { nome: 'Rui' }
83
39
  }
84
40
  ```
85
41
 
86
- If you need finer-grained tool telemetry — which tool fired, with what arguments — read `chunk.toolCalls` on the terminal chunk. It mirrors the same field on the non-streaming `AgentResponse`. For per-tool progress UI, attach observability to the [tool's `handler`](../reference/tool.md) directly; the streaming chunk shape stays clean.
42
+ The stream prints the reply one piece at a time, then the last chunk hands you the same `TurnResult` that `turn()` would have returned.
87
43
 
88
- When a step uses [verbatim `reply`](../reference/step.md) or a `halt` directive, the engine skips the LLM entirely and yields a single chunk with `done: true` and the full text in `accumulated`. The renderer above handles that case without a special branch — there is just no spinner gap.
44
+ ## The chunks
89
45
 
90
- ## The terminal chunk
91
-
92
- The chunk where `done: true` carries every observability field that lives on `AgentResponse`. Three matter for most call sites:
93
-
94
- ```typescript
95
- for await (const chunk of agent.respondStream({ history })) {
96
- // ...render delta...
97
- if (chunk.done) {
98
- console.log("flow complete:", chunk.isFlowComplete);
99
- console.log("instructions rendered:", chunk.appliedInstructions);
100
- console.log("signals fired:", chunk.triggeredSignals);
101
- }
102
- }
46
+ ```ts fragment
47
+ type TurnStreamChunk<D> =
48
+ | { delta: string } // a piece of the reply, in order
49
+ | { done: true; result: TurnResult<D> }; // always last, exactly once
103
50
  ```
104
51
 
105
- - **`appliedInstructions`** — the [instructions](../reference/instruction.md) whose conditions passed and were rendered into this turn's prompt. Deterministic; derived from rendering, not from LLM self-report. Empty on intermediate chunks; populated only when `done: true`.
106
- - **`triggeredSignals`** — the [signals](../reference/signals.md) that fired during this turn (pre- and post-phase), in fire order. Same population rule.
107
- - **`isFlowComplete`** — `true` when this turn finished the flow. Use it to decide whether to clear the conversation, show a summary card, or transition the UI.
52
+ Every `delta` is plain message text. Joined together they add up to the reply. The `done` chunk carries the whole result: `session`, `changed`, `messages[]`, `schedule[]`, `outcomes[]`, `started`, `ended`, `skipped`, `llmCalls`. Read [the agent reference](../reference/agent.md) for the fields.
108
53
 
109
- The terminal chunk also carries `executedSteps`, `stoppedReason`, `metadata` (model, token usage), and the updated `session`. These are the same fields you would read off `AgentResponse` — swapping between APIs does not change observability.
54
+ ## What streams and what does not
110
55
 
111
- ## Cancel mid-stream
56
+ Only the speak call streams: the one call that phrases the reply. Everything else in the turn is code or a call that never streams.
112
57
 
113
- Pass an `AbortSignal` through `respondStream` and abort the controller to cancel. The generator stops yielding, the in-flight LLM call is cancelled at the provider boundary, and any tool execution unwinds cleanly.
58
+ | Source | Arrives as |
59
+ |---|---|
60
+ | the talk step's reply, or the idle speaker's | `delta` chunks, then in `result.messages[]` as one `kind: "ai"` message |
61
+ | a `say` step's text | `result.messages[]` only, `kind: "verbatim"` |
62
+ | the understand call (routing, mentions, extraction) | nothing visible; it finishes before the first delta |
63
+ | actions, waits, `if` steps | `result.outcomes[]`, `result.schedule[]` |
114
64
 
115
- ```typescript
116
- const controller = new AbortController();
65
+ The provider streams a JSON envelope, not bare text: `{"message":"Oi, Rui! Em que posso"…` followed by the collected fields. The framework unwraps it as it arrives (`src/utils/streamingMessage.ts`), so a `delta` never contains a brace, a quote or a field name, and a field the model writes before the message is skipped rather than leaked. A provider that streams plain text passes through as it is.
117
66
 
118
- // User clicks Stop, or a 5s ceiling fires.
119
- const timer = setTimeout(() => controller.abort(), 5000);
67
+ ## Tool calls during a stream
120
68
 
121
- try {
122
- for await (const chunk of agent.respondStream({
123
- history,
124
- signal: controller.signal,
125
- })) {
126
- process.stdout.write(chunk.delta);
127
- }
128
- } finally {
129
- clearTimeout(timer);
130
- }
131
- ```
69
+ A speak call may run in rounds: the model calls tools, the results go back as history, and the model is asked again. This happens inside the stream, before the `done` chunk. Each round streams. If the model writes something beside a tool call ("deixa eu ver"), that preamble reaches the stream, while `result.messages[0].text` holds only the final round's message. A UI that shows deltas as they come should replace what it showed with `result.messages[0].text` when `done` arrives, so both paths end on the same text.
132
70
 
133
- When the signal aborts, the loop exits cleanly — no exception is thrown by the generator itself. If the LLM provider surfaces the cancellation as an error, it lands as a [`ResponseGenerationError`](../reference/errors.md) and you handle it the way you would any other turn-level error.
71
+ Rounds are capped by `maxToolLoops` on the agent, default 5; after the cap the model is asked once more with no tools so a message always comes back. Each round is one model call and counts in `result.llmCalls`.
134
72
 
135
- For a Stop button, store the `controller` reference for the active stream on the UI side and call `controller.abort()` from the click handler. For server-side hard ceilings, wrap `respondStream` with an `AbortController` whose `setTimeout` fires at your SLO budget.
73
+ ## A provider failure mid-stream
136
74
 
137
- If the turn fails — the generator surfaces an error chunk — it has no lasting effect: the in-memory session rolls back to its pre-turn snapshot (the user message added by `stream()` before the turn is retained), and persisted state is whatever the previous turn saved. Retrying is always safe.
75
+ The stream never throws for a speak failure. You get zero or more deltas and then the `done` chunk, whose result carries a `deferred` outcome and a retry wake, exactly as `turn()` would report it.
138
76
 
139
- ## Reliability: retries, backups, and the first-chunk deadline
77
+ A failure mid-stream leaves the person looking at half a reply. Nothing of that half reaches `result.messages[]`, so the deltas you showed are its only trace: clear them when `done` carries a `deferred` outcome, and leave a short line saying the reply is coming. The retry wake fires a minute later, speaks that step again from the start, and its reply arrives as an ordinary message carrying the key the first attempt would have used.
140
78
 
141
- Streaming inherits the same resilience machinery as non-streaming calls — provider `retryConfig` and `backupModels` — with stream-specific rules:
79
+ A failure in the understand call, before any delta, throws from the `for await` like `turn()` does. See [error handling](./error-handling.md).
142
80
 
143
- - **Retry only before the first chunk.** A stream that fails before yielding anything (a connection error, an empty completion, a stalled open) is retried on the same model up to `retryConfig.retries` times. Once a delta has reached your renderer, the stream is committed: any later failure propagates instead of retrying, so a retry can never emit a token your consumer has already seen.
144
- - **First-chunk deadline.** `retryConfig.timeout` doubles as the time-to-first-token budget. If the provider opens a stream but produces no first chunk within it, the attempt counts as failed and the retry and backup machinery takes over. Only the first chunk is bounded — later chunks are unbounded, so a long-but-healthy stream is never cut off.
145
- - **Transparent backup-model switch.** With `backupModels` configured, a model that fails mid-stream — even after deltas were delivered — falls through to the next model, whose chunks flow through unchanged. The switchover happens between chunks; no error reaches the consumer unless every model fails.
81
+ ## The same settle, the same result
146
82
 
147
- These knobs live on the provider constructor, not on `respondStream` — see [Providers](../reference/providers.md) for `retryConfig` and `backupModels`.
83
+ `turnStream` runs the same eight phases as `turn()` and applies the reply the same way. With the same provider output, the two return identical results: the same message keys, the same data written, the same schedule. Stream when you show text to a person as it is written. When the messages leave through a channel you send to yourself, `turn()` is simpler, because it gives you the messages after the save and nothing before it.
148
84
 
149
- **Next:** [Errors](./error-handling.md)
85
+ Save and send are still yours, and still in that order: the `done` chunk's `result.session` is what you save with the version you loaded, and a `SessionConflictError` means you replay the same input; see [persistence](./persistence.md). With a stream the person has already seen the text by then, which is fine in a chat window and is the reason to prefer `turn()` on a channel.
@@ -0,0 +1,284 @@
1
+ ---
2
+ title: "Testing"
3
+ description: "A clock you hold still, a scheduler you fire by hand, a store in memory and a provider you script: everything a turn needs, with no network."
4
+ type: guide
5
+ order: 12
6
+ ---
7
+
8
+ # Testing
9
+
10
+ The core does no I/O beyond the provider and your actions, so a test drives a real `Agent` with four fakes. Start with the clock.
11
+
12
+ ```ts
13
+ import { fakeClock } from "@falai/agent";
14
+
15
+ const clock = fakeClock("2026-09-20T10:00:00.000Z");
16
+ clock.advance("24h");
17
+ console.log(clock.now().toISOString()); // 2026-09-21T10:00:00.000Z
18
+ ```
19
+
20
+ Pass `clock` to the agent and every `now`, every wake time and every key that carries a timestamp comes from it. The core never reads `Date.now()`.
21
+
22
+ ## The four fakes
23
+
24
+ | Fake | From | What it replaces |
25
+ |---|---|---|
26
+ | `fakeClock(iso)` | `@falai/agent` | time: `now()`, `advance("2d" \| ms)`, `set(iso)` |
27
+ | `MemoryScheduler` | `@falai/agent` | your queue: `add(entry)`, `remove(key)`, `size`, `due(now)` returns and removes what is due, earliest first; a new entry with the same key replaces the old one, and `replaces` removes that key |
28
+ | `MemoryStore` | `@falai/agent` | your database, with the same version check |
29
+ | a scripted `AiProvider` | you write it, about 25 lines | the model |
30
+
31
+ The snippets below use `node:assert/strict` so they run under `bun run` or `node` with no framework. The repo's own tests use `bun test` the same way.
32
+
33
+ ## A scripted provider
34
+
35
+ The framework names each call through `parameters.schemaName`: `"understand"` for the call that judges the customer's message, `"speak"` for the call that phrases the reply. A scripted provider keeps one queue per name, shifts the next reply off it, and throws when a queue runs dry, so a turn that spends a call you did not expect fails loudly.
36
+
37
+ ```ts
38
+ import type { AiProvider, GenerateMessageInput, GenerateMessageOutput, GenerateMessageStreamChunk } from "@falai/agent";
39
+
40
+ type Reply = Record<string, unknown>;
41
+
42
+ export interface Scripted extends AiProvider {
43
+ /** Every call's schema name, in order. */
44
+ calls: string[];
45
+ }
46
+
47
+ export function scripted(script: { understand?: Reply[]; speak?: Reply[] }): Scripted {
48
+ const queues: Record<string, Reply[]> = { understand: [...(script.understand ?? [])], speak: [...(script.speak ?? [])] };
49
+ const calls: string[] = [];
50
+
51
+ function next<T>(input: GenerateMessageInput): GenerateMessageOutput<T> {
52
+ const name = input.parameters?.schemaName ?? "(unnamed)";
53
+ calls.push(name);
54
+ const reply = queues[name]?.shift();
55
+ if (!reply) throw new Error(`no scripted "${name}" reply left for call #${calls.length}`);
56
+ const message = typeof reply.message === "string" ? reply.message : JSON.stringify(reply);
57
+ return { message, structured: reply as T };
58
+ }
59
+
60
+ return {
61
+ name: "scripted",
62
+ calls,
63
+ capabilities: { supportsTools: true, supportsNativeJsonSchema: true, supportsStreaming: true, supportsStreamingToolCalls: true, supportsPromptCaching: false },
64
+ generateMessage: <_C, T>(input: GenerateMessageInput) => Promise.resolve().then(() => next<T>(input)),
65
+ // eslint-disable-next-line @typescript-eslint/require-await -- one chunk, nothing to await
66
+ async *generateMessageStream<_C, T>(input: GenerateMessageInput): AsyncGenerator<GenerateMessageStreamChunk<T>> {
67
+ const out = next<T>(input);
68
+ yield { delta: out.message, accumulated: out.message, done: true, structured: out.structured };
69
+ },
70
+ };
71
+ }
72
+ ```
73
+
74
+ The two envelopes you script, as the framework reads them:
75
+
76
+ ```ts fragment
77
+ // understand: every section present, empty when there is nothing to say
78
+ {
79
+ flows: { triagem: 90 }, // flowId → 0–100 fit of the message to the flow
80
+ mentions: { concorrente: true }, // flowId → the customer brought it up
81
+ extract: { concorrente: { trecho: "a Acme cobra metade" } }, // flowId → values for the mention's `extract`
82
+ branches: {}, // "runId/stepId/index" → the `when` holds
83
+ fields: { nome: "Ana" }, // field → the raw value the customer gave
84
+ }
85
+
86
+ // speak: the message, then one property per pending field, null when the customer did not give it
87
+ { message: "Oi Ana! De qual empresa você fala?", empresa: null }
88
+
89
+ // speak, calling a tool first: the next scripted speak reply answers after the tool ran
90
+ { toolCalls: [{ toolName: "orcamento", arguments: { pessoas: 30 } }] }
91
+ ```
92
+
93
+ A `fields` value goes through the same coercion as production: `"sim"` becomes `true` for a boolean, `"1,5"` becomes `1.5` for a number, `"mil"` is dropped with the outcome `code: 'bad-value'`, and an enum value outside the list is dropped with `code: 'not-in-enum'`.
94
+
95
+ ## One test, end to end
96
+
97
+ A triage flow that collects two fields and a silence flow that nudges after 24 hours. The test asserts the call count, the message keys, the wake key, then fires the wake through the scheduler.
98
+
99
+ ```ts
100
+ import assert from "node:assert/strict";
101
+ import { falai, fakeClock, MemoryScheduler, MemoryStore, type AiProvider, type DataOf, type GenerateMessageInput, type GenerateMessageOutput, type GenerateMessageStreamChunk, type TurnKind } from "@falai/agent";
102
+
103
+ // The scripted provider from above, inlined so this file stands alone.
104
+ type Reply = Record<string, unknown>;
105
+ function scripted(script: { understand?: Reply[]; speak?: Reply[] }): AiProvider & { calls: string[] } {
106
+ const queues: Record<string, Reply[]> = { understand: [...(script.understand ?? [])], speak: [...(script.speak ?? [])] };
107
+ const calls: string[] = [];
108
+ function next<T>(input: GenerateMessageInput): GenerateMessageOutput<T> {
109
+ const name = input.parameters?.schemaName ?? "(unnamed)";
110
+ calls.push(name);
111
+ const reply = queues[name]?.shift();
112
+ if (!reply) throw new Error(`no scripted "${name}" reply left for call #${calls.length}`);
113
+ return { message: typeof reply.message === "string" ? reply.message : JSON.stringify(reply), structured: reply as T };
114
+ }
115
+ return {
116
+ name: "scripted",
117
+ calls,
118
+ capabilities: { supportsTools: true, supportsNativeJsonSchema: true, supportsStreaming: true, supportsStreamingToolCalls: true, supportsPromptCaching: false },
119
+ generateMessage: <_C, T>(input: GenerateMessageInput) => Promise.resolve().then(() => next<T>(input)),
120
+ // eslint-disable-next-line @typescript-eslint/require-await -- one chunk, nothing to await
121
+ async *generateMessageStream<_C, T>(input: GenerateMessageInput): AsyncGenerator<GenerateMessageStreamChunk<T>> {
122
+ const out = next<T>(input);
123
+ yield { delta: out.message, accumulated: out.message, done: true, structured: out.structured };
124
+ },
125
+ };
126
+ }
127
+
128
+ const T0 = "2026-09-20T10:00:00.000Z";
129
+ const f = falai().fields({
130
+ nome: { type: "string", ask: "Pergunte o nome de um jeito leve." },
131
+ empresa: { type: "string", ask: "Pergunte de qual empresa a pessoa fala." },
132
+ });
133
+ type Data = DataOf<typeof f>;
134
+
135
+ const triagem = f.flow({
136
+ id: "triagem",
137
+ name: "Triagem",
138
+ on: [{ message: ["quer saber como funciona", "pede um orçamento"] }],
139
+ steps: [
140
+ { id: "quem", prompt: "Descubra quem é e de onde fala.", collect: ["nome", "empresa"] },
141
+ { id: "tchau", prompt: "Agradeça e diga que um vendedor continua daqui." },
142
+ ],
143
+ });
144
+
145
+ const retomar = f.flow({
146
+ id: "retomar",
147
+ name: "Retomar quem sumiu",
148
+ on: [{ silence: "24h" }],
149
+ steps: [
150
+ { id: "p1", prompt: "Retome a conversa de forma leve e pergunte se ainda faz sentido." },
151
+ { id: "w1", wait: "2d", else: "end" },
152
+ { id: "p2", prompt: "Última tentativa, curta e sem pressão." },
153
+ ],
154
+ });
155
+
156
+ const clock = fakeClock(T0);
157
+ const provider = scripted({
158
+ understand: [{ flows: {}, mentions: {}, extract: {}, branches: {}, fields: { nome: "Ana" } }],
159
+ speak: [{ message: "Oi Ana! De qual empresa você fala?", empresa: null }, { message: "Oi Ana, ainda faz sentido conversarmos?" }],
160
+ });
161
+ const agent = f.agent({ name: "Ana", provider, clock, flows: [triagem, retomar] });
162
+ const store = new MemoryStore<Data>();
163
+ const scheduler = new MemoryScheduler();
164
+
165
+ async function runTurn(input: TurnKind & { sessionId: string }) {
166
+ const session = await store.load(input.sessionId);
167
+ const r = await agent.turn({ ...input, session: session ?? undefined, history: [] });
168
+ if (r.changed) {
169
+ await store.save(r.session, session?.version ?? 0);
170
+ for (const entry of r.schedule) scheduler.add(entry);
171
+ }
172
+ return r;
173
+ }
174
+
175
+ // Turn 1: the customer writes. Understand extracts the name (1 call), speak asks for the company (1 call).
176
+ const t1 = await runTurn({ sessionId: "s1", message: "oi, sou a Ana, quero saber como funciona", id: "m1" });
177
+ assert.equal(t1.llmCalls, 2);
178
+ assert.deepEqual(provider.calls, ["understand", "speak"]);
179
+ assert.equal(t1.session.data.nome, "Ana");
180
+ assert.equal(t1.messages[0]?.key, "triagem#m1:quem:1"); // ${runId}:${stepId}:${visit}
181
+ assert.equal(t1.outcomes.find((o) => o.kind === "collect")?.status, "ok");
182
+ // The assistant spoke last: the silence flow armed a wake for 24h from now.
183
+ const silenceKey = `silence:retomar:s1:${Date.parse(T0)}`;
184
+ assert.deepEqual(t1.schedule.map((s) => s.key), [silenceKey]);
185
+ assert.equal(scheduler.size, 1);
186
+
187
+ // 23h later nothing is due; at 24h the wake fires.
188
+ clock.advance("23h");
189
+ assert.equal(scheduler.due(clock.now()).length, 0);
190
+ clock.advance("1h");
191
+ const due = scheduler.due(clock.now());
192
+ assert.deepEqual(due.map((d) => d.key), [silenceKey]);
193
+
194
+ // Turn 2: the wake starts `retomar`, which speaks first (1 call) and parks on w1.
195
+ const t2 = await runTurn({ sessionId: "s1", wake: due[0].key });
196
+ assert.equal(t2.llmCalls, 1);
197
+ assert.deepEqual(t2.started.map((s) => s.flowId), ["retomar"]);
198
+ assert.equal(t2.messages[0]?.key, `retomar#${Date.parse(T0)}:p1:1`);
199
+ assert.deepEqual(t2.outcomes.find((o) => o.stepId === "w1"), {
200
+ runId: `retomar#${Date.parse(T0)}`,
201
+ flowId: "retomar",
202
+ stepId: "w1",
203
+ key: `retomar#${Date.parse(T0)}:w1:1`,
204
+ kind: "wait",
205
+ status: "waiting",
206
+ until: new Date(clock.now().getTime() + 2 * 86_400_000).toISOString(),
207
+ at: clock.now().toISOString(),
208
+ });
209
+ assert.deepEqual(t2.schedule.map((s) => s.key), [`retomar#${Date.parse(T0)}:w1:${clock.now().getTime() + 2 * 86_400_000}`]);
210
+ // Triagem still holds its question: the nudge did not take the floor for good.
211
+ assert.equal(t2.session.runs.find((r) => r.flowId === "triagem")?.status, "asking");
212
+ assert.equal((await store.load("s1"))?.version, 2);
213
+
214
+ console.log("ok");
215
+ ```
216
+
217
+ What each assertion pins down:
218
+
219
+ - `llmCalls` is the budget. A turn that spends more than you scripted throws inside the provider, so an unexpected third call cannot pass silently. `usage` is absent in tests unless your scripted provider reports token counts — real providers do, and the turn adds them up.
220
+ - `messages[].key` is `${runId}:${stepId}:${visit}`, and `runId` is `${flowId}#${triggerKey}`. The trigger key of a message turn is the message `id` you passed; of a silence wake, the `lastAssistantAt` timestamp in milliseconds.
221
+ - `schedule[].key` is what your queue job carries (its id is the key encoded, since BullMQ refuses a `:` in one) and what you pass back as `wake`. The silence key is `silence:${flowId}:${sessionId}:${ms}`; a timer wait's key is `${runId}:${stepId}:${atMs}`.
222
+ - `outcomes[]` is the execution log, one line per step. Assert on `code`, which is stable across versions, not on `message`, the English sentence beside it; see [outcomes](../reference/outcomes.md).
223
+
224
+ ## Replaying the same input
225
+
226
+ The keys are deterministic: the same input on the same session version mints the same run id, the same message keys and the same wake keys. That is what makes a `SessionConflictError` safe to replay and a duplicate webhook harmless. Prove it with two agents that share a clock:
227
+
228
+ ```ts
229
+ import assert from "node:assert/strict";
230
+ import { falai, fakeClock, type AiProvider, type GenerateMessageInput, type GenerateMessageOutput, type GenerateMessageStreamChunk } from "@falai/agent";
231
+
232
+ type Reply = Record<string, unknown>;
233
+ function scripted(speak: Reply[]): AiProvider {
234
+ const queue = [...speak];
235
+ function next<T>(input: GenerateMessageInput): GenerateMessageOutput<T> {
236
+ if (input.parameters?.schemaName !== "speak") throw new Error(`unexpected ${input.parameters?.schemaName ?? "unnamed"} call`);
237
+ const reply = queue.shift();
238
+ if (!reply) throw new Error("no scripted speak reply left");
239
+ return { message: String(reply.message), structured: reply as T };
240
+ }
241
+ return {
242
+ name: "scripted",
243
+ capabilities: { supportsTools: true, supportsNativeJsonSchema: true, supportsStreaming: true, supportsStreamingToolCalls: true, supportsPromptCaching: false },
244
+ generateMessage: <_C, T>(input: GenerateMessageInput) => Promise.resolve().then(() => next<T>(input)),
245
+ // eslint-disable-next-line @typescript-eslint/require-await -- one chunk, nothing to await
246
+ async *generateMessageStream<_C, T>(input: GenerateMessageInput): AsyncGenerator<GenerateMessageStreamChunk<T>> {
247
+ const out = next<T>(input);
248
+ yield { delta: out.message, accumulated: out.message, done: true, structured: out.structured };
249
+ },
250
+ };
251
+ }
252
+
253
+ const f = falai().fields({
254
+ nome: { type: "string", ask: "Pergunte o nome." },
255
+ });
256
+ const flows = [
257
+ f.flow({ id: "boas-vindas", name: "Boas-vindas", on: [{ message: [] }], steps: [{ id: "nome", collect: ["nome"] }] }),
258
+ f.flow({ id: "retomar", name: "Retomar", on: [{ silence: "24h" }], steps: [{ id: "p1", prompt: "Retome a conversa." }] }),
259
+ ];
260
+ const clock = fakeClock("2026-09-20T10:00:00.000Z");
261
+ const reply = { message: "Oi! Como você se chama?", nome: null };
262
+
263
+ const first = await f.agent({ name: "Ana", provider: scripted([reply]), clock, flows }).turn({ sessionId: "s1", message: "oi", id: "m1" });
264
+ const replay = await f.agent({ name: "Ana", provider: scripted([reply]), clock, flows }).turn({ sessionId: "s1", message: "oi", id: "m1" });
265
+
266
+ assert.deepEqual(replay.messages, first.messages); // same key: boas-vindas#m1:nome:1
267
+ assert.deepEqual(replay.schedule, first.schedule); // same wake: silence:retomar:s1:<ms>
268
+ assert.deepEqual(replay.session.runs, first.session.runs);
269
+ assert.equal(first.llmCalls, 1); // a catch-all alone, and nothing to extract before the ask: no understand call
270
+ console.log("ok");
271
+ ```
272
+
273
+ The same holds inside one session: feed the same `{ message, id }` to the session version it was computed on and the result is the same. Feed it again to a version that already recorded that id and the turn is ignored with `changed: false` and the outcome `code: 'duplicate-input'`.
274
+
275
+ ## Other things worth a test
276
+
277
+ - A `silenced` turn: `agent.turn({ …, silenced: "humano no comando" })` spends zero calls, phrases nothing, and still runs `do` steps. Assert `llmCalls === 0` and `messages.length === 0`.
278
+ - A speak failure: leave the `speak` queue empty so the scripted provider throws inside the turn. `agent.turn()` still returns — no try/catch needed. Assert the outcome `{ status: "deferred", code: "provider-unavailable" }` and a `schedule[]` key ending in `:retry:<ms>`. See [error handling](./error-handling.md).
279
+ - A stale wake: fire a key the session no longer waits for and assert `changed === false` and the outcome `code: 'stale-wake'`.
280
+ - Actions: register `f.action` handlers that push `ctx.key` and `ctx.dedupeKey` to an array, and assert the list. The keys are the same on a replay.
281
+ - The prompt: keep every `GenerateMessageInput` your provider receives and assert on `input.prompt` (which instructions reached it) and `input.tools` (which tools were offered). The repo's own scripted provider, `tests/mock-provider.ts`, records them as `calls[].prompt` and `calls[].input`.
282
+ - Streaming: `turnStream` with the same scripted provider yields one `delta` per provider chunk and a final `{ done, result }` equal to what `turn()` returns.
283
+
284
+ See [the pipeline](../concepts/pipeline.md) for what each phase costs, and [runs and waits](../concepts/runs-and-waits.md) for the full key table.