@@ -37,19 +37,26 @@ export function useChatExtraContext(): ChatExtraContextApi {
3737 break ;
3838 }
3939
40- if ( mimeType . startsWith ( 'image/' ) && mimeType !== 'image/svg+xml' ) {
41- if ( ! serverProps ?. has_multimodal ) {
40+ if ( mimeType . startsWith ( 'image/' ) ) {
41+ if ( ! serverProps ?. modalities ?. vision ) {
4242 toast . error ( 'Multimodal is not supported by this server or model.' ) ;
4343 break ;
4444 }
4545 const reader = new FileReader ( ) ;
46- reader . onload = ( event ) => {
46+ reader . onload = async ( event ) => {
4747 if ( event . target ?. result ) {
48+ let base64Url = event . target . result as string ;
49+
50+ if ( mimeType === 'image/svg+xml' ) {
51+ // Convert SVG to PNG
52+ base64Url = await svgBase64UrlToPngDataURL ( base64Url ) ;
53+ }
54+
4855 addItems ( [
4956 {
5057 type : 'imageFile' ,
5158 name : file . name ,
52- base64Url : event . target . result as string ,
59+ base64Url,
5360 } ,
5461 ] ) ;
5562 }
@@ -172,3 +179,56 @@ export function isLikelyNotBinary(str: string): boolean {
172179 const ratio = suspiciousCharCount / sampleLength ;
173180 return ratio <= options . suspiciousCharThresholdRatio ;
174181}
182+
183+ // WARN: vibe code below
184+ // Converts a Base64URL encoded SVG string to a PNG Data URL using browser Canvas API.
185+ function svgBase64UrlToPngDataURL ( base64UrlSvg : string ) : Promise < string > {
186+ const backgroundColor = 'white' ; // Default background color for PNG
187+
188+ return new Promise ( ( resolve , reject ) => {
189+ try {
190+ const img = new Image ( ) ;
191+
192+ img . onload = ( ) => {
193+ const canvas = document . createElement ( 'canvas' ) ;
194+ const ctx = canvas . getContext ( '2d' ) ;
195+
196+ if ( ! ctx ) {
197+ reject ( new Error ( 'Failed to get 2D canvas context.' ) ) ;
198+ return ;
199+ }
200+
201+ // Use provided dimensions or SVG's natural dimensions, with fallbacks
202+ // Fallbacks (e.g., 300x300) are for SVGs without explicit width/height
203+ // or when naturalWidth/Height might be 0 before full processing.
204+ const targetWidth = img . naturalWidth || 300 ;
205+ const targetHeight = img . naturalHeight || 300 ;
206+
207+ canvas . width = targetWidth ;
208+ canvas . height = targetHeight ;
209+
210+ if ( backgroundColor ) {
211+ ctx . fillStyle = backgroundColor ;
212+ ctx . fillRect ( 0 , 0 , canvas . width , canvas . height ) ;
213+ }
214+
215+ ctx . drawImage ( img , 0 , 0 , targetWidth , targetHeight ) ;
216+ resolve ( canvas . toDataURL ( 'image/png' ) ) ;
217+ } ;
218+
219+ img . onerror = ( ) => {
220+ reject (
221+ new Error ( 'Failed to load SVG image. Ensure the SVG data is valid.' )
222+ ) ;
223+ } ;
224+
225+ // Load SVG string into an Image element
226+ img . src = base64UrlSvg ;
227+ } catch ( error ) {
228+ const message = error instanceof Error ? error . message : String ( error ) ;
229+ const errorMessage = `Error converting SVG to PNG: ${ message } ` ;
230+ toast . error ( errorMessage ) ;
231+ reject ( new Error ( errorMessage ) ) ;
232+ }
233+ } ) ;
234+ }
0 commit comments