mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
feat: Add fallback mechanism for agent and basic chain llm (#16617)
This commit is contained in:
@@ -29,7 +29,11 @@ const i18n = useI18n();
|
||||
const { debounce } = useDebounce();
|
||||
const emit = defineEmits<{
|
||||
switchSelectedNode: [nodeName: string];
|
||||
openConnectionNodeCreator: [nodeName: string, connectionType: NodeConnectionType];
|
||||
openConnectionNodeCreator: [
|
||||
nodeName: string,
|
||||
connectionType: NodeConnectionType,
|
||||
connectionIndex: number,
|
||||
];
|
||||
}>();
|
||||
|
||||
interface NodeConfig {
|
||||
@@ -38,6 +42,12 @@ interface NodeConfig {
|
||||
issues: string[];
|
||||
}
|
||||
|
||||
interface ConnectionContext {
|
||||
connectionType: NodeConnectionType;
|
||||
typeIndex: number;
|
||||
key: string;
|
||||
}
|
||||
|
||||
const possibleConnections = ref<INodeInputConfiguration[]>([]);
|
||||
|
||||
const expandedGroups = ref<string[]>([]);
|
||||
@@ -85,55 +95,60 @@ const connectedNodes = computed<Record<string, NodeConfig[]>>(() => {
|
||||
);
|
||||
});
|
||||
|
||||
function getConnectionKey(connection: INodeInputConfiguration, globalIndex: number): string {
|
||||
// Calculate the per-type index for this connection
|
||||
function getConnectionContext(
|
||||
connection: INodeInputConfiguration,
|
||||
globalIndex: number,
|
||||
): ConnectionContext {
|
||||
let typeIndex = 0;
|
||||
for (let i = 0; i < globalIndex; i++) {
|
||||
if (possibleConnections.value[i].type === connection.type) {
|
||||
typeIndex++;
|
||||
}
|
||||
}
|
||||
return `${connection.type}-${typeIndex}`;
|
||||
return {
|
||||
connectionType: connection.type,
|
||||
typeIndex,
|
||||
key: `${connection.type}-${typeIndex}`,
|
||||
};
|
||||
}
|
||||
|
||||
function getConnectionConfig(connectionKey: string) {
|
||||
const [type, indexStr] = connectionKey.split('-');
|
||||
const typeIndex = parseInt(indexStr, 10);
|
||||
|
||||
// Find the connection config by type and type-specific index
|
||||
let currentTypeIndex = 0;
|
||||
for (const connection of possibleConnections.value) {
|
||||
if (connection.type === type) {
|
||||
if (currentTypeIndex === typeIndex) {
|
||||
return connection;
|
||||
}
|
||||
currentTypeIndex++;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
function getConnectionKey(connection: INodeInputConfiguration, globalIndex: number): string {
|
||||
return getConnectionContext(connection, globalIndex).key;
|
||||
}
|
||||
|
||||
function isMultiConnection(connectionKey: string) {
|
||||
const connectionConfig = getConnectionConfig(connectionKey);
|
||||
function getConnectionConfig(connectionType: NodeConnectionType, typeIndex: number) {
|
||||
return possibleConnections.value
|
||||
.filter((connection) => connection.type === connectionType)
|
||||
.at(typeIndex);
|
||||
}
|
||||
|
||||
function isMultiConnection(connectionContext: ConnectionContext) {
|
||||
const connectionConfig = getConnectionConfig(
|
||||
connectionContext.connectionType,
|
||||
connectionContext.typeIndex,
|
||||
);
|
||||
return connectionConfig?.maxConnections !== 1;
|
||||
}
|
||||
|
||||
function shouldShowConnectionTooltip(connectionKey: string) {
|
||||
const [type] = connectionKey.split('-');
|
||||
return isMultiConnection(connectionKey) && !expandedGroups.value.includes(type);
|
||||
function shouldShowConnectionTooltip(connectionContext: ConnectionContext) {
|
||||
return (
|
||||
isMultiConnection(connectionContext) &&
|
||||
!expandedGroups.value.includes(connectionContext.connectionType)
|
||||
);
|
||||
}
|
||||
|
||||
function expandConnectionGroup(connectionKey: string, isExpanded: boolean) {
|
||||
const [type] = connectionKey.split('-');
|
||||
function expandConnectionGroup(connectionContext: ConnectionContext, isExpanded: boolean) {
|
||||
// If the connection is a single connection, we don't need to expand the group
|
||||
if (!isMultiConnection(connectionKey)) {
|
||||
if (!isMultiConnection(connectionContext)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isExpanded) {
|
||||
expandedGroups.value = [...expandedGroups.value, type];
|
||||
expandedGroups.value = [...expandedGroups.value, connectionContext.connectionType];
|
||||
} else {
|
||||
expandedGroups.value = expandedGroups.value.filter((g) => g !== type);
|
||||
expandedGroups.value = expandedGroups.value.filter(
|
||||
(g) => g !== connectionContext.connectionType,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,9 +169,11 @@ function getINodesFromNames(names: string[]): NodeConfig[] {
|
||||
.filter((n): n is NodeConfig => n !== null);
|
||||
}
|
||||
|
||||
function hasInputIssues(connectionKey: string) {
|
||||
const [type] = connectionKey.split('-');
|
||||
return shouldShowNodeInputIssues.value && (nodeInputIssues.value[type] ?? []).length > 0;
|
||||
function hasInputIssues(connectionContext: ConnectionContext) {
|
||||
return (
|
||||
shouldShowNodeInputIssues.value &&
|
||||
(nodeInputIssues.value[connectionContext.connectionType] ?? []).length > 0
|
||||
);
|
||||
}
|
||||
|
||||
function isNodeInputConfiguration(
|
||||
@@ -181,29 +198,35 @@ function getPossibleSubInputConnections(): INodeInputConfiguration[] {
|
||||
return nonMainInputs;
|
||||
}
|
||||
|
||||
function onNodeClick(nodeName: string, connectionKey: string) {
|
||||
const [type] = connectionKey.split('-');
|
||||
if (isMultiConnection(connectionKey) && !expandedGroups.value.includes(type)) {
|
||||
expandConnectionGroup(connectionKey, true);
|
||||
function onNodeClick(nodeName: string, connectionContext: ConnectionContext) {
|
||||
if (
|
||||
isMultiConnection(connectionContext) &&
|
||||
!expandedGroups.value.includes(connectionContext.connectionType)
|
||||
) {
|
||||
expandConnectionGroup(connectionContext, true);
|
||||
return;
|
||||
}
|
||||
|
||||
emit('switchSelectedNode', nodeName);
|
||||
}
|
||||
|
||||
function onPlusClick(connectionKey: string) {
|
||||
const [type] = connectionKey.split('-');
|
||||
const connectionNodes = connectedNodes.value[connectionKey];
|
||||
function onPlusClick(connectionContext: ConnectionContext) {
|
||||
const connectionNodes = connectedNodes.value[connectionContext.key];
|
||||
if (
|
||||
isMultiConnection(connectionKey) &&
|
||||
!expandedGroups.value.includes(type) &&
|
||||
isMultiConnection(connectionContext) &&
|
||||
!expandedGroups.value.includes(connectionContext.connectionType) &&
|
||||
connectionNodes.length >= 1
|
||||
) {
|
||||
expandConnectionGroup(connectionKey, true);
|
||||
expandConnectionGroup(connectionContext, true);
|
||||
return;
|
||||
}
|
||||
|
||||
emit('openConnectionNodeCreator', props.rootNode.name, type as NodeConnectionType);
|
||||
emit(
|
||||
'openConnectionNodeCreator',
|
||||
props.rootNode.name,
|
||||
connectionContext.connectionType,
|
||||
connectionContext.typeIndex,
|
||||
);
|
||||
}
|
||||
|
||||
function showNodeInputsIssues() {
|
||||
@@ -247,12 +270,12 @@ defineExpose({
|
||||
<span
|
||||
:class="{
|
||||
[$style.connectionLabel]: true,
|
||||
[$style.hasIssues]: hasInputIssues(getConnectionKey(connection, index)),
|
||||
[$style.hasIssues]: hasInputIssues(getConnectionContext(connection, index)),
|
||||
}"
|
||||
v-text="`${connection.displayName}${connection.required ? ' *' : ''}`"
|
||||
/>
|
||||
<OnClickOutside
|
||||
@trigger="expandConnectionGroup(getConnectionKey(connection, index), false)"
|
||||
@trigger="expandConnectionGroup(getConnectionContext(connection, index), false)"
|
||||
>
|
||||
<div
|
||||
ref="connectedNodesWrapper"
|
||||
@@ -261,7 +284,7 @@ defineExpose({
|
||||
[$style.connectedNodesWrapperExpanded]: expandedGroups.includes(connection.type),
|
||||
}"
|
||||
:style="`--nodes-length: ${connectedNodes[getConnectionKey(connection, index)].length}`"
|
||||
@click="expandConnectionGroup(getConnectionKey(connection, index), true)"
|
||||
@click="expandConnectionGroup(getConnectionContext(connection, index), true)"
|
||||
>
|
||||
<div
|
||||
v-if="
|
||||
@@ -271,9 +294,9 @@ defineExpose({
|
||||
"
|
||||
:class="{
|
||||
[$style.plusButton]: true,
|
||||
[$style.hasIssues]: hasInputIssues(getConnectionKey(connection, index)),
|
||||
[$style.hasIssues]: hasInputIssues(getConnectionContext(connection, index)),
|
||||
}"
|
||||
@click="onPlusClick(getConnectionKey(connection, index))"
|
||||
@click="onPlusClick(getConnectionContext(connection, index))"
|
||||
>
|
||||
<n8n-tooltip
|
||||
placement="top"
|
||||
@@ -281,13 +304,13 @@ defineExpose({
|
||||
:offset="10"
|
||||
:show-after="300"
|
||||
:disabled="
|
||||
shouldShowConnectionTooltip(getConnectionKey(connection, index)) &&
|
||||
shouldShowConnectionTooltip(getConnectionContext(connection, index)) &&
|
||||
connectedNodes[getConnectionKey(connection, index)].length >= 1
|
||||
"
|
||||
>
|
||||
<template #content>
|
||||
Add {{ connection.displayName }}
|
||||
<template v-if="hasInputIssues(getConnectionKey(connection, index))">
|
||||
<template v-if="hasInputIssues(getConnectionContext(connection, index))">
|
||||
<TitledList
|
||||
:title="`${i18n.baseText('node.issues')}:`"
|
||||
:items="nodeInputIssues[connection.type]"
|
||||
@@ -324,7 +347,7 @@ defineExpose({
|
||||
:teleported="true"
|
||||
:offset="10"
|
||||
:show-after="300"
|
||||
:disabled="shouldShowConnectionTooltip(getConnectionKey(connection, index))"
|
||||
:disabled="shouldShowConnectionTooltip(getConnectionContext(connection, index))"
|
||||
>
|
||||
<template #content>
|
||||
{{ node.node.name }}
|
||||
@@ -338,7 +361,7 @@ defineExpose({
|
||||
|
||||
<div
|
||||
:class="$style.connectedNode"
|
||||
@click="onNodeClick(node.node.name, getConnectionKey(connection, index))"
|
||||
@click="onNodeClick(node.node.name, getConnectionContext(connection, index))"
|
||||
>
|
||||
<NodeIcon
|
||||
:node-type="node.nodeType"
|
||||
|
||||
@@ -377,6 +377,9 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
|
||||
if (displayNode && filter?.nodes?.length) {
|
||||
return filter.nodes.includes(i.key);
|
||||
}
|
||||
if (displayNode && filter?.excludedNodes?.length) {
|
||||
return !filter.excludedNodes.includes(i.key);
|
||||
}
|
||||
|
||||
return displayNode;
|
||||
},
|
||||
|
||||
@@ -46,7 +46,11 @@ const emit = defineEmits<{
|
||||
saveKeyboardShortcut: [event: KeyboardEvent];
|
||||
valueChanged: [parameterData: IUpdateInformation];
|
||||
switchSelectedNode: [nodeTypeName: string];
|
||||
openConnectionNodeCreator: [nodeTypeName: string, connectionType: NodeConnectionType];
|
||||
openConnectionNodeCreator: [
|
||||
nodeTypeName: string,
|
||||
connectionType: NodeConnectionType,
|
||||
connectionIndex?: number,
|
||||
];
|
||||
redrawNode: [nodeName: string];
|
||||
stopExecution: [];
|
||||
}>();
|
||||
@@ -500,8 +504,12 @@ const onSwitchSelectedNode = (nodeTypeName: string) => {
|
||||
emit('switchSelectedNode', nodeTypeName);
|
||||
};
|
||||
|
||||
const onOpenConnectionNodeCreator = (nodeTypeName: string, connectionType: NodeConnectionType) => {
|
||||
emit('openConnectionNodeCreator', nodeTypeName, connectionType);
|
||||
const onOpenConnectionNodeCreator = (
|
||||
nodeTypeName: string,
|
||||
connectionType: NodeConnectionType,
|
||||
connectionIndex: number = 0,
|
||||
) => {
|
||||
emit('openConnectionNodeCreator', nodeTypeName, connectionType, connectionIndex);
|
||||
};
|
||||
|
||||
const close = async () => {
|
||||
|
||||
@@ -77,7 +77,11 @@ const emit = defineEmits<{
|
||||
redrawRequired: [];
|
||||
valueChanged: [value: IUpdateInformation];
|
||||
switchSelectedNode: [nodeName: string];
|
||||
openConnectionNodeCreator: [nodeName: string, connectionType: NodeConnectionType];
|
||||
openConnectionNodeCreator: [
|
||||
nodeName: string,
|
||||
connectionType: NodeConnectionType,
|
||||
connectionIndex?: number,
|
||||
];
|
||||
activate: [];
|
||||
execute: [];
|
||||
expand: [];
|
||||
@@ -382,8 +386,12 @@ const onSwitchSelectedNode = (node: string) => {
|
||||
emit('switchSelectedNode', node);
|
||||
};
|
||||
|
||||
const onOpenConnectionNodeCreator = (nodeName: string, connectionType: NodeConnectionType) => {
|
||||
emit('openConnectionNodeCreator', nodeName, connectionType);
|
||||
const onOpenConnectionNodeCreator = (
|
||||
nodeName: string,
|
||||
connectionType: NodeConnectionType,
|
||||
connectionIndex: number = 0,
|
||||
) => {
|
||||
emit('openConnectionNodeCreator', nodeName, connectionType, connectionIndex);
|
||||
};
|
||||
|
||||
const populateHiddenIssuesSet = () => {
|
||||
|
||||
Reference in New Issue
Block a user