@oomol-lab/open-flow 0.1.0-beta.50 → 0.1.0-beta.51

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 (33) hide show
  1. package/dist/browser/{createResourceDialog-CSltk-qY.js → createResourceDialog-BDtXpRSt.js} +1 -1
  2. package/dist/browser/flow-authoring-node.d.ts +3 -1
  3. package/dist/browser/flow-authoring.js +39 -3
  4. package/dist/browser/flow-change-schema.d.ts +1 -1
  5. package/dist/browser/flow-change.d.ts +9 -1
  6. package/dist/browser/flow-change.js +38 -3
  7. package/dist/browser/{flowChanges-DbYrpHnS.js → flowChanges-BWSXSnMX.js} +431 -27
  8. package/dist/browser/{flowWorkspace-CjwpbVBR.js → flowWorkspace-DBaq2Eks.js} +459 -190
  9. package/dist/browser/preview.css +20 -0
  10. package/dist/browser/preview.js +556 -21
  11. package/dist/browser/ui.css +20 -0
  12. package/dist/browser/ui.js +4 -3
  13. package/dist/browser/workbench-contract.d.ts +1 -0
  14. package/dist/browser/workbench.css +20 -0
  15. package/dist/browser/workbench.js +133 -22
  16. package/dist/browser/{workbenchSelect-oVujN2z6.js → workbenchSelect-C9kwcUmN.js} +47 -6
  17. package/dist/common/authoringExamples.d.ts +3 -2
  18. package/dist/common/control-api-conformance.js +82 -10
  19. package/dist/common/control-api.d.ts +34 -5
  20. package/dist/common/control-api.js +147 -10
  21. package/dist/common/control-requests.js +23 -1
  22. package/dist/common/flow-encoding.js +30 -5
  23. package/dist/common/flow-semantics.js +87 -2
  24. package/dist/common/integration-trigger.js +16 -1
  25. package/dist/common/mcp.js +82 -10
  26. package/dist/common/poll-trigger.js +16 -1
  27. package/dist/common/provider-triggers.js +16 -1
  28. package/dist/common/run-events.js +25 -1
  29. package/dist/common/scheduler.d.ts +3 -0
  30. package/dist/common/scheduler.js +91 -5
  31. package/dist/common/trigger-contract.d.ts +2 -0
  32. package/dist/common/webhook-trigger.js +16 -1
  33. package/package.json +1 -1
@@ -1144,6 +1144,10 @@
1144
1144
  margin-left: -1px;
1145
1145
  }
1146
1146
 
1147
+ :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .ml-2 {
1148
+ margin-left: calc(var(--spacing) * 2);
1149
+ }
1150
+
1147
1151
  :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .ml-4 {
1148
1152
  margin-left: calc(var(--spacing) * 4);
1149
1153
  }
@@ -1388,6 +1392,10 @@
1388
1392
  max-height: calc(var(--spacing) * 40);
1389
1393
  }
1390
1394
 
1395
+ :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .max-h-48 {
1396
+ max-height: calc(var(--spacing) * 48);
1397
+ }
1398
+
1391
1399
  :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .max-h-56 {
1392
1400
  max-height: calc(var(--spacing) * 56);
1393
1401
  }
@@ -1416,6 +1424,10 @@
1416
1424
  max-height: calc(100dvh - 32px);
1417
1425
  }
1418
1426
 
1427
+ :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .max-h-\[min\(40vh\,280px\)\] {
1428
+ max-height: min(40vh, 280px);
1429
+ }
1430
+
1419
1431
  :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .max-h-\[min\(60dvh\,480px\)\] {
1420
1432
  max-height: min(60dvh, 480px);
1421
1433
  }
@@ -2988,6 +3000,10 @@
2988
3000
  text-decoration-line: underline;
2989
3001
  }
2990
3002
 
3003
+ :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .underline-offset-2 {
3004
+ text-underline-offset: 2px;
3005
+ }
3006
+
2991
3007
  :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .underline-offset-4 {
2992
3008
  text-underline-offset: 4px;
2993
3009
  }
@@ -4837,6 +4853,10 @@
4837
4853
  }
4838
4854
 
4839
4855
  @media (min-width: 48rem) {
4856
+ :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .md\:grid-cols-2 {
4857
+ grid-template-columns: repeat(2, minmax(0, 1fr));
4858
+ }
4859
+
4840
4860
  :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .md\:text-sm {
4841
4861
  font-size: var(--ui-font-size);
4842
4862
  line-height: var(--tw-leading, var(--text-sm--line-height));
@@ -12112,12 +12112,13 @@ function Dialog$1(props) {
12112
12112
  ...props
12113
12113
  });
12114
12114
  }
