codex-backend-sdk 0.3.3__tar.gz → 0.3.4__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.3.4/CHANGELOG.md +13 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/PKG-INFO +9 -1
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/README.md +8 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/__init__.py +1 -1
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/_client.py +25 -1
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/pyproject.toml +1 -1
- codex_backend_sdk-0.3.4/tests/test_account_info.py +68 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/.gitignore +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/LICENSE +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/_models.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/_streaming.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/_transport.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/_utils.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/codex_client.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/oauth.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/pkce.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/resources/__init__.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/resources/_responses_payloads.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/resources/codex.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/resources/files.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/resources/models.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/resources/openai_oauth.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/resources/realtime.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/resources/responses.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/storage.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/docs/backend-api.md +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/examples/agent.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/tests/conftest.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/tests/test_basic.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/tests/test_client_retry.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/tests/test_codex_resources.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/tests/test_conversation.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/tests/test_files_resource.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/tests/test_openai_oauth_resources.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/tests/test_realtime_resource.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/tests/test_reasoning.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/tests/test_responses_resource.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/tests/test_structured_output.py +0 -0
- {codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/tests/test_tools.py +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.3.4] - 2026-05-15
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Added `authenticate(interactive=False)` to allow non-interactive credential checks without triggering the browser OAuth flow.
|
|
9
|
+
- Added `client.authenticated` for simple auth-state introspection.
|
|
10
|
+
- Added `client.account_info()` to expose safe non-secret account metadata (`authenticated`, `account_id`, `email`, `plan_type`).
|
|
11
|
+
|
|
12
|
+
### Documentation
|
|
13
|
+
- Documented the non-interactive authentication helpers in `README.md`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codex-backend-sdk
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: Unofficial Python SDK for the ChatGPT Codex backend API
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -355,6 +355,14 @@ headers = client.realtime_websocket_headers(session_id="voice-session")
|
|
|
355
355
|
`openai_api_key`. The default `authenticate(request_api_key=True)` flow stores
|
|
356
356
|
that key when available.
|
|
357
357
|
|
|
358
|
+
For non-interactive checks, you can avoid triggering a browser login flow:
|
|
359
|
+
|
|
360
|
+
```python
|
|
361
|
+
client = OpenAI().authenticate(interactive=False)
|
|
362
|
+
print(client.authenticated)
|
|
363
|
+
print(client.account_info())
|
|
364
|
+
```
|
|
365
|
+
|
|
358
366
|
### Embeddings
|
|
359
367
|
|
|
360
368
|
`client.embeddings.create(...)` mirrors the official OpenAI embeddings resource
|
|
@@ -329,6 +329,14 @@ headers = client.realtime_websocket_headers(session_id="voice-session")
|
|
|
329
329
|
`openai_api_key`. The default `authenticate(request_api_key=True)` flow stores
|
|
330
330
|
that key when available.
|
|
331
331
|
|
|
332
|
+
For non-interactive checks, you can avoid triggering a browser login flow:
|
|
333
|
+
|
|
334
|
+
```python
|
|
335
|
+
client = OpenAI().authenticate(interactive=False)
|
|
336
|
+
print(client.authenticated)
|
|
337
|
+
print(client.account_info())
|
|
338
|
+
```
|
|
339
|
+
|
|
332
340
|
### Embeddings
|
|
333
341
|
|
|
334
342
|
`client.embeddings.create(...)` mirrors the official OpenAI embeddings resource
|
|
@@ -62,7 +62,12 @@ class CodexClient:
|
|
|
62
62
|
self.files = Files(self)
|
|
63
63
|
self.codex = CodexResources(self)
|
|
64
64
|
|
|
65
|
-
def authenticate(
|
|
65
|
+
def authenticate(
|
|
66
|
+
self,
|
|
67
|
+
*,
|
|
68
|
+
request_api_key: bool = True,
|
|
69
|
+
interactive: bool = True,
|
|
70
|
+
) -> "CodexClient":
|
|
66
71
|
from .oauth import refresh_access_token, run_oauth_flow
|
|
67
72
|
|
|
68
73
|
def refresh(store: TokenStore) -> Optional[TokenStore]:
|
|
@@ -87,9 +92,28 @@ class CodexClient:
|
|
|
87
92
|
self._set_store(store)
|
|
88
93
|
return self
|
|
89
94
|
|
|
95
|
+
if not interactive:
|
|
96
|
+
raise RuntimeError("No usable stored Codex credentials; interactive login required.")
|
|
97
|
+
|
|
90
98
|
self._set_store(run_oauth_flow(request_api_key=request_api_key))
|
|
91
99
|
return self
|
|
92
100
|
|
|
101
|
+
@property
|
|
102
|
+
def authenticated(self) -> bool:
|
|
103
|
+
"""Whether this client currently has OAuth credentials loaded."""
|
|
104
|
+
return bool(self._store and self._store.account_id)
|
|
105
|
+
|
|
106
|
+
def account_info(self) -> dict[str, Any]:
|
|
107
|
+
"""Return safe non-secret account metadata decoded from stored tokens."""
|
|
108
|
+
store = self._store
|
|
109
|
+
authenticated = bool(store and store.account_id)
|
|
110
|
+
return {
|
|
111
|
+
"authenticated": authenticated,
|
|
112
|
+
"account_id": store.account_id if store else None,
|
|
113
|
+
"email": store.email if store else None,
|
|
114
|
+
"plan_type": store.plan_type if store else None,
|
|
115
|
+
}
|
|
116
|
+
|
|
93
117
|
def _set_store(self, store: TokenStore) -> None:
|
|
94
118
|
self._store = store
|
|
95
119
|
self._session.headers.update(self._auth_headers())
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from codex_backend_sdk import CodexClient, TokenStore
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def _store() -> TokenStore:
|
|
6
|
+
return TokenStore(
|
|
7
|
+
access_token="access-secret",
|
|
8
|
+
refresh_token="refresh-secret",
|
|
9
|
+
id_token_raw="id-secret",
|
|
10
|
+
account_id="acct_123",
|
|
11
|
+
openai_api_key="api-secret",
|
|
12
|
+
email="user@example.com",
|
|
13
|
+
plan_type="pro",
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_account_info_exposes_safe_metadata_only():
|
|
19
|
+
client = CodexClient(store=_store())
|
|
20
|
+
|
|
21
|
+
info = client.account_info()
|
|
22
|
+
|
|
23
|
+
assert client.authenticated is True
|
|
24
|
+
assert info == {
|
|
25
|
+
"authenticated": True,
|
|
26
|
+
"account_id": "acct_123",
|
|
27
|
+
"email": "user@example.com",
|
|
28
|
+
"plan_type": "pro",
|
|
29
|
+
}
|
|
30
|
+
assert "access-secret" not in repr(info)
|
|
31
|
+
assert "refresh-secret" not in repr(info)
|
|
32
|
+
assert "api-secret" not in repr(info)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_account_info_when_not_authenticated():
|
|
37
|
+
client = CodexClient()
|
|
38
|
+
|
|
39
|
+
assert client.authenticated is False
|
|
40
|
+
assert client.account_info() == {
|
|
41
|
+
"authenticated": False,
|
|
42
|
+
"account_id": None,
|
|
43
|
+
"email": None,
|
|
44
|
+
"plan_type": None,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_authenticate_non_interactive_uses_loaded_tokens(monkeypatch):
|
|
50
|
+
monkeypatch.setattr("codex_backend_sdk._client.load_tokens", lambda: _store())
|
|
51
|
+
monkeypatch.setattr("codex_backend_sdk._client.token_needs_refresh", lambda store: False)
|
|
52
|
+
|
|
53
|
+
client = CodexClient().authenticate(interactive=False)
|
|
54
|
+
|
|
55
|
+
assert client.authenticated is True
|
|
56
|
+
assert client.account_info()["email"] == "user@example.com"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_authenticate_non_interactive_without_tokens_raises(monkeypatch):
|
|
61
|
+
monkeypatch.setattr("codex_backend_sdk._client.load_tokens", lambda: None)
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
CodexClient().authenticate(interactive=False)
|
|
65
|
+
except RuntimeError as exc:
|
|
66
|
+
assert "interactive login required" in str(exc)
|
|
67
|
+
else:
|
|
68
|
+
raise AssertionError("Expected RuntimeError")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/resources/openai_oauth.py
RENAMED
|
File without changes
|
|
File without changes
|
{codex_backend_sdk-0.3.3 → codex_backend_sdk-0.3.4}/codex_backend_sdk/resources/responses.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|