codex-python 0.2.16__tar.gz → 0.3.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_python-0.3.0/PKG-INFO +358 -0
- codex_python-0.3.0/README.md +338 -0
- {codex_python-0.2.16 → codex_python-0.3.0}/codex/__init__.py +6 -9
- codex_python-0.3.0/codex/client.py +410 -0
- {codex_python-0.2.16 → codex_python-0.3.0}/codex/config.py +86 -3
- codex_python-0.3.0/codex/exec.py +138 -0
- codex_python-0.3.0/codex/native.py +85 -0
- {codex_python-0.2.16 → codex_python-0.3.0}/crates/codex_native/Cargo.lock +96 -96
- {codex_python-0.2.16 → codex_python-0.3.0}/crates/codex_native/Cargo.toml +1 -1
- codex_python-0.3.0/crates/codex_native/src/lib.rs +1176 -0
- {codex_python-0.2.16 → codex_python-0.3.0}/pyproject.toml +2 -2
- codex_python-0.2.16/PKG-INFO +0 -141
- codex_python-0.2.16/README.md +0 -121
- codex_python-0.2.16/codex/api.py +0 -123
- codex_python-0.2.16/codex/native.py +0 -35
- codex_python-0.2.16/crates/codex_native/src/lib.rs +0 -545
- {codex_python-0.2.16 → codex_python-0.3.0}/LICENSE +0 -0
- {codex_python-0.2.16 → codex_python-0.3.0}/codex/event.py +0 -0
- {codex_python-0.2.16 → codex_python-0.3.0}/codex/protocol/_base_model.py +0 -0
- {codex_python-0.2.16 → codex_python-0.3.0}/codex/protocol/types.py +0 -0
- {codex_python-0.2.16 → codex_python-0.3.0}/codex/py.typed +0 -0
- {codex_python-0.2.16 → codex_python-0.3.0}/crates/codex_native/src/bin/protocol_schema.rs +0 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codex-python
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Classifier: Programming Language :: Python :: 3
|
|
5
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
6
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Typing :: Typed
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Dist: pydantic>=2.11.7
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Summary: A minimal Python library scaffold for codex-python
|
|
13
|
+
Keywords: codex,library,scaffold
|
|
14
|
+
Requires-Python: >=3.12
|
|
15
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
16
|
+
Project-URL: Homepage, https://github.com/gersmann/codex-python
|
|
17
|
+
Project-URL: Repository, https://github.com/gersmann/codex-python
|
|
18
|
+
Project-URL: Issues, https://github.com/gersmann/codex-python/issues
|
|
19
|
+
|
|
20
|
+
# codex-python
|
|
21
|
+
|
|
22
|
+
Native Python bindings for Codex (in‑process execution). Distributed as a single package with prebuilt wheels that bundle the native extension.
|
|
23
|
+
|
|
24
|
+
- Python: 3.12–3.13 (CI also attempts 3.14)
|
|
25
|
+
- Import name: `codex`
|
|
26
|
+
- PyPI: https://pypi.org/project/codex-python/
|
|
27
|
+
|
|
28
|
+
## Table of Contents
|
|
29
|
+
|
|
30
|
+
1. Install
|
|
31
|
+
2. Quickstart
|
|
32
|
+
3. API Overview
|
|
33
|
+
4. Configuration
|
|
34
|
+
- Common Overrides
|
|
35
|
+
- Examples
|
|
36
|
+
5. Troubleshooting
|
|
37
|
+
6. Developing
|
|
38
|
+
7. CI Integration (Review + Act)
|
|
39
|
+
|
|
40
|
+
## 1) Install
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
pip install codex-python
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
If there’s no prebuilt wheel for your platform/Python, pip will build from source. That requires a Rust toolchain and maturin; see Developing.
|
|
47
|
+
|
|
48
|
+
## 2) Quickstart
|
|
49
|
+
|
|
50
|
+
Run a prompt and collect structured events (typed):
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from codex import run_exec, CodexClient, CodexNativeError
|
|
54
|
+
from codex.config import CodexConfig, ApprovalPolicy, SandboxMode
|
|
55
|
+
|
|
56
|
+
cfg = CodexConfig(
|
|
57
|
+
model="gpt-5",
|
|
58
|
+
model_provider="openai",
|
|
59
|
+
approval_policy=ApprovalPolicy.ON_REQUEST,
|
|
60
|
+
sandbox_mode=SandboxMode.WORKSPACE_WRITE,
|
|
61
|
+
include_apply_patch_tool=False, # disable apply patch tool by default
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# One‑shot
|
|
65
|
+
try:
|
|
66
|
+
events = run_exec("Explain this repo", config=cfg)
|
|
67
|
+
for ev in events:
|
|
68
|
+
print(ev.id, ev.msg.type)
|
|
69
|
+
except CodexNativeError as e:
|
|
70
|
+
print("codex-native error:", e)
|
|
71
|
+
|
|
72
|
+
# Conversation (streaming)
|
|
73
|
+
client = CodexClient(config=cfg)
|
|
74
|
+
conv = client.start_conversation()
|
|
75
|
+
conv.submit_user_turn("Add a smoke test")
|
|
76
|
+
for ev in conv:
|
|
77
|
+
print(ev.id, getattr(getattr(ev.msg, "root", ev.msg), "type", "unknown"))
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Notes
|
|
81
|
+
- `Event.msg` is a typed union (`EventMsg`). For raw dicts from the native layer, use `codex.native.start_exec_stream`.
|
|
82
|
+
|
|
83
|
+
### Example: basic_conversation.py
|
|
84
|
+
|
|
85
|
+
Run the interactive example that streams events and prompts for approvals:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
python examples/basic_conversation.py "ask me a question"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Flags you may find useful:
|
|
92
|
+
- `--approval on-request` (default) to be asked before running tools
|
|
93
|
+
- `--sandbox workspace-write` to allow writes within the repo
|
|
94
|
+
- `--allow-apply-patch` to include the apply‑patch tool in the session
|
|
95
|
+
|
|
96
|
+
## 3) API Overview
|
|
97
|
+
|
|
98
|
+
- `codex.run_exec(prompt, *, config=None, load_default_config=True, output_schema=None) -> list[Event]`
|
|
99
|
+
Synchronous one‑shot; returns all events.
|
|
100
|
+
|
|
101
|
+
- `codex.run_review(prompt, *, user_facing_hint=None, config=None, load_default_config=True) -> list[Event]`
|
|
102
|
+
Synchronous review flow; returns all events.
|
|
103
|
+
|
|
104
|
+
- `codex.run_prompt(prompt, *, config=None, load_default_config=True, output_schema=None) -> str | Any`
|
|
105
|
+
Convenience: returns the final assistant message (or parsed JSON when `output_schema` is set).
|
|
106
|
+
|
|
107
|
+
- `codex.CodexClient(config).start_conversation(... ) -> Conversation`
|
|
108
|
+
Creates a stateful session. Iterate over `Conversation` to stream events.
|
|
109
|
+
- `Conversation.submit_user_turn(prompt, *, cwd=None, approval_policy=..., sandbox_mode=..., model=None, effort=..., summary=..., output_schema=None)`
|
|
110
|
+
- `Conversation.submit_review(prompt, user_facing_hint=None)`
|
|
111
|
+
- `Conversation.approve_exec(id, decision)` / `approve_patch(id, decision)`
|
|
112
|
+
- `Conversation.interrupt()`, `Conversation.shutdown()`
|
|
113
|
+
- Utility: `user_input_text`, `override_turn_context`, `add_to_history`, `get_history_entry`, `get_path`, `list_mcp_tools`, `list_custom_prompts`, `compact`
|
|
114
|
+
|
|
115
|
+
- `await codex.CodexClient(...).astart_conversation() -> AsyncConversation`
|
|
116
|
+
Async iterator with the same methods as `Conversation` (async variants).
|
|
117
|
+
|
|
118
|
+
- Exceptions
|
|
119
|
+
- `CodexError` base; `CodexNativeError` wraps native failures / missing extension.
|
|
120
|
+
|
|
121
|
+
- Native helper
|
|
122
|
+
- `codex.native.preview_config(config_overrides, load_default_config)` → compact effective config snapshot (testing aid).
|
|
123
|
+
|
|
124
|
+
## 4) Configuration
|
|
125
|
+
|
|
126
|
+
Use the Pydantic model `CodexConfig` for strongly‑typed overrides (mirrors the Rust `ConfigOverrides`).
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from codex.config import CodexConfig, ApprovalPolicy, SandboxMode
|
|
130
|
+
|
|
131
|
+
cfg = CodexConfig(
|
|
132
|
+
model="gpt-5",
|
|
133
|
+
model_provider="openai",
|
|
134
|
+
approval_policy=ApprovalPolicy.ON_REQUEST,
|
|
135
|
+
sandbox_mode=SandboxMode.WORKSPACE_WRITE,
|
|
136
|
+
cwd="/path/to/project",
|
|
137
|
+
include_apply_patch_tool=True,
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Behavior
|
|
142
|
+
- Precedence matches the CLI: `config.toml` < CLI `-c key=value` < typed overrides (`CodexConfig`).
|
|
143
|
+
- `to_dict()` emits only set fields and serializes enums to kebab‑case as expected by the native core.
|
|
144
|
+
- Set `load_default_config=False` on API calls to avoid reading any on‑disk config and rely purely on overrides you pass in.
|
|
145
|
+
|
|
146
|
+
### Common Overrides
|
|
147
|
+
|
|
148
|
+
- Model selection: `model`, `review_model`, `model_provider`.
|
|
149
|
+
- Approvals & sandbox: `approval_policy`, `sandbox_mode`, `sandbox_workspace_write` (fine‑tune writeable roots, network, tmpdir behavior for WorkspaceWrite).
|
|
150
|
+
- Shell env policy: `shell_environment_policy` for child process envs: `inherit` (`core|all|none`), `exclude`, `include_only`, `set`, `experimental_use_profile`.
|
|
151
|
+
- Tools: `include_plan_tool`, `include_apply_patch_tool`, `include_view_image_tool`, `tools_web_search_request`.
|
|
152
|
+
- Reasoning & tokens: `model_context_window`, `model_max_output_tokens`, `model_auto_compact_token_limit`, `model_reasoning_effort`, `model_reasoning_summary`, `model_verbosity`, `model_supports_reasoning_summaries`, `model_reasoning_summary_format`.
|
|
153
|
+
- UI/UX: `show_raw_agent_reasoning`, `hide_agent_reasoning`, `disable_paste_burst`, `chatgpt_base_url`, `file_opener`.
|
|
154
|
+
- Providers & MCP: `model_providers` entries support `wire_api` (`responses|chat`), `env_key`, `env_key_instructions`, `http_headers`, `env_http_headers`, retry/timeout tuning; `requires_openai_auth` enables ChatGPT/OAuth auth. Define MCP servers via `mcp_servers`.
|
|
155
|
+
|
|
156
|
+
### Examples
|
|
157
|
+
|
|
158
|
+
Enable web search and tune sandbox writes:
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
from codex.config import CodexConfig, ApprovalPolicy, SandboxMode
|
|
162
|
+
|
|
163
|
+
cfg = CodexConfig(
|
|
164
|
+
model="gpt-5",
|
|
165
|
+
review_model="gpt-5-codex",
|
|
166
|
+
model_provider="openai",
|
|
167
|
+
approval_policy=ApprovalPolicy.ON_REQUEST,
|
|
168
|
+
sandbox_mode=SandboxMode.WORKSPACE_WRITE,
|
|
169
|
+
sandbox_workspace_write={
|
|
170
|
+
"writable_roots": ["/tmp/my-session"],
|
|
171
|
+
"exclude_tmpdir_env_var": True,
|
|
172
|
+
},
|
|
173
|
+
tools_web_search_request=True,
|
|
174
|
+
)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Constrain child process environment for shell tools:
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
from codex.config import CodexConfig, ShellEnvironmentPolicy
|
|
181
|
+
|
|
182
|
+
cfg = CodexConfig(
|
|
183
|
+
shell_environment_policy=ShellEnvironmentPolicy(
|
|
184
|
+
inherit="core",
|
|
185
|
+
exclude=["*TOKEN*", "*KEY*"],
|
|
186
|
+
set={"FOO": "bar"},
|
|
187
|
+
include_only=["PATH", "HOME", "FOO"],
|
|
188
|
+
)
|
|
189
|
+
)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Provider entry with OAuth‑style auth:
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
from codex.config import CodexConfig
|
|
196
|
+
|
|
197
|
+
cfg = CodexConfig(
|
|
198
|
+
model_provider="openai",
|
|
199
|
+
model_providers={
|
|
200
|
+
"openai": {
|
|
201
|
+
"name": "OpenAI",
|
|
202
|
+
"wire_api": "responses",
|
|
203
|
+
"requires_openai_auth": True,
|
|
204
|
+
"request_max_retries": 4,
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## 5) Troubleshooting
|
|
211
|
+
|
|
212
|
+
- “codex_native extension not installed”
|
|
213
|
+
- Install from PyPI or build locally (see Developing). If building, ensure Rust toolchain + maturin are available.
|
|
214
|
+
- No native wheel for your platform/Python
|
|
215
|
+
- Pip will build from source. If that fails, check your Rust toolchain and try `make dev-native` inside a virtualenv.
|
|
216
|
+
- Missing `OPENAI_API_KEY`
|
|
217
|
+
- Set the environment variable or configure a provider entry (`model_providers`) that uses a different auth method.
|
|
218
|
+
|
|
219
|
+
## 6) Developing
|
|
220
|
+
|
|
221
|
+
Prerequisites
|
|
222
|
+
- Python 3.12/3.13
|
|
223
|
+
- Rust toolchain (cargo)
|
|
224
|
+
- maturin (native builds)
|
|
225
|
+
- uv (optional, fast Python builds and dev tooling)
|
|
226
|
+
|
|
227
|
+
Common tasks
|
|
228
|
+
- Format: `make fmt`
|
|
229
|
+
- Lint: `make lint` (ruff + mypy)
|
|
230
|
+
- Test: `make test` (pytest)
|
|
231
|
+
- Build native locally: `make dev-native`
|
|
232
|
+
- Generate protocol types from upstream: `make gen-protocol`
|
|
233
|
+
|
|
234
|
+
Protocol types
|
|
235
|
+
- `make gen-protocol` generates TS types + JSON Schema and writes Pydantic v2 models to `codex/protocol/types.py`.
|
|
236
|
+
- Generated models include `model_config = ConfigDict(extra='allow')` at class end.
|
|
237
|
+
|
|
238
|
+
Releasing
|
|
239
|
+
- Bump versions in `codex/__init__.py` and `crates/codex_native/Cargo.toml`.
|
|
240
|
+
- Update `CHANGELOG.md`.
|
|
241
|
+
- Tag and push: `git tag -a vX.Y.Z -m "codex-python X.Y.Z" && git push origin vX.Y.Z`.
|
|
242
|
+
- GitHub Actions builds and publishes wheels and sdist via Trusted Publishing.
|
|
243
|
+
|
|
244
|
+
Project layout
|
|
245
|
+
```
|
|
246
|
+
.
|
|
247
|
+
├── codex/ # Python package
|
|
248
|
+
├── crates/codex_native/ # PyO3 native extension
|
|
249
|
+
├── scripts/ # generators and helpers
|
|
250
|
+
├── .github/workflows/ # CI, publish, native wheels
|
|
251
|
+
└── Makefile # common tasks
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Links
|
|
255
|
+
- Codex: https://github.com/openai/codex
|
|
256
|
+
- uv: https://docs.astral.sh/uv/
|
|
257
|
+
- maturin: https://www.maturin.rs/
|
|
258
|
+
|
|
259
|
+
## 7) CI Integration: Review + Act
|
|
260
|
+
|
|
261
|
+
This repo includes a workflow that:
|
|
262
|
+
- Runs autonomous code review on PRs ("Review" job).
|
|
263
|
+
- Listens for `/codex ...` comments and performs autonomous edits ("Act" job), optionally running your tests.
|
|
264
|
+
|
|
265
|
+
Both jobs use `gersmann/codex-review-action@v1`.
|
|
266
|
+
|
|
267
|
+
### Minimal Review Job
|
|
268
|
+
|
|
269
|
+
```yaml
|
|
270
|
+
name: Codex Review
|
|
271
|
+
on:
|
|
272
|
+
pull_request:
|
|
273
|
+
types: [opened, synchronize, ready_for_review]
|
|
274
|
+
jobs:
|
|
275
|
+
review:
|
|
276
|
+
name: Review
|
|
277
|
+
permissions:
|
|
278
|
+
contents: read
|
|
279
|
+
pull-requests: write
|
|
280
|
+
issues: read
|
|
281
|
+
env:
|
|
282
|
+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
283
|
+
runs-on: ubuntu-latest
|
|
284
|
+
steps:
|
|
285
|
+
- uses: actions/checkout@v4
|
|
286
|
+
with:
|
|
287
|
+
fetch-depth: 0
|
|
288
|
+
- name: Codex autonomous review
|
|
289
|
+
if: env.OPENAI_API_KEY != ''
|
|
290
|
+
uses: gersmann/codex-review-action@v1
|
|
291
|
+
with:
|
|
292
|
+
mode: review
|
|
293
|
+
openai_api_key: ${{ secrets.OPENAI_API_KEY }}
|
|
294
|
+
model: gpt-5
|
|
295
|
+
reasoning_effort: medium
|
|
296
|
+
debug_level: 1
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Act on `/codex` Comments
|
|
300
|
+
|
|
301
|
+
```yaml
|
|
302
|
+
act:
|
|
303
|
+
name: Act on /codex comments
|
|
304
|
+
if: >-
|
|
305
|
+
(
|
|
306
|
+
github.event_name == 'issue_comment' &&
|
|
307
|
+
startsWith(github.event.comment.body, '/codex') &&
|
|
308
|
+
github.event.issue.pull_request &&
|
|
309
|
+
contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association)
|
|
310
|
+
) || (
|
|
311
|
+
github.event_name == 'pull_request_review_comment' &&
|
|
312
|
+
startsWith(github.event.comment.body, '/codex') &&
|
|
313
|
+
contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association)
|
|
314
|
+
)
|
|
315
|
+
&& github.actor != 'dependabot[bot]'
|
|
316
|
+
concurrency:
|
|
317
|
+
group: codex-act-${{ github.event.issue.number || github.event.pull_request.number || github.ref }}
|
|
318
|
+
cancel-in-progress: false
|
|
319
|
+
permissions:
|
|
320
|
+
contents: write
|
|
321
|
+
issues: write
|
|
322
|
+
pull-requests: write
|
|
323
|
+
actions: write
|
|
324
|
+
runs-on: ubuntu-latest
|
|
325
|
+
env:
|
|
326
|
+
APP_ENV: test
|
|
327
|
+
CI: true
|
|
328
|
+
steps:
|
|
329
|
+
- uses: actions/checkout@v4
|
|
330
|
+
with:
|
|
331
|
+
fetch-depth: 0
|
|
332
|
+
ref: ${{ github.event.pull_request.head.sha || format('refs/pull/{0}/head', github.event.issue.number) }}
|
|
333
|
+
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
|
334
|
+
- name: Setup Environment
|
|
335
|
+
uses: ./.github/actions/setup
|
|
336
|
+
with:
|
|
337
|
+
python-version: '3.13'
|
|
338
|
+
node-version: '20'
|
|
339
|
+
- name: Codex autonomous edits
|
|
340
|
+
if: env.OPENAI_API_KEY != ''
|
|
341
|
+
uses: gersmann/codex-review-action@v1
|
|
342
|
+
with:
|
|
343
|
+
mode: act
|
|
344
|
+
openai_api_key: ${{ secrets.OPENAI_API_KEY }}
|
|
345
|
+
model: gpt-5
|
|
346
|
+
debug_level: 1
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Common `/codex` patterns
|
|
350
|
+
- `/codex` — propose and apply fixes
|
|
351
|
+
- `/codex focus <path>` — limit scope
|
|
352
|
+
- `/codex redo` — re‑run on latest PR head
|
|
353
|
+
|
|
354
|
+
Secrets
|
|
355
|
+
- `OPENAI_API_KEY` to call the model API
|
|
356
|
+
- `REPO_ACCESS_TOKEN` (write permission) so pushes from Act trigger CI
|
|
357
|
+
- Project‑specific secrets for tests (DB URLs, API keys), when services are enabled
|
|
358
|
+
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# codex-python
|
|
2
|
+
|
|
3
|
+
Native Python bindings for Codex (in‑process execution). Distributed as a single package with prebuilt wheels that bundle the native extension.
|
|
4
|
+
|
|
5
|
+
- Python: 3.12–3.13 (CI also attempts 3.14)
|
|
6
|
+
- Import name: `codex`
|
|
7
|
+
- PyPI: https://pypi.org/project/codex-python/
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
1. Install
|
|
12
|
+
2. Quickstart
|
|
13
|
+
3. API Overview
|
|
14
|
+
4. Configuration
|
|
15
|
+
- Common Overrides
|
|
16
|
+
- Examples
|
|
17
|
+
5. Troubleshooting
|
|
18
|
+
6. Developing
|
|
19
|
+
7. CI Integration (Review + Act)
|
|
20
|
+
|
|
21
|
+
## 1) Install
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
pip install codex-python
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
If there’s no prebuilt wheel for your platform/Python, pip will build from source. That requires a Rust toolchain and maturin; see Developing.
|
|
28
|
+
|
|
29
|
+
## 2) Quickstart
|
|
30
|
+
|
|
31
|
+
Run a prompt and collect structured events (typed):
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from codex import run_exec, CodexClient, CodexNativeError
|
|
35
|
+
from codex.config import CodexConfig, ApprovalPolicy, SandboxMode
|
|
36
|
+
|
|
37
|
+
cfg = CodexConfig(
|
|
38
|
+
model="gpt-5",
|
|
39
|
+
model_provider="openai",
|
|
40
|
+
approval_policy=ApprovalPolicy.ON_REQUEST,
|
|
41
|
+
sandbox_mode=SandboxMode.WORKSPACE_WRITE,
|
|
42
|
+
include_apply_patch_tool=False, # disable apply patch tool by default
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# One‑shot
|
|
46
|
+
try:
|
|
47
|
+
events = run_exec("Explain this repo", config=cfg)
|
|
48
|
+
for ev in events:
|
|
49
|
+
print(ev.id, ev.msg.type)
|
|
50
|
+
except CodexNativeError as e:
|
|
51
|
+
print("codex-native error:", e)
|
|
52
|
+
|
|
53
|
+
# Conversation (streaming)
|
|
54
|
+
client = CodexClient(config=cfg)
|
|
55
|
+
conv = client.start_conversation()
|
|
56
|
+
conv.submit_user_turn("Add a smoke test")
|
|
57
|
+
for ev in conv:
|
|
58
|
+
print(ev.id, getattr(getattr(ev.msg, "root", ev.msg), "type", "unknown"))
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Notes
|
|
62
|
+
- `Event.msg` is a typed union (`EventMsg`). For raw dicts from the native layer, use `codex.native.start_exec_stream`.
|
|
63
|
+
|
|
64
|
+
### Example: basic_conversation.py
|
|
65
|
+
|
|
66
|
+
Run the interactive example that streams events and prompts for approvals:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
python examples/basic_conversation.py "ask me a question"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Flags you may find useful:
|
|
73
|
+
- `--approval on-request` (default) to be asked before running tools
|
|
74
|
+
- `--sandbox workspace-write` to allow writes within the repo
|
|
75
|
+
- `--allow-apply-patch` to include the apply‑patch tool in the session
|
|
76
|
+
|
|
77
|
+
## 3) API Overview
|
|
78
|
+
|
|
79
|
+
- `codex.run_exec(prompt, *, config=None, load_default_config=True, output_schema=None) -> list[Event]`
|
|
80
|
+
Synchronous one‑shot; returns all events.
|
|
81
|
+
|
|
82
|
+
- `codex.run_review(prompt, *, user_facing_hint=None, config=None, load_default_config=True) -> list[Event]`
|
|
83
|
+
Synchronous review flow; returns all events.
|
|
84
|
+
|
|
85
|
+
- `codex.run_prompt(prompt, *, config=None, load_default_config=True, output_schema=None) -> str | Any`
|
|
86
|
+
Convenience: returns the final assistant message (or parsed JSON when `output_schema` is set).
|
|
87
|
+
|
|
88
|
+
- `codex.CodexClient(config).start_conversation(... ) -> Conversation`
|
|
89
|
+
Creates a stateful session. Iterate over `Conversation` to stream events.
|
|
90
|
+
- `Conversation.submit_user_turn(prompt, *, cwd=None, approval_policy=..., sandbox_mode=..., model=None, effort=..., summary=..., output_schema=None)`
|
|
91
|
+
- `Conversation.submit_review(prompt, user_facing_hint=None)`
|
|
92
|
+
- `Conversation.approve_exec(id, decision)` / `approve_patch(id, decision)`
|
|
93
|
+
- `Conversation.interrupt()`, `Conversation.shutdown()`
|
|
94
|
+
- Utility: `user_input_text`, `override_turn_context`, `add_to_history`, `get_history_entry`, `get_path`, `list_mcp_tools`, `list_custom_prompts`, `compact`
|
|
95
|
+
|
|
96
|
+
- `await codex.CodexClient(...).astart_conversation() -> AsyncConversation`
|
|
97
|
+
Async iterator with the same methods as `Conversation` (async variants).
|
|
98
|
+
|
|
99
|
+
- Exceptions
|
|
100
|
+
- `CodexError` base; `CodexNativeError` wraps native failures / missing extension.
|
|
101
|
+
|
|
102
|
+
- Native helper
|
|
103
|
+
- `codex.native.preview_config(config_overrides, load_default_config)` → compact effective config snapshot (testing aid).
|
|
104
|
+
|
|
105
|
+
## 4) Configuration
|
|
106
|
+
|
|
107
|
+
Use the Pydantic model `CodexConfig` for strongly‑typed overrides (mirrors the Rust `ConfigOverrides`).
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
from codex.config import CodexConfig, ApprovalPolicy, SandboxMode
|
|
111
|
+
|
|
112
|
+
cfg = CodexConfig(
|
|
113
|
+
model="gpt-5",
|
|
114
|
+
model_provider="openai",
|
|
115
|
+
approval_policy=ApprovalPolicy.ON_REQUEST,
|
|
116
|
+
sandbox_mode=SandboxMode.WORKSPACE_WRITE,
|
|
117
|
+
cwd="/path/to/project",
|
|
118
|
+
include_apply_patch_tool=True,
|
|
119
|
+
)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Behavior
|
|
123
|
+
- Precedence matches the CLI: `config.toml` < CLI `-c key=value` < typed overrides (`CodexConfig`).
|
|
124
|
+
- `to_dict()` emits only set fields and serializes enums to kebab‑case as expected by the native core.
|
|
125
|
+
- Set `load_default_config=False` on API calls to avoid reading any on‑disk config and rely purely on overrides you pass in.
|
|
126
|
+
|
|
127
|
+
### Common Overrides
|
|
128
|
+
|
|
129
|
+
- Model selection: `model`, `review_model`, `model_provider`.
|
|
130
|
+
- Approvals & sandbox: `approval_policy`, `sandbox_mode`, `sandbox_workspace_write` (fine‑tune writeable roots, network, tmpdir behavior for WorkspaceWrite).
|
|
131
|
+
- Shell env policy: `shell_environment_policy` for child process envs: `inherit` (`core|all|none`), `exclude`, `include_only`, `set`, `experimental_use_profile`.
|
|
132
|
+
- Tools: `include_plan_tool`, `include_apply_patch_tool`, `include_view_image_tool`, `tools_web_search_request`.
|
|
133
|
+
- Reasoning & tokens: `model_context_window`, `model_max_output_tokens`, `model_auto_compact_token_limit`, `model_reasoning_effort`, `model_reasoning_summary`, `model_verbosity`, `model_supports_reasoning_summaries`, `model_reasoning_summary_format`.
|
|
134
|
+
- UI/UX: `show_raw_agent_reasoning`, `hide_agent_reasoning`, `disable_paste_burst`, `chatgpt_base_url`, `file_opener`.
|
|
135
|
+
- Providers & MCP: `model_providers` entries support `wire_api` (`responses|chat`), `env_key`, `env_key_instructions`, `http_headers`, `env_http_headers`, retry/timeout tuning; `requires_openai_auth` enables ChatGPT/OAuth auth. Define MCP servers via `mcp_servers`.
|
|
136
|
+
|
|
137
|
+
### Examples
|
|
138
|
+
|
|
139
|
+
Enable web search and tune sandbox writes:
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from codex.config import CodexConfig, ApprovalPolicy, SandboxMode
|
|
143
|
+
|
|
144
|
+
cfg = CodexConfig(
|
|
145
|
+
model="gpt-5",
|
|
146
|
+
review_model="gpt-5-codex",
|
|
147
|
+
model_provider="openai",
|
|
148
|
+
approval_policy=ApprovalPolicy.ON_REQUEST,
|
|
149
|
+
sandbox_mode=SandboxMode.WORKSPACE_WRITE,
|
|
150
|
+
sandbox_workspace_write={
|
|
151
|
+
"writable_roots": ["/tmp/my-session"],
|
|
152
|
+
"exclude_tmpdir_env_var": True,
|
|
153
|
+
},
|
|
154
|
+
tools_web_search_request=True,
|
|
155
|
+
)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Constrain child process environment for shell tools:
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
from codex.config import CodexConfig, ShellEnvironmentPolicy
|
|
162
|
+
|
|
163
|
+
cfg = CodexConfig(
|
|
164
|
+
shell_environment_policy=ShellEnvironmentPolicy(
|
|
165
|
+
inherit="core",
|
|
166
|
+
exclude=["*TOKEN*", "*KEY*"],
|
|
167
|
+
set={"FOO": "bar"},
|
|
168
|
+
include_only=["PATH", "HOME", "FOO"],
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Provider entry with OAuth‑style auth:
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
from codex.config import CodexConfig
|
|
177
|
+
|
|
178
|
+
cfg = CodexConfig(
|
|
179
|
+
model_provider="openai",
|
|
180
|
+
model_providers={
|
|
181
|
+
"openai": {
|
|
182
|
+
"name": "OpenAI",
|
|
183
|
+
"wire_api": "responses",
|
|
184
|
+
"requires_openai_auth": True,
|
|
185
|
+
"request_max_retries": 4,
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## 5) Troubleshooting
|
|
192
|
+
|
|
193
|
+
- “codex_native extension not installed”
|
|
194
|
+
- Install from PyPI or build locally (see Developing). If building, ensure Rust toolchain + maturin are available.
|
|
195
|
+
- No native wheel for your platform/Python
|
|
196
|
+
- Pip will build from source. If that fails, check your Rust toolchain and try `make dev-native` inside a virtualenv.
|
|
197
|
+
- Missing `OPENAI_API_KEY`
|
|
198
|
+
- Set the environment variable or configure a provider entry (`model_providers`) that uses a different auth method.
|
|
199
|
+
|
|
200
|
+
## 6) Developing
|
|
201
|
+
|
|
202
|
+
Prerequisites
|
|
203
|
+
- Python 3.12/3.13
|
|
204
|
+
- Rust toolchain (cargo)
|
|
205
|
+
- maturin (native builds)
|
|
206
|
+
- uv (optional, fast Python builds and dev tooling)
|
|
207
|
+
|
|
208
|
+
Common tasks
|
|
209
|
+
- Format: `make fmt`
|
|
210
|
+
- Lint: `make lint` (ruff + mypy)
|
|
211
|
+
- Test: `make test` (pytest)
|
|
212
|
+
- Build native locally: `make dev-native`
|
|
213
|
+
- Generate protocol types from upstream: `make gen-protocol`
|
|
214
|
+
|
|
215
|
+
Protocol types
|
|
216
|
+
- `make gen-protocol` generates TS types + JSON Schema and writes Pydantic v2 models to `codex/protocol/types.py`.
|
|
217
|
+
- Generated models include `model_config = ConfigDict(extra='allow')` at class end.
|
|
218
|
+
|
|
219
|
+
Releasing
|
|
220
|
+
- Bump versions in `codex/__init__.py` and `crates/codex_native/Cargo.toml`.
|
|
221
|
+
- Update `CHANGELOG.md`.
|
|
222
|
+
- Tag and push: `git tag -a vX.Y.Z -m "codex-python X.Y.Z" && git push origin vX.Y.Z`.
|
|
223
|
+
- GitHub Actions builds and publishes wheels and sdist via Trusted Publishing.
|
|
224
|
+
|
|
225
|
+
Project layout
|
|
226
|
+
```
|
|
227
|
+
.
|
|
228
|
+
├── codex/ # Python package
|
|
229
|
+
├── crates/codex_native/ # PyO3 native extension
|
|
230
|
+
├── scripts/ # generators and helpers
|
|
231
|
+
├── .github/workflows/ # CI, publish, native wheels
|
|
232
|
+
└── Makefile # common tasks
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Links
|
|
236
|
+
- Codex: https://github.com/openai/codex
|
|
237
|
+
- uv: https://docs.astral.sh/uv/
|
|
238
|
+
- maturin: https://www.maturin.rs/
|
|
239
|
+
|
|
240
|
+
## 7) CI Integration: Review + Act
|
|
241
|
+
|
|
242
|
+
This repo includes a workflow that:
|
|
243
|
+
- Runs autonomous code review on PRs ("Review" job).
|
|
244
|
+
- Listens for `/codex ...` comments and performs autonomous edits ("Act" job), optionally running your tests.
|
|
245
|
+
|
|
246
|
+
Both jobs use `gersmann/codex-review-action@v1`.
|
|
247
|
+
|
|
248
|
+
### Minimal Review Job
|
|
249
|
+
|
|
250
|
+
```yaml
|
|
251
|
+
name: Codex Review
|
|
252
|
+
on:
|
|
253
|
+
pull_request:
|
|
254
|
+
types: [opened, synchronize, ready_for_review]
|
|
255
|
+
jobs:
|
|
256
|
+
review:
|
|
257
|
+
name: Review
|
|
258
|
+
permissions:
|
|
259
|
+
contents: read
|
|
260
|
+
pull-requests: write
|
|
261
|
+
issues: read
|
|
262
|
+
env:
|
|
263
|
+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
264
|
+
runs-on: ubuntu-latest
|
|
265
|
+
steps:
|
|
266
|
+
- uses: actions/checkout@v4
|
|
267
|
+
with:
|
|
268
|
+
fetch-depth: 0
|
|
269
|
+
- name: Codex autonomous review
|
|
270
|
+
if: env.OPENAI_API_KEY != ''
|
|
271
|
+
uses: gersmann/codex-review-action@v1
|
|
272
|
+
with:
|
|
273
|
+
mode: review
|
|
274
|
+
openai_api_key: ${{ secrets.OPENAI_API_KEY }}
|
|
275
|
+
model: gpt-5
|
|
276
|
+
reasoning_effort: medium
|
|
277
|
+
debug_level: 1
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Act on `/codex` Comments
|
|
281
|
+
|
|
282
|
+
```yaml
|
|
283
|
+
act:
|
|
284
|
+
name: Act on /codex comments
|
|
285
|
+
if: >-
|
|
286
|
+
(
|
|
287
|
+
github.event_name == 'issue_comment' &&
|
|
288
|
+
startsWith(github.event.comment.body, '/codex') &&
|
|
289
|
+
github.event.issue.pull_request &&
|
|
290
|
+
contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association)
|
|
291
|
+
) || (
|
|
292
|
+
github.event_name == 'pull_request_review_comment' &&
|
|
293
|
+
startsWith(github.event.comment.body, '/codex') &&
|
|
294
|
+
contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association)
|
|
295
|
+
)
|
|
296
|
+
&& github.actor != 'dependabot[bot]'
|
|
297
|
+
concurrency:
|
|
298
|
+
group: codex-act-${{ github.event.issue.number || github.event.pull_request.number || github.ref }}
|
|
299
|
+
cancel-in-progress: false
|
|
300
|
+
permissions:
|
|
301
|
+
contents: write
|
|
302
|
+
issues: write
|
|
303
|
+
pull-requests: write
|
|
304
|
+
actions: write
|
|
305
|
+
runs-on: ubuntu-latest
|
|
306
|
+
env:
|
|
307
|
+
APP_ENV: test
|
|
308
|
+
CI: true
|
|
309
|
+
steps:
|
|
310
|
+
- uses: actions/checkout@v4
|
|
311
|
+
with:
|
|
312
|
+
fetch-depth: 0
|
|
313
|
+
ref: ${{ github.event.pull_request.head.sha || format('refs/pull/{0}/head', github.event.issue.number) }}
|
|
314
|
+
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
|
315
|
+
- name: Setup Environment
|
|
316
|
+
uses: ./.github/actions/setup
|
|
317
|
+
with:
|
|
318
|
+
python-version: '3.13'
|
|
319
|
+
node-version: '20'
|
|
320
|
+
- name: Codex autonomous edits
|
|
321
|
+
if: env.OPENAI_API_KEY != ''
|
|
322
|
+
uses: gersmann/codex-review-action@v1
|
|
323
|
+
with:
|
|
324
|
+
mode: act
|
|
325
|
+
openai_api_key: ${{ secrets.OPENAI_API_KEY }}
|
|
326
|
+
model: gpt-5
|
|
327
|
+
debug_level: 1
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Common `/codex` patterns
|
|
331
|
+
- `/codex` — propose and apply fixes
|
|
332
|
+
- `/codex focus <path>` — limit scope
|
|
333
|
+
- `/codex redo` — re‑run on latest PR head
|
|
334
|
+
|
|
335
|
+
Secrets
|
|
336
|
+
- `OPENAI_API_KEY` to call the model API
|
|
337
|
+
- `REPO_ACCESS_TOKEN` (write permission) so pushes from Act trigger CI
|
|
338
|
+
- Project‑specific secrets for tests (DB URLs, API keys), when services are enabled
|