oauth-codex 3.2.2__tar.gz → 4.0.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.
Files changed (79) hide show
  1. oauth_codex-4.0.0/PKG-INFO +195 -0
  2. oauth_codex-4.0.0/README.md +179 -0
  3. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/pyproject.toml +9 -2
  4. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/_sdk_client.py +8 -11
  5. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/_version.py +1 -1
  6. oauth_codex-4.0.0/src/oauth_codex/core_types.py +64 -0
  7. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/chat/completions.py +64 -31
  8. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/responses/input_tokens.py +12 -6
  9. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/vector_stores/__init__.py +3 -0
  10. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/vector_stores/vector_stores.py +23 -2
  11. oauth_codex-4.0.0/src/oauth_codex.egg-info/PKG-INFO +195 -0
  12. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex.egg-info/SOURCES.txt +1 -5
  13. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex.egg-info/requires.txt +2 -0
  14. oauth_codex-4.0.0/tests/test_backend_tool_loop_contract.py +367 -0
  15. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/tests/test_beta_chat_completions.py +25 -8
  16. oauth_codex-4.0.0/tests/test_client_authentication.py +57 -0
  17. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/tests/test_client_resource_surface.py +37 -1
  18. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/tests/test_public_api_docstrings.py +2 -0
  19. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/tests/test_public_surface.py +10 -0
  20. oauth_codex-3.2.2/PKG-INFO +0 -219
  21. oauth_codex-3.2.2/README.md +0 -205
  22. oauth_codex-3.2.2/src/oauth_codex/_engine.py +0 -3686
  23. oauth_codex-3.2.2/src/oauth_codex/_module_client.py +0 -90
  24. oauth_codex-3.2.2/src/oauth_codex/_streaming.py +0 -94
  25. oauth_codex-3.2.2/src/oauth_codex/_types.py +0 -38
  26. oauth_codex-3.2.2/src/oauth_codex/compat_store.py +0 -402
  27. oauth_codex-3.2.2/src/oauth_codex/core_types.py +0 -179
  28. oauth_codex-3.2.2/src/oauth_codex.egg-info/PKG-INFO +0 -219
  29. oauth_codex-3.2.2/tests/test_client_authentication.py +0 -20
  30. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/setup.cfg +0 -0
  31. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/__init__.py +0 -0
  32. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/_base_client.py +0 -0
  33. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/_exceptions.py +0 -0
  34. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/_models.py +0 -0
  35. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/_resource.py +0 -0
  36. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/auth/__init__.py +0 -0
  37. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/auth/_oauth.py +0 -0
  38. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/auth/_provider.py +0 -0
  39. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/auth/config.py +0 -0
  40. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/auth/pkce.py +0 -0
  41. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/auth/store.py +0 -0
  42. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/auth/token_manager.py +0 -0
  43. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/errors.py +0 -0
  44. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/py.typed +0 -0
  45. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/__init__.py +0 -0
  46. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/_wrappers.py +0 -0
  47. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/beta.py +0 -0
  48. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/chat/__init__.py +0 -0
  49. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/files.py +0 -0
  50. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/models.py +0 -0
  51. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/responses/__init__.py +0 -0
  52. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/responses/_helpers.py +0 -0
  53. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/responses/responses.py +0 -0
  54. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/responses.py +0 -0
  55. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/vector_stores/file_batches.py +0 -0
  56. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/resources/vector_stores/files.py +0 -0
  57. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/store.py +0 -0
  58. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/tooling.py +0 -0
  59. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/__init__.py +0 -0
  60. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/chat/__init__.py +0 -0
  61. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/chat/completions.py +0 -0
  62. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/file_deleted.py +0 -0
  63. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/file_object.py +0 -0
  64. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/responses/__init__.py +0 -0
  65. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/responses/input_token_count_response.py +0 -0
  66. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/responses/response.py +0 -0
  67. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/responses/response_stream_event.py +0 -0
  68. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/shared/__init__.py +0 -0
  69. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/shared/model_capabilities.py +0 -0
  70. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/shared/usage.py +0 -0
  71. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/vector_stores/__init__.py +0 -0
  72. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/vector_stores/vector_store.py +0 -0
  73. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/vector_stores/vector_store_deleted.py +0 -0
  74. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/vector_stores/vector_store_file.py +0 -0
  75. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/vector_stores/vector_store_file_batch.py +0 -0
  76. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/types/vector_stores/vector_store_search_response.py +0 -0
  77. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex/version.py +0 -0
  78. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex.egg-info/dependency_links.txt +0 -0
  79. {oauth_codex-3.2.2 → oauth_codex-4.0.0}/src/oauth_codex.egg-info/top_level.txt +0 -0
