n8n-editor-ui 1.93.0 → 1.94.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/assets/{AnimatedSpinner-hbTZDd93.js → AnimatedSpinner-D6WDdcap.js} +1 -1
  2. package/dist/assets/{AnnotationTagsDropdown.ee.vue_vue_type_script_setup_true_lang-CYzc5StE.js → AnnotationTagsDropdown.ee.vue_vue_type_script_setup_true_lang-BIiF0RoL.js} +1 -1
  3. package/dist/assets/{AuthView-8SLMP0H_.js → AuthView-B4QlUHa3.js} +2 -2
  4. package/dist/assets/{CanvasChatSwitch-Dt8TgNJg.js → CanvasChatSwitch-K2_X0yVZ.js} +17 -18
  5. package/dist/assets/{ChangePasswordView-DIRyDp89.js → ChangePasswordView-nJzqV_9k.js} +3 -3
  6. package/dist/assets/CollectionParameter-DSAqoHVF.js +4 -0
  7. package/dist/assets/{CredentialsView-B6-VxAJ6.js → CredentialsView-DwV08zbe.js} +7 -7
  8. package/dist/assets/{DemoFooter-CIHwH5PG.js → DemoFooter-DKvO12Ew.js} +7 -8
  9. package/dist/assets/{ErrorView-C7i0TZwT.js → ErrorView-BJvgdQd3.js} +1 -1
  10. package/dist/assets/{ExecutionsTime.vue_vue_type_script_setup_true_lang--2G21NNR.js → ExecutionsTime.vue_vue_type_script_setup_true_lang-ykvCUf2F.js} +2 -2
  11. package/dist/assets/{ExecutionsView-C_YtciAr.js → ExecutionsView-Dv-BEvYW.js} +19 -18
  12. package/dist/assets/{FileSaver.min-bgn7Q9Gt.js → FileSaver.min-BuBI9fyd.js} +1 -1
  13. package/dist/assets/{FixedCollectionParameter-BPCJ5aaq.js → FixedCollectionParameter-C_dNC7Pj.js} +1 -1
  14. package/dist/assets/{ForgotMyPasswordView-DyUaGd6Z.js → ForgotMyPasswordView-BqD6YlYn.js} +3 -3
  15. package/dist/assets/{InsightsChartAverageRuntime-BB2I2vpV.js → InsightsChartAverageRuntime-yZMYNCP5.js} +4 -4
  16. package/dist/assets/{InsightsChartFailed-CN_Rl3Bl.js → InsightsChartFailed-DswsKdTF.js} +4 -4
  17. package/dist/assets/{InsightsChartFailureRate-CHKlg6tg.js → InsightsChartFailureRate-ChXUUpeM.js} +4 -4
  18. package/dist/assets/{InsightsChartTimeSaved-Cd05cM8q.js → InsightsChartTimeSaved-8QcRGtZx.js} +4 -4
  19. package/dist/assets/{InsightsChartTotal-ChAO7myf.js → InsightsChartTotal-NdMdI8Qq.js} +4 -4
  20. package/dist/assets/{InsightsDashboard-Bx4vx9gz.css → InsightsDashboard-BSrakbzr.css} +42 -8
  21. package/dist/assets/{InsightsDashboard-BeCfBVUz.js → InsightsDashboard-D41M-gz3.js} +40 -41
  22. package/dist/assets/{InsightsPaywall-Chz8CDc3.js → InsightsPaywall-bBhcjWHb.js} +1 -1
  23. package/dist/assets/{InsightsSummary-CdlaUpAt.css → InsightsSummary-DzGQpM5h.css} +27 -24
  24. package/dist/assets/InsightsSummary-cD6ZTQoq.js +209 -0
  25. package/dist/assets/{InsightsTableWorkflows-5rpYY7YT.js → InsightsTableWorkflows-D-kstco3.js} +5 -6
  26. package/dist/assets/{InsightsTableWorkflows-Blv_GPUj.css → InsightsTableWorkflows-DfTZQkWL.css} +3 -4
  27. package/dist/assets/{Logo-DUDCllkm.js → Logo-BWI1k82s.js} +1 -1
  28. package/dist/assets/{LogsPanel-D9r5AcQH.js → LogsPanel-dLKjFOi5.js} +331 -336
  29. package/dist/assets/{MainHeader-DkKOOZ_D.js → MainHeader-DKuLugMM.js} +13 -13
  30. package/dist/assets/{MainHeader-CEMGASqv.css → MainHeader-Y95RcfHb.css} +18 -18
  31. package/dist/assets/{MainSidebar-ZUBIWeXm.js → MainSidebar-D2cUU1u5.js} +2 -2
  32. package/dist/assets/{NodeCreation-DCfAFuL5.js → NodeCreation-ueFdk4bA.js} +3 -4
  33. package/dist/assets/{NodeCreator-a0YVv1IE.js → NodeCreator-BWDbSeT1.js} +172 -68
  34. package/dist/assets/{NodeCreator-D18StsVZ.css → NodeCreator-Cp8Apzva.css} +38 -21
  35. package/dist/assets/{NodeDetailsView-pYP-34nS.css → NodeDetailsView-DpO8nTmN.css} +16 -16
  36. package/dist/assets/{NodeDetailsView-C5_hVJzj.js → NodeDetailsView-Drob-YV5.js} +20 -11
  37. package/dist/assets/{NodeView-Bk9h8GYy.js → NodeView-Dnn0dJFr.js} +81 -38
  38. package/dist/assets/{ProjectCardBadge-DRlDZx3d.js → ProjectCardBadge-DK_f2cCt.js} +1 -1
  39. package/dist/assets/{ProjectHeader-DNm605Kk.js → ProjectHeader-NRCcW7_U.js} +2 -2
  40. package/dist/assets/{ProjectSettings-Dge_6KaR.js → ProjectSettings-B98B3ftD.js} +14 -4
  41. package/dist/assets/{PushConnectionTracker.vue_vue_type_script_setup_true_lang-CUf0LkWR.js → PushConnectionTracker.vue_vue_type_script_setup_true_lang-EcrEFKi4.js} +1 -1
  42. package/dist/assets/{ResourcesListLayout-Bbl-1i4l.js → ResourcesListLayout-sZKInqTx.js} +2 -2
  43. package/dist/assets/{RunData-DQeENuzG.css → RunData-CE5FsU6k.css} +2 -2
  44. package/dist/assets/{RunData-b0RE2JWc.js → RunData-D3endKo8.js} +233 -92
  45. package/dist/assets/{RunDataAi-DnWcCR_0.js → RunDataAi-DtrK7pjQ.js} +3 -4
  46. package/dist/assets/{RunDataJson-CptVuHuA.js → RunDataJson-BJ8lDeAI.js} +7 -7
  47. package/dist/assets/{RunDataJsonActions-3jjDztw7.js → RunDataJsonActions-DpCNv6bq.js} +1 -1
  48. package/dist/assets/{RunDataParsedAiContent-BbXv-NPD.js → RunDataParsedAiContent--QjlaSo3.js} +5 -5
  49. package/dist/assets/{RunDataSearch-B90wjsDA.js → RunDataSearch-InL45suv.js} +1 -1
  50. package/dist/assets/{RunDataTable-CpS78GlT.js → RunDataTable-CRwBT8_s.js} +3 -3
  51. package/dist/assets/{SamlOnboarding-Ch9K5rRW.js → SamlOnboarding-CKncz2Ro.js} +3 -3
  52. package/dist/assets/{SettingsApiView-9GU5n_rm.js → SettingsApiView-CE0y_6pn.js} +1 -1
  53. package/dist/assets/{SettingsCommunityNodesView-CPnVRzNX.js → SettingsCommunityNodesView-Dec23ei2.js} +4 -4
  54. package/dist/assets/{SettingsExternalSecrets-D7xTMV9h.js → SettingsExternalSecrets-Dqp4cvDN.js} +1 -1
  55. package/dist/assets/{SettingsLdapView-OfrjGKkt.js → SettingsLdapView-Dk8y5NtN.js} +1 -1
  56. package/dist/assets/{SettingsLogStreamingView-C_VnOaeX.js → SettingsLogStreamingView-BqphnxJz.js} +1 -1
  57. package/dist/assets/{SettingsPersonalView-Dm24akPV.js → SettingsPersonalView-aoam48uq.js} +1 -1
  58. package/dist/assets/{SettingsSourceControl-DDCmL82j.js → SettingsSourceControl-B_1iGyw9.js} +1 -1
  59. package/dist/assets/{SettingsSso-BGGQ0Cpg.js → SettingsSso-CRDg8n6o.js} +1 -1
  60. package/dist/assets/{SettingsUsageAndPlan-BzO_zdkH.js → SettingsUsageAndPlan-DALiZmtM.js} +1 -1
  61. package/dist/assets/{SettingsUsersView-DHQUqhqB.js → SettingsUsersView-BFmyoREW.js} +1 -1
  62. package/dist/assets/{SettingsView-CbtAqjOX.js → SettingsView-Ct5FP8RA.js} +1 -1
  63. package/dist/assets/{SetupView-BME1OE6U.js → SetupView-CWBcWcHu.js} +3 -3
  64. package/dist/assets/{SetupWorkflowCredentialsButton-DZr4TCPC.js → SetupWorkflowCredentialsButton-DNjlHJdz.js} +1 -1
  65. package/dist/assets/{SetupWorkflowFromTemplateView-CPkKEY04.js → SetupWorkflowFromTemplateView-CDxjlwvR.js} +3 -3
  66. package/dist/assets/{SigninView-DUeRvOiY.js → SigninView-w-cjH-9l.js} +3 -3
  67. package/dist/assets/{SignoutView-BC7SBunZ.js → SignoutView-BQRpyJSJ.js} +1 -1
  68. package/dist/assets/{SignupView-B5ecYJ2q.js → SignupView-C7787Mur.js} +3 -3
  69. package/dist/assets/{TemplateDetails-DjanZgC1.js → TemplateDetails-xekR6vvf.js} +1 -1
  70. package/dist/assets/{TemplateList-8TyNGxY-.js → TemplateList-ChkM_l8S.js} +1 -1
  71. package/dist/assets/{TemplatesCollectionView-BkH4pJCv.js → TemplatesCollectionView-C7G8-LtU.js} +5 -5
  72. package/dist/assets/{TemplatesSearchView-Bcdhi1SL.js → TemplatesSearchView-D1zNGFYQ.js} +3 -3
  73. package/dist/assets/{TemplatesView-De2XB6We.js → TemplatesView-l-xkgW6-.js} +1 -1
  74. package/dist/assets/{TemplatesWorkflowView-BVnwtrMa.js → TemplatesWorkflowView-VjCM8q6w.js} +5 -5
  75. package/dist/assets/{TestDefinitionEditView-DjmPnrTk.js → TestDefinitionEditView-NwOMxo3u.js} +6 -7
  76. package/dist/assets/{TestDefinitionListView-BL2s_qBZ.js → TestDefinitionListView-BWV9O0Q3.js} +1 -1
  77. package/dist/assets/{TestDefinitionNewView-B9BqJZST.js → TestDefinitionNewView-CPb07jVn.js} +2 -2
  78. package/dist/assets/{TestDefinitionRootView-AlWyxbc0.js → TestDefinitionRootView-dvJQLmpk.js} +1 -1
  79. package/dist/assets/{VariablesView-BZCvPfan.js → VariablesView-BVls8Qra.js} +4 -4
  80. package/dist/assets/{WorkerView-CigxqnWi.js → WorkerView-Dm9dqtjG.js} +6 -6
  81. package/dist/assets/{WorkflowActivator-B7jRy4L1.js → WorkflowActivator-DfshltMu.js} +11 -9
  82. package/dist/assets/{WorkflowExecutionsInfoAccordion-C_ZycbsF.js → WorkflowExecutionsInfoAccordion-CrrBjf1F.js} +1 -1
  83. package/dist/assets/{WorkflowExecutionsLandingPage-DOqrfKlC.js → WorkflowExecutionsLandingPage-DrIX9hPD.js} +2 -2
  84. package/dist/assets/{WorkflowExecutionsPreview-B4Cj2gXW.js → WorkflowExecutionsPreview-C3ZM2R3J.js} +6 -6
  85. package/dist/assets/{WorkflowExecutionsView-RXfP7zkJ.js → WorkflowExecutionsView-BfWgLIZh.js} +10 -10
  86. package/dist/assets/{WorkflowHistory-DrXrRwIS.js → WorkflowHistory-gIJ3qyRQ.js} +3 -3
  87. package/dist/assets/{WorkflowOnboardingView-CXH1vCW2.js → WorkflowOnboardingView-CuOxA3HS.js} +1 -1
  88. package/dist/assets/{WorkflowPreview-B_MuFEV8.js → WorkflowPreview-DeCTI_GV.js} +1 -1
  89. package/dist/assets/{WorkflowsView-D90hfJ35.js → WorkflowsView-D65lDvqh.js} +9 -9
  90. package/dist/assets/{chartjs.utils-DalQn9bk.js → chartjs.utils-BpJiEmTU.js} +2 -2
  91. package/dist/assets/{dateFormatter-BPfJSa6q.js → dateFormatter-DNA1ez0J.js} +1 -1
  92. package/dist/assets/{easyAiWorkflowUtils-kgtpBx2h.js → easyAiWorkflowUtils-CGShRraC.js} +1 -1
  93. package/dist/assets/{global-link-actions-CnWOMvqA.js → global-link-actions-C7aXjvv8.js} +1 -1
  94. package/dist/assets/{import-curl-BvX_O56D.js → import-curl-Cp0oelYK.js} +1 -1
  95. package/dist/assets/{index-Bb2NNknG.js → index-B9xszJYe.js} +1 -1
  96. package/dist/assets/{index-DZ6VpjNj.js → index-BEvy7DZc.js} +60295 -57650
  97. package/dist/assets/{index-yNaoC3fo.css → index-Ed_z14lJ.css} +91 -435
  98. package/dist/assets/{pickBy-B_HGYyxS.js → pickBy-B7cHrDCV.js} +1 -1
  99. package/dist/assets/{polyfills-CLZ4X0Ad.js → polyfills-J2x06Gdp.js} +157 -224
  100. package/dist/assets/{templateActions-DQfZ3ni5.js → templateActions-D2DZ5K8P.js} +1 -1
  101. package/dist/assets/{typescript.worker-BsxN2afA.js → typescript.worker-B1loTpxy.js} +1 -1
  102. package/dist/assets/{useBeforeUnload-Cu0LPVWe.js → useBeforeUnload-DkXUEOdq.js} +1 -1
  103. package/dist/assets/{useCanvasMapping-VtpW_QZA.css → useCanvasMapping-CFf4cwnq.css} +6 -6
  104. package/dist/assets/{useCanvasMapping-CTTq6x8X.js → useCanvasMapping-DjhK-zhP.js} +56 -31
  105. package/dist/assets/{useClearExecutionButtonVisible-Dwc1_eG9.js → useClearExecutionButtonVisible--2zd8JTS.js} +1 -2
  106. package/dist/assets/{useExecutionDebugging-rc72wLIp.js → useExecutionDebugging-CfJ1doKR.js} +1 -1
  107. package/dist/assets/{useExecutionHelpers-DqwMonFW.js → useExecutionHelpers-DcgY6WXs.js} +3 -3
  108. package/dist/assets/{useImportCurlCommand-D_onuFvo.js → useImportCurlCommand-D5kLqokm.js} +2 -2
  109. package/dist/assets/{useProjectPages-e8b03-5_.js → useProjectPages-DgIy9DQO.js} +1 -1
  110. package/dist/assets/{usePushConnection-wm-7Id6Q.js → usePushConnection-DieWXsRW.js} +16 -111
  111. package/dist/assets/{useTestDefinitionForm-DlUOnNC0.js → useTestDefinitionForm-Mm_EnTMi.js} +1 -1
  112. package/dist/assets/{useWorkflowActivate-65xML23U.js → useWorkflowActivate-CkyGF_8r.js} +1 -1
  113. package/dist/assets/{useWorkflowSaving-CUel20JA.js → useWorkflowSaving-B0hVR80g.js} +1 -1
  114. package/dist/index.html +3 -3
  115. package/package.json +1 -1
  116. package/tsconfig.json +1 -0
  117. package/vite.config.mts +4 -0
  118. package/dist/assets/CollectionParameter-Cj4t6-hd.js +0 -4
  119. package/dist/assets/InsightsSummary-MECenLJQ.js +0 -207
  120. package/dist/assets/useCanvasOperations-u8oSDa_u.js +0 -2834
