import {has, isEmpty} from 'licia' import type {JSX} from 'react' import {getAllIncomerNodeOutputVariables} from './Helper.tsx' import CodeNode from './node/CodeNode.tsx' import KnowledgeNode from './node/KnowledgeNode.tsx' import LlmNode from './node/LlmNode.tsx' import OutputNode from './node/OutputNode.tsx' import SwitchNode from './node/SwitchNode.tsx' import TemplateNode from './node/TemplateNode.tsx' import type {NodeChecker} from './types.ts' const inputSingleVariableChecker: (field: string) => NodeChecker = field => { return (id, inputSchema, nodes, edges, data) => { let nodeData = data[id] ?? {} if (has(nodeData, field)) { let expression = nodeData?.[field] ?? '' if (!isEmpty(expression)) { let outputVariables = new Set([ ...getAllIncomerNodeOutputVariables(id, nodes, edges, data).map(i => `${i.id}.${i.variable}`), ...Object.keys(inputSchema), ]) if (!outputVariables.has(expression)) { return { error: true, message: `节点 ${id} 存在错误:变量 ${expression} 不存在`, } } } } return {error: false} } } const inputMultiVariableChecker: NodeChecker = (id, inputSchema, nodes, edges, data) => { let nodeData = data[id] ?? {} if (has(nodeData, 'inputs')) { let inputs = nodeData?.inputs ?? {} if (!isEmpty(inputs)) { let outputVariables = new Set([ ...getAllIncomerNodeOutputVariables(id, nodes, edges, data).map(i => `${i.id}.${i.variable}`), ...Object.keys(inputSchema), ]) for (const key of Object.keys(inputs)) { let variable = inputs[key]?.variable ?? '' if (!outputVariables.has(variable)) { return { error: true, message: `节点 ${id} 存在错误:变量 ${variable} 不存在`, } } } } } return {error: false} } type NodeDefine = { key: string, group: string, name: string, icon: JSX.Element, description: string, component: any, checkers: NodeChecker[], } export const NodeRegistry: NodeDefine[] = [ { key: 'llm-node', group: '普通节点', name: '大模型', icon: , description: '使用大模型对话', component: LlmNode, checkers: [inputMultiVariableChecker], }, { key: 'knowledge-node', group: '普通节点', name: '知识库', icon: , description: '', component: KnowledgeNode, checkers: [inputMultiVariableChecker], }, { key: 'code-node', group: '普通节点', name: '代码执行', icon: , description: '执行自定义的处理代码', component: CodeNode, checkers: [inputMultiVariableChecker], }, { key: 'template-node', group: '普通节点', name: '模板替换', icon: , description: '使用模板聚合转换变量表示', component: TemplateNode, checkers: [inputMultiVariableChecker], }, { key: 'switch-node', group: '逻辑节点', name: '分支', icon: , description: '根据不同的情况前往不同的分支', component: SwitchNode, checkers: [], }, { key: 'output-node', group: '输出节点', name: '输出', icon: , description: '定义输出变量', component: OutputNode, checkers: [inputSingleVariableChecker('output')], }, ] export const NodeRegistryMap: Record = NodeRegistry.reduce((a, v) => ({...a, [v.key]: v}), {})