The-Agency/lib/ui/providers/session_provider.dart

193 lines
5.7 KiB
Dart

import "package:flutter/foundation.dart";
import "package:uuid/uuid.dart";
import "../../src/project_store.dart";
import "../../src/session/conversation_history.dart";
import "../../src/session/session_store.dart";
import "../../src/session/session_types.dart";
class SessionProvider extends ChangeNotifier {
SessionProvider(this._projectStore) {
_loadSessions();
}
final ProjectStore _projectStore;
final SessionStore _sessionStore = SessionStore.instance;
final ConversationHistory _conversationHistory = ConversationHistory();
List<SessionSummary> _sessions = <SessionSummary>[];
String? _currentSessionId;
ConversationSession? _currentSession;
String? _activeWorkingDirectory;
List<SessionSummary> get sessions => _sessions;
String? get currentSessionId => _currentSessionId;
ConversationSession? get currentSession => _currentSession;
String? get activeWorkingDirectory => _activeWorkingDirectory;
void setActiveSessionId(String id) {
_currentSessionId = id;
notifyListeners();
}
List<SessionSummary> sessionsForWorkingDirectory(String? workingDirectory) {
final normalizedDirectory = workingDirectory?.trim();
if (normalizedDirectory == null || normalizedDirectory.isEmpty) {
return List<SessionSummary>.unmodifiable(_sessions);
}
return List<SessionSummary>.unmodifiable(
_sessions.where(
(session) => session.workingDirectory == normalizedDirectory,
),
);
}
void selectWorkingDirectory(String? workingDirectory) {
_activeWorkingDirectory = workingDirectory?.trim();
notifyListeners();
}
void clearCurrentSession({String? workingDirectory}) {
_conversationHistory.setSession(
ConversationSession(
id: "",
name: "",
created: DateTime.now().toUtc(),
updated: DateTime.now().toUtc(),
workingDirectory: workingDirectory?.trim(),
),
);
_currentSession = null;
_currentSessionId = null;
_activeWorkingDirectory = workingDirectory?.trim();
notifyListeners();
}
Future<void> _loadSessions() async {
try {
final workingDirs = _projectStore.projects
.map((p) => p.workingDirectory)
.where((d) => d.isNotEmpty)
.toList();
_sessions = await _sessionStore.listAllSessions(workingDirs);
notifyListeners();
} catch (error, stackTrace) {
_logException("Failed to load sessions", error, stackTrace);
_sessions = <SessionSummary>[];
}
}
Future<void> createNewSession({
String? workingDirectory,
String? name,
String? model,
}) async {
try {
const uuid = Uuid();
final newSessionId = uuid.v4();
final now = DateTime.now().toUtc();
final normalizedDirectory = workingDirectory?.trim();
final newSession = ConversationSession(
id: newSessionId,
name: name ?? "New Chat",
created: now,
updated: now,
workingDirectory:
normalizedDirectory == null || normalizedDirectory.isEmpty
? null
: normalizedDirectory,
model: model,
);
await _sessionStore.saveSession(newSession);
_conversationHistory.setSession(newSession);
_currentSession = newSession;
_currentSessionId = newSessionId;
_activeWorkingDirectory = newSession.workingDirectory;
await _loadSessions();
notifyListeners();
} catch (error, stackTrace) {
_logException("Failed to create a new session", error, stackTrace);
}
}
Future<void> loadSession(SessionSummary summary) async {
try {
final workingDir = summary.workingDirectory;
if (workingDir == null || workingDir.isEmpty) return;
final session = await _sessionStore.loadSession(
summary.id,
workingDirectory: workingDir,
);
if (session != null) {
_conversationHistory.setSession(session);
_currentSession = session;
_currentSessionId = summary.id;
_activeWorkingDirectory = session.workingDirectory;
notifyListeners();
}
} catch (error, stackTrace) {
_logException("Failed to load session ${summary.id}", error, stackTrace);
_currentSession = null;
_currentSessionId = null;
_activeWorkingDirectory = null;
}
}
Future<void> deleteSession(SessionSummary summary) async {
try {
final workingDir = summary.workingDirectory;
if (workingDir == null || workingDir.isEmpty) return;
await _sessionStore.deleteSession(summary.id, workingDirectory: workingDir);
if (_currentSessionId == summary.id) {
_conversationHistory.setSession(
ConversationSession(
id: "",
name: "",
created: DateTime.now().toUtc(),
updated: DateTime.now().toUtc(),
),
);
_currentSession = null;
_currentSessionId = null;
_activeWorkingDirectory = null;
}
await _loadSessions();
notifyListeners();
} catch (error, stackTrace) {
_logException("Failed to delete session ${summary.id}", error, stackTrace);
}
}
Future<void> refreshSessions() async {
try {
await _loadSessions();
} catch (error, stackTrace) {
_logException("Failed to refresh sessions", error, stackTrace);
}
}
// Updates the model on the current in-memory session and persists it
Future<void> updateSessionModel(String model) async {
final session = _currentSession;
if (session == null) return;
session.model = model;
await _sessionStore.saveSession(session);
}
ConversationHistory getConversationHistory() => _conversationHistory;
void _logException(String message, Object error, StackTrace stackTrace) {
print("$message: $error");
print(stackTrace);
}
}