1- import { createContext , Dispatch , ReactNode , useCallback , useContext , useReducer } from 'react'
1+ import { createContext , Dispatch , ReactNode , useCallback , useContext , useReducer , useRef } from 'react'
22import type { ReactFlowInstance } from 'reactflow'
33
44import type { AgentflowAction , AgentflowState , FlowConfig , FlowData , FlowEdge , FlowNode , InputParam , NodeData } from '@/core/types'
@@ -32,6 +32,9 @@ export interface AgentflowContextValue {
3232 //Dialog operations
3333 openEditDialog : ( nodeId : string , data : NodeData , inputParams : InputParam [ ] ) => void
3434 closeEditDialog : ( ) => void
35+
36+ // Register ReactFlow local state setters
37+ registerLocalStateSetters : ( setLocalNodes : ( nodes : FlowNode [ ] ) => void , setLocalEdges : ( edges : FlowEdge [ ] ) => void ) => void
3538}
3639
3740const AgentflowContext = createContext < AgentflowContextValue | null > ( null )
@@ -48,6 +51,34 @@ export function AgentflowStateProvider({ children, initialFlow }: AgentflowState
4851 edges : initialFlow ?. edges || [ ]
4952 } )
5053
54+ // Store ReactFlow local state setters in refs which are populated by AgentflowCanvas
55+ const localNodesSetterRef = useRef < ( ( nodes : FlowNode [ ] ) => void ) | null > ( null )
56+ const localEdgesSetterRef = useRef < ( ( edges : FlowEdge [ ] ) => void ) | null > ( null )
57+
58+ const registerLocalStateSetters = useCallback (
59+ ( setLocalNodes : ( nodes : FlowNode [ ] ) => void , setLocalEdges : ( edges : FlowEdge [ ] ) => void ) => {
60+ localNodesSetterRef . current = setLocalNodes
61+ localEdgesSetterRef . current = setLocalEdges
62+ } ,
63+ [ ]
64+ )
65+
66+ // Helper function to synchronize state updates between context and ReactFlow
67+ const syncStateUpdate = useCallback ( ( { nodes, edges } : { nodes ?: FlowNode [ ] ; edges ?: FlowEdge [ ] } ) => {
68+ if ( nodes !== undefined ) {
69+ const normalizedNodes = normalizeNodes ( nodes )
70+ dispatch ( { type : 'SET_NODES' , payload : normalizedNodes } )
71+ localNodesSetterRef . current ?.( normalizedNodes )
72+ }
73+ if ( edges !== undefined ) {
74+ dispatch ( { type : 'SET_EDGES' , payload : edges } )
75+ localEdgesSetterRef . current ?.( edges )
76+ }
77+ if ( nodes !== undefined || edges !== undefined ) {
78+ dispatch ( { type : 'SET_DIRTY' , payload : true } )
79+ }
80+ } , [ ] )
81+
5182 // Convenience setters
5283 const setNodes = useCallback ( ( nodes : FlowNode [ ] ) => {
5384 dispatch ( { type : 'SET_NODES' , payload : nodes } )
@@ -74,11 +105,10 @@ export function AgentflowStateProvider({ children, initialFlow }: AgentflowState
74105 ( nodeId : string ) => {
75106 const newNodes = state . nodes . filter ( ( node ) => node . id !== nodeId )
76107 const newEdges = state . edges . filter ( ( edge ) => edge . source !== nodeId && edge . target !== nodeId )
77- dispatch ( { type : 'SET_NODES' , payload : newNodes } )
78- dispatch ( { type : 'SET_EDGES' , payload : newEdges } )
79- dispatch ( { type : 'SET_DIRTY' , payload : true } )
108+
109+ syncStateUpdate ( { nodes : newNodes , edges : newEdges } )
80110 } ,
81- [ state . nodes , state . edges ]
111+ [ state . nodes , state . edges , syncStateUpdate ]
82112 )
83113
84114 const duplicateNode = useCallback (
@@ -96,10 +126,10 @@ export function AgentflowStateProvider({ children, initialFlow }: AgentflowState
96126 data : { ...nodeToDuplicate . data }
97127 }
98128
99- dispatch ( { type : 'SET_NODES' , payload : [ ...state . nodes , newNode ] } )
100- dispatch ( { type : 'SET_DIRTY' , payload : true } )
129+ const newNodes = [ ...state . nodes , newNode ]
130+ syncStateUpdate ( { nodes : newNodes } )
101131 } ,
102- [ state . nodes ]
132+ [ state . nodes , syncStateUpdate ]
103133 )
104134
105135 const updateNodeData = useCallback (
@@ -113,20 +143,19 @@ export function AgentflowStateProvider({ children, initialFlow }: AgentflowState
113143 }
114144 return node
115145 } )
116- dispatch ( { type : 'SET_NODES' , payload : newNodes } )
117- dispatch ( { type : 'SET_DIRTY' , payload : true } )
146+
147+ syncStateUpdate ( { nodes : newNodes } )
118148 } ,
119- [ state . nodes ]
149+ [ state . nodes , syncStateUpdate ]
120150 )
121151
122152 // Edge operations
123153 const deleteEdge = useCallback (
124154 ( edgeId : string ) => {
125155 const newEdges = state . edges . filter ( ( edge ) => edge . id !== edgeId )
126- dispatch ( { type : 'SET_EDGES' , payload : newEdges } )
127- dispatch ( { type : 'SET_DIRTY' , payload : true } )
156+ syncStateUpdate ( { edges : newEdges } )
128157 } ,
129- [ state . edges ]
158+ [ state . edges , syncStateUpdate ]
130159 )
131160
132161 // Dialog operations
@@ -179,7 +208,8 @@ export function AgentflowStateProvider({ children, initialFlow }: AgentflowState
179208 openEditDialog,
180209 closeEditDialog,
181210 getFlowData,
182- reset
211+ reset,
212+ registerLocalStateSetters
183213 }
184214
185215 return < AgentflowContext . Provider value = { value } > { children } </ AgentflowContext . Provider >
0 commit comments