@oomol-lab/open-flow 0.1.0-beta.65 → 0.1.0-beta.66

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 (49) hide show
  1. package/dist/browser/{createResourceDialog-BAJXbzNH.js → createResourceDialog-C-Si_cYs.js} +2 -2
  2. package/dist/browser/flow-authoring-node.d.ts +12 -3
  3. package/dist/browser/flow-authoring.js +114 -19
  4. package/dist/browser/flow-change-schema.d.ts +3 -1
  5. package/dist/browser/flow-change.d.ts +15 -3
  6. package/dist/browser/flow-change.js +111 -16
  7. package/dist/browser/{flowChanges-DkvG5uDq.js → flowChanges-T4_R5p1f.js} +2654 -1858
  8. package/dist/browser/{flowRunInputEditorStore-B2Rw4VsT.js → flowRunInputEditorStore-DJqmR6Qh.js} +3 -2
  9. package/dist/browser/{flowWorkspace-BEp-lxqF.js → flowWorkspace-C0J5C0oM.js} +700 -224
  10. package/dist/browser/{icons-Db2Jb2iX.js → icons-BD3m0RQq.js} +4484 -4370
  11. package/dist/browser/preview.css +152 -64
  12. package/dist/browser/preview.js +4460 -3412
  13. package/dist/browser/ui.css +85 -3
  14. package/dist/browser/ui.js +8 -5
  15. package/dist/browser/workbench.css +152 -64
  16. package/dist/browser/workbench.js +146 -57
  17. package/dist/browser/{workbenchSelect-C-jf6NIM.js → workbenchSelect-B-PFpF_Q.js} +1 -1
  18. package/dist/command/index.js +49 -49
  19. package/dist/common/authoring.d.ts +7 -5
  20. package/dist/common/authoringExamples.d.ts +3 -3
  21. package/dist/common/authoringFields.d.ts +20 -0
  22. package/dist/common/authoringSchema.d.ts +404 -15
  23. package/dist/common/control-api-conformance.js +384 -137
  24. package/dist/common/control-api.d.ts +63 -7
  25. package/dist/common/control-api.js +3562 -3428
  26. package/dist/common/control-requests.d.ts +10 -3
  27. package/dist/common/control-requests.js +418 -43
  28. package/dist/common/decision.js +28 -3
  29. package/dist/common/flow-encoding.d.ts +4 -2
  30. package/dist/common/flow-encoding.js +144 -10
  31. package/dist/common/flow-graph.d.ts +1 -1
  32. package/dist/common/flow-semantics.d.ts +12 -2
  33. package/dist/common/flow-semantics.js +146 -33
  34. package/dist/common/integration-trigger.js +28 -3
  35. package/dist/common/liveDetails.d.ts +26 -11
  36. package/dist/common/mcp.d.ts +6 -3
  37. package/dist/common/mcp.js +203 -84
  38. package/dist/common/openapi.js +28 -3
  39. package/dist/common/poll-trigger.js +28 -3
  40. package/dist/common/run-events.d.ts +2 -0
  41. package/dist/common/run-events.js +9 -3
  42. package/dist/common/scheduler.d.ts +10 -1
  43. package/dist/common/scheduler.js +167 -45
  44. package/dist/common/trigger-contract.d.ts +2 -0
  45. package/dist/common/webhook-trigger.js +28 -3
  46. package/dist/common/workflow.d.ts +93 -0
  47. package/dist/common/workflow.js +10491 -0
  48. package/package.json +5 -1
  49. package/skills/open-flow/references/flow-authoring.md +26 -16
