Allow empty workflows and improve workflow validation (#24627)

This commit is contained in:
lyzno1
2025-08-27 17:49:09 +08:00
committed by GitHub
parent 73e65fd838
commit 87abfbf515
16 changed files with 72 additions and 45 deletions

View File

@ -166,7 +166,7 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => {
list.push({
id: 'start-node-required',
type: BlockEnum.Start,
title: t('workflow.blocks.start'),
title: t('workflow.panel.startNode'),
errorMessage: t('workflow.common.needStartNode'),
})
}

View File

@ -18,7 +18,6 @@ import {
} from 'reactflow'
import { unionBy } from 'lodash-es'
import type { ToolDefaultValue } from '../block-selector/types'
import { ENTRY_NODE_TYPES } from '../block-selector/constants'
import type {
Edge,
Node,
@ -64,23 +63,7 @@ import { WorkflowHistoryEvent, useWorkflowHistory } from './use-workflow-history
import useInspectVarsCrud from './use-inspect-vars-crud'
import { getNodeUsedVars } from '../nodes/_base/components/variable/utils'
// Helper function to check if a node is an entry node
const isEntryNode = (nodeType: BlockEnum): boolean => {
return ENTRY_NODE_TYPES.includes(nodeType as any)
}
// Helper function to check if entry node can be deleted
const canDeleteEntryNode = (nodes: Node[], nodeId: string): boolean => {
const targetNode = nodes.find(node => node.id === nodeId)
if (!targetNode || !isEntryNode(targetNode.data.type))
return true // Non-entry nodes can always be deleted
// Count all entry nodes
const entryNodes = nodes.filter(node => isEntryNode(node.data.type))
// Can delete if there's more than one entry node
return entryNodes.length > 1
}
// Entry node deletion restriction has been removed to allow empty workflows
export const useNodesInteractions = () => {
const { t } = useTranslation()
@ -568,9 +551,7 @@ export const useNodesInteractions = () => {
const nodes = getNodes()
// Check if entry node can be deleted (must keep at least one entry node)
if (!canDeleteEntryNode(nodes, nodeId))
return // Cannot delete the last entry node
// Allow deleting any node including the last entry node
const currentNodeIndex = nodes.findIndex(node => node.id === nodeId)
const currentNode = nodes[currentNodeIndex]
@ -1410,7 +1391,7 @@ export const useNodesInteractions = () => {
const nodes = getNodes()
const bundledNodes = nodes.filter(node =>
node.data._isBundled && canDeleteEntryNode(nodes, node.id),
node.data._isBundled,
)
if (bundledNodes.length) {
@ -1424,7 +1405,7 @@ export const useNodesInteractions = () => {
return
const selectedNode = nodes.find(node =>
node.data.selected && canDeleteEntryNode(nodes, node.id),
node.data.selected,
)
if (selectedNode)