mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-02 07:01:30 -08:00
fix(editor): Partial execution of a workflow with manual chat trigger (#12662)
Co-authored-by: Oleg Ivaniv <me@olegivaniv.com>
This commit is contained in:
parent
174cd44815
commit
2f81b29d34
|
@ -518,4 +518,52 @@ describe('Langchain Integration', () => {
|
|||
|
||||
getRunDataInfoCallout().should('not.exist');
|
||||
});
|
||||
|
||||
it('should execute up to Node 1 when using partial execution', () => {
|
||||
const workflowPage = new WorkflowPage();
|
||||
|
||||
cy.visit(workflowPage.url);
|
||||
cy.createFixtureWorkflow('Test_workflow_chat_partial_execution.json');
|
||||
workflowPage.actions.zoomToFit();
|
||||
|
||||
getManualChatModal().should('not.exist');
|
||||
workflowPage.actions.executeNode('Node 1');
|
||||
|
||||
getManualChatModal().should('exist');
|
||||
sendManualChatMessage('Test');
|
||||
|
||||
getManualChatMessages().should('contain', 'this_my_field_1');
|
||||
cy.getByTestId('refresh-session-button').click();
|
||||
cy.get('button').contains('Reset').click();
|
||||
getManualChatMessages().should('not.exist');
|
||||
|
||||
sendManualChatMessage('Another test');
|
||||
getManualChatMessages().should('contain', 'this_my_field_3');
|
||||
getManualChatMessages().should('contain', 'this_my_field_4');
|
||||
});
|
||||
|
||||
it('should execute up to Node 1 when using partial execution', () => {
|
||||
const workflowPage = new WorkflowPage();
|
||||
const ndv = new NDV();
|
||||
|
||||
cy.visit(workflowPage.url);
|
||||
cy.createFixtureWorkflow('Test_workflow_chat_partial_execution.json');
|
||||
workflowPage.actions.zoomToFit();
|
||||
|
||||
getManualChatModal().should('not.exist');
|
||||
openNode('Node 1');
|
||||
ndv.actions.execute();
|
||||
|
||||
getManualChatModal().should('exist');
|
||||
sendManualChatMessage('Test');
|
||||
|
||||
getManualChatMessages().should('contain', 'this_my_field_1');
|
||||
cy.getByTestId('refresh-session-button').click();
|
||||
cy.get('button').contains('Reset').click();
|
||||
getManualChatMessages().should('not.exist');
|
||||
|
||||
sendManualChatMessage('Another test');
|
||||
getManualChatMessages().should('contain', 'this_my_field_3');
|
||||
getManualChatMessages().should('contain', 'this_my_field_4');
|
||||
});
|
||||
});
|
||||
|
|
77
cypress/fixtures/Test_workflow_chat_partial_execution.json
Normal file
77
cypress/fixtures/Test_workflow_chat_partial_execution.json
Normal file
|
@ -0,0 +1,77 @@
|
|||
{
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"options": {}
|
||||
},
|
||||
"id": "535fd3dd-e78f-4ffa-a085-79723fc81b38",
|
||||
"name": "When chat message received",
|
||||
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
|
||||
"typeVersion": 1.1,
|
||||
"position": [
|
||||
320,
|
||||
-380
|
||||
],
|
||||
"webhookId": "4fb58136-3481-494a-a30f-d9e064dac186"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"mode": "raw",
|
||||
"jsonOutput": "{\n \"this_my_field_1\": \"value\",\n \"this_my_field_2\": 1\n}\n",
|
||||
"options": {}
|
||||
},
|
||||
"id": "78201ec2-6def-40b7-85e5-97b580d7f642",
|
||||
"name": "Node 1",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 3.4,
|
||||
"position": [
|
||||
580,
|
||||
-380
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"mode": "raw",
|
||||
"jsonOutput": "{\n \"this_my_field_3\": \"value\",\n \"this_my_field_4\": 1\n}\n",
|
||||
"options": {}
|
||||
},
|
||||
"id": "1cfca06d-3ec3-427f-89f7-1ef321e025ff",
|
||||
"name": "Node 2",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 3.4,
|
||||
"position": [
|
||||
780,
|
||||
-380
|
||||
]
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"When chat message received": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Node 1",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Node 1": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Node 2",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"pinData": {},
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "178ef8a5109fc76c716d40bcadb720c455319f7b7a3fd5a39e4f336a091f524a"
|
||||
}
|
||||
}
|
|
@ -201,11 +201,18 @@ async function createExecutionPromise() {
|
|||
|
||||
async function onRunChatWorkflow(payload: RunWorkflowChatPayload) {
|
||||
try {
|
||||
const response = await runWorkflow({
|
||||
const runWorkflowOptions: Parameters<typeof runWorkflow>[0] = {
|
||||
triggerNode: payload.triggerNode,
|
||||
nodeData: payload.nodeData,
|
||||
source: payload.source,
|
||||
});
|
||||
};
|
||||
|
||||
if (workflowsStore.chatPartialExecutionDestinationNode) {
|
||||
runWorkflowOptions.destinationNode = workflowsStore.chatPartialExecutionDestinationNode;
|
||||
workflowsStore.chatPartialExecutionDestinationNode = null;
|
||||
}
|
||||
|
||||
const response = await runWorkflow(runWorkflowOptions);
|
||||
|
||||
if (response) {
|
||||
await createExecutionPromise();
|
||||
|
|
|
@ -319,6 +319,7 @@ async function onClick() {
|
|||
|
||||
if (isChatNode.value || (isChatChild.value && ndvStore.isInputPanelEmpty)) {
|
||||
ndvStore.setActiveNodeName(null);
|
||||
workflowsStore.chatPartialExecutionDestinationNode = props.nodeName;
|
||||
nodeViewEventBus.emit('openChat');
|
||||
} else if (isListeningForEvents.value) {
|
||||
await stopWaitingForWebhook();
|
||||
|
|
|
@ -164,6 +164,9 @@ export function useRunWorkflow(useRunWorkflowOpts: { router: ReturnType<typeof u
|
|||
);
|
||||
newRunData = { [options.triggerNode]: [options.nodeData] };
|
||||
executedNode = options.triggerNode;
|
||||
}
|
||||
|
||||
if (options.triggerNode && options.nodeData) {
|
||||
triggerToStartFrom = {
|
||||
name: options.triggerNode,
|
||||
data: options.nodeData,
|
||||
|
@ -174,7 +177,8 @@ export function useRunWorkflow(useRunWorkflowOpts: { router: ReturnType<typeof u
|
|||
if (
|
||||
options.destinationNode &&
|
||||
(workflowsStore.checkIfNodeHasChatParent(options.destinationNode) ||
|
||||
destinationNodeType === CHAT_TRIGGER_NODE_TYPE)
|
||||
destinationNodeType === CHAT_TRIGGER_NODE_TYPE) &&
|
||||
options.source !== 'RunData.ManualChatMessage'
|
||||
) {
|
||||
const startNode = workflow.getStartNode(options.destinationNode);
|
||||
if (startNode && startNode.type === CHAT_TRIGGER_NODE_TYPE) {
|
||||
|
@ -186,6 +190,7 @@ export function useRunWorkflow(useRunWorkflowOpts: { router: ReturnType<typeof u
|
|||
// If the chat node has no input data or pin data, open the chat modal
|
||||
// and halt the execution
|
||||
if (!chatHasInputData && !chatHasPinData) {
|
||||
workflowsStore.chatPartialExecutionDestinationNode = options.destinationNode;
|
||||
workflowsStore.setPanelOpen('chat', true);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -145,6 +145,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
|
|||
const nodeMetadata = ref<NodeMetadataMap>({});
|
||||
const isInDebugMode = ref(false);
|
||||
const chatMessages = ref<string[]>([]);
|
||||
const chatPartialExecutionDestinationNode = ref<string | null>(null);
|
||||
const isChatPanelOpen = ref(false);
|
||||
const isLogsPanelOpen = ref(false);
|
||||
|
||||
|
@ -1634,6 +1635,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
|
|||
nodeMetadata,
|
||||
isInDebugMode,
|
||||
chatMessages,
|
||||
chatPartialExecutionDestinationNode,
|
||||
workflowName,
|
||||
workflowId,
|
||||
workflowVersionId,
|
||||
|
|
Loading…
Reference in a new issue