添加ai支持

This commit is contained in:
2026-06-10 16:04:42 +08:00
parent 51f3f917f9
commit cd03cdc44a
15 changed files with 2159 additions and 3 deletions
+108
View File
@@ -0,0 +1,108 @@
import { api } from './index'
import { useUserStore } from '@/stores/user'
export async function fetchOpenAIProfiles() {
return api.get('/aichat/openai')
}
export async function fetchAIChatAdminConfig() {
return api.post('/aichat/admin/config', {})
}
export async function updateAIChatAdminConfig(config) {
return api.post('/aichat/admin/config/update', config)
}
export async function refreshAIChatAdminConfig() {
return api.post('/aichat/admin/refresh', {})
}
function parseSSEBlock(block) {
const lines = block.split('\n')
const dataLines = []
for (const line of lines) {
if (line.startsWith('data:')) {
dataLines.push(line.slice(5).trimStart())
}
}
if (dataLines.length === 0) return null
return dataLines.join('\n')
}
export async function streamChat(messages, options = {}, handlers = {}) {
if (typeof options.onDelta === 'function' || typeof options.onError === 'function') {
handlers = options
options = {}
}
const userStore = useUserStore()
const response = await fetch('/api/aichat/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
userCookieValue: userStore.cookieValue || '',
data: { messages, openaiName: options.openaiName || '' },
}),
})
if (!response.ok) {
handlers.onError?.(`HTTP ${response.status}`)
return
}
if (!response.body) {
handlers.onError?.('ReadableStream is not supported')
return
}
const reader = response.body.getReader()
const decoder = new TextDecoder()
let buffer = ''
while (true) {
const { done, value } = await reader.read()
if (done) break
buffer += decoder.decode(value, { stream: true })
const blocks = buffer.split('\n\n')
buffer = blocks.pop() || ''
for (const block of blocks) {
const payload = parseSSEBlock(block)
if (!payload) continue
if (payload === '[DONE]') {
handlers.onDone?.()
return
}
try {
const frame = JSON.parse(payload)
switch (frame.type) {
case 'delta':
handlers.onDelta?.(frame.text || '')
break
case 'trace':
handlers.onTrace?.(frame)
break
case 'stats':
handlers.onStats?.(frame.stats || null)
break
case 'error':
handlers.onError?.(frame.error || frame.message || 'AI request failed')
break
case '[DONE]':
handlers.onDone?.()
return
default:
handlers.onFrame?.(frame)
break
}
} catch (error) {
handlers.onError?.(error.message)
}
}
}
handlers.onDone?.()
}