Co-authored-by: crazywoola <427733928@qq.com>tags/1.4.0
| getAvailablePrevNodes: (isChatMode: boolean) => BlockEnum[] | getAvailablePrevNodes: (isChatMode: boolean) => BlockEnum[] | ||||
| getAvailableNextNodes: (isChatMode: boolean) => BlockEnum[] | getAvailableNextNodes: (isChatMode: boolean) => BlockEnum[] | ||||
| checkValid: any | checkValid: any | ||||
| checkVarValid?: any | |||||
| } | } | ||||
| export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = { | export const NODES_EXTRA_DATA: Record<BlockEnum, NodesExtraData> = { | ||||
| [BlockEnum.Start]: { | [BlockEnum.Start]: { | ||||
| getAvailablePrevNodes: AnswerDefault.getAvailablePrevNodes, | getAvailablePrevNodes: AnswerDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: AnswerDefault.getAvailableNextNodes, | getAvailableNextNodes: AnswerDefault.getAvailableNextNodes, | ||||
| checkValid: AnswerDefault.checkValid, | checkValid: AnswerDefault.checkValid, | ||||
| checkVarValid: AnswerDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.LLM]: { | [BlockEnum.LLM]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: LLMDefault.getAvailablePrevNodes, | getAvailablePrevNodes: LLMDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: LLMDefault.getAvailableNextNodes, | getAvailableNextNodes: LLMDefault.getAvailableNextNodes, | ||||
| checkValid: LLMDefault.checkValid, | checkValid: LLMDefault.checkValid, | ||||
| checkVarValid: LLMDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.KnowledgeRetrieval]: { | [BlockEnum.KnowledgeRetrieval]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: KnowledgeRetrievalDefault.getAvailablePrevNodes, | getAvailablePrevNodes: KnowledgeRetrievalDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: KnowledgeRetrievalDefault.getAvailableNextNodes, | getAvailableNextNodes: KnowledgeRetrievalDefault.getAvailableNextNodes, | ||||
| checkValid: KnowledgeRetrievalDefault.checkValid, | checkValid: KnowledgeRetrievalDefault.checkValid, | ||||
| checkVarValid: KnowledgeRetrievalDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.IfElse]: { | [BlockEnum.IfElse]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: IfElseDefault.getAvailablePrevNodes, | getAvailablePrevNodes: IfElseDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: IfElseDefault.getAvailableNextNodes, | getAvailableNextNodes: IfElseDefault.getAvailableNextNodes, | ||||
| checkValid: IfElseDefault.checkValid, | checkValid: IfElseDefault.checkValid, | ||||
| checkVarValid: IfElseDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.Iteration]: { | [BlockEnum.Iteration]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: IterationDefault.getAvailablePrevNodes, | getAvailablePrevNodes: IterationDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: IterationDefault.getAvailableNextNodes, | getAvailableNextNodes: IterationDefault.getAvailableNextNodes, | ||||
| checkValid: IterationDefault.checkValid, | checkValid: IterationDefault.checkValid, | ||||
| checkVarValid: IterationDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.IterationStart]: { | [BlockEnum.IterationStart]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: CodeDefault.getAvailablePrevNodes, | getAvailablePrevNodes: CodeDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: CodeDefault.getAvailableNextNodes, | getAvailableNextNodes: CodeDefault.getAvailableNextNodes, | ||||
| checkValid: CodeDefault.checkValid, | checkValid: CodeDefault.checkValid, | ||||
| checkVarValid: CodeDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.TemplateTransform]: { | [BlockEnum.TemplateTransform]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: TemplateTransformDefault.getAvailablePrevNodes, | getAvailablePrevNodes: TemplateTransformDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: TemplateTransformDefault.getAvailableNextNodes, | getAvailableNextNodes: TemplateTransformDefault.getAvailableNextNodes, | ||||
| checkValid: TemplateTransformDefault.checkValid, | checkValid: TemplateTransformDefault.checkValid, | ||||
| checkVarValid: TemplateTransformDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.QuestionClassifier]: { | [BlockEnum.QuestionClassifier]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: QuestionClassifierDefault.getAvailablePrevNodes, | getAvailablePrevNodes: QuestionClassifierDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: QuestionClassifierDefault.getAvailableNextNodes, | getAvailableNextNodes: QuestionClassifierDefault.getAvailableNextNodes, | ||||
| checkValid: QuestionClassifierDefault.checkValid, | checkValid: QuestionClassifierDefault.checkValid, | ||||
| checkVarValid: QuestionClassifierDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.HttpRequest]: { | [BlockEnum.HttpRequest]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: HttpRequestDefault.getAvailablePrevNodes, | getAvailablePrevNodes: HttpRequestDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: HttpRequestDefault.getAvailableNextNodes, | getAvailableNextNodes: HttpRequestDefault.getAvailableNextNodes, | ||||
| checkValid: HttpRequestDefault.checkValid, | checkValid: HttpRequestDefault.checkValid, | ||||
| checkVarValid: HttpRequestDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.VariableAssigner]: { | [BlockEnum.VariableAssigner]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: AssignerDefault.getAvailablePrevNodes, | getAvailablePrevNodes: AssignerDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: AssignerDefault.getAvailableNextNodes, | getAvailableNextNodes: AssignerDefault.getAvailableNextNodes, | ||||
| checkValid: AssignerDefault.checkValid, | checkValid: AssignerDefault.checkValid, | ||||
| checkVarValid: AssignerDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.VariableAggregator]: { | [BlockEnum.VariableAggregator]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: VariableAssignerDefault.getAvailablePrevNodes, | getAvailablePrevNodes: VariableAssignerDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: VariableAssignerDefault.getAvailableNextNodes, | getAvailableNextNodes: VariableAssignerDefault.getAvailableNextNodes, | ||||
| checkValid: VariableAssignerDefault.checkValid, | checkValid: VariableAssignerDefault.checkValid, | ||||
| checkVarValid: VariableAssignerDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.ParameterExtractor]: { | [BlockEnum.ParameterExtractor]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: ParameterExtractorDefault.getAvailablePrevNodes, | getAvailablePrevNodes: ParameterExtractorDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: ParameterExtractorDefault.getAvailableNextNodes, | getAvailableNextNodes: ParameterExtractorDefault.getAvailableNextNodes, | ||||
| checkValid: ParameterExtractorDefault.checkValid, | checkValid: ParameterExtractorDefault.checkValid, | ||||
| checkVarValid: ParameterExtractorDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.Tool]: { | [BlockEnum.Tool]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: ToolDefault.getAvailablePrevNodes, | getAvailablePrevNodes: ToolDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: ToolDefault.getAvailableNextNodes, | getAvailableNextNodes: ToolDefault.getAvailableNextNodes, | ||||
| checkValid: ToolDefault.checkValid, | checkValid: ToolDefault.checkValid, | ||||
| checkVarValid: ToolDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.DocExtractor]: { | [BlockEnum.DocExtractor]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: DocExtractorDefault.getAvailablePrevNodes, | getAvailablePrevNodes: DocExtractorDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: DocExtractorDefault.getAvailableNextNodes, | getAvailableNextNodes: DocExtractorDefault.getAvailableNextNodes, | ||||
| checkValid: DocExtractorDefault.checkValid, | checkValid: DocExtractorDefault.checkValid, | ||||
| checkVarValid: DocExtractorDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.ListFilter]: { | [BlockEnum.ListFilter]: { | ||||
| author: 'Dify', | author: 'Dify', | ||||
| getAvailablePrevNodes: ListFilterDefault.getAvailablePrevNodes, | getAvailablePrevNodes: ListFilterDefault.getAvailablePrevNodes, | ||||
| getAvailableNextNodes: ListFilterDefault.getAvailableNextNodes, | getAvailableNextNodes: ListFilterDefault.getAvailableNextNodes, | ||||
| checkValid: ListFilterDefault.checkValid, | checkValid: ListFilterDefault.checkValid, | ||||
| checkVarValid: ListFilterDefault.checkVarValid, | |||||
| }, | }, | ||||
| [BlockEnum.Agent]: { | [BlockEnum.Agent]: { | ||||
| author: 'Dify', | author: 'Dify', |
| </div> | </div> | ||||
| ) | ) | ||||
| } | } | ||||
| { | |||||
| node.varErrorMessage?.map((errorMessage: string) => ( | |||||
| <div className='rounded-b-lg bg-gray-25 px-3 py-2'> | |||||
| <div className='flex text-xs leading-[18px] text-gray-500'> | |||||
| <AlertTriangle className='mr-2 mt-[3px] h-3 w-3 text-[#F79009]' /> | |||||
| {errorMessage} | |||||
| </div> | |||||
| </div> | |||||
| )) | |||||
| } | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| )) | )) |
| import { | import { | ||||
| getToolCheckParams, | getToolCheckParams, | ||||
| getValidTreeNodes, | getValidTreeNodes, | ||||
| transformStartNodeVariables, | |||||
| } from '../utils' | } from '../utils' | ||||
| import { | import { | ||||
| CUSTOM_NODE, | CUSTOM_NODE, | ||||
| const { data: strategyProviders } = useStrategyProviders() | const { data: strategyProviders } = useStrategyProviders() | ||||
| const datasetsDetail = useDatasetsDetailStore(s => s.datasetsDetail) | const datasetsDetail = useDatasetsDetailStore(s => s.datasetsDetail) | ||||
| const chatVarList = useStore(s => s.conversationVariables) | |||||
| const environmentVariables = useStore(s => s.environmentVariables) | |||||
| const getCheckData = useCallback((data: CommonNodeType<{}>) => { | const getCheckData = useCallback((data: CommonNodeType<{}>) => { | ||||
| let checkData = data | let checkData = data | ||||
| if (data.type === BlockEnum.KnowledgeRetrieval) { | if (data.type === BlockEnum.KnowledgeRetrieval) { | ||||
| const needWarningNodes = useMemo(() => { | const needWarningNodes = useMemo(() => { | ||||
| const list = [] | const list = [] | ||||
| const { validNodes } = getValidTreeNodes(nodes.filter(node => node.type === CUSTOM_NODE), edges) | |||||
| const { validNodes } = getValidTreeNodes(nodes.filter(node => node.type === CUSTOM_NODE), edges, true) | |||||
| const allVariablesMap = transformStartNodeVariables(chatVarList, environmentVariables) | |||||
| const errMessageMap = new Map() | |||||
| for (let i = 0; i < nodes.length; i++) { | for (let i = 0; i < nodes.length; i++) { | ||||
| const node = nodes[i] | const node = nodes[i] | ||||
| toolIcon, | toolIcon, | ||||
| unConnected: !validNodes.find(n => n.id === node.id), | unConnected: !validNodes.find(n => n.id === node.id), | ||||
| errorMessage, | errorMessage, | ||||
| varErrorMessage: [], | |||||
| }) | }) | ||||
| } | } | ||||
| errMessageMap.set(node.id, list[list.length - 1]) | |||||
| if (nodesExtraData[node.data.type as BlockEnum].checkVarValid) { | |||||
| const { errorMessage: varErrorMessages } = nodesExtraData[node.data.type as BlockEnum].checkVarValid(node.data, { ...allVariablesMap, ...node._parentOutputVarMap }, t) | |||||
| if (varErrorMessages?.length) { | |||||
| const errMessage = errMessageMap.get(node.id) | |||||
| if (errMessage) { | |||||
| errMessage.varErrorMessage = varErrorMessages | |||||
| } | |||||
| else { | |||||
| list.push({ | |||||
| id: node.id, | |||||
| type: node.data.type, | |||||
| title: node.data.title, | |||||
| toolIcon, | |||||
| unConnected: !validNodes.find(n => n.id === node.id), | |||||
| errorMessage: '', | |||||
| varErrorMessage: varErrorMessages, | |||||
| }) | |||||
| errMessageMap.set(node.id, list[list.length - 1]) | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| }) | }) | ||||
| } | } | ||||
| for (let i = 0; i < validNodes.length; i++) { | |||||
| const node = validNodes[i] | |||||
| delete node._parentOutputVarMap | |||||
| } | |||||
| return list | return list | ||||
| }, [nodes, edges, isChatMode, buildInTools, customTools, workflowTools, language, nodesExtraData, t, strategyProviders, getCheckData]) | |||||
| }, [nodes, edges, isChatMode, buildInTools, customTools, workflowTools, language, nodesExtraData, t, strategyProviders, getCheckData, chatVarList, environmentVariables]) | |||||
| return needWarningNodes | return needWarningNodes | ||||
| } | } | ||||
| const updateDatasetsDetail = useDatasetsDetailStore(s => s.updateDatasetsDetail) | const updateDatasetsDetail = useDatasetsDetailStore(s => s.updateDatasetsDetail) | ||||
| const updateTime = useRef(0) | const updateTime = useRef(0) | ||||
| const chatVarList = useStore(s => s.conversationVariables) | |||||
| const environmentVariables = useStore(s => s.environmentVariables) | |||||
| const getCheckData = useCallback((data: CommonNodeType<{}>, datasets: DataSet[]) => { | const getCheckData = useCallback((data: CommonNodeType<{}>, datasets: DataSet[]) => { | ||||
| let checkData = data | let checkData = data | ||||
| if (data.type === BlockEnum.KnowledgeRetrieval) { | if (data.type === BlockEnum.KnowledgeRetrieval) { | ||||
| const { | const { | ||||
| validNodes, | validNodes, | ||||
| maxDepth, | maxDepth, | ||||
| } = getValidTreeNodes(nodes.filter(node => node.type === CUSTOM_NODE), edges) | |||||
| } = getValidTreeNodes(nodes.filter(node => node.type === CUSTOM_NODE), edges, true) | |||||
| if (maxDepth > MAX_TREE_DEPTH) { | if (maxDepth > MAX_TREE_DEPTH) { | ||||
| notify({ type: 'error', message: t('workflow.common.maxTreeDepth', { depth: MAX_TREE_DEPTH }) }) | notify({ type: 'error', message: t('workflow.common.maxTreeDepth', { depth: MAX_TREE_DEPTH }) }) | ||||
| return false | return false | ||||
| } | } | ||||
| const allVariablesMap = transformStartNodeVariables(chatVarList, environmentVariables) | |||||
| // Before publish, we need to fetch datasets detail, in case of the settings of datasets have been changed | // Before publish, we need to fetch datasets detail, in case of the settings of datasets have been changed | ||||
| const knowledgeRetrievalNodes = nodes.filter(node => node.data.type === BlockEnum.KnowledgeRetrieval) | const knowledgeRetrievalNodes = nodes.filter(node => node.data.type === BlockEnum.KnowledgeRetrieval) | ||||
| const allDatasetIds = knowledgeRetrievalNodes.reduce<string[]>((acc, node) => { | const allDatasetIds = knowledgeRetrievalNodes.reduce<string[]>((acc, node) => { | ||||
| notify({ type: 'error', message: `[${node.data.title}] ${t('workflow.common.needConnectTip')}` }) | notify({ type: 'error', message: `[${node.data.title}] ${t('workflow.common.needConnectTip')}` }) | ||||
| return false | return false | ||||
| } | } | ||||
| if (nodesExtraData[node.data.type as BlockEnum].checkVarValid) { | |||||
| const { errorMessage: varErrorMessage } = nodesExtraData[node.data.type as BlockEnum].checkVarValid(node.data, { ...allVariablesMap, ...node._parentOutputVarMap }, t) | |||||
| if (varErrorMessage?.length) { | |||||
| notify({ type: 'error', message: `[${node.data.title}] ${varErrorMessage[0]}` }) | |||||
| return false | |||||
| } | |||||
| } | |||||
| } | } | ||||
| if (isChatMode && !nodes.find(node => node.data.type === BlockEnum.Answer)) { | if (isChatMode && !nodes.find(node => node.data.type === BlockEnum.Answer)) { | ||||
| } | } | ||||
| return true | return true | ||||
| }, [store, isChatMode, notify, t, buildInTools, customTools, workflowTools, language, nodesExtraData, strategyProviders, updateDatasetsDetail, getCheckData]) | |||||
| }, [store, isChatMode, notify, t, buildInTools, customTools, workflowTools, language, nodesExtraData, strategyProviders, updateDatasetsDetail, getCheckData, chatVarList, environmentVariables]) | |||||
| return { | return { | ||||
| handleCheckBeforePublish, | handleCheckBeforePublish, |
| return res | return res | ||||
| } | } | ||||
| const formatItem = ( | |||||
| export const formatItem = ( | |||||
| item: any, | item: any, | ||||
| isChatMode: boolean, | isChatMode: boolean, | ||||
| filterVar: (payload: Var, selector: ValueSelector) => boolean, | filterVar: (payload: Var, selector: ValueSelector) => boolean, |
| import { BlockEnum } from '../../types' | import { BlockEnum } from '../../types' | ||||
| import type { NodeDefault } from '../../types' | |||||
| import type { NodeDefault, Var } from '../../types' | |||||
| import { getNotExistVariablesByText } from '../../utils/workflow' | |||||
| import type { AnswerNodeType } from './types' | import type { AnswerNodeType } from './types' | ||||
| import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: AnswerNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr = [] | |||||
| const answer_warnings = getNotExistVariablesByText(payload.answer || '', varMap) | |||||
| if (answer_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.answer.answer')} ${t('workflow.common.referenceVar')}${answer_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: [...answer_warnings], | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import { BlockEnum } from '../../types' | import { BlockEnum } from '../../types' | ||||
| import type { NodeDefault } from '../../types' | |||||
| import type { NodeDefault, Var } from '../../types' | |||||
| import { getNotExistVariablesByArray } from '../../utils/workflow' | |||||
| import { type AssignerNodeType, WriteMode } from './types' | import { type AssignerNodeType, WriteMode } from './types' | ||||
| import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | ||||
| const i18nPrefix = 'workflow.errorMsg' | const i18nPrefix = 'workflow.errorMsg' | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: AssignerNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr: string[] = [] | |||||
| const variables_warnings = getNotExistVariablesByArray(payload.items.map(item => item.variable_selector ?? []) ?? [], varMap) | |||||
| if (variables_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.assigner.assignedVariable')} ${t('workflow.common.referenceVar')}${variables_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| const value_warnings = getNotExistVariablesByArray(payload.items.map(item => item.value ?? []) ?? [], varMap) | |||||
| if (value_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.assigner.setVariable')} ${t('workflow.common.referenceVar')}${value_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: [...variables_warnings, ...value_warnings], | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import { BlockEnum } from '../../types' | import { BlockEnum } from '../../types' | ||||
| import type { NodeDefault } from '../../types' | |||||
| import type { NodeDefault, Var } from '../../types' | |||||
| import { getNotExistVariablesByArray } from '../../utils/workflow' | |||||
| import { CodeLanguage, type CodeNodeType } from './types' | import { CodeLanguage, type CodeNodeType } from './types' | ||||
| import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: CodeNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr = [] | |||||
| const variables_selector = payload.variables.map(v => v.value_selector) | |||||
| const variables_selector_warnings = getNotExistVariablesByArray(variables_selector, varMap) | |||||
| if (variables_selector_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.code.inputVars')} ${t('workflow.common.referenceVar')}${variables_selector_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: variables_selector_warnings, | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import { BlockEnum } from '../../types' | import { BlockEnum } from '../../types' | ||||
| import type { NodeDefault } from '../../types' | |||||
| import type { NodeDefault, Var } from '../../types' | |||||
| import { getNotExistVariablesByArray } from '../../utils/workflow' | |||||
| import type { DocExtractorNodeType } from './types' | import type { DocExtractorNodeType } from './types' | ||||
| import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | ||||
| const i18nPrefix = 'workflow.errorMsg' | const i18nPrefix = 'workflow.errorMsg' | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: DocExtractorNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr: string[] = [] | |||||
| const variables_warnings = getNotExistVariablesByArray([payload.variable_selector], varMap) | |||||
| if (variables_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.docExtractor.inputVar')} ${t('workflow.common.referenceVar')}${variables_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: variables_warnings, | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import { BlockEnum } from '../../types' | import { BlockEnum } from '../../types' | ||||
| import type { NodeDefault } from '../../types' | |||||
| import type { NodeDefault, Var } from '../../types' | |||||
| import { getNotExistVariablesByArray, getNotExistVariablesByText } from '../../utils/workflow' | |||||
| import { AuthorizationType, BodyType, Method } from './types' | import { AuthorizationType, BodyType, Method } from './types' | ||||
| import type { BodyPayload, HttpNodeType } from './types' | import type { BodyPayload, HttpNodeType } from './types' | ||||
| import { | import { | ||||
| errorMessages = t('workflow.errorMsg.fieldRequired', { field: t('workflow.nodes.http.api') }) | errorMessages = t('workflow.errorMsg.fieldRequired', { field: t('workflow.nodes.http.api') }) | ||||
| if (!errorMessages | if (!errorMessages | ||||
| && payload.body.type === BodyType.binary | |||||
| && ((!(payload.body.data as BodyPayload)[0]?.file) || (payload.body.data as BodyPayload)[0]?.file?.length === 0) | |||||
| && payload.body.type === BodyType.binary | |||||
| && ((!(payload.body.data as BodyPayload)[0]?.file) || (payload.body.data as BodyPayload)[0]?.file?.length === 0) | |||||
| ) | ) | ||||
| errorMessages = t('workflow.errorMsg.fieldRequired', { field: t('workflow.nodes.http.binaryFileVariable') }) | errorMessages = t('workflow.errorMsg.fieldRequired', { field: t('workflow.nodes.http.binaryFileVariable') }) | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: HttpNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr: string[] = [] | |||||
| const url_warnings = getNotExistVariablesByText(payload.url, varMap) | |||||
| if (url_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.http.api')} ${t('workflow.common.referenceVar')}${url_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| const headers_warnings = getNotExistVariablesByText(payload.headers, varMap) | |||||
| if (headers_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.http.headers')} ${t('workflow.common.referenceVar')}${headers_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| const params_warnings = getNotExistVariablesByText(payload.params, varMap) | |||||
| if (params_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.http.params')} ${t('workflow.common.referenceVar')}${params_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| const body_warnings: string[] = [] | |||||
| if ([BodyType.binary].includes(payload.body.type)) { | |||||
| const body_data = payload.body.data as BodyPayload | |||||
| body_data.forEach((item) => { | |||||
| const key_warnings = getNotExistVariablesByText(item.key || '', varMap) | |||||
| if (key_warnings.length) | |||||
| body_warnings.push(...key_warnings) | |||||
| const warnings = getNotExistVariablesByArray([item.file || []], varMap) | |||||
| if (warnings.length) | |||||
| body_warnings.push(...warnings) | |||||
| }) | |||||
| } | |||||
| else { | |||||
| const body_data = payload.body.data as BodyPayload | |||||
| body_data.forEach((item) => { | |||||
| const key_warnings = getNotExistVariablesByText(item.key || '', varMap) | |||||
| if (key_warnings.length) | |||||
| body_warnings.push(...key_warnings) | |||||
| const value_warnings = getNotExistVariablesByText(item.value || '', varMap) | |||||
| if (value_warnings.length) | |||||
| body_warnings.push(...value_warnings) | |||||
| }) | |||||
| } | |||||
| if (body_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.http.body')} ${t('workflow.common.referenceVar')}${body_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: [...url_warnings, ...headers_warnings, ...params_warnings, ...body_warnings], | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import type { Var } from '../../types' | |||||
| import { BlockEnum, type NodeDefault } from '../../types' | import { BlockEnum, type NodeDefault } from '../../types' | ||||
| import { getNotExistVariablesByArray, getNotExistVariablesByText } from '../../utils/workflow' | |||||
| import { type IfElseNodeType, LogicalOperator } from './types' | import { type IfElseNodeType, LogicalOperator } from './types' | ||||
| import { isEmptyRelatedOperator } from './utils' | import { isEmptyRelatedOperator } from './utils' | ||||
| import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: IfElseNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr = [] | |||||
| const condition_variable_selector_warnings: string[] = [] | |||||
| const condition_value_warnings: string[] = [] | |||||
| payload.cases.forEach((caseItem) => { | |||||
| caseItem.conditions.forEach((condition) => { | |||||
| if (!condition.variable_selector) | |||||
| return | |||||
| const selector_warnings = getNotExistVariablesByArray([condition.variable_selector], varMap) | |||||
| if (selector_warnings.length) | |||||
| condition_variable_selector_warnings.push(...selector_warnings) | |||||
| const value_warnings = Array.isArray(condition.value) ? getNotExistVariablesByArray([condition.value], varMap) : getNotExistVariablesByText(condition.value, varMap) | |||||
| if (value_warnings.length) | |||||
| condition_value_warnings.push(...value_warnings) | |||||
| condition.sub_variable_condition?.conditions.forEach((subCondition) => { | |||||
| const sub_variable_value_warnings = Array.isArray(subCondition.value) ? getNotExistVariablesByArray([subCondition.value], varMap) : getNotExistVariablesByText(subCondition.value, varMap) | |||||
| if (sub_variable_value_warnings.length) | |||||
| condition_value_warnings.push(...sub_variable_value_warnings) | |||||
| }) | |||||
| }) | |||||
| }) | |||||
| if (condition_variable_selector_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.ifElse.condition')} ${t('workflow.common.referenceVar')}${condition_variable_selector_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| if (condition_value_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.ifElse.enterValue')} ${t('workflow.common.referenceVar')}${condition_value_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: condition_variable_selector_warnings, | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import { BlockEnum, ErrorHandleMode } from '../../types' | import { BlockEnum, ErrorHandleMode } from '../../types' | ||||
| import type { NodeDefault } from '../../types' | |||||
| import type { NodeDefault, Var } from '../../types' | |||||
| import { getNotExistVariablesByArray } from '../../utils/workflow' | |||||
| import type { IterationNodeType } from './types' | import type { IterationNodeType } from './types' | ||||
| import { | import { | ||||
| ALL_CHAT_AVAILABLE_BLOCKS, | ALL_CHAT_AVAILABLE_BLOCKS, | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: IterationNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr: string[] = [] | |||||
| const iterator_selector_warnings = getNotExistVariablesByArray([payload.iterator_selector], varMap) | |||||
| if (iterator_selector_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.iteration.input')} ${t('workflow.common.referenceVar')}${iterator_selector_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: iterator_selector_warnings, | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import { BlockEnum } from '../../types' | import { BlockEnum } from '../../types' | ||||
| import type { NodeDefault } from '../../types' | |||||
| import type { NodeDefault, Var } from '../../types' | |||||
| import { getNotExistVariablesByArray } from '../../utils/workflow' | |||||
| import type { KnowledgeRetrievalNodeType } from './types' | import type { KnowledgeRetrievalNodeType } from './types' | ||||
| import { checkoutRerankModelConfigedInRetrievalSettings } from './utils' | import { checkoutRerankModelConfigedInRetrievalSettings } from './utils' | ||||
| import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: KnowledgeRetrievalNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr = [] | |||||
| const query_variable_selector_warnings = getNotExistVariablesByArray([payload.query_variable_selector], varMap) | |||||
| if (query_variable_selector_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.knowledgeRetrieval.queryVariable')} ${t('workflow.common.referenceVar')}${query_variable_selector_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: [...query_variable_selector_warnings], | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import { BlockEnum, VarType } from '../../types' | import { BlockEnum, VarType } from '../../types' | ||||
| import type { NodeDefault } from '../../types' | |||||
| import type { NodeDefault, Var } from '../../types' | |||||
| import { getNotExistVariablesByArray } from '../../utils/workflow' | |||||
| import { comparisonOperatorNotRequireValue } from '../if-else/utils' | import { comparisonOperatorNotRequireValue } from '../if-else/utils' | ||||
| import { type ListFilterNodeType, OrderBy } from './types' | import { type ListFilterNodeType, OrderBy } from './types' | ||||
| import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: ListFilterNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr = [] | |||||
| const variable_warnings = getNotExistVariablesByArray([payload.variable], varMap) | |||||
| if (variable_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.listFilter.inputVar')} ${t('workflow.common.referenceVar')}${variable_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: variable_warnings, | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import { BlockEnum, EditionType } from '../../types' | |||||
| import type { Var } from '../../types' | |||||
| import { BlockEnum, EditionType, VarType } from '../../types' | |||||
| import { type NodeDefault, type PromptItem, PromptRole } from '../../types' | import { type NodeDefault, type PromptItem, PromptRole } from '../../types' | ||||
| import { getNotExistVariablesByArray, getNotExistVariablesByText } from '../../utils/workflow' | |||||
| import type { LLMNodeType } from './types' | import type { LLMNodeType } from './types' | ||||
| import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: LLMNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr = [] | |||||
| const prompt_templates_warnings: string[] = [] | |||||
| if (payload.context?.enabled && payload.context?.variable_selector?.length) { | |||||
| const context_variable_selector_warnings = getNotExistVariablesByArray([payload.context.variable_selector], varMap) | |||||
| if (context_variable_selector_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.llm.context')} ${t('workflow.common.referenceVar')}${context_variable_selector_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| } | |||||
| const prompt_templates = Array.isArray(payload.prompt_template) ? payload.prompt_template : [payload.prompt_template] as PromptItem[] | |||||
| prompt_templates.forEach((v) => { | |||||
| prompt_templates_warnings.push(...getNotExistVariablesByText(v.text, { context: { variable: 'context', type: VarType.string }, ...varMap })) | |||||
| }) | |||||
| if (prompt_templates_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.llm.prompt')} ${t('workflow.common.referenceVar')}${prompt_templates_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| const memory_query_prompt_template_warnings = getNotExistVariablesByText(payload.memory?.query_prompt_template || '', varMap) | |||||
| if (memory_query_prompt_template_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.common.memories.title')}USER ${t('workflow.common.referenceVar')}${memory_query_prompt_template_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| if (payload.vision?.enabled && payload.vision?.configs?.variable_selector?.length) { | |||||
| const vision_variable_selector_warnings = getNotExistVariablesByArray([payload.vision.configs.variable_selector], varMap) | |||||
| if (vision_variable_selector_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.llm.vision')} ${t('workflow.common.referenceVar')}${vision_variable_selector_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| } | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: [...prompt_templates_warnings, ...memory_query_prompt_template_warnings], | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import { BlockEnum } from '../../types' | import { BlockEnum } from '../../types' | ||||
| import type { NodeDefault } from '../../types' | |||||
| import type { NodeDefault, Var } from '../../types' | |||||
| import { getNotExistVariablesByArray, getNotExistVariablesByText } from '../../utils/workflow' | |||||
| import { type ParameterExtractorNodeType, ReasoningModeType } from './types' | import { type ParameterExtractorNodeType, ReasoningModeType } from './types' | ||||
| import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | ||||
| const i18nPrefix = 'workflow' | const i18nPrefix = 'workflow' | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: ParameterExtractorNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr: string[] = [] | |||||
| const variables_warnings = getNotExistVariablesByArray([payload.query], varMap) | |||||
| if (variables_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.parameterExtractor.inputVar')} ${t('workflow.common.referenceVar')}${variables_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| let vision_variable_warnings: string[] = [] | |||||
| if (payload.vision?.configs?.variable_selector?.length) { | |||||
| vision_variable_warnings = getNotExistVariablesByArray([payload.vision.configs.variable_selector], varMap) | |||||
| if (vision_variable_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.llm.vision')} ${t('workflow.common.referenceVar')}${vision_variable_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| } | |||||
| const instruction_warnings = getNotExistVariablesByText(payload.instruction, varMap) | |||||
| if (instruction_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.parameterExtractor.instruction')} ${t('workflow.common.referenceVar')}${instruction_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: [...variables_warnings, ...vision_variable_warnings, ...instruction_warnings], | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import type { NodeDefault } from '../../types' | |||||
| import type { NodeDefault, Var } from '../../types' | |||||
| import { BlockEnum } from '../../types' | import { BlockEnum } from '../../types' | ||||
| import { getNotExistVariablesByArray, getNotExistVariablesByText } from '../../utils/workflow' | |||||
| import type { QuestionClassifierNodeType } from './types' | import type { QuestionClassifierNodeType } from './types' | ||||
| import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: QuestionClassifierNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr = [] | |||||
| const query_variable_selector_warnings = getNotExistVariablesByArray([payload.query_variable_selector], varMap) | |||||
| if (query_variable_selector_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.questionClassifiers.inputVars')} ${t('workflow.common.referenceVar')}${query_variable_selector_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| let vision_variable_selector_warnings: string[] = [] | |||||
| if (payload.vision?.configs?.variable_selector?.length) { | |||||
| vision_variable_selector_warnings = getNotExistVariablesByArray([payload.vision?.configs?.variable_selector], varMap) | |||||
| if (vision_variable_selector_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.llm.vision')} ${t('workflow.common.referenceVar')}${vision_variable_selector_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| } | |||||
| const instruction_warnings: string[] = getNotExistVariablesByText(payload.instruction, varMap) | |||||
| if (instruction_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.questionClassifiers.advancedSetting')}-${t('workflow.nodes.questionClassifiers.instruction')} ${t('workflow.common.referenceVar')}${instruction_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: [...query_variable_selector_warnings, ...vision_variable_selector_warnings, ...instruction_warnings], | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import { BlockEnum } from '../../types' | import { BlockEnum } from '../../types' | ||||
| import type { NodeDefault } from '../../types' | |||||
| import type { NodeDefault, Var } from '../../types' | |||||
| import { getNotExistVariablesByArray } from '../../utils/workflow' | |||||
| import type { TemplateTransformNodeType } from './types' | import type { TemplateTransformNodeType } from './types' | ||||
| import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | ||||
| const i18nPrefix = 'workflow.errorMsg' | const i18nPrefix = 'workflow.errorMsg' | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: TemplateTransformNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr = [] | |||||
| const variables_selector = payload.variables.map(v => v.value_selector) | |||||
| const variables_selector_warnings = getNotExistVariablesByArray(variables_selector, varMap) | |||||
| if (variables_selector_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.templateTransform.inputVars')} ${t('workflow.common.referenceVar')}${variables_selector_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import { BlockEnum } from '../../types' | import { BlockEnum } from '../../types' | ||||
| import type { NodeDefault } from '../../types' | |||||
| import type { NodeDefault, Var } from '../../types' | |||||
| import type { ToolNodeType } from './types' | import type { ToolNodeType } from './types' | ||||
| import { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types' | import { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types' | ||||
| import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | ||||
| import { getNotExistVariablesByArray, getNotExistVariablesByText } from '../../utils/workflow' | |||||
| const i18nPrefix = 'workflow.errorMsg' | const i18nPrefix = 'workflow.errorMsg' | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: ToolNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr = [] | |||||
| const tool_parametersMap = payload.tool_parameters | |||||
| const tool_parameters_array = Object.values(tool_parametersMap) | |||||
| const tool_parameters_warnings: string[] = [] | |||||
| tool_parameters_array?.forEach((item) => { | |||||
| if (!item.value) | |||||
| return | |||||
| if (Array.isArray(item.value)) { | |||||
| const warnings = getNotExistVariablesByArray([item.value], varMap) | |||||
| if (warnings.length) | |||||
| tool_parameters_warnings.push(...warnings) | |||||
| return | |||||
| } | |||||
| if (typeof item.value === 'string') { | |||||
| const warnings = getNotExistVariablesByText(item.value, varMap) | |||||
| if (warnings.length) | |||||
| tool_parameters_warnings.push(...warnings) | |||||
| } | |||||
| }) | |||||
| if (tool_parameters_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.tool.inputVars')} ${t('workflow.common.referenceVar')}${tool_parameters_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: tool_parameters_warnings, | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| import type { Var } from '../../types' | |||||
| import { type NodeDefault, VarType } from '../../types' | import { type NodeDefault, VarType } from '../../types' | ||||
| import { BlockEnum } from '../../types' | import { BlockEnum } from '../../types' | ||||
| import { getNotExistVariablesByArray } from '../../utils/workflow' | |||||
| import type { VariableAssignerNodeType } from './types' | import type { VariableAssignerNodeType } from './types' | ||||
| import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | import { ALL_CHAT_AVAILABLE_BLOCKS, ALL_COMPLETION_AVAILABLE_BLOCKS } from '@/app/components/workflow/blocks' | ||||
| errorMessage: errorMessages, | errorMessage: errorMessages, | ||||
| } | } | ||||
| }, | }, | ||||
| checkVarValid(payload: VariableAssignerNodeType, varMap: Record<string, Var>, t: any) { | |||||
| const errorMessageArr: string[] = [] | |||||
| const variables_warnings = getNotExistVariablesByArray(payload.variables ?? [], varMap) | |||||
| if (variables_warnings.length) | |||||
| errorMessageArr.push(`${t('workflow.nodes.variableAssigner.title')} ${t('workflow.common.referenceVar')}${variables_warnings.join('、')}${t('workflow.common.noExist')}`) | |||||
| return { | |||||
| isValid: true, | |||||
| warning_vars: variables_warnings, | |||||
| errorMessage: errorMessageArr, | |||||
| } | |||||
| }, | |||||
| } | } | ||||
| export default nodeDefault | export default nodeDefault |
| getAvailablePrevNodes: (isChatMode: boolean) => BlockEnum[] | getAvailablePrevNodes: (isChatMode: boolean) => BlockEnum[] | ||||
| getAvailableNextNodes: (isChatMode: boolean) => BlockEnum[] | getAvailableNextNodes: (isChatMode: boolean) => BlockEnum[] | ||||
| checkValid: (payload: T, t: any, moreDataForCheckValid?: any) => { isValid: boolean; errorMessage?: string } | checkValid: (payload: T, t: any, moreDataForCheckValid?: any) => { isValid: boolean; errorMessage?: string } | ||||
| checkVarValid?: (payload: T, varMap: Record<string, Var>, t: any,) => { isValid: boolean; errorMessage?: string[] } | |||||
| } | } | ||||
| export type OnSelectBlock = (type: BlockEnum, toolDefaultValue?: ToolDefaultValue) => void | export type OnSelectBlock = (type: BlockEnum, toolDefaultValue?: ToolDefaultValue) => void |
| } from '@/app/components/workflow/types' | } from '@/app/components/workflow/types' | ||||
| import { CUSTOM_ITERATION_START_NODE } from '@/app/components/workflow/nodes/iteration-start/constants' | import { CUSTOM_ITERATION_START_NODE } from '@/app/components/workflow/nodes/iteration-start/constants' | ||||
| jest.mock('ky', () => ({ | |||||
| __esModule: true, | |||||
| default: { | |||||
| create: jest.fn(), | |||||
| }, | |||||
| })) | |||||
| jest.mock('lodash-es/groupBy', () => ({ | |||||
| __esModule: true, | |||||
| default: jest.fn(), | |||||
| })) | |||||
| describe('preprocessNodesAndEdges', () => { | describe('preprocessNodesAndEdges', () => { | ||||
| it('process nodes without iteration node or loop node should return origin nodes and edges.', () => { | it('process nodes without iteration node or loop node should return origin nodes and edges.', () => { | ||||
| const nodes = [ | const nodes = [ |
| uniqBy, | uniqBy, | ||||
| } from 'lodash-es' | } from 'lodash-es' | ||||
| import type { | import type { | ||||
| ConversationVariable, | |||||
| Edge, | Edge, | ||||
| EnvironmentVariable, | |||||
| Node, | Node, | ||||
| Var, | |||||
| } from '../types' | } from '../types' | ||||
| import { | import { | ||||
| BlockEnum, | BlockEnum, | ||||
| } from '../types' | } from '../types' | ||||
| import type { IterationNodeType } from '../nodes/iteration/types' | import type { IterationNodeType } from '../nodes/iteration/types' | ||||
| import type { LoopNodeType } from '../nodes/loop/types' | import type { LoopNodeType } from '../nodes/loop/types' | ||||
| import { VAR_REGEX_TEXT } from '@/config' | |||||
| import { formatItem } from '../nodes/_base/components/variable/utils' | |||||
| import type { StructuredOutput } from '../nodes/llm/types' | |||||
| export const canRunBySingle = (nodeType: BlockEnum) => { | export const canRunBySingle = (nodeType: BlockEnum) => { | ||||
| return nodeType === BlockEnum.LLM | return nodeType === BlockEnum.LLM | ||||
| return nodesConnectedSourceOrTargetHandleIdsMap | return nodesConnectedSourceOrTargetHandleIdsMap | ||||
| } | } | ||||
| export const getValidTreeNodes = (nodes: Node[], edges: Edge[]) => { | |||||
| function getParentOutputVarMap(item: Var, path: string, varMap: Record<string, Var>) { | |||||
| if (!item.children || (Array.isArray(item.children) && !item.children.length) || ((item.children as StructuredOutput).schema)) | |||||
| return | |||||
| (item.children as Var[]).forEach((child) => { | |||||
| const newPath = `${path}.${child.variable}` | |||||
| varMap[newPath] = child | |||||
| getParentOutputVarMap(child, newPath, varMap) | |||||
| }) | |||||
| } | |||||
| export const getValidTreeNodes = (nodes: Node[], edges: Edge[], isCollectVar?: boolean) => { | |||||
| const startNode = nodes.find(node => node.data.type === BlockEnum.Start) | const startNode = nodes.find(node => node.data.type === BlockEnum.Start) | ||||
| if (!startNode) { | if (!startNode) { | ||||
| outgoers.forEach((outgoer) => { | outgoers.forEach((outgoer) => { | ||||
| list.push(outgoer) | list.push(outgoer) | ||||
| if (isCollectVar) { | |||||
| const nodeObj = formatItem(root, false, () => true) | |||||
| const varMap = {} as Record<string, Var> | |||||
| nodeObj.vars.forEach((item) => { | |||||
| if (item.variable.startsWith('sys.')) | |||||
| return | |||||
| const newPath = `${nodeObj.nodeId}.${item.variable}` | |||||
| varMap[newPath] = item | |||||
| getParentOutputVarMap(item, newPath, varMap) | |||||
| }) | |||||
| outgoer._parentOutputVarMap = { ...(root._parentOutputVarMap ?? {}), ...varMap } | |||||
| } | |||||
| if (outgoer.data.type === BlockEnum.Iteration) | if (outgoer.data.type === BlockEnum.Iteration) | ||||
| list.push(...nodes.filter(node => node.parentId === outgoer.id)) | list.push(...nodes.filter(node => node.parentId === outgoer.id)) | ||||
| if (outgoer.data.type === BlockEnum.Loop) | if (outgoer.data.type === BlockEnum.Loop) | ||||
| export const hasErrorHandleNode = (nodeType?: BlockEnum) => { | export const hasErrorHandleNode = (nodeType?: BlockEnum) => { | ||||
| return nodeType === BlockEnum.LLM || nodeType === BlockEnum.Tool || nodeType === BlockEnum.HttpRequest || nodeType === BlockEnum.Code | return nodeType === BlockEnum.LLM || nodeType === BlockEnum.Tool || nodeType === BlockEnum.HttpRequest || nodeType === BlockEnum.Code | ||||
| } | } | ||||
| export const transformStartNodeVariables = (chatVarList: ConversationVariable[], environmentVariables: EnvironmentVariable[]) => { | |||||
| const variablesMap: Record<string, ConversationVariable | EnvironmentVariable> = {} | |||||
| chatVarList.forEach((variable) => { | |||||
| variablesMap[`conversation.${variable.name}`] = variable | |||||
| }) | |||||
| environmentVariables.forEach((variable) => { | |||||
| variablesMap[`env.${variable.name}`] = variable | |||||
| }) | |||||
| return variablesMap | |||||
| } | |||||
| export const getNotExistVariablesByText = (text: string, varMap: Record<string, Var>) => { | |||||
| const var_warnings: string[] = [] | |||||
| text?.replace(VAR_REGEX_TEXT, (str, id_name) => { | |||||
| if (id_name.startsWith('sys.')) | |||||
| return str | |||||
| if (varMap[id_name]) | |||||
| return str | |||||
| const arr = id_name.split('.') | |||||
| arr.shift() | |||||
| var_warnings.push(arr.join('.')) | |||||
| return str | |||||
| }) | |||||
| return var_warnings | |||||
| } | |||||
| export const getNotExistVariablesByArray = (array: string[][], varMap: Record<string, Var>) => { | |||||
| if (!array.length) | |||||
| return [] | |||||
| const var_warnings: string[] = [] | |||||
| array.forEach((item) => { | |||||
| if (!item.length) | |||||
| return | |||||
| if (['sys'].includes(item[0])) | |||||
| return | |||||
| const var_warning = varMap[item.join('.')] | |||||
| if (var_warning) | |||||
| return | |||||
| const arr = [...item] | |||||
| arr.shift() | |||||
| var_warnings.push(arr.join('.')) | |||||
| }) | |||||
| return var_warnings | |||||
| } |
| export const VAR_REGEX = /\{\{(#[a-zA-Z0-9_-]{1,50}(\.[a-zA-Z_]\w{0,29}){1,10}#)\}\}/gi | export const VAR_REGEX = /\{\{(#[a-zA-Z0-9_-]{1,50}(\.[a-zA-Z_]\w{0,29}){1,10}#)\}\}/gi | ||||
| export const VAR_REGEX_TEXT = /\{\{#([a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)*)#\}\}/gi | |||||
| export const resetReg = () => VAR_REGEX.lastIndex = 0 | export const resetReg = () => VAR_REGEX.lastIndex = 0 | ||||
| export let textGenerationTimeoutMs = 60000 | export let textGenerationTimeoutMs = 60000 |
| addFailureBranch: 'Add Fail Branch', | addFailureBranch: 'Add Fail Branch', | ||||
| loadMore: 'Load More', | loadMore: 'Load More', | ||||
| noHistory: 'No History', | noHistory: 'No History', | ||||
| referenceVar: 'Reference Variable', | |||||
| noExist: 'No such variable', | |||||
| }, | }, | ||||
| env: { | env: { | ||||
| envPanelTitle: 'Environment Variables', | envPanelTitle: 'Environment Variables', | ||||
| selectVariable: 'Select variable...', | selectVariable: 'Select variable...', | ||||
| addSubVariable: 'Sub Variable', | addSubVariable: 'Sub Variable', | ||||
| select: 'Select', | select: 'Select', | ||||
| condition: 'Condition', | |||||
| }, | }, | ||||
| variableAssigner: { | variableAssigner: { | ||||
| title: 'Assign variables', | title: 'Assign variables', |
| addFailureBranch: '失敗ブランチを追加', | addFailureBranch: '失敗ブランチを追加', | ||||
| loadMore: 'さらに読み込む', | loadMore: 'さらに読み込む', | ||||
| noHistory: '履歴がありません', | noHistory: '履歴がありません', | ||||
| referenceVar: '参照変数', | |||||
| noExist: '存在しません', | |||||
| }, | }, | ||||
| env: { | env: { | ||||
| envPanelTitle: '環境変数', | envPanelTitle: '環境変数', | ||||
| }, | }, | ||||
| select: '選ぶ', | select: '選ぶ', | ||||
| addSubVariable: 'サブ変数', | addSubVariable: 'サブ変数', | ||||
| condition: '条件', | |||||
| }, | }, | ||||
| variableAssigner: { | variableAssigner: { | ||||
| title: '変数を代入する', | title: '変数を代入する', |
| openInExplore: '在“探索”中打开', | openInExplore: '在“探索”中打开', | ||||
| loadMore: '加载更多', | loadMore: '加载更多', | ||||
| noHistory: '没有历史版本', | noHistory: '没有历史版本', | ||||
| referenceVar: '引用变量', | |||||
| noExist: '不存在', | |||||
| }, | }, | ||||
| env: { | env: { | ||||
| envPanelTitle: '环境变量', | envPanelTitle: '环境变量', | ||||
| selectVariable: '选择变量', | selectVariable: '选择变量', | ||||
| addSubVariable: '添加子变量', | addSubVariable: '添加子变量', | ||||
| select: '选择', | select: '选择', | ||||
| condition: '条件', | |||||
| }, | }, | ||||
| variableAssigner: { | variableAssigner: { | ||||
| title: '变量赋值', | title: '变量赋值', |