Repository navigation
fix(xai): GIF attachments reach Grok as PNG instead of being silently stripped (port opencode#53787) - #135372
Open
teknium1 wants to merge 1 commit into
Open
fix(xai): GIF attachments reach Grok as PNG instead of being silently stripped (port opencode#53787)#135372teknium1 wants to merge 1 commit into
teknium1 wants to merge 1 commit into
Conversation
… dropped Port from anomalyco/opencode#53787: only send png, jpeg and webp images to xAI. xAI decodes only JPG/PNG/WebP/ICO. A GIF input_image answers HTTP 400 invalid_image on both Responses and Chat Completions; the corrupt-image recovery then strips the image from the retry, so the turn "succeeds" and the model answers as if nothing was attached (live: grok-4.7 replied NOIMAGE 3/3 for a solid-green GIF). The Responses converter is the seam every xAI image crosses (user turns, history replay, tool results, auxiliary vision calls), and it already knows the issuer. On the xai_responses issuer GIF joins the rejected set and is re-encoded to PNG through the same Pillow transcoder native attachments use; SVG keeps its rasterizer. Other backends still receive the original GIF.
૮ >ﻌ< ა ci reviewran on a2f5a68 — fix(xai): GIF attachments reach Grok as PNG instead of being debug infoCI timingsCI timings · View report · View jobWall time 6m49s vs 45m13s (-84.9%). 8 job(s) slower, 7 faster, 1 unchanged.
|
|
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GIF images attached to an xAI (Grok) turn now reach the model as PNG. Before this, they were silently dropped and the model answered as if nothing had been attached.
What changes
agent/codex_responses_adapter.py: on thexai_responsesissuer,image/gifjoins the inline subtypes the converter rejects, and a rejected inline raster is re-encoded to PNG with the Pillow transcoder native attachments already use (agent.image_routing._transcode_to_png). SVG keeps its rasterizer. If an image can't be re-encoded, it gets the existing text placeholder._chat_content_to_responses_parts/_tool_output_items, so user turns, replayed history,vision_analyzetool results and auxiliary Responses calls all get the same handling.tools/vision_tools_image_prep.unsupported_inline_image_media_typetakes an optionalalso_rejectedset for per-backend refusals. The default behavior is unchanged.Root cause
xAI decodes only JPG/PNG/WebP/ICO, and a GIF
input_imagegets HTTP 400invalid_image. Hermes classifies that 400 asimage_corrupt(_IMAGE_CORRUPT_PATTERNS, #69078) and strips the image from the retry. The retried turn succeeds, so the user sees an answer with no error, but the model never saw the image.Validation
/v1/responses(stream + non-stream) and grok-4.20/v1/chat/completions, GIF partDownloaded response does not contain a valid JPG, PNG, WebP, or ICO image.hermes chat -q … --image solid-green.gif(providerxai, modelgrok-4.7), neutral filename, "do not use tools"HERMES_DUMP_REQUESTS=1) of the user turninput_image data:image/gif, then attempt 2 a text-only string (image stripped)input_image data:image/pngtest_xai_gif_is_reencoded_to_png_and_other_backends_keep_itgit show origin/main:copies)tests/agent/test_codex_responses_adapter.py,test_anthropic_adapter.py,test_image_routing.py,tests/tools/test_vision_tools.pytests/agent/transports/shows the same 70 failures on a pristineorigin/mainarchive as on this branch in this host's environment (provider-plugin snapshot/guard environment), so they are unrelated to this diff and CI is the judge.Live probe cost: ~12 xAI calls on grok-4.7 / grok-4.20 at ~16k input tokens each, well under $0.50.
Source
Ported from anomalyco/opencode#53787 ("only send png, jpeg and webp images to xAI"). OpenCode replaces the GIF with an
ERROR: Cannot read …text part at its model-request layer. Hermes re-encodes it to PNG at the Responses wire seam instead, so the model still sees the image. Hermes also already owns the transcoder and the per-backend placeholder seam (#29711), so the port only extends that seam to accept a per-issuer rejected set.Infographic