UNPKG

n8n-editor-ui

Version:

Workflow Editor UI for n8n

1,041 lines 65.8 kB
;
(function () {
  System.register(["./chunk-legacy-Re9CbdfL.js", "./vue.runtime.esm-bundler-legacy--Sn1h8On.js", "./_MapCache-legacy-DlYNX_X1.js", "./src-legacy-uZTNWMC0.js", "./_plugin-vue_export-helper-legacy-DZMI5HPp.js", "./truncate-legacy-BGje52Or.js", "./useTelemetry-legacy-B3pzzkAE.js", "./useToast-legacy-C4Vu5mt9.js", "./constants-legacy-TKxWCqvM.js", "./_baseOrderBy-legacy-CB2Dh5d_.js", "./useRunWorkflow-legacy-BClq6Sr5.js", "./NodeIcon-legacy-D0j2KPV5.js", "./isEmpty-legacy-SNiUTa-Q.js", "./dateFormatter-legacy-V7YuOSR6.js", "./AnimatedSpinner-legacy-jmjQlQzV.js"], function (_export, _context) {
    "use strict";

    var __toESM, computed, toDisplayString, createElementBlock, createCommentVNode, nextTick, unref, ref, createVNode, defineComponent, createBlock, toRef, mergeProps, Fragment, watch, normalizeStyle, withCtx, openBlock, withModifiers, renderList, createTextVNode, useTemplateRef, normalizeClass, createBaseVNode, shallowRef, useVirtualList, I18nT, useI18n, useThrottleFn, useTimestamp, N8nButton_default, N8nText_default, N8nIcon_default, N8nTooltip_default, N8nIconButton_default, __plugin_vue_export_helper_default, require_get, useRouter, emptyTokenUsageData, formatTokenUsageCount, v4_default, require_upperFirst, injectWorkflowState, addTokenUsageData, useNodeTypesStore, useWorkflowsStore, isChatNode, parse, useNodeHelpers, useToast, CHAT_TRIGGER_NODE_TYPE, createRunExecutionData, NodeConnectionTypes, MANUAL_CHAT_TRIGGER_NODE_TYPE, createEmptyRunExecutionData, AGENT_LANGCHAIN_NODE_TYPE, LOGS_EXECUTION_DATA_THROTTLE_DURATION, parseErrorMetadata, Workflow, PLACEHOLDER_EMPTY_WORKFLOW_ID, TOOL_EXECUTOR_NODE_NAME, useRunWorkflow, NodeIcon_default, require_isEmpty, toTime, toDayMonth, AnimatedSpinner_default, __vite_style__, import_get, import_isEmpty, ConsumedTokensDetails_vue_vue_type_script_setup_true_lang_default, ConsumedTokensDetails_default, LogsViewConsumedTokenCountText_vue_vue_type_script_setup_true_lang_default, LogsViewConsumedTokenCountText_default, _hoisted_1$1, LogsViewNodeName_vue_vue_type_script_setup_true_lang_default, name$1, LogsViewNodeName_vue_vue_type_style_index_0_lang_module_default, cssModules$2, LogsViewNodeName_default, import_upperFirst, _hoisted_1, LogsOverviewRow_vue_vue_type_script_setup_true_lang_default, container$1, background, selected, error, indent, connectorCurved, connectorStraight, icon, name, timeTook, statusTextIcon, startedAt, consumedTokens, compactErrorIcon, partialExecutionButton, openNdvButton, compact, unavailable, toggleButton, statusIcon, placeholder, LogsOverviewRow_vue_vue_type_style_index_0_lang_module_default, cssModules$1, LogsOverviewRow_default, LogsOverviewRows_vue_vue_type_script_setup_true_lang_default, tree, container, staticScrollBar, LogsOverviewRows_vue_vue_type_style_index_0_lang_module_default, cssModules, LogsOverviewRows_default;
    function getConsumedTokens(task) {
      return task.reduce((acc, curr) => {
        const tokenUsageData = curr?.json?.tokenUsage ?? curr?.json?.tokenUsageEstimate;
        if (!tokenUsageData) return acc;
        return addTokenUsageData(acc, {
          ...tokenUsageData,
          isEstimate: !!curr?.json.tokenUsageEstimate
        });
      }, emptyTokenUsageData);
    }
    function getConsumedTokensFromTaskData(runData) {
      return getConsumedTokens(Object.values(runData.data ?? {}).flat().flat());
    }
    function createNode(node, context, runIndex, runData, children = []) {
      return {
        parent: context.parent,
        node,
        id: `${context.workflow.id}:${node.id}:${[...context.ancestorRunIndexes, runIndex].join(":")}`,
        runIndex,
        runData,
        children,
        consumedTokens: runData ? getConsumedTokensFromTaskData(runData) : emptyTokenUsageData,
        workflow: context.workflow,
        executionId: context.executionId,
        execution: context.data,
        isSubExecution: context.isSubExecution
      };
    }
    function getChildNodes(treeNode, node, runIndex, context) {
      const subExecutionLocator = findSubExecutionLocator(treeNode);
      if (subExecutionLocator !== void 0) {
        const workflow = context.workflows[subExecutionLocator.workflowId];
        const subWorkflowRunData = context.subWorkflowData[subExecutionLocator.executionId];
        if (!workflow || !subWorkflowRunData) return [];
        return createLogTreeRec(void 0, {
          ...context,
          parent: treeNode,
          ancestorRunIndexes: [...context.ancestorRunIndexes, runIndex ?? 0],
          workflow,
          executionId: subExecutionLocator.executionId,
          data: subWorkflowRunData,
          isSubExecution: true
        });
      }
      const connectedSubNodes = context.workflow.getParentNodes(node.name, "ALL_NON_MAIN", 1);
      function isMatchedSource(source) {
        return (source?.previousNode === node.name || isPlaceholderLog(treeNode) && source?.previousNode === "PartialExecutionToolExecutor") && (runIndex === void 0 || source.previousNodeRun === runIndex);
      }
      return connectedSubNodes.flatMap(subNodeName => (context.data.resultData.runData[subNodeName] ?? []).flatMap((t, index) => {
        if (!(t.source.some(source => source !== null) ? t.source.some(isMatchedSource) : runIndex === void 0 || index === runIndex)) return [];
        const subNode = context.workflow.getNode(subNodeName);
        return subNode ? getTreeNodeData(subNode, t, index, {
          ...context,
          ancestorRunIndexes: [...context.ancestorRunIndexes, runIndex ?? 0],
          parent: treeNode
        }) : [];
      }));
    }
    function getTreeNodeData(node, runData, runIndex, context) {
      const treeNode = createNode(node, context, runIndex ?? 0, runData);
      const children = getChildNodes(treeNode, node, runIndex, context).sort(sortLogEntries);
      if ((runData === void 0 || node.disabled) && children.length === 0) return [];
      treeNode.children = children;
      return [treeNode];
    }
    function getTotalConsumedTokens(...usage) {
      return usage.reduce(addTokenUsageData, emptyTokenUsageData);
    }
    function getSubtreeTotalConsumedTokens(treeNode, includeSubWorkflow) {
      const executionId = treeNode.executionId;
      function calculate(currentNode) {
        if (!includeSubWorkflow && currentNode.executionId !== executionId) return emptyTokenUsageData;
        return getTotalConsumedTokens(currentNode.consumedTokens, ...currentNode.children.map(calculate));
      }
      return calculate(treeNode);
    }
    function findLogEntryToAutoSelect(subTree) {
      const entryWithError = findLogEntryRec(e => !!e.runData?.error, subTree);
      if (entryWithError) return entryWithError;
      const entryForAiAgent = findLogEntryRec(entry => entry.node.type === "@n8n/n8n-nodes-langchain.agent" || entry.parent?.node.type === "@n8n/n8n-nodes-langchain.agent" && isPlaceholderLog(entry.parent), subTree);
      if (entryForAiAgent) return entryForAiAgent;
      return subTree[subTree.length - 1];
    }
    function createLogTreeRec(filter, context) {
      const runData = context.data.resultData.runData;
      return Object.entries(runData).flatMap(([nodeName, taskData]) => {
        const node = context.workflow.getNode(nodeName);
        if (node === null || filter && filter.rootNodeId !== node.id) return [];
        const childNodes = context.workflow.getChildNodes(nodeName, "ALL_NON_MAIN");
        if (childNodes.length === 0) {
          const taskDataList = taskData.map((task, runIndex) => ({
            node,
            task,
            runIndex,
            nodeHasMultipleRuns: taskData.length > 1
          }));
          return filter ? taskDataList.filter(item => item.runIndex === filter.rootNodeRunIndex) : taskDataList;
        }
        if (childNodes.some(child => (runData[child] ?? []).length > 0)) return [];
        const firstChild = context.workflow.getNode(childNodes[0]);
        if (firstChild === null) return [];
        return [{
          node: firstChild,
          nodeHasMultipleRuns: false
        }];
      }).flatMap(({
        node,
        runIndex,
        task,
        nodeHasMultipleRuns
      }) => getTreeNodeData(node, task, nodeHasMultipleRuns ? runIndex : void 0, context)).sort(sortLogEntries);
    }
    function createLogTree(workflow, response, workflows = {}, subWorkflowData = {}, filter) {
      return createLogTreeRec(filter, {
        parent: void 0,
        ancestorRunIndexes: [],
        executionId: response.id,
        workflow,
        workflows,
        data: response.data ?? createEmptyRunExecutionData(),
        subWorkflowData,
        isSubExecution: false
      });
    }
    function findLogEntryById(id, entries) {
      return findLogEntryRec(entry => entry.id === id, entries);
    }
    function findLogEntryRec(isMatched, entries) {
      for (const entry of entries) {
        if (isMatched(entry)) return entry;
        const child = findLogEntryRec(isMatched, entry.children);
        if (child) return child;
      }
    }
    function findSelectedLogEntry(selection, entries, isExecuting) {
      switch (selection.type) {
        case "initial":
          return isExecuting ? void 0 : findLogEntryToAutoSelect(entries);
        case "none":
          return;
        case "selected":
          {
            const found = findLogEntryRec(e => e.id === selection.entry.id, entries);
            if (found === void 0 && !isExecuting) for (let runIndex = selection.entry.runIndex - 1; runIndex >= 0; runIndex--) {
              const fallback = findLogEntryRec(e => e.workflow.id === selection.entry.workflow.id && e.node.id === selection.entry.node.id && e.runIndex === runIndex, entries);
              if (fallback !== void 0) return fallback;
            }
            return found;
          }
      }
    }
    function flattenLogEntries(entries, collapsedEntryIds, ret = []) {
      for (const entry of entries) {
        ret.push(entry);
        if (!collapsedEntryIds[entry.id]) flattenLogEntries(entry.children, collapsedEntryIds, ret);
      }
      return ret;
    }
    function getEntryAtRelativeIndex(entries, id, relativeIndex) {
      const offset = entries.findIndex(e => e.id === id);
      return offset === -1 ? void 0 : entries[offset + relativeIndex];
    }
    function sortLogEntries(a, b) {
      if (a.runData === void 0) return a.children.length > 0 ? sortLogEntries(a.children[0], b) : 0;
      if (b.runData === void 0) return b.children.length > 0 ? sortLogEntries(a, b.children[0]) : 0;
      if (a.runData.startTime === b.runData.startTime) return a.runData.executionIndex - b.runData.executionIndex;
      return a.runData.startTime - b.runData.startTime;
    }
    function mergeStartData(startData, response) {
      if (!response.data) return response;
      const nodeNames = [...new Set(Object.keys(startData).concat(Object.keys(response.data.resultData.runData))).values()];
      const runData = Object.fromEntries(nodeNames.map(nodeName => {
        const tasks = response.data?.resultData.runData[nodeName] ?? [];
        return [nodeName, tasks.concat((startData[nodeName] ?? []).filter(task => tasks.every(t => t.startTime < task.startTime && t.executionIndex !== task.executionIndex)).map(task => ({
          ...task,
          executionTime: 0,
          executionStatus: "running"
        })))];
      }));
      return {
        ...response,
        data: {
          ...response.data,
          resultData: {
            ...response.data.resultData,
            runData
          }
        }
      };
    }
    function hasSubExecution(entry) {
      return findSubExecutionLocator(entry) !== void 0;
    }
    function findSubExecutionLocator(entry) {
      const metadata = entry.runData?.metadata?.subExecution;
      if (metadata) return {
        workflowId: metadata.workflowId,
        executionId: metadata.executionId
      };
      return parseErrorMetadata(entry.runData?.error)?.subExecution;
    }
    function getDepth(entry) {
      let depth = 0;
      let currentEntry = entry;
      while (currentEntry.parent !== void 0) {
        currentEntry = currentEntry.parent;
        depth++;
      }
      return depth;
    }
    function getInputKey(node) {
      if (node.type === "@n8n/n8n-nodes-langchain.manualChatTrigger" && node.typeVersion < 1.1) return "input";
      if (node.type === "@n8n/n8n-nodes-langchain.chatTrigger") return "chatInput";
      return "chatInput";
    }
    function extractChatInput(workflow, resultData) {
      const chatTrigger = workflow.nodes.find(isChatNode);
      if (chatTrigger === void 0) return;
      const inputKey = getInputKey(chatTrigger);
      const runData = (resultData.runData[chatTrigger.name] ?? [])[0];
      const message = runData?.data?.[NodeConnectionTypes.Main]?.[0]?.[0]?.json?.[inputKey];
      if (runData === void 0 || typeof message !== "string") return;
      return {
        text: message,
        sender: "user",
        id: v4_default()
      };
    }
    function extractBotResponse(resultData, executionId, emptyText) {
      const lastNodeExecuted = resultData.lastNodeExecuted;
      if (!lastNodeExecuted) return void 0;
      const nodeResponseDataArray = (0, import_get.default)(resultData.runData, lastNodeExecuted) ?? [];
      const nodeResponseData = nodeResponseDataArray[nodeResponseDataArray.length - 1];
      let responseMessage;
      if ((0, import_get.default)(nodeResponseData, "error")) responseMessage = "[ERROR: " + (0, import_get.default)(nodeResponseData, "error.message") + "]";else {
        const mainOutputs = (0, import_get.default)(nodeResponseData, "data.main");
        let text;
        if (mainOutputs && Array.isArray(mainOutputs)) {
          for (const branch of mainOutputs) if (branch?.[0]?.json) {
            const responseData = branch[0].json;
            text = extractResponseText(responseData);
            if (text) break;
          }
        }
        text = text ?? emptyText;
        if (!text) return;
        responseMessage = text;
      }
      return {
        text: responseMessage,
        sender: "bot",
        id: executionId ?? v4_default()
      };
    }
    /** Extracts response message from workflow output */
    function extractResponseText(responseData) {
      if (!responseData || (0, import_isEmpty.default)(responseData)) return;
      const matchedPath = ["output", "text", "response.text", "message"].find(path => (0, import_get.default)(responseData, path));
      if (!matchedPath) return JSON.stringify(responseData, null, 2);
      const matchedOutput = (0, import_get.default)(responseData, matchedPath);
      if (typeof matchedOutput === "object") return "```json\n" + JSON.stringify(matchedOutput, null, 2) + "\n```";
      return matchedOutput?.toString() ?? "";
    }
    function restoreChatHistory(workflowExecutionData, emptyText) {
      if (!workflowExecutionData?.data) return [];
      const userMessage = extractChatInput(workflowExecutionData.workflowData, workflowExecutionData.data.resultData);
      const botMessage = extractBotResponse(workflowExecutionData.data.resultData, workflowExecutionData.id, emptyText);
      return [...(userMessage ? [userMessage] : []), ...(botMessage ? [botMessage] : [])];
    }
    async function processFiles(data) {
      if (!data || data.length === 0) return [];
      const filePromises = data.map(async file => {
        return new Promise((resolve, reject) => {
          const reader = new FileReader();
          reader.onload = () => resolve({
            name: file.name,
            type: file.type,
            data: reader.result
          });
          reader.onerror = () => reject(/* @__PURE__ */new Error(`Error reading file: ${reader.error?.message ?? "Unknown error"}`));
          reader.readAsDataURL(file);
        });
      });
      return await Promise.all(filePromises);
    }
    function isSubNodeLog(logEntry) {
      return logEntry.parent !== void 0 && logEntry.parent.executionId === logEntry.executionId;
    }
    function isPlaceholderLog(treeNode) {
      return treeNode.runData === void 0;
    }
    /**
    * Creates a copy of execution data just deep enough to keeps logs immutable and not reactive.
    * We deliberately avoid full deep copy here for performance reason.
    *
    * TODO: use shallowRef() for execution data in workflows store to make this unnecessary.
    */
    function copyExecutionData(executionData) {
      return {
        ...executionData,
        data: createRunExecutionData({
          ...executionData.data,
          resultData: {
            ...executionData.data?.resultData,
            runData: Object.fromEntries(Object.entries(executionData.data?.resultData.runData ?? {}).map(([k, v]) => [k, [...v]]))
          }
        })
      };
    }

    //#endregion
    //#region src/app/components/ConsumedTokensDetails.vue?vue&type=script&setup=true&lang.ts

    //#endregion
    //#region ../@n8n/composables/src/useThrottleWithReactiveDelay.ts
    /**
    * Similar to `useThrottle` from @vueuse/core, but with changeable delay
    */
    function useThrottleWithReactiveDelay(state, delay) {
      const throttled = shallowRef(state.value);
      watch(state, useThrottleFn(latest => {
        throttled.value = latest;
      }, delay, true, true), {
        immediate: true
      });
      return throttled;
    }

    //#endregion
    //#region src/features/execution/logs/composables/useLogsExecutionData.ts
    function useLogsExecutionData({
      isEnabled,
      filter
    } = {}) {
      const nodeHelpers = useNodeHelpers();
      const workflowsStore = useWorkflowsStore();
      const workflowState = injectWorkflowState();
      const toast = useToast();
      const state = ref();
      const updateInterval = computed(() => workflowsStore.workflowExecutionData?.status === "running" && Object.keys(workflowsStore.workflowExecutionData.data?.resultData.runData ?? {}).length > 1 ? LOGS_EXECUTION_DATA_THROTTLE_DURATION : 0);
      const throttledState = useThrottleWithReactiveDelay(state, updateInterval);
      const throttledWorkflowData = computed(() => throttledState.value?.response.workflowData);
      const subWorkflowExecData = ref({});
      const subWorkflows = ref({});
      const workflow = ref();
      const latestNodeNameById = computed(() => Object.values(workflow.value?.nodes ?? {}).reduce((acc, node) => {
        const nodeInStore = workflowsStore.getNodeById(node.id);
        acc[node.id] = {
          deleted: !nodeInStore,
          disabled: nodeInStore?.disabled ?? false,
          name: nodeInStore?.name ?? node.name
        };
        return acc;
      }, {}));
      const hasChat = computed(() => [Object.values(workflow.value?.nodes ?? {}), workflowsStore.workflow.nodes].some(nodes => nodes.some(isChatNode)));
      const entries = computed(() => {
        if (isEnabled !== void 0 && !isEnabled.value || !throttledState.value || !workflow.value) return [];
        const mergedExecutionData = mergeStartData(throttledState.value.startData, throttledState.value.response);
        return createLogTree(workflow.value, mergedExecutionData, subWorkflows.value, subWorkflowExecData.value, filter?.value);
      });
      function resetExecutionData() {
        state.value = void 0;
        workflowState.setWorkflowExecutionData(null);
        nodeHelpers.updateNodesExecutionIssues();
        workflowsStore.fetchLastSuccessfulExecution();
      }
      async function loadSubExecution(logEntry) {
        const locator = findSubExecutionLocator(logEntry);
        if (!state.value || locator === void 0) return;
        try {
          const subExecution = await workflowsStore.fetchExecutionDataById(locator.executionId);
          const data = subExecution?.data ? parse(subExecution.data) : void 0;
          if (!data || !subExecution) throw Error("Data is missing");
          subWorkflowExecData.value[locator.executionId] = data;
          subWorkflows.value[locator.workflowId] = new Workflow({
            ...subExecution.workflowData,
            nodeTypes: workflowsStore.getNodeTypes()
          });
        } catch (e) {
          toast.showError(e, "Unable to load sub execution");
        }
      }
      watch([() => workflowsStore.workflowExecutionData?.id, () => workflowsStore.workflowExecutionData?.workflowData.id, () => workflowsStore.workflowExecutionData?.status, () => workflowsStore.workflowExecutionResultDataLastUpdate, () => workflowsStore.workflowExecutionStartedData], useThrottleFn(([executionId], [previousExecutionId]) => {
        state.value = workflowsStore.workflowExecutionData === null ? void 0 : {
          response: copyExecutionData(workflowsStore.workflowExecutionData),
          startData: workflowsStore.workflowExecutionStartedData?.[1] ?? {}
        };
        if (executionId !== previousExecutionId) {
          subWorkflowExecData.value = {};
          subWorkflows.value = {};
        }
      }, updateInterval, true, true), {
        immediate: true
      });
      watch(() => workflowsStore.workflowId, newId => {
        if (newId === "__EMPTY__") resetExecutionData();
      });
      watch(throttledWorkflowData, data => {
        workflow.value = data ? new Workflow({
          ...data,
          nodeTypes: workflowsStore.getNodeTypes()
        }) : void 0;
      }, {
        immediate: true
      });
      return {
        execution: computed(() => throttledState.value?.response),
        entries,
        hasChat,
        latestNodeNameById,
        resetExecutionData,
        loadSubExecution
      };
    }

    //#endregion
    //#region src/features/execution/logs/composables/useLogsTreeExpand.ts
    function useLogsTreeExpand(entries, loadSubExecution) {
      const collapsedEntries = shallowRef({});
      const flatLogEntries = computed(() => flattenLogEntries(entries.value, collapsedEntries.value));
      function toggleExpanded(treeNode, expand) {
        if (hasSubExecution(treeNode) && treeNode.children.length === 0) {
          loadSubExecution(treeNode);
          return;
        }
        collapsedEntries.value = {
          ...collapsedEntries.value,
          [treeNode.id]: expand === void 0 ? !collapsedEntries.value[treeNode.id] : !expand
        };
      }
      return {
        flatLogEntries,
        toggleExpanded
      };
    }

    //#endregion
    _export({
      _: isPlaceholderLog,
      b: restoreChatHistory,
      c: findLogEntryById,
      d: getConsumedTokens,
      f: getDepth,
      g: getTotalConsumedTokens,
      h: getSubtreeTotalConsumedTokens,
      l: findLogEntryRec,
      m: getInputKey,
      n: useLogsExecutionData,
      p: getEntryAtRelativeIndex,
      s: extractBotResponse,
      t: useLogsTreeExpand,
      u: findSelectedLogEntry,
      v: isSubNodeLog,
      y: processFiles
    });
    return {
      setters: [function (_chunkLegacy001Js) {
        __toESM = _chunkLegacy001Js.o;
      }, function (_vueRuntimeEsmBundlerLegacy003Js) {
        computed = _vueRuntimeEsmBundlerLegacy003Js.C;
        toDisplayString = _vueRuntimeEsmBundlerLegacy003Js.Cn;
        createElementBlock = _vueRuntimeEsmBundlerLegacy003Js.D;
        createCommentVNode = _vueRuntimeEsmBundlerLegacy003Js.E;
        nextTick = _vueRuntimeEsmBundlerLegacy003Js.G;
        unref = _vueRuntimeEsmBundlerLegacy003Js.Gt;
        ref = _vueRuntimeEsmBundlerLegacy003Js.It;
        createVNode = _vueRuntimeEsmBundlerLegacy003Js.M;
        defineComponent = _vueRuntimeEsmBundlerLegacy003Js.P;
        createBlock = _vueRuntimeEsmBundlerLegacy003Js.T;
        toRef = _vueRuntimeEsmBundlerLegacy003Js.Vt;
        mergeProps = _vueRuntimeEsmBundlerLegacy003Js.W;
        Fragment = _vueRuntimeEsmBundlerLegacy003Js._;
        watch = _vueRuntimeEsmBundlerLegacy003Js._t;
        normalizeStyle = _vueRuntimeEsmBundlerLegacy003Js.bn;
        withCtx = _vueRuntimeEsmBundlerLegacy003Js.bt;
        openBlock = _vueRuntimeEsmBundlerLegacy003Js.et;
        withModifiers = _vueRuntimeEsmBundlerLegacy003Js.h;
        renderList = _vueRuntimeEsmBundlerLegacy003Js.it;
        createTextVNode = _vueRuntimeEsmBundlerLegacy003Js.j;
        useTemplateRef = _vueRuntimeEsmBundlerLegacy003Js.mt;
        normalizeClass = _vueRuntimeEsmBundlerLegacy003Js.vn;
        createBaseVNode = _vueRuntimeEsmBundlerLegacy003Js.w;
        shallowRef = _vueRuntimeEsmBundlerLegacy003Js.zt;
      }, function (_MapCacheLegacy005Js) {
        useVirtualList = _MapCacheLegacy005Js.B;
        I18nT = _MapCacheLegacy005Js._t;
        useI18n = _MapCacheLegacy005Js.gt;
        useThrottleFn = _MapCacheLegacy005Js.it;
        useTimestamp = _MapCacheLegacy005Js.z;
      }, function (_srcLegacy007Js) {
        N8nButton_default = _srcLegacy007Js.Hn;
        N8nText_default = _srcLegacy007Js.Vn;
        N8nIcon_default = _srcLegacy007Js.Wn;
        N8nTooltip_default = _srcLegacy007Js.mt;
        N8nIconButton_default = _srcLegacy007Js.xt;
      }, function (_pluginVue_exportHelperLegacy00fJs) {
        __plugin_vue_export_helper_default = _pluginVue_exportHelperLegacy00fJs.t;
      }, function (_truncateLegacy00hJs) {
        require_get = _truncateLegacy00hJs.r;
        useRouter = _truncateLegacy00hJs.y;
      }, function (_useTelemetryLegacy00HJs) {
        emptyTokenUsageData = _useTelemetryLegacy00HJs.G;
        formatTokenUsageCount = _useTelemetryLegacy00HJs.K;
        v4_default = _useTelemetryLegacy00HJs.Ro;
        require_upperFirst = _useTelemetryLegacy00HJs.Rt;
        injectWorkflowState = _useTelemetryLegacy00HJs.Sn;
        addTokenUsageData = _useTelemetryLegacy00HJs.W;
        useNodeTypesStore = _useTelemetryLegacy00HJs.at;
        useWorkflowsStore = _useTelemetryLegacy00HJs.o;
        isChatNode = _useTelemetryLegacy00HJs.q;
        parse = _useTelemetryLegacy00HJs.ui;
        useNodeHelpers = _useTelemetryLegacy00HJs.xn;
      }, function (_useToastLegacy00JJs) {
        useToast = _useToastLegacy00JJs.t;
      }, function (_constantsLegacy00TJs) {
        CHAT_TRIGGER_NODE_TYPE = _constantsLegacy00TJs.Bt;
        createRunExecutionData = _constantsLegacy00TJs.Gi;
        NodeConnectionTypes = _constantsLegacy00TJs.Ka;
        MANUAL_CHAT_TRIGGER_NODE_TYPE = _constantsLegacy00TJs.Tn;
        createEmptyRunExecutionData = _constantsLegacy00TJs.Wi;
        AGENT_LANGCHAIN_NODE_TYPE = _constantsLegacy00TJs.Ya;
        LOGS_EXECUTION_DATA_THROTTLE_DURATION = _constantsLegacy00TJs._c;
        parseErrorMetadata = _constantsLegacy00TJs._i;
        Workflow = _constantsLegacy00TJs.gi;
        PLACEHOLDER_EMPTY_WORKFLOW_ID = _constantsLegacy00TJs.s;
      }, function (_baseOrderByLegacy00ZJs) {
        TOOL_EXECUTOR_NODE_NAME = _baseOrderByLegacy00ZJs.x;
      }, function (_useRunWorkflowLegacy01pJs) {
        useRunWorkflow = _useRunWorkflowLegacy01pJs.t;
      }, function (_NodeIconLegacy01FJs) {
        NodeIcon_default = _NodeIconLegacy01FJs.t;
      }, function (_isEmptyLegacy021Js) {
        require_isEmpty = _isEmptyLegacy021Js.t;
      }, function (_dateFormatterLegacy02LJs) {
        toTime = _dateFormatterLegacy02LJs.a;
        toDayMonth = _dateFormatterLegacy02LJs.i;
      }, function (_AnimatedSpinnerLegacy05BJs) {
        AnimatedSpinner_default = _AnimatedSpinnerLegacy05BJs.t;
      }],
      execute: function () {
        __vite_style__ = document.createElement('style');
        __vite_style__.textContent = "/* BEM support Func\n -------------------------- */\n/* Transition\n-------------------------- */\n/* Color\n-------------------------- */\n/* Link\n-------------------------- */\n/* Border\n-------------------------- */\n/* Outline\n-------------------------- */\n/* Box shadow\n-------------------------- */\n/* Fill\n-------------------------- */\n/* Typography\n-------------------------- */\n/* z-index\n-------------------------- */\n/* Disable base\n-------------------------- */\n/* Icon\n-------------------------- */\n/* Checkbox\n-------------------------- */\n/* Radio\n-------------------------- */\n/* Select\n-------------------------- */\n/* Alert\n-------------------------- */\n/* MessageBox\n-------------------------- */\n/* Message\n-------------------------- */\n/* Notification\n-------------------------- */\n/* Input\n-------------------------- */\n/* Cascader\n-------------------------- */\n/* Group\n-------------------------- */\n/* Tab\n-------------------------- */\n/* Button\n-------------------------- */\n/* cascader\n-------------------------- */\n/* Switch\n-------------------------- */\n/* Dialog\n-------------------------- */\n/* Table\n-------------------------- */\n/* Pagination\n-------------------------- */\n/* Popup\n-------------------------- */\n/* Popover\n-------------------------- */\n/* Tooltip\n-------------------------- */\n/* Tag\n-------------------------- */\n/* Tree\n-------------------------- */\n/* Dropdown\n-------------------------- */\n/* Badge\n-------------------------- */\n/* Card\n--------------------------*/\n/* Slider\n--------------------------*/\n/* Steps\n--------------------------*/\n/* Menu\n--------------------------*/\n/* Rate\n--------------------------*/\n/* DatePicker\n--------------------------*/\n/* Loading\n--------------------------*/\n/* Scrollbar\n--------------------------*/\n/* Carousel\n--------------------------*/\n/* Collapse\n--------------------------*/\n/* Transfer\n--------------------------*/\n/* Header\n  --------------------------*/\n/* Footer\n--------------------------*/\n/* Main\n--------------------------*/\n/* Timeline\n--------------------------*/\n/* Backtop\n--------------------------*/\n/* Link\n--------------------------*/\n/* Calendar\n--------------------------*/\n/* Form\n-------------------------- */\n/* Avatar\n--------------------------*/\n/* Break-point\n--------------------------*/\n/* Break-points\n -------------------------- */\n/* Scrollbar\n -------------------------- */\n/* Placeholder\n -------------------------- */\n/* BEM\n -------------------------- */\n._name_1qhq5_123 {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n._name_1qhq5_123 del:not(:last-child) {\n  margin-right: var(--spacing--4xs);\n}/* BEM support Func\n -------------------------- */\n/* Transition\n-------------------------- */\n/* Color\n-------------------------- */\n/* Link\n-------------------------- */\n/* Border\n-------------------------- */\n/* Outline\n-------------------------- */\n/* Box shadow\n-------------------------- */\n/* Fill\n-------------------------- */\n/* Typography\n-------------------------- */\n/* z-index\n-------------------------- */\n/* Disable base\n-------------------------- */\n/* Icon\n-------------------------- */\n/* Checkbox\n-------------------------- */\n/* Radio\n-------------------------- */\n/* Select\n-------------------------- */\n/* Alert\n-------------------------- */\n/* MessageBox\n-------------------------- */\n/* Message\n-------------------------- */\n/* Notification\n-------------------------- */\n/* Input\n-------------------------- */\n/* Cascader\n-------------------------- */\n/* Group\n-------------------------- */\n/* Tab\n-------------------------- */\n/* Button\n-------------------------- */\n/* cascader\n-------------------------- */\n/* Switch\n-------------------------- */\n/* Dialog\n-------------------------- */\n/* Table\n-------------------------- */\n/* Pagination\n-------------------------- */\n/* Popup\n-------------------------- */\n/* Popover\n-------------------------- */\n/* Tooltip\n-------------------------- */\n/* Tag\n-------------------------- */\n/* Tree\n-------------------------- */\n/* Dropdown\n-------------------------- */\n/* Badge\n-------------------------- */\n/* Card\n--------------------------*/\n/* Slider\n--------------------------*/\n/* Steps\n--------------------------*/\n/* Menu\n--------------------------*/\n/* Rate\n--------------------------*/\n/* DatePicker\n--------------------------*/\n/* Loading\n--------------------------*/\n/* Scrollbar\n--------------------------*/\n/* Carousel\n--------------------------*/\n/* Collapse\n--------------------------*/\n/* Transfer\n--------------------------*/\n/* Header\n  --------------------------*/\n/* Footer\n--------------------------*/\n/* Main\n--------------------------*/\n/* Timeline\n--------------------------*/\n/* Backtop\n--------------------------*/\n/* Link\n--------------------------*/\n/* Calendar\n--------------------------*/\n/* Form\n-------------------------- */\n/* Avatar\n--------------------------*/\n/* Break-point\n--------------------------*/\n/* Break-points\n -------------------------- */\n/* Scrollbar\n -------------------------- */\n/* Placeholder\n -------------------------- */\n/* BEM\n -------------------------- */\n._container_1742e_123 {\n  display: flex;\n  align-items: center;\n  justify-content: stretch;\n  overflow: hidden;\n  position: relative;\n  z-index: 1;\n  padding-inline-end: var(--spacing--5xs);\n  cursor: pointer;\n}\n._container_1742e_123 > * {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  padding: var(--spacing--2xs);\n}\n._background_1742e_140 {\n  position: absolute;\n  /* stylelint-disable-next-line @n8n/css-var-naming */\n  left: calc(var(--indent-depth) * 32px);\n  top: 0;\n  /* stylelint-disable-next-line @n8n/css-var-naming */\n  width: calc(100% - var(--indent-depth) * 32px);\n  height: 100%;\n  border-radius: var(--radius);\n  z-index: -1;\n}\n._selected_1742e_151 ._background_1742e_140 {\n  background-color: var(--color--foreground);\n}\n._container_1742e_123:hover:not(._selected_1742e_151) ._background_1742e_140 {\n  background-color: var(--color--background--light-1);\n}\n._selected_1742e_151:not(:hover)._error_1742e_157 ._background_1742e_140 {\n  background-color: var(--callout--color--background--danger);\n}\n._indent_1742e_161 {\n  flex-grow: 0;\n  flex-shrink: 0;\n  width: var(--spacing--xl);\n  align-self: stretch;\n  position: relative;\n  overflow: hidden;\n  margin-bottom: 0;\n}\n._indent_1742e_161._connectorCurved_1742e_170:before {\n  content: \"\";\n  position: absolute;\n  left: var(--spacing--sm);\n  bottom: var(--spacing--sm);\n  border: 2px solid var(--canvas--dot--color);\n  width: var(--spacing--lg);\n  height: var(--spacing--lg);\n  border-radius: var(--radius--lg);\n}\n._indent_1742e_161._connectorStraight_1742e_180:after {\n  content: \"\";\n  position: absolute;\n  left: var(--spacing--sm);\n  top: 0;\n  border-left: 2px solid var(--canvas--dot--color);\n  height: 100%;\n}\n._icon_1742e_189 {\n  /* stylelint-disable-next-line @n8n/css-var-naming */\n  margin-left: var(--row-gap-thickness);\n  flex-grow: 0;\n  flex-shrink: 0;\n}\n._name_1742e_196 {\n  flex-basis: 0;\n  flex-grow: 1;\n  padding-inline-start: 0;\n}\n._timeTook_1742e_202 {\n  flex-grow: 0;\n  flex-shrink: 0;\n  width: 20%;\n}\n._timeTook_1742e_202 ._statusTextIcon_1742e_207 {\n  margin-right: var(--spacing--5xs);\n  vertical-align: text-bottom;\n}\n._startedAt_1742e_212 {\n  flex-grow: 0;\n  flex-shrink: 0;\n  width: 25%;\n}\n._consumedTokens_1742e_218 {\n  flex-grow: 0;\n  flex-shrink: 0;\n  width: 15%;\n  text-align: right;\n}\n._compactErrorIcon_1742e_225 {\n  flex-grow: 0;\n  flex-shrink: 0;\n  width: 26px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n._container_1742e_123:hover ._compactErrorIcon_1742e_225 {\n  display: none;\n}\n._partialExecutionButton_1742e_237,\n._openNdvButton_1742e_238 {\n  transition: none;\n  /* By default, take space but keep invisible */\n  visibility: hidden;\n}\n._container_1742e_123._compact_1742e_225 ._partialExecutionButton_1742e_237,\n._container_1742e_123._compact_1742e_225 ._openNdvButton_1742e_238 {\n  /* When compact, collapse to save space */\n  display: none;\n}\n._container_1742e_123:hover ._partialExecutionButton_1742e_237:not(._unavailable_1742e_248),\n._container_1742e_123:hover ._openNdvButton_1742e_238:not(._unavailable_1742e_248) {\n  visibility: visible;\n  display: inline-flex;\n}\n._partialExecutionButton_1742e_237,\n._openNdvButton_1742e_238,\n._toggleButton_1742e_256 {\n  flex-grow: 0;\n  flex-shrink: 0;\n  border: none;\n  background: transparent;\n  color: var(--color--text);\n  align-items: center;\n  justify-content: center;\n}\n._partialExecutionButton_1742e_237:hover,\n._openNdvButton_1742e_238:hover,\n._toggleButton_1742e_256:hover {\n  background: transparent;\n}\n._partialExecutionButton_1742e_237:disabled,\n._openNdvButton_1742e_238:disabled,\n._toggleButton_1742e_256:disabled {\n  visibility: hidden !important;\n}\n._toggleButton_1742e_256 {\n  display: inline-flex;\n}\n._statusIcon_1742e_280 {\n  color: var(--color--text--tint-1);\n  flex-grow: 0;\n  flex-shrink: 0;\n  width: 26px;\n  height: 26px;\n  padding: var(--spacing--3xs);\n}\n._statusIcon_1742e_280._placeholder_1742e_288 {\n  color: transparent;\n}/* BEM support Func\n -------------------------- */\n/* Transition\n-------------------------- */\n/* Color\n-------------------------- */\n/* Link\n-------------------------- */\n/* Border\n-------------------------- */\n/* Outline\n-------------------------- */\n/* Box shadow\n-------------------------- */\n/* Fill\n-------------------------- */\n/* Typography\n-------------------------- */\n/* z-index\n-------------------------- */\n/* Disable base\n-------------------------- */\n/* Icon\n-------------------------- */\n/* Checkbox\n-------------------------- */\n/* Radio\n-------------------------- */\n/* Select\n-------------------------- */\n/* Alert\n-------------------------- */\n/* MessageBox\n-------------------------- */\n/* Message\n-------------------------- */\n/* Notification\n-------------------------- */\n/* Input\n-------------------------- */\n/* Cascader\n-------------------------- */\n/* Group\n-------------------------- */\n/* Tab\n-------------------------- */\n/* Button\n-------------------------- */\n/* cascader\n-------------------------- */\n/* Switch\n-------------------------- */\n/* Dialog\n-------------------------- */\n/* Table\n-------------------------- */\n/* Pagination\n-------------------------- */\n/* Popup\n-------------------------- */\n/* Popover\n-------------------------- */\n/* Tooltip\n-------------------------- */\n/* Tag\n-------------------------- */\n/* Tree\n-------------------------- */\n/* Dropdown\n-------------------------- */\n/* Badge\n-------------------------- */\n/* Card\n--------------------------*/\n/* Slider\n--------------------------*/\n/* Steps\n--------------------------*/\n/* Menu\n--------------------------*/\n/* Rate\n--------------------------*/\n/* DatePicker\n--------------------------*/\n/* Loading\n--------------------------*/\n/* Scrollbar\n--------------------------*/\n/* Carousel\n--------------------------*/\n/* Collapse\n--------------------------*/\n/* Transfer\n--------------------------*/\n/* Header\n  --------------------------*/\n/* Footer\n--------------------------*/\n/* Main\n--------------------------*/\n/* Timeline\n--------------------------*/\n/* Backtop\n--------------------------*/\n/* Link\n--------------------------*/\n/* Calendar\n--------------------------*/\n/* Form\n-------------------------- */\n/* Avatar\n--------------------------*/\n/* Break-point\n--------------------------*/\n/* Break-points\n -------------------------- */\n/* Scrollbar\n -------------------------- */\n/* Placeholder\n -------------------------- */\n/* BEM\n -------------------------- */\n._tree_92rld_123 {\n  padding: 0 var(--spacing--2xs) var(--spacing--2xs) var(--spacing--2xs);\n  /* For programmatically triggered scroll in useVirtualList to animate, make it scroll smoothly */\n  scroll-behavior: smooth;\n}\n._container_92rld_128:not(._staticScrollBar_92rld_128) ._tree_92rld_123 {\n  scroll-padding-block: var(--spacing--3xs);\n}\n@supports not (selector(::-webkit-scrollbar)) {\n._container_92rld_128:not(._staticScrollBar_92rld_128) ._tree_92rld_123 {\n    scrollbar-width: thin;\n}\n}\n@supports selector(::-webkit-scrollbar) {\n._container_92rld_128:not(._staticScrollBar_92rld_128) ._tree_92rld_123 {\n    padding-right: var(--spacing--5xs);\n    scrollbar-gutter: stable;\n}\n._container_92rld_128:not(._staticScrollBar_92rld_128) ._tree_92rld_123::-webkit-scrollbar {\n    width: var(--spacing--4xs);\n}\n._container_92rld_128:not(._staticScrollBar_92rld_128) ._tree_92rld_123::-webkit-scrollbar-thumb {\n    border-radius: var(--spacing--4xs);\n    background: var(--color--foreground--shade-1);\n}\n}\n._tree_92rld_123 .el-icon {\n  display: none;\n}/*$vite$:1*/";
        document.head.appendChild(__vite_style__);
        //#region src/features/execution/logs/logs.utils.ts
        import_get = /* @__PURE__ */__toESM(require_get());
        import_isEmpty = /* @__PURE__ */__toESM(require_isEmpty());
        ConsumedTokensDetails_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */defineComponent({
          __name: "ConsumedTokensDetails",
          props: {
            consumedTokens: {}
          },
          setup(__props) {
            const i18n = useI18n();
            return (_ctx, _cache) => {
              return openBlock(), createElementBlock("div", null, [createVNode(unref(N8nText_default), {
                bold: true,
                size: "small"
              }, {
                default: withCtx(() => [createTextVNode(toDisplayString(unref(i18n).baseText("runData.aiContentBlock.tokens.prompt")) + " " + toDisplayString(unref(i18n).baseText("runData.aiContentBlock.tokens", {
                  interpolate: {
                    count: unref(formatTokenUsageCount)(_ctx.consumedTokens, "prompt")
                  }
                })), 1)]),
                _: 1
              }), _cache[0] || (_cache[0] = createBaseVNode("br", null, null, -1)), createVNode(unref(N8nText_default), {
                bold: true,
                size: "small"
              }, {
                default: withCtx(() => [createTextVNode(toDisplayString(unref(i18n).baseText("runData.aiContentBlock.tokens.completion")) + " " + toDisplayString(unref(i18n).baseText("runData.aiContentBlock.tokens", {
                  interpolate: {
                    count: unref(formatTokenUsageCount)(_ctx.consumedTokens, "completion")
                  }
                })), 1)]),
                _: 1
              })]);
            };
          }
        }); //#endregion
        //#region src/app/components/ConsumedTokensDetails.vue
        _export("o", ConsumedTokensDetails_default = ConsumedTokensDetails_vue_vue_type_script_setup_true_lang_default); //#endregion
        //#region src/features/execution/logs/components/LogsViewConsumedTokenCountText.vue?vue&type=script&setup=true&lang.ts
        LogsViewConsumedTokenCountText_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */defineComponent({
          __name: "LogsViewConsumedTokenCountText",
          props: {
            consumedTokens: {}
          },
          setup(__props) {
            const locale = useI18n();
            return (_ctx, _cache) => {
              return _ctx.consumedTokens !== void 0 ? (openBlock(), createBlock(unref(N8nTooltip_default), {
                key: 0,
                enterable: false
              }, {
                content: withCtx(() => [createVNode(ConsumedTokensDetails_default, {
                  "consumed-tokens": _ctx.consumedTokens
                }, null, 8, ["consumed-tokens"])]),
                default: withCtx(() => [createBaseVNode("span", null, toDisplayString(unref(locale).baseText("runData.aiContentBlock.tokens", {
                  interpolate: {
                    count: unref(formatTokenUsageCount)(_ctx.consumedTokens, "total")
                  }
                })), 1)]),
                _: 1
              })) : createCommentVNode("", true);
            };
          }
        }); //#endregion
        //#region src/features/execution/logs/components/LogsViewConsumedTokenCountText.vue
        _export("a", LogsViewConsumedTokenCountText_default = LogsViewConsumedTokenCountText_vue_vue_type_script_setup_true_lang_default); //#endregion
        //#region src/features/execution/logs/components/LogsViewNodeName.vue?vue&type=script&setup=true&lang.ts
        _hoisted_1$1 = {
          key: 0
        };
        LogsViewNodeName_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */defineComponent({
          __name: "LogsViewNodeName",
          props: {
            name: {},
            isError: {
              type: Boolean
            },
            isDeleted: {
              type: Boolean
            }
          },
          setup(__props) {
            return (_ctx, _cache) => {
              return openBlock(), createBlock(unref(N8nText_default), {
                tag: "div",
                bold: true,
                size: "small",
                class: normalizeClass(_ctx.$style.name),
                color: _ctx.isError ? "danger" : void 0
              }, {
                default: withCtx(() => [_ctx.isDeleted ? (openBlock(), createElementBlock("del", _hoisted_1$1, toDisplayString(_ctx.name), 1)) : (openBlock(), createElementBlock(Fragment, {
                  key: 1
                }, [createTextVNode(toDisplayString(_ctx.name), 1)], 64))]),
                _: 1
              }, 8, ["class", "color"]);
            };
          }
        }); //#endregion
        //#region src/features/execution/logs/components/LogsViewNodeName.vue?vue&type=style&index=0&lang.module.scss
        name$1 = "_name_1qhq5_123";
        LogsViewNodeName_vue_vue_type_style_index_0_lang_module_default = {
          name: name$1
        }; //#endregion
        //#region src/features/execution/logs/components/LogsViewNodeName.vue
        cssModules$2 = {
          "$style": LogsViewNodeName_vue_vue_type_style_index_0_lang_module_default
        };
        _export("i", LogsViewNodeName_default = /* @__PURE__ */__plugin_vue_export_helper_default(LogsViewNodeName_vue_vue_type_script_setup_true_lang_default, [["__cssModules", cssModules$2]])); //#endregion
        //#region src/features/execution/logs/components/LogsOverviewRow.vue?vue&type=script&setup=true&lang.ts
        import_upperFirst = /* @__PURE__ */__toESM(require_upperFirst());
        _hoisted_1 = ["aria-expanded", "aria-selected"];
        LogsOverviewRow_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */defineComponent({
          __name: "LogsOverviewRow",
          props: {
            data: {},
            isSelected: {
              type: Boolean
            },
            isReadOnly: {
              type: Boolean
            },
            shouldShowTokenCountColumn: {
              type: Boolean
            },
            isCompact: {
              type: Boolean
            },
            latestInfo: {},
            expanded: {
              type: Boolean
            },
            canOpenNdv: {
              type: Boolean
            }
          },
          emits: ["toggleExpanded", "toggleSelected", "triggerPartialExecution", "openNdv"],
          setup(__props, {
            emit: __emit
          }) {
            const props = __props;
            const emit = __emit;
            const container$2 = useTemplateRef("containerRef");
            const locale = useI18n();
            const now = useTimestamp({
              interval: 1e3
            });
            const nodeTypeStore = useNodeTypesStore();
            const type = computed(() => nodeTypeStore.getNodeType(props.data.node.type));
            const isRunning = computed(() => props.data.runData?.executionStatus === "running");
            const isWaiting = computed(() => props.data.runData?.executionStatus === "waiting");
            const isSettled = computed(() => !isRunning.value && !isWaiting.value);
            const isError = computed(() => !!props.data.runData?.error);
            const statusTextKeyPath = computed(() => isSettled.value ? "logs.overview.body.summaryText.in" : "logs.overview.body.summaryText.for");
            const startedAtText = computed(() => {
              if (props.data.runData === void 0) return "—";
              const time = new Date(props.data.runData.startTime);
              return locale.baseText("logs.overview.body.started", {
                interpolate: {
                  time: `${toTime(time, true)}, ${toDayMonth(time)}`
                }
              });
            });
            const statusText = computed(() => (0, import_upperFirst.default)(props.data.runData?.executionStatus ?? ""));
            const timeText = computed(() => props.data.runData ? locale.displayTimer(isSettled.value ? props.data.runData.executionTime : Math.floor((now.value - props.data.runData.startTime) / 1e3) * 1e3, true) : void 0);
            const subtreeConsumedTokens = computed(() => props.shouldShowTokenCountColumn ? getSubtreeTotalConsumedTokens(props.data, false) : void 0);
            const hasChildren = computed(() => props.data.children.length > 0 || hasSubExecution(props.data));
            const indents = computed(() => {
              const ret = [];
              let data = props.data;
              while (data.parent !== void 0) {
                const siblings = data.parent?.children ?? [];
                const lastSibling = siblings[siblings.length - 1];
                ret.unshift({
                  straight: lastSibling?.id !== data.id,
                  curved: data === props.data
                });
                data = data.parent;
              }
              return ret;
            });
            watch(() => props.isSelected, isSelected => {
              nextTick(() => {
                if (isSelected) container$2.value?.focus();
              });
            }, {
              immediate: true
            });
            return (_ctx, _cache) => {
              return openBlock(), createElementBlock("div", {
                ref: "containerRef",
                role: "treeitem",
                tabindex: "-1",
                "aria-expanded": props.data.children.length > 0 && props.expanded,
                "aria-selected": props.isSelected,
                class: normalizeClass({
                  [_ctx.$style.container]: true,
                  [_ctx.$style.compact]: props.isCompact,
                  [_ctx.$style.error]: isError.value,
                  [_ctx.$style.selected]: props.isSelected
                }),
                onClick: _cache[3] || (_cache[3] = withModifiers($event => emit("toggleSelected"), ["stop"]))
              }, [(openBlock(true), createElementBlock(Fragment, null, renderList(indents.value, (indent$1, level) => {
                return openBlock(), createElementBlock("div", {
                  key: level,
                  class: normalizeClass({
                    [_ctx.$style.indent]: true,
                    [_ctx.$style.connectorCurved]: indent$1.curved,
                    [_ctx.$style.connectorStraight]: indent$1.straight
                  })
                }, null, 2);
              }), 128)), createBaseVNode("div", {
                class: normalizeClass(_ctx.$style.background),
                style: normalizeStyle({
                  "--indent-depth": indents.value.length
                })
              }, null, 6), createVNode(NodeIcon_default, {
                "node-type": type.value,
                size: 16,
                class: normalizeClass(_ctx.$style.icon)
              }, null, 8, ["node-type", "class"]), createVNode(LogsViewNodeName_default, {
                class: normalizeClass(_ctx.$style.name),
                name: _ctx.latestInfo?.name ?? props.data.node.name,
                "is-error": isError.value,
                "is-deleted": _ctx.latestInfo?.deleted ?? false
              }, null, 8, ["class", "name", "is-error", "is-deleted"]), !_ctx.isCompact ? (openBlock(), createBlock(unref(N8nText_default), {
                key: 0,
                tag: "div",
                color: "text-light",
                size: "small",
                class: normalizeClass(_ctx.$style.timeTook)
              }, {
                default: withCtx(() => [timeText.value !== void 0 ? (openBlock(), createBlock(unref(I18nT), {
                  key: 0,
                  keypath: statusTextKeyPath.value,
                  scope: "global"
                }, {
                  status: withCtx(() => [createVNode(unref(N8nText_default), {
                    color: isError.value ? "danger" : void 0,
                    bold: isError.value,
                    size: "small"
                  }, {
                    default: withCtx(() => [isRunning.value ? (openBlock(), createBlock(AnimatedSpinner_default, {
                      key: 0,
                      class: normalizeClass(_ctx.$style.statusTextIcon)
                    }, null, 8, ["class"])) : isWaiting.value ? (openBlock(), createBlock(unref(N8nIcon_default), {
                      key: 1,
                      icon: "status-waiting",
                      class: normalizeClass(_ctx.$style.statusTextIcon)
                    }, null, 8, ["class"])) : isError.value ? (openBlock(), createBlock(unref(N8nIcon_default), {
                      key: 2,
                      icon: "triangle-alert",
                      class: normalizeClass(_ctx.$style.statusTextIcon)
                    }, null, 8, ["class"])) : createCommentVNode("", true), createTextVNode(" " + toDisplayString(statusText.value), 1)]),
                    _: 1
                  }, 8, ["color", "bold"])]),
                  time: withCtx(() => [createTextVNode(toDisplayString(timeText.value), 1)]),
                  _: 1
                }, 8, ["keypath"])) : (openBlock(), createElementBlock(Fragment, {
                  key: 1
                }, [createTextVNode("—")], 64))]),
                _: 1
              }, 8, ["class"])) : createCommentVNode("", true), !_ctx.isCompact ? (openBlock(), createBlock(unref(N8nText_default), {
                key: 1,
                tag: "div",
                color: "text-light",
                size: "small",
                class: normalizeClass(_ctx.$style.startedAt)
              }, {
                default: withCtx(() => [createTextVNode(toDisplayString(startedAtText.value), 1)]),
                _: 1
              }, 8, ["class"])) : createCommentVNode("", true), !_ctx.isCompact && subtreeConsumedTokens.value !== void 0 ? (openBlock(), createBlock(unref(N8nText_default), {
                key: 2,
                tag: "div",
                color: "text-light",
                size: "small",
                class: normalizeClass(_ctx.$style.consumedTokens)
              }, {
                default: withCtx(() => [subtreeConsumedTokens.value.totalTokens > 0 && (props.data.children.length === 0 || !props.expanded) ? (openBlock(), createBlock(LogsViewConsumedTokenCountText_default, {
                  key: 0,
                  "consumed-tokens": subtreeConsumedTokens.value
                }, null, 8, ["consumed-tokens"])) : createCommentVNode("", true)]),
                _: 1
              }, 8, ["class"])) : createCommentVNode("", true), isError.value && _ctx.isCompact ? (openBlock(), createBlock(unref(N8nIcon_default), {
                key: 3,
                size: "medium",
                color: "danger",
                icon: "triangle-alert",
                class: normalizeClass(_ctx.$style.compactErrorIcon)
              }, null, 8, ["class"])) : createCommentVNode("", true), _ctx.canOpenNdv && (!_ctx.isCompact || !props.latestInfo?.deleted) ? (openBlock(), createBlock(unref(N8nIconButton_default), {
                key: 4,
                type: "secondary",
                size: "small",
                icon: "square-pen",
                "icon-size": "medium",
                style: normalizeStyle({
                  visibility: props.data.isSubExecution ? "hidden" : ""
                }),
                disabled: props.latestInfo?.deleted,
                class: normalizeClass(_ctx.$style.openNdvButton),
                "aria-label": unref(locale).baseText("logs.overview.body.open"),
                onClick: _cache[0] || (_cache[0] = withModifiers($event => emit("openNdv"), ["stop"]))
              }, null, 8, ["style", "disabled", "class", "aria-label"])) : createCommentVNode("", true), !_ctx.isCompact || !props.isReadOnly && !props.latestInfo?.deleted && !props.latestInfo?.disabled ? (openBlock(), createBlock(unref(N8nIconButton_default), {
                key: 5,
                type: "secondary",
                size: "small",
                icon: "play",
                "aria-label": unref(locale).baseText("logs.overview.body.run"),
                class: normalizeClass([_ctx.$style.partialExecutionButton, indents.value.length > 0 ? _ctx.$style.unavailable : ""]),
                disabled: props.latestInfo?.deleted || props.latestInfo?.disabled,
                onClick: _cache[1] || (_cache[1] = withModifiers($event => emit("triggerPartialExecution"), ["stop"]))
              }, null, 8, ["aria-label", "class", "disabled"])) : createCommentVNode("", true), _ctx.isCompact && !hasChildren.value ? (openBlock(), createElementBlock(Fragment, {
                key: 6
              }, [isRunning.value ? (openBlock(), createBlock(AnimatedSpinner_default, {
                key: 0,
                class: normalizeClass(_ctx.$style.statusIcon)
              }, null, 8, ["class"])) : isWaiting.value ? (openBlock(), createBlock(unref(N8nIcon_default), {
                key: 1,
                icon: "status-waiting",
                class: normalizeClass(_ctx.$style.statusIcon)
              }, null, 8, ["class"])) : createCommentVNode("", true)], 64)) : createCommentVNode("", true), !_ctx.isCompact || hasChildren.value ? (openBlock(), createBlock(unref(N8nButton_default), {
                key: 7,
                type: "secondary",
                size: "small",
                icon: props.expanded ? "chevron-down" : "chevron-up",
                "icon-size": "medium",
                square: true,
                style: normalizeStyle({
                  visibility: hasChildren.value ? "" : "hidden"
                }),
                class: normalizeClass(_ctx.$style.toggleButton),
                "aria-label": unref(locale).baseText("logs.overview.body.toggleRow"),
                onClick: _cache[2] || (_cache[2] = withModifiers($event => emit("toggleExpanded"), ["stop"]))
              }, null, 8, ["icon", "style", "class", "aria-label"])) : createCommentVNode("", true)], 10, _hoisted_1);
            };
          }
        }); //#endregion
        //#region src/features/execution/logs/components/LogsOverviewRow.vue?vue&type=style&index=0&lang.module.scss
        container$1 = "_container_1742e_123";
        background = "_background_1742e_140";
        selected = "_selected_1742e_151";
        error = "_error_1742e_157";
        indent = "_indent_1742e_161";
        connectorCurved = "_connectorCurved_1742e_170";
        connectorStraight = "_connectorStraight_1742e_180";
        icon = "_icon_1742e_189";
        name = "_name_1742e_196";
        timeTook = "_timeTook_1742e_202";
        statusTextIcon = "_statusTextIcon_1742e_207";
        startedAt = "_startedAt_1742e_212";
        consumedTokens = "_consumedTokens_1742e_218";
        compactErrorIcon = "_compactErrorIcon_1742e_225";
        partialExecutionButton = "_partialExecutionButton_1742e_237";
        openNdvButton = "_openNdvButton_1742e_238";
        compact = "_compact_1742e_225";
        unavailable = "_unavailable_1742e_248";
        toggleButton = "_toggleButton_1742e_256";
        statusIcon = "_statusIcon_1742e_280";
        placeholder = "_placeholder_1742e_288";
        LogsOverviewRow_vue_vue_type_style_index_0_lang_module_default = {
          container: container$1,
          background,
          selected,
          error,
          indent,
          connectorCurved,
          connectorStraight,
          icon,
          name,
          timeTook,
          statusTextIcon,
          startedAt,
          consumedTokens,
          compactErrorIcon,
          partialExecutionButton,
          openNdvButton,
          compact,
          unavailable,
          toggleButton,
          statusIcon,
          placeholder
        }; //#endregion
        //#region src/features/execution/logs/components/LogsOverviewRow.vue
        cssModules$1 = {
          "$style": LogsOverviewRow_vue_vue_type_style_index_0_lang_module_default
        };
        LogsOverviewRow_default = /* @__PURE__ */__plugin_vue_export_helper_default(LogsOverviewRow_vue_vue_type_script_setup_true_lang_default, [["__cssModules", cssModules$1]]); //#endregion
        //#region src/features/execution/logs/components/LogsOverviewRows.vue?vue&type=script&setup=true&lang.ts
        LogsOverviewRows_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */defineComponent({
          __name: "LogsOverviewRows",
          props: {
            selected: {},
            isReadOnly: {
              type: Boolean
            },
            isCompact: {
              type: Boolean
            },
            shouldShowTokenCountColumn: {
              type: Boolean
            },
            canOpenNdv: {
              type: Boolean
            },
            flatLogEntries: {},
            latestNodeInfo: {},
            execution: {}
          },
          emits: ["select", "openNdv", "toggleExpanded"],
          setup(__props, {
            emit: __emit
          }) {
            const emit = __emit;
            const runWorkflow = useRunWorkflow({
              router: useRouter()
            });
            const isExpanded = computed(() => __props.flatLogEntries.reduce((acc, entry, index, arr) => {
              acc[entry.id] = arr[index + 1]?.parent?.id === entry.id;
              return acc;
            }, {}));
            const virtualList = useVirtualList(toRef(() => __props.flatLogEntries), {
              itemHeight: 32
            });
            async function handleTriggerPartialExecution(treeNode) {
              const latestName = __props.latestNodeInfo[treeNode.node.id]?.name ?? treeNode.node.name;
              if (latestName) await runWorkflow.runWorkflow({
                destinationNode: {
                  nodeName: latestName,
                  mode: "inclusive"
                }
              });
            }
            watch([() => __props.execution?.status === "running", () => __props.flatLogEntries.length], async ([isRunning, flatEntryCount], [wasRunning]) => {
              await nextTick(() => {
                if (__props.selected === void 0 && (isRunning || wasRunning)) virtualList.scrollTo(flatEntryCount - 1);
              });
            }, {
              immediate: true
            });
            watch(() => __props.selected?.id, async selectedId => {
              await nextTick(() => {
                if (selectedId === void 0) return;
                const index = virtualList.list.value.some(e => e.data.id === selectedId) ? -1 : __props.flatLogEntries.findIndex(e => e.id === selectedId);
                if (index >= 0) virtualList.scrollTo(index);
              });
            }, {
              immediate: true
            });
            return (_ctx, _cache) => {
              return openBlock(), createElementBlock("div", mergeProps({
                class: _ctx.$style.tree
              }, unref(virtualList).containerProps), [createBaseVNode("div", mergeProps({
                role: "tree"
              }, unref(virtualList).wrapperProps.value), [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(virtualList).list.value, ({
                data,
                index
              }) => {
                return openBlock(), createBlock(LogsOverviewRow_default, {
                  key: index,
                  data,
                  "is-read-only": _ctx.isReadOnly,
                  "is-selected": data.id === _ctx.selected?.id,
                  "is-compact": _ctx.isCompact,
                  "should-show-token-count-column": _ctx.shouldShowTokenCountColumn,
                  "latest-info": _ctx.latestNodeInfo[data.node.id],
                  expanded: isExpanded.value[data.id],
                  "can-open-ndv": _ctx.canOpenNdv,
                  onToggleExpanded: $event => emit("toggleExpanded", data),
                  onOpenNdv: $event => emit("openNdv", data),
                  onTriggerPartialExecution: $event => handleTriggerPartialExecution(data),
                  onToggleSelected: $event => emit("select", _ctx.selected?.id === data.id ? void 0 : data)
                }, null, 8, ["data", "is-read-only", "is-selected", "is-compact", "should-show-token-count-column", "latest-info", "expanded", "can-open-ndv", "onToggleExpanded", "onOpenNdv", "onTriggerPartialExecution", "onToggleSelected"]);
              }), 128))], 16)], 16);
            };
          }
        }); //#endregion
        //#region src/features/execution/logs/components/LogsOverviewRows.vue?vue&type=style&index=0&lang.module.scss
        tree = "_tree_92rld_123";
        container = "_container_92rld_128";
        staticScrollBar = "_staticScrollBar_92rld_128";
        LogsOverviewRows_vue_vue_type_style_index_0_lang_module_default = {
          tree,
          container,
          staticScrollBar
        }; //#endregion
        //#region src/features/execution/logs/components/LogsOverviewRows.vue
        cssModules = {
          "$style": LogsOverviewRows_vue_vue_type_style_index_0_lang_module_default
        };
        _export("r", LogsOverviewRows_default = /* @__PURE__ */__plugin_vue_export_helper_default(LogsOverviewRows_vue_vue_type_script_setup_true_lang_default, [["__cssModules", cssModules]]));
      }
    };
  });
})();