import { useState, useCallback } from "react"; import { X, Send, Loader2, Bot, AlertCircle } from "lucide-react"; import type { ParticipantType, MessageType } from "@fusion/core"; import { sendMessage } from "../api"; import type { Agent } from "../api"; // ── Types ───────────────────────────────────────────────────────────────── interface MessageComposerProps { /** Pre-fill recipient (e.g. when replying) */ recipient?: { id: string; type: ParticipantType } | null; /** List of agents for recipient selection */ agents?: Agent[]; /** Project ID for multi-project */ projectId?: string; /** Called when message is successfully sent */ onSend: () => void; /** Called when user cancels */ onCancel: () => void; /** Toast notification callback */ addToast?: (msg: string, type?: "success" | "error") => void; /** Loading state for agents (shows placeholder) */ isLoadingAgents?: boolean; } const MAX_CONTENT_LENGTH = 2000; // ── Component ───────────────────────────────────────────────────────────── export function MessageComposer({ recipient, agents = [], projectId, onSend, onCancel, addToast, isLoadingAgents = false, }: MessageComposerProps) { const [toId, setToId] = useState(recipient?.id ?? ""); const [toType, setToType] = useState(recipient?.type ?? "agent"); const [content, setContent] = useState(""); const [isSending, setIsSending] = useState(false); const [error, setError] = useState(null); const isValid = toId.trim() !== "" && content.trim().length > 0 && content.length <= MAX_CONTENT_LENGTH; const handleSend = useCallback(async () => { if (!isValid || isSending) return; setIsSending(true); setError(null); try { const messageType: MessageType = toType === "agent" ? "user-to-agent" : "system"; await sendMessage( { toId: toId.trim(), toType, content: content.trim(), type: messageType, }, projectId, ); onSend(); } catch (err: any) { const msg = err?.message ?? "Failed to send message"; setError(msg); addToast?.(msg, "error"); } finally { setIsSending(false); } }, [isValid, isSending, toId, toType, content, projectId, onSend, addToast]); const handleAgentSelect = useCallback((agentId: string) => { setToId(agentId); setToType("agent"); }, []); return (
New Message
{/* Recipient selection */} {!recipient && (
)} {/* Recipient display (when pre-filled from reply) */} {recipient && (
To: {recipient.id}
)} {/* Content */}