@@ -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