@ai.ntellect/core 0.8.3 → 1.1.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 (460) hide show
  1. package/.mocharc.json +2 -1
  2. package/AGENTS.md +50 -0
  3. package/ARCHITECTURE.md +58 -0
  4. package/BENCHMARK.md +38 -0
  5. package/CHANGELOG.md +224 -0
  6. package/README.md +413 -199
  7. package/agent/agent-workflow.ts +569 -0
  8. package/agent/agent.ts +183 -0
  9. package/{modules/agent → agent}/base/executor.ts +11 -8
  10. package/{modules/agent → agent}/base/index.ts +2 -14
  11. package/agent/entity-resolver/confidence.ts +54 -0
  12. package/agent/entity-resolver/entity-index.ts +241 -0
  13. package/agent/entity-resolver/explore-strategy.ts +82 -0
  14. package/agent/entity-resolver/index.ts +22 -0
  15. package/agent/entity-resolver/resolver.ts +193 -0
  16. package/agent/entity-resolver/scorer.ts +211 -0
  17. package/agent/entity-resolver/types.ts +98 -0
  18. package/agent/generic-executor.ts +713 -0
  19. package/agent/handlers/cognitive-handler.ts +197 -0
  20. package/agent/handlers/index.ts +1 -0
  21. package/agent/handoff.ts +58 -0
  22. package/agent/llm-factory.ts +343 -0
  23. package/agent/orchestrator.ts +45 -0
  24. package/{modules/agent → agent}/prompt-builder.ts +1 -1
  25. package/agent/registry.ts +64 -0
  26. package/agent/tools/file-system.ts +471 -0
  27. package/agent/tools/index.ts +23 -0
  28. package/agent/tools/logger.ts +105 -0
  29. package/agent/tools/tool-resolver.ts +104 -0
  30. package/benchmark/cortexflow-workflow.ts +182 -0
  31. package/benchmark/langgraph-workflow.ts +201 -0
  32. package/benchmark/llm-client.ts +76 -0
  33. package/benchmark/run-benchmark.ts +222 -0
  34. package/cli-dev.ts +419 -0
  35. package/dist/agent/agent-workflow.d.ts +41 -0
  36. package/dist/agent/agent-workflow.d.ts.map +1 -0
  37. package/dist/agent/agent-workflow.js +560 -0
  38. package/dist/agent/agent-workflow.js.map +1 -0
  39. package/dist/agent/agent.d.ts +38 -0
  40. package/dist/agent/agent.d.ts.map +1 -0
  41. package/dist/agent/agent.js +149 -0
  42. package/dist/agent/agent.js.map +1 -0
  43. package/dist/{modules/agent → agent}/base/executor.d.ts +3 -3
  44. package/dist/agent/base/executor.d.ts.map +1 -0
  45. package/dist/{modules/agent → agent}/base/executor.js +8 -5
  46. package/dist/agent/base/executor.js.map +1 -0
  47. package/dist/{modules/agent → agent}/base/index.d.ts +1 -1
  48. package/dist/agent/base/index.d.ts.map +1 -0
  49. package/dist/{modules/agent → agent}/base/index.js +0 -12
  50. package/dist/agent/base/index.js.map +1 -0
  51. package/dist/agent/entity-resolver/confidence.d.ts +4 -0
  52. package/dist/agent/entity-resolver/confidence.d.ts.map +1 -0
  53. package/dist/agent/entity-resolver/confidence.js +47 -0
  54. package/dist/agent/entity-resolver/confidence.js.map +1 -0
  55. package/dist/agent/entity-resolver/entity-index.d.ts +40 -0
  56. package/dist/agent/entity-resolver/entity-index.d.ts.map +1 -0
  57. package/dist/agent/entity-resolver/entity-index.js +244 -0
  58. package/dist/agent/entity-resolver/entity-index.js.map +1 -0
  59. package/dist/agent/entity-resolver/explore-strategy.d.ts +13 -0
  60. package/dist/agent/entity-resolver/explore-strategy.d.ts.map +1 -0
  61. package/dist/agent/entity-resolver/explore-strategy.js +109 -0
  62. package/dist/agent/entity-resolver/explore-strategy.js.map +1 -0
  63. package/dist/agent/entity-resolver/index.d.ts +8 -0
  64. package/dist/agent/entity-resolver/index.d.ts.map +1 -0
  65. package/dist/agent/entity-resolver/index.js +16 -0
  66. package/dist/agent/entity-resolver/index.js.map +1 -0
  67. package/dist/agent/entity-resolver/resolver.d.ts +18 -0
  68. package/dist/agent/entity-resolver/resolver.d.ts.map +1 -0
  69. package/dist/agent/entity-resolver/resolver.js +158 -0
  70. package/dist/agent/entity-resolver/resolver.js.map +1 -0
  71. package/dist/agent/entity-resolver/scorer.d.ts +3 -0
  72. package/dist/agent/entity-resolver/scorer.d.ts.map +1 -0
  73. package/dist/agent/entity-resolver/scorer.js +182 -0
  74. package/dist/agent/entity-resolver/scorer.js.map +1 -0
  75. package/dist/agent/entity-resolver/types.d.ts +89 -0
  76. package/dist/agent/entity-resolver/types.d.ts.map +1 -0
  77. package/dist/agent/entity-resolver/types.js +3 -0
  78. package/dist/agent/entity-resolver/types.js.map +1 -0
  79. package/dist/{modules/agent → agent}/generic-executor.d.ts +37 -27
  80. package/dist/agent/generic-executor.d.ts.map +1 -0
  81. package/dist/agent/generic-executor.js +620 -0
  82. package/dist/agent/generic-executor.js.map +1 -0
  83. package/dist/agent/handlers/cognitive-handler.d.ts +44 -0
  84. package/dist/agent/handlers/cognitive-handler.d.ts.map +1 -0
  85. package/dist/agent/handlers/cognitive-handler.js +172 -0
  86. package/dist/agent/handlers/cognitive-handler.js.map +1 -0
  87. package/dist/agent/handlers/index.d.ts +2 -0
  88. package/dist/agent/handlers/index.d.ts.map +1 -0
  89. package/dist/agent/handlers/index.js +7 -0
  90. package/dist/agent/handlers/index.js.map +1 -0
  91. package/dist/agent/handoff.d.ts +12 -0
  92. package/dist/agent/handoff.d.ts.map +1 -0
  93. package/dist/agent/handoff.js +62 -0
  94. package/dist/agent/handoff.js.map +1 -0
  95. package/dist/agent/llm-factory.d.ts.map +1 -0
  96. package/dist/agent/llm-factory.js +297 -0
  97. package/dist/agent/llm-factory.js.map +1 -0
  98. package/dist/agent/orchestrator.d.ts +18 -0
  99. package/dist/agent/orchestrator.d.ts.map +1 -0
  100. package/dist/agent/orchestrator.js +44 -0
  101. package/dist/agent/orchestrator.js.map +1 -0
  102. package/dist/{modules/agent → agent}/prompt-builder.d.ts +1 -1
  103. package/dist/agent/prompt-builder.d.ts.map +1 -0
  104. package/dist/agent/prompt-builder.js.map +1 -0
  105. package/dist/agent/registry.d.ts +19 -0
  106. package/dist/agent/registry.d.ts.map +1 -0
  107. package/dist/agent/registry.js +48 -0
  108. package/dist/agent/registry.js.map +1 -0
  109. package/dist/agent/tools/file-system.d.ts +11 -0
  110. package/dist/agent/tools/file-system.d.ts.map +1 -0
  111. package/dist/agent/tools/file-system.js +528 -0
  112. package/dist/agent/tools/file-system.js.map +1 -0
  113. package/dist/agent/tools/index.d.ts +4 -0
  114. package/dist/agent/tools/index.d.ts.map +1 -0
  115. package/dist/agent/tools/index.js +20 -0
  116. package/dist/agent/tools/index.js.map +1 -0
  117. package/dist/agent/tools/logger.d.ts +33 -0
  118. package/dist/agent/tools/logger.d.ts.map +1 -0
  119. package/dist/agent/tools/logger.js +86 -0
  120. package/dist/agent/tools/logger.js.map +1 -0
  121. package/dist/agent/tools/tool-resolver.d.ts +7 -0
  122. package/dist/agent/tools/tool-resolver.d.ts.map +1 -0
  123. package/dist/agent/tools/tool-resolver.js +122 -0
  124. package/dist/agent/tools/tool-resolver.js.map +1 -0
  125. package/dist/execution/adapters/in-memory-checkpoint.d.ts +11 -0
  126. package/dist/execution/adapters/in-memory-checkpoint.d.ts.map +1 -0
  127. package/dist/execution/adapters/in-memory-checkpoint.js +54 -0
  128. package/dist/execution/adapters/in-memory-checkpoint.js.map +1 -0
  129. package/dist/execution/compiler.d.ts +8 -0
  130. package/dist/execution/compiler.d.ts.map +1 -0
  131. package/dist/execution/compiler.js +50 -0
  132. package/dist/execution/compiler.js.map +1 -0
  133. package/dist/execution/controller.d.ts.map +1 -0
  134. package/dist/execution/controller.js.map +1 -0
  135. package/dist/execution/event-manager.d.ts +29 -0
  136. package/dist/execution/event-manager.d.ts.map +1 -0
  137. package/dist/{graph → execution}/event-manager.js +4 -114
  138. package/dist/execution/event-manager.js.map +1 -0
  139. package/dist/{graph → execution}/index.d.ts +50 -2
  140. package/dist/execution/index.d.ts.map +1 -0
  141. package/dist/execution/index.js +638 -0
  142. package/dist/execution/index.js.map +1 -0
  143. package/dist/execution/logger.d.ts.map +1 -0
  144. package/dist/execution/logger.js.map +1 -0
  145. package/dist/{graph → execution}/node.d.ts +6 -1
  146. package/dist/execution/node.d.ts.map +1 -0
  147. package/dist/{graph → execution}/node.js +83 -10
  148. package/dist/execution/node.js.map +1 -0
  149. package/dist/execution/observer.d.ts.map +1 -0
  150. package/dist/execution/observer.js.map +1 -0
  151. package/dist/execution/planner.d.ts +14 -0
  152. package/dist/execution/planner.d.ts.map +1 -0
  153. package/dist/execution/planner.js +43 -0
  154. package/dist/execution/planner.js.map +1 -0
  155. package/dist/execution/reducer.d.ts +19 -0
  156. package/dist/execution/reducer.d.ts.map +1 -0
  157. package/dist/execution/reducer.js +61 -0
  158. package/dist/execution/reducer.js.map +1 -0
  159. package/dist/execution/registry.d.ts +38 -0
  160. package/dist/execution/registry.d.ts.map +1 -0
  161. package/dist/execution/registry.js +63 -0
  162. package/dist/execution/registry.js.map +1 -0
  163. package/dist/execution/send-api.d.ts +24 -0
  164. package/dist/execution/send-api.d.ts.map +1 -0
  165. package/dist/execution/send-api.js +52 -0
  166. package/dist/execution/send-api.js.map +1 -0
  167. package/dist/execution/types.parallel.d.ts +61 -0
  168. package/dist/execution/types.parallel.d.ts.map +1 -0
  169. package/dist/execution/types.parallel.js +3 -0
  170. package/dist/execution/types.parallel.js.map +1 -0
  171. package/dist/execution/visualizer.d.ts.map +1 -0
  172. package/dist/execution/visualizer.js.map +1 -0
  173. package/dist/index.d.ts +27 -8
  174. package/dist/index.d.ts.map +1 -1
  175. package/dist/index.js +42 -8
  176. package/dist/index.js.map +1 -1
  177. package/dist/interfaces/index.d.ts +32 -1
  178. package/dist/interfaces/index.d.ts.map +1 -1
  179. package/dist/interfaces/index.js.map +1 -1
  180. package/dist/modules/cli/index.d.ts +13 -0
  181. package/dist/modules/cli/index.d.ts.map +1 -0
  182. package/dist/modules/cli/index.js +672 -0
  183. package/dist/modules/cli/index.js.map +1 -0
  184. package/dist/modules/nlp/engine.d.ts.map +1 -1
  185. package/dist/modules/nlp/engine.js +0 -1
  186. package/dist/modules/nlp/engine.js.map +1 -1
  187. package/dist/persistence/index.d.ts +12 -0
  188. package/dist/persistence/index.d.ts.map +1 -0
  189. package/dist/persistence/index.js +24 -0
  190. package/dist/persistence/index.js.map +1 -0
  191. package/dist/persistence/neo4j/driver.d.ts +26 -0
  192. package/dist/persistence/neo4j/driver.d.ts.map +1 -0
  193. package/dist/persistence/neo4j/driver.js +64 -0
  194. package/dist/persistence/neo4j/driver.js.map +1 -0
  195. package/dist/persistence/neo4j/entity-store.d.ts +15 -0
  196. package/dist/persistence/neo4j/entity-store.d.ts.map +1 -0
  197. package/dist/persistence/neo4j/entity-store.js +136 -0
  198. package/dist/persistence/neo4j/entity-store.js.map +1 -0
  199. package/dist/persistence/neo4j/execution-tracer.d.ts +19 -0
  200. package/dist/persistence/neo4j/execution-tracer.d.ts.map +1 -0
  201. package/dist/persistence/neo4j/execution-tracer.js +166 -0
  202. package/dist/persistence/neo4j/execution-tracer.js.map +1 -0
  203. package/dist/persistence/neo4j/memory-adapter.d.ts +35 -0
  204. package/dist/persistence/neo4j/memory-adapter.d.ts.map +1 -0
  205. package/dist/persistence/neo4j/memory-adapter.js +252 -0
  206. package/dist/persistence/neo4j/memory-adapter.js.map +1 -0
  207. package/dist/persistence/neo4j/petri-checkpoint-adapter.d.ts +22 -0
  208. package/dist/persistence/neo4j/petri-checkpoint-adapter.d.ts.map +1 -0
  209. package/dist/persistence/neo4j/petri-checkpoint-adapter.js +141 -0
  210. package/dist/persistence/neo4j/petri-checkpoint-adapter.js.map +1 -0
  211. package/dist/pipeline/agent-pipeline.d.ts +99 -0
  212. package/dist/pipeline/agent-pipeline.d.ts.map +1 -0
  213. package/dist/pipeline/agent-pipeline.js +356 -0
  214. package/dist/pipeline/agent-pipeline.js.map +1 -0
  215. package/dist/routing/checkpoint-adapter.d.ts +30 -0
  216. package/dist/routing/checkpoint-adapter.d.ts.map +1 -0
  217. package/dist/routing/checkpoint-adapter.js +83 -0
  218. package/dist/routing/checkpoint-adapter.js.map +1 -0
  219. package/dist/routing/documentation-generator.d.ts +47 -0
  220. package/dist/routing/documentation-generator.d.ts.map +1 -0
  221. package/dist/routing/documentation-generator.js +320 -0
  222. package/dist/routing/documentation-generator.js.map +1 -0
  223. package/dist/routing/index.d.ts +38 -0
  224. package/dist/routing/index.d.ts.map +1 -0
  225. package/dist/routing/index.js +375 -0
  226. package/dist/routing/index.js.map +1 -0
  227. package/dist/routing/intent-classifier.d.ts +206 -0
  228. package/dist/routing/intent-classifier.d.ts.map +1 -0
  229. package/dist/routing/intent-classifier.js +267 -0
  230. package/dist/routing/intent-classifier.js.map +1 -0
  231. package/dist/routing/matrix.d.ts +6 -0
  232. package/dist/routing/matrix.d.ts.map +1 -0
  233. package/dist/routing/matrix.js +131 -0
  234. package/dist/routing/matrix.js.map +1 -0
  235. package/dist/routing/orchestrator.d.ts +87 -0
  236. package/dist/routing/orchestrator.d.ts.map +1 -0
  237. package/dist/routing/orchestrator.js +425 -0
  238. package/dist/routing/orchestrator.js.map +1 -0
  239. package/dist/routing/postgres-checkpoint-adapter.d.ts +32 -0
  240. package/dist/routing/postgres-checkpoint-adapter.d.ts.map +1 -0
  241. package/dist/routing/postgres-checkpoint-adapter.js +167 -0
  242. package/dist/routing/postgres-checkpoint-adapter.js.map +1 -0
  243. package/dist/routing/redis-checkpoint-adapter.d.ts +34 -0
  244. package/dist/routing/redis-checkpoint-adapter.d.ts.map +1 -0
  245. package/dist/routing/redis-checkpoint-adapter.js +170 -0
  246. package/dist/routing/redis-checkpoint-adapter.js.map +1 -0
  247. package/dist/routing/types.d.ts +49 -0
  248. package/dist/routing/types.d.ts.map +1 -0
  249. package/dist/routing/types.js +3 -0
  250. package/dist/routing/types.js.map +1 -0
  251. package/dist/types/agent.d.ts +144 -88
  252. package/dist/types/agent.d.ts.map +1 -1
  253. package/dist/types/agent.js +49 -0
  254. package/dist/types/agent.js.map +1 -1
  255. package/dist/types/index.d.ts +46 -4
  256. package/dist/types/index.d.ts.map +1 -1
  257. package/dist/utils/generate-action-schema.d.ts +2 -3
  258. package/dist/utils/generate-action-schema.d.ts.map +1 -1
  259. package/dist/utils/generate-action-schema.js +3 -1
  260. package/dist/utils/generate-action-schema.js.map +1 -1
  261. package/dist/utils/logger.d.ts +27 -0
  262. package/dist/utils/logger.d.ts.map +1 -0
  263. package/dist/utils/logger.js +45 -0
  264. package/dist/utils/logger.js.map +1 -0
  265. package/docs/.gitbook/assets/image (1).png +0 -0
  266. package/docs/.gitbook/assets/image (2).png +0 -0
  267. package/docs/.gitbook/assets/image (3).png +0 -0
  268. package/docs/.gitbook/assets/image (4).png +0 -0
  269. package/docs/.gitbook/assets/image (5).png +0 -0
  270. package/docs/.gitbook/assets/image (6).png +0 -0
  271. package/docs/.gitbook/assets/image.png +0 -0
  272. package/docs/README.md +57 -0
  273. package/docs/SUMMARY.md +34 -0
  274. package/docs/cas-dusages.md +69 -0
  275. package/docs/cli/README.md +65 -0
  276. package/docs/concepts-cles.md +50 -0
  277. package/docs/core/architecture.md +87 -0
  278. package/docs/core/benchmark.md +59 -0
  279. package/docs/core/checkpoint.md +72 -0
  280. package/docs/core/documentation.md +55 -0
  281. package/docs/core/graphcontroller.md +63 -0
  282. package/docs/core/graphflow.md +137 -0
  283. package/docs/core/introduction.md +41 -0
  284. package/docs/core/les-evenements.md +95 -0
  285. package/docs/modules/agenda/README.md +63 -0
  286. package/docs/modules/agenda/interface-iagenda.md +170 -0
  287. package/docs/modules/agenda/les-adaptateurs/README.md +237 -0
  288. package/docs/modules/agenda/les-adaptateurs/nodecronadapter.md +91 -0
  289. package/docs/modules/introduction.md +55 -0
  290. package/docs/modules/les-adaptateurs.md +52 -0
  291. package/docs/modules/memoire/README.md +68 -0
  292. package/docs/modules/memoire/interface-imemory.md +183 -0
  293. package/docs/modules/memoire/les-adaptateurs/README.md +209 -0
  294. package/docs/modules/memoire/les-adaptateurs/inmemoryadapter.md +110 -0
  295. package/docs/modules/memoire/les-adaptateurs/meilisearchadapter.md +147 -0
  296. package/docs/modules/memoire/les-adaptateurs/redisadapter.md +212 -0
  297. package/docs/modules/nlp/README.md +44 -0
  298. package/docs/philosophie.md +51 -0
  299. package/docs/tutoriels/ajouter-des-conditions.md +150 -0
  300. package/docs/tutoriels/branching.md +194 -0
  301. package/docs/tutoriels/checkpoint-usage.md +99 -0
  302. package/docs/tutoriels/creer-agent-onchain.md +1041 -0
  303. package/docs/tutoriels/creer-un-agent.md +108 -0
  304. package/docs/tutoriels/creer-un-graphe-simple.md +92 -0
  305. package/docs/tutoriels/gerer-les-erreurs.md +124 -0
  306. package/docs/tutoriels/pour-commencer.md +73 -0
  307. package/docs/tutoriels/retry.md +166 -0
  308. package/execution/adapters/in-memory-checkpoint.ts +35 -0
  309. package/execution/compiler.ts +47 -0
  310. package/{graph → execution}/event-manager.ts +4 -117
  311. package/{graph → execution}/index.ts +376 -8
  312. package/{graph → execution}/node.ts +116 -12
  313. package/execution/planner.ts +40 -0
  314. package/execution/reducer.ts +73 -0
  315. package/execution/registry.ts +86 -0
  316. package/execution/send-api.ts +58 -0
  317. package/execution/types.parallel.ts +81 -0
  318. package/index.ts +35 -8
  319. package/interfaces/index.ts +37 -0
  320. package/modules/cli/index.ts +580 -0
  321. package/modules/nlp/engine.ts +0 -1
  322. package/package.json +50 -16
  323. package/persistence/index.ts +27 -0
  324. package/persistence/neo4j/driver.ts +34 -0
  325. package/persistence/neo4j/entity-store.ts +141 -0
  326. package/persistence/neo4j/execution-tracer.ts +194 -0
  327. package/persistence/neo4j/memory-adapter.ts +281 -0
  328. package/persistence/neo4j/petri-checkpoint-adapter.ts +153 -0
  329. package/pipeline/agent-pipeline.ts +426 -0
  330. package/routing/checkpoint-adapter.ts +79 -0
  331. package/routing/documentation-generator.ts +358 -0
  332. package/routing/index.ts +459 -0
  333. package/routing/intent-classifier.ts +360 -0
  334. package/routing/matrix.ts +138 -0
  335. package/routing/orchestrator.ts +498 -0
  336. package/routing/patterns/data-extraction.json +79 -0
  337. package/routing/patterns/human-approval.json +64 -0
  338. package/routing/patterns/rag-search.json +68 -0
  339. package/routing/postgres-checkpoint-adapter.ts +172 -0
  340. package/routing/redis-checkpoint-adapter.ts +187 -0
  341. package/routing/types.ts +59 -0
  342. package/routing/web-server.ts +260 -0
  343. package/scripts/generate-petri-docs.ts +70 -0
  344. package/scripts/get-gmail-token.js +65 -0
  345. package/scripts/get-gmail-token.ts +65 -0
  346. package/test/agent/agent.test.ts +92 -0
  347. package/test/agent/clone.test.ts +143 -0
  348. package/test/agent/cognitive-handler.test.ts +78 -0
  349. package/test/agent/entity-store.test.ts +80 -0
  350. package/test/agent/generic-executor.test.ts +230 -0
  351. package/test/agent/handoff.test.ts +163 -0
  352. package/test/agent/llm-factory.test.ts +40 -0
  353. package/test/agent/orchestrator.test.ts +156 -0
  354. package/test/agent/registry.test.ts +97 -0
  355. package/test/agent/tools.test.ts +267 -0
  356. package/test/execution/checkpoint.test.ts +811 -0
  357. package/test/{graph → execution}/controller.test.ts +2 -2
  358. package/test/{graph → execution}/event-manager.test.ts +1 -1
  359. package/test/{graph → execution}/index.test.ts +24 -15
  360. package/test/{graph → execution}/node.test.ts +3 -3
  361. package/test/{graph → execution}/observer.test.ts +2 -2
  362. package/test/execution/parallel.test.ts +135 -0
  363. package/test/execution/plan-llm-integration.test.ts +290 -0
  364. package/test/execution/plan-real-onchain.test.ts +226 -0
  365. package/test/execution/send-api.test.ts +121 -0
  366. package/test/modules/cli/index.test.ts +125 -0
  367. package/test/persistence/neo4j-execution-tracer.test.ts +96 -0
  368. package/test/persistence/neo4j-memory-adapter.test.ts +107 -0
  369. package/test/persistence/neo4j-petri-checkpoint.test.ts +89 -0
  370. package/test/pipeline/agent-pipeline.test.ts +118 -0
  371. package/test/routing/checkpoint-persistence.test.ts +58 -0
  372. package/test/routing/documentation-generator.test.ts +76 -0
  373. package/test/routing/integration.test.ts +261 -0
  374. package/test/routing/intent-classifier.test.ts +102 -0
  375. package/test/routing/petri.test.ts +156 -0
  376. package/test/routing/real-llm.test.ts +260 -0
  377. package/test-petri-features.ts +218 -0
  378. package/test-pipeline-api.ts +163 -0
  379. package/tsconfig.json +5 -2
  380. package/types/agent.ts +126 -4
  381. package/types/index.ts +66 -5
  382. package/utils/generate-action-schema.ts +5 -4
  383. package/utils/logger.ts +40 -0
  384. package/dist/graph/controller.d.ts.map +0 -1
  385. package/dist/graph/controller.js.map +0 -1
  386. package/dist/graph/event-manager.d.ts +0 -101
  387. package/dist/graph/event-manager.d.ts.map +0 -1
  388. package/dist/graph/event-manager.js.map +0 -1
  389. package/dist/graph/index.d.ts.map +0 -1
  390. package/dist/graph/index.js +0 -340
  391. package/dist/graph/index.js.map +0 -1
  392. package/dist/graph/logger.d.ts.map +0 -1
  393. package/dist/graph/logger.js.map +0 -1
  394. package/dist/graph/node.d.ts.map +0 -1
  395. package/dist/graph/node.js.map +0 -1
  396. package/dist/graph/observer.d.ts.map +0 -1
  397. package/dist/graph/observer.js.map +0 -1
  398. package/dist/graph/visualizer.d.ts.map +0 -1
  399. package/dist/graph/visualizer.js.map +0 -1
  400. package/dist/modules/agent/agent.d.ts +0 -35
  401. package/dist/modules/agent/agent.d.ts.map +0 -1
  402. package/dist/modules/agent/agent.js +0 -103
  403. package/dist/modules/agent/agent.js.map +0 -1
  404. package/dist/modules/agent/base/executor.d.ts.map +0 -1
  405. package/dist/modules/agent/base/executor.js.map +0 -1
  406. package/dist/modules/agent/base/index.d.ts.map +0 -1
  407. package/dist/modules/agent/base/index.js.map +0 -1
  408. package/dist/modules/agent/generic-assistant.d.ts +0 -20
  409. package/dist/modules/agent/generic-assistant.d.ts.map +0 -1
  410. package/dist/modules/agent/generic-assistant.js +0 -89
  411. package/dist/modules/agent/generic-assistant.js.map +0 -1
  412. package/dist/modules/agent/generic-executor.d.ts.map +0 -1
  413. package/dist/modules/agent/generic-executor.js +0 -189
  414. package/dist/modules/agent/generic-executor.js.map +0 -1
  415. package/dist/modules/agent/llm-factory.d.ts.map +0 -1
  416. package/dist/modules/agent/llm-factory.js +0 -56
  417. package/dist/modules/agent/llm-factory.js.map +0 -1
  418. package/dist/modules/agent/prompt-builder.d.ts.map +0 -1
  419. package/dist/modules/agent/prompt-builder.js.map +0 -1
  420. package/dist/modules/memory/adapters/in-memory/index.d.ts +0 -120
  421. package/dist/modules/memory/adapters/in-memory/index.d.ts.map +0 -1
  422. package/dist/modules/memory/adapters/in-memory/index.js +0 -212
  423. package/dist/modules/memory/adapters/in-memory/index.js.map +0 -1
  424. package/dist/modules/memory/adapters/meilisearch/index.d.ts +0 -110
  425. package/dist/modules/memory/adapters/meilisearch/index.d.ts.map +0 -1
  426. package/dist/modules/memory/adapters/meilisearch/index.js +0 -324
  427. package/dist/modules/memory/adapters/meilisearch/index.js.map +0 -1
  428. package/dist/modules/memory/adapters/redis/index.d.ts +0 -82
  429. package/dist/modules/memory/adapters/redis/index.d.ts.map +0 -1
  430. package/dist/modules/memory/adapters/redis/index.js +0 -160
  431. package/dist/modules/memory/adapters/redis/index.js.map +0 -1
  432. package/dist/modules/memory/index.d.ts +0 -67
  433. package/dist/modules/memory/index.d.ts.map +0 -1
  434. package/dist/modules/memory/index.js +0 -104
  435. package/dist/modules/memory/index.js.map +0 -1
  436. package/modules/agent/agent.ts +0 -107
  437. package/modules/agent/generic-assistant.ts +0 -92
  438. package/modules/agent/generic-executor.ts +0 -252
  439. package/modules/agent/llm-factory.ts +0 -47
  440. package/modules/memory/adapters/in-memory/index.ts +0 -208
  441. package/modules/memory/adapters/meilisearch/index.ts +0 -364
  442. package/modules/memory/adapters/redis/index.ts +0 -165
  443. package/modules/memory/index.ts +0 -93
  444. package/test/modules/memory/adapters/in-memory.test.ts +0 -153
  445. package/test/modules/memory/adapters/meilisearch.test.ts +0 -287
  446. package/test/modules/memory/base.test.ts +0 -230
  447. /package/dist/{modules/agent → agent}/llm-factory.d.ts +0 -0
  448. /package/dist/{modules/agent → agent}/prompt-builder.js +0 -0
  449. /package/dist/{graph → execution}/controller.d.ts +0 -0
  450. /package/dist/{graph → execution}/controller.js +0 -0
  451. /package/dist/{graph → execution}/logger.d.ts +0 -0
  452. /package/dist/{graph → execution}/logger.js +0 -0
  453. /package/dist/{graph → execution}/observer.d.ts +0 -0
  454. /package/dist/{graph → execution}/observer.js +0 -0
  455. /package/dist/{graph → execution}/visualizer.d.ts +0 -0
  456. /package/dist/{graph → execution}/visualizer.js +0 -0
  457. /package/{graph → execution}/controller.ts +0 -0
  458. /package/{graph → execution}/logger.ts +0 -0
  459. /package/{graph → execution}/observer.ts +0 -0
  460. /package/{graph → execution}/visualizer.ts +0 -0
