mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
fix(editor): Show previous nodes autocomplete in AI tool nodes (#11111)
This commit is contained in:
parent
05d267954c
commit
8566b3a999
|
@ -1,5 +1,16 @@
|
||||||
import { expressionWithFirstItem } from '../utils';
|
import { createTestNode, createTestWorkflowObject } from '@/__tests__/mocks';
|
||||||
|
import * as workflowHelpers from '@/composables/useWorkflowHelpers';
|
||||||
import { javascriptLanguage } from '@codemirror/lang-javascript';
|
import { javascriptLanguage } from '@codemirror/lang-javascript';
|
||||||
|
import { autocompletableNodeNames, expressionWithFirstItem } from '../utils';
|
||||||
|
import type { MockInstance } from 'vitest';
|
||||||
|
import * as ndvStore from '@/stores/ndv.store';
|
||||||
|
import { NodeConnectionType, type IConnections } from 'n8n-workflow';
|
||||||
|
|
||||||
|
vi.mock('@/composables/useWorkflowHelpers', () => ({
|
||||||
|
useWorkflowHelpers: vi.fn().mockReturnValue({
|
||||||
|
getCurrentWorkflow: vi.fn(),
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
describe('completion utils', () => {
|
describe('completion utils', () => {
|
||||||
describe('expressionWithFirstItem', () => {
|
describe('expressionWithFirstItem', () => {
|
||||||
|
@ -43,4 +54,72 @@ describe('completion utils', () => {
|
||||||
expect(result).toBe(expected);
|
expect(result).toBe(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('autocompletableNodeNames', () => {
|
||||||
|
it('should work for normal nodes', () => {
|
||||||
|
const nodes = [
|
||||||
|
createTestNode({ name: 'Node 1' }),
|
||||||
|
createTestNode({ name: 'Node 2' }),
|
||||||
|
createTestNode({ name: 'Node 3' }),
|
||||||
|
];
|
||||||
|
const connections = {
|
||||||
|
[nodes[0].name]: {
|
||||||
|
[NodeConnectionType.Main]: [
|
||||||
|
[{ node: nodes[1].name, type: NodeConnectionType.Main, index: 0 }],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
[nodes[1].name]: {
|
||||||
|
[NodeConnectionType.Main]: [
|
||||||
|
[{ node: nodes[2].name, type: NodeConnectionType.Main, index: 0 }],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const workflowObject = createTestWorkflowObject({
|
||||||
|
nodes,
|
||||||
|
connections,
|
||||||
|
});
|
||||||
|
|
||||||
|
const workflowHelpersMock: MockInstance = vi.spyOn(workflowHelpers, 'useWorkflowHelpers');
|
||||||
|
workflowHelpersMock.mockReturnValue({
|
||||||
|
getCurrentWorkflow: vi.fn(() => workflowObject),
|
||||||
|
});
|
||||||
|
const ndvStoreMock: MockInstance = vi.spyOn(ndvStore, 'useNDVStore');
|
||||||
|
ndvStoreMock.mockReturnValue({ activeNode: nodes[2] });
|
||||||
|
|
||||||
|
expect(autocompletableNodeNames()).toEqual(['Node 2', 'Node 1']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work for AI tool nodes', () => {
|
||||||
|
const nodes = [
|
||||||
|
createTestNode({ name: 'Normal Node' }),
|
||||||
|
createTestNode({ name: 'Agent' }),
|
||||||
|
createTestNode({ name: 'Tool' }),
|
||||||
|
];
|
||||||
|
const connections: IConnections = {
|
||||||
|
[nodes[0].name]: {
|
||||||
|
[NodeConnectionType.Main]: [
|
||||||
|
[{ node: nodes[1].name, type: NodeConnectionType.Main, index: 0 }],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
[nodes[2].name]: {
|
||||||
|
[NodeConnectionType.AiMemory]: [
|
||||||
|
[{ node: nodes[1].name, type: NodeConnectionType.AiMemory, index: 0 }],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const workflowObject = createTestWorkflowObject({
|
||||||
|
nodes,
|
||||||
|
connections,
|
||||||
|
});
|
||||||
|
|
||||||
|
const workflowHelpersMock: MockInstance = vi.spyOn(workflowHelpers, 'useWorkflowHelpers');
|
||||||
|
workflowHelpersMock.mockReturnValue({
|
||||||
|
getCurrentWorkflow: vi.fn(() => workflowObject),
|
||||||
|
});
|
||||||
|
const ndvStoreMock: MockInstance = vi.spyOn(ndvStore, 'useNDVStore');
|
||||||
|
ndvStoreMock.mockReturnValue({ activeNode: nodes[2] });
|
||||||
|
|
||||||
|
expect(autocompletableNodeNames()).toEqual(['Normal Node']);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -208,15 +208,29 @@ export const isSplitInBatchesAbsent = () =>
|
||||||
!useWorkflowsStore().workflow.nodes.some((node) => node.type === SPLIT_IN_BATCHES_NODE_TYPE);
|
!useWorkflowsStore().workflow.nodes.some((node) => node.type === SPLIT_IN_BATCHES_NODE_TYPE);
|
||||||
|
|
||||||
export function autocompletableNodeNames() {
|
export function autocompletableNodeNames() {
|
||||||
const activeNodeName = useNDVStore().activeNode?.name;
|
const activeNode = useNDVStore().activeNode;
|
||||||
|
|
||||||
if (!activeNodeName) return [];
|
if (!activeNode) return [];
|
||||||
|
|
||||||
return useWorkflowHelpers({ router: useRouter() })
|
const activeNodeName = activeNode.name;
|
||||||
.getCurrentWorkflow()
|
|
||||||
.getParentNodesByDepth(activeNodeName)
|
const workflow = useWorkflowHelpers({ router: useRouter() }).getCurrentWorkflow();
|
||||||
|
const nonMainChildren = workflow.getChildNodes(activeNodeName, 'ALL_NON_MAIN');
|
||||||
|
|
||||||
|
// This is a tool node, look for the nearest node with main connections
|
||||||
|
if (nonMainChildren.length > 0) {
|
||||||
|
return nonMainChildren.map(getPreviousNodes).flat();
|
||||||
|
}
|
||||||
|
|
||||||
|
return getPreviousNodes(activeNodeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPreviousNodes(nodeName: string) {
|
||||||
|
const workflow = useWorkflowHelpers({ router: useRouter() }).getCurrentWorkflow();
|
||||||
|
return workflow
|
||||||
|
.getParentNodesByDepth(nodeName)
|
||||||
.map((node) => node.name)
|
.map((node) => node.name)
|
||||||
.filter((name) => name !== activeNodeName);
|
.filter((name) => name !== nodeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue