feat(editor): Show the simple vector store first in the nodes panel (no-changelog) (#15931)

This commit is contained in:
Jaakko Husso
2025-06-03 17:58:32 +03:00
committed by GitHub
parent a9f8b2d46a
commit 103bc20243
5 changed files with 31 additions and 10 deletions

View File

@@ -56,12 +56,17 @@ export class VectorStoreInMemory extends createVectorStoreNode<MemoryVectorStore
meta: { meta: {
displayName: 'Simple Vector Store', displayName: 'Simple Vector Store',
name: 'vectorStoreInMemory', name: 'vectorStoreInMemory',
description: description: 'The easiest way to experiment with vector stores, without external setup.',
"Work with your data in a Simple Vector Store. Don't use this for production usage.",
icon: 'fa:database', icon: 'fa:database',
iconColor: 'black', iconColor: 'black',
docsUrl: docsUrl:
'https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreinmemory/', 'https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreinmemory/',
categories: ['AI'],
subcategories: {
AI: ['Vector Stores', 'Tools', 'Root Nodes'],
'Vector Stores': ['For Beginners'],
Tools: ['Other Tools'],
},
}, },
sharedFields: [ sharedFields: [
{ {

View File

@@ -22,6 +22,9 @@ exports[`createVectorStoreNode retrieve mode supplies vector store as data 1`] =
"Tools": [ "Tools": [
"Other Tools", "Other Tools",
], ],
"Vector Stores": [
"Other Vector Stores",
],
}, },
}, },
"credentials": undefined, "credentials": undefined,

View File

@@ -50,9 +50,10 @@ export const createVectorStoreNode = <T extends VectorStore = VectorStore>(
name: args.meta.displayName, name: args.meta.displayName,
}, },
codex: { codex: {
categories: ['AI'], categories: args.meta.categories ?? ['AI'],
subcategories: { subcategories: args.meta.subcategories ?? {
AI: ['Vector Stores', 'Tools', 'Root Nodes'], AI: ['Vector Stores', 'Tools', 'Root Nodes'],
'Vector Stores': ['Other Vector Stores'],
Tools: ['Other Tools'], Tools: ['Other Tools'],
}, },
resources: { resources: {

View File

@@ -25,6 +25,8 @@ export interface NodeMeta {
iconColor?: ThemeIconColor; iconColor?: ThemeIconColor;
credentials?: INodeCredentialDescription[]; credentials?: INodeCredentialDescription[];
operationModes?: NodeOperationMode[]; operationModes?: NodeOperationMode[];
categories?: string[];
subcategories?: Record<string, string[]>;
} }
export interface VectorStoreNodeConstructorArgs<T extends VectorStore = VectorStore> { export interface VectorStoreNodeConstructorArgs<T extends VectorStore = VectorStore> {

View File

@@ -9,6 +9,7 @@ import {
AI_CATEGORY_MCP_NODES, AI_CATEGORY_MCP_NODES,
AI_CATEGORY_ROOT_NODES, AI_CATEGORY_ROOT_NODES,
AI_CATEGORY_TOOLS, AI_CATEGORY_TOOLS,
AI_CATEGORY_VECTOR_STORES,
AI_CODE_NODE_TYPE, AI_CODE_NODE_TYPE,
AI_NODE_CREATOR_VIEW, AI_NODE_CREATOR_VIEW,
AI_OTHERS_NODE_CREATOR_VIEW, AI_OTHERS_NODE_CREATOR_VIEW,
@@ -122,14 +123,14 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
const searchResults = extendItemsWithUUID(searchNodes(stack.search || '', searchBase)); const searchResults = extendItemsWithUUID(searchNodes(stack.search || '', searchBase));
const groupedNodes = groupIfAiNodes(searchResults, false) ?? searchResults; const groupedNodes = groupIfAiNodes(searchResults, stack.title, false) ?? searchResults;
// Set the active index to the second item if there's a section // Set the active index to the second item if there's a section
// as the first item is collapsable // as the first item is collapsable
stack.activeIndex = groupedNodes.some((node) => node.type === 'section') ? 1 : 0; stack.activeIndex = groupedNodes.some((node) => node.type === 'section') ? 1 : 0;
return groupedNodes; return groupedNodes;
} }
return extendItemsWithUUID(groupIfAiNodes(stack.baselineItems, true)); return extendItemsWithUUID(groupIfAiNodes(stack.baselineItems, stack.title, true));
}); });
const activeViewStack = computed<ViewStack>(() => { const activeViewStack = computed<ViewStack>(() => {
@@ -146,7 +147,7 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
}); });
const activeViewStackMode = computed( const activeViewStackMode = computed(
() => activeViewStack.value.mode || TRIGGER_NODE_CREATOR_VIEW, () => activeViewStack.value.mode ?? TRIGGER_NODE_CREATOR_VIEW,
); );
const searchBaseItems = computed<INodeCreateElement[]>(() => { const searchBaseItems = computed<INodeCreateElement[]>(() => {
@@ -183,7 +184,7 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
searchNodes(stack.search || '', filteredNodes), searchNodes(stack.search || '', filteredNodes),
); );
if (isAiRootView(stack)) { if (isAiRootView(stack)) {
globalSearchResult = groupIfAiNodes(globalSearchResult); globalSearchResult = groupIfAiNodes(globalSearchResult, stack.title, false);
} }
const filteredItems = globalSearchResult.filter((item) => { const filteredItems = globalSearchResult.filter((item) => {
@@ -233,7 +234,11 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
}); });
} }
function groupIfAiNodes(items: INodeCreateElement[], sortAlphabetically = true) { function groupIfAiNodes(
items: INodeCreateElement[],
stackCategory: string | undefined,
sortAlphabetically: boolean,
) {
const aiNodes = items.filter((node): node is NodeCreateElement => isAINode(node)); const aiNodes = items.filter((node): node is NodeCreateElement => isAINode(node));
const canvasHasAINodes = useCanvasStore().aiNodes.length > 0; const canvasHasAINodes = useCanvasStore().aiNodes.length > 0;
@@ -247,7 +252,12 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => {
const section = subcategories[AI_SUBCATEGORY]?.[0]; const section = subcategories[AI_SUBCATEGORY]?.[0];
if (section) { if (section) {
const subSection = subcategories[section]?.[0]; // Don't show sub sections for Vector Stores if we're currently viewing a 'Tools' stack
const subSection =
section === AI_CATEGORY_VECTOR_STORES && stackCategory === AI_CATEGORY_TOOLS
? undefined
: subcategories[section]?.[0];
const sectionKey = subSection ?? section; const sectionKey = subSection ?? section;
const currentItems = sectionsMap.get(sectionKey)?.items ?? []; const currentItems = sectionsMap.get(sectionKey)?.items ?? [];
const isSubnodesSection = !( const isSubnodesSection = !(