n8n-editor-ui 1.92.0 → 1.94.0

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 (124) hide show
  1. package/dist/assets/{AnimatedSpinner-CtKKeDrz.js → AnimatedSpinner-CY5xYI5m.js} +1 -1
  2. package/dist/assets/{AnnotationTagsDropdown.ee.vue_vue_type_script_setup_true_lang-DR6h_xsK.js → AnnotationTagsDropdown.ee.vue_vue_type_script_setup_true_lang-BOrzkwPH.js} +1 -1
  3. package/dist/assets/{AuthView-mKkzBRxh.js → AuthView-BTzGYAnY.js} +2 -2
  4. package/dist/assets/{CanvasChatSwitch-Bu2VD2kp.js → CanvasChatSwitch-CwpjFCL0.js} +17 -18
  5. package/dist/assets/{ChangePasswordView-D5UI1v-J.js → ChangePasswordView-BKR2UFVI.js} +3 -3
  6. package/dist/assets/CollectionParameter-BJtiV9En.js +4 -0
  7. package/dist/assets/{CredentialsView-B78eNJO5.js → CredentialsView-DVgxfnNi.js} +26 -11
  8. package/dist/assets/{DemoFooter-DP26HpCu.js → DemoFooter-C1T3Q0NX.js} +7 -8
  9. package/dist/assets/{ErrorView-C3fvEdCg.js → ErrorView-Cf2Yb8Ea.js} +1 -1
  10. package/dist/assets/{ExecutionsTime.vue_vue_type_script_setup_true_lang-BBpwYdHY.js → ExecutionsTime.vue_vue_type_script_setup_true_lang-DUu0UMcW.js} +2 -2
  11. package/dist/assets/{ExecutionsView-BvlDZwIs.js → ExecutionsView-DjNkfnDh.js} +20 -18
  12. package/dist/assets/{FileSaver.min-BzAtcQXX.js → FileSaver.min-C1p9Eies.js} +1 -1
  13. package/dist/assets/{FixedCollectionParameter-CS5zXMAh.js → FixedCollectionParameter-DN_uJhpe.js} +1 -1
  14. package/dist/assets/{ForgotMyPasswordView-CVQ7pcIG.js → ForgotMyPasswordView-BMQBDIrq.js} +3 -3
  15. package/dist/assets/{InsightsChartAverageRuntime-Boh0SMb3.js → InsightsChartAverageRuntime-JzBkV6Rc.js} +4 -4
  16. package/dist/assets/{InsightsChartFailed-IZ-KYOU9.js → InsightsChartFailed-DMD3c7zM.js} +4 -4
  17. package/dist/assets/{InsightsChartFailureRate-2fWw3p0L.js → InsightsChartFailureRate-D_qeZo4f.js} +4 -4
  18. package/dist/assets/{InsightsChartTimeSaved-B2pLVys1.js → InsightsChartTimeSaved-Cw2T-Wvp.js} +4 -4
  19. package/dist/assets/{InsightsChartTotal-2QD4wPLR.js → InsightsChartTotal-DlF47gob.js} +4 -4
  20. package/dist/assets/{InsightsDashboard-Bx4vx9gz.css → InsightsDashboard-BSrakbzr.css} +42 -8
  21. package/dist/assets/{InsightsDashboard-CbiFbJ8w.js → InsightsDashboard-CxQ9H296.js} +40 -41
  22. package/dist/assets/{InsightsPaywall-5d-cSdiS.js → InsightsPaywall-hRkAfeHz.js} +1 -1
  23. package/dist/assets/InsightsSummary-BcXd-3nU.js +209 -0
  24. package/dist/assets/{InsightsSummary-CdlaUpAt.css → InsightsSummary-DzGQpM5h.css} +27 -24
  25. package/dist/assets/{InsightsTableWorkflows-Blv_GPUj.css → InsightsTableWorkflows-DfTZQkWL.css} +3 -4
  26. package/dist/assets/{InsightsTableWorkflows-_eTCUNCX.js → InsightsTableWorkflows-ybloXdDn.js} +5 -6
  27. package/dist/assets/{Logo-Dl2xVRIu.js → Logo-BGe7-2Vd.js} +1 -1
  28. package/dist/assets/{LogsPanel-JnYirDqa.js → LogsPanel-DtTp6kY0.js} +334 -338
  29. package/dist/assets/{MainHeader-CEPLiR-5.css → MainHeader-Y95RcfHb.css} +24 -17
  30. package/dist/assets/{MainHeader-Bk29pgmL.js → MainHeader-h2DV-VuD.js} +148 -82
  31. package/dist/assets/{MainSidebar-BM5ku_wM.js → MainSidebar-AAHHRXFA.js} +28 -11
  32. package/dist/assets/{MainSidebar-zZpP3qQ0.css → MainSidebar-D1_1YFQZ.css} +2 -2
  33. package/dist/assets/{NodeCreation-BEjdAYc_.js → NodeCreation-nHiG-Lhi.js} +9 -5
  34. package/dist/assets/{NodeCreator-D9fmPdS2.css → NodeCreator-D18StsVZ.css} +1021 -174
  35. package/dist/assets/{NodeCreator-cEUgbAI9.js → NodeCreator-weAzsmlU.js} +862 -418
  36. package/dist/assets/{NodeDetailsView-D4O9dKTA.js → NodeDetailsView-BsXbcyfb.js} +22 -15
  37. package/dist/assets/{NodeDetailsView-DsFLtbxi.css → NodeDetailsView-DpO8nTmN.css} +16 -16
  38. package/dist/assets/{NodeView-DDSOUm8E.js → NodeView-BY1O3wWl.js} +104 -50
  39. package/dist/assets/{ProjectCardBadge-BNn2hiMe.js → ProjectCardBadge-3xpk5Z4e.js} +38 -2
  40. package/dist/assets/{ProjectHeader-CaEZ2OPj.js → ProjectHeader-CpoOisjf.js} +106 -64
  41. package/dist/assets/{ProjectSettings-otA8E-yW.js → ProjectSettings-B__3XaPY.js} +14 -3
  42. package/dist/assets/{PushConnectionTracker.vue_vue_type_script_setup_true_lang-C3JbZMCk.js → PushConnectionTracker.vue_vue_type_script_setup_true_lang-DaoPdG_5.js} +1 -1
  43. package/dist/assets/{ResourcesListLayout-1d9Ic6VX.js → ResourcesListLayout-DAxou314.js} +156 -53
  44. package/dist/assets/{ResourcesListLayout-CtGME7aU.css → ResourcesListLayout-DuNjbsMn.css} +8 -8
  45. package/dist/assets/{RunData-BjlZgIyx.css → RunData-CE5FsU6k.css} +2 -2
  46. package/dist/assets/{RunData-Bx47sNQp.js → RunData-fnd-jejc.js} +257 -99
  47. package/dist/assets/{RunDataAi-DOac7nwD.js → RunDataAi-Ck3VGKP_.js} +3 -4
  48. package/dist/assets/{RunDataJson-Pev6yNEV.js → RunDataJson-B80Z4URL.js} +7 -7
  49. package/dist/assets/{RunDataJsonActions-Co4xgmVq.js → RunDataJsonActions-CdZi1Qul.js} +1 -1
  50. package/dist/assets/{RunDataParsedAiContent-D6MNLmT3.js → RunDataParsedAiContent-BczxQ63H.js} +5 -5
  51. package/dist/assets/{RunDataSearch-C8orcAlP.js → RunDataSearch-C4KmCz4c.js} +1 -1
  52. package/dist/assets/{RunDataTable-oi_l8dhA.js → RunDataTable-CsLCZIWp.js} +3 -3
  53. package/dist/assets/{SamlOnboarding-CT5J6dx0.js → SamlOnboarding-DkhjCrPa.js} +3 -3
  54. package/dist/assets/{SettingsApiView-CupjcI9v.js → SettingsApiView-Ci2-rEpm.js} +1 -1
  55. package/dist/assets/{SettingsCommunityNodesView-B5K2VLyJ.js → SettingsCommunityNodesView-_UOppuqS.js} +24 -11
  56. package/dist/assets/{SettingsExternalSecrets-BidJCf_t.js → SettingsExternalSecrets-DHIkKr53.js} +1 -1
  57. package/dist/assets/{SettingsLdapView-Cva6akhW.js → SettingsLdapView-B8ezgdqP.js} +1 -1
  58. package/dist/assets/{SettingsLogStreamingView-Cy-rAKUO.js → SettingsLogStreamingView-YP6Xy7Fe.js} +1 -1
  59. package/dist/assets/{SettingsPersonalView-ZJ1Syok2.js → SettingsPersonalView-BmbFyWPb.js} +1 -1
  60. package/dist/assets/{SettingsSourceControl-CMtqqlkO.js → SettingsSourceControl-DwaOdDke.js} +1 -1
  61. package/dist/assets/{SettingsSso-Bi3OpykL.js → SettingsSso-DOC-P2wt.js} +14 -1
  62. package/dist/assets/{SettingsUsageAndPlan-C5TbwZhP.js → SettingsUsageAndPlan-DVOLlEkG.js} +1 -1
  63. package/dist/assets/{SettingsUsersView-BHuP5k0A.js → SettingsUsersView-CN_KLeIm.js} +1 -1
  64. package/dist/assets/{SettingsView-DPIIqaKN.js → SettingsView-DiAhLyco.js} +1 -1
  65. package/dist/assets/{SetupView-C4V9j6sh.js → SetupView-OE_yCNOU.js} +3 -3
  66. package/dist/assets/{SetupWorkflowCredentialsButton-BZ9ILQUp.js → SetupWorkflowCredentialsButton-Dx1IkZgW.js} +1 -1
  67. package/dist/assets/{SetupWorkflowFromTemplateView-3uV3zSU2.js → SetupWorkflowFromTemplateView-lQXKgIuL.js} +3 -3
  68. package/dist/assets/{SigninView-DWZHdCjG.js → SigninView-BWSrzbF7.js} +3 -3
  69. package/dist/assets/{SignoutView-DbduXAir.js → SignoutView-DxGgFxt2.js} +1 -1
  70. package/dist/assets/{SignupView-DWq6VACk.js → SignupView-Dtu5bMqF.js} +3 -3
  71. package/dist/assets/{TemplateDetails-BckqE6GK.js → TemplateDetails-CQ7TYqsP.js} +1 -1
  72. package/dist/assets/{TemplateList-Bw0JeBMP.js → TemplateList-Cxmv-0p-.js} +1 -1
  73. package/dist/assets/{TemplatesCollectionView-CAKT-mpV.js → TemplatesCollectionView-xvV6FXib.js} +5 -5
  74. package/dist/assets/{TemplatesSearchView-I2a5us58.js → TemplatesSearchView-CsECyZ52.js} +3 -3
  75. package/dist/assets/{TemplatesView-6EwGFFJK.js → TemplatesView-DrEKpZTU.js} +1 -1
  76. package/dist/assets/{TemplatesWorkflowView-C8xYMhwu.js → TemplatesWorkflowView-iSAL_yol.js} +5 -5
  77. package/dist/assets/{TestDefinitionEditView-CNd3Cuzq.js → TestDefinitionEditView-C3ohfu_r.js} +6 -7
  78. package/dist/assets/{TestDefinitionListView-BwTWIaAM.js → TestDefinitionListView-Dwto0jxH.js} +1 -1
  79. package/dist/assets/{TestDefinitionNewView-BQas0_G1.js → TestDefinitionNewView-9xVUm2ZJ.js} +2 -2
  80. package/dist/assets/{TestDefinitionRootView-D971MFye.js → TestDefinitionRootView-DLurQ4xl.js} +1 -1
  81. package/dist/assets/{VariablesView-DcBBuFxh.js → VariablesView-Cg2WSt_e.js} +4 -3
  82. package/dist/assets/{WorkerView-DSgBNIeb.js → WorkerView-BG-Dl0Ej.js} +6 -6
  83. package/dist/assets/{WorkflowActivator-DAyH7N29.css → WorkflowActivator-DrMTmuTZ.css} +2 -2
  84. package/dist/assets/{WorkflowActivator-CPCbgb_n.js → WorkflowActivator-e7wvW1kJ.js} +17 -11
  85. package/dist/assets/{WorkflowExecutionsInfoAccordion-Bc6vzAZu.js → WorkflowExecutionsInfoAccordion-CijtfO0l.js} +1 -1
  86. package/dist/assets/{WorkflowExecutionsLandingPage-BPPS4V9i.js → WorkflowExecutionsLandingPage-Do4y1yOx.js} +2 -2
  87. package/dist/assets/{WorkflowExecutionsPreview-Bbb5MB8Z.js → WorkflowExecutionsPreview-Bqo_3PXl.js} +6 -6
  88. package/dist/assets/{WorkflowExecutionsView-Pz-7iHJY.js → WorkflowExecutionsView-C1gS45nc.js} +10 -10
  89. package/dist/assets/{WorkflowHistory-Czo9IuI6.js → WorkflowHistory-CypQw7rC.js} +37 -19
  90. package/dist/assets/{WorkflowOnboardingView-B8DdkfJ5.js → WorkflowOnboardingView-DoKXpaNj.js} +1 -1
  91. package/dist/assets/{WorkflowPreview-eVlO1itk.js → WorkflowPreview-Bxs5XzBX.js} +1 -1
  92. package/dist/assets/{WorkflowsView-Cr2D0vym.js → WorkflowsView-BlvgD3xI.js} +299 -157
  93. package/dist/assets/{WorkflowsView-B2_HJCJ5.css → WorkflowsView-CQvTAWQ0.css} +24 -13
  94. package/dist/assets/{chartjs.utils-Dk1WO3Mr.js → chartjs.utils-CuWcgqCr.js} +2 -2
  95. package/dist/assets/{dateFormatter-C8N5khiG.js → dateFormatter-LbucaaRt.js} +1 -1
  96. package/dist/assets/{easyAiWorkflowUtils-CLqHnasO.js → easyAiWorkflowUtils-_kvYb5hw.js} +1 -1
  97. package/dist/assets/{global-link-actions-BvoZh8u9.js → global-link-actions-DG0SjhQE.js} +1 -1
  98. package/dist/assets/{import-curl-BpxkGYMX.js → import-curl-DQ6uPzZ1.js} +1 -1
  99. package/dist/assets/{index-DCpy4nCU.css → index-BA8d2DN9.css} +311 -515
  100. package/dist/assets/{index-B6eunbxp.js → index-hdsPF3tl.js} +61611 -57550
  101. package/dist/assets/{index-Br8T1Gn6.js → index-vIybYvt3.js} +1 -1
  102. package/dist/assets/{pickBy-8Urz9lDY.js → pickBy-DmKUpB7M.js} +1 -1
  103. package/dist/assets/{polyfills-CLZ4X0Ad.js → polyfills-J2x06Gdp.js} +157 -224
  104. package/dist/assets/{templateActions-DzjysjbQ.js → templateActions-DxoxchKp.js} +1 -1
  105. package/dist/assets/{typescript.worker-BsxN2afA.js → typescript.worker-B1loTpxy.js} +1 -1
  106. package/dist/assets/{useBeforeUnload-DxrN8vOO.js → useBeforeUnload-B7JAQiE8.js} +1 -1
  107. package/dist/assets/{useCanvasMapping-cuXLM-h-.css → useCanvasMapping-CFf4cwnq.css} +6 -5
  108. package/dist/assets/{useCanvasMapping-C2BQB9QB.js → useCanvasMapping-CvcOHj5p.js} +94 -50
  109. package/dist/assets/{useClearExecutionButtonVisible-BV-jMf2m.js → useClearExecutionButtonVisible-DFNEJves.js} +1 -2
  110. package/dist/assets/{useExecutionDebugging-0pPCimcw.js → useExecutionDebugging-DsRIfE0y.js} +1 -1
  111. package/dist/assets/{useExecutionHelpers-DIvhViMz.js → useExecutionHelpers-CEOL8_vt.js} +3 -3
  112. package/dist/assets/{useImportCurlCommand-BWf4R83s.js → useImportCurlCommand-DdIN4YaF.js} +2 -2
  113. package/dist/assets/useProjectPages-OGc-GAxb.js +17 -0
  114. package/dist/assets/{usePushConnection-Pobjq0U9.js → usePushConnection-DNGIaS0A.js} +29 -127
  115. package/dist/assets/{useTestDefinitionForm-BA3IS_2B.js → useTestDefinitionForm-Bi6EgFVm.js} +1 -1
  116. package/dist/assets/{useWorkflowActivate-DFqvrpj6.js → useWorkflowActivate-CJ1hLmv2.js} +1 -1
  117. package/dist/assets/{useWorkflowSaving-BACesUoL.js → useWorkflowSaving-BuokdhTC.js} +2 -2
  118. package/dist/index.html +3 -3
  119. package/package.json +1 -1
  120. package/tsconfig.json +1 -0
  121. package/vite.config.mts +4 -0
  122. package/dist/assets/CollectionParameter-BeCTpZ-q.js +0 -4
  123. package/dist/assets/InsightsSummary-gldDQ9rg.js +0 -207
  124. package/dist/assets/useCanvasOperations-DaP5jKbH.js +0 -3183
