@@ -1219,6 +1219,110 @@ describe("ProviderTransform.message - anthropic empty content filtering", () =>
12191219 expect ( result [ 0 ] . content ) . toBe ( "" )
12201220 expect ( result [ 1 ] . content ) . toHaveLength ( 1 )
12211221 } )
1222+
1223+ test ( "splits anthropic assistant messages when text trails tool calls" , ( ) => {
1224+ const msgs = [
1225+ {
1226+ role : "user" ,
1227+ content : [ { type : "text" , text : "Check my home directory for PDFs" } ] ,
1228+ } ,
1229+ {
1230+ role : "assistant" ,
1231+ content : [
1232+ { type : "tool-call" , toolCallId : "toolu_1" , toolName : "read" , input : { filePath : "/root" } } ,
1233+ { type : "tool-call" , toolCallId : "toolu_2" , toolName : "glob" , input : { pattern : "**/*.pdf" } } ,
1234+ { type : "text" , text : "I checked your home directory and looked for PDF files." } ,
1235+ ] ,
1236+ } ,
1237+ {
1238+ role : "tool" ,
1239+ content : [
1240+ { type : "tool-result" , toolCallId : "toolu_1" , toolName : "read" , output : { type : "text" , value : "ok" } } ,
1241+ {
1242+ type : "tool-result" ,
1243+ toolCallId : "toolu_2" ,
1244+ toolName : "glob" ,
1245+ output : { type : "text" , value : "No files found" } ,
1246+ } ,
1247+ ] ,
1248+ } ,
1249+ ] as any [ ]
1250+
1251+ const result = ProviderTransform . message ( msgs , anthropicModel , { } ) as any [ ]
1252+
1253+ expect ( result ) . toHaveLength ( 4 )
1254+ expect ( result [ 1 ] ) . toMatchObject ( {
1255+ role : "assistant" ,
1256+ content : [ { type : "text" , text : "I checked your home directory and looked for PDF files." } ] ,
1257+ } )
1258+ expect ( result [ 2 ] ) . toMatchObject ( {
1259+ role : "assistant" ,
1260+ content : [
1261+ { type : "tool-call" , toolCallId : "toolu_1" , toolName : "read" , input : { filePath : "/root" } } ,
1262+ { type : "tool-call" , toolCallId : "toolu_2" , toolName : "glob" , input : { pattern : "**/*.pdf" } } ,
1263+ ] ,
1264+ } )
1265+ } )
1266+
1267+ test ( "leaves valid anthropic assistant tool ordering unchanged" , ( ) => {
1268+ const msgs = [
1269+ {
1270+ role : "assistant" ,
1271+ content : [
1272+ { type : "text" , text : "I checked your home directory and looked for PDF files." } ,
1273+ { type : "tool-call" , toolCallId : "toolu_1" , toolName : "read" , input : { filePath : "/root" } } ,
1274+ { type : "tool-call" , toolCallId : "toolu_2" , toolName : "glob" , input : { pattern : "**/*.pdf" } } ,
1275+ ] ,
1276+ } ,
1277+ ] as any [ ]
1278+
1279+ const result = ProviderTransform . message ( msgs , anthropicModel , { } ) as any [ ]
1280+
1281+ expect ( result ) . toHaveLength ( 1 )
1282+ expect ( result [ 0 ] . content ) . toMatchObject ( [
1283+ { type : "text" , text : "I checked your home directory and looked for PDF files." } ,
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+ ] )
1287+ } )
1288+
1289+ test ( "splits vertex anthropic assistant messages when text trails tool calls" , ( ) => {
1290+ const model = {
1291+ ...anthropicModel ,
1292+ providerID : "google-vertex-anthropic" ,
1293+ api : {
1294+ id : "claude-sonnet-4@20250514" ,
1295+ url : "https://us-central1-aiplatform.googleapis.com" ,
1296+ npm : "@ai-sdk/google-vertex/anthropic" ,
1297+ } ,
1298+ }
1299+
1300+ const msgs = [
1301+ {
1302+ role : "assistant" ,
1303+ content : [
1304+ { type : "tool-call" , toolCallId : "toolu_1" , toolName : "read" , input : { filePath : "/root" } } ,
1305+ { type : "tool-call" , toolCallId : "toolu_2" , toolName : "glob" , input : { pattern : "**/*.pdf" } } ,
1306+ { type : "text" , text : "I checked your home directory and looked for PDF files." } ,
1307+ ] ,
1308+ } ,
1309+ ] as any [ ]
1310+
1311+ const result = ProviderTransform . message ( msgs , model , { } ) as any [ ]
1312+
1313+ expect ( result ) . toHaveLength ( 2 )
1314+ expect ( result [ 0 ] ) . toMatchObject ( {
1315+ role : "assistant" ,
1316+ content : [ { type : "text" , text : "I checked your home directory and looked for PDF files." } ] ,
1317+ } )
1318+ expect ( result [ 1 ] ) . toMatchObject ( {
1319+ role : "assistant" ,
1320+ content : [
1321+ { type : "tool-call" , toolCallId : "toolu_1" , toolName : "read" , input : { filePath : "/root" } } ,
1322+ { type : "tool-call" , toolCallId : "toolu_2" , toolName : "glob" , input : { pattern : "**/*.pdf" } } ,
1323+ ] ,
1324+ } )
1325+ } )
12221326} )
12231327
12241328describe ( "ProviderTransform.message - strip openai metadata when store=false" , ( ) => {
0 commit comments