-
-
Notifications
You must be signed in to change notification settings - Fork 4.9k
fix(codex): preserve image content in tool outputs #2349
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
38cf661
37cfef3
bcd8672
726381c
831e937
0d5429d
14f1703
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,13 +121,42 @@ func ConvertOpenAIRequestToCodex(modelName string, inputRawJSON []byte, stream b | |
| case "tool": | ||
| // Handle tool response messages as top-level function_call_output objects | ||
| toolCallID := m.Get("tool_call_id").String() | ||
| content := m.Get("content").String() | ||
| content := m.Get("content") | ||
|
|
||
| // Create function_call_output object | ||
| funcOutput := []byte(`{}`) | ||
| funcOutput, _ = sjson.SetBytes(funcOutput, "type", "function_call_output") | ||
| funcOutput, _ = sjson.SetBytes(funcOutput, "call_id", toolCallID) | ||
| funcOutput, _ = sjson.SetBytes(funcOutput, "output", content) | ||
|
|
||
| // Handle content: can be string or array (e.g., with image_url items) | ||
| if content.Type == gjson.String { | ||
| funcOutput, _ = sjson.SetBytes(funcOutput, "output", content.String()) | ||
| } else if content.IsArray() { | ||
| // Build output array from content items | ||
| outputArr := []byte(`[]`) | ||
| items := content.Array() | ||
| for j := 0; j < len(items); j++ { | ||
| it := items[j] | ||
| t := it.Get("type").String() | ||
| switch t { | ||
| case "text": | ||
| outputPart := []byte(`{}`) | ||
| outputPart, _ = sjson.SetBytes(outputPart, "type", "input_text") | ||
| outputPart, _ = sjson.SetBytes(outputPart, "text", it.Get("text").String()) | ||
| outputArr, _ = sjson.SetRawBytes(outputArr, "-1", outputPart) | ||
| case "image_url": | ||
| // Handle image_url content in tool message | ||
| if u := it.Get("image_url.url"); u.Exists() { | ||
| outputPart := []byte(`{}`) | ||
| outputPart, _ = sjson.SetBytes(outputPart, "type", "input_image") | ||
| outputPart, _ = sjson.SetBytes(outputPart, "image_url", u.String()) | ||
| outputArr, _ = sjson.SetRawBytes(outputArr, "-1", outputPart) | ||
| } | ||
| } | ||
| } | ||
| funcOutput, _ = sjson.SetRawBytes(funcOutput, "output", outputArr) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This branch always rewrites array-based tool content into Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| out, _ = sjson.SetRawBytes(out, "input.-1", funcOutput) | ||
|
Comment on lines
128
to
217
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Throughout this It is highly recommended to implement error handling for these operations, at least by logging the errors. For example, you could change |
||
|
|
||
| default: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This branch now sets
function_call_output.outputonly when toolcontentis a string or an array. If a caller sends tool content as an object, number, boolean, ornull, the generatedfunction_call_outputhas nooutputfield at all, whereas the previous code always serializedcontentwith.String(). In those inputs, tool results are dropped (or the request is rejected as malformed), so this should include anelsefallback that preserves non-array payloads.Useful? React with 👍 / 👎.