cleanupOldSessionFiles function

Future<CleanupResult> cleanupOldSessionFiles()

Clean up old session files (transcripts, tool results, etc.).

Implementation

Future<CleanupResult> cleanupOldSessionFiles() async {
  final cutoffDate = getCutoffDate();
  var result = const CleanupResult();
  final projectsDir = _getProjectsDir();

  Directory projectsDirObj;
  try {
    projectsDirObj = Directory(projectsDir);
    if (!await projectsDirObj.exists()) return result;
  } catch (_) {
    return result;
  }

  await for (final projectDirent in projectsDirObj.list()) {
    if (projectDirent is! Directory) continue;
    final projectDir = projectDirent.path;

    List<FileSystemEntity> entries;
    try {
      entries = await Directory(projectDir).list().toList();
    } catch (_) {
      result = CleanupResult(
        messages: result.messages,
        errors: result.errors + 1,
      );
      continue;
    }

    for (final entry in entries) {
      if (entry is File) {
        final name = p.basename(entry.path);
        if (!name.endsWith('.jsonl') && !name.endsWith('.cast')) continue;
        try {
          if (await _unlinkIfOld(entry.path, cutoffDate)) {
            result = CleanupResult(
              messages: result.messages + 1,
              errors: result.errors,
            );
          }
        } catch (_) {
          result = CleanupResult(
            messages: result.messages,
            errors: result.errors + 1,
          );
        }
      } else if (entry is Directory) {
        // Session directory — clean up tool-results subdirs.
        final sessionDir = entry.path;
        final toolResultsDir = p.join(sessionDir, _toolResultsSubdir);

        List<FileSystemEntity> toolDirs;
        try {
          toolDirs = await Directory(toolResultsDir).list().toList();
        } catch (_) {
          await _tryRmdir(sessionDir);
          continue;
        }

        for (final toolEntry in toolDirs) {
          if (toolEntry is File) {
            try {
              if (await _unlinkIfOld(toolEntry.path, cutoffDate)) {
                result = CleanupResult(
                  messages: result.messages + 1,
                  errors: result.errors,
                );
              }
            } catch (_) {
              result = CleanupResult(
                messages: result.messages,
                errors: result.errors + 1,
              );
            }
          } else if (toolEntry is Directory) {
            final toolDirPath = toolEntry.path;
            List<FileSystemEntity> toolFiles;
            try {
              toolFiles = await Directory(toolDirPath).list().toList();
            } catch (_) {
              continue;
            }
            for (final tf in toolFiles) {
              if (tf is! File) continue;
              try {
                if (await _unlinkIfOld(tf.path, cutoffDate)) {
                  result = CleanupResult(
                    messages: result.messages + 1,
                    errors: result.errors,
                  );
                }
              } catch (_) {
                result = CleanupResult(
                  messages: result.messages,
                  errors: result.errors + 1,
                );
              }
            }
            await _tryRmdir(toolDirPath);
          }
        }
        await _tryRmdir(toolResultsDir);
        await _tryRmdir(sessionDir);
      }
    }

    await _tryRmdir(projectDir);
  }

  return result;
}