@@ -1618,11 +1618,65 @@ describe("Cline", () => {
16181618 // Start the task
16191619 await ( task as any ) . startTask ( "Compare @/src/index.ts with @/src/utils.ts" )
16201620
1621- // Verify synthetic assistant message has multiple read_file calls
1621+ // Verify synthetic assistant message has a single read_file call with multiple files
16221622 expect ( apiMessages [ 1 ] . role ) . toBe ( "assistant" )
16231623 expect ( apiMessages [ 1 ] . content [ 0 ] . text ) . toContain ( "<path>/src/index.ts</path>" )
16241624 expect ( apiMessages [ 1 ] . content [ 0 ] . text ) . toContain ( "<path>/src/utils.ts</path>" )
1625- expect ( apiMessages [ 1 ] . content [ 0 ] . text ) . toMatch ( / r e a d _ f i l e .* r e a d _ f i l e / s) // Multiple read_file blocks
1625+ // Should have exactly one read_file block containing both files
1626+ const readFileMatches = apiMessages [ 1 ] . content [ 0 ] . text . match ( / < r e a d _ f i l e > / g)
1627+ expect ( readFileMatches ) . toHaveLength ( 1 )
1628+ } )
1629+
1630+ it ( "should batch files when more than 5 files are mentioned" , async ( ) => {
1631+ const task = new Task ( {
1632+ provider : mockProvider ,
1633+ apiConfiguration : mockApiConfig ,
1634+ task : "Analyze multiple files" ,
1635+ startTask : false ,
1636+ } )
1637+
1638+ // Mock the API conversation history to track messages
1639+ const apiMessages : any [ ] = [ ]
1640+ vi . spyOn ( task as any , "addToApiConversationHistory" ) . mockImplementation ( async ( message ) => {
1641+ apiMessages . push ( message )
1642+ } )
1643+
1644+ // Mock extractFileMentions to return 7 file mentions (more than 5)
1645+ const fileMentions = Array . from ( { length : 7 } , ( _ , i ) => ( {
1646+ mention : `@file${ i + 1 } .ts` ,
1647+ path : `file${ i + 1 } .ts` ,
1648+ } ) )
1649+ vi . mocked ( extractFileMentions ) . mockReturnValue ( fileMentions )
1650+ vi . mocked ( hasFileMentions ) . mockReturnValue ( true )
1651+
1652+ // Mock processUserContentMentions
1653+ vi . mocked ( processUserContentMentions ) . mockResolvedValue ( [
1654+ {
1655+ type : "text" ,
1656+ text : "Analyze multiple files with content" ,
1657+ } ,
1658+ ] )
1659+
1660+ // Start the task
1661+ await ( task as any ) . startTask ( "Analyze multiple files" )
1662+
1663+ // Verify synthetic assistant message has two read_file calls (5 files + 2 files)
1664+ expect ( apiMessages [ 1 ] . role ) . toBe ( "assistant" )
1665+ const assistantText = apiMessages [ 1 ] . content [ 0 ] . text
1666+
1667+ // Should have exactly two read_file blocks
1668+ const readFileMatches = assistantText . match ( / < r e a d _ f i l e > / g)
1669+ expect ( readFileMatches ) . toHaveLength ( 2 )
1670+
1671+ // First batch should have 5 files
1672+ const firstBatch = assistantText . match ( / < r e a d _ f i l e > [ \s \S ] * ?< \/ r e a d _ f i l e > / ) [ 0 ]
1673+ const firstBatchFiles = firstBatch . match ( / < p a t h > f i l e \d + \. t s < \/ p a t h > / g)
1674+ expect ( firstBatchFiles ) . toHaveLength ( 5 )
1675+
1676+ // Second batch should have 2 files
1677+ const secondBatch = assistantText . match ( / < r e a d _ f i l e > [ \s \S ] * ?< \/ r e a d _ f i l e > / g) [ 1 ]
1678+ const secondBatchFiles = secondBatch . match ( / < p a t h > f i l e \d + \. t s < \/ p a t h > / g)
1679+ expect ( secondBatchFiles ) . toHaveLength ( 2 )
16261680 } )
16271681
16281682 it ( "should preserve task history without embedded file content" , async ( ) => {
0 commit comments