@synergenius/flow-weaver 0.2.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 (466) hide show
  1. package/LICENSE +122 -0
  2. package/README.md +315 -0
  3. package/dist/annotation-generator.d.ts +45 -0
  4. package/dist/annotation-generator.js +557 -0
  5. package/dist/api/builder.d.ts +223 -0
  6. package/dist/api/builder.js +345 -0
  7. package/dist/api/compile.d.ts +92 -0
  8. package/dist/api/compile.js +149 -0
  9. package/dist/api/extract-types.d.ts +29 -0
  10. package/dist/api/extract-types.js +57 -0
  11. package/dist/api/generate-in-place.d.ts +73 -0
  12. package/dist/api/generate-in-place.js +1353 -0
  13. package/dist/api/generate.d.ts +83 -0
  14. package/dist/api/generate.js +510 -0
  15. package/dist/api/helpers.d.ts +248 -0
  16. package/dist/api/helpers.js +285 -0
  17. package/dist/api/index.d.ts +46 -0
  18. package/dist/api/index.js +45 -0
  19. package/dist/api/inline-runtime.d.ts +27 -0
  20. package/dist/api/inline-runtime.js +551 -0
  21. package/dist/api/manipulation/connections.d.ts +79 -0
  22. package/dist/api/manipulation/connections.js +151 -0
  23. package/dist/api/manipulation/index.d.ts +34 -0
  24. package/dist/api/manipulation/index.js +41 -0
  25. package/dist/api/manipulation/node-types.d.ts +123 -0
  26. package/dist/api/manipulation/node-types.js +200 -0
  27. package/dist/api/manipulation/nodes.d.ts +144 -0
  28. package/dist/api/manipulation/nodes.js +333 -0
  29. package/dist/api/manipulation/ports.d.ts +59 -0
  30. package/dist/api/manipulation/ports.js +228 -0
  31. package/dist/api/manipulation/scopes.d.ts +52 -0
  32. package/dist/api/manipulation/scopes.js +156 -0
  33. package/dist/api/manipulation/validation.d.ts +6 -0
  34. package/dist/api/manipulation/validation.js +6 -0
  35. package/dist/api/manipulation/workflow.d.ts +81 -0
  36. package/dist/api/manipulation/workflow.js +116 -0
  37. package/dist/api/manipulation.d.ts +8 -0
  38. package/dist/api/manipulation.js +8 -0
  39. package/dist/api/parse.d.ts +48 -0
  40. package/dist/api/parse.js +110 -0
  41. package/dist/api/patterns.d.ts +112 -0
  42. package/dist/api/patterns.js +306 -0
  43. package/dist/api/query.d.ts +429 -0
  44. package/dist/api/query.js +816 -0
  45. package/dist/api/templates.d.ts +98 -0
  46. package/dist/api/templates.js +117 -0
  47. package/dist/api/transform.d.ts +31 -0
  48. package/dist/api/transform.js +40 -0
  49. package/dist/api/validate.d.ts +25 -0
  50. package/dist/api/validate.js +39 -0
  51. package/dist/api/workflow-file-operations.d.ts +29 -0
  52. package/dist/api/workflow-file-operations.js +180 -0
  53. package/dist/ast/builder.d.ts +210 -0
  54. package/dist/ast/builder.js +395 -0
  55. package/dist/ast/index.d.ts +5 -0
  56. package/dist/ast/index.js +5 -0
  57. package/dist/ast/serialization-node.d.ts +6 -0
  58. package/dist/ast/serialization-node.js +30 -0
  59. package/dist/ast/serialization.d.ts +43 -0
  60. package/dist/ast/serialization.js +134 -0
  61. package/dist/ast/types.d.ts +852 -0
  62. package/dist/ast/types.js +2 -0
  63. package/dist/ast/workflow-utils.d.ts +54 -0
  64. package/dist/ast/workflow-utils.js +114 -0
  65. package/dist/body-generator.d.ts +31 -0
  66. package/dist/body-generator.js +35 -0
  67. package/dist/built-in-nodes/delay.d.ts +11 -0
  68. package/dist/built-in-nodes/delay.js +29 -0
  69. package/dist/built-in-nodes/index.d.ts +5 -0
  70. package/dist/built-in-nodes/index.js +4 -0
  71. package/dist/built-in-nodes/invoke-workflow.d.ts +13 -0
  72. package/dist/built-in-nodes/invoke-workflow.js +25 -0
  73. package/dist/built-in-nodes/mock-types.d.ts +18 -0
  74. package/dist/built-in-nodes/mock-types.js +12 -0
  75. package/dist/built-in-nodes/wait-for-event.d.ts +13 -0
  76. package/dist/built-in-nodes/wait-for-event.js +25 -0
  77. package/dist/chevrotain-parser/connect-parser.d.ts +24 -0
  78. package/dist/chevrotain-parser/connect-parser.js +98 -0
  79. package/dist/chevrotain-parser/grammar-diagrams.d.ts +29 -0
  80. package/dist/chevrotain-parser/grammar-diagrams.js +264 -0
  81. package/dist/chevrotain-parser/index.d.ts +25 -0
  82. package/dist/chevrotain-parser/index.js +27 -0
  83. package/dist/chevrotain-parser/map-parser.d.ts +33 -0
  84. package/dist/chevrotain-parser/map-parser.js +130 -0
  85. package/dist/chevrotain-parser/node-parser.d.ts +36 -0
  86. package/dist/chevrotain-parser/node-parser.js +466 -0
  87. package/dist/chevrotain-parser/path-parser.d.ts +28 -0
  88. package/dist/chevrotain-parser/path-parser.js +118 -0
  89. package/dist/chevrotain-parser/port-parser.d.ts +36 -0
  90. package/dist/chevrotain-parser/port-parser.js +442 -0
  91. package/dist/chevrotain-parser/position-parser.d.ts +20 -0
  92. package/dist/chevrotain-parser/position-parser.js +83 -0
  93. package/dist/chevrotain-parser/scope-parser.d.ts +19 -0
  94. package/dist/chevrotain-parser/scope-parser.js +104 -0
  95. package/dist/chevrotain-parser/tokens.d.ts +78 -0
  96. package/dist/chevrotain-parser/tokens.js +384 -0
  97. package/dist/chevrotain-parser/trigger-cancel-parser.d.ts +50 -0
  98. package/dist/chevrotain-parser/trigger-cancel-parser.js +282 -0
  99. package/dist/cli/commands/changelog.d.ts +13 -0
  100. package/dist/cli/commands/changelog.js +135 -0
  101. package/dist/cli/commands/compile.d.ts +64 -0
  102. package/dist/cli/commands/compile.js +278 -0
  103. package/dist/cli/commands/create.d.ts +33 -0
  104. package/dist/cli/commands/create.js +147 -0
  105. package/dist/cli/commands/describe.d.ts +68 -0
  106. package/dist/cli/commands/describe.js +377 -0
  107. package/dist/cli/commands/dev.d.ts +32 -0
  108. package/dist/cli/commands/dev.js +384 -0
  109. package/dist/cli/commands/diagram.d.ts +13 -0
  110. package/dist/cli/commands/diagram.js +33 -0
  111. package/dist/cli/commands/diff.d.ts +11 -0
  112. package/dist/cli/commands/diff.js +59 -0
  113. package/dist/cli/commands/doctor.d.ts +57 -0
  114. package/dist/cli/commands/doctor.js +719 -0
  115. package/dist/cli/commands/export.d.ts +57 -0
  116. package/dist/cli/commands/export.js +163 -0
  117. package/dist/cli/commands/grammar.d.ts +9 -0
  118. package/dist/cli/commands/grammar.js +39 -0
  119. package/dist/cli/commands/init.d.ts +59 -0
  120. package/dist/cli/commands/init.js +435 -0
  121. package/dist/cli/commands/listen.d.ts +16 -0
  122. package/dist/cli/commands/listen.js +39 -0
  123. package/dist/cli/commands/market.d.ts +52 -0
  124. package/dist/cli/commands/market.js +436 -0
  125. package/dist/cli/commands/migrate.d.ts +13 -0
  126. package/dist/cli/commands/migrate.js +89 -0
  127. package/dist/cli/commands/openapi.d.ts +37 -0
  128. package/dist/cli/commands/openapi.js +67 -0
  129. package/dist/cli/commands/pattern.d.ts +34 -0
  130. package/dist/cli/commands/pattern.js +185 -0
  131. package/dist/cli/commands/plugin.d.ts +16 -0
  132. package/dist/cli/commands/plugin.js +176 -0
  133. package/dist/cli/commands/run.d.ts +49 -0
  134. package/dist/cli/commands/run.js +191 -0
  135. package/dist/cli/commands/serve.d.ts +45 -0
  136. package/dist/cli/commands/serve.js +81 -0
  137. package/dist/cli/commands/templates.d.ts +8 -0
  138. package/dist/cli/commands/templates.js +54 -0
  139. package/dist/cli/commands/ui.d.ts +16 -0
  140. package/dist/cli/commands/ui.js +130 -0
  141. package/dist/cli/commands/validate.d.ts +12 -0
  142. package/dist/cli/commands/validate.js +247 -0
  143. package/dist/cli/commands/watch.d.ts +9 -0
  144. package/dist/cli/commands/watch.js +70 -0
  145. package/dist/cli/flow-weaver.mjs +92924 -0
  146. package/dist/cli/index.d.ts +9 -0
  147. package/dist/cli/index.js +742 -0
  148. package/dist/cli/templates/ai/mock-provider.d.ts +7 -0
  149. package/dist/cli/templates/ai/mock-provider.js +64 -0
  150. package/dist/cli/templates/ai/types.d.ts +47 -0
  151. package/dist/cli/templates/ai/types.js +5 -0
  152. package/dist/cli/templates/approvals/index.d.ts +15 -0
  153. package/dist/cli/templates/approvals/index.js +241 -0
  154. package/dist/cli/templates/index.d.ts +102 -0
  155. package/dist/cli/templates/index.js +101 -0
  156. package/dist/cli/templates/nodes/agent-router.d.ts +3 -0
  157. package/dist/cli/templates/nodes/agent-router.js +114 -0
  158. package/dist/cli/templates/nodes/aggregator.d.ts +7 -0
  159. package/dist/cli/templates/nodes/aggregator.js +63 -0
  160. package/dist/cli/templates/nodes/conversation-memory.d.ts +3 -0
  161. package/dist/cli/templates/nodes/conversation-memory.js +85 -0
  162. package/dist/cli/templates/nodes/http.d.ts +7 -0
  163. package/dist/cli/templates/nodes/http.js +80 -0
  164. package/dist/cli/templates/nodes/human-approval.d.ts +3 -0
  165. package/dist/cli/templates/nodes/human-approval.js +110 -0
  166. package/dist/cli/templates/nodes/json-extractor.d.ts +3 -0
  167. package/dist/cli/templates/nodes/json-extractor.js +119 -0
  168. package/dist/cli/templates/nodes/llm-call.d.ts +3 -0
  169. package/dist/cli/templates/nodes/llm-call.js +106 -0
  170. package/dist/cli/templates/nodes/prompt-template.d.ts +3 -0
  171. package/dist/cli/templates/nodes/prompt-template.js +52 -0
  172. package/dist/cli/templates/nodes/rag-retriever.d.ts +3 -0
  173. package/dist/cli/templates/nodes/rag-retriever.js +128 -0
  174. package/dist/cli/templates/nodes/tool-executor.d.ts +3 -0
  175. package/dist/cli/templates/nodes/tool-executor.js +108 -0
  176. package/dist/cli/templates/nodes/transformer.d.ts +7 -0
  177. package/dist/cli/templates/nodes/transformer.js +68 -0
  178. package/dist/cli/templates/nodes/validator.d.ts +7 -0
  179. package/dist/cli/templates/nodes/validator.js +62 -0
  180. package/dist/cli/templates/providers/index.d.ts +14 -0
  181. package/dist/cli/templates/providers/index.js +239 -0
  182. package/dist/cli/templates/shared/approval-types.d.ts +9 -0
  183. package/dist/cli/templates/shared/approval-types.js +31 -0
  184. package/dist/cli/templates/shared/llm-types.d.ts +15 -0
  185. package/dist/cli/templates/shared/llm-types.js +104 -0
  186. package/dist/cli/templates/workflows/aggregator.d.ts +7 -0
  187. package/dist/cli/templates/workflows/aggregator.js +104 -0
  188. package/dist/cli/templates/workflows/ai-agent-durable.d.ts +8 -0
  189. package/dist/cli/templates/workflows/ai-agent-durable.js +338 -0
  190. package/dist/cli/templates/workflows/ai-agent.d.ts +31 -0
  191. package/dist/cli/templates/workflows/ai-agent.js +326 -0
  192. package/dist/cli/templates/workflows/ai-chat.d.ts +7 -0
  193. package/dist/cli/templates/workflows/ai-chat.js +169 -0
  194. package/dist/cli/templates/workflows/ai-pipeline-durable.d.ts +8 -0
  195. package/dist/cli/templates/workflows/ai-pipeline-durable.js +330 -0
  196. package/dist/cli/templates/workflows/ai-rag.d.ts +7 -0
  197. package/dist/cli/templates/workflows/ai-rag.js +186 -0
  198. package/dist/cli/templates/workflows/ai-react.d.ts +7 -0
  199. package/dist/cli/templates/workflows/ai-react.js +294 -0
  200. package/dist/cli/templates/workflows/conditional.d.ts +12 -0
  201. package/dist/cli/templates/workflows/conditional.js +142 -0
  202. package/dist/cli/templates/workflows/error-handler.d.ts +7 -0
  203. package/dist/cli/templates/workflows/error-handler.js +147 -0
  204. package/dist/cli/templates/workflows/foreach.d.ts +7 -0
  205. package/dist/cli/templates/workflows/foreach.js +143 -0
  206. package/dist/cli/templates/workflows/sequential.d.ts +7 -0
  207. package/dist/cli/templates/workflows/sequential.js +198 -0
  208. package/dist/cli/templates/workflows/webhook.d.ts +7 -0
  209. package/dist/cli/templates/workflows/webhook.js +161 -0
  210. package/dist/cli/utils/logger.d.ts +15 -0
  211. package/dist/cli/utils/logger.js +46 -0
  212. package/dist/constants.d.ts +100 -0
  213. package/dist/constants.js +125 -0
  214. package/dist/defaults.d.ts +3 -0
  215. package/dist/defaults.js +3 -0
  216. package/dist/deployment/config/defaults.d.ts +29 -0
  217. package/dist/deployment/config/defaults.js +98 -0
  218. package/dist/deployment/config/loader.d.ts +24 -0
  219. package/dist/deployment/config/loader.js +236 -0
  220. package/dist/deployment/config/types.d.ts +117 -0
  221. package/dist/deployment/config/types.js +5 -0
  222. package/dist/deployment/core/adapters.d.ts +90 -0
  223. package/dist/deployment/core/adapters.js +251 -0
  224. package/dist/deployment/core/executor.d.ts +62 -0
  225. package/dist/deployment/core/executor.js +197 -0
  226. package/dist/deployment/core/formatters.d.ts +57 -0
  227. package/dist/deployment/core/formatters.js +170 -0
  228. package/dist/deployment/index.d.ts +31 -0
  229. package/dist/deployment/index.js +48 -0
  230. package/dist/deployment/openapi/generator.d.ts +146 -0
  231. package/dist/deployment/openapi/generator.js +347 -0
  232. package/dist/deployment/openapi/schema-converter.d.ts +49 -0
  233. package/dist/deployment/openapi/schema-converter.js +192 -0
  234. package/dist/deployment/targets/base.d.ts +316 -0
  235. package/dist/deployment/targets/base.js +823 -0
  236. package/dist/deployment/targets/cloudflare.d.ts +23 -0
  237. package/dist/deployment/targets/cloudflare.js +1125 -0
  238. package/dist/deployment/targets/inngest.d.ts +38 -0
  239. package/dist/deployment/targets/inngest.js +926 -0
  240. package/dist/deployment/targets/lambda.d.ts +23 -0
  241. package/dist/deployment/targets/lambda.js +1289 -0
  242. package/dist/deployment/targets/vercel.d.ts +23 -0
  243. package/dist/deployment/targets/vercel.js +886 -0
  244. package/dist/deployment/types.d.ts +183 -0
  245. package/dist/deployment/types.js +8 -0
  246. package/dist/diagram/geometry.d.ts +26 -0
  247. package/dist/diagram/geometry.js +850 -0
  248. package/dist/diagram/index.d.ts +16 -0
  249. package/dist/diagram/index.js +42 -0
  250. package/dist/diagram/layout.d.ts +11 -0
  251. package/dist/diagram/layout.js +143 -0
  252. package/dist/diagram/orthogonal-router.d.ts +79 -0
  253. package/dist/diagram/orthogonal-router.js +568 -0
  254. package/dist/diagram/renderer.d.ts +3 -0
  255. package/dist/diagram/renderer.js +207 -0
  256. package/dist/diagram/theme.d.ts +20 -0
  257. package/dist/diagram/theme.js +189 -0
  258. package/dist/diagram/types.d.ts +70 -0
  259. package/dist/diagram/types.js +2 -0
  260. package/dist/diff/WorkflowDiffer.d.ts +13 -0
  261. package/dist/diff/WorkflowDiffer.js +429 -0
  262. package/dist/diff/formatDiff.d.ts +10 -0
  263. package/dist/diff/formatDiff.js +220 -0
  264. package/dist/diff/impact.d.ts +29 -0
  265. package/dist/diff/impact.js +119 -0
  266. package/dist/diff/index.d.ts +10 -0
  267. package/dist/diff/index.js +9 -0
  268. package/dist/diff/types.d.ts +138 -0
  269. package/dist/diff/types.js +35 -0
  270. package/dist/doc-metadata/extractors/annotations.d.ts +56 -0
  271. package/dist/doc-metadata/extractors/annotations.js +337 -0
  272. package/dist/doc-metadata/extractors/cli-commands.d.ts +17 -0
  273. package/dist/doc-metadata/extractors/cli-commands.js +355 -0
  274. package/dist/doc-metadata/extractors/mcp-tools.d.ts +16 -0
  275. package/dist/doc-metadata/extractors/mcp-tools.js +689 -0
  276. package/dist/doc-metadata/extractors/plugin-api.d.ts +19 -0
  277. package/dist/doc-metadata/extractors/plugin-api.js +279 -0
  278. package/dist/doc-metadata/index.d.ts +5 -0
  279. package/dist/doc-metadata/index.js +4 -0
  280. package/dist/doc-metadata/types.d.ts +120 -0
  281. package/dist/doc-metadata/types.js +5 -0
  282. package/dist/editor-completions/annotationValues.d.ts +12 -0
  283. package/dist/editor-completions/annotationValues.js +138 -0
  284. package/dist/editor-completions/contextParser.d.ts +40 -0
  285. package/dist/editor-completions/contextParser.js +410 -0
  286. package/dist/editor-completions/dataTypes.d.ts +16 -0
  287. package/dist/editor-completions/dataTypes.js +95 -0
  288. package/dist/editor-completions/goToDefinition.d.ts +27 -0
  289. package/dist/editor-completions/goToDefinition.js +112 -0
  290. package/dist/editor-completions/index.d.ts +39 -0
  291. package/dist/editor-completions/index.js +181 -0
  292. package/dist/editor-completions/jsDocAnnotations.d.ts +29 -0
  293. package/dist/editor-completions/jsDocAnnotations.js +357 -0
  294. package/dist/editor-completions/modifierCompletions.d.ts +17 -0
  295. package/dist/editor-completions/modifierCompletions.js +197 -0
  296. package/dist/editor-completions/types.d.ts +119 -0
  297. package/dist/editor-completions/types.js +8 -0
  298. package/dist/export/index.d.ts +68 -0
  299. package/dist/export/index.js +1074 -0
  300. package/dist/export/templates.d.ts +24 -0
  301. package/dist/export/templates.js +186 -0
  302. package/dist/friendly-errors.d.ts +35 -0
  303. package/dist/friendly-errors.js +375 -0
  304. package/dist/function-like.d.ts +38 -0
  305. package/dist/function-like.js +83 -0
  306. package/dist/generated-branding.d.ts +16 -0
  307. package/dist/generated-branding.js +22 -0
  308. package/dist/generator/async-detection.d.ts +27 -0
  309. package/dist/generator/async-detection.js +56 -0
  310. package/dist/generator/code-utils.d.ts +76 -0
  311. package/dist/generator/code-utils.js +410 -0
  312. package/dist/generator/control-flow.d.ts +54 -0
  313. package/dist/generator/control-flow.js +284 -0
  314. package/dist/generator/inngest.d.ts +53 -0
  315. package/dist/generator/inngest.js +1126 -0
  316. package/dist/generator/scope-function-generator.d.ts +78 -0
  317. package/dist/generator/scope-function-generator.js +360 -0
  318. package/dist/generator/unified.d.ts +42 -0
  319. package/dist/generator/unified.js +1504 -0
  320. package/dist/generator.d.ts +54 -0
  321. package/dist/generator.js +100 -0
  322. package/dist/index.d.ts +85 -0
  323. package/dist/index.js +89 -0
  324. package/dist/jsdoc-parser.d.ts +308 -0
  325. package/dist/jsdoc-parser.js +923 -0
  326. package/dist/jsdoc-port-sync/constants.d.ts +41 -0
  327. package/dist/jsdoc-port-sync/constants.js +103 -0
  328. package/dist/jsdoc-port-sync/diff.d.ts +76 -0
  329. package/dist/jsdoc-port-sync/diff.js +319 -0
  330. package/dist/jsdoc-port-sync/index.d.ts +42 -0
  331. package/dist/jsdoc-port-sync/index.js +45 -0
  332. package/dist/jsdoc-port-sync/port-parser.d.ts +68 -0
  333. package/dist/jsdoc-port-sync/port-parser.js +579 -0
  334. package/dist/jsdoc-port-sync/rename.d.ts +21 -0
  335. package/dist/jsdoc-port-sync/rename.js +256 -0
  336. package/dist/jsdoc-port-sync/signature-parser.d.ts +104 -0
  337. package/dist/jsdoc-port-sync/signature-parser.js +559 -0
  338. package/dist/jsdoc-port-sync/sync.d.ts +36 -0
  339. package/dist/jsdoc-port-sync/sync.js +644 -0
  340. package/dist/jsdoc-port-sync.d.ts +10 -0
  341. package/dist/jsdoc-port-sync.js +10 -0
  342. package/dist/marketplace/index.d.ts +11 -0
  343. package/dist/marketplace/index.js +10 -0
  344. package/dist/marketplace/manifest.d.ts +32 -0
  345. package/dist/marketplace/manifest.js +176 -0
  346. package/dist/marketplace/registry.d.ts +30 -0
  347. package/dist/marketplace/registry.js +100 -0
  348. package/dist/marketplace/types.d.ts +154 -0
  349. package/dist/marketplace/types.js +9 -0
  350. package/dist/marketplace/validator.d.ts +13 -0
  351. package/dist/marketplace/validator.js +131 -0
  352. package/dist/mcp/auto-registration.d.ts +3 -0
  353. package/dist/mcp/auto-registration.js +62 -0
  354. package/dist/mcp/editor-connection.d.ts +50 -0
  355. package/dist/mcp/editor-connection.js +125 -0
  356. package/dist/mcp/event-buffer.d.ts +62 -0
  357. package/dist/mcp/event-buffer.js +150 -0
  358. package/dist/mcp/index.d.ts +12 -0
  359. package/dist/mcp/index.js +11 -0
  360. package/dist/mcp/resources.d.ts +14 -0
  361. package/dist/mcp/resources.js +55 -0
  362. package/dist/mcp/response-utils.d.ts +63 -0
  363. package/dist/mcp/response-utils.js +89 -0
  364. package/dist/mcp/server.d.ts +4 -0
  365. package/dist/mcp/server.js +99 -0
  366. package/dist/mcp/tools-diagram.d.ts +8 -0
  367. package/dist/mcp/tools-diagram.js +53 -0
  368. package/dist/mcp/tools-editor.d.ts +5 -0
  369. package/dist/mcp/tools-editor.js +190 -0
  370. package/dist/mcp/tools-export.d.ts +9 -0
  371. package/dist/mcp/tools-export.js +180 -0
  372. package/dist/mcp/tools-marketplace.d.ts +9 -0
  373. package/dist/mcp/tools-marketplace.js +132 -0
  374. package/dist/mcp/tools-pattern.d.ts +3 -0
  375. package/dist/mcp/tools-pattern.js +783 -0
  376. package/dist/mcp/tools-query.d.ts +3 -0
  377. package/dist/mcp/tools-query.js +364 -0
  378. package/dist/mcp/tools-template.d.ts +10 -0
  379. package/dist/mcp/tools-template.js +119 -0
  380. package/dist/mcp/types.d.ts +70 -0
  381. package/dist/mcp/types.js +8 -0
  382. package/dist/mcp/workflow-executor.d.ts +47 -0
  383. package/dist/mcp/workflow-executor.js +133 -0
  384. package/dist/migration/registry.d.ts +30 -0
  385. package/dist/migration/registry.js +29 -0
  386. package/dist/node-types-generator.d.ts +49 -0
  387. package/dist/node-types-generator.js +139 -0
  388. package/dist/npm-packages.d.ts +56 -0
  389. package/dist/npm-packages.js +255 -0
  390. package/dist/parser.d.ts +204 -0
  391. package/dist/parser.js +2100 -0
  392. package/dist/plugin/PluginPanel.d.ts +12 -0
  393. package/dist/plugin/PluginPanel.js +5 -0
  394. package/dist/plugin/index.d.ts +13 -0
  395. package/dist/plugin/index.js +14 -0
  396. package/dist/plugin/types.d.ts +75 -0
  397. package/dist/plugin/types.js +8 -0
  398. package/dist/resolve-package-types.d.ts +17 -0
  399. package/dist/resolve-package-types.js +123 -0
  400. package/dist/runtime/CancellationError.d.ts +11 -0
  401. package/dist/runtime/CancellationError.js +20 -0
  402. package/dist/runtime/ExecutionContext.d.ts +146 -0
  403. package/dist/runtime/ExecutionContext.js +235 -0
  404. package/dist/runtime/builtin-functions.d.ts +8 -0
  405. package/dist/runtime/builtin-functions.js +549 -0
  406. package/dist/runtime/events.d.ts +50 -0
  407. package/dist/runtime/events.js +2 -0
  408. package/dist/runtime/function-registry.d.ts +59 -0
  409. package/dist/runtime/function-registry.js +66 -0
  410. package/dist/runtime/index.d.ts +7 -0
  411. package/dist/runtime/index.js +7 -0
  412. package/dist/runtime/parameter-resolver.d.ts +62 -0
  413. package/dist/runtime/parameter-resolver.js +113 -0
  414. package/dist/server/index.d.ts +7 -0
  415. package/dist/server/index.js +6 -0
  416. package/dist/server/types.d.ts +93 -0
  417. package/dist/server/types.js +5 -0
  418. package/dist/server/webhook-server.d.ts +50 -0
  419. package/dist/server/webhook-server.js +269 -0
  420. package/dist/server/workflow-registry.d.ts +61 -0
  421. package/dist/server/workflow-registry.js +202 -0
  422. package/dist/shared-project.d.ts +9 -0
  423. package/dist/shared-project.js +28 -0
  424. package/dist/sugar-optimizer.d.ts +40 -0
  425. package/dist/sugar-optimizer.js +387 -0
  426. package/dist/testing/assertions.d.ts +51 -0
  427. package/dist/testing/assertions.js +127 -0
  428. package/dist/testing/index.d.ts +30 -0
  429. package/dist/testing/index.js +24 -0
  430. package/dist/testing/mock-approval.d.ts +81 -0
  431. package/dist/testing/mock-approval.js +98 -0
  432. package/dist/testing/mock-llm.d.ts +124 -0
  433. package/dist/testing/mock-llm.js +119 -0
  434. package/dist/testing/recorder.d.ts +72 -0
  435. package/dist/testing/recorder.js +70 -0
  436. package/dist/testing/replayer.d.ts +56 -0
  437. package/dist/testing/replayer.js +143 -0
  438. package/dist/testing/token-tracker.d.ts +71 -0
  439. package/dist/testing/token-tracker.js +94 -0
  440. package/dist/type-checker.d.ts +42 -0
  441. package/dist/type-checker.js +190 -0
  442. package/dist/type-mappings.d.ts +29 -0
  443. package/dist/type-mappings.js +125 -0
  444. package/dist/types/branded-ports.d.ts +151 -0
  445. package/dist/types/branded-ports.js +121 -0
  446. package/dist/types/index.d.ts +5 -0
  447. package/dist/types/index.js +5 -0
  448. package/dist/types.d.ts +139 -0
  449. package/dist/types.js +15 -0
  450. package/dist/utils/error-utils.d.ts +15 -0
  451. package/dist/utils/error-utils.js +27 -0
  452. package/dist/utils/lru-cache.d.ts +15 -0
  453. package/dist/utils/lru-cache.js +40 -0
  454. package/dist/utils/port-ordering.d.ts +26 -0
  455. package/dist/utils/port-ordering.js +88 -0
  456. package/dist/utils/port-tag-utils.d.ts +23 -0
  457. package/dist/utils/port-tag-utils.js +41 -0
  458. package/dist/utils/string-distance.d.ts +14 -0
  459. package/dist/utils/string-distance.js +56 -0
  460. package/dist/validation/agent-detection.d.ts +33 -0
  461. package/dist/validation/agent-detection.js +115 -0
  462. package/dist/validation/agent-rules.d.ts +48 -0
  463. package/dist/validation/agent-rules.js +262 -0
  464. package/dist/validator.d.ts +92 -0
  465. package/dist/validator.js +970 -0
  466. package/package.json +109 -0
