@@ -262,3 +262,106 @@ describe("ProviderTransform.message - DeepSeek reasoning content", () => {
262262 expect ( result [ 0 ] . providerOptions ?. openaiCompatible ?. reasoning_content ) . toBeUndefined ( )
263263 } )
264264} )
265+
266+ describe ( "ProviderTransform.message - empty image handling" , ( ) => {
267+ const mockModel = {
268+ id : "anthropic/claude-3-5-sonnet" ,
269+ providerID : "anthropic" ,
270+ api : {
271+ id : "claude-3-5-sonnet-20241022" ,
272+ url : "https://api.anthropic.com" ,
273+ npm : "@ai-sdk/anthropic" ,
274+ } ,
275+ name : "Claude 3.5 Sonnet" ,
276+ capabilities : {
277+ temperature : true ,
278+ reasoning : false ,
279+ attachment : true ,
280+ toolcall : true ,
281+ input : { text : true , audio : false , image : true , video : false , pdf : true } ,
282+ output : { text : true , audio : false , image : false , video : false , pdf : false } ,
283+ interleaved : false ,
284+ } ,
285+ cost : {
286+ input : 0.003 ,
287+ output : 0.015 ,
288+ cache : { read : 0.0003 , write : 0.00375 } ,
289+ } ,
290+ limit : {
291+ context : 200000 ,
292+ output : 8192 ,
293+ } ,
294+ status : "active" ,
295+ options : { } ,
296+ headers : { } ,
297+ } as any
298+
299+ test ( "should replace empty base64 image with error text" , ( ) => {
300+ const msgs = [
301+ {
302+ role : "user" ,
303+ content : [
304+ { type : "text" , text : "What is in this image?" } ,
305+ { type : "image" , image : "data:image/png;base64," } ,
306+ ] ,
307+ } ,
308+ ] as any [ ]
309+
310+ const result = ProviderTransform . message ( msgs , mockModel )
311+
312+ expect ( result ) . toHaveLength ( 1 )
313+ expect ( result [ 0 ] . content ) . toHaveLength ( 2 )
314+ expect ( result [ 0 ] . content [ 0 ] ) . toEqual ( { type : "text" , text : "What is in this image?" } )
315+ expect ( result [ 0 ] . content [ 1 ] ) . toEqual ( {
316+ type : "text" ,
317+ text : "ERROR: Image file is empty or corrupted. Please provide a valid image." ,
318+ } )
319+ } )
320+
321+ test ( "should keep valid base64 images unchanged" , ( ) => {
322+ const validBase64 =
323+ "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
324+ const msgs = [
325+ {
326+ role : "user" ,
327+ content : [
328+ { type : "text" , text : "What is in this image?" } ,
329+ { type : "image" , image : `data:image/png;base64,${ validBase64 } ` } ,
330+ ] ,
331+ } ,
332+ ] as any [ ]
333+
334+ const result = ProviderTransform . message ( msgs , mockModel )
335+
336+ expect ( result ) . toHaveLength ( 1 )
337+ expect ( result [ 0 ] . content ) . toHaveLength ( 2 )
338+ expect ( result [ 0 ] . content [ 0 ] ) . toEqual ( { type : "text" , text : "What is in this image?" } )
339+ expect ( result [ 0 ] . content [ 1 ] ) . toEqual ( { type : "image" , image : `data:image/png;base64,${ validBase64 } ` } )
340+ } )
341+
342+ test ( "should handle mixed valid and empty images" , ( ) => {
343+ const validBase64 =
344+ "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
345+ const msgs = [
346+ {
347+ role : "user" ,
348+ content : [
349+ { type : "text" , text : "Compare these images" } ,
350+ { type : "image" , image : `data:image/png;base64,${ validBase64 } ` } ,
351+ { type : "image" , image : "data:image/jpeg;base64," } ,
352+ ] ,
353+ } ,
354+ ] as any [ ]
355+
356+ const result = ProviderTransform . message ( msgs , mockModel )
357+
358+ expect ( result ) . toHaveLength ( 1 )
359+ expect ( result [ 0 ] . content ) . toHaveLength ( 3 )
360+ expect ( result [ 0 ] . content [ 0 ] ) . toEqual ( { type : "text" , text : "Compare these images" } )
361+ expect ( result [ 0 ] . content [ 1 ] ) . toEqual ( { type : "image" , image : `data:image/png;base64,${ validBase64 } ` } )
362+ expect ( result [ 0 ] . content [ 2 ] ) . toEqual ( {
363+ type : "text" ,
364+ text : "ERROR: Image file is empty or corrupted. Please provide a valid image." ,
365+ } )
366+ } )
367+ } )
0 commit comments