[codex] Accept string input for Python turns (#23162)

## Summary
- Allow thread.turn and turn.steer, including async variants, to accept
RunInput so plain strings work alongside typed input objects.
- Export RunInput and update the SDK artifact generator so regenerated
turn methods keep the same signature and normalization.
- Update docs, examples, notebook cells, and tests to use string
shorthand for text-only turns while keeping typed inputs for multimodal
input.

## Validation
- uv run --extra dev ruff format .
- uv run --extra dev ruff check --output-format=github .
- python3 -m py_compile sdk/python/src/openai_codex/__init__.py
sdk/python/src/openai_codex/api.py
sdk/python/src/openai_codex/_inputs.py
sdk/python/scripts/update_sdk_artifacts.py
sdk/python/tests/test_public_api_signatures.py
sdk/python/tests/test_app_server_streaming.py
sdk/python/tests/test_app_server_turn_controls.py
sdk/python/tests/test_real_app_server_integration.py
- python3 -c "import json;
json.load(open('sdk/python/notebooks/sdk_walkthrough.ipynb'))"
- sdk/python/.venv/bin/python -c "import inspect, openai_codex; from
openai_codex import Thread, AsyncThread, TurnHandle, AsyncTurnHandle,
RunInput; funcs=[Thread.run, Thread.turn, AsyncThread.run,
AsyncThread.turn, TurnHandle.steer, AsyncTurnHandle.steer]; assert
all(inspect.signature(fn).parameters['input'].annotation == 'RunInput'
for fn in funcs); assert RunInput is openai_codex.RunInput"
This commit is contained in:
Ahmed Ibrahim
2026-05-17 09:05:44 -07:00
committed by GitHub
parent 0a83353ca3
commit e7bffc5a20
31 changed files with 171 additions and 134 deletions

View File

@@ -14,6 +14,7 @@ from .api import (
InputItem,
LocalImageInput,
MentionInput,
RunInput,
SkillInput,
TextInput,
Thread,
@@ -54,6 +55,7 @@ __all__ = [
"TurnResult",
"Input",
"InputItem",
"RunInput",
"TextInput",
"ImageInput",
"LocalImageInput",

View File

@@ -12,7 +12,7 @@ from ._approval_mode import (
from ._initialize_metadata import validate_initialize_metadata
from ._inputs import (
ImageInput as ImageInput,
Input,
Input as Input,
InputItem as InputItem,
LocalImageInput as LocalImageInput,
MentionInput as MentionInput,
@@ -534,7 +534,7 @@ class Thread:
summary: ReasoningSummary | None = None,
) -> TurnResult:
turn = self.turn(
_normalize_run_input(input),
input,
approval_mode=approval_mode,
cwd=cwd,
effort=effort,
@@ -554,7 +554,7 @@ class Thread:
# BEGIN GENERATED: Thread.flat_methods
def turn(
self,
input: Input,
input: RunInput,
*,
approval_mode: ApprovalMode | None = None,
cwd: str | None = None,
@@ -566,7 +566,7 @@ class Thread:
service_tier: str | None = None,
summary: ReasoningSummary | None = None,
) -> TurnHandle:
wire_input = _to_wire_input(input)
wire_input = _to_wire_input(_normalize_run_input(input))
approval_policy, approvals_reviewer = _approval_mode_override_settings(approval_mode)
params = TurnStartParams(
thread_id=self.id,
@@ -617,7 +617,7 @@ class AsyncThread:
summary: ReasoningSummary | None = None,
) -> TurnResult:
turn = await self.turn(
_normalize_run_input(input),
input,
approval_mode=approval_mode,
cwd=cwd,
effort=effort,
@@ -637,7 +637,7 @@ class AsyncThread:
# BEGIN GENERATED: AsyncThread.flat_methods
async def turn(
self,
input: Input,
input: RunInput,
*,
approval_mode: ApprovalMode | None = None,
cwd: str | None = None,
@@ -650,7 +650,7 @@ class AsyncThread:
summary: ReasoningSummary | None = None,
) -> AsyncTurnHandle:
await self._codex._ensure_initialized()
wire_input = _to_wire_input(input)
wire_input = _to_wire_input(_normalize_run_input(input))
approval_policy, approvals_reviewer = _approval_mode_override_settings(approval_mode)
params = TurnStartParams(
thread_id=self.id,
@@ -694,8 +694,12 @@ class TurnHandle:
thread_id: str
id: str
def steer(self, input: Input) -> TurnSteerResponse:
return self._client.turn_steer(self.thread_id, self.id, _to_wire_input(input))
def steer(self, input: RunInput) -> TurnSteerResponse:
return self._client.turn_steer(
self.thread_id,
self.id,
_to_wire_input(_normalize_run_input(input)),
)
def interrupt(self) -> TurnInterruptResponse:
return self._client.turn_interrupt(self.thread_id, self.id)
@@ -730,12 +734,12 @@ class AsyncTurnHandle:
thread_id: str
id: str
async def steer(self, input: Input) -> TurnSteerResponse:
async def steer(self, input: RunInput) -> TurnSteerResponse:
await self._codex._ensure_initialized()
return await self._codex._client.turn_steer(
self.thread_id,
self.id,
_to_wire_input(input),
_to_wire_input(_normalize_run_input(input)),
)
async def interrupt(self) -> TurnInterruptResponse: