@falai/agent 1.2.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. package/README.md +40 -886
  2. package/dist/adapters/MemoryAdapter.js +2 -2
  3. package/dist/adapters/MemoryAdapter.js.map +1 -1
  4. package/dist/adapters/MongoAdapter.js +2 -2
  5. package/dist/adapters/MongoAdapter.js.map +1 -1
  6. package/dist/adapters/OpenSearchAdapter.d.ts.map +1 -1
  7. package/dist/adapters/OpenSearchAdapter.js +9 -7
  8. package/dist/adapters/OpenSearchAdapter.js.map +1 -1
  9. package/dist/adapters/PostgreSQLAdapter.d.ts +14 -0
  10. package/dist/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  11. package/dist/adapters/PostgreSQLAdapter.js +25 -9
  12. package/dist/adapters/PostgreSQLAdapter.js.map +1 -1
  13. package/dist/adapters/PrismaAdapter.js +5 -5
  14. package/dist/adapters/PrismaAdapter.js.map +1 -1
  15. package/dist/adapters/RedisAdapter.js +2 -2
  16. package/dist/adapters/RedisAdapter.js.map +1 -1
  17. package/dist/adapters/SQLiteAdapter.d.ts +17 -0
  18. package/dist/adapters/SQLiteAdapter.d.ts.map +1 -1
  19. package/dist/adapters/SQLiteAdapter.js +30 -11
  20. package/dist/adapters/SQLiteAdapter.js.map +1 -1
  21. package/dist/cjs/adapters/MemoryAdapter.js +2 -2
  22. package/dist/cjs/adapters/MemoryAdapter.js.map +1 -1
  23. package/dist/cjs/adapters/MongoAdapter.js +2 -2
  24. package/dist/cjs/adapters/MongoAdapter.js.map +1 -1
  25. package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +1 -1
  26. package/dist/cjs/adapters/OpenSearchAdapter.js +9 -7
  27. package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -1
  28. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts +14 -0
  29. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  30. package/dist/cjs/adapters/PostgreSQLAdapter.js +25 -9
  31. package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -1
  32. package/dist/cjs/adapters/PrismaAdapter.js +5 -5
  33. package/dist/cjs/adapters/PrismaAdapter.js.map +1 -1
  34. package/dist/cjs/adapters/RedisAdapter.js +2 -2
  35. package/dist/cjs/adapters/RedisAdapter.js.map +1 -1
  36. package/dist/cjs/adapters/SQLiteAdapter.d.ts +17 -0
  37. package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +1 -1
  38. package/dist/cjs/adapters/SQLiteAdapter.js +30 -11
  39. package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -1
  40. package/dist/cjs/constants/index.d.ts +0 -9
  41. package/dist/cjs/constants/index.d.ts.map +1 -1
  42. package/dist/cjs/constants/index.js +2 -11
  43. package/dist/cjs/constants/index.js.map +1 -1
  44. package/dist/cjs/core/Agent.d.ts +119 -153
  45. package/dist/cjs/core/Agent.d.ts.map +1 -1
  46. package/dist/cjs/core/Agent.js +471 -324
  47. package/dist/cjs/core/Agent.js.map +1 -1
  48. package/dist/cjs/core/AutoChainExecutor.d.ts +107 -0
  49. package/dist/cjs/core/AutoChainExecutor.d.ts.map +1 -0
  50. package/dist/cjs/core/AutoChainExecutor.js +297 -0
  51. package/dist/cjs/core/AutoChainExecutor.js.map +1 -0
  52. package/dist/cjs/core/BranchEvaluator.d.ts +54 -0
  53. package/dist/cjs/core/BranchEvaluator.d.ts.map +1 -0
  54. package/dist/cjs/core/BranchEvaluator.js +130 -0
  55. package/dist/cjs/core/BranchEvaluator.js.map +1 -0
  56. package/dist/cjs/core/DirectiveBus.d.ts +88 -0
  57. package/dist/cjs/core/DirectiveBus.d.ts.map +1 -0
  58. package/dist/cjs/core/DirectiveBus.js +196 -0
  59. package/dist/cjs/core/DirectiveBus.js.map +1 -0
  60. package/dist/cjs/core/DirectiveChainTracker.d.ts +49 -0
  61. package/dist/cjs/core/DirectiveChainTracker.d.ts.map +1 -0
  62. package/dist/cjs/core/DirectiveChainTracker.js +121 -0
  63. package/dist/cjs/core/DirectiveChainTracker.js.map +1 -0
  64. package/dist/cjs/core/Flow.d.ts +186 -0
  65. package/dist/cjs/core/Flow.d.ts.map +1 -0
  66. package/dist/cjs/core/Flow.js +550 -0
  67. package/dist/cjs/core/Flow.js.map +1 -0
  68. package/dist/cjs/core/FlowRouter.d.ts +182 -0
  69. package/dist/cjs/core/FlowRouter.d.ts.map +1 -0
  70. package/dist/cjs/core/{RoutingEngine.js → FlowRouter.js} +323 -306
  71. package/dist/cjs/core/FlowRouter.js.map +1 -0
  72. package/dist/cjs/core/PersistenceManager.d.ts +2 -2
  73. package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
  74. package/dist/cjs/core/PersistenceManager.js +7 -7
  75. package/dist/cjs/core/PersistenceManager.js.map +1 -1
  76. package/dist/cjs/core/PromptComposer.d.ts +21 -8
  77. package/dist/cjs/core/PromptComposer.d.ts.map +1 -1
  78. package/dist/cjs/core/PromptComposer.js +182 -105
  79. package/dist/cjs/core/PromptComposer.js.map +1 -1
  80. package/dist/cjs/core/PromptSectionCache.d.ts +1 -1
  81. package/dist/cjs/core/PromptSectionCache.js +1 -1
  82. package/dist/cjs/core/ResponseEngine.d.ts +18 -8
  83. package/dist/cjs/core/ResponseEngine.d.ts.map +1 -1
  84. package/dist/cjs/core/ResponseEngine.js +38 -36
  85. package/dist/cjs/core/ResponseEngine.js.map +1 -1
  86. package/dist/cjs/core/ResponseModal.d.ts +73 -56
  87. package/dist/cjs/core/ResponseModal.d.ts.map +1 -1
  88. package/dist/cjs/core/ResponseModal.js +1191 -1014
  89. package/dist/cjs/core/ResponseModal.js.map +1 -1
  90. package/dist/cjs/core/ResponsePipeline.d.ts +124 -26
  91. package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -1
  92. package/dist/cjs/core/ResponsePipeline.js +509 -136
  93. package/dist/cjs/core/ResponsePipeline.js.map +1 -1
  94. package/dist/cjs/core/SignalEvaluator.d.ts +86 -0
  95. package/dist/cjs/core/SignalEvaluator.d.ts.map +1 -0
  96. package/dist/cjs/core/SignalEvaluator.js +333 -0
  97. package/dist/cjs/core/SignalEvaluator.js.map +1 -0
  98. package/dist/cjs/core/SignalProcessor.d.ts +152 -0
  99. package/dist/cjs/core/SignalProcessor.d.ts.map +1 -0
  100. package/dist/cjs/core/SignalProcessor.js +562 -0
  101. package/dist/cjs/core/SignalProcessor.js.map +1 -0
  102. package/dist/cjs/core/Step.d.ts +43 -32
  103. package/dist/cjs/core/Step.d.ts.map +1 -1
  104. package/dist/cjs/core/Step.js +221 -126
  105. package/dist/cjs/core/Step.js.map +1 -1
  106. package/dist/cjs/core/StreamingToolExecutor.d.ts +2 -2
  107. package/dist/cjs/core/StreamingToolExecutor.d.ts.map +1 -1
  108. package/dist/cjs/core/StreamingToolExecutor.js.map +1 -1
  109. package/dist/cjs/core/ToolManager.d.ts +44 -13
  110. package/dist/cjs/core/ToolManager.d.ts.map +1 -1
  111. package/dist/cjs/core/ToolManager.js +174 -91
  112. package/dist/cjs/core/ToolManager.js.map +1 -1
  113. package/dist/cjs/core/createAgent.d.ts +35 -0
  114. package/dist/cjs/core/createAgent.d.ts.map +1 -0
  115. package/dist/cjs/core/createAgent.js +39 -0
  116. package/dist/cjs/core/createAgent.js.map +1 -0
  117. package/dist/cjs/core/flow-namespace.d.ts +49 -0
  118. package/dist/cjs/core/flow-namespace.d.ts.map +1 -0
  119. package/dist/cjs/core/flow-namespace.js +171 -0
  120. package/dist/cjs/core/flow-namespace.js.map +1 -0
  121. package/dist/cjs/index.d.ts +11 -14
  122. package/dist/cjs/index.d.ts.map +1 -1
  123. package/dist/cjs/index.js +18 -22
  124. package/dist/cjs/index.js.map +1 -1
  125. package/dist/cjs/types/agent.d.ts +183 -54
  126. package/dist/cjs/types/agent.d.ts.map +1 -1
  127. package/dist/cjs/types/agent.js +0 -6
  128. package/dist/cjs/types/agent.js.map +1 -1
  129. package/dist/cjs/types/ai.d.ts +3 -3
  130. package/dist/cjs/types/ai.d.ts.map +1 -1
  131. package/dist/cjs/types/errors.d.ts +15 -0
  132. package/dist/cjs/types/errors.d.ts.map +1 -0
  133. package/dist/cjs/types/errors.js +22 -0
  134. package/dist/cjs/types/errors.js.map +1 -0
  135. package/dist/cjs/types/flow.d.ts +513 -0
  136. package/dist/cjs/types/flow.d.ts.map +1 -0
  137. package/dist/cjs/types/{route.js → flow.js} +2 -2
  138. package/dist/cjs/types/flow.js.map +1 -0
  139. package/dist/cjs/types/index.d.ts +7 -6
  140. package/dist/cjs/types/index.d.ts.map +1 -1
  141. package/dist/cjs/types/index.js +6 -2
  142. package/dist/cjs/types/index.js.map +1 -1
  143. package/dist/cjs/types/persistence.d.ts +11 -7
  144. package/dist/cjs/types/persistence.d.ts.map +1 -1
  145. package/dist/cjs/types/routing.d.ts +1 -1
  146. package/dist/cjs/types/routing.d.ts.map +1 -1
  147. package/dist/cjs/types/session.d.ts +24 -23
  148. package/dist/cjs/types/session.d.ts.map +1 -1
  149. package/dist/cjs/types/signals.d.ts +248 -0
  150. package/dist/cjs/types/signals.d.ts.map +1 -0
  151. package/dist/cjs/types/signals.js +11 -0
  152. package/dist/cjs/types/signals.js.map +1 -0
  153. package/dist/cjs/types/template.d.ts +2 -8
  154. package/dist/cjs/types/template.d.ts.map +1 -1
  155. package/dist/cjs/types/tool.d.ts +36 -29
  156. package/dist/cjs/types/tool.d.ts.map +1 -1
  157. package/dist/cjs/types/tool.js +1 -1
  158. package/dist/cjs/types/tool.js.map +1 -1
  159. package/dist/cjs/utils/condition.d.ts +7 -1
  160. package/dist/cjs/utils/condition.d.ts.map +1 -1
  161. package/dist/cjs/utils/condition.js.map +1 -1
  162. package/dist/cjs/utils/id.d.ts +13 -5
  163. package/dist/cjs/utils/id.d.ts.map +1 -1
  164. package/dist/cjs/utils/id.js +24 -10
  165. package/dist/cjs/utils/id.js.map +1 -1
  166. package/dist/cjs/utils/index.d.ts +2 -2
  167. package/dist/cjs/utils/index.d.ts.map +1 -1
  168. package/dist/cjs/utils/index.js +7 -3
  169. package/dist/cjs/utils/index.js.map +1 -1
  170. package/dist/cjs/utils/session.d.ts +44 -5
  171. package/dist/cjs/utils/session.d.ts.map +1 -1
  172. package/dist/cjs/utils/session.js +197 -38
  173. package/dist/cjs/utils/session.js.map +1 -1
  174. package/dist/constants/index.d.ts +0 -9
  175. package/dist/constants/index.d.ts.map +1 -1
  176. package/dist/constants/index.js +3 -9
  177. package/dist/constants/index.js.map +1 -1
  178. package/dist/core/Agent.d.ts +119 -153
  179. package/dist/core/Agent.d.ts.map +1 -1
  180. package/dist/core/Agent.js +472 -325
  181. package/dist/core/Agent.js.map +1 -1
  182. package/dist/core/AutoChainExecutor.d.ts +107 -0
  183. package/dist/core/AutoChainExecutor.d.ts.map +1 -0
  184. package/dist/core/AutoChainExecutor.js +293 -0
  185. package/dist/core/AutoChainExecutor.js.map +1 -0
  186. package/dist/core/BranchEvaluator.d.ts +54 -0
  187. package/dist/core/BranchEvaluator.d.ts.map +1 -0
  188. package/dist/core/BranchEvaluator.js +126 -0
  189. package/dist/core/BranchEvaluator.js.map +1 -0
  190. package/dist/core/DirectiveBus.d.ts +88 -0
  191. package/dist/core/DirectiveBus.d.ts.map +1 -0
  192. package/dist/core/DirectiveBus.js +192 -0
  193. package/dist/core/DirectiveBus.js.map +1 -0
  194. package/dist/core/DirectiveChainTracker.d.ts +49 -0
  195. package/dist/core/DirectiveChainTracker.d.ts.map +1 -0
  196. package/dist/core/DirectiveChainTracker.js +117 -0
  197. package/dist/core/DirectiveChainTracker.js.map +1 -0
  198. package/dist/core/Flow.d.ts +186 -0
  199. package/dist/core/Flow.d.ts.map +1 -0
  200. package/dist/core/Flow.js +546 -0
  201. package/dist/core/Flow.js.map +1 -0
  202. package/dist/core/FlowRouter.d.ts +182 -0
  203. package/dist/core/FlowRouter.d.ts.map +1 -0
  204. package/dist/core/{RoutingEngine.js → FlowRouter.js} +322 -305
  205. package/dist/core/FlowRouter.js.map +1 -0
  206. package/dist/core/PersistenceManager.d.ts +2 -2
  207. package/dist/core/PersistenceManager.d.ts.map +1 -1
  208. package/dist/core/PersistenceManager.js +7 -7
  209. package/dist/core/PersistenceManager.js.map +1 -1
  210. package/dist/core/PromptComposer.d.ts +21 -8
  211. package/dist/core/PromptComposer.d.ts.map +1 -1
  212. package/dist/core/PromptComposer.js +183 -106
  213. package/dist/core/PromptComposer.js.map +1 -1
  214. package/dist/core/PromptSectionCache.d.ts +1 -1
  215. package/dist/core/PromptSectionCache.js +1 -1
  216. package/dist/core/ResponseEngine.d.ts +18 -8
  217. package/dist/core/ResponseEngine.d.ts.map +1 -1
  218. package/dist/core/ResponseEngine.js +38 -36
  219. package/dist/core/ResponseEngine.js.map +1 -1
  220. package/dist/core/ResponseModal.d.ts +73 -56
  221. package/dist/core/ResponseModal.d.ts.map +1 -1
  222. package/dist/core/ResponseModal.js +1193 -1016
  223. package/dist/core/ResponseModal.js.map +1 -1
  224. package/dist/core/ResponsePipeline.d.ts +124 -26
  225. package/dist/core/ResponsePipeline.d.ts.map +1 -1
  226. package/dist/core/ResponsePipeline.js +509 -137
  227. package/dist/core/ResponsePipeline.js.map +1 -1
  228. package/dist/core/SignalEvaluator.d.ts +86 -0
  229. package/dist/core/SignalEvaluator.d.ts.map +1 -0
  230. package/dist/core/SignalEvaluator.js +326 -0
  231. package/dist/core/SignalEvaluator.js.map +1 -0
  232. package/dist/core/SignalProcessor.d.ts +152 -0
  233. package/dist/core/SignalProcessor.d.ts.map +1 -0
  234. package/dist/core/SignalProcessor.js +555 -0
  235. package/dist/core/SignalProcessor.js.map +1 -0
  236. package/dist/core/Step.d.ts +43 -32
  237. package/dist/core/Step.d.ts.map +1 -1
  238. package/dist/core/Step.js +220 -126
  239. package/dist/core/Step.js.map +1 -1
  240. package/dist/core/StreamingToolExecutor.d.ts +2 -2
  241. package/dist/core/StreamingToolExecutor.d.ts.map +1 -1
  242. package/dist/core/StreamingToolExecutor.js.map +1 -1
  243. package/dist/core/ToolManager.d.ts +44 -13
  244. package/dist/core/ToolManager.d.ts.map +1 -1
  245. package/dist/core/ToolManager.js +174 -91
  246. package/dist/core/ToolManager.js.map +1 -1
  247. package/dist/core/createAgent.d.ts +35 -0
  248. package/dist/core/createAgent.d.ts.map +1 -0
  249. package/dist/core/createAgent.js +36 -0
  250. package/dist/core/createAgent.js.map +1 -0
  251. package/dist/core/flow-namespace.d.ts +49 -0
  252. package/dist/core/flow-namespace.d.ts.map +1 -0
  253. package/dist/core/flow-namespace.js +168 -0
  254. package/dist/core/flow-namespace.js.map +1 -0
  255. package/dist/index.d.ts +11 -14
  256. package/dist/index.d.ts.map +1 -1
  257. package/dist/index.js +9 -12
  258. package/dist/index.js.map +1 -1
  259. package/dist/types/agent.d.ts +183 -54
  260. package/dist/types/agent.d.ts.map +1 -1
  261. package/dist/types/agent.js +0 -6
  262. package/dist/types/agent.js.map +1 -1
  263. package/dist/types/ai.d.ts +3 -3
  264. package/dist/types/ai.d.ts.map +1 -1
  265. package/dist/types/errors.d.ts +15 -0
  266. package/dist/types/errors.d.ts.map +1 -0
  267. package/dist/types/errors.js +18 -0
  268. package/dist/types/errors.js.map +1 -0
  269. package/dist/types/flow.d.ts +513 -0
  270. package/dist/types/flow.d.ts.map +1 -0
  271. package/dist/types/flow.js +5 -0
  272. package/dist/types/flow.js.map +1 -0
  273. package/dist/types/index.d.ts +7 -6
  274. package/dist/types/index.d.ts.map +1 -1
  275. package/dist/types/index.js +4 -1
  276. package/dist/types/index.js.map +1 -1
  277. package/dist/types/persistence.d.ts +11 -7
  278. package/dist/types/persistence.d.ts.map +1 -1
  279. package/dist/types/routing.d.ts +1 -1
  280. package/dist/types/routing.d.ts.map +1 -1
  281. package/dist/types/session.d.ts +24 -23
  282. package/dist/types/session.d.ts.map +1 -1
  283. package/dist/types/signals.d.ts +248 -0
  284. package/dist/types/signals.d.ts.map +1 -0
  285. package/dist/types/signals.js +10 -0
  286. package/dist/types/signals.js.map +1 -0
  287. package/dist/types/template.d.ts +2 -8
  288. package/dist/types/template.d.ts.map +1 -1
  289. package/dist/types/tool.d.ts +36 -29
  290. package/dist/types/tool.d.ts.map +1 -1
  291. package/dist/types/tool.js +1 -1
  292. package/dist/types/tool.js.map +1 -1
  293. package/dist/utils/condition.d.ts +7 -1
  294. package/dist/utils/condition.d.ts.map +1 -1
  295. package/dist/utils/condition.js.map +1 -1
  296. package/dist/utils/id.d.ts +13 -5
  297. package/dist/utils/id.d.ts.map +1 -1
  298. package/dist/utils/id.js +22 -9
  299. package/dist/utils/id.js.map +1 -1
  300. package/dist/utils/index.d.ts +2 -2
  301. package/dist/utils/index.d.ts.map +1 -1
  302. package/dist/utils/index.js +2 -2
  303. package/dist/utils/index.js.map +1 -1
  304. package/dist/utils/session.d.ts +44 -5
  305. package/dist/utils/session.d.ts.map +1 -1
  306. package/dist/utils/session.js +193 -37
  307. package/dist/utils/session.js.map +1 -1
  308. package/docs/README.md +15 -202
  309. package/docs/concepts/architecture.md +281 -0
  310. package/docs/concepts/directives.md +400 -0
  311. package/docs/concepts/pipeline.md +399 -0
  312. package/docs/guides/branching.md +263 -0
  313. package/docs/guides/compaction.md +163 -0
  314. package/docs/guides/conditions.md +167 -0
  315. package/docs/guides/error-handling.md +176 -0
  316. package/docs/guides/flow-control.md +409 -0
  317. package/docs/guides/instructions.md +210 -0
  318. package/docs/guides/persistence.md +182 -0
  319. package/docs/guides/streaming.md +137 -0
  320. package/docs/migration/README.md +15 -0
  321. package/docs/migration/route-to-flow.md +560 -0
  322. package/docs/migration/v1-to-v2.md +909 -0
  323. package/docs/reference/adapters.md +481 -0
  324. package/docs/reference/branches.md +241 -0
  325. package/docs/reference/create-agent.md +186 -0
  326. package/docs/reference/directive.md +243 -0
  327. package/docs/reference/errors.md +122 -0
  328. package/docs/reference/flow.md +238 -0
  329. package/docs/reference/instruction.md +177 -0
  330. package/docs/reference/pre-directive.md +131 -0
  331. package/docs/reference/providers.md +227 -0
  332. package/docs/reference/signals.md +356 -0
  333. package/docs/reference/step.md +339 -0
  334. package/docs/reference/tool.md +269 -0
  335. package/docs/start/01-install.md +81 -0
  336. package/docs/start/02-first-agent.md +196 -0
  337. package/docs/start/03-collect-data.md +222 -0
  338. package/docs/start/04-add-tools.md +276 -0
  339. package/docs/start/05-go-to-production.md +216 -0
  340. package/examples/01-quickstart.ts +20 -0
  341. package/examples/02-data-extraction.ts +90 -0
  342. package/examples/03-tools.ts +136 -0
  343. package/examples/04-instructions.ts +100 -0
  344. package/examples/05-branching.ts +140 -0
  345. package/examples/06-flow-control.ts +103 -0
  346. package/examples/07-streaming.ts +69 -0
  347. package/examples/08-persistence.ts +98 -0
  348. package/examples/09-signals.ts +144 -0
  349. package/examples/tsconfig.json +30 -0
  350. package/package.json +2 -1
  351. package/src/adapters/MemoryAdapter.ts +3 -3
  352. package/src/adapters/MongoAdapter.ts +3 -3
  353. package/src/adapters/OpenSearchAdapter.ts +10 -8
  354. package/src/adapters/PostgreSQLAdapter.ts +26 -10
  355. package/src/adapters/PrismaAdapter.ts +6 -6
  356. package/src/adapters/RedisAdapter.ts +3 -3
  357. package/src/adapters/SQLiteAdapter.ts +31 -12
  358. package/src/constants/index.ts +2 -10
  359. package/src/core/Agent.ts +585 -374
  360. package/src/core/AutoChainExecutor.ts +440 -0
  361. package/src/core/BranchEvaluator.ts +167 -0
  362. package/src/core/DirectiveBus.ts +248 -0
  363. package/src/core/DirectiveChainTracker.ts +144 -0
  364. package/src/core/Flow.ts +666 -0
  365. package/src/core/{RoutingEngine.ts → FlowRouter.ts} +385 -365
  366. package/src/core/PersistenceManager.ts +8 -8
  367. package/src/core/PromptComposer.ts +209 -140
  368. package/src/core/PromptSectionCache.ts +1 -1
  369. package/src/core/ResponseEngine.ts +61 -46
  370. package/src/core/ResponseModal.ts +1453 -1240
  371. package/src/core/ResponsePipeline.ts +655 -175
  372. package/src/core/SignalEvaluator.ts +420 -0
  373. package/src/core/SignalProcessor.ts +723 -0
  374. package/src/core/Step.ts +279 -176
  375. package/src/core/StreamingToolExecutor.ts +4 -4
  376. package/src/core/ToolManager.ts +200 -97
  377. package/src/core/createAgent.ts +40 -0
  378. package/src/core/flow-namespace.ts +219 -0
  379. package/src/index.ts +42 -36
  380. package/src/types/agent.ts +182 -53
  381. package/src/types/ai.ts +3 -3
  382. package/src/types/errors.ts +18 -0
  383. package/src/types/flow.ts +590 -0
  384. package/src/types/index.ts +43 -16
  385. package/src/types/persistence.ts +12 -8
  386. package/src/types/routing.ts +1 -1
  387. package/src/types/session.ts +26 -23
  388. package/src/types/signals.ts +321 -0
  389. package/src/types/template.ts +3 -11
  390. package/src/types/tool.ts +50 -42
  391. package/src/utils/condition.ts +13 -4
  392. package/src/utils/id.ts +27 -9
  393. package/src/utils/index.ts +6 -2
  394. package/src/utils/session.ts +238 -42
  395. package/dist/cjs/core/BatchExecutor.d.ts +0 -359
  396. package/dist/cjs/core/BatchExecutor.d.ts.map +0 -1
  397. package/dist/cjs/core/BatchExecutor.js +0 -861
  398. package/dist/cjs/core/BatchExecutor.js.map +0 -1
  399. package/dist/cjs/core/BatchPromptBuilder.d.ts +0 -89
  400. package/dist/cjs/core/BatchPromptBuilder.d.ts.map +0 -1
  401. package/dist/cjs/core/BatchPromptBuilder.js +0 -223
  402. package/dist/cjs/core/BatchPromptBuilder.js.map +0 -1
  403. package/dist/cjs/core/Route.d.ts +0 -180
  404. package/dist/cjs/core/Route.d.ts.map +0 -1
  405. package/dist/cjs/core/Route.js +0 -542
  406. package/dist/cjs/core/Route.js.map +0 -1
  407. package/dist/cjs/core/RoutingEngine.d.ts +0 -185
  408. package/dist/cjs/core/RoutingEngine.d.ts.map +0 -1
  409. package/dist/cjs/core/RoutingEngine.js.map +0 -1
  410. package/dist/cjs/types/route.d.ts +0 -336
  411. package/dist/cjs/types/route.d.ts.map +0 -1
  412. package/dist/cjs/types/route.js.map +0 -1
  413. package/dist/core/BatchExecutor.d.ts +0 -359
  414. package/dist/core/BatchExecutor.d.ts.map +0 -1
  415. package/dist/core/BatchExecutor.js +0 -856
  416. package/dist/core/BatchExecutor.js.map +0 -1
  417. package/dist/core/BatchPromptBuilder.d.ts +0 -89
  418. package/dist/core/BatchPromptBuilder.d.ts.map +0 -1
  419. package/dist/core/BatchPromptBuilder.js +0 -219
  420. package/dist/core/BatchPromptBuilder.js.map +0 -1
  421. package/dist/core/Route.d.ts +0 -180
  422. package/dist/core/Route.d.ts.map +0 -1
  423. package/dist/core/Route.js +0 -538
  424. package/dist/core/Route.js.map +0 -1
  425. package/dist/core/RoutingEngine.d.ts +0 -185
  426. package/dist/core/RoutingEngine.d.ts.map +0 -1
  427. package/dist/core/RoutingEngine.js.map +0 -1
  428. package/dist/types/route.d.ts +0 -336
  429. package/dist/types/route.d.ts.map +0 -1
  430. package/dist/types/route.js +0 -5
  431. package/dist/types/route.js.map +0 -1
  432. package/docs/CONTRIBUTING.md +0 -521
  433. package/docs/api/README.md +0 -3299
  434. package/docs/api/overview.md +0 -1410
  435. package/docs/architecture/data-extraction-flow.md +0 -360
  436. package/docs/architecture/multi-step-execution.md +0 -277
  437. package/docs/core/agent/README.md +0 -938
  438. package/docs/core/agent/context-management.md +0 -796
  439. package/docs/core/agent/rules-and-prohibitions.md +0 -113
  440. package/docs/core/agent/session-management.md +0 -693
  441. package/docs/core/ai-integration/prompt-composition.md +0 -355
  442. package/docs/core/ai-integration/providers.md +0 -515
  443. package/docs/core/ai-integration/response-processing.md +0 -433
  444. package/docs/core/conversation-flows/data-collection.md +0 -772
  445. package/docs/core/conversation-flows/route-dsl.md +0 -509
  446. package/docs/core/conversation-flows/routes.md +0 -249
  447. package/docs/core/conversation-flows/step-transitions.md +0 -731
  448. package/docs/core/conversation-flows/steps.md +0 -268
  449. package/docs/core/error-handling.md +0 -830
  450. package/docs/core/persistence/adapters.md +0 -255
  451. package/docs/core/persistence/session-storage.md +0 -656
  452. package/docs/core/routing/intelligent-routing.md +0 -470
  453. package/docs/core/tools/enhanced-tool.md +0 -186
  454. package/docs/core/tools/streaming-execution.md +0 -161
  455. package/docs/core/tools/tool-definition.md +0 -970
  456. package/docs/core/tools/tool-scoping.md +0 -819
  457. package/docs/guides/advanced-patterns/publishing.md +0 -186
  458. package/docs/guides/context-compaction.md +0 -96
  459. package/docs/guides/error-handling-patterns.md +0 -578
  460. package/docs/guides/getting-started/README.md +0 -795
  461. package/docs/guides/migration/README.md +0 -101
  462. package/docs/guides/migration/flexible-routing-conditions.md +0 -375
  463. package/docs/guides/migration/multi-step-execution.md +0 -393
  464. package/docs/guides/migration/response-modal-refactor.md +0 -518
  465. package/docs/guides/prompt-optimization.md +0 -164
  466. package/examples/advanced-patterns/context-compaction.ts +0 -223
  467. package/examples/advanced-patterns/knowledge-based-agent.ts +0 -735
  468. package/examples/advanced-patterns/persistent-onboarding.ts +0 -728
  469. package/examples/advanced-patterns/route-lifecycle-hooks.ts +0 -556
  470. package/examples/advanced-patterns/streaming-responses.ts +0 -656
  471. package/examples/ai-providers/anthropic-integration.ts +0 -388
  472. package/examples/ai-providers/openai-integration.ts +0 -228
  473. package/examples/condition-patterns/function-only-conditions.ts +0 -365
  474. package/examples/condition-patterns/mixed-array-conditions.ts +0 -477
  475. package/examples/condition-patterns/route-skipif-patterns.ts +0 -468
  476. package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
  477. package/examples/condition-patterns/string-only-conditions.ts +0 -296
  478. package/examples/conversation-flows/completion-transitions.ts +0 -318
  479. package/examples/core-concepts/basic-agent.ts +0 -503
  480. package/examples/core-concepts/modern-streaming-api.ts +0 -309
  481. package/examples/core-concepts/schema-driven-extraction.ts +0 -332
  482. package/examples/core-concepts/session-management.ts +0 -494
  483. package/examples/integrations/database-integration.ts +0 -631
  484. package/examples/integrations/healthcare-integration.ts +0 -595
  485. package/examples/integrations/search-integration.ts +0 -530
  486. package/examples/integrations/server-session-management.ts +0 -307
  487. package/examples/persistence/custom-adapter.ts +0 -526
  488. package/examples/persistence/database-persistence.ts +0 -583
  489. package/examples/persistence/memory-sessions.ts +0 -495
  490. package/examples/persistence/prisma-schema.example.prisma +0 -74
  491. package/examples/persistence/redis-persistence.ts +0 -488
  492. package/examples/tools/basic-tools.ts +0 -765
  493. package/examples/tools/data-enrichment-tools.ts +0 -593
  494. package/examples/tools/enhanced-tool-metadata.ts +0 -268
  495. package/examples/tools/streaming-tool-execution.ts +0 -283
  496. package/src/core/BatchExecutor.ts +0 -1187
  497. package/src/core/BatchPromptBuilder.ts +0 -299
  498. package/src/core/Route.ts +0 -678
  499. package/src/types/route.ts +0 -392
