@synergenius/flow-weaver 0.33.1 → 0.44.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 (922) hide show
  1. package/LICENSE +201 -226
  2. package/NOTICE +13 -0
  3. package/README.md +152 -244
  4. package/dist/agent/agent-loop.d.ts +4 -2
  5. package/dist/agent/cli-session.d.ts +3 -3
  6. package/dist/agent/cli-session.js +511 -438
  7. package/dist/agent/cli-spawn-config.d.ts +4 -4
  8. package/dist/agent/gate.d.ts +164 -0
  9. package/dist/agent/index.d.ts +4 -4
  10. package/dist/agent/index.js +174 -28
  11. package/dist/agent/mcp-bridge.d.ts +1 -1
  12. package/dist/agent/mcp-bridge.js +114 -128
  13. package/dist/agent/mcp-tool-server.d.ts +2 -2
  14. package/dist/agent/mcp-tool-server.js +147 -189
  15. package/dist/agent/profiles.d.ts +69 -0
  16. package/dist/agent/providers/anthropic.d.ts +2 -4
  17. package/dist/agent/providers/claude-cli.d.ts +4 -5
  18. package/dist/agent/providers/openai-compat.d.ts +8 -1
  19. package/dist/agent/streaming.d.ts +2 -2
  20. package/dist/agent/types.d.ts +16 -10
  21. package/dist/api/builder.d.ts +3 -3
  22. package/dist/api/compile.d.ts +9 -4
  23. package/dist/api/durable-validation.d.ts +15 -0
  24. package/dist/api/generate-in-place.d.ts +21 -19
  25. package/dist/api/generate.d.ts +21 -16
  26. package/dist/api/generated-module/local-node-functions.d.ts +24 -0
  27. package/dist/api/generated-module/module-format.d.ts +23 -0
  28. package/dist/api/generated-module/module-writer.d.ts +34 -0
  29. package/dist/api/generated-module/node-type-imports.d.ts +39 -0
  30. package/dist/api/generated-module/preamble.d.ts +16 -0
  31. package/dist/api/generated-module/workflow-functions.d.ts +29 -0
  32. package/dist/api/graph-identity.d.ts +39 -0
  33. package/dist/api/helpers.d.ts +4 -60
  34. package/dist/api/in-place/built-in-nodes.d.ts +18 -0
  35. package/dist/api/in-place/function-body.d.ts +21 -0
  36. package/dist/api/in-place/fw-imports.d.ts +30 -0
  37. package/dist/api/in-place/macro-coverage.d.ts +14 -0
  38. package/dist/api/in-place/node-type-functions.d.ts +18 -0
  39. package/dist/api/in-place/node-type-jsdoc.d.ts +20 -0
  40. package/dist/api/in-place/orphaned-node-types.d.ts +16 -0
  41. package/dist/api/in-place/runtime-section.d.ts +16 -0
  42. package/dist/api/in-place/signature.d.ts +47 -0
  43. package/dist/api/in-place/source-file.d.ts +19 -0
  44. package/dist/api/in-place/workflow-jsdoc.d.ts +19 -0
  45. package/dist/api/index.d.ts +18 -21
  46. package/dist/api/index.js +259 -53
  47. package/dist/api/inline-engine.generated.d.ts +3 -0
  48. package/dist/api/inline-runtime.d.ts +10 -2
  49. package/dist/api/manipulation/connections.d.ts +1 -1
  50. package/dist/api/manipulation/index.d.ts +8 -8
  51. package/dist/api/manipulation/node-types.d.ts +1 -1
  52. package/dist/api/manipulation/nodes.d.ts +3 -13
  53. package/dist/api/manipulation/ports.d.ts +1 -1
  54. package/dist/api/manipulation/scopes.d.ts +1 -1
  55. package/dist/api/manipulation/workflow.d.ts +1 -1
  56. package/dist/api/modify-operation.d.ts +0 -2
  57. package/dist/api/parse.d.ts +22 -1
  58. package/dist/api/port-references.d.ts +66 -0
  59. package/dist/api/query.d.ts +18 -2
  60. package/dist/api/templates.d.ts +1 -1
  61. package/dist/api/transform.d.ts +1 -1
  62. package/dist/api/validate.d.ts +1 -1
  63. package/dist/api/validation-registry.d.ts +2 -2
  64. package/dist/artifacts/brief.d.ts +43 -0
  65. package/dist/artifacts/index.d.ts +31 -0
  66. package/dist/artifacts/pdf.d.ts +19 -0
  67. package/dist/ast/builder.d.ts +3 -3
  68. package/dist/ast/index.d.ts +4 -4
  69. package/dist/ast/index.js +60 -5
  70. package/dist/ast/serialization-node.d.ts +1 -1
  71. package/dist/ast/serialization.d.ts +1 -1
  72. package/dist/ast/types.d.ts +82 -291
  73. package/dist/ast/workflow-utils.d.ts +4 -4
  74. package/dist/built-in-nodes/coercion-types.d.ts +1 -1
  75. package/dist/built-in-nodes/delay.d.ts +3 -1
  76. package/dist/built-in-nodes/generated-registry.d.ts +1 -1
  77. package/dist/built-in-nodes/index.d.ts +6 -5
  78. package/dist/built-in-nodes/index.js +79 -5
  79. package/dist/built-in-nodes/invoke-workflow.d.ts +2 -1
  80. package/dist/built-in-nodes/mock-types.d.ts +45 -14
  81. package/dist/built-in-nodes/sleep.d.ts +12 -0
  82. package/dist/built-in-nodes/wait-for-agent.d.ts +2 -1
  83. package/dist/built-in-nodes/wait-for-event.d.ts +2 -1
  84. package/dist/chevrotain-parser/coerce-parser.d.ts +1 -1
  85. package/dist/chevrotain-parser/connect-parser.d.ts +1 -1
  86. package/dist/chevrotain-parser/grammar-diagrams.d.ts +1 -1
  87. package/dist/chevrotain-parser/index.d.ts +20 -23
  88. package/dist/chevrotain-parser/node-parser.d.ts +7 -8
  89. package/dist/chevrotain-parser/parse-line.d.ts +54 -0
  90. package/dist/chevrotain-parser/tokens.d.ts +0 -17
  91. package/dist/chevrotain-parser/trigger-cancel-parser.d.ts +6 -1
  92. package/dist/chunks/chunk-4EUSHAY6.js +298 -0
  93. package/dist/chunks/chunk-4KDUEOFD.js +197 -0
  94. package/dist/chunks/chunk-5Y3AIUWY.js +911 -0
  95. package/dist/chunks/chunk-6KMVP6AU.js +20 -0
  96. package/dist/chunks/chunk-6PNJORFL.js +128 -0
  97. package/dist/chunks/chunk-7AAQNGRH.js +2001 -0
  98. package/dist/chunks/chunk-7YYKTPJ5.js +22705 -0
  99. package/dist/chunks/chunk-A5MBOFVY.js +33 -0
  100. package/dist/chunks/chunk-AXNQRVJB.js +18 -0
  101. package/dist/chunks/chunk-B6HQ6YS5.js +572 -0
  102. package/dist/chunks/chunk-CY3RNVML.js +296 -0
  103. package/dist/chunks/chunk-CYHYDLV4.js +653 -0
  104. package/dist/chunks/chunk-CZBCCK4Y.js +82 -0
  105. package/dist/chunks/chunk-DCMGQP5V.js +505 -0
  106. package/dist/chunks/chunk-DIAA66GL.js +72 -0
  107. package/dist/chunks/chunk-DUO6H5PR.js +20 -0
  108. package/dist/chunks/chunk-E5WN7IGO.js +125 -0
  109. package/dist/chunks/chunk-EFGFXXQF.js +184 -0
  110. package/dist/chunks/chunk-F3RTZV2A.js +2811 -0
  111. package/dist/chunks/chunk-FMTLP5ZX.js +1397 -0
  112. package/dist/chunks/chunk-HKZLQJDV.js +79 -0
  113. package/dist/chunks/chunk-INDEVYEC.js +146 -0
  114. package/dist/chunks/chunk-JQTF4R5L.js +390 -0
  115. package/dist/chunks/chunk-KMCAYNUM.js +331 -0
  116. package/dist/chunks/chunk-KMWCCOUJ.js +1444 -0
  117. package/dist/chunks/chunk-KU3CLJI2.js +338 -0
  118. package/dist/chunks/chunk-NDSTGMKR.js +3300 -0
  119. package/dist/chunks/chunk-NQNLUAPO.js +505 -0
  120. package/dist/chunks/chunk-O2U2LO57.js +466 -0
  121. package/dist/chunks/chunk-OOQG7UPP.js +457 -0
  122. package/dist/chunks/chunk-OZQAW5ZG.js +112 -0
  123. package/dist/chunks/chunk-P2CVDGHR.js +487 -0
  124. package/dist/chunks/chunk-P44RIZ7C.js +592 -0
  125. package/dist/chunks/chunk-PEZCT37T.js +1475 -0
  126. package/dist/chunks/chunk-PKWSAW6O.js +152 -0
  127. package/dist/chunks/chunk-Q6MDDZMT.js +4373 -0
  128. package/dist/chunks/chunk-QDE4Z7KW.js +6 -0
  129. package/dist/chunks/chunk-QJDAVSNY.js +8 -0
  130. package/dist/chunks/chunk-QYPORSLO.js +7552 -0
  131. package/dist/chunks/chunk-R4QGNK34.js +183 -0
  132. package/dist/chunks/chunk-REEYC73I.js +3002 -0
  133. package/dist/chunks/chunk-SEWDMQ6Q.js +46 -0
  134. package/dist/chunks/chunk-TAIUWKZB.js +3057 -0
  135. package/dist/chunks/chunk-TN4YZ3O7.js +196 -0
  136. package/dist/chunks/chunk-TRMFB43C.js +143 -0
  137. package/dist/chunks/chunk-VO4QXG2X.js +1016 -0
  138. package/dist/chunks/chunk-VP2P3BPA.js +1002 -0
  139. package/dist/chunks/chunk-VQ7H33J4.js +2176 -0
  140. package/dist/chunks/chunk-VWA7MCV2.js +105 -0
  141. package/dist/chunks/chunk-XAV22WD7.js +253 -0
  142. package/dist/chunks/chunk-YSPBPZDV.js +148 -0
  143. package/dist/chunks/chunk-ZKEGXO73.js +282 -0
  144. package/dist/chunks/chunk-ZMGN6F3S.js +4256 -0
  145. package/dist/chunks/grammar-diagrams-AI7VDXOM.js +14 -0
  146. package/dist/chunks/index.min-ECJD6GZC.js +37 -0
  147. package/dist/chunks/manifest-EPTR5MYH.js +21 -0
  148. package/dist/chunks/openapi-document-6TCGVDUW.js +69 -0
  149. package/dist/chunks/registry-K2U5KUTY.js +23 -0
  150. package/dist/chunks/serialization-node-UGY6CFH6.js +38 -0
  151. package/dist/chunks/validate-GEKSZPIN.js +24 -0
  152. package/dist/chunks/validation-registry-IQZX3UE3.js +7 -0
  153. package/dist/chunks/validator-VXFHLPDW.js +26 -0
  154. package/dist/chunks/workflow-executor-KBGFKHNR.js +36 -0
  155. package/dist/cli/commands/agents.d.ts +16 -0
  156. package/dist/cli/commands/artifact.d.ts +10 -0
  157. package/dist/cli/commands/compile.d.ts +0 -30
  158. package/dist/cli/commands/console.d.ts +32 -0
  159. package/dist/cli/commands/context.d.ts +0 -3
  160. package/dist/cli/commands/describe.js +386 -352
  161. package/dist/cli/commands/dev.d.ts +9 -4
  162. package/dist/cli/commands/diagram.d.ts +3 -5
  163. package/dist/cli/commands/doctor.d.ts +27 -4
  164. package/dist/cli/commands/doctor.js +3307 -633
  165. package/dist/cli/commands/export.d.ts +6 -4
  166. package/dist/cli/commands/grammar.d.ts +0 -3
  167. package/dist/cli/commands/implement.d.ts +1 -1
  168. package/dist/cli/commands/init/agent-handoff.d.ts +28 -0
  169. package/dist/cli/commands/init/config.d.ts +3 -0
  170. package/dist/cli/commands/init/files.d.ts +12 -0
  171. package/dist/cli/commands/init/naming.d.ts +13 -0
  172. package/dist/cli/commands/init/output.d.ts +12 -0
  173. package/dist/cli/commands/init/setup.d.ts +21 -0
  174. package/dist/cli/commands/init/types.d.ts +53 -0
  175. package/dist/cli/commands/init-personas.d.ts +9 -1
  176. package/dist/cli/commands/init.d.ts +24 -88
  177. package/dist/cli/commands/market.d.ts +1 -1
  178. package/dist/cli/commands/mcp-setup.d.ts +1 -4
  179. package/dist/cli/commands/modify.d.ts +0 -5
  180. package/dist/cli/commands/openapi.d.ts +9 -11
  181. package/dist/cli/commands/run.d.ts +0 -4
  182. package/dist/cli/commands/serve.d.ts +24 -26
  183. package/dist/cli/commands/status.d.ts +1 -1
  184. package/dist/cli/exports.d.ts +3 -4
  185. package/dist/cli/exports.js +124 -23
  186. package/dist/cli/flow-weaver-agents-H653446S.mjs +81 -0
  187. package/dist/cli/flow-weaver-artifact-WBFYTW76.mjs +58 -0
  188. package/dist/cli/flow-weaver-chunk-265CEK74.mjs +2 -0
  189. package/dist/cli/flow-weaver-chunk-2C7PZCV5.mjs +186 -0
  190. package/dist/cli/flow-weaver-chunk-3BSYCWPL.mjs +3109 -0
  191. package/dist/cli/flow-weaver-chunk-3MKUQP3D.mjs +547 -0
  192. package/dist/cli/flow-weaver-chunk-3ZLMPQTH.mjs +27 -0
  193. package/dist/cli/flow-weaver-chunk-4DVY73ML.mjs +280 -0
  194. package/dist/cli/flow-weaver-chunk-54M4KNEL.mjs +200 -0
  195. package/dist/cli/flow-weaver-chunk-55QMUZIA.mjs +256 -0
  196. package/dist/cli/flow-weaver-chunk-6ZUJ7LMX.mjs +2003 -0
  197. package/dist/cli/flow-weaver-chunk-7ET6N32V.mjs +419 -0
  198. package/dist/cli/flow-weaver-chunk-7G63RR4K.mjs +8880 -0
  199. package/dist/cli/flow-weaver-chunk-A6M5K3W7.mjs +4418 -0
  200. package/dist/cli/flow-weaver-chunk-AA3NATMX.mjs +154 -0
  201. package/dist/cli/flow-weaver-chunk-APX6MQ5A.mjs +5652 -0
  202. package/dist/cli/flow-weaver-chunk-BHCC5FE5.mjs +17 -0
  203. package/dist/cli/flow-weaver-chunk-DM4BBRRU.mjs +35 -0
  204. package/dist/cli/flow-weaver-chunk-DRN7KPWY.mjs +168 -0
  205. package/dist/cli/flow-weaver-chunk-EKWF27G6.mjs +23 -0
  206. package/dist/cli/flow-weaver-chunk-EM5HWQ4R.mjs +338 -0
  207. package/dist/cli/flow-weaver-chunk-FPPPU2DG.mjs +226 -0
  208. package/dist/cli/flow-weaver-chunk-GAQXZHNO.mjs +3005 -0
  209. package/dist/cli/flow-weaver-chunk-GBUNNP33.mjs +1329 -0
  210. package/dist/cli/flow-weaver-chunk-HMAKDE55.mjs +636 -0
  211. package/dist/cli/flow-weaver-chunk-HQ3ZAN44.mjs +367 -0
  212. package/dist/cli/flow-weaver-chunk-I4APCXYN.mjs +21442 -0
  213. package/dist/cli/flow-weaver-chunk-IJJ4JXTL.mjs +2297 -0
  214. package/dist/cli/flow-weaver-chunk-J7EPZW2I.mjs +33 -0
  215. package/dist/cli/flow-weaver-chunk-KOEMJHLG.mjs +83 -0
  216. package/dist/cli/flow-weaver-chunk-M6CBWQKJ.mjs +271 -0
  217. package/dist/cli/flow-weaver-chunk-MHJ4N652.mjs +1580 -0
  218. package/dist/cli/flow-weaver-chunk-MKAFQWLP.mjs +202 -0
  219. package/dist/cli/flow-weaver-chunk-MMV2XGD3.mjs +3291 -0
  220. package/dist/cli/flow-weaver-chunk-MSI2UJES.mjs +125 -0
  221. package/dist/cli/flow-weaver-chunk-N767YRAI.mjs +48 -0
  222. package/dist/cli/flow-weaver-chunk-NQKKWDGF.mjs +56 -0
  223. package/dist/cli/flow-weaver-chunk-NYZDQYFU.mjs +45 -0
  224. package/dist/cli/flow-weaver-chunk-OMVWSNHJ.mjs +14 -0
  225. package/dist/cli/flow-weaver-chunk-PUWZ47H5.mjs +2188 -0
  226. package/dist/cli/flow-weaver-chunk-QOPRVDES.mjs +46 -0
  227. package/dist/cli/flow-weaver-chunk-RIWE7YTR.mjs +216 -0
  228. package/dist/cli/flow-weaver-chunk-S63Q3JIU.mjs +789 -0
  229. package/dist/cli/flow-weaver-chunk-T7X5A23H.mjs +558 -0
  230. package/dist/cli/flow-weaver-chunk-TLV3VZUN.mjs +2 -0
  231. package/dist/cli/flow-weaver-chunk-TS5P3PIN.mjs +194 -0
  232. package/dist/cli/flow-weaver-chunk-U3EO3X4B.mjs +649 -0
  233. package/dist/cli/flow-weaver-chunk-UNFS3NQP.mjs +34 -0
  234. package/dist/cli/flow-weaver-chunk-V6DHWFQG.mjs +2811 -0
  235. package/dist/cli/flow-weaver-chunk-VXWNLYQU.mjs +9 -0
  236. package/dist/cli/flow-weaver-chunk-W3YNK26P.mjs +149 -0
  237. package/dist/cli/flow-weaver-chunk-XG2WKXYZ.mjs +324 -0
  238. package/dist/cli/flow-weaver-chunk-YLSRZWFK.mjs +2219 -0
  239. package/dist/cli/flow-weaver-chunk-YVPURWS6.mjs +40 -0
  240. package/dist/cli/flow-weaver-chunk-Z44JK332.mjs +582 -0
  241. package/dist/cli/flow-weaver-chunk-Z5ZJPNSY.mjs +517 -0
  242. package/dist/cli/flow-weaver-chunk-ZQALO25T.mjs +594 -0
  243. package/dist/cli/flow-weaver-compile-A2CABDSB.mjs +37 -0
  244. package/dist/cli/flow-weaver-console-6EBHDBTN.mjs +71 -0
  245. package/dist/cli/flow-weaver-context-ECLYANFF.mjs +17 -0
  246. package/dist/cli/flow-weaver-context-ZRUMW2KE.mjs +69 -0
  247. package/dist/cli/flow-weaver-create-WIP4EFNP.mjs +124 -0
  248. package/dist/cli/flow-weaver-deployment-WJJRK7NO.mjs +14 -0
  249. package/dist/cli/flow-weaver-describe-XDIFF5LI.mjs +41 -0
  250. package/dist/cli/flow-weaver-dev-LG2NSQAU.mjs +196 -0
  251. package/dist/cli/flow-weaver-diagram-3EVQARQE.mjs +52 -0
  252. package/dist/cli/flow-weaver-diagram-7LR7O4M2.mjs +44 -0
  253. package/dist/cli/flow-weaver-diff-USF7DJLU.mjs +85 -0
  254. package/dist/cli/flow-weaver-docs-QU2ZOXKH.mjs +96 -0
  255. package/dist/cli/flow-weaver-doctor-K447YWHR.mjs +43 -0
  256. package/dist/cli/flow-weaver-export-LAS6N56Y.mjs +140 -0
  257. package/dist/cli/flow-weaver-grammar-RIRUS3Q6.mjs +49 -0
  258. package/dist/cli/flow-weaver-grammar-diagrams-WXRTW5SK.mjs +15 -0
  259. package/dist/cli/flow-weaver-implement-5JG6BCFZ.mjs +114 -0
  260. package/dist/cli/flow-weaver-index.min-OR5SIHXD.mjs +39 -0
  261. package/dist/cli/flow-weaver-init-34YZNPQX.mjs +972 -0
  262. package/dist/cli/flow-weaver-init-personas-NOGZTQQ2.mjs +48 -0
  263. package/dist/cli/flow-weaver-manifest-4JNUSEB3.mjs +18 -0
  264. package/dist/cli/flow-weaver-market-WA4CKHKV.mjs +444 -0
  265. package/dist/cli/flow-weaver-mcp-setup-O26MGXSD.mjs +22 -0
  266. package/dist/cli/flow-weaver-migrate-VFVEUTPH.mjs +119 -0
  267. package/dist/cli/flow-weaver-modify-VM3JP5K6.mjs +97 -0
  268. package/dist/cli/flow-weaver-openapi-IRBWI3HM.mjs +71 -0
  269. package/dist/cli/flow-weaver-openapi-document-7N6YMPG3.mjs +30 -0
  270. package/dist/cli/flow-weaver-pack-commands-OS2QRXAK.mjs +146 -0
  271. package/dist/cli/flow-weaver-registry-5MLFRPPT.mjs +25 -0
  272. package/dist/cli/flow-weaver-run-DSTLSTHR.mjs +555 -0
  273. package/dist/cli/flow-weaver-serialization-node-LE6PCG4M.mjs +50 -0
  274. package/dist/cli/flow-weaver-serve-NVLCLSOW.mjs +192 -0
  275. package/dist/cli/flow-weaver-server-7IERLVXE.mjs +2925 -0
  276. package/dist/cli/flow-weaver-server-KWF4PXYC.mjs +19112 -0
  277. package/dist/cli/flow-weaver-status-75W2S3YB.mjs +138 -0
  278. package/dist/cli/flow-weaver-strip-AZPXUYVA.mjs +79 -0
  279. package/dist/cli/flow-weaver-templates-DSNMB6K7.mjs +72 -0
  280. package/dist/cli/flow-weaver-validate-A4UWDQN6.mjs +19 -0
  281. package/dist/cli/flow-weaver-validate-GRBZ5W4C.mjs +296 -0
  282. package/dist/cli/flow-weaver-validation-registry-BINGUNXX.mjs +9 -0
  283. package/dist/cli/flow-weaver-validator-TY56CI42.mjs +21 -0
  284. package/dist/cli/flow-weaver-watch-OPPERXL6.mjs +114 -0
  285. package/dist/cli/flow-weaver-workflow-executor-6AHYPXAN.mjs +26 -0
  286. package/dist/cli/flow-weaver.mjs +3557 -89498
  287. package/dist/cli/index.d.ts +5 -2
  288. package/dist/cli/pack-commands-needed.d.ts +12 -0
  289. package/dist/cli/program.d.ts +14 -0
  290. package/dist/cli/templates/ai/mock-provider.d.ts +1 -1
  291. package/dist/cli/templates/index.d.ts +1 -8
  292. package/dist/cli/templates/nodes/agent-router.d.ts +1 -1
  293. package/dist/cli/templates/nodes/aggregator.d.ts +1 -1
  294. package/dist/cli/templates/nodes/conversation-memory.d.ts +1 -1
  295. package/dist/cli/templates/nodes/http.d.ts +1 -1
  296. package/dist/cli/templates/nodes/human-approval.d.ts +1 -1
  297. package/dist/cli/templates/nodes/json-extractor.d.ts +1 -1
  298. package/dist/cli/templates/nodes/llm-call.d.ts +1 -1
  299. package/dist/cli/templates/nodes/prompt-template.d.ts +1 -1
  300. package/dist/cli/templates/nodes/rag-retriever.d.ts +1 -1
  301. package/dist/cli/templates/nodes/tool-executor.d.ts +1 -1
  302. package/dist/cli/templates/nodes/transformer.d.ts +1 -1
  303. package/dist/cli/templates/nodes/validator.d.ts +1 -1
  304. package/dist/cli/templates/shared/approval-types.d.ts +1 -1
  305. package/dist/cli/templates/shared/case.d.ts +14 -0
  306. package/dist/cli/templates/shared/llm-types.d.ts +4 -4
  307. package/dist/cli/templates/workflows/aggregator.d.ts +1 -1
  308. package/dist/cli/templates/workflows/ai-agent.d.ts +1 -1
  309. package/dist/cli/templates/workflows/ai-chat.d.ts +1 -1
  310. package/dist/cli/templates/workflows/ai-rag.d.ts +1 -1
  311. package/dist/cli/templates/workflows/ai-react.d.ts +1 -1
  312. package/dist/cli/templates/workflows/approval.d.ts +10 -0
  313. package/dist/cli/templates/workflows/conditional.d.ts +2 -2
  314. package/dist/cli/templates/workflows/error-handler.d.ts +2 -2
  315. package/dist/cli/templates/workflows/foreach.d.ts +1 -1
  316. package/dist/cli/templates/workflows/sequential.d.ts +1 -1
  317. package/dist/cli/templates/workflows/webhook.d.ts +1 -1
  318. package/dist/cli/utils/interactive.d.ts +6 -0
  319. package/dist/cli/utils/json-option.d.ts +8 -0
  320. package/dist/cli/utils/logger.d.ts +2 -0
  321. package/dist/compiler/durable-source-proof.d.ts +23 -0
  322. package/dist/compiler/executable-artifact.d.ts +29 -0
  323. package/dist/compiler/index.d.ts +4 -0
  324. package/dist/compiler/index.js +36 -0
  325. package/dist/console/app.js +106 -0
  326. package/dist/console/assets/synergenius.svg +18 -0
  327. package/dist/console/author.d.ts +32 -0
  328. package/dist/console/cli-catalog.d.ts +21 -0
  329. package/dist/console/cli-run.d.ts +35 -0
  330. package/dist/console/cli-run.js +46 -0
  331. package/dist/console/debug.d.ts +67 -0
  332. package/dist/console/diff-view.d.ts +96 -0
  333. package/dist/console/export.d.ts +36 -0
  334. package/dist/console/git.d.ts +27 -0
  335. package/dist/console/index.d.ts +4 -0
  336. package/dist/console/index.html +16 -0
  337. package/dist/console/index.js +203 -0
  338. package/dist/console/packs.d.ts +100 -0
  339. package/dist/console/request-guard.d.ts +10 -0
  340. package/dist/console/respond.d.ts +16 -0
  341. package/dist/console/router.d.ts +64 -0
  342. package/dist/console/routes-agents.d.ts +14 -0
  343. package/dist/console/routes-project.d.ts +3 -0
  344. package/dist/console/routes-runs.d.ts +3 -0
  345. package/dist/console/routes-services.d.ts +7 -0
  346. package/dist/console/routes-tools.d.ts +3 -0
  347. package/dist/console/runs.d.ts +69 -0
  348. package/dist/console/scan.d.ts +49 -0
  349. package/dist/console/schema.d.ts +74 -0
  350. package/dist/console/server.d.ts +34 -0
  351. package/dist/console/server.js +43264 -0
  352. package/dist/console/services.d.ts +119 -0
  353. package/dist/console/source.d.ts +23 -0
  354. package/dist/console/status.d.ts +68 -0
  355. package/dist/console/styles.css +1023 -0
  356. package/dist/console/terminals.d.ts +22 -0
  357. package/dist/console/workflow-view.d.ts +153 -0
  358. package/dist/constants.d.ts +5 -1
  359. package/dist/constants.js +56 -167
  360. package/dist/context/index.d.ts +10 -0
  361. package/dist/context/index.js +14 -191
  362. package/dist/coordinator/agent-gate.d.ts +107 -0
  363. package/dist/coordinator/bundle-digest.d.ts +20 -0
  364. package/dist/coordinator/clock-tick.d.ts +4 -0
  365. package/dist/coordinator/effect-receipts.d.ts +10 -0
  366. package/dist/coordinator/errors.d.ts +31 -0
  367. package/dist/coordinator/file-store.d.ts +3 -0
  368. package/dist/coordinator/gate-labeling.d.ts +33 -0
  369. package/dist/coordinator/gate-resolution.d.ts +28 -0
  370. package/dist/coordinator/index.d.ts +12 -0
  371. package/dist/coordinator/index.js +107 -0
  372. package/dist/coordinator/memory-store.d.ts +3 -0
  373. package/dist/coordinator/params.d.ts +18 -0
  374. package/dist/coordinator/run-annotations.d.ts +6 -0
  375. package/dist/coordinator/run-context.d.ts +11 -0
  376. package/dist/coordinator/run-ending.d.ts +5 -0
  377. package/dist/coordinator/run-outcome.d.ts +31 -0
  378. package/dist/coordinator/run-resume.d.ts +6 -0
  379. package/dist/coordinator/run-start.d.ts +4 -0
  380. package/dist/coordinator/run-store.d.ts +275 -0
  381. package/dist/coordinator/run-trace.d.ts +41 -0
  382. package/dist/coordinator/run-views.d.ts +12 -0
  383. package/dist/coordinator/runs-dir.d.ts +26 -0
  384. package/dist/coordinator/store.d.ts +67 -0
  385. package/dist/coordinator/time.d.ts +39 -0
  386. package/dist/coordinator/workflow-selection.d.ts +6 -0
  387. package/dist/deployment/index.d.ts +11 -16
  388. package/dist/deployment/index.js +541 -50
  389. package/dist/deployment/targets/base.d.ts +11 -13
  390. package/dist/deployment/targets/openapi-parts.d.ts +92 -0
  391. package/dist/diagram/arms.d.ts +70 -0
  392. package/dist/diagram/ascii-renderer.d.ts +1 -1
  393. package/dist/diagram/geometry.d.ts +22 -29
  394. package/dist/diagram/graph/bounds.d.ts +30 -0
  395. package/dist/diagram/graph/metrics.d.ts +21 -0
  396. package/dist/diagram/graph/nodes.d.ts +33 -0
  397. package/dist/diagram/graph/placement.d.ts +22 -0
  398. package/dist/diagram/graph/ports.d.ts +23 -0
  399. package/dist/diagram/graph/routing.d.ts +40 -0
  400. package/dist/diagram/graph/scopes.d.ts +30 -0
  401. package/dist/diagram/index.d.ts +15 -23
  402. package/dist/diagram/index.js +632 -111
  403. package/dist/diagram/labels.d.ts +12 -0
  404. package/dist/diagram/lanes.d.ts +93 -0
  405. package/dist/diagram/layout.d.ts +1 -1
  406. package/dist/diagram/material-symbols.d.ts +7 -0
  407. package/dist/diagram/orthogonal-router.d.ts +15 -51
  408. package/dist/diagram/process-view.d.ts +79 -0
  409. package/dist/diagram/spine.d.ts +25 -0
  410. package/dist/diagram/theme.d.ts +3 -5
  411. package/dist/diagram/types.d.ts +6 -20
  412. package/dist/diff/index.js +53 -9
  413. package/dist/diff/types.d.ts +1 -5
  414. package/dist/doc-metadata/extractors/annotations.d.ts +0 -4
  415. package/dist/doc-metadata/extractors/cli-commands.d.ts +2 -1
  416. package/dist/doc-metadata/extractors/core-metadata.d.ts +19 -4
  417. package/dist/doc-metadata/extractors/error-codes.d.ts +1 -1
  418. package/dist/doc-metadata/extractors/mcp-tools.d.ts +7 -3
  419. package/dist/doc-metadata/index.d.ts +1 -2
  420. package/dist/doc-metadata/index.js +2368 -9
  421. package/dist/doc-metadata/types.d.ts +7 -24
  422. package/dist/docs/guide.d.ts +33 -0
  423. package/dist/docs/index.d.ts +7 -4
  424. package/dist/docs/index.js +298 -298
  425. package/dist/docs/pack-topics.d.ts +18 -0
  426. package/dist/editor-completions/annotationValues.d.ts +1 -1
  427. package/dist/editor-completions/contextParser.d.ts +3 -2
  428. package/dist/editor-completions/dataTypes.d.ts +1 -1
  429. package/dist/editor-completions/goToDefinition.d.ts +1 -1
  430. package/dist/editor-completions/index.d.ts +8 -8
  431. package/dist/editor-completions/index.js +1244 -175
  432. package/dist/editor-completions/jsDocAnnotations.d.ts +1 -1
  433. package/dist/editor-completions/modifierCompletions.d.ts +1 -1
  434. package/dist/export/index.d.ts +7 -1
  435. package/dist/generated-branding.js +8 -21
  436. package/dist/generated-version.d.ts +1 -1
  437. package/dist/generated-version.js +7 -3
  438. package/dist/generator/annotation-generator.d.ts +84 -0
  439. package/dist/generator/async-detection.d.ts +1 -1
  440. package/dist/{body-generator.d.ts → generator/body-generator.d.ts} +7 -3
  441. package/dist/generator/code-utils.d.ts +15 -60
  442. package/dist/generator/connection-reads.d.ts +94 -0
  443. package/dist/generator/control-flow-plan.d.ts +74 -0
  444. package/dist/generator/control-flow.d.ts +1 -1
  445. package/dist/generator/exit-assembly.d.ts +11 -0
  446. package/dist/generator/index.d.ts +4 -5
  447. package/dist/generator/index.js +34 -11
  448. package/dist/generator/input-port-values.d.ts +22 -0
  449. package/dist/generator/{scope-function-generator.d.ts → node-arguments.d.ts} +76 -1
  450. package/dist/generator/node-invocation.d.ts +74 -0
  451. package/dist/{node-types-generator.d.ts → generator/node-types-generator.d.ts} +3 -2
  452. package/dist/generator/scope-closure.d.ts +23 -0
  453. package/dist/generator/scoped-child.d.ts +49 -0
  454. package/dist/{sugar-optimizer.d.ts → generator/sugar-optimizer.d.ts} +1 -1
  455. package/dist/generator/unified.d.ts +14 -2
  456. package/dist/generator/workflow-generator.d.ts +37 -0
  457. package/dist/index.d.ts +29 -26
  458. package/dist/index.js +1322 -92
  459. package/dist/jsdoc-port-sync/apply-diff.d.ts +15 -0
  460. package/dist/jsdoc-port-sync/callback-signature.d.ts +17 -0
  461. package/dist/jsdoc-port-sync/diff.d.ts +5 -7
  462. package/dist/jsdoc-port-sync/incomplete-lines.d.ts +41 -0
  463. package/dist/jsdoc-port-sync/index.d.ts +11 -11
  464. package/dist/jsdoc-port-sync/index.js +88 -45
  465. package/dist/jsdoc-port-sync/jsdoc-to-signature.d.ts +66 -0
  466. package/dist/jsdoc-port-sync/port-parser.d.ts +6 -24
  467. package/dist/jsdoc-port-sync/port-tag-placement.d.ts +55 -0
  468. package/dist/jsdoc-port-sync/scoped-ports.d.ts +21 -0
  469. package/dist/jsdoc-port-sync/signature-parser.d.ts +8 -1
  470. package/dist/jsdoc-port-sync/signature-to-jsdoc.d.ts +77 -0
  471. package/dist/jsdoc-port-sync/sync.d.ts +4 -1
  472. package/dist/marketplace/index.d.ts +5 -3
  473. package/dist/marketplace/index.js +62 -10
  474. package/dist/marketplace/install.d.ts +24 -0
  475. package/dist/marketplace/manifest.d.ts +1 -1
  476. package/dist/marketplace/npmrc.d.ts +24 -0
  477. package/dist/marketplace/registry.d.ts +46 -11
  478. package/dist/marketplace/types.d.ts +41 -24
  479. package/dist/marketplace/validator.d.ts +1 -1
  480. package/dist/mcp/debug-session.d.ts +2 -4
  481. package/dist/mcp/dist-imports.d.ts +12 -0
  482. package/dist/mcp/response-utils.d.ts +11 -9
  483. package/dist/mcp/server.d.ts +0 -1
  484. package/dist/mcp/tools-context.d.ts +11 -0
  485. package/dist/mcp/tools-diagram.d.ts +1 -2
  486. package/dist/mcp/tools-export.d.ts +2 -2
  487. package/dist/mcp/tools-marketplace.d.ts +1 -1
  488. package/dist/mcp/tools-run.d.ts +17 -0
  489. package/dist/mcp/tools-workflow.d.ts +3 -0
  490. package/dist/mcp/types.d.ts +4 -14
  491. package/dist/mcp/workflow-executor.d.ts +57 -19
  492. package/dist/npm-packages.d.ts +1 -1
  493. package/dist/npm-packages.js +10 -473
  494. package/dist/parser/annotation-parser.d.ts +88 -0
  495. package/dist/parser/annotation-suggestion.d.ts +23 -0
  496. package/dist/parser/durable-effect-contract.d.ts +10 -0
  497. package/dist/parser/expression-references.d.ts +101 -0
  498. package/dist/parser/external-node-types.d.ts +69 -0
  499. package/dist/{function-like.d.ts → parser/function-like.d.ts} +10 -3
  500. package/dist/parser/generated-sections.d.ts +25 -0
  501. package/dist/parser/import-resolution.d.ts +67 -0
  502. package/dist/parser/import-stub.d.ts +29 -0
  503. package/dist/parser/jsdoc/config-types.d.ts +209 -0
  504. package/dist/parser/jsdoc/graph-tags.d.ts +54 -0
  505. package/dist/parser/jsdoc/node-type-block.d.ts +23 -0
  506. package/dist/parser/jsdoc/parse-line-once.d.ts +11 -0
  507. package/dist/parser/jsdoc/port-tags.d.ts +42 -0
  508. package/dist/parser/jsdoc/runtime-tags.d.ts +65 -0
  509. package/dist/parser/jsdoc/signature-types.d.ts +52 -0
  510. package/dist/parser/jsdoc/workflow-block.d.ts +22 -0
  511. package/dist/parser/jsdoc-parser.d.ts +23 -0
  512. package/dist/parser/macro-expansion.d.ts +80 -0
  513. package/dist/parser/module-resolution.d.ts +38 -0
  514. package/dist/parser/node-inference.d.ts +39 -0
  515. package/dist/parser/npm-node-types.d.ts +24 -0
  516. package/dist/parser/pack-handlers.d.ts +12 -0
  517. package/dist/parser/path-data-resolution.d.ts +75 -0
  518. package/dist/parser/port-inference.d.ts +15 -0
  519. package/dist/{resolve-package-types.d.ts → parser/resolve-package-types.d.ts} +4 -0
  520. package/dist/parser/serialize-deploy-annotations.d.ts +19 -0
  521. package/dist/parser/tag-registry.d.ts +22 -0
  522. package/dist/parser/workflow-extraction.d.ts +39 -0
  523. package/dist/runtime/ExecutionContext.d.ts +87 -99
  524. package/dist/runtime/continuation-core.d.ts +147 -0
  525. package/dist/runtime/continuation.d.ts +48 -0
  526. package/dist/runtime/debug-controller.d.ts +7 -22
  527. package/dist/runtime/durable-execution.d.ts +176 -0
  528. package/dist/runtime/events.d.ts +16 -1
  529. package/dist/runtime/executable-module-contract.d.ts +16 -0
  530. package/dist/runtime/index.d.ts +13 -10
  531. package/dist/runtime/index.js +947 -9
  532. package/dist/runtime/strict-json.d.ts +15 -0
  533. package/dist/server/access.d.ts +12 -0
  534. package/dist/server/api.d.ts +126 -0
  535. package/dist/server/callback-delivery.d.ts +62 -0
  536. package/dist/server/callback-url.d.ts +44 -0
  537. package/dist/server/context.d.ts +35 -0
  538. package/dist/server/http-error.d.ts +10 -0
  539. package/dist/server/index.d.ts +7 -1
  540. package/dist/server/index.js +125 -6
  541. package/dist/server/openapi-document.d.ts +33 -0
  542. package/dist/server/openapi.d.ts +32 -0
  543. package/dist/server/respond.d.ts +35 -0
  544. package/dist/server/route-params.d.ts +17 -0
  545. package/dist/server/route-plan.d.ts +41 -0
  546. package/dist/server/routes-catalog.d.ts +5 -0
  547. package/dist/server/routes-declared.d.ts +12 -0
  548. package/dist/server/routes-runs.d.ts +8 -0
  549. package/dist/server/run-driver.d.ts +58 -0
  550. package/dist/server/run-view.d.ts +26 -0
  551. package/dist/server/transport.d.ts +35 -0
  552. package/dist/server/types.d.ts +143 -52
  553. package/dist/server/webhook-server.d.ts +12 -38
  554. package/dist/server/workflow-registry.d.ts +7 -4
  555. package/dist/service-registry.d.ts +49 -0
  556. package/dist/service-registry.js +123 -0
  557. package/dist/testing/assertions.d.ts +2 -2
  558. package/dist/testing/index.d.ts +14 -13
  559. package/dist/testing/index.js +582 -24
  560. package/dist/testing/mock-approval.d.ts +3 -5
  561. package/dist/testing/mock-llm.d.ts +2 -3
  562. package/dist/testing/recorder.d.ts +5 -6
  563. package/dist/testing/replayer.d.ts +6 -7
  564. package/dist/testing/run-store-check.d.ts +3 -0
  565. package/dist/testing/token-tracker.d.ts +2 -2
  566. package/dist/{type-mappings.d.ts → types/type-mappings.d.ts} +13 -1
  567. package/dist/utils/error-utils.d.ts +4 -2
  568. package/dist/utils/port-ordering.d.ts +2 -2
  569. package/dist/utils/port-tag-utils.d.ts +1 -1
  570. package/dist/validation/agent-detection.d.ts +17 -5
  571. package/dist/validation/agent-rules.d.ts +6 -7
  572. package/dist/validation/core-rules.d.ts +49 -0
  573. package/dist/validation/design-rules.d.ts +9 -3
  574. package/dist/validation/rule-registry.d.ts +3 -3
  575. package/dist/validation/rules/connections.d.ts +27 -0
  576. package/dist/validation/rules/context.d.ts +11 -0
  577. package/dist/validation/rules/cycles.d.ts +17 -0
  578. package/dist/validation/rules/data-flow.d.ts +19 -0
  579. package/dist/validation/rules/scope-topology.d.ts +35 -0
  580. package/dist/validation/rules/type-compatibility.d.ts +30 -0
  581. package/dist/validation/type-checker.d.ts +39 -0
  582. package/dist/validation/validator-helpers.d.ts +31 -0
  583. package/dist/validation/validator.d.ts +30 -0
  584. package/docs/reference/advanced-annotations.md +277 -60
  585. package/docs/reference/built-in-nodes.md +164 -94
  586. package/docs/reference/cancellation.md +44 -0
  587. package/docs/reference/cli-reference.md +252 -234
  588. package/docs/reference/compilation.md +36 -109
  589. package/docs/reference/concepts.md +80 -63
  590. package/docs/reference/console.md +169 -0
  591. package/docs/reference/debugging.md +26 -57
  592. package/docs/reference/deployment.md +217 -143
  593. package/docs/reference/durable-gates.md +445 -0
  594. package/docs/reference/error-codes.md +90 -43
  595. package/docs/reference/export-interface.md +91 -26
  596. package/docs/reference/iterative-development.md +50 -28
  597. package/docs/reference/jsdoc-grammar.md +66 -311
  598. package/docs/reference/library.md +250 -0
  599. package/docs/reference/marketplace.md +301 -152
  600. package/docs/reference/mcp-tools.md +102 -0
  601. package/docs/reference/node-conversion.md +84 -59
  602. package/docs/reference/orientation.md +68 -0
  603. package/docs/reference/scaffold.md +5 -4
  604. package/docs/reference/tutorial.md +106 -166
  605. package/docs/reference/visual-reference.md +1 -1
  606. package/package.json +85 -50
  607. package/dist/agent/agent-loop.js +0 -156
  608. package/dist/agent/cli-spawn-config.js +0 -65
  609. package/dist/agent/device-connection.d.ts +0 -79
  610. package/dist/agent/device-connection.js +0 -184
  611. package/dist/agent/env-allowlist.js +0 -60
  612. package/dist/agent/providers/anthropic.js +0 -198
  613. package/dist/agent/providers/claude-cli.js +0 -161
  614. package/dist/agent/providers/openai-compat.js +0 -205
  615. package/dist/agent/providers/platform.d.ts +0 -23
  616. package/dist/agent/providers/platform.js +0 -132
  617. package/dist/agent/streaming.js +0 -186
  618. package/dist/agent/types.js +0 -20
  619. package/dist/annotation-generator.d.ts +0 -50
  620. package/dist/annotation-generator.js +0 -743
  621. package/dist/api/builder.js +0 -345
  622. package/dist/api/command-runner.js +0 -787
  623. package/dist/api/compile.js +0 -148
  624. package/dist/api/extract-types.js +0 -57
  625. package/dist/api/generate-in-place.js +0 -1477
  626. package/dist/api/generate.js +0 -514
  627. package/dist/api/helpers.js +0 -285
  628. package/dist/api/inline-runtime.js +0 -526
  629. package/dist/api/manipulation/connections.js +0 -151
  630. package/dist/api/manipulation/index.js +0 -41
  631. package/dist/api/manipulation/node-types.js +0 -200
  632. package/dist/api/manipulation/nodes.js +0 -355
  633. package/dist/api/manipulation/ports.js +0 -228
  634. package/dist/api/manipulation/scopes.js +0 -156
  635. package/dist/api/manipulation/workflow.js +0 -116
  636. package/dist/api/modify-operation.js +0 -177
  637. package/dist/api/parse.js +0 -115
  638. package/dist/api/patterns.d.ts +0 -112
  639. package/dist/api/patterns.js +0 -303
  640. package/dist/api/query.js +0 -840
  641. package/dist/api/templates.js +0 -117
  642. package/dist/api/transform.js +0 -40
  643. package/dist/api/validate.js +0 -64
  644. package/dist/api/validation-registry.js +0 -10
  645. package/dist/api/workflow-file-operations.js +0 -180
  646. package/dist/ast/builder.js +0 -395
  647. package/dist/ast/serialization-node.js +0 -30
  648. package/dist/ast/serialization.js +0 -134
  649. package/dist/ast/types.js +0 -2
  650. package/dist/ast/workflow-utils.js +0 -114
  651. package/dist/body-generator.js +0 -35
  652. package/dist/built-in-nodes/coercion-types.js +0 -61
  653. package/dist/built-in-nodes/delay.js +0 -29
  654. package/dist/built-in-nodes/generated-registry.js +0 -299
  655. package/dist/built-in-nodes/invoke-workflow.js +0 -36
  656. package/dist/built-in-nodes/mock-types.js +0 -42
  657. package/dist/built-in-nodes/wait-for-agent.js +0 -31
  658. package/dist/built-in-nodes/wait-for-event.js +0 -25
  659. package/dist/chevrotain-parser/coerce-parser.js +0 -103
  660. package/dist/chevrotain-parser/connect-parser.js +0 -136
  661. package/dist/chevrotain-parser/fan-parser.js +0 -149
  662. package/dist/chevrotain-parser/grammar-diagrams.js +0 -273
  663. package/dist/chevrotain-parser/index.js +0 -31
  664. package/dist/chevrotain-parser/map-parser.js +0 -130
  665. package/dist/chevrotain-parser/node-parser.js +0 -558
  666. package/dist/chevrotain-parser/path-parser.js +0 -140
  667. package/dist/chevrotain-parser/port-parser.js +0 -519
  668. package/dist/chevrotain-parser/position-parser.d.ts +0 -20
  669. package/dist/chevrotain-parser/position-parser.js +0 -83
  670. package/dist/chevrotain-parser/scope-parser.js +0 -104
  671. package/dist/chevrotain-parser/tokens.js +0 -429
  672. package/dist/chevrotain-parser/trigger-cancel-parser.js +0 -291
  673. package/dist/cli/commands/account.d.ts +0 -4
  674. package/dist/cli/commands/account.js +0 -50
  675. package/dist/cli/commands/ai-credentials.d.ts +0 -12
  676. package/dist/cli/commands/ai-credentials.js +0 -95
  677. package/dist/cli/commands/apikey.d.ts +0 -4
  678. package/dist/cli/commands/apikey.js +0 -64
  679. package/dist/cli/commands/auth.d.ts +0 -9
  680. package/dist/cli/commands/auth.js +0 -255
  681. package/dist/cli/commands/compile.js +0 -331
  682. package/dist/cli/commands/connect.d.ts +0 -4
  683. package/dist/cli/commands/connect.js +0 -163
  684. package/dist/cli/commands/context.js +0 -51
  685. package/dist/cli/commands/create.js +0 -139
  686. package/dist/cli/commands/deploy.d.ts +0 -6
  687. package/dist/cli/commands/deploy.js +0 -74
  688. package/dist/cli/commands/dev.js +0 -227
  689. package/dist/cli/commands/diagram.js +0 -39
  690. package/dist/cli/commands/diff.js +0 -57
  691. package/dist/cli/commands/docs.js +0 -74
  692. package/dist/cli/commands/export.js +0 -153
  693. package/dist/cli/commands/grammar.js +0 -40
  694. package/dist/cli/commands/implement.js +0 -91
  695. package/dist/cli/commands/init-personas.js +0 -541
  696. package/dist/cli/commands/init.js +0 -797
  697. package/dist/cli/commands/market.js +0 -440
  698. package/dist/cli/commands/mcp-setup.js +0 -433
  699. package/dist/cli/commands/migrate.js +0 -91
  700. package/dist/cli/commands/modify.js +0 -58
  701. package/dist/cli/commands/openapi.js +0 -71
  702. package/dist/cli/commands/org.d.ts +0 -8
  703. package/dist/cli/commands/org.js +0 -136
  704. package/dist/cli/commands/pattern.d.ts +0 -34
  705. package/dist/cli/commands/pattern.js +0 -186
  706. package/dist/cli/commands/plugin.d.ts +0 -16
  707. package/dist/cli/commands/plugin.js +0 -176
  708. package/dist/cli/commands/run.js +0 -742
  709. package/dist/cli/commands/serve.js +0 -93
  710. package/dist/cli/commands/status.js +0 -123
  711. package/dist/cli/commands/strip.js +0 -61
  712. package/dist/cli/commands/templates.js +0 -58
  713. package/dist/cli/commands/validate.js +0 -267
  714. package/dist/cli/commands/watch.js +0 -71
  715. package/dist/cli/config/credentials.d.ts +0 -15
  716. package/dist/cli/config/credentials.js +0 -43
  717. package/dist/cli/config/platform-client.d.ts +0 -123
  718. package/dist/cli/config/platform-client.js +0 -248
  719. package/dist/cli/env-setup.js +0 -12
  720. package/dist/cli/index.js +0 -850
  721. package/dist/cli/pack-commands.js +0 -122
  722. package/dist/cli/postinstall.d.ts +0 -16
  723. package/dist/cli/postinstall.js +0 -119
  724. package/dist/cli/templates/ai/mock-provider.js +0 -64
  725. package/dist/cli/templates/ai/types.js +0 -5
  726. package/dist/cli/templates/approvals/index.d.ts +0 -15
  727. package/dist/cli/templates/approvals/index.js +0 -241
  728. package/dist/cli/templates/index.js +0 -123
  729. package/dist/cli/templates/nodes/agent-router.js +0 -114
  730. package/dist/cli/templates/nodes/aggregator.js +0 -63
  731. package/dist/cli/templates/nodes/conversation-memory.js +0 -85
  732. package/dist/cli/templates/nodes/http.js +0 -80
  733. package/dist/cli/templates/nodes/human-approval.js +0 -109
  734. package/dist/cli/templates/nodes/json-extractor.js +0 -119
  735. package/dist/cli/templates/nodes/llm-call.js +0 -106
  736. package/dist/cli/templates/nodes/prompt-template.js +0 -52
  737. package/dist/cli/templates/nodes/rag-retriever.js +0 -128
  738. package/dist/cli/templates/nodes/tool-executor.js +0 -108
  739. package/dist/cli/templates/nodes/transformer.js +0 -68
  740. package/dist/cli/templates/nodes/validator.js +0 -62
  741. package/dist/cli/templates/pack-loader.js +0 -58
  742. package/dist/cli/templates/providers/index.js +0 -239
  743. package/dist/cli/templates/shared/approval-types.js +0 -31
  744. package/dist/cli/templates/shared/llm-types.js +0 -109
  745. package/dist/cli/templates/workflows/aggregator.js +0 -101
  746. package/dist/cli/templates/workflows/ai-agent.js +0 -326
  747. package/dist/cli/templates/workflows/ai-chat.js +0 -167
  748. package/dist/cli/templates/workflows/ai-rag.js +0 -184
  749. package/dist/cli/templates/workflows/ai-react.js +0 -293
  750. package/dist/cli/templates/workflows/conditional.js +0 -139
  751. package/dist/cli/templates/workflows/error-handler.js +0 -145
  752. package/dist/cli/templates/workflows/foreach.js +0 -140
  753. package/dist/cli/templates/workflows/sequential.js +0 -200
  754. package/dist/cli/templates/workflows/webhook.js +0 -158
  755. package/dist/cli/utils/cli-helpers.d.ts +0 -44
  756. package/dist/cli/utils/cli-helpers.js +0 -99
  757. package/dist/cli/utils/logger.js +0 -126
  758. package/dist/cli/utils/parse-int-strict.js +0 -17
  759. package/dist/cli/utils/safe-write.js +0 -54
  760. package/dist/deployment/config/defaults.d.ts +0 -29
  761. package/dist/deployment/config/defaults.js +0 -98
  762. package/dist/deployment/config/loader.d.ts +0 -24
  763. package/dist/deployment/config/loader.js +0 -237
  764. package/dist/deployment/config/types.d.ts +0 -117
  765. package/dist/deployment/config/types.js +0 -5
  766. package/dist/deployment/core/adapters.d.ts +0 -66
  767. package/dist/deployment/core/adapters.js +0 -156
  768. package/dist/deployment/core/executor.d.ts +0 -62
  769. package/dist/deployment/core/executor.js +0 -197
  770. package/dist/deployment/core/formatters.d.ts +0 -42
  771. package/dist/deployment/core/formatters.js +0 -146
  772. package/dist/deployment/openapi/generator.d.ts +0 -146
  773. package/dist/deployment/openapi/generator.js +0 -347
  774. package/dist/deployment/openapi/schema-converter.d.ts +0 -49
  775. package/dist/deployment/openapi/schema-converter.js +0 -192
  776. package/dist/deployment/targets/base.js +0 -855
  777. package/dist/deployment/types.d.ts +0 -140
  778. package/dist/deployment/types.js +0 -8
  779. package/dist/diagram/ascii-renderer.js +0 -528
  780. package/dist/diagram/geometry.js +0 -1267
  781. package/dist/diagram/html-viewer.d.ts +0 -21
  782. package/dist/diagram/html-viewer.js +0 -1689
  783. package/dist/diagram/layout.js +0 -143
  784. package/dist/diagram/orthogonal-router.js +0 -568
  785. package/dist/diagram/renderer.d.ts +0 -3
  786. package/dist/diagram/renderer.js +0 -266
  787. package/dist/diagram/theme.js +0 -282
  788. package/dist/diagram/types.js +0 -2
  789. package/dist/diff/WorkflowDiffer.js +0 -429
  790. package/dist/diff/formatDiff.js +0 -239
  791. package/dist/diff/impact.js +0 -119
  792. package/dist/diff/types.js +0 -35
  793. package/dist/doc-metadata/extractors/annotations.js +0 -638
  794. package/dist/doc-metadata/extractors/cli-commands.js +0 -326
  795. package/dist/doc-metadata/extractors/core-metadata.js +0 -61
  796. package/dist/doc-metadata/extractors/error-codes.js +0 -372
  797. package/dist/doc-metadata/extractors/grammar-rules.js +0 -51
  798. package/dist/doc-metadata/extractors/mcp-tools.js +0 -705
  799. package/dist/doc-metadata/extractors/plugin-api.d.ts +0 -19
  800. package/dist/doc-metadata/extractors/plugin-api.js +0 -279
  801. package/dist/doc-metadata/types.js +0 -5
  802. package/dist/editor-completions/annotationValues.js +0 -146
  803. package/dist/editor-completions/contextParser.js +0 -410
  804. package/dist/editor-completions/dataTypes.js +0 -95
  805. package/dist/editor-completions/goToDefinition.js +0 -112
  806. package/dist/editor-completions/jsDocAnnotations.js +0 -359
  807. package/dist/editor-completions/modifierCompletions.js +0 -197
  808. package/dist/editor-completions/types.js +0 -8
  809. package/dist/export/index.js +0 -212
  810. package/dist/extensions/index.d.ts +0 -16
  811. package/dist/extensions/index.js +0 -17
  812. package/dist/friendly-errors.js +0 -761
  813. package/dist/function-like.js +0 -84
  814. package/dist/generator/async-detection.js +0 -56
  815. package/dist/generator/code-utils.js +0 -551
  816. package/dist/generator/compile-target-registry.d.ts +0 -20
  817. package/dist/generator/compile-target-registry.js +0 -20
  818. package/dist/generator/control-flow.js +0 -358
  819. package/dist/generator/dev-mode-registry.d.ts +0 -27
  820. package/dist/generator/dev-mode-registry.js +0 -20
  821. package/dist/generator/scope-function-generator.js +0 -397
  822. package/dist/generator/unified.js +0 -1831
  823. package/dist/generator.d.ts +0 -54
  824. package/dist/generator.js +0 -101
  825. package/dist/jsdoc-parser.d.ts +0 -377
  826. package/dist/jsdoc-parser.js +0 -1189
  827. package/dist/jsdoc-port-sync/constants.js +0 -103
  828. package/dist/jsdoc-port-sync/diff.js +0 -319
  829. package/dist/jsdoc-port-sync/port-parser.js +0 -579
  830. package/dist/jsdoc-port-sync/rename.js +0 -256
  831. package/dist/jsdoc-port-sync/signature-parser.js +0 -559
  832. package/dist/jsdoc-port-sync/sync.js +0 -653
  833. package/dist/marketplace/manifest.js +0 -194
  834. package/dist/marketplace/registry.js +0 -198
  835. package/dist/marketplace/types.js +0 -9
  836. package/dist/marketplace/validator.js +0 -150
  837. package/dist/mcp/agent-channel.d.ts +0 -35
  838. package/dist/mcp/agent-channel.js +0 -61
  839. package/dist/mcp/auto-registration.d.ts +0 -3
  840. package/dist/mcp/auto-registration.js +0 -62
  841. package/dist/mcp/debug-session.js +0 -25
  842. package/dist/mcp/index.d.ts +0 -11
  843. package/dist/mcp/index.js +0 -10
  844. package/dist/mcp/pack-tools.js +0 -59
  845. package/dist/mcp/prompts.js +0 -68
  846. package/dist/mcp/response-utils.js +0 -97
  847. package/dist/mcp/run-registry.d.ts +0 -29
  848. package/dist/mcp/run-registry.js +0 -24
  849. package/dist/mcp/server.js +0 -63
  850. package/dist/mcp/tools-context.js +0 -51
  851. package/dist/mcp/tools-debug.js +0 -451
  852. package/dist/mcp/tools-diagram.js +0 -97
  853. package/dist/mcp/tools-docs.js +0 -62
  854. package/dist/mcp/tools-export.js +0 -222
  855. package/dist/mcp/tools-marketplace.js +0 -132
  856. package/dist/mcp/tools-model.d.ts +0 -3
  857. package/dist/mcp/tools-model.js +0 -279
  858. package/dist/mcp/tools-pattern.d.ts +0 -3
  859. package/dist/mcp/tools-pattern.js +0 -604
  860. package/dist/mcp/tools-query.js +0 -377
  861. package/dist/mcp/tools-resources.js +0 -41
  862. package/dist/mcp/tools-template.js +0 -119
  863. package/dist/mcp/tools-workflow-run.d.ts +0 -40
  864. package/dist/mcp/tools-workflow-run.js +0 -150
  865. package/dist/mcp/types.js +0 -2
  866. package/dist/mcp/workflow-executor.js +0 -242
  867. package/dist/migration/registry.js +0 -29
  868. package/dist/node-types-generator.js +0 -139
  869. package/dist/parser/tag-registry.js +0 -57
  870. package/dist/parser.d.ts +0 -232
  871. package/dist/parser.js +0 -2500
  872. package/dist/plugin/PluginPanel.d.ts +0 -12
  873. package/dist/plugin/PluginPanel.js +0 -5
  874. package/dist/plugin/index.d.ts +0 -13
  875. package/dist/plugin/index.js +0 -14
  876. package/dist/plugin/types.d.ts +0 -75
  877. package/dist/plugin/types.js +0 -8
  878. package/dist/resolve-package-types.js +0 -123
  879. package/dist/runtime/CancellationError.js +0 -20
  880. package/dist/runtime/ExecutionContext.js +0 -280
  881. package/dist/runtime/builtin-functions.js +0 -549
  882. package/dist/runtime/checkpoint.d.ts +0 -84
  883. package/dist/runtime/checkpoint.js +0 -225
  884. package/dist/runtime/debug-controller.js +0 -247
  885. package/dist/runtime/events.js +0 -2
  886. package/dist/runtime/function-registry.js +0 -66
  887. package/dist/runtime/parameter-resolver.js +0 -113
  888. package/dist/server/types.js +0 -5
  889. package/dist/server/webhook-server.js +0 -269
  890. package/dist/server/workflow-registry.js +0 -202
  891. package/dist/shared-project.js +0 -28
  892. package/dist/sugar-optimizer.js +0 -498
  893. package/dist/testing/assertions.js +0 -127
  894. package/dist/testing/mock-approval.js +0 -98
  895. package/dist/testing/mock-llm.js +0 -119
  896. package/dist/testing/recorder.js +0 -70
  897. package/dist/testing/replayer.js +0 -143
  898. package/dist/testing/token-tracker.js +0 -94
  899. package/dist/type-checker.d.ts +0 -42
  900. package/dist/type-checker.js +0 -190
  901. package/dist/type-mappings.js +0 -131
  902. package/dist/types/branded-ports.d.ts +0 -151
  903. package/dist/types/branded-ports.js +0 -121
  904. package/dist/types/index.d.ts +0 -5
  905. package/dist/types/index.js +0 -5
  906. package/dist/types.d.ts +0 -139
  907. package/dist/types.js +0 -15
  908. package/dist/utils/error-utils.js +0 -27
  909. package/dist/utils/lru-cache.js +0 -40
  910. package/dist/utils/port-ordering.js +0 -81
  911. package/dist/utils/port-tag-utils.js +0 -41
  912. package/dist/utils/string-distance.js +0 -56
  913. package/dist/validation/agent-detection.js +0 -115
  914. package/dist/validation/agent-rules.js +0 -262
  915. package/dist/validation/design-rules.js +0 -377
  916. package/dist/validation/rule-registry.js +0 -37
  917. package/dist/validator.d.ts +0 -113
  918. package/dist/validator.js +0 -1631
  919. package/docs/reference/patterns.md +0 -159
  920. package/scripts/postinstall.cjs +0 -86
  921. /package/dist/{shared-project.d.ts → parser/shared-project.d.ts} +0 -0
  922. /package/dist/{friendly-errors.d.ts → validation/friendly-errors.d.ts} +0 -0
