'use client'; import React, { useCallback, useMemo } from 'react'; import { ReactFlow, Background, Controls, MiniMap, type Node, type Edge, type OnNodesChange, type OnEdgesChange, type OnConnect, type NodeTypes, type EdgeTypes, BackgroundVariant, ConnectionMode, addEdge, } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; import { ToolNode } from './ToolNode'; import { GroupNode } from './GroupNode'; import { ConnectionEdge } from './ConnectionEdge'; import { CanvasToolbar } from './CanvasToolbar'; import { useCanvasState } from '../../hooks/useCanvasState'; import type { ToolDefinition } from '@mcpengine/ai-pipeline/types'; interface ToolCanvasProps { tools: ToolDefinition[]; onToolSelect: (toolName: string | null) => void; onToolsChange: (tools: ToolDefinition[]) => void; } const nodeTypes: NodeTypes = { tool: ToolNode, group: GroupNode, }; const edgeTypes: EdgeTypes = { connection: ConnectionEdge, }; export function ToolCanvas({ tools, onToolSelect, onToolsChange }: ToolCanvasProps) { const { nodes, edges, setNodes, setEdges, selectedNodeId, selectNode, } = useCanvasState(); const onNodesChange: OnNodesChange = useCallback( (changes) => { setNodes(changes); }, [setNodes] ); const onEdgesChange: OnEdgesChange = useCallback( (changes) => { setEdges(changes); }, [setEdges] ); const onConnect: OnConnect = useCallback( (connection) => { useCanvasState.setState((state) => ({ edges: addEdge( { ...connection, type: 'connection', animated: true }, state.edges ), })); }, [] ); const onNodeClick = useCallback( (_: React.MouseEvent, node: Node) => { selectNode(node.id); onToolSelect(node.id); }, [selectNode, onToolSelect] ); const onPaneClick = useCallback(() => { selectNode(null); onToolSelect(null); }, [selectNode, onToolSelect]); const defaultEdgeOptions = useMemo( () => ({ type: 'connection', animated: true, }), [] ); return (