From 019b407e943fc14f0e6b8803dc6c8935ef6304c0 Mon Sep 17 00:00:00 2001 From: waleed Date: Mon, 23 Feb 2026 13:34:38 -0800 Subject: [PATCH 1/8] fix(tag-dropdown): exclude downstream blocks in loops and parallel siblings from reference picker --- .../hooks/use-accessible-reference-prefixes.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts index f89971fab5..fddaf4a1a3 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts @@ -36,8 +36,12 @@ export function useAccessibleReferencePrefixes(blockId?: string | null): Set { 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)) + accessibleIds.add(loop.id) + loop.nodes.forEach((nodeId) => { + if (ancestorIds.includes(nodeId)) { + accessibleIds.add(nodeId) + } + }) } }) @@ -45,8 +49,7 @@ export function useAccessibleReferencePrefixes(blockId?: string | null): Set { 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)) + accessibleIds.add(parallel.id) } }) From 0c261f7082bbf2b003917bcabe9ca1dace6f119e Mon Sep 17 00:00:00 2001 From: waleed Date: Mon, 23 Feb 2026 13:40:20 -0800 Subject: [PATCH 2/8] chore(serializer): remove unused computeAccessibleBlockIds method --- apps/sim/serializer/index.ts | 50 ------------------------------------ 1 file changed, 50 deletions(-) diff --git a/apps/sim/serializer/index.ts b/apps/sim/serializer/index.ts index 35b675d224..6626468dd0 100644 --- a/apps/sim/serializer/index.ts +++ b/apps/sim/serializer/index.ts @@ -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, @@ -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) } @@ -170,7 +162,6 @@ export class Serializer { this.serializeBlock(block, { validateRequired, allBlocks: blocks, - accessibleBlocksMap, }) ), connections: edges.map((edge) => ({ @@ -201,7 +192,6 @@ export class Serializer { options: { validateRequired: boolean allBlocks: Record - accessibleBlocksMap: Map> } ): SerializedBlock { // Special handling for subflow blocks (loops, parallels, etc.) @@ -540,46 +530,6 @@ export class Serializer { } } - private computeAccessibleBlockIds( - blocks: Record, - edges: Edge[], - loops: Record, - parallels: Record - ): Map> { - const accessibleMap = new Map>() - 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(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 { try { return blockConfig.tools.config?.tool From f7404a3d0d81a4c305b28d37a0091650e6f2b51f Mon Sep 17 00:00:00 2001 From: waleed Date: Mon, 23 Feb 2026 13:45:14 -0800 Subject: [PATCH 3/8] chore(block-path-calculator): remove unused calculateAccessibleBlocksForWorkflow method --- .../workflows/blocks/block-path-calculator.ts | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/apps/sim/lib/workflows/blocks/block-path-calculator.ts b/apps/sim/lib/workflows/blocks/block-path-calculator.ts index a67094480a..17852dab93 100644 --- a/apps/sim/lib/workflows/blocks/block-path-calculator.ts +++ b/apps/sim/lib/workflows/blocks/block-path-calculator.ts @@ -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. @@ -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> { - const accessibleMap = new Map>() - - for (const block of workflow.blocks) { - const accessibleBlocks = new Set() - - // 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 - } } From b068b4246da5f45eb6b2eaf26c12c04e5d6eacc0 Mon Sep 17 00:00:00 2001 From: waleed Date: Mon, 23 Feb 2026 13:47:40 -0800 Subject: [PATCH 4/8] chore(tag-dropdown): remove no-op loop node filter --- .../[workflowId]/hooks/use-accessible-reference-prefixes.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts index fddaf4a1a3..3a5dce2fdc 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts @@ -37,11 +37,6 @@ export function useAccessibleReferencePrefixes(blockId?: string | null): Set { - if (ancestorIds.includes(nodeId)) { - accessibleIds.add(nodeId) - } - }) } }) From a44e7663f4ef171e2c7a5a1b8360f2ce15823b31 Mon Sep 17 00:00:00 2001 From: waleed Date: Mon, 23 Feb 2026 13:53:19 -0800 Subject: [PATCH 5/8] fix(tag-dropdown): remove parallel container from accessible references in parallel branches --- .../hooks/use-accessible-reference-prefixes.ts | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts index 3a5dce2fdc..c2b23c6992 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts @@ -5,15 +5,14 @@ import { SYSTEM_REFERENCE_PREFIXES } from '@/lib/workflows/sanitization/referenc 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' +import type { Loop } from '@/stores/workflows/workflow/types' export function useAccessibleReferencePrefixes(blockId?: string | null): Set | undefined { - const { blocks, edges, loops, parallels } = useWorkflowStore( + const { blocks, edges, loops } = useWorkflowStore( useShallow((state) => ({ blocks: state.blocks, edges: state.edges, loops: state.loops || {}, - parallels: state.parallels || {}, })) ) @@ -40,14 +39,6 @@ export function useAccessibleReferencePrefixes(blockId?: string | null): Set) - parallelValues.forEach((parallel) => { - if (!parallel?.nodes) return - if (parallel.nodes.includes(blockId)) { - accessibleIds.add(parallel.id) - } - }) - const prefixes = new Set() accessibleIds.forEach((id) => { prefixes.add(normalizeName(id)) @@ -60,5 +51,5 @@ export function useAccessibleReferencePrefixes(blockId?: string | null): Set prefixes.add(prefix)) return prefixes - }, [blockId, blocks, edges, loops, parallels]) + }, [blockId, blocks, edges, loops]) } From 68bc9f6ed294d508c9a886e8ccf67d96f3c0f65c Mon Sep 17 00:00:00 2001 From: waleed Date: Mon, 23 Feb 2026 13:57:01 -0800 Subject: [PATCH 6/8] chore(tag-dropdown): remove no-op starter block filter --- .../[workflowId]/hooks/use-accessible-reference-prefixes.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts index c2b23c6992..e50c4fa7be 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts @@ -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 } from '@/stores/workflows/workflow/types' @@ -26,11 +25,6 @@ export function useAccessibleReferencePrefixes(blockId?: string | null): Set(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) loopValues.forEach((loop) => { if (!loop?.nodes) return From de8ef284bada265768a4baf8d262a758eaf3aa27 Mon Sep 17 00:00:00 2001 From: waleed Date: Mon, 23 Feb 2026 14:07:27 -0800 Subject: [PATCH 7/8] fix(tag-dropdown): restore parallel container in accessible references for blocks inside parallel --- .../use-accessible-reference-prefixes.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts index e50c4fa7be..9e3830f9c2 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes.ts @@ -4,14 +4,15 @@ import { BlockPathCalculator } from '@/lib/workflows/blocks/block-path-calculato import { SYSTEM_REFERENCE_PREFIXES } from '@/lib/workflows/sanitization/references' import { normalizeName } from '@/executor/constants' import { useWorkflowStore } from '@/stores/workflows/workflow/store' -import type { Loop } from '@/stores/workflows/workflow/types' +import type { Loop, Parallel } from '@/stores/workflows/workflow/types' export function useAccessibleReferencePrefixes(blockId?: string | null): Set | undefined { - const { blocks, edges, loops } = useWorkflowStore( + const { blocks, edges, loops, parallels } = useWorkflowStore( useShallow((state) => ({ blocks: state.blocks, edges: state.edges, loops: state.loops || {}, + parallels: state.parallels || {}, })) ) @@ -25,12 +26,12 @@ export function useAccessibleReferencePrefixes(blockId?: string | null): Set(ancestorIds) accessibleIds.add(blockId) - const loopValues = Object.values(loops as Record) - loopValues.forEach((loop) => { - if (!loop?.nodes) return - if (loop.nodes.includes(blockId)) { - accessibleIds.add(loop.id) - } + Object.values(loops as Record).forEach((loop) => { + if (loop?.nodes?.includes(blockId)) accessibleIds.add(loop.id) + }) + + Object.values(parallels as Record).forEach((parallel) => { + if (parallel?.nodes?.includes(blockId)) accessibleIds.add(parallel.id) }) const prefixes = new Set() @@ -45,5 +46,5 @@ export function useAccessibleReferencePrefixes(blockId?: string | null): Set prefixes.add(prefix)) return prefixes - }, [blockId, blocks, edges, loops]) + }, [blockId, blocks, edges, loops, parallels]) } From f31ac108bc38b888392e00af0df55a8aa98b573a Mon Sep 17 00:00:00 2001 From: waleed Date: Mon, 23 Feb 2026 14:15:10 -0800 Subject: [PATCH 8/8] fix(copilot): exclude downstream loop nodes and parallel siblings from accessible references --- .../tool-executor/workflow-tools/queries.ts | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/queries.ts b/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/queries.ts index efd9d4c367..601e6fd7cc 100644 --- a/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/queries.ts +++ b/apps/sim/lib/copilot/orchestrator/tool-executor/workflow-tools/queries.ts @@ -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' @@ -457,20 +456,9 @@ export async function executeGetBlockUpstreamReferences( const accessibleIds = new Set(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[] = []