@falai/agent 3.4.5 → 4.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (847) 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 +1 -1
  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/types/agent.d.ts +153 -383
  100. package/dist/cjs/types/agent.d.ts.map +1 -1
  101. package/dist/cjs/types/agent.js +1 -1
  102. package/dist/cjs/types/ai.d.ts +32 -1
  103. package/dist/cjs/types/ai.d.ts.map +1 -1
  104. package/dist/cjs/types/compaction.d.ts +3 -1
  105. package/dist/cjs/types/compaction.d.ts.map +1 -1
  106. package/dist/cjs/types/errors.d.ts +9 -12
  107. package/dist/cjs/types/errors.d.ts.map +1 -1
  108. package/dist/cjs/types/errors.js +14 -17
  109. package/dist/cjs/types/errors.js.map +1 -1
  110. package/dist/cjs/types/flow.d.ts +265 -513
  111. package/dist/cjs/types/flow.d.ts.map +1 -1
  112. package/dist/cjs/types/flow.js +7 -1
  113. package/dist/cjs/types/flow.js.map +1 -1
  114. package/dist/cjs/types/history.d.ts +7 -18
  115. package/dist/cjs/types/history.d.ts.map +1 -1
  116. package/dist/cjs/types/history.js.map +1 -1
  117. package/dist/cjs/types/index.d.ts +9 -15
  118. package/dist/cjs/types/index.d.ts.map +1 -1
  119. package/dist/cjs/types/index.js +4 -14
  120. package/dist/cjs/types/index.js.map +1 -1
  121. package/dist/cjs/types/session.d.ts +94 -64
  122. package/dist/cjs/types/session.d.ts.map +1 -1
  123. package/dist/cjs/types/session.js +5 -1
  124. package/dist/cjs/types/session.js.map +1 -1
  125. package/dist/cjs/types/tool.d.ts +37 -207
  126. package/dist/cjs/types/tool.d.ts.map +1 -1
  127. package/dist/cjs/types/tool.js +5 -14
  128. package/dist/cjs/types/tool.js.map +1 -1
  129. package/dist/cjs/utils/clock.d.ts +28 -0
  130. package/dist/cjs/utils/clock.d.ts.map +1 -0
  131. package/dist/cjs/utils/clock.js +64 -0
  132. package/dist/cjs/utils/clock.js.map +1 -0
  133. package/dist/cjs/utils/duration.d.ts +11 -0
  134. package/dist/cjs/utils/duration.d.ts.map +1 -0
  135. package/dist/cjs/utils/duration.js +31 -0
  136. package/dist/cjs/utils/duration.js.map +1 -0
  137. package/dist/cjs/utils/history.d.ts +4 -1
  138. package/dist/cjs/utils/history.d.ts.map +1 -1
  139. package/dist/cjs/utils/history.js +2 -2
  140. package/dist/cjs/utils/history.js.map +1 -1
  141. package/dist/cjs/utils/index.d.ts +4 -10
  142. package/dist/cjs/utils/index.d.ts.map +1 -1
  143. package/dist/cjs/utils/index.js +14 -61
  144. package/dist/cjs/utils/index.js.map +1 -1
  145. package/dist/cjs/utils/json.d.ts +2 -0
  146. package/dist/cjs/utils/json.d.ts.map +1 -1
  147. package/dist/cjs/utils/json.js +5 -0
  148. package/dist/cjs/utils/json.js.map +1 -1
  149. package/dist/cjs/utils/outcomes.d.ts +48 -0
  150. package/dist/cjs/utils/outcomes.d.ts.map +1 -0
  151. package/dist/cjs/utils/outcomes.js +51 -0
  152. package/dist/cjs/utils/outcomes.js.map +1 -0
  153. package/dist/cjs/utils/schema.d.ts +50 -0
  154. package/dist/cjs/utils/schema.d.ts.map +1 -0
  155. package/dist/cjs/utils/schema.js +138 -0
  156. package/dist/cjs/utils/schema.js.map +1 -0
  157. package/dist/cjs/utils/streamingMessage.d.ts +3 -2
  158. package/dist/cjs/utils/streamingMessage.d.ts.map +1 -1
  159. package/dist/cjs/utils/streamingMessage.js +38 -4
  160. package/dist/cjs/utils/streamingMessage.js.map +1 -1
  161. package/dist/cjs/utils/template.d.ts +13 -149
  162. package/dist/cjs/utils/template.d.ts.map +1 -1
  163. package/dist/cjs/utils/template.js +31 -363
  164. package/dist/cjs/utils/template.js.map +1 -1
  165. package/dist/cjs/utils/usage.d.ts +19 -0
  166. package/dist/cjs/utils/usage.d.ts.map +1 -0
  167. package/dist/cjs/utils/usage.js +35 -0
  168. package/dist/cjs/utils/usage.js.map +1 -0
  169. package/dist/core/Agent.d.ts +22 -378
  170. package/dist/core/Agent.d.ts.map +1 -1
  171. package/dist/core/Agent.js +107 -1181
  172. package/dist/core/Agent.js.map +1 -1
  173. package/dist/core/CompactionEngine.d.ts.map +1 -1
  174. package/dist/core/CompactionEngine.js +5 -3
  175. package/dist/core/CompactionEngine.js.map +1 -1
  176. package/dist/core/FlowSpec.d.ts +136 -0
  177. package/dist/core/FlowSpec.d.ts.map +1 -0
  178. package/dist/core/FlowSpec.js +516 -0
  179. package/dist/core/FlowSpec.js.map +1 -0
  180. package/dist/core/Migrate.d.ts +38 -0
  181. package/dist/core/Migrate.d.ts.map +1 -0
  182. package/dist/core/Migrate.js +264 -0
  183. package/dist/core/Migrate.js.map +1 -0
  184. package/dist/core/Prompt.d.ts +54 -0
  185. package/dist/core/Prompt.d.ts.map +1 -0
  186. package/dist/core/Prompt.js +133 -0
  187. package/dist/core/Prompt.js.map +1 -0
  188. package/dist/core/Runner.d.ts +160 -0
  189. package/dist/core/Runner.d.ts.map +1 -0
  190. package/dist/core/Runner.js +1127 -0
  191. package/dist/core/Runner.js.map +1 -0
  192. package/dist/core/Speak.d.ts +37 -0
  193. package/dist/core/Speak.d.ts.map +1 -0
  194. package/dist/core/Speak.js +360 -0
  195. package/dist/core/Speak.js.map +1 -0
  196. package/dist/core/Understand.d.ts +28 -0
  197. package/dist/core/Understand.d.ts.map +1 -0
  198. package/dist/core/Understand.js +349 -0
  199. package/dist/core/Understand.js.map +1 -0
  200. package/dist/core/contracts.d.ts +122 -0
  201. package/dist/core/contracts.d.ts.map +1 -0
  202. package/dist/core/contracts.js +10 -0
  203. package/dist/core/contracts.js.map +1 -0
  204. package/dist/core/falai.d.ts +57 -0
  205. package/dist/core/falai.d.ts.map +1 -0
  206. package/dist/core/falai.js +40 -0
  207. package/dist/core/falai.js.map +1 -0
  208. package/dist/core/predicate.d.ts +9 -0
  209. package/dist/core/predicate.d.ts.map +1 -0
  210. package/dist/core/predicate.js +54 -0
  211. package/dist/core/predicate.js.map +1 -0
  212. package/dist/index.d.ts +26 -31
  213. package/dist/index.d.ts.map +1 -1
  214. package/dist/index.js +19 -24
  215. package/dist/index.js.map +1 -1
  216. package/dist/persistence/MemoryStore.d.ts +15 -0
  217. package/dist/persistence/MemoryStore.d.ts.map +1 -0
  218. package/dist/persistence/MemoryStore.js +35 -0
  219. package/dist/persistence/MemoryStore.js.map +1 -0
  220. package/dist/persistence/MongoStore.d.ts +42 -0
  221. package/dist/persistence/MongoStore.d.ts.map +1 -0
  222. package/dist/persistence/MongoStore.js +56 -0
  223. package/dist/persistence/MongoStore.js.map +1 -0
  224. package/dist/persistence/OpenSearchStore.d.ts +86 -0
  225. package/dist/persistence/OpenSearchStore.d.ts.map +1 -0
  226. package/dist/persistence/OpenSearchStore.js +116 -0
  227. package/dist/persistence/OpenSearchStore.js.map +1 -0
  228. package/dist/persistence/PostgresStore.d.ts +41 -0
  229. package/dist/persistence/PostgresStore.d.ts.map +1 -0
  230. package/dist/persistence/PostgresStore.js +54 -0
  231. package/dist/persistence/PostgresStore.js.map +1 -0
  232. package/dist/persistence/PrismaStore.d.ts +65 -0
  233. package/dist/persistence/PrismaStore.d.ts.map +1 -0
  234. package/dist/persistence/PrismaStore.js +91 -0
  235. package/dist/persistence/PrismaStore.js.map +1 -0
  236. package/dist/persistence/RedisStore.d.ts +34 -0
  237. package/dist/persistence/RedisStore.d.ts.map +1 -0
  238. package/dist/persistence/RedisStore.js +57 -0
  239. package/dist/persistence/RedisStore.js.map +1 -0
  240. package/dist/persistence/SQLiteStore.d.ts +45 -0
  241. package/dist/persistence/SQLiteStore.d.ts.map +1 -0
  242. package/dist/persistence/SQLiteStore.js +70 -0
  243. package/dist/persistence/SQLiteStore.js.map +1 -0
  244. package/dist/persistence/sessionRow.d.ts +14 -0
  245. package/dist/persistence/sessionRow.d.ts.map +1 -0
  246. package/dist/persistence/sessionRow.js +45 -0
  247. package/dist/persistence/sessionRow.js.map +1 -0
  248. package/dist/providers/DeepSeekProvider.d.ts.map +1 -1
  249. package/dist/providers/DeepSeekProvider.js +8 -3
  250. package/dist/providers/DeepSeekProvider.js.map +1 -1
  251. package/dist/providers/GeminiProvider.d.ts +4 -3
  252. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  253. package/dist/providers/GeminiProvider.js +4 -3
  254. package/dist/providers/GeminiProvider.js.map +1 -1
  255. package/dist/providers/OpenAICompatibleProvider.d.ts +4 -0
  256. package/dist/providers/OpenAICompatibleProvider.d.ts.map +1 -1
  257. package/dist/providers/OpenAICompatibleProvider.js +2 -0
  258. package/dist/providers/OpenAICompatibleProvider.js.map +1 -1
  259. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  260. package/dist/providers/OpenRouterProvider.js +2 -4
  261. package/dist/providers/OpenRouterProvider.js.map +1 -1
  262. package/dist/providers/ProviderAdapter.d.ts +1 -1
  263. package/dist/providers/ProviderAdapter.d.ts.map +1 -1
  264. package/dist/providers/ProviderAdapter.js +34 -11
  265. package/dist/providers/ProviderAdapter.js.map +1 -1
  266. package/dist/types/agent.d.ts +153 -383
  267. package/dist/types/agent.d.ts.map +1 -1
  268. package/dist/types/agent.js +1 -1
  269. package/dist/types/ai.d.ts +32 -1
  270. package/dist/types/ai.d.ts.map +1 -1
  271. package/dist/types/compaction.d.ts +3 -1
  272. package/dist/types/compaction.d.ts.map +1 -1
  273. package/dist/types/errors.d.ts +9 -12
  274. package/dist/types/errors.d.ts.map +1 -1
  275. package/dist/types/errors.js +12 -15
  276. package/dist/types/errors.js.map +1 -1
  277. package/dist/types/flow.d.ts +265 -513
  278. package/dist/types/flow.d.ts.map +1 -1
  279. package/dist/types/flow.js +7 -1
  280. package/dist/types/flow.js.map +1 -1
  281. package/dist/types/history.d.ts +7 -18
  282. package/dist/types/history.d.ts.map +1 -1
  283. package/dist/types/history.js.map +1 -1
  284. package/dist/types/index.d.ts +9 -15
  285. package/dist/types/index.d.ts.map +1 -1
  286. package/dist/types/index.js +2 -7
  287. package/dist/types/index.js.map +1 -1
  288. package/dist/types/session.d.ts +94 -64
  289. package/dist/types/session.d.ts.map +1 -1
  290. package/dist/types/session.js +5 -1
  291. package/dist/types/session.js.map +1 -1
  292. package/dist/types/tool.d.ts +37 -207
  293. package/dist/types/tool.d.ts.map +1 -1
  294. package/dist/types/tool.js +6 -13
  295. package/dist/types/tool.js.map +1 -1
  296. package/dist/utils/clock.d.ts +28 -0
  297. package/dist/utils/clock.d.ts.map +1 -0
  298. package/dist/utils/clock.js +59 -0
  299. package/dist/utils/clock.js.map +1 -0
  300. package/dist/utils/duration.d.ts +11 -0
  301. package/dist/utils/duration.d.ts.map +1 -0
  302. package/dist/utils/duration.js +26 -0
  303. package/dist/utils/duration.js.map +1 -0
  304. package/dist/utils/history.d.ts +4 -1
  305. package/dist/utils/history.d.ts.map +1 -1
  306. package/dist/utils/history.js +2 -2
  307. package/dist/utils/history.js.map +1 -1
  308. package/dist/utils/index.d.ts +4 -10
  309. package/dist/utils/index.d.ts.map +1 -1
  310. package/dist/utils/index.js +4 -21
  311. package/dist/utils/index.js.map +1 -1
  312. package/dist/utils/json.d.ts +2 -0
  313. package/dist/utils/json.d.ts.map +1 -1
  314. package/dist/utils/json.js +4 -0
  315. package/dist/utils/json.js.map +1 -1
  316. package/dist/utils/outcomes.d.ts +48 -0
  317. package/dist/utils/outcomes.d.ts.map +1 -0
  318. package/dist/utils/outcomes.js +48 -0
  319. package/dist/utils/outcomes.js.map +1 -0
  320. package/dist/utils/schema.d.ts +50 -0
  321. package/dist/utils/schema.d.ts.map +1 -0
  322. package/dist/utils/schema.js +129 -0
  323. package/dist/utils/schema.js.map +1 -0
  324. package/dist/utils/streamingMessage.d.ts +3 -2
  325. package/dist/utils/streamingMessage.d.ts.map +1 -1
  326. package/dist/utils/streamingMessage.js +38 -4
  327. package/dist/utils/streamingMessage.js.map +1 -1
  328. package/dist/utils/template.d.ts +13 -149
  329. package/dist/utils/template.d.ts.map +1 -1
  330. package/dist/utils/template.js +28 -355
  331. package/dist/utils/template.js.map +1 -1
  332. package/dist/utils/usage.d.ts +19 -0
  333. package/dist/utils/usage.d.ts.map +1 -0
  334. package/dist/utils/usage.js +31 -0
  335. package/dist/utils/usage.js.map +1 -0
  336. package/docs/README.md +37 -19
  337. package/docs/concepts/architecture.md +117 -239
  338. package/docs/concepts/collection.md +170 -0
  339. package/docs/concepts/pipeline.md +132 -378
  340. package/docs/concepts/runs-and-waits.md +192 -0
  341. package/docs/guides/actions-and-events.md +276 -0
  342. package/docs/guides/branching.md +119 -208
  343. package/docs/guides/compaction.md +63 -158
  344. package/docs/guides/conditions.md +164 -128
  345. package/docs/guides/error-handling.md +168 -164
  346. package/docs/guides/flow-control.md +210 -349
  347. package/docs/guides/flows-from-json.md +224 -0
  348. package/docs/guides/instructions.md +125 -161
  349. package/docs/guides/persistence.md +182 -206
  350. package/docs/guides/streaming.md +50 -114
  351. package/docs/guides/testing.md +284 -0
  352. package/docs/guides/triggers.md +401 -0
  353. package/docs/migration/README.md +8 -15
  354. package/docs/migration/v1-to-v2.md +1 -1
  355. package/docs/migration/v2-3-to-v2-4.md +2 -2
  356. package/docs/migration/v2-6-to-v2-7.md +4 -4
  357. package/docs/migration/v3-to-v4.md +452 -0
  358. package/docs/reference/actions-events-conditions.md +396 -0
  359. package/docs/reference/agent.md +244 -0
  360. package/docs/reference/branches.md +75 -203
  361. package/docs/reference/errors.md +188 -144
  362. package/docs/reference/fields.md +125 -0
  363. package/docs/reference/flow-spec.md +248 -0
  364. package/docs/reference/flow.md +104 -192
  365. package/docs/reference/instruction.md +83 -137
  366. package/docs/reference/outcomes.md +273 -0
  367. package/docs/reference/providers.md +525 -302
  368. package/docs/reference/session.md +210 -0
  369. package/docs/reference/step.md +194 -312
  370. package/docs/reference/stores.md +496 -0
  371. package/docs/reference/tool.md +162 -231
  372. package/docs/reference/trigger.md +180 -0
  373. package/docs/rfc/v4-one-flow.md +477 -0
  374. package/docs/start/01-install.md +59 -44
  375. package/docs/start/02-first-agent.md +97 -147
  376. package/docs/start/03-collect-data.md +78 -183
  377. package/docs/start/04-add-tools.md +159 -227
  378. package/docs/start/05-go-to-production.md +167 -164
  379. package/examples/01-quickstart.ts +26 -16
  380. package/examples/02-fields.ts +75 -0
  381. package/examples/03-tools.ts +79 -119
  382. package/examples/04-instructions.ts +60 -87
  383. package/examples/05-branches.ts +78 -0
  384. package/examples/06-triggers-and-waits.ts +148 -0
  385. package/examples/07-streaming.ts +34 -60
  386. package/examples/08-store-and-migration.ts +97 -0
  387. package/examples/09-flows-from-json.ts +107 -0
  388. package/package.json +9 -6
  389. package/src/core/Agent.ts +116 -1512
  390. package/src/core/CompactionEngine.ts +7 -4
  391. package/src/core/FlowSpec.ts +712 -0
  392. package/src/core/Migrate.ts +256 -0
  393. package/src/core/Prompt.ts +156 -0
  394. package/src/core/Runner.ts +1181 -0
  395. package/src/core/Speak.ts +451 -0
  396. package/src/core/Understand.ts +422 -0
  397. package/src/core/contracts.ts +111 -0
  398. package/src/core/falai.ts +86 -0
  399. package/src/core/predicate.ts +56 -0
  400. package/src/index.ts +119 -147
  401. package/src/persistence/MemoryStore.ts +37 -0
  402. package/src/persistence/MongoStore.ts +89 -0
  403. package/src/persistence/OpenSearchStore.ts +153 -0
  404. package/src/persistence/PostgresStore.ts +89 -0
  405. package/src/persistence/PrismaStore.ts +127 -0
  406. package/src/persistence/RedisStore.ts +90 -0
  407. package/src/persistence/SQLiteStore.ts +103 -0
  408. package/src/persistence/sessionRow.ts +45 -0
  409. package/src/providers/DeepSeekProvider.ts +8 -3
  410. package/src/providers/GeminiProvider.ts +4 -3
  411. package/src/providers/OpenAICompatibleProvider.ts +6 -0
  412. package/src/providers/OpenRouterProvider.ts +2 -4
  413. package/src/providers/ProviderAdapter.ts +36 -8
  414. package/src/types/agent.ts +124 -397
  415. package/src/types/ai.ts +33 -1
  416. package/src/types/compaction.ts +3 -1
  417. package/src/types/errors.ts +13 -16
  418. package/src/types/flow.ts +249 -550
  419. package/src/types/history.ts +7 -20
  420. package/src/types/index.ts +87 -139
  421. package/src/types/session.ts +135 -70
  422. package/src/types/tool.ts +42 -267
  423. package/src/utils/clock.ts +70 -0
  424. package/src/utils/duration.ts +33 -0
  425. package/src/utils/history.ts +3 -2
  426. package/src/utils/index.ts +8 -66
  427. package/src/utils/json.ts +5 -0
  428. package/src/utils/outcomes.ts +56 -0
  429. package/src/utils/schema.ts +145 -0
  430. package/src/utils/streamingMessage.ts +34 -4
  431. package/src/utils/template.ts +32 -423
  432. package/src/utils/usage.ts +37 -0
  433. package/dist/adapters/MemoryAdapter.d.ts +0 -47
  434. package/dist/adapters/MemoryAdapter.d.ts.map +0 -1
  435. package/dist/adapters/MemoryAdapter.js +0 -204
  436. package/dist/adapters/MemoryAdapter.js.map +0 -1
  437. package/dist/adapters/MongoAdapter.d.ts +0 -97
  438. package/dist/adapters/MongoAdapter.d.ts.map +0 -1
  439. package/dist/adapters/MongoAdapter.js +0 -196
  440. package/dist/adapters/MongoAdapter.js.map +0 -1
  441. package/dist/adapters/OpenSearchAdapter.d.ts +0 -169
  442. package/dist/adapters/OpenSearchAdapter.d.ts.map +0 -1
  443. package/dist/adapters/OpenSearchAdapter.js +0 -471
  444. package/dist/adapters/OpenSearchAdapter.js.map +0 -1
  445. package/dist/adapters/PostgreSQLAdapter.d.ts +0 -85
  446. package/dist/adapters/PostgreSQLAdapter.d.ts.map +0 -1
  447. package/dist/adapters/PostgreSQLAdapter.js +0 -308
  448. package/dist/adapters/PostgreSQLAdapter.js.map +0 -1
  449. package/dist/adapters/PrismaAdapter.d.ts +0 -115
  450. package/dist/adapters/PrismaAdapter.d.ts.map +0 -1
  451. package/dist/adapters/PrismaAdapter.js +0 -406
  452. package/dist/adapters/PrismaAdapter.js.map +0 -1
  453. package/dist/adapters/RedisAdapter.d.ts +0 -72
  454. package/dist/adapters/RedisAdapter.d.ts.map +0 -1
  455. package/dist/adapters/RedisAdapter.js +0 -286
  456. package/dist/adapters/RedisAdapter.js.map +0 -1
  457. package/dist/adapters/SQLiteAdapter.d.ts +0 -86
  458. package/dist/adapters/SQLiteAdapter.d.ts.map +0 -1
  459. package/dist/adapters/SQLiteAdapter.js +0 -337
  460. package/dist/adapters/SQLiteAdapter.js.map +0 -1
  461. package/dist/adapters/index.d.ts +0 -17
  462. package/dist/adapters/index.d.ts.map +0 -1
  463. package/dist/adapters/index.js +0 -11
  464. package/dist/adapters/index.js.map +0 -1
  465. package/dist/adapters/sessionRow.d.ts +0 -22
  466. package/dist/adapters/sessionRow.d.ts.map +0 -1
  467. package/dist/adapters/sessionRow.js +0 -48
  468. package/dist/adapters/sessionRow.js.map +0 -1
  469. package/dist/cjs/adapters/MemoryAdapter.d.ts +0 -47
  470. package/dist/cjs/adapters/MemoryAdapter.d.ts.map +0 -1
  471. package/dist/cjs/adapters/MemoryAdapter.js +0 -208
  472. package/dist/cjs/adapters/MemoryAdapter.js.map +0 -1
  473. package/dist/cjs/adapters/MongoAdapter.d.ts +0 -97
  474. package/dist/cjs/adapters/MongoAdapter.d.ts.map +0 -1
  475. package/dist/cjs/adapters/MongoAdapter.js +0 -200
  476. package/dist/cjs/adapters/MongoAdapter.js.map +0 -1
  477. package/dist/cjs/adapters/OpenSearchAdapter.d.ts +0 -169
  478. package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +0 -1
  479. package/dist/cjs/adapters/OpenSearchAdapter.js +0 -475
  480. package/dist/cjs/adapters/OpenSearchAdapter.js.map +0 -1
  481. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts +0 -85
  482. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +0 -1
  483. package/dist/cjs/adapters/PostgreSQLAdapter.js +0 -312
  484. package/dist/cjs/adapters/PostgreSQLAdapter.js.map +0 -1
  485. package/dist/cjs/adapters/PrismaAdapter.d.ts +0 -115
  486. package/dist/cjs/adapters/PrismaAdapter.d.ts.map +0 -1
  487. package/dist/cjs/adapters/PrismaAdapter.js +0 -410
  488. package/dist/cjs/adapters/PrismaAdapter.js.map +0 -1
  489. package/dist/cjs/adapters/RedisAdapter.d.ts +0 -72
  490. package/dist/cjs/adapters/RedisAdapter.d.ts.map +0 -1
  491. package/dist/cjs/adapters/RedisAdapter.js +0 -290
  492. package/dist/cjs/adapters/RedisAdapter.js.map +0 -1
  493. package/dist/cjs/adapters/SQLiteAdapter.d.ts +0 -86
  494. package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +0 -1
  495. package/dist/cjs/adapters/SQLiteAdapter.js +0 -341
  496. package/dist/cjs/adapters/SQLiteAdapter.js.map +0 -1
  497. package/dist/cjs/adapters/index.d.ts +0 -17
  498. package/dist/cjs/adapters/index.d.ts.map +0 -1
  499. package/dist/cjs/adapters/index.js +0 -21
  500. package/dist/cjs/adapters/index.js.map +0 -1
  501. package/dist/cjs/adapters/sessionRow.d.ts +0 -22
  502. package/dist/cjs/adapters/sessionRow.d.ts.map +0 -1
  503. package/dist/cjs/adapters/sessionRow.js +0 -52
  504. package/dist/cjs/adapters/sessionRow.js.map +0 -1
  505. package/dist/cjs/constants/index.d.ts +0 -1
  506. package/dist/cjs/constants/index.d.ts.map +0 -1
  507. package/dist/cjs/constants/index.js +0 -4
  508. package/dist/cjs/constants/index.js.map +0 -1
  509. package/dist/cjs/core/AutoChainExecutor.d.ts +0 -97
  510. package/dist/cjs/core/AutoChainExecutor.d.ts.map +0 -1
  511. package/dist/cjs/core/AutoChainExecutor.js +0 -288
  512. package/dist/cjs/core/AutoChainExecutor.js.map +0 -1
  513. package/dist/cjs/core/BranchEvaluator.d.ts +0 -55
  514. package/dist/cjs/core/BranchEvaluator.d.ts.map +0 -1
  515. package/dist/cjs/core/BranchEvaluator.js +0 -125
  516. package/dist/cjs/core/BranchEvaluator.js.map +0 -1
  517. package/dist/cjs/core/DirectiveChainTracker.d.ts +0 -49
  518. package/dist/cjs/core/DirectiveChainTracker.d.ts.map +0 -1
  519. package/dist/cjs/core/DirectiveChainTracker.js +0 -121
  520. package/dist/cjs/core/DirectiveChainTracker.js.map +0 -1
  521. package/dist/cjs/core/Events.d.ts +0 -26
  522. package/dist/cjs/core/Events.d.ts.map +0 -1
  523. package/dist/cjs/core/Events.js +0 -144
  524. package/dist/cjs/core/Events.js.map +0 -1
  525. package/dist/cjs/core/Flow.d.ts +0 -183
  526. package/dist/cjs/core/Flow.d.ts.map +0 -1
  527. package/dist/cjs/core/Flow.js +0 -551
  528. package/dist/cjs/core/Flow.js.map +0 -1
  529. package/dist/cjs/core/FlowRouter.d.ts +0 -183
  530. package/dist/cjs/core/FlowRouter.d.ts.map +0 -1
  531. package/dist/cjs/core/FlowRouter.js +0 -1047
  532. package/dist/cjs/core/FlowRouter.js.map +0 -1
  533. package/dist/cjs/core/PersistenceManager.d.ts +0 -114
  534. package/dist/cjs/core/PersistenceManager.d.ts.map +0 -1
  535. package/dist/cjs/core/PersistenceManager.js +0 -336
  536. package/dist/cjs/core/PersistenceManager.js.map +0 -1
  537. package/dist/cjs/core/PromptComposer.d.ts +0 -47
  538. package/dist/cjs/core/PromptComposer.d.ts.map +0 -1
  539. package/dist/cjs/core/PromptComposer.js +0 -397
  540. package/dist/cjs/core/PromptComposer.js.map +0 -1
  541. package/dist/cjs/core/PromptSectionCache.d.ts +0 -48
  542. package/dist/cjs/core/PromptSectionCache.d.ts.map +0 -1
  543. package/dist/cjs/core/PromptSectionCache.js +0 -108
  544. package/dist/cjs/core/PromptSectionCache.js.map +0 -1
  545. package/dist/cjs/core/ResponseEngine.d.ts +0 -43
  546. package/dist/cjs/core/ResponseEngine.d.ts.map +0 -1
  547. package/dist/cjs/core/ResponseEngine.js +0 -235
  548. package/dist/cjs/core/ResponseEngine.js.map +0 -1
  549. package/dist/cjs/core/ResponseGenerationError.d.ts +0 -30
  550. package/dist/cjs/core/ResponseGenerationError.d.ts.map +0 -1
  551. package/dist/cjs/core/ResponseGenerationError.js +0 -35
  552. package/dist/cjs/core/ResponseGenerationError.js.map +0 -1
  553. package/dist/cjs/core/ResponseModal.d.ts +0 -305
  554. package/dist/cjs/core/ResponseModal.d.ts.map +0 -1
  555. package/dist/cjs/core/ResponseModal.js +0 -1414
  556. package/dist/cjs/core/ResponseModal.js.map +0 -1
  557. package/dist/cjs/core/ResponsePipeline.d.ts +0 -220
  558. package/dist/cjs/core/ResponsePipeline.d.ts.map +0 -1
  559. package/dist/cjs/core/ResponsePipeline.js +0 -1040
  560. package/dist/cjs/core/ResponsePipeline.js.map +0 -1
  561. package/dist/cjs/core/SessionFinalizer.d.ts +0 -34
  562. package/dist/cjs/core/SessionFinalizer.d.ts.map +0 -1
  563. package/dist/cjs/core/SessionFinalizer.js +0 -88
  564. package/dist/cjs/core/SessionFinalizer.js.map +0 -1
  565. package/dist/cjs/core/SessionManager.d.ts +0 -112
  566. package/dist/cjs/core/SessionManager.d.ts.map +0 -1
  567. package/dist/cjs/core/SessionManager.js +0 -308
  568. package/dist/cjs/core/SessionManager.js.map +0 -1
  569. package/dist/cjs/core/SignalCoordinator.d.ts +0 -103
  570. package/dist/cjs/core/SignalCoordinator.d.ts.map +0 -1
  571. package/dist/cjs/core/SignalCoordinator.js +0 -207
  572. package/dist/cjs/core/SignalCoordinator.js.map +0 -1
  573. package/dist/cjs/core/SignalEvaluator.d.ts +0 -86
  574. package/dist/cjs/core/SignalEvaluator.d.ts.map +0 -1
  575. package/dist/cjs/core/SignalEvaluator.js +0 -319
  576. package/dist/cjs/core/SignalEvaluator.js.map +0 -1
  577. package/dist/cjs/core/SignalProcessor.d.ts +0 -152
  578. package/dist/cjs/core/SignalProcessor.d.ts.map +0 -1
  579. package/dist/cjs/core/SignalProcessor.js +0 -505
  580. package/dist/cjs/core/SignalProcessor.js.map +0 -1
  581. package/dist/cjs/core/Step.d.ts +0 -184
  582. package/dist/cjs/core/Step.d.ts.map +0 -1
  583. package/dist/cjs/core/Step.js +0 -599
  584. package/dist/cjs/core/Step.js.map +0 -1
  585. package/dist/cjs/core/StepLifecycle.d.ts +0 -43
  586. package/dist/cjs/core/StepLifecycle.d.ts.map +0 -1
  587. package/dist/cjs/core/StepLifecycle.js +0 -180
  588. package/dist/cjs/core/StepLifecycle.js.map +0 -1
  589. package/dist/cjs/core/StreamingToolExecutor.d.ts +0 -142
  590. package/dist/cjs/core/StreamingToolExecutor.d.ts.map +0 -1
  591. package/dist/cjs/core/StreamingToolExecutor.js +0 -490
  592. package/dist/cjs/core/StreamingToolExecutor.js.map +0 -1
  593. package/dist/cjs/core/ToolLoopExecutor.d.ts +0 -133
  594. package/dist/cjs/core/ToolLoopExecutor.d.ts.map +0 -1
  595. package/dist/cjs/core/ToolLoopExecutor.js +0 -568
  596. package/dist/cjs/core/ToolLoopExecutor.js.map +0 -1
  597. package/dist/cjs/core/ToolManager.d.ts +0 -250
  598. package/dist/cjs/core/ToolManager.d.ts.map +0 -1
  599. package/dist/cjs/core/ToolManager.js +0 -1104
  600. package/dist/cjs/core/ToolManager.js.map +0 -1
  601. package/dist/cjs/core/createAgent.d.ts +0 -35
  602. package/dist/cjs/core/createAgent.d.ts.map +0 -1
  603. package/dist/cjs/core/createAgent.js +0 -39
  604. package/dist/cjs/core/createAgent.js.map +0 -1
  605. package/dist/cjs/core/flow-namespace.d.ts +0 -64
  606. package/dist/cjs/core/flow-namespace.d.ts.map +0 -1
  607. package/dist/cjs/core/flow-namespace.js +0 -182
  608. package/dist/cjs/core/flow-namespace.js.map +0 -1
  609. package/dist/cjs/core/toolGates.d.ts +0 -24
  610. package/dist/cjs/core/toolGates.d.ts.map +0 -1
  611. package/dist/cjs/core/toolGates.js +0 -52
  612. package/dist/cjs/core/toolGates.js.map +0 -1
  613. package/dist/cjs/types/persistence.d.ts +0 -254
  614. package/dist/cjs/types/persistence.d.ts.map +0 -1
  615. package/dist/cjs/types/persistence.js +0 -7
  616. package/dist/cjs/types/persistence.js.map +0 -1
  617. package/dist/cjs/types/prompt-cache.d.ts +0 -15
  618. package/dist/cjs/types/prompt-cache.d.ts.map +0 -1
  619. package/dist/cjs/types/prompt-cache.js +0 -6
  620. package/dist/cjs/types/prompt-cache.js.map +0 -1
  621. package/dist/cjs/types/signals.d.ts +0 -263
  622. package/dist/cjs/types/signals.d.ts.map +0 -1
  623. package/dist/cjs/types/signals.js +0 -11
  624. package/dist/cjs/types/signals.js.map +0 -1
  625. package/dist/cjs/types/template.d.ts +0 -84
  626. package/dist/cjs/types/template.d.ts.map +0 -1
  627. package/dist/cjs/types/template.js +0 -3
  628. package/dist/cjs/types/template.js.map +0 -1
  629. package/dist/cjs/utils/condition.d.ts +0 -63
  630. package/dist/cjs/utils/condition.d.ts.map +0 -1
  631. package/dist/cjs/utils/condition.js +0 -239
  632. package/dist/cjs/utils/condition.js.map +0 -1
  633. package/dist/cjs/utils/event.d.ts +0 -6
  634. package/dist/cjs/utils/event.d.ts.map +0 -1
  635. package/dist/cjs/utils/event.js +0 -20
  636. package/dist/cjs/utils/event.js.map +0 -1
  637. package/dist/cjs/utils/id.d.ts +0 -33
  638. package/dist/cjs/utils/id.d.ts.map +0 -1
  639. package/dist/cjs/utils/id.js +0 -84
  640. package/dist/cjs/utils/id.js.map +0 -1
  641. package/dist/cjs/utils/serialize.d.ts +0 -36
  642. package/dist/cjs/utils/serialize.d.ts.map +0 -1
  643. package/dist/cjs/utils/serialize.js +0 -77
  644. package/dist/cjs/utils/serialize.js.map +0 -1
  645. package/dist/cjs/utils/session.d.ts +0 -124
  646. package/dist/cjs/utils/session.d.ts.map +0 -1
  647. package/dist/cjs/utils/session.js +0 -396
  648. package/dist/cjs/utils/session.js.map +0 -1
  649. package/dist/constants/index.d.ts +0 -2
  650. package/dist/constants/index.d.ts.map +0 -1
  651. package/dist/constants/index.js +0 -4
  652. package/dist/constants/index.js.map +0 -1
  653. package/dist/core/AutoChainExecutor.d.ts +0 -97
  654. package/dist/core/AutoChainExecutor.d.ts.map +0 -1
  655. package/dist/core/AutoChainExecutor.js +0 -284
  656. package/dist/core/AutoChainExecutor.js.map +0 -1
  657. package/dist/core/BranchEvaluator.d.ts +0 -55
  658. package/dist/core/BranchEvaluator.d.ts.map +0 -1
  659. package/dist/core/BranchEvaluator.js +0 -121
  660. package/dist/core/BranchEvaluator.js.map +0 -1
  661. package/dist/core/DirectiveChainTracker.d.ts +0 -49
  662. package/dist/core/DirectiveChainTracker.d.ts.map +0 -1
  663. package/dist/core/DirectiveChainTracker.js +0 -117
  664. package/dist/core/DirectiveChainTracker.js.map +0 -1
  665. package/dist/core/Events.d.ts +0 -26
  666. package/dist/core/Events.d.ts.map +0 -1
  667. package/dist/core/Events.js +0 -137
  668. package/dist/core/Events.js.map +0 -1
  669. package/dist/core/Flow.d.ts +0 -183
  670. package/dist/core/Flow.d.ts.map +0 -1
  671. package/dist/core/Flow.js +0 -547
  672. package/dist/core/Flow.js.map +0 -1
  673. package/dist/core/FlowRouter.d.ts +0 -183
  674. package/dist/core/FlowRouter.d.ts.map +0 -1
  675. package/dist/core/FlowRouter.js +0 -1043
  676. package/dist/core/FlowRouter.js.map +0 -1
  677. package/dist/core/PersistenceManager.d.ts +0 -114
  678. package/dist/core/PersistenceManager.d.ts.map +0 -1
  679. package/dist/core/PersistenceManager.js +0 -332
  680. package/dist/core/PersistenceManager.js.map +0 -1
  681. package/dist/core/PromptComposer.d.ts +0 -47
  682. package/dist/core/PromptComposer.d.ts.map +0 -1
  683. package/dist/core/PromptComposer.js +0 -393
  684. package/dist/core/PromptComposer.js.map +0 -1
  685. package/dist/core/PromptSectionCache.d.ts +0 -48
  686. package/dist/core/PromptSectionCache.d.ts.map +0 -1
  687. package/dist/core/PromptSectionCache.js +0 -104
  688. package/dist/core/PromptSectionCache.js.map +0 -1
  689. package/dist/core/ResponseEngine.d.ts +0 -43
  690. package/dist/core/ResponseEngine.d.ts.map +0 -1
  691. package/dist/core/ResponseEngine.js +0 -231
  692. package/dist/core/ResponseEngine.js.map +0 -1
  693. package/dist/core/ResponseGenerationError.d.ts +0 -30
  694. package/dist/core/ResponseGenerationError.d.ts.map +0 -1
  695. package/dist/core/ResponseGenerationError.js +0 -31
  696. package/dist/core/ResponseGenerationError.js.map +0 -1
  697. package/dist/core/ResponseModal.d.ts +0 -305
  698. package/dist/core/ResponseModal.d.ts.map +0 -1
  699. package/dist/core/ResponseModal.js +0 -1410
  700. package/dist/core/ResponseModal.js.map +0 -1
  701. package/dist/core/ResponsePipeline.d.ts +0 -220
  702. package/dist/core/ResponsePipeline.d.ts.map +0 -1
  703. package/dist/core/ResponsePipeline.js +0 -1035
  704. package/dist/core/ResponsePipeline.js.map +0 -1
  705. package/dist/core/SessionFinalizer.d.ts +0 -34
  706. package/dist/core/SessionFinalizer.d.ts.map +0 -1
  707. package/dist/core/SessionFinalizer.js +0 -84
  708. package/dist/core/SessionFinalizer.js.map +0 -1
  709. package/dist/core/SessionManager.d.ts +0 -112
  710. package/dist/core/SessionManager.d.ts.map +0 -1
  711. package/dist/core/SessionManager.js +0 -301
  712. package/dist/core/SessionManager.js.map +0 -1
  713. package/dist/core/SignalCoordinator.d.ts +0 -103
  714. package/dist/core/SignalCoordinator.d.ts.map +0 -1
  715. package/dist/core/SignalCoordinator.js +0 -203
  716. package/dist/core/SignalCoordinator.js.map +0 -1
  717. package/dist/core/SignalEvaluator.d.ts +0 -86
  718. package/dist/core/SignalEvaluator.d.ts.map +0 -1
  719. package/dist/core/SignalEvaluator.js +0 -312
  720. package/dist/core/SignalEvaluator.js.map +0 -1
  721. package/dist/core/SignalProcessor.d.ts +0 -152
  722. package/dist/core/SignalProcessor.d.ts.map +0 -1
  723. package/dist/core/SignalProcessor.js +0 -498
  724. package/dist/core/SignalProcessor.js.map +0 -1
  725. package/dist/core/Step.d.ts +0 -184
  726. package/dist/core/Step.d.ts.map +0 -1
  727. package/dist/core/Step.js +0 -594
  728. package/dist/core/Step.js.map +0 -1
  729. package/dist/core/StepLifecycle.d.ts +0 -43
  730. package/dist/core/StepLifecycle.d.ts.map +0 -1
  731. package/dist/core/StepLifecycle.js +0 -176
  732. package/dist/core/StepLifecycle.js.map +0 -1
  733. package/dist/core/StreamingToolExecutor.d.ts +0 -142
  734. package/dist/core/StreamingToolExecutor.d.ts.map +0 -1
  735. package/dist/core/StreamingToolExecutor.js +0 -483
  736. package/dist/core/StreamingToolExecutor.js.map +0 -1
  737. package/dist/core/ToolLoopExecutor.d.ts +0 -133
  738. package/dist/core/ToolLoopExecutor.d.ts.map +0 -1
  739. package/dist/core/ToolLoopExecutor.js +0 -564
  740. package/dist/core/ToolLoopExecutor.js.map +0 -1
  741. package/dist/core/ToolManager.d.ts +0 -250
  742. package/dist/core/ToolManager.d.ts.map +0 -1
  743. package/dist/core/ToolManager.js +0 -1098
  744. package/dist/core/ToolManager.js.map +0 -1
  745. package/dist/core/createAgent.d.ts +0 -35
  746. package/dist/core/createAgent.d.ts.map +0 -1
  747. package/dist/core/createAgent.js +0 -36
  748. package/dist/core/createAgent.js.map +0 -1
  749. package/dist/core/flow-namespace.d.ts +0 -64
  750. package/dist/core/flow-namespace.d.ts.map +0 -1
  751. package/dist/core/flow-namespace.js +0 -179
  752. package/dist/core/flow-namespace.js.map +0 -1
  753. package/dist/core/toolGates.d.ts +0 -24
  754. package/dist/core/toolGates.d.ts.map +0 -1
  755. package/dist/core/toolGates.js +0 -49
  756. package/dist/core/toolGates.js.map +0 -1
  757. package/dist/types/persistence.d.ts +0 -254
  758. package/dist/types/persistence.d.ts.map +0 -1
  759. package/dist/types/persistence.js +0 -6
  760. package/dist/types/persistence.js.map +0 -1
  761. package/dist/types/prompt-cache.d.ts +0 -15
  762. package/dist/types/prompt-cache.d.ts.map +0 -1
  763. package/dist/types/prompt-cache.js +0 -5
  764. package/dist/types/prompt-cache.js.map +0 -1
  765. package/dist/types/signals.d.ts +0 -263
  766. package/dist/types/signals.d.ts.map +0 -1
  767. package/dist/types/signals.js +0 -10
  768. package/dist/types/signals.js.map +0 -1
  769. package/dist/types/template.d.ts +0 -84
  770. package/dist/types/template.d.ts.map +0 -1
  771. package/dist/types/template.js +0 -2
  772. package/dist/types/template.js.map +0 -1
  773. package/dist/utils/condition.d.ts +0 -63
  774. package/dist/utils/condition.d.ts.map +0 -1
  775. package/dist/utils/condition.js +0 -230
  776. package/dist/utils/condition.js.map +0 -1
  777. package/dist/utils/event.d.ts +0 -6
  778. package/dist/utils/event.d.ts.map +0 -1
  779. package/dist/utils/event.js +0 -17
  780. package/dist/utils/event.js.map +0 -1
  781. package/dist/utils/id.d.ts +0 -33
  782. package/dist/utils/id.d.ts.map +0 -1
  783. package/dist/utils/id.js +0 -77
  784. package/dist/utils/id.js.map +0 -1
  785. package/dist/utils/serialize.d.ts +0 -36
  786. package/dist/utils/serialize.d.ts.map +0 -1
  787. package/dist/utils/serialize.js +0 -72
  788. package/dist/utils/serialize.js.map +0 -1
  789. package/dist/utils/session.d.ts +0 -124
  790. package/dist/utils/session.d.ts.map +0 -1
  791. package/dist/utils/session.js +0 -379
  792. package/dist/utils/session.js.map +0 -1
  793. package/docs/concepts/directives.md +0 -369
  794. package/docs/reference/adapters.md +0 -543
  795. package/docs/reference/create-agent.md +0 -216
  796. package/docs/reference/directive.md +0 -242
  797. package/docs/reference/signals.md +0 -368
  798. package/examples/02-data-extraction.ts +0 -90
  799. package/examples/05-branching.ts +0 -140
  800. package/examples/06-flow-control.ts +0 -103
  801. package/examples/08-persistence.ts +0 -98
  802. package/examples/09-signals.ts +0 -144
  803. package/src/adapters/MemoryAdapter.ts +0 -281
  804. package/src/adapters/MongoAdapter.ts +0 -341
  805. package/src/adapters/OpenSearchAdapter.ts +0 -693
  806. package/src/adapters/PostgreSQLAdapter.ts +0 -487
  807. package/src/adapters/PrismaAdapter.ts +0 -617
  808. package/src/adapters/RedisAdapter.ts +0 -439
  809. package/src/adapters/SQLiteAdapter.ts +0 -496
  810. package/src/adapters/index.ts +0 -43
  811. package/src/adapters/sessionRow.ts +0 -57
  812. package/src/constants/index.ts +0 -2
  813. package/src/core/AutoChainExecutor.ts +0 -397
  814. package/src/core/BranchEvaluator.ts +0 -161
  815. package/src/core/DirectiveChainTracker.ts +0 -144
  816. package/src/core/Events.ts +0 -164
  817. package/src/core/Flow.ts +0 -665
  818. package/src/core/FlowRouter.ts +0 -1540
  819. package/src/core/PersistenceManager.ts +0 -446
  820. package/src/core/PromptComposer.ts +0 -448
  821. package/src/core/PromptSectionCache.ts +0 -125
  822. package/src/core/ResponseEngine.ts +0 -338
  823. package/src/core/ResponseGenerationError.ts +0 -53
  824. package/src/core/ResponseModal.ts +0 -1902
  825. package/src/core/ResponsePipeline.ts +0 -1404
  826. package/src/core/SessionFinalizer.ts +0 -108
  827. package/src/core/SessionManager.ts +0 -372
  828. package/src/core/SignalCoordinator.ts +0 -263
  829. package/src/core/SignalEvaluator.ts +0 -404
  830. package/src/core/SignalProcessor.ts +0 -663
  831. package/src/core/Step.ts +0 -782
  832. package/src/core/StepLifecycle.ts +0 -242
  833. package/src/core/StreamingToolExecutor.ts +0 -609
  834. package/src/core/ToolLoopExecutor.ts +0 -749
  835. package/src/core/ToolManager.ts +0 -1379
  836. package/src/core/createAgent.ts +0 -40
  837. package/src/core/flow-namespace.ts +0 -227
  838. package/src/core/toolGates.ts +0 -72
  839. package/src/types/persistence.ts +0 -303
  840. package/src/types/prompt-cache.ts +0 -17
  841. package/src/types/signals.ts +0 -338
  842. package/src/types/template.ts +0 -98
  843. package/src/utils/condition.ts +0 -296
  844. package/src/utils/event.ts +0 -16
  845. package/src/utils/id.ts +0 -91
  846. package/src/utils/serialize.ts +0 -86
  847. package/src/utils/session.ts +0 -501
