@@ -81,6 +81,69 @@ const describeImageWithMistral = async (input: {
8181 }
8282} ;
8383
84+ interface ImageByteResponse {
85+ body : {
86+ getReader : ( ) => {
87+ cancel : ( ) => Promise < void > ;
88+ read : ( ) => Promise < { done : boolean ; value ?: Uint8Array } > ;
89+ releaseLock : ( ) => void ;
90+ } ;
91+ } | null ;
92+ headers : {
93+ get : ( name : string ) => string | null ;
94+ } ;
95+ }
96+
97+ const readBoundedImageBytes = async (
98+ response : ImageByteResponse ,
99+ maxBytes : number
100+ ) : Promise < Uint8Array > => {
101+ const contentLength = response . headers . get ( "content-length" ) ;
102+ if ( contentLength ) {
103+ const declaredBytes = Number ( contentLength ) ;
104+ if ( Number . isFinite ( declaredBytes ) && declaredBytes >= 0 ) {
105+ assertMaxSize ( "remote image payload" , declaredBytes , maxBytes ) ;
106+ }
107+ }
108+
109+ if ( ! response . body ) {
110+ return new Uint8Array ( ) ;
111+ }
112+
113+ const reader = response . body . getReader ( ) ;
114+ const chunks : Uint8Array [ ] = [ ] ;
115+ let totalBytes = 0 ;
116+
117+ try {
118+ while ( true ) {
119+ const { done, value } = await reader . read ( ) ;
120+ if ( done ) {
121+ break ;
122+ }
123+ if ( ! value ) {
124+ continue ;
125+ }
126+
127+ totalBytes += value . byteLength ;
128+ assertMaxSize ( "remote image payload" , totalBytes , maxBytes ) ;
129+ chunks . push ( value ) ;
130+ }
131+ } catch ( error ) {
132+ await reader . cancel ( ) . catch ( ( ) => undefined ) ;
133+ throw error ;
134+ } finally {
135+ reader . releaseLock ( ) ;
136+ }
137+
138+ const bytes = new Uint8Array ( totalBytes ) ;
139+ let offset = 0 ;
140+ for ( const chunk of chunks ) {
141+ bytes . set ( chunk , offset ) ;
142+ offset += chunk . byteLength ;
143+ }
144+ return bytes ;
145+ } ;
146+
84147export const ingestImage = async ( input : {
85148 url ?: string ;
86149 base64 ?: string ;
@@ -111,12 +174,7 @@ export const ingestImage = async (input: {
111174 if ( ! mimeType . startsWith ( "image/" ) ) {
112175 throw new Error ( `Unexpected image content type: ${ mimeType } ` ) ;
113176 }
114- const bytes = new Uint8Array ( await response . arrayBuffer ( ) ) ;
115- assertMaxSize (
116- "remote image payload" ,
117- bytes . byteLength ,
118- config . maxInlineBytes
119- ) ;
177+ const bytes = await readBoundedImageBytes ( response , config . maxInlineBytes ) ;
120178 imagePart = {
121179 type : "image_base64" ,
122180 image_base64 : Buffer . from ( bytes ) . toString ( "base64" ) ,
0 commit comments