fix(aux): default Codex reasoning effort to medium when extra_body.reasoning.effort is falsy

auxiliary.<task>.extra_body.reasoning, but the new translation path in
_CodexCompletionsAdapter.create() reads the effort with
``reasoning_cfg.get("effort", "medium")``.  That returns the configured
value verbatim when the key is present, so ``effort: null`` /
``effort: ""`` (both common YAML shapes) flow through as
``{"effort": null, "summary": "auto"}`` and Codex rejects the request
with "Invalid value for parameter ``reasoning.effort``".

agent/transports/codex.py::build_kwargs() — which the new adapter is
documented to mirror — uses a truthy check (``elif
reasoning_config.get("effort"):``) so the same falsy values keep the
"medium" default.  Switch the auxiliary adapter to the same
``or "medium"`` truthy form so identical config produces identical
requests on both paths.

- [x] Two new regression tests cover ``effort: None`` and
  ``effort: ""`` and assert the request goes out as
  ``{"effort": "medium", "summary": "auto"}``.
- [x] Old behaviour fails the new tests (``{'effort': None} !=
  {'effort': 'medium'}``); fixed behaviour passes all 11 tests in the
  ``TestCodexAdapterReasoningTranslation`` class.
- [x] Adjacent suites green: ``tests/agent/test_auxiliary_client.py``
  (108 passed) and ``tests/agent/transports/test_codex_transport.py +
  test_chat_completions.py`` (73 passed).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
briandevans 2026-04-28 06:18:49 -07:00 committed by Teknium
parent 44cf33449d
commit 9e893d16d1
2 changed files with 30 additions and 1 deletions

View file

@ -1650,6 +1650,30 @@ class TestCodexAdapterReasoningTranslation:
)
assert "reasoning" not in captured
def test_reasoning_effort_null_falls_back_to_medium(self):
"""Parity with agent/transports/codex.py::build_kwargs() — falsy
``effort`` (None / empty / 0) keeps the default ``medium`` instead
of being forwarded to Codex. Codex rejects ``{"effort": null}``
with HTTP 400 (Invalid value for parameter `reasoning.effort`)."""
adapter, captured = self._build_adapter()
adapter.create(
messages=[{"role": "user", "content": "hi"}],
extra_body={"reasoning": {"effort": None}},
)
assert captured.get("reasoning") == {"effort": "medium", "summary": "auto"}
assert captured.get("include") == ["reasoning.encrypted_content"]
def test_reasoning_effort_empty_string_falls_back_to_medium(self):
"""Empty-string effort (e.g. ``effort: ""`` in YAML) is falsy in
the main-agent path's truthy check; mirror that here so the same
config produces the same result."""
adapter, captured = self._build_adapter()
adapter.create(
messages=[{"role": "user", "content": "hi"}],
extra_body={"reasoning": {"effort": ""}},
)
assert captured.get("reasoning") == {"effort": "medium", "summary": "auto"}
assert captured.get("include") == ["reasoning.encrypted_content"]
class TestVisionAutoSkipsKimiCoding: