maybeTimeBasedMicrocompact function

MicrocompactResult? maybeTimeBasedMicrocompact(
  1. List<CompactMessage> messages,
  2. String? querySource
)

Time-based microcompact: content-clear old tool results when the gap since the last assistant message exceeds the threshold.

Implementation

MicrocompactResult? maybeTimeBasedMicrocompact(
  List<CompactMessage> messages,
  String? querySource,
) {
  final trigger = evaluateTimeBasedTrigger(messages, querySource);
  if (trigger == null) return null;

  final config = trigger.config;
  final compactableIds = collectCompactableToolIds(messages);

  final keepRecent = max(1, config.keepRecent);
  final keepSet = <String>{};
  for (
    int i = max(0, compactableIds.length - keepRecent);
    i < compactableIds.length;
    i++
  ) {
    keepSet.add(compactableIds[i]);
  }

  final clearSet = <String>{
    ...compactableIds.where((id) => !keepSet.contains(id)),
  };

  if (clearSet.isEmpty) return null;

  int tokensSaved = 0;
  final result = messages.map((message) {
    if (message.type != MessageRole.user) return message;
    bool touched = false;
    final newBlocks = message.contentBlocks.map((block) {
      if (block.type == ContentBlockType.toolResult &&
          block.toolUseId != null &&
          clearSet.contains(block.toolUseId) &&
          block.content != timeBasedMCClearedMessage) {
        tokensSaved += _calculateToolResultTokens(block);
        touched = true;
        return ContentBlock(
          type: block.type,
          toolUseId: block.toolUseId,
          content: timeBasedMCClearedMessage,
          isError: block.isError,
        );
      }
      return block;
    }).toList();
    if (!touched) return message;
    return message.copyWith(contentBlocks: newBlocks);
  }).toList();

  if (tokensSaved == 0) return null;

  suppressCompactWarning();
  return MicrocompactResult(messages: result);
}