mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-23 11:44:06 -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 AI_MEMORY_WINDOW_BUFFER_MEMORY_NODE_NAME = 'Window Buffer Memory';
|
||||
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_LANGUAGE_MODEL_OPENAI_CHAT_MODEL_NODE_NAME = 'OpenAI Chat Model';
|
||||
export const AI_OUTPUT_PARSER_AUTO_FIXING_NODE_NAME = 'Auto-fixing Output Parser';
|
||||
|
|
|
@ -47,10 +47,18 @@ function getInputs(
|
|||
};
|
||||
|
||||
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 = {
|
||||
type,
|
||||
displayName: type in displayNames ? displayNames[type] : undefined,
|
||||
required: type === NodeConnectionType.AiLanguageModel,
|
||||
displayName,
|
||||
required: isModelType,
|
||||
maxConnections: [NodeConnectionType.AiLanguageModel, NodeConnectionType.AiMemory].includes(
|
||||
type as NodeConnectionType,
|
||||
)
|
||||
|
|
|
@ -75,6 +75,7 @@ export class LmChatAnthropic implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Chat Models (Recommended)'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -29,6 +29,7 @@ export class LmChatOllama implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Chat Models (Recommended)'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -27,6 +27,7 @@ export class LmChatOpenAi implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Chat Models (Recommended)'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -27,6 +27,7 @@ export class LmCohere implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Text Completion Models'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -28,6 +28,7 @@ export class LmOllama implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Text Completion Models'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -39,6 +39,7 @@ export class LmOpenAi implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Text Completion Models'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -27,6 +27,7 @@ export class LmOpenHuggingFaceInference implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Text Completion Models'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -30,6 +30,7 @@ export class LmChatAwsBedrock implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Chat Models (Recommended)'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -28,6 +28,7 @@ export class LmChatAzureOpenAi implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Chat Models (Recommended)'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -28,6 +28,7 @@ export class LmChatGoogleGemini implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Chat Models (Recommended)'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -26,6 +26,7 @@ export class LmChatGooglePalm implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Chat Models (Recommended)'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -33,6 +33,7 @@ export class LmChatGoogleVertex implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Chat Models (Recommended)'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -27,6 +27,7 @@ export class LmChatGroq implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Chat Models (Recommended)'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -28,6 +28,7 @@ export class LmChatMistralCloud implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Chat Models (Recommended)'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -26,6 +26,7 @@ export class LmGooglePalm implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Language Models'],
|
||||
'Language Models': ['Text Completion Models'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -25,6 +25,7 @@ export class ToolCalculator implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Tools'],
|
||||
Tools: ['Other Tools'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -17,19 +17,20 @@ import { getConnectionHintNoticeField } from '../../../utils/sharedFields';
|
|||
|
||||
export class ToolCode implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Custom Code Tool',
|
||||
displayName: 'Code Tool',
|
||||
name: 'toolCode',
|
||||
icon: 'fa:code',
|
||||
group: ['transform'],
|
||||
version: [1, 1.1],
|
||||
description: 'Write a tool in JS or Python',
|
||||
defaults: {
|
||||
name: 'Custom Code Tool',
|
||||
name: 'Code Tool',
|
||||
},
|
||||
codex: {
|
||||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Tools'],
|
||||
Tools: ['Recommended Tools'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -49,6 +49,7 @@ export class ToolHttpRequest implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Tools'],
|
||||
Tools: ['Recommended Tools'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -25,6 +25,7 @@ export class ToolSerpApi implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Tools'],
|
||||
Tools: ['Other Tools'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -23,6 +23,7 @@ export class ToolVectorStore implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Tools'],
|
||||
Tools: ['Other Tools'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -25,6 +25,7 @@ export class ToolWikipedia implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Tools'],
|
||||
Tools: ['Other Tools'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -31,6 +31,7 @@ export class ToolWolframAlpha implements INodeType {
|
|||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Tools'],
|
||||
Tools: ['Other Tools'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -28,19 +28,20 @@ import {
|
|||
} from '../../../utils/descriptions';
|
||||
export class ToolWorkflow implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Custom n8n Workflow Tool',
|
||||
displayName: 'Call n8n Workflow Tool',
|
||||
name: 'toolWorkflow',
|
||||
icon: 'fa:network-wired',
|
||||
group: ['transform'],
|
||||
version: [1, 1.1],
|
||||
description: 'Uses another n8n workflow as a tool. Allows packaging any n8n node(s) as a tool.',
|
||||
defaults: {
|
||||
name: 'Custom n8n Workflow Tool',
|
||||
name: 'Call n8n Workflow Tool',
|
||||
},
|
||||
codex: {
|
||||
categories: ['AI'],
|
||||
subcategories: {
|
||||
AI: ['Tools'],
|
||||
Tools: ['Recommended Tools'],
|
||||
},
|
||||
resources: {
|
||||
primaryDocumentation: [
|
||||
|
|
|
@ -9,7 +9,10 @@
|
|||
<div :class="$style.title">
|
||||
<slot name="title" />
|
||||
<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') }}
|
||||
<n8n-link v-if="rootView === REGULAR_NODE_CREATOR_VIEW" @click="$emit('addHttpNode')">
|
||||
{{ $locale.baseText('nodeCreator.noResults.httpRequest') }}
|
||||
|
|
|
@ -93,8 +93,9 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
|
|||
if (
|
||||
// Filter-out AI sub-nodes if canvas has no AI nodes and the root view is not AI
|
||||
!(isAiRootView(stack) || canvasHasAINodes) ||
|
||||
// or if the source is a plus endpoint or a node connection drop
|
||||
['plus_endpoint', 'node_connection_drop'].includes(nodeCreatorStore.openSource)
|
||||
// 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) &&
|
||||
!isAiSubcategoryView(stack))
|
||||
) {
|
||||
searchBase = filterOutAiNodes(searchBase);
|
||||
}
|
||||
|
@ -135,6 +136,10 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
|
|||
return stack.searchItems.map((item) => transformNodeType(item, stack.subcategory));
|
||||
});
|
||||
|
||||
function isAiSubcategoryView(stack: ViewStack) {
|
||||
return stack.rootView === AI_OTHERS_NODE_CREATOR_VIEW;
|
||||
}
|
||||
|
||||
function getLastActiveStack() {
|
||||
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
|
||||
const globalSearchItemsDiff = computed<INodeCreateElement[]>(() => {
|
||||
const stack = getLastActiveStack();
|
||||
if (!stack?.search) return [];
|
||||
if (!stack?.search || isAiSubcategoryView(stack)) return [];
|
||||
|
||||
const allNodes = nodeCreatorStore.mergedNodes.map((item) => transformNodeType(item));
|
||||
// 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];
|
||||
|
||||
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 =
|
||||
!node.properties.codex?.subcategories?.[AI_SUBCATEGORY].includes(
|
||||
AI_CATEGORY_ROOT_NODES,
|
||||
);
|
||||
|
||||
sectionsMap.set(section, {
|
||||
key: section,
|
||||
title: isSubnodesSection
|
||||
? `${section} (${i18n.baseText('nodeCreator.subnodes')})`
|
||||
: section,
|
||||
let title = section;
|
||||
if (isSubnodesSection) {
|
||||
title = `${section} (${i18n.baseText('nodeCreator.subnodes')})`;
|
||||
}
|
||||
if (subSection) {
|
||||
title = subSection;
|
||||
}
|
||||
|
||||
sectionsMap.set(sectionKey, {
|
||||
key: sectionKey,
|
||||
title,
|
||||
items: [...currentItems, node.key],
|
||||
});
|
||||
}
|
||||
|
@ -419,6 +432,7 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
|
|||
activeViewStack,
|
||||
activeViewStackMode,
|
||||
globalSearchItemsDiff,
|
||||
isAiSubcategoryView,
|
||||
gotoCompatibleConnectionView,
|
||||
resetViewStacks,
|
||||
updateCurrentViewStack,
|
||||
|
|
|
@ -157,6 +157,12 @@ export function groupItemsInSections(
|
|||
})
|
||||
.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) {
|
||||
return items;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue