scan method

UsageChainScan scan(
  1. Iterable<String> lines
)

Scans lines (the session file's raw lines, header included).

Implementation

UsageChainScan scan(Iterable<String> lines) {
  final state = _ScanState();
  for (final raw in lines) {
    final line = raw.trimRight();
    if (line.isEmpty) continue;
    // Cheap pre-check for the giant blob records: hashed, counted, never
    // decoded.
    final skippedDecode = _isBlobRecord(line);
    final decoded = skippedDecode ? <String, dynamic>{} : _decode(line);
    if (decoded == null) continue; // torn line: contributes nothing
    final type = decoded['type'];
    if (type == 'session') continue; // header line
    state.noteRecord(line);
    if (skippedDecode) continue;
    final timestamp = DateTime.tryParse(
      decoded['timestamp'] as String? ?? '',
    );
    if (type == 'custom' &&
        decoded['customType'] == usageSegmentStartCustomType) {
      _handleMarker(timestamp, state);
      continue;
    }
    // Every other consumed record contributes its timestamp to the
    // current segment (its closedAt, or firstRecordAt fallback).
    state.current().noteRecordAt(timestamp);
    if (type == 'custom') {
      _handleSummary(decoded, state);
      continue;
    }
    if (type != 'message') continue;
    _handleAssistantMessage(decoded, state);
  }
  return state.finish();
}