@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,476 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { FlaskConicalIcon, Loader2Icon, PencilIcon, PlayIcon, PlusIcon, SparklesIcon, Trash2Icon } from 'lucide-react';
3
+ import { Button } from '@/components/ui/button';
4
+ import { Input } from '@/components/ui/input';
5
+ import { useBuilderStore } from '../store/builderStore';
6
+ import { cn } from '@/lib/utils';
7
+ import type {
8
+ FieldDefinition, ScenarioDefinition, ScenarioExpectation, WorkflowDefinition,
9
+ } from '../engine';
10
+ import type { ScenarioTestResult } from '../store/serverRunner';
11
+
12
+ const statusDot: Record<string, string> = {
13
+ succeeded: 'bg-success',
14
+ failed: 'bg-destructive',
15
+ cancelled: 'bg-muted-foreground',
16
+ running: 'bg-highlight animate-pulse',
17
+ };
18
+
19
+ /** Compact single-line payload preview: {points: 30, spikeIndex: 25}. */
20
+ function previewPayload(input: Record<string, unknown>): string {
21
+ const parts = Object.entries(input).map(([k, v]) => `${k}: ${JSON.stringify(v)}`);
22
+ return `{${parts.join(', ')}}`;
23
+ }
24
+
25
+ /** Starter payload from the Input node: defaults, plus blanks for declared fields. */
26
+ function seedPayload(flow: WorkflowDefinition): Record<string, unknown> {
27
+ const inputNode = flow.nodes.find((n) => n.type === 'Input');
28
+ if (!inputNode) return {};
29
+ const fields = Array.isArray(inputNode.config.fields)
30
+ ? (inputNode.config.fields as FieldDefinition[])
31
+ : [];
32
+ const defaults =
33
+ inputNode.config.defaults && typeof inputNode.config.defaults === 'object'
34
+ ? (inputNode.config.defaults as Record<string, unknown>)
35
+ : {};
36
+ const blank: Record<string, unknown> = {
37
+ string: '', number: 0, boolean: false, object: {}, array: [], enum: '', datetime: '',
38
+ };
39
+ const seed: Record<string, unknown> = {};
40
+ for (const f of fields) {
41
+ seed[f.name] = f.name in defaults ? defaults[f.name] : (blank[f.type] ?? '');
42
+ }
43
+ return seed;
44
+ }
45
+
46
+ interface EditorState {
47
+ /** Scenario id being edited, or 'new'. */
48
+ target: string;
49
+ name: string;
50
+ description: string;
51
+ payload: string;
52
+ /** Expect fields, all as raw editor strings; empty = unset. */
53
+ expectStatus: string;
54
+ expectNodes: string;
55
+ expectBody: string;
56
+ error: string | null;
57
+ }
58
+
59
+ /** Editor strings → ScenarioExpectation (undefined when all empty), or an error. */
60
+ function buildExpect(state: EditorState): { expect?: ScenarioExpectation } | { error: string } {
61
+ const expect: ScenarioExpectation = {};
62
+ if (state.expectStatus.trim()) {
63
+ const status = Number(state.expectStatus.trim());
64
+ if (!Number.isInteger(status) || status <= 0) {
65
+ return { error: 'Expected status must be a positive integer' };
66
+ }
67
+ expect.status = status;
68
+ }
69
+ const nodes = state.expectNodes.split(',').map((s) => s.trim()).filter(Boolean);
70
+ if (nodes.length > 0) expect.executedNodes = nodes;
71
+ if (state.expectBody.trim()) {
72
+ try {
73
+ expect.body = JSON.parse(state.expectBody) as unknown;
74
+ } catch {
75
+ return { error: 'Expected body must be valid JSON' };
76
+ }
77
+ }
78
+ return Object.keys(expect).length > 0 ? { expect } : {};
79
+ }
80
+
81
+ /** Compact chip text for a scenario's expectation: "→ 401 · body · nodes". */
82
+ function expectChipText(expect: ScenarioExpectation): string {
83
+ const parts: string[] = [];
84
+ if (expect.status !== undefined) parts.push(String(expect.status));
85
+ if (expect.body !== undefined) parts.push('body');
86
+ if (expect.executedNodes?.length) parts.push('nodes');
87
+ return `→ ${parts.join(' · ')}`;
88
+ }
89
+
90
+ function ScenarioEditor({
91
+ state,
92
+ onChange,
93
+ onSave,
94
+ onCancel,
95
+ }: {
96
+ state: EditorState;
97
+ onChange: (next: EditorState) => void;
98
+ onSave: () => void;
99
+ onCancel: () => void;
100
+ }) {
101
+ return (
102
+ <div className="mt-1 space-y-2 rounded-md border border-border bg-card/50 p-3">
103
+ <div className="grid grid-cols-2 gap-2">
104
+ <Input
105
+ value={state.name}
106
+ onChange={(e) => onChange({ ...state, name: e.target.value })}
107
+ placeholder="Scenario name"
108
+ autoFocus
109
+ />
110
+ <Input
111
+ value={state.description}
112
+ onChange={(e) => onChange({ ...state, description: e.target.value })}
113
+ placeholder="What this scenario demonstrates (optional)"
114
+ />
115
+ </div>
116
+ <textarea
117
+ value={state.payload}
118
+ onChange={(e) => onChange({ ...state, payload: e.target.value, error: null })}
119
+ spellCheck={false}
120
+ rows={5}
121
+ className="w-full resize-y rounded-md border border-border bg-background p-3 font-mono text-[12px] leading-relaxed outline-none focus-visible:ring-ring/50 focus-visible:ring-[3px]"
122
+ />
123
+ <div className="space-y-1.5 rounded-md border border-border/60 bg-background/50 p-2.5">
124
+ <div className="text-[10px] font-medium uppercase tracking-widest text-muted-foreground">
125
+ Expect <span className="normal-case tracking-normal">(optional — makes this scenario a test for `emberflow test` and the Test all button)</span>
126
+ </div>
127
+ <div className="grid grid-cols-2 gap-2">
128
+ <Input
129
+ value={state.expectStatus}
130
+ onChange={(e) => onChange({ ...state, expectStatus: e.target.value, error: null })}
131
+ placeholder="status, e.g. 200"
132
+ spellCheck={false}
133
+ className="font-mono text-[12px]"
134
+ />
135
+ <Input
136
+ value={state.expectNodes}
137
+ onChange={(e) => onChange({ ...state, expectNodes: e.target.value, error: null })}
138
+ placeholder="executed nodes, e.g. response-ok"
139
+ spellCheck={false}
140
+ className="font-mono text-[12px]"
141
+ />
142
+ </div>
143
+ <textarea
144
+ value={state.expectBody}
145
+ onChange={(e) => onChange({ ...state, expectBody: e.target.value, error: null })}
146
+ spellCheck={false}
147
+ rows={2}
148
+ placeholder='body subset, e.g. {"ok": true} — extra keys in the real response are fine'
149
+ className="w-full resize-y rounded-md border border-border bg-background p-2.5 font-mono text-[11.5px] leading-relaxed outline-none placeholder:text-muted-foreground/50 focus-visible:ring-ring/50 focus-visible:ring-[3px]"
150
+ />
151
+ </div>
152
+ {state.error && <div className="text-[12px] text-destructive">{state.error}</div>}
153
+ <div className="flex items-center gap-2">
154
+ <Button size="sm" onClick={onSave} disabled={state.name.trim().length === 0}>
155
+ Save scenario
156
+ </Button>
157
+ <Button size="sm" variant="ghost" onClick={onCancel}>
158
+ Cancel
159
+ </Button>
160
+ </div>
161
+ </div>
162
+ );
163
+ }
164
+
165
+ /**
166
+ * Storybook-style list of a flow's named test inputs. Each scenario runs the
167
+ * whole flow with its payload so branches can be exercised one story at a time.
168
+ */
169
+ export function ScenariosPanel({ autoNew = false }: { autoNew?: boolean } = {}) {
170
+ const flow = useBuilderStore((s) => s.flow);
171
+ const run = useBuilderStore((s) => s.run);
172
+ const runHistory = useBuilderStore((s) => s.runHistory);
173
+ const runScenario = useBuilderStore((s) => s.runScenario);
174
+ const addScenario = useBuilderStore((s) => s.addScenario);
175
+ const updateScenario = useBuilderStore((s) => s.updateScenario);
176
+ const removeScenario = useBuilderStore((s) => s.removeScenario);
177
+ const testWorkflow = useBuilderStore((s) => s.testWorkflow);
178
+ const testReport = useBuilderStore((s) => s.scenarioTestReports[s.flow.id]);
179
+ const testPending = useBuilderStore((s) => s.scenarioTestPending === s.flow.id);
180
+ const runnerOnline = useBuilderStore((s) => s.runnerOnline);
181
+ const runAgent = useBuilderStore((s) => s.runAgent);
182
+ const agentRunning = useBuilderStore((s) => s.agentRun?.status === 'running');
183
+ const [editor, setEditor] = useState<EditorState | null>(null);
184
+ const [testError, setTestError] = useState<string | null>(null);
185
+
186
+ const scenarios = flow.scenarios ?? [];
187
+ const hasInputNode = flow.nodes.some((n) => n.type === 'Input');
188
+ const busy = run?.status === 'running';
189
+ const hasExpects = scenarios.some((sc) => sc.expect && Object.keys(sc.expect).length > 0);
190
+
191
+ const resultFor = (sc: ScenarioDefinition): ScenarioTestResult | undefined =>
192
+ testReport?.results.find((r) => r.scenario === sc.name);
193
+
194
+ const onCoverWithAi = () =>
195
+ void runAgent({
196
+ action: 'cover-operation',
197
+ flowId: flow.id,
198
+ instruction:
199
+ 'Cover this operation: one scenario per branch, each with an expect, verified with the test command.',
200
+ });
201
+
202
+ const onTestAll = async () => {
203
+ setTestError(null);
204
+ try {
205
+ await testWorkflow(flow.id);
206
+ } catch (err) {
207
+ setTestError(err instanceof Error ? err.message : 'Test run failed');
208
+ }
209
+ };
210
+
211
+ // Opened via "New scenario…": jump straight into the create editor.
212
+ const blankEditor = (): EditorState => ({
213
+ target: 'new',
214
+ name: '',
215
+ description: '',
216
+ payload: JSON.stringify(seedPayload(flow), null, 2),
217
+ expectStatus: '',
218
+ expectNodes: '',
219
+ expectBody: '',
220
+ error: null,
221
+ });
222
+
223
+ useEffect(() => {
224
+ if (autoNew) setEditor(blankEditor());
225
+ // Seed once on mount for the create entry point.
226
+ // eslint-disable-next-line react-hooks/exhaustive-deps
227
+ }, [autoNew]);
228
+
229
+ const lastRunFor = (sc: ScenarioDefinition) =>
230
+ runHistory.find((r) => r.workflowId === flow.id && r.scenarioName === sc.name);
231
+
232
+ const openEditor = (sc?: ScenarioDefinition) =>
233
+ setEditor(
234
+ sc
235
+ ? {
236
+ target: sc.id,
237
+ name: sc.name,
238
+ description: sc.description ?? '',
239
+ payload: JSON.stringify(sc.input, null, 2),
240
+ expectStatus: sc.expect?.status !== undefined ? String(sc.expect.status) : '',
241
+ expectNodes: sc.expect?.executedNodes?.join(', ') ?? '',
242
+ expectBody:
243
+ sc.expect?.body !== undefined ? JSON.stringify(sc.expect.body, null, 2) : '',
244
+ error: null,
245
+ }
246
+ : blankEditor(),
247
+ );
248
+
249
+ const saveEditor = () => {
250
+ if (!editor) return;
251
+ let input: Record<string, unknown>;
252
+ try {
253
+ const parsed: unknown = JSON.parse(editor.payload);
254
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
255
+ throw new Error('Payload must be a JSON object');
256
+ }
257
+ input = parsed as Record<string, unknown>;
258
+ } catch (err) {
259
+ setEditor({ ...editor, error: err instanceof Error ? err.message : String(err) });
260
+ return;
261
+ }
262
+ const built = buildExpect(editor);
263
+ if ('error' in built) {
264
+ setEditor({ ...editor, error: built.error });
265
+ return;
266
+ }
267
+ const description = editor.description.trim() || undefined;
268
+ if (editor.target === 'new') {
269
+ addScenario(editor.name.trim(), input, description, built.expect);
270
+ } else {
271
+ // `expect: undefined` deliberately clears a removed expectation —
272
+ // JSON serialization drops the key on save.
273
+ updateScenario(editor.target, {
274
+ name: editor.name.trim(),
275
+ description,
276
+ input,
277
+ expect: built.expect,
278
+ });
279
+ }
280
+ setEditor(null);
281
+ };
282
+
283
+ if (scenarios.length === 0 && !editor) {
284
+ return (
285
+ <div className="px-1 py-2.5">
286
+ <div className="text-[12.5px] leading-relaxed text-muted-foreground/70">
287
+ Scenarios are example inputs for this operation — one per situation you want to see
288
+ it handle. Give a scenario an <span className="font-mono text-[11.5px]">expect</span>{' '}
289
+ and it becomes a test: <span className="font-mono text-[11.5px]">emberflow test</span>{' '}
290
+ and the Test all button will assert it.
291
+ </div>
292
+ <div className="mt-2.5 flex gap-2">
293
+ <Button
294
+ size="sm"
295
+ variant="outline"
296
+ className="gap-1.5"
297
+ disabled={agentRunning}
298
+ onClick={onCoverWithAi}
299
+ >
300
+ <SparklesIcon className="size-3.5" />
301
+ Cover with AI
302
+ </Button>
303
+ <Button size="sm" variant="ghost" className="gap-1.5 text-muted-foreground" onClick={() => openEditor()}>
304
+ <PlusIcon className="size-3.5" />
305
+ Add manually
306
+ </Button>
307
+ </div>
308
+ </div>
309
+ );
310
+ }
311
+
312
+ return (
313
+ <div className="space-y-0.5">
314
+ {!hasInputNode && (
315
+ <div className="px-2 py-1.5 text-[12px] text-muted-foreground/70">
316
+ This flow has no Input node, so scenario payloads are never consumed. Add an
317
+ Input node to drive it.
318
+ </div>
319
+ )}
320
+ <div className="flex items-center gap-2.5 px-2 pb-1.5">
321
+ <Button
322
+ size="sm"
323
+ variant="ghost"
324
+ className="h-6 gap-1.5 text-muted-foreground"
325
+ disabled={agentRunning}
326
+ title="Ask the agent to write one scenario per branch of this operation, each with an expect, and verify them"
327
+ onClick={onCoverWithAi}
328
+ >
329
+ <SparklesIcon className="size-3" />
330
+ Cover with AI
331
+ </Button>
332
+ {hasExpects && (
333
+ <>
334
+ <Button
335
+ size="sm"
336
+ variant="outline"
337
+ className="h-6 gap-1.5"
338
+ disabled={testPending || runnerOnline !== true}
339
+ title={runnerOnline !== true ? 'Runner offline — tests run on the runner' : 'Run every scenario that has an expect and check its assertions'}
340
+ onClick={() => void onTestAll()}
341
+ >
342
+ {testPending ? (
343
+ <Loader2Icon className="size-3 animate-spin" />
344
+ ) : (
345
+ <FlaskConicalIcon className="size-3" />
346
+ )}
347
+ Test all
348
+ </Button>
349
+ {testReport && !testPending && (
350
+ <span className="text-[11.5px] text-muted-foreground">
351
+ <span className={cn(testReport.failed > 0 ? 'text-destructive' : 'text-success')}>
352
+ {testReport.failed > 0
353
+ ? `${testReport.failed} failed`
354
+ : `${testReport.passed} passed`}
355
+ </span>
356
+ {testReport.failed > 0 && ` · ${testReport.passed} passed`}
357
+ {testReport.skipped > 0 && ` · ${testReport.skipped} skipped`}
358
+ </span>
359
+ )}
360
+ </>
361
+ )}
362
+ {testError && <span className="truncate text-[11.5px] text-destructive">{testError}</span>}
363
+ </div>
364
+ {scenarios.map((sc) => {
365
+ const last = lastRunFor(sc);
366
+ const result = resultFor(sc);
367
+ return (
368
+ <div key={sc.id}>
369
+ <div className="group flex items-center gap-2.5 rounded-md px-2 py-1 hover:bg-card">
370
+ <Button
371
+ variant="ghost"
372
+ size="icon"
373
+ className="size-6 shrink-0 text-muted-foreground hover:text-highlight"
374
+ disabled={busy}
375
+ onClick={() => void runScenario(sc.id)}
376
+ title={`Run "${sc.name}"`}
377
+ >
378
+ <PlayIcon className="size-3.5" />
379
+ </Button>
380
+ <span
381
+ className={cn(
382
+ 'size-1.5 shrink-0 rounded-full',
383
+ last ? statusDot[last.status] : 'bg-border',
384
+ )}
385
+ title={last ? `Last run ${last.status}` : 'Not run yet'}
386
+ />
387
+ <span className="shrink-0 text-[12.5px] font-medium text-foreground">{sc.name}</span>
388
+ {sc.expect && Object.keys(sc.expect).length > 0 && (
389
+ <span
390
+ className={cn(
391
+ 'shrink-0 rounded-sm border border-border/60 px-1 font-mono text-[10.5px]',
392
+ result?.status === 'passed' && 'border-success/40 text-success',
393
+ result?.status === 'failed' && 'border-destructive/40 text-destructive',
394
+ !result && 'text-muted-foreground/70',
395
+ )}
396
+ title={
397
+ result?.status === 'passed'
398
+ ? 'Last test passed'
399
+ : result?.status === 'failed'
400
+ ? 'Last test failed'
401
+ : 'Expectation — run Test all to assert'
402
+ }
403
+ >
404
+ {result?.status === 'passed' && '✓ '}
405
+ {result?.status === 'failed' && '✗ '}
406
+ {expectChipText(sc.expect)}
407
+ </span>
408
+ )}
409
+ {sc.description && (
410
+ <span className="truncate text-[12px] text-muted-foreground">{sc.description}</span>
411
+ )}
412
+ <span className="ml-auto max-w-72 truncate font-mono text-[11px] text-muted-foreground/60">
413
+ {previewPayload(sc.input)}
414
+ </span>
415
+ <span className="flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100">
416
+ <Button
417
+ variant="ghost"
418
+ size="icon"
419
+ className="size-6 text-muted-foreground"
420
+ onClick={() => openEditor(sc)}
421
+ title="Edit scenario"
422
+ >
423
+ <PencilIcon className="size-3" />
424
+ </Button>
425
+ <Button
426
+ variant="ghost"
427
+ size="icon"
428
+ className="size-6 text-muted-foreground hover:text-destructive"
429
+ onClick={() => removeScenario(sc.id)}
430
+ title="Delete scenario"
431
+ >
432
+ <Trash2Icon className="size-3" />
433
+ </Button>
434
+ </span>
435
+ </div>
436
+ {result?.status === 'failed' && result.failures && (
437
+ <div className="ml-11 space-y-0.5 pb-1">
438
+ {result.failures.map((f, i) => (
439
+ <div key={i} className="font-mono text-[11px] text-destructive/90">
440
+ {f}
441
+ </div>
442
+ ))}
443
+ </div>
444
+ )}
445
+ {editor?.target === sc.id && (
446
+ <ScenarioEditor
447
+ state={editor}
448
+ onChange={setEditor}
449
+ onSave={saveEditor}
450
+ onCancel={() => setEditor(null)}
451
+ />
452
+ )}
453
+ </div>
454
+ );
455
+ })}
456
+ {editor?.target === 'new' ? (
457
+ <ScenarioEditor
458
+ state={editor}
459
+ onChange={setEditor}
460
+ onSave={saveEditor}
461
+ onCancel={() => setEditor(null)}
462
+ />
463
+ ) : (
464
+ <Button
465
+ size="sm"
466
+ variant="ghost"
467
+ className="mt-1 gap-1.5 text-muted-foreground"
468
+ onClick={() => openEditor()}
469
+ >
470
+ <PlusIcon className="size-3.5" />
471
+ New scenario
472
+ </Button>
473
+ )}
474
+ </div>
475
+ );
476
+ }