fix: preserve partial content when synthesis stream drops mid-response
When the final synthesis stream dropped mid-way (connection error, timeout), the onError handler discarded the streaming message entirely and showed only the error. If the model had already streamed 90% of a good answer, the user lost all of it. Now: if the streaming message has partial content, it is preserved and finalized with an interrupted note appended. The error is still shown as a separate message so the user knows what happened. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1571,13 +1571,35 @@ export function ChatWorkspace() {
|
||||
}
|
||||
},
|
||||
onError: (err: Error) => {
|
||||
// Clean up streaming placeholder if the stream errored
|
||||
// Clean up streaming placeholder if the stream errored.
|
||||
// If the streaming message already has partial content (model streamed
|
||||
// most of the answer before the connection dropped), preserve it and
|
||||
// finalize it instead of discarding — losing a 90% complete response
|
||||
// is worse than showing it with an error note appended.
|
||||
streamCancelRef.current = null
|
||||
const streamMsgId = streamingMsgIdRef.current
|
||||
streamingMsgIdRef.current = null
|
||||
clearBridgeDraft(sessionId)
|
||||
if (streamMsgId) {
|
||||
setMessages(prev => prev.filter(m => m.id !== streamMsgId))
|
||||
let preserved = false
|
||||
setMessages(prev => {
|
||||
const streamMsg = prev.find(m => m.id === streamMsgId)
|
||||
if (streamMsg?.content && streamMsg.content.trim().length > 0) {
|
||||
// Preserve partial content — finalize the streaming message
|
||||
preserved = true
|
||||
return prev.map(m =>
|
||||
m.id === streamMsgId
|
||||
? { ...m, isStreaming: false, content: m.content + '\n\n---\n*Response interrupted — connection dropped before completion.*' }
|
||||
: m,
|
||||
)
|
||||
}
|
||||
// No useful content — remove the empty placeholder
|
||||
return prev.filter(m => m.id !== streamMsgId)
|
||||
})
|
||||
if (preserved) {
|
||||
if (err.name === 'AbortError') return
|
||||
// Still show the error as a separate message so the user knows what happened
|
||||
}
|
||||
}
|
||||
if (err.name === 'AbortError') return
|
||||
const isTimeout = err.name === 'TimeoutError'
|
||||
|
||||
Reference in New Issue
Block a user