mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
77 lines
2.5 KiB
TypeScript
77 lines
2.5 KiB
TypeScript
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;
|
|
}
|