package/src/core/Agent.ts CHANGED
@@ -1,1532 +1,136 @@
1
1
  /**
2
- * Core Agent implementation
2
+ * Agent: immutable configuration plus one entry point, `turn`.
3
+ *
4
+ * One instance serves every session; context and history arrive per turn.
5
+ * A turn is the eight phases of docs/rfc/v4-one-flow.md §4 in one line each:
6
+ * Runner moves the runs by code, Understand and Speak spend at most one
7
+ * provider call apiece, and Runner settles what they returned.
3
8
  */
4
9
 
5
- import type {
6
- AgentOptions,
7
- Term,
8
- Instruction,
9
- Tool,
10
- FlowOptions,
11
- SessionState,
12
- Template,
13
- AgentResponseStreamChunk,
14
- AgentResponse,
15
- StructuredSchema,
16
- ValidationError,
17
- ValidationResult,
18
- AiProvider,
19
- CompactionOptions,
20
- Directive,
21
- } from "../types/index.js";
22
- import type { Signal } from "../types/signals.js";
23
- import { NotImplementedError } from "../types/errors.js";
24
- import { SignalProcessor } from "./SignalProcessor.js";
25
- import { SignalEvaluator } from "./SignalEvaluator.js";
26
- import type { StreamOptions, GenerateOptions, RespondParams, ResponseModalDeps } from "./ResponseModal.js";
27
- import {
28
- mergeCollected,
29
- dropUndeclaredFields,
30
- enterFlow,
31
- enterStep,
32
- completeCurrentFlow,
33
- logger,
34
- LoggerLevel,
35
- generateSignalId,
36
- } from "../utils/index.js";
37
-
38
- import { Flow } from "./Flow.js";
39
- import { Step, FlowConfigurationError as StepFlowConfigurationError } from "./Step.js";
40
- import { PersistenceManager } from "./PersistenceManager.js";
41
- import { SessionManager } from "./SessionManager.js";
42
- import { FlowRouter } from "./FlowRouter.js";
43
- import { PromptSectionCache } from "./PromptSectionCache.js";
44
-
45
- import { ResponseModal } from "./ResponseModal.js";
46
- import { ToolManager } from "./ToolManager.js";
10
+ import type { AgentOptions, TurnInput, TurnResult, TurnStreamChunk } from "../types/agent.js";
11
+ import type { TokenUsage } from "../types/ai.js";
12
+ import type { CompactionOptions } from "../types/compaction.js";
13
+ import { FlowConfigurationError } from "../types/errors.js";
14
+ import { logger, LoggerLevel } from "../utils/logger.js";
15
+ import { addUsage } from "../utils/usage.js";
47
16
  import { CompactionEngine } from "./CompactionEngine.js";