@@ -1,12 +1,15 @@
1
1
  /**
2
2
  * Core Agent implementation
3
3
  */
4
- import { CompositionMode } from "../types";
5
- import { mergeCollected, logger, LoggerLevel, render, createTemplateContext, createConditionEvaluator, } from "../utils";
6
- import { Route } from "./Route";
4
+ import { NotImplementedError } from "../types/errors";
5
+ import { SignalProcessor } from "./SignalProcessor";
6
+ import { SignalEvaluator } from "./SignalEvaluator";
7
+ import { mergeCollected, enterFlow, enterStep, completeCurrentFlow, logger, LoggerLevel, generateSignalId, } from "../utils";
8
+ import { Flow } from "./Flow";
9
+ import { FlowConfigurationError as StepFlowConfigurationError } from "./Step";
7
10
  import { PersistenceManager } from "./PersistenceManager";
8
11
  import { SessionManager } from "./SessionManager";
9
- import { RoutingEngine } from "./RoutingEngine";
12
+ import { FlowRouter } from "./FlowRouter";
10
13
  import { PromptSectionCache } from "./PromptSectionCache";
11
14
  import { ResponseModal } from "./ResponseModal";
12
15
  import { ToolManager } from "./ToolManager";
@@ -22,14 +25,14 @@ class DataValidationError extends Error {
22
25
  }
