@@ -75,10 +75,21 @@ export class RunpodImageModel implements ImageModelV2 {
7575 > {
7676 const warnings : Array < ImageModelV2CallWarning > = [ ] ;
7777
78+ // Check if this is a Pruna model (skip standard size/aspectRatio validation)
79+ const isPrunaModel =
80+ this . modelId . includes ( 'pruna' ) || this . modelId . includes ( 'p-image' ) ;
81+
82+ // Check if this is a Nano Banana Pro model (skip standard size/aspectRatio validation)
83+ const isNanoBananaProModel = this . modelId . includes ( 'nano-banana-pro' ) ;
84+
7885 // Determine the size to use
7986 let runpodSize : string ;
8087
81- if ( size ) {
88+ if ( isPrunaModel || isNanoBananaProModel ) {
89+ // These models use aspect_ratio string directly, skip size validation
90+ // Pass through the aspectRatio or use default, validation happens at API level
91+ runpodSize = aspectRatio || '1:1' ;
92+ } else if ( size ) {
8293 // Convert AI SDK format "1328x1328" to Runpod format "1328*1328"
8394 const runpodSizeCandidate = size . replace ( 'x' , '*' ) ;
8495
@@ -128,7 +139,8 @@ export class RunpodImageModel implements ImageModelV2 {
128139 prompt ,
129140 runpodSize ,
130141 seed ,
131- providerOptions . runpod
142+ providerOptions . runpod ,
143+ aspectRatio
132144 ) ;
133145
134146 const { value : response , responseHeaders } = await postJsonToApi ( {
@@ -286,7 +298,8 @@ export class RunpodImageModel implements ImageModelV2 {
286298 prompt : string ,
287299 runpodSize : string ,
288300 seed ?: number ,
289- runpodOptions ?: Record < string , unknown >
301+ runpodOptions ?: Record < string , unknown > ,
302+ aspectRatio ?: string
290303 ) : Record < string , unknown > {
291304 // Check if this is a Flux model that uses different parameters
292305 const isFluxModel =
@@ -329,60 +342,96 @@ export class RunpodImageModel implements ImageModelV2 {
329342 }
330343
331344 // Check if this is a Pruna model
332- const isPrunaModel = this . modelId . includes ( 'pruna' ) || this . modelId . includes ( 'p-image' ) ;
345+ const isPrunaModel =
346+ this . modelId . includes ( 'pruna' ) || this . modelId . includes ( 'p-image' ) ;
333347 if ( isPrunaModel ) {
334348 const isPrunaEdit = this . modelId . includes ( 'edit' ) ;
335349
336350 if ( isPrunaEdit ) {
337- // Pruna image edit uses images array and aspect_ratio string
338- return {
351+ // Pruna image edit
352+ // Supported aspect_ratio: "match_input_image", "1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"
353+ // Supports 1-5 images via providerOptions.runpod.images
354+ const editPayload : Record < string , unknown > = {
339355 prompt,
340- seed : seed ?? - 1 ,
341- aspect_ratio : runpodOptions ?. aspect_ratio ?? 'match_input_image' ,
342- disable_safety_checker : runpodOptions ?. disable_safety_checker ?? false ,
343- enable_sync_mode : runpodOptions ?. enable_sync_mode ?? false ,
344- ...runpodOptions ,
356+ aspect_ratio :
357+ ( runpodOptions ?. aspect_ratio as string ) ??
358+ aspectRatio ??
359+ 'match_input_image' ,
360+ disable_safety_checker :
361+ ( runpodOptions ?. disable_safety_checker as boolean ) ?? false ,
345362 } ;
346- } else {
347- // Pruna text-to-image uses aspect_ratio string format
348- const aspectRatioMap : Record < string , string > = {
349- '1328*1328' : '1:1' ,
350- '1472*1140' : '4:3' ,
351- '1140*1472' : '3:4' ,
352- '512*512' : '1:1' ,
353- '768*768' : '1:1' ,
354- '1024*1024' : '1:1' ,
355- '1536*1536' : '1:1' ,
356- '2048*2048' : '1:1' ,
357- '4096*4096' : '1:1' ,
358- '512*768' : '2:3' ,
359- '768*512' : '3:2' ,
360- '1024*768' : '4:3' ,
361- '768*1024' : '3:4' ,
362- } ;
363- const aspectRatio = runpodOptions ?. aspect_ratio ?? aspectRatioMap [ runpodSize ] ?? '1:1' ;
364363
365- return {
364+ // Add seed if provided
365+ if ( seed !== undefined ) {
366+ editPayload . seed = seed ;
367+ } else if ( runpodOptions ?. seed !== undefined ) {
368+ editPayload . seed = runpodOptions . seed ;
369+ }
370+
371+ // Add images array (required, 1-5 images)
372+ if ( runpodOptions ?. images ) {
373+ editPayload . images = runpodOptions . images ;
374+ }
375+
376+ return editPayload ;
377+ } else {
378+ // Pruna text-to-image
379+ // Supported aspect_ratio: "1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3", "custom"
380+ // For custom: width/height 256-1440, must be multiple of 16
381+ const t2iPayload : Record < string , unknown > = {
366382 prompt,
367- seed : seed ?? 0 ,
368- aspect_ratio : aspectRatio ,
369- enable_safety_checker : runpodOptions ?. enable_safety_checker ?? true ,
370- ... runpodOptions ,
383+ aspect_ratio :
384+ ( runpodOptions ?. aspect_ratio as string ) ?? aspectRatio ?? '1:1' ,
385+ disable_safety_checker :
386+ ( runpodOptions ?. disable_safety_checker as boolean ) ?? false ,
371387 } ;
388+
389+ // Add seed if provided
390+ if ( seed !== undefined ) {
391+ t2iPayload . seed = seed ;
392+ } else if ( runpodOptions ?. seed !== undefined ) {
393+ t2iPayload . seed = runpodOptions . seed ;
394+ }
395+
396+ // Handle custom aspect ratio with width/height
397+ if ( t2iPayload . aspect_ratio === 'custom' ) {
398+ if ( runpodOptions ?. width ) {
399+ t2iPayload . width = runpodOptions . width ;
400+ }
401+ if ( runpodOptions ?. height ) {
402+ t2iPayload . height = runpodOptions . height ;
403+ }
404+ }
405+
406+ return t2iPayload ;
372407 }
373408 }
374409
375410 // Check if this is a Nano Banana Pro model (google/nano-banana-pro-edit)
376411 const isNanaBananaProModel = this . modelId . includes ( 'nano-banana-pro' ) ;
377412 if ( isNanaBananaProModel ) {
378- return {
413+ // Nano Banana Pro image edit
414+ // Supported aspect_ratio: "1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3", "21:9", "9:21"
415+ // Supported resolution: "1k", "2k", "4k"
416+ // Supported output_format: "jpeg", "png", "webp"
417+ const nanoBananaPayload : Record < string , unknown > = {
379418 prompt,
380- resolution : runpodOptions ?. resolution ?? '1k' ,
381- output_format : runpodOptions ?. output_format ?? 'jpeg' ,
382- enable_base64_output : runpodOptions ?. enable_base64_output ?? false ,
383- enable_sync_mode : runpodOptions ?. enable_sync_mode ?? false ,
384- ...runpodOptions ,
419+ aspect_ratio :
420+ ( runpodOptions ?. aspect_ratio as string ) ?? aspectRatio ?? '1:1' ,
421+ resolution : ( runpodOptions ?. resolution as string ) ?? '1k' ,
422+ output_format : ( runpodOptions ?. output_format as string ) ?? 'jpeg' ,
423+ enable_base64_output :
424+ ( runpodOptions ?. enable_base64_output as boolean ) ?? false ,
425+ enable_sync_mode :
426+ ( runpodOptions ?. enable_sync_mode as boolean ) ?? false ,
385427 } ;
428+
429+ // Add images array (required)
430+ if ( runpodOptions ?. images ) {
431+ nanoBananaPayload . images = runpodOptions . images ;
432+ }
433+
434+ return nanoBananaPayload ;
386435 }
387436
388437 // Default format for Qwen and other models
0 commit comments