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