12115
- function DialogTrigger$1(props) {
12115
+ var DialogTrigger$1 = React.forwardRef(function DialogTrigger(props, ref) {
12116
12116
  return /* @__PURE__ */ jsx(DialogTrigger$2, {
12117
12117
  "data-slot": "dialog-trigger",
12118
- ...props
12118
+ ...props,
12119
+ ref
12119
12120
  });
12120
- }
12121
+ });
12121
12122
  function DialogPortal(props) {
12122
12123
  return /* @__PURE__ */ jsx(DialogPortal$1, {
12123
12124
  "data-slot": "dialog-portal",
@@ -43,6 +43,7 @@ export interface WorkbenchHost {
43
43
  export interface WorkbenchLocation {
44
44
  /** Runs-only source filter. Hosts treat unknown URL values as absent. */
45
45
  readonly runSource?: 'draft' | 'live';
46
+ readonly runId?: string;
46
47
  readonly flowId?: string;
47
48
  readonly view: WorkbenchView;
48
49
  }
@@ -1911,6 +1911,10 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
1911
1911
  margin-left: -1px;
1912
1912
  }
1913
1913
 
1914
+ :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .ml-2 {
1915
+ margin-left: calc(var(--spacing) * 2);
1916
+ }
1917
+
1914
1918
  :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .ml-4 {
1915
1919
  margin-left: calc(var(--spacing) * 4);
1916
1920
  }
@@ -2155,6 +2159,10 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
2155
2159
  max-height: calc(var(--spacing) * 40);
2156
2160
  }
2157
2161
 
2162
+ :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .max-h-48 {
2163
+ max-height: calc(var(--spacing) * 48);
2164
+ }
2165
+
2158
2166
  :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .max-h-56 {
2159
2167
  max-height: calc(var(--spacing) * 56);
2160
2168
  }
@@ -2183,6 +2191,10 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
2183
2191
  max-height: calc(100dvh - 32px);
2184
2192
  }
2185
2193
 
2194
+ :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .max-h-\[min\(40vh\,280px\)\] {
2195
+ max-height: min(40vh, 280px);
2196
+ }
2197
+
2186
2198
  :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .max-h-\[min\(60dvh\,480px\)\] {
2187
2199
  max-height: min(60dvh, 480px);
2188
2200
  }
@@ -3755,6 +3767,10 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
3755
3767
  text-decoration-line: underline;
3756
3768
  }
3757
3769
 
3770
+ :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .underline-offset-2 {
3771
+ text-underline-offset: 2px;
3772
+ }
3773
+
3758
3774
  :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .underline-offset-4 {
3759
3775
  text-underline-offset: 4px;
3760
3776
  }
@@ -5604,6 +5620,10 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
5604
5620
  }
5605
5621
 
