Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { useMemo } from 'react'
import { useShallow } from 'zustand/react/shallow'
import { BlockPathCalculator } from '@/lib/workflows/blocks/block-path-calculator'
import { SYSTEM_REFERENCE_PREFIXES } from '@/lib/workflows/sanitization/references'
import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers'
import { normalizeName } from '@/executor/constants'
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
import type { Loop, Parallel } from '@/stores/workflows/workflow/types'
Expand All @@ -27,27 +26,12 @@ export function useAccessibleReferencePrefixes(blockId?: string | null): Set<str
const accessibleIds = new Set<string>(ancestorIds)
accessibleIds.add(blockId)

const starterBlock = Object.values(blocks).find((block) => isInputDefinitionTrigger(block.type))
if (starterBlock && ancestorIds.includes(starterBlock.id)) {
accessibleIds.add(starterBlock.id)
}

const loopValues = Object.values(loops as Record<string, Loop>)
loopValues.forEach((loop) => {
if (!loop?.nodes) return
if (loop.nodes.includes(blockId)) {
accessibleIds.add(loop.id) // Add the loop block itself
loop.nodes.forEach((nodeId) => accessibleIds.add(nodeId))
}
Object.values(loops as Record<string, Loop>).forEach((loop) => {
if (loop?.nodes?.includes(blockId)) accessibleIds.add(loop.id)
})

const parallelValues = Object.values(parallels as Record<string, Parallel>)
parallelValues.forEach((parallel) => {
if (!parallel?.nodes) return
if (parallel.nodes.includes(blockId)) {
accessibleIds.add(parallel.id) // Add the parallel block itself
parallel.nodes.forEach((nodeId) => accessibleIds.add(nodeId))
}
Object.values(parallels as Record<string, Parallel>).forEach((parallel) => {
if (parallel?.nodes?.includes(blockId)) accessibleIds.add(parallel.id)
})

const prefixes = new Set<string>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
loadDeployedWorkflowState,
loadWorkflowFromNormalizedTables,
} from '@/lib/workflows/persistence/utils'
import { isInputDefinitionTrigger } from '@/lib/workflows/triggers/input-definition-triggers'
import { hasTriggerCapability } from '@/lib/workflows/triggers/trigger-utils'
import { getBlock } from '@/blocks/registry'
import { normalizeName } from '@/executor/constants'
Expand Down Expand Up @@ -457,20 +456,9 @@ export async function executeGetBlockUpstreamReferences(
const accessibleIds = new Set<string>(ancestorIds)
accessibleIds.add(blockId)

const starterBlock = Object.values(blocks).find((b) => isInputDefinitionTrigger(b.type))
if (starterBlock && ancestorIds.includes(starterBlock.id)) {
accessibleIds.add(starterBlock.id)
}

containingLoopIds.forEach((loopId) => {
accessibleIds.add(loopId)
loops[loopId]?.nodes?.forEach((nodeId: string) => accessibleIds.add(nodeId))
})
containingLoopIds.forEach((loopId) => accessibleIds.add(loopId))

containingParallelIds.forEach((parallelId) => {
accessibleIds.add(parallelId)
parallels[parallelId]?.nodes?.forEach((nodeId: string) => accessibleIds.add(nodeId))
})
containingParallelIds.forEach((parallelId) => accessibleIds.add(parallelId))

const accessibleBlocks: AccessibleBlockEntry[] = []

Expand Down
34 changes: 0 additions & 34 deletions apps/sim/lib/workflows/blocks/block-path-calculator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type { SerializedWorkflow } from '@/serializer/types'

/**
* Shared utility for calculating block paths and accessible connections.
* Used by both frontend (useBlockConnections) and backend (InputResolver) to ensure consistency.
Expand Down Expand Up @@ -65,36 +63,4 @@ export class BlockPathCalculator {

return Array.from(pathNodes)
}

/**
* Calculates accessible blocks for all blocks in a workflow.
* This ensures consistent block reference resolution across frontend and backend.
*
* @param workflow - The serialized workflow
* @returns Map of block ID to Set of accessible block IDs
*/
static calculateAccessibleBlocksForWorkflow(
workflow: SerializedWorkflow
): Map<string, Set<string>> {
const accessibleMap = new Map<string, Set<string>>()

for (const block of workflow.blocks) {
const accessibleBlocks = new Set<string>()

// Find all blocks along paths leading to this block
const pathNodes = BlockPathCalculator.findAllPathNodes(workflow.connections, block.id)
pathNodes.forEach((nodeId) => accessibleBlocks.add(nodeId))

// Only add starter block if it's actually upstream (already in pathNodes)
// Don't add it just because it exists on the canvas
const starterBlock = workflow.blocks.find((b) => b.metadata?.id === 'starter')
if (starterBlock && starterBlock.id !== block.id && pathNodes.includes(starterBlock.id)) {
accessibleBlocks.add(starterBlock.id)
}

accessibleMap.set(block.id, accessibleBlocks)
}

return accessibleMap
}
}
50 changes: 0 additions & 50 deletions apps/sim/serializer/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { createLogger } from '@sim/logger'
import type { Edge } from 'reactflow'
import { BlockPathCalculator } from '@/lib/workflows/blocks/block-path-calculator'
import type { CanonicalModeOverrides } from '@/lib/workflows/subblocks/visibility'
import {
buildCanonicalIndex,
Expand Down Expand Up @@ -153,13 +152,6 @@ export class Serializer {
const safeLoops = Object.keys(canonicalLoops).length > 0 ? canonicalLoops : loops || {}
const safeParallels =
Object.keys(canonicalParallels).length > 0 ? canonicalParallels : parallels || {}
const accessibleBlocksMap = this.computeAccessibleBlockIds(
blocks,
edges,
safeLoops,
safeParallels
)

if (validateRequired) {
this.validateSubflowsBeforeExecution(blocks, safeLoops, safeParallels)
}
Expand All @@ -170,7 +162,6 @@ export class Serializer {
this.serializeBlock(block, {
validateRequired,
allBlocks: blocks,
accessibleBlocksMap,
})
),
connections: edges.map((edge) => ({
Expand Down Expand Up @@ -201,7 +192,6 @@ export class Serializer {
options: {
validateRequired: boolean
allBlocks: Record<string, BlockState>
accessibleBlocksMap: Map<string, Set<string>>
}
): SerializedBlock {
// Special handling for subflow blocks (loops, parallels, etc.)
Expand Down Expand Up @@ -540,46 +530,6 @@ export class Serializer {
}
}

private computeAccessibleBlockIds(
blocks: Record<string, BlockState>,
edges: Edge[],
loops: Record<string, Loop>,
parallels: Record<string, Parallel>
): Map<string, Set<string>> {
const accessibleMap = new Map<string, Set<string>>()
const simplifiedEdges = edges.map((edge) => ({ source: edge.source, target: edge.target }))

const starterBlock = Object.values(blocks).find((block) => block.type === 'starter')

Object.keys(blocks).forEach((blockId) => {
const ancestorIds = BlockPathCalculator.findAllPathNodes(simplifiedEdges, blockId)
const accessibleIds = new Set<string>(ancestorIds)
accessibleIds.add(blockId)

if (starterBlock && ancestorIds.includes(starterBlock.id)) {
accessibleIds.add(starterBlock.id)
}

Object.values(loops).forEach((loop) => {
if (!loop?.nodes) return
if (loop.nodes.includes(blockId)) {
loop.nodes.forEach((nodeId) => accessibleIds.add(nodeId))
}
})

Object.values(parallels).forEach((parallel) => {
if (!parallel?.nodes) return
if (parallel.nodes.includes(blockId)) {
parallel.nodes.forEach((nodeId) => accessibleIds.add(nodeId))
}
})

accessibleMap.set(blockId, accessibleIds)
})

return accessibleMap
}

private selectToolId(blockConfig: any, params: Record<string, any>): string {
try {
return blockConfig.tools.config?.tool
Expand Down