mirror of
https://github.com/openai/codex.git
synced 2026-10-27 18:48:37 +00:00
Store generated image items as attachment references (#54398)
## What changed - Upload generated images to the attachment store and expose `fileId` in image-generation items when available, with inline `result` fallback on upload or decoding failure. - Preserve file references through legacy events, persisted rollouts, thread history, and task output summaries. Keep model-facing image preparation separate. - Add attachment request tags and mark generated-image uploads with `usage=image_gen`, preserving the thread's ephemeral setting. - Update public schemas and SDK types to accept either image representation, retain the Python `ImageGenerationThreadItem` alias, and prefer `fileId` when reading records containing both fields. ## Testing Add coverage for file-backed generation and rollout persistence, legacy history replay, inline and transitional serialization, task output visibility, and Python SDK alias compatibility. GitOrigin-RevId: f7a2bb5707e2f277348a547a988bc33c8e96d891
This commit is contained in:
committed by
copyberry
parent
1ef30bcbe7
commit
aabf13307a
@@ -1,5 +1,6 @@
|
||||
//! Storage-neutral attachment persistence interfaces.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
@@ -42,6 +43,8 @@ pub struct UploadRequest {
|
||||
pub ephemeral: bool,
|
||||
/// Optional name associated with the attachment.
|
||||
pub file_name: Option<String>,
|
||||
/// Caller-supplied tags used by storage backends for policy decisions.
|
||||
pub tags: HashMap<String, String>,
|
||||
/// Attachment bytes to persist.
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
@@ -53,16 +56,19 @@ impl fmt::Debug for UploadRequest {
|
||||
.field("thread_id", &self.thread_id)
|
||||
.field("ephemeral", &self.ephemeral)
|
||||
.field("file_name", &self.file_name)
|
||||
.field("tags", &self.tags)
|
||||
.field("data", &"<redacted>")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Parameters supplied to [`AttachmentStore::resolve`].
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct ResolveRequest<'a> {
|
||||
/// Identifier assigned by the attachment store.
|
||||
pub file_id: &'a str,
|
||||
/// Caller-supplied tags used by storage backends for policy decisions.
|
||||
pub tags: HashMap<String, String>,
|
||||
/// Minimum remaining lifetime required for the returned file URL.
|
||||
///
|
||||
/// When absent, implementations must omit the file URL and may return cached metadata. When
|
||||
|
||||
@@ -9,6 +9,7 @@ fn attachment_debug_output_redacts_bytes() {
|
||||
thread_id: "thread-1".to_string(),
|
||||
ephemeral: false,
|
||||
file_name: Some("image.png".to_string()),
|
||||
tags: HashMap::new(),
|
||||
data: b"secret".to_vec(),
|
||||
};
|
||||
let result = UploadResult::Inline {
|
||||
@@ -18,7 +19,7 @@ fn attachment_debug_output_redacts_bytes() {
|
||||
assert_eq!(
|
||||
(format!("{request:?}"), format!("{result:?}")),
|
||||
(
|
||||
r#"UploadRequest { thread_id: "thread-1", ephemeral: false, file_name: Some("image.png"), data: "<redacted>" }"#.to_string(),
|
||||
r#"UploadRequest { thread_id: "thread-1", ephemeral: false, file_name: Some("image.png"), tags: {}, data: "<redacted>" }"#.to_string(),
|
||||
r#"Inline { bytes: "<redacted>" }"#.to_string(),
|
||||
)
|
||||
);
|
||||
@@ -52,6 +53,7 @@ async fn inline_store_preserves_image_bytes() {
|
||||
thread_id: "thread-1".to_string(),
|
||||
ephemeral: false,
|
||||
file_name: Some(file_name.to_string()),
|
||||
tags: HashMap::new(),
|
||||
data: data.to_vec(),
|
||||
})
|
||||
.await
|
||||
@@ -70,6 +72,7 @@ async fn inline_store_cannot_resolve_file_references() {
|
||||
let error = InlineAttachmentStore
|
||||
.resolve(ResolveRequest {
|
||||
file_id: "file_123",
|
||||
tags: HashMap::new(),
|
||||
download_url_ttl: None,
|
||||
})
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user