k-krawczyk opened a new pull request, #25489:
URL: https://github.com/apache/camel/pull/25489

   # Description
   
   Adds the `image-generation` and `image-edit` operations to `camel-openai`, 
closing [CAMEL-23967](https://issues.apache.org/jira/browse/CAMEL-23967).
   
   ```java
   // generate a product image and store it
   from("direct:product-image")
       .setBody(simple("Studio photo of ${header.productName} on a white 
background"))
       .to("openai:image-generation?imageModel=gpt-image-1&imageSize=1024x1024")
       .to("file:target/images?fileName=${header.productName}.png");
   
   // edit an image coming from object storage
   from("aws2-s3:marketing-assets")
       .setHeader(OpenAIConstants.IMAGE_PROMPT, constant("Add a red SALE banner 
in the top-right corner"))
       .to("openai:image-edit?imageModel=gpt-image-1")
       .to("aws2-s3:marketing-assets-processed");
   ```
   
   ## Two deviations from the issue
   
   **`imageResponseFormat` has no default and is only sent when set.** The KDoc 
of `ImageGenerateParams` in the pinned SDK says the parameter is not supported 
by the GPT image models, which always return base64. Checking against the live 
API on 13 August 2026 turned out to be stricter still: `POST 
/v1/images/generations` answers `400 Unknown parameter: 'response_format'` for 
every model, and `/v1/models` no longer lists any DALL-E model. The option is 
kept because OpenAI-compatible providers still implement the older images API, 
where `url` is often the default — but a default value here would break every 
route against OpenAI, so there is none.
   
   **The body shape follows the response, not the option.** Base64 payloads are 
decoded into `byte[]`, URLs stay as `String`. A single image becomes the body 
directly and several images become a `List`, so the common case does not force 
routes to unwrap a one-element list.
   
   ## What it adds
   
   - `imageModel`, `imagePrompt`, `imageSize`, `imageQuality`, 
`imageResponseFormat`, `imageCount`, `imageBackground`, `imageOutputFormat`, 
`imageOutputCompression`, `imageStyle`, `imageModeration`, `imageInputFidelity` 
— each overridable per exchange by a header.
   - `image-edit` takes the image from the body as `File`, `Path`, 
`InputStream`, `byte[]`, or a `List` of those, since the GPT image models 
accept up to 16 reference images. An optional mask goes through 
`CamelOpenAIImageMask`.
   - `Content-Type` is set from the output format reported by the response, 
falling back to the requested one, so the result chains into `file:` or object 
storage unchanged.
   - The multipart parts of an edit declare their content type. The API 
validates the upload on that content type rather than on the file name, and the 
SDK leaves it as `text/plain` unless it is set, so an edit is rejected without 
this. It is resolved from the usual MIME type detection, then from the 
extension of a `File`/`Path` body, and falls back to `image/png` for anything 
the API does not accept.
   - Revised prompt and token usage as headers; `storeFullResponse=true` keeps 
the full SDK response in `CamelOpenAIImageResponse`.
   
   Left out, as the issue suggests: `createVariation` and the streaming 
variants.
   
   ## Testing
   
   `camel-test-infra-openai-mock` gained `whenImageGeneration()`, 
`whenImageEdit()`, `replyWithImage(byte[])`, `replyWithImageUrl(String)`, 
`withRevisedPrompt()`, `withImageOutputFormat()`, `withImageSize()`, 
`withImageUsage()` and `assertImageRequest()`. Image edit requests are 
multipart and the mock does not parse multipart — the same simplification the 
transcription handler already makes — so those expectations are matched in 
declaration order and the raw body is exposed to assertions, which is enough to 
verify that several images and a mask reach the wire.
   
   24 unit tests, no model and no GPU involved.
   
   Beyond the mock, both operations were also exercised against the real OpenAI 
API once, which is what surfaced the multipart content type and the state of 
`response_format`. That smoke test is not part of the contribution — there is 
no CI-suitable local image backend, as the issue notes — but the multipart 
content type is now asserted in the mock tests.
   
   _Reported by Claude Code on behalf of Karol Krawczyk_
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to