@@ -34,6 +34,12 @@ function toRecord(value: unknown): Record<string, unknown> | undefined {
3434 return value && typeof value === "object" ? ( value as Record < string , unknown > ) : undefined ;
3535}
3636
37+ function resolveStreamContentIndex ( record : Record < string , unknown > ) : number {
38+ return typeof record . contentIndex === "number" && Number . isInteger ( record . contentIndex )
39+ ? record . contentIndex
40+ : 0 ;
41+ }
42+
3743function resolveContextToolNames ( context : Parameters < StreamFn > [ 1 ] ) : Set < string > {
3844 const tools = ( context as { tools ?: unknown } ) . tools ;
3945 if ( ! Array . isArray ( tools ) ) {
@@ -323,8 +329,8 @@ function wrapPlainTextToolCallStream(
323329 void ( async ( ) => {
324330 const bufferedTextEvents : unknown [ ] = [ ] ;
325331 let bufferedText = "" ;
326- let flushedTextEvents = false ;
327- let replacementSupersedesFlushedText = false ;
332+ const flushedTextContentIndexes = new Set < number > ( ) ;
333+ let replacementClearContentIndex : number | undefined ;
328334 let ended = false ;
329335 const endStream = ( ) => {
330336 if ( ! ended ) {
@@ -334,18 +340,25 @@ function wrapPlainTextToolCallStream(
334340 } ;
335341 const flushBufferedTextEvents = ( ) => {
336342 const events = bufferedTextEvents . splice ( 0 ) ;
337- if ( events . length > 0 ) {
338- flushedTextEvents = true ;
339- }
340343 for ( const event of events ) {
344+ const record = toRecord ( event ) ;
345+ if (
346+ record &&
347+ ( record . type === "text_start" ||
348+ record . type === "text_delta" ||
349+ record . type === "text_end" )
350+ ) {
351+ flushedTextContentIndexes . add ( resolveStreamContentIndex ( record ) ) ;
352+ }
341353 stream . push ( event ) ;
342354 }
343355 bufferedText = "" ;
356+ replacementClearContentIndex = undefined ;
344357 } ;
345- const emitTextReplacementClear = ( message : Record < string , unknown > ) => {
358+ const emitTextReplacementClear = ( message : Record < string , unknown > , contentIndex : number ) => {
346359 stream . push ( {
347360 type : "text_delta" ,
348- contentIndex : 0 ,
361+ contentIndex,
349362 delta : "" ,
350363 replace : true ,
351364 partial : { ...message , content : [ ] } ,
@@ -359,11 +372,12 @@ function wrapPlainTextToolCallStream(
359372
360373 if ( type === "text_start" || type === "text_delta" || type === "text_end" ) {
361374 const replacesBufferedText = type === "text_delta" && record ?. replace === true ;
375+ const contentIndex = record ? resolveStreamContentIndex ( record ) : 0 ;
362376 if ( replacesBufferedText ) {
363377 bufferedTextEvents . splice ( 0 ) ;
364- if ( flushedTextEvents ) {
365- replacementSupersedesFlushedText = true ;
366- }
378+ replacementClearContentIndex = flushedTextContentIndexes . has ( contentIndex )
379+ ? contentIndex
380+ : undefined ;
367381 }
368382 bufferedTextEvents . push ( event ) ;
369383 if ( typeof record ?. delta === "string" ) {
@@ -387,8 +401,8 @@ function wrapPlainTextToolCallStream(
387401 if ( promotedMessage ) {
388402 bufferedTextEvents . splice ( 0 ) ;
389403 bufferedText = "" ;
390- if ( replacementSupersedesFlushedText ) {
391- emitTextReplacementClear ( promotedMessage ) ;
404+ if ( replacementClearContentIndex !== undefined ) {
405+ emitTextReplacementClear ( promotedMessage , replacementClearContentIndex ) ;
392406 }
393407 emitPromotedToolCallEvents ( stream , promotedMessage ) ;
394408 stream . push ( { ...record , reason : "toolUse" , message : promotedMessage } ) ;
0 commit comments