diff --git a/sdk/python/README.md b/sdk/python/README.md index 4f150bb692..0c5a8bd3a6 100644 --- a/sdk/python/README.md +++ b/sdk/python/README.md @@ -3,9 +3,8 @@ Experimental Python SDK for `codex app-server` JSON-RPC v2 over stdio, with a small default surface optimized for real scripts and apps. The generated wire-model layer is sourced from the pinned `openai-codex-cli-bin` -runtime package. The package root exports the supported ergonomic SDK surface -plus selected public value types; generated transport modules are shipped for -runtime use but are not the supported public API. +runtime package and exposed as Pydantic models with snake_case Python fields +that serialize back to the app-server’s camelCase wire format. ## Install @@ -111,4 +110,4 @@ This supports the CI release flow: - Use context managers (`with Codex() as codex:`) to ensure shutdown. - Prefer `thread.run("...")` for the common case. Use `thread.turn(...)` when you need streaming, steering, or interrupt control. -- For transient overload, import `retry_on_overload` from `codex_app_server`. +- For transient overload, use `codex_app_server.retry.retry_on_overload`. diff --git a/sdk/python/docs/api-reference.md b/sdk/python/docs/api-reference.md index 8793929dcd..c7a763498d 100644 --- a/sdk/python/docs/api-reference.md +++ b/sdk/python/docs/api-reference.md @@ -10,12 +10,12 @@ This SDK surface is experimental. Turn streams are routed by turn ID so one clie from codex_app_server import ( Codex, AsyncCodex, - AppServerConfig, RunResult, Thread, AsyncThread, TurnHandle, AsyncTurnHandle, + InitializeResponse, Input, InputItem, TextInput, @@ -24,14 +24,13 @@ from codex_app_server import ( SkillInput, MentionInput, TurnStatus, - retry_on_overload, ) +from codex_app_server.generated.v2_all import ThreadItem, ThreadTokenUsage ``` - Version: `codex_app_server.__version__` - Requires Python >= 3.10 -- The package root `__all__` is the supported public import surface; generated - transport modules are shipped for runtime use but are not re-exported. +- Canonical generated app-server models live in `codex_app_server.generated.v2_all` ## Codex (sync) @@ -166,23 +165,20 @@ InputItem = TextInput | ImageInput | LocalImageInput | SkillInput | MentionInput Input = list[InputItem] | InputItem ``` -## Public Value Types +## Generated Models -The package root exports the ergonomic SDK plus selected value types used by -public method signatures: +The SDK wrappers return and accept canonical generated app-server models wherever possible: ```python -from codex_app_server import ( +from codex_app_server.generated.v2_all import ( AskForApproval, - ReasoningEffort, - SandboxPolicy, + ThreadReadResponse, + Turn, + TurnStartParams, TurnStatus, ) ``` -Generated transport modules are shipped for SDK runtime use, but they are not -the supported root API. - ## Retry + errors ```python diff --git a/sdk/python/docs/getting-started.md b/sdk/python/docs/getting-started.md index 6d5e4ab26c..1794d39f70 100644 --- a/sdk/python/docs/getting-started.md +++ b/sdk/python/docs/getting-started.md @@ -95,12 +95,12 @@ with Codex() as codex: print(result.final_response) ``` -## 6) Public value types +## 6) Generated models -The convenience wrappers and selected value types live at the package root: +The convenience wrappers live at the package root, but the canonical app-server models live under: ```python -from codex_app_server import AskForApproval, ReasoningEffort, SandboxPolicy, TurnStatus +from codex_app_server.generated.v2_all import Turn, TurnStatus, ThreadReadResponse ``` ## 7) Next stops diff --git a/sdk/python/examples/11_cli_mini_app/async.py b/sdk/python/examples/11_cli_mini_app/async.py index 2e0d2acba0..4216cf7820 100644 --- a/sdk/python/examples/11_cli_mini_app/async.py +++ b/sdk/python/examples/11_cli_mini_app/async.py @@ -14,6 +14,8 @@ import asyncio from codex_app_server import ( AsyncCodex, TextInput, + ThreadTokenUsageUpdatedNotification, + TurnCompletedNotification, ) @@ -70,13 +72,12 @@ async def main() -> None: print(delta, end="", flush=True) printed_delta = True continue - if event.method == "thread/tokenUsage/updated": - usage = getattr(payload, "token_usage", None) + if isinstance(payload, ThreadTokenUsageUpdatedNotification): + usage = payload.token_usage continue - if event.method == "turn/completed": - turn = getattr(payload, "turn", None) - status = getattr(turn, "status", None) - error = getattr(turn, "error", None) + if isinstance(payload, TurnCompletedNotification): + status = payload.turn.status + error = payload.turn.error if printed_delta: print() diff --git a/sdk/python/examples/11_cli_mini_app/sync.py b/sdk/python/examples/11_cli_mini_app/sync.py index 7b4c37cb23..e961cfbcc3 100644 --- a/sdk/python/examples/11_cli_mini_app/sync.py +++ b/sdk/python/examples/11_cli_mini_app/sync.py @@ -12,6 +12,8 @@ ensure_local_sdk_src() from codex_app_server import ( Codex, TextInput, + ThreadTokenUsageUpdatedNotification, + TurnCompletedNotification, ) print("Codex mini CLI. Type /exit to quit.") @@ -67,13 +69,12 @@ with Codex(config=runtime_config()) as codex: print(delta, end="", flush=True) printed_delta = True continue - if event.method == "thread/tokenUsage/updated": - usage = getattr(payload, "token_usage", None) + if isinstance(payload, ThreadTokenUsageUpdatedNotification): + usage = payload.token_usage continue - if event.method == "turn/completed": - turn = getattr(payload, "turn", None) - status = getattr(turn, "status", None) - error = getattr(turn, "error", None) + if isinstance(payload, TurnCompletedNotification): + status = payload.turn.status + error = payload.turn.error if printed_delta: print() diff --git a/sdk/python/src/codex_app_server/__init__.py b/sdk/python/src/codex_app_server/__init__.py index c950588325..49753f4e24 100644 --- a/sdk/python/src/codex_app_server/__init__.py +++ b/sdk/python/src/codex_app_server/__init__.py @@ -24,12 +24,22 @@ from .generated.v2_all import ( SandboxPolicy, SortDirection, ThreadListCwdFilter, + ThreadItem, + ThreadForkParams, + ThreadListParams, + ThreadResumeParams, ThreadSortKey, ThreadSource, ThreadSourceKind, + ThreadStartParams, ThreadStartSource, + ThreadTokenUsageUpdatedNotification, + TurnCompletedNotification, + TurnStartParams, TurnStatus, + TurnSteerParams, ) +from .models import InitializeResponse from .api import ( AsyncCodex, AsyncThread, @@ -58,6 +68,7 @@ __all__ = [ "AsyncThread", "TurnHandle", "AsyncTurnHandle", + "InitializeResponse", "RunResult", "Input", "InputItem", @@ -66,6 +77,9 @@ __all__ = [ "LocalImageInput", "SkillInput", "MentionInput", + "ThreadItem", + "ThreadTokenUsageUpdatedNotification", + "TurnCompletedNotification", "ApprovalsReviewer", "AskForApproval", "Personality", @@ -76,11 +90,17 @@ __all__ = [ "SandboxPolicy", "SortDirection", "ThreadListCwdFilter", + "ThreadStartParams", + "ThreadResumeParams", + "ThreadListParams", "ThreadSortKey", "ThreadSource", "ThreadSourceKind", + "ThreadForkParams", "ThreadStartSource", "TurnStatus", + "TurnStartParams", + "TurnSteerParams", "retry_on_overload", "AppServerError", "TransportClosedError", diff --git a/sdk/python/tests/test_public_api_signatures.py b/sdk/python/tests/test_public_api_signatures.py index 7ae5c706e9..2a956256d2 100644 --- a/sdk/python/tests/test_public_api_signatures.py +++ b/sdk/python/tests/test_public_api_signatures.py @@ -26,6 +26,7 @@ EXPECTED_ROOT_EXPORTS = [ "AsyncThread", "TurnHandle", "AsyncTurnHandle", + "InitializeResponse", "RunResult", "Input", "InputItem", @@ -34,6 +35,9 @@ EXPECTED_ROOT_EXPORTS = [ "LocalImageInput", "SkillInput", "MentionInput", + "ThreadItem", + "ThreadTokenUsageUpdatedNotification", + "TurnCompletedNotification", "ApprovalsReviewer", "AskForApproval", "Personality", @@ -44,11 +48,17 @@ EXPECTED_ROOT_EXPORTS = [ "SandboxPolicy", "SortDirection", "ThreadListCwdFilter", + "ThreadStartParams", + "ThreadResumeParams", + "ThreadListParams", "ThreadSortKey", "ThreadSource", "ThreadSourceKind", + "ThreadForkParams", "ThreadStartSource", "TurnStatus", + "TurnStartParams", + "TurnSteerParams", "retry_on_overload", "AppServerError", "TransportClosedError", @@ -115,15 +125,9 @@ def test_package_root_exports_only_public_api() -> None: assert { "AppServerClient": hasattr(codex_app_server, "AppServerClient"), "AsyncAppServerClient": hasattr(codex_app_server, "AsyncAppServerClient"), - "InitializeResponse": hasattr(codex_app_server, "InitializeResponse"), - "ThreadStartParams": hasattr(codex_app_server, "ThreadStartParams"), - "TurnStartParams": hasattr(codex_app_server, "TurnStartParams"), } == { "AppServerClient": False, "AsyncAppServerClient": False, - "InitializeResponse": False, - "ThreadStartParams": False, - "TurnStartParams": False, }