diff --git a/web/app/components/workflow/hooks/use-workflow-run.ts b/web/app/components/workflow/hooks/use-workflow-run.ts index a445a31f61..83e2a262c5 100644 --- a/web/app/components/workflow/hooks/use-workflow-run.ts +++ b/web/app/components/workflow/hooks/use-workflow-run.ts @@ -312,18 +312,38 @@ export const useWorkflowRun = () => { getNodes, setNodes, } = store.getState() + if (isInIteration) { setWorkflowRunningData(produce(workflowRunningData!, (draft) => { const tracing = draft.tracing! - const iterations = tracing[tracing.length - 1] - const currIteration = iterations.details![iterations.details!.length - 1] - const nodeInfo = currIteration[currIteration.length - 1] + const iterations = tracing[tracing.length - 1] // the iteration node - currIteration[currIteration.length - 1] = { - ...nodeInfo, - ...data, - status: NodeRunningStatus.Succeeded, - } as any + if (iterations && iterations.details) { + const iterationIndex = data.execution_metadata?.iteration_index || 0 + // console.log(`the current iteration index is ${iterationIndex}`) + + // console.log(JSON.parse(JSON.stringify(iterations.details))) + + if (!iterations.details[iterationIndex]) + iterations.details[iterationIndex] = [] + + const currIteration = iterations.details[iterationIndex] + const nodeIndex = currIteration.findIndex(node => + node.node_id === data.node_id, + ) + + if (nodeIndex !== -1) { + currIteration[nodeIndex] = { + ...(currIteration[nodeIndex].extras ? { extras: currIteration[nodeIndex].extras } : {}), + ...data, + } as any + } + else { + currIteration.push({ + ...data, + } as any) + } + } })) } else { @@ -332,12 +352,8 @@ export const useWorkflowRun = () => { const currentIndex = draft.tracing!.findIndex((trace) => { if (!trace.execution_metadata?.parallel_id) return trace.node_id === data.node_id - if (trace.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id) - return trace.node_id === data.node_id && trace.execution_metadata?.parallel_start_node_id === data.execution_metadata?.parallel_start_node_id - return trace.node_id === data.node_id && trace.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id }) - if (currentIndex > -1 && draft.tracing) { draft.tracing[currentIndex] = { ...(draft.tracing[currentIndex].extras @@ -347,16 +363,14 @@ export const useWorkflowRun = () => { } as any } })) - const newNodes = produce(nodes, (draft) => { const currentNode = draft.find(node => node.id === data.node_id)! - currentNode.data._runningStatus = data.status as any }) setNodes(newNodes) - prevNodeId = data.node_id } + if (onNodeFinished) onNodeFinished(params) }, diff --git a/web/app/components/workflow/panel/debug-and-preview/hooks.ts b/web/app/components/workflow/panel/debug-and-preview/hooks.ts index 978666b6a5..c23b73f874 100644 --- a/web/app/components/workflow/panel/debug-and-preview/hooks.ts +++ b/web/app/components/workflow/panel/debug-and-preview/hooks.ts @@ -385,9 +385,6 @@ export const useChat = ( const currentIndex = responseItem.workflowProcess!.tracing!.findIndex((item) => { if (!item.execution_metadata?.parallel_id) return item.node_id === data.node_id - if (item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id) - return item.node_id === data.node_id && item.execution_metadata?.parallel_start_node_id === data.execution_metadata?.parallel_start_node_id - return item.node_id === data.node_id && item.execution_metadata?.parallel_id === data.execution_metadata?.parallel_id }) responseItem.workflowProcess!.tracing[currentIndex] = { diff --git a/web/app/components/workflow/run/iteration-result-panel.tsx b/web/app/components/workflow/run/iteration-result-panel.tsx index 7a88d4da0a..b79d61f461 100644 --- a/web/app/components/workflow/run/iteration-result-panel.tsx +++ b/web/app/components/workflow/run/iteration-result-panel.tsx @@ -1,10 +1,14 @@ 'use client' import type { FC } from 'react' -import React, { useCallback } from 'react' +import React, { useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' -import { RiCloseLine } from '@remixicon/react' +import { + RiArrowRightSLine, + RiCloseLine, +} from '@remixicon/react' import { ArrowNarrowLeft } from '../../base/icons/src/vender/line/arrows' import TracingPanel from './tracing-panel' +import { Iteration } from '@/app/components/base/icons/src/vender/workflow' import cn from '@/utils/classnames' import type { NodeTracing } from '@/types/workflow' const i18nPrefix = 'workflow.singleRun' @@ -23,30 +27,69 @@ const IterationResultPanel: FC = ({ noWrap, }) => { const { t } = useTranslation() + const [expandedIterations, setExpandedIterations] = useState>([]) + + const toggleIteration = useCallback((index: number) => { + setExpandedIterations(prev => ({ + ...prev, + [index]: !prev[index], + })) + }, []) const main = ( <> -
+
-
+
{t(`${i18nPrefix}.testRunIteration`)}
- +
-
+
-
{t(`${i18nPrefix}.back`)}
+
{t(`${i18nPrefix}.back`)}
{/* List */} -
+
{list.map((iteration, index) => ( - +
+
toggleIteration(index)} + > +
+
+ +
+ + {t(`${i18nPrefix}.iteration`)} {index + 1} + + +
+
+ {expandedIterations[index] &&
} +
+ +
+
))}
diff --git a/web/app/components/workflow/run/node.tsx b/web/app/components/workflow/run/node.tsx index 6f13384e7b..2e1f9bb7e9 100644 --- a/web/app/components/workflow/run/node.tsx +++ b/web/app/components/workflow/run/node.tsx @@ -11,8 +11,10 @@ import { import BlockIcon from '../block-icon' import { BlockEnum } from '../types' import Split from '../nodes/_base/components/split' +import { Iteration } from '@/app/components/base/icons/src/vender/workflow' import cn from '@/utils/classnames' import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' +import Button from '@/app/components/base/button' import { CodeLanguage } from '@/app/components/workflow/nodes/code/types' import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' import type { NodeTracing } from '@/types/workflow' @@ -66,7 +68,7 @@ const NodePanel: FC = ({ }, [nodeInfo.expand, setCollapseState]) const isIterationNode = nodeInfo.node_type === BlockEnum.Iteration - const handleOnShowIterationDetail = (e: React.MouseEvent) => { + const handleOnShowIterationDetail = (e: React.MouseEvent) => { e.stopPropagation() e.nativeEvent.stopImmediatePropagation() onShowIterationDetail?.(nodeInfo.details || []) @@ -120,21 +122,23 @@ const NodePanel: FC = ({ {/* The nav to the iteration detail */} {isIterationNode && !notShowIterationNav && (
-
-
{t('workflow.nodes.iteration.iteration', { count: nodeInfo.metadata?.iterator_length || nodeInfo.details?.length })}
+
+
)} diff --git a/web/app/components/workflow/run/tracing-panel.tsx b/web/app/components/workflow/run/tracing-panel.tsx index 8fecaf8a9b..342956081e 100644 --- a/web/app/components/workflow/run/tracing-panel.tsx +++ b/web/app/components/workflow/run/tracing-panel.tsx @@ -20,6 +20,7 @@ import type { NodeTracing } from '@/types/workflow' type TracingPanelProps = { list: NodeTracing[] onShowIterationDetail?: (detail: NodeTracing[][]) => void + className?: string } type TracingNodeProps = { @@ -44,7 +45,7 @@ function buildLogTree(nodes: NodeTracing[]): TracingNodeProps[] { levelCounts[levelKey]++ - const parentTitle = parentId ? parallelStacks[parentId].parallelTitle : '' + const parentTitle = parentId ? parallelStacks[parentId]?.parallelTitle : '' const levelNumber = parentTitle ? parseInt(parentTitle.split('-')[1]) + 1 : 1 const letter = parallelChildCounts[levelKey]?.size > 1 ? String.fromCharCode(64 + levelCounts[levelKey]) : '' return `PARALLEL-${levelNumber}${letter}` @@ -52,7 +53,7 @@ function buildLogTree(nodes: NodeTracing[]): TracingNodeProps[] { const getBranchTitle = (parentId: string | null, branchNum: number): string => { const levelKey = parentId || 'root' - const parentTitle = parentId ? parallelStacks[parentId].parallelTitle : '' + const parentTitle = parentId ? parallelStacks[parentId]?.parallelTitle : '' const levelNumber = parentTitle ? parseInt(parentTitle.split('-')[1]) + 1 : 1 const letter = parallelChildCounts[levelKey]?.size > 1 ? String.fromCharCode(64 + levelCounts[levelKey]) : '' const branchLetter = String.fromCharCode(64 + branchNum) @@ -126,9 +127,12 @@ function buildLogTree(nodes: NodeTracing[]): TracingNodeProps[] { }) } else { - const sameBranchIndex = parallelStacks[parallel_id].children.findLastIndex(c => + let sameBranchIndex = parallelStacks[parallel_id].children.findLastIndex(c => c.data?.execution_metadata.parallel_start_node_id === parallel_start_node_id, ) + if (parallelStacks[parallel_id].children[sameBranchIndex + 1]?.isParallel) + sameBranchIndex++ + parallelStacks[parallel_id].children.splice(sameBranchIndex + 1, 0, { id: node.id, isParallel: false, @@ -143,7 +147,7 @@ function buildLogTree(nodes: NodeTracing[]): TracingNodeProps[] { return rootNodes } -const TracingPanel: FC = ({ list, onShowIterationDetail }) => { +const TracingPanel: FC = ({ list, onShowIterationDetail, className }) => { const treeNodes = buildLogTree(list) const [collapsedNodes, setCollapsedNodes] = useState>(new Set()) const [hoveredParallel, setHoveredParallel] = useState(null) @@ -238,7 +242,7 @@ const TracingPanel: FC = ({ list, onShowIterationDetail }) => } return ( -
+
{treeNodes.map(renderNode)}
) diff --git a/web/types/workflow.ts b/web/types/workflow.ts index 535595b9ad..bb57b0715d 100644 --- a/web/types/workflow.ts +++ b/web/types/workflow.ts @@ -145,6 +145,8 @@ export type NodeFinishedResponse = { total_price: number currency: string parallel_id?: string + parallel_start_node_id?: string + iteration_index?: number } created_at: number } @@ -159,6 +161,8 @@ export type IterationStartedResponse = { node_id: string metadata: { iterator_length: number + iteration_id: string + iteration_index: number } created_at: number extras?: any