getDeferredToolsDelta method

DeferredToolsDelta? getDeferredToolsDelta({
  1. required List<ToolDefinition> tools,
  2. required List<ToolSearchMessage> messages,
  3. DeferredToolsDeltaScanContext? scanContext,
})

Diff the current deferred-tool pool against what has been announced.

Returns null if nothing changed. A name that was announced but has since stopped being deferred -- yet is still in the base pool -- is NOT reported as removed.

Implementation

DeferredToolsDelta? getDeferredToolsDelta({
  required List<ToolDefinition> tools,
  required List<ToolSearchMessage> messages,
  DeferredToolsDeltaScanContext? scanContext,
}) {
  final announced = <String>{};
  int attachmentCount = 0;
  int dtdCount = 0;
  final attachmentTypesSeen = <String>{};

  for (final msg in messages) {
    if (msg.type != 'attachment') continue;
    attachmentCount++;
    final attachmentType = msg.attachment?['type'] as String?;
    if (attachmentType != null) attachmentTypesSeen.add(attachmentType);
    if (attachmentType != 'deferred_tools_delta') continue;
    dtdCount++;
    final addedNames = msg.attachment?['addedNames'];
    if (addedNames is List) {
      for (final n in addedNames) {
        if (n is String) announced.add(n);
      }
    }
    final removedNames = msg.attachment?['removedNames'];
    if (removedNames is List) {
      for (final n in removedNames) {
        if (n is String) announced.remove(n);
      }
    }
  }

  final deferred = tools.where((t) => t.isDeferred).toList();
  final deferredNames = deferred.map((t) => t.name).toSet();
  final poolNames = tools.map((t) => t.name).toSet();

  final added = deferred.where((t) => !announced.contains(t.name)).toList();
  final removed = <String>[];
  for (final n in announced) {
    if (deferredNames.contains(n)) continue;
    if (!poolNames.contains(n)) removed.add(n);
  }

  if (added.isEmpty && removed.isEmpty) return null;

  return DeferredToolsDelta(
    addedNames: added.map((t) => t.name).toList()..sort(),
    addedLines: added.map(_formatDeferredToolLine).toList()..sort(),
    removedNames: removed..sort(),
  );
}