Skip to content

Commit d8a25f0

Browse files
Jinyu XuJinyu Xu
authored andcommitted
fix: stop mobile stream after done event
1 parent f451118 commit d8a25f0

2 files changed

Lines changed: 17 additions & 3 deletions

File tree

src/api/index.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,7 @@ export const aiChatApi = {
753753
const reader = response.body.getReader()
754754
const decoder = new TextDecoder('utf-8')
755755
let buffer = ''
756+
let streamComplete = false
756757
const handlePart = async (part) => {
757758
const lines = String(part || '').split(/\r?\n/)
758759
let event = 'message'
@@ -767,19 +768,31 @@ export const aiChatApi = {
767768
data = JSON.parse(data)
768769
} catch (_) {}
769770
if (typeof onEvent === 'function') await onEvent(event, data)
771+
return event
770772
}
771773

772-
while (true) {
774+
while (!streamComplete) {
773775
const { value, done } = await reader.read()
774776
if (done) break
775777
buffer += decoder.decode(value, { stream: true })
776778
const parts = buffer.split(/\r?\n\r?\n/)
777779
buffer = parts.pop() || ''
778780
for (const part of parts) {
779-
await handlePart(part)
781+
if (await handlePart(part) === 'done') {
782+
streamComplete = true
783+
break
784+
}
785+
}
786+
if (streamComplete) {
787+
try {
788+
await reader.cancel()
789+
} catch (_) {}
780790
}
781791
}
782-
if (buffer.trim()) await handlePart(buffer)
792+
if (!streamComplete && buffer.trim()) {
793+
streamComplete = await handlePart(buffer) === 'done'
794+
}
795+
return { completed: streamComplete }
783796
},
784797
saveLocalMessage: (payload) => http.post('/api/ai/chat/message/local', payload),
785798
getSessions: async (params = {}) => {

tests/unit/mobile-usage-boundary.test.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ test('AI composer stays at the bottom and uses a text send action', () => {
205205
assert.match(aiHub, /await this\.sendMessageStream\(payload, pendingMsg\)[\s\S]*aiChatApi\.sendMessage\(\{/)
206206
assert.match(api, /sendMessage: \(payload\) => http\.post\('\/api\/ai\/chat\/message', payload, \{ timeout: 600000 \}\)/)
207207
assert.match(api, /streamMessage:[\s\S]*\/api\/ai\/chat\/message\/stream/)
208+
assert.match(api, /if \(await handlePart\(part\) === 'done'\)[\s\S]*await reader\.cancel\(\)/)
208209
})
209210

210211
test('signal chart supports mobile history navigation and candle inspection', () => {

0 commit comments

Comments
 (0)