mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
core: resize all history images behind a feature flag (#27247)
## Summary Adds complete client-side image preparation behind the default-off `resize_all_images` feature flag. When enabled, local image producers defer decoding and resizing. Images are prepared centrally before insertion into conversation history, covering user input, `view_image`, and structured tool-output images. ## Behavior - Processes base64 `data:` images in messages and function/custom tool outputs. - Leaves non-data URLs, including HTTP(S) URLs, unchanged. - Applies image-detail budgets: - `high` and omitted: 2048px maximum dimension and 2.5K 32px patches. - `original`: 6000px maximum dimension and 10K 32px patches. - `auto`: uses the same 2048px / 2.5K-patch budget as high. - `low`: unsupported and replaced with an actionable placeholder. - Preserves original image bytes when no resize or format conversion is needed. - Enforces the shared 1 GiB encoded and decoded data-URL sanity limits. - Replaces only an image that fails preparation, preserving sibling content and tool-output metadata. - Uses bounded placeholders distinguishing generic processing failures, oversized images, and unsupported `low` detail. - Prepares resumed and forked history before installing it as live history without modifying persisted rollouts. ## Flag-Off Behavior When `resize_all_images` is disabled: - Existing local user-input and `view_image` processing remains unchanged. - Existing decoding and error behavior remains unchanged. - Arbitrary tool-output images are not processed. - HTTP(S) image URLs continue to be forwarded unchanged. #### [git stack](https://github.com/magus/git-stack-cli) - ✅ `1` https://github.com/openai/codex/pull/27245 - 👉 `2` https://github.com/openai/codex/pull/27247 - ⏳ `3` https://github.com/openai/codex/pull/27246 - ⏳ `4` https://github.com/openai/codex/pull/27266
This commit is contained in:
committed by
GitHub
Unverified
parent
9d87b771ce
commit
a6f435ea94
@@ -105,8 +105,7 @@ async fn preserves_large_image_in_original_mode() {
|
||||
async fn data_url_processing_preserves_supported_source_bytes() {
|
||||
let image = ImageBuffer::from_pixel(64, 32, Rgba([10u8, 20, 30, 255]));
|
||||
let original_bytes = image_bytes(&image, ImageFormat::Png);
|
||||
let encoded = BASE64_STANDARD.encode(&original_bytes);
|
||||
let image_url = format!("data:image/png;base64,{encoded}")
|
||||
let image_url = data_url_from_bytes("image/png", &original_bytes)
|
||||
.replacen("data:", "DATA:", 1)
|
||||
.replacen(";base64,", ";BASE64,", 1);
|
||||
|
||||
@@ -123,8 +122,7 @@ async fn data_url_processing_preserves_supported_source_bytes() {
|
||||
async fn data_url_processing_converts_gif_to_png() {
|
||||
let image = ImageBuffer::from_pixel(64, 32, Rgba([10u8, 20, 30, 255]));
|
||||
let gif_bytes = image_bytes(&image, ImageFormat::Gif);
|
||||
let encoded = BASE64_STANDARD.encode(&gif_bytes);
|
||||
let image_url = format!("data:image/gif;base64,{encoded}");
|
||||
let image_url = data_url_from_bytes("image/gif", &gif_bytes);
|
||||
|
||||
let processed = load_data_url_for_prompt(&image_url, PromptImageMode::ResizeToFit)
|
||||
.expect("process GIF data URL");
|
||||
|
||||
@@ -40,11 +40,16 @@ pub struct EncodedImage {
|
||||
|
||||
impl EncodedImage {
|
||||
pub fn into_data_url(self) -> String {
|
||||
let encoded = BASE64_STANDARD.encode(&self.bytes);
|
||||
format!("data:{};base64,{encoded}", self.mime)
|
||||
data_url_from_bytes(&self.mime, &self.bytes)
|
||||
}
|
||||
}
|
||||
|
||||
/// Wraps image bytes in a data URL without decoding or validating them.
|
||||
pub fn data_url_from_bytes(mime: &str, bytes: &[u8]) -> String {
|
||||
let encoded = BASE64_STANDARD.encode(bytes);
|
||||
format!("data:{mime};base64,{encoded}")
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum PromptImageMode {
|
||||
ResizeToFit,
|
||||
|
||||
Reference in New Issue
Block a user