mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 10:31:15 +00:00
feat(editor): Align DynamicStructuredTool and DynamicTool name fields (#14604)
feat(Code Tool Node): Use node's name instead of separate name field as tool name feat(Vector Store Tool Node): Use node's name instead of separate name field as tool name feat(Custom n8n Workflow Tool Node): Use node's name instead of separate name field as tool name
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import { DynamicTool } from 'langchain/tools';
|
||||
import { type INode, type ISupplyDataFunctions } from 'n8n-workflow';
|
||||
|
||||
import { ToolWorkflow } from './ToolWorkflow.node';
|
||||
import type { ToolWorkflowV2 } from './v2/ToolWorkflowV2.node';
|
||||
|
||||
describe('ToolWorkflowV2', () => {
|
||||
describe('supplyData', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('should read name from node name on version >=2.2', async () => {
|
||||
const toolWorkflowNode = new ToolWorkflow();
|
||||
const node = toolWorkflowNode.nodeVersions[2.2] as ToolWorkflowV2;
|
||||
|
||||
const supplyDataResult = await node.supplyData.call(
|
||||
mock<ISupplyDataFunctions>({
|
||||
getNode: jest.fn(() => mock<INode>({ typeVersion: 2.2, name: 'test tool' })),
|
||||
getNodeParameter: jest.fn().mockImplementation((paramName, _itemIndex) => {
|
||||
switch (paramName) {
|
||||
case 'description':
|
||||
return 'description text';
|
||||
case 'name':
|
||||
return 'wrong_field';
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}),
|
||||
}),
|
||||
0,
|
||||
);
|
||||
|
||||
expect(supplyDataResult.response).toBeInstanceOf(DynamicTool);
|
||||
|
||||
const tool = supplyDataResult.response as DynamicTool;
|
||||
expect(tool.name).toBe('test_tool');
|
||||
expect(tool.description).toBe('description text');
|
||||
expect(tool.func).toBeInstanceOf(Function);
|
||||
});
|
||||
|
||||
it('should read name from name parameter on version <2.2', async () => {
|
||||
const toolWorkflowNode = new ToolWorkflow();
|
||||
const node = toolWorkflowNode.nodeVersions[2.1] as ToolWorkflowV2;
|
||||
|
||||
const supplyDataResult = await node.supplyData.call(
|
||||
mock<ISupplyDataFunctions>({
|
||||
getNode: jest.fn(() => mock<INode>({ typeVersion: 2.1, name: 'wrong name' })),
|
||||
getNodeParameter: jest.fn().mockImplementation((paramName, _itemIndex) => {
|
||||
switch (paramName) {
|
||||
case 'description':
|
||||
return 'description text';
|
||||
case 'name':
|
||||
return 'test_tool';
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}),
|
||||
}),
|
||||
0,
|
||||
);
|
||||
|
||||
expect(supplyDataResult.response).toBeInstanceOf(DynamicTool);
|
||||
|
||||
const tool = supplyDataResult.response as DynamicTool;
|
||||
expect(tool.name).toBe('test_tool');
|
||||
expect(tool.description).toBe('description text');
|
||||
expect(tool.func).toBeInstanceOf(Function);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -28,7 +28,7 @@ export class ToolWorkflow extends VersionedNodeType {
|
||||
],
|
||||
},
|
||||
},
|
||||
defaultVersion: 2.1,
|
||||
defaultVersion: 2.2,
|
||||
};
|
||||
|
||||
const nodeVersions: IVersionedNodeType['nodeVersions'] = {
|
||||
@@ -38,6 +38,7 @@ export class ToolWorkflow extends VersionedNodeType {
|
||||
1.3: new ToolWorkflowV1(baseDescription),
|
||||
2: new ToolWorkflowV2(baseDescription),
|
||||
2.1: new ToolWorkflowV2(baseDescription),
|
||||
2.2: new ToolWorkflowV2(baseDescription),
|
||||
};
|
||||
super(nodeVersions, baseDescription);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import type {
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { nodeNameToToolName } from '@utils/helpers';
|
||||
|
||||
import { localResourceMapping } from './methods';
|
||||
import { WorkflowToolService } from './utils/WorkflowToolService';
|
||||
import { versionDescription } from './versionDescription';
|
||||
@@ -25,10 +27,15 @@ export class ToolWorkflowV2 implements INodeType {
|
||||
};
|
||||
|
||||
async supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData> {
|
||||
const returnAllItems = this.getNode().typeVersion > 2;
|
||||
const node = this.getNode();
|
||||
const { typeVersion } = node;
|
||||
const returnAllItems = typeVersion > 2;
|
||||
|
||||
const workflowToolService = new WorkflowToolService(this, { returnAllItems });
|
||||
const name = this.getNodeParameter('name', itemIndex) as string;
|
||||
const name =
|
||||
typeVersion <= 2.1
|
||||
? (this.getNodeParameter('name', itemIndex) as string)
|
||||
: nodeNameToToolName(node);
|
||||
const description = this.getNodeParameter('description', itemIndex) as string;
|
||||
|
||||
const tool = await workflowToolService.createTool({
|
||||
|
||||
@@ -12,7 +12,7 @@ export const versionDescription: INodeTypeDescription = {
|
||||
defaults: {
|
||||
name: 'Call n8n Workflow Tool',
|
||||
},
|
||||
version: [2, 2.1],
|
||||
version: [2, 2.1, 2.2],
|
||||
inputs: [],
|
||||
outputs: [NodeConnectionTypes.AiTool],
|
||||
outputNames: ['Tool'],
|
||||
@@ -34,6 +34,11 @@ export const versionDescription: INodeTypeDescription = {
|
||||
validateType: 'string-alphanumeric',
|
||||
description:
|
||||
'The name of the function to be called, could contain letters, numbers, and underscores only',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [{ _cnd: { lte: 2.1 } }],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Description',
|
||||
|
||||
Reference in New Issue
Block a user