import { getNotebookApiBaseURL } from "@/core/config"; import type { SourceItem, StudioNotebook } from "./types"; function base(): string { return getNotebookApiBaseURL(); } export async function fetchStudioToken(email: string): Promise { const apiBase = base(); if (!apiBase) throw new Error("VITE_AIPI_FRONTEND_URL 未配置"); const res = await fetch( `${apiBase}/api/getTokenByEmail?email=${encodeURIComponent(email)}`, ); if (!res.ok) throw new Error(`获取 Token 失败:${res.status}`); const data = (await res.json()) as { token?: string } | string; const token = typeof data === "string" ? data : data?.token; if (!token) throw new Error("接口未返回有效 token"); return token; } export async function fetchStudioNotebooks(token: string): Promise { const apiBase = base(); if (!apiBase) throw new Error("VITE_AIPI_FRONTEND_URL 未配置"); const res = await fetch(`${apiBase}/api/v1/searchspaces`, { headers: { Authorization: `Bearer ${token}` }, }); if (!res.ok) throw new Error(`获取笔记本列表失败:${res.status}`); return res.json() as Promise; } export async function createSearchSpace( name: string, token: string, ): Promise { const apiBase = base(); if (!apiBase) throw new Error("VITE_AIPI_FRONTEND_URL 未配置"); const res = await fetch(`${apiBase}/api/v1/searchspaces`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify({ name, description: "", citations_enabled: true }), }); if (!res.ok) { const body = await res.json().catch(() => null); throw new Error(body?.detail || `创建失败:${res.status}`); } } export async function uploadSourceText( notebookId: number, content: string, title: string, token: string, ): Promise { const apiBase = base(); if (!apiBase) throw new Error("VITE_AIPI_FRONTEND_URL 未配置"); const res = await fetch(`${apiBase}/api/v1/documents/textupload`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, body: JSON.stringify({ search_space_id: notebookId, content, title: title || "粘贴的文字" }), }); if (!res.ok) throw new Error(`上传失败:${res.status}`); } export async function deleteSearchSpace(id: number, token: string): Promise { const apiBase = base(); if (!apiBase) throw new Error("VITE_AIPI_FRONTEND_URL 未配置"); const res = await fetch(`${apiBase}/api/v1/searchspaces/${id}`, { method: "DELETE", headers: { Authorization: `Bearer ${token}` }, }); if (!res.ok) throw new Error(`删除失败:${res.status}`); } export async function renameSearchSpace(id: number, name: string, token: string): Promise { const apiBase = base(); if (!apiBase) throw new Error("VITE_AIPI_FRONTEND_URL 未配置"); const res = await fetch(`${apiBase}/api/v1/searchspaces/${id}`, { method: "PATCH", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` }, body: JSON.stringify({ name }), }); if (!res.ok) throw new Error(`重命名失败:${res.status}`); } export interface ChunkRead { id: number; content: string; document_id: number; created_at: string; } export interface DocumentWithChunks { id: number; title: string; document_type: string; file_type: string; chunks: ChunkRead[]; } export async function fetchDocumentByChunk( chunkId: number, token: string, ): Promise { const apiBase = base(); if (!apiBase) throw new Error("VITE_AIPI_FRONTEND_URL 未配置"); const res = await fetch(`${apiBase}/api/v1/documents/by-chunk/${chunkId}`, { headers: { Authorization: `Bearer ${token}` }, }); if (!res.ok) throw new Error(`获取文档失败:${res.status}`); return res.json() as Promise; } export async function uploadSourceFiles( notebookId: number, files: File[], token: string, ): Promise { const apiBase = base(); if (!apiBase) throw new Error("VITE_AIPI_FRONTEND_URL 未配置"); const formData = new FormData(); formData.append("search_space_id", String(notebookId)); for (const file of files) { formData.append("files", file); } const res = await fetch(`${apiBase}/api/v1/documents/fileupload`, { method: "POST", headers: { Authorization: `Bearer ${token}` }, body: formData, }); if (!res.ok) throw new Error(`上传失败:${res.status}`); } export async function fetchNotebookSources( notebookId: number, token: string, ): Promise { const apiBase = base(); if (!apiBase) throw new Error("VITE_AIPI_FRONTEND_URL 未配置"); const res = await fetch( `${apiBase}/api/v1/source/search-space/${notebookId}?limit=100`, { headers: { Authorization: `Bearer ${token}` } }, ); if (!res.ok) throw new Error(`获取来源失败:${res.status}`); return res.json() as Promise; }