@@ -62,6 +62,48 @@ export const ReadTool = Tool.define("read", {
6262
6363 const instructions = await InstructionPrompt . resolve ( ctx . messages , filepath , ctx . messageID )
6464
65+ // Check for images by extension first (handles uppercase extensions like .PNG, .JPG)
66+ const ext = path . extname ( filepath ) . toLowerCase ( )
67+ const imageExts = new Set ( [ ".png" , ".jpg" , ".jpeg" , ".gif" , ".bmp" , ".webp" , ".ico" , ".tif" , ".tiff" ] )
68+ const isImageByExt = imageExts . has ( ext )
69+
70+ // Get MIME type from extension for images (more reliable than Bun's MIME detection for uppercase)
71+ const getImageMime = ( e : string ) => {
72+ if ( e === ".png" ) return "image/png"
73+ if ( e === ".jpg" || e === ".jpeg" ) return "image/jpeg"
74+ if ( e === ".gif" ) return "image/gif"
75+ if ( e === ".bmp" ) return "image/bmp"
76+ if ( e === ".webp" ) return "image/webp"
77+ if ( e === ".ico" ) return "image/x-icon"
78+ if ( e === ".tif" || e === ".tiff" ) return "image/tiff"
79+ return "image/" + e . slice ( 1 )
80+ }
81+
82+ // Handle images by extension (including uppercase)
83+ if ( isImageByExt ) {
84+ const mime = getImageMime ( ext )
85+ const msg = `Image read successfully`
86+ return {
87+ title,
88+ output : msg ,
89+ metadata : {
90+ preview : msg ,
91+ truncated : false ,
92+ ...( instructions . length > 0 && { loaded : instructions . map ( ( i ) => i . filepath ) } ) ,
93+ } ,
94+ attachments : [
95+ {
96+ id : Identifier . ascending ( "part" ) ,
97+ sessionID : ctx . sessionID ,
98+ messageID : ctx . messageID ,
99+ type : "file" ,
100+ mime,
101+ url : `data:${ mime } ;base64,${ Buffer . from ( await file . bytes ( ) ) . toString ( "base64" ) } ` ,
102+ } ,
103+ ] ,
104+ }
105+ }
106+
65107 // Exclude SVG (XML-based) and vnd.fastbidsheet (.fbs extension, commonly FlatBuffers schema files)
66108 const isImage =
67109 file . type . startsWith ( "image/" ) && file . type !== "image/svg+xml" && file . type !== "image/vnd.fastbidsheet"
0 commit comments