HostExtension constructor

HostExtension({
  1. required String name,
  2. List<AgentTool> tools = const [],
  3. required Map<String, CapabilityState> profileStates,
})

Validates and builds. Throws HostProfileViolation on an E6 gap (missing built-in profile, blank reason, a transport state — tool extensions have no transport dimension), an empty name, or an empty/duplicate tool id.

Implementation

HostExtension({
  required this.name,
  List<AgentTool> tools = const [],
  required Map<String, CapabilityState> profileStates,
}) : tools = List.unmodifiable(tools),
     profileStates = Map.unmodifiable(profileStates) {
  if (name.trim().isEmpty) {
    throw const HostProfileViolation(
      'HostExtension name must not be blank (E7 names registrants — '
      'they need a real id).',
    );
  }
  final missing = builtInProfiles.keys
      .where((profile) => !profileStates.containsKey(profile))
      .toList();
  if (missing.isNotEmpty) {
    throw HostProfileViolation(
      'HostExtension "$name" declares no state for built-in profile(s) '
      '${missing.map((m) => '"$m"').join(', ')} — declare every built-in '
      'profile explicitly (E6: there is no implicit default).',
    );
  }
  for (final entry in profileStates.entries) {
    if (entry.value is CapabilityTransportState) {
      throw HostProfileViolation(
        'HostExtension "$name" declares a transport state for profile '
        '"${entry.key}" — tool extensions have no transport dimension; '
        'declare on or off(reason).',
      );
    }
    if (entry.value.reason case final reason? when reason.trim().isEmpty) {
      throw HostProfileViolation(
        'HostExtension "$name" is off on "${entry.key}" without a reason '
        '— off is never silent (E8).',
      );
    }
  }
  final seen = <String>{};
  for (final tool in tools) {
    if (tool.name.trim().isEmpty) {
      throw HostProfileViolation(
        'HostExtension "$name" contributes a tool with a blank id.',
      );
    }
    if (!seen.add(tool.name)) {
      throw HostProfileViolation(
        'HostExtension "$name" contributes "${tool.name}" twice — the '
        'builder rejects duplicate ids at build time (E7).',
      );
    }
  }
}