import { listen } from "@tauri-apps/api/event"; import { FormEvent, useEffect, useMemo, useState } from "react"; import { useParams } from "react-router-dom"; import { createLiveSession, listAgents, listLiveMessages, listProjectModules, listLiveSessions, sendLiveMessage, } from "../../lib/api"; import { getErrorMessage } from "../../lib/errors"; import type { Agent, LiveMessage, LiveSession } from "../../lib/types"; interface LiveEventPayload { project_id: string; session_id: string; message: LiveMessage; } export default function ProjectLiveAgent() { const { projectId } = useParams<{ projectId: string }>(); const [agents, setAgents] = useState([]); const [sessions, setSessions] = useState([]); const [messages, setMessages] = useState([]); const [selectedSessionId, setSelectedSessionId] = useState(""); const [selectedAgentId, setSelectedAgentId] = useState(""); const [sessionTitle, setSessionTitle] = useState(""); const [draft, setDraft] = useState(""); const [sending, setSending] = useState(false); const [creatingSession, setCreatingSession] = useState(false); const [moduleEnabled, setModuleEnabled] = useState(true); const [error, setError] = useState(null); const usableAgents = useMemo( () => agents.filter((agent) => agent.role === "analyst" || agent.role === "developer"), [agents] ); async function refreshSessions(defaultSessionId?: string) { if (!projectId) return; const result = await listLiveSessions(projectId); setSessions(result); const targetSessionId = defaultSessionId ?? selectedSessionId; const firstSessionId = result[0]?.id; if (targetSessionId && result.some((session) => session.id === targetSessionId)) { setSelectedSessionId(targetSessionId); const sessionMessages = await listLiveMessages(targetSessionId); setMessages(sessionMessages); return; } if (firstSessionId) { setSelectedSessionId(firstSessionId); const sessionMessages = await listLiveMessages(firstSessionId); setMessages(sessionMessages); return; } setSelectedSessionId(""); setMessages([]); } useEffect(() => { async function load() { if (!projectId) return; setError(null); try { const [availableAgents, modules] = await Promise.all([ listAgents(), listProjectModules(projectId), ]); setAgents(availableAgents); setModuleEnabled( modules.find((mod) => mod.module_key === "ai_live_chat")?.enabled ?? true ); const firstAgentId = availableAgents[0]?.id ?? ""; setSelectedAgentId((current) => current || firstAgentId); await refreshSessions(); } catch (err: unknown) { setError(getErrorMessage(err)); } } void load(); }, [projectId]); useEffect(() => { if (!projectId) return; let stop: (() => void) | null = null; void (async () => { const unlisten = await listen("live-agent-message", (event) => { const payload = event.payload; if (payload.project_id !== projectId) return; if (payload.session_id !== selectedSessionId) return; setMessages((prev) => { if (prev.some((msg) => msg.id === payload.message.id)) { return prev; } return [...prev, payload.message]; }); }); stop = unlisten; })(); return () => { if (stop) stop(); }; }, [projectId, selectedSessionId]); async function handleCreateSession(event: FormEvent) { event.preventDefault(); if (!projectId || !selectedAgentId) return; if (!moduleEnabled) { setError("Le module Live chat agent est désactivé pour ce projet."); return; } setCreatingSession(true); setError(null); try { const created = await createLiveSession(projectId, selectedAgentId, sessionTitle); setSessionTitle(""); await refreshSessions(created.id); } catch (err: unknown) { setError(getErrorMessage(err)); } finally { setCreatingSession(false); } } async function handleSendMessage(event: FormEvent) { event.preventDefault(); if (!selectedSessionId || !draft.trim()) return; if (!moduleEnabled) { setError("Le module Live chat agent est désactivé pour ce projet."); return; } const content = draft.trim(); setDraft(""); setSending(true); setError(null); try { await sendLiveMessage(selectedSessionId, content); const updated = await listLiveMessages(selectedSessionId); setMessages(updated); } catch (err: unknown) { setDraft(content); setError(getErrorMessage(err)); } finally { setSending(false); } } async function handleSessionChange(sessionId: string) { setSelectedSessionId(sessionId); if (!sessionId) { setMessages([]); return; } try { const result = await listLiveMessages(sessionId); setMessages(result); } catch (err: unknown) { setError(getErrorMessage(err)); } } return (

Live agent

{error && (
{error}
)} {!moduleEnabled && (
Le module est désactivé. La lecture reste possible, mais la création de session et l'envoi de message sont bloqués.
)}

Nouvelle session

setSessionTitle(e.target.value)} placeholder="Titre de session (optionnel)" className="rounded border border-gray-300 px-3 py-2 text-sm" />
Sessions
{sessions.map((session) => ( ))} {sessions.length === 0 && (
Aucune session.
)}
Discussion
{messages.map((msg) => (
{msg.sender}
{msg.content}
))} {messages.length === 0 && (
Pas encore de message.
)}
setDraft(e.target.value)} placeholder="Ton message..." disabled={!selectedSessionId || sending} className="flex-1 rounded border border-gray-300 px-3 py-2 text-sm" />
); }