mirror of
https://github.com/openai/codex.git
synced 2026-04-28 18:32:04 +03:00
3.6 KiB
3.6 KiB
DOs
-
Bold the keyword, then colon + concise description.
-
Merge related points when possible; avoid a bullet for every trivial detail.
-
Keep bullets to one line unless breaking for clarity is unavoidable.
-
Bold the keyword, then colon + concise description.
-
Isolate config editing: Move config-toml mutation into a dedicated
config_edit.rsmodule and re-export minimal APIs.
// lib.rs
pub mod config_edit;
// config.rs
pub use crate::config_edit::set_default_model_and_effort_for_profile;
- Use idiomatic Option chaining: Compute the effective profile with concise, readable combinators.
let effective_profile = profile
.as_deref()
.or_else(|| {
load_config_as_toml(codex_home)
.ok()
.and_then(|v| v.get("profile").and_then(|i| i.as_str()))
})
.map(ToString::to_string);
- Edit TOML by segments: Address nested keys via explicit path segments so dots/spaces in names are handled safely.
let segments = ["profiles", "my.team name", "model"];
apply_toml_edit_override_segments(&mut doc, &segments, toml_edit::value("o3"));
- Preserve formatting/comments: When creating tables, mark them implicit to avoid gratuitous formatting changes.
current[*seg] = toml_edit::Item::Table(toml_edit::Table::new());
if let Some(t) = current[*seg].as_table_mut() {
t.set_implicit(true);
}
- Test full file output: Assert against the entire resulting
config.tomlso table structure and comments are verified.
let contents = std::fs::read_to_string(codex_home.join(CONFIG_TOML_FILE))?;
let expected = r#"profile = "o3"
[profiles.o3]
model = "o3"
model_reasoning_effort = "high"
"#;
assert_eq!(contents, expected);
- Use string fixtures: Seed input TOML and expected TOML as strings to make intent explicit and reviewable.
let seed = r#"# Global comment
profile = "o3"
[profiles.o3]
existing = "keep"
"#;
std::fs::write(config_path, seed)?;
let expected = r#"# Global comment
profile = "o3"
[profiles.o3]
existing = "keep"
model = "o3"
model_reasoning_effort = "high"
"#;
// ... write via API, then:
assert_eq!(std::fs::read_to_string(config_path)?, expected);
- Offer focused APIs: Provide both top-level and profile-scoped helpers for clarity and reuse.
set_default_model_and_effort(codex_home, "gpt-5", ReasoningEffort::Minimal)?;
set_default_model_and_effort_for_profile(codex_home, Some("o3"), "o3", ReasoningEffort::High)?;
DON’Ts
- Don’t bloat
config.rs: Avoid embedding large edit routines directly inconfig.rs; keep it thin.
// Bad (monolithic in config.rs):
fn set_default_model_and_effort(...) {
// hundreds of lines of edit logic here
}
- Don’t build dotted key strings: Dotted keys break when names contain dots/spaces; use segments instead.
// Bad:
doc["profiles.my.team name"]["model"] = toml_edit::value("o3");
- Don’t drop comments/formatting: Avoid serializing from structs that rewrite the whole file and lose trivia.
// Bad:
let s = toml::to_string(&my_struct)?; // loses comments/order
std::fs::write(config_path, s)?;
- Don’t assert partial changes: Contains/regex checks miss structural and formatting regressions.
// Bad:
assert!(contents.contains("model = \"o3\"")); // ignores tables/comments
- Don’t paper over parse errors: If the TOML can’t be parsed, surface the error and don’t clobber the file.
// Bad:
let doc = std::fs::read_to_string(config_path)
.ok()
.and_then(|s| s.parse::<toml_edit::DocumentMut>().ok())
.unwrap_or_default(); // silently discards invalid file