import type { NodeTracing } from '@/types/workflow' import { addChildrenToIterationNode } from './iteration' import { addChildrenToLoopNode } from './loop' import formatParallelNode from './parallel' import formatRetryNode from './retry' import formatAgentNode from './agent' import { cloneDeep } from 'lodash-es' import { BlockEnum } from '../../../types' const formatIterationAndLoopNode = (list: NodeTracing[], t: any) => { const clonedList = cloneDeep(list) // Identify all loop and iteration nodes const loopNodeIds = clonedList .filter(item => item.node_type === BlockEnum.Loop) .map(item => item.node_id) const iterationNodeIds = clonedList .filter(item => item.node_type === BlockEnum.Iteration) .map(item => item.node_id) // Identify all child nodes for both loop and iteration const loopChildrenNodeIds = clonedList .filter(item => item.execution_metadata?.loop_id && loopNodeIds.includes(item.execution_metadata.loop_id)) .map(item => item.node_id) const iterationChildrenNodeIds = clonedList .filter(item => item.execution_metadata?.iteration_id && iterationNodeIds.includes(item.execution_metadata.iteration_id)) .map(item => item.node_id) // Filter out child nodes as they will be included in their parent nodes const result = clonedList .filter(item => !loopChildrenNodeIds.includes(item.node_id) && !iterationChildrenNodeIds.includes(item.node_id)) .map((item) => { // Process Loop nodes if (item.node_type === BlockEnum.Loop) { const childrenNodes = clonedList.filter(child => child.execution_metadata?.loop_id === item.node_id) const error = childrenNodes.find(child => child.status === 'failed') if (error) { item.status = 'failed' item.error = error.error } const addedChildrenList = addChildrenToLoopNode(item, childrenNodes) // Handle parallel nodes in loop node if (addedChildrenList.details && addedChildrenList.details.length > 0) { addedChildrenList.details = addedChildrenList.details.map((row) => { return formatParallelNode(row, t) }) } return addedChildrenList } // Process Iteration nodes if (item.node_type === BlockEnum.Iteration) { const childrenNodes = clonedList.filter(child => child.execution_metadata?.iteration_id === item.node_id) const error = childrenNodes.find(child => child.status === 'failed') if (error) { item.status = 'failed' item.error = error.error } const addedChildrenList = addChildrenToIterationNode(item, childrenNodes) // Handle parallel nodes in iteration node if (addedChildrenList.details && addedChildrenList.details.length > 0) { addedChildrenList.details = addedChildrenList.details.map((row) => { return formatParallelNode(row, t) }) } return addedChildrenList } return item }) return result } const formatToTracingNodeList = (list: NodeTracing[], t: any) => { const allItems = cloneDeep([...list]).sort((a, b) => a.index - b.index) /* * First handle not change list structure node * Because Handle struct node will put the node in different */ const formattedAgentList = formatAgentNode(allItems) const formattedRetryList = formatRetryNode(formattedAgentList) // retry one node // would change the structure of the list. Iteration and parallel can include each other. const formattedLoopAndIterationList = formatIterationAndLoopNode(formattedRetryList, t) const formattedParallelList = formatParallelNode(formattedLoopAndIterationList, t) const result = formattedParallelList // console.log(allItems) // console.log(result) return result } export default formatToTracingNodeList