@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
@@ -0,0 +1,3291 @@
1
+ import { createRequire as __createRequire } from "module";
2
+ const require = __createRequire(import.meta.url);
3
+
4
+ // src/cli/templates/shared/case.ts
5
+ function toCamelCase(str) {
6
+ const leadingMatch = str.match(/^[_$]+/);
7
+ const leading = leadingMatch ? leadingMatch[0] : "";
8
+ const rest = leading ? str.slice(leading.length) : str;
9
+ const result = rest.replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : "").replace(/^[^a-zA-Z_$]+/, "").replace(/^./, (c) => c.toLowerCase());
10
+ const final = leading + result;
11
+ return final || "_" + str.replace(/[^a-zA-Z0-9_$]/g, "");
12
+ }
13
+ function toPascalCase(str) {
14
+ const camel = toCamelCase(str);
15
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
16
+ }
17
+
18
+ // src/cli/templates/workflows/sequential.ts
19
+ var configSchema = {
20
+ nodes: {
21
+ type: "string",
22
+ label: "Node Names",
23
+ description: 'Comma-separated list of node function names (e.g. "fetch,parse,store")',
24
+ placeholder: "validateData,transformData,outputResult"
25
+ },
26
+ input: {
27
+ type: "string",
28
+ label: "Input Port Name",
29
+ description: "Name of the input data port",
30
+ default: "data",
31
+ placeholder: "data"
32
+ },
33
+ output: {
34
+ type: "string",
35
+ label: "Output Port Name",
36
+ description: "Name of the output data port",
37
+ default: "result",
38
+ placeholder: "result"
39
+ }
40
+ };
41
+ function generateDefaultTemplate(workflowName, asyncKeyword, returnType) {
42
+ return `
43
+ // Use @expression for most functions, normal mode only for error-with-data or void side-effects
44
+
45
+ /**
46
+ * Validates input data
47
+ * Normal mode: explicit error routing with data on failure
48
+ *
49
+ * @flowWeaver nodeType
50
+ * @label Validate
51
+ * @input data [order:1] - Data to validate
52
+ * @input execute [order:0] - Execute
53
+ * @output data [order:2] - Validated data
54
+ * @output isValid [order:3] - Validation passed
55
+ * @output error [order:4] - Validation error message
56
+ * @output onSuccess [order:0] - On Success
57
+ * @output onFailure [order:1] - On Failure
58
+ */
59
+ function validateData(
60
+ execute: boolean,
61
+ data: any
62
+ ): { onSuccess: boolean; onFailure: boolean; data: any; isValid: boolean; error: string | null } {
63
+ if (!execute) {
64
+ return { onSuccess: false, onFailure: false, data: null, isValid: false, error: null };
65
+ }
66
+
67
+ // TODO: Add validation logic
68
+ if (!data) {
69
+ return { onSuccess: false, onFailure: true, data: null, isValid: false, error: "Data is required" };
70
+ }
71
+
72
+ return { onSuccess: true, onFailure: false, data, isValid: true, error: null };
73
+ }
74
+
75
+ /**
76
+ * Transforms validated data
77
+ *
78
+ * @flowWeaver nodeType
79
+ * @expression
80
+ * @label Transform
81
+ * @input data [order:0] - Data to transform
82
+ * @output data [order:0] - Transformed data
83
+ */
84
+ function transformData(data: any): { data: any } {
85
+ // TODO: Add transformation logic
86
+ return { data: { ...data, processedAt: new Date().toISOString() } };
87
+ }
88
+
89
+ /**
90
+ * Outputs the final result
91
+ *
92
+ * @flowWeaver nodeType
93
+ * @expression
94
+ * @label Output
95
+ * @input data [order:0] - Data to output
96
+ * @output result [order:0] - Final result
97
+ */
98
+ function outputResult(data: any): { result: any } {
99
+ return { result: data };
100
+ }
101
+
102
+ /**
103
+ * @flowWeaver workflow
104
+ * @node validator validateData [color: "green"] [icon: "verified"] [suppress: "UNUSED_OUTPUT_PORT"]
105
+ * @node transformer transformData [color: "blue"] [icon: "sync"]
106
+ * @node outputter outputResult [color: "cyan"] [icon: "inventory"]
107
+ * @path Start -> validator -> transformer -> outputter -> Exit
108
+ * @path Start -> validator:fail -> Exit
109
+ * @param execute [order:0] - Execute
110
+ * @param data [order:1] - Input data
111
+ * @returns onSuccess [order:0] - On Success
112
+ * @returns onFailure [order:1] - On Failure
113
+ * @returns result [order:2] - Processed result
114
+ * @returns error [order:3] - Error message if failed
115
+ */
116
+ export ${asyncKeyword}function ${workflowName}(
117
+ execute: boolean,
118
+ params: { data: any }
119
+ ): ${returnType} {
120
+ throw new Error("Compile with: fw compile <file>");
121
+ }
122
+ `.trim();
123
+ }
124
+ function generateCustomTemplate(workflowName, asyncKeyword, returnType, nodeNames, inputPort, outputPort) {
125
+ const nodeTypeDefs = nodeNames.map((name, i) => {
126
+ const isFirst = i === 0;
127
+ const isLast = i === nodeNames.length - 1;
128
+ const inputPortName = isFirst ? inputPort : "data";
129
+ const outputPortName = isLast ? outputPort : "data";
130
+ return `/**
131
+ * ${name} step
132
+ *
133
+ * @flowWeaver nodeType
134
+ * @expression
135
+ * @label ${name.charAt(0).toUpperCase() + name.slice(1)}
136
+ * @input ${inputPortName} [order:0] - Input data
137
+ * @output ${outputPortName} [order:0] - Output data
138
+ */
139
+ function ${name}(${inputPortName}: any): { ${outputPortName}: any } {
140
+ // TODO: Implement ${name} logic
141
+ return { ${outputPortName}: ${inputPortName} };
142
+ }`;
143
+ });
144
+ const stepColors = ["green", "blue", "cyan", "orange", "purple", "teal", "pink", "yellow"];
145
+ const nodeAnnotations = nodeNames.map((name, i) => {
146
+ const color = stepColors[i % stepColors.length];
147
+ return ` * @node step${i} ${name} [color: "${color}"] [icon: "settings"]`;
148
+ }).join("\n");
149
+ const pathNodes = ["Start", ...nodeNames.map((_, i) => `step${i}`), "Exit"];
150
+ const connections = [];
151
+ connections.push(` * @path ${pathNodes.join(" -> ")}`);
152
+ connections.push(` * @path Start -> step0:fail -> Exit`);
153
+ return `${nodeTypeDefs.join("\n\n")}
154
+
155
+ /**
156
+ * @flowWeaver workflow
157
+ ${nodeAnnotations}
158
+ ${connections.join("\n")}
159
+ * @param execute [order:0] - Execute
160
+ * @param ${inputPort} [order:1] - Input data
161
+ * @returns onSuccess [order:0] - On Success
162
+ * @returns onFailure [order:1] - On Failure
163
+ * @returns ${outputPort} [order:2] - Processed result
164
+ */
165
+ export ${asyncKeyword}function ${workflowName}(
166
+ execute: boolean,
167
+ params: { ${inputPort}: any }
168
+ ): ${returnType} {
169
+ throw new Error("Compile with: fw compile <file>");
170
+ }`.trim();
171
+ }
172
+ var sequentialTemplate = {
173
+ id: "sequential",
174
+ name: "Sequential Pipeline",
175
+ description: "Linear pipeline: validate -> transform -> output",
176
+ category: "data-processing",
177
+ configSchema,
178
+ generate: (opts) => {
179
+ const { workflowName, async: isAsync, config } = opts;
180
+ const asyncKeyword = isAsync ? "async " : "";
181
+ const returnTypeFor = (outputPort2, withError) => {
182
+ const body = `onSuccess: boolean, onFailure: boolean, ${outputPort2}: any${withError ? ", error: string | null" : ""}`;
183
+ return isAsync ? `Promise<{ ${body} }>` : `{ ${body} }`;
184
+ };
185
+ const customNodes = config?.nodes;
186
+ const inputPort = config?.input || "data";
187
+ const outputPort = config?.output || "result";
188
+ if (customNodes && Array.isArray(customNodes) && customNodes.length > 0) {
189
+ return generateCustomTemplate(
190
+ workflowName,
191
+ asyncKeyword,
192
+ returnTypeFor(outputPort, false),
193
+ customNodes,
194
+ inputPort,
195
+ outputPort
196
+ );
197
+ }
198
+ if (inputPort !== "data" || outputPort !== "result") {
199
+ return generateCustomTemplate(
200
+ workflowName,
201
+ asyncKeyword,
202
+ returnTypeFor(outputPort, false),
203
+ ["validateData", "transformData", "outputResult"],
204
+ inputPort,
205
+ outputPort
206
+ );
207
+ }
208
+ return generateDefaultTemplate(workflowName, asyncKeyword, returnTypeFor("result", true));
209
+ }
210
+ };
211
+
212
+ // src/cli/templates/workflows/foreach.ts
213
+ var foreachTemplate = {
214
+ id: "foreach",
215
+ name: "ForEach Batch",
216
+ description: "Batch processing with iteration over arrays",
217
+ category: "data-processing",
218
+ generate: (opts) => {
219
+ const { workflowName, async: isAsync } = opts;
220
+ const asyncKeyword = isAsync ? "async " : "";
221
+ const returnType = isAsync ? "Promise<{ onSuccess: boolean; onFailure: boolean; results: any[]; successCount: number; failedCount: number }>" : "{ onSuccess: boolean; onFailure: boolean; results: any[]; successCount: number; failedCount: number }";
222
+ return `
223
+ /**
224
+ * Iterates over items and processes each one.
225
+ * Normal mode on purpose: a scope owner drives its child through scoped STEP ports.
226
+ *
227
+ * @flowWeaver nodeType
228
+ * @label For Each Item
229
+ * @input items [order:1] - Array of items to iterate
230
+ * @input success scope:processItem [order:0] - From child onSuccess
231
+ * @input failure scope:processItem [order:1] - From child onFailure
232
+ * @input result scope:processItem [order:2] - Result from child
233
+ * @input execute [order:0] - Execute
234
+ * @output start scope:processItem [order:0] - Triggers child execute
235
+ * @output item scope:processItem [order:1] - Current item to process
236
+ * @output results [order:2] - Collected results after iteration
237
+ * @output onSuccess [order:0] - On Success
238
+ * @output onFailure [order:1] - On Failure
239
+ */
240
+ function forEachItem(
241
+ execute: boolean,
242
+ items: any[],
243
+ processItem: (start: boolean, item: any) => { success: boolean; failure: boolean; result: any }
244
+ ): { onSuccess: boolean; onFailure: boolean; results: any[] } {
245
+ if (!execute) {
246
+ return { onSuccess: false, onFailure: false, results: [] };
247
+ }
248
+
249
+ const results: any[] = [];
250
+ for (const item of items) {
251
+ const r = processItem(true, item);
252
+ results.push(r.result);
253
+ }
254
+
255
+ return { onSuccess: true, onFailure: false, results };
256
+ }
257
+
258
+ /**
259
+ * Processes a single item. A throw here aborts the whole batch with that
260
+ * error; to record a per-item failure instead, return it as part of the result.
261
+ *
262
+ * @flowWeaver nodeType
263
+ * @expression
264
+ * @label Process Item
265
+ * @input item - Item to process
266
+ * @output result - Processed result
267
+ */
268
+ function processItem(item: any): { result: any } {
269
+ // TODO: Add your processing logic here
270
+ return { result: { ...item, processed: true } };
271
+ }
272
+
273
+ /**
274
+ * Aggregates results from iteration
275
+ *
276
+ * @flowWeaver nodeType
277
+ * @expression
278
+ * @label Aggregate Results
279
+ * @input results - Array of processed results
280
+ * @output successCount - Number of successes
281
+ * @output failedCount - Number of failures
282
+ */
283
+ function aggregateResults(results: any[]): { successCount: number; failedCount: number } {
284
+ const successCount = results.filter(r => r?.processed).length;
285
+ return { successCount, failedCount: results.length - successCount };
286
+ }
287
+
288
+ /**
289
+ * @flowWeaver workflow
290
+ * @node iterator forEachItem [color: "purple"] [icon: "repeat"] [suppress: "DESIGN_SCOPE_NO_FAILURE_EXIT"]
291
+ * @node processor processItem iterator.processItem [color: "blue"] [icon: "settings"]
292
+ * @node aggregator aggregateResults [color: "teal"] [icon: "inventory"]
293
+ * @path Start -> iterator -> aggregator -> Exit
294
+ * @connect iterator.start:processItem -> processor.execute
295
+ * @connect iterator.item:processItem -> processor.item
296
+ * @connect processor.result -> iterator.result:processItem
297
+ * @connect processor.onSuccess -> iterator.success:processItem
298
+ * @connect processor.onFailure -> iterator.failure:processItem
299
+ * @param execute [order:0] - Execute
300
+ * @param items [order:1] - Array of items to process
301
+ * @returns onSuccess [order:0] - On Success
302
+ * @returns onFailure [order:1] - On Failure
303
+ * @returns results [order:2] - Processed results
304
+ * @returns successCount [order:3] - Number of successful items
305
+ * @returns failedCount [order:4] - Number of failed items
306
+ */
307
+ export ${asyncKeyword}function ${workflowName}(
308
+ execute: boolean,
309
+ params: { items: any[] }
310
+ ): ${returnType} {
311
+ throw new Error("Compile with: fw compile <file>");
312
+ }
313
+ `.trim();
314
+ }
315
+ };
316
+
317
+ // src/cli/templates/workflows/conditional.ts
318
+ var conditionalTemplate = {
319
+ id: "conditional",
320
+ name: "Conditional Router",
321
+ description: "Route data based on conditions with branching paths",
322
+ category: "automation",
323
+ generate: (opts) => {
324
+ const { workflowName, async: isAsync } = opts;
325
+ const asyncKeyword = isAsync ? "async " : "";
326
+ const returnType = isAsync ? "Promise<{ onSuccess: boolean; onFailure: boolean; successResult?: any; failureResult?: any }>" : "{ onSuccess: boolean; onFailure: boolean; successResult?: any; failureResult?: any }";
327
+ return `
328
+ /**
329
+ * Evaluates condition and routes data.
330
+ * onSuccess = condition met (true path), onFailure = condition not met (false path).
331
+ * Errors are caught internally and returned via the onFailure path.
332
+ *
333
+ * @flowWeaver nodeType
334
+ * @label Evaluate Condition
335
+ * @input data [order:1] - Data to evaluate
336
+ * @input execute [order:0] - Execute
337
+ * @output conditionTrue [order:2] - Data if condition passed
338
+ * @output conditionFalse [order:3] - Data if condition failed
339
+ * @output conditionMet [order:4] - Whether condition was met
340
+ * @output onSuccess [order:0] - Condition passed (routes to success handler)
341
+ * @output onFailure [order:1] - Condition not met (routes to failure handler)
342
+ */
343
+ function evaluateCondition(
344
+ execute: boolean,
345
+ data: any
346
+ ): { onSuccess: boolean; onFailure: boolean; conditionTrue: any; conditionFalse: any; conditionMet: boolean } {
347
+ if (!execute) {
348
+ return { onSuccess: false, onFailure: false, conditionTrue: null, conditionFalse: null, conditionMet: false };
349
+ }
350
+
351
+ try {
352
+ // TODO: Define your condition logic
353
+ const conditionMet = Boolean(data && data.isValid);
354
+
355
+ if (conditionMet) {
356
+ return { onSuccess: true, onFailure: false, conditionTrue: data, conditionFalse: null, conditionMet: true };
357
+ } else {
358
+ return { onSuccess: false, onFailure: true, conditionTrue: null, conditionFalse: data, conditionMet: false };
359
+ }
360
+ } catch (err) {
361
+ // On error, route to failure path with the original data
362
+ return { onSuccess: false, onFailure: true, conditionTrue: null, conditionFalse: data, conditionMet: false };
363
+ }
364
+ }
365
+
366
+ /**
367
+ * Handles success path
368
+ *
369
+ * @flowWeaver nodeType
370
+ * @label Handle Success
371
+ * @input data [order:1] - Data from success path
372
+ * @input execute [order:0] - Execute
373
+ * @output result [order:2] - Success result
374
+ * @output onSuccess [order:0] - On Success
375
+ * @output onFailure [order:1] - On Failure
376
+ */
377
+ function handleSuccess(
378
+ execute: boolean,
379
+ data: any
380
+ ): { onSuccess: boolean; onFailure: boolean; result: any } {
381
+ if (!execute) {
382
+ return { onSuccess: false, onFailure: false, result: null };
383
+ }
384
+
385
+ // TODO: Handle success case
386
+ return { onSuccess: true, onFailure: false, result: { status: "success", data } };
387
+ }
388
+
389
+ /**
390
+ * Handles failure path
391
+ *
392
+ * @flowWeaver nodeType
393
+ * @label Handle Failure
394
+ * @input data [order:1] - Data from failure path
395
+ * @input execute [order:0] - Execute
396
+ * @output result [order:2] - Failure result
397
+ * @output onSuccess [order:0] - On Success
398
+ * @output onFailure [order:1] - On Failure
399
+ */
400
+ function handleFailure(
401
+ execute: boolean,
402
+ data: any
403
+ ): { onSuccess: boolean; onFailure: boolean; result: any } {
404
+ if (!execute) {
405
+ return { onSuccess: false, onFailure: false, result: null };
406
+ }
407
+
408
+ // TODO: Handle failure case
409
+ return { onSuccess: true, onFailure: false, result: { status: "failure", data } };
410
+ }
411
+
412
+ /**
413
+ * @flowWeaver workflow
414
+ * @node router evaluateCondition [color: "orange"] [icon: "altRoute"] [suppress: "UNUSED_OUTPUT_PORT"]
415
+ * @node successHandler handleSuccess [color: "green"] [icon: "checkCircle"]
416
+ * @node failureHandler handleFailure [color: "red"] [icon: "error"]
417
+ * @connect Start.execute -> router.execute
418
+ * @connect Start.data -> router.data
419
+ * @connect router.onSuccess -> successHandler.execute
420
+ * @connect router.conditionTrue -> successHandler.data
421
+ * @connect router.onFailure -> failureHandler.execute
422
+ * @connect router.conditionFalse -> failureHandler.data
423
+ * @connect successHandler.result -> Exit.successResult
424
+ * @connect successHandler.onSuccess -> Exit.onSuccess
425
+ * @connect failureHandler.result -> Exit.failureResult
426
+ * @connect failureHandler.onSuccess -> Exit.onFailure
427
+ * @param execute [order:0] - Execute
428
+ * @param data [order:1] - Input data to route
429
+ * @returns onSuccess [order:0] - Success path completed
430
+ * @returns onFailure [order:1] - Failure path completed
431
+ * @returns successResult [order:2] - Result from success path
432
+ * @returns failureResult [order:3] - Result from failure path
433
+ */
434
+ export ${asyncKeyword}function ${workflowName}(
435
+ execute: boolean,
436
+ params: { data: any }
437
+ ): ${returnType} {
438
+ throw new Error("Compile with: fw compile <file>");
439
+ }
440
+ `.trim();
441
+ }
442
+ };
443
+
444
+ // src/cli/templates/providers/index.ts
445
+ function generateOpenAIProvider(opts) {
446
+ const model = opts.model || "gpt-4o";
447
+ const apiKey = opts.apiKeyEnvVar || "OPENAI_API_KEY";
448
+ return `
449
+ /* ============================================================
450
+ * OPENAI PROVIDER
451
+ * Set ${apiKey} environment variable before running
452
+ * ============================================================ */
453
+
454
+ const ${apiKey} = process.env.${apiKey};
455
+ if (!${apiKey}) {
456
+ throw new Error('Missing ${apiKey} environment variable');
457
+ }
458
+
459
+ const _defaultLlmProvider: LLMProvider = {
460
+ async chat(messages, options) {
461
+ const response = await fetch('https://api.openai.com/v1/chat/completions', {
462
+ method: 'POST',
463
+ headers: {
464
+ 'Authorization': \`Bearer \${${apiKey}}\`,
465
+ 'Content-Type': 'application/json',
466
+ },
467
+ body: JSON.stringify({
468
+ model: options?.model ?? '${model}',
469
+ messages: messages.map(m => ({
470
+ role: m.role,
471
+ content: m.content,
472
+ ...(m.toolCallId && { tool_call_id: m.toolCallId }),
473
+ })),
474
+ tools: options?.tools?.map(t => ({
475
+ type: 'function',
476
+ function: { name: t.name, description: t.description, parameters: t.parameters },
477
+ })),
478
+ temperature: options?.temperature,
479
+ max_tokens: options?.maxTokens,
480
+ }),
481
+ });
482
+
483
+ if (!response.ok) {
484
+ const error = await response.text();
485
+ throw new Error(\`OpenAI API error: \${response.status} \${error}\`);
486
+ }
487
+
488
+ const data = await response.json();
489
+ const choice = data.choices[0];
490
+
491
+ return {
492
+ content: choice.message.content,
493
+ toolCalls: choice.message.tool_calls?.map((tc: any) => ({
494
+ id: tc.id,
495
+ name: tc.function.name,
496
+ arguments: JSON.parse(tc.function.arguments),
497
+ })) ?? [],
498
+ finishReason: choice.finish_reason === 'tool_calls' ? 'tool_calls' : 'stop',
499
+ };
500
+ },
501
+ };
502
+
503
+ const llmProvider: LLMProvider = _defaultLlmProvider;
504
+ `;
505
+ }
506
+ function generateAnthropicProvider(opts) {
507
+ const model = opts.model || "claude-3-5-sonnet-20241022";
508
+ const apiKey = opts.apiKeyEnvVar || "ANTHROPIC_API_KEY";
509
+ return `
510
+ /* ============================================================
511
+ * ANTHROPIC PROVIDER
512
+ * Set ${apiKey} environment variable before running
513
+ * ============================================================ */
514
+
515
+ const ${apiKey} = process.env.${apiKey};
516
+ if (!${apiKey}) {
517
+ throw new Error('Missing ${apiKey} environment variable');
518
+ }
519
+
520
+ const _defaultLlmProvider: LLMProvider = {
521
+ async chat(messages, options) {
522
+ // Separate system message (Anthropic handles it differently)
523
+ const systemMessage = messages.find(m => m.role === 'system');
524
+ const chatMessages = messages.filter(m => m.role !== 'system');
525
+
526
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
527
+ method: 'POST',
528
+ headers: {
529
+ 'x-api-key': ${apiKey},
530
+ 'anthropic-version': '2023-06-01',
531
+ 'Content-Type': 'application/json',
532
+ },
533
+ body: JSON.stringify({
534
+ model: options?.model ?? '${model}',
535
+ max_tokens: options?.maxTokens ?? 4096,
536
+ system: systemMessage?.content ?? options?.systemPrompt,
537
+ messages: chatMessages.map(m => {
538
+ if (m.role === 'tool') {
539
+ return {
540
+ role: 'user',
541
+ content: [{ type: 'tool_result', tool_use_id: m.toolCallId, content: m.content }],
542
+ };
543
+ }
544
+ return { role: m.role, content: m.content };
545
+ }),
546
+ tools: options?.tools?.map(t => ({
547
+ name: t.name,
548
+ description: t.description,
549
+ input_schema: { type: 'object', properties: t.parameters.properties, required: t.parameters.required },
550
+ })),
551
+ }),
552
+ });
553
+
554
+ if (!response.ok) {
555
+ const error = await response.text();
556
+ throw new Error(\`Anthropic API error: \${response.status} \${error}\`);
557
+ }
558
+
559
+ const data = await response.json();
560
+
561
+ let content: string | null = null;
562
+ const toolCalls: LLMToolCall[] = [];
563
+
564
+ for (const block of data.content) {
565
+ if (block.type === 'text') content = block.text;
566
+ if (block.type === 'tool_use') {
567
+ toolCalls.push({ id: block.id, name: block.name, arguments: block.input });
568
+ }
569
+ }
570
+
571
+ return {
572
+ content,
573
+ toolCalls,
574
+ finishReason: data.stop_reason === 'tool_use' ? 'tool_calls' : 'stop',
575
+ };
576
+ },
577
+ };
578
+
579
+ const llmProvider: LLMProvider = _defaultLlmProvider;
580
+ `;
581
+ }
582
+ function generateOllamaProvider(opts) {
583
+ const model = opts.model || "llama3.2";
584
+ return `
585
+ /* ============================================================
586
+ * OLLAMA PROVIDER (Local)
587
+ * Ensure Ollama is running: ollama serve
588
+ * Pull model first: ollama pull ${model}
589
+ * ============================================================ */
590
+
591
+ const OLLAMA_BASE_URL = process.env.OLLAMA_BASE_URL ?? 'http://localhost:11434';
592
+
593
+ const _defaultLlmProvider: LLMProvider = {
594
+ async chat(messages, options) {
595
+ const response = await fetch(\`\${OLLAMA_BASE_URL}/api/chat\`, {
596
+ method: 'POST',
597
+ headers: { 'Content-Type': 'application/json' },
598
+ body: JSON.stringify({
599
+ model: options?.model ?? '${model}',
600
+ messages: messages.map(m => ({ role: m.role, content: m.content })),
601
+ stream: false,
602
+ options: {
603
+ temperature: options?.temperature,
604
+ num_predict: options?.maxTokens,
605
+ },
606
+ }),
607
+ });
608
+
609
+ if (!response.ok) {
610
+ const error = await response.text();
611
+ throw new Error(\`Ollama error: \${response.status} \${error}\`);
612
+ }
613
+
614
+ const data = await response.json();
615
+
616
+ return {
617
+ content: data.message?.content ?? null,
618
+ toolCalls: [], // Ollama tool support varies by model
619
+ finishReason: 'stop',
620
+ };
621
+ },
622
+ };
623
+
624
+ const llmProvider: LLMProvider = _defaultLlmProvider;
625
+ `;
626
+ }
627
+ function generateMockProvider() {
628
+ return `
629
+ /* ============================================================
630
+ * MOCK PROVIDER (For Testing)
631
+ * Replace with real provider for production use
632
+ * ============================================================ */
633
+
634
+ const _defaultLlmProvider: LLMProvider = {
635
+ async chat(messages, options) {
636
+ const last = messages[messages.length - 1];
637
+
638
+ // Simulate tool call if message contains "search"
639
+ if (options?.tools && last.content.toLowerCase().includes('search')) {
640
+ return {
641
+ content: null,
642
+ toolCalls: [{
643
+ id: 'call_' + Date.now(),
644
+ name: 'search',
645
+ arguments: { query: last.content },
646
+ }],
647
+ finishReason: 'tool_calls',
648
+ };
649
+ }
650
+
651
+ return {
652
+ content: '[Mock response] ' + last.content,
653
+ toolCalls: [],
654
+ finishReason: 'stop',
655
+ };
656
+ },
657
+ };
658
+
659
+ const llmProvider: LLMProvider = _defaultLlmProvider;
660
+ `;
661
+ }
662
+ function getProviderCode(provider, model) {
663
+ const opts = { model: model || "" };
664
+ switch (provider) {
665
+ case "openai":
666
+ return generateOpenAIProvider({ ...opts, model: model || "gpt-4o" });
667
+ case "anthropic":
668
+ return generateAnthropicProvider({
669
+ ...opts,
670
+ model: model || "claude-3-5-sonnet-20241022"
671
+ });
672
+ case "ollama":
673
+ return generateOllamaProvider({ ...opts, model: model || "llama3.2" });
674
+ case "mock":
675
+ default:
676
+ return generateMockProvider();
677
+ }
678
+ }
679
+
680
+ // src/cli/templates/shared/llm-types.ts
681
+ var LLM_CORE_TYPES = `interface LLMMessage {
682
+ role: 'system' | 'user' | 'assistant' | 'tool';
683
+ content: string;
684
+ toolCallId?: string;
685
+ }
686
+
687
+ interface LLMResponse {
688
+ content: string | null;
689
+ toolCalls: LLMToolCall[];
690
+ finishReason: 'stop' | 'tool_calls' | 'length' | 'error';
691
+ usage?: { promptTokens: number; completionTokens: number };
692
+ }
693
+
694
+ interface LLMToolCall {
695
+ id: string;
696
+ name: string;
697
+ arguments: Record<string, unknown>;
698
+ }
699
+
700
+ interface LLMTool {
701
+ name: string;
702
+ description: string;
703
+ parameters: {
704
+ type: 'object';
705
+ properties: Record<string, { type: string }>;
706
+ required?: string[];
707
+ };
708
+ }
709
+
710
+ interface LLMProvider {
711
+ chat(
712
+ messages: LLMMessage[],
713
+ options?: { tools?: LLMTool[]; systemPrompt?: string; model?: string; temperature?: number; maxTokens?: number }
714
+ ): Promise<LLMResponse>;
715
+ }`;
716
+ var LLM_SIMPLE_TYPES = `interface LLMMessage {
717
+ role: 'system' | 'user' | 'assistant' | 'tool';
718
+ content: string;
719
+ toolCallId?: string;
720
+ }
721
+
722
+ interface LLMToolCall {
723
+ id: string;
724
+ name: string;
725
+ arguments: Record<string, unknown>;
726
+ }
727
+
728
+ interface LLMResponse {
729
+ content: string | null;
730
+ toolCalls: LLMToolCall[];
731
+ finishReason: 'stop' | 'tool_calls' | 'length' | 'error';
732
+ usage?: { promptTokens: number; completionTokens: number };
733
+ }
734
+
735
+ interface LLMProvider {
736
+ chat(messages: LLMMessage[], options?: { systemPrompt?: string; model?: string; temperature?: number; maxTokens?: number }): Promise<LLMResponse>;
737
+ }`;
738
+ var LLM_MOCK_PROVIDER = `const createMockProvider = (): LLMProvider => ({
739
+ async chat(messages) {
740
+ const lastMessage = messages[messages.length - 1];
741
+ return {
742
+ content: \`[Mock response to: \${(lastMessage?.content ?? '').slice(0, 50)}...]\`,
743
+ toolCalls: [],
744
+ finishReason: 'stop',
745
+ usage: { promptTokens: 10, completionTokens: 20 },
746
+ };
747
+ },
748
+ });
749
+
750
+ const llmProvider: LLMProvider = createMockProvider();`;
751
+ var LLM_MOCK_PROVIDER_WITH_TOOLS = `const createMockProvider = (): LLMProvider => ({
752
+ async chat(messages, options) {
753
+ const last = messages[messages.length - 1];
754
+ if (options?.tools && last.content.toLowerCase().includes('search')) {
755
+ return {
756
+ content: null,
757
+ toolCalls: [
758
+ {
759
+ id: 'call_' + Date.now(),
760
+ name: 'search',
761
+ arguments: { query: last.content },
762
+ },
763
+ ],
764
+ finishReason: 'tool_calls',
765
+ usage: { promptTokens: 15, completionTokens: 30 },
766
+ };
767
+ }
768
+
769
+ return {
770
+ content: '[Mock answer] ' + last.content,
771
+ toolCalls: [],
772
+ finishReason: 'stop',
773
+ usage: { promptTokens: 10, completionTokens: 20 },
774
+ };
775
+ },
776
+ });
777
+
778
+ const llmProvider: LLMProvider = createMockProvider();`;
779
+
780
+ // src/cli/templates/workflows/ai-agent.ts
781
+ var aiConfigSchema = {
782
+ provider: {
783
+ type: "select",
784
+ label: "LLM Provider",
785
+ description: "Choose your LLM provider",
786
+ default: "mock",
787
+ options: [
788
+ { value: "openai", label: "OpenAI" },
789
+ { value: "anthropic", label: "Anthropic" },
790
+ { value: "ollama", label: "Ollama (Local)" },
791
+ { value: "mock", label: "Mock (Testing)" }
792
+ ]
793
+ },
794
+ model: {
795
+ type: "string",
796
+ label: "Model",
797
+ description: "Model identifier",
798
+ default: "gpt-4o",
799
+ placeholder: "e.g., gpt-4o, claude-3-5-sonnet-20241022, llama3.2",
800
+ dependsOn: {
801
+ field: "provider",
802
+ values: ["openai", "anthropic", "ollama"]
803
+ }
804
+ }
805
+ };
806
+ var aiAgentTemplate = {
807
+ id: "ai-agent",
808
+ name: "AI Agent (Tool Calling)",
809
+ description: "Stateful LLM agent with explicit reasoning loop and tool execution",
810
+ category: "ai",
811
+ configSchema: aiConfigSchema,
812
+ generate: ({ workflowName, config }) => {
813
+ const provider = config?.provider || "mock";
814
+ const model = config?.model || "";
815
+ const providerCode = provider === "mock" ? `
816
+ /* ============================================================
817
+ * MOCK PROVIDER (REPLACE IN REAL USE)
818
+ * ============================================================
819
+ */
820
+
821
+ ${LLM_MOCK_PROVIDER_WITH_TOOLS}
822
+ ` : getProviderCode(provider, model);
823
+ return `
824
+ /* ============================================================
825
+ * CORE TYPES
826
+ * ============================================================
827
+ */
828
+
829
+ ${LLM_CORE_TYPES}
830
+
831
+ type TerminationReason =
832
+ | 'completed'
833
+ | 'max_iterations'
834
+ | 'tool_error'
835
+ | 'llm_error'
836
+ | 'aborted';
837
+
838
+ /* ============================================================
839
+ * AGENT STATE
840
+ * ============================================================
841
+ */
842
+
843
+ interface AgentState {
844
+ messages: LLMMessage[];
845
+ iteration: number;
846
+ toolsUsed: string[];
847
+ terminated: boolean;
848
+ terminationReason?: TerminationReason;
849
+ finalResponse?: string;
850
+ }
851
+
852
+ ${providerCode}
853
+
854
+ const SYSTEM_PROMPT = \`You are a helpful AI assistant with access to tools.
855
+ Use tools when necessary. Respond directly when the task is complete.\`;
856
+
857
+ const MAX_ITERATIONS = 10;
858
+
859
+ /* ============================================================
860
+ * TOOLS
861
+ * ============================================================
862
+ */
863
+
864
+ const AVAILABLE_TOOLS: LLMTool[] = [
865
+ {
866
+ name: 'search',
867
+ description: 'Search for information',
868
+ parameters: {
869
+ type: 'object',
870
+ properties: {
871
+ query: { type: 'string' },
872
+ },
873
+ required: ['query'],
874
+ },
875
+ },
876
+ ];
877
+
878
+ type ToolResult =
879
+ | { ok: true; value: string }
880
+ | { ok: false; error: string };
881
+
882
+ type ToolFn = (args: Record<string, unknown>) => Promise<ToolResult>;
883
+
884
+ const TOOL_IMPLEMENTATIONS: Record<string, ToolFn> = {
885
+ async search(args) {
886
+ if (typeof args.query !== 'string') {
887
+ return { ok: false, error: 'Invalid query' };
888
+ }
889
+ return { ok: true, value: '[Search results for: ' + args.query + ']' };
890
+ },
891
+ };
892
+
893
+ /* ============================================================
894
+ * NODES
895
+ * ============================================================
896
+ */
897
+
898
+ /**
899
+ * Agent loop that orchestrates LLM calls and tool execution
900
+ * Uses scoped ports to handle iteration internally
901
+ *
902
+ * @flowWeaver nodeType
903
+ * @label Agent Loop
904
+ * @input userMessage [order:1] - User's input message
905
+ * @input [maxIterations] [order:2] - Maximum loop iterations (default: 10)
906
+ * @input success scope:iteration [order:0] - From LLM onSuccess
907
+ * @input failure scope:iteration [order:1] - From LLM onFailure
908
+ * @input llmResponse scope:iteration [order:2] - LLM response
909
+ * @input toolMessages scope:iteration [order:3] - Tool results
910
+ * @input execute [order:0] - Execute
911
+ * @output start scope:iteration [order:0] - Triggers iteration
912
+ * @output state scope:iteration [order:1] - Current agent state
913
+ * @output response [order:2] - Final response when done
914
+ * @output onSuccess [order:0] - On Success
915
+ * @output onFailure [order:1] - On Failure
916
+ */
917
+ async function agentLoop(
918
+ execute: boolean,
919
+ userMessage: string,
920
+ maxIterations: number = MAX_ITERATIONS,
921
+ iteration: (start: boolean, state: AgentState) => Promise<{
922
+ success: boolean;
923
+ failure: boolean;
924
+ llmResponse: LLMResponse | null;
925
+ toolMessages: LLMMessage[];
926
+ }>
927
+ ): Promise<{ onSuccess: boolean; onFailure: boolean; response: string }> {
928
+ if (!execute) {
929
+ return { onSuccess: false, onFailure: false, response: '' };
930
+ }
931
+
932
+ let state: AgentState = {
933
+ messages: [{ role: 'user', content: userMessage }],
934
+ iteration: 0,
935
+ toolsUsed: [],
936
+ terminated: false,
937
+ };
938
+
939
+ while (state.iteration < maxIterations) {
940
+ const result = await iteration(true, state);
941
+
942
+ state.iteration++;
943
+
944
+ // Handle LLM failure
945
+ if (result.failure) {
946
+ return { onSuccess: false, onFailure: true, response: 'LLM error occurred' };
947
+ }
948
+
949
+ // Add assistant message if present
950
+ if (result.llmResponse?.content) {
951
+ state.messages.push({ role: 'assistant', content: result.llmResponse.content });
952
+ }
953
+
954
+ // Add tool messages
955
+ if (result.toolMessages && result.toolMessages.length > 0) {
956
+ state.messages.push(...result.toolMessages);
957
+ }
958
+
959
+ // Check termination: no tool calls means we're done
960
+ if (result.llmResponse && result.llmResponse.toolCalls.length === 0 && result.llmResponse.content) {
961
+ return { onSuccess: true, onFailure: false, response: result.llmResponse.content };
962
+ }
963
+ }
964
+
965
+ return { onSuccess: true, onFailure: false, response: 'Max iterations reached' };
966
+ }
967
+
968
+ /**
969
+ * Calls the LLM with current state
970
+ *
971
+ * @flowWeaver nodeType
972
+ * @label Call LLM
973
+ * @input state [order:1] - Current agent state
974
+ * @input execute [order:0] - Execute
975
+ * @output response [order:2] - LLM response
976
+ * @output toolCalls [order:3] - Tool calls from LLM
977
+ * @output onSuccess [order:0] - On Success
978
+ * @output onFailure [order:1] - On Failure
979
+ */
980
+ async function callLLM(
981
+ execute: boolean,
982
+ state: AgentState
983
+ ): Promise<{
984
+ onSuccess: boolean;
985
+ onFailure: boolean;
986
+ response: LLMResponse | null;
987
+ toolCalls: LLMToolCall[];
988
+ }> {
989
+ if (!execute) {
990
+ return { onSuccess: false, onFailure: false, response: null, toolCalls: [] };
991
+ }
992
+
993
+ try {
994
+ const response = await llmProvider.chat(state.messages, {
995
+ tools: AVAILABLE_TOOLS,
996
+ systemPrompt: SYSTEM_PROMPT,
997
+ });
998
+
999
+ return { onSuccess: true, onFailure: false, response, toolCalls: response.toolCalls };
1000
+ } catch {
1001
+ return { onSuccess: false, onFailure: true, response: null, toolCalls: [] };
1002
+ }
1003
+ }
1004
+
1005
+ /**
1006
+ * Executes tool calls
1007
+ *
1008
+ * @flowWeaver nodeType
1009
+ * @label Execute Tools
1010
+ * @input calls [order:1] - Tool calls to execute
1011
+ * @input execute [order:0] - Execute
1012
+ * @output messages [order:2] - Tool response messages
1013
+ * @output onSuccess [order:0] - On Success
1014
+ * @output onFailure [order:1] - On Failure
1015
+ */
1016
+ async function executeTools(
1017
+ execute: boolean,
1018
+ calls: LLMToolCall[]
1019
+ ): Promise<{
1020
+ onSuccess: boolean;
1021
+ onFailure: boolean;
1022
+ messages: LLMMessage[];
1023
+ }> {
1024
+ if (!execute || !calls || calls.length === 0) {
1025
+ return { onSuccess: true, onFailure: false, messages: [] };
1026
+ }
1027
+
1028
+ const messages: LLMMessage[] = [];
1029
+
1030
+ for (const call of calls) {
1031
+ const impl = TOOL_IMPLEMENTATIONS[call.name];
1032
+ if (!impl) {
1033
+ messages.push({
1034
+ role: 'tool',
1035
+ content: 'Unknown tool: ' + call.name,
1036
+ toolCallId: call.id,
1037
+ });
1038
+ continue;
1039
+ }
1040
+
1041
+ const result = await impl(call.arguments);
1042
+
1043
+ messages.push({
1044
+ role: 'tool',
1045
+ content: result.ok ? result.value : 'Error: ' + result.error,
1046
+ toolCallId: call.id,
1047
+ });
1048
+ }
1049
+
1050
+ return { onSuccess: true, onFailure: false, messages };
1051
+ }
1052
+
1053
+ /* ============================================================
1054
+ * WORKFLOW
1055
+ * ============================================================
1056
+ */
1057
+
1058
+ /**
1059
+ * AI Agent that uses tools to accomplish tasks
1060
+ *
1061
+ * @flowWeaver workflow
1062
+ * @node loop agentLoop [color: "purple"] [icon: "smartToy"]
1063
+ * @node llm callLLM loop.iteration [color: "blue"] [icon: "psychology"]
1064
+ * @node tools executeTools loop.iteration [color: "orange"] [icon: "build"] [suppress: "AGENT_UNGUARDED_TOOL_EXECUTOR"]
1065
+ * @connect Start.execute -> loop.execute
1066
+ * @connect Start.userMessage -> loop.userMessage
1067
+ * @connect loop.start:iteration -> llm.execute
1068
+ * @connect loop.state:iteration -> llm.state
1069
+ * @connect llm.toolCalls -> tools.calls
1070
+ * @connect llm.onSuccess -> tools.execute
1071
+ * @connect llm.response -> loop.llmResponse:iteration
1072
+ * @connect llm.onSuccess -> loop.success:iteration
1073
+ * @connect llm.onFailure -> loop.failure:iteration
1074
+ * @connect tools.messages -> loop.toolMessages:iteration
1075
+ * @connect tools.onFailure -> loop.failure:iteration
1076
+ * @connect loop.response -> Exit.response
1077
+ * @connect loop.onSuccess -> Exit.onSuccess
1078
+ * @connect loop.onFailure -> Exit.onFailure
1079
+ * @param execute [order:0] - Execute
1080
+ * @param userMessage [order:1] - User's message to the agent
1081
+ * @returns onSuccess [order:0] - Agent completed successfully
1082
+ * @returns onFailure [order:1] - Agent encountered an error
1083
+ * @returns response [order:2] - Agent's final response
1084
+ */
1085
+ export async function ${workflowName}(
1086
+ execute: boolean,
1087
+ params: { userMessage: string }
1088
+ ): Promise<{
1089
+ onSuccess: boolean;
1090
+ onFailure: boolean;
1091
+ response: string;
1092
+ }> {
1093
+ throw new Error('Compile with: fw compile <file>');
1094
+ }
1095
+ `.trim();
1096
+ }
1097
+ };
1098
+
1099
+ // src/cli/templates/workflows/ai-react.ts
1100
+ var aiReactTemplate = {
1101
+ id: "ai-react",
1102
+ name: "ReAct Agent",
1103
+ description: "Reasoning + Acting agent with explicit thought process",
1104
+ category: "ai",
1105
+ configSchema: aiConfigSchema,
1106
+ generate: (opts) => {
1107
+ const { workflowName, config } = opts;
1108
+ const provider = config?.provider || "mock";
1109
+ const model = config?.model || "";
1110
+ const providerCode = provider === "mock" ? `
1111
+ // Mock provider. Replace with a real provider for production.
1112
+ const createMockReactProvider = (): LLMProvider => ({
1113
+ async chat(messages) {
1114
+ const lastMessage = messages[messages.length - 1];
1115
+ return {
1116
+ content: \`Thought: Processing the request\\nAction: FINISH\\nAction Input: [Mock answer to: \${lastMessage.content.slice(0, 30)}...]\`,
1117
+ toolCalls: [],
1118
+ finishReason: 'stop',
1119
+ };
1120
+ },
1121
+ });
1122
+
1123
+ const llmProvider: LLMProvider = createMockReactProvider();
1124
+ ` : getProviderCode(provider, model);
1125
+ return `
1126
+ // ============================================================
1127
+ // ReAct Agent: Thought \u2192 Action \u2192 Observation loop
1128
+ // ============================================================
1129
+ //
1130
+ // The agent follows the ReAct pattern (Yao et al., 2022):
1131
+ // 1. Think: reason about the current state
1132
+ // 2. Act: call a tool or FINISH
1133
+ // 3. Observe: receive tool output, feed back into next thought
1134
+ //
1135
+ // The reactLoop node manages iteration and message accumulation.
1136
+ // think + act run inside the loop's scoped iteration.
1137
+
1138
+ // ============================================================
1139
+ // LLM TYPES
1140
+ // ============================================================
1141
+
1142
+ ${LLM_CORE_TYPES}
1143
+
1144
+ ${providerCode}
1145
+ const MAX_STEPS = 10;
1146
+
1147
+ const REACT_PROMPT = \`You are a ReAct (Reasoning + Acting) agent.
1148
+
1149
+ For each step, you MUST respond in this exact format:
1150
+ Thought: [Your reasoning about what to do next]
1151
+ Action: [tool_name] or [FINISH]
1152
+ Action Input: [input for the tool, or final answer if FINISH]
1153
+
1154
+ Available tools: search, calculate
1155
+
1156
+ When you have the final answer:
1157
+ Thought: I now have enough information to answer
1158
+ Action: FINISH
1159
+ Action Input: [Your final answer here]\`;
1160
+
1161
+ // Parse ReAct response format
1162
+ function parseReactResponse(content: string): {
1163
+ thought: string;
1164
+ action: string;
1165
+ actionInput: string;
1166
+ } {
1167
+ const thoughtMatch = content.match(/Thought:\\s*(.+?)(?=\\nAction:|$)/s);
1168
+ const actionMatch = content.match(/Action:\\s*(.+?)(?=\\nAction Input:|$)/s);
1169
+ const inputMatch = content.match(/Action Input:\\s*(.+?)$/s);
1170
+
1171
+ return {
1172
+ thought: thoughtMatch?.[1]?.trim() ?? '',
1173
+ action: actionMatch?.[1]?.trim() ?? 'FINISH',
1174
+ actionInput: inputMatch?.[1]?.trim() ?? '',
1175
+ };
1176
+ }
1177
+
1178
+ // ============================================================
1179
+ // TOOL IMPLEMENTATIONS
1180
+ // ============================================================
1181
+
1182
+ // Replace with real tools
1183
+ const TOOL_IMPLEMENTATIONS: Record<string, (input: string) => Promise<string>> = {
1184
+ async search(input: string): Promise<string> {
1185
+ return '[Search results for: ' + input + ']';
1186
+ },
1187
+ async calculate(input: string): Promise<string> {
1188
+ return '[Calculation result for: ' + input + ']';
1189
+ },
1190
+ };
1191
+
1192
+ // ============================================================
1193
+ // NODES
1194
+ // ============================================================
1195
+
1196
+ /**
1197
+ * ReAct loop: manages Think\u2192Act\u2192Observe iterations.
1198
+ * Accumulates messages and terminates when action is FINISH or max steps.
1199
+ *
1200
+ * @flowWeaver nodeType
1201
+ * @label ReAct Loop
1202
+ * @input execute [order:0] - Execute
1203
+ * @input task [order:1] - Task for the agent
1204
+ * @input [maxSteps] [order:2] - Maximum reasoning steps (default: 10)
1205
+ * @input success scope:step [order:0] - Iteration succeeded
1206
+ * @input failure scope:step [order:1] - Iteration failed
1207
+ * @input thought scope:step [order:2] - Agent's reasoning
1208
+ * @input action scope:step [order:3] - Action name
1209
+ * @input actionInput scope:step [order:4] - Action input / final answer
1210
+ * @input observation scope:step [order:5] - Tool observation
1211
+ * @output onSuccess [order:0] - On Success (finished)
1212
+ * @output onFailure [order:1] - On Failure
1213
+ * @output start scope:step [order:0] - Triggers iteration
1214
+ * @output messages scope:step [order:1] - Current messages for LLM
1215
+ * @output answer [order:2] - Final answer
1216
+ */
1217
+ async function reactLoop(
1218
+ execute: boolean,
1219
+ task: string,
1220
+ maxSteps: number = MAX_STEPS,
1221
+ step: (start: boolean, messages: LLMMessage[]) => Promise<{
1222
+ success: boolean;
1223
+ failure: boolean;
1224
+ thought: string;
1225
+ action: string;
1226
+ actionInput: string;
1227
+ observation: string;
1228
+ }>
1229
+ ): Promise<{ onSuccess: boolean; onFailure: boolean; answer: string }> {
1230
+ if (!execute) {
1231
+ return { onSuccess: false, onFailure: false, answer: '' };
1232
+ }
1233
+
1234
+ const messages: LLMMessage[] = [{ role: 'user', content: task }];
1235
+
1236
+ for (let i = 0; i < maxSteps; i++) {
1237
+ const result = await step(true, messages);
1238
+
1239
+ if (result.failure) {
1240
+ return { onSuccess: false, onFailure: true, answer: '' };
1241
+ }
1242
+
1243
+ // Append thought + action as assistant message
1244
+ messages.push({
1245
+ role: 'assistant',
1246
+ content: \`Thought: \${result.thought}\\nAction: \${result.action}\\nAction Input: \${result.actionInput}\`,
1247
+ });
1248
+
1249
+ // Check termination
1250
+ if (result.action.toUpperCase() === 'FINISH') {
1251
+ return { onSuccess: true, onFailure: false, answer: result.actionInput };
1252
+ }
1253
+
1254
+ // Append observation
1255
+ if (result.observation) {
1256
+ messages.push({ role: 'user', content: \`Observation: \${result.observation}\` });
1257
+ }
1258
+ }
1259
+
1260
+ return { onSuccess: true, onFailure: false, answer: 'Max steps reached' };
1261
+ }
1262
+
1263
+ /**
1264
+ * ReAct reasoning step: calls LLM and parses Thought/Action/ActionInput
1265
+ *
1266
+ * @flowWeaver nodeType
1267
+ * @label Think
1268
+ * @input execute [order:0] - Execute
1269
+ * @input messages [order:1] - Conversation history
1270
+ * @output onSuccess [order:0] - On Success
1271
+ * @output onFailure [order:1] - On Failure
1272
+ * @output thought [order:2] - Agent's reasoning
1273
+ * @output action [order:3] - Action to take (tool name or FINISH)
1274
+ * @output actionInput [order:4] - Input for action or final answer
1275
+ */
1276
+ async function think(
1277
+ execute: boolean,
1278
+ messages: LLMMessage[]
1279
+ ): Promise<{
1280
+ onSuccess: boolean;
1281
+ onFailure: boolean;
1282
+ thought: string;
1283
+ action: string;
1284
+ actionInput: string;
1285
+ }> {
1286
+ if (!execute) {
1287
+ return { onSuccess: false, onFailure: false, thought: '', action: '', actionInput: '' };
1288
+ }
1289
+
1290
+ try {
1291
+ const response = await llmProvider.chat(messages, { systemPrompt: REACT_PROMPT });
1292
+ const parsed = parseReactResponse(response.content ?? '');
1293
+
1294
+ return {
1295
+ onSuccess: true,
1296
+ onFailure: false,
1297
+ thought: parsed.thought,
1298
+ action: parsed.action,
1299
+ actionInput: parsed.actionInput,
1300
+ };
1301
+ } catch {
1302
+ return { onSuccess: false, onFailure: true, thought: '', action: '', actionInput: '' };
1303
+ }
1304
+ }
1305
+
1306
+ /**
1307
+ * Execute action and return observation
1308
+ *
1309
+ * @flowWeaver nodeType
1310
+ * @label Act
1311
+ * @input execute [order:0] - Execute
1312
+ * @input action [order:1] - Tool name to execute
1313
+ * @input actionInput [order:2] - Input for tool
1314
+ * @output onSuccess [order:0] - On Success
1315
+ * @output onFailure [order:1] - On Failure
1316
+ * @output observation [order:2] - Tool observation result
1317
+ */
1318
+ async function act(
1319
+ execute: boolean,
1320
+ action: string,
1321
+ actionInput: string
1322
+ ): Promise<{
1323
+ onSuccess: boolean;
1324
+ onFailure: boolean;
1325
+ observation: string;
1326
+ }> {
1327
+ if (!execute) {
1328
+ return { onSuccess: false, onFailure: false, observation: '' };
1329
+ }
1330
+
1331
+ const tool = TOOL_IMPLEMENTATIONS[action.toLowerCase()];
1332
+ if (!tool) {
1333
+ return {
1334
+ onSuccess: true,
1335
+ onFailure: false,
1336
+ observation: 'Unknown tool: ' + action,
1337
+ };
1338
+ }
1339
+
1340
+ try {
1341
+ const observation = await tool(actionInput);
1342
+ return { onSuccess: true, onFailure: false, observation };
1343
+ } catch (error) {
1344
+ return { onSuccess: false, onFailure: true, observation: '' };
1345
+ }
1346
+ }
1347
+
1348
+ // ============================================================
1349
+ // WORKFLOW
1350
+ // ============================================================
1351
+
1352
+ /**
1353
+ * ReAct Agent: iterative Thought\u2192Action\u2192Observation loop
1354
+ *
1355
+ * @flowWeaver workflow
1356
+ * @node loop reactLoop [color: "purple"] [icon: "psychology"]
1357
+ * @node thinking think loop.step [color: "blue"] [icon: "autoAwesome"]
1358
+ * @node acting act loop.step [color: "orange"] [icon: "bolt"]
1359
+ * @connect Start.execute -> loop.execute
1360
+ * @connect Start.task -> loop.task
1361
+ * @connect loop.start:step -> thinking.execute
1362
+ * @connect loop.messages:step -> thinking.messages
1363
+ * @connect thinking.onSuccess -> acting.execute
1364
+ * @connect thinking.action -> acting.action
1365
+ * @connect thinking.actionInput -> acting.actionInput
1366
+ * @connect thinking.thought -> loop.thought:step
1367
+ * @connect thinking.action -> loop.action:step
1368
+ * @connect thinking.actionInput -> loop.actionInput:step
1369
+ * @connect thinking.onFailure -> loop.failure:step
1370
+ * @connect acting.observation -> loop.observation:step
1371
+ * @connect acting.onSuccess -> loop.success:step
1372
+ * @connect acting.onFailure -> loop.failure:step
1373
+ * @connect loop.onSuccess -> Exit.onSuccess
1374
+ * @connect loop.onFailure -> Exit.onFailure
1375
+ * @connect loop.answer -> Exit.answer
1376
+ * @param execute [order:0] - Execute
1377
+ * @param task [order:1] - Task for the agent
1378
+ * @returns onSuccess [order:0] - On Success
1379
+ * @returns onFailure [order:1] - On Failure
1380
+ * @returns answer [order:2] - Final answer
1381
+ */
1382
+ export async function ${workflowName}(
1383
+ execute: boolean,
1384
+ params: { task: string }
1385
+ ): Promise<{
1386
+ onSuccess: boolean;
1387
+ onFailure: boolean;
1388
+ answer: string;
1389
+ }> {
1390
+ throw new Error('Compile with: fw compile <file>');
1391
+ }
1392
+ `.trim();
1393
+ }
1394
+ };
1395
+
1396
+ // src/cli/templates/workflows/ai-rag.ts
1397
+ var aiRagTemplate = {
1398
+ id: "ai-rag",
1399
+ name: "RAG Pipeline",
1400
+ description: "Retrieval-Augmented Generation for knowledge-based Q&A",
1401
+ category: "ai",
1402
+ configSchema: aiConfigSchema,
1403
+ generate: (opts) => {
1404
+ const { workflowName, config } = opts;
1405
+ const provider = config?.provider || "mock";
1406
+ const model = config?.model || "";
1407
+ const providerCode = provider === "mock" ? `
1408
+ // Mock provider for testing - replace with real provider
1409
+ ${LLM_MOCK_PROVIDER}
1410
+ ` : getProviderCode(provider, model);
1411
+ return `
1412
+ // ============================================================
1413
+ // LLM TYPES - Provider-agnostic interface
1414
+ // ============================================================
1415
+
1416
+ ${LLM_SIMPLE_TYPES}
1417
+
1418
+ ${providerCode}
1419
+
1420
+ // Document store (replace with vector DB like Pinecone, Weaviate, etc.)
1421
+ interface Document {
1422
+ id: string;
1423
+ content: string;
1424
+ metadata?: Record<string, unknown>;
1425
+ }
1426
+
1427
+ const documentStore: Document[] = [
1428
+ // TODO: Add your documents or connect to vector database
1429
+ { id: '1', content: 'Flow Weaver is a visual programming tool.' },
1430
+ { id: '2', content: 'It uses typed ports for data flow.' },
1431
+ ];
1432
+
1433
+ /**
1434
+ * Retrieves relevant documents for a query
1435
+ *
1436
+ * @flowWeaver nodeType
1437
+ * @label Retrieve
1438
+ * @input query [order:1] - Search query
1439
+ * @input [topK] [order:2] - Number of results (default 3)
1440
+ * @input execute [order:0] - Execute
1441
+ * @output documents [order:2] [hidden] - Retrieved documents
1442
+ * @output context [order:3] - Combined document text
1443
+ * @output onSuccess [order:0] - On Success
1444
+ * @output onFailure [order:1] - On Failure
1445
+ */
1446
+ async function retrieve(
1447
+ execute: boolean,
1448
+ query: string,
1449
+ topK?: number
1450
+ ): Promise<{
1451
+ onSuccess: boolean;
1452
+ onFailure: boolean;
1453
+ documents: Document[];
1454
+ context: string;
1455
+ }> {
1456
+ if (!execute) {
1457
+ return { onSuccess: false, onFailure: false, documents: [], context: '' };
1458
+ }
1459
+
1460
+ const k = topK ?? 3;
1461
+
1462
+ // TODO: Replace with actual vector similarity search
1463
+ // For now, simple keyword matching
1464
+ const queryLower = query.toLowerCase();
1465
+ const scored = documentStore
1466
+ .map((doc) => ({
1467
+ doc,
1468
+ score: doc.content.toLowerCase().includes(queryLower) ? 1 : 0,
1469
+ }))
1470
+ .filter((s) => s.score > 0)
1471
+ .slice(0, k)
1472
+ .map((s) => s.doc);
1473
+
1474
+ const context = scored.map((d) => d.content).join('\\n\\n');
1475
+
1476
+ return {
1477
+ onSuccess: true,
1478
+ onFailure: false,
1479
+ documents: scored,
1480
+ context,
1481
+ };
1482
+ }
1483
+
1484
+ /**
1485
+ * Generates answer using retrieved context
1486
+ *
1487
+ * @flowWeaver nodeType
1488
+ * @label Generate
1489
+ * @input question [order:1] - User question
1490
+ * @input context [order:2] - Retrieved context
1491
+ * @input execute [order:0] - Execute
1492
+ * @output answer [order:2] - Generated answer
1493
+ * @output sourcesUsed [order:3] - Number of sources used
1494
+ * @output onSuccess [order:0] - On Success
1495
+ * @output onFailure [order:1] - On Failure
1496
+ */
1497
+ async function generate(
1498
+ execute: boolean,
1499
+ question: string,
1500
+ context: string
1501
+ ): Promise<{
1502
+ onSuccess: boolean;
1503
+ onFailure: boolean;
1504
+ answer: string;
1505
+ sourcesUsed: number;
1506
+ }> {
1507
+ if (!execute) {
1508
+ return { onSuccess: false, onFailure: false, answer: '', sourcesUsed: 0 };
1509
+ }
1510
+
1511
+ const prompt = \`Answer the question based on the following context.
1512
+ If the context doesn't contain relevant information, say so.
1513
+
1514
+ Context:
1515
+ \${context}
1516
+
1517
+ Question: \${question}
1518
+
1519
+ Answer:\`;
1520
+
1521
+ const response = await llmProvider.chat([{ role: 'user', content: prompt }]);
1522
+ const sourcesUsed = context
1523
+ .split('\\n\\n')
1524
+ .filter((s) => s.trim()).length;
1525
+
1526
+ return {
1527
+ onSuccess: true,
1528
+ onFailure: false,
1529
+ answer: response.content ?? '',
1530
+ sourcesUsed,
1531
+ };
1532
+ }
1533
+
1534
+ /**
1535
+ * RAG Pipeline for knowledge-based Q&A
1536
+ *
1537
+ * @flowWeaver workflow
1538
+ * @node retriever retrieve [color: "teal"] [icon: "search"] [suppress: "UNUSED_OUTPUT_PORT", "DESIGN_ASYNC_NO_ERROR_PATH"]
1539
+ * @node generator generate [color: "purple"] [icon: "autoAwesome"]
1540
+ * @connect Start.execute -> retriever.execute
1541
+ * @connect Start.question -> retriever.query
1542
+ * @connect Start.topK -> retriever.topK
1543
+ * @connect Start.question -> generator.question
1544
+ * @connect retriever.context -> generator.context
1545
+ * @connect retriever.onSuccess -> generator.execute
1546
+ * @connect generator.answer -> Exit.answer
1547
+ * @connect generator.sourcesUsed -> Exit.sourcesUsed
1548
+ * @connect generator.onSuccess -> Exit.onSuccess
1549
+ * @connect generator.onFailure -> Exit.onFailure
1550
+ * @param execute [order:0] - Execute
1551
+ * @param question [order:1] - User's question
1552
+ * @param topK [order:2] - Number of documents to retrieve
1553
+ * @returns onSuccess [order:0] - On Success
1554
+ * @returns onFailure [order:1] - On Failure
1555
+ * @returns answer [order:2] - Generated answer
1556
+ * @returns sourcesUsed [order:3] - Number of sources used
1557
+ */
1558
+ export async function ${workflowName}(
1559
+ execute: boolean,
1560
+ params: { question: string; topK?: number }
1561
+ ): Promise<{
1562
+ onSuccess: boolean;
1563
+ onFailure: boolean;
1564
+ answer: string;
1565
+ sourcesUsed: number;
1566
+ }> {
1567
+ throw new Error('Compile with: fw compile <file>');
1568
+ }
1569
+ `.trim();
1570
+ }
1571
+ };
1572
+
1573
+ // src/cli/templates/workflows/ai-chat.ts
1574
+ var aiChatTemplate = {
1575
+ id: "ai-chat",
1576
+ name: "Stateful Chat",
1577
+ description: "Conversational AI with memory management",
1578
+ category: "ai",
1579
+ configSchema: aiConfigSchema,
1580
+ generate: (opts) => {
1581
+ const { workflowName, config } = opts;
1582
+ const provider = config?.provider || "mock";
1583
+ const model = config?.model || "";
1584
+ const providerCode = provider === "mock" ? `
1585
+ // Mock provider for testing - replace with real provider
1586
+ ${LLM_MOCK_PROVIDER}
1587
+ ` : getProviderCode(provider, model);
1588
+ return `
1589
+ // ============================================================
1590
+ // LLM TYPES - Provider-agnostic interface
1591
+ // ============================================================
1592
+
1593
+ ${LLM_SIMPLE_TYPES}
1594
+
1595
+ ${providerCode}
1596
+
1597
+ // Conversation memory store
1598
+ const conversations: Map<string, LLMMessage[]> = new Map();
1599
+
1600
+ const DEFAULT_SYSTEM_PROMPT = \`You are a helpful AI assistant.
1601
+ Be concise but friendly. Remember context from earlier in the conversation.\`;
1602
+
1603
+ /**
1604
+ * Manages conversation memory
1605
+ *
1606
+ * @flowWeaver nodeType
1607
+ * @label Memory
1608
+ * @input conversationId [order:1] - Conversation identifier
1609
+ * @input [newMessage] [order:2] - Message to add
1610
+ * @input [maxHistory=50] [order:3] - Max messages to retain
1611
+ * @input execute [order:0] - Execute
1612
+ * @output history [order:2] - Conversation history
1613
+ * @output onSuccess [order:0] - On Success
1614
+ * @output onFailure [order:1] - On Failure
1615
+ */
1616
+ function memory(
1617
+ execute: boolean,
1618
+ conversationId: string,
1619
+ newMessage?: LLMMessage,
1620
+ maxHistory?: number
1621
+ ): {
1622
+ onSuccess: boolean;
1623
+ onFailure: boolean;
1624
+ history: LLMMessage[];
1625
+ } {
1626
+ if (!execute) {
1627
+ return { onSuccess: false, onFailure: false, history: [] };
1628
+ }
1629
+
1630
+ if (!conversations.has(conversationId)) {
1631
+ conversations.set(conversationId, []);
1632
+ }
1633
+
1634
+ const history = conversations.get(conversationId)!;
1635
+
1636
+ if (newMessage) {
1637
+ history.push(newMessage);
1638
+ const max = maxHistory ?? 50;
1639
+ while (history.length > max) {
1640
+ history.shift();
1641
+ }
1642
+ }
1643
+
1644
+ return { onSuccess: true, onFailure: false, history: [...history] };
1645
+ }
1646
+
1647
+ /**
1648
+ * Generates chat response
1649
+ *
1650
+ * @flowWeaver nodeType
1651
+ * @label Chat
1652
+ * @input history [order:1] - Conversation history
1653
+ * @input [systemPrompt] [order:2] - System prompt
1654
+ * @input execute [order:0] - Execute
1655
+ * @output response [order:2] - Assistant response
1656
+ * @output responseMessage [order:3] - Response as LLMMessage
1657
+ * @output onSuccess [order:0] - On Success
1658
+ * @output onFailure [order:1] - On Failure
1659
+ */
1660
+ async function chat(
1661
+ execute: boolean,
1662
+ history: LLMMessage[],
1663
+ systemPrompt?: string
1664
+ ): Promise<{
1665
+ onSuccess: boolean;
1666
+ onFailure: boolean;
1667
+ response: string;
1668
+ responseMessage: LLMMessage;
1669
+ }> {
1670
+ if (!execute) {
1671
+ return {
1672
+ onSuccess: false,
1673
+ onFailure: false,
1674
+ response: '',
1675
+ responseMessage: { role: 'assistant', content: '' },
1676
+ };
1677
+ }
1678
+
1679
+ const response = await llmProvider.chat(history, {
1680
+ systemPrompt: systemPrompt ?? DEFAULT_SYSTEM_PROMPT,
1681
+ });
1682
+
1683
+ const content = response.content ?? '';
1684
+
1685
+ return {
1686
+ onSuccess: true,
1687
+ onFailure: false,
1688
+ response: content,
1689
+ responseMessage: { role: 'assistant', content },
1690
+ };
1691
+ }
1692
+
1693
+ /**
1694
+ * Stateful chat with conversation memory
1695
+ *
1696
+ * @flowWeaver workflow
1697
+ * @node mem memory [color: "teal"] [icon: "database"]
1698
+ * @node respond chat [color: "purple"] [icon: "campaign"] [suppress: "AGENT_LLM_NO_FALLBACK"]
1699
+ * @node saveMem memory [color: "teal"] [icon: "database"] [suppress: "UNUSED_OUTPUT_PORT"]
1700
+ * @connect Start.execute -> mem.execute
1701
+ * @connect Start.conversationId -> mem.conversationId
1702
+ * @connect Start.userMessage -> mem.newMessage
1703
+ * @connect mem.history -> respond.history
1704
+ * @connect mem.onSuccess -> respond.execute
1705
+ * @connect Start.conversationId -> saveMem.conversationId
1706
+ * @connect respond.responseMessage -> saveMem.newMessage
1707
+ * @connect respond.onSuccess -> saveMem.execute
1708
+ * @connect respond.onFailure -> Exit.onFailure
1709
+ * @connect respond.response -> Exit.response
1710
+ * @connect saveMem.onSuccess -> Exit.onSuccess
1711
+ * @param execute [order:0] - Execute
1712
+ * @param conversationId [order:1] - Unique conversation ID
1713
+ * @param userMessage [order:2] - User's message
1714
+ * @param systemPrompt [order:3] - System prompt (optional)
1715
+ * @returns onSuccess [order:0] - On Success
1716
+ * @returns onFailure [order:1] - On Failure
1717
+ * @returns response [order:2] - Assistant's response
1718
+ */
1719
+ export async function ${workflowName}(
1720
+ execute: boolean,
1721
+ params: { conversationId: string; userMessage: LLMMessage; systemPrompt?: string }
1722
+ ): Promise<{
1723
+ onSuccess: boolean;
1724
+ onFailure: boolean;
1725
+ response: string;
1726
+ }> {
1727
+ throw new Error('Compile with: fw compile <file>');
1728
+ }
1729
+ `.trim();
1730
+ }
1731
+ };
1732
+
1733
+ // src/cli/templates/workflows/aggregator.ts
1734
+ var aggregatorTemplate = {
1735
+ id: "aggregator",
1736
+ name: "Aggregator",
1737
+ description: "Combine multiple data sources into one output",
1738
+ category: "data-processing",
1739
+ generate: (opts) => {
1740
+ const { workflowName, async: isAsync } = opts;
1741
+ const asyncKeyword = isAsync ? "async " : "";
1742
+ const returnType = isAsync ? "Promise<{ onSuccess: boolean; onFailure: boolean; aggregated: any }>" : "{ onSuccess: boolean; onFailure: boolean; aggregated: any }";
1743
+ return `
1744
+ // Use @expression for most functions, normal mode only for error-with-data or void side-effects
1745
+
1746
+ /**
1747
+ * Fetches data from source A
1748
+ *
1749
+ * @flowWeaver nodeType
1750
+ * @expression
1751
+ * @label Fetch Source A
1752
+ * @input query [order:0] - Query parameters
1753
+ * @output data [order:0] - Data from source A
1754
+ */
1755
+ function fetchSourceA(query: any): { data: any } {
1756
+ // TODO: Fetch from source A
1757
+ return { data: { source: "A", items: [] } };
1758
+ }
1759
+
1760
+ /**
1761
+ * Fetches data from source B
1762
+ *
1763
+ * @flowWeaver nodeType
1764
+ * @expression
1765
+ * @label Fetch Source B
1766
+ * @input query [order:0] - Query parameters
1767
+ * @output data [order:0] - Data from source B
1768
+ */
1769
+ function fetchSourceB(query: any): { data: any } {
1770
+ // TODO: Fetch from source B
1771
+ return { data: { source: "B", items: [] } };
1772
+ }
1773
+
1774
+ /**
1775
+ * Combines data from multiple sources
1776
+ *
1777
+ * @flowWeaver nodeType
1778
+ * @expression
1779
+ * @label Combine Data
1780
+ * @input dataA [order:0] - Data from source A
1781
+ * @input dataB [order:1] - Data from source B
1782
+ * @output aggregated [order:0] - Combined data
1783
+ */
1784
+ function combineData(dataA: any, dataB: any): { aggregated: any } {
1785
+ // TODO: Implement aggregation logic
1786
+ return {
1787
+ aggregated: {
1788
+ sources: [dataA?.source, dataB?.source],
1789
+ totalItems: (dataA?.items?.length || 0) + (dataB?.items?.length || 0),
1790
+ items: [...(dataA?.items || []), ...(dataB?.items || [])],
1791
+ aggregatedAt: new Date().toISOString()
1792
+ }
1793
+ };
1794
+ }
1795
+
1796
+ /**
1797
+ * @flowWeaver workflow
1798
+ * @node sourceA fetchSourceA [color: "blue"] [icon: "download"]
1799
+ * @node sourceB fetchSourceB [color: "blue"] [icon: "download"]
1800
+ * @node combiner combineData [color: "purple"] [icon: "callMerge"]
1801
+ * @connect Start.execute -> sourceA.execute
1802
+ * @connect Start.execute -> sourceB.execute
1803
+ * @connect Start.query -> sourceA.query
1804
+ * @connect Start.query -> sourceB.query
1805
+ * @connect sourceA.onSuccess -> combiner.execute
1806
+ * @connect sourceA.data -> combiner.dataA
1807
+ * @connect sourceB.data -> combiner.dataB
1808
+ * @connect combiner.aggregated -> Exit.aggregated
1809
+ * @connect combiner.onSuccess -> Exit.onSuccess
1810
+ * @connect combiner.onFailure -> Exit.onFailure
1811
+ * @param execute [order:0] - Execute
1812
+ * @param query [order:1] - Query parameters for fetching
1813
+ * @returns onSuccess [order:0] - On Success
1814
+ * @returns onFailure [order:1] - On Failure
1815
+ * @returns aggregated [order:2] - Combined data from all sources
1816
+ */
1817
+ export ${asyncKeyword}function ${workflowName}(
1818
+ execute: boolean,
1819
+ params: { query: any }
1820
+ ): ${returnType} {
1821
+ throw new Error("Compile with: fw compile <file>");
1822
+ }
1823
+ `.trim();
1824
+ }
1825
+ };
1826
+
1827
+ // src/cli/templates/workflows/webhook.ts
1828
+ var webhookTemplate = {
1829
+ id: "webhook",
1830
+ name: "Webhook Handler",
1831
+ description: "HTTP-triggered workflow with request/response handling",
1832
+ category: "integration",
1833
+ generate: (opts) => {
1834
+ const { workflowName, async: isAsync } = opts;
1835
+ const asyncKeyword = isAsync ? "async " : "";
1836
+ const returnType = isAsync ? "Promise<{ onSuccess: boolean; onFailure: boolean; statusCode: number; body: any }>" : "{ onSuccess: boolean; onFailure: boolean; statusCode: number; body: any }";
1837
+ return `
1838
+ /**
1839
+ * Validates incoming webhook request
1840
+ *
1841
+ * @flowWeaver nodeType
1842
+ * @label Validate Request
1843
+ * @input headers [order:1] - Request headers
1844
+ * @input body [order:2] - Request body
1845
+ * @input execute [order:0] - Execute
1846
+ * @output isValid [order:2] - Whether request is valid
1847
+ * @output validatedData [order:3] - Validated request data
1848
+ * @output error [order:4] - Validation error message
1849
+ * @output onSuccess [order:0] - On Success
1850
+ * @output onFailure [order:1] - On Failure
1851
+ */
1852
+ function validateRequest(
1853
+ execute: boolean,
1854
+ headers: Record<string, string>,
1855
+ body: any
1856
+ ): { onSuccess: boolean; onFailure: boolean; isValid: boolean; validatedData: any; error: string } {
1857
+ if (!execute) {
1858
+ return { onSuccess: false, onFailure: false, isValid: false, validatedData: null, error: "" };
1859
+ }
1860
+
1861
+ // TODO: Add your validation logic
1862
+ // Example: Check API key, validate body schema, etc.
1863
+ const apiKey = headers["x-api-key"] || headers["authorization"];
1864
+
1865
+ if (!apiKey) {
1866
+ return { onSuccess: false, onFailure: true, isValid: false, validatedData: null, error: "Missing API key" };
1867
+ }
1868
+
1869
+ return { onSuccess: true, onFailure: false, isValid: true, validatedData: body, error: "" };
1870
+ }
1871
+
1872
+ /**
1873
+ * Processes the webhook payload
1874
+ *
1875
+ * @flowWeaver nodeType
1876
+ * @label Process Payload
1877
+ * @input data [order:1] - Validated payload data
1878
+ * @input execute [order:0] - Execute
1879
+ * @output result [order:2] - Processing result
1880
+ * @output onSuccess [order:0] - On Success
1881
+ * @output onFailure [order:1] - On Failure
1882
+ */
1883
+ function processPayload(
1884
+ execute: boolean,
1885
+ data: any
1886
+ ): { onSuccess: boolean; onFailure: boolean; result: any } {
1887
+ if (!execute) {
1888
+ return { onSuccess: false, onFailure: false, result: null };
1889
+ }
1890
+
1891
+ // TODO: Add your business logic
1892
+ const result = {
1893
+ processed: true,
1894
+ timestamp: new Date().toISOString(),
1895
+ data
1896
+ };
1897
+
1898
+ return { onSuccess: true, onFailure: false, result };
1899
+ }
1900
+
1901
+ /**
1902
+ * Formats the HTTP response
1903
+ *
1904
+ * @flowWeaver nodeType
1905
+ * @label Format Response
1906
+ * @input result [order:1] - Processing result
1907
+ * @input error [order:2] - Error message if any
1908
+ * @input isSuccess [order:3] - Whether processing succeeded
1909
+ * @input execute [order:0] - Execute
1910
+ * @output statusCode [order:2] - HTTP status code
1911
+ * @output body [order:3] - Response body
1912
+ * @output onSuccess [order:0] - On Success
1913
+ * @output onFailure [order:1] - On Failure
1914
+ */
1915
+ function formatResponse(
1916
+ execute: boolean,
1917
+ result: any,
1918
+ error: string,
1919
+ isSuccess: boolean
1920
+ ): { onSuccess: boolean; onFailure: boolean; statusCode: number; body: any } {
1921
+ if (!execute) {
1922
+ return { onSuccess: false, onFailure: false, statusCode: 0, body: null };
1923
+ }
1924
+
1925
+ if (isSuccess) {
1926
+ return {
1927
+ onSuccess: true,
1928
+ onFailure: false,
1929
+ statusCode: 200,
1930
+ body: { success: true, data: result }
1931
+ };
1932
+ } else {
1933
+ return {
1934
+ onSuccess: true,
1935
+ onFailure: false,
1936
+ statusCode: 400,
1937
+ body: { success: false, error: error || "Processing failed" }
1938
+ };
1939
+ }
1940
+ }
1941
+
1942
+ /**
1943
+ * @flowWeaver workflow
1944
+ * @node validator validateRequest [color: "green"] [icon: "verified"]
1945
+ * @node processor processPayload [color: "blue"] [icon: "settings"]
1946
+ * @node responder formatResponse [color: "cyan"] [icon: "send"]
1947
+ * @connect Start.execute -> validator.execute
1948
+ * @connect Start.headers -> validator.headers
1949
+ * @connect Start.body -> validator.body
1950
+ * @connect validator.onSuccess -> processor.execute
1951
+ * @connect validator.validatedData -> processor.data
1952
+ * @connect validator.error -> responder.error
1953
+ * @connect processor.onSuccess -> responder.execute
1954
+ * @connect processor.result -> responder.result
1955
+ * @connect validator.isValid -> responder.isSuccess
1956
+ * @connect responder.statusCode -> Exit.statusCode
1957
+ * @connect responder.body -> Exit.body
1958
+ * @connect responder.onSuccess -> Exit.onSuccess
1959
+ * @connect responder.onFailure -> Exit.onFailure
1960
+ * @param execute [order:0] - Execute
1961
+ * @param headers [order:1] - HTTP request headers
1962
+ * @param body [order:2] - HTTP request body
1963
+ * @returns onSuccess [order:0] - On Success
1964
+ * @returns onFailure [order:1] - On Failure
1965
+ * @returns statusCode [order:2] - HTTP response status code
1966
+ * @returns body [order:3] - HTTP response body
1967
+ */
1968
+ export ${asyncKeyword}function ${workflowName}(
1969
+ execute: boolean,
1970
+ params: { headers: Record<string, string>; body: any }
1971
+ ): ${returnType} {
1972
+ throw new Error("Compile with: fw compile <file>");
1973
+ }
1974
+ `.trim();
1975
+ }
1976
+ };
1977
+
1978
+ // src/cli/templates/workflows/error-handler.ts
1979
+ var errorHandlerTemplate = {
1980
+ id: "error-handler",
1981
+ name: "Error Handler",
1982
+ description: "Try/catch/retry pattern with error recovery",
1983
+ category: "utility",
1984
+ generate: (opts) => {
1985
+ const { workflowName, async: isAsync } = opts;
1986
+ const asyncKeyword = isAsync ? "async " : "";
1987
+ const returnType = isAsync ? "Promise<{ onSuccess: boolean; onFailure: boolean; result: any; attempts: number; lastError?: string }>" : "{ onSuccess: boolean; onFailure: boolean; result: any; attempts: number; lastError?: string }";
1988
+ return `
1989
+ /**
1990
+ * Retry loop that orchestrates operation attempts
1991
+ * Uses scoped ports to handle retry iteration internally
1992
+ *
1993
+ * @flowWeaver nodeType
1994
+ * @label Retry Loop
1995
+ * @input data [order:1] - Input data to process
1996
+ * @input maxRetries [order:2] - Maximum retry attempts
1997
+ * @input success scope:attempt [order:0] - From operation onSuccess
1998
+ * @input failure scope:attempt [order:1] - From operation onFailure
1999
+ * @input result scope:attempt [order:2] - Operation result
2000
+ * @input error scope:attempt [order:3] - Error from operation
2001
+ * @input execute [order:0] - Execute
2002
+ * @output start scope:attempt [order:0] - Triggers attempt
2003
+ * @output attemptData scope:attempt [order:1] - Data for this attempt
2004
+ * @output attemptNum scope:attempt [order:2] - Current attempt number
2005
+ * @output finalResult [order:2] - Final result
2006
+ * @output attempts [order:3] - Total attempts made
2007
+ * @output lastError [order:4] - Last error if failed
2008
+ * @output onSuccess [order:0] - On Success
2009
+ * @output onFailure [order:1] - On Failure
2010
+ */
2011
+ function retryLoop(
2012
+ execute: boolean,
2013
+ data: any,
2014
+ maxRetries: number,
2015
+ attempt: (start: boolean, attemptData: any, attemptNum: number) => {
2016
+ success: boolean;
2017
+ failure: boolean;
2018
+ result: any;
2019
+ error: string;
2020
+ }
2021
+ ): { onSuccess: boolean; onFailure: boolean; finalResult: any; attempts: number; lastError: string } {
2022
+ if (!execute) {
2023
+ return { onSuccess: false, onFailure: false, finalResult: null, attempts: 0, lastError: '' };
2024
+ }
2025
+
2026
+ let lastError = '';
2027
+ for (let attemptNum = 1; attemptNum <= maxRetries; attemptNum++) {
2028
+ const result = attempt(true, data, attemptNum);
2029
+
2030
+ if (result.success) {
2031
+ return { onSuccess: true, onFailure: false, finalResult: result.result, attempts: attemptNum, lastError: '' };
2032
+ }
2033
+
2034
+ lastError = result.error;
2035
+ console.log(\`[Retry] Attempt \${attemptNum} failed: \${lastError}. \${attemptNum < maxRetries ? 'Retrying...' : 'Max retries reached.'}\`);
2036
+ }
2037
+
2038
+ return { onSuccess: false, onFailure: true, finalResult: null, attempts: maxRetries, lastError };
2039
+ }
2040
+
2041
+ /**
2042
+ * Attempts an operation that might fail
2043
+ *
2044
+ * @flowWeaver nodeType
2045
+ * @label Try Operation
2046
+ * @input data [order:1] - Input data
2047
+ * @input attempt [order:2] - Current attempt number
2048
+ * @input execute [order:0] - Execute
2049
+ * @output result [order:2] - Operation result
2050
+ * @output error [order:3] - Error message if failed
2051
+ * @output onSuccess [order:0] - On Success
2052
+ * @output onFailure [order:1] - On Failure
2053
+ */
2054
+ function tryOperation(
2055
+ execute: boolean,
2056
+ data: any,
2057
+ attempt: number
2058
+ ): { onSuccess: boolean; onFailure: boolean; result: any; error: string } {
2059
+ if (!execute) {
2060
+ return { onSuccess: false, onFailure: false, result: null, error: '' };
2061
+ }
2062
+
2063
+ try {
2064
+ // TODO: Replace with your operation that might fail
2065
+ // This is a placeholder that randomly fails for demonstration
2066
+ if (Math.random() < 0.3) {
2067
+ throw new Error('Simulated failure');
2068
+ }
2069
+
2070
+ const result = { processed: data, attempt };
2071
+ return { onSuccess: true, onFailure: false, result, error: '' };
2072
+ } catch (err) {
2073
+ const error = err instanceof Error ? err.message : String(err);
2074
+ return { onSuccess: false, onFailure: true, result: null, error };
2075
+ }
2076
+ }
2077
+
2078
+ /**
2079
+ * @flowWeaver workflow
2080
+ * @node loop retryLoop [color: "orange"] [icon: "refresh"]
2081
+ * @node tryOp tryOperation loop.attempt [color: "blue"] [icon: "playArrow"]
2082
+ * @connect Start.execute -> loop.execute
2083
+ * @connect Start.data -> loop.data
2084
+ * @connect Start.maxRetries -> loop.maxRetries
2085
+ * @connect loop.start:attempt -> tryOp.execute
2086
+ * @connect loop.attemptData:attempt -> tryOp.data
2087
+ * @connect loop.attemptNum:attempt -> tryOp.attempt
2088
+ * @connect tryOp.result -> loop.result:attempt
2089
+ * @connect tryOp.error -> loop.error:attempt
2090
+ * @connect tryOp.onSuccess -> loop.success:attempt
2091
+ * @connect tryOp.onFailure -> loop.failure:attempt
2092
+ * @connect loop.finalResult -> Exit.result
2093
+ * @connect loop.attempts -> Exit.attempts
2094
+ * @connect loop.lastError -> Exit.lastError
2095
+ * @connect loop.onSuccess -> Exit.onSuccess
2096
+ * @connect loop.onFailure -> Exit.onFailure
2097
+ * @param execute [order:0] - Execute
2098
+ * @param data [order:1] - Input data to process
2099
+ * @param [maxRetries=3] [order:2] - Maximum retry attempts
2100
+ * @returns onSuccess [order:0] - Operation succeeded
2101
+ * @returns onFailure [order:1] - All retries exhausted
2102
+ * @returns result [order:2] - Operation result
2103
+ * @returns attempts [order:3] - Number of attempts made
2104
+ * @returns lastError [order:4] - Last error message if failed
2105
+ */
2106
+ export ${asyncKeyword}function ${workflowName}(
2107
+ execute: boolean,
2108
+ params: { data: any; maxRetries?: number }
2109
+ ): ${returnType} {
2110
+ throw new Error("Compile with: fw compile <file>");
2111
+ }
2112
+ `.trim();
2113
+ }
2114
+ };
2115
+
2116
+ // src/cli/templates/workflows/approval.ts
2117
+ var configSchema2 = {
2118
+ input: {
2119
+ type: "string",
2120
+ label: "Input Port Name",
2121
+ description: "Name of the parameter that carries what needs approval",
2122
+ default: "request",
2123
+ placeholder: "request"
2124
+ },
2125
+ output: {
2126
+ type: "string",
2127
+ label: "Output Port Name",
2128
+ description: "Name of the return value",
2129
+ default: "outcome",
2130
+ placeholder: "outcome"
2131
+ }
2132
+ };
2133
+ var approvalTemplate = {
2134
+ id: "approval",
2135
+ name: "Approval",
2136
+ description: "Prepare a request, pause for a person to approve it, then carry it out",
2137
+ category: "automation",
2138
+ configSchema: configSchema2,
2139
+ generate: (opts) => {
2140
+ const { workflowName, config } = opts;
2141
+ const input = config?.input || "request";
2142
+ const output = config?.output || "outcome";
2143
+ return `
2144
+ /**
2145
+ * Summarises the ${input} for the person who will decide.
2146
+ *
2147
+ * @flowWeaver nodeType
2148
+ * @expression
2149
+ * @label Prepare
2150
+ * @input ${input} - What needs approval
2151
+ * @output summary - One line for the approver
2152
+ * @output ${input} - The same, passed on
2153
+ */
2154
+ function prepare${cap(input)}(${input}: any): { summary: string; ${input}: any } {
2155
+ // TODO: say what is being asked, in one line
2156
+ return { summary: typeof ${input} === 'string' ? ${input} : JSON.stringify(${input}), ${input} };
2157
+ }
2158
+
2159
+ /**
2160
+ * A person approves or refuses. The run pauses here and resumes with the
2161
+ * answer: the approver's note on onSuccess, or a refusal along onFailure.
2162
+ * The body never runs. The coordinator substitutes the answer.
2163
+ *
2164
+ * @flowWeaver nodeType
2165
+ * @durableGate approval
2166
+ * @label Approve
2167
+ * @input summary - What the approver sees
2168
+ * @output note - What the approver said
2169
+ */
2170
+ async function approve(
2171
+ execute: boolean,
2172
+ summary: string
2173
+ ): Promise<{ onSuccess: boolean; onFailure: boolean; note: string }> {
2174
+ throw new Error(\`durable gate: never executes (\${execute}:\${summary})\`);
2175
+ }
2176
+
2177
+ /**
2178
+ * Carries out the approved ${input}.
2179
+ *
2180
+ * @flowWeaver nodeType
2181
+ * @expression
2182
+ * @label Apply
2183
+ * @input ${input} - The approved ${input}, from Prepare
2184
+ * @input note - The approver's note
2185
+ * @output ${output} - What happened
2186
+ */
2187
+ function apply${cap(input)}(${input}: any, note: string): { ${output}: string } {
2188
+ // TODO: do the thing
2189
+ return { ${output}: \`applied \${JSON.stringify(${input})} -- \${note}\` };
2190
+ }
2191
+
2192
+ /**
2193
+ * @flowWeaver workflow
2194
+ * @node prepare prepare${cap(input)} [color: "blue"] [icon: "description"]
2195
+ * @node approval approve [color: "purple"] [icon: "how_to_reg"]
2196
+ * @node apply apply${cap(input)} [color: "green"] [icon: "task_alt"]
2197
+ * @path Start -> prepare -> approval -> apply -> Exit
2198
+ * @path approval:fail -> Exit
2199
+ * @param ${input} - What needs approval
2200
+ * @returns ${output} - What happened
2201
+ */
2202
+ export async function ${workflowName}(
2203
+ execute: boolean,
2204
+ params: { ${input}: any }
2205
+ ): Promise<{ onSuccess: boolean, onFailure: boolean, ${output}: string }> {
2206
+ throw new Error("Compile with: fw compile <file>");
2207
+ }
2208
+ `.trim();
2209
+ }
2210
+ };
2211
+ var cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
2212
+
2213
+ // src/cli/templates/nodes/validator.ts
2214
+ var validatorNodeTemplate = {
2215
+ id: "validator",
2216
+ name: "Validator",
2217
+ description: "Input validation with success/failure routing",
2218
+ category: "validation",
2219
+ generate: (name) => {
2220
+ const pascalName = toPascalCase(name);
2221
+ return `
2222
+ /**
2223
+ * Validates input data against rules
2224
+ *
2225
+ * @flowWeaver nodeType
2226
+ * @label ${pascalName}
2227
+ * @color green
2228
+ * @icon rule
2229
+ * @input data [order:1] - Data to validate
2230
+ * @input execute [order:0] - Execute
2231
+ * @output isValid [order:2] - Whether data is valid
2232
+ * @output validData [order:3] - Validated data (if valid)
2233
+ * @output errors [order:4] - Validation errors (if invalid)
2234
+ * @output onSuccess [order:0] - Validation passed
2235
+ * @output onFailure [order:1] - Validation failed
2236
+ */
2237
+ function ${name}(
2238
+ execute: boolean,
2239
+ data: any
2240
+ ): { onSuccess: boolean; onFailure: boolean; isValid: boolean; validData: any; errors: string[] } {
2241
+ if (!execute) {
2242
+ return { onSuccess: false, onFailure: false, isValid: false, validData: null, errors: [] };
2243
+ }
2244
+
2245
+ const errors: string[] = [];
2246
+
2247
+ // TODO: Add your validation rules
2248
+ // Example validations:
2249
+ if (data === null || data === undefined) {
2250
+ errors.push("Data is required");
2251
+ }
2252
+
2253
+ // if (typeof data.email === 'string' && !data.email.includes('@')) {
2254
+ // errors.push("Invalid email format");
2255
+ // }
2256
+
2257
+ // if (typeof data.age === 'number' && (data.age < 0 || data.age > 150)) {
2258
+ // errors.push("Age must be between 0 and 150");
2259
+ // }
2260
+
2261
+ if (errors.length > 0) {
2262
+ return { onSuccess: false, onFailure: true, isValid: false, validData: null, errors };
2263
+ }
2264
+
2265
+ return { onSuccess: true, onFailure: false, isValid: true, validData: data, errors: [] };
2266
+ }
2267
+ `.trim();
2268
+ }
2269
+ };
2270
+
2271
+ // src/cli/templates/nodes/transformer.ts
2272
+ var transformerNodeTemplate = {
2273
+ id: "transformer",
2274
+ name: "Transformer",
2275
+ description: "Data transformation and mapping",
2276
+ category: "data",
2277
+ generate: (name) => {
2278
+ const pascalName = toPascalCase(name);
2279
+ return `
2280
+ /**
2281
+ * Transforms input data into a new shape
2282
+ *
2283
+ * @flowWeaver nodeType
2284
+ * @label ${pascalName}
2285
+ * @color pink
2286
+ * @icon changeCircle
2287
+ * @input data [order:1] - Input data to transform
2288
+ * @input execute [order:0] - Execute
2289
+ * @output result [order:2] - Transformed data
2290
+ * @output onSuccess [order:0] - On Success
2291
+ * @output onFailure [order:1] - On Failure
2292
+ */
2293
+ function ${name}(
2294
+ execute: boolean,
2295
+ data: any
2296
+ ): { onSuccess: boolean; onFailure: boolean; result: any } {
2297
+ if (!execute) {
2298
+ return { onSuccess: false, onFailure: false, result: null };
2299
+ }
2300
+
2301
+ try {
2302
+ // TODO: Implement your transformation logic
2303
+ // Examples:
2304
+
2305
+ // Map array items
2306
+ // const result = data.map(item => ({ ...item, processed: true }));
2307
+
2308
+ // Reshape object
2309
+ // const result = {
2310
+ // id: data.userId,
2311
+ // fullName: \`\${data.firstName} \${data.lastName}\`,
2312
+ // email: data.contactEmail
2313
+ // };
2314
+
2315
+ // Filter and transform
2316
+ // const result = data
2317
+ // .filter(item => item.active)
2318
+ // .map(item => item.name);
2319
+
2320
+ const result = {
2321
+ ...data,
2322
+ transformedAt: new Date().toISOString()
2323
+ };
2324
+
2325
+ return { onSuccess: true, onFailure: false, result };
2326
+ } catch (err) {
2327
+ console.error("[${pascalName}] Transform error:", err);
2328
+ return { onSuccess: false, onFailure: true, result: null };
2329
+ }
2330
+ }
2331
+ `.trim();
2332
+ }
2333
+ };
2334
+
2335
+ // src/cli/templates/nodes/http.ts
2336
+ var httpNodeTemplate = {
2337
+ id: "http",
2338
+ name: "HTTP Request",
2339
+ description: "Make HTTP requests to external APIs",
2340
+ category: "integration",
2341
+ generate: (name) => {
2342
+ const pascalName = toPascalCase(name);
2343
+ return `
2344
+ /**
2345
+ * Makes an HTTP request
2346
+ *
2347
+ * @flowWeaver nodeType
2348
+ * @label ${pascalName}
2349
+ * @color blue
2350
+ * @icon api
2351
+ * @input url [order:1] - Request URL
2352
+ * @input method [order:2] - HTTP method (GET, POST, PUT, DELETE)
2353
+ * @input headers [order:3] - Request headers
2354
+ * @input body [order:4] - Request body
2355
+ * @input execute [order:0] - Execute
2356
+ * @output response [order:2] - Response data
2357
+ * @output statusCode [order:3] - HTTP status code
2358
+ * @output onSuccess [order:0] - On Success
2359
+ * @output onFailure [order:1] - On Failure
2360
+ */
2361
+ async function ${name}(
2362
+ execute: boolean,
2363
+ url: string,
2364
+ method: "GET" | "POST" | "PUT" | "DELETE",
2365
+ headers: Record<string, string>,
2366
+ body: any
2367
+ ): Promise<{ onSuccess: boolean; onFailure: boolean; response: any; statusCode: number }> {
2368
+ if (!execute) {
2369
+ return { onSuccess: false, onFailure: false, response: null, statusCode: 0 };
2370
+ }
2371
+
2372
+ try {
2373
+ const options: RequestInit = {
2374
+ method,
2375
+ headers: {
2376
+ "Content-Type": "application/json",
2377
+ ...headers
2378
+ }
2379
+ };
2380
+
2381
+ if (method !== "GET" && body) {
2382
+ options.body = JSON.stringify(body);
2383
+ }
2384
+
2385
+ const res = await fetch(url, options);
2386
+ const statusCode = res.status;
2387
+
2388
+ let response;
2389
+ const contentType = res.headers.get("content-type");
2390
+ if (contentType?.includes("application/json")) {
2391
+ response = await res.json();
2392
+ } else {
2393
+ response = await res.text();
2394
+ }
2395
+
2396
+ if (!res.ok) {
2397
+ console.error("[${pascalName}] HTTP error:", statusCode, response);
2398
+ return { onSuccess: false, onFailure: true, response, statusCode };
2399
+ }
2400
+
2401
+ return { onSuccess: true, onFailure: false, response, statusCode };
2402
+ } catch (err) {
2403
+ console.error("[${pascalName}] Request failed:", err);
2404
+ return { onSuccess: false, onFailure: true, response: null, statusCode: 0 };
2405
+ }
2406
+ }
2407
+ `.trim();
2408
+ }
2409
+ };
2410
+
2411
+ // src/cli/templates/nodes/aggregator.ts
2412
+ var aggregatorNodeTemplate = {
2413
+ id: "aggregator",
2414
+ name: "Aggregator",
2415
+ description: "Combine multiple inputs into a single output",
2416
+ category: "data",
2417
+ generate: (name) => {
2418
+ const pascalName = toPascalCase(name);
2419
+ return `
2420
+ /**
2421
+ * Combines multiple inputs into a single output
2422
+ *
2423
+ * @flowWeaver nodeType
2424
+ * @label ${pascalName}
2425
+ * @color orange
2426
+ * @icon callMerge
2427
+ * @input inputA [order:1] - First input
2428
+ * @input inputB [order:2] - Second input
2429
+ * @input inputC [order:3] - Third input (optional)
2430
+ * @input execute [order:0] - Execute
2431
+ * @output combined [order:2] - Combined result
2432
+ * @output count [order:3] - Number of non-null inputs combined
2433
+ * @output onSuccess [order:0] - On Success
2434
+ * @output onFailure [order:1] - On Failure
2435
+ */
2436
+ function ${name}(
2437
+ execute: boolean,
2438
+ inputA: any,
2439
+ inputB: any,
2440
+ inputC: any
2441
+ ): { onSuccess: boolean; onFailure: boolean; combined: any; count: number } {
2442
+ if (!execute) {
2443
+ return { onSuccess: false, onFailure: false, combined: null, count: 0 };
2444
+ }
2445
+
2446
+ // TODO: Customize aggregation logic based on your data types
2447
+ const inputs = [inputA, inputB, inputC].filter(x => x !== null && x !== undefined);
2448
+ const count = inputs.length;
2449
+
2450
+ // Default: merge arrays or objects, or collect into array
2451
+ let combined: any;
2452
+
2453
+ if (inputs.every(Array.isArray)) {
2454
+ // Merge arrays
2455
+ combined = inputs.flat();
2456
+ } else if (inputs.every(x => typeof x === "object" && x !== null && !Array.isArray(x))) {
2457
+ // Merge objects
2458
+ combined = Object.assign({}, ...inputs);
2459
+ } else {
2460
+ // Collect as array
2461
+ combined = inputs;
2462
+ }
2463
+
2464
+ return { onSuccess: true, onFailure: false, combined, count };
2465
+ }
2466
+ `.trim();
2467
+ }
2468
+ };
2469
+
2470
+ // src/cli/templates/nodes/llm-call.ts
2471
+ var llmCallNodeTemplate = {
2472
+ id: "llm-call",
2473
+ name: "LLM Call",
2474
+ description: "Provider-agnostic LLM API call with tool support",
2475
+ category: "ai",
2476
+ generate: (name) => {
2477
+ const funcName = name || "llmCall";
2478
+ return `
2479
+ // LLM Types
2480
+ interface LLMMessage { role: 'system' | 'user' | 'assistant' | 'tool'; content: string; toolCallId?: string; }
2481
+ interface LLMTool { name: string; description: string; parameters: { type: 'object'; properties: Record<string, { type: string; description?: string }>; required?: string[] }; }
2482
+ interface LLMToolCall { id: string; name: string; arguments: Record<string, unknown>; }
2483
+ interface LLMResponse { content: string | null; toolCalls: LLMToolCall[]; finishReason: string; }
2484
+ interface LLMProvider { chat(messages: LLMMessage[], options?: { tools?: LLMTool[]; temperature?: number }): Promise<LLMResponse>; }
2485
+
2486
+ // Mock provider - replace with real provider (OpenAI, Anthropic, etc.)
2487
+ const createMockProvider = (): LLMProvider => ({
2488
+ async chat(messages, options) {
2489
+ const lastMsg = messages[messages.length - 1];
2490
+ if (options?.tools?.length && lastMsg.content.toLowerCase().includes('search')) {
2491
+ return { content: null, toolCalls: [{ id: \`call_\${Date.now()}\`, name: 'search', arguments: { query: lastMsg.content } }], finishReason: 'tool_calls' };
2492
+ }
2493
+ return { content: \`[Mock: \${lastMsg.content.slice(0, 40)}...]\`, toolCalls: [], finishReason: 'stop' };
2494
+ },
2495
+ });
2496
+
2497
+ const llmProvider: LLMProvider = createMockProvider();
2498
+
2499
+ /**
2500
+ * Calls an LLM with messages and optional tools
2501
+ *
2502
+ * @flowWeaver nodeType
2503
+ * @label ${funcName}
2504
+ * @color purple
2505
+ * @icon psychology
2506
+ * @input messages [order:1] - Conversation messages
2507
+ * @input tools [order:2] - Available tools/functions (optional)
2508
+ * @input systemPrompt [order:3] - System prompt (optional)
2509
+ * @input temperature [order:4] - Temperature 0-1 (optional)
2510
+ * @input execute [order:0] - Execute
2511
+ * @output content [order:2] - Text response (null if tool call)
2512
+ * @output toolCalls [order:3] - Tool calls requested by LLM
2513
+ * @output hasToolCalls [order:4] - Whether LLM wants to call tools
2514
+ * @output finishReason [order:5] - Why generation stopped
2515
+ * @output onSuccess [order:0] - On Success
2516
+ * @output onFailure [order:1] - On Failure
2517
+ */
2518
+ async function ${funcName}(
2519
+ execute: boolean,
2520
+ messages: LLMMessage[],
2521
+ tools?: LLMTool[],
2522
+ systemPrompt?: string,
2523
+ temperature?: number
2524
+ ): Promise<{
2525
+ onSuccess: boolean;
2526
+ onFailure: boolean;
2527
+ content: string | null;
2528
+ toolCalls: LLMToolCall[];
2529
+ hasToolCalls: boolean;
2530
+ finishReason: string;
2531
+ }> {
2532
+ if (!execute) {
2533
+ return {
2534
+ onSuccess: false,
2535
+ onFailure: false,
2536
+ content: null,
2537
+ toolCalls: [],
2538
+ hasToolCalls: false,
2539
+ finishReason: 'skipped'
2540
+ };
2541
+ }
2542
+
2543
+ try {
2544
+ const allMessages: LLMMessage[] = systemPrompt
2545
+ ? [{ role: 'system', content: systemPrompt }, ...messages]
2546
+ : messages;
2547
+
2548
+ const response = await llmProvider.chat(allMessages, {
2549
+ tools,
2550
+ temperature,
2551
+ });
2552
+
2553
+ return {
2554
+ onSuccess: true,
2555
+ onFailure: false,
2556
+ content: response.content,
2557
+ toolCalls: response.toolCalls,
2558
+ hasToolCalls: response.toolCalls.length > 0,
2559
+ finishReason: response.finishReason
2560
+ };
2561
+ } catch (error) {
2562
+ console.error('LLM call failed:', error);
2563
+ return {
2564
+ onSuccess: false,
2565
+ onFailure: true,
2566
+ content: null,
2567
+ toolCalls: [],
2568
+ hasToolCalls: false,
2569
+ finishReason: 'error'
2570
+ };
2571
+ }
2572
+ }
2573
+ `.trim();
2574
+ }
2575
+ };
2576
+
2577
+ // src/cli/templates/nodes/tool-executor.ts
2578
+ var toolExecutorNodeTemplate = {
2579
+ id: "tool-executor",
2580
+ name: "Tool Executor",
2581
+ description: "Executes tool calls from LLM response",
2582
+ category: "ai",
2583
+ generate: (name) => {
2584
+ const funcName = name || "executeTool";
2585
+ return `
2586
+ // LLM Types
2587
+ interface LLMToolCall { id: string; name: string; arguments: Record<string, unknown>; }
2588
+ interface LLMMessage { role: 'system' | 'user' | 'assistant' | 'tool'; content: string; toolCallId?: string; }
2589
+
2590
+ // Register your tools here
2591
+ type ToolFunction = (args: Record<string, unknown>) => Promise<unknown>;
2592
+ const toolRegistry: Record<string, ToolFunction> = {
2593
+ // Example tools:
2594
+ // 'search': async (args) => {
2595
+ // const query = String(args.query || '');
2596
+ // return await searchDatabase(query);
2597
+ // },
2598
+ // 'get_weather': async (args) => {
2599
+ // const city = String(args.city || '');
2600
+ // const response = await fetch(\`https://api.weather.example/v1/\${encodeURIComponent(city)}\`);
2601
+ // return response.json();
2602
+ // },
2603
+ };
2604
+
2605
+ /**
2606
+ * Executes a single tool call and returns result as message
2607
+ *
2608
+ * @flowWeaver nodeType
2609
+ * @label ${funcName}
2610
+ * @color cyan
2611
+ * @icon build
2612
+ * @input toolCall [order:1] - Tool call to execute
2613
+ * @input execute [order:0] - Execute
2614
+ * @output result [order:2] - Tool execution result
2615
+ * @output resultMessage [order:3] - Result formatted as LLM message
2616
+ * @output toolName [order:4] - Name of executed tool
2617
+ * @output onSuccess [order:0] - On Success
2618
+ * @output onFailure [order:1] - On Failure
2619
+ */
2620
+ async function ${funcName}(
2621
+ execute: boolean,
2622
+ toolCall: LLMToolCall
2623
+ ): Promise<{
2624
+ onSuccess: boolean;
2625
+ onFailure: boolean;
2626
+ result: unknown;
2627
+ resultMessage: LLMMessage;
2628
+ toolName: string;
2629
+ }> {
2630
+ if (!execute) {
2631
+ return {
2632
+ onSuccess: false,
2633
+ onFailure: false,
2634
+ result: null,
2635
+ resultMessage: { role: 'tool', content: '', toolCallId: '' },
2636
+ toolName: ''
2637
+ };
2638
+ }
2639
+
2640
+ const tool = toolRegistry[toolCall.name];
2641
+ if (!tool) {
2642
+ return {
2643
+ onSuccess: false,
2644
+ onFailure: true,
2645
+ result: null,
2646
+ resultMessage: {
2647
+ role: 'tool',
2648
+ content: JSON.stringify({ error: \`Unknown tool: \${toolCall.name}\` }),
2649
+ toolCallId: toolCall.id
2650
+ },
2651
+ toolName: toolCall.name
2652
+ };
2653
+ }
2654
+
2655
+ try {
2656
+ const result = await tool(toolCall.arguments);
2657
+ return {
2658
+ onSuccess: true,
2659
+ onFailure: false,
2660
+ result,
2661
+ resultMessage: {
2662
+ role: 'tool',
2663
+ content: JSON.stringify(result),
2664
+ toolCallId: toolCall.id
2665
+ },
2666
+ toolName: toolCall.name
2667
+ };
2668
+ } catch (error) {
2669
+ return {
2670
+ onSuccess: false,
2671
+ onFailure: true,
2672
+ result: null,
2673
+ resultMessage: {
2674
+ role: 'tool',
2675
+ content: JSON.stringify({ error: String(error) }),
2676
+ toolCallId: toolCall.id
2677
+ },
2678
+ toolName: toolCall.name
2679
+ };
2680
+ }
2681
+ }
2682
+ `.trim();
2683
+ }
2684
+ };
2685
+
2686
+ // src/cli/templates/nodes/conversation-memory.ts
2687
+ var conversationMemoryNodeTemplate = {
2688
+ id: "conversation-memory",
2689
+ name: "Conversation Memory",
2690
+ description: "Stores and retrieves conversation history",
2691
+ category: "ai",
2692
+ generate: (name) => {
2693
+ const funcName = name || "conversationMemory";
2694
+ return `
2695
+ // LLM Types
2696
+ interface LLMMessage { role: 'system' | 'user' | 'assistant' | 'tool'; content: string; toolCallId?: string; }
2697
+
2698
+ // In-memory store (replace with Redis, database, etc. for production)
2699
+ const conversations: Map<string, LLMMessage[]> = new Map();
2700
+
2701
+ /**
2702
+ * Manages conversation history for stateful chat
2703
+ *
2704
+ * @flowWeaver nodeType
2705
+ * @label ${funcName}
2706
+ * @color blue
2707
+ * @icon database
2708
+ * @input conversationId [order:1] - Unique conversation identifier
2709
+ * @input newMessage [order:2] - New message to add (optional)
2710
+ * @input maxMessages [order:3] - Max messages to retain (optional, default 50)
2711
+ * @input execute [order:0] - Execute
2712
+ * @output messages [order:2] - Full conversation history
2713
+ * @output messageCount [order:3] - Number of messages
2714
+ * @output onSuccess [order:0] - On Success
2715
+ * @output onFailure [order:1] - On Failure
2716
+ */
2717
+ function ${funcName}(
2718
+ execute: boolean,
2719
+ conversationId: string,
2720
+ newMessage?: LLMMessage,
2721
+ maxMessages?: number
2722
+ ): {
2723
+ onSuccess: boolean;
2724
+ onFailure: boolean;
2725
+ messages: LLMMessage[];
2726
+ messageCount: number;
2727
+ } {
2728
+ if (!execute) {
2729
+ return {
2730
+ onSuccess: false,
2731
+ onFailure: false,
2732
+ messages: [],
2733
+ messageCount: 0
2734
+ };
2735
+ }
2736
+
2737
+ const limit = maxMessages ?? 50;
2738
+
2739
+ // Get or create conversation
2740
+ if (!conversations.has(conversationId)) {
2741
+ conversations.set(conversationId, []);
2742
+ }
2743
+
2744
+ const history = conversations.get(conversationId)!;
2745
+
2746
+ // Add new message if provided
2747
+ if (newMessage) {
2748
+ history.push(newMessage);
2749
+
2750
+ // Trim to max length (keep system message if present)
2751
+ while (history.length > limit) {
2752
+ const firstNonSystem = history.findIndex(m => m.role !== 'system');
2753
+ if (firstNonSystem > 0) {
2754
+ history.splice(firstNonSystem, 1);
2755
+ } else {
2756
+ history.shift();
2757
+ }
2758
+ }
2759
+ }
2760
+
2761
+ return {
2762
+ onSuccess: true,
2763
+ onFailure: false,
2764
+ messages: [...history],
2765
+ messageCount: history.length
2766
+ };
2767
+ }
2768
+ `.trim();
2769
+ }
2770
+ };
2771
+
2772
+ // src/cli/templates/nodes/prompt-template.ts
2773
+ var promptTemplateNodeTemplate = {
2774
+ id: "prompt-template",
2775
+ name: "Prompt Template",
2776
+ description: "Interpolate variables into a prompt template string",
2777
+ category: "ai",
2778
+ generate: (name) => {
2779
+ const funcName = name || "promptTemplate";
2780
+ const label = toPascalCase(funcName);
2781
+ return `
2782
+ /**
2783
+ * Interpolate variables into a prompt template string.
2784
+ * Uses {{variableName}} syntax for placeholders.
2785
+ *
2786
+ * Example:
2787
+ * template: "Hello {{name}}, your order {{orderId}} is ready."
2788
+ * variables: { name: "Alice", orderId: "12345" }
2789
+ * \u2192 prompt: "Hello Alice, your order 12345 is ready."
2790
+ *
2791
+ * @flowWeaver nodeType
2792
+ * @expression
2793
+ * @label ${label}
2794
+ * @color pink
2795
+ * @icon textSnippet
2796
+ * @input template [order:0] - Template string with {{variable}} placeholders
2797
+ * @input variables [order:1] - Key-value pairs to interpolate
2798
+ * @output prompt [order:0] - Rendered prompt string
2799
+ * @output unresolvedCount [order:1] - Number of unresolved placeholders
2800
+ */
2801
+ function ${funcName}(
2802
+ template: string,
2803
+ variables: Record<string, string>
2804
+ ): {
2805
+ prompt: string;
2806
+ unresolvedCount: number;
2807
+ } {
2808
+ let unresolved = 0;
2809
+
2810
+ const prompt = template.replace(/\\{\\{\\s*(\\w+)\\s*\\}\\}/g, (match, key) => {
2811
+ if (key in variables) {
2812
+ return variables[key];
2813
+ }
2814
+ unresolved++;
2815
+ return match; // Leave unresolved placeholders as-is
2816
+ });
2817
+
2818
+ return { prompt, unresolvedCount: unresolved };
2819
+ }
2820
+ `.trim();
2821
+ }
2822
+ };
2823
+
2824
+ // src/cli/templates/nodes/json-extractor.ts
2825
+ var jsonExtractorNodeTemplate = {
2826
+ id: "json-extractor",
2827
+ name: "JSON Extractor",
2828
+ description: "Extract structured JSON from LLM text output",
2829
+ category: "ai",
2830
+ generate: (name) => {
2831
+ const funcName = name || "jsonExtractor";
2832
+ const label = toPascalCase(funcName);
2833
+ return `
2834
+ /**
2835
+ * Extract structured JSON from LLM text output.
2836
+ * Handles markdown code fences, leading/trailing text, and optional schema validation.
2837
+ *
2838
+ * Strips \\\`\\\`\\\`json ... \\\`\\\`\\\` fences, finds the first valid JSON object or array,
2839
+ * and optionally validates that expected field names are present.
2840
+ *
2841
+ * @flowWeaver nodeType
2842
+ * @expression
2843
+ * @label ${label}
2844
+ * @color cyan
2845
+ * @icon dataObject
2846
+ * @input text [order:0] - Raw text potentially containing JSON
2847
+ * @input schema [order:1] - Expected field names for validation (optional)
2848
+ * @output extracted [order:0] - Parsed JSON object (null if extraction failed)
2849
+ * @output valid [order:1] - Whether extraction and validation succeeded
2850
+ * @output raw [order:2] - The raw JSON string that was found
2851
+ */
2852
+ function ${funcName}(
2853
+ text: string,
2854
+ schema?: string[]
2855
+ ): {
2856
+ extracted: Record<string, unknown> | null;
2857
+ valid: boolean;
2858
+ raw: string;
2859
+ } {
2860
+ if (!text || typeof text !== 'string') {
2861
+ return { extracted: null, valid: false, raw: '' };
2862
+ }
2863
+
2864
+ // Strip markdown code fences
2865
+ let cleaned = text;
2866
+ const fenceMatch = cleaned.match(/\\\`\\\`\\\`(?:json)?\\s*([\\s\\S]*?)\\\`\\\`\\\`/);
2867
+ if (fenceMatch) {
2868
+ cleaned = fenceMatch[1].trim();
2869
+ }
2870
+
2871
+ // Find first JSON object or array via brace/bracket matching
2872
+ const startChar = cleaned.indexOf('{') !== -1 && (cleaned.indexOf('[') === -1 || cleaned.indexOf('{') < cleaned.indexOf('['))
2873
+ ? '{'
2874
+ : '[';
2875
+ const endChar = startChar === '{' ? '}' : ']';
2876
+ const startIdx = cleaned.indexOf(startChar);
2877
+
2878
+ if (startIdx === -1) {
2879
+ return { extracted: null, valid: false, raw: '' };
2880
+ }
2881
+
2882
+ // Walk forward to find the matching closing brace/bracket
2883
+ let depth = 0;
2884
+ let inString = false;
2885
+ let escape = false;
2886
+ let endIdx = -1;
2887
+
2888
+ for (let i = startIdx; i < cleaned.length; i++) {
2889
+ const ch = cleaned[i];
2890
+
2891
+ if (escape) {
2892
+ escape = false;
2893
+ continue;
2894
+ }
2895
+
2896
+ if (ch === '\\\\') {
2897
+ escape = true;
2898
+ continue;
2899
+ }
2900
+
2901
+ if (ch === '"') {
2902
+ inString = !inString;
2903
+ continue;
2904
+ }
2905
+
2906
+ if (inString) continue;
2907
+
2908
+ if (ch === startChar) depth++;
2909
+ if (ch === endChar) depth--;
2910
+
2911
+ if (depth === 0) {
2912
+ endIdx = i;
2913
+ break;
2914
+ }
2915
+ }
2916
+
2917
+ if (endIdx === -1) {
2918
+ return { extracted: null, valid: false, raw: '' };
2919
+ }
2920
+
2921
+ const raw = cleaned.slice(startIdx, endIdx + 1);
2922
+
2923
+ try {
2924
+ const parsed = JSON.parse(raw);
2925
+
2926
+ // Validate schema if provided
2927
+ if (schema && schema.length > 0 && typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
2928
+ const missingFields = schema.filter(field => !(field in parsed));
2929
+ if (missingFields.length > 0) {
2930
+ return { extracted: parsed, valid: false, raw };
2931
+ }
2932
+ }
2933
+
2934
+ return { extracted: parsed, valid: true, raw };
2935
+ } catch {
2936
+ return { extracted: null, valid: false, raw };
2937
+ }
2938
+ }
2939
+ `.trim();
2940
+ }
2941
+ };
2942
+
2943
+ // src/cli/templates/nodes/human-approval.ts
2944
+ var humanApprovalNodeTemplate = {
2945
+ id: "human-approval",
2946
+ name: "Human Approval",
2947
+ description: "Pause workflow and wait for human approval",
2948
+ category: "workflow",
2949
+ generate: (name) => {
2950
+ const funcName = name || "humanApproval";
2951
+ const label = toPascalCase(funcName);
2952
+ return `
2953
+ /**
2954
+ * Yield a durable human-approval gate.
2955
+ *
2956
+ * The generated engine never calls this body. A coordinator persists the
2957
+ * yielded continuation and gate atomically, then supplies the exact resolution
2958
+ * to a later compatible Node.js executor invocation.
2959
+ *
2960
+ * @flowWeaver nodeType
2961
+ * @durableGate approval
2962
+ * @label ${label}
2963
+ * @color orange
2964
+ * @icon verified
2965
+ * @input execute [order:0] - Execute
2966
+ * @input prompt [order:1] - Approval prompt shown to reviewer
2967
+ * @input context [order:2] - Additional context for the reviewer (optional)
2968
+ * @input timeout [order:3] - Timeout duration e.g. "7d", "1h" (optional)
2969
+ * @output onSuccess [order:0] - On Success
2970
+ * @output onFailure [order:1] - On Failure (timeout or error)
2971
+ * @output approved [order:2] - Whether the request was approved
2972
+ * @output response [order:3] - Reviewer's response text
2973
+ * @output reviewer [order:4] - Reviewer identifier
2974
+ */
2975
+ async function ${funcName}(
2976
+ execute: boolean,
2977
+ prompt: string,
2978
+ context?: Record<string, unknown>,
2979
+ timeout?: string
2980
+ ): Promise<{
2981
+ onSuccess: boolean;
2982
+ onFailure: boolean;
2983
+ approved: boolean;
2984
+ response?: string;
2985
+ reviewer?: string;
2986
+ }> {
2987
+ throw new Error(
2988
+ \`durable approval gate must not execute: \${execute}:\${prompt}:\${String(context)}:\${String(timeout)}\`,
2989
+ );
2990
+ }
2991
+ `.trim();
2992
+ }
2993
+ };
2994
+
2995
+ // src/cli/templates/nodes/agent-router.ts
2996
+ var agentRouterNodeTemplate = {
2997
+ id: "agent-router",
2998
+ name: "Agent Router",
2999
+ description: "Route to different handlers based on a classification result",
3000
+ category: "ai",
3001
+ generate: (name) => {
3002
+ const funcName = name || "agentRouter";
3003
+ const label = toPascalCase(funcName);
3004
+ return `
3005
+ // ============================================================
3006
+ // ROUTE DEFINITIONS
3007
+ // ============================================================
3008
+ //
3009
+ // Define your routes here. The router matches the 'category' input
3010
+ // (from an upstream LLM call) against route names using case-insensitive
3011
+ // comparison. The last route is used as a default/fallback.
3012
+ //
3013
+ // Example wiring in a workflow:
3014
+ // llmCall.content \u2192 agentRouter.category
3015
+ // agentRouter.selectedRoute \u2192 (use for downstream branching)
3016
+
3017
+ interface Route {
3018
+ name: string;
3019
+ description: string;
3020
+ }
3021
+
3022
+ const DEFAULT_ROUTES: Route[] = [
3023
+ { name: 'billing', description: 'Billing inquiries, invoices, payments' },
3024
+ { name: 'technical', description: 'Technical support, bugs, troubleshooting' },
3025
+ { name: 'general', description: 'General questions (default fallback)' },
3026
+ ];
3027
+
3028
+ /**
3029
+ * Route to different handlers based on a classification result.
3030
+ * Matches the category string against route names (case-insensitive).
3031
+ * Falls back to the last route if no match is found.
3032
+ *
3033
+ * @flowWeaver nodeType
3034
+ * @label ${label}
3035
+ * @color blue
3036
+ * @icon altRoute
3037
+ * @input execute [order:0] - Execute
3038
+ * @input category [order:1] - Classification result (from upstream LLM call)
3039
+ * @input routes [order:2] - Available routes with name and description (optional)
3040
+ * @output onSuccess [order:0] - On Success
3041
+ * @output onFailure [order:1] - On Failure (no routes provided)
3042
+ * @output selectedRoute [order:2] - Name of the matched route
3043
+ * @output routeDescription [order:3] - Description of the matched route
3044
+ * @output isDefault [order:4] - Whether the default/fallback route was used
3045
+ */
3046
+ function ${funcName}(
3047
+ execute: boolean,
3048
+ category: string,
3049
+ routes?: Route[]
3050
+ ): {
3051
+ onSuccess: boolean;
3052
+ onFailure: boolean;
3053
+ selectedRoute: string;
3054
+ routeDescription: string;
3055
+ isDefault: boolean;
3056
+ } {
3057
+ if (!execute) {
3058
+ return {
3059
+ onSuccess: false,
3060
+ onFailure: false,
3061
+ selectedRoute: '',
3062
+ routeDescription: '',
3063
+ isDefault: false,
3064
+ };
3065
+ }
3066
+
3067
+ const activeRoutes = routes && routes.length > 0 ? routes : DEFAULT_ROUTES;
3068
+
3069
+ if (activeRoutes.length === 0) {
3070
+ return {
3071
+ onSuccess: false,
3072
+ onFailure: true,
3073
+ selectedRoute: '',
3074
+ routeDescription: '',
3075
+ isDefault: false,
3076
+ };
3077
+ }
3078
+
3079
+ // Case-insensitive match against route names
3080
+ const normalized = (category || '').trim().toLowerCase();
3081
+ const matched = activeRoutes.find(
3082
+ (r) => r.name.toLowerCase() === normalized
3083
+ );
3084
+
3085
+ if (matched) {
3086
+ return {
3087
+ onSuccess: true,
3088
+ onFailure: false,
3089
+ selectedRoute: matched.name,
3090
+ routeDescription: matched.description,
3091
+ isDefault: false,
3092
+ };
3093
+ }
3094
+
3095
+ // Fallback to last route as default
3096
+ const fallback = activeRoutes[activeRoutes.length - 1];
3097
+ return {
3098
+ onSuccess: true,
3099
+ onFailure: false,
3100
+ selectedRoute: fallback.name,
3101
+ routeDescription: fallback.description,
3102
+ isDefault: true,
3103
+ };
3104
+ }
3105
+ `.trim();
3106
+ }
3107
+ };
3108
+
3109
+ // src/cli/templates/nodes/rag-retriever.ts
3110
+ var ragRetrieverNodeTemplate = {
3111
+ id: "rag-retriever",
3112
+ name: "RAG Retriever",
3113
+ description: "Retrieve relevant documents via vector similarity search",
3114
+ category: "ai",
3115
+ generate: (name) => {
3116
+ const funcName = name || "ragRetriever";
3117
+ const label = toPascalCase(funcName);
3118
+ return `
3119
+ // ============================================================
3120
+ // VECTOR STORE
3121
+ // ============================================================
3122
+ //
3123
+ // Replace mockRetrieve() with your vector store:
3124
+ //
3125
+ // Pinecone: const results = await index.query({ vector: embedding, topK });
3126
+ // pgvector: const results = await db.query(
3127
+ // 'SELECT text, metadata, 1 - (embedding <=> $1) AS score FROM docs ORDER BY score DESC LIMIT $2',
3128
+ // [embedding, topK]
3129
+ // );
3130
+ // Weaviate: const results = await client.graphql.get()
3131
+ // .withClassName('Document')
3132
+ // .withNearText({ concepts: [query] })
3133
+ // .withLimit(topK)
3134
+ // .do();
3135
+ // ChromaDB: const results = await collection.query({ queryTexts: [query], nResults: topK });
3136
+
3137
+ interface RetrievedDocument {
3138
+ text: string;
3139
+ score: number;
3140
+ metadata?: Record<string, unknown>;
3141
+ }
3142
+
3143
+ // Mock document store. Replace with a real vector database
3144
+ const MOCK_DOCUMENTS: Record<string, RetrievedDocument[]> = {
3145
+ default: [
3146
+ { text: 'Flow Weaver compiles workflows to standalone TypeScript functions.', score: 0.95, metadata: { source: 'docs/overview.md' } },
3147
+ { text: 'The compiler validates connections at compile time, catching errors before runtime.', score: 0.88, metadata: { source: 'docs/compiler.md' } },
3148
+ { text: 'Workflows are standard TypeScript files with JSDoc annotations.', score: 0.82, metadata: { source: 'docs/authoring.md' } },
3149
+ { text: 'Deploy compiled workflows to any supported target via installed packs.', score: 0.75, metadata: { source: 'docs/deployment.md' } },
3150
+ { text: 'The console shows each run step by step and answers paused gates from a form.', score: 0.71, metadata: { source: 'docs/console.md' } },
3151
+ ],
3152
+ };
3153
+
3154
+ async function mockRetrieve(query: string, collection: string, topK: number): Promise<RetrievedDocument[]> {
3155
+ const docs = MOCK_DOCUMENTS[collection] || MOCK_DOCUMENTS['default'] || [];
3156
+
3157
+ // Simple keyword overlap scoring (mock, since real stores use vector similarity)
3158
+ const queryWords = new Set(query.toLowerCase().split(/\\s+/));
3159
+ const scored = docs.map((doc) => {
3160
+ const docWords = doc.text.toLowerCase().split(/\\s+/);
3161
+ const overlap = docWords.filter((w) => queryWords.has(w)).length;
3162
+ const score = Math.min(0.99, overlap / Math.max(queryWords.size, 1) * 0.5 + doc.score * 0.5);
3163
+ return { ...doc, score };
3164
+ });
3165
+
3166
+ return scored
3167
+ .sort((a, b) => b.score - a.score)
3168
+ .slice(0, topK);
3169
+ }
3170
+
3171
+ /**
3172
+ * Retrieve relevant documents via vector similarity search.
3173
+ * Returns scored documents and a concatenated context string ready for LLM input.
3174
+ *
3175
+ * @flowWeaver nodeType
3176
+ * @label ${label}
3177
+ * @color green
3178
+ * @icon search
3179
+ * @input execute [order:0] - Execute
3180
+ * @input query [order:1] - Search query text
3181
+ * @input collection [order:2] - Collection/index name
3182
+ * @input topK [order:3] - Number of results (optional, default 5)
3183
+ * @output onSuccess [order:0] - On Success
3184
+ * @output onFailure [order:1] - On Failure
3185
+ * @output documents [order:2] - Retrieved documents with relevance scores
3186
+ * @output context [order:3] - Concatenated document text for LLM context
3187
+ */
3188
+ async function ${funcName}(
3189
+ execute: boolean,
3190
+ query: string,
3191
+ collection: string,
3192
+ topK?: number
3193
+ ): Promise<{
3194
+ onSuccess: boolean;
3195
+ onFailure: boolean;
3196
+ documents: RetrievedDocument[];
3197
+ context: string;
3198
+ }> {
3199
+ if (!execute) {
3200
+ return {
3201
+ onSuccess: false,
3202
+ onFailure: false,
3203
+ documents: [],
3204
+ context: '',
3205
+ };
3206
+ }
3207
+
3208
+ try {
3209
+ const limit = topK ?? 5;
3210
+ const documents = await mockRetrieve(query, collection, limit);
3211
+
3212
+ // Concatenate document texts for easy LLM context injection
3213
+ const context = documents
3214
+ .map((doc, i) => \`[Document \${i + 1} (score: \${doc.score.toFixed(2)})]
3215
+ \${doc.text}\`)
3216
+ .join('\\n\\n');
3217
+
3218
+ return {
3219
+ onSuccess: true,
3220
+ onFailure: false,
3221
+ documents,
3222
+ context,
3223
+ };
3224
+ } catch (error) {
3225
+ console.error('RAG retrieval failed:', error);
3226
+ return {
3227
+ onSuccess: false,
3228
+ onFailure: true,
3229
+ documents: [],
3230
+ context: '',
3231
+ };
3232
+ }
3233
+ }
3234
+ `.trim();
3235
+ }
3236
+ };
3237
+
3238
+ // src/cli/templates/index.ts
3239
+ var workflowTemplates = [
3240
+ sequentialTemplate,
3241
+ foreachTemplate,
3242
+ conditionalTemplate,
3243
+ approvalTemplate,
3244
+ aiAgentTemplate,
3245
+ aiReactTemplate,
3246
+ aiRagTemplate,
3247
+ aiChatTemplate,
3248
+ aggregatorTemplate,
3249
+ webhookTemplate,
3250
+ errorHandlerTemplate
3251
+ ];
3252
+ var nodeTemplates = [
3253
+ validatorNodeTemplate,
3254
+ transformerNodeTemplate,
3255
+ httpNodeTemplate,
3256
+ aggregatorNodeTemplate,
3257
+ llmCallNodeTemplate,
3258
+ toolExecutorNodeTemplate,
3259
+ conversationMemoryNodeTemplate,
3260
+ promptTemplateNodeTemplate,
3261
+ jsonExtractorNodeTemplate,
3262
+ humanApprovalNodeTemplate,
3263
+ agentRouterNodeTemplate,
3264
+ ragRetrieverNodeTemplate
3265
+ ];
3266
+ function getWorkflowTemplate(id) {
3267
+ return workflowTemplates.find((t) => t.id === id) ?? packWorkflowTemplates.find((t) => t.id === id);
3268
+ }
3269
+ function getNodeTemplate(id) {
3270
+ return nodeTemplates.find((t) => t.id === id);
3271
+ }
3272
+ var packWorkflowTemplates = [];
3273
+ function getAllWorkflowTemplates() {
3274
+ return [...workflowTemplates, ...packWorkflowTemplates];
3275
+ }
3276
+ function registerWorkflowTemplates(templates) {
3277
+ for (const tmpl of templates) {
3278
+ if (!packWorkflowTemplates.some((t) => t.id === tmpl.id)) {
3279
+ packWorkflowTemplates.push(tmpl);
3280
+ }
3281
+ }
3282
+ }
3283
+
3284
+ export {
3285
+ toCamelCase,
3286
+ nodeTemplates,
3287
+ getWorkflowTemplate,
3288
+ getNodeTemplate,
3289
+ getAllWorkflowTemplates,
3290
+ registerWorkflowTemplates
3291
+ };