@@ -1,9 +1,11 @@
1
1
  import { EventEmitter } from "events";
2
2
  import { BehaviorSubject, Subject } from "rxjs";
3
3
  import { ZodSchema } from "zod";
4
- import { GraphObservable, IEventEmitter } from "../interfaces";
4
+ import { GraphObservable, ICheckpointAdapter, IEventEmitter } from "../interfaces";
5
5
  import { NLPNode } from "../modules/nlp";
6
6
  import {
7
+ Checkpoint,
8
+ CheckpointConfig,
7
9
  GraphConfig,
8
10
  GraphContext,
9
11
  GraphEvent,
@@ -11,7 +13,7 @@ import {
11
13
  } from "../types";
12
14
  import { GraphEventManager } from "./event-manager";
13
15
  import { GraphLogger } from "./logger";
14
- import { GraphNode } from "./node";
16
+ import { GraphNode, NodeExecutionHooks } from "./node";
15
17
  import { GraphObserver } from "./observer";
16
18
  import { GraphVisualizer } from "./visualizer";
17
19
 
@@ -30,6 +32,7 @@ import { GraphVisualizer } from "./visualizer";
30
32
  */
31
33
  export class GraphFlow<T extends ZodSchema> {
32
34
  private context: GraphContext<T>;
35
+ private _initialContext: GraphContext<T>;
33
36
  public validator?: T;
34
37
  private eventEmitter: IEventEmitter;
35
38
  private globalErrorHandler?: (error: Error, context: GraphContext<T>) => void;
@@ -50,6 +53,11 @@ export class GraphFlow<T extends ZodSchema> {
50
53
 
51
54
  private nlpNodes: Map<string, NLPNode<T>> = new Map();
52
55
 
56
+ private _interrupted = false;
57
+ private _interruptCheckpoint: Checkpoint | null = null;
58
+ private _checkpointCounter = 0;
59
+ private _breakpoints: Set<string> = new Set();
60
+
53
61
  /**
54
62
  * Creates a new instance of GraphFlow
55
63
  * @param {GraphConfig<T>} config - Configuration object containing name, nodes, schema, context, and error handlers
@@ -62,6 +70,7 @@ export class GraphFlow<T extends ZodSchema> {
62
70
  );
63
71
  this.validator = config.schema;
64
72
  this.context = config.schema.parse(config.context) as GraphContext<T>;
73
+ this._initialContext = structuredClone(this.context);
65
74
  this.globalErrorHandler = config.onError;
66
75
  this.eventEmitter =
67
76
  config.eventEmitter || (new EventEmitter() as IEventEmitter);
@@ -226,17 +235,21 @@ export class GraphFlow<T extends ZodSchema> {
226
235
  context?: Partial<GraphContext<T>>
227
236
  ): Promise<GraphContext<T>> {
228
237
  try {
229
- // Validate and merge context if provided
230
238
  if (context) {
231
- const mergedContext = { ...this.context, ...context };
239
+ const base = this._initialContext ? structuredClone(this._initialContext) : this.context;
240
+ const previousMessages = (this.context as any)?.messages;
241
+ const mergedContext = { ...base, ...context };
242
+ if (previousMessages && Array.isArray(previousMessages) && previousMessages.length > 0) {
243
+ (mergedContext as any).messages = previousMessages;
244
+ }
232
245
  const validationResult = this.validator?.safeParse(mergedContext);
233
246
  if (!validationResult?.success) {
234
- const errors = validationResult?.error?.errors.map(
247
+ const errors = validationResult?.error?.issues.map(
235
248
  (err) => `${err.path.join(".")}: ${err.message}`
236
249
  );
237
250
  throw new Error(`Context validation failed: ${errors?.join(", ")}`);
238
251
  }
239
- this.context = validationResult.data;
252
+ this.context = validationResult.data as GraphContext<T>;
240
253
  }
241
254
 
242
255
  this.eventEmitter.emit("graphStarted", { name: this.name });
@@ -259,6 +272,341 @@ export class GraphFlow<T extends ZodSchema> {
259
272
  }
260
273
  }
261
274
 
275
+ /**
276
+ * Executes the graph flow with automatic checkpointing at each node
277
+ * @param startNode - Name of the node to start execution from
278
+ * @param adapter - Checkpoint persistence adapter
279
+ * @param config - Checkpoint configuration options
280
+ * @returns Execution result with final context and checkpoint ID
281
+ */
282
+ public async executeWithCheckpoint(
283
+ startNode: string,
284
+ adapter: ICheckpointAdapter,
285
+ config: CheckpointConfig = {}
286
+ ): Promise<{ context: GraphContext<T>; checkpointId: string }> {
287
+ const {
288
+ saveEveryNode = true,
289
+ saveOnComplete = true,
290
+ checkpointId = crypto.randomUUID(),
291
+ breakpoints = [],
292
+ runId,
293
+ initialContext,
294
+ } = config;
295
+
296
+ this._interrupted = false;
297
+ this._interruptCheckpoint = null;
298
+ this._checkpointCounter = 0;
299
+ this._breakpoints = new Set(breakpoints);
300
+
301
+ if (initialContext) {
302
+ const base = this._initialContext ? structuredClone(this._initialContext) : this.context;
303
+ const previousMessages = (this.context as any)?.messages;
304
+ const mergedContext = { ...base, ...initialContext };
305
+ if (previousMessages && Array.isArray(previousMessages) && previousMessages.length > 0) {
306
+ (mergedContext as any).messages = previousMessages;
307
+ }
308
+ const validationResult = this.validator?.safeParse(mergedContext);
309
+ if (!validationResult?.success) {
310
+ const errors = validationResult?.error?.issues.map(
311
+ (err) => `${err.path.join(".")}: ${err.message}`
312
+ );
313
+ throw new Error(`Context validation failed: ${errors?.join(", ")}`);
314
+ }
315
+ this.context = validationResult.data as GraphContext<T>;
316
+ }
317
+
318
+ if (this.context) {
319
+ const validationResult = this.validator?.safeParse(this.context);
320
+ if (!validationResult?.success) {
321
+ const errors = validationResult?.error?.issues.map(
322
+ (err) => `${err.path.join(".")}: ${err.message}`
323
+ );
324
+ throw new Error(`Context validation failed: ${errors?.join(", ")}`);
325
+ }
326
+ }
327
+
328
+ this.eventEmitter.emit("graphStarted", { name: this.name });
329
+
330
+ const runIdResolved = runId || crypto.randomUUID();
331
+
332
+ let hooks: NodeExecutionHooks<T> | undefined;
333
+ if (saveEveryNode) {
334
+ hooks = {
335
+ onBeforeExecute: async (nodeName, ctx) => {
336
+ const isBreakpoint = this._breakpoints.has(nodeName);
337
+ if (isBreakpoint) {
338
+ const cpId = `${checkpointId}-${++this._checkpointCounter}`;
339
+ const cp: Checkpoint<T> = {
340
+ id: cpId,
341
+ graphName: this.name,
342
+ runId: runIdResolved,
343
+ nodeName,
344
+ nextNodes: [nodeName],
345
+ context: structuredClone(ctx),
346
+ metadata: {
347
+ createdAt: Date.now(),
348
+ awaitingApproval: true,
349
+ },
350
+ };
351
+ this._interruptCheckpoint = cp;
352
+ await adapter.save(cp);
353
+ throw new CheckpointAwaitApprovalError(
354
+ `Awaiting approval at breakpoint "${nodeName}"`,
355
+ cpId
356
+ );
357
+ }
358
+ },
359
+ onBeforeExecuteNext: async (nodeName, ctx, nextNodes) => {
360
+ if (this._interrupted) {
361
+ const cpId = `${checkpointId}-${++this._checkpointCounter}`;
362
+ const cp: Checkpoint<T> = {
363
+ id: cpId,
364
+ graphName: this.name,
365
+ runId: runIdResolved,
366
+ nodeName,
367
+ nextNodes,
368
+ context: this.getContext(),
369
+ metadata: {
370
+ createdAt: Date.now(),
371
+ interrupted: true,
372
+ },
373
+ };
374
+ this._interruptCheckpoint = cp;
375
+ await adapter.save(cp);
376
+ throw new CheckpointInterruptError(
377
+ `Execution interrupted at node "${nodeName}"`,
378
+ cpId
379
+ );
380
+ }
381
+
382
+ const cpId = `${checkpointId}-${++this._checkpointCounter}`;
383
+ const cp: Checkpoint<T> = {
384
+ id: cpId,
385
+ graphName: this.name,
386
+ runId: runIdResolved,
387
+ nodeName,
388
+ nextNodes,
389
+ context: this.getContext(),
390
+ metadata: { createdAt: Date.now() },
391
+ };
392
+ await adapter.save(cp);
393
+ },
394
+ };
395
+ }
396
+
397
+ try {
398
+ const node = this.nodes.get(startNode);
399
+ if (!node) throw new Error(`Node "${startNode}" not found`);
400
+
401
+ await this.nodeExecutor.executeNode(
402
+ startNode,
403
+ this.context,
404
+ false,
405
+ hooks
406
+ );
407
+
408
+ if (saveOnComplete) {
409
+ const cpId = `${checkpointId}-${++this._checkpointCounter}`;
410
+ const cp: Checkpoint<T> = {
411
+ id: cpId,
412
+ graphName: this.name,
413
+ runId: runIdResolved,
414
+ nodeName: "__completed__",
415
+ nextNodes: [],
416
+ context: this.getContext(),
417
+ metadata: { createdAt: Date.now() },
418
+ };
419
+ await adapter.save(cp);
420
+ }
421
+
422
+ this.eventEmitter.emit("graphCompleted", {
423
+ name: this.name,
424
+ context: this.context,
425
+ });
426
+
427
+ return { context: this.getContext(), checkpointId };
428
+ } catch (error) {
429
+ if (
430
+ error instanceof CheckpointInterruptError ||
431
+ error instanceof CheckpointAwaitApprovalError
432
+ ) {
433
+ this.eventEmitter.emit("graphError", { name: this.name, error });
434
+ throw error;
435
+ }
436
+ if (saveOnComplete) {
437
+ const cpId = `${checkpointId}-${++this._checkpointCounter}`;
438
+ const cp: Checkpoint<T> = {
439
+ id: cpId,
440
+ graphName: this.name,
441
+ runId: runIdResolved,
442
+ nodeName: "__error__",
443
+ nextNodes: [],
444
+ context: this.getContext(),
445
+ metadata: {
446
+ createdAt: Date.now(),
447
+ error: (error as Error).message,
448
+ },
449
+ };
450
+ await adapter.save(cp);
451
+ }
452
+ this.eventEmitter.emit("graphError", { name: this.name, error });
453
+ this.globalErrorHandler?.(error as Error, this.context);
454
+ throw error;
455
+ }
456
+ }
457
+
458
+ /**
459
+ * Resumes execution from a saved checkpoint
460
+ * @param checkpointId - ID of the checkpoint to resume from
461
+ * @param adapter - Checkpoint persistence adapter
462
+ * @returns Final context after execution
463
+ */
464
+ public async resumeFromCheckpoint(
465
+ checkpointId: string,
466
+ adapter: ICheckpointAdapter,
467
+ contextModifications?: Partial<Record<string, any>>
468
+ ): Promise<GraphContext<T>> {
469
+ const checkpoint = await adapter.load(checkpointId);
470
+ if (!checkpoint) {
471
+ throw new Error(`Checkpoint "${checkpointId}" not found`);
472
+ }
473
+
474
+ if (checkpoint.nodeName === "__completed__") {
475
+ return checkpoint.context as GraphContext<T>;
476
+ }
477
+
478
+ let resumeContext = checkpoint.context;
479
+ if (contextModifications) {
480
+ resumeContext = { ...checkpoint.context, ...contextModifications };
481
+ }
482
+
483
+ const validationResult = this.validator?.safeParse(resumeContext);
484
+ if (!validationResult?.success) {
485
+ const errors = validationResult?.error?.issues.map(
486
+ (err) => `${err.path.join(".")}: ${err.message}`
487
+ );
488
+ throw new Error(`Context validation failed: ${errors?.join(", ")}`);
489
+ }
490
+ this.context = validationResult.data as GraphContext<T>;
491
+
492
+ this.eventEmitter.emit("graphStarted", { name: this.name });
493
+
494
+ this._interrupted = false;
495
+ this._interruptCheckpoint = null;
496
+ this._checkpointCounter = 0;
497
+
498
+ const hooks: NodeExecutionHooks<T> = {
499
+ onBeforeExecuteNext: async (nodeName, ctx, nextNodes) => {
500
+ const cpId = `${checkpointId}-${++this._checkpointCounter}`;
501
+ if (this._interrupted) {
502
+ const cp: Checkpoint<T> = {
503
+ id: cpId,
504
+ graphName: this.name,
505
+ nodeName,
506
+ nextNodes,
507
+ context: this.getContext(),
508
+ metadata: { createdAt: Date.now(), interrupted: true },
509
+ };
510
+ this._interruptCheckpoint = cp;
511
+ await adapter.save(cp);
512
+ throw new CheckpointInterruptError(
513
+ `Execution interrupted at node "${nodeName}"`,
514
+ cpId
515
+ );
516
+ }
517
+
518
+ const cp: Checkpoint<T> = {
519
+ id: cpId,
520
+ graphName: this.name,
521
+ nodeName,
522
+ nextNodes,
523
+ context: this.getContext(),
524
+ metadata: { createdAt: Date.now() },
525
+ };
526
+ await adapter.save(cp);
527
+ },
528
+ };
529
+
530
+ try {
531
+ for (const nextNode of checkpoint.nextNodes) {
532
+ await this.nodeExecutor.executeNode(
533
+ nextNode,
534
+ this.context,
535
+ false,
536
+ hooks
537
+ );
538
+ }
539
+
540
+ const cpId = `${checkpointId}-${++this._checkpointCounter}`;
541
+ const cp: Checkpoint<T> = {
542
+ id: cpId,
543
+ graphName: this.name,
544
+ nodeName: "__completed__",
545
+ nextNodes: [],
546
+ context: this.getContext(),
547
+ metadata: { createdAt: Date.now() },
548
+ };
549
+ await adapter.save(cp);
550
+
551
+ this.eventEmitter.emit("graphCompleted", {
552
+ name: this.name,
553
+ context: this.context,
554
+ });
555
+
556
+ return this.getContext();
557
+ } catch (error) {
558
+ if (error instanceof CheckpointInterruptError) {
559
+ this.eventEmitter.emit("graphError", { name: this.name, error });
560
+ throw error;
561
+ }
562
+ const cpId = `${checkpointId}-${++this._checkpointCounter}`;
563
+ const cp: Checkpoint<T> = {
564
+ id: cpId,
565
+ graphName: this.name,
566
+ nodeName: "__error__",
567
+ nextNodes: [],
568
+ context: this.getContext(),
569
+ metadata: { createdAt: Date.now(), error: (error as Error).message },
570
+ };
571
+ await adapter.save(cp);
572
+ this.eventEmitter.emit("graphError", { name: this.name, error });
573
+ this.globalErrorHandler?.(error as Error, this.context);
574
+ throw error;
575
+ }
576
+ }
577
+
578
+ /**
579
+ * Interrupts the current execution and saves a checkpoint
580
+ */
581
+ public interrupt(): void {
582
+ this._interrupted = true;
583
+ }
584
+
585
+ /**
586
+ * Lists all checkpoints for this graph
587
+ * @param adapter - Checkpoint persistence adapter
588
+ * @returns Array of checkpoints sorted by creation date (newest first)
589
+ */
590
+ public async listCheckpoints(
591
+ adapter: ICheckpointAdapter
592
+ ): Promise<Checkpoint<T>[]> {
593
+ return adapter.list(this.name);
594
+ }
595
+
596
+ /**
597
+ * Gets checkpoint history for a specific run
598
+ * @param runId - Run identifier
599
+ * @param adapter - Checkpoint persistence adapter
600
+ * @returns Checkpoints for the specified run, sorted newest first
601
+ */
602
+ public async getCheckpointHistory(
603
+ runId: string,
604
+ adapter: ICheckpointAdapter
605
+ ): Promise<Checkpoint<T>[]> {
606
+ const all = await adapter.list(this.name);
607
+ return all.filter((cp) => cp.runId === runId);
608
+ }
609
+
262
610
  /**
263
611
  * Emits an event to trigger event-based nodes
264
612
  * @param {string} eventName - Name of the event to emit
@@ -313,12 +661,12 @@ export class GraphFlow<T extends ZodSchema> {
313
661
  // Parse the new context
314
662
  const validationResult = definition.schema.safeParse(definition.context);
315
663
  if (!validationResult.success) {
316
- const errors = validationResult.error.errors.map(
664
+ const errors = validationResult.error.issues.map(
317
665
  (err) => `${err.path.join(".")}: ${err.message}`
318
666
  );
319
667
  throw new Error(`Context validation failed: ${errors.join(", ")}`);
320
668
  }
321
- this.context = validationResult.data;
669
+ this.context = validationResult.data as GraphContext<T>;
322
670
  this.validator = definition.schema;
323
671
 
324
672
  // Store entry node and graph events
@@ -430,3 +778,23 @@ export class GraphFlow<T extends ZodSchema> {
430
778
  return this.execute(nodeName, { input: text });
431
779
  }
432
780
  }
781
+
782
+ export class CheckpointInterruptError extends Error {
783
+ constructor(
784
+ message: string,
785
+ public readonly checkpointId: string
786
+ ) {
787
+ super(message);
788
+ this.name = "CheckpointInterruptError";
789
+ }
790
+ }
791
+
792
+ export class CheckpointAwaitApprovalError extends Error {
793
+ constructor(
794
+ message: string,
795
+ public readonly checkpointId: string
796
+ ) {
797
+ super(message);
798
+ this.name = "CheckpointAwaitApprovalError";
799
+ }
800
+ }
@@ -1,8 +1,10 @@
1
- import { IEventEmitter } from "interfaces";
1
+ import { IEventEmitter, ICheckpointAdapter } from "interfaces";
2
2
  import { BehaviorSubject, Subject } from "rxjs";
3
3
  import { ZodSchema } from "zod";
4
- import { GraphContext, GraphEvent, GraphNodeConfig } from "../types";
4
+ import { Checkpoint, GraphContext, GraphEvent, GraphNodeConfig } from "../types";
5
5
  import { GraphEventManager } from "./event-manager";
6
+ import { SendAPI } from "./send-api";
7
+ import { applyReducers } from "./reducer";
6
8
 
7
9
  /**
8
10
  * Represents a node in the graph that can execute operations and manage state
@@ -16,6 +18,15 @@ export interface GraphLogger {
16
18
  addLog: (message: string, data?: any) => void;
17
19
  }
18
20
 
21
+ export interface NodeExecutionHooks<T extends ZodSchema> {
22
+ onBeforeExecute?: (nodeName: string, context: GraphContext<T>) => Promise<void>;
23
+ onBeforeExecuteNext?: (
24
+ nodeName: string,
25
+ context: GraphContext<T>,
26
+ nextNodes: string[]
27
+ ) => Promise<void>;
28
+ }
29
+
19
30
  export class GraphNode<T extends ZodSchema> {
20
31
  private lastStateEvent: GraphEvent<T> | null = null;
21
32
  private eventEmitter: IEventEmitter;
@@ -81,16 +92,22 @@ export class GraphNode<T extends ZodSchema> {
81
92
  * @param context - The current graph context
82
93
  * @param params - Input data for the node
83
94
  * @param triggeredByEvent - Whether the execution was triggered by an event
95
+ * @param hooks - Optional execution hooks
84
96
  * @throws Error if the node is not found or execution fails
85
97
  */
86
98
  public async executeNode(
87
99
  nodeName: string,
88
100
  context: GraphContext<T>,
89
- triggeredByEvent: boolean = false
101
+ triggeredByEvent: boolean = false,
102
+ hooks?: NodeExecutionHooks<T>
90
103
  ): Promise<void> {
91
104
  const node = this.nodes.get(nodeName);
92
105
  if (!node) throw new Error(`Node "${nodeName}" not found.`);
93
106
 
107
+ if (hooks?.onBeforeExecute) {
108
+ await hooks.onBeforeExecute(nodeName, context);
109
+ }
110
+
94
111
  const nodeContext = { ...context };
95
112
  this.emitEvent("nodeStarted", { name: nodeName, context: nodeContext });
96
113
 
@@ -105,7 +122,6 @@ export class GraphNode<T extends ZodSchema> {
105
122
  if (oldValue === value) return true;
106
123
 
107
124
  target[prop.toString()] = value;
108
- // Mettre à jour le contexte global
109
125
  context[prop.toString() as keyof typeof context] = value;
110
126
 
111
127
  this.emitEvent("nodeStateChanged", {
@@ -126,14 +142,53 @@ export class GraphNode<T extends ZodSchema> {
126
142
  await this.executeWithRetry(node, contextProxy, nodeName);
127
143
  this.emitEvent("nodeCompleted", { name: nodeName, context: nodeContext });
128
144
 
129
- if (!triggeredByEvent && node.next) {
145
+ // ====== HANDOFF / COMMAND DETECTION ======
146
+ const command = (context as any)._handoff || (context as any)._command;
147
+ if (command?.goto) {
148
+ if (command.graph === "PARENT") {
149
+ return; // Stop here; parent orchestrator checks context._handoff
150
+ }
151
+ if (this.nodes.has(command.goto)) {
152
+ if (command.update) Object.assign(context, command.update);
153
+ await this.executeNode(command.goto, context, false, hooks);
154
+ return;
155
+ }
156
+ }
157
+
158
+ if (!triggeredByEvent && (node.next || (node as any).send)) {
130
159
  const nextNodes =
131
160
  typeof node.next === "function" ? node.next(contextProxy) : node.next;
132
161
 
133
- // Vérifier d'abord les conditions de tous les nœuds suivants
134
- const nextNodeConfigs = Array.isArray(nextNodes)
135
- ? nextNodes
136
- : [nextNodes];
162
+ // ====== SEND API (Fan-out dynamique) ======
163
+ if ((node as any).send) {
164
+ const sends = (node as any).send(contextProxy);
165
+ const branchResults = await SendAPI.processSends(
166
+ sends,
167
+ context,
168
+ (nodeName: string, ctx: any) => this.executeNode(nodeName, ctx, false, hooks)
169
+ );
170
+
171
+ // Merge avec reducers
172
+ const merged = applyReducers(
173
+ context,
174
+ branchResults,
175
+ (node as any).reducers || []
176
+ );
177
+ Object.assign(context, merged);
178
+
179
+ // Si un joinNode est spécifié (dans parallel), l'exécuter
180
+ const joinNode = (node as any).parallel?.joinNode;
181
+ if (joinNode) {
182
+ await this.executeNode(joinNode, context, false, hooks);
183
+ }
184
+
185
+ return; // Pas de next séquentiel après Send
186
+ }
187
+
188
+ // Filtrer les valeurs nulles/undefined
189
+ const nextNodeConfigs = (Array.isArray(nextNodes) ? nextNodes : [nextNodes]).filter(
190
+ (n) => n != null
191
+ );
137
192
  const validNextNodes = nextNodeConfigs
138
193
  .map((nextNode) => {
139
194
  const nextNodeName =
@@ -143,14 +198,63 @@ export class GraphNode<T extends ZodSchema> {
143
198
  return {
144
199
  name: nextNodeName,
145
200
  condition,
146
- isValid: !condition || condition(contextProxy),
201
+ isValid: !condition || (condition && condition(contextProxy)),
147
202
  };
148
203
  })
149
204
  .filter((n) => n.isValid);
150
205
 
151
- // Sinon, exécuter les autres nœuds valides
206
+ const nextNodeNames = validNextNodes.map((n) => n.name);
207
+
208
+ if (hooks?.onBeforeExecuteNext) {
209
+ await hooks.onBeforeExecuteNext(nodeName, context, nextNodeNames);
210
+ }
211
+
212
+ // ====== PARALLÉLISME FORK-JOIN ======
213
+ if ((node as any).parallel?.enabled) {
214
+ const { joinNode, reducers, mergeStrategy } = (node as any).parallel;
215
+
216
+ // Fork : cloner le contexte pour chaque branche
217
+ const branchContexts = validNextNodes.map((n, i: number) => ({
218
+ nodeName: n.name,
219
+ context: structuredClone(context),
220
+ branchId: `${n.name}_${i}`,
221
+ }));
222
+
223
+ // Exécution parallèle (Promise.all)
224
+ const branchResults = await Promise.all(
225
+ branchContexts.map(async ({ nodeName, context: ctx, branchId }: any) => {
226
+ await this.executeNode(nodeName, ctx, false, hooks);
227
+ return { branchId, context: ctx };
228
+ })
229
+ );
230
+
231
+ // Join : merger les résultats
232
+ if (reducers && reducers.length > 0) {
233
+ const merged = applyReducers(context, branchResults, reducers);
234
+ Object.assign(context, merged);
235
+ } else if (mergeStrategy === "isolated") {
236
+ branchResults.forEach(({ branchId, context: ctx }: any) => {
237
+ (context as any)[`branch_${branchId}`] = ctx;
238
+ });
239
+ } else {
240
+ // deep-merge par défaut
241
+ const { deepMerge } = require("./reducer");
242
+ const merged = deepMerge(context, ...branchResults.map((r: any) => r.context));
243
+ Object.assign(context, merged);
244
+ }
245
+
246
+ // Si un joinNode est spécifié, l'exécuter
247
+ if (joinNode) {
248
+ await this.executeNode(joinNode, context, false, hooks);
249
+ }
250
+
251
+ return;
252
+ }
253
+
254
+ // ====== SÉQUENTIEL (logique existante) ======
152
255
  for (const nextNode of validNextNodes) {
153
- await this.executeNode(nextNode.name, context, false);
256
+ await this.executeNode(nextNode.name, context, false, hooks);
257
+ if ((context as any)._handoff || (context as any)._command) break;
154
258
  }
155
259
  }
156
260
  } catch (error) {
@@ -0,0 +1,40 @@
1
+ import { z } from 'zod';
2
+ import { ToolRegistry, PlanStep } from './registry';
3
+
4
+ export const PlanSchema = z.object({
5
+ goal: z.string(),
6
+ steps: z.array(
7
+ z.object({
8
+ node: z.string(),
9
+ params: z.record(z.string(), z.any()).optional(),
10
+ description: z.string().optional(),
11
+ })
12
+ ),
13
+ });
14
+
15
+ export type Plan = z.infer<typeof PlanSchema>;
16
+
17
+ export async function generatePlan(
18
+ userIntent: string,
19
+ registry: ToolRegistry,
20
+ llmCall: (prompt: string) => Promise<string>
21
+ ): Promise<Plan> {
22
+ const availableTools = registry.list();
23
+
24
+ const prompt = `You are a workflow planner. Generate a structured plan as JSON with "goal" (string) and "steps" (array of { node: string, params?: Record<string, any>, description?: string }).
25
+ Only use tools from the available list.
26
+
27
+ Available tools:
28
+ ${availableTools.map(t => `- ${t.name}: ${t.description}`).join('\n')}
29
+
30
+ User intent: ${userIntent}
31
+
32
+ Respond with valid JSON only.`;
33
+
34
+ const response = await llmCall(prompt);
35
+ return PlanSchema.parse(JSON.parse(response));
36
+ }
37
+
38
+ export function renderPlan(plan: Plan): string {
39
+ return `Goal: ${plan.goal}\nSteps:\n${plan.steps.map((s, i) => `${i + 1}. ${s.node}${s.description ? ` (${s.description})` : ''}`).join('\n')}`;
40
+ }