UNPKG

n8n-editor-ui

Version:

Workflow Editor UI for n8n

1,137 lines 50.7 kB
;
(function () {
  System.register(["./chunk-legacy-Re9CbdfL.js", "./vue.runtime.esm-bundler-legacy--Sn1h8On.js", "./_MapCache-legacy-DlYNX_X1.js", "./truncate-legacy-BGje52Or.js", "./useTelemetry-legacy-B3pzzkAE.js", "./useToast-legacy-C4Vu5mt9.js", "./constants-legacy-TKxWCqvM.js", "./_baseOrderBy-legacy-CB2Dh5d_.js", "./useExternalHooks-legacy-8pg6K3ln.js", "./useWorkflowSaving-legacy-B3LVQV33.js", "./retry-legacy-CTwsGM7o.js", "./executions.store-legacy-COqSks8S.js", "./useCanvasOperations-legacy-CXe_JeOj.js"], function (_export, _context) {
    "use strict";

    var __toESM, computed, ref, watch, useI18n, useLocalStorage, require_get, EnableNodeToggleCommand, CanvasNodeDirtiness, AddNodeCommand, AddConnectionCommand, useSettingsStore, RemoveConnectionCommand, RemoveNodeCommand, BulkCommand, injectWorkflowState, useDocumentTitle, useHistoryStore, displayForm, useWorkflowHelpers, useWorkflowsStore, STORES, useTelemetry, isEmpty, useNodeHelpers, useToast, CHAT_TRIGGER_NODE_TYPE, LOCAL_STORAGE_RUN_DATA_WORKER, createRunExecutionData, NodeConnectionTypes, IN_PROGRESS_EXECUTION_ID, generateNodesGraph, createHeartbeatMessage, SINGLE_WEBHOOK_TRIGGERS, defineStore, useRootStore, useExternalHooks, useWorkflowSaving, retry, useExecutionsStore, useCanvasOperations, useHeartbeat, useReconnectTimer, useWebSocketClient, useEventSourceClient, proxyMarker, createEndpoint, releaseProxy, finalizer, throwMarker, isObject, transferHandlers, proxyCounter, proxyFinalizers, transferCache, worker, runDataWorker, usePushConnectionStore, LOCAL_STORAGE_AGENT_REQUESTS, useAgentRequestStore, import_get;
    function isAllowedOrigin(allowedOrigins, origin) {
      for (const allowedOrigin of allowedOrigins) {
        if (origin === allowedOrigin || allowedOrigin === "*") return true;
        if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) return true;
      }
      return false;
    }
    function expose(obj, ep = globalThis, allowedOrigins = ["*"]) {
      ep.addEventListener("message", function callback(ev) {
        if (!ev || !ev.data) return;
        if (!isAllowedOrigin(allowedOrigins, ev.origin)) {
          console.warn(`Invalid origin '${ev.origin}' for comlink proxy`);
          return;
        }
        const {
          id,
          type,
          path
        } = Object.assign({
          path: []
        }, ev.data);
        const argumentList = (ev.data.argumentList || []).map(fromWireValue);
        let returnValue;
        try {
          const parent = path.slice(0, -1).reduce((obj$1, prop) => obj$1[prop], obj);
          const rawValue = path.reduce((obj$1, prop) => obj$1[prop], obj);
          switch (type) {
            case "GET":
              returnValue = rawValue;
              break;
            case "SET":
              parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);
              returnValue = true;
              break;
            case "APPLY":
              returnValue = rawValue.apply(parent, argumentList);
              break;
            case "CONSTRUCT":
              returnValue = proxy(new rawValue(...argumentList));
              break;
            case "ENDPOINT":
              {
                const {
                  port1,
                  port2
                } = new MessageChannel();
                expose(obj, port2);
                returnValue = transfer(port1, [port1]);
              }
              break;
            case "RELEASE":
              returnValue = void 0;
              break;
            default:
              return;
          }
        } catch (value) {
          returnValue = {
            value,
            [throwMarker]: 0
          };
        }
        Promise.resolve(returnValue).catch(value => {
          return {
            value,
            [throwMarker]: 0
          };
        }).then(returnValue$1 => {
          const [wireValue, transferables] = toWireValue(returnValue$1);
          ep.postMessage(Object.assign(Object.assign({}, wireValue), {
            id
          }), transferables);
          if (type === "RELEASE") {
            ep.removeEventListener("message", callback);
            closeEndPoint(ep);
            if (finalizer in obj && typeof obj[finalizer] === "function") obj[finalizer]();
          }
        }).catch(error => {
          const [wireValue, transferables] = toWireValue({
            value: /* @__PURE__ */new TypeError("Unserializable return value"),
            [throwMarker]: 0
          });
          ep.postMessage(Object.assign(Object.assign({}, wireValue), {
            id
          }), transferables);
        });
      });
      if (ep.start) ep.start();
    }
    function isMessagePort(endpoint) {
      return endpoint.constructor.name === "MessagePort";
    }
    function closeEndPoint(endpoint) {
      if (isMessagePort(endpoint)) endpoint.close();
    }
    function wrap(ep, target) {
      return createProxy(ep, [], target);
    }
    function throwIfProxyReleased(isReleased) {
      if (isReleased) throw new Error("Proxy has been released and is not useable");
    }
    function releaseEndpoint(ep) {
      return requestResponseMessage(ep, {
        type: "RELEASE"
      }).then(() => {
        closeEndPoint(ep);
      });
    }
    function registerProxy(proxy$1, ep) {
      const newCount = (proxyCounter.get(ep) || 0) + 1;
      proxyCounter.set(ep, newCount);
      if (proxyFinalizers) proxyFinalizers.register(proxy$1, ep, proxy$1);
    }
    function unregisterProxy(proxy$1) {
      if (proxyFinalizers) proxyFinalizers.unregister(proxy$1);
    }
    function createProxy(ep, path = [], target = function () {}) {
      let isProxyReleased = false;
      const proxy$1 = new Proxy(target, {
        get(_target, prop) {
          throwIfProxyReleased(isProxyReleased);
          if (prop === releaseProxy) return () => {
            unregisterProxy(proxy$1);
            releaseEndpoint(ep);
            isProxyReleased = true;
          };
          if (prop === "then") {
            if (path.length === 0) return {
              then: () => proxy$1
            };
            const r = requestResponseMessage(ep, {
              type: "GET",
              path: path.map(p => p.toString())
            }).then(fromWireValue);
            return r.then.bind(r);
          }
          return createProxy(ep, [...path, prop]);
        },
        set(_target, prop, rawValue) {
          throwIfProxyReleased(isProxyReleased);
          const [value, transferables] = toWireValue(rawValue);
          return requestResponseMessage(ep, {
            type: "SET",
            path: [...path, prop].map(p => p.toString()),
            value
          }, transferables).then(fromWireValue);
        },
        apply(_target, _thisArg, rawArgumentList) {
          throwIfProxyReleased(isProxyReleased);
          const last = path[path.length - 1];
          if (last === createEndpoint) return requestResponseMessage(ep, {
            type: "ENDPOINT"
          }).then(fromWireValue);
          if (last === "bind") return createProxy(ep, path.slice(0, -1));
          const [argumentList, transferables] = processArguments(rawArgumentList);
          return requestResponseMessage(ep, {
            type: "APPLY",
            path: path.map(p => p.toString()),
            argumentList
          }, transferables).then(fromWireValue);
        },
        construct(_target, rawArgumentList) {
          throwIfProxyReleased(isProxyReleased);
          const [argumentList, transferables] = processArguments(rawArgumentList);
          return requestResponseMessage(ep, {
            type: "CONSTRUCT",
            path: path.map(p => p.toString()),
            argumentList
          }, transferables).then(fromWireValue);
        }
      });
      registerProxy(proxy$1, ep);
      return proxy$1;
    }
    function myFlat(arr) {
      return Array.prototype.concat.apply([], arr);
    }
    function processArguments(argumentList) {
      const processed = argumentList.map(toWireValue);
      return [processed.map(v => v[0]), myFlat(processed.map(v => v[1]))];
    }
    function transfer(obj, transfers) {
      transferCache.set(obj, transfers);
      return obj;
    }
    function proxy(obj) {
      return Object.assign(obj, {
        [proxyMarker]: true
      });
    }
    function toWireValue(value) {
      for (const [name, handler] of transferHandlers) if (handler.canHandle(value)) {
        const [serializedValue, transferables] = handler.serialize(value);
        return [{
          type: "HANDLER",
          name,
          value: serializedValue
        }, transferables];
      }
      return [{
        type: "RAW",
        value
      }, transferCache.get(value) || []];
    }
    function fromWireValue(value) {
      switch (value.type) {
        case "HANDLER":
          return transferHandlers.get(value.name).deserialize(value.value);
        case "RAW":
          return value.value;
      }
    }
    function requestResponseMessage(ep, msg, transfers) {
      return new Promise(resolve => {
        const id = generateUUID();
        ep.addEventListener("message", function l(ev) {
          if (!ev.data || !ev.data.id || ev.data.id !== id) return;
          ep.removeEventListener("message", l);
          resolve(ev.data);
        });
        if (ep.start) ep.start();
        ep.postMessage(Object.assign({
          id
        }, msg), transfers);
      });
    }
    function generateUUID() {
      return new Array(4).fill(0).map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16)).join("-");
    }

    //#endregion
    //#region src/app/workers/run-data/instance.ts

    //#endregion
    //#region src/app/composables/useNodeDirtiness.ts
    /**
    * Does the command make the given node dirty?
    */
    function shouldCommandMarkDirty(command, nodeName, siblingCommands, getIncomingConnections, getOutgoingConnectors) {
      if (command instanceof BulkCommand) return command.commands.some(cmd => shouldCommandMarkDirty(cmd, nodeName, command.commands, getIncomingConnections, getOutgoingConnectors));
      if (command instanceof AddConnectionCommand) return command.connectionData[1]?.node === nodeName;
      if (command instanceof RemoveConnectionCommand) {
        const [from, to] = command.connectionData;
        if (to.node !== nodeName) return false;
        return siblingCommands.some(sibling => sibling instanceof RemoveNodeCommand && sibling.node.name === from.node);
      }
      const incomingNodes = Object.values(getIncomingConnections(nodeName)).flat().flat().filter(connection => connection !== null).map(connection => connection.node);
      if (command instanceof AddNodeCommand) return incomingNodes.includes(command.node.name);
      if (command instanceof EnableNodeToggleCommand) return incomingNodes.includes(command.nodeName) && (command.newState || Object.keys(getOutgoingConnectors(command.nodeName)).some(type => type !== NodeConnectionTypes.Main));
      return false;
    }
    /**
    * If given node is part of a loop, returns the set of nodes that forms the loop, otherwise returns undefined.
    */
    function findLoop(nodeName, visited, getIncomingConnections) {
      const index = visited.indexOf(nodeName);
      if (index >= 0) return visited.slice(index);
      const newVisited = [...visited, nodeName];
      for (const [type, typeConnections] of Object.entries(getIncomingConnections(nodeName))) {
        if (type !== NodeConnectionTypes.Main) continue;
        for (const connections of typeConnections) for (const {
          node
        } of connections ?? []) {
          const loop = findLoop(node, newVisited, getIncomingConnections);
          if (loop) return loop;
        }
      }
    }
    /**
    * Determines the subgraph that is affected by changes made after the last (partial) execution
    */
    function useNodeDirtiness() {
      const historyStore = useHistoryStore();
      const workflowsStore = useWorkflowsStore();
      function getParentSubNodes(nodeName) {
        return Object.entries(workflowsStore.incomingConnectionsByNodeName(nodeName)).filter(([type]) => type !== NodeConnectionTypes.Main).flatMap(([, typeConnections]) => typeConnections.flat().filter(conn => conn !== null));
      }
      function getDirtinessByParametersUpdate(nodeName, after) {
        if ((workflowsStore.getParametersLastUpdate(nodeName) ?? 0) > after) return CanvasNodeDirtiness.PARAMETERS_UPDATED;
        for (const connection of getParentSubNodes(nodeName)) if (getDirtinessByParametersUpdate(connection.node, after) !== void 0) return CanvasNodeDirtiness.UPSTREAM_DIRTY;
      }
      function getDirtinessByConnectionsUpdate(nodeName, after) {
        for (let i = historyStore.undoStack.length - 1; i >= 0; i--) {
          const command = historyStore.undoStack[i];
          if (command.getTimestamp() < after) break;
          if (shouldCommandMarkDirty(command, nodeName, [], workflowsStore.incomingConnectionsByNodeName, workflowsStore.outgoingConnectionsByNodeName)) return CanvasNodeDirtiness.INCOMING_CONNECTIONS_UPDATED;
        }
        for (const connection of getParentSubNodes(nodeName)) if (getDirtinessByConnectionsUpdate(connection.node, after) !== void 0) return CanvasNodeDirtiness.UPSTREAM_DIRTY;
      }
      /**
      * Depth of node is defined as the minimum distance (number of connections) from the trigger node
      */
      const depthByName = computed(() => {
        const depth = {};
        function setDepthRecursively(nodeName, current, visited) {
          if (visited.has(nodeName)) return;
          const myVisited = new Set(visited);
          myVisited.add(nodeName);
          for (const [type, typeConnections] of Object.entries(workflowsStore.outgoingConnectionsByNodeName(nodeName))) {
            if (type !== NodeConnectionTypes.Main) continue;
            for (const connections of typeConnections) for (const {
              node
            } of connections ?? []) {
              if (!depth[node] || depth[node] > current) depth[node] = current;
              setDepthRecursively(node, current + 1, myVisited);
            }
          }
        }
        for (const startNode of workflowsStore.allNodes) {
          if (Object.keys(workflowsStore.incomingConnectionsByNodeName(startNode.name)).length > 0) continue;
          depth[startNode.name] = 0;
          setDepthRecursively(startNode.name, 1, /* @__PURE__ */new Set());
        }
        return depth;
      });
      return {
        dirtinessByName: computed(() => {
          const dirtiness = {};
          const runDataByNode = workflowsStore.getWorkflowRunData ?? {};
          function setDirtiness(nodeName, value) {
            dirtiness[nodeName] = dirtiness[nodeName] ?? value;
            const loop = findLoop(nodeName, [], workflowsStore.incomingConnectionsByNodeName);
            if (!loop) return;
            const loopEntryNodeName = [...loop].sort((a, b) => (depthByName.value[a] ?? Number.MAX_SAFE_INTEGER) - (depthByName.value[b] ?? Number.MAX_SAFE_INTEGER))?.[0];
            if (loopEntryNodeName && depthByName.value[loopEntryNodeName]) dirtiness[loopEntryNodeName] = dirtiness[loopEntryNodeName] ?? CanvasNodeDirtiness.UPSTREAM_DIRTY;
          }
          for (const [nodeName, runData] of Object.entries(runDataByNode)) {
            const runAt = runData[0]?.startTime ?? 0;
            if (!runAt) continue;
            const parameterUpdate = getDirtinessByParametersUpdate(nodeName, runAt);
            if (parameterUpdate) {
              setDirtiness(nodeName, parameterUpdate);
              continue;
            }
            const connectionUpdate = getDirtinessByConnectionsUpdate(nodeName, runAt);
            if (connectionUpdate) {
              setDirtiness(nodeName, connectionUpdate);
              continue;
            }
            if (Object.values(workflowsStore.incomingConnectionsByNodeName(nodeName)).flat().flat().filter(connection => connection !== null).some(connection => {
              return (workflowsStore.getPinnedDataLastUpdate(connection.node) ?? 0) > runAt;
            })) {
              setDirtiness(nodeName, CanvasNodeDirtiness.PINNED_DATA_UPDATED);
              continue;
            }
            if ((workflowsStore.getPinnedDataLastRemovedAt(nodeName) ?? 0) > runAt) {
              setDirtiness(nodeName, CanvasNodeDirtiness.PINNED_DATA_UPDATED);
              continue;
            }
          }
          return dirtiness;
        })
      };
    }

    //#endregion
    //#region ../@n8n/stores/src/useAgentRequestStore.ts

    function useRunWorkflow(useRunWorkflowOpts) {
      const workflowHelpers = useWorkflowHelpers();
      const i18n = useI18n();
      const toast = useToast();
      const telemetry = useTelemetry();
      const externalHooks = useExternalHooks();
      const settingsStore = useSettingsStore();
      const agentRequestStore = useAgentRequestStore();
      const rootStore = useRootStore();
      const pushConnectionStore = usePushConnectionStore();
      const workflowsStore = useWorkflowsStore();
      const workflowState = useRunWorkflowOpts.workflowState ?? injectWorkflowState();
      const nodeHelpers = useNodeHelpers({
        workflowState
      });
      const workflowSaving = useWorkflowSaving({
        router: useRunWorkflowOpts.router,
        workflowState
      });
      const executionsStore = useExecutionsStore();
      const {
        dirtinessByName
      } = useNodeDirtiness();
      const {
        startChat
      } = useCanvasOperations();
      const workflowObject = computed(() => workflowsStore.workflowObject);
      function sortNodesByYPosition(nodes) {
        return [...nodes].sort((a, b) => {
          const nodeA = workflowsStore.getNodeByName(a)?.position ?? [0, 0];
          const nodeB = workflowsStore.getNodeByName(b)?.position ?? [0, 0];
          const nodeAYPosition = nodeA[1];
          const nodeBYPosition = nodeB[1];
          if (nodeAYPosition === nodeBYPosition) return 0;
          return nodeAYPosition > nodeBYPosition ? 1 : -1;
        });
      }
      async function runWorkflowApi(runData) {
        if (!pushConnectionStore.isConnected) throw new Error(i18n.baseText("workflowRun.noActiveConnectionToTheServer"));
        workflowsStore.subWorkflowExecutionError = null;
        workflowState.setActiveExecutionId(null);
        let response;
        try {
          response = await workflowsStore.runWorkflow(runData);
        } catch (error) {
          workflowState.setActiveExecutionId(void 0);
          throw error;
        }
        const workflowExecutionIdIsNew = workflowsStore.previousExecutionId !== response.executionId;
        const workflowExecutionIdIsPending = workflowsStore.activeExecutionId === null;
        if (response.executionId && workflowExecutionIdIsNew && workflowExecutionIdIsPending) workflowState.setActiveExecutionId(response.executionId);
        if (response.waitingForWebhook === true && workflowsStore.nodesIssuesExist) {
          workflowState.setActiveExecutionId(void 0);
          throw new Error(i18n.baseText("workflowRun.showError.resolveOutstandingIssues"));
        }
        if (response.waitingForWebhook === true) workflowsStore.executionWaitingForWebhook = true;
        return response;
      }
      async function runWorkflow(options) {
        if (workflowsStore.activeExecutionId) return;
        toast.clearAllStickyNotifications();
        try {
          let directParentNodes = [];
          if (options.destinationNode !== void 0) directParentNodes = workflowObject.value.getParentNodes(options.destinationNode.nodeName, NodeConnectionTypes.Main, -1);
          const runData = workflowsStore.getWorkflowRunData;
          if (workflowsStore.isNewWorkflow) await workflowSaving.saveCurrentWorkflow();
          const workflowData = await workflowHelpers.getWorkflowDataToSave();
          const {
            startNodeNames
          } = consolidateRunDataAndStartNodes(directParentNodes, runData, workflowData.pinData, workflowObject.value);
          const destinationNodeType = options.destinationNode ? workflowsStore.getNodeByName(options.destinationNode.nodeName)?.type : "";
          let executedNode;
          let triggerToStartFrom;
          if (startNodeNames.length === 0 && directParentNodes.length === 0 && "destinationNode" in options && options.destinationNode !== void 0) {
            executedNode = options.destinationNode.nodeName;
            startNodeNames.push(options.destinationNode.nodeName);
          } else if (options.triggerNode && options.nodeData && !options.rerunTriggerNode) startNodeNames.push(...workflowObject.value.getChildNodes(options.triggerNode, NodeConnectionTypes.Main, 1));else if (options.destinationNode) executedNode = options.destinationNode.nodeName;
          if (options.triggerNode) triggerToStartFrom = {
            name: options.triggerNode,
            data: options.nodeData
          };
          if (options.destinationNode && (workflowsStore.checkIfNodeHasChatParent(options.destinationNode.nodeName) || destinationNodeType === "@n8n/n8n-nodes-langchain.chatTrigger") && options.source !== "RunData.ManualChatMessage") {
            const startNode = workflowObject.value.getStartNode(options.destinationNode.nodeName);
            if (startNode && startNode.type === "@n8n/n8n-nodes-langchain.chatTrigger") {
              const chatHasInputData = nodeHelpers.getNodeInputData(startNode, 0, 0, "input")?.length > 0;
              const chatHasPinData = !!workflowData.pinData?.[startNode.name];
              if (!chatHasInputData && !chatHasPinData) {
                workflowsStore.chatPartialExecutionDestinationNode = options.destinationNode.nodeName;
                startChat();
                return;
              }
            }
          }
          const triggers = workflowData.nodes.filter(node => node.type.toLowerCase().includes("trigger") && !node.disabled);
          if (!options.destinationNode && options.source !== "RunData.ManualChatMessage" && workflowData.nodes.some(node => node.type === "@n8n/n8n-nodes-langchain.chatTrigger")) {
            if (triggers.filter(node => node.type !== "@n8n/n8n-nodes-langchain.chatTrigger").length) {
              const chatTriggerNode = workflowData.nodes.find(node => node.type === CHAT_TRIGGER_NODE_TYPE);
              if (chatTriggerNode) chatTriggerNode.disabled = true;
            }
          }
          const isPartialExecution = options.destinationNode !== void 0;
          const startNodes = sortNodesByYPosition(startNodeNames).map(name => {
            let sourceData = (0, import_get.default)(runData, [name, 0, "source", 0], null);
            if (sourceData === null) {
              const parentNodes = workflowObject.value.getParentNodes(name, NodeConnectionTypes.Main, 1);
              sourceData = (0, import_get.default)(workflowHelpers.executeData(workflowObject.value.connectionsBySourceNode, parentNodes, name, NodeConnectionTypes.Main, 0), ["source", NodeConnectionTypes.Main, 0], null);
            }
            return {
              name,
              sourceData
            };
          }).filter(node => {
            if (options.destinationNode && workflowsStore.checkIfNodeHasChatParent(options.destinationNode.nodeName)) return node.name !== options.destinationNode.nodeName;
            return true;
          });
          const singleWebhookTrigger = options.triggerNode === void 0 ? triggers.find(node => SINGLE_WEBHOOK_TRIGGERS.includes(node.type)) : workflowData.nodes.find(node => node.name === options.triggerNode && SINGLE_WEBHOOK_TRIGGERS.includes(node.type));
          if (singleWebhookTrigger && workflowsStore.isWorkflowActive && !workflowData.pinData?.[singleWebhookTrigger.name]) {
            toast.showMessage({
              title: i18n.baseText("workflowRun.showError.deactivate"),
              message: i18n.baseText("workflowRun.showError.productionActive", {
                interpolate: {
                  nodeName: singleWebhookTrigger.name
                }
              }),
              type: "error"
            });
            return;
          }
          const startRunData = {
            workflowData,
            runData: isPartialExecution ? runData ?? void 0 : void 0,
            startNodes,
            triggerToStartFrom
          };
          if ("destinationNode" in options) {
            startRunData.destinationNode = options.destinationNode;
            const nodeId = workflowsStore.getNodeByName(options.destinationNode?.nodeName ?? "")?.id;
            if (workflowObject.value.id && nodeId) {
              const agentRequest = agentRequestStore.getAgentRequest(workflowObject.value.id, nodeId);
              if (agentRequest) startRunData.agentRequest = {
                query: agentRequest.query ?? {},
                tool: {
                  name: agentRequest.toolName ?? ""
                }
              };
            }
          }
          if (startRunData.runData) {
            const nodeNames = Object.entries(dirtinessByName.value).flatMap(([nodeName, dirtiness]) => dirtiness ? [nodeName] : []);
            startRunData.dirtyNodeNames = nodeNames.length > 0 ? nodeNames : void 0;
          }
          const executionData = {
            id: IN_PROGRESS_EXECUTION_ID,
            finished: false,
            mode: "manual",
            status: "running",
            createdAt: /* @__PURE__ */new Date(),
            startedAt: /* @__PURE__ */new Date(),
            stoppedAt: void 0,
            workflowId: workflowObject.value.id,
            executedNode,
            triggerNode: triggerToStartFrom?.name,
            data: createRunExecutionData({
              resultData: {
                runData: startRunData.runData ?? {},
                pinData: workflowData.pinData
              }
            }),
            workflowData: {
              id: workflowsStore.workflowId,
              name: workflowData.name,
              active: workflowData.active,
              createdAt: 0,
              updatedAt: 0,
              ...workflowData
            }
          };
          workflowState.setWorkflowExecutionData(executionData);
          nodeHelpers.updateNodesExecutionIssues();
          useDocumentTitle().setDocumentTitle(workflowObject.value.name, "EXECUTING");
          const runWorkflowApiResponse = await runWorkflowApi(startRunData);
          const pinData = workflowData.pinData ?? {};
          const getTestUrl = (() => {
            return node => {
              const path = node.parameters.path || node.parameters.options?.path || node.webhookId;
              return `${rootStore.formTestUrl}/${path}`;
            };
          })();
          try {
            await displayForm({
              nodes: workflowData.nodes,
              runData: workflowsStore.getWorkflowExecution?.data?.resultData?.runData,
              destinationNode: options.destinationNode?.nodeName,
              triggerNode: options.triggerNode,
              pinData,
              directParentNodes,
              source: options.source,
              getTestUrl
            });
          } catch (error) {}
          await externalHooks.run("workflowRun.runWorkflow", {
            nodeName: options.destinationNode?.nodeName,
            source: options.source
          });
          return runWorkflowApiResponse;
        } catch (error) {
          workflowState.setWorkflowExecutionData(null);
          useDocumentTitle().setDocumentTitle(workflowObject.value.name, "ERROR");
          toast.showError(error, i18n.baseText("workflowRun.showError.title"));
          return;
        }
      }
      function consolidateRunDataAndStartNodes(directParentNodes, runData, pinData, workflow) {
        const startNodeNames = /* @__PURE__ */new Set();
        let newRunData;
        if (runData !== null && Object.keys(runData).length !== 0) {
          newRunData = {};
          for (const directParentNode of directParentNodes) {
            const parentNodes = workflow.getParentNodes(directParentNode, NodeConnectionTypes.Main);
            if (workflow.nodes[directParentNode].disabled) continue;
            parentNodes.push(directParentNode);
            for (const parentNode of parentNodes) {
              if (!runData[parentNode]?.length && !pinData?.[parentNode]?.length || runData[parentNode]?.[0]?.error !== void 0) {
                startNodeNames.add(parentNode);
                break;
              }
              if (runData[parentNode] && !runData[parentNode]?.[0]?.error) newRunData[parentNode] = runData[parentNode]?.slice(0, 1);
            }
          }
          if (isEmpty(newRunData)) newRunData = void 0;
        }
        return {
          runData: newRunData,
          startNodeNames: [...startNodeNames]
        };
      }
      async function stopCurrentExecution() {
        const executionId = workflowsStore.activeExecutionId;
        let stopData;
        if (!executionId) return;
        try {
          stopData = await executionsStore.stopCurrentExecution(executionId);
        } catch (error) {
          const execution = await workflowsStore.getExecution(executionId);
          if (execution === void 0) toast.showMessage({
            title: i18n.baseText("nodeView.showMessage.stopExecutionCatch.unsaved.title"),
            message: i18n.baseText("nodeView.showMessage.stopExecutionCatch.unsaved.message"),
            type: "success"
          });else if (execution?.finished) {
            const executedData = {
              data: execution.data,
              workflowData: workflowsStore.workflow,
              finished: execution.finished,
              mode: execution.mode,
              startedAt: execution.startedAt,
              stoppedAt: execution.stoppedAt
            };
            workflowState.setWorkflowExecutionData(executedData);
            toast.showMessage({
              title: i18n.baseText("nodeView.showMessage.stopExecutionCatch.title"),
              message: i18n.baseText("nodeView.showMessage.stopExecutionCatch.message"),
              type: "success"
            });
          } else toast.showError(error, i18n.baseText("nodeView.showError.stopExecution.title"));
        } finally {
          if (!(await retry(async () => {
            const execution = await workflowsStore.getExecution(executionId);
            if (!["running", "waiting"].includes(execution?.status)) {
              workflowState.markExecutionAsStopped(stopData);
              return true;
            }
            return false;
          }, 250, 20))) workflowState.markExecutionAsStopped(stopData);
        }
      }
      async function stopWaitingForWebhook() {
        try {
          await workflowsStore.removeTestWebhook(workflowsStore.workflowId);
        } catch (error) {
          toast.showError(error, i18n.baseText("nodeView.showError.stopWaitingForWebhook.title"));
          return;
        }
      }
      async function runEntireWorkflow(source, triggerNode) {
        workflowHelpers.getWorkflowDataToSave().then(workflowData => {
          const telemetryPayload = {
            workflow_id: workflowObject.value.id,
            node_graph_string: JSON.stringify(generateNodesGraph(workflowData, workflowHelpers.getNodeTypes(), {
              isCloudDeployment: settingsStore.isCloudDeployment
            }).nodeGraph),
            button_type: source
          };
          telemetry.track("User clicked execute workflow button", telemetryPayload);
          externalHooks.run("nodeView.onRunWorkflow", telemetryPayload);
        });
        runWorkflow({
          triggerNode: triggerNode ?? workflowsStore.selectedTriggerNodeName
        });
      }
      return {
        consolidateRunDataAndStartNodes,
        runEntireWorkflow,
        runWorkflow,
        runWorkflowApi,
        stopCurrentExecution,
        stopWaitingForWebhook,
        sortNodesByYPosition
      };
    }

    //#endregion
    _export({
      a: proxy,
      o: wrap,
      r: useNodeDirtiness,
      t: useRunWorkflow
    });
    return {
      setters: [function (_chunkLegacy001Js) {
        __toESM = _chunkLegacy001Js.o;
      }, function (_vueRuntimeEsmBundlerLegacy003Js) {
        computed = _vueRuntimeEsmBundlerLegacy003Js.C;
        ref = _vueRuntimeEsmBundlerLegacy003Js.It;
        watch = _vueRuntimeEsmBundlerLegacy003Js._t;
      }, function (_MapCacheLegacy005Js) {
        useI18n = _MapCacheLegacy005Js.gt;
        useLocalStorage = _MapCacheLegacy005Js.j;
      }, function (_truncateLegacy00hJs) {
        require_get = _truncateLegacy00hJs.r;
      }, function (_useTelemetryLegacy00HJs) {
        EnableNodeToggleCommand = _useTelemetryLegacy00HJs.Ar;
        CanvasNodeDirtiness = _useTelemetryLegacy00HJs.Cr;
        AddNodeCommand = _useTelemetryLegacy00HJs.Dr;
        AddConnectionCommand = _useTelemetryLegacy00HJs.Er;
        useSettingsStore = _useTelemetryLegacy00HJs.Ho;
        RemoveConnectionCommand = _useTelemetryLegacy00HJs.Mr;
        RemoveNodeCommand = _useTelemetryLegacy00HJs.Nr;
        BulkCommand = _useTelemetryLegacy00HJs.Or;
        injectWorkflowState = _useTelemetryLegacy00HJs.Sn;
        useDocumentTitle = _useTelemetryLegacy00HJs.Tn;
        useHistoryStore = _useTelemetryLegacy00HJs.Tr;
        displayForm = _useTelemetryLegacy00HJs.X;
        useWorkflowHelpers = _useTelemetryLegacy00HJs.mn;
        useWorkflowsStore = _useTelemetryLegacy00HJs.o;
        STORES = _useTelemetryLegacy00HJs.oc;
        useTelemetry = _useTelemetryLegacy00HJs.t;
        isEmpty = _useTelemetryLegacy00HJs.vi;
        useNodeHelpers = _useTelemetryLegacy00HJs.xn;
      }, function (_useToastLegacy00JJs) {
        useToast = _useToastLegacy00JJs.t;
      }, function (_constantsLegacy00TJs) {
        CHAT_TRIGGER_NODE_TYPE = _constantsLegacy00TJs.Bt;
        LOCAL_STORAGE_RUN_DATA_WORKER = _constantsLegacy00TJs.Fs;
        createRunExecutionData = _constantsLegacy00TJs.Gi;
        NodeConnectionTypes = _constantsLegacy00TJs.Ka;
        IN_PROGRESS_EXECUTION_ID = _constantsLegacy00TJs.N;
        generateNodesGraph = _constantsLegacy00TJs.Zi;
        createHeartbeatMessage = _constantsLegacy00TJs.Zr;
        SINGLE_WEBHOOK_TRIGGERS = _constantsLegacy00TJs.ir;
      }, function (_baseOrderByLegacy00ZJs) {
        defineStore = _baseOrderByLegacy00ZJs.k;
        useRootStore = _baseOrderByLegacy00ZJs.r;
      }, function (_useExternalHooksLegacy013Js) {
        useExternalHooks = _useExternalHooksLegacy013Js.t;
      }, function (_useWorkflowSavingLegacy01jJs) {
        useWorkflowSaving = _useWorkflowSavingLegacy01jJs.t;
      }, function (_retryLegacy01lJs) {
        retry = _retryLegacy01lJs.t;
      }, function (_executionsStoreLegacy01nJs) {
        useExecutionsStore = _executionsStoreLegacy01nJs.t;
      }, function (_useCanvasOperationsLegacy01zJs) {
        useCanvasOperations = _useCanvasOperationsLegacy01zJs.t;
      }],
      execute: function () {
        //#region src/app/push-connection/useHeartbeat.ts
        /**
        * Creates a heartbeat timer using the given interval. The timer needs
        * to be started and stopped manually.
        */
        useHeartbeat = options => {
          const {
            interval,
            onHeartbeat
          } = options;
          const heartbeatTimer = ref(null);
          const startHeartbeat = () => {
            heartbeatTimer.value = setInterval(onHeartbeat, interval);
          };
          const stopHeartbeat = () => {
            if (heartbeatTimer.value) {
              clearInterval(heartbeatTimer.value);
              heartbeatTimer.value = null;
            }
          };
          return {
            startHeartbeat,
            stopHeartbeat
          };
        }; //#endregion
        //#region src/app/push-connection/useReconnectTimer.ts
        /**
        * A timer for exponential backoff reconnect attempts.
        */
        useReconnectTimer = ({
          onAttempt,
          onAttemptScheduled
        }) => {
          const initialReconnectDelay = 1e3;
          const maxReconnectDelay = 15e3;
          const reconnectTimer = ref(null);
          const reconnectAttempts = ref(0);
          const scheduleReconnect = () => {
            const delay = Math.min(initialReconnectDelay * 2 ** reconnectAttempts.value, maxReconnectDelay);
            reconnectAttempts.value++;
            onAttemptScheduled(delay);
            reconnectTimer.value = setTimeout(() => {
              onAttempt();
            }, delay);
          };
          /** Stops the reconnect timer. NOTE: This does not reset the reconnect attempts. */
          const stopReconnectTimer = () => {
            if (reconnectTimer.value) {
              clearTimeout(reconnectTimer.value);
              reconnectTimer.value = null;
            }
          };
          const resetConnectionAttempts = () => {
            reconnectAttempts.value = 0;
          };
          return {
            scheduleReconnect,
            stopReconnectTimer,
            resetConnectionAttempts
          };
        }; //#endregion
        //#region src/app/push-connection/useWebSocketClient.ts
        /**
        * Creates a WebSocket connection to the server. Uses reconnection logic
        * to reconnect if the connection is lost.
        */
        useWebSocketClient = options => {
          const isConnected = ref(false);
          const socket = ref(null);
          /**
          * Heartbeat timer to keep the connection alive. This is an additional
          * mechanism to the protocol level ping/pong mechanism the server sends.
          * This is used the ensure the client notices connection issues.
          */
          const {
            startHeartbeat,
            stopHeartbeat
          } = useHeartbeat({
            interval: 3e4,
            onHeartbeat: () => {
              socket.value?.send(JSON.stringify(createHeartbeatMessage()));
            }
          });
          const onConnected = () => {
            socket.value?.removeEventListener("open", onConnected);
            isConnected.value = true;
            startHeartbeat();
            reconnectTimer.resetConnectionAttempts();
          };
          const onConnectionLost = event => {
            console.warn(`[WebSocketClient] Connection lost, code=${event.code ?? "unknown"}`);
            disconnect();
            reconnectTimer.scheduleReconnect();
          };
          const onMessage = event => {
            options.onMessage(event.data);
          };
          const onError = error => {
            console.warn("[WebSocketClient] Connection error:", error);
          };
          const disconnect = () => {
            if (socket.value) {
              stopHeartbeat();
              reconnectTimer.stopReconnectTimer();
              socket.value.removeEventListener("message", onMessage);
              socket.value.removeEventListener("error", onError);
              socket.value.removeEventListener("close", onConnectionLost);
              socket.value.close(1e3);
              socket.value = null;
            }
            isConnected.value = false;
          };
          const connect = () => {
            disconnect();
            socket.value = new WebSocket(options.url);
            socket.value.addEventListener("open", onConnected);
            socket.value.addEventListener("message", onMessage);
            socket.value.addEventListener("error", onError);
            socket.value.addEventListener("close", onConnectionLost);
            socket.value.binaryType = "arraybuffer";
          };
          const reconnectTimer = useReconnectTimer({
            onAttempt: connect,
            onAttemptScheduled: delay => {
              console.log(`[WebSocketClient] Attempting to reconnect in ${delay}ms`);
            }
          });
          const sendMessage = serializedMessage => {
            if (!isConnected.value || !socket.value) throw new Error("Not connected to the server");
            socket.value.send(serializedMessage);
          };
          return {
            isConnected,
            connect,
            disconnect,
            sendMessage
          };
        }; //#endregion
        //#region src/app/push-connection/useEventSourceClient.ts
        /**
        * Creates an EventSource connection to the server. Uses reconnection logic
        * to reconnect if the connection is lost.
        */
        useEventSourceClient = options => {
          const isConnected = ref(false);
          const eventSource = ref(null);
          const onConnected = () => {
            isConnected.value = true;
            reconnectTimer.resetConnectionAttempts();
          };
          const onConnectionLost = () => {
            console.warn("[EventSourceClient] Connection lost");
            isConnected.value = false;
            reconnectTimer.scheduleReconnect();
          };
          const onMessage = event => {
            options.onMessage(event.data);
          };
          const disconnect = () => {
            if (eventSource.value) {
              reconnectTimer.stopReconnectTimer();
              eventSource.value.close();
              eventSource.value = null;
            }
            isConnected.value = false;
          };
          const connect = () => {
            disconnect();
            eventSource.value = new EventSource(options.url, {
              withCredentials: true
            });
            eventSource.value.addEventListener("open", onConnected);
            eventSource.value.addEventListener("message", onMessage);
            eventSource.value.addEventListener("close", onConnectionLost);
          };
          const reconnectTimer = useReconnectTimer({
            onAttempt: connect,
            onAttemptScheduled: delay => {
              console.log(`[EventSourceClient] Attempting to reconnect in ${delay}ms`);
            }
          });
          const sendMessage = _ => {};
          return {
            isConnected,
            connect,
            disconnect,
            sendMessage
          };
        }; //#endregion
        //#region ../../../node_modules/.pnpm/comlink@4.4.1/node_modules/comlink/dist/esm/comlink.mjs
        /**
        * @license
        * Copyright 2019 Google LLC
        * SPDX-License-Identifier: Apache-2.0
        */
        proxyMarker = Symbol("Comlink.proxy");
        createEndpoint = Symbol("Comlink.endpoint");
        releaseProxy = Symbol("Comlink.releaseProxy");
        finalizer = Symbol("Comlink.finalizer");
        throwMarker = Symbol("Comlink.thrown");
        isObject = val => typeof val === "object" && val !== null || typeof val === "function";
        /**
        * Allows customizing the serialization of certain values.
        */
        transferHandlers = new Map([["proxy", {
          canHandle: val => isObject(val) && val[proxyMarker],
          serialize(obj) {
            const {
              port1,
              port2
            } = new MessageChannel();
            expose(obj, port1);
            return [port2, [port2]];
          },
          deserialize(port) {
            port.start();
            return wrap(port);
          }
        }], ["throw", {
          canHandle: value => isObject(value) && throwMarker in value,
          serialize({
            value
          }) {
            let serialized;
            if (value instanceof Error) serialized = {
              isError: true,
              value: {
                message: value.message,
                name: value.name,
                stack: value.stack
              }
            };else serialized = {
              isError: false,
              value
            };
            return [serialized, []];
          },
          deserialize(serialized) {
            if (serialized.isError) throw Object.assign(new Error(serialized.value.message), serialized.value);
            throw serialized.value;
          }
        }]]);
        proxyCounter = /* @__PURE__ */new WeakMap();
        proxyFinalizers = "FinalizationRegistry" in globalThis && new FinalizationRegistry(ep => {
          const newCount = (proxyCounter.get(ep) || 0) - 1;
          proxyCounter.set(ep, newCount);
          if (newCount === 0) releaseEndpoint(ep);
        });
        transferCache = /* @__PURE__ */new WeakMap();
        worker = new Worker(new URL(/* @vite-ignore */
        "/%7B%7BBASE_PATH%7D%7D/assets/worker-CIvWfg3a.js", "" + _context.meta.url), {
          type: "module"
        });
        runDataWorker = wrap(worker); //#endregion
        //#region src/app/stores/pushConnection.store.ts
        /**
        * Store for managing a push connection to the server
        */
        _export("i", usePushConnectionStore = defineStore(STORES.PUSH, () => {
          const rootStore = useRootStore();
          const settingsStore = useSettingsStore();
          const isRunDataWorkerEnabled = useLocalStorage(LOCAL_STORAGE_RUN_DATA_WORKER, false);
          /**
          * Queue of messages to be sent to the server. Messages are queued if
          * the connection is down.
          */
          const outgoingQueue = ref([]);
          /** Whether the connection has been requested */
          const isConnectionRequested = ref(false);
          const onMessageReceivedHandlers = ref([]);
          const addEventListener = handler => {
            onMessageReceivedHandlers.value.push(handler);
            return () => {
              const index = onMessageReceivedHandlers.value.indexOf(handler);
              if (index !== -1) onMessageReceivedHandlers.value.splice(index, 1);
            };
          };
          const useWebSockets = computed(() => settingsStore.pushBackend === "websocket");
          const getConnectionUrl = () => {
            const restUrl = rootStore.restUrl;
            const url$1 = `/push?pushRef=${rootStore.pushRef}`;
            if (useWebSockets.value) {
              const {
                protocol,
                host
              } = window.location;
              return `${restUrl.startsWith("http") ? restUrl.replace(/^http/, "ws") : `${protocol === "https:" ? "wss" : "ws"}://${host + restUrl}`}${url$1}`;
            } else return `${restUrl}${url$1}`;
          };
          /**
          * Process a newly received message
          */
          async function onMessage(data) {
            if (data instanceof ArrayBuffer) if (isRunDataWorkerEnabled.value) {
              await runDataWorker.onNodeExecuteAfterData(data);
              return;
            } else data = new TextDecoder("utf-8").decode(new Uint8Array(data));
            let parsedData;
            try {
              parsedData = JSON.parse(data);
            } catch (error) {
              return;
            }
            onMessageReceivedHandlers.value.forEach(handler => handler(parsedData));
          }
          const url = getConnectionUrl();
          const client = computed(() => useWebSockets.value ? useWebSocketClient({
            url,
            onMessage
          }) : useEventSourceClient({
            url,
            onMessage
          }));
          function serializeAndSend(message) {
            if (client.value.isConnected.value) client.value.sendMessage(JSON.stringify(message));else outgoingQueue.value.push(message);
          }
          const pushConnect = () => {
            isConnectionRequested.value = true;
            client.value.connect();
          };
          const pushDisconnect = () => {
            isConnectionRequested.value = false;
            client.value.disconnect();
          };
          watch(() => client.value.isConnected.value, didConnect => {
            if (!didConnect) return;
            if (outgoingQueue.value.length) {
              for (const message of outgoingQueue.value) serializeAndSend(message);
              outgoingQueue.value = [];
            }
          });
          /** Removes all buffered messages from the sent queue */
          const clearQueue = () => {
            outgoingQueue.value = [];
          };
          return {
            isConnected: computed(() => client.value.isConnected.value),
            isConnectionRequested,
            onMessageReceivedHandlers,
            addEventListener,
            pushConnect,
            pushDisconnect,
            send: serializeAndSend,
            clearQueue
          };
        }));
        LOCAL_STORAGE_AGENT_REQUESTS = "N8N_AGENT_REQUESTS";
        _export("n", useAgentRequestStore = defineStore("agentRequest", () => {
          const agentRequests = useLocalStorage(LOCAL_STORAGE_AGENT_REQUESTS, {});
          const ensureWorkflowAndNodeExist = (workflowId, nodeId) => {
            if (!agentRequests.value[workflowId]) agentRequests.value[workflowId] = {};
            if (!agentRequests.value[workflowId][nodeId]) agentRequests.value[workflowId][nodeId] = {
              query: {}
            };
          };
          const getAgentRequests = (workflowId, nodeId) => {
            return agentRequests.value[workflowId]?.[nodeId]?.query || {};
          };
          const getQueryValue = (workflowId, nodeId, paramName) => {
            const query = agentRequests.value[workflowId]?.[nodeId]?.query;
            if (typeof query === "string") return;
            return query?.[paramName];
          };
          const setAgentRequestForNode = (workflowId, nodeId, request) => {
            ensureWorkflowAndNodeExist(workflowId, nodeId);
            agentRequests.value[workflowId][nodeId] = {
              ...request,
              query: typeof request.query === "string" ? request.query : {
                ...request.query
              }
            };
          };
          const clearAgentRequests = (workflowId, nodeId) => {
            if (agentRequests.value[workflowId]) agentRequests.value[workflowId][nodeId] = {
              query: {}
            };
          };
          const clearAllAgentRequests = workflowId => {
            if (workflowId) agentRequests.value[workflowId] = {};else agentRequests.value = {};
          };
          const getAgentRequest = (workflowId, nodeId) => {
            if (agentRequests.value[workflowId]) return agentRequests.value[workflowId]?.[nodeId];
          };
          return {
            agentRequests,
            getAgentRequests,
            getQueryValue,
            setAgentRequestForNode,
            clearAgentRequests,
            clearAllAgentRequests,
            getAgentRequest
          };
        })); //#endregion
        //#region src/app/composables/useRunWorkflow.ts
        import_get = /* @__PURE__ */__toESM(require_get());
      }
    };
  });
})();