saveConversation method

Future<void> saveConversation({
  1. required String sessionId,
  2. required List<Map<String, dynamic>> messages,
  3. required String model,
  4. required List<ConversationTurn> turns,
  5. String? title,
})

Save conversation state.

Implementation

Future<void> saveConversation({
  required String sessionId,
  required List<Map<String, dynamic>> messages,
  required String model,
  required List<ConversationTurn> turns,
  String? title,
}) async {
  final sessionDir = Directory(p.join(_sessionsDir, sessionId));
  await sessionDir.create(recursive: true);

  // Save full messages
  final messagesFile = File(p.join(sessionDir.path, 'messages.jsonl'));
  final sink = messagesFile.openWrite();
  for (final msg in messages) {
    sink.writeln(jsonEncode(msg));
  }
  await sink.close();

  // Save summary
  final summary = ConversationSummary(
    sessionId: sessionId,
    title: title ?? _generateTitle(messages),
    startedAt: turns.isNotEmpty
        ? DateTime.now().subtract(
            turns.fold(Duration.zero, (sum, t) => sum + t.duration),
          )
        : DateTime.now(),
    lastActiveAt: DateTime.now(),
    messageCount: messages.length,
    turnCount: turns.length,
    model: model,
    totalInputTokens: turns.fold(0, (sum, t) => sum + t.inputTokens),
    totalOutputTokens: turns.fold(0, (sum, t) => sum + t.outputTokens),
    totalCost: turns.fold(0.0, (sum, t) => sum + t.cost),
    toolsUsed: turns
        .expand((t) => t.toolExecutions.map((e) => e.toolName))
        .toSet()
        .toList(),
    lastUserMessage: _extractLastUserMessage(messages),
    lastAssistantMessage: _extractLastAssistantMessage(messages),
  );

  final summaryFile = File(p.join(sessionDir.path, 'summary.json'));
  await summaryFile.writeAsString(
    const JsonEncoder.withIndent('  ').convert(summary.toJson()),
  );
}