"use client"; import { Handle, Position, useReactFlow, type NodeProps } from "@xyflow/react"; import { NodeKind, UINode } from "lib/ai/workflow/workflow.interface"; import { cn } from "lib/utils"; import { Loader2Icon, PlusIcon, TriangleAlertIcon } from "lucide-react"; import { memo, useCallback, useEffect, useState } from "react"; import { NodeSelect } from "./node-select"; import { NodeIcon } from "./node-icon"; import { useUpdate } from "@/hooks/use-update"; import { ContextMenu, ContextMenuContent, ContextMenuTrigger, } from "ui/context-menu"; import { OutputSchemaStack } from "./node-config/input-node-config"; import { OutputNodeDataOutputStack } from "./node-config/output-node-config"; import { LLMNodeDataStack } from "./node-config/llm-node-config"; import { NodeContextMenuContent } from "./node-context-menu-content"; import { ConditionNodeDataOutputStack } from "./node-config/condition-node-config"; import { createAppendNode } from "./create-append-node"; import { ToolNodeStack } from "./node-config/tool-node-config"; import { Markdown } from "../markdown"; import { HttpNodeDataStack } from "./node-config/http-node-config"; type Props = NodeProps; export const DefaultNode = memo(function DefaultNode({ data, isConnectable, selected, id, }: Props) { const [openNodeSelect, setOpenNodeSelect] = useState(false); const { fitView, getEdges, addNodes, getNode, getNodes, addEdges, updateNode, } = useReactFlow(); const update = useUpdate(); const appendNode = useCallback( (kind: NodeKind) => { setOpenNodeSelect(false); const edges = getEdges(); const nodes = getNodes() as UINode[]; const { node: newNode, edge: newEdge } = createAppendNode({ sourceNode: getNode(data.id)! as UINode, kind, allNodes: nodes, allEdges: edges, }); addNodes([newNode]); if (newEdge) { addEdges([newEdge]); } update(() => { updateNode(id, { selected: false, }); }); }, [id, addNodes], ); useEffect(() => { if (data.runtime?.isNew) { updateNode(id, { selected: true, }); const node = getNode(id)!; if (node) { fitView({ nodes: [node], duration: 500, maxZoom: 1.2, }); } } }, [id]); return (
{![NodeKind.Note, NodeKind.Input].includes(data.kind) && ( )}
{data.name}
{![NodeKind.Note, NodeKind.Output, NodeKind.Condition].includes( data.kind, ) && ( update()} position={Position.Right} className={cn( "z-10 border-none! -right-0! bg-transparent! w-4! h-4!", )} id="right" isConnectable={isConnectable} onMouseUp={() => { setOpenNodeSelect(true); }} >
{ setOpenNodeSelect(open); }} >
)} {data.runtime?.status === "fail" ? (
) : data.runtime?.status === "running" ? (
) : null}
{data.kind === NodeKind.Input && } {data.kind === NodeKind.Output && ( )} {data.kind === NodeKind.LLM && } {data.kind === NodeKind.Condition && ( )} {data.kind === NodeKind.Tool && } {data.kind === NodeKind.Http && } {data.description && (
{data.kind === NodeKind.Note ? ( {data.description} ) : (

{data.description}

)}
)}
); });