def normalize_config(
*,
runtime: RuntimeConfig,
capabilities: Sequence[FamilyConfig] = (),
services: Sequence[FamilyConfig] = (),
integrations: IntegrationSelections | None = None,
compat: LegacyBehavior | None = None,
provenance: ConfigProvenance | None = None,
bindings: ConfigBindings | None = None,
context: ValidationContext | None = None,
) -> NormalizedConfig:
"""Normalize once, validate once, and return the compiler's sole input."""
capability_map = _index_families(capabilities, CAPABILITY_MODELS, "capability")
service_map = _index_families(services, SERVICE_MODELS, "service")
selected_integrations = integrations or IntegrationSelections()
live_bindings = bindings or ConfigBindings()
validation_context = context or ValidationContext()
generated = _native_entries(runtime, runtime.family_id)
for family_id, value in (*capability_map.items(), *service_map.items()):
generated.update(_native_entries(value, family_id))
generated.update(
_native_entries(selected_integrations.provider, selected_integrations.provider.family_id)
)
if selected_integrations.embedding:
generated.update(
_native_entries(
selected_integrations.embedding,
selected_integrations.embedding.family_id,
)
)
if selected_integrations.telemetry:
generated.update(
_native_entries(
selected_integrations.telemetry,
selected_integrations.telemetry.family_id,
)
)
if compat:
generated.update(_native_entries(compat, compat.family_id))
if provenance is None:
provenance = ConfigProvenance(entries=generated)
else:
missing = sorted(set(generated) - set(provenance.entries))
if missing:
raise ConfigurationError("XV-01 missing provenance for target " + ", ".join(missing))
normalized = NormalizedConfig(
runtime=runtime,
capabilities=capability_map,
services=service_map,
integrations=selected_integrations,
compat=compat,
provenance=provenance,
binding_descriptors=live_bindings.descriptors(),
)
from .validation import validate_dependencies
validate_dependencies(normalized, bindings=live_bindings, context=validation_context)
return normalized