prepareCompaction method

CompactionPreparation? prepareCompaction(
  1. List<SessionRecord> pathEntries, {
  2. required int tokensBefore,
  3. CompactionSettings? settings,
})

Prepare session branch records for compaction, or return null when compaction is not applicable (empty branch, or the last entry is already a compaction).

Ported from pi's prepareCompaction: the summarized region starts at the previous compaction's kept boundary (with its summary threaded in for iterative updates), and file operations accumulate across compactions.

Implementation

CompactionPreparation? prepareCompaction(
  List<SessionRecord> pathEntries, {
  required int tokensBefore,
  CompactionSettings? settings,
}) {
  final effectiveSettings = settings ?? this.settings;
  if (pathEntries.isEmpty || pathEntries.last is CompactionRecord) {
    return null;
  }

  final prevCompactionIndex = _findLastCompactionIndex(pathEntries);

  final fileOps = createFileOps();
  final prevContext = _previousCompactionContext(
    pathEntries,
    prevCompactionIndex,
    fileOps,
  );
  final previousSummary = prevContext.previousSummary;
  final boundaryStart = prevContext.boundaryStart;

  final cutPoint = findCutPoint(
    pathEntries,
    boundaryStart,
    pathEntries.length,
    effectiveSettings.keepRecentTokens,
  );
  final firstKeptEntryId = pathEntries[cutPoint.firstKeptEntryIndex].id;

  final historyEnd = cutPoint.isSplitTurn
      ? cutPoint.turnStartIndex
      : cutPoint.firstKeptEntryIndex;
  final messagesToSummarize = <Message>[];
  final summarizableRecordIds = <String?>[];
  for (var i = boundaryStart; i < historyEnd; i++) {
    for (final message in _entryToSummarizableMessages(pathEntries[i])) {
      messagesToSummarize.add(message);
      summarizableRecordIds.add(pathEntries[i].id);
    }
  }
  final turnPrefixMessages = cutPoint.isSplitTurn
      ? _summarizableMessagesInRange(
          pathEntries,
          cutPoint.turnStartIndex,
          cutPoint.firstKeptEntryIndex,
        )
      : <Message>[];
  _accumulateFileOps(messagesToSummarize, fileOps);
  _accumulateFileOps(turnPrefixMessages, fileOps);
  final fileLists = computeFileLists(fileOps);

  return CompactionPreparation(
    firstKeptEntryId: firstKeptEntryId,
    messagesToSummarize: messagesToSummarize,
    turnPrefixMessages: turnPrefixMessages,
    isSplitTurn: cutPoint.isSplitTurn,
    tokensBefore: tokensBefore,
    previousSummary: previousSummary,
    readFiles: fileLists.readFiles,
    modifiedFiles: fileLists.modifiedFiles,
    settings: effectiveSettings,
    summarizableRecordIds: summarizableRecordIds,
  );
}