From 55b97c47357d57ec8fc488ac33fe0018a08da65d Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Mon, 1 Apr 2024 11:52:06 +0300 Subject: [PATCH 1/4] :zap: fix --- .../src/composables/useRunWorkflow.ts | 21 +++++++++++++++++++ packages/editor-ui/src/views/NodeView.vue | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/packages/editor-ui/src/composables/useRunWorkflow.ts b/packages/editor-ui/src/composables/useRunWorkflow.ts index fa2dbd3d0d236..1fd0c0fe9cb49 100644 --- a/packages/editor-ui/src/composables/useRunWorkflow.ts +++ b/packages/editor-ui/src/composables/useRunWorkflow.ts @@ -247,6 +247,27 @@ export function useRunWorkflow(options: { router: ReturnType } } } } + + //if no destination node is specified + //and execution is not triggered from chat + //and there are other triggers in the workflow + //disable chat trigger node to avoid modal opening and webhook creation + if ( + !options.destinationNode && + options.source !== 'RunData.ManualChatMessage' && + workflowData.nodes.some((node) => node.type === CHAT_TRIGGER_NODE_TYPE) + ) { + const otherTriggers = workflowData.nodes.filter( + (node) => + node.type !== CHAT_TRIGGER_NODE_TYPE && + node.type.toLowerCase().includes('trigger') && + !node.disabled, + ); + if (otherTriggers.length) { + workflowData.nodes.find((node) => node.type === CHAT_TRIGGER_NODE_TYPE)!.disabled = true; + } + } + const startNodes: StartNodeData[] = startNodeNames.map((name) => { // Find for each start node the source data let sourceData = get(runData, [name, 0, 'source', 0], null); diff --git a/packages/editor-ui/src/views/NodeView.vue b/packages/editor-ui/src/views/NodeView.vue index 202389be66a56..47863f5c196c6 100644 --- a/packages/editor-ui/src/views/NodeView.vue +++ b/packages/editor-ui/src/views/NodeView.vue @@ -728,6 +728,12 @@ export default defineComponent({ return this.containsChatNodes && this.triggerNodes.length === 1; }, isExecutionDisabled(): boolean { + if ( + this.containsChatNodes && + this.triggerNodes.every((node) => node.disabled || node.type === CHAT_TRIGGER_NODE_TYPE) + ) { + return true; + } return !this.containsTrigger || this.allTriggersDisabled; }, getNodeViewOffsetPosition(): XYPosition { From bbdd6be4e1a274031eeec8376ec68fd900751820 Mon Sep 17 00:00:00 2001 From: Oleg Ivaniv Date: Mon, 1 Apr 2024 12:14:22 +0200 Subject: [PATCH 2/4] Fix linting warning Signed-off-by: Oleg Ivaniv --- packages/editor-ui/src/composables/useRunWorkflow.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/editor-ui/src/composables/useRunWorkflow.ts b/packages/editor-ui/src/composables/useRunWorkflow.ts index 1fd0c0fe9cb49..6d642b3436a89 100644 --- a/packages/editor-ui/src/composables/useRunWorkflow.ts +++ b/packages/editor-ui/src/composables/useRunWorkflow.ts @@ -263,8 +263,14 @@ export function useRunWorkflow(options: { router: ReturnType } node.type.toLowerCase().includes('trigger') && !node.disabled, ); + if (otherTriggers.length) { - workflowData.nodes.find((node) => node.type === CHAT_TRIGGER_NODE_TYPE)!.disabled = true; + const chatTriggerNode = workflowData.nodes.find( + (node) => node.type === CHAT_TRIGGER_NODE_TYPE, + ); + if (chatTriggerNode) { + chatTriggerNode.disabled = true; + } } } From f15134b8b8cb1965ef052247a68bc71f64024adc Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Mon, 1 Apr 2024 16:05:29 +0300 Subject: [PATCH 3/4] :zap: e2e tests --- cypress/composables/workflow.ts | 16 +++++++- cypress/e2e/30-langchain.cy.ts | 70 ++++++++++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/cypress/composables/workflow.ts b/cypress/composables/workflow.ts index 1518805c6be41..1aa469b19458f 100644 --- a/cypress/composables/workflow.ts +++ b/cypress/composables/workflow.ts @@ -48,6 +48,12 @@ export function getNodeByName(name: string) { return cy.getByTestId('canvas-node').filter(`[data-name="${name}"]`).eq(0); } +export function disableNode(name: string) { + const target = getNodeByName(name); + target.rightclick(name ? 'center' : 'topLeft', { force: true }); + cy.getByTestId(`context-menu-item-toggle_activation`).click(); +} + export function getConnectionBySourceAndTarget(source: string, target: string) { return cy .get('.jtk-connector') @@ -110,14 +116,20 @@ export function addSupplementalNodeToParent( ) { getAddInputEndpointByType(parentNodeName, endpointType).click({ force: true }); if (exactMatch) { - getNodeCreatorItems().contains(new RegExp("^" + nodeName + "$", "g")).click(); + getNodeCreatorItems() + .contains(new RegExp('^' + nodeName + '$', 'g')) + .click(); } else { getNodeCreatorItems().contains(nodeName).click(); } getConnectionBySourceAndTarget(parentNodeName, nodeName).should('exist'); } -export function addLanguageModelNodeToParent(nodeName: string, parentNodeName: string, exactMatch = false) { +export function addLanguageModelNodeToParent( + nodeName: string, + parentNodeName: string, + exactMatch = false, +) { addSupplementalNodeToParent(nodeName, 'ai_languageModel', parentNodeName, exactMatch); } diff --git a/cypress/e2e/30-langchain.cy.ts b/cypress/e2e/30-langchain.cy.ts index 6b69d3fb65651..8feb448c385e5 100644 --- a/cypress/e2e/30-langchain.cy.ts +++ b/cypress/e2e/30-langchain.cy.ts @@ -9,6 +9,7 @@ import { AI_TOOL_CODE_NODE_NAME, AI_TOOL_WIKIPEDIA_NODE_NAME, BASIC_LLM_CHAIN_NODE_NAME, + EDIT_FIELDS_SET_NODE_NAME, } from './../constants'; import { createMockNodeExecutionData, runMockWorkflowExcution } from '../utils'; import { @@ -17,7 +18,10 @@ import { addNodeToCanvas, addOutputParserNodeToParent, addToolNodeToParent, + clickExecuteWorkflowButton, clickManualChatButton, + disableNode, + getExecuteWorkflowButton, navigateToNewWorkflowPage, openNode, } from '../composables/workflow'; @@ -32,6 +36,7 @@ import { closeManualChatModal, getManualChatDialog, getManualChatMessages, + getManualChatModal, getManualChatModalLogs, getManualChatModalLogsEntries, getManualChatModalLogsTree, @@ -43,13 +48,58 @@ describe('Langchain Integration', () => { navigateToNewWorkflowPage(); }); + it('should not open chat modal', () => { + addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME, true); + addNodeToCanvas(EDIT_FIELDS_SET_NODE_NAME, true); + + clickGetBackToCanvas(); + + addNodeToCanvas(AGENT_NODE_NAME, true, true); + clickGetBackToCanvas(); + + addLanguageModelNodeToParent( + AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, + AGENT_NODE_NAME, + true, + ); + clickGetBackToCanvas(); + + getManualChatModal().should('not.exist'); + clickExecuteWorkflowButton(); + }); + + it('should disable test workflow button', () => { + addNodeToCanvas('Schedule Trigger', true); + addNodeToCanvas(EDIT_FIELDS_SET_NODE_NAME, true); + + clickGetBackToCanvas(); + + addNodeToCanvas(AGENT_NODE_NAME, true, true); + clickGetBackToCanvas(); + + addLanguageModelNodeToParent( + AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, + AGENT_NODE_NAME, + true, + ); + clickGetBackToCanvas(); + + disableNode('Schedule Trigger'); + + getExecuteWorkflowButton().should('be.disabled'); + }); + it('should add nodes to all Agent node input types', () => { addNodeToCanvas(MANUAL_TRIGGER_NODE_NAME, true); addNodeToCanvas(AGENT_NODE_NAME, true, true); toggleParameterCheckboxInputByName('hasOutputParser'); clickGetBackToCanvas(); - addLanguageModelNodeToParent(AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, AGENT_NODE_NAME, true); + addLanguageModelNodeToParent( + AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, + AGENT_NODE_NAME, + true, + ); clickGetBackToCanvas(); addMemoryNodeToParent(AI_MEMORY_WINDOW_BUFFER_MEMORY_NODE_NAME, AGENT_NODE_NAME); @@ -85,7 +135,7 @@ describe('Langchain Integration', () => { addLanguageModelNodeToParent( AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, BASIC_LLM_CHAIN_NODE_NAME, - true + true, ); clickCreateNewCredential(); @@ -98,7 +148,7 @@ describe('Langchain Integration', () => { const inputMessage = 'Hello!'; const outputMessage = 'Hi there! How can I assist you today?'; - clickExecuteNode() + clickExecuteNode(); runMockWorkflowExcution({ trigger: () => sendManualChatMessage(inputMessage), runData: [ @@ -121,7 +171,11 @@ describe('Langchain Integration', () => { addNodeToCanvas(MANUAL_CHAT_TRIGGER_NODE_NAME, true); addNodeToCanvas(AGENT_NODE_NAME, true); - addLanguageModelNodeToParent(AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, AGENT_NODE_NAME, true); + addLanguageModelNodeToParent( + AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, + AGENT_NODE_NAME, + true, + ); clickCreateNewCredential(); setCredentialValues({ @@ -134,7 +188,7 @@ describe('Langchain Integration', () => { const inputMessage = 'Hello!'; const outputMessage = 'Hi there! How can I assist you today?'; - clickExecuteNode() + clickExecuteNode(); runMockWorkflowExcution({ trigger: () => sendManualChatMessage(inputMessage), runData: [ @@ -157,7 +211,11 @@ describe('Langchain Integration', () => { addNodeToCanvas(MANUAL_CHAT_TRIGGER_NODE_NAME, true); addNodeToCanvas(AGENT_NODE_NAME, true); - addLanguageModelNodeToParent(AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, AGENT_NODE_NAME, true); + addLanguageModelNodeToParent( + AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME, + AGENT_NODE_NAME, + true, + ); clickCreateNewCredential(); setCredentialValues({ From 2b8631c585d46229bfbb75f36a72efaff5cc448e Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Mon, 1 Apr 2024 16:10:34 +0300 Subject: [PATCH 4/4] :zap: test fix --- cypress/e2e/30-langchain.cy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/e2e/30-langchain.cy.ts b/cypress/e2e/30-langchain.cy.ts index 8feb448c385e5..9536b3cf60b5a 100644 --- a/cypress/e2e/30-langchain.cy.ts +++ b/cypress/e2e/30-langchain.cy.ts @@ -64,8 +64,8 @@ describe('Langchain Integration', () => { ); clickGetBackToCanvas(); - getManualChatModal().should('not.exist'); clickExecuteWorkflowButton(); + getManualChatModal().should('not.exist'); }); it('should disable test workflow button', () => {