@w6w/embed 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/README.md +231 -4
  2. package/dist/ConfirmModal-RLbZT5_k.js +181 -0
  3. package/dist/ConfirmModal-RLbZT5_k.js.map +1 -0
  4. package/dist/CreateFunctionModal-DRsFx-FB.js +221 -0
  5. package/dist/CreateFunctionModal-DRsFx-FB.js.map +1 -0
  6. package/dist/DocumentFormModal-BExK1V-B.js +89 -0
  7. package/dist/DocumentFormModal-BExK1V-B.js.map +1 -0
  8. package/dist/ImportSpecModal-BDQIf6rg.js +136 -0
  9. package/dist/ImportSpecModal-BDQIf6rg.js.map +1 -0
  10. package/dist/W6WEmbedProvider.d.ts +22 -4
  11. package/dist/WorkflowEditor-DlbVv6Fs.js +854 -0
  12. package/dist/WorkflowEditor-DlbVv6Fs.js.map +1 -0
  13. package/dist/api-calls--JHyif6a.js +107 -0
  14. package/dist/api-calls--JHyif6a.js.map +1 -0
  15. package/dist/apps-1FNUwbGv.js +77 -0
  16. package/dist/apps-1FNUwbGv.js.map +1 -0
  17. package/dist/callables-3mFrMVG_.js +151 -0
  18. package/dist/callables-3mFrMVG_.js.map +1 -0
  19. package/dist/chrome/index.d.ts +6 -0
  20. package/dist/chrome/workspace.d.ts +29 -1
  21. package/dist/coerce-input-BicYr7nc.js +139 -0
  22. package/dist/coerce-input-BicYr7nc.js.map +1 -0
  23. package/dist/connections-CjjYeRqb.js +78 -0
  24. package/dist/connections-CjjYeRqb.js.map +1 -0
  25. package/dist/document-sources-C0grrtdq.js +86 -0
  26. package/dist/document-sources-C0grrtdq.js.map +1 -0
  27. package/dist/draft/index.d.ts +3 -1
  28. package/dist/draft/use-callable-draft.d.ts +65 -0
  29. package/dist/draft/workflow-save.d.ts +3 -0
  30. package/dist/draft.mjs +9 -5
  31. package/dist/draft.mjs.map +1 -1
  32. package/dist/editor/CallableEditorFrame.d.ts +33 -0
  33. package/dist/editor/EditorShell.d.ts +16 -0
  34. package/dist/editor/EndpointCards.d.ts +56 -0
  35. package/dist/editor/EndpointEditor.d.ts +26 -0
  36. package/dist/editor/FunctionEditor.d.ts +21 -0
  37. package/dist/editor/InputListEditor.d.ts +29 -0
  38. package/dist/editor/TargetSelector.d.ts +30 -0
  39. package/dist/editor/TargetSelector.types.d.ts +62 -0
  40. package/dist/editor/editor-apps.d.ts +8 -2
  41. package/dist/editor/types.d.ts +57 -0
  42. package/dist/editor-apps-BdenSV1o.js +95 -0
  43. package/dist/editor-apps-BdenSV1o.js.map +1 -0
  44. package/dist/editor-tools-RxmY5iyi.js +1279 -0
  45. package/dist/editor-tools-RxmY5iyi.js.map +1 -0
  46. package/dist/editor.mjs +2 -2166
  47. package/dist/editor.mjs.map +1 -1
  48. package/dist/editors/DocumentEditor.d.ts +20 -0
  49. package/dist/editors/doc-format.d.ts +3 -0
  50. package/dist/editors.d.ts +12 -0
  51. package/dist/editors.mjs +1313 -0
  52. package/dist/editors.mjs.map +1 -0
  53. package/dist/embed-status.d.ts +20 -0
  54. package/dist/endpoints-B2ynbZo-.js +227 -0
  55. package/dist/endpoints-B2ynbZo-.js.map +1 -0
  56. package/dist/forms/CreateEndpointModal.d.ts +54 -0
  57. package/dist/forms/CreateFunctionModal.d.ts +55 -0
  58. package/dist/forms/DocumentFormModal.d.ts +8 -0
  59. package/dist/forms/SecretsManager.d.ts +12 -0
  60. package/dist/forms/VarsManager.d.ts +29 -0
  61. package/dist/forms.d.ts +6 -0
  62. package/dist/forms.mjs +407 -0
  63. package/dist/forms.mjs.map +1 -0
  64. package/dist/index.d.ts +3 -1
  65. package/dist/index.mjs +153 -50
  66. package/dist/index.mjs.map +1 -1
  67. package/dist/lib/callable-record.d.ts +21 -0
  68. package/dist/lib/coerce-input.d.ts +6 -0
  69. package/dist/lib/endpoint-editor.d.ts +23 -0
  70. package/dist/lib/index.d.ts +7 -0
  71. package/dist/lib/input-coverage.d.ts +28 -0
  72. package/dist/lib/input-seeding.d.ts +67 -0
  73. package/dist/lib/rail-settings.d.ts +3 -3
  74. package/dist/lib/recent-activity.d.ts +128 -0
  75. package/dist/lib/target-fields.d.ts +168 -0
  76. package/dist/lib/workflow-blank.d.ts +2 -0
  77. package/dist/lib.mjs +70 -48
  78. package/dist/lib.mjs.map +1 -1
  79. package/dist/lists/ActivitySummary.d.ts +29 -0
  80. package/dist/lists/CallableKindList.d.ts +34 -0
  81. package/dist/lists/ConnectionDetail.d.ts +17 -0
  82. package/dist/lists/ConnectionList.d.ts +16 -0
  83. package/dist/lists/DocumentList.d.ts +29 -0
  84. package/dist/lists/EndpointList.d.ts +19 -0
  85. package/dist/lists/FunctionList.d.ts +18 -0
  86. package/dist/lists/ReliabilityBoard.d.ts +23 -0
  87. package/dist/lists/RunHistory.d.ts +11 -0
  88. package/dist/lists/ServiceDetail.d.ts +20 -0
  89. package/dist/lists/WorkflowList.d.ts +19 -0
  90. package/dist/lists/vendor-history.d.ts +40 -0
  91. package/dist/lists.d.ts +20 -0
  92. package/dist/lists.mjs +1185 -0
  93. package/dist/lists.mjs.map +1 -0
  94. package/dist/project-context-BiCjv_E3.js +25 -0
  95. package/dist/project-context-BiCjv_E3.js.map +1 -0
  96. package/dist/project-context.d.ts +15 -1
  97. package/dist/rail/CallableRail.d.ts +12 -0
  98. package/dist/rail/CallableWorkspace.d.ts +16 -0
  99. package/dist/rail/SettingsTool.d.ts +7 -1
  100. package/dist/rail/settings-sections.d.ts +2 -2
  101. package/dist/rail-settings-XYGToh00.js +111 -0
  102. package/dist/rail-settings-XYGToh00.js.map +1 -0
  103. package/dist/rail.d.ts +11 -0
  104. package/dist/rail.mjs +35 -0
  105. package/dist/rail.mjs.map +1 -0
  106. package/dist/repos/api-calls.d.ts +4 -0
  107. package/dist/repos/apps.d.ts +14 -0
  108. package/dist/repos/callables.d.ts +91 -0
  109. package/dist/repos/connections.d.ts +33 -0
  110. package/dist/repos/dashboard.d.ts +4 -0
  111. package/dist/repos/endpoints.d.ts +125 -0
  112. package/dist/repos/functions.d.ts +79 -0
  113. package/dist/repos/index.d.ts +10 -0
  114. package/dist/repos/reliability.d.ts +42 -0
  115. package/dist/repos/saved-tests.d.ts +46 -0
  116. package/dist/repos/spec-export.d.ts +23 -0
  117. package/dist/repos/workflows.d.ts +138 -0
  118. package/dist/repos.mjs +174 -88
  119. package/dist/repos.mjs.map +1 -1
  120. package/dist/settings-rail--GdRMusb.js +33 -0
  121. package/dist/settings-rail--GdRMusb.js.map +1 -0
  122. package/dist/slug-C4ktDPdy.js +315 -0
  123. package/dist/slug-C4ktDPdy.js.map +1 -0
  124. package/dist/spec-export-Cf3VQSQS.js +176 -0
  125. package/dist/spec-export-Cf3VQSQS.js.map +1 -0
  126. package/dist/spec-import-CjmxyZDR.js +465 -0
  127. package/dist/spec-import-CjmxyZDR.js.map +1 -0
  128. package/dist/step-tests-CivICmTq.js +18 -0
  129. package/dist/step-tests-CivICmTq.js.map +1 -0
  130. package/dist/trigger-preview-VPkrryDl.js +120 -0
  131. package/dist/trigger-preview-VPkrryDl.js.map +1 -0
  132. package/dist/use-callable-draft-zHLpcr-b.js +271 -0
  133. package/dist/use-callable-draft-zHLpcr-b.js.map +1 -0
  134. package/dist/{use-workflow-draft-oI02dsP-.js → use-workflow-draft-DzAyUeA6.js} +48 -46
  135. package/dist/use-workflow-draft-DzAyUeA6.js.map +1 -0
  136. package/dist/vault-BSEWhMYC.js +117 -0
  137. package/dist/vault-BSEWhMYC.js.map +1 -0
  138. package/dist/workflow-blank-DyL3_RUA.js +14 -0
  139. package/dist/workflow-blank-DyL3_RUA.js.map +1 -0
  140. package/package.json +34 -5
  141. package/src/styles.css +408 -1
  142. package/dist/project-context-Dbk0Gr1K.js +0 -16
  143. package/dist/project-context-Dbk0Gr1K.js.map +0 -1
  144. package/dist/slug-ByKQgxrf.js +0 -642
  145. package/dist/slug-ByKQgxrf.js.map +0 -1
  146. package/dist/spec-import-HgO7ZkLZ.js +0 -898
  147. package/dist/spec-import-HgO7ZkLZ.js.map +0 -1
  148. package/dist/use-workflow-draft-oI02dsP-.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkflowEditor-DlbVv6Fs.js","sources":["../src/chrome/ExecutionProfileHeader.tsx","../src/chrome/history-open-run.ts","../src/chrome/HistoryModal.tsx","../src/chrome/HistoryButton.tsx","../src/chrome/JsonToggle.tsx","../src/editor/EditorShell.tsx","../src/editor/WorkflowSettingsModal.tsx","../src/editor/definition.ts","../src/editor/WorkflowEditor.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\n\n/**\n * `ExecutionProfileHeader` — the ONE editor header every execution profile's\n * editor mounts (T3.1.1, `building-blocks.md` §Profile building blocks\n * §Mirror).\n *\n * Extracted verbatim from `WorkflowsPage.tsx`'s full-bleed editor head, which\n * is the presentation of record: back control, title, actions. Two hosts use\n * it with two title CONFIGURATIONS, never two headers:\n * - `WorkflowsPage.tsx` — an inline-editable, controlled name input\n * (`editable: true`); back clears the `?edit=` search param; the action row\n * (run / stop / publish / JSON / settings) stays host-owned and arrives as\n * `actions`.\n * - `CallablePage.tsx`'s `CallableEditorChrome` — a Function/Endpoint\n * read-only heading (`editable: false`) with the `incomplete` badge passed\n * as `titleAdornment`, and the host's own JSON toggle then Save button as\n * `actions`.\n *\n * Presentation only: no query, mutation or navigation logic lives here — every\n * callback (`onBack`, `onChange`, `onBlur`) and every node in the action row is\n * the host's, mirroring the `ConnectionHeader.tsx` action-slot precedent.\n *\n * The rendered DOM of the Workflow editor's header is byte-for-byte what it\n * was before the extraction (`wf-fullbleed-head` / `wf-back-btn` /\n * `wf-title-input` / `wf-head-actions`, every `data-testid`, the `aria-label`\n * and the attribute order), which is what `styles.css`'s\n * `.wf-fullbleed-head input.wf-title-input` ancestor specificity and the\n * workflow header screenshot guard both depend on.\n */\n\n/** The editable title variant: the Workflow editor's inline-editable name. */\nexport interface EditableProfileTitle {\n /** The controlled value. */\n value: string;\n /** Called with the new text on every keystroke. */\n onChange: (next: string) => void;\n /** Called when the field loses focus — the Workflow host saves here. */\n onBlur: () => void;\n /** Shown while the value is empty; also the field's minimum sizing basis. */\n placeholder: string;\n /** The `maxLength` the input carries. */\n maxLength: number;\n /** The input's accessible name. */\n ariaLabel: string;\n}\n\n/** The read-only title variant: a Function/Endpoint editor's heading text. */\nexport interface ReadOnlyProfileTitle {\n value: string;\n}\n\n/** Which title the host mounts. The discriminant is `editable`. */\nexport type ExecutionProfileTitle =\n | ({ editable: true } & EditableProfileTitle)\n | ({ editable: false } & ReadOnlyProfileTitle);\n\n/**\n * The editable title field itself. Extracted so the input's own JSX — and the\n * `size` expression `src/lib/__tests__/workflow-title-size.test.ts` extracts\n * and RUNS — lives in one readable place. `size` is capped at the literal 80\n * (the same cap `maxLength` carries on the workflow host), independently of\n * `maxLength`: a name longer than 80 characters can only ever come from the\n * server, so `maxLength` alone would leave a pre-existing long name overflowing\n * its header.\n */\nfunction EditableTitle({ title }: { title: EditableProfileTitle }) {\n const { value, placeholder, maxLength, ariaLabel, onChange, onBlur } = title;\n return (\n <input\n className=\"wf-title-input\"\n value={value}\n placeholder={placeholder}\n maxLength={maxLength}\n size={Math.min(Math.max(value.length, placeholder.length), 80)}\n aria-label={ariaLabel}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n />\n );\n}\n\nexport interface ExecutionProfileHeaderProps {\n /** The back control's click handler — host-owned (the Workflow host clears\n * `?edit=`; `CallableEditorChrome` navigates to the kind's listing). */\n onBack: () => void;\n /** The back control's visible text — host-owned copy (`\"← Workflows\"`,\n * `descriptor.editor.backLabel`). */\n backLabel: string;\n /** Editable (Workflow) or read-only (Function/Endpoint) title. */\n title: ExecutionProfileTitle;\n /** Rendered immediately after a read-only title — the `incomplete` badge. */\n titleAdornment?: ReactNode;\n /** The host's action row (buttons only; this component owns the wrapper). */\n actions: ReactNode;\n}\n\nexport function ExecutionProfileHeader({\n onBack,\n backLabel,\n title,\n titleAdornment,\n actions,\n}: ExecutionProfileHeaderProps) {\n return (\n <div className=\"wf-fullbleed-head\">\n <button\n type=\"button\"\n className=\"muted wf-back-btn\"\n data-testid=\"wf-editor-back\"\n onClick={onBack}\n >\n {backLabel}\n </button>\n {title.editable ? (\n <EditableTitle title={title} />\n ) : (\n <h2 className=\"exec-profile-title\">\n {title.value} {titleAdornment}\n </h2>\n )}\n <div className=\"wf-head-actions\" style={{ marginLeft: \"auto\" }}>\n {actions}\n </div>\n </div>\n );\n}\n","import type { CallableKind, ExecutionSummary } from \"../repos/index.ts\";\n\n/**\n * The open-in-editor decision for a History view: only a workflow run has an editor to open, and\n * only when the host supplied `onOpenRun`. The handler closes the modal BEFORE handing the run id\n * to the host (the host's navigation then lands on an unobscured page).\n */\nexport function historyOpenRun(\n kind: CallableKind,\n onOpenRun: ((runId: string) => void) | undefined,\n onClose: () => void,\n): ((execution: ExecutionSummary) => void) | undefined {\n if (kind !== \"workflow\" || onOpenRun === undefined) return undefined;\n return (execution) => {\n onClose();\n onOpenRun(execution.id);\n };\n}\n","/**\n * `HistoryModal` (R-2 / T3.2.1) — the callable's own execution history,\n * opened as a full-page modal OVER the profile instead of away from it: the\n * route and the URL never change, so the editor underneath (unsaved edits,\n * canvas position, selected node) stays exactly as the author left it.\n * Mounted by `HistoryButton` in place of the navigation it used to do.\n *\n * `@w6w/ui`'s `Modal` at `size=\"full\"` (a near-fullscreen work surface,\n * `ui/src/components/Modal.tsx:12`) wraps `HistoryView`, scoped to this one\n * callable (`{ callable: id }`) with `showKind={false}` — a per-callable\n * view already knows its own kind. Filters are LOCAL state, starting empty\n * every time the modal opens, and are never written to the URL (HB10):\n * bookmarking a filtered view only makes sense for the standalone History\n * page, which still owns the URL-backed form.\n *\n * Closeable by ✕ (the `headerRight` button below), Esc (the real `Modal`'s\n * own `cancel` handling) or its backdrop click — all three funnel through\n * the same `onClose`, so the caller's \"focus returns to the History button\"\n * behaviour (`HistoryButton.tsx`) covers every dismissal path.\n *\n * \"Open in visual editor\" only ever applies to a workflow run, and every\n * execution this modal lists already belongs to THIS callable — its scope\n * is `{ callable: id }`, never project-wide — so there is no \"other\n * workflow\" branch to handle here (that one only exists on the project-wide\n * History page, which `HistoryPage.tsx` still owns). Closes the modal and\n * seeds `?run=` on the SAME route; `WorkflowsPage`'s own `[editId, runParam]`\n * effect (T2.4.2 HB7) is what opens the run overlay in place.\n */\nimport { type CallableKind, EMPTY_HISTORY_FILTERS, type HistoryFilters } from \"@w6w/embed/repos\";\nimport { IconButton, Modal } from \"@w6w/ui\";\nimport { useState } from \"react\";\nimport { HistoryView } from \"./HistoryView.tsx\";\nimport { historyOpenRun } from \"./history-open-run.ts\";\n\nexport interface HistoryModalProps {\n kind: CallableKind;\n id: string;\n onClose: () => void;\n /** Open a workflow run in the host's editor; absent ⇒ no open-in-editor affordance. */\n onOpenRun?: (runId: string) => void;\n}\n\nexport function HistoryModal(props: HistoryModalProps) {\n const { kind, id, onClose, onOpenRun } = props;\n const [filters, setFilters] = useState<HistoryFilters>(EMPTY_HISTORY_FILTERS);\n\n const onOpenInEditor = historyOpenRun(kind, onOpenRun, onClose);\n\n return (\n <Modal\n size=\"full\"\n title=\"History\"\n subtitle={id}\n onClose={onClose}\n headerRight={<IconButton icon=\"close\" label=\"Close\" onClick={onClose} />}\n >\n <div className=\"w6w-modal-body\">\n <HistoryView\n scope={{ callable: id }}\n showKind={false}\n filters={filters}\n onFiltersChange={setFilters}\n onOpenInEditor={onOpenInEditor}\n />\n </div>\n </Modal>\n );\n}\n","/**\n * The History affordance in the Function/Endpoint/Workflow editor headers\n * (T2.4.2, reworked by T3.2.1/R-2) — one icon button that opens the\n * callable's own execution history as a full-page modal OVER the profile\n * (`HistoryModal.tsx`) instead of navigating away from it, and refuses to\n * open while that callable has never executed.\n *\n * \"Has it ever executed?\" is `repos/history.ts`'s `useHasExecutedQuery` — the\n * cheap one-row `GET /history?callable=<id>&limit=1` existence probe (D1:\n * caller-scoped, exactly the rows its own History page lists). `hasExecuted`\n * reads `false` while that probe is in flight or has failed, so the button's\n * disabled state can never claim history that isn't there — the same \"no\n * false yes\" rule the hook's own docblock states.\n *\n * FAIL CLOSED WHEN THE ANSWER IS UNREADABLE. The hook assumes the envelope\n * (`{executions, hasMore}`) and dereferences `executions` directly, so a\n * response that is JSON but not that envelope — a bare `[]`, which several\n * older page-guard harnesses return from their catch-all for any unmodelled\n * `GET` — throws DURING RENDER. An uncaught render throw unmounts the whole\n * editor, so a header icon would be able to take the page down. The boundary\n * below keeps that failure inside this component and renders the same button\n * in its disabled state: no history is claimed, no modal is opened, and the\n * editor survives. The envelope-vs-array mismatch itself belongs to T2.3.1's\n * file (`src/repos/history.ts`), which this node must not edit.\n *\n * Chrome is `@w6w/ui`'s `IconButton` — the same borderless glyph-only control\n * `JsonToggle.tsx`'s `JsonToggleButton` renders, so the two header icon buttons\n * read as one family. The glyph is that component's `icon=\"history\"` (T2; the\n * local `HistoryIcon` hand-drawn SVG is gone), named `history` in the shared\n * set because it is the same drawing the left rail's History entry uses.\n *\n * Focus handling (R-2's \"closing it puts the user back exactly where they\n * were\"): the button keeps a ref to its own DOM node and refocuses it the\n * moment the modal reports `onClose`, regardless of which of the modal's own\n * three dismiss paths (✕, Esc, backdrop) fired it.\n */\nimport { type CallableKind, useHasExecutedQuery } from \"@w6w/embed/repos\";\nimport { IconButton } from \"@w6w/ui\";\nimport { Component, type ReactNode, type Ref, useEffect, useRef, useState } from \"react\";\nimport { HistoryModal } from \"./HistoryModal.tsx\";\n\nexport interface HistoryButtonProps {\n kind: CallableKind;\n id: string;\n /** Forwarded to the modal; see `HistoryModalProps.onOpenRun`. */\n onOpenRun?: (runId: string) => void;\n}\n\n/** The chrome itself, shared by the live button and the fail-closed fallback —\n * the fallback must be the SAME control (same test id, same name, same\n * glyph), only disabled, or a caller could tell the two apart by shape. */\nfunction HistoryButtonChrome({\n hasExecuted,\n onClick,\n buttonRef,\n}: {\n hasExecuted: boolean;\n onClick: () => void;\n buttonRef?: Ref<HTMLButtonElement>;\n}) {\n return (\n <IconButton\n ref={buttonRef}\n icon=\"history\"\n data-testid=\"history-button\"\n label=\"Execution history\"\n title={hasExecuted ? \"Execution history\" : \"No executions yet\"}\n disabled={!hasExecuted}\n onClick={onClick}\n />\n );\n}\n\n/** The probe's own render — the only thing that reads the query. Kept separate\n * so a throw from the hook lands on the boundary, not on the page. */\nfunction HistoryButtonProbe({ kind, id, onOpenRun }: HistoryButtonProps) {\n const { hasExecuted } = useHasExecutedQuery(id);\n const [open, setOpen] = useState(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n // Tracks the PREVIOUS `open` so the effect below only fires the moment the\n // modal actually goes from open to closed — never on first mount.\n const wasOpen = useRef(false);\n\n // Deferred to an effect (runs after the modal's `<dialog>` is gone from the\n // DOM) rather than called straight from `onClose`: while the native dialog\n // is still the top-layer modal, it traps focus, so a `.focus()` call fired\n // DURING its own `cancel`/dismiss handling can be silently ignored. Waiting\n // for the post-commit effect sidesteps that race for all three dismiss\n // paths (✕, Esc, backdrop) alike.\n useEffect(() => {\n if (wasOpen.current && !open) buttonRef.current?.focus();\n wasOpen.current = open;\n }, [open]);\n\n return (\n <>\n <HistoryButtonChrome\n hasExecuted={hasExecuted}\n buttonRef={buttonRef}\n onClick={() => setOpen(true)}\n />\n {open && (\n <HistoryModal kind={kind} id={id} onClose={() => setOpen(false)} onOpenRun={onOpenRun} />\n )}\n </>\n );\n}\n\n/** Last-resort boundary: an unreadable history answer disables the button\n * instead of unmounting the editor that hosts it. The fallback's `onClick` can\n * never fire (the button is disabled), so it does not need the router. */\nclass HistoryProbeBoundary extends Component<{ children: ReactNode }, { failed: boolean }> {\n state = { failed: false };\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true };\n }\n\n componentDidCatch(error: unknown): void {\n console.error(\"history probe answer was unreadable; disabling the button\", error);\n }\n\n render(): ReactNode {\n if (this.state.failed) return <HistoryButtonChrome hasExecuted={false} onClick={() => {}} />;\n return this.props.children;\n }\n}\n\nexport function HistoryButton(props: HistoryButtonProps) {\n return (\n <HistoryProbeBoundary>\n <HistoryButtonProbe {...props} />\n </HistoryProbeBoundary>\n );\n}\n","import { IconButton, JsonEditor } from \"@w6w/ui\";\nimport { Modal } from \"./Modal.tsx\";\n\nexport type JsonToggleMode = \"synced\" | \"disconnected\";\n\n/** The header icon button: `IconButton` with the set's `json` glyph — the\n * curly-brace icon, distinct from the `code` `</>` \"Call from code\" icon\n * beside it, so the two stop reading as the same button. The local\n * `JsonIcon` SVG this file used to carry is now `icon=\"json\"` in the shared\n * set. */\nexport function JsonToggleButton(props: { onClick: () => void }) {\n return <IconButton icon=\"json\" onClick={props.onClick} label=\"Edit raw JSON definition\" />;\n}\n\nexport interface JsonToggleProps {\n /** Parent-owned; render nothing when false. */\n open: boolean;\n onClose: () => void;\n /** Modal title. */\n title: string;\n mode: JsonToggleMode;\n /** Parent-owned text; the component keeps NO copy of it. */\n value: string;\n /** Every JsonEditor change, both modes. */\n onChange: (text: string) => void;\n /** JsonEditor's, error ?? null. */\n onValidityChange?: (v: { valid: boolean; error: string | null }) => void;\n /** When non-null: \"Invalid JSON — {invalidReason}\" (Workflow's existing line). */\n invalidReason?: string | null;\n /** Evaluated on `value` every render; non-null → shown in\n * <p className=\"muted small\" data-testid=\"json-toggle-reason\">. */\n guard?: (text: string) => string | null;\n /** disconnected only. */\n onSave?: () => void;\n /** disconnected only. */\n saving?: boolean;\n /** disconnected only; rendered as <div className=\"error\"> inside the dialog. */\n error?: string | null;\n /** JsonEditor aria-label. */\n editorLabel: string;\n}\n\n/**\n * The JSON⇄editor toggle's chrome — the header icon button's dialog, extracted\n * verbatim from `WorkflowsPage.tsx`'s raw-JSON modal (T2.1.1 D-2) so a second\n * host can reuse it in `mode=\"disconnected\"` (T2.1.2). Wraps `@w6w/ui`'s\n * `JsonEditor` and studio's own `Modal` (not `@w6w/ui`'s) — both existing\n * JSON-toggle-shaped precedents in this repo use studio's `Modal`.\n *\n * The component holds NO copy of `value`: every render shows exactly what the\n * parent hands it, which is what keeps a reopened dialog free of a stale\n * snapshot from the previous time it was open.\n */\nexport function JsonToggle(props: JsonToggleProps): JSX.Element | null {\n const {\n open,\n onClose,\n title,\n mode,\n value,\n onChange,\n onValidityChange,\n invalidReason,\n guard,\n onSave,\n saving,\n error,\n editorLabel,\n } = props;\n if (!open) return null;\n\n const guardReason = guard?.(value) ?? null;\n\n return (\n <Modal title={title} onClose={onClose} wide>\n <div className=\"modal-body\">\n <p className=\"muted small\">\n {mode === \"synced\" ? (\n <>\n Edit the raw definition (<code>manifestVersion: \"2\"</code>). Changes sync live to the\n visual editor.\n </>\n ) : (\n \"Save replaces the stored definition.\"\n )}\n </p>\n <JsonEditor\n value={value}\n onChange={onChange}\n onValidityChange={({ valid, error: err }) =>\n onValidityChange?.({ valid, error: err ?? null })\n }\n minHeight=\"420px\"\n aria-label={editorLabel}\n />\n {guardReason && (\n <p className=\"muted small\" data-testid=\"json-toggle-reason\">\n {guardReason}\n </p>\n )}\n {invalidReason && <div className=\"muted small\">Invalid JSON — {invalidReason}</div>}\n {error && <div className=\"error\">{error}</div>}\n </div>\n <div className=\"modal-actions\">\n {mode === \"synced\" ? (\n <button type=\"button\" className=\"btn ghost\" onClick={onClose}>\n Done\n </button>\n ) : (\n <>\n <button type=\"button\" className=\"btn ghost\" onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"btn\"\n data-testid=\"json-toggle-save\"\n disabled={guardReason != null || Boolean(saving)}\n onClick={onSave}\n >\n {saving ? \"Saving…\" : \"Save\"}\n </button>\n </>\n )}\n </div>\n </Modal>\n );\n}\n","/**\n * The editor frame shared by every callable editor: the rail environment, the project expression\n * scope, and (unless `rail={false}`) the workspace + `RightRail`. `WorkflowEditor` uses it; the\n * Function and Endpoint editors reuse it rather than re-inlining the providers.\n *\n * - `rail` omitted / `true`: its OWN nested `WorkspaceProvider` plus a `RightRail` — the editor's\n * rail, and the nested provider is what keeps a host's outer rail empty.\n * - `rail={false}`: no `RightRail`. Inside a `<CallableWorkspace>` the editor publishes into that\n * workspace; with none it mounts its own provider (no rail) so it can still publish and edit.\n */\nimport type { ReactNode } from \"react\";\nimport { type RailTool, RightRail } from \"../chrome/RightRail.tsx\";\nimport { WorkspaceProvider, useHasWorkspace } from \"../chrome/workspace.tsx\";\nimport { ProjectExpressionScope } from \"../rail/ExpressionScope.tsx\";\nimport { editorRailTools } from \"../rail/editor-tools.ts\";\nimport { RailEnvProvider, type RailNavigation } from \"../rail/rail-env.tsx\";\n\nexport interface EditorShellProps {\n /** Resolved project (`null` = none; tools refuse to save). */\n project: string | null;\n onNavigate: (to: RailNavigation) => void;\n /** Default `true`. `false`: render no rail; publish into the enclosing workspace if any. */\n rail?: boolean;\n /** Persisted-rail key; `null` = not yet persistable. */\n storageKey: string | null;\n /** Default {@link editorRailTools}. */\n tools?: readonly RailTool[];\n children: ReactNode;\n}\n\nexport function EditorShell({\n project,\n onNavigate,\n rail = true,\n storageKey,\n tools = editorRailTools,\n children,\n}: EditorShellProps): ReactNode {\n const enclosed = useHasWorkspace();\n const body = (\n <RailEnvProvider project={project} onNavigate={onNavigate}>\n <ProjectExpressionScope project={project}>\n {children}\n {rail && <RightRail tools={tools} storageKey={storageKey} />}\n </ProjectExpressionScope>\n </RailEnvProvider>\n );\n // Own provider when the rail is ours, or when there is no workspace to publish into.\n return rail || !enclosed ? <WorkspaceProvider>{body}</WorkspaceProvider> : body;\n}\n","import {\n type ExprValue,\n ExpressionInput,\n ExpressionOptionsProvider,\n IconButton,\n type SecretValue,\n useExpressionOptions,\n} from \"@w6w/ui\";\nimport { useState } from \"react\";\nimport { Modal } from \"../chrome/Modal.tsx\";\nimport { type WorkflowVariableRow, duplicateKeyIndexes, varsRailFor } from \"../lib/index.ts\";\n\n/** The settings modal's two tabs — General is always the one it opens on. */\nconst SETTINGS_TABS = [\"general\", \"variables\"] as const;\ntype SettingsTab = (typeof SETTINGS_TABS)[number];\n\n/** The `WorkflowVariable.type` union a row's type `<select>` offers. */\nconst VARIABLE_TYPES = [\"string\", \"number\", \"boolean\", \"object\", \"array\"] as const;\n\n/**\n * Per-workflow authoring settings (General) plus the Variables tab (T1.1.5) —\n * the workflow's declared `variables` list, its public input schema (HITL-5).\n * Both General flags are on unless the workflow says otherwise and persist\n * immediately (`saveMeta`, via `onChange`); every Variables edit instead goes\n * through the auto-saver (`onVariablesChange` → `patchMeta`, never an\n * immediate save — see the module docstring's Save path decision).\n */\nexport function WorkflowSettingsModal(props: {\n autoSave: boolean;\n savePosition: boolean;\n variables: WorkflowVariableRow[];\n onClose: () => void;\n onChange: (key: \"autoSave\" | \"savePosition\", value: boolean) => void;\n onVariablesChange: (next: WorkflowVariableRow[]) => void;\n}) {\n const { autoSave, savePosition, variables, onClose, onChange, onVariablesChange } = props;\n // The project's variable names, inherited from the app shell — the base list\n // `varsRailFor` narrows per row below.\n const inheritedVars = useExpressionOptions().vars ?? [];\n const [tab, setTab] = useState<SettingsTab>(\"general\");\n\n function addVariable() {\n onVariablesChange([...variables, { key: \"\" }]);\n }\n function updateVariable(i: number, next: Partial<WorkflowVariableRow>) {\n onVariablesChange(variables.map((v, idx) => (idx === i ? { ...v, ...next } : v)));\n }\n function removeVariable(i: number) {\n onVariablesChange(variables.filter((_, idx) => idx !== i));\n }\n const dupIndexes = duplicateKeyIndexes(variables);\n\n return (\n <Modal title=\"Workflow settings\" onClose={onClose} wide>\n <div className=\"w6w-subtabs\">\n <button\n type=\"button\"\n className={`w6w-subtab${tab === \"general\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"general\")}\n >\n General\n </button>\n <button\n type=\"button\"\n className={`w6w-subtab${tab === \"variables\" ? \" active\" : \"\"}`}\n onClick={() => setTab(\"variables\")}\n >\n Variables\n </button>\n </div>\n\n {tab === \"general\" ? (\n <>\n <div className=\"modal-body\">\n <p className=\"muted small\">\n These settings belong to the workflow, so everyone who opens it gets the same\n behaviour. Both are on unless you turn them off; each change saves straight away.\n </p>\n <label\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--w6w-sp-2)\",\n cursor: \"pointer\",\n }}\n title=\"Save edits as you make them, without pressing Save.\"\n >\n <input\n type=\"checkbox\"\n checked={autoSave}\n onChange={(e) => onChange(\"autoSave\", e.target.checked)}\n />\n <span className=\"muted small\">Auto-save edits</span>\n </label>\n <label\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--w6w-sp-2)\",\n cursor: \"pointer\",\n }}\n title=\"Keep the arrangement of the canvas — where each step sits, and the view you left it at.\"\n >\n <input\n type=\"checkbox\"\n checked={savePosition}\n onChange={(e) => onChange(\"savePosition\", e.target.checked)}\n />\n <span className=\"muted small\">Save step positions and canvas view</span>\n </label>\n </div>\n <div className=\"modal-actions\">\n {/* T1.3.1: Archive/Delete moved to the right rail's Settings tool\n — one consistent Settings surface, same archive-before-delete\n lifecycle, only relocated (D-I0.1-1). See\n `SettingsTool.tsx`'s own module docstring. */}\n <button type=\"button\" className=\"btn ghost\" onClick={onClose}>\n Done\n </button>\n </div>\n </>\n ) : (\n <>\n <div className=\"modal-body\">\n {/* HITL-5: declaring a variable flips this workflow's generated MCP\n tool from a pass-through schema to a declared one — say so. */}\n <p className=\"muted small\">\n Declaring variables here defines this workflow's <strong>public input schema</strong>:\n API and AI (MCP) callers then see exactly these inputs. With none declared, they may\n send anything.\n </p>\n <div className=\"row\" style={{ justifyContent: \"space-between\", alignItems: \"center\" }}>\n <span className=\"muted small\">\n {variables.length === 0\n ? \"No variables declared.\"\n : `${variables.length} variable${variables.length === 1 ? \"\" : \"s\"} declared.`}\n </span>\n <button type=\"button\" className=\"btn ghost\" onClick={addVariable}>\n + Add variable\n </button>\n </div>\n {variables.length > 0 && (\n <ul className=\"list\" data-testid=\"workflow-variables-list\">\n {variables.map((v, i) => (\n <li\n // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional and reorderable\n key={i}\n style={{\n flexDirection: \"column\",\n alignItems: \"stretch\",\n gap: \"var(--w6w-sp-1)\",\n }}\n >\n <div className=\"row\" style={{ alignItems: \"center\", gap: \"var(--w6w-sp-2)\" }}>\n <input\n type=\"text\"\n value={v.key}\n placeholder=\"key\"\n aria-label=\"Variable key\"\n onChange={(e) => updateVariable(i, { key: e.target.value })}\n />\n <select\n value={v.type ?? \"\"}\n aria-label=\"Variable type\"\n onChange={(e) =>\n updateVariable(i, {\n type: (e.target.value || undefined) as WorkflowVariableRow[\"type\"],\n })\n }\n >\n <option value=\"\">(unset)</option>\n {VARIABLE_TYPES.map((t) => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <label\n className=\"row\"\n style={{ gap: \"var(--w6w-sp-1)\", alignItems: \"center\" }}\n >\n <input\n type=\"checkbox\"\n checked={v.required ?? false}\n onChange={(e) => updateVariable(i, { required: e.target.checked })}\n />\n <span className=\"muted small\">required</span>\n </label>\n {/* Narrow `vars` for THIS row only: a variable's default\n may reference the variables declared above it, never\n itself or the ones below. Only that one key is\n contributed — secrets, documents, sample values and the\n callbacks come through from the app shell untouched,\n because the provider layers rather than replaces. */}\n <ExpressionOptionsProvider\n value={{ vars: varsRailFor(variables, i, inheritedVars) }}\n >\n <ExpressionInput\n // Re-key on the list's shape (not just `i`): ExpressionInput\n // seeds its parts once on mount and never again, so when a\n // row is removed and later rows shift up an index, React\n // must remount the widget rather than reuse the instance —\n // otherwise the surviving cell keeps showing the previous\n // occupant's default (see ExpressionInput.tsx:56-57).\n key={`${variables.length}:${i}`}\n value={v.default as ExprValue | string | SecretValue | undefined}\n onChange={(next) => updateVariable(i, { default: next })}\n placeholder=\"default\"\n aria-label=\"Variable default\"\n />\n </ExpressionOptionsProvider>\n <IconButton\n danger\n icon=\"close\"\n label={`Remove variable ${v.key || i + 1}`}\n onClick={() => removeVariable(i)}\n />\n </div>\n {dupIndexes.includes(i) && (\n <span className=\"muted small\" data-testid=\"variable-duplicate\">\n Duplicate key — a later row with the same name wins.\n </span>\n )}\n </li>\n ))}\n </ul>\n )}\n </div>\n <div className=\"modal-actions\">\n <button type=\"button\" className=\"btn ghost\" onClick={onClose}>\n Done\n </button>\n </div>\n </>\n )}\n </Modal>\n );\n}\n","import type { WorkflowStatus } from \"@w6w/sdk\";\nimport type { CallablePolicy, WorkflowSettings, WorkflowVariableRow } from \"../lib/index.ts\";\n\nexport type Parsed = Record<string, unknown> & {\n id?: string;\n name?: string;\n /** D-1: nullable, no backfill; `undefined` when the field is absent from\n * the text entirely — both mean \"no key\" to {@link workflowKeyEditAllowed}\n * (D-3). The rail's Key control (`SettingsTool.tsx`) is the only place\n * this is ever ASSIGNED; this page only ever reads it back. */\n key?: string | null;\n steps?: unknown[];\n status?: WorkflowStatus;\n tags?: string[];\n /** Authoring presentation — rides in the definition, no column of its own. */\n settings?: WorkflowSettings;\n /** Declared public input schema (T1.1.5) — see `workflow-variables.ts`. */\n variables?: WorkflowVariableRow[];\n /**\n * The RUN-level error policy (core Workflow RFC — *Amendment — 2026-08-21:\n * the run-level error handler*). Authored from the right rail's Error\n * handling tool, which this page hands a writer to rather than letting it\n * save independently — see the `useWorkspace` call below.\n */\n retry?: CallablePolicy[\"retry\"];\n onError?: CallablePolicy[\"onError\"];\n reroute?: CallablePolicy[\"reroute\"];\n};\n\n/** Workflow ids: start alphanumeric, then word chars / dots / dashes. */\nexport const ID_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;\n\n/** Placeholder + minimum sizing basis for the inline title field. */\nexport const TITLE_PLACEHOLDER = \"Untitled workflow\";\n","import { useQueries } from \"@tanstack/react-query\";\nimport { ApiError } from \"@w6w/sdk\";\nimport {\n ExecutionLogPanel,\n IconButton,\n isTestRequired,\n requiredParamsFilled,\n useW6WApi,\n} from \"@w6w/ui\";\nimport type { InternalNodeDef } from \"@w6w/ui/flow\";\nimport {\n type ReactNode,\n Suspense,\n lazy,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { ExecutionProfileHeader } from \"../chrome/ExecutionProfileHeader.tsx\";\nimport { HistoryButton } from \"../chrome/HistoryButton.tsx\";\nimport { JsonToggle, JsonToggleButton } from \"../chrome/JsonToggle.tsx\";\nimport { Modal } from \"../chrome/Modal.tsx\";\nimport { useWorkspace } from \"../chrome/workspace.tsx\";\nimport { useEmbedClient, useWorkflowDraft } from \"../draft/index.ts\";\nimport {\n type ActionParamLike,\n type CallablePolicy,\n type TriggerPreview,\n type TriggerPreviewFieldDef,\n type ValidityContext,\n type WorkflowLike,\n type WorkflowStepLike,\n definitionWithPolicy,\n invalidReason,\n policyFromDefinition,\n readSettings,\n readVariables,\n triggerPreviews,\n variablesForSave,\n workflowKeyEditAllowed,\n workflowValid,\n writeSetting,\n} from \"../lib/index.ts\";\nimport { useEditorProject } from \"../project-context.ts\";\nimport type { RailNavigation } from \"../rail/rail-env.tsx\";\nimport {\n classifyCancelError,\n isRunInFlight,\n listStepTests,\n mapRunStateToLogSteps,\n resolveHeaderRunInput,\n runButtonLabel,\n runLevelErrors,\n stepTestsKey,\n useCancelRunMutation,\n useLiveRunQuery,\n usePublishMutation,\n useStartRunMutation,\n useVersionsQuery,\n} from \"../repos/index.ts\";\nimport { EditorShell } from \"./EditorShell.tsx\";\nimport { WorkflowSettingsModal } from \"./WorkflowSettingsModal.tsx\";\nimport { ID_RE, type Parsed, TITLE_PLACEHOLDER } from \"./definition.ts\";\nimport { appActionsKey, useEditorApps } from \"./editor-apps.ts\";\nimport type {\n WorkflowEditorNavigation,\n WorkflowEditorProps,\n WorkflowEditorSlots,\n} from \"./types.ts\";\n\n// The visual editor is code-split — its @xyflow/react payload only loads when\n// the editor is actually open.\nconst WorkflowFlowEditor = lazy(() =>\n import(\"@w6w/ui/flow\").then((m) => ({ default: m.WorkflowFlowEditor })),\n);\n\nfunction EditorBody(props: {\n workflowId: string;\n project: string | null;\n initialRunId?: string;\n onNavigate: (to: WorkflowEditorNavigation) => void;\n slots?: WorkflowEditorSlots;\n}) {\n const { workflowId, project, initialRunId, onNavigate, slots } = props;\n const apiClient = useEmbedClient();\n const api = useW6WApi();\n const [valid, setValid] = useState(true);\n const [validityError, setValidityError] = useState<string | null>(null);\n // Page-level errors only (run, publish, create); the draft's own load/save errors come from\n // `useWorkflowDraft` (`draftError` below).\n const [error, setError] = useState<string | null>(null);\n const [showJson, setShowJson] = useState(false);\n const [showSettings, setShowSettings] = useState(false);\n const [reloading, setReloading] = useState(false);\n\n // D-3/P4: the key the SERVER most recently sent for the row the buffer is showing — what\n // `workflowKeyEditAllowed` compares the parsed text's own `key` against. `undefined` = nothing\n // loaded yet (refuses unconditionally). Captured whenever the buffer equals the server's copy\n // (load, 409 reload, and after a save), never while it holds unsaved edits. State, not a ref:\n // the guard below must change identity for the draft to re-evaluate it.\n const [loadedKey, setLoadedKey] = useState<string | null | undefined>(undefined);\n // Injected into the draft (the hook is headless — these are Studio's own rules).\n // `autoSave` and the publish-validity reason both depend on the parsed text, which the hook\n // itself produces, so they ride refs assigned after the call (one render of lag at most).\n const autoSaveRef = useRef(true);\n const publishReasonRef = useRef<(def: unknown) => string | null>(() => null);\n const saveGuard = useCallback(\n (def: unknown): string | null => {\n const d = def as Parsed;\n if (!ID_RE.test(typeof d.id === \"string\" ? d.id : \"\")) return \"Invalid workflow id.\";\n // D-3/P4: the rail's Key control is the only place a key is ever assigned — this JSON\n // editor must refuse to save a definition whose `key` differs from what was loaded. Folded\n // into the draft's save gate (never a separate `disabled` on the Save button): auto-save\n // reads the same gate, so a guard on the button alone would be bypassed by typing.\n return workflowKeyEditAllowed(loadedKey, d.key).reason;\n },\n [loadedKey],\n );\n // Load, buffer, save, auto-save, flush-on-hide/unmount and the 409 all live in the hook\n // (`../draft`). The project is `useEditorProject`'s answer (prop, else the provider's): with\n // none, the hook refuses to save (`saveBlockedReason`) rather than let the server pick the\n // account default.\n const draft = useWorkflowDraft({\n workflowId,\n project,\n autoSave: autoSaveRef.current,\n // The expression editor holds uncommitted parts in its own local state until its Save\n // button, so saving from under it would persist a workflow without the expression the user\n // is looking at. Read at fire time (opening it changes neither the buffer nor `canSave`).\n canAutoSave: () => !document.querySelector(\".w6w-exprmodal\"),\n saveGuard,\n publishBlockedReason: (def) => publishReasonRef.current(def),\n });\n const json = draft.json;\n const parsed = draft.parsed as Parsed | null;\n const canSave = draft.canSave;\n const dirty = draft.dirty;\n\n // Capture the server's key whenever the buffer equals the server's copy (never while it holds\n // unsaved edits), and forget it while a workflow is loading or failed to load.\n useEffect(() => {\n if (draft.loading || draft.loadError !== null) {\n setLoadedKey(undefined);\n return;\n }\n if (!draft.dirty && parsed) setLoadedKey((parsed.key as string | null | undefined) ?? null);\n }, [draft.loading, draft.loadError, draft.dirty, parsed]);\n\n // \"Keep editing\" dismisses the 409 modal; the draft stays stale (it refuses to save into the\n // conflict) until the author reloads.\n const [staleDismissed, setStaleDismissed] = useState(false);\n useEffect(() => {\n if (!draft.stale) setStaleDismissed(false);\n }, [draft.stale]);\n\n // The \"Saved.\" marker: a save finished without error since the last one began.\n const [saved, setSaved] = useState(false);\n const wasSaving = useRef(false);\n useEffect(() => {\n if (draft.saving) setSaved(false);\n else if (wasSaving.current && draft.error === null) setSaved(true);\n wasSaving.current = draft.saving;\n }, [draft.saving, draft.error]);\n\n // T2.1.1: the run this canvas is currently showing, if any. Reset inside\n // the `workflowId` load effect below, so a run from a previously open\n // workflow never bleeds into a different one's canvas.\n const [activeRunId, setActiveRunId] = useState<string | null>(null);\n\n // Names offered by each step field's expression picker (task 3.2). The vault\n // No project-scope memo here any more. The ƒx rail's vars, secrets,\n // documents, sample values and \"+ Add\"/seal callbacks are INHERITED from\n // `ProjectExpressionScope` (`App.tsx`); `WorkflowFlowEditor` and the settings\n // modal below both read them from context. What this page's editor\n // contributes on top — the upstream `steps` for one node, and the narrowed\n // `vars` rail for a variable's own default row — is added where it is known,\n // not restated here. See `ui/ExpressionScope.tsx`.\n\n // ── T2.1.1: Run/Stop in the visual editor — live poll, canvas feedback, ──\n // ── log panel, read-only lock. See building-blocks.md §G3/§G4/§G6/§5. ────\n const startRunMut = useStartRunMutation();\n const cancelRunMut = useCancelRunMutation();\n const runQuery = useLiveRunQuery(activeRunId);\n const runStatus = runQuery.data?.status;\n const runPollFailed = runQuery.isError;\n const runInFlight = isRunInFlight(runStatus, runPollFailed);\n // 26-10-04-01-fixes I-1: the run log's rows (each carrying its step's error)\n // and the run-level `error`/`stepErrors` the rows don't already show —\n // mapped once per render, shared by the panel's three props.\n const runLogSteps = mapRunStateToLogSteps(\n runQuery.data?.steps as unknown as Parameters<typeof mapRunStateToLogSteps>[0],\n );\n const runLogErrors = runLevelErrors(runQuery.data, runLogSteps);\n // Header Run fetches the trigger's saved fixture before starting the run;\n // the ref guards re-entry synchronously (a second click can land before the\n // re-render that disables the button), the state disables the button.\n const runStartingRef = useRef(false);\n const [runStarting, setRunStarting] = useState(false);\n\n // ── T2.4.2: `?run=<runId>` — the History page's \"Open in visual editor\" ──\n // A workflow run's History row links to `workflows/<id>?run=<runId>`, and\n // THIS editor is what that link opens. The run plumbing above already\n // renders a terminal run exactly like a live one (`useLiveRunQuery` stops\n // polling on a terminal status by itself), so seeding `activeRunId` from the\n // URL is the whole feature — nothing about the poll, the canvas, the\n // read-only lock or the log panel moves.\n //\n // Declared AFTER the `workflowId` load effect on purpose: that effect resets\n // `activeRunId` for the row it is opening, and effects run in declaration\n // order, so on a mount the URL's run wins. Keyed on `[workflowId, initialRunId]`\n // rather than on mount alone, so an in-app transition to `?run=…` while the\n // editor stays mounted (`history.pushState` + `popstate`) still opens the\n // panel.\n // T2.1.1: a run belongs to the row that started it — the draft's load (formerly this page's\n // `workflowId` effect) reset it; declared BEFORE the `?run=` seed below so the URL's run still wins.\n // biome-ignore lint/correctness/useExhaustiveDependencies: `workflowId` is the trigger, not a value read\n useEffect(() => {\n setActiveRunId(null);\n }, [workflowId]);\n // biome-ignore lint/correctness/useExhaustiveDependencies: `workflowId`'s own value is never read below — it exists solely to re-seed the URL's run when the OPEN WORKFLOW changes, not as a value this closure needs (same retrigger-dependency shape as `api/w6wApiFacade.tsx`).\n useEffect(() => {\n if (initialRunId) setActiveRunId(initialRunId);\n }, [workflowId, initialRunId]);\n\n // The run id alone is not enough: a stale or hand-edited `?run=` can name a\n // run belonging to a DIFFERENT workflow, and painting that run's steps on\n // this canvas would be a lie. `RunState` carries its own `workflowId`, so the\n // first answer that names another workflow drops the run instead of\n // rendering it.\n useEffect(() => {\n if (runQuery.data && runQuery.data.workflowId !== workflowId) setActiveRunId(null);\n }, [runQuery.data, workflowId]);\n\n /**\n * T2.1.5: run `action` only once the buffer is saved. `blocked` shows its reason in the banner;\n * `failed` is already surfaced by the draft itself (banner, or the 409 modal via `draft.stale`).\n */\n async function runAfterFlush(action: () => Promise<unknown>) {\n try {\n const r = await draft.flushThen(action);\n if (!r.ok && r.outcome.status === \"blocked\") setError(r.outcome.reason);\n } catch (e) {\n setError(e instanceof ApiError ? e.message : String(e));\n }\n }\n\n async function onRunClick() {\n if (!workflowId || runInFlight || runStartingRef.current) return;\n setError(null);\n runStartingRef.current = true;\n setRunStarting(true);\n try {\n // 26-10-04-01-fixes I-1 (pinned): the manual trigger's latest saved Test-tab\n // values become the run's `input`, verbatim; no fixture (or no trigger,\n // or a failed fetch) sends no `input` key, exactly as before.\n const input = await resolveHeaderRunInput(triggerPreviewList?.[0]?.id, (stepId) =>\n listStepTests(apiClient, workflowId, stepId),\n );\n // T2.1.5 (R-27): the stored row is what runs, so an unsaved edit is saved FIRST. A refused\n // flush (`blocked` reason / `failed` save) never starts the run.\n await runAfterFlush(() =>\n startRunMut\n .mutateAsync({\n id: workflowId,\n variables: {},\n ...(input ? { input } : {}),\n })\n .then((res) => setActiveRunId(res.runId)),\n );\n } finally {\n runStartingRef.current = false;\n setRunStarting(false);\n }\n }\n\n function onStopClick() {\n if (!activeRunId) return;\n cancelRunMut.mutate(activeRunId, {\n onError: (e) => {\n const code = e instanceof ApiError ? e.code : \"\";\n // A `409 run_not_cancelable` means the run already finished before the\n // cancel request landed — reconcile via the next poll, no error banner.\n if (classifyCancelError(code) === \"surface\") {\n setError(e instanceof ApiError ? e.message : String(e));\n }\n },\n });\n // T1.1.1 A1: ask the server to cancel, but reset the LOCAL run state now —\n // the cancel is cooperative (heartbeat-driven) and may land long after the\n // click, so waiting for a poll to observe a terminal status would leave the\n // canvas greyed out in front of the user who just pressed Stop. The request\n // above still goes out, and `onError` still classifies the 409.\n setActiveRunId(null);\n }\n\n /** Replace the editor's contents with the server's copy and re-arm the token. */\n async function reloadFromServer() {\n setReloading(true);\n try {\n await draft.reload();\n setValid(true);\n setValidityError(null);\n setError(null);\n } finally {\n setReloading(false);\n }\n }\n\n // Page-level errors win; the draft's own load/save failure shows otherwise. A 409 is the\n // modal's business, not the banner's.\n const draftFailure = draft.stale ? null : (draft.error ?? draft.loadError);\n const bannerError =\n error ??\n (draftFailure === null\n ? null\n : draftFailure instanceof Error\n ? draftFailure.message\n : String(draftFailure));\n\n // Parse for the visual view + meta fields — the draft already parses (memoized) per edit.\n const flowUsable = parsed !== null && Array.isArray(parsed.steps);\n\n const displayName = (parsed?.displayName as string) ?? \"\";\n // Both flags are ON for a workflow that declares no `settings` — see readSettings.\n const settings = readSettings(parsed?.settings);\n // The Variables tab's rows (T1.1.5) — declaring the workflow's public input\n // schema (HITL-5). `useMemo` because `varsRailFor` runs once per row on\n // every render otherwise.\n const variables = useMemo(() => readVariables(parsed?.variables), [parsed?.variables]);\n // Visible only once something has actually loaded AND the parsed text is\n // real JSON — never flashes \"Workflow not loaded yet\" on a fresh mount\n // before the initial fetch resolves.\n const keyEdit = workflowKeyEditAllowed(loadedKey, parsed?.key);\n const keyGuardReason =\n parsed !== null && loadedKey !== undefined && !keyEdit.allowed ? keyEdit.reason : null;\n\n // ── Publish-time validity gate (T4.2.1) ──────────────────────────────────\n const steps = useMemo<WorkflowStepLike[]>(\n () => (Array.isArray(parsed?.steps) ? (parsed.steps as WorkflowStepLike[]) : []),\n [parsed],\n );\n\n // `INTERNAL_NODES`/`isInternalApp`/`internalNodeParams` resolve from the SAME\n // `import(\"@w6w/ui/flow\")` the canvas's `lazy()` above already triggers (a\n // module-cache hit, not a second bundle) — only needed while the editor is\n // open, same as the canvas itself. Defaults to \"nothing resolved yet\", which\n // fails `hasTrigger`/`actionParamsByKey` closed (invalid) until it lands.\n const [flowHelpers, setFlowHelpers] = useState<{\n internalNodes: InternalNodeDef[];\n isInternalApp: (app: string) => boolean;\n internalNodeParams: (app: string, action: string) => ActionParamLike[];\n // \"Call from code\" trigger preview (T2.2.1) — `TRIGGER_APP`/`asFieldDefs`\n // resolve from the SAME import, no second dynamic import.\n isManualTrigger: (app: string) => boolean;\n asFieldDefs: (fields: unknown) => TriggerPreviewFieldDef[];\n } | null>(null);\n useEffect(() => {\n let canceled = false;\n import(\"@w6w/ui/flow\").then((m) => {\n if (canceled) return;\n setFlowHelpers({\n internalNodes: m.INTERNAL_NODES,\n isInternalApp: m.isInternalApp,\n internalNodeParams: m.internalNodeParams,\n isManualTrigger: (app) => app === m.TRIGGER_APP,\n asFieldDefs: m.asFieldDefs,\n });\n });\n return () => {\n canceled = true;\n };\n }, []);\n\n // \"Call from code\" trigger preview (T2.2.1, HITL-2/HITL-4 pinned): the\n // modal's per-trigger field picker, derived from the SAME `steps` above —\n // no new fetch, no new query key.\n const triggerPreviewList = useMemo<TriggerPreview[] | undefined>(() => {\n if (!flowHelpers) return undefined;\n return triggerPreviews(\n { steps },\n {\n isManualTrigger: flowHelpers.isManualTrigger,\n asFieldDefs: flowHelpers.asFieldDefs,\n },\n );\n }, [flowHelpers, steps]);\n\n // \"A trigger exists\" means a graph STEP whose (app, action) is a trigger\n // node (an `INTERNAL_NODES` entry with `group: \"trigger\"`) — not the\n // workflow's top-level `trigger` field, which `blankDefinition` always\n // seeds and so is truthy unconditionally (rfcs/workflow.md:114).\n const hasTrigger = useMemo(() => {\n if (!flowHelpers) return false;\n const triggerKeys = new Set(\n flowHelpers.internalNodes\n .filter((n) => n.group === \"trigger\")\n .map((n) => `${n.app}::${n.action}`),\n );\n return steps.some((s) => {\n const { app, action } = s.uses ?? {};\n return !!app && !!action && triggerKeys.has(`${app}::${action}`);\n });\n }, [flowHelpers, steps]);\n\n // Unique third-party (non-internal) app ids across the graph, batch-fetched\n // once each — mirrors the per-step fetch WorkflowFlowEditor already does\n // (WorkflowFlowEditor.tsx:~1432), hoisted to page level and de-duplicated.\n const thirdPartyAppIds = useMemo(() => {\n if (!flowHelpers) return [];\n const ids = new Set<string>();\n for (const s of steps) {\n const { app, action } = s.uses ?? {};\n if (app && action && !flowHelpers.isInternalApp(app)) ids.add(app);\n }\n return [...ids];\n }, [flowHelpers, steps]);\n // Registered apps, so the visual editor can render each action node with its\n // owning app's icon, display name, and version — bounded to the ids this\n // graph actually references (src/apps provider, T3.1.2).\n const { byId: fetchedAppsById } = useEditorApps(thirdPartyAppIds);\n const appsList = useMemo(() => [...fetchedAppsById.values()], [fetchedAppsById]);\n const appActionsQueries = useQueries({\n queries: thirdPartyAppIds.map((appId) => ({\n queryKey: appActionsKey(appId),\n queryFn: () => api.getAppActions(appId),\n })),\n });\n\n // Declared params for every step's target, internal (sync) or third-party\n // (fetched above) — keyed `${app}::${action}`, one entry per unique target.\n const actionParamsByKey = useMemo(() => {\n const out: Record<string, ActionParamLike[]> = {};\n if (!flowHelpers) return out;\n for (const s of steps) {\n const { app, action } = s.uses ?? {};\n if (!app || !action) continue;\n const key = `${app}::${action}`;\n if (key in out) continue;\n if (flowHelpers.isInternalApp(app)) {\n out[key] = flowHelpers.internalNodeParams(app, action);\n } else {\n const idx = thirdPartyAppIds.indexOf(app);\n const fetched = idx >= 0 ? appActionsQueries[idx]?.data : undefined;\n out[key] = fetched?.find((a) => a.key === action)?.params ?? [];\n }\n }\n return out;\n }, [flowHelpers, steps, thirdPartyAppIds, appActionsQueries]);\n\n const appsById = useMemo(() => {\n const out: Record<string, unknown> = {};\n for (const [id, a] of fetchedAppsById) out[id] = a;\n return out;\n }, [fetchedAppsById]);\n\n // Only a step whose app is BOTH a real fetched app AND opts into\n // testRequired needs a `listStepTests` fetch — an internal/trigger/control\n // step's app is never a key in `appsById`, so it is never gated.\n const testGatedSteps = useMemo(\n () =>\n steps.filter((s) => {\n const app = s.uses?.app;\n return !!app && app in appsById && isTestRequired(appsById[app]);\n }),\n [steps, appsById],\n );\n const stepTestsQueries = useQueries({\n queries: testGatedSteps.map((s) => ({\n queryKey: stepTestsKey(workflowId, s.id),\n queryFn: () => listStepTests(apiClient, workflowId, s.id),\n enabled: !!workflowId,\n })),\n });\n const testStatus = useMemo(() => {\n const out: Record<string, boolean> = {};\n testGatedSteps.forEach((s, i) => {\n out[s.id] = !!stepTestsQueries[i]?.data?.some((t) => t.lastRunStatus === \"succeeded\");\n });\n return out;\n }, [testGatedSteps, stepTestsQueries]);\n\n // T3.1.1: the Publish button's own published-state, gated the same shape\n // as `stepTestsQueries` above (`!!workflowId`) — never on mount\n // alone. Shares its cache entry with the Settings rail's own History\n // section (same `[\"versions\", \"workflow\", id]` key), so either surface's\n // Publish click refreshes both without a reload.\n const versionsQuery = useVersionsQuery(\"workflow\", workflowId, !!workflowId);\n const publishMut = usePublishMutation(\"workflow\");\n\n const validityCtx = useMemo<ValidityContext>(\n () => ({\n hasTrigger,\n actionParamsByKey,\n appsById,\n testStatus,\n requiredParamsFilled,\n isTestRequired,\n }),\n [hasTrigger, actionParamsByKey, appsById, testStatus],\n );\n const workflowIsValid =\n parsed !== null && workflowValid(parsed as unknown as WorkflowLike, validityCtx);\n const publishInvalidReason =\n parsed !== null ? invalidReason(parsed as unknown as WorkflowLike, validityCtx) : null;\n\n publishReasonRef.current = (def) =>\n def !== null && typeof def === \"object\"\n ? invalidReason(def as unknown as WorkflowLike, validityCtx)\n : null;\n autoSaveRef.current = settings.autoSave;\n\n /** Patch top-level workflow fields, keeping the JSON text as source of truth. */\n function patchMeta(patch: Partial<Parsed>) {\n if (!parsed) return;\n const next: Parsed = { ...parsed, ...patch };\n draft.setJson(JSON.stringify(next, null, 2));\n }\n\n /** Patch top-level fields and persist immediately (for publish/tags edits). */\n function saveMeta(patch: Partial<Parsed>) {\n if (!parsed) return;\n const next: Parsed = { ...parsed, ...patch };\n setError(null);\n void draft.commit(JSON.stringify(next, null, 2));\n }\n\n // The rail's `onPolicyChange` must be referentially stable (see the `useWorkspace` call\n // below) and therefore cannot close over `parsed`/`draft` directly: it reads the live\n // definition and the draft's `commit` through refs.\n const parsedRef = useRef(parsed);\n parsedRef.current = parsed;\n const commitRef = useRef(draft.commit);\n commitRef.current = draft.commit;\n const saveNowRef = useRef(draft.saveNow);\n saveNowRef.current = draft.saveNow;\n\n // Cmd/Ctrl+S saves while the visual editor is open (mirrors the project\n // switcher's keydown effect in components/Layout.tsx: one guarded document\n // listener, symmetric cleanup).\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.altKey || !(e.metaKey || e.ctrlKey) || e.key.toLowerCase() !== \"s\") return;\n // Suppress the browser's Save Page dialog on every match, including the\n // paths below that decline to save.\n e.preventDefault();\n // The expression editor holds uncommitted parts in its own local state\n // until its Save button, so saving from under it would persist a workflow\n // without the expression the user is looking at.\n if (document.querySelector(\".w6w-exprmodal\")) return;\n if (!canSave) return;\n saveNowRef.current();\n };\n document.addEventListener(\"keydown\", onKey);\n return () => {\n document.removeEventListener(\"keydown\", onKey);\n };\n }, [canSave]);\n\n // T2.1.2: publishes into the right rail's Code/Aliases tools — called on\n // EVERY render, into the `WorkspaceProvider` the outer `WorkflowEditor` mounts.\n //\n // The `policy`/`onPolicyChange` pair is the right rail's Error handling tool\n // (core Workflow RFC — *Amendment — 2026-08-21: the run-level error\n // handler*). The rail does NOT save a workflow itself: this page owns the\n // definition buffer and the draft saves it, so a second writer over the wire\n // would race the canvas and one side's edit would vanish. Handing the rail a\n // writer instead makes its Save fold into the very same JSON text.\n const wfPolicy = useMemo<CallablePolicy>(\n () => (parsed ? policyFromDefinition(parsed) : {}),\n [parsed],\n );\n // Referentially STABLE, as `workspace.tsx` requires: `useWorkspace` keys its\n // publish effect on `JSON.stringify(resource)`, which drops functions, so a\n // callback rebuilt per render would be stored once and then go stale. It\n // reads the current definition through `parsedRef` — always the live value,\n // never a captured one. Persists immediately, exactly like `saveMeta`'s\n // publish/tags edits.\n const onPolicyChange = useCallback((policy: CallablePolicy) => {\n const current = parsedRef.current;\n if (!current) return;\n const next = definitionWithPolicy(current, policy);\n setError(null);\n void commitRef.current(JSON.stringify(next, null, 2));\n }, []);\n\n useWorkspace({\n kind: \"workflow\",\n id: workflowId,\n label: displayName,\n key: parsed?.key ?? undefined,\n triggers: triggerPreviewList,\n policy: wfPolicy,\n onPolicyChange,\n });\n\n return (\n <div className=\"wf-fullbleed\" style={{ height: \"100%\", minWidth: 0, flex: 1 }}>\n {/* T3.1.1: the header itself is `ExecutionProfileHeader` — the SAME\n component a Function/Endpoint editor mounts through\n `CallableEditorChrome`. Everything below is host business: the\n back control (A8, updated by T4.1.1: the editor is its own route\n now, so \"back\" navigates to the LISTING — the sibling params it was\n opened with are kept, since they are the author's), the controlled\n name field that persists on blur, and the action row. */}\n {slots?.header ?? (\n <ExecutionProfileHeader\n onBack={() => onNavigate({ type: \"list\" })}\n backLabel={slots?.backLabel ?? \"← Workflows\"}\n title={{\n editable: true,\n value: displayName,\n placeholder: TITLE_PLACEHOLDER,\n maxLength: 80,\n ariaLabel: \"Workflow name\",\n onChange: (next) => patchMeta({ displayName: next }),\n onBlur: () => {\n if (canSave) draft.saveNow();\n },\n }}\n actions={\n <>\n <IconButton\n icon=\"play\"\n label={runButtonLabel(runStatus, runPollFailed)}\n data-testid=\"wf-run-start\"\n onClick={onRunClick}\n disabled={!workflowId || runInFlight || runStarting || startRunMut.isPending}\n />\n {runInFlight && (\n <IconButton\n icon=\"stop\"\n label=\"Stop this run\"\n data-testid=\"wf-run-stop\"\n onClick={onStopClick}\n disabled={cancelRunMut.isPending}\n />\n )}\n <button\n type=\"button\"\n className={`btn ghost wf-publish${versionsQuery.data?.currentPublishedVersion != null ? \" active\" : \"\"}`}\n data-testid=\"wf-publish\"\n onClick={() => {\n if (!workflowId) return;\n setError(null);\n void runAfterFlush(() => publishMut.mutateAsync(workflowId));\n }}\n disabled={project === null || !canSave || !workflowIsValid || publishMut.isPending}\n title={\n canSave && !workflowIsValid\n ? (publishInvalidReason ?? \"Workflow is not valid\")\n : versionsQuery.data?.currentPublishedVersion != null\n ? \"Published — click to publish a new version\"\n : \"Never published — click to publish\"\n }\n >\n {publishMut.isPending\n ? \"Publishing…\"\n : versionsQuery.data?.currentPublishedVersion != null\n ? \"● Published\"\n : \"Publish\"}\n </button>\n <HistoryButton\n kind=\"workflow\"\n id={workflowId}\n onOpenRun={(runId) => {\n setActiveRunId(runId);\n onNavigate({ type: \"run\", id: workflowId, runId });\n }}\n />\n <JsonToggleButton onClick={() => setShowJson(true)} />\n {/* T2.1.2: \"Call from code\" moved to the right rail's Code tool —\n see the `useWorkspace` call above (this closes the prior\n project's HITL-1: the flow editor now publishes, since the\n gate is the editor's own mount, not the route wrapper that could\n never see this component's route param). */}\n <IconButton\n icon=\"settings\"\n label=\"Workflow settings\"\n onClick={() => setShowSettings(true)}\n />\n {slots?.headerActions}\n </>\n }\n />\n )}\n <div className=\"wf-fullbleed-canvas\">\n <div className=\"wf-run-area\">\n <div className=\"wf-run-canvas\">\n <Suspense fallback={<p className=\"muted\">Loading visual editor…</p>}>\n {flowUsable && parsed ? (\n <WorkflowFlowEditor\n // The parsed cast is safe: onChange only receives shapes we produced.\n value={parsed as unknown as Parameters<typeof WorkflowFlowEditor>[0][\"value\"]}\n onChange={(next) => {\n draft.setJson(JSON.stringify(next, null, 2));\n setValid(true);\n setValidityError(null);\n // T1.1.1 A2.1: an edit to the graph — a canvas edit or a\n // step-config commit from `StepEditModal`, both of which\n // arrive here — means the run this canvas was showing is\n // no longer the thing the author is looking at.\n setActiveRunId(null);\n }}\n apps={appsList}\n project={project ?? undefined}\n height=\"100%\"\n // A4: locked while the run this canvas is showing is still\n // in flight, unlocked again on every terminal status AND\n // when the poll itself gives up or errors.\n readOnly={runInFlight}\n // L-3b: re-frame the graph when the run-log panel docks\n // beside it and again when it leaves — keyed on the panel\n // being MOUNTED (`activeRunId`, same condition as the\n // `wf-run-log` block below), not on `runInFlight` (the\n // panel stays after a terminal status) nor on the run's\n // data (changes every poll tick).\n fitViewKey={activeRunId !== null}\n // A3: each intermediate RunState reaches the canvas as it\n // arrives — the cast crosses the same opaque-`steps`\n // boundary `getRunState`'s own callers already cross (the\n // SDK's console `RunState.steps` is `Record<string,\n // unknown>` on purpose; the server's real per-step shape\n // structurally satisfies `ui`'s narrower `RunState`).\n runState={\n runQuery.data as unknown as Parameters<typeof WorkflowFlowEditor>[0][\"runState\"]\n }\n // T1.1.1 A3: a step test starts → the run this canvas was\n // showing is no longer the thing under test, so drop it on\n // the click rather than waiting for the test's result.\n onTestRun={() => setActiveRunId(null)}\n />\n ) : json === \"\" ? (\n <p className=\"muted\">Loading…</p>\n ) : (\n <p className=\"muted\">Fix the JSON to render the visual editor.</p>\n )}\n </Suspense>\n </div>\n {activeRunId && (\n <div className=\"wf-run-log\" data-testid=\"wf-run-log\">\n <ExecutionLogPanel\n steps={runLogSteps}\n runError={runLogErrors.runError}\n stepErrors={runLogErrors.stepErrors}\n // T1.1.1 A4: the one explicit \"I'm done looking at this run\"\n // control — same lever as Stop, so it must work in the empty\n // branch too (the panel renders its head there as well).\n onDismiss={() => setActiveRunId(null)}\n />\n </div>\n )}\n </div>\n </div>\n {project === null && (\n <div role=\"alert\" className=\"error\" data-testid=\"wf-project-required\">\n No project selected — pass a <code>project</code> prop (or set the provider's project) to\n edit and save this workflow.\n </div>\n )}\n <div className=\"wf-fullbleed-foot\">\n <div className=\"row\" style={{ flexWrap: \"wrap\", alignItems: \"center\" }}>\n {/* Auto-save does not remove this button (it is the escape hatch when\n `autoSave` is off, and the only legible signal of save state when it\n is on): it flushes the pending window now, and greys out once the\n canvas matches the server. */}\n <button\n type=\"button\"\n className=\"btn\"\n disabled={project === null || !canSave || !dirty}\n onClick={draft.saveNow}\n >\n {draft.saving ? \"Saving…\" : \"Save\"}\n </button>\n {saved && <span className=\"ok\">Saved.</span>}\n </div>\n {bannerError && <div className=\"error\">{bannerError}</div>}\n {keyGuardReason && (\n <div className=\"error\" data-testid=\"wf-key-guard\">\n {keyGuardReason}\n </div>\n )}\n </div>\n\n <JsonToggle\n open={showJson}\n onClose={() => setShowJson(false)}\n title={`JSON — ${(parsed?.displayName as string) || \"workflow\"}`}\n mode=\"synced\"\n value={json}\n onChange={(next) => {\n draft.setJson(next);\n // T1.1.1 A2.2 (D-2): the raw-JSON surface is an edit surface\n // too, so it clears the shown run the same way the canvas does.\n setActiveRunId(null);\n }}\n onValidityChange={({ valid: v, error: err }) => {\n setValid(v);\n setValidityError(err);\n }}\n invalidReason={!valid ? validityError : null}\n editorLabel=\"Workflow definition JSON\"\n />\n\n {draft.stale && !staleDismissed && (\n <Modal title=\"This workflow changed on the server\" onClose={() => setStaleDismissed(true)}>\n <div className=\"modal-body\">\n <p className=\"muted small\">\n Someone else — another tab, another session — saved this workflow after you opened it.\n Your save was refused rather than applied, so their work is still intact.\n </p>\n <p className=\"muted small\">\n <strong>Reload from server</strong> replaces what is on this canvas with the saved\n copy; anything you changed here and have not saved is lost.{\" \"}\n <strong>Keep editing</strong> leaves your version exactly as it is — but every save\n will be refused the same way until you reload, so copy out anything you need first.\n </p>\n </div>\n <div className=\"modal-actions\">\n <button type=\"button\" className=\"btn ghost\" onClick={() => setStaleDismissed(true)}>\n Keep editing\n </button>\n <button type=\"button\" className=\"btn\" disabled={reloading} onClick={reloadFromServer}>\n {reloading ? \"Reloading…\" : \"Reload from server\"}\n </button>\n </div>\n </Modal>\n )}\n\n {showSettings && (\n <WorkflowSettingsModal\n autoSave={settings.autoSave}\n savePosition={settings.savePosition}\n variables={variables}\n onClose={() => setShowSettings(false)}\n onChange={(key, value) =>\n saveMeta({ settings: writeSetting(parsed?.settings, key, value) })\n }\n onVariablesChange={(next) => patchMeta({ variables: variablesForSave(next) })}\n />\n )}\n </div>\n );\n}\n\nconst NOOP = (): void => {};\n\n/**\n * The managed workflow editor. The outermost element is `.w6w-embed-root` (pinned for the embed\n * stylesheet); everything the editor renders — header, canvas, modals, rail — stays a descendant of\n * it, and nothing goes through a portal. It fills its host container (`height: 100%`), so the host\n * decides how tall the editor is.\n *\n * `useEditorProject(props.project)` is the ONLY project source: it feeds the draft, the expression\n * scope, the rail environment and the canvas. `null` (no project) refuses — see `EditorBody`.\n */\nexport function WorkflowEditor(props: WorkflowEditorProps): ReactNode {\n const { workflowId, initialRunId, onNavigate = NOOP, slots } = props;\n const project = useEditorProject(props.project);\n const railNavigate = useCallback(\n (to: RailNavigation) => {\n if (to.type === \"list\") onNavigate({ type: \"list\" });\n else if (to.kind === \"workflow\") onNavigate({ type: \"workflow\", id: to.id });\n },\n [onNavigate],\n );\n return (\n <div\n className=\"w6w-embed-root\"\n style={{ display: \"flex\", width: \"100%\", height: \"100%\", minHeight: 0 }}\n >\n <EditorShell\n project={project}\n onNavigate={railNavigate}\n rail={props.rail}\n storageKey={project === null ? null : `w6w.rail.embed.${project}`}\n >\n <EditorBody\n workflowId={workflowId}\n project={project}\n initialRunId={initialRunId}\n onNavigate={onNavigate}\n slots={slots}\n />\n </EditorShell>\n </div>\n );\n}\n"],"names":["EditableTitle","title","value","placeholder","maxLength","ariaLabel","onChange","onBlur","jsx","e","ExecutionProfileHeader","onBack","backLabel","titleAdornment","actions","jsxs","historyOpenRun","kind","onOpenRun","onClose","execution","HistoryModal","props","id","filters","setFilters","useState","EMPTY_HISTORY_FILTERS","onOpenInEditor","Modal","IconButton","HistoryView","HistoryButtonChrome","hasExecuted","onClick","buttonRef","HistoryButtonProbe","useHasExecutedQuery","open","setOpen","useRef","wasOpen","useEffect","_a","Fragment","HistoryProbeBoundary","Component","__publicField","error","HistoryButton","JsonToggleButton","JsonToggle","mode","onValidityChange","invalidReason","guard","onSave","saving","editorLabel","guardReason","JsonEditor","valid","err","EditorShell","project","onNavigate","rail","storageKey","tools","editorRailTools","children","enclosed","useHasWorkspace","body","RailEnvProvider","ProjectExpressionScope","RightRail","WorkspaceProvider","VARIABLE_TYPES","WorkflowSettingsModal","autoSave","savePosition","variables","onVariablesChange","inheritedVars","useExpressionOptions","tab","setTab","addVariable","updateVariable","i","next","v","idx","removeVariable","_","dupIndexes","duplicateKeyIndexes","t","ExpressionOptionsProvider","varsRailFor","ExpressionInput","ID_RE","TITLE_PLACEHOLDER","WorkflowFlowEditor","lazy","m","EditorBody","workflowId","initialRunId","slots","apiClient","useEmbedClient","api","useW6WApi","setValid","validityError","setValidityError","setError","showJson","setShowJson","showSettings","setShowSettings","reloading","setReloading","loadedKey","setLoadedKey","autoSaveRef","publishReasonRef","saveGuard","useCallback","def","d","workflowKeyEditAllowed","draft","useWorkflowDraft","json","parsed","canSave","dirty","staleDismissed","setStaleDismissed","saved","setSaved","wasSaving","activeRunId","setActiveRunId","startRunMut","useStartRunMutation","cancelRunMut","useCancelRunMutation","runQuery","useLiveRunQuery","runStatus","runPollFailed","runInFlight","isRunInFlight","runLogSteps","mapRunStateToLogSteps","_b","runLogErrors","runLevelErrors","runStartingRef","runStarting","setRunStarting","runAfterFlush","action","r","ApiError","onRunClick","input","resolveHeaderRunInput","triggerPreviewList","stepId","listStepTests","res","onStopClick","code","classifyCancelError","reloadFromServer","draftFailure","bannerError","flowUsable","displayName","settings","readSettings","useMemo","readVariables","keyEdit","keyGuardReason","steps","flowHelpers","setFlowHelpers","canceled","app","triggerPreviews","hasTrigger","triggerKeys","s","thirdPartyAppIds","ids","fetchedAppsById","useEditorApps","appsList","appActionsQueries","useQueries","appId","appActionsKey","actionParamsByKey","out","key","fetched","a","appsById","testGatedSteps","isTestRequired","stepTestsQueries","stepTestsKey","testStatus","versionsQuery","useVersionsQuery","publishMut","usePublishMutation","validityCtx","requiredParamsFilled","workflowIsValid","workflowValid","publishInvalidReason","patchMeta","patch","saveMeta","parsedRef","commitRef","saveNowRef","onKey","wfPolicy","policyFromDefinition","onPolicyChange","policy","current","definitionWithPolicy","useWorkspace","runButtonLabel","_c","_d","_e","runId","Suspense","ExecutionLogPanel","writeSetting","variablesForSave","NOOP","WorkflowEditor","useEditorProject","railNavigate","to"],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ import { useQuery as a } from "@tanstack/react-query";
2
+ import { u as r } from "./client-context-CX61Bgw-.js";
3
+ const v = (e) => ["saved-tests", e];
4
+ function f(e, s) {
5
+ return e.console.savedTests.list(s);
6
+ }
7
+ function S(e) {
8
+ const s = r();
9
+ return a({
10
+ queryKey: v(e),
11
+ queryFn: () => f(s, e)
12
+ });
13
+ }
14
+ const T = (e) => ["test-runs", e];
15
+ function h(e, s) {
16
+ return e.console.savedTests.listTestRuns(s);
17
+ }
18
+ function R(e) {
19
+ const s = r();
20
+ return a({
21
+ queryKey: T(e),
22
+ queryFn: () => h(s, e),
23
+ retry: !1
24
+ });
25
+ }
26
+ function F(e, s, t) {
27
+ return e.console.savedTests.create(s, t);
28
+ }
29
+ function Q(e, s, t, n) {
30
+ return e.console.savedTests.update(s, t, n);
31
+ }
32
+ function B(e, s, t) {
33
+ return e.console.savedTests.delete(s, t);
34
+ }
35
+ function A(e, s, t) {
36
+ return e.console.savedTests.recordTestRun(s, t).then(() => {
37
+ });
38
+ }
39
+ const u = 10;
40
+ function q(e) {
41
+ return Array.from(
42
+ { length: Math.ceil(e.length / u) },
43
+ (s, t) => e.slice(t * u, (t + 1) * u)
44
+ );
45
+ }
46
+ function C(e, s, t, n) {
47
+ const o = r();
48
+ return a({
49
+ queryKey: ["reliability-services", e, s, t, n ?? "all"],
50
+ queryFn: () => o.console.reliability.list(e, s, t, n),
51
+ enabled: !!e && s.length > 0 && s.length <= u
52
+ });
53
+ }
54
+ function L(e, s) {
55
+ var d, y;
56
+ const t = r(), n = a({
57
+ queryKey: ["reliability-service-members", e, s],
58
+ queryFn: () => t.console.reliability.listMembers(e, s),
59
+ enabled: !!e
60
+ }), o = q(((d = n.data) == null ? void 0 : d.appIds) ?? []), i = a({
61
+ queryKey: ["reliability-service-batches", e, (y = n.data) == null ? void 0 : y.appIds, s],
62
+ queryFn: async () => {
63
+ const l = [];
64
+ for (const b of o)
65
+ l.push(await t.console.reliability.list(e, b, s));
66
+ return l;
67
+ },
68
+ enabled: !!e && n.data !== void 0
69
+ }), c = i.data ?? [];
70
+ return {
71
+ data: n.data && i.data ? c.length === 0 ? { ...n.data, services: [] } : { ...c[0], services: c.flatMap((l) => l.services) } : void 0,
72
+ error: n.error ?? i.error ?? null,
73
+ isLoading: n.isLoading || i.isLoading
74
+ };
75
+ }
76
+ function M(e, s) {
77
+ const t = r();
78
+ return a({
79
+ queryKey: ["dashboard-stats", e],
80
+ queryFn: () => t.dashboard.stats(s)
81
+ });
82
+ }
83
+ function _(e, s, t) {
84
+ const n = r();
85
+ return a({
86
+ queryKey: ["api-calls", e, s],
87
+ queryFn: () => n.console.apiCalls.list({ project: e, appId: s, limit: t == null ? void 0 : t.limit }),
88
+ enabled: !!e
89
+ });
90
+ }
91
+ export {
92
+ h as a,
93
+ _ as b,
94
+ F as c,
95
+ B as d,
96
+ M as e,
97
+ L as f,
98
+ C as g,
99
+ S as h,
100
+ R as i,
101
+ f as l,
102
+ A as r,
103
+ v as s,
104
+ T as t,
105
+ Q as u
106
+ };
107
+ //# sourceMappingURL=api-calls--JHyif6a.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-calls--JHyif6a.js","sources":["../src/repos/saved-tests.ts","../src/repos/reliability.ts","../src/repos/dashboard.ts","../src/repos/api-calls.ts"],"sourcesContent":["/**\n * Moved from Studio's `repos/saved-tests.ts` (D-12e); the Studio file re-exports these names.\n * The client comes from `useEmbedClient()`.\n *\n * The `saved tests` domain repo — wraps `@w6w/sdk`'s\n * `client.console.savedTests.*` (T2.6.1) in react-query. Mirrors\n * `repos/apps.ts`'s/`repos/connections.ts`'s shape: a query-key factory + a\n * plain, explicit-client fetcher + a convenience hook, for each read; plain\n * functions only for the mutations, which have no studio-page caller of\n * their own — `w6wApiFacade.tsx` is the sole consumer, closing over its own\n * memoized `apiClient`, never through react-query.\n *\n * None of these methods take a `project` scoping parameter — saved tests are\n * scoped by connection/tenant server-side, mirroring `console.connections`'s\n * own host shape.\n */\nimport { useQuery } from \"@tanstack/react-query\";\nimport type { W6WClient } from \"@w6w/sdk\";\nimport type { SavedTest, TestRunSummary } from \"@w6w/sdk/console\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\n\nexport type { SavedTest, TestRunSummary } from \"@w6w/sdk/console\";\n\n// ── saved tests (list) ──────────────────────────────────────────────────\n\nexport const savedTestsKey = (connId: string) => [\"saved-tests\", connId] as const;\n\nexport function listSavedTests(client: W6WClient, connId: string): Promise<SavedTest[]> {\n return client.console.savedTests.list(connId);\n}\n\n/**\n * Shared by BOTH `ConnectionDetailPage.tsx` and `ConnectionActionPage.tsx` —\n * the action page deliberately \"just subscribes\" to the SAME cache entry\n * the list page already populates (no `getSavedTest` method exists). Both call\n * sites MUST go through this hook (or `savedTestsKey` directly) so the key\n * is byte-identical; a hand-spelled second key here would silently defeat\n * the sharing and either double-fetch or leave the tester reading a cold,\n * empty cache.\n */\nexport function useSavedTestsQuery(connId: string) {\n const client = useEmbedClient();\n return useQuery({\n queryKey: savedTestsKey(connId),\n queryFn: () => listSavedTests(client, connId),\n });\n}\n\n// ── test runs (connection history, thin projection) ────────────────────\n\nexport const testRunsKey = (connId: string) => [\"test-runs\", connId] as const;\n\nexport function listTestRuns(client: W6WClient, connId: string): Promise<TestRunSummary[]> {\n return client.console.savedTests.listTestRuns(connId);\n}\n\n/** `retry: false` baked in — matches the sole pre-migration caller's original option\n * (`ConnectionDetailPage.tsx`'s comment: a load failure must not retry-storm the page). */\nexport function useTestRunsQuery(connId: string) {\n const client = useEmbedClient();\n return useQuery({\n queryKey: testRunsKey(connId),\n queryFn: () => listTestRuns(client, connId),\n retry: false,\n });\n}\n\n// ── mutations (facade-only — no studio page calls any of these directly) ──\n\nexport function createSavedTest(\n client: W6WClient,\n connId: string,\n body: { actionKey: string; name: string; values: Record<string, unknown> },\n): Promise<SavedTest> {\n return client.console.savedTests.create(connId, body);\n}\n\nexport function updateSavedTest(\n client: W6WClient,\n connId: string,\n id: string,\n patch: { name?: string; values?: Record<string, unknown> },\n): Promise<SavedTest> {\n return client.console.savedTests.update(connId, id, patch);\n}\n\nexport function deleteSavedTest(client: W6WClient, connId: string, id: string): Promise<void> {\n return client.console.savedTests.delete(connId, id);\n}\n\n/**\n * The SDK returns the REAL created `SavedTestRun` (T2.6.1's design). `@w6w/ui`'s\n * `W6WApi.recordTestRun` is pinned `Promise<void>` (`provider.tsx:168-177`) —\n * discard here, in the repo/adaptation layer, not in the SDK. Verified this\n * discard is load-bearing, not decorative: a scratch `tsc --strict` check\n * confirms `Promise<SavedTestRun>` does NOT structurally satisfy\n * `Promise<void>` (TS's void-return leniency does not extend through a\n * `Promise<T>` wrapper).\n */\nexport function recordTestRun(\n client: W6WClient,\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 return client.console.savedTests.recordTestRun(connId, body).then(() => undefined);\n}\n","/**\n * The `reliability` domain repo — `client.console.reliability.*` in react-query.\n *\n * Moved from Studio's `repos/reliability.ts` (E-1e); the Studio file re-exports these names. The\n * client comes from `useEmbedClient()`. Query keys are byte-identical to the Studio literals, so\n * the board and the service detail page share one project-keyed cache entry.\n *\n * No reliability logic lives here: `state` arrives already decided by the server. Order is the\n * server's too (urgency tier, then `lastCallAt` descending) and is never re-sorted.\n */\nimport { useQuery } from \"@tanstack/react-query\";\nimport type {\n ReliabilityComponentReport,\n ReliabilityErrorMix,\n ReliabilityService,\n ReliabilityServiceMembers,\n ReliabilityServices,\n ReliabilityTimelineEntry,\n} from \"@w6w/sdk/console\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\n\nexport type {\n ReliabilityComponentReport,\n ReliabilityErrorMix,\n ReliabilityService,\n ReliabilityServiceMembers,\n ReliabilityServices,\n ReliabilityTimelineEntry,\n};\n\n/** The server accepts at most ten ids per status request. */\nconst STATUS_BATCH_SIZE = 10;\n\nfunction batches(appIds: readonly string[]): string[][] {\n return Array.from({ length: Math.ceil(appIds.length / STATUS_BATCH_SIZE) }, (_, i) =>\n appIds.slice(i * STATUS_BATCH_SIZE, (i + 1) * STATUS_BATCH_SIZE),\n );\n}\n\n/** A single bounded status request. Callers must pass at most ten app ids. */\nexport function useReliabilityQuery(\n project: string | undefined,\n appIds: readonly string[],\n days?: number,\n limit?: number,\n) {\n const client = useEmbedClient();\n return useQuery({\n queryKey: [\"reliability-services\", project, appIds, days, limit ?? \"all\"],\n queryFn: () => client.console.reliability.list(project!, appIds, days, limit),\n enabled: Boolean(project) && appIds.length > 0 && appIds.length <= STATUS_BATCH_SIZE,\n });\n}\n\n/**\n * Discover a project's service ids, then request their status in batches of at most ten.\n * Membership discovery is identifier-only; every status request names the app ids it may inspect.\n */\nexport function useProjectReliabilityQuery(project: string | undefined, days?: number) {\n const client = useEmbedClient();\n const members = useQuery({\n queryKey: [\"reliability-service-members\", project, days],\n queryFn: () => client.console.reliability.listMembers(project!, days),\n enabled: Boolean(project),\n });\n const appBatches = batches(members.data?.appIds ?? []);\n const boards = useQuery({\n queryKey: [\"reliability-service-batches\", project, members.data?.appIds, days],\n queryFn: async () => {\n const results: ReliabilityServices[] = [];\n // Intentionally serial: never more than ten status probes in flight.\n for (const appIds of appBatches) {\n results.push(await client.console.reliability.list(project!, appIds, days));\n }\n return results;\n },\n enabled: Boolean(project) && members.data !== undefined,\n });\n const results = boards.data ?? [];\n const data =\n members.data && boards.data\n ? results.length === 0\n ? { ...members.data, services: [] }\n : { ...results[0], services: results.flatMap((board) => board.services) }\n : undefined;\n return {\n data,\n error: members.error ?? boards.error ?? null,\n isLoading: members.isLoading || boards.isLoading,\n };\n}\n","/**\n * The `dashboard` domain repo — the public SDK's `client.dashboard.stats` in react-query.\n *\n * Moved from Studio's `repos/dashboard.ts` (E-2): same hook, same key. The client comes from\n * `useEmbedClient()`, so Studio and `W6WEmbedProvider` share one implementation. The query key\n * ships from HERE, not from each caller — `key` distinguishes the \"today\" and \"week\" windows that\n * `<ActivitySummary>` reads through this one hook.\n */\nimport { useQuery } from \"@tanstack/react-query\";\nimport type { DashboardStatsParams } from \"@w6w/sdk/console\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\n\nexport type { DashboardStats, DashboardStatsParams } from \"@w6w/sdk/console\";\n\n/** One of the two account-scoped dashboard windows `<ActivitySummary>` renders. */\nexport function useDashboardStatsQuery(key: \"today\" | \"week\", params: DashboardStatsParams) {\n const client = useEmbedClient();\n return useQuery({\n queryKey: [\"dashboard-stats\", key],\n queryFn: () => client.dashboard.stats(params),\n });\n}\n","/**\n * The `api-calls` domain repo — wraps `@w6w/sdk`'s `client.console.apiCalls.*`\n * in react-query (HITL-6), mirroring `repos/reliability.ts`'s \"thin,\n * read-only domain\" shape: no mutations, no cache-key sharing concern.\n *\n * Query keys include the project so a reliability drill-down cannot reuse call\n * rows from another project.\n */\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\n\nexport type { ApiCallRecord } from \"@w6w/sdk/console\";\n\nexport function useApiCallsQuery(\n project: string | undefined,\n appId: string,\n opts?: { limit?: number },\n) {\n const client = useEmbedClient();\n return useQuery({\n queryKey: [\"api-calls\", project, appId],\n queryFn: () => client.console.apiCalls.list({ project, appId, limit: opts?.limit }),\n enabled: Boolean(project),\n });\n}\n"],"names":["savedTestsKey","connId","listSavedTests","client","useSavedTestsQuery","useEmbedClient","useQuery","testRunsKey","listTestRuns","useTestRunsQuery","createSavedTest","body","updateSavedTest","id","patch","deleteSavedTest","recordTestRun","STATUS_BATCH_SIZE","batches","appIds","_","i","useReliabilityQuery","project","days","limit","useProjectReliabilityQuery","members","appBatches","_a","boards","_b","results","board","useDashboardStatsQuery","key","params","useApiCallsQuery","appId","opts"],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ import { useQuery as s, keepPreviousData as p } from "@tanstack/react-query";
2
+ import { u } from "./client-context-CX61Bgw-.js";
3
+ import { H as l, h as y, m as o, i as a, E as q, j as d } from "./spec-import-CjmxyZDR.js";
4
+ const c = { project: "" };
5
+ function F(e, t, n = l) {
6
+ const i = u();
7
+ return s({
8
+ queryKey: o.list(e ?? c, t, n),
9
+ queryFn: () => a(i, e, t, n),
10
+ enabled: e !== null,
11
+ placeholderData: p
12
+ });
13
+ }
14
+ function Q(e, t) {
15
+ const n = u();
16
+ return s({
17
+ queryKey: o.stats(e ?? c, t),
18
+ queryFn: () => d(n, e, t),
19
+ enabled: e !== null
20
+ });
21
+ }
22
+ function S(e) {
23
+ var i, r;
24
+ const t = u(), n = s({
25
+ queryKey: o.exists(e),
26
+ queryFn: () => a(t, { callable: e }, q, 1)
27
+ });
28
+ return {
29
+ hasExecuted: (((r = (i = n.data) == null ? void 0 : i.executions) == null ? void 0 : r.length) ?? 0) > 0,
30
+ isLoading: n.isLoading
31
+ };
32
+ }
33
+ function h(e) {
34
+ const t = u();
35
+ return s({
36
+ queryKey: o.detail((e == null ? void 0 : e.kind) ?? "function", (e == null ? void 0 : e.id) ?? ""),
37
+ queryFn: () => y(t, e),
38
+ enabled: e !== null
39
+ });
40
+ }
41
+ const f = (e) => ["app-actions", e];
42
+ function g(e, t) {
43
+ return e.console.apps.getActions(t);
44
+ }
45
+ function C(e, t = !0) {
46
+ const n = u();
47
+ return s({
48
+ queryKey: f(e),
49
+ queryFn: () => g(n, e),
50
+ enabled: t
51
+ });
52
+ }
53
+ const E = (e) => ["app", e];
54
+ function A(e, t) {
55
+ return e.console.apps.get(t);
56
+ }
57
+ function b(e, t = !0) {
58
+ const n = u();
59
+ return s({
60
+ queryKey: E(e ?? ""),
61
+ queryFn: () => A(n, e),
62
+ enabled: t
63
+ });
64
+ }
65
+ export {
66
+ f as a,
67
+ E as b,
68
+ g as c,
69
+ b as d,
70
+ h as e,
71
+ S as f,
72
+ A as g,
73
+ F as h,
74
+ Q as i,
75
+ C as u
76
+ };
77
+ //# sourceMappingURL=apps-1FNUwbGv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apps-1FNUwbGv.js","sources":["../src/repos/history.ts","../src/repos/apps.ts"],"sourcesContent":["/**\n * The `history` domain repo (T2.3.1) — thin react-query hooks over\n * `lib/history-query.ts`'s pure fetchers, mirroring `./dashboard.ts`'s\n * shape exactly: the query keys ship from the pure module, not from here or\n * from a caller; every hook is `useEmbedClient()` + one `useQuery`.\n *\n * `lib/history-query.ts` carries every judgment call (URL⇄filter mapping,\n * request params, cache keys, fetchers, detail mapping) so it stays loadable\n * by `node --test`; this file adds nothing but React wiring on top of it.\n */\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\nimport {\n EMPTY_HISTORY_FILTERS,\n type ExecutionSummary,\n HISTORY_PAGE_SIZE,\n type HistoryFilters,\n type HistoryScope,\n getExecutionDetail,\n getHistory,\n getHistoryStats,\n historyKeys,\n} from \"../lib/history-query.ts\";\n\n/** A placeholder scope to key a disabled query by — never fetched, since\n * `enabled` gates on the real (possibly `null`) scope, matching\n * `repos/workflows.ts`'s `useLiveRunQuery(runId ?? \"\")` idiom. */\nconst NO_SCOPE: HistoryScope = { project: \"\" };\n\n/** The project-wide or per-callable execution list, one page at a time.\n * Disabled while `scope` is `null` (no project/callable selected yet).\n * `placeholderData: keepPreviousData` keeps the previous page's rows on\n * screen while a filter/page change is in flight, instead of flashing to\n * an empty list. */\nexport function useHistoryQuery(\n scope: HistoryScope | null,\n f: HistoryFilters,\n limit: number = HISTORY_PAGE_SIZE,\n) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: historyKeys.list(scope ?? NO_SCOPE, f, limit),\n queryFn: () => getHistory(apiClient, scope as HistoryScope, f, limit),\n enabled: scope !== null,\n placeholderData: keepPreviousData,\n });\n}\n\n/** The aggregate stats card above the list — same scope/filters, no paging.\n * Disabled while `scope` is `null`. */\nexport function useHistoryStatsQuery(scope: HistoryScope | null, f: HistoryFilters) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: historyKeys.stats(scope ?? NO_SCOPE, f),\n queryFn: () => getHistoryStats(apiClient, scope as HistoryScope, f),\n enabled: scope !== null,\n });\n}\n\n/** \"Has this callable ever been executed?\" — the cheap existence probe the\n * header's History button uses to decide its disabled state (one row,\n * every filter at its default). `hasExecuted` reads `false` while loading\n * or on error — never a false \"yes\". */\nexport function useHasExecutedQuery(callableId: string): {\n hasExecuted: boolean;\n isLoading: boolean;\n} {\n const apiClient = useEmbedClient();\n const query = useQuery({\n queryKey: historyKeys.exists(callableId),\n queryFn: () => getHistory(apiClient, { callable: callableId }, EMPTY_HISTORY_FILTERS, 1),\n });\n return {\n hasExecuted: (query.data?.executions?.length ?? 0) > 0,\n isLoading: query.isLoading,\n };\n}\n\n/** One execution's full detail, opened from a list row. Disabled while\n * `summary` is `null` (no row selected). */\nexport function useExecutionDetailQuery(summary: ExecutionSummary | null) {\n const apiClient = useEmbedClient();\n return useQuery({\n queryKey: historyKeys.detail(summary?.kind ?? \"function\", summary?.id ?? \"\"),\n queryFn: () => getExecutionDetail(apiClient, summary as ExecutionSummary),\n enabled: summary !== null,\n });\n}\n","/**\n * The per-app Actions repo — what the Target selector and the canvas's step pickers read.\n *\n * Moved from Studio's `repos/apps.ts` (B-3a); the Studio file re-exports these names. The client\n * comes from `useEmbedClient()`. `GET /apps/:id` through `client.console.apps.getActions` is the\n * same payload the W6WApi adapter serves the canvas, and the key is byte-identical to the one\n * the editor and `WorkflowsPage` compose by hand, so every reader shares one cache entry.\n */\nimport { useQuery } from \"@tanstack/react-query\";\nimport type { W6WClient } from \"@w6w/sdk\";\nimport type { ActionDef, AppDetail } from \"@w6w/sdk/console\";\nimport { useEmbedClient } from \"../draft/client-context.ts\";\n\nexport const appActionsKey = (id: string) => [\"app-actions\", id] as const;\n\nexport function getAppActions(client: W6WClient, id: string): Promise<ActionDef[]> {\n return client.console.apps.getActions(id);\n}\n\n/** `enabled` defaults to `true`; a selector passes `app !== \"\"` so an empty app issues nothing. */\nexport function useAppActionsQuery(id: string, enabled = true) {\n const client = useEmbedClient();\n return useQuery({\n queryKey: appActionsKey(id),\n queryFn: () => getAppActions(client, id),\n enabled,\n });\n}\n\n// ── app (detail) ─────────────────────────────────────────────────────────\n\nexport const appKey = (id: string) => [\"app\", id] as const;\n\nexport function getApp(client: W6WClient, id: string): Promise<AppDetail> {\n return client.console.apps.get(id);\n}\n\n/**\n * `id` accepts `string | undefined`: a detail view's app id is `undefined` until its own\n * connection query resolves, so the caller passes `enabled` (its `!!id` guard) instead of\n * `!`-asserting.\n */\nexport function useAppQuery(id: string | undefined, enabled = true) {\n const client = useEmbedClient();\n return useQuery({\n queryKey: appKey(id ?? \"\"),\n queryFn: () => getApp(client, id as string),\n enabled,\n });\n}\n"],"names":["NO_SCOPE","useHistoryQuery","scope","f","limit","HISTORY_PAGE_SIZE","apiClient","useEmbedClient","useQuery","historyKeys","getHistory","keepPreviousData","useHistoryStatsQuery","getHistoryStats","useHasExecutedQuery","callableId","query","EMPTY_HISTORY_FILTERS","_b","_a","useExecutionDetailQuery","summary","getExecutionDetail","appActionsKey","id","getAppActions","client","useAppActionsQuery","enabled","appKey","getApp","useAppQuery"],"mappings":";;;AA2BA,MAAMA,IAAyB,EAAE,SAAS,GAAA;AAOnC,SAASC,EACdC,GACAC,GACAC,IAAgBC,GAChB;AACA,QAAMC,IAAYC,EAAA;AAClB,SAAOC,EAAS;AAAA,IACd,UAAUC,EAAY,KAAKP,KAASF,GAAUG,GAAGC,CAAK;AAAA,IACtD,SAAS,MAAMM,EAAWJ,GAAWJ,GAAuBC,GAAGC,CAAK;AAAA,IACpE,SAASF,MAAU;AAAA,IACnB,iBAAiBS;AAAA,EAAA,CAClB;AACH;AAIO,SAASC,EAAqBV,GAA4BC,GAAmB;AAClF,QAAMG,IAAYC,EAAA;AAClB,SAAOC,EAAS;AAAA,IACd,UAAUC,EAAY,MAAMP,KAASF,GAAUG,CAAC;AAAA,IAChD,SAAS,MAAMU,EAAgBP,GAAWJ,GAAuBC,CAAC;AAAA,IAClE,SAASD,MAAU;AAAA,EAAA,CACpB;AACH;AAMO,SAASY,EAAoBC,GAGlC;;AACA,QAAMT,IAAYC,EAAA,GACZS,IAAQR,EAAS;AAAA,IACrB,UAAUC,EAAY,OAAOM,CAAU;AAAA,IACvC,SAAS,MAAML,EAAWJ,GAAW,EAAE,UAAUS,EAAA,GAAcE,GAAuB,CAAC;AAAA,EAAA,CACxF;AACD,SAAO;AAAA,IACL,gBAAcC,KAAAC,IAAAH,EAAM,SAAN,gBAAAG,EAAY,eAAZ,gBAAAD,EAAwB,WAAU,KAAK;AAAA,IACrD,WAAWF,EAAM;AAAA,EAAA;AAErB;AAIO,SAASI,EAAwBC,GAAkC;AACxE,QAAMf,IAAYC,EAAA;AAClB,SAAOC,EAAS;AAAA,IACd,UAAUC,EAAY,QAAOY,KAAA,gBAAAA,EAAS,SAAQ,aAAYA,KAAA,gBAAAA,EAAS,OAAM,EAAE;AAAA,IAC3E,SAAS,MAAMC,EAAmBhB,GAAWe,CAA2B;AAAA,IACxE,SAASA,MAAY;AAAA,EAAA,CACtB;AACH;AC1EO,MAAME,IAAgB,CAACC,MAAe,CAAC,eAAeA,CAAE;AAExD,SAASC,EAAcC,GAAmBF,GAAkC;AACjF,SAAOE,EAAO,QAAQ,KAAK,WAAWF,CAAE;AAC1C;AAGO,SAASG,EAAmBH,GAAYI,IAAU,IAAM;AAC7D,QAAMF,IAASnB,EAAA;AACf,SAAOC,EAAS;AAAA,IACd,UAAUe,EAAcC,CAAE;AAAA,IAC1B,SAAS,MAAMC,EAAcC,GAAQF,CAAE;AAAA,IACvC,SAAAI;AAAA,EAAA,CACD;AACH;AAIO,MAAMC,IAAS,CAACL,MAAe,CAAC,OAAOA,CAAE;AAEzC,SAASM,EAAOJ,GAAmBF,GAAgC;AACxE,SAAOE,EAAO,QAAQ,KAAK,IAAIF,CAAE;AACnC;AAOO,SAASO,EAAYP,GAAwBI,IAAU,IAAM;AAClE,QAAMF,IAASnB,EAAA;AACf,SAAOC,EAAS;AAAA,IACd,UAAUqB,EAAOL,KAAM,EAAE;AAAA,IACzB,SAAS,MAAMM,EAAOJ,GAAQF,CAAY;AAAA,IAC1C,SAAAI;AAAA,EAAA,CACD;AACH;"}