@@ -1,7 +1,7 @@
1
- import { $n as isJsonObject, $t as EmptyTitle, An as createI18n, At as updateTriggerSchedule, B as CacheResource, Cr as controlErrorCode, Ct as repairNodeNames, Dn as EventSourcesPage, Dt as setInputSources, En as Badge, Er as IconThemeContext, Et as setConnectorConnection, F as feishuResourceKind, Ft as PopoverContent, G as designerGraph, Gn as randomId, Gt as InputGroup, H as resourceData, I as supportsFeishuChatFilter, Jn as decodeTriggerCatalog, Jt as Empty, Kn as allConnectorConnectionsQuery, Kt as InputGroupAddon, L as combineSources, M as addNodeIntent, Mt as IdTooltip, N as deriveAddNodeOptions, Nt as followWorkbenchLink, Ot as setTriggerConnection, Pt as Popover, Qn as triggerOutputDefinitions, Qt as EmptyMedia, Sr as ApiError, St as setNodePositions, Tt as setCodeActions, U as resourceValue, Un as errorNotice, W as connectorActionPorts, Wn as WorkbenchClient, Xt as EmptyDescription, Y as providerIcon, Yt as EmptyContent, Zn as sampleErrorOutputs, Zt as EmptyHeader, _ as updateValue, _r as inputValue, _t as removeComments, a as nameCreatedNodes, ar as workflowNameFromFile, at as flowResourceReferences, br as record, bt as setFlowViewport, c as updateCondition, cn as DropdownMenuSeparator, cr as providerIconAppearance, ct as diagnosticItems, d as updateNodeName, en as DropdownMenu, er as connection, f as updateNodeSettings, fn as DropdownMenuTrigger, ft as actionWithConnections, g as updateTaskPorts, gt as flowPresentation, h as updateTaskAdditionalInputs, ht as commentIds, i as deleteSelection, in as DropdownMenuItem, ir as workflowFileName, it as revisionView, jt as WorkflowExportMenuItem, kt as updateTriggerConfig, l as updateNodeDescription, m as updateTask, mt as canvasPresentationChange, nn as DropdownMenuContent, nr as encodeWorkflowFile, o as setInputValue, ot as Latest, p as updateResolution, pt as connectionCatalog, qt as InputGroupInput, r as applyFlowChanges, rr as parseWorkflowFile, s as setInputVariable, st as deriveInspectorDiagnostics, t as addNode, tr as connectorActionMetadata, tt as RunStore, u as updateNodeIcon, v as updateWebhook, vr as invalidResponse, vt as restoreCanvasPresentation, wt as resetInputValues, xr as string, xt as setNodeContentHidden, yr as jsonValue, yt as setComment, z as scopedValue, zt as PopoverTitle } from "./flowChanges-DkvG5uDq.js";
1
+ import { $n as normalizeTriggerOutputs, $t as EmptyHeader, At as updateStartInputDefs, B as scopedValue, Cr as inputValue, Ct as setNodePositions, Dr as string, Dt as setConnectorConnection, Er as record, Et as setCodeActions, Ft as followWorkbenchLink, G as connectorActionPorts, Gn as errorNotice, I as feishuResourceKind, It as Popover, Jn as allConnectorConnectionsQuery, Jt as InputGroupAddon, K as designerGraph, Kn as WorkbenchClient, L as supportsFeishuChatFilter, Lt as PopoverContent, Mn as createI18n, Mr as IconThemeContext, Mt as updateTriggerSchedule, N as addNodeIntent, Nt as WorkflowExportMenuItem, On as Badge, Or as ApiError, Ot as setInputSources, P as deriveAddNodeOptions, Pt as IdTooltip, Qt as EmptyDescription, R as combineSources, St as setNodeContentHidden, Tr as jsonValue, Tt as resetInputValues, U as resourceData, V as CacheResource, Vt as PopoverTitle, W as resourceValue, X as providerIcon, Xn as decodeTriggerCatalog, Xt as Empty, Yt as InputGroupInput, Zt as EmptyContent, _ as updateTaskPorts, _t as flowPresentation, a as nameCreatedNodes, ar as encodeWorkflowFile, at as revisionView, br as workflowCandidate, bt as setComment, c as updateCondition, cr as workflowNameFromFile, ct as deriveInspectorDiagnostics, d as updateNodeName, dr as providerIconAppearance, en as EmptyMedia, er as sampleErrorOutputs, f as updateNodeSettings, g as updateTaskAdditionalInputs, gt as commentIds, h as updateTask, ht as canvasPresentationChange, i as deleteSelection, in as DropdownMenuContent, ir as connectorActionMetadata, jt as updateTriggerConfig, kn as EventSourcesPage, kr as controlErrorCode, kt as setTriggerConnection, l as updateNodeDescription, lt as diagnosticItems, m as updateResolution, mn as DropdownMenuTrigger, mt as connectionCatalog, nn as DropdownMenu, nr as isJsonObject, nt as RunStore, o as setInputValue, on as DropdownMenuItem, or as parseWorkflowFile, ot as flowResourceReferences, p as updateOutputPorts, pt as actionWithConnections, qn as randomId, qt as InputGroup, r as applyFlowChanges, rr as connection, s as setInputVariable, sr as workflowFileName, st as Latest, t as addNode, tn as EmptyTitle, tr as triggerOutputDefinitions, u as updateNodeIcon, un as DropdownMenuSeparator, v as updateValue, vt as removeComments, wr as invalidResponse, wt as repairNodeNames, xt as setFlowViewport, y as updateWebhook, yt as restoreCanvasPresentation } from "./flowChanges-T4_R5p1f.js";
2
2
  import { a as derive, i as compute, l as val } from "./dist-bO8nvHFH.js";
3
3
  import { c as useLang, l as useTranslate, o as I18nProvider, u as useVal } from "./dist-BFmpkX4P.js";
