@@ -1271,6 +1271,110 @@ describe("ProviderTransform.message - anthropic empty content filtering", () =>
12711271 expect ( result [ 0 ] . content ) . toBe ( "" )
12721272 expect ( result [ 1 ] . content ) . toHaveLength ( 1 )
12731273 } )
1274+
1275+ test ( "splits anthropic assistant messages when text trails tool calls" , ( ) => {
1276+ const msgs = [
1277+ {
1278+ role : "user" ,
1279+ content : [ { type : "text" , text : "Check my home directory for PDFs" } ] ,
1280+ } ,
1281+ {
1282+ role : "assistant" ,
1283+ content : [
1284+ { type : "tool-call" , toolCallId : "toolu_1" , toolName : "read" , input : { filePath : "/root" } } ,
1285+ { type : "tool-call" , toolCallId : "toolu_2" , toolName : "glob" , input : { pattern : "**/*.pdf" } } ,
1286+ { type : "text" , text : "I checked your home directory and looked for PDF files." } ,
1287+ ] ,
1288+ } ,
1289+ {
1290+ role : "tool" ,
1291+ content : [
1292+ { type : "tool-result" , toolCallId : "toolu_1" , toolName : "read" , output : { type : "text" , value : "ok" } } ,
1293+ {
1294+ type : "tool-result" ,
1295+ toolCallId : "toolu_2" ,
1296+ toolName : "glob" ,
1297+ output : { type : "text" , value : "No files found" } ,
1298+ } ,
1299+ ] ,
1300+ } ,
1301+ ] as any [ ]
1302+
1303+ const result = ProviderTransform . message ( msgs , anthropicModel , { } ) as any [ ]
1304+
1305+ expect ( result ) . toHaveLength ( 4 )
1306+ expect ( result [ 1 ] ) . toMatchObject ( {
1307+ role : "assistant" ,
1308+ content : [ { type : "text" , text : "I checked your home directory and looked for PDF files." } ] ,
1309+ } )
1310+ expect ( result [ 2 ] ) . toMatchObject ( {
1311+ role : "assistant" ,
1312+ content : [
1313+ { type : "tool-call" , toolCallId : "toolu_1" , toolName : "read" , input : { filePath : "/root" } } ,
1314+ { type : "tool-call" , toolCallId : "toolu_2" , toolName : "glob" , input : { pattern : "**/*.pdf" } } ,
1315+ ] ,
1316+ } )
1317+ } )
1318+
1319+ test ( "leaves valid anthropic assistant tool ordering unchanged" , ( ) => {
1320+ const msgs = [
1321+ {
1322+ role : "assistant" ,
1323+ content : [
1324+ { type : "text" , text : "I checked your home directory and looked for PDF files." } ,
1325+ { type : "tool-call" , toolCallId : "toolu_1" , toolName : "read" , input : { filePath : "/root" } } ,
1326+ { type : "tool-call" , toolCallId : "toolu_2" , toolName : "glob" , input : { pattern : "**/*.pdf" } } ,
1327+ ] ,
1328+ } ,
1329+ ] as any [ ]
1330+
1331+ const result = ProviderTransform . message ( msgs , anthropicModel , { } ) as any [ ]
1332+
1333+ expect ( result ) . toHaveLength ( 1 )
1334+ expect ( result [ 0 ] . content ) . toMatchObject ( [
1335+ { type : "text" , text : "I checked your home directory and looked for PDF files." } ,
1336+ { type : "tool-call" , toolCallId : "toolu_1" , toolName : "read" , input : { filePath : "/root" } } ,
1337+ { type : "tool-call" , toolCallId : "toolu_2" , toolName : "glob" , input : { pattern : "**/*.pdf" } } ,
1338+ ] )
1339+ } )
1340+
1341+ test ( "splits vertex anthropic assistant messages when text trails tool calls" , ( ) => {
1342+ const model = {
1343+ ...anthropicModel ,
1344+ providerID : "google-vertex-anthropic" ,
1345+ api : {
1346+ id : "claude-sonnet-4@20250514" ,
1347+ url : "https://us-central1-aiplatform.googleapis.com" ,
1348+ npm : "@ai-sdk/google-vertex/anthropic" ,
1349+ } ,
1350+ }
1351+
1352+ const msgs = [
1353+ {
1354+ role : "assistant" ,
1355+ content : [
1356+ { type : "tool-call" , toolCallId : "toolu_1" , toolName : "read" , input : { filePath : "/root" } } ,
1357+ { type : "tool-call" , toolCallId : "toolu_2" , toolName : "glob" , input : { pattern : "**/*.pdf" } } ,
1358+ { type : "text" , text : "I checked your home directory and looked for PDF files." } ,
1359+ ] ,
1360+ } ,
1361+ ] as any [ ]
1362+
1363+ const result = ProviderTransform . message ( msgs , model , { } ) as any [ ]
1364+
1365+ expect ( result ) . toHaveLength ( 2 )
1366+ expect ( result [ 0 ] ) . toMatchObject ( {
1367+ role : "assistant" ,
1368+ content : [ { type : "text" , text : "I checked your home directory and looked for PDF files." } ] ,
1369+ } )
1370+ expect ( result [ 1 ] ) . toMatchObject ( {
1371+ role : "assistant" ,
1372+ content : [
1373+ { type : "tool-call" , toolCallId : "toolu_1" , toolName : "read" , input : { filePath : "/root" } } ,
1374+ { type : "tool-call" , toolCallId : "toolu_2" , toolName : "glob" , input : { pattern : "**/*.pdf" } } ,
1375+ ] ,
1376+ } )
1377+ } )
12741378} )
12751379
12761380describe ( "ProviderTransform.message - strip openai metadata when store=false" , ( ) => {
0 commit comments