Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions sdk/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Experimental Python SDK for `codex app-server` JSON-RPC v2 over stdio, with a sm

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 app-server’s camelCase wire format.
The package root exports the ergonomic client API; public app-server value and
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
Expand All @@ -26,7 +26,7 @@ when you intentionally want to run against a specific local app-server binary.
from openai_codex import Codex, Sandbox

with Codex() as codex:
# Call login_api_key(...) first when this app-server session is not
# 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.")
Expand Down Expand Up @@ -57,7 +57,7 @@ Available presets:
- `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, app-server uses its configured default. A sandbox
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.

Expand Down Expand Up @@ -87,7 +87,7 @@ with Codex() as codex:

Use `login_chatgpt_device_code()` for device-code auth, `handle.cancel()` to
stop an in-progress interactive login, and `logout()` to clear the active
app-server account session.
Codex account session.

## Docs map

Expand Down
8 changes: 4 additions & 4 deletions sdk/python/docs/api-reference.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# OpenAI Codex SDK — API Reference

Public surface of `openai_codex` for app-server v2.
Public surface of `openai_codex` for Codex workflows.

This SDK surface is experimental. Turn streams are routed by turn ID so one client can consume multiple active turns concurrently.
Thread starts default to `ApprovalMode.auto_review`; turn starts accept an optional `approval_mode` override.
Expand Down Expand Up @@ -48,7 +48,7 @@ from openai_codex.types import (

- Version: `openai_codex.__version__`
- Requires Python >= 3.10
- Public app-server value and event types live in `openai_codex.types`
- Public Codex protocol value and event types live in `openai_codex.types`

## Codex (sync)

Expand Down Expand Up @@ -202,7 +202,7 @@ Presets:
- `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, app-server uses its configured default. A sandbox
When `sandbox=` is omitted, Codex uses its configured default. A sandbox
passed to `run(...)` or `turn(...)` applies to that turn and subsequent turns.

## TurnHandle / AsyncTurnHandle
Expand Down Expand Up @@ -250,7 +250,7 @@ Use a plain `str` as shorthand for `TextInput(...)` anywhere a turn input is acc

## Public Types

The SDK wrappers return and accept public app-server models wherever possible:
The SDK wrappers return and accept public Codex protocol models wherever possible:

```python
from openai_codex.types import (
Expand Down
4 changes: 2 additions & 2 deletions sdk/python/docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ The presets are:
- `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, app-server uses its configured default. A turn
When `sandbox=` is omitted, Codex uses its configured default. A turn
sandbox override applies to that turn and subsequent turns.

## Why only `thread_start(...)` and `thread_resume(...)`?
Expand All @@ -86,7 +86,7 @@ Common causes:

- published runtime package (`openai-codex-cli-bin`) is not installed
- local `codex_bin` override points to a missing file
- app-server version older than the SDK schema
- installed Codex runtime version older than the SDK schema

## Why does a turn "hang"?

Expand Down
6 changes: 3 additions & 3 deletions sdk/python/docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ Available presets:
- `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, app-server uses its configured default. A turn
When `sandbox=` is omitted, Codex uses its configured default. A turn
override also becomes the sandbox for subsequent turns on that thread.

## 5) Continue the same thread (multi-turn)
Expand Down Expand Up @@ -150,9 +150,9 @@ with Codex() as codex:
print(result.final_response)
```

## 8) Public app-server types
## 8) Public Codex protocol types

The convenience wrappers live at the package root. Public app-server value and
The convenience wrappers live at the package root. Public Codex protocol value and
event types live under:

