readLiteMetadata method

Future<SessionMetadata?> readLiteMetadata(
  1. String filePath
)

Read lite metadata from the tail of a session file.

Implementation

Future<SessionMetadata?> readLiteMetadata(String filePath) async {
  final file = File(filePath);
  if (!await file.exists()) return null;

  final stat = await file.stat();
  final tail = await _readFileTail(filePath, _liteReadBufSize);
  if (tail.isEmpty) return null;

  final lines = tail.split('\n');
  String? customTitle;
  String? aiTitle;
  String? firstPrompt;
  String? lastPrompt;
  String? tag;
  String? agentName;
  String? agentColor;
  String? agentSetting;
  String? mode;

  for (final line in lines.reversed) {
    if (line.isEmpty) continue;
    try {
      if (line.startsWith('{"type":"custom-title"')) {
        customTitle ??= _extractJsonField(line, 'customTitle');
      } else if (line.startsWith('{"type":"ai-title"')) {
        aiTitle ??= _extractJsonField(line, 'title');
      } else if (line.startsWith('{"type":"last-prompt"')) {
        lastPrompt ??= _extractJsonField(line, 'lastPrompt');
      } else if (line.startsWith('{"type":"tag"')) {
        tag ??= _extractJsonField(line, 'tag');
      } else if (line.startsWith('{"type":"agent-name"')) {
        agentName ??= _extractJsonField(line, 'agentName');
      } else if (line.startsWith('{"type":"agent-color"')) {
        agentColor ??= _extractJsonField(line, 'agentColor');
      } else if (line.startsWith('{"type":"agent-setting"')) {
        agentSetting ??= _extractJsonField(line, 'agentSetting');
      } else if (line.startsWith('{"type":"mode"')) {
        mode ??= _extractJsonField(line, 'mode');
      }
    } catch (_) {
      // Skip malformed lines.
    }
  }

  // Extract first prompt from transcript messages.
  for (final line in lines) {
    if (line.isEmpty) continue;
    try {
      final parsed = jsonDecode(line) as Map<String, dynamic>;
      if (parsed['type'] == 'user') {
        final content = parsed['message']?['content'];
        final text = content is String ? content : null;
        if (text != null &&
            text.isNotEmpty &&
            !_skipFirstPromptPattern.hasMatch(text)) {
          firstPrompt = text.length > 200
              ? '${text.substring(0, 200).trim()}\u2026'
              : text;
          break;
        }
      }
    } catch (_) {
      // Skip malformed lines.
    }
  }

  final sessionId = p.basenameWithoutExtension(filePath);
  return SessionMetadata(
    sessionId: sessionId,
    customTitle: customTitle,
    aiTitle: aiTitle,
    firstPrompt: firstPrompt,
    lastPrompt: lastPrompt,
    tag: tag,
    agentName: agentName,
    agentColor: agentColor,
    agentSetting: agentSetting,
    mode: mode,
    lastModified: stat.modified,
    fileSize: stat.size,
  );
}