mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
core: strip image detail from Responses Lite requests (#27246)
## Summary - Strip image `detail` fields from every Responses Lite request. - Apply stripping to message images and function/custom tool-output images. - Transform only the formatted request copy without mutating stored history. - Preserve image URLs byte-for-byte, including HTTP(S) URLs, without downloading, validating, or resizing them. - Preserve all image `detail` fields for non-Responses-Lite models. ## Motivation Responses Lite does not support image `detail` tags, so Codex must omit them whenever `model_info.use_responses_lite` is enabled. This transport requirement is independent of the `resize_all_images` feature. Stored history retains the original detail values. This keeps request-specific formatting isolated from conversation state and preserves the information for local image preparation and non-Responses-Lite requests. #### [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:
@@ -9,9 +9,11 @@ use codex_features::Feature;
|
||||
use codex_image_generation_extension::install as install_image_generation_extension;
|
||||
use codex_login::CodexAuth;
|
||||
use codex_protocol::config_types::WebSearchMode;
|
||||
use codex_protocol::models::ImageDetail;
|
||||
use codex_protocol::openai_models::InputModality;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
use codex_protocol::protocol::Op;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
use codex_web_search_extension::install as install_web_search_extension;
|
||||
use core_test_support::responses;
|
||||
use core_test_support::skip_if_no_network;
|
||||
@@ -52,6 +54,62 @@ fn has_hosted_tool(tools: &[Value], tool_type: &str) -> bool {
|
||||
.any(|tool| tool.get("type").and_then(Value::as_str) == Some(tool_type))
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn responses_lite_strips_data_image_detail_without_resize_all_images() -> Result<()> {
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let server = responses::start_mock_server().await;
|
||||
let response_mock = responses::mount_sse_once(
|
||||
&server,
|
||||
responses::sse(vec![
|
||||
responses::ev_response_created("resp-1"),
|
||||
responses::ev_completed("resp-1"),
|
||||
]),
|
||||
)
|
||||
.await;
|
||||
let image_url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGP4z8DwHwAFAAH/iZk9HQAAAABJRU5ErkJggg==";
|
||||
let mut builder = test_codex().with_model_info_override("gpt-5.4", |model_info| {
|
||||
model_info.use_responses_lite = true;
|
||||
configure_image_capable_model(model_info);
|
||||
});
|
||||
let test = builder.build(&server).await?;
|
||||
|
||||
test.codex
|
||||
.submit(Op::UserInput {
|
||||
items: vec![UserInput::Image {
|
||||
image_url: image_url.to_string(),
|
||||
detail: Some(ImageDetail::Original),
|
||||
}],
|
||||
final_output_json_schema: None,
|
||||
responsesapi_client_metadata: None,
|
||||
additional_context: Default::default(),
|
||||
thread_settings: Default::default(),
|
||||
})
|
||||
.await?;
|
||||
wait_for_event(&test.codex, |event| {
|
||||
matches!(event, EventMsg::TurnComplete(_))
|
||||
})
|
||||
.await;
|
||||
|
||||
let request = response_mock.single_request();
|
||||
let input = request.input();
|
||||
let image = input
|
||||
.iter()
|
||||
.filter_map(|item| item.get("content").and_then(Value::as_array))
|
||||
.flatten()
|
||||
.find(|item| item.get("type").and_then(Value::as_str) == Some("input_image"))
|
||||
.context("request should contain an image")?;
|
||||
assert_eq!(
|
||||
image,
|
||||
&serde_json::json!({
|
||||
"type": "input_image",
|
||||
"image_url": image_url
|
||||
})
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn responses_lite_uses_standalone_web_search_and_image_generation() -> Result<()> {
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
Reference in New Issue
Block a user