## Why
`TurnHandle.run()` returned the raw app-server `Turn`, whose live
start/completed payloads do not include loaded `items`, so users saw
empty `items` after starting a turn. That made the handle-based path
behave differently from `Thread.run(...)`, and pushed examples toward
persisted-thread reads plus helper extraction.
This PR makes the run APIs standalone: starting a turn and running it
returns collected turn data directly, or fails visibly when required
stream events are missing.
## What Changed
- Replaces the public `RunResult` export with `TurnResult`.
- Adds turn metadata to `TurnResult`: `id`, `status`, `error`,
`started_at`, `completed_at`, and `duration_ms`, alongside
`final_response`, `items`, and `usage`.
- Changes `TurnHandle.run()` and `AsyncTurnHandle.run()` to consume
stream events with the same collector used by `Thread.run(...)`.
- Exports `TurnError` from `openai_codex.types` for the new result
shape.
- Updates tests, examples, docs, and the walkthrough notebook to use
`result.final_response` and `result.items` directly.
- Removes persisted-thread helper paths and placeholder/skipped control
flows from the public examples and notebook.
## Verification
- `python3 -m py_compile ...` over changed SDK, example, and test Python
files.
- `python3 -c "import json;
json.load(open('sdk/python/notebooks/sdk_walkthrough.ipynb'))"`
- `git diff --check`
- `PYTHONPATH=sdk/python/src python3 -c ...` import/signature smoke for
`TurnResult`, `TurnHandle.run`, and `AsyncTurnHandle.run`.
## Why
The Python SDK can already create threads and run turns, but
authentication still has to be arranged outside the SDK. App-server
already exposes account login, account inspection, logout, and
`account/login/completed` notifications, so SDK users currently have to
work around a missing public client layer for a core setup step.
This change makes authentication a normal SDK workflow while preserving
the backend flow shape: API-key login completes immediately, and
interactive ChatGPT flows return live handles that complete later
through app-server notifications.
## What changed
- Added public sync and async auth methods on `Codex` / `AsyncCodex`:
- `login_api_key(...)`
- `login_chatgpt()`
- `login_chatgpt_device_code()`
- `account(...)`
- `logout()`
- Added public browser-login and device-code handle types with
attempt-local `wait()` and `cancel()` helpers. Cancellation stays on the
handle instead of a root-level SDK method.
- Extended the Python app-server client and notification router so login
completion events are routed by `login_id` without consuming unrelated
global notifications.
- Kept login request/handle logic in a focused internal `_login.py`
module so `api.py` remains the public facade instead of absorbing more
auth plumbing.
- Exported the new handle types plus curated account/login response
types from the SDK surfaces.
- Updated SDK docs, added sync/async login walkthrough examples, and
added a notebook login walkthrough cell.
## Verification
Added SDK coverage for:
- API-key login, account readback, and logout through the app-server
harness in both sync and async clients.
- Browser login cancellation plus `handle.wait()` completion through the
real app-server boundary used by the Python SDK harness.
- Waiter routing that stays scoped across replaced interactive login
attempts, plus async handle cancellation coverage.
- Login notification demuxing, replay of early completion events, and
async client delegation.
- Public export/signature assertions.
- Real integration-suite smoke coverage for the new examples and
notebook login cell.
## Why
The high-level SDK should expose the approval behavior it actually
supports instead of leaking generated app-server routing fields. New
work should have two clear choices: default auto review, or explicitly
deny escalated permission requests. Existing threads and subsequent
turns should preserve their current approval behavior unless the caller
passes an override.
## What
- Add the public `ApprovalMode` enum with `auto_review` and `deny_all`.
- Default new thread creation to `ApprovalMode.auto_review`.
- Preserve existing approval settings by default for resume, fork, run,
and turn helpers.
- Remove raw `approval_policy` / `approvals_reviewer` kwargs from
high-level SDK wrappers.
- Update generated wrapper output, docs, examples, notebooks, and tests
for the high-level approval mode API.
## Stack
1. #21891 `[1/8]` Pin Python SDK runtime dependency
2. #21893 `[2/8]` Generate Python SDK types from pinned runtime
3. #21895 `[3/8]` Run Python SDK tests in CI
4. #21896 `[4/8]` Define Python SDK public API surface
5. #21905 `[5/8]` Rename Python SDK package to `openai-codex`
6. This PR `[6/8]` Add high-level Python SDK approval mode
7. #22014 `[7/8]` Add Python SDK app-server integration harness
8. #22021 `[8/8]` Add Python SDK Ruff formatting
## Verification
- Added approval-mode mapping/default tests for new threads, existing
threads, forks, resumes, and subsequent turns.
---------
Co-authored-by: Codex <noreply@openai.com>
## Why
The SDK should publish under the reserved public distribution name
`openai-codex`, and its import module should match that name in the
Python style. Since package names can contain hyphens but import modules
cannot, the public import path becomes `openai_codex`.
Keeping the rename separate from the public API surface change makes the
naming change easy to review and avoids mixing it with API curation.
## What
- Rename the SDK distribution from `openai-codex-app-server-sdk` to
`openai-codex`.
- Rename the import package from `codex_app_server` to `openai_codex`.
- Keep the runtime wheel as the separate `openai-codex-cli-bin`
dependency.
- Update docs, examples, notebooks, artifact scripts, lockfile metadata,
and tests for the new distribution/module names.
## Stack
1. #21891 `[1/8]` Pin Python SDK runtime dependency
2. #21893 `[2/8]` Generate Python SDK types from pinned runtime
3. #21895 `[3/8]` Run Python SDK tests in CI
4. #21896 `[4/8]` Define Python SDK public API surface
5. This PR `[5/8]` Rename Python SDK package to `openai-codex`
6. #21910 `[6/8]` Add high-level Python SDK approval mode
7. #22014 `[7/8]` Add Python SDK app-server integration harness
8. #22021 `[8/8]` Add Python SDK Ruff formatting
## Verification
- Updated package metadata and public API tests to assert the
distribution and import names.
Co-authored-by: Codex <noreply@openai.com>
## TL;DR
WIP esp the examples
Thin the Python SDK public surface so the wrapper layer returns
canonical app-server generated models directly.
- keeps `Codex` / `AsyncCodex` / `Thread` / `Turn` and input helpers,
but removes alias-only type layers and custom result models
- `metadata` now returns `InitializeResponse` and `run()` returns the
generated app-server `Turn`
- updates docs, examples, notebook, and tests to use canonical generated
types and regenerates `v2_all.py` against current schema
- keeps the pinned runtime-package integration flow and real integration
coverage
## Validation
- `PYTHONPATH=sdk/python/src python3 -m pytest sdk/python/tests`
- `GH_TOKEN="$(gh auth token)" RUN_REAL_CODEX_TESTS=1
PYTHONPATH=sdk/python/src python3 -m pytest sdk/python/tests -rs`
---------
Co-authored-by: Codex <noreply@openai.com>