mirror of
https://github.com/openai/codex.git
synced 2026-11-10 21:00:47 +00:00
## What changed
- Gate GIF output behind `features.image_generation_animation`, disabled by default.
- Accept `gif` options for generation and editing, with optional `frame_count` and `frame_duration_ms` controls. Use `gif: {}` for API defaults.
- Preserve animated output with `.gif` filenames and `image/gif` data URLs while providing a still preview to the model.
- Add guidance for simple animations and spritesheet-based GIF edits.
## Testing
Add integration coverage for GIF generation and editing, explicit frame controls and API defaults, saved animation bytes, and still-preview replay across follow-up turns.
GitOrigin-RevId: 08afa0316ae3675921652157836191a649f563cf
94 lines
2.8 KiB
Rust
94 lines
2.8 KiB
Rust
use codex_protocol::models::ImageReference;
|
||
use schemars::JsonSchema;
|
||
use serde::Deserialize;
|
||
use serde::Serialize;
|
||
|
||
#[derive(Debug, Clone, Serialize, PartialEq)]
|
||
pub struct ImageGenerationRequest {
|
||
pub prompt: String,
|
||
#[serde(flatten)]
|
||
pub output: Option<ImageOutput>,
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub background: Option<ImageBackground>,
|
||
pub model: String,
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub n: Option<u64>,
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub quality: Option<ImageQuality>,
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub size: Option<String>,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, PartialEq)]
|
||
pub struct ImageEditRequest {
|
||
pub images: Vec<ImageReference>,
|
||
pub prompt: String,
|
||
#[serde(flatten)]
|
||
pub output: Option<ImageOutput>,
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub background: Option<ImageBackground>,
|
||
pub model: String,
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub n: Option<u64>,
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub quality: Option<ImageQuality>,
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
pub size: Option<String>,
|
||
}
|
||
|
||
/// Optional GIF controls accepted by the Images generation and edit endpoints.
|
||
#[derive(Debug, Clone, Copy, Deserialize, Serialize, JsonSchema, PartialEq)]
|
||
pub struct GifOptions {
|
||
/// Number of frames (2–16). Defaults to 9.
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
#[schemars(range(min = 2, max = 16))]
|
||
pub frame_count: Option<u32>,
|
||
/// Duration of each frame in milliseconds (20–2000). Defaults to 200.
|
||
#[serde(skip_serializing_if = "Option::is_none")]
|
||
#[schemars(range(min = 20, max = 2000))]
|
||
pub frame_duration_ms: Option<u32>,
|
||
}
|
||
|
||
/// The Images API expects the format and its controls as sibling fields.
|
||
#[derive(Debug, Clone, Copy, Serialize, PartialEq)]
|
||
#[serde(tag = "output_format", rename_all = "lowercase")]
|
||
pub enum ImageOutput {
|
||
Gif(GifOptions),
|
||
}
|
||
|
||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||
#[serde(rename_all = "lowercase")]
|
||
pub enum ImageBackground {
|
||
Transparent,
|
||
Opaque,
|
||
Auto,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||
#[serde(rename_all = "lowercase")]
|
||
pub enum ImageQuality {
|
||
Low,
|
||
Medium,
|
||
High,
|
||
Auto,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
|
||
pub struct ImageResponse {
|
||
pub created: u64,
|
||
pub data: Vec<ImageData>,
|
||
#[serde(default)]
|
||
pub background: Option<ImageBackground>,
|
||
#[serde(default)]
|
||
pub quality: Option<ImageQuality>,
|
||
#[serde(default)]
|
||
pub size: Option<String>,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
|
||
pub struct ImageData {
|
||
pub b64_json: String,
|
||
#[serde(default)]
|
||
pub generation_id: Option<String>,
|
||
}
|