import { useLocation } from '@docusaurus/router'; import { useCallback, useEffect, useRef, useState } from 'react'; import { useOptions } from '@docuservix/hooks/useOptions'; import { IChat, IChatMessage, IChatSource } from '@docuservix/models/chat'; interface UseChatResult { dialog: IChat; typing: boolean; statusMessage?: string; sendMessage: (text: string) => void; } function useQuery(): string { const location = useLocation(); const params = new URLSearchParams(location.search); return params.get('q') ?? ''; } export function useChat(): UseChatResult { const chatEndpoint = useOptions().api + '/v1/chat'; const urlQuery = useQuery(); const [messages, setMessages] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const initialSentRef = useRef(false); const messagesEndRef = useRef(messages); messagesEndRef.current = messages; const sendMessage = useCallback( async (text: string) => { const content = text.trim(); if (!content) { return; } const userMessage: IChatMessage = { role: 'user', content }; const newHistory = [...messagesEndRef.current, userMessage]; setMessages(newHistory); setLoading(true); setError(null); try { const res = await fetch(chatEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ messages: newHistory }), }); if (!res.ok) { throw new Error(`HTTP ${res.status}`); } const data: { answer: string; sources?: IChatSource[] } = await res.json(); setMessages((prev) => [ ...prev, { role: 'assistant', content: data.answer, sources: data.sources }, ]); } catch (err) { setError(err instanceof Error ? err.message : 'Ошибка при обращении к серверу'); } finally { setLoading(false); } }, [chatEndpoint], ); useEffect(() => { if (urlQuery && !initialSentRef.current) { initialSentRef.current = true; sendMessage(urlQuery); } }, [urlQuery, sendMessage]); return { dialog: { messages }, typing: loading, statusMessage: error ?? undefined, sendMessage, }; }