fix(image_gen/codex): remove unsupported tool_choice from request payload (#19505)

The chatgpt.com/backend-api/codex backend 400s on every tool_choice
shape for the hosted image_generation tool — it looks up tool_choice as
a function name and never recognizes hosted-tool entries. Removing the
field from _build_responses_payload() lets the host model decide; the
instructions field nudges it toward the tool.

Salvaged from PR #19979 (originally targeted the old
client.responses.stream call, which no longer exists on upstream/main;
the live request now flows through _build_responses_payload + httpx in
_collect_image_b64).
This commit is contained in:
Tranquil-Flow 2026-07-13 15:23:05 +00:00 committed by Teknium
parent 776c43befe
commit 2bfe9fabbc
2 changed files with 13 additions and 8 deletions

View file

@ -307,11 +307,15 @@ def _build_responses_payload(
"background": "opaque",
"partial_images": 1,
}],
"tool_choice": {
"type": "allowed_tools",
"mode": "required",
"tools": [{"type": "image_generation"}],
},
# No ``tool_choice`` is sent: the chatgpt.com/backend-api/codex backend
# rejects every shape we have for forcing the hosted ``image_generation``
# tool. ``{"type": "allowed_tools", "mode": "required", "tools": [{"type":
# "image_generation"}]}`` (and the simpler ``{"type": "image_generation"}``
# form) both 400 with ``Tool choice 'image_generation' not found in 'tools'
# parameter`` — the backend looks up tool_choice as a *function* name and
# never recognizes hosted-tool entries. Letting the host model decide is
# the only shape Codex currently accepts; the ``instructions`` above are
# what nudge it toward the tool. See issue #19505.
"stream": True,
}

View file

@ -149,9 +149,10 @@ class TestGenerate:
assert captured["input"][0]["type"] == "message"
assert captured["input"][0]["role"] == "user"
assert captured["input"][0]["content"][0]["type"] == "input_text"
assert captured["tool_choice"]["type"] == "allowed_tools"
assert captured["tool_choice"]["mode"] == "required"
assert captured["tool_choice"]["tools"] == [{"type": "image_generation"}]
# Regression for #19505: the Codex backend 400s on every tool_choice
# shape we have for the hosted ``image_generation`` tool, so the
# provider must omit tool_choice entirely and rely on instructions.
assert "tool_choice" not in captured
tool = captured["tools"][0]
assert tool["type"] == "image_generation"