Skip to content

Add feature-gated standalone image generation extension#24723

Merged
won-openai merged 6 commits into
mainfrom
imagegen_extension
May 28, 2026
Merged

Add feature-gated standalone image generation extension#24723
won-openai merged 6 commits into
mainfrom
imagegen_extension

Conversation

@won-openai
Copy link
Copy Markdown
Collaborator

@won-openai won-openai commented May 27, 2026

Why

Add a standalone image generation path that can be exercised independently of hosted Responses image generation, while retaining the hosted tool as fallback unless the extension is actually available to the model.

What changed

  • Added the codex-image-generation-extension crate with standalone generate/edit execution, prior-image selection for edits, model-visible image output, and local generated-image persistence.
  • Installed the extension in app-server behind the disabled-by-default imagegenext feature and backend eligibility checks.
  • Updated core tool planning so eligible image_gen.imagegen exposure replaces hosted image_generation, while unavailable configurations retain hosted fallback.
  • Added coverage for extension behavior, edit history reuse, feature gating, auth eligibility, and hosted-tool replacement.
  • The extension is installed through app-server only in this PR; other execution paths retain hosted image generation because hosted replacement occurs only when the standalone executor is actually registered and model-visible.
  • The initial extension contract intentionally fixes the image model to gpt-image-2 and uses automatic image parameters.
  • Native generated-image history/card parity and rollout persistence cleanup are intentionally deferred follow-up work.

Validation

  • just test -p codex-image-generation-extension
  • just test -p codex-features
  • just test -p codex-core hosted_tools_follow_provider_auth_model_and_config_gates
  • just test -p codex-app-server
  • just fix -p codex-image-generation-extension -p codex-features -p codex-core -p codex-app-server
  • just fmt
  • just bazel-lock-update
  • just bazel-lock-check

@won-openai won-openai requested a review from a team as a code owner May 27, 2026 07:47
@@ -0,0 +1,11 @@
The `image_gen.imagegen` tool enables image generation from descriptions and editing of existing images based on specific instructions. Use it when:
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

placeholder, subject to change

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly not sure we need a doc file then... just drop it

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

placeholder as in we need to change the guidelines later depending on how we want the model to use this image gen tool, we should still give it guidelines on generate and edit etc bc the model isn't trained to do it

Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ce9ab1187e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +342 to +345
fn standalone_image_generation_model_visible(turn_context: &TurnContext) -> bool {
image_generation_runtime_enabled(turn_context)
&& turn_context.features.get().enabled(Feature::ImageGenExt)
&& namespace_tools_enabled(turn_context)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate imagegenext behind image_generation

When a user disables [features].image_generation but enables [features].imagegenext, this predicate still returns true for ChatGPT auth on an image-capable OpenAI model, so append_extension_tool_executors exposes image_gen.imagegen even though the stable image generation kill switch is off. The existing hosted path used image_generation_tool_enabled, so this regresses configurations that intentionally disable all model image-generation tools; include Feature::ImageGeneration in the standalone visibility check as well.

Useful? React with 👍 / 👎.

Comment on lines +371 to +374
ResponseInputItem::FunctionCallOutput {
call_id: call_id.to_string(),
output: FunctionCallOutputPayload {
body: FunctionCallOutputBody::ContentItems(content),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Surface standalone generated images to clients

When the standalone image tool succeeds, the image is only recorded as a FunctionCallOutput for the follow-up model request; app-server thread reconstruction ignores ResponseItem::FunctionCallOutput and only creates visible image-generation thread items from ImageGenerationBegin/End events. Since the new tool instructions tell the model to say nothing after generation, users in the app/TUI can get a successful generation with no visible image or saved-path item, so this path should emit/reuse image-generation events or otherwise publish the generated artifact to the client.

Useful? React with 👍 / 👎.

Comment on lines +349 to +353
impl ToolOutput for GeneratedImageOutput {
/// Avoids copying image bytes into tool-call telemetry.
fn log_preview(&self) -> String {
"[generated image]".to_string()
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid piping generated images into hooks

When PostToolUse hooks are configured, the default CoreToolRuntime::post_tool_use_payload fallback serializes this output's to_response_item body because GeneratedImageOutput does not override post_tool_use_response; that includes the full data:image/png;base64,... payload for every generated image. Multi-MB image results can make hook stdin very large or expose image bytes to hooks despite the telemetry preview being redacted, so return a small hook-facing response (for example the saved path/hint) instead of letting the default fallback serialize the image content.

Useful? React with 👍 / 👎.

Comment thread codex-rs/ext/image-generation/src/tool.rs Outdated
Comment thread codex-rs/ext/image-generation/src/backend.rs Outdated
Comment thread codex-rs/ext/image-generation/src/extension.rs Outdated
Comment thread codex-rs/ext/image-generation/src/extension.rs Outdated
use tracing::warn;

const MULTI_AGENT_V2_NAMESPACE_DESCRIPTION: &str = "Tools for spawning and managing sub-agents.";
const IMAGE_GEN_NAMESPACE: &str = "image_gen";
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the plan to drop this? (and drop the old tool)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

once the standalone path is ready to replace the hosted tool, I plan to remove the hosted tool and this replacement detection together

Comment thread codex-rs/core/src/tools/spec_plan_tests.rs Outdated
}

/// Returns generated bytes and persisted-artifact context for the model's follow-up response.
fn to_response_item(&self, call_id: &str, _payload: &ToolPayload) -> ResponseInputItem {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OOC do you also plan to emit events after this? FunctionCallOutput might not be rich enough? Not sure what is the product expecting

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya i am keeping this PR scoped to the standalone extension and fallback wiring, and will handle event emission in a follow-up PR

@@ -0,0 +1,11 @@
The `image_gen.imagegen` tool enables image generation from descriptions and editing of existing images based on specific instructions. Use it when:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly not sure we need a doc file then... just drop it

Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d121f9377a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread codex-rs/Cargo.toml
Comment thread codex-rs/ext/image-generation/src/tool.rs Outdated
Copy link
Copy Markdown
Collaborator

@jif-oai jif-oai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a test or an eval to prove equivalence with the original tool?

Comment thread codex-rs/ext/image-generation/src/tool.rs
.await;
image_generation.assert_visible_contains(&["image_generation"]);

let extension_flag_without_imagegen_tool = probe(|turn| {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only covers the fallback when imagegenext is on but the executor is absent. The replacement path itself is untested now

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: doing as follow-up / as the need comes to invest time in making sure we are at parity

Copy link
Copy Markdown
Collaborator

@jif-oai jif-oai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok after my comment

if role != "user" {
return None;
}
let images = content
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reverses the user-visible attachment order before calling the edit API. If the user/model prompt says “edit the first image” after uploading [A, B], we now send [B, A], so positional references can target the wrong image. I guess this is a big deal but I'm not sure

@won-openai won-openai merged commit ecb41fc into main May 28, 2026
46 checks passed
@won-openai won-openai deleted the imagegen_extension branch May 28, 2026 18:44
@github-actions github-actions Bot locked and limited conversation to collaborators May 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants