mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
4d0c4cd058
## Why `openai-codex` needs a beta release lifecycle without requiring beta releases of its pinned runtime package. Previously, SDK staging rewrote its runtime dependency to the SDK version, which made an SDK-only beta impossible. ## What changed - Set the initial SDK beta version to `0.1.0b1` and pin it to published stable `openai-codex-cli-bin==0.132.0`. - Decoupled SDK release staging from runtime versioning so it preserves the reviewed exact runtime pin. - Added a `python-v*` tag workflow that builds and publishes only `openai-codex` through PyPI trusted publishing. - Removed the Beta classifier from runtime package metadata for future runtime publications. - Regenerated protocol-derived SDK models from the selected stable runtime package. `0.132.0` is the newest stable runtime admitted by the checked-in dependency date fence and retains the Linux wheel family currently used by SDK CI. ## Release setup Before pushing `python-v0.1.0b1`, configure PyPI trusted publishing for the `openai-codex` project with workflow `python-sdk-release.yml`, environment `pypi`, and job `publish-python-sdk`. ## Validation - `uv run --frozen --extra dev ruff check src/openai_codex scripts examples tests` - Parsed `.github/workflows/python-sdk-release.yml` with PyYAML. - Built staged release artifacts locally: `openai_codex-0.1.0b1-py3-none-any.whl` and `openai_codex-0.1.0b1.tar.gz`. - Verified wheel metadata pins `openai-codex-cli-bin==0.132.0`. - Tests are deferred to online CI for this PR.
133 lines
4.2 KiB
Markdown
133 lines
4.2 KiB
Markdown
# OpenAI Codex Python SDK (Experimental)
|
|
|
|
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 and exposed as Pydantic models with snake_case Python fields
|
|
that serialize back to the protocol's camelCase wire format.
|
|
The package root exports the ergonomic client API; public Codex protocol value and
|
|
event types live in `openai_codex.types`.
|
|
|
|
## Install
|
|
|
|
```bash
|
|
cd sdk/python
|
|
uv sync
|
|
source .venv/bin/activate
|
|
```
|
|
|
|
Published SDK builds pin an exact compatible `openai-codex-cli-bin` runtime
|
|
dependency. Pass `CodexConfig(codex_bin=...)` only
|
|
when you intentionally want to run against a specific local app-server binary.
|
|
|
|
## Quickstart
|
|
|
|
```python
|
|
from openai_codex import Codex, Sandbox
|
|
|
|
with Codex() as codex:
|
|
# Call login_api_key(...) first when this Codex session is not
|
|
# already authenticated.
|
|
thread = codex.thread_start(model="gpt-5", sandbox=Sandbox.workspace_write)
|
|
result = thread.run("Say hello in one sentence.")
|
|
print(result.final_response)
|
|
print(len(result.items))
|
|
```
|
|
|
|
`thread.run(...)` and `thread.turn(...).run()` return `TurnResult`. Its
|
|
`final_response` is `None` when the turn completes without a final-answer or
|
|
phase-less assistant message item.
|
|
|
|
## Sandbox
|
|
|
|
Use the same enum when creating a thread or changing its sandbox for a turn:
|
|
|
|
```python
|
|
from openai_codex import Codex, Sandbox
|
|
|
|
with Codex() as codex:
|
|
thread = codex.thread_start(sandbox=Sandbox.workspace_write)
|
|
thread.run("Make the requested change.")
|
|
review = thread.run("Review the diff only.", sandbox=Sandbox.read_only)
|
|
```
|
|
|
|
Available presets:
|
|
|
|
- `Sandbox.read_only`: read files without allowing writes.
|
|
- `Sandbox.workspace_write`: the normal default for projects with a recorded trust decision; read files and write inside the workspace and configured writable roots.
|
|
- `Sandbox.full_access`: run without filesystem access restrictions.
|
|
|
|
When `sandbox=` is omitted, Codex uses its configured default. A sandbox
|
|
passed to `run(...)` or `turn(...)` applies to that turn and subsequent turns
|
|
on the thread.
|
|
|
|
## Login
|
|
|
|
Use the auth helper that matches your app:
|
|
|
|
```python
|
|
from openai_codex import Codex
|
|
|
|
with Codex() as codex:
|
|
codex.login_api_key("sk-...")
|
|
account = codex.account()
|
|
print(account.account)
|
|
```
|
|
|
|
Interactive ChatGPT login returns a handle. Open the provided URL or device-code
|
|
page, then wait for the matching completion event:
|
|
|
|
```python
|
|
with Codex() as codex:
|
|
login = codex.login_chatgpt()
|
|
print(login.auth_url)
|
|
completed = login.wait()
|
|
print(completed.success)
|
|
```
|
|
|
|
Use `login_chatgpt_device_code()` for device-code auth, `handle.cancel()` to
|
|
stop an in-progress interactive login, and `logout()` to clear the active
|
|
Codex account session.
|
|
|
|
## Docs map
|
|
|
|
- Golden path tutorial: `docs/getting-started.md`
|
|
- API reference (signatures + behavior): `docs/api-reference.md`
|
|
- Common decisions and pitfalls: `docs/faq.md`
|
|
- Runnable examples index: `examples/README.md`
|
|
- Jupyter walkthrough notebook: `notebooks/sdk_walkthrough.ipynb`
|
|
|
|
## Examples
|
|
|
|
Start here:
|
|
|
|
```bash
|
|
cd sdk/python
|
|
python examples/01_quickstart_constructor/sync.py
|
|
python examples/01_quickstart_constructor/async.py
|
|
```
|
|
|
|
## Runtime
|
|
|
|
Published SDK builds are pinned to an exact `openai-codex-cli-bin` package
|
|
version, and that runtime package carries the platform-specific binary for the
|
|
target wheel. SDK beta releases are versioned independently of runtime releases.
|
|
|
|
## Compatibility and versioning
|
|
|
|
- Package: `openai-codex`
|
|
- Runtime package: `openai-codex-cli-bin`
|
|
- Python: `>=3.10`
|
|
- Target protocol: Codex `app-server` JSON-RPC v2
|
|
- Versioning rule: SDK releases pin one exact compatible Codex runtime version
|
|
|
|
## Notes
|
|
|
|
- `Codex()` is eager and performs startup + `initialize` in the constructor.
|
|
- Use context managers (`with Codex() as codex:`) to ensure shutdown.
|
|
- Plain strings are accepted anywhere a turn input is accepted; they are
|
|
shorthand for `TextInput(...)`.
|
|
- Prefer `thread.run("...")` for the common case. Use `thread.turn(...)` when
|
|
you need streaming, steering, or interrupt control.
|
|
- For transient overload, use `retry_on_overload` from the package root.
|