Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions plugins/_oauth/helpers/codex.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand Down
30 changes: 29 additions & 1 deletion tests/test_oauth_codex.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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(
{
Expand Down