Skip to content

Konfigurationssystem

源码版本rust-v0.145.0

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

  1. codex home lokalisieren: find_codex_home liest CODEX_HOME; ist es nicht gesetzt, fällt es auf ~/.codex zurück (codex-rs/core/src/config/mod.rs:4440-4442).
  2. Mehrlagiges Laden: load_config_layers_state lädt der Reihe nach system / managed / cloud bundle / user / project / session flags und liefert einen ConfigLayerStack (codex-rs/config/src/loader/mod.rs:116-168).
  3. Merge zur effective config: ConfigLayerStack::effective_config mergt TOML von niedriger zu hoher precedence (codex-rs/config/src/state.rs:483-492).
  4. Runtime-Config aufbauen: ConfigBuilder setzt codex_home, cli_overrides, harness_overrides und cloud bundle zusammen und ruft build().await auf (codex-rs/core/src/config/mod.rs:1258-1297).
  5. Login-Zustand schreiben: login_with_chatgpt / run_login_with_api_key laufen den Login-Prozess und schreiben Credentials nach auth.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-49ConfigLayerSource-Enum und precedence(); definiert 8 Quellen und Merge-Reihenfolge.codex-rs/config/src/loader/mod.rs:116-168load_config_layers_state; lädt system / managed / cloud bundle / user / project in den Stack.codex-rs/config/src/state.rs:483-492effective_config; mergt von niedriger zu hoher precedence via merge_toml_values.codex-rs/core/src/config/mod.rs:614-673Config-Struktur; das „endgültige Konfigurations"-Objekt zur Laufzeit, mit model_provider, permissions, enforce_residency usw.codex-rs/core/src/config/mod.rs:1258-1297ConfigBuilder; bestückt codex_home, cli_overrides, harness_overrides und cloud bundle und ruft build().await auf.codex-rs/core/src/config/mod.rs:1721-1728Config::load_with_cli_overrides; der häufigste Einstieg.codex-rs/core/src/config_lock.rs:38-74config_lockfile und validate_config_lock_replay; Lockfile-Erzeugung und Replay-Validierung.codex-rs/codex-home/src/instructions/mod.rs:14-68CodexHomeUserInstructionsProvider; lädt globale Nutzeranweisungen aus ~/.codex/AGENTS.md.

ConfigLayerSource presst 8 Quellen in ein Enum; die Zahl von precedence bestimmt die Merge-Reihenfolge:

rust
// 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:

rust
// 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:

rust
// 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 ~/.codex zurück (codex-rs/core/src/config/mod.rs:4436-4442).
  • Ungültige Konfiguration ist nicht fatal: Config::load_default_with_cli_overrides fä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=true wird es zugelassen (codex-rs/core/src/config_lock.rs:54-61).
  • AGENTS.md-Priorität: Im selben Verzeichnis hat AGENTS.override.md Vorrang vor AGENTS.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_auth verlangt uses_codex_backend und 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.