codex-python 0.2.14__tar.gz → 0.2.15__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.15}/PKG-INFO +1 -1
- {codex_python-0.2.14 → codex_python-0.2.15}/codex/__init__.py +1 -1
- {codex_python-0.2.14 → codex_python-0.2.15}/crates/codex_native/Cargo.lock +8 -1
- {codex_python-0.2.14 → codex_python-0.2.15}/crates/codex_native/Cargo.toml +2 -1
- {codex_python-0.2.14 → codex_python-0.2.15}/crates/codex_native/src/lib.rs +48 -7
- {codex_python-0.2.14 → codex_python-0.2.15}/LICENSE +0 -0
- {codex_python-0.2.14 → codex_python-0.2.15}/README.md +0 -0
- {codex_python-0.2.14 → codex_python-0.2.15}/codex/api.py +0 -0
- {codex_python-0.2.14 → codex_python-0.2.15}/codex/config.py +0 -0
- {codex_python-0.2.14 → codex_python-0.2.15}/codex/event.py +0 -0
- {codex_python-0.2.14 → codex_python-0.2.15}/codex/native.py +0 -0
- {codex_python-0.2.14 → codex_python-0.2.15}/codex/protocol/_base_model.py +0 -0
- {codex_python-0.2.14 → codex_python-0.2.15}/codex/protocol/types.py +0 -0
- {codex_python-0.2.14 → codex_python-0.2.15}/codex/py.typed +0 -0
- {codex_python-0.2.14 → codex_python-0.2.15}/crates/codex_native/src/bin/protocol_schema.rs +0 -0
- {codex_python-0.2.14 → codex_python-0.2.15}/pyproject.toml +0 -0
|
@@ -422,12 +422,13 @@ dependencies = [
|
|
|
422
422
|
|
|
423
423
|
[[package]]
|
|
424
424
|
name = "codex_native"
|
|
425
|
-
version = "0.2.
|
|
425
|
+
version = "0.2.15"
|
|
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"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "codex_native"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.15"
|
|
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
|
|
@@ -1,7 +1,7 @@
|
|
|
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};
|
|
@@ -38,9 +38,14 @@ 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(
|
|
46
|
+
config.codex_home.clone(),
|
|
47
|
+
)),
|
|
48
|
+
};
|
|
44
49
|
let new_conv = conversation_manager.new_conversation(config).await?;
|
|
45
50
|
let conversation = new_conv.conversation.clone();
|
|
46
51
|
|
|
@@ -173,6 +178,10 @@ fn build_config(
|
|
|
173
178
|
overrides: Option<Bound<'_, PyDict>>,
|
|
174
179
|
load_default_config: bool,
|
|
175
180
|
) -> Result<Config> {
|
|
181
|
+
// Match CLI behavior: import env vars from ~/.codex/.env (if present)
|
|
182
|
+
// before reading config/auth so OPENAI_API_KEY and friends are visible.
|
|
183
|
+
// Security: filter out CODEX_* variables just like the CLI does.
|
|
184
|
+
load_dotenv();
|
|
176
185
|
let mut overrides_struct = ConfigOverrides::default();
|
|
177
186
|
let mut cli_overrides: Vec<(String, TomlValue)> = Vec::new();
|
|
178
187
|
|
|
@@ -291,6 +300,33 @@ fn build_config(
|
|
|
291
300
|
}
|
|
292
301
|
}
|
|
293
302
|
|
|
303
|
+
const ILLEGAL_ENV_VAR_PREFIX: &str = "CODEX_";
|
|
304
|
+
|
|
305
|
+
/// Load env vars from ~/.codex/.env, filtering out any keys that start with
|
|
306
|
+
/// CODEX_ (reserved for internal use). This mirrors the behavior in the
|
|
307
|
+
/// `codex-arg0` crate used by the CLI so python users get the same DX.
|
|
308
|
+
fn load_dotenv() {
|
|
309
|
+
if let Ok(codex_home) = find_codex_home() {
|
|
310
|
+
let env_path = codex_home.join(".env");
|
|
311
|
+
if let Ok(iter) = dotenvy::from_path_iter(env_path) {
|
|
312
|
+
set_filtered(iter);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/// Helper to set vars from a dotenvy iterator while filtering out `CODEX_` keys.
|
|
318
|
+
fn set_filtered<I>(iter: I)
|
|
319
|
+
where
|
|
320
|
+
I: IntoIterator<Item = Result<(String, String), dotenvy::Error>>,
|
|
321
|
+
{
|
|
322
|
+
for (key, value) in iter.into_iter().flatten() {
|
|
323
|
+
if !key.to_ascii_uppercase().starts_with(ILLEGAL_ENV_VAR_PREFIX) {
|
|
324
|
+
// Safe to modify env here – we do it up front before we spawn runtimes/threads.
|
|
325
|
+
unsafe { std::env::set_var(&key, &value) };
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
294
330
|
/// Convert a Python object into a TOML value. Returns Ok(None) for `None`.
|
|
295
331
|
fn py_to_toml_value(obj: Bound<'_, PyAny>) -> Result<Option<TomlValue>> {
|
|
296
332
|
use pyo3::types::{PyBool, PyDict, PyFloat, PyInt, PyList, PyString};
|
|
@@ -397,9 +433,14 @@ fn insert_parts(current: &mut TomlTable, parts: &[&str], val: TomlValue) {
|
|
|
397
433
|
fn run_exec_stream_impl(prompt: String, config: Config, tx: mpsc::Sender<JsonValue>) -> Result<()> {
|
|
398
434
|
let rt = tokio::runtime::Runtime::new()?;
|
|
399
435
|
rt.block_on(async move {
|
|
400
|
-
let conversation_manager =
|
|
401
|
-
|
|
402
|
-
|
|
436
|
+
let conversation_manager = match std::env::var("OPENAI_API_KEY") {
|
|
437
|
+
Ok(val) if !val.trim().is_empty() => {
|
|
438
|
+
ConversationManager::with_auth(CodexAuth::from_api_key(&val))
|
|
439
|
+
}
|
|
440
|
+
_ => ConversationManager::new(AuthManager::shared(
|
|
441
|
+
config.codex_home.clone(),
|
|
442
|
+
)),
|
|
443
|
+
};
|
|
403
444
|
let new_conv = conversation_manager.new_conversation(config).await?;
|
|
404
445
|
let conversation = new_conv.conversation.clone();
|
|
405
446
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|