feat(chat): implement AiChatRepository for SSE streaming

This commit is contained in:
844143714@qq,com 2026-05-19 21:13:06 +08:00
parent f93c7c3e43
commit fcf63c6175
1 changed files with 55 additions and 0 deletions

View File

@ -0,0 +1,55 @@
package com.stand.standapp.ui.chat.repo
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okhttp3.sse.EventSource
import okhttp3.sse.EventSourceListener
import okhttp3.sse.EventSources
import timber.log.Timber
import java.util.concurrent.TimeUnit
class AiChatRepository {
// 根据后端实际情况修改,模拟器访问本地后端用 10.0.2.2
private val backendUrl = "http://10.0.2.2:8080/api/chat/stream"
private val client = OkHttpClient.Builder()
.readTimeout(0, TimeUnit.MILLISECONDS) // SSE 需要关闭读取超时
.build()
fun streamChat(message: String): Flow<String> = callbackFlow {
val json = """{"message": "$message"}"""
val request = Request.Builder()
.url(backendUrl)
.post(json.toRequestBody("application/json".toMediaType()))
.header("Accept", "text/event-stream")
.build()
val listener = object : EventSourceListener() {
override fun onEvent(eventSource: EventSource, id: String?, type: String?, data: String) {
// 收到后端推送的数据块
trySend(data)
}
override fun onFailure(eventSource: EventSource, t: Throwable?, response: Response?) {
Timber.e(t, "SSE Connection failed")
close(t) // 结束流
}
override fun onClosed(eventSource: EventSource) {
close() // 正常结束
}
}
val eventSource = EventSources.createFactory(client).newEventSource(request, listener)
awaitClose {
eventSource.cancel()
}
}
}