@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,569 @@
1
+ import { useState } from 'react';
2
+ import { Loader2Icon, PlusIcon, ShieldIcon, SparklesIcon, XIcon } from 'lucide-react';
3
+ import { cn } from '@/lib/utils';
4
+ import { Button } from '@/components/ui/button';
5
+ import { Dialog, DialogContent, DialogDescription, DialogTitle } from '@/components/ui/dialog';
6
+ import { Input } from '@/components/ui/input';
7
+ import { useBuilderStore } from '../store/builderStore';
8
+ import type { EnvAuth, EnvironmentSummary } from '../store/serverRunner';
9
+
10
+ function SectionTitle({ children }: { children: React.ReactNode }) {
11
+ return (
12
+ <div className="text-[10px] font-medium uppercase tracking-widest text-muted-foreground">
13
+ {children}
14
+ </div>
15
+ );
16
+ }
17
+
18
+ /** Inline error line shared by the dialog's sections. */
19
+ function ErrorLine({ message }: { message: string | null }) {
20
+ if (!message) return null;
21
+ return <div className="text-[11.5px] text-destructive">{message}</div>;
22
+ }
23
+
24
+ /**
25
+ * Secrets manager: stored values are write-only — the dialog shows key names
26
+ * and a set/unset state, never a value. New values go straight to the runner
27
+ * (PUT …/secrets/:key) and exist in studio memory only for the duration of
28
+ * the call.
29
+ */
30
+ function SecretsSection({ env }: { env: EnvironmentSummary }) {
31
+ const setEnvironmentSecret = useBuilderStore((s) => s.setEnvironmentSecret);
32
+ const deleteEnvironmentSecret = useBuilderStore((s) => s.deleteEnvironmentSecret);
33
+ const [key, setKey] = useState('');
34
+ const [value, setValue] = useState('');
35
+ const [pending, setPending] = useState<string | null>(null); // key being written/cleared
36
+ const [error, setError] = useState<string | null>(null);
37
+
38
+ const onSet = async () => {
39
+ const k = key.trim();
40
+ if (!k || !value) return;
41
+ setError(null);
42
+ setPending(k);
43
+ try {
44
+ await setEnvironmentSecret(env.name, k, value);
45
+ setKey('');
46
+ setValue('');
47
+ } catch (err) {
48
+ setError(err instanceof Error ? err.message : 'Failed to set secret');
49
+ } finally {
50
+ setPending(null);
51
+ }
52
+ };
53
+
54
+ const onClear = async (k: string) => {
55
+ setError(null);
56
+ setPending(k);
57
+ try {
58
+ await deleteEnvironmentSecret(env.name, k);
59
+ } catch (err) {
60
+ setError(err instanceof Error ? err.message : 'Failed to clear secret');
61
+ } finally {
62
+ setPending(null);
63
+ }
64
+ };
65
+
66
+ return (
67
+ <div className="flex flex-col gap-2">
68
+ <SectionTitle>Secrets</SectionTitle>
69
+ {env.secretKeys.length === 0 && (
70
+ <div className="text-[11.5px] text-muted-foreground">No secrets stored.</div>
71
+ )}
72
+ {env.secretKeys.map((k) => (
73
+ <div key={k} className="flex items-center gap-2 text-[12px]">
74
+ <span className="min-w-0 truncate font-mono">{k}</span>
75
+ <span className="text-muted-foreground">••••••</span>
76
+ <button
77
+ type="button"
78
+ onClick={() => void onClear(k)}
79
+ disabled={pending === k}
80
+ title={`Clear ${k}`}
81
+ className="ml-auto cursor-pointer rounded-sm p-0.5 text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground disabled:opacity-50"
82
+ >
83
+ {pending === k ? (
84
+ <Loader2Icon className="size-3 animate-spin" />
85
+ ) : (
86
+ <XIcon className="size-3" />
87
+ )}
88
+ </button>
89
+ </div>
90
+ ))}
91
+ <div className="flex items-center gap-2">
92
+ <Input
93
+ value={key}
94
+ onChange={(e) => setKey(e.target.value)}
95
+ placeholder="key"
96
+ spellCheck={false}
97
+ className="h-7 flex-1 font-mono text-[12px]"
98
+ />
99
+ <Input
100
+ value={value}
101
+ onChange={(e) => setValue(e.target.value)}
102
+ placeholder="value"
103
+ type="password"
104
+ autoComplete="off"
105
+ className="h-7 flex-1 text-[12px]"
106
+ onKeyDown={(e) => {
107
+ if (e.key === 'Enter') void onSet();
108
+ }}
109
+ />
110
+ <Button
111
+ variant="secondary"
112
+ size="sm"
113
+ className="h-7"
114
+ disabled={!key.trim() || !value || pending !== null}
115
+ onClick={() => void onSet()}
116
+ >
117
+ <PlusIcon className="size-3" />
118
+ Set
119
+ </Button>
120
+ </div>
121
+ <ErrorLine message={error} />
122
+ </div>
123
+ );
124
+ }
125
+
126
+ /** Blank form state derived from an existing config (or sensible defaults). */
127
+ function formFromConfig(config: EnvAuth | undefined) {
128
+ return {
129
+ attachAs: config?.attach.as ?? ('cookie' as 'cookie' | 'header'),
130
+ attachName: config?.attach.name ?? '',
131
+ secretRef: config?.attach.secretRef ?? '',
132
+ prefix: config?.attach.prefix ?? '',
133
+ hasLogin: !!config?.login,
134
+ loginMethod: config?.login?.request.method ?? 'POST',
135
+ loginUrl: config?.login?.request.url ?? '',
136
+ loginHeaders: config?.login?.request.headers
137
+ ? JSON.stringify(config.login.request.headers, null, 2)
138
+ : '',
139
+ bodyRef: config?.login?.request.bodyRef ?? '',
140
+ captureFrom: (config?.login?.capture.from ?? 'set-cookie') as 'set-cookie' | 'json' | 'header',
141
+ captureField:
142
+ config?.login?.capture.from === 'set-cookie'
143
+ ? (config.login.capture.cookieName ?? '')
144
+ : config?.login?.capture.from === 'json'
145
+ ? config.login.capture.path
146
+ : config?.login?.capture.from === 'header'
147
+ ? config.login.capture.name
148
+ : '',
149
+ };
150
+ }
151
+
152
+ const fieldLabel = 'w-24 shrink-0 text-[11px] text-muted-foreground';
153
+ const fieldRow = 'flex items-center gap-2';
154
+ const selectCls =
155
+ 'h-7 rounded-md border border-input bg-transparent px-2 text-[12px] outline-none focus-visible:ring-1 focus-visible:ring-ring';
156
+
157
+ /**
158
+ * Auth configuration: maps 1:1 to the runner's EnvAuth shape. Values here are
159
+ * config (names/refs), never credentials — the one sharp edge is login
160
+ * headers, which round-trip through GET /environments, so we warn against
161
+ * putting secrets there.
162
+ */
163
+ function AuthSection({ env }: { env: EnvironmentSummary }) {
164
+ const setEnvironmentAuth = useBuilderStore((s) => s.setEnvironmentAuth);
165
+ const loginEnvironment = useBuilderStore((s) => s.loginEnvironment);
166
+ const runAgent = useBuilderStore((s) => s.runAgent);
167
+ const configured = env.auth?.configured ?? false;
168
+ const [editing, setEditing] = useState(false);
169
+ const [aiOpen, setAiOpen] = useState(false);
170
+ const [aiInstruction, setAiInstruction] = useState('');
171
+ const [form, setForm] = useState(() => formFromConfig(env.auth?.config));
172
+ const [pending, setPending] = useState<'save' | 'clear' | 'login' | null>(null);
173
+ const [error, setError] = useState<string | null>(null);
174
+ const [loginResult, setLoginResult] = useState<string | null>(null);
175
+
176
+ const set = <K extends keyof typeof form>(k: K, v: (typeof form)[K]) =>
177
+ setForm((f) => ({ ...f, [k]: v }));
178
+
179
+ const buildAuth = (): EnvAuth | { error: string } => {
180
+ if (!form.attachName.trim()) return { error: 'Attach name is required' };
181
+ if (!form.secretRef.trim()) return { error: 'Secret ref is required' };
182
+ const auth: EnvAuth = {
183
+ attach: {
184
+ as: form.attachAs,
185
+ name: form.attachName.trim(),
186
+ secretRef: form.secretRef.trim(),
187
+ ...(form.prefix ? { prefix: form.prefix } : {}),
188
+ },
189
+ };
190
+ if (form.hasLogin) {
191
+ if (!form.loginUrl.trim()) return { error: 'Login URL is required' };
192
+ let headers: Record<string, string> | undefined;
193
+ if (form.loginHeaders.trim()) {
194
+ try {
195
+ headers = JSON.parse(form.loginHeaders) as Record<string, string>;
196
+ } catch {
197
+ return { error: 'Login headers must be valid JSON' };
198
+ }
199
+ }
200
+ const field = form.captureField.trim();
201
+ auth.login = {
202
+ request: {
203
+ method: form.loginMethod.trim() || 'POST',
204
+ url: form.loginUrl.trim(),
205
+ ...(headers ? { headers } : {}),
206
+ ...(form.bodyRef.trim() ? { bodyRef: form.bodyRef.trim() } : {}),
207
+ },
208
+ capture:
209
+ form.captureFrom === 'set-cookie'
210
+ ? { from: 'set-cookie', ...(field ? { cookieName: field } : {}) }
211
+ : form.captureFrom === 'json'
212
+ ? { from: 'json', path: field }
213
+ : { from: 'header', name: field },
214
+ };
215
+ }
216
+ return auth;
217
+ };
218
+
219
+ const onSave = async () => {
220
+ const auth = buildAuth();
221
+ if ('error' in auth) {
222
+ setError(auth.error);
223
+ return;
224
+ }
225
+ setError(null);
226
+ setPending('save');
227
+ try {
228
+ await setEnvironmentAuth(env.name, auth);
229
+ setEditing(false);
230
+ } catch (err) {
231
+ setError(err instanceof Error ? err.message : 'Failed to save auth config');
232
+ } finally {
233
+ setPending(null);
234
+ }
235
+ };
236
+
237
+ const onClearAuth = async () => {
238
+ setError(null);
239
+ setPending('clear');
240
+ try {
241
+ await setEnvironmentAuth(env.name, null);
242
+ setEditing(false);
243
+ setForm(formFromConfig(undefined));
244
+ } catch (err) {
245
+ setError(err instanceof Error ? err.message : 'Failed to clear auth config');
246
+ } finally {
247
+ setPending(null);
248
+ }
249
+ };
250
+
251
+ const onLogin = async () => {
252
+ setError(null);
253
+ setLoginResult(null);
254
+ setPending('login');
255
+ try {
256
+ await loginEnvironment(env.name);
257
+ setLoginResult('Logged in.');
258
+ } catch (err) {
259
+ setError(err instanceof Error ? err.message : 'Login failed');
260
+ } finally {
261
+ setPending(null);
262
+ }
263
+ };
264
+
265
+ const onSetupWithAi = () => {
266
+ const instruction = aiInstruction.trim();
267
+ if (!instruction) return;
268
+ void runAgent({ action: 'setup-auth', environment: env.name, instruction });
269
+ setAiOpen(false);
270
+ setAiInstruction('');
271
+ };
272
+
273
+ const summary = env.auth?.config
274
+ ? `${env.auth.config.attach.as} · ${env.auth.config.attach.name} ← «${env.auth.config.attach.secretRef}»${env.auth.config.login ? ` · login ${env.auth.config.login.request.method} ${env.auth.config.login.request.url}` : ''}`
275
+ : null;
276
+
277
+ return (
278
+ <div className="flex flex-col gap-2">
279
+ <SectionTitle>Auth</SectionTitle>
280
+
281
+ {!configured && !editing && !aiOpen && (
282
+ <div className="flex flex-col gap-2">
283
+ <div className="text-[11.5px] text-muted-foreground">
284
+ No auth configured — runs against this environment carry no credential.
285
+ </div>
286
+ <div className="flex gap-2">
287
+ <Button variant="secondary" size="sm" className="h-7" onClick={() => setAiOpen(true)}>
288
+ <SparklesIcon className="size-3" />
289
+ Set up with AI
290
+ </Button>
291
+ <Button variant="ghost" size="sm" className="h-7" onClick={() => setEditing(true)}>
292
+ Configure manually
293
+ </Button>
294
+ </div>
295
+ </div>
296
+ )}
297
+
298
+ {aiOpen && (
299
+ <div className="flex flex-col gap-2">
300
+ <textarea
301
+ value={aiInstruction}
302
+ onChange={(e) => setAiInstruction(e.target.value)}
303
+ placeholder={
304
+ 'Describe how this API logs in — paste a curl, name the endpoint, say where the token/cookie comes back…'
305
+ }
306
+ rows={4}
307
+ className="w-full resize-none rounded-md border border-input bg-transparent px-2.5 py-2 text-[12px] outline-none placeholder:text-muted-foreground/60 focus-visible:ring-1 focus-visible:ring-ring"
308
+ />
309
+ <div className="text-[11px] text-muted-foreground">
310
+ The agent writes the config and verifies the login. It never sees credential values —
311
+ you'll enter those here as secrets.
312
+ </div>
313
+ <div className="flex justify-end gap-2">
314
+ <Button variant="ghost" size="sm" className="h-7" onClick={() => setAiOpen(false)}>
315
+ Cancel
316
+ </Button>
317
+ <Button
318
+ variant="secondary"
319
+ size="sm"
320
+ className="h-7"
321
+ disabled={!aiInstruction.trim()}
322
+ onClick={onSetupWithAi}
323
+ >
324
+ <SparklesIcon className="size-3" />
325
+ Start
326
+ </Button>
327
+ </div>
328
+ </div>
329
+ )}
330
+
331
+ {configured && !editing && (
332
+ <div className="flex flex-col gap-2">
333
+ <div className="flex items-center gap-2 text-[12px]">
334
+ <span
335
+ className={cn(
336
+ 'size-1.5 shrink-0 rounded-full',
337
+ env.auth?.authenticated ? 'bg-success' : 'border border-muted-foreground',
338
+ )}
339
+ />
340
+ <span className="min-w-0 truncate font-mono text-[11.5px]">{summary}</span>
341
+ </div>
342
+ <div className="flex gap-2">
343
+ <Button
344
+ variant="secondary"
345
+ size="sm"
346
+ className="h-7"
347
+ disabled={pending !== null}
348
+ onClick={() => void onLogin()}
349
+ >
350
+ {pending === 'login' && <Loader2Icon className="size-3 animate-spin" />}
351
+ {env.auth?.authenticated ? 'Re-log in' : 'Log in'}
352
+ </Button>
353
+ <Button
354
+ variant="ghost"
355
+ size="sm"
356
+ className="h-7"
357
+ onClick={() => {
358
+ setForm(formFromConfig(env.auth?.config));
359
+ setEditing(true);
360
+ }}
361
+ >
362
+ Edit
363
+ </Button>
364
+ <Button
365
+ variant="ghost"
366
+ size="sm"
367
+ className="h-7 text-destructive hover:text-destructive"
368
+ disabled={pending !== null}
369
+ onClick={() => void onClearAuth()}
370
+ >
371
+ {pending === 'clear' && <Loader2Icon className="size-3 animate-spin" />}
372
+ Remove
373
+ </Button>
374
+ </div>
375
+ {loginResult && <div className="text-[11.5px] text-success">{loginResult}</div>}
376
+ </div>
377
+ )}
378
+
379
+ {editing && (
380
+ <div className="flex flex-col gap-2">
381
+ <div className={fieldRow}>
382
+ <span className={fieldLabel}>Attach as</span>
383
+ <select
384
+ value={form.attachAs}
385
+ onChange={(e) => set('attachAs', e.target.value as 'cookie' | 'header')}
386
+ className={selectCls}
387
+ >
388
+ <option value="cookie">cookie</option>
389
+ <option value="header">header</option>
390
+ </select>
391
+ <Input
392
+ value={form.attachName}
393
+ onChange={(e) => set('attachName', e.target.value)}
394
+ placeholder={form.attachAs === 'cookie' ? 'cookie name' : 'header name'}
395
+ spellCheck={false}
396
+ className="h-7 flex-1 font-mono text-[12px]"
397
+ />
398
+ </div>
399
+ <div className={fieldRow}>
400
+ <span className={fieldLabel}>Secret ref</span>
401
+ <Input
402
+ value={form.secretRef}
403
+ onChange={(e) => set('secretRef', e.target.value)}
404
+ placeholder="secret key holding the credential"
405
+ spellCheck={false}
406
+ className="h-7 flex-1 font-mono text-[12px]"
407
+ />
408
+ </div>
409
+ <div className={fieldRow}>
410
+ <span className={fieldLabel}>Prefix</span>
411
+ <Input
412
+ value={form.prefix}
413
+ onChange={(e) => set('prefix', e.target.value)}
414
+ placeholder='optional, e.g. "Bearer "'
415
+ className="h-7 flex-1 font-mono text-[12px]"
416
+ />
417
+ </div>
418
+
419
+ <label className="flex cursor-pointer items-center gap-2 text-[12px]">
420
+ <input
421
+ type="checkbox"
422
+ checked={form.hasLogin}
423
+ onChange={(e) => set('hasLogin', e.target.checked)}
424
+ />
425
+ Login request mints the credential
426
+ </label>
427
+
428
+ {form.hasLogin && (
429
+ <>
430
+ <div className={fieldRow}>
431
+ <span className={fieldLabel}>Login</span>
432
+ <Input
433
+ value={form.loginMethod}
434
+ onChange={(e) => set('loginMethod', e.target.value)}
435
+ className="h-7 w-20 font-mono text-[12px]"
436
+ spellCheck={false}
437
+ />
438
+ <Input
439
+ value={form.loginUrl}
440
+ onChange={(e) => set('loginUrl', e.target.value)}
441
+ placeholder="https://…/login"
442
+ spellCheck={false}
443
+ className="h-7 flex-1 font-mono text-[12px]"
444
+ />
445
+ </div>
446
+ <div className={fieldRow}>
447
+ <span className={fieldLabel}>Body secret</span>
448
+ <Input
449
+ value={form.bodyRef}
450
+ onChange={(e) => set('bodyRef', e.target.value)}
451
+ placeholder="secret key holding the login body JSON"
452
+ spellCheck={false}
453
+ className="h-7 flex-1 font-mono text-[12px]"
454
+ />
455
+ </div>
456
+ <div className="flex items-start gap-2">
457
+ <span className={cn(fieldLabel, 'pt-1.5')}>Headers</span>
458
+ <div className="flex min-w-0 flex-1 flex-col gap-1">
459
+ <textarea
460
+ value={form.loginHeaders}
461
+ onChange={(e) => set('loginHeaders', e.target.value)}
462
+ placeholder='{"origin": "http://localhost:5173"}'
463
+ rows={2}
464
+ spellCheck={false}
465
+ className="w-full resize-none rounded-md border border-input bg-transparent px-2.5 py-1.5 font-mono text-[11.5px] outline-none placeholder:text-muted-foreground/50 focus-visible:ring-1 focus-visible:ring-ring"
466
+ />
467
+ <div className="text-[10.5px] text-muted-foreground">
468
+ Config only — never put credentials here; use the body secret instead.
469
+ </div>
470
+ </div>
471
+ </div>
472
+ <div className={fieldRow}>
473
+ <span className={fieldLabel}>Capture</span>
474
+ <select
475
+ value={form.captureFrom}
476
+ onChange={(e) =>
477
+ set('captureFrom', e.target.value as 'set-cookie' | 'json' | 'header')
478
+ }
479
+ className={selectCls}
480
+ >
481
+ <option value="set-cookie">set-cookie</option>
482
+ <option value="json">json path</option>
483
+ <option value="header">header</option>
484
+ </select>
485
+ <Input
486
+ value={form.captureField}
487
+ onChange={(e) => set('captureField', e.target.value)}
488
+ placeholder={
489
+ form.captureFrom === 'set-cookie'
490
+ ? 'cookie name (optional)'
491
+ : form.captureFrom === 'json'
492
+ ? 'dot.path.to.token'
493
+ : 'header name'
494
+ }
495
+ spellCheck={false}
496
+ className="h-7 flex-1 font-mono text-[12px]"
497
+ />
498
+ </div>
499
+ </>
500
+ )}
501
+
502
+ <div className="flex justify-end gap-2">
503
+ <Button variant="ghost" size="sm" className="h-7" onClick={() => setEditing(false)}>
504
+ Cancel
505
+ </Button>
506
+ <Button
507
+ variant="secondary"
508
+ size="sm"
509
+ className="h-7"
510
+ disabled={pending !== null}
511
+ onClick={() => void onSave()}
512
+ >
513
+ {pending === 'save' && <Loader2Icon className="size-3 animate-spin" />}
514
+ Save
515
+ </Button>
516
+ </div>
517
+ </div>
518
+ )}
519
+
520
+ <ErrorLine message={error} />
521
+ </div>
522
+ );
523
+ }
524
+
525
+ /**
526
+ * Manage Environment dialog: secrets (write-only), auth config, and login —
527
+ * everything that previously required hand-editing emberflow.environments.json.
528
+ */
529
+ export function EnvironmentDialog({
530
+ env,
531
+ open,
532
+ onOpenChange,
533
+ }: {
534
+ env: EnvironmentSummary | null;
535
+ open: boolean;
536
+ onOpenChange: (open: boolean) => void;
537
+ }) {
538
+ if (!env) return null;
539
+ return (
540
+ <Dialog open={open} onOpenChange={onOpenChange}>
541
+ <DialogContent className="max-w-lg">
542
+ <DialogTitle className="flex items-center gap-2">
543
+ {env.name}
544
+ {env.protected && (
545
+ <span className="flex items-center gap-1 text-[10.5px] font-normal uppercase tracking-wide text-destructive-foreground/80">
546
+ <ShieldIcon className="size-3" /> protected
547
+ </span>
548
+ )}
549
+ {env.auth?.configured && (
550
+ <span
551
+ className={cn(
552
+ 'ml-auto size-1.5 rounded-full',
553
+ env.auth.authenticated ? 'bg-success' : 'border border-muted-foreground',
554
+ )}
555
+ title={env.auth.authenticated ? 'Authenticated' : 'Not authenticated'}
556
+ />
557
+ )}
558
+ </DialogTitle>
559
+ <DialogDescription className="sr-only">
560
+ Manage secrets and auth for the {env.name} environment.
561
+ </DialogDescription>
562
+ <div className="flex flex-col gap-5">
563
+ <SecretsSection env={env} />
564
+ <AuthSection env={env} />
565
+ </div>
566
+ </DialogContent>
567
+ </Dialog>
568
+ );
569
+ }