From d9868550e66fe8aaa7fff55a8e24b871ee51e3b1 Mon Sep 17 00:00:00 2001 From: blackhao <13851610112@163.com> Date: Fri, 5 Dec 2025 20:40:40 -0600 Subject: init: add project files and ignore secrets --- frontend/src/components/nodes/LLMNode.tsx | 139 ++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 frontend/src/components/nodes/LLMNode.tsx (limited to 'frontend/src/components/nodes/LLMNode.tsx') diff --git a/frontend/src/components/nodes/LLMNode.tsx b/frontend/src/components/nodes/LLMNode.tsx new file mode 100644 index 0000000..cdd402c --- /dev/null +++ b/frontend/src/components/nodes/LLMNode.tsx @@ -0,0 +1,139 @@ +import { useEffect } from 'react'; +import { Handle, Position, type NodeProps, useUpdateNodeInternals, useEdges } from 'reactflow'; +import type { NodeData } from '../../store/flowStore'; +import { Loader2, MessageSquare } from 'lucide-react'; +import useFlowStore from '../../store/flowStore'; + +const LLMNode = ({ id, data, selected }: NodeProps) => { + const { updateNodeData } = useFlowStore(); + const updateNodeInternals = useUpdateNodeInternals(); + const edges = useEdges(); + + // Force update handles when traces change + useEffect(() => { + updateNodeInternals(id); + }, [id, data.outgoingTraces, data.inputs, updateNodeInternals]); + + // Determine how many input handles to show + // We want to ensure there is always at least one empty handle at the bottom + // plus all currently connected handles. + + // Find all edges connected to this node's inputs + const connectedHandles = new Set( + edges + .filter(e => e.target === id) + .map(e => e.targetHandle) + ); + + // Logic: + // If input-0 is connected, show input-1. + // If input-1 is connected, show input-2. + // We can just iterate until we find an unconnected one. + + let handleCount = 1; + while (connectedHandles.has(`input-${handleCount - 1}`)) { + handleCount++; + } + + // But wait, if we delete an edge to input-0, we still want input-1 to exist if it's connected? + // No, usually in this designs, we just render up to max(connected_index) + 1. + + // Let's get the max index connected + let maxConnectedIndex = -1; + edges.filter(e => e.target === id).forEach(e => { + const idx = parseInt(e.targetHandle?.replace('input-', '') || '0'); + if (!isNaN(idx) && idx > maxConnectedIndex) { + maxConnectedIndex = idx; + } + }); + + const inputsToShow = Math.max(maxConnectedIndex + 2, 1); + + return ( +
+
+
+ {data.status === 'loading' ? ( + + ) : ( + + )} +
+
+
{data.label}
+
{data.model}
+
+
+ + {/* Dynamic Inputs */} +
+ {Array.from({ length: inputsToShow }).map((_, i) => { + // Find the connected edge to get color + const connectedEdge = edges.find(e => e.target === id && e.targetHandle === `input-${i}`); + const edgeColor = connectedEdge?.style?.stroke as string; + + return ( +
+ + + {i} + +
+ ); + })} +
+ + {/* Dynamic Outputs (Traces) */} +
+ {/* 1. Outgoing Traces (Pass-through + Self) */} + {data.outgoingTraces && data.outgoingTraces.map((trace, i) => ( +
+ +
+ ))} + + {/* 2. New Branch Generator Handle (Always visible) */} +
+ + + + New + +
+
+ + {data.status === 'error' && ( +
Error
+ )} +
+ ); +}; + +export default LLMNode; + -- cgit v1.2.3