diff --git a/plugins/_oauth/helpers/codex.py b/plugins/_oauth/helpers/codex.py index ad32cd2714..a23fc4b29c 100644 --- a/plugins/_oauth/helpers/codex.py +++ b/plugins/_oauth/helpers/codex.py @@ -616,6 +616,7 @@ def fetch_models() -> list[str]: def prepare_responses_body(body: dict[str, Any], *, force_stream: bool) -> dict[str, Any]: normalized = dict(body) + normalized["input"] = normalize_responses_input(normalized.get("input")) normalized.setdefault("instructions", "") normalized.setdefault("store", False) if force_stream: @@ -624,6 +625,24 @@ def prepare_responses_body(body: dict[str, Any], *, force_stream: bool) -> dict[ return normalized + +def normalize_responses_input(value: Any) -> list[Any]: + if isinstance(value, list): + return value + if value is None: + return [] + if isinstance(value, dict): + return [value] + if isinstance(value, str): + if not value: + return [] + return [{"role": "user", "content": value}] + text = str(value) + if not text: + return [] + return [{"role": "user", "content": text}] + + def collect_completed_response(response: requests.Response) -> dict[str, Any]: latest_response: dict[str, Any] | None = None latest_error: Any = None diff --git a/tests/test_oauth_codex.py b/tests/test_oauth_codex.py index 4a2fb31e68..9fdbd74724 100644 --- a/tests/test_oauth_codex.py +++ b/tests/test_oauth_codex.py @@ -7,12 +7,19 @@ import sys import threading import time +import types from pathlib import Path import pytest import yaml -sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +PROJECT_ROOT = Path(__file__).resolve().parents[1] +if str(PROJECT_ROOT) not in sys.path: + sys.path.insert(0, str(PROJECT_ROOT)) +plugins_pkg = types.ModuleType("plugins") +plugins_pkg.__path__ = [str(PROJECT_ROOT / "plugins")] +sys.modules["plugins"] = plugins_pkg + from plugins._oauth.helpers import codex from plugins._oauth.helpers import routes from plugins._oauth.extensions.python._functions.models.get_api_key.end import ( @@ -70,6 +77,27 @@ def test_build_authorize_url_uses_existing_a0_origin_callback(monkeypatch): assert "originator=codex_cli_rs" in auth_url +def test_prepare_responses_body_wraps_string_input_for_codex_upstream(): + body = codex.prepare_responses_body( + { + "model": "gpt-5.2", + "input": "Hello", + "max_output_tokens": 100, + }, + force_stream=True, + ) + + assert body["input"] == [{"role": "user", "content": "Hello"}] + assert body["stream"] is True + assert "max_output_tokens" not in body + + +def test_prepare_responses_body_normalizes_empty_string_input_to_list(): + body = codex.prepare_responses_body({"input": ""}, force_stream=True) + + assert body["input"] == [] + + def test_chat_messages_to_response_body_extracts_instructions(): body = codex.chat_messages_to_response_body( {