Feature/newnew workflow loop node (#14863)
Co-authored-by: arkunzz <4873204@qq.com>
This commit is contained in:
@@ -38,7 +38,7 @@ const Add = ({
|
||||
const [open, setOpen] = useState(false)
|
||||
const { handleNodeAdd } = useNodesInteractions()
|
||||
const { nodesReadOnly } = useNodesReadOnly()
|
||||
const { availableNextBlocks } = useAvailableBlocks(nodeData.type, nodeData.isInIteration)
|
||||
const { availableNextBlocks } = useAvailableBlocks(nodeData.type, nodeData.isInIteration, nodeData.isInLoop)
|
||||
const { checkParallelLimit } = useWorkflow()
|
||||
|
||||
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
|
||||
|
@@ -36,7 +36,7 @@ const ChangeItem = ({
|
||||
const {
|
||||
availablePrevBlocks,
|
||||
availableNextBlocks,
|
||||
} = useAvailableBlocks(data.type, data.isInIteration)
|
||||
} = useAvailableBlocks(data.type, data.isInIteration, data.isInLoop)
|
||||
|
||||
const handleSelect = useCallback<OnSelectBlock>((type, toolDefaultValue) => {
|
||||
handleNodeChange(nodeId, type, sourceHandle, toolDefaultValue)
|
||||
|
@@ -47,7 +47,7 @@ export const NodeTargetHandle = memo(({
|
||||
const { handleNodeAdd } = useNodesInteractions()
|
||||
const { getNodesReadOnly } = useNodesReadOnly()
|
||||
const connected = data._connectedTargetHandleIds?.includes(handleId)
|
||||
const { availablePrevBlocks } = useAvailableBlocks(data.type, data.isInIteration)
|
||||
const { availablePrevBlocks } = useAvailableBlocks(data.type, data.isInIteration, data.isInLoop)
|
||||
const isConnectable = !!availablePrevBlocks.length
|
||||
|
||||
const handleOpenChange = useCallback((v: boolean) => {
|
||||
@@ -129,7 +129,7 @@ export const NodeSourceHandle = memo(({
|
||||
const [open, setOpen] = useState(false)
|
||||
const { handleNodeAdd } = useNodesInteractions()
|
||||
const { getNodesReadOnly } = useNodesReadOnly()
|
||||
const { availableNextBlocks } = useAvailableBlocks(data.type, data.isInIteration)
|
||||
const { availableNextBlocks } = useAvailableBlocks(data.type, data.isInIteration, data.isInLoop)
|
||||
const isConnectable = !!availableNextBlocks.length
|
||||
const isChatMode = useIsChatMode()
|
||||
const { checkParallelLimit } = useWorkflow()
|
||||
|
@@ -30,7 +30,7 @@ const ChangeBlock = ({
|
||||
const {
|
||||
availablePrevBlocks,
|
||||
availableNextBlocks,
|
||||
} = useAvailableBlocks(nodeData.type, nodeData.isInIteration)
|
||||
} = useAvailableBlocks(nodeData.type, nodeData.isInIteration, nodeData.isInLoop)
|
||||
|
||||
const availableNodes = useMemo(() => {
|
||||
if (availablePrevBlocks.length && availableNextBlocks.length)
|
||||
|
@@ -79,7 +79,7 @@ const PanelOperatorPopup = ({
|
||||
return customTools.find(toolWithProvider => toolWithProvider.id === data.provider_id)?.description[language]
|
||||
}, [data, nodesExtraData, language, buildInTools, customTools, workflowTools])
|
||||
|
||||
const showChangeBlock = data.type !== BlockEnum.Start && !nodesReadOnly && data.type !== BlockEnum.Iteration
|
||||
const showChangeBlock = data.type !== BlockEnum.Start && !nodesReadOnly && data.type !== BlockEnum.Iteration && data.type !== BlockEnum.Loop
|
||||
|
||||
const link = useNodeHelpLink(data.type)
|
||||
|
||||
|
@@ -13,6 +13,7 @@ import { VarType as ToolVarType } from '../../../tool/types'
|
||||
import type { ToolNodeType } from '../../../tool/types'
|
||||
import type { ParameterExtractorNodeType } from '../../../parameter-extractor/types'
|
||||
import type { IterationNodeType } from '../../../iteration/types'
|
||||
import type { LoopNodeType } from '../../../loop/types'
|
||||
import type { ListFilterNodeType } from '../../../list-operator/types'
|
||||
import { OUTPUT_FILE_SUB_VARIABLES } from '../../../constants'
|
||||
import type { DocExtractorNodeType } from '../../../document-extractor/types'
|
||||
@@ -518,10 +519,61 @@ const getIterationItemType = ({
|
||||
}
|
||||
}
|
||||
|
||||
const getLoopItemType = ({
|
||||
valueSelector,
|
||||
beforeNodesOutputVars,
|
||||
}: {
|
||||
valueSelector: ValueSelector
|
||||
beforeNodesOutputVars: NodeOutPutVar[]
|
||||
}): VarType => {
|
||||
const outputVarNodeId = valueSelector[0]
|
||||
const isSystem = isSystemVar(valueSelector)
|
||||
|
||||
const targetVar = isSystem ? beforeNodesOutputVars.find(v => v.isStartNode) : beforeNodesOutputVars.find(v => v.nodeId === outputVarNodeId)
|
||||
if (!targetVar)
|
||||
return VarType.string
|
||||
|
||||
let arrayType: VarType = VarType.string
|
||||
|
||||
let curr: any = targetVar.vars
|
||||
if (isSystem) {
|
||||
arrayType = curr.find((v: any) => v.variable === (valueSelector).join('.'))?.type
|
||||
}
|
||||
else {
|
||||
(valueSelector).slice(1).forEach((key, i) => {
|
||||
const isLast = i === valueSelector.length - 2
|
||||
curr = curr?.find((v: any) => v.variable === key)
|
||||
if (isLast) {
|
||||
arrayType = curr?.type
|
||||
}
|
||||
else {
|
||||
if (curr?.type === VarType.object || curr?.type === VarType.file)
|
||||
curr = curr.children
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
switch (arrayType as VarType) {
|
||||
case VarType.arrayString:
|
||||
return VarType.string
|
||||
case VarType.arrayNumber:
|
||||
return VarType.number
|
||||
case VarType.arrayObject:
|
||||
return VarType.object
|
||||
case VarType.array:
|
||||
return VarType.any
|
||||
case VarType.arrayFile:
|
||||
return VarType.file
|
||||
default:
|
||||
return VarType.string
|
||||
}
|
||||
}
|
||||
|
||||
export const getVarType = ({
|
||||
parentNode,
|
||||
valueSelector,
|
||||
isIterationItem,
|
||||
isLoopItem,
|
||||
availableNodes,
|
||||
isChatMode,
|
||||
isConstant,
|
||||
@@ -532,6 +584,7 @@ export const getVarType = ({
|
||||
valueSelector: ValueSelector
|
||||
parentNode?: Node | null
|
||||
isIterationItem?: boolean
|
||||
isLoopItem?: boolean
|
||||
availableNodes: any[]
|
||||
isChatMode: boolean
|
||||
isConstant?: boolean
|
||||
@@ -567,6 +620,26 @@ export const getVarType = ({
|
||||
if (valueSelector[1] === 'index')
|
||||
return VarType.number
|
||||
}
|
||||
|
||||
const isLoopInnerVar = parentNode?.data.type === BlockEnum.Loop
|
||||
if (isLoopItem) {
|
||||
return getLoopItemType({
|
||||
valueSelector,
|
||||
beforeNodesOutputVars,
|
||||
})
|
||||
}
|
||||
if (isLoopInnerVar) {
|
||||
if (valueSelector[1] === 'item') {
|
||||
const itemType = getLoopItemType({
|
||||
valueSelector: (parentNode?.data as any).iterator_selector || [],
|
||||
beforeNodesOutputVars,
|
||||
})
|
||||
return itemType
|
||||
}
|
||||
if (valueSelector[1] === 'index')
|
||||
return VarType.number
|
||||
}
|
||||
|
||||
const isSystem = isSystemVar(valueSelector)
|
||||
const isEnv = isENV(valueSelector)
|
||||
const isChatVar = isConversationVar(valueSelector)
|
||||
@@ -802,6 +875,14 @@ export const getNodeUsedVars = (node: Node): ValueSelector[] => {
|
||||
break
|
||||
}
|
||||
|
||||
case BlockEnum.Loop: {
|
||||
const payload = data as LoopNodeType
|
||||
res = payload.break_conditions?.map((c) => {
|
||||
return c.variable_selector || []
|
||||
}) || []
|
||||
break
|
||||
}
|
||||
|
||||
case BlockEnum.ListFilter: {
|
||||
res = [(data as ListFilterNodeType).variable]
|
||||
break
|
||||
@@ -1079,6 +1160,17 @@ export const updateNodeVars = (oldNode: Node, oldVarSelector: ValueSelector, new
|
||||
|
||||
break
|
||||
}
|
||||
case BlockEnum.Loop: {
|
||||
const payload = data as LoopNodeType
|
||||
if (payload.break_conditions) {
|
||||
payload.break_conditions = payload.break_conditions.map((c) => {
|
||||
if (c.variable_selector?.join('.') === oldVarSelector.join('.'))
|
||||
c.variable_selector = newVarSelector
|
||||
return c
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
case BlockEnum.ListFilter: {
|
||||
const payload = data as ListFilterNodeType
|
||||
if (payload.variable.join('.') === oldVarSelector.join('.'))
|
||||
@@ -1200,6 +1292,11 @@ export const getNodeOutputVars = (node: Node, isChatMode: boolean): ValueSelecto
|
||||
break
|
||||
}
|
||||
|
||||
case BlockEnum.Loop: {
|
||||
res.push([id, 'output'])
|
||||
break
|
||||
}
|
||||
|
||||
case BlockEnum.DocExtractor: {
|
||||
res.push([id, 'text'])
|
||||
break
|
||||
|
@@ -114,6 +114,9 @@ const VarReferencePicker: FC<Props> = ({
|
||||
const isInIteration = !!node?.data.isInIteration
|
||||
const iterationNode = isInIteration ? getNodes().find(n => n.id === node.parentId) : null
|
||||
|
||||
const isInLoop = !!node?.data.isInLoop
|
||||
const loopNode = isInLoop ? getNodes().find(n => n.id === node.parentId) : null
|
||||
|
||||
const triggerRef = useRef<HTMLDivElement>(null)
|
||||
const [triggerWidth, setTriggerWidth] = useState(TRIGGER_DEFAULT_WIDTH)
|
||||
useEffect(() => {
|
||||
@@ -142,6 +145,14 @@ const VarReferencePicker: FC<Props> = ({
|
||||
return false
|
||||
}, [isInIteration, value, node])
|
||||
|
||||
const isLoopVar = useMemo(() => {
|
||||
if (!isInLoop)
|
||||
return false
|
||||
if (value[0] === node?.parentId && ['item', 'index'].includes(value[1]))
|
||||
return true
|
||||
return false
|
||||
}, [isInLoop, value, node])
|
||||
|
||||
const outputVarNodeId = hasValue ? value[0] : ''
|
||||
const outputVarNode = useMemo(() => {
|
||||
if (!hasValue || isConstant)
|
||||
@@ -150,11 +161,14 @@ const VarReferencePicker: FC<Props> = ({
|
||||
if (isIterationVar)
|
||||
return iterationNode?.data
|
||||
|
||||
if (isLoopVar)
|
||||
return loopNode?.data
|
||||
|
||||
if (isSystemVar(value as ValueSelector))
|
||||
return startNode?.data
|
||||
|
||||
return getNodeInfoById(availableNodes, outputVarNodeId)?.data
|
||||
}, [value, hasValue, isConstant, isIterationVar, iterationNode, availableNodes, outputVarNodeId, startNode])
|
||||
}, [value, hasValue, isConstant, isIterationVar, iterationNode, availableNodes, outputVarNodeId, startNode, isLoopVar, loopNode])
|
||||
|
||||
const varName = useMemo(() => {
|
||||
if (hasValue) {
|
||||
@@ -220,7 +234,7 @@ const VarReferencePicker: FC<Props> = ({
|
||||
}, [onChange, varKindType])
|
||||
|
||||
const type = getCurrentVariableType({
|
||||
parentNode: iterationNode,
|
||||
parentNode: isInIteration ? iterationNode : loopNode,
|
||||
valueSelector: value as ValueSelector,
|
||||
availableNodes,
|
||||
isChatMode,
|
||||
|
Reference in New Issue
Block a user