mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 10:31:15 +00:00
feat: AI Workflow Builder agent (no-changelog) (#17423)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import { type INode, NodeConnectionTypes, type INodeTypeDescription } from 'n8n-workflow';
|
||||
|
||||
/**
|
||||
* Determines if a node is a sub-node (has no main input connections)
|
||||
* Sub-nodes are nodes that only have AI inputs or no inputs at all
|
||||
* @param nodeType - The node type description to check
|
||||
* @returns true if the node is a sub-node, false otherwise
|
||||
*/
|
||||
export function isSubNode(nodeType: INodeTypeDescription, node?: INode): boolean {
|
||||
if (node?.parameters?.mode === 'retrieve-as-tool') {
|
||||
return true;
|
||||
}
|
||||
// Treating agent as main node always
|
||||
if (nodeType.name === '@n8n/n8n-nodes-langchain.agent') {
|
||||
return false;
|
||||
}
|
||||
// If no inputs at all, it's definitely a sub-node
|
||||
if (!nodeType.inputs || (Array.isArray(nodeType.inputs) && nodeType.inputs.length === 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle array of inputs
|
||||
if (Array.isArray(nodeType.inputs)) {
|
||||
// Check if ALL inputs are AI connections (no main inputs)
|
||||
const hasMainInput = nodeType.inputs.some((input) => {
|
||||
if (typeof input === 'string') {
|
||||
return input === NodeConnectionTypes.Main || input.toLowerCase() === 'main';
|
||||
}
|
||||
// It's an INodeInputConfiguration object
|
||||
return input.type === NodeConnectionTypes.Main || input.type.toLowerCase() === 'main';
|
||||
});
|
||||
|
||||
return !hasMainInput;
|
||||
}
|
||||
// Handle expression-based inputs (dynamic)
|
||||
if (typeof nodeType.inputs === 'string') {
|
||||
// Check if the expression contains any indication of main input
|
||||
// We need to check for any pattern that would result in a main connection
|
||||
const mainInputPatterns = [
|
||||
'NodeConnectionTypes.Main',
|
||||
'type: "main"',
|
||||
"type: 'main'",
|
||||
'type:"main"',
|
||||
"type:'main'",
|
||||
'type: `main`',
|
||||
'type: NodeConnectionTypes.Main',
|
||||
'type:NodeConnectionTypes.Main',
|
||||
'{ displayName: "", type: "main"',
|
||||
"{ displayName: '', type: 'main'",
|
||||
'{ displayName: "", type: NodeConnectionTypes.Main',
|
||||
"{ displayName: '', type: NodeConnectionTypes.Main",
|
||||
// Patterns for arrays that include "main" as first element
|
||||
'return ["main"',
|
||||
"return ['main'",
|
||||
'return [`main`',
|
||||
'return[["main"',
|
||||
"return[['main'",
|
||||
'return [[`main`',
|
||||
// Pattern for spread operations that include main
|
||||
'["main", ...',
|
||||
"['main', ...",
|
||||
'[`main`, ...',
|
||||
];
|
||||
|
||||
// If any main input pattern is found, it's NOT a sub-node
|
||||
const hasMainInput = mainInputPatterns.some(
|
||||
(pattern) =>
|
||||
typeof nodeType.inputs === 'string' &&
|
||||
nodeType.inputs.toLowerCase().includes(pattern.toLowerCase()),
|
||||
);
|
||||
|
||||
return !hasMainInput;
|
||||
}
|
||||
// If we can't determine, assume it's not a sub-node (safer default)
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user