Prepare Python SDK 0.144.4 stable release (#33213)

## What changed

- Mark `openai-codex` as stable and align its versioned runtime dependency with Codex CLI `0.144.4`.
- Regenerate the Python protocol models and notification registry from that runtime, exposing the latest requests, responses, notifications, and schema fields.
- Keep `ReasoningEffort` and `ThreadSource` as enum-style APIs while accepting unknown future wire values, and omit `last_turn_id` from the flat `thread_fork` helper.

## Testing

- Cover stable SDK/runtime version matching, forward-compatible enum parsing, and generated client method signatures.

GitOrigin-RevId: eaa616bcbfca4258f11274e12e7eefaa551110b7
This commit is contained in:
Ahmed Ibrahim
2026-07-15 02:43:31 +00:00
committed by copyberry
parent d88db19144
commit 3f74f00295
13 changed files with 1146 additions and 194 deletions
@@ -373,6 +373,7 @@ def test_schema_normalization_only_flattens_string_literal_oneofs(
"ExperimentalFeatureStage",
"ProcessOutputStream",
"CommandExecOutputStream",
"ConsumeAccountRateLimitResetCreditOutcome",
"AutoCompactTokenLimitScope",
]
@@ -501,32 +502,33 @@ def test_source_sdk_template_pins_published_runtime() -> None:
"dependencies": pyproject["project"]["dependencies"],
} == {
"sdk_template_version": "0.0.0-dev",
"runtime_pin": "0.137.0a4",
"runtime_pin": "0.144.4",
"dependencies": [
"pydantic>=2.12",
"openai-codex-cli-bin==0.137.0a4",
"openai-codex-cli-bin==0.144.4",
],
}
def test_source_sdk_package_declares_beta_documentation() -> None:
"""Public package metadata should link beta docs."""
def test_source_sdk_package_declares_stable_documentation() -> None:
"""Public package metadata should link stable docs."""
pyproject = tomllib.loads((ROOT / "pyproject.toml").read_text())
readme = (ROOT / "README.md").read_text()
assert {
"description": pyproject["project"]["description"],
"is_beta": "Development Status :: 4 - Beta" in pyproject["project"]["classifiers"],
"is_stable": "Development Status :: 5 - Production/Stable"
in pyproject["project"]["classifiers"],
"license": pyproject["project"]["license"],
"documentation": pyproject["project"]["urls"]["Documentation"],
"readme_is_beta": "# OpenAI Codex Python SDK (Beta)" in readme,
"readme_is_stable": "# OpenAI Codex Python SDK\n" in readme,
"local_license_file": (ROOT / "LICENSE").exists(),
} == {
"description": "Python SDK for Codex",
"is_beta": True,
"is_stable": True,
"license": "Apache-2.0",
"documentation": "https://github.com/openai/codex/tree/main/sdk/python/docs",
"readme_is_beta": True,
"readme_is_stable": True,
"local_license_file": False,
}
@@ -558,7 +560,7 @@ def test_release_metadata_retries_without_invalid_auth(
def test_runtime_setup_reads_independent_runtime_pin_and_release_tags() -> None:
"""Runtime package pins remain independent of the SDK beta version."""
"""Runtime package pins remain independent of the SDK template version."""
runtime_setup = _load_runtime_setup_module()
pyproject = tomllib.loads((ROOT / "pyproject.toml").read_text())
@@ -573,7 +575,7 @@ def test_runtime_setup_reads_independent_runtime_pin_and_release_tags() -> None:
} == {
"package_name": "openai-codex-cli-bin",
"sdk_template_version": "0.0.0-dev",
"runtime_pin": "0.137.0a4",
"runtime_pin": "0.144.4",
"normalized_release_version": "0.116.0a1",
"release_tag": "rust-v0.116.0-alpha.1",
}
@@ -777,7 +779,7 @@ def test_stage_sdk_release_preserves_reviewed_runtime_pin(tmp_path: Path) -> Non
script = _load_update_script_module()
staged = script.stage_python_sdk_package(
tmp_path / "sdk-stage",
"0.1.0b1",
"0.144.4",
)
pyproject = tomllib.loads((staged / "pyproject.toml").read_text())
@@ -787,18 +789,18 @@ def test_stage_sdk_release_preserves_reviewed_runtime_pin(tmp_path: Path) -> Non
"dependencies": pyproject["project"]["dependencies"],
} == {
"name": "openai-codex",
"version": "0.1.0b1",
"version": "0.144.4",
"dependencies": [
"pydantic>=2.12",
"openai-codex-cli-bin==0.137.0a4",
"openai-codex-cli-bin==0.144.4",
],
}
assert (
'__version__ = "0.1.0b1"'
'__version__ = "0.144.4"'
not in (staged / "src" / "openai_codex" / "__init__.py").read_text()
)
assert (
'client_version: str = "0.1.0b1"'
'client_version: str = "0.144.4"'
not in (staged / "src" / "openai_codex" / "client.py").read_text()
)
assert not any((staged / "src" / "openai_codex").glob("bin/**"))
@@ -811,23 +813,23 @@ def test_stage_sdk_release_replaces_existing_staging_dir(tmp_path: Path) -> None
old_file.parent.mkdir(parents=True)
old_file.write_text("stale")
staged = script.stage_python_sdk_package(staging_dir, "0.1.0b1")
staged = script.stage_python_sdk_package(staging_dir, "0.144.4")
assert staged == staging_dir
assert not old_file.exists()
def test_sdk_beta_release_can_pin_stable_runtime(tmp_path: Path) -> None:
def test_sdk_release_matches_stable_runtime(tmp_path: Path) -> None:
script = _load_update_script_module()
package_archive = _write_fake_codex_package_archive(tmp_path, script)
sdk_stage = script.stage_python_sdk_package(
tmp_path / "sdk-stage",
"0.1.0b1",
"0.144.4",
)
runtime_stage = script.stage_python_runtime_package(
tmp_path / "runtime-stage",
"0.137.0a4",
"0.144.4",
package_archive,
)
@@ -839,11 +841,11 @@ def test_sdk_beta_release_can_pin_stable_runtime(tmp_path: Path) -> None:
"runtime_version": runtime_pyproject["project"]["version"],
"sdk_dependencies": sdk_pyproject["project"]["dependencies"],
} == {
"sdk_version": "0.1.0b1",
"runtime_version": "0.137.0a4",
"sdk_version": "0.144.4",
"runtime_version": "0.144.4",
"sdk_dependencies": [
"pydantic>=2.12",
"openai-codex-cli-bin==0.137.0a4",
"openai-codex-cli-bin==0.144.4",
],
}
@@ -856,7 +858,7 @@ def test_stage_sdk_runs_type_generation_before_staging(tmp_path: Path) -> None:
"stage-sdk",
str(tmp_path / "sdk-stage"),
"--sdk-version",
"0.1.0b1",
"0.144.4",
]
)
@@ -887,7 +889,7 @@ def test_stage_sdk_runs_type_generation_before_staging(tmp_path: Path) -> None:
script.run_command(args, ops)
assert calls == ["generate_types", "stage_sdk:0.1.0b1"]
assert calls == ["generate_types", "stage_sdk:0.144.4"]
def test_stage_runtime_stages_package_without_type_generation(tmp_path: Path) -> None:
@@ -7,13 +7,19 @@ from openai_codex.generated.notification_registry import notification_turn_id
from openai_codex.generated.v2_all import (
AgentMessageDeltaNotification,
ApprovalsReviewer,
ReasoningEffort,
ReasoningEffortOption,
ThreadForkParams,
ThreadListParams,
ThreadResumeResponse,
ThreadStartParams,
ThreadTokenUsageUpdatedNotification,
TurnCompletedNotification,
TurnStartParams,
WarningNotification,
)
from openai_codex.models import Notification, UnknownNotification
from openai_codex.types import ThreadSource
ROOT = Path(__file__).resolve().parents[1]
@@ -31,6 +37,56 @@ def test_generated_v2_bundle_has_single_shared_plan_type_definition() -> None:
assert source.count("class PlanType(") == 1
def test_reasoning_effort_preserves_enum_constants_and_accepts_future_values() -> None:
"""Known effort members and new runtime values should share the enum-style API."""
known_option = ReasoningEffortOption.model_validate(
{"description": "Balanced", "reasoningEffort": "medium"}
)
future_option = ReasoningEffortOption.model_validate(
{"description": "Future", "reasoningEffort": "ultra"}
)
turn_params = TurnStartParams(
thread_id="thread-1",
input=[],
effort=ReasoningEffort.medium,
)
assert {
"known_member": ReasoningEffort.medium.value,
"known_option": known_option.reasoning_effort.value,
"future_option": future_option.reasoning_effort.value,
"turn_effort": _params_dict(turn_params)["effort"],
} == {
"known_member": "medium",
"known_option": "medium",
"future_option": "ultra",
"turn_effort": "medium",
}
def test_thread_source_preserves_enum_constants_and_accepts_future_values() -> None:
"""Known thread sources and new runtime values should share the enum-style API."""
start_params = ThreadStartParams(thread_source=ThreadSource.user)
fork_params = ThreadForkParams(
thread_id="thread-1",
thread_source=ThreadSource("future_source"),
)
assert {
"known_member": ThreadSource.user.value,
"subagent_member": ThreadSource.subagent.value,
"memory_member": ThreadSource.memory_consolidation.value,
"start_source": _params_dict(start_params)["threadSource"],
"fork_source": _params_dict(fork_params)["threadSource"],
} == {
"known_member": "user",
"subagent_member": "subagent",
"memory_member": "memory_consolidation",
"start_source": "user",
"fork_source": "future_source",
}
def test_thread_resume_response_accepts_auto_review_reviewer() -> None:
"""Generated response models should keep accepting the auto review enum value."""
response = ThreadResumeResponse.model_validate(
+1 -1
View File
@@ -40,7 +40,7 @@ def test_generated_files_are_up_to_date():
# Regenerate contract artifacts via the pinned runtime package, not a local
# app-server binary from the checkout or CI environment.
assert importlib.metadata.version("openai-codex-cli-bin") == "0.137.0a4"
assert importlib.metadata.version("openai-codex-cli-bin") == "0.144.4"
env = os.environ.copy()
env.pop("CODEX_EXEC_PATH", None)
python_bin = str(Path(sys.executable).parent)