@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,2925 @@
1
+ import { createRequire as __createRequire } from "module";
2
+ const require = __createRequire(import.meta.url);
3
+ import {
4
+ exportWorkflow
5
+ } from "./flow-weaver-chunk-54M4KNEL.mjs";
6
+ import {
7
+ ERROR_HINTS
8
+ } from "./flow-weaver-chunk-KOEMJHLG.mjs";
9
+ import {
10
+ loadPackDocTopics
11
+ } from "./flow-weaver-chunk-J7EPZW2I.mjs";
12
+ import {
13
+ DebugController
14
+ } from "./flow-weaver-chunk-FPPPU2DG.mjs";
15
+ import {
16
+ ARTIFACT_KINDS,
17
+ renderArtifact
18
+ } from "./flow-weaver-chunk-Z5ZJPNSY.mjs";
19
+ import {
20
+ WorkflowDiffer,
21
+ getImpactReasons
22
+ } from "./flow-weaver-chunk-7ET6N32V.mjs";
23
+ import {
24
+ buildProcessModel,
25
+ stepLabel
26
+ } from "./flow-weaver-chunk-HMAKDE55.mjs";
27
+ import {
28
+ getPackDocTopics,
29
+ listTopics,
30
+ readTopic,
31
+ readTopicStructured,
32
+ searchDocs
33
+ } from "./flow-weaver-chunk-XG2WKXYZ.mjs";
34
+ import {
35
+ generateManifest,
36
+ readManifest
37
+ } from "./flow-weaver-chunk-AA3NATMX.mjs";
38
+ import {
39
+ validatePackage
40
+ } from "./flow-weaver-chunk-2C7PZCV5.mjs";
41
+ import {
42
+ RESERVED_PATHS,
43
+ gateOutputSchemas,
44
+ isLoopback,
45
+ planRoutes,
46
+ workflowParamsSchema
47
+ } from "./flow-weaver-chunk-MHJ4N652.mjs";
48
+ import {
49
+ answerAgentGate,
50
+ computeBundleDigest,
51
+ createFileEffectAdapter,
52
+ createLocalCoordinator,
53
+ defaultRunsDir,
54
+ isAnswering,
55
+ noteAnswerMisfit,
56
+ reclaimStaleAgentAnswers,
57
+ transcriptName,
58
+ tryProfile
59
+ } from "./flow-weaver-chunk-YLSRZWFK.mjs";
60
+ import "./flow-weaver-chunk-EKWF27G6.mjs";
61
+ import {
62
+ DEFAULT_MODEL,
63
+ STARTER_AGENTS_YAML,
64
+ SUGGESTED_MODELS,
65
+ agentsFile,
66
+ keyEnvOf,
67
+ loadAgentProfiles,
68
+ readiness,
69
+ saveAgentProfiles,
70
+ validateProfile
71
+ } from "./flow-weaver-chunk-TS5P3PIN.mjs";
72
+ import {
73
+ executeWorkflow
74
+ } from "./flow-weaver-chunk-GBUNNP33.mjs";
75
+ import {
76
+ getAvailableWorkflows
77
+ } from "./flow-weaver-chunk-NQKKWDGF.mjs";
78
+ import "./flow-weaver-chunk-V6DHWFQG.mjs";
79
+ import {
80
+ createTargetRegistry
81
+ } from "./flow-weaver-chunk-3MKUQP3D.mjs";
82
+ import {
83
+ runDoctorChecks
84
+ } from "./flow-weaver-chunk-U3EO3X4B.mjs";
85
+ import {
86
+ installRoot,
87
+ isAlive,
88
+ listServices
89
+ } from "./flow-weaver-chunk-MSI2UJES.mjs";
90
+ import "./flow-weaver-chunk-3BSYCWPL.mjs";
91
+ import {
92
+ listInstalledPackages,
93
+ resolveRegistries,
94
+ searchAllRegistries
95
+ } from "./flow-weaver-chunk-4DVY73ML.mjs";
96
+ import {
97
+ validateWorkflow
98
+ } from "./flow-weaver-chunk-ZQALO25T.mjs";
99
+ import "./flow-weaver-chunk-DM4BBRRU.mjs";
100
+ import "./flow-weaver-chunk-6ZUJ7LMX.mjs";
101
+ import "./flow-weaver-chunk-A6M5K3W7.mjs";
102
+ import {
103
+ parseWorkflow
104
+ } from "./flow-weaver-chunk-W3YNK26P.mjs";
105
+ import "./flow-weaver-chunk-BHCC5FE5.mjs";
106
+ import {
107
+ VERSION
108
+ } from "./flow-weaver-chunk-VXWNLYQU.mjs";
109
+ import "./flow-weaver-chunk-RIWE7YTR.mjs";
110
+ import "./flow-weaver-chunk-IJJ4JXTL.mjs";
111
+ import "./flow-weaver-chunk-55QMUZIA.mjs";
112
+ import "./flow-weaver-chunk-EM5HWQ4R.mjs";
113
+ import {
114
+ getTopologicalOrder
115
+ } from "./flow-weaver-chunk-Z44JK332.mjs";
116
+ import {
117
+ hasInPlaceMarkers,
118
+ httpRouteText,
119
+ isConnectionCoveredByMacroStatic
120
+ } from "./flow-weaver-chunk-APX6MQ5A.mjs";
121
+ import "./flow-weaver-chunk-7G63RR4K.mjs";
122
+ import {
123
+ getErrorMessage
124
+ } from "./flow-weaver-chunk-OMVWSNHJ.mjs";
125
+ import "./flow-weaver-chunk-GAQXZHNO.mjs";
126
+ import "./flow-weaver-chunk-DRN7KPWY.mjs";
127
+ import "./flow-weaver-chunk-N767YRAI.mjs";
128
+
129
+ // src/console/server.ts
130
+ import * as http from "node:http";
131
+ import * as fs13 from "node:fs";
132
+ import * as path13 from "node:path";
133
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
134
+
135
+ // src/console/services.ts
136
+ import { spawn as spawn2 } from "node:child_process";
137
+ import { createHash, randomBytes } from "node:crypto";
138
+ import * as fs2 from "node:fs";
139
+ import * as os from "node:os";
140
+ import * as path2 from "node:path";
141
+
142
+ // src/console/cli-run.ts
143
+ import { spawn } from "node:child_process";
144
+ import * as fs from "node:fs";
145
+ import * as path from "node:path";
146
+ import { fileURLToPath } from "node:url";
147
+ var NOT_FROM_CONSOLE = /* @__PURE__ */ new Set([
148
+ "console",
149
+ "mcp-server",
150
+ "mcp-setup",
151
+ "dev",
152
+ "watch",
153
+ "serve"
154
+ ]);
155
+ function planFwCommand(argv) {
156
+ const args = argv[0] === "fw" || argv[0] === "flow-weaver" ? argv.slice(1) : [...argv];
157
+ if (!args.length) return { ok: false, error: "nothing to run" };
158
+ if (args.some((a) => typeof a !== "string")) return { ok: false, error: "arguments must be strings" };
159
+ const command = args[0];
160
+ if (NOT_FROM_CONSOLE.has(command)) {
161
+ return { ok: false, error: `\`fw ${command}\` runs outside the console: it is long-lived. Use a terminal.` };
162
+ }
163
+ return { ok: true, args };
164
+ }
165
+ function resolveCliEntry(here = path.dirname(fileURLToPath(import.meta.url))) {
166
+ const built = path.join(here, "..", "cli", "flow-weaver.mjs");
167
+ if (fs.existsSync(built)) return { exec: process.execPath, prefix: [built] };
168
+ const source = path.join(here, "..", "cli", "index.ts");
169
+ if (fs.existsSync(source)) return { exec: process.execPath, prefix: ["--import", "tsx", source] };
170
+ throw new Error("cannot find the fw CLI beside the console");
171
+ }
172
+ function spawnFw(args, cwd) {
173
+ const { exec, prefix } = resolveCliEntry();
174
+ const { NODE_OPTIONS: _flags, ...env } = process.env;
175
+ return spawn(exec, [...prefix, ...args], {
176
+ cwd,
177
+ env: { ...env, FORCE_COLOR: "0", NO_COLOR: "1" },
178
+ stdio: ["ignore", "pipe", "pipe"],
179
+ windowsHide: true
180
+ });
181
+ }
182
+
183
+ // src/console/services.ts
184
+ var DEFAULT_SETTINGS = {
185
+ serve: { port: 3e3, host: "127.0.0.1", auth: "token", agents: true, trace: true, dev: false, swagger: false, autoStart: false },
186
+ watch: { autoStart: false }
187
+ };
188
+ var MAX_LINES = 500;
189
+ var STOP_GRACE_MS = 5e3;
190
+ function consoleSettingsDir() {
191
+ return process.env.FW_CONSOLE_DIR ?? path2.join(os.homedir(), ".fw", "console");
192
+ }
193
+ function spawnFwWith(args, cwd, env) {
194
+ const { exec, prefix } = resolveCliEntry();
195
+ return spawn2(exec, [...prefix, ...args], { cwd, env, stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
196
+ }
197
+ var Supervisor = class {
198
+ constructor(opts) {
199
+ this.opts = opts;
200
+ this.projectDir = path2.resolve(opts.projectDir);
201
+ const dir = opts.settingsDir ?? consoleSettingsDir();
202
+ this.file = path2.join(dir, `${createHash("sha256").update(real(this.projectDir)).digest("hex").slice(0, 16)}.json`);
203
+ }
204
+ opts;
205
+ children = /* @__PURE__ */ new Map();
206
+ listeners = /* @__PURE__ */ new Map();
207
+ file;
208
+ cache;
209
+ projectDir;
210
+ // ---------------------------------------------------------- settings
211
+ settings() {
212
+ if (this.cache) return this.cache;
213
+ let stored;
214
+ try {
215
+ stored = JSON.parse(fs2.readFileSync(this.file, "utf8"));
216
+ } catch {
217
+ stored = {};
218
+ }
219
+ this.cache = {
220
+ serve: { ...DEFAULT_SETTINGS.serve, ...stored.serve ?? {} },
221
+ watch: { ...DEFAULT_SETTINGS.watch, ...stored.watch ?? {} }
222
+ };
223
+ return this.cache;
224
+ }
225
+ saveSettings(kind, patch) {
226
+ const current = this.settings();
227
+ const next = { ...current, [kind]: { ...current[kind], ...patch } };
228
+ if (kind === "serve") {
229
+ const s = next.serve;
230
+ if (!Number.isInteger(s.port) || s.port < 0 || s.port > 65535) throw new Error("port must be a whole number between 0 and 65535");
231
+ if (!/^[A-Za-z0-9.:[\]-]+$/.test(s.host)) throw new Error("host must be a host name or an address");
232
+ if (s.auth !== "token" && s.auth !== "open") throw new Error("auth is token or open");
233
+ if (s.auth === "open" && !["127.0.0.1", "localhost", "::1", "[::1]"].includes(s.host)) throw new Error("a server beyond loopback needs a token: set auth to token, or host to 127.0.0.1");
234
+ }
235
+ fs2.mkdirSync(path2.dirname(this.file), { recursive: true });
236
+ const tmp = `${this.file}.${process.pid}.tmp`;
237
+ fs2.writeFileSync(tmp, JSON.stringify(next, null, 2));
238
+ fs2.renameSync(tmp, this.file);
239
+ this.cache = next;
240
+ return next;
241
+ }
242
+ // ------------------------------------------------------------ control
243
+ /** Start a service with the saved settings. A running one is left alone. */
244
+ start(kind) {
245
+ const existing = this.children.get(kind);
246
+ if (existing && (existing.state === "running" || existing.state === "starting")) return this.view(kind);
247
+ const others = this.registryFor(kind);
248
+ if (kind === "serve" && others.length) throw new Error(`fw serve is already running for this project (pid ${others[0].pid}${others[0].url ? `, ${others[0].url}` : ""}). Stop it first`);
249
+ const settings = this.settings();
250
+ const { NODE_OPTIONS: _flags, ...base } = process.env;
251
+ const env = { ...base, FORCE_COLOR: "0", NO_COLOR: "1" };
252
+ let args;
253
+ let token;
254
+ if (kind === "serve") {
255
+ const s = settings.serve;
256
+ args = ["serve", this.projectDir, "--port", String(s.port), "--host", s.host];
257
+ if (s.auth === "token") {
258
+ token = randomBytes(24).toString("hex");
259
+ env.FW_SERVE_TOKEN = token;
260
+ } else {
261
+ delete env.FW_SERVE_TOKEN;
262
+ if (!["127.0.0.1", "localhost", "::1", "[::1]"].includes(s.host)) args.push("--insecure");
263
+ }
264
+ if (!s.agents) args.push("--no-agents");
265
+ if (s.trace) args.push("--trace");
266
+ if (s.dev) args.push("--dev");
267
+ if (s.swagger) args.push("--swagger");
268
+ } else {
269
+ args = ["watch", this.projectDir];
270
+ }
271
+ const proc = (this.opts.spawn ?? spawnFwWith)(args, this.projectDir, env);
272
+ const child = { kind, proc, state: "starting", startedAt: (/* @__PURE__ */ new Date()).toISOString(), token, lines: [] };
273
+ this.children.set(kind, child);
274
+ if (kind === "watch") child.state = "running";
275
+ const onData = (stream) => (chunk) => {
276
+ for (const raw of chunk.toString().split(/\r?\n/)) {
277
+ if (!raw.trim()) continue;
278
+ const line = { t: Date.now(), stream, text: raw };
279
+ child.lines.push(line);
280
+ if (child.lines.length > MAX_LINES) child.lines.splice(0, child.lines.length - MAX_LINES);
281
+ const listening = /Listening:\s*(https?:\/\/\S+)/.exec(raw);
282
+ if (listening && child.state === "starting") {
283
+ child.state = "running";
284
+ child.url = listening[1];
285
+ this.opts.onChange?.({ kind, state: "running", url: child.url });
286
+ }
287
+ for (const fn of this.listeners.get(kind) ?? []) fn(line);
288
+ this.opts.onChange?.({ kind, state: child.state, line });
289
+ }
290
+ };
291
+ proc.stdout?.on("data", onData("out"));
292
+ proc.stderr?.on("data", onData("err"));
293
+ proc.on("error", (err) => {
294
+ child.state = "exited";
295
+ child.error = err.message;
296
+ this.opts.onChange?.({ kind, state: "exited", error: err.message });
297
+ });
298
+ proc.on("close", (code) => {
299
+ if (child.state === "exited") return;
300
+ child.state = "exited";
301
+ child.exitCode = code;
302
+ const lastErr = [...child.lines].reverse().find((l) => l.stream === "err")?.text;
303
+ if (code && code !== 0 && !child.stopping) child.error = lastErr ?? `exited with code ${code}`;
304
+ this.opts.onChange?.({ kind, state: "exited", exitCode: code, error: child.error });
305
+ });
306
+ this.opts.onChange?.({ kind, state: child.state });
307
+ return this.view(kind);
308
+ }
309
+ /** Stop our child of this kind, or another process of this kind for the project by pid. */
310
+ async stop(kind, pid) {
311
+ const child = this.children.get(kind);
312
+ if (child && (pid === void 0 || child.proc.pid === pid) && child.state !== "exited") {
313
+ child.stopping = true;
314
+ await terminate(child.proc);
315
+ return this.view(kind);
316
+ }
317
+ if (pid !== void 0) {
318
+ const other = this.registryFor(kind).find((r) => r.pid === pid);
319
+ if (!other) throw new Error(`no ${kind} with pid ${pid} for this project`);
320
+ try {
321
+ process.kill(pid, "SIGTERM");
322
+ } catch (e) {
323
+ throw new Error(`could not stop pid ${pid}: ${e.message}`, { cause: e });
324
+ }
325
+ const end = Date.now() + STOP_GRACE_MS;
326
+ while (Date.now() < end && isAlive(pid)) await sleep(100);
327
+ if (isAlive(pid)) {
328
+ try {
329
+ process.kill(pid, "SIGKILL");
330
+ } catch {
331
+ }
332
+ }
333
+ }
334
+ return this.view(kind);
335
+ }
336
+ async restart(kind) {
337
+ await this.stop(kind);
338
+ return this.start(kind);
339
+ }
340
+ /** Stop every child; called when the console closes. */
341
+ async close() {
342
+ await Promise.all([...this.children.values()].filter((c) => c.state !== "exited").map((c) => {
343
+ c.stopping = true;
344
+ return terminate(c.proc);
345
+ }));
346
+ }
347
+ // -------------------------------------------------------------- reading
348
+ logs(kind) {
349
+ return [...this.children.get(kind)?.lines ?? []];
350
+ }
351
+ /** Every new line as it arrives. Returns the unsubscribe. */
352
+ onLog(kind, fn) {
353
+ const set = this.listeners.get(kind) ?? this.listeners.set(kind, /* @__PURE__ */ new Set()).get(kind);
354
+ set.add(fn);
355
+ return () => {
356
+ set.delete(fn);
357
+ };
358
+ }
359
+ view(kind) {
360
+ const child = this.children.get(kind);
361
+ const records = this.registryFor(kind);
362
+ const mine = child && child.state !== "exited" ? records.find((r) => r.pid === child.proc.pid) : void 0;
363
+ const others = records.filter((r) => r.pid !== child?.proc.pid).map((r) => ({ pid: r.pid, url: r.url, startedAt: r.startedAt, version: r.version, install: r.install }));
364
+ const activity = (r) => r ? { count: r.activityCount, last: r.activity, at: r.lastActivityAt, version: r.version, install: r.install } : void 0;
365
+ if (child) {
366
+ return {
367
+ kind,
368
+ state: child.state,
369
+ owned: true,
370
+ pid: child.proc.pid,
371
+ url: child.url ?? mine?.url,
372
+ startedAt: child.startedAt,
373
+ exitCode: child.exitCode,
374
+ error: child.error,
375
+ lines: child.lines.length,
376
+ token: child.token,
377
+ activity: activity(mine),
378
+ others
379
+ };
380
+ }
381
+ const first = records[0];
382
+ return first ? { kind, state: "running", owned: false, pid: first.pid, url: first.url, startedAt: first.startedAt, lines: 0, activity: activity(first), others: others.filter((o) => o.pid !== first.pid) } : { kind, state: "stopped", owned: false, lines: 0, others: [] };
383
+ }
384
+ list() {
385
+ return ["serve", "watch"].map((k) => this.view(k));
386
+ }
387
+ registryFor(kind) {
388
+ const here = real(this.projectDir);
389
+ return listServices(this.opts.registryDir).filter((s) => s.kind === kind && real(s.project ?? s.cwd) === here);
390
+ }
391
+ };
392
+ var real = (p) => {
393
+ try {
394
+ return fs2.realpathSync(p);
395
+ } catch {
396
+ return path2.resolve(p);
397
+ }
398
+ };
399
+ var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
400
+ function terminate(proc) {
401
+ return new Promise((resolve9) => {
402
+ if (proc.exitCode !== null || proc.signalCode !== null) {
403
+ resolve9();
404
+ return;
405
+ }
406
+ const timer = setTimeout(() => {
407
+ try {
408
+ proc.kill("SIGKILL");
409
+ } catch {
410
+ }
411
+ }, STOP_GRACE_MS);
412
+ proc.once("close", () => {
413
+ clearTimeout(timer);
414
+ resolve9();
415
+ });
416
+ try {
417
+ proc.kill("SIGTERM");
418
+ } catch {
419
+ clearTimeout(timer);
420
+ resolve9();
421
+ }
422
+ });
423
+ }
424
+
425
+ // src/console/scan.ts
426
+ import * as fs3 from "node:fs";
427
+ import * as path3 from "node:path";
428
+
429
+ // src/console/packs.ts
430
+ function packNamespace(name) {
431
+ return name.replace(/^@[^/]+\//, "").replace(/^flow-weaver-pack-/, "");
432
+ }
433
+ var posix = (p) => p.replace(/\\/g, "/").replace(/\/+$/, "");
434
+ function packForFile(file, packs) {
435
+ const f = posix(file);
436
+ let best = null;
437
+ for (const p of packs) {
438
+ const root = posix(p.path);
439
+ if ((f === root || f.startsWith(`${root}/`)) && (!best || root.length > posix(best.path).length)) best = p;
440
+ }
441
+ return best?.name ?? null;
442
+ }
443
+ function packageOfSpecifier(specifier) {
444
+ const parts = specifier.split("/");
445
+ if (!parts[0] || parts[0].startsWith(".")) return null;
446
+ return parts[0].startsWith("@") ? parts[1] ? `${parts[0]}/${parts[1]}` : null : parts[0];
447
+ }
448
+ function packForSpecifier(specifier, packs) {
449
+ const name = specifier ? packageOfSpecifier(specifier) : null;
450
+ return name && packs.some((p) => p.name === name) ? name : null;
451
+ }
452
+ var refsCache = /* @__PURE__ */ new Map();
453
+ async function installedRefs(projectDir) {
454
+ const hit = refsCache.get(projectDir);
455
+ if (hit && Date.now() - hit.at < 2e3) return hit.refs;
456
+ const refs = (await listInstalledPackages(projectDir)).map((p) => ({ name: p.name, path: p.path }));
457
+ refsCache.set(projectDir, { at: Date.now(), refs });
458
+ return refs;
459
+ }
460
+ var parse = (v) => {
461
+ const m = v.trim().match(/^v?(\d+)\.(\d+)\.(\d+)/);
462
+ return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
463
+ };
464
+ var cmp = (a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
465
+ function engineCompatible(range, version = VERSION) {
466
+ if (!range || range.trim() === "*") return true;
467
+ const have = parse(version);
468
+ const m = range.trim().match(/^(>=|\^|~)?\s*(v?\d+\.\d+\.\d+)$/);
469
+ const want = m ? parse(m[2]) : null;
470
+ if (!have || !want) return null;
471
+ const op = m[1] ?? "";
472
+ if (op === ">=") return cmp(have, want) >= 0;
473
+ if (op === "^") return want[0] === 0 ? have[0] === 0 && have[1] === want[1] && have[2] >= want[2] : have[0] === want[0] && cmp(have, want) >= 0;
474
+ if (op === "~") return have[0] === want[0] && have[1] === want[1] && have[2] >= want[2];
475
+ return cmp(have, want) === 0;
476
+ }
477
+ var CONTROL = /* @__PURE__ */ new Set(["execute", "onSuccess", "onFailure"]);
478
+ var ports = (map) => Object.entries(map ?? {}).filter(([name]) => !CONTROL.has(name)).map(([name, p]) => ({ name, type: String(p.dataType).toLowerCase(), optional: !!p.optional, description: p.description ?? "" }));
479
+ function describePack(pkg) {
480
+ const m = pkg.manifest;
481
+ const namespace = packNamespace(pkg.name);
482
+ return {
483
+ name: pkg.name,
484
+ namespace,
485
+ version: pkg.version,
486
+ path: pkg.path,
487
+ description: m.description ?? "",
488
+ engineVersion: m.engineVersion ?? null,
489
+ compatible: engineCompatible(m.engineVersion),
490
+ nodeTypes: (m.nodeTypes ?? []).map((n) => ({
491
+ name: n.name,
492
+ functionName: n.functionName,
493
+ description: n.description ?? "",
494
+ inputs: ports(n.inputs),
495
+ outputs: ports(n.outputs),
496
+ color: n.visuals?.color ?? null,
497
+ icon: n.visuals?.icon ?? null
498
+ })),
499
+ workflows: (m.workflows ?? []).map((w) => ({ name: w.name, description: w.description ?? "", params: ports(w.startPorts), returns: ports(w.exitPorts), nodes: w.nodeCount })),
500
+ exportTargets: (m.exportTargets ?? []).map((t) => ({ name: t.name, description: t.description ?? "" })),
501
+ tagHandlers: (m.tagHandlers ?? []).map((t) => ({ tags: t.tags, namespace: t.namespace, scope: t.scope })),
502
+ validationRuleSets: (m.validationRuleSets ?? []).map((r) => ({ name: r.name, namespace: r.namespace })),
503
+ docs: (m.docs ?? []).map((d) => ({ slug: d.slug, name: d.name, description: d.description ?? "" })),
504
+ // A pack with an entrypoint but no commands contributes none: the CLI skips it.
505
+ cliCommands: m.cliEntrypoint ? (m.cliCommands ?? []).map((c) => ({
506
+ name: c.name,
507
+ description: c.description,
508
+ usage: ["fw", namespace, c.name, ...c.arguments?.map((a) => a.syntax) ?? (c.usage ? [c.usage] : [])].join(" "),
509
+ flags: (c.options ?? []).map((o) => ({ flag: o.flags, description: o.description, default: o.default === void 0 ? "" : String(o.default) }))
510
+ })) : [],
511
+ mcpTools: m.mcpEntrypoint ? (m.mcpTools ?? []).map((t) => ({ name: t.name, description: t.description })) : []
512
+ };
513
+ }
514
+ async function describePacks(projectDir) {
515
+ const installed = await listInstalledPackages(projectDir);
516
+ return installed.map(describePack).sort((a, b) => a.namespace.localeCompare(b.namespace));
517
+ }
518
+
519
+ // src/console/scan.ts
520
+ var SKIP = /* @__PURE__ */ new Set(["node_modules", "dist", ".git", ".fw", "coverage"]);
521
+ var toPosix = (p) => p.split(path3.sep).join("/");
522
+ function walk(dir, out) {
523
+ let entries;
524
+ try {
525
+ entries = fs3.readdirSync(dir, { withFileTypes: true });
526
+ } catch {
527
+ return;
528
+ }
529
+ for (const entry of entries) {
530
+ if (SKIP.has(entry.name) || entry.name.startsWith(".")) continue;
531
+ const full = path3.join(dir, entry.name);
532
+ if (entry.isDirectory()) walk(full, out);
533
+ else if (entry.name.endsWith(".ts") && !entry.name.endsWith(".d.ts") && !entry.name.startsWith(".fw-diff-")) out.push(full);
534
+ }
535
+ }
536
+ function listOne(file, projectDir, mtimeMs) {
537
+ let text;
538
+ try {
539
+ text = fs3.readFileSync(file, "utf8");
540
+ } catch {
541
+ return null;
542
+ }
543
+ if (!text.includes("@flowWeaver workflow")) return null;
544
+ const names2 = getAvailableWorkflows(text).map((w) => w.functionName).filter(Boolean);
545
+ return names2.length ? { file, rel: toPosix(path3.relative(projectDir, file)), names: names2, mtimeMs } : null;
546
+ }
547
+ var checked = /* @__PURE__ */ new Map();
548
+ var listings = /* @__PURE__ */ new Map();
549
+ function invalidateListing(projectDir) {
550
+ if (projectDir) listings.delete(path3.resolve(projectDir));
551
+ else listings.clear();
552
+ }
553
+ function listCached(projectDir) {
554
+ const key = path3.resolve(projectDir);
555
+ const files = [];
556
+ walk(key, files);
557
+ const stats = /* @__PURE__ */ new Map();
558
+ for (const file of files) {
559
+ try {
560
+ stats.set(file, fs3.statSync(file).mtimeMs);
561
+ } catch {
562
+ }
563
+ }
564
+ const signature = [...stats].map(([f, m]) => `${f}:${m}`).join("|");
565
+ const hit = listings.get(key);
566
+ if (hit && hit.signature === signature) return [...hit.byFile.values()];
567
+ const byFile = /* @__PURE__ */ new Map();
568
+ for (const [file, mtimeMs] of stats) {
569
+ const previous = hit?.byFile.get(file);
570
+ if (previous && previous.mtimeMs === mtimeMs) {
571
+ byFile.set(file, previous);
572
+ continue;
573
+ }
574
+ const listed = listOne(file, key, mtimeMs);
575
+ if (listed) byFile.set(file, listed);
576
+ }
577
+ listings.set(key, { byFile, signature });
578
+ return [...byFile.values()];
579
+ }
580
+ async function check(entry, name, packs) {
581
+ const base = {
582
+ file: entry.file,
583
+ rel: entry.rel,
584
+ name,
585
+ steps: 0,
586
+ gates: 0,
587
+ errors: 0,
588
+ warnings: 0,
589
+ checked: true,
590
+ codes: [],
591
+ uses: []
592
+ };
593
+ try {
594
+ const parsed = await parseWorkflow(entry.file, { workflowName: name, projectDir: path3.dirname(entry.file) });
595
+ if (parsed.errors.length || !parsed.ast) return { ...base, errors: Math.max(1, parsed.errors.length) };
596
+ const ast = parsed.ast;
597
+ const v = validateWorkflow(ast);
598
+ const uses = /* @__PURE__ */ new Set();
599
+ let gates = 0;
600
+ for (const i of ast.instances) {
601
+ const nt = ast.nodeTypes.find((n) => n.name === i.nodeType) ?? ast.nodeTypes.find((n) => n.functionName === i.nodeType);
602
+ if (nt?.durableGate !== void 0) {
603
+ gates++;
604
+ uses.add(`gate:${nt.durableGate}`);
605
+ }
606
+ if (nt && !nt.functionText) uses.add(`builtin:${nt.functionName}`);
607
+ const pack = (nt?.sourceLocation?.file ? packForFile(nt.sourceLocation.file, packs) : null) ?? packForSpecifier(nt?.importSource, packs);
608
+ if (pack) uses.add(`pack:${pack}`);
609
+ if (nt?.durableEffect) uses.add("effect");
610
+ if (nt?.durablePure) uses.add("pure");
611
+ if (nt?.expression) uses.add("expression");
612
+ if (i.config?.pullExecution !== void 0) uses.add("pull");
613
+ if (i.config?.portConfigs?.some((c) => c.expression)) uses.add("expr");
614
+ }
615
+ if (Object.keys(ast.scopes ?? {}).length) uses.add("scope");
616
+ const codes = [...new Set([...v.errors, ...v.warnings].map((e) => e.code))];
617
+ return { ...base, steps: ast.instances.length, gates, errors: v.errors.length, warnings: v.warnings.length, codes, uses: [...uses] };
618
+ } catch {
619
+ return { ...base, errors: 1 };
620
+ }
621
+ }
622
+ var sortSummaries = (rows) => rows.sort((a, b) => a.rel.localeCompare(b.rel) || a.name.localeCompare(b.name));
623
+ function scanWorkflowNames(projectDir) {
624
+ const rows = [];
625
+ for (const entry of listCached(projectDir)) {
626
+ for (const name of entry.names) {
627
+ const hit = checked.get(`${entry.file}|${name}`);
628
+ rows.push(hit && hit.mtimeMs === entry.mtimeMs ? hit.summary : { file: entry.file, rel: entry.rel, name, steps: 0, gates: 0, errors: 0, warnings: 0, checked: false, codes: [], uses: [] });
629
+ }
630
+ }
631
+ return sortSummaries(rows);
632
+ }
633
+ async function checkWorkflows(projectDir, onChecked) {
634
+ const rows = [];
635
+ const packs = await installedRefs(projectDir);
636
+ for (const entry of listCached(projectDir)) {
637
+ for (const name of entry.names) {
638
+ const key = `${entry.file}|${name}`;
639
+ const hit = checked.get(key);
640
+ if (hit && hit.mtimeMs === entry.mtimeMs) {
641
+ rows.push(hit.summary);
642
+ continue;
643
+ }
644
+ const summary = await check(entry, name, packs);
645
+ checked.set(key, { mtimeMs: entry.mtimeMs, summary });
646
+ rows.push(summary);
647
+ onChecked?.(summary);
648
+ }
649
+ }
650
+ return sortSummaries(rows);
651
+ }
652
+
653
+ // src/console/runs.ts
654
+ import * as fs8 from "node:fs";
655
+ import * as path7 from "node:path";
656
+ import { randomUUID as randomUUID3 } from "node:crypto";
657
+
658
+ // src/console/debug.ts
659
+ import * as fs4 from "node:fs";
660
+ import * as os2 from "node:os";
661
+ import * as path4 from "node:path";
662
+ import { randomUUID } from "node:crypto";
663
+ function latestValues(variables) {
664
+ const best = /* @__PURE__ */ new Map();
665
+ for (const [key, value] of Object.entries(variables)) {
666
+ const at2 = key.lastIndexOf(":");
667
+ const mid = key.lastIndexOf(":", at2 - 1);
668
+ if (at2 < 0 || mid < 0) continue;
669
+ const name = `${key.slice(0, mid)}.${key.slice(mid + 1, at2)}`;
670
+ const index = Number(key.slice(at2 + 1));
671
+ const cur = best.get(name);
672
+ if (!cur || index > cur.index) best.set(name, { index, value });
673
+ }
674
+ return Object.fromEntries([...best].map(([k, v]) => [k, v.value]));
675
+ }
676
+ function latestKey(variables, node, port) {
677
+ const prefix = `${node}:${port}:`;
678
+ let found = null;
679
+ let top = -1;
680
+ for (const key of Object.keys(variables)) {
681
+ if (!key.startsWith(prefix)) continue;
682
+ const index = Number(key.slice(prefix.length));
683
+ if (index > top) {
684
+ top = index;
685
+ found = key;
686
+ }
687
+ }
688
+ return found;
689
+ }
690
+ var DebugSessions = class {
691
+ sessions = /* @__PURE__ */ new Map();
692
+ get(id) {
693
+ return this.sessions.get(id)?.view;
694
+ }
695
+ list() {
696
+ return [...this.sessions.values()].map((s) => s.view);
697
+ }
698
+ /**
699
+ * Start a session. Resolves at the first pause, or when the run ends
700
+ * without one. The session is listed from the moment this is called, so
701
+ * a caller that answers with the id before the pause can show it.
702
+ */
703
+ async start(options) {
704
+ const file = path4.resolve(options.file);
705
+ const id = options.id ?? randomUUID();
706
+ const controller = new DebugController({ debug: true, breakpoints: options.breakpoints });
707
+ const abort = new AbortController();
708
+ const effectsDir = fs4.mkdtempSync(path4.join(os2.tmpdir(), "fw-debug-"));
709
+ const view = {
710
+ id,
711
+ file,
712
+ name: options.name,
713
+ params: options.params ?? {},
714
+ status: "running",
715
+ startedAt: Date.now(),
716
+ updatedAt: Date.now(),
717
+ position: 0,
718
+ order: [],
719
+ breakpoints: controller.getBreakpoints(),
720
+ values: {}
721
+ };
722
+ const session = {
723
+ view,
724
+ controller,
725
+ abort,
726
+ done: Promise.resolve({ kind: "error", error: new Error("not started") }),
727
+ aborting: false,
728
+ effectsDir,
729
+ onChange: options.onChange
730
+ };
731
+ this.sessions.set(id, session);
732
+ const parsed = await parseWorkflow(file, { workflowName: options.name, projectDir: path4.dirname(file) });
733
+ if (parsed.errors.length) {
734
+ session.view = { ...view, status: "failed", error: parsed.errors.join("\n"), updatedAt: Date.now() };
735
+ fs4.rmSync(effectsDir, { recursive: true, force: true });
736
+ session.onChange?.(session.view);
737
+ return session.view;
738
+ }
739
+ const order = getTopologicalOrder(parsed.ast, { includeScopedChildren: true });
740
+ controller.setExecutionOrder(order);
741
+ session.view = { ...session.view, order };
742
+ let bundleDigest;
743
+ try {
744
+ bundleDigest = await computeBundleDigest(file, options.name);
745
+ } catch {
746
+ }
747
+ session.done = executeWorkflow({
748
+ runId: id,
749
+ filePath: file,
750
+ workflowName: options.name,
751
+ params: options.params,
752
+ includeTrace: true,
753
+ onEvent: options.onEvent,
754
+ debugController: controller,
755
+ abortSignal: abort.signal,
756
+ mocks: options.mocks,
757
+ bundleDigest,
758
+ effectAdapter: createFileEffectAdapter(effectsDir)
759
+ }).then((outcome) => ({ kind: "outcome", outcome })).catch((error) => ({ kind: "error", error }));
760
+ await this.settle(session);
761
+ return session.view;
762
+ }
763
+ /** Run the next node and pause again. */
764
+ step(id) {
765
+ return this.act(id, { type: "step" });
766
+ }
767
+ /** Run to the end, or to the next breakpoint. */
768
+ continue(id, toBreakpoint = false) {
769
+ return this.act(id, { type: toBreakpoint ? "continueToBreakpoint" : "continue" });
770
+ }
771
+ /** Stop the session, paused or not. */
772
+ async abort(id) {
773
+ const s = this.need(id);
774
+ s.aborting = true;
775
+ if (s.view.status === "paused") return this.act(id, { type: "abort" });
776
+ s.abort.abort();
777
+ await this.settle(s);
778
+ return s.view;
779
+ }
780
+ /**
781
+ * Change a value a node produced. Takes effect before the next node runs,
782
+ * which is how a branch is forced or a bad value patched without a rerun.
783
+ */
784
+ setVariable(id, node, port, value) {
785
+ const s = this.need(id);
786
+ if (s.view.status !== "paused" || !s.last) throw new Error("the session is not paused");
787
+ const key = latestKey(s.last.variables, node, port);
788
+ if (!key) throw new Error(`${node}.${port} has no value yet. It can be set once ${node} has run`);
789
+ s.controller.setVariable(key, value);
790
+ s.last.variables[key] = value;
791
+ s.view = { ...s.view, values: { ...s.view.values, [`${node}.${port}`]: value }, updatedAt: Date.now() };
792
+ s.onChange?.(s.view);
793
+ return s.view;
794
+ }
795
+ breakpoint(id, action, node) {
796
+ const s = this.need(id);
797
+ if (action === "add") s.controller.addBreakpoint(node);
798
+ else s.controller.removeBreakpoint(node);
799
+ s.view = { ...s.view, breakpoints: s.controller.getBreakpoints(), updatedAt: Date.now() };
800
+ s.onChange?.(s.view);
801
+ return s.view;
802
+ }
803
+ need(id) {
804
+ const s = this.sessions.get(id);
805
+ if (!s) throw new Error(`no debug session ${id}`);
806
+ return s;
807
+ }
808
+ async act(id, action) {
809
+ const s = this.need(id);
810
+ if (s.view.status !== "paused") throw new Error(`the session is ${s.view.status}, not paused`);
811
+ s.view = { ...s.view, status: "running", node: void 0, phase: void 0, updatedAt: Date.now() };
812
+ s.onChange?.(s.view);
813
+ s.controller.resume(action);
814
+ await this.settle(s);
815
+ return s.view;
816
+ }
817
+ /** Wait for the next pause or the end, and record which it was. */
818
+ async settle(s) {
819
+ const paused = s.controller.onPause().then((state) => ({ kind: "paused", state }));
820
+ const next = await Promise.race([s.done, paused]);
821
+ const now = Date.now();
822
+ if (next.kind === "paused") {
823
+ s.last = next.state;
824
+ s.view = {
825
+ ...s.view,
826
+ status: "paused",
827
+ node: next.state.currentNodeId,
828
+ phase: next.state.phase,
829
+ position: next.state.position,
830
+ breakpoints: next.state.breakpoints,
831
+ values: latestValues(next.state.variables),
832
+ updatedAt: now
833
+ };
834
+ } else if (next.kind === "outcome" && next.outcome.kind === "completed") {
835
+ s.view = { ...s.view, status: "completed", node: void 0, phase: void 0, position: s.view.order.length, result: next.outcome.result, updatedAt: now };
836
+ } else if (next.kind === "outcome" && next.outcome.kind === "yielded") {
837
+ const gate = next.outcome.gate.address.nodeId;
838
+ s.view = {
839
+ ...s.view,
840
+ status: "yielded",
841
+ node: gate,
842
+ phase: void 0,
843
+ updatedAt: now,
844
+ error: `Reached the gate at ${gate}. The debugger cannot hold a gate. Run the workflow without it to answer one.`
845
+ };
846
+ } else {
847
+ const error = next.kind === "error" ? next.error : void 0;
848
+ const message = getErrorMessage(error);
849
+ const aborted = s.aborting || s.abort.signal.aborted || /Debug session aborted/.test(message);
850
+ s.view = { ...s.view, status: aborted ? "aborted" : "failed", node: void 0, phase: void 0, error: aborted ? void 0 : message, updatedAt: now };
851
+ }
852
+ if (s.view.status !== "paused" && s.view.status !== "running") fs4.rmSync(s.effectsDir, { recursive: true, force: true });
853
+ s.onChange?.(s.view);
854
+ }
855
+ };
856
+
857
+ // src/console/workflow-view.ts
858
+ import * as fs6 from "node:fs";
859
+ import * as path6 from "node:path";
860
+ import { randomUUID as randomUUID2 } from "node:crypto";
861
+
862
+ // src/console/git.ts
863
+ import { execFile } from "node:child_process";
864
+ import * as fs5 from "node:fs";
865
+ import * as path5 from "node:path";
866
+ function git(cwd, args) {
867
+ return new Promise((resolve9, reject) => {
868
+ execFile("git", args, { cwd, maxBuffer: 16 * 1024 * 1024, windowsHide: true }, (err, stdout) => {
869
+ if (err) reject(err instanceof Error ? err : new Error(String(err)));
870
+ else resolve9(String(stdout));
871
+ });
872
+ });
873
+ }
874
+ async function repoRoot(file) {
875
+ try {
876
+ return (await git(path5.dirname(file), ["rev-parse", "--show-toplevel"])).trim() || void 0;
877
+ } catch {
878
+ return void 0;
879
+ }
880
+ }
881
+ function gitPath(root, file) {
882
+ const real2 = (p) => {
883
+ try {
884
+ return fs5.realpathSync(p);
885
+ } catch {
886
+ return p;
887
+ }
888
+ };
889
+ return path5.relative(real2(root), real2(file)).split(path5.sep).join("/");
890
+ }
891
+ async function fileHistory(file, limit = 60) {
892
+ const root = await repoRoot(file);
893
+ if (!root) return { repo: false, dirty: false, commits: [] };
894
+ const rel = gitPath(root, file);
895
+ const [head, status, log] = await Promise.all([
896
+ git(root, ["rev-parse", "--short", "HEAD"]).then((s) => s.trim()).catch(() => void 0),
897
+ git(root, ["status", "--porcelain", "--", rel]).catch(() => ""),
898
+ git(root, ["log", "--follow", `-n${limit}`, "--format=%H%x1f%h%x1f%an%x1f%at%x1f%s", "--", rel]).catch(() => "")
899
+ ]);
900
+ const commits = log.split("\n").filter(Boolean).map((line) => {
901
+ const [sha, short, author, at2, subject] = line.split("");
902
+ return { sha, short, author, at: Number(at2) * 1e3, subject };
903
+ });
904
+ return { repo: true, head, dirty: status.trim().length > 0, commits };
905
+ }
906
+ async function fileAt(file, ref) {
907
+ const root = await repoRoot(file);
908
+ if (!root) return void 0;
909
+ try {
910
+ return await git(root, ["show", `${ref}:${gitPath(root, file)}`]);
911
+ } catch {
912
+ return void 0;
913
+ }
914
+ }
915
+ async function stamp(file) {
916
+ const root = await repoRoot(file);
917
+ if (!root) return void 0;
918
+ const rel = gitPath(root, file);
919
+ const [commit, status] = await Promise.all([
920
+ git(root, ["rev-parse", "--short", "HEAD"]).then((s) => s.trim()).catch(() => void 0),
921
+ git(root, ["status", "--porcelain", "--", rel]).catch(() => "")
922
+ ]);
923
+ return commit ? { commit, dirty: status.trim().length > 0 } : void 0;
924
+ }
925
+
926
+ // src/console/source.ts
927
+ function findDeclaration(text, fnName) {
928
+ const re = new RegExp(`\\bexport\\s+(?:async\\s+)?function\\s+${fnName}\\s*[(<]`);
929
+ return text.search(re);
930
+ }
931
+ function endOfSignature(text, from) {
932
+ let depth = 0;
933
+ let closedParams = false;
934
+ let inReturnType = false;
935
+ const i0 = text.indexOf("(", from);
936
+ if (i0 < 0) return -1;
937
+ let i = i0;
938
+ for (; i < text.length; i++) {
939
+ const c = text[i];
940
+ if (c === "/" && text[i + 1] === "/") {
941
+ const nl = text.indexOf("\n", i);
942
+ if (nl < 0) return -1;
943
+ i = nl;
944
+ continue;
945
+ }
946
+ if (c === "/" && text[i + 1] === "*") {
947
+ const end = text.indexOf("*/", i + 2);
948
+ if (end < 0) return -1;
949
+ i = end + 1;
950
+ continue;
951
+ }
952
+ if (c === "'" || c === '"' || c === "`") {
953
+ const quote = c;
954
+ i++;
955
+ while (i < text.length && text[i] !== quote) {
956
+ if (text[i] === "\\") i++;
957
+ i++;
958
+ }
959
+ continue;
960
+ }
961
+ if (c === ":" && depth === 0 && closedParams) {
962
+ inReturnType = true;
963
+ continue;
964
+ }
965
+ if (c === "(" || c === "[" || c === "{" || c === "<") {
966
+ if (c === "{" && depth === 0 && closedParams && !inReturnType) return i + 1;
967
+ depth++;
968
+ continue;
969
+ }
970
+ if (c === ")" || c === "]" || c === "}" || c === ">") {
971
+ if (c === ">" && text[i - 1] === "=") continue;
972
+ depth--;
973
+ if (c === ")" && depth === 0) closedParams = true;
974
+ if (depth === 0 && inReturnType && c !== ")") inReturnType = false;
975
+ continue;
976
+ }
977
+ }
978
+ return -1;
979
+ }
980
+ function workflowSource(text, fnName) {
981
+ const declaration = findDeclaration(text, fnName);
982
+ if (declaration < 0) return { source: "", line: 1 };
983
+ const bodyStart = endOfSignature(text, declaration);
984
+ const end = bodyStart < 0 ? text.length : bodyStart;
985
+ const commentStart = text.lastIndexOf("/**", declaration);
986
+ const between = commentStart >= 0 ? text.slice(text.indexOf("*/", commentStart) + 2, declaration) : "";
987
+ const attached = commentStart >= 0 && /^\s*$/.test(between);
988
+ const from = attached ? commentStart : declaration;
989
+ return {
990
+ source: text.slice(from, end).trimEnd(),
991
+ line: text.slice(0, from).split("\n").length
992
+ };
993
+ }
994
+
995
+ // src/console/terminals.ts
996
+ var CONTROL2 = /* @__PURE__ */ new Set(["execute", "onSuccess", "onFailure"]);
997
+ function terminalWiring(ast) {
998
+ const start = {};
999
+ const exit = {};
1000
+ for (const c of ast.connections) {
1001
+ if (c.from.node === "Start" && !CONTROL2.has(c.from.port)) {
1002
+ (start[c.from.port] ??= []).push({ node: c.to.node, port: c.to.port });
1003
+ }
1004
+ if (c.to.node === "Exit" && !CONTROL2.has(c.to.port) && !exit[c.to.port]) {
1005
+ exit[c.to.port] = { node: c.from.node, port: c.from.port };
1006
+ }
1007
+ }
1008
+ return { start, exit };
1009
+ }
1010
+
1011
+ // src/console/workflow-view.ts
1012
+ var CONTROL3 = /* @__PURE__ */ new Set(["execute", "onSuccess", "onFailure"]);
1013
+ function nodeTypeOf(ast, inst) {
1014
+ return ast.nodeTypes.find((n) => n.name === inst.nodeType) ?? ast.nodeTypes.find((n) => n.functionName === inst.nodeType);
1015
+ }
1016
+ function ports2(map) {
1017
+ return Object.entries(map ?? {}).filter(([k, p]) => !CONTROL3.has(k) && !p.isControlFlow).map(([k, p]) => ({ name: k, tsType: p.tsType ?? String(p.dataType).toLowerCase(), optional: !!p.optional, description: p.description ?? "" }));
1018
+ }
1019
+ async function parseOne(file, name) {
1020
+ const p = await parseWorkflow(file, { workflowName: name, projectDir: path6.dirname(file) });
1021
+ return { ast: p.errors.length ? void 0 : p.ast, errors: p.errors };
1022
+ }
1023
+ function describeIssue(e) {
1024
+ return {
1025
+ severity: e.type,
1026
+ code: e.code,
1027
+ message: e.message,
1028
+ node: e.node ?? null,
1029
+ line: e.location?.line ?? null,
1030
+ hint: ERROR_HINTS[e.code] ? ERROR_HINTS[e.code].replace(/<nodeId>/g, e.node ?? "<nodeId>") : null
1031
+ };
1032
+ }
1033
+ async function astAt(file, name, ref) {
1034
+ if (ref === "worktree") {
1035
+ const p = await parseOne(file, name);
1036
+ return p.ast ? { ast: p.ast } : { error: p.errors.join("\n") || "the file does not parse" };
1037
+ }
1038
+ const text = await fileAt(file, ref);
1039
+ if (text === void 0) return { error: `${path6.basename(file)} does not exist at ${ref}` };
1040
+ const tmp = path6.join(path6.dirname(file), `.fw-diff-${randomUUID2().slice(0, 8)}-${path6.basename(file)}`);
1041
+ fs6.writeFileSync(tmp, text, "utf8");
1042
+ try {
1043
+ const p = await parseWorkflow(tmp, { workflowName: name, projectDir: path6.dirname(file) });
1044
+ if (p.errors.length) return { error: `${path6.basename(file)} at ${ref} does not parse: ${p.errors[0]}` };
1045
+ return { ast: { ...p.ast, sourceFile: file } };
1046
+ } finally {
1047
+ fs6.rmSync(tmp, { force: true });
1048
+ }
1049
+ }
1050
+ async function describeWorkflow(projectDir, file, name) {
1051
+ const text = fs6.readFileSync(file, "utf8");
1052
+ const rel = toPosix(path6.relative(projectDir, file));
1053
+ const { ast, errors } = await parseOne(file, name);
1054
+ if (!ast) return { file, rel, name, parseErrors: errors };
1055
+ const v = validateWorkflow(ast);
1056
+ const packs = await installedRefs(projectDir);
1057
+ const nodes = {};
1058
+ for (const inst of ast.instances) {
1059
+ const nt = nodeTypeOf(ast, inst);
1060
+ const nodeFile = nt?.sourceLocation?.file ?? file;
1061
+ nodes[inst.id] = {
1062
+ id: inst.id,
1063
+ type: inst.nodeType,
1064
+ label: stepLabel(inst, nt),
1065
+ description: nt?.description ?? "",
1066
+ builtin: !nt?.functionText,
1067
+ color: inst.config?.color ?? nt?.visuals?.color ?? null,
1068
+ icon: inst.config?.icon ?? nt?.visuals?.icon ?? null,
1069
+ pull: inst.config?.pullExecution !== void 0,
1070
+ source: nt?.functionText ?? "",
1071
+ file: nodeFile,
1072
+ line: nt?.sourceLocation?.line ?? null,
1073
+ gate: nt?.durableGate ?? null,
1074
+ // Where the node type came from, and what a pack's tags said about
1075
+ // this step: the parser resolves both and then shows neither.
1076
+ pack: packForFile(nodeFile, packs) ?? packForSpecifier(nt?.importSource, packs),
1077
+ deploy: Object.keys({ ...nt?.deploy, ...inst.deploy }).length ? { ...nt?.deploy, ...inst.deploy } : null,
1078
+ // What a step can and cannot do is the thing an author gets wrong:
1079
+ // an expression node has no onFailure, so a throw aborts the run,
1080
+ // and only a pure node may re-run when a gated workflow resumes.
1081
+ expression: !!nt?.expression,
1082
+ durablePure: !!nt?.durablePure,
1083
+ effect: !!nt?.durableEffect,
1084
+ async: !!nt?.isAsync,
1085
+ inputs: ports2(nt?.inputs),
1086
+ outputs: ports2(nt?.outputs),
1087
+ outputSchema: nt?.durableGate !== void 0 ? gateOutputSchemas(ast, inst.id, file) : null,
1088
+ expr: (inst.config?.portConfigs ?? []).filter((c) => c.expression).map((c) => ({ port: c.portName, expr: c.expression }))
1089
+ };
1090
+ }
1091
+ const model = buildProcessModel(ast);
1092
+ const stamp2 = (steps) => steps.forEach((s) => {
1093
+ s.label = nodes[s.id]?.label ?? s.label;
1094
+ s.pull = !!nodes[s.id]?.pull;
1095
+ stamp2(s.children);
1096
+ });
1097
+ stamp2(model.steps);
1098
+ const ws = workflowSource(text, ast.functionName);
1099
+ return {
1100
+ file,
1101
+ rel,
1102
+ name: ast.functionName,
1103
+ description: ast.description ?? "",
1104
+ compiled: hasInPlaceMarkers(text),
1105
+ params: ports2(ast.startPorts),
1106
+ paramsSchema: workflowParamsSchema(file, ast.functionName),
1107
+ returns: ports2(ast.exitPorts),
1108
+ // Port level, for the Start and Exit cards: which input each parameter
1109
+ // feeds, and which output becomes each return value.
1110
+ wiring: terminalWiring(ast),
1111
+ model,
1112
+ nodes,
1113
+ issues: [...v.errors, ...v.warnings].map(describeIssue),
1114
+ source: ws.source,
1115
+ sourceLine: ws.line,
1116
+ deploy: ast.options?.deploy && Object.keys(ast.options.deploy).length ? ast.options.deploy : null,
1117
+ // The routes the workflow declares with @http, for the Serve pane.
1118
+ http: ast.options?.http ?? [],
1119
+ reference: referenceOf(ast)
1120
+ };
1121
+ }
1122
+ var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE"]);
1123
+ function routeFrom(raw) {
1124
+ if (typeof raw !== "object" || raw === null) return "a route is an object";
1125
+ const r = raw;
1126
+ const method = String(r.method ?? "").toUpperCase();
1127
+ if (!HTTP_METHODS.has(method)) return `method must be one of ${[...HTTP_METHODS].join(", ")}`;
1128
+ const p = String(r.path ?? "").trim();
1129
+ if (!p.startsWith("/") || /\s/.test(p)) return "a path starts with / and has no spaces";
1130
+ if (RESERVED_PATHS.some((x) => p === x || p.startsWith(`${x}/`))) return `${p} is under a reserved path (${RESERVED_PATHS.join(", ")})`;
1131
+ const route = { method, path: p };
1132
+ if (r.mode === "async") route.mode = "async";
1133
+ if (r.auth === "none") route.auth = "none";
1134
+ if (r.callback === true) route.callback = true;
1135
+ return route;
1136
+ }
1137
+ async function setHttpRoutes(file, name, routes) {
1138
+ const before = fs6.readFileSync(file, "utf8");
1139
+ const ws = workflowSource(before, name);
1140
+ if (!ws.source) return { ok: false, error: `${name} was not found in ${path6.basename(file)}` };
1141
+ const start = before.indexOf(ws.source);
1142
+ const block = ws.source;
1143
+ const marker = block.match(/^([ \t]*\*[ \t]*)@flowWeaver[ \t]+workflow[^\n]*\n/m);
1144
+ if (!marker || marker.index === void 0) return { ok: false, error: `${name} has no @flowWeaver workflow line` };
1145
+ const kept = block.replace(/^[ \t]*\*[ \t]*@http\b[^\n]*\n/gm, "");
1146
+ const at2 = kept.match(/^([ \t]*\*[ \t]*)@flowWeaver[ \t]+workflow[^\n]*\n/m);
1147
+ const insertAt = at2.index + at2[0].length;
1148
+ const lines = routes.map((r) => `${at2[1]}@http ${httpRouteText(r)}
1149
+ `).join("");
1150
+ const rewritten = kept.slice(0, insertAt) + lines + kept.slice(insertAt);
1151
+ const after = before.slice(0, start) + rewritten + before.slice(start + block.length);
1152
+ fs6.writeFileSync(file, after, "utf8");
1153
+ const p = await parseOne(file, name);
1154
+ if (!p.ast) {
1155
+ fs6.writeFileSync(file, before, "utf8");
1156
+ return { ok: false, error: `the file no longer parsed, so it was put back: ${p.errors[0] ?? "unknown error"}` };
1157
+ }
1158
+ return { ok: true };
1159
+ }
1160
+ function referenceOf(ast) {
1161
+ const { deploy: _deploy, ...options } = ast.options ?? {};
1162
+ const macros = ast.macros ?? [];
1163
+ const paths = macros.filter((m) => m.type === "path").map((m) => m.steps);
1164
+ const connects = ast.connections.filter((c) => !c.derived && !(macros.length && isConnectionCoveredByMacroStatic(c, macros))).map((c) => ({ from: { node: c.from.node, port: c.from.port }, to: { node: c.to.node, port: c.to.port } }));
1165
+ const exprs = ast.instances.flatMap((i) => (i.config?.portConfigs ?? []).filter((p) => p.expression).map((p) => ({ node: i.id, port: p.portName, expr: p.expression })));
1166
+ const importsFrom = ast.nodeTypes.filter((nt) => nt.importSource).map((nt) => ({ type: nt.name, from: nt.importSource }));
1167
+ return { options, paths, connects, exprs, importsFrom };
1168
+ }
1169
+ function crumbsFor(at2) {
1170
+ const { root } = path6.parse(at2);
1171
+ const rest = at2.slice(root.length).split(path6.sep).filter(Boolean);
1172
+ const crumbs = [];
1173
+ let dir = root;
1174
+ for (const name of rest) {
1175
+ dir = path6.join(dir, name);
1176
+ crumbs.push({ name, dir });
1177
+ }
1178
+ return crumbs;
1179
+ }
1180
+ function errorCodeSection(code) {
1181
+ const section = readTopicStructured("error-codes")?.sections.find((s) => s.heading.includes(code));
1182
+ return section ? { heading: section.heading, content: section.content, codeBlocks: section.codeBlocks } : null;
1183
+ }
1184
+
1185
+ // src/console/respond.ts
1186
+ import * as fs7 from "node:fs";
1187
+ function json(res, status, body) {
1188
+ res.writeHead(status, { "Content-Type": "application/json" });
1189
+ res.end(JSON.stringify(body));
1190
+ }
1191
+ function sse(res) {
1192
+ res.writeHead(200, { "Content-Type": "text/event-stream", "Cache-Control": "no-cache", Connection: "keep-alive" });
1193
+ res.write(": ok\n\n");
1194
+ }
1195
+ function send(res, msg) {
1196
+ res.write(`data: ${JSON.stringify(msg)}
1197
+
1198
+ `);
1199
+ }
1200
+ function sendFile(res, file, type) {
1201
+ res.writeHead(200, { "Content-Type": type, "Cache-Control": "no-cache" });
1202
+ res.end(fs7.readFileSync(file));
1203
+ }
1204
+ var BadRequest = class extends Error {
1205
+ };
1206
+ var MAX_BODY = 1024 * 1024;
1207
+ async function readBody(req) {
1208
+ let s = "";
1209
+ for await (const c of req) {
1210
+ s += c;
1211
+ if (s.length > MAX_BODY) throw new BadRequest(`the body may not exceed ${MAX_BODY} bytes`);
1212
+ }
1213
+ if (!s.trim()) return {};
1214
+ let parsed;
1215
+ try {
1216
+ parsed = JSON.parse(s);
1217
+ } catch {
1218
+ throw new BadRequest("the body is not valid JSON");
1219
+ }
1220
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new BadRequest("the body must be a JSON object");
1221
+ return parsed;
1222
+ }
1223
+
1224
+ // src/console/runs.ts
1225
+ function mocksFrom(b) {
1226
+ const m = b.mocks;
1227
+ if (!m || typeof m !== "object" || Array.isArray(m)) return void 0;
1228
+ const src = m;
1229
+ const out = {};
1230
+ for (const k of ["events", "agents", "invocations", "gates"]) {
1231
+ if (src[k] && typeof src[k] === "object" && !Array.isArray(src[k]) && Object.keys(src[k]).length) out[k] = src[k];
1232
+ }
1233
+ if (src.fast === true) out.fast = true;
1234
+ return Object.keys(out).length ? out : void 0;
1235
+ }
1236
+ var at = (iso) => Date.parse(iso);
1237
+ var DEBUG_STATUS = {
1238
+ running: "running",
1239
+ paused: "running",
1240
+ completed: "completed",
1241
+ failed: "failed",
1242
+ aborted: "cancelled",
1243
+ yielded: "cancelled"
1244
+ };
1245
+ function debugSnapshot(d, source) {
1246
+ return {
1247
+ id: d.id,
1248
+ file: d.file,
1249
+ name: d.name,
1250
+ params: d.params,
1251
+ source,
1252
+ status: DEBUG_STATUS[d.status],
1253
+ startedAt: d.startedAt,
1254
+ updatedAt: d.updatedAt,
1255
+ result: d.result,
1256
+ error: d.error,
1257
+ traced: true,
1258
+ debug: { status: d.status, node: d.node, phase: d.phase, position: d.position, order: d.order, breakpoints: d.breakpoints }
1259
+ };
1260
+ }
1261
+ function createRunDriver({ coordinator, broadcast, projectDir, profiles }) {
1262
+ const live = /* @__PURE__ */ new Map();
1263
+ const debug = new DebugSessions();
1264
+ const debugEvents = /* @__PURE__ */ new Map();
1265
+ const debugSource = /* @__PURE__ */ new Map();
1266
+ const agentEvents = /* @__PURE__ */ new Map();
1267
+ const subs = /* @__PURE__ */ new Map();
1268
+ const push = (id, msg) => {
1269
+ for (const res of subs.get(id) ?? []) send(res, msg);
1270
+ };
1271
+ let listed;
1272
+ const storeList = async () => {
1273
+ if (!listed || Date.now() - listed.at > 500) listed = { at: Date.now(), rows: await coordinator.list() };
1274
+ return listed.rows;
1275
+ };
1276
+ let lastCounts = /* @__PURE__ */ new Map();
1277
+ const waitingCounts = async () => {
1278
+ const counts = /* @__PURE__ */ new Map();
1279
+ for (const s of await storeList()) if (s.status === "waiting") counts.set(`${s.filePath}|${s.workflowName}`, (counts.get(`${s.filePath}|${s.workflowName}`) ?? 0) + 1);
1280
+ lastCounts = counts;
1281
+ return counts;
1282
+ };
1283
+ const withWaiting = (w, counts = lastCounts) => ({
1284
+ ...w,
1285
+ waiting: counts.get(`${w.file}|${w.name}`) ?? 0
1286
+ });
1287
+ const asts = /* @__PURE__ */ new Map();
1288
+ async function astFor(file, name) {
1289
+ const key = `${file}|${name}`;
1290
+ let mtimeMs;
1291
+ try {
1292
+ mtimeMs = fs8.statSync(file).mtimeMs;
1293
+ } catch {
1294
+ return void 0;
1295
+ }
1296
+ const hit = asts.get(key);
1297
+ if (hit && hit.mtimeMs === mtimeMs) return hit.ast;
1298
+ const { ast } = await parseOne(file, name);
1299
+ asts.set(key, { mtimeMs, ast });
1300
+ return ast;
1301
+ }
1302
+ async function gateView(rec) {
1303
+ const g = rec.gate;
1304
+ if (!g) return void 0;
1305
+ const ast = await astFor(rec.filePath, rec.workflowName);
1306
+ const inst = ast?.instances.find((i) => i.id === g.node);
1307
+ const nt = ast && inst ? nodeTypeOf(ast, inst) : void 0;
1308
+ return {
1309
+ id: g.id,
1310
+ kind: g.kind,
1311
+ node: g.node,
1312
+ inputs: g.inputs,
1313
+ absent: g.absent,
1314
+ outputs: g.outputs,
1315
+ hasSuccessPort: g.hasSuccessPort,
1316
+ hasFailurePort: g.hasFailurePort,
1317
+ outputTypes: Object.fromEntries(g.outputs.map((o) => [o, nt?.outputs?.[o]?.tsType ?? "unknown"])),
1318
+ outputSchema: ast ? gateOutputSchemas(ast, g.node, rec.filePath) : null,
1319
+ // The words for whoever answers: the gate function's own description,
1320
+ // and each output's label from its @output line. Types alone say what
1321
+ // shape an answer has, not what it means.
1322
+ description: nt?.description ?? "",
1323
+ outputLabels: Object.fromEntries(g.outputs.map((o) => [o, nt?.outputs?.[o]?.label ?? ""])),
1324
+ inputLabels: Object.fromEntries(Object.keys(g.inputs).map((i) => [i, nt?.inputs?.[i]?.label ?? ""]))
1325
+ };
1326
+ }
1327
+ async function snapshot(id) {
1328
+ const d = debug.get(id);
1329
+ if (d) return debugSnapshot(d, debugSource.get(id));
1330
+ const l = live.get(id);
1331
+ const rec = await coordinator.record(id);
1332
+ if (l) return { id, file: l.file, name: l.name, params: l.params, mocks: l.mocks, source: l.source, status: l.status, startedAt: l.startedAt, updatedAt: Date.now(), error: l.error, traced: true, agent: rec?.agent, agents: rec?.agents, origin: rec?.origin ?? "console" };
1333
+ if (!rec) return void 0;
1334
+ return {
1335
+ id,
1336
+ file: rec.filePath,
1337
+ name: rec.workflowName,
1338
+ params: rec.params,
1339
+ mocks: rec.mocks,
1340
+ source: rec.source,
1341
+ status: rec.status,
1342
+ startedAt: at(rec.createdAt),
1343
+ updatedAt: at(rec.updatedAt),
1344
+ gate: rec.gate ? { node: rec.gate.node, kind: rec.gate.kind } : void 0,
1345
+ due: rec.due ? { at: at(rec.due.at), action: rec.due.action } : void 0,
1346
+ result: rec.result,
1347
+ error: rec.error,
1348
+ failedAt: rec.failedNode,
1349
+ traced: !!rec.traced,
1350
+ agent: rec.agent,
1351
+ agents: rec.agents,
1352
+ origin: rec.origin
1353
+ };
1354
+ }
1355
+ async function fullSnapshot(id) {
1356
+ const snap = await snapshot(id);
1357
+ const rec = live.has(id) ? void 0 : await coordinator.record(id);
1358
+ return snap && rec?.gate ? { ...snap, gate: await gateView(rec) } : snap;
1359
+ }
1360
+ async function pushRun(id) {
1361
+ if (!subs.get(id)?.size) return;
1362
+ const run = await fullSnapshot(id);
1363
+ if (run) push(id, { type: "run", run });
1364
+ }
1365
+ async function changed(id) {
1366
+ listed = void 0;
1367
+ if (id) await pushRun(id);
1368
+ broadcast({ type: "runs" });
1369
+ }
1370
+ async function drive(l, segment) {
1371
+ live.set(l.id, l);
1372
+ listed = void 0;
1373
+ broadcast({ type: "runs" });
1374
+ void pushRun(l.id);
1375
+ const onEvent = (ev) => {
1376
+ const entry = { t: ev.timestamp, e: ev.data ?? ev };
1377
+ l.events.push(entry);
1378
+ push(l.id, { type: "event", ...entry });
1379
+ };
1380
+ try {
1381
+ await segment(onEvent);
1382
+ live.delete(l.id);
1383
+ } catch (err) {
1384
+ if (await coordinator.record(l.id)) live.delete(l.id);
1385
+ else {
1386
+ l.status = "failed";
1387
+ l.error = getErrorMessage(err);
1388
+ }
1389
+ }
1390
+ await changed(l.id);
1391
+ void afterSegment(l.id);
1392
+ }
1393
+ async function afterSegment(id, asked = false) {
1394
+ const rec = await coordinator.record(id);
1395
+ if (!rec || rec.status !== "waiting" || rec.gate?.kind !== "agent" || rec.agents === "manual" && !asked) return;
1396
+ const note = () => changed(id);
1397
+ try {
1398
+ if (asked && rec.agents === "manual") await coordinator.setAgent(id, rec.agent);
1399
+ const step = await answerAgentGate(coordinator, id, {
1400
+ projectDir: projectDir(),
1401
+ profiles: profiles(),
1402
+ outputSchema: async (r) => {
1403
+ const g = await gateView(r);
1404
+ return g ? { schema: g.outputSchema ?? null, types: g.outputTypes } : void 0;
1405
+ },
1406
+ onEvent: (e) => {
1407
+ const entry = { t: Date.now(), e };
1408
+ (agentEvents.get(id) ?? agentEvents.set(id, []).get(id)).push(entry);
1409
+ push(id, { ...e, t: entry.t });
1410
+ if (e.phase === "start" || e.phase === "done") void note();
1411
+ }
1412
+ });
1413
+ await note();
1414
+ if (step.kind === "answer") await resume(id, { answer: step.answer });
1415
+ else if (step.kind === "reject") await resume(id, { reject: step.reason });
1416
+ } catch (err) {
1417
+ await noteAnswerMisfit(coordinator, id, err);
1418
+ await note();
1419
+ }
1420
+ }
1421
+ function startDebug(file, name, params, breakpoints, mocks, runTo, source) {
1422
+ const id = randomUUID3();
1423
+ const events = [];
1424
+ debugEvents.set(id, events);
1425
+ if (source) debugSource.set(id, source);
1426
+ void debug.start({
1427
+ id,
1428
+ file,
1429
+ name,
1430
+ params,
1431
+ breakpoints,
1432
+ mocks,
1433
+ onEvent: (ev) => {
1434
+ const entry = { t: ev.timestamp, e: ev.data ?? ev };
1435
+ events.push(entry);
1436
+ push(id, { type: "event", ...entry });
1437
+ },
1438
+ onChange: () => {
1439
+ void pushRun(id);
1440
+ broadcast({ type: "runs" });
1441
+ }
1442
+ }).then((view) => {
1443
+ if (runTo === "breakpoint" && view.status === "paused" && breakpoints.length) return debug.continue(id, true).then(() => void 0);
1444
+ }).catch(() => void 0);
1445
+ broadcast({ type: "runs" });
1446
+ return debugSnapshot(debug.get(id), debugSource.get(id));
1447
+ }
1448
+ async function start(file, name, params, mocks, source, agents) {
1449
+ const ast = await astFor(file, name);
1450
+ if (!ast) throw new Error((await parseOne(file, name)).errors.join("\n"));
1451
+ const id = randomUUID3();
1452
+ const l = { id, file, name, params, mocks, source, startedAt: Date.now(), status: "running", events: [], abort: new AbortController() };
1453
+ void drive(l, (onEvent) => coordinator.start({ filePath: file, workflowName: name, params, runId: id, mocks, source, agents, origin: "console" }, { onEvent, abortSignal: l.abort.signal }));
1454
+ return await snapshot(id);
1455
+ }
1456
+ async function resume(id, input) {
1457
+ if (live.has(id)) throw new Error("run is already resuming");
1458
+ const rec = await coordinator.record(id);
1459
+ if (rec?.gate && isAnswering(rec.agent, rec.gate.id)) throw new Error(`agent profile ${rec.agent.profile} is answering this gate. Wait for it, or cancel the run`);
1460
+ const resolve9 = "reject" in input ? { reject: input.reject ?? "" } : { answer: input.answer };
1461
+ await coordinator.checkResume({ runId: id, input: resolve9 });
1462
+ if (!rec) return;
1463
+ const l = { id, file: rec.filePath, name: rec.workflowName, params: rec.params, startedAt: at(rec.createdAt), status: "running", events: [], abort: new AbortController() };
1464
+ void drive(l, (onEvent) => coordinator.resume({ runId: id, input: resolve9 }, { onEvent, abortSignal: l.abort.signal }));
1465
+ }
1466
+ async function cancel(id) {
1467
+ if (debug.get(id)) {
1468
+ await debug.abort(id).catch(() => void 0);
1469
+ return;
1470
+ }
1471
+ const l = live.get(id);
1472
+ if (l?.status === "running") {
1473
+ l.abort.abort();
1474
+ return;
1475
+ }
1476
+ if ((await coordinator.record(id))?.status === "waiting") {
1477
+ await coordinator.cancel(id);
1478
+ await changed(id);
1479
+ }
1480
+ }
1481
+ async function list(file, name) {
1482
+ const inFlight = [
1483
+ ...debug.list().filter((d) => (!file || d.file === file) && (!name || d.name === name)).map((d) => debugSnapshot(d, debugSource.get(d.id))),
1484
+ ...await Promise.all([...live.values()].filter((l) => (!file || l.file === file) && (!name || l.name === name)).map(async (l) => await snapshot(l.id)))
1485
+ ];
1486
+ const stored = (file ? await coordinator.list({ filePath: file }) : await storeList()).filter((s) => (!name || s.workflowName === name) && !live.has(s.runId)).map((s) => ({
1487
+ id: s.runId,
1488
+ file: s.filePath,
1489
+ name: s.workflowName,
1490
+ status: s.status,
1491
+ params: s.params,
1492
+ mocks: s.mocks,
1493
+ source: s.source,
1494
+ startedAt: at(s.createdAt),
1495
+ updatedAt: at(s.updatedAt),
1496
+ gate: s.gate,
1497
+ failedAt: s.failedNode,
1498
+ origin: s.origin,
1499
+ due: s.due ? { at: at(s.due.at), action: s.due.action } : void 0
1500
+ }));
1501
+ return [...inFlight, ...stored].sort((a, b) => b.startedAt - a.startedAt).filter((r, i) => i < 20 || live.has(r.id) || debug.get(r.id));
1502
+ }
1503
+ async function remove(id) {
1504
+ if (live.has(id) || debug.get(id)) throw new Error("the run is in flight. Cancel it first");
1505
+ await coordinator.remove(id);
1506
+ await changed();
1507
+ }
1508
+ async function watch(id, req, res) {
1509
+ sse(res);
1510
+ send(res, { type: "run", run: await fullSnapshot(id) });
1511
+ const lines = [];
1512
+ for (const entry of [...await coordinator.trace(id), ...live.get(id)?.events ?? [], ...debugEvents.get(id) ?? []]) lines.push({ t: entry.t, line: JSON.stringify({ type: "event", ...entry }) });
1513
+ for (const entry of agentEvents.get(id) ?? []) lines.push({ t: entry.t, line: JSON.stringify({ ...entry.e, t: entry.t }) });
1514
+ lines.sort((a, b) => a.t - b.t);
1515
+ for (const l of lines) res.write(`data: ${l.line}
1516
+
1517
+ `);
1518
+ send(res, { type: "synced" });
1519
+ const set = subs.get(id) ?? subs.set(id, /* @__PURE__ */ new Set()).get(id);
1520
+ set.add(res);
1521
+ req.on("close", () => {
1522
+ set.delete(res);
1523
+ if (!set.size) subs.delete(id);
1524
+ });
1525
+ }
1526
+ async function withEvents(id) {
1527
+ return { ...await fullSnapshot(id), events: [...await coordinator.trace(id), ...live.get(id)?.events ?? []] };
1528
+ }
1529
+ async function askAgent(id) {
1530
+ const rec = await coordinator.record(id);
1531
+ if (!rec || rec.status !== "waiting" || rec.gate?.kind !== "agent") return "the run is not waiting at an agent gate";
1532
+ if (isAnswering(rec.agent, rec.gate.id)) return `${rec.agent.profile} is already answering`;
1533
+ void afterSegment(id, true);
1534
+ return void 0;
1535
+ }
1536
+ let storeWatcher;
1537
+ let storePoll;
1538
+ async function follow(opts) {
1539
+ if (opts.watching && opts.runsDir) {
1540
+ fs8.mkdirSync(opts.runsDir, { recursive: true });
1541
+ const chokidar = await import("chokidar");
1542
+ storeWatcher = chokidar.watch(opts.runsDir, { ignoreInitial: true, depth: 1 });
1543
+ storeWatcher.on("all", (_event, file) => {
1544
+ if (typeof file !== "string" || path7.basename(file) !== "run.json") return;
1545
+ void changed(path7.basename(path7.dirname(file)));
1546
+ });
1547
+ } else if (opts.watching) {
1548
+ let seen = /* @__PURE__ */ new Map();
1549
+ storePoll = setInterval(() => {
1550
+ void coordinator.list().then((rows) => {
1551
+ const now = new Map(rows.map((r) => [r.runId, r.updatedAt]));
1552
+ const moved = rows.filter((r) => seen.get(r.runId) !== r.updatedAt).map((r) => r.runId);
1553
+ const gone = [...seen.keys()].some((id) => !now.has(id));
1554
+ seen = now;
1555
+ if (!moved.length && !gone) return;
1556
+ listed = void 0;
1557
+ broadcast({ type: "runs" });
1558
+ for (const id of moved) if (!live.has(id)) void pushRun(id);
1559
+ }).catch(() => void 0);
1560
+ }, 3e3);
1561
+ storePoll.unref?.();
1562
+ }
1563
+ }
1564
+ const clock = setInterval(() => {
1565
+ void coordinator.tick().then(async (moved) => {
1566
+ for (const run of [...moved.woke, ...moved.timedOut]) {
1567
+ await changed(run.runId);
1568
+ void afterSegment(run.runId);
1569
+ }
1570
+ }).catch(() => void 0);
1571
+ }, 3e3);
1572
+ clock.unref?.();
1573
+ return {
1574
+ debug,
1575
+ /** The stored record, as the coordinator has it. */
1576
+ record: (id) => coordinator.record(id),
1577
+ /** A document kept beside the run. */
1578
+ kept: (id, name) => coordinator.kept(id, name),
1579
+ snapshot,
1580
+ list,
1581
+ start,
1582
+ startDebug,
1583
+ resume,
1584
+ cancel,
1585
+ remove,
1586
+ watch,
1587
+ withEvents,
1588
+ askAgent,
1589
+ follow,
1590
+ waitingCounts,
1591
+ withWaiting,
1592
+ /** A value set in a paused session, told to the pages that read values from the trace. */
1593
+ announce: push,
1594
+ /** Keep the run streams open through proxies. */
1595
+ ping() {
1596
+ for (const set of subs.values()) for (const res of set) res.write(": ping\n\n");
1597
+ },
1598
+ async close() {
1599
+ clearInterval(clock);
1600
+ if (storePoll) clearInterval(storePoll);
1601
+ await storeWatcher?.close();
1602
+ for (const set of subs.values()) for (const res of set) res.end();
1603
+ }
1604
+ };
1605
+ }
1606
+
1607
+ // src/console/routes-agents.ts
1608
+ import * as fs9 from "node:fs";
1609
+ function createProfileCache(projectDir) {
1610
+ let cache;
1611
+ const get = () => {
1612
+ const dir = projectDir();
1613
+ let mtime;
1614
+ try {
1615
+ mtime = fs9.statSync(agentsFile(dir)).mtimeMs;
1616
+ } catch {
1617
+ mtime = 0;
1618
+ }
1619
+ if (!cache || cache.dir !== dir || cache.mtime !== mtime) cache = { dir, mtime, profiles: loadAgentProfiles(dir) };
1620
+ return cache.profiles;
1621
+ };
1622
+ return {
1623
+ get,
1624
+ save(profiles) {
1625
+ saveAgentProfiles(projectDir(), profiles);
1626
+ cache = void 0;
1627
+ },
1628
+ describe() {
1629
+ const p = get();
1630
+ return {
1631
+ file: p.file,
1632
+ exists: p.exists,
1633
+ default: p.default ?? null,
1634
+ errors: p.errors,
1635
+ gates: p.gates,
1636
+ starter: STARTER_AGENTS_YAML,
1637
+ suggestedModels: SUGGESTED_MODELS,
1638
+ agents: Object.values(p.agents).map((a) => {
1639
+ const r = readiness(a);
1640
+ return { name: a.name, provider: a.provider, model: a.model || DEFAULT_MODEL[a.provider] || null, keyEnv: keyEnvOf(a) ?? null, ready: r.ready, reason: r.reason ?? null, description: a.description ?? null, system: a.system ?? null, maxIterations: a.maxIterations ?? null, baseUrl: a.baseUrl ?? null, bin: a.bin ?? null };
1641
+ })
1642
+ };
1643
+ }
1644
+ };
1645
+ }
1646
+ function profileFrom(name, b) {
1647
+ const str = (k) => typeof b[k] === "string" && b[k].trim() ? b[k].trim() : void 0;
1648
+ const num = (k) => typeof b[k] === "number" ? b[k] : typeof b[k] === "string" && b[k].trim() ? Number(b[k]) : void 0;
1649
+ return {
1650
+ name,
1651
+ provider: b.provider,
1652
+ model: str("model"),
1653
+ apiKeyEnv: str("apiKeyEnv"),
1654
+ baseUrl: str("baseUrl"),
1655
+ system: typeof b.system === "string" && b.system.trim() ? b.system : void 0,
1656
+ maxIterations: num("maxIterations"),
1657
+ maxTokens: num("maxTokens"),
1658
+ bin: str("bin"),
1659
+ description: str("description")
1660
+ };
1661
+ }
1662
+ var PROFILE = /^\/api\/agents\/profiles\/([^/]+)$/;
1663
+ var TRY = /^\/api\/agents\/try\/([^/]+)$/;
1664
+ var nameIn = ({ match }) => decodeURIComponent(match[1] ?? "");
1665
+ function agentRoutes(ctx) {
1666
+ const { profiles } = ctx;
1667
+ const describe = (call) => json(call.res, 200, profiles.describe());
1668
+ return [
1669
+ { path: "/api/agents", handle: describe },
1670
+ // Whether an environment variable is set here -- never its value.
1671
+ {
1672
+ path: "/api/agents/env",
1673
+ handle: ({ res, q }) => json(res, 200, { name: q("name"), set: /^[A-Z_][A-Z0-9_]*$/.test(q("name")) && !!process.env[q("name")] })
1674
+ },
1675
+ {
1676
+ method: "PUT",
1677
+ path: "/api/agents/default",
1678
+ handle: async (call) => {
1679
+ const b = await call.body();
1680
+ const p = profiles.get();
1681
+ const name = typeof b.name === "string" && b.name ? b.name : void 0;
1682
+ if (name && !p.agents[name]) return json(call.res, 400, { error: `no profile named ${name}` });
1683
+ profiles.save({ agents: p.agents, default: name, gates: p.gates });
1684
+ return describe(call);
1685
+ }
1686
+ },
1687
+ {
1688
+ method: "PUT",
1689
+ path: "/api/agents/gates",
1690
+ handle: async (call) => {
1691
+ const b = await call.body();
1692
+ const p = profiles.get();
1693
+ const key = typeof b.key === "string" ? b.key.trim() : "";
1694
+ if (!key) return json(call.res, 400, { error: "a gate key is an agentId or workflow/node" });
1695
+ const gates = { ...p.gates };
1696
+ if (typeof b.profile === "string" && b.profile) {
1697
+ if (!p.agents[b.profile]) return json(call.res, 400, { error: `no profile named ${b.profile}` });
1698
+ gates[key] = b.profile;
1699
+ } else delete gates[key];
1700
+ profiles.save({ agents: p.agents, default: p.default, gates });
1701
+ return describe(call);
1702
+ }
1703
+ },
1704
+ {
1705
+ method: "POST",
1706
+ path: TRY,
1707
+ handle: async (call) => {
1708
+ const profile = profiles.get().agents[nameIn(call)];
1709
+ if (!profile) return json(call.res, 404, { error: `no profile named ${nameIn(call)}` });
1710
+ return json(call.res, 200, await tryProfile(profile, process.env, { cwd: ctx.projectDir() }));
1711
+ }
1712
+ },
1713
+ {
1714
+ method: "PUT",
1715
+ path: PROFILE,
1716
+ handle: async (call) => {
1717
+ const name = nameIn(call);
1718
+ const p = profiles.get();
1719
+ const profile = profileFrom(name, await call.body());
1720
+ const problems = validateProfile(profile);
1721
+ if (problems.length) return json(call.res, 400, { error: problems.join("; ") });
1722
+ const agents = { ...p.agents, [name]: profile };
1723
+ const def = p.default && agents[p.default] ? p.default : Object.keys(agents).length === 1 ? name : p.default;
1724
+ profiles.save({ agents, default: def, gates: p.gates });
1725
+ return describe(call);
1726
+ }
1727
+ },
1728
+ {
1729
+ method: "DELETE",
1730
+ path: PROFILE,
1731
+ handle: (call) => {
1732
+ const name = nameIn(call);
1733
+ const p = profiles.get();
1734
+ if (!p.agents[name]) return json(call.res, 404, { error: `no profile named ${name}` });
1735
+ const agents = { ...p.agents };
1736
+ delete agents[name];
1737
+ const gates = Object.fromEntries(Object.entries(p.gates).filter(([, v]) => v !== name));
1738
+ profiles.save({ agents, default: p.default === name ? void 0 : p.default, gates });
1739
+ return describe(call);
1740
+ }
1741
+ }
1742
+ ];
1743
+ }
1744
+
1745
+ // src/console/routes-project.ts
1746
+ import * as fs10 from "node:fs";
1747
+ import * as path8 from "node:path";
1748
+
1749
+ // src/console/diff-view.ts
1750
+ var CONTROL4 = /* @__PURE__ */ new Set(["execute", "onSuccess", "onFailure"]);
1751
+ var isControl = (c) => CONTROL4.has(c.from.port) || c.to.port === "execute";
1752
+ function typeOf(ast, inst) {
1753
+ return ast.nodeTypes.find((n) => n.name === inst.nodeType) ?? ast.nodeTypes.find((n) => n.functionName === inst.nodeType);
1754
+ }
1755
+ var portList = (map) => Object.entries(map ?? {}).filter(([k, p]) => !CONTROL4.has(k) && !p.isControlFlow).map(([k, p]) => ({ name: k, tsType: p.tsType ?? String(p.dataType).toLowerCase(), optional: !!p.optional, description: p.description ?? "" }));
1756
+ function nodeOf(ast, inst) {
1757
+ const nt = typeOf(ast, inst);
1758
+ return {
1759
+ id: inst.id,
1760
+ type: inst.nodeType,
1761
+ label: stepLabel(inst, nt),
1762
+ description: nt?.description ?? "",
1763
+ builtin: !nt?.functionText,
1764
+ color: inst.config?.color ?? nt?.visuals?.color ?? null,
1765
+ icon: inst.config?.icon ?? nt?.visuals?.icon ?? null,
1766
+ pull: inst.config?.pullExecution !== void 0,
1767
+ gate: nt?.durableGate ?? null,
1768
+ expression: !!nt?.expression,
1769
+ durablePure: !!nt?.durablePure,
1770
+ effect: !!nt?.durableEffect,
1771
+ async: !!nt?.isAsync,
1772
+ inputs: portList(nt?.inputs),
1773
+ outputs: portList(nt?.outputs),
1774
+ source: nt?.functionText ?? "",
1775
+ file: nt?.sourceLocation?.file ?? ast.sourceFile,
1776
+ line: nt?.sourceLocation?.line ?? null,
1777
+ outputSchema: null,
1778
+ expr: (inst.config?.portConfigs ?? []).filter((c) => c.expression).map((c) => ({ port: c.portName, expr: String(c.expression) })),
1779
+ pack: null,
1780
+ deploy: null
1781
+ };
1782
+ }
1783
+ function instanceDetail(d, typeChanged) {
1784
+ const bits = [];
1785
+ if (d.changes.nodeType) bits.push(`now ${d.changes.nodeType.after}, was ${d.changes.nodeType.before}`);
1786
+ if (d.changes.config?.portConfigs) bits.push("expressions changed");
1787
+ if (d.changes.config?.pullExecution) bits.push(d.changes.config.pullExecution.after ? "now pulled on demand" : "no longer pulled");
1788
+ if (d.changes.parent) {
1789
+ const a = d.changes.parent.after, b = d.changes.parent.before;
1790
+ bits.push(a ? `moved into ${a.id} (${a.scope})` : b ? `moved out of ${b.id} (${b.scope})` : "scope changed");
1791
+ }
1792
+ if (typeChanged) bits.push(typeDetail(typeChanged));
1793
+ return bits.join(", ");
1794
+ }
1795
+ function typeDetail(d) {
1796
+ const bits = [];
1797
+ const io = (list, word) => {
1798
+ for (const p of list ?? []) bits.push(`${p.type === "ADDED" ? "+" : p.type === "REMOVED" ? "\u2212" : "~"}${word} ${p.portName}`);
1799
+ };
1800
+ io(d.changes.inputs, "in");
1801
+ io(d.changes.outputs, "out");
1802
+ if (d.changes.executeWhen) bits.push("execute-when changed");
1803
+ if (d.changes.isAsync) bits.push(d.changes.isAsync.after ? "now async" : "no longer async");
1804
+ if (d.changes.scope) bits.push("scope changed");
1805
+ if (d.changes.functionName) bits.push(`function ${d.changes.functionName.after}`);
1806
+ return bits.join(", ");
1807
+ }
1808
+ function buildDiffView(before, after) {
1809
+ const diff = WorkflowDiffer.compare(before, after);
1810
+ const reasons = diff.identical ? [] : getImpactReasons(diff);
1811
+ const beforeInst = new Map(before.instances.map((i) => [i.id, i]));
1812
+ const afterInst = new Map(after.instances.map((i) => [i.id, i]));
1813
+ const label = (id) => {
1814
+ if (id === "Start" || id === "Exit") return id;
1815
+ const inst = afterInst.get(id) ?? beforeInst.get(id);
1816
+ return inst ? stepLabel(inst, typeOf(afterInst.has(id) ? after : before, inst)) : id;
1817
+ };
1818
+ const typeDiffs = new Map(diff.nodeTypes.filter((n) => n.changeType === "MODIFIED").map((n) => [n.name, n]));
1819
+ const steps = [];
1820
+ for (const d of diff.instances) {
1821
+ const inst = afterInst.get(d.id) ?? beforeInst.get(d.id);
1822
+ if (!inst) continue;
1823
+ if (d.changeType === "ADDED") steps.push({ id: d.id, label: label(d.id), change: "added", detail: `${inst.nodeType}` });
1824
+ else if (d.changeType === "REMOVED") steps.push({ id: d.id, label: label(d.id), change: "removed", detail: `${inst.nodeType}` });
1825
+ else {
1826
+ const t = typeDiffs.get(inst.nodeType) ?? [...typeDiffs.values()].find((x) => typeOf(after, inst)?.functionName === x.name);
1827
+ const detail = instanceDetail(d, t);
1828
+ if (detail) steps.push({ id: d.id, label: label(d.id), change: "changed", detail });
1829
+ }
1830
+ }
1831
+ const touched = new Set(steps.map((s) => s.id));
1832
+ for (const inst of after.instances) {
1833
+ if (touched.has(inst.id)) continue;
1834
+ const nt = typeOf(after, inst);
1835
+ const t = typeDiffs.get(inst.nodeType) ?? (nt ? typeDiffs.get(nt.name) : void 0);
1836
+ if (t) {
1837
+ steps.push({ id: inst.id, label: label(inst.id), change: "changed", detail: typeDetail(t) });
1838
+ touched.add(inst.id);
1839
+ }
1840
+ }
1841
+ const wiring = [];
1842
+ const edgesAdded = /* @__PURE__ */ new Map();
1843
+ const edgesRemoved = /* @__PURE__ */ new Map();
1844
+ for (const c of diff.connections) {
1845
+ const change = c.changeType === "ADDED" ? "added" : "removed";
1846
+ const kind = isControl(c) ? c.from.port === "onFailure" ? "fail" : "ok" : "data";
1847
+ const text = kind === "data" ? `${label(c.from.node)}.${c.from.port} \u2192 ${label(c.to.node)}.${c.to.port}` : `${label(c.from.node)}${kind === "fail" ? " on failure" : ""} \u2192 ${label(c.to.node)}`;
1848
+ wiring.push({ change, from: c.from.node, to: c.to.node, fromPort: c.from.port, toPort: c.to.port, kind, label: text });
1849
+ if (kind !== "data") (change === "added" ? edgesAdded : edgesRemoved).set(`${c.from.node}>${c.to.node}`, [c.from.node, c.to.node]);
1850
+ }
1851
+ const contract = [];
1852
+ const ports3 = (side, p) => {
1853
+ for (const x of p.added) contract.push({ side, name: x.name, change: "added", detail: x.definition.tsType ?? String(x.definition.dataType ?? "") });
1854
+ for (const x of p.removed) contract.push({ side, name: x.name, change: "removed", detail: x.definition.tsType ?? String(x.definition.dataType ?? "") });
1855
+ for (const x of p.modified) contract.push({ side, name: x.name, change: "changed", detail: `${x.before.tsType ?? x.before.dataType} \u2192 ${x.after.tsType ?? x.after.dataType}` });
1856
+ };
1857
+ ports3("in", diff.startPorts);
1858
+ ports3("out", diff.exitPorts);
1859
+ const removedInstances = before.instances.filter((i) => !afterInst.has(i.id));
1860
+ const afterTypes = new Set(after.nodeTypes.map((n) => n.name));
1861
+ const unionTypes = [...after.nodeTypes, ...before.nodeTypes.filter((n) => !afterTypes.has(n.name))];
1862
+ const unionIds = new Set([...after.instances, ...removedInstances].map((i) => i.id));
1863
+ const afterConn = new Set(after.connections.map(connKey));
1864
+ const removedConnections = before.connections.filter((c) => !afterConn.has(connKey(c)) && (c.from.node === "Start" || unionIds.has(c.from.node)) && (c.to.node === "Exit" || unionIds.has(c.to.node)));
1865
+ const union = { ...after, nodeTypes: unionTypes, instances: [...after.instances, ...removedInstances], connections: [...after.connections, ...removedConnections] };
1866
+ let model;
1867
+ try {
1868
+ model = buildProcessModel(union);
1869
+ } catch {
1870
+ model = null;
1871
+ }
1872
+ if (model) {
1873
+ const unionInst = new Map(union.instances.map((i) => [i.id, i]));
1874
+ const stampAll = (steps2) => steps2.forEach((s) => {
1875
+ const inst = unionInst.get(s.id);
1876
+ if (inst) {
1877
+ s.label = label(s.id);
1878
+ s.pull = inst.config?.pullExecution !== void 0;
1879
+ }
1880
+ stampAll(s.children);
1881
+ });
1882
+ stampAll(model.steps);
1883
+ }
1884
+ const nodes = {};
1885
+ for (const inst of removedInstances) nodes[inst.id] = nodeOf(before, inst);
1886
+ return {
1887
+ identical: diff.identical,
1888
+ impact: diff.impact,
1889
+ reasons,
1890
+ steps,
1891
+ wiring,
1892
+ contract,
1893
+ marks: {
1894
+ added: steps.filter((s) => s.change === "added").map((s) => s.id),
1895
+ removed: steps.filter((s) => s.change === "removed").map((s) => s.id),
1896
+ changed: steps.filter((s) => s.change === "changed").map((s) => s.id),
1897
+ edgesAdded: [...edgesAdded.values()],
1898
+ edgesRemoved: [...edgesRemoved.values()]
1899
+ },
1900
+ model,
1901
+ nodes
1902
+ };
1903
+ }
1904
+ var connKey = (c) => `${c.from.node}.${c.from.port}${c.from.scope ? ":" + c.from.scope : ""}>${c.to.node}.${c.to.port}${c.to.scope ? ":" + c.to.scope : ""}`;
1905
+
1906
+ // src/console/routes-services.ts
1907
+ function describeServe(supervisor) {
1908
+ const s = supervisor.view("serve");
1909
+ return {
1910
+ running: s.state === "running" && s.pid ? { url: s.url ?? null, pid: s.pid, startedAt: s.startedAt, version: s.activity?.version ?? VERSION, install: s.activity?.install ?? "", owned: s.owned, token: s.token ?? null } : null,
1911
+ state: s.state,
1912
+ command: "fw serve --trace"
1913
+ };
1914
+ }
1915
+ function serviceRoutes(ctx) {
1916
+ const listing = () => ({ services: ctx.supervisor().list(), settings: ctx.supervisor().settings() });
1917
+ return [
1918
+ { path: "/api/serve", handle: ({ res }) => json(res, 200, describeServe(ctx.supervisor())) },
1919
+ // The project's services: what runs, its settings, start and stop, its output.
1920
+ { path: "/api/services", handle: ({ res }) => json(res, 200, listing()) },
1921
+ {
1922
+ path: /^\/api\/services\/(serve|watch)\/(start|stop|restart|settings|logs)$/,
1923
+ handle: async ({ req, res, q, body, match }) => {
1924
+ const kind = match[1];
1925
+ const action = match[2];
1926
+ const supervisor = ctx.supervisor();
1927
+ try {
1928
+ if (action === "logs") {
1929
+ if (q("format") === "json") return json(res, 200, supervisor.logs(kind));
1930
+ sse(res);
1931
+ for (const line of supervisor.logs(kind)) send(res, line);
1932
+ send(res, { synced: true });
1933
+ const off = supervisor.onLog(kind, (line) => send(res, line));
1934
+ req.on("close", off);
1935
+ return;
1936
+ }
1937
+ if (req.method !== "POST" && req.method !== "PUT") return json(res, 405, { error: "POST to start, stop or restart; PUT settings" });
1938
+ const b = await body();
1939
+ if (action === "settings") {
1940
+ supervisor.saveSettings(kind, b);
1941
+ return json(res, 200, listing());
1942
+ }
1943
+ if (action === "start") {
1944
+ if (Object.keys(b).length) supervisor.saveSettings(kind, b);
1945
+ supervisor.start(kind);
1946
+ }
1947
+ if (action === "stop") await supervisor.stop(kind, typeof b.pid === "number" ? b.pid : void 0);
1948
+ if (action === "restart") await supervisor.restart(kind);
1949
+ return json(res, 200, listing());
1950
+ } catch (err) {
1951
+ return json(res, 400, { error: getErrorMessage(err) });
1952
+ }
1953
+ }
1954
+ },
1955
+ {
1956
+ path: "/api/events",
1957
+ handle: ({ req, res }) => {
1958
+ sse(res);
1959
+ ctx.followers.add(res);
1960
+ req.on("close", () => ctx.followers.delete(res));
1961
+ }
1962
+ }
1963
+ ];
1964
+ }
1965
+
1966
+ // src/console/routes-project.ts
1967
+ var OUTSIDE = { error: "file is outside the project" };
1968
+ function projectRoutes(ctx) {
1969
+ const here = () => {
1970
+ const dir = ctx.projectDir();
1971
+ return { dir, name: path8.basename(dir), parent: path8.dirname(dir) };
1972
+ };
1973
+ const { pageDir, scriptDir } = ctx.client;
1974
+ return [
1975
+ { path: "/", handle: ({ res }) => sendFile(res, path8.join(pageDir, "index.html"), "text/html") },
1976
+ { path: "/app.js", handle: ({ res }) => sendFile(res, path8.join(scriptDir, "app.js"), "text/javascript") },
1977
+ { path: "/styles.css", handle: ({ res }) => sendFile(res, path8.join(pageDir, "styles.css"), "text/css") },
1978
+ { path: "/synergenius.svg", handle: ({ res }) => sendFile(res, path8.join(pageDir, "assets", "synergenius.svg"), "image/svg+xml") },
1979
+ { method: "GET", path: "/api/project", handle: ({ res }) => json(res, 200, here()) },
1980
+ // Opening another project. The console is a local tool driving a local
1981
+ // engine, so any directory the user can read is fair game -- but it
1982
+ // must exist, and the answer re-points the watcher and the containment
1983
+ // check together so neither is left pointing at the old project.
1984
+ {
1985
+ method: "POST",
1986
+ path: "/api/project",
1987
+ handle: async ({ res, body }) => {
1988
+ const target = path8.resolve(String((await body()).dir ?? ""));
1989
+ if (!fs10.existsSync(target) || !fs10.statSync(target).isDirectory()) {
1990
+ return json(res, 400, { error: `not a directory: ${target}` });
1991
+ }
1992
+ await ctx.openProject(target);
1993
+ return json(res, 200, here());
1994
+ }
1995
+ },
1996
+ // Directories to choose from, so the console can offer a picker
1997
+ // rather than asking someone to type a path.
1998
+ {
1999
+ path: "/api/browse",
2000
+ handle: ({ res, q }) => {
2001
+ const at2 = path8.resolve(q("dir") || ctx.projectDir());
2002
+ try {
2003
+ const entries = fs10.readdirSync(at2, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".") && e.name !== "node_modules").map((e) => ({ name: e.name, dir: path8.join(at2, e.name) })).sort((a, b) => a.name.localeCompare(b.name));
2004
+ return json(res, 200, { dir: at2, parent: path8.dirname(at2), entries, crumbs: crumbsFor(at2) });
2005
+ } catch (err) {
2006
+ return json(res, 400, { error: getErrorMessage(err) });
2007
+ }
2008
+ }
2009
+ },
2010
+ {
2011
+ path: "/api/workflows",
2012
+ handle: async ({ res }) => {
2013
+ const list = scanWorkflowNames(ctx.projectDir());
2014
+ ctx.queueCheck();
2015
+ const counts = await ctx.runs.waitingCounts();
2016
+ return json(res, 200, list.map((w) => ctx.runs.withWaiting(w, counts)));
2017
+ }
2018
+ },
2019
+ // A workflow as something to hand to someone: a brief for people who
2020
+ // will not open the code, or the diagram. Sent as a download,
2021
+ // self-contained.
2022
+ {
2023
+ path: "/api/artifact",
2024
+ handle: async ({ res, q }) => {
2025
+ const target = ctx.inProject(q("file"));
2026
+ if (!target) return json(res, 400, OUTSIDE);
2027
+ const { ast, errors } = await parseOne(target, q("name"));
2028
+ if (!ast) return json(res, 400, { error: errors.join("\n") || "does not parse" });
2029
+ const theme = q("theme") === "dark" ? "dark" : "light";
2030
+ const kind = q("kind");
2031
+ if (!ARTIFACT_KINDS.includes(kind)) return json(res, 400, { error: `unknown artifact ${kind}` });
2032
+ let artifact;
2033
+ try {
2034
+ artifact = await renderArtifact(ast, kind, { theme, subtitle: path8.basename(ctx.projectDir()) });
2035
+ } catch (e) {
2036
+ return json(res, 500, { error: getErrorMessage(e) });
2037
+ }
2038
+ res.writeHead(200, { "Content-Type": artifact.type, "Content-Disposition": `attachment; filename="${ast.functionName}${artifact.extension}"`, "Cache-Control": "no-cache" });
2039
+ return res.end(artifact.body);
2040
+ }
2041
+ },
2042
+ {
2043
+ path: "/api/workflow",
2044
+ handle: async ({ res, q }) => {
2045
+ const file = ctx.inProject(q("file"));
2046
+ if (!file) return json(res, 400, OUTSIDE);
2047
+ return json(res, 200, await describeWorkflow(ctx.projectDir(), file, q("name")));
2048
+ }
2049
+ },
2050
+ // Expose a workflow as an endpoint, or change its routes: the @http
2051
+ // lines are rewritten, nothing else in the file is touched.
2052
+ {
2053
+ method: "PUT",
2054
+ path: "/api/workflow/http",
2055
+ handle: async ({ res, body }) => {
2056
+ const b = await body();
2057
+ const target = ctx.inProject(String(b.file ?? ""));
2058
+ if (!target) return json(res, 400, OUTSIDE);
2059
+ const routes = [];
2060
+ for (const raw of Array.isArray(b.routes) ? b.routes : []) {
2061
+ const r = routeFrom(raw);
2062
+ if (typeof r === "string") return json(res, 400, { error: r });
2063
+ if (routes.some((x) => x.method === r.method && x.path === r.path)) return json(res, 400, { error: `${r.method} ${r.path} is listed twice` });
2064
+ routes.push(r);
2065
+ }
2066
+ const out = await setHttpRoutes(target, String(b.name ?? ""), routes);
2067
+ if (!out.ok) return json(res, 400, { error: out.error });
2068
+ return json(res, 200, await describeWorkflow(ctx.projectDir(), target, String(b.name)));
2069
+ }
2070
+ },
2071
+ // Every route the project declares, as one list: what `fw serve` or
2072
+ // an embedding would mount, and what it would refuse.
2073
+ {
2074
+ path: "/api/endpoints",
2075
+ handle: async ({ res }) => {
2076
+ const names2 = scanWorkflowNames(ctx.projectDir());
2077
+ const parsed = await Promise.all(names2.map(async (w) => {
2078
+ const p = await parseOne(w.file, w.name);
2079
+ const ast = p.ast;
2080
+ const gates = ast ? ast.instances.filter((i) => nodeTypeOf(ast, i)?.durableGate !== void 0).length : 0;
2081
+ return { file: w.file, rel: w.rel, name: w.name, description: ast?.description ?? "", routes: ast?.options?.http ?? [], gates, params: ast ? ports2(ast.startPorts) : [], returns: ast ? ports2(ast.exitPorts) : [], parses: !!ast };
2082
+ }));
2083
+ const plan = planRoutes(parsed.map((w) => ({ name: w.name, routes: w.routes, w })));
2084
+ return json(res, 200, {
2085
+ workflows: parsed.filter((w) => w.routes.length).map(({ routes, ...w }) => ({ ...w, routes: routes.map((r) => ({ ...r, mounted: plan.mounted.some((m) => m.owner.name === w.name && m.route === r) })) })),
2086
+ candidates: parsed.filter((w) => !w.routes.length && w.parses).map(({ routes: _r, ...w }) => w),
2087
+ problems: plan.problems,
2088
+ serve: describeServe(ctx.supervisor())
2089
+ });
2090
+ }
2091
+ },
2092
+ // Version control: the commits that touched a file, and two versions
2093
+ // of a workflow as one marked picture. `from`/`to` are git refs, or
2094
+ // `worktree` for the file as it is now.
2095
+ {
2096
+ path: "/api/git/history",
2097
+ handle: async ({ res, q }) => {
2098
+ const file = ctx.inProject(q("file"));
2099
+ if (!file) return json(res, 400, OUTSIDE);
2100
+ return json(res, 200, await fileHistory(file));
2101
+ }
2102
+ },
2103
+ {
2104
+ path: "/api/diff",
2105
+ handle: async ({ res, q }) => {
2106
+ const file = ctx.inProject(q("file"));
2107
+ if (!file) return json(res, 400, OUTSIDE);
2108
+ const name = q("name"), from = q("from") || "HEAD", to = q("to") || "worktree";
2109
+ const [a, b] = await Promise.all([astAt(file, name, from), astAt(file, name, to)]);
2110
+ if (!a.ast) return json(res, 400, { error: a.error });
2111
+ if (!b.ast) return json(res, 400, { error: b.error });
2112
+ return json(res, 200, { from, to, ...buildDiffView(a.ast, b.ast) });
2113
+ }
2114
+ }
2115
+ ];
2116
+ }
2117
+
2118
+ // src/console/routes-tools.ts
2119
+ import * as path12 from "node:path";
2120
+
2121
+ // src/docs/guide.ts
2122
+ var GROUPS = [
2123
+ { title: "Getting started", topics: [["orientation"], ["tutorial"], ["console"]] },
2124
+ {
2125
+ title: "Authoring",
2126
+ topics: [
2127
+ ["concepts"],
2128
+ ["jsdoc-grammar"],
2129
+ ["advanced-annotations", { uses: ["pull", "expr", "scope"] }],
2130
+ ["export-interface", { uses: ["scope"] }],
2131
+ ["built-in-nodes", { uses: ["builtin:"] }],
2132
+ ["node-conversion"],
2133
+ ["visual-reference"],
2134
+ ["scaffold"]
2135
+ ]
2136
+ },
2137
+ {
2138
+ title: "Running",
2139
+ topics: [
2140
+ ["library"],
2141
+ ["durable-gates", { uses: ["gate:", "effect", "pure"] }],
2142
+ ["debugging", { codes: true }],
2143
+ ["cancellation"],
2144
+ ["compilation"],
2145
+ ["deployment"]
2146
+ ]
2147
+ },
2148
+ { title: "Tooling", topics: [["cli-reference"], ["mcp-tools"], ["iterative-development"], ["marketplace"]] },
2149
+ { title: "Reference", topics: [["error-codes", { codes: true }]] }
2150
+ ];
2151
+ function guideOutline(topics = listTopics(), packSlugs = /* @__PURE__ */ new Set()) {
2152
+ const byslug = new Map(topics.map((t) => [t.slug, t]));
2153
+ const placed = /* @__PURE__ */ new Set();
2154
+ const groups = [];
2155
+ for (const g of GROUPS) {
2156
+ const entries = [];
2157
+ for (const [slug, related] of g.topics) {
2158
+ const t = byslug.get(slug);
2159
+ if (!t) continue;
2160
+ placed.add(slug);
2161
+ entries.push({ slug, name: t.name || slug, description: t.description, ...related ? { related } : {} });
2162
+ }
2163
+ if (entries.length) groups.push({ title: g.title, topics: entries });
2164
+ }
2165
+ const rest = topics.filter((t) => !placed.has(t.slug));
2166
+ const more = rest.filter((t) => !packSlugs.has(t.slug)).map((t) => ({ slug: t.slug, name: t.name || t.slug, description: t.description }));
2167
+ const packs = rest.filter((t) => packSlugs.has(t.slug)).map((t) => ({ slug: t.slug, name: t.name || t.slug, description: t.description }));
2168
+ if (more.length) groups.push({ title: "More", topics: more });
2169
+ if (packs.length) groups.push({ title: "Packs", topics: packs });
2170
+ return groups;
2171
+ }
2172
+
2173
+ // src/console/cli-catalog.ts
2174
+ var SKIP_GROUPS = /* @__PURE__ */ new Set(["Quick Reference", "Global Flag", "Related Topics"]);
2175
+ var cell = (s) => s.trim().replace(/^`|`$/g, "");
2176
+ function parseCliReference(markdown) {
2177
+ const out = [];
2178
+ let group = "";
2179
+ let cur;
2180
+ let fence = null;
2181
+ let examplesNext = false;
2182
+ let inFlags = false;
2183
+ let described = false;
2184
+ for (const raw of markdown.split("\n")) {
2185
+ const line = raw.trimEnd();
2186
+ const h2 = line.match(/^## (.+)$/);
2187
+ if (h2) {
2188
+ group = h2[1].trim();
2189
+ cur = void 0;
2190
+ fence = null;
2191
+ continue;
2192
+ }
2193
+ const h3 = line.match(/^### (.+)$/);
2194
+ if (h3) {
2195
+ if (SKIP_GROUPS.has(group)) {
2196
+ cur = void 0;
2197
+ continue;
2198
+ }
2199
+ cur = { name: h3[1].trim(), words: [], group, description: "", usage: "", flags: [], examples: [] };
2200
+ out.push(cur);
2201
+ fence = null;
2202
+ examplesNext = false;
2203
+ inFlags = false;
2204
+ described = false;
2205
+ continue;
2206
+ }
2207
+ if (!cur) continue;
2208
+ if (line.startsWith("```")) {
2209
+ if (fence) {
2210
+ fence = null;
2211
+ continue;
2212
+ }
2213
+ fence = examplesNext ? "examples" : !cur.usage ? "usage" : "other";
2214
+ examplesNext = false;
2215
+ continue;
2216
+ }
2217
+ if (fence === "usage") {
2218
+ if (!cur.usage && /^fw\b/.test(line)) {
2219
+ cur.usage = line;
2220
+ cur.words = line.split(/\s+/).slice(1).filter((w) => !/^[<[-]/.test(w));
2221
+ }
2222
+ continue;
2223
+ }
2224
+ if (fence === "examples") {
2225
+ if (line.trim() && !line.startsWith("#")) cur.examples.push(line.trim());
2226
+ continue;
2227
+ }
2228
+ if (fence) continue;
2229
+ if (/^\*\*Examples:?\*\*/.test(line)) {
2230
+ examplesNext = true;
2231
+ continue;
2232
+ }
2233
+ if (/^\|\s*Flag\s*\|/i.test(line)) {
2234
+ inFlags = true;
2235
+ continue;
2236
+ }
2237
+ if (inFlags) {
2238
+ if (!line.startsWith("|")) {
2239
+ inFlags = false;
2240
+ } else {
2241
+ const cells = line.split("|").slice(1, -1);
2242
+ if (cells.length >= 2 && !/^[\s-:]+$/.test(cells[0])) {
2243
+ cur.flags.push({ flag: cell(cells[0]), description: cells[1].trim(), default: cell(cells[2] ?? "") });
2244
+ }
2245
+ continue;
2246
+ }
2247
+ }
2248
+ if (!described && line.trim() && !line.startsWith("|") && !line.startsWith(">") && !line.startsWith("---")) {
2249
+ cur.description = line.trim();
2250
+ described = true;
2251
+ }
2252
+ }
2253
+ return out.filter((c) => c.usage);
2254
+ }
2255
+ var cached;
2256
+ function cliCatalog() {
2257
+ if (!cached) cached = parseCliReference(readTopic("cli-reference")?.content ?? "");
2258
+ return cached;
2259
+ }
2260
+
2261
+ // src/console/export.ts
2262
+ import * as path9 from "node:path";
2263
+ var defaultOutputDir = (file, target) => path9.join(path9.dirname(file), "dist", target);
2264
+ async function listTargets(projectDir) {
2265
+ const registry = await createTargetRegistry(projectDir);
2266
+ const packs = await describePacks(projectDir);
2267
+ const owner = /* @__PURE__ */ new Map();
2268
+ for (const p of packs) for (const t of p.exportTargets) owner.set(t.name, p.name);
2269
+ return registry.getNames().map((name) => {
2270
+ const t = registry.get(name);
2271
+ return { name, description: t.description, pack: owner.get(name) ?? null, deploySchema: t.deploySchema ?? null };
2272
+ }).sort((a, b) => a.name.localeCompare(b.name));
2273
+ }
2274
+ async function runExport(projectDir, req) {
2275
+ const outputDir = path9.resolve(req.outputDir ?? defaultOutputDir(req.file, req.target));
2276
+ const result = await exportWorkflow({
2277
+ target: req.target,
2278
+ input: req.file,
2279
+ output: outputDir,
2280
+ workflow: req.name,
2281
+ dryRun: req.preview,
2282
+ production: true,
2283
+ projectDir
2284
+ });
2285
+ const files = result.files.map((f) => ({ path: path9.relative(outputDir, f.path).split(path9.sep).join("/"), content: f.content }));
2286
+ const registry = await createTargetRegistry(projectDir);
2287
+ const target = registry.get(req.target);
2288
+ let instructions = null;
2289
+ if (target && files.length) {
2290
+ const artifacts = {
2291
+ target: req.target,
2292
+ workflowName: result.workflow,
2293
+ entryPoint: files[0].path,
2294
+ files: files.map((f) => ({ relativePath: f.path, absolutePath: path9.join(outputDir, f.path), content: f.content, type: "other" })),
2295
+ warnings: result.warnings
2296
+ };
2297
+ try {
2298
+ instructions = target.getDeployInstructions(artifacts);
2299
+ } catch {
2300
+ instructions = null;
2301
+ }
2302
+ }
2303
+ return { target: req.target, outputDir, written: !req.preview, files, warnings: result.warnings ?? [], instructions };
2304
+ }
2305
+
2306
+ // src/console/author.ts
2307
+ import * as fs11 from "node:fs";
2308
+ import * as path10 from "node:path";
2309
+ var PACK_NAME = /^(@[^/]+\/)?flow-weaver-pack-.+$/;
2310
+ var PACK_KEYWORD = "flow-weaver-marketplace-pack";
2311
+ function detectPackProject(projectDir) {
2312
+ const file = path10.join(projectDir, "package.json");
2313
+ if (!fs11.existsSync(file)) return { isPack: false };
2314
+ try {
2315
+ const pkg = JSON.parse(fs11.readFileSync(file, "utf8"));
2316
+ const isPack = fs11.existsSync(path10.join(projectDir, "flowweaver.manifest.json")) || (pkg.keywords ?? []).includes(PACK_KEYWORD) || typeof pkg.name === "string" && PACK_NAME.test(pkg.name);
2317
+ return isPack ? { isPack, name: pkg.name, version: pkg.version } : { isPack: false };
2318
+ } catch {
2319
+ return { isPack: false };
2320
+ }
2321
+ }
2322
+ var names = (list) => new Set((list ?? []).map((x) => x.name));
2323
+ function manifestChanges(existing, next) {
2324
+ if (!existing) return ["No flowweaver.manifest.json yet. fw market pack writes it."];
2325
+ const out = [];
2326
+ if (existing.version !== next.version) out.push(`version ${existing.version} \u2192 ${next.version}`);
2327
+ if ((existing.description ?? "") !== (next.description ?? "")) out.push("description changed");
2328
+ for (const [label, was, now] of [
2329
+ ["node type", names(existing.nodeTypes), names(next.nodeTypes)],
2330
+ ["workflow", names(existing.workflows), names(next.workflows)]
2331
+ ]) {
2332
+ for (const n of now) if (!was.has(n)) out.push(`${label} ${n} added`);
2333
+ for (const n of was) if (!now.has(n)) out.push(`${label} ${n} removed`);
2334
+ }
2335
+ for (const n of next.nodeTypes ?? []) {
2336
+ const e = (existing.nodeTypes ?? []).find((x) => x.name === n.name);
2337
+ if (e && JSON.stringify({ i: e.inputs, o: e.outputs, d: e.description }) !== JSON.stringify({ i: n.inputs, o: n.outputs, d: n.description })) out.push(`node type ${n.name} changed`);
2338
+ }
2339
+ return out;
2340
+ }
2341
+ async function checkPackProject(projectDir) {
2342
+ const { manifest, parsedFiles, errors } = await generateManifest({ directory: projectDir });
2343
+ const validation = await validatePackage(projectDir, manifest);
2344
+ const existing = readManifest(projectDir);
2345
+ return {
2346
+ name: manifest.name,
2347
+ version: manifest.version,
2348
+ parsedFiles: parsedFiles.length,
2349
+ parseErrors: errors,
2350
+ valid: validation.valid,
2351
+ issues: validation.issues,
2352
+ manifest: describePack({ name: manifest.name, version: manifest.version, manifest, path: projectDir }),
2353
+ hasManifest: existing !== null,
2354
+ changes: manifestChanges(existing, manifest)
2355
+ };
2356
+ }
2357
+
2358
+ // src/console/status.ts
2359
+ import * as fs12 from "node:fs";
2360
+ import * as os3 from "node:os";
2361
+ import * as path11 from "node:path";
2362
+ var realpath = (p) => {
2363
+ try {
2364
+ return fs12.realpathSync(p);
2365
+ } catch {
2366
+ return path11.resolve(p);
2367
+ }
2368
+ };
2369
+ function installVerdict(command, args, here = installRoot()) {
2370
+ const all = [command, ...args];
2371
+ if (all.some((a) => /@synergenius\/flow-weaver(@|$)/.test(a)) && /npx|pnpm|yarn|bunx/.test(command)) return { runs: "npm latest" };
2372
+ const pathArg = all.find((a) => /flow-weaver\.mjs$|[\\/]flow-weaver([\\/]|$)/.test(a) && /[\\/]/.test(a));
2373
+ if (!pathArg) return { runs: "unknown" };
2374
+ let install = realpath(pathArg);
2375
+ for (let i = 0; i < 6 && !fs12.existsSync(path11.join(install, "package.json")); i++) install = path11.dirname(install);
2376
+ return { runs: realpath(install) === realpath(here) ? "this install" : "other install", install };
2377
+ }
2378
+ function readJson(file) {
2379
+ try {
2380
+ return JSON.parse(fs12.readFileSync(file, "utf8"));
2381
+ } catch {
2382
+ return null;
2383
+ }
2384
+ }
2385
+ function mcpRegistrations(projectDir, home = os3.homedir(), here = installRoot()) {
2386
+ const out = [];
2387
+ const add = (tool, file, entry) => {
2388
+ if (!entry || typeof entry.command !== "string") return;
2389
+ const args = Array.isArray(entry.args) ? entry.args.map(String) : [];
2390
+ out.push({ tool, file, command: entry.command, args, ...installVerdict(entry.command, args, here) });
2391
+ };
2392
+ const servers = (file, key) => {
2393
+ const cfg = readJson(file);
2394
+ const map = cfg?.[key];
2395
+ return map?.["flow-weaver"];
2396
+ };
2397
+ add("Claude Code (project)", path11.join(projectDir, ".mcp.json"), servers(path11.join(projectDir, ".mcp.json"), "mcpServers"));
2398
+ const claude = readJson(path11.join(home, ".claude.json"));
2399
+ if (claude) {
2400
+ add("Claude Code (user)", path11.join(home, ".claude.json"), claude.mcpServers?.["flow-weaver"]);
2401
+ const projects = claude.projects;
2402
+ const mine = projects?.[projectDir] ?? projects?.[realpath(projectDir)];
2403
+ add("Claude Code (this project)", path11.join(home, ".claude.json"), mine?.mcpServers?.["flow-weaver"]);
2404
+ }
2405
+ add("Cursor", path11.join(projectDir, ".cursor", "mcp.json"), servers(path11.join(projectDir, ".cursor", "mcp.json"), "mcpServers"));
2406
+ add("VS Code", path11.join(projectDir, ".vscode", "mcp.json"), servers(path11.join(projectDir, ".vscode", "mcp.json"), "servers"));
2407
+ add("Windsurf", path11.join(home, ".codeium", "windsurf", "mcp_config.json"), servers(path11.join(home, ".codeium", "windsurf", "mcp_config.json"), "mcpServers"));
2408
+ add("OpenClaw", path11.join(projectDir, "openclaw.json"), servers(path11.join(projectDir, "openclaw.json"), "mcpServers"));
2409
+ return out;
2410
+ }
2411
+ async function probe(url, init, timeoutMs = 2500) {
2412
+ const started = Date.now();
2413
+ const ctl = new AbortController();
2414
+ const t = setTimeout(() => ctl.abort(), timeoutMs);
2415
+ try {
2416
+ const res = await fetch(url, { ...init, signal: ctl.signal });
2417
+ return { url, ok: res.ok, status: res.status, ms: Date.now() - started };
2418
+ } catch (err) {
2419
+ return { url, ok: false, ms: Date.now() - started, error: err instanceof Error ? err.name === "AbortError" ? "timed out" : err.message : String(err) };
2420
+ } finally {
2421
+ clearTimeout(t);
2422
+ }
2423
+ }
2424
+ async function registryStatuses(projectDir, registries = resolveRegistries(projectDir)) {
2425
+ return Promise.all(registries.map(async (r) => {
2426
+ const url = `${r.url}-/whoami`;
2427
+ const started = Date.now();
2428
+ const ctl = new AbortController();
2429
+ const t = setTimeout(() => ctl.abort(), 2500);
2430
+ try {
2431
+ const res = await fetch(url, { headers: r.authorization ? { Authorization: r.authorization } : {}, signal: ctl.signal });
2432
+ let user;
2433
+ if (res.ok) {
2434
+ try {
2435
+ user = (await res.json()).username;
2436
+ } catch {
2437
+ }
2438
+ }
2439
+ const reachable = res.ok || !r.authorization && (res.status === 401 || res.status === 403);
2440
+ return { url: r.url, scopes: r.scopes, authenticated: !!r.authorization, ok: reachable, status: res.status, ms: Date.now() - started, user };
2441
+ } catch (err) {
2442
+ return { url: r.url, scopes: r.scopes, authenticated: !!r.authorization, ok: false, ms: Date.now() - started, error: err instanceof Error ? err.name === "AbortError" ? "timed out" : err.message : String(err) };
2443
+ } finally {
2444
+ clearTimeout(t);
2445
+ }
2446
+ }));
2447
+ }
2448
+ async function describeStatus(projectDir, info) {
2449
+ const services = listServices().map((s) => ({ ...s, alive: true }));
2450
+ const serve = services.filter((s) => s.kind === "serve" && s.url);
2451
+ const [http2, registries] = await Promise.all([
2452
+ Promise.all(serve.map(async (service) => ({ service, probe: await probe(`${service.url.replace(/\/$/, "")}/health`) }))),
2453
+ registryStatuses(projectDir)
2454
+ ]);
2455
+ return {
2456
+ console: { version: VERSION, install: installRoot(), project: projectDir, url: info.url, watching: info.watching, runsDir: info.runsDir },
2457
+ services,
2458
+ mcp: { registrations: mcpRegistrations(projectDir), running: services.filter((s) => s.kind === "mcp-server") },
2459
+ doctor: runDoctorChecks(projectDir),
2460
+ http: http2,
2461
+ registries,
2462
+ at: (/* @__PURE__ */ new Date()).toISOString()
2463
+ };
2464
+ }
2465
+
2466
+ // src/console/routes-tools.ts
2467
+ var CLI_TIMEOUT_MS = 5 * 60 * 1e3;
2468
+ function toolRoutes(ctx) {
2469
+ return [
2470
+ // An empty or one-letter query matches every topic with an empty
2471
+ // heading and excerpt, which is noise rather than a result list.
2472
+ {
2473
+ path: "/api/docs/search",
2474
+ handle: ({ res, q }) => {
2475
+ const query = q("q").trim();
2476
+ const limit = Math.min(80, Math.max(1, Number(q("limit")) || 12));
2477
+ return json(res, 200, query.length < 2 ? [] : searchDocs(query).filter((r) => r.heading).slice(0, limit));
2478
+ }
2479
+ },
2480
+ { path: "/api/docs/topics", handle: ({ res }) => json(res, 200, listTopics()) },
2481
+ {
2482
+ path: "/api/docs/guide",
2483
+ handle: ({ res }) => json(res, 200, guideOutline(listTopics(), new Set(getPackDocTopics().map((t) => t.slug))))
2484
+ },
2485
+ // The page as markdown for rendering, its sections for the contents
2486
+ // list, and the compact form -- what `fw_docs` hands an assistant --
2487
+ // for copying into a conversation.
2488
+ {
2489
+ path: "/api/docs/topic",
2490
+ handle: ({ res, q }) => {
2491
+ const slug = q("slug");
2492
+ const full = readTopic(slug);
2493
+ if (!full) return json(res, 404, { error: `no topic ${slug}` });
2494
+ const structured = readTopicStructured(slug);
2495
+ return json(res, 200, {
2496
+ slug,
2497
+ name: full.name,
2498
+ description: full.description,
2499
+ sections: structured?.sections.map((s) => ({ heading: s.heading, level: s.level })) ?? [],
2500
+ markdown: full.content,
2501
+ compact: readTopic(slug, true)?.content ?? ""
2502
+ });
2503
+ }
2504
+ },
2505
+ { path: "/api/docs/error", handle: ({ res, q }) => json(res, 200, errorCodeSection(q("code"))) },
2506
+ // Core commands from the reference, then each installed pack's, so
2507
+ // completion knows `fw audio replay` as well as `fw validate`.
2508
+ {
2509
+ path: "/api/cli/commands",
2510
+ handle: async ({ res }) => {
2511
+ const packCommands = (await describePacks(ctx.projectDir())).flatMap((p) => p.cliCommands.map((c) => ({
2512
+ name: `${p.namespace} ${c.name}`,
2513
+ words: [p.namespace, c.name],
2514
+ group: `Pack: ${p.namespace}`,
2515
+ description: c.description,
2516
+ usage: c.usage,
2517
+ flags: c.flags,
2518
+ examples: []
2519
+ })));
2520
+ return json(res, 200, [...cliCatalog(), ...packCommands]);
2521
+ }
2522
+ },
2523
+ // An fw command, run in the project, its output streamed back. The
2524
+ // argument list is spawned as is -- no shell -- and the child goes
2525
+ // when the page lets go of the stream.
2526
+ {
2527
+ method: "POST",
2528
+ path: "/api/cli/run",
2529
+ handle: async ({ req, res, body }) => {
2530
+ const argv = (await body()).argv;
2531
+ const plan = planFwCommand(Array.isArray(argv) ? argv : []);
2532
+ if (!plan.ok) return json(res, 400, { error: plan.error });
2533
+ sse(res);
2534
+ const started = Date.now();
2535
+ const emit = (msg) => send(res, msg);
2536
+ emit({ type: "start", args: plan.args });
2537
+ let child;
2538
+ try {
2539
+ child = spawnFw(plan.args, ctx.projectDir());
2540
+ } catch (err) {
2541
+ emit({ type: "exit", code: null, error: getErrorMessage(err), ms: 0 });
2542
+ res.end();
2543
+ return;
2544
+ }
2545
+ child.stdout?.on("data", (d) => emit({ type: "out", text: d.toString() }));
2546
+ child.stderr?.on("data", (d) => emit({ type: "err", text: d.toString() }));
2547
+ const timer = setTimeout(() => child.kill(), CLI_TIMEOUT_MS);
2548
+ child.on("error", (err) => {
2549
+ emit({ type: "exit", code: null, error: err.message, ms: Date.now() - started });
2550
+ res.end();
2551
+ });
2552
+ child.on("close", (code) => {
2553
+ clearTimeout(timer);
2554
+ emit({ type: "exit", code, ms: Date.now() - started });
2555
+ res.end();
2556
+ });
2557
+ req.on("close", () => {
2558
+ clearTimeout(timer);
2559
+ if (child.exitCode === null) child.kill();
2560
+ });
2561
+ }
2562
+ },
2563
+ { path: "/api/packs", handle: async ({ res }) => json(res, 200, await describePacks(ctx.projectDir())) },
2564
+ { path: "/api/export/targets", handle: async ({ res }) => json(res, 200, await listTargets(ctx.projectDir())) },
2565
+ {
2566
+ method: "POST",
2567
+ path: "/api/export",
2568
+ handle: async ({ res, body }) => {
2569
+ const b = await body();
2570
+ const target = ctx.inProject(String(b.file));
2571
+ if (!target) return json(res, 400, { error: "file is outside the project" });
2572
+ try {
2573
+ return json(res, 200, await runExport(ctx.projectDir(), {
2574
+ file: target,
2575
+ name: String(b.name),
2576
+ target: String(b.target),
2577
+ outputDir: typeof b.outputDir === "string" && b.outputDir ? path12.resolve(ctx.projectDir(), b.outputDir) : void 0,
2578
+ preview: b.preview !== false
2579
+ }));
2580
+ } catch (err) {
2581
+ return json(res, 400, { error: getErrorMessage(err) });
2582
+ }
2583
+ }
2584
+ },
2585
+ // The project as a pack: cheap to detect, slow to check (every source
2586
+ // file is parsed), so the check is a separate call made on request.
2587
+ { path: "/api/pack-project", handle: ({ res }) => json(res, 200, detectPackProject(ctx.projectDir())) },
2588
+ {
2589
+ path: "/api/pack-project/check",
2590
+ handle: async ({ res }) => {
2591
+ if (!detectPackProject(ctx.projectDir()).isPack) return json(res, 400, { error: "the project is not a pack" });
2592
+ try {
2593
+ return json(res, 200, await checkPackProject(ctx.projectDir()));
2594
+ } catch (err) {
2595
+ return json(res, 400, { error: getErrorMessage(err) });
2596
+ }
2597
+ }
2598
+ },
2599
+ // The marketplace is npm: a search goes to the registry, and installing
2600
+ // is `fw market install`, which the command-line pane runs when asked
2601
+ // to. Every registry the project's npm uses is searched, credentials
2602
+ // included: a private pack is on a private registry, and .npmrc says which.
2603
+ {
2604
+ path: "/api/market/search",
2605
+ handle: async ({ res, q }) => json(res, 200, await searchAllRegistries({ query: q("q") || void 0, limit: 30, projectDir: ctx.projectDir() }))
2606
+ },
2607
+ // Everything around the project: services alive, MCP registrations,
2608
+ // the environment and registries. Probes are brief.
2609
+ { path: "/api/status", handle: async ({ res }) => json(res, 200, await describeStatus(ctx.projectDir(), ctx.status())) }
2610
+ ];
2611
+ }
2612
+
2613
+ // src/console/routes-runs.ts
2614
+ async function debugAction(ctx, id, { res, body }) {
2615
+ const { debug } = ctx.runs;
2616
+ const d = debug.get(id);
2617
+ if (!d) return json(res, 404, { error: "not a debug session" });
2618
+ const b = await body();
2619
+ const action = String(b.action);
2620
+ try {
2621
+ if (action === "step" || action === "continue" || action === "toBreakpoint") {
2622
+ if (d.status !== "paused") return json(res, 400, { error: `the session is ${d.status}, not paused` });
2623
+ const move = action === "step" ? debug.step(id) : debug.continue(id, action === "toBreakpoint");
2624
+ move.catch(() => void 0);
2625
+ } else if (action === "abort") {
2626
+ debug.abort(id).catch(() => void 0);
2627
+ } else if (action === "set") {
2628
+ debug.setVariable(id, String(b.node), String(b.port), b.value);
2629
+ ctx.runs.announce(id, { type: "event", t: Date.now(), e: { type: "VARIABLE_SET", identifier: { id: String(b.node), portName: String(b.port) }, value: b.value } });
2630
+ } else if (action === "breakpoint") {
2631
+ debug.breakpoint(id, b.op === "remove" ? "remove" : "add", String(b.node));
2632
+ } else {
2633
+ return json(res, 400, { error: `unknown action ${action}` });
2634
+ }
2635
+ return json(res, 200, await ctx.runs.snapshot(id));
2636
+ } catch (err) {
2637
+ return json(res, 400, { error: getErrorMessage(err) });
2638
+ }
2639
+ }
2640
+ function runRoutes(ctx) {
2641
+ const { runs } = ctx;
2642
+ return [
2643
+ { method: "GET", path: "/api/runs", handle: async ({ res, q }) => json(res, 200, await runs.list(q("file"), q("name"))) },
2644
+ {
2645
+ method: "POST",
2646
+ path: "/api/runs",
2647
+ handle: async ({ res, body }) => {
2648
+ const b = await body();
2649
+ const target = ctx.inProject(String(b.file));
2650
+ if (!target) return json(res, 400, { error: "file is outside the project" });
2651
+ const mocks = mocksFrom(b);
2652
+ const source = await stamp(target).catch(() => void 0);
2653
+ const params = b.params ?? {};
2654
+ if (b.debug === true) {
2655
+ const bps = Array.isArray(b.breakpoints) ? b.breakpoints.filter((x) => typeof x === "string") : [];
2656
+ return json(res, 200, runs.startDebug(target, String(b.name), params, bps, mocks, b.runTo === "breakpoint" ? "breakpoint" : "first", source));
2657
+ }
2658
+ return json(res, 200, await runs.start(target, String(b.name), params, mocks, source, b.agents === "manual" ? "manual" : "auto"));
2659
+ }
2660
+ },
2661
+ {
2662
+ path: /^\/api\/runs\/([^/]+)(?:\/(events|resolve|cancel|debug|agent))?$/,
2663
+ handle: async (call) => {
2664
+ const { req, res, q, body, match } = call;
2665
+ const id = match[1];
2666
+ const sub = match[2];
2667
+ if (!await runs.snapshot(id)) return json(res, 404, { error: "no such run" });
2668
+ if (!sub && req.method === "DELETE") {
2669
+ try {
2670
+ await runs.remove(id);
2671
+ } catch (err) {
2672
+ return json(res, 409, { error: getErrorMessage(err) });
2673
+ }
2674
+ return json(res, 200, { removed: id });
2675
+ }
2676
+ if (sub === "events") return runs.watch(id, req, res);
2677
+ if (sub === "resolve" && req.method === "POST") {
2678
+ try {
2679
+ await runs.resume(id, await body());
2680
+ return json(res, 200, await runs.snapshot(id));
2681
+ } catch (err) {
2682
+ return json(res, 400, { error: getErrorMessage(err) });
2683
+ }
2684
+ }
2685
+ if (sub === "agent" && req.method === "POST") {
2686
+ const refused = await runs.askAgent(id);
2687
+ if (refused) return json(res, 409, { error: refused });
2688
+ return json(res, 200, await runs.snapshot(id));
2689
+ }
2690
+ if (sub === "agent" && req.method === "GET") {
2691
+ const rec = await ctx.runs.record(id);
2692
+ const gateId = q("gate") || rec?.agent?.gateId;
2693
+ const kept = gateId ? await ctx.runs.kept(id, transcriptName(gateId)) : void 0;
2694
+ if (!kept) return json(res, 404, { error: "no agent has answered this run" });
2695
+ return json(res, 200, kept);
2696
+ }
2697
+ if (sub === "cancel" && req.method === "POST") {
2698
+ await runs.cancel(id);
2699
+ return json(res, 200, await runs.snapshot(id));
2700
+ }
2701
+ if (sub === "debug" && req.method === "POST") return debugAction(ctx, id, call);
2702
+ return json(res, 200, await runs.withEvents(id));
2703
+ }
2704
+ }
2705
+ ];
2706
+ }
2707
+
2708
+ // src/console/router.ts
2709
+ function findRoute(routes, method, pathname) {
2710
+ for (const route of routes) {
2711
+ if (route.method && route.method !== method) continue;
2712
+ if (typeof route.path === "string") {
2713
+ if (route.path === pathname) return { route, match: [] };
2714
+ } else {
2715
+ const match = pathname.match(route.path);
2716
+ if (match) return { route, match };
2717
+ }
2718
+ }
2719
+ return void 0;
2720
+ }
2721
+
2722
+ // src/console/request-guard.ts
2723
+ var SAFE_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
2724
+ function hostName(host) {
2725
+ const bracketed = host.match(/^\[[^\]]*\]/);
2726
+ return (bracketed ? bracketed[0] : host.replace(/:\d*$/, "")).toLowerCase();
2727
+ }
2728
+ function refusal(req, bound) {
2729
+ const host = typeof req.headers.host === "string" ? req.headers.host : "";
2730
+ if (!host) return "the request has no Host header";
2731
+ if (isLoopback(bound) && !isLoopback(hostName(host))) {
2732
+ return `the console answers only to a loopback Host, not ${host}`;
2733
+ }
2734
+ const origin = req.headers.origin;
2735
+ if (origin === void 0 || SAFE_METHODS.has((req.method ?? "GET").toUpperCase())) return void 0;
2736
+ if (origin !== `http://${host}`) {
2737
+ return `a change is accepted only from the console's own origin, not ${String(origin)}`;
2738
+ }
2739
+ return void 0;
2740
+ }
2741
+
2742
+ // src/console/server.ts
2743
+ function resolveAssets(explicit) {
2744
+ const here = path13.dirname(fileURLToPath2(import.meta.url));
2745
+ const candidates = [explicit, here, path13.join(here, "..", "console"), path13.join(here, "..", "..", "dist", "console")].filter(Boolean);
2746
+ return candidates.find((dir) => fs13.existsSync(path13.join(dir, "index.html")) && fs13.existsSync(path13.join(dir, "app.js")));
2747
+ }
2748
+ async function devBuild(onRebuilt) {
2749
+ const here = path13.dirname(fileURLToPath2(import.meta.url));
2750
+ const uiDir = path13.join(here, "..", "..", "console-ui");
2751
+ if (!fs13.existsSync(path13.join(uiDir, "src", "main.tsx"))) return void 0;
2752
+ let esbuild;
2753
+ try {
2754
+ esbuild = await import("esbuild");
2755
+ } catch {
2756
+ return void 0;
2757
+ }
2758
+ const out = path13.join(here, "..", "..", "dist", ".console-dev");
2759
+ fs13.mkdirSync(out, { recursive: true });
2760
+ const ctx = await esbuild.context({
2761
+ entryPoints: [path13.join(uiDir, "src", "main.tsx")],
2762
+ bundle: true,
2763
+ outfile: path13.join(out, "app.js"),
2764
+ format: "esm",
2765
+ target: "es2022",
2766
+ jsx: "automatic",
2767
+ jsxImportSource: "preact",
2768
+ sourcemap: "inline",
2769
+ logLevel: "warning",
2770
+ absWorkingDir: uiDir,
2771
+ plugins: [{ name: "reload", setup(b) {
2772
+ b.onEnd((res) => {
2773
+ if (!res.errors.length) onRebuilt();
2774
+ });
2775
+ } }]
2776
+ });
2777
+ await ctx.watch();
2778
+ const chokidar = await import("chokidar");
2779
+ chokidar.watch([path13.join(uiDir, "index.html"), path13.join(uiDir, "styles.css")], { ignoreInitial: true }).on("all", onRebuilt);
2780
+ return { serveFrom: uiDir, scriptFrom: out };
2781
+ }
2782
+ function within(root, p) {
2783
+ if (!p) return null;
2784
+ const abs = path13.resolve(p);
2785
+ const fold = (x) => path13.sep === "\\" || process.platform === "darwin" ? x.toLowerCase() : x;
2786
+ const a = fold(abs);
2787
+ const r = fold(root);
2788
+ return a === r || a.startsWith(r + path13.sep) ? abs : null;
2789
+ }
2790
+ async function createConsoleServer(options) {
2791
+ let projectDir = path13.resolve(options.projectDir);
2792
+ const host = options.host ?? "127.0.0.1";
2793
+ const port = options.port ?? 4311;
2794
+ const watching = options.watch !== false;
2795
+ const followers = /* @__PURE__ */ new Set();
2796
+ const broadcast = (msg) => {
2797
+ for (const res of followers) send(res, msg);
2798
+ };
2799
+ const runsDir = defaultRunsDir(projectDir);
2800
+ const coordinator = createLocalCoordinator(options.store ? { store: options.store } : { rootDir: runsDir });
2801
+ await reclaimStaleAgentAnswers(coordinator).catch(() => void 0);
2802
+ const profiles = createProfileCache(() => projectDir);
2803
+ const runs = createRunDriver({ coordinator, broadcast, projectDir: () => projectDir, profiles: () => profiles.get() });
2804
+ const superviseFor = (dir) => new Supervisor({
2805
+ projectDir: dir,
2806
+ ...options.services,
2807
+ onChange: (e) => {
2808
+ if (!e.line) broadcast({ type: "services", kind: e.kind, state: e.state, url: e.url ?? null, exitCode: e.exitCode ?? null, error: e.error ?? null });
2809
+ }
2810
+ });
2811
+ let supervisor = superviseFor(projectDir);
2812
+ let checking;
2813
+ function queueCheck() {
2814
+ if (checking) return;
2815
+ const dir = projectDir;
2816
+ checking = checkWorkflows(dir, (summary) => {
2817
+ if (dir === projectDir) broadcast({ type: "checked", workflow: runs.withWaiting(summary) });
2818
+ }).then(() => void 0).catch(() => void 0).finally(() => {
2819
+ checking = void 0;
2820
+ });
2821
+ }
2822
+ let watcher;
2823
+ async function watchProject() {
2824
+ if (!watching) return;
2825
+ await watcher?.close();
2826
+ const chokidar = await import("chokidar");
2827
+ watcher = chokidar.watch(projectDir, {
2828
+ ignoreInitial: true,
2829
+ ignored: (p) => /(^|[\\/])(node_modules|dist|\.git|\.fw)([\\/]|$)/.test(p) || /(^|[\\/])\.fw-diff-/.test(p)
2830
+ });
2831
+ watcher.on("all", (_event, file) => {
2832
+ if (typeof file === "string" && file.endsWith(".ts")) {
2833
+ invalidateListing(projectDir);
2834
+ broadcast({ type: "changed", file });
2835
+ }
2836
+ });
2837
+ }
2838
+ await watchProject();
2839
+ await loadPackDocTopics(projectDir).catch(() => 0);
2840
+ await runs.follow({ watching, runsDir: options.store ? void 0 : runsDir });
2841
+ const heartbeat = setInterval(() => {
2842
+ for (const res of followers) res.write(": ping\n\n");
2843
+ runs.ping();
2844
+ }, 15e3);
2845
+ const dev = options.assetsDir ? void 0 : await devBuild(() => broadcast({ type: "client" }));
2846
+ const built = dev ? void 0 : resolveAssets(options.assetsDir);
2847
+ if (!built && !dev) throw new Error("console client not found: run `npm run build:console`, or pass assetsDir");
2848
+ let actualPort = port;
2849
+ const ctx = {
2850
+ projectDir: () => projectDir,
2851
+ async openProject(dir) {
2852
+ projectDir = dir;
2853
+ invalidateListing(projectDir);
2854
+ await supervisor.close().catch(() => void 0);
2855
+ supervisor = superviseFor(projectDir);
2856
+ await watchProject();
2857
+ await loadPackDocTopics(projectDir).catch(() => 0);
2858
+ options.onProject?.(projectDir);
2859
+ broadcast({ type: "project" });
2860
+ },
2861
+ inProject: (p) => within(projectDir, p),
2862
+ broadcast,
2863
+ followers,
2864
+ queueCheck,
2865
+ supervisor: () => supervisor,
2866
+ profiles,
2867
+ runs,
2868
+ status: () => ({ url: `http://${host}:${actualPort}`, watching, runsDir: options.store ? "a run store of your own" : runsDir }),
2869
+ client: { pageDir: dev?.serveFrom ?? built, scriptDir: dev?.scriptFrom ?? built }
2870
+ };
2871
+ const routes = [...projectRoutes(ctx), ...toolRoutes(ctx), ...agentRoutes(ctx), ...serviceRoutes(ctx), ...runRoutes(ctx)];
2872
+ const handle = async (req, res) => {
2873
+ const refused = refusal(req, host);
2874
+ if (refused) return json(res, 403, { error: refused });
2875
+ let url;
2876
+ try {
2877
+ url = new URL(req.url ?? "/", `http://${host}`);
2878
+ } catch {
2879
+ return json(res, 400, { error: "the request target is not a valid URL" });
2880
+ }
2881
+ try {
2882
+ const found = findRoute(routes, req.method ?? "GET", url.pathname);
2883
+ if (!found) return json(res, 404, { error: "not found" });
2884
+ await found.route.handle({ req, res, url, match: found.match, q: (k) => url.searchParams.get(k) ?? "", body: () => readBody(req) });
2885
+ } catch (err) {
2886
+ if (res.headersSent) {
2887
+ res.destroy();
2888
+ return;
2889
+ }
2890
+ json(res, err instanceof BadRequest ? 400 : 500, { error: getErrorMessage(err) });
2891
+ }
2892
+ };
2893
+ const server = http.createServer((req, res) => {
2894
+ handle(req, res).catch(() => res.destroy());
2895
+ });
2896
+ await new Promise((resolve9, reject) => {
2897
+ server.once("error", reject);
2898
+ server.listen(port, host, () => resolve9());
2899
+ });
2900
+ const address = server.address();
2901
+ actualPort = typeof address === "object" && address ? address.port : port;
2902
+ for (const kind of ["serve", "watch"]) {
2903
+ if (supervisor.settings()[kind].autoStart) {
2904
+ try {
2905
+ supervisor.start(kind);
2906
+ } catch {
2907
+ }
2908
+ }
2909
+ }
2910
+ return {
2911
+ url: `http://${host}:${actualPort}`,
2912
+ async close() {
2913
+ clearInterval(heartbeat);
2914
+ await supervisor.close().catch(() => void 0);
2915
+ await watcher?.close();
2916
+ await runs.close();
2917
+ for (const res of followers) res.end();
2918
+ await new Promise((resolve9) => server.close(() => resolve9()));
2919
+ }
2920
+ };
2921
+ }
2922
+ export {
2923
+ createConsoleServer,
2924
+ stepLabel
2925
+ };