mirror of
https://github.com/openai/codex.git
synced 2026-05-20 11:12:43 +00: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:
@@ -12,6 +12,10 @@ from openai_codex import (
|
||||
Codex,
|
||||
AsyncCodex,
|
||||
ApprovalMode,
|
||||
ChatgptLoginHandle,
|
||||
DeviceCodeLoginHandle,
|
||||
AsyncChatgptLoginHandle,
|
||||
AsyncDeviceCodeLoginHandle,
|
||||
RunResult,
|
||||
Thread,
|
||||
AsyncThread,
|
||||
@@ -26,6 +30,11 @@ from openai_codex import (
|
||||
MentionInput,
|
||||
)
|
||||
from openai_codex.types import (
|
||||
Account,
|
||||
AccountLoginCompletedNotification,
|
||||
CancelLoginAccountResponse,
|
||||
CancelLoginAccountStatus,
|
||||
GetAccountResponse,
|
||||
InitializeResponse,
|
||||
ThreadItem,
|
||||
ThreadTokenUsage,
|
||||
@@ -47,6 +56,11 @@ Properties/methods:
|
||||
|
||||
- `metadata -> InitializeResponse`
|
||||
- `close() -> None`
|
||||
- `login_api_key(api_key: str) -> None`
|
||||
- `login_chatgpt() -> ChatgptLoginHandle`
|
||||
- `login_chatgpt_device_code() -> DeviceCodeLoginHandle`
|
||||
- `account(*, refresh_token: bool = False) -> GetAccountResponse`
|
||||
- `logout() -> None`
|
||||
- `thread_start(*, approval_mode=ApprovalMode.auto_review, base_instructions=None, config=None, cwd=None, developer_instructions=None, ephemeral=None, model=None, model_provider=None, personality=None, sandbox=None) -> Thread`
|
||||
- `thread_list(*, archived=None, cursor=None, cwd=None, limit=None, model_providers=None, sort_key=None, source_kinds=None) -> ThreadListResponse`
|
||||
- `thread_resume(thread_id: str, *, approval_mode=ApprovalMode.auto_review, base_instructions=None, config=None, cwd=None, developer_instructions=None, model=None, model_provider=None, personality=None, sandbox=None) -> Thread`
|
||||
@@ -82,6 +96,11 @@ Properties/methods:
|
||||
|
||||
- `metadata -> InitializeResponse`
|
||||
- `close() -> Awaitable[None]`
|
||||
- `login_api_key(api_key: str) -> Awaitable[None]`
|
||||
- `login_chatgpt() -> Awaitable[AsyncChatgptLoginHandle]`
|
||||
- `login_chatgpt_device_code() -> Awaitable[AsyncDeviceCodeLoginHandle]`
|
||||
- `account(*, refresh_token: bool = False) -> Awaitable[GetAccountResponse]`
|
||||
- `logout() -> Awaitable[None]`
|
||||
- `thread_start(*, approval_mode=ApprovalMode.auto_review, base_instructions=None, config=None, cwd=None, developer_instructions=None, ephemeral=None, model=None, model_provider=None, personality=None, sandbox=None) -> Awaitable[AsyncThread]`
|
||||
- `thread_list(*, archived=None, cursor=None, cwd=None, limit=None, model_providers=None, sort_key=None, source_kinds=None) -> Awaitable[ThreadListResponse]`
|
||||
- `thread_resume(thread_id: str, *, approval_mode=ApprovalMode.auto_review, base_instructions=None, config=None, cwd=None, developer_instructions=None, model=None, model_provider=None, personality=None, sandbox=None) -> Awaitable[AsyncThread]`
|
||||
@@ -97,6 +116,30 @@ async with AsyncCodex() as codex:
|
||||
...
|
||||
```
|
||||
|
||||
## Login handles
|
||||
|
||||
### ChatgptLoginHandle / AsyncChatgptLoginHandle
|
||||
|
||||
- `login_id: str`
|
||||
- `auth_url: str`
|
||||
- `wait() -> AccountLoginCompletedNotification`
|
||||
- `cancel() -> CancelLoginAccountResponse`
|
||||
|
||||
Async handle methods return awaitables.
|
||||
|
||||
### DeviceCodeLoginHandle / AsyncDeviceCodeLoginHandle
|
||||
|
||||
- `login_id: str`
|
||||
- `verification_url: str`
|
||||
- `user_code: str`
|
||||
- `wait() -> AccountLoginCompletedNotification`
|
||||
- `cancel() -> CancelLoginAccountResponse`
|
||||
|
||||
Async handle methods return awaitables.
|
||||
|
||||
`wait()` consumes only the completion notification for its matching login
|
||||
attempt. API-key login completes synchronously and does not return a handle.
|
||||
|
||||
## Thread / AsyncThread
|
||||
|
||||
`Thread` and `AsyncThread` share the same shape and intent.
|
||||
@@ -176,6 +219,11 @@ The SDK wrappers return and accept public app-server models wherever possible:
|
||||
|
||||
```python
|
||||
from openai_codex.types import (
|
||||
Account,
|
||||
AccountLoginCompletedNotification,
|
||||
CancelLoginAccountResponse,
|
||||
CancelLoginAccountStatus,
|
||||
GetAccountResponse,
|
||||
ThreadReadResponse,
|
||||
Turn,
|
||||
TurnStatus,
|
||||
|
||||
Reference in New Issue
Block a user