import request from "@/utils/request"; import { PREFIX_BASE_URL, TOKEN_HEADER_NAME } from "@/config/setting"; import { getToken } from "@/utils/token-util"; export const getAiRuntime = async (promptCode = "home.default", sessionId = null) => { const res = await request.get("ai/chat/runtime", { params: { promptCode, sessionId }, }); const { code, msg, data } = res.data; if (code === 200) { return data; } throw new Error(msg || "获取 AI 运行时信息失败"); }; export const getAiSessions = async (promptCode = "home.default", keyword = "") => { const res = await request.get("ai/chat/sessions", { params: { promptCode, keyword }, }); const { code, msg, data } = res.data; if (code === 200) { return data || []; } throw new Error(msg || "获取 AI 会话列表失败"); }; export const removeAiSession = async (sessionId) => { const res = await request.post(`ai/chat/session/remove/${sessionId}`); const { code, msg, data } = res.data; if (code === 200) { return data; } throw new Error(msg || "删除 AI 会话失败"); }; export const renameAiSession = async (sessionId, title) => { const res = await request.post(`ai/chat/session/rename/${sessionId}`, { title }); const { code, msg, data } = res.data; if (code === 200) { return data; } throw new Error(msg || "重命名 AI 会话失败"); }; export const pinAiSession = async (sessionId, pinned) => { const res = await request.post(`ai/chat/session/pin/${sessionId}`, { pinned }); const { code, msg, data } = res.data; if (code === 200) { return data; } throw new Error(msg || "更新 AI 会话置顶状态失败"); }; export const clearAiSessionMemory = async (sessionId) => { const res = await request.post(`ai/chat/session/memory/clear/${sessionId}`); const { code, msg, data } = res.data; if (code === 200) { return data; } throw new Error(msg || "清空 AI 会话记忆失败"); }; export const retainAiSessionLatestRound = async (sessionId) => { const res = await request.post(`ai/chat/session/memory/retain-latest/${sessionId}`); const { code, msg, data } = res.data; if (code === 200) { return data; } throw new Error(msg || "仅保留当前轮记忆失败"); }; export const streamAiChat = async (payload, { signal, onEvent } = {}) => { const token = getToken(); const response = await fetch(`${PREFIX_BASE_URL}ai/chat/stream`, { method: "POST", headers: { "Content-Type": "application/json", "Accept": "text/event-stream", ...(token ? { [TOKEN_HEADER_NAME]: token } : {}), }, body: JSON.stringify(payload), signal, }); if (!response.ok) { throw new Error(`AI 请求失败 (${response.status})`); } if (!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 events = buffer.split(/\r?\n\r?\n/); buffer = events.pop() || ""; events.forEach((item) => dispatchSseEvent(item, onEvent)); } if (buffer.trim()) { dispatchSseEvent(buffer, onEvent); } }; const dispatchSseEvent = (rawEvent, onEvent) => { const lines = rawEvent.split(/\r?\n/); let eventName = "message"; const dataLines = []; lines.forEach((line) => { if (line.startsWith("event:")) { eventName = line.slice(6).trim(); } if (line.startsWith("data:")) { dataLines.push(line.slice(5).trim()); } }); if (!dataLines.length) { return; } const rawData = dataLines.join("\n"); let payload = rawData; try { payload = JSON.parse(rawData); } catch (error) { } if (onEvent) { onEvent(eventName, payload); } };