@@ -0,0 +1,195 @@
1
+ Metadata-Version: 2.4
2
+ Name: oauth-codex
3
+ Version: 4.0.0
4
+ Summary: Codex OAuth-based Python SDK with resource-style Client and AsyncClient APIs
5
+ Author: Codex
6
+ Requires-Python: >=3.11
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: httpx>=0.27.0
9
+ Requires-Dist: keyring>=25.0.0
10
+ Requires-Dist: pydantic>=2.8.0
11
+ Provides-Extra: dev
12
+ Requires-Dist: build>=1.2.0; extra == "dev"
13
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
14
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
15
+ Requires-Dist: twine>=5.0.0; extra == "dev"
16
+
17
+ [English](README.md) | [한국어](README.ko.md)
18
+
19
+ # oauth-codex
20
+
21
+ OAuth PKCE-based Python SDK for the Codex backend.
22
+
23
+ ## Highlights
24
+
25
+ - Resource-style clients: `Client` and `AsyncClient`
26
+ - OAuth PKCE only, with interactive login and automatic token refresh
27
+ - OpenAI-style `chat.completions.create(...)`
28
+ - Lower-level `responses.create(...)`, `responses.parse(...)`, and `responses.stream(...)`
29
+ - Callable tool loop helpers via `client.beta.chat.completions.run_tools(...)`
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ pip install oauth-codex
35
+ ```
36
+
37
+ Requires Python 3.11 or newer.
38
+
39
+ ## Quick Start
40
+
41
+ ### Synchronous Client
42
+
43
+ ```python
44
+ from oauth_codex import Client
45
+
46
+ client = Client()
47
+ client.authenticate()
48
+
49
+ completion = client.chat.completions.create(
50
+ model="gpt-5.3-codex",
51
+ messages=[{"role": "user", "content": "Hello from oauth-codex"}],
52
+ )
53
+ print(completion.choices[0].message.content)
54
+ ```
55
+
56
+ ### Asynchronous Client
57
+
58
+ ```python
59
+ import asyncio
60
+
61
+ from oauth_codex import AsyncClient
62
+
63
+
64
+ async def main():
65
+ client = AsyncClient()
66
+ await client.authenticate()
67
+
68
+ completion = await client.chat.completions.create(
69
+ model="gpt-5.3-codex",
70
+ messages=[{"role": "user", "content": "Hello async"}],
71
+ )
72
+ print(completion.choices[0].message.content)
73
+
74
+
75
+ asyncio.run(main())
76
+ ```
77
+
78
+ ## Authentication
79
+
80
+ This SDK uses OAuth PKCE only. API keys are not supported.
81
+
82
+ ```python
83
+ client = Client()
84
+ client.authenticate()
85
+ ```
86
+
87
+ On first authentication, the SDK prints an authorization URL, waits for the browser sign-in flow, and asks you to paste the localhost callback URL back into the terminal. Tokens are stored locally and refreshed automatically on later requests.
88
+
89
+ ## Main API Surface
90
+
91
+ ### Chat Completions
92
+
93
+ ```python
94
+ response = client.chat.completions.create(
95
+ model="gpt-5.3-codex",
96
+ messages=[{"role": "user", "content": "Write a sorting function"}],
97
+ )
98
+ print(response.choices[0].message.content)
99
+ ```
100
+
101
+ ### Responses Resource
102
+
103
+ ```python
104
+ response = client.responses.create(
105
+ model="gpt-5.3-codex",
106
+ input=[{"role": "user", "content": "Analyze this code snippet."}],
107
+ )
108
+ print(response.output_text)
109
+ ```
110
+
111
+ ### Streaming
112
+
113
+ ```python
114
+ for event in client.responses.stream(
115
+ model="gpt-5.3-codex",
116
+ input=[{"role": "user", "content": "Say hello in three words"}],
117
+ ):
118
+ if event.type == "text_delta" and event.delta:
119
+ print(event.delta, end="", flush=True)
120
+ ```
121
+
122
+ ### Structured Output
123
+
124
+ ```python
125
+ from pydantic import BaseModel
126
+
127
+
128
+ class Summary(BaseModel):
129
+ title: str
130
+ score: int
131
+
132
+
133
+ response = client.responses.parse(
134
+ model="gpt-5.3-codex",
135
+ input=[{"role": "user", "content": "Return JSON with title and score"}],
136
+ response_format=Summary,
137
+ )
138
+ print(response.parsed)
139
+ ```
140
+
141
+ ### Tool Execution
142
+
143
+ ```python
144
+ def add(a: int, b: int) -> int:
145
+ return a + b
146
+
147
+
148
+ completion = client.beta.chat.completions.run_tools(
149
+ model="gpt-5.3-codex",
150
+ messages=[{"role": "user", "content": "What is 2 + 3?"}],
151
+ tools=[add],
152
+ )
153
+ print(completion.choices[0].message.content)
154
+ ```
155
+
156
+ ## Available Namespaces
157
+
158
+ - `client.chat.completions`
159
+ - `client.responses`
160
+ - `client.files`
161
+ - `client.vector_stores`
162
+ - `client.vector_stores.files`
163
+ - `client.vector_stores.file_batches`
164
+ - `client.models`
165
+ - `client.beta.chat.completions`
166
+
167
+ `AsyncClient` exposes the same namespaces with async methods.
168
+
169
+ ## Removed In 4.0
170
+
171
+ - `authenticate_on_init`
172
+ - `generate`, `agenerate`, `stream`, `astream`
173
+ - legacy `OAuthCodexClient` and `AsyncOAuthCodexClient`
174
+ - module-level proxy usage such as `oauth_codex.responses.create(...)`
175
+
176
+ ## Error Handling
177
+
178
+ The package exports OpenAI-style exception classes such as `AuthenticationError`, `RateLimitError`, `APIConnectionError`, and `APIStatusError`.
179
+
180
+ ## Documentation
181
+
182
+ - English: [`docs/en/index.md`](docs/en/index.md)
183
+ - Korean: [`docs/ko/index.md`](docs/ko/index.md)
184
+
185
+ ## Development
186
+
187
+ ```bash
188
+ pip install -e .[dev]
189
+ pytest -q
190
+ python -m build
191
+ ```
192
+
193
+ ## Changelog
194
+
195
+ [`CHANGELOG.md`](CHANGELOG.md)
@@ -0,0 +1,179 @@
1
+ [English](README.md) | [한국어](README.ko.md)
2
+
3
+ # oauth-codex
4
+
5
+ OAuth PKCE-based Python SDK for the Codex backend.
6
+
7
+ ## Highlights
8
+
9
+ - Resource-style clients: `Client` and `AsyncClient`
10
+ - OAuth PKCE only, with interactive login and automatic token refresh
11
+ - OpenAI-style `chat.completions.create(...)`
12
+ - Lower-level `responses.create(...)`, `responses.parse(...)`, and `responses.stream(...)`
13
+ - Callable tool loop helpers via `client.beta.chat.completions.run_tools(...)`
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pip install oauth-codex
19
+ ```
20
+
21
+ Requires Python 3.11 or newer.
22
+
23
+ ## Quick Start
24
+
25
+ ### Synchronous Client
26
+
27
+ ```python
28
+ from oauth_codex import Client
29
+
30
+ client = Client()
31
+ client.authenticate()
32
+
33
+ completion = client.chat.completions.create(
34
+ model="gpt-5.3-codex",
35
+ messages=[{"role": "user", "content": "Hello from oauth-codex"}],
36
+ )
37
+ print(completion.choices[0].message.content)
38
+ ```
39
+
40
+ ### Asynchronous Client
41
+
42
+ ```python
43
+ import asyncio
44
+
45
+ from oauth_codex import AsyncClient
46
+
47
+
48
+ async def main():
49
+ client = AsyncClient()
50
+ await client.authenticate()
51
+
52
+ completion = await client.chat.completions.create(
53
+ model="gpt-5.3-codex",
54
+ messages=[{"role": "user", "content": "Hello async"}],
55
+ )
56
+ print(completion.choices[0].message.content)
57
+
58
+
59
+ asyncio.run(main())
60
+ ```
61
+
62
+ ## Authentication
63
+
64
+ This SDK uses OAuth PKCE only. API keys are not supported.
65
+
66
+ ```python
67
+ client = Client()
68
+ client.authenticate()
69
+ ```
70
+
71
+ On first authentication, the SDK prints an authorization URL, waits for the browser sign-in flow, and asks you to paste the localhost callback URL back into the terminal. Tokens are stored locally and refreshed automatically on later requests.
72
+
73
+ ## Main API Surface
74
+
75
+ ### Chat Completions
76
+
77
+ ```python
78
+ response = client.chat.completions.create(
79
+ model="gpt-5.3-codex",
80
+ messages=[{"role": "user", "content": "Write a sorting function"}],
81
+ )
82
+ print(response.choices[0].message.content)
83
+ ```
84
+
85
+ ### Responses Resource
86
+
87
+ ```python
88
+ response = client.responses.create(
89
+ model="gpt-5.3-codex",
90
+ input=[{"role": "user", "content": "Analyze this code snippet."}],
91
+ )
92
+ print(response.output_text)
93
+ ```
94
+
95
+ ### Streaming
96
+
97
+ ```python
98
+ for event in client.responses.stream(
99
+ model="gpt-5.3-codex",
100
+ input=[{"role": "user", "content": "Say hello in three words"}],
101
+ ):
102
+ if event.type == "text_delta" and event.delta:
103
+ print(event.delta, end="", flush=True)
104
+ ```
105
+
106
+ ### Structured Output
107
+
108
+ ```python
109
+ from pydantic import BaseModel
110
+
111
+
112
+ class Summary(BaseModel):
113
+ title: str
114
+ score: int
115
+
116
+
117
+ response = client.responses.parse(
118
+ model="gpt-5.3-codex",
119
+ input=[{"role": "user", "content": "Return JSON with title and score"}],
120
+ response_format=Summary,
121
+ )
122
+ print(response.parsed)
123
+ ```
124
+
125
+ ### Tool Execution
126
+
127
+ ```python
128
+ def add(a: int, b: int) -> int:
129
+ return a + b
130
+
131
+
132
+ completion = client.beta.chat.completions.run_tools(
133
+ model="gpt-5.3-codex",
134
+ messages=[{"role": "user", "content": "What is 2 + 3?"}],
135
+ tools=[add],
136
+ )
137
+ print(completion.choices[0].message.content)
138
+ ```
139
+
140
+ ## Available Namespaces
141
+
142
+ - `client.chat.completions`
143
+ - `client.responses`
144
+ - `client.files`
145
+ - `client.vector_stores`
146
+ - `client.vector_stores.files`
147
+ - `client.vector_stores.file_batches`
148
+ - `client.models`
149
+ - `client.beta.chat.completions`
150
+
151
+ `AsyncClient` exposes the same namespaces with async methods.
152
+
153
+ ## Removed In 4.0
154
+
155
+ - `authenticate_on_init`
156
+ - `generate`, `agenerate`, `stream`, `astream`
157
+ - legacy `OAuthCodexClient` and `AsyncOAuthCodexClient`
158
+ - module-level proxy usage such as `oauth_codex.responses.create(...)`
159
+
160
+ ## Error Handling
161
+
162
+ The package exports OpenAI-style exception classes such as `AuthenticationError`, `RateLimitError`, `APIConnectionError`, and `APIStatusError`.
163
+
164
+ ## Documentation
165
+
166
+ - English: [`docs/en/index.md`](docs/en/index.md)
167
+ - Korean: [`docs/ko/index.md`](docs/ko/index.md)
168
+
169
+ ## Development
170
+
171
+ ```bash
172
+ pip install -e .[dev]
173
+ pytest -q
174
+ python -m build
175
+ ```
176
+
177
+ ## Changelog
178
+
179
+ [`CHANGELOG.md`](CHANGELOG.md)
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "oauth-codex"
7
- version = "3.2.2"
8
- description = "Codex OAuth-based Python SDK with a single Client and generate-first API"
7
+ dynamic = ["version"]
8
+ description = "Codex OAuth-based Python SDK with resource-style Client and AsyncClient APIs"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
11
11
  authors = [{ name = "Codex" }]
