mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
sdk/python: add first-class login support (#23093)
## 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.
This commit is contained in:
committed by
GitHub
Unverified
parent
0445b290fe
commit
4c89772314
@@ -19,9 +19,37 @@ Requirements:
|
||||
- Python `>=3.10`
|
||||
- uv
|
||||
- installed `openai-codex-cli-bin` runtime package, or an explicit `codex_bin` override
|
||||
- local Codex auth/session configured
|
||||
|
||||
## 2) Run your first turn (sync)
|
||||
## 2) Authenticate when needed
|
||||
|
||||
Existing Codex auth state is reused automatically. To authenticate from the SDK,
|
||||
use the flow that fits 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 browser login returns a handle that carries the URL and the
|
||||
matching completion event:
|
||||
|
||||
```python
|
||||
with Codex() as codex:
|
||||
login = codex.login_chatgpt()
|
||||
print(login.auth_url)
|
||||
completed = login.wait()
|
||||
print(completed.success)
|
||||
```
|
||||
|
||||
Device-code login works the same way with
|
||||
`login_chatgpt_device_code()`, which exposes `verification_url`, `user_code`,
|
||||
and `wait()`.
|
||||
|
||||
## 3) Run your first turn (sync)
|
||||
|
||||
```python
|
||||
from openai_codex import Codex
|
||||
@@ -47,7 +75,7 @@ What happened:
|
||||
- use `thread.turn(...)` when you need a `TurnHandle` for streaming, steering, interrupting, or turn IDs/status
|
||||
- one client can consume multiple active turns concurrently; turn streams are routed by turn ID
|
||||
|
||||
## 3) Continue the same thread (multi-turn)
|
||||
## 4) Continue the same thread (multi-turn)
|
||||
|
||||
```python
|
||||
from openai_codex import Codex
|
||||
@@ -62,7 +90,7 @@ with Codex() as codex:
|
||||
print("second:", second.final_response)
|
||||
```
|
||||
|
||||
## 4) Async parity
|
||||
## 5) Async parity
|
||||
|
||||
Use `async with AsyncCodex()` as the normal async entrypoint. `AsyncCodex`
|
||||
initializes lazily, and context entry makes startup/shutdown explicit.
|
||||
@@ -82,7 +110,7 @@ async def main() -> None:
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## 5) Resume an existing thread
|
||||
## 6) Resume an existing thread
|
||||
|
||||
```python
|
||||
from openai_codex import Codex
|
||||
@@ -95,7 +123,7 @@ with Codex() as codex:
|
||||
print(result.final_response)
|
||||
```
|
||||
|
||||
## 6) Public app-server types
|
||||
## 7) Public app-server types
|
||||
|
||||
The convenience wrappers live at the package root. Public app-server value and
|
||||
event types live under:
|
||||
@@ -104,7 +132,7 @@ event types live under:
|
||||
from openai_codex.types import ThreadReadResponse, Turn, TurnStatus
|
||||
```
|
||||
|
||||
## 7) Next stops
|
||||
## 8) Next stops
|
||||
|
||||
- API surface and signatures: `docs/api-reference.md`
|
||||
- Common decisions/pitfalls: `docs/faq.md`
|
||||
|
||||
Reference in New Issue
Block a user