dspy-codex-auth 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.
@@ -0,0 +1,238 @@
1
+ Metadata-Version: 2.4
2
+ Name: dspy-codex-auth
3
+ Version: 0.1.0
4
+ Summary: DSPy integration for ChatGPT Codex subscription-backed language models
5
+ Keywords: codex,dspy,language-models,openai
6
+ Author: hrbatra
7
+ Author-email: hrbatra <hrbatra@utexas.edu>
8
+ License-Expression: MIT
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Requires-Dist: dspy>=3.2.0
17
+ Requires-Dist: litellm>=1.82.6
18
+ Requires-Dist: requests>=2.33.1
19
+ Requires-Python: >=3.12
20
+ Project-URL: Homepage, https://github.com/hrbatra/dspy-codex-auth
21
+ Project-URL: Issues, https://github.com/hrbatra/dspy-codex-auth/issues
22
+ Project-URL: Repository, https://github.com/hrbatra/dspy-codex-auth
23
+ Description-Content-Type: text/markdown
24
+
25
+ # dspy-codex-auth
26
+
27
+ DSPy integration for using ChatGPT/Codex subscription credentials as a DSPy
28
+ language model.
29
+
30
+ This package is intentionally narrow:
31
+
32
+ - It includes ChatGPT/Codex OAuth login, token refresh, and Pi-compatible
33
+ credential storage.
34
+ - It installs a DSPy `LM` wrapper for `codex/...` model strings.
35
+ - It fixes Codex Responses streaming shapes that DSPy 3.2 cannot parse from
36
+ the current Codex backend response stream.
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ uv add dspy-codex-auth
42
+ ```
43
+
44
+ Until the first PyPI release is installed in your environment, install from the
45
+ GitHub repo:
46
+
47
+ ```bash
48
+ uv add "dspy-codex-auth @ git+https://github.com/hrbatra/dspy-codex-auth.git@main"
49
+ ```
50
+
51
+ ## Login
52
+
53
+ If you already have Codex credentials in `~/.pi/agent/auth.json`, no extra
54
+ login is needed.
55
+
56
+ Otherwise:
57
+
58
+ ```bash
59
+ uv run python -c "import dspy_codex_auth; dspy_codex_auth.login()"
60
+ ```
61
+
62
+ ## Basic Usage
63
+
64
+ ```python
65
+ import dspy
66
+ import dspy_codex_auth
67
+
68
+ dspy_codex_auth.install()
69
+
70
+ lm = dspy.LM("codex/gpt-5.5", cache=False)
71
+ dspy.configure(lm=lm, adapter=dspy.JSONAdapter())
72
+ ```
73
+
74
+ `cache=False` is recommended for Codex while iterating because stale DSPy cache
75
+ entries can preserve old empty-output responses across package upgrades.
76
+
77
+ ## Reasoning Summary
78
+
79
+ Pass `reasoning_effort` as usual. This package also supports
80
+ `reasoning_summary`, which maps to the Responses API `reasoning.summary` field.
81
+
82
+ ```python
83
+ lm = dspy.LM(
84
+ "codex/gpt-5.5",
85
+ cache=False,
86
+ reasoning_effort="medium",
87
+ reasoning_summary="detailed",
88
+ )
89
+ ```
90
+
91
+ DSPy predictions expose declared output fields. The lower-level LM history can
92
+ also include a returned reasoning summary:
93
+
94
+ ```python
95
+ summary = lm.history[-1]["outputs"][0].get("reasoning_content")
96
+ ```
97
+
98
+ ## OpenAI-Style Model String With Codex Auth
99
+
100
+ If you prefer to keep an `openai/...` model string and select Codex auth
101
+ explicitly:
102
+
103
+ ```python
104
+ lm = dspy_codex_auth.LM(
105
+ "openai/gpt-5.5",
106
+ auth_provider="codex",
107
+ cache=False,
108
+ reasoning_effort="medium",
109
+ reasoning_summary="detailed",
110
+ )
111
+ ```
112
+
113
+ ## What It Fixes
114
+
115
+ The ChatGPT Codex backend streams useful output events, but the completed
116
+ LiteLLM Responses object can arrive with `response.output == []`. DSPy expects
117
+ Responses output items to contain final message text, function calls, and
118
+ reasoning summaries. This package reconstructs those output items from stream
119
+ events before DSPy parses the response.
120
+
121
+ It currently handles:
122
+
123
+ - `response.output_item.done`
124
+ - `response.output_text.done`
125
+ - `response.output_text.delta`
126
+ - `response.reasoning_summary_text.done`
127
+ - `response.reasoning_summary_text.delta`
128
+ - streamed function-call output items
129
+
130
+ It also strips output-token cap fields that the Codex backend currently rejects:
131
+
132
+ - `max_tokens`
133
+ - `max_output_tokens`
134
+ - `max_completion_tokens`
135
+
136
+ ## French Example
137
+
138
+ ```python
139
+ import dspy
140
+ import dspy_codex_auth
141
+
142
+ dspy_codex_auth.install()
143
+
144
+ lm = dspy.LM("codex/gpt-5.5", cache=False)
145
+ dspy.configure(lm=lm, adapter=dspy.JSONAdapter())
146
+
147
+
148
+ class TranslateFrenchToEnglish(dspy.Signature):
149
+ """Translate the French input into short, natural English."""
150
+
151
+ french: str = dspy.InputField(desc="French sentence")
152
+ english: str = dspy.OutputField(desc="Natural English translation")
153
+
154
+
155
+ translator = dspy.Predict(TranslateFrenchToEnglish)
156
+ print(translator(french="merci beaucoup").english)
157
+ ```
158
+
159
+ ## Math Example With Reasoning Summary
160
+
161
+ ```python
162
+ import dspy
163
+ import dspy_codex_auth
164
+
165
+ dspy_codex_auth.install()
166
+
167
+ lm = dspy.LM(
168
+ "codex/gpt-5.5",
169
+ cache=False,
170
+ reasoning_effort="medium",
171
+ reasoning_summary="detailed",
172
+ )
173
+ dspy.configure(lm=lm, adapter=dspy.JSONAdapter())
174
+
175
+
176
+ class SolveMath(dspy.Signature):
177
+ """Solve the math problem. Return a concise numeric answer and a brief explanation."""
178
+
179
+ problem: str = dspy.InputField(desc="Math problem")
180
+ answer: str = dspy.OutputField(desc="Concise final answer")
181
+ explanation: str = dspy.OutputField(desc="Brief explanation")
182
+
183
+
184
+ solver = dspy.Predict(SolveMath)
185
+ pred = solver(
186
+ problem=(
187
+ "Compute the integral of the standard normal probability density "
188
+ "function from 0 to 1.5."
189
+ )
190
+ )
191
+
192
+ print(pred.answer)
193
+ print(pred.explanation)
194
+ print(lm.history[-1]["outputs"][0].get("reasoning_content"))
195
+ ```
196
+
197
+ ## Attribution
198
+
199
+ `dspy-codex-auth` includes and adapts MIT-licensed auth and DSPy integration
200
+ code from `dspy-lm-auth`:
201
+
202
+ https://github.com/MaximeRivest/dspy-lm-auth
203
+
204
+ The streamed-output reconstruction addresses a DSPy/Codex Responses streaming
205
+ compatibility issue that was also discussed in `dspy-lm-auth` PR #2:
206
+
207
+ https://github.com/MaximeRivest/dspy-lm-auth/pull/2
208
+
209
+ `dspy-lm-auth` is MIT-licensed. The original copyright notice is preserved in
210
+ `THIRD_PARTY_NOTICES.md`.
211
+
212
+ ## Development
213
+
214
+ ```bash
215
+ uv sync --dev
216
+ uv run pytest
217
+ uv run ruff check .
218
+ uv build --no-sources
219
+ ```
220
+
221
+ ## Release
222
+
223
+ Releases are published from GitHub Actions with PyPI Trusted Publishing.
224
+
225
+ For the first release, create a pending PyPI publisher for:
226
+
227
+ - PyPI project: `dspy-codex-auth`
228
+ - Owner: `hrbatra`
229
+ - Repository: `dspy-codex-auth`
230
+ - Workflow: `publish.yml`
231
+ - Environment: `pypi`
232
+
233
+ Then tag and push:
234
+
235
+ ```bash
236
+ git tag v0.1.0
237
+ git push origin v0.1.0
238
+ ```
@@ -0,0 +1,214 @@
1
+ # dspy-codex-auth
2
+
3
+ DSPy integration for using ChatGPT/Codex subscription credentials as a DSPy
4
+ language model.
5
+
6
+ This package is intentionally narrow:
7
+
8
+ - It includes ChatGPT/Codex OAuth login, token refresh, and Pi-compatible
9
+ credential storage.
10
+ - It installs a DSPy `LM` wrapper for `codex/...` model strings.
11
+ - It fixes Codex Responses streaming shapes that DSPy 3.2 cannot parse from
12
+ the current Codex backend response stream.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ uv add dspy-codex-auth
18
+ ```
19
+
20
+ Until the first PyPI release is installed in your environment, install from the
21
+ GitHub repo:
22
+
23
+ ```bash
24
+ uv add "dspy-codex-auth @ git+https://github.com/hrbatra/dspy-codex-auth.git@main"
25
+ ```
26
+
27
+ ## Login
28
+
29
+ If you already have Codex credentials in `~/.pi/agent/auth.json`, no extra
30
+ login is needed.
31
+
32
+ Otherwise:
33
+
34
+ ```bash
35
+ uv run python -c "import dspy_codex_auth; dspy_codex_auth.login()"
36
+ ```
37
+
38
+ ## Basic Usage
39
+
40
+ ```python
41
+ import dspy
42
+ import dspy_codex_auth
43
+
44
+ dspy_codex_auth.install()
45
+
46
+ lm = dspy.LM("codex/gpt-5.5", cache=False)
47
+ dspy.configure(lm=lm, adapter=dspy.JSONAdapter())
48
+ ```
49
+
50
+ `cache=False` is recommended for Codex while iterating because stale DSPy cache
51
+ entries can preserve old empty-output responses across package upgrades.
52
+
53
+ ## Reasoning Summary
54
+
55
+ Pass `reasoning_effort` as usual. This package also supports
56
+ `reasoning_summary`, which maps to the Responses API `reasoning.summary` field.
57
+
58
+ ```python
59
+ lm = dspy.LM(
60
+ "codex/gpt-5.5",
61
+ cache=False,
62
+ reasoning_effort="medium",
63
+ reasoning_summary="detailed",
64
+ )
65
+ ```
66
+
67
+ DSPy predictions expose declared output fields. The lower-level LM history can
68
+ also include a returned reasoning summary:
69
+
70
+ ```python
71
+ summary = lm.history[-1]["outputs"][0].get("reasoning_content")
72
+ ```
73
+
74
+ ## OpenAI-Style Model String With Codex Auth
75
+
76
+ If you prefer to keep an `openai/...` model string and select Codex auth
77
+ explicitly:
78
+
79
+ ```python
80
+ lm = dspy_codex_auth.LM(
81
+ "openai/gpt-5.5",
82
+ auth_provider="codex",
83
+ cache=False,
84
+ reasoning_effort="medium",
85
+ reasoning_summary="detailed",
86
+ )
87
+ ```
88
+
89
+ ## What It Fixes
90
+
91
+ The ChatGPT Codex backend streams useful output events, but the completed
92
+ LiteLLM Responses object can arrive with `response.output == []`. DSPy expects
93
+ Responses output items to contain final message text, function calls, and
94
+ reasoning summaries. This package reconstructs those output items from stream
95
+ events before DSPy parses the response.
96
+
97
+ It currently handles:
98
+
99
+ - `response.output_item.done`
100
+ - `response.output_text.done`
101
+ - `response.output_text.delta`
102
+ - `response.reasoning_summary_text.done`
103
+ - `response.reasoning_summary_text.delta`
104
+ - streamed function-call output items
105
+
106
+ It also strips output-token cap fields that the Codex backend currently rejects:
107
+
108
+ - `max_tokens`
109
+ - `max_output_tokens`
110
+ - `max_completion_tokens`
111
+
112
+ ## French Example
113
+
114
+ ```python
115
+ import dspy
116
+ import dspy_codex_auth
117
+
118
+ dspy_codex_auth.install()
119
+
120
+ lm = dspy.LM("codex/gpt-5.5", cache=False)
121
+ dspy.configure(lm=lm, adapter=dspy.JSONAdapter())
122
+
123
+
124
+ class TranslateFrenchToEnglish(dspy.Signature):
125
+ """Translate the French input into short, natural English."""
126
+
127
+ french: str = dspy.InputField(desc="French sentence")
128
+ english: str = dspy.OutputField(desc="Natural English translation")
129
+
130
+
131
+ translator = dspy.Predict(TranslateFrenchToEnglish)
132
+ print(translator(french="merci beaucoup").english)
133
+ ```
134
+
135
+ ## Math Example With Reasoning Summary
136
+
137
+ ```python
138
+ import dspy
139
+ import dspy_codex_auth
140
+
141
+ dspy_codex_auth.install()
142
+
143
+ lm = dspy.LM(
144
+ "codex/gpt-5.5",
145
+ cache=False,
146
+ reasoning_effort="medium",
147
+ reasoning_summary="detailed",
148
+ )
149
+ dspy.configure(lm=lm, adapter=dspy.JSONAdapter())
150
+
151
+
152
+ class SolveMath(dspy.Signature):
153
+ """Solve the math problem. Return a concise numeric answer and a brief explanation."""
154
+
155
+ problem: str = dspy.InputField(desc="Math problem")
156
+ answer: str = dspy.OutputField(desc="Concise final answer")
157
+ explanation: str = dspy.OutputField(desc="Brief explanation")
158
+
159
+
160
+ solver = dspy.Predict(SolveMath)
161
+ pred = solver(
162
+ problem=(
163
+ "Compute the integral of the standard normal probability density "
164
+ "function from 0 to 1.5."
165
+ )
166
+ )
167
+
168
+ print(pred.answer)
169
+ print(pred.explanation)
170
+ print(lm.history[-1]["outputs"][0].get("reasoning_content"))
171
+ ```
172
+
173
+ ## Attribution
174
+
175
+ `dspy-codex-auth` includes and adapts MIT-licensed auth and DSPy integration
176
+ code from `dspy-lm-auth`:
177
+
178
+ https://github.com/MaximeRivest/dspy-lm-auth
179
+
180
+ The streamed-output reconstruction addresses a DSPy/Codex Responses streaming
181
+ compatibility issue that was also discussed in `dspy-lm-auth` PR #2:
182
+
183
+ https://github.com/MaximeRivest/dspy-lm-auth/pull/2
184
+
185
+ `dspy-lm-auth` is MIT-licensed. The original copyright notice is preserved in
186
+ `THIRD_PARTY_NOTICES.md`.
187
+
188
+ ## Development
189
+
190
+ ```bash
191
+ uv sync --dev
192
+ uv run pytest
193
+ uv run ruff check .
194
+ uv build --no-sources
195
+ ```
196
+
197
+ ## Release
198
+
199
+ Releases are published from GitHub Actions with PyPI Trusted Publishing.
200
+
201
+ For the first release, create a pending PyPI publisher for:
202
+
203
+ - PyPI project: `dspy-codex-auth`
204
+ - Owner: `hrbatra`
205
+ - Repository: `dspy-codex-auth`
206
+ - Workflow: `publish.yml`
207
+ - Environment: `pypi`
208
+
209
+ Then tag and push:
210
+
211
+ ```bash
212
+ git tag v0.1.0
213
+ git push origin v0.1.0
214
+ ```
@@ -0,0 +1,40 @@
1
+ [project]
2
+ name = "dspy-codex-auth"
3
+ version = "0.1.0"
4
+ description = "DSPy integration for ChatGPT Codex subscription-backed language models"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "hrbatra", email = "hrbatra@utexas.edu" }
8
+ ]
9
+ license = "MIT"
10
+ requires-python = ">=3.12"
11
+ keywords = ["codex", "dspy", "language-models", "openai"]
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Intended Audience :: Developers",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
19
+ "Topic :: Software Development :: Libraries :: Python Modules",
20
+ ]
21
+ dependencies = [
22
+ "dspy>=3.2.0",
23
+ "litellm>=1.82.6",
24
+ "requests>=2.33.1",
25
+ ]
26
+
27
+ [project.urls]
28
+ Homepage = "https://github.com/hrbatra/dspy-codex-auth"
29
+ Repository = "https://github.com/hrbatra/dspy-codex-auth"
30
+ Issues = "https://github.com/hrbatra/dspy-codex-auth/issues"
31
+
32
+ [build-system]
33
+ requires = ["uv_build>=0.9.17,<0.10.0"]
34
+ build-backend = "uv_build"
35
+
36
+ [dependency-groups]
37
+ dev = [
38
+ "pytest>=9.0.3",
39
+ "ruff>=0.15.12",
40
+ ]
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 hrbatra
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,38 @@
1
+ # Third-Party Notices
2
+
3
+ `dspy-codex-auth` includes and adapts MIT-licensed auth and DSPy integration
4
+ code from `dspy-lm-auth`:
5
+
6
+ https://github.com/MaximeRivest/dspy-lm-auth
7
+
8
+ `dspy-lm-auth` is licensed under the MIT License.
9
+
10
+ The Codex streamed-output reconstruction implemented here addresses a
11
+ DSPy/Codex Responses streaming compatibility issue that was also discussed in
12
+ `dspy-lm-auth` pull request #2:
13
+
14
+ https://github.com/MaximeRivest/dspy-lm-auth/pull/2
15
+
16
+ ## dspy-lm-auth MIT License
17
+
18
+ MIT License
19
+
20
+ Copyright (c) 2026 Maxime Rivest
21
+
22
+ Permission is hereby granted, free of charge, to any person obtaining a copy
23
+ of this software and associated documentation files (the "Software"), to deal
24
+ in the Software without restriction, including without limitation the rights
25
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
26
+ copies of the Software, and to permit persons to whom the Software is
27
+ furnished to do so, subject to the following conditions:
28
+
29
+ The above copyright notice and this permission notice shall be included in all
30
+ copies or substantial portions of the Software.
31
+
32
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38
+ SOFTWARE.
@@ -0,0 +1,74 @@
1
+ from dspy_codex_auth.auth import (
2
+ OPENAI_CODEX_PROVIDER,
3
+ ApiKeyCredential,
4
+ AuthStorage,
5
+ Credential,
6
+ OAuthCredential,
7
+ OpenAICodexOAuthProvider,
8
+ build_openai_codex_authorization_url,
9
+ clear_command_cache,
10
+ exchange_openai_codex_code,
11
+ extract_chatgpt_account_id,
12
+ get_default_auth_storage,
13
+ get_oauth_provider,
14
+ getauthtoken,
15
+ login,
16
+ login_openai_codex,
17
+ logout,
18
+ normalize_provider_id,
19
+ parse_authorization_input,
20
+ refresh_openai_codex_token,
21
+ register_oauth_provider,
22
+ resolve_config_value,
23
+ set_default_auth_storage,
24
+ )
25
+
26
+ from dspy_codex_auth.lm import (
27
+ DEFAULT_CODEX_API_BASE,
28
+ DEFAULT_CODEX_INSTRUCTIONS,
29
+ DEFAULT_CODEX_MODEL,
30
+ DEFAULT_CODEX_ORIGINATOR,
31
+ LM,
32
+ codex_headers,
33
+ install,
34
+ register_model_alias,
35
+ resolve_lm_route,
36
+ uninstall,
37
+ unregister_model_alias,
38
+ )
39
+
40
+ __all__ = [
41
+ "DEFAULT_CODEX_API_BASE",
42
+ "DEFAULT_CODEX_INSTRUCTIONS",
43
+ "DEFAULT_CODEX_MODEL",
44
+ "DEFAULT_CODEX_ORIGINATOR",
45
+ "OPENAI_CODEX_PROVIDER",
46
+ "ApiKeyCredential",
47
+ "AuthStorage",
48
+ "Credential",
49
+ "LM",
50
+ "OAuthCredential",
51
+ "OpenAICodexOAuthProvider",
52
+ "build_openai_codex_authorization_url",
53
+ "clear_command_cache",
54
+ "codex_headers",
55
+ "exchange_openai_codex_code",
56
+ "extract_chatgpt_account_id",
57
+ "get_default_auth_storage",
58
+ "get_oauth_provider",
59
+ "getauthtoken",
60
+ "install",
61
+ "login",
62
+ "login_openai_codex",
63
+ "logout",
64
+ "normalize_provider_id",
65
+ "parse_authorization_input",
66
+ "refresh_openai_codex_token",
67
+ "register_model_alias",
68
+ "register_oauth_provider",
69
+ "resolve_config_value",
70
+ "resolve_lm_route",
71
+ "set_default_auth_storage",
72
+ "uninstall",
73
+ "unregister_model_alias",
74
+ ]