mirror of
https://github.com/openai/codex.git
synced 2026-05-15 16:53:05 +00:00
Narrow Python SDK root exports
Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -3,8 +3,9 @@
|
||||
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 app-server’s camelCase wire format.
|
||||
runtime package. The package root exports the supported ergonomic SDK surface
|
||||
plus selected public value types; generated transport modules are shipped for
|
||||
runtime use but are not the supported public API.
|
||||
|
||||
## Install
|
||||
|
||||
@@ -110,4 +111,4 @@ This supports the CI release flow:
|
||||
- Use context managers (`with Codex() as codex:`) to ensure shutdown.
|
||||
- Prefer `thread.run("...")` for the common case. Use `thread.turn(...)` when
|
||||
you need streaming, steering, or interrupt control.
|
||||
- For transient overload, use `codex_app_server.retry.retry_on_overload`.
|
||||
- For transient overload, import `retry_on_overload` from `codex_app_server`.
|
||||
|
||||
@@ -10,12 +10,12 @@ This SDK surface is experimental. Turn streams are routed by turn ID so one clie
|
||||
from codex_app_server import (
|
||||
Codex,
|
||||
AsyncCodex,
|
||||
AppServerConfig,
|
||||
RunResult,
|
||||
Thread,
|
||||
AsyncThread,
|
||||
TurnHandle,
|
||||
AsyncTurnHandle,
|
||||
InitializeResponse,
|
||||
Input,
|
||||
InputItem,
|
||||
TextInput,
|
||||
@@ -24,13 +24,14 @@ from codex_app_server import (
|
||||
SkillInput,
|
||||
MentionInput,
|
||||
TurnStatus,
|
||||
retry_on_overload,
|
||||
)
|
||||
from codex_app_server.generated.v2_all import ThreadItem, ThreadTokenUsage
|
||||
```
|
||||
|
||||
- Version: `codex_app_server.__version__`
|
||||
- Requires Python >= 3.10
|
||||
- Canonical generated app-server models live in `codex_app_server.generated.v2_all`
|
||||
- The package root `__all__` is the supported public import surface; generated
|
||||
transport modules are shipped for runtime use but are not re-exported.
|
||||
|
||||
## Codex (sync)
|
||||
|
||||
@@ -165,20 +166,23 @@ InputItem = TextInput | ImageInput | LocalImageInput | SkillInput | MentionInput
|
||||
Input = list[InputItem] | InputItem
|
||||
```
|
||||
|
||||
## Generated Models
|
||||
## Public Value Types
|
||||
|
||||
The SDK wrappers return and accept canonical generated app-server models wherever possible:
|
||||
The package root exports the ergonomic SDK plus selected value types used by
|
||||
public method signatures:
|
||||
|
||||
```python
|
||||
from codex_app_server.generated.v2_all import (
|
||||
from codex_app_server import (
|
||||
AskForApproval,
|
||||
ThreadReadResponse,
|
||||
Turn,
|
||||
TurnStartParams,
|
||||
ReasoningEffort,
|
||||
SandboxPolicy,
|
||||
TurnStatus,
|
||||
)
|
||||
```
|
||||
|
||||
Generated transport modules are shipped for SDK runtime use, but they are not
|
||||
the supported root API.
|
||||
|
||||
## Retry + errors
|
||||
|
||||
```python
|
||||
|
||||
@@ -95,12 +95,12 @@ with Codex() as codex:
|
||||
print(result.final_response)
|
||||
```
|
||||
|
||||
## 6) Generated models
|
||||
## 6) Public value types
|
||||
|
||||
The convenience wrappers live at the package root, but the canonical app-server models live under:
|
||||
The convenience wrappers and selected value types live at the package root:
|
||||
|
||||
```python
|
||||
from codex_app_server.generated.v2_all import Turn, TurnStatus, ThreadReadResponse
|
||||
from codex_app_server import AskForApproval, ReasoningEffort, SandboxPolicy, TurnStatus
|
||||
```
|
||||
|
||||
## 7) Next stops
|
||||
|
||||
@@ -14,8 +14,6 @@ import asyncio
|
||||
from codex_app_server import (
|
||||
AsyncCodex,
|
||||
TextInput,
|
||||
ThreadTokenUsageUpdatedNotification,
|
||||
TurnCompletedNotification,
|
||||
)
|
||||
|
||||
|
||||
@@ -72,12 +70,13 @@ async def main() -> None:
|
||||
print(delta, end="", flush=True)
|
||||
printed_delta = True
|
||||
continue
|
||||
if isinstance(payload, ThreadTokenUsageUpdatedNotification):
|
||||
usage = payload.token_usage
|
||||
if event.method == "thread/tokenUsage/updated":
|
||||
usage = getattr(payload, "token_usage", None)
|
||||
continue
|
||||
if isinstance(payload, TurnCompletedNotification):
|
||||
status = payload.turn.status
|
||||
error = payload.turn.error
|
||||
if event.method == "turn/completed":
|
||||
turn = getattr(payload, "turn", None)
|
||||
status = getattr(turn, "status", None)
|
||||
error = getattr(turn, "error", None)
|
||||
|
||||
if printed_delta:
|
||||
print()
|
||||
|
||||
@@ -12,8 +12,6 @@ ensure_local_sdk_src()
|
||||
from codex_app_server import (
|
||||
Codex,
|
||||
TextInput,
|
||||
ThreadTokenUsageUpdatedNotification,
|
||||
TurnCompletedNotification,
|
||||
)
|
||||
|
||||
print("Codex mini CLI. Type /exit to quit.")
|
||||
@@ -69,12 +67,13 @@ with Codex(config=runtime_config()) as codex:
|
||||
print(delta, end="", flush=True)
|
||||
printed_delta = True
|
||||
continue
|
||||
if isinstance(payload, ThreadTokenUsageUpdatedNotification):
|
||||
usage = payload.token_usage
|
||||
if event.method == "thread/tokenUsage/updated":
|
||||
usage = getattr(payload, "token_usage", None)
|
||||
continue
|
||||
if isinstance(payload, TurnCompletedNotification):
|
||||
status = payload.turn.status
|
||||
error = payload.turn.error
|
||||
if event.method == "turn/completed":
|
||||
turn = getattr(payload, "turn", None)
|
||||
status = getattr(turn, "status", None)
|
||||
error = getattr(turn, "error", None)
|
||||
|
||||
if printed_delta:
|
||||
print()
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from .async_client import AsyncAppServerClient
|
||||
from .client import AppServerClient, AppServerConfig
|
||||
from .client import AppServerConfig
|
||||
from .errors import (
|
||||
AppServerError,
|
||||
AppServerRpcError,
|
||||
@@ -15,6 +14,7 @@ from .errors import (
|
||||
is_retryable_error,
|
||||
)
|
||||
from .generated.v2_all import (
|
||||
ApprovalsReviewer,
|
||||
AskForApproval,
|
||||
Personality,
|
||||
PlanType,
|
||||
@@ -22,21 +22,14 @@ from .generated.v2_all import (
|
||||
ReasoningSummary,
|
||||
SandboxMode,
|
||||
SandboxPolicy,
|
||||
ThreadItem,
|
||||
ThreadForkParams,
|
||||
ThreadListParams,
|
||||
ThreadResumeParams,
|
||||
SortDirection,
|
||||
ThreadListCwdFilter,
|
||||
ThreadSortKey,
|
||||
ThreadSource,
|
||||
ThreadSourceKind,
|
||||
ThreadStartParams,
|
||||
ThreadTokenUsageUpdatedNotification,
|
||||
TurnCompletedNotification,
|
||||
TurnStartParams,
|
||||
ThreadStartSource,
|
||||
TurnStatus,
|
||||
TurnSteerParams,
|
||||
)
|
||||
from .models import InitializeResponse
|
||||
from .api import (
|
||||
AsyncCodex,
|
||||
AsyncThread,
|
||||
@@ -58,8 +51,6 @@ from ._version import __version__
|
||||
|
||||
__all__ = [
|
||||
"__version__",
|
||||
"AppServerClient",
|
||||
"AsyncAppServerClient",
|
||||
"AppServerConfig",
|
||||
"Codex",
|
||||
"AsyncCodex",
|
||||
@@ -67,7 +58,6 @@ __all__ = [
|
||||
"AsyncThread",
|
||||
"TurnHandle",
|
||||
"AsyncTurnHandle",
|
||||
"InitializeResponse",
|
||||
"RunResult",
|
||||
"Input",
|
||||
"InputItem",
|
||||
@@ -76,9 +66,7 @@ __all__ = [
|
||||
"LocalImageInput",
|
||||
"SkillInput",
|
||||
"MentionInput",
|
||||
"ThreadItem",
|
||||
"ThreadTokenUsageUpdatedNotification",
|
||||
"TurnCompletedNotification",
|
||||
"ApprovalsReviewer",
|
||||
"AskForApproval",
|
||||
"Personality",
|
||||
"PlanType",
|
||||
@@ -86,16 +74,13 @@ __all__ = [
|
||||
"ReasoningSummary",
|
||||
"SandboxMode",
|
||||
"SandboxPolicy",
|
||||
"ThreadStartParams",
|
||||
"ThreadResumeParams",
|
||||
"ThreadListParams",
|
||||
"SortDirection",
|
||||
"ThreadListCwdFilter",
|
||||
"ThreadSortKey",
|
||||
"ThreadSource",
|
||||
"ThreadSourceKind",
|
||||
"ThreadForkParams",
|
||||
"ThreadStartSource",
|
||||
"TurnStatus",
|
||||
"TurnStartParams",
|
||||
"TurnSteerParams",
|
||||
"retry_on_overload",
|
||||
"AppServerError",
|
||||
"TransportClosedError",
|
||||
|
||||
@@ -7,9 +7,62 @@ from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import codex_app_server
|
||||
from codex_app_server import AppServerConfig, RunResult
|
||||
from codex_app_server import (
|
||||
AppServerConfig,
|
||||
AsyncCodex,
|
||||
AsyncThread,
|
||||
Codex,
|
||||
RunResult,
|
||||
Thread,
|
||||
)
|
||||
from codex_app_server.models import InitializeResponse
|
||||
from codex_app_server.api import AsyncCodex, AsyncThread, Codex, Thread
|
||||
|
||||
EXPECTED_ROOT_EXPORTS = [
|
||||
"__version__",
|
||||
"AppServerConfig",
|
||||
"Codex",
|
||||
"AsyncCodex",
|
||||
"Thread",
|
||||
"AsyncThread",
|
||||
"TurnHandle",
|
||||
"AsyncTurnHandle",
|
||||
"RunResult",
|
||||
"Input",
|
||||
"InputItem",
|
||||
"TextInput",
|
||||
"ImageInput",
|
||||
"LocalImageInput",
|
||||
"SkillInput",
|
||||
"MentionInput",
|
||||
"ApprovalsReviewer",
|
||||
"AskForApproval",
|
||||
"Personality",
|
||||
"PlanType",
|
||||
"ReasoningEffort",
|
||||
"ReasoningSummary",
|
||||
"SandboxMode",
|
||||
"SandboxPolicy",
|
||||
"SortDirection",
|
||||
"ThreadListCwdFilter",
|
||||
"ThreadSortKey",
|
||||
"ThreadSource",
|
||||
"ThreadSourceKind",
|
||||
"ThreadStartSource",
|
||||
"TurnStatus",
|
||||
"retry_on_overload",
|
||||
"AppServerError",
|
||||
"TransportClosedError",
|
||||
"JsonRpcError",
|
||||
"AppServerRpcError",
|
||||
"ParseError",
|
||||
"InvalidRequestError",
|
||||
"MethodNotFoundError",
|
||||
"InvalidParamsError",
|
||||
"InternalRpcError",
|
||||
"ServerBusyError",
|
||||
"RetryLimitExceededError",
|
||||
"is_retryable_error",
|
||||
]
|
||||
|
||||
|
||||
def _keyword_only_names(fn: object) -> list[str]:
|
||||
@@ -53,6 +106,36 @@ def test_package_includes_py_typed_marker() -> None:
|
||||
assert marker.is_file()
|
||||
|
||||
|
||||
def test_package_root_exports_only_public_api() -> None:
|
||||
"""The package root should expose the supported SDK surface, not internals."""
|
||||
assert codex_app_server.__all__ == EXPECTED_ROOT_EXPORTS
|
||||
assert {
|
||||
name: hasattr(codex_app_server, name) for name in EXPECTED_ROOT_EXPORTS
|
||||
} == {name: True for name in EXPECTED_ROOT_EXPORTS}
|
||||
assert {
|
||||
"AppServerClient": hasattr(codex_app_server, "AppServerClient"),
|
||||
"AsyncAppServerClient": hasattr(codex_app_server, "AsyncAppServerClient"),
|
||||
"InitializeResponse": hasattr(codex_app_server, "InitializeResponse"),
|
||||
"ThreadStartParams": hasattr(codex_app_server, "ThreadStartParams"),
|
||||
"TurnStartParams": hasattr(codex_app_server, "TurnStartParams"),
|
||||
} == {
|
||||
"AppServerClient": False,
|
||||
"AsyncAppServerClient": False,
|
||||
"InitializeResponse": False,
|
||||
"ThreadStartParams": False,
|
||||
"TurnStartParams": False,
|
||||
}
|
||||
|
||||
|
||||
def test_package_star_import_matches_public_api() -> None:
|
||||
"""Star imports should follow the same explicit public API list."""
|
||||
namespace: dict[str, object] = {}
|
||||
exec("from codex_app_server import *", namespace)
|
||||
|
||||
exported = set(namespace) - {"__builtins__"}
|
||||
assert exported == set(EXPECTED_ROOT_EXPORTS)
|
||||
|
||||
|
||||
def test_generated_public_signatures_are_snake_case_and_typed() -> None:
|
||||
"""Generated convenience methods should expose typed Pythonic keyword names."""
|
||||
expected = {
|
||||
|
||||
Reference in New Issue
Block a user