codex-open-client 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codex_open_client-0.1.0/.github/workflows/ci.yml +28 -0
- codex_open_client-0.1.0/.github/workflows/release.yml +104 -0
- codex_open_client-0.1.0/.gitignore +14 -0
- codex_open_client-0.1.0/CHANGELOG.md +15 -0
- codex_open_client-0.1.0/LICENSE +21 -0
- codex_open_client-0.1.0/PKG-INFO +156 -0
- codex_open_client-0.1.0/README.md +123 -0
- codex_open_client-0.1.0/docs/api/client.md +72 -0
- codex_open_client-0.1.0/docs/api/errors.md +47 -0
- codex_open_client-0.1.0/docs/api/stream-events.md +41 -0
- codex_open_client-0.1.0/docs/api/types.md +50 -0
- codex_open_client-0.1.0/docs/dev/internals.md +164 -0
- codex_open_client-0.1.0/docs/getting-started.md +79 -0
- codex_open_client-0.1.0/docs/guide/authentication.md +97 -0
- codex_open_client-0.1.0/docs/guide/error-handling.md +106 -0
- codex_open_client-0.1.0/docs/guide/models.md +48 -0
- codex_open_client-0.1.0/docs/guide/responses.md +118 -0
- codex_open_client-0.1.0/docs/guide/streaming.md +105 -0
- codex_open_client-0.1.0/docs/guide/tool-calls.md +127 -0
- codex_open_client-0.1.0/docs/index.md +40 -0
- codex_open_client-0.1.0/mkdocs.yml +68 -0
- codex_open_client-0.1.0/pyproject.toml +81 -0
- codex_open_client-0.1.0/src/codex_open_client/__init__.py +133 -0
- codex_open_client-0.1.0/src/codex_open_client/_api.py +45 -0
- codex_open_client-0.1.0/src/codex_open_client/_auth.py +285 -0
- codex_open_client-0.1.0/src/codex_open_client/_client.py +114 -0
- codex_open_client-0.1.0/src/codex_open_client/_config.py +76 -0
- codex_open_client-0.1.0/src/codex_open_client/_errors.py +133 -0
- codex_open_client-0.1.0/src/codex_open_client/_models.py +99 -0
- codex_open_client-0.1.0/src/codex_open_client/_pkce.py +16 -0
- codex_open_client-0.1.0/src/codex_open_client/_responses.py +258 -0
- codex_open_client-0.1.0/src/codex_open_client/_server.py +98 -0
- codex_open_client-0.1.0/src/codex_open_client/_stream.py +250 -0
- codex_open_client-0.1.0/src/codex_open_client/_types.py +320 -0
- codex_open_client-0.1.0/src/codex_open_client/_version.py +1 -0
- codex_open_client-0.1.0/src/codex_open_client/py.typed +0 -0
- codex_open_client-0.1.0/tests/__init__.py +0 -0
- codex_open_client-0.1.0/tests/test_api.py +74 -0
- codex_open_client-0.1.0/tests/test_auth.py +98 -0
- codex_open_client-0.1.0/tests/test_client_live.py +239 -0
- codex_open_client-0.1.0/tests/test_client_unit.py +68 -0
- codex_open_client-0.1.0/tests/test_config.py +79 -0
- codex_open_client-0.1.0/tests/test_errors.py +122 -0
- codex_open_client-0.1.0/tests/test_interactive.py +171 -0
- codex_open_client-0.1.0/tests/test_live.py +80 -0
- codex_open_client-0.1.0/tests/test_models.py +46 -0
- codex_open_client-0.1.0/tests/test_pkce.py +35 -0
- codex_open_client-0.1.0/tests/test_responses.py +89 -0
- codex_open_client-0.1.0/tests/test_stream.py +340 -0
- codex_open_client-0.1.0/tests/test_types.py +97 -0
- codex_open_client-0.1.0/tests/test_version.py +5 -0
- codex_open_client-0.1.0/uv.lock +1351 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, develop]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, develop]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: astral-sh/setup-uv@v6
|
|
15
|
+
- run: uv run ruff check src/ tests/
|
|
16
|
+
- run: uv run mypy src/codex_open_client/ tests/ --strict
|
|
17
|
+
|
|
18
|
+
test:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
strategy:
|
|
21
|
+
matrix:
|
|
22
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
- uses: astral-sh/setup-uv@v6
|
|
26
|
+
with:
|
|
27
|
+
python-version: ${{ matrix.python-version }}
|
|
28
|
+
- run: uv run pytest -x -q
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: astral-sh/setup-uv@v6
|
|
16
|
+
with:
|
|
17
|
+
python-version: ${{ matrix.python-version }}
|
|
18
|
+
- run: uv run ruff check src/ tests/
|
|
19
|
+
- run: uv run mypy src/codex_open_client/ tests/ --strict
|
|
20
|
+
- run: uv run pytest -x -q
|
|
21
|
+
|
|
22
|
+
check-version:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- name: Verify tag matches package version
|
|
27
|
+
run: |
|
|
28
|
+
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
|
|
29
|
+
PKG_VERSION=$(grep '__version__' src/codex_open_client/_version.py | sed "s/.*\"\(.*\)\"/\1/")
|
|
30
|
+
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
|
|
31
|
+
echo "::error::Tag version ($TAG_VERSION) does not match package version ($PKG_VERSION)"
|
|
32
|
+
exit 1
|
|
33
|
+
fi
|
|
34
|
+
echo "Version: $TAG_VERSION"
|
|
35
|
+
|
|
36
|
+
publish:
|
|
37
|
+
needs: [test, check-version]
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
permissions:
|
|
40
|
+
id-token: write
|
|
41
|
+
environment: pypi
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
- uses: astral-sh/setup-uv@v6
|
|
45
|
+
- run: uv build
|
|
46
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
47
|
+
|
|
48
|
+
docs:
|
|
49
|
+
needs: publish
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
permissions:
|
|
52
|
+
contents: write
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v4
|
|
55
|
+
with:
|
|
56
|
+
fetch-depth: 0
|
|
57
|
+
- uses: astral-sh/setup-uv@v6
|
|
58
|
+
- name: Configure git
|
|
59
|
+
run: |
|
|
60
|
+
git config user.name "github-actions[bot]"
|
|
61
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
62
|
+
- name: Deploy docs
|
|
63
|
+
run: |
|
|
64
|
+
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
|
|
65
|
+
|
|
66
|
+
# Extract major.minor for the doc version alias
|
|
67
|
+
MINOR_VERSION=$(echo "$TAG_VERSION" | grep -oP '^\d+\.\d+')
|
|
68
|
+
|
|
69
|
+
# Check if this is a pre-release (alpha/beta/rc)
|
|
70
|
+
if echo "$TAG_VERSION" | grep -qP '(a|b|rc)\d+'; then
|
|
71
|
+
# Pre-release: deploy under "X.Y-beta", no alias update
|
|
72
|
+
uv run mike deploy "${MINOR_VERSION}-beta" --push
|
|
73
|
+
else
|
|
74
|
+
# Stable: deploy under "X.Y" and update "latest" alias
|
|
75
|
+
uv run mike deploy "${MINOR_VERSION}" latest --update-aliases --push
|
|
76
|
+
uv run mike set-default latest --push
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
github-release:
|
|
80
|
+
needs: [publish, docs]
|
|
81
|
+
runs-on: ubuntu-latest
|
|
82
|
+
permissions:
|
|
83
|
+
contents: write
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/checkout@v4
|
|
86
|
+
- name: Create GitHub Release
|
|
87
|
+
run: |
|
|
88
|
+
TAG="${GITHUB_REF#refs/tags/}"
|
|
89
|
+
VERSION="${TAG#v}"
|
|
90
|
+
|
|
91
|
+
if echo "$VERSION" | grep -qP '(a|b|rc)\d+'; then
|
|
92
|
+
PRERELEASE="--prerelease"
|
|
93
|
+
TITLE="codex-open-client $VERSION (pre-release)"
|
|
94
|
+
else
|
|
95
|
+
PRERELEASE=""
|
|
96
|
+
TITLE="codex-open-client $VERSION"
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
gh release create "$TAG" \
|
|
100
|
+
--title "$TITLE" \
|
|
101
|
+
--generate-notes \
|
|
102
|
+
$PRERELEASE
|
|
103
|
+
env:
|
|
104
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
Initial release.
|
|
6
|
+
|
|
7
|
+
- OAuth 2.0 PKCE authentication with token caching and refresh
|
|
8
|
+
- Three login modes: browser, headless, custom handler
|
|
9
|
+
- Two-step login flow (`start_login` / `finish_login`)
|
|
10
|
+
- `CodexClient` with typed `responses.create()` and `models.list()`
|
|
11
|
+
- Streaming support via `ResponseStream` (SSE parsing, context manager)
|
|
12
|
+
- Function tool calls with roundtrip support
|
|
13
|
+
- Typed dataclasses for all API objects
|
|
14
|
+
- Exception hierarchy with automatic retry on 429/5xx
|
|
15
|
+
- Interop with Codex CLI token storage (`~/.codex/auth.json`)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yegor
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codex-open-client
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python client for OpenAI Codex — use your ChatGPT subscription for API access
|
|
5
|
+
Project-URL: Homepage, https://github.com/lunavod/codex-py
|
|
6
|
+
Project-URL: Documentation, https://lunavod.github.io/codex-py/
|
|
7
|
+
Project-URL: Repository, https://github.com/lunavod/codex-py
|
|
8
|
+
Project-URL: Issues, https://github.com/lunavod/codex-py/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/lunavod/codex-py/blob/main/CHANGELOG.md
|
|
10
|
+
Author: Yegor
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: api-client,chatgpt,codex,oauth,openai,pkce
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: httpx>=0.27
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.8; extra == 'dev'
|
|
30
|
+
Provides-Extra: openai
|
|
31
|
+
Requires-Dist: openai>=1.0; extra == 'openai'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# codex-open-client
|
|
35
|
+
|
|
36
|
+
[](https://pypi.org/project/codex-open-client/)
|
|
37
|
+
[](https://pypi.org/project/codex-open-client/)
|
|
38
|
+
[](LICENSE)
|
|
39
|
+
[](https://github.com/lunavod/codex-open-client/actions/workflows/ci.yml)
|
|
40
|
+
|
|
41
|
+
Python client for OpenAI Codex — use your ChatGPT Plus/Pro subscription for API access.
|
|
42
|
+
|
|
43
|
+
**[Documentation](https://lunavod.github.io/codex-open-client/)**
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install codex-open-client
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Quick Start
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
import codex_open_client
|
|
55
|
+
|
|
56
|
+
client = codex_open_client.CodexClient()
|
|
57
|
+
|
|
58
|
+
response = client.responses.create(
|
|
59
|
+
model="gpt-5.1-codex-mini",
|
|
60
|
+
instructions="Be brief.",
|
|
61
|
+
input="What is 2 + 2?",
|
|
62
|
+
)
|
|
63
|
+
print(response.output_text)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
On first run, your browser opens for OAuth login. Tokens are cached at `~/.codex/auth.json` (shared with the official Codex CLI) and refreshed automatically after that.
|
|
67
|
+
|
|
68
|
+
## Authentication
|
|
69
|
+
|
|
70
|
+
Multiple ways to authenticate, depending on your environment:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
# Default — opens browser, local server catches the callback
|
|
74
|
+
client = codex_open_client.CodexClient()
|
|
75
|
+
|
|
76
|
+
# Headless — prints URL, you paste the redirect URL back (servers, Docker, CI)
|
|
77
|
+
client = codex_open_client.CodexClient(headless=True)
|
|
78
|
+
|
|
79
|
+
# Custom handler — full control over the auth UX (GUI apps, bots, web apps)
|
|
80
|
+
def my_handler(url: str) -> str:
|
|
81
|
+
send_url_to_user(url)
|
|
82
|
+
return get_callback_url_from_user()
|
|
83
|
+
|
|
84
|
+
client = codex_open_client.CodexClient(login_handler=my_handler)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
For async or multi-step flows, use the two-step API:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
auth = codex_open_client.start_login()
|
|
91
|
+
# present auth.url to the user, collect callback URL however you want
|
|
92
|
+
tokens = codex_open_client.finish_login(auth, callback_url="http://localhost:1455/...")
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Streaming
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
with client.responses.create(
|
|
99
|
+
model="gpt-5.1-codex-mini",
|
|
100
|
+
instructions="Be helpful.",
|
|
101
|
+
input="Write a haiku about Python.",
|
|
102
|
+
stream=True,
|
|
103
|
+
) as stream:
|
|
104
|
+
for event in stream:
|
|
105
|
+
if isinstance(event, codex_open_client.ResponseOutputTextDeltaEvent):
|
|
106
|
+
print(event.delta, end="", flush=True)
|
|
107
|
+
print()
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Tool Calls
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
import json
|
|
114
|
+
|
|
115
|
+
tool = codex_open_client.FunctionTool(
|
|
116
|
+
name="get_weather",
|
|
117
|
+
description="Get weather for a city.",
|
|
118
|
+
parameters={
|
|
119
|
+
"type": "object",
|
|
120
|
+
"properties": {"city": {"type": "string"}},
|
|
121
|
+
"required": ["city"],
|
|
122
|
+
"additionalProperties": False,
|
|
123
|
+
},
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
response = client.responses.create(
|
|
127
|
+
model="gpt-5.1-codex-mini",
|
|
128
|
+
instructions="Use tools when helpful.",
|
|
129
|
+
input="What's the weather in Tokyo?",
|
|
130
|
+
tools=[tool],
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
for call in response.tool_calls:
|
|
134
|
+
print(f"{call.name}({call.arguments})")
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Features
|
|
138
|
+
|
|
139
|
+
- **Automatic auth** — OAuth PKCE with token caching and refresh
|
|
140
|
+
- **Typed API** — dataclass-based types for all objects, full mypy strict support
|
|
141
|
+
- **Streaming** — iterate SSE events with context manager support
|
|
142
|
+
- **Tool calls** — function calling with roundtrip helpers
|
|
143
|
+
- **Retries** — built-in exponential backoff for 429/5xx
|
|
144
|
+
- **Models** — list available models with cached metadata
|
|
145
|
+
- **Headless mode** — works on remote servers, Docker, CI
|
|
146
|
+
- **Custom login** — bring your own auth UX with `login_handler`
|
|
147
|
+
- **CLI interop** — shares token storage with the official Codex CLI
|
|
148
|
+
|
|
149
|
+
## Requirements
|
|
150
|
+
|
|
151
|
+
- Python 3.10+
|
|
152
|
+
- ChatGPT Plus or Pro subscription
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
MIT
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# codex-open-client
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/codex-open-client/)
|
|
4
|
+
[](https://pypi.org/project/codex-open-client/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://github.com/lunavod/codex-open-client/actions/workflows/ci.yml)
|
|
7
|
+
|
|
8
|
+
Python client for OpenAI Codex — use your ChatGPT Plus/Pro subscription for API access.
|
|
9
|
+
|
|
10
|
+
**[Documentation](https://lunavod.github.io/codex-open-client/)**
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install codex-open-client
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
import codex_open_client
|
|
22
|
+
|
|
23
|
+
client = codex_open_client.CodexClient()
|
|
24
|
+
|
|
25
|
+
response = client.responses.create(
|
|
26
|
+
model="gpt-5.1-codex-mini",
|
|
27
|
+
instructions="Be brief.",
|
|
28
|
+
input="What is 2 + 2?",
|
|
29
|
+
)
|
|
30
|
+
print(response.output_text)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
On first run, your browser opens for OAuth login. Tokens are cached at `~/.codex/auth.json` (shared with the official Codex CLI) and refreshed automatically after that.
|
|
34
|
+
|
|
35
|
+
## Authentication
|
|
36
|
+
|
|
37
|
+
Multiple ways to authenticate, depending on your environment:
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
# Default — opens browser, local server catches the callback
|
|
41
|
+
client = codex_open_client.CodexClient()
|
|
42
|
+
|
|
43
|
+
# Headless — prints URL, you paste the redirect URL back (servers, Docker, CI)
|
|
44
|
+
client = codex_open_client.CodexClient(headless=True)
|
|
45
|
+
|
|
46
|
+
# Custom handler — full control over the auth UX (GUI apps, bots, web apps)
|
|
47
|
+
def my_handler(url: str) -> str:
|
|
48
|
+
send_url_to_user(url)
|
|
49
|
+
return get_callback_url_from_user()
|
|
50
|
+
|
|
51
|
+
client = codex_open_client.CodexClient(login_handler=my_handler)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
For async or multi-step flows, use the two-step API:
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
auth = codex_open_client.start_login()
|
|
58
|
+
# present auth.url to the user, collect callback URL however you want
|
|
59
|
+
tokens = codex_open_client.finish_login(auth, callback_url="http://localhost:1455/...")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Streaming
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
with client.responses.create(
|
|
66
|
+
model="gpt-5.1-codex-mini",
|
|
67
|
+
instructions="Be helpful.",
|
|
68
|
+
input="Write a haiku about Python.",
|
|
69
|
+
stream=True,
|
|
70
|
+
) as stream:
|
|
71
|
+
for event in stream:
|
|
72
|
+
if isinstance(event, codex_open_client.ResponseOutputTextDeltaEvent):
|
|
73
|
+
print(event.delta, end="", flush=True)
|
|
74
|
+
print()
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Tool Calls
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
import json
|
|
81
|
+
|
|
82
|
+
tool = codex_open_client.FunctionTool(
|
|
83
|
+
name="get_weather",
|
|
84
|
+
description="Get weather for a city.",
|
|
85
|
+
parameters={
|
|
86
|
+
"type": "object",
|
|
87
|
+
"properties": {"city": {"type": "string"}},
|
|
88
|
+
"required": ["city"],
|
|
89
|
+
"additionalProperties": False,
|
|
90
|
+
},
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
response = client.responses.create(
|
|
94
|
+
model="gpt-5.1-codex-mini",
|
|
95
|
+
instructions="Use tools when helpful.",
|
|
96
|
+
input="What's the weather in Tokyo?",
|
|
97
|
+
tools=[tool],
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
for call in response.tool_calls:
|
|
101
|
+
print(f"{call.name}({call.arguments})")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Features
|
|
105
|
+
|
|
106
|
+
- **Automatic auth** — OAuth PKCE with token caching and refresh
|
|
107
|
+
- **Typed API** — dataclass-based types for all objects, full mypy strict support
|
|
108
|
+
- **Streaming** — iterate SSE events with context manager support
|
|
109
|
+
- **Tool calls** — function calling with roundtrip helpers
|
|
110
|
+
- **Retries** — built-in exponential backoff for 429/5xx
|
|
111
|
+
- **Models** — list available models with cached metadata
|
|
112
|
+
- **Headless mode** — works on remote servers, Docker, CI
|
|
113
|
+
- **Custom login** — bring your own auth UX with `login_handler`
|
|
114
|
+
- **CLI interop** — shares token storage with the official Codex CLI
|
|
115
|
+
|
|
116
|
+
## Requirements
|
|
117
|
+
|
|
118
|
+
- Python 3.10+
|
|
119
|
+
- ChatGPT Plus or Pro subscription
|
|
120
|
+
|
|
121
|
+
## License
|
|
122
|
+
|
|
123
|
+
MIT
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# CodexClient
|
|
2
|
+
|
|
3
|
+
The main entry point for the Codex API.
|
|
4
|
+
|
|
5
|
+
::: codex_open_client.CodexClient
|
|
6
|
+
options:
|
|
7
|
+
members:
|
|
8
|
+
- __init__
|
|
9
|
+
- login
|
|
10
|
+
- token
|
|
11
|
+
- account_id
|
|
12
|
+
|
|
13
|
+
## Responses
|
|
14
|
+
|
|
15
|
+
::: codex_open_client._responses.Responses
|
|
16
|
+
options:
|
|
17
|
+
members:
|
|
18
|
+
- create
|
|
19
|
+
|
|
20
|
+
## ResponseStream
|
|
21
|
+
|
|
22
|
+
::: codex_open_client._stream.ResponseStream
|
|
23
|
+
options:
|
|
24
|
+
members:
|
|
25
|
+
- __iter__
|
|
26
|
+
- get_final_response
|
|
27
|
+
- close
|
|
28
|
+
- __enter__
|
|
29
|
+
- __exit__
|
|
30
|
+
|
|
31
|
+
## Models
|
|
32
|
+
|
|
33
|
+
::: codex_open_client._models.Models
|
|
34
|
+
options:
|
|
35
|
+
members:
|
|
36
|
+
- list
|
|
37
|
+
|
|
38
|
+
## Authentication Functions
|
|
39
|
+
|
|
40
|
+
### login
|
|
41
|
+
|
|
42
|
+
::: codex_open_client.login
|
|
43
|
+
|
|
44
|
+
### get_token
|
|
45
|
+
|
|
46
|
+
::: codex_open_client.get_token
|
|
47
|
+
|
|
48
|
+
### refresh
|
|
49
|
+
|
|
50
|
+
::: codex_open_client.refresh
|
|
51
|
+
|
|
52
|
+
### start_login
|
|
53
|
+
|
|
54
|
+
::: codex_open_client.start_login
|
|
55
|
+
|
|
56
|
+
### finish_login
|
|
57
|
+
|
|
58
|
+
::: codex_open_client.finish_login
|
|
59
|
+
|
|
60
|
+
### PendingLogin
|
|
61
|
+
|
|
62
|
+
::: codex_open_client.PendingLogin
|
|
63
|
+
|
|
64
|
+
## Helper Functions
|
|
65
|
+
|
|
66
|
+
### build_headers
|
|
67
|
+
|
|
68
|
+
::: codex_open_client.build_headers
|
|
69
|
+
|
|
70
|
+
### get_account_id
|
|
71
|
+
|
|
72
|
+
::: codex_open_client.get_account_id
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Errors
|
|
2
|
+
|
|
3
|
+
## Hierarchy
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
CodexError
|
|
7
|
+
├── APIError
|
|
8
|
+
│ ├── AuthError
|
|
9
|
+
│ ├── RateLimitError
|
|
10
|
+
│ ├── InvalidRequestError
|
|
11
|
+
│ │ └── ContextWindowError
|
|
12
|
+
│ ├── QuotaExceededError
|
|
13
|
+
│ └── ServerError
|
|
14
|
+
├── APIConnectionError
|
|
15
|
+
│ └── APITimeoutError
|
|
16
|
+
└── StreamError
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Base Classes
|
|
20
|
+
|
|
21
|
+
::: codex_open_client.CodexError
|
|
22
|
+
|
|
23
|
+
::: codex_open_client.APIError
|
|
24
|
+
|
|
25
|
+
::: codex_open_client.APIConnectionError
|
|
26
|
+
|
|
27
|
+
## API Errors
|
|
28
|
+
|
|
29
|
+
::: codex_open_client.AuthError
|
|
30
|
+
|
|
31
|
+
::: codex_open_client.RateLimitError
|
|
32
|
+
|
|
33
|
+
::: codex_open_client.InvalidRequestError
|
|
34
|
+
|
|
35
|
+
::: codex_open_client.ContextWindowError
|
|
36
|
+
|
|
37
|
+
::: codex_open_client.QuotaExceededError
|
|
38
|
+
|
|
39
|
+
::: codex_open_client.ServerError
|
|
40
|
+
|
|
41
|
+
## Connection Errors
|
|
42
|
+
|
|
43
|
+
::: codex_open_client.APITimeoutError
|
|
44
|
+
|
|
45
|
+
## Stream Errors
|
|
46
|
+
|
|
47
|
+
::: codex_open_client.StreamError
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Stream Events
|
|
2
|
+
|
|
3
|
+
All stream events are dataclasses with a `type` field matching the SSE event name.
|
|
4
|
+
|
|
5
|
+
Use `isinstance()` checks to handle specific event types when iterating a `ResponseStream`.
|
|
6
|
+
|
|
7
|
+
## Response Lifecycle Events
|
|
8
|
+
|
|
9
|
+
::: codex_open_client.ResponseCreatedEvent
|
|
10
|
+
|
|
11
|
+
::: codex_open_client.ResponseInProgressEvent
|
|
12
|
+
|
|
13
|
+
::: codex_open_client.ResponseCompletedEvent
|
|
14
|
+
|
|
15
|
+
::: codex_open_client.ResponseFailedEvent
|
|
16
|
+
|
|
17
|
+
::: codex_open_client.ResponseIncompleteEvent
|
|
18
|
+
|
|
19
|
+
## Text Events
|
|
20
|
+
|
|
21
|
+
::: codex_open_client.ResponseOutputTextDeltaEvent
|
|
22
|
+
|
|
23
|
+
::: codex_open_client.ResponseOutputTextDoneEvent
|
|
24
|
+
|
|
25
|
+
## Output Item Events
|
|
26
|
+
|
|
27
|
+
::: codex_open_client.ResponseOutputItemAddedEvent
|
|
28
|
+
|
|
29
|
+
::: codex_open_client.ResponseOutputItemDoneEvent
|
|
30
|
+
|
|
31
|
+
## Function Call Events
|
|
32
|
+
|
|
33
|
+
::: codex_open_client.ResponseFunctionCallArgumentsDeltaEvent
|
|
34
|
+
|
|
35
|
+
::: codex_open_client.ResponseFunctionCallArgumentsDoneEvent
|
|
36
|
+
|
|
37
|
+
## Reasoning Events
|
|
38
|
+
|
|
39
|
+
::: codex_open_client.ResponseReasoningSummaryTextDeltaEvent
|
|
40
|
+
|
|
41
|
+
::: codex_open_client.ResponseReasoningSummaryTextDoneEvent
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Types
|
|
2
|
+
|
|
3
|
+
All types are dataclasses with `slots=True`.
|
|
4
|
+
|
|
5
|
+
## Response
|
|
6
|
+
|
|
7
|
+
::: codex_open_client.Response
|
|
8
|
+
options:
|
|
9
|
+
members:
|
|
10
|
+
- output_text
|
|
11
|
+
- reasoning_summary
|
|
12
|
+
- tool_calls
|
|
13
|
+
|
|
14
|
+
::: codex_open_client.Usage
|
|
15
|
+
|
|
16
|
+
::: codex_open_client.ResponseError
|
|
17
|
+
|
|
18
|
+
## Output Types
|
|
19
|
+
|
|
20
|
+
::: codex_open_client.ResponseOutputMessage
|
|
21
|
+
|
|
22
|
+
::: codex_open_client.OutputText
|
|
23
|
+
|
|
24
|
+
::: codex_open_client.ResponseFunctionToolCall
|
|
25
|
+
|
|
26
|
+
::: codex_open_client.ResponseReasoningItem
|
|
27
|
+
|
|
28
|
+
::: codex_open_client.ReasoningSummary
|
|
29
|
+
|
|
30
|
+
## Input Types
|
|
31
|
+
|
|
32
|
+
::: codex_open_client.InputMessage
|
|
33
|
+
|
|
34
|
+
::: codex_open_client.InputText
|
|
35
|
+
|
|
36
|
+
::: codex_open_client.InputImage
|
|
37
|
+
|
|
38
|
+
::: codex_open_client.FunctionCallOutput
|
|
39
|
+
|
|
40
|
+
## Tools & Config
|
|
41
|
+
|
|
42
|
+
::: codex_open_client.FunctionTool
|
|
43
|
+
|
|
44
|
+
::: codex_open_client.Reasoning
|
|
45
|
+
|
|
46
|
+
::: codex_open_client.TextConfig
|
|
47
|
+
|
|
48
|
+
## Model
|
|
49
|
+
|
|
50
|
+
::: codex_open_client.Model
|