48
-
49
- /**
50
- * Error thrown when data validation fails
51
- */
52
- class DataValidationError extends Error {
53
- constructor(public errors: ValidationError[], message?: string) {
54
- super(message || "Data validation failed");
55
- this.name = "DataValidationError";
17
+ import type { IdleRequest, SpeakOutcome, TalkRequest } from "./contracts.js";
18
+ import { validateFlow } from "./FlowSpec.js";
19
+ import { Runner, type Turn } from "./Runner.js";
20
+ import { Speak } from "./Speak.js";
21
+ import { Understand } from "./Understand.js";
22
+
23
+ export class Agent<C = unknown, D = unknown> {
24
+ private readonly runner: Runner<C, D>;
25
+ private readonly understand: Understand<C, D>;
26
+ private readonly speak: Speak<C, D>;
27
+ private readonly compaction?: CompactionOptions;
28
+
29
+ constructor(readonly options: AgentOptions<C, D>) {
30
+ if (options.debug) logger.setLevel(LoggerLevel.DEBUG);
31
+ validate(options);
32
+ this.compaction = compactionOptions(options);
33
+ this.runner = new Runner(options);
34
+ this.understand = new Understand(options);
35
+ this.speak = new Speak(options);
36
+ }
37
+
38
+ /** Take whatever just happened and return the messages to send and the timers to set. */
39
+ async turn(input: TurnInput<C, D>): Promise<TurnResult<D>> {
40
+ const { turn, talk } = await this.open(input);
41
+ await this.runner.settle(turn, talk ? await this.speak.run(this.runner.speakRequest(turn, talk)) : null);
42
+ return this.runner.finish(turn);
43
+ }
44
+
45
+ /** `turn`, streaming the spoken text as it is generated; the last chunk carries the result. */
46
+ async *turnStream(input: TurnInput<C, D>): AsyncIterable<TurnStreamChunk<D>> {
47
+ const { turn, talk } = await this.open(input);
48
+ let outcome: SpeakOutcome | null = null;
49
+ if (talk) {
50
+ for await (const chunk of this.speak.stream(this.runner.speakRequest(turn, talk))) {
51
+ if ("delta" in chunk) yield { delta: chunk.delta };
52
+ else outcome = chunk.outcome;
53
+ }
54
+ }
55
+ await this.runner.settle(turn, outcome);
56
+ yield { done: true, result: this.runner.finish(turn) };
57
+ }
58
+
59
+ /** Load, Ingest, Understand, Decide and Run: everything before the one speaker is known. */
60
+ private async open(input: TurnInput<C, D>): Promise<{ turn: Turn<C, D>; talk: TalkRequest<C, D> | IdleRequest<C, D> | null }> {
61
+ const { runner } = this;
62
+ const compacted = await this.compacted(input);
63
+ const turn = runner.begin(compacted.input);
64
+ turn.llmCalls += compacted.llmCalls;
65
+ turn.usage = addUsage(turn.usage, compacted.usage);
66
+ const request = runner.understandRequest(turn);
67
+ runner.decide(turn, request ? await this.understand.run(request) : null);
68
+ return { turn, talk: await runner.advance(turn) };
69
+ }
70
+
71
+ /** With `compaction` set, the history both calls see is trimmed once per turn; a summarization is one model call. */
72
+ private async compacted(
73
+ input: TurnInput<C, D>,
74
+ ): Promise<{ input: TurnInput<C, D>; llmCalls: number; usage?: TokenUsage }> {
75
+ const history = input.history ?? input.session?.history;
76
+ if (!this.compaction || !history?.length) return { input, llmCalls: 0 };
77
+ const result = await CompactionEngine.checkAndCompact(history, this.compaction);
78
+ const llmCalls = result.strategy === "auto_compact" ? 1 : 0;
79
+ const usage = result.usage ? { usage: result.usage } : {};
80
+ if (result.history === history) return { input, llmCalls, ...usage };
81
+ const trimmed: TurnInput<C, D> = Object.assign({}, input);
82
+ trimmed.history = result.history;
83
+ return { input: trimmed, llmCalls, ...usage };
56
84
  }
57
85
  }
58
86
 
59
- /**
60
- * Error thrown when flow configuration is invalid
61
- */
62
- class FlowConfigurationError extends Error {
63
- constructor(public flowTitle: string, public invalidFields: string[], message?: string) {
64
- super(message || `Flow configuration error in '${flowTitle}'`);
65
- this.name = "FlowConfigurationError";
66
- }
87
+ function compactionOptions<C, D>(options: AgentOptions<C, D>): CompactionOptions | undefined {
88
+ const config = options.compaction;
89
+ if (!config || config.enabled === false) return undefined;
90
+ const resolved: CompactionOptions = {
91
+ maxTokens: config.maxTokens,
92
+ compactionThreshold: config.compactionThreshold ?? 0.8,
93
+ preserveRecentCount: config.preserveRecentCount ?? 4,
94
+ maxToolResultChars: config.maxToolResultChars ?? 5000,
95
+ provider: options.provider,
96
+ };
97
+ CompactionEngine.validateOptions(resolved);
98
+ return resolved;
67
99
  }
68
100
 
69
- /**
70
- * Main Agent class with generic context and data support
71
- */
72
-
73
- export class Agent<TContext = unknown, TData = unknown> implements ResponseModalDeps<TContext, TData> {
74
- private _terms: Term<TContext, TData>[] = [];
75
- private _instructions: Instruction<TContext, TData>[] = [];
76
- private _tools: Tool<TContext, TData>[] = [];
77
- private _flows: Flow<TContext, TData>[] = [];
78
- private _context: TContext | undefined;
79
- private _persistenceManager: PersistenceManager<TData> | undefined;
80
- private _routingEngine: FlowRouter<TContext, TData>;
81
- private _responseModal: ResponseModal<TContext, TData>;
82
- private _knowledgeBase: Record<string, unknown> = {};
83
- private _schema?: StructuredSchema;
84
- /**
85
- * Staging buffer for data set before any session exists (initialData and
86
- * pre-session updateCollectedData calls). Consumed when a session is
87
- * created; once a session exists, `session.data` is the single source of
88
- * truth and this buffer stays empty.
89
- */
90
- private _pendingData: Partial<TData> = {};
91
- private _compactionOptions?: CompactionOptions;
92
- private _promptSectionCache: PromptSectionCache;
93
-
94
- /** Signals: typed event detectors that run around the LLM turn. */
95
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
96
- private _signals: Signal<TContext, TData, any>[];
97
-
98
- /**
99
- * Signal processor instance. Undefined when no signals are configured.
100
- * Constructed only when `options.signals` is non-empty (Requirement 2.3).
101
- */
102
- public signalProcessor: SignalProcessor<TContext, TData> | undefined;
103
-
104
- /** Maximum consecutive auto-steps allowed in a single turn before throwing. */
105
- public readonly maxAutoStepsPerTurn: number;
106
-
107
- /** Maximum chained directives allowed in a single turn before throwing. */
108
- public readonly maxDirectiveChain: number;
109
-
110
- /** Public session manager for easy session management */
111
- public session: SessionManager<TData>;
112
-
113
- /** Public tool manager for simplified tool creation and management */
114
- public tool: ToolManager<TContext, TData>;
115
-
116
- constructor(private options: AgentOptions<TContext, TData>) {
117
- this.maxAutoStepsPerTurn = options.maxAutoStepsPerTurn ?? 10;
118
- this.maxDirectiveChain = options.maxDirectiveChain ?? 10;
119
-
120
- // Validate routerMode reservation — only 'ai' is supported in v2.0
121
- if (options.routerMode !== undefined && options.routerMode !== 'ai') {
122
- throw new NotImplementedError(
123
- `[NotImplementedError] routerMode "${String(options.routerMode)}" is not implemented: only "ai" is supported in v2.0. ` +
124
- `Set routerMode to "ai" or omit the option.`
125
- );
126
- }
127
-
128
- // ─── Signal construction-time validation (Requirements 1.4, 1.5, 1.6, 1.9, 2.3) ───
129
- const rawSignals = options.signals ?? [];
130
-
131
- // Auto-generate stable ids for entries without `id`
132
- for (let i = 0; i < rawSignals.length; i++) {
133
- if (!rawSignals[i].id) {
134
- rawSignals[i] = {
135
- ...rawSignals[i],
136
- id: generateSignalId(rawSignals[i].title, rawSignals[i].description, i),
137
- };
138
- }
139
- }
140
-
141
- // Validate unique ids (Requirement 1.4)
142
- const idCounts = new Map<string, number>();
143
- for (const signal of rawSignals) {
144
- const id = signal.id!;
145
- idCounts.set(id, (idCounts.get(id) ?? 0) + 1);
146
- }
147
- const duplicateIds = [...idCounts.entries()]
148
- .filter(([, count]) => count > 1)
149
- .map(([id]) => id);
150
- if (duplicateIds.length > 0) {
151
- throw new StepFlowConfigurationError(
152
- `[FlowConfigurationError] Duplicate signal ids: ${duplicateIds.join(', ')}. ` +
153
- `Each signal must have a unique id.`
154
- );
155
- }
156
-
157
- // Validate signalBatchSize (positive integer when set)
158
- if (options.signalBatchSize !== undefined) {
159
- if (
160
- !Number.isInteger(options.signalBatchSize) ||
161
- options.signalBatchSize <= 0
162
- ) {
163
- throw new StepFlowConfigurationError(
164
- `[FlowConfigurationError] signalBatchSize must be a positive integer, got: ${options.signalBatchSize}.`
165
- );
166
- }
167
- }
168
-
169
- // Validate each signal's configuration
170
- for (const signal of rawSignals) {
171
- // Requirement 1.5: cooldown without cooldownMs → debug warning, treat as 'always'
172
- if (signal.behavior === 'cooldown' && signal.cooldownMs == null) {
173
- logger.debug(
174
- `[Agent] Signal "${signal.id}" has behavior 'cooldown' but no cooldownMs. Treating as 'always'.`
175
- );
176
- (signal as { behavior?: string }).behavior = 'always';
177
- }
178
-
179
- // Requirement 1.9: validate extract schema is a JSON Schema object
180
- if (signal.extract !== undefined) {
181
- if (
182
- signal.extract === null ||
183
- typeof signal.extract !== 'object' ||
184
- Array.isArray(signal.extract)
185
- ) {
186
- throw new StepFlowConfigurationError(
187
- `[FlowConfigurationError] Signal "${signal.id}" has an invalid extract schema. ` +
188
- `Expected a JSON Schema object, got: ${typeof signal.extract}.`
189
- );
190
- }
191
- }
192
- }
193
-
194
- this._signals = rawSignals;
195
-
196
- // Requirement 2.3: Only instantiate SignalProcessor when signals are present
197
- if (rawSignals.length > 0) {
198
- const evaluator = new SignalEvaluator<TContext, TData>(options.provider);
199
- this.signalProcessor = new SignalProcessor<TContext, TData>(
200
- rawSignals,
201
- options.provider,
202
- evaluator,
203
- { batchSize: options.signalBatchSize ?? 10 },
204
- );
205
- } else {
206
- this.signalProcessor = undefined;
207
- }
208
-
209
- // Set log level based on debug option. NOTE: loglevel's default logger is
210
- // process-global — one agent enabling debug turns on DEBUG for every agent
211
- // in the process. Warned so multi-tenant embedders aren't surprised.
212
- if (options.debug) {
213
- logger.warn(
214
- `[Agent] "${options.name}" enabled debug logging via the PROCESS-GLOBAL loglevel level. ` +
215
- `Every agent in this process now logs at DEBUG. Scope logging in your host if needed.`
216
- );
217
- logger.setLevel(LoggerLevel.DEBUG);
218
- }
219
-
220
- // Validate context configuration
221
- if (options.context !== undefined && options.contextProvider) {
222
- throw new Error(
223
- "Cannot provide both 'context' and 'contextProvider'. Choose one."
224
- );
225
- }
226
-
227
- // Initialize and validate agent-level schema if provided
228
- if (options.schema) {
229
- this._schema = options.schema;
230
- this.validateSchema(this._schema);
231
- logger.debug("[Agent] Agent-level schema initialized and validated");
232
- }
233
-
234
- // Initialize context if provided
235
- this._context = options.context;
236
-
237
- // Initialize collected data with initial data if provided
238
- if (options.initialData) {
239
- if (this._schema) {
240
- const validation = this.validateData(options.initialData);
241
- if (!validation.valid) {
242
- throw new Error(
243
- `Initial data validation failed: ${validation.errors.map(e => e.message).join(', ')}`
244
- );
245
- }
246
- }
247
- this._pendingData = { ...options.initialData };
248
- logger.debug("[Agent] Initial data set:", this._pendingData);
249
- }
250
-
251
- // Initialize prompt section cache
252
- this._promptSectionCache = new PromptSectionCache(options.promptCache);
253
-
254
- // Initialize flow router
255
- this._routingEngine = new FlowRouter<TContext, TData>({
256
- flowSwitchMargin: options.flowSwitchMargin,
257
- onFlowSwitch: () => this.invalidateFlowSections(),
258
- promptSectionCache: this._promptSectionCache,
259
- });
260
-
261
- // Initialize tool manager BEFORE ResponseModal (it reads agent.tool in constructor)
262
- this.tool = new ToolManager<TContext, TData>(this);
263
-
264
- // Initialize ResponseModal for handling all response generation
265
- this._responseModal = new ResponseModal<TContext, TData>(this, {
266
- maxToolLoops: options.maxToolLoops,
267
- });
268
-
269
- // Initialize persistence if configured
270
- if (options.persistence) {
271
- try {
272
- // Validate persistence configuration
273
- if (!options.persistence.adapter) {
274
- throw new Error("Persistence adapter is required when persistence is configured");
275
- }
276
-
277
- if (!options.persistence.adapter.sessionRepository) {
278
- throw new Error("Persistence adapter must provide a sessionRepository");
279
- }
280
-
281
- if (!options.persistence.adapter.messageRepository) {
282
- throw new Error("Persistence adapter must provide a messageRepository");
283
- }
284
-
285
- this._persistenceManager = new PersistenceManager<TData>(options.persistence);
286
-
287
- // Initialize the adapter if it has an initialize method
288
- if (options.persistence.adapter.initialize) {
289
- options.persistence.adapter.initialize().catch((error) => {
290
- logger.error(
291
- "[Agent] Persistence adapter initialization failed:",
292
- error instanceof Error ? error.message : String(error)
293
- );
294
- });
295
- }
296
- } catch (error) {
297
- const errorMessage = error instanceof Error ? error.message : String(error);
298
- logger.error("[Agent] Failed to initialize persistence:", errorMessage);
299
- throw new Error(`Failed to initialize persistence: ${errorMessage}`);
300
- }
301
- }
302
-
303
- // Initialize from options - use create methods for consistency
304
- if (options.terms) {
305
- options.terms.forEach((term) => {
306
- this.createTerm(term);
307
- });
308
- }
309
-
310
- // Initialize instructions (new unified form)
311
- if (options.instructions) {
312
- options.instructions.forEach((instruction) => {
313
- this.createInstruction(instruction);
314
- });
315
- }
316
-
317
- if (options.tools) {
318
- options.tools.forEach((tool) => {
319
- this.addTool(tool);
320
- });
321
- }
322
-
323
- if (options.flows) {
324
- options.flows.forEach((flowOptions) => {
325
- this.createFlow(flowOptions);
326
- });
327
- }
328
-
329
- // Validate deferred branch `then` string references against the flow registry.
330
- // This catches strings that don't match a local step id AND don't match any flow id/title.
331
- this.validateBranchReferences();
332
-
333
- // Initialize knowledge base
334
- if (options.knowledgeBase) {
335
- this._knowledgeBase = { ...options.knowledgeBase };
336
- }
337
-
338
- // Initialize compaction options if configured
339
- if (options.compaction && options.compaction.enabled !== false) {
340
- const compactionOptions: CompactionOptions = {
341
- maxTokens: options.compaction.maxTokens,
342
- compactionThreshold: options.compaction.compactionThreshold ?? 0.8,
343
- preserveRecentCount: options.compaction.preserveRecentCount ?? 4,
344
- maxToolResultChars: options.compaction.maxToolResultChars ?? 5000,
345
- provider: options.provider,
346
- };
347
- CompactionEngine.validateOptions(compactionOptions);
348
- this._compactionOptions = compactionOptions;
349
- logger.debug("[Agent] Compaction options initialized and validated");
350
- }
351
-
352
- // Initialize session manager — the single owner of the live session
353
- this.session = new SessionManager<TData>(this._persistenceManager, this);
354
-
355
- // Adopt an explicitly provided session
356
- if (options.session) {
357
- this.session.syncSession(options.session);
358
- }
359
-
360
- // Store sessionId for later use in getOrCreate calls
361
- if (options.sessionId) {
362
- this.session.setDefaultSessionId(options.sessionId);
363
- // The session will be loaded on first getOrCreate call; session.data
364
- // is the source of truth, so no data sync is needed here
365
- this.session.getOrCreate(options.sessionId).catch((err) => {
366
- logger.error("Failed to start session", err);
367
- });
368
- }
369
- }
370
-
371
- /**
372
- * Drain the pre-session data staging buffer.
373
- * @internal Called by SessionManager when a session is created or loaded.
374
- */
375
- consumePendingData(): Partial<TData> {
376
- const pending = this._pendingData;
377
- this._pendingData = {};
378
- return pending;
379
- }
380
-
381
- /**
382
- * Validate the agent-level schema structure
383
- * @private
384
- */
385
- private validateSchema(schema: StructuredSchema): void {
386
- if (!schema || typeof schema !== 'object') {
387
- throw new Error(
388
- "Agent schema must be a valid JSON Schema object. " +
389
- "Provide a schema with 'type': 'object' and 'properties' to define the data structure."
390
- );
391
- }
392
-
393
- if (schema.type !== 'object') {
394
- throw new Error(
395
- `Agent schema must be of type 'object', but received '${String(schema.type)}'. ` +
396
- "Agent-level schemas must define object structures for data collection."
397
- );
398
- }
399
-
400
- if (!schema.properties || typeof schema.properties !== 'object') {
401
- throw new Error(
402
- "Agent schema must have a 'properties' field defining the data fields. " +
403
- "Example: { type: 'object', properties: { name: { type: 'string' }, email: { type: 'string' } } }"
101
+ /** Every name a flow uses must resolve now, not on the turn that first reaches it. */
102
+ function validate<C, D>(options: AgentOptions<C, D>): void {
103
+ const ids = new Set<string>();
104
+ for (const flow of options.flows ?? []) {
105
+ if (ids.has(flow.id)) {
106
+ throw new FlowConfigurationError(
107
+ `[FlowConfigurationError] flow "${flow.id}" is declared twice: flow ids must be unique. Rename one of them.`,
404
108
  );
405
109
  }
406
-
407
- logger.debug("[Agent] Schema validation passed");
408
- }
409
-
410
- /**
411
- * Walk every flow's steps and resolve deferred string `then` values in branches
412
- * against the agent's flow registry. Strings that match neither a local step id
413
- * nor any flow id/title throw FlowConfigurationError.
414
- * @private
415
- */
416
- private validateBranchReferences(): void {
417
- for (const flow of this._flows) {
418
- this.validateFlowBranchReferences(flow);
419
- }
110
+ ids.add(flow.id);
111
+ for (const warning of validateFlow(flow, options).warnings) logger.warn(`[Agent] ${warning}`);
420
112
  }
421
-
422
- /**
423
- * Validate branch `then` string references for a single flow against the agent's
424
- * flow registry. Throws FlowConfigurationError for unresolved references.
425
- * @private
426
- */
427
- private validateFlowBranchReferences(flow: Flow<TContext, TData>): void {
428
- const steps = flow.getAllSteps();
429
- const localStepIds = new Set(steps.map(s => s.id));
430
-
431
- for (const step of steps) {
432
- if (!step.branches) continue;
433
-
434
- for (const entry of step.branches) {
435
- if (typeof entry.then !== 'string') continue;
436
-
437
- // Already matches a local step id — no deferred resolution needed
438
- if (localStepIds.has(entry.then)) continue;
439
-
440
- // Check against the agent's flow registry (id or title)
441
- const matchesFlow = this._flows.some(
442
- f => f.id === entry.then || f.title === entry.then
443
- );
444
-
445
- if (!matchesFlow) {
446
- throw new StepFlowConfigurationError(
447
- `[FlowConfigurationError] Unresolved branch target: "${entry.then}" in ${flow.id}.${step.id} does not match any step in the flow or any flow in the agent. ` +
448
- `Fix the branch "then" value to reference a valid step id or flow id/title.`
449
- );
450
- }
451
- }
452
- }
453
- }
454
-
455
- /**
456
- * Validate that every step's `collect` fields in a flow reference valid keys
457
- * from the agent-level schema. Throws FlowConfigurationError at construction
458
- * time if any collect field is not a valid schema key.
459
- *
460
- * This enforces Requirement 14.5: generic inference is preserved AND every
461
- * `collect` field reference is a valid key of the inferred TData.
462
- * @private
463
- */
464
- private validateFlowCollectFields(flow: Flow<TContext, TData>): void {
465
- const schemaKeys = Object.keys(this._schema!.properties!);
466
- const schemaKeySet = new Set(schemaKeys);
467
- const steps = flow.getAllSteps();
468
-
469
- for (const step of steps) {
470
- if (!step.collect || step.collect.length === 0) continue;
471
-
472
- const invalidFields = step.collect.filter(
473
- field => !schemaKeySet.has(String(field))
113
+ for (const tool of options.tools ?? []) {
114
+ // A function's parameters are a JSON Schema object, so anything else is a
115
+ // mistake — most often the action's `{ name: { type } }` map written in a
116
+ // tool. Only DeepSeek rejects it on the wire; everywhere else the tool is
117
+ // simply never callable, and nothing says so.
118
+ if (tool.parameters && tool.parameters.type !== "object") {
119
+ throw new FlowConfigurationError(
120
+ `[FlowConfigurationError] tool "${tool.id}": parameters must be a JSON Schema object. ` +
121
+ `Write { type: "object", properties: { ... }, required: [...] }.`,
474
122
  );
475
-
476
- if (invalidFields.length > 0) {
477
- throw new StepFlowConfigurationError(
478
- `[FlowConfigurationError] Step "${step.id}" in flow "${flow.title}" references invalid collect fields: ${invalidFields.map(f => String(f)).join(', ')}. ` +
479
- `Must be valid keys from agent schema. Available fields: ${schemaKeys.join(', ')}.`
480
- );
481
- }
482
- }
483
- }
484
-
485
- /**
486
- * Validate data against the agent-level schema.
487
- *
488
- * A field the schema does not declare is a warning, not an error: a model
489
- * can extract a key nobody asked for, and `updateCollectedData` drops it
490
- * instead of failing the turn. `valid` is false only when `errors` is not empty.
491
- */
492
- validateData(data: Partial<TData>): ValidationResult {
493
- if (!this._schema) {
494
- // No schema defined, consider all data valid
495
- return { valid: true, errors: [], warnings: [] };
496
- }
497
-
498
- const errors: ValidationError[] = [];
499
- const warnings: ValidationError[] = [];
500
-
501
- // Undeclared fields are warnings — updateCollectedData drops them
502
- if (this._schema.properties) {
503
- for (const [key, value] of Object.entries(data)) {
504
- if (!(key in this._schema.properties)) {
505
- warnings.push({
506
- field: key,
507
- value,
508
- message: `Field '${key}' is not defined in agent schema`,
509
- schemaPath: `properties.${key}`
510
- });
511
- }
512
- }
513
- }
514
-
515
- // Check required fields if specified
516
- if (this._schema.required && Array.isArray(this._schema.required)) {
517
- for (const requiredField of this._schema.required) {
518
- if (!(requiredField in data) || data[requiredField as keyof TData] === undefined) {
519
- warnings.push({
520
- field: requiredField,
521
- value: undefined,
522
- message: `Required field '${requiredField}' is missing`,
523
- schemaPath: `required`
524
- });
525
- }
526
- }
527
- }
528
-
529
- return {
530
- valid: errors.length === 0,
531
- errors,
532
- warnings
533
- };
534
- }
535
-
536
- /**
537
- * Check if a field is valid according to the agent schema
538
- * @param field - The field key to validate
539
- * @returns true if field exists in schema or no schema is defined, false otherwise
540
- */
541
- isValidSchemaField(field: keyof TData): boolean {
542
- if (!this._schema || !this._schema.properties) {
543
- // No schema defined, consider all fields valid
544
- return true;
545
- }
546
-
547
- return field as string in this._schema.properties;
548
- }
549
-
550
- /**
551
- * Get the current collected data.
552
- * Reads from the live session when one exists; otherwise from the
553
- * pre-session staging buffer.
554
- */
555
- getCollectedData(): Partial<TData> {
556
- const session = this.session.current;
557
- return session ? { ...session.data } : { ...this._pendingData };
558
- }
559
-
560
- /**
561
- * Update collected data with validation.
562
- * Writes to the live session when one exists; otherwise stages the data
563
- * for the session that will be created. Fields the agent schema does not
564
- * declare are dropped with a warning, never stored.
565
- */
566
- async updateCollectedData(updates: Partial<TData>): Promise<void> {
567
- const declaredUpdates = dropUndeclaredFields(updates, this._schema);
568
-
569
- // Validate the updates
570
- const validation = this.validateData(declaredUpdates);
571
- if (!validation.valid) {
572
- const errorMessages = validation.errors.map(e => e.message).join(', ');
573
- throw new DataValidationError(validation.errors, `[DataValidationError] Data validation failed: fields [${errorMessages}] did not pass schema validation. Fix the offending values to match the declared schema.`);
574
123
  }
575
-
576
- // Log warnings if any
577
- if (validation.warnings.length > 0) {
578
- const warningMessages = validation.warnings.map(w => w.message).join(', ');
579
- logger.warn(`[Agent] Data validation warnings: ${warningMessages}`);
580
- }
581
-
582
- const session = this.session.current;
583
- const previousData = session ? { ...session.data } : { ...this._pendingData };
584
-
585
- let newData: Partial<TData> = {
586
- ...previousData,
587
- ...declaredUpdates
588
- };
589
-
590
- // Trigger agent-level lifecycle hook if configured
591
- if (this.options.hooks?.onDataUpdate) {
592
- newData = await this.options.hooks.onDataUpdate(newData, previousData);
593
- }
594
-
595
- if (session) {
596
- session.data = newData;
597
- session.metadata!.lastUpdatedAt = new Date();
598
- } else {
599
- this._pendingData = newData;
600
- }
601
-
602
- logger.debug("[Agent] Collected data updated:", declaredUpdates);
603
- }
604
-
605
- // ---------------------------------------------------------------------------
606
- // Property accessors (get / set)
607
- // ---------------------------------------------------------------------------
608
-
609
- /**
610
- * Get agent name
611
- */
612
- get name(): string {
613
- return this.options.name;
614
- }
615
-
616
- /**
617
- * Set agent name
618
- */
619
- set name(value: string) {
620
- this.options.name = value;
621
- }
622
-
623
- /**
624
- * Get agent persona
625
- */
626
- get persona(): Template<TContext> | undefined {
627
- return this.options.persona;
628
- }
629
-
630
- /**
631
- * Set agent persona
632
- */
633
- set persona(value: Template<TContext> | undefined) {
634
- this.options.persona = value;
635
- }
636
-
637
- /**
638
- * Get agent goal
639
- */
640
- get goal(): string | undefined {
641
- return this.options.goal;
642
- }
643
-
644
- /**
645
- * Set agent goal
646
- */
647
- set goal(value: string | undefined) {
648
- this.options.goal = value;
649
- }
650
-
651
- /**
652
- * Get whether debug mode is enabled
653
- */
654
- get debug(): boolean {
655
- return this.options.debug ?? false;
656
- }
657
-
658
- /**
659
- * Set debug mode (also updates logger level)
660
- */
661
- set debug(value: boolean) {
662
- this.options.debug = value;
663
- logger.setLevel(value ? LoggerLevel.DEBUG : LoggerLevel.INFO);
664
- }
665
-
666
- /**
667
- * Get the AI provider
668
- */
669
- get provider(): AiProvider {
670
- return this.options.provider;
671
- }
672
-
673
- /**
674
- * Set the AI provider
675
- */
676
- set provider(value: AiProvider) {
677
- this.options.provider = value;
678
- }
679
-
680
- /**
681
- * Get the flow switch margin
682
- * @default 15
683
- */
684
- get flowSwitchMargin(): number {
685
- return this.options.flowSwitchMargin ?? 15;
686
- }
687
-
688
- /**
689
- * Set the flow switch margin
690
- */
691
- set flowSwitchMargin(value: number) {
692
- this.options.flowSwitchMargin = value;
693
- }
694
-
695
- /**
696
- * Get the prompt section cache instance
697
- */
698
- get promptSectionCache(): PromptSectionCache {
699
- return this._promptSectionCache;
700
- }
701
-
702
- /**
703
- * Get all terms
704
- */
705
- get terms(): Term<TContext, TData>[] {
706
- return [...this._terms];
707
- }
708
-
709
- /**
710
- * Get all instructions
711
- */
712
- get instructions(): Instruction<TContext, TData>[] {
713
- return [...this._instructions];
714
- }
715
-
716
- /**
717
- * Get all tools
718
- */
719
- get tools(): Tool<TContext, TData>[] {
720
- return [...this._tools];
721
- }
722
-
723
- /**
724
- * Get all flows
725
- */
726
- get flows(): Flow<TContext, TData>[] {
727
- return [...this._flows];
728
124
  }
729
-
730
- /**
731
- * Get current schema
732
- */
733
- get schema(): StructuredSchema | undefined {
734
- return this._schema;
735
- }
736
-
737
- /**
738
- * Set schema (validates structure)
739
- */
740
- set schema(value: StructuredSchema | undefined) {
741
- if (value) {
742
- this.validateSchema(value);
743
- }
744
- this._schema = value;
745
- }
746
-
747
- /**
748
- * Get the configured signals.
749
- */
750
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
751
- get signals(): Signal<TContext, TData, any>[] {
752
- return this._signals;
753
- }
754
-
755
- /**
756
- * Get the agent's knowledge base
757
- */
758
- get knowledgeBase(): Record<string, unknown> {
759
- return { ...this._knowledgeBase };
760
- }
761
-
762
- /**
763
- * Set the agent's knowledge base
764
- */
765
- set knowledgeBase(value: Record<string, unknown>) {
766
- this._knowledgeBase = { ...value };
767
- }
768
-
769
- /**
770
- * Get the current session (if set). Delegates to the SessionManager —
771
- * the single owner of the live session.
772
- */
773
- get currentSession(): SessionState<TData> | undefined {
774
- return this.session.current;
775
- }
776
-
777
- /**
778
- * Set the current session for convenience methods
779
- * Set to undefined to clear the current session
780
- */
781
- set currentSession(value: SessionState<TData> | undefined) {
782
- this.session.syncSession(value);
783
- this._promptSectionCache.invalidateAll();
784
- }
785
-
786
- /**
787
- * Get all flows
788
- */
789
- getFlows(): Flow<TContext, TData>[] {
790
- return this.flows;
791
- }
792
-
793
- /**
794
- * Get all terms
795
- */
796
- getTerms(): Term<TContext, TData>[] {
797
- return this.terms;
798
- }
799
-
800
- /**
801
- * Get all tools
802
- */
803
- getTools(): Tool<TContext, TData>[] {
804
- return this.tools;
805
- }
806
-
807
- /**
808
- * Get all instructions
809
- */
810
- getInstructions(): Instruction<TContext, TData>[] {
811
- return this.instructions;
812
- }
813
-
814
- /**
815
- * Invalidate flow-dependent prompt cache sections.
816
- * Called automatically when the active flow changes.
817
- */
818
- invalidateFlowSections(): void {
819
- this._promptSectionCache.invalidate('activeFlows');
820
- this._promptSectionCache.invalidate('flowKnowledgeBase');
821
- this._promptSectionCache.invalidate('instructionsFlow');
822
- }
823
-
824
- /**
825
- * Get the persistence manager (if configured)
826
- */
827
- getPersistenceManager(): PersistenceManager<TData> | undefined {
828
- return this._persistenceManager;
829
- }
830
-
831
- /**
832
- * Check if persistence is enabled
833
- */
834
- hasPersistence(): boolean {
835
- return this._persistenceManager !== undefined;
836
- }
837
-
838
- /**
839
- * Get the resolved compaction options (if compaction is configured)
840
- */
841
- getCompactionOptions(): CompactionOptions | undefined {
842
- return this._compactionOptions;
843
- }
844
-
845
- // ---------------------------------------------------------------------------
846
- // Core methods
847
- // ---------------------------------------------------------------------------
848
-
849
- /**
850
- * Create a new flow (journey) using agent-level data type
851
- */
852
- createFlow(
853
- options: FlowOptions<TContext, TData>
854
- ): Flow<TContext, TData> {
855
- // Validate that requiredFields exist in agent schema
856
- if (options.requiredFields && this._schema?.properties) {
857
- const invalidRequiredFields = options.requiredFields.filter(
858
- field => !(String(field) in this._schema!.properties!)
859
- );
860
- if (invalidRequiredFields.length > 0) {
125
+ const { idle } = options;
126
+ if (idle && idle !== "silent") {
127
+ const known = new Set((options.tools ?? []).map((tool) => tool.id));
128
+ for (const name of idle.tools ?? []) {
129
+ if (!known.has(name)) {
861
130
  throw new FlowConfigurationError(
862
- options.title,
863
- invalidRequiredFields.map(f => String(f)),
864
- `[FlowConfigurationError] Invalid required fields in flow "${options.title}": [${invalidRequiredFields.join(', ')}] are not declared in the agent schema. ` +
865
- `Use valid schema keys. Available fields: ${Object.keys(this._schema.properties).join(', ')}.`
131
+ `[FlowConfigurationError] idle: unknown tool "${name}". Register it in the agent's tools or fix the name.`,
866
132
  );
867
133
  }
868
134
  }
869
-
870
- // Validate that optionalFields exist in agent schema
871
- if (options.optionalFields && this._schema?.properties) {
872
- const invalidOptionalFields = options.optionalFields.filter(
873
- field => !(String(field) in this._schema!.properties!)
874
- );
875
- if (invalidOptionalFields.length > 0) {
876
- throw new FlowConfigurationError(
877
- options.title,
878
- invalidOptionalFields.map(f => String(f)),
879
- `[FlowConfigurationError] Invalid optional fields in flow "${options.title}": [${invalidOptionalFields.join(', ')}] are not declared in the agent schema. ` +
880
- `Use valid schema keys. Available fields: ${Object.keys(this._schema.properties).join(', ')}.`
881
- );
882
- }
883
- }
884
-
885
- // Overlap detection: warn (don't throw) when the incoming flow's
886
- // requiredFields intersect another registered flow's — the schema is
887
- // agent-level, so both flows complete together and one is silently
888
- // excluded from routing.
889
- if (options.requiredFields && options.requiredFields.length > 0) {
890
- const incoming = new Set(options.requiredFields.map(String));
891
- for (const existing of this._flows) {
892
- const shared = (existing.requiredFields ?? [])
893
- .map(String)
894
- .filter((f) => incoming.has(f));
895
- if (shared.length > 0) {
896
- logger.warn(
897
- `[FlowConfigurationError] Overlapping requiredFields: flows "${existing.title}" and "${options.title}" share [${shared.join(', ')}]. ` +
898
- `The schema is agent-level, so data collected for one flow marks the other complete and excludes it from routing. ` +
899
- `Give each flow distinct requiredFields, or set \`reentrant: true\` on flows that legitimately share fields.`
900
- );
901
- }
902
- }
903
- }
904
-
905
- const flow = new Flow<TContext, TData>(options, this);
906
-
907
- // Validate that step collect fields reference valid schema keys
908
- if (this._schema?.properties) {
909
- this.validateFlowCollectFields(flow);
910
- }
911
-
912
- this._flows.push(flow);
913
- return flow;
914
- }
915
-
916
- /**
917
- * Create a domain term for the glossary
918
- */
919
- createTerm(term: Term<TContext, TData>): this {
920
- this._terms.push(term);
921
- return this;
922
- }
923
-
924
- /**
925
- * Create an instruction (unified behavioral primitive).
926
- */
927
- createInstruction(instruction: Instruction<TContext, TData>): this {
928
- const instructionWithId = {
929
- ...instruction,
930
- kind: instruction.kind || 'should' as const,
931
- id: instruction.id || `instruction_${this._instructions.length}`,
932
- enabled: instruction.enabled !== false, // Default to true
933
- };
934
- this._instructions.push(instructionWithId);
935
- this._promptSectionCache.invalidate('instructionsGlobal');
936
- return this;
937
- }
938
-
939
- /**
940
- * Add a tool to the agent using the unified Tool interface
941
- * Creates and adds the tool to agent scope in one operation
942
- */
943
-
944
- addTool<TResult = unknown>(
945
- tool: Tool<TContext, TData, TResult>
946
- ): this {
947
- // Validate tool before adding
948
- if (!tool || !tool.id || !tool.handler) {
949
- throw new Error('Invalid tool: must have id and handler properties');
950
- }
951
-
952
- // Add directly to agent's tools array, preserving the TResult type
953
- this._tools.push(tool);
954
- logger.debug(`[Agent] Added tool to agent scope: ${tool.id}`);
955
- return this;
956
- }
957
-
958
- /**
959
- * Register multiple tools at the agent level
960
- */
961
-
962
- registerTools<TResult = unknown>(tools: Tool<TContext, TData, TResult>[]): this {
963
- tools.forEach((tool) => {
964
- // Validate each tool before adding
965
- if (!tool || !tool.id || !tool.handler) {
966
- throw new Error(`Invalid tool in batch: must have id and handler properties (tool: ${tool?.id || 'unknown'})`);
967
- }
968
- this._tools.push(tool);
969
- });
970
- logger.debug(`[Agent] Registered ${tools.length} tools`);
971
- return this;
972
- }
973
-
974
- /**
975
- * Update the agent's context
976
- * Triggers both agent-level and flow-specific onContextUpdate lifecycle hooks if configured
977
- */
978
- async updateContext(updates: Partial<TContext>): Promise<void> {
979
- const previousContext = this._context;
980
-
981
- // Merge updates with current context
982
- this._context = {
983
- ...(this._context as Record<string, unknown>),
984
- ...(updates as Record<string, unknown>),
985
- } as TContext;
986
-
987
- // Trigger flow-specific lifecycle hook if configured and session has current flow
988
- const activeSession = this.session.current;
989
- if (activeSession?.currentFlow) {
990
- const currentFlow = this._flows.find(
991
- (r) => r.id === activeSession.currentFlow?.id
992
- );
993
- if (
994
- currentFlow?.hooks?.onContextUpdate &&
995
- previousContext !== undefined
996
- ) {
997
- await currentFlow.handleContextUpdate(this._context, previousContext);
998
- }
999
- }
1000
-
1001
- // Trigger agent-level lifecycle hook if configured
1002
- if (this.options.hooks?.onContextUpdate && previousContext !== undefined) {
1003
- await this.options.hooks.onContextUpdate(this._context, previousContext);
1004
- }
1005
-
1006
- // Invalidate context-dependent prompt cache sections
1007
- this._promptSectionCache.invalidate('agentMeta');
1008
- this._promptSectionCache.invalidate('knowledgeBase');
1009
- this._promptSectionCache.invalidate('instructionsGlobal');
1010
- }
1011
-
1012
- /**
1013
- * Update collected data in session with lifecycle hook support
1014
- * Triggers both agent-level and flow-specific onDataUpdate lifecycle hooks if configured
1015
- * @internal
1016
- */
1017
- private async updateData(
1018
- session: SessionState<TData>,
1019
- dataUpdate: Partial<TData>
1020
- ): Promise<SessionState<TData>> {
1021
- const previousCollected = { ...session.data };
1022
-
1023
- // Merge new collected data
1024
- let newCollected = {
1025
- ...session.data,
1026
- ...dataUpdate,
1027
- };
1028
-
1029
- // Trigger flow-specific lifecycle hook if configured and session has a current flow
1030
- if (session.currentFlow) {
1031
- const currentFlow = this._flows.find(
1032
- (r) => r.id === session.currentFlow?.id
1033
- );
1034
- if (currentFlow?.hooks?.onDataUpdate) {
1035
- newCollected = await currentFlow.handleDataUpdate(
1036
- newCollected,
1037
- previousCollected
1038
- );
1039
- }
1040
- }
1041
-
1042
- // Trigger agent-level lifecycle hook if configured
1043
- if (this.options.hooks?.onDataUpdate) {
1044
- newCollected = (await this.options.hooks.onDataUpdate(
1045
- newCollected,
1046
- previousCollected
1047
- ));
1048
- }
1049
-
1050
- // Return updated session — session.data is the single source of truth,
1051
- // so no agent-side copy is kept
1052
- return mergeCollected(session, newCollected);
1053
- }
1054
-
1055
- /**
1056
- * Get current context (fetches from provider if configured)
1057
- */
1058
- async getContext(): Promise<TContext | undefined> {
1059
- // If context provider is configured, use it to fetch fresh context
1060
- if (this.options.contextProvider) {
1061
- return await this.options.contextProvider();
1062
- }
1063
-
1064
- // Otherwise return the stored context
1065
- return this._context;
1066
- }
1067
-
1068
- /**
1069
- * Generate a response based on history and context as a stream
1070
- */
1071
- async * respondStream(params: RespondParams<TContext, TData>): AsyncGenerator<AgentResponseStreamChunk<TData>> {
1072
- // Delegate to ResponseModal
1073
- yield* this._responseModal.respondStream(params);
1074
- }
1075
-
1076
- /**
1077
- * Generate a response based on history and context
1078
- */
1079
- async respond(params: RespondParams<TContext, TData>): Promise<AgentResponse<TData>> {
1080
- // Delegate to ResponseModal
1081
- return this._responseModal.respond(params);
1082
- }
1083
-
1084
- /**
1085
- * Get agent options
1086
- * @internal Used by ResponseModal
1087
- */
1088
- getAgentOptions(): AgentOptions<TContext, TData> {
1089
- return this.options;
1090
135
  }
1091
-
1092
- /**
1093
- * Get flow router
1094
- * @internal Used by ResponseModal
1095
- */
1096
- getFlowRouter(): FlowRouter<TContext, TData> {
1097
- return this._routingEngine;
1098
- }
1099
-
1100
- /**
1101
- * Get the updateData method bound to this agent
1102
- * @internal Used by ResponseModal
1103
- */
1104
- getUpdateDataMethod(): (session: SessionState<TData>, dataUpdate: Partial<TData>) => Promise<SessionState<TData>> {
1105
- return this.updateData.bind(this);
1106
- }
1107
-
1108
- /**
1109
- * Execute a prepare or finalize function/tool
1110
- * @internal Used by ResponseModal
1111
- */
1112
- async executePrepareFinalize(
1113
- prepareOrFinalize:
1114
- | string
1115
- | Tool<TContext, TData>
1116
- | ((context: TContext, data?: Partial<TData>) => void | Promise<void>)
1117
- | undefined,
1118
- context: TContext,
1119
- data?: Partial<TData>,
1120
- flow?: Flow<TContext, TData>,
1121
- step?: Step<TContext, TData>
1122
- ): Promise<void> {
1123
- if (!prepareOrFinalize) return;
1124
-
1125
- if (typeof prepareOrFinalize === "function") {
1126
- // It's a function - call it directly
1127
- await prepareOrFinalize(context, data);
1128
- } else {
1129
- // It's a tool reference - find and execute the tool
1130
- let tool: Tool<TContext, TData> | undefined;
1131
-
1132
- if (typeof prepareOrFinalize === "string") {
1133
- // Tool ID - use ToolManager to find it across all scopes
1134
- tool = this.tool.find(prepareOrFinalize, undefined, step, flow);
1135
- } else {
1136
- // Tool object - validate it has required properties
1137
- if (prepareOrFinalize.id && typeof prepareOrFinalize.handler === 'function') {
1138
- tool = prepareOrFinalize;
1139
- } else {
1140
- logger.error(`[Agent] Invalid tool object for prepare/finalize: missing id or invalid handler`);
1141
- return;
1142
- }
1143
- }
1144
-
1145
- if (tool) {
1146
- // Use ToolManager for execution
1147
- const result = await this.tool.executeTool({
1148
- tool,
1149
- context,
1150
- updateContext: this.updateContext.bind(this),
1151
- updateData: this.updateCollectedData.bind(this),
1152
- history: [], // Empty history for prepare/finalize
1153
- data,
1154
- });
1155
-
1156
- if (!result.success) {
1157
- logger.error(
1158
- `[Agent] Tool execution failed in prepare/finalize: ${result.error}`
1159
- );
1160
- throw new Error(`Tool execution failed: ${result.error}`);
1161
- }
1162
- } else {
1163
- logger.warn(
1164
- `[Agent] Tool not found for prepare/finalize: ${typeof prepareOrFinalize === "string"
1165
- ? prepareOrFinalize
1166
- : "inline tool"
1167
- }`
1168
- );
1169
- }
1170
- }
1171
- }
1172
-
1173
- /**
1174
- * Get collected data from the current session (or the pre-session staging
1175
- * buffer when no session exists yet). Alias of getCollectedData().
1176
- */
1177
- getData(): Partial<TData> {
1178
- return this.getCollectedData();
1179
- }
1180
-
1181
- /**
1182
- * Dispatch a directive (or a flow shorthand) into a session.
1183
- * Sets `pendingDirective` on the session without triggering a `respond()` call.
1184
- * The directive will be applied at the start of the next turn.
1185
- *
1186
- * String form desugars to `{ goTo: target }`.
1187
- *
1188
- * Durability: with a persistence adapter and autoSave configured (the
1189
- * defaults), the queued directive is persisted immediately — safe for
1190
- * out-of-process callers like webhooks or cron. Without an adapter it is
1191
- * memory-only, as is `persistence.autoSave: false` (then persisting before
1192
- * the next turn is the caller's job).
1193
- *
1194
- * @param target - Flow ID/title string (desugars to `{ goTo: target }`) or a full Directive
1195
- * @param session - Session to update (uses current session if not provided)
1196
- * @returns Updated session with `pendingDirective` set
1197
- *
1198
- * @throws FlowConfigurationError if the string target doesn't match any flow
1199
- * @throws FlowConfigurationError if the directive fails validation
1200
- * @throws SessionConflictError when persistence is enabled and another writer
1201
- * moved the stored session since this copy was loaded
1202
- *
1203
- * @example
1204
- * // String shorthand — desugars to { goTo: 'Feedback' }
1205
- * const updated = await agent.dispatch('Feedback', session);
1206
- *
1207
- * @example
1208
- * // Full directive
1209
- * const updated = await agent.dispatch({ goTo: 'Billing', reply: 'Transferring you now.' }, session);
1210
- */
1211
- async dispatch(
1212
- target: string | Directive<TContext, TData>,
1213
- session?: SessionState<TData>
1214
- ): Promise<SessionState<TData>> {
1215
- const targetSession = session || this.session.current;
1216
-
1217
- if (!targetSession) {
1218
- throw new Error(
1219
- "No session provided and no current session available. Please provide a session to dispatch into."
1220
- );
1221
- }
1222
-
1223
- // Desugar string form to { goTo: target }
1224
- const directive: Directive<TContext, TData> = typeof target === 'string'
1225
- ? { goTo: target }
1226
- : target;
1227
-
1228
- // Validate the directive: check for multiple position fields, empty goTo, etc.
1229
- this.validateDirective(directive);
1230
-
1231
- // If goTo is a string, validate it references a known flow
1232
- if (typeof directive.goTo === 'string') {
1233
- const flowTarget = directive.goTo;
1234
- const matchesFlow = this._flows.some(
1235
- f => f.id === flowTarget || f.title === flowTarget
1236
- );
1237
- if (!matchesFlow) {
1238
- throw new StepFlowConfigurationError(
1239
- `[FlowConfigurationError] Unknown flow: "${flowTarget}" does not match any flow id or title. ` +
1240
- `Available flows: ${this._flows.map(f => f.title).join(', ')}.`
1241
- );
1242
- }
1243
- } else if (directive.goTo && typeof directive.goTo === 'object' && directive.goTo.flow) {
1244
- const flowTarget = directive.goTo.flow;
1245
- const matchesFlow = this._flows.some(
1246
- f => f.id === flowTarget || f.title === flowTarget
1247
- );
1248
- if (!matchesFlow) {
1249
- throw new StepFlowConfigurationError(
1250
- `[FlowConfigurationError] Unknown flow: "${flowTarget}" does not match any flow id or title. ` +
1251
- `Available flows: ${this._flows.map(f => f.title).join(', ')}.`
1252
- );
1253
- }
1254
- }
1255
-
1256
- // Strip pre-LLM-only fields before storing
1257
- const stripped = this.stripPreDirectiveFields(directive);
1258
-
1259
- // Set pendingDirective on the session without applying it
1260
- const updatedSession: SessionState<TData> = {
1261
- ...targetSession,
1262
- pendingDirective: stripped as Directive<unknown, TData>,
1263
- metadata: {
1264
- ...targetSession.metadata,
1265
- lastUpdatedAt: new Date(),
1266
- },
1267
- };
1268
-
1269
- // Durability: with an adapter + autoSave configured, dispatch persists
1270
- // immediately — webhooks/cron run out-of-process from the responder, and a
1271
- // memory-only queue would evaporate with this process. The save stamps the
1272
- // new version back onto updatedSession, so the next turn's auto-save CAS
1273
- // stays clean. Persisting BEFORE the in-memory sync keeps the existing
1274
- // invariant: a throwing dispatch leaves the session untouched.
1275
- if (this._persistenceManager && this.options.persistence?.autoSave !== false) {
1276
- await this._persistenceManager.saveSessionState(updatedSession.id, updatedSession);
1277
- logger.debug(
1278
- `[Agent] Dispatched directive persisted to adapter for session ${updatedSession.id}`
1279
- );
1280
- }
1281
-
1282
- // Update current session in place if no explicit session was passed
1283
- if (!session && this.session.current) {
1284
- this.session.syncSession(updatedSession);
1285
- }
1286
-
1287
- logger.debug(
1288
- `[Agent] Dispatched directive: pendingDirective set on session ${updatedSession.id}`
1289
- );
1290
-
1291
- return updatedSession;
1292
- }
1293
-
1294
- /**
1295
- * Apply a directive synchronously to a session without invoking `respond()`.
1296
- * Performs in-place application: updates flow/step position, merges state writes.
1297
- *
1298
- * This is the synchronous counterpart to `dispatch` — it applies immediately
1299
- * rather than deferring to the next turn.
1300
- *
1301
- * @param directive - The directive to apply
1302
- * @param session - The session to apply the directive to
1303
- * @returns The updated session with the directive applied
1304
- */
1305
- applyDirective(
1306
- directive: Directive<TContext, TData>,
1307
- session: SessionState<TData>
1308
- ): SessionState<TData> {
1309
- // Validate the directive
1310
- this.validateDirective(directive);
1311
-
1312
- let updatedSession = { ...session };
1313
- const now = new Date();
1314
-
1315
- // Apply state writes
1316
- if (directive.contextUpdate) {
1317
- // Context updates are applied to the agent, not the session
1318
- this._context = {
1319
- ...(this._context as Record<string, unknown>),
1320
- ...(directive.contextUpdate as Record<string, unknown>),
1321
- } as TContext;
1322
- }
1323
-
1324
- if (directive.dataUpdate) {
1325
- updatedSession = {
1326
- ...updatedSession,
1327
- data: {
1328
- ...updatedSession.data,
1329
- ...directive.dataUpdate,
1330
- },
1331
- };
1332
- }
1333
-
1334
- // Apply position control
1335
- if (directive.goTo) {
1336
- const flowTarget = typeof directive.goTo === 'string'
1337
- ? directive.goTo
1338
- : directive.goTo.flow;
1339
-
1340
- if (flowTarget) {
1341
- const targetFlow = this._flows.find(
1342
- f => f.id === flowTarget || f.title === flowTarget
1343
- );
1344
- if (targetFlow) {
1345
- // Merge goTo.data if present
1346
- if (typeof directive.goTo === 'object' && directive.goTo.data) {
1347
- updatedSession = {
1348
- ...updatedSession,
1349
- data: {
1350
- ...updatedSession.data,
1351
- ...directive.goTo.data,
1352
- },
1353
- };
1354
- }
1355
-
1356
- updatedSession = enterFlow(updatedSession, targetFlow.id, targetFlow.title);
1357
-
1358
- // If a specific step is targeted
1359
- if (typeof directive.goTo === 'object' && directive.goTo.step) {
1360
- updatedSession = enterStep(updatedSession, directive.goTo.step);
1361
- }
1362
- }
1363
- }
1364
- } else if (directive.goToStep) {
1365
- const stepTarget = typeof directive.goToStep === 'string'
1366
- ? directive.goToStep
1367
- : directive.goToStep.step;
1368
-
1369
- // Merge goToStep.data if present
1370
- if (typeof directive.goToStep === 'object' && directive.goToStep.data) {
1371
- updatedSession = {
1372
- ...updatedSession,
1373
- data: {
1374
- ...updatedSession.data,
1375
- ...directive.goToStep.data,
1376
- },
1377
- };
1378
- }
1379
-
1380
- updatedSession = enterStep(updatedSession, stepTarget);
1381
- } else if (directive.complete) {
1382
- updatedSession = completeCurrentFlow(updatedSession);
1383
-
1384
- // If complete carries a chained directive, set it as pendingDirective
1385
- if (typeof directive.complete === 'object' && directive.complete.next) {
1386
- updatedSession = {
1387
- ...updatedSession,
1388
- pendingDirective: directive.complete.next as Directive<unknown, TData>,
1389
- };
1390
- }
1391
- } else if (directive.abort) {
1392
- const clearSession = typeof directive.abort === 'object'
1393
- ? directive.abort.clearSession !== false
1394
- : true;
1395
-
1396
- if (clearSession) {
1397
- updatedSession = {
1398
- ...updatedSession,
1399
- currentFlow: undefined,
1400
- currentStep: undefined,
1401
- data: {} as Partial<TData>,
1402
- };
1403
- } else {
1404
- updatedSession = {
1405
- ...updatedSession,
1406
- currentFlow: undefined,
1407
- currentStep: undefined,
1408
- };
1409
- }
1410
- } else if (directive.reset) {
1411
- const currentFlowId = updatedSession.currentFlow?.id;
1412
- const currentFlowTitle = updatedSession.currentFlow?.title;
1413
-
1414
- if (currentFlowId && currentFlowTitle) {
1415
- // Clear data if requested
1416
- if (typeof directive.reset === 'object' && directive.reset.clearData) {
1417
- const currentFlow = this._flows.find(f => f.id === currentFlowId);
1418
- if (currentFlow) {
1419
- const ownedFields = [
1420
- ...(currentFlow.requiredFields || []),
1421
- ...(currentFlow.optionalFields || []),
1422
- ];
1423
- updatedSession = completeCurrentFlow(updatedSession, { clearOwnedFields: ownedFields });
1424
- // Re-enter the same flow
1425
- updatedSession = enterFlow(updatedSession, currentFlowId, currentFlowTitle);
1426
- }
1427
- } else {
1428
- // Re-enter the flow from the beginning (or specified step)
1429
- updatedSession = enterFlow(updatedSession, currentFlowId, currentFlowTitle);
1430
- }
1431
-
1432
- // If a specific step is targeted for reset
1433
- if (typeof directive.reset === 'object' && directive.reset.step) {
1434
- updatedSession = enterStep(updatedSession, directive.reset.step);
1435
- }
1436
- }
1437
- }
1438
-
1439
- // Update metadata
1440
- updatedSession = {
1441
- ...updatedSession,
1442
- metadata: {
1443
- ...updatedSession.metadata,
1444
- lastUpdatedAt: now,
1445
- },
1446
- };
1447
-
1448
- return updatedSession;
1449
- }
1450
-
1451
- /**
1452
- * Validate a directive for structural correctness.
1453
- * Throws FlowConfigurationError for invalid combinations.
1454
- * @private
1455
- */
1456
- private validateDirective(directive: Directive<TContext, TData>): void {
1457
- // Check for multiple position fields
1458
- const positionFields = ['goTo', 'goToStep', 'complete', 'abort', 'reset'] as const;
1459
- const setPositionFields = positionFields.filter(
1460
- field => directive[field] !== undefined
1461
- );
1462
-
1463
- if (setPositionFields.length > 1) {
1464
- throw new StepFlowConfigurationError(
1465
- `[FlowConfigurationError] Multiple position fields: a Directive may set at most one position field. ` +
1466
- `Found: ${setPositionFields.join(', ')}. Remove all but one.`
1467
- );
1468
- }
1469
-
1470
- // Check for empty goTo object
1471
- if (directive.goTo && typeof directive.goTo === 'object') {
1472
- const goToObj = directive.goTo;
1473
- if (!goToObj.flow && !goToObj.step) {
1474
- throw new StepFlowConfigurationError(
1475
- `[FlowConfigurationError] Empty goTo: "goTo" requires at least a "flow" field. ` +
1476
- `Provide { goTo: { flow: '<id>' } } or use the string shorthand { goTo: '<id>' }.`
1477
- );
1478
- }
1479
- }
1480
- }
1481
-
1482
- /**
1483
- * Strip pre-LLM-only fields (appendPrompt, injectTools, halt) from a directive.
1484
- * These fields are transient (one-turn lifetime) and must not be persisted.
1485
- * @private
1486
- */
1487
- private stripPreDirectiveFields(directive: Directive<TContext, TData>): Directive<TContext, TData> {
1488
- const raw = directive as Record<string, unknown>;
1489
- if (!raw.appendPrompt && !raw.injectTools && raw.halt === undefined) {
1490
- return directive;
1491
- }
1492
-
1493
- const { appendPrompt, injectTools, halt, ...rest } = raw;
1494
-
1495
- if (appendPrompt || injectTools || halt !== undefined) {
1496
- logger.warn(
1497
- `[Agent] Ignoring pre-LLM-only fields on pendingDirective (these only take effect in onEnter/prepare hooks): ` +
1498
- `${[appendPrompt && 'appendPrompt', injectTools && 'injectTools', halt !== undefined && 'halt'].filter(Boolean).join(', ')}`
1499
- );
1500
- }
1501
-
1502
- return rest as Directive<TContext, TData>;
1503
- }
1504
-
1505
- /**
1506
- * Simplified respond method using SessionManager
1507
- * Automatically manages conversation history through the session
1508
- */
1509
- async chat(
1510
- message?: string,
1511
- options?: GenerateOptions<TContext>
1512
- ): Promise<AgentResponse<TData>> {
1513
- // Delegate to ResponseModal.generate()
1514
- return this._responseModal.generate(message, options);
1515
- }
1516
-
1517
- /**
1518
- * Modern streaming API - simple interface like chat() but returns a stream
1519
- * Automatically manages conversation history through the session
1520
- */
1521
- async * stream(
1522
- message?: string,
1523
- options?: StreamOptions<TContext>
1524
- ): AsyncGenerator<AgentResponseStreamChunk<TData>> {
1525
- // Delegate to ResponseModal with the same options structure as chat()
1526
- yield* this._responseModal.stream(message, {
1527
- history: options?.history,
1528
- contextOverride: options?.contextOverride,
1529
- signal: options?.signal,
1530
- });
1531
- }
1532
- }
136
+ }