import request from '@/utils/http' import { useUserStore } from '@/store/modules/user' const DEFAULT_PROMPT_CODE = 'home.default' function buildRuntimeParams(promptCode = DEFAULT_PROMPT_CODE, sessionId = null, aiParamId = null) { return { promptCode, ...(sessionId ? { sessionId } : {}), ...(aiParamId !== null && aiParamId !== undefined ? { aiParamId } : {}) } } function fetchGetAiRuntime(promptCode = DEFAULT_PROMPT_CODE, sessionId = null, aiParamId = null) { return request.get({ url: '/ai/chat/runtime', params: buildRuntimeParams(promptCode, sessionId, aiParamId), showErrorMessage: false }) } function fetchGetAiSessions(promptCode = DEFAULT_PROMPT_CODE, keyword = '') { return request.get({ url: '/ai/chat/sessions', params: { promptCode, ...(keyword ? { keyword } : {}) }, showErrorMessage: false }) } function fetchRemoveAiSession(sessionId) { return request.post({ url: `/ai/chat/session/remove/${sessionId}`, showErrorMessage: false }) } function fetchRenameAiSession(sessionId, title) { return request.post({ url: `/ai/chat/session/rename/${sessionId}`, params: { title }, showErrorMessage: false }) } function fetchPinAiSession(sessionId, pinned) { return request.post({ url: `/ai/chat/session/pin/${sessionId}`, params: { pinned }, showErrorMessage: false }) } function fetchClearAiSessionMemory(sessionId) { return request.post({ url: `/ai/chat/session/memory/clear/${sessionId}`, showErrorMessage: false }) } function fetchRetainAiSessionLatestRound(sessionId) { return request.post({ url: `/ai/chat/session/memory/retain-latest/${sessionId}`, showErrorMessage: false }) } async function fetchStreamAiChat(payload, { signal, onEvent } = {}) { const { VITE_API_URL } = import.meta.env const { accessToken } = useUserStore() const response = await fetch(`${VITE_API_URL}/ai/chat/stream`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'text/event-stream', ...(accessToken ? { Authorization: accessToken } : {}) }, 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) } } function dispatchSseEvent(rawEvent, onEvent) { if (!onEvent) { return } 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 { } onEvent(eventName, payload) } export { DEFAULT_PROMPT_CODE, fetchClearAiSessionMemory, fetchGetAiRuntime, fetchGetAiSessions, fetchPinAiSession, fetchRemoveAiSession, fetchRenameAiSession, fetchRetainAiSessionLatestRound, fetchStreamAiChat }