Konfigurationssystem
Die Konfiguration (config) von codex ist kein einzelnes Datei-Laden, sondern eine mehrlagige Schichtung: config.toml aus mehreren Quellen — system / user / project / cloud bundle / session flags — wird nach precedence zur effective config zusammengeführt und zusätzlich mit ConfigRequirements gegen Einschränkungen geprüft. Der config-Crate übernimmt Schichtung und Merge; codex-home liefert CODEX_HOME-Auflösung und Laden des globalen AGENTS.md; core/src/config/mod.rs packt das Merge-Ergebnis in ein Config für die Agent-Hauptschleife; core/src/config_lock.rs garantiert mit einem Lockfile reproduzierbare Ausführung. cli/src/login.rs schreibt auth.json; der Login-Zustand ist ebenfalls Teil der Konfigurationsschicht.
Verantwortlichkeiten
- codex home lokalisieren:
find_codex_homeliestCODEX_HOME; ist es nicht gesetzt, fällt es auf~/.codexzurück (codex-rs/core/src/config/mod.rs:4440-4442). - Mehrlagiges Laden:
load_config_layers_statelädt der Reihe nach system / managed / cloud bundle / user / project / session flags und liefert einenConfigLayerStack(codex-rs/config/src/loader/mod.rs:116-168). - Merge zur effective config:
ConfigLayerStack::effective_configmergt TOML von niedriger zu hoher precedence (codex-rs/config/src/state.rs:483-492). - Runtime-
Configaufbauen:ConfigBuildersetzt codex_home, cli_overrides, harness_overrides und cloud bundle zusammen und ruftbuild().awaitauf (codex-rs/core/src/config/mod.rs:1258-1297). - Login-Zustand schreiben:
login_with_chatgpt/run_login_with_api_keylaufen den Login-Prozess und schreiben Credentials nachauth.json(codex-rs/cli/src/login.rs:137-165).
Entwurfsbeweggründe
Ein einzelnes config.toml ist einfach, aber Unternehmensauslieferung verlangt mehrlagige Schichtung: Eine MDM-pushed erzwungene Policy darf nicht vom Nutzer geändert werden; ein projektweites .codex/config.toml muss das nutzerweite überschreiben; CLI-Flags müssen wiederum Projektkonfiguration übersteuern. codex abstrahiert jede Lage als ConfigLayerEntry; ConfigLayerSource::precedence liefert eine Zahl, die die Merge-Reihenfolge bestimmt — Session flags (30) über Project (25) über User (20) über System (10) über MDM (0). Eine neue Quelle ist nur eine enum-Variante plus Zahl, ohne Änderung der Merge-Logik. cloud bundle ist eine später hinzugekommene Schicht, die vom ChatGPT-Backend enterprise-managed config und requirements zieht und in load_config_layers_state über CloudConfigBundleLayers::from_bundle in eine normale Layer umgewandelt und in den Stack gesteckt wird; sie geht denselben Merge-Pfad wie lokales TOML. config_lock.rs sorgt für Reproduzierbarkeit: Das gemergete ConfigToml plus codex-Version werden als ConfigLockfileToml serialisiert; beim Replay vergleicht validate_config_lock_replay erwartet vs tatsächlich und bricht bei Versions- oder Feldabweichung ab, damit derselbe Prompt auf verschiedenen Maschinen nicht zu unterschiedlichen Ergebnissen führt.
Wichtige Dateien
codex-rs/config/src/config_layer_source.rs:6-49 — ConfigLayerSource-Enum und precedence(); definiert 8 Quellen und Merge-Reihenfolge.codex-rs/config/src/loader/mod.rs:116-168 — load_config_layers_state; lädt system / managed / cloud bundle / user / project in den Stack.codex-rs/config/src/state.rs:483-492 — effective_config; mergt von niedriger zu hoher precedence via merge_toml_values.codex-rs/core/src/config/mod.rs:614-673 — Config-Struktur; das „endgültige Konfigurations"-Objekt zur Laufzeit, mit model_provider, permissions, enforce_residency usw.codex-rs/core/src/config/mod.rs:1258-1297 — ConfigBuilder; bestückt codex_home, cli_overrides, harness_overrides und cloud bundle und ruft build().await auf.codex-rs/core/src/config/mod.rs:1721-1728 — Config::load_with_cli_overrides; der häufigste Einstieg.codex-rs/core/src/config_lock.rs:38-74 — config_lockfile und validate_config_lock_replay; Lockfile-Erzeugung und Replay-Validierung.codex-rs/codex-home/src/instructions/mod.rs:14-68 — CodexHomeUserInstructionsProvider; lädt globale Nutzeranweisungen aus ~/.codex/AGENTS.md.ConfigLayerSource presst 8 Quellen in ein Enum; die Zahl von precedence bestimmt die Merge-Reihenfolge:
// config/src/config_layer_source.rs:6-48 — 来源 + 优先级
pub enum ConfigLayerSource {
Mdm { domain: String, key: String }, // 0
System { file: AbsolutePathBuf }, // 10
EnterpriseManaged { id: String, name: String }, // 15
User { file: AbsolutePathBuf, profile: Option<String> }, // 20 或 21
Project { dot_codex_folder: AbsolutePathBuf }, // 25
SessionFlags, // 30
LegacyManagedConfigTomlFromFile { .. }, // 40
LegacyManagedConfigTomlFromMdm, // 50
}
impl ConfigLayerSource {
pub fn precedence(&self) -> i16 {
match self {
ConfigLayerSource::Mdm { .. } => 0,
ConfigLayerSource::System { .. } => 10,
ConfigLayerSource::SessionFlags => 30,
// ...
}
}
}effective_config mergt nach precedence von niedrig nach hoch; später Geschriebenes überschreibt früher Geschriebenes:
// config/src/state.rs:483-492 — 合并层叠
pub fn effective_config(&self) -> TomlValue {
let mut merged = TomlValue::Table(toml::map::Map::new());
for layer in self.get_layers(
ConfigLayerStackOrdering::LowestPrecedenceFirst,
/*include_disabled*/ false,
) {
merge_toml_values(&mut merged, &layer.config);
}
merged
}config_lock sperrt das damalige Merge-Ergebnis und vergleicht beim Replay TOML-Feldabweichungen:
// core/src/config_lock.rs:46-74 — 锁文件重放校验
pub(crate) fn validate_config_lock_replay(
expected_lock: &ConfigLockfileToml,
actual_lock: &ConfigLockfileToml,
options: ConfigLockReplayOptions,
) -> io::Result<()> {
validate_config_lock_metadata_shape(expected_lock)?;
validate_config_lock_metadata_shape(actual_lock)?;
if !options.allow_codex_version_mismatch
&& expected_lock.codex_version != actual_lock.codex_version
{
return Err(config_lock_error(format!(
"config lock Codex version mismatch: lock was generated by {}, current version is {}; ...",
expected_lock.codex_version, actual_lock.codex_version
)));
}
// ...继续 TOML 字段对比,不一致时用 similar 算 diff 报错
}Datenfluss
Grenzen und Fehler
- CODEX_HOME muss ein Verzeichnis sein: Ist die Umgebungsvariable gesetzt, aber nicht vorhanden oder kein Verzeichnis, bricht er direkt ab und fällt nicht stillschweigend auf
~/.codexzurück (codex-rs/core/src/config/mod.rs:4436-4442). - Ungültige Konfiguration ist nicht fatal:
Config::load_default_with_cli_overridesfällt bei Parse-Fehler in der Nutzerkonfiguration auf default + cli overrides zurück, damit die CLI noch hochkommt (codex-rs/core/src/config/mod.rs:1731-1740). - config_lock-Versionssprung defaultmäßig Fehler: Bei abweichender codex-Version wird das Replay abgelehnt; nur mit explizitem
debug.config_lockfile.allow_codex_version_mismatch=truewird es zugelassen (codex-rs/core/src/config_lock.rs:54-61). - AGENTS.md-Priorität: Im selben Verzeichnis hat
AGENTS.override.mdVorrang vorAGENTS.md; nur die erste nicht-leere Datei wird gelesen, um Mehrdeutigkeit durch Schichtung zu vermeiden (codex-rs/codex-home/src/instructions/mod.rs:26-67). - cloud bundle nur für Unternehmenskonten:
cloud_config_eligible_authverlangtuses_codex_backendund Plan Business/Enterprise/Edu (codex-rs/cloud-config/src/service.rs:47-54).
Zusammenfassung
Das Konfigurationssystem mergt mehrere Quellen (system / user / project / cloud / session flags) nach der Zahl precedence() zu Config; cloud bundle geht über denselben merge_toml_values-Pfad wie lokales TOML; der Login-Zustand steht in auth.json und wird vom AuthManager in Model Provider gelesen. ConfigLockfileToml sperrt das Merge-Ergebnis für Replay-Konsistenz. Die von Cloud-Aufgaben genutzte enterprise-Policy wird vom cloud-config-Dienst im Cloud Tasks-Pfad regelmäßig aktualisiert, lokal gecacht und hier in die effective config eingelesen.