Documentation Index
Fetch the complete documentation index at: https://cloud-docs.mentra.glass/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The Session Service is the central coordinator for user session management in MentraOS Cloud. It handles session creation, retrieval, and transformation while delegating specialized tasks to the UserSession class and its managers.
File: packages/cloud/src/services/session/session.service.ts
Key Responsibilities
- Session Lifecycle Management: Creating and retrieving sessions
- Message Routing: Relaying messages between glasses and apps
- Settings Management: User and app-specific settings
- Session Transformation: Preparing session data for clients
- Audio Routing: Directing audio data to appropriate handlers
Session Creation
The service creates or retrieves sessions with automatic reconnection handling:
async createSession(ws: WebSocket, userId: string): Promise<{
userSession: UserSession,
reconnection: boolean
}> {
// Check for existing session
const existingSession = UserSession.getById(userId);
if (existingSession) {
// Reconnection scenario
existingSession.updateWebSocket(ws);
existingSession.disconnectedAt = null;
// Clear cleanup timer
if (existingSession.cleanupTimerId) {
clearTimeout(existingSession.cleanupTimerId);
existingSession.cleanupTimerId = undefined;
}
return { userSession: existingSession, reconnection: true };
}
// Create new session
const userSession = new UserSession(userId, ws);
// Fetch and populate installed apps
const installedApps = await appService.getAllApps(userId);
for (const app of installedApps) {
userSession.installedApps.set(app.packageName, app);
}
return { userSession: userSession, reconnection: false };
}
Reconnection Handling
When a user reconnects:
- Existing session is preserved
- WebSocket connection is updated
- Cleanup timers are cancelled
- Disconnection timestamp is cleared
Session Retrieval
Multiple methods for accessing sessions:
// By session ID
getSession(sessionId: string): UserSession | null
// By user ID (email)
getSessionByUserId(userId: string): UserSession | null
// All active sessions
getAllSessions(): UserSession[]
Prepares session data for client consumption with calculated requirements:
async transformUserSessionForClient(userSession: UserSession): Promise<any> {
// Collect app subscriptions
const appSubscriptions: Record<string, string[]> = {};
for (const packageName of userSession.runningApps) {
appSubscriptions[packageName] = subscriptionService.getAppSubscriptions(
userId,
packageName
);
}
// Calculate stream requirements
const hasPCMTranscriptionSubscriptions =
subscriptionService.hasPCMTranscriptionSubscriptions(userId);
const requiresAudio = hasPCMTranscriptionSubscriptions.hasMedia;
// Update microphone state based on requirements
const requiredData = userSession.microphoneManager.calculateRequiredData(
hasPCMTranscriptionSubscriptions.hasPCM,
hasPCMTranscriptionSubscriptions.hasTranscription
);
userSession.microphoneManager.updateState(requiresAudio, requiredData);
return {
userId,
startTime: userSession.startTime,
activeAppSessions: Array.from(userSession.runningApps),
loadingApps: Array.from(userSession.loadingApps),
appSubscriptions,
requiresAudio,
minimumTranscriptionLanguages,
isTranscribing: userSession.isTranscribing || false
};
}
Message Routing
Relay to Apps
Routes messages from glasses to subscribed apps:
relayMessageToApps(userSession: UserSession, data: GlassesToCloudMessage): void {
// Get subscribed apps
const subscribedPackageNames = subscriptionService.getSubscribedApps(
userSession,
data.type
);
// Send to each subscriber
for (const packageName of subscribedPackageNames) {
const connection = userSession.appWebsockets.get(packageName);
if (connection && connection.readyState === WebSocket.OPEN) {
const dataStream: DataStream = {
type: CloudToAppMessageType.DATA_STREAM,
sessionId: `${userSession.sessionId}-${packageName}`,
streamType: data.type as StreamType,
data,
timestamp: new Date()
};
connection.send(JSON.stringify(dataStream));
}
}
}
Audio Routing
Delegates audio processing to the AudioManager:
relayAudioToApps(userSession: UserSession, audioData: ArrayBuffer): void {
userSession.audioManager.processAudioData(audioData, false);
}
Audio Response Routing
Routes audio play responses back to requesting apps:
relayAudioPlayResponseToApp(userSession: UserSession, audioResponse: any): void {
const requestId = audioResponse.requestId;
// Find which app made the request
const packageName = userSession.audioPlayRequestMapping.get(requestId);
if (packageName) {
const connection = userSession.appWebsockets.get(packageName);
// Send response to app...
}
}
Settings Management
User Settings
Retrieves combined system and app settings:
async getUserSettings(userId: string): Promise<Record<string, any>> {
const user = await User.findOne({ email: userId });
if (!user) {
return DEFAULT_AUGMENTOS_SETTINGS;
}
// Get system settings
const augmentosSettings = user.getAugmentosSettings();
// Add app settings
const allSettings = {
...augmentosSettings,
appSettings: Object.fromEntries(user.appSettings || new Map())
};
return allSettings;
}
App-Specific Settings
async getAppSettings(userId: string, packageName: string): Promise<Record<string, any>> {
const allSettings = await this.getUserSettings(userId);
return allSettings.appSettings?.[packageName] || {};
}
Default Settings
System default settings when user settings are not available:
const DEFAULT_AUGMENTOS_SETTINGS = {
useOnboardMic: false,
contextualDashboard: true,
headUpAngle: 20,
brightness: 50,
autoBrightness: false,
sensingEnabled: true,
alwaysOnStatusBar: false,
bypassVad: false,
bypassAudioEncoding: false,
metricSystemEnabled: false
};
Error Handling
- Session Creation: Logs errors and re-throws for upstream handling
- Message Routing: Catches and logs send errors per app
- Settings Retrieval: Returns defaults on error
- Transformation: Returns minimal data on error
Integration Points
- UserSession: Core session object creation and management
- SubscriptionService: Determining app subscriptions and requirements
- AppService: Fetching installed apps
- User Model: Database access for settings
- AudioManager: Audio data processing
- MicrophoneManager: Microphone state management
Best Practices
- Always check WebSocket state before sending messages
- Handle reconnections gracefully by preserving session state
- Return sensible defaults when data is unavailable
- Log errors with context for debugging
- Delegate specialized tasks to appropriate managers