| 
									
										
										
										
											2024-05-27 21:57:08 +08:00
										 |  |  | import { useCallback } from 'react' | 
					
						
							|  |  |  | import produce from 'immer' | 
					
						
							|  |  |  | import { useBoolean } from 'ahooks' | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   useIsChatMode, | 
					
						
							|  |  |  |   useIsNodeInIteration, | 
					
						
							|  |  |  |   useNodesReadOnly, | 
					
						
							|  |  |  |   useWorkflow, | 
					
						
							|  |  |  | } from '../../hooks' | 
					
						
							|  |  |  | import { VarType } from '../../types' | 
					
						
							| 
									
										
										
										
											2024-11-05 10:32:49 +08:00
										 |  |  | import type { ErrorHandleMode, ValueSelector, Var } from '../../types' | 
					
						
							| 
									
										
										
										
											2024-05-27 21:57:08 +08:00
										 |  |  | import useNodeCrud from '../_base/hooks/use-node-crud' | 
					
						
							|  |  |  | import { getNodeInfoById, getNodeUsedVarPassToServerKey, getNodeUsedVars, isSystemVar, toNodeOutputVars } from '../_base/components/variable/utils' | 
					
						
							|  |  |  | import useOneStepRun from '../_base/hooks/use-one-step-run' | 
					
						
							|  |  |  | import type { IterationNodeType } from './types' | 
					
						
							|  |  |  | import type { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types' | 
					
						
							| 
									
										
										
										
											2024-11-05 10:32:49 +08:00
										 |  |  | import type { Item } from '@/app/components/base/select' | 
					
						
							| 
									
										
										
										
											2024-05-27 21:57:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | const DELIMITER = '@@@@@' | 
					
						
							|  |  |  | const useConfig = (id: string, payload: IterationNodeType) => { | 
					
						
							|  |  |  |   const { nodesReadOnly: readOnly } = useNodesReadOnly() | 
					
						
							|  |  |  |   const { isNodeInIteration } = useIsNodeInIteration(id) | 
					
						
							|  |  |  |   const isChatMode = useIsChatMode() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const { inputs, setInputs } = useNodeCrud<IterationNodeType>(id, payload) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const filterInputVar = useCallback((varPayload: Var) => { | 
					
						
							| 
									
										
										
										
											2024-10-21 10:32:37 +08:00
										 |  |  |     return [VarType.array, VarType.arrayString, VarType.arrayNumber, VarType.arrayObject, VarType.arrayFile].includes(varPayload.type) | 
					
						
							| 
									
										
										
										
											2024-05-27 21:57:08 +08:00
										 |  |  |   }, []) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const handleInputChange = useCallback((input: ValueSelector | string) => { | 
					
						
							|  |  |  |     const newInputs = produce(inputs, (draft) => { | 
					
						
							|  |  |  |       draft.iterator_selector = input as ValueSelector || [] | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     setInputs(newInputs) | 
					
						
							|  |  |  |   }, [inputs, setInputs]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // output
 | 
					
						
							|  |  |  |   const { getIterationNodeChildren, getBeforeNodesInSameBranch } = useWorkflow() | 
					
						
							|  |  |  |   const beforeNodes = getBeforeNodesInSameBranch(id) | 
					
						
							|  |  |  |   const iterationChildrenNodes = getIterationNodeChildren(id) | 
					
						
							|  |  |  |   const canChooseVarNodes = [...beforeNodes, ...iterationChildrenNodes] | 
					
						
							|  |  |  |   const childrenNodeVars = toNodeOutputVars(iterationChildrenNodes, isChatMode) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const handleOutputVarChange = useCallback((output: ValueSelector | string, _varKindType: VarKindType, varInfo?: Var) => { | 
					
						
							|  |  |  |     const newInputs = produce(inputs, (draft) => { | 
					
						
							|  |  |  |       draft.output_selector = output as ValueSelector || [] | 
					
						
							|  |  |  |       const outputItemType = varInfo?.type || VarType.string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       draft.output_type = ({ | 
					
						
							|  |  |  |         [VarType.string]: VarType.arrayString, | 
					
						
							|  |  |  |         [VarType.number]: VarType.arrayNumber, | 
					
						
							|  |  |  |         [VarType.object]: VarType.arrayObject, | 
					
						
							| 
									
										
										
										
											2024-10-21 10:32:37 +08:00
										 |  |  |         [VarType.file]: VarType.arrayFile, | 
					
						
							| 
									
										
										
										
											2024-05-27 21:57:08 +08:00
										 |  |  |       } as Record<VarType, VarType>)[outputItemType] || VarType.arrayString | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     setInputs(newInputs) | 
					
						
							|  |  |  |   }, [inputs, setInputs]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // single run
 | 
					
						
							|  |  |  |   const iteratorInputKey = `${id}.input_selector` | 
					
						
							|  |  |  |   const { | 
					
						
							|  |  |  |     isShowSingleRun, | 
					
						
							|  |  |  |     showSingleRun, | 
					
						
							|  |  |  |     hideSingleRun, | 
					
						
							|  |  |  |     toVarInputs, | 
					
						
							|  |  |  |     runningStatus, | 
					
						
							|  |  |  |     handleRun: doHandleRun, | 
					
						
							|  |  |  |     handleStop, | 
					
						
							|  |  |  |     runInputData, | 
					
						
							|  |  |  |     setRunInputData, | 
					
						
							|  |  |  |     runResult, | 
					
						
							|  |  |  |     iterationRunResult, | 
					
						
							|  |  |  |   } = useOneStepRun<IterationNodeType>({ | 
					
						
							|  |  |  |     id, | 
					
						
							|  |  |  |     data: inputs, | 
					
						
							|  |  |  |     iteratorInputKey, | 
					
						
							|  |  |  |     defaultRunInputData: { | 
					
						
							|  |  |  |       [iteratorInputKey]: [''], | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const [isShowIterationDetail, { | 
					
						
							|  |  |  |     setTrue: doShowIterationDetail, | 
					
						
							|  |  |  |     setFalse: doHideIterationDetail, | 
					
						
							|  |  |  |   }] = useBoolean(false) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const hideIterationDetail = useCallback(() => { | 
					
						
							|  |  |  |     hideSingleRun() | 
					
						
							|  |  |  |     doHideIterationDetail() | 
					
						
							|  |  |  |   }, [doHideIterationDetail, hideSingleRun]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const showIterationDetail = useCallback(() => { | 
					
						
							|  |  |  |     doShowIterationDetail() | 
					
						
							|  |  |  |   }, [doShowIterationDetail]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const backToSingleRun = useCallback(() => { | 
					
						
							|  |  |  |     hideIterationDetail() | 
					
						
							|  |  |  |     showSingleRun() | 
					
						
							|  |  |  |   }, [hideIterationDetail, showSingleRun]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const { usedOutVars, allVarObject } = (() => { | 
					
						
							|  |  |  |     const vars: ValueSelector[] = [] | 
					
						
							|  |  |  |     const varObjs: Record<string, boolean> = {} | 
					
						
							|  |  |  |     const allVarObject: Record<string, { | 
					
						
							|  |  |  |       inSingleRunPassedKey: string | 
					
						
							|  |  |  |     }> = {} | 
					
						
							|  |  |  |     iterationChildrenNodes.forEach((node) => { | 
					
						
							|  |  |  |       const nodeVars = getNodeUsedVars(node).filter(item => item && item.length > 0) | 
					
						
							|  |  |  |       nodeVars.forEach((varSelector) => { | 
					
						
							|  |  |  |         if (varSelector[0] === id) { // skip iteration node itself variable: item, index
 | 
					
						
							|  |  |  |           return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const isInIteration = isNodeInIteration(varSelector[0]) | 
					
						
							|  |  |  |         if (isInIteration) // not pass iteration inner variable
 | 
					
						
							|  |  |  |           return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const varSectorStr = varSelector.join('.') | 
					
						
							|  |  |  |         if (!varObjs[varSectorStr]) { | 
					
						
							|  |  |  |           varObjs[varSectorStr] = true | 
					
						
							|  |  |  |           vars.push(varSelector) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         let passToServerKeys = getNodeUsedVarPassToServerKey(node, varSelector) | 
					
						
							|  |  |  |         if (typeof passToServerKeys === 'string') | 
					
						
							|  |  |  |           passToServerKeys = [passToServerKeys] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         passToServerKeys.forEach((key: string, index: number) => { | 
					
						
							|  |  |  |           allVarObject[[varSectorStr, node.id, index].join(DELIMITER)] = { | 
					
						
							|  |  |  |             inSingleRunPassedKey: key, | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     const res = toVarInputs(vars.map((item) => { | 
					
						
							|  |  |  |       const varInfo = getNodeInfoById(canChooseVarNodes, item[0]) | 
					
						
							|  |  |  |       return { | 
					
						
							|  |  |  |         label: { | 
					
						
							|  |  |  |           nodeType: varInfo?.data.type, | 
					
						
							|  |  |  |           nodeName: varInfo?.data.title || canChooseVarNodes[0]?.data.title, // default start node title
 | 
					
						
							|  |  |  |           variable: isSystemVar(item) ? item.join('.') : item[item.length - 1], | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         variable: `${item.join('.')}`, | 
					
						
							|  |  |  |         value_selector: item, | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     })) | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |       usedOutVars: res, | 
					
						
							|  |  |  |       allVarObject, | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   })() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const handleRun = useCallback((data: Record<string, any>) => { | 
					
						
							|  |  |  |     const formattedData: Record<string, any> = {} | 
					
						
							|  |  |  |     Object.keys(allVarObject).forEach((key) => { | 
					
						
							|  |  |  |       const [varSectorStr, nodeId] = key.split(DELIMITER) | 
					
						
							|  |  |  |       formattedData[`${nodeId}.${allVarObject[key].inSingleRunPassedKey}`] = data[varSectorStr] | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     formattedData[iteratorInputKey] = data[iteratorInputKey] | 
					
						
							|  |  |  |     doHandleRun(formattedData) | 
					
						
							|  |  |  |   }, [allVarObject, doHandleRun, iteratorInputKey]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const inputVarValues = (() => { | 
					
						
							|  |  |  |     const vars: Record<string, any> = {} | 
					
						
							|  |  |  |     Object.keys(runInputData) | 
					
						
							|  |  |  |       .filter(key => ![iteratorInputKey].includes(key)) | 
					
						
							|  |  |  |       .forEach((key) => { | 
					
						
							|  |  |  |         vars[key] = runInputData[key] | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |     return vars | 
					
						
							|  |  |  |   })() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const setInputVarValues = useCallback((newPayload: Record<string, any>) => { | 
					
						
							|  |  |  |     const newVars = { | 
					
						
							|  |  |  |       ...newPayload, | 
					
						
							|  |  |  |       [iteratorInputKey]: runInputData[iteratorInputKey], | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     setRunInputData(newVars) | 
					
						
							|  |  |  |   }, [iteratorInputKey, runInputData, setRunInputData]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const iterator = runInputData[iteratorInputKey] | 
					
						
							|  |  |  |   const setIterator = useCallback((newIterator: string[]) => { | 
					
						
							|  |  |  |     setRunInputData({ | 
					
						
							|  |  |  |       ...runInputData, | 
					
						
							|  |  |  |       [iteratorInputKey]: newIterator, | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   }, [iteratorInputKey, runInputData, setRunInputData]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-05 10:32:49 +08:00
										 |  |  |   const changeParallel = useCallback((value: boolean) => { | 
					
						
							|  |  |  |     const newInputs = produce(inputs, (draft) => { | 
					
						
							|  |  |  |       draft.is_parallel = value | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     setInputs(newInputs) | 
					
						
							|  |  |  |   }, [inputs, setInputs]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const changeErrorResponseMode = useCallback((item: Item) => { | 
					
						
							|  |  |  |     const newInputs = produce(inputs, (draft) => { | 
					
						
							|  |  |  |       draft.error_handle_mode = item.value as ErrorHandleMode | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     setInputs(newInputs) | 
					
						
							|  |  |  |   }, [inputs, setInputs]) | 
					
						
							|  |  |  |   const changeParallelNums = useCallback((num: number) => { | 
					
						
							|  |  |  |     const newInputs = produce(inputs, (draft) => { | 
					
						
							|  |  |  |       draft.parallel_nums = num | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     setInputs(newInputs) | 
					
						
							|  |  |  |   }, [inputs, setInputs]) | 
					
						
							| 
									
										
										
										
											2024-05-27 21:57:08 +08:00
										 |  |  |   return { | 
					
						
							|  |  |  |     readOnly, | 
					
						
							|  |  |  |     inputs, | 
					
						
							|  |  |  |     filterInputVar, | 
					
						
							|  |  |  |     handleInputChange, | 
					
						
							|  |  |  |     childrenNodeVars, | 
					
						
							|  |  |  |     iterationChildrenNodes, | 
					
						
							|  |  |  |     handleOutputVarChange, | 
					
						
							|  |  |  |     isShowSingleRun, | 
					
						
							|  |  |  |     showSingleRun, | 
					
						
							|  |  |  |     hideSingleRun, | 
					
						
							|  |  |  |     isShowIterationDetail, | 
					
						
							|  |  |  |     showIterationDetail, | 
					
						
							|  |  |  |     hideIterationDetail, | 
					
						
							|  |  |  |     backToSingleRun, | 
					
						
							|  |  |  |     runningStatus, | 
					
						
							|  |  |  |     handleRun, | 
					
						
							|  |  |  |     handleStop, | 
					
						
							|  |  |  |     runResult, | 
					
						
							|  |  |  |     inputVarValues, | 
					
						
							|  |  |  |     setInputVarValues, | 
					
						
							|  |  |  |     usedOutVars, | 
					
						
							|  |  |  |     iterator, | 
					
						
							|  |  |  |     setIterator, | 
					
						
							|  |  |  |     iteratorInputKey, | 
					
						
							|  |  |  |     iterationRunResult, | 
					
						
							| 
									
										
										
										
											2024-11-05 10:32:49 +08:00
										 |  |  |     changeParallel, | 
					
						
							|  |  |  |     changeErrorResponseMode, | 
					
						
							|  |  |  |     changeParallelNums, | 
					
						
							| 
									
										
										
										
											2024-05-27 21:57:08 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default useConfig |