5606
5622
  @media (min-width: 48rem) {
5623
+ :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .md\:grid-cols-2 {
5624
+ grid-template-columns: repeat(2, minmax(0, 1fr));
5625
+ }
5626
+
5607
5627
  :where(.open-flow-theme, .open-flow-workbench, .open-flow-canvas-root) .md\:text-sm {
5608
5628
  font-size: var(--ui-font-size);
5609
5629
  line-height: var(--tw-leading, var(--text-sm--line-height));
@@ -1,7 +1,7 @@
1
- import { $t as EmptyTitle, An as connectorActionMetadata, At as flowDependencies, Bn as IconThemeContext, Ct as resetInputValues, Dt as setTriggerConnection, Et as setInputSources, F as deriveAddNodeOptions, Fn as string, Ft as PopoverContent, G as resourceValue, Gt as InputGroup, H as Resource, In as providerIconAppearance, Jt as Empty, K as designerGraph, Kt as InputGroupAddon, L as feishuResourceKind, Ln as ApiError, Mn as invalidResponse, Mt as followWorkbenchLink, Nn as jsonValue, Nt as Switch, Ot as updateTriggerConfig, P as addNodeIntent, Pn as record, Pt as Popover, Qt as EmptyMedia, R as supportsFeishuChatFilter, Rn as controlErrorCode, Rt as PopoverTitle, St as repairNodeNames, Tn as isJsonObject, Tt as setConnectorConnection, V as scopedValue, W as resourceData, X as providerIcon, Xt as EmptyDescription, Yt as EmptyContent, Zt as EmptyHeader, _ as updateTaskAdditionalInputs, _n as WorkbenchClient, _t as setComment, a as deleteSelection, at as Latest, b as updateWebhook, bt as setNodePositions, c as setInputVariable, d as updateNodeIcon, dt as actionWithConnections, en as EventSourcesPage, f as updateNodeName, ft as connectionCatalog, g as updateTask, gn as errorNotice, gt as restoreCanvasPresentation, h as updateSubflow, ht as removeComments, i as createResource, it as revisionView, jn as inputValue, jt as IdTooltip, kn as connection, kt as updateTriggerSchedule, l as updateCondition, m as updateResolution, mt as commentIds, o as nameCreatedNodes, ot as deriveInspectorDiagnostics, p as updateNodeSettings, pt as canvasPresentationChange, qt as InputGroupInput, r as applyFlowChanges, rn as createI18n, s as setInputValue, st as diagnosticItems, t as addNode, tt as RunStore, u as updateNodeDescription, v as updateTaskPorts, vn as randomId, vt as setFlowViewport, wn as triggerOutputDefinitions, wt as setCodeActions, xn as decodeTriggerCatalog, xt as targetPresentation, y as updateValue, yn as allConnectorConnectionsQuery, yt as setNodeContentHidden, z as combineSources, zt as PopoverTrigger } from "./flowChanges-DbYrpHnS.js";
1
+ import { $t as EmptyTitle, An as connection, At as flowDependencies, Ct as resetInputValues, Dt as setTriggerConnection, En as isJsonObject, Et as setInputSources, F as deriveAddNodeOptions, Fn as record, Ft as PopoverContent, G as resourceValue, Gt as InputGroup, H as Resource, In as string, Jt as Empty, K as designerGraph, Kt as InputGroupAddon, L as feishuResourceKind, Ln as providerIconAppearance, Mn as inputValue, Mt as followWorkbenchLink, Nn as invalidResponse, Nt as Switch, Ot as updateTriggerConfig, P as addNodeIntent, Pn as jsonValue, Pt as Popover, Qt as EmptyMedia, R as supportsFeishuChatFilter, Rn as ApiError, Rt as PopoverTitle, St as repairNodeNames, Tn as triggerOutputDefinitions, Tt as setConnectorConnection, V as scopedValue, Vn as IconThemeContext, W as resourceData, X as providerIcon, Xt as EmptyDescription, Yt as EmptyContent, Zt as EmptyHeader, _ as updateTaskAdditionalInputs, _n as WorkbenchClient, _t as setComment, a as deleteSelection, at as Latest, b as updateWebhook, bt as setNodePositions, c as setInputVariable, d as updateNodeIcon, dt as actionWithConnections, en as EventSourcesPage, f as updateNodeName, ft as connectionCatalog, g as updateTask, gn as errorNotice, gt as restoreCanvasPresentation, h as updateSubflow, ht as removeComments, i as createResource, it as revisionView, jn as connectorActionMetadata, jt as IdTooltip, kt as updateTriggerSchedule, l as updateCondition, m as updateResolution, mt as commentIds, o as nameCreatedNodes, ot as deriveInspectorDiagnostics, p as updateNodeSettings, pt as canvasPresentationChange, qt as InputGroupInput, r as applyFlowChanges, rn as createI18n, s as setInputValue, st as diagnosticItems, t as addNode, tt as RunStore, u as updateNodeDescription, v as updateTaskPorts, vn as randomId, vt as setFlowViewport, wn as sampleErrorOutputs, wt as setCodeActions, xn as decodeTriggerCatalog, xt as targetPresentation, y as updateValue, yn as allConnectorConnectionsQuery, yt as setNodeContentHidden, z as combineSources, zn as controlErrorCode, zt as PopoverTrigger } from "./flowChanges-BWSXSnMX.js";
2
2
  import { a as derive, i as compute, l as val } from "./dist-bO8nvHFH.js";
3
3
  import { a as useVal, i as useTranslate, r as useLang, t as I18nProvider } from "./main-BPABKzwN.js";
4
- import { D as FlowChangeError, E as FieldLabel, Fr as Button, L as mapConditionSources, Lr as cn, Mn as Input, N as portsByHandle, O as applyFlowChanges$1, P as resourceNameIssue, R as nodeInputMappings, S as Field, T as FieldGroup, a as DialogContent, c as DialogHeader, d as Tooltip, f as TooltipContent, i as DialogClose, l as DialogTitle, m as TooltipTrigger, n as Icon, o as DialogDescription, q as dequal$1, r as Dialog, s as DialogFooter, t as WorkbenchSelect, w as FieldError, x as Spinner } from "./workbenchSelect-oVujN2z6.js";
4
+ import { D as FlowChangeError, E as FieldLabel, Fr as Button, L as mapConditionSources, Lr as cn, Mn as Input, N as portsByHandle, O as applyFlowChanges$1, P as resourceNameIssue, R as nodeInputMappings, S as Field, T as FieldGroup, a as DialogContent, c as DialogHeader, d as Tooltip, f as TooltipContent, i as DialogClose, l as DialogTitle, m as TooltipTrigger, n as Icon, o as DialogDescription, q as dequal$1, r as Dialog, s as DialogFooter, t as WorkbenchSelect, w as FieldError, x as Spinner } from "./workbenchSelect-C9kwcUmN.js";
5
5
  import { a as toPlainObject } from "./dist-BDBTOgS5.js";
6
6
  import { c as isUiLanguage, d as uiLanguages, l as resolveUiLanguage, u as uiLanguageNames } from "./value-DL_poNiC.js";
7
7
  import { Suspense, lazy, useEffect, useRef, useState } from "react";
@@ -68,6 +68,9 @@ var NavigationStore = class {
68
68
  this.#store = store;
69
69
  this.#view.set(location.view);
70
70
  }
71
+ get runId() {
72
+ return this.#location.view == "runs" ? this.#location.runId : void 0;
73
+ }
71
74
  get runSource() {
72
75
  return this.#location.view == "runs" ? this.#location.runSource : void 0;
73
76
  }
@@ -155,15 +158,19 @@ var NavigationStore = class {
155
158
  #sync;
156
159
  #write(view, replace, options = this.#location) {
157
160
  const flowId = this.#store.workspace.$.flowId.value;
158
- const { runSource } = options;
161
+ const { runSource, runId } = options;
159
162
  const location = {
160
163
  flowId,
161
164
  view: flowId == null ? "design" : view,
162
- ...flowId != null && view == "runs" && runSource != null ? { runSource } : {}
165
+ ...flowId != null && view == "runs" && runSource != null ? { runSource } : {},
166
+ ...flowId != null && view == "runs" && runId != null ? { runId } : {}
163
167
  };
164
168
  if (this.#ready.value && this.#view.value == "runs" && location.view == "runs") {
165
169
  const filter = this.#store.runs.$.filter.value;
166
- if (filter.source != location.runSource) this.#store.runs.applyFilter({
170
+ if (filter.source != location.runSource || filter.runId != location.runId) this.#store.runs.applyFilter(location.runId != filter.runId ? {
171
+ source: location.runSource,
172
+ runId: location.runId
173
+ } : {
167
174
  ...filter,
168
175
  source: location.runSource
169
176
  });
@@ -176,7 +183,7 @@ var NavigationStore = class {
176
183
  }
177
184
  };
178
185
  function sameLocation(left, right) {
179
- return left.flowId == right.flowId && left.view == right.view && left.runSource == right.runSource;
186
+ return left.flowId == right.flowId && left.view == right.view && left.runSource == right.runSource && left.runId == right.runId;
180
187
  }
181
188
  //#endregion
182
189
  //#region src/ui/browser/skeleton.tsx
@@ -189,7 +196,7 @@ function Skeleton({ className, ...props }) {
189
196
  }
190
197
  //#endregion
191
198
  //#region src/workbench/browser/runtime/shell/resourceBrowser.tsx
192
- var CreateResourceDialog = lazy(() => import("./createResourceDialog-CSltk-qY.js"));
199
+ var CreateResourceDialog = lazy(() => import("./createResourceDialog-BDtXpRSt.js"));
193
200
  var languageOptions = uiLanguages.map((language) => ({
194
201
  label: uiLanguageNames[language],
195
202
  value: language
@@ -234,6 +241,56 @@ function formatUpdatedAt(updatedAt, locale) {
234
241
  function clickedRowControl(event) {
235
242
  return event.target instanceof Element && event.target.closest(rowControlSelector) != null;
236
243
  }
244
+ function FlowDeletionImpact({ listeners, failed, onRetry }) {
245
+ const t = useTranslate();
246
+ if (failed) return /* @__PURE__ */ jsxs("div", {
247
+ className: "space-y-2",
248
+ children: [/* @__PURE__ */ jsx("p", {
249
+ role: "alert",
250
+ className: "text-sm text-destructive",
251
+ children: t("sidebar.listenersFailed")
252
+ }), /* @__PURE__ */ jsx(Button, {
253
+ variant: "outline",
254
+ size: "sm",
255
+ onClick: onRetry,
256
+ children: t("errorWorkflow.retry")
257
+ })]
258
+ });
259
+ if (listeners == null) return /* @__PURE__ */ jsx("p", {
260
+ role: "status",
261
+ className: "text-sm text-muted-foreground",
262
+ children: t("sidebar.listenersLoading")
263
+ });
264
+ if (listeners.length == 0) return null;
265
+ return /* @__PURE__ */ jsxs("div", {
266
+ className: "min-w-0 space-y-3 text-sm",
267
+ children: [
268
+ /* @__PURE__ */ jsx("p", { children: t("sidebar.listenersTitle") }),
269
+ /* @__PURE__ */ jsx("ul", {
270
+ className: "m-0 max-h-48 list-none space-y-2 overflow-y-auto p-0",
271
+ children: listeners.map((listener) => /* @__PURE__ */ jsxs("li", {
272
+ className: "break-words",
273
+ children: [
274
+ /* @__PURE__ */ jsx("span", {
275
+ className: "font-medium",
276
+ children: listener.flowName
277
+ }),
278
+ " / ",
279
+ listener.nodeName,
280
+ !listener.enabled && /* @__PURE__ */ jsx("span", {
281
+ className: "ml-2 text-muted-foreground",
282
+ children: t("sidebar.listenerDisabled")
283
+ })
284
+ ]
285
+ }, `${listener.flowId}/${listener.nodeId}`))
286
+ }),
287
+ /* @__PURE__ */ jsx("p", {
288
+ className: "text-muted-foreground",
289
+ children: t("sidebar.listenersImpact")
290
+ })
291
+ ]
292
+ });
293
+ }
237
294
  function FlowItem({ badge, busy, flow, href, onSelect, store }) {
238
295
  const [root, setRoot] = useState(null);
239
296
  const renameAnchor = useRef(null);
@@ -244,6 +301,26 @@ function FlowItem({ badge, busy, flow, href, onSelect, store }) {
244
301
  const t = useTranslate();
245
302
  const [mode, setMode] = useState("idle");
246
303
  const [name, setName] = useState(flow.name);
304
+ const [listeners, setListeners] = useState();
305
+ const [listenersFailed, setListenersFailed] = useState(false);
306
+ const [listenersRetry, setListenersRetry] = useState(0);
307
+ useEffect(() => {
308
+ if (mode != "delete") return;
309
+ const controller = new AbortController();
310
+ setListeners(void 0);
311
+ setListenersFailed(false);
312
+ store.workspace.getErrorListeners(flow.flowId, controller.signal).then((value) => {
313
+ if (!controller.signal.aborted) setListeners(value);
314
+ }, () => {
315
+ if (!controller.signal.aborted) setListenersFailed(true);
316
+ });
317
+ return () => controller.abort();
318
+ }, [
319
+ mode,
320
+ flow.flowId,
321
+ store,
322
+ listenersRetry
323
+ ]);
247
324
  const [pending, setPending] = useState();
248
325
  const changed = flow.live != null && flow.live.revisionId != flow.draftRevisionId;
249
326
  const publicationStatus = flow.status == "retiring" ? "resource.retiring" : flow.live == null ? "resource.notPublished" : changed ? "resource.unpublishedChanges" : "resource.isPublished";
@@ -496,18 +573,26 @@ function FlowItem({ badge, busy, flow, href, onSelect, store }) {
496
573
  initialFocus: cancelDelete,
497
574
  finalFocus: deleteButton,
498
575
  showCloseButton: false,
499
- children: [/* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: t("sidebar.deleteFlowConfirm", { name: flow.name }) }), /* @__PURE__ */ jsx(DialogDescription, { children: t("resource.deleteDescription") })] }), /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(DialogClose, {
500
- render: /* @__PURE__ */ jsx(Button, {
501
- ref: cancelDelete,
502
- variant: "outline"
576
+ children: [
577
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: t("sidebar.deleteFlowConfirm", { name: flow.name }) }), /* @__PURE__ */ jsx(DialogDescription, { children: t("resource.deleteDescription") })] }),
578
+ /* @__PURE__ */ jsx(FlowDeletionImpact, {
579
+ listeners,
580
+ failed: listenersFailed,
581
+ onRetry: () => setListenersRetry((value) => value + 1)
503
582
  }),
504
- children: t("common.cancel")
505
- }), /* @__PURE__ */ jsx(Button, {
506
- disabled: busy != null,
507
- onClick: () => void remove(),
508
- variant: "destructive",
509
- children: t(busy == "flow" ? "common.deleting" : "common.delete")
510
- })] })]
583
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(DialogClose, {
584
+ render: /* @__PURE__ */ jsx(Button, {
585
+ ref: cancelDelete,
586
+ variant: "outline"
587
+ }),
588
+ children: t("common.cancel")
589
+ }), /* @__PURE__ */ jsx(Button, {
590
+ disabled: busy != null || listeners == null && !listenersFailed,
591
+ onClick: () => void remove(),
592
+ variant: "destructive",
593
+ children: t(busy == "flow" ? "common.deleting" : "common.delete")
594
+ })] })
595
+ ]
511
596
  })
