@@ -544,19 +544,33 @@ export function getMessagesSinceLastSummary(messages: ApiMessage[]): ApiMessage[
544544 * @returns The filtered history that should be sent to the API
545545 */
546546export function getEffectiveApiHistory ( messages : ApiMessage [ ] ) : ApiMessage [ ] {
547+ const effectiveHistoryWithIndices = getEffectiveApiHistoryWithIndices ( messages )
548+ return effectiveHistoryWithIndices . map ( ( { message } ) => message )
549+ }
550+
551+ export function getEffectiveApiHistoryIndices ( messages : ApiMessage [ ] ) : number [ ] {
552+ const effectiveHistoryWithIndices = getEffectiveApiHistoryWithIndices ( messages )
553+ return effectiveHistoryWithIndices . map ( ( { index } ) => index )
554+ }
555+
556+ function getEffectiveApiHistoryWithIndices ( messages : ApiMessage [ ] ) : Array < { message : ApiMessage ; index : number } > {
547557 // Find the most recent summary message
548558 const lastSummary = findLast ( messages , ( msg ) => msg . isSummary === true )
549559
550560 if ( lastSummary ) {
551561 // Fresh start model: return only messages from the summary onwards
552562 const summaryIndex = messages . indexOf ( lastSummary )
553- let messagesFromSummary = messages . slice ( summaryIndex )
563+ let messagesFromSummary = messages . slice ( summaryIndex ) . map ( ( message , offset ) => ( {
564+ message,
565+ index : summaryIndex + offset ,
566+ } ) )
554567
555568 // Collect all tool_use IDs from assistant messages in the result
556569 // This is needed to filter out orphan tool_result blocks that reference
557570 // tool_use IDs from messages that were condensed away
558571 const toolUseIds = new Set < string > ( )
559- for ( const msg of messagesFromSummary ) {
572+ for ( const { message } of messagesFromSummary ) {
573+ const msg = message
560574 if ( msg . role === "assistant" && Array . isArray ( msg . content ) ) {
561575 for ( const block of msg . content ) {
562576 if ( block . type === "tool_use" && ( block as Anthropic . Messages . ToolUseBlockParam ) . id ) {
@@ -568,7 +582,8 @@ export function getEffectiveApiHistory(messages: ApiMessage[]): ApiMessage[] {
568582
569583 // Filter out orphan tool_result blocks from user messages
570584 messagesFromSummary = messagesFromSummary
571- . map ( ( msg ) => {
585+ . map ( ( { message, index } ) => {
586+ const msg = message
572587 if ( msg . role === "user" && Array . isArray ( msg . content ) ) {
573588 const filteredContent = msg . content . filter ( ( block ) => {
574589 if ( block . type === "tool_result" ) {
@@ -582,22 +597,24 @@ export function getEffectiveApiHistory(messages: ApiMessage[]): ApiMessage[] {
582597 }
583598 // If some content was filtered, return updated message
584599 if ( filteredContent . length !== msg . content . length ) {
585- return { ...msg , content : filteredContent }
600+ return { message : { ...msg , content : filteredContent } , index }
586601 }
587602 }
588- return msg
603+ return { message : msg , index }
589604 } )
590- . filter ( ( msg ) : msg is ApiMessage => msg !== null )
605+ . filter ( ( entry ) : entry is { message : ApiMessage ; index : number } => entry !== null )
591606
592607 // Still need to filter out any truncated messages within this range
593608 const existingTruncationIds = new Set < string > ( )
594- for ( const msg of messagesFromSummary ) {
609+ for ( const { message } of messagesFromSummary ) {
610+ const msg = message
595611 if ( msg . isTruncationMarker && msg . truncationId ) {
596612 existingTruncationIds . add ( msg . truncationId )
597613 }
598614 }
599615
600- return messagesFromSummary . filter ( ( msg ) => {
616+ return messagesFromSummary . filter ( ( { message } ) => {
617+ const msg = message
601618 // Filter out truncated messages if their truncation marker exists
602619 if ( msg . truncationParent && existingTruncationIds . has ( msg . truncationParent ) ) {
603620 return false
@@ -626,17 +643,20 @@ export function getEffectiveApiHistory(messages: ApiMessage[]): ApiMessage[] {
626643 // Filter out messages whose condenseParent points to an existing summary
627644 // or whose truncationParent points to an existing truncation marker.
628645 // Messages with orphaned parents (summary/marker was deleted) are included.
629- return messages . filter ( ( msg ) => {
630- // Filter out condensed messages if their summary exists
631- if ( msg . condenseParent && existingSummaryIds . has ( msg . condenseParent ) ) {
632- return false
633- }
634- // Filter out truncated messages if their truncation marker exists
635- if ( msg . truncationParent && existingTruncationIds . has ( msg . truncationParent ) ) {
636- return false
637- }
638- return true
639- } )
646+ return messages
647+ . map ( ( message , index ) => ( { message, index } ) )
648+ . filter ( ( { message } ) => {
649+ const msg = message
650+ // Filter out condensed messages if their summary exists
651+ if ( msg . condenseParent && existingSummaryIds . has ( msg . condenseParent ) ) {
652+ return false
653+ }
654+ // Filter out truncated messages if their truncation marker exists
655+ if ( msg . truncationParent && existingTruncationIds . has ( msg . truncationParent ) ) {
656+ return false
657+ }
658+ return true
659+ } )
640660}
641661
642662/**
0 commit comments