@xdelivered/emberflow 0.2.0 → 0.5.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.
- package/bin/commands.ts +7 -3
- package/bin/init.test.ts +94 -0
- package/bin/init.ts +108 -2
- package/dist/bin/commands.d.ts +1 -0
- package/dist/bin/commands.js +6 -3
- package/dist/bin/init.d.ts +4 -0
- package/dist/bin/init.js +96 -2
- package/dist/server/agents/codexParse.js +31 -0
- package/dist/server/agents/detect.d.ts +18 -8
- package/dist/server/agents/detect.js +78 -13
- package/dist/server/agents/modelRejectionHint.js +1 -1
- package/dist/server/agents/prompt.d.ts +15 -1
- package/dist/server/agents/prompt.js +59 -37
- package/dist/server/agents/runManager.d.ts +23 -2
- package/dist/server/agents/runManager.js +36 -8
- package/dist/server/client.d.ts +1 -0
- package/dist/server/client.js +7 -2
- package/dist/server/index.js +208 -16
- package/dist/server/nodesPayload.d.ts +14 -1
- package/dist/server/nodesPayload.js +15 -2
- package/dist/server/projectMode.js +5 -2
- package/dist/server/runRegistry.d.ts +52 -1
- package/dist/server/runRegistry.js +170 -1
- package/dist/server/sourceNav.d.ts +77 -0
- package/dist/server/sourceNav.js +503 -0
- package/dist/server/subflowRunner.d.ts +48 -1
- package/dist/server/subflowRunner.js +34 -7
- package/dist/server/updateCheck.d.ts +68 -0
- package/dist/server/updateCheck.js +142 -0
- package/dist/src/engine/executor.js +4 -3
- package/dist/src/engine/registry.d.ts +27 -2
- package/dist/src/engine/registry.js +84 -2
- package/dist/src/nodes/index.d.ts +8 -2
- package/dist/src/nodes/index.js +7 -3
- package/dist/src/nodes/login.d.ts +3 -1
- package/dist/src/nodes/login.js +2 -2
- package/package.json +28 -7
- package/server/agentRoute.test.ts +20 -0
- package/server/agents/codexParse.test.ts +37 -0
- package/server/agents/codexParse.ts +34 -0
- package/server/agents/detect.test.ts +26 -7
- package/server/agents/detect.ts +82 -14
- package/server/agents/modelRejectionHint.ts +2 -1
- package/server/agents/prompt.test.ts +128 -0
- package/server/agents/prompt.ts +102 -3
- package/server/agents/runManager.test.ts +9 -0
- package/server/agents/runManager.ts +37 -7
- package/server/client.ts +10 -4
- package/server/index.ts +213 -15
- package/server/nodeRun.test.ts +189 -0
- package/server/nodesPayload.test.ts +38 -0
- package/server/nodesPayload.ts +28 -3
- package/server/projectMode.ts +5 -2
- package/server/runRegistry.ts +200 -3
- package/server/setupStatus.test.ts +3 -0
- package/server/sourceNav.test.ts +382 -0
- package/server/sourceNav.ts +644 -0
- package/server/sourceNavRoute.test.ts +163 -0
- package/server/stepDrill.test.ts +380 -0
- package/server/subflowRunner.ts +92 -11
- package/server/updateCheck.test.ts +209 -0
- package/server/updateCheck.ts +175 -0
- package/server/workflowTestRoute.test.ts +1 -1
- package/src/App.tsx +82 -2
- package/src/components/AgentConsole.tsx +7 -280
- package/src/components/AgentStream.test.tsx +88 -0
- package/src/components/AgentStream.tsx +303 -0
- package/src/components/CreateModal.tsx +43 -9
- package/src/components/Dock.tsx +1 -1
- package/src/components/EmptyState.test.tsx +49 -0
- package/src/components/EmptyState.tsx +61 -0
- package/src/components/EnvironmentDialog.tsx +4 -1
- package/src/components/EnvironmentPicker.tsx +8 -3
- package/src/components/EnvironmentsDialog.tsx +4 -1
- package/src/components/InfraPanel.tsx +30 -2
- package/src/components/InfrastructureDialog.test.tsx +97 -0
- package/src/components/InfrastructureDialog.tsx +111 -0
- package/src/components/Inspector.tsx +9 -26
- package/src/components/RunbookView.tsx +70 -6
- package/src/components/SettingsDialog.tsx +4 -59
- package/src/components/Sidebar.tsx +6 -26
- package/src/components/SourceNavigator.test.tsx +226 -0
- package/src/components/SourceNavigator.tsx +520 -0
- package/src/components/StatusBar.tsx +227 -26
- package/src/components/Toolbar.tsx +28 -16
- package/src/components/UpdateChip.test.tsx +31 -0
- package/src/components/WelcomeDialog.test.tsx +384 -13
- package/src/components/WelcomeDialog.tsx +996 -177
- package/src/engine/executor.ts +4 -3
- package/src/engine/registry.sourceRef.test.ts +112 -0
- package/src/engine/registry.ts +103 -2
- package/src/lib/guidedQuestions.test.ts +224 -0
- package/src/lib/guidedQuestions.ts +181 -0
- package/src/lib/runbookModel.ts +3 -3
- package/src/lib/runbookProjection.test.ts +43 -0
- package/src/lib/runbookProjection.ts +26 -6
- package/src/nodes/index.ts +10 -3
- package/src/nodes/login.ts +5 -2
- package/src/store/agentClient.ts +27 -8
- package/src/store/apiTree.ts +12 -0
- package/src/store/builderStore.test.ts +441 -99
- package/src/store/builderStore.ts +385 -314
- package/src/store/nodeMeta.ts +10 -2
- package/src/store/serverRunner.ts +56 -5
- package/src/store/setupClient.ts +7 -2
- package/src/store/sourceNavClient.ts +48 -0
- package/src/store/updateClient.ts +50 -0
- package/studio-dist/assets/index-BbzppDpt.js +65 -0
- package/studio-dist/assets/index-CLf6blcA.css +1 -0
- package/studio-dist/index.html +2 -2
- package/templates/skills/emberflow-basics/SKILL.md +29 -1
- package/templates/skills/emberflow-model-process/SKILL.md +92 -9
- package/templates/skills/emberflow-new-workflow/SKILL.md +8 -1
- package/templates/skills/emberflow-review-workflow/SKILL.md +64 -1
- package/studio-dist/assets/index-DNJwW-hM.css +0 -1
- package/studio-dist/assets/index-O26dKRjW.js +0 -65
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2)format("woff2-variations");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2)format("woff2-variations");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2)format("woff2-variations");unicode-range:U+1F??}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-greek-wght-normal-CkhJZR-_.woff2)format("woff2-variations");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2)format("woff2-variations");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2)format("woff2-variations");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-latin-wght-normal-Dx4kXJAl.woff2)format("woff2-variations");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2)format("woff2"),url(/assets/ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff)format("woff");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2)format("woff2"),url(/assets/ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff)format("woff");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2)format("woff2"),url(/assets/ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2)format("woff2"),url(/assets/ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:400;src:url(/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2)format("woff2"),url(/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/ibm-plex-mono-cyrillic-ext-500-normal-BqneJy0T.woff2)format("woff2"),url(/assets/ibm-plex-mono-cyrillic-ext-500-normal-BIfNGwUT.woff)format("woff");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/ibm-plex-mono-cyrillic-500-normal-Bq9vWWag.woff2)format("woff2"),url(/assets/ibm-plex-mono-cyrillic-500-normal-Ael50iVv.woff)format("woff");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/ibm-plex-mono-vietnamese-500-normal-DZ4AoWbu.woff2)format("woff2"),url(/assets/ibm-plex-mono-vietnamese-500-normal-C8zxqsMH.woff)format("woff");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/ibm-plex-mono-latin-ext-500-normal-CAhNIIs5.woff2)format("woff2"),url(/assets/ibm-plex-mono-latin-ext-500-normal-CZ70TYgx.woff)format("woff");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:IBM Plex Mono;font-style:normal;font-display:swap;font-weight:500;src:url(/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2)format("woff2"),url(/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff)format("woff");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial;--tw-content:"";--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--font-mono:"IBM Plex Mono", "SF Mono", ui-monospace, Menlo, monospace;--color-amber-500:oklch(76.9% .188 70.08);--color-yellow-500:oklch(79.5% .184 86.047);--color-emerald-500:oklch(69.6% .17 162.48);--color-teal-500:oklch(70.4% .14 182.503);--color-cyan-500:oklch(71.5% .143 215.221);--color-sky-500:oklch(68.5% .169 237.323);--color-violet-500:oklch(60.6% .25 292.717);--color-fuchsia-500:oklch(66.7% .295 322.15);--color-pink-500:oklch(65.6% .241 354.308);--color-rose-500:oklch(64.5% .246 16.439);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-4xl:56rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-normal:0em;--tracking-wide:.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-tight:1.25;--leading-snug:1.375;--leading-relaxed:1.625;--radius-xs:.125rem;--ease-out:cubic-bezier(0, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:"Inter Variable", "Inter", ui-sans-serif, system-ui, sans-serif;--default-mono-font-family:"IBM Plex Mono", "SF Mono", ui-monospace, Menlo, monospace}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--border);outline-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){*{outline-color:color-mix(in oklab, var(--ring) 50%, transparent)}}body{background-color:var(--background);color:var(--foreground);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:Inter Variable,Inter,ui-sans-serif,system-ui,sans-serif;font-size:13px}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-thumb{background:#3f3f4680;border-radius:6px}::-webkit-scrollbar-track{background:0 0}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{inset-inline:0}.top-0{top:0}.top-1{top:var(--spacing)}.top-1\.5{top:calc(var(--spacing) * 1.5)}.top-1\/2{top:50%}.top-4{top:calc(var(--spacing) * 4)}.top-6{top:calc(var(--spacing) * 6)}.top-full{top:100%}.right-1{right:var(--spacing)}.right-1\.5{right:calc(var(--spacing) * 1.5)}.right-4{right:calc(var(--spacing) * 4)}.bottom-0{bottom:0}.left-0{left:0}.left-1\/2{left:50%}.z-10{z-index:10}.z-50{z-index:50}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.-mx-2\.5{margin-inline:calc(var(--spacing) * -2.5)}.mx-0\.5{margin-inline:calc(var(--spacing) * .5)}.mx-auto{margin-inline:auto}.my-0\.5{margin-block:calc(var(--spacing) * .5)}.my-1{margin-block:var(--spacing)}.-mt-1{margin-top:calc(var(--spacing) * -1)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-3\.5{margin-top:calc(var(--spacing) * 3.5)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-10{margin-top:calc(var(--spacing) * 10)}.mt-\[5px\]{margin-top:5px}.mt-\[7px\]{margin-top:7px}.mr-1{margin-right:var(--spacing)}.mr-1\.5{margin-right:calc(var(--spacing) * 1.5)}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:var(--spacing)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-2\.5{margin-bottom:calc(var(--spacing) * 2.5)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.-ml-1\.5{margin-left:calc(var(--spacing) * -1.5)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-1{margin-left:var(--spacing)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.ml-3{margin-left:calc(var(--spacing) * 3)}.ml-4{margin-left:calc(var(--spacing) * 4)}.ml-11{margin-left:calc(var(--spacing) * 11)}.ml-\[18px\]{margin-left:18px}.ml-\[54px\]{margin-left:54px}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.size-1{width:var(--spacing);height:var(--spacing)}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-3{width:calc(var(--spacing) * 3);height:calc(var(--spacing) * 3)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-11{width:calc(var(--spacing) * 11);height:calc(var(--spacing) * 11)}.size-\[5px\]{width:5px;height:5px}.size-\[9px\]{width:9px;height:9px}.h-0\.5{height:calc(var(--spacing) * .5)}.h-3{height:calc(var(--spacing) * 3)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-11{height:calc(var(--spacing) * 11)}.h-12{height:calc(var(--spacing) * 12)}.h-\[2px\]{height:2px}.h-\[24px\]{height:24px}.h-\[85vh\]{height:85vh}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-32{max-height:calc(var(--spacing) * 32)}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-72{max-height:calc(var(--spacing) * 72)}.max-h-96{max-height:calc(var(--spacing) * 96)}.max-h-\[55vh\]{max-height:55vh}.max-h-\[65vh\]{max-height:65vh}.max-h-\[85vh\]{max-height:85vh}.min-h-0{min-height:0}.w-\(--radix-popover-trigger-width\){width:var(--radix-popover-trigger-width)}.w-3{width:calc(var(--spacing) * 3)}.w-6{width:calc(var(--spacing) * 6)}.w-9{width:calc(var(--spacing) * 9)}.w-10{width:calc(var(--spacing) * 10)}.w-11{width:calc(var(--spacing) * 11)}.w-14{width:calc(var(--spacing) * 14)}.w-20{width:calc(var(--spacing) * 20)}.w-24{width:calc(var(--spacing) * 24)}.w-28{width:calc(var(--spacing) * 28)}.w-36{width:calc(var(--spacing) * 36)}.w-40{width:calc(var(--spacing) * 40)}.w-44{width:calc(var(--spacing) * 44)}.w-64{width:calc(var(--spacing) * 64)}.w-72{width:calc(var(--spacing) * 72)}.w-96{width:calc(var(--spacing) * 96)}.w-\[26rem\]{width:26rem}.w-\[380px\]{width:380px}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-28{max-width:calc(var(--spacing) * 28)}.max-w-36{max-width:calc(var(--spacing) * 36)}.max-w-40{max-width:calc(var(--spacing) * 40)}.max-w-44{max-width:calc(var(--spacing) * 44)}.max-w-72{max-width:calc(var(--spacing) * 72)}.max-w-\[65ch\]{max-width:65ch}.max-w-\[80vw\]{max-width:80vw}.max-w-\[90\%\]{max-width:90%}.max-w-\[800px\]{max-width:800px}.max-w-\[calc\(100vw-2rem\)\]{max-width:calc(100vw - 2rem)}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:0}.min-w-32{min-width:calc(var(--spacing) * 32)}.min-w-44{min-width:calc(var(--spacing) * 44)}.min-w-56{min-width:calc(var(--spacing) * 56)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-0{--tw-translate-x:0;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-full{--tw-translate-x:100%;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-90{rotate:90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-help{cursor:help}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.resize-y{resize:vertical}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-\[repeat\(auto-fill\,minmax\(240px\,1fr\)\)\]{grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}.grid-cols-\[repeat\(auto-fit\,minmax\(280px\,1fr\)\)\]{grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0{gap:0}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-3\.5{gap:calc(var(--spacing) * 3.5)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-2{column-gap:calc(var(--spacing) * 2)}.gap-y-1{row-gap:var(--spacing)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-border>:not(:last-child)),:where(.divide-border\/50>:not(:last-child)){border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){:where(.divide-border\/50>:not(:last-child)){border-color:color-mix(in oklab, var(--border) 50%, transparent)}}.self-center{align-self:center}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-\[3px\]{border-radius:3px}.rounded-\[4px\]{border-radius:4px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.rounded-xs{border-radius:var(--radius-xs)}.rounded-l-none{border-top-left-radius:0;border-bottom-left-radius:0}.rounded-r-none{border-top-right-radius:0;border-bottom-right-radius:0}.rounded-br-sm{border-bottom-right-radius:calc(var(--radius) - 4px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-\[1\.5px\]{border-left-style:var(--tw-border-style);border-left-width:1.5px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-\[\#8fb8d8\]\/40{border-color:oklab(76.4209% -.0297927 -.056321/.4)}.border-black\/20{border-color:#0003}@supports (color:color-mix(in lab, red, red)){.border-black\/20{border-color:color-mix(in oklab, var(--color-black) 20%, transparent)}}.border-border,.border-border\/35{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.border-border\/35{border-color:color-mix(in oklab, var(--border) 35%, transparent)}}.border-border\/50{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.border-border\/50{border-color:color-mix(in oklab, var(--border) 50%, transparent)}}.border-border\/60{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.border-border\/60{border-color:color-mix(in oklab, var(--border) 60%, transparent)}}.border-border\/70{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.border-border\/70{border-color:color-mix(in oklab, var(--border) 70%, transparent)}}.border-destructive,.border-destructive\/40{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.border-destructive\/40{border-color:color-mix(in oklab, var(--destructive) 40%, transparent)}}.border-destructive\/50{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.border-destructive\/50{border-color:color-mix(in oklab, var(--destructive) 50%, transparent)}}.border-highlight,.border-highlight\/30{border-color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.border-highlight\/30{border-color:color-mix(in oklab, var(--highlight) 30%, transparent)}}.border-highlight\/40{border-color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.border-highlight\/40{border-color:color-mix(in oklab, var(--highlight) 40%, transparent)}}.border-highlight\/60{border-color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.border-highlight\/60{border-color:color-mix(in oklab, var(--highlight) 60%, transparent)}}.border-input{border-color:var(--input)}.border-muted-foreground{border-color:var(--muted-foreground)}.border-ring{border-color:var(--ring)}.border-sidebar-border{border-color:var(--sidebar-border)}.border-success,.border-success\/40{border-color:var(--success)}@supports (color:color-mix(in lab, red, red)){.border-success\/40{border-color:color-mix(in oklab, var(--success) 40%, transparent)}}.border-transparent{border-color:#0000}.border-warn\/40{border-color:var(--warn)}@supports (color:color-mix(in lab, red, red)){.border-warn\/40{border-color:color-mix(in oklab, var(--warn) 40%, transparent)}}.bg-\[\#8fb8d8\]{background-color:#8fb8d8}.bg-background,.bg-background\/40{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){.bg-background\/40{background-color:color-mix(in oklab, var(--background) 40%, transparent)}}.bg-background\/50{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){.bg-background\/50{background-color:color-mix(in oklab, var(--background) 50%, transparent)}}.bg-background\/60{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){.bg-background\/60{background-color:color-mix(in oklab, var(--background) 60%, transparent)}}.bg-black\/15{background-color:#00000026}@supports (color:color-mix(in lab, red, red)){.bg-black\/15{background-color:color-mix(in oklab, var(--color-black) 15%, transparent)}}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab, red, red)){.bg-black\/60{background-color:color-mix(in oklab, var(--color-black) 60%, transparent)}}.bg-border,.bg-border\/70{background-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.bg-border\/70{background-color:color-mix(in oklab, var(--border) 70%, transparent)}}.bg-card,.bg-card\/50{background-color:var(--card)}@supports (color:color-mix(in lab, red, red)){.bg-card\/50{background-color:color-mix(in oklab, var(--card) 50%, transparent)}}.bg-card\/60{background-color:var(--card)}@supports (color:color-mix(in lab, red, red)){.bg-card\/60{background-color:color-mix(in oklab, var(--card) 60%, transparent)}}.bg-current{background-color:currentColor}.bg-destructive,.bg-destructive\/15{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.bg-destructive\/15{background-color:color-mix(in oklab, var(--destructive) 15%, transparent)}}.bg-destructive\/80{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.bg-destructive\/80{background-color:color-mix(in oklab, var(--destructive) 80%, transparent)}}.bg-highlight,.bg-highlight\/12{background-color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.bg-highlight\/12{background-color:color-mix(in oklab, var(--highlight) 12%, transparent)}}.bg-highlight\/15{background-color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.bg-highlight\/15{background-color:color-mix(in oklab, var(--highlight) 15%, transparent)}}.bg-highlight\/80{background-color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.bg-highlight\/80{background-color:color-mix(in oklab, var(--highlight) 80%, transparent)}}.bg-highlight\/\[0\.03\]{background-color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.bg-highlight\/\[0\.03\]{background-color:color-mix(in oklab, var(--highlight) 3%, transparent)}}.bg-highlight\/\[0\.06\]{background-color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.bg-highlight\/\[0\.06\]{background-color:color-mix(in oklab, var(--highlight) 6%, transparent)}}.bg-input\/30{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.bg-input\/30{background-color:color-mix(in oklab, var(--input) 30%, transparent)}}.bg-muted-foreground,.bg-muted-foreground\/40{background-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.bg-muted-foreground\/40{background-color:color-mix(in oklab, var(--muted-foreground) 40%, transparent)}}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-secondary,.bg-secondary\/40{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.bg-secondary\/40{background-color:color-mix(in oklab, var(--secondary) 40%, transparent)}}.bg-secondary\/60{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.bg-secondary\/60{background-color:color-mix(in oklab, var(--secondary) 60%, transparent)}}.bg-sidebar{background-color:var(--sidebar)}.bg-sidebar-accent{background-color:var(--sidebar-accent)}.bg-success,.bg-success\/15{background-color:var(--success)}@supports (color:color-mix(in lab, red, red)){.bg-success\/15{background-color:color-mix(in oklab, var(--success) 15%, transparent)}}.bg-success\/70{background-color:var(--success)}@supports (color:color-mix(in lab, red, red)){.bg-success\/70{background-color:color-mix(in oklab, var(--success) 70%, transparent)}}.bg-tertiary{background-color:var(--tertiary)}.bg-transparent{background-color:#0000}.bg-warn,.bg-warn\/15{background-color:var(--warn)}@supports (color:color-mix(in lab, red, red)){.bg-warn\/15{background-color:color-mix(in oklab, var(--warn) 15%, transparent)}}.bg-warn\/85{background-color:var(--warn)}@supports (color:color-mix(in lab, red, red)){.bg-warn\/85{background-color:color-mix(in oklab, var(--warn) 85%, transparent)}}.fill-current{fill:currentColor}.p-0{padding:0}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:var(--spacing)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-3\.5{padding:calc(var(--spacing) * 3.5)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-8{padding:calc(var(--spacing) * 8)}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-14{padding-block:calc(var(--spacing) * 14)}.py-px{padding-block:1px}.pt-0\.5{padding-top:calc(var(--spacing) * .5)}.pt-1{padding-top:var(--spacing)}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-2\.5{padding-top:calc(var(--spacing) * 2.5)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-\[26px\]{padding-top:26px}.pr-0\.5{padding-right:calc(var(--spacing) * .5)}.pr-1\.5{padding-right:calc(var(--spacing) * 1.5)}.pr-2{padding-right:calc(var(--spacing) * 2)}.pr-2\.5{padding-right:calc(var(--spacing) * 2.5)}.pr-8{padding-right:calc(var(--spacing) * 8)}.pb-1{padding-bottom:var(--spacing)}.pb-1\.5{padding-bottom:calc(var(--spacing) * 1.5)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-\[140px\]{padding-bottom:140px}.pl-0\.5{padding-left:calc(var(--spacing) * .5)}.pl-1{padding-left:var(--spacing)}.pl-1\.5{padding-left:calc(var(--spacing) * 1.5)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-3{padding-left:calc(var(--spacing) * 3)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:IBM Plex Mono,SF Mono,ui-monospace,Menlo,monospace}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[7px\]{font-size:7px}.text-\[8\.5px\]{font-size:8.5px}.text-\[9\.5px\]{font-size:9.5px}.text-\[9px\]{font-size:9px}.text-\[10\.5px\]{font-size:10.5px}.text-\[10px\]{font-size:10px}.text-\[11\.5px\]{font-size:11.5px}.text-\[11px\]{font-size:11px}.text-\[12\.5px\]{font-size:12.5px}.text-\[12px\]{font-size:12px}.text-\[13\.5px\]{font-size:13.5px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.text-\[22px\]{font-size:22px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-normal{--tw-tracking:var(--tracking-normal);letter-spacing:var(--tracking-normal)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-words{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[\#8fb8d8\]{color:#8fb8d8}.text-amber-500{color:var(--color-amber-500)}.text-background{color:var(--background)}.text-black{color:var(--color-black)}.text-border{color:var(--border)}.text-cyan-500{color:var(--color-cyan-500)}.text-destructive{color:var(--destructive)}.text-destructive-foreground,.text-destructive-foreground\/80{color:var(--destructive-foreground)}@supports (color:color-mix(in lab, red, red)){.text-destructive-foreground\/80{color:color-mix(in oklab, var(--destructive-foreground) 80%, transparent)}}.text-destructive\/90{color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.text-destructive\/90{color:color-mix(in oklab, var(--destructive) 90%, transparent)}}.text-emerald-500{color:var(--color-emerald-500)}.text-foreground,.text-foreground\/70{color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.text-foreground\/70{color:color-mix(in oklab, var(--foreground) 70%, transparent)}}.text-foreground\/75{color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.text-foreground\/75{color:color-mix(in oklab, var(--foreground) 75%, transparent)}}.text-foreground\/80{color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.text-foreground\/80{color:color-mix(in oklab, var(--foreground) 80%, transparent)}}.text-foreground\/85{color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.text-foreground\/85{color:color-mix(in oklab, var(--foreground) 85%, transparent)}}.text-foreground\/90{color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.text-foreground\/90{color:color-mix(in oklab, var(--foreground) 90%, transparent)}}.text-fuchsia-500{color:var(--color-fuchsia-500)}.text-highlight{color:var(--highlight)}.text-highlight-foreground{color:var(--highlight-foreground)}.text-highlight\/60{color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.text-highlight\/60{color:color-mix(in oklab, var(--highlight) 60%, transparent)}}.text-highlight\/80{color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.text-highlight\/80{color:color-mix(in oklab, var(--highlight) 80%, transparent)}}.text-highlight\/90{color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.text-highlight\/90{color:color-mix(in oklab, var(--highlight) 90%, transparent)}}.text-muted-foreground,.text-muted-foreground\/30{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/30{color:color-mix(in oklab, var(--muted-foreground) 30%, transparent)}}.text-muted-foreground\/45{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/45{color:color-mix(in oklab, var(--muted-foreground) 45%, transparent)}}.text-muted-foreground\/50{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/50{color:color-mix(in oklab, var(--muted-foreground) 50%, transparent)}}.text-muted-foreground\/60{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/60{color:color-mix(in oklab, var(--muted-foreground) 60%, transparent)}}.text-muted-foreground\/70{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/70{color:color-mix(in oklab, var(--muted-foreground) 70%, transparent)}}.text-muted-foreground\/75{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/75{color:color-mix(in oklab, var(--muted-foreground) 75%, transparent)}}.text-muted-foreground\/80{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/80{color:color-mix(in oklab, var(--muted-foreground) 80%, transparent)}}.text-pink-500{color:var(--color-pink-500)}.text-popover-foreground{color:var(--popover-foreground)}.text-primary-foreground{color:var(--primary-foreground)}.text-rose-500{color:var(--color-rose-500)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-sidebar-accent-foreground{color:var(--sidebar-accent-foreground)}.text-sky-500{color:var(--color-sky-500)}.text-success,.text-success\/70{color:var(--success)}@supports (color:color-mix(in lab, red, red)){.text-success\/70{color:color-mix(in oklab, var(--success) 70%, transparent)}}.text-success\/80{color:var(--success)}@supports (color:color-mix(in lab, red, red)){.text-success\/80{color:color-mix(in oklab, var(--success) 80%, transparent)}}.text-teal-500{color:var(--color-teal-500)}.text-violet-500{color:var(--color-violet-500)}.text-warn{color:var(--warn)}.text-white{color:var(--color-white)}.text-yellow-500{color:var(--color-yellow-500)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.normal-case{text-transform:none}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.decoration-dotted{text-decoration-style:dotted}.underline-offset-2{text-underline-offset:2px}.underline-offset-4{text-underline-offset:4px}.accent-\(--highlight\){accent-color:var(--highlight)}.opacity-0{opacity:0}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-55{opacity:.55}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_18px_48px_rgb\(0_0_0\/0\.55\)\]{--tw-shadow:0 18px 48px var(--tw-shadow-color,#0000008c);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-highlight{--tw-ring-color:var(--highlight)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\,opacity\]{transition-property:width,opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.duration-500{--tw-duration:.5s;transition-duration:.5s}.duration-\[400ms\]{--tw-duration:.4s;transition-duration:.4s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.\!running{animation-play-state:running!important}.paused{animation-play-state:paused}.ring-inset{--tw-ring-inset:inset}.running{animation-play-state:running}.group-focus-within\:opacity-100:is(:where(.group):focus-within *){opacity:1}@media (hover:hover){.group-hover\:hidden:is(:where(.group):hover *){display:none}.group-hover\:inline:is(:where(.group):hover *){display:inline}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.group-hover\/badge\:block:is(:where(.group\/badge):hover *){display:block}}.selection\:bg-highlight ::selection{background-color:var(--highlight)}.selection\:bg-highlight::selection{background-color:var(--highlight)}.selection\:text-highlight-foreground ::selection{color:var(--highlight-foreground)}.selection\:text-highlight-foreground::selection{color:var(--highlight-foreground)}.placeholder\:text-muted-foreground::placeholder,.placeholder\:text-muted-foreground\/50::placeholder{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.placeholder\:text-muted-foreground\/50::placeholder{color:color-mix(in oklab, var(--muted-foreground) 50%, transparent)}}.placeholder\:text-muted-foreground\/60::placeholder{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.placeholder\:text-muted-foreground\/60::placeholder{color:color-mix(in oklab, var(--muted-foreground) 60%, transparent)}}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:inset-y-0:after{content:var(--tw-content);inset-block:0}.after\:left-1\/2:after{content:var(--tw-content);left:50%}.after\:w-1\.5:after{content:var(--tw-content);width:calc(var(--spacing) * 1.5)}.after\:-translate-x-1\/2:after{content:var(--tw-content);--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}@media (hover:hover){.hover\:border-border:hover{border-color:var(--border)}.hover\:border-highlight\/40:hover{border-color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.hover\:border-highlight\/40:hover{border-color:color-mix(in oklab, var(--highlight) 40%, transparent)}}.hover\:border-highlight\/50:hover{border-color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.hover\:border-highlight\/50:hover{border-color:color-mix(in oklab, var(--highlight) 50%, transparent)}}.hover\:border-ring\/50:hover{border-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.hover\:border-ring\/50:hover{border-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.hover\:bg-accent:hover{background-color:var(--accent)}.hover\:bg-card:hover{background-color:var(--card)}.hover\:bg-destructive\/10:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/10:hover{background-color:color-mix(in oklab, var(--destructive) 10%, transparent)}}.hover\:bg-destructive\/25:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/25:hover{background-color:color-mix(in oklab, var(--destructive) 25%, transparent)}}.hover\:bg-destructive\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-destructive\/90:hover{background-color:color-mix(in oklab, var(--destructive) 90%, transparent)}}.hover\:bg-highlight\/5:hover{background-color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-highlight\/5:hover{background-color:color-mix(in oklab, var(--highlight) 5%, transparent)}}.hover\:bg-highlight\/90:hover{background-color:var(--highlight)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-highlight\/90:hover{background-color:color-mix(in oklab, var(--highlight) 90%, transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--primary) 90%, transparent)}}.hover\:bg-ring:hover{background-color:var(--ring)}.hover\:bg-secondary:hover,.hover\:bg-secondary\/40:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/40:hover{background-color:color-mix(in oklab, var(--secondary) 40%, transparent)}}.hover\:bg-secondary\/50:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/50:hover{background-color:color-mix(in oklab, var(--secondary) 50%, transparent)}}.hover\:bg-secondary\/60:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/60:hover{background-color:color-mix(in oklab, var(--secondary) 60%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--secondary) 80%, transparent)}}.hover\:bg-sidebar-accent\/60:hover{background-color:var(--sidebar-accent)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-sidebar-accent\/60:hover{background-color:color-mix(in oklab, var(--sidebar-accent) 60%, transparent)}}.hover\:bg-warn:hover,.hover\:bg-warn\/10:hover{background-color:var(--warn)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-warn\/10:hover{background-color:color-mix(in oklab, var(--warn) 10%, transparent)}}.hover\:bg-warn\/25:hover{background-color:var(--warn)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-warn\/25:hover{background-color:color-mix(in oklab, var(--warn) 25%, transparent)}}.hover\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\:text-destructive:hover{color:var(--destructive)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:text-highlight:hover{color:var(--highlight)}.hover\:underline:hover{text-decoration-line:underline}.hover\:decoration-solid:hover{text-decoration-style:solid}.hover\:opacity-100:hover{opacity:1}}.focus\:border-ring:focus{border-color:var(--ring)}.focus\:text-foreground:focus{color:var(--foreground)}.focus-visible\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\:opacity-100:focus-visible{opacity:1}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-\[3px\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible,.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-ring\/50:focus-visible{--tw-ring-color:color-mix(in oklab, var(--ring) 50%, transparent)}}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:cursor-wait:disabled{cursor:wait}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.data-\[disabled\=true\]\:pointer-events-none[data-disabled=true]{pointer-events:none}.data-\[disabled\=true\]\:opacity-50[data-disabled=true]{opacity:.5}.data-\[panel-group-direction\=vertical\]\:h-px[data-panel-group-direction=vertical]{height:1px}.data-\[panel-group-direction\=vertical\]\:w-full[data-panel-group-direction=vertical]{width:100%}.data-\[panel-group-direction\=vertical\]\:flex-col[data-panel-group-direction=vertical]{flex-direction:column}.data-\[panel-group-direction\=vertical\]\:after\:top-1\/2[data-panel-group-direction=vertical]:after{content:var(--tw-content);top:50%}.data-\[panel-group-direction\=vertical\]\:after\:left-0[data-panel-group-direction=vertical]:after{content:var(--tw-content);left:0}.data-\[panel-group-direction\=vertical\]\:after\:h-1\.5[data-panel-group-direction=vertical]:after{content:var(--tw-content);height:calc(var(--spacing) * 1.5)}.data-\[panel-group-direction\=vertical\]\:after\:w-full[data-panel-group-direction=vertical]:after{content:var(--tw-content);width:100%}.data-\[panel-group-direction\=vertical\]\:after\:translate-x-0[data-panel-group-direction=vertical]:after{content:var(--tw-content);--tw-translate-x:0;translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[panel-group-direction\=vertical\]\:after\:-translate-y-1\/2[data-panel-group-direction=vertical]:after{content:var(--tw-content);--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[resize-handle-state\=drag\]\:bg-highlight[data-resize-handle-state=drag]{background-color:var(--highlight)}.data-\[selected\=true\]\:bg-accent[data-selected=true]{background-color:var(--accent)}.data-\[selected\=true\]\:text-accent-foreground[data-selected=true]{color:var(--accent-foreground)}.data-\[state\=active\]\:border-highlight[data-state=active]{border-color:var(--highlight)}.data-\[state\=active\]\:text-foreground[data-state=active]{color:var(--foreground)}.data-\[state\=closed\]\:animate-out[data-state=closed]{animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity:0}.data-\[state\=closed\]\:zoom-out-95[data-state=closed]{--tw-exit-scale:.95}.data-\[state\=open\]\:animate-in[data-state=open]{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\[state\=open\]\:opacity-100[data-state=open]{opacity:1}.data-\[state\=open\]\:fade-in-0[data-state=open]{--tw-enter-opacity:0}.data-\[state\=open\]\:zoom-in-95[data-state=open]{--tw-enter-scale:.95}@media (prefers-reduced-motion:no-preference){.motion-safe\:animate-pulse{animation:var(--animate-pulse)}}@media (prefers-reduced-motion:reduce){.motion-reduce\:animate-none{animation:none}.motion-reduce\:transition-none{transition-property:none}}@media (width>=40rem){.sm\:inline{display:inline}}@media (width>=48rem){.md\:grid-cols-\[minmax\(0\,1fr\)_minmax\(0\,1\.15fr\)\]{grid-template-columns:minmax(0,1fr) minmax(0,1.15fr)}}.\[\&_\[cmdk-group-heading\]\]\:px-2 [cmdk-group-heading]{padding-inline:calc(var(--spacing) * 2)}.\[\&_\[cmdk-group-heading\]\]\:py-1\.5 [cmdk-group-heading]{padding-block:calc(var(--spacing) * 1.5)}.\[\&_\[cmdk-group-heading\]\]\:text-\[10px\] [cmdk-group-heading]{font-size:10px}.\[\&_\[cmdk-group-heading\]\]\:font-medium [cmdk-group-heading]{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.\[\&_\[cmdk-group-heading\]\]\:tracking-wider [cmdk-group-heading]{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.\[\&_\[cmdk-group-heading\]\]\:text-muted-foreground [cmdk-group-heading]{color:var(--muted-foreground)}.\[\&_\[cmdk-group-heading\]\]\:uppercase [cmdk-group-heading]{text-transform:uppercase}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}.\[\&_svg\]\:text-muted-foreground svg{color:var(--muted-foreground)}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-3\.5 svg:not([class*=size-]){width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.\[\&_svg\:not\(\[class\*\=\'size-\'\]\)\]\:size-4 svg:not([class*=size-]){width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}:root{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--background:#151110;--foreground:#eae8e6;--card:#201e1c;--card-foreground:#eae8e6;--popover:#201e1c;--popover-foreground:#eae8e6;--primary:#eae8e6;--primary-foreground:#151110;--secondary:#2a2827;--secondary-foreground:#eae8e6;--muted:#2a2827;--muted-foreground:#a8a5a3;--accent:#2a2827;--accent-foreground:#eae8e6;--tertiary:#1a1716;--tertiary-active:#252220;--destructive:#c44;--destructive-foreground:#fcc;--border:#2a2827;--input:#2a2827;--ring:#3a3837;--radius:.625rem;--sidebar:#1a1716;--sidebar-foreground:#eae8e6;--sidebar-primary:#e07850;--sidebar-primary-foreground:#151110;--sidebar-accent:#252220;--sidebar-accent-foreground:#eae8e6;--sidebar-border:#2a2827;--sidebar-ring:#3a3837;--highlight:#e07850;--highlight-foreground:#151110;--success:#50a878;--warn:#d9a441}#root{height:100vh}.ember-step-active{animation:1.3s ease-in-out infinite ember-step-pulse}@keyframes ember-step-pulse{0%,to{box-shadow:0 0 0 1px #e0785099,0 0 6px #e0785059}50%{box-shadow:0 0 0 2px #e0785066,0 0 10px #e0785099}}@media (prefers-reduced-motion:reduce){.ember-step-active{animation:none;box-shadow:0 0 0 2px #e0785080,0 0 8px #e0785066}}[data-panel-group]:not(:has([data-resize-handle-state=drag]))>[data-panel]{transition:flex-grow .28s cubic-bezier(.22,1,.36,1)}@media (prefers-reduced-motion:reduce){[data-panel-group]>[data-panel]{transition:none}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0));filter:blur(var(--tw-enter-blur,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0));filter:blur(var(--tw-exit-blur,0))}}
|
package/studio-dist/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>Emberflow</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-BbzppDpt.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CLf6blcA.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: emberflow-basics
|
|
3
3
|
description: Use whenever working with Emberflow in this project — running the studio, understanding the file layout, adding or editing API operations and scenarios, registering custom nodes, or using the CLI/MCP. The foundation the other emberflow-* skills build on. Trigger on "emberflow", "workflow builder", "operation", "api", "flow", "run a scenario", "emberflow dev".
|
|
4
4
|
metadata:
|
|
5
|
-
version: 2.
|
|
5
|
+
version: 2.8.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Emberflow basics
|
|
@@ -101,6 +101,34 @@ export default defineConfig({
|
|
|
101
101
|
clear error naming the missing key. Fake success is worse than failure;
|
|
102
102
|
`doctor` flags simulated commit paths as `simulated-commit`.
|
|
103
103
|
|
|
104
|
+
## Node source is executable documentation — keep it in ONE file
|
|
105
|
+
|
|
106
|
+
The studio shows each node's implementation as source, and can navigate into
|
|
107
|
+
project files the implementation imports. That works because Emberflow records
|
|
108
|
+
where each node was registered and resolves ordinary ESM/TS imports. Keep it
|
|
109
|
+
inspectable:
|
|
110
|
+
|
|
111
|
+
- **When YOU author node logic, it lives in ONE module** — the file the
|
|
112
|
+
`registry.register(...)` call sits in. Helpers are named functions in that
|
|
113
|
+
SAME file, above or below the registrations; the studio's file view shows
|
|
114
|
+
them all together. Do NOT spread newly-authored node logic across multiple
|
|
115
|
+
files: every extra hop is a place a reader can get lost, and a file split
|
|
116
|
+
buys nothing the single-file view doesn't already give.
|
|
117
|
+
- **Existing project code is different.** When a node wraps logic the project
|
|
118
|
+
already owns (a `src/pricing.ts` the app also uses), IMPORT it normally —
|
|
119
|
+
never copy or inline it. The studio resolves the import and navigates to it.
|
|
120
|
+
Ordinary relative imports and tsconfig path aliases resolve automatically;
|
|
121
|
+
you do not maintain any reference list.
|
|
122
|
+
- **Never inline logic merely to satisfy the inspector.** The rule is "one
|
|
123
|
+
file for NEW node logic", not "no imports".
|
|
124
|
+
- A registration whose implementation is generated at runtime (a factory, a
|
|
125
|
+
wrapper) can pass an explicit source location:
|
|
126
|
+
`registry.register(def, impl, { sourceRef: { file: 'src/factory.ts', line: 12 } })`.
|
|
127
|
+
- **A thin adapter is not an implementation.** If the displayed handler just
|
|
128
|
+
calls `computeX(ctx.input)` and `computeX` can't be resolved to source, the
|
|
129
|
+
node is NOT adequately inspectable — fix the import so it resolves, or move
|
|
130
|
+
the logic into the registering file.
|
|
131
|
+
|
|
104
132
|
## Operation file shape
|
|
105
133
|
|
|
106
134
|
```json
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: emberflow-model-process
|
|
3
3
|
description: Use when modeling or MIGRATING EXISTING functionality into Emberflow — a single process (script, controller, job, runbook) as one operation, or a whole subsystem (a worker, a pipeline, a service's job handlers) as an API of operations. Emphasises verbatim porting, branch fidelity, determinism, and (at subsystem scale) decomposition and seam verification. For designing something brand-new, use emberflow-new-workflow instead.
|
|
4
4
|
metadata:
|
|
5
|
-
version: 2.
|
|
5
|
+
version: 2.9.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Modeling an existing process as an Emberflow operation
|
|
@@ -14,6 +14,12 @@ documentation of the system. Sections 1–6 govern each individual port; when
|
|
|
14
14
|
the source is a whole subsystem spanning several operations, ALSO apply
|
|
15
15
|
**At subsystem scale** at the end.
|
|
16
16
|
|
|
17
|
+
**Fidelity means preserving behaviour and real execution boundaries, not
|
|
18
|
+
copying the source's file, class, helper-function, or implementation-task
|
|
19
|
+
boundaries into the canvas.** The visible graph tells the domain process in the
|
|
20
|
+
language of its intended readers; existing functions sit underneath those
|
|
21
|
+
domain steps as their implementations.
|
|
22
|
+
|
|
17
23
|
If the process is (or is triggered by) an HTTP endpoint, model it as an HTTP
|
|
18
24
|
operation: create `emberflow/apis/<api>/<folder…>/<name>.json` with `id` equal to
|
|
19
25
|
that path (`emberflow/apis/billing/charge.json` → `"billing/charge"`), add the
|
|
@@ -54,9 +60,30 @@ secret NAMES instead of re-deriving infrastructure the manifest already names.
|
|
|
54
60
|
4. **Scenarios.** "Beyond one scenario per branch of the source, which
|
|
55
61
|
specific cases do you want named and asserted?" (A known incident, a
|
|
56
62
|
particular account shape, the case that motivated the port.)
|
|
63
|
+
5. **Domain read-through.** "Who must be able to read this flow, and which
|
|
64
|
+
decisions or conclusions must they be able to explain from the canvas?"
|
|
65
|
+
Skip the question when the user has already named the audience and the
|
|
66
|
+
domain questions. Record those terms verbatim; they become node and branch
|
|
67
|
+
labels rather than names copied from helper functions.
|
|
57
68
|
|
|
58
69
|
Confirm the summary before porting. The answers feed sections 4–6.
|
|
59
70
|
|
|
71
|
+
### Process-model proposal — required before implementation
|
|
72
|
+
|
|
73
|
+
Present one compact proposal before authoring operation files. It contains:
|
|
74
|
+
|
|
75
|
+
1. The process trigger and outcome in one sentence.
|
|
76
|
+
2. The intended reader and what they must be able to explain from the canvas.
|
|
77
|
+
3. Each proposed operation boundary and the real trigger, durability, retry, or
|
|
78
|
+
lifecycle reason that justifies it.
|
|
79
|
+
4. The visible read-through in domain language, including meaningful decisions
|
|
80
|
+
and intermediate conclusions.
|
|
81
|
+
5. How existing source functions map underneath those visible steps, plus any
|
|
82
|
+
genuinely opaque dependency or deliberate divergence.
|
|
83
|
+
|
|
84
|
+
Get the user's approval when working interactively. Route names, file lists,
|
|
85
|
+
helper names, or implementation tasks are not a substitute for this proposal.
|
|
86
|
+
|
|
60
87
|
## 1. Read the source first, fully
|
|
61
88
|
|
|
62
89
|
Find and read the actual implementation — the script, controller, job, or written
|
|
@@ -68,6 +95,13 @@ runbook. Identify:
|
|
|
68
95
|
- **The side effects** — DB writes, external POSTs, emails, queue sends. These
|
|
69
96
|
become custom nodes marked `effects: 'mutation'`.
|
|
70
97
|
- **The inputs and external data sources** it reads.
|
|
98
|
+
- **The domain story** — trigger, meaningful actions and decisions, and the
|
|
99
|
+
outcome the intended reader cares about. Keep this separate from source helper
|
|
100
|
+
calls, modules, controllers, repositories, and technical layers.
|
|
101
|
+
- **The real process boundaries** — independently triggered HTTP/queue/cron
|
|
102
|
+
handlers, durable hand-offs, separate lifecycles, and independently invoked
|
|
103
|
+
reusable domain processes. A function call or file boundary alone is not a
|
|
104
|
+
process boundary.
|
|
71
105
|
|
|
72
106
|
Do not skim. A faithful model requires knowing what the code actually does,
|
|
73
107
|
including the edge cases.
|
|
@@ -94,17 +128,41 @@ stale constants are findings worth reporting — not things to tidy away.
|
|
|
94
128
|
|
|
95
129
|
## 4. Map the shape onto Emberflow
|
|
96
130
|
|
|
131
|
+
Before choosing files or operation ids, write the visible domain read-through
|
|
132
|
+
as `trigger → domain action/decision → outcome`. A person in the audience
|
|
133
|
+
named during intake must be able to follow that sequence from node and branch
|
|
134
|
+
labels without opening the node implementations. Then map the existing source
|
|
135
|
+
underneath it:
|
|
136
|
+
|
|
97
137
|
- Request in → an `Input` node reading `{ params, query, body, headers }` (for an
|
|
98
138
|
HTTP op); response out → a `Response` node `{ status, body }` per real exit,
|
|
99
139
|
matching the source's status codes (internal flow → `Result`).
|
|
100
|
-
-
|
|
140
|
+
- Domain-meaningful linear steps → a chain of nodes with `inputMap` + edges.
|
|
141
|
+
A node may call one existing function or coordinate several helpers; its
|
|
142
|
+
boundary is the result the intended reader needs to inspect, not the number of
|
|
143
|
+
functions involved.
|
|
101
144
|
- Decisions → `Conditional` (ordered rules) or `Route` (switch on a field), one
|
|
102
145
|
branch per real code path, including the else/default. A branch that returns a
|
|
103
146
|
different HTTP status gets its own `Response`.
|
|
104
147
|
- Loops over collections → `ForEach`/`Collect`.
|
|
105
|
-
-
|
|
106
|
-
|
|
107
|
-
|
|
148
|
+
- Existing helper functions and technical layers → implementation code beneath
|
|
149
|
+
the relevant domain node. Promote a helper to its own visible node when it
|
|
150
|
+
produces a meaningful intermediate domain result, owns an infrastructure
|
|
151
|
+
or effect boundary, or needs distinct retry/inspection behaviour.
|
|
152
|
+
- **Port by importing, never by copying.** A node implementation that wraps
|
|
153
|
+
existing source IMPORTS it from where it lives — the studio resolves the
|
|
154
|
+
import and navigates to the real code, so the port stays verbatim and the
|
|
155
|
+
source of truth stays single. Copying helper bodies into the registering
|
|
156
|
+
file forks them. New glue you write for the port (adapters, small
|
|
157
|
+
reshaping helpers) follows the one-file rule: it lives in the registering
|
|
158
|
+
module itself, not in new satellite files. After porting, open each node's
|
|
159
|
+
source in the studio: every project-owned reference must resolve —
|
|
160
|
+
an unresolved reference hiding ported business logic defeats the port's
|
|
161
|
+
documentation purpose (the review skill treats it as Important/Critical).
|
|
162
|
+
- A coherent in-process domain process that is repeated or independently
|
|
163
|
+
useful → a `Subflow` node calling a separate internal operation. Subflow
|
|
164
|
+
extraction must make the domain read-through clearer. Do not mirror a
|
|
165
|
+
helper call merely because the source factors it out.
|
|
108
166
|
- Effects → `effects: 'mutation'` nodes that dry-run by default and only commit
|
|
109
167
|
under an explicit opt-in. The commit path performs the REAL side effect the
|
|
110
168
|
source performs — the same insert, the same webhook, the same send. A
|
|
@@ -123,6 +181,25 @@ a node's implementation in `registerNodes` before you reference its `type`; the
|
|
|
123
181
|
runner rejects an unregistered type (a name with no implementation), but a type
|
|
124
182
|
you register in the same change is exactly how you model the step.
|
|
125
183
|
|
|
184
|
+
### Keep domain logic visible
|
|
185
|
+
|
|
186
|
+
A generic bridge such as `RunStage`, `ExecuteScript`, or `CallService` may be a
|
|
187
|
+
leaf implementation detail, but it is not a faithful visible model when it
|
|
188
|
+
contains several domain actions or decisions. A graph shaped only as
|
|
189
|
+
`Input → RunWholeStage → Result` documents plumbing, not the process.
|
|
190
|
+
|
|
191
|
+
For each bridge or broad adapter, inspect the source it invokes:
|
|
192
|
+
|
|
193
|
+
1. Put each reader-relevant decision and intermediate conclusion on the
|
|
194
|
+
canvas as a specifically named node or branch.
|
|
195
|
+
2. Keep formulas and constants in the existing implementation when duplicating
|
|
196
|
+
them would risk drift; call that implementation from the domain-named node.
|
|
197
|
+
3. Expose the inputs, calculation basis, outcome, and provenance needed to
|
|
198
|
+
explain the result in the run trace.
|
|
199
|
+
4. If the dependency is genuinely opaque and cannot yet be decomposed, label it
|
|
200
|
+
explicitly as an opaque external step and report the model as
|
|
201
|
+
`process-logic-opaque`; do not call it executable documentation.
|
|
202
|
+
|
|
126
203
|
## 5. Make it deterministic and reproducible
|
|
127
204
|
|
|
128
205
|
Real processes read the clock, the DB, live data. For a faithful, testable model,
|
|
@@ -171,10 +248,13 @@ phases — and a wrongly-shaped mock masks every one of them.
|
|
|
171
248
|
every constant in a table (that table becomes the fidelity checklist all
|
|
172
249
|
reviews check against), external dependencies per phase, and the data
|
|
173
250
|
shapes phases pass each other.
|
|
174
|
-
- **One operation per process boundary.** A queue or cron hop in the source
|
|
175
|
-
an operation boundary in the model — do NOT collapse an async boundary
|
|
176
|
-
a synchronous `Subflow` (the fan-out op models the *send*; the per-job op
|
|
177
|
-
invoked separately).
|
|
251
|
+
- **One operation per real process boundary.** A queue or cron hop in the source
|
|
252
|
+
is an operation boundary in the model — do NOT collapse an async boundary
|
|
253
|
+
into a synchronous `Subflow` (the fan-out op models the *send*; the per-job op
|
|
254
|
+
is invoked separately). Files, classes, helper functions, source-code phases,
|
|
255
|
+
implementation-plan tasks, and test seams are NOT operation boundaries. An
|
|
256
|
+
in-process helper normally stays beneath a node; use a `Subflow` only for a
|
|
257
|
+
coherent repeated or independently useful domain process.
|
|
178
258
|
- **Inventory existing nodes before authoring new ones** — migrations often
|
|
179
259
|
land where partial models already exist. Reuse and extend.
|
|
180
260
|
- **Producers own their output contracts.** If a consumer needs rows, the
|
|
@@ -204,6 +284,9 @@ phases — and a wrongly-shaped mock masks every one of them.
|
|
|
204
284
|
Someone who knows the original system should read the flow and recognise it
|
|
205
285
|
exactly — same steps, same decisions, same constants, same effects — with every
|
|
206
286
|
divergence explicitly marked. If they'd be surprised by a branch, you modeled it wrong.
|
|
287
|
+
The intended reader should also be able to explain from the canvas why the
|
|
288
|
+
process reached its conclusion. If they must open a generic bridge node or read
|
|
289
|
+
source helper names to discover the domain logic, the model is too opaque.
|
|
207
290
|
For a subsystem migration the same bar holds system-wide, and both worlds must
|
|
208
291
|
work: every scenario green in mock mode, and the real path proven or explicitly
|
|
209
292
|
pending.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: emberflow-new-workflow
|
|
3
3
|
description: Use when creating a BRAND-NEW Emberflow API operation from scratch (greenfield) — the user describes a goal or endpoint they want and no existing code models it yet. Guides choosing method + path, wiring Input → logic → Response, choosing built-in vs custom nodes, and covering branches with scenarios. For porting an EXISTING system, use emberflow-model-process instead.
|
|
4
4
|
metadata:
|
|
5
|
-
version: 2.
|
|
5
|
+
version: 2.6.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Building a new Emberflow operation (greenfield)
|
|
@@ -95,6 +95,13 @@ List the steps the endpoint takes, in order. Each becomes a node:
|
|
|
95
95
|
(`'db'|'http'|'llm'`) on every node that touches infrastructure — mock mode
|
|
96
96
|
uses it to know what to intercept. An unmarked infra node silently executes
|
|
97
97
|
for real during mock runs.
|
|
98
|
+
- **Node logic lives in ONE file.** Everything you write for a node — its
|
|
99
|
+
implementation and any helpers — goes in the module the `registry.register`
|
|
100
|
+
call sits in, helpers as named functions in that same file. The studio shows
|
|
101
|
+
that whole file as the node's source, so a reader sees the complete story in
|
|
102
|
+
one place. Never spread newly-authored node logic across multiple files.
|
|
103
|
+
Code the project ALREADY owns is the exception: import it normally (never
|
|
104
|
+
copy it) — the studio resolves imports and navigates to them.
|
|
98
105
|
- **Implementations are real.** A custom node's implementation calls the actual
|
|
99
106
|
dependency (the real query, the real HTTP call, the real SDK) — never canned
|
|
100
107
|
data pretending to be an implementation. Canned data belongs in the scenario
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: emberflow-review-workflow
|
|
3
3
|
description: Use to code-review an Emberflow API operation before it ships — after authoring or modeling one, or when asked to check/audit/review an existing operation. A rubric covering HTTP trigger + auth, wiring integrity, branch coverage, effects/safe-mode correctness, determinism, and readability. Reports findings by severity; does not rubber-stamp.
|
|
4
4
|
metadata:
|
|
5
|
-
version: 2.
|
|
5
|
+
version: 2.4.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Reviewing an Emberflow operation
|
|
@@ -107,6 +107,33 @@ serving, mocks for mock mode. Check both halves.
|
|
|
107
107
|
are mock (canned), dry-run (`wouldSend`/`wouldWrite`), and real commit;
|
|
108
108
|
missing credentials at commit time must THROW naming the secretRef, never
|
|
109
109
|
succeed quietly. `doctor` reports these as `simulated-commit`.
|
|
110
|
+
|
|
111
|
+
## 4c. Source inspectability
|
|
112
|
+
|
|
113
|
+
A node is executable documentation only if its displayed implementation shows
|
|
114
|
+
(or navigates to) the behaviour it delegates. Open each custom node's source
|
|
115
|
+
in the studio and check:
|
|
116
|
+
|
|
117
|
+
- **No unresolved project-owned references.** Every project function, constant
|
|
118
|
+
or class the implementation uses must resolve — either declared in the same
|
|
119
|
+
file or reachable through the studio's reference navigation (ordinary
|
|
120
|
+
imports resolve automatically). An unresolved project-owned reference that
|
|
121
|
+
hides a business decision, formula, classification, or side effect is
|
|
122
|
+
**Important** — **Critical** when the operation's documentation value
|
|
123
|
+
depends on it (a thin adapter presenting `computeX(ctx.input)` as if it
|
|
124
|
+
were the implementation, with `computeX` unreachable).
|
|
125
|
+
- **Newly-authored logic lives in ONE file.** Node logic written for this
|
|
126
|
+
operation belongs in the registering module — helpers as named functions in
|
|
127
|
+
the same file. New logic scattered across multiple new files is Important:
|
|
128
|
+
it fragments the readable story without buying anything. (Imports of code
|
|
129
|
+
the project ALREADY owned are correct and expected — that's what navigation
|
|
130
|
+
is for.)
|
|
131
|
+
- **Nobody inlined to appease the inspector.** Pre-existing shared code that
|
|
132
|
+
was copy-pasted into the registering file (instead of imported) is Important
|
|
133
|
+
— it forks the source of truth.
|
|
134
|
+
- Runtime-generated implementations (factories) must carry an explicit
|
|
135
|
+
`sourceRef` (third argument to `register`) — a generated function with no
|
|
136
|
+
navigable source is Important.
|
|
110
137
|
- **Both modes verified.** Run the scenarios in mock mode; if an environment
|
|
111
138
|
exists, run the real path too. Green in only one world is an unproven
|
|
112
139
|
operation — Important.
|
|
@@ -128,6 +155,37 @@ serving, mocks for mock mode. Check both halves.
|
|
|
128
155
|
- **Layout reads left-to-right, no overlaps** (auto-layout in the studio). Minor,
|
|
129
156
|
but a jumbled graph hides wiring bugs.
|
|
130
157
|
|
|
158
|
+
### Domain read-through (for modeled processes)
|
|
159
|
+
|
|
160
|
+
When an operation claims to model an existing process or serve as executable
|
|
161
|
+
documentation, read the source process and identify its audience before
|
|
162
|
+
approving it. The canvas itself must read as:
|
|
163
|
+
|
|
164
|
+
`trigger → reader-relevant actions/decisions → explained outcome`
|
|
165
|
+
|
|
166
|
+
- **Domain decisions are visible.** Decisions needed to explain the result
|
|
167
|
+
appear as domain-named nodes and `Conditional`/`Route` branches. Existing formulas
|
|
168
|
+
may remain in source functions called by those nodes; do not require copied
|
|
169
|
+
logic merely to make it visible.
|
|
170
|
+
- **Intermediate conclusions are inspectable.** Outputs carry the facts,
|
|
171
|
+
calculation basis, outcome, and provenance the named audience needs to
|
|
172
|
+
explain why the process reached its result.
|
|
173
|
+
- **The graph is not a generic bridge.** `Input → RunWholeStage → Result` is
|
|
174
|
+
Important when `RunWholeStage` hides several reader-relevant actions or
|
|
175
|
+
decisions. Report `process-logic-opaque` and name the hidden decisions.
|
|
176
|
+
- **The graph is not source/task decomposition.** Files, classes, helper
|
|
177
|
+
functions, source-code phases, implementation-plan tasks, and test seams do
|
|
178
|
+
not justify separate operations. Fragmentation that replaces the domain
|
|
179
|
+
read-through with technical stage names is Important.
|
|
180
|
+
- **Real process boundaries remain real.** Independently triggered HTTP,
|
|
181
|
+
queue, and cron handlers and durable hand-offs remain separate operations;
|
|
182
|
+
collapsing one into a synchronous `Subflow` is Critical when it changes
|
|
183
|
+
lifecycle, retry, or delivery semantics.
|
|
184
|
+
|
|
185
|
+
A typed proxy to a genuinely opaque external service is not required to expose
|
|
186
|
+
that service's unavailable internals. It must be described as a proxy or opaque
|
|
187
|
+
step, not as executable documentation of the external process.
|
|
188
|
+
|
|
131
189
|
## 7. Fidelity (for modeled processes)
|
|
132
190
|
|
|
133
191
|
If the flow models existing code (see emberflow-model-process): spot-check the
|
|
@@ -135,6 +193,11 @@ ported constants/thresholds/branch-order against the source. A silently "cleaned
|
|
|
135
193
|
up" constant or dropped branch is a Critical fidelity break. Documented
|
|
136
194
|
`PORT NOTE:` divergences are fine; undocumented ones are findings.
|
|
137
195
|
|
|
196
|
+
Also compare operation and `Subflow` boundaries with the source's real trigger,
|
|
197
|
+
durability, retry, and lifecycle boundaries. Matching function/file structure
|
|
198
|
+
is not fidelity; preserving behaviour while making its domain explanation
|
|
199
|
+
visible is.
|
|
200
|
+
|
|
138
201
|
## Output format
|
|
139
202
|
|
|
140
203
|
```
|