@xdelivered/emberflow 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 (414) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +153 -0
  3. package/bin/commands.test.ts +185 -0
  4. package/bin/commands.ts +306 -0
  5. package/bin/emberflow.mjs +38 -0
  6. package/bin/init.test.ts +165 -0
  7. package/bin/init.ts +297 -0
  8. package/bin/runtime.mjs +105 -0
  9. package/bin/runtime.test.ts +167 -0
  10. package/bin/skillTargets.test.ts +108 -0
  11. package/bin/skillTargets.ts +36 -0
  12. package/bin/skillTemplates.test.ts +37 -0
  13. package/bin/tsconfig.json +23 -0
  14. package/dist/bin/commands.d.ts +24 -0
  15. package/dist/bin/commands.js +252 -0
  16. package/dist/bin/init.d.ts +17 -0
  17. package/dist/bin/init.js +241 -0
  18. package/dist/bin/runtime.d.mts +39 -0
  19. package/dist/bin/runtime.mjs +96 -0
  20. package/dist/bin/skillTargets.d.ts +13 -0
  21. package/dist/bin/skillTargets.js +22 -0
  22. package/dist/server/agents/claudeAdapter.d.ts +8 -0
  23. package/dist/server/agents/claudeAdapter.js +190 -0
  24. package/dist/server/agents/claudeParse.d.ts +2 -0
  25. package/dist/server/agents/claudeParse.js +162 -0
  26. package/dist/server/agents/codexAdapter.d.ts +13 -0
  27. package/dist/server/agents/codexAdapter.js +174 -0
  28. package/dist/server/agents/codexParse.d.ts +2 -0
  29. package/dist/server/agents/codexParse.js +74 -0
  30. package/dist/server/agents/detect.d.ts +23 -0
  31. package/dist/server/agents/detect.js +35 -0
  32. package/dist/server/agents/gitScope.d.ts +24 -0
  33. package/dist/server/agents/gitScope.js +95 -0
  34. package/dist/server/agents/modelRejectionHint.d.ts +8 -0
  35. package/dist/server/agents/modelRejectionHint.js +12 -0
  36. package/dist/server/agents/prompt.d.ts +79 -0
  37. package/dist/server/agents/prompt.js +364 -0
  38. package/dist/server/agents/runManager.d.ts +90 -0
  39. package/dist/server/agents/runManager.js +259 -0
  40. package/dist/server/agents/types.d.ts +15 -0
  41. package/dist/server/agents/types.js +1 -0
  42. package/dist/server/apiStore.d.ts +60 -0
  43. package/dist/server/apiStore.js +249 -0
  44. package/dist/server/auth/enforce.d.ts +1 -0
  45. package/dist/server/auth/enforce.js +6 -0
  46. package/dist/server/auth/types.d.ts +1 -0
  47. package/dist/server/auth/types.js +1 -0
  48. package/dist/server/auth/verifiers.d.ts +1 -0
  49. package/dist/server/auth/verifiers.js +4 -0
  50. package/dist/server/authAttach.d.ts +19 -0
  51. package/dist/server/authAttach.js +79 -0
  52. package/dist/server/cli.d.ts +7 -0
  53. package/dist/server/cli.js +804 -0
  54. package/dist/server/client.d.ts +130 -0
  55. package/dist/server/client.js +247 -0
  56. package/dist/server/environments.d.ts +103 -0
  57. package/dist/server/environments.js +486 -0
  58. package/dist/server/flowStore.d.ts +37 -0
  59. package/dist/server/flowStore.js +117 -0
  60. package/dist/server/httpOperations.d.ts +32 -0
  61. package/dist/server/httpOperations.js +62 -0
  62. package/dist/server/index.d.ts +1 -0
  63. package/dist/server/index.js +1022 -0
  64. package/dist/server/infrastructure.d.ts +51 -0
  65. package/dist/server/infrastructure.js +116 -0
  66. package/dist/server/login.d.ts +21 -0
  67. package/dist/server/login.js +44 -0
  68. package/dist/server/mcp.d.ts +1 -0
  69. package/dist/server/mcp.js +182 -0
  70. package/dist/server/migrateFlows.d.ts +8 -0
  71. package/dist/server/migrateFlows.js +25 -0
  72. package/dist/server/mockHandler.d.ts +15 -0
  73. package/dist/server/mockHandler.js +35 -0
  74. package/dist/server/nodesPayload.d.ts +14 -0
  75. package/dist/server/nodesPayload.js +14 -0
  76. package/dist/server/normalizeFlow.d.ts +21 -0
  77. package/dist/server/normalizeFlow.js +48 -0
  78. package/dist/server/openBrowser.d.ts +8 -0
  79. package/dist/server/openBrowser.js +16 -0
  80. package/dist/server/operationResult.d.ts +12 -0
  81. package/dist/server/operationResult.js +26 -0
  82. package/dist/server/pathGuard.d.ts +1 -0
  83. package/dist/server/pathGuard.js +16 -0
  84. package/dist/server/pathSafety.d.ts +20 -0
  85. package/dist/server/pathSafety.js +35 -0
  86. package/dist/server/projectConfig.d.ts +47 -0
  87. package/dist/server/projectConfig.js +61 -0
  88. package/dist/server/projectMode.d.ts +26 -0
  89. package/dist/server/projectMode.js +44 -0
  90. package/dist/server/redact.d.ts +6 -0
  91. package/dist/server/redact.js +37 -0
  92. package/dist/server/runRegistry.d.ts +84 -0
  93. package/dist/server/runRegistry.js +200 -0
  94. package/dist/server/runtime/RuntimeAdapter.d.ts +22 -0
  95. package/dist/server/runtime/RuntimeAdapter.js +1 -0
  96. package/dist/server/runtime/expressAdapter.d.ts +19 -0
  97. package/dist/server/runtime/expressAdapter.js +56 -0
  98. package/dist/server/scenarioTest.d.ts +14 -0
  99. package/dist/server/scenarioTest.js +66 -0
  100. package/dist/server/subflowRunner.d.ts +32 -0
  101. package/dist/server/subflowRunner.js +72 -0
  102. package/dist/server/testRunner.d.ts +70 -0
  103. package/dist/server/testRunner.js +151 -0
  104. package/dist/src/config.d.ts +3 -0
  105. package/dist/src/config.js +2 -0
  106. package/dist/src/engine/authVerify.d.ts +33 -0
  107. package/dist/src/engine/authVerify.js +63 -0
  108. package/dist/src/engine/diagnostics.d.ts +62 -0
  109. package/dist/src/engine/diagnostics.js +148 -0
  110. package/dist/src/engine/executor.d.ts +151 -0
  111. package/dist/src/engine/executor.js +684 -0
  112. package/dist/src/engine/httpError.d.ts +7 -0
  113. package/dist/src/engine/httpError.js +14 -0
  114. package/dist/src/engine/index.d.ts +11 -0
  115. package/dist/src/engine/index.js +11 -0
  116. package/dist/src/engine/output.d.ts +11 -0
  117. package/dist/src/engine/output.js +20 -0
  118. package/dist/src/engine/publish.d.ts +30 -0
  119. package/dist/src/engine/publish.js +95 -0
  120. package/dist/src/engine/registry.d.ts +34 -0
  121. package/dist/src/engine/registry.js +67 -0
  122. package/dist/src/engine/scenarios.d.ts +12 -0
  123. package/dist/src/engine/scenarios.js +19 -0
  124. package/dist/src/engine/schemaCheck.d.ts +4 -0
  125. package/dist/src/engine/schemaCheck.js +34 -0
  126. package/dist/src/engine/trace.d.ts +12 -0
  127. package/dist/src/engine/trace.js +12 -0
  128. package/dist/src/engine/types.d.ts +308 -0
  129. package/dist/src/engine/types.js +1 -0
  130. package/dist/src/engine/validation.d.ts +26 -0
  131. package/dist/src/engine/validation.js +318 -0
  132. package/dist/src/flows/anomaly-flows.d.ts +23 -0
  133. package/dist/src/flows/anomaly-flows.js +151 -0
  134. package/dist/src/flows/city-sweep-flow.d.ts +10 -0
  135. package/dist/src/flows/city-sweep-flow.js +127 -0
  136. package/dist/src/flows/login-flow.d.ts +13 -0
  137. package/dist/src/flows/login-flow.js +145 -0
  138. package/dist/src/flows/pradar-flows.d.ts +5 -0
  139. package/dist/src/flows/pradar-flows.js +375 -0
  140. package/dist/src/flows/weather-flow.d.ts +12 -0
  141. package/dist/src/flows/weather-flow.js +150 -0
  142. package/dist/src/lib/pathParams.d.ts +3 -0
  143. package/dist/src/lib/pathParams.js +6 -0
  144. package/dist/src/nodes/anomaly.d.ts +2 -0
  145. package/dist/src/nodes/anomaly.js +556 -0
  146. package/dist/src/nodes/flow-control.d.ts +7 -0
  147. package/dist/src/nodes/flow-control.js +270 -0
  148. package/dist/src/nodes/index.d.ts +3 -0
  149. package/dist/src/nodes/index.js +20 -0
  150. package/dist/src/nodes/login.d.ts +7 -0
  151. package/dist/src/nodes/login.js +158 -0
  152. package/dist/src/nodes/loops.d.ts +11 -0
  153. package/dist/src/nodes/loops.js +60 -0
  154. package/dist/src/nodes/pradar/index.d.ts +7 -0
  155. package/dist/src/nodes/pradar/index.js +9 -0
  156. package/dist/src/nodes/pradar/logic.d.ts +189 -0
  157. package/dist/src/nodes/pradar/logic.js +370 -0
  158. package/dist/src/nodes/pradar/nodes.d.ts +42 -0
  159. package/dist/src/nodes/pradar/nodes.js +801 -0
  160. package/dist/src/nodes/requireAuth.d.ts +20 -0
  161. package/dist/src/nodes/requireAuth.js +48 -0
  162. package/dist/src/nodes/response.d.ts +8 -0
  163. package/dist/src/nodes/response.js +33 -0
  164. package/dist/src/nodes/weather.d.ts +33 -0
  165. package/dist/src/nodes/weather.js +260 -0
  166. package/package.json +92 -0
  167. package/server/agentRoute.test.ts +157 -0
  168. package/server/agents/__fixtures__/fake-claude-writer.mjs +23 -0
  169. package/server/agents/__fixtures__/fake-claude.mjs +55 -0
  170. package/server/agents/__fixtures__/fake-codex-writer.mjs +27 -0
  171. package/server/agents/__fixtures__/fake-codex.mjs +52 -0
  172. package/server/agents/__fixtures__/fake-version-empty.mjs +3 -0
  173. package/server/agents/__fixtures__/fake-version-fail.mjs +4 -0
  174. package/server/agents/__fixtures__/fake-version-garbage.mjs +4 -0
  175. package/server/agents/__fixtures__/fake-version-good.mjs +4 -0
  176. package/server/agents/__fixtures__/fake-version-hang.mjs +3 -0
  177. package/server/agents/claudeAdapter.test.ts +127 -0
  178. package/server/agents/claudeAdapter.ts +212 -0
  179. package/server/agents/claudeParse.ts +193 -0
  180. package/server/agents/codexAdapter.test.ts +125 -0
  181. package/server/agents/codexAdapter.ts +198 -0
  182. package/server/agents/codexParse.test.ts +58 -0
  183. package/server/agents/codexParse.ts +126 -0
  184. package/server/agents/detect.test.ts +65 -0
  185. package/server/agents/detect.ts +43 -0
  186. package/server/agents/gitScope.test.ts +129 -0
  187. package/server/agents/gitScope.ts +110 -0
  188. package/server/agents/modelRejectionHint.test.ts +30 -0
  189. package/server/agents/modelRejectionHint.ts +14 -0
  190. package/server/agents/prompt.test.ts +613 -0
  191. package/server/agents/prompt.ts +527 -0
  192. package/server/agents/runManager.test.ts +251 -0
  193. package/server/agents/runManager.ts +286 -0
  194. package/server/agents/types.ts +17 -0
  195. package/server/apiMount.test.ts +591 -0
  196. package/server/apiStore.test.ts +324 -0
  197. package/server/apiStore.ts +241 -0
  198. package/server/auth/enforce.test.ts +61 -0
  199. package/server/auth/enforce.ts +6 -0
  200. package/server/auth/types.ts +5 -0
  201. package/server/auth/verifiers.test.ts +37 -0
  202. package/server/auth/verifiers.ts +9 -0
  203. package/server/authAttach.test.ts +175 -0
  204. package/server/authAttach.ts +99 -0
  205. package/server/cli.ts +847 -0
  206. package/server/cliAuth.test.ts +229 -0
  207. package/server/cliCreate.test.ts +131 -0
  208. package/server/cliDoctor.test.ts +326 -0
  209. package/server/cliTest.test.ts +735 -0
  210. package/server/client.ts +314 -0
  211. package/server/demoProject.test.ts +29 -0
  212. package/server/diagnosticsRoute.test.ts +169 -0
  213. package/server/environments.test.ts +620 -0
  214. package/server/environments.ts +603 -0
  215. package/server/environmentsRoute.test.ts +385 -0
  216. package/server/errorWorkflow.test.ts +205 -0
  217. package/server/flowStore.test.ts +84 -0
  218. package/server/flowStore.ts +125 -0
  219. package/server/httpOperations.test.ts +377 -0
  220. package/server/httpOperations.ts +96 -0
  221. package/server/index.ts +1111 -0
  222. package/server/infrastructure.test.ts +154 -0
  223. package/server/infrastructure.ts +161 -0
  224. package/server/infrastructureRoute.test.ts +105 -0
  225. package/server/login.test.ts +153 -0
  226. package/server/login.ts +67 -0
  227. package/server/mcp.ts +278 -0
  228. package/server/migrateFlows.test.ts +55 -0
  229. package/server/migrateFlows.ts +23 -0
  230. package/server/mockHandler.test.ts +138 -0
  231. package/server/mockHandler.ts +52 -0
  232. package/server/mockRun.test.ts +367 -0
  233. package/server/mockServe.test.ts +467 -0
  234. package/server/nodesPayload.test.ts +29 -0
  235. package/server/nodesPayload.ts +26 -0
  236. package/server/normalizeFlow.test.ts +80 -0
  237. package/server/normalizeFlow.ts +59 -0
  238. package/server/openBrowser.test.ts +20 -0
  239. package/server/openBrowser.ts +22 -0
  240. package/server/operationResult.test.ts +67 -0
  241. package/server/operationResult.ts +27 -0
  242. package/server/pathGuard.test.ts +19 -0
  243. package/server/pathGuard.ts +12 -0
  244. package/server/pathSafety.test.ts +38 -0
  245. package/server/pathSafety.ts +33 -0
  246. package/server/projectConfig.test.ts +67 -0
  247. package/server/projectConfig.ts +101 -0
  248. package/server/projectMode.test.ts +106 -0
  249. package/server/projectMode.ts +59 -0
  250. package/server/redact.test.ts +88 -0
  251. package/server/redact.ts +35 -0
  252. package/server/redactEgress.test.ts +281 -0
  253. package/server/runRegistry.ts +270 -0
  254. package/server/runsAuth.test.ts +119 -0
  255. package/server/runtime/RuntimeAdapter.ts +24 -0
  256. package/server/runtime/expressAdapter.test.ts +38 -0
  257. package/server/runtime/expressAdapter.ts +70 -0
  258. package/server/scenarioTest.test.ts +148 -0
  259. package/server/scenarioTest.ts +88 -0
  260. package/server/setupStatus.test.ts +127 -0
  261. package/server/subflowRunner.ts +104 -0
  262. package/server/testRunner.ts +216 -0
  263. package/server/tsconfig.json +20 -0
  264. package/server/workflowTestRoute.test.ts +297 -0
  265. package/src/App.tsx +233 -0
  266. package/src/components/AgentConsole.tsx +461 -0
  267. package/src/components/BranchRulesEditor.tsx +156 -0
  268. package/src/components/CreateModal.tsx +275 -0
  269. package/src/components/Dock.tsx +487 -0
  270. package/src/components/EnvironmentDialog.tsx +569 -0
  271. package/src/components/EnvironmentPicker.tsx +357 -0
  272. package/src/components/EnvironmentsDialog.tsx +144 -0
  273. package/src/components/ExecutionPager.tsx +67 -0
  274. package/src/components/InfraPanel.test.tsx +103 -0
  275. package/src/components/InfraPanel.tsx +171 -0
  276. package/src/components/Inspector.tsx +1182 -0
  277. package/src/components/Json.tsx +50 -0
  278. package/src/components/JsonModal.tsx +52 -0
  279. package/src/components/LogMessage.tsx +61 -0
  280. package/src/components/NodeRunModal.tsx +213 -0
  281. package/src/components/RunLogPanel.tsx +397 -0
  282. package/src/components/RunbookView.tsx +1085 -0
  283. package/src/components/Scenarios.tsx +476 -0
  284. package/src/components/SettingsDialog.tsx +229 -0
  285. package/src/components/Sidebar.tsx +436 -0
  286. package/src/components/StatusBar.tsx +302 -0
  287. package/src/components/Toolbar.tsx +663 -0
  288. package/src/components/WelcomeDialog.test.tsx +107 -0
  289. package/src/components/WelcomeDialog.tsx +412 -0
  290. package/src/components/agentMarkdown.test.tsx +91 -0
  291. package/src/components/agentMarkdown.tsx +158 -0
  292. package/src/components/ui/badge.tsx +31 -0
  293. package/src/components/ui/button.tsx +46 -0
  294. package/src/components/ui/combobox.tsx +114 -0
  295. package/src/components/ui/command.tsx +82 -0
  296. package/src/components/ui/dialog.tsx +73 -0
  297. package/src/components/ui/input.tsx +20 -0
  298. package/src/components/ui/popover.tsx +32 -0
  299. package/src/components/ui/resizable.tsx +44 -0
  300. package/src/components/ui/tabs.tsx +36 -0
  301. package/src/config.ts +4 -0
  302. package/src/engine/authVerify.ts +81 -0
  303. package/src/engine/diagnostics.test.ts +437 -0
  304. package/src/engine/diagnostics.ts +211 -0
  305. package/src/engine/executor.test.ts +1339 -0
  306. package/src/engine/executor.ts +840 -0
  307. package/src/engine/httpError.test.ts +12 -0
  308. package/src/engine/httpError.ts +16 -0
  309. package/src/engine/index.ts +11 -0
  310. package/src/engine/output.ts +21 -0
  311. package/src/engine/publish.test.ts +176 -0
  312. package/src/engine/publish.ts +127 -0
  313. package/src/engine/registry.test.ts +64 -0
  314. package/src/engine/registry.ts +80 -0
  315. package/src/engine/scenarios.test.ts +55 -0
  316. package/src/engine/scenarios.ts +29 -0
  317. package/src/engine/schemaCheck.test.ts +21 -0
  318. package/src/engine/schemaCheck.ts +35 -0
  319. package/src/engine/trace.test.ts +19 -0
  320. package/src/engine/trace.ts +23 -0
  321. package/src/engine/types.test.ts +22 -0
  322. package/src/engine/types.ts +316 -0
  323. package/src/engine/validation.test.ts +314 -0
  324. package/src/engine/validation.ts +354 -0
  325. package/src/flows/anomaly-flows.test.ts +81 -0
  326. package/src/flows/anomaly-flows.ts +202 -0
  327. package/src/flows/city-sweep-flow.ts +131 -0
  328. package/src/flows/flows.test.ts +30 -0
  329. package/src/flows/login-flow.ts +150 -0
  330. package/src/flows/pradar-flows.test.ts +204 -0
  331. package/src/flows/pradar-flows.ts +419 -0
  332. package/src/flows/weather-flow.ts +154 -0
  333. package/src/globals.css +147 -0
  334. package/src/lib/pathParams.test.ts +24 -0
  335. package/src/lib/pathParams.ts +6 -0
  336. package/src/lib/registerLens.test.ts +79 -0
  337. package/src/lib/registerLens.ts +59 -0
  338. package/src/lib/runbookModel.test.ts +61 -0
  339. package/src/lib/runbookModel.ts +290 -0
  340. package/src/lib/runbookProjection.test.ts +417 -0
  341. package/src/lib/runbookProjection.ts +254 -0
  342. package/src/lib/useTailAnchor.ts +53 -0
  343. package/src/lib/utils.ts +7 -0
  344. package/src/main.tsx +13 -0
  345. package/src/nodes/anomaly.test.ts +98 -0
  346. package/src/nodes/anomaly.ts +637 -0
  347. package/src/nodes/effects-scan.test.ts +44 -0
  348. package/src/nodes/flow-control.test.ts +280 -0
  349. package/src/nodes/flow-control.ts +305 -0
  350. package/src/nodes/index.ts +22 -0
  351. package/src/nodes/login.test.ts +81 -0
  352. package/src/nodes/login.ts +186 -0
  353. package/src/nodes/loops.ts +69 -0
  354. package/src/nodes/pradar/index.ts +11 -0
  355. package/src/nodes/pradar/logic.test.ts +288 -0
  356. package/src/nodes/pradar/logic.ts +582 -0
  357. package/src/nodes/pradar/nodes.test.ts +146 -0
  358. package/src/nodes/pradar/nodes.ts +955 -0
  359. package/src/nodes/requireAuth.test.ts +75 -0
  360. package/src/nodes/requireAuth.ts +55 -0
  361. package/src/nodes/response.test.ts +33 -0
  362. package/src/nodes/response.ts +39 -0
  363. package/src/nodes/traceDetail.test.ts +39 -0
  364. package/src/nodes/weather.test.ts +65 -0
  365. package/src/nodes/weather.ts +306 -0
  366. package/src/store/agentClient.test.ts +103 -0
  367. package/src/store/agentClient.ts +131 -0
  368. package/src/store/apiTree.test.ts +17 -0
  369. package/src/store/apiTree.ts +73 -0
  370. package/src/store/builderStore.test.ts +1234 -0
  371. package/src/store/builderStore.ts +1879 -0
  372. package/src/store/infraClient.ts +63 -0
  373. package/src/store/nodeMeta.test.ts +24 -0
  374. package/src/store/nodeMeta.ts +21 -0
  375. package/src/store/persistence.test.ts +15 -0
  376. package/src/store/persistence.ts +54 -0
  377. package/src/store/serverRunner.ts +381 -0
  378. package/src/store/setupClient.ts +57 -0
  379. package/studio-dist/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2 +0 -0
  380. package/studio-dist/assets/ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff +0 -0
  381. package/studio-dist/assets/ibm-plex-mono-cyrillic-500-normal-Ael50iVv.woff +0 -0
  382. package/studio-dist/assets/ibm-plex-mono-cyrillic-500-normal-Bq9vWWag.woff2 +0 -0
  383. package/studio-dist/assets/ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff +0 -0
  384. package/studio-dist/assets/ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2 +0 -0
  385. package/studio-dist/assets/ibm-plex-mono-cyrillic-ext-500-normal-BIfNGwUT.woff +0 -0
  386. package/studio-dist/assets/ibm-plex-mono-cyrillic-ext-500-normal-BqneJy0T.woff2 +0 -0
  387. package/studio-dist/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  388. package/studio-dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  389. package/studio-dist/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  390. package/studio-dist/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  391. package/studio-dist/assets/ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2 +0 -0
  392. package/studio-dist/assets/ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff +0 -0
  393. package/studio-dist/assets/ibm-plex-mono-latin-ext-500-normal-CAhNIIs5.woff2 +0 -0
  394. package/studio-dist/assets/ibm-plex-mono-latin-ext-500-normal-CZ70TYgx.woff +0 -0
  395. package/studio-dist/assets/ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2 +0 -0
  396. package/studio-dist/assets/ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff +0 -0
  397. package/studio-dist/assets/ibm-plex-mono-vietnamese-500-normal-C8zxqsMH.woff +0 -0
  398. package/studio-dist/assets/ibm-plex-mono-vietnamese-500-normal-DZ4AoWbu.woff2 +0 -0
  399. package/studio-dist/assets/index-DNJwW-hM.css +1 -0
  400. package/studio-dist/assets/index-O26dKRjW.js +65 -0
  401. package/studio-dist/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  402. package/studio-dist/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  403. package/studio-dist/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  404. package/studio-dist/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  405. package/studio-dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  406. package/studio-dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  407. package/studio-dist/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  408. package/studio-dist/favicon.svg +1 -0
  409. package/studio-dist/icons.svg +24 -0
  410. package/studio-dist/index.html +14 -0
  411. package/templates/skills/emberflow-basics/SKILL.md +316 -0
  412. package/templates/skills/emberflow-model-process/SKILL.md +209 -0
  413. package/templates/skills/emberflow-new-workflow/SKILL.md +211 -0
  414. package/templates/skills/emberflow-review-workflow/SKILL.md +148 -0
