@falai/agent 3.4.5 → 4.0.0-alpha.2

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 (856) hide show
  1. package/README.md +41 -34
  2. package/dist/cjs/core/Agent.d.ts +22 -378
  3. package/dist/cjs/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/core/Agent.js +104 -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 +522 -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 +143 -0
  20. package/dist/cjs/core/Prompt.js.map +1 -0
  21. package/dist/cjs/core/Runner.d.ts +160 -0
  22. package/dist/cjs/core/Runner.d.ts.map +1 -0
  23. package/dist/cjs/core/Runner.js +1131 -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 +364 -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 +353 -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 +153 -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/schema.d.ts +50 -0
  158. package/dist/cjs/utils/schema.d.ts.map +1 -0
  159. package/dist/cjs/utils/schema.js +138 -0
  160. package/dist/cjs/utils/schema.js.map +1 -0
  161. package/dist/cjs/utils/streamingMessage.d.ts +3 -2
  162. package/dist/cjs/utils/streamingMessage.d.ts.map +1 -1
  163. package/dist/cjs/utils/streamingMessage.js +38 -4
  164. package/dist/cjs/utils/streamingMessage.js.map +1 -1
  165. package/dist/cjs/utils/template.d.ts +13 -149
  166. package/dist/cjs/utils/template.d.ts.map +1 -1
  167. package/dist/cjs/utils/template.js +31 -363
  168. package/dist/cjs/utils/template.js.map +1 -1
  169. package/dist/cjs/utils/usage.d.ts +19 -0
  170. package/dist/cjs/utils/usage.d.ts.map +1 -0
  171. package/dist/cjs/utils/usage.js +35 -0
  172. package/dist/cjs/utils/usage.js.map +1 -0
  173. package/dist/core/Agent.d.ts +22 -378
  174. package/dist/core/Agent.d.ts.map +1 -1
  175. package/dist/core/Agent.js +107 -1181
  176. package/dist/core/Agent.js.map +1 -1
  177. package/dist/core/CompactionEngine.d.ts.map +1 -1
  178. package/dist/core/CompactionEngine.js +5 -3
  179. package/dist/core/CompactionEngine.js.map +1 -1
  180. package/dist/core/FlowSpec.d.ts +136 -0
  181. package/dist/core/FlowSpec.d.ts.map +1 -0
  182. package/dist/core/FlowSpec.js +516 -0
  183. package/dist/core/FlowSpec.js.map +1 -0
  184. package/dist/core/Migrate.d.ts +38 -0
  185. package/dist/core/Migrate.d.ts.map +1 -0
  186. package/dist/core/Migrate.js +264 -0
  187. package/dist/core/Migrate.js.map +1 -0
  188. package/dist/core/Prompt.d.ts +54 -0
  189. package/dist/core/Prompt.d.ts.map +1 -0
  190. package/dist/core/Prompt.js +133 -0
  191. package/dist/core/Prompt.js.map +1 -0
  192. package/dist/core/Runner.d.ts +160 -0
  193. package/dist/core/Runner.d.ts.map +1 -0
  194. package/dist/core/Runner.js +1127 -0
  195. package/dist/core/Runner.js.map +1 -0
  196. package/dist/core/Speak.d.ts +37 -0
  197. package/dist/core/Speak.d.ts.map +1 -0
  198. package/dist/core/Speak.js +360 -0
  199. package/dist/core/Speak.js.map +1 -0
  200. package/dist/core/Understand.d.ts +28 -0
  201. package/dist/core/Understand.d.ts.map +1 -0
  202. package/dist/core/Understand.js +349 -0
  203. package/dist/core/Understand.js.map +1 -0
  204. package/dist/core/contracts.d.ts +122 -0
  205. package/dist/core/contracts.d.ts.map +1 -0
  206. package/dist/core/contracts.js +10 -0
  207. package/dist/core/contracts.js.map +1 -0
  208. package/dist/core/falai.d.ts +57 -0
  209. package/dist/core/falai.d.ts.map +1 -0
  210. package/dist/core/falai.js +40 -0
  211. package/dist/core/falai.js.map +1 -0
  212. package/dist/core/predicate.d.ts +9 -0
  213. package/dist/core/predicate.d.ts.map +1 -0
  214. package/dist/core/predicate.js +54 -0
  215. package/dist/core/predicate.js.map +1 -0
  216. package/dist/index.d.ts +26 -31
  217. package/dist/index.d.ts.map +1 -1
  218. package/dist/index.js +19 -24
  219. package/dist/index.js.map +1 -1
  220. package/dist/persistence/MemoryStore.d.ts +15 -0
  221. package/dist/persistence/MemoryStore.d.ts.map +1 -0
  222. package/dist/persistence/MemoryStore.js +35 -0
  223. package/dist/persistence/MemoryStore.js.map +1 -0
  224. package/dist/persistence/MongoStore.d.ts +42 -0
  225. package/dist/persistence/MongoStore.d.ts.map +1 -0
  226. package/dist/persistence/MongoStore.js +56 -0
  227. package/dist/persistence/MongoStore.js.map +1 -0
  228. package/dist/persistence/OpenSearchStore.d.ts +86 -0
  229. package/dist/persistence/OpenSearchStore.d.ts.map +1 -0
  230. package/dist/persistence/OpenSearchStore.js +116 -0
  231. package/dist/persistence/OpenSearchStore.js.map +1 -0
  232. package/dist/persistence/PostgresStore.d.ts +41 -0
  233. package/dist/persistence/PostgresStore.d.ts.map +1 -0
  234. package/dist/persistence/PostgresStore.js +54 -0
  235. package/dist/persistence/PostgresStore.js.map +1 -0
  236. package/dist/persistence/PrismaStore.d.ts +65 -0
  237. package/dist/persistence/PrismaStore.d.ts.map +1 -0
  238. package/dist/persistence/PrismaStore.js +91 -0
  239. package/dist/persistence/PrismaStore.js.map +1 -0
  240. package/dist/persistence/RedisStore.d.ts +34 -0
  241. package/dist/persistence/RedisStore.d.ts.map +1 -0
  242. package/dist/persistence/RedisStore.js +57 -0
  243. package/dist/persistence/RedisStore.js.map +1 -0
  244. package/dist/persistence/SQLiteStore.d.ts +45 -0
  245. package/dist/persistence/SQLiteStore.d.ts.map +1 -0
  246. package/dist/persistence/SQLiteStore.js +70 -0
  247. package/dist/persistence/SQLiteStore.js.map +1 -0
  248. package/dist/persistence/sessionRow.d.ts +14 -0
  249. package/dist/persistence/sessionRow.d.ts.map +1 -0
  250. package/dist/persistence/sessionRow.js +45 -0
  251. package/dist/persistence/sessionRow.js.map +1 -0
  252. package/dist/providers/DeepSeekProvider.d.ts.map +1 -1
  253. package/dist/providers/DeepSeekProvider.js +8 -3
  254. package/dist/providers/DeepSeekProvider.js.map +1 -1
  255. package/dist/providers/GeminiProvider.d.ts +4 -3
  256. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  257. package/dist/providers/GeminiProvider.js +4 -3
  258. package/dist/providers/GeminiProvider.js.map +1 -1
  259. package/dist/providers/OpenAICompatibleProvider.d.ts +4 -0
  260. package/dist/providers/OpenAICompatibleProvider.d.ts.map +1 -1
  261. package/dist/providers/OpenAICompatibleProvider.js +2 -0
  262. package/dist/providers/OpenAICompatibleProvider.js.map +1 -1
  263. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  264. package/dist/providers/OpenRouterProvider.js +2 -4
  265. package/dist/providers/OpenRouterProvider.js.map +1 -1
  266. package/dist/providers/ProviderAdapter.d.ts +11 -6
  267. package/dist/providers/ProviderAdapter.d.ts.map +1 -1
  268. package/dist/providers/ProviderAdapter.js +34 -11
  269. package/dist/providers/ProviderAdapter.js.map +1 -1
  270. package/dist/providers/ZaiProvider.d.ts +6 -4
  271. package/dist/providers/ZaiProvider.d.ts.map +1 -1
  272. package/dist/providers/ZaiProvider.js +6 -4
  273. package/dist/providers/ZaiProvider.js.map +1 -1
  274. package/dist/types/agent.d.ts +153 -383
  275. package/dist/types/agent.d.ts.map +1 -1
  276. package/dist/types/agent.js +1 -1
  277. package/dist/types/ai.d.ts +32 -1
  278. package/dist/types/ai.d.ts.map +1 -1
  279. package/dist/types/compaction.d.ts +3 -1
  280. package/dist/types/compaction.d.ts.map +1 -1
  281. package/dist/types/errors.d.ts +9 -12
  282. package/dist/types/errors.d.ts.map +1 -1
  283. package/dist/types/errors.js +12 -15
  284. package/dist/types/errors.js.map +1 -1
  285. package/dist/types/flow.d.ts +265 -513
  286. package/dist/types/flow.d.ts.map +1 -1
  287. package/dist/types/flow.js +7 -1
  288. package/dist/types/flow.js.map +1 -1
  289. package/dist/types/history.d.ts +7 -18
  290. package/dist/types/history.d.ts.map +1 -1
  291. package/dist/types/history.js.map +1 -1
  292. package/dist/types/index.d.ts +9 -15
  293. package/dist/types/index.d.ts.map +1 -1
  294. package/dist/types/index.js +2 -7
  295. package/dist/types/index.js.map +1 -1
  296. package/dist/types/session.d.ts +94 -64
  297. package/dist/types/session.d.ts.map +1 -1
  298. package/dist/types/session.js +5 -1
  299. package/dist/types/session.js.map +1 -1
  300. package/dist/types/tool.d.ts +37 -207
  301. package/dist/types/tool.d.ts.map +1 -1
  302. package/dist/types/tool.js +6 -13
  303. package/dist/types/tool.js.map +1 -1
  304. package/dist/utils/clock.d.ts +28 -0
  305. package/dist/utils/clock.d.ts.map +1 -0
  306. package/dist/utils/clock.js +59 -0
  307. package/dist/utils/clock.js.map +1 -0
  308. package/dist/utils/duration.d.ts +11 -0
  309. package/dist/utils/duration.d.ts.map +1 -0
  310. package/dist/utils/duration.js +26 -0
  311. package/dist/utils/duration.js.map +1 -0
  312. package/dist/utils/history.d.ts +4 -1
  313. package/dist/utils/history.d.ts.map +1 -1
  314. package/dist/utils/history.js +2 -2
  315. package/dist/utils/history.js.map +1 -1
  316. package/dist/utils/index.d.ts +4 -10
  317. package/dist/utils/index.d.ts.map +1 -1
  318. package/dist/utils/index.js +4 -21
  319. package/dist/utils/index.js.map +1 -1
  320. package/dist/utils/json.d.ts +2 -0
  321. package/dist/utils/json.d.ts.map +1 -1
  322. package/dist/utils/json.js +4 -0
  323. package/dist/utils/json.js.map +1 -1
  324. package/dist/utils/outcomes.d.ts +48 -0
  325. package/dist/utils/outcomes.d.ts.map +1 -0
  326. package/dist/utils/outcomes.js +48 -0
  327. package/dist/utils/outcomes.js.map +1 -0
  328. package/dist/utils/schema.d.ts +50 -0
  329. package/dist/utils/schema.d.ts.map +1 -0
  330. package/dist/utils/schema.js +129 -0
  331. package/dist/utils/schema.js.map +1 -0
  332. package/dist/utils/streamingMessage.d.ts +3 -2
  333. package/dist/utils/streamingMessage.d.ts.map +1 -1
  334. package/dist/utils/streamingMessage.js +38 -4
  335. package/dist/utils/streamingMessage.js.map +1 -1
  336. package/dist/utils/template.d.ts +13 -149
  337. package/dist/utils/template.d.ts.map +1 -1
  338. package/dist/utils/template.js +28 -355
  339. package/dist/utils/template.js.map +1 -1
  340. package/dist/utils/usage.d.ts +19 -0
  341. package/dist/utils/usage.d.ts.map +1 -0
  342. package/dist/utils/usage.js +31 -0
  343. package/dist/utils/usage.js.map +1 -0
  344. package/docs/README.md +37 -19
  345. package/docs/concepts/architecture.md +117 -239
  346. package/docs/concepts/collection.md +170 -0
  347. package/docs/concepts/pipeline.md +132 -378
  348. package/docs/concepts/runs-and-waits.md +192 -0
  349. package/docs/guides/actions-and-events.md +276 -0
  350. package/docs/guides/branching.md +119 -208
  351. package/docs/guides/compaction.md +63 -158
  352. package/docs/guides/conditions.md +164 -128
  353. package/docs/guides/error-handling.md +168 -164
  354. package/docs/guides/flow-control.md +210 -349
  355. package/docs/guides/flows-from-json.md +224 -0
  356. package/docs/guides/instructions.md +125 -161
  357. package/docs/guides/persistence.md +182 -206
  358. package/docs/guides/streaming.md +50 -114
  359. package/docs/guides/testing.md +284 -0
  360. package/docs/guides/triggers.md +401 -0
  361. package/docs/migration/README.md +8 -15
  362. package/docs/migration/v1-to-v2.md +1 -1
  363. package/docs/migration/v2-3-to-v2-4.md +2 -2
  364. package/docs/migration/v2-6-to-v2-7.md +4 -4
  365. package/docs/migration/v3-to-v4.md +452 -0
  366. package/docs/reference/actions-events-conditions.md +396 -0
  367. package/docs/reference/agent.md +244 -0
  368. package/docs/reference/branches.md +75 -203
  369. package/docs/reference/errors.md +188 -144
  370. package/docs/reference/fields.md +125 -0
  371. package/docs/reference/flow-spec.md +248 -0
  372. package/docs/reference/flow.md +104 -192
  373. package/docs/reference/instruction.md +83 -137
  374. package/docs/reference/outcomes.md +273 -0
  375. package/docs/reference/providers.md +525 -302
  376. package/docs/reference/session.md +210 -0
  377. package/docs/reference/step.md +194 -312
  378. package/docs/reference/stores.md +496 -0
  379. package/docs/reference/tool.md +162 -231
  380. package/docs/reference/trigger.md +180 -0
  381. package/docs/rfc/v4-one-flow.md +477 -0
  382. package/docs/start/01-install.md +59 -44
  383. package/docs/start/02-first-agent.md +97 -147
  384. package/docs/start/03-collect-data.md +78 -183
  385. package/docs/start/04-add-tools.md +159 -227
  386. package/docs/start/05-go-to-production.md +167 -164
  387. package/examples/01-quickstart.ts +26 -16
  388. package/examples/02-fields.ts +75 -0
  389. package/examples/03-tools.ts +79 -119
  390. package/examples/04-instructions.ts +60 -87
  391. package/examples/05-branches.ts +78 -0
  392. package/examples/06-triggers-and-waits.ts +148 -0
  393. package/examples/07-streaming.ts +34 -60
  394. package/examples/08-store-and-migration.ts +97 -0
  395. package/examples/09-flows-from-json.ts +107 -0
  396. package/package.json +9 -6
  397. package/src/core/Agent.ts +116 -1512
  398. package/src/core/CompactionEngine.ts +7 -4
  399. package/src/core/FlowSpec.ts +712 -0
  400. package/src/core/Migrate.ts +256 -0
  401. package/src/core/Prompt.ts +156 -0
  402. package/src/core/Runner.ts +1181 -0
  403. package/src/core/Speak.ts +451 -0
  404. package/src/core/Understand.ts +422 -0
  405. package/src/core/contracts.ts +111 -0
  406. package/src/core/falai.ts +86 -0
  407. package/src/core/predicate.ts +56 -0
  408. package/src/index.ts +119 -147
  409. package/src/persistence/MemoryStore.ts +37 -0
  410. package/src/persistence/MongoStore.ts +89 -0
  411. package/src/persistence/OpenSearchStore.ts +153 -0
  412. package/src/persistence/PostgresStore.ts +89 -0
  413. package/src/persistence/PrismaStore.ts +127 -0
  414. package/src/persistence/RedisStore.ts +90 -0
  415. package/src/persistence/SQLiteStore.ts +103 -0
  416. package/src/persistence/sessionRow.ts +45 -0
  417. package/src/providers/DeepSeekProvider.ts +8 -3
  418. package/src/providers/GeminiProvider.ts +4 -3
  419. package/src/providers/OpenAICompatibleProvider.ts +6 -0
  420. package/src/providers/OpenRouterProvider.ts +2 -4
  421. package/src/providers/ProviderAdapter.ts +46 -13
  422. package/src/providers/ZaiProvider.ts +6 -4
  423. package/src/types/agent.ts +124 -397
  424. package/src/types/ai.ts +33 -1
  425. package/src/types/compaction.ts +3 -1
  426. package/src/types/errors.ts +13 -16
  427. package/src/types/flow.ts +249 -550
  428. package/src/types/history.ts +7 -20
  429. package/src/types/index.ts +87 -139
  430. package/src/types/session.ts +135 -70
  431. package/src/types/tool.ts +42 -267
  432. package/src/utils/clock.ts +70 -0
  433. package/src/utils/duration.ts +33 -0
  434. package/src/utils/history.ts +3 -2
  435. package/src/utils/index.ts +8 -66
  436. package/src/utils/json.ts +5 -0
  437. package/src/utils/outcomes.ts +56 -0
  438. package/src/utils/schema.ts +145 -0
  439. package/src/utils/streamingMessage.ts +34 -4
  440. package/src/utils/template.ts +32 -423
  441. package/src/utils/usage.ts +37 -0
  442. package/dist/adapters/MemoryAdapter.d.ts +0 -47
  443. package/dist/adapters/MemoryAdapter.d.ts.map +0 -1
  444. package/dist/adapters/MemoryAdapter.js +0 -204
  445. package/dist/adapters/MemoryAdapter.js.map +0 -1
  446. package/dist/adapters/MongoAdapter.d.ts +0 -97
  447. package/dist/adapters/MongoAdapter.d.ts.map +0 -1
  448. package/dist/adapters/MongoAdapter.js +0 -196
  449. package/dist/adapters/MongoAdapter.js.map +0 -1
  450. package/dist/adapters/OpenSearchAdapter.d.ts +0 -169
  451. package/dist/adapters/OpenSearchAdapter.d.ts.map +0 -1
  452. package/dist/adapters/OpenSearchAdapter.js +0 -471
  453. package/dist/adapters/OpenSearchAdapter.js.map +0 -1
  454. package/dist/adapters/PostgreSQLAdapter.d.ts +0 -85
  455. package/dist/adapters/PostgreSQLAdapter.d.ts.map +0 -1
  456. package/dist/adapters/PostgreSQLAdapter.js +0 -308
  457. package/dist/adapters/PostgreSQLAdapter.js.map +0 -1
  458. package/dist/adapters/PrismaAdapter.d.ts +0 -115
  459. package/dist/adapters/PrismaAdapter.d.ts.map +0 -1
  460. package/dist/adapters/PrismaAdapter.js +0 -406
  461. package/dist/adapters/PrismaAdapter.js.map +0 -1
  462. package/dist/adapters/RedisAdapter.d.ts +0 -72
  463. package/dist/adapters/RedisAdapter.d.ts.map +0 -1
  464. package/dist/adapters/RedisAdapter.js +0 -286
  465. package/dist/adapters/RedisAdapter.js.map +0 -1
  466. package/dist/adapters/SQLiteAdapter.d.ts +0 -86
  467. package/dist/adapters/SQLiteAdapter.d.ts.map +0 -1
  468. package/dist/adapters/SQLiteAdapter.js +0 -337
  469. package/dist/adapters/SQLiteAdapter.js.map +0 -1
  470. package/dist/adapters/index.d.ts +0 -17
  471. package/dist/adapters/index.d.ts.map +0 -1
  472. package/dist/adapters/index.js +0 -11
  473. package/dist/adapters/index.js.map +0 -1
  474. package/dist/adapters/sessionRow.d.ts +0 -22
  475. package/dist/adapters/sessionRow.d.ts.map +0 -1
  476. package/dist/adapters/sessionRow.js +0 -48
  477. package/dist/adapters/sessionRow.js.map +0 -1
  478. package/dist/cjs/adapters/MemoryAdapter.d.ts +0 -47
  479. package/dist/cjs/adapters/MemoryAdapter.d.ts.map +0 -1
  480. package/dist/cjs/adapters/MemoryAdapter.js +0 -208
  481. package/dist/cjs/adapters/MemoryAdapter.js.map +0 -1
  482. package/dist/cjs/adapters/MongoAdapter.d.ts +0 -97
  483. package/dist/cjs/adapters/MongoAdapter.d.ts.map +0 -1
  484. package/dist/cjs/adapters/MongoAdapter.js +0 -200
  485. package/dist/cjs/adapters/MongoAdapter.js.map +0 -1
  486. package/dist/cjs/adapters/OpenSearchAdapter.d.ts +0 -169
  487. package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +0 -1
  488. package/dist/cjs/adapters/OpenSearchAdapter.js +0 -475
  489. package/dist/cjs/adapters/OpenSearchAdapter.js.map +0 -1
  490. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts +0 -85
  491. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +0 -1
  492. package/dist/cjs/adapters/PostgreSQLAdapter.js +0 -312
  493. package/dist/cjs/adapters/PostgreSQLAdapter.js.map +0 -1
  494. package/dist/cjs/adapters/PrismaAdapter.d.ts +0 -115
  495. package/dist/cjs/adapters/PrismaAdapter.d.ts.map +0 -1
  496. package/dist/cjs/adapters/PrismaAdapter.js +0 -410
  497. package/dist/cjs/adapters/PrismaAdapter.js.map +0 -1
  498. package/dist/cjs/adapters/RedisAdapter.d.ts +0 -72
  499. package/dist/cjs/adapters/RedisAdapter.d.ts.map +0 -1
  500. package/dist/cjs/adapters/RedisAdapter.js +0 -290
  501. package/dist/cjs/adapters/RedisAdapter.js.map +0 -1
  502. package/dist/cjs/adapters/SQLiteAdapter.d.ts +0 -86
  503. package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +0 -1
  504. package/dist/cjs/adapters/SQLiteAdapter.js +0 -341
  505. package/dist/cjs/adapters/SQLiteAdapter.js.map +0 -1
  506. package/dist/cjs/adapters/index.d.ts +0 -17
  507. package/dist/cjs/adapters/index.d.ts.map +0 -1
  508. package/dist/cjs/adapters/index.js +0 -21
  509. package/dist/cjs/adapters/index.js.map +0 -1
  510. package/dist/cjs/adapters/sessionRow.d.ts +0 -22
  511. package/dist/cjs/adapters/sessionRow.d.ts.map +0 -1
  512. package/dist/cjs/adapters/sessionRow.js +0 -52
  513. package/dist/cjs/adapters/sessionRow.js.map +0 -1
  514. package/dist/cjs/constants/index.d.ts +0 -1
  515. package/dist/cjs/constants/index.d.ts.map +0 -1
  516. package/dist/cjs/constants/index.js +0 -4
  517. package/dist/cjs/constants/index.js.map +0 -1
  518. package/dist/cjs/core/AutoChainExecutor.d.ts +0 -97
  519. package/dist/cjs/core/AutoChainExecutor.d.ts.map +0 -1
  520. package/dist/cjs/core/AutoChainExecutor.js +0 -288
  521. package/dist/cjs/core/AutoChainExecutor.js.map +0 -1
  522. package/dist/cjs/core/BranchEvaluator.d.ts +0 -55
  523. package/dist/cjs/core/BranchEvaluator.d.ts.map +0 -1
  524. package/dist/cjs/core/BranchEvaluator.js +0 -125
  525. package/dist/cjs/core/BranchEvaluator.js.map +0 -1
  526. package/dist/cjs/core/DirectiveChainTracker.d.ts +0 -49
  527. package/dist/cjs/core/DirectiveChainTracker.d.ts.map +0 -1
  528. package/dist/cjs/core/DirectiveChainTracker.js +0 -121
  529. package/dist/cjs/core/DirectiveChainTracker.js.map +0 -1
  530. package/dist/cjs/core/Events.d.ts +0 -26
  531. package/dist/cjs/core/Events.d.ts.map +0 -1
  532. package/dist/cjs/core/Events.js +0 -144
  533. package/dist/cjs/core/Events.js.map +0 -1
  534. package/dist/cjs/core/Flow.d.ts +0 -183
  535. package/dist/cjs/core/Flow.d.ts.map +0 -1
  536. package/dist/cjs/core/Flow.js +0 -551
  537. package/dist/cjs/core/Flow.js.map +0 -1
  538. package/dist/cjs/core/FlowRouter.d.ts +0 -183
  539. package/dist/cjs/core/FlowRouter.d.ts.map +0 -1
  540. package/dist/cjs/core/FlowRouter.js +0 -1047
  541. package/dist/cjs/core/FlowRouter.js.map +0 -1
  542. package/dist/cjs/core/PersistenceManager.d.ts +0 -114
  543. package/dist/cjs/core/PersistenceManager.d.ts.map +0 -1
  544. package/dist/cjs/core/PersistenceManager.js +0 -336
  545. package/dist/cjs/core/PersistenceManager.js.map +0 -1
  546. package/dist/cjs/core/PromptComposer.d.ts +0 -47
  547. package/dist/cjs/core/PromptComposer.d.ts.map +0 -1
  548. package/dist/cjs/core/PromptComposer.js +0 -397
  549. package/dist/cjs/core/PromptComposer.js.map +0 -1
  550. package/dist/cjs/core/PromptSectionCache.d.ts +0 -48
  551. package/dist/cjs/core/PromptSectionCache.d.ts.map +0 -1
  552. package/dist/cjs/core/PromptSectionCache.js +0 -108
  553. package/dist/cjs/core/PromptSectionCache.js.map +0 -1
  554. package/dist/cjs/core/ResponseEngine.d.ts +0 -43
  555. package/dist/cjs/core/ResponseEngine.d.ts.map +0 -1
  556. package/dist/cjs/core/ResponseEngine.js +0 -235
  557. package/dist/cjs/core/ResponseEngine.js.map +0 -1
  558. package/dist/cjs/core/ResponseGenerationError.d.ts +0 -30
  559. package/dist/cjs/core/ResponseGenerationError.d.ts.map +0 -1
  560. package/dist/cjs/core/ResponseGenerationError.js +0 -35
  561. package/dist/cjs/core/ResponseGenerationError.js.map +0 -1
  562. package/dist/cjs/core/ResponseModal.d.ts +0 -305
  563. package/dist/cjs/core/ResponseModal.d.ts.map +0 -1
  564. package/dist/cjs/core/ResponseModal.js +0 -1414
  565. package/dist/cjs/core/ResponseModal.js.map +0 -1
  566. package/dist/cjs/core/ResponsePipeline.d.ts +0 -220
  567. package/dist/cjs/core/ResponsePipeline.d.ts.map +0 -1
  568. package/dist/cjs/core/ResponsePipeline.js +0 -1040
  569. package/dist/cjs/core/ResponsePipeline.js.map +0 -1
  570. package/dist/cjs/core/SessionFinalizer.d.ts +0 -34
  571. package/dist/cjs/core/SessionFinalizer.d.ts.map +0 -1
  572. package/dist/cjs/core/SessionFinalizer.js +0 -88
  573. package/dist/cjs/core/SessionFinalizer.js.map +0 -1
  574. package/dist/cjs/core/SessionManager.d.ts +0 -112
  575. package/dist/cjs/core/SessionManager.d.ts.map +0 -1
  576. package/dist/cjs/core/SessionManager.js +0 -308
  577. package/dist/cjs/core/SessionManager.js.map +0 -1
  578. package/dist/cjs/core/SignalCoordinator.d.ts +0 -103
  579. package/dist/cjs/core/SignalCoordinator.d.ts.map +0 -1
  580. package/dist/cjs/core/SignalCoordinator.js +0 -207
  581. package/dist/cjs/core/SignalCoordinator.js.map +0 -1
  582. package/dist/cjs/core/SignalEvaluator.d.ts +0 -86
  583. package/dist/cjs/core/SignalEvaluator.d.ts.map +0 -1
  584. package/dist/cjs/core/SignalEvaluator.js +0 -319
  585. package/dist/cjs/core/SignalEvaluator.js.map +0 -1
  586. package/dist/cjs/core/SignalProcessor.d.ts +0 -152
  587. package/dist/cjs/core/SignalProcessor.d.ts.map +0 -1
  588. package/dist/cjs/core/SignalProcessor.js +0 -505
  589. package/dist/cjs/core/SignalProcessor.js.map +0 -1
  590. package/dist/cjs/core/Step.d.ts +0 -184
  591. package/dist/cjs/core/Step.d.ts.map +0 -1
  592. package/dist/cjs/core/Step.js +0 -599
  593. package/dist/cjs/core/Step.js.map +0 -1
  594. package/dist/cjs/core/StepLifecycle.d.ts +0 -43
  595. package/dist/cjs/core/StepLifecycle.d.ts.map +0 -1
  596. package/dist/cjs/core/StepLifecycle.js +0 -180
  597. package/dist/cjs/core/StepLifecycle.js.map +0 -1
  598. package/dist/cjs/core/StreamingToolExecutor.d.ts +0 -142
  599. package/dist/cjs/core/StreamingToolExecutor.d.ts.map +0 -1
  600. package/dist/cjs/core/StreamingToolExecutor.js +0 -490
  601. package/dist/cjs/core/StreamingToolExecutor.js.map +0 -1
  602. package/dist/cjs/core/ToolLoopExecutor.d.ts +0 -133
  603. package/dist/cjs/core/ToolLoopExecutor.d.ts.map +0 -1
  604. package/dist/cjs/core/ToolLoopExecutor.js +0 -568
  605. package/dist/cjs/core/ToolLoopExecutor.js.map +0 -1
  606. package/dist/cjs/core/ToolManager.d.ts +0 -250
  607. package/dist/cjs/core/ToolManager.d.ts.map +0 -1
  608. package/dist/cjs/core/ToolManager.js +0 -1104
  609. package/dist/cjs/core/ToolManager.js.map +0 -1
  610. package/dist/cjs/core/createAgent.d.ts +0 -35
  611. package/dist/cjs/core/createAgent.d.ts.map +0 -1
  612. package/dist/cjs/core/createAgent.js +0 -39
  613. package/dist/cjs/core/createAgent.js.map +0 -1
  614. package/dist/cjs/core/flow-namespace.d.ts +0 -64
  615. package/dist/cjs/core/flow-namespace.d.ts.map +0 -1
  616. package/dist/cjs/core/flow-namespace.js +0 -182
  617. package/dist/cjs/core/flow-namespace.js.map +0 -1
  618. package/dist/cjs/core/toolGates.d.ts +0 -24
  619. package/dist/cjs/core/toolGates.d.ts.map +0 -1
  620. package/dist/cjs/core/toolGates.js +0 -52
  621. package/dist/cjs/core/toolGates.js.map +0 -1
  622. package/dist/cjs/types/persistence.d.ts +0 -254
  623. package/dist/cjs/types/persistence.d.ts.map +0 -1
  624. package/dist/cjs/types/persistence.js +0 -7
  625. package/dist/cjs/types/persistence.js.map +0 -1
  626. package/dist/cjs/types/prompt-cache.d.ts +0 -15
  627. package/dist/cjs/types/prompt-cache.d.ts.map +0 -1
  628. package/dist/cjs/types/prompt-cache.js +0 -6
  629. package/dist/cjs/types/prompt-cache.js.map +0 -1
  630. package/dist/cjs/types/signals.d.ts +0 -263
  631. package/dist/cjs/types/signals.d.ts.map +0 -1
  632. package/dist/cjs/types/signals.js +0 -11
  633. package/dist/cjs/types/signals.js.map +0 -1
  634. package/dist/cjs/types/template.d.ts +0 -84
  635. package/dist/cjs/types/template.d.ts.map +0 -1
  636. package/dist/cjs/types/template.js +0 -3
  637. package/dist/cjs/types/template.js.map +0 -1
  638. package/dist/cjs/utils/condition.d.ts +0 -63
  639. package/dist/cjs/utils/condition.d.ts.map +0 -1
  640. package/dist/cjs/utils/condition.js +0 -239
  641. package/dist/cjs/utils/condition.js.map +0 -1
  642. package/dist/cjs/utils/event.d.ts +0 -6
  643. package/dist/cjs/utils/event.d.ts.map +0 -1
  644. package/dist/cjs/utils/event.js +0 -20
  645. package/dist/cjs/utils/event.js.map +0 -1
  646. package/dist/cjs/utils/id.d.ts +0 -33
  647. package/dist/cjs/utils/id.d.ts.map +0 -1
  648. package/dist/cjs/utils/id.js +0 -84
  649. package/dist/cjs/utils/id.js.map +0 -1
  650. package/dist/cjs/utils/serialize.d.ts +0 -36
  651. package/dist/cjs/utils/serialize.d.ts.map +0 -1
  652. package/dist/cjs/utils/serialize.js +0 -77
  653. package/dist/cjs/utils/serialize.js.map +0 -1
  654. package/dist/cjs/utils/session.d.ts +0 -124
  655. package/dist/cjs/utils/session.d.ts.map +0 -1
  656. package/dist/cjs/utils/session.js +0 -396
  657. package/dist/cjs/utils/session.js.map +0 -1
  658. package/dist/constants/index.d.ts +0 -2
  659. package/dist/constants/index.d.ts.map +0 -1
  660. package/dist/constants/index.js +0 -4
  661. package/dist/constants/index.js.map +0 -1
  662. package/dist/core/AutoChainExecutor.d.ts +0 -97
  663. package/dist/core/AutoChainExecutor.d.ts.map +0 -1
  664. package/dist/core/AutoChainExecutor.js +0 -284
  665. package/dist/core/AutoChainExecutor.js.map +0 -1
  666. package/dist/core/BranchEvaluator.d.ts +0 -55
  667. package/dist/core/BranchEvaluator.d.ts.map +0 -1
  668. package/dist/core/BranchEvaluator.js +0 -121
  669. package/dist/core/BranchEvaluator.js.map +0 -1
  670. package/dist/core/DirectiveChainTracker.d.ts +0 -49
  671. package/dist/core/DirectiveChainTracker.d.ts.map +0 -1
  672. package/dist/core/DirectiveChainTracker.js +0 -117
  673. package/dist/core/DirectiveChainTracker.js.map +0 -1
  674. package/dist/core/Events.d.ts +0 -26
  675. package/dist/core/Events.d.ts.map +0 -1
  676. package/dist/core/Events.js +0 -137
  677. package/dist/core/Events.js.map +0 -1
  678. package/dist/core/Flow.d.ts +0 -183
  679. package/dist/core/Flow.d.ts.map +0 -1
  680. package/dist/core/Flow.js +0 -547
  681. package/dist/core/Flow.js.map +0 -1
  682. package/dist/core/FlowRouter.d.ts +0 -183
  683. package/dist/core/FlowRouter.d.ts.map +0 -1
  684. package/dist/core/FlowRouter.js +0 -1043
  685. package/dist/core/FlowRouter.js.map +0 -1
  686. package/dist/core/PersistenceManager.d.ts +0 -114
  687. package/dist/core/PersistenceManager.d.ts.map +0 -1
  688. package/dist/core/PersistenceManager.js +0 -332
  689. package/dist/core/PersistenceManager.js.map +0 -1
  690. package/dist/core/PromptComposer.d.ts +0 -47
  691. package/dist/core/PromptComposer.d.ts.map +0 -1
  692. package/dist/core/PromptComposer.js +0 -393
  693. package/dist/core/PromptComposer.js.map +0 -1
  694. package/dist/core/PromptSectionCache.d.ts +0 -48
  695. package/dist/core/PromptSectionCache.d.ts.map +0 -1
  696. package/dist/core/PromptSectionCache.js +0 -104
  697. package/dist/core/PromptSectionCache.js.map +0 -1
  698. package/dist/core/ResponseEngine.d.ts +0 -43
  699. package/dist/core/ResponseEngine.d.ts.map +0 -1
  700. package/dist/core/ResponseEngine.js +0 -231
  701. package/dist/core/ResponseEngine.js.map +0 -1
  702. package/dist/core/ResponseGenerationError.d.ts +0 -30
  703. package/dist/core/ResponseGenerationError.d.ts.map +0 -1
  704. package/dist/core/ResponseGenerationError.js +0 -31
  705. package/dist/core/ResponseGenerationError.js.map +0 -1
  706. package/dist/core/ResponseModal.d.ts +0 -305
  707. package/dist/core/ResponseModal.d.ts.map +0 -1
  708. package/dist/core/ResponseModal.js +0 -1410
  709. package/dist/core/ResponseModal.js.map +0 -1
  710. package/dist/core/ResponsePipeline.d.ts +0 -220
  711. package/dist/core/ResponsePipeline.d.ts.map +0 -1
  712. package/dist/core/ResponsePipeline.js +0 -1035
  713. package/dist/core/ResponsePipeline.js.map +0 -1
  714. package/dist/core/SessionFinalizer.d.ts +0 -34
  715. package/dist/core/SessionFinalizer.d.ts.map +0 -1
  716. package/dist/core/SessionFinalizer.js +0 -84
  717. package/dist/core/SessionFinalizer.js.map +0 -1
  718. package/dist/core/SessionManager.d.ts +0 -112
  719. package/dist/core/SessionManager.d.ts.map +0 -1
  720. package/dist/core/SessionManager.js +0 -301
  721. package/dist/core/SessionManager.js.map +0 -1
  722. package/dist/core/SignalCoordinator.d.ts +0 -103
  723. package/dist/core/SignalCoordinator.d.ts.map +0 -1
  724. package/dist/core/SignalCoordinator.js +0 -203
  725. package/dist/core/SignalCoordinator.js.map +0 -1
  726. package/dist/core/SignalEvaluator.d.ts +0 -86
  727. package/dist/core/SignalEvaluator.d.ts.map +0 -1
  728. package/dist/core/SignalEvaluator.js +0 -312
  729. package/dist/core/SignalEvaluator.js.map +0 -1
  730. package/dist/core/SignalProcessor.d.ts +0 -152
  731. package/dist/core/SignalProcessor.d.ts.map +0 -1
  732. package/dist/core/SignalProcessor.js +0 -498
  733. package/dist/core/SignalProcessor.js.map +0 -1
  734. package/dist/core/Step.d.ts +0 -184
  735. package/dist/core/Step.d.ts.map +0 -1
  736. package/dist/core/Step.js +0 -594
  737. package/dist/core/Step.js.map +0 -1
  738. package/dist/core/StepLifecycle.d.ts +0 -43
  739. package/dist/core/StepLifecycle.d.ts.map +0 -1
  740. package/dist/core/StepLifecycle.js +0 -176
  741. package/dist/core/StepLifecycle.js.map +0 -1
  742. package/dist/core/StreamingToolExecutor.d.ts +0 -142
  743. package/dist/core/StreamingToolExecutor.d.ts.map +0 -1
  744. package/dist/core/StreamingToolExecutor.js +0 -483
  745. package/dist/core/StreamingToolExecutor.js.map +0 -1
  746. package/dist/core/ToolLoopExecutor.d.ts +0 -133
  747. package/dist/core/ToolLoopExecutor.d.ts.map +0 -1
  748. package/dist/core/ToolLoopExecutor.js +0 -564
  749. package/dist/core/ToolLoopExecutor.js.map +0 -1
  750. package/dist/core/ToolManager.d.ts +0 -250
  751. package/dist/core/ToolManager.d.ts.map +0 -1
  752. package/dist/core/ToolManager.js +0 -1098
  753. package/dist/core/ToolManager.js.map +0 -1
  754. package/dist/core/createAgent.d.ts +0 -35
  755. package/dist/core/createAgent.d.ts.map +0 -1
  756. package/dist/core/createAgent.js +0 -36
  757. package/dist/core/createAgent.js.map +0 -1
  758. package/dist/core/flow-namespace.d.ts +0 -64
  759. package/dist/core/flow-namespace.d.ts.map +0 -1
  760. package/dist/core/flow-namespace.js +0 -179
  761. package/dist/core/flow-namespace.js.map +0 -1
  762. package/dist/core/toolGates.d.ts +0 -24
  763. package/dist/core/toolGates.d.ts.map +0 -1
  764. package/dist/core/toolGates.js +0 -49
  765. package/dist/core/toolGates.js.map +0 -1
  766. package/dist/types/persistence.d.ts +0 -254
  767. package/dist/types/persistence.d.ts.map +0 -1
  768. package/dist/types/persistence.js +0 -6
  769. package/dist/types/persistence.js.map +0 -1
  770. package/dist/types/prompt-cache.d.ts +0 -15
  771. package/dist/types/prompt-cache.d.ts.map +0 -1
  772. package/dist/types/prompt-cache.js +0 -5
  773. package/dist/types/prompt-cache.js.map +0 -1
  774. package/dist/types/signals.d.ts +0 -263
  775. package/dist/types/signals.d.ts.map +0 -1
  776. package/dist/types/signals.js +0 -10
  777. package/dist/types/signals.js.map +0 -1
  778. package/dist/types/template.d.ts +0 -84
  779. package/dist/types/template.d.ts.map +0 -1
  780. package/dist/types/template.js +0 -2
  781. package/dist/types/template.js.map +0 -1
  782. package/dist/utils/condition.d.ts +0 -63
  783. package/dist/utils/condition.d.ts.map +0 -1
  784. package/dist/utils/condition.js +0 -230
  785. package/dist/utils/condition.js.map +0 -1
  786. package/dist/utils/event.d.ts +0 -6
  787. package/dist/utils/event.d.ts.map +0 -1
  788. package/dist/utils/event.js +0 -17
  789. package/dist/utils/event.js.map +0 -1
  790. package/dist/utils/id.d.ts +0 -33
  791. package/dist/utils/id.d.ts.map +0 -1
  792. package/dist/utils/id.js +0 -77
  793. package/dist/utils/id.js.map +0 -1
  794. package/dist/utils/serialize.d.ts +0 -36
  795. package/dist/utils/serialize.d.ts.map +0 -1
  796. package/dist/utils/serialize.js +0 -72
  797. package/dist/utils/serialize.js.map +0 -1
  798. package/dist/utils/session.d.ts +0 -124
  799. package/dist/utils/session.d.ts.map +0 -1
  800. package/dist/utils/session.js +0 -379
  801. package/dist/utils/session.js.map +0 -1
  802. package/docs/concepts/directives.md +0 -369
  803. package/docs/reference/adapters.md +0 -543
  804. package/docs/reference/create-agent.md +0 -216
  805. package/docs/reference/directive.md +0 -242
  806. package/docs/reference/signals.md +0 -368
  807. package/examples/02-data-extraction.ts +0 -90
  808. package/examples/05-branching.ts +0 -140
  809. package/examples/06-flow-control.ts +0 -103
  810. package/examples/08-persistence.ts +0 -98
  811. package/examples/09-signals.ts +0 -144
  812. package/src/adapters/MemoryAdapter.ts +0 -281
  813. package/src/adapters/MongoAdapter.ts +0 -341
  814. package/src/adapters/OpenSearchAdapter.ts +0 -693
  815. package/src/adapters/PostgreSQLAdapter.ts +0 -487
  816. package/src/adapters/PrismaAdapter.ts +0 -617
  817. package/src/adapters/RedisAdapter.ts +0 -439
  818. package/src/adapters/SQLiteAdapter.ts +0 -496
  819. package/src/adapters/index.ts +0 -43
  820. package/src/adapters/sessionRow.ts +0 -57
  821. package/src/constants/index.ts +0 -2
  822. package/src/core/AutoChainExecutor.ts +0 -397
  823. package/src/core/BranchEvaluator.ts +0 -161
  824. package/src/core/DirectiveChainTracker.ts +0 -144
  825. package/src/core/Events.ts +0 -164
  826. package/src/core/Flow.ts +0 -665
  827. package/src/core/FlowRouter.ts +0 -1540
  828. package/src/core/PersistenceManager.ts +0 -446
  829. package/src/core/PromptComposer.ts +0 -448
  830. package/src/core/PromptSectionCache.ts +0 -125
  831. package/src/core/ResponseEngine.ts +0 -338
  832. package/src/core/ResponseGenerationError.ts +0 -53
  833. package/src/core/ResponseModal.ts +0 -1902
  834. package/src/core/ResponsePipeline.ts +0 -1404
  835. package/src/core/SessionFinalizer.ts +0 -108
  836. package/src/core/SessionManager.ts +0 -372
  837. package/src/core/SignalCoordinator.ts +0 -263
  838. package/src/core/SignalEvaluator.ts +0 -404
  839. package/src/core/SignalProcessor.ts +0 -663
  840. package/src/core/Step.ts +0 -782
  841. package/src/core/StepLifecycle.ts +0 -242
  842. package/src/core/StreamingToolExecutor.ts +0 -609
  843. package/src/core/ToolLoopExecutor.ts +0 -749
  844. package/src/core/ToolManager.ts +0 -1379
  845. package/src/core/createAgent.ts +0 -40
  846. package/src/core/flow-namespace.ts +0 -227
  847. package/src/core/toolGates.ts +0 -72
  848. package/src/types/persistence.ts +0 -303
  849. package/src/types/prompt-cache.ts +0 -17
  850. package/src/types/signals.ts +0 -338
  851. package/src/types/template.ts +0 -98
  852. package/src/utils/condition.ts +0 -296
  853. package/src/utils/event.ts +0 -16
  854. package/src/utils/id.ts +0 -91
  855. package/src/utils/serialize.ts +0 -86
  856. package/src/utils/session.ts +0 -501