@@ -0,0 +1,783 @@
1
+ import { z } from 'zod';
2
+ import * as path from 'path';
3
+ import * as fs from 'fs';
4
+ import { globSync } from 'glob';
5
+ import { parseWorkflow, validateWorkflow } from '../api/index.js';
6
+ import { listPatterns, applyPattern, findWorkflows, extractPattern } from '../api/patterns.js';
7
+ import { generateInPlace } from '../api/generate-in-place.js';
8
+ import { applyMigrations, getRegisteredMigrations } from '../migration/registry.js';
9
+ import { describeWorkflow, formatDescribeOutput } from '../cli/commands/describe.js';
10
+ import { addNode as manipAddNode, removeNode as manipRemoveNode, renameNode as manipRenameNode, addConnection as manipAddConnection, removeConnection as manipRemoveConnection, setNodePosition as manipSetNodePosition, setNodeLabel as manipSetNodeLabel, } from '../api/manipulation.js';
11
+ import { findIsolatedNodes } from '../api/query.js';
12
+ import { AnnotationParser } from '../parser.js';
13
+ import { makeToolResult, makeErrorResult, addHintsToItems } from './response-utils.js';
14
+ import { getFriendlyError } from '../friendly-errors.js';
15
+ // Runtime validation schemas for fw_modify operations
16
+ const modifyParamsSchemas = {
17
+ addNode: z.object({
18
+ nodeId: z.string({ required_error: 'nodeId is required' }),
19
+ nodeType: z.string({ required_error: 'nodeType is required' }),
20
+ x: z.number().optional(),
21
+ y: z.number().optional(),
22
+ }),
23
+ removeNode: z.object({
24
+ nodeId: z.string({ required_error: 'nodeId is required' }),
25
+ }),
26
+ renameNode: z.object({
27
+ oldId: z.string({ required_error: 'oldId is required' }),
28
+ newId: z.string({ required_error: 'newId is required' }),
29
+ }),
30
+ addConnection: z.object({
31
+ from: z.string({ required_error: 'from is required (format: "node.port")' }),
32
+ to: z.string({ required_error: 'to is required (format: "node.port")' }),
33
+ }),
34
+ removeConnection: z.object({
35
+ from: z.string({ required_error: 'from is required (format: "node.port")' }),
36
+ to: z.string({ required_error: 'to is required (format: "node.port")' }),
37
+ }),
38
+ setNodePosition: z.object({
39
+ nodeId: z.string({ required_error: 'nodeId is required' }),
40
+ x: z.number({ required_error: 'x is required', invalid_type_error: 'x must be a number' }),
41
+ y: z.number({ required_error: 'y is required', invalid_type_error: 'y must be a number' }),
42
+ }),
43
+ setNodeLabel: z.object({
44
+ nodeId: z.string({ required_error: 'nodeId is required' }),
45
+ label: z.string({ required_error: 'label is required' }),
46
+ }),
47
+ };
48
+ function validateModifyParams(operation, params) {
49
+ const schema = modifyParamsSchemas[operation];
50
+ if (!schema) {
51
+ return { success: false, error: `Unknown operation: ${operation}` };
52
+ }
53
+ const result = schema.safeParse(params);
54
+ if (!result.success) {
55
+ const messages = result.error.issues.map((i) => i.message).join('; ');
56
+ return { success: false, error: `${operation} params invalid: ${messages}` };
57
+ }
58
+ return { success: true };
59
+ }
60
+ /**
61
+ * Apply a single modify operation to an AST.
62
+ * Shared by fw_modify and fw_modify_batch.
63
+ */
64
+ function applyModifyOperation(ast, operation, params) {
65
+ const p = params;
66
+ const warnings = [];
67
+ const extraData = {};
68
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- AST manipulation functions use loose typing
69
+ let modifiedAST = ast;
70
+ switch (operation) {
71
+ case 'addNode': {
72
+ const nodeId = p.nodeId;
73
+ const nodeType = p.nodeType;
74
+ const nodeTypeExists = modifiedAST.nodeTypes.some((nt) => nt.name === nodeType || nt.functionName === nodeType);
75
+ if (!nodeTypeExists) {
76
+ warnings.push(`Node type "${nodeType}" is not defined in the file. ` +
77
+ `The node will be added but may not render until the type is defined.`);
78
+ }
79
+ let autoX = typeof p.x === 'number' ? p.x : undefined;
80
+ let autoY = typeof p.y === 'number' ? p.y : undefined;
81
+ if (autoX === undefined || autoY === undefined) {
82
+ const positions = modifiedAST.instances
83
+ .map((inst) => inst.config)
84
+ .filter((c) => c !== undefined &&
85
+ c !== null &&
86
+ typeof c.x === 'number' &&
87
+ typeof c.y === 'number');
88
+ if (positions.length > 0) {
89
+ const maxX = Math.max(...positions.map((pos) => pos.x));
90
+ if (autoX === undefined)
91
+ autoX = maxX + 180;
92
+ if (autoY === undefined)
93
+ autoY = 0;
94
+ }
95
+ else {
96
+ if (autoX === undefined)
97
+ autoX = 0;
98
+ if (autoY === undefined)
99
+ autoY = 0;
100
+ }
101
+ }
102
+ modifiedAST = manipAddNode(modifiedAST, {
103
+ type: 'NodeInstance',
104
+ id: nodeId,
105
+ nodeType,
106
+ config: { x: autoX, y: autoY },
107
+ });
108
+ break;
109
+ }
110
+ case 'removeNode': {
111
+ const nodeId = p.nodeId;
112
+ const removedConnections = modifiedAST.connections
113
+ .filter((c) => c.from.node === nodeId || c.to.node === nodeId)
114
+ .map((c) => ({
115
+ from: `${c.from.node}.${c.from.port}`,
116
+ to: `${c.to.node}.${c.to.port}`,
117
+ }));
118
+ modifiedAST = manipRemoveNode(modifiedAST, nodeId);
119
+ if (removedConnections.length > 0) {
120
+ extraData.removedConnections = removedConnections;
121
+ }
122
+ break;
123
+ }
124
+ case 'renameNode': {
125
+ modifiedAST = manipRenameNode(modifiedAST, p.oldId, p.newId);
126
+ break;
127
+ }
128
+ case 'addConnection': {
129
+ const from = p.from;
130
+ const to = p.to;
131
+ const [fromNode, fromPort] = from.split('.');
132
+ const [toNode, toPort] = to.split('.');
133
+ if (!fromPort || !toPort) {
134
+ throw new Error('Connection format must be "node.port" (e.g., "Start.execute")');
135
+ }
136
+ const validNodes = [
137
+ 'Start',
138
+ 'Exit',
139
+ ...modifiedAST.instances.map((i) => i.id),
140
+ ];
141
+ if (!validNodes.includes(fromNode)) {
142
+ throw new Error(`Source node "${fromNode}" not found. Available: ${validNodes.join(', ')}`);
143
+ }
144
+ if (!validNodes.includes(toNode)) {
145
+ throw new Error(`Target node "${toNode}" not found. Available: ${validNodes.join(', ')}`);
146
+ }
147
+ if (fromNode !== 'Start' && fromNode !== 'Exit') {
148
+ const inst = modifiedAST.instances.find((i) => i.id === fromNode);
149
+ const nt = modifiedAST.nodeTypes.find((t) => t.name === inst?.nodeType);
150
+ if (nt && !nt.outputs[fromPort]) {
151
+ throw new Error(`Node "${fromNode}" has no output "${fromPort}". Available: ${Object.keys(nt.outputs).join(', ')}`);
152
+ }
153
+ }
154
+ if (toNode !== 'Start' && toNode !== 'Exit') {
155
+ const inst = modifiedAST.instances.find((i) => i.id === toNode);
156
+ const nt = modifiedAST.nodeTypes.find((t) => t.name === inst?.nodeType);
157
+ if (nt && !nt.inputs[toPort]) {
158
+ throw new Error(`Node "${toNode}" has no input "${toPort}". Available: ${Object.keys(nt.inputs).join(', ')}`);
159
+ }
160
+ }
161
+ modifiedAST = manipAddConnection(modifiedAST, from, to);
162
+ // Transition from autoConnect to explicit mode when connections are manually modified
163
+ if (modifiedAST.options?.autoConnect) {
164
+ modifiedAST = { ...modifiedAST, options: { ...modifiedAST.options, autoConnect: undefined } };
165
+ warnings.push('autoConnect was disabled because connections were manually modified');
166
+ }
167
+ break;
168
+ }
169
+ case 'removeConnection': {
170
+ modifiedAST = manipRemoveConnection(modifiedAST, p.from, p.to);
171
+ // Transition from autoConnect to explicit mode when connections are manually modified
172
+ if (modifiedAST.options?.autoConnect) {
173
+ modifiedAST = { ...modifiedAST, options: { ...modifiedAST.options, autoConnect: undefined } };
174
+ warnings.push('autoConnect was disabled because connections were manually modified');
175
+ }
176
+ const newlyIsolated = findIsolatedNodes(modifiedAST);
177
+ if (newlyIsolated.length > 0) {
178
+ extraData.newlyIsolatedNodes = newlyIsolated;
179
+ }
180
+ break;
181
+ }
182
+ case 'setNodePosition': {
183
+ modifiedAST = manipSetNodePosition(modifiedAST, p.nodeId, p.x, p.y);
184
+ break;
185
+ }
186
+ case 'setNodeLabel': {
187
+ modifiedAST = manipSetNodeLabel(modifiedAST, p.nodeId, p.label);
188
+ break;
189
+ }
190
+ default:
191
+ throw new Error(`Unknown operation: ${operation}`);
192
+ }
193
+ return { ast: modifiedAST, warnings, extraData };
194
+ }
195
+ export function registerPatternTools(mcp) {
196
+ mcp.tool('fw_list_patterns', 'List reusable patterns defined in a file.', {
197
+ filePath: z.string().describe('Path to file containing patterns'),
198
+ }, async (args) => {
199
+ try {
200
+ const filePath = path.resolve(args.filePath);
201
+ const patterns = listPatterns(filePath);
202
+ return makeToolResult(patterns);
203
+ }
204
+ catch (err) {
205
+ return makeErrorResult('LIST_PATTERNS_ERROR', `fw_list_patterns failed: ${err instanceof Error ? err.message : String(err)}`);
206
+ }
207
+ });
208
+ mcp.tool('fw_apply_pattern', 'Apply a reusable pattern to a workflow file.', {
209
+ patternFile: z.string().describe('Path to file containing the pattern'),
210
+ targetFile: z.string().describe('Path to target workflow file'),
211
+ patternName: z.string().optional().describe('Specific pattern name if file has multiple'),
212
+ prefix: z.string().optional().describe('Node ID prefix to avoid conflicts'),
213
+ preview: z.boolean().optional().describe("Preview only, don't write (default: false)"),
214
+ }, async (args) => {
215
+ try {
216
+ const patternFilePath = path.resolve(args.patternFile);
217
+ const targetFilePath = path.resolve(args.targetFile);
218
+ const annotationParser = new AnnotationParser();
219
+ // Parse pattern file
220
+ const patternResult = annotationParser.parse(patternFilePath);
221
+ if (patternResult.patterns.length === 0) {
222
+ return makeErrorResult('PATTERN_NOT_FOUND', `No patterns found in ${args.patternFile}`);
223
+ }
224
+ // Select pattern
225
+ let pattern;
226
+ if (args.patternName) {
227
+ pattern = patternResult.patterns.find((p) => p.name === args.patternName);
228
+ if (!pattern) {
229
+ return makeErrorResult('PATTERN_NOT_FOUND', `Pattern "${args.patternName}" not found in ${args.patternFile}`);
230
+ }
231
+ }
232
+ else {
233
+ pattern = patternResult.patterns[0];
234
+ }
235
+ // Read target file and parse for existing node types
236
+ const targetContent = fs.readFileSync(targetFilePath, 'utf8');
237
+ const targetResult = annotationParser.parse(targetFilePath);
238
+ const existingNodeTypes = new Set(targetResult.nodeTypes.map((nt) => nt.name));
239
+ // Apply pattern via pure API
240
+ const result = applyPattern({
241
+ patternAST: pattern,
242
+ targetContent,
243
+ targetNodeTypes: existingNodeTypes,
244
+ prefix: args.prefix,
245
+ });
246
+ if (args.preview) {
247
+ return makeToolResult({
248
+ success: true,
249
+ preview: true,
250
+ nodesAdded: result.nodesAdded,
251
+ connectionsAdded: result.connectionsAdded,
252
+ nodeTypesAdded: result.nodeTypesAdded,
253
+ conflicts: result.conflicts,
254
+ wiringInstructions: result.wiringInstructions,
255
+ content: result.modifiedContent,
256
+ });
257
+ }
258
+ fs.writeFileSync(targetFilePath, result.modifiedContent, 'utf8');
259
+ return makeToolResult({
260
+ success: true,
261
+ nodesAdded: result.nodesAdded,
262
+ connectionsAdded: result.connectionsAdded,
263
+ nodeTypesAdded: result.nodeTypesAdded,
264
+ conflicts: result.conflicts,
265
+ wiringInstructions: result.wiringInstructions,
266
+ });
267
+ }
268
+ catch (err) {
269
+ return makeErrorResult('APPLY_PATTERN_ERROR', `fw_apply_pattern failed: ${err instanceof Error ? err.message : String(err)}`);
270
+ }
271
+ });
272
+ mcp.tool('fw_find_workflows', 'Scan a directory for workflow files containing @flowWeaver workflow annotations. Returns file paths and workflow metadata.', {
273
+ directory: z.string().describe('Directory to search for workflow files'),
274
+ pattern: z.string().optional().describe('Glob pattern (default: **/*.ts)'),
275
+ }, async (args) => {
276
+ try {
277
+ const dir = path.resolve(args.directory);
278
+ const results = await findWorkflows(dir, args.pattern);
279
+ return makeToolResult(results);
280
+ }
281
+ catch (err) {
282
+ return makeErrorResult('FIND_WORKFLOWS_ERROR', `fw_find_workflows failed: ${err instanceof Error ? err.message : String(err)}`);
283
+ }
284
+ });
285
+ mcp.tool('fw_modify', 'Modify a workflow file: add/remove/rename nodes, add/remove connections, set positions/labels. Parses the file, applies the mutation, and regenerates annotations in-place. Returns auto-validation results and a text description of the updated workflow. For addNode: if x/y are omitted, the node is placed to the right of the rightmost existing node.', {
286
+ filePath: z.string().describe('Path to the workflow file'),
287
+ workflowName: z.string().optional().describe('Specific workflow if file has multiple'),
288
+ operation: z
289
+ .enum([
290
+ 'addNode',
291
+ 'removeNode',
292
+ 'renameNode',
293
+ 'addConnection',
294
+ 'removeConnection',
295
+ 'setNodePosition',
296
+ 'setNodeLabel',
297
+ ])
298
+ .describe('The mutation to perform'),
299
+ params: z
300
+ .record(z.unknown())
301
+ .describe('Operation-specific parameters. ' +
302
+ 'addNode: {nodeId, nodeType, x?, y?}. ' +
303
+ 'removeNode: {nodeId}. ' +
304
+ 'renameNode: {oldId, newId}. ' +
305
+ 'addConnection: {from, to} ("node.port" format). ' +
306
+ 'removeConnection: {from, to} ("node.port" format). ' +
307
+ 'setNodePosition: {nodeId, x, y}. ' +
308
+ 'setNodeLabel: {nodeId, label}.'),
309
+ preview: z.boolean().optional().describe('Preview without writing (default: false)'),
310
+ }, async (args) => {
311
+ try {
312
+ // Validate params against schema for the operation
313
+ const paramValidation = validateModifyParams(args.operation, args.params);
314
+ if (!paramValidation.success) {
315
+ return makeErrorResult('INVALID_PARAMS', paramValidation.error);
316
+ }
317
+ const filePath = path.resolve(args.filePath);
318
+ const sourceCode = fs.readFileSync(filePath, 'utf8');
319
+ // Parse the workflow
320
+ const parseResult = await parseWorkflow(filePath, { workflowName: args.workflowName });
321
+ if (parseResult.errors.length > 0) {
322
+ return makeErrorResult('PARSE_ERROR', `Parse errors:\n${parseResult.errors.join('\n')}`);
323
+ }
324
+ let modifiedAST = parseResult.ast;
325
+ const p = args.params;
326
+ const warnings = [];
327
+ const extraResponseData = {};
328
+ // Apply the requested operation
329
+ switch (args.operation) {
330
+ case 'addNode': {
331
+ const nodeId = p.nodeId;
332
+ const nodeType = p.nodeType;
333
+ if (!nodeId || !nodeType) {
334
+ return makeErrorResult('INVALID_PARAMS', 'addNode requires params: nodeId, nodeType');
335
+ }
336
+ const nodeTypeExists = parseResult.ast.nodeTypes.some((nt) => nt.name === nodeType || nt.functionName === nodeType);
337
+ if (!nodeTypeExists) {
338
+ warnings.push(`Node type "${nodeType}" is not defined in the file. ` +
339
+ `The node will be added but may not render until the type is defined.`);
340
+ }
341
+ // Auto-position: if x/y not provided, place to the right of the rightmost node
342
+ let autoX = typeof p.x === 'number' ? p.x : undefined;
343
+ let autoY = typeof p.y === 'number' ? p.y : undefined;
344
+ if (autoX === undefined || autoY === undefined) {
345
+ const positions = parseResult.ast.instances
346
+ .map((inst) => inst.config)
347
+ .filter((c) => c !== undefined && typeof c.x === 'number' && typeof c.y === 'number');
348
+ if (positions.length > 0) {
349
+ const maxX = Math.max(...positions.map((pos) => pos.x));
350
+ if (autoX === undefined)
351
+ autoX = maxX + 180;
352
+ if (autoY === undefined)
353
+ autoY = 0;
354
+ }
355
+ else {
356
+ if (autoX === undefined)
357
+ autoX = 0;
358
+ if (autoY === undefined)
359
+ autoY = 0;
360
+ }
361
+ }
362
+ modifiedAST = manipAddNode(modifiedAST, {
363
+ type: 'NodeInstance',
364
+ id: nodeId,
365
+ nodeType,
366
+ config: {
367
+ x: autoX,
368
+ y: autoY,
369
+ },
370
+ });
371
+ break;
372
+ }
373
+ case 'removeNode': {
374
+ const nodeId = p.nodeId;
375
+ if (!nodeId)
376
+ return makeErrorResult('INVALID_PARAMS', 'removeNode requires params: nodeId');
377
+ // Snapshot connections that will be removed along with the node
378
+ const removedConnections = parseResult.ast.connections
379
+ .filter((c) => c.from.node === nodeId || c.to.node === nodeId)
380
+ .map((c) => ({
381
+ from: `${c.from.node}.${c.from.port}`,
382
+ to: `${c.to.node}.${c.to.port}`,
383
+ }));
384
+ modifiedAST = manipRemoveNode(modifiedAST, nodeId);
385
+ if (removedConnections.length > 0) {
386
+ extraResponseData.removedConnections = removedConnections;
387
+ }
388
+ break;
389
+ }
390
+ case 'renameNode': {
391
+ const oldId = p.oldId;
392
+ const newId = p.newId;
393
+ if (!oldId || !newId) {
394
+ return makeErrorResult('INVALID_PARAMS', 'renameNode requires params: oldId, newId');
395
+ }
396
+ modifiedAST = manipRenameNode(modifiedAST, oldId, newId);
397
+ break;
398
+ }
399
+ case 'addConnection': {
400
+ const from = p.from;
401
+ const to = p.to;
402
+ if (!from || !to) {
403
+ return makeErrorResult('INVALID_PARAMS', 'addConnection requires params: from, to (format: "node.port")');
404
+ }
405
+ const [fromNode, fromPort] = from.split('.');
406
+ const [toNode, toPort] = to.split('.');
407
+ if (!fromPort || !toPort) {
408
+ return makeErrorResult('INVALID_PARAMS', 'Connection format must be "node.port" (e.g., "Start.execute")');
409
+ }
410
+ // Pre-validate nodes exist
411
+ const validNodes = [
412
+ 'Start',
413
+ 'Exit',
414
+ ...modifiedAST.instances.map((i) => i.id),
415
+ ];
416
+ if (!validNodes.includes(fromNode)) {
417
+ return makeErrorResult('UNKNOWN_SOURCE_NODE', `Source node "${fromNode}" not found. Available: ${validNodes.join(', ')}`);
418
+ }
419
+ if (!validNodes.includes(toNode)) {
420
+ return makeErrorResult('UNKNOWN_TARGET_NODE', `Target node "${toNode}" not found. Available: ${validNodes.join(', ')}`);
421
+ }
422
+ // Pre-validate ports exist for non-Start/Exit nodes
423
+ if (fromNode !== 'Start' && fromNode !== 'Exit') {
424
+ const inst = modifiedAST.instances.find((i) => i.id === fromNode);
425
+ const nt = modifiedAST.nodeTypes.find((t) => t.name === inst?.nodeType);
426
+ if (nt && !nt.outputs[fromPort]) {
427
+ return makeErrorResult('UNKNOWN_SOURCE_PORT', `Node "${fromNode}" has no output "${fromPort}". Available: ${Object.keys(nt.outputs).join(', ')}`);
428
+ }
429
+ }
430
+ if (toNode !== 'Start' && toNode !== 'Exit') {
431
+ const inst = modifiedAST.instances.find((i) => i.id === toNode);
432
+ const nt = modifiedAST.nodeTypes.find((t) => t.name === inst?.nodeType);
433
+ if (nt && !nt.inputs[toPort]) {
434
+ return makeErrorResult('UNKNOWN_TARGET_PORT', `Node "${toNode}" has no input "${toPort}". Available: ${Object.keys(nt.inputs).join(', ')}`);
435
+ }
436
+ }
437
+ modifiedAST = manipAddConnection(modifiedAST, from, to);
438
+ break;
439
+ }
440
+ case 'removeConnection': {
441
+ const from = p.from;
442
+ const to = p.to;
443
+ if (!from || !to) {
444
+ return makeErrorResult('INVALID_PARAMS', 'removeConnection requires params: from, to (format: "node.port")');
445
+ }
446
+ modifiedAST = manipRemoveConnection(modifiedAST, from, to);
447
+ // Check if any nodes became isolated after removing the connection
448
+ const newlyIsolated = findIsolatedNodes(modifiedAST);
449
+ if (newlyIsolated.length > 0) {
450
+ extraResponseData.newlyIsolatedNodes = newlyIsolated;
451
+ }
452
+ break;
453
+ }
454
+ case 'setNodePosition': {
455
+ const nodeId = p.nodeId;
456
+ const x = p.x;
457
+ const y = p.y;
458
+ if (!nodeId || typeof x !== 'number' || typeof y !== 'number') {
459
+ return makeErrorResult('INVALID_PARAMS', 'setNodePosition requires params: nodeId, x, y');
460
+ }
461
+ modifiedAST = manipSetNodePosition(modifiedAST, nodeId, x, y);
462
+ break;
463
+ }
464
+ case 'setNodeLabel': {
465
+ const nodeId = p.nodeId;
466
+ const label = p.label;
467
+ if (!nodeId || typeof label !== 'string') {
468
+ return makeErrorResult('INVALID_PARAMS', 'setNodeLabel requires params: nodeId, label');
469
+ }
470
+ modifiedAST = manipSetNodeLabel(modifiedAST, nodeId, label);
471
+ break;
472
+ }
473
+ default:
474
+ return makeErrorResult('UNKNOWN_OPERATION', `Unknown operation: ${args.operation}`);
475
+ }
476
+ // Regenerate the file in-place
477
+ const genResult = generateInPlace(sourceCode, modifiedAST);
478
+ if (args.preview) {
479
+ return makeToolResult({
480
+ success: true,
481
+ preview: true,
482
+ hasChanges: genResult.hasChanges,
483
+ code: genResult.code,
484
+ });
485
+ }
486
+ if (genResult.hasChanges) {
487
+ fs.writeFileSync(filePath, genResult.code, 'utf8');
488
+ }
489
+ // Auto-validate and describe after successful modification
490
+ let validation;
491
+ let description;
492
+ if (!args.preview) {
493
+ try {
494
+ const reParseResult = await parseWorkflow(filePath, {
495
+ workflowName: args.workflowName,
496
+ });
497
+ if (reParseResult.errors.length === 0) {
498
+ const valResult = validateWorkflow(reParseResult.ast);
499
+ const errors = valResult.errors.map((e) => ({
500
+ message: e.message,
501
+ severity: e.type,
502
+ nodeId: e.node,
503
+ code: e.code,
504
+ }));
505
+ const valWarnings = [
506
+ ...reParseResult.warnings,
507
+ ...valResult.warnings.map((w) => ({
508
+ message: w.message,
509
+ severity: w.type,
510
+ nodeId: w.node,
511
+ code: w.code,
512
+ })),
513
+ ];
514
+ validation = {
515
+ valid: valResult.valid,
516
+ errors: addHintsToItems(errors, getFriendlyError),
517
+ warnings: addHintsToItems(valWarnings, getFriendlyError),
518
+ };
519
+ // Generate text description
520
+ try {
521
+ const output = describeWorkflow(reParseResult.ast);
522
+ description = formatDescribeOutput(reParseResult.ast, output, 'text');
523
+ }
524
+ catch {
525
+ // Description is best-effort; don't fail the operation
526
+ }
527
+ }
528
+ else {
529
+ validation = {
530
+ valid: false,
531
+ errors: reParseResult.errors.map((msg) => ({ message: msg, severity: 'error' })),
532
+ warnings: reParseResult.warnings,
533
+ };
534
+ }
535
+ }
536
+ catch (valErr) {
537
+ // Validation is best-effort after modify; include parse warning
538
+ warnings.push(`Post-modify validation failed: ${valErr instanceof Error ? valErr.message : String(valErr)}. The file was still written.`);
539
+ }
540
+ }
541
+ return makeToolResult({
542
+ success: true,
543
+ hasChanges: genResult.hasChanges,
544
+ operation: args.operation,
545
+ ...(warnings.length > 0 && { warnings }),
546
+ ...extraResponseData,
547
+ ...(validation && { validation }),
548
+ ...(description && { description }),
549
+ });
550
+ }
551
+ catch (err) {
552
+ return makeErrorResult('MODIFY_ERROR', `fw_modify failed: ${err instanceof Error ? err.message : String(err)}`);
553
+ }
554
+ });
555
+ mcp.tool('fw_modify_batch', 'Apply multiple modify operations in a single parse/write/validate cycle. More efficient than calling fw_modify multiple times.', {
556
+ filePath: z.string().describe('Path to the workflow file'),
557
+ workflowName: z.string().optional().describe('Specific workflow if file has multiple'),
558
+ operations: z
559
+ .array(z.object({
560
+ operation: z.enum([
561
+ 'addNode',
562
+ 'removeNode',
563
+ 'renameNode',
564
+ 'addConnection',
565
+ 'removeConnection',
566
+ 'setNodePosition',
567
+ 'setNodeLabel',
568
+ ]),
569
+ params: z.record(z.unknown()),
570
+ }))
571
+ .describe('Array of operations to apply sequentially'),
572
+ preview: z.boolean().optional().describe('Preview without writing (default: false)'),
573
+ }, async (args) => {
574
+ try {
575
+ // Pre-validate all operation params before applying any
576
+ for (let i = 0; i < args.operations.length; i++) {
577
+ const op = args.operations[i];
578
+ const paramValidation = validateModifyParams(op.operation, op.params);
579
+ if (!paramValidation.success) {
580
+ return makeErrorResult('INVALID_PARAMS', `Operation ${i} (${op.operation}): ${paramValidation.error}`);
581
+ }
582
+ }
583
+ const filePath = path.resolve(args.filePath);
584
+ const sourceCode = fs.readFileSync(filePath, 'utf8');
585
+ // Parse once
586
+ const parseResult = await parseWorkflow(filePath, { workflowName: args.workflowName });
587
+ if (parseResult.errors.length > 0) {
588
+ return makeErrorResult('PARSE_ERROR', `Parse errors:\n${parseResult.errors.join('\n')}`);
589
+ }
590
+ // Apply all operations sequentially to the AST
591
+ let currentAST = parseResult.ast;
592
+ const allWarnings = [];
593
+ const allExtraData = {};
594
+ for (let i = 0; i < args.operations.length; i++) {
595
+ const op = args.operations[i];
596
+ try {
597
+ const result = applyModifyOperation(currentAST, op.operation, op.params);
598
+ currentAST = result.ast;
599
+ allWarnings.push(...result.warnings);
600
+ Object.assign(allExtraData, result.extraData);
601
+ }
602
+ catch (opErr) {
603
+ return makeErrorResult('MODIFY_ERROR', `Operation ${i} (${op.operation}) failed: ${opErr instanceof Error ? opErr.message : String(opErr)}`);
604
+ }
605
+ }
606
+ // Generate once
607
+ const genResult = generateInPlace(sourceCode, currentAST);
608
+ if (args.preview) {
609
+ return makeToolResult({
610
+ success: true,
611
+ preview: true,
612
+ operationsApplied: args.operations.length,
613
+ hasChanges: genResult.hasChanges,
614
+ code: genResult.code,
615
+ });
616
+ }
617
+ // Write once
618
+ if (genResult.hasChanges) {
619
+ fs.writeFileSync(filePath, genResult.code, 'utf8');
620
+ }
621
+ // Validate once
622
+ let validation;
623
+ let description;
624
+ try {
625
+ const reParseResult = await parseWorkflow(filePath, { workflowName: args.workflowName });
626
+ if (reParseResult.errors.length === 0) {
627
+ const valResult = validateWorkflow(reParseResult.ast);
628
+ const errors = valResult.errors.map((e) => ({
629
+ message: e.message,
630
+ severity: e.type,
631
+ nodeId: e.node,
632
+ code: e.code,
633
+ }));
634
+ const valWarnings = [
635
+ ...reParseResult.warnings,
636
+ ...valResult.warnings.map((w) => ({
637
+ message: w.message,
638
+ severity: w.type,
639
+ nodeId: w.node,
640
+ code: w.code,
641
+ })),
642
+ ];
643
+ validation = {
644
+ valid: valResult.valid,
645
+ errors: addHintsToItems(errors, getFriendlyError),
646
+ warnings: addHintsToItems(valWarnings, getFriendlyError),
647
+ };
648
+ try {
649
+ const output = describeWorkflow(reParseResult.ast);
650
+ description = formatDescribeOutput(reParseResult.ast, output, 'text');
651
+ }
652
+ catch {
653
+ // Description is best-effort
654
+ }
655
+ }
656
+ else {
657
+ validation = {
658
+ valid: false,
659
+ errors: reParseResult.errors.map((msg) => ({ message: msg, severity: 'error' })),
660
+ warnings: reParseResult.warnings,
661
+ };
662
+ }
663
+ }
664
+ catch (valErr) {
665
+ allWarnings.push(`Post-modify validation failed: ${valErr instanceof Error ? valErr.message : String(valErr)}. The file was still written.`);
666
+ }
667
+ return makeToolResult({
668
+ success: true,
669
+ operationsApplied: args.operations.length,
670
+ hasChanges: genResult.hasChanges,
671
+ ...(allWarnings.length > 0 && { warnings: allWarnings }),
672
+ ...allExtraData,
673
+ ...(validation && { validation }),
674
+ ...(description && { description }),
675
+ });
676
+ }
677
+ catch (err) {
678
+ return makeErrorResult('MODIFY_ERROR', `fw_modify_batch failed: ${err instanceof Error ? err.message : String(err)}`);
679
+ }
680
+ });
681
+ mcp.tool('fw_extract_pattern', 'Extract a reusable pattern from selected nodes in a workflow. Identifies internal connections and boundary IN/OUT ports automatically.', {
682
+ sourceFile: z.string().describe('Path to workflow file'),
683
+ nodes: z.string().describe('Comma-separated node IDs to extract'),
684
+ name: z.string().optional().describe('Pattern name'),
685
+ outputFile: z.string().optional().describe('Output file path (omit for preview only)'),
686
+ }, async (args) => {
687
+ try {
688
+ const filePath = path.resolve(args.sourceFile);
689
+ const parseResult = await parseWorkflow(filePath);
690
+ if (parseResult.errors.length > 0) {
691
+ return makeErrorResult('PARSE_ERROR', `Parse errors:\n${parseResult.errors.join('\n')}`);
692
+ }
693
+ const annotationParser = new AnnotationParser();
694
+ const fullParse = annotationParser.parse(filePath);
695
+ const nodeIds = args.nodes.split(',').map((s) => s.trim());
696
+ const result = extractPattern({
697
+ workflowAST: parseResult.ast,
698
+ nodeTypes: fullParse.nodeTypes,
699
+ nodeIds,
700
+ name: args.name,
701
+ });
702
+ if (args.outputFile) {
703
+ const outPath = path.resolve(args.outputFile);
704
+ fs.writeFileSync(outPath, result.patternCode, 'utf8');
705
+ return makeToolResult({
706
+ success: true,
707
+ filePath: outPath,
708
+ patternName: result.patternName,
709
+ nodes: result.nodes,
710
+ inputPorts: result.inputPorts,
711
+ outputPorts: result.outputPorts,
712
+ internalConnectionCount: result.internalConnectionCount,
713
+ });
714
+ }
715
+ return makeToolResult({
716
+ success: true,
717
+ preview: true,
718
+ patternName: result.patternName,
719
+ nodes: result.nodes,
720
+ inputPorts: result.inputPorts,
721
+ outputPorts: result.outputPorts,
722
+ internalConnectionCount: result.internalConnectionCount,
723
+ code: result.patternCode,
724
+ });
725
+ }
726
+ catch (err) {
727
+ return makeErrorResult('EXTRACT_PATTERN_ERROR', `fw_extract_pattern failed: ${err instanceof Error ? err.message : String(err)}`);
728
+ }
729
+ });
730
+ mcp.tool('fw_migrate', 'Migrate workflow files to current syntax via parse → regenerate round-trip. The parser adds defaults for missing fields, edge-case migrations transform the AST, and generateInPlace writes current syntax back.', {
731
+ glob: z.string().describe('Glob pattern for workflow files to migrate (e.g., "src/**/*.ts")'),
732
+ dryRun: z.boolean().optional().describe('Preview changes without writing files (default: false)'),
733
+ }, async (args) => {
734
+ try {
735
+ const files = globSync(args.glob, { ignore: ['**/node_modules/**', '**/*.generated.ts'] });
736
+ if (files.length === 0) {
737
+ return makeToolResult({ success: true, message: `No files matched pattern: ${args.glob}`, files: [] });
738
+ }
739
+ const results = [];
740
+ for (const file of files) {
741
+ const filePath = path.resolve(file);
742
+ try {
743
+ const sourceCode = fs.readFileSync(filePath, 'utf8');
744
+ const parseResult = await parseWorkflow(filePath);
745
+ if (parseResult.errors.length > 0) {
746
+ results.push({ file, status: 'error', error: parseResult.errors.join('; ') });
747
+ continue;
748
+ }
749
+ let ast = parseResult.ast;
750
+ ast = applyMigrations(ast);
751
+ const genResult = generateInPlace(sourceCode, ast, {
752
+ allWorkflows: parseResult.allWorkflows,
753
+ });
754
+ if (!genResult.hasChanges) {
755
+ results.push({ file, status: 'current' });
756
+ continue;
757
+ }
758
+ if (!args.dryRun) {
759
+ fs.writeFileSync(filePath, genResult.code, 'utf8');
760
+ }
761
+ results.push({ file, status: 'migrated' });
762
+ }
763
+ catch (err) {
764
+ results.push({ file, status: 'error', error: err instanceof Error ? err.message : String(err) });
765
+ }
766
+ }
767
+ const migrated = results.filter((r) => r.status === 'migrated').length;
768
+ const current = results.filter((r) => r.status === 'current').length;
769
+ const errors = results.filter((r) => r.status === 'error').length;
770
+ return makeToolResult({
771
+ success: true,
772
+ dryRun: args.dryRun ?? false,
773
+ summary: { migrated, current, errors, total: files.length },
774
+ registeredMigrations: getRegisteredMigrations(),
775
+ files: results,
776
+ });
777
+ }
778
+ catch (err) {
779
+ return makeErrorResult('MIGRATE_ERROR', `fw_migrate failed: ${err instanceof Error ? err.message : String(err)}`);
780
+ }
781
+ });
782
+ }
783
+ //# sourceMappingURL=tools-pattern.js.map