Skip to main content

gproxy_protocol/wire/openai/
images.rs

1//! Sources: local OpenAI create-operation docs; missing request/event schemas
2//! from openai/openai-python e12b81d3bbf644ec7045e152d69bc4b68d69cd48
3//! and openai/openai-openapi 38170fdddbb6a1813eae6c6587ee17cf2987185b,
4//! checked 2026-09-13. Binary bodies and multipart streams remain transport-owned.
5use crate::connection::{HttpBody, MultipartPart};
6use crate::{Rest, WireRequest, WireResponse};
7use serde::{Deserialize, Serialize};
8fn optional<'de, D, T>(d: D) -> Result<Option<T>, D::Error>
9where
10    D: serde::Deserializer<'de>,
11    T: Deserialize<'de>,
12{
13    T::deserialize(d).map(Some)
14}
15fn nullable<'de, D, T>(d: D) -> Result<Option<Option<T>>, D::Error>
16where
17    D: serde::Deserializer<'de>,
18    T: Deserialize<'de>,
19{
20    Option::<T>::deserialize(d).map(Some)
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
24#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
25#[derive(gproxy_protocol_macros::DeclaredFields)]
26pub enum ImageBackground {
27    #[serde(rename = "transparent")]
28    Transparent,
29    #[serde(rename = "opaque")]
30    Opaque,
31    #[serde(rename = "auto")]
32    Auto,
33}
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
36#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
37#[derive(gproxy_protocol_macros::DeclaredFields)]
38pub enum ImageModeration {
39    #[serde(rename = "low")]
40    Low,
41    #[serde(rename = "auto")]
42    Auto,
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
46#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
47#[derive(gproxy_protocol_macros::DeclaredFields)]
48pub enum ImageOutputFormat {
49    #[serde(rename = "png")]
50    Png,
51    #[serde(rename = "jpeg")]
52    Jpeg,
53    #[serde(rename = "webp")]
54    Webp,
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
58#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
59#[derive(gproxy_protocol_macros::DeclaredFields)]
60pub enum ImageQuality {
61    #[serde(rename = "standard")]
62    Standard,
63    #[serde(rename = "hd")]
64    Hd,
65    #[serde(rename = "low")]
66    Low,
67    #[serde(rename = "medium")]
68    Medium,
69    #[serde(rename = "high")]
70    High,
71    #[serde(rename = "auto")]
72    Auto,
73    #[serde(rename = "xhigh")]
74    Xhigh,
75    #[serde(rename = "max")]
76    Max,
77}
78
79#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
80#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
81#[derive(gproxy_protocol_macros::DeclaredFields)]
82pub enum ImageResponseFormat {
83    #[serde(rename = "url")]
84    Url,
85    #[serde(rename = "b64_json")]
86    B64Json,
87}
88
89#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
90#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
91#[derive(gproxy_protocol_macros::DeclaredFields)]
92pub enum ImageStyle {
93    #[serde(rename = "vivid")]
94    Vivid,
95    #[serde(rename = "natural")]
96    Natural,
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
100#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
101#[derive(gproxy_protocol_macros::DeclaredFields)]
102pub enum InputFidelity {
103    #[serde(rename = "high")]
104    High,
105    #[serde(rename = "low")]
106    Low,
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
110#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
111#[derive(gproxy_protocol_macros::DeclaredFields)]
112pub enum EditedImageQuality {
113    #[serde(rename = "low")]
114    Low,
115    #[serde(rename = "medium")]
116    Medium,
117    #[serde(rename = "high")]
118    High,
119    #[serde(rename = "auto")]
120    Auto,
121    #[serde(rename = "xhigh")]
122    Xhigh,
123    #[serde(rename = "max")]
124    Max,
125}
126
127#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
128#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
129#[derive(gproxy_protocol_macros::DeclaredFields)]
130pub enum EditedImageSize {
131    #[serde(rename = "auto")]
132    Auto,
133    #[serde(rename = "1024x1024")]
134    Square,
135    #[serde(rename = "1536x1024")]
136    Landscape,
137    #[serde(rename = "1024x1536")]
138    Portrait,
139    #[serde(untagged)]
140    Custom(String),
141}
142
143#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
144#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
145#[derive(gproxy_protocol_macros::DeclaredFields)]
146pub enum OutputImageBackground {
147    #[serde(rename = "transparent")]
148    Transparent,
149    #[serde(rename = "opaque")]
150    Opaque,
151}
152
153#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
154#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
155#[derive(gproxy_protocol_macros::DeclaredFields)]
156pub enum OutputImageQuality {
157    #[serde(rename = "low")]
158    Low,
159    #[serde(rename = "medium")]
160    Medium,
161    #[serde(rename = "high")]
162    High,
163    #[serde(rename = "xhigh")]
164    Xhigh,
165    #[serde(rename = "max")]
166    Max,
167}
168
169#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
170#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
171#[derive(gproxy_protocol_macros::DeclaredFields)]
172pub enum OutputImageSize {
173    #[serde(rename = "1024x1024")]
174    Square,
175    #[serde(rename = "1024x1536")]
176    Portrait,
177    #[serde(rename = "1536x1024")]
178    Landscape,
179    #[serde(untagged)]
180    Custom(String),
181}
182
183#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
184#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
185#[derive(gproxy_protocol_macros::DeclaredFields)]
186pub enum MultipartImageQuality {
187    #[serde(rename = "standard")]
188    Standard,
189    #[serde(rename = "low")]
190    Low,
191    #[serde(rename = "medium")]
192    Medium,
193    #[serde(rename = "high")]
194    High,
195    #[serde(rename = "xhigh")]
196    Xhigh,
197    #[serde(rename = "max")]
198    Max,
199    #[serde(rename = "auto")]
200    Auto,
201}
202
203#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
204#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
205#[derive(gproxy_protocol_macros::DeclaredFields)]
206pub enum StreamImageQuality {
207    #[serde(rename = "low")]
208    Low,
209    #[serde(rename = "medium")]
210    Medium,
211    #[serde(rename = "high")]
212    High,
213    #[serde(rename = "xhigh")]
214    Xhigh,
215    #[serde(rename = "max")]
216    Max,
217    #[serde(rename = "auto")]
218    Auto,
219}
220
221#[derive(
222    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
223)]
224#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
225#[derive(gproxy_protocol_macros::DeclaredFields)]
226pub struct CreateImageRequestBody {
227    pub prompt: String,
228    #[serde(
229        default,
230        deserialize_with = "nullable",
231        skip_serializing_if = "Option::is_none"
232    )]
233    pub background: Option<Option<ImageBackground>>,
234    #[serde(
235        default,
236        deserialize_with = "nullable",
237        skip_serializing_if = "Option::is_none"
238    )]
239    pub model: Option<Option<String>>,
240    #[serde(
241        default,
242        deserialize_with = "nullable",
243        skip_serializing_if = "Option::is_none"
244    )]
245    pub moderation: Option<Option<ImageModeration>>,
246    #[serde(
247        default,
248        deserialize_with = "nullable",
249        skip_serializing_if = "Option::is_none"
250    )]
251    pub n: Option<Option<i64>>,
252    #[serde(
253        default,
254        deserialize_with = "nullable",
255        skip_serializing_if = "Option::is_none"
256    )]
257    pub output_compression: Option<Option<i64>>,
258    #[serde(
259        default,
260        deserialize_with = "nullable",
261        skip_serializing_if = "Option::is_none"
262    )]
263    pub output_format: Option<Option<ImageOutputFormat>>,
264    #[serde(
265        default,
266        deserialize_with = "nullable",
267        skip_serializing_if = "Option::is_none"
268    )]
269    pub partial_images: Option<Option<i64>>,
270    #[serde(
271        default,
272        deserialize_with = "nullable",
273        skip_serializing_if = "Option::is_none"
274    )]
275    pub quality: Option<Option<ImageQuality>>,
276    #[serde(
277        default,
278        deserialize_with = "nullable",
279        skip_serializing_if = "Option::is_none"
280    )]
281    pub response_format: Option<Option<ImageResponseFormat>>,
282    #[serde(
283        default,
284        deserialize_with = "nullable",
285        skip_serializing_if = "Option::is_none"
286    )]
287    pub size: Option<Option<String>>,
288    #[serde(
289        default,
290        deserialize_with = "nullable",
291        skip_serializing_if = "Option::is_none"
292    )]
293    pub stream: Option<Option<bool>>,
294    #[serde(
295        default,
296        deserialize_with = "nullable",
297        skip_serializing_if = "Option::is_none"
298    )]
299    pub style: Option<Option<ImageStyle>>,
300    #[serde(
301        default,
302        deserialize_with = "optional",
303        skip_serializing_if = "Option::is_none"
304    )]
305    pub user: Option<String>,
306    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
307    pub rest: Rest,
308}
309
310#[derive(
311    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
312)]
313#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
314#[derive(gproxy_protocol_macros::DeclaredFields)]
315pub struct ImageReference {
316    #[serde(
317        default,
318        deserialize_with = "optional",
319        skip_serializing_if = "Option::is_none"
320    )]
321    pub file_id: Option<String>,
322    #[serde(
323        default,
324        deserialize_with = "optional",
325        skip_serializing_if = "Option::is_none"
326    )]
327    pub image_url: Option<String>,
328    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
329    pub rest: Rest,
330}
331
332#[derive(
333    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
334)]
335#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
336#[derive(gproxy_protocol_macros::DeclaredFields)]
337pub struct EditImageJsonBody {
338    pub images: Vec<ImageReference>,
339    pub prompt: String,
340    #[serde(
341        default,
342        deserialize_with = "nullable",
343        skip_serializing_if = "Option::is_none"
344    )]
345    pub background: Option<Option<ImageBackground>>,
346    #[serde(
347        default,
348        deserialize_with = "nullable",
349        skip_serializing_if = "Option::is_none"
350    )]
351    pub model: Option<Option<String>>,
352    #[serde(
353        default,
354        deserialize_with = "nullable",
355        skip_serializing_if = "Option::is_none"
356    )]
357    pub moderation: Option<Option<ImageModeration>>,
358    #[serde(
359        default,
360        deserialize_with = "nullable",
361        skip_serializing_if = "Option::is_none"
362    )]
363    pub n: Option<Option<i64>>,
364    #[serde(
365        default,
366        deserialize_with = "nullable",
367        skip_serializing_if = "Option::is_none"
368    )]
369    pub output_compression: Option<Option<i64>>,
370    #[serde(
371        default,
372        deserialize_with = "nullable",
373        skip_serializing_if = "Option::is_none"
374    )]
375    pub output_format: Option<Option<ImageOutputFormat>>,
376    #[serde(
377        default,
378        deserialize_with = "nullable",
379        skip_serializing_if = "Option::is_none"
380    )]
381    pub partial_images: Option<Option<i64>>,
382    #[serde(
383        default,
384        deserialize_with = "nullable",
385        skip_serializing_if = "Option::is_none"
386    )]
387    pub input_fidelity: Option<Option<InputFidelity>>,
388    #[serde(
389        default,
390        deserialize_with = "optional",
391        skip_serializing_if = "Option::is_none"
392    )]
393    pub mask: Option<ImageReference>,
394    #[serde(
395        default,
396        deserialize_with = "nullable",
397        skip_serializing_if = "Option::is_none"
398    )]
399    pub quality: Option<Option<EditedImageQuality>>,
400    #[serde(
401        default,
402        deserialize_with = "nullable",
403        skip_serializing_if = "Option::is_none"
404    )]
405    pub size: Option<Option<EditedImageSize>>,
406    #[serde(
407        default,
408        deserialize_with = "nullable",
409        skip_serializing_if = "Option::is_none"
410    )]
411    pub stream: Option<Option<bool>>,
412    #[serde(
413        default,
414        deserialize_with = "optional",
415        skip_serializing_if = "Option::is_none"
416    )]
417    pub user: Option<String>,
418    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
419    pub rest: Rest,
420}
421
422#[derive(Debug, gproxy_protocol_macros::WireBuilder)]
423#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
424#[derive(gproxy_protocol_macros::DeclaredFields)]
425pub struct EditImageMultipartForm {
426    pub image: Vec<MultipartPart>,
427    pub prompt: String,
428    pub mask: Option<MultipartPart>,
429    pub background: Option<Option<ImageBackground>>,
430    pub model: Option<Option<String>>,
431    pub n: Option<Option<i64>>,
432    pub output_compression: Option<Option<i64>>,
433    pub output_format: Option<Option<ImageOutputFormat>>,
434    pub partial_images: Option<Option<i64>>,
435    pub input_fidelity: Option<Option<InputFidelity>>,
436    pub quality: Option<Option<MultipartImageQuality>>,
437    pub size: Option<Option<String>>,
438    pub response_format: Option<Option<ImageResponseFormat>>,
439    pub stream: Option<Option<bool>>,
440    pub user: Option<String>,
441}
442
443#[derive(
444    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
445)]
446#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
447#[derive(gproxy_protocol_macros::DeclaredFields)]
448pub struct ImagesResponse {
449    pub created: i64,
450    #[serde(
451        default,
452        deserialize_with = "optional",
453        skip_serializing_if = "Option::is_none"
454    )]
455    pub background: Option<OutputImageBackground>,
456    #[serde(
457        default,
458        deserialize_with = "optional",
459        skip_serializing_if = "Option::is_none"
460    )]
461    pub data: Option<Vec<GeneratedImage>>,
462    #[serde(
463        default,
464        deserialize_with = "optional",
465        skip_serializing_if = "Option::is_none"
466    )]
467    pub output_format: Option<ImageOutputFormat>,
468    #[serde(
469        default,
470        deserialize_with = "optional",
471        skip_serializing_if = "Option::is_none"
472    )]
473    pub quality: Option<OutputImageQuality>,
474    #[serde(
475        default,
476        deserialize_with = "optional",
477        skip_serializing_if = "Option::is_none"
478    )]
479    pub size: Option<OutputImageSize>,
480    #[serde(
481        default,
482        deserialize_with = "optional",
483        skip_serializing_if = "Option::is_none"
484    )]
485    pub usage: Option<ImageUsage>,
486    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
487    pub rest: Rest,
488}
489
490#[derive(
491    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
492)]
493#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
494#[derive(gproxy_protocol_macros::DeclaredFields)]
495pub struct GeneratedImage {
496    #[serde(
497        default,
498        deserialize_with = "optional",
499        skip_serializing_if = "Option::is_none"
500    )]
501    pub b64_json: Option<String>,
502    #[serde(
503        default,
504        deserialize_with = "optional",
505        skip_serializing_if = "Option::is_none"
506    )]
507    pub url: Option<String>,
508    #[serde(
509        default,
510        deserialize_with = "optional",
511        skip_serializing_if = "Option::is_none"
512    )]
513    pub revised_prompt: Option<String>,
514    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
515    pub rest: Rest,
516}
517
518#[derive(
519    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
520)]
521#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
522#[derive(gproxy_protocol_macros::DeclaredFields)]
523pub struct ImageUsage {
524    pub input_tokens: i64,
525    pub input_tokens_details: ImageTokenDetails,
526    pub output_tokens: i64,
527    pub total_tokens: i64,
528    #[serde(
529        default,
530        deserialize_with = "optional",
531        skip_serializing_if = "Option::is_none"
532    )]
533    pub output_tokens_details: Option<ImageTokenDetails>,
534    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
535    pub rest: Rest,
536}
537
538#[derive(
539    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
540)]
541#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
542#[derive(gproxy_protocol_macros::DeclaredFields)]
543pub struct ImageTokenDetails {
544    pub image_tokens: i64,
545    pub text_tokens: i64,
546    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
547    pub rest: Rest,
548}
549
550#[derive(
551    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
552)]
553#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
554#[derive(gproxy_protocol_macros::DeclaredFields)]
555pub struct ImagePartialEvent {
556    pub b64_json: String,
557    pub background: ImageBackground,
558    pub created_at: i64,
559    pub output_format: ImageOutputFormat,
560    pub partial_image_index: i64,
561    pub quality: StreamImageQuality,
562    pub size: String,
563    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
564    pub rest: Rest,
565}
566
567#[derive(
568    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder,
569)]
570#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
571#[derive(gproxy_protocol_macros::DeclaredFields)]
572pub struct ImageCompletedEvent {
573    pub b64_json: String,
574    pub background: ImageBackground,
575    pub created_at: i64,
576    pub output_format: ImageOutputFormat,
577    pub quality: StreamImageQuality,
578    pub size: String,
579    pub usage: ImageUsage,
580    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
581    pub rest: Rest,
582}
583
584#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
585#[serde(tag = "type")]
586#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
587#[derive(gproxy_protocol_macros::DeclaredFields)]
588pub enum ImageGenerationStreamEvent {
589    #[serde(rename = "image_generation.partial_image")]
590    Partial(ImagePartialEvent),
591    #[serde(rename = "image_generation.completed")]
592    Completed(ImageCompletedEvent),
593}
594
595#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
596#[serde(tag = "type")]
597#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
598#[derive(gproxy_protocol_macros::DeclaredFields)]
599pub enum ImageEditStreamEvent {
600    #[serde(rename = "image_edit.partial_image")]
601    Partial(ImagePartialEvent),
602    #[serde(rename = "image_edit.completed")]
603    Completed(ImageCompletedEvent),
604}
605
606pub type CreateImageRequest = WireRequest<CreateImageRequestBody>;
607pub type CreateImageResponse = WireResponse<ImagesResponse>;
608pub type CreateImageStreamResponse = WireResponse<crate::connection::ByteStream>;
609pub type EditImageJsonRequest = WireRequest<EditImageJsonBody>;
610pub type EditImageMultipartRequest = WireRequest<EditImageMultipartForm>;
611pub type RawEditImageRequest = WireRequest<crate::connection::Multipart>;
612pub type EditImageResponse = WireResponse<ImagesResponse>;
613pub type EditImageStreamResponse = WireResponse<crate::connection::ByteStream>;
614pub type RawImageResponse = WireResponse<HttpBody>;