512
597
  })
513
598
  ]
@@ -1456,6 +1541,7 @@ function inputSpecs(draft, triggerId) {
1456
1541
  if (resolved.trigger.kind == "manual" || resolved.trigger.kind == "cron") return [];
1457
1542
  return [{
1458
1543
  definitions: triggerOutputDefinitions(resolved.trigger),
1544
+ samples: resolved.trigger.kind == "error" ? sampleErrorOutputs : void 0,
1459
1545
  nodeId,
1460
1546
  title: resolved.trigger.name
1461
1547
  }];
@@ -1467,6 +1553,7 @@ function inputSpecs(draft, triggerId) {
1467
1553
  }, port.description == null ? {} : { description: port.description }));
1468
1554
  return definitions.length == 0 ? [] : [{
1469
1555
  definitions,
1556
+ samples: void 0,
1470
1557
  nodeId,
1471
1558
  title: nodeTitle(resolved)
1472
1559
  }];
@@ -1483,7 +1570,8 @@ async function inputGroups(specs, language, values) {
1483
1570
  const { FlowRunInputEditorStore } = await import("./flowRunInputEditorStore-Dsxyfwae.js").then((n) => n.t);
1484
1571
  return specs.map((group) => {
1485
1572
  const editor = new FlowRunInputEditorStore(group.definitions, language);
1486
- if (values?.[group.nodeId] != null) editor.replaceValues(values[group.nodeId]);
1573
+ const initial = values?.[group.nodeId] ?? group.samples;
1574
+ if (initial != null) editor.replaceValues(initial);
1487
1575
  return {
1488
1576
  editor,
1489
1577
  nodeId: group.nodeId,
@@ -1495,7 +1583,9 @@ function groupValues(groups) {
1495
1583
  return Object.fromEntries(groups.map((group) => [group.nodeId, group.editor.values()]));
1496
1584
  }
1497
1585
  function testOutputs(revision, triggerId) {
1498
- return (revisionView(revision).graph({ kind: "flow" })?.nodes[triggerId])?.kind === "cron" ? { scheduledAt: (/* @__PURE__ */ new Date()).toISOString() } : {};
1586
+ const node = revisionView(revision).graph({ kind: "flow" })?.nodes[triggerId];
1587
+ if (node?.kind == "error") return sampleErrorOutputs;
1588
+ return node?.kind === "cron" ? { scheduledAt: (/* @__PURE__ */ new Date()).toISOString() } : {};
1499
1589
  }
1500
1590
  function runValues(groups, triggerId, revision) {
1501
1591
  return {
@@ -3440,6 +3530,13 @@ function inverseFlowChanges(content, operations) {
3440
3530
  });
3441
3531
  break;
3442
3532
  }
3533
+ case "graph.trigger.sources.set":
3534
+ restore.push({
3535
+ ...operation,
3536
+ before: operation.value,
3537
+ value: operation.before
3538
+ });
3539
+ break;
3443
3540
  case "binding.target.set":
3444
3541
  restore.push({
3445
3542
  ...operation,
@@ -3595,8 +3692,9 @@ function pasteNodes(revision, target, clipboard, identity) {
3595
3692
  nodeIds: [],
3596
3693
  sourceIds: []
3597
3694
  };
3695
+ const hasErrorTrigger = Object.values(revision.graph(target)?.nodes ?? {}).some((node) => node.kind === "error");
3598
3696
  const hasManualTrigger = Object.values(revision.graph(target)?.nodes ?? {}).some((node) => node.kind === "manual");
3599
- const entries = Object.entries(clipboard.nodes).filter(([, node]) => (target.kind == "flow" || "inputs" in node) && (node.kind !== "manual" || !hasManualTrigger) && (node.kind != "task" || node.task == null || clipboard.modules[node.task.moduleId] != null));
3697
+ const entries = Object.entries(clipboard.nodes).filter(([, node]) => (target.kind == "flow" || "inputs" in node) && (node.kind !== "manual" || !hasManualTrigger) && (node.kind !== "error" || !hasErrorTrigger) && (node.kind != "task" || node.task == null || clipboard.modules[node.task.moduleId] != null));
3600
3698
  const sourceIds = entries.map(([sourceId]) => sourceId);
3601
3699
  const ids = new Map(sourceIds.map((sourceId) => [sourceId, identity()]));
3602
3700
  const operations = [];
@@ -4848,6 +4946,9 @@ var WorkspaceStore = class {
4848
4946
  this.#set({ busy: void 0 });
4849
4947
  }
4850
4948
  }
4949
+ getErrorListeners(flowId, signal) {
4950
+ return this.#client.getErrorListeners(flowId, signal);
4951
+ }
4851
4952
  async deleteFlow(flowId) {
4852
4953
  if (!await this.saveModuleEditor()) return false;
4853
4954
  const flow = this.#flows.flow(flowId);
@@ -5048,6 +5149,16 @@ var WorkspaceStore = class {
5048
5149
  this.copySelectedNodes();
5049
5150
  await this.pasteNodes(positions, offset);
5050
5151
  }
5152
+ async saveErrorSources(nodeId, value) {
5153
+ const node = this.$.revision.value?.graph({ kind: "flow" })?.nodes[nodeId];
5154
+ if (node?.kind != "error" || dequal$1(node.sourceFlowIds ?? [], value)) return false;
5155
+ return await this.#editDraft([{
5156
+ kind: "graph.trigger.sources.set",
5157
+ nodeId,
5158
+ before: node.sourceFlowIds,
5159
+ value: value.length == 0 ? void 0 : value
5160
+ }]) != null;
5161
+ }
5051
5162
  async saveNodeSettings(nodeId, settings) {
5052
5163
  const revision = this.$.revision.value;
5053
5164
  const target = this.#model.value.target;
@@ -6118,7 +6229,7 @@ var WorkbenchStore = class {
6118
6229
  };
6119
6230
  //#endregion
6120
6231
  //#region src/workbench/browser/runtime/openFlowWorkbench.tsx
6121
- var FlowWorkspace = lazy(() => import("./flowWorkspace-CjwpbVBR.js"));
6232
+ var FlowWorkspace = lazy(() => import("./flowWorkspace-DBaq2Eks.js"));
6122
6233
  function OpenFlowSessionGate({ action, description, error, onSubmit, onTokenChange, pending = false, title, token, tokenLabel }) {
6123
6234
  const hasToken = token != null && tokenLabel != null && onTokenChange != null;
6124
6235
  const tokenValue = token ?? "";
@@ -20688,6 +20688,7 @@ var endpoint = object({
20688
20688
  ])),
20689
20689
  successStatus: number()
20690
20690
  });
20691
+ var sourceFlowIds = array(text.min(1)).refine((ids) => new Set(ids).size === ids.length, "Duplicate source Flow ID.");
20691
20692
  var trigger = {
20692
20693
  name: text,
20693
20694
  description: text.optional(),
@@ -20745,6 +20746,11 @@ var node = union([
20745
20746
  ...trigger,
20746
20747
  kind: literal("manual")
20747
20748
  }),
20749
+ strictObject({
20750
+ ...trigger,
20751
+ kind: literal("error"),
20752
+ sourceFlowIds: sourceFlowIds.optional()
20753
+ }),
20748
20754
  object({
20749
20755
  ...trigger,
20750
20756
  kind: literal("webhook"),
@@ -20816,7 +20822,11 @@ var document$1 = object({
20816
20822
  tasks: record(text, managed)
20817
20823
  });
20818
20824
  var revision = object({
20819
- modelVersion: union([literal(2), literal(4)]),
20825
+ modelVersion: union([
20826
+ literal(2),
20827
+ literal(4),
20828
+ literal(5)
20829
+ ]),
20820
20830
  document: document$1,
20821
20831
  modules: record(text, module$1)
20822
20832
  });
@@ -20826,9 +20836,16 @@ revision.extend({
20826
20836
  });
20827
20837
  function decodeRevisionContent(value) {
20828
20838
  checkJsonDepth(value);
20829
- return revision.parse(value);
20839
+ const content = revision.parse(value);
20840
+ checkErrorModelVersion(content);
20841
+ return content;
20830
20842
  }
20831
20843
  var shapes = {
20844
+ "graph.trigger.sources.set": {
20845
+ nodeId: text,
20846
+ before: sourceFlowIds.optional(),
20847
+ value: sourceFlowIds.optional()
20848
+ },
20832
20849
  "binding.create": {
20833
20850
  bindingId: text,
20834
20851
  binding
@@ -21002,6 +21019,9 @@ array(union([...new Map(Object.entries(shapes).map(([kind, shape]) => [kind, sha
21002
21019
  kind: literal(kind),
21003
21020
  ...shape
21004
21021
  })])).values()])).min(1);
21022
+ function checkErrorModelVersion(content) {
21023
+ if (content.modelVersion < 5 && [content.document.graph, ...Object.values(content.document.subflows).map((item) => item.graph)].some((item) => Object.values(item.nodes).some((itemNode) => itemNode.kind == "error"))) throw new TypeError("Error workflows require Flow model version 5.");
21024
+ }
21005
21025
  //#endregion
21006
21026
  //#region src/flow/common/condition.ts
21007
21027
  var otherwiseOutput = "otherwise";
@@ -21385,6 +21405,25 @@ function applyFlowChanges(content, operations) {
21385
21405
  const document = { ...content.document };
21386
21406
  const modules = { ...content.modules };
21387
21407
  for (const operation of operations) switch (operation.kind) {
21408
+ case "graph.trigger.sources.set": {
21409
+ const graph = document.graph;
21410
+ const node = graph.nodes[operation.nodeId];
21411
+ if (node?.kind != "error") invalid("The Error Trigger does not exist.");
21412
+ if (!dequal(node.sourceFlowIds, operation.before)) invalid("The Error Trigger sources changed before this operation was applied.");
21413
+ const { sourceFlowIds: _, ...base } = node;
21414
+ const updated = operation.value == null ? base : {
21415
+ ...base,
21416
+ sourceFlowIds: operation.value
21417
+ };
21418
+ document.graph = {
21419
+ ...graph,
21420
+ nodes: {
21421
+ ...graph.nodes,
21422
+ [operation.nodeId]: updated
21423
+ }
21424
+ };
21425
+ break;
21426
+ }
21388
21427
  case "binding.create":
21389
21428
  if (document.bindings[operation.bindingId] != null) invalid("A Binding with this ID already exists.");
21390
21429
  document.bindings = {
@@ -21475,6 +21514,7 @@ function applyFlowChanges(content, operations) {
21475
21514
  const graph = selectedGraph(document, operation.target);
21476
21515
  if (graph.nodes[operation.nodeId] != null) invalid("A Node with this ID already exists in the target graph.");
21477
21516
  if (operation.target.kind == "subflow" && !("inputs" in operation.node)) invalid("Trigger Nodes cannot be created inside a Subflow.");
21517
+ if (operation.node.kind == "error" && Object.values(graph.nodes).some((node) => node.kind == "error")) invalid("A graph can contain only one Error Trigger.");
21478
21518
  if (operation.node.kind == "manual" && Object.values(graph.nodes).some((node) => node.kind == "manual")) invalid("A graph can contain only one manual Trigger.");
21479
21519
  if (operation.node.kind == "task" && operation.node.task?.capabilities !== void 0) decodeConnectorCapabilities(operation.node.task.capabilities);
21480
21520
  if (operation.node.name == null) invalid("A Node name cannot be empty.");
@@ -21854,7 +21894,7 @@ function applyFlowChanges(content, operations) {
21854
21894
  }
21855
21895
  return {
21856
21896
  document,
21857
- modelVersion: 4,
21897
+ modelVersion: 5,
21858
21898
  modules
21859
21899
  };
21860
21900
  }
@@ -23053,12 +23093,13 @@ function Dialog(props) {
23053
23093
  ...props
23054
23094
  });
23055
23095
  }
23056
- function DialogTrigger(props) {
23096
+ var DialogTrigger = React.forwardRef(function DialogTrigger(props, ref) {
23057
23097
  return /* @__PURE__ */ jsx(DialogTrigger$1, {
23058
23098
  "data-slot": "dialog-trigger",
23059
- ...props
23099
+ ...props,
23100
+ ref
23060
23101
  });
23061
- }
23102
+ });
23062
23103
  function DialogPortal(props) {
23063
23104
  return /* @__PURE__ */ jsx(DialogPortal$1, {
23064
23105
  "data-slot": "dialog-portal",
@@ -1,6 +1,7 @@
1
1
  import type { DraftOperation } from './draftOperations.js';
2
2
  declare const descriptions: {
3
3
  readonly manual: 'A Manual start node.';
4
+ readonly error: 'An Error Trigger. Publish and enable this Flow before selecting it as another Flow’s error workflow.';
4
5
  readonly webhook: 'A Webhook start node.';
5
6
  readonly cron: 'An hourly scheduled start node.';
6
7
  readonly poll: 'Gmail polling by key; replace CONNECTION_ID with an active Gmail connection.';
@@ -18,8 +19,8 @@ declare const descriptions: {
18
19
  };
19
20
  export declare const authoringExampleNames: (keyof typeof descriptions)[];
20
21
  export declare const authoringExamples: {
21
- name: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "integration" | "llm-chat" | "llm-json" | "manual" | "poll" | "poll-notification" | "value" | "wait" | "webhook";
22
- description: "A Connector Task and its node. Replace ACTION_ID, CONNECTION_ID and port definitions using connector_get / connector show." | "A JavaScript module and its node. Use Code for custom computation; use Connector Tasks for existing actions." | "A Manual start node." | "A Wait with a continue action and a built-in notification output." | "A Webhook start node." | "A condition with true and false execution branches." | "A fixed value node." | "An Agent with code computation enabled. Configure a model available in the deployment." | "An Approval with approve and reject decision branches and a built-in notification output." | "An LLM JSON Task and its node; configure a model available in the deployment." | "An LLM chat Task and its node; configure a model available in the deployment." | "An hourly scheduled start node." | "Gmail events → JavaScript text formatting → Connector notification. Replace connection/action IDs and match the notification input ports." | "Gmail polling by key; replace CONNECTION_ID with an active Gmail connection." | "Telegram webhook integration by key; replace CONNECTION_ID with an active Telegram connection.";
22
+ name: "agent" | "approval" | "code" | "condition" | "connector" | "cron" | "error" | "integration" | "llm-chat" | "llm-json" | "manual" | "poll" | "poll-notification" | "value" | "wait" | "webhook";
23
+ description: "A Connector Task and its node. Replace ACTION_ID, CONNECTION_ID and port definitions using connector_get / connector show." | "A JavaScript module and its node. Use Code for custom computation; use Connector Tasks for existing actions." | "A Manual start node." | "A Wait with a continue action and a built-in notification output." | "A Webhook start node." | "A condition with true and false execution branches." | "A fixed value node." | "An Agent with code computation enabled. Configure a model available in the deployment." | "An Approval with approve and reject decision branches and a built-in notification output." | "An Error Trigger. Publish and enable this Flow before selecting it as another Flow’s error workflow." | "An LLM JSON Task and its node; configure a model available in the deployment." | "An LLM chat Task and its node; configure a model available in the deployment." | "An hourly scheduled start node." | "Gmail events → JavaScript text formatting → Connector notification. Replace connection/action IDs and match the notification input ports." | "Gmail polling by key; replace CONNECTION_ID with an active Gmail connection." | "Telegram webhook integration by key; replace CONNECTION_ID with an active Telegram connection.";
23
24
  }[];
24
25
  export declare function authoringExample(name: string): {
25
26
  version: 1;