@@ -388,4 +388,180 @@ describe("file_read tool", () => {
388388      expect ( result . content ) . toContain ( "content in subdir" ) ; 
389389    } 
390390  } ) ; 
391+ 
392+   it ( "should read image files and return base64 content with mime type" ,  async  ( )  =>  { 
393+     // Setup - create a simple 1x1 PNG image (smallest valid PNG) 
394+     const  pngBuffer  =  Buffer . from ( [ 
395+       0x89 , 
396+       0x50 , 
397+       0x4e , 
398+       0x47 , 
399+       0x0d , 
400+       0x0a , 
401+       0x1a , 
402+       0x0a ,  // PNG signature 
403+       0x00 , 
404+       0x00 , 
405+       0x00 , 
406+       0x0d , 
407+       0x49 , 
408+       0x48 , 
409+       0x44 , 
410+       0x52 ,  // IHDR chunk 
411+       0x00 , 
412+       0x00 , 
413+       0x00 , 
414+       0x01 , 
415+       0x00 , 
416+       0x00 , 
417+       0x00 , 
418+       0x01 ,  // 1x1 dimensions 
419+       0x08 , 
420+       0x06 , 
421+       0x00 , 
422+       0x00 , 
423+       0x00 , 
424+       0x1f , 
425+       0x15 , 
426+       0xc4 , 
427+       0x89 , 
428+       0x00 , 
429+       0x00 , 
430+       0x00 , 
431+       0x0a , 
432+       0x49 , 
433+       0x44 , 
434+       0x41 , 
435+       0x54 , 
436+       0x78 , 
437+       0x9c , 
438+       0x63 , 
439+       0x00 , 
440+       0x01 , 
441+       0x00 , 
442+       0x00 , 
443+       0x05 , 
444+       0x00 , 
445+       0x01 , 
446+       0x0d , 
447+       0x0a , 
448+       0x2d , 
449+       0xb4 , 
450+       0x00 , 
451+       0x00 , 
452+       0x00 , 
453+       0x00 , 
454+       0x49 , 
455+       0x45 , 
456+       0x4e , 
457+       0x44 , 
458+       0xae , 
459+       0x42 , 
460+       0x60 , 
461+       0x82 , 
462+     ] ) ; 
463+     const  imagePath  =  path . join ( testDir ,  "test.png" ) ; 
464+     await  fs . writeFile ( imagePath ,  pngBuffer ) ; 
465+ 
466+     using testEnv  =  createTestFileReadTool ( {  cwd : testDir  } ) ; 
467+     const  tool  =  testEnv . tool ; 
468+     const  args : FileReadToolArgs  =  { 
469+       filePath : imagePath , 
470+     } ; 
471+ 
472+     // Execute 
473+     const  result  =  ( await  tool . execute ! ( args ,  mockToolCallOptions ) )  as  FileReadToolResult ; 
474+ 
475+     // Assert 
476+     expect ( result . success ) . toBe ( true ) ; 
477+     if  ( result . success )  { 
478+       expect ( result . mime_type ) . toBe ( "image/png" ) ; 
479+       expect ( result . lines_read ) . toBe ( 0 ) ;  // Images don't have lines 
480+       expect ( result . content ) . toBe ( pngBuffer . toString ( "base64" ) ) ; 
481+       expect ( result . file_size ) . toBe ( pngBuffer . length ) ; 
482+     } 
483+   } ) ; 
484+ 
485+   it ( "should return media content for images via toModelOutput" ,  async  ( )  =>  { 
486+     // Setup - create a simple image 
487+     const  jpegBuffer  =  Buffer . from ( [ 
488+       0xff , 
489+       0xd8 , 
490+       0xff , 
491+       0xe0 , 
492+       0x00 , 
493+       0x10 , 
494+       0x4a , 
495+       0x46 ,  // JPEG header 
496+       0x49 , 
497+       0x46 , 
498+       0x00 , 
499+       0x01 , 
500+       0x01 , 
501+       0x00 , 
502+       0x00 , 
503+       0x01 , 
504+       0x00 , 
505+       0x01 , 
506+       0x00 , 
507+       0x00 , 
508+       0xff , 
509+       0xd9 ,  // End of image 
510+     ] ) ; 
511+     const  imagePath  =  path . join ( testDir ,  "test.jpg" ) ; 
512+     await  fs . writeFile ( imagePath ,  jpegBuffer ) ; 
513+ 
514+     using testEnv  =  createTestFileReadTool ( {  cwd : testDir  } ) ; 
515+     const  tool  =  testEnv . tool ; 
516+     const  args : FileReadToolArgs  =  { 
517+       filePath : imagePath , 
518+     } ; 
519+ 
520+     // Execute 
521+     const  result  =  ( await  tool . execute ! ( args ,  mockToolCallOptions ) )  as  FileReadToolResult ; 
522+ 
523+     // Assert execute result 
524+     expect ( result . success ) . toBe ( true ) ; 
525+     if  ( result . success )  { 
526+       expect ( result . mime_type ) . toBe ( "image/jpeg" ) ; 
527+ 
528+       // Test toModelOutput transformation 
529+       const  modelOutput  =  tool . toModelOutput ! ( result ) ; 
530+       expect ( modelOutput . type ) . toBe ( "content" ) ; 
531+       if  ( modelOutput . type  ===  "content" )  { 
532+         expect ( modelOutput . value ) . toHaveLength ( 1 ) ; 
533+         expect ( modelOutput . value [ 0 ] . type ) . toBe ( "media" ) ; 
534+         if  ( modelOutput . value [ 0 ] . type  ===  "media" )  { 
535+           expect ( modelOutput . value [ 0 ] . mediaType ) . toBe ( "image/jpeg" ) ; 
536+           expect ( modelOutput . value [ 0 ] . data ) . toBe ( jpegBuffer . toString ( "base64" ) ) ; 
537+         } 
538+       } 
539+     } 
540+   } ) ; 
541+ 
542+   it ( "should return json for text files via toModelOutput" ,  async  ( )  =>  { 
543+     // Setup 
544+     const  content  =  "line one\nline two" ; 
545+     await  fs . writeFile ( testFilePath ,  content ) ; 
546+ 
547+     using testEnv  =  createTestFileReadTool ( {  cwd : testDir  } ) ; 
548+     const  tool  =  testEnv . tool ; 
549+     const  args : FileReadToolArgs  =  { 
550+       filePath : testFilePath , 
551+     } ; 
552+ 
553+     // Execute 
554+     const  result  =  ( await  tool . execute ! ( args ,  mockToolCallOptions ) )  as  FileReadToolResult ; 
555+ 
556+     // Assert 
557+     expect ( result . success ) . toBe ( true ) ; 
558+     if  ( result . success )  { 
559+       // Test toModelOutput transformation 
560+       const  modelOutput  =  tool . toModelOutput ! ( result ) ; 
561+       expect ( modelOutput . type ) . toBe ( "json" ) ; 
562+       if  ( modelOutput . type  ===  "json" )  { 
563+         expect ( modelOutput . value ) . toEqual ( result ) ; 
564+       } 
565+     } 
566+   } ) ; 
391567} ) ; 
0 commit comments