4
- import { B as FlowChangeError, Ci as cn, E as FieldLabel, Q as nodeInputMappings, S as Field, T as FieldGroup, V as applyFlowChanges$1, Z as mapConditionSources, a as DialogDescription, at as dequal$1, c as DialogTitle, d as TooltipContent, i as DialogContent, lr as Input, n as Dialog, o as DialogFooter, p as TooltipTrigger, q as resourceNameIssue, r as DialogClose, s as DialogHeader, t as Icon, u as Tooltip, w as FieldError, x as Spinner, xi as Button } from "./icons-Db2Jb2iX.js";
4
+ import { B as upgradeManualTrigger, E as FieldLabel, Ei as cn, G as mapConditionSources, K as nodeInputMappings, M as applyFlowChanges$1, P as isTriggerNode, S as Field, T as FieldGroup, Tt as dequal$1, V as upgradeRevisionContent, a as DialogDescription, c as DialogTitle, d as TooltipContent, fr as Input, i as DialogContent, j as FlowChangeError, n as Dialog, o as DialogFooter, p as TooltipTrigger, r as DialogClose, s as DialogHeader, t as Icon, u as Tooltip, w as FieldError, wi as Button, x as Spinner, z as resourceNameIssue } from "./icons-BD3m0RQq.js";
5
5
  import { c as importedWorkflowName, d as uiLanguageNames, f as uiLanguages, l as isUiLanguage, u as resolveUiLanguage } from "./value-BADHeZ9I.js";
