fix(workflow): allow human input in iteration and loop (#40061)

This commit is contained in:
-LAN- 2026-08-31 08:28:17 +00:00 committed by GitHub
parent 336dd0b8c0
commit d0a86cfd4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 41 additions and 19 deletions

View File

@ -145,7 +145,7 @@ describe('useAvailableBlocks', () => {
})
describe('inContainer filtering', () => {
it('should exclude Iteration, Loop, End, DataSource, KnowledgeBase, HumanInput when inContainer=true', () => {
it('should allow HumanInput while excluding unsupported blocks when inContainer=true', () => {
const { result } = renderWorkflowHook(() => useAvailableBlocks(BlockEnum.LLM, true), {
hooksStoreProps,
})
@ -155,7 +155,7 @@ describe('useAvailableBlocks', () => {
expect(result.current.availableNextBlocks).not.toContain(BlockEnum.End)
expect(result.current.availableNextBlocks).not.toContain(BlockEnum.DataSource)
expect(result.current.availableNextBlocks).not.toContain(BlockEnum.KnowledgeBase)
expect(result.current.availableNextBlocks).not.toContain(BlockEnum.HumanInput)
expect(result.current.availableNextBlocks).toContain(BlockEnum.HumanInput)
})
it('should exclude LoopEnd when not in container', () => {

View File

@ -1183,15 +1183,14 @@ describe('useNodesInteractions', () => {
)
})
// Nested container paste restrictions should stay aligned with available block filtering.
describe('nested container paste restrictions', () => {
// Nested container paste behavior should stay aligned with available block filtering.
describe('nested container paste behavior', () => {
const disallowedNestedPasteNodeTypes = [
BlockEnum.End,
BlockEnum.Iteration,
BlockEnum.Loop,
BlockEnum.DataSource,
BlockEnum.KnowledgeBase,
BlockEnum.HumanInput,
]
const createNodeMeta = (type: BlockEnum) => ({
@ -1205,7 +1204,7 @@ describe('useNodesInteractions', () => {
},
})
const runDisallowedPasteScenario = async (
const pasteNodeIntoContainer = async (
containerType: BlockEnum.Iteration | BlockEnum.Loop,
nodeType: BlockEnum,
) => {
@ -1263,23 +1262,48 @@ describe('useNodesInteractions', () => {
const pastedNodes = rfState.setNodes.mock.calls.at(-1)?.[0] as Node[]
expect(pastedNodes).toHaveLength(1)
expect(pastedNodes[0]?.id).toBe(containerId)
expect(pastedNodes[0]?.data._children).toEqual([])
expect(
pastedNodes.some((node) => node.data.type === nodeType && node.parentId === containerId),
).toBe(false)
return { containerId, pastedNodes }
}
it.each(disallowedNestedPasteNodeTypes)(
'should not paste %s into an iteration container',
async (nodeType) => {
await runDisallowedPasteScenario(BlockEnum.Iteration, nodeType)
const { containerId, pastedNodes } = await pasteNodeIntoContainer(
BlockEnum.Iteration,
nodeType,
)
expect(pastedNodes).toHaveLength(1)
expect(pastedNodes[0]?.id).toBe(containerId)
expect(pastedNodes[0]?.data._children).toEqual([])
},
)
it('should not paste human-input into a loop container', async () => {
await runDisallowedPasteScenario(BlockEnum.Loop, BlockEnum.HumanInput)
})
it.each([BlockEnum.Iteration, BlockEnum.Loop] as const)(
'should paste human-input into a %s container',
async (containerType) => {
const { containerId, pastedNodes } = await pasteNodeIntoContainer(
containerType,
BlockEnum.HumanInput,
)
const container = pastedNodes.find((node) => node.id === containerId)
const pastedHumanInput = pastedNodes.find(
(node) => node.data.type === BlockEnum.HumanInput && node.parentId === containerId,
)
const isIteration = containerType === BlockEnum.Iteration
expect(pastedHumanInput).toBeDefined()
expect(pastedHumanInput?.data).toMatchObject({
isInIteration: isIteration,
iteration_id: isIteration ? containerId : undefined,
isInLoop: !isIteration,
loop_id: isIteration ? undefined : containerId,
})
expect(container?.data._children).toContainEqual({
nodeId: pastedHumanInput?.id,
nodeType: BlockEnum.HumanInput,
})
},
)
})
})

View File

@ -11,8 +11,7 @@ const availableBlocksFilter = (nodeType: BlockEnum, inContainer?: boolean) => {
nodeType === BlockEnum.Loop ||
nodeType === BlockEnum.End ||
nodeType === BlockEnum.DataSource ||
nodeType === BlockEnum.KnowledgeBase ||
nodeType === BlockEnum.HumanInput)
nodeType === BlockEnum.KnowledgeBase)
)
return false

View File

@ -1786,7 +1786,6 @@ export const useNodesInteractions = () => {
BlockEnum.Loop,
BlockEnum.DataSource,
BlockEnum.KnowledgeBase,
BlockEnum.HumanInput,
]
// Same-canvas copy keeps the source container selected, so only treat a
// selected container as the paste target when it is not part of the clipboard.