@@ -1,1831 +0,0 @@
1
- import { extractStartPorts } from '../ast/workflow-utils.js';
2
- import { mapToTypeScript } from '../type-mappings.js';
3
- import { buildNodeArgumentsWithContext, toValidIdentifier } from './code-utils.js';
4
- import { buildControlFlowGraph, computeParallelLevels, detectBranchingChains, findAllBranchingNodes, findNodesInBranch, performKahnsTopologicalSort, isPerPortScopedChild, } from './control-flow.js';
5
- import { RESERVED_NODE_NAMES, RESERVED_PORT_NAMES, EXECUTION_STRATEGIES, isStartNode, isExitNode, isExecutePort, isSuccessPort, isFailurePort, } from '../constants.js';
6
- /**
7
- * Helper: Determine if an instance has pull execution enabled
8
- * Checks instance config first, then falls back to node type default config
9
- * Returns { enabled: boolean, triggerPort: string }
10
- */
11
- function getPullExecutionConfig(instance, nodeType) {
12
- // Check instance config first
13
- if (instance.config?.pullExecution) {
14
- const pullConfig = instance.config.pullExecution;
15
- if (typeof pullConfig === 'boolean') {
16
- return { enabled: pullConfig, triggerPort: 'execute' };
17
- }
18
- return {
19
- enabled: true,
20
- triggerPort: pullConfig.triggerPort || 'execute',
21
- };
22
- }
23
- // Fall back to node type default config
24
- if (nodeType.defaultConfig?.pullExecution) {
25
- const pullConfig = nodeType.defaultConfig.pullExecution;
26
- if (typeof pullConfig === 'boolean') {
27
- return { enabled: pullConfig, triggerPort: 'execute' };
28
- }
29
- return {
30
- enabled: true,
31
- triggerPort: pullConfig.triggerPort || 'execute',
32
- };
33
- }
34
- // No pull execution configured
35
- return { enabled: false, triggerPort: 'execute' };
36
- }
37
- /**
38
- * Generates executable TypeScript code from a workflow AST using ExecutionContext for state management.
39
- *
40
- * This is the main code generation function that transforms a visual workflow into runnable code.
41
- *
42
- * ## Algorithm Overview:
43
- * 1. **Setup Phase**: Initialize ExecutionContext, set recursion depth protection
44
- * 2. **Start Node**: Store workflow parameters as Start node outputs
45
- * 3. **Control Flow Graph**: Build CFG from connections, perform topological sort
46
- * 4. **Branch Detection**: Identify branching nodes (with onSuccess/onFailure) and their regions
47
- * 5. **Parallel Detection**: For async workflows, compute parallel levels from the CFG
48
- * and group independent nodes at the same topological depth into Promise.all() blocks
49
- * 6. **Code Generation**: For each node in execution order:
50
- * - Regular nodes: Generate direct execution with variable storage
51
- * - Parallel groups: Wrap 2+ independent nodes in `await Promise.all([...])`
52
- * - Branching nodes: Generate if/else blocks for success/failure paths
53
- * - Scoped children: Generate scope function closures (for forEach, etc.)
54
- * - Pull nodes: Generate lazy executors registered with context
55
- * 7. **Exit Node**: Collect outputs and return result object
56
- *
57
- * ## Key Concepts:
58
- * - **Parallel Execution**: Independent async nodes at the same topological level run concurrently
59
- * via Promise.all(). Sync workflows skip this since there's no event loop concurrency.
60
- * - **Branching Nodes**: Nodes with both onSuccess and onFailure ports create conditional branches
61
- * - **Per-Port Scoped Children**: Children of forEach-like nodes execute via closure functions
62
- * - **Pull Execution**: Nodes marked for lazy evaluation only run when outputs are consumed
63
- * - **Execution Index**: Each node execution gets a unique index for variable tracking
64
- *
65
- * ## Generated Code Structure:
66
- * ```typescript
67
- * const ctx = new GeneratedExecutionContext(isAsync, debugger?);
68
- * const startIdx = ctx.addExecution('Start');
69
- * ctx.setVariable({ id: 'Start', portName: 'param', ... }, value);
70
- * // ... node executions in topological order ...
71
- * const exitIdx = ctx.addExecution('Exit');
72
- * return { onSuccess: ..., onFailure: ..., ...outputs };
73
- * ```
74
- *
75
- * @param workflow - The workflow AST to generate code for
76
- * @param nodeTypes - Available node type definitions (includes workflow's nodeTypes + imports)
77
- * @param isAsync - Whether to generate async code (adds await, returns Promise)
78
- * @param production - If true, omits debug instrumentation for smaller output
79
- * @returns Generated TypeScript function body (without function signature)
80
- */
81
- export function generateControlFlowWithExecutionContext(workflow, nodeTypes, isAsync, production = false, bundleMode = false) {
82
- const lines = [];
83
- // In development mode, use the injected debugger if available
84
- if (!production) {
85
- lines.push(` const __effectiveDebugger__ = typeof __flowWeaverDebugger__ !== 'undefined' ? __flowWeaverDebugger__ : undefined;`);
86
- lines.push('');
87
- }
88
- // Recursion depth protection: prevent infinite recursion in workflows
89
- lines.push(` // Recursion depth protection`);
90
- lines.push(` const __rd__ = (params as { __rd__?: number }).__rd__ ?? 0;`);
91
- lines.push(` if (__rd__ >= 1000) {`);
92
- lines.push(` throw new Error('Max recursion depth exceeded (1000) in workflow "${workflow.functionName}"');`);
93
- lines.push(` }`);
94
- lines.push('');
95
- // In development mode, pass the effective debugger (from parameter or environment)
96
- // In production mode, omit the debugger parameter
97
- // Always pass abort signal for cancellation support
98
- // In dev mode, always treat as async so the debugger can pause execution
99
- // at breakpoints (sendStatusChangedEvent must be awaited for this to work).
100
- // Production mode respects the original isAsync to avoid overhead.
101
- if (!production) {
102
- isAsync = true; // eslint-disable-line no-param-reassign
103
- }
104
- const asyncArg = isAsync ? 'true' : 'false';
105
- if (production) {
106
- lines.push(` const ctx = new GeneratedExecutionContext(${asyncArg}, __abortSignal__);`);
107
- }
108
- else {
109
- lines.push(` const ctx = new GeneratedExecutionContext(${asyncArg}, __effectiveDebugger__, __abortSignal__);`);
110
- }
111
- lines.push('');
112
- // Debug controller: step-through debugging and checkpoint/resume
113
- // In production mode, no controller is emitted. In dev mode, the controller
114
- // resolves from globalThis (injected by executor) or falls back to a no-op.
115
- if (!production) {
116
- lines.push(` // Debug controller for step-through debugging and checkpoint/resume`);
117
- lines.push(` const __ctrl__: TDebugController = (`);
118
- lines.push(` typeof globalThis !== 'undefined' && (globalThis as unknown as { __fw_debug_controller__?: TDebugController }).__fw_debug_controller__`);
119
- lines.push(` ? (globalThis as unknown as { __fw_debug_controller__?: TDebugController }).__fw_debug_controller__`);
120
- lines.push(` : { beforeNode: () => true, afterNode: () => {} }`);
121
- lines.push(` )!;`);
122
- lines.push('');
123
- }
124
- lines.push(` const startIdx = ctx.addExecution('${RESERVED_NODE_NAMES.START}');`);
125
- const awaitPrefixTop = isAsync ? 'await ' : '';
126
- Object.keys(extractStartPorts(workflow)).forEach((portName) => {
127
- const setCall = isAsync ? `await ctx.setVariable` : `ctx.setVariable`;
128
- // STEP Port Architecture: execute comes from workflow parameter, data from params object
129
- const valueSource = isExecutePort(portName) ? 'execute' : `params.${portName}`;
130
- lines.push(` ${setCall}({ id: '${RESERVED_NODE_NAMES.START}', portName: '${portName}', executionIndex: startIdx, nodeTypeName: '${RESERVED_NODE_NAMES.START}' }, ${valueSource});`);
131
- });
132
- lines.push(` ${awaitPrefixTop}ctx.sendStatusChangedEvent({`);
133
- lines.push(` nodeTypeName: '${RESERVED_NODE_NAMES.START}',`);
134
- lines.push(` id: '${RESERVED_NODE_NAMES.START}',`);
135
- lines.push(` executionIndex: startIdx,`);
136
- lines.push(` status: 'SUCCEEDED',`);
137
- lines.push(` });`);
138
- lines.push('');
139
- const cfg = buildControlFlowGraph(workflow, nodeTypes);
140
- const executionOrder = performKahnsTopologicalSort(cfg); // Now returns instance IDs
141
- const branchingNodes = findAllBranchingNodes(workflow, nodeTypes);
142
- const allInstanceIds = new Set(workflow.instances.map((i) => i.id));
143
- const branchRegions = new Map();
144
- branchingNodes.forEach((branchInstanceId) => {
145
- const successNodes = findNodesInBranch(branchInstanceId, RESERVED_PORT_NAMES.ON_SUCCESS, workflow, allInstanceIds, branchingNodes, nodeTypes);
146
- const failureNodes = findNodesInBranch(branchInstanceId, RESERVED_PORT_NAMES.ON_FAILURE, workflow, allInstanceIds, branchingNodes, nodeTypes);
147
- branchRegions.set(branchInstanceId, { successNodes, failureNodes });
148
- });
149
- // Determine which nodes are in conditional branches (need let declaration)
150
- // Nodes in branches may not execute, so we need undefined checks for them
151
- const nodesInBranches = new Set();
152
- branchRegions.forEach((region) => {
153
- region.successNodes.forEach((n) => nodesInBranches.add(n));
154
- region.failureNodes.forEach((n) => nodesInBranches.add(n));
155
- });
156
- // Identify pull execution nodes (they also need let due to undefined check)
157
- const pullExecutionNodes = new Set();
158
- workflow.instances.forEach((instance) => {
159
- // Check both name (for npm nodes like 'npm/pkg/func') and functionName (for local nodes)
160
- const nodeType = nodeTypes.find((nt) => nt.name === instance.nodeType || nt.functionName === instance.nodeType);
161
- if (nodeType) {
162
- const pullConfig = getPullExecutionConfig(instance, nodeType);
163
- if (pullConfig.enabled) {
164
- pullExecutionNodes.add(instance.id);
165
- }
166
- }
167
- });
168
- // Identify node-level scoped children (they need let because referenced outside scope block)
169
- const nodeLevelScopedChildren = new Set();
170
- workflow.instances.forEach((instance) => {
171
- if (instance.parent && !isPerPortScopedChild(instance, workflow, nodeTypes)) {
172
- nodeLevelScopedChildren.add(instance.id);
173
- }
174
- });
175
- // Create execution index variables only for nodes that need undefined checking
176
- // Skip per-port scoped children (they're in scope functions)
177
- let hasLetDeclarations = false;
178
- workflow.instances.forEach((instance) => {
179
- if (!isPerPortScopedChild(instance, workflow, nodeTypes)) {
180
- // Nodes in branches, branching nodes, pull nodes, or scoped children need let
181
- if (nodesInBranches.has(instance.id) ||
182
- branchingNodes.has(instance.id) ||
183
- pullExecutionNodes.has(instance.id) ||
184
- nodeLevelScopedChildren.has(instance.id)) {
185
- lines.push(` let ${toValidIdentifier(instance.id)}Idx: number | undefined;`);
186
- hasLetDeclarations = true;
187
- }
188
- }
189
- });
190
- // Pre-declare _success flags for branching nodes that have downstream nodes.
191
- // These flags must be at the function's top level because downstream guards
192
- // (promoted nodes, chain guards) may reference them outside the branch block
193
- // where the branching node is generated.
194
- const topLevelSuccessFlags = new Set();
195
- branchRegions.forEach((region, nodeId) => {
196
- if (region.successNodes.size > 0 || region.failureNodes.size > 0) {
197
- const safeId = toValidIdentifier(nodeId);
198
- lines.push(` let ${safeId}_success = false;`);
199
- topLevelSuccessFlags.add(safeId);
200
- hasLetDeclarations = true;
201
- }
202
- });
203
- if (hasLetDeclarations) {
204
- lines.push('');
205
- }
206
- const instancesInMultipleBranches = new Set();
207
- allInstanceIds.forEach((instanceId) => {
208
- let branchCount = 0;
209
- branchRegions.forEach((region) => {
210
- if (region.successNodes.has(instanceId) || region.failureNodes.has(instanceId)) {
211
- branchCount++;
212
- }
213
- });
214
- if (branchCount > 1) {
215
- instancesInMultipleBranches.add(instanceId);
216
- }
217
- });
218
- branchRegions.forEach((region, _branchNode) => {
219
- instancesInMultipleBranches.forEach((instanceId) => {
220
- region.successNodes.delete(instanceId);
221
- region.failureNodes.delete(instanceId);
222
- });
223
- });
224
- // Promote nodes that appear in BOTH success and failure regions of the same
225
- // branching node. These nodes execute regardless of which branch is taken,
226
- // so they must not be nested inside either branch (which would cause duplicate
227
- // variable declarations and cancelled events for nodes that actually run).
228
- const nodesInBothBranches = new Set();
229
- branchRegions.forEach((region) => {
230
- region.successNodes.forEach((nodeId) => {
231
- if (region.failureNodes.has(nodeId)) {
232
- nodesInBothBranches.add(nodeId);
233
- }
234
- });
235
- });
236
- branchRegions.forEach((region) => {
237
- nodesInBothBranches.forEach((nodeId) => {
238
- region.successNodes.delete(nodeId);
239
- region.failureNodes.delete(nodeId);
240
- });
241
- });
242
- // Promote nodes that have DATA dependencies on nodes outside their branch.
243
- // Without this, STEP-nesting places the node before its data providers are generated.
244
- const nodesPromotedFromBranches = new Set(nodesInBothBranches);
245
- branchRegions.forEach((region, branchNodeId) => {
246
- const allBranchNodes = new Set([...region.successNodes, ...region.failureNodes]);
247
- allBranchNodes.forEach((nodeId) => {
248
- const hasExternalDataDep = workflow.connections.some((conn) => {
249
- if (conn.to.node !== nodeId)
250
- return false;
251
- if (conn.from.scope || conn.to.scope)
252
- return false;
253
- const fromNode = conn.from.node;
254
- // Dependencies on branch parent or Start are fine (already generated)
255
- if (fromNode === branchNodeId || isStartNode(fromNode))
256
- return false;
257
- // STEP connections (execute port) are handled by the guard, not data flow
258
- if (isExecutePort(conn.to.port))
259
- return false;
260
- // External dep: source is NOT in the same branch
261
- return !allBranchNodes.has(fromNode);
262
- });
263
- if (hasExternalDataDep) {
264
- nodesPromotedFromBranches.add(nodeId);
265
- }
266
- });
267
- });
268
- // Remove promoted nodes from branch regions (they'll generate at top level)
269
- branchRegions.forEach((region) => {
270
- nodesPromotedFromBranches.forEach((nodeId) => {
271
- region.successNodes.delete(nodeId);
272
- region.failureNodes.delete(nodeId);
273
- });
274
- });
275
- // Identify branching nodes whose _success flag must be tracked because
276
- // promoted nodes depend on their onSuccess/onFailure ports for STEP guards.
277
- const branchingNodesNeedingSuccessFlag = new Set();
278
- nodesPromotedFromBranches.forEach((promotedNodeId) => {
279
- workflow.connections.forEach((conn) => {
280
- if (conn.to.node === promotedNodeId && isExecutePort(conn.to.port)) {
281
- const sourceNode = conn.from.node;
282
- const sourcePort = conn.from.port;
283
- if (branchingNodes.has(sourceNode) && (isSuccessPort(sourcePort) || isFailurePort(sourcePort))) {
284
- branchingNodesNeedingSuccessFlag.add(sourceNode);
285
- }
286
- }
287
- });
288
- });
289
- // Detect sequential branching chains for flattening
290
- const branchingChains = detectBranchingChains(branchingNodes, branchRegions);
291
- const chainMembers = new Set();
292
- branchingChains.forEach((chain) => {
293
- // All non-head nodes are chain members (skip in main loop)
294
- for (let i = 1; i < chain.length; i++) {
295
- chainMembers.add(chain[i]);
296
- }
297
- });
298
- // Compute parallel levels for async workflows
299
- const perPortScopedChildrenSet = new Set();
300
- workflow.instances.forEach((instance) => {
301
- if (isPerPortScopedChild(instance, workflow, nodeTypes)) {
302
- perPortScopedChildrenSet.add(instance.id);
303
- }
304
- });
305
- const parallelGroupOf = new Map();
306
- if (isAsync) {
307
- const parallelLevels = computeParallelLevels(cfg, branchingNodes, perPortScopedChildrenSet);
308
- for (const group of parallelLevels) {
309
- if (group.length < 2)
310
- continue;
311
- // Filter out nodes that can't be parallelized
312
- const eligible = group.filter((id) => {
313
- if (nodesInBranches.has(id))
314
- return false;
315
- if (pullExecutionNodes.has(id))
316
- return false;
317
- if (nodeLevelScopedChildren.has(id))
318
- return false;
319
- if (nodesPromotedFromBranches.has(id))
320
- return false;
321
- if (chainMembers.has(id))
322
- return false;
323
- if (branchingNodes.has(id))
324
- return false;
325
- return true;
326
- });
327
- if (eligible.length >= 2) {
328
- for (const nodeId of eligible) {
329
- parallelGroupOf.set(nodeId, eligible);
330
- }
331
- }
332
- }
333
- }
334
- // Pre-declare execution indices for parallel group nodes
335
- if (parallelGroupOf.size > 0) {
336
- const declared = new Set();
337
- parallelGroupOf.forEach((_, instanceId) => {
338
- if (declared.has(instanceId))
339
- return;
340
- declared.add(instanceId);
341
- // Only declare if not already declared by earlier let declarations
342
- if (!nodesInBranches.has(instanceId) &&
343
- !branchingNodes.has(instanceId) &&
344
- !pullExecutionNodes.has(instanceId) &&
345
- !nodeLevelScopedChildren.has(instanceId)) {
346
- lines.push(` let ${toValidIdentifier(instanceId)}Idx: number | undefined;`);
347
- }
348
- });
349
- lines.push('');
350
- }
351
- const generatedNodes = new Set();
352
- const availableVars = new Map();
353
- Object.keys(extractStartPorts(workflow)).forEach((portName) => {
354
- availableVars.set(`${RESERVED_NODE_NAMES.START}.${portName}`, `params.${portName}`);
355
- });
356
- executionOrder.forEach((instanceId) => {
357
- if (isStartNode(instanceId) || isExitNode(instanceId) || generatedNodes.has(instanceId)) {
358
- return;
359
- }
360
- // Find the instance and its node type
361
- const instance = workflow.instances.find((i) => i.id === instanceId);
362
- if (!instance) {
363
- lines.push(` // Node '${instanceId}' skipped: instance not found in workflow`);
364
- return;
365
- }
366
- // Skip per-port scoped children (they're in scope functions)
367
- // Include node-level scoped children (they're in scope blocks)
368
- if (isPerPortScopedChild(instance, workflow, nodeTypes)) {
369
- return;
370
- }
371
- // Check both name (for npm nodes like 'npm/pkg/func') and functionName (for local nodes)
372
- const nodeType = nodeTypes.find((nt) => nt.name === instance.nodeType || nt.functionName === instance.nodeType);
373
- if (!nodeType) {
374
- lines.push(` // Node '${instance.id}' skipped: type '${instance.nodeType}' not found`);
375
- return;
376
- }
377
- // Handle parallel groups: emit Promise.all when hitting first node of a group
378
- if (parallelGroupOf.has(instanceId)) {
379
- const group = parallelGroupOf.get(instanceId);
380
- const ungeneratedGroup = group.filter((id) => !generatedNodes.has(id));
381
- if (ungeneratedGroup.length >= 2) {
382
- generateParallelGroupWithContext(ungeneratedGroup, workflow, nodeTypes, availableVars, lines, generatedNodes, ' ', isAsync, 'ctx', bundleMode, branchingNodes, production);
383
- // Generate scoped children for each parallel node
384
- for (const parallelNodeId of ungeneratedGroup) {
385
- const inst = workflow.instances.find((i) => i.id === parallelNodeId);
386
- if (!inst)
387
- continue;
388
- const nt = nodeTypes.find((n) => n.name === inst.nodeType || n.functionName === inst.nodeType);
389
- if (!nt)
390
- continue;
391
- generateScopedChildrenExecution(inst, nt, workflow, nodeTypes, generatedNodes, availableVars, lines, ' ', branchingNodes, branchRegions, isAsync, bundleMode, production);
392
- }
393
- return;
394
- }
395
- // else: degenerated to 1 or 0, fall through to sequential handling
396
- }
397
- if (branchingNodes.has(instanceId)) {
398
- // Chain members are generated by their chain head — skip
399
- if (chainMembers.has(instanceId)) {
400
- return;
401
- }
402
- // Chain heads: use flat chain generation
403
- if (branchingChains.has(instanceId)) {
404
- // For promoted chain heads, wrap in STEP guard
405
- let chainIndent = ' ';
406
- let chainNeedsClose = false;
407
- if (nodesPromotedFromBranches.has(instanceId)) {
408
- const stepSourceConditions = [];
409
- workflow.connections.forEach((conn) => {
410
- if (conn.to.node === instanceId && isExecutePort(conn.to.port)) {
411
- const src = conn.from.node;
412
- if (!isStartNode(src)) {
413
- stepSourceConditions.push(buildStepSourceCondition(src, conn.from.port, branchingNodes));
414
- }
415
- }
416
- });
417
- if (stepSourceConditions.length > 0) {
418
- const condition = stepSourceConditions.length === 1
419
- ? stepSourceConditions[0]
420
- : stepSourceConditions.join(' || ');
421
- lines.push(` if (${condition}) {`);
422
- chainIndent = ' ';
423
- chainNeedsClose = true;
424
- }
425
- }
426
- generateBranchingChainCode(branchingChains.get(instanceId), workflow, nodeTypes, branchingNodes, branchRegions, availableVars, generatedNodes, lines, chainIndent, isAsync, 'ctx', bundleMode, branchingNodesNeedingSuccessFlag, production, topLevelSuccessFlags);
427
- if (chainNeedsClose) {
428
- lines.push(` }`);
429
- }
430
- return;
431
- }
432
- // Non-chain branching nodes: existing path
433
- // For promoted branching nodes, wrap in STEP guard from execute port source
434
- let branchIndent = ' ';
435
- let branchNeedsClose = false;
436
- // Pre-declare _success flag at the outer scope so downstream guards
437
- // (which may run after the promoted guard block) can access it.
438
- const nodeRegion = branchRegions.get(instanceId);
439
- const promotedPreDeclared = new Set(topLevelSuccessFlags);
440
- if (nodesPromotedFromBranches.has(instanceId)) {
441
- const stepSourceConditions = [];
442
- workflow.connections.forEach((conn) => {
443
- if (conn.to.node === instanceId && isExecutePort(conn.to.port)) {
444
- const src = conn.from.node;
445
- if (!isStartNode(src)) {
446
- stepSourceConditions.push(buildStepSourceCondition(src, conn.from.port, branchingNodes));
447
- }
448
- }
449
- });
450
- if (stepSourceConditions.length > 0) {
451
- const condition = stepSourceConditions.length === 1
452
- ? stepSourceConditions[0]
453
- : stepSourceConditions.join(' || ');
454
- lines.push(` if (${condition}) {`);
455
- branchIndent = ' ';
456
- branchNeedsClose = true;
457
- }
458
- }
459
- generateBranchingNodeCode(instance, nodeType, workflow, nodeTypes, nodeRegion, availableVars, generatedNodes, lines, branchIndent, false, branchingNodes, branchRegions, isAsync, 'ctx', bundleMode, promotedPreDeclared, branchingNodesNeedingSuccessFlag.has(instanceId) || topLevelSuccessFlags.has(toValidIdentifier(instanceId)), production);
460
- if (branchNeedsClose) {
461
- lines.push(` }`);
462
- }
463
- const region = branchRegions.get(instanceId);
464
- region.successNodes.forEach((n) => generatedNodes.add(n));
465
- region.failureNodes.forEach((n) => generatedNodes.add(n));
466
- // Check if this node creates a scope and generate scoped children
467
- generateScopedChildrenExecution(instance, nodeType, workflow, nodeTypes, generatedNodes, availableVars, lines, ' ', branchingNodes, branchRegions, isAsync, bundleMode, production);
468
- }
469
- else {
470
- const belongsToBranch = Array.from(branchRegions.values()).some((region) => region.successNodes.has(instanceId) || region.failureNodes.has(instanceId));
471
- if (!belongsToBranch) {
472
- const nodeUseConst = !nodesInBranches.has(instanceId) &&
473
- !branchingNodes.has(instanceId) &&
474
- !pullExecutionNodes.has(instanceId) &&
475
- !nodeLevelScopedChildren.has(instanceId) &&
476
- !parallelGroupOf.has(instanceId);
477
- generateNodeCallWithContext(instance, nodeType, workflow, availableVars, lines, nodeTypes, ' ', isAsync, nodeUseConst, undefined, // instanceParent
478
- 'ctx', // ctxVar
479
- bundleMode, false, // skipExecuteGuard
480
- branchingNodes, // for port-aware STEP guards
481
- production);
482
- generatedNodes.add(instanceId);
483
- // Check if this node creates a scope and generate scoped children
484
- generateScopedChildrenExecution(instance, nodeType, workflow, nodeTypes, generatedNodes, availableVars, lines, ' ', branchingNodes, branchRegions, isAsync, bundleMode, production);
485
- }
486
- }
487
- });
488
- lines.push(` const exitIdx = ctx.addExecution('${RESERVED_NODE_NAMES.EXIT}');`);
489
- const exitConnections = workflow.connections.filter((conn) => isExitNode(conn.to.node));
490
- // Group exit connections by port (multiple connections to the same port are coalesced)
491
- const exitConnectionsByPort = new Map();
492
- exitConnections.forEach((conn) => {
493
- const existing = exitConnectionsByPort.get(conn.to.port) || [];
494
- existing.push(conn);
495
- exitConnectionsByPort.set(conn.to.port, existing);
496
- });
497
- const returnProps = [];
498
- const awaitKeyword = isAsync ? 'await ' : '';
499
- const setCall = isAsync ? 'await ctx.setVariable' : 'ctx.setVariable';
500
- exitConnectionsByPort.forEach((conns, exitPort) => {
501
- // Get exit port type for type casting - check if exit port is declared
502
- const exitPortDef = workflow.exitPorts[exitPort];
503
- // Skip connections to undeclared exit ports (typos like Exit.resultx when only @returns result exists)
504
- if (!exitPortDef) {
505
- lines.push(` // Exit connection skipped: '${exitPort}' is not a declared @returns port`);
506
- return;
507
- }
508
- const varName = `exit_${exitPort}`;
509
- const exitPortType = exitPortDef?.tsType || (exitPortDef ? mapToTypeScript(exitPortDef.dataType) : 'unknown');
510
- // Filter to valid connections (skip undeclared nodes, missing types)
511
- const validConns = conns.filter((conn) => {
512
- const sourceNode = conn.from.node;
513
- const sourceInstance = workflow.instances.find((i) => i.id === sourceNode);
514
- const sourceNodeType = nodeTypes.find((n) => n.name === sourceInstance?.nodeType || n.functionName === sourceInstance?.nodeType);
515
- if (!isStartNode(sourceNode) && !sourceInstance) {
516
- lines.push(` // Exit connection skipped: source node '${sourceNode}' is not declared`);
517
- return false;
518
- }
519
- if (!isStartNode(sourceNode) && sourceInstance && !sourceNodeType) {
520
- lines.push(` // Exit connection skipped: source node '${sourceNode}' has missing type '${sourceInstance.nodeType}'`);
521
- return false;
522
- }
523
- return true;
524
- });
525
- if (validConns.length === 0) {
526
- lines.push(` const ${varName} = undefined as unknown;`);
527
- returnProps.push(`${exitPort}: ${varName} as ${exitPortType}`);
528
- return;
529
- }
530
- // Helper to build a value expression for a single connection
531
- const buildSourceExpr = (conn, defaultValue) => {
532
- const sourceNode = conn.from.node;
533
- const sourcePort = conn.from.port;
534
- const sourceIdx = isStartNode(sourceNode) ? 'startIdx' : `${toValidIdentifier(sourceNode)}Idx`;
535
- const sourceInstance = workflow.instances.find((i) => i.id === sourceNode);
536
- const sourceNodeType = nodeTypes.find((n) => n.name === sourceInstance?.nodeType || n.functionName === sourceInstance?.nodeType);
537
- const pullConfig = sourceInstance && sourceNodeType
538
- ? getPullExecutionConfig(sourceInstance, sourceNodeType)
539
- : { enabled: false, triggerPort: 'execute' };
540
- const isPullNode = pullConfig.enabled;
541
- // Parallel group nodes are NOT included here because they always execute —
542
- // they sit outside branches, aren't lazy (pull), and aren't scoped children.
543
- // The await Promise.all(...) guarantees their Idx variables are assigned
544
- // before any downstream node reads them, so no undefined check is needed.
545
- const needsUndefinedCheck = !isStartNode(sourceNode) &&
546
- (nodesInBranches.has(sourceNode) ||
547
- branchingNodes.has(sourceNode) ||
548
- pullExecutionNodes.has(sourceNode) ||
549
- nodeLevelScopedChildren.has(sourceNode));
550
- if (isPullNode) {
551
- return `${awaitKeyword}ctx.getVariable({ id: '${sourceNode}', portName: '${sourcePort}', executionIndex: ${sourceIdx}!, nodeTypeName: '${sourceNode}' })`;
552
- }
553
- else if (needsUndefinedCheck) {
554
- return `${sourceIdx} !== undefined ? ${awaitKeyword}ctx.getVariable({ id: '${sourceNode}', portName: '${sourcePort}', executionIndex: ${sourceIdx} }) : ${defaultValue}`;
555
- }
556
- else {
557
- return `${awaitKeyword}ctx.getVariable({ id: '${sourceNode}', portName: '${sourcePort}', executionIndex: ${sourceIdx} })`;
558
- }
559
- };
560
- const isControlFlowPort = exitPort === 'onSuccess' || exitPort === 'onFailure';
561
- const defaultValue = isControlFlowPort ? 'false' : 'undefined';
562
- if (validConns.length === 1) {
563
- // Single connection - straightforward assignment
564
- lines.push(` const ${varName} = ${buildSourceExpr(validConns[0], defaultValue)};`);
565
- }
566
- else {
567
- // Multiple connections - coalesce with || (STEP ports) or ?? (data ports)
568
- const operator = isControlFlowPort ? ' || ' : ' ?? ';
569
- const parts = validConns.map((conn) => `(${buildSourceExpr(conn, defaultValue)})`);
570
- lines.push(` const ${varName} = ${parts.join(operator)};`);
571
- }
572
- // Emit VARIABLE_SET for Exit node INPUT ports
573
- if (!production) {
574
- lines.push(` ${setCall}({ id: '${RESERVED_NODE_NAMES.EXIT}', portName: '${exitPort}', executionIndex: exitIdx, nodeTypeName: '${RESERVED_NODE_NAMES.EXIT}' }, ${varName});`);
575
- }
576
- // Cast to the exit port's declared type for type safety
577
- returnProps.push(`${exitPort}: ${varName} as ${exitPortType}`);
578
- });
579
- // Add default undefined for declared exit ports that weren't connected
580
- // (e.g., when connection had typo like Exit.resultx instead of Exit.result)
581
- const connectedExitPorts = new Set(returnProps.map((prop) => prop.split(':')[0]));
582
- Object.entries(workflow.exitPorts).forEach(([portName, portDef]) => {
583
- if (!connectedExitPorts.has(portName) && portName !== 'onSuccess' && portName !== 'onFailure') {
584
- const portType = portDef?.tsType || (portDef ? mapToTypeScript(portDef.dataType) : 'unknown');
585
- lines.push(` // Exit port '${portName}' has no valid connection - using undefined`);
586
- returnProps.push(`${portName}: undefined as unknown as ${portType}`);
587
- }
588
- });
589
- lines.push('');
590
- // Check if onSuccess/onFailure are explicitly connected
591
- const hasOnSuccess = returnProps.some((prop) => prop.startsWith('onSuccess:'));
592
- const hasOnFailure = returnProps.some((prop) => prop.startsWith('onFailure:'));
593
- // Only add defaults if not explicitly connected
594
- const defaults = [];
595
- const setCallForDefaults = isAsync ? 'await ctx.setVariable' : 'ctx.setVariable';
596
- if (!hasOnSuccess) {
597
- defaults.push('onSuccess: true');
598
- // Emit VARIABLE_SET for default onSuccess
599
- if (!production) {
600
- lines.push(` ${setCallForDefaults}({ id: '${RESERVED_NODE_NAMES.EXIT}', portName: 'onSuccess', executionIndex: exitIdx, nodeTypeName: '${RESERVED_NODE_NAMES.EXIT}' }, true);`);
601
- }
602
- }
603
- if (!hasOnFailure) {
604
- defaults.push('onFailure: false');
605
- // Emit VARIABLE_SET for default onFailure
606
- if (!production) {
607
- lines.push(` ${setCallForDefaults}({ id: '${RESERVED_NODE_NAMES.EXIT}', portName: 'onFailure', executionIndex: exitIdx, nodeTypeName: '${RESERVED_NODE_NAMES.EXIT}' }, false);`);
608
- }
609
- }
610
- // Assemble final result with onSuccess first, onFailure second, then data ports.
611
- // This ensures JSON.stringify output is readable and predictable.
612
- const allPropsUnsorted = [...defaults, ...returnProps];
613
- const onSuccessProp = allPropsUnsorted.find(p => p.trimStart().startsWith('onSuccess'));
614
- const onFailureProp = allPropsUnsorted.find(p => p.trimStart().startsWith('onFailure'));
615
- const dataProps = allPropsUnsorted.filter(p => {
616
- const key = p.trimStart().split(':')[0].trim();
617
- return key !== 'onSuccess' && key !== 'onFailure';
618
- });
619
- const orderedProps = [];
620
- if (onSuccessProp)
621
- orderedProps.push(onSuccessProp);
622
- if (onFailureProp)
623
- orderedProps.push(onFailureProp);
624
- orderedProps.push(...dataProps);
625
- const allProps = orderedProps.join(', ');
626
- lines.push(` const finalResult = { ${allProps} };`);
627
- lines.push('');
628
- lines.push(` ${awaitPrefixTop}ctx.sendStatusChangedEvent({`);
629
- lines.push(` nodeTypeName: '${RESERVED_NODE_NAMES.EXIT}',`);
630
- lines.push(` id: '${RESERVED_NODE_NAMES.EXIT}',`);
631
- lines.push(` executionIndex: exitIdx,`);
632
- lines.push(` status: 'SUCCEEDED',`);
633
- lines.push(` });`);
634
- lines.push(` ctx.sendWorkflowCompletedEvent({`);
635
- lines.push(` executionIndex: exitIdx,`);
636
- lines.push(` status: 'SUCCEEDED',`);
637
- lines.push(` result: finalResult,`);
638
- lines.push(` });`);
639
- lines.push('');
640
- lines.push(` return finalResult;`);
641
- return lines.join('\n');
642
- }
643
- /**
644
- * Helper function to generate scoped children execution for nodes that create scopes
645
- */
646
- function generateScopedChildrenExecution(parentInstance, parentNodeType, workflow, allNodeTypes, generatedNodes, availableVars, lines, indent, branchingNodes, branchRegions, isAsync, bundleMode = false, production = false) {
647
- // Check if this node creates a scope
648
- if (!parentNodeType.scope)
649
- return;
650
- // Check if this is a per-port scope (has scoped OUTPUT ports)
651
- // Per-port scopes have children handled inside the scope function closure generated by
652
- // buildNodeArgumentsWithContext -> generateScopeFunctionClosure, so we skip here
653
- const rawScopeName = parentNodeType.scope;
654
- const hasPerPortScope = Object.values(parentNodeType.outputs).some((portDef) => portDef.scope === rawScopeName);
655
- if (hasPerPortScope) {
656
- // Children are already generated inside the scope function closure
657
- return;
658
- }
659
- const scopeName = `${parentInstance.id}.${parentNodeType.scope}`;
660
- // Find children in this scope from workflow.scopes or instance.parentScope
661
- const childrenInScope = [];
662
- // Check workflow.scopes mapping
663
- if (workflow.scopes && workflow.scopes[scopeName]) {
664
- childrenInScope.push(...workflow.scopes[scopeName]);
665
- }
666
- // Also check instances with parent field
667
- workflow.instances.forEach((instance) => {
668
- const parentScopeName = instance.parent
669
- ? `${instance.parent.id}.${instance.parent.scope}`
670
- : null;
671
- if (parentScopeName === scopeName && !childrenInScope.includes(instance.id)) {
672
- childrenInScope.push(instance.id);
673
- }
674
- });
675
- if (childrenInScope.length === 0)
676
- return;
677
- // Generate scope creation
678
- const safeParentId = toValidIdentifier(parentInstance.id);
679
- lines.push(``);
680
- lines.push(`${indent}// Create scope for children of ${parentInstance.id}`);
681
- lines.push(`${indent}const ${safeParentId}_scopedCtx = ctx.createScope('${parentInstance.id}', ${safeParentId}Idx, '${parentNodeType.scope}');`);
682
- lines.push(``);
683
- // Scoped context variable name for child generators
684
- const scopedCtxVar = `${safeParentId}_scopedCtx`;
685
- // Generate child nodes execution using scoped context
686
- childrenInScope.forEach((childInstanceId) => {
687
- if (generatedNodes.has(childInstanceId))
688
- return;
689
- const childInstance = workflow.instances.find((i) => i.id === childInstanceId);
690
- if (!childInstance)
691
- return;
692
- // Check both name (for npm nodes like 'npm/pkg/func') and functionName (for local nodes)
693
- const childNodeType = allNodeTypes.find((nt) => nt.name === childInstance.nodeType || nt.functionName === childInstance.nodeType);
694
- if (!childNodeType)
695
- return;
696
- // Check if this child is a branching node
697
- if (branchingNodes.has(childInstanceId)) {
698
- generateBranchingNodeCode(childInstance, childNodeType, workflow, allNodeTypes, branchRegions.get(childInstanceId), availableVars, generatedNodes, lines, indent, false, branchingNodes, branchRegions, isAsync, scopedCtxVar, // Pass scoped context name
699
- bundleMode, new Set(), false, production);
700
- const region = branchRegions.get(childInstanceId);
701
- region.successNodes.forEach((n) => generatedNodes.add(n));
702
- region.failureNodes.forEach((n) => generatedNodes.add(n));
703
- }
704
- else {
705
- generateNodeCallWithContext(childInstance, childNodeType, workflow, availableVars, lines, allNodeTypes, indent, isAsync, false, // useConst = false - scoped children need let (referenced outside scope block)
706
- parentInstance.id, // instanceParent - parent node is const, no ! needed when referencing it
707
- scopedCtxVar, // Pass scoped context name
708
- bundleMode, false, // skipExecuteGuard
709
- new Set(), // branchingNodes
710
- production);
711
- }
712
- generatedNodes.add(childInstanceId);
713
- });
714
- lines.push(``);
715
- lines.push(`${indent}// Merge scope back into parent context`);
716
- lines.push(`${indent}ctx.mergeScope(${parentInstance.id}_scopedCtx);`);
717
- lines.push(``);
718
- }
719
- /**
720
- * Generate a Promise.all block for 2+ parallel nodes in the unified generator.
721
- *
722
- * Each node's execution code is wrapped in an async IIFE inside Promise.all.
723
- * The outer `let` variables for execution indices are assigned inside the IIFEs.
724
- */
725
- function generateParallelGroupWithContext(nodeIds, workflow, nodeTypes, availableVars, lines, generatedNodes, indent, isAsync, ctxVar, bundleMode, branchingNodes, production = false) {
726
- // Collect code buffers for each node
727
- const nodeBuffers = [];
728
- for (const nodeId of nodeIds) {
729
- const instance = workflow.instances.find((i) => i.id === nodeId);
730
- if (!instance)
731
- continue;
732
- const nodeType = nodeTypes.find((nt) => nt.name === instance.nodeType || nt.functionName === instance.nodeType);
733
- if (!nodeType)
734
- continue;
735
- const nodeLines = [];
736
- generateNodeCallWithContext(instance, nodeType, workflow, availableVars, nodeLines, nodeTypes, `${indent} `, // indent for inside the async IIFE
737
- isAsync, false, // useConst = false — outer let declarations
738
- undefined, ctxVar, bundleMode, false, branchingNodes, production);
739
- nodeBuffers.push({ id: nodeId, lines: nodeLines });
740
- }
741
- // Fallback: if only 0-1 nodes remain, emit directly without Promise.all
742
- if (nodeBuffers.length < 2) {
743
- for (const buf of nodeBuffers) {
744
- for (const line of buf.lines) {
745
- lines.push(line);
746
- }
747
- generatedNodes.add(buf.id);
748
- }
749
- return;
750
- }
751
- lines.push(`${indent}await Promise.all([`);
752
- for (let i = 0; i < nodeBuffers.length; i++) {
753
- const buf = nodeBuffers[i];
754
- const comma = i < nodeBuffers.length - 1 ? ',' : '';
755
- lines.push(`${indent} (async () => {`);
756
- for (const line of buf.lines) {
757
- lines.push(line);
758
- }
759
- lines.push(`${indent} })()${comma}`);
760
- generatedNodes.add(buf.id);
761
- }
762
- lines.push(`${indent}]);`);
763
- lines.push('');
764
- }
765
- /**
766
- * Sort branch nodes topologically based on their dependencies
767
- *
768
- * This ensures nodes within a branch execute in the correct order:
769
- * dependencies before dependents.
770
- *
771
- * @param nodeIds - Set of node IDs within the branch
772
- * @param workflow - The workflow AST
773
- * @returns Array of node IDs in topologically sorted order
774
- */
775
- function sortBranchNodesTopologically(nodeIds, workflow) {
776
- if (nodeIds.size === 0) {
777
- return [];
778
- }
779
- // Build a mini control flow graph for just these nodes
780
- const graph = new Map();
781
- const inDegree = new Map();
782
- // Initialize
783
- nodeIds.forEach((id) => {
784
- graph.set(id, []);
785
- inDegree.set(id, 0);
786
- });
787
- // Add edges based on data flow connections within the branch
788
- workflow.connections.forEach((conn) => {
789
- const fromNode = conn.from.node;
790
- const toNode = conn.to.node;
791
- // Only consider connections within this branch
792
- if (nodeIds.has(fromNode) && nodeIds.has(toNode)) {
793
- const successors = graph.get(fromNode) || [];
794
- if (!successors.includes(toNode)) {
795
- successors.push(toNode);
796
- graph.set(fromNode, successors);
797
- inDegree.set(toNode, (inDegree.get(toNode) || 0) + 1);
798
- }
799
- }
800
- });
801
- // Perform Kahn's topological sort
802
- const result = [];
803
- const queue = [];
804
- // Start with nodes that have no dependencies within the branch
805
- inDegree.forEach((degree, node) => {
806
- if (degree === 0) {
807
- queue.push(node);
808
- }
809
- });
810
- while (queue.length > 0) {
811
- const node = queue.shift();
812
- result.push(node);
813
- const successors = graph.get(node) || [];
814
- successors.forEach((successor) => {
815
- const newDegree = (inDegree.get(successor) || 0) - 1;
816
- inDegree.set(successor, newDegree);
817
- if (newDegree === 0) {
818
- queue.push(successor);
819
- }
820
- });
821
- }
822
- // If we haven't processed all nodes, there's a cycle (shouldn't happen after validation)
823
- if (result.length !== nodeIds.size) {
824
- // Fallback: add remaining nodes in arbitrary order
825
- nodeIds.forEach((id) => {
826
- if (!result.includes(id)) {
827
- result.push(id);
828
- }
829
- });
830
- }
831
- return result;
832
- }
833
- /**
834
- * Generates CANCELLED status events for all nodes in a branch that won't be executed.
835
- * This is called when a branching node decides to take one path, marking nodes in
836
- * the non-taken path as CANCELLED. We must add an execution index first to have a
837
- * valid reference for the event.
838
- */
839
- function generateCancelledEventsForBranch(nodeIds, workflow, allNodeTypes, lines, indent, ctxVar = 'ctx', // Context variable name (for scoped contexts)
840
- isAsync = false) {
841
- const awaitPrefix = isAsync ? 'await ' : '';
842
- nodeIds.forEach((instanceId) => {
843
- const instance = workflow.instances.find((i) => i.id === instanceId);
844
- if (!instance)
845
- return;
846
- const safeId = toValidIdentifier(instanceId);
847
- // Use const (block-scoped) intentionally — the outer `let ${safeId}Idx`
848
- // stays undefined, which signals to downstream guards that this node was
849
- // CANCELLED and its data ports should not be read.
850
- lines.push(`${indent}const ${safeId}Idx = ${ctxVar}.addExecution('${instanceId}');`);
851
- // Set STEP port variables so downstream nodes reading onSuccess/onFailure
852
- // from this cancelled node don't crash with "Variable not found".
853
- lines.push(`${indent}${awaitPrefix}${ctxVar}.setVariable({ id: '${instanceId}', portName: 'onSuccess', executionIndex: ${safeId}Idx, nodeTypeName: '${instance.nodeType}' }, false);`);
854
- lines.push(`${indent}${awaitPrefix}${ctxVar}.setVariable({ id: '${instanceId}', portName: 'onFailure', executionIndex: ${safeId}Idx, nodeTypeName: '${instance.nodeType}' }, false);`);
855
- lines.push(`${indent}${awaitPrefix}${ctxVar}.sendStatusChangedEvent({`);
856
- lines.push(`${indent} nodeTypeName: '${instance.nodeType}',`);
857
- lines.push(`${indent} id: '${instanceId}',`);
858
- lines.push(`${indent} executionIndex: ${safeId}Idx,`);
859
- lines.push(`${indent} status: 'CANCELLED',`);
860
- lines.push(`${indent}});`);
861
- });
862
- }
863
- /**
864
- * Build a guard condition for a STEP connection source.
865
- * For branching nodes whose onSuccess/onFailure port is the source,
866
- * use the _success flag to guard the correct branch path.
867
- * For other sources, use Idx !== undefined.
868
- */
869
- function buildStepSourceCondition(sourceNode, sourcePort, branchingNodes) {
870
- const safeNode = toValidIdentifier(sourceNode);
871
- if (branchingNodes.has(sourceNode)) {
872
- if (isSuccessPort(sourcePort)) {
873
- return `${safeNode}_success`;
874
- }
875
- if (isFailurePort(sourcePort)) {
876
- return `${safeNode}_success === false`;
877
- }
878
- }
879
- return `${safeNode}Idx !== undefined`;
880
- }
881
- /**
882
- * Generate flat code for a sequential chain of branching nodes.
883
- *
884
- * Instead of nesting each subsequent branching node inside the previous one's
885
- * success/failure branch (O(N) depth), this generates them sequentially with
886
- * accumulated guard conditions (O(1) depth).
887
- *
888
- * For chain [A, B, C]:
889
- * A code (no guard)
890
- * if (A_success) { B code } else { CANCELLED for B,C and regions }
891
- * if (A_success && B_success) { C code } else { CANCELLED for C and regions }
892
- */
893
- function generateBranchingChainCode(chain, workflow, nodeTypes, branchingNodes, branchRegions, availableVars, generatedNodes, lines, indent, isAsync, ctxVar, bundleMode, forceTrackSuccessNodes = new Set(), production = false, alreadyDeclaredFlags = new Set()) {
894
- // Pre-declare success flags for all non-last chain nodes so they're
895
- // accessible across guard blocks (avoiding let-in-block scoping issues).
896
- // Also pre-declare for the last node if promoted nodes depend on its _success flag.
897
- // Skip flags already declared at a higher scope (e.g. function top-level).
898
- const preDeclaredFlags = new Set(alreadyDeclaredFlags);
899
- for (let i = 0; i < chain.length; i++) {
900
- const isLast = i === chain.length - 1;
901
- const safeId = toValidIdentifier(chain[i]);
902
- if (!isLast || forceTrackSuccessNodes.has(chain[i]) || alreadyDeclaredFlags.has(safeId)) {
903
- if (!alreadyDeclaredFlags.has(safeId)) {
904
- lines.push(`${indent}let ${safeId}_success = false;`);
905
- }
906
- preDeclaredFlags.add(safeId);
907
- }
908
- }
909
- if (chain.length > 1) {
910
- lines.push('');
911
- }
912
- const guardParts = [];
913
- for (let i = 0; i < chain.length; i++) {
914
- const nodeId = chain[i];
915
- const isLast = i === chain.length - 1;
916
- const instance = workflow.instances.find((inst) => inst.id === nodeId);
917
- if (!instance)
918
- continue;
919
- const nodeType = nodeTypes.find((nt) => nt.name === instance.nodeType || nt.functionName === instance.nodeType);
920
- if (!nodeType)
921
- continue;
922
- const safeId = toValidIdentifier(nodeId);
923
- const originalRegion = branchRegions.get(nodeId);
924
- // For non-last nodes, create modified region with chain successor removed
925
- // so generateBranchingNodeCode won't recurse into the next chain node
926
- let effectiveRegion = originalRegion;
927
- if (!isLast) {
928
- const nextNodeId = chain[i + 1];
929
- effectiveRegion = {
930
- successNodes: new Set([...originalRegion.successNodes].filter((n) => n !== nextNodeId)),
931
- failureNodes: new Set([...originalRegion.failureNodes].filter((n) => n !== nextNodeId)),
932
- };
933
- }
934
- const hasGuard = guardParts.length > 0;
935
- const guardCondition = guardParts.join(' && ');
936
- if (hasGuard) {
937
- lines.push(`${indent}if (${guardCondition}) {`);
938
- }
939
- const nodeIndent = hasGuard ? indent + ' ' : indent;
940
- generateBranchingNodeCode(instance, nodeType, workflow, nodeTypes, effectiveRegion, availableVars, generatedNodes, lines, nodeIndent, false, branchingNodes, branchRegions, isAsync, ctxVar, bundleMode, preDeclaredFlags, !isLast || forceTrackSuccessNodes.has(chain[i]) || alreadyDeclaredFlags.has(safeId), // forceTrackSuccess for non-last chain nodes, nodes with promoted dependents, or nodes with pre-declared flags
941
- production);
942
- // Generate scoped children for this chain node
943
- generateScopedChildrenExecution(instance, nodeType, workflow, nodeTypes, generatedNodes, availableVars, lines, nodeIndent, branchingNodes, branchRegions, isAsync, bundleMode, production);
944
- if (hasGuard) {
945
- lines.push(`${indent}} else {`);
946
- // Emit CANCELLED for this node and all remaining chain nodes + their regions
947
- const remainingNodes = new Set();
948
- for (let j = i; j < chain.length; j++) {
949
- const chainNodeId = chain[j];
950
- remainingNodes.add(chainNodeId);
951
- const region = branchRegions.get(chainNodeId);
952
- region.successNodes.forEach((n) => remainingNodes.add(n));
953
- region.failureNodes.forEach((n) => remainingNodes.add(n));
954
- }
955
- generateCancelledEventsForBranch(remainingNodes, workflow, nodeTypes, lines, indent + ' ', ctxVar, isAsync);
956
- lines.push(`${indent}}`);
957
- }
958
- // Add success condition for next iteration's guard
959
- if (!isLast) {
960
- guardParts.push(`${safeId}_success`);
961
- }
962
- // Mark node and its effective region as generated
963
- generatedNodes.add(nodeId);
964
- effectiveRegion.successNodes.forEach((n) => generatedNodes.add(n));
965
- effectiveRegion.failureNodes.forEach((n) => generatedNodes.add(n));
966
- }
967
- }
968
- function generateBranchingNodeCode(instance, branchNode, workflow, allNodeTypes, region, availableVars, generatedNodes, lines, indent, _generateReturns = true, // DEPRECATED: always false, kept for signature compat
969
- branchingNodes, branchRegions, isAsync, ctxVar = 'ctx', // Context variable name (for scoped contexts)
970
- bundleMode = false, preDeclaredSuccessFlags = new Set(), forceTrackSuccess = false, production = false) {
971
- const instanceId = instance.id;
972
- const safeId = toValidIdentifier(instanceId);
973
- const functionName = branchNode.functionName;
974
- // Debug controller: beforeNode hook for branching nodes
975
- const emitDebugHooks = !production;
976
- const outerIndent = indent;
977
- // Only declare success flag if there are downstream nodes
978
- const hasSuccessDownstream = region.successNodes.size > 0;
979
- const hasFailureDownstream = region.failureNodes.size > 0;
980
- const hasDownstream = hasSuccessDownstream || hasFailureDownstream;
981
- // Track success flag when there are downstream nodes OR when chain code needs it
982
- const trackSuccess = hasDownstream || forceTrackSuccess;
983
- if (emitDebugHooks) {
984
- // Hoist success flag declaration before the if block so it remains in scope
985
- // for downstream branching code that runs after the if/else.
986
- if (trackSuccess && !preDeclaredSuccessFlags.has(safeId)) {
987
- lines.push(`${indent}let ${safeId}_success = false;`);
988
- }
989
- const awaitHook = isAsync ? 'await ' : '';
990
- lines.push(`${indent}if (${awaitHook}__ctrl__.beforeNode('${instanceId}', ${ctxVar})) {`);
991
- indent = `${indent} `;
992
- }
993
- const awaitPrefix = isAsync ? 'await ' : '';
994
- if (!production) {
995
- lines.push('');
996
- lines.push(`${indent}// ── ${instanceId} (${functionName}) ──`);
997
- }
998
- lines.push(`${indent}${ctxVar}.checkAborted('${instanceId}');`);
999
- lines.push(`${indent}${safeId}Idx = ${ctxVar}.addExecution('${instanceId}');`);
1000
- lines.push(`${indent}if (typeof globalThis !== 'undefined') (globalThis as unknown as { __fw_current_node_id__?: string }).__fw_current_node_id__ = '${instanceId}';`);
1001
- lines.push(`${indent}${awaitPrefix}${ctxVar}.sendStatusChangedEvent({`);
1002
- lines.push(`${indent} nodeTypeName: '${functionName}',`);
1003
- lines.push(`${indent} id: '${instanceId}',`);
1004
- lines.push(`${indent} executionIndex: ${safeId}Idx,`);
1005
- lines.push(`${indent} status: 'RUNNING',`);
1006
- lines.push(`${indent}});`);
1007
- lines.push('');
1008
- if (trackSuccess) {
1009
- if (preDeclaredSuccessFlags.has(safeId) || emitDebugHooks) {
1010
- // Flag was pre-declared (by chain code or hoisted for debug hooks) — assignment only
1011
- lines.push(`${indent}${safeId}_success = false;`);
1012
- }
1013
- else {
1014
- lines.push(`${indent}let ${safeId}_success = false;`);
1015
- }
1016
- lines.push('');
1017
- }
1018
- lines.push(`${indent}try {`);
1019
- const getCall = isAsync ? `await ${ctxVar}.getVariable` : `${ctxVar}.getVariable`;
1020
- const setCall = isAsync ? `await ${ctxVar}.setVariable` : `${ctxVar}.setVariable`;
1021
- const argNames = buildNodeArgumentsWithContext({
1022
- node: branchNode,
1023
- workflow,
1024
- id: instanceId,
1025
- lines,
1026
- indent: `${indent} `,
1027
- getCall,
1028
- isAsync,
1029
- emitInputEvents: true,
1030
- setCall,
1031
- nodeTypeName: functionName,
1032
- bundleMode,
1033
- production,
1034
- });
1035
- const awaitKeyword = branchNode.isAsync ? 'await ' : '';
1036
- if (branchNode.expression) {
1037
- // Expression branching node: call without execute, auto-set onSuccess/onFailure
1038
- lines.push(`${indent} const ${safeId}Result = ${awaitKeyword}${functionName}(${argNames.join(', ')});`);
1039
- // Determine data output ports (exclude control flow and scoped ports)
1040
- const dataOutputPorts = Object.keys(branchNode.outputs).filter((portName) => {
1041
- const portConfig = branchNode.outputs[portName];
1042
- if (portConfig.scope)
1043
- return false;
1044
- if (isSuccessPort(portName) || isFailurePort(portName))
1045
- return false;
1046
- if (portConfig.isControlFlow || portConfig.failure)
1047
- return false;
1048
- return true;
1049
- });
1050
- if (dataOutputPorts.length === 1) {
1051
- // Single data output: destructure if result is an object with the port key, else use raw value
1052
- // Extract to unknown-typed variable to prevent TypeScript from narrowing
1053
- // specific return types (e.g. boolean) to `never` in the typeof check
1054
- const portName = dataOutputPorts[0];
1055
- const rawVar = `${safeId}Result_raw`;
1056
- lines.push(`${indent} const ${rawVar}: unknown = ${safeId}Result;`);
1057
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: '${portName}', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, typeof ${rawVar} === 'object' && ${rawVar} !== null && '${portName}' in ${rawVar} ? ${rawVar}.${portName} : ${rawVar});`);
1058
- }
1059
- else {
1060
- // Multiple data outputs: destructure from object return
1061
- dataOutputPorts.forEach((portName) => {
1062
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: '${portName}', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, ${safeId}Result.${portName});`);
1063
- });
1064
- }
1065
- // Auto-set onSuccess/onFailure
1066
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: 'onSuccess', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, true);`);
1067
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: 'onFailure', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, false);`);
1068
- }
1069
- else if (branchNode.variant === 'MAP_ITERATOR') {
1070
- // MAP_ITERATOR: inline iteration — no user function to call
1071
- // argNames: [execute, items, scopeFn]
1072
- const executeArg = argNames[0];
1073
- const itemsArg = argNames[1];
1074
- const scopeFnArg = argNames[2];
1075
- lines.push(`${indent} let ${safeId}Result: { onSuccess: boolean; onFailure: boolean; results: unknown[] };`);
1076
- lines.push(`${indent} if (!${executeArg}) {`);
1077
- lines.push(`${indent} ${safeId}Result = { onSuccess: false, onFailure: false, results: [] };`);
1078
- lines.push(`${indent} } else {`);
1079
- lines.push(`${indent} const __results: unknown[] = [];`);
1080
- lines.push(`${indent} for (const __item of ${itemsArg}) {`);
1081
- lines.push(`${indent} __results.push((${isAsync ? 'await ' : ''}${scopeFnArg}(true, __item)).processed);`);
1082
- lines.push(`${indent} }`);
1083
- lines.push(`${indent} ${safeId}Result = { onSuccess: true, onFailure: false, results: __results };`);
1084
- lines.push(`${indent} }`);
1085
- // Set output ports from result
1086
- Object.keys(branchNode.outputs).forEach((portName) => {
1087
- const portConfig = branchNode.outputs[portName];
1088
- if (portConfig.scope)
1089
- return;
1090
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: '${portName}', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, ${safeId}Result.${portName});`);
1091
- });
1092
- }
1093
- else if (branchNode.variant === 'IMPORTED_WORKFLOW' || branchNode.variant === 'WORKFLOW') {
1094
- // Check if this is a workflow call (IMPORTED_WORKFLOW or WORKFLOW variant)
1095
- // Workflows use (execute, params) signature where params is an object
1096
- // Regular nodes use (execute, arg1, arg2, ...) positional signature
1097
- // For workflow calls, wrap data args in an object and include recursion depth
1098
- const executeArg = argNames[0]; // First arg is always execute
1099
- const dataArgs = argNames.slice(1); // Rest are data inputs
1100
- const inputPortNames = Object.keys(branchNode.inputs).filter((p) => !isExecutePort(p));
1101
- // Build params object: { portName1: value1, portName2: value2, ..., __rd__: __rd__ + 1 }
1102
- // Assign to variable first to avoid TypeScript excess property checking on object literals
1103
- const paramsEntries = inputPortNames.map((portName, i) => `${portName}: ${dataArgs[i]}`);
1104
- paramsEntries.push('__rd__: __rd__ + 1');
1105
- const paramsObj = `{ ${paramsEntries.join(', ')} }`;
1106
- const paramsVar = `__${safeId}Params__`;
1107
- lines.push(`${indent} const ${paramsVar} = ${paramsObj};`);
1108
- lines.push(`${indent} const ${safeId}Result = ${awaitKeyword}${functionName}(${executeArg}, ${paramsVar});`);
1109
- // STEP Port Architecture: Extract ALL outputs from result, including onSuccess/onFailure
1110
- // Skip scoped OUTPUT ports - they're parameters to scope functions, not return values
1111
- Object.keys(branchNode.outputs).forEach((portName) => {
1112
- const portConfig = branchNode.outputs[portName];
1113
- if (portConfig.scope)
1114
- return;
1115
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: '${portName}', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, ${safeId}Result.${portName});`);
1116
- });
1117
- }
1118
- else if (branchNode.scope || (branchNode.scopes && branchNode.scopes.length > 0)) {
1119
- // Scoped node call with positional arguments (uses _impl signature)
1120
- // Scoped nodes have callback parameters that can't be passed via params object
1121
- lines.push(`${indent} const ${safeId}Result = ${awaitKeyword}${functionName}(${argNames.join(', ')});`);
1122
- // STEP Port Architecture: Extract ALL outputs from result, including onSuccess/onFailure
1123
- // Skip scoped OUTPUT ports - they're parameters to scope functions, not return values
1124
- Object.keys(branchNode.outputs).forEach((portName) => {
1125
- const portConfig = branchNode.outputs[portName];
1126
- if (portConfig.scope)
1127
- return;
1128
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: '${portName}', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, ${safeId}Result.${portName});`);
1129
- });
1130
- }
1131
- else {
1132
- // Regular node call - always use positional args
1133
- // In bundle mode we import _impl which takes (execute, ...positional_args)
1134
- lines.push(`${indent} const ${safeId}Result = ${awaitKeyword}${functionName}(${argNames.join(', ')});`);
1135
- // STEP Port Architecture: Extract ALL outputs from result, including onSuccess/onFailure
1136
- // Skip scoped OUTPUT ports - they're parameters to scope functions, not return values
1137
- Object.keys(branchNode.outputs).forEach((portName) => {
1138
- const portConfig = branchNode.outputs[portName];
1139
- if (portConfig.scope)
1140
- return;
1141
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: '${portName}', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, ${safeId}Result.${portName});`);
1142
- });
1143
- }
1144
- lines.push(`${indent} ${awaitPrefix}${ctxVar}.sendStatusChangedEvent({`);
1145
- lines.push(`${indent} nodeTypeName: '${functionName}',`);
1146
- lines.push(`${indent} id: '${instanceId}',`);
1147
- lines.push(`${indent} executionIndex: ${safeId}Idx,`);
1148
- lines.push(`${indent} status: 'SUCCEEDED',`);
1149
- lines.push(`${indent} });`);
1150
- // Debug controller: afterNode hook for branching nodes
1151
- if (emitDebugHooks) {
1152
- const awaitHook = isAsync ? 'await ' : '';
1153
- lines.push(`${indent} ${awaitHook}__ctrl__.afterNode('${instanceId}', ${ctxVar});`);
1154
- }
1155
- // Use onSuccess from result to determine control flow
1156
- // For expression nodes, onSuccess is always true here (catch handles failure)
1157
- if (trackSuccess) {
1158
- lines.push(`${indent} ${safeId}_success = ${branchNode.expression ? 'true' : `${safeId}Result.onSuccess`};`);
1159
- }
1160
- lines.push(`${indent}} catch (error: unknown) {`);
1161
- lines.push(`${indent} const isCancellation = CancellationError.isCancellationError(error);`);
1162
- lines.push(`${indent} ${awaitPrefix}${ctxVar}.sendStatusChangedEvent({`);
1163
- lines.push(`${indent} nodeTypeName: '${functionName}',`);
1164
- lines.push(`${indent} id: '${instanceId}',`);
1165
- lines.push(`${indent} executionIndex: ${safeId}Idx,`);
1166
- lines.push(`${indent} status: isCancellation ? 'CANCELLED' : 'FAILED',`);
1167
- lines.push(`${indent} });`);
1168
- lines.push(`${indent} if (!isCancellation) {`);
1169
- lines.push(`${indent} ${ctxVar}.sendLogErrorEvent({`);
1170
- lines.push(`${indent} nodeTypeName: '${functionName}',`);
1171
- lines.push(`${indent} id: '${instanceId}',`);
1172
- lines.push(`${indent} executionIndex: ${safeId}Idx,`);
1173
- lines.push(`${indent} error: error instanceof Error ? error.message : String(error),`);
1174
- lines.push(`${indent} });`);
1175
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: 'onSuccess', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, false);`);
1176
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: 'onFailure', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, true);`);
1177
- if (trackSuccess) {
1178
- lines.push(`${indent} ${safeId}_success = false;`);
1179
- }
1180
- lines.push(`${indent} }`);
1181
- // Emit CANCELLED for all downstream nodes since branching node threw
1182
- if (hasSuccessDownstream) {
1183
- generateCancelledEventsForBranch(region.successNodes, workflow, allNodeTypes, lines, `${indent} `, ctxVar, isAsync);
1184
- }
1185
- if (hasFailureDownstream) {
1186
- generateCancelledEventsForBranch(region.failureNodes, workflow, allNodeTypes, lines, `${indent} `, ctxVar, isAsync);
1187
- }
1188
- // Re-throw the error to propagate it up (important for recursive workflows)
1189
- lines.push(`${indent} throw error;`);
1190
- lines.push(`${indent}}`);
1191
- // Close the debug controller beforeNode if block for the node's own execution.
1192
- // The downstream branching must be outside the if block so it runs even when
1193
- // the node is skipped (checkpoint resume).
1194
- if (emitDebugHooks) {
1195
- lines.push(`${outerIndent}} else {`);
1196
- // Node was skipped (checkpoint resume). Controller already restored outputs
1197
- // into ctx, but we need local vars for downstream branching.
1198
- lines.push(`${outerIndent} ${safeId}Idx = ${ctxVar}.addExecution('${instanceId}');`);
1199
- if (trackSuccess) {
1200
- lines.push(`${outerIndent} ${safeId}_success = true;`);
1201
- }
1202
- lines.push(`${outerIndent}}`);
1203
- indent = outerIndent; // Restore indent level for downstream code
1204
- }
1205
- lines.push('');
1206
- // Only generate if/else if there are downstream nodes
1207
- if (hasDownstream) {
1208
- lines.push(`${indent}if (${safeId}_success) {`);
1209
- // Emit CANCELLED for failure branch nodes since success path was taken
1210
- if (hasFailureDownstream) {
1211
- generateCancelledEventsForBranch(region.failureNodes, workflow, allNodeTypes, lines, `${indent} `, ctxVar, isAsync);
1212
- }
1213
- const successVars = new Map(availableVars);
1214
- Object.keys(branchNode.outputs).forEach((portName) => {
1215
- successVars.set(`${instanceId}.${portName}`, `${safeId}Result.${portName}`);
1216
- });
1217
- // Sort success branch nodes topologically to ensure correct execution order
1218
- const successInstanceIds = sortBranchNodesTopologically(region.successNodes, workflow);
1219
- const successExecutedNodes = [instance.id];
1220
- successInstanceIds.forEach((instanceId) => {
1221
- const inst = workflow.instances.find((i) => i.id === instanceId);
1222
- if (!inst)
1223
- return;
1224
- // Check both name (for npm nodes like 'npm/pkg/func') and functionName (for local nodes)
1225
- const nodeType = allNodeTypes.find((nt) => nt.name === inst.nodeType || nt.functionName === inst.nodeType);
1226
- if (!nodeType)
1227
- return;
1228
- if (branchingNodes.has(instanceId)) {
1229
- const nestedRegion = branchRegions.get(instanceId);
1230
- // Pre-declare nested branching node's _success flag at the current
1231
- // scope so it remains accessible to downstream guards that may run
1232
- // outside this branch block. (Fixes scoping bug where the flag was
1233
- // declared inside a nested conditional but referenced at a higher scope.)
1234
- const nestedSafeId = toValidIdentifier(instanceId);
1235
- const nestedHasDownstream = nestedRegion.successNodes.size > 0 || nestedRegion.failureNodes.size > 0;
1236
- const nestedPreDeclared = new Set(preDeclaredSuccessFlags);
1237
- if (nestedHasDownstream && !nestedPreDeclared.has(nestedSafeId)) {
1238
- lines.push(`${indent} let ${nestedSafeId}_success = false;`);
1239
- nestedPreDeclared.add(nestedSafeId);
1240
- }
1241
- generateBranchingNodeCode(inst, nodeType, workflow, allNodeTypes, nestedRegion, successVars, generatedNodes, lines, `${indent} `, false, branchingNodes, branchRegions, isAsync, ctxVar, bundleMode, nestedPreDeclared, nestedPreDeclared.has(nestedSafeId), // force tracking if flag was pre-declared at higher scope
1242
- production);
1243
- successExecutedNodes.push(instanceId);
1244
- nestedRegion.successNodes.forEach((n) => successExecutedNodes.push(n));
1245
- nestedRegion.failureNodes.forEach((n) => successExecutedNodes.push(n));
1246
- }
1247
- else {
1248
- generateNodeCallWithContext(inst, nodeType, workflow, successVars, lines, allNodeTypes, `${indent} `, isAsync, false, // useConst
1249
- undefined, // instanceParent
1250
- ctxVar, bundleMode, true, // skipExecuteGuard — inside branch, execute is guaranteed by if/else
1251
- branchingNodes, production);
1252
- Object.keys(nodeType.outputs).forEach((portName) => {
1253
- successVars.set(`${instanceId}.${portName}`, `${toValidIdentifier(instanceId)}Result.${portName}`);
1254
- });
1255
- successExecutedNodes.push(instanceId);
1256
- generatedNodes.add(instanceId);
1257
- }
1258
- });
1259
- // Only generate else block if there are failure nodes to execute
1260
- if (hasFailureDownstream) {
1261
- lines.push(`${indent}} else {`);
1262
- // Emit CANCELLED for success branch nodes since failure path was taken
1263
- if (hasSuccessDownstream) {
1264
- generateCancelledEventsForBranch(region.successNodes, workflow, allNodeTypes, lines, `${indent} `, ctxVar, isAsync);
1265
- }
1266
- const failureVars = new Map(availableVars);
1267
- Object.keys(branchNode.outputs).forEach((portName) => {
1268
- failureVars.set(`${instanceId}.${portName}`, `${safeId}Result.${portName}`);
1269
- });
1270
- // Sort failure branch nodes topologically to ensure correct execution order
1271
- const failureInstanceIds = sortBranchNodesTopologically(region.failureNodes, workflow);
1272
- const failureExecutedNodes = [instance.id];
1273
- failureInstanceIds.forEach((instanceId) => {
1274
- const inst = workflow.instances.find((i) => i.id === instanceId);
1275
- if (!inst)
1276
- return;
1277
- // Check both name (for npm nodes like 'npm/pkg/func') and functionName (for local nodes)
1278
- const nodeType = allNodeTypes.find((nt) => nt.name === inst.nodeType || nt.functionName === inst.nodeType);
1279
- if (!nodeType)
1280
- return;
1281
- if (branchingNodes.has(instanceId)) {
1282
- const nestedRegion = branchRegions.get(instanceId);
1283
- // Pre-declare nested branching node's _success flag at the current
1284
- // scope (same fix as success branch above).
1285
- const nestedSafeId = toValidIdentifier(instanceId);
1286
- const nestedHasDownstream = nestedRegion.successNodes.size > 0 || nestedRegion.failureNodes.size > 0;
1287
- const nestedPreDeclared = new Set(preDeclaredSuccessFlags);
1288
- if (nestedHasDownstream && !nestedPreDeclared.has(nestedSafeId)) {
1289
- lines.push(`${indent} let ${nestedSafeId}_success = false;`);
1290
- nestedPreDeclared.add(nestedSafeId);
1291
- }
1292
- generateBranchingNodeCode(inst, nodeType, workflow, allNodeTypes, nestedRegion, failureVars, generatedNodes, lines, `${indent} `, false, branchingNodes, branchRegions, isAsync, ctxVar, bundleMode, nestedPreDeclared, nestedPreDeclared.has(nestedSafeId), // force tracking if flag was pre-declared at higher scope
1293
- production);
1294
- failureExecutedNodes.push(instanceId);
1295
- nestedRegion.successNodes.forEach((n) => failureExecutedNodes.push(n));
1296
- nestedRegion.failureNodes.forEach((n) => failureExecutedNodes.push(n));
1297
- }
1298
- else {
1299
- generateNodeCallWithContext(inst, nodeType, workflow, failureVars, lines, allNodeTypes, `${indent} `, isAsync, false, // useConst
1300
- undefined, // instanceParent
1301
- ctxVar, bundleMode, true, // skipExecuteGuard — inside branch, execute is guaranteed by if/else
1302
- branchingNodes, production);
1303
- Object.keys(nodeType.outputs).forEach((portName) => {
1304
- failureVars.set(`${instanceId}.${portName}`, `${toValidIdentifier(instanceId)}Result.${portName}`);
1305
- });
1306
- failureExecutedNodes.push(instanceId);
1307
- generatedNodes.add(instanceId);
1308
- }
1309
- });
1310
- lines.push(`${indent}}`);
1311
- }
1312
- else {
1313
- // No failure branch - emit CANCELLED for success nodes and close
1314
- if (hasSuccessDownstream) {
1315
- lines.push(`${indent}} else {`);
1316
- generateCancelledEventsForBranch(region.successNodes, workflow, allNodeTypes, lines, `${indent} `, ctxVar, isAsync);
1317
- lines.push(`${indent}}`);
1318
- }
1319
- else {
1320
- lines.push(`${indent}}`);
1321
- }
1322
- }
1323
- }
1324
- generatedNodes.add(instanceId);
1325
- }
1326
- function generatePullNodeWithContext(instance, nodeType, workflow, lines, indent, isAsync, ctxVar = 'ctx', // Context variable name (for scoped contexts)
1327
- bundleMode = false, production = false) {
1328
- const instanceId = instance.id;
1329
- const safeId = toValidIdentifier(instanceId);
1330
- const functionName = nodeType.functionName;
1331
- // Executor must be async if:
1332
- // 1. The workflow is async (context returns Promises)
1333
- // 2. OR the node function is async (function returns Promise)
1334
- // Sync executors only work when BOTH workflow and node are sync
1335
- const executorIsAsync = isAsync || nodeType.isAsync;
1336
- const asyncKeyword = executorIsAsync ? 'async ' : '';
1337
- const awaitKeyword = nodeType.isAsync ? 'await ' : '';
1338
- const awaitPrefix = executorIsAsync ? 'await ' : '';
1339
- // Create a lazy execution function for this pull node
1340
- // The function will only execute when its outputs are accessed
1341
- lines.push(`${indent}// Pull execution node: ${instanceId}`);
1342
- lines.push(`${indent}const ${safeId}_executor = ${asyncKeyword}() => {`);
1343
- lines.push(`${indent} if (${safeId}Idx !== undefined) {`);
1344
- lines.push(`${indent} return; // Already executed`);
1345
- lines.push(`${indent} }`);
1346
- lines.push(`${indent} ${ctxVar}.checkAborted('${instanceId}');`);
1347
- lines.push(`${indent} ${safeId}Idx = ${ctxVar}.addExecution('${instanceId}');`);
1348
- lines.push(`${indent} if (typeof globalThis !== 'undefined') (globalThis as unknown as { __fw_current_node_id__?: string }).__fw_current_node_id__ = '${instanceId}';`);
1349
- lines.push(`${indent} ${awaitPrefix}${ctxVar}.sendStatusChangedEvent({`);
1350
- lines.push(`${indent} nodeTypeName: '${functionName}',`);
1351
- lines.push(`${indent} id: '${instanceId}',`);
1352
- lines.push(`${indent} executionIndex: ${safeId}Idx,`);
1353
- lines.push(`${indent} status: 'RUNNING',`);
1354
- lines.push(`${indent} });`);
1355
- lines.push(`${indent} try {`);
1356
- // Use executor's async status for get/set calls within the executor
1357
- const getCall = executorIsAsync ? `await ${ctxVar}.getVariable` : `${ctxVar}.getVariable`;
1358
- const setCall = executorIsAsync ? `await ${ctxVar}.setVariable` : `${ctxVar}.setVariable`;
1359
- const args = buildNodeArgumentsWithContext({
1360
- node: nodeType,
1361
- workflow,
1362
- id: instanceId,
1363
- lines,
1364
- indent: `${indent} `,
1365
- getCall,
1366
- isAsync: executorIsAsync,
1367
- emitInputEvents: true,
1368
- setCall,
1369
- nodeTypeName: functionName,
1370
- bundleMode,
1371
- production,
1372
- });
1373
- const resultVar = `${safeId}Result`;
1374
- // Check if this is a workflow call (IMPORTED_WORKFLOW or WORKFLOW variant)
1375
- // Workflows use (execute, params) signature where params is an object
1376
- // Regular nodes use (execute, arg1, arg2, ...) positional signature
1377
- if (nodeType.variant === 'MAP_ITERATOR') {
1378
- // MAP_ITERATOR: inline iteration in pull executor
1379
- const executeArg = args[0];
1380
- const itemsArg = args[1];
1381
- const scopeFnArg = args[2];
1382
- lines.push(`${indent} let ${resultVar}: { onSuccess: boolean; onFailure: boolean; results: unknown[] };`);
1383
- lines.push(`${indent} if (!${executeArg}) {`);
1384
- lines.push(`${indent} ${resultVar} = { onSuccess: false, onFailure: false, results: [] };`);
1385
- lines.push(`${indent} } else {`);
1386
- lines.push(`${indent} const __results: unknown[] = [];`);
1387
- lines.push(`${indent} for (const __item of ${itemsArg}) {`);
1388
- lines.push(`${indent} __results.push((${executorIsAsync ? 'await ' : ''}${scopeFnArg}(true, __item)).processed);`);
1389
- lines.push(`${indent} }`);
1390
- lines.push(`${indent} ${resultVar} = { onSuccess: true, onFailure: false, results: __results };`);
1391
- lines.push(`${indent} }`);
1392
- }
1393
- else if (nodeType.variant === 'IMPORTED_WORKFLOW' || nodeType.variant === 'WORKFLOW') {
1394
- // For workflow calls, wrap data args in an object and include recursion depth
1395
- const executeArg = args[0]; // First arg is always execute
1396
- const dataArgs = args.slice(1); // Rest are data inputs
1397
- const inputPortNames = Object.keys(nodeType.inputs).filter((p) => !isExecutePort(p));
1398
- // Build params object: { portName1: value1, portName2: value2, ..., __rd__: __rd__ + 1 }
1399
- // Assign to variable first to avoid TypeScript excess property checking on object literals
1400
- const paramsEntries = inputPortNames.map((portName, i) => `${portName}: ${dataArgs[i]}`);
1401
- paramsEntries.push('__rd__: __rd__ + 1');
1402
- const paramsObj = `{ ${paramsEntries.join(', ')} }`;
1403
- const paramsVar = `__${safeId}Params__`;
1404
- lines.push(`${indent} const ${paramsVar} = ${paramsObj};`);
1405
- lines.push(`${indent} const ${resultVar} = ${awaitKeyword}${functionName}(${executeArg}, ${paramsVar});`);
1406
- }
1407
- else if (nodeType.scope || (nodeType.scopes && nodeType.scopes.length > 0)) {
1408
- // Scoped node call with positional arguments (uses _impl signature)
1409
- // Scoped nodes have callback parameters that can't be passed via params object
1410
- lines.push(`${indent} const ${resultVar} = ${awaitKeyword}${functionName}(${args.join(', ')});`);
1411
- }
1412
- else {
1413
- // Regular node call - always use positional args
1414
- // In bundle mode we import _impl which takes (execute, ...positional_args)
1415
- lines.push(`${indent} const ${resultVar} = ${awaitKeyword}${functionName}(${args.join(', ')});`);
1416
- }
1417
- Object.keys(nodeType.outputs).forEach((portName) => {
1418
- if (isSuccessPort(portName) || isFailurePort(portName))
1419
- return;
1420
- // Skip scoped OUTPUT ports - they don't exist in the function return value
1421
- const portConfig = nodeType.outputs[portName];
1422
- if (portConfig.scope)
1423
- return;
1424
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: '${portName}', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, ${resultVar}.${portName});`);
1425
- });
1426
- lines.push(`${indent} ${awaitPrefix}${ctxVar}.sendStatusChangedEvent({`);
1427
- lines.push(`${indent} nodeTypeName: '${functionName}',`);
1428
- lines.push(`${indent} id: '${instanceId}',`);
1429
- lines.push(`${indent} executionIndex: ${safeId}Idx,`);
1430
- lines.push(`${indent} status: 'SUCCEEDED',`);
1431
- lines.push(`${indent} });`);
1432
- lines.push(`${indent} } catch (error: unknown) {`);
1433
- lines.push(`${indent} const isCancellation = CancellationError.isCancellationError(error);`);
1434
- lines.push(`${indent} ${awaitPrefix}${ctxVar}.sendStatusChangedEvent({`);
1435
- lines.push(`${indent} nodeTypeName: '${functionName}',`);
1436
- lines.push(`${indent} id: '${instanceId}',`);
1437
- lines.push(`${indent} executionIndex: ${safeId}Idx,`);
1438
- lines.push(`${indent} status: isCancellation ? 'CANCELLED' : 'FAILED',`);
1439
- lines.push(`${indent} });`);
1440
- lines.push(`${indent} if (!isCancellation) {`);
1441
- lines.push(`${indent} ${ctxVar}.sendLogErrorEvent({`);
1442
- lines.push(`${indent} nodeTypeName: '${functionName}',`);
1443
- lines.push(`${indent} id: '${instanceId}',`);
1444
- lines.push(`${indent} executionIndex: ${safeId}Idx,`);
1445
- lines.push(`${indent} error: error instanceof Error ? error.message : String(error),`);
1446
- lines.push(`${indent} });`);
1447
- lines.push(`${indent} }`);
1448
- lines.push(`${indent} throw error;`);
1449
- lines.push(`${indent} }`);
1450
- lines.push(`${indent}};`);
1451
- lines.push(`${indent}// Register lazy executor for pull node`);
1452
- lines.push(`${indent}${ctxVar}.registerPullExecutor('${instanceId}', ${safeId}_executor);`);
1453
- lines.push(``);
1454
- }
1455
- function generateNodeCallWithContext(instance, nodeType, workflow, _availableVars, lines, _allNodeTypes, indent, isAsync, useConst = false, // Use const for nodes that always execute (not in branches)
1456
- instanceParent, // Parent node ID for scope children (parent is const, no ! needed)
1457
- ctxVar = 'ctx', // Context variable name (for scoped contexts)
1458
- bundleMode = false, // Bundle mode uses params object pattern for wrapper functions
1459
- skipExecuteGuard = false, // Skip execute port STEP guard (for nodes inside branch blocks)
1460
- branchingNodes = new Set(), // Branching nodes set for port-aware STEP guards
1461
- production = false // When false, emit debug controller hooks (beforeNode/afterNode)
1462
- ) {
1463
- const instanceId = instance.id;
1464
- const safeId = toValidIdentifier(instanceId);
1465
- const functionName = nodeType.functionName;
1466
- // Check if this instance has pull execution enabled
1467
- const fullInstance = workflow.instances.find((i) => i.id === instanceId);
1468
- const pullConfig = fullInstance
1469
- ? getPullExecutionConfig(fullInstance, nodeType)
1470
- : { enabled: false, triggerPort: 'execute' };
1471
- // If this is a pull execution node, wrap it in a lazy function
1472
- if (pullConfig.enabled) {
1473
- generatePullNodeWithContext(instance, nodeType, workflow, lines, indent, isAsync, ctxVar, bundleMode, production);
1474
- return;
1475
- }
1476
- const stepInputs = Object.entries(nodeType.inputs).filter(([portName, portConfig]) => {
1477
- // Include the primary execute port for promoted nodes (useConst=false at top level)
1478
- // so they get a STEP guard from their conditional source.
1479
- // Skip execute guard for nodes inside branch blocks (execute is guaranteed by if/else).
1480
- if (isExecutePort(portName) && !useConst && !skipExecuteGuard) {
1481
- return portConfig.dataType === 'STEP';
1482
- }
1483
- return portConfig.dataType === 'STEP' && !isExecutePort(portName);
1484
- });
1485
- // Expression nodes don't declare 'execute' in their inputs, but the workflow
1486
- // connects STEP signals to their execute port. Include it for promoted expression
1487
- // nodes so they get a proper branch-aware STEP guard.
1488
- if (nodeType.expression && !useConst && !skipExecuteGuard && !stepInputs.some(([p]) => isExecutePort(p))) {
1489
- const hasExecuteConnection = workflow.connections.some((conn) => conn.to.node === instanceId && isExecutePort(conn.to.port));
1490
- if (hasExecuteConnection) {
1491
- stepInputs.push(['execute', { dataType: 'STEP' }]);
1492
- }
1493
- }
1494
- const stepSignalSources = [];
1495
- if (stepInputs.length > 0) {
1496
- workflow.connections.forEach((conn) => {
1497
- const toNode = conn.to.node;
1498
- const toPort = conn.to.port;
1499
- if (toNode === instanceId && stepInputs.some(([port]) => port === toPort)) {
1500
- const sourceNode = conn.from.node;
1501
- // Skip per-port scoped children - they don't have Idx in main scope
1502
- const sourceInstance = workflow.instances.find((i) => i.id === sourceNode);
1503
- if (sourceInstance && isPerPortScopedChild(sourceInstance, workflow, _allNodeTypes)) {
1504
- return;
1505
- }
1506
- if (!isStartNode(sourceNode) && !stepSignalSources.includes(sourceNode)) {
1507
- stepSignalSources.push(sourceNode);
1508
- }
1509
- }
1510
- });
1511
- }
1512
- let shouldIndent = false;
1513
- if (stepSignalSources.length > 0) {
1514
- const conditions = [];
1515
- const portToSources = new Map();
1516
- stepInputs.forEach(([portName]) => {
1517
- const sources = [];
1518
- workflow.connections.forEach((conn) => {
1519
- const toNode = conn.to.node;
1520
- const toPort = conn.to.port;
1521
- if (toNode === instanceId && toPort === portName) {
1522
- const sourceNode = conn.from.node;
1523
- if (!isStartNode(sourceNode)) {
1524
- // Skip per-port scoped children - they don't have Idx in main scope
1525
- const sourceInstance = workflow.instances.find((i) => i.id === sourceNode);
1526
- if (sourceInstance && isPerPortScopedChild(sourceInstance, workflow, _allNodeTypes)) {
1527
- return;
1528
- }
1529
- sources.push({ node: sourceNode, port: conn.from.port });
1530
- }
1531
- }
1532
- });
1533
- if (sources.length > 0) {
1534
- portToSources.set(portName, sources);
1535
- }
1536
- });
1537
- if (nodeType.executeWhen === EXECUTION_STRATEGIES.CONJUNCTION) {
1538
- // CONJUNCTION: Execute when ALL input ports have data (AND logic)
1539
- portToSources.forEach((sources, _portName) => {
1540
- if (sources.length === 1) {
1541
- conditions.push(buildStepSourceCondition(sources[0].node, sources[0].port, branchingNodes));
1542
- }
1543
- else {
1544
- const orCondition = sources.map((s) => buildStepSourceCondition(s.node, s.port, branchingNodes)).join(' || ');
1545
- conditions.push(`(${orCondition})`);
1546
- }
1547
- });
1548
- if (conditions.length > 0) {
1549
- const fullCondition = conditions.join(' && ');
1550
- lines.push(`${indent}if (${fullCondition}) {`);
1551
- indent = `${indent} `;
1552
- shouldIndent = true;
1553
- }
1554
- }
1555
- else if (nodeType.executeWhen === EXECUTION_STRATEGIES.DISJUNCTION) {
1556
- // DISJUNCTION: Execute when ANY input port has data (OR logic)
1557
- const allSources = [];
1558
- portToSources.forEach((sources) => {
1559
- sources.forEach((source) => {
1560
- if (!allSources.some((s) => s.node === source.node && s.port === source.port)) {
1561
- allSources.push(source);
1562
- }
1563
- });
1564
- });
1565
- if (allSources.length > 0) {
1566
- const fullCondition = allSources.map((s) => buildStepSourceCondition(s.node, s.port, branchingNodes)).join(' || ');
1567
- lines.push(`${indent}if (${fullCondition}) {`);
1568
- indent = `${indent} `;
1569
- shouldIndent = true;
1570
- }
1571
- }
1572
- else if (nodeType.executeWhen === EXECUTION_STRATEGIES.CUSTOM) {
1573
- // CUSTOM: User-provided execution condition
1574
- // Custom condition should be in nodeType.metadata.customExecuteCondition
1575
- const customCondition = nodeType.metadata?.customExecuteCondition;
1576
- if (customCondition && typeof customCondition === 'string') {
1577
- lines.push(`${indent}if (${customCondition}) {`);
1578
- indent = `${indent} `;
1579
- shouldIndent = true;
1580
- }
1581
- else {
1582
- // Fallback to CONJUNCTION if no custom condition provided
1583
- portToSources.forEach((sources, _portName) => {
1584
- if (sources.length === 1) {
1585
- conditions.push(buildStepSourceCondition(sources[0].node, sources[0].port, branchingNodes));
1586
- }
1587
- else {
1588
- const orCondition = sources.map((s) => buildStepSourceCondition(s.node, s.port, branchingNodes)).join(' || ');
1589
- conditions.push(`(${orCondition})`);
1590
- }
1591
- });
1592
- if (conditions.length > 0) {
1593
- const fullCondition = conditions.join(' && ');
1594
- lines.push(`${indent}if (${fullCondition}) {`);
1595
- indent = `${indent} `;
1596
- shouldIndent = true;
1597
- }
1598
- }
1599
- }
1600
- }
1601
- // Debug controller: beforeNode hook (step-through / checkpoint resume)
1602
- // When enabled, wraps the entire node execution in if(await __ctrl__.beforeNode(...))
1603
- // so checkpoint resume can skip already-completed nodes.
1604
- const emitDebugHooks = !production;
1605
- const outerIndent = indent; // preserve for closing brace
1606
- if (emitDebugHooks) {
1607
- // When useConst=true, the Idx variable would normally be declared with const
1608
- // inside the node execution block. Since debug hooks wrap that in if/else,
1609
- // we must hoist the declaration before the if block to keep it in scope.
1610
- if (useConst) {
1611
- lines.push(`${indent}let ${safeId}Idx: number;`);
1612
- }
1613
- const awaitHook = isAsync ? 'await ' : '';
1614
- lines.push(`${indent}if (${awaitHook}__ctrl__.beforeNode('${instanceId}', ${ctxVar})) {`);
1615
- indent = `${indent} `;
1616
- }
1617
- // When debug hooks hoist the declaration, we use assignment only inside the block.
1618
- const varDecl = (useConst && !emitDebugHooks) ? 'const ' : '';
1619
- const awaitPrefix = isAsync ? 'await ' : '';
1620
- lines.push(`${indent}${ctxVar}.checkAborted('${instanceId}');`);
1621
- lines.push(`${indent}${varDecl}${safeId}Idx = ${ctxVar}.addExecution('${instanceId}');`);
1622
- lines.push(`${indent}if (typeof globalThis !== 'undefined') (globalThis as unknown as { __fw_current_node_id__?: string }).__fw_current_node_id__ = '${instanceId}';`);
1623
- lines.push(`${indent}${awaitPrefix}${ctxVar}.sendStatusChangedEvent({`);
1624
- lines.push(`${indent} nodeTypeName: '${functionName}',`);
1625
- lines.push(`${indent} id: '${instanceId}',`);
1626
- lines.push(`${indent} executionIndex: ${safeId}Idx,`);
1627
- lines.push(`${indent} status: 'RUNNING',`);
1628
- lines.push(`${indent}});`);
1629
- lines.push(`${indent}try {`);
1630
- const getCall = isAsync ? `await ${ctxVar}.getVariable` : `${ctxVar}.getVariable`;
1631
- const setCall = isAsync ? `await ${ctxVar}.setVariable` : `${ctxVar}.setVariable`;
1632
- const args = buildNodeArgumentsWithContext({
1633
- node: nodeType,
1634
- workflow,
1635
- id: instanceId,
1636
- lines,
1637
- indent: `${indent} `,
1638
- getCall,
1639
- isAsync,
1640
- instanceParent,
1641
- emitInputEvents: true,
1642
- setCall,
1643
- nodeTypeName: functionName,
1644
- bundleMode,
1645
- production,
1646
- });
1647
- const resultVar = `${safeId}Result`;
1648
- const awaitKeyword = nodeType.isAsync ? 'await ' : '';
1649
- if (nodeType.variant === 'STUB') {
1650
- // Stub node: emit a runtime throw. The workflow was generated with generateStubs: true.
1651
- lines.push(`${indent} throw new Error('Node "${instanceId}" uses stub type "${functionName}" which has no implementation.');`);
1652
- }
1653
- else if (nodeType.variant === 'COERCION') {
1654
- // Coercion node: inline JS expression instead of function call
1655
- const coerceExprMap = {
1656
- __fw_toString: 'String',
1657
- __fw_toNumber: 'Number',
1658
- __fw_toBoolean: 'Boolean',
1659
- __fw_toJSON: 'JSON.stringify',
1660
- __fw_parseJSON: 'JSON.parse',
1661
- };
1662
- const coerceExpr = coerceExprMap[functionName] || 'String';
1663
- // args[0] is the value input (execute is skipped for expression nodes)
1664
- const valueArg = args[0] || 'undefined';
1665
- lines.push(`${indent} const ${resultVar} = ${coerceExpr}(${valueArg});`);
1666
- // Set the single result output port
1667
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: 'result', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, ${resultVar});`);
1668
- // Auto-set onSuccess/onFailure
1669
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: 'onSuccess', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, true);`);
1670
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: 'onFailure', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, false);`);
1671
- }
1672
- else if (nodeType.expression) {
1673
- // Expression node: call without execute, map raw return to output ports
1674
- // _impl returns data only; onSuccess/onFailure are auto-set in the workflow body
1675
- lines.push(`${indent} const ${resultVar} = ${awaitKeyword}${functionName}(${args.join(', ')});`);
1676
- // Determine data output ports (exclude control flow and scoped ports)
1677
- const dataOutputPorts = Object.keys(nodeType.outputs).filter((portName) => {
1678
- const portConfig = nodeType.outputs[portName];
1679
- if (portConfig.scope)
1680
- return false;
1681
- if (isSuccessPort(portName) || isFailurePort(portName))
1682
- return false;
1683
- if (portConfig.isControlFlow || portConfig.failure)
1684
- return false;
1685
- return true;
1686
- });
1687
- if (dataOutputPorts.length === 1) {
1688
- // Single data output: destructure if result is an object with the port key, else use raw value
1689
- // Extract to unknown-typed variable to prevent TypeScript from narrowing
1690
- // specific return types (e.g. boolean) to `never` in the typeof check
1691
- const portName = dataOutputPorts[0];
1692
- const rawVar = `${resultVar}_raw`;
1693
- lines.push(`${indent} const ${rawVar}: unknown = ${resultVar};`);
1694
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: '${portName}', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, typeof ${rawVar} === 'object' && ${rawVar} !== null && '${portName}' in ${rawVar} ? ${rawVar}.${portName} : ${rawVar});`);
1695
- }
1696
- else {
1697
- // Multiple data outputs: destructure from object return
1698
- dataOutputPorts.forEach((portName) => {
1699
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: '${portName}', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, ${resultVar}.${portName});`);
1700
- });
1701
- }
1702
- // Auto-set onSuccess/onFailure
1703
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: 'onSuccess', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, true);`);
1704
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: 'onFailure', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, false);`);
1705
- }
1706
- else if (nodeType.variant === 'MAP_ITERATOR') {
1707
- // MAP_ITERATOR: inline iteration — no user function to call
1708
- // args: [execute, items, scopeFn]
1709
- const executeArg = args[0];
1710
- const itemsArg = args[1];
1711
- const scopeFnArg = args[2];
1712
- lines.push(`${indent} let ${resultVar}: { onSuccess: boolean; onFailure: boolean; results: unknown[] };`);
1713
- lines.push(`${indent} if (!${executeArg}) {`);
1714
- lines.push(`${indent} ${resultVar} = { onSuccess: false, onFailure: false, results: [] };`);
1715
- lines.push(`${indent} } else {`);
1716
- lines.push(`${indent} const __results: unknown[] = [];`);
1717
- lines.push(`${indent} for (const __item of ${itemsArg}) {`);
1718
- lines.push(`${indent} __results.push((${isAsync ? 'await ' : ''}${scopeFnArg}(true, __item)).processed);`);
1719
- lines.push(`${indent} }`);
1720
- lines.push(`${indent} ${resultVar} = { onSuccess: true, onFailure: false, results: __results };`);
1721
- lines.push(`${indent} }`);
1722
- // Set output ports from result
1723
- Object.keys(nodeType.outputs).forEach((portName) => {
1724
- const portConfig = nodeType.outputs[portName];
1725
- if (portConfig.scope)
1726
- return;
1727
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: '${portName}', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, ${resultVar}.${portName});`);
1728
- });
1729
- }
1730
- else if (nodeType.variant === 'IMPORTED_WORKFLOW' || nodeType.variant === 'WORKFLOW') {
1731
- // Check if this is a workflow call (IMPORTED_WORKFLOW or WORKFLOW variant)
1732
- // Workflows use (execute, params) signature where params is an object
1733
- // Regular nodes use (execute, arg1, arg2, ...) positional signature
1734
- // For workflow calls, wrap data args in an object and include recursion depth
1735
- const executeArg = args[0]; // First arg is always execute
1736
- const dataArgs = args.slice(1); // Rest are data inputs
1737
- const inputPortNames = Object.keys(nodeType.inputs).filter((p) => !isExecutePort(p));
1738
- // Build params object: { portName1: value1, portName2: value2, ..., __rd__: __rd__ + 1 }
1739
- // Assign to variable first to avoid TypeScript excess property checking on object literals
1740
- const paramsEntries = inputPortNames.map((portName, i) => `${portName}: ${dataArgs[i]}`);
1741
- paramsEntries.push('__rd__: __rd__ + 1');
1742
- const paramsObj = `{ ${paramsEntries.join(', ')} }`;
1743
- const paramsVar = `__${safeId}Params__`;
1744
- lines.push(`${indent} const ${paramsVar} = ${paramsObj};`);
1745
- lines.push(`${indent} const ${resultVar} = ${awaitKeyword}${functionName}(${executeArg}, ${paramsVar});`);
1746
- // STEP Port Architecture: Extract ALL outputs from result, including onSuccess/onFailure
1747
- // Skip scoped OUTPUT ports - they're parameters to scope functions, not return values
1748
- Object.keys(nodeType.outputs).forEach((portName) => {
1749
- const portConfig = nodeType.outputs[portName];
1750
- // Skip scoped OUTPUT ports - they don't exist in the function return value
1751
- if (portConfig.scope)
1752
- return;
1753
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: '${portName}', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, ${resultVar}.${portName});`);
1754
- });
1755
- }
1756
- else if (nodeType.scope || (nodeType.scopes && nodeType.scopes.length > 0)) {
1757
- // Scoped node call with positional arguments (uses _impl signature)
1758
- // Scoped nodes have callback parameters that can't be passed via params object
1759
- lines.push(`${indent} const ${resultVar} = ${awaitKeyword}${functionName}(${args.join(', ')});`);
1760
- // STEP Port Architecture: Extract ALL outputs from result, including onSuccess/onFailure
1761
- // Skip scoped OUTPUT ports - they're parameters to scope functions, not return values
1762
- Object.keys(nodeType.outputs).forEach((portName) => {
1763
- const portConfig = nodeType.outputs[portName];
1764
- // Skip scoped OUTPUT ports - they don't exist in the function return value
1765
- if (portConfig.scope)
1766
- return;
1767
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: '${portName}', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, ${resultVar}.${portName});`);
1768
- });
1769
- }
1770
- else {
1771
- // Regular node call - always use positional args
1772
- // In bundle mode we import _impl which takes (execute, ...positional_args)
1773
- lines.push(`${indent} const ${resultVar} = ${awaitKeyword}${functionName}(${args.join(', ')});`);
1774
- // STEP Port Architecture: Extract ALL outputs from result, including onSuccess/onFailure
1775
- // Skip scoped OUTPUT ports - they're parameters to scope functions, not return values
1776
- Object.keys(nodeType.outputs).forEach((portName) => {
1777
- const portConfig = nodeType.outputs[portName];
1778
- // Skip scoped OUTPUT ports - they don't exist in the function return value
1779
- if (portConfig.scope)
1780
- return;
1781
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: '${portName}', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, ${resultVar}.${portName});`);
1782
- });
1783
- }
1784
- lines.push(`${indent} ${awaitPrefix}${ctxVar}.sendStatusChangedEvent({`);
1785
- lines.push(`${indent} nodeTypeName: '${functionName}',`);
1786
- lines.push(`${indent} id: '${instanceId}',`);
1787
- lines.push(`${indent} executionIndex: ${safeId}Idx,`);
1788
- lines.push(`${indent} status: 'SUCCEEDED',`);
1789
- lines.push(`${indent} });`);
1790
- // Debug controller: afterNode hook (checkpoint write, step pause)
1791
- if (emitDebugHooks) {
1792
- const awaitHook = isAsync ? 'await ' : '';
1793
- lines.push(`${indent} ${awaitHook}__ctrl__.afterNode('${instanceId}', ${ctxVar});`);
1794
- }
1795
- lines.push(`${indent}} catch (error: unknown) {`);
1796
- lines.push(`${indent} const isCancellation = CancellationError.isCancellationError(error);`);
1797
- lines.push(`${indent} ${awaitPrefix}${ctxVar}.sendStatusChangedEvent({`);
1798
- lines.push(`${indent} nodeTypeName: '${functionName}',`);
1799
- lines.push(`${indent} id: '${instanceId}',`);
1800
- lines.push(`${indent} executionIndex: ${safeId}Idx,`);
1801
- lines.push(`${indent} status: isCancellation ? 'CANCELLED' : 'FAILED',`);
1802
- lines.push(`${indent} });`);
1803
- lines.push(`${indent} if (!isCancellation) {`);
1804
- lines.push(`${indent} ${ctxVar}.sendLogErrorEvent({`);
1805
- lines.push(`${indent} nodeTypeName: '${functionName}',`);
1806
- lines.push(`${indent} id: '${instanceId}',`);
1807
- lines.push(`${indent} executionIndex: ${safeId}Idx,`);
1808
- lines.push(`${indent} error: error instanceof Error ? error.message : String(error),`);
1809
- lines.push(`${indent} });`);
1810
- if (nodeType.expression) {
1811
- // Expression node: auto-set failure flags in catch block
1812
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: 'onSuccess', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, false);`);
1813
- lines.push(`${indent} ${setCall}({ id: '${instanceId}', portName: 'onFailure', executionIndex: ${safeId}Idx, nodeTypeName: '${functionName}' }, true);`);
1814
- }
1815
- lines.push(`${indent} }`);
1816
- lines.push(`${indent} throw error;`);
1817
- lines.push(`${indent}}`);
1818
- // Close the debug controller beforeNode if block
1819
- if (emitDebugHooks) {
1820
- // Else block: node was skipped (checkpoint resume).
1821
- // Register execution so downstream nodes can reference {safeId}Idx.
1822
- lines.push(`${outerIndent}} else {`);
1823
- lines.push(`${outerIndent} ${varDecl}${safeId}Idx = ${ctxVar}.addExecution('${instanceId}');`);
1824
- lines.push(`${outerIndent}}`);
1825
- }
1826
- if (shouldIndent) {
1827
- const originalIndent = outerIndent.slice(0, -2);
1828
- lines.push(`${originalIndent}}`);
1829
- }
1830
- }
1831
- //# sourceMappingURL=unified.js.map