fix: 修复TypeScript配置错误并更新项目文档
详细说明: - 修复了@n8n/config包的TypeScript配置错误 - 移除了不存在的jest-expect-message类型引用 - 清理了所有TypeScript构建缓存 - 更新了可行性分析文档,添加了技术实施方案 - 更新了Agent prompt文档 - 添加了会展策划工作流文档 - 包含了n8n-chinese-translation子项目 - 添加了exhibition-demo展示系统框架
This commit is contained in:
114
n8n-n8n-1.109.2/packages/@n8n/nodes-langchain/utils/N8nTool 2.ts
Executable file
114
n8n-n8n-1.109.2/packages/@n8n/nodes-langchain/utils/N8nTool 2.ts
Executable file
@@ -0,0 +1,114 @@
|
||||
import type { DynamicStructuredToolInput } from '@langchain/core/tools';
|
||||
import { DynamicStructuredTool, DynamicTool } from '@langchain/core/tools';
|
||||
import { StructuredOutputParser } from 'langchain/output_parsers';
|
||||
import type { ISupplyDataFunctions, IDataObject } from 'n8n-workflow';
|
||||
import { NodeConnectionTypes, jsonParse, NodeOperationError } from 'n8n-workflow';
|
||||
import type { ZodTypeAny } from 'zod';
|
||||
import { ZodBoolean, ZodNullable, ZodNumber, ZodObject, ZodOptional } from 'zod';
|
||||
|
||||
import type { ZodObjectAny } from '../types/types';
|
||||
|
||||
const getSimplifiedType = (schema: ZodTypeAny) => {
|
||||
if (schema instanceof ZodObject) {
|
||||
return 'object';
|
||||
} else if (schema instanceof ZodNumber) {
|
||||
return 'number';
|
||||
} else if (schema instanceof ZodBoolean) {
|
||||
return 'boolean';
|
||||
} else if (schema instanceof ZodNullable || schema instanceof ZodOptional) {
|
||||
return getSimplifiedType(schema.unwrap());
|
||||
}
|
||||
|
||||
return 'string';
|
||||
};
|
||||
|
||||
const getParametersDescription = (parameters: Array<[string, ZodTypeAny]>) =>
|
||||
parameters
|
||||
.map(
|
||||
([name, schema]) =>
|
||||
`${name}: (description: ${schema.description ?? ''}, type: ${getSimplifiedType(schema)}, required: ${!schema.isOptional()})`,
|
||||
)
|
||||
.join(',\n ');
|
||||
|
||||
export const prepareFallbackToolDescription = (toolDescription: string, schema: ZodObject<any>) => {
|
||||
let description = `${toolDescription}`;
|
||||
|
||||
const toolParameters = Object.entries<ZodTypeAny>(schema.shape);
|
||||
|
||||
if (toolParameters.length) {
|
||||
description += `
|
||||
Tool expects valid stringified JSON object with ${toolParameters.length} properties.
|
||||
Property names with description, type and required status:
|
||||
${getParametersDescription(toolParameters)}
|
||||
ALL parameters marked as required must be provided`;
|
||||
}
|
||||
|
||||
return description;
|
||||
};
|
||||
|
||||
export class N8nTool extends DynamicStructuredTool<ZodObjectAny> {
|
||||
constructor(
|
||||
private context: ISupplyDataFunctions,
|
||||
fields: DynamicStructuredToolInput<ZodObjectAny>,
|
||||
) {
|
||||
super(fields);
|
||||
}
|
||||
|
||||
asDynamicTool(): DynamicTool {
|
||||
const { name, func, schema, context, description } = this;
|
||||
|
||||
const parser = new StructuredOutputParser(schema);
|
||||
|
||||
const wrappedFunc = async function (query: string) {
|
||||
let parsedQuery: object;
|
||||
|
||||
// First we try to parse the query using the structured parser (Zod schema)
|
||||
try {
|
||||
parsedQuery = await parser.parse(query);
|
||||
} catch (e) {
|
||||
// If we were unable to parse the query using the schema, we try to gracefully handle it
|
||||
let dataFromModel;
|
||||
|
||||
try {
|
||||
// First we try to parse a JSON with more relaxed rules
|
||||
dataFromModel = jsonParse<IDataObject>(query, { acceptJSObject: true });
|
||||
} catch (error) {
|
||||
// In case of error,
|
||||
// If model supplied a simple string instead of an object AND only one parameter expected, we try to recover the object structure
|
||||
if (Object.keys(schema.shape).length === 1) {
|
||||
const parameterName = Object.keys(schema.shape)[0];
|
||||
dataFromModel = { [parameterName]: query };
|
||||
} else {
|
||||
// Finally throw an error if we were unable to parse the query
|
||||
throw new NodeOperationError(
|
||||
context.getNode(),
|
||||
`Input is not a valid JSON: ${error.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// If we were able to parse the query with a fallback, we try to validate it using the schema
|
||||
// Here we will throw an error if the data still does not match the schema
|
||||
parsedQuery = schema.parse(dataFromModel);
|
||||
}
|
||||
|
||||
try {
|
||||
// Call tool function with parsed query
|
||||
const result = await func(parsedQuery);
|
||||
|
||||
return result;
|
||||
} catch (e) {
|
||||
const { index } = context.addInputData(NodeConnectionTypes.AiTool, [[{ json: { query } }]]);
|
||||
void context.addOutputData(NodeConnectionTypes.AiTool, index, e);
|
||||
|
||||
return e.toString();
|
||||
}
|
||||
};
|
||||
|
||||
return new DynamicTool({
|
||||
name,
|
||||
description: prepareFallbackToolDescription(description, schema),
|
||||
func: wrappedFunc,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user