mirror of
https://github.com/openai/codex.git
synced 2026-10-16 16:58:46 +00:00
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:
@@ -1,4 +1,4 @@
|
||||
# OpenAI Codex Python SDK (Beta)
|
||||
# OpenAI Codex Python SDK
|
||||
|
||||
Build Python applications that start Codex threads, run turns, stream progress,
|
||||
and control workspace access.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# OpenAI Codex Python SDK (Beta) - API Reference
|
||||
# OpenAI Codex Python SDK - API Reference
|
||||
|
||||
Public surface of `openai_codex` for Codex workflows.
|
||||
|
||||
This SDK is in beta. Public APIs may change before `1.0`. Turn streams are routed by turn ID so one client can consume multiple active turns concurrently.
|
||||
Turn streams are routed by turn ID so one client can consume multiple active turns concurrently.
|
||||
Thread starts default to `ApprovalMode.auto_review`; turn starts accept an optional `approval_mode` override.
|
||||
|
||||
## Package Entry
|
||||
|
||||
@@ -2,15 +2,13 @@
|
||||
|
||||
## Is the Python SDK stable?
|
||||
|
||||
`openai-codex` is a public beta. Install it with
|
||||
`pip install openai-codex`; public APIs may change before `1.0`. While beta
|
||||
releases are the only published SDK releases, pip selects the latest beta.
|
||||
After a stable release exists, pass `--pre` to opt into newer prereleases.
|
||||
`openai-codex` publishes stable releases. Install the latest one with
|
||||
`pip install openai-codex`.
|
||||
|
||||
## Why does the SDK install a runtime package?
|
||||
|
||||
The SDK and runtime packages are versioned independently. Each SDK release
|
||||
pins and installs one compatible runtime dependency automatically.
|
||||
The SDK version tracks the corresponding Codex CLI release. Each SDK release
|
||||
pins and installs its matching runtime dependency automatically.
|
||||
|
||||
## Thread vs turn
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Getting Started
|
||||
|
||||
This guide gets a published OpenAI Codex Python SDK beta installation running
|
||||
This guide gets a published OpenAI Codex Python SDK installation running
|
||||
with a multi-turn thread.
|
||||
|
||||
## 1. Install
|
||||
@@ -16,10 +16,8 @@ Requirements:
|
||||
- Python `>=3.10`
|
||||
- An existing Codex account session, or one of the login flows below
|
||||
|
||||
The SDK installs its compatible `openai-codex-cli-bin` runtime dependency
|
||||
automatically. While beta releases are the only published SDK releases, this
|
||||
normal install command selects the latest beta. After a stable release exists,
|
||||
use `pip install --pre openai-codex` to opt into a newer prerelease.
|
||||
The SDK installs its matching `openai-codex-cli-bin` runtime dependency
|
||||
automatically. SDK release versions track the corresponding Codex CLI release.
|
||||
|
||||
## 2. Authenticate When Needed
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ multimodal or structured input lists.
|
||||
- Python `>=3.10`
|
||||
- Install the SDK for the same Python interpreter you will use to run examples
|
||||
|
||||
Install the published beta:
|
||||
Install the published SDK:
|
||||
|
||||
```bash
|
||||
python -m pip install openai-codex
|
||||
|
||||
@@ -12,11 +12,11 @@ license = "Apache-2.0"
|
||||
authors = [{ name = "OpenAI" }]
|
||||
keywords = ["codex", "sdk", "llm", "ai", "agents"]
|
||||
classifiers = [
|
||||
"Development Status :: 4 - Beta",
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
]
|
||||
dependencies = ["pydantic>=2.12", "openai-codex-cli-bin==0.137.0a4"]
|
||||
dependencies = ["pydantic>=2.12", "openai-codex-cli-bin==0.144.4"]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/openai/codex"
|
||||
@@ -65,10 +65,10 @@ combine-as-imports = true
|
||||
|
||||
[tool.uv]
|
||||
exclude-newer = "7 days"
|
||||
exclude-newer-package = { openai-codex-cli-bin = "2026-06-03T19:00:00Z" }
|
||||
exclude-newer-package = { openai-codex-cli-bin = "2026-07-15T01:00:00Z" }
|
||||
index-strategy = "first-index"
|
||||
|
||||
[tool.uv.pip]
|
||||
exclude-newer = "7 days"
|
||||
exclude-newer-package = { openai-codex-cli-bin = "2026-06-03T19:00:00Z" }
|
||||
exclude-newer-package = { openai-codex-cli-bin = "2026-07-15T01:00:00Z" }
|
||||
index-strategy = "first-index"
|
||||
|
||||
@@ -616,6 +616,8 @@ def generate_v2_all(schema_dir: Path) -> None:
|
||||
cwd=sdk_root(),
|
||||
)
|
||||
_require_nullable_chatgpt_account_email(out_path)
|
||||
_preserve_reasoning_effort_enum(out_path)
|
||||
_preserve_thread_source_enum(out_path)
|
||||
_normalize_generated_timestamps(out_path)
|
||||
|
||||
|
||||
@@ -643,6 +645,66 @@ def _require_nullable_chatgpt_account_email(out_path: Path) -> None:
|
||||
out_path.write_text(source[:class_start] + class_source + source[class_end:])
|
||||
|
||||
|
||||
def _preserve_reasoning_effort_enum(out_path: Path) -> None:
|
||||
"""Keep the public effort constants while accepting future wire values."""
|
||||
source = out_path.read_text()
|
||||
class_start = source.find("class ReasoningEffort(RootModel[str]):")
|
||||
if class_start == -1:
|
||||
raise RuntimeError("Generated SDK is missing the open ReasoningEffort model")
|
||||
class_end = source.find("\n\nclass ", class_start)
|
||||
if class_end == -1:
|
||||
class_end = len(source)
|
||||
|
||||
class_source = source[class_start:class_end]
|
||||
if "min_length=1" not in class_source:
|
||||
raise RuntimeError("Generated ReasoningEffort did not preserve the non-empty constraint")
|
||||
open_enum = """class ReasoningEffort(str, Enum):
|
||||
none = "none"
|
||||
minimal = "minimal"
|
||||
low = "low"
|
||||
medium = "medium"
|
||||
high = "high"
|
||||
xhigh = "xhigh"
|
||||
|
||||
@classmethod
|
||||
def _missing_(cls, value: object) -> ReasoningEffort | None:
|
||||
if not isinstance(value, str) or not value:
|
||||
return None
|
||||
member = str.__new__(cls, value)
|
||||
member._name_ = value
|
||||
member._value_ = value
|
||||
return member
|
||||
"""
|
||||
out_path.write_text(source[:class_start] + open_enum + source[class_end:])
|
||||
|
||||
|
||||
def _preserve_thread_source_enum(out_path: Path) -> None:
|
||||
"""Keep the public thread-source constants while accepting future wire values."""
|
||||
source = out_path.read_text()
|
||||
class_start = source.find("class ThreadSource(RootModel[str]):")
|
||||
if class_start == -1:
|
||||
raise RuntimeError("Generated SDK is missing the open ThreadSource model")
|
||||
class_end = source.find("\n\nclass ", class_start)
|
||||
if class_end == -1:
|
||||
class_end = len(source)
|
||||
|
||||
open_enum = """class ThreadSource(str, Enum):
|
||||
user = "user"
|
||||
subagent = "subagent"
|
||||
memory_consolidation = "memory_consolidation"
|
||||
|
||||
@classmethod
|
||||
def _missing_(cls, value: object) -> ThreadSource | None:
|
||||
if not isinstance(value, str):
|
||||
return None
|
||||
member = str.__new__(cls, value)
|
||||
member._name_ = value
|
||||
member._value_ = value
|
||||
return member
|
||||
"""
|
||||
out_path.write_text(source[:class_start] + open_enum + source[class_end:])
|
||||
|
||||
|
||||
def _notification_specs(schema_dir: Path) -> list[tuple[str, str]]:
|
||||
"""Map each server notification method to its generated payload model class."""
|
||||
server_notifications = json.loads((schema_dir / "ServerNotification.json").read_text())
|
||||
@@ -1217,7 +1279,7 @@ def generate_public_api_flat_methods() -> None:
|
||||
thread_fork_fields = _load_public_fields(
|
||||
"openai_codex.generated.v2_all",
|
||||
"ThreadForkParams",
|
||||
exclude={"thread_id", *approval_fields},
|
||||
exclude={"thread_id", "last_turn_id", *approval_fields},
|
||||
)
|
||||
thread_fork_fields = _replace_public_sandbox_field(thread_fork_fields, wire_name="sandbox")
|
||||
turn_start_fields = _load_public_fields(
|
||||
@@ -1299,7 +1361,7 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
required=True,
|
||||
help=(
|
||||
"Python SDK release version to write into the staged package. "
|
||||
"Accepts PEP 440 versions such as 0.1.0b1."
|
||||
"Accepts PEP 440 versions such as 0.144.4."
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ from .v2_all import ContextCompactedNotification
|
||||
from .v2_all import DeprecationNoticeNotification
|
||||
from .v2_all import ErrorNotification
|
||||
from .v2_all import ExternalAgentConfigImportCompletedNotification
|
||||
from .v2_all import ExternalAgentConfigImportProgressNotification
|
||||
from .v2_all import FileChangeOutputDeltaNotification
|
||||
from .v2_all import FileChangePatchUpdatedNotification
|
||||
from .v2_all import FsChangedNotification
|
||||
@@ -33,6 +34,7 @@ from .v2_all import McpServerOauthLoginCompletedNotification
|
||||
from .v2_all import McpServerStatusUpdatedNotification
|
||||
from .v2_all import McpToolCallProgressNotification
|
||||
from .v2_all import ModelReroutedNotification
|
||||
from .v2_all import ModelSafetyBufferingUpdatedNotification
|
||||
from .v2_all import ModelVerificationNotification
|
||||
from .v2_all import PlanDeltaNotification
|
||||
from .v2_all import ProcessExitedNotification
|
||||
@@ -46,6 +48,7 @@ from .v2_all import SkillsChangedNotification
|
||||
from .v2_all import TerminalInteractionNotification
|
||||
from .v2_all import ThreadArchivedNotification
|
||||
from .v2_all import ThreadClosedNotification
|
||||
from .v2_all import ThreadDeletedNotification
|
||||
from .v2_all import ThreadGoalClearedNotification
|
||||
from .v2_all import ThreadGoalUpdatedNotification
|
||||
from .v2_all import ThreadNameUpdatedNotification
|
||||
@@ -64,6 +67,7 @@ from .v2_all import ThreadTokenUsageUpdatedNotification
|
||||
from .v2_all import ThreadUnarchivedNotification
|
||||
from .v2_all import TurnCompletedNotification
|
||||
from .v2_all import TurnDiffUpdatedNotification
|
||||
from .v2_all import TurnModerationMetadataNotification
|
||||
from .v2_all import TurnPlanUpdatedNotification
|
||||
from .v2_all import TurnStartedNotification
|
||||
from .v2_all import WarningNotification
|
||||
@@ -80,6 +84,7 @@ NOTIFICATION_MODELS: dict[str, type[BaseModel]] = {
|
||||
"deprecationNotice": DeprecationNoticeNotification,
|
||||
"error": ErrorNotification,
|
||||
"externalAgentConfig/import/completed": ExternalAgentConfigImportCompletedNotification,
|
||||
"externalAgentConfig/import/progress": ExternalAgentConfigImportProgressNotification,
|
||||
"fs/changed": FsChangedNotification,
|
||||
"fuzzyFileSearch/sessionCompleted": FuzzyFileSearchSessionCompletedNotification,
|
||||
"fuzzyFileSearch/sessionUpdated": FuzzyFileSearchSessionUpdatedNotification,
|
||||
@@ -103,6 +108,7 @@ NOTIFICATION_MODELS: dict[str, type[BaseModel]] = {
|
||||
"mcpServer/oauthLogin/completed": McpServerOauthLoginCompletedNotification,
|
||||
"mcpServer/startupStatus/updated": McpServerStatusUpdatedNotification,
|
||||
"model/rerouted": ModelReroutedNotification,
|
||||
"model/safetyBuffering/updated": ModelSafetyBufferingUpdatedNotification,
|
||||
"model/verification": ModelVerificationNotification,
|
||||
"process/exited": ProcessExitedNotification,
|
||||
"process/outputDelta": ProcessOutputDeltaNotification,
|
||||
@@ -112,6 +118,7 @@ NOTIFICATION_MODELS: dict[str, type[BaseModel]] = {
|
||||
"thread/archived": ThreadArchivedNotification,
|
||||
"thread/closed": ThreadClosedNotification,
|
||||
"thread/compacted": ContextCompactedNotification,
|
||||
"thread/deleted": ThreadDeletedNotification,
|
||||
"thread/goal/cleared": ThreadGoalClearedNotification,
|
||||
"thread/goal/updated": ThreadGoalUpdatedNotification,
|
||||
"thread/name/updated": ThreadNameUpdatedNotification,
|
||||
@@ -130,6 +137,7 @@ NOTIFICATION_MODELS: dict[str, type[BaseModel]] = {
|
||||
"thread/unarchived": ThreadUnarchivedNotification,
|
||||
"turn/completed": TurnCompletedNotification,
|
||||
"turn/diff/updated": TurnDiffUpdatedNotification,
|
||||
"turn/moderationMetadata": TurnModerationMetadataNotification,
|
||||
"turn/plan/updated": TurnPlanUpdatedNotification,
|
||||
"turn/started": TurnStartedNotification,
|
||||
"warning": WarningNotification,
|
||||
@@ -152,6 +160,7 @@ DIRECT_TURN_ID_NOTIFICATION_TYPES: tuple[type[BaseModel], ...] = (
|
||||
ItemStartedNotification,
|
||||
McpToolCallProgressNotification,
|
||||
ModelReroutedNotification,
|
||||
ModelSafetyBufferingUpdatedNotification,
|
||||
ModelVerificationNotification,
|
||||
PlanDeltaNotification,
|
||||
ReasoningSummaryPartAddedNotification,
|
||||
@@ -161,6 +170,7 @@ DIRECT_TURN_ID_NOTIFICATION_TYPES: tuple[type[BaseModel], ...] = (
|
||||
ThreadGoalUpdatedNotification,
|
||||
ThreadTokenUsageUpdatedNotification,
|
||||
TurnDiffUpdatedNotification,
|
||||
TurnModerationMetadataNotification,
|
||||
TurnPlanUpdatedNotification,
|
||||
)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
|
||||
Generated
+11
-11
@@ -7,7 +7,7 @@ exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for
|
||||
exclude-newer-span = "P7D"
|
||||
|
||||
[options.exclude-newer-package]
|
||||
openai-codex-cli-bin = "2026-06-03T19:00:00Z"
|
||||
openai-codex-cli-bin = "2026-07-15T01:00:00Z"
|
||||
|
||||
[[package]]
|
||||
name = "annotated-types"
|
||||
@@ -306,7 +306,7 @@ test = [
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "openai-codex-cli-bin", specifier = "==0.137.0a4" },
|
||||
{ name = "openai-codex-cli-bin", specifier = "==0.144.4" },
|
||||
{ name = "pydantic", specifier = ">=2.12" },
|
||||
]
|
||||
|
||||
@@ -325,17 +325,17 @@ test = [
|
||||
|
||||
[[package]]
|
||||
name = "openai-codex-cli-bin"
|
||||
version = "0.137.0a4"
|
||||
version = "0.144.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/60/af73ef1676cd477fa83ed4b889bf3b57c63c47dd87025b2cc4262793cff6/openai_codex_cli_bin-0.137.0a4-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:b33c3917e0b58d527ee11a11a78ad390f7d8e6aa25577dd21665ab3c8bf5cf9a", size = 94300191, upload-time = "2026-06-03T18:44:36.312Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/8f/d1a5f8c87176e00ef6a85798794f4530f5eb04e5a1a13468b5b3c3a361f9/openai_codex_cli_bin-0.137.0a4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3d0f0bc5becc88c61952fbfa9bd792ac9d74fa78b3a6bd40f545b612048b07eb", size = 83924479, upload-time = "2026-06-03T18:44:40.854Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/3c/fc00bcdc0c302208317d5eb1d0bfaab3024f351cd0121400f19baa6b19aa/openai_codex_cli_bin-0.137.0a4-py3-none-manylinux_2_17_aarch64.whl", hash = "sha256:2f1656339e2736868c4cce59f6d9e5c633879123687169b03b1137d42bf2c11a", size = 83363315, upload-time = "2026-06-03T18:44:44.851Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/09/39362e944ebeb12fcbfb86881fbb4dd6e806f77f7541c1f1f993bb9351a0/openai_codex_cli_bin-0.137.0a4-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:6454f838d44c56c1ed07a29b391fa412785e5dd2ffd06db0b62e62478c19bb64", size = 90611239, upload-time = "2026-06-03T18:44:49.338Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/38/87b1247fdfe95cddce7f7fe8331d6843cf037e14292c0f5004e23247133b/openai_codex_cli_bin-0.137.0a4-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:f5ae7401d00c65d56a75d9645d7bf87d809566a12d238e4b2a8b328a02f2316e", size = 83363315, upload-time = "2026-06-03T18:44:53.428Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/c4/3c693ad07e587f6b3a28128c417f2e831d81a40cdbd85c0e5f0f36aaff82/openai_codex_cli_bin-0.137.0a4-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:3dcec1e649448be498d6e7ec0e1f71dca83efa76063d90890dafb41e987069b7", size = 90611238, upload-time = "2026-06-03T18:44:57.612Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/26/81e037066b9b8d312a6f9e09015e452ce17630d5ab88e02a4c1d9503e4e8/openai_codex_cli_bin-0.137.0a4-py3-none-win_amd64.whl", hash = "sha256:9e13bf68e18e36bd3a0efd51213281c83e9f6ec22bdb7a45bd2e0211822733a9", size = 94744969, upload-time = "2026-06-03T18:45:02.23Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/a3/952bc2a5d62373a51fea161effe3b338b3417c2f6e65fe467ed91b205e2b/openai_codex_cli_bin-0.137.0a4-py3-none-win_arm64.whl", hash = "sha256:5ec4303ca2dcb5f838e0de3ca7f44050b6bcdd41d281a178c3a1420a985a515d", size = 86963504, upload-time = "2026-06-03T18:45:07.131Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/30/7e457c007a32aa7333a78438a9f532504c3b77a1ea57e7808855712c2c0f/openai_codex_cli_bin-0.144.4-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:4d587d152d5f0aa25f21ded4d08aac5150da48639b29fc3e57b2a8b413d06903", size = 126851183, upload-time = "2026-07-15T00:14:00.171Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/eb/64c180514a2cc3e2500e486813f5a8d7f7e349342e9bebd78d99ddd9791a/openai_codex_cli_bin-0.144.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:05db505a9c7f020f58b70837a94e00d32a50086986c267bcc44ea97b573d4a05", size = 116474758, upload-time = "2026-07-15T00:14:08.177Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/34/921ab692c7ed140941a91e39b84c6deafddb45072793f3a5f6dcbf86f59a/openai_codex_cli_bin-0.144.4-py3-none-manylinux_2_17_aarch64.whl", hash = "sha256:cd4bb31b8a477a3adba22139c8c493693fa5292ba21e86eef08ace3e96c41294", size = 119437596, upload-time = "2026-07-15T00:14:17.418Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/62/39e630cf8b7b2e2444a5a6669235a6cd88004869a25bb7f3f629ed35638c/openai_codex_cli_bin-0.144.4-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:4106229c38f37245c3eea8d904426afd45b8bf19831765715647f5402f757c06", size = 128817757, upload-time = "2026-07-15T00:14:30.539Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/24/318f91a95baaff845307e529d138d42a7202e6bd0e626556058eab3dead5/openai_codex_cli_bin-0.144.4-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:d2d3fada11731938e3d3e3660819d5324b7f92e825a0ed5aede63100b36ffc9a", size = 119437594, upload-time = "2026-07-15T00:14:39.327Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/a0/65e6fd3a6fba52639937801d9ce517b0c48026458723bb9f08eb07a1dd35/openai_codex_cli_bin-0.144.4-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:70fb62ed7755e332dd8b00ed48e22ee16df10f4a977335039e237cd330490df3", size = 128817755, upload-time = "2026-07-15T00:14:47.849Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/8a/3ab5fc97352e8f780d472c8dd6d7504d6a670cd7dede106d461ac1171999/openai_codex_cli_bin-0.144.4-py3-none-win_amd64.whl", hash = "sha256:56e142974467332f1f669b89f2636e06b3ada09413512abb2f24c33b4a4f59fc", size = 140595092, upload-time = "2026-07-15T00:14:58.484Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/1a/3aa52ab8f89e0f596b6eea835e3f3494697da51917d3231f5f48f92e2bcb/openai_codex_cli_bin-0.144.4-py3-none-win_arm64.whl", hash = "sha256:2ad01058db7181323ae7c6217e560702e38c4f107595b99ab1d0abc9f184890a", size = 130665105, upload-time = "2026-07-15T00:15:08.861Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
Reference in New Issue
Block a user