mirror of
https://github.com/openai/codex.git
synced 2026-10-23 18:08:45 +00:00
## What changed Add optional `inputImages` metadata containing each referenced local image's path and SHA-256 hash of the bytes read before normalization. Compute the hash from the same bytes used to prepare the edit request. Preserve this metadata through completion events, persisted thread history, resume, and legacy rollout migration. Update app-server schemas and generated TypeScript and Python types; older items continue to deserialize without the field. ## Testing Add coverage for input ordering, changed contents at the same path, unreadable or invalid references, serialization, persisted history and resume, and legacy migration. GitOrigin-RevId: 522be8ec1e39c9b2bbe5b9ccb37ea67d17f0e21a
88 lines
3.1 KiB
Rust
88 lines
3.1 KiB
Rust
use codex_utils_absolute_path::AbsolutePathBuf;
|
|
use schemars::JsonSchema;
|
|
use serde::Deserialize;
|
|
use serde::Serialize;
|
|
use ts_rs::TS;
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
|
#[serde(tag = "type", rename_all = "camelCase")]
|
|
#[ts(tag = "type", rename_all = "camelCase")]
|
|
pub enum ImageGenerationFailure {
|
|
UsageLimitExceeded {
|
|
#[serde(rename = "limitId")]
|
|
#[ts(rename = "limitId")]
|
|
limit_id: String,
|
|
#[serde(rename = "resetsAt")]
|
|
#[ts(rename = "resetsAt")]
|
|
#[ts(type = "number | null")]
|
|
resets_at: Option<i64>,
|
|
},
|
|
}
|
|
|
|
/// A local image file successfully read for this exact image-generation request.
|
|
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq, Eq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(rename_all = "camelCase")]
|
|
pub struct ImageGenerationInputImage {
|
|
pub path: AbsolutePathBuf,
|
|
/// Lowercase SHA-256 of the file bytes read before image normalization.
|
|
pub sha256: String,
|
|
}
|
|
|
|
// Standalone image-generation item owned by the image extension. This is also
|
|
// the field-level representation exposed by app-server; core and rollout
|
|
// persistence only carry it inside an ExtensionItem envelope.
|
|
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[ts(rename_all = "camelCase")]
|
|
pub struct ImageGenerationItem {
|
|
pub id: String,
|
|
pub status: String,
|
|
pub revised_prompt: Option<String>,
|
|
#[serde(flatten)]
|
|
pub image: GeneratedImageRef,
|
|
#[serde(default)]
|
|
#[ts(optional)]
|
|
pub transparent_background: Option<bool>,
|
|
#[serde(default)]
|
|
pub failure: Option<ImageGenerationFailure>,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
#[ts(optional)]
|
|
pub saved_path: Option<AbsolutePathBuf>,
|
|
/// Observed local inputs for a completed generation, absent on older items.
|
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
|
#[ts(as = "Option<_>", optional)]
|
|
pub input_images: Vec<ImageGenerationInputImage>,
|
|
/// Exact nested ImageGen request ID retained only for in-process analytics.
|
|
///
|
|
/// This is deliberately excluded from the extension/app-server wire shape
|
|
/// and rollout persistence because it is not a client-facing item field.
|
|
#[serde(skip)]
|
|
#[schemars(skip)]
|
|
#[ts(skip)]
|
|
pub imagegen_request_id: Option<String>,
|
|
/// Backend generation ID for this exact image, retained only for in-process analytics.
|
|
#[serde(skip)]
|
|
#[schemars(skip)]
|
|
#[ts(skip)]
|
|
pub generation_id: Option<String>,
|
|
}
|
|
|
|
/// Either inline generated-image data or its durable attachment-store identity.
|
|
///
|
|
/// `File` must remain first so rollouts written during the migration, which contain both an empty
|
|
/// `result` and a `fileId`, retain the file reference when deserialized.
|
|
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
|
#[serde(untagged)]
|
|
#[ts(untagged)]
|
|
pub enum GeneratedImageRef {
|
|
File {
|
|
#[serde(rename = "fileId")]
|
|
#[ts(rename = "fileId")]
|
|
file_id: String,
|
|
},
|
|
Inline {
|
|
result: String,
|
|
},
|
|
}
|