fix(ui): prevent streaming text flicker and first-chunk loss

This commit is contained in:
Bohdan Triapitsyn
2026-05-03 02:32:05 +03:00
parent 4ad5d2f4b7
commit f810a3316c
2 changed files with 13 additions and 9 deletions
+7 -3
View File
@@ -314,9 +314,13 @@ export function createEventPipeline(input: EventPipelineInput) {
} else {
d.queue[i] = normalizedPayload
if (normalizedPayload.type === "message.part.updated") {
const part = (normalizedPayload.properties as { part: { messageID: string; id: string } }).part
d.staleDeltas.add(deltaKey(part.messageID, part.id, "text"))
d.staleDeltas.add(deltaKey(part.messageID, part.id, "output"))
const part = (normalizedPayload.properties as { part: Record<string, unknown> & { messageID: string; id: string } }).part
for (const field of ["text", "output"] as const) {
const value = part[field]
if (typeof value === "string" && value.length > 0) {
d.staleDeltas.add(deltaKey(part.messageID, part.id, field))
}
}
}
}
syncDebug.pipeline.coalesced(normalizedPayload.type, k)
+6 -6
View File
@@ -1227,12 +1227,12 @@ function handleEvent(
const messageID = getMessageIdFromPayload(payload) ?? undefined
syncDebug.dispatch.eventNoChange(payload.type, sessionID, messageID)
// Parts-gap recovery: if a part event was dropped because the parts array
// was missing (message not yet inserted or parts lost), trigger a repair
// fetch for the session.
if (sessionID && messageID && (
payload.type === "message.part.delta" || payload.type === "message.part.updated"
)) {
// Parts-gap recovery: if a delta event was dropped because the parts array
// was missing or the partID was not found, trigger a repair fetch for the
// session. message.part.updated never needs repair — it only returns false
// for intentionally skipped types (step-start, step-finish, patch) or when
// preserving an existing finished tool part, neither of which indicates missing data.
if (sessionID && messageID && payload.type === "message.part.delta") {
enqueuePartsRepair(resolvedDirectory, sessionID, childStores)
}
}