codex-python 0.2.14__tar.gz → 0.2.16__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.2.14 → codex_python-0.2.16}/PKG-INFO +12 -1
- {codex_python-0.2.14 → codex_python-0.2.16}/README.md +11 -0
- {codex_python-0.2.14 → codex_python-0.2.16}/codex/__init__.py +1 -1
- {codex_python-0.2.14 → codex_python-0.2.16}/codex/api.py +16 -6
- {codex_python-0.2.14 → codex_python-0.2.16}/codex/config.py +2 -1
- {codex_python-0.2.14 → codex_python-0.2.16}/crates/codex_native/Cargo.lock +53 -45
- {codex_python-0.2.14 → codex_python-0.2.16}/crates/codex_native/Cargo.toml +2 -1
- {codex_python-0.2.14 → codex_python-0.2.16}/crates/codex_native/src/bin/protocol_schema.rs +10 -3
- {codex_python-0.2.14 → codex_python-0.2.16}/crates/codex_native/src/lib.rs +85 -29
- {codex_python-0.2.14 → codex_python-0.2.16}/pyproject.toml +6 -0
- {codex_python-0.2.14 → codex_python-0.2.16}/LICENSE +0 -0
- {codex_python-0.2.14 → codex_python-0.2.16}/codex/event.py +0 -0
- {codex_python-0.2.14 → codex_python-0.2.16}/codex/native.py +0 -0
- {codex_python-0.2.14 → codex_python-0.2.16}/codex/protocol/_base_model.py +0 -0
- {codex_python-0.2.14 → codex_python-0.2.16}/codex/protocol/types.py +0 -0
- {codex_python-0.2.14 → codex_python-0.2.16}/codex/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codex-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.16
|
|
4
4
|
Classifier: Programming Language :: Python :: 3
|
|
5
5
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
6
6
|
Classifier: Programming Language :: Python :: 3.13
|
|
@@ -128,3 +128,14 @@ Links
|
|
|
128
128
|
- uv: https://docs.astral.sh/uv/
|
|
129
129
|
- maturin: https://www.maturin.rs/
|
|
130
130
|
|
|
131
|
+
## GitHub Workflow: Autonomous Review
|
|
132
|
+
|
|
133
|
+
This repo includes a workflow that runs autonomous code review on pull requests and can
|
|
134
|
+
apply edits on demand via a slash command.
|
|
135
|
+
|
|
136
|
+
- Automatic review runs on PR open, synchronize, reopen, and when marked ready for review.
|
|
137
|
+
- To request autonomous edits on a PR, comment `/codex` in either a PR thread or a
|
|
138
|
+
review comment. The workflow listens for `/codex` and triggers the "act" job.
|
|
139
|
+
|
|
140
|
+
See `.github/workflows/codex-autoreview.yml` for configuration.
|
|
141
|
+
|
|
@@ -108,3 +108,14 @@ Links
|
|
|
108
108
|
- Codex repo: https://github.com/openai/codex
|
|
109
109
|
- uv: https://docs.astral.sh/uv/
|
|
110
110
|
- maturin: https://www.maturin.rs/
|
|
111
|
+
|
|
112
|
+
## GitHub Workflow: Autonomous Review
|
|
113
|
+
|
|
114
|
+
This repo includes a workflow that runs autonomous code review on pull requests and can
|
|
115
|
+
apply edits on demand via a slash command.
|
|
116
|
+
|
|
117
|
+
- Automatic review runs on PR open, synchronize, reopen, and when marked ready for review.
|
|
118
|
+
- To request autonomous edits on a PR, comment `/codex` in either a PR thread or a
|
|
119
|
+
review comment. The workflow listens for `/codex` and triggers the "act" job.
|
|
120
|
+
|
|
121
|
+
See `.github/workflows/codex-autoreview.yml` for configuration.
|
|
@@ -16,10 +16,13 @@ class CodexError(Exception):
|
|
|
16
16
|
class CodexNativeError(CodexError):
|
|
17
17
|
"""Raised when the native extension is not available or fails."""
|
|
18
18
|
|
|
19
|
-
def __init__(self) -> None:
|
|
19
|
+
def __init__(self, message: str | None = None) -> None:
|
|
20
20
|
super().__init__(
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
message
|
|
22
|
+
or (
|
|
23
|
+
"codex_native extension not installed or failed to run. "
|
|
24
|
+
"Run `make dev-native` or ensure native wheels are installed."
|
|
25
|
+
)
|
|
23
26
|
)
|
|
24
27
|
|
|
25
28
|
|
|
@@ -31,7 +34,14 @@ class Conversation:
|
|
|
31
34
|
|
|
32
35
|
def __iter__(self) -> Iterator[Event]:
|
|
33
36
|
"""Yield `Event` objects from the native stream."""
|
|
34
|
-
|
|
37
|
+
iterator = iter(self._stream)
|
|
38
|
+
while True:
|
|
39
|
+
try:
|
|
40
|
+
item = next(iterator)
|
|
41
|
+
except StopIteration:
|
|
42
|
+
return
|
|
43
|
+
except RuntimeError as exc: # surfaced from native iterator
|
|
44
|
+
raise CodexNativeError(str(exc)) from exc
|
|
35
45
|
try:
|
|
36
46
|
yield Event.model_validate(item)
|
|
37
47
|
except Exception:
|
|
@@ -76,7 +86,7 @@ class CodexClient:
|
|
|
76
86
|
)
|
|
77
87
|
return Conversation(_stream=stream)
|
|
78
88
|
except RuntimeError as e:
|
|
79
|
-
raise CodexNativeError() from e
|
|
89
|
+
raise CodexNativeError(str(e)) from e
|
|
80
90
|
|
|
81
91
|
|
|
82
92
|
def run_exec(
|
|
@@ -97,7 +107,7 @@ def run_exec(
|
|
|
97
107
|
load_default_config=load_default_config,
|
|
98
108
|
)
|
|
99
109
|
except RuntimeError as e:
|
|
100
|
-
raise CodexNativeError() from e
|
|
110
|
+
raise CodexNativeError(str(e)) from e
|
|
101
111
|
|
|
102
112
|
out: list[Event] = []
|
|
103
113
|
for item in events:
|
|
@@ -218,7 +218,8 @@ class CodexConfig(BaseModel):
|
|
|
218
218
|
project_doc_max_bytes: int | None = None
|
|
219
219
|
profile: str | None = None
|
|
220
220
|
profiles: dict[str, ProfileConfig] | None = None
|
|
221
|
-
|
|
221
|
+
# Accept either a structured ToolsConfig or a plain mapping (common in tests/CLI overrides)
|
|
222
|
+
tools: ToolsConfig | dict[str, Any] | None = None
|
|
222
223
|
projects: dict[str, ProjectConfig] | None = None
|
|
223
224
|
|
|
224
225
|
# Experimental / internal
|
|
@@ -311,7 +311,7 @@ checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
|
|
|
311
311
|
[[package]]
|
|
312
312
|
name = "codex-apply-patch"
|
|
313
313
|
version = "0.0.0"
|
|
314
|
-
source = "git+https://github.com/openai/codex?branch=main#
|
|
314
|
+
source = "git+https://github.com/openai/codex?branch=main#a8026d3846486e790827b26e9abf13e7f96e48bf"
|
|
315
315
|
dependencies = [
|
|
316
316
|
"anyhow",
|
|
317
317
|
"once_cell",
|
|
@@ -324,7 +324,7 @@ dependencies = [
|
|
|
324
324
|
[[package]]
|
|
325
325
|
name = "codex-core"
|
|
326
326
|
version = "0.0.0"
|
|
327
|
-
source = "git+https://github.com/openai/codex?branch=main#
|
|
327
|
+
source = "git+https://github.com/openai/codex?branch=main#a8026d3846486e790827b26e9abf13e7f96e48bf"
|
|
328
328
|
dependencies = [
|
|
329
329
|
"anyhow",
|
|
330
330
|
"askama",
|
|
@@ -374,7 +374,7 @@ dependencies = [
|
|
|
374
374
|
[[package]]
|
|
375
375
|
name = "codex-file-search"
|
|
376
376
|
version = "0.0.0"
|
|
377
|
-
source = "git+https://github.com/openai/codex?branch=main#
|
|
377
|
+
source = "git+https://github.com/openai/codex?branch=main#a8026d3846486e790827b26e9abf13e7f96e48bf"
|
|
378
378
|
dependencies = [
|
|
379
379
|
"anyhow",
|
|
380
380
|
"clap",
|
|
@@ -388,7 +388,7 @@ dependencies = [
|
|
|
388
388
|
[[package]]
|
|
389
389
|
name = "codex-mcp-client"
|
|
390
390
|
version = "0.0.0"
|
|
391
|
-
source = "git+https://github.com/openai/codex?branch=main#
|
|
391
|
+
source = "git+https://github.com/openai/codex?branch=main#a8026d3846486e790827b26e9abf13e7f96e48bf"
|
|
392
392
|
dependencies = [
|
|
393
393
|
"anyhow",
|
|
394
394
|
"mcp-types",
|
|
@@ -402,7 +402,7 @@ dependencies = [
|
|
|
402
402
|
[[package]]
|
|
403
403
|
name = "codex-protocol"
|
|
404
404
|
version = "0.0.0"
|
|
405
|
-
source = "git+https://github.com/openai/codex?branch=main#
|
|
405
|
+
source = "git+https://github.com/openai/codex?branch=main#a8026d3846486e790827b26e9abf13e7f96e48bf"
|
|
406
406
|
dependencies = [
|
|
407
407
|
"base64",
|
|
408
408
|
"icu_decimal",
|
|
@@ -422,12 +422,13 @@ dependencies = [
|
|
|
422
422
|
|
|
423
423
|
[[package]]
|
|
424
424
|
name = "codex_native"
|
|
425
|
-
version = "0.2.
|
|
425
|
+
version = "0.2.16"
|
|
426
426
|
dependencies = [
|
|
427
427
|
"anyhow",
|
|
428
428
|
"clap",
|
|
429
429
|
"codex-core",
|
|
430
430
|
"codex-protocol",
|
|
431
|
+
"dotenvy",
|
|
431
432
|
"openssl-sys",
|
|
432
433
|
"pathdiff",
|
|
433
434
|
"pyo3",
|
|
@@ -601,6 +602,12 @@ dependencies = [
|
|
|
601
602
|
"syn",
|
|
602
603
|
]
|
|
603
604
|
|
|
605
|
+
[[package]]
|
|
606
|
+
name = "dotenvy"
|
|
607
|
+
version = "0.15.7"
|
|
608
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
609
|
+
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
|
|
610
|
+
|
|
604
611
|
[[package]]
|
|
605
612
|
name = "downcast-rs"
|
|
606
613
|
version = "1.2.1"
|
|
@@ -885,7 +892,7 @@ dependencies = [
|
|
|
885
892
|
"cfg-if",
|
|
886
893
|
"libc",
|
|
887
894
|
"r-efi",
|
|
888
|
-
"wasi 0.14.
|
|
895
|
+
"wasi 0.14.7+wasi-0.2.4",
|
|
889
896
|
]
|
|
890
897
|
|
|
891
898
|
[[package]]
|
|
@@ -919,7 +926,7 @@ dependencies = [
|
|
|
919
926
|
"futures-core",
|
|
920
927
|
"futures-sink",
|
|
921
928
|
"http",
|
|
922
|
-
"indexmap 2.11.
|
|
929
|
+
"indexmap 2.11.3",
|
|
923
930
|
"slab",
|
|
924
931
|
"tokio",
|
|
925
932
|
"tokio-util",
|
|
@@ -1064,9 +1071,9 @@ dependencies = [
|
|
|
1064
1071
|
|
|
1065
1072
|
[[package]]
|
|
1066
1073
|
name = "hyper-util"
|
|
1067
|
-
version = "0.1.
|
|
1074
|
+
version = "0.1.17"
|
|
1068
1075
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1069
|
-
checksum = "
|
|
1076
|
+
checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8"
|
|
1070
1077
|
dependencies = [
|
|
1071
1078
|
"base64",
|
|
1072
1079
|
"bytes",
|
|
@@ -1299,13 +1306,14 @@ dependencies = [
|
|
|
1299
1306
|
|
|
1300
1307
|
[[package]]
|
|
1301
1308
|
name = "indexmap"
|
|
1302
|
-
version = "2.11.
|
|
1309
|
+
version = "2.11.3"
|
|
1303
1310
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1304
|
-
checksum = "
|
|
1311
|
+
checksum = "92119844f513ffa41556430369ab02c295a3578af21cf945caa3e9e0c2481ac3"
|
|
1305
1312
|
dependencies = [
|
|
1306
1313
|
"equivalent",
|
|
1307
1314
|
"hashbrown 0.15.5",
|
|
1308
1315
|
"serde",
|
|
1316
|
+
"serde_core",
|
|
1309
1317
|
]
|
|
1310
1318
|
|
|
1311
1319
|
[[package]]
|
|
@@ -1448,7 +1456,7 @@ dependencies = [
|
|
|
1448
1456
|
[[package]]
|
|
1449
1457
|
name = "mcp-types"
|
|
1450
1458
|
version = "0.0.0"
|
|
1451
|
-
source = "git+https://github.com/openai/codex?branch=main#
|
|
1459
|
+
source = "git+https://github.com/openai/codex?branch=main#a8026d3846486e790827b26e9abf13e7f96e48bf"
|
|
1452
1460
|
dependencies = [
|
|
1453
1461
|
"serde",
|
|
1454
1462
|
"serde_json",
|
|
@@ -1748,12 +1756,12 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
|
|
1748
1756
|
|
|
1749
1757
|
[[package]]
|
|
1750
1758
|
name = "plist"
|
|
1751
|
-
version = "1.
|
|
1759
|
+
version = "1.8.0"
|
|
1752
1760
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1753
|
-
checksum = "
|
|
1761
|
+
checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07"
|
|
1754
1762
|
dependencies = [
|
|
1755
1763
|
"base64",
|
|
1756
|
-
"indexmap 2.11.
|
|
1764
|
+
"indexmap 2.11.3",
|
|
1757
1765
|
"quick-xml",
|
|
1758
1766
|
"serde",
|
|
1759
1767
|
"time",
|
|
@@ -2122,9 +2130,9 @@ dependencies = [
|
|
|
2122
2130
|
|
|
2123
2131
|
[[package]]
|
|
2124
2132
|
name = "rustls-webpki"
|
|
2125
|
-
version = "0.103.
|
|
2133
|
+
version = "0.103.6"
|
|
2126
2134
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2127
|
-
checksum = "
|
|
2135
|
+
checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb"
|
|
2128
2136
|
dependencies = [
|
|
2129
2137
|
"ring",
|
|
2130
2138
|
"rustls-pki-types",
|
|
@@ -2225,9 +2233,9 @@ dependencies = [
|
|
|
2225
2233
|
|
|
2226
2234
|
[[package]]
|
|
2227
2235
|
name = "serde"
|
|
2228
|
-
version = "1.0.
|
|
2236
|
+
version = "1.0.225"
|
|
2229
2237
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2230
|
-
checksum = "
|
|
2238
|
+
checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d"
|
|
2231
2239
|
dependencies = [
|
|
2232
2240
|
"serde_core",
|
|
2233
2241
|
"serde_derive",
|
|
@@ -2235,18 +2243,18 @@ dependencies = [
|
|
|
2235
2243
|
|
|
2236
2244
|
[[package]]
|
|
2237
2245
|
name = "serde_core"
|
|
2238
|
-
version = "1.0.
|
|
2246
|
+
version = "1.0.225"
|
|
2239
2247
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2240
|
-
checksum = "
|
|
2248
|
+
checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383"
|
|
2241
2249
|
dependencies = [
|
|
2242
2250
|
"serde_derive",
|
|
2243
2251
|
]
|
|
2244
2252
|
|
|
2245
2253
|
[[package]]
|
|
2246
2254
|
name = "serde_derive"
|
|
2247
|
-
version = "1.0.
|
|
2255
|
+
version = "1.0.225"
|
|
2248
2256
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2249
|
-
checksum = "
|
|
2257
|
+
checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516"
|
|
2250
2258
|
dependencies = [
|
|
2251
2259
|
"proc-macro2",
|
|
2252
2260
|
"quote",
|
|
@@ -2259,7 +2267,7 @@ version = "1.0.145"
|
|
|
2259
2267
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2260
2268
|
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
|
|
2261
2269
|
dependencies = [
|
|
2262
|
-
"indexmap 2.11.
|
|
2270
|
+
"indexmap 2.11.3",
|
|
2263
2271
|
"itoa",
|
|
2264
2272
|
"memchr",
|
|
2265
2273
|
"ryu",
|
|
@@ -2269,11 +2277,11 @@ dependencies = [
|
|
|
2269
2277
|
|
|
2270
2278
|
[[package]]
|
|
2271
2279
|
name = "serde_spanned"
|
|
2272
|
-
version = "1.0.
|
|
2280
|
+
version = "1.0.1"
|
|
2273
2281
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2274
|
-
checksum = "
|
|
2282
|
+
checksum = "2789234a13a53fc4be1b51ea1bab45a3c338bdb884862a257d10e5a74ae009e6"
|
|
2275
2283
|
dependencies = [
|
|
2276
|
-
"
|
|
2284
|
+
"serde_core",
|
|
2277
2285
|
]
|
|
2278
2286
|
|
|
2279
2287
|
[[package]]
|
|
@@ -2298,7 +2306,7 @@ dependencies = [
|
|
|
2298
2306
|
"chrono",
|
|
2299
2307
|
"hex",
|
|
2300
2308
|
"indexmap 1.9.3",
|
|
2301
|
-
"indexmap 2.11.
|
|
2309
|
+
"indexmap 2.11.3",
|
|
2302
2310
|
"schemars 0.9.0",
|
|
2303
2311
|
"schemars 1.0.4",
|
|
2304
2312
|
"serde",
|
|
@@ -2698,12 +2706,12 @@ dependencies = [
|
|
|
2698
2706
|
|
|
2699
2707
|
[[package]]
|
|
2700
2708
|
name = "toml"
|
|
2701
|
-
version = "0.9.
|
|
2709
|
+
version = "0.9.6"
|
|
2702
2710
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2703
|
-
checksum = "
|
|
2711
|
+
checksum = "ae2a4cf385da23d1d53bc15cdfa5c2109e93d8d362393c801e87da2f72f0e201"
|
|
2704
2712
|
dependencies = [
|
|
2705
|
-
"indexmap 2.11.
|
|
2706
|
-
"
|
|
2713
|
+
"indexmap 2.11.3",
|
|
2714
|
+
"serde_core",
|
|
2707
2715
|
"serde_spanned",
|
|
2708
2716
|
"toml_datetime",
|
|
2709
2717
|
"toml_parser",
|
|
@@ -2713,20 +2721,20 @@ dependencies = [
|
|
|
2713
2721
|
|
|
2714
2722
|
[[package]]
|
|
2715
2723
|
name = "toml_datetime"
|
|
2716
|
-
version = "0.7.
|
|
2724
|
+
version = "0.7.1"
|
|
2717
2725
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2718
|
-
checksum = "
|
|
2726
|
+
checksum = "a197c0ec7d131bfc6f7e82c8442ba1595aeab35da7adbf05b6b73cd06a16b6be"
|
|
2719
2727
|
dependencies = [
|
|
2720
|
-
"
|
|
2728
|
+
"serde_core",
|
|
2721
2729
|
]
|
|
2722
2730
|
|
|
2723
2731
|
[[package]]
|
|
2724
2732
|
name = "toml_edit"
|
|
2725
|
-
version = "0.23.
|
|
2733
|
+
version = "0.23.5"
|
|
2726
2734
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2727
|
-
checksum = "
|
|
2735
|
+
checksum = "c2ad0b7ae9cfeef5605163839cb9221f453399f15cfb5c10be9885fcf56611f9"
|
|
2728
2736
|
dependencies = [
|
|
2729
|
-
"indexmap 2.11.
|
|
2737
|
+
"indexmap 2.11.3",
|
|
2730
2738
|
"toml_datetime",
|
|
2731
2739
|
"toml_parser",
|
|
2732
2740
|
"toml_writer",
|
|
@@ -3032,18 +3040,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
|
|
3032
3040
|
|
|
3033
3041
|
[[package]]
|
|
3034
3042
|
name = "wasi"
|
|
3035
|
-
version = "0.14.
|
|
3043
|
+
version = "0.14.7+wasi-0.2.4"
|
|
3036
3044
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3037
|
-
checksum = "
|
|
3045
|
+
checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
|
|
3038
3046
|
dependencies = [
|
|
3039
3047
|
"wasip2",
|
|
3040
3048
|
]
|
|
3041
3049
|
|
|
3042
3050
|
[[package]]
|
|
3043
3051
|
name = "wasip2"
|
|
3044
|
-
version = "1.0.
|
|
3052
|
+
version = "1.0.1+wasi-0.2.4"
|
|
3045
3053
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3046
|
-
checksum = "
|
|
3054
|
+
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
|
3047
3055
|
dependencies = [
|
|
3048
3056
|
"wit-bindgen",
|
|
3049
3057
|
]
|
|
@@ -3477,9 +3485,9 @@ checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
|
|
|
3477
3485
|
|
|
3478
3486
|
[[package]]
|
|
3479
3487
|
name = "wit-bindgen"
|
|
3480
|
-
version = "0.
|
|
3488
|
+
version = "0.46.0"
|
|
3481
3489
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3482
|
-
checksum = "
|
|
3490
|
+
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
|
3483
3491
|
|
|
3484
3492
|
[[package]]
|
|
3485
3493
|
name = "writeable"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "codex_native"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.16"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
|
|
6
6
|
[lib]
|
|
@@ -22,6 +22,7 @@ tracing = "0.1"
|
|
|
22
22
|
clap = { version = "4", features = ["derive"] }
|
|
23
23
|
which = "6"
|
|
24
24
|
pathdiff = "0.2"
|
|
25
|
+
dotenvy = "0.15.7"
|
|
25
26
|
|
|
26
27
|
# Upstream Codex crates from the monorepo (use git deps; pin to main for now)
|
|
27
28
|
# Pin to a specific commit of the upstream Codex monorepo to avoid breaking API changes
|
|
@@ -15,7 +15,11 @@ struct Args {
|
|
|
15
15
|
ts_out: PathBuf,
|
|
16
16
|
|
|
17
17
|
/// Output directory for the generated JSON Schema (.generated/schema by default)
|
|
18
|
-
#[arg(
|
|
18
|
+
#[arg(
|
|
19
|
+
long = "schema-out",
|
|
20
|
+
value_name = "DIR",
|
|
21
|
+
default_value = ".generated/schema"
|
|
22
|
+
)]
|
|
19
23
|
schema_out: PathBuf,
|
|
20
24
|
|
|
21
25
|
/// Optional path to the Prettier binary to format emitted TS (forwarded to upstream generator)
|
|
@@ -63,9 +67,12 @@ fn ensure_ts_generated(ts_out: &Path, prettier: Option<&Path>) -> Result<()> {
|
|
|
63
67
|
.arg(relative_path_from(&monorepo, ts_out)?)
|
|
64
68
|
.current_dir(&monorepo);
|
|
65
69
|
if let Some(bin) = prettier {
|
|
66
|
-
cmd.arg("--prettier")
|
|
70
|
+
cmd.arg("--prettier")
|
|
71
|
+
.arg(relative_path_from(&monorepo, bin)?);
|
|
67
72
|
}
|
|
68
|
-
let status = cmd
|
|
73
|
+
let status = cmd
|
|
74
|
+
.status()
|
|
75
|
+
.context("Failed to run codex-protocol-ts generator")?;
|
|
69
76
|
if status.success() {
|
|
70
77
|
return Ok(());
|
|
71
78
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
use anyhow::{Context, Result};
|
|
2
2
|
use codex_core::config::{find_codex_home, Config, ConfigOverrides, ConfigToml};
|
|
3
3
|
use codex_core::protocol::{EventMsg, InputItem};
|
|
4
|
-
use codex_core::{AuthManager, ConversationManager};
|
|
4
|
+
use codex_core::{AuthManager, CodexAuth, ConversationManager};
|
|
5
5
|
// use of SandboxMode is handled within core::config; not needed here
|
|
6
6
|
use pyo3::prelude::*;
|
|
7
7
|
use pyo3::types::{PyDict, PyFloat, PyList, PyModule, PyString};
|
|
8
8
|
use serde_json::Value as JsonValue;
|
|
9
|
-
use toml::value::Value as TomlValue;
|
|
10
|
-
use toml::value::Table as TomlTable;
|
|
11
9
|
use std::path::PathBuf;
|
|
12
10
|
use std::sync::{mpsc, Arc, Mutex};
|
|
13
11
|
use std::thread;
|
|
12
|
+
use toml::value::Table as TomlTable;
|
|
13
|
+
use toml::value::Value as TomlValue;
|
|
14
14
|
|
|
15
15
|
#[pyfunction]
|
|
16
16
|
fn run_exec_collect(
|
|
@@ -38,9 +38,12 @@ fn run_exec_collect(
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
async fn run_exec_impl(prompt: String, config: Config) -> Result<Vec<JsonValue>> {
|
|
41
|
-
let conversation_manager =
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
let conversation_manager = match std::env::var("OPENAI_API_KEY") {
|
|
42
|
+
Ok(val) if !val.trim().is_empty() => {
|
|
43
|
+
ConversationManager::with_auth(CodexAuth::from_api_key(&val))
|
|
44
|
+
}
|
|
45
|
+
_ => ConversationManager::new(AuthManager::shared(config.codex_home.clone())),
|
|
46
|
+
};
|
|
44
47
|
let new_conv = conversation_manager.new_conversation(config).await?;
|
|
45
48
|
let conversation = new_conv.conversation.clone();
|
|
46
49
|
|
|
@@ -61,13 +64,15 @@ async fn run_exec_impl(prompt: String, config: Config) -> Result<Vec<JsonValue>>
|
|
|
61
64
|
out.push(serde_json::to_value(&ev)?);
|
|
62
65
|
if is_complete {
|
|
63
66
|
// Ask the agent to shutdown; collect remaining events
|
|
64
|
-
let _ = conversation
|
|
67
|
+
let _ = conversation
|
|
68
|
+
.submit(codex_core::protocol::Op::Shutdown)
|
|
69
|
+
.await;
|
|
65
70
|
}
|
|
66
71
|
if is_shutdown {
|
|
67
72
|
break;
|
|
68
73
|
}
|
|
69
74
|
}
|
|
70
|
-
Err(
|
|
75
|
+
Err(err) => return Err(err.into()),
|
|
71
76
|
}
|
|
72
77
|
}
|
|
73
78
|
Ok(out)
|
|
@@ -79,7 +84,7 @@ fn to_py<E: std::fmt::Display>(e: E) -> PyErr {
|
|
|
79
84
|
|
|
80
85
|
#[pyclass]
|
|
81
86
|
struct CodexEventStream {
|
|
82
|
-
rx: Arc<Mutex<mpsc::Receiver<JsonValue
|
|
87
|
+
rx: Arc<Mutex<mpsc::Receiver<Result<JsonValue, String>>>>,
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
#[pymethods]
|
|
@@ -88,12 +93,13 @@ impl CodexEventStream {
|
|
|
88
93
|
slf
|
|
89
94
|
}
|
|
90
95
|
|
|
91
|
-
fn __next__(&mut self, py: Python<'_>) -> Option<Py<PyAny
|
|
96
|
+
fn __next__(&mut self, py: Python<'_>) -> PyResult<Option<Py<PyAny>>> {
|
|
92
97
|
// Run the blocking recv without holding the GIL
|
|
93
|
-
let res = py.detach(|| self.rx.lock().ok()
|
|
98
|
+
let res = py.detach(|| self.rx.lock().ok().and_then(|rx| rx.recv().ok()));
|
|
94
99
|
match res {
|
|
95
|
-
Some(v) => json_to_py(py, &v)
|
|
96
|
-
|
|
100
|
+
Some(Ok(v)) => Ok(Some(json_to_py(py, &v)?)),
|
|
101
|
+
Some(Err(msg)) => Err(pyo3::exceptions::PyRuntimeError::new_err(msg)),
|
|
102
|
+
None => Ok(None),
|
|
97
103
|
}
|
|
98
104
|
}
|
|
99
105
|
}
|
|
@@ -104,15 +110,18 @@ fn start_exec_stream(
|
|
|
104
110
|
config_overrides: Option<Bound<'_, PyDict>>,
|
|
105
111
|
load_default_config: bool,
|
|
106
112
|
) -> PyResult<CodexEventStream> {
|
|
107
|
-
let (tx, rx) = mpsc::channel::<JsonValue
|
|
113
|
+
let (tx, rx) = mpsc::channel::<Result<JsonValue, String>>();
|
|
108
114
|
|
|
109
115
|
// Build a pure-Rust Config on the Python thread
|
|
110
116
|
let config = build_config(config_overrides, load_default_config).map_err(to_py)?;
|
|
111
117
|
let prompt_clone = prompt.clone();
|
|
112
118
|
|
|
113
119
|
thread::spawn(move || {
|
|
114
|
-
|
|
115
|
-
|
|
120
|
+
let tx_for_impl = tx.clone();
|
|
121
|
+
if let Err(e) = run_exec_stream_impl(prompt_clone, config, tx_for_impl) {
|
|
122
|
+
let msg = e.to_string();
|
|
123
|
+
let _ = tx.send(Err(msg.clone()));
|
|
124
|
+
eprintln!("codex_native stream error: {msg}");
|
|
116
125
|
}
|
|
117
126
|
});
|
|
118
127
|
Ok(CodexEventStream {
|
|
@@ -169,10 +178,11 @@ fn json_to_py(py: Python<'_>, v: &JsonValue) -> PyResult<Py<PyAny>> {
|
|
|
169
178
|
Ok(obj)
|
|
170
179
|
}
|
|
171
180
|
|
|
172
|
-
fn build_config(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
181
|
+
fn build_config(overrides: Option<Bound<'_, PyDict>>, load_default_config: bool) -> Result<Config> {
|
|
182
|
+
// Match CLI behavior: import env vars from ~/.codex/.env (if present)
|
|
183
|
+
// before reading config/auth so OPENAI_API_KEY and friends are visible.
|
|
184
|
+
// Security: filter out CODEX_* variables just like the CLI does.
|
|
185
|
+
load_dotenv();
|
|
176
186
|
let mut overrides_struct = ConfigOverrides::default();
|
|
177
187
|
let mut cli_overrides: Vec<(String, TomlValue)> = Vec::new();
|
|
178
188
|
|
|
@@ -272,7 +282,10 @@ fn build_config(
|
|
|
272
282
|
|
|
273
283
|
if load_default_config {
|
|
274
284
|
// Start from built-in defaults and apply CLI + typed overrides.
|
|
275
|
-
Ok(Config::load_with_cli_overrides(
|
|
285
|
+
Ok(Config::load_with_cli_overrides(
|
|
286
|
+
cli_overrides,
|
|
287
|
+
overrides_struct,
|
|
288
|
+
)?)
|
|
276
289
|
} else {
|
|
277
290
|
// Do NOT read any on-disk config. Build a TOML value purely from CLI-style overrides
|
|
278
291
|
// and then apply the strongly-typed overrides on top. We still resolve CODEX_HOME to
|
|
@@ -287,7 +300,38 @@ fn build_config(
|
|
|
287
300
|
|
|
288
301
|
let root_value = TomlValue::Table(base_tbl);
|
|
289
302
|
let cfg: ConfigToml = root_value.try_into().map_err(|e| anyhow::anyhow!(e))?;
|
|
290
|
-
Ok(Config::load_from_base_config_with_overrides(
|
|
303
|
+
Ok(Config::load_from_base_config_with_overrides(
|
|
304
|
+
cfg,
|
|
305
|
+
overrides_struct,
|
|
306
|
+
codex_home,
|
|
307
|
+
)?)
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const ILLEGAL_ENV_VAR_PREFIX: &str = "CODEX_";
|
|
312
|
+
|
|
313
|
+
/// Load env vars from ~/.codex/.env, filtering out any keys that start with
|
|
314
|
+
/// CODEX_ (reserved for internal use). This mirrors the behavior in the
|
|
315
|
+
/// `codex-arg0` crate used by the CLI so python users get the same DX.
|
|
316
|
+
fn load_dotenv() {
|
|
317
|
+
if let Ok(codex_home) = find_codex_home() {
|
|
318
|
+
let env_path = codex_home.join(".env");
|
|
319
|
+
if let Ok(iter) = dotenvy::from_path_iter(env_path) {
|
|
320
|
+
set_filtered(iter);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/// Helper to set vars from a dotenvy iterator while filtering out `CODEX_` keys.
|
|
326
|
+
fn set_filtered<I>(iter: I)
|
|
327
|
+
where
|
|
328
|
+
I: IntoIterator<Item = Result<(String, String), dotenvy::Error>>,
|
|
329
|
+
{
|
|
330
|
+
for (key, value) in iter.into_iter().flatten() {
|
|
331
|
+
if !key.to_ascii_uppercase().starts_with(ILLEGAL_ENV_VAR_PREFIX) {
|
|
332
|
+
// Safe to modify env here – we do it up front before we spawn runtimes/threads.
|
|
333
|
+
unsafe { std::env::set_var(&key, &value) };
|
|
334
|
+
}
|
|
291
335
|
}
|
|
292
336
|
}
|
|
293
337
|
|
|
@@ -394,12 +438,19 @@ fn insert_parts(current: &mut TomlTable, parts: &[&str], val: TomlValue) {
|
|
|
394
438
|
}
|
|
395
439
|
}
|
|
396
440
|
|
|
397
|
-
fn run_exec_stream_impl(
|
|
441
|
+
fn run_exec_stream_impl(
|
|
442
|
+
prompt: String,
|
|
443
|
+
config: Config,
|
|
444
|
+
tx: mpsc::Sender<Result<JsonValue, String>>,
|
|
445
|
+
) -> Result<()> {
|
|
398
446
|
let rt = tokio::runtime::Runtime::new()?;
|
|
399
447
|
rt.block_on(async move {
|
|
400
|
-
let conversation_manager =
|
|
401
|
-
|
|
402
|
-
|
|
448
|
+
let conversation_manager = match std::env::var("OPENAI_API_KEY") {
|
|
449
|
+
Ok(val) if !val.trim().is_empty() => {
|
|
450
|
+
ConversationManager::with_auth(CodexAuth::from_api_key(&val))
|
|
451
|
+
}
|
|
452
|
+
_ => ConversationManager::new(AuthManager::shared(config.codex_home.clone())),
|
|
453
|
+
};
|
|
403
454
|
let new_conv = conversation_manager.new_conversation(config).await?;
|
|
404
455
|
let conversation = new_conv.conversation.clone();
|
|
405
456
|
|
|
@@ -415,15 +466,20 @@ fn run_exec_stream_impl(prompt: String, config: Config, tx: mpsc::Sender<JsonVal
|
|
|
415
466
|
Ok(ev) => {
|
|
416
467
|
let is_shutdown = matches!(ev.msg, EventMsg::ShutdownComplete);
|
|
417
468
|
let is_complete = matches!(ev.msg, EventMsg::TaskComplete(_));
|
|
418
|
-
let
|
|
469
|
+
let event_json = serde_json::to_value(&ev)?;
|
|
470
|
+
if tx.send(Ok(event_json)).is_err() {
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
419
473
|
if is_complete {
|
|
420
|
-
let _ = conversation
|
|
474
|
+
let _ = conversation
|
|
475
|
+
.submit(codex_core::protocol::Op::Shutdown)
|
|
476
|
+
.await;
|
|
421
477
|
}
|
|
422
478
|
if is_shutdown {
|
|
423
479
|
break;
|
|
424
480
|
}
|
|
425
481
|
}
|
|
426
|
-
Err(
|
|
482
|
+
Err(err) => return Err(err.into()),
|
|
427
483
|
}
|
|
428
484
|
}
|
|
429
485
|
Ok::<(), anyhow::Error>(())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|