mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
feat(editor): Split Tools and Models into sub-sections (#10159)
This commit is contained in:
parent
95b85dd5c1
commit
3846eb967a
|
@ -53,7 +53,7 @@ export const AGENT_NODE_NAME = 'AI Agent';
|
||||||
export const BASIC_LLM_CHAIN_NODE_NAME = 'Basic LLM Chain';
|
export const BASIC_LLM_CHAIN_NODE_NAME = 'Basic LLM Chain';
|
||||||
export const AI_MEMORY_WINDOW_BUFFER_MEMORY_NODE_NAME = 'Window Buffer Memory';
|
export const AI_MEMORY_WINDOW_BUFFER_MEMORY_NODE_NAME = 'Window Buffer Memory';
|
||||||
export const AI_TOOL_CALCULATOR_NODE_NAME = 'Calculator';
|
export const AI_TOOL_CALCULATOR_NODE_NAME = 'Calculator';
|
||||||
export const AI_TOOL_CODE_NODE_NAME = 'Custom Code Tool';
|
export const AI_TOOL_CODE_NODE_NAME = 'Code Tool';
|
||||||
export const AI_TOOL_WIKIPEDIA_NODE_NAME = 'Wikipedia';
|
export const AI_TOOL_WIKIPEDIA_NODE_NAME = 'Wikipedia';
|
||||||
export const AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME = 'OpenAI Chat Model';
|
export const AI_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME = 'OpenAI Chat Model';
|
||||||
export const AI_OUTPUT_PARSER_AUTO_FIXING_NODE_NAME = 'Auto-fixing Output Parser';
|
export const AI_OUTPUT_PARSER_AUTO_FIXING_NODE_NAME = 'Auto-fixing Output Parser';
|
||||||
|
|
|
@ -47,10 +47,18 @@ function getInputs(
|
||||||
};
|
};
|
||||||
|
|
||||||
return inputs.map(({ type, filter }) => {
|
return inputs.map(({ type, filter }) => {
|
||||||
|
const isModelType = type === NodeConnectionType.AiLanguageModel;
|
||||||
|
let displayName = type in displayNames ? displayNames[type] : undefined;
|
||||||
|
if (
|
||||||
|
isModelType &&
|
||||||
|
['openAiFunctionsAgent', 'toolsAgent', 'conversationalAgent'].includes(agent)
|
||||||
|
) {
|
||||||
|
displayName = 'Chat Model';
|
||||||
|
}
|
||||||
const input: INodeInputConfiguration = {
|
const input: INodeInputConfiguration = {
|
||||||
type,
|
type,
|
||||||
displayName: type in displayNames ? displayNames[type] : undefined,
|
displayName,
|
||||||
required: type === NodeConnectionType.AiLanguageModel,
|
required: isModelType,
|
||||||
maxConnections: [NodeConnectionType.AiLanguageModel, NodeConnectionType.AiMemory].includes(
|
maxConnections: [NodeConnectionType.AiLanguageModel, NodeConnectionType.AiMemory].includes(
|
||||||
type as NodeConnectionType,
|
type as NodeConnectionType,
|
||||||
)
|
)
|
||||||
|
|
|
@ -75,6 +75,7 @@ export class LmChatAnthropic implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Chat Models (Recommended)'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -29,6 +29,7 @@ export class LmChatOllama implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Chat Models (Recommended)'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -27,6 +27,7 @@ export class LmChatOpenAi implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Chat Models (Recommended)'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -27,6 +27,7 @@ export class LmCohere implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Text Completion Models'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -28,6 +28,7 @@ export class LmOllama implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Text Completion Models'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -39,6 +39,7 @@ export class LmOpenAi implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Text Completion Models'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -27,6 +27,7 @@ export class LmOpenHuggingFaceInference implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Text Completion Models'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -30,6 +30,7 @@ export class LmChatAwsBedrock implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Chat Models (Recommended)'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -28,6 +28,7 @@ export class LmChatAzureOpenAi implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Chat Models (Recommended)'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -28,6 +28,7 @@ export class LmChatGoogleGemini implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Chat Models (Recommended)'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -26,6 +26,7 @@ export class LmChatGooglePalm implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Chat Models (Recommended)'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -33,6 +33,7 @@ export class LmChatGoogleVertex implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Chat Models (Recommended)'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -27,6 +27,7 @@ export class LmChatGroq implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Chat Models (Recommended)'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -28,6 +28,7 @@ export class LmChatMistralCloud implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Chat Models (Recommended)'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -26,6 +26,7 @@ export class LmGooglePalm implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Language Models'],
|
AI: ['Language Models'],
|
||||||
|
'Language Models': ['Text Completion Models'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -25,6 +25,7 @@ export class ToolCalculator implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Tools'],
|
AI: ['Tools'],
|
||||||
|
Tools: ['Other Tools'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -17,19 +17,20 @@ import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
||||||
|
|
||||||
export class ToolCode implements INodeType {
|
export class ToolCode implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
displayName: 'Custom Code Tool',
|
displayName: 'Code Tool',
|
||||||
name: 'toolCode',
|
name: 'toolCode',
|
||||||
icon: 'fa:code',
|
icon: 'fa:code',
|
||||||
group: ['transform'],
|
group: ['transform'],
|
||||||
version: [1, 1.1],
|
version: [1, 1.1],
|
||||||
description: 'Write a tool in JS or Python',
|
description: 'Write a tool in JS or Python',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: 'Custom Code Tool',
|
name: 'Code Tool',
|
||||||
},
|
},
|
||||||
codex: {
|
codex: {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Tools'],
|
AI: ['Tools'],
|
||||||
|
Tools: ['Recommended Tools'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -49,6 +49,7 @@ export class ToolHttpRequest implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Tools'],
|
AI: ['Tools'],
|
||||||
|
Tools: ['Recommended Tools'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -25,6 +25,7 @@ export class ToolSerpApi implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Tools'],
|
AI: ['Tools'],
|
||||||
|
Tools: ['Other Tools'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -23,6 +23,7 @@ export class ToolVectorStore implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Tools'],
|
AI: ['Tools'],
|
||||||
|
Tools: ['Other Tools'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -25,6 +25,7 @@ export class ToolWikipedia implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Tools'],
|
AI: ['Tools'],
|
||||||
|
Tools: ['Other Tools'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -31,6 +31,7 @@ export class ToolWolframAlpha implements INodeType {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Tools'],
|
AI: ['Tools'],
|
||||||
|
Tools: ['Other Tools'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -28,19 +28,20 @@ import {
|
||||||
} from '../../../utils/descriptions';
|
} from '../../../utils/descriptions';
|
||||||
export class ToolWorkflow implements INodeType {
|
export class ToolWorkflow implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
displayName: 'Custom n8n Workflow Tool',
|
displayName: 'Call n8n Workflow Tool',
|
||||||
name: 'toolWorkflow',
|
name: 'toolWorkflow',
|
||||||
icon: 'fa:network-wired',
|
icon: 'fa:network-wired',
|
||||||
group: ['transform'],
|
group: ['transform'],
|
||||||
version: [1, 1.1],
|
version: [1, 1.1],
|
||||||
description: 'Uses another n8n workflow as a tool. Allows packaging any n8n node(s) as a tool.',
|
description: 'Uses another n8n workflow as a tool. Allows packaging any n8n node(s) as a tool.',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: 'Custom n8n Workflow Tool',
|
name: 'Call n8n Workflow Tool',
|
||||||
},
|
},
|
||||||
codex: {
|
codex: {
|
||||||
categories: ['AI'],
|
categories: ['AI'],
|
||||||
subcategories: {
|
subcategories: {
|
||||||
AI: ['Tools'],
|
AI: ['Tools'],
|
||||||
|
Tools: ['Recommended Tools'],
|
||||||
},
|
},
|
||||||
resources: {
|
resources: {
|
||||||
primaryDocumentation: [
|
primaryDocumentation: [
|
||||||
|
|
|
@ -9,7 +9,10 @@
|
||||||
<div :class="$style.title">
|
<div :class="$style.title">
|
||||||
<slot name="title" />
|
<slot name="title" />
|
||||||
<p v-text="$locale.baseText('nodeCreator.noResults.weDidntMakeThatYet')" />
|
<p v-text="$locale.baseText('nodeCreator.noResults.weDidntMakeThatYet')" />
|
||||||
<div :class="$style.action">
|
<div
|
||||||
|
v-if="rootView === REGULAR_NODE_CREATOR_VIEW || rootView === TRIGGER_NODE_CREATOR_VIEW"
|
||||||
|
:class="$style.action"
|
||||||
|
>
|
||||||
{{ $locale.baseText('nodeCreator.noResults.dontWorryYouCanProbablyDoItWithThe') }}
|
{{ $locale.baseText('nodeCreator.noResults.dontWorryYouCanProbablyDoItWithThe') }}
|
||||||
<n8n-link v-if="rootView === REGULAR_NODE_CREATOR_VIEW" @click="$emit('addHttpNode')">
|
<n8n-link v-if="rootView === REGULAR_NODE_CREATOR_VIEW" @click="$emit('addHttpNode')">
|
||||||
{{ $locale.baseText('nodeCreator.noResults.httpRequest') }}
|
{{ $locale.baseText('nodeCreator.noResults.httpRequest') }}
|
||||||
|
|
|
@ -93,8 +93,9 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
|
||||||
if (
|
if (
|
||||||
// Filter-out AI sub-nodes if canvas has no AI nodes and the root view is not AI
|
// Filter-out AI sub-nodes if canvas has no AI nodes and the root view is not AI
|
||||||
!(isAiRootView(stack) || canvasHasAINodes) ||
|
!(isAiRootView(stack) || canvasHasAINodes) ||
|
||||||
// or if the source is a plus endpoint or a node connection drop
|
// or if the source is a plus endpoint or a node connection drop and the root view is not AI subcategory
|
||||||
['plus_endpoint', 'node_connection_drop'].includes(nodeCreatorStore.openSource)
|
(['plus_endpoint', 'node_connection_drop'].includes(nodeCreatorStore.openSource) &&
|
||||||
|
!isAiSubcategoryView(stack))
|
||||||
) {
|
) {
|
||||||
searchBase = filterOutAiNodes(searchBase);
|
searchBase = filterOutAiNodes(searchBase);
|
||||||
}
|
}
|
||||||
|
@ -135,6 +136,10 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
|
||||||
return stack.searchItems.map((item) => transformNodeType(item, stack.subcategory));
|
return stack.searchItems.map((item) => transformNodeType(item, stack.subcategory));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function isAiSubcategoryView(stack: ViewStack) {
|
||||||
|
return stack.rootView === AI_OTHERS_NODE_CREATOR_VIEW;
|
||||||
|
}
|
||||||
|
|
||||||
function getLastActiveStack() {
|
function getLastActiveStack() {
|
||||||
return viewStacks.value[viewStacks.value.length - 1];
|
return viewStacks.value[viewStacks.value.length - 1];
|
||||||
}
|
}
|
||||||
|
@ -142,7 +147,7 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
|
||||||
// Generate a delta between the global search results(all nodes) and the stack search results
|
// Generate a delta between the global search results(all nodes) and the stack search results
|
||||||
const globalSearchItemsDiff = computed<INodeCreateElement[]>(() => {
|
const globalSearchItemsDiff = computed<INodeCreateElement[]>(() => {
|
||||||
const stack = getLastActiveStack();
|
const stack = getLastActiveStack();
|
||||||
if (!stack?.search) return [];
|
if (!stack?.search || isAiSubcategoryView(stack)) return [];
|
||||||
|
|
||||||
const allNodes = nodeCreatorStore.mergedNodes.map((item) => transformNodeType(item));
|
const allNodes = nodeCreatorStore.mergedNodes.map((item) => transformNodeType(item));
|
||||||
// Apply filtering for AI nodes if the current view is not the AI root view
|
// Apply filtering for AI nodes if the current view is not the AI root view
|
||||||
|
@ -213,17 +218,25 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
|
||||||
const section = node.properties.codex?.subcategories?.[AI_SUBCATEGORY]?.[0];
|
const section = node.properties.codex?.subcategories?.[AI_SUBCATEGORY]?.[0];
|
||||||
|
|
||||||
if (section) {
|
if (section) {
|
||||||
const currentItems = sectionsMap.get(section)?.items ?? [];
|
const subSection = node.properties.codex?.subcategories?.[section]?.[0];
|
||||||
|
const sectionKey = subSection ?? section;
|
||||||
|
const currentItems = sectionsMap.get(sectionKey)?.items ?? [];
|
||||||
const isSubnodesSection =
|
const isSubnodesSection =
|
||||||
!node.properties.codex?.subcategories?.[AI_SUBCATEGORY].includes(
|
!node.properties.codex?.subcategories?.[AI_SUBCATEGORY].includes(
|
||||||
AI_CATEGORY_ROOT_NODES,
|
AI_CATEGORY_ROOT_NODES,
|
||||||
);
|
);
|
||||||
|
|
||||||
sectionsMap.set(section, {
|
let title = section;
|
||||||
key: section,
|
if (isSubnodesSection) {
|
||||||
title: isSubnodesSection
|
title = `${section} (${i18n.baseText('nodeCreator.subnodes')})`;
|
||||||
? `${section} (${i18n.baseText('nodeCreator.subnodes')})`
|
}
|
||||||
: section,
|
if (subSection) {
|
||||||
|
title = subSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
sectionsMap.set(sectionKey, {
|
||||||
|
key: sectionKey,
|
||||||
|
title,
|
||||||
items: [...currentItems, node.key],
|
items: [...currentItems, node.key],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -419,6 +432,7 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
|
||||||
activeViewStack,
|
activeViewStack,
|
||||||
activeViewStackMode,
|
activeViewStackMode,
|
||||||
globalSearchItemsDiff,
|
globalSearchItemsDiff,
|
||||||
|
isAiSubcategoryView,
|
||||||
gotoCompatibleConnectionView,
|
gotoCompatibleConnectionView,
|
||||||
resetViewStacks,
|
resetViewStacks,
|
||||||
updateCurrentViewStack,
|
updateCurrentViewStack,
|
||||||
|
|
|
@ -157,6 +157,12 @@ export function groupItemsInSections(
|
||||||
})
|
})
|
||||||
.filter((section) => section.type !== 'section' || section.children.length > 0);
|
.filter((section) => section.type !== 'section' || section.children.length > 0);
|
||||||
|
|
||||||
|
result.sort((a, b) => {
|
||||||
|
if (a.key.toLowerCase().includes('recommended')) return -1;
|
||||||
|
if (b.key.toLowerCase().includes('recommended')) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
if (result.length <= 1) {
|
if (result.length <= 1) {
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue