From f1643e182e53c662c9c192169af5aa5c96ea82e4 Mon Sep 17 00:00:00 2001 From: Mminamiyama Date: Fri, 4 Jul 2025 17:21:55 +0800 Subject: [PATCH] fix(workflow): handle loop node vars and validate variable usage - Add loop node to available nodes for variable access - Validate variable usage in nodes and show error for invalid vars --- .../workflow/hooks/use-checklist.ts | 33 +++++++++++++++---- .../hooks/use-nodes-available-var-list.ts | 5 +-- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/web/app/components/workflow/hooks/use-checklist.ts b/web/app/components/workflow/hooks/use-checklist.ts index 075aebb9ba..35ff86044d 100644 --- a/web/app/components/workflow/hooks/use-checklist.ts +++ b/web/app/components/workflow/hooks/use-checklist.ts @@ -9,6 +9,7 @@ import type { CommonNodeType, Edge, Node, + ValueSelector, } from '../types' import { BlockEnum } from '../types' import { useStore } from '../store' @@ -34,6 +35,7 @@ import type { DataSet } from '@/models/datasets' import { fetchDatasets } from '@/service/datasets' import { MAX_TREE_DEPTH } from '@/config' import useNodesAvailableVarList from './use-nodes-available-var-list' +import { getNodeUsedVars, isConversationVar, isENV, isSystemVar } from '../nodes/_base/components/variable/utils' export const useChecklist = (nodes: Node[], edges: Edge[]) => { const { t } = useTranslation() @@ -46,9 +48,7 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => { const { data: strategyProviders } = useStrategyProviders() const datasetsDetail = useDatasetsDetailStore(s => s.datasetsDetail) - console.log('==========================nodes: ', nodes) const map = useNodesAvailableVarList(nodes) - console.log('==========================map: ', map) const getCheckData = useCallback((data: CommonNodeType<{}>) => { let checkData = data @@ -75,6 +75,7 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => { const node = nodes[i] let toolIcon let moreDataForCheckValid + let usedVars: ValueSelector[] = [] if (node.data.type === BlockEnum.Tool) { const { provider_type } = node.data @@ -102,15 +103,33 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => { } } else { - moreDataForCheckValid = { - node, - ...map[node.id], - } + usedVars = getNodeUsedVars(node).filter(v => v.length > 0) } if (node.type === CUSTOM_NODE) { const checkData = getCheckData(node.data) - const { errorMessage } = nodesExtraData[node.data.type].checkValid(checkData, t, moreDataForCheckValid) + let { errorMessage } = nodesExtraData[node.data.type].checkValid(checkData, t, moreDataForCheckValid) + + if (!errorMessage) { + const availableVars = map[node.id].availableVars + + usedVars.forEach((variable) => { + const isEnv = isENV(variable) + const isConvVar = isConversationVar(variable) + const isSysVar = isSystemVar(variable) + if (!isEnv && !isConvVar && !isSysVar) { + const usedNode = availableVars.find(v => v.nodeId === variable?.[0]) + if (usedNode) { + const usedVar = usedNode.vars.find(v => v.variable === variable?.[1]) + if (!usedVar) + errorMessage = t('workflow.errorMsg.invalidVariable') + } + else { + errorMessage = t('workflow.errorMsg.invalidVariable') + } + } + }) + } if (errorMessage || !validNodes.find(n => n.id === node.id)) { list.push({ diff --git a/web/app/components/workflow/hooks/use-nodes-available-var-list.ts b/web/app/components/workflow/hooks/use-nodes-available-var-list.ts index 761bdce6af..fd07ca26b1 100644 --- a/web/app/components/workflow/hooks/use-nodes-available-var-list.ts +++ b/web/app/components/workflow/hooks/use-nodes-available-var-list.ts @@ -3,7 +3,7 @@ import { useWorkflow, useWorkflowVariables, } from '@/app/components/workflow/hooks' -import type { Node, NodeOutPutVar, ValueSelector, Var } from '@/app/components/workflow/types' +import { BlockEnum, type Node, type NodeOutPutVar, type ValueSelector, type Var } from '@/app/components/workflow/types' type Params = { onlyLeafNodeVar?: boolean hideEnv?: boolean @@ -47,6 +47,8 @@ const useNodesAvailableVarList = (nodes: Node[], { nodes.forEach((node) => { const nodeId = node.id const availableNodes = passedInAvailableNodes || (onlyLeafNodeVar ? getTreeLeafNodes(nodeId) : getBeforeNodesInSameBranchIncludeParent(nodeId)) + if (node.data.type === BlockEnum.Loop) + availableNodes.push(node) const { parentNode: iterationNode, @@ -60,7 +62,6 @@ const useNodesAvailableVarList = (nodes: Node[], { hideEnv, hideChatVar, }) - const result = { node, availableVars,