import type { ApiResponse, ChatMessage, ChatSession, LoginResult, UserProfile } from "../types/api"; const API_BASE = import.meta.env.VITE_API_BASE_URL ?? "http://127.0.0.1:8100/api"; const TOKEN_KEY = "ai-kb-user-token"; export function getToken() { return window.localStorage.getItem(TOKEN_KEY); } export function saveToken(token: string) { window.localStorage.setItem(TOKEN_KEY, token); } export function clearToken() { window.localStorage.removeItem(TOKEN_KEY); } async function request(path: string, init: RequestInit = {}): Promise { const headers = new Headers(init.headers); headers.set("Content-Type", "application/json"); const token = getToken(); if (token) { headers.set("Authorization", `Bearer ${token}`); } const response = await fetch(`${API_BASE}${path}`, { ...init, headers }); const body = (await response.json()) as ApiResponse; if (!response.ok || body.code !== 0) { throw new Error(body.message || `${response.status} ${response.statusText}`); } return body.data; } export const api = { sendSms: (phone: string) => request("/auth/sms/send", { method: "POST", body: JSON.stringify({ phone }) }), login: (phone: string, code: string) => request("/auth/login", { method: "POST", body: JSON.stringify({ phone, code }) }), logout: () => request("/auth/logout", { method: "POST", body: JSON.stringify({}) }), profile: () => request("/user/profile"), createSession: () => request<{ sessionId: number }>("/chat/session", { method: "POST", body: JSON.stringify({}) }), listSessions: () => request("/chat/session/list"), history: (sessionId: number) => request(`/chat/history?sessionId=${sessionId}`), renameSession: (sessionId: number, title: string) => request("/chat/session/title", { method: "PUT", body: JSON.stringify({ sessionId, title }) }), deleteSession: (sessionId: number) => request(`/chat/session/${sessionId}`, { method: "DELETE" }), stop: (sessionId: number) => request("/chat/stop", { method: "POST", body: JSON.stringify({ sessionId }) }), }; export async function streamChat(sessionId: number, message: string, onChunk: (chunk: string) => void) { const token = getToken(); const response = await fetch(`${API_BASE}/chat/completions`, { method: "POST", headers: { "Content-Type": "application/json", ...(token ? { Authorization: `Bearer ${token}` } : {}), }, body: JSON.stringify({ sessionId, message }), }); if (!response.ok || !response.body) { throw new Error("AI 回复连接失败"); } const reader = response.body.getReader(); const decoder = new TextDecoder("utf-8"); let buffer = ""; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const parts = buffer.split("\n\n"); buffer = parts.pop() ?? ""; for (const part of parts) { const line = part.trim(); if (!line.startsWith("data:")) continue; const payload = line.slice(5).trim(); if (payload === "[DONE]") return; const parsed = JSON.parse(payload) as { content?: string }; if (parsed.content) onChunk(parsed.content); } } }