@@ -0,0 +1,1131 @@
1
+ "use strict";
2
+ /**
3
+ * Runner: the code half of a turn. Load, Ingest, Decide, Run, Settle and
4
+ * Return (design §4) with one applier, `advance`. Zero provider calls live
5
+ * here: the Agent asks `understandRequest` and `advance` what to judge and
6
+ * what to speak, spends the calls, and hands the plain results back to
7
+ * `decide` and `settle`.
8
+ *
9
+ * begin ─▶ understandRequest ─(Understand)─▶ decide ─▶ advance ─(Speak)─▶ settle ─▶ finish
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.Runner = void 0;
13
+ const clone_js_1 = require("../utils/clone.js");
14
+ const duration_js_1 = require("../utils/duration.js");
15
+ const outcomes_js_1 = require("../utils/outcomes.js");
16
+ const schema_js_1 = require("../utils/schema.js");
17
+ const template_js_1 = require("../utils/template.js");
18
+ const usage_js_1 = require("../utils/usage.js");
19
+ const predicate_js_1 = require("./predicate.js");
20
+ /** A `wait` this short rides as `afterMs` on the next message instead of a real wake. */
21
+ const SHORT_WAIT_MS = 10000;
22
+ const MAX_STEPS_PER_TURN = 50;
23
+ const MAX_HOP = 5;
24
+ /** Kept always-claims per flow and anchor, kept input ids, kept outcomes per run. */
25
+ const KEEP = 50;
26
+ /**
27
+ * How long a talk step waits after the provider failed, and how many times. The
28
+ * ladder used to be three rungs clamped by `Math.min`, which meant it never
29
+ * ran out: a stuck session re-ran understand AND speak every fifteen minutes
30
+ * for as long as it existed. It now ends after the last rung, so one outage
31
+ * costs at most five retries spread over seven hours instead of forever.
32
+ */
33
+ const RETRY_BACKOFF = ["1m", "5m", "15m", "1h", "6h"];
34
+ const DEFAULT_EVENT_WAIT = "30d";
35
+ const ROUTE_MIN = 40;
36
+ const ROUTE_STICKY = 15;
37
+ function isTalk(step) {
38
+ return "prompt" in step || "collect" in step;
39
+ }
40
+ function isSay(step) {
41
+ return "say" in step;
42
+ }
43
+ function isDo(step) {
44
+ return "do" in step;
45
+ }
46
+ function isWait(step) {
47
+ return "wait" in step && typeof step.wait === "string";
48
+ }
49
+ function isWaitEvent(step) {
50
+ return "wait" in step && typeof step.wait === "object";
51
+ }
52
+ function isIf(step) {
53
+ return "if" in step;
54
+ }
55
+ function triggerKind(trigger) {
56
+ if ("message" in trigger)
57
+ return "message";
58
+ if ("mention" in trigger)
59
+ return "mention";
60
+ if ("silence" in trigger)
61
+ return "silence";
62
+ return "event";
63
+ }
64
+ function defaultRepeat(kind) {
65
+ return kind === "message" || kind === "mention" || kind === "silence" ? "once" : "always";
66
+ }
67
+ function talkKind(step) {
68
+ return step.collect?.length ? "collect" : "prompt";
69
+ }
70
+ function kindOf(step) {
71
+ if (!step)
72
+ return "if";
73
+ if (isTalk(step))
74
+ return talkKind(step);
75
+ if (isSay(step))
76
+ return "say";
77
+ if (isDo(step))
78
+ return "do";
79
+ if (isIf(step))
80
+ return "if";
81
+ return "wait";
82
+ }
83
+ function describe(input, nowIso) {
84
+ if ("message" in input)
85
+ return { kind: "message", text: input.message, id: input.id, at: input.at ?? nowIso };
86
+ if ("wake" in input)
87
+ return { kind: "wake", key: input.wake };
88
+ if ("event" in input)
89
+ return { kind: "event", name: input.event, payload: input.payload, key: input.key, hop: input.hop ?? 0 };
90
+ return { kind: "start", flow: input.start.flow, input: input.start.input, key: input.start.key, hop: input.start.hop ?? 0 };
91
+ }
92
+ function freshSession(id) {
93
+ return { id, v: 4, version: 0, data: {}, runs: [], claims: {}, inputs: [], metadata: {} };
94
+ }
95
+ function keepLast(list, n) {
96
+ if (list.length > n)
97
+ list.splice(0, list.length - n);
98
+ }
99
+ class Runner {
100
+ constructor(options) {
101
+ this.options = options;
102
+ this.flows = new Map((options.flows ?? []).map((flow) => [flow.id, flow]));
103
+ }
104
+ // ── Load + Ingest ─────────────────────────────────────────────────────
105
+ begin(input) {
106
+ const now = (this.options.clock ?? (() => new Date()))();
107
+ const nowIso = now.toISOString();
108
+ const what = describe(input, nowIso);
109
+ const silenced = typeof input.silenced === "string" ? input.silenced : input.silenced?.reason;
110
+ const turn = {
111
+ input,
112
+ what,
113
+ kind: what.kind,
114
+ triggerKey: what.kind === "message" ? (what.id ?? what.at) : what.key,
115
+ session: input.session ? (0, clone_js_1.cloneDeep)(input.session) : freshSession(input.sessionId),
116
+ original: input.session,
117
+ now,
118
+ nowIso,
119
+ // `context` is optional only when C allows undefined, so this is C at every call site that compiles.
120
+ context: input.context,
121
+ silenced,
122
+ understandAllowed: typeof input.silenced === "object" && input.silenced.understand === true,
123
+ ignored: false,
124
+ messages: [],
125
+ schedule: [],
126
+ outcomes: [],
127
+ started: [],
128
+ ended: [],
129
+ skipped: [],
130
+ llmCalls: 0,
131
+ floorFromIngest: false,
132
+ ingesting: false,
133
+ spokeBy: new Set(),
134
+ spoke: false,
135
+ afterMs: 0,
136
+ speakDone: false,
137
+ queue: [],
138
+ };
139
+ if (what.kind === "wake" && !input.session) {
140
+ this.ignore(turn, "no-session", what.key);
141
+ return turn;
142
+ }
143
+ turn.ingesting = true;
144
+ this.ingest(turn);
145
+ turn.ingesting = false;
146
+ return turn;
147
+ }
148
+ ingest(turn) {
149
+ const { what, session } = turn;
150
+ switch (what.kind) {
151
+ case "message": {
152
+ if (what.id) {
153
+ if (session.inputs.includes(what.id)) {
154
+ this.ignore(turn, "duplicate-input", what.id);
155
+ return;
156
+ }
157
+ session.inputs.push(what.id);
158
+ keepLast(session.inputs, KEEP);
159
+ }
160
+ session.lastUserAt = what.at;
161
+ this.resolveReplyWaits(turn);
162
+ return;
163
+ }
164
+ case "wake":
165
+ if (what.key.startsWith("silence:"))
166
+ this.silenceWake(turn, what.key);
167
+ else
168
+ this.runWake(turn, what.key);
169
+ return;
170
+ case "event": {
171
+ const direction = this.options.events?.[what.name]?.direction;
172
+ if (direction === "inbound") {
173
+ session.lastUserAt = turn.nowIso;
174
+ this.resolveReplyWaits(turn);
175
+ }
176
+ else if (direction === "outbound") {
177
+ session.lastAssistantAt = turn.nowIso;
178
+ }
179
+ for (const run of [...session.runs]) {
180
+ if (run.waiting?.kind !== "event" || run.waiting.event !== what.name)
181
+ continue;
182
+ const flow = this.flows.get(run.flowId);
183
+ const step = flow && this.stepOf(flow, run.stepId);
184
+ run.status = "running";
185
+ delete run.waiting;
186
+ if (!flow || !step)
187
+ continue; // move() reports the missing flow or step
188
+ this.outcome(turn, run, { kind: "wait", status: "ok", code: "event-arrived", next: nextLabel(step.then) });
189
+ this.follow(turn, run, flow, step, step.then);
190
+ this.takeFloor(turn, run);
191
+ }
192
+ for (const flow of this.flows.values()) {
193
+ for (const trigger of flow.on ?? []) {
194
+ if (!("event" in trigger) || trigger.event !== what.name)
195
+ continue;
196
+ if (this.startRun(turn, flow, "event", what.key, { trigger, payload: what.payload, hop: what.hop }))
197
+ break;
198
+ }
199
+ }
200
+ return;
201
+ }
202
+ case "start": {
203
+ const flow = this.flows.get(what.flow);
204
+ if (!flow) {
205
+ turn.skipped.push({ flowId: what.flow, anchor: session.id, triggerKey: what.key, code: "flow-gone", message: outcomes_js_1.OUTCOME_MESSAGES["flow-gone"] });
206
+ return;
207
+ }
208
+ this.startRun(turn, flow, "start", what.key, { payload: what.input, hop: what.hop });
209
+ return;
210
+ }
211
+ }
212
+ }
213
+ /** The lead wrote: every run parked on a timer `wait` with `else` takes `else`, oldest first. */
214
+ resolveReplyWaits(turn) {
215
+ for (const run of [...turn.session.runs]) {
216
+ if (run.status !== "waiting" || run.waiting?.kind !== "timer" || run.stepId === null)
217
+ continue;
218
+ const flow = this.flows.get(run.flowId);
219
+ const step = flow && this.stepOf(flow, run.stepId);
220
+ if (!flow || !step || !isWait(step) || step.else === undefined)
221
+ continue;
222
+ run.status = "running";
223
+ delete run.waiting;
224
+ const branch = step.branches?.find((b) => "if" in b && this.holds(b.if, turn, run));
225
+ const target = branch ? branch.then : step.else;
226
+ this.outcome(turn, run, { kind: "wait", status: "ok", code: "replied", next: nextLabel(target) });
227
+ this.follow(turn, run, flow, step, target);
228
+ this.takeFloor(turn, run);
229
+ }
230
+ }
231
+ /** Honoured only by the run whose `waiting.key` equals it (I3). */
232
+ runWake(turn, key) {
233
+ const run = turn.session.runs.find((r) => r.waiting?.key === key);
234
+ if (!run) {
235
+ this.ignore(turn, "stale-wake", key);
236
+ return;
237
+ }
238
+ const setAt = run.waiting?.setAt ?? run.startedAt;
239
+ run.status = "running";
240
+ delete run.waiting;
241
+ turn.floorRunId = run.id;
242
+ if (run.stepId === null)
243
+ return; // parked on the trigger's `after`: enters its first step in advance()
244
+ const flow = this.flows.get(run.flowId);
245
+ const step = flow && this.stepOf(flow, run.stepId);
246
+ if (!flow || !step)
247
+ return; // move() reports it
248
+ if (isWait(step)) {
249
+ // The reply beat the job: the lead wrote after the wait was set.
250
+ const replied = step.else !== undefined && this.leadWroteSince(turn, setAt, flow);
251
+ const target = replied ? step.else : step.then;
252
+ this.outcome(turn, run, { kind: "wait", status: "ok", code: replied ? "replied" : "no-reply", next: nextLabel(target) });
253
+ this.follow(turn, run, flow, step, target);
254
+ }
255
+ else if (isWaitEvent(step)) {
256
+ // ponytail: an event wait that times out without `else` ends the run; nothing sensible follows an event that never came.
257
+ const target = step.else ?? "end";
258
+ this.outcome(turn, run, { kind: "wait", status: "ok", code: "no-event", next: nextLabel(target) });
259
+ this.follow(turn, run, flow, step, target);
260
+ }
261
+ // A deferred `do` or a retried talk step re-runs at the same visit in advance(): same key, same idempotency.
262
+ }
263
+ /** `silence:<flowId>:<sessionId>:<lastAssistantAtMs>`, honoured only while the blob still shows that silence. */
264
+ silenceWake(turn, key) {
265
+ const rest = key.slice("silence:".length);
266
+ const flowId = rest.slice(0, rest.indexOf(":"));
267
+ const ms = Number(rest.slice(rest.lastIndexOf(":") + 1));
268
+ const { lastAssistantAt } = turn.session;
269
+ const flow = this.flows.get(flowId);
270
+ if (!flow) {
271
+ turn.skipped.push({ flowId, anchor: turn.session.id, triggerKey: String(ms), code: "flow-gone", message: outcomes_js_1.OUTCOME_MESSAGES["flow-gone"] });
272
+ return;
273
+ }
274
+ if (!lastAssistantAt || Date.parse(lastAssistantAt) !== ms || this.leadWroteSince(turn, lastAssistantAt, flow)) {
275
+ this.ignore(turn, "silence-broken", key);
276
+ return;
277
+ }
278
+ const trigger = (flow.on ?? []).find((t) => "silence" in t);
279
+ const run = this.startRun(turn, flow, "silence", String(ms), { trigger });
280
+ if (run)
281
+ turn.floorRunId = run.id;
282
+ }
283
+ ignore(turn, code, key) {
284
+ turn.ignored = true;
285
+ turn.outcomes.push({ kind: "wait", status: "skipped", code, message: outcomes_js_1.OUTCOME_MESSAGES[code], key, at: turn.nowIso });
286
+ }
287
+ takeFloor(turn, run) {
288
+ if (!turn.session.runs.includes(run) || turn.floorFromIngest)
289
+ return;
290
+ turn.floorFromIngest = true;
291
+ turn.floorRunId = run.id;
292
+ }
293
+ // ── Starting runs: the one start order (design §4.2) ─────────────────
294
+ startRun(turn, flow, kind, key, opts) {
295
+ const { session } = turn;
296
+ const anchor = this.anchorOf(turn, flow);
297
+ const hop = opts.hop ?? 0;
298
+ const repeat = opts.trigger?.repeat ?? defaultRepeat(kind);
299
+ const nonce = repeat === "always" ? key : "";
300
+ const dedupeKey = `${flow.id}:${anchor}:${nonce}`;
301
+ const run = {
302
+ id: `${flow.id}#${key}`,
303
+ flowId: flow.id,
304
+ anchor,
305
+ dedupeKey,
306
+ stepId: null,
307
+ status: "running",
308
+ trigger: { kind, key, ...(opts.payload !== undefined ? { payload: opts.payload } : {}) },
309
+ ...(opts.payload !== undefined ? { input: opts.payload } : {}),
310
+ hop,
311
+ startedAt: turn.nowIso,
312
+ asked: {},
313
+ visits: {},
314
+ outcomes: [],
315
+ };
316
+ const skip = (code) => {
317
+ turn.skipped.push({ flowId: flow.id, anchor, triggerKey: key, code, message: outcomes_js_1.OUTCOME_MESSAGES[code] });
318
+ return null;
319
+ };
320
+ if (opts.trigger?.if && !this.holds(opts.trigger.if, turn, run))
321
+ return null;
322
+ const heldAt = this.claimAt(turn, dedupeKey);
323
+ if (heldAt !== undefined) {
324
+ if (typeof repeat === "string")
325
+ return skip("already-claimed");
326
+ if (turn.now.getTime() - Date.parse(heldAt) < (0, duration_js_1.parseDuration)(repeat.cooldown))
327
+ return skip("cooldown");
328
+ }
329
+ if (hop >= MAX_HOP)
330
+ return skip("hop-limit");
331
+ const live = session.runs.find((r) => r.flowId === flow.id && r.anchor === anchor);
332
+ if (live) {
333
+ if (live.status === "waiting" && live.stepId === null)
334
+ this.endRun(turn, live, "replaced");
335
+ else
336
+ return skip("already-running");
337
+ }
338
+ else if (turn.input.claims?.active.includes(`${flow.id}:${anchor}`)) {
339
+ return skip("already-running");
340
+ }
341
+ session.claims[dedupeKey] = { at: turn.nowIso };
342
+ if (nonce)
343
+ this.pruneAlwaysClaims(session, `${flow.id}:${anchor}:`);
344
+ if (!opts.keepData) {
345
+ const data = session.data;
346
+ for (const field of flow.clearOnStart ?? [])
347
+ delete data[field];
348
+ }
349
+ session.runs.push(run);
350
+ turn.started.push({ runId: run.id, flowId: flow.id, anchor, dedupeKey });
351
+ const after = opts.trigger && "event" in opts.trigger ? opts.trigger.after : undefined;
352
+ if (after) {
353
+ const at = this.snap(turn, new Date(turn.now.getTime() + (0, duration_js_1.parseDuration)(after)), opts.trigger && "event" in opts.trigger ? opts.trigger.businessHours : undefined);
354
+ this.park(turn, run, { kind: "timer", key: `${run.id}:start:${at.getTime()}` }, at);
355
+ this.outcome(turn, run, { kind: "wait", status: "waiting", code: "awaiting-trigger", until: at.toISOString() });
356
+ }
357
+ return run;
358
+ }
359
+ /** Always-claims keep the last 50 per flow and anchor; once/cooldown keys (empty nonce) are never pruned. */
360
+ pruneAlwaysClaims(session, prefix) {
361
+ const keys = Object.keys(session.claims).filter((k) => k.startsWith(prefix) && k.length > prefix.length);
362
+ for (const key of keys.slice(0, Math.max(0, keys.length - KEEP)))
363
+ delete session.claims[key];
364
+ }
365
+ anchorOf(turn, flow) {
366
+ if (!flow.anchor || flow.anchor === "session")
367
+ return turn.session.id;
368
+ return turn.input.anchors?.[flow.anchor]?.key ?? turn.session.id;
369
+ }
370
+ claimAt(turn, key) {
371
+ return turn.session.claims[key]?.at ?? turn.input.claims?.held[key];
372
+ }
373
+ repeatAllows(turn, flow, trigger, key) {
374
+ const repeat = trigger.repeat ?? defaultRepeat(triggerKind(trigger));
375
+ const heldAt = this.claimAt(turn, `${flow.id}:${this.anchorOf(turn, flow)}:${repeat === "always" ? key : ""}`);
376
+ if (heldAt === undefined)
377
+ return true;
378
+ if (typeof repeat === "string")
379
+ return false;
380
+ return turn.now.getTime() - Date.parse(heldAt) >= (0, duration_js_1.parseDuration)(repeat.cooldown);
381
+ }
382
+ /** A run as it would be if started now, for trigger-level predicates. */
383
+ draftRun(turn, flow, kind, key, payload) {
384
+ const anchor = this.anchorOf(turn, flow);
385
+ return {
386
+ id: `${flow.id}#${key}`, flowId: flow.id, anchor, dedupeKey: `${flow.id}:${anchor}:`, stepId: null, status: "running",
387
+ trigger: { kind, key }, input: payload, hop: 0, startedAt: turn.nowIso, asked: {}, visits: {}, outcomes: [],
388
+ };
389
+ }
390
+ holds(pred, turn, run, input = run.input) {
391
+ return (0, predicate_js_1.evaluate)(pred, { context: turn.context, data: turn.session.data, input, run, silenced: turn.silenced, now: turn.now }, this.options.conditions ?? {});
392
+ }
393
+ leadWroteSince(turn, sinceIso, flow) {
394
+ const since = Date.parse(sinceIso);
395
+ const { lastUserAt } = turn.session;
396
+ if (lastUserAt && Date.parse(lastUserAt) > since)
397
+ return true;
398
+ if (!flow.anchor || flow.anchor === "session")
399
+ return false;
400
+ const inbound = turn.input.anchors?.[flow.anchor]?.lastInboundAt;
401
+ return inbound !== undefined && Date.parse(inbound) > since;
402
+ }
403
+ snap(turn, at, businessHours) {
404
+ return businessHours && this.options.businessHours ? this.options.businessHours(at, { context: turn.context }) : at;
405
+ }
406
+ stepOf(flow, stepId) {
407
+ return stepId === null ? undefined : flow.steps.find((s) => s.id === stepId);
408
+ }
409
+ stepKey(run, step) {
410
+ return `${run.id}:${step.id}:${run.visits[step.id] ?? 0}`;
411
+ }
412
+ scope(turn, run) {
413
+ return { data: turn.session.data, context: turn.context, input: run.input };
414
+ }
415
+ asker(turn) {
416
+ return turn.session.runs.find((r) => r.status === "asking");
417
+ }
418
+ outcome(turn, run, line) {
419
+ const full = {
420
+ ...(run ? { runId: run.id, flowId: run.flowId, stepId: line.stepId ?? run.stepId ?? undefined } : {}),
421
+ ...line,
422
+ ...(line.code ? { message: outcomes_js_1.OUTCOME_MESSAGES[line.code] } : {}),
423
+ at: turn.nowIso,
424
+ };
425
+ if (full.stepId === undefined)
426
+ delete full.stepId;
427
+ turn.outcomes.push(full);
428
+ if (run) {
429
+ run.outcomes.push(full);
430
+ keepLast(run.outcomes, KEEP);
431
+ }
432
+ }
433
+ // ── Understand: what the one call may judge (design §4.3) ─────────────
434
+ understandRequest(turn) {
435
+ if (turn.ignored || turn.what.kind !== "message")
436
+ return null;
437
+ if (turn.silenced !== undefined && !turn.understandAllowed)
438
+ return null;
439
+ const floorRun = this.floorRun(turn);
440
+ const floorFlow = floorRun && this.flows.get(floorRun.flowId);
441
+ const eligible = this.eligibleMessageFlows(turn);
442
+ // Exactly one eligible message flow and no floor: it starts without scoring (S9).
443
+ const messageFlows = !floorRun && eligible.length === 1 ? [] : eligible;
444
+ const mentionFlows = this.mentionFlows()
445
+ .filter(({ flow, trigger }) => trigger.mention.length > 0 && this.repeatAllows(turn, flow, trigger, turn.triggerKey))
446
+ .map(({ flow }) => flow);
447
+ const branches = [];
448
+ const askingStep = floorRun && floorFlow ? this.stepOf(floorFlow, floorRun.stepId) : undefined;
449
+ if (floorRun && askingStep && isTalk(askingStep)) {
450
+ askingStep.branches?.forEach((branch, index) => {
451
+ if ("when" in branch)
452
+ branches.push({ runId: floorRun.id, stepId: askingStep.id, index, when: branch.when });
453
+ });
454
+ }
455
+ const fields = {};
456
+ const data = turn.session.data;
457
+ for (const flow of [...(floorFlow ? [floorFlow] : []), ...eligible]) {
458
+ for (const step of flow.steps) {
459
+ if (!isTalk(step))
460
+ continue;
461
+ for (const field of step.collect ?? []) {
462
+ const def = this.options.fields[field];
463
+ if (def && !(0, schema_js_1.isKnown)(data[field]) && (0, schema_js_1.extractMode)(def) === "anywhere")
464
+ fields[field] = def;
465
+ }
466
+ }
467
+ }
468
+ if (!messageFlows.length && !mentionFlows.length && !branches.length && !Object.keys(fields).length)
469
+ return null;
470
+ return {
471
+ text: turn.what.text,
472
+ history: this.historyOf(turn),
473
+ context: turn.context,
474
+ data: turn.session.data,
475
+ ...(floorRun && floorFlow ? { floor: { run: floorRun, flow: floorFlow } } : {}),
476
+ messageFlows,
477
+ mentionFlows,
478
+ branches,
479
+ fields,
480
+ };
481
+ }
482
+ /** The host's history for this turn; the session's own (playground) is the fallback. */
483
+ historyOf(turn) {
484
+ return turn.input.history ?? turn.session.history ?? [];
485
+ }
486
+ /** The asker, or the run that took the floor in Ingest. */
487
+ floorRun(turn) {
488
+ const asking = this.asker(turn);
489
+ if (asking)
490
+ return asking;
491
+ return turn.floorRunId ? turn.session.runs.find((r) => r.id === turn.floorRunId) : undefined;
492
+ }
493
+ /** `message` flows with a non-empty list passing `if` and `repeat`, in flow order. */
494
+ eligibleMessageFlows(turn) {
495
+ return this.messageFlows(turn, (list) => list.length > 0);
496
+ }
497
+ messageFlows(turn, accept) {
498
+ const out = [];
499
+ for (const flow of this.flows.values()) {
500
+ const trigger = (flow.on ?? []).find((t) => "message" in t && accept(t.message));
501
+ if (!trigger)
502
+ continue;
503
+ if (trigger.if && !this.holds(trigger.if, turn, this.draftRun(turn, flow, "message", turn.triggerKey)))
504
+ continue;
505
+ if (!this.repeatAllows(turn, flow, trigger, turn.triggerKey))
506
+ continue;
507
+ out.push(flow);
508
+ }
509
+ return out;
510
+ }
511
+ /** Every `mention` flow with its trigger, in flow order. `if` and `repeat` are judged at start, when `extract` is in hand. */
512
+ mentionFlows() {
513
+ const out = [];
514
+ for (const flow of this.flows.values()) {
515
+ const trigger = (flow.on ?? []).find((t) => "mention" in t);
516
+ if (trigger)
517
+ out.push({ flow, trigger });
518
+ }
519
+ return out;
520
+ }
521
+ // ── Decide: apply the judgement (design §4.4) ─────────────────────────
522
+ decide(turn, understanding) {
523
+ if (turn.ignored || turn.what.kind !== "message")
524
+ return;
525
+ turn.llmCalls += understanding?.llmCalls ?? 0;
526
+ turn.usage = (0, usage_js_1.addUsage)(turn.usage, understanding?.usage);
527
+ const key = turn.triggerKey;
528
+ const asker = this.asker(turn);
529
+ // Routing is decided before extraction lands so `clearOnStart` runs first, and applied after mention runs.
530
+ let route;
531
+ if (!turn.floorFromIngest) {
532
+ const eligible = this.eligibleMessageFlows(turn);
533
+ const scores = understanding?.flows ?? {};
534
+ const best = (flows) => flows.map((flow) => ({ flow, score: scores[flow.id] ?? 0 })).reduce((top, cur) => (top && top.score >= cur.score ? top : cur), undefined);
535
+ if (asker) {
536
+ const current = scores[asker.flowId] ?? 0;
537
+ const top = best(eligible.filter((f) => f.id !== asker.flowId));
538
+ if (top && top.score >= current + ROUTE_STICKY && top.score >= ROUTE_MIN)
539
+ route = top.flow;
540
+ }
541
+ else if (eligible.length === 1) {
542
+ route = eligible[0];
543
+ }
544
+ else {
545
+ const top = best(eligible);
546
+ route = top && top.score >= ROUTE_MIN ? top.flow : this.messageFlows(turn, (list) => list.length === 0)[0];
547
+ }
548
+ }
549
+ // A code-only detector (`mention: []`) goes through the full start order here, so a blocked `repeat` is logged as a skip.
550
+ for (const { flow, trigger } of this.mentionFlows()) {
551
+ if (trigger.mention.length === 0)
552
+ this.startRun(turn, flow, "mention", key, { trigger });
553
+ else if (understanding?.mentions[flow.id])
554
+ this.startRun(turn, flow, "mention", key, { trigger, payload: understanding.extract[flow.id] });
555
+ }
556
+ if (route) {
557
+ const suspended = turn.session.runs.find((r) => r.flowId === route.id && r.status === "suspended");
558
+ if (suspended) {
559
+ suspended.status = "running";
560
+ delete suspended.suspendedAt;
561
+ turn.floorRunId = suspended.id;
562
+ }
563
+ else {
564
+ const trigger = (route.on ?? []).find((t) => "message" in t);
565
+ const run = this.startRun(turn, route, "message", key, { trigger });
566
+ if (run)
567
+ turn.floorRunId = run.id;
568
+ }
569
+ }
570
+ for (const [field, raw] of Object.entries(understanding?.fields ?? {}))
571
+ this.writeField(turn, field, raw);
572
+ if (asker && turn.session.runs.includes(asker) && asker.status === "asking") {
573
+ const flow = this.flows.get(asker.flowId);
574
+ const step = flow && this.stepOf(flow, asker.stepId);
575
+ if (flow && step && isTalk(step))
576
+ this.fireBranch(turn, asker, flow, step, understanding);
577
+ }
578
+ }
579
+ fireBranch(turn, run, flow, step, understanding) {
580
+ const hit = (branch, index) => "if" in branch ? this.holds(branch.if, turn, run) : understanding?.branches[`${run.id}/${step.id}/${index}`] === true;
581
+ const index = (step.branches ?? []).findIndex(hit);
582
+ if (index < 0)
583
+ return;
584
+ const branch = (step.branches ?? [])[index];
585
+ this.outcome(turn, run, { kind: talkKind(step), status: "ok", key: this.stepKey(run, step), code: "branch", next: nextLabel(branch.then) });
586
+ run.status = "running";
587
+ this.follow(turn, run, flow, step, branch.then);
588
+ }
589
+ /** Validate a raw extracted value and write it; unknown or invalid values leave an outcome line instead. */
590
+ writeField(turn, field, raw) {
591
+ if (raw === undefined || raw === null)
592
+ return;
593
+ const def = this.options.fields[field];
594
+ if (!def) {
595
+ this.outcome(turn, undefined, { kind: "collect", status: "skipped", code: "unknown-field", detail: field });
596
+ return;
597
+ }
598
+ const coerced = (0, schema_js_1.coerceField)(def, raw);
599
+ if (!coerced.ok) {
600
+ this.outcome(turn, undefined, { kind: "collect", status: "skipped", code: coerced.code, detail: field });
601
+ return;
602
+ }
603
+ const data = turn.session.data;
604
+ data[field] = coerced.value;
605
+ }
606
+ // ── Run: move everything that can move (design §4.5) ──────────────────
607
+ async advance(turn) {
608
+ if (turn.ignored)
609
+ return null;
610
+ this.resumeSuspended(turn);
611
+ turn.queue = [...turn.session.runs];
612
+ await this.drain(turn);
613
+ return this.speaker(turn);
614
+ }
615
+ /**
616
+ * Everything Speak needs for this turn's one speaker. Instructions are agent,
617
+ * then flow, then step (idle: agent, then idle), each already judged by its
618
+ * `if`; tools are the step's list, else the flow's, else every agent tool.
619
+ */
620
+ speakRequest(turn, talk) {
621
+ const own = "idle" in talk
622
+ ? { instructions: talk.idle.instructions ?? [], tools: talk.idle.tools }
623
+ : { instructions: [...(talk.flow.instructions ?? []), ...(talk.step.instructions ?? [])], tools: talk.step.tools ?? talk.flow.tools };
624
+ const ctx = {
625
+ context: turn.context,
626
+ data: turn.session.data,
627
+ input: "idle" in talk ? undefined : talk.run.input,
628
+ ...("idle" in talk ? {} : { run: talk.run }),
629
+ silenced: turn.silenced,
630
+ now: turn.now,
631
+ };
632
+ const conditions = this.options.conditions ?? {};
633
+ const instructions = [...(this.options.instructions ?? []), ...own.instructions].filter((ins) => !ins.if || (0, predicate_js_1.evaluate)(ins.if, ctx, conditions));
634
+ const all = this.options.tools ?? [];
635
+ const allowed = own.tools;
636
+ return {
637
+ talk,
638
+ input: turn.what.kind === "message" ? { kind: turn.kind, text: turn.what.text } : { kind: turn.kind },
639
+ context: turn.context,
640
+ data: turn.session.data,
641
+ history: this.historyOf(turn),
642
+ now: turn.now,
643
+ instructions,
644
+ tools: allowed ? all.filter((tool) => allowed.includes(tool.id)) : all,
645
+ };
646
+ }
647
+ speaker(turn) {
648
+ if (turn.silenced !== undefined)
649
+ return null;
650
+ const { talk } = turn;
651
+ if (talk) {
652
+ // Another run's say (or spoke: true) already answered the lead: the floor's talk waits; the run stays asking.
653
+ if (turn.what.kind === "message" && [...turn.spokeBy].some((id) => id !== talk.run.id)) {
654
+ this.outcome(turn, talk.run, { kind: talkKind(talk.step), status: "skipped", key: this.stepKey(talk.run, talk.step), code: "another-reply" });
655
+ turn.talk = undefined;
656
+ return null;
657
+ }
658
+ return talk;
659
+ }
660
+ if (turn.what.kind === "message" && !this.asker(turn) && this.options.idle !== "silent" && turn.spokeBy.size === 0) {
661
+ return { idle: this.options.idle ?? { prompt: "" } };
662
+ }
663
+ return null;
664
+ }
665
+ async drain(turn) {
666
+ for (let run = turn.queue.shift(); run; run = turn.queue.shift()) {
667
+ if (turn.session.runs.includes(run))
668
+ await this.move(turn, run);
669
+ }
670
+ }
671
+ async move(turn, run) {
672
+ if (run.status === "waiting" || run.status === "suspended")
673
+ return;
674
+ // An asker only re-speaks when the lead writes; wakes and events leave it alone.
675
+ if (run.status === "asking" && turn.what.kind !== "message")
676
+ return;
677
+ const flow = this.flows.get(run.flowId);
678
+ if (!flow) {
679
+ this.endRun(turn, run, "skipped", "flow-gone");
680
+ return;
681
+ }
682
+ if (!this.premiseHolds(turn, run, flow))
683
+ return;
684
+ const resuming = run.status === "asking";
685
+ run.status = "running";
686
+ if (run.stepId === null) {
687
+ if (!flow.steps.length) {
688
+ this.finishFlow(turn, run, flow);
689
+ return;
690
+ }
691
+ this.enter(run, flow.steps[0].id);
692
+ }
693
+ for (let steps = 0; run.status === "running" && turn.session.runs.includes(run); steps++) {
694
+ if (steps >= MAX_STEPS_PER_TURN) {
695
+ this.endRun(turn, run, "failed", "step-loop");
696
+ return;
697
+ }
698
+ const step = this.stepOf(flow, run.stepId);
699
+ if (!step) {
700
+ this.endRun(turn, run, "skipped", "step-gone");
701
+ return;
702
+ }
703
+ await this.execute(turn, run, flow, step, resuming && steps === 0);
704
+ }
705
+ }
706
+ /** `while` (default: the trigger's `if`) with fresh context; silence runs add "no lead message since the run started". */
707
+ premiseHolds(turn, run, flow) {
708
+ // A wake-driven move only: on a message turn the lead just wrote, and the flow's `wait ... else` says what to do about it.
709
+ if (run.trigger.kind === "silence" && turn.what.kind === "wake" && this.leadWroteSince(turn, run.startedAt, flow)) {
710
+ this.endRun(turn, run, "skipped", "customer-replied");
711
+ return false;
712
+ }
713
+ let ok;
714
+ if (flow.while) {
715
+ ok = this.holds(flow.while, turn, run);
716
+ }
717
+ else {
718
+ // ponytail: several triggers of one kind (two event triggers, say) are not told apart; the premise holds when any of them would fire.
719
+ const same = (flow.on ?? []).filter((t) => triggerKind(t) === run.trigger.kind);
720
+ ok = same.length === 0 || same.some((t) => !t.if || this.holds(t.if, turn, run));
721
+ }
722
+ if (!ok)
723
+ this.endRun(turn, run, "skipped", "premise-changed");
724
+ return ok;
725
+ }
726
+ async execute(turn, run, flow, step, resuming) {
727
+ const data = turn.session.data;
728
+ const key = this.stepKey(run, step);
729
+ if (isTalk(step)) {
730
+ const kind = talkKind(step);
731
+ let pending = [];
732
+ if (step.collect?.length) {
733
+ pending = (0, schema_js_1.pendingFields)(step, data, run.asked);
734
+ if (!pending.length) {
735
+ this.reportMaxAsks(turn, run, step);
736
+ this.outcome(turn, run, resuming
737
+ ? { kind, status: "ok", key, next: nextLabel(step.then) }
738
+ : { kind, status: "skipped", key, code: "already-known", next: nextLabel(step.then) });
739
+ this.follow(turn, run, flow, step, step.then);
740
+ return;
741
+ }
742
+ }
743
+ if (turn.silenced !== undefined) {
744
+ if (resuming)
745
+ run.status = "asking"; // the gate is closed; it speaks when the gate opens
746
+ else
747
+ this.endRun(turn, run, "skipped", "silenced", kind, turn.silenced);
748
+ return;
749
+ }
750
+ for (const other of turn.session.runs) {
751
+ if (other !== run && other.status === "asking") {
752
+ other.status = "suspended";
753
+ other.suspendedAt = turn.nowIso;
754
+ }
755
+ }
756
+ run.status = "asking";
757
+ if (!turn.speakDone)
758
+ turn.talk = { run, flow, step, pending };
759
+ return;
760
+ }
761
+ if (isSay(step)) {
762
+ if (turn.silenced !== undefined) {
763
+ this.endRun(turn, run, "skipped", "silenced", "say", turn.silenced);
764
+ return;
765
+ }
766
+ if (step.once) {
767
+ const claim = `${flow.id}:${step.id}:${turn.session.id}`;
768
+ if (this.claimAt(turn, claim) !== undefined) {
769
+ this.outcome(turn, run, { kind: "say", status: "skipped", key, code: "already-sent", next: nextLabel(step.then) });
770
+ this.follow(turn, run, flow, step, step.then);
771
+ return;
772
+ }
773
+ turn.session.claims[claim] = { at: turn.nowIso };
774
+ }
775
+ turn.messages.push({
776
+ text: (0, template_js_1.render)(step.say, this.scope(turn, run)),
777
+ kind: "verbatim",
778
+ ...(step.media ? { media: step.media } : {}),
779
+ afterMs: turn.afterMs,
780
+ key,
781
+ runId: run.id,
782
+ stepId: step.id,
783
+ });
784
+ turn.afterMs = 0;
785
+ turn.spokeBy.add(run.id);
786
+ turn.spoke = true;
787
+ this.outcome(turn, run, { kind: "say", status: "ok", key, next: nextLabel(step.then) });
788
+ this.follow(turn, run, flow, step, step.then);
789
+ return;
790
+ }
791
+ if (isDo(step)) {
792
+ const action = this.options.actions?.[step.do];
793
+ let result;
794
+ if (!action) {
795
+ // `validateFlow` rejects this at agent build; a spec that reached the
796
+ // runner another way still names what is missing rather than failing blank.
797
+ result = { failed: `unknown action "${step.do}"` };
798
+ }
799
+ else {
800
+ try {
801
+ result = await action.run((0, template_js_1.renderDeep)(step.with ?? {}, this.scope(turn, run)), {
802
+ context: turn.context, data: turn.session.data, input: run.input, run, key, dedupeKey: run.dedupeKey,
803
+ silenced: turn.silenced, now: turn.now, set: (patch) => void Object.assign(turn.session.data, patch),
804
+ });
805
+ }
806
+ catch (error) {
807
+ result = { failed: error instanceof Error ? error.message : String(error) };
808
+ }
809
+ }
810
+ if ("ok" in result) {
811
+ if (result.spoke) {
812
+ turn.spokeBy.add(run.id);
813
+ turn.spoke = true;
814
+ }
815
+ this.outcome(turn, run, { kind: "do", status: "ok", key, ...(result.detail ? { detail: result.detail } : {}), next: nextLabel(step.then) });
816
+ this.follow(turn, run, flow, step, step.then);
817
+ }
818
+ else if ("skipped" in result) {
819
+ this.outcome(turn, run, { kind: "do", status: "skipped", key, code: "action-skipped", detail: result.skipped, next: nextLabel(step.then) });
820
+ this.follow(turn, run, flow, step, step.then);
821
+ }
822
+ else if ("failed" in result) {
823
+ const target = step.onFail ?? step.then;
824
+ this.outcome(turn, run, { kind: "do", status: "failed", key, code: "action-failed", detail: result.failed, next: nextLabel(target) });
825
+ this.follow(turn, run, flow, step, target);
826
+ }
827
+ else {
828
+ const at = new Date(turn.now.getTime() + (0, duration_js_1.parseDuration)(result.defer));
829
+ this.park(turn, run, { kind: "timer", key: `${run.id}:${step.id}:${at.getTime()}` }, at);
830
+ this.outcome(turn, run, { kind: "do", status: "deferred", key, code: "action-deferred", detail: result.detail, until: at.toISOString() });
831
+ }
832
+ return;
833
+ }
834
+ if (isWait(step)) {
835
+ const ms = (0, duration_js_1.parseDuration)(step.wait);
836
+ if (ms <= SHORT_WAIT_MS) {
837
+ // ponytail: a short wait rides on the next message only when the very next step is a say or talk step; an `if` in between is not looked through.
838
+ const next = this.peek(flow, step);
839
+ if (next && (isSay(next) || isTalk(next))) {
840
+ turn.afterMs += ms;
841
+ this.outcome(turn, run, { kind: "wait", status: "ok", key, code: "inline-delay", detail: `${ms}ms`, next: nextLabel(step.then) });
842
+ this.follow(turn, run, flow, step, step.then);
843
+ return;
844
+ }
845
+ }
846
+ const at = this.snap(turn, new Date(turn.now.getTime() + ms), step.businessHours);
847
+ this.park(turn, run, { kind: "timer", key: `${run.id}:${step.id}:${at.getTime()}` }, at);
848
+ this.outcome(turn, run, { kind: "wait", status: "waiting", key, until: at.toISOString() });
849
+ return;
850
+ }
851
+ if (isWaitEvent(step)) {
852
+ const at = new Date(turn.now.getTime() + (0, duration_js_1.parseDuration)(step.wait.upTo ?? DEFAULT_EVENT_WAIT));
853
+ this.park(turn, run, { kind: "event", event: step.wait.event, key: `${run.id}:${step.id}:${at.getTime()}` }, at);
854
+ this.outcome(turn, run, { kind: "wait", status: "waiting", key, code: "awaiting-event", detail: step.wait.event, until: at.toISOString() });
855
+ return;
856
+ }
857
+ if (isIf(step)) {
858
+ const target = this.holds(step.if, turn, run) ? step.then : (step.else ?? "end");
859
+ this.outcome(turn, run, { kind: "if", status: "ok", key, next: nextLabel(target) });
860
+ this.follow(turn, run, flow, step, target);
861
+ }
862
+ }
863
+ /** The step `then` leads to, when it is a step of this flow. */
864
+ peek(flow, step) {
865
+ const { then } = step;
866
+ if (then === undefined)
867
+ return flow.steps[flow.steps.indexOf(step) + 1];
868
+ if (typeof then === "string")
869
+ return then === "end" ? undefined : this.stepOf(flow, then);
870
+ return "step" in then ? this.stepOf(flow, then.step) : undefined;
871
+ }
872
+ reportMaxAsks(turn, run, step) {
873
+ const data = turn.session.data;
874
+ const maxAsks = step.maxAsks ?? schema_js_1.DEFAULT_MAX_ASKS;
875
+ for (const field of step.collect ?? []) {
876
+ const asked = run.asked[field] ?? 0;
877
+ if (!(0, schema_js_1.isKnown)(data[field]) && asked >= maxAsks) {
878
+ this.outcome(turn, run, { kind: "collect", status: "skipped", key: this.stepKey(run, step), code: "max-asks", detail: field });
879
+ }
880
+ }
881
+ }
882
+ // ── Movement primitives ───────────────────────────────────────────────
883
+ follow(turn, run, flow, step, target) {
884
+ if (target === undefined) {
885
+ const next = flow.steps[flow.steps.indexOf(step) + 1];
886
+ if (next)
887
+ this.enter(run, next.id);
888
+ else
889
+ this.finishFlow(turn, run, flow);
890
+ return;
891
+ }
892
+ if (typeof target === "string") {
893
+ if (target === "end")
894
+ this.finishFlow(turn, run, flow);
895
+ else
896
+ this.jump(turn, run, flow, target);
897
+ return;
898
+ }
899
+ if ("step" in target) {
900
+ const data = turn.session.data;
901
+ for (const field of target.clear ?? [])
902
+ delete data[field];
903
+ this.jump(turn, run, flow, target.step);
904
+ return;
905
+ }
906
+ const childId = (0, template_js_1.render)(target.flow, this.scope(turn, run));
907
+ const key = this.stepKey(run, step);
908
+ this.endRun(turn, run, "flow");
909
+ this.chain(turn, childId, key, target.input ?? run.input, run.hop + 1);
910
+ }
911
+ /** Start a child flow that holds the floor and moves in this same phase. */
912
+ chain(turn, flowId, key, input, hop, keepData = false) {
913
+ const child = this.flows.get(flowId);
914
+ if (!child) {
915
+ turn.skipped.push({ flowId, anchor: turn.session.id, triggerKey: key, code: "flow-gone", message: outcomes_js_1.OUTCOME_MESSAGES["flow-gone"] });
916
+ return;
917
+ }
918
+ const run = this.startRun(turn, child, "flow", key, { payload: input, hop, keepData });
919
+ if (!run)
920
+ return;
921
+ turn.floorRunId = run.id;
922
+ if (turn.ingesting)
923
+ turn.floorFromIngest = true;
924
+ turn.queue.push(run);
925
+ }
926
+ jump(turn, run, flow, stepId) {
927
+ if (this.stepOf(flow, stepId))
928
+ this.enter(run, stepId);
929
+ else
930
+ this.endRun(turn, run, "skipped", "step-gone");
931
+ }
932
+ /** Entering a step is what mints a new visit, and with it new action and message keys (I4). */
933
+ enter(run, stepId) {
934
+ run.stepId = stepId;
935
+ run.visits[stepId] = (run.visits[stepId] ?? 0) + 1;
936
+ run.status = "running";
937
+ delete run.waiting;
938
+ }
939
+ finishFlow(turn, run, flow) {
940
+ const onEnd = flow.onEnd ?? "end";
941
+ const last = flow.steps[flow.steps.length - 1];
942
+ if (onEnd === "stay" && last) {
943
+ // "repete o último passo": the run stays live at its last step, re-entered so the repetition mints a new key, and runs it on the next message.
944
+ this.enter(run, last.id);
945
+ run.status = "asking";
946
+ return;
947
+ }
948
+ if (onEnd === "reset" && last) {
949
+ // The run record closes (`reason: 'reset'`) and a fresh run of the same flow starts at step one, data kept.
950
+ // It is a chain into itself, so it costs a hop: a code-only flow that resets forever stops at the hop cap instead of spinning.
951
+ const key = this.stepKey(run, last);
952
+ this.endRun(turn, run, "reset");
953
+ this.chain(turn, flow.id, key, run.input, run.hop + 1, true);
954
+ return;
955
+ }
956
+ this.endRun(turn, run, "end");
957
+ }
958
+ endRun(turn, run, reason, code, kind, detail) {
959
+ const index = turn.session.runs.indexOf(run);
960
+ if (index >= 0)
961
+ turn.session.runs.splice(index, 1);
962
+ if (code) {
963
+ const flow = this.flows.get(run.flowId);
964
+ this.outcome(turn, run, { kind: kind ?? kindOf(flow && this.stepOf(flow, run.stepId)), status: reason === "failed" ? "failed" : "skipped", code, ...(detail ? { detail } : {}) });
965
+ }
966
+ turn.ended.push({ ...run, reason });
967
+ if (turn.talk?.run === run)
968
+ turn.talk = undefined;
969
+ }
970
+ park(turn, run, waiting, at) {
971
+ run.status = "waiting";
972
+ run.waiting = { ...waiting, until: at.toISOString(), setAt: turn.nowIso };
973
+ turn.schedule.push({ key: waiting.key, at });
974
+ }
975
+ /** When nobody asks, the most recently suspended run returns to asking. */
976
+ resumeSuspended(turn) {
977
+ if (this.asker(turn))
978
+ return;
979
+ const suspendedAt = (r) => r.suspendedAt ?? r.startedAt;
980
+ const next = turn.session.runs
981
+ .filter((r) => r.status === "suspended")
982
+ .reduce((top, cur) => (top && suspendedAt(top) > suspendedAt(cur) ? top : cur), undefined);
983
+ if (next) {
984
+ next.status = "asking";
985
+ delete next.suspendedAt;
986
+ }
987
+ }
988
+ // ── Settle: the one applier after Speak (design §4.7) ─────────────────
989
+ async settle(turn, outcome) {
990
+ if (turn.ignored)
991
+ return;
992
+ turn.speakDone = true;
993
+ const { talk } = turn;
994
+ turn.talk = undefined;
995
+ if (outcome && "deferred" in outcome) {
996
+ turn.llmCalls += outcome.llmCalls;
997
+ turn.usage = (0, usage_js_1.addUsage)(turn.usage, outcome.usage);
998
+ if (talk)
999
+ this.deferTalk(turn, talk, outcome.deferred);
1000
+ else
1001
+ this.outcome(turn, undefined, { kind: "idle", status: "deferred", code: outcome.deferred.code, llmCalls: outcome.llmCalls });
1002
+ }
1003
+ else if (outcome) {
1004
+ const { spoken } = outcome;
1005
+ turn.llmCalls += spoken.llmCalls;
1006
+ turn.usage = (0, usage_js_1.addUsage)(turn.usage, spoken.usage);
1007
+ if (talk) {
1008
+ this.applySpoken(turn, talk, spoken);
1009
+ await this.drain(turn);
1010
+ }
1011
+ else {
1012
+ if (spoken.message) {
1013
+ turn.messages.push({ text: spoken.message, kind: "ai", afterMs: turn.afterMs, key: `idle:${turn.triggerKey}` });
1014
+ turn.afterMs = 0;
1015
+ turn.spoke = true;
1016
+ }
1017
+ Object.assign(turn.session.data, spoken.data);
1018
+ this.outcome(turn, undefined, { kind: "idle", status: "ok", key: `idle:${turn.triggerKey}`, llmCalls: spoken.llmCalls });
1019
+ }
1020
+ }
1021
+ if (turn.spoke)
1022
+ turn.session.lastAssistantAt = turn.nowIso;
1023
+ this.resumeSuspended(turn);
1024
+ this.armSilence(turn);
1025
+ }
1026
+ applySpoken(turn, talk, spoken) {
1027
+ const { run, flow, step } = talk;
1028
+ const key = this.stepKey(run, step);
1029
+ if (spoken.message) {
1030
+ turn.messages.push({ text: spoken.message, kind: "ai", afterMs: turn.afterMs, key, runId: run.id, stepId: step.id });
1031
+ turn.afterMs = 0;
1032
+ turn.spokeBy.add(run.id);
1033
+ turn.spoke = true;
1034
+ }
1035
+ for (const [field, raw] of Object.entries(spoken.fields))
1036
+ this.writeField(turn, field, raw);
1037
+ Object.assign(turn.session.data, spoken.data);
1038
+ this.outcome(turn, run, { kind: talkKind(step), status: "ok", key, llmCalls: spoken.llmCalls, stepId: step.id });
1039
+ if (!turn.session.runs.includes(run))
1040
+ return;
1041
+ if (step.collect?.length) {
1042
+ const pending = (0, schema_js_1.pendingFields)(step, turn.session.data, run.asked);
1043
+ if (pending.length) {
1044
+ for (const field of pending)
1045
+ run.asked[field] = (run.asked[field] ?? 0) + 1;
1046
+ run.status = "asking";
1047
+ return;
1048
+ }
1049
+ this.reportMaxAsks(turn, run, step);
1050
+ }
1051
+ run.status = "running";
1052
+ this.follow(turn, run, flow, step, step.then);
1053
+ if (turn.session.runs.includes(run) && run.status === "running")
1054
+ turn.queue.push(run);
1055
+ }
1056
+ /** The provider failed: park the talk step under a retry wake, or stop trying. */
1057
+ deferTalk(turn, talk, deferred) {
1058
+ const { run, step } = talk;
1059
+ const key = this.stepKey(run, step);
1060
+ let attempt = 0;
1061
+ for (let i = run.outcomes.length - 1; i >= 0 && run.outcomes[i].status === "deferred" && run.outcomes[i].stepId === step.id; i--)
1062
+ attempt++;
1063
+ const at = this.retryAt(turn, deferred, attempt);
1064
+ if (!at) {
1065
+ // A wrong key, a prompt past the context window or a spent balance is not
1066
+ // going to be different in fifteen minutes. End the run and let the host
1067
+ // read the code, rather than burning two model calls against the same
1068
+ // wall until someone notices.
1069
+ this.outcome(turn, run, { kind: talkKind(step), status: "failed", key, code: deferred.code });
1070
+ this.endRun(turn, run, "failed");
1071
+ return;
1072
+ }
1073
+ const visit = run.visits[step.id] ?? 0;
1074
+ this.park(turn, run, { kind: "timer", key: `${run.id}:${step.id}:${visit}:retry:${at.getTime()}` }, at);
1075
+ this.outcome(turn, run, { kind: talkKind(step), status: "deferred", key, code: deferred.code, until: at.toISOString() });
1076
+ }
1077
+ /** When to try again, or `null` when trying again cannot help. */
1078
+ retryAt(turn, deferred, attempt) {
1079
+ if (!deferred.retryable || attempt >= RETRY_BACKOFF.length)
1080
+ return null;
1081
+ const ladder = turn.now.getTime() + (0, duration_js_1.parseDuration)(RETRY_BACKOFF[attempt]);
1082
+ // The provider said when its window reopens. One wake then beats climbing a
1083
+ // ladder measured in minutes inside a limit measured in hours.
1084
+ const reset = deferred.resetAtMs;
1085
+ return new Date(reset !== undefined && reset > ladder ? reset : ladder);
1086
+ }
1087
+ /** The assistant spoke last: every silence flow passing `if` and `repeat` gets a wake. */
1088
+ armSilence(turn) {
1089
+ const { session } = turn;
1090
+ const { lastAssistantAt, lastUserAt } = session;
1091
+ if (!lastAssistantAt || lastAssistantAt === turn.original?.lastAssistantAt)
1092
+ return;
1093
+ if (lastUserAt && Date.parse(lastUserAt) > Date.parse(lastAssistantAt))
1094
+ return;
1095
+ const ms = Date.parse(lastAssistantAt);
1096
+ const previous = turn.original?.lastAssistantAt;
1097
+ for (const flow of this.flows.values()) {
1098
+ const trigger = (flow.on ?? []).find((t) => "silence" in t);
1099
+ if (!trigger)
1100
+ continue;
1101
+ const key = String(ms);
1102
+ if (trigger.if && !this.holds(trigger.if, turn, this.draftRun(turn, flow, "silence", key)))
1103
+ continue;
1104
+ if (!this.repeatAllows(turn, flow, trigger, key))
1105
+ continue;
1106
+ const at = this.snap(turn, new Date(ms + (0, duration_js_1.parseDuration)(trigger.silence)), trigger.businessHours);
1107
+ turn.schedule.push({
1108
+ key: `silence:${flow.id}:${session.id}:${ms}`,
1109
+ at,
1110
+ ...(previous ? { replaces: `silence:${flow.id}:${session.id}:${Date.parse(previous)}` } : {}),
1111
+ });
1112
+ }
1113
+ }
1114
+ // ── Return (design §4.8) ──────────────────────────────────────────────
1115
+ finish(turn) {
1116
+ const { session, messages, schedule, outcomes, started, ended, skipped, llmCalls, usage } = turn;
1117
+ const changed = !turn.ignored &&
1118
+ (!turn.original || !(0, predicate_js_1.deepEqual)(session, turn.original) || messages.length > 0 || schedule.length > 0 || outcomes.length > 0 || skipped.length > 0);
1119
+ return { session, changed, messages, schedule, outcomes, started, ended, skipped, llmCalls, ...(usage ? { usage } : {}) };
1120
+ }
1121
+ }
1122
+ exports.Runner = Runner;
1123
+ /** The `next` column of an outcome line: a step id, `end`, or the flow a `then` chains into. */
1124
+ function nextLabel(target) {
1125
+ if (target === undefined)
1126
+ return undefined;
1127
+ if (typeof target === "string")
1128
+ return target;
1129
+ return "step" in target ? target.step : `flow:${target.flow}`;
1130
+ }
1131
+ //# sourceMappingURL=Runner.js.map