Repository navigation
fix(translator): accept content-part arrays in function_call_output so tool images reach the model - #79
Merged
TriDefender merged 1 commit intoNov 14, 2026
Conversation
…o tool images reach the model
The Responses spec allows function_call_output.output to be a content-part array (OpenAI's own docs show {type:"input_image", image_url} inside a tool result so the model can see a screenshot the tool returned). The translator only accepted strings, so clients sending the array form (e.g. coding agents returning read_file image results) had every image silently degraded: the raw part array rode into the Chat tool-message content, and the downstream Chat-to-Anthropic toolResultContent mapper only knows image_url/video_url/file parts, so the unknown input_image parts became empty text blocks.
Normalize the output via toolOutputToChat(): strings pass through, arrays convert Responses parts (input_text/input_image/input_video/input_file and their already-Chat-shaped aliases) to Chat content parts, structured objects stringify. Unknown parts degrade to a text part carrying their JSON instead of being dropped. All-text arrays collapse to a plain string, so existing pure-text tool results keep the exact wire shape they had before.
The Chat->Anthropic hop already maps tool-message image_url parts onto Anthropic tool_result image blocks (base64 or URL source), so images now reach Anthropic-dialect upstreams end to end.
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.
fix(translator): accept content-part arrays in
function_call_outputso tool images reach the modelProblem
The Responses spec allows
function_call_output.outputto be a content-part array — OpenAI's own API docs show{type:"input_image", image_url}inside a tool result precisely so the model can look at a screenshot/image the tool returned. Coding agents (e.g. returningread_fileresults for image files) send exactly this shape.src/translator/responses-to-chat.tsonly acceptedstringoutput:With an array, the raw part array rode into the Chat tool-message
contentverbatim, and the downstream Chat→AnthropictoolResultContent()mapper only knowsimage_url/video_url/fileparts — the Responses-dialectinput_imageparts fell through to the unknown-part fallback and became empty text blocks. Every image in a tool result was silently dropped; the model received no trace of it.Fix
Normalize the output with a new
toolOutputToChat():outputPartsToChat()maps Responses parts (input_text,input_imagewithimage_url: string | {url},input_video,input_file) and their already-Chat-shaped aliases onto Chat content parts; unknown parts degrade to a text part carrying their JSON instead of being dropped. All-text arrays collapse to a plain string, so pure-text tool results keep their exact previous shape.No downstream changes needed: the Chat→Anthropic hop already maps tool-message
image_urlparts onto Anthropictool_resultimage blocks (base64 or URL source), so images now reach Anthropic-dialect upstreams end to end.Tests
responses-to-chat.test.ts: array output (input_text+input_image) → Chat tool message withimage_urlpart; structured (non-array, non-string) output → stringified.openai-to-anthropic.test.ts: end-to-end Responses→Chat→Anthropic —input_imagein a tool output arrives as a base64 image block inside thetool_result.123 pass / 0 failacross the two touched files;bun x tsc --noEmitclean.Evidence (live)
Sent a 64×64 PNG data-URL as
input_imageinside afunction_call_outputto a build running this fix, via/v1/responses→ Anthropic-dialect upstream: the model's reasoning cites "The image shows a solid red square." and the final answer is "Red". With the unfixed translator the same request produced an answer with no knowledge of the image (empty text block reached the upstream).