parseImagesSection function
Parses the images: section (session image registry, issue #171):
registry (kill switch), maxPerRequest (per-request unique-image
cap) and perModel (per-model cap overrides, issue #1750). Strict —
a bad schema throws ConfigException instead of silently keeping the
defaults. Public so the settings flow's reload-after-write (issue
#395) reuses the same parser the boot runs.
Implementation
ImageRegistryConfig? parseImagesSection(Object? node) {
if (node == null) return null;
if (node is! YamlMap) {
throw ConfigException('images must be a map, got: $node');
}
bool readBool(String key) {
final value = node[key];
if (value is! bool) {
throw ConfigException('"images.$key" must be a boolean');
}
return value;
}
int readPositiveInt(String key) {
final value = node[key];
if (value is! int || value <= 0) {
throw ConfigException('"images.$key" must be a positive integer');
}
return value;
}
int readPerModelCap(Object? key, Object? value) {
if (value is! int || value <= 0) {
throw ConfigException(
'"images.perModel.$key" must be a positive integer',
);
}
return value;
}
Map<String, int> readPerModel() {
final value = node['perModel'];
if (value is! YamlMap) {
throw ConfigException(
'"images.perModel" must be a map of model id → cap, got: $value',
);
}
return {
for (final entry in value.entries)
'${entry.key}': readPerModelCap(entry.key, entry.value),
};
}
bool? registry;
int? maxPerRequest;
Map<String, int>? perModel;
for (final key in node.keys) {
switch (key) {
case 'registry':
registry = readBool('$key');
case 'maxPerRequest':
maxPerRequest = readPositiveInt('$key');
case 'perModel':
perModel = readPerModel();
default:
throw ConfigException('unknown "images" key: $key');
}
}
if (registry == null && maxPerRequest == null && perModel == null) {
return null;
}
return ImageRegistryConfig(
enabled: registry ?? true,
maxPerRequest: maxPerRequest ?? defaultMaxImagesPerRequest,
perModel: perModel ?? const {},
);
}