@@ -1,3183 +0,0 @@
1
- import { es as baseSlice, et as toString, eu as createCompounder, ev as SetCache, ew as arrayIncludes, ex as cacheHas, ey as baseRest, ez as isArrayLikeObject, eA as baseFlatten, e2 as CORE_NODES_CATEGORY, eB as DEFAULT_SUBCATEGORY, bn as v4, p as useSettingsStore, eC as AI_TRANSFORM_NODE_TYPE, bs as AI_SUBCATEGORY, eD as HUMAN_IN_THE_LOOP_CATEGORY, bt as AI_CATEGORY_AGENTS, eE as sortBy, dp as i18n, eF as AI_CATEGORY_OTHER_TOOLS, eG as SEND_AND_WAIT_OPERATION, eH as noCase, eI as AI_CATEGORY_DOCUMENT_LOADERS, eJ as AI_CATEGORY_LANGUAGE_MODELS, eK as AI_CATEGORY_MEMORY, eL as AI_CATEGORY_OUTPUTPARSER, eM as AI_CATEGORY_RETRIEVERS, eN as AI_CATEGORY_TEXT_SPLITTERS, eO as AI_WORKFLOW_TOOL_LANGCHAIN_NODE_TYPE, eP as AI_CODE_TOOL_LANGCHAIN_NODE_TYPE, c as useI18n, eQ as AI_CATEGORY_TOOLS, eR as AI_CATEGORY_EMBEDDING, eS as AI_CATEGORY_VECTOR_STORES, eT as AI_UNCATEGORIZED_CATEGORY, eU as AI_OTHERS_NODE_CREATOR_VIEW, bm as NodeConnectionTypes, bz as useNodeTypesStore, aN as useTemplatesStore, eV as AI_NODE_CREATOR_VIEW, eW as RSS_READ_NODE_TYPE, eX as EMAIL_SEND_NODE_TYPE, eY as SET_NODE_TYPE, eZ as CODE_NODE_TYPE, e_ as DATETIME_NODE_TYPE, e$ as FILTER_NODE_TYPE, f0 as REMOVE_DUPLICATES_NODE_TYPE, f1 as SPLIT_OUT_NODE_TYPE, f2 as LIMIT_NODE_TYPE, f3 as SUMMARIZE_NODE_TYPE, f4 as AGGREGATE_NODE_TYPE, f5 as MERGE_NODE_TYPE, eb as HTML_NODE_TYPE, f6 as MARKDOWN_NODE_TYPE, f7 as XML_NODE_TYPE, f8 as CRYPTO_NODE_TYPE, f9 as EXTRACT_FROM_FILE_NODE_TYPE, fa as CONVERT_TO_FILE_NODE_TYPE, fb as COMPRESSION_NODE_TYPE, fc as EDIT_IMAGE_NODE_TYPE, fd as TRANSFORM_DATA_SUBCATEGORY, fe as IF_NODE_TYPE, ff as SPLIT_IN_BATCHES_NODE_TYPE, fg as FLOWS_CONTROL_SUBCATEGORY, fh as HTTP_REQUEST_NODE_TYPE, fi as WEBHOOK_NODE_TYPE, fj as HELPERS_SUBCATEGORY, fk as HITL_SUBCATEGORY, fl as TRIGGER_NODE_CREATOR_VIEW, fm as REGULAR_NODE_CREATOR_VIEW, fn as MANUAL_TRIGGER_NODE_TYPE, fo as EMAIL_IMAP_NODE_TYPE, fp as SCHEDULE_TRIGGER_NODE_TYPE, fq as FORM_TRIGGER_NODE_TYPE, dH as EXECUTE_WORKFLOW_TRIGGER_NODE_TYPE, bk as CHAT_TRIGGER_NODE_TYPE, fr as OTHER_TRIGGER_NODES_SUBCATEGORY, bu as AI_CATEGORY_CHAINS, O as defineStore, r as ref, q as computed, $ as useCanvasStore, fs as AI_CATEGORY_ROOT_NODES, ft as AI_CATEGORY_MCP_NODES, z as nextTick, fu as getThemedValue, H as useUIStore, bv as AI_CODE_NODE_TYPE, fv as AI_TRANSFORM_NODE_TYPE$1, fw as isValidCanvasConnectionMode, c7 as CanvasConnectionMode, c6 as isValidNodeConnectionType, Q as useWorkflowsStore, as as useNDVStore, aP as useExternalHooks, fx as isVueFlowConnection, bw as getNodeInputs, fy as CUSTOM_API_CALL_KEY, T as STORES, ca as NODE_CREATOR_OPEN_SOURCES, ag as useTelemetry, Z as useRootStore, bR as useCredentialsStore, bU as useHistoryStore, E as useTagsStore, at as useExecutionsStore, a1 as useProjectsStore, a as useToast, a5 as useWorkflowHelpers, bA as useNodeHelpers, bf as useClipboard, fz as MCP_TRIGGER_NODE_TYPE, fA as UPDATE_WEBHOOK_ID_NODE_TYPES, dy as generateNodesGraph, fB as getNewNodePosition, fC as AddConnectionCommand, ay as STICKY_NODE_TYPE, by as getNodeOutputs, fD as RemoveConnectionCommand, aa as EnterpriseEditionFeature, cl as deepCopy, ek as isPresent, fE as RemoveNodeCommand, fF as RenameNodeCommand, bq as usePinnedData, fG as useDataSchema, fH as MoveNodeCommand, fI as DEFAULT_NODE_SIZE, fJ as CONFIGURATION_NODE_SIZE, bx as getConnectionTypes, fK as generateOffsets, fL as CONFIGURABLE_NODE_SIZE, fM as PUSH_NODES_OFFSET, fN as AddNodeCommand, fO as NODE_SIZE, fP as GRID_SIZE, fQ as getNodeParameters } from "./index-B6eunbxp.js";
2
- function castSlice(array, start, end) {
3
- var length = array.length;
4
- end = end === void 0 ? length : end;
5
- return false ? array : baseSlice(array, start, end);
6
- }
7
- var rsAstralRange$1 = "\\ud800-\\udfff", rsComboMarksRange$1 = "\\u0300-\\u036f", reComboHalfMarksRange$1 = "\\ufe20-\\ufe2f", rsComboSymbolsRange$1 = "\\u20d0-\\u20ff", rsComboRange$1 = rsComboMarksRange$1 + reComboHalfMarksRange$1 + rsComboSymbolsRange$1, rsVarRange$1 = "\\ufe0e\\ufe0f";
8
- var rsZWJ$1 = "\\u200d";
9
- var reHasUnicode = RegExp("[" + rsZWJ$1 + rsAstralRange$1 + rsComboRange$1 + rsVarRange$1 + "]");
10
- function hasUnicode(string) {
11
- return reHasUnicode.test(string);
12
- }
13
- function asciiToArray(string) {
14
- return string.split("");
15
- }
16
- var rsAstralRange = "\\ud800-\\udfff", rsComboMarksRange = "\\u0300-\\u036f", reComboHalfMarksRange = "\\ufe20-\\ufe2f", rsComboSymbolsRange = "\\u20d0-\\u20ff", rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, rsVarRange = "\\ufe0e\\ufe0f";
17
- var rsAstral = "[" + rsAstralRange + "]", rsCombo = "[" + rsComboRange + "]", rsFitz = "\\ud83c[\\udffb-\\udfff]", rsModifier = "(?:" + rsCombo + "|" + rsFitz + ")", rsNonAstral = "[^" + rsAstralRange + "]", rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}", rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]", rsZWJ = "\\u200d";
18
- var reOptMod = rsModifier + "?", rsOptVar = "[" + rsVarRange + "]?", rsOptJoin = "(?:" + rsZWJ + "(?:" + [rsNonAstral, rsRegional, rsSurrPair].join("|") + ")" + rsOptVar + reOptMod + ")*", rsSeq = rsOptVar + reOptMod + rsOptJoin, rsSymbol = "(?:" + [rsNonAstral + rsCombo + "?", rsCombo, rsRegional, rsSurrPair, rsAstral].join("|") + ")";
19
- var reUnicode = RegExp(rsFitz + "(?=" + rsFitz + ")|" + rsSymbol + rsSeq, "g");
20
- function unicodeToArray(string) {
21
- return string.match(reUnicode) || [];
22
- }
23
- function stringToArray(string) {
24
- return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string);
25
- }
26
- function createCaseFirst(methodName) {
27
- return function(string) {
28
- string = toString(string);
29
- var strSymbols = hasUnicode(string) ? stringToArray(string) : void 0;
30
- var chr = strSymbols ? strSymbols[0] : string.charAt(0);
31
- var trailing = strSymbols ? castSlice(strSymbols, 1).join("") : string.slice(1);
32
- return chr[methodName]() + trailing;
33
- };
34
- }
35
- var upperFirst = createCaseFirst("toUpperCase");
36
- function capitalize(string) {
37
- return upperFirst(toString(string).toLowerCase());
38
- }
39
- var camelCase = createCompounder(function(result, word, index) {
40
- word = word.toLowerCase();
41
- return result + (index ? capitalize(word) : word);
42
- });
43
- var LARGE_ARRAY_SIZE = 200;
44
- function baseDifference(array, values, iteratee, comparator) {
45
- var index = -1, includes = arrayIncludes, isCommon = true, length = array.length, result = [], valuesLength = values.length;
46
- if (!length) {
47
- return result;
48
- }
49
- if (values.length >= LARGE_ARRAY_SIZE) {
50
- includes = cacheHas;
51
- isCommon = false;
52
- values = new SetCache(values);
53
- }
54
- outer:
55
- while (++index < length) {
56
- var value = array[index], computed2 = value;
57
- value = value !== 0 ? value : 0;
58
- if (isCommon && computed2 === computed2) {
59
- var valuesIndex = valuesLength;
60
- while (valuesIndex--) {
61
- if (values[valuesIndex] === computed2) {
62
- continue outer;
63
- }
64
- }
65
- result.push(value);
66
- } else if (!includes(values, computed2, comparator)) {
67
- result.push(value);
68
- }
69
- }
70
- return result;
71
- }
72
- var difference = baseRest(function(array, values) {
73
- return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) : [];
74
- });
75
- const SEQUENTIAL_BONUS = 60;
76
- const SEPARATOR_BONUS = 30;
77
- const CAMEL_BONUS = 30;
78
- const FIRST_LETTER_BONUS = 15;
79
- const LEADING_LETTER_PENALTY = -20;
80
- const MAX_LEADING_LETTER_PENALTY = -200;
81
- const UNMATCHED_LETTER_PENALTY = -5;
82
- const DEFAULT_KEYS = [
83
- { key: "properties.displayName", weight: 1.3 },
84
- { key: "properties.codex.alias", weight: 1 }
85
- ];
86
- function fuzzyMatchSimple(pattern, target) {
87
- let patternIdx = 0;
88
- let strIdx = 0;
89
- while (patternIdx < pattern.length && strIdx < target.length) {
90
- const patternChar = pattern.charAt(patternIdx).toLowerCase();
91
- const targetChar = target.charAt(strIdx).toLowerCase();
92
- if (patternChar === targetChar) {
93
- patternIdx++;
94
- }
95
- ++strIdx;
96
- }
97
- return pattern.length !== 0 && target.length !== 0 && patternIdx === pattern.length;
98
- }
99
- function fuzzyMatchRecursive(pattern, target, patternCurIndex, targetCurrIndex, targetMatches, matches, maxMatches, nextMatch, recursionCount, recursionLimit) {
100
- let outScore = 0;
101
- if (++recursionCount >= recursionLimit) {
102
- return { matched: false, outScore };
103
- }
104
- if (patternCurIndex === pattern.length || targetCurrIndex === target.length) {
105
- return { matched: false, outScore };
106
- }
107
- let recursiveMatch = false;
108
- let bestRecursiveMatches = [];
109
- let bestRecursiveScore = 0;
110
- let firstMatch = true;
111
- while (patternCurIndex < pattern.length && targetCurrIndex < target.length) {
112
- if (pattern[patternCurIndex].toLowerCase() === target[targetCurrIndex].toLowerCase()) {
113
- if (nextMatch >= maxMatches) {
114
- return { matched: false, outScore };
115
- }
116
- if (firstMatch && targetMatches) {
117
- matches = [...targetMatches];
118
- firstMatch = false;
119
- }
120
- const recursiveMatches = [];
121
- const recursiveResult = fuzzyMatchRecursive(
122
- pattern,
123
- target,
124
- patternCurIndex,
125
- targetCurrIndex + 1,
126
- matches,
127
- recursiveMatches,
128
- maxMatches,
129
- nextMatch,
130
- recursionCount,
131
- recursionLimit
132
- );
133
- const recursiveScore = recursiveResult.outScore;
134
- if (recursiveResult.matched) {
135
- if (!recursiveMatch || recursiveScore > bestRecursiveScore) {
136
- bestRecursiveMatches = [...recursiveMatches];
137
- bestRecursiveScore = recursiveScore;
138
- }
139
- recursiveMatch = true;
140
- }
141
- matches[nextMatch++] = targetCurrIndex;
142
- ++patternCurIndex;
143
- }
144
- ++targetCurrIndex;
145
- }
146
- const matched = patternCurIndex === pattern.length;
147
- if (matched) {
148
- outScore = 100;
149
- if (!target.toLowerCase().startsWith("n8n")) {
150
- let penalty = LEADING_LETTER_PENALTY * matches[0];
151
- penalty = penalty < MAX_LEADING_LETTER_PENALTY ? MAX_LEADING_LETTER_PENALTY : penalty;
152
- outScore += penalty;
153
- }
154
- const unmatched = target.length - nextMatch;
155
- outScore += UNMATCHED_LETTER_PENALTY * unmatched;
156
- for (let i = 0; i < nextMatch; i++) {
157
- const currIdx = matches[i];
158
- if (i > 0) {
159
- const prevIdx = matches[i - 1];
160
- if (currIdx === prevIdx + 1) {
161
- outScore += SEQUENTIAL_BONUS;
162
- }
163
- }
164
- if (currIdx > 0) {
165
- const neighbor = target[currIdx - 1];
166
- const curr = target[currIdx];
167
- if (neighbor !== neighbor.toUpperCase() && curr !== curr.toLowerCase()) {
168
- outScore += CAMEL_BONUS;
169
- }
170
- const isNeighbourSeparator = neighbor === "_" || neighbor === " ";
171
- if (isNeighbourSeparator) {
172
- outScore += SEPARATOR_BONUS;
173
- }
174
- } else {
175
- outScore += FIRST_LETTER_BONUS;
176
- }
177
- }
178
- if (recursiveMatch && (!matched || bestRecursiveScore > outScore)) {
179
- matches = [...bestRecursiveMatches];
180
- outScore = bestRecursiveScore;
181
- return { matched: true, outScore };
182
- } else if (matched) {
183
- return { matched: true, outScore };
184
- } else {
185
- return { matched: false, outScore };
186
- }
187
- }
188
- return { matched: false, outScore };
189
- }
190
- function fuzzyMatch(pattern, target) {
191
- const recursionCount = 0;
192
- const recursionLimit = 5;
193
- const matches = [];
194
- const maxMatches = 256;
195
- return fuzzyMatchRecursive(
196
- pattern,
197
- target,
198
- 0,
199
- 0,
200
- null,
201
- matches,
202
- maxMatches,
203
- 0,
204
- recursionCount,
205
- recursionLimit
206
- );
207
- }
208
- function getValue(obj, prop) {
209
- if (obj.hasOwnProperty(prop)) {
210
- return obj[prop];
211
- }
212
- const segments = prop.split(".");
213
- let result = obj;
214
- let i = 0;
215
- while (result && i < segments.length) {
216
- const key = segments[i];
217
- result = result[key];
218
- i++;
219
- }
220
- return result;
221
- }
222
- function sublimeSearch(filter, data, keys = DEFAULT_KEYS) {
223
- const results = data.reduce((accu, item) => {
224
- let values = [];
225
- keys.forEach(({ key, weight }) => {
226
- const value = getValue(item, key);
227
- if (Array.isArray(value)) {
228
- values = values.concat(value.map((v) => ({ value: v, weight })));
229
- } else if (typeof value === "string") {
230
- values.push({
231
- value,
232
- weight
233
- });
234
- }
235
- });
236
- const itemMatch = values.reduce(
237
- (result, { value, weight }) => {
238
- if (!fuzzyMatchSimple(filter, value)) {
239
- return result;
240
- }
241
- const match = fuzzyMatch(filter, value);
242
- match.outScore *= weight;
243
- const { matched, outScore } = match;
244
- if (!result && matched) {
245
- return match;
246
- }
247
- if (matched && result && outScore > result.outScore) {
248
- return match;
249
- }
250
- return result;
251
- },
252
- null
253
- );
254
- if (itemMatch) {
255
- accu.push({
256
- score: itemMatch.outScore,
257
- item
258
- });
259
- }
260
- return accu;
261
- }, []);
262
- results.sort((a, b) => {
263
- return b.score - a.score;
264
- });
265
- return results;
266
- }
267
- function transformNodeType(node, subcategory, type = "node") {
268
- const createElement = {
269
- uuid: v4(),
270
- key: node.name,
271
- subcategory: subcategory ?? node.codex?.subcategories?.[CORE_NODES_CATEGORY]?.[0] ?? DEFAULT_SUBCATEGORY,
272
- properties: {
273
- ...node
274
- },
275
- type
276
- };
277
- return type === "action" ? createElement : createElement;
278
- }
279
- function subcategorizeItems(items) {
280
- const WHITE_LISTED_SUBCATEGORIES = [
281
- CORE_NODES_CATEGORY,
282
- AI_SUBCATEGORY,
283
- HUMAN_IN_THE_LOOP_CATEGORY
284
- ];
285
- return items.reduce((acc, item) => {
286
- let subcategories = [DEFAULT_SUBCATEGORY];
287
- const matchedSubcategories = WHITE_LISTED_SUBCATEGORIES.flatMap((category) => {
288
- if (item.codex?.categories?.includes(category)) {
289
- return item.codex?.subcategories?.[category] ?? [];
290
- }
291
- return [];
292
- });
293
- if (matchedSubcategories.length > 0) {
294
- subcategories = matchedSubcategories;
295
- }
296
- subcategories.forEach((subcategory) => {
297
- if (!acc[subcategory]) {
298
- acc[subcategory] = [];
299
- }
300
- acc[subcategory].push(transformNodeType(item, subcategory));
301
- });
302
- return acc;
303
- }, {});
304
- }
305
- function sortNodeCreateElements(nodes) {
306
- return nodes.sort((a, b) => {
307
- if (a.type !== "node" || b.type !== "node") return 0;
308
- const displayNameA = a.properties?.displayName?.toLowerCase() || a.key;
309
- const displayNameB = b.properties?.displayName?.toLowerCase() || b.key;
310
- return displayNameA.localeCompare(displayNameB, void 0, { sensitivity: "base" });
311
- });
312
- }
313
- function removeTrailingTrigger(searchFilter) {
314
- const parts = searchFilter.split(" ");
315
- if (parts.length > 1 && "trigger".startsWith(parts.slice(-1)[0].toLowerCase())) {
316
- return parts.slice(0, -1).filter((x) => x).join(" ").trimEnd();
317
- }
318
- return searchFilter;
319
- }
320
- function searchNodes(searchFilter, items) {
321
- const askAiEnabled = useSettingsStore().isAskAiEnabled;
322
- if (!askAiEnabled) {
323
- items = items.filter((item) => item.key !== AI_TRANSFORM_NODE_TYPE);
324
- }
325
- const trimmedFilter = removeTrailingTrigger(searchFilter).toLowerCase();
326
- const result = (sublimeSearch(trimmedFilter, items) || []).map(
327
- ({ item }) => item
328
- );
329
- return result;
330
- }
331
- function flattenCreateElements(items) {
332
- return items.map((item) => item.type === "section" ? item.children : item).flat();
333
- }
334
- function isAINode(node) {
335
- const isNode = node.type === "node";
336
- if (!isNode) return false;
337
- if (node.properties.codex?.categories?.includes(AI_SUBCATEGORY)) {
338
- const isAgentSubcategory = node.properties.codex?.subcategories?.[AI_SUBCATEGORY]?.includes(AI_CATEGORY_AGENTS);
339
- return !isAgentSubcategory;
340
- }
341
- return false;
342
- }
343
- function groupItemsInSections(items, sections, sortAlphabetically = true) {
344
- const filteredSections = sections.filter(
345
- (section) => typeof section === "object"
346
- );
347
- const itemsBySection = (items2) => items2.reduce((acc, item) => {
348
- const section = filteredSections.find((s) => s.items.includes(item.key));
349
- const key = section?.key ?? "other";
350
- if (key) {
351
- acc[key] = [...acc[key] ?? [], item];
352
- }
353
- return acc;
354
- }, {});
355
- const mapNewSections = (newSections, children) => newSections.map(
356
- (section) => ({
357
- type: "section",
358
- key: section.key,
359
- title: section.title,
360
- children: sortAlphabetically ? sortNodeCreateElements(children[section.key] ?? []) : children[section.key] ?? []
361
- })
362
- );
363
- const nonAINodes = items.filter((item) => !isAINode(item));
364
- const AINodes = items.filter((item) => isAINode(item));
365
- const nonAINodesBySection = itemsBySection(nonAINodes);
366
- const nonAINodesSections = mapNewSections(filteredSections, nonAINodesBySection);
367
- const AINodesBySection = itemsBySection(AINodes);
368
- const AINodesSections = mapNewSections(sortBy(filteredSections, ["title"]), AINodesBySection);
369
- const result = [...nonAINodesSections, ...AINodesSections].concat({
370
- type: "section",
371
- key: "other",
372
- title: i18n.baseText("nodeCreator.sectionNames.other"),
373
- children: sortNodeCreateElements(nonAINodesBySection.other ?? [])
374
- }).filter((section) => section.type !== "section" || section.children.length > 0);
375
- result.sort((a, b) => {
376
- if (a.key.toLowerCase().includes("recommended")) return -1;
377
- if (b.key.toLowerCase().includes("recommended")) return 1;
378
- if (b.key === AI_CATEGORY_OTHER_TOOLS) return -1;
379
- return 0;
380
- });
381
- if (!shouldRenderSectionSubtitle(result)) {
382
- return items;
383
- }
384
- return result;
385
- }
386
- const shouldRenderSectionSubtitle = (sections) => {
387
- if (!sections.length) return false;
388
- if (sections.length > 1) return true;
389
- if (sections[0].key === SEND_AND_WAIT_OPERATION) return true;
390
- return false;
391
- };
392
- const formatTriggerActionName = (actionPropertyName) => {
393
- let name = actionPropertyName;
394
- if (actionPropertyName.includes(".")) {
395
- name = actionPropertyName.split(".").join(" ");
396
- }
397
- return noCase(name);
398
- };
399
- function getNodeView(node) {
400
- return {
401
- key: node.name,
402
- type: "node",
403
- properties: {
404
- group: [],
405
- name: node.name,
406
- displayName: node.displayName,
407
- title: node.displayName,
408
- description: node.description,
409
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
410
- icon: node.icon,
411
- iconUrl: node.iconUrl
412
- }
413
- };
414
- }
415
- function getAiNodesBySubcategory(nodes, subcategory) {
416
- return nodes.filter(
417
- (node) => !node.hidden && node.codex?.subcategories?.[AI_SUBCATEGORY]?.includes(subcategory)
418
- ).map(getNodeView).sort((a, b) => a.properties.displayName.localeCompare(b.properties.displayName));
419
- }
420
- function AIView(_nodes) {
421
- const i18n2 = useI18n();
422
- const nodeTypesStore = useNodeTypesStore();
423
- const templatesStore = useTemplatesStore();
424
- const chainNodes = getAiNodesBySubcategory(nodeTypesStore.allLatestNodeTypes, AI_CATEGORY_CHAINS);
425
- const agentNodes = getAiNodesBySubcategory(nodeTypesStore.allLatestNodeTypes, AI_CATEGORY_AGENTS);
426
- const websiteCategoryURLParams = templatesStore.websiteTemplateRepositoryParameters;
427
- websiteCategoryURLParams.append("utm_user_role", "AdvancedAI");
428
- const websiteCategoryURL = templatesStore.constructTemplateRepositoryURL(websiteCategoryURLParams);
429
- const askAiEnabled = useSettingsStore().isAskAiEnabled;
430
- const aiTransformNode = nodeTypesStore.getNodeType(AI_TRANSFORM_NODE_TYPE);
431
- const transformNode = askAiEnabled && aiTransformNode ? [getNodeView(aiTransformNode)] : [];
432
- return {
433
- value: AI_NODE_CREATOR_VIEW,
434
- title: i18n2.baseText("nodeCreator.aiPanel.aiNodes"),
435
- subtitle: i18n2.baseText("nodeCreator.aiPanel.selectAiNode"),
436
- items: [
437
- {
438
- key: "ai_templates_root",
439
- type: "link",
440
- properties: {
441
- title: i18n2.baseText("nodeCreator.aiPanel.linkItem.title"),
442
- icon: "box-open",
443
- description: i18n2.baseText("nodeCreator.aiPanel.linkItem.description"),
444
- name: "ai_templates_root",
445
- url: websiteCategoryURL,
446
- tag: {
447
- type: "info",
448
- text: i18n2.baseText("nodeCreator.triggerHelperPanel.manualTriggerTag")
449
- }
450
- }
451
- },
452
- ...agentNodes,
453
- ...chainNodes,
454
- ...transformNode,
455
- {
456
- key: AI_OTHERS_NODE_CREATOR_VIEW,
457
- type: "view",
458
- properties: {
459
- title: i18n2.baseText("nodeCreator.aiPanel.aiOtherNodes"),
460
- icon: "robot",
461
- description: i18n2.baseText("nodeCreator.aiPanel.aiOtherNodesDescription")
462
- }
463
- }
464
- ]
465
- };
466
- }
467
- function AINodesView(_nodes) {
468
- const i18n2 = useI18n();
469
- function getAISubcategoryProperties(nodeConnectionType) {
470
- return {
471
- connectionType: nodeConnectionType,
472
- iconProps: {
473
- color: `var(--node-type-${nodeConnectionType}-color)`
474
- },
475
- panelClass: `nodes-list-panel-${nodeConnectionType}`
476
- };
477
- }
478
- function getSubcategoryInfo(subcategory) {
479
- const localeKey = `nodeCreator.subcategoryInfos.${camelCase(subcategory)}`;
480
- const info = i18n2.baseText(localeKey);
481
- if (info === localeKey) return void 0;
482
- return info;
483
- }
484
- return {
485
- value: AI_OTHERS_NODE_CREATOR_VIEW,
486
- title: i18n2.baseText("nodeCreator.aiPanel.aiOtherNodes"),
487
- subtitle: i18n2.baseText("nodeCreator.aiPanel.selectAiNode"),
488
- items: [
489
- {
490
- key: AI_CATEGORY_DOCUMENT_LOADERS,
491
- type: "subcategory",
492
- properties: {
493
- title: AI_CATEGORY_DOCUMENT_LOADERS,
494
- info: getSubcategoryInfo(AI_CATEGORY_DOCUMENT_LOADERS),
495
- icon: "file-import",
496
- ...getAISubcategoryProperties(NodeConnectionTypes.AiDocument)
497
- }
498
- },
499
- {
500
- key: AI_CATEGORY_LANGUAGE_MODELS,
501
- type: "subcategory",
502
- properties: {
503
- title: AI_CATEGORY_LANGUAGE_MODELS,
504
- info: getSubcategoryInfo(AI_CATEGORY_LANGUAGE_MODELS),
505
- icon: "language",
506
- ...getAISubcategoryProperties(NodeConnectionTypes.AiLanguageModel)
507
- }
508
- },
509
- {
510
- key: AI_CATEGORY_MEMORY,
511
- type: "subcategory",
512
- properties: {
513
- title: AI_CATEGORY_MEMORY,
514
- info: getSubcategoryInfo(AI_CATEGORY_MEMORY),
515
- icon: "brain",
516
- ...getAISubcategoryProperties(NodeConnectionTypes.AiMemory)
517
- }
518
- },
519
- {
520
- key: AI_CATEGORY_OUTPUTPARSER,
521
- type: "subcategory",
522
- properties: {
523
- title: AI_CATEGORY_OUTPUTPARSER,
524
- info: getSubcategoryInfo(AI_CATEGORY_OUTPUTPARSER),
525
- icon: "list",
526
- ...getAISubcategoryProperties(NodeConnectionTypes.AiOutputParser)
527
- }
528
- },
529
- {
530
- key: AI_CATEGORY_RETRIEVERS,
531
- type: "subcategory",
532
- properties: {
533
- title: AI_CATEGORY_RETRIEVERS,
534
- info: getSubcategoryInfo(AI_CATEGORY_RETRIEVERS),
535
- icon: "search",
536
- ...getAISubcategoryProperties(NodeConnectionTypes.AiRetriever)
537
- }
538
- },
539
- {
540
- key: AI_CATEGORY_TEXT_SPLITTERS,
541
- type: "subcategory",
542
- properties: {
543
- title: AI_CATEGORY_TEXT_SPLITTERS,
544
- info: getSubcategoryInfo(AI_CATEGORY_TEXT_SPLITTERS),
545
- icon: "grip-lines-vertical",
546
- ...getAISubcategoryProperties(NodeConnectionTypes.AiTextSplitter)
547
- }
548
- },
549
- {
550
- type: "subcategory",
551
- key: AI_CATEGORY_TOOLS,
552
- category: CORE_NODES_CATEGORY,
553
- properties: {
554
- title: AI_CATEGORY_TOOLS,
555
- info: getSubcategoryInfo(AI_CATEGORY_TOOLS),
556
- icon: "tools",
557
- ...getAISubcategoryProperties(NodeConnectionTypes.AiTool),
558
- sections: [
559
- {
560
- key: "popular",
561
- title: i18n2.baseText("nodeCreator.sectionNames.popular"),
562
- items: [AI_WORKFLOW_TOOL_LANGCHAIN_NODE_TYPE, AI_CODE_TOOL_LANGCHAIN_NODE_TYPE]
563
- }
564
- ]
565
- }
566
- },
567
- {
568
- key: AI_CATEGORY_EMBEDDING,
569
- type: "subcategory",
570
- properties: {
571
- title: AI_CATEGORY_EMBEDDING,
572
- info: getSubcategoryInfo(AI_CATEGORY_EMBEDDING),
573
- icon: "vector-square",
574
- ...getAISubcategoryProperties(NodeConnectionTypes.AiEmbedding)
575
- }
576
- },
577
- {
578
- key: AI_CATEGORY_VECTOR_STORES,
579
- type: "subcategory",
580
- properties: {
581
- title: AI_CATEGORY_VECTOR_STORES,
582
- info: getSubcategoryInfo(AI_CATEGORY_VECTOR_STORES),
583
- icon: "project-diagram",
584
- ...getAISubcategoryProperties(NodeConnectionTypes.AiVectorStore)
585
- }
586
- },
587
- {
588
- key: AI_UNCATEGORIZED_CATEGORY,
589
- type: "subcategory",
590
- properties: {
591
- title: AI_UNCATEGORIZED_CATEGORY,
592
- icon: "code"
593
- }
594
- }
595
- ]
596
- };
597
- }
598
- function TriggerView() {
599
- const i18n2 = useI18n();
600
- const view = {
601
- value: TRIGGER_NODE_CREATOR_VIEW,
602
- title: i18n2.baseText("nodeCreator.triggerHelperPanel.selectATrigger"),
603
- subtitle: i18n2.baseText("nodeCreator.triggerHelperPanel.selectATriggerDescription"),
604
- items: [
605
- {
606
- key: MANUAL_TRIGGER_NODE_TYPE,
607
- type: "node",
608
- category: [CORE_NODES_CATEGORY],
609
- properties: {
610
- group: [],
611
- name: MANUAL_TRIGGER_NODE_TYPE,
612
- displayName: i18n2.baseText("nodeCreator.triggerHelperPanel.manualTriggerDisplayName"),
613
- description: i18n2.baseText("nodeCreator.triggerHelperPanel.manualTriggerDescription"),
614
- icon: "fa:mouse-pointer"
615
- }
616
- },
617
- {
618
- key: DEFAULT_SUBCATEGORY,
619
- type: "subcategory",
620
- properties: {
621
- forceIncludeNodes: [WEBHOOK_NODE_TYPE, EMAIL_IMAP_NODE_TYPE],
622
- title: "App Trigger Nodes",
623
- icon: "satellite-dish"
624
- }
625
- },
626
- {
627
- key: SCHEDULE_TRIGGER_NODE_TYPE,
628
- type: "node",
629
- category: [CORE_NODES_CATEGORY],
630
- properties: {
631
- group: [],
632
- name: SCHEDULE_TRIGGER_NODE_TYPE,
633
- displayName: i18n2.baseText("nodeCreator.triggerHelperPanel.scheduleTriggerDisplayName"),
634
- description: i18n2.baseText("nodeCreator.triggerHelperPanel.scheduleTriggerDescription"),
635
- icon: "fa:clock"
636
- }
637
- },
638
- {
639
- key: WEBHOOK_NODE_TYPE,
640
- type: "node",
641
- category: [CORE_NODES_CATEGORY],
642
- properties: {
643
- group: [],
644
- name: WEBHOOK_NODE_TYPE,
645
- displayName: i18n2.baseText("nodeCreator.triggerHelperPanel.webhookTriggerDisplayName"),
646
- description: i18n2.baseText("nodeCreator.triggerHelperPanel.webhookTriggerDescription"),
647
- iconData: {
648
- type: "file",
649
- fileBuffer: "/static/webhook-icon.svg"
650
- }
651
- }
652
- },
653
- {
654
- key: FORM_TRIGGER_NODE_TYPE,
655
- type: "node",
656
- category: [CORE_NODES_CATEGORY],
657
- properties: {
658
- group: [],
659
- name: FORM_TRIGGER_NODE_TYPE,
660
- displayName: i18n2.baseText("nodeCreator.triggerHelperPanel.formTriggerDisplayName"),
661
- description: i18n2.baseText("nodeCreator.triggerHelperPanel.formTriggerDescription"),
662
- iconData: {
663
- type: "file",
664
- fileBuffer: "/static/form-grey.svg"
665
- }
666
- }
667
- },
668
- {
669
- key: EXECUTE_WORKFLOW_TRIGGER_NODE_TYPE,
670
- type: "node",
671
- category: [CORE_NODES_CATEGORY],
672
- properties: {
673
- group: [],
674
- name: EXECUTE_WORKFLOW_TRIGGER_NODE_TYPE,
675
- displayName: i18n2.baseText("nodeCreator.triggerHelperPanel.workflowTriggerDisplayName"),
676
- description: i18n2.baseText("nodeCreator.triggerHelperPanel.workflowTriggerDescription"),
677
- icon: "fa:sign-out-alt"
678
- }
679
- },
680
- {
681
- key: CHAT_TRIGGER_NODE_TYPE,
682
- type: "node",
683
- category: [CORE_NODES_CATEGORY],
684
- properties: {
685
- group: [],
686
- name: CHAT_TRIGGER_NODE_TYPE,
687
- displayName: i18n2.baseText("nodeCreator.triggerHelperPanel.chatTriggerDisplayName"),
688
- description: i18n2.baseText("nodeCreator.triggerHelperPanel.chatTriggerDescription"),
689
- icon: "fa:comments"
690
- }
691
- },
692
- {
693
- type: "subcategory",
694
- key: OTHER_TRIGGER_NODES_SUBCATEGORY,
695
- category: CORE_NODES_CATEGORY,
696
- properties: {
697
- title: OTHER_TRIGGER_NODES_SUBCATEGORY,
698
- icon: "folder-open"
699
- }
700
- }
701
- ]
702
- };
703
- return view;
704
- }
705
- function RegularView(nodes) {
706
- const i18n2 = useI18n();
707
- const popularItemsSubcategory = [
708
- SET_NODE_TYPE,
709
- CODE_NODE_TYPE,
710
- DATETIME_NODE_TYPE,
711
- AI_TRANSFORM_NODE_TYPE
712
- ];
713
- const getSendAndWaitNodes = (nodes2) => {
714
- return (nodes2 ?? []).filter((node) => node.codex?.categories?.includes(HUMAN_IN_THE_LOOP_CATEGORY)).map((node) => node.name);
715
- };
716
- const view = {
717
- value: REGULAR_NODE_CREATOR_VIEW,
718
- title: i18n2.baseText("nodeCreator.triggerHelperPanel.whatHappensNext"),
719
- items: [
720
- {
721
- key: DEFAULT_SUBCATEGORY,
722
- type: "subcategory",
723
- properties: {
724
- title: "App Regular Nodes",
725
- icon: "globe",
726
- forceIncludeNodes: [RSS_READ_NODE_TYPE, EMAIL_SEND_NODE_TYPE]
727
- }
728
- },
729
- {
730
- type: "subcategory",
731
- key: TRANSFORM_DATA_SUBCATEGORY,
732
- category: CORE_NODES_CATEGORY,
733
- properties: {
734
- title: TRANSFORM_DATA_SUBCATEGORY,
735
- icon: "pen",
736
- sections: [
737
- {
738
- key: "popular",
739
- title: i18n2.baseText("nodeCreator.sectionNames.popular"),
740
- items: popularItemsSubcategory
741
- },
742
- {
743
- key: "addOrRemove",
744
- title: i18n2.baseText("nodeCreator.sectionNames.transform.addOrRemove"),
745
- items: [
746
- FILTER_NODE_TYPE,
747
- REMOVE_DUPLICATES_NODE_TYPE,
748
- SPLIT_OUT_NODE_TYPE,
749
- LIMIT_NODE_TYPE
750
- ]
751
- },
752
- {
753
- key: "combine",
754
- title: i18n2.baseText("nodeCreator.sectionNames.transform.combine"),
755
- items: [SUMMARIZE_NODE_TYPE, AGGREGATE_NODE_TYPE, MERGE_NODE_TYPE]
756
- },
757
- {
758
- key: "convert",
759
- title: i18n2.baseText("nodeCreator.sectionNames.transform.convert"),
760
- items: [
761
- HTML_NODE_TYPE,
762
- MARKDOWN_NODE_TYPE,
763
- XML_NODE_TYPE,
764
- CRYPTO_NODE_TYPE,
765
- EXTRACT_FROM_FILE_NODE_TYPE,
766
- CONVERT_TO_FILE_NODE_TYPE,
767
- COMPRESSION_NODE_TYPE,
768
- EDIT_IMAGE_NODE_TYPE
769
- ]
770
- }
771
- ]
772
- }
773
- },
774
- {
775
- type: "subcategory",
776
- key: FLOWS_CONTROL_SUBCATEGORY,
777
- category: CORE_NODES_CATEGORY,
778
- properties: {
779
- title: FLOWS_CONTROL_SUBCATEGORY,
780
- icon: "code-branch",
781
- sections: [
782
- {
783
- key: "popular",
784
- title: i18n2.baseText("nodeCreator.sectionNames.popular"),
785
- items: [FILTER_NODE_TYPE, IF_NODE_TYPE, SPLIT_IN_BATCHES_NODE_TYPE, MERGE_NODE_TYPE]
786
- }
787
- ]
788
- }
789
- },
790
- {
791
- type: "subcategory",
792
- key: HELPERS_SUBCATEGORY,
793
- category: CORE_NODES_CATEGORY,
794
- properties: {
795
- title: HELPERS_SUBCATEGORY,
796
- icon: "toolbox",
797
- sections: [
798
- {
799
- key: "popular",
800
- title: i18n2.baseText("nodeCreator.sectionNames.popular"),
801
- items: [HTTP_REQUEST_NODE_TYPE, WEBHOOK_NODE_TYPE, CODE_NODE_TYPE]
802
- }
803
- ]
804
- }
805
- },
806
- // To add node to this subcategory:
807
- // - add "HITL" to the "categories" property of the node's codex
808
- // - add "HITL": ["Human in the Loop"] to the "subcategories" property of the node's codex
809
- // node has to have the "sendAndWait" operation, if a new operation needs to be included here:
810
- // - update getHumanInTheLoopActions in packages/frontend/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue
811
- {
812
- type: "subcategory",
813
- key: HITL_SUBCATEGORY,
814
- category: HUMAN_IN_THE_LOOP_CATEGORY,
815
- properties: {
816
- title: HITL_SUBCATEGORY,
817
- icon: "user-check",
818
- sections: [
819
- {
820
- key: "sendAndWait",
821
- title: i18n2.baseText("nodeCreator.sectionNames.sendAndWait"),
822
- items: getSendAndWaitNodes(nodes)
823
- }
824
- ]
825
- }
826
- }
827
- ]
828
- };
829
- const hasAINodes = (nodes ?? []).some((node) => node.codex?.categories?.includes(AI_SUBCATEGORY));
830
- if (hasAINodes)
831
- view.items.unshift({
832
- key: AI_NODE_CREATOR_VIEW,
833
- type: "view",
834
- properties: {
835
- title: i18n2.baseText("nodeCreator.aiPanel.langchainAiNodes"),
836
- icon: "robot",
837
- description: i18n2.baseText("nodeCreator.aiPanel.nodesForAi"),
838
- borderless: true
839
- }
840
- });
841
- view.items.push({
842
- key: TRIGGER_NODE_CREATOR_VIEW,
843
- type: "view",
844
- properties: {
845
- title: i18n2.baseText("nodeCreator.triggerHelperPanel.addAnotherTrigger"),
846
- icon: "bolt",
847
- description: i18n2.baseText("nodeCreator.triggerHelperPanel.addAnotherTriggerDescription")
848
- }
849
- });
850
- return view;
851
- }
852
- const KEYBOARD_ID_ATTR = "data-keyboard-nav-id";
853
- const WATCHED_KEYS = [
854
- "ArrowUp",
855
- "ArrowDown",
856
- "ArrowLeft",
857
- "ArrowRight",
858
- "Enter",
859
- "Escape",
860
- "Tab"
861
- ];
862
- const useKeyboardNavigation = defineStore("nodeCreatorKeyboardNavigation", () => {
863
- const selectableItems = ref([]);
864
- const activeItemId = ref(null);
865
- const keysHooks = ref({});
866
- function getItemType(element) {
867
- return element?.getAttribute("data-keyboard-nav-type");
868
- }
869
- function getElementId(element) {
870
- return element?.getAttribute(KEYBOARD_ID_ATTR) || void 0;
871
- }
872
- async function refreshSelectableItems() {
873
- return await new Promise((resolve) => {
874
- cleanupSelectableItems();
875
- setTimeout(() => {
876
- selectableItems.value = Array.from(
877
- document.querySelectorAll("[data-keyboard-nav-type]")
878
- ).map((el) => new WeakRef(el));
879
- resolve();
880
- }, 0);
881
- });
882
- }
883
- function executeKeyHooks(keyboardKey, activeItem) {
884
- const flatHooks = Object.values(keysHooks.value);
885
- const hooks = flatHooks.filter((hook) => hook.keyboardKeys.includes(keyboardKey));
886
- hooks.forEach((hook) => {
887
- if (!activeItemId.value) return;
888
- const conditionPassed = hook.condition === void 0 || hook.condition(getItemType(activeItem) || "", activeItemId.value);
889
- if (conditionPassed && activeItemId.value) {
890
- hook.handler(activeItemId.value, keyboardKey);
891
- }
892
- });
893
- }
894
- async function onKeyDown(e) {
895
- if (e.target instanceof Element && e.target.classList.contains("ignore-key-press-node-creator")) {
896
- return;
897
- }
898
- const pressedKey = e.key;
899
- if (!WATCHED_KEYS.includes(pressedKey)) return;
900
- e.preventDefault();
901
- e.stopPropagation();
902
- await refreshSelectableItems();
903
- const activeItemIndex = selectableItems.value.findIndex(
904
- (item) => getElementId(item?.deref()) === activeItemId.value
905
- );
906
- const activeItem = selectableItems.value[activeItemIndex]?.deref();
907
- const isArrowDown = pressedKey === "ArrowDown";
908
- const isArrowUp = pressedKey === "ArrowUp";
909
- if (!activeItem) return;
910
- if (isArrowDown) {
911
- const nextItemIndex = activeItemIndex < selectableItems.value.length - 1 ? activeItemIndex + 1 : 0;
912
- setActiveItem(selectableItems.value[nextItemIndex]?.deref());
913
- }
914
- if (isArrowUp) {
915
- const previousIndex = activeItemIndex > 0 ? activeItemIndex - 1 : selectableItems.value.length - 1;
916
- setActiveItem(selectableItems.value[previousIndex]?.deref());
917
- }
918
- executeKeyHooks(pressedKey, activeItem);
919
- }
920
- function setActiveItemId(id) {
921
- activeItemId.value = id;
922
- }
923
- function setActiveItem(item) {
924
- const itemId = getElementId(item);
925
- if (!itemId) return;
926
- setActiveItemId(itemId);
927
- if (item?.scrollIntoView) {
928
- item?.scrollIntoView({ block: "center" });
929
- }
930
- }
931
- async function setActiveItemIndex(index) {
932
- await refreshSelectableItems();
933
- setActiveItem(selectableItems.value[index]?.deref());
934
- }
935
- function attachKeydownEvent() {
936
- document.addEventListener("keydown", onKeyDown, { capture: true });
937
- }
938
- function detachKeydownEvent() {
939
- cleanupSelectableItems();
940
- document.removeEventListener("keydown", onKeyDown, { capture: true });
941
- }
942
- function registerKeyHook(name, hook) {
943
- hook.keyboardKeys.forEach((keyboardKey) => {
944
- if (WATCHED_KEYS.includes(keyboardKey)) {
945
- keysHooks.value = { ...keysHooks.value, [name]: hook };
946
- } else {
947
- throw new Error(`Key ${keyboardKey} is not supported`);
948
- }
949
- });
950
- }
951
- function cleanupSelectableItems() {
952
- selectableItems.value = [];
953
- }
954
- function getActiveItemIndex() {
955
- return selectableItems.value.findIndex(
956
- (item) => getElementId(item?.deref()) === activeItemId.value
957
- );
958
- }
959
- return {
960
- activeItemId,
961
- attachKeydownEvent,
962
- refreshSelectableItems,
963
- detachKeydownEvent,
964
- registerKeyHook,
965
- getActiveItemIndex,
966
- setActiveItemId,
967
- setActiveItemIndex
968
- };
969
- });
970
- const useViewStacks = defineStore("nodeCreatorViewStacks", () => {
971
- const nodeCreatorStore = useNodeCreatorStore();
972
- const { getActiveItemIndex } = useKeyboardNavigation();
973
- const i18n2 = useI18n();
974
- const settingsStore = useSettingsStore();
975
- const viewStacks = ref([]);
976
- const activeStackItems = computed(() => {
977
- const stack = getLastActiveStack();
978
- if (!stack?.baselineItems) {
979
- return stack.items ? extendItemsWithUUID(stack.items) : [];
980
- }
981
- if (stack.search && searchBaseItems.value) {
982
- let searchBase = searchBaseItems.value;
983
- const canvasHasAINodes = useCanvasStore().aiNodes.length > 0;
984
- if (searchBaseItems.value.length === 0) {
985
- searchBase = flattenCreateElements(stack.baselineItems ?? []);
986
- }
987
- if (
988
- // Filter-out AI sub-nodes if canvas has no AI nodes and the root view is not AI
989
- !(isAiRootView(stack) || canvasHasAINodes) || // or if the source is a plus endpoint or a node connection drop and the root view is not AI subcategory
990
- ["plus_endpoint", "node_connection_drop"].includes(nodeCreatorStore.openSource) && !isAiSubcategoryView(stack)
991
- ) {
992
- searchBase = filterOutAiNodes(searchBase);
993
- }
994
- const searchResults = extendItemsWithUUID(searchNodes(stack.search || "", searchBase));
995
- const groupedNodes = groupIfAiNodes(searchResults, false) ?? searchResults;
996
- stack.activeIndex = groupedNodes.some((node) => node.type === "section") ? 1 : 0;
997
- return groupedNodes;
998
- }
999
- return extendItemsWithUUID(groupIfAiNodes(stack.baselineItems, true));
1000
- });
1001
- const activeViewStack = computed(() => {
1002
- const stack = getLastActiveStack();
1003
- if (!stack) return {};
1004
- const flatBaselineItems = flattenCreateElements(stack.baselineItems ?? []);
1005
- return {
1006
- ...stack,
1007
- items: activeStackItems.value,
1008
- hasSearch: flatBaselineItems.length > 8 || stack?.hasSearch
1009
- };
1010
- });
1011
- const activeViewStackMode = computed(
1012
- () => activeViewStack.value.mode || TRIGGER_NODE_CREATOR_VIEW
1013
- );
1014
- const searchBaseItems = computed(() => {
1015
- const stack = getLastActiveStack();
1016
- if (!stack?.searchItems) return [];
1017
- return stack.searchItems.map((item) => transformNodeType(item, stack.subcategory));
1018
- });
1019
- function isAiSubcategoryView(stack) {
1020
- return stack.rootView === AI_OTHERS_NODE_CREATOR_VIEW;
1021
- }
1022
- function getLastActiveStack() {
1023
- return viewStacks.value[viewStacks.value.length - 1];
1024
- }
1025
- const globalSearchItemsDiff = computed(() => {
1026
- const stack = getLastActiveStack();
1027
- if (!stack?.search || isAiSubcategoryView(stack)) return [];
1028
- const allNodes = nodeCreatorStore.mergedNodes.map((item) => transformNodeType(item));
1029
- const filteredNodes = isAiRootView(stack) ? allNodes : filterOutAiNodes(allNodes);
1030
- let globalSearchResult = extendItemsWithUUID(
1031
- searchNodes(stack.search || "", filteredNodes)
1032
- );
1033
- if (isAiRootView(stack)) {
1034
- globalSearchResult = groupIfAiNodes(globalSearchResult);
1035
- }
1036
- const filteredItems = globalSearchResult.filter((item) => {
1037
- return !activeStackItems.value.find((activeItem) => {
1038
- if (activeItem.type === "section") {
1039
- const matchingSectionItem = activeItem.children.some(
1040
- (sectionItem) => sectionItem.key === item.key
1041
- );
1042
- return matchingSectionItem;
1043
- }
1044
- return activeItem.key === item.key;
1045
- });
1046
- });
1047
- const filteredSections = filteredItems.filter((item) => {
1048
- if (item.type === "section") {
1049
- const hasVisibleChildren = item.children.some(
1050
- (child) => activeStackItems.value.some((filteredItem) => filteredItem.key === child.key)
1051
- );
1052
- return hasVisibleChildren;
1053
- }
1054
- return true;
1055
- });
1056
- return filteredSections;
1057
- });
1058
- const itemsBySubcategory = computed(() => subcategorizeItems(nodeCreatorStore.mergedNodes));
1059
- function isAiRootView(stack) {
1060
- return stack.rootView === AI_NODE_CREATOR_VIEW;
1061
- }
1062
- function filterAiRootNodes(items) {
1063
- return items.filter((node) => {
1064
- if (node.type !== "node") return false;
1065
- const subcategories = node.properties.codex?.subcategories?.[AI_SUBCATEGORY] ?? [];
1066
- return subcategories.includes(AI_CATEGORY_ROOT_NODES) && !subcategories?.includes(AI_CATEGORY_TOOLS);
1067
- });
1068
- }
1069
- function groupIfAiNodes(items, sortAlphabetically = true) {
1070
- const aiNodes = items.filter((node) => isAINode(node));
1071
- const canvasHasAINodes = useCanvasStore().aiNodes.length > 0;
1072
- if (aiNodes.length > 0 && (canvasHasAINodes || isAiRootView(getLastActiveStack()))) {
1073
- const sectionsMap = /* @__PURE__ */ new Map();
1074
- const aiRootNodes = filterAiRootNodes(aiNodes);
1075
- const aiSubNodes = difference(aiNodes, aiRootNodes);
1076
- aiSubNodes.forEach((node) => {
1077
- const subcategories = node.properties.codex?.subcategories ?? {};
1078
- const section = subcategories[AI_SUBCATEGORY]?.[0];
1079
- if (section) {
1080
- const subSection = subcategories[section]?.[0];
1081
- const sectionKey = subSection ?? section;
1082
- const currentItems = sectionsMap.get(sectionKey)?.items ?? [];
1083
- const isSubnodesSection = !(subcategories[AI_SUBCATEGORY].includes(AI_CATEGORY_ROOT_NODES) || subcategories[AI_SUBCATEGORY].includes(AI_CATEGORY_MCP_NODES));
1084
- let title = section;
1085
- if (isSubnodesSection) {
1086
- title = `${section} (${i18n2.baseText("nodeCreator.subnodes")})`;
1087
- }
1088
- if (subSection) {
1089
- title = subSection;
1090
- }
1091
- sectionsMap.set(sectionKey, {
1092
- key: sectionKey,
1093
- title,
1094
- items: [...currentItems, node.key]
1095
- });
1096
- }
1097
- });
1098
- const nonAiNodes = difference(items, aiNodes);
1099
- const sections = Array.from(sectionsMap.values());
1100
- return [
1101
- ...nonAiNodes,
1102
- ...aiRootNodes,
1103
- ...groupItemsInSections(aiSubNodes, sections, sortAlphabetically)
1104
- ];
1105
- }
1106
- return items;
1107
- }
1108
- function filterOutAiNodes(items) {
1109
- const filteredSearchBase = items.filter((item) => {
1110
- if (item.type === "node") {
1111
- const isAICategory = item.properties.codex?.categories?.includes(AI_SUBCATEGORY) === true;
1112
- if (!isAICategory) return true;
1113
- const isRootNodeSubcategory = item.properties.codex?.subcategories?.[AI_SUBCATEGORY]?.includes(AI_CATEGORY_ROOT_NODES);
1114
- return isRootNodeSubcategory;
1115
- }
1116
- return true;
1117
- });
1118
- return filteredSearchBase;
1119
- }
1120
- async function gotoCompatibleConnectionView(connectionType, isOutput, filter) {
1121
- let nodesByConnectionType;
1122
- let relatedAIView;
1123
- if (isOutput === true) {
1124
- nodesByConnectionType = useNodeTypesStore().visibleNodeTypesByInputConnectionTypeNames;
1125
- relatedAIView = {
1126
- properties: {
1127
- title: i18n2.baseText("nodeCreator.aiPanel.aiNodes"),
1128
- icon: "robot"
1129
- }
1130
- };
1131
- } else {
1132
- nodesByConnectionType = useNodeTypesStore().visibleNodeTypesByOutputConnectionTypeNames;
1133
- relatedAIView = AINodesView().items.find(
1134
- (item) => item.properties.connectionType === connectionType
1135
- );
1136
- }
1137
- let extendedInfo = {};
1138
- if (!filter?.nodes?.length && relatedAIView?.properties.info) {
1139
- extendedInfo = { info: relatedAIView?.properties.info };
1140
- }
1141
- await nextTick();
1142
- const iconName = getThemedValue(relatedAIView?.properties.icon, useUIStore().appliedTheme);
1143
- pushViewStack(
1144
- {
1145
- title: relatedAIView?.properties.title,
1146
- ...extendedInfo,
1147
- rootView: AI_OTHERS_NODE_CREATOR_VIEW,
1148
- mode: "nodes",
1149
- items: nodeCreatorStore.allNodeCreatorNodes,
1150
- nodeIcon: iconName ? {
1151
- type: "icon",
1152
- name: iconName,
1153
- color: relatedAIView?.properties.iconProps?.color
1154
- } : void 0,
1155
- panelClass: relatedAIView?.properties.panelClass,
1156
- baseFilter: (i) => {
1157
- if (i.key === AI_CODE_NODE_TYPE) return false;
1158
- const displayNode = nodesByConnectionType[connectionType].includes(i.key);
1159
- if (displayNode && filter?.nodes?.length) {
1160
- return filter.nodes.includes(i.key);
1161
- }
1162
- return displayNode;
1163
- },
1164
- itemsMapper(item) {
1165
- return {
1166
- ...item,
1167
- subcategory: connectionType
1168
- };
1169
- },
1170
- actionsFilter: (items) => {
1171
- if (items.some((item) => item.outputConnectionType)) {
1172
- return items.filter((item) => item.outputConnectionType === connectionType);
1173
- }
1174
- return items;
1175
- },
1176
- hideActions: true,
1177
- preventBack: true
1178
- },
1179
- { resetStacks: true }
1180
- );
1181
- }
1182
- function setStackBaselineItems() {
1183
- const stack = getLastActiveStack();
1184
- if (!stack || !activeViewStack.value.uuid) return;
1185
- let stackItems = stack?.items ?? [];
1186
- if (!stack?.items) {
1187
- const subcategory = stack?.subcategory ?? DEFAULT_SUBCATEGORY;
1188
- let itemsInSubcategory = itemsBySubcategory.value[subcategory];
1189
- const isAskAiEnabled = settingsStore.isAskAiEnabled;
1190
- if (!isAskAiEnabled) {
1191
- itemsInSubcategory = itemsInSubcategory.filter(
1192
- (item) => item.key !== AI_TRANSFORM_NODE_TYPE$1
1193
- );
1194
- }
1195
- const sections = stack.sections;
1196
- if (sections) {
1197
- stackItems = groupItemsInSections(itemsInSubcategory, sections);
1198
- } else {
1199
- stackItems = itemsInSubcategory;
1200
- }
1201
- }
1202
- if ((stack.forceIncludeNodes ?? []).length > 0) {
1203
- const matchedNodes = nodeCreatorStore.mergedNodes.filter((item) => stack.forceIncludeNodes?.includes(item.name)).map((item) => transformNodeType(item, stack.subcategory));
1204
- stackItems.push(...matchedNodes);
1205
- }
1206
- if (stack.baseFilter) {
1207
- stackItems = stackItems.filter(stack.baseFilter);
1208
- }
1209
- if (stack.itemsMapper) {
1210
- stackItems = stackItems.map(stack.itemsMapper);
1211
- }
1212
- if (!stack.items) {
1213
- stackItems = sortNodeCreateElements(stackItems);
1214
- }
1215
- updateCurrentViewStack({ baselineItems: stackItems });
1216
- }
1217
- function extendItemsWithUUID(items) {
1218
- return items.map((item) => ({
1219
- ...item,
1220
- uuid: `${item.key}-${v4()}`
1221
- }));
1222
- }
1223
- function pushViewStack(stack, options = {}) {
1224
- if (options.resetStacks) {
1225
- resetViewStacks();
1226
- }
1227
- if (activeViewStack.value.uuid) {
1228
- updateCurrentViewStack({ activeIndex: getActiveItemIndex() });
1229
- }
1230
- const newStackUuid = v4();
1231
- viewStacks.value.push({
1232
- ...stack,
1233
- uuid: newStackUuid,
1234
- transitionDirection: "in",
1235
- activeIndex: 0
1236
- });
1237
- setStackBaselineItems();
1238
- }
1239
- function popViewStack() {
1240
- if (activeViewStack.value.uuid) {
1241
- viewStacks.value.pop();
1242
- updateCurrentViewStack({ transitionDirection: "out" });
1243
- }
1244
- }
1245
- function updateCurrentViewStack(stack) {
1246
- const currentStack = getLastActiveStack();
1247
- const matchedIndex = viewStacks.value.findIndex((s) => s.uuid === currentStack.uuid);
1248
- if (!currentStack) return;
1249
- Object.keys(stack).forEach((key) => {
1250
- const typedKey = key;
1251
- viewStacks.value[matchedIndex] = {
1252
- ...viewStacks.value[matchedIndex],
1253
- [key]: stack[typedKey]
1254
- };
1255
- });
1256
- }
1257
- function resetViewStacks() {
1258
- viewStacks.value = [];
1259
- }
1260
- return {
1261
- viewStacks,
1262
- activeViewStack,
1263
- activeViewStackMode,
1264
- globalSearchItemsDiff,
1265
- isAiSubcategoryView,
1266
- gotoCompatibleConnectionView,
1267
- resetViewStacks,
1268
- updateCurrentViewStack,
1269
- pushViewStack,
1270
- popViewStack
1271
- };
1272
- });
1273
- function mapLegacyConnectionsToCanvasConnections(legacyConnections, nodes) {
1274
- const mappedConnections = [];
1275
- Object.keys(legacyConnections).forEach((fromNodeName) => {
1276
- const fromId = nodes.find((node) => node.name === fromNodeName)?.id ?? "";
1277
- const fromConnectionTypes = Object.keys(
1278
- legacyConnections[fromNodeName]
1279
- );
1280
- fromConnectionTypes.forEach((fromConnectionType) => {
1281
- const fromPorts = legacyConnections[fromNodeName][fromConnectionType];
1282
- fromPorts?.forEach((toPorts, fromIndex) => {
1283
- toPorts?.forEach((toPort) => {
1284
- const toNodeName = toPort.node;
1285
- const toId = nodes.find((node) => node.name === toNodeName)?.id ?? "";
1286
- const toConnectionType = toPort.type;
1287
- const toIndex = toPort.index;
1288
- const sourceHandle = createCanvasConnectionHandleString({
1289
- mode: CanvasConnectionMode.Output,
1290
- type: fromConnectionType,
1291
- index: fromIndex
1292
- });
1293
- const targetHandle = createCanvasConnectionHandleString({
1294
- mode: CanvasConnectionMode.Input,
1295
- type: toConnectionType,
1296
- index: toIndex
1297
- });
1298
- const connectionId = createCanvasConnectionId({
1299
- source: fromId,
1300
- sourceHandle,
1301
- target: toId,
1302
- targetHandle
1303
- });
1304
- if (fromId && toId) {
1305
- mappedConnections.push({
1306
- id: connectionId,
1307
- source: fromId,
1308
- target: toId,
1309
- sourceHandle,
1310
- targetHandle,
1311
- data: {
1312
- source: {
1313
- node: fromNodeName,
1314
- index: fromIndex,
1315
- type: fromConnectionType
1316
- },
1317
- target: {
1318
- node: toNodeName,
1319
- index: toIndex,
1320
- type: toConnectionType
1321
- }
1322
- }
1323
- });
1324
- }
1325
- });
1326
- });
1327
- });
1328
- });
1329
- return mappedConnections;
1330
- }
1331
- function mapLegacyConnectionToCanvasConnection(sourceNode, targetNode, legacyConnection) {
1332
- const source = sourceNode.id;
1333
- const sourceHandle = createCanvasConnectionHandleString({
1334
- mode: CanvasConnectionMode.Output,
1335
- type: legacyConnection[0].type,
1336
- index: legacyConnection[0].index
1337
- });
1338
- const target = targetNode.id;
1339
- const targetHandle = createCanvasConnectionHandleString({
1340
- mode: CanvasConnectionMode.Input,
1341
- type: legacyConnection[1].type,
1342
- index: legacyConnection[1].index
1343
- });
1344
- return {
1345
- source,
1346
- sourceHandle,
1347
- target,
1348
- targetHandle
1349
- };
1350
- }
1351
- function parseCanvasConnectionHandleString(handle) {
1352
- const [mode, type, index] = (handle ?? "").split("/");
1353
- const resolvedMode = isValidCanvasConnectionMode(mode) ? mode : CanvasConnectionMode.Output;
1354
- const resolvedType = isValidNodeConnectionType(type) ? type : NodeConnectionTypes.Main;
1355
- let resolvedIndex = parseInt(index, 10);
1356
- if (isNaN(resolvedIndex)) {
1357
- resolvedIndex = 0;
1358
- }
1359
- return {
1360
- mode: resolvedMode,
1361
- type: resolvedType,
1362
- index: resolvedIndex
1363
- };
1364
- }
1365
- function createCanvasConnectionHandleString({
1366
- mode,
1367
- type = NodeConnectionTypes.Main,
1368
- index = 0
1369
- }) {
1370
- return `${mode}/${type}/${index}`;
1371
- }
1372
- function createCanvasConnectionId(connection) {
1373
- return `[${connection.source}/${connection.sourceHandle}][${connection.target}/${connection.targetHandle}]`;
1374
- }
1375
- function mapCanvasConnectionToLegacyConnection(sourceNode, targetNode, connection) {
1376
- const sourceNodeName = sourceNode?.name ?? "";
1377
- const { type: sourceType, index: sourceIndex } = parseCanvasConnectionHandleString(
1378
- connection.sourceHandle
1379
- );
1380
- const targetNodeName = targetNode?.name ?? "";
1381
- const { type: targetType, index: targetIndex } = parseCanvasConnectionHandleString(
1382
- connection.targetHandle
1383
- );
1384
- return [
1385
- {
1386
- node: sourceNodeName,
1387
- type: sourceType,
1388
- index: sourceIndex
1389
- },
1390
- {
1391
- node: targetNodeName,
1392
- type: targetType,
1393
- index: targetIndex
1394
- }
1395
- ];
1396
- }
1397
- function mapLegacyEndpointsToCanvasConnectionPort(endpoints, endpointNames = []) {
1398
- if (typeof endpoints === "string") {
1399
- console.warn("Node endpoints have not been evaluated", endpoints);
1400
- return [];
1401
- }
1402
- return endpoints.map((endpoint, endpointIndex) => {
1403
- const typeValue = typeof endpoint === "string" ? endpoint : endpoint.type;
1404
- const type = isValidNodeConnectionType(typeValue) ? typeValue : NodeConnectionTypes.Main;
1405
- const label = typeof endpoint === "string" ? endpointNames[endpointIndex] : endpoint.displayName;
1406
- const index = endpoints.slice(0, endpointIndex + 1).filter((e) => (typeof e === "string" ? e : e.type) === type).length - 1;
1407
- const required = typeof endpoint === "string" ? false : endpoint.required;
1408
- const maxConnections = typeof endpoint === "string" ? void 0 : endpoint.maxConnections;
1409
- return {
1410
- type,
1411
- index,
1412
- label,
1413
- ...maxConnections ? { maxConnections } : {},
1414
- ...required ? { required } : {}
1415
- };
1416
- });
1417
- }
1418
- function checkOverlap(node1, node2) {
1419
- return !// node1 is completely to the left of node2
1420
- (node1.x + node1.width <= node2.x || // node2 is completely to the left of node1
1421
- node2.x + node2.width <= node1.x || // node1 is completely above node2
1422
- node1.y + node1.height <= node2.y || // node2 is completely above node1
1423
- node2.y + node2.height <= node1.y);
1424
- }
1425
- function insertSpacersBetweenEndpoints(endpoints, requiredEndpointsCount = 0, minEndpointsCount = 4) {
1426
- const endpointsWithSpacers = [...endpoints];
1427
- const optionalNonMainInputsCount = endpointsWithSpacers.length - requiredEndpointsCount;
1428
- const spacerCount = minEndpointsCount - requiredEndpointsCount - optionalNonMainInputsCount;
1429
- if (endpointsWithSpacers.length < minEndpointsCount) {
1430
- for (let i = 0; i < spacerCount; i++) {
1431
- endpointsWithSpacers.splice(requiredEndpointsCount + i, 0, null);
1432
- }
1433
- }
1434
- return endpointsWithSpacers;
1435
- }
1436
- const useNodeCreatorStore = defineStore(STORES.NODE_CREATOR, () => {
1437
- const workflowsStore = useWorkflowsStore();
1438
- const ndvStore = useNDVStore();
1439
- const uiStore = useUIStore();
1440
- const nodeTypesStore = useNodeTypesStore();
1441
- const telemetry = useTelemetry();
1442
- const externalHooks = useExternalHooks();
1443
- const selectedView = ref(TRIGGER_NODE_CREATOR_VIEW);
1444
- const mergedNodes = ref([]);
1445
- const actions = ref({});
1446
- const showScrim = ref(false);
1447
- const openSource = ref("");
1448
- const isCreateNodeActive = ref(false);
1449
- const nodePanelSessionId = ref("");
1450
- const allNodeCreatorNodes = computed(
1451
- () => Object.values(mergedNodes.value).map((i) => transformNodeType(i))
1452
- );
1453
- function setMergeNodes(nodes) {
1454
- mergedNodes.value = nodes;
1455
- }
1456
- function setActions(nodes) {
1457
- actions.value = nodes;
1458
- }
1459
- function setShowScrim(isVisible) {
1460
- showScrim.value = isVisible;
1461
- }
1462
- function setSelectedView(view) {
1463
- selectedView.value = view;
1464
- }
1465
- function setOpenSource(view) {
1466
- openSource.value = view;
1467
- }
1468
- function openSelectiveNodeCreator({
1469
- connectionType,
1470
- node,
1471
- creatorView
1472
- }) {
1473
- const nodeName = node ?? ndvStore.activeNodeName;
1474
- const nodeData = nodeName ? workflowsStore.getNodeByName(nodeName) : null;
1475
- ndvStore.activeNodeName = null;
1476
- setTimeout(() => {
1477
- if (creatorView) {
1478
- setNodeCreatorState({
1479
- createNodeActive: true,
1480
- nodeCreatorView: creatorView
1481
- });
1482
- } else if (connectionType && nodeData) {
1483
- openNodeCreatorForConnectingNode({
1484
- connection: {
1485
- source: nodeData.id,
1486
- sourceHandle: createCanvasConnectionHandleString({
1487
- mode: "inputs",
1488
- type: connectionType,
1489
- index: 0
1490
- })
1491
- },
1492
- eventSource: NODE_CREATOR_OPEN_SOURCES.NOTICE_ERROR_MESSAGE
1493
- });
1494
- }
1495
- });
1496
- }
1497
- function setNodeCreatorState({
1498
- source,
1499
- createNodeActive,
1500
- nodeCreatorView
1501
- }) {
1502
- if (!nodeCreatorView) {
1503
- nodeCreatorView = workflowsStore.workflowTriggerNodes.length > 0 ? REGULAR_NODE_CREATOR_VIEW : TRIGGER_NODE_CREATOR_VIEW;
1504
- }
1505
- setSelectedView(nodeCreatorView);
1506
- isCreateNodeActive.value = createNodeActive;
1507
- if (createNodeActive && source) {
1508
- setOpenSource(source);
1509
- }
1510
- void externalHooks.run("nodeView.createNodeActiveChanged", {
1511
- source,
1512
- mode: getMode(nodeCreatorView),
1513
- createNodeActive
1514
- });
1515
- if (createNodeActive) {
1516
- onCreatorOpened({
1517
- source,
1518
- mode: getMode(nodeCreatorView),
1519
- workflow_id: workflowsStore.workflowId
1520
- });
1521
- }
1522
- }
1523
- function openNodeCreatorForConnectingNode({
1524
- connection,
1525
- eventSource,
1526
- nodeCreatorView
1527
- }) {
1528
- const sourceNode = workflowsStore.getNodeById(connection.source);
1529
- if (!sourceNode) {
1530
- return;
1531
- }
1532
- const { type, index, mode } = parseCanvasConnectionHandleString(connection.sourceHandle);
1533
- uiStore.lastSelectedNode = sourceNode.name;
1534
- uiStore.lastSelectedNodeEndpointUuid = connection.sourceHandle ?? null;
1535
- uiStore.lastSelectedNodeOutputIndex = index;
1536
- if (isVueFlowConnection(connection)) {
1537
- uiStore.lastInteractedWithNodeConnection = connection;
1538
- }
1539
- uiStore.lastInteractedWithNodeHandle = connection.sourceHandle ?? null;
1540
- uiStore.lastInteractedWithNodeId = sourceNode.id;
1541
- const isOutput = mode === CanvasConnectionMode.Output;
1542
- const isScopedConnection = type !== NodeConnectionTypes.Main;
1543
- setNodeCreatorState({
1544
- source: eventSource,
1545
- createNodeActive: true,
1546
- nodeCreatorView: isScopedConnection ? AI_UNCATEGORIZED_CATEGORY : nodeCreatorView
1547
- });
1548
- if (isScopedConnection) {
1549
- useViewStacks().gotoCompatibleConnectionView(type, isOutput, getNodeCreatorFilter(sourceNode.name, type)).catch(() => {
1550
- });
1551
- }
1552
- }
1553
- function openNodeCreatorForTriggerNodes(source) {
1554
- ndvStore.activeNodeName = null;
1555
- setSelectedView(TRIGGER_NODE_CREATOR_VIEW);
1556
- setShowScrim(true);
1557
- setNodeCreatorState({
1558
- source,
1559
- createNodeActive: true,
1560
- nodeCreatorView: TRIGGER_NODE_CREATOR_VIEW
1561
- });
1562
- }
1563
- function getNodeCreatorFilter(nodeName, outputType) {
1564
- let filter;
1565
- const workflow = workflowsStore.getCurrentWorkflow();
1566
- const workflowNode = workflow.getNode(nodeName);
1567
- if (!workflowNode) return { nodes: [] };
1568
- const nodeType = nodeTypesStore.getNodeType(workflowNode?.type, workflowNode.typeVersion);
1569
- if (nodeType) {
1570
- const inputs = getNodeInputs(workflow, workflowNode, nodeType);
1571
- const filterFound = inputs.filter((input) => {
1572
- if (typeof input === "string" || input.type !== outputType || !input.filter) {
1573
- return false;
1574
- }
1575
- return true;
1576
- });
1577
- if (filterFound.length) {
1578
- filter = filterFound[0].filter;
1579
- }
1580
- }
1581
- return filter;
1582
- }
1583
- function resetNodesPanelSession() {
1584
- nodePanelSessionId.value = `nodes_panel_session_${(/* @__PURE__ */ new Date()).valueOf()}`;
1585
- }
1586
- function trackNodeCreatorEvent(event, properties = {}, withPostHog = false) {
1587
- telemetry.track(
1588
- event,
1589
- {
1590
- ...properties,
1591
- nodes_panel_session_id: nodePanelSessionId.value
1592
- },
1593
- {
1594
- withPostHog
1595
- }
1596
- );
1597
- }
1598
- function onCreatorOpened({
1599
- source,
1600
- mode,
1601
- workflow_id
1602
- }) {
1603
- resetNodesPanelSession();
1604
- trackNodeCreatorEvent("User opened nodes panel", {
1605
- source,
1606
- mode,
1607
- workflow_id
1608
- });
1609
- }
1610
- function onNodeFilterChanged({
1611
- newValue,
1612
- filteredNodes,
1613
- filterMode,
1614
- subcategory,
1615
- title
1616
- }) {
1617
- if (!newValue.length) {
1618
- return;
1619
- }
1620
- const { results_count, trigger_count, regular_count } = filteredNodes.reduce(
1621
- (accu, node) => {
1622
- if (!("properties" in node)) {
1623
- return accu;
1624
- }
1625
- const isCustomAction = "actionKey" in node.properties && node.properties.actionKey === CUSTOM_API_CALL_KEY;
1626
- if (isCustomAction) {
1627
- return accu;
1628
- }
1629
- const isTrigger = node.key.includes("Trigger");
1630
- return {
1631
- results_count: accu.results_count + 1,
1632
- trigger_count: accu.trigger_count + (isTrigger ? 1 : 0),
1633
- regular_count: accu.regular_count + (isTrigger ? 0 : 1)
1634
- };
1635
- },
1636
- {
1637
- results_count: 0,
1638
- trigger_count: 0,
1639
- regular_count: 0
1640
- }
1641
- );
1642
- trackNodeCreatorEvent("User entered nodes panel search term", {
1643
- search_string: newValue,
1644
- filter_mode: getMode(filterMode),
1645
- category_name: subcategory,
1646
- results_count,
1647
- trigger_count,
1648
- regular_count,
1649
- title
1650
- });
1651
- }
1652
- function onCategoryExpanded(properties) {
1653
- trackNodeCreatorEvent("User viewed node category", { ...properties, is_subcategory: false });
1654
- }
1655
- function onViewActions(properties) {
1656
- trackNodeCreatorEvent("User viewed node actions", properties);
1657
- }
1658
- function onActionsCustomAPIClicked(properties) {
1659
- trackNodeCreatorEvent("User clicked custom API from node actions", properties);
1660
- }
1661
- function onAddActions(properties) {
1662
- trackNodeCreatorEvent("User added action", properties);
1663
- }
1664
- function onSubcategorySelected(properties) {
1665
- trackNodeCreatorEvent("User viewed node category", {
1666
- category_name: properties.subcategory,
1667
- is_subcategory: true
1668
- });
1669
- }
1670
- function onNodeAddedToCanvas(properties) {
1671
- trackNodeCreatorEvent("User added node to workflow canvas", properties, true);
1672
- }
1673
- function getMode(mode) {
1674
- if (mode === AI_NODE_CREATOR_VIEW || mode === AI_OTHERS_NODE_CREATOR_VIEW) {
1675
- return "ai";
1676
- }
1677
- if (mode === TRIGGER_NODE_CREATOR_VIEW) {
1678
- return "trigger";
1679
- }
1680
- return "regular";
1681
- }
1682
- return {
1683
- isCreateNodeActive,
1684
- openSource,
1685
- selectedView,
1686
- showScrim,
1687
- mergedNodes,
1688
- actions,
1689
- setShowScrim,
1690
- setSelectedView,
1691
- setOpenSource,
1692
- setActions,
1693
- setMergeNodes,
1694
- setNodeCreatorState,
1695
- openSelectiveNodeCreator,
1696
- openNodeCreatorForConnectingNode,
1697
- openNodeCreatorForTriggerNodes,
1698
- allNodeCreatorNodes,
1699
- onCreatorOpened,
1700
- onNodeFilterChanged,
1701
- onCategoryExpanded,
1702
- onActionsCustomAPIClicked,
1703
- onViewActions,
1704
- onAddActions,
1705
- onSubcategorySelected,
1706
- onNodeAddedToCanvas
1707
- };
1708
- });
1709
- function useUniqueNodeName() {
1710
- function numberSuffixedNames() {
1711
- return useNodeTypesStore().allNodeTypes.reduce((acc, nodeType) => {
1712
- if (typeof nodeType.defaults.name !== "string") {
1713
- throw new Error("Expected node name default to be a string");
1714
- }
1715
- if (/\d$/.test(nodeType.defaults.name)) acc.push(nodeType.defaults.name);
1716
- return acc;
1717
- }, []);
1718
- }
1719
- function uniqueNodeName(originalName, extraNames = []) {
1720
- const { canvasNames } = useWorkflowsStore();
1721
- const isUnique = !canvasNames.has(originalName) && !extraNames.includes(originalName);
1722
- if (isUnique) return originalName;
1723
- const nsn = numberSuffixedNames().find((nsn2) => originalName.startsWith(nsn2));
1724
- if (nsn) {
1725
- let unique2 = "";
1726
- let index2 = 1;
1727
- const remainder = originalName.split(nsn).pop();
1728
- const lastChar = remainder?.[remainder.length - 1];
1729
- if (lastChar && Number.isInteger(Number(lastChar))) {
1730
- index2 = parseInt(lastChar, 10);
1731
- originalName = originalName.slice(0, -1);
1732
- }
1733
- unique2 = originalName;
1734
- while (canvasNames.has(unique2) || extraNames.includes(unique2)) {
1735
- unique2 = originalName + index2++;
1736
- }
1737
- return unique2;
1738
- }
1739
- if (/^\d+-?\d*$/.test(originalName)) {
1740
- let unique2 = "";
1741
- let index2 = 1;
1742
- const match2 = originalName.match(/(?<base>\d+)-?(?<suffix>\d*)/);
1743
- if (!match2?.groups) {
1744
- throw new Error("Failed to find match for unique name");
1745
- }
1746
- if (match2?.groups?.suffix !== "") {
1747
- index2 = parseInt(match2.groups.suffix, 10);
1748
- }
1749
- unique2 = match2.groups.base;
1750
- while (canvasNames.has(unique2) || extraNames.includes(unique2)) {
1751
- unique2 = match2.groups.base + "-" + index2++;
1752
- }
1753
- return unique2;
1754
- }
1755
- let unique = "";
1756
- let index = 1;
1757
- const match = originalName.match(/(?<base>.*\D+)(?<suffix>\d*)/);
1758
- if (!match?.groups) {
1759
- throw new Error("Failed to find match for unique name");
1760
- }
1761
- if (match?.groups?.suffix !== "") {
1762
- index = parseInt(match.groups.suffix, 10);
1763
- }
1764
- unique = match.groups.base;
1765
- while (canvasNames.has(unique) || extraNames.includes(unique)) {
1766
- unique = match.groups.base + index++;
1767
- }
1768
- return unique;
1769
- }
1770
- return { uniqueNodeName };
1771
- }
1772
- function useCanvasOperations({ router }) {
1773
- const rootStore = useRootStore();
1774
- const workflowsStore = useWorkflowsStore();
1775
- const credentialsStore = useCredentialsStore();
1776
- const historyStore = useHistoryStore();
1777
- const uiStore = useUIStore();
1778
- const ndvStore = useNDVStore();
1779
- const nodeTypesStore = useNodeTypesStore();
1780
- const canvasStore = useCanvasStore();
1781
- const settingsStore = useSettingsStore();
1782
- const tagsStore = useTagsStore();
1783
- const nodeCreatorStore = useNodeCreatorStore();
1784
- const executionsStore = useExecutionsStore();
1785
- const projectsStore = useProjectsStore();
1786
- const i18n2 = useI18n();
1787
- const toast = useToast();
1788
- const workflowHelpers = useWorkflowHelpers({ router });
1789
- const nodeHelpers = useNodeHelpers();
1790
- const telemetry = useTelemetry();
1791
- const externalHooks = useExternalHooks();
1792
- const clipboard = useClipboard();
1793
- const { uniqueNodeName } = useUniqueNodeName();
1794
- const lastClickPosition = ref([0, 0]);
1795
- const preventOpeningNDV = !!localStorage.getItem("NodeView.preventOpeningNDV");
1796
- const editableWorkflow = computed(() => workflowsStore.workflow);
1797
- const editableWorkflowObject = computed(() => workflowsStore.getCurrentWorkflow());
1798
- const triggerNodes = computed(() => {
1799
- return workflowsStore.workflowTriggerNodes;
1800
- });
1801
- function tidyUp({ result, source, target }) {
1802
- updateNodesPosition(
1803
- result.nodes.map(({ id, x, y }) => ({ id, position: { x, y } })),
1804
- { trackBulk: true, trackHistory: true }
1805
- );
1806
- trackTidyUp({ result, source, target });
1807
- }
1808
- function trackTidyUp({ result, source, target }) {
1809
- telemetry.track(
1810
- "User tidied up canvas",
1811
- {
1812
- source,
1813
- target,
1814
- nodes_count: result.nodes.length
1815
- },
1816
- { withPostHog: true }
1817
- );
1818
- }
1819
- function updateNodesPosition(events, { trackHistory = false, trackBulk = true } = {}) {
1820
- if (trackHistory && trackBulk) {
1821
- historyStore.startRecordingUndo();
1822
- }
1823
- events.forEach(({ id, position }) => {
1824
- updateNodePosition(id, position, { trackHistory });
1825
- });
1826
- if (trackHistory && trackBulk) {
1827
- historyStore.stopRecordingUndo();
1828
- }
1829
- }
1830
- function updateNodePosition(id, position, { trackHistory = false } = {}) {
1831
- const node = workflowsStore.getNodeById(id);
1832
- if (!node) {
1833
- return;
1834
- }
1835
- const oldPosition = [...node.position];
1836
- const newPosition = [position.x, position.y];
1837
- workflowsStore.setNodePositionById(id, newPosition);
1838
- if (trackHistory) {
1839
- historyStore.pushCommandToUndo(
1840
- new MoveNodeCommand(node.name, oldPosition, newPosition, Date.now())
1841
- );
1842
- }
1843
- }
1844
- function revertUpdateNodePosition(nodeName, position) {
1845
- const node = workflowsStore.getNodeByName(nodeName);
1846
- if (!node) {
1847
- return;
1848
- }
1849
- updateNodePosition(node.id, position);
1850
- }
1851
- async function renameNode(currentName, newName, { trackHistory = false, trackBulk = true } = {}) {
1852
- if (currentName === newName) {
1853
- return;
1854
- }
1855
- if (trackHistory && trackBulk) {
1856
- historyStore.startRecordingUndo();
1857
- }
1858
- newName = uniqueNodeName(newName);
1859
- const workflow = workflowsStore.getCurrentWorkflow(true);
1860
- workflow.renameNode(currentName, newName);
1861
- if (trackHistory) {
1862
- historyStore.pushCommandToUndo(new RenameNodeCommand(currentName, newName, Date.now()));
1863
- }
1864
- workflowsStore.renameNodeSelectedAndExecution({ old: currentName, new: newName });
1865
- workflowsStore.setNodes(Object.values(workflow.nodes));
1866
- workflowsStore.setConnections(workflow.connectionsBySourceNode);
1867
- const isRenamingActiveNode = ndvStore.activeNodeName === currentName;
1868
- if (isRenamingActiveNode) {
1869
- ndvStore.activeNodeName = newName;
1870
- }
1871
- if (trackHistory && trackBulk) {
1872
- historyStore.stopRecordingUndo();
1873
- }
1874
- }
1875
- async function revertRenameNode(currentName, previousName) {
1876
- await renameNode(currentName, previousName);
1877
- }
1878
- function connectAdjacentNodes(id, { trackHistory = false } = {}) {
1879
- const node = workflowsStore.getNodeById(id);
1880
- if (!node) {
1881
- return;
1882
- }
1883
- const outputConnectionsByType = workflowsStore.outgoingConnectionsByNodeName(node.name);
1884
- const incomingConnectionsByType = workflowsStore.incomingConnectionsByNodeName(node.name);
1885
- for (const [type, incomingConnectionsByInputIndex] of Object.entries(
1886
- incomingConnectionsByType
1887
- )) {
1888
- for (const incomingConnection of incomingConnectionsByInputIndex.at(0) ?? []) {
1889
- const incomingNodeId = workflowsStore.getNodeByName(incomingConnection.node)?.id;
1890
- if (!incomingNodeId) continue;
1891
- for (const outgoingConnection of outputConnectionsByType[type]?.at(0) ?? []) {
1892
- const outgoingNodeId = workflowsStore.getNodeByName(outgoingConnection.node)?.id;
1893
- if (!outgoingNodeId) continue;
1894
- if (trackHistory) {
1895
- historyStore.pushCommandToUndo(
1896
- new AddConnectionCommand(
1897
- [
1898
- {
1899
- node: incomingConnection.node,
1900
- type,
1901
- index: incomingConnection.index
1902
- },
1903
- {
1904
- node: outgoingConnection.node,
1905
- type,
1906
- index: outgoingConnection.index
1907
- }
1908
- ],
1909
- Date.now()
1910
- )
1911
- );
1912
- }
1913
- createConnection({
1914
- source: incomingNodeId,
1915
- sourceHandle: createCanvasConnectionHandleString({
1916
- mode: CanvasConnectionMode.Output,
1917
- type,
1918
- index: incomingConnection.index
1919
- }),
1920
- target: outgoingNodeId,
1921
- targetHandle: createCanvasConnectionHandleString({
1922
- mode: CanvasConnectionMode.Input,
1923
- type,
1924
- index: outgoingConnection.index
1925
- })
1926
- });
1927
- }
1928
- }
1929
- }
1930
- }
1931
- function deleteNode(id, { trackHistory = false, trackBulk = true } = {}) {
1932
- const node = workflowsStore.getNodeById(id);
1933
- if (!node) {
1934
- return;
1935
- }
1936
- if (trackHistory && trackBulk) {
1937
- historyStore.startRecordingUndo();
1938
- }
1939
- if (uiStore.lastInteractedWithNodeId === id) {
1940
- uiStore.lastInteractedWithNodeId = void 0;
1941
- }
1942
- connectAdjacentNodes(id, { trackHistory });
1943
- deleteConnectionsByNodeId(id, { trackHistory, trackBulk: false });
1944
- workflowsStore.removeNodeExecutionDataById(id);
1945
- workflowsStore.removeNodeById(id);
1946
- if (trackHistory) {
1947
- historyStore.pushCommandToUndo(new RemoveNodeCommand(node, Date.now()));
1948
- if (trackBulk) {
1949
- historyStore.stopRecordingUndo();
1950
- }
1951
- }
1952
- trackDeleteNode(id);
1953
- }
1954
- function deleteNodes(ids, { trackHistory = true, trackBulk = true } = {}) {
1955
- if (trackHistory && trackBulk) {
1956
- historyStore.startRecordingUndo();
1957
- }
1958
- ids.forEach((id) => deleteNode(id, { trackHistory, trackBulk: false }));
1959
- if (trackHistory && trackBulk) {
1960
- historyStore.stopRecordingUndo();
1961
- }
1962
- }
1963
- function revertDeleteNode(node) {
1964
- workflowsStore.addNode(node);
1965
- }
1966
- function trackDeleteNode(id) {
1967
- const node = workflowsStore.getNodeById(id);
1968
- if (!node) {
1969
- return;
1970
- }
1971
- if (node.type === STICKY_NODE_TYPE) {
1972
- telemetry.track("User deleted workflow note", {
1973
- workflow_id: workflowsStore.workflowId
1974
- });
1975
- } else {
1976
- void externalHooks.run("node.deleteNode", { node });
1977
- telemetry.track("User deleted node", {
1978
- node_type: node.type,
1979
- workflow_id: workflowsStore.workflowId
1980
- });
1981
- }
1982
- }
1983
- function setNodeActive(id) {
1984
- const node = workflowsStore.getNodeById(id);
1985
- if (!node) {
1986
- return;
1987
- }
1988
- workflowsStore.setNodePristine(node.name, false);
1989
- setNodeActiveByName(node.name);
1990
- }
1991
- function setNodeActiveByName(name) {
1992
- ndvStore.activeNodeName = name;
1993
- }
1994
- function clearNodeActive() {
1995
- ndvStore.activeNodeName = null;
1996
- }
1997
- function setNodeParameters(id, parameters) {
1998
- const node = workflowsStore.getNodeById(id);
1999
- if (!node) {
2000
- return;
2001
- }
2002
- workflowsStore.setNodeParameters(
2003
- {
2004
- name: node.name,
2005
- value: parameters
2006
- },
2007
- true
2008
- );
2009
- }
2010
- function setNodeSelected(id) {
2011
- if (!id) {
2012
- uiStore.lastInteractedWithNodeId = void 0;
2013
- uiStore.lastSelectedNode = "";
2014
- return;
2015
- }
2016
- const node = workflowsStore.getNodeById(id);
2017
- if (!node) {
2018
- return;
2019
- }
2020
- uiStore.lastInteractedWithNodeId = id;
2021
- uiStore.lastSelectedNode = node.name;
2022
- }
2023
- function toggleNodesDisabled(ids, { trackHistory = true, trackBulk = true } = {}) {
2024
- if (trackHistory && trackBulk) {
2025
- historyStore.startRecordingUndo();
2026
- }
2027
- const nodes = workflowsStore.getNodesByIds(ids);
2028
- nodeHelpers.disableNodes(nodes, { trackHistory, trackBulk: false });
2029
- if (trackHistory && trackBulk) {
2030
- historyStore.stopRecordingUndo();
2031
- }
2032
- }
2033
- function revertToggleNodeDisabled(nodeName) {
2034
- const node = workflowsStore.getNodeByName(nodeName);
2035
- if (node) {
2036
- nodeHelpers.disableNodes([node]);
2037
- }
2038
- }
2039
- function toggleNodesPinned(ids, source, { trackHistory = true, trackBulk = true } = {}) {
2040
- if (trackHistory && trackBulk) {
2041
- historyStore.startRecordingUndo();
2042
- }
2043
- const nodes = workflowsStore.getNodesByIds(ids);
2044
- const nextStatePinned = nodes.some((node) => !workflowsStore.pinDataByNodeName(node.name));
2045
- for (const node of nodes) {
2046
- const pinnedDataForNode = usePinnedData(node);
2047
- if (nextStatePinned) {
2048
- const dataToPin = useDataSchema().getInputDataWithPinned(node);
2049
- if (dataToPin.length !== 0) {
2050
- pinnedDataForNode.setData(dataToPin, source);
2051
- }
2052
- } else {
2053
- pinnedDataForNode.unsetData(source);
2054
- }
2055
- }
2056
- if (trackHistory && trackBulk) {
2057
- historyStore.stopRecordingUndo();
2058
- }
2059
- }
2060
- function requireNodeTypeDescription(type, version) {
2061
- return nodeTypesStore.getNodeType(type, version) ?? {
2062
- properties: [],
2063
- displayName: type,
2064
- name: type,
2065
- group: [],
2066
- description: "",
2067
- version: version ?? 1,
2068
- defaults: {},
2069
- inputs: [],
2070
- outputs: []
2071
- };
2072
- }
2073
- async function addNodes(nodes, options = {}) {
2074
- let insertPosition = options.position;
2075
- let lastAddedNode;
2076
- const addedNodes = [];
2077
- const nodesWithTypeVersion = nodes.map((node) => {
2078
- const typeVersion = node.typeVersion ?? resolveNodeVersion(requireNodeTypeDescription(node.type));
2079
- return {
2080
- ...node,
2081
- typeVersion
2082
- };
2083
- });
2084
- await loadNodeTypesProperties(nodesWithTypeVersion);
2085
- if (options.trackHistory && options.trackBulk) {
2086
- historyStore.startRecordingUndo();
2087
- }
2088
- for (const nodeAddData of nodesWithTypeVersion) {
2089
- const { isAutoAdd, openDetail: openNDV, ...node } = nodeAddData;
2090
- const position = node.position ?? insertPosition;
2091
- const nodeTypeDescription = requireNodeTypeDescription(node.type, node.typeVersion);
2092
- try {
2093
- const newNode = addNode(
2094
- {
2095
- ...node,
2096
- position
2097
- },
2098
- nodeTypeDescription,
2099
- {
2100
- ...options,
2101
- openNDV,
2102
- isAutoAdd
2103
- }
2104
- );
2105
- lastAddedNode = newNode;
2106
- addedNodes.push(newNode);
2107
- } catch (error) {
2108
- toast.showError(error, i18n2.baseText("error"));
2109
- console.error(error);
2110
- continue;
2111
- }
2112
- insertPosition = [
2113
- lastAddedNode.position[0] + NODE_SIZE * 2 + GRID_SIZE,
2114
- lastAddedNode.position[1]
2115
- ];
2116
- }
2117
- if (lastAddedNode) {
2118
- updatePositionForNodeWithMultipleInputs(lastAddedNode);
2119
- }
2120
- if (options.trackHistory && options.trackBulk) {
2121
- historyStore.stopRecordingUndo();
2122
- }
2123
- if (!options.keepPristine) {
2124
- uiStore.stateIsDirty = true;
2125
- }
2126
- return addedNodes;
2127
- }
2128
- function updatePositionForNodeWithMultipleInputs(node) {
2129
- const inputNodes = editableWorkflowObject.value.getParentNodesByDepth(node.name, 1);
2130
- if (inputNodes.length > 1) {
2131
- inputNodes.slice(1).forEach((inputNode, index) => {
2132
- const nodeUi = workflowsStore.getNodeByName(inputNode.name);
2133
- if (!nodeUi) return;
2134
- updateNodePosition(nodeUi.id, {
2135
- x: nodeUi.position[0],
2136
- y: nodeUi.position[1] + 100 * (index + 1)
2137
- });
2138
- });
2139
- }
2140
- }
2141
- function checkMaxNodesOfTypeReached(nodeTypeDescription) {
2142
- if (nodeTypeDescription.maxNodes !== void 0 && workflowHelpers.getNodeTypeCount(nodeTypeDescription.name) >= nodeTypeDescription.maxNodes) {
2143
- throw new Error(
2144
- i18n2.baseText("nodeView.showMessage.showMaxNodeTypeError.message", {
2145
- adjustToNumber: nodeTypeDescription.maxNodes,
2146
- interpolate: { nodeTypeDataDisplayName: nodeTypeDescription.displayName }
2147
- })
2148
- );
2149
- }
2150
- }
2151
- function addNode(node, nodeTypeDescription, options = {}) {
2152
- checkMaxNodesOfTypeReached(nodeTypeDescription);
2153
- const nodeData = resolveNodeData(node, nodeTypeDescription);
2154
- if (!nodeData) {
2155
- throw new Error(i18n2.baseText("nodeViewV2.showError.failedToCreateNode"));
2156
- }
2157
- workflowsStore.addNode(nodeData);
2158
- if (options.trackHistory) {
2159
- historyStore.pushCommandToUndo(new AddNodeCommand(nodeData, Date.now()));
2160
- }
2161
- if (!options.isAutoAdd) {
2162
- createConnectionToLastInteractedWithNode(nodeData, options);
2163
- }
2164
- void nextTick(() => {
2165
- if (!options.keepPristine) {
2166
- uiStore.stateIsDirty = true;
2167
- }
2168
- workflowsStore.setNodePristine(nodeData.name, true);
2169
- nodeHelpers.matchCredentials(nodeData);
2170
- nodeHelpers.updateNodeParameterIssues(nodeData);
2171
- nodeHelpers.updateNodeCredentialIssues(nodeData);
2172
- nodeHelpers.updateNodeInputIssues(nodeData);
2173
- if (options.telemetry) {
2174
- trackAddNode(nodeData, options);
2175
- }
2176
- if (nodeData.type !== STICKY_NODE_TYPE) {
2177
- void externalHooks.run("nodeView.addNodeButton", { nodeTypeName: nodeData.type });
2178
- if (options.openNDV && !preventOpeningNDV) {
2179
- ndvStore.setActiveNodeName(nodeData.name);
2180
- }
2181
- }
2182
- });
2183
- return nodeData;
2184
- }
2185
- async function revertAddNode(nodeName) {
2186
- const node = workflowsStore.getNodeByName(nodeName);
2187
- if (!node) {
2188
- return;
2189
- }
2190
- deleteNode(node.id);
2191
- }
2192
- function createConnectionToLastInteractedWithNode(node, options = {}) {
2193
- const lastInteractedWithNode = uiStore.lastInteractedWithNode;
2194
- if (!lastInteractedWithNode) {
2195
- return;
2196
- }
2197
- const lastInteractedWithNodeId = lastInteractedWithNode.id;
2198
- const lastInteractedWithNodeConnection = uiStore.lastInteractedWithNodeConnection;
2199
- const lastInteractedWithNodeHandle = uiStore.lastInteractedWithNodeHandle;
2200
- if (lastInteractedWithNodeHandle) {
2201
- const { type: connectionType, mode } = parseCanvasConnectionHandleString(
2202
- lastInteractedWithNodeHandle
2203
- );
2204
- const nodeId = node.id;
2205
- const nodeHandle = createCanvasConnectionHandleString({
2206
- mode: CanvasConnectionMode.Input,
2207
- type: connectionType,
2208
- index: 0
2209
- });
2210
- if (mode === CanvasConnectionMode.Input) {
2211
- createConnection({
2212
- source: nodeId,
2213
- sourceHandle: nodeHandle,
2214
- target: lastInteractedWithNodeId,
2215
- targetHandle: lastInteractedWithNodeHandle
2216
- });
2217
- } else {
2218
- createConnection({
2219
- source: lastInteractedWithNodeId,
2220
- sourceHandle: lastInteractedWithNodeHandle,
2221
- target: nodeId,
2222
- targetHandle: nodeHandle
2223
- });
2224
- }
2225
- } else {
2226
- createConnection({
2227
- source: lastInteractedWithNodeId,
2228
- sourceHandle: createCanvasConnectionHandleString({
2229
- mode: CanvasConnectionMode.Output,
2230
- type: NodeConnectionTypes.Main,
2231
- index: 0
2232
- }),
2233
- target: node.id,
2234
- targetHandle: createCanvasConnectionHandleString({
2235
- mode: CanvasConnectionMode.Input,
2236
- type: NodeConnectionTypes.Main,
2237
- index: 0
2238
- })
2239
- });
2240
- }
2241
- if (lastInteractedWithNodeConnection) {
2242
- deleteConnection(lastInteractedWithNodeConnection, { trackHistory: options.trackHistory });
2243
- const targetNode = workflowsStore.getNodeById(lastInteractedWithNodeConnection.target);
2244
- if (targetNode) {
2245
- createConnection({
2246
- source: node.id,
2247
- sourceHandle: createCanvasConnectionHandleString({
2248
- mode: CanvasConnectionMode.Input,
2249
- type: NodeConnectionTypes.Main,
2250
- index: 0
2251
- }),
2252
- target: lastInteractedWithNodeConnection.target,
2253
- targetHandle: lastInteractedWithNodeConnection.targetHandle
2254
- });
2255
- }
2256
- }
2257
- }
2258
- function trackAddNode(nodeData, options) {
2259
- switch (nodeData.type) {
2260
- case STICKY_NODE_TYPE:
2261
- trackAddStickyNoteNode();
2262
- break;
2263
- default:
2264
- trackAddDefaultNode(nodeData, options);
2265
- }
2266
- }
2267
- function trackAddStickyNoteNode() {
2268
- telemetry.track("User inserted workflow note", {
2269
- workflow_id: workflowsStore.workflowId
2270
- });
2271
- }
2272
- function trackAddDefaultNode(nodeData, options) {
2273
- nodeCreatorStore.onNodeAddedToCanvas({
2274
- node_id: nodeData.id,
2275
- node_type: nodeData.type,
2276
- node_version: nodeData.typeVersion,
2277
- is_auto_add: options.isAutoAdd,
2278
- workflow_id: workflowsStore.workflowId,
2279
- drag_and_drop: options.dragAndDrop,
2280
- input_node_type: uiStore.lastInteractedWithNode ? uiStore.lastInteractedWithNode.type : void 0
2281
- });
2282
- }
2283
- function resolveNodeData(node, nodeTypeDescription) {
2284
- const id = node.id ?? nodeHelpers.assignNodeId(node);
2285
- const name = node.name ?? nodeTypeDescription.defaults.name;
2286
- const type = nodeTypeDescription.name;
2287
- const typeVersion = node.typeVersion;
2288
- const position = resolveNodePosition(node, nodeTypeDescription);
2289
- const disabled = node.disabled ?? false;
2290
- const parameters = node.parameters ?? {};
2291
- const nodeData = {
2292
- ...node,
2293
- id,
2294
- name,
2295
- type,
2296
- typeVersion,
2297
- position,
2298
- disabled,
2299
- parameters
2300
- };
2301
- resolveNodeName(nodeData);
2302
- resolveNodeParameters(nodeData, nodeTypeDescription);
2303
- resolveNodeWebhook(nodeData, nodeTypeDescription);
2304
- return nodeData;
2305
- }
2306
- async function loadNodeTypesProperties(nodes) {
2307
- const allNodeTypeDescriptions = nodeTypesStore.allNodeTypes;
2308
- const nodesToBeFetched = [];
2309
- allNodeTypeDescriptions.forEach((nodeTypeDescription) => {
2310
- const nodeVersions = Array.isArray(nodeTypeDescription.version) ? nodeTypeDescription.version : [nodeTypeDescription.version];
2311
- if (!!nodes.find(
2312
- (n) => n.type === nodeTypeDescription.name && nodeVersions.includes(n.typeVersion)
2313
- ) && !nodeTypeDescription.hasOwnProperty("properties")) {
2314
- nodesToBeFetched.push({
2315
- name: nodeTypeDescription.name,
2316
- version: Array.isArray(nodeTypeDescription.version) ? nodeTypeDescription.version.slice(-1)[0] : nodeTypeDescription.version
2317
- });
2318
- }
2319
- });
2320
- if (nodesToBeFetched.length > 0) {
2321
- await nodeTypesStore.getNodesInformation(nodesToBeFetched);
2322
- }
2323
- }
2324
- function resolveNodeVersion(nodeTypeDescription) {
2325
- let nodeVersion = nodeTypeDescription.defaultVersion;
2326
- if (typeof nodeVersion === "undefined") {
2327
- nodeVersion = Array.isArray(nodeTypeDescription.version) ? nodeTypeDescription.version.slice(-1)[0] : nodeTypeDescription.version;
2328
- }
2329
- return nodeVersion;
2330
- }
2331
- function resolveNodeParameters(node, nodeTypeDescription) {
2332
- const nodeParameters = getNodeParameters(
2333
- nodeTypeDescription?.properties ?? [],
2334
- node.parameters,
2335
- true,
2336
- false,
2337
- node,
2338
- nodeTypeDescription
2339
- );
2340
- node.parameters = nodeParameters ?? {};
2341
- }
2342
- function resolveNodePosition(node, nodeTypeDescription) {
2343
- let position = node.position;
2344
- let pushOffsets = [40, 40];
2345
- if (position) {
2346
- return getNewNodePosition(workflowsStore.allNodes, position, pushOffsets);
2347
- }
2348
- const lastInteractedWithNode = uiStore.lastInteractedWithNode;
2349
- const lastInteractedWithNodeConnection = uiStore.lastInteractedWithNodeConnection;
2350
- const lastInteractedWithNodeHandle = uiStore.lastInteractedWithNodeHandle;
2351
- const { type: connectionType, index: connectionIndex } = parseCanvasConnectionHandleString(
2352
- lastInteractedWithNodeHandle ?? lastInteractedWithNodeConnection?.sourceHandle ?? ""
2353
- );
2354
- const nodeSize = connectionType === NodeConnectionTypes.Main ? DEFAULT_NODE_SIZE : CONFIGURATION_NODE_SIZE;
2355
- if (lastInteractedWithNode) {
2356
- const lastInteractedWithNodeTypeDescription = nodeTypesStore.getNodeType(
2357
- lastInteractedWithNode.type,
2358
- lastInteractedWithNode.typeVersion
2359
- );
2360
- const lastInteractedWithNodeObject = editableWorkflowObject.value.getNode(
2361
- lastInteractedWithNode.name
2362
- );
2363
- const newNodeInsertPosition = uiStore.lastCancelledConnectionPosition;
2364
- if (newNodeInsertPosition) {
2365
- const xOffset = connectionType === NodeConnectionTypes.Main ? 0 : -nodeSize[0] / 2;
2366
- const yOffset = connectionType === NodeConnectionTypes.Main ? -nodeSize[1] / 2 : 0;
2367
- position = [newNodeInsertPosition[0] + xOffset, newNodeInsertPosition[1] + yOffset];
2368
- uiStore.lastCancelledConnectionPosition = void 0;
2369
- } else if (lastInteractedWithNodeTypeDescription && lastInteractedWithNodeObject) {
2370
- const lastInteractedWithNodeInputs = getNodeInputs(
2371
- editableWorkflowObject.value,
2372
- lastInteractedWithNodeObject,
2373
- lastInteractedWithNodeTypeDescription
2374
- );
2375
- const lastInteractedWithNodeInputTypes = getConnectionTypes(
2376
- lastInteractedWithNodeInputs
2377
- );
2378
- const lastInteractedWithNodeScopedInputTypes = (lastInteractedWithNodeInputTypes || []).filter((input) => input !== NodeConnectionTypes.Main);
2379
- const lastInteractedWithNodeOutputs = getNodeOutputs(
2380
- editableWorkflowObject.value,
2381
- lastInteractedWithNodeObject,
2382
- lastInteractedWithNodeTypeDescription
2383
- );
2384
- const lastInteractedWithNodeOutputTypes = getConnectionTypes(
2385
- lastInteractedWithNodeOutputs
2386
- );
2387
- const lastInteractedWithNodeMainOutputs = lastInteractedWithNodeOutputTypes.filter(
2388
- (output) => output === NodeConnectionTypes.Main
2389
- );
2390
- let yOffset = 0;
2391
- if (lastInteractedWithNodeConnection) {
2392
- shiftDownstreamNodesPosition(lastInteractedWithNode.name, PUSH_NODES_OFFSET, {
2393
- trackHistory: true
2394
- });
2395
- }
2396
- if (lastInteractedWithNodeMainOutputs.length > 1) {
2397
- const yOffsetValues = generateOffsets(
2398
- lastInteractedWithNodeMainOutputs.length,
2399
- NODE_SIZE,
2400
- GRID_SIZE
2401
- );
2402
- yOffset = yOffsetValues[connectionIndex];
2403
- }
2404
- let outputs = [];
2405
- try {
2406
- outputs = getNodeOutputs(
2407
- editableWorkflowObject.value,
2408
- node,
2409
- nodeTypeDescription
2410
- );
2411
- } catch (e) {
2412
- }
2413
- const outputTypes = getConnectionTypes(outputs);
2414
- pushOffsets = [100, 0];
2415
- if (outputTypes.length > 0 && outputTypes.every((outputName) => outputName !== NodeConnectionTypes.Main)) {
2416
- const scopedConnectionIndex = lastInteractedWithNodeScopedInputTypes.findIndex(
2417
- (inputType) => outputs[0] === inputType
2418
- );
2419
- const lastInteractedWithNodeWidthDivisions = Math.max(
2420
- lastInteractedWithNodeScopedInputTypes.length + 1,
2421
- 1
2422
- );
2423
- position = [
2424
- lastInteractedWithNode.position[0] + CONFIGURABLE_NODE_SIZE[0] / lastInteractedWithNodeWidthDivisions * (scopedConnectionIndex + 1) - nodeSize[0] / 2,
2425
- lastInteractedWithNode.position[1] + PUSH_NODES_OFFSET
2426
- ];
2427
- } else {
2428
- let pushOffset = PUSH_NODES_OFFSET;
2429
- if (!!lastInteractedWithNodeInputTypes.find((input) => input !== NodeConnectionTypes.Main)) {
2430
- pushOffset += 140;
2431
- }
2432
- position = [
2433
- lastInteractedWithNode.position[0] + pushOffset,
2434
- lastInteractedWithNode.position[1] + yOffset
2435
- ];
2436
- }
2437
- }
2438
- }
2439
- if (!position) {
2440
- if (nodeTypesStore.isTriggerNode(node.type) && triggerNodes.value.length === 0) {
2441
- position = [0, 0];
2442
- } else {
2443
- position = lastClickPosition.value;
2444
- }
2445
- }
2446
- return getNewNodePosition(workflowsStore.allNodes, position, pushOffsets);
2447
- }
2448
- function resolveNodeName(node) {
2449
- const localizedName = i18n2.localizeNodeName(node.name, node.type);
2450
- node.name = uniqueNodeName(localizedName);
2451
- }
2452
- function resolveNodeWebhook(node, nodeTypeDescription) {
2453
- if (nodeTypeDescription.webhooks?.length && !node.webhookId) {
2454
- nodeHelpers.assignWebhookId(node);
2455
- }
2456
- if ([WEBHOOK_NODE_TYPE, FORM_TRIGGER_NODE_TYPE, MCP_TRIGGER_NODE_TYPE].includes(node.type) && node.parameters.path === "") {
2457
- node.parameters.path = node.webhookId;
2458
- }
2459
- }
2460
- function shiftDownstreamNodesPosition(sourceNodeName, margin, { trackHistory = false }) {
2461
- const sourceNode = workflowsStore.nodesByName[sourceNodeName];
2462
- const checkNodes = workflowHelpers.getConnectedNodes(
2463
- "downstream",
2464
- editableWorkflowObject.value,
2465
- sourceNodeName
2466
- );
2467
- for (const nodeName of checkNodes) {
2468
- const node = workflowsStore.nodesByName[nodeName];
2469
- if (node.position[0] < sourceNode.position[0]) {
2470
- continue;
2471
- }
2472
- updateNodePosition(
2473
- node.id,
2474
- {
2475
- x: node.position[0] + margin,
2476
- y: node.position[1]
2477
- },
2478
- { trackHistory }
2479
- );
2480
- }
2481
- }
2482
- function createConnection(connection, { trackHistory = false, keepPristine = false } = {}) {
2483
- const sourceNode = workflowsStore.getNodeById(connection.source);
2484
- const targetNode = workflowsStore.getNodeById(connection.target);
2485
- if (!sourceNode || !targetNode) {
2486
- return;
2487
- }
2488
- if (trackHistory) {
2489
- historyStore.pushCommandToUndo(
2490
- new AddConnectionCommand(
2491
- mapCanvasConnectionToLegacyConnection(sourceNode, targetNode, connection),
2492
- Date.now()
2493
- )
2494
- );
2495
- }
2496
- const mappedConnection = mapCanvasConnectionToLegacyConnection(
2497
- sourceNode,
2498
- targetNode,
2499
- connection
2500
- );
2501
- if (!isConnectionAllowed(sourceNode, targetNode, mappedConnection[0], mappedConnection[1])) {
2502
- return;
2503
- }
2504
- workflowsStore.addConnection({
2505
- connection: mappedConnection
2506
- });
2507
- void nextTick(() => {
2508
- nodeHelpers.updateNodeInputIssues(sourceNode);
2509
- nodeHelpers.updateNodeInputIssues(targetNode);
2510
- });
2511
- if (!keepPristine) {
2512
- uiStore.stateIsDirty = true;
2513
- }
2514
- }
2515
- function revertCreateConnection(connection) {
2516
- const sourceNodeName = connection[0].node;
2517
- const sourceNode = workflowsStore.getNodeByName(sourceNodeName);
2518
- const targetNodeName = connection[1].node;
2519
- const targetNode = workflowsStore.getNodeByName(targetNodeName);
2520
- if (!sourceNode || !targetNode) {
2521
- return;
2522
- }
2523
- deleteConnection(mapLegacyConnectionToCanvasConnection(sourceNode, targetNode, connection));
2524
- }
2525
- function deleteConnectionsByNodeId(targetNodeId, { trackHistory = false, trackBulk = true } = {}) {
2526
- const targetNode = workflowsStore.getNodeById(targetNodeId);
2527
- if (!targetNode) {
2528
- return;
2529
- }
2530
- if (trackHistory && trackBulk) {
2531
- historyStore.startRecordingUndo();
2532
- }
2533
- const connections = workflowsStore.workflow.connections;
2534
- for (const nodeName of Object.keys(connections)) {
2535
- const node = workflowsStore.getNodeByName(nodeName);
2536
- if (!node) {
2537
- continue;
2538
- }
2539
- for (const type of Object.keys(connections[nodeName])) {
2540
- for (const index of Object.keys(connections[nodeName][type])) {
2541
- const connectionsToDelete = connections[nodeName][type][parseInt(index, 10)] ?? [];
2542
- for (const connectionIndex of Object.keys(connectionsToDelete)) {
2543
- const connectionData = connectionsToDelete[parseInt(connectionIndex, 10)];
2544
- if (!connectionData) {
2545
- continue;
2546
- }
2547
- const connectionDataNode = workflowsStore.getNodeByName(connectionData.node);
2548
- if (connectionDataNode && (connectionDataNode.id === targetNode.id || node.name === targetNode.name)) {
2549
- deleteConnection(
2550
- {
2551
- source: node.id,
2552
- sourceHandle: createCanvasConnectionHandleString({
2553
- mode: CanvasConnectionMode.Output,
2554
- type,
2555
- index: parseInt(index, 10)
2556
- }),
2557
- target: connectionDataNode.id,
2558
- targetHandle: createCanvasConnectionHandleString({
2559
- mode: CanvasConnectionMode.Input,
2560
- type: connectionData.type,
2561
- index: connectionData.index
2562
- })
2563
- },
2564
- { trackHistory, trackBulk: false }
2565
- );
2566
- }
2567
- }
2568
- }
2569
- }
2570
- }
2571
- delete workflowsStore.workflow.connections[targetNode.name];
2572
- if (trackHistory && trackBulk) {
2573
- historyStore.stopRecordingUndo();
2574
- }
2575
- }
2576
- function deleteConnection(connection, { trackHistory = false, trackBulk = true } = {}) {
2577
- const sourceNode = workflowsStore.getNodeById(connection.source);
2578
- const targetNode = workflowsStore.getNodeById(connection.target);
2579
- if (!sourceNode || !targetNode) {
2580
- return;
2581
- }
2582
- const mappedConnection = mapCanvasConnectionToLegacyConnection(
2583
- sourceNode,
2584
- targetNode,
2585
- connection
2586
- );
2587
- if (trackHistory && trackBulk) {
2588
- historyStore.startRecordingUndo();
2589
- }
2590
- workflowsStore.removeConnection({
2591
- connection: mappedConnection
2592
- });
2593
- if (trackHistory) {
2594
- historyStore.pushCommandToUndo(new RemoveConnectionCommand(mappedConnection, Date.now()));
2595
- if (trackBulk) {
2596
- historyStore.stopRecordingUndo();
2597
- }
2598
- }
2599
- }
2600
- function revertDeleteConnection(connection) {
2601
- workflowsStore.addConnection({
2602
- connection
2603
- });
2604
- }
2605
- function revalidateNodeConnections(id, connectionMode) {
2606
- const node = workflowsStore.getNodeById(id);
2607
- const isInput = connectionMode === CanvasConnectionMode.Input;
2608
- if (!node) {
2609
- return;
2610
- }
2611
- const nodeType = nodeTypesStore.getNodeType(node.type, node.typeVersion);
2612
- if (!nodeType) {
2613
- return;
2614
- }
2615
- const connections = mapLegacyConnectionsToCanvasConnections(
2616
- workflowsStore.workflow.connections,
2617
- workflowsStore.workflow.nodes
2618
- );
2619
- connections.forEach((connection) => {
2620
- const isRelevantConnection = isInput ? connection.target === id : connection.source === id;
2621
- if (isRelevantConnection) {
2622
- const otherNodeId = isInput ? connection.source : connection.target;
2623
- const otherNode = workflowsStore.getNodeById(otherNodeId);
2624
- if (!otherNode || !connection.data) {
2625
- return;
2626
- }
2627
- const [firstNode, secondNode] = isInput ? [otherNode, node] : [node, otherNode];
2628
- if (!isConnectionAllowed(
2629
- firstNode,
2630
- secondNode,
2631
- connection.data.source,
2632
- connection.data.target
2633
- )) {
2634
- void nextTick(() => deleteConnection(connection));
2635
- }
2636
- }
2637
- });
2638
- }
2639
- function revalidateNodeInputConnections(id) {
2640
- return revalidateNodeConnections(id, CanvasConnectionMode.Input);
2641
- }
2642
- function revalidateNodeOutputConnections(id) {
2643
- return revalidateNodeConnections(id, CanvasConnectionMode.Output);
2644
- }
2645
- function isConnectionAllowed(sourceNode, targetNode, sourceConnection, targetConnection) {
2646
- const blocklist = [STICKY_NODE_TYPE];
2647
- if (sourceConnection.type !== targetConnection.type) {
2648
- return false;
2649
- }
2650
- if (blocklist.includes(sourceNode.type) || blocklist.includes(targetNode.type)) {
2651
- return false;
2652
- }
2653
- const sourceNodeType = nodeTypesStore.getNodeType(sourceNode.type, sourceNode.typeVersion);
2654
- const sourceWorkflowNode = editableWorkflowObject.value.getNode(sourceNode.name);
2655
- if (!sourceWorkflowNode) {
2656
- return false;
2657
- }
2658
- let sourceNodeOutputs = [];
2659
- if (sourceNodeType) {
2660
- sourceNodeOutputs = getNodeOutputs(
2661
- editableWorkflowObject.value,
2662
- sourceWorkflowNode,
2663
- sourceNodeType
2664
- ) || [];
2665
- }
2666
- const sourceNodeHasOutputConnectionOfType = !!sourceNodeOutputs.find((output) => {
2667
- const outputType = typeof output === "string" ? output : output.type;
2668
- return outputType === sourceConnection.type;
2669
- });
2670
- const sourceNodeHasOutputConnectionPortOfType = sourceConnection.index < sourceNodeOutputs.length;
2671
- if (!sourceNodeHasOutputConnectionOfType || !sourceNodeHasOutputConnectionPortOfType) {
2672
- return false;
2673
- }
2674
- const targetNodeType = nodeTypesStore.getNodeType(targetNode.type, targetNode.typeVersion);
2675
- const targetWorkflowNode = editableWorkflowObject.value.getNode(targetNode.name);
2676
- if (!targetWorkflowNode) {
2677
- return false;
2678
- }
2679
- let targetNodeInputs = [];
2680
- if (targetNodeType) {
2681
- targetNodeInputs = getNodeInputs(
2682
- editableWorkflowObject.value,
2683
- targetWorkflowNode,
2684
- targetNodeType
2685
- ) || [];
2686
- }
2687
- const targetNodeHasInputConnectionOfType = !!targetNodeInputs.find((input) => {
2688
- const inputType = typeof input === "string" ? input : input.type;
2689
- if (inputType !== targetConnection.type) return false;
2690
- const filter = typeof input === "object" && "filter" in input ? input.filter : void 0;
2691
- if (filter?.nodes.length && !filter.nodes.includes(sourceNode.type)) {
2692
- toast.showToast({
2693
- title: i18n2.baseText("nodeView.showError.nodeNodeCompatible.title"),
2694
- message: i18n2.baseText("nodeView.showError.nodeNodeCompatible.message", {
2695
- interpolate: { sourceNodeName: sourceNode.name, targetNodeName: targetNode.name }
2696
- }),
2697
- type: "error",
2698
- duration: 5e3
2699
- });
2700
- return false;
2701
- }
2702
- return true;
2703
- });
2704
- const targetNodeHasInputConnectionPortOfType = targetConnection.index < targetNodeInputs.length;
2705
- return targetNodeHasInputConnectionOfType && targetNodeHasInputConnectionPortOfType;
2706
- }
2707
- async function addConnections(connections, { trackBulk = true, trackHistory = false, keepPristine = false } = {}) {
2708
- await nextTick();
2709
- if (trackBulk && trackHistory) {
2710
- historyStore.startRecordingUndo();
2711
- }
2712
- for (const connection of connections) {
2713
- createConnection(connection, { trackHistory, keepPristine });
2714
- }
2715
- if (trackBulk && trackHistory) {
2716
- historyStore.stopRecordingUndo();
2717
- }
2718
- if (!keepPristine) {
2719
- uiStore.stateIsDirty = true;
2720
- }
2721
- }
2722
- function resetWorkspace() {
2723
- nodeCreatorStore.setNodeCreatorState({ createNodeActive: false });
2724
- nodeCreatorStore.setShowScrim(false);
2725
- if (workflowsStore.executionWaitingForWebhook) {
2726
- try {
2727
- void workflowsStore.removeTestWebhook(workflowsStore.workflowId);
2728
- } catch (error) {
2729
- }
2730
- }
2731
- workflowsStore.resetWorkflow();
2732
- workflowsStore.resetState();
2733
- workflowsStore.currentWorkflowExecutions = [];
2734
- workflowsStore.setActiveExecutionId(void 0);
2735
- uiStore.resetLastInteractedWith();
2736
- uiStore.stateIsDirty = false;
2737
- executionsStore.activeExecution = null;
2738
- nodeHelpers.credentialsUpdated.value = false;
2739
- }
2740
- function initializeWorkspace(data) {
2741
- workflowHelpers.initState(data);
2742
- data.nodes.forEach((node) => {
2743
- const nodeTypeDescription = requireNodeTypeDescription(node.type, node.typeVersion);
2744
- nodeHelpers.matchCredentials(node);
2745
- resolveNodeParameters(node, nodeTypeDescription);
2746
- resolveNodeWebhook(node, nodeTypeDescription);
2747
- });
2748
- workflowsStore.setNodes(data.nodes);
2749
- workflowsStore.setConnections(data.connections);
2750
- }
2751
- function removeUnknownCredentials(workflow) {
2752
- if (!workflow?.nodes) return;
2753
- for (const node of workflow.nodes) {
2754
- if (!node.credentials) continue;
2755
- for (const [name, credential] of Object.entries(node.credentials)) {
2756
- if (typeof credential === "string" || credential.id === null) continue;
2757
- if (!credentialsStore.getCredentialById(credential.id)) {
2758
- delete node.credentials[name];
2759
- }
2760
- }
2761
- }
2762
- }
2763
- async function addImportedNodesToWorkflow(data, { trackBulk = true, trackHistory = false } = {}) {
2764
- const nodeNameTable = {};
2765
- const newNodeNames = /* @__PURE__ */ new Set();
2766
- if (!data.nodes) {
2767
- throw new Error(i18n2.baseText("nodeView.noNodesGivenToAdd"));
2768
- }
2769
- const nodeTypesCount = workflowHelpers.getNodeTypesMaxCount();
2770
- let oldName;
2771
- let newName;
2772
- const createNodes = [];
2773
- await nodeHelpers.loadNodesProperties(
2774
- data.nodes.map((node) => ({ name: node.type, version: node.typeVersion }))
2775
- );
2776
- data.nodes.forEach((node) => {
2777
- if (nodeTypesCount[node.type] !== void 0) {
2778
- if (nodeTypesCount[node.type].exist >= nodeTypesCount[node.type].max) {
2779
- nodeNameTable[node.name] = nodeTypesCount[node.type].nodeNames[0];
2780
- return;
2781
- } else {
2782
- nodeTypesCount[node.type].exist += 1;
2783
- }
2784
- }
2785
- oldName = node.name;
2786
- const localized = i18n2.localizeNodeName(node.name, node.type);
2787
- newName = uniqueNodeName(localized, Array.from(newNodeNames));
2788
- newNodeNames.add(newName);
2789
- nodeNameTable[oldName] = newName;
2790
- createNodes.push(node);
2791
- });
2792
- const newConnections = {};
2793
- const currentConnections = data.connections ?? {};
2794
- const createNodeNames = createNodes.map((node) => node.name);
2795
- let sourceNode, type, sourceIndex, connectionIndex, connectionData;
2796
- for (sourceNode of Object.keys(currentConnections)) {
2797
- if (!createNodeNames.includes(sourceNode)) {
2798
- continue;
2799
- }
2800
- const connection = {};
2801
- for (type of Object.keys(currentConnections[sourceNode])) {
2802
- connection[type] = [];
2803
- for (sourceIndex = 0; sourceIndex < currentConnections[sourceNode][type].length; sourceIndex++) {
2804
- const nodeSourceConnections = [];
2805
- const connectionsToCheck = currentConnections[sourceNode][type][sourceIndex];
2806
- if (connectionsToCheck) {
2807
- for (connectionIndex = 0; connectionIndex < connectionsToCheck.length; connectionIndex++) {
2808
- connectionData = connectionsToCheck[connectionIndex];
2809
- if (!createNodeNames.includes(connectionData.node)) {
2810
- continue;
2811
- }
2812
- nodeSourceConnections.push(connectionData);
2813
- }
2814
- }
2815
- connection[type].push(nodeSourceConnections);
2816
- }
2817
- }
2818
- newConnections[sourceNode] = connection;
2819
- }
2820
- const tempWorkflow = workflowsStore.getWorkflow(createNodes, newConnections);
2821
- for (oldName in nodeNameTable) {
2822
- if (oldName === nodeNameTable[oldName]) {
2823
- continue;
2824
- }
2825
- tempWorkflow.renameNode(oldName, nodeNameTable[oldName]);
2826
- }
2827
- if (data.pinData) {
2828
- let pinDataSuccess = true;
2829
- for (const nodeName of Object.keys(data.pinData)) {
2830
- if (!pinDataSuccess) {
2831
- toast.showError(
2832
- new Error(i18n2.baseText("ndv.pinData.error.tooLarge.description")),
2833
- i18n2.baseText("ndv.pinData.error.tooLarge.title")
2834
- );
2835
- continue;
2836
- }
2837
- const node = tempWorkflow.nodes[nodeNameTable[nodeName]];
2838
- try {
2839
- const pinnedDataForNode = usePinnedData(node);
2840
- pinnedDataForNode.setData(data.pinData[nodeName], "add-nodes");
2841
- pinDataSuccess = true;
2842
- } catch (error) {
2843
- pinDataSuccess = false;
2844
- console.error(error);
2845
- }
2846
- }
2847
- }
2848
- if (trackBulk && trackHistory) {
2849
- historyStore.startRecordingUndo();
2850
- }
2851
- await addNodes(Object.values(tempWorkflow.nodes), { trackBulk: false, trackHistory });
2852
- await addConnections(
2853
- mapLegacyConnectionsToCanvasConnections(
2854
- tempWorkflow.connectionsBySourceNode,
2855
- Object.values(tempWorkflow.nodes)
2856
- ),
2857
- { trackBulk: false, trackHistory }
2858
- );
2859
- if (trackBulk && trackHistory) {
2860
- historyStore.stopRecordingUndo();
2861
- }
2862
- uiStore.stateIsDirty = true;
2863
- return {
2864
- nodes: Object.values(tempWorkflow.nodes),
2865
- connections: tempWorkflow.connectionsBySourceNode
2866
- };
2867
- }
2868
- async function importWorkflowData(workflowData, source, importTags = true, { trackBulk = true, trackHistory = true } = {}) {
2869
- uiStore.resetLastInteractedWith();
2870
- if (!workflowData.hasOwnProperty("nodes") || !workflowData.hasOwnProperty("connections")) {
2871
- return {};
2872
- }
2873
- try {
2874
- const nodeIdMap = {};
2875
- if (workflowData.nodes) {
2876
- const nodeNames = new Set(workflowData.nodes.map((node) => node.name));
2877
- workflowData.nodes.forEach((node) => {
2878
- if (!node.name) {
2879
- const nodeType = nodeTypesStore.getNodeType(node.type);
2880
- const newName = uniqueNodeName(
2881
- nodeType?.displayName ?? node.type,
2882
- Array.from(nodeNames)
2883
- );
2884
- node.name = newName;
2885
- nodeNames.add(newName);
2886
- }
2887
- if (node.webhookId && UPDATE_WEBHOOK_ID_NODE_TYPES.includes(node.type)) {
2888
- const isDuplicate = Object.values(workflowHelpers.getCurrentWorkflow().nodes).some(
2889
- (n) => n.webhookId === node.webhookId
2890
- );
2891
- if (isDuplicate) {
2892
- nodeHelpers.assignWebhookId(node);
2893
- if (node.parameters.path) {
2894
- node.parameters.path = node.webhookId;
2895
- } else if (node.parameters.options.path) {
2896
- node.parameters.options.path = node.webhookId;
2897
- }
2898
- }
2899
- }
2900
- if (node.id) {
2901
- const previousId = node.id;
2902
- const newId = nodeHelpers.assignNodeId(node);
2903
- nodeIdMap[newId] = previousId;
2904
- } else {
2905
- nodeHelpers.assignNodeId(node);
2906
- }
2907
- });
2908
- }
2909
- removeUnknownCredentials(workflowData);
2910
- const nodeGraph = JSON.stringify(
2911
- generateNodesGraph(
2912
- workflowData,
2913
- workflowHelpers.getNodeTypes(),
2914
- {
2915
- nodeIdMap,
2916
- sourceInstanceId: workflowData.meta && workflowData.meta.instanceId !== rootStore.instanceId ? workflowData.meta.instanceId : "",
2917
- isCloudDeployment: settingsStore.isCloudDeployment
2918
- }
2919
- ).nodeGraph
2920
- );
2921
- if (source === "paste") {
2922
- telemetry.track("User pasted nodes", {
2923
- workflow_id: workflowsStore.workflowId,
2924
- node_graph_string: nodeGraph
2925
- });
2926
- } else if (source === "duplicate") {
2927
- telemetry.track("User duplicated nodes", {
2928
- workflow_id: workflowsStore.workflowId,
2929
- node_graph_string: nodeGraph
2930
- });
2931
- } else {
2932
- telemetry.track("User imported workflow", {
2933
- source,
2934
- workflow_id: workflowsStore.workflowId,
2935
- node_graph_string: nodeGraph
2936
- });
2937
- }
2938
- workflowHelpers.updateNodePositions(
2939
- workflowData,
2940
- getNewNodePosition(editableWorkflow.value.nodes, lastClickPosition.value)
2941
- );
2942
- await addImportedNodesToWorkflow(workflowData, { trackBulk, trackHistory });
2943
- if (importTags && settingsStore.areTagsEnabled && Array.isArray(workflowData.tags)) {
2944
- await importWorkflowTags(workflowData);
2945
- }
2946
- return workflowData;
2947
- } catch (error) {
2948
- toast.showError(error, i18n2.baseText("nodeView.showError.importWorkflowData.title"));
2949
- return {};
2950
- }
2951
- }
2952
- async function importWorkflowTags(workflowData) {
2953
- const allTags = await tagsStore.fetchAll();
2954
- const tagNames = new Set(allTags.map((tag) => tag.name));
2955
- const workflowTags = workflowData.tags;
2956
- const notFound = workflowTags.filter((tag) => !tagNames.has(tag.name));
2957
- const creatingTagPromises = [];
2958
- for (const tag of notFound) {
2959
- const creationPromise = tagsStore.create(tag.name).then((newTag) => {
2960
- allTags.push(newTag);
2961
- return newTag;
2962
- });
2963
- creatingTagPromises.push(creationPromise);
2964
- }
2965
- await Promise.all(creatingTagPromises);
2966
- const tagIds = workflowTags.reduce((accu, imported) => {
2967
- const tag = allTags.find((t) => t.name === imported.name);
2968
- if (tag) {
2969
- accu.push(tag.id);
2970
- }
2971
- return accu;
2972
- }, []);
2973
- workflowsStore.addWorkflowTagIds(tagIds);
2974
- }
2975
- async function fetchWorkflowDataFromUrl(url) {
2976
- let workflowData;
2977
- canvasStore.startLoading();
2978
- try {
2979
- workflowData = await workflowsStore.getWorkflowFromUrl(url);
2980
- } catch (error) {
2981
- toast.showError(error, i18n2.baseText("nodeView.showError.getWorkflowDataFromUrl.title"));
2982
- return;
2983
- } finally {
2984
- canvasStore.stopLoading();
2985
- }
2986
- return workflowData;
2987
- }
2988
- function getNodesToSave(nodes) {
2989
- const data = {
2990
- nodes: [],
2991
- connections: {},
2992
- pinData: {}
2993
- };
2994
- const exportedNodeNames = /* @__PURE__ */ new Set();
2995
- for (const node of nodes) {
2996
- const nodeSaveData = workflowHelpers.getNodeDataToSave(node);
2997
- const pinDataForNode = workflowsStore.pinDataByNodeName(node.name);
2998
- if (pinDataForNode) {
2999
- data.pinData[node.name] = pinDataForNode;
3000
- }
3001
- if (nodeSaveData.credentials && settingsStore.isEnterpriseFeatureEnabled[EnterpriseEditionFeature.Sharing]) {
3002
- nodeSaveData.credentials = filterAllowedCredentials(
3003
- nodeSaveData.credentials,
3004
- workflowsStore.usedCredentials
3005
- );
3006
- }
3007
- data.nodes.push(nodeSaveData);
3008
- exportedNodeNames.add(node.name);
3009
- }
3010
- data.connections = getConnectionsForNodes(data.nodes, exportedNodeNames);
3011
- workflowHelpers.removeForeignCredentialsFromWorkflow(data, credentialsStore.allCredentials);
3012
- return data;
3013
- }
3014
- function filterAllowedCredentials(credentials, usedCredentials) {
3015
- return Object.fromEntries(
3016
- Object.entries(credentials).filter(([, credential]) => {
3017
- return credential.id && (!usedCredentials[credential.id] || usedCredentials[credential.id]?.currentUserHasAccess);
3018
- })
3019
- );
3020
- }
3021
- function getConnectionsForNodes(nodes, includeNodeNames) {
3022
- const connections = {};
3023
- for (const node of nodes) {
3024
- const outgoingConnections = workflowsStore.outgoingConnectionsByNodeName(node.name);
3025
- if (!Object.keys(outgoingConnections).length) continue;
3026
- const filteredConnections = filterConnectionsByNodes(outgoingConnections, includeNodeNames);
3027
- if (Object.keys(filteredConnections).length) {
3028
- connections[node.name] = filteredConnections;
3029
- }
3030
- }
3031
- return connections;
3032
- }
3033
- function filterConnectionsByNodes(connections, includeNodeNames) {
3034
- const filteredConnections = {};
3035
- for (const [type, typeConnections] of Object.entries(connections)) {
3036
- const validConnections = typeConnections.map(
3037
- (sourceConnections) => (sourceConnections ?? []).filter((connection) => includeNodeNames.has(connection.node))
3038
- );
3039
- if (validConnections.length) {
3040
- filteredConnections[type] = validConnections;
3041
- }
3042
- }
3043
- return filteredConnections;
3044
- }
3045
- async function duplicateNodes(ids) {
3046
- const workflowData = deepCopy(getNodesToSave(workflowsStore.getNodesByIds(ids)));
3047
- const result = await importWorkflowData(workflowData, "duplicate", false);
3048
- return result.nodes?.map((node) => node.id).filter(isPresent) ?? [];
3049
- }
3050
- async function copyNodes(ids) {
3051
- const workflowData = deepCopy(getNodesToSave(workflowsStore.getNodesByIds(ids)));
3052
- workflowData.meta = {
3053
- ...workflowData.meta,
3054
- ...workflowsStore.workflow.meta,
3055
- instanceId: rootStore.instanceId
3056
- };
3057
- await clipboard.copy(JSON.stringify(workflowData, null, 2));
3058
- telemetry.track("User copied nodes", {
3059
- node_types: workflowData.nodes.map((node) => node.type),
3060
- workflow_id: workflowsStore.workflowId
3061
- });
3062
- }
3063
- async function cutNodes(ids) {
3064
- await copyNodes(ids);
3065
- deleteNodes(ids);
3066
- }
3067
- async function openExecution(executionId) {
3068
- let data;
3069
- try {
3070
- data = await workflowsStore.getExecution(executionId);
3071
- } catch (error) {
3072
- toast.showError(error, i18n2.baseText("nodeView.showError.openExecution.title"));
3073
- return;
3074
- }
3075
- if (data === void 0) {
3076
- throw new Error(`Execution with id "${executionId}" could not be found!`);
3077
- }
3078
- initializeWorkspace(data.workflowData);
3079
- workflowsStore.setWorkflowExecutionData(data);
3080
- if (!["manual", "evaluation"].includes(data.mode)) {
3081
- workflowsStore.setWorkflowPinData({});
3082
- }
3083
- uiStore.stateIsDirty = false;
3084
- return data;
3085
- }
3086
- async function toggleChatOpen(source, isOpen) {
3087
- const workflow = workflowsStore.getCurrentWorkflow();
3088
- workflowsStore.toggleLogsPanelOpen(isOpen);
3089
- const payload = {
3090
- workflow_id: workflow.id,
3091
- button_type: source
3092
- };
3093
- void externalHooks.run("nodeView.onOpenChat", payload);
3094
- telemetry.track("User clicked chat open button", payload);
3095
- }
3096
- async function importTemplate({
3097
- id,
3098
- name,
3099
- workflow
3100
- }) {
3101
- const convertedNodes = workflow.nodes?.map(workflowsStore.convertTemplateNodeToNodeUi);
3102
- if (workflow.connections) {
3103
- workflowsStore.setConnections(workflow.connections);
3104
- }
3105
- await addNodes(convertedNodes ?? []);
3106
- await workflowsStore.getNewWorkflowData(name, projectsStore.currentProjectId);
3107
- workflowsStore.addToWorkflowMetadata({ templateId: `${id}` });
3108
- }
3109
- return {
3110
- lastClickPosition,
3111
- editableWorkflow,
3112
- editableWorkflowObject,
3113
- triggerNodes,
3114
- requireNodeTypeDescription,
3115
- addNodes,
3116
- addNode,
3117
- resolveNodePosition,
3118
- revertAddNode,
3119
- updateNodesPosition,
3120
- updateNodePosition,
3121
- tidyUp,
3122
- revertUpdateNodePosition,
3123
- setNodeActive,
3124
- setNodeActiveByName,
3125
- clearNodeActive,
3126
- setNodeSelected,
3127
- toggleNodesDisabled,
3128
- revertToggleNodeDisabled,
3129
- toggleNodesPinned,
3130
- setNodeParameters,
3131
- renameNode,
3132
- revertRenameNode,
3133
- deleteNode,
3134
- deleteNodes,
3135
- copyNodes,
3136
- cutNodes,
3137
- duplicateNodes,
3138
- getNodesToSave,
3139
- revertDeleteNode,
3140
- addConnections,
3141
- createConnection,
3142
- revertCreateConnection,
3143
- deleteConnection,
3144
- revertDeleteConnection,
3145
- deleteConnectionsByNodeId,
3146
- revalidateNodeInputConnections,
3147
- revalidateNodeOutputConnections,
3148
- isConnectionAllowed,
3149
- filterConnectionsByNodes,
3150
- connectAdjacentNodes,
3151
- importWorkflowData,
3152
- fetchWorkflowDataFromUrl,
3153
- resetWorkspace,
3154
- initializeWorkspace,
3155
- resolveNodeWebhook,
3156
- openExecution,
3157
- toggleChatOpen,
3158
- importTemplate
3159
- };
3160
- }
3161
- export {
3162
- AINodesView as A,
3163
- RegularView as R,
3164
- TriggerView as T,
3165
- useNodeCreatorStore as a,
3166
- useCanvasOperations as b,
3167
- createCanvasConnectionHandleString as c,
3168
- capitalize as d,
3169
- checkOverlap as e,
3170
- mapLegacyConnectionsToCanvasConnections as f,
3171
- formatTriggerActionName as g,
3172
- useViewStacks as h,
3173
- insertSpacersBetweenEndpoints as i,
3174
- camelCase as j,
3175
- useKeyboardNavigation as k,
3176
- AIView as l,
3177
- mapLegacyEndpointsToCanvasConnectionPort as m,
3178
- flattenCreateElements as n,
3179
- parseCanvasConnectionHandleString as p,
3180
- sortNodeCreateElements as s,
3181
- transformNodeType as t,
3182
- upperFirst as u
3183
- };