@@ -17,8 +17,10 @@ dependencies = [
17
17
 
18
18
  [project.optional-dependencies]
19
19
  dev = [
20
+ "build>=1.2.0",
20
21
  "pytest>=8.0.0",
21
22
  "pytest-asyncio>=0.23.0",
23
+ "twine>=5.0.0",
22
24
  ]
23
25
 
24
26
  [tool.setuptools]
@@ -27,9 +29,14 @@ package-dir = {"" = "src"}
27
29
  [tool.setuptools.packages.find]
28
30
  where = ["src"]
29
31
 
32
+ [tool.setuptools.dynamic]
33
+ version = {attr = "oauth_codex._version.__version__"}
34
+
30
35
  [tool.setuptools.package-data]
31
36
  oauth_codex = ["py.typed"]
32
37
 
33
38
  [tool.pytest.ini_options]
34
39
  addopts = "-q"
40
+ asyncio_mode = "auto"
35
41
  pythonpath = ["src"]
42
+ testpaths = ["tests"]
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from collections.abc import AsyncIterator, Iterator, Mapping
4
- from types import SimpleNamespace
5
4
  from typing import Any, cast
6
5
 
7
6
  import httpx
@@ -33,16 +32,6 @@ def _with_auth_headers(
33
32
  if auth_headers:
34
33
  merged.update(auth_headers)
35
34
  return merged
36
-
37
-
38
- def _to_namespace(value: Any) -> Any:
39
- if isinstance(value, dict):
40
- return SimpleNamespace(**{k: _to_namespace(v) for k, v in value.items()})
41
- if isinstance(value, list):
42
- return [_to_namespace(v) for v in value]
43
- return value
44
-
45
-
46
35
  def _payload_without_none(values: dict[str, Any]) -> dict[str, Any]:
47
36
  payload = {k: v for k, v in values.items() if v is not None}
48
37
  payload.pop("self", None)
@@ -131,8 +120,12 @@ class Client(SyncAPIClient):
131
120
  self._chat: Chat | None = None
132
121
  self._beta: Beta | None = None
133
122
  self._auth_provider: SyncAuthProvider | None = None
123
+ self._vector_file_batches: dict[str, dict[str, Any]] = {}
134
124
  self._engine = _SyncEngine(self)
135
125
 
126
+ def authenticate(self) -> None:
127
+ self.auth.ensure_valid(interactive=True)
128
+
136
129
  @property
137
130
  def auth(self) -> SyncAuthProvider:
138
131
  if self._auth_provider is None:
@@ -232,8 +225,12 @@ class AsyncClient(AsyncAPIClient):
232
225
  self._chat: AsyncChat | None = None
233
226
  self._beta: AsyncBeta | None = None
234
227
  self._auth_provider: AsyncAuthProvider | None = None
228
+ self._vector_file_batches: dict[str, dict[str, Any]] = {}
235
229
  self._engine = _AsyncEngine(self)
236
230
 
231
+ async def authenticate(self) -> None:
232
+ await self.auth.aensure_valid(interactive=True)
233
+
237
234
  @property
238
235
  def auth(self) -> AsyncAuthProvider:
239
236
  if self._auth_provider is None:
@@ -1,2 +1,2 @@
1
1
  __title__ = "oauth-codex"
2
- __version__ = "3.2.2"
2
+ __version__ = "4.0.0"
@@ -0,0 +1,64 @@
1
+ """Core public data types used by oauth-codex.
2
+
3
+ `Message` represents a single Responses API input message dictionary, and
4
+ `listMessage` is the list container commonly passed to resource methods such as
5
+ `client.chat.completions.create(...)` and `client.responses.create(...)`.
6
+
7
+ Recommended minimal message shape:
8
+
9
+ [{"role": "user", "content": "hello"}]
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from dataclasses import dataclass
15
+ from typing import Any, Callable, Literal, Protocol, TypeAlias
16
+
17
+ #: A single response input message item (for example role/content dict).
18
+ Message: TypeAlias = dict[str, Any]
19
+ #: List of response input messages accepted by resource-style client methods.
20
+ listMessage: TypeAlias = list[Message]
21
+ ValidationMode: TypeAlias = Literal["warn", "error", "ignore"]
22
+ TruncationMode: TypeAlias = Literal["auto", "disabled"]
23
+
24
+
25
+ @dataclass
26
+ class OAuthTokens:
27
+ access_token: str
28
+ api_key: str | None = None
29
+ refresh_token: str | None = None
30
+ id_token: str | None = None
31
+ token_type: str = "Bearer"
32
+ scope: str | None = None
33
+ expires_at: float | None = None
34
+ account_id: str | None = None
35
+ last_refresh: float | None = None
36
+
37
+ def is_expired(self, *, leeway_seconds: int = 0) -> bool:
38
+ if self.expires_at is None:
39
+ return False
40
+ import time
41
+
42
+ return time.time() + max(leeway_seconds, 0) >= self.expires_at
43
+
44
+
45
+ @dataclass
46
+ class ToolResult:
47
+ tool_call_id: str
48
+ name: str
49
+ output: dict[str, Any]
50
+
51
+
52
+ ToolSchema = dict[str, Any]
53
+ ToolInput: TypeAlias = ToolSchema | Callable[..., Any]
54
+
55
+
56
+ class TokenStore(Protocol):
57
+ def load(self) -> OAuthTokens | None:
58
+ ...
59
+
60
+ def save(self, tokens: OAuthTokens) -> None:
61
+ ...
62
+
63
+ def delete(self) -> None:
64
+ ...