```python
Expand Down
8 changes: 4 additions & 4 deletions sdk/python/src/openai_codex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
)
from .client import CodexConfig
from .errors import (
AppServerError,
AppServerRpcError,
CodexError,
CodexRpcError,
InternalRpcError,
InvalidParamsError,
InvalidRequestError,
Expand Down Expand Up @@ -64,10 +64,10 @@
"SkillInput",
"MentionInput",
"retry_on_overload",
"AppServerError",
"CodexError",
"TransportClosedError",
"JsonRpcError",
"AppServerRpcError",
"CodexRpcError",
"ParseError",
"InvalidRequestError",
"MethodNotFoundError",
Expand Down
16 changes: 8 additions & 8 deletions sdk/python/src/openai_codex/_login.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from dataclasses import dataclass
from typing import Protocol

from .async_client import AsyncAppServerClient
from .client import AppServerClient
from .async_client import AsyncCodexClient
from .client import CodexClient
from .generated.v2_all import (
AccountLoginCompletedNotification,
CancelLoginAccountResponse,
Expand All @@ -19,14 +19,14 @@
class _AsyncLoginOwner(Protocol):
"""Subset of AsyncCodex needed by async login handles."""

_client: AsyncAppServerClient
_client: AsyncCodexClient

async def _ensure_initialized(self) -> None:
"""Ensure the owning SDK client has a live app-server connection."""
"""Ensure the owning SDK client has a live Codex connection."""
...


def start_chatgpt_login(client: AppServerClient) -> ChatgptLoginHandle:
def start_chatgpt_login(client: CodexClient) -> ChatgptLoginHandle:
"""Start browser ChatGPT login and return the handle for that attempt."""
response = client.account_login_start(
LoginAccountParams(
Expand Down Expand Up @@ -60,7 +60,7 @@ async def async_start_chatgpt_login(owner: _AsyncLoginOwner) -> AsyncChatgptLogi
)


def start_device_code_login(client: AppServerClient) -> DeviceCodeLoginHandle:
def start_device_code_login(client: CodexClient) -> DeviceCodeLoginHandle:
"""Start device-code ChatGPT login and return the handle for that attempt."""
response = client.account_login_start(
LoginAccountParams(
Expand Down Expand Up @@ -102,7 +102,7 @@ async def async_start_device_code_login(
class ChatgptLoginHandle:
"""Live browser-login attempt returned by `Codex.login_chatgpt()`."""

_client: AppServerClient
_client: CodexClient
login_id: str
auth_url: str

Expand All @@ -119,7 +119,7 @@ def cancel(self) -> CancelLoginAccountResponse:
class DeviceCodeLoginHandle:
"""Live device-code login attempt returned by `Codex.login_chatgpt_device_code()`."""

_client: AppServerClient
_client: CodexClient
login_id: str
verification_url: str
user_code: str
Expand Down
4 changes: 2 additions & 2 deletions sdk/python/src/openai_codex/_message_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import threading
from collections import deque

from .errors import AppServerError, map_jsonrpc_error
from .errors import CodexError, map_jsonrpc_error
from .generated.notification_registry import notification_turn_id
from .generated.v2_all import AccountLoginCompletedNotification
from .models import JsonValue, Notification, UnknownNotification
Expand Down Expand Up @@ -136,7 +136,7 @@ def route_response(self, msg: dict[str, JsonValue]) -> None:
)
)
else:
waiter.put(AppServerError("Malformed JSON-RPC error response"))
waiter.put(CodexError("Malformed JSON-RPC error response"))
return

waiter.put(msg.get("result"))
Expand Down
4 changes: 2 additions & 2 deletions sdk/python/src/openai_codex/_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
ThreadItem,
ThreadTokenUsage,
ThreadTokenUsageUpdatedNotification,
Turn as AppServerTurn,
Turn,
TurnCompletedNotification,
TurnError,
TurnStatus,
Expand Down Expand Up @@ -55,7 +55,7 @@ def _final_assistant_response_from_items(items: list[ThreadItem]) -> str | None:
return last_unknown_phase_response


def _raise_for_failed_turn(turn: AppServerTurn) -> None:
def _raise_for_failed_turn(turn: Turn) -> None:
if turn.status != TurnStatus.failed:
return
if turn.error is not None and turn.error.message:
Expand Down
26 changes: 13 additions & 13 deletions sdk/python/src/openai_codex/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
_collect_turn_result,
)
from ._sandbox import Sandbox as Sandbox, _sandbox_mode, _sandbox_policy
from .async_client import AsyncAppServerClient
from .client import AppServerClient, CodexConfig
from .async_client import AsyncCodexClient
from .client import CodexClient, CodexConfig
from .generated.v2_all import (
ApiKeyLoginAccountParams,
GetAccountParams,
Expand Down Expand Up @@ -73,10 +73,10 @@


class Codex:
"""Typed Python client for app-server v2 workflows."""
"""Typed Python client for Codex workflows."""

def __init__(self, config: CodexConfig | None = None) -> None:
self._client = AppServerClient(config=config)
self._client = CodexClient(config=config)
try:
self._client.start()
self._init = validate_initialize_metadata(self._client.initialize())
Expand All @@ -98,7 +98,7 @@ def close(self) -> None:
self._client.close()

def login_api_key(self, api_key: str) -> None:
"""Authenticate app-server with an API key."""
"""Authenticate Codex with an API key."""
self._client.account_login_start(
LoginAccountParams(
root=ApiKeyLoginAccountParams(
Expand All @@ -117,11 +117,11 @@ def login_chatgpt_device_code(self) -> DeviceCodeLoginHandle:
return start_device_code_login(self._client)

def account(self, *, refresh_token: bool = False) -> GetAccountResponse:
"""Read the current app-server account state."""
"""Read the current Codex account state."""
return self._client.account_read(GetAccountParams(refresh_token=refresh_token))

def logout(self) -> None:
"""Clear the current app-server account session."""
"""Clear the current Codex account session."""
self._client.account_logout()

# BEGIN GENERATED: Codex.flat_methods
Expand Down Expand Up @@ -282,7 +282,7 @@ class AsyncCodex:
"""

def __init__(self, config: CodexConfig | None = None) -> None:
self._client = AsyncAppServerClient(config=config)
self._client = AsyncCodexClient(config=config)
self._init: InitializeResponse | None = None
self._initialized = False
self._init_lock = asyncio.Lock()
Expand Down Expand Up @@ -326,7 +326,7 @@ async def close(self) -> None:
self._initialized = False

async def login_api_key(self, api_key: str) -> None:
"""Authenticate app-server with an API key."""
"""Authenticate Codex with an API key."""
await self._ensure_initialized()
await self._client.account_login_start(
LoginAccountParams(
Expand All @@ -348,12 +348,12 @@ async def login_chatgpt_device_code(self) -> AsyncDeviceCodeLoginHandle:
return await async_start_device_code_login(self)

async def account(self, *, refresh_token: bool = False) -> GetAccountResponse:
"""Read the current app-server account state."""
"""Read the current Codex account state."""
await self._ensure_initialized()
return await self._client.account_read(GetAccountParams(refresh_token=refresh_token))

async def logout(self) -> None:
"""Clear the current app-server account session."""
"""Clear the current Codex account session."""
await self._ensure_initialized()
await self._client.account_logout()

Expand Down Expand Up @@ -515,7 +515,7 @@ async def models(self, *, include_hidden: bool = False) -> ModelListResponse:

@dataclass(slots=True)
class Thread:
_client: AppServerClient
_client: CodexClient
id: str

def run(
Expand Down Expand Up @@ -689,7 +689,7 @@ async def compact(self) -> ThreadCompactStartResponse:

@dataclass(slots=True)
class TurnHandle:
_client: AppServerClient
_client: CodexClient
thread_id: str
id: str

Expand Down
16 changes: 8 additions & 8 deletions sdk/python/src/openai_codex/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from pydantic import BaseModel

from .client import AppServerClient, CodexConfig
from .client import CodexClient, CodexConfig
from .generated.v2_all import (
AccountLoginCompletedNotification,
AgentMessageDeltaNotification,
Expand Down Expand Up @@ -43,20 +43,20 @@
ReturnT = TypeVar("ReturnT")


class AsyncAppServerClient:
"""Async wrapper around AppServerClient using thread offloading."""
class AsyncCodexClient:
"""Async wrapper around CodexClient using thread offloading."""

def __init__(self, config: CodexConfig | None = None) -> None:
"""Create the wrapped sync client that owns the transport process."""
self._sync = AppServerClient(config=config)
self._sync = CodexClient(config=config)

async def __aenter__(self) -> "AsyncAppServerClient":
"""Start the app-server process when entering an async context."""
async def __aenter__(self) -> "AsyncCodexClient":
"""Start the Codex process when entering an async context."""
await self.start()
return self

async def __aexit__(self, _exc_type, _exc, _tb) -> None:
"""Close the app-server process when leaving an async context."""
"""Close the Codex process when leaving an async context."""
await self.close()

async def _call_sync(
Expand Down Expand Up @@ -88,7 +88,7 @@ async def close(self) -> None:
await self._call_sync(self._sync.close)

async def initialize(self) -> InitializeResponse:
"""Initialize the app-server session."""
"""Initialize the Codex session."""
return await self._call_sync(self._sync.initialize)

def register_turn_notifications(self, turn_id: str) -> None:
Expand Down
Loading
Loading