codex-backend-sdk 0.1.1__tar.gz → 0.2.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_backend_sdk-0.2.0/.vscode/settings.json +3 -0
- codex_backend_sdk-0.2.0/PKG-INFO +190 -0
- codex_backend_sdk-0.2.0/README.md +164 -0
- {codex_backend_sdk-0.1.1 → codex_backend_sdk-0.2.0}/codex_backend_sdk/__init__.py +25 -31
- codex_backend_sdk-0.2.0/codex_backend_sdk/codex_client.py +786 -0
- {codex_backend_sdk-0.1.1 → codex_backend_sdk-0.2.0}/docs/backend-api.md +1 -10
- codex_backend_sdk-0.2.0/examples/agent.py +54 -0
- {codex_backend_sdk-0.1.1 → codex_backend_sdk-0.2.0}/pyproject.toml +3 -3
- codex_backend_sdk-0.2.0/tests/test_basic.py +35 -0
- codex_backend_sdk-0.2.0/tests/test_conversation.py +33 -0
- codex_backend_sdk-0.2.0/tests/test_reasoning.py +43 -0
- codex_backend_sdk-0.2.0/tests/test_responses_resource.py +141 -0
- codex_backend_sdk-0.2.0/tests/test_structured_output.py +57 -0
- codex_backend_sdk-0.2.0/tests/test_tools.py +66 -0
- codex_backend_sdk-0.1.1/CHANGELOG.md +0 -7
- codex_backend_sdk-0.1.1/PKG-INFO +0 -369
- codex_backend_sdk-0.1.1/README.md +0 -341
- codex_backend_sdk-0.1.1/codex_backend_sdk/codex_client.py +0 -1084
- codex_backend_sdk-0.1.1/examples/agent.py +0 -356
- codex_backend_sdk-0.1.1/tests/test_abort.py +0 -69
- codex_backend_sdk-0.1.1/tests/test_account_info.py +0 -63
- codex_backend_sdk-0.1.1/tests/test_basic.py +0 -65
- codex_backend_sdk-0.1.1/tests/test_conversation.py +0 -73
- codex_backend_sdk-0.1.1/tests/test_realtime.py +0 -81
- codex_backend_sdk-0.1.1/tests/test_reasoning.py +0 -80
- codex_backend_sdk-0.1.1/tests/test_structured_output.py +0 -68
- codex_backend_sdk-0.1.1/tests/test_tools.py +0 -117
- {codex_backend_sdk-0.1.1 → codex_backend_sdk-0.2.0}/.gitignore +0 -0
- {codex_backend_sdk-0.1.1 → codex_backend_sdk-0.2.0}/LICENSE +0 -0
- {codex_backend_sdk-0.1.1 → codex_backend_sdk-0.2.0}/codex_backend_sdk/oauth.py +0 -0
- {codex_backend_sdk-0.1.1 → codex_backend_sdk-0.2.0}/codex_backend_sdk/pkce.py +0 -0
- {codex_backend_sdk-0.1.1 → codex_backend_sdk-0.2.0}/codex_backend_sdk/storage.py +0 -0
- {codex_backend_sdk-0.1.1 → codex_backend_sdk-0.2.0}/tests/conftest.py +0 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codex-backend-sdk
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Unofficial Python SDK for the ChatGPT Codex backend API
|
|
5
|
+
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: chatgpt,codex,llm,openai,sdk
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.9
|
|
18
|
+
Requires-Dist: pydantic>=2.0
|
|
19
|
+
Requires-Dist: requests>=2.28
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: openai>=1.0; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
23
|
+
Provides-Extra: openai
|
|
24
|
+
Requires-Dist: openai>=1.0; extra == 'openai'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# codex-backend-sdk
|
|
28
|
+
|
|
29
|
+
Unofficial Python SDK for the ChatGPT Codex backend API
|
|
30
|
+
(`chatgpt.com/backend-api/codex`).
|
|
31
|
+
|
|
32
|
+
This package mirrors the official OpenAI Python SDK shape for the API surface
|
|
33
|
+
that the Codex backend exposes. Use `OpenAI`, `client.responses.create(...)`,
|
|
34
|
+
and `client.models.list()` just as you would with `openai-python`, with
|
|
35
|
+
Codex-specific authentication and backend limitations under the hood.
|
|
36
|
+
|
|
37
|
+
> **Requirements:** a ChatGPT Plus, Pro, or Enterprise subscription.
|
|
38
|
+
> Authentication goes through ChatGPT OAuth and stores tokens in
|
|
39
|
+
> `~/.codex/auth.json`.
|
|
40
|
+
|
|
41
|
+
> **Disclaimer:** This is an independent, community-maintained library that
|
|
42
|
+
> reverse-engineers undocumented endpoints of `chatgpt.com`. It is not
|
|
43
|
+
> affiliated with, endorsed by, or supported by OpenAI.
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
git clone https://github.com/B4PT0R/codex-backend-sdk.git
|
|
49
|
+
cd codex-backend-sdk
|
|
50
|
+
pip install -e .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Basic Usage
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from codex_backend_sdk import OpenAI
|
|
57
|
+
|
|
58
|
+
client = OpenAI().authenticate()
|
|
59
|
+
|
|
60
|
+
response = client.responses.create(
|
|
61
|
+
model="gpt-5.4",
|
|
62
|
+
input="Explain quicksort in one paragraph.",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
print(response.output_text)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Streaming
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
stream = client.responses.create(
|
|
72
|
+
model="gpt-5.4",
|
|
73
|
+
input="Say 'hi' five times.",
|
|
74
|
+
stream=True,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
for event in stream:
|
|
78
|
+
if event.type in {"response.output_text.delta", "response.content_part.delta"}:
|
|
79
|
+
delta = event.delta
|
|
80
|
+
print(delta if isinstance(delta, str) else delta.get("text", ""), end="")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Models
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
models = client.models.list()
|
|
87
|
+
for model in models:
|
|
88
|
+
print(model.id, model.display_name, model.context_window)
|
|
89
|
+
|
|
90
|
+
info = client.models.retrieve("gpt-5.4")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Multi-Turn Input
|
|
94
|
+
|
|
95
|
+
The Codex backend does not expose `previous_response_id`, so pass prior
|
|
96
|
+
input/output items explicitly.
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
history = [
|
|
100
|
+
{"role": "user", "content": "My name is Alice. Say OK."},
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
reply1 = client.responses.create(input=history).output_text
|
|
104
|
+
history.append({"role": "assistant", "content": reply1})
|
|
105
|
+
history.append({"role": "user", "content": "What is my name?"})
|
|
106
|
+
|
|
107
|
+
reply2 = client.responses.create(input=history).output_text
|
|
108
|
+
print(reply2)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Function Calling
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
import json
|
|
115
|
+
|
|
116
|
+
tools = [{
|
|
117
|
+
"type": "function",
|
|
118
|
+
"name": "get_weather",
|
|
119
|
+
"description": "Get the current weather for a city.",
|
|
120
|
+
"parameters": {
|
|
121
|
+
"type": "object",
|
|
122
|
+
"properties": {"city": {"type": "string"}},
|
|
123
|
+
"required": ["city"],
|
|
124
|
+
"additionalProperties": False,
|
|
125
|
+
},
|
|
126
|
+
}]
|
|
127
|
+
|
|
128
|
+
first = client.responses.create(
|
|
129
|
+
input="What's the weather in Paris?",
|
|
130
|
+
tools=tools,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
call = next(item for item in first.output if item["type"] == "function_call")
|
|
134
|
+
result = {"temperature": 18, "unit": "celsius", "condition": "cloudy"}
|
|
135
|
+
|
|
136
|
+
second = client.responses.create(
|
|
137
|
+
input=[
|
|
138
|
+
call,
|
|
139
|
+
{
|
|
140
|
+
"type": "function_call_output",
|
|
141
|
+
"call_id": call["call_id"],
|
|
142
|
+
"output": json.dumps(result),
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
tools=tools,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
print(second.output_text)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Structured Output
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
schema = {
|
|
155
|
+
"title": "person",
|
|
156
|
+
"type": "object",
|
|
157
|
+
"properties": {
|
|
158
|
+
"name": {"type": "string"},
|
|
159
|
+
"age": {"type": "integer"},
|
|
160
|
+
},
|
|
161
|
+
"required": ["name", "age"],
|
|
162
|
+
"additionalProperties": False,
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
response = client.responses.create(
|
|
166
|
+
input="Extract: Bob is 42 years old.",
|
|
167
|
+
text={
|
|
168
|
+
"format": {
|
|
169
|
+
"type": "json_schema",
|
|
170
|
+
"name": "person",
|
|
171
|
+
"schema": schema,
|
|
172
|
+
"strict": True,
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Codex-Specific Endpoints
|
|
179
|
+
|
|
180
|
+
Codex-only operations live under `client.codex`.
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
quota = client.codex.usage()
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
The backend currently rejects some official Responses parameters, including
|
|
187
|
+
`temperature`, `top_p`, `max_output_tokens`, `metadata`, `user`,
|
|
188
|
+
`safety_identifier`, `truncation`, and `previous_response_id`. The SDK raises
|
|
189
|
+
`CodexBackendUnsupportedParameterError` for those instead of silently dropping
|
|
190
|
+
them.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# codex-backend-sdk
|
|
2
|
+
|
|
3
|
+
Unofficial Python SDK for the ChatGPT Codex backend API
|
|
4
|
+
(`chatgpt.com/backend-api/codex`).
|
|
5
|
+
|
|
6
|
+
This package mirrors the official OpenAI Python SDK shape for the API surface
|
|
7
|
+
that the Codex backend exposes. Use `OpenAI`, `client.responses.create(...)`,
|
|
8
|
+
and `client.models.list()` just as you would with `openai-python`, with
|
|
9
|
+
Codex-specific authentication and backend limitations under the hood.
|
|
10
|
+
|
|
11
|
+
> **Requirements:** a ChatGPT Plus, Pro, or Enterprise subscription.
|
|
12
|
+
> Authentication goes through ChatGPT OAuth and stores tokens in
|
|
13
|
+
> `~/.codex/auth.json`.
|
|
14
|
+
|
|
15
|
+
> **Disclaimer:** This is an independent, community-maintained library that
|
|
16
|
+
> reverse-engineers undocumented endpoints of `chatgpt.com`. It is not
|
|
17
|
+
> affiliated with, endorsed by, or supported by OpenAI.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
git clone https://github.com/B4PT0R/codex-backend-sdk.git
|
|
23
|
+
cd codex-backend-sdk
|
|
24
|
+
pip install -e .
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Basic Usage
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from codex_backend_sdk import OpenAI
|
|
31
|
+
|
|
32
|
+
client = OpenAI().authenticate()
|
|
33
|
+
|
|
34
|
+
response = client.responses.create(
|
|
35
|
+
model="gpt-5.4",
|
|
36
|
+
input="Explain quicksort in one paragraph.",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
print(response.output_text)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Streaming
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
stream = client.responses.create(
|
|
46
|
+
model="gpt-5.4",
|
|
47
|
+
input="Say 'hi' five times.",
|
|
48
|
+
stream=True,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
for event in stream:
|
|
52
|
+
if event.type in {"response.output_text.delta", "response.content_part.delta"}:
|
|
53
|
+
delta = event.delta
|
|
54
|
+
print(delta if isinstance(delta, str) else delta.get("text", ""), end="")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Models
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
models = client.models.list()
|
|
61
|
+
for model in models:
|
|
62
|
+
print(model.id, model.display_name, model.context_window)
|
|
63
|
+
|
|
64
|
+
info = client.models.retrieve("gpt-5.4")
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Multi-Turn Input
|
|
68
|
+
|
|
69
|
+
The Codex backend does not expose `previous_response_id`, so pass prior
|
|
70
|
+
input/output items explicitly.
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
history = [
|
|
74
|
+
{"role": "user", "content": "My name is Alice. Say OK."},
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
reply1 = client.responses.create(input=history).output_text
|
|
78
|
+
history.append({"role": "assistant", "content": reply1})
|
|
79
|
+
history.append({"role": "user", "content": "What is my name?"})
|
|
80
|
+
|
|
81
|
+
reply2 = client.responses.create(input=history).output_text
|
|
82
|
+
print(reply2)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Function Calling
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
import json
|
|
89
|
+
|
|
90
|
+
tools = [{
|
|
91
|
+
"type": "function",
|
|
92
|
+
"name": "get_weather",
|
|
93
|
+
"description": "Get the current weather for a city.",
|
|
94
|
+
"parameters": {
|
|
95
|
+
"type": "object",
|
|
96
|
+
"properties": {"city": {"type": "string"}},
|
|
97
|
+
"required": ["city"],
|
|
98
|
+
"additionalProperties": False,
|
|
99
|
+
},
|
|
100
|
+
}]
|
|
101
|
+
|
|
102
|
+
first = client.responses.create(
|
|
103
|
+
input="What's the weather in Paris?",
|
|
104
|
+
tools=tools,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
call = next(item for item in first.output if item["type"] == "function_call")
|
|
108
|
+
result = {"temperature": 18, "unit": "celsius", "condition": "cloudy"}
|
|
109
|
+
|
|
110
|
+
second = client.responses.create(
|
|
111
|
+
input=[
|
|
112
|
+
call,
|
|
113
|
+
{
|
|
114
|
+
"type": "function_call_output",
|
|
115
|
+
"call_id": call["call_id"],
|
|
116
|
+
"output": json.dumps(result),
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
tools=tools,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
print(second.output_text)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Structured Output
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
schema = {
|
|
129
|
+
"title": "person",
|
|
130
|
+
"type": "object",
|
|
131
|
+
"properties": {
|
|
132
|
+
"name": {"type": "string"},
|
|
133
|
+
"age": {"type": "integer"},
|
|
134
|
+
},
|
|
135
|
+
"required": ["name", "age"],
|
|
136
|
+
"additionalProperties": False,
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
response = client.responses.create(
|
|
140
|
+
input="Extract: Bob is 42 years old.",
|
|
141
|
+
text={
|
|
142
|
+
"format": {
|
|
143
|
+
"type": "json_schema",
|
|
144
|
+
"name": "person",
|
|
145
|
+
"schema": schema,
|
|
146
|
+
"strict": True,
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Codex-Specific Endpoints
|
|
153
|
+
|
|
154
|
+
Codex-only operations live under `client.codex`.
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
quota = client.codex.usage()
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The backend currently rejects some official Responses parameters, including
|
|
161
|
+
`temperature`, `top_p`, `max_output_tokens`, `metadata`, `user`,
|
|
162
|
+
`safety_identifier`, `truncation`, and `previous_response_id`. The SDK raises
|
|
163
|
+
`CodexBackendUnsupportedParameterError` for those instead of silently dropping
|
|
164
|
+
them.
|
|
@@ -8,59 +8,53 @@ to OpenAI's Terms of Use (https://openai.com/policies/terms-of-use).
|
|
|
8
8
|
Endpoints may change or break without notice.
|
|
9
9
|
|
|
10
10
|
Quickstart:
|
|
11
|
-
from codex_backend_sdk import
|
|
11
|
+
from codex_backend_sdk import OpenAI
|
|
12
12
|
|
|
13
|
-
client =
|
|
13
|
+
client = OpenAI().authenticate() # opens browser on first run
|
|
14
14
|
# subsequent runs load & refresh tokens automatically
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
response = client.responses.create(input="Explain quicksort")
|
|
17
|
+
print(response.output_text)
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
|
-
__version__ = "0.
|
|
20
|
+
__version__ = "0.2.0"
|
|
21
21
|
|
|
22
22
|
from .oauth import run_oauth_flow, refresh_access_token, obtain_api_key
|
|
23
23
|
from .storage import load_tokens, save_tokens, TokenStore
|
|
24
24
|
from .codex_client import (
|
|
25
|
+
CodexBackendUnsupportedParameterError,
|
|
26
|
+
CodexBaseModel,
|
|
25
27
|
ReasoningEffort,
|
|
26
28
|
ReasoningSummary,
|
|
27
|
-
Verbosity,
|
|
28
29
|
ServiceTier,
|
|
30
|
+
Verbosity,
|
|
29
31
|
CodexClient,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
ResponseCompleted,
|
|
38
|
-
ResponseFailed,
|
|
39
|
-
ResponseAborted,
|
|
40
|
-
CompactionResult,
|
|
41
|
-
RealtimeCallResult,
|
|
32
|
+
OpenAI,
|
|
33
|
+
Model,
|
|
34
|
+
Response,
|
|
35
|
+
ResponseStreamEvent,
|
|
36
|
+
ResponseUsage,
|
|
37
|
+
SyncPage,
|
|
38
|
+
CompactedResponse,
|
|
42
39
|
image_url,
|
|
43
40
|
image_b64,
|
|
44
41
|
)
|
|
45
42
|
|
|
46
43
|
__all__ = [
|
|
47
44
|
"CodexClient",
|
|
45
|
+
"OpenAI",
|
|
46
|
+
"CodexBackendUnsupportedParameterError",
|
|
47
|
+
"CodexBaseModel",
|
|
48
|
+
"Model",
|
|
49
|
+
"Response",
|
|
50
|
+
"ResponseStreamEvent",
|
|
51
|
+
"ResponseUsage",
|
|
52
|
+
"SyncPage",
|
|
53
|
+
"CompactedResponse",
|
|
48
54
|
"ReasoningEffort",
|
|
49
55
|
"ReasoningSummary",
|
|
50
|
-
"Verbosity",
|
|
51
56
|
"ServiceTier",
|
|
52
|
-
"
|
|
53
|
-
"ReasoningLevel",
|
|
54
|
-
"TextDelta",
|
|
55
|
-
"ReasoningDelta",
|
|
56
|
-
"ToolCall",
|
|
57
|
-
"OutputItem",
|
|
58
|
-
"TokenUsage",
|
|
59
|
-
"ResponseCompleted",
|
|
60
|
-
"ResponseFailed",
|
|
61
|
-
"ResponseAborted",
|
|
62
|
-
"CompactionResult",
|
|
63
|
-
"RealtimeCallResult",
|
|
57
|
+
"Verbosity",
|
|
64
58
|
"image_url",
|
|
65
59
|
"image_b64",
|
|
66
60
|
"run_oauth_flow",
|