@@ -8,6 +8,15 @@ const ABSOLUTE_PATH_PATTERN = /^(\/|[A-Za-z]:[\\/]|\\\\)/;
88
99export const sdcppConfigSchema = z
1010 . object ( {
11+ mode : z . enum ( [ "diffusion" , "upscale" ] ) . default ( "diffusion" )
12+ . describe (
13+ "Operation mode for the diffusion plugin. " +
14+ "`'diffusion'` (default) builds a full SD / SDXL / SD3 / FLUX pipeline from " +
15+ "the primary model plus optional auxiliary text encoders, VAE, and ESRGAN " +
16+ "upscaler, and exposes diffusion({ ... }). " +
17+ "`'upscale'` builds a standalone ESRGAN upscaler from the primary model " +
18+ "file alone (auxiliary model sources are ignored) and exposes upscale({ ... })." ,
19+ ) ,
1120 threads : z . number ( ) . optional ( ) ,
1221 device : z . enum ( [ "gpu" , "cpu" ] ) . optional ( ) ,
1322 prediction : z
@@ -52,17 +61,18 @@ export const sdcppConfigSchema = z
5261 upscaler : z . object ( {
5362 type : z . literal ( "esrgan" ) . optional ( )
5463 . describe ( "Type of upscaler to use for post-generation upscaling when requested in diffusion({ upscale })." ) ,
55- model_src : modelSrcInputSchema
64+ model_src : modelSrcInputSchema . optional ( )
5665 . describe (
57- "ESRGAN upscaler model (e.g. RealESRGAN_x4plus_anime_6B.pth). When " +
58- "provided, generation requests can opt into post-generation upscale " +
59- "via diffusion({ upscale: true }) or diffusion({ upscale: { repeats } })." ,
66+ "ESRGAN upscaler model (e.g. RealESRGAN_x4plus_anime_6B.pth). " +
67+ "Required in diffusion mode when this `upscaler` block is set — " +
68+ "configures the post-generation upscaler invoked via diffusion({ upscale }). " +
69+ "In `mode: 'upscale'` the primary modelSrc itself is the ESRGAN model, " +
70+ "so this field is ignored." ,
6071 ) ,
6172 tile_size : z . number ( ) . int ( ) . positive ( ) . optional ( )
6273 . describe (
6374 "ESRGAN upscaler tile size in pixels. Smaller tiles use less VRAM " +
64- "at the cost of more passes. Only used when upscaler.model_src is " +
65- "configured and diffusion({ upscale }) is requested." ,
75+ "at the cost of more passes." ,
6676 ) ,
6777 direct : z . boolean ( ) . optional ( )
6878 . describe (
@@ -83,10 +93,19 @@ export const sdcppConfigSchema = z
8393 "Number of CPU threads dedicated to the ESRGAN upscaler. -1 = auto." ,
8494 ) ,
8595 } ) . strict ( ) . optional ( )
86- . describe ( "Configuration for an optional upscaler that can be applied after diffusion generation when requested in diffusion({ upscale })." ) ,
96+ . describe (
97+ "ESRGAN upscaler configuration. In diffusion mode this enables the " +
98+ "post-generation upscale path invoked via diffusion({ upscale }) and " +
99+ "requires `model_src`. In `mode: 'upscale'` only the tuning fields " +
100+ "(tile_size, direct, offload_params_to_cpu, threads) are honored — " +
101+ "the primary modelSrc IS the ESRGAN model in that mode and " +
102+ "`model_src` here is ignored. Mode-dependent constraints (e.g. " +
103+ "`model_src` required in diffusion mode) are enforced by the " +
104+ "sdcpp-generation plugin at load time, not at the schema layer." ,
105+ ) ,
87106 } ) ;
88107
89- export type SdcppConfig = z . infer < typeof sdcppConfigSchema > ;
108+ export type SdcppConfig = z . input < typeof sdcppConfigSchema > ;
90109
91110export const diffusionStatsSchema = z . object ( {
92111 modelLoadMs : z
@@ -350,3 +369,94 @@ export type DiffusionClientParams = DiffusionClientParamsBase &
350369 | { init_image ?: Uint8Array ; init_images ?: never }
351370 | { init_image ?: never ; init_images ?: Uint8Array [ ] }
352371 ) ;
372+
373+ // ============================================
374+ // Standalone ESRGAN upscale (mode: "upscale")
375+ // ============================================
376+
377+ export const upscaleStatsSchema = z . object ( {
378+ modelLoadMs : z
379+ . number ( )
380+ . optional ( )
381+ . describe ( "Wall-clock time in milliseconds spent loading the upscaler model." ) ,
382+ upscaleMs : z
383+ . number ( )
384+ . optional ( )
385+ . describe ( "Wall-clock time in milliseconds for the most recent upscale job." ) ,
386+ totalUpscaleMs : z
387+ . number ( )
388+ . optional ( )
389+ . describe ( "Cumulative upscale time in milliseconds across all jobs." ) ,
390+ totalWallMs : z
391+ . number ( )
392+ . optional ( )
393+ . describe (
394+ "Total wall-clock time in milliseconds including model load and upscaling." ,
395+ ) ,
396+ totalUpscales : z
397+ . number ( )
398+ . optional ( )
399+ . describe ( "Cumulative number of upscale calls." ) ,
400+ totalImages : z
401+ . number ( )
402+ . optional ( )
403+ . describe ( "Cumulative number of images produced." ) ,
404+ totalPixels : z
405+ . number ( )
406+ . optional ( )
407+ . describe ( "Cumulative number of pixels produced across all images." ) ,
408+ width : z . number ( ) . optional ( ) . describe ( "Width of the most recent emitted PNG." ) ,
409+ height : z . number ( ) . optional ( ) . describe ( "Height of the most recent emitted PNG." ) ,
410+ repeats : z
411+ . number ( )
412+ . optional ( )
413+ . describe ( "Number of ESRGAN passes used by the most recent upscale job." ) ,
414+ } ) ;
415+
416+ export type UpscaleStats = z . infer < typeof upscaleStatsSchema > ;
417+
418+ export const upscaleRequestSchema = z . object ( {
419+ modelId : z
420+ . string ( )
421+ . describe (
422+ "Identifier of the loaded upscaler model. The model must have been loaded " +
423+ "with `modelType: 'diffusion'` and `modelConfig.mode: 'upscale'`." ,
424+ ) ,
425+ image : z
426+ . string ( )
427+ . min ( 1 )
428+ . regex ( BASE64_PATTERN )
429+ . describe ( "Base64-encoded PNG/JPEG bytes of the source image." ) ,
430+ repeats : z
431+ . number ( )
432+ . int ( )
433+ . positive ( )
434+ . optional ( )
435+ . describe (
436+ "Number of ESRGAN passes to run sequentially. Each pass multiplies " +
437+ "dimensions by the model's native scale factor; only the final image " +
438+ "is emitted (`outputs.length === 1`). Defaults to 1." ,
439+ ) ,
440+ } ) ;
441+
442+ export type UpscaleRequest = z . input < typeof upscaleRequestSchema > ;
443+
444+ export const upscaleStreamRequestSchema = upscaleRequestSchema . extend ( {
445+ type : z . literal ( "upscaleStream" ) ,
446+ } ) ;
447+
448+ export type UpscaleStreamRequest = z . input < typeof upscaleStreamRequestSchema > ;
449+
450+ export const upscaleStreamResponseSchema = z . object ( {
451+ type : z . literal ( "upscaleStream" ) ,
452+ data : z . string ( ) . optional ( ) ,
453+ outputIndex : z . number ( ) . optional ( ) ,
454+ done : z . boolean ( ) . optional ( ) ,
455+ stats : upscaleStatsSchema . optional ( ) ,
456+ } ) ;
457+
458+ export type UpscaleStreamResponse = z . infer < typeof upscaleStreamResponseSchema > ;
459+
460+ export type UpscaleClientParams = Omit < UpscaleRequest , "image" > & {
461+ image : Uint8Array ;
462+ } ;
0 commit comments