Avoid rendering generated images twice (#34378)

## What changed

- Tell the model that generated images are already displayed to the user and should not be repeated as Markdown images or file links.
- Keep generated-image artifact paths and output hints owned by the image generation extension.
- Centralize the availability check for the image generation tool across feature, provider, namespace-tool, model modality, and authentication requirements.

## Testing

- Verify artifact paths sanitize session and call identifiers.
- Verify the model-facing output hint reports that the generated image is already displayed.

GitOrigin-RevId: 6c865b6a96d6a71bb2c33246d1518a00e7c8b840
This commit is contained in:
Won Park
2026-07-20 16:47:03 +00:00
committed by copyberry
parent 9a7e823e5b
commit 7e51abbbd1
12 changed files with 99 additions and 95 deletions
@@ -429,11 +429,6 @@ mod tests {
async fn image_generation_publication_preserves_extension_saved_path() {
let (session, turn, rx) = crate::session::tests::make_session_and_context_with_rx().await;
let expected_path = test_path_buf("/tmp/extension-claimed.png").abs();
let default_path = crate::stream_events_utils::image_generation_artifact_path(
&turn.config.codex_home,
&session.thread_id.to_string(),
"call-image",
);
let emitter = CoreTurnItemEmitter {
session: Arc::downgrade(&session),
turn: Arc::downgrade(&turn),
@@ -498,6 +493,5 @@ mod tests {
assert_eq!(started_item, expected_started_item);
assert_eq!(completed_item, expected_completed_item);
assert!(!default_path.exists());
}
}
+27 -24
View File
@@ -364,33 +364,36 @@ fn agent_jobs_worker_tools_enabled(turn_context: &TurnContext) -> bool {
)
}
fn image_generation_runtime_enabled(turn_context: &TurnContext) -> bool {
(turn_context
.provider
.info()
.uses_openai_actor_authorization()
|| (turn_context.provider.info().requires_openai_auth
&& turn_context
.auth_manager
.as_deref()
.is_some_and(AuthManager::current_auth_uses_codex_backend)))
&& turn_context.provider.capabilities().image_generation
&& turn_context
.model_info
.input_modalities
.contains(&InputModality::Image)
}
fn standalone_image_generation_model_visible(turn_context: &TurnContext) -> bool {
if !image_generation_runtime_enabled(turn_context) || !namespace_tools_enabled(turn_context) {
return false;
}
turn_context
fn image_generation_available(turn_context: &TurnContext) -> bool {
if !turn_context
.config
.features
.get()
.enabled(Feature::ImageGeneration)
{
return false;
}
let capabilities = turn_context.provider.capabilities();
if !capabilities.image_generation || !capabilities.namespace_tools {
return false;
}
if !turn_context
.model_info
.input_modalities
.contains(&InputModality::Image)
{
return false;
}
let provider = turn_context.provider.info();
provider.uses_openai_actor_authorization()
|| (provider.requires_openai_auth
&& turn_context
.auth_manager
.as_deref()
.is_some_and(AuthManager::current_auth_uses_codex_backend))
}
fn wait_agent_timeout_options(turn_context: &TurnContext) -> WaitAgentTimeoutOptions {
@@ -996,7 +999,7 @@ fn append_extension_tool_executors(
continue;
}
if tool_name == ToolName::namespaced(IMAGE_GEN_NAMESPACE, IMAGEGEN_TOOL_NAME)
&& !standalone_image_generation_model_visible(turn_context)
&& !image_generation_available(turn_context)
{
continue;
}