import { useIsDarkTheme, useTheme } from '@/components/theme-provider'; import { Tooltip, TooltipContent, TooltipTrigger, } from '@/components/ui/tooltip'; import { useSetModalState } from '@/hooks/common-hooks'; import { cn } from '@/lib/utils'; import { ConnectionMode, ControlButton, Controls, NodeTypes, Position, ReactFlow, } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; import { NotebookPen } from 'lucide-react'; import { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ChatSheet } from '../chat/chat-sheet'; import { AgentBackground } from '../components/background'; import { AgentChatContext, AgentChatLogContext, AgentInstanceContext, HandleContext, } from '../context'; import FormSheet from '../form-sheet/next'; import { useHandleDrop, useSelectCanvasData, useValidateConnection, } from '../hooks'; import { useAddNode } from '../hooks/use-add-node'; import { useBeforeDelete } from '../hooks/use-before-delete'; import { useCacheChatLog } from '../hooks/use-cache-chat-log'; import { useConnectionDrag } from '../hooks/use-connection-drag'; import { useDropdownPosition } from '../hooks/use-dropdown-position'; import { useMoveNote } from '../hooks/use-move-note'; import { usePlaceholderManager } from '../hooks/use-placeholder-manager'; import { useDropdownManager } from './context'; import Spotlight from '@/components/spotlight'; import { useHideFormSheetOnNodeDeletion, useShowDrawer, useShowLogSheet, } from '../hooks/use-show-drawer'; import { LogSheet } from '../log-sheet'; import RunSheet from '../run-sheet'; import { ButtonEdge } from './edge'; import styles from './index.less'; import { RagNode } from './node'; import { AgentNode } from './node/agent-node'; import { BeginNode } from './node/begin-node'; import { CategorizeNode } from './node/categorize-node'; import { InnerNextStepDropdown } from './node/dropdown/next-step-dropdown'; import { GenerateNode } from './node/generate-node'; import { InvokeNode } from './node/invoke-node'; import { IterationNode, IterationStartNode } from './node/iteration-node'; import { KeywordNode } from './node/keyword-node'; import { LogicNode } from './node/logic-node'; import { MessageNode } from './node/message-node'; import NoteNode from './node/note-node'; import { PlaceholderNode } from './node/placeholder-node'; import { RelevantNode } from './node/relevant-node'; import { RetrievalNode } from './node/retrieval-node'; import { RewriteNode } from './node/rewrite-node'; import { SwitchNode } from './node/switch-node'; import { TemplateNode } from './node/template-node'; import { ToolNode } from './node/tool-node'; export const nodeTypes: NodeTypes = { ragNode: RagNode, categorizeNode: CategorizeNode, beginNode: BeginNode, placeholderNode: PlaceholderNode, relevantNode: RelevantNode, logicNode: LogicNode, noteNode: NoteNode, switchNode: SwitchNode, generateNode: GenerateNode, retrievalNode: RetrievalNode, messageNode: MessageNode, rewriteNode: RewriteNode, keywordNode: KeywordNode, invokeNode: InvokeNode, templateNode: TemplateNode, // emailNode: EmailNode, group: IterationNode, iterationStartNode: IterationStartNode, agentNode: AgentNode, toolNode: ToolNode, }; const edgeTypes = { buttonEdge: ButtonEdge, }; interface IProps { drawerVisible: boolean; hideDrawer(): void; } function AgentCanvas({ drawerVisible, hideDrawer }: IProps) { const { t } = useTranslation(); const { nodes, edges, onConnect: originalOnConnect, onEdgesChange, onNodesChange, onSelectionChange, onEdgeMouseEnter, onEdgeMouseLeave, } = useSelectCanvasData(); const isValidConnection = useValidateConnection(); const { onDrop, onDragOver, setReactFlowInstance, reactFlowInstance } = useHandleDrop(); const { onNodeClick, clickedNode, formDrawerVisible, hideFormDrawer, singleDebugDrawerVisible, hideSingleDebugDrawer, showSingleDebugDrawer, chatVisible, runVisible, hideRunOrChatDrawer, showChatModal, showFormDrawer, } = useShowDrawer({ drawerVisible, hideDrawer, }); const { addEventList, setCurrentMessageId, currentEventListWithoutMessageById, clearEventList, currentMessageId, } = useCacheChatLog(); const { showLogSheet, logSheetVisible, hideLogSheet } = useShowLogSheet({ setCurrentMessageId, }); const [lastSendLoading, setLastSendLoading] = useState(false); const { handleBeforeDelete } = useBeforeDelete(); const { addCanvasNode, addNoteNode } = useAddNode(reactFlowInstance); const { ref, showImage, hideImage, imgVisible, mouse } = useMoveNote(); const { theme } = useTheme(); useEffect(() => { if (!chatVisible) { clearEventList(); } }, [chatVisible, clearEventList]); const setLastSendLoadingFunc = (loading: boolean, messageId: string) => { if (messageId === currentMessageId) { setLastSendLoading(loading); } else { setLastSendLoading(false); } }; const isDarkTheme = useIsDarkTheme(); useHideFormSheetOnNodeDeletion({ hideFormDrawer }); const { visible, hideModal, showModal } = useSetModalState(); const [dropdownPosition, setDropdownPosition] = useState({ x: 0, y: 0 }); const { clearActiveDropdown } = useDropdownManager(); const { removePlaceholderNode, onNodeCreated, setCreatedPlaceholderRef } = usePlaceholderManager(reactFlowInstance); const { calculateDropdownPosition } = useDropdownPosition(reactFlowInstance); const { onConnectStart, onConnectEnd, handleConnect, getConnectionStartContext, shouldPreventClose, onMove, } = useConnectionDrag( reactFlowInstance, originalOnConnect, showModal, hideModal, setDropdownPosition, setCreatedPlaceholderRef, calculateDropdownPosition, removePlaceholderNode, clearActiveDropdown, ); const onPaneClick = useCallback(() => { hideFormDrawer(); if (visible && !shouldPreventClose()) { removePlaceholderNode(); hideModal(); clearActiveDropdown(); } if (imgVisible) { addNoteNode(mouse); hideImage(); } }, [ hideFormDrawer, visible, shouldPreventClose, hideModal, imgVisible, addNoteNode, mouse, hideImage, clearActiveDropdown, removePlaceholderNode, ]); return (