trajectoryPromptDiff function

List<TrajectoryDiffLine> trajectoryPromptDiff(
  1. String before,
  2. String after
)

Minimal unified-style line diff between two prompt versions (AC2): the common prefix/suffix is trimmed, the middle renders as one changed block, up to 3 context lines flank it, and collapsed ranges show an ellipsis line. Pure — the UI tab and the CLI mirror share it.

Implementation

List<TrajectoryDiffLine> trajectoryPromptDiff(String before, String after) {
  if (before == after) return const [];
  final beforeLines = before.split('\n');
  final afterLines = after.split('\n');
  final (:start, :beforeEnd, :afterEnd) = _diffChangedRange(
    beforeLines,
    afterLines,
  );
  const context = 3;

  final lines = <TrajectoryDiffLine>[];
  void contextRange(int from, int to, List<String> source) {
    for (var i = from; i < to; i++) {
      lines.add(TrajectoryDiffLine('context', source[i]));
    }
  }

  final contextStart = start > context ? start - context : 0;
  if (contextStart > 0) lines.add(const TrajectoryDiffLine('ellipsis', '…'));
  contextRange(contextStart, start, beforeLines);
  for (var i = start; i < beforeEnd; i++) {
    lines.add(TrajectoryDiffLine('removed', beforeLines[i]));
  }
  for (var i = start; i < afterEnd; i++) {
    lines.add(TrajectoryDiffLine('added', afterLines[i]));
  }
  final contextEnd = beforeLines.length - beforeEnd > context
      ? beforeEnd + context
      : beforeLines.length;
  contextRange(beforeEnd, contextEnd, beforeLines);
  if (contextEnd < beforeLines.length) {
    lines.add(const TrajectoryDiffLine('ellipsis', '…'));
  }
  return lines;
}