feat: AI 流式服务完善、ProviderHttp 优化及 web-admin API 调整

- AiRuntimeServiceImpl: 流式输出逻辑优化,支持多 Provider 适配
- ProviderHttpSupport: HTTP 请求处理优化
- AiRoutingController: 新增日志查询接口
- AiCallLogService: 分页查询支持
- AiRuntimeRequest: 补充用户字段
- web-admin aiconfig API: 新增分页查询接口

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 18:35:56 +08:00
parent 64476eee6d
commit 886f04046b
9 changed files with 153 additions and 39 deletions
+31 -4
View File
@@ -358,6 +358,22 @@ async function fetchSseStream(
const decoder = new TextDecoder('utf-8')
let buffer = ''
let output = ''
let recovered = false
const finishRecovered = (event: AiRuntimeStreamEvent, message?: string) => {
if (!output.trim()) return false
recovered = true
onEvent({
type: 'done',
metadata: {
...(event.metadata || {}),
recovered: true,
warningCode: event.code,
warningMessage: message || event.message
}
}, output)
return true
}
const consumeText = (text: string) => {
buffer += text
@@ -370,17 +386,28 @@ async function fetchSseStream(
output += normalizeAiText(event.content || '')
}
onEvent(event, output)
if (event.type === 'error' && finishRecovered(event)) {
return
}
if (event.type === 'error') {
throw new Error(event.message || event.code || '流式测试失败')
}
})
}
while (true) {
const { value, done } = await reader.read()
if (done) break
consumeText(decoder.decode(value, { stream: true }))
try {
while (true) {
const { value, done } = await reader.read()
if (done) break
consumeText(decoder.decode(value, { stream: true }))
if (recovered) break
}
} catch (error: any) {
if (!finishRecovered({ type: 'error', message: error?.message })) {
throw error
}
}
if (recovered) return output
consumeText(decoder.decode())
if (buffer.trim()) consumeText('\n\n')
return output