Created state edge detection on edge connect

This commit is contained in:
Emir Karabeg
2025-02-10 15:06:32 -08:00
parent 85b35eacdf
commit c499946346
2 changed files with 82 additions and 10 deletions
+21 -10
View File
@@ -5,6 +5,7 @@ import { getBlock } from '@/blocks'
import { resolveOutputType } from '@/blocks/utils'
import { WorkflowStoreWithHistory, pushHistory, withHistory } from './middleware'
import { Position, SubBlockState } from './types'
import { detectCycle } from './utils'
const initialState = {
blocks: {},
@@ -179,18 +180,28 @@ export const useWorkflowStore = create<WorkflowStoreWithHistory>()(
},
addEdge: (edge: Edge) => {
// First create the new edge
const newEdge = {
id: edge.id || crypto.randomUUID(),
source: edge.source,
target: edge.target,
sourceHandle: edge.sourceHandle,
targetHandle: edge.targetHandle,
}
// Create temporary edges array with the new edge
const newEdges = [...get().edges, newEdge]
// Check for cycles starting from the source node
const { hasCycle, path } = detectCycle(newEdges, edge.source)
if (hasCycle) {
console.log('Loop detected through nodes:', path.join(' → '))
}
const newState = {
blocks: { ...get().blocks },
edges: [
...get().edges,
{
id: edge.id || crypto.randomUUID(),
source: edge.source,
target: edge.target,
sourceHandle: edge.sourceHandle,
targetHandle: edge.targetHandle,
},
],
edges: newEdges,
}
set(newState)
+61
View File
@@ -0,0 +1,61 @@
import { Edge } from 'reactflow'
/**
* Performs a depth-first search to detect cycles in the graph
* @param edges - List of all edges in the graph
* @param startNode - Starting node for cycle detection
* @returns boolean indicating if a cycle was detected and the path of the cycle if found
*/
export function detectCycle(edges: Edge[], startNode: string): { hasCycle: boolean; path: string[] } {
const visited = new Set<string>()
const recursionStack = new Set<string>()
const pathMap = new Map<string, string>()
function dfs(node: string): boolean {
// Add to both visited and recursion stack
visited.add(node)
recursionStack.add(node)
// Get all neighbors of current node
const neighbors = edges
.filter(edge => edge.source === node)
.map(edge => edge.target)
for (const neighbor of neighbors) {
// If not visited, explore that path
if (!visited.has(neighbor)) {
pathMap.set(neighbor, node)
if (dfs(neighbor)) return true
}
// If the neighbor is in recursion stack, we found a cycle
else if (recursionStack.has(neighbor)) {
// Record the last edge of the cycle
pathMap.set(neighbor, node)
return true
}
}
// Remove from recursion stack when backtracking
recursionStack.delete(node)
return false
}
// Perform DFS and construct cycle path if found
const hasCycle = dfs(startNode)
// If cycle found, construct the path
const cyclePath: string[] = []
if (hasCycle) {
let current = startNode
do {
cyclePath.unshift(current)
current = pathMap.get(current)!
} while (current !== startNode && current !== undefined)
if (current === startNode) {
cyclePath.unshift(startNode)
}
}
return { hasCycle, path: cyclePath }
}