@@ -351,7 +351,7 @@ export class WebSocketClient {
351351 this . setStatus ( "disconnected" ) ;
352352 }
353353
354- sendPrompt ( content : string , imagePaths ?: string [ ] ) : void {
354+ async sendPrompt ( content : string , imagePaths ?: string [ ] ) : Promise < void > {
355355 if ( ! this . ws || this . ws . readyState !== WebSocket . OPEN ) {
356356 this . options . onError ( new Error ( "Not connected" ) ) ;
357357 return ;
@@ -364,13 +364,64 @@ export class WebSocketClient {
364364 } ;
365365
366366 if ( imagePaths && imagePaths . length > 0 ) {
367- message . imagePaths = imagePaths ;
367+ try {
368+ console . log ( "[expo-air] Uploading" , imagePaths . length , "image(s) to:" , this . getUploadUrl ( ) ) ;
369+ const serverPaths = await this . uploadImages ( imagePaths ) ;
370+ console . log ( "[expo-air] Upload returned paths:" , serverPaths ) ;
371+ if ( serverPaths . length > 0 ) {
372+ message . imagePaths = serverPaths ;
373+ }
374+ } catch ( error ) {
375+ console . error ( "[expo-air] Image upload failed:" , error ) ;
376+ }
368377 }
369378
370379 this . ws . send ( JSON . stringify ( message ) ) ;
371380 this . setStatus ( "sending" ) ;
372381 }
373382
383+ private getUploadUrl ( ) : string {
384+ let url = this . options . url ;
385+ // ws:// → http://, wss:// → https://
386+ if ( url . startsWith ( "wss://" ) ) url = "https://" + url . slice ( 6 ) ;
387+ else if ( url . startsWith ( "ws://" ) ) url = "http://" + url . slice ( 5 ) ;
388+ // Insert /upload before the query string
389+ const qIndex = url . indexOf ( "?" ) ;
390+ if ( qIndex >= 0 ) {
391+ return url . slice ( 0 , qIndex ) + "/upload" + url . slice ( qIndex ) ;
392+ }
393+ return url + "/upload" ;
394+ }
395+
396+ private async uploadImages ( localPaths : string [ ] ) : Promise < string [ ] > {
397+ const uploadUrl = this . getUploadUrl ( ) ;
398+
399+ const formData = new FormData ( ) ;
400+ for ( const path of localPaths ) {
401+ const uri = path . startsWith ( "file://" ) ? path : `file://${ path } ` ;
402+ const ext = path . split ( "." ) . pop ( ) ?. toLowerCase ( ) || "jpg" ;
403+ const mimeType = ext === "png" ? "image/png" : "image/jpeg" ;
404+ formData . append ( "images" , {
405+ uri,
406+ type : mimeType ,
407+ name : `image.${ ext } ` ,
408+ } as unknown as Blob ) ;
409+ }
410+
411+ const response = await fetch ( uploadUrl , {
412+ method : "POST" ,
413+ body : formData ,
414+ } ) ;
415+
416+ if ( ! response . ok ) {
417+ const text = await response . text ( ) . catch ( ( ) => "" ) ;
418+ throw new Error ( `Upload failed: ${ response . status } ${ text } ` ) ;
419+ }
420+
421+ const result = await response . json ( ) ;
422+ return result . paths || [ ] ;
423+ }
424+
374425 requestNewSession ( ) : void {
375426 if ( ! this . ws || this . ws . readyState !== WebSocket . OPEN ) {
376427 this . options . onError ( new Error ( "Not connected" ) ) ;
0 commit comments