23
26
  }
24
27
  /**
25
- * Error thrown when route configuration is invalid
28
+ * Error thrown when flow configuration is invalid
26
29
  */
27
- class RouteConfigurationError extends Error {
28
- constructor(routeTitle, invalidFields, message) {
29
- super(message || `Route configuration error in '${routeTitle}'`);
30
- this.routeTitle = routeTitle;
30
+ class FlowConfigurationError extends Error {
31
+ constructor(flowTitle, invalidFields, message) {
32
+ super(message || `Flow configuration error in '${flowTitle}'`);
33
+ this.flowTitle = flowTitle;
31
34
  this.invalidFields = invalidFields;
32
- this.name = "RouteConfigurationError";
35
+ this.name = "FlowConfigurationError";
33
36
  }
34
37
  }
35
38
  /**
@@ -40,13 +43,75 @@ export class Agent {
40
43
  constructor(options) {
41
44
  this.options = options;
42
45
  this._terms = [];
43
- this._guidelines = [];
46
+ this._instructions = [];
44
47
  this._tools = [];
45
- this._routes = [];
46
- this._rules = [];
47
- this._prohibitions = [];
48
+ this._flows = [];
48
49
  this._knowledgeBase = {};
49
50
  this._collectedData = {};
51
+ this.maxAutoStepsPerTurn = options.maxAutoStepsPerTurn ?? 10;
52
+ this.maxDirectiveChain = options.maxDirectiveChain ?? 10;
53
+ // Validate routerMode reservation — only 'ai' is supported in v2.0
54
+ if (options.routerMode !== undefined && options.routerMode !== 'ai') {
55
+ throw new NotImplementedError(`[NotImplementedError] routerMode "${String(options.routerMode)}" is not implemented: only "ai" is supported in v2.0. ` +
56
+ `Set routerMode to "ai" or omit the option.`);
57
+ }
58
+ // ─── Signal construction-time validation (Requirements 1.4, 1.5, 1.6, 1.9, 2.3) ───
59
+ const rawSignals = options.signals ?? [];
60
+ // Auto-generate stable ids for entries without `id`
61
+ for (let i = 0; i < rawSignals.length; i++) {
62
+ if (!rawSignals[i].id) {
63
+ rawSignals[i] = {
64
+ ...rawSignals[i],
65
+ id: generateSignalId(rawSignals[i].title, rawSignals[i].description, i),
66
+ };
67
+ }
68
+ }
69
+ // Validate unique ids (Requirement 1.4)
70
+ const idCounts = new Map();
71
+ for (const signal of rawSignals) {
72
+ const id = signal.id;
73
+ idCounts.set(id, (idCounts.get(id) ?? 0) + 1);
74
+ }
75
+ const duplicateIds = [...idCounts.entries()]
76
+ .filter(([, count]) => count > 1)
77
+ .map(([id]) => id);
78
+ if (duplicateIds.length > 0) {
79
+ throw new StepFlowConfigurationError(`[FlowConfigurationError] Duplicate signal ids: ${duplicateIds.join(', ')}. ` +
80
+ `Each signal must have a unique id.`);
81
+ }
82
+ // Validate signalBatchSize (positive integer when set)
83
+ if (options.signalBatchSize !== undefined) {
84
+ if (!Number.isInteger(options.signalBatchSize) ||
85
+ options.signalBatchSize <= 0) {
86
+ throw new StepFlowConfigurationError(`[FlowConfigurationError] signalBatchSize must be a positive integer, got: ${options.signalBatchSize}.`);
87
+ }
88
+ }
89
+ // Validate each signal's configuration
90
+ for (const signal of rawSignals) {
91
+ // Requirement 1.5: cooldown without cooldownMs → debug warning, treat as 'always'
92
+ if (signal.behavior === 'cooldown' && signal.cooldownMs == null) {
93
+ logger.debug(`[Agent] Signal "${signal.id}" has behavior 'cooldown' but no cooldownMs. Treating as 'always'.`);
94
+ signal.behavior = 'always';
95
+ }
96
+ // Requirement 1.9: validate extract schema is a JSON Schema object
97
+ if (signal.extract !== undefined) {
98
+ if (signal.extract === null ||
99
+ typeof signal.extract !== 'object' ||
100
+ Array.isArray(signal.extract)) {
101
+ throw new StepFlowConfigurationError(`[FlowConfigurationError] Signal "${signal.id}" has an invalid extract schema. ` +
102
+ `Expected a JSON Schema object, got: ${typeof signal.extract}.`);
103
+ }
104
+ }
105
+ }
106
+ this._signals = rawSignals;
107
+ // Requirement 2.3: Only instantiate SignalProcessor when signals are present
108
+ if (rawSignals.length > 0) {
109
+ const evaluator = new SignalEvaluator(options.provider);
110
+ this.signalProcessor = new SignalProcessor(rawSignals, options.provider, evaluator, { batchSize: options.signalBatchSize ?? 10 });
111
+ }
112
+ else {
113
+ this.signalProcessor = undefined;
114
+ }
50
115
  // Set log level based on debug option
51
116
  if (options.debug) {
52
117
  logger.setLevel(LoggerLevel.DEBUG);
@@ -78,10 +143,10 @@ export class Agent {
78
143
  this._currentSession = options.session;
79
144
  // Initialize prompt section cache
80
145
  this._promptSectionCache = new PromptSectionCache(options.promptCache);
81
- // Initialize routing engine
82
- this._routingEngine = new RoutingEngine({
83
- routeSwitchMargin: options.routeSwitchMargin,
84
- onRouteSwitch: () => this.invalidateRouteSections(),
146
+ // Initialize flow router
147
+ this._routingEngine = new FlowRouter({
148
+ flowSwitchMargin: options.flowSwitchMargin,
149
+ onFlowSwitch: () => this.invalidateFlowSections(),
85
150
  promptSectionCache: this._promptSectionCache,
86
151
  });
87
152
  // Initialize ResponseModal for handling all response generation
@@ -119,28 +184,25 @@ export class Agent {
119
184
  this.createTerm(term);
120
185
  });
121
186
  }
122
- if (options.guidelines) {
123
- options.guidelines.forEach((guideline) => {
124
- this.createGuideline(guideline);
187
+ // Initialize instructions (new unified form)
188
+ if (options.instructions) {
189
+ options.instructions.forEach((instruction) => {
190
+ this.createInstruction(instruction);
125
191
  });
126
192
  }
127
193
  if (options.tools) {
128
194
  options.tools.forEach((tool) => {
129
- this.createTool(tool);
195
+ this.addTool(tool);
130
196
  });
131
197
  }
132
- // Initialize agent-level rules and prohibitions
133
- if (options.rules) {
134
- this._rules = [...options.rules];
135
- }
136
- if (options.prohibitions) {
137
- this._prohibitions = [...options.prohibitions];
138
- }
139
- if (options.routes) {
140
- options.routes.forEach((routeOptions) => {
141
- this.createRoute(routeOptions);
198
+ if (options.flows) {
199
+ options.flows.forEach((flowOptions) => {
200
+ this.createFlow(flowOptions);
142
201
  });
143
202
  }
203
+ // Validate deferred branch `then` string references against the flow registry.
204
+ // This catches strings that don't match a local step id AND don't match any flow id/title.
205
+ this.validateBranchReferences();
144
206
  // Initialize knowledge base
145
207
  if (options.knowledgeBase) {
146
208
  this._knowledgeBase = { ...options.knowledgeBase };
@@ -196,6 +258,66 @@ export class Agent {
196
258
  }
197
259
  logger.debug("[Agent] Schema validation passed");
198
260
  }
261
+ /**
262
+ * Walk every flow's steps and resolve deferred string `then` values in branches
263
+ * against the agent's flow registry. Strings that match neither a local step id
264
+ * nor any flow id/title throw FlowConfigurationError.
265
+ * @private
266
+ */
267
+ validateBranchReferences() {
268
+ for (const flow of this._flows) {
269
+ this.validateFlowBranchReferences(flow);
270
+ }
271
+ }
272
+ /**
273
+ * Validate branch `then` string references for a single flow against the agent's
274
+ * flow registry. Throws FlowConfigurationError for unresolved references.
275
+ * @private
276
+ */
277
+ validateFlowBranchReferences(flow) {
278
+ const steps = flow.getAllSteps();
279
+ const localStepIds = new Set(steps.map(s => s.id));
280
+ for (const step of steps) {
281
+ if (!step.branches)
282
+ continue;
283
+ for (const entry of step.branches) {
284
+ if (typeof entry.then !== 'string')
285
+ continue;
286
+ // Already matches a local step id — no deferred resolution needed
287
+ if (localStepIds.has(entry.then))
288
+ continue;
289
+ // Check against the agent's flow registry (id or title)
290
+ const matchesFlow = this._flows.some(f => f.id === entry.then || f.title === entry.then);
291
+ if (!matchesFlow) {
292
+ throw new StepFlowConfigurationError(`[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. ` +
293
+ `Fix the branch "then" value to reference a valid step id or flow id/title.`);
294
+ }
295
+ }
296
+ }
297
+ }
298
+ /**
299
+ * Validate that every step's `collect` fields in a flow reference valid keys
300
+ * from the agent-level schema. Throws FlowConfigurationError at construction
301
+ * time if any collect field is not a valid schema key.
302
+ *
303
+ * This enforces Requirement 14.5: generic inference is preserved AND every
304
+ * `collect` field reference is a valid key of the inferred TData.
305
+ * @private
306
+ */
307
+ validateFlowCollectFields(flow) {
308
+ const schemaKeys = Object.keys(this._schema.properties);
309
+ const schemaKeySet = new Set(schemaKeys);
310
+ const steps = flow.getAllSteps();
311
+ for (const step of steps) {
312
+ if (!step.collect || step.collect.length === 0)
313
+ continue;
314
+ const invalidFields = step.collect.filter(field => !schemaKeySet.has(String(field)));
315
+ if (invalidFields.length > 0) {
316
+ throw new StepFlowConfigurationError(`[FlowConfigurationError] Step "${step.id}" in flow "${flow.title}" references invalid collect fields: ${invalidFields.map(f => String(f)).join(', ')}. ` +
317
+ `Must be valid keys from agent schema. Available fields: ${schemaKeys.join(', ')}.`);
318
+ }
319
+ }
320
+ }
199
321
  /**
200
322
  * Validate data against the agent-level schema
201
323
  */
@@ -266,7 +388,7 @@ export class Agent {
266
388
  const validation = this.validateData(updates);
267
389
  if (!validation.valid) {
268
390
  const errorMessages = validation.errors.map(e => e.message).join(', ');
269
- throw new DataValidationError(validation.errors, `Data validation failed: ${errorMessages}`);
391
+ 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.`);
270
392
  }
271
393
  // Log warnings if any
272
394
  if (validation.warnings.length > 0) {
@@ -311,16 +433,16 @@ export class Agent {
311
433
  this.options.name = value;
312
434
  }
313
435
  /**
314
- * Get agent description
436
+ * Get agent persona
315
437
  */
316
- get description() {
317
- return this.options.description;
438
+ get persona() {
439
+ return this.options.persona;
318
440
  }
319
441
  /**
320
- * Set agent description
442
+ * Set agent persona
321
443
  */
322
- set description(value) {
323
- this.options.description = value;
444
+ set persona(value) {
445
+ this.options.persona = value;
324
446
  }
325
447
  /**
326
448
  * Get agent goal
@@ -334,30 +456,6 @@ export class Agent {
334
456
  set goal(value) {
335
457
  this.options.goal = value;
336
458
  }
337
- /**
338
- * Get agent identity
339
- */
340
- get identity() {
341
- return this.options.identity;
342
- }
343
- /**
344
- * Set agent identity
345
- */
346
- set identity(value) {
347
- this.options.identity = value;
348
- }
349
- /**
350
- * Get agent personality
351
- */
352
- get personality() {
353
- return this.options.personality;
354
- }
355
- /**
356
- * Set agent personality
357
- */
358
- set personality(value) {
359
- this.options.personality = value;
360
- }
361
459
  /**
362
460
  * Get whether debug mode is enabled
363
461
  */
@@ -384,29 +482,17 @@ export class Agent {
384
482
  this.options.provider = value;
385
483
  }
386
484
  /**
387
- * Get the composition mode
388
- */
389
- get compositionMode() {
390
- return this.options.compositionMode ?? CompositionMode.FLUID;
391
- }
392
- /**
393
- * Set the composition mode
394
- */
395
- set compositionMode(value) {
396
- this.options.compositionMode = value;
397
- }
398
- /**
399
- * Get the route switch margin
485
+ * Get the flow switch margin
400
486
  * @default 15
401
487
  */
402
- get routeSwitchMargin() {
403
- return this.options.routeSwitchMargin ?? 15;
488
+ get flowSwitchMargin() {
489
+ return this.options.flowSwitchMargin ?? 15;
404
490
  }
405
491
  /**
406
- * Set the route switch margin
492
+ * Set the flow switch margin
407
493
  */
408
- set routeSwitchMargin(value) {
409
- this.options.routeSwitchMargin = value;
494
+ set flowSwitchMargin(value) {
495
+ this.options.flowSwitchMargin = value;
410
496
  }
411
497
  /**
412
498
  * Get the prompt section cache instance
@@ -414,19 +500,6 @@ export class Agent {
414
500
  get promptSectionCache() {
415
501
  return this._promptSectionCache;
416
502
  }
417
- /**
418
- * Get the maximum steps per batch
419
- * @default 1
420
- */
421
- get maxStepsPerBatch() {
422
- return this.options.maxStepsPerBatch ?? 1;
423
- }
424
- /**
425
- * Set the maximum steps per batch
426
- */
427
- set maxStepsPerBatch(value) {
428
- this.options.maxStepsPerBatch = value;
429
- }
430
503
  /**
431
504
  * Get all terms
432
505
  */
@@ -434,10 +507,10 @@ export class Agent {
434
507
  return [...this._terms];
435
508
  }
436
509
  /**
437
- * Get all guidelines
510
+ * Get all instructions
438
511
  */
439
- get guidelines() {
440
- return [...this._guidelines];
512
+ get instructions() {
513
+ return [...this._instructions];
441
514
  }
442
515
  /**
443
516
  * Get all tools
@@ -446,34 +519,10 @@ export class Agent {
446
519
  return [...this._tools];
447
520
  }
448
521
  /**
449
- * Get all routes
450
- */
451
- get routes() {
452
- return [...this._routes];
453
- }
454
- /**
455
- * Get agent-level rules
456
- */
457
- get rules() {
458
- return [...this._rules];
459
- }
460
- /**
461
- * Set agent-level rules
462
- */
463
- set rules(value) {
464
- this._rules = [...value];
465
- }
466
- /**
467
- * Get agent-level prohibitions
522
+ * Get all flows
468
523
  */
469
- get prohibitions() {
470
- return [...this._prohibitions];
471
- }
472
- /**
473
- * Set agent-level prohibitions
474
- */
475
- set prohibitions(value) {
476
- this._prohibitions = [...value];
524
+ get flows() {
525
+ return [...this._flows];
477
526
  }
478
527
  /**
479
528
  * Get current schema
@@ -490,6 +539,13 @@ export class Agent {
490
539
  }
491
540
  this._schema = value;
492
541
  }
542
+ /**
543
+ * Get the configured signals.
544
+ */
545
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
546
+ get signals() {
547
+ return this._signals;
548
+ }
493
549
  /**
494
550
  * Get the agent's knowledge base
495
551
  */
@@ -516,98 +572,38 @@ export class Agent {
516
572
  this._currentSession = value;
517
573
  this._promptSectionCache.invalidateAll();
518
574
  }
519
- // ---------------------------------------------------------------------------
520
- // Deprecated method-based accessors (for backward compatibility)
521
- // ---------------------------------------------------------------------------
575
+ /**
576
+ * Get all flows
577
+ */
578
+ getFlows() {
579
+ return this.flows;
580
+ }
522
581
  /**
523
582
  * Get all terms
524
- * @deprecated Use `agent.terms` instead
525
583
  */
526
584
  getTerms() {
527
585
  return this.terms;
528
586
  }
529
587
  /**
530
588
  * Get all tools
531
- * @deprecated Use `agent.tools` instead
532
589
  */
533
590
  getTools() {
534
591
  return this.tools;
535
592
  }
536
593
  /**
537
- * Get all guidelines
538
- * @deprecated Use `agent.guidelines` instead
594
+ * Get all instructions
539
595
  */
540
- getGuidelines() {
541
- return this.guidelines;
596
+ getInstructions() {
597
+ return this.instructions;
542
598
  }
543
599
  /**
544
- * Get all routes
545
- * @deprecated Use `agent.routes` instead
600
+ * Invalidate flow-dependent prompt cache sections.
601
+ * Called automatically when the active flow changes.
546
602
  */
547
- getRoutes() {
548
- return this.routes;
549
- }
550
- /**
551
- * Get agent-level rules
552
- * @deprecated Use `agent.rules` instead
553
- */
554
- getRules() {
555
- return this.rules;
556
- }
557
- /**
558
- * Get agent-level prohibitions
559
- * @deprecated Use `agent.prohibitions` instead
560
- */
561
- getProhibitions() {
562
- return this.prohibitions;
563
- }
564
- /**
565
- * Get current schema
566
- * @deprecated Use `agent.schema` instead
567
- */
568
- getSchema() {
569
- return this.schema;
570
- }
571
- /**
572
- * Get the agent's knowledge base
573
- * @deprecated Use `agent.knowledgeBase` instead
574
- */
575
- getKnowledgeBase() {
576
- return this.knowledgeBase;
577
- }
578
- /**
579
- * Get the current session (if set)
580
- * @deprecated Use `agent.currentSession` instead
581
- */
582
- getCurrentSession() {
583
- return this.currentSession;
584
- }
585
- /**
586
- * Set the current session for convenience methods
587
- * @deprecated Use `agent.currentSession = session` instead
588
- * @param session - Session step to use for subsequent calls
589
- */
590
- setCurrentSession(session) {
591
- this.currentSession = session;
592
- this._promptSectionCache.invalidateAll();
593
- }
594
- /**
595
- * Clear the current session
596
- * @deprecated Use `agent.currentSession = undefined` instead
597
- */
598
- clearCurrentSession() {
599
- this._currentSession = undefined;
600
- this._promptSectionCache.invalidateAll();
601
- }
602
- /**
603
- * Invalidate route-dependent prompt cache sections.
604
- * Called automatically when the active route changes.
605
- */
606
- invalidateRouteSections() {
607
- this._promptSectionCache.invalidate('activeRoutes');
608
- this._promptSectionCache.invalidate('routeRules');
609
- this._promptSectionCache.invalidate('routeProhibitions');
610
- this._promptSectionCache.invalidate('routeKnowledgeBase');
603
+ invalidateFlowSections() {
604
+ this._promptSectionCache.invalidate('activeFlows');
605
+ this._promptSectionCache.invalidate('flowKnowledgeBase');
606
+ this._promptSectionCache.invalidate('instructionsFlow');
611
607
  }
612
608
  /**
613
609
  * Get the persistence manager (if configured)
@@ -631,28 +627,32 @@ export class Agent {
631
627
  // Core methods
632
628
  // ---------------------------------------------------------------------------
633
629
  /**
634
- * Create a new route (journey) using agent-level data type
630
+ * Create a new flow (journey) using agent-level data type
635
631
  */
636
- createRoute(options) {
632
+ createFlow(options) {
637
633
  // Validate that requiredFields exist in agent schema
638
634
  if (options.requiredFields && this._schema?.properties) {
639
635
  const invalidRequiredFields = options.requiredFields.filter(field => !(String(field) in this._schema.properties));
640
636
  if (invalidRequiredFields.length > 0) {
641
- throw new RouteConfigurationError(options.title, invalidRequiredFields.map(f => String(f)), `Invalid required fields in route '${options.title}': ${invalidRequiredFields.join(', ')}. ` +
642
- `Must be valid keys from agent schema. Available fields: ${Object.keys(this._schema.properties).join(', ')}.`);
637
+ throw new FlowConfigurationError(options.title, invalidRequiredFields.map(f => String(f)), `[FlowConfigurationError] Invalid required fields in flow "${options.title}": [${invalidRequiredFields.join(', ')}] are not declared in the agent schema. ` +
638
+ `Use valid schema keys. Available fields: ${Object.keys(this._schema.properties).join(', ')}.`);
643
639
  }
644
640
  }
645
641
  // Validate that optionalFields exist in agent schema
646
642
  if (options.optionalFields && this._schema?.properties) {
647
643
  const invalidOptionalFields = options.optionalFields.filter(field => !(String(field) in this._schema.properties));
648
644
  if (invalidOptionalFields.length > 0) {
649
- throw new RouteConfigurationError(options.title, invalidOptionalFields.map(f => String(f)), `Invalid optional fields in route '${options.title}': ${invalidOptionalFields.join(', ')}. ` +
650
- `Must be valid keys from agent schema. Available fields: ${Object.keys(this._schema.properties).join(', ')}.`);
645
+ throw new FlowConfigurationError(options.title, invalidOptionalFields.map(f => String(f)), `[FlowConfigurationError] Invalid optional fields in flow "${options.title}": [${invalidOptionalFields.join(', ')}] are not declared in the agent schema. ` +
646
+ `Use valid schema keys. Available fields: ${Object.keys(this._schema.properties).join(', ')}.`);
651
647
  }
652
648
  }
653
- const route = new Route(options, this);
654
- this._routes.push(route);
655
- return route;
649
+ const flow = new Flow(options, this);
650
+ // Validate that step collect fields reference valid schema keys
651
+ if (this._schema?.properties) {
652
+ this.validateFlowCollectFields(flow);
653
+ }
654
+ this._flows.push(flow);
655
+ return flow;
656
656
  }
657
657
  /**
658
658
  * Create a domain term for the glossary
@@ -662,20 +662,22 @@ export class Agent {
662
662
  return this;
663
663
  }
664
664
  /**
665
- * Create a behavioral guideline
665
+ * Create an instruction (unified behavioral primitive).
666
666
  */
667
- createGuideline(guideline) {
668
- const guidelineWithId = {
669
- ...guideline,
670
- id: guideline.id || `guideline_${this._guidelines.length}`,
671
- enabled: guideline.enabled !== false, // Default to true
667
+ createInstruction(instruction) {
668
+ const instructionWithId = {
669
+ ...instruction,
670
+ kind: instruction.kind || 'should',
671
+ id: instruction.id || `instruction_${this._instructions.length}`,
672
+ enabled: instruction.enabled !== false, // Default to true
672
673
  };
673
- this._guidelines.push(guidelineWithId);
674
+ this._instructions.push(instructionWithId);
675
+ this._promptSectionCache.invalidate('instructionsGlobal');
674
676
  return this;
675
677
  }
676
678
  /**
677
679
  * Add a tool to the agent using the unified Tool interface
678
- * Creates and adds the tool to agent scope in one operation (BREAKING CHANGE: replaces createTool)
680
+ * Creates and adds the tool to agent scope in one operation
679
681
  */
680
682
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
681
683
  addTool(tool) {
@@ -688,20 +690,6 @@ export class Agent {
688
690
  logger.debug(`[Agent] Added tool to agent scope: ${tool.id}`);
689
691
  return this;
690
692
  }
691
- /**
692
- * Register a tool at the agent level (legacy method for backward compatibility)
693
- * @deprecated Use addTool() with Tool interface instead
694
- */
695
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
696
- createTool(tool) {
697
- // Validate tool before adding
698
- if (!tool || !tool.id || !tool.handler) {
699
- throw new Error('Invalid tool: must have id and handler properties');
700
- }
701
- this._tools.push(tool);
702
- logger.debug(`[Agent] Created tool (legacy): ${tool.id}`);
703
- return this;
704
- }
705
693
  /**
706
694
  * Register multiple tools at the agent level
707
695
  */
@@ -719,7 +707,7 @@ export class Agent {
719
707
  }
720
708
  /**
721
709
  * Update the agent's context
722
- * Triggers both agent-level and route-specific onContextUpdate lifecycle hooks if configured
710
+ * Triggers both agent-level and flow-specific onContextUpdate lifecycle hooks if configured
723
711
  */
724
712
  async updateContext(updates) {
725
713
  const previousContext = this._context;
@@ -728,12 +716,12 @@ export class Agent {
728
716
  ...this._context,
729
717
  ...updates,
730
718
  };
731
- // Trigger route-specific lifecycle hook if configured and session has current route
732
- if (this._currentSession?.currentRoute) {
733
- const currentRoute = this._routes.find((r) => r.id === this._currentSession.currentRoute?.id);
734
- if (currentRoute?.hooks?.onContextUpdate &&
719
+ // Trigger flow-specific lifecycle hook if configured and session has current flow
720
+ if (this._currentSession?.currentFlow) {
721
+ const currentFlow = this._flows.find((r) => r.id === this._currentSession.currentFlow?.id);
722
+ if (currentFlow?.hooks?.onContextUpdate &&
735
723
  previousContext !== undefined) {
736
- await currentRoute.handleContextUpdate(this._context, previousContext);
724
+ await currentFlow.handleContextUpdate(this._context, previousContext);
737
725
  }
738
726
  }
739
727
  // Trigger agent-level lifecycle hook if configured
@@ -743,10 +731,11 @@ export class Agent {
743
731
  // Invalidate context-dependent prompt cache sections
744
732
  this._promptSectionCache.invalidate('agentMeta');
745
733
  this._promptSectionCache.invalidate('knowledgeBase');
734
+ this._promptSectionCache.invalidate('instructionsGlobal');
746
735
  }
747
736
  /**
748
737
  * Update collected data in session with lifecycle hook support
749
- * Triggers both agent-level and route-specific onDataUpdate lifecycle hooks if configured
738
+ * Triggers both agent-level and flow-specific onDataUpdate lifecycle hooks if configured
750
739
  * @internal
751
740
  */
752
741
  async updateData(session, dataUpdate) {
@@ -756,11 +745,11 @@ export class Agent {
756
745
  ...session.data,
757
746
  ...dataUpdate,
758
747
  };
759
- // Trigger route-specific lifecycle hook if configured and session has a current route
760
- if (session.currentRoute) {
761
- const currentRoute = this._routes.find((r) => r.id === session.currentRoute?.id);
762
- if (currentRoute?.hooks?.onDataUpdate) {
763
- newCollected = await currentRoute.handleDataUpdate(newCollected, previousCollected);
748
+ // Trigger flow-specific lifecycle hook if configured and session has a current flow
749
+ if (session.currentFlow) {
750
+ const currentFlow = this._flows.find((r) => r.id === session.currentFlow?.id);
751
+ if (currentFlow?.hooks?.onDataUpdate) {
752
+ newCollected = await currentFlow.handleDataUpdate(newCollected, previousCollected);
764
753
  }
765
754
  }
766
755
  // Trigger agent-level lifecycle hook if configured
@@ -805,10 +794,10 @@ export class Agent {
805
794
  return this.options;
806
795
  }
807
796
  /**
808
- * Get routing engine
797
+ * Get flow router
809
798
  * @internal Used by ResponseModal
810
799
  */
811
- getRoutingEngine() {
800
+ getFlowRouter() {
812
801
  return this._routingEngine;
813
802
  }
814
803
  /**
@@ -818,51 +807,11 @@ export class Agent {
818
807
  getUpdateDataMethod() {
819
808
  return this.updateData.bind(this);
820
809
  }
821
- /**
822
- * Evaluate and match active guidelines based on their conditions
823
- * Returns guidelines that should be active given the current context
824
- */
825
- async evaluateGuidelines(context, session, history) {
826
- const templateContext = { context, session, history, data: session?.data };
827
- const evaluator = createConditionEvaluator(templateContext);
828
- const matches = [];
829
- for (const guideline of this._guidelines) {
830
- // Skip disabled guidelines
831
- if (guideline.enabled === false) {
832
- continue;
833
- }
834
- if (guideline.condition) {
835
- const evaluation = await evaluator.evaluateCondition(guideline.condition, 'AND');
836
- // Include guideline if:
837
- // 1. No programmatic conditions (only strings) - always active
838
- // 2. Programmatic conditions evaluate to true
839
- if (!evaluation.hasProgrammaticConditions || evaluation.programmaticResult) {
840
- const rationale = evaluation.aiContextStrings.length > 0
841
- ? `Condition met: ${evaluation.aiContextStrings.join(" AND ")}`
842
- : evaluation.hasProgrammaticConditions
843
- ? "Programmatic condition evaluated to true"
844
- : "Always active (no conditions)";
845
- matches.push({
846
- guideline,
847
- rationale
848
- });
849
- }
850
- }
851
- else {
852
- // No condition means always active
853
- matches.push({
854
- guideline,
855
- rationale: "Always active (no conditions)"
856
- });
857
- }
858
- }
859
- return matches;
860
- }
861
810
  /**
862
811
  * Execute a prepare or finalize function/tool
863
812
  * @internal Used by ResponseModal
864
813
  */
865
- async executePrepareFinalize(prepareOrFinalize, context, data, route, step) {
814
+ async executePrepareFinalize(prepareOrFinalize, context, data, flow, step) {
866
815
  if (!prepareOrFinalize)
867
816
  return;
868
817
  if (typeof prepareOrFinalize === "function") {
@@ -874,7 +823,7 @@ export class Agent {
874
823
  let tool;
875
824
  if (typeof prepareOrFinalize === "string") {
876
825
  // Tool ID - use ToolManager to find it across all scopes
877
- tool = this.tool.find(prepareOrFinalize, undefined, step, route);
826
+ tool = this.tool.find(prepareOrFinalize, undefined, step, flow);
878
827
  }
879
828
  else {
880
829
  // Tool object - validate it has required properties
@@ -921,7 +870,6 @@ export class Agent {
921
870
  }
922
871
  /**
923
872
  * Get collected data from current session or agent-level collected data
924
- * @param routeId - Optional route ID to get data for (uses current route if not provided)
925
873
  * @returns The collected data from the current session or agent-level data
926
874
  */
927
875
  getData() {
@@ -929,64 +877,263 @@ export class Agent {
929
877
  this.syncSessionDataToCollectedData();
930
878
  // If we have a current session, use session data
931
879
  if (this._currentSession) {
932
- // With agent-level data, all routes share the same data structure
933
- // No need for route-specific data access
880
+ // With agent-level data, all flows share the same data structure
881
+ // No need for flow-specific data access
934
882
  return (this._currentSession.data) || {};
935
883
  }
936
884
  // Otherwise, return agent-level collected data
937
885
  return this.getCollectedData();
938
886
  }
939
887
  /**
940
- * Manually transition to a different route
941
- * Sets a pending transition that will be executed on the next respond() call
888
+ * Dispatch a directive (or a flow shorthand) into a session.
889
+ * Sets `pendingDirective` on the session without triggering a `respond()` call.
890
+ * The directive will be applied at the start of the next turn.
891
+ *
892
+ * String form desugars to `{ goTo: target }`.
942
893
  *
943
- * @param routeIdOrTitle - Route ID or title to transition to
944
- * @param session - Session step to update (uses current session if not provided)
945
- * @param condition - Optional AI-evaluated condition for the transition
946
- * @returns Updated session with pending transition
894
+ * @param target - Flow ID/title string (desugars to `{ goTo: target }`) or a full Directive
895
+ * @param session - Session to update (uses current session if not provided)
896
+ * @returns Updated session with `pendingDirective` set
897
+ *
898
+ * @throws FlowConfigurationError if the string target doesn't match any flow
899
+ * @throws FlowConfigurationError if the directive fails validation
900
+ *
901
+ * @example
902
+ * // String shorthand — desugars to { goTo: 'Feedback' }
903
+ * const updated = await agent.dispatch('Feedback', session);
947
904
  *
948
905
  * @example
949
- * // After route completes
950
- * if (response.isRouteComplete && response.session) {
951
- * const updatedSession = agent.nextStepRoute("feedback-collection", response.session);
952
- * // Next respond() call will automatically transition to feedback route
953
- * const nextResponse = await agent.respond({ history, session: updatedSession });
954
- * }
955
- */
956
- async nextStepRoute(routeIdOrTitle, session, condition, history) {
906
+ * // Full directive
907
+ * const updated = await agent.dispatch({ goTo: 'Billing', reply: 'Transferring you now.' }, session);
908
+ */
909
+ // eslint-disable-next-line @typescript-eslint/require-await
910
+ async dispatch(target, session) {
957
911
  const targetSession = session || this._currentSession;
958
912
  if (!targetSession) {
959
- throw new Error("No session provided and no current session available. Please provide a session to transition.");
960
- }
961
- // Find target route by ID or title
962
- const targetRoute = this._routes.find((r) => r.id === routeIdOrTitle || r.title === routeIdOrTitle);
963
- if (!targetRoute) {
964
- throw new Error(`Route not found: ${routeIdOrTitle}. Available routes: ${this._routes
965
- .map((r) => r.title)
966
- .join(", ")}`);
967
- }
968
- const templateContext = createTemplateContext({
969
- context: this._context,
970
- session,
971
- history,
972
- data: this._currentSession?.data,
973
- });
974
- const renderedCondition = await render(condition, templateContext);
913
+ throw new Error("No session provided and no current session available. Please provide a session to dispatch into.");
914
+ }
915
+ // Desugar string form to { goTo: target }
916
+ const directive = typeof target === 'string'
917
+ ? { goTo: target }
918
+ : target;
919
+ // Validate the directive: check for multiple position fields, empty goTo, etc.
920
+ this.validateDirective(directive);
921
+ // If goTo is a string, validate it references a known flow
922
+ if (typeof directive.goTo === 'string') {
923
+ const flowTarget = directive.goTo;
924
+ const matchesFlow = this._flows.some(f => f.id === flowTarget || f.title === flowTarget);
925
+ if (!matchesFlow) {
926
+ throw new StepFlowConfigurationError(`[FlowConfigurationError] Unknown flow: "${flowTarget}" does not match any flow id or title. ` +
927
+ `Available flows: ${this._flows.map(f => f.title).join(', ')}.`);
928
+ }
929
+ }
930
+ else if (directive.goTo && typeof directive.goTo === 'object' && directive.goTo.flow) {
931
+ const flowTarget = directive.goTo.flow;
932
+ const matchesFlow = this._flows.some(f => f.id === flowTarget || f.title === flowTarget);
933
+ if (!matchesFlow) {
934
+ throw new StepFlowConfigurationError(`[FlowConfigurationError] Unknown flow: "${flowTarget}" does not match any flow id or title. ` +
935
+ `Available flows: ${this._flows.map(f => f.title).join(', ')}.`);
936
+ }
937
+ }
938
+ // Strip PreDirective-only fields before storing
939
+ const stripped = this.stripPreDirectiveFields(directive);
940
+ // Set pendingDirective on the session without applying it
975
941
  const updatedSession = {
976
942
  ...targetSession,
977
- pendingTransition: {
978
- targetRouteId: targetRoute.id,
979
- condition: renderedCondition,
980
- reason: "route_complete",
943
+ pendingDirective: stripped,
944
+ metadata: {
945
+ ...targetSession.metadata,
946
+ lastUpdatedAt: new Date(),
981
947
  },
982
948
  };
983
- // Update current session if using it
949
+ // Update current session in place if no explicit session was passed
984
950
  if (!session && this._currentSession) {
985
951
  this._currentSession = updatedSession;
986
952
  }
987
- logger.debug(`[Agent] Set pending transition to route: ${targetRoute.title}`);
953
+ logger.debug(`[Agent] Dispatched directive: pendingDirective set on session ${updatedSession.id}`);
954
+ return updatedSession;
955
+ }
956
+ /**
957
+ * Apply a directive synchronously to a session without invoking `respond()`.
958
+ * Performs in-place application: updates flow/step position, merges state writes.
959
+ *
960
+ * This is the synchronous counterpart to `dispatch` — it applies immediately
961
+ * rather than deferring to the next turn.
962
+ *
963
+ * @param directive - The directive to apply
964
+ * @param session - The session to apply the directive to
965
+ * @returns The updated session with the directive applied
966
+ */
967
+ applyDirective(directive, session) {
968
+ // Validate the directive
969
+ this.validateDirective(directive);
970
+ let updatedSession = { ...session };
971
+ const now = new Date();
972
+ // Apply state writes
973
+ if (directive.contextUpdate) {
974
+ // Context updates are applied to the agent, not the session
975
+ this._context = {
976
+ ...this._context,
977
+ ...directive.contextUpdate,
978
+ };
979
+ }
980
+ if (directive.dataUpdate) {
981
+ updatedSession = {
982
+ ...updatedSession,
983
+ data: {
984
+ ...updatedSession.data,
985
+ ...directive.dataUpdate,
986
+ },
987
+ };
988
+ }
989
+ // Apply position control
990
+ if (directive.goTo) {
991
+ const flowTarget = typeof directive.goTo === 'string'
992
+ ? directive.goTo
993
+ : directive.goTo.flow;
994
+ if (flowTarget) {
995
+ const targetFlow = this._flows.find(f => f.id === flowTarget || f.title === flowTarget);
996
+ if (targetFlow) {
997
+ // Merge goTo.data if present
998
+ if (typeof directive.goTo === 'object' && directive.goTo.data) {
999
+ updatedSession = {
1000
+ ...updatedSession,
1001
+ data: {
1002
+ ...updatedSession.data,
1003
+ ...directive.goTo.data,
1004
+ },
1005
+ };
1006
+ }
1007
+ updatedSession = enterFlow(updatedSession, targetFlow.id, targetFlow.title);
1008
+ // If a specific step is targeted
1009
+ if (typeof directive.goTo === 'object' && directive.goTo.step) {
1010
+ updatedSession = enterStep(updatedSession, directive.goTo.step);
1011
+ }
1012
+ }
1013
+ }
1014
+ }
1015
+ else if (directive.goToStep) {
1016
+ const stepTarget = typeof directive.goToStep === 'string'
1017
+ ? directive.goToStep
1018
+ : directive.goToStep.step;
1019
+ // Merge goToStep.data if present
1020
+ if (typeof directive.goToStep === 'object' && directive.goToStep.data) {
1021
+ updatedSession = {
1022
+ ...updatedSession,
1023
+ data: {
1024
+ ...updatedSession.data,
1025
+ ...directive.goToStep.data,
1026
+ },
1027
+ };
1028
+ }
1029
+ updatedSession = enterStep(updatedSession, stepTarget);
1030
+ }
1031
+ else if (directive.complete) {
1032
+ updatedSession = completeCurrentFlow(updatedSession);
1033
+ // If complete carries a chained directive, set it as pendingDirective
1034
+ if (typeof directive.complete === 'object' && directive.complete.next) {
1035
+ updatedSession = {
1036
+ ...updatedSession,
1037
+ pendingDirective: directive.complete.next,
1038
+ };
1039
+ }
1040
+ }
1041
+ else if (directive.abort) {
1042
+ const clearSession = typeof directive.abort === 'object'
1043
+ ? directive.abort.clearSession !== false
1044
+ : true;
1045
+ if (clearSession) {
1046
+ updatedSession = {
1047
+ ...updatedSession,
1048
+ currentFlow: undefined,
1049
+ currentStep: undefined,
1050
+ data: {},
1051
+ };
1052
+ }
1053
+ else {
1054
+ updatedSession = {
1055
+ ...updatedSession,
1056
+ currentFlow: undefined,
1057
+ currentStep: undefined,
1058
+ };
1059
+ }
1060
+ }
1061
+ else if (directive.reset) {
1062
+ const currentFlowId = updatedSession.currentFlow?.id;
1063
+ const currentFlowTitle = updatedSession.currentFlow?.title;
1064
+ if (currentFlowId && currentFlowTitle) {
1065
+ // Clear data if requested
1066
+ if (typeof directive.reset === 'object' && directive.reset.clearData) {
1067
+ const currentFlow = this._flows.find(f => f.id === currentFlowId);
1068
+ if (currentFlow) {
1069
+ const ownedFields = [
1070
+ ...(currentFlow.requiredFields || []),
1071
+ ...(currentFlow.optionalFields || []),
1072
+ ];
1073
+ updatedSession = completeCurrentFlow(updatedSession, { clearOwnedFields: ownedFields });
1074
+ // Re-enter the same flow
1075
+ updatedSession = enterFlow(updatedSession, currentFlowId, currentFlowTitle);
1076
+ }
1077
+ }
1078
+ else {
1079
+ // Re-enter the flow from the beginning (or specified step)
1080
+ updatedSession = enterFlow(updatedSession, currentFlowId, currentFlowTitle);
1081
+ }
1082
+ // If a specific step is targeted for reset
1083
+ if (typeof directive.reset === 'object' && directive.reset.step) {
1084
+ updatedSession = enterStep(updatedSession, directive.reset.step);
1085
+ }
1086
+ }
1087
+ }
1088
+ // Update metadata
1089
+ updatedSession = {
1090
+ ...updatedSession,
1091
+ metadata: {
1092
+ ...updatedSession.metadata,
1093
+ lastUpdatedAt: now,
1094
+ },
1095
+ };
988
1096
  return updatedSession;
989
1097
  }
1098
+ /**
1099
+ * Validate a directive for structural correctness.
1100
+ * Throws FlowConfigurationError for invalid combinations.
1101
+ * @private
1102
+ */
1103
+ validateDirective(directive) {
1104
+ // Check for multiple position fields
1105
+ const positionFields = ['goTo', 'goToStep', 'complete', 'abort', 'reset'];
1106
+ const setPositionFields = positionFields.filter(field => directive[field] !== undefined);
1107
+ if (setPositionFields.length > 1) {
1108
+ throw new StepFlowConfigurationError(`[FlowConfigurationError] Multiple position fields: a Directive may set at most one position field. ` +
1109
+ `Found: ${setPositionFields.join(', ')}. Remove all but one.`);
1110
+ }
1111
+ // Check for empty goTo object
1112
+ if (directive.goTo && typeof directive.goTo === 'object') {
1113
+ const goToObj = directive.goTo;
1114
+ if (!goToObj.flow && !goToObj.step) {
1115
+ throw new StepFlowConfigurationError(`[FlowConfigurationError] Empty goTo: "goTo" requires at least a "flow" field. ` +
1116
+ `Provide { goTo: { flow: '<id>' } } or use the string shorthand { goTo: '<id>' }.`);
1117
+ }
1118
+ }
1119
+ }
1120
+ /**
1121
+ * Strip PreDirective-only fields (appendPrompt, injectTools, halt) from a directive.
1122
+ * These fields are transient (one-turn lifetime) and must not be persisted.
1123
+ * @private
1124
+ */
1125
+ stripPreDirectiveFields(directive) {
1126
+ const raw = directive;
1127
+ if (!raw.appendPrompt && !raw.injectTools && raw.halt === undefined) {
1128
+ return directive;
1129
+ }
1130
+ const { appendPrompt, injectTools, halt, ...rest } = raw;
1131
+ if (appendPrompt || injectTools || halt !== undefined) {
1132
+ logger.debug(`[Agent] Stripped PreDirective-only fields before storing pendingDirective: ` +
1133
+ `${[appendPrompt && 'appendPrompt', injectTools && 'injectTools', halt !== undefined && 'halt'].filter(Boolean).join(', ')}`);
1134
+ }
1135
+ return rest;
1136
+ }
990
1137
  /**
991
1138
  * Simplified respond method using SessionManager
992
1139
  * Automatically manages conversation history through the session