feat: Respond to chat and wait for response (#12546)

Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
This commit is contained in:
Michael Kret
2025-07-24 11:48:40 +03:00
committed by GitHub
parent e61b25c53f
commit a98ed2ca49
47 changed files with 3441 additions and 71 deletions

View File

@@ -10,7 +10,7 @@ import type {
Workflow,
WorkflowExecuteMode,
} from 'n8n-workflow';
import { NodeConnectionTypes } from 'n8n-workflow';
import { CHAT_TRIGGER_NODE_TYPE, NodeConnectionTypes } from 'n8n-workflow';
import { InstanceSettings } from '@/instance-settings';
@@ -115,6 +115,31 @@ describe('NodeExecutionContext', () => {
});
});
describe('getChatTrigger', () => {
it('should return a chat trigger node if it exists in the workflow', () => {
const chatNode = mock<INode>({ name: 'Chat', type: CHAT_TRIGGER_NODE_TYPE });
workflow.nodes = {
Chat: chatNode,
};
const result = testContext.getChatTrigger();
expect(result).toEqual(chatNode);
});
it('should return a null if there is no chat trigger node in the workflow', () => {
const someNode = mock<INode>({ name: 'Some Node', type: 'someType' });
workflow.nodes = {
'Some Node': someNode,
};
const result = testContext.getChatTrigger();
expect(result).toBeNull();
});
});
describe('getKnownNodeTypes', () => {
it('should call getKnownTypes method of nodeTypes', () => {
testContext.getKnownNodeTypes();

View File

@@ -25,6 +25,7 @@ import type {
} from 'n8n-workflow';
import {
ApplicationError,
CHAT_TRIGGER_NODE_TYPE,
deepCopy,
ExpressionError,
NodeHelpers,
@@ -106,22 +107,43 @@ export abstract class NodeExecutionContext implements Omit<FunctionsBase, 'getCr
return output;
}
getParentNodes(nodeName: string) {
getParentNodes(nodeName: string, options?: { includeNodeParameters?: boolean }) {
const output: NodeTypeAndVersion[] = [];
const nodeNames = this.workflow.getParentNodes(nodeName);
for (const n of nodeNames) {
const node = this.workflow.nodes[n];
output.push({
const entry: NodeTypeAndVersion = {
name: node.name,
type: node.type,
typeVersion: node.typeVersion,
disabled: node.disabled ?? false,
});
};
if (options?.includeNodeParameters) {
entry.parameters = node.parameters;
}
output.push(entry);
}
return output;
}
/**
* Gets the chat trigger node
*
* this is needed for sub-nodes where the parent nodes are not available
*/
getChatTrigger() {
for (const node of Object.values(this.workflow.nodes)) {
if (this.workflow.nodes[node.name].type === CHAT_TRIGGER_NODE_TYPE) {
return this.workflow.nodes[node.name];
}
}
return null;
}
@Memoized
get nodeType() {
const { type, typeVersion } = this.node;