// web/src/api.ts const BASE = import.meta.env.VITE_API_BASE ?? "" export interface Document { id: string title: string file_path: string status: "pending" | "processing" | "ready" | "error" task_id: string | null page_count: number | null created_at: string } export interface SearchResult { chunk_id: string doc_id: string page_number: number text_snippet: string bm25_score: number } export interface Citation { doc_id: string page_number: number snippet: string bm25_score: number | null } export interface ChatResponse { answer: string citations: Citation[] } export interface TaskStatus { status: string progress?: number error?: string } export interface ChatMessage { role: string content: string } export const api = { async getLibrary(): Promise { const r = await fetch(`${BASE}/api/library`) if (!r.ok) throw new Error(await r.text()) return r.json() }, async scanLibrary(): Promise<{ discovered: number; queued: number; tasks: { doc_id: string; task_id: string }[] }> { const r = await fetch(`${BASE}/api/library/scan`, { method: "POST" }) if (!r.ok) throw new Error(await r.text()) return r.json() }, async reingestDocument(docId: string): Promise<{ task_id: string }> { const r = await fetch(`${BASE}/api/library/${docId}/reingest`, { method: "POST" }) if (!r.ok) throw new Error(await r.text()) return r.json() }, async deleteDocument(docId: string): Promise { const r = await fetch(`${BASE}/api/library/${docId}`, { method: "DELETE" }) if (!r.ok) throw new Error(await r.text()) }, async getTaskStatus(taskId: string): Promise { const r = await fetch(`${BASE}/api/ingest/${taskId}`) if (!r.ok) throw new Error(await r.text()) return r.json() }, async search(query: string, topK = 10, docIds?: string[]): Promise { const r = await fetch(`${BASE}/api/search`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query, top_k: topK, doc_ids: docIds ?? null }), }) if (!r.ok) throw new Error(await r.text()) return r.json() }, async chat( message: string, history: ChatMessage[], docIds?: string[], topK = 5, ): Promise { const r = await fetch(`${BASE}/api/chat`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message, history, doc_ids: docIds ?? null, top_k: topK }), }) if (!r.ok) { const body = await r.json().catch(() => ({})) const err: Error & { status?: number; detail?: unknown } = new Error( (body as { detail?: { message?: string } }).detail?.message ?? "Request failed" ) err.status = r.status err.detail = (body as { detail?: unknown }).detail throw err } return r.json() }, }