+ {/* Agent avatar badge - positioned at top right */}
+ {data.agent && (
+
+ )}
#{data.priority}
+ {/* Show agent name inline if present */}
+ {data.agent && (
+
+ {data.agent.name}
+
+ )}
{data.name}
@@ -184,7 +206,7 @@ function getLayoutedElements(
return { nodes: layoutedNodes, edges }
}
-function DependencyGraphInner({ graphData, onNodeClick }: DependencyGraphProps) {
+function DependencyGraphInner({ graphData, onNodeClick, activeAgents = [] }: DependencyGraphProps) {
const [direction, setDirection] = useState<'TB' | 'LR'>('LR')
// Use ref for callback to avoid triggering re-renders when callback identity changes
@@ -198,6 +220,15 @@ function DependencyGraphInner({ graphData, onNodeClick }: DependencyGraphProps)
onNodeClickRef.current?.(nodeId)
}, [])
+ // Create a map of featureId to agent info for quick lookup
+ const agentByFeatureId = useMemo(() => {
+ const map = new Map()
+ for (const agent of activeAgents) {
+ map.set(agent.featureId, { name: agent.agentName, state: agent.state })
+ }
+ return map
+ }, [activeAgents])
+
// Convert graph data to React Flow format
// Only recalculate when graphData or direction changes (not when onNodeClick changes)
const initialElements = useMemo(() => {
@@ -208,6 +239,7 @@ function DependencyGraphInner({ graphData, onNodeClick }: DependencyGraphProps)
data: {
...node,
onClick: () => handleNodeClick(node.id),
+ agent: agentByFeatureId.get(node.id),
},
}))
@@ -225,7 +257,7 @@ function DependencyGraphInner({ graphData, onNodeClick }: DependencyGraphProps)
}))
return getLayoutedElements(nodes, edges, direction)
- }, [graphData, direction, handleNodeClick])
+ }, [graphData, direction, handleNodeClick, agentByFeatureId])
const [nodes, setNodes, onNodesChange] = useNodesState(initialElements.nodes)
const [edges, setEdges, onEdgesChange] = useEdgesState(initialElements.edges)
@@ -237,9 +269,16 @@ function DependencyGraphInner({ graphData, onNodeClick }: DependencyGraphProps)
useEffect(() => {
// Create a simple hash of the graph data to detect actual changes
+ // Include agent assignments so nodes update when agents change
+ const agentInfo = Array.from(agentByFeatureId.entries()).map(([id, agent]) => ({
+ featureId: id,
+ agentName: agent.name,
+ agentState: agent.state,
+ }))
const graphHash = JSON.stringify({
nodes: graphData.nodes.map(n => ({ id: n.id, status: n.status })),
edges: graphData.edges,
+ agents: agentInfo,
})
// Only update if graph data or direction actually changed
@@ -255,7 +294,7 @@ function DependencyGraphInner({ graphData, onNodeClick }: DependencyGraphProps)
setNodes(layoutedNodes)
setEdges(layoutedEdges)
}
- }, [graphData, direction, setNodes, setEdges, initialElements])
+ }, [graphData, direction, setNodes, setEdges, initialElements, agentByFeatureId])
const onLayout = useCallback(
(newDirection: 'TB' | 'LR') => {
@@ -374,7 +413,7 @@ function DependencyGraphInner({ graphData, onNodeClick }: DependencyGraphProps)
}
// Wrapper component with error boundary for stability
-export function DependencyGraph({ graphData, onNodeClick }: DependencyGraphProps) {
+export function DependencyGraph({ graphData, onNodeClick, activeAgents }: DependencyGraphProps) {
// Use a key based on graph data length to force remount on structural changes
// This helps recover from corrupted ReactFlow state
const [resetKey, setResetKey] = useState(0)
@@ -385,7 +424,7 @@ export function DependencyGraph({ graphData, onNodeClick }: DependencyGraphProps
return (
-
+
)
}