@@ -1,7 +1,7 @@
1
- import { b0 as inject, b1 as isRef, i as createElementBlock, g as openBlock, k as createBaseVNode, d as defineComponent, q as computed, j as createVNode, e as createBlock, f as createCommentVNode, m as unref, t as toDisplayString, b2 as withModifiers, _ as _export_sfc, b3 as toRefs, r as ref, o as onMounted, n as normalizeClass, x as renderSlot, b4 as normalizeProps, b5 as guardReactiveProps, b6 as resolveDynamicComponent, b7 as mergeProps, b8 as VueMarkdown, F as Fragment, D as renderList, b9 as markdownLink, ba as useFileDialog, bb as onUnmounted, B as normalizeStyle, aA as withDirectives, bc as vModelText, bd as withKeys, w as withCtx, X as watch, h as resolveComponent, l as createTextVNode, be as N8nText, bf as useClipboard, a as useToast, c as useI18n$1, aR as N8nTooltip, bg as N8nButton, aT as _sfc_main$i, aV as createSlots, aJ as useStorage, a_ as watchEffect, y as onBeforeUnmount, G as useDebounce, bh as provide, bi as useProvideTooltipAppendTo, bj as IsInPiPWindowSymbol, bk as CHAT_TRIGGER_NODE_TYPE, bl as MANUAL_CHAT_TRIGGER_NODE_TYPE, bm as NodeConnectionTypes, bn as v4, bo as get, bp as isEmpty, bq as usePinnedData, ai as useMessage, aj as MODAL_CONFIRM, br as CHAIN_SUMMARIZATION_LANGCHAIN_NODE_TYPE, bs as AI_SUBCATEGORY, bt as AI_CATEGORY_AGENTS, bu as AI_CATEGORY_CHAINS, bv as AI_CODE_NODE_TYPE, bw as getNodeInputs, bx as getConnectionTypes, by as getNodeOutputs, Q as useWorkflowsStore, bz as useNodeTypesStore, b as useRouter, bA as useNodeHelpers, bB as useRunWorkflow, V as VIEWS, aZ as LOGS_PANEL_STATE, bC as _sfc_main$k, bD as I18nT, bE as N8nIcon, bF as upperFirst, as as useNDVStore, bG as useVirtualList, bH as N8nRadioButtons, ag as useTelemetry, z as nextTick, bI as ndvEventBus, aS as N8nLink, av as useLocalStorage, bJ as LOG_DETAILS_CONTENT, aY as useTemplateRef, a$ as N8nResizeWrapper, bK as useStyles, $ as useCanvasStore, bL as Workflow, bM as IN_PROGRESS_EXECUTION_ID, bN as useThrottleFn } from "./index-DZ6VpjNj.js";
2
- import { u as useClearExecutionButtonVisible } from "./useClearExecutionButtonVisible-Dwc1_eG9.js";
3
- import { H as HighlightJS, f as formatTokenUsageCount, _ as _sfc_main$j, g as getSubtreeTotalConsumedTokens, a as getTotalConsumedTokens, b as flattenLogEntries, R as RunData, c as createLogEntries, d as deepToRaw, e as findSelectedLogEntry } from "./RunData-b0RE2JWc.js";
4
- import { t as toTime, a as toDayMonth } from "./dateFormatter-BPfJSa6q.js";
1
+ import { b1 as inject, b2 as isRef, i as createElementBlock, g as openBlock, k as createBaseVNode, d as defineComponent, q as computed, j as createVNode, e as createBlock, f as createCommentVNode, m as unref, t as toDisplayString, b3 as withModifiers, _ as _export_sfc, b4 as toRefs, r as ref, o as onMounted, n as normalizeClass, x as renderSlot, b5 as normalizeProps, b6 as guardReactiveProps, b7 as resolveDynamicComponent, b8 as mergeProps, F as Fragment, D as renderList, b9 as markdownLink, ba as useFileDialog, bb as chatEventBus, bc as onUnmounted, B as normalizeStyle, aA as withDirectives, bd as vModelText, be as withKeys, w as withCtx, X as watch, h as resolveComponent, l as createTextVNode, bf as N8nText, bg as useClipboard, a as useToast, p as useSettingsStore, c as useI18n$1, aR as N8nTooltip, bh as N8nButton, aT as _sfc_main$i, aV as createSlots, aJ as useStorage, a$ as watchEffect, y as onBeforeUnmount, G as useDebounce, bi as provide, bj as useProvideTooltipAppendTo, bk as IsInPiPWindowSymbol, bl as usePinnedData, ai as useMessage, aj as MODAL_CONFIRM, bm as v4, bn as getInputKey, bo as extractBotResponse, bp as isChatNode, bq as CHAIN_SUMMARIZATION_LANGCHAIN_NODE_TYPE, br as AI_SUBCATEGORY, bs as AI_CATEGORY_AGENTS, bt as AI_CATEGORY_CHAINS, bu as AI_CODE_NODE_TYPE, bv as getNodeInputs, bw as getConnectionTypes, bx as getNodeOutputs, by as NodeConnectionTypes, Q as useWorkflowsStore, bz as useNodeTypesStore, aY as useLogsStore, b as useRouter, bA as useNodeHelpers, bB as useRunWorkflow, bC as restoreChatHistory, V as VIEWS, aZ as useTemplateRef, bD as _sfc_main$k, bE as I18nT, bF as N8nIcon, bG as upperFirst, z as nextTick, bH as useVirtualList, bI as toRef, bJ as N8nRadioButtons, as as useNDVStore, aS as N8nLink, av as useLocalStorage, bK as LOG_DETAILS_PANEL_STATE, bL as KeyboardShortcutTooltip, b0 as N8nResizeWrapper, bM as useStyles, a_ as LOGS_PANEL_STATE, ag as useTelemetry, bN as Workflow, bO as useThrottleFn, bP as parse, bQ as ndvEventBus } from "./index-BEvy7DZc.js";
2
+ import { u as useClearExecutionButtonVisible } from "./useClearExecutionButtonVisible--2zd8JTS.js";
3
+ import { H as HighlightJS, V as VueMarkdown, f as formatTokenUsageCount, _ as _sfc_main$j, g as getSubtreeTotalConsumedTokens, a as getTotalConsumedTokens, h as hasSubExecution, R as RunData, c as createLogTree, d as deepToRaw, m as mergeStartData, b as findSelectedLogEntry, e as getEntryAtRelativeIndex, i as getDepth, j as flattenLogEntries } from "./RunData-D3endKo8.js";
4
+ import { t as toTime, a as toDayMonth } from "./dateFormatter-DNA1ez0J.js";
5
5
  function bash(hljs) {
6
6
  const regex = hljs.regex;
7
7
  const VAR = {};
@@ -2797,39 +2797,6 @@ function render(_ctx, _cache) {
2797
2797
  ]));
