initialize method
Implementation
Future<bool> initialize() async {
SintSentinel.logger.i('ChatController.initialize() starting...');
final config = await _authService.loadApiConfig();
if (config == null) return false;
_provider = _createProvider(config);
_toolRegistry = _createToolRegistry();
final settings = await AppSettings.load();
// Generate session ID
sessionId.value = _uuid.v4();
// Initialize session history manager (saves/loads full sessions)
if (!kIsWeb) {
_sessionHistoryManager = SessionHistoryManager(
baseDir: SystemConstants.sessionDir,
);
}
// Initialize compaction service (auto-compact + microcompact)
_compactionService = CompactionService(provider: _provider!);
// Initialize session memory (periodic extraction)
if (!kIsWeb) {
final projectDir = Directory.current.path;
_sessionMemoryService = SessionMemoryService(
sessionId: sessionId.value,
projectDir: '${SystemConstants.configDir}/projects/${_sanitizePath(projectDir)}',
);
}
// Initialize memdir (persistent memory across sessions)
if (!kIsWeb) {
_memdirService = MemdirService(projectRoot: Directory.current.path);
}
// Load personality modules (IDENTITY, COGNITION, CAPABILITIES, TOOLS, etc.)
await NeomageSystemPrompt.load();
// Build memdir context
String? memoryContext;
if (_memdirService != null) {
try {
final memoryResult = await _memdirService!.loadMemoryPrompt();
memoryContext = memoryResult.prompt;
SintSentinel.logger.i(
'Loaded ${memoryResult.memoryFileCount} memory files into context',
);
} catch (e) {
SintSentinel.logger.w('Failed to load memory prompt: $e');
}
}
// Load NEOMAGE.md / project instructions
final neomageInstructions = await _loadNeomageInstructions();
// Load existing session memory if resuming
String? sessionMemoryContext;
if (_sessionMemoryService != null) {
try {
sessionMemoryContext = await _sessionMemoryService!.load();
} catch (_) {}
}
// Detect working directory, git branch, and platform info
String workingDir = '.';
String? gitBranch;
bool isGitRepo = false;
String? platformInfo;
if (!kIsWeb) {
workingDir = Directory.current.path;
try {
final branchResult = await Process.run('git', ['branch', '--show-current'],
workingDirectory: workingDir);
if (branchResult.exitCode == 0) {
gitBranch = (branchResult.stdout as String).trim();
isGitRepo = true;
}
} catch (_) {}
try {
final unameResult = await Process.run('uname', ['-sr']);
if (unameResult.exitCode == 0) {
platformInfo = (unameResult.stdout as String).trim();
}
} catch (_) {
platformInfo = Platform.operatingSystem;
}
} else {
platformInfo = 'Web';
}
// Build the full system prompt from personality modules + dynamic context.
// If user has a custom system prompt override, use that instead of modules.
String systemPrompt;
if (settings.customSystemPrompt != null) {
systemPrompt = settings.customSystemPrompt!;
} else {
// Combine memdir + session memory into single memory block
final combinedMemory = [
if (memoryContext != null && memoryContext.isNotEmpty) memoryContext,
if (sessionMemoryContext != null && sessionMemoryContext.isNotEmpty)
'<session_memory>\n$sessionMemoryContext\n</session_memory>',
].join('\n\n');
systemPrompt = NeomageSystemPrompt.build(
model: config.model,
workingDirectory: workingDir,
gitBranch: gitBranch,
isGitRepo: isGitRepo,
platform: platformInfo,
projectFramework: 'Flutter/Dart',
userInstructions: neomageInstructions,
memoryContext: combinedMemory.isEmpty ? null : combinedMemory,
);
}
// Create query engine with ALL services connected
_engine = QueryEngine(
provider: _provider!,
toolRegistry: _toolRegistry!,
systemPrompt: systemPrompt,
compactionService: _compactionService,
sessionMemory: _sessionMemoryService,
);
// Initialize rate limit service
_rateLimitService = RateLimitService(
apiKey: config.apiKey,
baseUrl: config.baseUrl,
cacheDir: SystemConstants.configDir,
);
// Load policies in background — fail-open if unavailable
_rateLimitService!.loadPolicies().ignore();
// Start telemetry session
_telemetry.startSession(metadata: {
'sessionId': sessionId.value,
'provider': config.type.name,
'model': config.model,
});
// Register slash commands
_registerBuiltinCommands();
// Initialize transcript file for JSONL persistence
if (!kIsWeb) {
_transcriptPath = '${SystemConstants.sessionDir}/${sessionId.value}.jsonl';
await _ensureTranscriptDir();
}
// Try to restore last session if no messages
if (messages.isEmpty && !kIsWeb) {
await _tryRestoreLastSession();
}
// Fire session_start lifecycle hook
await _hookExecutor.executeAsync(
HookType.onSessionStart,
HookContext.now(
hookType: HookType.onSessionStart,
sessionId: sessionId.value,
metadata: {
'provider': config.type.name,
'model': config.model,
},
),
);
update();
SintSentinel.logger.i(
'ChatController.initialize() completed — '
'session=${sessionId.value}, '
'compaction=${_compactionService != null}, '
'sessionMemory=${_sessionMemoryService != null}, '
'memdir=${_memdirService != null}, '
'transcript=${_transcriptPath != null}',
);
return true;
}