mergeSettings function

SettingsJson mergeSettings(
  1. List<SettingsJson> sources
)

Merge multiple settings (first takes priority).

Implementation

SettingsJson mergeSettings(List<SettingsJson> sources) {
  if (sources.isEmpty) return const SettingsJson();
  if (sources.length == 1) return sources.first;

  // Model: first non-null wins
  String? model;
  for (final s in sources) {
    if (s.model != null) {
      model = s.model;
      break;
    }
  }

  // Permissions: concatenate all rules
  final allAllow = <String>[];
  final allDeny = <String>[];
  final allAsk = <String>[];
  final allAdditionalDirs = <String>[];
  String? defaultMode;
  bool? disableBypass;

  for (final s in sources) {
    allAllow.addAll(s.permissions.allow);
    allDeny.addAll(s.permissions.deny);
    allAsk.addAll(s.permissions.ask);
    allAdditionalDirs.addAll(s.permissions.additionalDirectories);
    defaultMode ??= s.permissions.defaultMode;
    disableBypass ??= s.permissions.disableBypassPermissionsMode;
  }

  // Sandbox: first non-default wins
  SandboxSettings sandbox = const SandboxSettings();
  for (final s in sources) {
    if (s.sandbox.enabled) {
      sandbox = s.sandbox;
      break;
    }
  }

  // Environment variables: merge (earlier takes priority)
  final envVars = <String, String>{};
  for (final s in sources.reversed) {
    envVars.addAll(s.environmentVariables);
  }

  // Model overrides: merge
  final modelOverrides = <String, String>{};
  for (final s in sources.reversed) {
    modelOverrides.addAll(s.modelOverrides);
  }

  // Available models: first non-empty wins
  List<String> availableModels = [];
  for (final s in sources) {
    if (s.availableModels.isNotEmpty) {
      availableModels = s.availableModels;
      break;
    }
  }

  // Managed-only: any source can enable
  final managedOnly = sources.any((s) => s.allowManagedPermissionRulesOnly);

  return SettingsJson(
    model: model,
    permissions: PermissionSettings(
      allow: allAllow,
      deny: allDeny,
      ask: allAsk,
      defaultMode: defaultMode,
      disableBypassPermissionsMode: disableBypass,
      additionalDirectories: allAdditionalDirs,
    ),
    sandbox: sandbox,
    hooks: sources
        .firstWhere((s) => s.hooks != null, orElse: () => const SettingsJson())
        .hooks,
    installedPlugins: sources
        .expand((s) => s.installedPlugins)
        .toSet()
        .toList(),
    environmentVariables: envVars,
    modelOverrides: modelOverrides,
    availableModels: availableModels,
    allowManagedPermissionRulesOnly: managedOnly,
    syntaxHighlightingEnabled: sources.first.syntaxHighlightingEnabled,
    theme: sources
        .map((s) => s.theme)
        .firstWhere((t) => t != null, orElse: () => null),
    outputStyle: sources
        .map((s) => s.outputStyle)
        .firstWhere((o) => o != null, orElse: () => null),
  );
}