diff --git a/executor/index.ts b/executor/index.ts index 706fb10e92..27984bdbe2 100644 --- a/executor/index.ts +++ b/executor/index.ts @@ -296,58 +296,30 @@ export class Executor { // Only process if we haven't hit max iterations if (iterations < loop.maxIterations - 1) { + // Removed the -1 + // Check if any block in the loop has outgoing connections to other blocks in the loop const hasLoopConnection = executedLoopBlocks.some((blockId) => { const outgoingConns = connections.filter((conn) => conn.source === blockId) return outgoingConns.some((conn) => loopBlocks.has(conn.target)) }) - // Track if this iteration is complete by checking if we've hit a terminal node - const isTerminalNode = executedLoopBlocks.some((blockId) => { - // A block is terminal if: - // 1. It's not in the loop nodes (like the Function block), OR - // 2. It's a condition block that selected a path to a non-loop node + // Check if this was the last block in the loop (e.g., a condition block) + const isLoopComplete = executedLoopBlocks.some((blockId) => { const block = blocks.find((b) => b.id === blockId) - if (!block) return false - - if (!loop.nodes.includes(blockId)) return true - - if (block.metadata?.type === 'condition') { - const conditionResult = context.blockStates.get(blockId) - if ( - !conditionResult || - typeof conditionResult === 'string' || - !('response' in conditionResult) - ) - return false - - // Check if the selected path goes to a node outside the loop - const response = conditionResult.response as { - condition?: { selectedPath?: { blockId?: string } } - } - const selectedPath = response.condition?.selectedPath?.blockId - return selectedPath && !loop.nodes.includes(selectedPath) - } - - return false + return block?.metadata?.type === 'condition' }) - // Only reset and queue new blocks if we haven't hit a terminal node - if (hasLoopConnection && !isTerminalNode) { - const allCurrentBlocksComplete = executedLoopBlocks.every((blockId) => { - const blockState = context.blockStates.get(blockId) - return blockState !== undefined - }) - - if (allCurrentBlocksComplete) { - // Reset the loop blocks' inDegrees - resetLoopBlocksDegrees(loopId) - for (const blockId of loop.nodes) { - if (inDegree.get(blockId) === 0) { - queue.push(blockId) - } + if (hasLoopConnection) { + // Reset the loop blocks' inDegrees + resetLoopBlocksDegrees(loopId) + for (const blockId of loop.nodes) { + if (inDegree.get(blockId) === 0) { + queue.push(blockId) } + } - // Increment the iteration counter when all blocks in current iteration are done + // Only increment counter when we complete a loop cycle + if (isLoopComplete) { loopIterations.set(loopId, iterations + 1) } } @@ -804,7 +776,7 @@ export class Executor { let selectedConnection: { target: string; sourceHandle?: string } | null = null let selectedCondition: { id: string; title: string; value: string } | null = null - // Build the evaluation context using the dynamic key instead of a hardcoded "agent1". + // Build the evaluation context using the dynamic key const evalContext = { ...(typeof sourceOutput === 'object' && sourceOutput !== null ? sourceOutput : {}), [sourceKey]: sourceOutput, @@ -875,15 +847,6 @@ export class Executor { throw new Error(`No state found for source block ${sourceBlockId}`) } - const isExitingLoop = () => { - const loop = Object.values(this.workflow.loops || {}).find((loop) => - loop.nodes.includes(block.id) - ) - if (!loop) return false - - return !loop.nodes.includes(targetBlock.id) - } - // Create the block output with the source output when condition is met. const blockOutput = { response: { @@ -897,7 +860,6 @@ export class Executor { blockTitle: targetBlock.metadata?.title || '', }, selectedConditionId: selectedCondition.id, - exitsLoop: isExitingLoop(), }, }, }