2798
2798
  }
2799
2799
  const IconSend = { name: "mdi-send", render };
2800
- function createEventBus() {
2801
- const handlers = /* @__PURE__ */ new Map();
2802
- function off(eventName, fn) {
2803
- const eventFns = handlers.get(eventName);
2804
- if (eventFns) {
2805
- eventFns.splice(eventFns.indexOf(fn) >>> 0, 1);
2806
- }
2807
- }
2808
- function on(eventName, fn) {
2809
- let eventFns = handlers.get(eventName);
2810
- if (!eventFns) {
2811
- eventFns = [fn];
2812
- } else {
2813
- eventFns.push(fn);
2814
- }
2815
- handlers.set(eventName, eventFns);
2816
- return () => off(eventName, fn);
2817
- }
2818
- function emit(eventName, event) {
2819
- const eventFns = handlers.get(eventName);
2820
- if (eventFns) {
2821
- eventFns.slice().forEach(async (handler) => {
2822
- await handler(event);
2823
- });
2824
- }
2825
- }
2826
- return {
2827
- on,
2828
- off,
2829
- emit
2830
- };
2831
- }
2832
- const chatEventBus = createEventBus();
2833
2800
  const _hoisted_1$4 = { class: "chat-inputs" };
2834
2801
  const _hoisted_2$2 = {
2835
2802
  key: 0,
@@ -3268,7 +3235,7 @@ const cssModules$a = {
3268
3235
  };
3269
3236
  const MessageOptionAction = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__cssModules", cssModules$a]]);
3270
3237
  const _sfc_main$a = /* @__PURE__ */ defineComponent({
3271
- __name: "PanelHeader",
3238
+ __name: "LogsPanelHeader",
3272
3239
  props: {
3273
3240
  title: {}
3274
3241
  },
@@ -3312,7 +3279,7 @@ const style0$9 = {
3312
3279
  const cssModules$9 = {
3313
3280
  "$style": style0$9
3314
3281
  };
3315
- const PanelHeader = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__cssModules", cssModules$9]]);
3282
+ const LogsPanelHeader = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__cssModules", cssModules$9]]);
3316
3283
  const _hoisted_1$2 = ["onClick"];
3317
3284
  const _sfc_main$9 = /* @__PURE__ */ defineComponent({
3318
3285
  __name: "ChatMessagesPanel",
@@ -3332,6 +3299,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
3332
3299
  const clipboard = useClipboard();
3333
3300
  const locale = useI18n$1();
3334
3301
  const toast = useToast();
3302
+ const settingsStore = useSettingsStore();
3335
3303
  const previousMessageIndex = ref(0);
3336
3304
  const sessionIdText = computed(
3337
3305
  () => locale.baseText("chat.window.session.id", {
@@ -3398,7 +3366,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
3398
3366
  watch(
3399
3367
  () => props.isOpen,
3400
3368
  (isOpen) => {
3401
- if (isOpen) {
3369
+ if (isOpen && !settingsStore.isNewLogsEnabled) {
3402
3370
  setTimeout(() => {
3403
3371
  chatEventBus.emit("focusInput");
3404
3372
  }, 0);
@@ -3408,10 +3376,11 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
3408
3376
  );
3409
3377
  return (_ctx, _cache) => {
3410
3378
  return openBlock(), createElementBlock("div", {
3411
- class: normalizeClass(_ctx.$style.chat),
3412
- "data-test-id": "workflow-lm-chat-dialog"
3379
+ class: normalizeClass([_ctx.$style.chat, "ignore-key-press-canvas"]),
3380
+ "data-test-id": "workflow-lm-chat-dialog",
3381
+ tabindex: "0"
3413
3382
  }, [
3414
- _ctx.isNewLogsEnabled ? (openBlock(), createBlock(PanelHeader, {
3383
+ _ctx.isNewLogsEnabled ? (openBlock(), createBlock(LogsPanelHeader, {
3415
3384
  key: 0,
3416
3385
  "data-test-id": "chat-header",
3417
3386
  title: unref(locale).baseText("chat.window.title"),
@@ -3775,85 +3744,6 @@ function usePiPWindow({
3775
3744
  });
3776
3745
  return { canPopOut, isPoppedOut, pipWindow };
3777
3746
  }
3778
- function isChatNode(node) {
3779
- return [CHAT_TRIGGER_NODE_TYPE, MANUAL_CHAT_TRIGGER_NODE_TYPE].includes(node.type);
3780
- }
3781
- function getInputKey(node) {
3782
- if (node.type === MANUAL_CHAT_TRIGGER_NODE_TYPE && node.typeVersion < 1.1) {
3783
- return "input";
3784
- }
3785
- if (node.type === CHAT_TRIGGER_NODE_TYPE) {
3786
- return "chatInput";
3787
- }
3788
- return "chatInput";
3789
- }
3790
- function extractChatInput(workflow, resultData) {
3791
- const chatTrigger = workflow.nodes.find(isChatNode);
3792
- if (chatTrigger === void 0) {
3793
- return void 0;
3794
- }
3795
- const inputKey = getInputKey(chatTrigger);
3796
- const runData = (resultData.runData[chatTrigger.name] ?? [])[0];
3797
- const message = runData?.data?.[NodeConnectionTypes.Main]?.[0]?.[0]?.json?.[inputKey];
3798
- if (runData === void 0 || typeof message !== "string") {
3799
- return void 0;
3800
- }
3801
- return {
3802
- text: message,
3803
- sender: "user",
3804
- id: v4()
3805
- };
3806
- }
3807
- function extractBotResponse(resultData, executionId, emptyText2) {
3808
- const lastNodeExecuted = resultData.lastNodeExecuted;
3809
- if (!lastNodeExecuted) return void 0;
3810
- const nodeResponseDataArray = get(resultData.runData, lastNodeExecuted) ?? [];
3811
- const nodeResponseData = nodeResponseDataArray[nodeResponseDataArray.length - 1];
3812
- let responseMessage;
3813
- if (get(nodeResponseData, "error")) {
3814
- responseMessage = "[ERROR: " + get(nodeResponseData, "error.message") + "]";
3815
- } else {
3816
- const responseData = get(nodeResponseData, "data.main[0][0].json");
3817
- const text = extractResponseText(responseData) ?? emptyText2;
3818
- if (!text) {
3819
- return void 0;
3820
- }
3821
- responseMessage = text;
3822
- }
3823
- return {
3824
- text: responseMessage,
3825
- sender: "bot",
3826
- id: executionId ?? v4()
3827
- };
3828
- }
3829
- function extractResponseText(responseData) {
3830
- if (!responseData || isEmpty(responseData)) {
3831
- return void 0;
3832
- }
3833
- const paths = ["output", "text", "response.text"];
3834
- const matchedPath = paths.find((path) => get(responseData, path));
3835
- if (!matchedPath) return JSON.stringify(responseData, null, 2);
3836
- const matchedOutput = get(responseData, matchedPath);
3837
- if (typeof matchedOutput === "object") {
3838
- return "```json\n" + JSON.stringify(matchedOutput, null, 2) + "\n```";
3839
- }
3840
- return matchedOutput?.toString() ?? "";
3841
- }
3842
- function restoreChatHistory(workflowExecutionData, emptyText2) {
3843
- if (!workflowExecutionData?.data) {
3844
- return [];
3845
- }
3846
- const userMessage = extractChatInput(
3847
- workflowExecutionData.workflowData,
3848
- workflowExecutionData.data.resultData
3849
- );
3850
- const botMessage = extractBotResponse(
3851
- workflowExecutionData.data.resultData,
3852
- workflowExecutionData.id,
3853
- emptyText2
3854
- );
3855
- return [...userMessage ? [userMessage] : [], ...botMessage ? [botMessage] : []];
3856
- }
3857
3747
  function useChatMessaging({
3858
3748
  chatTrigger,
3859
3749
  messages: messages2,
@@ -4046,13 +3936,13 @@ function useChatState(isReadOnly) {
4046
3936
  const locale = useI18n$1();
4047
3937
  const workflowsStore = useWorkflowsStore();
4048
3938
  const nodeTypesStore = useNodeTypesStore();
3939
+ const logsStore = useLogsStore();
4049
3940
  const router = useRouter();
4050
3941
  const nodeHelpers = useNodeHelpers();
4051
3942
  const { runWorkflow } = useRunWorkflow({ router });
4052
3943
  const messages2 = ref([]);
4053
3944
  const currentSessionId = ref(v4().replace(/-/g, ""));
4054
3945
  const previousChatMessages = computed(() => workflowsStore.getPastChatMessages);
4055
- const logsPanelState = computed(() => workflowsStore.logsPanelState);
4056
3946
  const workflow = computed(() => workflowsStore.getCurrentWorkflow());
4057
3947
  const { chatTriggerNode, connectedNode, allowFileUploads, allowedFilesMimeTypes } = useChatTrigger({
4058
3948
  workflow,
@@ -4146,7 +4036,7 @@ function useChatState(isReadOnly) {
4146
4036
  nodeHelpers.updateNodesExecutionIssues();
4147
4037
  messages2.value = [];
4148
4038
  currentSessionId.value = v4().replace(/-/g, "");
4149
- if (logsPanelState.value !== LOGS_PANEL_STATE.CLOSED) {
4039
+ if (logsStore.isOpen) {
4150
4040
  chatEventBus.emit("focusInput");
4151
4041
  }
4152
4042
  }
@@ -4169,7 +4059,7 @@ function useChatState(isReadOnly) {
4169
4059
  };
4170
4060
  }
4171
4061
  const _sfc_main$8 = /* @__PURE__ */ defineComponent({
4172
- __name: "ConsumedTokenCountText",
4062
+ __name: "LogsViewConsumedTokenCountText",
4173
4063
  props: {
4174
4064
  consumedTokens: {}
4175
4065
  },
@@ -4199,7 +4089,7 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
4199
4089
  const _hoisted_1$1 = { key: 0 };
4200
4090
  const _hoisted_2 = { key: 1 };
4201
4091
  const _sfc_main$7 = /* @__PURE__ */ defineComponent({
4202
- __name: "NodeName",
4092
+ __name: "LogsViewNodeName",
4203
4093
  props: {
4204
4094
  name: {},
4205
4095
  latestName: {},
@@ -4231,7 +4121,7 @@ const style0$7 = {
4231
4121
  const cssModules$7 = {
4232
4122
  "$style": style0$7
4233
4123
  };
4234
- const NodeName = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__cssModules", cssModules$7]]);
4124
+ const LogsViewNodeName = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__cssModules", cssModules$7]]);
4235
4125
  const _hoisted_1 = ["aria-expanded", "aria-selected"];
4236
4126
  const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4237
4127
  __name: "LogsOverviewRow",
@@ -4239,15 +4129,17 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4239
4129
  data: {},
4240
4130
  isSelected: { type: Boolean },
4241
4131
  isReadOnly: { type: Boolean },
4242
- shouldShowConsumedTokens: { type: Boolean },
4132
+ shouldShowTokenCountColumn: { type: Boolean },
4243
4133
  isCompact: { type: Boolean },
4244
4134
  latestInfo: {},
4245
- expanded: { type: Boolean }
4135
+ expanded: { type: Boolean },
4136
+ canOpenNdv: { type: Boolean }
4246
4137
  },
4247
- emits: ["toggleExpanded", "triggerPartialExecution", "openNdv"],
4138
+ emits: ["toggleExpanded", "toggleSelected", "triggerPartialExecution", "openNdv"],
4248
4139
  setup(__props, { emit: __emit }) {
4249
4140
  const props = __props;
4250
4141
  const emit = __emit;
4142
+ const container2 = useTemplateRef("containerRef");
4251
4143
  const locale = useI18n$1();
4252
4144
  const nodeTypeStore = useNodeTypesStore();
4253
4145
  const type = computed(() => nodeTypeStore.getNodeType(props.data.node.type));
@@ -4264,7 +4156,10 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4264
4156
  });
4265
4157
  });
4266
4158
  const subtreeConsumedTokens = computed(
4267
- () => props.shouldShowConsumedTokens ? getSubtreeTotalConsumedTokens(props.data) : void 0
4159
+ () => props.shouldShowTokenCountColumn ? getSubtreeTotalConsumedTokens(props.data, false) : void 0
4160
+ );
4161
+ const hasChildren = computed(
4162
+ () => props.data.children.length > 0 || !!props.data.runData.metadata?.subExecution
4268
4163
  );
4269
4164
  function isLastChild(level) {
4270
4165
  let parent = props.data.parent;
@@ -4277,11 +4172,23 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4277
4172
  const lastSibling = siblings[siblings.length - 1];
4278
4173
  return data === void 0 && lastSibling === void 0 || data?.node === lastSibling?.node && data?.runIndex === lastSibling?.runIndex;
4279
4174
  }
4175
+ watch(
4176
+ () => props.isSelected,
4177
+ (isSelected) => {
4178
+ void nextTick(() => {
4179
+ if (isSelected) {
4180
+ container2.value?.focus();
4181
+ }
4182
+ });
4183
+ },
4184
+ { immediate: true }
4185
+ );
4280
4186
  return (_ctx, _cache) => {
4281
4187
  const _component_NodeIcon = _sfc_main$k;
4282
4188
  return openBlock(), createElementBlock("div", {
4189
+ ref: "containerRef",
4283
4190
  role: "treeitem",
4284
- tabindex: "0",
4191
+ tabindex: "-1",
4285
4192
  "aria-expanded": props.data.children.length > 0 && props.expanded,
4286
4193
  "aria-selected": props.isSelected,
4287
4194
  class: normalizeClass({
@@ -4289,7 +4196,8 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4289
4196
  [_ctx.$style.compact]: props.isCompact,
4290
4197
  [_ctx.$style.error]: isError.value,
4291
4198
  [_ctx.$style.selected]: props.isSelected
4292
- })
4199
+ }),
4200
+ onClick: _cache[3] || (_cache[3] = withModifiers(($event) => emit("toggleSelected"), ["stop"]))
4293
4201
  }, [
4294
4202
  (openBlock(true), createElementBlock(Fragment, null, renderList(props.data.depth, (level) => {
4295
4203
  return openBlock(), createElementBlock("div", {
@@ -4310,7 +4218,7 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4310
4218
  size: 16,
4311
4219
  class: normalizeClass(_ctx.$style.icon)
4312
4220
  }, null, 8, ["node-type", "class"]),
4313
- createVNode(NodeName, {
4221
+ createVNode(LogsViewNodeName, {
4314
4222
  class: normalizeClass(_ctx.$style.name),
4315
4223
  "latest-name": _ctx.latestInfo?.name ?? props.data.node.name,
4316
4224
  name: props.data.node.name,
@@ -4397,12 +4305,15 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4397
4305
  type: "secondary",
4398
4306
  size: "medium",
4399
4307
  icon: "edit",
4400
- style: { "color": "var(--color-text-base)" },
4308
+ style: normalizeStyle([{ "color": "var(--color-text-base)" }, {
4309
+ visibility: props.canOpenNdv ? "" : "hidden",
4310
+ color: "var(--color-text-base)"
4311
+ }]),
4401
4312
  disabled: props.latestInfo?.deleted,
4402
4313
  class: normalizeClass(_ctx.$style.openNdvButton),
4403
4314
  "aria-label": unref(locale).baseText("logs.overview.body.open"),
4404
- onClick: _cache[0] || (_cache[0] = withModifiers(($event) => emit("openNdv", props.data), ["stop"]))
4405
- }, null, 8, ["disabled", "class", "aria-label"])) : createCommentVNode("", true),
4315
+ onClick: _cache[0] || (_cache[0] = withModifiers(($event) => emit("openNdv"), ["stop"]))
4316
+ }, null, 8, ["style", "disabled", "class", "aria-label"])) : createCommentVNode("", true),
4406
4317
  !_ctx.isCompact || !props.isReadOnly && !props.latestInfo?.deleted && !props.latestInfo?.disabled ? (openBlock(), createBlock(unref(_sfc_main$i), {
4407
4318
  key: 5,
4408
4319
  type: "secondary",
@@ -4412,21 +4323,21 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4412
4323
  "aria-label": unref(locale).baseText("logs.overview.body.run"),
4413
4324
  class: normalizeClass([_ctx.$style.partialExecutionButton, props.data.depth > 0 ? _ctx.$style.unavailable : ""]),
4414
4325
  disabled: props.latestInfo?.deleted || props.latestInfo?.disabled,
4415
- onClick: _cache[1] || (_cache[1] = withModifiers(($event) => emit("triggerPartialExecution", props.data), ["stop"]))
4326
+ onClick: _cache[1] || (_cache[1] = withModifiers(($event) => emit("triggerPartialExecution"), ["stop"]))
4416
4327
  }, null, 8, ["aria-label", "class", "disabled"])) : createCommentVNode("", true),
4417
- !_ctx.isCompact || props.data.children.length > 0 ? (openBlock(), createBlock(unref(N8nButton), {
4328
+ !_ctx.isCompact || hasChildren.value ? (openBlock(), createBlock(unref(N8nButton), {
4418
4329
  key: 6,
4419
4330
  type: "secondary",
4420
4331
  size: "small",
4421
4332
  square: true,
4422
4333
  style: normalizeStyle({
4423
- visibility: props.data.children.length === 0 ? "hidden" : "",
4334
+ visibility: hasChildren.value ? "" : "hidden",
4424
4335
  color: "var(--color-text-base)"
4425
4336
  // give higher specificity than the style from the component itself
4426
4337
  }),
4427
4338
  class: normalizeClass(_ctx.$style.toggleButton),
4428
4339
  "aria-label": unref(locale).baseText("logs.overview.body.toggleRow"),
4429
- onClick: _cache[2] || (_cache[2] = withModifiers(($event) => emit("toggleExpanded", props.data), ["stop"]))
4340
+ onClick: _cache[2] || (_cache[2] = withModifiers(($event) => emit("toggleExpanded"), ["stop"]))
4430
4341
  }, {
4431
4342
  default: withCtx(() => [
4432
4343
  createVNode(unref(N8nIcon), {
@@ -4485,7 +4396,7 @@ const cssModules$6 = {
4485
4396
  };
4486
4397
  const LogsOverviewRow = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__cssModules", cssModules$6]]);
4487
4398
  const _sfc_main$5 = /* @__PURE__ */ defineComponent({
4488
- __name: "ExecutionSummary",
4399
+ __name: "LogsViewExecutionSummary",
4489
4400
  props: {
4490
4401
  status: {},
4491
4402
  consumedTokens: {},
@@ -4527,7 +4438,7 @@ const style0$5 = {
4527
4438
  const cssModules$5 = {
4528
4439
  "$style": style0$5
4529
4440
  };
4530
- const ExecutionSummary = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__cssModules", cssModules$5]]);
4441
+ const LogsViewExecutionSummary = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__cssModules", cssModules$5]]);
4531
4442
  const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4532
4443
  __name: "LogsOverviewPanel",
4533
4444
  props: {
@@ -4536,62 +4447,49 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4536
4447
  isReadOnly: { type: Boolean },
4537
4448
  isCompact: { type: Boolean },
4538
4449
  execution: {},
4539
- latestNodeInfo: {},
4540
- scrollToSelection: { type: Boolean }
4450
+ entries: {},
4451
+ flatLogEntries: {},
4452
+ latestNodeInfo: {}
4541
4453
  },
4542
- emits: ["clickHeader", "select", "clearExecutionData"],
4454
+ emits: ["clickHeader", "select", "clearExecutionData", "openNdv", "toggleExpanded", "loadSubExecution"],
4543
4455
  setup(__props, { emit: __emit }) {
4544
4456
  const emit = __emit;
4545
4457
  const locale = useI18n$1();
4546
- const telemetry = useTelemetry();
4547
4458
  const router = useRouter();
4548
4459
  const runWorkflow = useRunWorkflow({ router });
4549
- const ndvStore = useNDVStore();
4550
4460
  const isClearExecutionButtonVisible = useClearExecutionButtonVisible();
4551
- const isEmpty2 = computed(() => __props.execution === void 0);
4461
+ const isEmpty = computed(() => __props.flatLogEntries.length === 0 || __props.execution === void 0);
4552
4462
  const switchViewOptions = computed(() => [
4553
4463
  { label: locale.baseText("logs.overview.header.switch.overview"), value: "overview" },
4554
4464
  { label: locale.baseText("logs.overview.header.switch.details"), value: "details" }
4555
4465
  ]);
4556
4466
  const consumedTokens2 = computed(
4557
- () => getTotalConsumedTokens(...(__props.execution?.tree ?? []).map(getSubtreeTotalConsumedTokens))
4467
+ () => getTotalConsumedTokens(
4468
+ ...__props.entries.map(
4469
+ (entry) => getSubtreeTotalConsumedTokens(
4470
+ entry,
4471
+ false
4472
+ // Exclude token usages from sub workflow which is loaded only after expanding the row
4473
+ )
4474
+ )
4475
+ )
4558
4476
  );
4559
- const collapsedEntries = ref({});
4560
- const flatLogEntries = computed(
4561
- () => flattenLogEntries(__props.execution?.tree ?? [], collapsedEntries.value)
4477
+ const shouldShowTokenCountColumn = computed(
4478
+ () => consumedTokens2.value.totalTokens > 0 || __props.entries.some((entry) => getSubtreeTotalConsumedTokens(entry, true).totalTokens > 0)
4479
+ );
4480
+ const virtualList = useVirtualList(
4481
+ toRef(() => __props.flatLogEntries),
4482
+ { itemHeight: 32 }
4562
4483
  );
4563
- const virtualList = useVirtualList(flatLogEntries, { itemHeight: 32 });
4564
- function handleClickNode(clicked) {
4565
- if (__props.selected?.node === clicked.node && __props.selected?.runIndex === clicked.runIndex) {
4566
- emit("select", void 0);
4567
- return;
4568
- }
4569
- emit("select", clicked);
4570
- telemetry.track("User selected node in log view", {
4571
- node_type: clicked.node.type,
4572
- node_id: clicked.node.id,
4573
- execution_id: __props.execution?.id,
4574
- workflow_id: __props.execution?.workflowData.id
4575
- });
4576
- }
4577
4484
  function handleSwitchView(value) {
4578
- emit(
4579
- "select",
4580
- value === "overview" || (__props.execution?.tree ?? []).length === 0 ? void 0 : __props.execution?.tree[0]
4581
- );
4485
+ emit("select", value === "overview" ? void 0 : __props.flatLogEntries[0]);
4582
4486
  }
4583
4487
  function handleToggleExpanded(treeNode) {
4584
- collapsedEntries.value[treeNode.id] = !collapsedEntries.value[treeNode.id];
4585
- }
4586
- async function handleOpenNdv(treeNode) {
4587
- ndvStore.setActiveNodeName(treeNode.node.name);
4588
- await nextTick(() => {
4589
- const source = treeNode.runData.source[0];
4590
- const inputBranch = source?.previousNodeOutput ?? 0;
4591
- ndvEventBus.emit("updateInputNodeName", source?.previousNode);
4592
- ndvEventBus.emit("setInputBranchIndex", inputBranch);
4593
- ndvStore.setOutputRunIndex(treeNode.runIndex);
4594
- });
4488
+ if (hasSubExecution(treeNode) && treeNode.children.length === 0) {
4489
+ emit("loadSubExecution", treeNode);
4490
+ return;
4491
+ }
4492
+ emit("toggleExpanded", treeNode);
4595
4493
  }
4596
4494
  async function handleTriggerPartialExecution(treeNode) {
4597
4495
  const latestName = __props.latestNodeInfo[treeNode.node.id]?.name ?? treeNode.node.name;
@@ -4600,10 +4498,10 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4600
4498
  }
4601
4499
  }
4602
4500
  watch(
4603
- () => __props.scrollToSelection ? __props.selected : void 0,
4604
- async (entry) => {
4605
- if (entry) {
4606
- const index = flatLogEntries.value.findIndex((e) => e.id === entry.id);
4501
+ () => __props.selected,
4502
+ async (selection) => {
4503
+ if (selection && virtualList.list.value.every((e) => e.data.id !== selection.id)) {
4504
+ const index = __props.flatLogEntries.findIndex((e) => e.id === selection?.id);
4607
4505
  if (index >= 0) {
4608
4506
  await nextTick(() => virtualList.scrollTo(index));
4609
4507
  }
@@ -4616,7 +4514,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4616
4514
  class: normalizeClass(_ctx.$style.container),
4617
4515
  "data-test-id": "logs-overview"
4618
4516
  }, [
4619
- createVNode(PanelHeader, {
4517
+ createVNode(LogsPanelHeader, {
4620
4518
  title: unref(locale).baseText("logs.overview.header.title"),
4621
4519
  "data-test-id": "logs-overview-header",
4622
4520
  onClick: _cache[1] || (_cache[1] = ($event) => emit("clickHeader"))
@@ -4632,6 +4530,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4632
4530
  type: "secondary",
4633
4531
  icon: "trash",
4634
4532
  "icon-size": "medium",
4533
+ "data-test-id": "clear-execution-data-button",
4635
4534
  class: normalizeClass(_ctx.$style.clearButton),
4636
4535
  onClick: _cache[0] || (_cache[0] = withModifiers(($event) => emit("clearExecutionData"), ["stop"]))
4637
4536
  }, {
@@ -4649,10 +4548,10 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4649
4548
  }, 8, ["title"]),
4650
4549
  _ctx.isOpen ? (openBlock(), createElementBlock("div", {
4651
4550
  key: 0,
4652
- class: normalizeClass([_ctx.$style.content, isEmpty2.value ? _ctx.$style.empty : ""]),
4551
+ class: normalizeClass([_ctx.$style.content, isEmpty.value ? _ctx.$style.empty : ""]),
4653
4552
  "data-test-id": "logs-overview-body"
4654
4553
  }, [
4655
- isEmpty2.value ? (openBlock(), createBlock(unref(N8nText), {
4554
+ isEmpty.value || _ctx.execution === void 0 ? (openBlock(), createBlock(unref(N8nText), {
4656
4555
  key: 0,
4657
4556
  tag: "p",
4658
4557
  size: "medium",
@@ -4665,14 +4564,13 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4665
4564
  ]),
4666
4565
  _: 1
4667
4566
  }, 8, ["class"])) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
4668
- _ctx.execution ? (openBlock(), createBlock(ExecutionSummary, {
4669
- key: 0,
4567
+ createVNode(LogsViewExecutionSummary, {
4670
4568
  "data-test-id": "logs-overview-status",
4671
4569
  class: normalizeClass(_ctx.$style.summary),
4672
4570
  status: _ctx.execution.status,
4673
4571
  "consumed-tokens": consumedTokens2.value,
4674
4572
  "time-took": _ctx.execution.startedAt && _ctx.execution.stoppedAt ? +new Date(_ctx.execution.stoppedAt) - +new Date(_ctx.execution.startedAt) : void 0
4675
- }, null, 8, ["class", "status", "consumed-tokens", "time-took"])) : createCommentVNode("", true),
4573
+ }, null, 8, ["class", "status", "consumed-tokens", "time-took"]),
4676
4574
  createBaseVNode("div", mergeProps({
4677
4575
  class: _ctx.$style.tree
4678
4576
  }, unref(virtualList).containerProps), [
@@ -4682,16 +4580,17 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4682
4580
  key: index,
4683
4581
  data,
4684
4582
  "is-read-only": _ctx.isReadOnly,
4685
- "is-selected": data.node.name === _ctx.selected?.node.name && data.runIndex === _ctx.selected?.runIndex,
4583
+ "is-selected": data.id === _ctx.selected?.id,
4686
4584
  "is-compact": _ctx.isCompact,
4687
- "should-show-consumed-tokens": consumedTokens2.value.totalTokens > 0,
4585
+ "should-show-token-count-column": shouldShowTokenCountColumn.value,
4688
4586
  "latest-info": _ctx.latestNodeInfo[data.node.id],
4689
- expanded: !collapsedEntries.value[data.id],
4690
- onClick: withModifiers(($event) => handleClickNode(data), ["stop"]),
4691
- onToggleExpanded: handleToggleExpanded,
4692
- onOpenNdv: handleOpenNdv,
4693
- onTriggerPartialExecution: handleTriggerPartialExecution
4694
- }, null, 8, ["data", "is-read-only", "is-selected", "is-compact", "should-show-consumed-tokens", "latest-info", "expanded", "onClick"]);
4587
+ expanded: unref(virtualList).list.value[index + 1]?.data.parent?.id === data.id,
4588
+ "can-open-ndv": data.executionId === _ctx.execution?.id,
4589
+ onToggleExpanded: ($event) => handleToggleExpanded(data),
4590
+ onOpenNdv: ($event) => emit("openNdv", data),
4591
+ onTriggerPartialExecution: ($event) => handleTriggerPartialExecution(data),
4592
+ onToggleSelected: ($event) => emit("select", _ctx.selected?.id === data.id ? void 0 : data)
4593
+ }, 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"]);
4695
4594
  }), 128))
4696
4595
  ], 16)
4697
4596
  ], 16),
@@ -4731,13 +4630,11 @@ const cssModules$4 = {
4731
4630
  };
4732
4631
  const LogsOverviewPanel = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__cssModules", cssModules$4]]);
4733
4632
  const _sfc_main$3 = /* @__PURE__ */ defineComponent({
4734
- __name: "RunDataView",
4633
+ __name: "LogsViewRunData",
4735
4634
  props: {
4736
4635
  title: {},
4737
4636
  paneType: {},
4738
- logEntry: {},
4739
- workflow: {},
4740
- execution: {}
4637
+ logEntry: {}
4741
4638
  },
4742
4639
  setup(__props) {
4743
4640
  const locale = useI18n$1();
@@ -4749,7 +4646,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
4749
4646
  return { node: __props.logEntry.node, runIndex: __props.logEntry.runIndex };
4750
4647
  }
4751
4648
  const source = __props.logEntry.runData.source[0];
4752
- const node = source && __props.workflow.getNode(source.previousNode);
4649
+ const node = source && __props.logEntry.workflow.getNode(source.previousNode);
4753
4650
  if (!source || !node) {
4754
4651
  return void 0;
4755
4652
  }
@@ -4771,8 +4668,8 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
4771
4668
  }
4772
4669
  return (_ctx, _cache) => {
4773
4670
  return runDataProps.value ? (openBlock(), createBlock(RunData, mergeProps({ key: 0 }, runDataProps.value, {
4774
- workflow: _ctx.workflow,
4775
- "workflow-execution": _ctx.execution,
4671
+ workflow: _ctx.logEntry.workflow,
4672
+ "workflow-execution": _ctx.logEntry.execution,
4776
4673
  "too-much-data-title": unref(locale).baseText("ndv.output.tooMuchData.title"),
4777
4674
  "no-data-in-branch-message": unref(locale).baseText("ndv.output.noOutputDataInBranch"),
4778
4675
  "executing-message": unref(locale).baseText("ndv.output.executing"),
@@ -4850,7 +4747,7 @@ const style0$3 = {
4850
4747
  const cssModules$3 = {
4851
4748
  "$style": style0$3
4852
4749
  };
4853
- const RunDataView = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__cssModules", cssModules$3]]);
4750
+ const LogsViewRunData = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__cssModules", cssModules$3]]);
4854
4751
  function useResizablePanel(localStorageKey, {
4855
4752
  container: container2,
4856
4753
  defaultSize,
@@ -4948,24 +4845,17 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
4948
4845
  props: {
4949
4846
  isOpen: { type: Boolean },
4950
4847
  logEntry: {},
4951
- workflow: {},
4952
- execution: {},
4953
4848
  window: {},
4954
- latestInfo: {}
4849
+ latestInfo: {},
4850
+ panels: {}
4955
4851
  },
4956
- emits: ["clickHeader"],
4852
+ emits: ["clickHeader", "toggleInputOpen", "toggleOutputOpen"],
4957
4853
  setup(__props, { emit: __emit }) {
4958
4854
  const emit = __emit;
4959
4855
  const locale = useI18n$1();
4960
- const telemetry = useTelemetry();
4961
4856
  const nodeTypeStore = useNodeTypesStore();
4962
- const content2 = useLocalStorage(
4963
- "N8N_LOGS_DETAIL_PANEL_CONTENT",
4964
- LOG_DETAILS_CONTENT.OUTPUT,
4965
- { writeDefaults: false }
4966
- );
4967
4857
  const type = computed(() => nodeTypeStore.getNodeType(__props.logEntry.node.type));
4968
- const consumedTokens2 = computed(() => getSubtreeTotalConsumedTokens(__props.logEntry));
4858
+ const consumedTokens2 = computed(() => getSubtreeTotalConsumedTokens(__props.logEntry, false));
4969
4859
  const isTriggerNode = computed(() => type.value?.group.includes("trigger"));
4970
4860
  const container2 = useTemplateRef("container");
4971
4861
  const resizer = useResizablePanel("N8N_LOGS_INPUT_PANEL_WIDTH", {
@@ -4976,35 +4866,13 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
4976
4866
  allowCollapse: true,
4977
4867
  allowFullSize: true
4978
4868
  });
4979
- const shouldResize = computed(() => content2.value === LOG_DETAILS_CONTENT.BOTH);
4980
- function handleToggleInput(open) {
4981
- const wasOpen = [LOG_DETAILS_CONTENT.INPUT, LOG_DETAILS_CONTENT.BOTH].includes(content2.value);
4982
- if (open === wasOpen) {
4983
- return;
4984
- }
4985
- content2.value = wasOpen ? LOG_DETAILS_CONTENT.OUTPUT : LOG_DETAILS_CONTENT.BOTH;
4986
- telemetry.track("User toggled log view sub pane", {
4987
- pane: "input",
4988
- newState: wasOpen ? "hidden" : "visible"
4989
- });
4990
- }
4991
- function handleToggleOutput(open) {
4992
- const wasOpen = [LOG_DETAILS_CONTENT.OUTPUT, LOG_DETAILS_CONTENT.BOTH].includes(content2.value);
4993
- if (open === wasOpen) {
4994
- return;
4995
- }
4996
- content2.value = wasOpen ? LOG_DETAILS_CONTENT.INPUT : LOG_DETAILS_CONTENT.BOTH;
4997
- telemetry.track("User toggled log view sub pane", {
4998
- pane: "output",
4999
- newState: wasOpen ? "hidden" : "visible"
5000
- });
5001
- }
4869
+ const shouldResize = computed(() => __props.panels === LOG_DETAILS_PANEL_STATE.BOTH);
5002
4870
  function handleResizeEnd() {
5003
4871
  if (resizer.isCollapsed.value) {
5004
- handleToggleInput(false);
4872
+ emit("toggleInputOpen", false);
5005
4873
  }
5006
4874
  if (resizer.isFullSize.value) {
5007
- handleToggleOutput(false);
4875
+ emit("toggleOutputOpen", false);
5008
4876
  }
5009
4877
  resizer.onResizeEnd();
5010
4878
  }
@@ -5015,10 +4883,10 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
5015
4883
  class: normalizeClass(_ctx.$style.container),
5016
4884
  "data-test-id": "log-details"
5017
4885
  }, [
5018
- createVNode(PanelHeader, {
4886
+ createVNode(LogsPanelHeader, {
5019
4887
  "data-test-id": "log-details-header",
5020
4888
  class: normalizeClass(_ctx.$style.header),
5021
- onClick: _cache[0] || (_cache[0] = ($event) => emit("clickHeader"))
4889
+ onClick: _cache[2] || (_cache[2] = ($event) => emit("clickHeader"))
5022
4890
  }, {
5023
4891
  title: withCtx(() => [
5024
4892
  createBaseVNode("div", {
@@ -5029,12 +4897,12 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
5029
4897
  size: 16,
5030
4898
  class: normalizeClass(_ctx.$style.icon)
5031
4899
  }, null, 8, ["node-type", "class"]),
5032
- createVNode(NodeName, {
4900
+ createVNode(LogsViewNodeName, {
5033
4901
  "latest-name": _ctx.latestInfo?.name ?? _ctx.logEntry.node.name,
5034
4902
  name: _ctx.logEntry.node.name,
5035
4903
  "is-deleted": _ctx.latestInfo?.deleted ?? false
5036
4904
  }, null, 8, ["latest-name", "name", "is-deleted"]),
5037
- _ctx.isOpen ? (openBlock(), createBlock(ExecutionSummary, {
4905
+ _ctx.isOpen ? (openBlock(), createBlock(LogsViewExecutionSummary, {
5038
4906
  key: 0,
5039
4907
  class: normalizeClass(_ctx.$style.executionSummary),
5040
4908
  status: _ctx.logEntry.runData.executionStatus ?? "unknown",
@@ -5048,28 +4916,44 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
5048
4916
  key: 0,
5049
4917
  class: normalizeClass(_ctx.$style.actions)
5050
4918
  }, [
5051
- createVNode(unref(N8nButton), {
5052
- size: "mini",
5053
- type: "secondary",
5054
- class: normalizeClass(unref(content2) === unref(LOG_DETAILS_CONTENT).OUTPUT ? "" : _ctx.$style.pressed),
5055
- onClick: withModifiers(handleToggleInput, ["stop"])
4919
+ createVNode(KeyboardShortcutTooltip, {
4920
+ label: unref(locale).baseText("generic.shortcutHint"),
4921
+ shortcut: { keys: ["i"] }
5056
4922
  }, {
5057
4923
  default: withCtx(() => [
5058
- createTextVNode(toDisplayString(unref(locale).baseText("logs.details.header.actions.input")), 1)
4924
+ createVNode(unref(N8nButton), {
4925
+ size: "mini",
4926
+ type: "secondary",
4927
+ class: normalizeClass(_ctx.panels === unref(LOG_DETAILS_PANEL_STATE).OUTPUT ? "" : _ctx.$style.pressed),
4928
+ onClick: _cache[0] || (_cache[0] = withModifiers(($event) => emit("toggleInputOpen"), ["stop"]))
4929
+ }, {
4930
+ default: withCtx(() => [
4931
+ createTextVNode(toDisplayString(unref(locale).baseText("logs.details.header.actions.input")), 1)
4932
+ ]),
4933
+ _: 1
4934
+ }, 8, ["class"])
5059
4935
  ]),
5060
4936
  _: 1
5061
- }, 8, ["class"]),
5062
- createVNode(unref(N8nButton), {
5063
- size: "mini",
5064
- type: "secondary",
5065
- class: normalizeClass(unref(content2) === unref(LOG_DETAILS_CONTENT).INPUT ? "" : _ctx.$style.pressed),
5066
- onClick: withModifiers(handleToggleOutput, ["stop"])
4937
+ }, 8, ["label"]),
4938
+ createVNode(KeyboardShortcutTooltip, {
4939
+ label: unref(locale).baseText("generic.shortcutHint"),
4940
+ shortcut: { keys: ["o"] }
5067
4941
  }, {
5068
4942
  default: withCtx(() => [
5069
- createTextVNode(toDisplayString(unref(locale).baseText("logs.details.header.actions.output")), 1)
4943
+ createVNode(unref(N8nButton), {
4944
+ size: "mini",
4945
+ type: "secondary",
4946
+ class: normalizeClass(_ctx.panels === unref(LOG_DETAILS_PANEL_STATE).INPUT ? "" : _ctx.$style.pressed),
4947
+ onClick: _cache[1] || (_cache[1] = withModifiers(($event) => emit("toggleOutputOpen"), ["stop"]))
4948
+ }, {
4949
+ default: withCtx(() => [
4950
+ createTextVNode(toDisplayString(unref(locale).baseText("logs.details.header.actions.output")), 1)
4951
+ ]),
4952
+ _: 1
4953
+ }, 8, ["class"])
5070
4954
  ]),
5071
4955
  _: 1
5072
- }, 8, ["class"])
4956
+ }, 8, ["label"])
5073
4957
  ], 2)) : createCommentVNode("", true),
5074
4958
  renderSlot(_ctx.$slots, "actions")
5075
4959
  ]),
@@ -5080,7 +4964,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
5080
4964
  class: normalizeClass(_ctx.$style.content),
5081
4965
  "data-test-id": "logs-details-body"
5082
4966
  }, [
5083
- !isTriggerNode.value && unref(content2) !== unref(LOG_DETAILS_CONTENT).OUTPUT ? (openBlock(), createBlock(unref(N8nResizeWrapper), {
4967
+ !isTriggerNode.value && _ctx.panels !== unref(LOG_DETAILS_PANEL_STATE).OUTPUT ? (openBlock(), createBlock(unref(N8nResizeWrapper), {
5084
4968
  key: 0,
5085
4969
  class: normalizeClass({
5086
4970
  [_ctx.$style.inputResizer]: true,
@@ -5096,27 +4980,23 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
5096
4980
  onResizeend: handleResizeEnd
5097
4981
  }, {
5098
4982
  default: withCtx(() => [
5099
- createVNode(RunDataView, {
4983
+ createVNode(LogsViewRunData, {
5100
4984
  "data-test-id": "log-details-input",
5101
4985
  "pane-type": "input",
5102
4986
  title: unref(locale).baseText("logs.details.header.actions.input"),
5103
- "log-entry": _ctx.logEntry,
5104
- workflow: _ctx.workflow,
5105
- execution: _ctx.execution
5106
- }, null, 8, ["title", "log-entry", "workflow", "execution"])
4987
+ "log-entry": _ctx.logEntry
4988
+ }, null, 8, ["title", "log-entry"])
5107
4989
  ]),
5108
4990
  _: 1
5109
4991
  }, 8, ["class", "width", "style", "is-resizing-enabled", "window", "onResize"])) : createCommentVNode("", true),
5110
- isTriggerNode.value || unref(content2) !== unref(LOG_DETAILS_CONTENT).INPUT ? (openBlock(), createBlock(RunDataView, {
4992
+ isTriggerNode.value || _ctx.panels !== unref(LOG_DETAILS_PANEL_STATE).INPUT ? (openBlock(), createBlock(LogsViewRunData, {
5111
4993
  key: 1,
5112
4994
  "data-test-id": "log-details-output",
5113
4995
  "pane-type": "output",
5114
4996
  class: normalizeClass(_ctx.$style.outputPanel),
5115
4997
  title: unref(locale).baseText("logs.details.header.actions.output"),
5116
- "log-entry": _ctx.logEntry,
5117
- workflow: _ctx.workflow,
5118
- execution: _ctx.execution
5119
- }, null, 8, ["class", "title", "log-entry", "workflow", "execution"])) : createCommentVNode("", true)
4998
+ "log-entry": _ctx.logEntry
4999
+ }, null, 8, ["class", "title", "log-entry"])) : createCommentVNode("", true)
5120
5000
  ], 2)) : createCommentVNode("", true)
5121
5001
  ], 2);
5122
5002
  };
@@ -5190,10 +5070,11 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
5190
5070
  ]),
5191
5071
  _: 1
5192
5072
  }, 8, ["z-index", "content"])) : createCommentVNode("", true),
5193
- _ctx.showToggleButton ? (openBlock(), createBlock(unref(N8nTooltip), {
5073
+ _ctx.showToggleButton ? (openBlock(), createBlock(KeyboardShortcutTooltip, {
5194
5074
  key: 1,
5195
- "z-index": tooltipZIndex.value,
5196
- content: toggleButtonText.value
5075
+ label: unref(locales).baseText("generic.shortcutHint"),
5076
+ shortcut: { keys: ["l"] },
5077
+ "z-index": tooltipZIndex.value
5197
5078
  }, {
5198
5079
  default: withCtx(() => [
5199
5080
  createVNode(unref(_sfc_main$i), {
@@ -5207,7 +5088,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
5207
5088
  }, null, 8, ["icon", "aria-label"])
5208
5089
  ]),
5209
5090
  _: 1
5210
- }, 8, ["z-index", "content"])) : createCommentVNode("", true)
5091
+ }, 8, ["label", "z-index"])) : createCommentVNode("", true)
5211
5092
  ], 2);
5212
5093
  };
5213
5094
  }
@@ -5220,11 +5101,9 @@ const cssModules$1 = {
5220
5101
  "$style": style0$1
5221
5102
  };
5222
5103
  const LogsPanelActions = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__cssModules", cssModules$1]]);
5223
- function useLayout(pipContainer, pipContent2, container2, logsContainer2) {
5224
- const canvasStore = useCanvasStore();
5104
+ function useLogsPanelLayout(pipContainer, pipContent2, container2, logsContainer2) {
5105
+ const logsStore = useLogsStore();
5225
5106
  const telemetry = useTelemetry();
5226
- const workflowsStore = useWorkflowsStore();
5227
- const panelState = computed(() => workflowsStore.logsPanelState);
5228
5107
  const resizer = useResizablePanel(LOCAL_STORAGE_PANEL_HEIGHT, {
5229
5108
  container: document.body,
5230
5109
  position: "bottom",
@@ -5248,7 +5127,7 @@ function useLayout(pipContainer, pipContent2, container2, logsContainer2) {
5248
5127
  allowFullSize: true
5249
5128
  });
5250
5129
  const isOpen = computed(
5251
- () => panelState.value === LOGS_PANEL_STATE.CLOSED ? resizer.isResizing.value && resizer.size.value > 0 : !resizer.isCollapsed.value
5130
+ () => logsStore.isOpen ? !resizer.isCollapsed.value : resizer.isResizing.value && resizer.size.value > 0
5252
5131
  );
5253
5132
  const isCollapsingDetailsPanel = computed(() => overviewPanelResizer.isFullSize.value);
5254
5133
  const { canPopOut, isPoppedOut, pipWindow } = usePiPWindow({
@@ -5256,32 +5135,32 @@ function useLayout(pipContainer, pipContent2, container2, logsContainer2) {
5256
5135
  initialWidth: window.document.body.offsetWidth * 0.8,
5257
5136
  container: pipContainer,
5258
5137
  content: pipContent2,
5259
- shouldPopOut: computed(() => panelState.value === LOGS_PANEL_STATE.FLOATING),
5138
+ shouldPopOut: computed(() => logsStore.state === LOGS_PANEL_STATE.FLOATING),
5260
5139
  onRequestClose: () => {
5261
5140
  if (!isOpen.value) {
5262
5141
  return;
5263
5142
  }
5264
5143
  telemetry.track("User toggled log view", { new_state: "attached" });
5265
- workflowsStore.setPreferPoppedOutLogsView(false);
5144
+ logsStore.setPreferPoppedOut(false);
5266
5145
  }
5267
5146
  });
5268
5147
  function handleToggleOpen(open) {
5269
- const wasOpen = panelState.value !== LOGS_PANEL_STATE.CLOSED;
5148
+ const wasOpen = logsStore.isOpen;
5270
5149
  if (open === wasOpen) {
5271
5150
  return;
5272
5151
  }
5273
- workflowsStore.toggleLogsPanelOpen(open);
5152
+ logsStore.toggleOpen(open);
5274
5153
  telemetry.track("User toggled log view", {
5275
5154
  new_state: wasOpen ? "collapsed" : "attached"
5276
5155
  });
5277
5156
  }
5278
5157
  function handlePopOut() {
5279
5158
  telemetry.track("User toggled log view", { new_state: "floating" });
5280
- workflowsStore.toggleLogsPanelOpen(true);
5281
- workflowsStore.setPreferPoppedOutLogsView(true);
5159
+ logsStore.toggleOpen(true);
5160
+ logsStore.setPreferPoppedOut(true);
5282
5161
  }
5283
5162
  function handleResizeEnd() {
5284
- if (panelState.value === LOGS_PANEL_STATE.CLOSED && !resizer.isCollapsed.value) {
5163
+ if (!logsStore.isOpen && !resizer.isCollapsed.value) {
5285
5164
  handleToggleOpen(true);
5286
5165
  }
5287
5166
  if (resizer.isCollapsed.value) {
@@ -5290,9 +5169,9 @@ function useLayout(pipContainer, pipContent2, container2, logsContainer2) {
5290
5169
  resizer.onResizeEnd();
5291
5170
  }
5292
5171
  watch(
5293
- [panelState, resizer.size],
5172
+ [() => logsStore.state, resizer.size],
5294
5173
  ([state, height]) => {
5295
- canvasStore.setPanelHeight(
5174
+ logsStore.setHeight(
5296
5175
  state === LOGS_PANEL_STATE.FLOATING ? 0 : state === LOGS_PANEL_STATE.ATTACHED ? height : 32
5297
5176
  );
5298
5177
  },
@@ -5318,10 +5197,13 @@ function useLayout(pipContainer, pipContent2, container2, logsContainer2) {
5318
5197
  onOverviewPanelResizeEnd: overviewPanelResizer.onResizeEnd
5319
5198
  };
5320
5199
  }
5321
- function useExecutionData() {
5200
+ function useLogsExecutionData() {
5322
5201
  const nodeHelpers = useNodeHelpers();
5323
5202
  const workflowsStore = useWorkflowsStore();
5203
+ const toast = useToast();
5324
5204
  const execData = ref();
5205
+ const subWorkflowExecData = ref({});
5206
+ const subWorkflows = ref({});
5325
5207
  const workflow = computed(
5326
5208
  () => execData.value ? new Workflow({
5327
5209
  ...execData.value?.workflowData,
@@ -5347,35 +5229,65 @@ function useExecutionData() {
5347
5229
  (nodes) => nodes.some(isChatNode)
5348
5230
  )
5349
5231
  );
5350
- const execution = computed(() => {
5351
- if (!execData.value || !workflow.value) {
5352
- return void 0;
5232
+ const entries = computed(() => {
5233
+ if (!execData.value?.data || !workflow.value) {
5234
+ return [];
5353
5235
  }
5354
- return {
5355
- ...execData.value,
5356
- tree: createLogEntries(workflow.value, execData.value.data?.resultData.runData ?? {})
5357
- };
5236
+ return createLogTree(
5237
+ workflow.value,
5238
+ execData.value,
5239
+ subWorkflows.value,
5240
+ subWorkflowExecData.value
5241
+ );
5358
5242
  });
5359
- const updateInterval = computed(() => (execution.value?.tree.length ?? 0) > 10 ? 300 : 0);
5360
- const runStatusList = computed(
5361
- () => workflowsStore.workflowExecutionData?.id === IN_PROGRESS_EXECUTION_ID ? Object.values(workflowsStore.workflowExecutionData?.data?.resultData.runData ?? {}).flatMap((tasks) => tasks.map((task) => task.executionStatus ?? "")).join("|") : ""
5362
- );
5243
+ const updateInterval = computed(() => (entries.value?.length ?? 0) > 10 ? 300 : 0);
5363
5244
  function resetExecutionData() {
5364
5245
  execData.value = void 0;
5365
5246
  workflowsStore.setWorkflowExecutionData(null);
5366
5247
  nodeHelpers.updateNodesExecutionIssues();
5367
5248
  }
5249
+ async function loadSubExecution(logEntry) {
5250
+ const executionId = logEntry.runData.metadata?.subExecution?.executionId;
5251
+ const workflowId = logEntry.runData.metadata?.subExecution?.workflowId;
5252
+ if (!execData.value?.data || !executionId || !workflowId) {
5253
+ return;
5254
+ }
5255
+ try {
5256
+ const subExecution = await workflowsStore.fetchExecutionDataById(executionId);
5257
+ const data = subExecution?.data ? parse(subExecution.data) : void 0;
5258
+ if (!data || !subExecution) {
5259
+ throw Error("Data is missing");
5260
+ }
5261
+ subWorkflowExecData.value[executionId] = data;
5262
+ subWorkflows.value[workflowId] = new Workflow({
5263
+ ...subExecution.workflowData,
5264
+ nodeTypes: workflowsStore.getNodeTypes()
5265
+ });
5266
+ } catch (e) {
5267
+ toast.showError(e, "Unable to load sub execution");
5268
+ }
5269
+ }
5368
5270
  watch(
5369
5271
  // Fields that should trigger update
5370
5272
  [
5371
5273
  () => workflowsStore.workflowExecutionData?.id,
5372
5274
  () => workflowsStore.workflowExecutionData?.workflowData.id,
5373
5275
  () => workflowsStore.workflowExecutionData?.status,
5374
- runStatusList
5276
+ () => workflowsStore.workflowExecutionResultDataLastUpdate,
5277
+ () => workflowsStore.workflowExecutionStartedData
5375
5278
  ],
5376
5279
  useThrottleFn(
5377
- () => {
5378
- execData.value = deepToRaw(workflowsStore.workflowExecutionData ?? void 0);
5280
+ ([executionId], [previousExecutionId]) => {
5281
+ execData.value = workflowsStore.workflowExecutionData === null ? void 0 : deepToRaw(
5282
+ mergeStartData(
5283
+ workflowsStore.workflowExecutionStartedData?.[1] ?? {},
5284
+ workflowsStore.workflowExecutionData
5285
+ )
5286
+ );
5287
+ if (executionId !== previousExecutionId) {
5288
+ subWorkflowExecData.value = {};
5289
+ subWorkflows.value = {};
5290
+ }
5379
5291
  },
5380
5292
  updateInterval,
5381
5293
  true,
@@ -5383,7 +5295,53 @@ function useExecutionData() {
5383
5295
  ),
5384
5296
  { immediate: true }
5385
5297
  );
5386
- return { execution, workflow, hasChat, latestNodeNameById, resetExecutionData };
5298
+ return {
5299
+ execution: computed(() => execData.value),
5300
+ entries,
5301
+ hasChat,
5302
+ latestNodeNameById,
5303
+ resetExecutionData,
5304
+ loadSubExecution
5305
+ };
5306
+ }
5307
+ function useLogsSelection(execution, tree2, flatLogEntries) {
5308
+ const telemetry = useTelemetry();
5309
+ const manualLogEntrySelection = ref({ type: "initial" });
5310
+ const selected2 = computed(() => findSelectedLogEntry(manualLogEntrySelection.value, tree2.value));
5311
+ function select(value) {
5312
+ manualLogEntrySelection.value = value === void 0 ? { type: "none" } : { type: "selected", id: value.id };
5313
+ if (value) {
5314
+ telemetry.track("User selected node in log view", {
5315
+ node_type: value.node.type,
5316
+ node_id: value.node.id,
5317
+ execution_id: execution.value?.id,
5318
+ workflow_id: execution.value?.workflowData.id,
5319
+ subworkflow_depth: getDepth(value)
5320
+ });
5321
+ }
5322
+ }
5323
+ function selectPrev() {
5324
+ const entries = flatLogEntries.value;
5325
+ const prevEntry = selected2.value ? getEntryAtRelativeIndex(entries, selected2.value.id, -1) ?? entries[0] : entries[entries.length - 1];
5326
+ select(prevEntry);
5327
+ }
5328
+ function selectNext() {
5329
+ const entries = flatLogEntries.value;
5330
+ const nextEntry = selected2.value ? getEntryAtRelativeIndex(entries, selected2.value.id, 1) ?? entries[entries.length - 1] : entries[0];
5331
+ select(nextEntry);
5332
+ }
5333
+ return { selected: selected2, select, selectPrev, selectNext };
5334
+ }
5335
+ function useLogsTreeExpand(entries) {
5336
+ const collapsedEntries = ref({});
5337
+ const flatLogEntries = computed(() => flattenLogEntries(entries.value, collapsedEntries.value));
5338
+ function toggleExpanded(treeNode) {
5339
+ collapsedEntries.value[treeNode.id] = !collapsedEntries.value[treeNode.id];
5340
+ }
5341
+ return {
5342
+ flatLogEntries,
5343
+ toggleExpanded
5344
+ };
5387
5345
  }
5388
5346
  const _sfc_main = /* @__PURE__ */ defineComponent({
5389
5347
  __name: "LogsPanel",
@@ -5396,6 +5354,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
5396
5354
  const logsContainer2 = useTemplateRef("logsContainer");
5397
5355
  const pipContainer = useTemplateRef("pipContainer");
5398
5356
  const pipContent2 = useTemplateRef("pipContent");
5357
+ const logsStore = useLogsStore();
5358
+ const ndvStore = useNDVStore();
5399
5359
  const {
5400
5360
  height,
5401
5361
  chatPanelWidth,
@@ -5414,7 +5374,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
5414
5374
  onChatPanelResizeEnd,
5415
5375
  onOverviewPanelResize,
5416
5376
  onOverviewPanelResizeEnd
5417
- } = useLayout(pipContainer, pipContent2, container2, logsContainer2);
5377
+ } = useLogsPanelLayout(pipContainer, pipContent2, container2, logsContainer2);
5418
5378
  const {
5419
5379
  currentSessionId,
5420
5380
  messages: messages2,
@@ -5423,12 +5383,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
5423
5383
  refreshSession,
5424
5384
  displayExecution
5425
5385
  } = useChatState(props.isReadOnly);
5426
- const { workflow, execution, hasChat, latestNodeNameById, resetExecutionData } = useExecutionData();
5427
- const manualLogEntrySelection = ref({ type: "initial" });
5428
- const selectedLogEntry = computed(
5429
- () => findSelectedLogEntry(manualLogEntrySelection.value, execution.value)
5386
+ const { entries, execution, hasChat, latestNodeNameById, resetExecutionData, loadSubExecution } = useLogsExecutionData();
5387
+ const { flatLogEntries, toggleExpanded } = useLogsTreeExpand(entries);
5388
+ const { selected: selected2, select, selectNext, selectPrev } = useLogsSelection(
5389
+ execution,
5390
+ entries,
5391
+ flatLogEntries
5430
5392
  );
5431
- const isLogDetailsOpen = computed(() => isOpen.value && selectedLogEntry.value !== void 0);
5393
+ const isLogDetailsOpen = computed(() => isOpen.value && selected2.value !== void 0);
5432
5394
  const isLogDetailsVisuallyOpen = computed(
5433
5395
  () => isLogDetailsOpen.value && !isCollapsingDetailsPanel.value
5434
5396
  );
@@ -5439,19 +5401,22 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
5439
5401
  onPopOut,
5440
5402
  onToggleOpen
5441
5403
  }));
5442
- function handleSelectLogEntry(selected2) {
5443
- const workflowId = execution.value?.workflowData.id;
5444
- if (!workflowId) {
5445
- return;
5446
- }
5447
- manualLogEntrySelection.value = selected2 === void 0 ? { type: "none", workflowId } : { type: "selected", workflowId, data: selected2 };
5448
- }
5449
5404
  function handleResizeOverviewPanelEnd() {
5450
5405
  if (isOverviewPanelFullWidth.value) {
5451
- handleSelectLogEntry(void 0);
5406
+ select(void 0);
5452
5407
  }
5453
5408
  onOverviewPanelResizeEnd();
5454
5409
  }
5410
+ async function handleOpenNdv(treeNode) {
5411
+ ndvStore.setActiveNodeName(treeNode.node.name);
5412
+ await nextTick(() => {
5413
+ const source = treeNode.runData.source[0];
5414
+ const inputBranch = source?.previousNodeOutput ?? 0;
5415
+ ndvEventBus.emit("updateInputNodeName", source?.previousNode);
5416
+ ndvEventBus.emit("setInputBranchIndex", inputBranch);
5417
+ ndvStore.setOutputRunIndex(treeNode.runIndex);
5418
+ });
5419
+ }
5455
5420
  return (_ctx, _cache) => {
5456
5421
  return openBlock(), createElementBlock("div", {
5457
5422
  ref_key: "pipContainer",
@@ -5475,8 +5440,33 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
5475
5440
  createBaseVNode("div", {
5476
5441
  ref_key: "container",
5477
5442
  ref: container2,
5478
- class: normalizeClass([_ctx.$style.container, "ignore-key-press-canvas"]),
5479
- tabindex: "0"
5443
+ class: normalizeClass(_ctx.$style.container),
5444
+ tabindex: "-1",
5445
+ onKeydown: [
5446
+ _cache[3] || (_cache[3] = withKeys(withModifiers(($event) => unref(select)(void 0), ["stop"]), ["esc"])),
5447
+ _cache[4] || (_cache[4] = withKeys(withModifiers(
5448
+ //@ts-ignore
5449
+ (...args) => unref(selectNext) && unref(selectNext)(...args),
5450
+ ["stop"]
5451
+ ), ["j"])),
5452
+ _cache[5] || (_cache[5] = withKeys(withModifiers(
5453
+ //@ts-ignore
5454
+ (...args) => unref(selectNext) && unref(selectNext)(...args),
5455
+ ["stop", "prevent"]
5456
+ ), ["down"])),
5457
+ _cache[6] || (_cache[6] = withKeys(withModifiers(
5458
+ //@ts-ignore
5459
+ (...args) => unref(selectPrev) && unref(selectPrev)(...args),
5460
+ ["stop"]
5461
+ ), ["k"])),
5462
+ _cache[7] || (_cache[7] = withKeys(withModifiers(
5463
+ //@ts-ignore
5464
+ (...args) => unref(selectPrev) && unref(selectPrev)(...args),
5465
+ ["stop", "prevent"]
5466
+ ), ["up"])),
5467
+ _cache[8] || (_cache[8] = withKeys(withModifiers(($event) => unref(selected2) && unref(toggleExpanded)(unref(selected2)), ["stop"]), ["space"])),
5468
+ _cache[9] || (_cache[9] = withKeys(withModifiers(($event) => unref(selected2) && handleOpenNdv(unref(selected2)), ["stop"]), ["enter"]))
5469
+ ]
5480
5470
  }, [
5481
5471
  unref(hasChat) && (!props.isReadOnly || unref(messages2).length > 0) ? (openBlock(), createBlock(unref(N8nResizeWrapper), {
5482
5472
  key: 0,
@@ -5530,40 +5520,45 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
5530
5520
  "is-open": unref(isOpen),
5531
5521
  "is-read-only": _ctx.isReadOnly,
5532
5522
  "is-compact": isLogDetailsVisuallyOpen.value,
5533
- selected: selectedLogEntry.value,
5523
+ selected: unref(selected2),
5534
5524
  execution: unref(execution),
5535
- "scroll-to-selection": manualLogEntrySelection.value.type !== "selected" || manualLogEntrySelection.value.data.id !== selectedLogEntry.value?.id,
5525
+ entries: unref(entries),
5536
5526
  "latest-node-info": unref(latestNodeNameById),
5527
+ "flat-log-entries": unref(flatLogEntries),
5537
5528
  onClickHeader: _cache[1] || (_cache[1] = ($event) => unref(onToggleOpen)(true)),
5538
- onSelect: handleSelectLogEntry,
5539
- onClearExecutionData: unref(resetExecutionData)
5529
+ onSelect: unref(select),
5530
+ onClearExecutionData: unref(resetExecutionData),
5531
+ onToggleExpanded: unref(toggleExpanded),
5532
+ onOpenNdv: handleOpenNdv,
5533
+ onLoadSubExecution: unref(loadSubExecution)
5540
5534
  }, {
5541
5535
  actions: withCtx(() => [
5542
5536
  !isLogDetailsVisuallyOpen.value ? (openBlock(), createBlock(LogsPanelActions, normalizeProps(mergeProps({ key: 0 }, logsPanelActionsProps.value)), null, 16)) : createCommentVNode("", true)
5543
5537
  ]),
5544
5538
  _: 1
5545
- }, 8, ["class", "is-open", "is-read-only", "is-compact", "selected", "execution", "scroll-to-selection", "latest-node-info", "onClearExecutionData"]))
5539
+ }, 8, ["class", "is-open", "is-read-only", "is-compact", "selected", "execution", "entries", "latest-node-info", "flat-log-entries", "onSelect", "onClearExecutionData", "onToggleExpanded", "onLoadSubExecution"]))
5546
5540
  ]),
5547
5541
  _: 1
5548
5542
  }, 8, ["class", "width", "style", "is-resizing-enabled", "window", "onResize"]),
5549
- isLogDetailsVisuallyOpen.value && selectedLogEntry.value && unref(workflow) && unref(execution) ? (openBlock(), createBlock(LogsDetailsPanel, {
5543
+ isLogDetailsVisuallyOpen.value && unref(selected2) ? (openBlock(), createBlock(LogsDetailsPanel, {
5550
5544
  key: 0,
5551
5545
  class: normalizeClass(_ctx.$style.logDetails),
5552
5546
  "is-open": unref(isOpen),
5553
- "log-entry": selectedLogEntry.value,
5554
- workflow: unref(workflow),
5555
- execution: unref(execution),
5547
+ "log-entry": unref(selected2),
5556
5548
  window: unref(pipWindow),
5557
- "latest-info": unref(latestNodeNameById)[selectedLogEntry.value.node.id],
5558
- onClickHeader: _cache[2] || (_cache[2] = ($event) => unref(onToggleOpen)(true))
5549
+ "latest-info": unref(latestNodeNameById)[unref(selected2).id],
5550
+ panels: unref(logsStore).detailsState,
5551
+ onClickHeader: _cache[2] || (_cache[2] = ($event) => unref(onToggleOpen)(true)),
5552
+ onToggleInputOpen: unref(logsStore).toggleInputOpen,
5553
+ onToggleOutputOpen: unref(logsStore).toggleOutputOpen
5559
5554
  }, {
5560
5555
  actions: withCtx(() => [
5561
5556
  isLogDetailsVisuallyOpen.value ? (openBlock(), createBlock(LogsPanelActions, normalizeProps(mergeProps({ key: 0 }, logsPanelActionsProps.value)), null, 16)) : createCommentVNode("", true)
5562
5557
  ]),
5563
5558
  _: 1
5564
- }, 8, ["class", "is-open", "log-entry", "workflow", "execution", "window", "latest-info"])) : createCommentVNode("", true)
5559
+ }, 8, ["class", "is-open", "log-entry", "window", "latest-info", "panels", "onToggleInputOpen", "onToggleOutputOpen"])) : createCommentVNode("", true)
5565
5560
  ], 2)
5566
- ], 2)
5561
+ ], 34)
5567
5562
  ]),
5568
5563
  _: 1
5569
5564
  }, 8, ["height", "is-resizing-enabled", "class", "style", "onResize", "onResizeend"])