UNPKG

@n8n/n8n-nodes-langchain

Version:

![Banner image](https://user-images.githubusercontent.com/10284570/173569848-c624317f-42b1-45a6-ab09-f0ea3c247648.png)

325 lines 11.9 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var ToolCode_node_exports = {}; __export(ToolCode_node_exports, { ToolCode: () => ToolCode }); module.exports = __toCommonJS(ToolCode_node_exports); var import_tools = require("@langchain/core/tools"); var import_config = require("@n8n/config"); var import_di = require("@n8n/di"); var import_JavaScriptSandbox = require("n8n-nodes-base/dist/nodes/Code/JavaScriptSandbox"); var import_JsTaskRunnerSandbox = require("n8n-nodes-base/dist/nodes/Code/JsTaskRunnerSandbox"); var import_PythonTaskRunnerSandbox = require("n8n-nodes-base/dist/nodes/Code/PythonTaskRunnerSandbox"); var import_Sandbox = require("n8n-nodes-base/dist/nodes/Code/Sandbox"); var import_n8n_workflow = require("n8n-workflow"); var import_descriptions = require("../../../utils/descriptions"); var import_schemaParsing = require("../../../utils/schemaParsing"); var import_sharedFields = require("../../../utils/sharedFields"); const jsonSchemaExampleField = (0, import_descriptions.buildJsonSchemaExampleField)({ showExtraProps: { specifyInputSchema: [true] } }); const jsonSchemaExampleNotice = (0, import_descriptions.buildJsonSchemaExampleNotice)({ showExtraProps: { specifyInputSchema: [true], "@version": [{ _cnd: { gte: 1.3 } }] } }); const jsonSchemaField = (0, import_descriptions.buildInputSchemaField)({ showExtraProps: { specifyInputSchema: [true] } }); function getTool(ctx, itemIndex, log = true) { const node = ctx.getNode(); const workflowMode = ctx.getMode(); const runnersConfig = import_di.Container.get(import_config.TaskRunnersConfig); const isJsRunnerEnabled = runnersConfig.enabled; const { typeVersion } = node; const name = typeVersion <= 1.1 ? ctx.getNodeParameter("name", itemIndex) : (0, import_n8n_workflow.nodeNameToToolName)(node); const description = ctx.getNodeParameter("description", itemIndex); const useSchema = ctx.getNodeParameter("specifyInputSchema", itemIndex); const language = ctx.getNodeParameter("language", itemIndex); let code = ""; if (language === "javaScript") { code = ctx.getNodeParameter("jsCode", itemIndex); } else { code = ctx.getNodeParameter("pythonCode", itemIndex); } const runFunction = async (query) => { if (language === "javaScript") { if (isJsRunnerEnabled) { const sandbox = new import_JsTaskRunnerSandbox.JsTaskRunnerSandbox( code, "runOnceForAllItems", workflowMode, ctx, void 0, { query } ); return await sandbox.runCodeForTool(); } else { const context = import_Sandbox.getSandboxContext.call(ctx, itemIndex); context.query = query; const sandbox = new import_JavaScriptSandbox.JavaScriptSandbox(context, code, ctx.helpers); sandbox.on( "output", workflowMode === "manual" ? ctx.sendMessageToUI.bind(ctx) : (...args) => console.log(`[Workflow "${ctx.getWorkflow().id}"][Node "${node.name}"]`, ...args) ); return await sandbox.runCode(); } } else { const sandbox = new import_PythonTaskRunnerSandbox.PythonTaskRunnerSandbox( code, "runOnceForAllItems", workflowMode, ctx, { query } ); return await sandbox.runCodeForTool(); } }; const toolHandler = async (query) => { const { index } = log ? ctx.addInputData(import_n8n_workflow.NodeConnectionTypes.AiTool, [[{ json: { query } }]]) : { index: 0 }; let response = ""; let executionError; try { response = await runFunction(query); } catch (error) { executionError = new import_n8n_workflow.NodeOperationError(ctx.getNode(), error); response = `There was an error: "${executionError.message}"`; } if (typeof response === "number") { response = response.toString(); } if (typeof response !== "string") { executionError = new import_n8n_workflow.NodeOperationError(ctx.getNode(), "Wrong output type returned", { description: `The response property should be a string, but it is an ${typeof response}` }); response = `There was an error: "${executionError.message}"`; } if (executionError && log) { void ctx.addOutputData(import_n8n_workflow.NodeConnectionTypes.AiTool, index, executionError); } else if (log) { void ctx.addOutputData(import_n8n_workflow.NodeConnectionTypes.AiTool, index, [[{ json: { response } }]]); } return response; }; const commonToolOptions = { name, description, func: toolHandler }; let tool = void 0; if (useSchema) { try { const jsonExample = ctx.getNodeParameter("jsonSchemaExample", itemIndex, ""); const inputSchema = ctx.getNodeParameter("inputSchema", itemIndex, ""); const schemaType = ctx.getNodeParameter("schemaType", itemIndex); const jsonSchema = schemaType === "fromJson" ? (0, import_schemaParsing.generateSchemaFromExample)(jsonExample, ctx.getNode().typeVersion >= 1.3) : (0, import_n8n_workflow.jsonParse)(inputSchema); const zodSchema = (0, import_schemaParsing.convertJsonSchemaToZod)(jsonSchema); tool = new import_tools.DynamicStructuredTool({ schema: zodSchema, ...commonToolOptions }); } catch (error) { throw new import_n8n_workflow.NodeOperationError( ctx.getNode(), "Error during parsing of JSON Schema. \n " + error ); } } else { tool = new import_tools.DynamicTool(commonToolOptions); } return tool; } class ToolCode { constructor() { this.description = { displayName: "Code Tool", name: "toolCode", icon: "fa:code", iconColor: "black", group: ["transform"], version: [1, 1.1, 1.2, 1.3], description: "Write a tool in JS or Python", defaults: { name: "Code Tool" }, codex: { categories: ["AI"], subcategories: { AI: ["Tools"], Tools: ["Recommended Tools"] }, resources: { primaryDocumentation: [ { url: "https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolcode/" } ] } }, inputs: [], outputs: [import_n8n_workflow.NodeConnectionTypes.AiTool], outputNames: ["Tool"], properties: [ (0, import_sharedFields.getConnectionHintNoticeField)([import_n8n_workflow.NodeConnectionTypes.AiAgent]), { displayName: 'See an example of a conversational agent with custom tool written in JavaScript <a href="/templates/1963" target="_blank">here</a>.', name: "noticeTemplateExample", type: "notice", default: "" }, { displayName: "Name", name: "name", type: "string", default: "", placeholder: "My_Tool", displayOptions: { show: { "@version": [1] } } }, { displayName: "Name", name: "name", type: "string", default: "", placeholder: "e.g. My_Tool", validateType: "string-alphanumeric", description: "The name of the function to be called, could contain letters, numbers, and underscores only", displayOptions: { show: { "@version": [1.1] } } }, { displayName: "Description", name: "description", type: "string", default: "", placeholder: "Call this tool to get a random color. The input should be a string with comma separted names of colors to exclude.", typeOptions: { rows: 3 } }, { displayName: "Language", name: "language", type: "options", noDataExpression: true, options: [ { name: "JavaScript", value: "javaScript" }, { name: "Python (Beta)", value: "python" } ], default: "javaScript" }, { displayName: "JavaScript", name: "jsCode", type: "string", displayOptions: { show: { language: ["javaScript"] } }, typeOptions: { editor: "jsEditor" }, default: "// Example: convert the incoming query to uppercase and return it\nreturn query.toUpperCase()", // TODO: Add proper text here later hint: 'You can access the input the tool receives via the input property "query". The returned value should be a single string.', // eslint-disable-next-line n8n-nodes-base/node-param-description-missing-final-period description: "E.g. Converts any text to uppercase", noDataExpression: true }, { displayName: "Python", name: "pythonCode", type: "string", displayOptions: { show: { language: ["python"] } }, typeOptions: { editor: "codeNodeEditor", // TODO: create a separate `pythonEditor` component editorLanguage: "python" }, default: "# Example: convert the incoming query to uppercase and return it\nreturn _query.upper()", // TODO: Add proper text here later hint: 'You can access the input the tool receives via the input property "_query". The returned value should be a single string.', // eslint-disable-next-line n8n-nodes-base/node-param-description-missing-final-period description: "E.g. Converts any text to uppercase", noDataExpression: true }, { displayName: "Specify Input Schema", name: "specifyInputSchema", type: "boolean", description: "Whether to specify the schema for the function. This would require the LLM to provide the input in the correct format and would validate it against the schema.", noDataExpression: true, default: false }, { ...import_descriptions.schemaTypeField, displayOptions: { show: { specifyInputSchema: [true] } } }, jsonSchemaExampleField, jsonSchemaExampleNotice, jsonSchemaField ] }; } async supplyData(itemIndex) { return { response: getTool(this, itemIndex) }; } async execute() { const result = []; const input = this.getInputData(); for (let i = 0; i < input.length; i++) { const item = input[i]; const tool = getTool(this, i, false); result.push({ json: { response: await tool.invoke(item.json) }, pairedItem: { item: i } }); } return [result]; } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { ToolCode }); //# sourceMappingURL=ToolCode.node.js.map