6
6
  import { Suspense, forwardRef, lazy, useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
7
7
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -190,7 +190,7 @@ function Skeleton({ className, ...props }) {
190
190
  }
191
191
  //#endregion
192
192
  //#region src/workbench/browser/runtime/shell/resourceBrowser.tsx
193
- var CreateResourceDialog = lazy(() => import("./createResourceDialog-BAJXbzNH.js"));
193
+ var CreateResourceDialog = lazy(() => import("./createResourceDialog-C-Si_cYs.js"));
194
194
  var flowIdTooltipAlignOffset = 44;
195
195
  var renamePopoverAlignOffset = -12;
196
196
  function compactFlowId(flowId) {
@@ -1631,26 +1631,30 @@ var PublicationStore = class {
1631
1631
  var initialState$5 = { starting: false };
1632
1632
  function inputSpec(draft, triggerId) {
1633
1633
  const trigger = revisionView(draft).graph()?.nodes[triggerId];
1634
- if (trigger == null || "inputs" in trigger || trigger.kind == "manual" || trigger.kind == "cron") return void 0;
1634
+ if (trigger == null || !isTriggerNode(trigger) || trigger.kind == "manual" || trigger.kind == "cron") return void 0;
1635
1635
  const definitions = triggerOutputDefinitions(trigger);
1636
1636
  return definitions.length === 0 ? void 0 : {
1637
1637
  definitions,
1638
+ allowOmittedNullable: trigger.kind == "start",
1638
1639
  samples: trigger.kind == "error" ? sampleErrorOutputs : void 0
1639
1640
  };
1640
1641
  }
1641
1642
  function inputSignature(spec) {
1642
- return JSON.stringify(spec?.definitions.map((definition) => [
1643
- definition.handle,
1644
- definition.jsonSchema,
1645
- definition.nullable
1646
- ]) ?? []);
1643
+ return JSON.stringify({
1644
+ allowOmittedNullable: spec?.allowOmittedNullable ?? false,
1645
+ definitions: spec?.definitions.map((definition) => [
1646
+ definition.handle,
1647
+ definition.jsonSchema,
1648
+ definition.nullable
1649
+ ]) ?? []
1650
+ });
1647
1651
  }
1648
1652
  async function inputEditor(spec, language, values) {
1649
1653
  if (spec == null) return void 0;
1650
- const { FlowRunInputEditorStore } = await import("./flowRunInputEditorStore-B2Rw4VsT.js").then((n) => n.t);
1651
- const editor = new FlowRunInputEditorStore(spec.definitions, language);
1654
+ const { FlowRunInputEditorStore } = await import("./flowRunInputEditorStore-DJqmR6Qh.js").then((n) => n.t);
1655
+ const editor = new FlowRunInputEditorStore(spec.definitions, language, { allowOmittedNullable: spec.allowOmittedNullable });
1652
1656
  const initial = values ?? spec.samples;
1653
- if (initial != null) editor.replaceValues(initial);
1657
+ if (initial != null) editor.replaceValues(Object.fromEntries(spec.definitions.flatMap(({ handle }) => Object.hasOwn(initial, handle) ? [[handle, initial[handle]]] : [])));
1654
1658
  return editor;
1655
1659
  }
1656
1660
  function testOutputs(revision, triggerId) {
@@ -1702,7 +1706,7 @@ var RunRequestStore = class {
1702
1706
  async requestDraft(flow, draft, triggerId) {
1703
1707
  const current = this.#requests.begin();
1704
1708
  try {
1705
- return await this.#request("draft", flow, draft, draft.revisionId, current, void 0, triggerId);
1709
+ return await this.#request("draft", flow, draft, current, void 0, triggerId);
1706
1710
  } catch (error) {
1707
1711
  if (current()) this.#setNotice(errorNotice(error, this.#i18n.t));
1708
1712
  return "unavailable";
@@ -1713,7 +1717,7 @@ var RunRequestStore = class {
1713
1717
  async editDraft(flow, draft, triggerId) {
1714
1718
  const current = this.#requests.begin();
1715
1719
  try {
1716
- return await this.#request("draft", flow, draft, draft.revisionId, current, void 0, triggerId, true);
1720
+ return await this.#request("draft", flow, draft, current, void 0, triggerId, true);
1717
1721
  } catch (error) {
1718
1722
  if (current()) this.#setNotice(errorNotice(error, this.#i18n.t));
1719
1723
  return "unavailable";
@@ -1723,7 +1727,10 @@ var RunRequestStore = class {
1723
1727
  }
1724
1728
  inputStatus(flowId, draft, triggerId) {
1725
1729
  const spec = inputSpec(draft, triggerId);
1726
- if (spec == null) return "none";
1730
+ if (spec == null) {
1731
+ const request = this.#state.value.inputRequest;
1732
+ return request?.flow.flowId == flowId && request.triggerId == triggerId ? "ready" : "none";
1733
+ }
1727
1734
  const saved = this.#savedInputs.get(this.#inputKey(flowId, triggerId));
1728
1735
  return saved?.valid == true && saved.signature == inputSignature(spec) ? "ready" : "missing";
1729
1736
  }
@@ -1735,7 +1742,7 @@ var RunRequestStore = class {
1735
1742
  if (publication == null) return "unavailable";
1736
1743
  const revision = await this.#client.getRevision(flow.flowId, publication.revisionId);
1737
1744
  if (!current()) return "unavailable";
1738
- return await this.#request("live", flow, revision, publication.revisionId, current, publication.publicationId);
1745
+ return await this.#request("live", flow, revision, current, publication.publicationId);
1739
1746
  } catch (error) {
1740
1747
  if (current()) this.#setNotice(errorNotice(error, this.#i18n.t));
1741
1748
  return "unavailable";
@@ -1752,7 +1759,7 @@ var RunRequestStore = class {
1752
1759
  async confirmInputs() {
1753
1760
  const request = this.#state.value.inputRequest;
1754
1761
  if (request == null || request.triggerId == null) return false;
1755
- if (!request.valid.value) {
1762
+ if (request.source == "live" && !request.valid.value) {
1756
1763
  this.#set({ inputRequest: {
1757
1764
  ...request,
1758
1765
  attempted: true
@@ -1761,10 +1768,10 @@ var RunRequestStore = class {
1761
1768
  }
1762
1769
  this.#rememberInputs(request);
1763
1770
  const outputs = request.editor?.values() ?? testOutputs(request.revision, request.triggerId);
1764
- const started = await this.#start(request.source, request.flow, request.revisionId, {
1771
+ const started = await this.#start(request.source, request.flow, request.revision, {
1765
1772
  nodeId: request.triggerId,
1766
1773
  outputs
1767
- }, request.publicationId);
1774
+ }, request.publicationId, request);
1768
1775
  if (started && this.#state.value.inputRequest === request) this.dismissInputs();
1769
1776
  return started;
1770
1777
  }
@@ -1797,7 +1804,7 @@ var RunRequestStore = class {
1797
1804
  if (current()) this.#set({ starting: false });
1798
1805
  }
1799
1806
  }
1800
- async #request(source, flow, revision, revisionId, current, publicationId, triggerId, edit = false) {
1807
+ async #request(source, flow, revision, current, publicationId, triggerId, edit = false) {
1801
1808
  const previous = this.#state.value.inputRequest;
1802
1809
  this.#rememberInputs(previous);
1803
1810
  this.#set({
@@ -1807,7 +1814,7 @@ var RunRequestStore = class {
1807
1814
  });
1808
1815
  this.#disposeInputRequest(previous);
1809
1816
  const graph = revisionView(revision).graph();
1810
- const triggers = Object.entries(graph?.nodes ?? {}).flatMap(([nodeId, node]) => "inputs" in node ? [] : [{
1817
+ const triggers = Object.entries(graph?.nodes ?? {}).flatMap(([nodeId, node]) => !isTriggerNode(node) ? [] : [{
1811
1818
  nodeId,
1812
1819
  title: node.name
1813
1820
  }]);
@@ -1819,7 +1826,7 @@ var RunRequestStore = class {
1819
1826
  });
1820
1827
  return "unavailable";
1821
1828
  }
1822
- const only = triggerId == null ? triggers[0] : triggers.find((trigger) => trigger.nodeId == triggerId);
1829
+ const only = triggerId == null ? triggers.find((trigger) => graph?.nodes[trigger.nodeId]?.kind == "start") ?? triggers[0] : triggers.find((trigger) => trigger.nodeId == triggerId);
1823
1830
  if (triggerId != null && only == null) {
1824
1831
  this.#set({ starting: false });
1825
1832
  this.#setNotice({
@@ -1836,14 +1843,14 @@ var RunRequestStore = class {
1836
1843
  editor?.dispose();
1837
1844
  return "unavailable";
1838
1845
  }
1839
- if (!edit && only != null && editor == null) return await this.#start(source, flow, revisionId, {
1846
+ if (!edit && only != null && editor == null) return await this.#start(source, flow, revision, {
1840
1847
  nodeId: only.nodeId,
1841
1848
  outputs: testOutputs(revision, only.nodeId)
1842
1849
  }, publicationId) ? "started" : "unavailable";
1843
1850
  if (!edit && only != null && saved?.valid == true && saved.signature == signature && editor != null && editor.valid$.value) {
1844
1851
  const outputs = editor.values();
1845
1852
  editor?.dispose();
1846
- return await this.#start(source, flow, revisionId, {
1853
+ return await this.#start(source, flow, revision, {
1847
1854
  nodeId: only.nodeId,
1848
1855
  outputs
1849
1856
  }, publicationId) ? "started" : "unavailable";
@@ -1858,7 +1865,6 @@ var RunRequestStore = class {
1858
1865
  triggers,
1859
1866
  triggerId: only?.nodeId,
1860
1867
  ...publicationId == null ? {} : { publicationId },
1861
- revisionId,
1862
1868
  source,
1863
1869
  valid
1864
1870
  },
@@ -1867,23 +1873,46 @@ var RunRequestStore = class {
1867
1873
  });
1868
1874
  return "input";
1869
1875
  }
1870
- async #start(source, flow, revisionId, trigger, publicationId) {
1876
+ async #start(source, flow, revision, trigger, publicationId, request) {
1871
1877
  if (source == "live" && publicationId == null) return false;
1872
1878
  const alive = this.#lifetime.capture();
1873
- const current = this.#runs.prepareStart();
1879
+ const requestCurrent = this.#requests.begin();
1880
+ let current = this.#runs.captureSelection();
1874
1881
  this.#set({
1875
1882
  starting: true,
1876
1883
  submitting: source
1877
1884
  });
1878
1885
  try {
1879
- if (source == "draft") {
1880
- const savedRevision = await this.#prepareDraft(flow.flowId);
1881
- if (savedRevision == null || !alive() || !current()) return false;
1882
- revisionId = savedRevision;
1886
+ const prepared = source == "draft" ? await this.#prepareDraft(flow.flowId) : revision;
1887
+ if (prepared == null || !alive() || !current() || !requestCurrent()) return false;
1888
+ const node = revisionView(prepared).trigger(trigger.nodeId);
1889
+ if (node == null || node.kind !== revisionView(revision).trigger(trigger.nodeId)?.kind || inputSignature(inputSpec(prepared, trigger.nodeId)) !== inputSignature(inputSpec(revision, trigger.nodeId))) {
1890
+ await this.#request(source, flow, prepared, requestCurrent, publicationId, trigger.nodeId, true);
1891
+ return false;
1892
+ }
1893
+ if (request != null && !request.valid.value) {
1894
+ if (this.#state.value.inputRequest === request) this.#set({ inputRequest: {
1895
+ ...request,
1896
+ attempted: true
1897
+ } });
1898
+ return false;
1883
1899
  }
1900
+ const outputs = normalizeTriggerOutputs(node, request?.editor?.values() ?? trigger.outputs);
1901
+ if (outputs == null) {
1902
+ this.#setNotice({
1903
+ kind: "error",
1904
+ message: this.#i18n.t("runInput.invalid")
1905
+ });
1906
+ return false;
1907
+ }
1908
+ current = this.#runs.prepareStart();
1909
+ trigger = {
1910
+ nodeId: trigger.nodeId,
1911
+ outputs
1912
+ };
1884
1913
  const target = source == "draft" ? {
1885
1914
  flowId: flow.flowId,
1886
- revisionId
1915
+ revisionId: prepared.revisionId
1887
1916
  } : { publicationId };
1888
1917
  const signature = JSON.stringify({
1889
1918
  trigger,
@@ -1895,7 +1924,7 @@ var RunRequestStore = class {
1895
1924
  signature
1896
1925
  };
1897
1926
  this.#attempt = attempt;
1898
- const run = source == "draft" ? await this.#client.createDraftRun(flow.flowId, revisionId, {
1927
+ const run = source == "draft" ? await this.#client.createDraftRun(flow.flowId, prepared.revisionId, {
1899
1928
  idempotencyKey: attempt.key,
1900
1929
  inputs: {},
1901
1930
  trigger
@@ -1904,14 +1933,14 @@ var RunRequestStore = class {
1904
1933
  inputs: {},
1905
1934
  trigger
1906
1935
  });
1907
- if (!alive() || !current()) return false;
1936
+ if (!alive() || !current() || !requestCurrent()) return false;
1908
1937
  this.#attempt = void 0;
1909
1938
  return this.#runs.follow(run, current);
1910
1939
  } catch (error) {
1911
- if (alive() && current()) this.#setNotice(errorNotice(error, this.#i18n.t));
1940
+ if (alive() && current() && requestCurrent()) this.#setNotice(errorNotice(error, this.#i18n.t));
1912
1941
  return false;
1913
1942
  } finally {
1914
- if (alive()) this.#set({
1943
+ if (alive() && requestCurrent()) this.#set({
1915
1944
  starting: false,
1916
1945
  submitting: void 0
1917
1946
  });
@@ -4099,11 +4128,19 @@ var TriggerStore = class {
4099
4128
  };
4100
4129
  //#endregion
4101
4130
  //#region src/flow/common/inverseChanges.ts
4102
- /** Invert canvas authoring operations, including the reducer's cascading deletions. */
4131
+ /** Invert authoring operations and cascading deletions while retaining model upgrades. */
4103
4132
  function inverseFlowChanges(content, operations) {
4104
- let current = content;
4133
+ let current = upgradeRevisionContent(content);
4105
4134
  const groups = [];
4106
- for (const operation of operations) {
4135
+ for (const requested of operations) {
4136
+ const operation = requested.kind == "graph.node.create" ? {
4137
+ ...requested,
4138
+ node: upgradeManualTrigger(requested.node)
4139
+ } : requested.kind == "graph.node.replace" && requested.before.kind == "manual" && requested.node.kind == "manual" ? {
4140
+ ...requested,
4141
+ before: upgradeManualTrigger(requested.before),
4142
+ node: upgradeManualTrigger(requested.node)
4143
+ } : requested;
4107
4144
  const after = applyFlowChanges$1(current, [operation]);
4108
4145
  const restore = [];
4109
4146
  switch (operation.kind) {
@@ -4200,7 +4237,13 @@ function inverseFlowChanges(content, operations) {
4200
4237
  const afterGraph = after.document.graph;
4201
4238
  const beforeNode = beforeGraph.nodes[operation.nodeId];
4202
4239
  const afterNode = afterGraph.nodes[operation.nodeId];
4203
- if (beforeNode.kind === "condition" && afterNode.kind === "condition") restore.push({
4240
+ if (beforeNode.kind === "outputs") restore.push({
4241
+ kind: "graph.node.replace",
4242
+ nodeId: operation.nodeId,
4243
+ before: afterNode,
4244
+ node: beforeNode
4245
+ });
4246
+ else if (beforeNode.kind === "condition" && afterNode.kind === "condition") restore.push({
4204
4247
  kind: "graph.node.condition.set",
4205
4248
  nodeId: operation.nodeId,
4206
4249
  before: {
@@ -4332,7 +4375,7 @@ function copyNodes(revision, nodeIds) {
4332
4375
  return {
4333
4376
  edges: (revision.graph()?.edges ?? []).filter((edge) => copied[edge.source] != null && copied[edge.target] != null),
4334
4377
  bindings: Object.fromEntries(Object.values(copied).flatMap((node) => {
4335
- if (!("inputs" in node)) return [];
4378
+ if (!("inputs" in node) && node.kind != "outputs") return [];
4336
4379
  return Object.values(nodeInputMappings(node)).flatMap((mapping) => mapping.kind == "sources" ? mapping.sources.flatMap((source) => {
4337
4380
  if (source.kind != "binding") return [];
4338
4381
  const binding = revision.binding(source.bindingId);
@@ -4348,15 +4391,16 @@ function copyNodes(revision, nodeIds) {
4348
4391
  };
4349
4392
  }
4350
4393
  function pasteNodes(revision, clipboard, identity) {
4394
+ const hasOutputs = Object.values(revision.graph().nodes).some((node) => node.kind == "outputs");
4351
4395
  const hasErrorTrigger = Object.values(revision.graph()?.nodes ?? {}).some((node) => node.kind === "error");
4352
- const hasManualTrigger = Object.values(revision.graph()?.nodes ?? {}).some((node) => node.kind === "manual");
4353
- const entries = Object.entries(clipboard.nodes).filter(([, node]) => (node.kind !== "manual" || !hasManualTrigger) && (node.kind !== "error" || !hasErrorTrigger) && (node.kind != "task" || !("moduleId" in node.task) || clipboard.modules[node.task.moduleId] != null));
4396
+ const hasStartTrigger = Object.values(revision.graph()?.nodes ?? {}).some((node) => node.kind === "manual" || node.kind === "start");
4397
+ const entries = Object.entries(clipboard.nodes).filter(([, node]) => (node.kind !== "manual" && node.kind !== "start" || !hasStartTrigger) && (node.kind !== "outputs" || !hasOutputs) && (node.kind !== "error" || !hasErrorTrigger) && (node.kind != "task" || !("moduleId" in node.task) || clipboard.modules[node.task.moduleId] != null));
4354
4398
  const sourceIds = entries.map(([sourceId]) => sourceId);
4355
4399
  const ids = new Map(sourceIds.map((sourceId) => [sourceId, identity()]));
4356
4400
  const operations = [];
4357
4401
  const bindingIds = /* @__PURE__ */ new Map();
4358
4402
  for (const [, node] of entries) {
4359
- if (!("inputs" in node)) continue;
4403
+ if (!("inputs" in node) && node.kind != "outputs") continue;
4360
4404
  const inputs = Object.values(nodeInputMappings(node));
4361
4405
  for (const mapping of inputs) {
4362
4406
  if (mapping.kind != "sources") continue;
@@ -4376,7 +4420,7 @@ function pasteNodes(revision, clipboard, identity) {
4376
4420
  }
4377
4421
  for (const [sourceId, node] of entries) {
4378
4422
  const nodeId = ids.get(sourceId);
4379
- if (!("inputs" in node)) {
4423
+ if (!("inputs" in node) && node.kind != "outputs") {
4380
4424
  operations.push({
4381
4425
  kind: "graph.node.create",
4382
4426
  node,
@@ -4418,8 +4462,11 @@ function pasteNodes(revision, clipboard, identity) {
4418
4462
  }
4419
4463
  return inputs;
4420
4464
  };
4421
- const inputs = remapInputs(node.inputs);
4422
- let copy = {
4465
+ const inputs = remapInputs(nodeInputMappings(node));
4466
+ let copy = node.kind == "outputs" ? {
4467
+ ...node,
4468
+ outputMappings: inputs
4469
+ } : {
4423
4470
  ...node,
4424
4471
  inputs
4425
4472
  };
@@ -5491,7 +5538,18 @@ var WorkspaceStore = class {
5491
5538
  this.#stopFlowWatch = subscription.stop;
5492
5539
  await subscription.ready;
5493
5540
  if (!current()) return false;
5494
- const { flow, draft, live, presentation } = await this.#client.getEditor(flowId);
5541
+ let editor = await this.#client.getEditor(flowId);
5542
+ for (let attempt = 0; current() && Object.values(revisionView(editor.draft).graph().nodes).some((node) => node.kind == "manual"); attempt += 1) {
5543
+ if (attempt >= 3) throw new ApiError(409, controlErrorCode.flowRevisionConflict, "The Draft changed while upgrading its Start node.");
5544
+ try {
5545
+ await this.#client.upgradeDraft(flowId, editor.draft.revisionId, { idempotencyKey: this.#identity() });
5546
+ } catch (error) {
5547
+ if (!(error instanceof ApiError) || error.code !== controlErrorCode.flowRevisionConflict || attempt >= 2) throw error;
5548
+ }
5549
+ if (!current()) return false;
5550
+ editor = await this.#client.getEditor(flowId);
5551
+ }
5552
+ const { flow, draft, live, presentation } = editor;
5495
5553
  if (!current()) return false;
5496
5554
  this.#draftChanges.reset(draft);
5497
5555
  this.#presentationChanges.reset(presentation);
@@ -5501,10 +5559,11 @@ var WorkspaceStore = class {
5501
5559
  live,
5502
5560
  presentation,
5503
5561
  workspaceLoadFailed: false,
5504
- workspaceLoadProblem: void 0,
5505
- workspaceLoading: false
5562
+ workspaceLoadProblem: void 0
5506
5563
  });
5507
5564
  await this.#repairDraftNodeNames(current);
5565
+ if (!current()) return false;
5566
+ this.#set({ workspaceLoading: false });
5508
5567
  if (invalidated && pendingRevision != draft.revisionId) this.#refreshDraft(pendingRevision);
5509
5568
  } catch (error) {
5510
5569
  if (!current()) return false;
@@ -5848,6 +5907,17 @@ var WorkspaceStore = class {
5848
5907
  if (revision == null) return false;
5849
5908
  return await this.#editDraft(resetInputValues(revision.revision.content, nodeId, handles)) != null;
5850
5909
  }
5910
+ async saveOutputsDefs(nodeId, definitions, deletion, values) {
5911
+ const revision = this.$.revision.value;
5912
+ if (revision == null || revision.graph().nodes[nodeId]?.kind != "outputs") return false;
5913
+ return await this.#editDraft(updateOutputPorts(revision, nodeId, definitions, values), deletion) != null;
5914
+ }
5915
+ async saveStartInputDefs(nodeId, inputDefs, deletion) {
5916
+ const revision = this.$.revision.value;
5917
+ if (revision == null || revision.graph().nodes[nodeId]?.kind != "start") return false;
5918
+ const changes = updateStartInputDefs(revision.revision.content, nodeId, inputDefs);
5919
+ return await this.#editDraft(changes, deletion) != null;
5920
+ }
5851
5921
  async resetTriggerConfig(triggerId, names) {
5852
5922
  const revision = this.$.revision.value;
5853
5923
  if (revision == null) return false;
@@ -5908,6 +5978,25 @@ var WorkspaceStore = class {
5908
5978
  position
5909
5979
  }));
5910
5980
  }
5981
+ async listWorkflowTargets(signal) {
5982
+ const flowId = this.$.revision.value?.revision.flowId;
5983
+ if (flowId == null) return [];
5984
+ const candidates = [];
5985
+ let cursor;
5986
+ do {
5987
+ const page = await this.#client.listFlows({
5988
+ cursor,
5989
+ limit: 100,
5990
+ signal
5991
+ });
5992
+ candidates.push(...page.flows.filter((flow) => flow.flowId != flowId).map((flow) => workflowCandidate(flow)));
5993
+ cursor = page.nextCursor;
5994
+ } while (cursor != null);
5995
+ return candidates;
5996
+ }
5997
+ loadWorkflowContract(flowId, signal) {
5998
+ return this.#client.getWorkflowContract(flowId, signal);
5999
+ }
5911
6000
  loadOpenApiDocument(url, signal) {
5912
6001
  return this.#client.loadOpenApiDocument(url, signal);
5913
6002
  }
@@ -6135,7 +6224,7 @@ var WorkspaceStore = class {
6135
6224
  for (let attempt = 0; attempt < 2 && current(); attempt += 1) {
6136
6225
  const draft = this.#model.value.draft;
6137
6226
  if (draft == null) return;
6138
- const repairs = repairNodeNames(draft.content);
6227
+ const repairs = repairNodeNames(draft.content, { start: this.#i18n.t("addNode.start") });
6139
6228
  if (repairs.length == 0) {
6140
6229
  this.#checkDraft();
6141
6230
  return;
@@ -6489,8 +6578,8 @@ var WorkbenchStore = class {
6489
6578
  this.triggers = new TriggerStore(client, this.workspace, setNotice, host, i18n);
6490
6579
  this.publications = new PublicationStore(client, this.workspace, setNotice, preferences, identity, i18n);
6491
6580
  this.runRequests = new RunRequestStore(client, this.runs, setNotice, async (flowId) => {
6492
- if (flowId != this.workspace.$.flowId.value || !await this.workspace.saveModuleEditor() || this.#disposed || flowId != this.workspace.$.flowId.value) return;
6493
- return this.workspace.$.draft.value?.revisionId;
6581
+ if (flowId != this.workspace.$.flowId.value || !await this.workspace.saveDraft() || this.#disposed || flowId != this.workspace.$.flowId.value) return;
6582
+ return this.workspace.$.draft.value;
6494
6583
  }, i18n, identity);
6495
6584
  const diagnostics = compute((get) => {
6496
6585
  const check = get(this.workspace.$.diagnostics);
@@ -6665,14 +6754,14 @@ var WorkbenchStore = class {
6665
6754
  return await this.#openNewFlow(await this.workspace.importFlow(file, name, key, importer), "notice.flowImported");
6666
6755
  }
6667
6756
  async createFlow(name, create) {
6668
- return await this.#openNewFlow(await this.workspace.createFlow(name, create), "notice.created");
6757
+ return await this.#openNewFlow(await this.workspace.createFlow(name, create));
6669
6758
  }
6670
6759
  async #openNewFlow(created, notice) {
6671
6760
  if (this.#disposed || created == null) return false;
6672
6761
  await this.selectFlow(created.flowId);
6673
- if (!this.#disposed) this.#notice.set({
6762
+ if (!this.#disposed && notice != null) this.#notice.set({
6674
6763
  kind: "success",
6675
- message: this.#i18n.t(notice, { name: created.name })
6764
+ message: this.#i18n.t(notice)
6676
6765
  });
6677
6766
  return true;
6678
6767
  }
@@ -6852,7 +6941,7 @@ var WorkbenchStore = class {
6852
6941
  };
6853
6942
  //#endregion
6854
6943
  //#region src/workbench/browser/runtime/openFlowWorkbench.tsx
6855
- var FlowWorkspace = lazy(() => import("./flowWorkspace-BEp-lxqF.js"));
6944
+ var FlowWorkspace = lazy(() => import("./flowWorkspace-C0J5C0oM.js"));
6856
6945
  function OpenFlowSessionGate({ action, description, error, onSubmit, onTokenChange, pending = false, title, token, tokenLabel }) {
6857
6946
  const hasToken = token != null && tokenLabel != null && onTokenChange != null;
6858
6947
  const tokenValue = token ?? "";
@@ -1,4 +1,4 @@
1
- import { At as SelectValue, Ci as cn, Ct as Select, Dt as SelectItem, Et as SelectGroup, Tt as SelectContent, kt as SelectTrigger } from "./icons-Db2Jb2iX.js";
1
+ import { At as SelectItem, Ei as cn, Et as Select, Mt as SelectTrigger, Nt as SelectValue, Ot as SelectContent, kt as SelectGroup } from "./icons-BD3m0RQq.js";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  //#region src/workbench/browser/runtime/shell/workbenchSelect.tsx
4
4
  function WorkbenchSelect({ ariaLabel, className, disabled = false, id, onValueChange, options, portalRoot, size, value, variant }) {