/** * @file AI Chat Node - Interactive chatbot interface */ import * as React from "react"; import type { NodeDefinition, NodeRendererProps, InspectorRenderProps, ExternalDataReference, } from "../../../../../types/NodeDefinition"; import classes from "./AIChatNode.module.css"; export type ChatMessage = { role: "user" | "assistant" | "system"; content: string; timestamp: number; }; export type ChatData = { id: string; botName: string; botAvatar: string; messages: ChatMessage[]; isTyping: boolean; temperature: number; model: string; }; export const AIChatRenderer = ({ node, isSelected, isDragging, externalData }: NodeRendererProps) => { const chatData = externalData as ChatData | undefined; const messagesEndRef = React.useRef(null); const chatColor = "#06b6d4"; return (
{chatData?.botAvatar || "🤖"}
{chatData?.botName || "AI Assistant"}
{chatData?.isTyping ? "typing..." : "online"}
{chatData?.model || "GPT-4"}
{chatData?.messages?.slice(-3).map((message, index) => (
{message.content}
))} {chatData?.isTyping && (
)}
Type a message...
); }; export const AIChatInspectorRenderer = ({ externalData, onUpdateExternalData }: InspectorRenderProps) => { const chatData = externalData as ChatData | undefined; const [editedData, setEditedData] = React.useState({ id: chatData?.id || "", botName: chatData?.botName || "AI Assistant", botAvatar: chatData?.botAvatar || "🤖", messages: chatData?.messages || [], isTyping: chatData?.isTyping || false, temperature: chatData?.temperature || 0.7, model: chatData?.model || "GPT-4", }); const [newMessage, setNewMessage] = React.useState(""); const addMessage = (role: "user" | "assistant") => { if (!newMessage.trim()) { return; } setEditedData((prev) => ({ ...prev, messages: [ ...prev.messages, { role, content: newMessage, timestamp: Date.now(), }, ], })); setNewMessage(""); }; const clearMessages = () => { setEditedData((prev) => ({ ...prev, messages: [] })); }; const handleSave = async () => { if (onUpdateExternalData) { await onUpdateExternalData(editedData); } }; return (

AI Chat Configuration

setEditedData({ ...editedData, botName: e.target.value })} className={classes.input} />
setEditedData({ ...editedData, botAvatar: e.target.value })} className={classes.input} maxLength={2} />
setEditedData({ ...editedData, temperature: Number(e.target.value) })} className={classes.slider} />