@@ -364,7 +364,11 @@ export function createLaneTextDeliverer(params: CreateLaneTextDelivererParams) {
|
364 | 364 | }; |
365 | 365 | |
366 | 366 | const candidateTexts = [stream.lastDeliveredText?.(), lane.lastPartialText]; |
367 | | -if (useFinalTextRecovery && remainingChunks.length === 0 && isPotentialTruncatedFinal(activeFullText)) { |
| 367 | +if ( |
| 368 | +useFinalTextRecovery && |
| 369 | +remainingChunks.length === 0 && |
| 370 | +isPotentialTruncatedFinal(activeFullText) |
| 371 | +) { |
368 | 372 | const resolvedFullCandidate = await params.resolveFinalTextCandidate?.({ |
369 | 373 | finalText: text, |
370 | 374 | laneName, |
@@ -379,7 +383,9 @@ export function createLaneTextDeliverer(params: CreateLaneTextDelivererParams) {
|
379 | 383 | } |
380 | 384 | |
381 | 385 | const retainedPreview = |
382 | | -useFinalTextRecovery && remainingChunks.length === 0 && isPotentialTruncatedFinal(activeFullText) |
| 386 | +useFinalTextRecovery && |
| 387 | +remainingChunks.length === 0 && |
| 388 | +isPotentialTruncatedFinal(activeFullText) |
383 | 389 | ? selectLongerFinalText({ |
384 | 390 | finalText: activeFullText, |
385 | 391 | candidateTexts, |
@@ -443,9 +449,20 @@ export function createLaneTextDeliverer(params: CreateLaneTextDelivererParams) {
|
443 | 449 | } else { |
444 | 450 | await params.flushDraftLane(lane); |
445 | 451 | } |
446 | | -const activeChunkIndexAfterStop = useFinalTextRecovery ? clampActiveChunkIndex() : activeChunkIndex; |
447 | | -const activeChunkAfterStop = chunks[activeChunkIndexAfterStop] ?? activeChunk; |
448 | | -const remainingChunksAfterStop = chunks.slice(activeChunkIndexAfterStop + 1); |
| 452 | +const activeChunkIndexAfterStop = useFinalTextRecovery |
| 453 | + ? clampActiveChunkIndex() |
| 454 | + : activeChunkIndex; |
| 455 | +const deliveredStreamTextAfterStop = stream.lastDeliveredText?.(); |
| 456 | +const retainedOriginalActiveChunkAfterStop = |
| 457 | +activeChunkIndexAfterStop > activeChunkIndex && |
| 458 | +deliveredStreamTextAfterStop === activeChunk.trimEnd(); |
| 459 | +// `activeChunkIndex` is advanced by retained preview callbacks. If callbacks |
| 460 | +// outrun the stream's delivered text, trust the delivered text and replay the gap. |
| 461 | +const effectiveActiveChunkIndexAfterStop = retainedOriginalActiveChunkAfterStop |
| 462 | + ? activeChunkIndex |
| 463 | + : activeChunkIndexAfterStop; |
| 464 | +const activeChunkAfterStop = chunks[effectiveActiveChunkIndexAfterStop] ?? activeChunk; |
| 465 | +const remainingChunksAfterStop = chunks.slice(effectiveActiveChunkIndexAfterStop + 1); |
449 | 466 | |
450 | 467 | const messageId = stream.messageId(); |
451 | 468 | if (typeof messageId !== "number") { |
@@ -460,16 +477,12 @@ export function createLaneTextDeliverer(params: CreateLaneTextDelivererParams) {
|
460 | 477 | return undefined; |
461 | 478 | } |
462 | 479 | |
463 | | -const deliveredStreamTextAfterStop = stream.lastDeliveredText?.(); |
464 | 480 | const activeChunkTextAfterStop = activeChunkAfterStop.trimEnd(); |
465 | | -const retainedActiveChunkAfterStop = |
466 | | -activeChunkIndexAfterStop !== activeChunkIndex && |
467 | | -deliveredStreamTextAfterStop === activeChunk.trimEnd(); |
468 | 481 | if ( |
469 | 482 | finalizePreview && |
470 | 483 | deliveredStreamTextAfterStop !== undefined && |
471 | 484 | deliveredStreamTextAfterStop !== activeChunkTextAfterStop && |
472 | | -!retainedActiveChunkAfterStop |
| 485 | +!retainedOriginalActiveChunkAfterStop |
473 | 486 | ) { |
474 | 487 | if ( |
475 | 488 | useFinalTextRecovery && |
|