@@ -0,0 +1,314 @@
1
+ import type {
2
+ LogLine,
3
+ NodeExecutionSample,
4
+ NodeRunState,
5
+ PublishedArtifact,
6
+ WorkflowDefinition,
7
+ WorkflowRun,
8
+ } from '../src/engine';
9
+ import type { ApiTree, FolderNode, ApiNode, OpSummary } from './apiStore';
10
+
11
+ export type { ApiTree, FolderNode, ApiNode, OpSummary } from './apiStore';
12
+
13
+ const DEFAULT_BASE_URL = 'http://127.0.0.1:8092';
14
+
15
+ function baseUrl(): string {
16
+ return process.env.EMBERFLOW_RUNNER_URL ?? DEFAULT_BASE_URL;
17
+ }
18
+
19
+ /** SSE-shaped events emitted on GET /runs/:id/events — mirrors server/runRegistry.ts RunEvent. */
20
+ export type RunEvent =
21
+ | { type: 'nodeState'; nodeId: string; state: NodeRunState }
22
+ | { type: 'log'; line: LogLine }
23
+ | { type: 'finished'; run: WorkflowRun };
24
+
25
+ /** Thrown when the runner cannot be reached at all (connection refused, DNS, etc). */
26
+ export class RunnerUnreachableError extends Error {
27
+ constructor(cause?: unknown) {
28
+ super(`runner unreachable at ${baseUrl()} — is \`npm run server\` running?`);
29
+ this.name = 'RunnerUnreachableError';
30
+ this.cause = cause;
31
+ }
32
+ }
33
+
34
+ async function request<T>(path: string, init?: RequestInit): Promise<T> {
35
+ let res: Response;
36
+ try {
37
+ res = await fetch(`${baseUrl()}${path}`, init);
38
+ } catch (err) {
39
+ throw new RunnerUnreachableError(err);
40
+ }
41
+ if (!res.ok) {
42
+ let message = `${res.status} ${res.statusText}`;
43
+ try {
44
+ const body = (await res.json()) as { error?: unknown };
45
+ if (body && typeof body.error === 'string') message = body.error;
46
+ } catch {
47
+ /* body wasn't JSON — keep the status text */
48
+ }
49
+ throw new Error(message);
50
+ }
51
+ if (res.status === 204) return undefined as T;
52
+ return (await res.json()) as T;
53
+ }
54
+
55
+ export async function health(): Promise<{ status: string }> {
56
+ return request('/healthz');
57
+ }
58
+
59
+ export async function listWorkflows(): Promise<WorkflowDefinition[]> {
60
+ const { flows } = await request<{ flows: WorkflowDefinition[] }>('/workflows');
61
+ return flows;
62
+ }
63
+
64
+ /** Fetches a single flow by id from the full workflow list (no single-flow GET endpoint). */
65
+ export async function getWorkflow(id: string): Promise<WorkflowDefinition | undefined> {
66
+ const flows = await listWorkflows();
67
+ return flows.find((f) => f.id === id);
68
+ }
69
+
70
+ export interface NodeMeta {
71
+ type: string;
72
+ label?: string;
73
+ description?: string;
74
+ category?: string;
75
+ traceKind?: string;
76
+ effects?: string;
77
+ inputSchema?: unknown;
78
+ outputSchema?: unknown;
79
+ source?: string;
80
+ }
81
+
82
+ /** The runner's LIVE node registry (built-ins + the project's registerNodes),
83
+ * so the CLI sees the same nodes execution does — not a project-blind local
84
+ * createDefaultRegistry(). */
85
+ export async function listNodes(): Promise<NodeMeta[]> {
86
+ const { nodes } = await request<{ nodes: NodeMeta[] }>('/nodes');
87
+ return nodes;
88
+ }
89
+
90
+ /** Validate a flow against the runner's live registry (built-ins + project nodes). */
91
+ export async function validateOperation(
92
+ flow: WorkflowDefinition,
93
+ ): Promise<{ valid: boolean; issues: unknown[] }> {
94
+ return request('/validate', {
95
+ method: 'POST',
96
+ headers: { 'Content-Type': 'application/json' },
97
+ body: JSON.stringify({ flow }),
98
+ });
99
+ }
100
+
101
+ export async function saveWorkflow(flow: WorkflowDefinition): Promise<void> {
102
+ await request(`/workflows/${encodeURIComponent(flow.id)}`, {
103
+ method: 'PUT',
104
+ headers: { 'Content-Type': 'application/json' },
105
+ body: JSON.stringify(flow),
106
+ });
107
+ }
108
+
109
+ /** One summary per operation with its on-disk `path` (id === path) and `http`
110
+ * trigger metadata (undefined for internal sub-flows). Sourced from the
111
+ * `operations[]` array of `GET /workflows`. */
112
+ export async function listOperations(): Promise<OpSummary[]> {
113
+ const { operations } = await request<{ operations: OpSummary[] }>('/workflows');
114
+ return operations;
115
+ }
116
+
117
+ /** Builds the API tree (apis → folders → operations) client-side from the flat
118
+ * `operations[]` summaries, splitting each op's `path` into [api, …folders, op].
119
+ * Mirrors the server's `ApiStore.tree()` so no extra runner route is needed. */
120
+ export async function apiTree(): Promise<ApiTree> {
121
+ const ops = await listOperations();
122
+ const apis = new Map<string, ApiNode>();
123
+ const folderAt = (parent: { folders: FolderNode[] }, name: string): FolderNode => {
124
+ let f = parent.folders.find((x) => x.name === name);
125
+ if (!f) { f = { name, folders: [], operations: [] }; parent.folders.push(f); }
126
+ return f;
127
+ };
128
+ for (const op of ops) {
129
+ const parts = op.path.split('/'); // [api, ...folders, opName]
130
+ const apiName = parts[0];
131
+ let api = apis.get(apiName);
132
+ if (!api) { api = { name: apiName, folders: [], operations: [] }; apis.set(apiName, api); }
133
+ let container: { folders: FolderNode[]; operations: OpSummary[] } = api;
134
+ for (const fp of parts.slice(1, -1)) container = folderAt(container, fp);
135
+ container.operations.push(op);
136
+ }
137
+ return { apis: [...apis.values()] };
138
+ }
139
+
140
+ /** Result of a create-operation attempt: `ok: false` always carries a message
141
+ * (e.g. a 409 collision) so a creation failure is never silent. */
142
+ export interface CreateOperationResult { ok: boolean; error?: string }
143
+
144
+ /**
145
+ * Creates a brand-new operation at an explicit `apis/` path via
146
+ * `POST /operations { flow, path }`. The runner enforces `flow.id === path` and
147
+ * 409s if an operation already exists at that path (never overwrites — that's
148
+ * `saveWorkflow`/PUT). Mirrors `src/store/serverRunner.ts createOperationOnServer`.
149
+ */
150
+ /** Delete an operation by id (its apis-tree path). id is URL-encoded so slash
151
+ * ids match the /workflows/:id route. Returns ok:false with a message on 404. */
152
+ export async function deleteOperation(id: string): Promise<CreateOperationResult> {
153
+ let res: Response;
154
+ try {
155
+ res = await fetch(`${baseUrl()}/workflows/${encodeURIComponent(id)}`, { method: 'DELETE' });
156
+ } catch (err) {
157
+ throw new RunnerUnreachableError(err);
158
+ }
159
+ if (res.status === 204 || res.ok) return { ok: true };
160
+ const body = (await res.json().catch(() => undefined)) as { error?: string } | undefined;
161
+ return { ok: false, error: body?.error ?? `Delete failed with status ${res.status}` };
162
+ }
163
+
164
+ export async function createOperation(
165
+ flow: WorkflowDefinition,
166
+ path: string,
167
+ ): Promise<CreateOperationResult> {
168
+ let res: Response;
169
+ try {
170
+ res = await fetch(`${baseUrl()}/operations`, {
171
+ method: 'POST',
172
+ headers: { 'Content-Type': 'application/json' },
173
+ body: JSON.stringify({ flow, path }),
174
+ });
175
+ } catch (err) {
176
+ throw new RunnerUnreachableError(err);
177
+ }
178
+ if (res.ok) return { ok: true };
179
+ const body = (await res.json().catch(() => undefined)) as { error?: string } | undefined;
180
+ return { ok: false, error: body?.error ?? `Request failed with status ${res.status}` };
181
+ }
182
+
183
+ export interface StartRunOptions {
184
+ /** A flow to run under dev semantics (mutually exclusive with `artifact`). */
185
+ flow?: WorkflowDefinition;
186
+ /** A sealed artifact to run under production semantics (mutually exclusive with `flow`). */
187
+ artifact?: PublishedArtifact;
188
+ /** Pinned node outputs; ignored/rejected by the runner in production. */
189
+ pins?: Record<string, unknown>;
190
+ /** The invocation payload, exposed to nodes as ctx.runInput. */
191
+ input?: Record<string, unknown>;
192
+ /** Explicit env override; artifact runs always force 'production' regardless. */
193
+ env?: 'dev' | 'production';
194
+ /** Named environment to run against (from emberflow.environments.json); omitted → runner default. */
195
+ environment?: string;
196
+ /** Explicit safe-mode override; omitted → environment's default (protected ⇒ true). */
197
+ safeMode?: boolean;
198
+ /** Required to equal `environment` when explicitly disabling safe mode on a protected environment. */
199
+ confirm?: string;
200
+ }
201
+
202
+ export async function startRun(opts: StartRunOptions): Promise<string> {
203
+ const { flow, artifact, pins, input, env, environment, safeMode, confirm } = opts;
204
+ const { runId } = await request<{ runId: string }>('/runs', {
205
+ method: 'POST',
206
+ headers: { 'Content-Type': 'application/json' },
207
+ body: JSON.stringify({ flow, artifact, mode: 'run', pins, input, env, environment, safeMode, confirm }),
208
+ });
209
+ return runId;
210
+ }
211
+
212
+ export interface EnvironmentSummary {
213
+ name: string;
214
+ protected: boolean;
215
+ varKeys: string[];
216
+ secretKeys: string[];
217
+ auth?: { configured: boolean; authenticated: boolean; secretRef?: string };
218
+ }
219
+
220
+ export async function listEnvironments(): Promise<{ defaultEnvironment: string; environments: EnvironmentSummary[] }> {
221
+ return request('/environments');
222
+ }
223
+
224
+ /** Performs the named environment's configured login, storing the captured
225
+ * credential runner-side. Never returns the secret value — only whether the
226
+ * login succeeded and which secret it landed in. */
227
+ export async function loginEnvironment(name: string): Promise<{ authenticated: boolean; secretRef: string }> {
228
+ return request(`/environments/${encodeURIComponent(name)}/login`, { method: 'POST' });
229
+ }
230
+
231
+ /** Sets (or, when `auth` is `null`, clears) an environment's auth config via
232
+ * `PUT /environments/:name/auth`. Never sends secret values — `auth` carries
233
+ * only refs/names (attach.secretRef, login.request.bodyRef). 204 on success. */
234
+ export async function setEnvironmentAuth(name: string, auth: unknown): Promise<void> {
235
+ await request(`/environments/${encodeURIComponent(name)}/auth`, {
236
+ method: 'PUT',
237
+ headers: { 'Content-Type': 'application/json' },
238
+ body: JSON.stringify(auth),
239
+ });
240
+ }
241
+
242
+ /** Flips whether mounted HTTP endpoints execute for real or answer from
243
+ * scenario expectations (mock), via `POST /serving`. 204 on success; a
244
+ * bogus mode is rejected by the runner (surfaced via request()'s error path). */
245
+ export async function setServingMode(mode: 'real' | 'mock'): Promise<void> {
246
+ await request('/serving', {
247
+ method: 'POST',
248
+ headers: { 'Content-Type': 'application/json' },
249
+ body: JSON.stringify({ mode }),
250
+ });
251
+ }
252
+
253
+ export async function samples(nodeId: string): Promise<NodeExecutionSample[]> {
254
+ const { samples: results } = await request<{ samples: NodeExecutionSample[] }>(
255
+ `/samples?nodeId=${encodeURIComponent(nodeId)}`,
256
+ );
257
+ return results;
258
+ }
259
+
260
+ /**
261
+ * Opens the run's SSE stream and collects events until `finished`.
262
+ * Parses the stream by hand: messages are separated by a blank line, each
263
+ * made of `event:`/`data:` lines; lines starting with `:` are heartbeat
264
+ * comments and are ignored.
265
+ */
266
+ export async function waitForRun(runId: string): Promise<{ run: WorkflowRun; logs: LogLine[] }> {
267
+ let res: Response;
268
+ try {
269
+ res = await fetch(`${baseUrl()}/runs/${encodeURIComponent(runId)}/events`);
270
+ } catch (err) {
271
+ throw new RunnerUnreachableError(err);
272
+ }
273
+ if (!res.ok || !res.body) {
274
+ throw new Error(`Failed to open event stream for run ${runId}: ${res.status} ${res.statusText}`);
275
+ }
276
+
277
+ const reader = res.body.getReader();
278
+ const decoder = new TextDecoder();
279
+ let buffer = '';
280
+ const logs: LogLine[] = [];
281
+ let finalRun: WorkflowRun | undefined;
282
+
283
+ const processMessage = (raw: string): void => {
284
+ const dataLines: string[] = [];
285
+ for (const line of raw.split('\n')) {
286
+ if (line.length === 0 || line.startsWith(':')) continue;
287
+ if (line.startsWith('data:')) dataLines.push(line.slice(5).trimStart());
288
+ }
289
+ if (dataLines.length === 0) return;
290
+ const event = JSON.parse(dataLines.join('\n')) as RunEvent;
291
+ if (event.type === 'log') logs.push(event.line);
292
+ else if (event.type === 'finished') finalRun = event.run;
293
+ };
294
+
295
+ try {
296
+ while (!finalRun) {
297
+ const { done, value } = await reader.read();
298
+ if (done) break;
299
+ buffer += decoder.decode(value, { stream: true });
300
+ let sepIndex: number;
301
+ while ((sepIndex = buffer.indexOf('\n\n')) !== -1) {
302
+ const raw = buffer.slice(0, sepIndex);
303
+ buffer = buffer.slice(sepIndex + 2);
304
+ processMessage(raw);
305
+ if (finalRun) break;
306
+ }
307
+ }
308
+ } finally {
309
+ reader.cancel().catch(() => {});
310
+ }
311
+
312
+ if (!finalRun) throw new Error(`Run ${runId} stream ended before a "finished" event was received`);
313
+ return { run: finalRun, logs };
314
+ }
@@ -0,0 +1,29 @@
1
+ // server/demoProject.test.ts
2
+ import { resolve } from 'node:path';
3
+ import { describe, expect, it } from 'vitest';
4
+ import { loadProjectConfig } from './projectConfig';
5
+ import { buildFlowStore, buildRegistries } from './projectMode';
6
+ import { startRun } from '../src/engine';
7
+
8
+ const FIXTURE = resolve(__dirname, '../examples/demo-project');
9
+
10
+ describe('demo project (committed fixture)', () => {
11
+ it('loads, registers TriageOrder, and every scenario runs green', async () => {
12
+ const project = await loadProjectConfig(FIXTURE);
13
+ expect(project).not.toBeNull();
14
+ const store = buildFlowStore(project);
15
+ const flow = store.load('order-triage')!;
16
+ expect(flow.scenarios).toHaveLength(3);
17
+ const { execution } = buildRegistries(project);
18
+ const expected: Record<string, { tier: string; rush: boolean }> = {
19
+ 'standard-order': { tier: 'standard', rush: false },
20
+ 'priority-rush': { tier: 'priority', rush: true },
21
+ vip: { tier: 'vip', rush: false },
22
+ };
23
+ for (const sc of flow.scenarios!) {
24
+ const run = await startRun({ flow, registry: execution, input: sc.input }).runToEnd();
25
+ expect(run.status).toBe('succeeded');
26
+ expect(run.nodeStates.triage.output).toEqual(expected[sc.name]);
27
+ }
28
+ });
29
+ });
@@ -0,0 +1,169 @@
1
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
2
+ import { spawn, type ChildProcess } from 'node:child_process';
3
+ import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
5
+ import { join } from 'node:path';
6
+
7
+ // Verifies GET /workflows/:id/diagnostics (Task 2) plus normalize-on-write
8
+ // (seedParamDefaults called from PUT /workflows/:id and POST /operations
9
+ // before persisting). Boots the real runner subprocess against a scratch
10
+ // project dir, mirroring server/workflowTestRoute.test.ts's harness.
11
+
12
+ let proc: ChildProcess;
13
+ const PORT = 8146;
14
+ const base = `http://127.0.0.1:${PORT}`;
15
+ let projectDir: string;
16
+ let apisDir: string;
17
+
18
+ async function waitHealthy(url: string, tries = 40): Promise<void> {
19
+ for (let i = 0; i < tries; i++) {
20
+ try {
21
+ if ((await fetch(url)).ok) return;
22
+ } catch {
23
+ /* not up yet */
24
+ }
25
+ await new Promise((r) => setTimeout(r, 150));
26
+ }
27
+ throw new Error('runner did not become healthy');
28
+ }
29
+
30
+ function bootRunner(port: number, env: Record<string, string | undefined>): ChildProcess {
31
+ return spawn('npx', ['tsx', 'server/index.ts'], {
32
+ env: { ...process.env, EMBERFLOW_RUNNER_PORT: String(port), ...env },
33
+ stdio: 'ignore',
34
+ });
35
+ }
36
+
37
+ function noParamOp(id: string) {
38
+ return {
39
+ id,
40
+ name: id,
41
+ version: 1,
42
+ http: { method: 'GET', path: `/${id}` },
43
+ nodes: [
44
+ {
45
+ id: 'input',
46
+ type: 'Input',
47
+ label: 'Input',
48
+ position: { x: 0, y: 0 },
49
+ config: { fields: [] },
50
+ },
51
+ {
52
+ id: 'response',
53
+ type: 'Response',
54
+ label: 'Response',
55
+ position: { x: 200, y: 0 },
56
+ config: { status: 200, body: { ok: true } },
57
+ },
58
+ ],
59
+ edges: [{ id: 'e1', source: 'input', target: 'response' }],
60
+ createdAt: '2026-01-01T00:00:00Z',
61
+ updatedAt: '2026-01-01T00:00:00Z',
62
+ };
63
+ }
64
+
65
+ function withParamNoDefault(id: string) {
66
+ const op = noParamOp(id);
67
+ op.http = { method: 'GET', path: `/${id}/:id` };
68
+ return op;
69
+ }
70
+
71
+ beforeAll(async () => {
72
+ projectDir = mkdtempSync(join(tmpdir(), 'diagnosticsroute-'));
73
+ writeFileSync(join(projectDir, 'emberflow.config.mjs'), 'export default {};\n');
74
+ apisDir = join(projectDir, 'emberflow', 'apis', 'default');
75
+ mkdirSync(apisDir, { recursive: true });
76
+
77
+ writeFileSync(join(apisDir, 'needs-default.json'), JSON.stringify(withParamNoDefault('needs-default')));
78
+
79
+ proc = bootRunner(PORT, { EMBERFLOW_PROJECT: projectDir });
80
+ await waitHealthy(`${base}/healthz`);
81
+ }, 20_000);
82
+
83
+ afterAll(async () => {
84
+ proc?.kill();
85
+ if (projectDir) rmSync(projectDir, { recursive: true, force: true });
86
+ });
87
+
88
+ describe('GET /workflows/:id/diagnostics', () => {
89
+ it('includes missing-param-default for a path param with no default', async () => {
90
+ const res = await fetch(`${base}/api/workflows/needs-default/diagnostics`);
91
+ expect(res.status).toBe(200);
92
+ const body = await res.json();
93
+ const codes = body.diagnostics.map((d: { code: string }) => d.code);
94
+ expect(codes).toContain('missing-param-default');
95
+ const diag = body.diagnostics.find((d: { code: string }) => d.code === 'missing-param-default');
96
+ expect(diag.severity).toBe('warning');
97
+ expect(diag.param).toBe('id');
98
+ });
99
+
100
+ it('404s for an unknown op id', async () => {
101
+ const res = await fetch(`${base}/api/workflows/no-such-op/diagnostics`);
102
+ expect(res.status).toBe(404);
103
+ const body = await res.json();
104
+ expect(body.error).toBeTruthy();
105
+ });
106
+ });
107
+
108
+ describe('normalize-on-write: PUT /workflows/:id', () => {
109
+ it('seeds an empty-string default for a path param missing one, and persists it to disk', async () => {
110
+ const flow = withParamNoDefault('default/put-seed-test');
111
+ const createRes = await fetch(`${base}/api/operations`, {
112
+ method: 'POST',
113
+ headers: { 'Content-Type': 'application/json' },
114
+ body: JSON.stringify({ flow, path: 'default/put-seed-test' }),
115
+ });
116
+ expect(createRes.status).toBe(201);
117
+
118
+ const putRes = await fetch(`${base}/api/workflows/${encodeURIComponent('default/put-seed-test')}`, {
119
+ method: 'PUT',
120
+ headers: { 'Content-Type': 'application/json' },
121
+ body: JSON.stringify(flow),
122
+ });
123
+ expect(putRes.status).toBe(200);
124
+
125
+ const onDisk = JSON.parse(readFileSync(join(apisDir, 'put-seed-test.json'), 'utf8'));
126
+ expect(onDisk.nodes.find((n: { type: string }) => n.type === 'Input').config.defaults.params.id).toBe('');
127
+ });
128
+
129
+ it('preserves an existing real default value on PUT — never overwrites', async () => {
130
+ const flow = withParamNoDefault('default/put-preserve-test');
131
+ (flow.nodes[0] as { config: Record<string, unknown> }).config = {
132
+ fields: [],
133
+ defaults: { params: { id: 'real-id-value' } },
134
+ };
135
+ const createRes = await fetch(`${base}/api/operations`, {
136
+ method: 'POST',
137
+ headers: { 'Content-Type': 'application/json' },
138
+ body: JSON.stringify({ flow, path: 'default/put-preserve-test' }),
139
+ });
140
+ expect(createRes.status).toBe(201);
141
+
142
+ const putRes = await fetch(`${base}/api/workflows/${encodeURIComponent('default/put-preserve-test')}`, {
143
+ method: 'PUT',
144
+ headers: { 'Content-Type': 'application/json' },
145
+ body: JSON.stringify(flow),
146
+ });
147
+ expect(putRes.status).toBe(200);
148
+
149
+ const onDisk = JSON.parse(readFileSync(join(apisDir, 'put-preserve-test.json'), 'utf8'));
150
+ expect(onDisk.nodes.find((n: { type: string }) => n.type === 'Input').config.defaults.params.id).toBe(
151
+ 'real-id-value',
152
+ );
153
+ });
154
+ });
155
+
156
+ describe('normalize-on-write: POST /operations', () => {
157
+ it('seeds an empty-string default for a path param missing one, and persists it to disk', async () => {
158
+ const flow = withParamNoDefault('default/post-seed-test');
159
+ const res = await fetch(`${base}/api/operations`, {
160
+ method: 'POST',
161
+ headers: { 'Content-Type': 'application/json' },
162
+ body: JSON.stringify({ flow, path: 'default/post-seed-test' }),
163
+ });
164
+ expect(res.status).toBe(201);
165
+
166
+ const onDisk = JSON.parse(readFileSync(join(apisDir, 'post-seed-test.json'), 'utf8'));
167
+ expect(onDisk.nodes.find((n: { type: string }) => n.type === 'Input').config.defaults.params.id).toBe('');
168
+ });
169
+ });