@w6w/ui 0.1.0 → 0.1.1
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/CHANGELOG.md +20 -0
- package/README.md +18 -3
- package/dist/ConfirmModal-8avl9Nv8.cjs +11 -0
- package/dist/ConfirmModal-8avl9Nv8.cjs.map +1 -0
- package/dist/{ConfirmModal-sY1tzkBO.js → ConfirmModal-CD-P8mhN.js} +3822 -3822
- package/dist/ConfirmModal-CD-P8mhN.js.map +1 -0
- package/dist/code.cjs +1 -1
- package/dist/code.mjs +1 -0
- package/dist/code.mjs.map +1 -1
- package/dist/flow.cjs +1 -1
- package/dist/flow.cjs.map +1 -1
- package/dist/flow.d.ts +3 -1
- package/dist/flow.mjs +50 -49
- package/dist/flow.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +3 -2
- package/dist/index.mjs.map +1 -1
- package/dist/provider.d.ts +2 -1
- package/package.json +2 -1
- package/src/code.css +23 -4
- package/src/styles/_flow.scss +4 -4
- package/src/styles/_tokens.scss +23 -4
- package/src/styles.css +695 -9
- package/dist/ConfirmModal-DJPYXE9t.cjs +0 -11
- package/dist/ConfirmModal-DJPYXE9t.cjs.map +0 -1
- package/dist/ConfirmModal-sY1tzkBO.js.map +0 -1
- package/dist/ui.css +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmModal-sY1tzkBO.js","sources":["../src/theme.ts","../src/CodeEditor.tsx","../src/JsonEditor.tsx","../src/components/IconButton.tsx","../src/components/Modal.tsx","../src/types.ts","../src/components/expression-template.ts","../src/components/expression-dom.ts","../src/components/ExpressionEditorModal.tsx","../src/components/ExpressionOptions.tsx","../src/components/ExpressionInput.tsx","../src/resolve-params.ts","../src/resolved-json.ts","../src/ParamsForm.tsx","../src/WaitEditor.tsx","../src/app-categories.ts","../src/flow-types.ts","../src/app-pages.ts","../src/components/AppIcon.tsx","../src/provider.tsx","../src/AppPicker.tsx","../src/components/AuthFieldsForm.tsx","../src/oauth-popup.ts","../src/use-enter-submit.ts","../src/AddConnectionModal.tsx","../src/RetryPolicyFields.tsx","../src/NodeConfigForm.tsx","../src/trigger-fields.ts","../src/TriggerFillForm.tsx","../src/components/Combobox.tsx","../src/components/InternalIcon.tsx","../src/flow-utils.ts","../src/output-shape.ts","../src/step-preview-state.ts","../src/use-seed-sources.ts","../src/StepBuilderModal.tsx","../src/PropertyEntryForm.tsx","../src/components/ConfirmModal.tsx"],"sourcesContent":["import { createContext, useContext, useEffect, useState } from \"react\";\nimport type { ThemeMode } from \"./types.ts\";\n\n/**\n * Set by `<W6WUIProvider theme={...}>` (`provider.tsx`) — the HOST's\n * explicit theme choice for an EMBEDDED `@w6w/ui`, threaded through context\n * so every JS-side theme-aware component resolves the SAME value the\n * provider's own `data-theme` DOM wrapper sets for the CSS side (below),\n * without each component separately re-deriving it from `<html>`.\n * `undefined` when no `<W6WUIProvider>` is in the tree, or one that didn't\n * pass `theme` — every consumer then falls through to the pre-existing\n * `data-theme`-on-`<html>` / OS-preference chain unchanged. See\n * `docs/theming.md`.\n */\nexport const ProvidedThemeCtx = createContext<ThemeMode | undefined>(undefined);\n\n/**\n * Resolve the effective light/dark mode. Priority: explicit prop >\n * `<W6WUIProvider theme>` > `data-theme` on <html> > `prefers-color-scheme`.\n * The `data-theme` step matches the CSS defaults in `styles.css`, so\n * components and stylesheet agree even without a provider `theme` — see\n * `docs/theming.md` for why relying on that alone is a trap for an embedded\n * host, though.\n */\nexport function detectTheme(explicit: ThemeMode | undefined, provided?: ThemeMode): ThemeMode {\n if (explicit) return explicit;\n if (provided) return provided;\n if (typeof document === \"undefined\") return \"light\";\n const attr = document.documentElement.getAttribute(\"data-theme\");\n if (attr === \"dark\" || attr === \"light\") return attr;\n return window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\";\n}\n\n/**\n * Reactive `detectTheme`: reads `<W6WUIProvider theme>` from context, and —\n * when that's unset — subscribes to `data-theme` mutations on <html> and OS\n * `prefers-color-scheme` changes, so a runtime theme toggle (e.g. studio's\n * ThemeToggle, or a host re-rendering `<W6WUIProvider theme>` with a new\n * value) is reflected without a remount. Shared by every ui component that\n * needs the mode in JS (AppIcon, CodeEditor, JsonEditor, WorkflowFlowEditor)\n * so they never drift from each other or from the CSS.\n */\nexport function useEffectiveTheme(explicit?: ThemeMode): ThemeMode {\n const provided = useContext(ProvidedThemeCtx);\n const [mode, setMode] = useState<ThemeMode>(() => detectTheme(explicit, provided));\n\n useEffect(() => {\n if (explicit) {\n setMode(explicit);\n return;\n }\n if (provided) {\n setMode(provided);\n return;\n }\n if (typeof window === \"undefined\") return;\n\n const update = () => setMode(detectTheme(undefined, provided));\n\n const mql = window.matchMedia(\"(prefers-color-scheme: dark)\");\n mql.addEventListener(\"change\", update);\n\n const observer = new MutationObserver(update);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"data-theme\"],\n });\n\n // Re-sync once in case the attribute changed between the initial render and\n // this effect running.\n update();\n\n return () => {\n mql.removeEventListener(\"change\", update);\n observer.disconnect();\n };\n }, [explicit, provided]);\n\n return mode;\n}\n","import { javascript } from \"@codemirror/lang-javascript\";\nimport { python } from \"@codemirror/lang-python\";\nimport type { Extension } from \"@codemirror/state\";\nimport { EditorView } from \"@codemirror/view\";\nimport CodeMirror from \"@uiw/react-codemirror\";\nimport { useMemo } from \"react\";\nimport { useEffectiveTheme } from \"./theme.ts\";\nimport type { ThemeMode } from \"./types.ts\";\n\n/**\n * A CodeMirror *editing* mode for `<CodeEditor>` — a distinct concept from the\n * Prism *display-highlighting* grammar name a sibling module exports for\n * rendered snippets. Deliberately its own type, not shared with that one.\n */\nexport type ScriptLanguage = \"javascript\" | \"python\";\n\n// Exhaustive over every `ScriptLanguage` member, with no fallback arm — a\n// third value added to the union fails to compile here instead of silently\n// falling through (house idiom, see `StepBuilderModal.tsx`'s glyph maps /\n// `doc-format.ts`'s total switch).\nfunction languageExtension(language: ScriptLanguage): Extension {\n switch (language) {\n case \"javascript\":\n return javascript();\n case \"python\":\n return python();\n }\n}\n\nexport interface CodeEditorProps {\n value: string;\n onChange: (value: string) => void;\n /** Placeholder text shown when value is empty. */\n placeholder?: string;\n /** Minimum editor height. Defaults to \"160px\". */\n minHeight?: string;\n /** Maximum editor height before scrolling. Defaults to no cap. */\n maxHeight?: string;\n /** Explicit editor height. Pass `\"100%\"` to fill a flex parent. */\n height?: string;\n /** Read-only mode. */\n readOnly?: boolean;\n /**\n * Explicit theme. If omitted, auto-detects `data-theme` on `<html>` and falls\n * back to `prefers-color-scheme` — same behavior as `<JsonEditor>`.\n */\n theme?: ThemeMode;\n /**\n * CodeMirror editing mode (syntax highlighting + language-aware editing).\n * Omitted ⇒ today's exact plain-text behavior, unchanged.\n */\n language?: ScriptLanguage;\n /** Accessible label for the editor. */\n \"aria-label\"?: string;\n}\n\n/**\n * Plain-text-by-default code editor built on CodeMirror 6 — the same surface as\n * `<JsonEditor>` minus JSON language/linting, for editing snippets (e.g. an\n * inline script). Line numbers, bracket matching, and `--w6w-*` theming so it\n * inherits the consumer's palette. Pass `language` to opt into a CodeMirror\n * language pack (JavaScript/Python); omit it for the original dependency-free\n * plain-text mode.\n */\nexport function CodeEditor(props: CodeEditorProps) {\n const theme = useEffectiveTheme(props.theme);\n const extensions = useMemo(\n () => [\n ...(props.language ? [languageExtension(props.language)] : []),\n EditorView.theme({\n \"&\": {\n fontSize: \"13px\",\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n backgroundColor: \"var(--w6w-panel-2)\",\n color: \"var(--w6w-text)\",\n border: \"1px solid var(--w6w-border)\",\n borderRadius: \"8px\",\n },\n \"&.cm-focused\": { outline: \"2px solid var(--w6w-accent)\" },\n \".cm-gutters\": {\n backgroundColor: \"var(--w6w-panel)\",\n color: \"var(--w6w-muted)\",\n border: \"none\",\n borderRight: \"1px solid var(--w6w-border)\",\n },\n \".cm-scroller\": { overflow: \"auto\" },\n }),\n ],\n [props.language],\n );\n\n return (\n <div className=\"w6w-code-editor\" aria-label={props[\"aria-label\"] ?? \"Code editor\"}>\n <CodeMirror\n value={props.value}\n onChange={props.onChange}\n extensions={extensions}\n placeholder={props.placeholder}\n readOnly={props.readOnly}\n theme={theme}\n height={props.height}\n minHeight={props.minHeight ?? \"160px\"}\n maxHeight={props.maxHeight}\n basicSetup={{\n lineNumbers: true,\n foldGutter: false,\n highlightActiveLine: !props.readOnly,\n bracketMatching: true,\n closeBrackets: true,\n }}\n />\n </div>\n );\n}\n","import { json, jsonParseLinter } from \"@codemirror/lang-json\";\nimport { lintGutter, linter } from \"@codemirror/lint\";\nimport { EditorView } from \"@codemirror/view\";\nimport CodeMirror from \"@uiw/react-codemirror\";\nimport { useMemo } from \"react\";\nimport { CheckGlyph, CopyGlyph } from \"./components/Copyable.tsx\";\nimport { useCopyToClipboard } from \"./components/use-copy.ts\";\nimport { useEffectiveTheme } from \"./theme.ts\";\nimport type { ThemeMode } from \"./types.ts\";\n\nexport interface JsonEditorProps {\n value: string;\n onChange: (value: string) => void;\n /**\n * Fired whenever the current value parses as JSON, with the parsed value.\n * Never fires while the value is invalid — pair it with a validity flag if\n * you want to react to invalidation too (e.g., disable a Save button).\n */\n onValidChange?: (parsed: unknown) => void;\n /** Optional callback fired on every keystroke with parse validity + error. */\n onValidityChange?: (result: { valid: boolean; error?: string }) => void;\n\n /** Placeholder text shown when value is empty. */\n placeholder?: string;\n /** Minimum editor height. Defaults to \"240px\". */\n minHeight?: string;\n /** Maximum editor height before scrolling. Defaults to no cap. */\n maxHeight?: string;\n /**\n * Explicit editor height. Pass `\"100%\"` to fill a flex parent (the whole-config\n * \"code\" view). Omit to let the editor grow with its content between\n * `minHeight` and `maxHeight` — an inline JSON/group field wants this.\n */\n height?: string;\n\n /** Read-only mode — useful for previewing a stored definition. */\n readOnly?: boolean;\n\n /**\n * Explicit theme. If omitted, the editor auto-detects `data-theme` on\n * `<html>` and falls back to `prefers-color-scheme` — same behavior as\n * `<AppIcon>`. Uses CodeMirror's built-in one-dark for dark mode.\n */\n theme?: ThemeMode;\n\n /** Accessible label for the editor. */\n \"aria-label\"?: string;\n\n /**\n * Render an in-box copy-to-clipboard button, a direct child of this\n * component's own `.w6w-json-editor` wrapper (sibling to the CodeMirror\n * mount — no extra DOM node). Copies the current `value` verbatim.\n *\n * Off by default: the other five `<JsonEditor>` mounts in this tree are\n * not step-JSON config views and must render byte-identically to before\n * this prop existed.\n */\n copyable?: boolean;\n}\n\n/**\n * JSON editor built on CodeMirror 6. Syntax highlighting, folding, gutter with\n * lint markers for invalid JSON. Themed with the `--w6w-*` custom properties so\n * it inherits from the consumer's palette.\n *\n * ```tsx\n * <JsonEditor value={text} onChange={setText}\n * onValidChange={(parsed) => setDefinition(parsed)}\n * minHeight=\"320px\" />\n * ```\n */\nexport function JsonEditor(props: JsonEditorProps) {\n const theme = useEffectiveTheme(props.theme);\n // Only mounted when `copyable` is on, but the hook itself must run\n // unconditionally (Rules of Hooks) — it is inert (no button, no listener)\n // until `copy()` is actually invoked from the button below.\n const { copied, copy } = useCopyToClipboard(props.value);\n const extensions = useMemo(\n () => [\n json(),\n linter(jsonParseLinter()),\n lintGutter(),\n EditorView.theme({\n \"&\": {\n fontSize: \"13px\",\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n backgroundColor: \"var(--w6w-panel-2)\",\n color: \"var(--w6w-text)\",\n border: \"1px solid var(--w6w-border)\",\n borderRadius: \"8px\",\n },\n \"&.cm-focused\": { outline: \"2px solid var(--w6w-accent)\" },\n \".cm-gutters\": {\n backgroundColor: \"var(--w6w-panel)\",\n color: \"var(--w6w-muted)\",\n border: \"none\",\n borderRight: \"1px solid var(--w6w-border)\",\n },\n \".cm-scroller\": { overflow: \"auto\" },\n }),\n ],\n [],\n );\n\n function handleChange(next: string) {\n props.onChange(next);\n if (!props.onValidChange && !props.onValidityChange) return;\n if (next.trim().length === 0) {\n props.onValidityChange?.({ valid: false, error: \"Empty\" });\n return;\n }\n try {\n const parsed = JSON.parse(next);\n props.onValidChange?.(parsed);\n props.onValidityChange?.({ valid: true });\n } catch (e) {\n props.onValidityChange?.({ valid: false, error: (e as Error).message });\n }\n }\n\n return (\n <div className=\"w6w-json-editor\" aria-label={props[\"aria-label\"] ?? \"JSON editor\"}>\n <CodeMirror\n value={props.value}\n onChange={handleChange}\n extensions={extensions}\n placeholder={props.placeholder}\n readOnly={props.readOnly}\n // `readOnly` alone only blocks CodeMirror's own transactions\n // (`EditorState.readOnly`) — it leaves the content DOM\n // `contenteditable=\"true\"`, so a screen reader / a11y test still sees\n // it as an editable field. `editable` is the separate switch that\n // actually sets `contenteditable` (`EditorView.editable`); tying it to\n // `readOnly` here makes the prop mean what its name says.\n editable={!props.readOnly}\n theme={theme}\n height={props.height}\n minHeight={props.minHeight ?? \"240px\"}\n maxHeight={props.maxHeight}\n basicSetup={{\n lineNumbers: true,\n foldGutter: true,\n highlightActiveLine: !props.readOnly,\n autocompletion: true,\n bracketMatching: true,\n closeBrackets: true,\n }}\n />\n {props.copyable && (\n <>\n <button\n type=\"button\"\n className={`w6w-icon-btn w6w-copyable-btn${copied ? \" is-copied\" : \"\"}`}\n aria-label=\"Copy\"\n onClick={() => void copy()}\n >\n {copied ? <CheckGlyph /> : <CopyGlyph />}\n </button>\n {/* Same live-region convention as `Copyable.tsx:141-147`: the\n button's accessible name stays constant, so this announces the\n result. */}\n <span className=\"w6w-copyable-status\" aria-live=\"polite\">\n {copied ? \"Copied\" : \"\"}\n </span>\n </>\n )}\n </div>\n );\n}\n","import { type ReactNode, forwardRef } from \"react\";\nimport { Icon } from \"./Icon.tsx\";\nimport type { IconName } from \"./icons.tsx\";\n\nexport interface IconButtonProps {\n /** Accessible name — ALWAYS rendered as `aria-label`. Required: an icon-only\n * button with no name has no safe default (unlike `Copyable`'s `label`,\n * which is always \"Copy\"). */\n label: string;\n /** The glyph, as caller-supplied markup. Still the primary path — pass this\n * or `icon` (both given ⇒ `children` wins). */\n children?: ReactNode;\n /** The glyph, by name from the shared set (`./icons.tsx`) — e.g. `\"history\"`.\n * Renders `<Icon name={icon} size={iconSize ?? 16} />`, decorative, so this\n * button's `label` stays the only thing announced. */\n icon?: IconName;\n /** Size handed to `Icon`. Default 16. No effect without `icon`. */\n iconSize?: number;\n /** Tooltip override. Defaults to `label`; `aria-label` is ALWAYS `label`, so\n * the two may legitimately differ (see the docblock). */\n title?: string;\n /** Required — an icon-only button that can't fire has no reason to exist. */\n onClick: () => void;\n disabled?: boolean;\n className?: string;\n /** Caller opts into danger styling; `IconButton` itself has no \"delete\" concept. */\n danger?: boolean;\n /** Passed straight through, for a toggle button. */\n \"aria-pressed\"?: boolean;\n /** Passed straight through, for a disclosure button. */\n \"aria-expanded\"?: boolean;\n /** Passed straight through, for a disclosure button naming the region it controls. */\n \"aria-controls\"?: string;\n \"data-testid\"?: string;\n}\n\n/**\n * The primitive icon-only button: a caller-supplied glyph, a required\n * accessible name, native `disabled`, and a merged `className`.\n *\n * `EditButton`/`DeleteButton` build on this and bundle one canonical glyph\n * each — this component itself carries no glyph and no \"edit\"/\"delete\"\n * meaning, only the `danger` styling hook.\n *\n * The glyph comes from one of two places. `children` is the original path and\n * still works unchanged; `icon` names one from the shared set (`./icons.tsx`)\n * and is rendered through `Icon`, so a caller no longer has to redraw (or\n * import) an SVG for a glyph the set already holds. Given both, `children`\n * wins — the named prop is the convenience, never a way to hide a caller's own\n * markup.\n *\n * `label` is always the accessible name, and `title` overrides ONLY the\n * tooltip. The two legitimately differ: studio's history button is named\n * \"Execution history\" while, with nothing executed yet, its tooltip reads \"No\n * executions yet\" — the tooltip says why the control is inert to a sighted\n * user, the name stays the action, and a screen reader must keep hearing the\n * latter.\n *\n * `ref` reaches the `<button>` itself (`forwardRef` — React 18, so the\n * ref-as-prop syntax is not available), which is what a caller needs to move\n * focus or measure the control.\n */\nexport const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(\n function IconButton(props, ref) {\n const {\n label,\n children,\n icon,\n iconSize,\n title,\n onClick,\n disabled,\n className,\n danger,\n ...rest\n } = props;\n const glyph = children ?? (icon ? <Icon name={icon} size={iconSize ?? 16} /> : null);\n return (\n <button\n ref={ref}\n type=\"button\"\n className={[\"w6w-icon-button\", danger ? \"w6w-icon-button-danger\" : \"\", className ?? \"\"]\n .filter(Boolean)\n .join(\" \")}\n title={title ?? label}\n aria-label={label}\n aria-pressed={rest[\"aria-pressed\"]}\n aria-expanded={rest[\"aria-expanded\"]}\n aria-controls={rest[\"aria-controls\"]}\n disabled={disabled}\n onClick={onClick}\n data-testid={rest[\"data-testid\"]}\n >\n {glyph}\n </button>\n );\n },\n);\n\nIconButton.displayName = \"IconButton\";\n","import { type ReactNode, useEffect, useRef } from \"react\";\n\ninterface ModalProps {\n /** Title row content. A plain string also seeds the dialog's `aria-label`. */\n title: ReactNode;\n /** Accessible name for the dialog; defaults to `title` when it's a string. */\n ariaLabel?: string;\n onClose: () => void;\n children: ReactNode;\n /**\n * Dialog width. `\"wide\"` fits a sidebar + content layout; `\"xl\"` is a large\n * work surface (e.g. the app picker); `\"full\"` is a near-fullscreen work\n * surface (e.g. the expression editor) that fills most of the viewport;\n * `\"fullscreen\"` is edge-to-edge 100vw x 100vh with no visible backdrop.\n *\n * `\"fullscreen\"` leaves NO backdrop to click, so outside-click dismissal is\n * unreachable by construction — a caller using it must give the user a\n * visible way out via {@link ModalProps.headerRight} (Esc alone is not a\n * discoverable affordance).\n */\n size?: \"default\" | \"wide\" | \"xl\" | \"full\" | \"fullscreen\";\n /** Optional node rendered next to the title (e.g. an app icon). */\n titleIcon?: ReactNode;\n /** Optional muted meta rendered after the title (e.g. an app's id + version). */\n subtitle?: ReactNode;\n /** Optional node rendered at the far right of the title row (e.g. a back button). */\n headerRight?: ReactNode;\n}\n\n/**\n * Small dialog modal. Built on the native `<dialog>` element so it gets focus\n * trapping, Esc-dismiss, and accessibility semantics for free. A button\n * positioned over the backdrop catches outside-clicks to close.\n */\nconst SIZE_CLASS: Record<NonNullable<ModalProps[\"size\"]>, string> = {\n default: \"\",\n wide: \" w6w-modal-wide\",\n xl: \" w6w-modal-xl\",\n full: \" w6w-modal-full\",\n fullscreen: \" w6w-modal-fullscreen\",\n};\n\nexport function Modal({\n title,\n ariaLabel,\n onClose,\n children,\n size = \"default\",\n titleIcon,\n subtitle,\n headerRight,\n}: ModalProps) {\n const ref = useRef<HTMLDialogElement>(null);\n\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n if (!el.open) el.showModal();\n const onCancel = (e: Event) => {\n e.preventDefault();\n onClose();\n };\n // A `showModal()` dialog and its ::backdrop live in the browser's top layer,\n // above any sibling overlay — so an overlay button can't catch outside\n // clicks. Backdrop clicks are dispatched with the dialog as target, so\n // treat a click landing outside the dialog's box as a dismiss.\n const onClick = (e: MouseEvent) => {\n if (e.target !== el) return;\n const r = el.getBoundingClientRect();\n const outside =\n e.clientX < r.left || e.clientX > r.right || e.clientY < r.top || e.clientY > r.bottom;\n if (outside) onClose();\n };\n el.addEventListener(\"cancel\", onCancel);\n el.addEventListener(\"click\", onClick);\n return () => {\n el.removeEventListener(\"cancel\", onCancel);\n el.removeEventListener(\"click\", onClick);\n };\n }, [onClose]);\n\n return (\n <div className=\"w6w-modal-backdrop\">\n <dialog\n ref={ref}\n className={`w6w-modal${SIZE_CLASS[size]}`}\n aria-label={ariaLabel ?? (typeof title === \"string\" ? title : undefined)}\n >\n <div className=\"w6w-modal-header\">\n <h3 className=\"w6w-modal-title\">\n {titleIcon}\n <span>{title}</span>\n {subtitle && <span className=\"w6w-modal-subtitle\">{subtitle}</span>}\n </h3>\n {headerRight}\n </div>\n {children}\n </dialog>\n </div>\n );\n}\n","/**\n * Wire types the components consume. These mirror the shapes the w6w server\n * returns over HTTP. They are intentionally a local copy so consumers who\n * don't use `@w6w/types` (partners, non-TypeScript backends) don't need it.\n */\n\n/** Summary of a registered app as returned by GET /apps. */\nexport interface AppSummary {\n id: string;\n displayName: string;\n version?: string;\n description?: string;\n categories?: string[];\n sourceRef?: string;\n importedAt?: string;\n /** Inlined data: URI (or absolute URL) for the app's icon. */\n iconSvg?: string;\n /** Optional dark-mode variant. */\n iconSvgDark?: string;\n brandColor?: string;\n brandColorDark?: string;\n versionCount?: number;\n maturity?: string;\n visibility?: string;\n successor?: string;\n /**\n * True when the calling tenant has zero-credential access flagged for this\n * app — usable with no connection step at all (server-computed per caller;\n * `packages/server/packages/api/wire-summary.ts`'s `zeroCredential`).\n */\n zeroCredential?: boolean;\n}\n\n/** One trigger an app declares, as returned by GET /apps/:id/triggers. */\nexport interface TriggerSummary {\n key: string;\n /** The trigger's human label. REQUIRED — the wire type calls it `title`, not\n * `displayName`; do not rename it. */\n title: string;\n description?: string;\n requiresAuth?: boolean;\n /** `\"poll\"` triggers are fetched on an interval; absent or `\"webhook\"` receive pushes. */\n type?: \"webhook\" | \"poll\";\n /** Host floor for a poll trigger's interval, in milliseconds. */\n minIntervalMs?: number;\n}\n\n/** A Subscription (rfcs/trigger.md) as returned by the console subscription routes. */\nexport interface SubscriptionSummary {\n id: string;\n appId: string;\n triggerKey: string;\n workflowId: string;\n connectionId: string | null;\n /** Present only for `appId === \"@w6w/webhook\"` — the server's own computed receive URL. */\n webhookUrl?: string;\n type?: \"webhook\" | \"poll\";\n status?: string;\n /** Poll interval in milliseconds; null for webhook subscriptions. */\n intervalMs?: number | null;\n lastError?: { code: string; message: string } | null;\n}\n\n/** One field on an Auth method's connection form. Drives the input widgets. */\nexport interface AuthField {\n key: string;\n label: string;\n type: \"string\" | \"number\" | \"boolean\" | \"secret\" | string;\n required?: boolean;\n default?: unknown;\n hint?: string;\n}\n\n/**\n * One declared parameter of an action, as returned by GET /apps/:id (the\n * `actions[].params` array). Drives the guided step-builder form. Same shape as\n * an app manifest's action param — a superset of `AuthField` (adds `text`/`json`\n * widget types).\n */\nexport interface ActionParam {\n key: string;\n label?: string;\n /**\n * Widget to render for this param. Beyond the scalar types, `text` is a\n * textarea, `json`/`group` an inline JSON editor, `code` a code editor, and\n * `vars` a dynamic typed key/value table.\n */\n type:\n | \"string\"\n | \"text\"\n | \"number\"\n | \"boolean\"\n | \"select\"\n | \"multiselect\"\n | \"array\"\n | \"json\"\n | \"group\"\n | \"secret\"\n | \"code\"\n | \"vars\"\n | \"section\"\n | string;\n required?: boolean;\n default?: unknown;\n hint?: string;\n /** Placeholder text for the input (e.g. the trailing prompt on a multiselect). */\n placeholder?: string;\n /**\n * Move this (optional) param under the collapsed \"Additional parameters\"\n * section. Required + non-advanced params show up front. Ignored for required\n * params (they always show).\n */\n advanced?: boolean;\n /**\n * Lay this param out on a shared row with adjacent params carrying the same\n * `row` id — e.g. a username/password pair side by side.\n */\n row?: string;\n /**\n * Allow multiple values (array of `type`). Renders as an add/remove list via\n * the same `ArrayField` a `type: \"array\"` param uses, with a synthesized\n * `item` — sugar for `type: \"array\"`; see rfcs/param.md's `repeat` amendment.\n * Mirrors `@w6w/types`' `Param.repeat`.\n */\n repeat?: boolean;\n /** Element schema when `type: \"array\"` (a scalar list or a list of objects). */\n item?: ParamArrayItem;\n /**\n * Conditional visibility — the param renders only when this predicate holds\n * against a sibling field's value. Lets a schema declare conditional sections\n * (e.g. Basic-auth fields shown only when `auth` is `\"basic\"`).\n */\n showIf?: ParamCondition;\n /**\n * Constrained choices. Renders as a single-select dropdown for `select` (or any\n * param with options), and as a multi-select pill picker for `multiselect`.\n */\n options?: ParamOption[];\n /** Type-specific render/behavior options. */\n config?: ParamConfig;\n /**\n * Nested params, walked by the renderer for `type: \"group\"` (nested object)\n * and `type: \"section\"` (layout-only container whose children write to the\n * ENCLOSING form values, not under this param's key).\n */\n children?: ActionParam[];\n /**\n * `type: \"section\"` only — the container behavior. `\"collapsible\"` renders a\n * titled, collapsed-by-default disclosure; `\"group\"` a `layout` row/stack.\n */\n section?: \"collapsible\" | \"group\";\n /** `section: \"collapsible\"` only — the `<summary>` heading. */\n title?: string;\n /** `section: \"collapsible\"` only — an optional secondary summary line. */\n subtitle?: string;\n /** `section: \"group\"` only — `\"row\"` side by side, `\"stack\"` vertical (default). */\n layout?: \"row\" | \"stack\";\n /** `section: \"collapsible\"` only — start collapsed (default `true`). */\n collapsed?: boolean;\n}\n\n/** A single choice for a param rendered as a dropdown. */\nexport interface ParamOption {\n value: string | number;\n label: string;\n}\n\n/**\n * The element schema for a `type: \"array\"` param. Either a scalar list\n * (`type: \"string\" | \"number\"`, each item a single value) or a list of objects\n * (`type: \"object\"` with `fields`, each item a `{ [key]: value }` record whose\n * fields render side by side).\n */\nexport interface ParamArrayItem {\n type: \"string\" | \"number\" | \"object\" | string;\n /** For object items — the fields of each element (rendered inline in a row). */\n fields?: ActionParam[];\n /** Placeholder for a scalar item's input. */\n placeholder?: string;\n /** For a scalar item — constrained choices, carried over from a `repeat: true`\n * param's own `options` (a `repeat` scalar with `options` still needs them). */\n options?: ParamOption[];\n}\n\n/**\n * A conditional-visibility predicate tested against a sibling param's value.\n * Exactly one of `equals` / `in` / `notIn` / `truthy` is used (checked in that\n * order). The compared value falls back to the sibling's `default` when unset.\n */\nexport interface ParamCondition {\n /** Sibling param key whose value is tested. */\n field: string;\n /** Visible when the field's value strictly equals this. */\n equals?: string | number | boolean;\n /** Visible when the field's value is one of these. */\n in?: Array<string | number | boolean>;\n /** Visible when the field's value is NOT one of these. */\n notIn?: Array<string | number | boolean>;\n /** Visible when the field's value is truthy (`true`) or falsy (`false`). */\n truthy?: boolean;\n}\n\n/** Type-specific render/behavior options for a param. */\nexport interface ParamConfig {\n /** Render as a multi-line textarea. Implied by `type: \"text\"`. */\n multiline?: boolean;\n}\n\n/** Summary of an action an app exposes, as returned by GET /apps/:id. */\nexport interface ActionDef {\n key: string;\n type?: string;\n title?: string;\n description?: string;\n params?: ActionParam[];\n /**\n * The declared output shape — `OutputField[]` (`{ key, type, label }`, a dot\n * key for a nested path) or a `DynamicOutput` (`{ source }`) the editor does\n * not resolve. Read by `output-shape.ts`, so a later step can pick fields.\n */\n output?: unknown;\n /** An example output value; used for the field shape when `output` is absent. */\n sample?: unknown;\n /** Declared connection ports; `\"many\"` is unbounded. Absent fields fall through to defaults. */\n ports?: { in?: number | \"many\"; out?: number | \"many\" };\n}\n\n/**\n * Summary of a registered Function, as returned by GET /functions (core\n * rfcs/function.md). `valid` mirrors the server's `isFunctionValid` — false for\n * a draft Function (no `impl`, or an incomplete one) — the picker's list stage\n * doesn't gate on it (an invalid Function still shows up; the server's own\n * invoke route is what refuses it).\n */\nexport interface FunctionSummary {\n id: string;\n key: string;\n displayName?: string;\n description?: string;\n updatedAt?: string;\n valid: boolean;\n}\n\n/**\n * A Function's canonical interface, as returned by GET /functions/:id — enough\n * to render its `inputs` form (core rfcs/function.md). `inputs` reuses the\n * wire-mirror `ActionParam[]` shape verbatim, exactly as an app action's own\n * declared `params` do.\n */\nexport interface FunctionDetail {\n id: string;\n key: string;\n displayName?: string;\n description?: string;\n inputs: ActionParam[];\n valid: boolean;\n}\n\n/** Summary of a registered Workflow, as returned by GET /workflows. */\nexport interface WorkflowSummary {\n id: string;\n name: string;\n displayName?: string;\n description?: string;\n status?: string;\n updatedAt?: string;\n}\n\n/** One step of a Workflow, as returned by GET /workflows/:id — the minimal\n * shape the picker's Configure stage needs to find the entry/trigger step's\n * own declared `with.fields` (core rfcs/node-types.md's trigger node). */\nexport interface WorkflowStepSummary {\n id: string;\n uses: { app: string; action: string };\n with?: Record<string, unknown>;\n}\n\n/**\n * Full Workflow definition, as returned by GET /workflows/:id — enough to\n * derive the trigger's declared input fields for the Functions/Workflows\n * picker's Configure stage. A deliberately smaller mirror than `FlowWorkflow`\n * (`flow-types.ts`) — these wire types stay independent of the flow-editor's\n * own type, matching this file's own \"local copy\" convention.\n */\nexport interface WorkflowDetail {\n id: string;\n name: string;\n displayName?: string;\n description?: string;\n steps: WorkflowStepSummary[];\n}\n\n/** Auth method declaration as exposed by an app's manifest. */\nexport interface AuthDef {\n key: string;\n type: \"oauth2\" | \"apiKey\" | \"basic\" | \"bearer\" | \"custom\" | \"tenantAuth\" | \"jit\" | string;\n displayName?: string;\n description?: string;\n connectionLabel?: string;\n fields?: AuthField[];\n /** OAuth2 endpoints (only present when type === \"oauth2\"). */\n oauth2?: Record<string, unknown>;\n /**\n * False when the method requires per-host configuration that hasn't been\n * provided yet (e.g. an oauth2 method with no client credentials set up).\n * The picker hides entries with `available === false`.\n */\n available?: boolean;\n /** Names of host-side config keys this method needs, when applicable. */\n requiresHostConfig?: string[];\n /**\n * Present only on a `tenantAuth`/`jit` entry: `true` when the operator has\n * flagged this method as zero-credential for the calling scope's tenant, so\n * the server resolves a connection automatically at invoke time. This is\n * NOT `available` — `available` means \"this method can be picked at all\";\n * `autoSatisfied` means \"the user does not have to pick anything for it\".\n */\n autoSatisfied?: boolean;\n /**\n * `true` on the one method the server marks as the tenant's default for this\n * app. The connect modal preselects it (among the available methods).\n */\n default?: boolean;\n}\n\n/** Public summary of a stored connection — never carries the credential. */\n/** The display meta the server inlines on each {@link ConnectionSummary} (`app`). */\nexport interface ConnectionAppMeta {\n displayName: string;\n iconSvg?: string;\n iconSvgDark?: string;\n brandColor?: string;\n brandColorDark?: string;\n}\n\nexport interface ConnectionSummary {\n id: string;\n appId: string;\n authKey: string;\n /** The owning tenant. The server sends `tenant`/`subject`, never `owner`. */\n tenant?: string;\n /** The owning subject (the partner's user id). */\n subject?: string;\n /**\n * The connection's app, inline: just enough to draw its card. `null` when the\n * app is no longer in the catalog; absent from servers that don't send it.\n */\n app?: ConnectionAppMeta | null;\n displayName?: string;\n state?: \"pending\" | \"connected\" | \"needs_refresh\" | \"broken\" | \"revoked\" | string;\n profile?: Record<string, unknown>;\n createdAt?: string;\n updatedAt?: string;\n}\n\n/** A saved set of action-test input values, scoped to a connection + action. */\nexport interface SavedTest {\n id: string;\n connectionId: string;\n appId: string;\n actionKey: string;\n name: string;\n values: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n /** When this saved test was last run (ISO), or null/undefined if never run. */\n lastRunAt?: string | null;\n /** Whether the most recent run succeeded, or null/undefined if never run. */\n lastRunOk?: boolean | null;\n /** Short headline for the most recent run's outcome, or null/undefined if never run. */\n lastRunSummary?: string | null;\n}\n\n/**\n * One outbound HTTP call an action made while running — the exact (redacted)\n * request that went to the third-party API and the response that came back.\n * Returned alongside an invoke's value/error and persisted server-side, so a\n * run can be debugged and evaluated against the vendor's documented API.\n */\nexport interface ApiCallRecord {\n host: string;\n method: string;\n /** 0 when the request never produced a response (`error` says why). */\n status: number;\n url?: string;\n requestHeaders?: Record<string, string>;\n /** `null` on a persisted row that captured no body. */\n requestBody?: string | null;\n responseHeaders?: Record<string, string>;\n responseBody?: string | null;\n responseBytes?: number;\n durationMs?: number;\n /** A captured body hit the size cap and was cut. */\n truncated?: boolean;\n error?: string | null;\n}\n\n/** Effective theme hint passed to icon components to pick a light/dark variant. */\nexport type ThemeMode = \"light\" | \"dark\";\n\n/*\n * ---------------------------------------------------------------------------\n * Value model — the multipart/expression + secret envelopes for a step's\n * `with` block. Mirrored (shape-for-shape) from `@w6w/types` `value.ts` so\n * consumers who don't depend on `@w6w/types` don't have to. Keep in sync with\n * core: packages/core/packages/types/src/value.ts.\n * ---------------------------------------------------------------------------\n */\n\n/** The segment kinds an {@link ExprValue} part can take. */\nexport type ExprPartKind = \"text\" | \"var\" | \"secret\" | \"expr\" | \"render\";\n\n/**\n * One segment of an {@link ExprValue}. The populated field depends on `kind`:\n * - `text` → `value` holds a literal string chunk.\n * - `var` → `ref` names a project variable.\n * - `secret` → `ref` names a vault secret (surfaced via the secret picker).\n * - `expr` → `expr` holds inline JSONLogic evaluated against the run scope.\n */\nexport interface ExprPart {\n kind: ExprPartKind;\n /** Literal chunk, for `kind: \"text\"`. */\n value?: string;\n /** Name of the referenced variable/secret, for `kind: \"var\" | \"secret\"`. */\n ref?: string;\n /** Inline JSONLogic, for `kind: \"expr\"`. */\n expr?: unknown;\n}\n\n/**\n * A multipart value: an ordered list of {@link ExprPart} segments that\n * concatenate to a string at resolve time.\n */\nexport interface ExprValue {\n type: \"expr\";\n parts: ExprPart[];\n}\n\n/**\n * The at-rest form of a secret-typed scalar field: AES-GCM ciphertext + IV\n * (both base64). Decrypted server-side; never decrypted in the client — the UI\n * renders it as `***`.\n */\nexport interface SecretValue {\n type: \"secret\";\n ciphertext: string;\n iv: string;\n}\n\n/** `true` if `v` is an {@link ExprValue} envelope. Safe on `unknown`. */\nexport function isExprValue(v: unknown): v is ExprValue {\n return (\n typeof v === \"object\" &&\n v !== null &&\n !Array.isArray(v) &&\n (v as { type?: unknown }).type === \"expr\" &&\n Array.isArray((v as { parts?: unknown }).parts)\n );\n}\n\n/** `true` if `v` is a {@link SecretValue} envelope. Safe on `unknown`. */\nexport function isSecretValue(v: unknown): v is SecretValue {\n return (\n typeof v === \"object\" &&\n v !== null &&\n !Array.isArray(v) &&\n (v as { type?: unknown }).type === \"secret\" &&\n typeof (v as { ciphertext?: unknown }).ciphertext === \"string\" &&\n typeof (v as { iv?: unknown }).iv === \"string\"\n );\n}\n","import {\n coalesceOperandRefs,\n hasRefusedChainToken,\n parseTemplate,\n serializeTemplate,\n} from \"@w6w/expr\";\nimport {\n type ExprPart,\n type ExprValue,\n type SecretValue,\n isExprValue,\n isSecretValue,\n} from \"../types.ts\";\n\n/**\n * `ui`'s view of the one `{{ }}` inline-expression grammar. The parser and the\n * serializer live in `@w6w/expr` (`core/packages/expr/src/template.ts`) so the\n * engine and the editor read the SAME grammar rather than two copies that must\n * agree forever; this module re-exports them and keeps the editor-only helpers\n * below (`renderResult` masks secrets as `•••` — a preview policy that must not\n * enter the engine's package).\n *\n * Grammar, modes, and the secret fence (D-8) are documented at the definition.\n *\n * `parseTemplate` itself builds every `{{ }}` marker unconditionally — it has\n * no opinion on whether a marker is a W6W expression or a vendor placeholder\n * (Mailjet's `{{var:name}}`, Metabase's `{{tag}}`, …). {@link\n * parseRootAnchoredTemplate} below adds that opinion (root-anchored parsing,\n * CONDUCTOR AMENDMENT 2026-08-14) and is what `valueToParts` and the chip-ify\n * commit paths call — never `parseTemplate` directly on untrusted text.\n */\nexport { parseTemplate, serializeTemplate };\n\n/** Strip editor-only noise, keeping only the wire fields each kind carries. */\nfunction toWirePart(p: ExprPart): ExprPart {\n if (p.kind === \"text\") return { kind: \"text\", value: p.value ?? \"\" };\n if (p.kind === \"expr\") return { kind: \"expr\", expr: p.expr };\n return { kind: p.kind, ref: p.ref ?? \"\" }; // var | secret\n}\n\n/**\n * Serialize parts to the leanest faithful VALUE: prune empty text, collapse a\n * lone text segment to a plain string (backward-compat), else an `ExprValue`.\n * Shared by the inline field and the expression editor modal.\n */\nexport function partsToValue(parts: ExprPart[]): ExprValue | string {\n const cleaned = parts.filter((p) => p.kind !== \"text\" || (p.value ?? \"\") !== \"\");\n if (cleaned.length === 0) return \"\";\n if (cleaned.length === 1 && cleaned[0].kind === \"text\") return cleaned[0].value ?? \"\";\n return { type: \"expr\", parts: cleaned.map(toWirePart) };\n}\n\n/**\n * Mirrors the engine's `RunScope` (`w6w-workflow/packages/engine/src/expr.ts:42`)\n * — the roots a `{{ }}` marker's first path segment must land in for the\n * marker to be treated as a W6W expression rather than literal vendor\n * placeholder text (CONDUCTOR AMENDMENT 2026-08-14 on this project's T1.2.2\n * contract). `ui` must not depend on `@w6w/workflow` — the import-map graph\n * runs `core -> w6w-workflow -> server`, and `ui -> studio` only — so this is\n * a LOCAL mirror, kept in sync BY HAND, deliberately and permanently: T1.5.1\n * already landed (`.ai/projects/done/26-08-13-00-fixes/`) and its `HITL-12`\n * considered — and declined — putting this predicate in `@w6w/expr` instead\n * of duplicating it, precisely because `ui` cannot depend on `@w6w/workflow`.\n * What IS shared is the chain-shape walk (`parseCoalesceChain` /\n * `coalesceOperandRefs` / `hasRefusedChainToken`, all `@w6w/expr`) — both\n * sites call the same predicates over their own local root set, so they\n * cannot silently drift on what a chain IS, only on which roots they accept.\n */\ninterface LocalRunScope {\n vars: unknown;\n steps: unknown;\n trigger: unknown;\n foreach?: unknown;\n inputs?: unknown;\n output?: unknown;\n secrets?: unknown;\n documents?: unknown;\n}\n\n/**\n * The root set, DERIVED from `LocalRunScope`'s keys rather than written out by\n * hand: this object literal is typed `Record<keyof LocalRunScope, true>`, so\n * adding a root to `LocalRunScope` without adding it here is a `tsc` error\n * (missing property) — the set cannot silently drift from the type it mirrors.\n */\nconst RUN_SCOPE_ROOTS: Record<keyof LocalRunScope, true> = {\n vars: true,\n steps: true,\n trigger: true,\n foreach: true,\n inputs: true,\n output: true,\n secrets: true,\n documents: true,\n};\n\n/** Every root name, for tests that pin the derived set without reaching into the type. */\nexport const RUN_SCOPE_ROOT_NAMES: readonly string[] = Object.freeze(Object.keys(RUN_SCOPE_ROOTS));\n\nconst isRunScopeRoot = (segment: string): boolean =>\n Object.prototype.hasOwnProperty.call(RUN_SCOPE_ROOTS, segment);\n\n/** The first `.`-delimited segment of a ref, e.g. `\"steps\"` for `\"steps.a.output\"`. */\nfunction firstSegment(ref: string): string {\n const i = ref.indexOf(\".\");\n return i === -1 ? ref : ref.slice(0, i);\n}\n\n/**\n * Root-anchored parse (CONDUCTOR AMENDMENT 2026-08-14): builds every marker in\n * `s` via `parseTemplate` (never a second `{{ }}` scanner), then requires:\n * - a `var` marker: `hasRefusedChainToken` must be false (a `||`/`??` the\n * chain grammar refused — mixed operators, a `secrets.` operand, … — is\n * never treated as an ordinary path) AND its first path segment must be a\n * `RUN_SCOPE_ROOTS` member;\n * - an `expr` marker recognised by `coalesceOperandRefs` as a `||`/`??`\n * chain: EVERY operand ref's first path segment must be a\n * `RUN_SCOPE_ROOTS` member — a chain is a first-class citizen here, not\n * the opaque escape hatch below;\n * - any other `expr` marker (`=<jsonlogic>`, or a `{{ }}` chip inserted from\n * the rail) or a `secret` marker (`secrets.NAME`): unambiguous by its OWN\n * syntax, no separate check.\n * One unrooted marker/operand reverts the WHOLE string to a single literal\n * `text` part (byte-identical to the input) — all-or-nothing, because the\n * grammar has no escape syntax and a mixed string can't half-chip. This is\n * what keeps `{{ vars.a }}` and `{{ vars.a || \"x\" }}` chips while Mailjet's\n * `{{var:name}}`, Mandrill's Handlebars, and Metabase's `{{tag}}` stay literal\n * text forever (121 spellings surveyed across `packages/apps`, 116 of them\n * vendor placeholders with no root of their own).\n */\nexport function parseRootAnchoredTemplate(s: string): ExprPart[] {\n const parts = parseTemplate(s);\n const allRooted = parts.every((p) => {\n if (p.kind === \"var\") {\n const ref = p.ref ?? \"\";\n return !hasRefusedChainToken(ref) && isRunScopeRoot(firstSegment(ref));\n }\n if (p.kind === \"expr\") {\n const refs = coalesceOperandRefs(p.expr);\n if (refs === null) return true; // not a chain — the `=` escape hatch: always ours.\n return refs.every((ref) => isRunScopeRoot(firstSegment(ref)));\n }\n return true; // `secret` / `text`\n });\n return allRooted ? parts : [{ kind: \"text\", value: s }];\n}\n\n/**\n * Parse an incoming value into editable parts (+ any sealed secret to display).\n * The inverse of {@link partsToValue} for the editable forms; a sealed\n * `SecretValue` has no parts (it's shown as a masked chip, never decrypted).\n *\n * The string arm root-anchor-parses (see {@link parseRootAnchoredTemplate}):\n * a hand-typed, pasted, re-opened, or SDK/MCP-written `\"{{ vars.x }}\"` now\n * chip-ifies identically to a rail insertion, while a vendor placeholder like\n * `\"{{name}}\"` stays literal text forever — it never had a root to lose.\n */\nexport function valueToParts(value: ExprValue | string | SecretValue | undefined): {\n parts: ExprPart[];\n sealed: SecretValue | null;\n} {\n if (isSecretValue(value)) return { parts: [], sealed: value };\n if (isExprValue(value)) return { parts: value.parts.map((p) => ({ ...p })), sealed: null };\n const s = typeof value === \"string\" ? value : \"\";\n return { parts: s ? parseRootAnchoredTemplate(s) : [], sealed: null };\n}\n\n/**\n * Render parts to their preview text for the expression editor's Result pane:\n * `text` parts concatenate literally, a `var` part resolves against `samples`\n * (keyed by full ref) or renders `\"\"` when unresolved — never the raw\n * `{{ ref }}` template token — and a `secret` part always masks as `•••`.\n *\n * A `render` part resolves through the exact SAME flat `samples` lookup as\n * `var` (A4c) — it does NOT additionally substitute `{{ }}` markers inside the\n * resolved value. That substitution is the engine's `resolveRenderPart`\n * (`packages/w6w-workflow/packages/engine/src/expr.ts`, out of scope), which\n * runs against a real run scope; this design-time preview has no run scope to\n * substitute against, so it shows the field's raw template text verbatim, same\n * as `var` would. Without at least the flat-lookup half, the new\n * insert-as-render action's very first click would leave the Result pane\n * blank, which reads as broken.\n *\n * No client-side evaluator for `expr` parts (see the TODO in\n * `ExpressionEditorModal.tsx`) — those fall back to their `{{ }}` template\n * form.\n */\nexport function renderResult(parts: ExprPart[], samples: Record<string, string>): string {\n let out = \"\";\n for (const p of parts) {\n switch (p.kind) {\n case \"text\":\n out += p.value ?? \"\";\n break;\n case \"var\":\n case \"render\": {\n const ref = p.ref ?? \"\";\n out += ref in samples ? samples[ref] : \"\";\n break;\n }\n case \"secret\":\n out += \"•••\";\n break;\n case \"expr\":\n // No client-side evaluator (see TODO above) — show the template form.\n out += serializeTemplate([p]);\n break;\n }\n }\n return out;\n}\n","import { type CoalesceChain, parseCoalesceChain } from \"@w6w/expr\";\nimport type { ExprPart } from \"../types.ts\";\nimport { parseRootAnchoredTemplate, serializeTemplate } from \"./expression-template.ts\";\n\n/**\n * DOM helpers for the inline / modal expression editors: they render a value's\n * parts as editable text with atomic, non-editable CHIPS (tags) inline in the\n * flow, and read the parts back out of the contentEditable DOM. Shared so the\n * inline field and the full editor modal agree on chip markup and parsing.\n */\n\n/**\n * A step-output ref: `steps.<id>.output` optionally followed by `.<field…>`.\n *\n * The id is one dot-free segment (`[^.]+`): a step id may not contain `.`, so a\n * dotted ref such as `steps.my.step.output.email` is NOT a step ref and falls\n * through to {@link varLabel}'s verbatim branch.\n */\nconst STEP_OUTPUT_REF = /^steps\\.([^.]+)\\.output(?:\\.(.+))?$/;\n\n/** `steps.<id>.meta.<key>` for exactly the four metadata keys; the output form is tried first. */\nconst STEP_META_REF = /^steps\\.([^.]+)\\.meta\\.(app|version|action|connectionId)$/;\n\n/**\n * The name a source or chip DISPLAYS. Never the ref it SAVES.\n *\n * A saved ref is always canonical and engine-resolvable — the run scope offers\n * exactly `vars.* · steps.<id>.output.* · steps.<id>.meta.* · trigger.* · secrets.* · documents.* ·\n * inputs.* · foreach.* · output.*` (`core/rfcs/workflow.md` §Expressions, built\n * in `w6w-workflow/packages/engine/src/run.ts`). Those read long in a field, so\n * the label drops the root the chip's sigil and colour already imply:\n *\n * | ref | label |\n * |-----------------------------|----------------|\n * | `vars.from_email` | `from_email` |\n * | `steps.gate_1.output` | `gate_1` |\n * | `steps.gate_1.output.email` | `gate_1.email` |\n * | `steps.gate_1.meta.version` | `gate_1 meta · version` |\n * | anything else | verbatim |\n *\n * **`gate_1.email` is a LABEL ONLY — it is not an expression.** There is no\n * `gate_1` key at the run-scope root, so a chip that STORED the short form would\n * render perfectly in the editor and resolve to empty at run time, silently and\n * untraceably. `makeChip` keeps the two apart deliberately: the chip's stored\n * attribute carries the ref, this function only ever feeds `label.textContent`.\n */\nexport const varLabel = (ref: string): string => {\n if (ref.startsWith(\"vars.\")) return ref.slice(\"vars.\".length);\n const m = STEP_OUTPUT_REF.exec(ref);\n if (m) return m[2] ? `${m[1]}.${m[2]}` : m[1];\n const meta = STEP_META_REF.exec(ref);\n if (meta) return `${meta[1]} meta · ${meta[2]}`;\n return ref;\n};\n\n/** `v`'s `var` ref if `v` is a single-key `{ var: <string> }` object, else `undefined`. Mirrors\n * `@w6w/expr`'s own private `asVarOperand` (`core/packages/expr/src/template.ts`) — not exported,\n * so this repeats the shape check `parseCoalesceChain` already validated, purely to tell a `var`\n * operand from a literal one when rendering; it does not re-derive whether `part.expr` IS a chain. */\nfunction chainOperandVarRef(v: unknown): string | undefined {\n if (v === null || typeof v !== \"object\" || Array.isArray(v)) return undefined;\n const keys = Object.keys(v as Record<string, unknown>);\n if (keys.length !== 1 || keys[0] !== \"var\") return undefined;\n const ref = (v as Record<string, unknown>).var;\n return typeof ref === \"string\" ? ref : undefined;\n}\n\n/**\n * A recognised `||`/`??` chain's chip LABEL (D-2) — mirrors {@link varLabel}'s split between what\n * a chip DISPLAYS and what it SAVES: `data-expr` (in {@link makeChip}) is the stored JSONLogic\n * untouched; this is display-only, built from the chain's own operands rather than truncated raw\n * JSON. A `{ var: ref }` operand renders through `varLabel` (the short form); any other operand (a\n * JSON primitive literal) renders through `JSON.stringify`. Do NOT call `varLabel` on the whole\n * chain — only on each `var` operand, same as a standalone `var` chip would.\n */\nfunction chainLabel(chain: CoalesceChain): string {\n const token = chain.op === \"or\" ? \"||\" : \"??\";\n const text = chain.operands\n .map((operand) => {\n const ref = chainOperandVarRef(operand);\n return ref !== undefined ? varLabel(ref) : JSON.stringify(operand);\n })\n .join(` ${token} `);\n return text.length > 40 ? `${text.slice(0, 40)}…` : text;\n}\n\n/**\n * A key that cannot survive the trip from picker to engine, by CHARACTER.\n *\n * - `.` — JSONLogic's `var` splits its path on \".\" with **no escape and no\n * bracket form** (`core/packages/expr/src/jsonlogic.ts` `getVar`:\n * `String(path).split(\".\")`), so a key `a.b` becomes the lookup\n * `output → a → b` and yields `null`. There is no spelling that reaches it.\n * - `{` / `}` — they collide with the `{{ … }}` template grammar\n * (`expression-template.ts`), so the ref does not survive the text round trip.\n *\n * Interior whitespace is deliberately NOT here: `output[\"first name\"]` is a\n * plain property lookup that `getVar` performs correctly, and\n * `{{ steps.g.output.first name }}` round-trips (only the OUTER pad is trimmed).\n * Leading/trailing whitespace IS rejected, below — that pad is what gets eaten.\n */\nconst UNREACHABLE_KEY_CHARS = /[.{}]/;\n\n/**\n * Whether a declared output key can become a ref the engine actually resolves.\n *\n * A key that fails this would still produce a chip that renders perfectly and\n * evaluates to **empty at run time, silently** — the same failure mode the\n * label/ref split exists to avoid — so the picker must not offer it at all. The\n * step's WHOLE output (`steps.<id>.output`) is still offered, which remains the\n * author's route to such a field via an explicit `=` JSONLogic expression.\n */\nexport function isRefSafeKey(key: string): boolean {\n if (key === \"\" || key !== key.trim()) return false;\n return !UNREACHABLE_KEY_CHARS.test(key);\n}\n\n/**\n * Whether a declared output PATH (`start.utc` — an app action's `OutputField`\n * key, where `.` means nesting, not a literal character) can become a ref the\n * engine resolves: the same `getVar` split that makes a literal `a.b` key\n * unreachable is what walks a path, so each SEGMENT must pass\n * {@link isRefSafeKey} on its own.\n */\nexport function isRefSafePath(path: string): boolean {\n return path.split(\".\").every(isRefSafeKey);\n}\n\n/**\n * Build the non-editable inline chip (tag) DOM node for a part.\n *\n * `renderToggle` is opt-in and defaults OFF: `makeChip` is shared through\n * {@link paintParts} by every editing surface, including the inline\n * `ExpressionInput` (`ExpressionInput.tsx`), which has no handler for the\n * flip control at all. A painter must not decide who gets an affordance —\n * only `ExpressionEditorModal` (the one surface with a click delegate for\n * `[data-render-toggle]`) passes `true`. Round 2 fix for F-2: before this,\n * every `var`/`render` chip everywhere painted the toggle unconditionally,\n * so it leaked into every inline expression field in studio as a dead,\n * screen-reader-announced control.\n */\nexport function makeChip(\n doc: Document,\n part: ExprPart,\n { renderToggle }: { renderToggle?: boolean } = {},\n): HTMLElement {\n const span = doc.createElement(\"span\");\n span.contentEditable = \"false\";\n span.className = `w6w-expr-chip w6w-expr-chip-${part.kind}`;\n span.setAttribute(\"data-kind\", part.kind);\n\n const sigil = doc.createElement(\"span\");\n sigil.className = \"w6w-expr-chip-sigil\";\n const label = doc.createElement(\"span\");\n label.className = \"w6w-expr-chip-label\";\n\n if (part.kind === \"var\") {\n span.setAttribute(\"data-ref\", part.ref ?? \"\");\n // A small, quiet marker (accent colour carries the \"variable\" meaning) —\n // never the literal `{x}`, which read as noise crowding the field.\n sigil.textContent = \"◆\";\n label.textContent = varLabel(part.ref ?? \"\");\n span.title = `Variable: ${part.ref ?? \"\"}`;\n } else if (part.kind === \"render\") {\n span.setAttribute(\"data-ref\", part.ref ?? \"\");\n // A visually distinct sigil from a plain `var` chip: this ref's RESOLVED\n // value is itself parsed as a `{{ }}` template and rendered (the amendment\n // in `core/rfcs/workflow.md`). Same label rule — `varLabel` doesn't\n // depend on kind.\n sigil.textContent = \"▤\";\n label.textContent = varLabel(part.ref ?? \"\");\n span.title = `Render as template: ${part.ref ?? \"\"}`;\n } else if (part.kind === \"secret\") {\n span.setAttribute(\"data-ref\", part.ref ?? \"\");\n sigil.textContent = \"🔒\";\n label.textContent = part.ref ?? \"\"; // the NAME — never the value\n span.title = `Secret: ${part.ref ?? \"\"}`;\n } else {\n const raw = typeof part.expr === \"string\" ? part.expr : JSON.stringify(part.expr ?? \"\");\n span.setAttribute(\"data-expr\", raw); // display-only label below; the stored JSONLogic is unchanged.\n sigil.textContent = \"ƒ\";\n const chain = parseCoalesceChain(part.expr);\n if (chain) {\n label.textContent = chainLabel(chain);\n span.title = `Expression: ${serializeTemplate([part])}`;\n } else {\n label.textContent = raw.length > 24 ? `${raw.slice(0, 24)}…` : raw || \"expr\";\n span.title = `Expression: ${raw}`;\n }\n }\n\n span.append(sigil, label);\n\n if ((part.kind === \"var\" || part.kind === \"render\") && renderToggle) {\n // The render affordance: flip THIS chip between \"insert this ref\" (var)\n // and \"insert this ref, then render its resolved value as a `{{ }}`\n // template\" (render) — never a second, free-text ref-construction path.\n // The modal's click delegate handles the flip by rebuilding the chip via\n // `makeChip` from the SAME `data-ref`, never a re-derived string.\n const toggle = doc.createElement(\"span\");\n toggle.className = \"w6w-expr-chip-toggle\";\n toggle.setAttribute(\"data-render-toggle\", \"1\");\n toggle.setAttribute(\"role\", \"button\");\n const toggleLabel =\n part.kind === \"render\" ? \"Stop rendering as a template\" : \"Render this as a template\";\n toggle.setAttribute(\"aria-label\", toggleLabel);\n toggle.title = toggleLabel;\n toggle.textContent = \"⇄\";\n span.append(toggle);\n }\n\n const x = doc.createElement(\"span\");\n x.className = \"w6w-expr-chip-x\";\n x.setAttribute(\"data-x\", \"1\");\n x.setAttribute(\"role\", \"button\");\n x.setAttribute(\"aria-label\", \"Remove\");\n x.textContent = \"×\";\n span.append(x);\n return span;\n}\n\n/**\n * Elements `contentEditable` builds one-per-line. A block child means \"the\n * content before me ended a line\", so it contributes an implicit newline.\n */\nconst BLOCK_TAGS = new Set([\"div\", \"p\"]);\n\n/**\n * Decode a chip element back into the part it represents — the one and only\n * decode in the file. Hoisted out of {@link readParts}'s inline `var` /\n * `secret` / `render` (`data-ref`) and `expr` (`data-expr` JSON) arms so\n * {@link chipToText} can reuse the exact same logic rather than re-deriving\n * it; `readParts` itself now calls this instead of carrying its own copy.\n * `null` for any element that isn't a chip (`data-kind` absent or not one of\n * the four kinds) — the caller falls through to its other element handling.\n */\nexport function chipToPart(el: HTMLElement): ExprPart | null {\n const kind = el.getAttribute(\"data-kind\");\n if (kind === \"var\" || kind === \"secret\" || kind === \"render\") {\n return { kind, ref: el.getAttribute(\"data-ref\") ?? \"\" };\n }\n if (kind === \"expr\") {\n const raw = el.getAttribute(\"data-expr\") ?? \"\";\n let expr: unknown = raw;\n try {\n expr = JSON.parse(raw);\n } catch {\n expr = raw;\n }\n return { kind: \"expr\", expr };\n }\n return null;\n}\n\n/**\n * Reconstruct parts from an editor's DOM (the source of truth while editing).\n *\n * The walk is **recursive**: a native Enter wraps the caret's line in a `<div>`\n * (or drops a `<br>`), and anything nested inside it — chips included — must\n * survive. Reading `textContent` at that point would flatten a chip to its\n * label and silently destroy the reference it carries, so every unrecognised\n * element is descended into instead. `<br>` and block children map to a literal\n * `\"\\n\"`; `pushText` coalesces those into the surrounding text part.\n *\n * One `<br>` is deliberately NOT a newline: a FILLER one, closing its block —\n * see `walk` and {@link ensureFillerBreak}.\n */\nexport function readParts(root: HTMLElement): ExprPart[] {\n const parts: ExprPart[] = [];\n const pushText = (t: string) => {\n if (!t) return;\n const last = parts[parts.length - 1];\n if (last && last.kind === \"text\") last.value = (last.value ?? \"\") + t;\n else parts.push({ kind: \"text\", value: t });\n };\n\n /** `lastInBlock`: this node is the final child of the root, a `div` or a `p`. */\n const walk = (node: Node, lastInBlock: boolean) => {\n if (node.nodeType === Node.TEXT_NODE) {\n pushText(node.textContent ?? \"\");\n return;\n }\n if (node.nodeType !== Node.ELEMENT_NODE) return;\n const el = node as HTMLElement;\n\n const part = chipToPart(el);\n if (part) {\n parts.push(part);\n return;\n }\n\n // Browsers report `BR` / `DIV` uppercase for HTML documents.\n const tag = (el.tagName ?? \"\").toLowerCase();\n if (tag === \"br\") {\n // A <br> CLOSING its block is a FILLER, not a line the author made: it\n // exists so an otherwise-empty last line has a box for the caret to land\n // in. Three things produce one, all measured in Chromium\n // (`artifacts/T3.1.2-browser-check.sh`):\n // 1. {@link ensureFillerBreak}, after we insert our own \"\\n\";\n // 2. a PASTED blank line — `<div><br></div>`, where the block already\n // carries the break and the <br> only fills it. Counting both\n // inflates one blank line into two;\n // 3. the browser itself, after a `contentEditable=\"false\"` chip.\n // A <br> the author really made has content (or another line) after it\n // inside its block, so it is never the block's last child.\n if (!lastInBlock) pushText(\"\\n\");\n return;\n }\n // A *leading* block is the first line, not a break after something.\n const isBlock = BLOCK_TAGS.has(tag);\n if (isBlock && parts.length > 0) pushText(\"\\n\");\n walkChildren(el, isBlock);\n };\n\n const walkChildren = (parent: Node, isBlockParent: boolean) => {\n const children = Array.from(parent.childNodes);\n children.forEach((child, i) => walk(child, isBlockParent && i === children.length - 1));\n };\n\n walkChildren(root, true);\n return parts;\n}\n\n/**\n * Is this the filler `<br>` closing a block — the caret's landing pad, never\n * part of the value? Callers only ever ask it about a block's LAST child, which\n * is what makes \"a `<br>` here\" and \"a filler\" the same question (`readParts`\n * skips exactly this node).\n *\n * The test is deliberately narrower than \"is an element\": a block ending in a\n * CHIP is also ending in an element, and a chip is `contentEditable=\"false\"`, so\n * it gives the caret nowhere to land and still needs a filler after it.\n */\nconst isFillerBreak = (node: Node | null): boolean =>\n !!node && ((node as HTMLElement).tagName ?? \"\").toLowerCase() === \"br\";\n\n/**\n * Append the filler `<br>` that lets a `\"\\n\"` ENDING this block render.\n *\n * Idempotent — a block already closed by a `<br>` is left alone. That guard is\n * load-bearing, not tidiness: a second filler would no longer be the block's\n * last child, so `readParts` would read it as a real newline and the value would\n * grow a blank line per keystroke-that-triggers-a-fill.\n */\nfunction fillBlock(block: HTMLElement): void {\n if (isFillerBreak(block.lastChild)) return;\n block.appendChild(block.ownerDocument.createElement(\"br\"));\n}\n\n/**\n * The block the caret currently sits in, within `editor` — the editor itself\n * when the caret is at its top level, or is not inside it at all.\n *\n * The filler has to go in the SAME block as the newline it exists to render.\n * After a paste, the caret's line is an inner `<div>` (`one<div>three</div>`),\n * so filling the root instead would leave the `\"\\n\"` trailing inside the div\n * with nothing to render it — the very failure the filler exists to prevent.\n */\nfunction caretBlock(editor: HTMLElement): HTMLElement {\n const sel = editor.ownerDocument.getSelection();\n const range = sel?.rangeCount ? sel.getRangeAt(0) : null;\n // `editor.contains(...)`: a selection somewhere ELSE in the document must not\n // make us walk up into a foreign `div`/`p` and append a filler there. Nothing\n // reaches it today — `ensureFillerBreak`'s only callers are the two keydown\n // handlers, where the caret is inside the editor by construction — so no probe\n // can distinguish it from its absence (T3.1.2 eval, R2-5). It is kept because\n // the barrier is the CALL SITES, and the first non-keydown caller arms it.\n if (!range || !editor.contains(range.endContainer)) return editor;\n let node: Node | null = range.endContainer;\n while (node && node !== editor) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as HTMLElement;\n if (BLOCK_TAGS.has((el.tagName ?? \"\").toLowerCase())) return el;\n }\n node = node.parentNode;\n }\n return editor;\n}\n\n/**\n * Give a line break at the very END of the caret's line somewhere to render.\n *\n * A `\"\\n\"` that is the last thing in a `white-space: pre-wrap` block paints\n * nothing, and the caret cannot land past it — the author presses Enter, sees no\n * break, and their next keystroke lands on the *previous* line (observed in\n * Chromium; see `artifacts/T3.1.2-browser-check.sh`). Browsers solve this for\n * their own line breaks with a FILLER `<br>` as the block's last child, so ours\n * uses the same device. `readParts` skips exactly that node — the two are one\n * fact, kept in one file.\n */\nexport function ensureFillerBreak(editor: HTMLElement): void {\n fillBlock(caretBlock(editor));\n}\n\n/**\n * Does this editing host render more than one line?\n *\n * Read from the host's OWN `aria-multiline`, which both editors set from the\n * same `multiline` prop that decides whether Enter inserts anything\n * (`ExpressionInput.tsx`, `ExpressionEditorModal.tsx`) — so the attribute is not\n * a proxy for the flag, it *is* the flag, already on the node this file is\n * handed. Threading a second copy of it down as an argument would make the two\n * editors' call sites the only source of truth and leave the DOM free to\n * disagree with it.\n *\n * Absent ⇒ multiline: a host that never declared itself single-line keeps the\n * pre-existing behaviour, and the two real editors always declare.\n */\nconst isMultilineHost = (el: HTMLElement): boolean => el.getAttribute(\"aria-multiline\") !== \"false\";\n\n/**\n * Paint an editor's DOM from parts (text nodes + chips).\n *\n * `opts` passes straight through to {@link makeChip} — `renderToggle`\n * defaults off, so a caller that never opts in (`ExpressionInput.tsx`) paints\n * no toggle at all, and only `ExpressionEditorModal` turns it on.\n */\nexport function paintParts(\n el: HTMLElement,\n parts: ExprPart[],\n opts?: { renderToggle?: boolean },\n): void {\n const doc = el.ownerDocument;\n el.textContent = \"\";\n for (const p of parts) {\n if (p.kind === \"text\") {\n if (p.value) el.appendChild(doc.createTextNode(p.value));\n } else {\n el.appendChild(makeChip(doc, p, opts));\n }\n }\n // A painted value ENDING in a newline needs the filler just as much as a\n // freshly typed one does — this is the same block, rebuilt from parts. Without\n // it the break survives the round trip in the VALUE but not on SCREEN, and the\n // author's next keystroke lands before it: \"a\\n\" + typing \"b\" saved \"ab\\n\".\n //\n // …but only where a break can be rendered at all. A SINGLE-LINE field can\n // still hold a value ending in \"\\n\" (paste it in — neither editor has an\n // `onPaste` handler), and there the filler gives it a second line box: the\n // field silently doubles in height for a break the author can never reach,\n // since Enter is swallowed on that path. The value is identical either way —\n // `readParts` skips the filler — so this is purely about what is painted.\n const last = parts[parts.length - 1];\n if (last?.kind === \"text\" && last.value?.endsWith(\"\\n\") && isMultilineHost(el)) fillBlock(el);\n}\n\n/**\n * Put the caret at the end of the editor.\n *\n * Deliberately NOT special-cased for a trailing filler `<br>`: a caret placed\n * past the filler is a position Chromium normalises straight back into the\n * content, so the next character still lands before the filler. That was\n * measured, not assumed — a version of this function that skipped the filler\n * explicitly could not be distinguished from this one by any probe in\n * `T3.1.2-browser-check.sh`, including §K, which exists to try. What DOES have\n * to respect the filler is the node insertion itself (see `insertNodeAtCaret`).\n */\nexport function placeCaretAtEnd(el: HTMLElement): void {\n const sel = el.ownerDocument.getSelection();\n if (!sel) return;\n const range = el.ownerDocument.createRange();\n range.selectNodeContents(el);\n range.collapse(false);\n sel.removeAllRanges();\n sel.addRange(range);\n}\n\n/** Insert a node at the caret (or at the end if the caret isn't in the editor). */\nexport function insertNodeAtCaret(editor: HTMLElement, node: Node): void {\n const doc = editor.ownerDocument;\n const sel = doc.getSelection();\n const range = sel?.rangeCount ? sel.getRangeAt(0) : null;\n if (range && editor.contains(range.commonAncestorContainer)) {\n range.deleteContents();\n range.insertNode(node);\n const after = doc.createRange();\n after.setStartAfter(node);\n after.collapse(true);\n sel?.removeAllRanges();\n sel?.addRange(after);\n } else {\n // No caret in the editor (e.g. a source clicked in the modal's left pane\n // before the editor was ever focused). Insert at the end of the CONTENT —\n // which is before a trailing filler, not after it: appending past the filler\n // would stop it being the block's last child and `readParts` would then read\n // it as a real newline (\"a\\n\" + a chip saved \"a\\n\\n{{ … }}\").\n if (isFillerBreak(editor.lastChild)) editor.insertBefore(node, editor.lastChild);\n else editor.appendChild(node);\n placeCaretAtEnd(editor);\n }\n editor.focus();\n}\n\n/**\n * D-3 (binding): promote a just-closed `{{ … }}` marker to a chip at the\n * keystroke that closes it — the caret-safe surgery an `onInput` handler can\n * call directly, with NO `paintGen` bump (see the warning at the top of\n * `ExpressionEditorModal.tsx` and `G-typing` in `expr-template-guards.test.cjs`:\n * a repaint here resets the caret and reorders every subsequent keystroke).\n *\n * Returns `false`, doing nothing, unless ALL of:\n * - the selection is collapsed inside a text node `editor` contains;\n * - the two characters immediately before the caret are `}}`;\n * - there is a `{{` earlier in THAT SAME text node (a marker interrupted by\n * a chip — i.e. split across text nodes — is not a marker, deliberately);\n * - `parseRootAnchoredTemplate` of the text from that `{{` to the caret\n * parses to exactly ONE part that is not `kind: \"text\"` (an unrooted\n * marker, or one that isn't a single complete part, stays literal).\n *\n * On success: deletes exactly that span and inserts the chip in its place —\n * the same `Range` surgery `insertNodeAtCaret` performs, mirrored rather than\n * reused because the span here is a slice of an EXISTING text node, not the\n * live selection — then collapses the caret just after the chip.\n */\nexport function promoteCompletedMarkerAtCaret(\n editor: HTMLElement,\n opts: { renderToggle?: boolean } = {},\n): boolean {\n const doc = editor.ownerDocument;\n const sel = doc.getSelection();\n if (!sel || sel.rangeCount === 0 || !sel.isCollapsed) return false;\n const range = sel.getRangeAt(0);\n const node = range.startContainer;\n if (node.nodeType !== Node.TEXT_NODE || !editor.contains(node)) return false;\n\n const offset = range.startOffset;\n const text = node.textContent ?? \"\";\n if (offset < 2 || text.slice(offset - 2, offset) !== \"}}\") return false;\n const openIdx = text.lastIndexOf(\"{{\", offset - 2);\n if (openIdx === -1) return false;\n\n const marker = text.slice(openIdx, offset);\n const parsed = parseRootAnchoredTemplate(marker);\n if (parsed.length !== 1 || parsed[0].kind === \"text\") return false;\n\n const markerRange = doc.createRange();\n markerRange.setStart(node, openIdx);\n markerRange.setEnd(node, offset);\n markerRange.deleteContents();\n const chip = makeChip(doc, parsed[0], opts);\n markerRange.insertNode(chip);\n\n const after = doc.createRange();\n after.setStartAfter(chip);\n after.collapse(true);\n sel.removeAllRanges();\n sel.addRange(after);\n return true;\n}\n\n/**\n * D-3: the reverse of {@link promoteCompletedMarkerAtCaret} — a chip back to\n * its editable `{{ … }}` text, in place. `chipToPart` is the SAME decode\n * `readParts` uses, so what comes back is exactly what the chip carries, and\n * `serializeTemplate` is the SAME serializer the round trip already goes\n * through everywhere else in this file. `null` for an element that isn't a\n * chip. The caller collapses the caret at the returned node's end — this\n * function only performs the DOM swap, mirroring `chip.replaceWith` being the\n * whole of the \"remove\" arm (`onClick`'s `[data-x]` handler) in both editors.\n */\nexport function chipToText(chip: HTMLElement): Text | null {\n const part = chipToPart(chip);\n if (!part) return null;\n const text = chip.ownerDocument.createTextNode(serializeTemplate([part]));\n chip.replaceWith(text);\n return text;\n}\n","import { Fragment, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport type { ExprPart, ExprValue, SecretValue } from \"../types.ts\";\nimport { Copyable } from \"./Copyable.tsx\";\nimport type { ExpressionOptions } from \"./ExpressionOptions.tsx\";\nimport { IconButton } from \"./IconButton.tsx\";\nimport { Modal } from \"./Modal.tsx\";\nimport {\n chipToText,\n ensureFillerBreak,\n insertNodeAtCaret,\n isRefSafeKey,\n isRefSafePath,\n makeChip,\n paintParts,\n placeCaretAtEnd,\n promoteCompletedMarkerAtCaret,\n readParts,\n varLabel,\n} from \"./expression-dom.ts\";\nimport {\n parseRootAnchoredTemplate,\n partsToValue,\n renderResult,\n serializeTemplate,\n valueToParts,\n} from \"./expression-template.ts\";\n\n/**\n * A near-full-screen editor for an expression value. Left: the data sources in\n * scope (variables, secrets, and the workflow state leading to this step) — one\n * click inserts a colored TAG (chip) at the caret. Right: the expression editor\n * (top, where tags read distinctly from plain text) over the `{{ }}` template\n * form that gets saved plus a live Result pane (bottom) that previews the\n * expression against user-supplied sample values for the injected scope.\n *\n * The value it saves is the same `ExprValue | string` the inline field and the\n * engine already use (see `expression-template.ts` / `expression-dom.ts`).\n */\nexport interface ExpressionEditorModalProps {\n value: ExprValue | string | SecretValue | undefined;\n masked?: boolean;\n /**\n * The field being edited holds multi-line text (a `text`-typed param, or one\n * flagged `config.multiline`). Enter then inserts a literal `\"\\n\"` at the\n * caret instead of being swallowed, and `aria-multiline` follows. Omitted ⇒\n * single-line, as every existing consumer expects.\n */\n multiline?: boolean;\n options: ExpressionOptions;\n /** Field name shown in the modal title. */\n fieldLabel?: string;\n /** Expression mode's commit. Not used in `mode=\"json-binding\"` (see `onBind`). */\n onSave?: (next: ExprValue | string) => void;\n onClose: () => void;\n /**\n * `\"json-binding\"`: pick ONE upstream step output for a whole `json`/`group`\n * param. The rail shows only the Workflow state slot, each step gets an\n * \"Entire output\" leaf, and a click calls `onBind({ $: ref })` (the plain\n * one-key object, never an `ExprValue`) and closes. No chips editor, no\n * Save, no template/Result panes. Absent ⇒ expression mode, unchanged.\n */\n mode?: \"json-binding\";\n onBind?: (next: { $: string }) => void;\n}\n\nexport function ExpressionEditorModal({\n value,\n masked,\n multiline,\n options,\n fieldLabel,\n onSave,\n onClose,\n mode,\n onBind,\n}: ExpressionEditorModalProps) {\n const jsonBinding = mode === \"json-binding\";\n const [parts, setParts] = useState<ExprPart[]>(() => valueToParts(value).parts);\n // Bumped ONLY for programmatic repaints — mount, and committing template\n // text back into chips. Typing/insert mutate the DOM directly and sync out,\n // so the caret is never clobbered; NEVER bump this from `onInput`,\n // `insertPart`, the Enter handler, or a chip flip.\n const [paintGen, setPaintGen] = useState(0);\n const editorRef = useRef<HTMLDivElement>(null);\n // Set right before a programmatic paint that should also move focus/caret\n // into the chips editor — never on the mount paint.\n const focusChipsAfterPaint = useRef(false);\n // User-supplied sample values (keyed by var ref) that the Result pane previews\n // the expression against. Design-time only — never sent to the engine.\n const [samples, setSamples] = useState<Record<string, string>>({});\n // Which store's \"+ Add\" nested dialog is open, or none. Gated at render by\n // whether the host supplied the matching callback (`options.createVar` /\n // `.createSecret`) — see the rail below.\n const [adding, setAdding] = useState<\"var\" | \"secret\" | null>(null);\n // Rail sources with surviving child rows (a multi-field document, a step\n // with declared outputs) collapse by default — ONE mechanism, composite\n // keys (\"doc:<key>\" / \"step:<id>\"), serving both loops below.\n const [expanded, setExpanded] = useState<Set<string>>(() => new Set());\n const toggleExpanded = (key: string) => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (next.has(key)) next.delete(key);\n else next.add(key);\n return next;\n });\n };\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: paint on `paintGen`, not on every `parts` change; edits otherwise flow through the DOM.\n useLayoutEffect(() => {\n const el = editorRef.current;\n if (!el) return;\n // renderToggle: true — the modal is the one surface with a click delegate\n // for `[data-render-toggle]` (below); `ExpressionInput.tsx` never opts in.\n paintParts(el, parts, { renderToggle: true });\n if (focusChipsAfterPaint.current) {\n focusChipsAfterPaint.current = false;\n placeCaretAtEnd(el);\n el.focus();\n }\n }, [paintGen]);\n\n const sync = () => {\n const el = editorRef.current;\n if (el) setParts(readParts(el));\n };\n\n const insertPart = (part: ExprPart) => {\n const el = editorRef.current;\n if (!el) return;\n insertNodeAtCaret(el, makeChip(el.ownerDocument, part, { renderToggle: true }));\n setParts(readParts(el));\n };\n\n // A render part can be authored two ways: flipping an EXISTING var chip\n // (below), or inserting one directly via a document field's \"insert as\n // render\" action (the Documents group's field sub-source loop, below) — so\n // this is derived from `parts` on every render, not computed once at mount:\n // either path must disable the control below immediately, and flipping the\n // toggled chip back must re-enable it.\n const hasRenderPart = parts.some((p) => p.kind === \"render\");\n\n // Adopt a text form as the parts and repaint the chips editor — the\n // chip-ify commit mechanism: root-anchor-parse `text` (never the naive\n // `parseTemplate` — a hand-typed vendor placeholder like `{{name}}` must\n // stay literal, see `expression-template.ts`'s `parseRootAnchoredTemplate`),\n // set it as the new `parts`, and bump `paintGen` so the `useLayoutEffect`\n // above repaints. `restoreFocus` is `false` from `onBlur` (the editor has\n // already lost focus; forcing it back would yank focus out of Save/Cancel —\n // caret position is moot there) and `true` for a caller that wants the\n // caret restored into the chips editor after the repaint.\n const adoptText = (text: string, { restoreFocus }: { restoreFocus: boolean }) => {\n setParts(parseRootAnchoredTemplate(text));\n if (restoreFocus) focusChipsAfterPaint.current = true;\n setPaintGen((g) => g + 1);\n };\n\n const save = () => {\n const el = editorRef.current;\n onSave?.(partsToValue(el ? readParts(el) : parts));\n onClose();\n };\n\n // Save `part` alone as the field's value (what Save yields for an editor\n // holding only that chip) and close.\n // In json-binding mode this is the ONE save path: a leaf (Entire output, a\n // field, or any later Metadata leaf) yields `{ $: ref }` and closes.\n const saveOnly = (part: ExprPart) => {\n if (jsonBinding) onBind?.({ $: part.ref ?? \"\" });\n else onSave?.(partsToValue([part]));\n onClose();\n };\n\n // Close the nested \"+ Add\" dialog and return focus + caret to the chips\n // editor. `Modal.tsx` never calls `el.close()` on unmount, so React would\n // otherwise leave a still-`open` `<dialog>` for the browser to tear down and\n // restore focus to `<body>` — the author loses their insertion point right\n // when they come back to insert the value they just created. Reuse the same\n // programmatic-repaint mechanism `exitTemplate` used for the same problem.\n const closeAdding = () => {\n setAdding(null);\n focusChipsAfterPaint.current = true;\n setPaintGen((g) => g + 1);\n };\n\n const vars = options.vars ?? [];\n const secrets = options.secrets ?? [];\n const inputs = options.inputs ?? [];\n const documents = options.documents ?? [];\n const steps = options.steps ?? [];\n const hasState = steps.length > 0 || !!options.hasTrigger;\n const template = serializeTemplate(parts);\n\n // The sample map the Result pane previews against: host-seeded defaults\n // (real project vars/documents, keyed by full ref) overlaid by anything the\n // author typed into the Sample values box, which takes precedence. Non-string\n // seeds are stringified for the text preview.\n const effectiveSamples = useMemo(() => {\n const seeded: Record<string, string> = {};\n for (const [ref, v] of Object.entries(options.sampleValues ?? {})) {\n seeded[ref] = typeof v === \"string\" ? v : JSON.stringify(v);\n }\n return { ...seeded, ...samples };\n }, [options.sampleValues, samples]);\n\n // The distinct var/render refs the current expression reads (first-seen\n // order) — the in-scope roots the author can supply sample values for. A\n // `render` part reads through the same sample lookup as `var` (A4c), so its\n // ref belongs here too — otherwise the Sample-values box never offers a row\n // for it and the Result pane's first click on the new insert-render action\n // reads as broken (blank output).\n const usedRefs = useMemo(() => {\n const seen = new Set<string>();\n const refs: string[] = [];\n for (const p of parts) {\n if ((p.kind === \"var\" || p.kind === \"render\") && p.ref && !seen.has(p.ref)) {\n seen.add(p.ref);\n refs.push(p.ref);\n }\n }\n return refs;\n }, [parts]);\n\n // Best-effort client-side preview of the expression against the sample values.\n // Follow-up: `@w6w/expr` is now a dependency of this package, but the\n // preview does not call it yet, so inline JSONLogic (`expr` parts) isn't\n // evaluated client-side — we render the resolved `{{ }}` template instead:\n // substitute sample values for var refs, mask secrets, and keep the\n // `{{ … }}` form for anything we can't resolve. Never throws on an\n // un-evaluable expression.\n const result = useMemo(() => {\n try {\n return renderResult(parts, effectiveSamples);\n } catch {\n // Last-resort fallback — the pane must never throw.\n return template;\n }\n }, [parts, effectiveSamples, template]);\n\n // `sigil: null` drops the glyph — a step row with fields renders its own\n // disclosure caret in that spot instead (see the Workflow state loop).\n //\n // A LEAF row's click saves that single ref as if it were the only thing in\n // the editor and Save were pressed; a COMPOSITE row (it has a disclosure for\n // child rows) keeps the old click = insert into the editor. Every row also\n // carries a copy icon at its right that keeps the old insert-and-stay-open.\n const source = (\n label: string,\n part: ExprPart,\n cls: string,\n sigil: string | null,\n composite = false,\n ariaLabel?: string,\n ) => (\n <div\n key={`${part.kind}:${part.ref ?? label}`}\n className=\"w6w-exprmodal-item\"\n style={{ display: \"flex\", alignItems: \"center\", gap: 4, minWidth: 0 }}\n >\n <button\n type=\"button\"\n className={`w6w-exprmodal-source ${cls}`}\n style={{ flex: 1, minWidth: 0 }}\n title={composite ? `Insert ${label}` : `Use ${label}`}\n aria-label={ariaLabel}\n onClick={() => (composite ? insertPart(part) : saveOnly(part))}\n >\n {sigil !== null && <span className=\"w6w-expr-chip-sigil\">{sigil}</span>}\n <span className=\"w6w-exprmodal-source-label\">{label}</span>\n </button>\n {!jsonBinding && (\n <IconButton\n icon=\"copy\"\n iconSize={14}\n label=\"Copy to expression editor\"\n data-testid=\"expr-copy-to-editor\"\n onClick={() => insertPart(part)}\n />\n )}\n </div>\n );\n\n return (\n <Modal\n title={jsonBinding ? \"Bind to a step output\" : \"Edit expression\"}\n subtitle={fieldLabel ? <code>{fieldLabel}</code> : undefined}\n onClose={onClose}\n size=\"full\"\n headerRight={\n jsonBinding ? (\n <div className=\"w6w-exprmodal-actions\">\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={onClose}>\n Cancel\n </button>\n </div>\n ) : (\n <div className=\"w6w-exprmodal-actions\">\n {/* Take the field back OUT of expression mode. It saves the `{{ }}`\n TEXT form, so the content survives exactly as the old expr→text\n toggle made it — a lone text part collapses to a plain string in\n `partsToValue`, so the field renders its plain widget again.\n Hidden when `masked`: a sealed secret has no text form. */}\n {!masked && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n disabled={hasRenderPart}\n title={\n hasRenderPart\n ? \"Unavailable — a render part has no plain-text form. Flip it back to a variable first.\"\n : \"Close the expression and keep the text as a literal value\"\n }\n onClick={() => {\n onSave?.(serializeTemplate(parts));\n onClose();\n }}\n >\n Use a plain value\n </button>\n )}\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={onClose}>\n Cancel\n </button>\n <button type=\"button\" className=\"w6w-btn\" onClick={save}>\n Save\n </button>\n </div>\n )\n }\n >\n <div\n className=\"w6w-exprmodal\"\n style={jsonBinding ? { gridTemplateColumns: \"1fr\" } : undefined}\n >\n {/* Left: the data sources in scope. */}\n <aside className=\"w6w-exprmodal-sources\">\n {/* First slot — context-specific, mutually exclusive in the real\n wiring (a Function supplies `inputs` and never `steps`; the flow\n editor supplies `steps`/`hasTrigger` and never `inputs`). Render\n Workflow state first should a host ever supply both. */}\n {jsonBinding && !hasState && (\n <span className=\"w6w-expr-menu-empty\">No upstream steps</span>\n )}\n {hasState && (\n <div className=\"w6w-exprmodal-group\">\n <span className=\"w6w-exprmodal-group-label\">Workflow state</span>\n {options.hasTrigger &&\n source(\n \"trigger.event\",\n { kind: \"var\", ref: \"trigger.event\" },\n \"w6w-expr-chip-var\",\n \"⚡\",\n )}\n {steps.map((st) => {\n // The Metadata disclosure (external app steps only, R-7). It sits\n // directly under the \"N fields\" toggle (same left edge, same\n // glyph) when the step has fields, else on its own row.\n const metaToggle = (id: string) => {\n const open = expanded.has(`meta:${id}`);\n return (\n <button\n type=\"button\"\n className=\"w6w-exprmodal-toggle-btn\"\n data-testid=\"expr-meta-toggle\"\n aria-expanded={open}\n title={open ? \"Hide metadata\" : \"Show metadata\"}\n onClick={() => toggleExpanded(`meta:${id}`)}\n >\n Metadata {open ? \"⌄\" : \"›\"}\n </button>\n );\n };\n // Only keys that can become a ref the ENGINE resolves are\n // offered. The guard lives here, at the one place a ref is\n // built, so it holds for any host that supplies `steps` —\n // not only for the flow editor's own projection.\n const fields = (st.outputs ?? []).filter((o) =>\n o.path ? isRefSafePath(o.key) : isRefSafeKey(o.key),\n );\n const stepKey = `step:${st.id}`;\n const isOpen = expanded.has(stepKey);\n // The whole output — still a real, useful ref on its own, and\n // the author's route to a key the guard dropped. Its class,\n // label, sigil and inserted ref are unchanged from before.\n //\n // With fields, the `▸` is pulled OUT of the chip into its own\n // disclosure caret: authors read that arrow as \"expand\", and\n // inside the chip it inserted the whole output instead.\n const wholeBtn = source(\n st.label ?? st.id,\n { kind: \"var\", ref: `steps.${st.id}.output` },\n \"w6w-expr-chip-var\",\n fields.length > 0 ? null : \"▸\",\n fields.length > 0,\n );\n if (jsonBinding) {\n return (\n <Fragment key={st.id}>\n <span className=\"w6w-exprmodal-shape-note\">{st.label ?? st.id}</span>\n {source(\n \"Entire output\",\n { kind: \"var\", ref: `steps.${st.id}.output` },\n \"w6w-expr-chip-var\",\n \"▸\",\n false,\n `Entire output of ${st.label ?? st.id}`,\n )}\n {st.needsTest && (\n <div className=\"w6w-exprmodal-subsources\">\n <span className=\"w6w-exprmodal-shape-note\" data-testid=\"expr-needs-test\">\n Run a test of this step to see its fields\n </span>\n </div>\n )}\n {fields.length > 0 && (\n <>\n <div className=\"w6w-exprmodal-source-row\">\n <button\n type=\"button\"\n className=\"w6w-exprmodal-caret-btn\"\n data-testid=\"expr-caret-fields\"\n aria-expanded={isOpen}\n aria-label={isOpen ? \"Hide fields\" : \"Show fields\"}\n title={isOpen ? \"Hide fields\" : \"Show fields\"}\n onClick={() => toggleExpanded(stepKey)}\n >\n {isOpen ? \"▾\" : \"▸\"}\n </button>\n <FieldsToggle\n count={fields.length}\n open={isOpen}\n onToggle={() => toggleExpanded(stepKey)}\n />\n </div>\n {isOpen && (\n <div className=\"w6w-exprmodal-subsources\">\n {fields.map((o) => {\n const ref = `steps.${st.id}.output.${o.key}`;\n return source(\n varLabel(ref),\n { kind: \"var\", ref },\n \"w6w-expr-chip-var\",\n \"·\",\n );\n })}\n </div>\n )}\n </>\n )}\n </Fragment>\n );\n }\n return (\n <Fragment key={st.id}>\n {fields.length > 0 ? (\n <div className=\"w6w-exprmodal-source-row\">\n <button\n type=\"button\"\n className=\"w6w-exprmodal-caret-btn\"\n data-testid=\"expr-caret-fields\"\n aria-expanded={isOpen}\n aria-label={isOpen ? \"Hide fields\" : \"Show fields\"}\n title={isOpen ? \"Hide fields\" : \"Show fields\"}\n onClick={() => toggleExpanded(stepKey)}\n >\n {isOpen ? \"▾\" : \"▸\"}\n </button>\n {wholeBtn}\n <div className=\"w6w-exprmodal-toggle-stack\">\n <FieldsToggle\n count={fields.length}\n open={isOpen}\n onToggle={() => toggleExpanded(stepKey)}\n />\n {st.hasMeta === true && metaToggle(st.id)}\n </div>\n </div>\n ) : (\n wholeBtn\n )}\n {/* An app action that declares no output shape and has\n never been tested: nothing to offer but the whole\n output, so say how to get its fields. */}\n {st.needsTest && (\n <div className=\"w6w-exprmodal-subsources\">\n <span className=\"w6w-exprmodal-shape-note\" data-testid=\"expr-needs-test\">\n Run a test of this step to see its fields\n </span>\n </div>\n )}\n {/* …and one source per DECLARED output field, nested under\n it, collapsed until the toggle above is expanded. Each\n SAVES the canonical `steps.<id>.output.<key>` (the only\n form the engine resolves) and SHOWS `varLabel(ref)`,\n i.e. the short `<id>.<key>`. The key goes into the ref\n VERBATIM — `o.label` is display data and must never be\n substituted into a ref. */}\n {fields.length > 0 && isOpen && (\n <div className=\"w6w-exprmodal-subsources\">\n {st.outputsFrom === \"test\" && (\n <span\n className=\"w6w-exprmodal-shape-note\"\n data-testid=\"expr-fields-from-test\"\n >\n Fields from the last test run\n </span>\n )}\n {fields.map((o) => {\n const ref = `steps.${st.id}.output.${o.key}`;\n return source(\n varLabel(ref),\n { kind: \"var\", ref },\n \"w6w-expr-chip-var\",\n \"·\",\n );\n })}\n </div>\n )}\n {/* External app steps only (`st.hasMeta`, R-7): a fixed group of\n four LABELS. No value is ever shown: it exists only at run\n time. Independent of the fields caret and of `needsTest`. */}\n {st.hasMeta === true && (\n <>\n {fields.length === 0 && (\n <div className=\"w6w-exprmodal-source-row w6w-exprmodal-meta-row\">\n {metaToggle(st.id)}\n </div>\n )}\n {expanded.has(`meta:${st.id}`) && (\n <div className=\"w6w-exprmodal-subsources\" data-testid=\"expr-meta-fields\">\n {META_LEAVES.map(([key, label]) =>\n source(\n label,\n { kind: \"var\", ref: `steps.${st.id}.meta.${key}` },\n \"w6w-expr-chip-var\",\n \"·\",\n ),\n )}\n </div>\n )}\n </>\n )}\n </Fragment>\n );\n })}\n </div>\n )}\n\n {!jsonBinding && (\n <>\n {options.inputs !== undefined && (\n <div className=\"w6w-exprmodal-group\">\n <span className=\"w6w-exprmodal-group-label\">Inputs</span>\n {inputs.length === 0 && <span className=\"w6w-expr-menu-empty\">No inputs</span>}\n {inputs.map((i) =>\n source(i, { kind: \"var\", ref: `inputs.${i}` }, \"w6w-expr-chip-var\", \"⇥\"),\n )}\n </div>\n )}\n\n <div className=\"w6w-exprmodal-group\">\n <div className=\"w6w-field-labelrow\">\n <span className=\"w6w-exprmodal-group-label\">Variables</span>\n {options.createVar && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n data-testid=\"expr-add-var\"\n onClick={() => setAdding(\"var\")}\n >\n + Add\n </button>\n )}\n </div>\n {vars.length === 0 && <span className=\"w6w-expr-menu-empty\">No variables</span>}\n {vars.map((v) =>\n source(v, { kind: \"var\", ref: `vars.${v}` }, \"w6w-expr-chip-var\", \"◆\"),\n )}\n </div>\n\n <div className=\"w6w-exprmodal-group\">\n <span className=\"w6w-exprmodal-group-label\">Documents</span>\n {documents.length === 0 && (\n <span className=\"w6w-expr-menu-empty\">No documents</span>\n )}\n {documents.map((d) => {\n // Same guard, same single render site, as the steps block above:\n // enumerated raw at the source (studio's `document-sources.ts`),\n // filtered exactly once, here, where the ref is built (A3, A4a).\n const fields = (d.fields ?? []).filter((f) => isRefSafeKey(f.key));\n const docKey = `doc:${d.key}`;\n const isOpen = expanded.has(docKey);\n // The whole document — unconditional, for every format, exactly\n // as before (A2). Its class, label, sigil and inserted ref are\n // unchanged from before.\n const wholeBtn = source(\n d.key,\n { kind: \"var\", ref: `documents.${d.key}` },\n \"w6w-expr-chip-var\",\n \"▦\",\n fields.length > 0,\n );\n return (\n <Fragment key={d.key}>\n {fields.length > 0 ? (\n <div className=\"w6w-exprmodal-source-row\">\n {wholeBtn}\n <FieldsToggle\n count={fields.length}\n open={isOpen}\n onToggle={() => toggleExpanded(docKey)}\n />\n </div>\n ) : (\n wholeBtn\n )}\n {/* …and one source per surviving top-level field, nested\n under it, collapsed until the toggle above is expanded.\n The label is the field key itself — the parent row above\n already shows `d.key` — never `varLabel(ref)`, which\n would spell out the whole dotted ref again. Each row\n additionally carries a SECOND, visible action (D-P1)\n that inserts the SAME ref as a `render` part, so the\n placeholder-substitution behaviour is discoverable at\n the moment of insertion — not only via the chip's own\n post-insertion ⇄ toggle. */}\n {fields.length > 0 && isOpen && (\n <div className=\"w6w-exprmodal-subsources\">\n {fields.map((f) => {\n const ref = `documents.${d.key}.${f.key}`;\n return (\n <div key={ref} className=\"w6w-exprmodal-subsource-row\">\n {source(f.key, { kind: \"var\", ref }, \"w6w-expr-chip-var\", \"·\")}\n <button\n type=\"button\"\n className=\"w6w-exprmodal-render-btn\"\n data-testid=\"expr-insert-render\"\n title={`Insert ${ref} and render its {{ }} placeholders`}\n aria-label={`Insert ${ref} and render its {{ }} placeholders`}\n onClick={() => insertPart({ kind: \"render\", ref })}\n >\n ▤\n </button>\n </div>\n );\n })}\n </div>\n )}\n </Fragment>\n );\n })}\n </div>\n\n <div className=\"w6w-exprmodal-group\">\n <div className=\"w6w-field-labelrow\">\n <span className=\"w6w-exprmodal-group-label\">Secrets</span>\n {options.createSecret && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n data-testid=\"expr-add-secret\"\n onClick={() => setAdding(\"secret\")}\n >\n + Add\n </button>\n )}\n </div>\n {secrets.length === 0 && <span className=\"w6w-expr-menu-empty\">No secrets</span>}\n {secrets.map((s) =>\n source(s, { kind: \"secret\", ref: s }, \"w6w-expr-chip-secret\", \"🔒\"),\n )}\n </div>\n </>\n )}\n </aside>\n\n {/* Right: editor over the saved {{ }} template. */}\n {!jsonBinding && (\n <div className=\"w6w-exprmodal-main\">\n <div className=\"w6w-exprmodal-editor\">\n <span className=\"w6w-exprmodal-pane-label\">\n Expression\n <span className=\"w6w-muted w6w-small\"> — click a source on the left, or type</span>\n </span>\n <div\n ref={editorRef}\n className={`w6w-exprmodal-chips${masked ? \" is-masked\" : \"\"}${\n parts.length === 0 ? \" is-empty\" : \"\"\n }`}\n contentEditable\n suppressContentEditableWarning\n role=\"textbox\"\n tabIndex={0}\n aria-multiline={multiline ? \"true\" : \"false\"}\n aria-label=\"Expression\"\n data-placeholder=\"Type text and insert {x} variables, 🔒 secrets, or ▸ step outputs…\"\n spellCheck={false}\n onInput={() => {\n // D-3: promote a just-closed `{{ … }}` marker to a chip AT\n // THE KEYSTROKE THAT CLOSES IT — caret-safe surgery on the\n // matched span only (see `promoteCompletedMarkerAtCaret`'s\n // own docstring). `sync()` unconditionally afterwards either\n // way: promoted or not, the DOM is the source of truth.\n // NEVER bump `paintGen` here — see the warning at the top of\n // this file and `G-typing` in `expr-template-guards.test.cjs`.\n const el = editorRef.current;\n if (el) promoteCompletedMarkerAtCaret(el, { renderToggle: true });\n sync();\n }}\n onDoubleClick={(e) => {\n // D-3, the reverse direction: double-click a chip back to its\n // editable `{{ … }}` text, in place. Mirrors the onClick\n // delegate's short-circuit order just below — data-x, then\n // data-render-toggle — so a precise double-click on either\n // still wins (in practice the FIRST of the two clicks that\n // make up a dblclick already removes/flips the chip via\n // onClick, so by the time this fires there is no\n // `.w6w-expr-chip` left to find; these checks are the\n // explicit guard for that intent).\n const target = e.target as HTMLElement;\n if (target.closest(\"[data-x]\")) return;\n if (target.closest(\"[data-render-toggle]\")) return;\n const chip = target.closest(\".w6w-expr-chip\") as HTMLElement | null;\n if (!chip) return;\n e.preventDefault();\n const node = chipToText(chip);\n if (node) {\n const doc = node.ownerDocument;\n const after = doc.createRange();\n after.setStartAfter(node);\n after.collapse(true);\n const sel = doc.getSelection();\n sel?.removeAllRanges();\n sel?.addRange(after);\n }\n sync();\n }}\n onBlur={() => {\n // Discrete-event chip-ify commit #1: the editor just lost\n // focus, so any hand-typed `{{ … }}` left as raw text gets\n // one chance to become a chip. NEVER do this from `onInput`\n // above — see the `paintGen` warning at the top of this file\n // and G-typing in `expr-template-guards.test.cjs`.\n const el = editorRef.current;\n if (!el) return;\n adoptText(serializeTemplate(readParts(el)), { restoreFocus: false });\n }}\n onPaste={(e) => {\n // Discrete-event chip-ify commit #2. `insertNodeAtCaret` is\n // the SAME mechanism a rail click uses, so the caret is\n // preserved by construction — no bespoke caret-offset repaint\n // needed (out of scope by contract). No `setPaintGen`: each\n // part is inserted directly into the live DOM, exactly like a\n // rail insertion, so the existing chips are never re-painted.\n e.preventDefault();\n const el = editorRef.current;\n if (!el) return;\n const text = e.clipboardData?.getData(\"text/plain\") ?? \"\";\n for (const part of parseRootAnchoredTemplate(text)) {\n if (part.kind === \"text\") {\n insertNodeAtCaret(el, el.ownerDocument.createTextNode(part.value ?? \"\"));\n } else {\n insertNodeAtCaret(\n el,\n makeChip(el.ownerDocument, part, { renderToggle: true }),\n );\n }\n }\n sync();\n }}\n onClick={(e) => {\n const target = e.target as HTMLElement;\n const x = target.closest(\"[data-x]\");\n if (x) {\n e.preventDefault();\n x.closest(\".w6w-expr-chip\")?.remove();\n sync();\n return;\n }\n // The render affordance: flip a var⇄render chip IN PLACE. The\n // ref never changes — only `data-kind` (via a rebuilt chip\n // from the same `data-ref`, `makeChip`'s only construction\n // path) — and this does NOT bump `paintGen`, exactly like the\n // remove control above.\n const toggle = target.closest(\"[data-render-toggle]\");\n if (toggle) {\n e.preventDefault();\n const chip = toggle.closest(\".w6w-expr-chip\") as HTMLElement | null;\n if (chip) {\n const ref = chip.getAttribute(\"data-ref\") ?? \"\";\n const nextKind =\n chip.getAttribute(\"data-kind\") === \"render\" ? \"var\" : \"render\";\n chip.replaceWith(\n makeChip(\n chip.ownerDocument,\n { kind: nextKind, ref },\n { renderToggle: true },\n ),\n );\n }\n sync();\n }\n }}\n onKeyDown={(e) => {\n if (e.key !== \"Enter\") return;\n // ALWAYS suppressed — with or without Shift, multiline or not.\n // The browser's own line break (a wrapper <div>, or a <br>) is\n // markup we neither paint nor want to depend on.\n e.preventDefault();\n if (!multiline) return;\n const el = editorRef.current;\n if (!el) return;\n // Our own literal \"\\n\" text node, via the same caret helper the\n // source picker inserts chips with. `.w6w-exprmodal-chips` is\n // `pre-wrap`, so it renders as a break. The filler keeps a break\n // at the very END visible (and is skipped by `readParts`, so it\n // never reaches the value).\n insertNodeAtCaret(el, el.ownerDocument.createTextNode(\"\\n\"));\n ensureFillerBreak(el);\n sync();\n }}\n />\n </div>\n {usedRefs.length > 0 && (\n <div className=\"w6w-exprmodal-preview\">\n <span className=\"w6w-exprmodal-pane-label\">\n Sample values\n <span className=\"w6w-muted w6w-small\">\n {\" \"}\n — try the expression against example data\n </span>\n </span>\n {usedRefs.map((ref) => (\n <label key={ref} className=\"w6w-field\">\n <span>{ref}</span>\n <input\n type=\"text\"\n value={samples[ref] ?? \"\"}\n placeholder=\"sample value\"\n onChange={(e) => setSamples((s) => ({ ...s, [ref]: e.target.value }))}\n />\n </label>\n ))}\n </div>\n )}\n <div className=\"w6w-exprmodal-preview w6w-exprmodal-result-pane\">\n <span className=\"w6w-exprmodal-pane-label\">\n Result\n <span className=\"w6w-muted w6w-small\">\n {\" \"}\n — live preview against the sample values\n </span>\n </span>\n <Copyable value={result} readOnly>\n <pre className=\"w6w-exprmodal-result\">{result || \" \"}</pre>\n </Copyable>\n </div>\n </div>\n )}\n </div>\n\n {/* Nested \"+ Add\" dialog — last child of this Modal, so its own\n <dialog> stacks over this one in the browser's top layer\n (structurally identical to StepBuilderModal's AddConnectionModal\n nesting). Gated the same way the rail button was, so state can\n never point at a store the host didn't wire a callback for. */}\n {adding === \"var\" && options.createVar && (\n <AddValueModal kind=\"var\" onCreate={options.createVar} onClose={closeAdding} />\n )}\n {adding === \"secret\" && options.createSecret && (\n <AddValueModal kind=\"secret\" onCreate={options.createSecret} onClose={closeAdding} />\n )}\n </Modal>\n );\n}\n\n/**\n * The disclosure beside a rail source that has child field rows (a step's\n * output fields, a document's top-level keys). It names what it reveals —\n * \"11 fields\" — because the source chip's own `▸`/`▦` sigil reads as an\n * expander but INSERTS the whole value; a bare 20px chevron next to it went\n * unnoticed, leaving authors no visible way to reach `get_event_1.name`.\n */\nfunction FieldsToggle({\n count,\n open,\n onToggle,\n}: { count: number; open: boolean; onToggle: () => void }) {\n return (\n <button\n type=\"button\"\n className=\"w6w-exprmodal-toggle-btn\"\n data-testid=\"expr-toggle-fields\"\n aria-expanded={open}\n title={open ? \"Hide fields\" : \"Show fields\"}\n onClick={onToggle}\n >\n {count} {count === 1 ? \"field\" : \"fields\"} {open ? \"⌄\" : \"›\"}\n </button>\n );\n}\n\n/** The fixed Metadata leaves (R-7): key under `steps.<id>.meta.`, and the label shown. */\nconst META_LEAVES: [string, string][] = [\n [\"app\", \"App\"],\n [\"version\", \"App version\"],\n [\"action\", \"Action\"],\n [\"connectionId\", \"Connection ID\"],\n];\n\ninterface AddValueModalProps {\n kind: \"var\" | \"secret\";\n onCreate: (input: { name: string; value: string; description?: string }) => Promise<void>;\n onClose: () => void;\n}\n\n/**\n * The nested \"+ Add\" form. Same shape as `AddConnectionModal`'s\n * `ConnectionConfig` — `w6w-stack` body, one `w6w-field` label per input, an\n * inline `w6w-result w6w-error` block, ghost-Cancel + primary footer — but it\n * never fetches: `onCreate` (the host's `ExpressionOptions.createVar` /\n * `.createSecret`) is the only IO, so this mounts fine with no\n * `<W6WUIProvider>` around it (see `ExpressionEditorModal`'s own module\n * contract). A rejection leaves the dialog open with the message shown, name\n * hint copy matches studio's Vars/Vault pages.\n */\nfunction AddValueModal({ kind, onCreate, onClose }: AddValueModalProps) {\n const [name, setName] = useState(\"\");\n const [value, setValue] = useState(\"\");\n const [description, setDescription] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n const [pending, setPending] = useState(false);\n\n const noun = kind === \"var\" ? \"variable\" : \"secret\";\n\n async function submit() {\n setError(null);\n setPending(true);\n try {\n await onCreate({ name, value, description: description || undefined });\n onClose();\n } catch (e) {\n setError((e as Error).message);\n } finally {\n setPending(false);\n }\n }\n\n return (\n <Modal title={`Add ${noun}`} onClose={onClose}>\n {/* Body + pinned footer (D-3): `.w6w-stack` stays intact INSIDE the body so\n the fields keep their own spacing; only the action row moved out. */}\n <div className=\"w6w-modal-body\">\n <div className=\"w6w-stack\">\n <label className=\"w6w-field\">\n <span>Name</span>\n <input\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={kind === \"var\" ? \"e.g. api_base_url\" : \"e.g. openai_api_key\"}\n autoComplete=\"off\"\n data-testid=\"expr-add-value-name\"\n // biome-ignore lint/a11y/noAutofocus: nested dialog opened on demand — showModal() already moved focus in, this just picks the first field.\n autoFocus\n />\n <span className=\"w6w-muted w6w-small\">\n Lowercase letters, digits, and underscores. Must start with a letter or underscore.\n </span>\n </label>\n\n <label className=\"w6w-field\">\n <span>Value</span>\n <input\n type={kind === \"secret\" ? \"password\" : \"text\"}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n autoComplete=\"off\"\n data-testid=\"expr-add-value-value\"\n />\n {kind === \"secret\" && (\n <span className=\"w6w-muted w6w-small\">\n Stored encrypted at rest. Once saved, it is not readable through the UI.\n </span>\n )}\n </label>\n\n <label className=\"w6w-field\">\n <span>Description</span>\n <input\n type=\"text\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"Optional\"\n autoComplete=\"off\"\n />\n </label>\n\n {error && <div className=\"w6w-result w6w-error\">{error}</div>}\n </div>\n </div>\n <div className=\"w6w-modal-actions\">\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n data-testid=\"expr-add-value-cancel\"\n onClick={onClose}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"w6w-btn\"\n data-testid=\"expr-add-value-save\"\n disabled={!name || !value || pending}\n onClick={submit}\n >\n {pending ? \"Saving…\" : \"Save\"}\n </button>\n </div>\n </Modal>\n );\n}\n","/**\n * Context that supplies the var/secret PICKER data to every `ExpressionInput`\n * under it (task 3.2). The editor tree is deep — a step's params render several\n * layers below the editor root (`WorkflowFlowEditor → StepEditModal/StepBuilder\n * → ParamsForm → ParamField → ExpressionInput`), so threading names as props\n * through each layer would be noisy. A context keeps the wiring at the two ends:\n * the editor provides the names once, the input consumes them where it renders.\n *\n * The data pattern stays intact — ui components remain pure (they never fetch);\n * the host (studio) fetches `/vars` + `/vault` and hands the NAMES in via the\n * editor's `exprOptions` prop, which feeds this provider. Only names/refs ever\n * cross this boundary — secret plaintext never reaches the client.\n *\n * ## The scope is PROGRESSIVE, and that is the point\n *\n * `ExpressionOptionsProvider` **layers over** whatever it inherits rather than\n * replacing it, so scope is assembled by the tree instead of by one exhaustive\n * object at each call site:\n *\n * ```\n * app shell ── vars · secrets · documents · sampleValues · sealSecret · create*\n * └ page ── + inputs (a Function's / Endpoint's declared input keys)\n * └ region ── + steps (the workflow state leading to one step)\n * ```\n *\n * Two properties fall out of that, and both are requirements rather than\n * conveniences:\n *\n * 1. **Position, not plumbing, decides scope.** An `ExpressionInput` rendered\n * anywhere under the page — a modal, a mapping row, a nested card — sees\n * the same rail, because it inherits it. Before this, scope travelled as an\n * `exprOptions` prop and a field the prop had not been threaded to opened\n * the editor with an empty rail: the `ƒx` toggles on an Implementation\n * card's mapping rows offered nothing, while the very same editor reached\n * through the card's \"Change\" button offered everything.\n * 2. **Narrower scope cannot leak outward.** `inputs` added by a Function page\n * is invisible to a sibling route and to anything above the provider,\n * because React context only flows down. Navigating away drops it with the\n * subtree — no teardown to remember and no chance of one page's `inputs.*`\n * appearing in another's picker.\n *\n * Merging is **shallow, per key**: a key present in `value` wins outright (a\n * provider narrowing `vars` replaces the inherited list, it does not union with\n * it), and a key absent from `value` is inherited. To *remove* an inherited key\n * for a subtree, pass it explicitly as `undefined` — `{ inputs: undefined }` —\n * which is a present key and therefore wins.\n */\nimport { type ReactNode, createContext, useContext, useMemo } from \"react\";\nimport type { SecretValue } from \"../types.ts\";\n\n/**\n * Drop the step being edited (or drafted, not yet persisted) from its own rail\n * sources — a step cannot reference its own output.\n */\nexport function excludeSelfStep(\n steps: ExpressionStepSource[],\n selfId: string | null | undefined,\n): ExpressionStepSource[] {\n return selfId ? steps.filter((s) => s.id !== selfId) : steps;\n}\n\n/** An upstream step whose output this field can reference (`steps.<id>.output`). */\nexport interface ExpressionStepSource {\n /** Step id — the key under `steps` in the run scope. */\n id: string;\n /** Human label (defaults to the id). */\n label?: string;\n /**\n * The step's output field keys, when any are known (a manual trigger's\n * configured `fields`, a built-in node's static output, or an app action's\n * shape — see `outputsFrom`). Each entry feeds exactly one ref —\n * `steps.<id>.output.<key>` — which is the canonical form the engine resolves\n * (`RunScope.steps`; `core/rfcs/workflow.md` §\"Expressions\", `core/rfcs/node-types.md`\n * \"Executing a trigger node yields the run's start payload … which downstream\n * nodes read as `steps.<triggerId>.output`\").\n *\n * `key` is carried **verbatim**: a display-shortened key would build a ref\n * that renders fine in the editor and evaluates to empty at run time, with no\n * error. `label` is for display only and must never be substituted into a ref.\n *\n * **Omitted** (not `[]`) when the step declares no outputs, so a consumer can\n * tell \"nothing declared\" from \"declared none\" without a special case.\n */\n outputs?: { key: string; label?: string; path?: boolean }[];\n /**\n * Where `outputs` came from, for an app-action step: the action's declared\n * `output`, its `sample`, or the step's last test run (`output-shape.ts`).\n * An entry with `path: true` is a dot path into nested output (`start.utc`),\n * checked segment by segment; without it the key is one literal key.\n */\n outputsFrom?: \"declared\" | \"sample\" | \"test\";\n /**\n * `true` when the step is an app action that declares no output shape and has\n * no test run yet — the picker tells the author to run a test to see fields.\n */\n needsTest?: boolean;\n /**\n * `true` for an EXTERNAL app-action step only (R-7): the picker then offers a fixed\n * Metadata group (`steps.<id>.meta.app|version|action|connectionId`). **Omitted, not\n * `false`**, for triggers and every `@w6w/*` node. Carries no metadata VALUE: the group\n * is just labels, and the value exists only at run time.\n */\n hasMeta?: boolean;\n}\n\n/**\n * A document contributing pickable refs (`documents.<key>`, and one\n * `documents.<key>.<field>` per top-level field when it qualifies).\n *\n * A document contributes field sub-entries **iff**: `doc.format === \"json\"`\n * AND `JSON.parse(doc.content)` succeeds into a plain object, OR\n * `doc.format === \"yaml\"` AND npm `yaml`'s `parse(doc.content)` succeeds into\n * a plain object — where *plain object* means\n * `typeof v === \"object\" && v !== null && !Array.isArray(v)`. This mirrors\n * the engine's own gate: `documentsSeed`\n * (`packages/server/packages/api/run-seed.ts`, read-only, out of scope) is the\n * authority for each format — `format === \"json\"` or `format === \"yaml\"`,\n * then a `try/catch` parse, falling back to the raw content string on either\n * a non-matching format or a throw. `text`/`markdown`/`html` documents, and a\n * `json`/`yaml` document whose parse throws or yields a non-plain-object\n * (array/scalar), are excluded — offering a field ref outside this gate would\n * fail at run time with `render_ref_unresolved`, because the run scope itself\n * never parsed that document into an object.\n *\n * The two parsers (`@std/yaml` server-side, npm `yaml` here) are not\n * identical for every input — they diverge on tab-indented content and on an\n * unresolvable custom tag, both accepted, tested debt (D-3) — but agree on\n * everything else, including a plain JSON object (JSON is a subset of YAML).\n */\nexport interface ExpressionDocumentSource {\n /** Document key — the key under `documents` in the run scope. */\n key: string;\n /**\n * The document's top-level field keys, when the gate above holds. Each\n * entry feeds exactly one ref — `documents.<key>.<field>` — with `key`\n * carried **verbatim**: a display-shortened key would build a ref that\n * renders fine in the editor and evaluates to empty at run time, with no\n * error.\n *\n * **Omitted** (not `[]`) when the document contributes no fields, so a\n * consumer can tell \"nothing declared\" from \"declared none\" without a\n * special case — mirrors {@link ExpressionStepSource.outputs}'s own rule.\n */\n fields?: { key: string }[];\n}\n\n/** Known variable/secret names offered in an ExpressionInput's insert menu. */\nexport interface ExpressionOptions {\n vars?: string[];\n secrets?: string[];\n /**\n * Function/run input keys in scope (`inputs.<name>`). Present when the field\n * is edited inside a Function (the engine resolves these from `RunScope.inputs`);\n * omitted for a standalone field.\n */\n inputs?: string[];\n /**\n * Documents in scope (`documents.<key>`, plus `documents.<key>.<field>` for\n * each document that qualifies — see {@link ExpressionDocumentSource}). A\n * store-independent affordance: whatever the host passes is offered as\n * insertable chips. Omitted when no documents are available.\n */\n documents?: ExpressionDocumentSource[];\n /**\n * The workflow state leading to this step: upstream steps whose output is in\n * scope (`steps.<id>.output`). Present only in a workflow context; omitted for\n * a standalone field.\n */\n steps?: ExpressionStepSource[];\n /** Whether a trigger event is in scope (`trigger.event`). */\n hasTrigger?: boolean;\n /**\n * Design-time sample values the Result preview substitutes for known refs,\n * keyed by FULL ref (`\"vars.from_email\"`, `\"documents.test\"`). Seeded by the\n * host from the project's real vars/documents so the preview shows actual\n * values instead of the raw `{{ ref }}` template. Optional — a user-typed\n * Sample value still overrides, and unknown refs keep the raw fallback.\n */\n sampleValues?: Record<string, unknown>;\n /**\n * Seal a typed secret value into an at-rest `SecretValue` envelope via the\n * host (the client has no key). Provided by studio (`POST /vault/seal`); when\n * present, a secret-typed field encrypts on blur so its clear text never\n * lands in the workflow/config JSON. Absent → the value stays a plain string\n * and the server encrypts it on receive instead.\n */\n sealSecret?: (value: string) => Promise<SecretValue>;\n /**\n * Create a new named variable via the host (`POST /vars`-shaped: the host\n * persists it, `ui` never fetches). Powers the rail's \"+ Add\" control next\n * to the Variables group label. Absent ⇒ the control is not rendered.\n */\n createVar?: (input: { name: string; value: string; description?: string }) => Promise<void>;\n /**\n * Create a new named secret via the host (`POST /vault`-shaped, plaintext\n * value — the server encrypts it, `ui` never sees a key). Powers the rail's\n * \"+ Add\" control next to the Secrets group label. Absent ⇒ the control is\n * not rendered.\n */\n createSecret?: (input: { name: string; value: string; description?: string }) => Promise<void>;\n}\n\nconst ExpressionOptionsCtx = createContext<ExpressionOptions>({});\n\nexport interface ExpressionOptionsProviderProps {\n /**\n * The scope this level CONTRIBUTES — not the whole scope. Shallow-merged over\n * whatever is inherited (see the module doc): keys here win, keys absent are\n * inherited, and an explicit `undefined` removes an inherited key for this\n * subtree.\n */\n value: ExpressionOptions;\n children: ReactNode;\n}\n\n/**\n * Contribute expression scope to every `ExpressionInput` below.\n *\n * Layers over the inherited scope rather than replacing it, so an app shell can\n * provide vars/secrets/documents once and a page can add its `inputs` without\n * restating them — and without a field somewhere in the page missing the rail\n * because a prop was not threaded to it. See the module doc for the model.\n */\nexport function ExpressionOptionsProvider({ value, children }: ExpressionOptionsProviderProps) {\n const inherited = useContext(ExpressionOptionsCtx);\n // Memoised on the two inputs: a fresh object every render would re-render\n // every consumer below on every parent render, which on the workflow editor\n // is a repaint of each chip rail.\n const merged = useMemo(() => ({ ...inherited, ...value }), [inherited, value]);\n return <ExpressionOptionsCtx.Provider value={merged}>{children}</ExpressionOptionsCtx.Provider>;\n}\n\n/**\n * The scope in effect here — every contributing provider above, merged.\n *\n * Empty by default so a standalone `ExpressionInput` (no provider) still works\n * — authors just type names by hand.\n */\nexport function useExpressionOptions(): ExpressionOptions {\n return useContext(ExpressionOptionsCtx);\n}\n","import { useLayoutEffect, useRef, useState } from \"react\";\nimport type { ExprValue, SecretValue } from \"../types.ts\";\nimport { ExpressionEditorModal } from \"./ExpressionEditorModal.tsx\";\nimport { useExpressionOptions } from \"./ExpressionOptions.tsx\";\nimport {\n chipToText,\n ensureFillerBreak,\n insertNodeAtCaret,\n paintParts,\n placeCaretAtEnd,\n promoteCompletedMarkerAtCaret,\n readParts,\n} from \"./expression-dom.ts\";\nimport { partsToValue, valueToParts } from \"./expression-template.ts\";\n\n/**\n * ExpressionInput — a single field that reads like a textbox but whose contents\n * are inline SEGMENTS: plain text plus var/secret/expr chips (Notion/Zapier\n * blocks). You can type directly; to browse the data sources in scope\n * (variables, secrets, upstream step outputs) and build a reference, open the\n * full editor via the ƒx button — see {@link ExpressionEditorModal}.\n *\n * Value in ↔ out: incoming `value` is a plain string, an `ExprValue`, or a\n * sealed `SecretValue`. `onChange` emits the leanest faithful form — a plain\n * string when pure-text, an `ExprValue` for mixed content, or a sealed\n * `SecretValue` once a masked field is encrypted.\n */\nexport interface ExpressionInputProps {\n value: ExprValue | string | SecretValue | undefined;\n onChange: (next: ExprValue | string | SecretValue) => void;\n placeholder?: string;\n /** Mask typed text as dots + seal on blur (used for secret-typed params). */\n masked?: boolean;\n /**\n * The underlying param holds multi-line text (a `text`-typed param, or one\n * flagged `config.multiline` — the same fields that render a `textarea`).\n * Enter then inserts a literal `\"\\n\"` at the caret instead of being swallowed,\n * and `aria-multiline` follows. Omitted ⇒ single-line, as every existing\n * consumer expects.\n */\n multiline?: boolean;\n readOnly?: boolean;\n /** Picker data; falls back to the nearest `ExpressionOptionsProvider`. */\n options?: { vars?: string[]; secrets?: string[] };\n \"aria-label\"?: string;\n}\n\nexport function ExpressionInput({\n value,\n onChange,\n placeholder,\n masked,\n multiline,\n readOnly,\n options,\n \"aria-label\": ariaLabel,\n}: ExpressionInputProps) {\n // Seed once and own the content thereafter — the parent re-keys this widget\n // per field, so we never fight our own onChange echoes.\n const [state, setState] = useState(() => valueToParts(value));\n const { parts, sealed } = state;\n const [paintGen, setPaintGen] = useState(0);\n const [sealing, setSealing] = useState(false);\n const [modalOpen, setModalOpen] = useState(false);\n const wantFocus = useRef(false);\n const editorRef = useRef<HTMLDivElement>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n const ctxOptions = useExpressionOptions();\n // Merge so an explicit `options` prop can override vars/secrets while the\n // richer context sources (steps, trigger, sealSecret) still flow through.\n const resolved = { ...ctxOptions, ...(options ?? {}) };\n const sealSecret = ctxOptions.sealSecret;\n\n // Paint the editor DOM from `parts` on programmatic changes only (mount,\n // modal save, seal/replace) — never on keystrokes (would clobber the caret).\n // biome-ignore lint/correctness/useExhaustiveDependencies: repaint is gated on paintGen, never on `parts`.\n useLayoutEffect(() => {\n const el = editorRef.current;\n if (!el || sealed) return;\n paintParts(el, parts);\n if (wantFocus.current || el.ownerDocument.activeElement === el) {\n el.focus();\n placeCaretAtEnd(el);\n wantFocus.current = false;\n }\n }, [paintGen, sealed]);\n\n const syncFromDom = () => {\n const el = editorRef.current;\n if (!el) return;\n const next = readParts(el);\n setState((s) => ({ ...s, parts: next }));\n onChange(partsToValue(next));\n };\n\n // A masked field must never leave clear text: seal a plain typed value into a\n // `{type:\"secret\"}` envelope via the host (the client has no key).\n const sealPlain = async (v: string) => {\n if (!sealSecret) return false;\n setSealing(true);\n try {\n const env = await sealSecret(v);\n wantFocus.current = false;\n setState({ parts: [], sealed: env });\n setPaintGen((g) => g + 1);\n onChange(env);\n return true;\n } catch {\n return false; // keep the value; the server still encrypts at rest on save\n } finally {\n setSealing(false);\n }\n };\n\n // Seal on blur — but not while the editor modal is open (focus moved there).\n //\n // Deliberate behaviour change (CONDUCTOR AMENDMENT 2026-08-14, T1.2.2):\n // `valueToParts`'s string arm now root-anchor-parses, so a masked field\n // holding a ROOTED `{{ vars.x }}` yields an `ExprValue` here — `typeof v ===\n // \"string\"` is false, and it no longer seals (sealing would encrypt the\n // template text and permanently break resolution). A masked field holding\n // an UNROOTED placeholder like `{{name}}` still parses to a plain string\n // and still seals, exactly as before — see `expression-template.test.ts`'s\n // CA-4 tests for both arms.\n const onLeave = (e: React.FocusEvent) => {\n if (modalOpen || !masked || readOnly || sealing) return;\n const next = e.relatedTarget as Node | null;\n if (next && wrapperRef.current?.contains(next)) return;\n const v = partsToValue(parts);\n if (typeof v === \"string\" && v !== \"\") void sealPlain(v);\n };\n\n // Adopt a value from the modal: re-seed + repaint. For a masked field a plain\n // string is sealed instead of stored in the clear.\n const adopt = (next: ExprValue | string) => {\n if (masked && typeof next === \"string\" && next.trim() !== \"\") {\n void sealPlain(next);\n return;\n }\n wantFocus.current = false;\n setState(valueToParts(next));\n setPaintGen((g) => g + 1);\n onChange(next);\n };\n\n // A sealed at-rest secret: a single masked chip; ciphertext is never rendered.\n if (sealed) {\n return (\n <div className={`w6w-expr-sealed${readOnly ? \" is-readonly\" : \"\"}`} aria-label={ariaLabel}>\n <span className=\"w6w-expr-chip w6w-expr-chip-secret\" title=\"Encrypted secret\">\n <span className=\"w6w-expr-chip-sigil\">🔒</span>\n <span className=\"w6w-expr-chip-label\">••••••</span>\n </span>\n {!readOnly && (\n <button\n type=\"button\"\n className=\"w6w-expr-replace\"\n onClick={() => {\n wantFocus.current = true;\n setState({ parts: [], sealed: null });\n setPaintGen((g) => g + 1);\n onChange(\"\");\n }}\n >\n Replace\n </button>\n )}\n </div>\n );\n }\n\n return (\n <div className=\"w6w-expr\" ref={wrapperRef} onBlur={onLeave}>\n <div className=\"w6w-expr-field\">\n <div\n ref={editorRef}\n className={`w6w-expr-editor${masked ? \" is-masked\" : \"\"}${\n parts.length === 0 ? \" is-empty\" : \"\"\n }${readOnly ? \" is-readonly\" : \"\"}`}\n contentEditable={!readOnly}\n suppressContentEditableWarning\n role=\"textbox\"\n tabIndex={readOnly ? -1 : 0}\n aria-multiline={multiline ? \"true\" : \"false\"}\n aria-label={ariaLabel}\n data-placeholder={placeholder ?? \"\"}\n spellCheck={false}\n onInput={() => {\n // D-3: the more severe half — before this, a plain (unmasked)\n // inline field had NO promotion path at all (`onLeave` below\n // early-returns unless `masked`). Promote a just-closed\n // `{{ … }}` marker to a chip at the keystroke that closes it,\n // then sync unconditionally either way. NO `renderToggle` (R4 —\n // the toggle stays absent from this component), and NEVER bump\n // `paintGen`/repaint the field from here — see `G-typing`.\n const el = editorRef.current;\n if (el) promoteCompletedMarkerAtCaret(el);\n syncFromDom();\n }}\n onClick={(e) => {\n const x = (e.target as HTMLElement).closest(\"[data-x]\");\n if (!x) return;\n e.preventDefault();\n x.closest(\".w6w-expr-chip\")?.remove();\n syncFromDom();\n }}\n onDoubleClick={(e) => {\n // D-3, the reverse direction: double-click a chip back to its\n // editable `{{ … }}` text, in place. Mirrors the onClick\n // delegate immediately above — no render-toggle arm here, since\n // this component never paints one (R4).\n const target = e.target as HTMLElement;\n if (target.closest(\"[data-x]\")) return;\n const chip = target.closest(\".w6w-expr-chip\") as HTMLElement | null;\n if (!chip) return;\n e.preventDefault();\n const node = chipToText(chip);\n if (node) {\n const doc = node.ownerDocument;\n const after = doc.createRange();\n after.setStartAfter(node);\n after.collapse(true);\n const sel = doc.getSelection();\n sel?.removeAllRanges();\n sel?.addRange(after);\n }\n syncFromDom();\n }}\n onKeyDown={(e) => {\n if (e.key !== \"Enter\") return;\n // ALWAYS suppressed — with or without Shift, multiline or not. Left\n // to itself the browser wraps the caret's line in a <div> (or drops\n // a <br>), which is markup we neither paint nor want to depend on.\n e.preventDefault();\n if (!multiline) return; // single-line value field\n const el = editorRef.current;\n if (!el) return;\n // The break is OUR literal \"\\n\" text node, inserted with the same\n // caret helper the chip picker uses. `.w6w-expr-editor` is\n // `pre-wrap`, so it renders as a break; `readParts` reads it back\n // verbatim. The filler keeps a break at the very END visible (and is\n // skipped by `readParts`, so it never reaches the value).\n insertNodeAtCaret(el, el.ownerDocument.createTextNode(\"\\n\"));\n ensureFillerBreak(el);\n syncFromDom();\n }}\n />\n {!readOnly && (\n <button\n type=\"button\"\n className=\"w6w-expr-edit\"\n title=\"Edit expression — browse variables, secrets & step outputs\"\n aria-label=\"Edit expression\"\n onClick={() => setModalOpen(true)}\n >\n ƒx\n </button>\n )}\n </div>\n\n {modalOpen && (\n <ExpressionEditorModal\n value={partsToValue(parts)}\n masked={masked}\n multiline={multiline}\n options={resolved}\n fieldLabel={ariaLabel}\n onSave={adopt}\n onClose={() => setModalOpen(false)}\n />\n )}\n </div>\n );\n}\n","/**\n * Resolve a step's configured param VALUES against a test scope — the\n * \"what will this expression actually produce\" the Test tab shows, distinct\n * from `ParamsForm`/`ExpressionInput` which only ever EDIT the stored value.\n *\n * Greenfield by contract: `components/expression-template.ts`'s `renderResult`\n * is the only existing \"resolve a var ref against sample values\" function, but\n * it collapses \"ref not in scope\" and \"ref resolved to an empty value\" to the\n * same `out += \"\"` INSIDE its per-part loop — the distinction this module\n * exists to preserve is already gone by the time it returns. This file shares\n * no code with it and is not imported by it (0 lines touched there, verified\n * by `git diff --numstat` in the result).\n *\n * No React, no JSX — a pure, `node --test`-covered module, mirroring the\n * `step-preview-state.ts` / `trigger-fields.ts` precedent. `StepStartState` is\n * imported type-only (erased at runtime, same idiom `step-preview-state.ts:16`\n * already uses), so this file never actually loads `provider.tsx`'s React\n * import.\n */\nimport type { StepMeta, StepStartState } from \"./provider.tsx\";\nimport { type ExprPart, type ExprValue, isExprValue, isSecretValue } from \"./types.ts\";\n\n/**\n * Per-segment resolution outcome. Every value that can contain a `var`/`expr`\n * part resolves to an ARRAY of these (one per part of a multipart `ExprValue`,\n * or one for a single top-level marker/literal) — never a bare `string`, which\n * is exactly the shape `renderResult` collapses to and loses the distinction.\n *\n * `value` on `\"resolved\"` is `unknown` and explicitly INCLUDES `null` / `\"\"` /\n * `false` / `0` — those are real, present values, not absence. `\"unresolved\"`\n * carries no `value` at all (there is nothing to show) and always carries the\n * `ref` that failed to resolve, so a caller can render \"this ref, unresolved\"\n * without ever falling back to rendering the ref as if it WERE the value.\n */\nexport type ResolvedSegment =\n | { status: \"resolved\"; ref?: string; value: unknown }\n | { status: \"unresolved\"; ref: string }\n | { status: \"not-evaluated\"; ref?: string }\n | { status: \"masked\"; ref?: string };\n\n/**\n * The scope a param's `var` refs resolve against. Built by {@link buildResolveScope}\n * from the SAME two things `StepEditModal` already computes: `testStartState`\n * (for `steps.*`/`trigger.*` — the object literally sent as the test's `state`)\n * and `sampleValues` (for `vars.*`/`documents.*`).\n */\nexport interface ResolveScope {\n vars: Record<string, unknown>;\n documents: Record<string, unknown>;\n steps: Record<string, { output?: unknown; meta?: StepMeta }>;\n trigger: { event?: unknown };\n /**\n * The original flat `sampleValues` map, keyed by full ref string — checked\n * BEFORE the nested walk in {@link resolveRef}. `documentSampleValues`\n * (`document-sources.ts`) emits a document field's sample as its OWN\n * complete flat entry (`\"documents.<key>.<field>\"`), not as a nested value\n * living under the shorter `\"documents.<key>\"` entry — so the one-hop strip\n * below reconstructs `documents[\"<key>.<field>\"]` (one key, a literal dot\n * in it) instead of `documents[\"<key>\"][\"<field>\"]`, and a real\n * `\"<key>\"` entry (the whole document's raw content, a string) already\n * occupies that slot besides. `walkPath`'s segment-by-segment walk can\n * never reach either shape. An exact flat-key hit here resolves any ref\n * `sampleValues` names directly, regardless of how many segments it has;\n * the nested walk stays the fallback for a ref whose own reconstructed\n * value happens to be an object (`vars.address` = `{ city: \"X\" }`, walking\n * into it for `vars.address.city`), which is a value shape `sampleValues`\n * never produces a matching flat key for in the first place.\n *\n * Optional: a `ResolveScope` built by hand (as most tests in\n * `resolve-params.test.ts` do, to exercise the walk directly) has no flat\n * map to check and falls straight through to `walkPath` — only\n * `buildResolveScope` populates it.\n */\n flat?: Record<string, unknown>;\n}\n\nconst VARS_PREFIX = \"vars.\";\nconst DOCUMENTS_PREFIX = \"documents.\";\n\n/**\n * Build a {@link ResolveScope} from the two sources scope fidelity requires\n * they come from separately:\n *\n * - `steps`/`trigger` come from `testStartState` — the exact object the test\n * invoke sends as `state`, so a `steps.<id>.output.<field>` ref resolves to\n * what the test will ACTUALLY see, not a design-time sample.\n * - `vars`/`documents` come from `sampleValues` (`useExpressionOptions()`), a\n * FLAT map keyed by full ref (`\"vars.from_email\"`, `\"documents.<key>\"`).\n * Reconstructed into a nested object here (strip the root prefix, one hop)\n * so {@link walkPath} can dot-walk into a var/document whose OWN value is an\n * object — `sampleValues[\"vars.address\"]` holding `{ city: \"X\" }` still\n * resolves `vars.address.city` correctly, because the walk continues INTO\n * the reconstructed value rather than doing a second flat-key lookup.\n */\nexport function buildResolveScope(\n sampleValues: Record<string, unknown> | undefined,\n testStartState: StepStartState | undefined,\n): ResolveScope {\n const vars: Record<string, unknown> = {};\n const documents: Record<string, unknown> = {};\n for (const [ref, value] of Object.entries(sampleValues ?? {})) {\n if (ref.startsWith(VARS_PREFIX)) vars[ref.slice(VARS_PREFIX.length)] = value;\n else if (ref.startsWith(DOCUMENTS_PREFIX))\n documents[ref.slice(DOCUMENTS_PREFIX.length)] = value;\n }\n return {\n vars,\n documents,\n steps: (testStartState?.steps as Record<string, { output?: unknown; meta?: StepMeta }>) ?? {},\n trigger: testStartState?.trigger ?? {},\n flat: sampleValues ?? {},\n };\n}\n\n/**\n * `getVar`-style dot-path walk (mirrors `packages/core/packages/expr/src/jsonlogic.ts`'s\n * `getVar`: `String(path).split(\".\")`, `cur = cur[part]`), but — the one\n * deliberate improvement a design-time PREVIEW can make that the run-time\n * engine cannot — it reports PRESENCE as a first-class result instead of\n * collapsing \"path absent\" and \"path present but null\" to the same fallback.\n * A hop into `null`/a non-object with segments still remaining is \"absent\",\n * never a value to keep walking into.\n */\nfunction walkPath(\n root: Record<string, unknown>,\n path: string,\n): { present: boolean; value: unknown } {\n const parts = path.split(\".\");\n let cur: unknown = root;\n for (const part of parts) {\n if (cur === null || typeof cur !== \"object\") return { present: false, value: undefined };\n if (!(part in (cur as Record<string, unknown>))) return { present: false, value: undefined };\n cur = (cur as Record<string, unknown>)[part];\n }\n return { present: true, value: cur };\n}\n\n/** Resolve a single `var`/`$`-marker ref against the scope. */\nfunction resolveRef(ref: string, scope: ResolveScope): ResolvedSegment {\n // A `vars.*`/`documents.*` ref that `sampleValues` already names directly\n // (any number of segments) resolves exactly, before the nested walk below\n // ever gets a chance to misreconstruct it — see `ResolveScope.flat`'s doc.\n if (\n scope.flat &&\n (ref.startsWith(VARS_PREFIX) || ref.startsWith(DOCUMENTS_PREFIX)) &&\n Object.hasOwn(scope.flat, ref)\n ) {\n return { status: \"resolved\", ref, value: scope.flat[ref] };\n }\n const walked = walkPath(scope as unknown as Record<string, unknown>, ref);\n return walked.present\n ? { status: \"resolved\", ref, value: walked.value }\n : { status: \"unresolved\", ref };\n}\n\n/** Resolve one {@link ExprPart} of a multipart `ExprValue`. */\nfunction resolvePart(part: ExprPart, scope: ResolveScope): ResolvedSegment {\n switch (part.kind) {\n case \"text\":\n return { status: \"resolved\", value: part.value ?? \"\" };\n case \"var\":\n return resolveRef(part.ref ?? \"\", scope);\n case \"secret\":\n // A named secret reference is ALWAYS masked — never looked up, never\n // shown, regardless of whether the name is \"in scope\". Mirrors the\n // engine/editor precedent: the plaintext never reaches the client at\n // all, so there is nothing to resolve here, only something to hide.\n return { status: \"masked\", ref: part.ref };\n case \"expr\":\n // Raw JSONLogic — no client-side evaluator exists anywhere in `ui`\n // (confirmed by the gap analysis). Labeled \"not evaluated\": a distinct\n // status from \"unresolved\", never rendered as if it were a value.\n return { status: \"not-evaluated\" };\n case \"render\":\n // The resolved ref is itself parsed as a `{{ }}` template and rendered\n // against the run scope — that needs the run's own resolver (T2.1.1),\n // not this design-time preview. Same honest answer as `expr` above;\n // without this arm the `default:` below reports a render part as\n // RESOLVED with `undefined`, i.e. a blank that looks correct.\n return { status: \"not-evaluated\" };\n default:\n return { status: \"resolved\", value: undefined };\n }\n}\n\n/** A hand-authored whole-value path marker: `{ \"$\": \"<path>\" }`, exactly one key. */\nexport function isDollarPath(v: unknown): v is { $: unknown } {\n return (\n typeof v === \"object\" &&\n v !== null &&\n !Array.isArray(v) &&\n Object.keys(v as object).length === 1 &&\n \"$\" in (v as object)\n );\n}\n\n/** A hand-authored whole-value JSONLogic marker: `{ \"$expr\": <logic> }`, exactly one key. */\nexport function isDollarExpr(v: unknown): v is { $expr: unknown } {\n return (\n typeof v === \"object\" &&\n v !== null &&\n !Array.isArray(v) &&\n Object.keys(v as object).length === 1 &&\n \"$expr\" in (v as object)\n );\n}\n\n/**\n * Resolve one configured param VALUE (or one `vars`-row's `value`, per A5 — the\n * same function, called again per row) against `scope`. Returns one segment\n * per part of a multipart `ExprValue`, or a single segment for anything else:\n * a `SecretValue` at-rest envelope (`masked`), a hand-authored `{\"$\":…}` /\n * `{\"$expr\":…}` marker (resolved as a ref lookup / not-evaluated — NOT as a\n * literal object, per the acceptance pin), or a plain literal (`resolved`,\n * `value` as-is, no `ref`).\n */\nexport function resolveParamValue(value: unknown, scope: ResolveScope): ResolvedSegment[] {\n if (isSecretValue(value)) return [{ status: \"masked\" }];\n if (isExprValue(value)) return (value as ExprValue).parts.map((p) => resolvePart(p, scope));\n if (isDollarPath(value)) return [resolveRef(String((value as { $: unknown }).$), scope)];\n if (isDollarExpr(value)) return [{ status: \"not-evaluated\" }];\n return [{ status: \"resolved\", value }];\n}\n\n/**\n * Structural deep-equality over JSON-shaped values (primitives, arrays, plain\n * objects, recursively) — no new dependency. Used by the Test tab's \"unchanged\n * from default\" filter (D-1/A1): equality, not presence, so a value the\n * hand-editable JSON view baked in explicitly is still recognized as\n * unchanged when it matches the declared default. `a === b` covers primitives\n * (including `undefined === undefined`, so a param with neither a value nor a\n * declared default is \"equal\" too) and short-circuits identical references\n * before the recursive object/array walk.\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a !== typeof b) return false;\n if (a === null || b === null || typeof a !== \"object\") return false;\n const aArr = Array.isArray(a);\n const bArr = Array.isArray(b as object);\n if (aArr !== bArr) return false;\n if (aArr) {\n const arrA = a as unknown[];\n const arrB = b as unknown[];\n return arrA.length === arrB.length && arrA.every((v, i) => deepEqual(v, arrB[i]));\n }\n const objA = a as Record<string, unknown>;\n const objB = b as Record<string, unknown>;\n const keysA = Object.keys(objA);\n const keysB = Object.keys(objB);\n return (\n keysA.length === keysB.length && keysA.every((k) => k in objB && deepEqual(objA[k], objB[k]))\n );\n}\n","/**\n * Fold a param's resolved {@link ResolvedSegment}s into the one JSON value the\n * Test tab's code view shows (A6). Distinct from both existing serializers:\n * `resolve-params.ts` stops at the per-segment array (what `ResolvedParams`\n * renders as chips + badges), and `flow-utils.ts`'s `stepToJson`/`paramsToJson`\n * serialize the raw stored step/`with` — the schema-shaped envelope this view\n * must never leak (a `{type:\"expr\",parts:[…]}` blob, or worse, `ciphertext`).\n *\n * No React, no JSX — a pure, `node --test`-covered module, mirroring the\n * `resolve-params.ts` precedent this sits beside.\n */\nimport { type ResolveScope, type ResolvedSegment, resolveParamValue } from \"./resolve-params.ts\";\n\n/**\n * Fold ONE segment into its JSON token. `value === undefined` on a `resolved`\n * segment folds to `\"<not set>\"`, never to an omitted key — `JSON.stringify`\n * drops `undefined` keys on its own, and a silently missing key is exactly the\n * D-6 defect (blank-indistinguishable-from-null) this module exists to avoid.\n */\nfunction foldOne(seg: ResolvedSegment): unknown {\n switch (seg.status) {\n case \"resolved\":\n return seg.value === undefined ? \"<not set>\" : seg.value;\n case \"unresolved\":\n return `<unresolved: ${seg.ref}>`;\n case \"not-evaluated\":\n return \"<not evaluated>\";\n case \"masked\":\n return seg.ref ? `<masked: ${seg.ref}>` : \"<masked>\";\n }\n}\n\n/** Render one segment as TEXT for the multi-segment concatenation case. */\nfunction foldOneAsText(seg: ResolvedSegment): string {\n if (seg.status === \"resolved\" && seg.value !== undefined) {\n return typeof seg.value === \"string\" ? seg.value : JSON.stringify(seg.value);\n }\n return String(foldOne(seg));\n}\n\n/**\n * Fold a param's full segment array (the shape {@link resolveParamValue}\n * returns) into ONE JSON value, per A6's pinned table: a single segment folds\n * to its own token/value; multiple segments (a multipart `ExprValue`)\n * concatenate into one string, each `resolved` part contributing its text\n * (strings as-is, non-strings `JSON.stringify`d) and every other part\n * contributing its placeholder token.\n */\nexport function foldResolvedSegments(segments: ResolvedSegment[]): unknown {\n if (segments.length === 1) return foldOne(segments[0]);\n return segments.map(foldOneAsText).join(\"\");\n}\n\n/** Resolve + fold one param VALUE against `scope` in a single call. */\nexport function resolveParamJson(value: unknown, scope: ResolveScope): unknown {\n return foldResolvedSegments(resolveParamValue(value, scope));\n}\n\n/**\n * A `vars`-typed param's configured rows, folded into one object keyed by\n * each row's own `key` (`\"(no key)\"` when blank — mirrors `ResolvedVarsRow`'s\n * fallback), each row's `value` folded by the same rules as any other param.\n */\nexport function resolveVarsJson(\n rows: Array<{ key?: string; value: unknown }>,\n scope: ResolveScope,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const row of rows) {\n out[row.key || \"(no key)\"] = resolveParamJson(row.value, scope);\n }\n return out;\n}\n","import { type ReactNode, useEffect, useId, useState } from \"react\";\nimport { CodeEditor, type ScriptLanguage } from \"./CodeEditor.tsx\";\nimport { JsonEditor } from \"./JsonEditor.tsx\";\nimport { ExpressionEditorModal } from \"./components/ExpressionEditorModal.tsx\";\nimport { ExpressionInput } from \"./components/ExpressionInput.tsx\";\nimport { useExpressionOptions } from \"./components/ExpressionOptions.tsx\";\nimport { Icon } from \"./components/Icon.tsx\";\nimport { Modal } from \"./components/Modal.tsx\";\nimport { buildResolveScope, isDollarPath } from \"./resolve-params.ts\";\nimport { resolveParamJson } from \"./resolved-json.ts\";\nimport { type ActionParam, type ExprValue, type SecretValue, isExprValue } from \"./types.ts\";\n\n/**\n * Evaluate a param's `showIf` predicate. `getValue` resolves a sibling field's\n * current value (falling back to its default). Params with no `showIf` always show.\n *\n * Exported so callers outside this form (e.g. `requiredParamsFilled`'s Test-gate)\n * can skip a `required` field that's currently hidden — otherwise `required` and\n * `showIf` can't safely combine: a field required only in one branch (e.g.\n * SendGrid's `contentValue`, moot once a dynamic template supplies the body)\n * would block the gate even while hidden.\n */\nexport function isParamVisible(param: ActionParam, getValue: (key: string) => unknown): boolean {\n const c = param.showIf;\n if (!c) return true;\n const v = getValue(c.field);\n if (c.equals !== undefined) return v === c.equals;\n if (c.in) return c.in.some((x) => x === v);\n if (c.notIn) return !c.notIn.some((x) => x === v);\n if (c.truthy !== undefined) return c.truthy ? !!v : !v;\n return true;\n}\n\n/**\n * Render a param list, laying adjacent params that share a `row` id side by side\n * in a flex row; everything else stacks normally.\n */\n/**\n * Flatten a param list, descending into `section` children (which write their\n * values flat at the enclosing form level). Used to resolve declared defaults\n * for `showIf` across sections. Non-section `children` (e.g. a nested `group`\n * object) are left alone — those values live nested under the parent key.\n */\nexport function flattenParams(list: ActionParam[]): ActionParam[] {\n const out: ActionParam[] = [];\n for (const p of list) {\n out.push(p);\n if (p.type === \"section\" && p.children) out.push(...flattenParams(p.children));\n }\n return out;\n}\n\nfunction renderFieldRows(\n list: ActionParam[],\n renderOne: (p: ActionParam) => ReactNode,\n): ReactNode[] {\n const out: ReactNode[] = [];\n for (let i = 0; i < list.length; ) {\n const rowId = list[i].row;\n if (rowId) {\n const group: ActionParam[] = [];\n while (i < list.length && list[i].row === rowId) group.push(list[i++]);\n out.push(\n <div className=\"w6w-field-row\" key={`row:${rowId}`}>\n {group.map(renderOne)}\n </div>,\n );\n } else {\n out.push(renderOne(list[i]));\n i++;\n }\n }\n return out;\n}\n\n/**\n * Builds the `renderOne` dispatch a param list is rendered through: `section`\n * (layout-only, shares the caller's `values`/`set`/`effective`), `repeat: true`\n * (→ {@link RepeatField}, the existing `ArrayField` with a synthesized `item`),\n * `type: \"group\"` with a non-empty `children` (→ {@link GroupField}, a nested\n * form), else the plain {@link ParamField}. Factored out so {@link GroupField}\n * can build its OWN dispatch bound to its nested `values`/`set`/`effective` —\n * the one place a group's value-plumbing must differ from `SectionField`'s (see\n * `GroupField`'s own doc comment).\n */\nfunction makeRenderOne(\n values: Record<string, unknown>,\n set: (key: string, value: unknown) => void,\n effective: (key: string) => unknown,\n readOnly: boolean | undefined,\n): (p: ActionParam) => ReactNode {\n const renderOne = (p: ActionParam): ReactNode => {\n if (p.type === \"section\") {\n return <SectionField key={p.key} param={p} effective={effective} renderOne={renderOne} />;\n }\n // `repeat` is sugar for `type: \"array\"` (rfcs/param.md's amendment) — an\n // explicit `type: \"array\"` param already routes through `ParamField`'s own\n // `array` arm, so it's excluded here to avoid double-synthesizing `item`.\n if (p.repeat && p.type !== \"array\") {\n return (\n <RepeatField\n key={p.key}\n param={p}\n value={values[p.key]}\n onChange={set}\n readOnly={readOnly}\n />\n );\n }\n if (p.type === \"group\" && p.children && p.children.length > 0) {\n return (\n <GroupField\n key={p.key}\n param={p}\n value={values[p.key]}\n onChange={set}\n effective={effective}\n readOnly={readOnly}\n />\n );\n }\n return (\n <ParamField\n key={p.key}\n param={p}\n value={values[p.key]}\n onChange={set}\n effective={effective}\n readOnly={readOnly}\n />\n );\n };\n return renderOne;\n}\n\nexport interface ParamsFormProps {\n /** Declared params of the selected action. */\n params: ActionParam[];\n /** Current values, keyed by param `key`. Becomes the step's `with`. */\n values: Record<string, unknown>;\n /** Fired with the next values object on every edit. */\n onChange: (values: Record<string, unknown>) => void;\n readOnly?: boolean;\n}\n\n/**\n * Renders an action's declared params as a form. Required params are always\n * shown; optional ones collapse under a disclosure so the common path stays\n * tidy. Widget is chosen by `param.type` — same field-driven approach as\n * `AuthFieldsForm`, extended with `text` (textarea) and `json` (JsonEditor).\n *\n * Values are collected into a plain object suitable for a step's `with`. For\n * expression bindings (`{ $: \"steps.x.output.y\" }`) authors drop to the JSON\n * view; this form deals in literals.\n */\nexport function ParamsForm({ params, values, onChange, readOnly }: ParamsFormProps) {\n // Effective value of a field for `showIf` checks: the entered value, else the\n // field's declared default (so conditions hold before the user touches it).\n // Section/group children write flat at the enclosing level, so flatten them\n // too — otherwise a `showIf` referencing a section child sees `undefined` for\n // its declared default until the user edits it.\n const flat = flattenParams(params);\n const effective = (key: string) =>\n values[key] !== undefined ? values[key] : flat.find((p) => p.key === key)?.default;\n const visible = params.filter((p) => isParamVisible(p, effective));\n // Split by `advanced` (not by required): required + non-advanced show up front;\n // only fields flagged `advanced` collapse under \"Additional parameters\".\n const main = visible.filter((p) => p.required || !p.advanced);\n const additional = visible.filter((p) => !p.required && p.advanced);\n // A `language` change is the one edit that must also touch a SIBLING field:\n // any `code` param whose currently-stored value is still untouched\n // boilerplate (undefined, its own declared default, or the other\n // language's hardcoded default) swaps to the new language's default, in\n // the SAME compound `onChange` call — so there is no intermediate render\n // with a mismatched `language`/`code` pair (D-3, ROUND 2 / B3). This is the\n // one choke point every field edit passes through (`makeRenderOne`'s\n // `ParamField`/`GroupField`/`RepeatField` call sites all get this same\n // `set` as their `onChange`), so it's the right place to own the write.\n const set = (key: string, value: unknown) => {\n if (key === \"language\") {\n const next: Record<string, unknown> = { ...values, [key]: value };\n for (const p of flat) {\n if (p.type !== \"code\") continue;\n const current = values[p.key];\n const isUntouchedBoilerplate =\n current === undefined || current === p.default || current === PYTHON_CODE_DEFAULT;\n if (isUntouchedBoilerplate) {\n next[p.key] = value === \"python\" ? PYTHON_CODE_DEFAULT : p.default;\n }\n }\n onChange(next);\n return;\n }\n onChange({ ...values, [key]: value });\n };\n\n if (params.length === 0) {\n return <p className=\"w6w-muted w6w-small\">This action takes no parameters.</p>;\n }\n\n // A `section` is a layout-only container: it renders its children through this\n // SAME pipeline (so child `row`/`showIf`/nested sections still work) and —\n // crucially — passes the TOP-LEVEL `set`/`values` down, so section children\n // write to the enclosing form values, not nested under the section key. Note a\n // section IS the disclosure, so a child's `advanced` flag is not re-split here.\n const renderOne = makeRenderOne(values, set, effective, readOnly);\n\n return (\n <div className=\"w6w-stack\">\n {renderFieldRows(main, renderOne)}\n {additional.length > 0 && (\n <details className=\"w6w-params-optional\">\n <summary className=\"w6w-muted w6w-small\">\n Additional parameters ({additional.length})\n </summary>\n <div className=\"w6w-stack\" style={{ marginTop: 8 }}>\n {renderFieldRows(additional, renderOne)}\n </div>\n </details>\n )}\n </div>\n );\n}\n\n/**\n * A `section`-typed param — a layout-only container of `children`. Two shapes:\n * `section: \"collapsible\"` renders a titled, collapsed-by-default `<details>`\n * disclosure (the app-authored per-cluster disclosure, distinct from the single\n * global \"Additional parameters\" one); `section: \"group\"` lays the children out\n * per `layout` — `\"row\"` side by side (reusing `.w6w-field-row`), else stacked.\n *\n * Children render through the SAME `renderOne` pipeline the enclosing form uses,\n * so their values are written flat at the enclosing form level (a section does\n * NOT nest its value object), and child `row`/`showIf`/nested sections keep\n * working. A child's `advanced` flag is ignored inside a section — the section\n * itself is the disclosure, so children are shown inline within it.\n */\nfunction SectionField({\n param,\n effective,\n renderOne,\n}: {\n param: ActionParam;\n effective: (key: string) => unknown;\n renderOne: (p: ActionParam) => ReactNode;\n}) {\n const visibleChildren = (param.children ?? []).filter((c) => isParamVisible(c, effective));\n\n if (param.section === \"collapsible\") {\n return (\n <details className=\"w6w-section\" open={param.collapsed === false}>\n <summary className=\"w6w-section-summary\">\n <span className=\"w6w-section-title\">{param.title ?? param.label ?? param.key}</span>\n {param.subtitle && <span className=\"w6w-section-subtitle\">{param.subtitle}</span>}\n </summary>\n <div className=\"w6w-stack w6w-section-body\">\n {renderFieldRows(visibleChildren, renderOne)}\n </div>\n </details>\n );\n }\n\n // group: side by side (`layout: \"row\"`) or stacked (default). The row wrapper\n // reuses the existing `.w6w-field-row` rule so each child `.w6w-field` sits\n // side by side; stack still honors child `row` grouping via renderFieldRows.\n if (param.layout === \"row\") {\n return <div className=\"w6w-field-row\">{visibleChildren.map(renderOne)}</div>;\n }\n return <div className=\"w6w-stack\">{renderFieldRows(visibleChildren, renderOne)}</div>;\n}\n\n/** Scalar-only types `ArrayItemInput` (`:795-850` below) actually renders — a\n * select, checkbox, number or text input. Anything else (a `secret`, or a\n * child carrying its own `children`) falls back to the JSON editor for the\n * whole group rather than half-rendering it (D-2, rfcs/param.md's amendment). */\nconst ARRAY_ITEM_SCALAR_TYPES = new Set([\"string\", \"text\", \"number\", \"boolean\", \"select\"]);\n\nfunction fitsArrayItemFields(fields: ActionParam[]): boolean {\n return (\n fields.length > 0 && fields.every((f) => ARRAY_ITEM_SCALAR_TYPES.has(f.type) && !f.children)\n );\n}\n\n/**\n * A `type: \"group\"` param with a non-empty `children` — a **nested** form.\n * Mirrors `SectionField`'s shape (a heading + `renderFieldRows` over the\n * visible children) with the ONE inversion a group requires: values write\n * NESTED under this param's own key (`onChange(param.key, {...current,\n * [childKey]: v})`), matching `resolveParams`' own nesting and\n * rfcs/param.md:190 — a section's children stay flat, a group's do not, so\n * this is deliberately a separate component rather than `SectionField`\n * parameterized to do both (that would conflate two value contracts in one\n * component's props).\n *\n * Bare container (D-1): `param.label`/`param.key` as a plain heading (reusing\n * the existing `.w6w-section-title`/`.w6w-section-body` type styles — no new\n * class, no border, no `<details>`), children stacked below.\n *\n * Group-local `showIf` (D-3): a child's `showIf` resolves against the group's\n * OWN children first, falling back to the enclosing form's `effective` for any\n * key the group doesn't declare — the same rule rfcs/param.md:256 already\n * states for `dependsOn`, extended here to `showIf`.\n */\nfunction GroupField({\n param,\n value,\n onChange,\n effective,\n readOnly,\n}: {\n param: ActionParam;\n value: unknown;\n onChange: (key: string, value: unknown) => void;\n /** The ENCLOSING form's `effective` — the fallback for a key this group\n * doesn't declare among its own (flattened) children. */\n effective: (key: string) => unknown;\n readOnly?: boolean;\n}) {\n const children = param.children ?? [];\n const groupValue = (value ?? {}) as Record<string, unknown>;\n const groupSet = (key: string, v: unknown) => onChange(param.key, { ...groupValue, [key]: v });\n // Flattened so a `section` nested inside this group (which writes flat at\n // the group's own level) still counts as \"the group's own\" for showIf\n // resolution — mirrors flattenParams' existing section-descent, reused as-is.\n const flatChildren = flattenParams(children);\n const groupEffective = (key: string): unknown => {\n const local = flatChildren.find((c) => c.key === key);\n if (!local) return effective(key);\n return groupValue[key] !== undefined ? groupValue[key] : local.default;\n };\n const visibleChildren = children.filter((c) => isParamVisible(c, groupEffective));\n const groupRenderOne = makeRenderOne(groupValue, groupSet, groupEffective, readOnly);\n\n return (\n <div className=\"w6w-stack\">\n <span className=\"w6w-section-title\">{param.label ?? param.key}</span>\n <div className=\"w6w-stack w6w-section-body\">\n {renderFieldRows(visibleChildren, groupRenderOne)}\n </div>\n </div>\n );\n}\n\n/**\n * A `repeat: true` param — sugar for `type: \"array\"` with a synthesized `item`\n * (rfcs/param.md's amendment); routes to the SAME `ArrayField` an explicit\n * `type: \"array\"` param uses, never a second list component:\n * - scalar (`param.type` is not `group`/`section`/`array`): `item = { type:\n * param.type, options: param.options }`, passed explicitly because\n * `ArrayField`'s own fallback (`param.item ?? { type: \"string\" }`) is the\n * literal `\"string\"`, not `param.type`.\n * - `type: \"group\"` with scalar-only `children` (the D-2 ceiling above):\n * `item = { type: \"object\", fields: param.children }`.\n * - `type: \"group\"` with no `children`, or any child the ceiling excludes:\n * falls back to the JSON editor for the whole group.\n */\nfunction RepeatField({\n param,\n value,\n onChange,\n readOnly,\n}: {\n param: ActionParam;\n value: unknown;\n onChange: (key: string, value: unknown) => void;\n readOnly?: boolean;\n}) {\n if (param.type === \"group\") {\n const children = param.children ?? [];\n if (!fitsArrayItemFields(children)) {\n return <JsonParamField param={param} value={value} onChange={onChange} readOnly={readOnly} />;\n }\n const synthesized: ActionParam = { ...param, item: { type: \"object\", fields: children } };\n return <ArrayField param={synthesized} value={value} onChange={onChange} readOnly={readOnly} />;\n }\n const synthesized: ActionParam = {\n ...param,\n item: { type: param.type, options: param.options },\n };\n return <ArrayField param={synthesized} value={value} onChange={onChange} readOnly={readOnly} />;\n}\n\n/** The Python default snippet for a `code` param when its sibling `language`\n * resolves to `\"python\"` (D-3) — a working `return input`-equivalent, same\n * shape/intent as `SCRIPT_APP`'s JS default in `flow-types.ts`. */\nconst PYTHON_CODE_DEFAULT = \"# Runs as a function body. Return the step's output.\\nreturn input\";\n\nfunction ParamField({\n param,\n value,\n onChange,\n effective,\n readOnly,\n}: {\n param: ActionParam;\n value: unknown;\n onChange: (key: string, value: unknown) => void;\n /** Sibling-value getter (D-1/D-3) — only the `code` branch reads it, to pick\n * the editor's language mode and default snippet from a sibling `language`\n * param, when one exists. */\n effective?: (key: string) => unknown;\n readOnly?: boolean;\n}) {\n const label = param.label ?? param.key;\n // A checkbox always carries a value (true/false), so \"required\" has no meaning\n // for it — don't decorate booleans with the required asterisk.\n const req = param.required && param.type !== \"boolean\" ? \" *\" : \"\";\n // Stable id so the INLINE variant's label can point at the control it names\n // (the label no longer wraps it — the ƒx sits between them).\n const controlId = useId();\n\n if (param.type === \"boolean\") {\n const current = Boolean(value ?? param.default ?? false);\n return (\n <FxField\n param={param}\n value={value}\n onChange={onChange}\n readOnly={readOnly}\n label={label}\n req={req}\n // A checkbox does NOT fill the field box a text input fills, so it opts\n // out of that box HERE, at the seam — the wrapper renders a different\n // class rather than having the chrome clawed back off by a more\n // specific rule. Layout becomes the row: <checkbox> <ƒx> <label>.\n variant=\"inline\"\n controlId={controlId}\n >\n <input\n id={controlId}\n type=\"checkbox\"\n checked={current}\n disabled={readOnly}\n onChange={(e) => onChange(param.key, e.target.checked)}\n />\n </FxField>\n );\n }\n\n // `json` and `group` params hold objects/arrays. Edit them as JSON so the\n // value round-trips faithfully instead of collapsing to \"[object Object]\".\n if (param.type === \"json\" || param.type === \"group\") {\n return <JsonParamField param={param} value={value} onChange={onChange} readOnly={readOnly} />;\n }\n\n // `code` — an inline script/snippet, edited in a real code editor. A sibling\n // `language` param (if one exists in this form) drives the editor's\n // CodeMirror mode. The default-snippet swap itself is no longer a render-time\n // guess (ROUND 1's approach): `ParamsForm`'s `set` (above) already writes the\n // swapped default into `values.code` the moment `language` changes (D-3,\n // ROUND 2 / B3), so by the time this renders, `value` is always the true\n // saved value — this is back to the same `value ?? fallbackDefault ?? \"\"`\n // shape the form used before `language` support existed, just with\n // `fallbackDefault` following the sibling language for the one case where\n // `value` is genuinely `undefined` (e.g. a `code` param that hasn't been\n // touched or seeded yet).\n if (param.type === \"code\") {\n const siblingLanguage = effective?.(\"language\");\n const language: ScriptLanguage | undefined =\n siblingLanguage === \"python\"\n ? \"python\"\n : siblingLanguage === \"javascript\"\n ? \"javascript\"\n : undefined;\n const fallbackDefault = language === \"python\" ? PYTHON_CODE_DEFAULT : param.default;\n const current = (value ?? fallbackDefault ?? \"\") as string;\n return (\n <div className=\"w6w-field\">\n <span>\n {label}\n {req}\n </span>\n <CodeEditor\n value={String(current)}\n readOnly={readOnly}\n minHeight=\"180px\"\n language={language}\n aria-label={`${param.key} code`}\n onChange={(next) => onChange(param.key, next)}\n />\n {param.hint && <span className=\"w6w-hint\">{param.hint}</span>}\n </div>\n );\n }\n\n // `vars` — a dynamic table of typed key/value variables.\n if (param.type === \"vars\") {\n return <VarsField param={param} value={value} onChange={onChange} readOnly={readOnly} />;\n }\n\n // Multi-line text: either the dedicated `text` type or any field the app\n // flagged `config.multiline` (e.g. a `string` message body as a textarea).\n if (param.type === \"text\" || param.config?.multiline) {\n const current = (value ?? param.default ?? \"\") as string;\n return (\n <FxField\n param={param}\n value={value}\n onChange={onChange}\n readOnly={readOnly}\n label={label}\n req={req}\n >\n <textarea\n rows={3}\n value={String(current)}\n readOnly={readOnly}\n aria-label={label}\n onChange={(e) => onChange(param.key, e.target.value)}\n />\n </FxField>\n );\n }\n\n // Multi-select: pick several options from a dropdown; each becomes a removable\n // pill. Value is an array of the chosen option values.\n if (param.type === \"multiselect\") {\n return <MultiSelectField param={param} value={value} onChange={onChange} readOnly={readOnly} />;\n }\n\n // `array` — a list control: a row per item (a scalar input, or an object's\n // fields side by side), with add/remove buttons.\n if (param.type === \"array\") {\n return <ArrayField param={param} value={value} onChange={onChange} readOnly={readOnly} />;\n }\n\n // A constrained set of choices renders as a dropdown — even for a `string`\n // param (e.g. an HTTP method). Driven by `param.options` in the config.\n if (Array.isArray(param.options) && param.options.length > 0) {\n const current = value ?? param.default ?? param.options[0]?.value ?? \"\";\n const isNumber = param.type === \"number\";\n return (\n <FxField\n param={param}\n value={value}\n onChange={onChange}\n readOnly={readOnly}\n label={label}\n req={req}\n >\n <select\n value={String(current)}\n disabled={readOnly}\n aria-label={label}\n onChange={(e) => onChange(param.key, isNumber ? Number(e.target.value) : e.target.value)}\n >\n {param.options.map((o) => (\n <option key={String(o.value)} value={String(o.value)}>\n {o.label}\n </option>\n ))}\n </select>\n </FxField>\n );\n }\n\n // `secret` — an encrypted / expression-capable field. Rendered via the\n // segmented ExpressionInput (masked): the value may be a plain string, an\n // `{type:\"expr\"}` envelope, or an at-rest `{type:\"secret\"}` (shown as `***`,\n // never the ciphertext). The var/secret picker data source is wired later\n // (task 3.2) via the `options` prop.\n //\n // General (non-secret) scalar fields get their own expression mode via the\n // `fx` toggle on {@link FxField} — the plain widget stays the default there.\n if (param.type === \"secret\") {\n const current = (value ?? param.default) as ExprValue | string | SecretValue | undefined;\n return (\n <div className=\"w6w-field\">\n <span>\n {label}\n {req}\n </span>\n <ExpressionInput\n value={current}\n masked\n readOnly={readOnly}\n aria-label={label}\n onChange={(next) => onChange(param.key, next)}\n />\n {param.hint && <span className=\"w6w-hint\">{param.hint}</span>}\n </div>\n );\n }\n\n // Plain text / number input for everything else.\n const inputType = param.type === \"number\" ? \"number\" : \"text\";\n const raw = value ?? param.default ?? \"\";\n // Guard against object/array values landing in a text field (they'd render as\n // \"[object Object]\"); show them JSON-stringified instead.\n const display = typeof raw === \"object\" && raw !== null ? JSON.stringify(raw) : String(raw ?? \"\");\n return (\n <FxField\n param={param}\n value={value}\n onChange={onChange}\n readOnly={readOnly}\n label={label}\n req={req}\n >\n <input\n type={inputType}\n value={display}\n readOnly={readOnly}\n aria-label={label}\n autoComplete=\"off\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n data-1p-ignore=\"true\"\n data-lpignore=\"true\"\n data-bwignore=\"true\"\n data-form-type=\"other\"\n onChange={(e) =>\n onChange(param.key, param.type === \"number\" ? Number(e.target.value) : e.target.value)\n }\n />\n </FxField>\n );\n}\n\n/**\n * Wraps a general scalar field (text/number `input`, `textarea`, or an\n * `options` dropdown) with an `fx` affordance: a small ƒx at the end of the\n * field opens the {@link ExpressionEditorModal}, so an author can bind the field\n * to a variable/expression instead of a literal. Mirrors the `secret`-param\n * path, which already renders {@link ExpressionInput}.\n *\n * The plain widget is the DEFAULT: a number/select round-trips as its original\n * scalar until the author actually SAVES an expression from the modal (gap #6).\n * The engine's `resolveWith` accepts an `ExprValue` or a literal for any `with`\n * value, so a stored expression round-trips without an engine change.\n *\n * ONE ƒx, ONE click. Plain mode renders the plain widget plus the single ƒx\n * button below, which opens the modal WITHOUT writing to the form. Expression\n * mode renders `ExpressionInput`, whose own ƒx reopens the same modal — so the\n * field never shows two ƒx controls at once.\n *\n * TWO CHROME VARIANTS, picked by the CALLER from the control it is passing:\n * `\"boxed\"` (default) is the text-field box above — right for any widget that\n * FILLS the box (input, textarea, select, the multiselect chip box). `\"inline\"`\n * is for a widget that does not: a `boolean`'s ~13px checkbox left the rest of a\n * full-width panel empty. The inline variant renders a DIFFERENT wrapper class\n * (`.w6w-fx-inline`, which simply declares no chrome) instead of over-riding\n * `.w6w-fx-wrap` with a more specific rule, and lays the row out as the review\n * asked: `<checkbox> <ƒx> <label>`, with no stacked label above it.\n */\nfunction FxField({\n param,\n value,\n onChange,\n readOnly,\n label,\n req,\n bare,\n variant = \"boxed\",\n controlId,\n children,\n}: {\n param: ActionParam;\n value: unknown;\n onChange: (key: string, value: unknown) => void;\n readOnly?: boolean;\n label: string;\n req: string;\n /** Render only the toggle + widget (no label/hint chrome) — for compact\n * cells such as a `vars` row value that already live inside their own grid. */\n bare?: boolean;\n /** Chrome + layout of the wrapper. See the note above: `\"inline\"` is for a\n * control that does not fill a text-field box (today: a checkbox). */\n variant?: \"boxed\" | \"inline\";\n /** `id` of the control `children` renders, so the inline row's label can name\n * it (`htmlFor`) — the label is a sibling there, not a wrapper. */\n controlId?: string;\n children: ReactNode;\n}) {\n // Expression mode is DERIVED from the stored value — never a local flag.\n // Nothing turns a local boolean back off now that the value-mutating toggle is\n // gone, so it would drift: the field would read as an expression while holding\n // a plain string (or the reverse). Deriving makes control and value unable to\n // disagree BY CONSTRUCTION, and Cancel-leaves-the-field-plain falls out for\n // free — the modal's `onClose` writes nothing, so `value`, and therefore `fx`,\n // is unchanged. A value that arrives after mount (a saved test seeded into a\n // field that mounted empty) is picked up on the next render, no effect needed.\n const fx = isExprValue(value);\n // Multi-line text fields keep their newlines in expression mode too: Enter\n // inserts a literal \"\\n\" instead of being swallowed. Same predicate the\n // textarea branch above renders on, so the two can never disagree.\n const multiline = param.type === \"text\" || !!param.config?.multiline;\n const [modalOpen, setModalOpen] = useState(false);\n // Picker data (vars/secrets/steps/…) — sourced exactly the way ExpressionInput\n // sources it, from the nearest ExpressionOptionsProvider.\n const exprOptions = useExpressionOptions();\n\n // The ƒx rides at the end of the input (an in-field decoration) rather than up\n // in the label row — so the affordance sits next to the value it governs. It\n // OPENS THE MODAL and writes nothing; the value only changes if the author\n // saves from there.\n //\n // `.w6w-fx-wrap` IS the field's box: it owns the border/background/radius and\n // the `:focus-within` ring, and the widget it holds is flattened by compound\n // selectors in styles.css — so widget + ƒx read as one box, not as a button\n // beside a field. A widget that owns a box itself (`.w6w-multiselect`, the\n // `.w6w-expr-field` inside ExpressionInput) is flattened there too.\n //\n // The inline variant applies to the PLAIN widget only: once the field holds\n // an expression it renders `ExpressionInput`, which IS a text-like control\n // that fills a box — so it goes back to the standard boxed field with its\n // label above, exactly like every other expression-bound field.\n const inline = variant === \"inline\" && !fx;\n const body = (\n <>\n <div className={inline ? \"w6w-fx-inline\" : `w6w-fx-wrap${fx ? \" is-fx\" : \"\"}`}>\n {fx ? (\n // Expression mode: ExpressionInput already carries the ONE ƒx here\n // (its own edit button), which reopens this same modal. Rendering a\n // second one would put two ƒx side by side — the bug the intake filed.\n <ExpressionInput\n value={value as ExprValue | string | undefined}\n multiline={multiline}\n readOnly={readOnly}\n aria-label={label}\n onChange={(next) => onChange(param.key, next)}\n />\n ) : (\n <>\n {children}\n {!readOnly && (\n <button\n type=\"button\"\n className=\"w6w-expr-fx\"\n title=\"Use an expression\"\n aria-label={`Use an expression for ${label}`}\n onClick={() => setModalOpen(true)}\n >\n ƒx\n </button>\n )}\n {/* Inline variant: the label rides HERE, after the ƒx — it is the\n field's ONLY label (the stacked one below is not rendered). */}\n {inline && (\n <label className=\"w6w-fx-inline-label\" htmlFor={controlId}>\n {label}\n {req}\n </label>\n )}\n </>\n )}\n </div>\n {modalOpen && (\n // The modal owns the whole round trip — it seeds itself from `value` and\n // commits through the shared template helpers in its own save. Nothing\n // is re-implemented here: this supplies the value and consumes `onSave`.\n <ExpressionEditorModal\n value={value as ExprValue | string | undefined}\n multiline={multiline}\n options={exprOptions}\n fieldLabel={label}\n onSave={(next) => onChange(param.key, next)}\n onClose={() => setModalOpen(false)}\n />\n )}\n </>\n );\n\n // Bare: just the toggle + widget, no label/hint chrome (the host cell owns them).\n if (bare) return body;\n\n return (\n <div className=\"w6w-field\">\n {/* Inline: the label lives INSIDE the row (above), so the stacked one is\n not rendered at all — one label per field, never two. */}\n {!inline && (\n <span>\n {label}\n {req}\n </span>\n )}\n {body}\n {param.hint && <span className=\"w6w-hint\">{param.hint}</span>}\n </div>\n );\n}\n\n/**\n * A `json`-typed param edited through the JsonEditor. Holds its own text state\n * (seeded from the incoming value) and only pushes back to the form when the\n * text parses — an invalid draft doesn't corrupt the collected values.\n */\nfunction JsonParamField({\n param,\n value,\n onChange,\n readOnly,\n}: {\n param: ActionParam;\n value: unknown;\n onChange: (key: string, value: unknown) => void;\n readOnly?: boolean;\n}) {\n // \"Bound\" is DERIVED from the stored value on every render — never a local\n // flag — so control and value cannot disagree (same stance as `FxField`'s `fx`).\n const bound = isDollarPath(value) && typeof value.$ === \"string\";\n const boundRef = bound ? String((value as { $: string }).$) : \"\";\n const seed = value ?? param.default;\n // The draft is NEVER seeded from a binding (R-18a): Clear must be able to give\n // back the literal JSON the author had, or \"\" if there was none.\n const [text, setText] = useState(() =>\n bound || seed === undefined ? \"\" : JSON.stringify(seed, null, 2),\n );\n const [invalid, setInvalid] = useState(false);\n const [expanded, setExpanded] = useState(false);\n const [pickerOpen, setPickerOpen] = useState(false);\n const exprOptions = useExpressionOptions();\n\n // Re-seed when the field identity changes OR the incoming value changes to\n // something other than what the current draft already represents — i.e. an\n // external load (a saved test opened into an already-mounted JSON field), not\n // the echo of the user's own valid edit. Comparing against the parsed draft\n // avoids clobbering the cursor/formatting on every keystroke.\n // biome-ignore lint/correctness/useExhaustiveDependencies: `text` is read as the draft baseline but must NOT retrigger the effect (that would reseed mid-edit); reseed is keyed on the incoming value + param identity\n useEffect(() => {\n if (bound) return; // keep the held draft so Clear can restore it\n let current: unknown;\n try {\n current = text.trim() === \"\" ? undefined : JSON.parse(text);\n } catch {\n current = undefined; // invalid draft — let an external value win\n }\n if (JSON.stringify(current) !== JSON.stringify(seed)) {\n setText(seed === undefined ? \"\" : JSON.stringify(seed, null, 2));\n setInvalid(false);\n }\n }, [seed, param.key, bound]);\n\n const onEdit = (next: string) => {\n setText(next);\n };\n const onValid = (parsed: unknown) => {\n setInvalid(false);\n onChange(param.key, parsed);\n };\n const label = param.label ?? param.key;\n\n // Clear: back to the literal JSON the editor still holds (undefined if the\n // draft is empty or does not parse). Exactly one onChange.\n const clear = () => {\n let restored: unknown;\n try {\n restored = text.trim() === \"\" ? undefined : JSON.parse(text);\n } catch {\n restored = undefined;\n }\n onChange(param.key, restored);\n };\n // Preview: the bound ref resolved against the host's sample values. The flow\n // editor seeds `steps.<id>.output` as a flat key, which `resolveRef` does not\n // read for `steps.*`, so the nested `steps` scope is built from those keys.\n const preview = (() => {\n if (!bound) return \"\";\n const steps: Record<string, { output?: unknown }> = {};\n for (const [ref, v] of Object.entries(exprOptions.sampleValues ?? {})) {\n const m = /^steps\\.([^.]+)\\.output$/.exec(ref);\n if (m) steps[m[1]] = { output: v };\n }\n return JSON.stringify(\n resolveParamJson(value, buildResolveScope(undefined, { steps })),\n null,\n 2,\n );\n })();\n\n return (\n <div className=\"w6w-field\">\n <span className=\"w6w-field-labelrow\">\n <span>\n {label}\n {param.required ? \" *\" : \"\"}\n </span>\n {!readOnly && !bound && (\n <button\n type=\"button\"\n className=\"w6w-expr-fx\"\n title=\"Use an expression\"\n aria-label={`Use an expression for ${label}`}\n onClick={() => setPickerOpen(true)}\n >\n ƒx\n </button>\n )}\n {!bound && (\n <button\n type=\"button\"\n className=\"w6w-icon-btn w6w-btn-sm\"\n title=\"Open in full view\"\n aria-label={`Open ${label} in full view`}\n onClick={() => setExpanded(true)}\n >\n {/* `icons.tsx`'s `maximize` — Feather `maximize-2`'s diagonal expand arrows on a\n 24×24 viewBox, drawn at 14px. */}\n <Icon name=\"maximize\" size={14} />\n </button>\n )}\n </span>\n {/* Inline: content-sized, grows with content up to maxHeight, then scrolls\n internally (so it never overlaps the next field). Full view via button. */}\n {bound ? (\n <div className=\"w6w-json-binding\">\n <div className=\"w6w-fx-wrap is-fx\">\n <code>{boundRef}</code>\n {!readOnly && (\n <>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n onClick={() => setPickerOpen(true)}\n >\n Edit\n </button>\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\" onClick={clear}>\n Clear\n </button>\n </>\n )}\n </div>\n <pre\n className=\"w6w-json-binding-preview\"\n data-testid=\"json-binding-preview\"\n style={{ margin: 0, maxHeight: 260, overflow: \"auto\", fontSize: \"0.85em\" }}\n >\n {preview}\n </pre>\n </div>\n ) : (\n <JsonEditor\n value={text}\n onChange={onEdit}\n readOnly={readOnly}\n minHeight=\"34px\"\n maxHeight=\"260px\"\n aria-label={`${param.key} JSON`}\n onValidChange={onValid}\n onValidityChange={({ valid }) => setInvalid(!valid)}\n />\n )}\n {pickerOpen && (\n <ExpressionEditorModal\n mode=\"json-binding\"\n value={undefined}\n options={exprOptions}\n fieldLabel={label}\n onBind={(next) => onChange(param.key, next)}\n onClose={() => setPickerOpen(false)}\n />\n )}\n {!bound && invalid && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n Invalid JSON\n </span>\n )}\n {param.hint && <span className=\"w6w-hint\">{param.hint}</span>}\n\n {expanded && !bound && (\n <Modal\n title={label}\n subtitle={<code>JSON</code>}\n size=\"wide\"\n onClose={() => setExpanded(false)}\n >\n <div className=\"w6w-json-fullview\">\n <JsonEditor\n value={text}\n onChange={onEdit}\n readOnly={readOnly}\n height=\"100%\"\n minHeight=\"360px\"\n aria-label={`${param.key} JSON (full view)`}\n onValidChange={onValid}\n onValidityChange={({ valid }) => setInvalid(!valid)}\n />\n </div>\n {invalid && (\n <span className=\"w6w-hint\" style={{ color: \"var(--w6w-danger)\" }}>\n Invalid JSON\n </span>\n )}\n </Modal>\n )}\n </div>\n );\n}\n\n/**\n * A `multiselect` param — a Material-style chips input: the chosen options render\n * as removable chips *inside* a single input-like box, followed by a dropdown\n * (reading as placeholder text) that appends more. Value is an array of the\n * chosen option values; the dropdown only lists options not already selected.\n */\nfunction MultiSelectField({\n param,\n value,\n onChange,\n readOnly,\n}: {\n param: ActionParam;\n value: unknown;\n onChange: (key: string, value: unknown) => void;\n readOnly?: boolean;\n}) {\n const options = Array.isArray(param.options) ? param.options : [];\n const selected: Array<string | number> = Array.isArray(value)\n ? (value as Array<string | number>)\n : Array.isArray(param.default)\n ? (param.default as Array<string | number>)\n : [];\n const selectedKeys = new Set(selected.map(String));\n const available = options.filter((o) => !selectedKeys.has(String(o.value)));\n const labelFor = (v: string | number) =>\n options.find((o) => String(o.value) === String(v))?.label ?? String(v);\n\n const add = (raw: string) => {\n if (!raw || selectedKeys.has(raw)) return;\n const opt = options.find((o) => String(o.value) === raw);\n onChange(param.key, [...selected, opt ? opt.value : raw]);\n };\n const remove = (v: string | number) =>\n onChange(\n param.key,\n selected.filter((x) => String(x) !== String(v)),\n );\n\n const placeholder =\n typeof param.placeholder === \"string\" && param.placeholder ? param.placeholder : \"Select…\";\n const label = param.label ?? param.key;\n const req = param.required ? \" *\" : \"\";\n\n return (\n <FxField\n param={param}\n value={value}\n onChange={onChange}\n readOnly={readOnly}\n label={label}\n req={req}\n >\n {/* One input-like box: chips inline, then the dropdown as the trailing\n placeholder — chips appear to live inside the field's boundaries. The\n ƒx toggle (via FxField) swaps the whole box for an expression. */}\n <div className={`w6w-multiselect${readOnly ? \" is-readonly\" : \"\"}`}>\n {selected.map((v) => (\n <span className=\"w6w-chip\" key={String(v)}>\n {labelFor(v)}\n {!readOnly && (\n <button\n type=\"button\"\n className=\"w6w-chip-x\"\n aria-label={`Remove ${labelFor(v)}`}\n title=\"Remove\"\n onClick={() => remove(v)}\n >\n ×\n </button>\n )}\n </span>\n ))}\n {!readOnly && (\n // Controlled to \"\" so it always reads as the trailing placeholder;\n // picking an option appends a chip and resets.\n <select\n className=\"w6w-multiselect-add\"\n value=\"\"\n disabled={available.length === 0}\n aria-label={`Add to ${param.label ?? param.key}`}\n onChange={(e) => add(e.target.value)}\n >\n <option value=\"\">\n {available.length > 0\n ? selected.length\n ? \"Add more…\"\n : placeholder\n : \"All selected\"}\n </option>\n {available.map((o) => (\n <option key={String(o.value)} value={String(o.value)}>\n {o.label}\n </option>\n ))}\n </select>\n )}\n </div>\n </FxField>\n );\n}\n\n/** A single input inside an `array` object-item row (placeholder = the field label). */\nfunction ArrayItemInput({\n field,\n value,\n onChange,\n readOnly,\n}: {\n field: ActionParam;\n value: unknown;\n onChange: (v: unknown) => void;\n readOnly?: boolean;\n}) {\n const ph = field.placeholder ?? field.label ?? field.key;\n if (Array.isArray(field.options) && field.options.length > 0) {\n return (\n <select\n className=\"w6w-array-input\"\n value={String(value ?? field.default ?? field.options[0]?.value ?? \"\")}\n disabled={readOnly}\n aria-label={field.label ?? field.key}\n onChange={(e) => onChange(e.target.value)}\n >\n {field.options.map((o) => (\n <option key={String(o.value)} value={String(o.value)}>\n {o.label}\n </option>\n ))}\n </select>\n );\n }\n if (field.type === \"boolean\") {\n return (\n <label className=\"w6w-array-check\" title={field.label ?? field.key}>\n <input\n type=\"checkbox\"\n checked={Boolean(value ?? field.default ?? false)}\n disabled={readOnly}\n aria-label={field.label ?? field.key}\n onChange={(e) => onChange(e.target.checked)}\n />\n <span>{field.label ?? field.key}</span>\n </label>\n );\n }\n const isNumber = field.type === \"number\";\n return (\n <input\n className=\"w6w-array-input\"\n type={isNumber ? \"number\" : \"text\"}\n value={String(value ?? field.default ?? \"\")}\n placeholder={ph}\n aria-label={field.label ?? field.key}\n readOnly={readOnly}\n onChange={(e) => onChange(isNumber ? Number(e.target.value) : e.target.value)}\n />\n );\n}\n\n/**\n * An `array`-typed param — a list control. Each row is either a single scalar\n * input (`item.type: \"string\" | \"number\"`) or an object's `fields` side by side\n * (`item.type: \"object\"`). \"+ Add\" appends a blank item; each row has an `×`.\n */\nfunction ArrayField({\n param,\n value,\n onChange,\n readOnly,\n}: {\n param: ActionParam;\n value: unknown;\n onChange: (key: string, value: unknown) => void;\n readOnly?: boolean;\n}) {\n const item = param.item ?? { type: \"string\" };\n const isObject = item.type === \"object\";\n const items: unknown[] = Array.isArray(value)\n ? value\n : Array.isArray(param.default)\n ? (param.default as unknown[])\n : [];\n const commit = (next: unknown[]) => onChange(param.key, next);\n const blank = (): unknown =>\n isObject\n ? Object.fromEntries((item.fields ?? []).map((f) => [f.key, f.default ?? \"\"]))\n : item.type === \"number\"\n ? 0\n : \"\";\n const patchAt = (idx: number, next: unknown) =>\n commit(items.map((it, j) => (j === idx ? next : it)));\n\n return (\n <div className=\"w6w-field\">\n <span>\n {param.label ?? param.key}\n {param.required ? \" *\" : \"\"}\n </span>\n <div className=\"w6w-array\">\n {items.length === 0 && <p className=\"w6w-muted w6w-small\">None yet — add one below.</p>}\n {items.map((it, idx) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: rows have no stable id; values are user-edited\n <div className=\"w6w-array-row\" key={idx}>\n {isObject ? (\n <div className=\"w6w-array-cells\">\n {(item.fields ?? []).map((f) => (\n <ArrayItemInput\n key={f.key}\n field={f}\n value={(it as Record<string, unknown>)?.[f.key]}\n readOnly={readOnly}\n onChange={(fv) =>\n patchAt(idx, { ...((it as Record<string, unknown>) ?? {}), [f.key]: fv })\n }\n />\n ))}\n </div>\n ) : (\n <input\n className=\"w6w-array-input\"\n type={item.type === \"number\" ? \"number\" : \"text\"}\n value={String(it ?? \"\")}\n placeholder={item.placeholder}\n readOnly={readOnly}\n onChange={(e) =>\n patchAt(idx, item.type === \"number\" ? Number(e.target.value) : e.target.value)\n }\n />\n )}\n {!readOnly && (\n <button\n type=\"button\"\n className=\"w6w-array-x\"\n aria-label=\"Remove item\"\n title=\"Remove\"\n onClick={() => commit(items.filter((_, j) => j !== idx))}\n >\n ×\n </button>\n )}\n </div>\n ))}\n {!readOnly && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm w6w-array-add\"\n onClick={() => commit([...items, blank()])}\n >\n + Add\n </button>\n )}\n </div>\n {param.hint && <span className=\"w6w-hint\">{param.hint}</span>}\n </div>\n );\n}\n\n/**\n * One typed key/value entry in a `vars` param. `type` is a real value type only:\n * `expression` is a binding *mode* (see {@link FxField}/`ExprValue`), not a value\n * type, so it is no longer offered in the dropdown. Each row value carries its own\n * ƒx toggle (via {@link FxField} in `bare` mode), so any declared type can be bound\n * to an expression; a legacy row persisted with `type:\"expression\"` (an `ExprValue`)\n * still round-trips — FxField opens it in expression mode from the stored value.\n */\nexport interface DataVar {\n key: string;\n type: \"string\" | \"number\" | \"boolean\" | \"json\";\n value: unknown;\n}\n\nconst DATA_VAR_TYPES: DataVar[\"type\"][] = [\"string\", \"number\", \"boolean\", \"json\"];\n\n/** Coerce a text input into the variable's declared type (best-effort). */\nfunction coerceVarValue(type: DataVar[\"type\"], raw: string): unknown {\n if (type === \"number\") {\n if (raw.trim() === \"\") return \"\";\n const n = Number(raw);\n return Number.isNaN(n) ? raw : n;\n }\n if (type === \"boolean\") return raw === \"true\";\n if (type === \"json\") {\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n }\n return raw;\n}\n\n/** Render a stored variable value back into an editable string. */\nfunction varValueToText(v: unknown): string {\n if (v === undefined || v === null) return \"\";\n if (typeof v === \"object\") return JSON.stringify(v);\n return String(v);\n}\n\n/**\n * A `vars`-typed param: a dynamic table of typed key/value variables. The value\n * is an array of `{ key, type, value }`, collected into the step's `with`.\n */\nfunction VarsField({\n param,\n value,\n onChange,\n readOnly,\n}: {\n param: ActionParam;\n value: unknown;\n onChange: (key: string, value: unknown) => void;\n readOnly?: boolean;\n}) {\n const vars: DataVar[] = Array.isArray(value)\n ? (value as DataVar[])\n : Array.isArray(param.default)\n ? (param.default as DataVar[])\n : [];\n const commit = (next: DataVar[]) => onChange(param.key, next);\n const patch = (i: number, p: Partial<DataVar>) =>\n commit(vars.map((v, idx) => (idx === i ? { ...v, ...p } : v)));\n\n return (\n <div className=\"w6w-field\">\n <span>\n {param.label ?? param.key}\n {param.required ? \" *\" : \"\"}\n </span>\n <div className=\"w6w-stack\">\n {vars.length === 0 && (\n <p className=\"w6w-muted w6w-small\">No variables yet — add one below.</p>\n )}\n {vars.map((v, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: rows have no stable id; keys/values are user-edited\n <div className=\"w6w-datavar-row\" key={i}>\n <input\n type=\"text\"\n placeholder=\"key\"\n value={v.key}\n readOnly={readOnly}\n onChange={(e) => patch(i, { key: e.target.value })}\n />\n <select\n value={v.type}\n disabled={readOnly}\n onChange={(e) => {\n const type = e.target.value as DataVar[\"type\"];\n patch(i, { type, value: coerceVarValue(type, varValueToText(v.value)) });\n }}\n >\n {DATA_VAR_TYPES.map((t) => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n {/* Per-value ƒx toggle: any declared type can be bound to an\n expression (stored as an `{type:\"expr\"}` envelope, resolved\n against the run scope before the data node runs). A legacy\n `type:\"expression\"` row (an ExprValue) reopens in fx mode from\n its stored value. `bare` drops the field chrome so the widget\n fits the row's grid cell. */}\n <FxField\n bare\n param={param}\n value={v.value}\n onChange={(_key, next) => patch(i, { value: next })}\n readOnly={readOnly}\n label={v.key || \"value\"}\n req=\"\"\n >\n {v.type === \"boolean\" ? (\n <select\n value={v.value === true ? \"true\" : \"false\"}\n disabled={readOnly}\n onChange={(e) => patch(i, { value: e.target.value === \"true\" })}\n >\n <option value=\"true\">true</option>\n <option value=\"false\">false</option>\n </select>\n ) : (\n <input\n type={v.type === \"number\" ? \"number\" : \"text\"}\n placeholder=\"value\"\n value={varValueToText(v.value)}\n readOnly={readOnly}\n onChange={(e) => patch(i, { value: coerceVarValue(v.type, e.target.value) })}\n />\n )}\n </FxField>\n {!readOnly && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n aria-label={`Remove variable ${v.key || i + 1}`}\n title=\"Remove\"\n onClick={() => commit(vars.filter((_, idx) => idx !== i))}\n >\n ×\n </button>\n )}\n </div>\n ))}\n {!readOnly && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n onClick={() => commit([...vars, { key: \"\", type: \"string\", value: \"\" }])}\n >\n + Add variable\n </button>\n )}\n </div>\n {param.hint && <span className=\"w6w-hint\">{param.hint}</span>}\n </div>\n );\n}\n","import { useState } from \"react\";\nimport { ParamsForm } from \"./ParamsForm.tsx\";\n\nconst units = [\n [\"s\", \"Seconds\"],\n [\"m\", \"Minutes\"],\n [\"h\", \"Hours\"],\n [\"d\", \"Days\"],\n [\"w\", \"Weeks\"],\n];\nconst durationPattern =\n /^(?=\\d)(?:\\d+w)?(?:\\d+d)?(?:\\d+h)?(?:\\d+m)?(?:\\d+(?:\\.\\d+)?s)?$|^P(?:\\d+W)?(?:\\d+D)?(?:T(?=\\d)(?:\\d+H)?(?:\\d+M)?(?:\\d+(?:\\.\\d+)?S)?)?$/i;\n\n/** Both input modes write the same duration field; switching never discards a compound value. */\nexport function WaitEditor({\n values,\n onChange,\n readOnly,\n}: {\n values: Record<string, unknown>;\n onChange: (values: Record<string, unknown>) => void;\n readOnly?: boolean;\n}) {\n const duration = values.duration ?? \"1s\";\n const single =\n typeof duration === \"string\" ? duration.match(/^(\\d+(?:\\.\\d+)?)([smhdw])$/i) : null;\n const [lastUnit, setLastUnit] = useState(\"s\");\n const [mode, setMode] = useState<\"text\" | \"value\">(\"text\");\n const [target, setTarget] = useState<\"duration\" | \"until\">(values.until ? \"until\" : \"duration\");\n const invalid =\n typeof duration === \"string\" &&\n (!durationPattern.test(duration.trim()) || /^P$/i.test(duration.trim()));\n return (\n <div className=\"w6w-params-form\">\n <label>\n Wait for\n <select\n aria-label=\"Wait for\"\n disabled={readOnly}\n value={target}\n onChange={(e) => {\n const next = e.target.value as \"duration\" | \"until\";\n setTarget(next);\n onChange({\n ...values,\n duration: next === \"duration\" ? \"1s\" : \"\",\n until: \"\",\n });\n }}\n >\n <option value=\"duration\">A duration</option>\n <option value=\"until\">Until a timestamp</option>\n </select>\n </label>\n {target === \"until\" ? (\n <ParamsForm\n params={[\n {\n key: \"until\",\n label: \"Until\",\n type: \"string\",\n hint: \"ISO-8601 timestamp, e.g. 2026-10-08T09:00:00Z.\",\n },\n ]}\n values={values}\n onChange={onChange}\n readOnly={readOnly}\n />\n ) : (\n <>\n <label>\n Duration input\n <select\n aria-label=\"Duration input\"\n disabled={readOnly}\n value={mode}\n onChange={(e) => {\n if (single) {\n setLastUnit(single?.[2].toLowerCase() ?? lastUnit);\n }\n setMode(e.target.value as \"text\" | \"value\");\n }}\n >\n <option value=\"text\">Shorthand</option>\n <option value=\"value\" disabled={!single}>\n Value and unit\n </option>\n </select>\n </label>\n {mode === \"value\" ? (\n <div className=\"w6w-field-row\">\n <label>\n Value\n <input\n aria-label=\"Duration value\"\n type=\"number\"\n min=\"0\"\n step={(single?.[2].toLowerCase() ?? lastUnit) === \"s\" ? \"any\" : \"1\"}\n disabled={readOnly}\n value={single?.[1] ?? \"\"}\n onChange={(e) =>\n onChange({\n ...values,\n duration: `${e.target.value}${single?.[2].toLowerCase() ?? lastUnit}`,\n })\n }\n />\n </label>\n <label>\n Unit\n <select\n aria-label=\"Duration unit\"\n disabled={readOnly}\n value={single?.[2].toLowerCase() ?? lastUnit}\n onChange={(e) => {\n setLastUnit(e.target.value);\n onChange({\n ...values,\n duration: `${single?.[1] ?? \"\"}${e.target.value}`,\n });\n }}\n >\n {units.map(([value, label]) => (\n <option key={value} value={value}>\n {label}\n </option>\n ))}\n </select>\n </label>\n </div>\n ) : (\n <ParamsForm\n params={[\n {\n key: \"duration\",\n label: \"Duration\",\n type: \"string\",\n default: \"1s\",\n hint: \"Use 30s, 1h30m30s, or 3d30s. Units: w, d, h, m, s, in that order. Uppercase and ISO-8601 also work. Value and unit is available for single-unit durations.\",\n },\n ]}\n values={values}\n onChange={onChange}\n readOnly={readOnly}\n />\n )}\n {invalid && (\n <p role=\"alert\">\n Enter a duration such as 30s or 1h30m30s, using units w, d, h, m, s in order.\n </p>\n )}\n </>\n )}\n </div>\n );\n}\n","/**\n * Pure category-derivation + label logic for `AppPicker`'s opt-in category\n * filter (T1.1.1). No React import — usable from a plain unit test and from\n * the real-browser `test/picker-layout` gate's bundle alike.\n *\n * Two things are MIRRORED, not imported (`ui` sits upstream of both `studio`\n * and `frontend` in the package dependency graph, so neither is reachable):\n *\n * - filter LOGIC — `packages/studio/src/pages/AppsPage.tsx:110-197`:\n * `selectedCats: string[]`, empty array means \"all\", OR-across-selected\n * membership (an app matches if it carries ANY selected slug).\n * - label ALGORITHM — `packages/frontend/packages/web/src/lib/categories.ts:65-74`:\n * split on `[-_\\s]+`, capitalize each word, join with spaces.\n *\n * D-4 (project DECISIONS.md): no 31-slug transcription of `rfcs/categories.md`.\n * Only the handful of acronyms/irregulars the mechanical algorithm gets wrong\n * carry an explicit override; every other slug — including one the RFC's own\n * vocabulary doesn't list, e.g. the live `sales` value — falls through to the\n * algorithm and renders as a readable (if unofficial) label, never a throw.\n */\nimport type { AppSummary } from \"./types.ts\";\n\n/**\n * Slugs where hyphen/underscore-split + per-word title-case produces the\n * wrong reading (an acronym, or a mid-word capital). Exactly the five the\n * live catalog needs (`building-blocks.md` §3) — not a transcription of the\n * RFC's full label table.\n */\nconst LABEL_OVERRIDES: Readonly<Record<string, string>> = {\n ai: \"AI\",\n cms: \"CMS\",\n crm: \"CRM\",\n hr: \"HR\",\n devops: \"DevOps\",\n};\n\n/**\n * Display label for a category slug. A known override wins; otherwise the\n * slug is split on `-`/`_`/whitespace and each word is capitalized. Never\n * throws — an empty/non-string slug renders as `\"\"`, and any out-of-\n * vocabulary slug still gets a readable (title-cased) label.\n *\n * @example\n * categoryLabel(\"crm\"); // \"CRM\" (override)\n * categoryLabel(\"project-management\"); // \"Project Management\"\n * categoryLabel(\"sales\"); // \"Sales\" (out-of-vocabulary, still safe)\n */\nexport function categoryLabel(slug: string): string {\n if (typeof slug !== \"string\" || slug.trim() === \"\") return \"\";\n const known = LABEL_OVERRIDES[slug];\n if (known) return known;\n return slug\n .split(/[-_\\s]+/)\n .filter(Boolean)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\" \");\n}\n\n/** One category chip's derived data — a slug, its display label, and how\n * many of the supplied apps carry it. */\nexport interface CategoryChip {\n slug: string;\n label: string;\n count: number;\n}\n\n/**\n * Distinct category slugs present across `apps`, each with its app count.\n * Ordered by count DESCENDING; ties break on the derived LABEL, ascending\n * (a deterministic order — never insertion/slug order, which would vary with\n * the catalog's own listing order).\n *\n * Derive from the caller's already-visible catalog (post any `filter` prop),\n * never from the full RFC vocabulary — a category with nothing behind it in\n * the current list is a dead end (D-1a).\n */\nexport function deriveCategories(apps: readonly AppSummary[]): CategoryChip[] {\n const counts = new Map<string, number>();\n for (const app of apps) {\n for (const slug of app.categories ?? []) {\n counts.set(slug, (counts.get(slug) ?? 0) + 1);\n }\n }\n return [...counts.entries()]\n .map(([slug, count]) => ({ slug, label: categoryLabel(slug), count }))\n .sort(\n (a, b) =>\n b.count - a.count || a.label.localeCompare(b.label, undefined, { sensitivity: \"base\" }),\n );\n}\n\n/**\n * Whether `app` matches a set of selected category slugs. An EMPTY selection\n * means \"all\" (every app matches); a non-empty selection is OR-across-\n * selected — the app matches if it carries ANY of the selected slugs. Mirrors\n * `AppsPage.tsx`'s `cats.size === 0 ? … : appCats.some((c) => cats.has(c))`.\n */\nexport function matchesCategories(app: AppSummary, selected: readonly string[]): boolean {\n if (selected.length === 0) return true;\n const cats = app.categories ?? [];\n return selected.some((slug) => cats.includes(slug));\n}\n","/**\n * Minimal Workflow shape the flow editor operates on. Deliberately a subset of\n * `@w6w/workflow-types` so the ui lib doesn't pin partners to a specific engine\n * package version — consumers who already have `Workflow` from\n * `@w6w/workflow-types` are structurally compatible.\n */\n\n// T1.1.1 — `edgeVisuals`'s run-state argument; see `run-visuals.ts`.\nimport type { EdgeRunState } from \"./run-visuals.ts\";\n\nexport interface FlowStep {\n id: string;\n uses: { app: string; action: string; connection?: string | null };\n /**\n * Declared connection-port cardinality for this step (see core\n * `rfcs/node-types.md` · Ports & cardinality). Omitted fields fall through field-wise to the catalog action, the internal def, then `{ in: 1, out: \"many\" }`.\n * A persisted value wins over the node's default — `in > 1` opts the step into\n * accepting multiple inbound edges (e.g. a flow-control aggregator joining\n * several upstream branches).\n */\n ports?: PortsDecl;\n with?: Record<string, unknown>;\n retry?: {\n maxAttempts: number;\n backoff?: \"fixed\" | \"exponential\";\n delayMs?: number;\n };\n /**\n * What to do when this step errors:\n * - `fail` — stop the run (default)\n * - `continue` — swallow the error and keep going\n * - `continue-record` — keep going, but record the error into the run's end state\n */\n onError?: \"fail\" | \"continue\" | \"continue-record\";\n /** Free-form author notes for this step. Not executed. */\n notes?: string;\n /**\n * How this step's outgoing edges in one lane run when there are two or more:\n * `parallel` runs them concurrently; omitted (never written as `\"sequential\"`)\n * runs them one after another.\n */\n fanOut?: \"sequential\" | \"parallel\";\n /**\n * Authoring-time canvas coordinate for this step, in this editor's own\n * coordinate space (core `rfcs/workflow.md` · \"Amendment — 2026-07-29:\n * authoring presentation (`Step.position`, `Workflow.settings`)\" — the spec\n * pins no unit, origin or grid). Declarative only: the engine ignores it\n * exactly as it ignores `notes`.\n *\n * **Omitted ⇒ the editor computes a layout** from the graph alone, exactly as\n * before this field existed, so it is additive and backward-compatible.\n * Partial coverage is valid: `workflowToFlow` places the steps that declare a\n * `position` and computes a slot for the rest.\n *\n * Rename-safe by construction — the coordinate travels *with* the step, so\n * there is no workflow-level `id → {x,y}` map to fix up on rename (D-I0-2).\n *\n * Mirrors `Step.position` in `@w6w/workflow-types` by hand — see the header\n * note: these types are deliberately a structural subset with no compiler\n * tie, so the spelling here must stay identical to the engine's.\n */\n position?: { x: number; y: number };\n}\n\nexport interface FlowEdge {\n from: string;\n to: string;\n /**\n * Which outcome of the `from` step this edge carries (core\n * `rfcs/workflow.md` · \"Amendment — 2026-07-29: failure-conditioned edges\n * (`Edge.when`)\"). **Omitted ⇒ `\"success\"`**, so every pre-existing edge is a\n * success edge and needs no migration.\n * - `\"success\"` — activates when `from` succeeds. Per the house\n * omit-the-default idiom it is written as **absent**, never spelled out:\n * this editor emits no `when` for a success edge, which is what keeps an\n * untouched definition byte-identical across a load/save cycle.\n * - `\"error\"` — activates when `from` fails, and overrides that step's\n * `onError`.\n *\n * Mirrors `Edge.when` in `@w6w/workflow-types` by hand — see the header note:\n * these types are deliberately a structural subset, with no compiler tie, so\n * the spelling here must stay identical to the engine's.\n */\n when?: \"success\" | \"error\";\n}\n\n/**\n * The React Flow presentation for an edge lane — **the one place** the error\n * look is spelled out.\n *\n * Three callers need it and they run at different times: `workflowToFlow` stamps\n * a *stored* edge on load, `setEdgeWhen` (`flow-connect.ts`) stamps an edge the\n * author re-lanes **live**, before any save, and a live-run repaint effect\n * (`WorkflowFlowEditor.tsx`, T1.1.1) restyles an edge as a run polls in. Spelled\n * out more than once, the copies drift and a freshly marked error edge stops\n * looking like a reloaded one. The className is what `styles.css`'s\n * `.w6w-edge-error`/`.w6w-edge-taken`/`.w6w-edge-skipped` blocks paint from\n * `--w6w-danger`/`--w6w-success`/`--w6w-muted`; no custom edge component is\n * involved (D-T1-7).\n *\n * `runState` (T1.1.1) is the edge's OWN taken/skipped verdict (see\n * `run-visuals.ts`'s `edgeRunState`) — omitted (or `undefined`) when there is no\n * run in progress, or the run hasn't decided this edge's fate yet, in which case\n * this returns exactly what it always has. `workflowToFlow`'s and `setEdgeWhen`'s\n * call sites deliberately never have a live run's state available (a *stored*\n * load and a live *re-lane* are never mid-run), so both pass no `runState` at\n * all — only the new repaint-effect call site does.\n *\n * A `\"success\"`/absent lane with no `runState` returns an **empty object** — not\n * `{ className: \"\" }` — so an untouched success edge carries neither key and a\n * definition round-trips unchanged. That makes it a trap for a *re-laning*\n * caller: spreading `{}` over an edge that already carries the error class\n * leaves the class in place, so `setEdgeWhen` assigns both keys explicitly\n * rather than spreading.\n */\nexport function edgeVisuals(\n when: \"success\" | \"error\" | undefined,\n runState?: EdgeRunState,\n): {\n className?: string;\n label?: string;\n} {\n const lane = when === \"error\" ? { className: \"w6w-edge-error\", label: \"on error\" } : {};\n if (!runState) return lane;\n const runClass = runState === \"taken\" ? \"w6w-edge-taken\" : \"w6w-edge-skipped\";\n return {\n className: lane.className ? `${lane.className} ${runClass}` : runClass,\n ...(lane.label ? { label: lane.label } : {}),\n };\n}\n\n/**\n * The React Flow handle id a step/control node's **error exit port** carries\n * (T1.1.1). Internal to `@w6w/ui` — not re-exported from `flow.ts` / `index.ts`\n * (D-P2), since no consumer outside this package needs it.\n */\nexport const ERROR_SOURCE_HANDLE = \"out-error\";\n\n/**\n * The `sourceHandle` a minted/re-laned/loaded edge carries for a given lane —\n * the inverse of {@link laneForSourceHandle}. `undefined` for `\"success\"`/\n * absent is **load-bearing, not stylistic**: React Flow anchors a handle-less\n * edge to the node's sole *unnamed* handle, which is the exit every\n * already-saved workflow's edges implicitly use. An empty string would not do\n * this — an empty string is a real, if degenerate, handle id.\n */\nexport function sourceHandleForLane(when: \"success\" | \"error\" | undefined): string | undefined {\n return when === \"error\" ? ERROR_SOURCE_HANDLE : undefined;\n}\n\n/**\n * The lane a drag started from, read off the handle id React Flow reports.\n * **The one canonicalisation point** every minting/re-laning site calls\n * (`onConnect`, `onConnectEnd`) so the handle-id spelling is decided once and\n * both drag gestures provably agree — two inline comparisons is the shape\n * where one gesture silently drifts. Exactly {@link ERROR_SOURCE_HANDLE} is\n * `\"error\"`; everything else — a near-miss id, `null`, `undefined` — is\n * `\"success\"`.\n */\nexport function laneForSourceHandle(handleId: string | null | undefined): \"success\" | \"error\" {\n return handleId === ERROR_SOURCE_HANDLE ? \"error\" : \"success\";\n}\n\nexport interface FlowWorkflow {\n manifestVersion: string;\n id: string;\n name: string;\n displayName?: string;\n description?: string;\n variables?: Array<{ key: string; type?: string; required?: boolean; default?: unknown }>;\n steps: FlowStep[];\n edges?: FlowEdge[];\n /**\n * Authoring-time presentation and preferences for this workflow (core\n * `rfcs/workflow.md` · \"Amendment — 2026-07-29: authoring presentation\n * (`Step.position`, `Workflow.settings`)\"). Declarative only — the engine\n * ignores it, exactly like `FlowStep.notes` and `FlowStep.position`.\n * `viewport` sits *inside* `settings` deliberately, so exactly one new\n * top-level key enters the portable workflow document. `settings` is itself\n * optional; when the object is absent every member below still takes its own\n * default.\n *\n * ⚠️ **`autoSave` and `savePosition` default to `true` when omitted.** That is\n * *deliberately unlike* the `ports`/`onError` rule (\"omitted reproduces the\n * status quo\") — here it does not. Read them as `?? true` / `!== false`, never\n * `?? false` and never `=== true`. The consequence, stated plainly: **a\n * workflow that has never been saved by the new editor starts persisting step\n * coordinates the first time it is saved.** That is intended (the product\n * requires both features on by default); only an explicit `false` turns one\n * off.\n *\n * HITL-6 asked whether a workflow's arrangement and its auto-save preference\n * belong to *the workflow* or to *the person looking at it*; the amendment\n * takes the **workflow** answer, so everyone who opens a workflow sees the\n * same arrangement. HITL-6 is still open — a viewer-owned answer would move\n * these fields out of the document and re-contract this shape.\n *\n * Mirrors `Workflow.settings` in `@w6w/workflow-types` by hand (structural\n * subset, no compiler tie — the spelling must stay identical).\n */\n settings?: {\n /**\n * Whether an authoring tool persists edits without an explicit save action.\n * Omitted ⇒ **true** — auto-save is ON. Not read by this module; the editor\n * and its host own it (T3.3.2 / T4.1.x).\n */\n autoSave?: boolean;\n /**\n * Whether an authoring tool persists step coordinates (`FlowStep.position`)\n * and `settings.viewport` when it saves. Omitted ⇒ **true** — positions ARE\n * persisted. When explicitly `false`, `flowToWorkflow` writes no `position`;\n * any value already stored is **left as it is, never erased**.\n */\n savePosition?: boolean;\n /**\n * The camera position the author last left the canvas at, so reopening the\n * workflow restores the view. **No default** — a workflow with no `viewport`\n * opens at whatever view the editor computes, exactly as today. Written by\n * the component (T3.3.2), not by `flowToWorkflow`, whose signature cannot\n * see a viewport.\n */\n viewport?: { x: number; y: number; zoom: number };\n };\n}\n\nimport type { ActionParam } from \"./types.ts\";\n\n// ── Internal pseudo-app nodes (see core rfcs/node-types.md) ─────────────────\n//\n// A node's kind + processor are derived from `uses.app`. The reserved `@w6w/*`\n// namespace holds internal pseudo-apps the platform runs itself: `@w6w/control`\n// (engine-native flow control), `@w6w/script`/`@w6w/data` (host-run compute),\n// and `@w6w/trigger` (the entry node). They render as pill nodes and configure\n// through the same dynamic form as apps.\n\n/** Reserved namespace for internal pseudo-apps. */\nexport const INTERNAL_APP_PREFIX = \"@w6w/\";\n/** Engine-native flow control (if/foreach/parallel/wait). */\nexport const CONTROL_APP = \"@w6w/control\";\n/** Host-run inline JS. */\nexport const SCRIPT_APP = \"@w6w/script\";\n/** Host-run typed key/value data. */\nexport const DATA_APP = \"@w6w/data\";\n/** The workflow's entry/trigger node. */\nexport const TRIGGER_APP = \"@w6w/trigger\";\n/** Host-run outbound HTTP(S) request. */\nexport const HTTP_APP = \"@w6w/http\";\n/** Inbound HTTP(S) webhook trigger (entry node; provisions a receive URL). */\nexport const WEBHOOK_APP = \"@w6w/webhook\";\n/** Time-based scheduler trigger (entry node; fires the workflow on a schedule). */\nexport const SCHEDULER_APP = \"@w6w/scheduler\";\n/** \"Respond to Webhook\" — shapes the HTTP response for `responseMode: responseNode`. */\nexport const RESPOND_APP = \"@w6w/respond\";\n/**\n * Sub-workflow / Function caller (core rfcs/node-types.md · F-3). The host runs\n * this node itself: it resolves `with.target` to a project-scoped `CallableRef` (a\n * Function or a Workflow) and invokes it through `ctx.invokeCallable`, honoring\n * the per-node `with.wait` flag. The engine never loads the target.\n */\nexport const CALL_APP = \"@w6w/call\";\n/**\n * Read a stored JSON document by key (core rfcs/node-types.md · F-3 amendment,\n * \"Reserved internal pseudo-app\"). Host node: `runInternalNode` short-circuits\n * this id before the registry loads a module — the run's own project is bound\n * host-side, so there is no `project` param (C-6).\n */\nexport const DOCUMENT_APP = \"@w6w/document\";\n/**\n * Compile a Handlebars `template` string against a resolved `values` object\n * (core rfcs/node-types.md · F-3 amendment, \"the `@w6w/template` host node\").\n * Host node: `runInternalNode` short-circuits this id before the registry\n * loads a module — it needs no privileged host resource (no DB, no\n * tenant/project scope), and runs host-side only because the template\n * compiles to a JS function, the same risk shape `@w6w/script` has.\n */\nexport const TEMPLATE_APP = \"@w6w/template\";\n\n/** True when `app` is a reserved internal pseudo-app id (`@w6w/*`). */\nexport function isInternalApp(app: string): boolean {\n return app.startsWith(INTERNAL_APP_PREFIX);\n}\n\n/** True when a node is an engine-native flow-control node (can't run standalone). */\nexport function isControlApp(app: string): boolean {\n return app === CONTROL_APP;\n}\n\n/**\n * Whether a step is an entry/trigger node — the one predicate, shared by the\n * step editor's Test tab and the canvas ▶ collect phase. A trigger's configured\n * `fields` are *definitions*, so both surfaces project them into a fillable form\n * and send the filled values as `{ input }` rather than running the raw config.\n */\nexport function isTriggerApp(app: string): boolean {\n return app === TRIGGER_APP || app === WEBHOOK_APP || app === SCHEDULER_APP;\n}\n\n/** A palette entry for an internal node: its id, label, group, and config schema. */\nexport interface InternalNodeDef {\n app: string;\n action: string;\n label: string;\n /**\n * Human display name (mirrors an app's `displayName`). Defaults conceptually\n * to `label`; kept explicit so internal pseudo-apps carry the same info an app\n * does. Shown wherever an app's name would be.\n */\n displayName: string;\n group: \"trigger\" | \"control\" | \"compute\" | \"request\";\n /**\n * Inline SVG *inner* markup (paths / circles / polylines) for this primitive's\n * glyph — internal pseudo-apps have no icon asset dir, so the glyph is bundled\n * here. Drawn on a 24×24 `viewBox`, stroked with `currentColor` (theme-aware),\n * so both app nodes and internal nodes display a consistent icon on the canvas.\n */\n icon: string;\n /**\n * Hidden from every palette list but still resolvable by `internalNodeDef`, so\n * a workflow already using the node keeps rendering and editing.\n */\n hidden?: boolean;\n /**\n * Connection ports: how many inbound (entry) and outbound (exit) connections\n * this node accepts. A port is the ability to receive/emit a connection —\n * rendered as a React Flow Handle. Defaults to one of each (`{ in: 1, out: 1 }`)\n * when omitted; a trigger overrides to `{ in: 0, out: 1 }` (nothing flows into\n * the entry node). Fixed for now — not user-editable.\n */\n ports?: PortsDecl;\n /** Config schema (same `ActionParam[]` shape apps declare) rendered by ParamsForm. */\n params: ActionParam[];\n /**\n * This node's static output field keys, when its shape is known ahead of any\n * run — same shape as `ExpressionStepSource.outputs`\n * (`components/ExpressionOptions.tsx`), fed verbatim by `projectStepSources`\n * (`step-preview-state.ts`) so the expression rail can offer\n * `steps.<id>.output.<key>` for a step using this node. Omitted (not `[]`)\n * when the node's output is not statically knowable (e.g. `@w6w/document ·\n * get`, whose shape is whatever JSON the referenced document holds).\n */\n output?: { key: string; label?: string }[];\n}\n\n/** A declared port count: a number, or `\"many\"` (unbounded). */\nexport type PortCount = number | \"many\";\n\n/** A (possibly partial) port declaration, as an author / catalog / def writes it. */\nexport interface PortsDecl {\n in?: PortCount;\n out?: PortCount;\n}\n\n/** Resolved inbound (entry) and outbound (exit) connection-port counts; `\"many\"` is `Infinity`. */\nexport interface NodePorts {\n in: number;\n out: number;\n}\n\n/** The default a node gets when nothing declares ports: 1 in, unbounded out. */\nexport const DEFAULT_NODE_PORTS: NodePorts = { in: 1, out: Number.POSITIVE_INFINITY };\n\nfunction portCount(v: PortCount | undefined): number | undefined {\n if (v === \"many\") return Number.POSITIVE_INFINITY;\n return typeof v === \"number\" ? v : undefined;\n}\n\n/** Field-wise resolution: first declared value per field wins, else the default. */\nexport function resolvePorts(...layers: (PortsDecl | undefined)[]): NodePorts {\n let inn: number | undefined;\n let out: number | undefined;\n for (const l of layers) {\n inn ??= portCount(l?.in);\n out ??= portCount(l?.out);\n }\n return { in: inn ?? DEFAULT_NODE_PORTS.in, out: out ?? DEFAULT_NODE_PORTS.out };\n}\n\n/** Catalog lookup of an action's declared ports, passed as an argument (never stamped on a step). */\nexport type PortsLookup = (app: string, action: string) => PortsDecl | undefined;\n\n/**\n * Resolve a node's connection ports from its internal def only (triggers drop the\n * entry port); everything else gets the default.\n */\nexport function nodePorts(app: string, action: string): NodePorts {\n return resolvePorts(internalNodeDef(app, action)?.ports);\n}\n\n/**\n * Resolve a *step's* ports field-wise: `step.ports` → catalog action (via `lookup`)\n * → internal def → default `{ in: 1, out: Infinity }`. The catalog is read through\n * the `lookup` argument and never written onto the step, so it never serializes.\n */\nexport function nodePortsForStep(step: FlowStep, lookup?: PortsLookup): NodePorts {\n const { app, action } = step.uses;\n return resolvePorts(step.ports, lookup?.(app, action), internalNodeDef(app, action)?.ports);\n}\n\n// Feather-style 24×24 stroked glyphs (inner markup only; the card supplies the\n// <svg> wrapper). One clean, recognizable glyph per internal primitive.\n/** Lightning bolt — a trigger firing. */\nconst ICON_TRIGGER = '<polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\" />';\n/** Git-branch — a conditional split. */\nconst ICON_IF =\n '<line x1=\"6\" y1=\"3\" x2=\"6\" y2=\"15\" /><circle cx=\"18\" cy=\"6\" r=\"3\" /><circle cx=\"6\" cy=\"18\" r=\"3\" /><path d=\"M18 9a9 9 0 0 1-9 9\" />';\n/** Repeat arrows — iterate over items. */\nconst ICON_FOREACH =\n '<polyline points=\"17 1 21 5 17 9\" /><path d=\"M3 11V9a4 4 0 0 1 4-4h14\" /><polyline points=\"7 23 3 19 7 15\" /><path d=\"M21 13v2a4 4 0 0 1-4 4H3\" />';\n/** Concurrent lanes — parallel execution. */\nconst ICON_PARALLEL =\n '<line x1=\"6\" y1=\"4\" x2=\"6\" y2=\"20\" /><line x1=\"12\" y1=\"4\" x2=\"12\" y2=\"20\" /><line x1=\"18\" y1=\"4\" x2=\"18\" y2=\"20\" />';\n/** Clock — a timed wait. */\nconst ICON_WAIT = '<circle cx=\"12\" cy=\"12\" r=\"9\" /><polyline points=\"12 7 12 12 15 14\" />';\n/** Angle brackets — inline code. */\nconst ICON_SCHEDULER =\n '<rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\" /><line x1=\"16\" y1=\"2\" x2=\"16\" y2=\"6\" />' +\n '<line x1=\"8\" y1=\"2\" x2=\"8\" y2=\"6\" /><line x1=\"3\" y1=\"10\" x2=\"21\" y2=\"10\" />' +\n '<polyline points=\"12 13 12 16 14 17\" />';\nconst ICON_SCRIPT = '<polyline points=\"16 18 22 12 16 6\" /><polyline points=\"8 6 2 12 8 18\" />';\n/** Database cylinder — typed data. */\nconst ICON_DATA =\n '<ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" /><path d=\"M21 12c0 1.66-4 3-9 3s-9-1.34-9-3\" /><path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />';\n/** Globe — an outbound HTTP(S) request. */\nconst ICON_HTTP =\n '<circle cx=\"12\" cy=\"12\" r=\"10\" /><line x1=\"2\" y1=\"12\" x2=\"22\" y2=\"12\" /><path d=\"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z\" />';\n/** Connected nodes — an inbound webhook. */\nconst ICON_WEBHOOK =\n '<circle cx=\"18\" cy=\"5\" r=\"3\" /><circle cx=\"6\" cy=\"12\" r=\"3\" /><circle cx=\"18\" cy=\"19\" r=\"3\" /><line x1=\"8.59\" y1=\"13.51\" x2=\"15.42\" y2=\"17.49\" /><line x1=\"15.41\" y1=\"6.51\" x2=\"8.59\" y2=\"10.49\" />';\n/** Reply arrow — respond to the caller. */\nconst ICON_RESPOND = '<polyline points=\"9 17 4 12 9 7\" /><path d=\"M20 18v-2a4 4 0 0 0-4-4H4\" />';\n/** Funnel — many inbound branches joined into one. */\nconst ICON_AGGREGATE = '<polygon points=\"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\" />';\n/** External-link box — delegate out to another Workflow / Function. */\nconst ICON_CALL =\n '<path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" /><polyline points=\"15 3 21 3 21 9\" /><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />';\n/** Dog-eared page with lines — a stored JSON document. */\nconst ICON_DOCUMENT =\n '<path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\" /><polyline points=\"14 2 14 8 20 8\" /><line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\" /><line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\" /><polyline points=\"10 9 9 9 8 9\" />';\n/** Braces — a compiled placeholder template. */\nconst ICON_TEMPLATE =\n '<path d=\"M8 3H7a2 2 0 0 0-2 2v4a2 2 0 0 1-2 2 2 2 0 0 1 2 2v4a2 2 0 0 0 2 2h1\" /><path d=\"M16 3h1a2 2 0 0 1 2 2v4a2 2 0 0 0 2 2 2 2 0 0 0-2 2v4a2 2 0 0 1-2 2h-1\" />';\n\n/** The built-in internal nodes, in palette order. */\nexport const INTERNAL_NODES: InternalNodeDef[] = [\n {\n app: TRIGGER_APP,\n action: \"manual\",\n label: \"Manual trigger\",\n displayName: \"Manual trigger\",\n group: \"trigger\",\n icon: ICON_TRIGGER,\n ports: { in: 0, out: 1 },\n params: [\n {\n key: \"fields\",\n label: \"Fields\",\n type: \"array\",\n default: [],\n hint: 'The fields this trigger emits into the run. Reference them downstream as {\"$\": \"steps.<trigger>.output.<key>\"}.',\n item: {\n type: \"object\",\n fields: [\n { key: \"key\", label: \"Key\", type: \"string\", placeholder: \"e.g. email\" },\n {\n key: \"type\",\n label: \"Type\",\n type: \"select\",\n default: \"string\",\n options: [\n { value: \"string\", label: \"String\" },\n { value: \"number\", label: \"Number\" },\n { value: \"boolean\", label: \"Boolean\" },\n { value: \"json\", label: \"JSON\" },\n ],\n },\n { key: \"default\", label: \"Default\", type: \"string\", placeholder: \"optional\" },\n { key: \"required\", label: \"Required\", type: \"boolean\", default: false },\n ],\n },\n },\n ],\n },\n {\n app: WEBHOOK_APP,\n action: \"webhook\",\n label: \"Webhook\",\n displayName: \"Webhook\",\n group: \"trigger\",\n icon: ICON_WEBHOOK,\n ports: { in: 0, out: 1 },\n params: [\n {\n key: \"methods\",\n label: \"HTTP Methods\",\n type: \"multiselect\",\n required: true,\n default: [\"POST\"],\n hint: \"Which HTTP methods this webhook accepts.\",\n options: [\n { value: \"GET\", label: \"GET\" },\n { value: \"POST\", label: \"POST\" },\n { value: \"PUT\", label: \"PUT\" },\n { value: \"PATCH\", label: \"PATCH\" },\n { value: \"DELETE\", label: \"DELETE\" },\n { value: \"HEAD\", label: \"HEAD\" },\n ],\n },\n {\n key: \"auth\",\n label: \"Authentication\",\n type: \"select\",\n default: \"none\",\n hint: \"How incoming requests are authenticated.\",\n options: [\n { value: \"none\", label: \"None\" },\n { value: \"basic\", label: \"Basic auth\" },\n { value: \"header\", label: \"Header auth\" },\n { value: \"jwt\", label: \"JWT (HMAC)\" },\n ],\n },\n {\n key: \"basicUser\",\n label: \"Username\",\n type: \"string\",\n row: \"basic-auth\",\n showIf: { field: \"auth\", equals: \"basic\" },\n },\n {\n key: \"basicPassword\",\n label: \"Password\",\n type: \"secret\",\n row: \"basic-auth\",\n showIf: { field: \"auth\", equals: \"basic\" },\n },\n {\n key: \"headerName\",\n label: \"Header name\",\n type: \"string\",\n row: \"header-auth\",\n placeholder: \"e.g. X-Api-Key\",\n showIf: { field: \"auth\", equals: \"header\" },\n },\n {\n key: \"headerValue\",\n label: \"Header value\",\n type: \"secret\",\n row: \"header-auth\",\n showIf: { field: \"auth\", equals: \"header\" },\n },\n {\n key: \"jwtSecret\",\n label: \"JWT secret\",\n type: \"secret\",\n showIf: { field: \"auth\", equals: \"jwt\" },\n },\n {\n key: \"responseMode\",\n label: \"Respond\",\n type: \"select\",\n default: \"onReceived\",\n hint: \"When and how to respond to the caller.\",\n options: [\n { value: \"onReceived\", label: \"Immediately (ASAP)\" },\n { value: \"lastNode\", label: \"When the run finishes\" },\n { value: \"responseNode\", label: \"Using a Response node\" },\n { value: \"streaming\", label: \"Streaming\" },\n ],\n },\n {\n key: \"responseCode\",\n label: \"Response status code\",\n type: \"number\",\n default: 200,\n showIf: { field: \"responseMode\", notIn: [\"responseNode\"] },\n },\n {\n key: \"responseData\",\n label: \"Response body (immediate)\",\n type: \"text\",\n hint: 'Body for \"Immediately\" responses. Empty = { \"message\": \"Workflow was started\" }.',\n showIf: { field: \"responseMode\", equals: \"onReceived\" },\n },\n { key: \"rawBody\", label: \"Raw body\", type: \"boolean\", default: false, advanced: true },\n { key: \"ignoreBots\", label: \"Ignore bots\", type: \"boolean\", default: false, advanced: true },\n {\n key: \"ipAllowList\",\n label: \"IP allow list\",\n type: \"array\",\n advanced: true,\n item: { type: \"string\", placeholder: \"e.g. 203.0.113.4\" },\n hint: \"Client IPs allowed to call this webhook. Empty = allow all.\",\n },\n { key: \"binaryPropertyName\", label: \"Binary field name\", type: \"string\", advanced: true },\n { key: \"cors\", label: \"CORS allowed origin\", type: \"string\", advanced: true },\n {\n key: \"responseHeaders\",\n label: \"Response headers\",\n type: \"array\",\n default: [],\n advanced: true,\n item: {\n type: \"object\",\n fields: [\n { key: \"name\", label: \"Name\", type: \"string\" },\n { key: \"value\", label: \"Value\", type: \"string\" },\n ],\n },\n },\n ],\n },\n {\n app: SCHEDULER_APP,\n action: \"schedule\",\n label: \"Schedule\",\n displayName: \"Scheduler\",\n group: \"trigger\",\n icon: ICON_SCHEDULER,\n // An entry node: nothing flows in, one branch flows out.\n ports: { in: 0, out: 1 },\n params: [\n {\n key: \"mode\",\n label: \"Mode\",\n type: \"select\",\n required: true,\n default: \"cron\",\n hint: \"How the schedule fires.\",\n options: [\n { value: \"once\", label: \"Once\" },\n { value: \"cron\", label: \"Cron\" },\n { value: \"interval\", label: \"Interval\" },\n ],\n },\n {\n key: \"cron\",\n label: \"Cron expression\",\n type: \"string\",\n placeholder: \"e.g. 0 9 * * 1-5\",\n showIf: { field: \"mode\", equals: \"cron\" },\n },\n {\n key: \"runAt\",\n label: \"Run at\",\n type: \"string\",\n placeholder: \"e.g. 2026-01-01T09:00:00Z\",\n showIf: { field: \"mode\", equals: \"once\" },\n },\n {\n key: \"intervalSeconds\",\n label: \"Interval (seconds)\",\n type: \"number\",\n showIf: { field: \"mode\", equals: \"interval\" },\n },\n {\n key: \"timezone\",\n label: \"Timezone\",\n type: \"string\",\n default: \"UTC\",\n advanced: true,\n },\n ],\n },\n {\n app: CONTROL_APP,\n action: \"if\",\n label: \"If\",\n displayName: \"If\",\n group: \"control\",\n icon: ICON_IF,\n params: [\n {\n key: \"condition\",\n type: \"json\",\n label: \"Condition\",\n required: true,\n default: true,\n hint: 'A boolean, or an expression binding like { \"$\": \"steps.x.output.ok\" }.',\n },\n ],\n },\n {\n app: CONTROL_APP,\n action: \"foreach\",\n label: \"For each\",\n displayName: \"For each\",\n group: \"control\",\n icon: ICON_FOREACH,\n params: [\n {\n key: \"items\",\n type: \"json\",\n label: \"Items\",\n required: true,\n default: [],\n hint: \"An array to iterate, or an expression binding to one.\",\n },\n ],\n },\n {\n app: CONTROL_APP,\n action: \"parallel\",\n label: \"Parallel\",\n displayName: \"Parallel\",\n group: \"control\",\n icon: ICON_PARALLEL,\n params: [],\n },\n {\n app: CONTROL_APP,\n action: \"wait\",\n label: \"Wait\",\n displayName: \"Wait\",\n group: \"control\",\n icon: ICON_WAIT,\n params: [\n {\n key: \"duration\",\n type: \"string\",\n label: \"Duration\",\n default: \"1s\",\n hint: \"Use 30s, 1h30m30s, or 3d30s. Units: w, d, h, m, s; uppercase also works.\",\n },\n ],\n },\n {\n app: SCRIPT_APP,\n action: \"run\",\n label: \"Run script\",\n displayName: \"Run script\",\n group: \"compute\",\n icon: ICON_SCRIPT,\n params: [\n {\n key: \"language\",\n label: \"Language\",\n type: \"select\",\n default: \"javascript\",\n options: [\n { value: \"javascript\", label: \"JavaScript\" },\n { value: \"python\", label: \"Python\" },\n ],\n hint: \"Execution language for this step's code. Python runs CPython-on-WASM with no network.\",\n },\n {\n key: \"code\",\n type: \"code\",\n label: \"Script\",\n required: true,\n default: \"// Runs as a function body. Return the step's output.\\nreturn input;\",\n hint: \"Function body; return the step's output.\",\n },\n ],\n },\n {\n app: TEMPLATE_APP,\n action: \"render\",\n label: \"Render template\",\n displayName: \"Template\",\n group: \"compute\",\n icon: ICON_TEMPLATE,\n // Static output shape (core rfcs/node-types.md:582): the already-rendered\n // string, host-side Handlebars having run — an ordinary `var` ref, not the\n // `resolveRenderPart` mechanism.\n output: [{ key: \"result\" }],\n params: [\n {\n key: \"template\",\n label: \"Template\",\n type: \"text\",\n required: true,\n hint:\n \"Handlebars template. Placeholder names are workflow-agnostic — bind them below. \" +\n \"{{name}} is HTML-escaped; use {{{name}}} for raw output.\",\n },\n {\n // The manifest declares `values` as `type: \"json\"` — `\"vars\"` is a\n // UI-only type, not a member of core's canonical `ParamType`, exactly\n // the same divergence `data/index.ts:10-13` explains for `@w6w/data`'s\n // own `vars` param. `required` surfaces the table in the form directly.\n key: \"values\",\n label: \"Values\",\n type: \"vars\",\n required: true,\n default: [],\n hint:\n 'A typed key/value array: [{ \"key\": \"data\", \"type\": \"json\", \"value\": ... }]. ' +\n \"Each key becomes a top-level placeholder root.\",\n },\n ],\n },\n {\n app: DATA_APP,\n action: \"set\",\n label: \"Data\",\n displayName: \"Data set\",\n group: \"compute\",\n icon: ICON_DATA,\n params: [\n {\n // `required` surfaces the table in the form directly (not hidden under\n // the optional disclosure). The value may be an empty array — a Data\n // node with no vars yet is valid.\n key: \"vars\",\n type: \"vars\",\n label: \"Variables\",\n required: true,\n default: [],\n hint: \"Typed key/value variables for downstream steps to reference.\",\n },\n ],\n },\n {\n app: HTTP_APP,\n action: \"request\",\n label: \"HTTP request\",\n displayName: \"HTTP\",\n group: \"request\",\n icon: ICON_HTTP,\n // Static output shape: `packages/server/packages/api/internal-nodes.ts:317-322`'s\n // `runHttpRequest` literally returns these five fields on every response.\n output: [\n { key: \"status\" },\n { key: \"statusText\" },\n { key: \"ok\" },\n { key: \"headers\" },\n { key: \"body\" },\n ],\n params: [\n {\n key: \"method\",\n type: \"string\",\n label: \"Method\",\n required: true,\n default: \"GET\",\n options: [\n { value: \"GET\", label: \"GET\" },\n { value: \"POST\", label: \"POST\" },\n { value: \"PUT\", label: \"PUT\" },\n { value: \"PATCH\", label: \"PATCH\" },\n { value: \"DELETE\", label: \"DELETE\" },\n ],\n hint: \"HTTP method for the request.\",\n },\n {\n key: \"url\",\n type: \"string\",\n label: \"URL\",\n required: true,\n default: \"\",\n hint: \"Full request URL, e.g. https://api.example.com/v1/things.\",\n },\n {\n key: \"headers\",\n type: \"json\",\n label: \"Headers\",\n default: {},\n hint: \"Object of header name → value.\",\n },\n {\n key: \"query\",\n type: \"json\",\n label: \"Query params\",\n default: {},\n hint: \"Object of query-string name → value, appended to the URL.\",\n },\n {\n key: \"body\",\n type: \"text\",\n label: \"Body\",\n default: \"\",\n hint: \"Request body (raw text or a JSON string). Ignored for GET/HEAD.\",\n },\n ],\n },\n {\n app: RESPOND_APP,\n action: \"respond\",\n label: \"Respond to Webhook\",\n displayName: \"Respond to Webhook\",\n group: \"request\",\n icon: ICON_RESPOND,\n params: [\n {\n key: \"respondWith\",\n label: \"Respond with\",\n type: \"select\",\n default: \"json\",\n hint: \"Shape of the response returned to the webhook caller.\",\n options: [\n { value: \"json\", label: \"JSON\" },\n { value: \"text\", label: \"Text\" },\n { value: \"noData\", label: \"No body\" },\n ],\n },\n { key: \"responseCode\", label: \"Response status code\", type: \"number\", default: 200 },\n {\n key: \"responseBody\",\n label: \"Response body\",\n type: \"json\",\n default: {},\n hint: \"Body to return (object for JSON, string for Text).\",\n },\n {\n key: \"responseHeaders\",\n label: \"Response headers\",\n type: \"array\",\n default: [],\n item: {\n type: \"object\",\n fields: [\n { key: \"name\", label: \"Name\", type: \"string\" },\n { key: \"value\", label: \"Value\", type: \"string\" },\n ],\n },\n },\n ],\n },\n {\n app: CONTROL_APP,\n action: \"aggregate\",\n label: \"Aggregate\",\n displayName: \"Aggregate\",\n group: \"control\",\n icon: ICON_AGGREGATE,\n hidden: true,\n // Fan-in join: accepts several inbound branches and emits one combined\n // output. `in > 1` opts the node into multiple inbound edges (see core\n // rfcs/node-types.md · Ports & cardinality); `out: 1` is a single exit.\n ports: { in: 10, out: 1 },\n params: [\n {\n key: \"mode\",\n label: \"Mode\",\n type: \"select\",\n default: \"array\",\n hint: \"How to combine the inbound branch outputs: an array of results, or an object keyed by source step.\",\n options: [\n { value: \"array\", label: \"Array\" },\n { value: \"object\", label: \"Object\" },\n ],\n },\n ],\n },\n {\n app: CONTROL_APP,\n action: \"merge\",\n label: \"Merge\",\n displayName: \"Merge\",\n group: \"control\",\n icon: ICON_AGGREGATE,\n // Fan-in join with named entries: any number of inbound branches, one output\n // built from `entries` (key → expression), as an array or an object.\n ports: { in: \"many\", out: 1 },\n params: [\n {\n key: \"mode\",\n label: \"Mode\",\n type: \"select\",\n default: \"array\",\n hint: \"Combine the entries into an array, or into an object keyed by each entry's key.\",\n options: [\n { value: \"array\", label: \"Array\" },\n { value: \"object\", label: \"Object\" },\n ],\n },\n {\n key: \"entries\",\n label: \"Entries\",\n type: \"array\",\n default: [],\n hint: \"Each entry's value may be an expression (ƒx) over the inbound branches' outputs.\",\n item: {\n type: \"object\",\n fields: [\n { key: \"key\", label: \"Key\", type: \"string\" },\n { key: \"value\", label: \"Value\", type: \"string\" },\n ],\n },\n },\n ],\n },\n {\n app: CALL_APP,\n action: \"call\",\n label: \"Call workflow\",\n displayName: \"Call\",\n group: \"compute\",\n icon: ICON_CALL,\n // Internal host node: invokes a project-scoped CallableRef (a Function or a\n // Workflow) via `ctx.invokeCallable` (core rfcs/node-types.md · F-3). One\n // inbound, one outbound — the sub-run is a single downstream continuation.\n ports: { in: 1, out: 1 },\n params: [\n {\n // The target's discriminant (HITL-D: resolved within the same project).\n // A populated target picker is a deferred follow-up (FOLLOWUPS.md); v1\n // pairs this kind with a plain id field below.\n key: \"targetKind\",\n label: \"Target kind\",\n type: \"select\",\n required: true,\n default: \"workflow\",\n hint: \"Whether this node calls another Workflow or a Function.\",\n options: [\n { value: \"workflow\", label: \"Workflow\" },\n { value: \"function\", label: \"Function\" },\n ],\n },\n {\n key: \"targetId\",\n label: \"Target id\",\n type: \"string\",\n required: true,\n default: \"\",\n placeholder: \"e.g. wf_… or fn_…\",\n hint: \"Id of the Workflow (wf_…) or Function (fn_…) to call, within this project.\",\n },\n {\n // SEAM PIN: the key is `inputs` (plural) — it maps to the engine's\n // `InvokeCallableRequest.inputs` (the target's canonical inputs). Do\n // NOT rename to `input`.\n key: \"inputs\",\n label: \"Inputs\",\n type: \"json\",\n default: {},\n hint: \"Payload passed to the target — an object keyed by the callee's declared inputs. Values may be expressions.\",\n },\n {\n // HITL-5: wait/no-wait is a per-node choice, independent of the target\n // kind. `true` ⇒ block for the sub-run's output; `false` ⇒ return a run\n // handle ({ runId }) and continue the parent graph.\n key: \"wait\",\n label: \"Wait for completion\",\n type: \"boolean\",\n default: true,\n hint: \"On: block until the sub-run finishes and expose its output. Off: return a run handle and continue.\",\n },\n ],\n },\n {\n app: DOCUMENT_APP,\n action: \"get\",\n label: \"Get document\",\n displayName: \"Document\",\n group: \"compute\",\n icon: ICON_DOCUMENT,\n // Host node: reads a stored JSON document by key (core rfcs/node-types.md\n // · F-3 amendment, \"Reserved internal pseudo-app\"). One inbound, one\n // outbound — a single read step. No `project` param: the run's own\n // project is bound host-side (C-6).\n ports: { in: 1, out: 1 },\n params: [\n {\n key: \"key\",\n label: \"Key\",\n type: \"string\",\n required: true,\n default: \"\",\n hint: \"Document key to read — may be an expression, e.g. a step output.\",\n },\n ],\n },\n];\n\n/** Look up an internal node's definition by its (app, action) pair. */\nexport function internalNodeDef(app: string, action: string): InternalNodeDef | undefined {\n return INTERNAL_NODES.find((n) => n.app === app && n.action === action);\n}\n\n/** The label the editor shows for an internal node (falls back to the action key). */\nexport function internalNodeLabel(app: string, action: string): string {\n return internalNodeDef(app, action)?.label ?? action;\n}\n\n/**\n * The inline SVG glyph markup for an internal node (empty when unknown). Lets a\n * node retrieve its icon from just the (app, action) pair — same lookup path as\n * `internalNodeLabel`.\n */\nexport function internalNodeIcon(app: string, action: string): string {\n return internalNodeDef(app, action)?.icon ?? \"\";\n}\n\n/** The config schema for an internal node (empty when unknown). */\nexport function internalNodeParams(app: string, action: string): ActionParam[] {\n return internalNodeDef(app, action)?.params ?? [];\n}\n\n/** Build an internal node's default `with` from its param schema defaults. */\nexport function internalNodeDefaults(app: string, action: string): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const p of internalNodeParams(app, action)) {\n if (p.default !== undefined) out[p.key] = p.default;\n }\n return out;\n}\n","/**\n * Pure state/normalization helpers behind the bounded app-picker paths\n * (`AppPicker`'s paged mode, `StepBuilderModal`'s Apps/AI/Triggers tabs and\n * its \"Ready to use\" connected-id batching). No React, no fetch, no I/O — a\n * `.ts` module so `node --test` loads it with no JSX/browser harness, per\n * this task's contract.\n *\n * Two independent state machines live here, because the two loading shapes\n * are genuinely different problems:\n *\n * - {@link AppsPageState} / {@link appsPageReducer} — ONE outstanding\n * server-paged request at a time (search / category / \"load more\"),\n * generation-guarded so a late response from an abandoned query can never\n * overwrite a newer one.\n * - {@link nextIdBatch} / {@link mergeResolvedApps} — bounded, order-stable\n * resolution of a fixed id LIST (connected app ids), a few ids per batch,\n * with no cursor at all.\n */\nimport { isInternalApp } from \"./flow-types.ts\";\nimport type { AppSummary } from \"./types.ts\";\n\n// ── Paged search/category/load-more state machine ──────────────────────────\n\n/** The user-controlled inputs that identify a distinct page fetch. */\nexport interface AppsPageQuery {\n /** Trimmed search text; `\"\"` means no search term. */\n q: string;\n /** Server-side category filter (e.g. `\"ai\"` for the AI tab), or absent. */\n category?: string;\n}\n\n/**\n * Two queries are the same fetch target when both fields match exactly\n * (empty-string `q` included) — used to short-circuit a reducer action that\n * would otherwise restart an identical in-flight query.\n */\nexport function sameAppsPageQuery(a: AppsPageQuery, b: AppsPageQuery): boolean {\n return a.q === b.q && (a.category ?? \"\") === (b.category ?? \"\");\n}\n\nexport type AppsPageStatus = \"loading\" | \"loading-more\" | \"ready\" | \"error\";\n\nexport interface AppsPageState {\n query: AppsPageQuery;\n /**\n * Bumped every time the query changes (new search/category/tab). A\n * response tagged with an older generation is stale and MUST be dropped by\n * the caller before dispatching — {@link isStalePageGeneration} is the\n * check; the reducer itself also refuses a stale `page-loaded`/`page-failed`\n * defensively, so a caller that forgets the check still cannot corrupt state.\n */\n generation: number;\n status: AppsPageStatus;\n /** Every app fetched so far for the CURRENT query, in server order, deduped by id. */\n apps: AppSummary[];\n /** Cursor to send on the NEXT \"load more\"; absent once the server has no more pages. */\n cursor?: string;\n hasMore: boolean;\n error?: string;\n}\n\nexport function initialAppsPageState(query: AppsPageQuery, generation = 0): AppsPageState {\n return { query, generation, status: \"loading\", apps: [], hasMore: false };\n}\n\nexport type AppsPageAction =\n /** A new search/category/tab was selected — resets `apps`/`cursor` and starts a fresh fetch. */\n | { type: \"query-changed\"; query: AppsPageQuery; generation: number }\n /** The user asked for more results on the CURRENT query. No-op unless `status===\"ready\" && hasMore`. */\n | { type: \"load-more\" }\n /**\n * The user pressed Retry after a failure. Only meaningful from `\"error\"`:\n * back to `\"loading\"` when nothing is shown yet, `\"loading-more\"` when a\n * list is already on screen (apps and cursor kept, so the retry resends the\n * SAME cursor). No-op in any other status.\n */\n | { type: \"retry\" }\n /**\n * One page arrived. `requestedCursor` is the cursor that page was fetched\n * WITH (undefined for a first page) — compared against the server's own\n * `nextCursor` to catch a server that echoes back the same cursor forever\n * (a repeated/non-advancing cursor is treated as \"no more pages\", never\n * retried, so it can neither loop nor duplicate a request).\n */\n | {\n type: \"page-loaded\";\n generation: number;\n apps: AppSummary[];\n nextCursor?: string;\n requestedCursor?: string;\n }\n | { type: \"page-failed\"; generation: number; error: string };\n\n/**\n * Dedupe-append: every app in `incoming` not already present (by `id`) in\n * `existing`, in `incoming`'s own order, appended after `existing`.\n * Immutable — always returns a new array, and existing entries in `existing`\n * are shared references, never mutated, so a caller that kept the old array\n * around still sees the original values (copy-safety for cache reads).\n */\nexport function dedupeAppend(existing: AppSummary[], incoming: AppSummary[]): AppSummary[] {\n const seen = new Set(existing.map((a) => a.id));\n const added: AppSummary[] = [];\n for (const app of incoming) {\n if (seen.has(app.id)) continue;\n seen.add(app.id);\n added.push(app);\n }\n return added.length === 0 ? existing : [...existing, ...added];\n}\n\n/**\n * The paged-picker reducer. Every transition is a pure function of\n * `(state, action)` — no timers, no fetch; the caller performs the actual\n * request and feeds the result back in as `page-loaded`/`page-failed`.\n */\nexport function appsPageReducer(state: AppsPageState, action: AppsPageAction): AppsPageState {\n switch (action.type) {\n case \"query-changed\": {\n if (action.generation === state.generation && sameAppsPageQuery(action.query, state.query)) {\n return state;\n }\n return initialAppsPageState(action.query, action.generation);\n }\n case \"load-more\": {\n if (state.status !== \"ready\" || !state.hasMore) return state;\n return { ...state, status: \"loading-more\" };\n }\n case \"retry\": {\n if (state.status !== \"error\") return state;\n return { ...state, status: state.apps.length === 0 ? \"loading\" : \"loading-more\" };\n }\n case \"page-loaded\": {\n // A late arrival from an abandoned generation is dropped outright — the\n // reducer is the last line of defense even if a caller forgot to check\n // `isStalePageGeneration` before dispatching.\n if (action.generation !== state.generation) return state;\n const apps = dedupeAppend(state.apps, action.apps);\n // A server that echoes the same cursor back (or a caller that mistakenly\n // resends the current cursor) can never advance — treat it as terminal\n // rather than retrying it, which is the one shape that would loop.\n const nonAdvancing =\n action.nextCursor !== undefined && action.nextCursor === action.requestedCursor;\n const hasMore = Boolean(action.nextCursor) && !nonAdvancing;\n return {\n ...state,\n status: \"ready\",\n apps,\n cursor: hasMore ? action.nextCursor : undefined,\n hasMore,\n error: undefined,\n };\n }\n case \"page-failed\": {\n if (action.generation !== state.generation) return state;\n // Errors keep whatever was already loaded (retry-in-place), and are\n // distinguished from \"loaded zero results\" by `status === \"error\"` plus\n // a non-empty `error`, never by an empty `apps` array alone.\n return { ...state, status: \"error\", error: action.error };\n }\n default:\n return state;\n }\n}\n\n/** Whether a response tagged `generation` is stale against `state` — check before dispatching. */\nexport function isStalePageGeneration(state: AppsPageState, generation: number): boolean {\n return generation !== state.generation;\n}\n\n/**\n * Reserved `@w6w/*` pseudo-apps are never a pickable catalog entry (mirrors\n * `AppPicker`'s existing exclusion) — factored out so the paged path and the\n * id-batch path apply the exact same rule.\n */\nexport function excludeInternalApps(apps: readonly AppSummary[]): AppSummary[] {\n return apps.filter((a) => !isInternalApp(a.id));\n}\n\n// ── Bounded id-batch resolution (connected/\"Ready to use\" apps) ────────────\n\n/**\n * The next batch of ids to resolve: up to `batchSize` entries from `ids`,\n * preserving `ids`' own order, skipping anything already in `requested`.\n * Returns `[]` once every id has been requested — the caller's signal to stop\n * showing \"load more\". Never re-requests an id already in `requested`, even\n * across repeated calls with a growing `requested` set (idempotent given the\n * same two inputs).\n */\nexport function nextIdBatch(\n ids: readonly string[],\n requested: ReadonlySet<string>,\n batchSize: number,\n): string[] {\n if (batchSize <= 0) return [];\n const batch: string[] = [];\n for (const id of ids) {\n if (requested.has(id)) continue;\n batch.push(id);\n if (batch.length >= batchSize) break;\n }\n return batch;\n}\n\n/**\n * Merge a batch of resolved summaries into the accumulated visible list,\n * preserving `ids`' overall order (not fetch-arrival order) and silently\n * dropping any id with no entry in `resolved` — the caller's contract for a\n * missing/404 id (see `useReadyToUse`'s id-batch rewrite): omitted, not shown\n * as an error.\n */\nexport function mergeResolvedApps(\n ids: readonly string[],\n resolved: ReadonlyMap<string, AppSummary>,\n): AppSummary[] {\n const out: AppSummary[] = [];\n for (const id of ids) {\n const app = resolved.get(id);\n if (app) out.push(app);\n }\n return out;\n}\n","import { useState } from \"react\";\nimport { useEffectiveTheme } from \"../theme.ts\";\nimport type { ThemeMode } from \"../types.ts\";\n\ninterface Props {\n /** Data URI or absolute URL for the light-mode icon. Falsy → render an initials tile. */\n src?: string;\n /** Optional dark-mode variant; used when `theme === \"dark\"`. */\n srcDark?: string;\n /** Background color when falling back to the initials tile. */\n brandColor?: string;\n /** Display name used to produce initials when there's no image. */\n name?: string;\n /** Square px size. Defaults to 32. */\n size?: number;\n /**\n * Explicit theme. If omitted, reads `data-theme` from `<html>` and falls\n * back to `prefers-color-scheme` — matches how most theme systems work.\n */\n theme?: ThemeMode;\n}\n\n/**\n * Renders an app's icon. Prefers the inlined SVG served by the w6w server;\n * falls back to a small initials tile when no icon is provided or when both\n * light and dark variants are missing.\n */\nexport function AppIcon({ src, srcDark, brandColor, name, size = 32, theme }: Props) {\n const effective = useEffectiveTheme(theme);\n const displaySrc = effective === \"dark\" ? (srcDark ?? src) : src;\n // An icon ref that failed to inline server-side (asset-inliner.ts) can persist\n // as a raw, unresolvable path string rather than a data: URI — that never\n // renders, so `<img>` needs an escape hatch to the initials tile too. Stores\n // the src it failed on (not just a bool) so a later, different src retries\n // instead of staying stuck on the fallback.\n const [brokenSrc, setBrokenSrc] = useState<string | undefined>(undefined);\n\n if (displaySrc && displaySrc !== brokenSrc) {\n return (\n <img\n src={displaySrc}\n width={size}\n height={size}\n alt=\"\"\n onError={() => setBrokenSrc(displaySrc)}\n style={{\n width: size,\n height: size,\n borderRadius: 6,\n flexShrink: 0,\n // `contain` (not `cover`) keeps the whole glyph visible; the small\n // inset + border-box keep square/edge-to-edge icons from clipping\n // the rounded frame, without eating so much of the box that the\n // glyph reads as a stamp inside a swatch.\n objectFit: \"contain\",\n padding: Math.max(1, Math.round(size * 0.06)),\n boxSizing: \"border-box\",\n // A real icon SVG carries its own colors — painting `brandColor`\n // behind it double-tints the glyph and, for icons with built-in\n // transparent margin, reads as a thick brand-colored border rather\n // than an icon. Always the neutral swatch here; `brandColor` stays\n // reserved for the initials-tile fallback below, where it IS the\n // glyph's only color.\n background: \"var(--w6w-icon-swatch, var(--w6w-panel-2))\",\n }}\n />\n );\n }\n\n const initials = (name ?? \"?\")\n .split(/\\s+/)\n .slice(0, 2)\n .map((s) => s[0]?.toUpperCase() ?? \"\")\n .join(\"\");\n\n return (\n <span\n aria-hidden=\"true\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: size,\n height: size,\n borderRadius: 6,\n background: brandColor ?? \"var(--w6w-accent)\",\n color: \"#fff\",\n fontWeight: 700,\n fontSize: Math.round(size * 0.42),\n flexShrink: 0,\n }}\n >\n {initials}\n </span>\n );\n}\n","/**\n * Provider + hook that give every component a single, typed w6w API client.\n *\n * Consumers wrap their app once and every component under it can grab the\n * client via `useW6WApi()` — no more per-component callback prop drilling.\n *\n * const api = createW6WApi({ baseUrl: \"/api\", token });\n * <W6WUIProvider api={api}>...</W6WUIProvider>\n *\n * Embedding inside a host app that has its own theme? Pass `theme` too — see\n * this file's `W6WUIProviderProps.theme` doc and `docs/theming.md`.\n */\nimport { type ReactNode, createContext, useContext } from \"react\";\nimport { ProvidedThemeCtx } from \"./theme.ts\";\nimport type {\n ActionDef,\n ApiCallRecord,\n AppSummary,\n AuthDef,\n ConnectionSummary,\n FunctionDetail,\n FunctionSummary,\n SavedTest,\n SubscriptionSummary,\n ThemeMode,\n TriggerSummary,\n WorkflowDetail,\n WorkflowSummary,\n} from \"./types.ts\";\n\n/**\n * A single tester-run summary from the unified `run_log` ledger, keyed to a\n * connection. Thin by design — the full result payload stays server-side in\n * `saved_test_runs`; this is the history row shown in the test screens.\n * `summary` is null when the run recorded no summary; `occurredAt` is ISO.\n */\nexport interface TestRunSummary {\n id: string;\n actionKey: string;\n ok: boolean;\n summary: string | null;\n occurredAt: string;\n}\n\n/**\n * Which app, version, action and connection a step ran with. A local structural\n * copy of the engine's `StepMeta` (`@w6w/workflow-types`); the server sanitizes it.\n */\nexport interface StepMeta {\n app: string;\n version: string;\n action: string;\n connectionId: string | null;\n}\n\n/**\n * A saved per-step test fixture — a reusable, project-owned named capture of a\n * workflow step's resolved incoming state (`input`) and its params (`with`),\n * keyed by `(workflowId, stepId)`. Mirrors the connection-scoped `SavedTest`,\n * re-keyed to a workflow step. `lastRun*` denormalizes the most recent run.\n */\nexport interface StepTest {\n id: string;\n workflowId: string;\n stepId: string;\n name: string | null;\n input: Record<string, unknown>;\n with: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n /** When this fixture was last run (ISO), or null/undefined if never run. */\n lastRunAt?: string | null;\n /** The most recent run's status (e.g. `succeeded`/`failed`), or null. */\n lastRunStatus?: string | null;\n /** The most recent run's error payload, or null when it succeeded/never ran. */\n lastRunError?: unknown;\n /** The most recent run's captured output, or null. */\n lastRunOutput?: unknown;\n /** The most recent run's step metadata; omitted when the server has none. */\n lastRunMeta?: StepMeta | null;\n}\n\n/**\n * The **start state** a single-step invoke may carry — the RFC's third\n * `executeNode(workflow, nodeId, startState)` argument\n * (`core/rfcs/node-types.md`), sent as the invoke body's `state` field.\n *\n * Structurally the server's `StartStateInput`\n * (`server/packages/api/ambient-scope.ts`): `steps` seeds `steps.<id>.output`\n * and `trigger.event` seeds `trigger.event`, so a `with` block written as\n * `{{ steps.<id>.output.<field> }}` resolves instead of concatenating as `\"\"`.\n * Anything else in it is ignored server-side — `vars`, `documents` and\n * `secrets` are host-owned and loaded from the caller's authenticated scope, so\n * a start state can only echo back data the caller already had.\n *\n * ⚠️ It is honoured by the **single-step** invoke route only. A full run\n * (`POST /workflows/:id/run`) builds its own scope and takes nothing from here.\n */\nexport interface StepStartState {\n /** Outputs of steps that already ran, keyed by step id → `steps.<id>.output`. */\n steps?: Record<string, { output?: unknown; meta?: StepMeta }>;\n /** Trigger context; only `event` is honoured → `trigger.event`. */\n trigger?: { event?: unknown };\n}\n\n/**\n * A caller-supplied override merged into an app action's outbound request at\n * the wire — the escape hatch for a vendor field the Action's own `params`\n * don't declare (`.claude/docs/overrides.md`). Rides on the invocation\n * envelope beside `params`, never inside it; `resolveParams` never sees it.\n * Mirrors the server's `RequestOverrides`\n * (`core/packages/types/src/overrides.ts`) structurally.\n */\nexport interface RequestOverrides {\n /** Merged over the request body — deep-merges objects, index-merges arrays. */\n body?: Record<string, unknown>;\n /** Merged into the URL's query string; `null` removes a key the action set. */\n query?: Record<string, string | number | boolean | null>;\n /** Added to the request headers; applied before the auth `sign` hook, so it can't hijack it. */\n headers?: Record<string, string>;\n /** Which outbound request receives the overrides. Defaults to `\"first\"`. */\n target?: \"first\" | \"first-write\" | \"all\";\n /** Restrict the merge to requests whose URL contains this substring. */\n match?: string;\n}\n\n/**\n * The surface every w6w-io component may call. Grows as we add components;\n * new members are added at the end so consumer implementations only need to\n * grow when they want to use the new component.\n */\n/**\n * Options for {@link W6WApi.listAppsPage} — one bounded, server-paged\n * request. Every member is optional; an omitted member is a host-defined\n * default (usually \"no filter\"/\"first page\"), never a client-side guess.\n */\nexport interface ListAppsPageOptions {\n /** Full-text search term, forwarded to the server verbatim. */\n q?: string;\n /** Server-side category filter (e.g. `\"ai\"`). */\n category?: string;\n /** Opaque pagination cursor from a prior {@link AppsPageResult.nextCursor}. */\n cursor?: string;\n /** Page size; a host may clamp this to its own bounds. */\n limit?: number;\n /** Ask the host for a bounded picker-summary projection (heavy fields like inline icons may be trimmed). */\n compact?: boolean;\n /** Abort this request. Local request control only; never a wire field. */\n signal?: AbortSignal;\n}\n\n/** One page of apps, as returned by {@link W6WApi.listAppsPage}. */\nexport interface AppsPageResult {\n apps: AppSummary[];\n /** Present unless this is the last page. */\n nextCursor?: string;\n}\n\nexport interface W6WApi {\n /**\n * List registered apps to pick from in the connection modal.\n *\n * OPTIONAL: the legacy, full-catalog counterpart to {@link listAppsPage}\n * and {@link listAppsByIds} — `createW6WApi.ts`'s own implementation still\n * provides it, and every bounded seam above is preferred wherever a host\n * implements it. Callers MUST guard on `typeof api.listApps === \"function\"`\n * before invoking it: a host with neither this nor a bounded seam settles\n * into that call site's own existing empty state instead of making a\n * request, never a crash.\n */\n listApps?(): Promise<AppSummary[]>;\n\n /**\n * Fetch ONE bounded, server-paged slice of the app catalog — the seam every\n * bounded picker UI (`AppPicker`'s paged mode, `StepBuilderModal`'s\n * Apps/AI/Triggers tabs) prefers over {@link listApps} when a host\n * implements it. OPTIONAL and ADDITIVE: an older/imported provider that\n * only implements `listApps` still typechecks and simply keeps the\n * eager-list behavior everywhere this member is absent — and a host with\n * neither this nor `listApps` settles into each caller's own existing empty\n * state instead of ever requesting a catalog.\n */\n listAppsPage?(options?: ListAppsPageOptions): Promise<AppsPageResult>;\n\n /**\n * Resolve a bounded, explicit set of app ids to their summaries — the seam\n * behind the \"Ready to use\" tab's connected-app batching and\n * `AddConnectionModal`'s `initialAppId` resolution: a caller that already\n * knows exactly which ids it needs never has to fetch (or filter) the whole\n * catalog to find them. OPTIONAL, like {@link listAppsPage}: absent, a\n * caller falls back to its pre-existing `listApps`-based resolution; absent\n * too, that caller settles into its own not-found/empty outcome instead of\n * ever calling an undefined function.\n * Missing/404 ids are simply omitted from the result, never an error for\n * the whole batch.\n */\n listAppsByIds?(ids: readonly string[], options?: { signal?: AbortSignal }): Promise<AppSummary[]>;\n\n /** Load auth methods declared by an app's manifest, with availability flags. */\n getAppAuth(appId: string): Promise<AuthDef[]>;\n\n /** Create a non-OAuth connection with a user-supplied credential. */\n createConnection(\n appId: string,\n body: {\n authKey: string;\n credential: Record<string, unknown>;\n displayName?: string;\n profile?: Record<string, unknown>;\n },\n ): Promise<ConnectionSummary>;\n\n /**\n * Start an OAuth 2.0 flow. Server builds the provider's authorize URL and\n * returns it; the caller opens it in a popup and awaits the server's\n * callback message (see `startOAuthPopup`).\n */\n startAppOAuthFlow(\n appId: string,\n authKey: string,\n body: { displayName?: string },\n ): Promise<{ authorizationUrl: string }>;\n\n /** List the actions an app exposes, to pick from in the step builder. */\n getAppActions(appId: string): Promise<ActionDef[]>;\n\n /** List the connections that already exist for a given app. */\n listConnectionsForApp(appId: string): Promise<ConnectionSummary[]>;\n\n /** List every connection across apps — drives the \"Connected apps\" tab. */\n listConnections(): Promise<ConnectionSummary[]>;\n\n /**\n * Invoke a single action — used to test-run one step from the visual editor.\n * Pass `connectionId` to run with a stored connection's credential. Pass\n * `project` to resolve document expressions against the workflow's selected\n * project (omitted → the scope's default/starter project). Pass `state` — the\n * {@link StepStartState} — so `{{ steps.<id>.output.<field> }}` in the params\n * resolves against what those upstream steps last produced; omitted, every\n * such reference resolves to the empty string.\n *\n * `apiCalls` carries the outbound HTTP calls the action made (redacted); a\n * failed invoke rejects with an `ApiError` whose `body ?? raw` holds the same\n * field (ui's own class carries it on `body`, `@w6w/sdk`'s on `raw`).\n *\n * Pass `overrides` — a {@link RequestOverrides} — to reach a vendor field the\n * action's own params don't declare. It rides on the invocation envelope,\n * never merged into `params`; an absent or empty envelope is a no-op.\n */\n invokeAction(\n appId: string,\n actionKey: string,\n params: Record<string, unknown>,\n opts?: {\n connectionId?: string;\n project?: string;\n state?: StepStartState;\n overrides?: RequestOverrides;\n },\n ): Promise<{\n value: unknown;\n logs?: string[];\n apiCalls?: ApiCallRecord[];\n meta?: StepMeta;\n }>;\n\n /** List the saved action-test inputs stored against a connection. */\n listSavedTests(connectionId: string): Promise<SavedTest[]>;\n\n /** Save a new set of action-test inputs against a connection. */\n createSavedTest(\n connectionId: string,\n body: { actionKey: string; name: string; values: Record<string, unknown> },\n ): Promise<SavedTest>;\n\n /** Rename a saved test or replace its stored input values. */\n updateSavedTest(\n connectionId: string,\n id: string,\n patch: { name?: string; values?: Record<string, unknown> },\n ): Promise<SavedTest>;\n\n /** Delete a saved test by id. */\n deleteSavedTest(connectionId: string, id: string): Promise<void>;\n\n /**\n * Record the outcome of an action-test run against a connection. Appends a\n * run-log row server-side; when `savedTestId` is present the saved test's\n * `lastRun*` fields are updated too. POSTs to `/connections/:connId/test-runs`.\n */\n recordTestRun(\n connId: string,\n body: {\n savedTestId?: string | null;\n actionKey: string;\n ok: boolean;\n summary?: string;\n result?: unknown;\n },\n ): Promise<void>;\n\n /**\n * List a connection's recent tester-run history from the unified `run_log`\n * ledger (`GET /connections/:connId/test-runs` → the `.runs` array). Powers\n * the run-history list in the test screens, complementing the per-test\n * `lastRun*` badge with the full ledger.\n *\n * OPTIONAL: consumers that don't render history (or haven't wired it up yet)\n * may omit it, so a missing member never poisons their typecheck. Callers\n * MUST guard on its presence before invoking.\n */\n listTestRuns?(connectionId: string): Promise<TestRunSummary[]>;\n\n /**\n * Save a reusable per-step test fixture against a workflow step. Captures the\n * resolved incoming state (`input`) and the step's params (`with`); the server\n * stores both verbatim, project-owned. Mirrors `createSavedTest`, re-keyed from\n * a connection to a `(workflowId, stepId)`. POSTs to\n * `/workflows/:workflowId/steps/:stepId/tests`.\n */\n saveStepTest(\n workflowId: string,\n stepId: string,\n body: { name?: string; input: Record<string, unknown>; with: Record<string, unknown> },\n ): Promise<StepTest>;\n\n /**\n * Record the outcome of a step-test run so every run (saved or ad-hoc) is\n * logged authoritatively server-side. The run row mirrors `node_executions`\n * (status/input/output/error). When `stepTestId` is present the fixture's\n * `lastRun*` fields are updated too. Mirrors `recordTestRun`, re-keyed to a\n * workflow step. POSTs to `/workflows/:workflowId/steps/:stepId/test-runs`.\n */\n recordStepTestRun(\n workflowId: string,\n stepId: string,\n body: {\n stepTestId?: string | null;\n status: string;\n input?: unknown;\n output?: unknown;\n error?: unknown;\n meta?: unknown;\n },\n ): Promise<void>;\n\n /**\n * List the saved test fixtures for a workflow step (project-owned, not\n * subject-filtered). Added now so the ui-only incoming-state picker and\n * test-gate tasks need no further studio change. Mirrors `listSavedTests`,\n * re-keyed to a `(workflowId, stepId)`. GETs\n * `/workflows/:workflowId/steps/:stepId/tests`.\n */\n listStepTests(workflowId: string, stepId: string): Promise<StepTest[]>;\n\n /**\n * List the caller's registered Functions (core rfcs/function.md) — drives\n * the step builder's Functions tab (F-2.0). GETs `/functions`.\n */\n listFunctions(): Promise<FunctionSummary[]>;\n\n /**\n * Load one Function's canonical interface (`inputs`), so the Functions tab\n * can render its Configure stage's `ParamsForm`. GETs `/functions/:id`.\n */\n getFunction(id: string): Promise<FunctionDetail>;\n\n /**\n * Invoke a Function directly — the Functions tab's Test stage\n * (`CallableStepConfig`), NOT the `@w6w/call` node's own run-time path (that\n * goes through `ctx.invokeCallable`, host-side). Returns the raw output —\n * `unknown`, not an invocation envelope — matching the committed\n * `studio/src/repos/functions.ts`. POSTs `/functions/:id/invoke`.\n */\n invokeFunction(id: string, inputs: Record<string, unknown>): Promise<unknown>;\n\n /**\n * List the caller's registered Workflows — drives the step builder's\n * Workflows tab (F-2.0). GETs `/workflows`.\n */\n listWorkflows(): Promise<WorkflowSummary[]>;\n\n /**\n * Load one Workflow's full definition, so the Workflows tab can derive its\n * entry/trigger step's declared `with.fields` for the Configure stage's\n * `ParamsForm`. GETs `/workflows/:id`.\n */\n getWorkflow(id: string): Promise<WorkflowDetail>;\n\n /**\n * Run a Workflow synchronously — the Workflows tab's Test stage (D-11/\n * D-15(c)): the SAME `?wait=true` path the saved `@w6w/call` step takes at\n * run time, never a client-side enqueue-and-poll. `terminal` is derived from\n * the response's HTTP status (`200` ⇒ `true`, the server's own `202`\n * synchronous-wait timeout ⇒ `false` — a legitimate \"still running\" outcome,\n * not an error). POSTs `/workflows/:id/run?wait=true`.\n */\n runWorkflow(\n id: string,\n opts?: { variables?: Record<string, unknown>; input?: Record<string, unknown> },\n ): Promise<{\n runId: string;\n status: string;\n output?: unknown;\n error?: unknown;\n terminal: boolean;\n }>;\n\n /**\n * List apps that declare at least one trigger — the Triggers tab's\n * \"App triggers\" section (T-0). GETs whatever the host resolves to (e.g.\n * apps filtered by `triggerCount > 0`).\n *\n * OPTIONAL, like `listTestRuns?` above: a host that hasn't wired this member\n * still typechecks and simply doesn't render the App-triggers section.\n */\n listTriggerApps?(): Promise<AppSummary[]>;\n\n /**\n * List one app's declared triggers. GETs `/apps/:id/triggers`.\n */\n getAppTriggers?(appId: string): Promise<TriggerSummary[]>;\n\n /**\n * List the Subscriptions bound to one workflow (rfcs/trigger.md). Powers\n * the webhook-URL panel's get-or-create check (I-2) — GETs\n * `/workflows/:id/subscriptions`.\n */\n listSubscriptionsForWorkflow?(workflowId: string): Promise<SubscriptionSummary[]>;\n\n /**\n * Create a Subscription binding an app trigger to a workflow — the one\n * explicit user action both the Triggers-tab app section (T-0) and the\n * webhook-URL panel (I-2) call, per DECISIONS.md HITL-1. POSTs\n * `/apps/:id/triggers/:key/subscriptions`.\n */\n createSubscription?(\n appId: string,\n triggerKey: string,\n input: {\n workflowId: string;\n connectionId?: string | null;\n params?: Record<string, unknown>;\n /** Poll triggers only, in milliseconds. */\n intervalMs?: number;\n },\n ): Promise<SubscriptionSummary>;\n}\n\nconst Ctx = createContext<W6WApi | null>(null);\n\nexport interface W6WUIProviderProps {\n api: W6WApi;\n /**\n * Force the theme every `@w6w/ui` component resolves to — both the CSS\n * tokens (`styles.css`'s `:where([data-theme=...])` blocks) and the\n * JS-side theme-aware components (`AppIcon`, `CodeEditor`, `JsonEditor`,\n * `WorkflowFlowEditor`, via `useEffectiveTheme`) — instead of each one\n * independently falling back to `data-theme` on `<html>` or the visitor's\n * OS `prefers-color-scheme`.\n *\n * Omit to keep that pre-existing default — the right choice for `@w6w/ui`'s\n * own app (studio), which already manages `data-theme` on `<html>` itself.\n * But it's a silent trap for a HOST embedding these components inside its\n * own page: without this prop, `@w6w/ui` resolves its theme from the\n * visitor's OS setting, independently of whatever theme the host's own\n * page is using — a visitor with a dark-mode OS preference gets `@w6w/ui`\n * components rendered in ITS dark palette sitting inside an otherwise-light\n * host page (or vice versa). Pass your host's own resolved theme here to\n * make `@w6w/ui` follow it instead. See `docs/theming.md`.\n */\n theme?: ThemeMode;\n children: ReactNode;\n}\n\n/**\n * Provides the w6w API client to every component under it, and — when\n * `theme` is given — forces `@w6w/ui`'s theme to match it (see\n * `W6WUIProviderProps.theme` above). Setting `theme` wraps `children` in a\n * `data-theme` DOM node: CSS custom properties cascade to every descendant\n * regardless of specificity, so this alone is enough for every `@w6w/ui`\n * stylesheet rule to resolve correctly — no need to also set the attribute\n * on `<html>` yourself. `display: contents` keeps that wrapper invisible to\n * layout (flex/grid gap, `:nth-child`, etc. all behave as if it weren't\n * there).\n */\nexport function W6WUIProvider({ api, theme, children }: W6WUIProviderProps) {\n const content = (\n <Ctx.Provider value={api}>\n <ProvidedThemeCtx.Provider value={theme}>{children}</ProvidedThemeCtx.Provider>\n </Ctx.Provider>\n );\n if (!theme) return content;\n return (\n <div data-theme={theme} style={{ display: \"contents\" }}>\n {content}\n </div>\n );\n}\n\n/**\n * Access the w6w API client. Throws a helpful error if used outside a\n * `<W6WUIProvider>` — the common mistake is forgetting to wrap the app root.\n */\nexport function useW6WApi(): W6WApi {\n const api = useContext(Ctx);\n if (!api) {\n throw new Error(\n \"useW6WApi must be used inside <W6WUIProvider>. \" +\n \"Wrap your app root with <W6WUIProvider api={api}>...</W6WUIProvider>.\",\n );\n }\n return api;\n}\n\n/**\n * The workflow's currently-selected project id, provided by the editor so an\n * ad-hoc test-invoke resolves document expressions against that project (not the\n * scope's default/starter project). `undefined` — no project provided — keeps the\n * server's default-project behavior. Deliberately not throwing when absent: test\n * panels render outside the editor too (e.g. connection screens).\n */\nconst WorkflowProjectCtx = createContext<string | undefined>(undefined);\n\n/** Scopes test-invokes under it to `project`; the editor wraps its body with this. */\nexport function WorkflowProjectProvider({\n project,\n children,\n}: {\n project?: string;\n children: ReactNode;\n}) {\n return <WorkflowProjectCtx.Provider value={project}>{children}</WorkflowProjectCtx.Provider>;\n}\n\n/** The selected workflow project id in scope, or `undefined` outside the editor. */\nexport function useWorkflowProject(): string | undefined {\n return useContext(WorkflowProjectCtx);\n}\n","import { type ReactNode, useCallback, useEffect, useReducer, useRef, useState } from \"react\";\nimport { deriveCategories, matchesCategories } from \"./app-categories.ts\";\nimport {\n type AppsPageQuery,\n appsPageReducer,\n excludeInternalApps,\n initialAppsPageState,\n} from \"./app-pages.ts\";\nimport { AppIcon } from \"./components/AppIcon.tsx\";\nimport { useW6WApi } from \"./provider.tsx\";\nimport type { AppSummary, ThemeMode } from \"./types.ts\";\n\n/**\n * Category-filter chip row collapse budget (D-1a: \"collapsed to a fixed\n * count budget with a `+N more` toggle\", \"≈2 rows\"). An implementation\n * constant, not part of the public API.\n */\nconst CHIP_VISIBLE_BUDGET = 8;\n\n/**\n * Default bounded page size for the paged loading path (T2.1.1 A2: \"Apps/AI\n * request one page (limit at most 60)\"). Also the default for any other\n * paged-mode caller of this component that does not override `pageLimit`.\n */\nconst DEFAULT_PAGE_LIMIT = 60;\n\n/** How long to wait after the last keystroke before firing a server search. */\nconst SEARCH_DEBOUNCE_MS = 300;\n\nexport interface AppPickerProps {\n /** Fired when the user picks an app card. */\n onSelectApp: (app: AppSummary) => void;\n theme?: ThemeMode;\n /** Optional pre-filter over the app list (e.g. only connectable apps). Applied CLIENT-side, on top of whatever page/list was fetched — never widens a fetch, only narrows what's shown. */\n filter?: (app: AppSummary) => boolean;\n /** Search-box placeholder. Defaults to \"Search apps…\". */\n searchPlaceholder?: string;\n /** Message shown when the (filtered) app list is empty. */\n emptyMessage?: string;\n /** Render the search input. Defaults to `true`; the connected-apps list opts out. */\n search?: boolean;\n /** Rendered beneath `emptyMessage` in the empty state (e.g. a \"Browse all apps\" button). */\n emptyAction?: ReactNode;\n /**\n * Supply the catalog instead of letting the picker fetch it. For a caller\n * that already holds the list — and, more to the point, that decides\n * membership from fields this package's {@link AppSummary} does not carry\n * (`supportsOAuth`, `owner`): passing the decided list keeps ONE list and one\n * loading/error state, where `filter` would mean a second `listApps()` whose\n * result can disagree with the caller's. `null` is \"still loading\" and\n * renders the same placeholder the internal fetch does. Supplying a list\n * (including `null`) always suppresses BOTH the legacy eager fetch and the\n * bounded paged fetch below.\n */\n apps?: AppSummary[] | null;\n /**\n * Render an opt-in category-filter chip row, derived from the VISIBLE\n * catalog's own `categories` values (never the full RFC vocabulary — see\n * `app-categories.ts`). Defaults to `false`. Only {@link AddConnectionModal}\n * turns this on today — both `StepBuilderModal` picker call sites already\n * narrow their catalog through `filter`, so a second filter layer there\n * would be redundant.\n */\n categoryFilter?: boolean;\n /**\n * Server-side `category` param for the bounded paged fetch (e.g. `\"ai\"` for\n * the AI tab) — sent to `W6WApi.listAppsPage`, never applied client-side.\n * Ignored when `apps` is supplied or the host has no `listAppsPage`.\n */\n category?: string;\n /** Bounded page size for the paged fetch. Defaults to {@link DEFAULT_PAGE_LIMIT} (60). */\n pageLimit?: number;\n /**\n * Optional page loader that takes precedence over `W6WApi.listAppsPage` and\n * turns on the paged mode by itself (ignored when `apps` is supplied). It\n * is called with exactly `{ q, cursor, limit, signal }` — never `category`\n * or `compact` — and reuses the picker's debounce, stale-response guard,\n * abort, Load more and Retry. Held in a ref: its identity may change every\n * render without causing a request.\n */\n loadPage?: (options: {\n q?: string;\n cursor?: string;\n limit: number;\n signal: AbortSignal;\n }) => Promise<{ apps: AppSummary[]; nextCursor?: string }>;\n}\n\n/**\n * Searchable grid of app cards (icon + name + id + version) — the shared app picker used\n * by both the step builder and the add-connection modal.\n *\n * **Three loading modes**, chosen automatically and mutually exclusive:\n *\n * 1. `apps` supplied (including `null`) — the caller owns loading; this\n * component only renders.\n * 2. `apps` omitted and the host implements `W6WApi.listAppsPage` — bounded\n * server-paged loading: one page per search/category, explicit\n * \"Load more\", debounced search, cancellation on query change/unmount\n * (T2.1.1 A2). This is the path every current call site in this package\n * reaches once its host wires the optional method.\n * 3. `apps` omitted and the host has ONLY the legacy `W6WApi.listApps` —\n * unchanged eager full-catalog fetch, preserved byte-for-byte for\n * backward compatibility with an older/imported provider (C6). A host\n * with neither `listAppsPage` nor `listApps` settles into this same\n * mode's existing empty state — no request, no throw.\n */\nexport function AppPicker({\n onSelectApp,\n theme,\n filter,\n searchPlaceholder,\n emptyMessage,\n search = true,\n emptyAction,\n apps: providedApps,\n categoryFilter = false,\n category,\n pageLimit = DEFAULT_PAGE_LIMIT,\n loadPage,\n}: AppPickerProps) {\n const api = useW6WApi();\n // `undefined` means \"not supplied\" — a supplied `null` is a caller whose own\n // fetch has not resolved yet, which must NOT start a second one.\n const supplied = providedApps !== undefined;\n // Capability detection is `typeof === \"function\"` ONLY — never inferred\n // from a runtime response shape. A response this component cannot use (not\n // an array of apps), on a first page or a load-more alike, is a retryable\n // safe error (A6), never evidence that the optional method \"isn't really\n // implemented\": that conflation previously let one transiently-malformed\n // response permanently and silently revert a genuinely bounded host to the\n // unbounded `listApps()` for the rest of the component's lifetime, tainting\n // every tab sharing this mounted instance (T2.1.1 ROUND 2). A host that\n // truly lacks `listAppsPage` must answer `undefined` for it, not a callable\n // stub that returns the wrong shape — see the fixed test fixtures this\n // package's own suites now use (`StepBuilderModal.connection-only/\n // homepage-tabs/template-node.test.ts`) rather than working around a\n // stub's shape in production semantics.\n const paged = !supplied && (loadPage !== undefined || typeof api.listAppsPage === \"function\");\n const loadPageRef = useRef(loadPage);\n loadPageRef.current = loadPage;\n\n // ── Mode 3: legacy eager full-catalog fetch (unchanged, plus the fallback above) ──\n const [fetchedApps, setFetchedApps] = useState<AppSummary[] | null>(null);\n const [legacyError, setLegacyError] = useState<string | null>(null);\n\n useEffect(() => {\n if (supplied || paged) return;\n const listApps = api.listApps;\n // A host with neither `listAppsPage` (checked above, via `paged`) nor\n // `listApps` settles here into the empty catalog — not a permanent\n // \"Loading apps…\" and not a call to an undefined function — exactly the\n // pre-existing empty-state branch below (`base.length === 0`).\n if (typeof listApps !== \"function\") {\n setFetchedApps([]);\n return;\n }\n let canceled = false;\n listApps()\n .then((r) => !canceled && setFetchedApps(r))\n .catch((e) => !canceled && setLegacyError((e as Error).message));\n return () => {\n canceled = true;\n };\n }, [api, supplied, paged]);\n\n // ── Mode 2: bounded paged fetch ────────────────────────────────────────────\n const [pageState, dispatch] = useReducer(\n appsPageReducer,\n initialAppsPageState({ q: \"\", category }, 0),\n );\n const [inputValue, setInputValue] = useState(\"\");\n const [debouncedQuery, setDebouncedQuery] = useState(\"\");\n // Mirrors `pageState.generation` synchronously — an async `.then`/`.catch`\n // callback closes over the generation IT was issued with, and compares\n // against this ref (not the React state, which the callback's own closure\n // cannot see update) to decide whether its own result is still wanted.\n const generationRef = useRef(0);\n const abortRef = useRef<AbortController | null>(null);\n\n const fetchPage = useCallback(\n (query: AppsPageQuery, generation: number, cursor: string | undefined) => {\n const custom = loadPageRef.current;\n const listAppsPage = api.listAppsPage;\n if (!custom && !listAppsPage) return;\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n // A loader that throws synchronously must land in the same error/Retry\n // state as a rejected promise (and not defer the call: request-shape\n // timing is observable).\n let request: ReturnType<NonNullable<typeof custom>>;\n try {\n request = custom\n ? custom({\n q: query.q || undefined,\n cursor,\n limit: pageLimit,\n signal: controller.signal,\n })\n : (listAppsPage as NonNullable<typeof listAppsPage>)({\n q: query.q || undefined,\n category: query.category,\n cursor,\n limit: pageLimit,\n compact: true,\n signal: controller.signal,\n });\n } catch (e) {\n request = Promise.reject(e);\n }\n request\n .then((page) => {\n if (generationRef.current !== generation) return; // stale: a newer query/unmount won\n if (!page || !Array.isArray((page as { apps?: unknown }).apps)) {\n // A6: a malformed envelope — first page or \"load more\" alike — is\n // always a safe, retryable error, never a crash and never treated\n // as proof the optional method \"isn't really implemented\" (that\n // capability question is `typeof api.listAppsPage === \"function\"`\n // alone, checked once above `paged`'s definition). Already-shown\n // apps (if any) are preserved.\n dispatch({\n type: \"page-failed\",\n generation,\n error: \"The server returned a malformed apps page.\",\n });\n return;\n }\n dispatch({\n type: \"page-loaded\",\n generation,\n apps: page.apps,\n nextCursor: page.nextCursor,\n requestedCursor: cursor,\n });\n })\n .catch((e: unknown) => {\n if (generationRef.current !== generation) return;\n // Our own cancellation (query change / unmount) — not a user-facing\n // error; the newer request (or nothing, on unmount) owns the state.\n if (e instanceof Error && e.name === \"AbortError\") return;\n dispatch({ type: \"page-failed\", generation, error: (e as Error).message });\n });\n },\n [api, pageLimit],\n );\n\n // Debounce the search box; cancelled on every keystroke and on unmount.\n useEffect(() => {\n if (!paged) return;\n const t = setTimeout(() => setDebouncedQuery(inputValue.trim()), SEARCH_DEBOUNCE_MS);\n return () => clearTimeout(t);\n }, [inputValue, paged]);\n\n // A new debounced query or a new `category` (e.g. the AI tab reusing this\n // same mounted component after Apps→AI) starts a fresh bounded fetch and\n // aborts whatever the previous one was still waiting on.\n useEffect(() => {\n if (!paged) return;\n const generation = ++generationRef.current;\n const query: AppsPageQuery = { q: debouncedQuery, category };\n dispatch({ type: \"query-changed\", query, generation });\n fetchPage(query, generation, undefined);\n return () => {\n abortRef.current?.abort();\n };\n }, [paged, debouncedQuery, category, fetchPage]);\n\n // Abort any still-pending request when the component itself unmounts (tab\n // switch away, modal close) even if no new query/category fired above.\n useEffect(() => {\n if (!paged) return;\n return () => abortRef.current?.abort();\n }, [paged]);\n\n const loadMore = () => {\n if (!paged || pageState.status !== \"ready\" || !pageState.hasMore) return;\n const generation = generationRef.current;\n dispatch({ type: \"load-more\" });\n fetchPage(pageState.query, generation, pageState.cursor);\n };\n\n const retry = () => {\n if (!paged || pageState.status !== \"error\") return;\n dispatch({ type: \"retry\" });\n fetchPage(pageState.query, generationRef.current, pageState.cursor);\n };\n\n const [selectedCats, setSelectedCats] = useState<string[]>([]);\n const [catsExpanded, setCatsExpanded] = useState(false);\n\n // Single layout owner for all exits below, so the panel never resizes\n // between error/loading/empty and the loaded list — see `.w6w-apppicker-host`.\n const host = (body: ReactNode) => <div className=\"w6w-apppicker-host\">{body}</div>;\n\n // ── Resolve the raw app list for the active mode ───────────────────────────\n let rawApps: AppSummary[] | null;\n let fatalError: string | null = null;\n let loadingMore = false;\n let hasMore = false;\n let pageError: string | null = null;\n // Paged-only: true while a query change (search/category, INCLUDING the\n // very first mount) has reset `apps` and is awaiting its first page. Unlike\n // the non-paged modes' one-time `rawApps === null`, this must NOT hide the\n // search box/chip row on every subsequent search — only the initial mount\n // has no shell to preserve; every later keystroke should keep the input (and\n // whatever was already on screen) interactive while the new page loads.\n let pagedInitialLoading = false;\n\n if (supplied) {\n rawApps = providedApps ?? null;\n } else if (paged) {\n rawApps = pageState.apps;\n pagedInitialLoading = pageState.status === \"loading\";\n loadingMore = pageState.status === \"loading-more\";\n hasMore = pageState.hasMore;\n if (pageState.status === \"error\") {\n if (pageState.apps.length === 0) fatalError = pageState.error ?? \"Failed to load apps.\";\n else pageError = pageState.error ?? \"Failed to load apps.\";\n }\n } else {\n rawApps = fetchedApps;\n fatalError = legacyError;\n }\n\n if (!paged && fatalError) return host(<div className=\"w6w-result w6w-error\">{fatalError}</div>);\n if (!paged && rawApps === null) {\n return host(<p className=\"w6w-muted w6w-small\">Loading apps…</p>);\n }\n rawApps ??= [];\n\n // Reserved `@w6w/*` pseudo-apps are added via the builder's \"Controls\" tab, not\n // as connectable apps — keep them out of this grid even after they register.\n const connectable = excludeInternalApps(rawApps);\n const base = filter ? connectable.filter(filter) : connectable;\n\n // Non-paged modes (supplied / legacy eager fetch) preserve the ORIGINAL,\n // pre-T2.1.1 behavior byte-for-byte: a truly empty candidate list is an\n // early return with no search box at all — there is nothing a search could\n // ever surface. Paged mode never takes this branch: a bounded first page\n // that filtered down to nothing may still have more pages behind a search\n // or \"Load more\", so the search box (and the rest of the shell) must stay\n // reachable — see the `visible.length === 0` branches below instead.\n if (!paged && base.length === 0) {\n return host(\n <div className=\"w6w-stack\">\n <p className=\"w6w-muted w6w-small\">\n {emptyMessage ?? \"No apps registered yet. Register one from the Apps page first.\"}\n </p>\n {emptyAction}\n </div>,\n );\n }\n\n // Category chips (opt-in — P4/P6): derived from `base`, the VISIBLE\n // catalog post the `filter` prop and pre-search, never from the raw `apps`\n // fetch and never from the RFC's full slug vocabulary — a category with no\n // apps behind it here is a dead end. In paged mode this is necessarily\n // scoped to the currently-loaded page(s), not the whole catalog. Chips over\n // the collapse budget stay hidden unless already selected (P5), so toggling\n // a selection never makes its own chip disappear.\n const chips = categoryFilter ? deriveCategories(base) : [];\n const withinBudget = chips.slice(0, CHIP_VISIBLE_BUDGET);\n const pinnedOverflow = chips\n .slice(CHIP_VISIBLE_BUDGET)\n .filter((c) => selectedCats.includes(c.slug));\n const collapsedChips = [...withinBudget, ...pinnedOverflow];\n const hiddenChipCount = chips.length - collapsedChips.length;\n const displayedChips = catsExpanded ? chips : collapsedChips;\n const toggleCat = (slug: string) =>\n setSelectedCats((prev) =>\n prev.includes(slug) ? prev.filter((s) => s !== slug) : [...prev, slug],\n );\n const clearCats = () => setSelectedCats([]);\n\n // Composition order (P4): the `filter` prop already ran (-> `base`); the\n // category-chip selection composes next; the search query runs last —\n // except in paged mode, where the search already happened server-side and\n // re-filtering locally on the (possibly stale, mid-debounce) input value\n // would just hide correct results for a beat.\n const catFiltered =\n categoryFilter && selectedCats.length > 0\n ? base.filter((a) => matchesCategories(a, selectedCats))\n : base;\n\n const sorted = paged\n ? catFiltered\n : [...catFiltered].sort((a, b) =>\n a.displayName.localeCompare(b.displayName, undefined, { sensitivity: \"base\" }),\n );\n // `q` drives LOCAL filtering only — empty in paged mode, since the server\n // already applied `inputValue` as its own `q` param. `searchActive` drives\n // message text and is always the user's real input, in every mode.\n const q = paged ? \"\" : inputValue.trim().toLowerCase();\n const searchActive = inputValue.trim().length > 0;\n const visible = q\n ? sorted.filter(\n (a) => a.displayName.toLowerCase().includes(q) || a.id.toLowerCase().includes(q),\n )\n : sorted;\n // A7: a category selection narrowed the list to nothing, distinct from the\n // search-only empty state below (and distinct from either alone: the\n // message names whichever of the two is actually active).\n const categoryEmpty = categoryFilter && selectedCats.length > 0 && visible.length === 0;\n\n return host(\n <div className=\"w6w-stepbuilder-apps\">\n {search && (\n <input\n type=\"text\"\n className=\"w6w-stepbuilder-search\"\n placeholder={searchPlaceholder ?? \"Search apps…\"}\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n aria-label=\"Search apps\"\n />\n )}\n {categoryFilter && chips.length > 0 && (\n <div className=\"w6w-apppicker-cats\">\n {displayedChips.map((c) => (\n <button\n key={c.slug}\n type=\"button\"\n className=\"w6w-apppicker-chip\"\n aria-pressed={selectedCats.includes(c.slug)}\n aria-label={`Filter by ${c.label}`}\n onClick={() => toggleCat(c.slug)}\n >\n {c.label} <span className=\"w6w-muted\">({c.count})</span>\n </button>\n ))}\n {!catsExpanded && hiddenChipCount > 0 && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n onClick={() => setCatsExpanded(true)}\n >\n +{hiddenChipCount} more\n </button>\n )}\n {catsExpanded && chips.length > CHIP_VISIBLE_BUDGET && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n onClick={() => setCatsExpanded(false)}\n >\n Show less\n </button>\n )}\n {selectedCats.length > 0 && (\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\" onClick={clearCats}>\n Clear\n </button>\n )}\n </div>\n )}\n {paged && pagedInitialLoading ? (\n <p className=\"w6w-muted w6w-small\">Loading apps…</p>\n ) : paged && fatalError ? (\n <div className=\"w6w-result w6w-error\">\n {fatalError}{\" \"}\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\" onClick={retry}>\n Retry\n </button>\n </div>\n ) : visible.length === 0 && !hasMore ? (\n categoryEmpty ? (\n <div className=\"w6w-stack\">\n <p className=\"w6w-muted w6w-small\">\n {searchActive\n ? `No apps match “${inputValue}” in the selected categories.`\n : \"No apps match the selected categories.\"}\n </p>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n onClick={() => {\n setSelectedCats([]);\n setInputValue(\"\");\n }}\n >\n Clear filters\n </button>\n </div>\n ) : !paged ? (\n // Original, unchanged text: reachable here only with a non-empty\n // query (an empty-query empty result was already handled by the\n // `base.length === 0` early return above, for this non-paged path).\n <p className=\"w6w-muted w6w-small\">No apps match “{inputValue}”.</p>\n ) : (\n <div className=\"w6w-stack\">\n <p className=\"w6w-muted w6w-small\">\n {searchActive\n ? `No apps match “${inputValue}”.`\n : (emptyMessage ??\n \"No apps registered yet. Register one from the Apps page first.\")}\n </p>\n {!searchActive && emptyAction}\n </div>\n )\n ) : (\n <>\n {visible.length === 0 && hasMore ? (\n // A page loaded but every entry was filtered out client-side\n // (internal/rejected/non-trigger/etc.) — never auto-drain the\n // next page to fill this in; the user's own \"Load more\" click is\n // the only thing allowed to fetch further.\n <p className=\"w6w-muted w6w-small\">\n No matching apps on this page yet — try “Load more”.\n </p>\n ) : (\n <div className=\"w6w-stepbuilder-list w6w-apppicker-grid w6w-stepbuilder-scroll\">\n {visible.map((a) => (\n <button\n key={a.id}\n type=\"button\"\n className=\"w6w-stepbuilder-item w6w-apppicker-card\"\n onClick={() => onSelectApp(a)}\n >\n <AppIcon\n src={a.iconSvg}\n srcDark={a.iconSvgDark}\n brandColor={a.brandColor}\n name={a.displayName}\n theme={theme}\n size={24}\n />\n <span className=\"w6w-stepbuilder-item-main\">\n <strong>{a.displayName}</strong>\n {/* The id is secondary metadata under the NAME, and it is the one\n field on this card with no length bound (`vendor-app-…`, a\n `@`-scoped id, a long slug), so it truncates rather than\n widening the card or wrapping to a second line — the tile's\n geometry is fixed by the grid, not by its longest id. */}\n <code className=\"w6w-apppicker-card-id\">{a.id}</code>\n {a.version && <span className=\"w6w-apppicker-card-version\">v{a.version}</span>}\n </span>\n </button>\n ))}\n </div>\n )}\n {paged && pageError && (\n <div className=\"w6w-result w6w-error w6w-small\">\n {pageError}{\" \"}\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\" onClick={retry}>\n Retry\n </button>\n </div>\n )}\n {paged && hasMore && !pageError && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm w6w-apppicker-load-more\"\n onClick={loadMore}\n disabled={loadingMore}\n >\n {loadingMore ? \"Loading more…\" : \"Load more\"}\n </button>\n )}\n </>\n )}\n </div>,\n );\n}\n","import type { KeyboardEventHandler } from \"react\";\nimport type { AuthField } from \"../types.ts\";\n\ninterface Props {\n fields: AuthField[];\n values: Record<string, unknown>;\n onChange: (values: Record<string, unknown>) => void;\n /**\n * Spread onto every field's `<input>` — from the caller's own\n * `useEnterSubmit(submit, { enabled })`, so Enter in a credential field\n * submits the same way the form's primary button does. Optional so this\n * component still works with no submit-on-Enter wiring at all.\n */\n enterSubmitProps?: { onKeyDown: KeyboardEventHandler<HTMLElement> };\n}\n\n/**\n * Renders the form for an Auth method's `fields` declaration. Field shape\n * comes from the app's manifest so no app-specific knowledge is needed here.\n */\nexport function AuthFieldsForm({ fields, values, onChange, enterSubmitProps }: Props) {\n const update = (key: string, value: unknown) => onChange({ ...values, [key]: value });\n\n return (\n <div className=\"w6w-stack\">\n {fields.length === 0 && (\n <p className=\"w6w-muted w6w-small\">\n This auth method declares no fields — nothing to fill in. The credential will be an empty\n object.\n </p>\n )}\n {fields.map((field) => {\n const value = (values[field.key] ?? field.default ?? \"\") as string | number | boolean;\n if (field.type === \"boolean\") {\n return (\n <label key={field.key} className=\"w6w-field\">\n <span>\n <input\n type=\"checkbox\"\n checked={Boolean(value)}\n onChange={(e) => update(field.key, e.target.checked)}\n {...enterSubmitProps}\n />\n {field.label}\n {field.required ? \" *\" : \"\"}\n </span>\n {field.hint && <span className=\"w6w-hint\">{field.hint}</span>}\n </label>\n );\n }\n const isSecret = field.type === \"secret\";\n // Credentials (API keys, tokens) are NOT login passwords. Never use\n // `type=\"password\"` — that's the sole trigger for the browser's\n // \"save password?\" prompt and for suggesting saved passwords. Secrets are\n // plain text fields masked with CSS (`-webkit-text-security`) so they\n // still read as dots without ever being a password field.\n const inputType = field.type === \"number\" ? \"number\" : \"text\";\n return (\n <label key={field.key} className=\"w6w-field\">\n <span>\n {field.label}\n {field.required ? \" *\" : \"\"}\n </span>\n <input\n type={inputType}\n className={isSecret ? \"w6w-secret-input\" : undefined}\n value={String(value ?? \"\")}\n onChange={(e) =>\n update(field.key, field.type === \"number\" ? Number(e.target.value) : e.target.value)\n }\n // Belt-and-braces opt-out from browser autofill + password managers.\n name={`w6w-cred-${field.key}`}\n autoComplete=\"off\"\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n data-1p-ignore=\"true\"\n data-lpignore=\"true\"\n data-bwignore=\"true\"\n data-form-type=\"other\"\n {...enterSubmitProps}\n />\n {field.hint && <span className=\"w6w-hint\">{field.hint}</span>}\n </label>\n );\n })}\n </div>\n );\n}\n","/**\n * Open an OAuth 2.0 authorize URL in a popup and resolve when the callback\n * page posts a `w6w: \"oauth-result\"` message back to the opener.\n *\n * The server-rendered callback page (see the w6w server) posts one of:\n * { w6w: \"oauth-result\", ok: true, connectionId: string }\n * { w6w: \"oauth-result\", ok: false, error: string }\n *\n * Rejects if:\n * - The popup was blocked (`window.open` returned null).\n * - The user closed the popup without completing the flow.\n * - The server signaled failure.\n */\nexport interface OAuthPopupResult {\n connectionId: string;\n}\n\nconst POPUP_FEATURES = \"width=560,height=720,menubar=no,toolbar=no,location=no\";\n\nexport function startOAuthPopup(authorizationUrl: string): Promise<OAuthPopupResult> {\n return new Promise((resolve, reject) => {\n const popup = window.open(authorizationUrl, \"w6w-oauth\", POPUP_FEATURES);\n if (!popup) {\n reject(new Error(\"Popup blocked — allow popups for this site and try again.\"));\n return;\n }\n\n let done = false;\n const cleanup = () => {\n done = true;\n window.removeEventListener(\"message\", onMessage);\n window.clearInterval(pollHandle);\n };\n\n const onMessage = (event: MessageEvent) => {\n const data = event.data as\n | { w6w?: string; ok?: boolean; connectionId?: string; error?: string }\n | undefined;\n if (data?.w6w !== \"oauth-result\") return;\n cleanup();\n try {\n popup.close();\n } catch {\n /* popup may already be closed */\n }\n if (data.ok && typeof data.connectionId === \"string\") {\n resolve({ connectionId: data.connectionId });\n } else {\n reject(new Error(data.error ?? \"OAuth flow failed.\"));\n }\n };\n window.addEventListener(\"message\", onMessage);\n\n // If the user closes the popup without completing the flow the message\n // never arrives; detect that with a low-freq poll and reject cleanly.\n const pollHandle = window.setInterval(() => {\n if (done) return;\n if (popup.closed) {\n cleanup();\n reject(new Error(\"OAuth popup was closed before the flow completed.\"));\n }\n }, 500);\n });\n}\n","import type { KeyboardEvent, KeyboardEventHandler } from \"react\";\n\n/**\n * HTML `<input>` types that are either a multi-line control (none are — that's\n * `<textarea>`) or not a plain single-line text control: a checkbox/radio has\n * no text to \"submit\", and a native picker (date, color, range, file, …) has\n * its own Enter semantics this hook must not override.\n */\nconst NON_TEXT_INPUT_TYPES = new Set([\n \"checkbox\",\n \"radio\",\n \"button\",\n \"submit\",\n \"reset\",\n \"file\",\n \"range\",\n \"color\",\n \"image\",\n \"hidden\",\n \"date\",\n \"datetime-local\",\n \"month\",\n \"week\",\n \"time\",\n]);\n\n/**\n * Whether `target` is (or sits inside) a `contenteditable` region — checked\n * via the attribute chain rather than the `isContentEditable` DOM property,\n * which some environments (including this package's own jsdom-based unit\n * suite) never compute; the attribute is what both a real browser and jsdom\n * actually see once React renders `contentEditable`.\n */\nfunction isWithinContentEditable(target: HTMLElement): boolean {\n return target.closest('[contenteditable]:not([contenteditable=\"false\"])') !== null;\n}\n\n/**\n * Enter-to-submit for a single-line text input, one implementation mounted by\n * every form instead of each surface hand-rolling its own `onKeyDown` — see\n * `studio/src/components/ApiServerSetting.tsx:75-80` for the ad-hoc version\n * this replaces (a bare `if (e.key === \"Enter\")` with no modifier guard and no\n * check that the target is actually a single-line text field). Spread the\n * returned object onto the input: `<input {...useEnterSubmit(save)} … />`.\n *\n * Deliberately narrow: fires only for a bare `Enter` (no Shift/Alt/Ctrl/Meta,\n * and not mid-IME-composition) on an `<input>` whose `type` is a plain\n * single-line text control — never a `<textarea>`, a `contenteditable` node,\n * or a non-text `<input>` (checkbox, date picker, …), each of which has its\n * own meaning for Enter (a newline, a native widget's own key handling) that\n * this hook must not steal. `opts.enabled` is a hard off switch: pass the same\n * boolean guarding the caller's own submit button so Enter can never do\n * something the button itself refuses to do.\n */\nexport function useEnterSubmit(\n onSubmit: () => void,\n opts?: { enabled?: boolean },\n): { onKeyDown: KeyboardEventHandler<HTMLElement> } {\n return {\n onKeyDown: (e: KeyboardEvent<HTMLElement>) => {\n if (opts?.enabled === false) return;\n if (e.key !== \"Enter\") return;\n if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) return;\n if (e.nativeEvent.isComposing) return;\n const target = e.target as HTMLElement;\n if (target.tagName === \"TEXTAREA\") return;\n if (isWithinContentEditable(target)) return;\n if (\n target.tagName === \"INPUT\" &&\n NON_TEXT_INPUT_TYPES.has((target as HTMLInputElement).type)\n ) {\n return;\n }\n e.preventDefault();\n onSubmit();\n },\n };\n}\n","import { useEffect, useState } from \"react\";\nimport { AppPicker } from \"./AppPicker.tsx\";\nimport { AppIcon } from \"./components/AppIcon.tsx\";\nimport { AuthFieldsForm } from \"./components/AuthFieldsForm.tsx\";\nimport { Modal } from \"./components/Modal.tsx\";\nimport { startOAuthPopup } from \"./oauth-popup.ts\";\nimport { useW6WApi } from \"./provider.tsx\";\nimport type { AppSummary, AuthDef, AuthField, ThemeMode } from \"./types.ts\";\nimport { useEnterSubmit } from \"./use-enter-submit.ts\";\n\nexport interface AddConnectionModalProps {\n onClose: () => void;\n /** Fired after a successful create (both API-key and OAuth paths). */\n onCreated: (result: { connectionId: string }) => void;\n /** Optional theme hint passed through to `AppIcon` (light/dark variant). */\n theme?: ThemeMode;\n /**\n * Pre-select an app and skip the picker — used when the modal is opened for a\n * specific app (e.g. from the step builder). Omit to let the user pick.\n */\n initialAppId?: string;\n}\n\n/**\n * Add-connection modal. Same shape as the step builder's \"add a step\" modal —\n * the shared {@link AppPicker} (searchable icon grid) for step one, then the\n * chosen app's connection fields for step two — minus the tabs. Pick an app →\n * pick an auth method → fill the fields (or run OAuth) → submit. The\n * `AuthDef.fields` array drives the form, so no app-specific knowledge is baked\n * in. Data + IO come from `useW6WApi()`.\n */\nexport function AddConnectionModal(props: AddConnectionModalProps) {\n const api = useW6WApi();\n const [selectedApp, setSelectedApp] = useState<AppSummary | null>(null);\n const [resolvingInitial, setResolvingInitial] = useState<boolean>(Boolean(props.initialAppId));\n\n // Opened for a specific app: resolve it to an AppSummary (for the header) and\n // go straight to the connection fields, skipping the picker. Prefers the\n // bounded `listAppsByIds([id])` seam (A3) over a full-catalog `listApps()`\n // scan. When `listAppsByIds` exists, its result is final — found resolves to\n // that app, a miss (empty result or rejection) resolves to not-found —\n // `listApps` is NEVER called alongside it: a bounded host's \"no such id\" is\n // a real answer, not evidence the seam \"isn't really implemented\" (mirrors\n // AppPicker/useReadyToUse's own no-silent-downgrade rule, T2.1.1 ROUND 2).\n // Only when `listAppsByIds` is itself absent does this fall back to\n // `listApps`-based full-list resolution (today's pre-existing behavior);\n // with neither seam present, it resolves to not-found without ever calling\n // an undefined function.\n useEffect(() => {\n const id = props.initialAppId;\n if (!id) return;\n let canceled = false;\n const finish = (app: AppSummary | null) => {\n if (canceled) return;\n setSelectedApp(app);\n setResolvingInitial(false);\n };\n const listAppsByIds = api.listAppsByIds;\n if (listAppsByIds) {\n listAppsByIds([id])\n .then((apps) => finish(apps.find((a) => a.id === id) ?? null))\n .catch(() => finish(null));\n return () => {\n canceled = true;\n };\n }\n const listApps = api.listApps;\n if (typeof listApps === \"function\") {\n listApps()\n .then((apps) => finish(apps.find((a) => a.id === id) ?? null))\n .catch(() => finish(null));\n } else {\n finish(null);\n }\n return () => {\n canceled = true;\n };\n }, [api, props.initialAppId]);\n\n // Step two: the chosen app's connection fields.\n if (selectedApp) {\n return (\n <Modal\n title={selectedApp.displayName}\n subtitle={\n <>\n <code>{selectedApp.id}</code>\n {selectedApp.version && ` · v${selectedApp.version}`}\n </>\n }\n onClose={props.onClose}\n size=\"xl\"\n titleIcon={\n <AppIcon\n src={selectedApp.iconSvg}\n srcDark={selectedApp.iconSvgDark}\n brandColor={selectedApp.brandColor}\n name={selectedApp.displayName}\n theme={props.theme}\n size={22}\n />\n }\n headerRight={\n props.initialAppId ? undefined : (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n onClick={() => setSelectedApp(null)}\n >\n ← Apps\n </button>\n )\n }\n >\n <ConnectionConfig app={selectedApp} onCreated={props.onCreated} onClose={props.onClose} />\n </Modal>\n );\n }\n\n // Resolving an initialAppId — don't flash the picker.\n if (resolvingInitial) {\n return (\n <Modal title=\"Add connection\" onClose={props.onClose} size=\"xl\">\n <div className=\"w6w-stepbuilder-content\">\n <p className=\"w6w-muted w6w-small\">Loading…</p>\n </div>\n </Modal>\n );\n }\n\n // Step one: the shared searchable app picker (icons + search).\n return (\n <Modal title=\"Add connection\" onClose={props.onClose} size=\"xl\">\n <div className=\"w6w-stepbuilder-content\">\n <AppPicker\n onSelectApp={setSelectedApp}\n theme={props.theme}\n searchPlaceholder=\"Search apps to connect…\"\n categoryFilter\n />\n </div>\n </Modal>\n );\n}\n\n/**\n * The chosen app's connection form: pick an auth method (when >1), name the\n * connection, fill the credential fields (or run OAuth), and submit.\n */\nfunction ConnectionConfig({\n app,\n onCreated,\n onClose,\n}: {\n app: AppSummary;\n onCreated: (result: { connectionId: string }) => void;\n onClose: () => void;\n}) {\n const api = useW6WApi();\n const [auths, setAuths] = useState<AuthDef[] | null>(null);\n const [authKey, setAuthKey] = useState<string>(\"\");\n const [displayName, setDisplayName] = useState(\"\");\n const [credential, setCredential] = useState<Record<string, unknown>>({});\n const [error, setError] = useState<string | null>(null);\n const [pending, setPending] = useState(false);\n\n useEffect(() => {\n let canceled = false;\n setAuths(null);\n api\n .getAppAuth(app.id)\n // Hide methods the server flagged unavailable (e.g. oauth2 with no host creds).\n .then((a) => !canceled && setAuths(a.filter((x) => x.available !== false)))\n .catch((e) => !canceled && setError((e as Error).message));\n return () => {\n canceled = true;\n };\n }, [api, app.id]);\n\n const available = auths ?? [];\n // User's pick, else the server-flagged default (over the already-filtered\n // list, so an unavailable default falls through), else the first.\n const auth: AuthDef | undefined =\n available.find((a) => a.key === authKey) ??\n available.find((a) => a.default === true) ??\n available[0];\n const fields: AuthField[] = auth?.fields ?? [];\n const isOAuth = auth?.type === \"oauth2\";\n // The synthetic \"no connection needed\" entry `GET /apps/:id/auths` appends\n // for a zero-credential-flagged tenant (`admin/apps-catalog.ts`) — matched\n // by `key`, never `type` (its `type` is the existing `\"custom\"` value,\n // shared with real custom auth methods; `key: \"zero-credential\"` is the\n // one thing only this synthetic entry carries). Selecting it needs no\n // fields and no real `POST /apps/:id/connections` — the tenant is already\n // \"connected\" via the flag (`admin/connections.ts`'s own synthetic\n // `zerocred:<appId>` summary), so submitting here just reports that same\n // id back rather than creating a second, real row for nothing to store.\n const isZeroCred = auth?.key === \"zero-credential\";\n const requiredMissing =\n !isOAuth &&\n !isZeroCred &&\n fields.some((f) => f.required && (credential[f.key] === undefined || credential[f.key] === \"\"));\n // Hoisted once — shared by the primary button's `disabled` and the\n // enter-to-submit hook's `enabled`, so Enter can never do something the\n // button itself refuses to do.\n const submitDisabled = !auth || (!isOAuth && !isZeroCred && requiredMissing) || pending;\n\n async function submit() {\n if (!auth) return;\n setError(null);\n setPending(true);\n try {\n if (isZeroCred) {\n onCreated({ connectionId: `zerocred:${app.id}` });\n } else if (isOAuth) {\n const { authorizationUrl } = await api.startAppOAuthFlow(app.id, auth.key, {\n displayName: displayName || undefined,\n });\n const { connectionId } = await startOAuthPopup(authorizationUrl);\n onCreated({ connectionId });\n } else {\n const conn = await api.createConnection(app.id, {\n authKey: auth.key,\n credential,\n displayName: displayName || undefined,\n });\n onCreated({ connectionId: conn.id });\n }\n } catch (e) {\n setError((e as Error).message);\n } finally {\n setPending(false);\n }\n }\n\n const enterSubmit = useEnterSubmit(submit, { enabled: !submitDisabled });\n\n return (\n // `.w6w-stepconfig` frame + body + pinned footer (D-3) — the same shape the\n // step builder's own config pane uses, so only the form scrolls and\n // Cancel/Save never leave the dialog's bottom.\n <div className=\"w6w-stepconfig\">\n <div className=\"w6w-modal-body\">\n <div className=\"w6w-stack\">\n {auths === null && <p className=\"w6w-muted w6w-small\">Loading auth methods…</p>}\n\n {auths !== null && available.length === 0 && (\n <p className=\"w6w-muted w6w-small\">\n This app has no available auth methods. If it uses OAuth, its client credentials may\n not be configured on the server yet.\n </p>\n )}\n\n {available.length > 1 && (\n <label className=\"w6w-field\">\n <span>Auth method</span>\n <select\n value={auth?.key ?? \"\"}\n onChange={(e) => {\n setAuthKey(e.target.value);\n setCredential({});\n setError(null);\n }}\n >\n {available.map((a) => (\n <option key={a.key} value={a.key}>\n {a.displayName ?? a.key} ({a.type})\n </option>\n ))}\n </select>\n </label>\n )}\n\n {auth && (\n <>\n {!isZeroCred && (\n <label className=\"w6w-field\">\n <span>Display name</span>\n <input\n type=\"text\"\n value={displayName}\n onChange={(e) => setDisplayName(e.target.value)}\n placeholder=\"e.g. Production API key\"\n maxLength={80}\n // A plain text field above a credential field gets treated as the\n // \"username\" of a login form and prefilled — opt it out.\n name=\"w6w-connection-label\"\n autoComplete=\"off\"\n data-1p-ignore=\"true\"\n data-lpignore=\"true\"\n data-bwignore=\"true\"\n data-form-type=\"other\"\n {...enterSubmit}\n />\n </label>\n )}\n {auth.description && <p className=\"w6w-muted w6w-small\">{auth.description}</p>}\n {isZeroCred ? null : isOAuth ? (\n <p className=\"w6w-muted w6w-small\">\n You'll be redirected to <strong>{auth.displayName ?? auth.key}</strong> to\n authorize this connection.\n </p>\n ) : (\n <AuthFieldsForm\n fields={fields}\n values={credential}\n onChange={setCredential}\n enterSubmitProps={enterSubmit}\n />\n )}\n </>\n )}\n\n {error && <div className=\"w6w-result w6w-error\">{error}</div>}\n </div>\n </div>\n <div className=\"w6w-modal-actions\">\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={onClose}>\n Cancel\n </button>\n <button type=\"button\" className=\"w6w-btn\" disabled={submitDisabled} onClick={submit}>\n {pending\n ? isZeroCred\n ? \"Saving…\"\n : isOAuth\n ? \"Waiting for authorization…\"\n : \"Saving…\"\n : isZeroCred\n ? \"Use this\"\n : isOAuth\n ? `Sign in with ${auth?.displayName ?? auth?.key ?? \"provider\"}`\n : \"Save connection\"}\n </button>\n </div>\n </div>\n );\n}\n","import type { FlowStep } from \"./flow-types.ts\";\n\n/** Who this retry policy applies to — picks the helper line's wording. */\nexport type RetryTarget = \"step\" | \"function\" | \"endpoint\" | \"workflow\";\n\n/** The persisted retry shape (core `rfcs/node-types.md`), minus the `undefined` case. */\nexport type RetryPolicyValue = NonNullable<FlowStep[\"retry\"]>;\n\nconst HELPER_TEXT: Record<RetryTarget, string> = {\n step: \"Re-run this step if it fails, up to N attempts.\",\n function: \"Re-run this function call if it fails, up to N attempts.\",\n endpoint: \"Re-run this endpoint call if it fails, up to N attempts.\",\n workflow: \"Re-run the whole workflow run if it fails, up to N attempts.\",\n};\n\n/**\n * The \"Retry on failure\" checkbox + helper line + Attempts/Delay (ms)/Backoff\n * row — the one retry shape shared by every host that can offer a retry\n * policy (core rfcs/R-2 \"one retry shape everywhere\"). `value` is the\n * persisted policy or `undefined` for \"no retry\"; `target` only changes the\n * helper line's wording, never the behavior.\n */\nexport function RetryPolicyFields({\n value,\n onChange,\n readOnly,\n target = \"step\",\n}: {\n value: RetryPolicyValue | undefined;\n onChange: (next: RetryPolicyValue | undefined) => void;\n readOnly?: boolean;\n target?: RetryTarget;\n}) {\n const retryOn = !!value;\n const attempts = value?.maxAttempts ?? 3;\n const delayMs = value?.delayMs ?? 1000;\n const backoff = value?.backoff ?? \"fixed\";\n\n const setRetry = (patch: Partial<RetryPolicyValue>) =>\n onChange({ maxAttempts: attempts, delayMs, backoff, ...value, ...patch });\n\n return (\n <>\n <label className=\"w6w-field\">\n <span>\n <input\n type=\"checkbox\"\n checked={retryOn}\n disabled={readOnly}\n onChange={(e) =>\n onChange(e.target.checked ? { maxAttempts: attempts, delayMs, backoff } : undefined)\n }\n />{\" \"}\n Retry on failure\n </span>\n <span className=\"w6w-hint\">{HELPER_TEXT[target]}</span>\n </label>\n {retryOn && (\n <div className=\"w6w-field-row\">\n <label className=\"w6w-field\">\n <span>Attempts</span>\n <input\n type=\"number\"\n min={1}\n value={attempts}\n readOnly={readOnly}\n onChange={(e) => setRetry({ maxAttempts: Math.max(1, Number(e.target.value) || 1) })}\n />\n </label>\n <label className=\"w6w-field\">\n <span>Delay (ms)</span>\n <input\n type=\"number\"\n min={0}\n value={delayMs}\n readOnly={readOnly}\n onChange={(e) => setRetry({ delayMs: Math.max(0, Number(e.target.value) || 0) })}\n />\n </label>\n <label className=\"w6w-field\">\n <span>Backoff</span>\n <select\n value={backoff}\n disabled={readOnly}\n onChange={(e) => setRetry({ backoff: e.target.value as \"fixed\" | \"exponential\" })}\n >\n <option value=\"fixed\">Fixed</option>\n <option value=\"exponential\">Exponential</option>\n </select>\n </label>\n </div>\n )}\n </>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { RetryPolicyFields } from \"./RetryPolicyFields.tsx\";\nimport type { FlowStep } from \"./flow-types.ts\";\n\n/** The base, always-available node settings — independent of the action's params. */\nexport type NodeConfig = Pick<FlowStep, \"retry\" | \"onError\" | \"notes\">;\n\n/**\n * A stable reference over a Function or a Workflow (core rfcs/endpoint.md ·\n * CallableRef). Declared **locally** — structurally identical to\n * `@w6w/workflow-types`'s `CallableRef` — because `@w6w/ui` has no dependency edge\n * to that package and must not gain one (D-10).\n */\nexport type CallableRef =\n | { kind: \"function\"; function: string }\n | { kind: \"workflow\"; workflow: string };\n\n/**\n * Node settings form: retry-on-fail, error handling, and notes. Operates on a\n * plain {@link NodeConfig} so it's shared by the add-a-step config and the node\n * editor (all fields optional; absent = defaults).\n *\n * `hasGraph` and `reroute` are ADDITIVE (D-10, F-2.1): a graph-less host — a\n * Function or an Endpoint, which has no canvas and so can never author an\n * `Edge.when: \"error\"` — passes `hasGraph={false}` and supplies `reroute` so a\n * failure can still be redirected somewhere. Both are omitted by every\n * existing caller, so `NodeConfig` itself and every pre-existing render path\n * are unchanged.\n */\nexport function NodeConfigForm({\n config,\n onChange,\n readOnly,\n hasGraph = true,\n failureHandling = true,\n retryControls = true,\n reroute,\n}: {\n config: NodeConfig;\n onChange: (next: NodeConfig) => void;\n readOnly?: boolean;\n /**\n * `false` for a graph-less host. Swaps the \"outgoing error edge\" hint for a\n * sentence about the `reroute` field, and drops `continue-record` from the\n * `onError` select — `continue-record` writes to a run's `stepErrors`, which\n * a Function/Endpoint invocation has none of. Default `true` reproduces\n * today's behavior byte-identically.\n */\n hasGraph?: boolean;\n /**\n * `false` for a node that cannot fail on its own — today only a trigger,\n * which is the run's ENTRY rather than a step that acts: it emits the start\n * payload, makes no vendor call, and so has nothing to retry and no failure\n * to police (human report, 2026-09-01). Drops the retry and \"On error\"\n * controls; Notes stay. Default `true` reproduces today's behavior\n * byte-identically.\n */\n failureHandling?: boolean;\n /**\n * `false` omits only the \"Retry on failure\" block — \"On error\" and Notes are\n * unaffected. Used by a host whose step can never retry on its own (a\n * `@w6w/call`/`@w6w/control` step; core rfcs/workflow.md \"Retries come\n * first\"). Default `true` reproduces today's markup byte-identically.\n */\n retryControls?: boolean;\n /**\n * Failure re-dispatch — a `CallableRef`, rendered only when supplied. `value`/\n * `onChange` are the host's own state (so it can offer a \"clear\" affordance);\n * `picker` is a slot the host renders its own selection control into — this\n * component never reaches for anything outside `{retry, onError, notes,\n * reroute}`, so it still has no view of the app/workflow catalog itself.\n */\n reroute?: {\n value: CallableRef | undefined;\n onChange: (next: CallableRef | undefined) => void;\n picker: ReactNode;\n };\n}) {\n const onError = config.onError ?? \"fail\";\n\n return (\n <div className=\"w6w-stack\">\n {failureHandling && (\n <>\n {retryControls && (\n <RetryPolicyFields\n value={config.retry}\n onChange={(retry) => onChange({ ...config, retry })}\n readOnly={readOnly}\n />\n )}\n\n {/* Error handling */}\n <label className=\"w6w-field\">\n <span>On error</span>\n <select\n value={onError}\n disabled={readOnly}\n onChange={(e) => {\n const v = e.target.value as NonNullable<NodeConfig[\"onError\"]>;\n // \"fail\" is the default — store it as absent to keep the step clean.\n onChange({ ...config, onError: v === \"fail\" ? undefined : v });\n }}\n >\n <option value=\"fail\">Stop the run (default)</option>\n <option value=\"continue\">Continue to the next step</option>\n {hasGraph && (\n <option value=\"continue-record\">\n Continue to the next step & record the error\n </option>\n )}\n </select>\n {hasGraph ? (\n // This select reads as if it had total authority over failure, and since\n // an error edge became authorable it no longer does: per D-T1-3 an\n // outgoing error edge OVERRIDES this policy. The honest fix is a static\n // hint — this form receives only `{ retry, onError, notes }` (plus the\n // additive `reroute` below) and has no view of the graph, so it cannot\n // know whether the step has such an edge, and giving it one just to\n // find out is out of scope.\n //\n // Ordering per rfcs/workflow.md's Amendment — 2026-07-29 (failure-\n // conditioned edges): retries come first (only a *finally* failed\n // attempt reaches this policy at all); Continue/Continue & record\n // both carry on down this step's normal outgoing edges despite the\n // failure; an outgoing error edge overrides all of the above. The\n // drag gesture named below is the SAME one `LANE_HINT` (T1.1.1)\n // describes for the error exit port — not re-derived here.\n <span className=\"w6w-muted w6w-small\">\n Retries run first: this policy is reached only once this step's retry attempts (if\n any) are exhausted — a run that succeeds on a later attempt continues down the\n normal path instead. Once reached, <strong>Continue</strong> and{\" \"}\n <strong>Continue & record the error</strong> both carry on down this step's\n ordinary outgoing edges despite the failure. If this step has an outgoing{\" \"}\n <strong>error</strong> edge on the canvas, that edge decides what happens instead\n and this policy is not consulted — drawn by dragging from the step's error exit\n port.\n </span>\n ) : (\n // Graph-less host: there is no canvas and so no error edge to draw —\n // the reroute field below is this host's equivalent. Must not\n // contradict the graph arm above: retries still come first here too.\n <span className=\"w6w-muted w6w-small\">\n Retries run first: this policy (and reroute, below) is only reached once this step's\n retry attempts (if any) are exhausted — a run that succeeds on a later attempt\n continues normally. This step has no canvas of its own, so it can't carry an error\n edge. Set a <strong>reroute</strong> target below to send a failure somewhere else\n instead of stopping.\n </span>\n )}\n </label>\n </>\n )}\n\n {/* Reroute on failure — graph-less hosts only (additive; see `reroute`).\n A `<div>`, not a `<label>`: `picker` is the host's own control (of\n unknown shape), so there is no single form element to associate a\n label with here. */}\n {reroute && (\n <div className=\"w6w-field\">\n <span>Reroute on failure</span>\n <div className=\"w6w-field-row\">\n {reroute.picker}\n {reroute.value && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n disabled={readOnly}\n onClick={() => reroute.onChange(undefined)}\n >\n Clear\n </button>\n )}\n </div>\n <span className=\"w6w-hint\">\n Invoked once, after retry is exhausted, if this step still fails; its output becomes\n this step's output.\n </span>\n </div>\n )}\n\n {/* Notes — shown under the step's own card on the canvas (2026-08-30),\n not just here, so a description written once helps a reader orient\n without opening every step. */}\n <label className=\"w6w-field\">\n <span>Notes</span>\n <textarea\n rows={3}\n value={config.notes ?? \"\"}\n readOnly={readOnly}\n placeholder=\"A short description — shown under this step on the canvas. Not executed.\"\n onChange={(e) => onChange({ ...config, notes: e.target.value || undefined })}\n />\n </label>\n </div>\n );\n}\n","import type { ActionParam } from \"./types.ts\";\n\n/**\n * One field configured on a manual (`@w6w/trigger`) or webhook (`@w6w/webhook`)\n * trigger — the `fields` param stores an array of these *definitions*\n * (`{ key, type, default, required }`), not values. The Test tab derives a\n * fillable form from them (see `TriggerFillForm`).\n */\nexport interface TriggerFieldDef {\n key?: string;\n /** Declared value type — maps to an existing `ParamsForm` widget. */\n type?: string;\n /** Author-declared default (stored as text on the trigger config). */\n default?: unknown;\n required?: boolean;\n}\n\n/** Read a trigger's `fields` param value as an array of field definitions. */\nexport function asFieldDefs(fields: unknown): TriggerFieldDef[] {\n return Array.isArray(fields) ? (fields as TriggerFieldDef[]) : [];\n}\n\n/**\n * Map a field def's declared type onto one of the `ParamsForm` scalar\n * widgets. `object`/`array` (a `WorkflowVariable`'s type union,\n * `w6w-workflow/packages/types/mod.ts:40-45` — this seam is also reused for\n * T1.1.5's run-page form) render as the `json` widget, same as an explicit\n * `json` declaration: there is no dedicated object/array widget, and `json`\n * is the one that round-trips a structured value without flattening it to\n * text. Verified inert for the trigger `fields` editor itself: its type\n * `<select>` offers exactly `string|number|boolean|json`\n * (`flow-types.ts:343-353`), so no editor-authored trigger field can reach\n * these two arms — only a call site that hands in `WorkflowVariable.type`\n * can.\n */\nexport function fieldWidget(type: string | undefined): ActionParam[\"type\"] {\n if (type === \"object\" || type === \"array\") return \"json\";\n return type === \"number\" || type === \"boolean\" || type === \"json\" ? type : \"string\";\n}\n\n/**\n * Coerce a field's author-declared default into a value of the field's\n * declared type, so the derived form seeds a sensible starting value and the\n * required gate sees it as filled. Returns `undefined` for an empty/invalid\n * default (the operator then supplies the value).\n *\n * A trigger field's default is stored as **text** and needs parsing; a\n * `WorkflowVariable`'s default is stored as a **real JSON value already**\n * (T1.1.5) — coercing it through `String(...)` would flatten `{a:1}` to the\n * literal text `\"[object Object]\"` and `[1,2]` to `\"1,2\"`, and re-parsing\n * `String({a:1})` as JSON fails outright (`coerceDefault(\"json\", {a:1})` used\n * to return `undefined`, silently dropping the default). So an already-object\n * or already-array `raw` is returned unchanged, before any type-specific\n * branch runs — this holds regardless of `type`, because the value needs no\n * coercion either way.\n */\nexport function coerceDefault(type: string | undefined, raw: unknown): unknown {\n if (raw === undefined || raw === null || raw === \"\") return undefined;\n if (typeof raw === \"object\") return raw;\n if (type === \"number\") {\n const n = Number(raw);\n return Number.isFinite(n) ? n : undefined;\n }\n if (type === \"boolean\") return raw === true || raw === \"true\";\n if (type === \"json\") {\n try {\n return JSON.parse(String(raw));\n } catch {\n return undefined;\n }\n }\n return String(raw);\n}\n\n/**\n * Project a trigger's `fields` definitions into a `ParamsForm`-compatible param\n * list — one input per declared field, keyed by the field's `key`, rendered with\n * the existing per-type widget. Unnamed fields are skipped.\n */\nexport function fieldsToParams(defs: TriggerFieldDef[]): ActionParam[] {\n return defs\n .filter((f) => typeof f.key === \"string\" && f.key.trim() !== \"\")\n .map((f) => ({\n key: f.key as string,\n label: f.key as string,\n type: fieldWidget(f.type),\n required: !!f.required,\n }));\n}\n\n/** Seed the fill-form values from each declared field's (coerced) default. */\nexport function seedValues(defs: TriggerFieldDef[]): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const f of defs) {\n if (typeof f.key !== \"string\" || f.key.trim() === \"\") continue;\n const v = coerceDefault(f.type, f.default);\n if (v !== undefined) out[f.key] = v;\n }\n return out;\n}\n","import { useEffect, useMemo, useState } from \"react\";\nimport { PropertyEntryForm } from \"./PropertyEntryForm.tsx\";\nimport { type StepTestPersist, requiredParamsFilled } from \"./StepBuilderModal.tsx\";\nimport { useW6WApi, useWorkflowProject } from \"./provider.tsx\";\nimport { asFieldDefs, fieldsToParams, seedValues } from \"./trigger-fields.ts\";\n\ntype TestState =\n | { status: \"running\" }\n | { status: \"done\"; value: unknown; logs?: string[] }\n | { status: \"error\"; error: string; errorCode?: string; logs?: string[] };\n\n/**\n * The Test-tab widget for a manual/webhook trigger. A trigger's configured\n * `fields` ARE the run's starting state, so testing it means **filling those\n * fields**, not running the raw config (which is why the trigger's output used to\n * come back `{}` — the invoke never carried an `input`).\n *\n * It projects the trigger's `fields` into params (see `./trigger-fields.ts`) and\n * hands them to {@link PropertyEntryForm} — the one property-entry surface, which\n * gives it the per-field widgets, per-field `ƒx`, and the fields ⇄ raw-JSON\n * toggle. This component keeps only the *run*: it enforces each field's\n * `required` via {@link requiredParamsFilled} before enabling Test, and invokes\n * with `{ input: {…filled} }` so the handler (which passes `params.input`\n * through) returns the populated values as the trigger's output state.\n *\n * A trigger with no declared fields (e.g. a webhook, whose payload is arbitrary)\n * gets the raw JSON payload editor — that is the entry form's own empty-params\n * path, not a second code path here — so the operator can still supply a\n * starting state, and the same `{ input }` projection applies.\n *\n * **Remembered values (T4.1.3).** With `persist` supplied, the values are not\n * just used for the invoke: they are saved as the step's latest `step_tests`\n * fixture (`with`) and the run is recorded **against that fixture's id**, and the\n * form seeds itself from the latest fixture next time it opens. The store is\n * project-owned and shared per workflow — any editor of the workflow sees the\n * same saved values, which is the answer to HITL-2. The canvas ▶ Run collect\n * form reads and writes the same fixture, so values entered on either surface\n * come back on the other.\n *\n * That persistence is **local to testing** — `TriggerFillForm` itself never\n * calls `POST /workflows/:id/run`. It does not by itself reach a production\n * workflow run: that route does accept an `input` body field, and the server\n * lands it as the entry trigger's output (`run-workflow.ts`,\n * `EnqueueRunInput.input`), but a CALLER has to fetch the saved fixture and\n * pass it in. Studio's header ▶ Run is that caller (`WorkflowsPage.tsx`'s\n * `onRunClick` → `resolveHeaderRunInput`,\n * `packages/studio/src/lib/workflow-live-run.ts`): it fetches the manual\n * trigger's latest `step_tests` row and sends its `with` verbatim as `input`.\n * This form is not in that path; it only writes the fixture that call reads.\n */\nexport function TriggerFillForm({\n app,\n action,\n fields,\n persist,\n}: {\n app: string;\n action: string;\n /** The trigger's `fields` param value (an array of field definitions). */\n fields: unknown;\n /**\n * Where to remember the entered values. Absent in the add-step builder — that\n * step is not in a workflow yet, so there is no `(workflowId, stepId)` to key\n * a fixture by and this form neither reads nor writes one.\n */\n persist?: StepTestPersist;\n}) {\n const api = useW6WApi();\n // The workflow's selected project scopes document-expression resolution in the\n // trigger test (undefined outside the editor → server default project).\n const project = useWorkflowProject();\n const defs = useMemo(() => asFieldDefs(fields), [fields]);\n const params = useMemo(() => fieldsToParams(defs), [defs]);\n const hasFields = params.length > 0;\n\n // One value bag for both paths: declared fields fill it by key, a webhook's\n // raw payload replaces it wholesale.\n const [values, setValues] = useState<Record<string, unknown>>(() => seedValues(defs));\n\n const [state, setState] = useState<TestState | null>(null);\n\n // Pre-fill from the step's last saved fixture. Depends on the ids rather than\n // on `persist` itself — the host builds that object inline, so its identity\n // changes every render.\n const persistWorkflowId = persist?.workflowId;\n const persistStepId = persist?.stepId;\n // Nothing to wait for when there is no fixture key (the add-step builder).\n const [seeded, setSeeded] = useState(!persistWorkflowId || !persistStepId);\n useEffect(() => {\n if (!persistWorkflowId || !persistStepId) {\n setSeeded(true);\n return;\n }\n let canceled = false;\n api\n .listStepTests(persistWorkflowId, persistStepId)\n .then((tests) => {\n if (canceled) return;\n // `listStepTests` is oldest-first, so the LAST entry is the most recent\n // fixture — the same convention the editor's upstream-seed effect uses.\n // Layered over the declared defaults so a field added since the last run\n // still arrives with its default rather than blank. An `ExprValue`\n // (`{type:\"expr\",…}`) is stored and restored as-is: `FxField` derives\n // expression mode from the value, so it comes back as a chip.\n const latest = tests.length ? tests[tests.length - 1] : null;\n if (latest?.with) setValues((v) => ({ ...v, ...latest.with }));\n setSeeded(true);\n })\n // A missing/failed list must never block the form — fall back to the\n // declared defaults, silently, exactly as the seed effect does.\n .catch(() => {\n if (!canceled) setSeeded(true);\n });\n return () => {\n canceled = true;\n };\n }, [api, persistWorkflowId, persistStepId]);\n\n // A raw-JSON draft that is not a values map never reaches `values`. Testing\n // now WRITES the saved fixture the Run form pre-fills from, so running the\n // previous payload while the operator looks at a different one would persist\n // the wrong values too — the same interlock Run uses (T4.1.2's validity-out).\n const [draftValid, setDraftValid] = useState(true);\n // With no declared params the required-check is vacuously true — a webhook\n // payload has nothing to require.\n const canRun = draftValid && requiredParamsFilled(params, values);\n\n const run = async () => {\n setState({ status: \"running\" });\n let outcome: Exclude<TestState, { status: \"running\" }>;\n try {\n // The filled values become the trigger's output/run-input — the handler\n // reads `params.input` and returns it verbatim.\n const result = await api.invokeAction(app, action, { input: values }, { project });\n outcome = {\n status: \"done\",\n value: result.value,\n logs: (result as { logs?: string[] }).logs,\n };\n } catch (e) {\n const err = e as { message?: string; code?: string; logs?: string[] };\n outcome = {\n status: \"error\",\n error: err.message ?? String(e),\n errorCode: err.code,\n logs: err.logs,\n };\n }\n setState(outcome);\n // Remember what was entered, and record the run AGAINST that fixture — the\n // same two-call sequence `StepTestRun` uses on the non-trigger Test path.\n // Without the `stepTestId` the fixture's `last_run_*` columns are never\n // written. Best-effort: a persist failure never masks the run's own result.\n if (persist) {\n try {\n const saved = await api.saveStepTest(persist.workflowId, persist.stepId, {\n input: persist.input,\n with: values,\n });\n await api.recordStepTestRun(persist.workflowId, persist.stepId, {\n stepTestId: saved.id,\n status: outcome.status === \"done\" ? \"succeeded\" : \"failed\",\n input: persist.input,\n output: outcome.status === \"done\" ? outcome.value : undefined,\n error: outcome.status === \"error\" ? outcome.error : undefined,\n });\n } catch (err) {\n console.error(\"step test persist failed\", err);\n }\n }\n };\n\n const logs = state && state.status !== \"running\" ? state.logs : undefined;\n\n return (\n <div className=\"w6w-stack\">\n {/* Held until the saved values land, so the form is never shown with the\n defaults and then re-written under the operator's cursor. */}\n {!seeded ? (\n <p className=\"w6w-muted w6w-small\">Loading saved values…</p>\n ) : (\n <>\n <PropertyEntryForm\n params={params}\n values={values}\n onChange={setValues}\n onValidityChange={setDraftValid}\n />\n {!hasFields && (\n <span className=\"w6w-hint\">\n This trigger declares no fields — provide a sample payload to test with. It becomes\n the trigger's output state (<code>input</code>).\n </span>\n )}\n </>\n )}\n\n <div className=\"w6w-steptest\">\n <div className=\"w6w-steptest-bar\">\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n disabled={!seeded || !canRun || state?.status === \"running\"}\n onClick={run}\n >\n {state?.status === \"running\" ? \"Running…\" : \"▶ Test run\"}\n </button>\n {seeded && !canRun && (\n <span className=\"w6w-muted w6w-small\">\n {draftValid\n ? \"Fill the required fields to test.\"\n : \"The payload must be a JSON object to test.\"}\n </span>\n )}\n </div>\n {state?.status === \"error\" && (\n <div className=\"w6w-result w6w-error\">\n {state.errorCode && (\n <div className=\"w6w-small\" style={{ opacity: 0.75, marginBottom: 4 }}>\n <code>{state.errorCode}</code>\n </div>\n )}\n {state.error}\n </div>\n )}\n {state?.status === \"done\" && (\n <div className=\"w6w-testout\">\n <div className=\"w6w-testout-label\">Output state (filled values)</div>\n <pre\n className=\"w6w-result\"\n style={{ whiteSpace: \"pre-wrap\", maxHeight: 220, overflow: \"auto\", margin: 0 }}\n >\n {JSON.stringify(state.value, null, 2)}\n </pre>\n </div>\n )}\n {logs && logs.length > 0 && (\n <div className=\"w6w-testout\">\n <div className=\"w6w-testout-label\">Console output</div>\n <pre\n className=\"w6w-result w6w-testout-console\"\n style={{ whiteSpace: \"pre-wrap\", maxHeight: 160, overflow: \"auto\", margin: 0 }}\n >\n {logs.join(\"\\n\")}\n </pre>\n </div>\n )}\n </div>\n </div>\n );\n}\n","import { type CSSProperties, useEffect, useId, useMemo, useRef, useState } from \"react\";\n\nexport interface ComboboxOption {\n value: string;\n label: string;\n}\n\nexport interface ComboboxProps {\n options: ComboboxOption[];\n value: string;\n onChange: (value: string) => void;\n placeholder?: string;\n disabled?: boolean;\n \"aria-label\"?: string;\n /** `auto` picks a native `<select>` for short lists, a combobox for long ones. */\n mode?: \"select\" | \"combobox\" | \"auto\";\n /** true (default): typing only filters; value changes by picking. false: free text is a value. */\n forceSelection?: boolean;\n /** Estimated option height in px, used by `auto` mode. Default 32. */\n optionHeight?: number;\n className?: string;\n}\n\n/** Combobox is chosen when the list would take more than 60% of the viewport. */\nexport function shouldUseCombobox(\n count: number,\n optionHeight: number,\n viewportHeight: number,\n): boolean {\n return count * optionHeight > 0.6 * viewportHeight;\n}\n\n/** Case-insensitive substring match on label and value. */\nexport function filterOptions(options: ComboboxOption[], query: string): ComboboxOption[] {\n const q = query.trim().toLowerCase();\n if (!q) return options;\n return options.filter(\n (o) => o.label.toLowerCase().includes(q) || o.value.toLowerCase().includes(q),\n );\n}\n\nconst LIST_STYLE: CSSProperties = {\n position: \"absolute\",\n zIndex: 50,\n left: 0,\n right: 0,\n top: \"100%\",\n maxHeight: 240,\n overflowY: \"auto\",\n margin: 0,\n padding: 4,\n listStyle: \"none\",\n background: \"var(--w6w-surface, #fff)\",\n border: \"1px solid var(--w6w-border, #ccc)\",\n borderRadius: 6,\n boxShadow: \"0 4px 12px rgba(0,0,0,0.15)\",\n};\n\nexport function Combobox({\n options,\n value,\n onChange,\n placeholder,\n disabled,\n \"aria-label\": ariaLabel,\n mode = \"auto\",\n forceSelection = true,\n optionHeight = 32,\n className,\n}: ComboboxProps) {\n const useBox =\n mode === \"combobox\" ||\n (mode === \"auto\" &&\n shouldUseCombobox(\n options.length,\n optionHeight,\n typeof window === \"undefined\" ? 0 : window.innerHeight,\n ));\n\n const id = useId();\n const selectedLabel =\n options.find((o) => o.value === value)?.label ?? (forceSelection ? \"\" : value);\n const [text, setText] = useState(selectedLabel);\n const [open, setOpen] = useState(false);\n const [filtering, setFiltering] = useState(false);\n const [active, setActive] = useState(0);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n setText(selectedLabel);\n }, [selectedLabel]);\n\n const shown = useMemo(\n () => (filtering ? filterOptions(options, text) : options),\n [options, text, filtering],\n );\n\n if (!useBox) {\n return (\n <select\n className={className}\n value={value}\n disabled={disabled}\n aria-label={ariaLabel}\n onChange={(e) => onChange(e.target.value)}\n >\n {placeholder !== undefined && value === \"\" && (\n <option value=\"\" disabled>\n {placeholder}\n </option>\n )}\n {options.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n );\n }\n\n const optId = (i: number) => `${id}-opt-${i}`;\n\n const close = () => {\n setOpen(false);\n setFiltering(false);\n };\n\n const pick = (o: ComboboxOption) => {\n setText(o.label);\n onChange(o.value);\n close();\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n if (!open) setOpen(true);\n else setActive((a) => Math.min(a + 1, shown.length - 1));\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n if (!open) setOpen(true);\n else setActive((a) => Math.max(a - 1, 0));\n } else if (e.key === \"Enter\") {\n if (open && shown[active]) {\n e.preventDefault();\n pick(shown[active]);\n } else if (!forceSelection) {\n onChange(text);\n close();\n }\n } else if (e.key === \"Escape\") {\n if (open) e.stopPropagation();\n setText(selectedLabel);\n close();\n }\n };\n\n const onBlur = () => {\n if (forceSelection) setText(selectedLabel);\n else if (text !== value) onChange(text);\n close();\n };\n\n return (\n <div ref={rootRef} style={{ position: \"relative\" }}>\n <input\n type=\"text\"\n role=\"combobox\"\n className={className}\n value={text}\n disabled={disabled}\n placeholder={placeholder}\n aria-label={ariaLabel}\n aria-expanded={open}\n aria-controls={`${id}-list`}\n aria-autocomplete=\"list\"\n aria-activedescendant={open && shown[active] ? optId(active) : undefined}\n autoComplete=\"off\"\n onFocus={() => setOpen(true)}\n onChange={(e) => {\n setText(e.target.value);\n setFiltering(true);\n setActive(0);\n setOpen(true);\n }}\n onKeyDown={onKeyDown}\n onBlur={onBlur}\n />\n {open && (\n <div\n id={`${id}-list`}\n // biome-ignore lint/a11y/useFocusableInteractive lint/a11y/useSemanticElements: ARIA popup, focus stays on the input via aria-activedescendant\n role=\"listbox\"\n tabIndex={-1}\n aria-label={ariaLabel}\n style={LIST_STYLE}\n >\n {shown.map((o, i) => (\n <div\n key={o.value}\n id={optId(i)}\n // biome-ignore lint/a11y/useFocusableInteractive lint/a11y/useSemanticElements: ARIA popup, focus stays on the input via aria-activedescendant\n role=\"option\"\n tabIndex={-1}\n aria-selected={o.value === value}\n style={{\n padding: \"6px 8px\",\n cursor: \"pointer\",\n borderRadius: 4,\n background: i === active ? \"var(--w6w-hover, rgba(127,127,127,0.18))\" : undefined,\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n pick(o);\n }}\n onMouseEnter={() => setActive(i)}\n >\n {o.label}\n </div>\n ))}\n {shown.length === 0 && (\n <div role=\"presentation\" style={{ padding: \"6px 8px\", opacity: 0.6 }}>\n No matches\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","/**\n * InternalIcon — an internal pseudo-app's glyph on a rounded tile, sized and\n * shaped to match `AppIcon`'s image tile so internal (`@w6w/*`) nodes and app\n * nodes read as the same family everywhere they appear (canvas, add-step\n * picker, edit modal). The glyph markup comes from the node def\n * (`InternalNodeDef.icon` / `internalNodeIcon`) — static, in-repo SVG (no user\n * input). It strokes with the accent color and tracks the active theme.\n *\n * Deliberately NOT the shared `Icon` (`./Icon.tsx`), despite owning an `<svg>`:\n * this is a DATA-DRIVEN per-app identity mark — its content is a markup string\n * off the node def, one glyph per internal app, not a fixed UI glyph with a name\n * in the set (`./icons.tsx`). Unifying them would mean changing\n * `InternalNodeDef` to carry a name instead of its markup, which is a data-model\n * change, not an icon migration.\n */\nexport function InternalIcon({ icon, size = 28 }: { icon: string; size?: number }) {\n return (\n <span\n aria-hidden=\"true\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: size,\n height: size,\n borderRadius: 6,\n flexShrink: 0,\n background: \"var(--w6w-icon-swatch, var(--w6w-panel-2))\",\n color: \"var(--w6w-accent)\",\n }}\n >\n <svg\n width={Math.round(size * 0.6)}\n height={Math.round(size * 0.6)}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n // biome-ignore lint/security/noDangerouslySetInnerHtml: static, in-repo SVG glyph markup (no user input)\n dangerouslySetInnerHTML={{ __html: icon }}\n />\n </span>\n );\n}\n","/**\n * Convert between the Workflow logical model and the React Flow node/edge\n * representation. Also computes an auto-layout — a simple topological layering\n * (columns = depth; rows = sibling index) that is deterministic and portable\n * so the same workflow always opens with the same layout.\n */\nimport type { Edge, Node } from \"@xyflow/react\";\nimport {\n type FlowEdge,\n type FlowStep,\n type FlowWorkflow,\n edgeVisuals,\n isInternalApp,\n sourceHandleForLane,\n} from \"./flow-types.ts\";\n// T1.1.1 — the run-aware visual state a live-run repaint effect stamps onto a\n// node's `data` (see `WorkflowFlowEditor.tsx`'s patch effect). Never written\n// here: `workflowToFlow` is memoized on workflow identity alone (Trap 1), so\n// threading run state through it would repaint nothing on a poll tick.\nimport type { RunStatus, StepVisualState } from \"./run-visuals.ts\";\n\nexport interface StepNodeData extends Record<string, unknown> {\n step: FlowStep;\n /** True for internal pseudo-app nodes (`@w6w/*`) — rendered as pill cards. */\n isInternal: boolean;\n /**\n * This step's status within the run the host is currently showing\n * (T1.1.1). `undefined`/`\"no-run\"` ⇒ no run, or this canvas isn't showing\n * one. Patched in by `WorkflowFlowEditor.tsx`'s live-run repaint effect —\n * never set here, and never read by {@link flowToWorkflow}, which only\n * ever reads `.step` off a node's `data` (A6 — nothing run-related is\n * persisted).\n */\n stepStatus?: StepVisualState;\n /**\n * The owning run's OWN status, alongside {@link stepStatus} — a node\n * card's visual is a function of BOTH (RunStatus × StepStatus, not\n * StepStatus alone; see `run-visuals.ts`'s `stepNodeVisual`). Same\n * provenance/persistence rules as `stepStatus`.\n */\n runStatus?: RunStatus;\n}\n\nexport type StepNode = Node<StepNodeData>;\n\n/**\n * The React Flow id for the edge `from → to` in a given lane — **the one place**\n * the id convention lives.\n *\n * A success edge keeps the historic unqualified `from->to` spelling (so no\n * persisted definition changes id when it is reloaded); an error edge is\n * **qualified** with `:error`, because the model permits a success edge AND an\n * error edge between the same pair (core `rfcs/workflow.md` · `Edge.when`\n * amendment; D-T1-8) and two edges sharing one id would be collapsed by React\n * Flow's id-keyed store — silently losing a lane.\n *\n * Every site that mints or rewrites an edge id calls this: {@link workflowToFlow},\n * `applyConnect` (edge creation) and `renameStepInEdges` (the step-rename\n * rewrite) in `flow-connect.ts`. A second hand-rolled copy of the template is\n * exactly how the rename path came to drop the qualifier.\n */\nexport function flowEdgeId(from: string, to: string, when?: FlowEdge[\"when\"]): string {\n return when === \"error\" ? `${from}->${to}:error` : `${from}->${to}`;\n}\n\n/**\n * Why a step id may not be saved from the editor, or `null` when it may. The one\n * rule here is \"no `.`\" (a dotted id cannot be addressed by `steps.<id>.output`);\n * duplicates and the edge-time `->` / `:error` checks are NOT this function's job.\n */\nexport function stepIdError(id: string): string | null {\n return id.includes(\".\") ? \"A step id can't contain a dot (.).\" : null;\n}\n\n/**\n * The one wording for a refused edge id, shared by both routes into the collision —\n * drawing a wire whose minted id is taken (`applyConnect` / `connectConflict`) and\n * re-laning one onto a taken id (`setEdgeWhen` / `edgeWhenConflict`). `lead` names\n * what was refused, `id` is the taken id, and `involved` carries the step ids of the\n * **two edges that mint it**: the new/moving edge's endpoints and the sitting\n * edge's. Rendered inline with `role=\"alert\"`, never in a browser dialog\n * (`.ai/conventions.md`).\n *\n * It lives here, beside {@link flowEdgeId}, for two reasons: the clash *is* a\n * property of that function's non-injectivity over free-text step ids, and this\n * module is JSX-free so `node --test` can pin the wording (it used to sit in\n * `WorkflowFlowEditor.tsx`, where the runner cannot reach it — which is how the\n * wrong advice below shipped uncovered).\n *\n * ⚠️ **The cause is DETERMINED, never asserted.** This message used to hard-code\n * *\"because a step id ending in `:error` collides with the error-lane marker.\n * Rename that step\"* — and the guard has a second, equally real trigger: a step id\n * containing `->`, the separator itself. With steps `a`, `b->c`, `a->b`, `c` and an\n * edge `a → \"b->c\"`, drawing `\"a->b\" → c` is correctly refused (both mint\n * `a->b->c`) while **no step id ends in `:error`** — so the author was told to\n * rename a step that does not exist, and given advice that could not resolve their\n * problem. Inferring the cause from the taken `id` alone does not fix that: an id\n * ending in `:error` may equally be an error-lane edge whose collision came from an\n * embedded `->`. So the culprit is looked up among the ids actually involved, and\n * when none of them is ambiguous the message names **no** cause at all.\n *\n * ## Which of the two triggers it is, is decided by the LANE PAIR\n *\n * Scanning the involved ids for *either* spelling and taking the first match is\n * **not** enough — it names a step whose renaming cannot resolve the clash. Steps\n * `p->q`, `b`, `b:error` with `p->q → b` sitting on the **error** lane and\n * `p->q → \"b:error\"` drawn on the **success** lane both mint `p->q->b:error`; the\n * first-match scan blames `p->q`, which is the **shared source of both edges**, so\n * renaming it re-mints both and the edge is still refused. The mirror is just as\n * wrong: two **success**-lane edges over steps `x:error`, `y->z`, `x:error->y`, `z`\n * collide with no error lane anywhere, yet get blamed on the error-lane marker.\n *\n * The lane pair decides it, and decides it exactly:\n * - **Same lane on both edges** ⇒ `f1->t1` == `f2->t2` (with the same suffix) forces\n * the two splits to differ, i.e. an **embedded `->`**; it also forces both\n * endpoints to differ (equal sources would force equal targets and vice versa), so\n * renaming *any* involved id re-mints exactly one of the two edges.\n * - **Different lanes** ⇒ `fs->ts` == `fe->te:error`, and since `:error` contains\n * neither `-` nor `>` its 6 characters cannot overlap the separator — so **the\n * success edge's target** ends in `:error`, and that is the step to rename.\n *\n * The lanes are not passed in: they are recovered from `id` itself, which\n * {@link flowEdgeId} is the only minter of, so an endpoint pair spells `id` on at\n * most one lane (`f->t` and `f->t:error` are never equal). A pair that spells it on\n * neither means an already-corrupt edge set — the lane pair then determines nothing\n * and the message names no cause, exactly as when nothing involved is ambiguous. A\n * vague-but-true message beats a confident false one.\n */\nexport function idClashMessage(\n lead: string,\n id: string,\n involved: readonly (string | null | undefined)[],\n): string {\n const laneOf = (from: string | null | undefined, to: string | null | undefined) =>\n !from || !to\n ? undefined\n : flowEdgeId(from, to) === id\n ? \"success\"\n : flowEdgeId(from, to, \"error\") === id\n ? \"error\"\n : undefined;\n const drawn = laneOf(involved[0], involved[1]);\n const sitting = laneOf(involved[2], involved[3]);\n const sameLane = drawn !== undefined && drawn === sitting;\n const mixedLane = drawn !== undefined && sitting !== undefined && drawn !== sitting;\n // On mixed lanes the culprit is the SUCCESS edge's target (`involved` is\n // `[drawn.source, drawn.target, sitting.source, sitting.target]`).\n const successTarget = drawn === \"success\" ? involved[1] : involved[3];\n const culprit = sameLane\n ? involved.find((s): s is string => !!s && s.includes(\"->\"))\n : mixedLane && successTarget?.endsWith(\":error\")\n ? successTarget\n : undefined;\n // One long template per arm on purpose: `lint/style/useTemplate` forbids\n // concatenating a template with a literal, and the formatter does not break\n // string contents.\n const cause =\n culprit === undefined\n ? \"Rename one of the steps it connects, then try again.\"\n : sameLane\n ? `A step id containing “->” collides with the edge-id separator, so two different edges mint one id — rename the step “${culprit}”, then try again.`\n : `A step id ending in “:error” collides with the error-lane marker, so two different edges mint one id — rename the step “${culprit}”, then try again.`;\n return `${lead}: the id “${id}” is already taken by another edge. ${cause}`;\n}\n\n/** Nice constants — tunable but stable defaults so layouts don't jitter. */\nconst COLUMN_WIDTH = 240;\nconst ROW_HEIGHT = 100;\nconst MARGIN_X = 40;\nconst MARGIN_Y = 40;\n\n/**\n * The canvas slot a step in column `col`, row `row` occupies — **the one place**\n * the placement arithmetic lives, exactly as {@link flowEdgeId} is the one place\n * the id convention lives.\n *\n * Two callers, and the reason they must share this is user-visible: {@link\n * workflowToFlow} uses the slot as the *fallback* for a step with no stored\n * `position` (first open), while {@link relayoutNodes} uses it for *every* node\n * (the auto-layout control). A second copy of the arithmetic would make\n * \"auto-layout\" disagree with \"first open\" — the one difference an author would\n * notice immediately — so the only thing that differs between the two is whether\n * a stored coordinate wins, which belongs at the call site.\n *\n * A **fresh object** every call: React Flow owns `node.position` and mutates it\n * in place during a drag (see {@link storedPosition}).\n */\nfunction slotPosition(col: number, row: number): { x: number; y: number } {\n return { x: MARGIN_X + col * COLUMN_WIDTH, y: MARGIN_Y + row * ROW_HEIGHT };\n}\n\n/**\n * Layer index per step id under a topological layout of the graph: a step sits\n * one column right of its furthest-right predecessor (longest-path layering,\n * computed by relaxation).\n *\n * ## Termination — this loop used to hang the tab\n *\n * The relaxation is **bounded to `steps.length + 1` passes**. The unbounded\n * `while (changed)` it replaces assumed a DAG (\"for a DAG this converges\") and\n * never exited on a cycle: with `a → b → a` the `<` test stays satisfiable\n * forever and the layers climb without bound. The engine rejects cycles at plan\n * time, but **this editor lets you draw one**, and `workflowToFlow` calls this\n * on open — so a cyclic workflow froze the tab on load, and would have frozen it\n * mid-edit once an auto-layout button called the same code from a click.\n *\n * A **pass bound** was chosen over a separate cycle detector (a DFS colouring)\n * for two reasons: it keeps one traversal and one notion of \"the graph\" instead\n * of two that can drift, and the bound is provably exact rather than heuristic —\n * by the Bellman-Ford argument, after `k` full passes every step whose longest\n * path from a source is `k` edges long already holds its final layer, and an\n * acyclic graph's longest path visits each step at most once. So a DAG reaches\n * its fixpoint within `steps.length` passes and the extra pass here only ever\n * observes `changed === false`. **Acyclic output is therefore byte-identical to\n * the unbounded version** — the bound is not a heuristic cut-off, and\n * `artifacts/T3.3.1-computelayers-equivalence.sh` proves it against the previous\n * commit's blob over 200+ fixtures.\n *\n * ⚠️ What is **not** guaranteed is that a layer stays ≤ `steps.length - 1` (an\n * earlier revision of this comment claimed it, and used the claim to call the\n * clamp below a provable no-op on any DAG — that was **false**). `layer.get(pred)\n * ?? 0` treats an edge whose `from` is **not a declared step** as a phantom\n * predecessor sitting at layer 0, so such an edge contributes a real `+1`:\n * `steps: [a, b]` with `edges: [ghost→a, a→b]` puts `b` in column **2** while\n * `lastColumn` is 1. That graph is still fine — it converges, so `changed` is\n * `false` and the clamp never runs; the extra column simply renders (pinned by\n * `flow-utils.test.ts` · \"an edge from an UNDECLARED step adds a column\"). The\n * honest invariant is the narrower one: **the clamp runs only when the pass bound\n * is exhausted with the layout still moving, which requires a cycle.**\n *\n * Exceeding the bound *is* the cycle signal (`changed` is still true). The\n * layout then stays **usable** rather than throwing or refusing: the runaway\n * values are clamped to the last real column, so the steps on the cycle stack up\n * in one column (distinct rows — `workflowToFlow` counts rows per column) and\n * the author can see the loop they drew and delete an edge. Refusing to lay out\n * a cyclic graph would trade a hang for a workflow nobody can open to fix. The\n * clamp cannot fire on a DAG, because a DAG converges before the bound is spent —\n * **not** because its layers are bounded by `steps.length - 1`; see the ⚠️ above.\n */\nfunction computeLayers(steps: FlowStep[], edges: FlowEdge[]): Map<string, number> {\n const layer = new Map<string, number>();\n const incoming = new Map<string, string[]>();\n for (const s of steps) {\n layer.set(s.id, 0);\n incoming.set(s.id, []);\n }\n for (const e of edges) {\n incoming.get(e.to)?.push(e.from);\n }\n // Iterate to fixpoint. For a DAG this converges in O(V+E) passes — and the\n // pass bound is what makes that assumption safe instead of load-bearing.\n const maxPasses = steps.length + 1;\n let passes = 0;\n let changed = true;\n while (changed && passes < maxPasses) {\n passes++;\n changed = false;\n for (const s of steps) {\n const preds = incoming.get(s.id) ?? [];\n if (preds.length === 0) continue;\n const next = preds.reduce((max, p) => Math.max(max, (layer.get(p) ?? 0) + 1), 0);\n if ((layer.get(s.id) ?? 0) < next) {\n layer.set(s.id, next);\n changed = true;\n }\n }\n }\n if (changed) {\n // The bound ran out with the layout still moving ⇒ there is a cycle. Pull\n // the runaway columns back to the last real one so the graph still renders.\n const lastColumn = Math.max(0, steps.length - 1);\n for (const [id, col] of layer) {\n if (col > lastColumn) layer.set(id, lastColumn);\n }\n }\n return layer;\n}\n\n/**\n * A step's **stored** canvas coordinate, when it has a usable one.\n *\n * `position` arrives from a persisted JSON document (core `rfcs/workflow.md` ·\n * authoring-presentation amendment, mirrored on {@link FlowStep}), so both axes\n * are checked with `Number.isFinite`: a `null`, a string, a `NaN` from a\n * `JSON.parse`d `null`, or a half-written `{ x }` falls back to the computed slot\n * rather than putting the node at an unreachable coordinate.\n *\n * A **fresh object** is returned, never the one hanging off the step: React Flow\n * owns `node.position` while a drag is in flight, and the same step object is\n * also handed to the node's `data.step`.\n */\nfunction storedPosition(step: FlowStep): { x: number; y: number } | undefined {\n const p = step.position;\n if (!p || !Number.isFinite(p.x) || !Number.isFinite(p.y)) return undefined;\n return { x: p.x, y: p.y };\n}\n\n/**\n * Turn a Workflow into (nodes, edges) with an auto-layout when no positions are\n * known.\n *\n * A step's **stored `position` wins** over the computed slot (the amendment's\n * \"omitted ⇒ the editor computes a layout\" arm, and its converse). A partially\n * positioned graph mixes the two: positioned steps sit where they were left,\n * unpositioned ones take their computed slot.\n *\n * `computeLayers` runs over the **whole** graph either way, and the per-column\n * row counter advances for every step including positioned ones — so an\n * unpositioned step's computed coordinate is a pure function of the graph and\n * does not shift depending on which of its neighbours happen to carry a\n * coordinate.\n */\nexport function workflowToFlow(wf: FlowWorkflow): { nodes: StepNode[]; edges: Edge[] } {\n const edges: FlowEdge[] = wf.edges ?? implicitChain(wf.steps);\n const layer = computeLayers(wf.steps, edges);\n const rowsInLayer = new Map<number, number>();\n\n const nodes: StepNode[] = wf.steps.map((step) => {\n const isInternal = isInternalApp(step.uses.app);\n const col = layer.get(step.id) ?? 0;\n const row = rowsInLayer.get(col) ?? 0;\n rowsInLayer.set(col, row + 1);\n return {\n id: step.id,\n type: isInternal ? \"control\" : \"step\",\n position: storedPosition(step) ?? slotPosition(col, row),\n data: { step, isInternal },\n };\n });\n\n const flowEdges: Edge[] = edges.map((e) => {\n // Omitted ⇒ \"success\" (core rfcs/workflow.md · Edge.when amendment). The\n // lane rides on `data` so flowToWorkflow can read it straight back off the\n // React Flow edge; the className + label that tell an error edge apart on\n // the canvas come from {@link edgeVisuals} — the single source of truth,\n // shared with `setEdgeWhen`, which re-lanes an edge live. Inlining them here\n // is how the loaded look and the just-marked look drift apart.\n //\n // The id is qualified per lane, because the model permits a success edge AND\n // an error edge between the same pair: two edges sharing one id would be\n // collapsed by React Flow's id-keyed store and one lane silently lost. The\n // qualifier comes from {@link flowEdgeId}, which every other id site calls.\n //\n // `sourceHandle` is stamped from {@link sourceHandleForLane} (T1.1.1) so a\n // workflow saved before the error port existed renders its error edges from\n // the new port on next open, not only edges drawn live after the feature\n // shipped. `sourceHandle` is presentation only — `flowToWorkflow` never\n // reads it back, so this does not touch the persisted `Edge.when` round-trip.\n const when = e.when ?? \"success\";\n return {\n id: flowEdgeId(e.from, e.to, when),\n source: e.from,\n target: e.to,\n sourceHandle: sourceHandleForLane(when),\n animated: false,\n data: { when },\n // No run state here either (T1.1.1): `workflowToFlow` only ever runs\n // on workflow identity change (Trap 1), never on a live run's poll\n // tick, so it has no run state to pass — the live-run repaint effect\n // in `WorkflowFlowEditor.tsx` is the one call site that does.\n ...edgeVisuals(when, undefined),\n };\n });\n\n return { nodes, edges: flowEdges };\n}\n\n/**\n * Re-flow every node with the same deterministic layering the editor uses on\n * first open — the auto-layout control's whole implementation.\n *\n * Takes React Flow's `(nodes, edges)` rather than a `FlowWorkflow` because the\n * button acts on **what is currently on the canvas**, including steps added and\n * wires drawn since the last save.\n *\n * Same {@link computeLayers} and same {@link slotPosition} as {@link\n * workflowToFlow}, so a graph with no stored positions lays out byte-identically\n * either way (pinned by `flow-utils.test.ts` — \"auto-layout agrees with first\n * open\"). The **only** difference is that a stored coordinate does not win here:\n * overriding hand placement is precisely what the author asked for by clicking.\n * That is also why the caller confirms first — there is no undo in studio.\n *\n * Layering is keyed by **`node.id`**, not `node.data.step.id`: React Flow's\n * `edge.source`/`edge.target` name node ids, so keying by anything else would\n * silently drop every edge from the layering (a `?? 0` fallback puts the whole\n * graph in column 0) if the two ever disagreed.\n *\n * Returns a **new array of new node objects** — React Flow's state handle\n * compares by reference, so a mutated-in-place array does not re-render — with\n * every node's `id`, `type` and `data` carried across untouched (`data` by the\n * same reference, so no node card re-derives its metadata).\n */\nexport function relayoutNodes(nodes: StepNode[], edges: Edge[]): StepNode[] {\n // `computeLayers` reads only `.id` off a step; keying on the NODE id keeps it\n // consistent with the edge endpoints below. The bounded relaxation inside is\n // what makes this safe to call from a click: before it, a cyclic graph froze\n // the tab, and this button would have frozen it mid-edit.\n const steps: FlowStep[] = nodes.map((n) => ({ ...n.data.step, id: n.id }));\n const layer = computeLayers(\n steps,\n edges.map((e) => ({ from: e.source, to: e.target })),\n );\n const rowsInLayer = new Map<number, number>();\n return nodes.map((n) => {\n const col = layer.get(n.id) ?? 0;\n const row = rowsInLayer.get(col) ?? 0;\n // Advance for EVERY node, exactly as `workflowToFlow` does — the row counter\n // is per column, and skipping any node would collapse two onto one slot.\n rowsInLayer.set(col, row + 1);\n return { ...n, position: slotPosition(col, row) };\n });\n}\n\n/**\n * Reverse direction: pull the graph state back into a Workflow shape for\n * onChange.\n *\n * Each emitted step carries the **current canvas coordinate** of its node, unless\n * `original.settings.savePosition` is explicitly `false`. The flag is read off\n * the workflow this function already receives — deliberately **not** a new\n * parameter or an options bag, because both exported conversion functions are\n * public `@w6w/ui/flow` API for a partner-facing library and a signature\n * change here would break it for a value the function can already see.\n *\n * ⚠️ **`savePosition` defaults to `true`** (core `rfcs/workflow.md` ·\n * authoring-presentation amendment), so it is read as `!== false`: an absent\n * `settings` object means positions *are* persisted. The practical consequence is\n * intended — **a workflow that has never been saved by this editor starts\n * carrying `position` on every step the first time it is saved.**\n */\nexport function flowToWorkflow(\n original: FlowWorkflow,\n nodes: StepNode[],\n edges: Edge[],\n): FlowWorkflow {\n // `!== false`, never `?? false` and never `=== true`: omitted ⇒ ON.\n const savePosition = original.settings?.savePosition !== false;\n const nodeById = new Map<string, StepNode>(nodes.map((n) => [n.id, n]));\n\n /**\n * Stamp a step with its node's coordinate.\n *\n * `Math.round` is required, not cosmetic: React Flow reports fractional\n * coordinates, and auto-save dedupes by comparing the serialized payload — an\n * unrounded float would make a no-op render look like a change and produce a\n * write storm.\n *\n * When `savePosition` is `false` the step is returned **untouched**, which is\n * not the same as clearing it: \"not written\" is not \"erased\", so a coordinate a\n * colleague already stored survives someone else turning their own toggle off\n * (amendment: \"any values already stored are left as they are, not erased\").\n */\n const withPosition = (step: FlowStep): FlowStep => {\n if (!savePosition) return step;\n const p = nodeById.get(step.id)?.position;\n if (!p || !Number.isFinite(p.x) || !Number.isFinite(p.y)) return step;\n return { ...step, position: { x: Math.round(p.x), y: Math.round(p.y) } };\n };\n\n // Preserve original step order where possible; append new nodes at the end.\n const stepById = new Map<string, FlowStep>();\n for (const s of original.steps) stepById.set(s.id, s);\n for (const n of nodes) if (n.data?.step) stepById.set(n.id, n.data.step);\n\n const nextSteps: FlowStep[] = [];\n const seen = new Set<string>();\n for (const s of original.steps) {\n const current = stepById.get(s.id);\n if (current && nodes.some((n) => n.id === s.id)) {\n nextSteps.push(withPosition(current));\n seen.add(s.id);\n }\n }\n for (const n of nodes) {\n if (seen.has(n.id)) continue;\n const s = stepById.get(n.id);\n if (s) nextSteps.push(withPosition(s));\n }\n\n // Read the lane back off the React Flow edge (put there by workflowToFlow /\n // by applyConnect at creation). `\"success\"` is written as ABSENT — the house\n // omit-the-default idiom — so a definition with no error edge round-trips\n // byte-identically to what was loaded.\n const nextEdges: FlowEdge[] = edges.map((e) => {\n const when = (e.data as { when?: FlowEdge[\"when\"] } | undefined)?.when;\n return when === \"error\"\n ? { from: e.source, to: e.target, when }\n : { from: e.source, to: e.target };\n });\n\n return { ...original, steps: nextSteps, edges: nextEdges };\n}\n\n/** The workflow's stored camera, as `settings.viewport` declares it. */\ntype StoredViewport = NonNullable<NonNullable<FlowWorkflow[\"settings\"]>[\"viewport\"]>;\n\n/**\n * The workflow's **stored** camera position, when it has a usable one — the\n * viewport counterpart to {@link storedPosition}, and the single definition of\n * \"a viewport this editor will act on\". Both the restore-on-open read and\n * {@link withViewport}'s no-op comparison go through it, so they cannot disagree\n * about what counts as stored.\n *\n * All three components are checked with `Number.isFinite` for the same reason\n * `storedPosition` checks two: `settings.viewport` arrives from a persisted JSON\n * document that an author can hand-edit (studio's `</>` raw-JSON modal), and a\n * `null`, a string or a half-written `{ x, y }` would otherwise be handed to\n * React Flow's `defaultViewport` as the initial transform — a `NaN` there blanks\n * the canvas, with no way back except editing the JSON again. Unusable ⇒\n * `undefined`, i.e. \"no stored viewport\", which falls back to `fitView`.\n *\n * A **fresh object** is returned, never the one hanging off `settings`: React\n * Flow owns the viewport it is given.\n */\nexport function storedViewport(wf: FlowWorkflow): StoredViewport | undefined {\n const v = wf.settings?.viewport;\n if (!v || !Number.isFinite(v.x) || !Number.isFinite(v.y) || !Number.isFinite(v.zoom)) {\n return undefined;\n }\n return { x: v.x, y: v.y, zoom: v.zoom };\n}\n\n/**\n * Record the author's viewport on the workflow (core `rfcs/workflow.md` ·\n * authoring-presentation amendment). Pure, so the two decisions that matter —\n * rounding and no-op detection — are unit-testable without mounting React Flow.\n *\n * Returns `wf` **UNCHANGED (the same reference)** when:\n * - `settings.savePosition` is `false` — read as `!== false`, never `?? false`\n * and never `=== true`: **omitted ⇒ ON**, same as `flowToWorkflow`;\n * - the rounded viewport already equals the stored one;\n * - the incoming viewport is not finite (nothing usable to store).\n *\n * The same-reference return **is** the coalescing guard: the caller emits only\n * when the reference changes, so a pan that lands back where it started emits\n * nothing at all. That matters because the host's auto-save is a trailing\n * debounce over emitted changes — every emission is a candidate network write.\n *\n * Rounding is pinned for that same reason (and mirrors `flowToWorkflow`'s\n * coordinate rounding): `x`/`y` to integers, `zoom` to **3 decimal places**.\n * A trackpad reports the zoom as a long float, so without it two visually\n * identical viewports serialize differently and every idle gesture looks like a\n * change to a payload-comparing auto-save.\n *\n * `settings` is spread, not replaced, so `autoSave` / `savePosition` survive a\n * viewport write — the mirror image of `writeSetting` (studio) deleting a key at\n * its default without disturbing `viewport`. That mirror runs to the **guard on\n * the spread** as well: `settings` is typed as an object here, but it arrives from\n * a `JSON.parse`d document an author can hand-edit (studio's `</>` raw-JSON\n * modal), so `\"settings\": \"hello\"` would spread into indexed keys —\n * `{\"0\":\"h\",\"1\":\"e\",…, viewport}` — **on a pan**, and the host's auto-save would\n * re-persist that on a debounce with nobody clicking anything. Anything that is\n * not a plain object therefore reads as \"no settings\", i.e. the write produces a\n * fresh `{ viewport }`, discarding the unusable value; the predicate is\n * `writeSetting`'s, character for character, so the two really are one rule.\n */\nexport function withViewport(wf: FlowWorkflow, vp: StoredViewport): FlowWorkflow {\n // `!== false`, never `?? false` and never `=== true`: omitted ⇒ ON.\n const savePosition = wf.settings?.savePosition !== false;\n if (!savePosition) return wf;\n if (!Number.isFinite(vp.x) || !Number.isFinite(vp.y) || !Number.isFinite(vp.zoom)) return wf;\n const next: StoredViewport = {\n x: Math.round(vp.x),\n y: Math.round(vp.y),\n zoom: Math.round(vp.zoom * 1000) / 1000,\n };\n const current = storedViewport(wf);\n if (current && current.x === next.x && current.y === next.y && current.zoom === next.zoom) {\n return wf;\n }\n // Studio's `writeSetting` predicate, verbatim — a non-object `settings` must not\n // spread into indexed keys (see the docstring).\n const prev =\n typeof wf.settings === \"object\" && wf.settings !== null && !Array.isArray(wf.settings)\n ? wf.settings\n : undefined;\n return { ...wf, settings: { ...prev, viewport: next } };\n}\n\n/** When no edges are declared, treat steps as a linear chain in declared order. */\nfunction implicitChain(steps: FlowStep[]): FlowEdge[] {\n const out: FlowEdge[] = [];\n for (let i = 0; i < steps.length - 1; i++) out.push({ from: steps[i].id, to: steps[i + 1].id });\n return out;\n}\n\n/**\n * Turn a human-readable label (an action's `label`/`displayName`) into an\n * id-safe slug for {@link suggestStepId}'s `prefix` — human override,\n * 2026-08-30: a step id derived from its OWN action (\"data_1\",\n * \"render_template_1\", \"manual_trigger_1\") orients a reader who never\n * renamed it, unlike the generic \"gate_1\"/\"step_1\" every internal/external\n * step used to get regardless of what it actually does. Lowercase,\n * underscore-separated, ASCII word characters only; falls back to `\"step\"`\n * for a label that slugifies to nothing (empty, or entirely punctuation).\n */\nexport function slugifyLabel(label: string): string {\n const slug = label\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n return slug || \"step\";\n}\n\n/**\n * The current chain's ROOT: the earliest-added node (array/declaration order)\n * with no incoming edge. `undefined` for an empty graph. Used to give a\n * newly-added TRIGGER a sensible default wire — human override, 2026-08-30 —\n * rather than always landing as a floating node. Array order (not position)\n * is the tie-break because it is deterministic and matches \"the node that\n * was here first,\" not wherever the canvas happens to have placed it.\n */\nexport function findChainRoot(nodes: StepNode[], edges: Edge[]): StepNode | undefined {\n const hasIncoming = new Set(edges.map((e) => e.target));\n return nodes.find((n) => !hasIncoming.has(n.id));\n}\n\n/**\n * The current chain's TAIL: the most-recently-added node (array/declaration\n * order) with no outgoing edge. `undefined` for an empty graph. Used to give\n * a newly-added non-trigger STEP a sensible default wire — the most recently\n * placed branch is the one a user adding steps one at a time is most likely\n * extending.\n */\nexport function findChainTail(nodes: StepNode[], edges: Edge[]): StepNode | undefined {\n const hasOutgoing = new Set(edges.map((e) => e.source));\n for (let i = nodes.length - 1; i >= 0; i--) {\n if (!hasOutgoing.has(nodes[i].id)) return nodes[i];\n }\n return undefined;\n}\n\n/** Suggest a unique step id given the current graph. */\nexport function suggestStepId(existing: string[], prefix = \"step\"): string {\n const set = new Set(existing);\n for (let i = 1; i < 1000; i++) {\n const id = `${prefix}_${i}`;\n if (!set.has(id)) return id;\n }\n return `${prefix}_${crypto.randomUUID().slice(0, 8)}`;\n}\n\n// ── Code-view serializers ──────────────────────────────────────────────────\n//\n// The ONE place a step or its params turn into code-view text — three hosts\n// (`StepBuilderModal.tsx`'s `ControlStepConfig`/`AppStepConfig` and\n// `WorkflowFlowEditor.tsx`'s `StepEditModal`) used to call `JSON.stringify`\n// locally, which is how a manual trigger's `<>` came to show only\n// `{\"fields\":[…]}`: `with.fields` is that trigger's one declared param, and a\n// bare `JSON.stringify(step.with)` never surfaced `uses`/`id` at all.\n\n/**\n * A step, or the add-step hosts' in-progress `BuiltStep` (`StepBuilderModal.tsx`)\n * — structurally `FlowStep` minus `id`, which those hosts legitimately have not\n * minted yet (the editor assigns it once the step first joins the graph). Kept\n * structural rather than importing `BuiltStep` so this module stays the\n * dependency-free base every host already imports from, not the other way\n * round.\n */\nexport type StepLike = Omit<FlowStep, \"id\"> & { id?: string };\n\n/**\n * The full-step `<>` view text — every persisted field, `id` included when the\n * caller has one, no more and no less. Core `rfcs/workflow.md`: \"A step **is**\n * an Invocation\", so this is the whole step, not a derived projection — no\n * `kind` field is added, and nothing here special-cases a trigger's\n * `with.fields`; it is an ordinary declared param living in the same `with`\n * slot every step uses.\n *\n * **Read-only in v1 (D-3)** — a hand-edited `uses`/`id` has no validation path\n * today, so callers must not wire a write-back path from this text. Write\n * access stays on {@link paramsToJson}'s view and the Form view.\n */\nexport function stepToJson(step: StepLike): string {\n return JSON.stringify(step, null, 2);\n}\n\n/**\n * The params-only view text — `step.with`, exactly what the `<>` view showed\n * before this task split \"the whole step\" out from \"just its params\". Still\n * writable: the params-only `JsonEditor`'s `onValidChange` feeds straight back\n * into `with`/`withValues`, same as it always has.\n */\nexport function paramsToJson(step: Pick<StepLike, \"with\">): string {\n return JSON.stringify(step.with ?? {}, null, 2);\n}\n","/**\n * An upstream step's output SHAPE — the field paths a later step can pick —\n * from the three places one can come from, in precedence order:\n *\n * 1. **Declared** — the app action's `output` (`core/rfcs/action.md`\n * `OutputField[]`), so a downstream step can reference `get-event`'s\n * `name.text` before anything has run.\n * 2. **Sample** — the action's `sample` value, when it declares no `output`.\n * 3. **Test run** — the step's last saved test output, when the action\n * declares neither. With none of the three, the author has to run a test.\n *\n * Every field is a dot-separated PATH (`start.utc`), the spec's own notation\n * for nesting (`OutputField.key`: \"Dot notation for nested paths\"). That is\n * also exactly how the engine resolves a ref — JSONLogic `var` splits on `.`\n * (`core/packages/expr/src/jsonlogic.ts` `getVar`) — so `steps.<id>.output.<path>`\n * reaches the nested value. A segment that can't survive that split is dropped\n * by the picker (`isRefSafePath`).\n *\n * Pure and JSX-free so `node --test` exercises it directly.\n */\n\n/** One pickable output field of a step. `key` is a dot path; `label` is display-only. */\nexport interface OutputFieldRef {\n key: string;\n label?: string;\n /** `true` — `key` is a dot path whose segments are checked one by one. */\n path: true;\n}\n\n/** Where a step's offered fields came from. */\nexport type OutputShapeSource = \"declared\" | \"sample\" | \"test\";\n\n/** How deep inference walks a sample/test value. Deeper paths stay reachable via the parent. */\nconst MAX_DEPTH = 3;\n/** Cap on inferred fields per step, so a huge test payload can't flood the rail. */\nconst MAX_FIELDS = 100;\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/**\n * The fields an action's `output` declares, or `undefined` when it declares\n * none. A `DynamicOutput` (`{ source }`) is resolved by a hook the editor does\n * not run, so it counts as \"nothing declared\" and the test-run fallback applies.\n */\nexport function declaredOutputFields(output: unknown): OutputFieldRef[] | undefined {\n if (!Array.isArray(output)) return undefined;\n const fields: OutputFieldRef[] = [];\n for (const f of output) {\n if (!isPlainObject(f) || typeof f.key !== \"string\" || f.key === \"\") continue;\n const label = typeof f.label === \"string\" && f.label !== \"\" ? f.label : undefined;\n fields.push(label ? { key: f.key, label, path: true } : { key: f.key, path: true });\n }\n return fields.length > 0 ? fields : undefined;\n}\n\n/**\n * Field paths inferred from a concrete value (an action's `sample` or a test\n * run's output): every key of a plain object, recursing into nested plain\n * objects up to {@link MAX_DEPTH}. Arrays and scalars are leaves. `undefined`\n * when the value isn't a plain object with at least one key.\n */\nexport function inferOutputFields(value: unknown): OutputFieldRef[] | undefined {\n if (!isPlainObject(value)) return undefined;\n const fields: OutputFieldRef[] = [];\n const walk = (obj: Record<string, unknown>, prefix: string, depth: number) => {\n for (const [k, v] of Object.entries(obj)) {\n if (fields.length >= MAX_FIELDS) return;\n const key = prefix ? `${prefix}.${k}` : k;\n fields.push({ key, path: true });\n if (isPlainObject(v) && depth < MAX_DEPTH) walk(v, key, depth + 1);\n }\n };\n walk(value, \"\", 1);\n return fields.length > 0 ? fields : undefined;\n}\n\n/** The value at a dot path inside `value`, or `undefined` when any segment is missing. */\nexport function valueAtPath(value: unknown, path: string): unknown {\n let cur: unknown = value;\n for (const seg of path.split(\".\")) {\n if (!isPlainObject(cur) || !(seg in cur)) return undefined;\n cur = cur[seg];\n }\n return cur;\n}\n\n/** The subset of an action definition this module reads. */\nexport interface ActionShapeDef {\n output?: unknown;\n sample?: unknown;\n}\n\n/**\n * Resolve a step's offered fields by the precedence above. `action` is the\n * app action definition (`undefined` while its app's actions are loading, or\n * for a node that has none); `testOutput` is the step's last saved test output.\n */\nexport function resolveOutputShape(\n action: ActionShapeDef | undefined,\n testOutput: unknown,\n): { fields: OutputFieldRef[]; from: OutputShapeSource } | undefined {\n const declared = declaredOutputFields(action?.output);\n if (declared) return { fields: declared, from: \"declared\" };\n const fromSample = inferOutputFields(action?.sample);\n if (fromSample) return { fields: fromSample, from: \"sample\" };\n const fromTest = inferOutputFields(testOutput);\n if (fromTest) return { fields: fromTest, from: \"test\" };\n return undefined;\n}\n","/**\n * The incoming state a single-step Test / ▶ Run is sent with, and the pure\n * graph logic that derives it. Extracted out of `WorkflowFlowEditor.tsx` so\n * `node --test` can exercise it directly — the same precedent `flow-connect.ts`\n * sets (see that file's own header comment); this module stays JSX-free.\n *\n * Three surfaces mount this state today, all from the SAME functions so they\n * cannot drift: the step editor's Test tab and the canvas ▶ Run collect form\n * (both already wired, unchanged by this move) and `StepBuilderModal`'s\n * add-step Test tab (T1.1.1 — the new caller, via {@link stepBuilderUpstreamSteps}).\n */\nimport type { Edge } from \"@xyflow/react\";\nimport type { ExpressionStepSource } from \"./components/ExpressionOptions.tsx\";\nimport { TRIGGER_APP, internalNodeDef, isInternalApp } from \"./flow-types.ts\";\nimport type { StepNode } from \"./flow-utils.ts\";\nimport { type ActionShapeDef, inferOutputFields, resolveOutputShape } from \"./output-shape.ts\";\nimport type { StepMeta, StepStartState, StepTest } from \"./provider.tsx\";\nimport { asFieldDefs, fieldsToParams } from \"./trigger-fields.ts\";\n\n/**\n * What the editor knows about upstream steps' output SHAPES beyond the static\n * `internalNodeDef(...).output` — both optional, so a caller without them gets\n * exactly the old projection.\n */\nexport interface StepShapeContext {\n /**\n * An app step's action definition (its declared `output` / `sample`).\n * `undefined` while that app's actions haven't loaded — the step then makes\n * no \"run a test\" claim it might have to retract a moment later.\n */\n actionDef?: (app: string, action: string) => ActionShapeDef | undefined;\n /** Each step's latest saved test-run output, by step id. */\n testOutputs?: Record<string, unknown>;\n}\n\n/** A graph ancestor carrying a saved step-test, offered as a one-click seed. */\nexport interface SeedSource {\n stepId: string;\n label: string;\n test: StepTest;\n}\n\n/**\n * `pendingConnect`'s shape (`WorkflowFlowEditor.tsx`'s state): the handle a\n * connection drag was released from, when it ended on empty canvas and opened\n * the step builder to create + auto-wire a new node. `position` is part of\n * that state too (where to place the new node) but unused by the direction\n * rule below, so it is deliberately omitted here — `pendingConnect`'s real\n * type carries it, and a wider object satisfies this narrower one structurally.\n */\ninterface PendingConnect {\n nodeId: string;\n handleType: \"source\" | \"target\";\n}\n\n/** Every node id that is a graph ancestor of `rootId` — walks `edges` backward. */\nfunction ancestorIds(rootId: string, edges: Edge[]): Set<string> {\n const parents = new Map<string, string[]>();\n for (const e of edges) {\n const arr = parents.get(e.target) ?? [];\n arr.push(e.source);\n parents.set(e.target, arr);\n }\n const ancestors = new Set<string>();\n const stack = [rootId];\n while (stack.length) {\n const id = stack.pop() as string;\n for (const p of parents.get(id) ?? []) {\n if (!ancestors.has(p)) {\n ancestors.add(p);\n stack.push(p);\n }\n }\n }\n return ancestors;\n}\n\n/**\n * Project the nodes in `ids` into `ExpressionStepSource`s, the one place that\n * decides trigger detection and declared-output projection — shared by\n * {@link upstreamStateSources} and {@link stepBuilderUpstreamSteps} so both\n * callers agree on what a trigger ancestor looks like.\n */\nfunction projectStepSources(\n ids: Set<string>,\n nodes: StepNode[],\n shapes: StepShapeContext = {},\n): { steps: ExpressionStepSource[]; hasTrigger: boolean } {\n const steps: ExpressionStepSource[] = [];\n let hasTrigger = false;\n for (const n of nodes) {\n if (!ids.has(n.id)) continue;\n const step = n.data.step;\n const isTrigger = internalNodeDef(step.uses.app, step.uses.action)?.group === \"trigger\";\n if (isTrigger) {\n // `trigger.event` stays on offer — but the trigger is ALSO a `steps.<id>`\n // source (see `upstreamStateSources`'s doc below), so it falls through to\n // the push.\n hasTrigger = true;\n }\n // Declared output fields, from one of two DISJOINT sources today — a\n // manual trigger's own `with.fields`, or a node's static `output`\n // declaration (`internalNodeDef(...).output`, e.g. `@w6w/template ·\n // render` / `@w6w/http · request`). A manual trigger never carries a\n // static `output` (INTERNAL_NODES declares one or the other, never both),\n // so this is written as explicit precedence rather than a merge that could\n // silently clobber one with the other: the manual-trigger path wins when\n // it applies, the static declaration is the fallback otherwise.\n //\n // MANUAL-TRIGGER-ONLY for the `with.fields` path: a webhook/scheduler\n // entry node's `with.fields` payload is `trigger.event` (see the\n // file-header-level doc below), not `steps.<id>.output`, so it must not be\n // projected here; on any other node `with.fields` is that action's INPUT,\n // and projecting it would fabricate declared outputs the step never\n // produces. The trigger-field parser already skips a blank/missing `key`.\n const isManualTrigger = isTrigger && step.uses.app === TRIGGER_APP;\n const declared: { key: string; label?: string }[] = isManualTrigger\n ? fieldsToParams(asFieldDefs(step.with?.fields)).map((p) => ({\n key: p.key,\n label: p.label,\n }))\n : (internalNodeDef(step.uses.app, step.uses.action)?.output ?? []);\n const source: ExpressionStepSource = { id: step.id, label: step.id };\n // OMITTED (not `[]`) when nothing is declared, so a consumer can tell\n // \"nothing declared\" from \"declared none\". Keys are verbatim: each becomes\n // `steps.<id>.output.<key>`, and only that form resolves at run time.\n if (declared.length > 0) {\n steps.push({ ...source, outputs: declared });\n continue;\n }\n // A webhook/scheduler entry node's payload is `trigger.event`, never\n // `steps.<id>.output` (see above), so no fallback shape applies to it.\n if (isTrigger) {\n steps.push(source);\n continue;\n }\n const testOutput = shapes.testOutputs?.[step.id];\n if (isInternalApp(step.uses.app)) {\n // A built-in node with no static output (`@w6w/script`, a Function\n // call, …): its last test run is the only shape there is.\n const fields = inferOutputFields(testOutput);\n steps.push(fields ? { ...source, outputs: fields, outputsFrom: \"test\" } : source);\n continue;\n }\n // An app action: its declared `output`, else its `sample`, else the last\n // test run (`output-shape.ts`). With none, the author has to run a test —\n // but only say so once the action definition has actually loaded.\n const action = shapes.actionDef?.(step.uses.app, step.uses.action);\n const shape = resolveOutputShape(action, testOutput);\n // Only this branch is an external app action, so only it carries `hasMeta` (R-7),\n // and only with a real app id (a blank `uses.app` is a half-built step).\n const meta = step.uses.app.trim() !== \"\" ? { hasMeta: true as const } : {};\n if (shape) {\n steps.push({ ...source, outputs: shape.fields, outputsFrom: shape.from, ...meta });\n } else {\n steps.push(action ? { ...source, needsTest: true, ...meta } : { ...source, ...meta });\n }\n }\n return { steps, hasTrigger };\n}\n\n/**\n * The workflow state a given step can reference: the outputs of every step\n * that runs before it (its graph ancestors) plus whether a trigger precedes\n * it.\n *\n * A trigger ancestor is **both**. It is pushed into `steps` like any other\n * ancestor — `core/rfcs/node-types.md` (\"Triggers as nodes\"): *\"Executing a\n * trigger node yields the run's start payload … which downstream nodes read as\n * `steps.<triggerId>.output`\"* — **and** it sets `hasTrigger`, which offers the\n * separate `trigger.event` root. The two are different values, not two spellings\n * of one: `trigger.event` is the dispatcher-delivered event payload (seeded from\n * `seed.event`), while a manual trigger's filled fields land under\n * `steps.<id>.output`. Offering only the former is why a trigger's declared\n * fields were unreachable from the picker.\n *\n * A **manual trigger** that declares output fields (`with.fields`) carries\n * them as `outputs`, so a consumer can offer `steps.<id>.output.<key>` per\n * field. Only a manual trigger: `fields` is an ordinary param name, and on any\n * other node — including a webhook/scheduler entry node, whose payload is\n * `trigger.event` instead (see the ⚠️ note below) — it holds that action's\n * INPUT; an `@w6w/http:request` with `with.fields = [{key:\"x\"}]` would\n * otherwise be advertised as declaring an output `x` it never produces. The\n * manual trigger's `fields` is the one case where the param IS the output\n * contract (`core/rfcs/node-types.md:194-196`; `trigger.md:119` covers only\n * what drives editor autocomplete).\n *\n * ⚠️ These declared fields resolve differently on each run path. On the\n * **single-step Test / ▶ Run** path (below), this editor sends a start state\n * seeded from the upstream saved fixtures (see {@link startStateFromSeeds})\n * which `POST /apps/:id/actions/:key/invoke` projects onto\n * `steps.<id>.output`. On a **full run**, a manual trigger's declared fields\n * resolve too: `POST /workflows/:id/run` accepts an `input` body field, and\n * `run-workflow.ts` seeds the `@w6w/trigger` node's own output with it\n * (verified by `server/e2e/trigger_run_payload_e2e_test.ts`). A\n * webhook/scheduler entry node's declared fields do **not** resolve on a full\n * run — its payload there is `trigger.event`, not `steps.<id>.output`, by\n * design (`core/rfcs/trigger.md:378`) — which is exactly why the projection\n * above is narrowed to a manual trigger only.\n *\n * With no specific step (shouldn't happen for a field edit) every node is offered.\n */\nexport function upstreamStateSources(\n editingId: string | null,\n nodes: StepNode[],\n edges: Edge[],\n shapes?: StepShapeContext,\n): { steps: ExpressionStepSource[]; hasTrigger: boolean } {\n const ids = editingId ? ancestorIds(editingId, edges) : new Set(nodes.map((n) => n.id));\n return projectStepSources(ids, nodes, shapes);\n}\n\n/**\n * The new add-step wizard's graph ancestors, derived from `pendingConnect` —\n * the handle a connection drag was released from before the builder opened\n * (`null` for a floating add with no drag at all).\n *\n * **Direction matters.** `addBuiltStep`'s edge-wiring ternary\n * (`WorkflowFlowEditor.tsx`) only makes the new step DOWNSTREAM of\n * `pendingConnect.nodeId` when the drag came off a **source** handle\n * (`[pendingConnect.nodeId, id]`); off a **target** handle the new step becomes\n * the edge's SOURCE instead (`[id, pendingConnect.nodeId]`), so\n * `pendingConnect.nodeId` ends up downstream of the new step, not upstream —\n * offering it as a seed would be backwards. A `handleType: \"source\"` drag\n * carries the dragged node itself (it IS upstream of the step about to be\n * created) plus that node's own ancestors, via the same projection\n * {@link upstreamStateSources} uses.\n */\nexport function stepBuilderUpstreamSteps(\n pendingConnect: PendingConnect | null,\n nodes: StepNode[],\n edges: Edge[],\n shapes?: StepShapeContext,\n): ExpressionStepSource[] {\n if (!pendingConnect || pendingConnect.handleType === \"target\") return [];\n const ids = ancestorIds(pendingConnect.nodeId, edges);\n ids.add(pendingConnect.nodeId);\n return projectStepSources(ids, nodes, shapes).steps;\n}\n\n/**\n * Gather each graph ancestor's latest saved step-test so the incoming-state\n * control can offer it as a seed. **One implementation**, called by every\n * surface that mounts {@link SeedSource}s — the step editor's Test tab, the\n * canvas ▶ Run collect form, and `StepBuilderModal`'s add-step Test tab — so\n * the `gate_1 · succeeded` chip behaves identically everywhere.\n *\n * `listStepTests` is injected (rather than reached for via `useW6WApi()`\n * directly) so this stays a plain async function `node --test` can call with a\n * stub — the React-facing wrapper is `use-seed-sources.ts`'s `useSeedSources`.\n * It returns oldest-first per step, so the last entry is the most recent\n * fixture. A step with no saved fixture (an empty list, or a lookup that\n * throws) contributes nothing — best-effort, per step, never breaking the rest.\n */\nexport async function fetchSeedSources(\n listStepTests: (stepId: string) => Promise<StepTest[]>,\n upstreamSteps: ExpressionStepSource[],\n): Promise<SeedSource[]> {\n const results = await Promise.all(\n upstreamSteps.map(async (s): Promise<SeedSource | null> => {\n try {\n const tests = await listStepTests(s.id);\n const latest = tests.length ? tests[tests.length - 1] : null;\n return latest ? { stepId: s.id, label: s.label ?? s.id, test: latest } : null;\n } catch {\n return null;\n }\n }),\n );\n return results.filter((r): r is SeedSource => r !== null);\n}\n\n/**\n * The start state a single-step Test / ▶ Run is sent with: **the last-known\n * saved output of each upstream step**, keyed by step id, in the shape the\n * invoke route accepts (`{ steps: { <id>: { output } } }` — the server's\n * `StartStateInput`, `packages/api/ambient-scope.ts`). It is what makes a\n * `with` block written as `{{ steps.<id>.output.<field> }}` resolve to the\n * value that step last produced instead of concatenating as `\"\"`.\n *\n * Read from the same `step_tests` fixtures the seed chips offer — no upstream\n * step is re-run to produce it, and nothing here is computed live.\n *\n * A step whose fixture never captured an output contributes **no entry** rather\n * than an empty one, and a set with no outputs at all returns `undefined` so\n * the invoke body carries no `state` key at all (byte-identical to a request\n * from before this existed). Each id gets its OWN `{ output }` object: sharing\n * one would make every reference resolve the last step's data.\n *\n * ⚠️ Single-step scope only. A full run (`POST /workflows/:id/run`) builds its\n * own scope and is not affected by this.\n */\nexport function startStateFromSeeds(seeds: SeedSource[]): StepStartState | undefined {\n const steps: Record<string, { output?: unknown; meta?: StepMeta }> = {};\n for (const s of seeds) {\n const output = s.test.lastRunOutput;\n const hasOutput = output !== undefined && output !== null;\n // `lastRunOutput` is NULL for both \"never ran\" and \"ran and returned null\"\n // (`rowToStepTest`), so only a succeeded status tells them apart. A failed\n // run is never seeded, even when it carries meta (meta reaches scope for\n // succeeded steps only).\n if (!hasOutput && s.test.lastRunStatus !== \"succeeded\") continue;\n const meta = s.test.lastRunMeta;\n steps[s.stepId] = { output: hasOutput ? output : null, ...(meta ? { meta } : {}) };\n }\n return Object.keys(steps).length > 0 ? { steps } : undefined;\n}\n\n/**\n * Sample values for a step's `steps.<id>.meta.*` refs, from a saved fixture's\n * `lastRunMeta`. Reads the four named fields only; absent meta yields nothing\n * (a version or connection is never derived from anywhere else).\n */\nexport function stepMetaSampleValues(\n stepId: string,\n meta: StepMeta | null | undefined,\n): Record<string, unknown> {\n if (!meta) return {};\n const p = `steps.${stepId}.meta`;\n return {\n [`${p}.app`]: meta.app,\n [`${p}.version`]: meta.version,\n [`${p}.action`]: meta.action,\n [`${p}.connectionId`]: meta.connectionId,\n };\n}\n","/**\n * The React-facing wrapper around `step-preview-state.ts`'s pure\n * {@link fetchSeedSources} — the one piece of the seed pipeline that must stay\n * a hook (it reaches for `useW6WApi()` + `useState`/`useEffect`), so it lives\n * apart from that JSX-free module. Every surface that offers upstream seed\n * chips mounts this SAME hook: the step editor's Test tab, the canvas ▶ Run\n * collect form, and `StepBuilderModal`'s add-step Test tab.\n */\nimport { useEffect, useState } from \"react\";\nimport type { ExpressionStepSource } from \"./components/ExpressionOptions.tsx\";\nimport { useW6WApi } from \"./provider.tsx\";\nimport { type SeedSource, fetchSeedSources } from \"./step-preview-state.ts\";\n\n/**\n * Gather each graph ancestor's latest saved step-test so the incoming-state\n * control can offer it as a seed. **One implementation**, mounted by every\n * surface — the step editor's Test tab, the canvas ▶ Run collect form, and the\n * add-step builder's Test tab — so the `gate_1 · succeeded` chip behaves\n * identically on each.\n *\n * Driven by `upstreamSteps` (from `upstreamStateSources` /\n * `stepBuilderUpstreamSteps`), not a re-walked graph. Keyed on the *set* of\n * upstream ids rather than the array's identity: that array is rebuilt on\n * every node drag and every field edit, so keying on it would refetch on each\n * keystroke.\n */\nexport function useSeedSources(\n workflowId: string,\n upstreamSteps: ExpressionStepSource[],\n enabled: boolean,\n): SeedSource[] {\n const api = useW6WApi();\n const [seedSources, setSeedSources] = useState<SeedSource[]>([]);\n const idsKey = JSON.stringify(upstreamSteps.map((s) => [s.id, s.label]));\n useEffect(() => {\n const ids = JSON.parse(idsKey) as [string, string][];\n if (!enabled || ids.length === 0) {\n setSeedSources([]);\n return;\n }\n let canceled = false;\n fetchSeedSources(\n (stepId) => api.listStepTests(workflowId, stepId),\n ids.map(([id, label]) => ({ id, label })),\n ).then((seeds) => {\n if (!canceled) setSeedSources(seeds);\n });\n return () => {\n canceled = true;\n };\n }, [api, workflowId, idsKey, enabled]);\n return seedSources;\n}\n","import {\n type ReactNode,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport { AddConnectionModal } from \"./AddConnectionModal.tsx\";\nimport { AppPicker } from \"./AppPicker.tsx\";\nimport { JsonEditor } from \"./JsonEditor.tsx\";\nimport { type NodeConfig, NodeConfigForm } from \"./NodeConfigForm.tsx\";\nimport { ParamsForm, flattenParams, isParamVisible } from \"./ParamsForm.tsx\";\nimport { TriggerFillForm } from \"./TriggerFillForm.tsx\";\nimport { WaitEditor } from \"./WaitEditor.tsx\";\nimport { mergeResolvedApps, nextIdBatch } from \"./app-pages.ts\";\nimport { AppIcon } from \"./components/AppIcon.tsx\";\nimport { Combobox } from \"./components/Combobox.tsx\";\nimport type { ExpressionStepSource } from \"./components/ExpressionOptions.tsx\";\nimport { Icon } from \"./components/Icon.tsx\";\nimport { InternalIcon } from \"./components/InternalIcon.tsx\";\nimport { Modal } from \"./components/Modal.tsx\";\nimport type { IconName } from \"./components/icons.tsx\";\nimport {\n CALL_APP,\n DATA_APP,\n INTERNAL_NODES,\n type InternalNodeDef,\n internalNodeDefaults,\n isControlApp,\n isInternalApp,\n isTriggerApp,\n} from \"./flow-types.ts\";\nimport { paramsToJson, stepToJson } from \"./flow-utils.ts\";\nimport { type StepMeta, type StepStartState, useW6WApi, useWorkflowProject } from \"./provider.tsx\";\nimport { startStateFromSeeds } from \"./step-preview-state.ts\";\nimport type {\n ActionDef,\n ActionParam,\n AppSummary,\n AuthDef,\n ConnectionSummary,\n FunctionSummary,\n ThemeMode,\n TriggerSummary,\n WorkflowDetail,\n WorkflowSummary,\n} from \"./types.ts\";\nimport { useSeedSources } from \"./use-seed-sources.ts\";\n\n/** The step the builder emits — the editor assigns the final `id`. `NodeConfig`\n * carries the base settings (retry / onError / notes) set on the Config view. */\nexport interface BuiltStep extends NodeConfig {\n uses: { app: string; action: string; connection?: string | null };\n with?: Record<string, unknown>;\n}\n\nexport interface StepBuilderModalProps {\n onClose: () => void;\n /**\n * Fired once per session, the moment the step first has identity — for an\n * app step, when Setup completes (action + connection, if needed); for a\n * control node, on mount. Returns the minted step id so subsequent edits can\n * target it via {@link StepBuilderModalProps.onDraftChange}.\n */\n // biome-ignore lint/suspicious/noConfusingVoidType: widened so studio's void-returning callers stay assignable.\n onAdd: (step: BuiltStep) => string | undefined | void;\n /**\n * Fired for every field change **after** the step has been committed via\n * `onAdd` — keeps the already-added node current without minting a second\n * one. `id` is the id `onAdd` returned. Progressive commit (mint-then-update)\n * only engages when this is supplied; omitted callers (the Functions/\n * Endpoints pickers) keep the original one-shot \"Add step\" behavior.\n */\n onDraftChange?: (id: string, step: BuiltStep) => void;\n theme?: ThemeMode;\n /**\n * Hide the GRAPH-ONLY tabs — Triggers / Controls / Utilities / Data, the\n * flow-control and internal `@w6w/*` node kinds that only mean something\n * inside a workflow canvas. Used by every picker that binds a *target*\n * rather than adding a node to a graph.\n *\n * ⚠️ It does NOT hide Functions and Workflows, and did not always behave\n * that way: it used to, which is why the Implementation card's picker\n * showed only `Connected apps / Apps / AI` and F-2.0's tabs were\n * unreachable outside the canvas. A Function and a Workflow are *callable\n * targets*, not graph-only node kinds — they belong in every picker.\n * {@link StepBuilderModalProps.callables} is the knob for those two.\n */\n appsOnly?: boolean;\n /**\n * Which callable families the Functions/Workflows tabs offer. Defaults to\n * BOTH, so a caller that says nothing keeps the full F-2.0 homepage\n * (`Connected apps | Functions | Workflows`). Pass a narrower array — or\n * `[]` — where the surrounding contract cannot accept one of them.\n */\n callables?: readonly (\"function\" | \"workflow\")[];\n /**\n * Which homepage tab opens first. Defaults to `\"connected\"` — F-2.0's\n * homepage. A caller re-opening the picker for an already-bound target\n * passes that target's own family, so \"Change\" lands where the current\n * value lives instead of making the author re-find the tab.\n */\n initialTab?: \"connected\" | \"functions\" | \"workflows\";\n\n /** Modal heading. Defaults to \"Add a step\". */\n title?: string;\n /**\n * Workflow-step context, when the builder is opened for a step that already\n * lives in a workflow. When present the `testRequired` save-gate can discover a\n * previously-saved **passing** test for the step via {@link W6WApi.listStepTests}.\n * Absent in the plain add-step flow (the step has no id yet) — there the gate is\n * satisfied by running a passing test in-session.\n */\n workflowId?: string;\n /** Step id paired with {@link StepBuilderModalProps.workflowId}. */\n stepId?: string;\n /**\n * The new step's known graph ancestors, when the builder is opened from the\n * workflow canvas (`stepBuilderUpstreamSteps`, derived from the connection\n * drag that opened it). Threaded into the Test tab's `<StepTestRun>` the same\n * way `StepEditModal` seeds an existing step's Test tab, so a `with` block\n * written as `{{ steps.<id>.output.<field> }}` resolves instead of coming\n * back empty. Absent (defaults to `[]`) for the Functions/Endpoints pickers,\n * which have no graph to draw ancestors from.\n */\n upstreamSteps?: ExpressionStepSource[];\n /**\n * Pre-select an app when the modal opens. When provided along with\n * initialAction/initialConnection/initialWith, the modal opens directly\n * to the action configuration view instead of the app picker.\n * Used when editing an existing action (e.g., clicking \"Change\" on an\n * Endpoint's already-configured target).\n */\n initialApp?: AppSummary;\n /**\n * Pre-select an action key. Requires initialApp to be set.\n */\n initialAction?: string;\n /**\n * Pre-select a connection. Requires initialApp and initialAction.\n */\n initialConnection?: string;\n /**\n * Pre-fill the action's parameter values. Requires initialApp and initialAction.\n */\n initialWith?: Record<string, unknown>;\n /**\n * Narrow which apps a scoped caller may pick, everywhere an app list is\n * computed — the \"Apps\" tab's grid, the \"AI\" tab's composed filter, and\n * {@link StepBuilderModalProps.callables}'s \"Ready to use\" tab. An\n * `undefined` filter is a no-op; every existing caller (none of which sets\n * this) is unaffected.\n *\n * On \"Ready to use\", an app built from a connection's inline `app` meta\n * carries only `id` plus those meta keys (`displayName`, icons, brand\n * colours) — no `version` or `categories` — so the filter sees just those,\n * and the selected-app header omits the ` · v<version>` suffix for it.\n */\n appsFilter?: (app: AppSummary) => boolean;\n /**\n * Stop at \"a connection is chosen\" — no Action, no Configure/Test. Renders\n * {@link AppConnectionOnlyConfig} in place of the usual `AppStepConfig`\n * once an app is picked. Used by a caller that only needs a connection\n * (e.g. binding a repository), not a runnable step.\n */\n connectionOnly?: boolean;\n /**\n * Fired once, on {@link AppConnectionOnlyConfig}'s footer button — never on\n * selection alone. Only meaningful with {@link StepBuilderModalProps.connectionOnly}.\n */\n onConnected?: (connectionId: string, app: AppSummary) => void;\n}\n\n/** {@link StepBuilderModalProps.callables}'s default — both families. Module\n * scope so the default is one shared frozen array, never a fresh literal per\n * render (it lands in a `useEffect`-free read path, but a stable identity\n * keeps it honest for any future memo). */\nconst CALLABLE_FAMILIES = [\"function\", \"workflow\"] as const;\n\n/** Row glyphs for the home tab's non-app entries, in `InternalIcon`'s\n * stroked-24-viewBox idiom so a Function/Workflow row sits on the same tile\n * an app row's icon does. Feather `git-branch` for a Workflow (it is a graph)\n * and `zap` for a Function (one operation, immediate). */\nconst CALLABLE_GLYPH: Record<\"function\" | \"workflow\", string> = {\n workflow:\n '<line x1=\"6\" y1=\"3\" x2=\"6\" y2=\"15\"/><circle cx=\"18\" cy=\"6\" r=\"3\"/><circle cx=\"6\" cy=\"18\" r=\"3\"/><path d=\"M18 9a9 9 0 0 1-9 9\"/>',\n function: '<polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"/>',\n};\n\ntype Tab =\n | \"connected\"\n | \"functions\"\n | \"workflows\"\n | \"apps\"\n | \"ai\"\n | \"triggers\"\n | \"controls\"\n | \"utilities\"\n | \"data\";\n\n/** Config sub-tabs shared by the add-step config and the node editor. */\ntype StepConfigTab = \"setup\" | \"configure\" | \"test\";\n\n/** The four representations of the Configure tab: form, full-step JSON,\n * params-only JSON, node settings. */\nexport type ConfigView = \"props\" | \"code\" | \"params-code\" | \"config\";\n\n/** The glyph + accessible label each view is drawn with. Every glyph is a named\n * entry of the shared set (`components/icons.tsx`), drawn at 15px like the\n * editor's toolbar glyphs. `props`/`code` read as \"the step, as a form\" vs \"the\n * step, as code\"; `braces` (square braces, NOT `code`'s chevrons) reads as \"the\n * params, as a value\" — distinct at a glance from the pair above it. */\nconst CONFIG_VIEW_GLYPHS: Record<ConfigView, { label: string; icon: IconName }> = {\n props: { label: \"Form\", icon: \"form\" },\n code: { label: \"JSON\", icon: \"code\" },\n \"params-code\": { label: \"Params JSON\", icon: \"braces\" },\n config: { label: \"Node settings\", icon: \"settings-2\" },\n};\n\n/** Every view, in the order the editor's tabs bar has always shown them. */\nconst ALL_CONFIG_VIEWS: ConfigView[] = [\"props\", \"code\", \"params-code\", \"config\"];\n\n/**\n * The props / code / params-code / config view toggle, right-aligned in the\n * tabs bar. Disabled off the Configure tab (all four views represent the\n * action's config).\n *\n * `views` narrows it to a subset, in the order given — a fields ⇄ raw-JSON\n * property form (see `PropertyEntryForm`) passes `[\"props\", \"code\"]`. There is\n * deliberately no second toggle component: one glyph set, one styling, one\n * pressed-state behaviour, however many views a host offers.\n */\nexport function ConfigViewToggle({\n view,\n onChange,\n disabled,\n views = ALL_CONFIG_VIEWS,\n}: {\n view: ConfigView;\n onChange: (v: ConfigView) => void;\n disabled?: boolean;\n /** Which views to offer, in order. Defaults to all four. */\n views?: ConfigView[];\n}) {\n const btn = (v: ConfigView) => (\n <button\n key={v}\n type=\"button\"\n title={CONFIG_VIEW_GLYPHS[v].label}\n aria-label={CONFIG_VIEW_GLYPHS[v].label}\n aria-pressed={view === v}\n disabled={disabled}\n className={`w6w-icon-btn${view === v && !disabled ? \" active\" : \"\"}`}\n onClick={() => onChange(v)}\n >\n <Icon name={CONFIG_VIEW_GLYPHS[v].icon} size={15} />\n </button>\n );\n return <div className=\"w6w-view-toggle\">{views.map(btn)}</div>;\n}\n\n/**\n * Guided \"add a step\" flow. A sidebar toggles between **Apps** (pick app →\n * ensure a connection → pick action → fill params) and **Controls** — the\n * internal nodes: triggers, flow control (if/foreach/parallel/wait), and compute\n * (script/data). Emits a `BuiltStep` via `onAdd`.\n *\n * Data + IO come from `useW6WApi()`, so mount it under `<W6WUIProvider>`.\n */\nexport function StepBuilderModal({\n onClose,\n onAdd,\n onDraftChange,\n theme,\n appsOnly,\n callables = CALLABLE_FAMILIES,\n initialTab,\n title,\n workflowId,\n stepId,\n upstreamSteps = [],\n initialApp,\n initialAction,\n initialConnection,\n initialWith,\n appsFilter,\n connectionOnly,\n onConnected,\n}: StepBuilderModalProps) {\n // Default to the apps the user already connected — no searching for the one\n // integration they use every day.\n const [tab, setTab] = useState<Tab>(initialTab ?? \"connected\");\n // When an app is selected the modal collapses to a single-app detail view:\n // the sidebar is hidden and the header switches to the app's name + icon.\n // Initialize with initialApp if provided to skip the app picker.\n const [selectedApp, setSelectedApp] = useState<AppSummary | null>(initialApp ?? null);\n // Same collapse for a chosen internal node (trigger / control / compute) — its\n // config form (dynamic ParamsForm over the node's schema) shows before adding.\n const [selectedNode, setSelectedNode] = useState<InternalNodeDef | null>(null);\n // Same collapse for a picked Function/Workflow target (D-12/D-15): both tabs\n // mint the SAME `@w6w/call` step shape, so one piece of state (family + id +\n // label) is enough — `CallableStepConfig` decides what to call from `family`.\n const [selectedCallable, setSelectedCallable] = useState<{\n family: \"function\" | \"workflow\";\n id: string;\n label: string;\n } | null>(null);\n\n // The home tab's contents, fetched here rather than inside the tab, because\n // whether the TAB EXISTS depends on them: nothing connected and nothing\n // built ⇒ no \"Ready to use\" tab at all. Still `\"loading\"` counts as present,\n // so the sidebar does not shuffle a beat after it renders.\n const readyToUse = useReadyToUse(callables, appsFilter);\n const homeAvailable = readyToUse.state !== \"empty\";\n // If the home tab vanishes while it is the open one, fall to the catalogue\n // rather than rendering a tab body with no tab.\n useEffect(() => {\n if (!homeAvailable && tab === \"connected\") setTab(\"apps\");\n }, [homeAvailable, tab]);\n\n if (selectedCallable) {\n return (\n <Modal\n title={selectedCallable.label}\n subtitle={<code>{selectedCallable.id}</code>}\n onClose={onClose}\n size=\"xl\"\n headerRight={\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n onClick={() => setSelectedCallable(null)}\n >\n ← Back\n </button>\n }\n >\n <div className=\"w6w-stepbuilder-config\">\n <CallableStepConfig\n family={selectedCallable.family}\n targetId={selectedCallable.id}\n targetLabel={selectedCallable.label}\n onAdd={onAdd}\n onClose={onClose}\n onDraftChange={onDraftChange}\n />\n </div>\n </Modal>\n );\n }\n\n if (selectedNode) {\n return (\n <Modal\n title={selectedNode.label}\n titleIcon={<InternalIcon icon={selectedNode.icon} size={22} />}\n subtitle={\n <code>\n {selectedNode.app} · {selectedNode.action}\n </code>\n }\n onClose={onClose}\n size=\"xl\"\n headerRight={\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n onClick={() => setSelectedNode(null)}\n >\n ← Back\n </button>\n }\n >\n <div className=\"w6w-stepbuilder-config\">\n <ControlStepConfig\n node={selectedNode}\n onAdd={onAdd}\n onClose={onClose}\n onDraftChange={onDraftChange}\n workflowId={workflowId}\n upstreamSteps={upstreamSteps}\n />\n </div>\n </Modal>\n );\n }\n\n if (selectedApp) {\n return (\n <Modal\n title={selectedApp.displayName}\n subtitle={\n <>\n <code>{selectedApp.id}</code>\n {selectedApp.version && ` · v${selectedApp.version}`}\n </>\n }\n onClose={onClose}\n size=\"xl\"\n titleIcon={\n <AppIcon\n src={selectedApp.iconSvg}\n srcDark={selectedApp.iconSvgDark}\n brandColor={selectedApp.brandColor}\n name={selectedApp.displayName}\n theme={theme}\n size={22}\n />\n }\n >\n <div className=\"w6w-stepbuilder-config\">\n {/* App-switching lives in the Setup tab's \"Change\" (à la Zapier), not a\n top-right back button. */}\n {connectionOnly ? (\n <AppConnectionOnlyConfig\n appId={selectedApp.id}\n app={selectedApp}\n onClose={onClose}\n onChangeApp={() => setSelectedApp(null)}\n theme={theme}\n initialConnection={initialConnection}\n onConnected={(connectionId, app) => onConnected?.(connectionId, app)}\n />\n ) : (\n <AppStepConfig\n appId={selectedApp.id}\n app={selectedApp}\n onAdd={onAdd}\n onClose={onClose}\n onDraftChange={onDraftChange}\n onChangeApp={() => setSelectedApp(null)}\n theme={theme}\n workflowId={workflowId}\n stepId={stepId}\n upstreamSteps={upstreamSteps}\n initialAction={initialAction}\n initialConnection={initialConnection}\n initialWith={initialWith}\n />\n )}\n </div>\n </Modal>\n );\n }\n\n return (\n <Modal title={title ?? \"Add a step\"} onClose={onClose} size=\"xl\">\n <div className=\"w6w-stepbuilder\">\n <nav className=\"w6w-stepbuilder-sidebar\">\n {/* F-2.0's homepage, and the order it asks for:\n Ready to use · Apps · AI · Workflows · Functions\n The home tab is ONE list holding connected apps + Workflows +\n Functions (see `ReadyToUseFlow`); the four after it are the\n browse-everything tabs. `callables` still narrows the two\n callable tabs — and the home list with them — for a call site\n whose contract cannot accept one of the families. */}\n {homeAvailable && (\n <button\n type=\"button\"\n className={`w6w-stepbuilder-tab${tab === \"connected\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"connected\")}\n >\n Ready to use\n </button>\n )}\n <button\n type=\"button\"\n className={`w6w-stepbuilder-tab${tab === \"apps\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"apps\")}\n >\n Apps\n </button>\n <button\n type=\"button\"\n className={`w6w-stepbuilder-tab${tab === \"ai\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"ai\")}\n >\n AI\n </button>\n {callables.includes(\"workflow\") && (\n <button\n type=\"button\"\n className={`w6w-stepbuilder-tab${tab === \"workflows\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"workflows\")}\n >\n Workflows\n </button>\n )}\n {callables.includes(\"function\") && (\n <button\n type=\"button\"\n className={`w6w-stepbuilder-tab${tab === \"functions\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"functions\")}\n >\n Functions\n </button>\n )}\n {!appsOnly && (\n <>\n <button\n type=\"button\"\n className={`w6w-stepbuilder-tab${tab === \"triggers\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"triggers\")}\n >\n Triggers\n </button>\n <button\n type=\"button\"\n className={`w6w-stepbuilder-tab${tab === \"controls\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"controls\")}\n >\n Controls\n </button>\n <button\n type=\"button\"\n className={`w6w-stepbuilder-tab${tab === \"utilities\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"utilities\")}\n >\n Utilities\n </button>\n <button\n type=\"button\"\n className={`w6w-stepbuilder-tab${tab === \"data\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"data\")}\n >\n Data\n </button>\n </>\n )}\n </nav>\n <div className=\"w6w-stepbuilder-content\">\n {tab === \"connected\" ? (\n <ReadyToUseFlow\n data={readyToUse}\n onSelectApp={setSelectedApp}\n onSelectCallable={setSelectedCallable}\n theme={theme}\n />\n ) : tab === \"functions\" ? (\n <CallableList\n family=\"function\"\n onSelect={(t) => setSelectedCallable({ family: \"function\", ...t })}\n />\n ) : tab === \"workflows\" ? (\n <CallableList\n family=\"workflow\"\n onSelect={(t) => setSelectedCallable({ family: \"workflow\", ...t })}\n />\n ) : tab === \"apps\" ? (\n <AppPicker onSelectApp={setSelectedApp} theme={theme} filter={appsFilter} />\n ) : tab === \"ai\" ? (\n <AppPicker\n onSelectApp={setSelectedApp}\n theme={theme}\n // `category=\"ai\"` reaches the server on the bounded paged path\n // (A2); `filter` is the client-side backstop every mode still\n // applies — the only path that needs it end-to-end is a legacy\n // `listApps()`-only host, which never sees `category` at all.\n category=\"ai\"\n filter={(a) => (appsFilter?.(a) ?? true) && (a.categories?.includes(\"ai\") ?? false)}\n searchPlaceholder=\"Search AI apps…\"\n emptyMessage=\"No AI apps registered yet.\"\n />\n ) : tab === \"triggers\" ? (\n <TriggersFlow onSelect={setSelectedNode} workflowId={workflowId} onClose={onClose} />\n ) : tab === \"controls\" ? (\n <ControlsFlow onSelect={setSelectedNode} />\n ) : tab === \"data\" ? (\n <DataFlow onSelect={setSelectedNode} />\n ) : (\n <UtilitiesFlow onSelect={setSelectedNode} />\n )}\n </div>\n </div>\n </Modal>\n );\n}\n\n// ── Internal nodes tab (triggers, flow control, compute) ───────────────────\n\n/** A flat, clickable list of internal nodes. Shared by Controls + Utilities. */\nfunction NodeList({\n nodes,\n onSelect,\n}: {\n nodes: InternalNodeDef[];\n onSelect: (node: InternalNodeDef) => void;\n}) {\n return (\n <div className=\"w6w-stepbuilder-list\">\n {nodes.map((n) => (\n <button\n key={`${n.app}:${n.action}`}\n type=\"button\"\n className=\"w6w-stepbuilder-item\"\n onClick={() => onSelect(n)}\n >\n <InternalIcon icon={n.icon} size={24} />\n <span className=\"w6w-stepbuilder-item-main\">\n <strong>{n.label}</strong>\n <code className=\"w6w-muted w6w-small\">\n {n.app} · {n.action}\n </code>\n </span>\n </button>\n ))}\n </div>\n );\n}\n\n/**\n * Triggers tab — entry nodes that start a workflow (manual, webhook, …), plus\n * (T-0) an \"App triggers\" section listing apps that declare their own\n * triggers (RFC `trigger.md`). The internal 3 keep their existing `onSelect`\n * → `onAdd` graph-node behaviour, untouched; the app section is a SEPARATE,\n * non-graph mechanism (DECISIONS.md HITL-1, plan.md D-3) — selecting an app\n * trigger never calls `onAdd`.\n */\nfunction TriggersFlow({\n onSelect,\n workflowId,\n onClose,\n}: {\n onSelect: (node: InternalNodeDef) => void;\n workflowId?: string;\n onClose: () => void;\n}) {\n const nodes = INTERNAL_NODES.filter((n) => n.group === \"trigger\");\n const api = useW6WApi();\n return (\n <div className=\"w6w-stack\">\n <p className=\"w6w-muted w6w-small\">\n Triggers start a workflow — run it manually or on an inbound webhook.\n </p>\n <NodeList nodes={nodes} onSelect={onSelect} />\n {/* Gated on BOTH workflowId (this builder is opened for a real workflow —\n * a Subscription needs a workflow to bind to) and the optional member\n * itself. `test/picker-layout`'s I5/I6 mount with no `workflowId` even\n * though its stub `api` answers every key truthy — this second gate is\n * exactly why that suite stays unaffected (see the contract's test plan). */}\n {workflowId && api.listTriggerApps && (\n <AppTriggersSection workflowId={workflowId} onClose={onClose} />\n )}\n </div>\n );\n}\n\n/**\n * `AppSummary.triggerCount` is declared on the SDK/wire type\n * (`@w6w/sdk/console`'s `AppSummary`) but not on this package's own\n * `types.ts` (`ui/src/types.ts`, read-only reuse site per this task's\n * contract) — accessed defensively rather than widening that shared type.\n */\nfunction hasDeclaredTriggers(a: AppSummary): boolean {\n return ((a as { triggerCount?: number }).triggerCount ?? 0) > 0;\n}\n\n/**\n * \"App triggers\" section (T-0): apps that declare triggers, then — once one\n * is picked — that app's declared triggers (`api.getAppTriggers`). Choosing a\n * trigger calls `api.createSubscription` on an explicit click only; no graph\n * step is added (plan.md D-3 — `onAdd` is never reached from this section).\n *\n * **Bounded when the host implements `listAppsPage`** (A2/C3): delegates\n * straight to `AppPicker`'s own paged mode (no `apps` prop, so AppPicker runs\n * its own bounded fetch/search/load-more/cancellation) with a client-side\n * `triggerCount > 0` filter — there is no server-side trigger-only filter, so\n * pages legitimately without SEE trigger apps stay reachable via search/load\n * more rather than being auto-drained. Falls back to the legacy\n * `api.listTriggerApps()` eager fetch, unchanged, for a host that has not\n * (yet) implemented the bounded seam.\n */\nfunction AppTriggersSection({ workflowId, onClose }: { workflowId: string; onClose: () => void }) {\n const api = useW6WApi();\n const bounded = typeof api.listAppsPage === \"function\";\n const [legacyApps, setLegacyApps] = useState<AppSummary[] | null>(null);\n const [legacyError, setLegacyError] = useState<string | null>(null);\n const [selectedApp, setSelectedApp] = useState<AppSummary | null>(null);\n\n useEffect(() => {\n if (bounded) return;\n const load = api.listTriggerApps;\n if (!load) return;\n let canceled = false;\n load()\n .then((r) => !canceled && setLegacyApps(r))\n .catch((e) => !canceled && setLegacyError((e as Error).message));\n return () => {\n canceled = true;\n };\n }, [api, bounded]);\n\n if (!bounded && !api.listTriggerApps) return null;\n\n return (\n <div className=\"w6w-stack\">\n <p className=\"w6w-muted w6w-small\">\n <strong>App triggers</strong> — bind one of these apps' declared triggers to this workflow.\n </p>\n {selectedApp ? (\n <AppTriggerPicker\n app={selectedApp}\n workflowId={workflowId}\n onBack={() => setSelectedApp(null)}\n onClose={onClose}\n />\n ) : bounded ? (\n <AppPicker\n onSelectApp={setSelectedApp}\n filter={hasDeclaredTriggers}\n search\n searchPlaceholder=\"Search apps with triggers…\"\n emptyMessage=\"No apps declare triggers yet.\"\n />\n ) : legacyError ? (\n <div className=\"w6w-result w6w-error\">{legacyError}</div>\n ) : (\n <AppPicker\n apps={legacyApps}\n onSelectApp={setSelectedApp}\n search={false}\n emptyMessage=\"No apps declare triggers yet.\"\n />\n )}\n </div>\n );\n}\n\n/**\n * One app's declared triggers, once picked in {@link AppTriggersSection} — a\n * chooser when the app declares triggers, an explicit \"declares no triggers\"\n * message when it doesn't (mirrors `SubscriptionsPage.tsx`'s\n * `TriggerKeyField`, minus its free-text fallback: a trigger key the app\n * doesn't declare is a `404 unknown_trigger` here, so there is nothing useful\n * a free-text arm could submit).\n */\nfunction AppTriggerPicker({\n app,\n workflowId,\n onBack,\n onClose,\n}: {\n app: AppSummary;\n workflowId: string;\n onBack: () => void;\n onClose: () => void;\n}) {\n const api = useW6WApi();\n const [triggers, setTriggers] = useState<TriggerSummary[] | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [creating, setCreating] = useState(false);\n // A poll trigger waits here for its \"Check every N minutes\" before it is created.\n const [pending, setPending] = useState<TriggerSummary | null>(null);\n // Raw text while editing — clamped to the trigger's minimum only on blur / confirm.\n const [minutes, setMinutes] = useState(\"5\");\n\n useEffect(() => {\n const load = api.getAppTriggers;\n if (!load) return;\n let canceled = false;\n load(app.id)\n .then((r) => !canceled && setTriggers(r))\n .catch((e) => !canceled && setError((e as Error).message));\n return () => {\n canceled = true;\n };\n }, [api, app.id]);\n\n const minMinutes = (t: TriggerSummary) => Math.max(1, Math.ceil((t.minIntervalMs ?? 0) / 60000));\n\n const pick = (t: TriggerSummary) => {\n if (t.type !== \"poll\") return create(t.key);\n setError(null);\n setPending(t);\n setMinutes(String(Math.max(5, Math.ceil((t.minIntervalMs ?? 0) / 60000))));\n };\n\n const create = (triggerKey: string, intervalMs?: number) => {\n const createSubscription = api.createSubscription;\n if (!createSubscription) return;\n setError(null);\n setCreating(true);\n createSubscription(app.id, triggerKey, {\n workflowId,\n connectionId: null,\n params: {},\n ...(intervalMs === undefined ? {} : { intervalMs }),\n })\n .then(() => onClose())\n .catch((e) => {\n setCreating(false);\n setError(e instanceof Error ? e.message : String(e));\n });\n };\n\n return (\n <div className=\"w6w-stack\">\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\" onClick={onBack}>\n ← Back\n </button>\n <strong>{app.displayName}</strong>\n {error && <div className=\"w6w-result w6w-error\">{error}</div>}\n {triggers === null ? (\n <p className=\"w6w-muted w6w-small\">Loading triggers…</p>\n ) : triggers.length === 0 ? (\n <p className=\"w6w-muted w6w-small\">This app declares no triggers.</p>\n ) : (\n <div className=\"w6w-stepbuilder-list\">\n {triggers.map((t) => (\n <button\n key={t.key}\n type=\"button\"\n className=\"w6w-stepbuilder-item\"\n disabled={creating}\n onClick={() => pick(t)}\n >\n <span className=\"w6w-stepbuilder-item-main\">\n <strong>{t.title}</strong>\n <code className=\"w6w-muted w6w-small\">{t.key}</code>\n {t.description && <span className=\"w6w-muted w6w-small\">{t.description}</span>}\n </span>\n </button>\n ))}\n </div>\n )}\n {pending && (\n <div className=\"w6w-stack\">\n <label className=\"w6w-field\">\n <span>Check every … minutes</span>\n <input\n type=\"number\"\n min={minMinutes(pending)}\n step={1}\n value={minutes}\n disabled={creating}\n onChange={(e) => setMinutes(e.target.value)}\n onBlur={() => setMinutes(String(clampMinutes(minutes, minMinutes(pending))))}\n />\n </label>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-primary w6w-btn-sm\"\n disabled={creating}\n onClick={() => create(pending.key, clampMinutes(minutes, minMinutes(pending)) * 60000)}\n >\n Add trigger\n </button>\n </div>\n )}\n </div>\n );\n}\n\n/** Controls tab — engine-native flow control only (branch, loop, parallelize, wait). */\nfunction ControlsFlow({ onSelect }: { onSelect: (node: InternalNodeDef) => void }) {\n const nodes = INTERNAL_NODES.filter((n) => n.group === \"control\" && !n.hidden);\n return (\n <div className=\"w6w-stack\">\n <p className=\"w6w-muted w6w-small\">\n Flow-control nodes branch, loop, parallelize, or pause the run.\n </p>\n <NodeList nodes={nodes} onSelect={onSelect} />\n </div>\n );\n}\n\n/** Utilities tab — compute + request nodes (script, HTTP, respond). The `@w6w/data`\n * node lives in its own **Data** tab, so exclude it here. */\nfunction UtilitiesFlow({ onSelect }: { onSelect: (node: InternalNodeDef) => void }) {\n const nodes = INTERNAL_NODES.filter(\n (n) => n.group !== \"control\" && n.group !== \"trigger\" && n.app !== DATA_APP && !n.hidden,\n );\n return (\n <div className=\"w6w-stack\">\n <p className=\"w6w-muted w6w-small\">\n Utilities run a script, call an HTTP(S) endpoint, or respond to a webhook.\n </p>\n <NodeList nodes={nodes} onSelect={onSelect} />\n </div>\n );\n}\n\n/** Data tab — the `@w6w/data` node: declare typed key/value variables for\n * downstream steps to reference. */\nfunction DataFlow({ onSelect }: { onSelect: (node: InternalNodeDef) => void }) {\n const nodes = INTERNAL_NODES.filter((n) => n.app === DATA_APP);\n return (\n <div className=\"w6w-stack\">\n <p className=\"w6w-muted w6w-small\">\n Declare typed key/value variables for downstream steps to reference.\n </p>\n <NodeList nodes={nodes} onSelect={onSelect} />\n </div>\n );\n}\n\n/**\n * Config form for a chosen internal node — its schema rendered through the same\n * `ParamsForm` as app actions, seeded with the node's defaults. Emits the built\n * step on Add.\n */\nexport function ControlStepConfig({\n node,\n onAdd,\n onClose,\n onDraftChange,\n workflowId,\n upstreamSteps = [],\n}: {\n node: InternalNodeDef;\n // biome-ignore lint/suspicious/noConfusingVoidType: see StepBuilderModalProps.onAdd, forwarded as-is.\n onAdd: (s: BuiltStep) => string | undefined | void;\n onClose: () => void;\n /** See {@link StepBuilderModalProps.onDraftChange}. */\n onDraftChange?: (id: string, step: BuiltStep) => void;\n workflowId?: string;\n /** The new step's known graph ancestors — see {@link StepBuilderModalProps.upstreamSteps}. */\n upstreamSteps?: ExpressionStepSource[];\n}) {\n const [withValues, setWithValues] = useState<Record<string, unknown>>(() =>\n internalNodeDefaults(node.app, node.action),\n );\n // Internal nodes have no connection/action to pick, so there's no Setup tab —\n // just Configure + Test (flow-control nodes aren't testable standalone).\n const testable = !isControlApp(node.app);\n // The step-being-added's graph ancestors that carry a saved step-test, offered\n // as one-click seeds for the incoming state — the SAME pipeline `StepEditModal`\n // uses, so the Test tab here resolves `{{ steps.<id>.output.<field> }}` the\n // same way an existing step's Test tab does (T1.1.1). Only meaningful when the\n // builder was opened from a workflow canvas (`workflowId` present); the\n // Functions/Endpoints pickers pass no `workflowId` and no `upstreamSteps`.\n const seedSources = useSeedSources(workflowId ?? \"\", upstreamSteps, testable && !!workflowId);\n const testStartState = startStateFromSeeds(seedSources);\n const [tab, setTab] = useState<\"configure\" | \"test\">(\"configure\");\n const [configView, setConfigView] = useState<ConfigView>(\"props\");\n // Draft text backing the \"code\" (full-step, read-only) view.\n const [codeText, setCodeText] = useState(\"{}\");\n // Draft text backing the \"params-code\" (params-only, writable) view.\n const [paramsCodeText, setParamsCodeText] = useState(\"{}\");\n const [draftConfig, setDraftConfig] = useState<NodeConfig>({});\n const configComplete = requiredParamsFilled(node.params, withValues);\n\n // The id `onAdd` minted at commit time, once a control node's identity has\n // been committed to the graph this session. `null` until then (and forever,\n // for a caller that doesn't supply `onDraftChange` — the original one-shot\n // \"Add step\" behavior).\n const [committedId, setCommittedId] = useState<string | null>(null);\n const buildStep = (): BuiltStep => ({\n uses: { app: node.app, action: node.action },\n with: withValues,\n ...draftConfig,\n });\n\n // Mint — a control node has identity the instant it's picked (no Setup tab),\n // so commit it to the graph on mount, exactly once.\n // biome-ignore lint/correctness/useExhaustiveDependencies: mint fires once on mount only; buildStep/onAdd intentionally read fresh closure state without retriggering this effect.\n useEffect(() => {\n if (!onDraftChange) return;\n const id = onAdd(buildStep());\n if (id) setCommittedId(id);\n }, []);\n\n // Update — keep the already-committed node current on every subsequent field\n // change, instead of minting a duplicate via a second `onAdd` call.\n // biome-ignore lint/correctness/useExhaustiveDependencies: buildStep reads fresh closure state; only these fields should retrigger the update.\n useEffect(() => {\n if (!onDraftChange || committedId === null) return;\n onDraftChange(committedId, buildStep());\n }, [committedId, withValues, draftConfig]);\n\n const changeConfigView = (v: ConfigView) => {\n if (v === \"code\") setCodeText(stepToJson(buildStep()));\n else if (v === \"params-code\") setParamsCodeText(paramsToJson(buildStep()));\n setConfigView(v);\n };\n const add = () => onAdd(buildStep());\n\n return (\n <div className=\"w6w-stepconfig\">\n <div className=\"w6w-tabsbar\">\n <div className=\"w6w-subtabs\">\n <button\n type=\"button\"\n className={`w6w-subtab${tab === \"configure\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"configure\")}\n >\n Configure\n </button>\n {testable && (\n <button\n type=\"button\"\n disabled={!configComplete}\n title={configComplete ? undefined : \"Fill the required fields first\"}\n className={`w6w-subtab${tab === \"test\" ? \" active\" : \"\"}`}\n onClick={() => configComplete && setTab(\"test\")}\n >\n Test\n </button>\n )}\n </div>\n <ConfigViewToggle\n view={configView}\n onChange={changeConfigView}\n disabled={tab !== \"configure\"}\n />\n </div>\n\n <div className=\"w6w-stepconfig-body\">\n {tab === \"configure\" &&\n (configView === \"props\" ? (\n node.action === \"wait\" && isControlApp(node.app) ? (\n <WaitEditor values={withValues} onChange={setWithValues} />\n ) : (\n <ParamsForm params={node.params} values={withValues} onChange={setWithValues} />\n )\n ) : configView === \"code\" ? (\n // Full step, read-only (D-3) — `stepToJson` is the ONE serializer,\n // shared with the two other code-view hosts.\n <JsonEditor\n value={codeText}\n onChange={() => {}}\n readOnly\n minHeight=\"240px\"\n height=\"100%\"\n aria-label=\"Step JSON\"\n copyable\n />\n ) : configView === \"params-code\" ? (\n <JsonEditor\n value={paramsCodeText}\n onChange={setParamsCodeText}\n minHeight=\"240px\"\n height=\"100%\"\n aria-label=\"Parameters JSON\"\n copyable\n onValidChange={(p) =>\n p &&\n typeof p === \"object\" &&\n !Array.isArray(p) &&\n setWithValues(p as Record<string, unknown>)\n }\n />\n ) : (\n <NodeConfigForm\n config={draftConfig}\n onChange={setDraftConfig}\n // A trigger has no failure of its own to retry or police — same\n // reason its canvas card renders no error exit port.\n failureHandling={!isTriggerApp(node.app)}\n // A `@w6w/call`/`@w6w/control` step runs no retry loop of its\n // own (core rfcs/workflow.md \"Retries come first\"; D-3).\n retryControls={!isControlApp(node.app) && node.app !== CALL_APP}\n />\n ))}\n {tab === \"test\" &&\n testable &&\n (isTriggerApp(node.app) ? (\n <TriggerFillForm app={node.app} action={node.action} fields={withValues.fields} />\n ) : (\n <StepTestRun\n app={node.app}\n action={node.action}\n values={withValues}\n canRun={configComplete}\n state={testStartState}\n />\n ))}\n </div>\n\n {/* Footer — pinned to the modal bottom, outside the scroll area. */}\n <div className=\"w6w-modal-actions w6w-stepconfig-footer\">\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={onClose}>\n Cancel\n </button>\n {tab === \"configure\" && testable ? (\n <button\n type=\"button\"\n className=\"w6w-btn\"\n disabled={!configComplete}\n onClick={() => setTab(\"test\")}\n >\n Next →\n </button>\n ) : (\n <button type=\"button\" className=\"w6w-btn\" onClick={committedId !== null ? onClose : add}>\n {committedId !== null ? \"Done\" : \"Add step\"}\n </button>\n )}\n </div>\n </div>\n );\n}\n\n// ── Functions / Workflows tabs (F-2.0, D-12/D-15) ───────────────────────────\n//\n// Both tabs mint ONE step shape — an `@w6w/call` step — so there is no\n// per-family component pair: `CallableList` (the browse-and-pick stage,\n// styled after `AppPicker.tsx`) and `CallableStepConfig` (Configure/Test/Add,\n// mirroring `ControlStepConfig`'s progressive-commit shape) both take a single\n// `family: \"function\" | \"workflow\"` prop that only decides which endpoints to\n// call and what `with.targetKind` gets stamped.\n\n/**\n * Searchable list of a family's summaries — the picker's browse-and-pick\n * stage. Mirrors `AppPicker.tsx`'s shape (search box, sorted/filtered list,\n * loading/error/empty states); a Function/Workflow summary has no\n * icon/brandColor, so each row is text-only. `onSelect` hands the picked\n * target's id + display label up to `StepBuilderModal`, which collapses into\n * `CallableStepConfig` exactly as picking an app or an internal node does.\n */\nfunction CallableList({\n family,\n onSelect,\n}: {\n family: \"function\" | \"workflow\";\n onSelect: (target: { id: string; label: string }) => void;\n}) {\n const api = useW6WApi();\n const [items, setItems] = useState<Array<FunctionSummary | WorkflowSummary> | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [query, setQuery] = useState(\"\");\n const noun = family === \"function\" ? \"Functions\" : \"Workflows\";\n\n useEffect(() => {\n let canceled = false;\n const p = family === \"function\" ? api.listFunctions() : api.listWorkflows();\n p.then((r) => !canceled && setItems(r)).catch(\n (e) => !canceled && setError((e as Error).message),\n );\n return () => {\n canceled = true;\n };\n }, [api, family]);\n\n // Single layout owner, mirroring `.w6w-apppicker-host`'s role for AppPicker\n // (I4: every render path — error/loading/empty/loaded — reports the same\n // host height, so the modal never resizes switching between them).\n const host = (body: ReactNode) => <div className=\"w6w-apppicker-host\">{body}</div>;\n\n if (error) return host(<div className=\"w6w-result w6w-error\">{error}</div>);\n if (items === null) {\n return host(<p className=\"w6w-muted w6w-small\">Loading {noun.toLowerCase()}…</p>);\n }\n if (items.length === 0) {\n return host(<p className=\"w6w-muted w6w-small\">No {noun.toLowerCase()} registered yet.</p>);\n }\n\n // The same label rule the home tab uses — one definition, so a Function is\n // named identically wherever it is listed.\n const label = callableLabel;\n const q = query.trim().toLowerCase();\n const sorted = [...items].sort(byLabel(label));\n const visible = q\n ? sorted.filter((it) => label(it).toLowerCase().includes(q) || it.id.toLowerCase().includes(q))\n : sorted;\n\n return host(\n <div className=\"w6w-stepbuilder-apps\">\n <input\n type=\"text\"\n className=\"w6w-stepbuilder-search\"\n placeholder={`Search ${noun.toLowerCase()}…`}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n aria-label={`Search ${noun.toLowerCase()}`}\n />\n {visible.length === 0 ? (\n <p className=\"w6w-muted w6w-small\">\n No {noun.toLowerCase()} match “{query}”.\n </p>\n ) : (\n <div className=\"w6w-stepbuilder-list w6w-stepbuilder-scroll\">\n {/* The SAME row component the home tab renders — same glyph, same\n tinted background. This list used to draw its own bare row, so a\n Function looked like one thing here and another there. */}\n {visible.map((it) => (\n <CallableRow key={it.id} family={family} item={it} onSelect={onSelect} />\n ))}\n </div>\n )}\n </div>,\n );\n}\n\n/**\n * A Workflow target's declared inputs, for the picker's Configure stage — the\n * entry/trigger step's own `with.fields` (core rfcs/node-types.md, the manual\n * trigger's `fields` param — see `INTERNAL_NODES`). A webhook/schedule trigger\n * declares no such fields, so this returns `[]` and the Configure stage's\n * `ParamsForm` renders empty, which is a legitimate call (no inputs to send).\n */\nconst TRIGGER_FIELD_TYPES: readonly string[] = [\"string\", \"number\", \"boolean\", \"json\"];\n\nfunction triggerFieldsOf(wf: WorkflowDetail): ActionParam[] {\n const step = wf.steps.find((s) => isTriggerApp(s.uses.app));\n const raw = step?.with?.fields;\n if (!Array.isArray(raw)) return [];\n const out: ActionParam[] = [];\n for (const item of raw) {\n if (typeof item !== \"object\" || item === null) continue;\n const rec = item as Record<string, unknown>;\n const key = typeof rec.key === \"string\" ? rec.key : \"\";\n if (!key) continue;\n const type = typeof rec.type === \"string\" ? rec.type : \"string\";\n out.push({\n key,\n label: key,\n type: (TRIGGER_FIELD_TYPES.includes(type) ? type : \"string\") as ActionParam[\"type\"],\n default: rec.default,\n required: Boolean(rec.required),\n });\n }\n return out;\n}\n\n/**\n * Config → test → add flow for a picked Function/Workflow target (D-12,\n * D-15). Mints a single `@w6w/call` step — `family` only decides which\n * summary/detail/invoke endpoints are called and what `with.targetKind` is\n * stamped; it is never two near-copies. Mirrors `ControlStepConfig`'s\n * progressive-commit shape (mint via `onAdd` the instant the target is\n * picked, then `onDraftChange` on every later change) — unlike `AppStepConfig`\n * there is no Setup tab (the target picked in `CallableList` IS the identity)\n * and no `NodeConfigForm` here: a second onError/retry form is out of scope —\n * `NodeConfigForm` is reached once the `@w6w/call` step already lives on a\n * canvas, not at add-time.\n */\nexport function CallableStepConfig({\n family,\n targetId,\n targetLabel,\n onAdd,\n onClose,\n onDraftChange,\n}: {\n family: \"function\" | \"workflow\";\n targetId: string;\n targetLabel: string;\n // biome-ignore lint/suspicious/noConfusingVoidType: see StepBuilderModalProps.onAdd, forwarded as-is.\n onAdd: (s: BuiltStep) => string | undefined | void;\n onClose: () => void;\n /** See {@link StepBuilderModalProps.onDraftChange}. */\n onDraftChange?: (id: string, step: BuiltStep) => void;\n}) {\n const api = useW6WApi();\n const [fields, setFields] = useState<ActionParam[] | null>(null);\n const [fieldsError, setFieldsError] = useState<string | null>(null);\n const [inputs, setInputs] = useState<Record<string, unknown>>({});\n const [wait, setWait] = useState(true);\n const [tab, setTab] = useState<\"configure\" | \"test\">(\"configure\");\n // The id `onAdd` minted at commit time — see `ControlStepConfig`'s identical\n // field for the progressive-commit rationale.\n const [committedId, setCommittedId] = useState<string | null>(null);\n\n // Load the target's own declared inputs (acceptance 2b's seam pin: they\n // populate the `inputs` object below, never `input` singular).\n useEffect(() => {\n let canceled = false;\n setFields(null);\n setFieldsError(null);\n const p =\n family === \"function\"\n ? api.getFunction(targetId).then((d) => d.inputs)\n : api.getWorkflow(targetId).then(triggerFieldsOf);\n p.then((f) => !canceled && setFields(f)).catch(\n (e) => !canceled && setFieldsError((e as Error).message),\n );\n return () => {\n canceled = true;\n };\n }, [api, family, targetId]);\n\n const configComplete = fields !== null && requiredParamsFilled(fields, inputs);\n\n const buildStep = (): BuiltStep => ({\n uses: { app: CALL_APP, action: \"call\" },\n with: { targetKind: family, targetId, inputs, wait },\n });\n\n // Mint — a Function/Workflow target has identity the instant it's picked,\n // exactly like ControlStepConfig's mount-time mint. `CallableStepConfig` is\n // only ever mounted for one target: `StepBuilderModal` collapses into it via\n // `selectedCallable`, and \"← Back\" unmounts this subtree entirely rather\n // than re-parenting it onto a new `targetId`.\n // biome-ignore lint/correctness/useExhaustiveDependencies: mint fires once on mount only; buildStep/onAdd intentionally read fresh closure state without retriggering this effect.\n useEffect(() => {\n if (!onDraftChange) return;\n const id = onAdd(buildStep());\n if (id) setCommittedId(id);\n }, []);\n\n // Update — keep the already-committed node current on every later change.\n // biome-ignore lint/correctness/useExhaustiveDependencies: buildStep reads fresh closure state; only these fields should retrigger the update.\n useEffect(() => {\n if (!onDraftChange || committedId === null) return;\n onDraftChange(committedId, buildStep());\n }, [committedId, inputs, wait]);\n\n const add = () => onAdd(buildStep());\n\n return (\n <div className=\"w6w-stepconfig\">\n <div className=\"w6w-tabsbar\">\n <div className=\"w6w-subtabs\">\n <button\n type=\"button\"\n className={`w6w-subtab${tab === \"configure\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"configure\")}\n >\n Configure\n </button>\n <button\n type=\"button\"\n disabled={!configComplete}\n title={configComplete ? undefined : \"Fill the required fields first\"}\n className={`w6w-subtab${tab === \"test\" ? \" active\" : \"\"}`}\n onClick={() => configComplete && setTab(\"test\")}\n >\n Test\n </button>\n </div>\n </div>\n\n <div className=\"w6w-stepconfig-body\">\n {tab === \"configure\" ? (\n <div className=\"w6w-stack\">\n {fieldsError ? (\n <div className=\"w6w-result w6w-error\">{fieldsError}</div>\n ) : fields === null ? (\n <p className=\"w6w-muted w6w-small\">Loading {targetLabel}’s inputs…</p>\n ) : fields.length === 0 ? (\n <p className=\"w6w-muted w6w-small\">\n {targetLabel} declares no inputs — it can be called as-is.\n </p>\n ) : (\n <ParamsForm params={fields} values={inputs} onChange={setInputs} />\n )}\n <label className=\"w6w-field\">\n <span>\n <input type=\"checkbox\" checked={wait} onChange={(e) => setWait(e.target.checked)} />{\" \"}\n Wait for completion\n </span>\n <span className=\"w6w-hint\">\n On: block until the sub-run finishes and expose its output. Off: return a run handle\n and continue.\n </span>\n </label>\n </div>\n ) : (\n <CallableTestRun\n family={family}\n targetId={targetId}\n inputs={inputs}\n canRun={configComplete}\n />\n )}\n </div>\n\n {/* Footer — pinned to the modal bottom, outside the scroll area. */}\n <div className=\"w6w-modal-actions w6w-stepconfig-footer\">\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={onClose}>\n Cancel\n </button>\n {tab === \"configure\" ? (\n <button\n type=\"button\"\n className=\"w6w-btn\"\n disabled={!configComplete}\n onClick={() => setTab(\"test\")}\n >\n Next →\n </button>\n ) : (\n <button type=\"button\" className=\"w6w-btn\" onClick={committedId !== null ? onClose : add}>\n {committedId !== null ? \"Done\" : \"Add step\"}\n </button>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Inline test run for a picked Function/Workflow — the picker's own Test stage\n * (D-11/D-15(c)): invokes the SAME `wait: true` path the saved step will take\n * at run time (`api.invokeFunction` / `api.runWorkflow`), never a client-side\n * poll. A Workflow's non-`terminal` result (the server's own `?wait=true`\n * timeout, a `202`) renders as \"still running\" with its `runId` — never a\n * silent no-op.\n */\nfunction CallableTestRun({\n family,\n targetId,\n inputs,\n canRun,\n}: {\n family: \"function\" | \"workflow\";\n targetId: string;\n inputs: Record<string, unknown>;\n canRun: boolean;\n}) {\n const api = useW6WApi();\n const [state, setState] = useState<\n | { status: \"running\" }\n | { status: \"done\"; output: unknown; runId?: string; terminal: boolean; error?: unknown }\n | { status: \"error\"; error: string }\n | null\n >(null);\n\n const run = async () => {\n if (!canRun || state?.status === \"running\") return;\n setState({ status: \"running\" });\n try {\n if (family === \"function\") {\n const output = await api.invokeFunction(targetId, inputs);\n setState({ status: \"done\", output, terminal: true });\n } else {\n const r = await api.runWorkflow(targetId, { input: inputs });\n setState({\n status: \"done\",\n output: r.output,\n runId: r.runId,\n terminal: r.terminal,\n error: r.error,\n });\n }\n } catch (e) {\n setState({ status: \"error\", error: (e as { message?: string }).message ?? String(e) });\n }\n };\n\n return (\n <div className=\"w6w-steptest\">\n <div className=\"w6w-steptest-bar\">\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n disabled={!canRun || state?.status === \"running\"}\n onClick={run}\n >\n {state?.status === \"running\" ? \"Running…\" : \"▶ Test run\"}\n </button>\n {!canRun && <span className=\"w6w-muted w6w-small\">Fill the required fields to test.</span>}\n </div>\n {state?.status === \"error\" && <div className=\"w6w-result w6w-error\">{state.error}</div>}\n {state?.status === \"done\" && !state.terminal && (\n <div className=\"w6w-testout\">\n <div className=\"w6w-testout-label\">Still running</div>\n <div className=\"w6w-result\">\n Run <code>{state.runId}</code> has not finished yet — check its status from the\n workflow's run history.\n </div>\n </div>\n )}\n {state?.status === \"done\" && state.terminal && state.error !== undefined && (\n <div className=\"w6w-testout\">\n <div className=\"w6w-testout-label\">Run failed</div>\n <pre\n className=\"w6w-result w6w-error\"\n style={{ whiteSpace: \"pre-wrap\", maxHeight: 220, overflow: \"auto\", margin: 0 }}\n >\n {JSON.stringify(state.error, null, 2)}\n </pre>\n </div>\n )}\n {state?.status === \"done\" && state.terminal && state.error === undefined && (\n <div className=\"w6w-testout\">\n <div className=\"w6w-testout-label\">Result</div>\n <pre\n className=\"w6w-result\"\n style={{ whiteSpace: \"pre-wrap\", maxHeight: 220, overflow: \"auto\", margin: 0 }}\n >\n {JSON.stringify(state.output, null, 2)}\n </pre>\n </div>\n )}\n </div>\n );\n}\n\n/**\n * Whether every required param has a usable value — gates the inline \"Test run\".\n * A required array (e.g. a `vars` table) may be empty (see the Data node); other\n * required fields must be non-empty.\n *\n * A param hidden by its own `showIf` is skipped, matching `ParamsForm`'s render\n * visibility — this is what lets `required` and `showIf` combine at all (e.g.\n * SendGrid's `contentValue`, required only when NOT using a dynamic template):\n * without it, a conditionally-required field would either block the gate in the\n * branch where it's moot, or (if left non-required to dodge that) never be\n * caught here and only surface as a raw runtime error from the app's own\n * `execute()` — the app was previously written the second way for exactly this\n * reason; that workaround was fixed alongside this once the gate learned `showIf`.\n */\nexport function requiredParamsFilled(\n params: ActionParam[],\n values: Record<string, unknown>,\n): boolean {\n // Built once from the FULL top-level tree (not per-section) so a section\n // child's `showIf` can reference a sibling outside its own section — same\n // reasoning as `ParamsForm`'s `effective`.\n const flat = flattenParams(params);\n const effective = (key: string) =>\n values[key] !== undefined ? values[key] : flat.find((p) => p.key === key)?.default;\n\n const check = (\n list: ActionParam[],\n vals: Record<string, unknown>,\n eff: (key: string) => unknown,\n ): boolean =>\n list.every((p) => {\n // A `section` is a layout-only container whose children write flat at this\n // level — recurse so a required child (e.g. a grouped Sender Email) still\n // gates. The section param itself carries no value.\n if (p.type === \"section\") return check(p.children ?? [], vals, eff);\n // A `group` nests its children's values under its own key (or, for\n // `repeat: true`, one nested slice per row) — mirrors `GroupField`'s\n // rendering (`ParamsForm.tsx`) including its group-local-first `showIf`\n // resolution (D-3): a child's `showIf` checks the group's OWN children\n // first, falling back to `eff` (the enclosing scope) for any key the\n // group doesn't declare.\n if (p.type === \"group\") {\n const children = p.children ?? [];\n const flatChildren = flattenParams(children);\n const scoped =\n (groupVals: Record<string, unknown>) =>\n (key: string): unknown => {\n const local = flatChildren.find((c) => c.key === key);\n if (!local) return eff(key);\n return groupVals[key] !== undefined ? groupVals[key] : local.default;\n };\n if (p.repeat) {\n const rows = Array.isArray(vals[p.key]) ? (vals[p.key] as unknown[]) : [];\n // An empty list passes unless the group itself is required.\n if (rows.length === 0) return !p.required;\n return rows.every((row) => {\n const rowVals = (row ?? {}) as Record<string, unknown>;\n return check(children, rowVals, scoped(rowVals));\n });\n }\n const groupVals = (vals[p.key] ?? {}) as Record<string, unknown>;\n return check(children, groupVals, scoped(groupVals));\n }\n if (!p.required) return true;\n if (!isParamVisible(p, eff)) return true;\n const v = vals[p.key] ?? p.default;\n if (v === undefined || v === null) return false;\n if (typeof v === \"string\") return v.trim() !== \"\";\n return true;\n });\n return check(params, values, effective);\n}\n\n/**\n * Whether adding this step is gated on a **passing** saved test — the per-app\n * `testRequired` save-gate. Defaults to **required**; an app/node surface may\n * opt out by carrying `testRequired: false`.\n *\n * The flag is read defensively off the app/node surface because the core app\n * manifest does not carry a `testRequired` field yet (a recorded follow-up); an\n * absent flag therefore means **required**, so today every app step must pass a\n * test before it can be added.\n */\nexport function isTestRequired(surface: unknown): boolean {\n const flag = (surface as { testRequired?: unknown } | null | undefined)?.testRequired;\n return typeof flag === \"boolean\" ? flag : true;\n}\n\ntype TestState =\n | { status: \"running\" }\n | { status: \"done\"; value: unknown; logs?: string[]; meta?: StepMeta }\n | { status: \"error\"; error: string; errorCode?: string; logs?: string[] };\n\n/**\n * Where a test run should be persisted. When present, `StepTestRun` saves the\n * fixture (`saveStepTest`) and records the run's outcome (`recordStepTestRun`)\n * against the given workflow step after each invoke. `input` is the resolved\n * incoming state captured alongside the params (`values` → `with`). Absent in\n * the add-step builder (the step isn't in a workflow yet).\n */\nexport interface StepTestPersist {\n workflowId: string;\n stepId: string;\n input: Record<string, unknown>;\n}\n\n/** Imperative handle so a host (e.g. the step modal footer) can trigger the run. */\nexport interface StepTestRunHandle {\n run: () => void;\n}\n\n/**\n * Inline \"Test run\" — invokes the action/node with the current params (and, for\n * app actions, the chosen connection) so the user can try a step from inside the\n * builder before adding it. Pressable only once required fields are filled.\n *\n * When `persist` is supplied (the node editor's Test tab), each run also saves\n * the fixture and records the outcome server-side, so a step test becomes saved\n * and re-runnable. `hideRunButton` suppresses the inline button when the host\n * drives the run from elsewhere (the modal footer) via the imperative handle.\n */\nexport const StepTestRun = forwardRef<\n StepTestRunHandle,\n {\n app: string;\n action: string;\n connectionId?: string;\n values: Record<string, unknown>;\n canRun: boolean;\n hideRunButton?: boolean;\n persist?: StepTestPersist;\n /**\n * The run's start state — what the upstream steps last produced — so a\n * `values` entry written as `{{ steps.<id>.output.<field> }}` resolves\n * server-side instead of coming back empty. The host builds it (both the\n * node editor's Test tab and, since T1.1.1, the add-step builder's Test\n * tab seed it from the upstream fixtures, via `useSeedSources` +\n * `startStateFromSeeds`); absent only when the host itself has no upstream\n * steps to offer — the Functions/Endpoints pickers, which have no graph.\n */\n state?: StepStartState;\n /** Notified when the run starts/finishes so a host button can reflect it. */\n onBusyChange?: (busy: boolean) => void;\n /**\n * Notified with the outcome of each finished run (`true` = passed). Lets a\n * host satisfy the `testRequired` save-gate from an in-session test run.\n */\n onResult?: (passed: boolean) => void;\n }\n>(function StepTestRun(\n {\n app,\n action,\n connectionId,\n values,\n canRun,\n hideRunButton,\n persist,\n state: startState,\n onBusyChange,\n onResult,\n },\n ref,\n) {\n const api = useW6WApi();\n // Resolve document expressions against the workflow's selected project (the\n // editor provides it; undefined outside the editor → server default project).\n const project = useWorkflowProject();\n const [state, setState] = useState<TestState | null>(null);\n\n const run = async () => {\n if (!canRun || state?.status === \"running\") return;\n setState({ status: \"running\" });\n onBusyChange?.(true);\n let outcome: Exclude<TestState, { status: \"running\" }>;\n try {\n const result = await api.invokeAction(app, action, values, {\n ...(connectionId ? { connectionId } : {}),\n project,\n // Omitted when the host has no upstream state to offer, so the request\n // is unchanged for every caller that never had one.\n ...(startState ? { state: startState } : {}),\n });\n outcome = {\n status: \"done\",\n value: result.value,\n logs: (result as { logs?: string[] }).logs,\n ...(result.meta ? { meta: result.meta } : {}),\n };\n } catch (e) {\n const err = e as { message?: string; code?: string; logs?: string[] };\n outcome = {\n status: \"error\",\n error: err.message ?? String(e),\n errorCode: err.code,\n logs: err.logs,\n };\n }\n setState(outcome);\n onResult?.(outcome.status === \"done\");\n // Persist the fixture + record the outcome when the host targets a workflow\n // step. Best-effort: a failed save must never mask the run's own result.\n if (persist) {\n try {\n const saved = await api.saveStepTest(persist.workflowId, persist.stepId, {\n input: persist.input,\n with: values,\n });\n await api.recordStepTestRun(persist.workflowId, persist.stepId, {\n stepTestId: saved.id,\n status: outcome.status === \"done\" ? \"succeeded\" : \"failed\",\n input: persist.input,\n output: outcome.status === \"done\" ? outcome.value : undefined,\n error: outcome.status === \"error\" ? outcome.error : undefined,\n ...(outcome.status === \"done\" && outcome.meta ? { meta: outcome.meta } : {}),\n });\n } catch (err) {\n console.error(\"step test persist failed\", err);\n }\n }\n onBusyChange?.(false);\n };\n\n useImperativeHandle(ref, () => ({ run }));\n\n const logs = state && state.status !== \"running\" ? state.logs : undefined;\n\n return (\n <div className=\"w6w-steptest\">\n {!hideRunButton && (\n <div className=\"w6w-steptest-bar\">\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n disabled={!canRun || state?.status === \"running\"}\n onClick={run}\n >\n {state?.status === \"running\" ? \"Running…\" : \"▶ Test run\"}\n </button>\n {!canRun && (\n <span className=\"w6w-muted w6w-small\">Fill the required fields to test.</span>\n )}\n </div>\n )}\n {state?.status === \"error\" && (\n <div className=\"w6w-result w6w-error\">\n {state.errorCode && (\n <div className=\"w6w-small\" style={{ opacity: 0.75, marginBottom: 4 }}>\n <code>{state.errorCode}</code>\n </div>\n )}\n {state.error}\n </div>\n )}\n {state?.status === \"done\" && (\n <div className=\"w6w-testout\">\n <div className=\"w6w-testout-label\">Result (return value)</div>\n <pre\n className=\"w6w-result\"\n style={{ whiteSpace: \"pre-wrap\", maxHeight: 220, overflow: \"auto\", margin: 0 }}\n >\n {JSON.stringify(state.value, null, 2)}\n </pre>\n {state.meta && (\n <>\n <div className=\"w6w-testout-label\">Metadata</div>\n <pre\n className=\"w6w-result\"\n style={{ whiteSpace: \"pre-wrap\", maxHeight: 220, overflow: \"auto\", margin: 0 }}\n >\n {JSON.stringify(state.meta, null, 2)}\n </pre>\n </>\n )}\n </div>\n )}\n {logs && logs.length > 0 && (\n <div className=\"w6w-testout\">\n <div className=\"w6w-testout-label\">Console output</div>\n <pre\n className=\"w6w-result w6w-testout-console\"\n style={{ whiteSpace: \"pre-wrap\", maxHeight: 160, overflow: \"auto\", margin: 0 }}\n >\n {logs.join(\"\\n\")}\n </pre>\n </div>\n )}\n </div>\n );\n});\n\n// ── Connected apps tab (default) ─────────────────────────────────────────────\n\n/**\n * What the home tab has to show. Lifted out of the tab's own component because\n * the MODAL needs the answer too: a home tab with nothing in it is not\n * rendered at all (no connected apps, no Functions, no Workflows ⇒ no tab),\n * and that decision belongs to whoever draws the sidebar.\n *\n * `state` is deliberately four-valued. \"Empty\" and \"not loaded yet\" must not\n * collapse into one: hiding the tab while its fetches are in flight would make\n * it appear a beat later, moving the sidebar under the cursor.\n */\ninterface ReadyToUse {\n state: \"loading\" | \"error\" | \"empty\" | \"ready\";\n error?: string;\n apps: AppSummary[];\n fns: FunctionSummary[];\n wfs: WorkflowSummary[];\n /** More connected-app ids remain unresolved — draw an explicit \"load more\" affordance. */\n moreApps: boolean;\n /** Resolve the next bounded batch of connected-app ids. No-op off the bounded path or with nothing left. */\n loadMoreApps: () => void;\n}\n\n/** Bounded batch size for {@link W6WApi.listAppsByIds} resolution — a handful\n * per request, never the whole connected-id list at once (A3). */\nconst READY_TO_USE_ID_BATCH = 12;\n\n/** A stable, always-empty `Set` — the first batch's \"nothing requested yet\". */\nconst EMPTY_ID_SET: ReadonlySet<string> = new Set();\n\n/**\n * Clamp the poll-interval text to an integer number of minutes ≥ `min`. Blank,\n * non-numeric or below-minimum input yields `min`; fractions round to nearest.\n */\nexport function clampMinutes(raw: string, min: number): number {\n const n = Number(raw.trim());\n if (raw.trim() === \"\" || !Number.isFinite(n) || n < min) return min;\n return Math.max(min, Math.round(n));\n}\n\n/**\n * \"Ready to use\"'s data: distinct connected app ids (A3) resolved in bounded\n * batches via the optional `listAppsByIds`, plus Functions/Workflows.\n *\n * `/connections` already includes a synthetic zero-credential row per\n * zero-credential-flagged app the caller's tenant can use with no connection\n * step (`admin/connections.ts`) — so the DISTINCT connection app ids alone are\n * the full \"ready\" membership; unlike the old full-catalog scan, no separate\n * `AppSummary.zeroCredential` check is needed on this path.\n *\n * `listAppsByIds` is optional (older/imported providers implement only\n * `listApps`): capability is `typeof api.listAppsByIds === \"function\"`\n * ALONE — never inferred from a runtime result. A first batch that resolves\n * to an empty array is a LEGITIMATE answer from a fully-working\n * `listAppsByIds` (every connected app was since deleted from the catalog,\n * an ordinary case) and must be shown as such, not treated as evidence the\n * optional method \"isn't really implemented\" (T2.1.1 ROUND 2 — that\n * conflation previously made a correct, well-typed empty result permanently\n * fall back to the unbounded `listApps()` for the rest of the component's\n * lifetime, the exact \"one request per entire catalog at open\" A3 forbids).\n * When the method is genuinely absent, this hook falls back to the ORIGINAL\n * full-catalog scan (`listApps()` + the zero-credential check), unchanged —\n * and with `listApps` itself also absent (now optional, like this member),\n * settles on the empty catalog instead of calling an undefined function.\n *\n * On the bounded path each connection's inline `app` meta is read FIRST: an\n * app id with a non-null `app` on any of its rows is built as\n * `{ ...c.app, id: c.appId }` and seeded as resolved + requested, so\n * `listAppsByIds` is called only for ids whose rows all lack it (`app` absent\n * or `null`) — and not at all when none do. Such inline apps have no\n * `version`/`categories`: the selected-app header drops its ` · v<version>`\n * suffix and `appsFilter` sees only `id` and the meta keys.\n *\n * Exported for tests only (not re-exported from the package index).\n */\nexport function useReadyToUse(\n callables: readonly (\"function\" | \"workflow\")[],\n appsFilter?: (app: AppSummary) => boolean,\n): ReadyToUse {\n const api = useW6WApi();\n const [connectedIds, setConnectedIds] = useState<string[] | null>(null);\n const [allApps, setAllApps] = useState<AppSummary[] | null>(null);\n const [fns, setFns] = useState<FunctionSummary[] | null>(null);\n const [wfs, setWfs] = useState<WorkflowSummary[] | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [resolved, setResolved] = useState<Map<string, AppSummary>>(() => new Map());\n const [requestedIds, setRequestedIds] = useState<Set<string>>(() => new Set());\n // Ids sent to `listAppsByIds` and not yet resolved. Separate from\n // `requestedIds` (whose emptiness is the first-batch loading gate). The ref\n // mirrors it so a same-tick second call is guarded too.\n const [inFlightIds, setInFlightIds] = useState<ReadonlySet<string>>(EMPTY_ID_SET);\n const inFlightRef = useRef<ReadonlySet<string>>(EMPTY_ID_SET);\n const setInFlight = useCallback((next: ReadonlySet<string>) => {\n inFlightRef.current = next;\n setInFlightIds(next);\n }, []);\n // App ids whose connection rows carried inline `app` meta — never looked up.\n const inlineIdsRef = useRef<ReadonlySet<string>>(EMPTY_ID_SET);\n\n const wantFns = callables.includes(\"function\");\n const wantWfs = callables.includes(\"workflow\");\n const bounded = typeof api.listAppsByIds === \"function\";\n\n useEffect(() => {\n let canceled = false;\n const fail = (e: unknown) => !canceled && setError((e as Error).message);\n api\n .listConnections()\n .then((conns) => {\n if (canceled) return;\n const ids: string[] = [];\n const seen = new Set<string>();\n const inline = new Map<string, AppSummary>();\n for (const c of conns) {\n if (isInternalApp(c.appId)) continue;\n if (bounded && c.app && !inline.has(c.appId)) {\n inline.set(c.appId, { ...c.app, id: c.appId });\n }\n if (seen.has(c.appId)) continue;\n seen.add(c.appId);\n ids.push(c.appId);\n }\n if (inline.size > 0) {\n inlineIdsRef.current = new Set(inline.keys());\n setResolved((prev) => new Map([...prev, ...inline]));\n setRequestedIds((prev) => new Set([...prev, ...inline.keys()]));\n }\n setConnectedIds(ids);\n })\n .catch(fail);\n // A family this picker does not offer is never fetched, and resolves to an\n // empty list so the readiness check below still completes.\n if (wantFns) {\n api\n .listFunctions()\n .then((r) => !canceled && setFns(r))\n .catch(fail);\n } else setFns([]);\n if (wantWfs) {\n api\n .listWorkflows()\n .then((r) => !canceled && setWfs(r))\n .catch(fail);\n } else setWfs([]);\n return () => {\n canceled = true;\n };\n }, [api, bounded, wantFns, wantWfs]);\n\n // Legacy full-catalog fallback — fetched only when there is no bounded id\n // lookup to use instead, never alongside it.\n useEffect(() => {\n if (bounded) return;\n const listApps = api.listApps;\n // Neither `listAppsByIds` (checked above, via `bounded`) nor `listApps`:\n // settle on the empty catalog below rather than calling an undefined\n // function — the \"ready to use\" tab then shows just Functions/Workflows\n // (or its own empty state), never a throw or a stuck loading state.\n if (typeof listApps !== \"function\") {\n setAllApps([]);\n return;\n }\n let canceled = false;\n listApps()\n .then((r) => !canceled && setAllApps(r))\n .catch((e) => !canceled && setError((e as Error).message));\n return () => {\n canceled = true;\n };\n }, [api, bounded]);\n\n const mountedRef = useRef(true);\n useEffect(\n () => () => {\n mountedRef.current = false;\n },\n [],\n );\n\n const resolveBatch = useCallback(\n (batch: string[]) => {\n const listAppsByIds = api.listAppsByIds;\n if (!listAppsByIds || batch.length === 0 || inFlightRef.current.size > 0) return;\n setInFlight(new Set(batch));\n listAppsByIds(batch)\n .then((apps) => {\n if (!mountedRef.current) return;\n setInFlight(EMPTY_ID_SET);\n // An empty result (every requested id was a 404) is a legitimate\n // answer, not evidence the optional method \"isn't really\n // implemented\" — see this hook's own doc-comment above. It is\n // recorded as resolved (nothing to show for this batch) exactly\n // like a batch with some, but not all, ids found.\n setResolved((prev) => {\n const next = new Map(prev);\n for (const a of apps) next.set(a.id, a);\n return next;\n });\n setRequestedIds((prev) => new Set([...prev, ...batch]));\n })\n .catch((e) => mountedRef.current && setError((e as Error).message));\n },\n [api, setInFlight],\n );\n\n // Exactly ONE automatic batch, the moment connected ids first arrive —\n // every subsequent batch is explicit, via `loadMoreApps` (A3: \"never one\n // request per entire catalog at open\"). Guarded by a ref (not `requestedIds`\n // itself) so a re-render before the first batch resolves can never start a\n // second, duplicate first-batch request.\n const firstBatchStartedRef = useRef(false);\n useEffect(() => {\n if (!bounded || connectedIds === null || firstBatchStartedRef.current) return;\n const batch = nextIdBatch(connectedIds, inlineIdsRef.current, READY_TO_USE_ID_BATCH);\n if (batch.length === 0) return;\n firstBatchStartedRef.current = true;\n resolveBatch(batch);\n }, [bounded, connectedIds, resolveBatch]);\n\n const loadMoreApps = () => {\n if (!bounded || connectedIds === null) return;\n if (inFlightRef.current.size > 0) return;\n const exclude = new Set([...requestedIds, ...inFlightRef.current]);\n resolveBatch(nextIdBatch(connectedIds, exclude, READY_TO_USE_ID_BATCH));\n };\n\n if (error)\n return { state: \"error\", error, apps: [], fns: [], wfs: [], moreApps: false, loadMoreApps };\n if (fns === null || wfs === null) {\n return { state: \"loading\", apps: [], fns: [], wfs: [], moreApps: false, loadMoreApps };\n }\n\n if (bounded) {\n if (connectedIds === null) {\n return { state: \"loading\", apps: [], fns, wfs, moreApps: false, loadMoreApps };\n }\n if (connectedIds.length > 0 && requestedIds.size === 0) {\n return { state: \"loading\", apps: [], fns, wfs, moreApps: false, loadMoreApps };\n }\n const apps = mergeResolvedApps(connectedIds, resolved).filter((a) => appsFilter?.(a) ?? true);\n const moreApps =\n inFlightIds.size === 0 &&\n nextIdBatch(connectedIds, new Set([...requestedIds, ...inFlightIds]), 1).length > 0;\n const empty = apps.length === 0 && fns.length === 0 && wfs.length === 0 && !moreApps;\n return { state: empty ? \"empty\" : \"ready\", apps, fns, wfs, moreApps, loadMoreApps };\n }\n\n if (allApps === null) {\n return { state: \"loading\", apps: [], fns, wfs, moreApps: false, loadMoreApps };\n }\n // Reserved `@w6w/*` pseudo-apps are never connectable — they are added from\n // the Controls/Utilities tabs, exactly as `AppPicker` excludes them.\n //\n // \"Ready to use\" means EITHER an actual Connection exists OR the app needs\n // none at all — a zero-credential-flagged app's whole point is that its\n // tenant's users get the declared tenantAuth/jit path with no connection\n // step, so requiring membership in `connectedIds` alone hid it from the one\n // tab it is MOST meant to appear in. This full-catalog fallback path is the\n // ONLY place that check still needs `AppSummary.zeroCredential` directly —\n // the bounded path above gets zero-credential membership from `/connections`'\n // own synthetic rows instead (see this function's doc comment).\n const connectedSet = new Set(connectedIds ?? []);\n const apps = allApps.filter(\n (a) =>\n !isInternalApp(a.id) &&\n (appsFilter?.(a) ?? true) &&\n (connectedSet.has(a.id) || a.zeroCredential === true),\n );\n const empty = apps.length === 0 && fns.length === 0 && wfs.length === 0;\n return { state: empty ? \"empty\" : \"ready\", apps, fns, wfs, moreApps: false, loadMoreApps };\n}\n\n/** Sort helper — by display label, case-insensitively. */\nfunction byLabel<T>(label: (t: T) => string) {\n return (a: T, b: T) => label(a).localeCompare(label(b), undefined, { sensitivity: \"base\" });\n}\n\n/** A Function/Workflow summary's display name, falling back to name then id. */\nfunction callableLabel(it: FunctionSummary | WorkflowSummary): string {\n const dn = it.displayName;\n if (dn?.trim()) return dn;\n return \"name\" in it ? it.name : it.id;\n}\n\n/**\n * One Function/Workflow row. Shared by the home tab and by the Workflows and\n * Functions tabs, so a Function looks like a Function wherever it is offered —\n * same glyph, same tinted background. Two surfaces drawing the same thing\n * differently is how a list stops being learnable.\n */\nfunction CallableRow({\n family,\n item,\n onSelect,\n}: {\n family: \"function\" | \"workflow\";\n item: FunctionSummary | WorkflowSummary;\n onSelect: (t: { id: string; label: string }) => void;\n}) {\n const label = callableLabel(item);\n return (\n <button\n type=\"button\"\n className=\"w6w-stepbuilder-item w6w-stepbuilder-item--callable\"\n data-kind={family}\n onClick={() => onSelect({ id: item.id, label })}\n >\n <InternalIcon icon={CALLABLE_GLYPH[family]} size={24} />\n <span className=\"w6w-stepbuilder-item-main\">\n <strong>{label}</strong>\n <code className=\"w6w-muted w6w-small\">{item.id}</code>\n </span>\n </button>\n );\n}\n\n/**\n * The picker's home tab — **everything already usable**, in the two-column\n * layout the intake draws:\n *\n * Connnected apps | functions\n * | workflows\n *\n * Connected apps down the left; Functions above Workflows down the right, with\n * a rule between the halves. That sketch is a LAYOUT, not a tab list — it was\n * built as three sidebar tabs first, and that was wrong twice over: the three\n * kinds belong on one screen, side by side, so the author sees everything they\n * can reach without navigating. The browse-everything tabs (Apps, AI,\n * Workflows, Functions) still sit below this one for the full catalogues.\n *\n * \"Ready to use\" rather than \"Connected apps\": what unites the columns is that\n * none of them needs setting up before it can be picked. The Apps tab, by\n * contrast, is the catalogue, where picking may mean connecting first.\n *\n * **Every empty column disappears** — heading and all. A \"Workflows\" heading\n * over nothing claims you have workflows ready to use, which is exactly what\n * an empty list is telling you is false. No connected apps ⇒ no left column,\n * and the grid collapses to one. Nothing at all ⇒ the modal does not render\n * the tab (see {@link useReadyToUse}), so this component never sees that case.\n *\n * No search box: the original Connected-apps tab ran `AppPicker` with\n * `search={false}`, and short scoped lists are not the surface a search box\n * earns. The Apps/Workflows/Functions tabs each keep their own.\n */\nfunction ReadyToUseFlow({\n data,\n onSelectApp,\n onSelectCallable,\n theme,\n}: {\n data: ReadyToUse;\n onSelectApp: (app: AppSummary) => void;\n onSelectCallable: (t: { family: \"function\" | \"workflow\"; id: string; label: string }) => void;\n theme?: ThemeMode;\n}) {\n // Single layout owner for every exit, so the panel never resizes between\n // error/loading and the loaded columns — mirrors `.w6w-apppicker-host`'s role\n // in `AppPicker` and `CallableList`.\n const host = (body: ReactNode) => <div className=\"w6w-apppicker-host\">{body}</div>;\n\n if (data.state === \"error\") {\n return host(<div className=\"w6w-result w6w-error\">{data.error}</div>);\n }\n if (data.state === \"loading\") return host(<p className=\"w6w-muted w6w-small\">Loading…</p>);\n\n const apps = [...data.apps].sort(byLabel((a: AppSummary) => a.displayName));\n const fns = [...data.fns].sort(byLabel(callableLabel));\n const wfs = [...data.wfs].sort(byLabel(callableLabel));\n\n /** One column: a heading and its rows. Rendered only when it HAS rows. */\n const column = (title: string, rows: ReactNode[]) =>\n rows.length === 0 ? null : (\n <section key={title} className=\"w6w-readytouse-col\">\n <h4 className=\"w6w-readytouse-heading\">{title}</h4>\n <div className=\"w6w-stepbuilder-list w6w-stepbuilder-scroll\">{rows}</div>\n </section>\n );\n\n const leftRows: ReactNode[] = apps.map((a) => (\n <button\n key={a.id}\n type=\"button\"\n className=\"w6w-stepbuilder-item\"\n data-kind=\"app\"\n onClick={() => onSelectApp(a)}\n >\n <AppIcon\n src={a.iconSvg}\n srcDark={a.iconSvgDark}\n brandColor={a.brandColor}\n name={a.displayName}\n theme={theme}\n size={24}\n />\n <span className=\"w6w-stepbuilder-item-main\">\n <strong>{a.displayName}</strong>\n <code className=\"w6w-muted w6w-small\">{a.id}</code>\n </span>\n </button>\n ));\n // A3: further connected-app ids remain unresolved — an explicit affordance,\n // never an automatic drain of the rest of the connected-id list.\n if (data.moreApps) {\n leftRows.push(\n <button\n key=\"__load_more_apps\"\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n onClick={data.loadMoreApps}\n >\n Load more\n </button>,\n );\n }\n const left = column(\"Connected apps\", leftRows);\n\n // Functions above Workflows — the order the intake draws them in.\n const right = [\n column(\n \"Functions\",\n fns.map((f) => (\n <CallableRow\n key={f.id}\n family=\"function\"\n item={f}\n onSelect={(t) => onSelectCallable({ family: \"function\", ...t })}\n />\n )),\n ),\n column(\n \"Workflows\",\n wfs.map((w) => (\n <CallableRow\n key={w.id}\n family=\"workflow\"\n item={w}\n onSelect={(t) => onSelectCallable({ family: \"workflow\", ...t })}\n />\n )),\n ),\n ].filter(Boolean);\n\n // `data-cols` drives the grid template, so a missing half collapses rather\n // than leaving an empty tract — and the divider only exists when there are\n // in fact two halves to divide.\n const cols = (left ? 1 : 0) + (right.length > 0 ? 1 : 0);\n return host(\n <div className=\"w6w-readytouse\" data-cols={cols}>\n {left}\n {right.length > 0 && <div className=\"w6w-readytouse-stack\">{right}</div>}\n </div>,\n );\n}\n\nexport function AppStepConfig({\n appId,\n app,\n onAdd,\n onClose,\n onDraftChange,\n onChangeApp,\n theme,\n workflowId,\n stepId,\n upstreamSteps = [],\n initialAction,\n initialConnection,\n initialWith,\n}: {\n appId: string;\n app?: AppSummary;\n // biome-ignore lint/suspicious/noConfusingVoidType: see StepBuilderModalProps.onAdd, forwarded as-is.\n onAdd: (s: BuiltStep) => string | undefined | void;\n onClose: () => void;\n /** See {@link StepBuilderModalProps.onDraftChange}. */\n onDraftChange?: (id: string, step: BuiltStep) => void;\n onChangeApp?: () => void;\n theme?: ThemeMode;\n workflowId?: string;\n stepId?: string;\n /** The new step's known graph ancestors — see {@link StepBuilderModalProps.upstreamSteps}. */\n upstreamSteps?: ExpressionStepSource[];\n /** Pre-selected action key, opens directly to Configure tab when provided with initialWith */\n initialAction?: string;\n /** Pre-selected connection id */\n initialConnection?: string;\n /** Pre-filled parameter values */\n initialWith?: Record<string, unknown>;\n}) {\n const api = useW6WApi();\n const [auths, setAuths] = useState<AuthDef[] | null>(null);\n const [conns, setConns] = useState<ConnectionSummary[] | null>(null);\n const [actions, setActions] = useState<ActionDef[] | null>(null);\n const [metaError, setMetaError] = useState<string | null>(null);\n\n const [connectionId, setConnectionId] = useState<string>(initialConnection ?? \"\");\n const [actionKey, setActionKey] = useState<string>(initialAction ?? \"\");\n const [withValues, setWithValues] = useState<Record<string, unknown>>(initialWith ?? {});\n const [showConnModal, setShowConnModal] = useState(false);\n // Once a connection is chosen it renders as a static label; \"Change\" flips\n // back to the dropdown. No connection selected yet also forces the dropdown.\n const [changingConn, setChangingConn] = useState(false);\n // Setup (app + connection + action) / Configure (params) / Test — same tabs as\n // the node editor, so add + edit are consistent.\n // When initial values are provided, skip Setup and open directly to Configure.\n const [tab, setTab] = useState<StepConfigTab>(\n initialAction && initialWith ? \"configure\" : \"setup\",\n );\n // The Configure tab's four representations (form / full-step JSON /\n // params-only JSON / node settings).\n const [configView, setConfigView] = useState<ConfigView>(\"props\");\n // Draft text backing the \"code\" (full-step, read-only) view.\n const [codeText, setCodeText] = useState(\"{}\");\n // Draft text backing the \"params-code\" (params-only, writable) view.\n const [paramsCodeText, setParamsCodeText] = useState(\"{}\");\n // Base node settings (retry / onError / notes) set on the Config view.\n const [draftConfig, setDraftConfig] = useState<NodeConfig>({});\n\n // Load auth methods, existing connections, and actions for the app in parallel.\n useEffect(() => {\n let canceled = false;\n setMetaError(null);\n Promise.all([api.getAppAuth(appId), api.listConnectionsForApp(appId), api.getAppActions(appId)])\n .then(([au, co, ac]) => {\n if (canceled) return;\n setAuths(au);\n setConns(co);\n setActions(ac);\n // P2: in the auto-satisfied state, never auto-select an existing\n // connection — it would be silently written into every step the user\n // builds. A connection picked deliberately through the \"+ New\" escape\n // hatch still is (that flows through `refetchConns`/`onCreated`, not\n // here). No availability re-filter needed: `autoSatisfied` is only\n // ever set on a `tenantAuth`/`jit` entry, and `available` stays\n // unconditionally `true` for every non-`oauth2` type (T3.1.1 P5).\n const autoSat = (au ?? []).some((a) => a.autoSatisfied === true);\n if (!autoSat && co.length > 0) setConnectionId(co[0].id);\n })\n .catch((e) => !canceled && setMetaError((e as Error).message));\n return () => {\n canceled = true;\n };\n }, [api, appId]);\n\n const refetchConns = async () => {\n const co = await api.listConnectionsForApp(appId);\n setConns(co);\n if (co.length > 0) setConnectionId((prev) => prev || co[0].id);\n };\n\n const availableAuths = (auths ?? []).filter((a) => a.available !== false);\n // Third connection state: the operator has flagged a `tenantAuth`/`jit`\n // method as zero-credential for this tenant, so the server resolves a\n // connection automatically at invoke time — the step is complete with none\n // picked. `.some(...)` deliberately: an app declaring both an `oauth2`\n // method and an auto-satisfied `tenantAuth` method is auto-satisfied, and\n // the oauth2 route stays reachable through the \"+ New\" escape hatch (P3).\n const autoSatisfied = availableAuths.some(\n (a) => a.autoSatisfied === true && (a.type === \"tenantAuth\" || a.type === \"jit\"),\n );\n const needsConnection = availableAuths.length > 0 && !autoSatisfied;\n const hasConnection = (conns ?? []).length > 0;\n const selectedAction = (actions ?? []).find((a) => a.key === actionKey);\n // Alphabetical by display title (falling back to key) so the dropdown is\n // scannable regardless of the manifest's declaration order.\n const sortedActions = [...(actions ?? [])].sort((a, b) =>\n (a.title ?? a.key).localeCompare(b.title ?? b.key, undefined, { sensitivity: \"base\" }),\n );\n\n // Per-app `testRequired` save-gate — defaults to required, read off the app\n // surface. `testPassed` is satisfied either by an in-session passing test run\n // (below) or by a previously-saved passing test discovered via `listStepTests`\n // when the builder carries a workflow-step context.\n const testRequired = isTestRequired(app);\n const [testPassed, setTestPassed] = useState(false);\n useEffect(() => {\n if (!testRequired || !workflowId || !stepId) return;\n let canceled = false;\n api\n .listStepTests(workflowId, stepId)\n .then((tests) => {\n if (!canceled && tests.some((t) => t.lastRunStatus === \"succeeded\")) setTestPassed(true);\n })\n .catch(() => {});\n return () => {\n canceled = true;\n };\n }, [api, testRequired, workflowId, stepId]);\n\n // The step-being-added's graph ancestors that carry a saved step-test,\n // offered as one-click seeds for the incoming state — the SAME pipeline\n // `StepEditModal` uses, so the Test tab here resolves\n // `{{ steps.<id>.output.<field> }}` the same way an existing step's Test\n // tab does (T1.1.1). Only meaningful when the builder was opened from a\n // workflow canvas (`workflowId` present); the Functions/Endpoints pickers\n // pass no `workflowId` and no `upstreamSteps`.\n const seedSources = useSeedSources(workflowId ?? \"\", upstreamSteps, !!workflowId);\n const testStartState = startStateFromSeeds(seedSources);\n\n const connectionSatisfied = !needsConnection || (hasConnection && !!connectionId);\n // Setup is done when an action is picked and its connection (if any) is set;\n // Configure is done when the action's required params are filled.\n const setupComplete = !!actionKey && connectionSatisfied;\n const configComplete =\n setupComplete &&\n !!selectedAction &&\n requiredParamsFilled(selectedAction.params ?? [], withValues);\n // HITL-1 amendment: a passing test is required to *publish* (T4.2.1), not to\n // add the step to the graph — `testRequired`/`testPassed` still drive the\n // Test tab's own \"test passed\" messaging below.\n const canAdd = setupComplete;\n\n const selectedConn = (conns ?? []).find((c) => c.id === connectionId);\n // Show the dropdown only before a connection is picked or while changing it;\n // otherwise the selected connection reads as a compact label.\n const showConnPicker = changingConn || !connectionId;\n\n function buildStep(): BuiltStep {\n return {\n uses: {\n app: appId,\n action: selectedAction?.key ?? actionKey,\n // A connection is emitted only when the user explicitly picked one —\n // in the auto-satisfied state nothing is picked by default (P2), so\n // nothing is emitted here, and the server resolves the connection\n // live on every call. Never synthesise an id: it does not exist\n // server-side.\n ...((needsConnection || autoSatisfied) && connectionId ? { connection: connectionId } : {}),\n },\n with: withValues,\n ...draftConfig,\n };\n }\n function add() {\n if (!selectedAction) return;\n onAdd(buildStep());\n }\n\n // The id `onAdd` minted at commit time, once Setup has completed this\n // session. `null` until then (and forever, for a caller that doesn't supply\n // `onDraftChange` — the original one-shot \"Add step\" behavior).\n const [committedId, setCommittedId] = useState<string | null>(null);\n\n // Mint — the moment Setup first completes (action + connection, if needed),\n // commit the WIP step to the graph, exactly once.\n // biome-ignore lint/correctness/useExhaustiveDependencies: buildStep/onAdd intentionally read fresh closure state; only the mint gate should retrigger this effect.\n useEffect(() => {\n if (!onDraftChange || committedId !== null || !setupComplete) return;\n const id = onAdd(buildStep());\n if (id) setCommittedId(id);\n }, [onDraftChange, committedId, setupComplete]);\n\n // Update — keep the already-committed node current on every subsequent field\n // change, instead of minting a duplicate via a second `onAdd` call.\n // biome-ignore lint/correctness/useExhaustiveDependencies: buildStep reads fresh closure state; only these fields should retrigger the update.\n useEffect(() => {\n if (!onDraftChange || committedId === null) return;\n onDraftChange(committedId, buildStep());\n }, [committedId, withValues, draftConfig, connectionId]);\n\n const changeConfigView = (v: ConfigView) => {\n if (v === \"code\") setCodeText(stepToJson(buildStep()));\n else if (v === \"params-code\") setParamsCodeText(paramsToJson(buildStep()));\n setConfigView(v);\n };\n\n return (\n <div className=\"w6w-stepconfig\">\n {/* Tabs bar — full width: Setup/Configure/Test on the left, the props/code/\n config view icons on the right (enabled only on the Configure tab). */}\n <div className=\"w6w-tabsbar\">\n <div className=\"w6w-subtabs\">\n <button\n type=\"button\"\n className={`w6w-subtab${tab === \"setup\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"setup\")}\n >\n Setup\n </button>\n <button\n type=\"button\"\n disabled={!setupComplete}\n title={setupComplete ? undefined : \"Complete Setup first\"}\n className={`w6w-subtab${tab === \"configure\" ? \" active\" : \"\"}`}\n onClick={() => setupComplete && setTab(\"configure\")}\n >\n Configure\n </button>\n <button\n type=\"button\"\n disabled={!configComplete}\n title={configComplete ? undefined : \"Fill the required fields first\"}\n className={`w6w-subtab${tab === \"test\" ? \" active\" : \"\"}`}\n onClick={() => configComplete && setTab(\"test\")}\n >\n Test\n </button>\n </div>\n <ConfigViewToggle\n view={configView}\n onChange={changeConfigView}\n disabled={tab !== \"configure\"}\n />\n </div>\n\n <div className=\"w6w-stepconfig-body\">\n {/* Setup — app, connection, action. */}\n {tab === \"setup\" && (\n <div className=\"w6w-stack\">\n {metaError && <div className=\"w6w-result w6w-error\">{metaError}</div>}\n {auths === null && !metaError && <p className=\"w6w-muted w6w-small\">Loading…</p>}\n\n {/* App — click Change to go back to the app picker. */}\n <div className=\"w6w-field\">\n <span>App</span>\n <div className=\"w6w-conn-label\">\n {app && (\n <AppIcon\n src={app.iconSvg}\n srcDark={app.iconSvgDark}\n brandColor={app.brandColor}\n name={app.displayName}\n theme={theme}\n size={20}\n />\n )}\n <span className=\"w6w-conn-label-name\">{app?.displayName ?? appId}</span>\n {onChangeApp && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n onClick={onChangeApp}\n >\n Change\n </button>\n )}\n </div>\n </div>\n\n {/* Connection — the third, auto-satisfied state (P3): the section\n still renders (it never disappears — a user may still want to\n add their own third-party account), but the picker is replaced\n by a passive line plus the escape hatch. */}\n {auths !== null && autoSatisfied && (\n <div className=\"w6w-field\">\n <span>Connection</span>\n <div className=\"w6w-conn-label\">\n <span className=\"w6w-conn-label-name\">\n Connected automatically — this app needs no connection for your organization.\n </span>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n onClick={() => setShowConnModal(true)}\n >\n Create connection\n </button>\n </div>\n {/* P3a / HITL-8's pinned default: auto-connect is synchronous-only\n (HITL-4) — a queued/scheduled Run of this saved workflow drops\n `subjectToken` before it reaches the invoke path, so it still\n needs a connection configured on the step. Nothing server-side\n changes; this is the editor telling the truth about that limit. */}\n <span className=\"w6w-hint\">\n A scheduled or queued run of this workflow still needs a connection configured on\n this step — use \"Create connection\" if this step will run on a schedule.\n </span>\n </div>\n )}\n\n {/* Connection — the two pre-existing states (needs one / has one). */}\n {auths !== null &&\n needsConnection &&\n (!hasConnection ? (\n <div className=\"w6w-result w6w-stepconfig-conn-empty\">\n <div style={{ marginBottom: 8 }}>\n This app needs a connection before its actions can run.\n </div>\n <button type=\"button\" className=\"w6w-btn\" onClick={() => setShowConnModal(true)}>\n Create connection\n </button>\n </div>\n ) : showConnPicker ? (\n <label className=\"w6w-field\">\n <span>Connection</span>\n <div style={{ display: \"flex\", gap: 6 }}>\n <select\n value={connectionId}\n onChange={(e) => {\n setConnectionId(e.target.value);\n setChangingConn(false);\n }}\n style={{ flex: 1 }}\n >\n {(conns ?? []).map((c) => (\n <option key={c.id} value={c.id}>\n {c.displayName || c.id} {c.state ? `(${c.state})` : \"\"}\n </option>\n ))}\n </select>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n onClick={() => setShowConnModal(true)}\n >\n + New\n </button>\n </div>\n </label>\n ) : (\n <div className=\"w6w-field\">\n <span>Connection</span>\n <div className=\"w6w-conn-label\">\n <span className=\"w6w-conn-label-name\">\n {selectedConn?.displayName || selectedConn?.id || connectionId}\n {selectedConn?.state ? ` (${selectedConn.state})` : \"\"}\n </span>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n onClick={() => setChangingConn(true)}\n >\n Change\n </button>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n onClick={() => setShowConnModal(true)}\n >\n + New\n </button>\n </div>\n </div>\n ))}\n\n {/* Action */}\n {actions !== null &&\n (actions.length === 0 ? (\n <p className=\"w6w-muted w6w-small\">This app exposes no actions.</p>\n ) : (\n // biome-ignore lint/a11y/noLabelWithoutControl: Combobox renders its own <select>/<input> INSIDE this label, so the field text labels the control at runtime; the rule cannot see through the component boundary.\n <label className=\"w6w-field\">\n <span>Action{actionKey ? \"\" : \" *\"}</span>\n <Combobox\n value={actionKey}\n placeholder=\"— pick an action —\"\n onChange={(key) => {\n setActionKey(key);\n setWithValues({});\n // A new action hasn't been tested — re-arm the save-gate.\n setTestPassed(false);\n }}\n options={sortedActions.map((a) => ({\n value: a.key,\n label: `${a.title ?? a.key} (${a.key})`,\n }))}\n />\n {selectedAction?.description && (\n <span className=\"w6w-hint\">{selectedAction.description}</span>\n )}\n </label>\n ))}\n </div>\n )}\n\n {/* Configure — the action's config, as a form (props), the full step\n (code), the params alone (params-code), or the base node settings\n (config). */}\n {tab === \"configure\" &&\n (!selectedAction ? (\n <p className=\"w6w-muted w6w-small\">Pick an action in Setup first.</p>\n ) : configView === \"props\" ? (\n <ParamsForm\n params={selectedAction.params ?? []}\n values={withValues}\n onChange={setWithValues}\n />\n ) : configView === \"code\" ? (\n // Full step, read-only (D-3) — `stepToJson` is the ONE serializer,\n // shared with the two other code-view hosts.\n <JsonEditor\n value={codeText}\n onChange={() => {}}\n readOnly\n minHeight=\"240px\"\n height=\"100%\"\n aria-label=\"Step JSON\"\n copyable\n />\n ) : configView === \"params-code\" ? (\n <JsonEditor\n value={paramsCodeText}\n onChange={setParamsCodeText}\n minHeight=\"240px\"\n height=\"100%\"\n aria-label=\"Parameters JSON\"\n copyable\n onValidChange={(p) =>\n p &&\n typeof p === \"object\" &&\n !Array.isArray(p) &&\n setWithValues(p as Record<string, unknown>)\n }\n />\n ) : (\n <NodeConfigForm config={draftConfig} onChange={setDraftConfig} />\n ))}\n\n {/* Test — try the action with the current params. */}\n {tab === \"test\" &&\n (selectedAction ? (\n <StepTestRun\n app={appId}\n action={selectedAction.key}\n connectionId={\n (needsConnection || autoSatisfied) && connectionId ? connectionId : undefined\n }\n values={withValues}\n canRun={\n setupComplete && requiredParamsFilled(selectedAction.params ?? [], withValues)\n }\n state={testStartState}\n onResult={setTestPassed}\n />\n ) : (\n <p className=\"w6w-muted w6w-small\">Pick an action in Setup first.</p>\n ))}\n </div>\n\n {/* Test-required note — always rendered while on the Test tab, as a\n sibling ABOVE the footer, so the footer's two buttons never move\n whether the note has text or not (the row's reserved min-height\n keeps both states geometrically identical). */}\n {tab === \"test\" && (\n <div className=\"w6w-stepconfig-testnote\">\n {testRequired && !testPassed && (\n <span className=\"w6w-muted w6w-small\">\n Not yet tested — a passing test is required before this step can be published.\n </span>\n )}\n </div>\n )}\n\n {/* Footer — pinned to the modal bottom. Each tab has a Next button; the\n last (Test) commits the step. */}\n <div className=\"w6w-modal-actions w6w-stepconfig-footer\">\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={onClose}>\n Cancel\n </button>\n {tab === \"test\" ? (\n <button\n type=\"button\"\n className=\"w6w-btn\"\n disabled={committedId === null && !canAdd}\n onClick={committedId !== null ? onClose : add}\n >\n {committedId !== null ? \"Done\" : \"Add step\"}\n </button>\n ) : (\n <button\n type=\"button\"\n className=\"w6w-btn\"\n disabled={tab === \"setup\" ? !setupComplete : !configComplete}\n onClick={() => setTab(tab === \"setup\" ? \"configure\" : \"test\")}\n >\n Next →\n </button>\n )}\n </div>\n\n {showConnModal && (\n <AddConnectionModal\n theme={theme}\n initialAppId={appId}\n onClose={() => setShowConnModal(false)}\n onCreated={async ({ connectionId: id }) => {\n setShowConnModal(false);\n setConnectionId(id);\n setChangingConn(false);\n await refetchConns();\n }}\n />\n )}\n </div>\n );\n}\n\n/**\n * {@link AppStepConfig}'s Setup tab, minus the Action and Configure/Test\n * gate — for a caller that only needs \"a connection is chosen\" (e.g. binding\n * a repository), not a runnable step. Copies its App section and all three\n * Connection-section branches verbatim, same CSS classes; fetches only\n * {@link W6WApi.getAppAuth} + {@link W6WApi.listConnectionsForApp} (never\n * `getAppActions`). Ends in one footer button, gated on `connectionSatisfied`\n * alone, that fires {@link onConnected} once — never on selection (D-sbm-2).\n */\nexport function AppConnectionOnlyConfig({\n appId,\n app,\n onClose,\n onChangeApp,\n theme,\n initialConnection,\n onConnected,\n}: {\n appId: string;\n app?: AppSummary;\n onClose: () => void;\n onChangeApp?: () => void;\n theme?: ThemeMode;\n /** Pre-selected connection id */\n initialConnection?: string;\n /** Fired once, on the footer button — never on a state change (D-sbm-2). */\n onConnected: (connectionId: string, app: AppSummary) => void;\n}) {\n const api = useW6WApi();\n const [auths, setAuths] = useState<AuthDef[] | null>(null);\n const [conns, setConns] = useState<ConnectionSummary[] | null>(null);\n const [metaError, setMetaError] = useState<string | null>(null);\n\n const [connectionId, setConnectionId] = useState<string>(initialConnection ?? \"\");\n const [showConnModal, setShowConnModal] = useState(false);\n // Once a connection is chosen it renders as a static label; \"Change\" flips\n // back to the dropdown. No connection selected yet also forces the dropdown.\n const [changingConn, setChangingConn] = useState(false);\n\n // Load auth methods and existing connections for the app in parallel — no\n // actions fetch here: this component stops at \"a connection is chosen\", it\n // never lists or picks an Action.\n useEffect(() => {\n let canceled = false;\n setMetaError(null);\n Promise.all([api.getAppAuth(appId), api.listConnectionsForApp(appId)])\n .then(([au, co]) => {\n if (canceled) return;\n setAuths(au);\n setConns(co);\n // P2: in the auto-satisfied state, never auto-select an existing\n // connection — see AppStepConfig's own fetch effect for why.\n const autoSat = (au ?? []).some((a) => a.autoSatisfied === true);\n if (!autoSat && co.length > 0) setConnectionId(co[0].id);\n })\n .catch((e) => !canceled && setMetaError((e as Error).message));\n return () => {\n canceled = true;\n };\n }, [api, appId]);\n\n const refetchConns = async () => {\n const co = await api.listConnectionsForApp(appId);\n setConns(co);\n if (co.length > 0) setConnectionId((prev) => prev || co[0].id);\n };\n\n const availableAuths = (auths ?? []).filter((a) => a.available !== false);\n const autoSatisfied = availableAuths.some(\n (a) => a.autoSatisfied === true && (a.type === \"tenantAuth\" || a.type === \"jit\"),\n );\n const needsConnection = availableAuths.length > 0 && !autoSatisfied;\n const hasConnection = (conns ?? []).length > 0;\n const connectionSatisfied = !needsConnection || (hasConnection && !!connectionId);\n\n const selectedConn = (conns ?? []).find((c) => c.id === connectionId);\n // Show the dropdown only before a connection is picked or while changing it;\n // otherwise the selected connection reads as a compact label.\n const showConnPicker = changingConn || !connectionId;\n\n return (\n <div className=\"w6w-stepconfig\">\n <div className=\"w6w-stepconfig-body\">\n <div className=\"w6w-stack\">\n {metaError && <div className=\"w6w-result w6w-error\">{metaError}</div>}\n {auths === null && !metaError && <p className=\"w6w-muted w6w-small\">Loading…</p>}\n\n {/* App — click Change to go back to the app picker. */}\n <div className=\"w6w-field\">\n <span>App</span>\n <div className=\"w6w-conn-label\">\n {app && (\n <AppIcon\n src={app.iconSvg}\n srcDark={app.iconSvgDark}\n brandColor={app.brandColor}\n name={app.displayName}\n theme={theme}\n size={20}\n />\n )}\n <span className=\"w6w-conn-label-name\">{app?.displayName ?? appId}</span>\n {onChangeApp && (\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n onClick={onChangeApp}\n >\n Change\n </button>\n )}\n </div>\n </div>\n\n {/* Connection — the third, auto-satisfied state (P3): the section\n still renders (it never disappears — a user may still want to\n add their own third-party account), but the picker is replaced\n by a passive line plus the escape hatch. */}\n {auths !== null && autoSatisfied && (\n <div className=\"w6w-field\">\n <span>Connection</span>\n <div className=\"w6w-conn-label\">\n <span className=\"w6w-conn-label-name\">\n Connected automatically — this app needs no connection for your organization.\n </span>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n onClick={() => setShowConnModal(true)}\n >\n Create connection\n </button>\n </div>\n {/* P3a / HITL-8's pinned default: auto-connect is synchronous-only\n (HITL-4) — a queued/scheduled Run of this saved workflow drops\n `subjectToken` before it reaches the invoke path, so it still\n needs a connection configured on the step. Nothing server-side\n changes; this is the editor telling the truth about that limit. */}\n <span className=\"w6w-hint\">\n A scheduled or queued run of this workflow still needs a connection configured on\n this step — use \"Create connection\" if this step will run on a schedule.\n </span>\n </div>\n )}\n\n {/* Connection — the two pre-existing states (needs one / has one). */}\n {auths !== null &&\n needsConnection &&\n (!hasConnection ? (\n <div className=\"w6w-result w6w-stepconfig-conn-empty\">\n <div style={{ marginBottom: 8 }}>\n This app needs a connection before its actions can run.\n </div>\n <button type=\"button\" className=\"w6w-btn\" onClick={() => setShowConnModal(true)}>\n Create connection\n </button>\n </div>\n ) : showConnPicker ? (\n <label className=\"w6w-field\">\n <span>Connection</span>\n <div style={{ display: \"flex\", gap: 6 }}>\n <select\n value={connectionId}\n onChange={(e) => {\n setConnectionId(e.target.value);\n setChangingConn(false);\n }}\n style={{ flex: 1 }}\n >\n {(conns ?? []).map((c) => (\n <option key={c.id} value={c.id}>\n {c.displayName || c.id} {c.state ? `(${c.state})` : \"\"}\n </option>\n ))}\n </select>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost\"\n onClick={() => setShowConnModal(true)}\n >\n + New\n </button>\n </div>\n </label>\n ) : (\n <div className=\"w6w-field\">\n <span>Connection</span>\n <div className=\"w6w-conn-label\">\n <span className=\"w6w-conn-label-name\">\n {selectedConn?.displayName || selectedConn?.id || connectionId}\n {selectedConn?.state ? ` (${selectedConn.state})` : \"\"}\n </span>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n onClick={() => setChangingConn(true)}\n >\n Change\n </button>\n <button\n type=\"button\"\n className=\"w6w-btn w6w-btn-ghost w6w-btn-sm\"\n onClick={() => setShowConnModal(true)}\n >\n + New\n </button>\n </div>\n </div>\n ))}\n </div>\n </div>\n\n {/* Footer — pinned to the modal bottom. One button: it commits the\n chosen connection and hands control back to the caller. Gated on\n connectionSatisfied alone — there is no Action here, so the\n `!!actionKey` clause of AppStepConfig's setupComplete does not\n exist. Fires onConnected on click only, never on a state change\n (D-sbm-2). */}\n <div className=\"w6w-modal-actions w6w-stepconfig-footer\">\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"w6w-btn\"\n disabled={!connectionSatisfied || !app}\n onClick={() => app && onConnected(connectionId, app)}\n >\n Next →\n </button>\n </div>\n\n {showConnModal && (\n <AddConnectionModal\n theme={theme}\n initialAppId={appId}\n onClose={() => setShowConnModal(false)}\n onCreated={async ({ connectionId: id }) => {\n setShowConnModal(false);\n setConnectionId(id);\n setChangingConn(false);\n await refetchConns();\n }}\n />\n )}\n </div>\n );\n}\n","import { useRef, useState } from \"react\";\nimport { JsonEditor } from \"./JsonEditor.tsx\";\nimport { ParamsForm } from \"./ParamsForm.tsx\";\nimport { ConfigViewToggle } from \"./StepBuilderModal.tsx\";\nimport type { ActionParam } from \"./types.ts\";\n\n/** The two views this form offers — a subset of the editor's `ConfigView`. */\nconst VIEWS = [\"props\", \"code\"] as const;\ntype EntryView = (typeof VIEWS)[number];\n\nexport interface PropertyEntryFormProps {\n /** Declared params to collect values for. Empty ⇒ raw-JSON only. */\n params: ActionParam[];\n /** Current values, keyed by param `key`. */\n values: Record<string, unknown>;\n /** Fired with the next values object on every (valid) edit. */\n onChange: (next: Record<string, unknown>) => void;\n /**\n * **The validity-out.** Fired (on change only) with whether the raw-JSON draft\n * currently *is* a values map. A draft that does not parse — **or that parses\n * to an array / scalar / `null`** — never reaches `onChange`, so without this\n * channel a host cannot tell \"the user is mid-edit on something that isn't a\n * values map\" from \"the user is happy with what's collected\", and would run\n * the *previous* payload silently. Hosts that execute something (the canvas ▶\n * Run) MUST gate their run affordance on it. Always `true` while the field\n * form is showing — a form cannot be syntactically wrong.\n */\n onValidityChange?: (valid: boolean) => void;\n readOnly?: boolean;\n /** Which view opens first. Defaults to the field form. */\n initialView?: EntryView;\n}\n\n/**\n * Whether a parsed JSON draft IS a values map. An array, a scalar and `null` all\n * parse but are not a set of values — and `typeof null === \"object\"`, so the\n * null arm is load-bearing, not defensive noise (dropping it lets `null` through\n * as the whole values object and blows up the required-check downstream).\n */\nfunction isValuesMap(parsed: unknown): parsed is Record<string, unknown> {\n return parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed);\n}\n\n/**\n * The one property-entry surface: a param form ⇄ raw-JSON editor over a single\n * `values` object. **Chrome-less and value-emitting** — its root is a plain\n * `div.w6w-stack`, it owns no modal, no header, no run button and no result\n * pane. It collects values and emits them through `onChange`; the *host* decides\n * what to do with them (Test invokes, Run executes the step) and supplies any\n * surrounding chrome.\n *\n * That is deliberate: it is mounted both inline inside an already-open\n * `<dialog>` (the step editor's Test tab) and inside a modal of its own (Run).\n * Rendering a modal in here would give the first host a modal-in-a-modal —\n * which *works* mechanically, since this library's modal is a native\n * `<dialog>` that top-layer-stacks, and just looks wrong.\n *\n * The fields view is {@link ParamsForm} reused as-is, so per-field `ƒx`\n * (expression binding) comes for free. The raw view is {@link JsonEditor} bound\n * to the **values** object — never the field *definitions* — and only pushes\n * back when the text parses to a plain object, so an invalid draft cannot\n * corrupt what has been collected. Because such a draft is *silently* held back,\n * the form also reports it through `onValidityChange` (the validity-out): a host\n * that runs something real must gate its run affordance on that, or it would\n * execute the previous payload while the operator looks at a different one. The\n * toggle is the shared {@link ConfigViewToggle}, narrowed to its two views.\n *\n * With **no declared params** (a webhook trigger, an action with no schema)\n * there is nothing to render a form from, so it shows the raw-JSON view alone\n * and hides the toggle.\n */\nexport function PropertyEntryForm({\n params,\n values,\n onChange,\n onValidityChange,\n readOnly,\n initialView = \"props\",\n}: PropertyEntryFormProps) {\n const hasFields = params.length > 0;\n const [view, setView] = useState<EntryView>(initialView);\n // No params ⇒ there is no form to show, so the raw view is the only view.\n const showJson = !hasFields || view === \"code\";\n // The JSON draft is local text: it is re-seeded from the VALUES (never from\n // the param *definitions* — that blob-where-a-form-should-be is the bug this\n // form exists to kill) whenever the raw view is (re-)entered, and only flows\n // back when it parses to a values map.\n const [text, setText] = useState(() => toJsonText(values));\n // Whether the current raw draft is a values map. Mirrored in a ref so the\n // validity-out fires on *change* only — no effect, no render loop.\n const [draftValid, setDraftValid] = useState(true);\n const validRef = useRef(true);\n const emitValid = (next: boolean) => {\n if (next === validRef.current) return;\n validRef.current = next;\n setDraftValid(next);\n onValidityChange?.(next);\n };\n\n const openView = (next: EntryView) => {\n // Either way the old draft is discarded: entering the raw view re-seeds it\n // from the values, leaving it drops it. So validity resets with it.\n if (next === \"code\") setText(toJsonText(values));\n emitValid(true);\n setView(next);\n };\n\n // A webhook-style payload gets the plainer label; alongside a field form the\n // raw view is explicitly \"the same values, as JSON\".\n const label = hasFields ? \"Values (JSON)\" : \"Payload\";\n\n return (\n <div className=\"w6w-stack\">\n {/* Right-aligned, like the toggle's other two call sites in their tabs\n bar. Inline style because the form owns no chrome of its own — no new\n rule in `styles.css` for a one-line layout. */}\n {hasFields && (\n <div style={{ display: \"flex\", justifyContent: \"flex-end\" }}>\n <ConfigViewToggle\n view={view}\n views={[...VIEWS]}\n onChange={(v) => openView(v as EntryView)}\n />\n </div>\n )}\n\n {showJson ? (\n <div className=\"w6w-field\">\n <span>{label}</span>\n <JsonEditor\n value={text}\n onChange={setText}\n readOnly={readOnly}\n minHeight=\"140px\"\n aria-label={`${label} JSON`}\n onValidChange={(parsed) => {\n // Only a plain object IS a values map — an array, a scalar or\n // `null` is a half-typed edit, not a new set of values. It never\n // reaches `onChange`, so the host is told through the validity-out\n // instead of silently keeping (and running) the previous payload.\n const ok = isValuesMap(parsed);\n emitValid(ok);\n if (ok) onChange(parsed);\n }}\n // Fires for unparseable text too, where `onValidChange` never does.\n onValidityChange={(r) => {\n if (!r.valid) emitValid(false);\n }}\n />\n {!draftValid && (\n <span className=\"w6w-hint\">\n This draft isn’t a JSON object yet — the collected values are unchanged until it is.\n </span>\n )}\n </div>\n ) : (\n <ParamsForm params={params} values={values} onChange={onChange} readOnly={readOnly} />\n )}\n </div>\n );\n}\n\n/** Render a values object as the editor's starting text. */\nfunction toJsonText(values: Record<string, unknown>): string {\n return JSON.stringify(values ?? {}, null, 2);\n}\n","import type { ReactNode } from \"react\";\nimport { Modal } from \"./Modal.tsx\";\n\nexport interface ConfirmModalProps {\n title: string;\n message: string;\n /** Fired when the user confirms. The caller clears its pending state via onClose. */\n onConfirm: () => void;\n /** Fired on Cancel, Esc, or outside-click — dismisses without confirming. */\n onClose: () => void;\n confirmLabel?: string;\n cancelLabel?: string;\n /** Style the confirm button as destructive (default true — this dialog gates dangerous actions). */\n destructive?: boolean;\n /** Extra consequence copy under the message (e.g. a warning line) that a string cannot carry. */\n children?: ReactNode;\n}\n\n/**\n * A reusable confirmation dialog built on `@w6w/ui`'s <Modal>, so it inherits the\n * same backdrop, Esc-dismiss and outside-click close as every other dialog here.\n * Replaces the browser's native confirmation prompt: Confirm fires `onConfirm`;\n * Cancel/Esc/outside-click fires `onClose` only (no confirmation).\n *\n * Prop API mirrors `packages/studio/src/components/ConfirmModal.tsx` and\n * `packages/admin/src/components/ConfirmModal.tsx` so all three consoles share one\n * vocabulary. Only the class names differ — this one is `w6w-*` namespaced.\n *\n * It owns its own <Modal>, so never render it *inside* another modal's body: ui's\n * Modal is a native <dialog>, so nesting one works mechanically and fails no gate —\n * it just looks wrong. Render it as a **sibling** of the other modal instead.\n *\n * Confirmations are `{pending}` state + a rendered sibling modal, never a blocking\n * call: a caller reachable from a keydown handler cannot swap in a boolean.\n */\nexport function ConfirmModal({\n title,\n message,\n onConfirm,\n onClose,\n confirmLabel = \"Confirm\",\n cancelLabel = \"Cancel\",\n destructive = true,\n children,\n}: ConfirmModalProps) {\n return (\n <Modal title={title} onClose={onClose}>\n {/* One body wrapper + a pinned footer (D-3): long consequence copy scrolls\n inside `.w6w-modal-body`, the buttons never leave the dialog's bottom. */}\n <div className=\"w6w-modal-body\">\n <p className=\"w6w-muted w6w-small\">{message}</p>\n {children}\n </div>\n <div className=\"w6w-modal-actions\">\n <button type=\"button\" className=\"w6w-btn w6w-btn-ghost\" onClick={onClose}>\n {cancelLabel}\n </button>\n <button\n type=\"button\"\n className={destructive ? \"w6w-btn w6w-btn-danger\" : \"w6w-btn\"}\n onClick={onConfirm}\n >\n {confirmLabel}\n </button>\n </div>\n </Modal>\n );\n}\n"],"names":["ProvidedThemeCtx","createContext","detectTheme","explicit","provided","attr","_a","useEffectiveTheme","useContext","mode","setMode","useState","useEffect","update","mql","observer","languageExtension","language","javascript","python","CodeEditor","props","theme","extensions","useMemo","EditorView","jsx","CodeMirror","JsonEditor","copied","copy","useCopyToClipboard","json","linter","jsonParseLinter","lintGutter","handleChange","next","parsed","_b","_c","e","_d","jsxs","Fragment","CheckGlyph","CopyGlyph","IconButton","forwardRef","ref","label","children","icon","iconSize","title","onClick","disabled","className","danger","rest","glyph","Icon","SIZE_CLASS","Modal","ariaLabel","onClose","size","titleIcon","subtitle","headerRight","useRef","el","onCancel","r","isExprValue","v","isSecretValue","toWirePart","p","partsToValue","parts","cleaned","RUN_SCOPE_ROOTS","isRunScopeRoot","segment","firstSegment","i","parseRootAnchoredTemplate","s","parseTemplate","hasRefusedChainToken","refs","coalesceOperandRefs","valueToParts","value","renderResult","samples","out","serializeTemplate","STEP_OUTPUT_REF","STEP_META_REF","varLabel","m","meta","chainOperandVarRef","keys","chainLabel","chain","token","text","operand","UNREACHABLE_KEY_CHARS","isRefSafeKey","key","isRefSafePath","path","makeChip","doc","part","renderToggle","span","sigil","raw","parseCoalesceChain","toggle","toggleLabel","x","BLOCK_TAGS","chipToPart","kind","expr","readParts","root","pushText","t","last","walk","node","lastInBlock","tag","isBlock","walkChildren","parent","isBlockParent","child","isFillerBreak","fillBlock","block","caretBlock","editor","sel","range","ensureFillerBreak","isMultilineHost","paintParts","opts","placeCaretAtEnd","insertNodeAtCaret","after","promoteCompletedMarkerAtCaret","offset","openIdx","marker","markerRange","chip","chipToText","ExpressionEditorModal","masked","multiline","options","fieldLabel","onSave","onBind","jsonBinding","setParts","paintGen","setPaintGen","editorRef","focusChipsAfterPaint","setSamples","adding","setAdding","expanded","setExpanded","toggleExpanded","prev","useLayoutEffect","sync","insertPart","hasRenderPart","adoptText","restoreFocus","g","save","saveOnly","closeAdding","vars","secrets","inputs","documents","steps","hasState","template","effectiveSamples","seeded","usedRefs","seen","result","source","cls","composite","st","metaToggle","id","open","fields","o","stepKey","isOpen","wholeBtn","FieldsToggle","META_LEAVES","d","f","docKey","target","nextKind","Copyable","AddValueModal","count","onToggle","onCreate","name","setName","setValue","description","setDescription","error","setError","pending","setPending","noun","submit","excludeSelfStep","selfId","ExpressionOptionsCtx","ExpressionOptionsProvider","inherited","merged","useExpressionOptions","ExpressionInput","onChange","placeholder","readOnly","state","setState","sealed","sealing","setSealing","modalOpen","setModalOpen","wantFocus","wrapperRef","ctxOptions","resolved","sealSecret","syncFromDom","sealPlain","env","onLeave","adopt","VARS_PREFIX","DOCUMENTS_PREFIX","buildResolveScope","sampleValues","testStartState","walkPath","cur","resolveRef","scope","walked","resolvePart","isDollarPath","isDollarExpr","resolveParamValue","deepEqual","a","b","aArr","bArr","arrA","arrB","objA","objB","keysA","keysB","k","foldOne","seg","foldOneAsText","foldResolvedSegments","segments","resolveParamJson","resolveVarsJson","rows","row","isParamVisible","param","getValue","c","flattenParams","list","renderFieldRows","renderOne","rowId","group","makeRenderOne","values","set","effective","SectionField","RepeatField","GroupField","ParamField","ParamsForm","params","flat","visible","main","additional","current","PYTHON_CODE_DEFAULT","visibleChildren","ARRAY_ITEM_SCALAR_TYPES","fitsArrayItemFields","groupValue","groupSet","flatChildren","groupEffective","local","groupRenderOne","JsonParamField","synthesized","ArrayField","req","controlId","useId","FxField","siblingLanguage","fallbackDefault","VarsField","MultiSelectField","isNumber","inputType","display","bare","variant","fx","exprOptions","inline","body","bound","boundRef","seed","setText","invalid","setInvalid","pickerOpen","setPickerOpen","onEdit","onValid","clear","restored","preview","valid","selected","selectedKeys","available","labelFor","add","opt","remove","ArrayItemInput","field","ph","item","isObject","items","commit","blank","patchAt","idx","it","j","fv","_","DATA_VAR_TYPES","coerceVarValue","type","varValueToText","patch","_key","units","durationPattern","WaitEditor","duration","single","lastUnit","setLastUnit","setTarget","LABEL_OVERRIDES","categoryLabel","slug","known","word","deriveCategories","apps","counts","app","matchesCategories","cats","edgeVisuals","when","runState","lane","runClass","ERROR_SOURCE_HANDLE","sourceHandleForLane","laneForSourceHandle","handleId","INTERNAL_APP_PREFIX","CONTROL_APP","SCRIPT_APP","DATA_APP","TRIGGER_APP","HTTP_APP","WEBHOOK_APP","SCHEDULER_APP","RESPOND_APP","CALL_APP","DOCUMENT_APP","TEMPLATE_APP","isInternalApp","isControlApp","isTriggerApp","DEFAULT_NODE_PORTS","portCount","resolvePorts","layers","inn","l","nodePortsForStep","step","lookup","action","internalNodeDef","ICON_TRIGGER","ICON_IF","ICON_FOREACH","ICON_PARALLEL","ICON_WAIT","ICON_SCHEDULER","ICON_SCRIPT","ICON_DATA","ICON_HTTP","ICON_WEBHOOK","ICON_RESPOND","ICON_AGGREGATE","ICON_CALL","ICON_DOCUMENT","ICON_TEMPLATE","INTERNAL_NODES","internalNodeLabel","internalNodeIcon","internalNodeParams","internalNodeDefaults","sameAppsPageQuery","initialAppsPageState","query","generation","dedupeAppend","existing","incoming","added","appsPageReducer","nonAdvancing","hasMore","excludeInternalApps","nextIdBatch","ids","requested","batchSize","batch","mergeResolvedApps","AppIcon","src","srcDark","brandColor","displaySrc","brokenSrc","setBrokenSrc","initials","Ctx","W6WUIProvider","api","content","useW6WApi","WorkflowProjectCtx","WorkflowProjectProvider","project","useWorkflowProject","CHIP_VISIBLE_BUDGET","DEFAULT_PAGE_LIMIT","SEARCH_DEBOUNCE_MS","AppPicker","onSelectApp","filter","searchPlaceholder","emptyMessage","search","emptyAction","providedApps","categoryFilter","category","pageLimit","loadPage","supplied","paged","loadPageRef","fetchedApps","setFetchedApps","legacyError","setLegacyError","listApps","canceled","pageState","dispatch","useReducer","inputValue","setInputValue","debouncedQuery","setDebouncedQuery","generationRef","abortRef","fetchPage","useCallback","cursor","custom","listAppsPage","controller","request","page","loadMore","retry","selectedCats","setSelectedCats","catsExpanded","setCatsExpanded","host","rawApps","fatalError","loadingMore","pageError","pagedInitialLoading","connectable","base","chips","withinBudget","pinnedOverflow","collapsedChips","hiddenChipCount","displayedChips","toggleCat","clearCats","catFiltered","sorted","q","searchActive","categoryEmpty","AuthFieldsForm","enterSubmitProps","isSecret","POPUP_FEATURES","startOAuthPopup","authorizationUrl","resolve","reject","popup","done","cleanup","onMessage","pollHandle","event","data","NON_TEXT_INPUT_TYPES","isWithinContentEditable","useEnterSubmit","onSubmit","AddConnectionModal","selectedApp","setSelectedApp","resolvingInitial","setResolvingInitial","finish","listAppsByIds","ConnectionConfig","onCreated","auths","setAuths","authKey","setAuthKey","displayName","setDisplayName","credential","setCredential","auth","isOAuth","isZeroCred","requiredMissing","submitDisabled","connectionId","conn","enterSubmit","HELPER_TEXT","RetryPolicyFields","retryOn","attempts","delayMs","backoff","setRetry","NodeConfigForm","config","hasGraph","failureHandling","retryControls","reroute","onError","asFieldDefs","fieldWidget","coerceDefault","fieldsToParams","defs","seedValues","TriggerFillForm","persist","hasFields","setValues","persistWorkflowId","persistStepId","setSeeded","tests","latest","draftValid","setDraftValid","canRun","requiredParamsFilled","run","outcome","err","saved","logs","PropertyEntryForm","shouldUseCombobox","optionHeight","viewportHeight","filterOptions","LIST_STYLE","Combobox","forceSelection","useBox","selectedLabel","setOpen","filtering","setFiltering","active","setActive","rootRef","shown","optId","close","pick","onKeyDown","onBlur","InternalIcon","flowEdgeId","from","to","stepIdError","idClashMessage","lead","involved","laneOf","drawn","sitting","sameLane","mixedLane","successTarget","culprit","cause","COLUMN_WIDTH","ROW_HEIGHT","MARGIN_X","MARGIN_Y","slotPosition","col","computeLayers","edges","layer","maxPasses","passes","changed","preds","max","lastColumn","storedPosition","workflowToFlow","wf","implicitChain","rowsInLayer","nodes","isInternal","flowEdges","relayoutNodes","n","flowToWorkflow","original","savePosition","nodeById","withPosition","stepById","nextSteps","nextEdges","storedViewport","withViewport","vp","slugifyLabel","findChainRoot","hasIncoming","findChainTail","hasOutgoing","suggestStepId","prefix","stepToJson","paramsToJson","MAX_DEPTH","MAX_FIELDS","isPlainObject","declaredOutputFields","output","inferOutputFields","obj","depth","valueAtPath","resolveOutputShape","testOutput","declared","fromSample","fromTest","ancestorIds","rootId","parents","arr","ancestors","stack","projectStepSources","shapes","hasTrigger","isTrigger","_e","shape","upstreamStateSources","editingId","stepBuilderUpstreamSteps","pendingConnect","fetchSeedSources","listStepTests","upstreamSteps","startStateFromSeeds","seeds","hasOutput","stepMetaSampleValues","stepId","useSeedSources","workflowId","enabled","seedSources","setSeedSources","idsKey","CALLABLE_FAMILIES","CALLABLE_GLYPH","CONFIG_VIEW_GLYPHS","ALL_CONFIG_VIEWS","ConfigViewToggle","view","views","btn","StepBuilderModal","onAdd","onDraftChange","appsOnly","callables","initialTab","initialApp","initialAction","initialConnection","initialWith","appsFilter","connectionOnly","onConnected","tab","setTab","selectedNode","setSelectedNode","selectedCallable","setSelectedCallable","readyToUse","useReadyToUse","homeAvailable","CallableStepConfig","ControlStepConfig","AppConnectionOnlyConfig","AppStepConfig","ReadyToUseFlow","CallableList","TriggersFlow","ControlsFlow","DataFlow","UtilitiesFlow","NodeList","onSelect","AppTriggersSection","hasDeclaredTriggers","bounded","legacyApps","setLegacyApps","load","AppTriggerPicker","onBack","triggers","setTriggers","creating","setCreating","minutes","setMinutes","minMinutes","create","triggerKey","intervalMs","createSubscription","clampMinutes","withValues","setWithValues","testable","configView","setConfigView","codeText","setCodeText","paramsCodeText","setParamsCodeText","draftConfig","setDraftConfig","configComplete","committedId","setCommittedId","buildStep","changeConfigView","StepTestRun","family","setItems","setQuery","callableLabel","byLabel","CallableRow","TRIGGER_FIELD_TYPES","triggerFieldsOf","rec","targetId","targetLabel","setFields","fieldsError","setFieldsError","setInputs","wait","setWait","CallableTestRun","check","vals","eff","scoped","groupVals","rowVals","isTestRequired","surface","flag","hideRunButton","startState","onBusyChange","onResult","useImperativeHandle","READY_TO_USE_ID_BATCH","EMPTY_ID_SET","min","connectedIds","setConnectedIds","allApps","setAllApps","fns","setFns","wfs","setWfs","setResolved","requestedIds","setRequestedIds","inFlightIds","setInFlightIds","inFlightRef","setInFlight","inlineIdsRef","wantFns","wantWfs","fail","conns","mountedRef","resolveBatch","firstBatchStartedRef","loadMoreApps","exclude","moreApps","connectedSet","dn","onSelectCallable","column","leftRows","left","right","w","cols","appId","onChangeApp","setConns","actions","setActions","metaError","setMetaError","setConnectionId","actionKey","setActionKey","showConnModal","setShowConnModal","changingConn","setChangingConn","au","co","ac","refetchConns","availableAuths","autoSatisfied","needsConnection","hasConnection","selectedAction","sortedActions","testRequired","testPassed","setTestPassed","setupComplete","canAdd","selectedConn","showConnPicker","connectionSatisfied","VIEWS","isValuesMap","onValidityChange","initialView","setView","showJson","toJsonText","validRef","emitValid","openView","ok","ConfirmModal","message","onConfirm","confirmLabel","cancelLabel","destructive"],"mappings":"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"}
|