diff --git a/skyvern-frontend/src/routes/workflows/editor/FlowRenderer.tsx b/skyvern-frontend/src/routes/workflows/editor/FlowRenderer.tsx index 6740e10bb1..81fe4c3c44 100644 --- a/skyvern-frontend/src/routes/workflows/editor/FlowRenderer.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/FlowRenderer.tsx @@ -265,7 +265,7 @@ function FlowRenderer({ }, [nodesInitialized]); async function handleSave() { - const blocks = getWorkflowBlocks(nodes); + const blocks = getWorkflowBlocks(nodes, edges); const parametersInYAMLConvertibleJSON = convertToParametersYAML(parameters); const filteredParameters = workflow.workflow_definition.parameters.filter( (parameter) => { diff --git a/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts b/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts index 7384c8a43a..bab9bea5b5 100644 --- a/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts +++ b/skyvern-frontend/src/routes/workflows/editor/workflowEditorUtils.ts @@ -635,9 +635,48 @@ function getWorkflowBlock(node: WorkflowBlockNode): BlockYAML { } } -function getWorkflowBlocksUtil(nodes: Array): Array { +function getOrderedChildrenBlocks( + nodes: Array, + edges: Array, + parentId: string, +): Array { + const parentNode = nodes.find((node) => node.id === parentId); + if (!parentNode) { + return []; + } + const blockStartNode = nodes.find( + (node) => node.type === "start" && node.parentId === parentId, + ); + if (!blockStartNode) { + return []; + } + const firstChildId = edges.find( + (edge) => edge.source === blockStartNode.id, + )?.target; + const firstChild = nodes.find((node) => node.id === firstChildId); + if (!firstChild || !isWorkflowBlockNode(firstChild)) { + return []; + } + + const children: Array = []; + let currentNode: WorkflowBlockNode | undefined = firstChild; + while (currentNode) { + children.push(getWorkflowBlock(currentNode)); + const nextId = edges.find( + (edge) => edge.source === currentNode?.id, + )?.target; + const next = nodes.find((node) => node.id === nextId); + currentNode = next && isWorkflowBlockNode(next) ? next : undefined; + } + return children; +} + +function getWorkflowBlocksUtil( + nodes: Array, + edges: Array, +): Array { return nodes.flatMap((node) => { - if (node.parentId) { + if (node.parentId || node.type === "start" || node.type === "nodeAdder") { return []; } if (node.type === "loop") { @@ -647,26 +686,19 @@ function getWorkflowBlocksUtil(nodes: Array): Array { label: node.data.label, continue_on_failure: node.data.continueOnFailure, loop_over_parameter_key: node.data.loopValue, - loop_blocks: nodes - .filter((n) => n.parentId === node.id) - .map((n) => { - return getWorkflowBlock( - n as Exclude, - ); - }), + loop_blocks: getOrderedChildrenBlocks(nodes, edges, node.id), }, ]; } - return [ - getWorkflowBlock( - node as Exclude, - ), - ]; + return [getWorkflowBlock(node as Exclude)]; }); } -function getWorkflowBlocks(nodes: Array): Array { - return getWorkflowBlocksUtil(nodes.filter(isWorkflowBlockNode)); +function getWorkflowBlocks( + nodes: Array, + edges: Array, +): Array { + return getWorkflowBlocksUtil(nodes, edges); } function generateNodeLabel(existingLabels: Array) {