Files
codex/codex-rs/app-server/src/config_layer.rs
jif 34ecac1f2b Support packaged defaults in config layering (#37810)
## What changed

- Load an optional package-supplied config file as the lowest-precedence
  configuration layer, so every existing layer can override its values.
- Report the layer as `packagedDefaults`, including its source path, through
  config diagnostics and the app-server protocol.
- Return an error when a configured packaged defaults file is missing.

## Testing

- Cover precedence across packaged, system, user, and session layers.
- Cover the missing-file error path.

GitOrigin-RevId: 52406890f4d580eedabc90bf2a9ee3affa36fee1
2026-08-10 11:22:55 +00:00

67 lines
3.1 KiB
Rust

use codex_app_server_protocol::ConfigLayer as ApiConfigLayer;
use codex_app_server_protocol::ConfigLayerMetadata as ApiConfigLayerMetadata;
use codex_app_server_protocol::ConfigLayerSource as ApiConfigLayerSource;
use codex_config::ConfigLayer;
use codex_config::ConfigLayerMetadata;
use codex_config::ConfigLayerSource;
/// Converts a config-layer source owned by `codex-config` into the app-server wire type owned by
/// `codex-app-server-protocol`.
///
/// The types stay separate so app-server protocol ownership does not leak into the config domain
/// crate. Because this crate owns neither type, Rust's orphan rules require an explicit conversion
/// function instead of a `From` implementation.
pub(crate) fn config_layer_source_to_api(source: ConfigLayerSource) -> ApiConfigLayerSource {
match source {
ConfigLayerSource::PackagedDefaults { file } => {
ApiConfigLayerSource::PackagedDefaults { file }
}
ConfigLayerSource::Mdm { domain, key } => ApiConfigLayerSource::Mdm { domain, key },
ConfigLayerSource::System { file } => ApiConfigLayerSource::System { file },
ConfigLayerSource::EnterpriseManaged { id, name } => {
ApiConfigLayerSource::EnterpriseManaged { id, name }
}
ConfigLayerSource::User { file, profile } => ApiConfigLayerSource::User { file, profile },
ConfigLayerSource::Project { dot_codex_folder } => {
ApiConfigLayerSource::Project { dot_codex_folder }
}
ConfigLayerSource::SessionFlags => ApiConfigLayerSource::SessionFlags,
ConfigLayerSource::LegacyManagedConfigTomlFromFile { file } => {
ApiConfigLayerSource::LegacyManagedConfigTomlFromFile { file }
}
ConfigLayerSource::LegacyManagedConfigTomlFromMdm => {
ApiConfigLayerSource::LegacyManagedConfigTomlFromMdm
}
}
}
/// Converts config-layer metadata owned by `codex-config` into the app-server wire type owned by
/// `codex-app-server-protocol`.
///
/// The types stay separate so app-server protocol ownership does not leak into the config domain
/// crate. Because this crate owns neither type, Rust's orphan rules require an explicit conversion
/// function instead of a `From` implementation.
pub(crate) fn config_layer_metadata_to_api(
metadata: ConfigLayerMetadata,
) -> ApiConfigLayerMetadata {
ApiConfigLayerMetadata {
name: config_layer_source_to_api(metadata.name),
version: metadata.version,
}
}
/// Converts a config layer owned by `codex-config` into the app-server wire type owned by
/// `codex-app-server-protocol`.
///
/// The types stay separate so app-server protocol ownership does not leak into the config domain
/// crate. Because this crate owns neither type, Rust's orphan rules require an explicit conversion
/// function instead of a `From` implementation.
pub(crate) fn config_layer_to_api(layer: ConfigLayer) -> ApiConfigLayer {
ApiConfigLayer {
name: config_layer_source_to_api(layer.name),
version: layer.version,
config: layer.config,
disabled_reason: layer.disabled_reason,
}
}