import { parseSSE, type SSEEvent } from "./lib/sse"; export interface Source { reference: string; text: string; book: string; chapter: number; verse: number; file: string; score: number; } export interface Status { state: "ready" | "indexing" | "error"; sources_total: number; sources_indexed: number; chunks: number; model: string; last_indexed_at: string | null; errors: string[]; verses_indexed: number; verses_total: number; current_file: string | null; } export interface ChatMessage { role: "user" | "assistant"; content: string; } const API_BASE = import.meta.env.VITE_API_BASE_URL ?? ""; async function request(path: string, init?: RequestInit): Promise { const response = await fetch(`${API_BASE}${path}`, { headers: { "Content-Type": "application/json" }, ...init, }); if (!response.ok) { let detail = `Erro ${response.status}`; try { const body = (await response.json()) as { detail?: string }; if (body.detail) { detail = body.detail; } } catch { /* resposta sem corpo JSON */ } throw new Error(detail); } return (await response.json()) as T; } export function fetchStatus(): Promise { return request("/api/status"); } export function reindex(): Promise<{ state: string }> { return request<{ state: string }>("/api/reindex", { method: "POST" }); } /** Envia a mensagem e devolve os eventos do stream. */ export async function* sendMessage( message: string, history: ChatMessage[], ): AsyncGenerator { const response = await fetch(`${API_BASE}/api/chat`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message, history }), }); if (!response.ok || !response.body) { let detail = `Erro ${response.status}`; try { const body = (await response.json()) as { detail?: string }; if (body.detail) { detail = body.detail; } } catch { /* resposta sem corpo JSON */ } throw new Error(detail); } yield* parseSSE(response.body); }