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);
|
}
|
};
|