@mentra/sdk 2.1.29-beta.2 → 2.1.31-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/app/server/index.d.ts +2 -1
  2. package/dist/app/server/index.d.ts.map +1 -1
  3. package/dist/app/session/device-state.d.ts +83 -0
  4. package/dist/app/session/device-state.d.ts.map +1 -0
  5. package/dist/app/session/events.d.ts +9 -0
  6. package/dist/app/session/events.d.ts.map +1 -1
  7. package/dist/app/session/index.d.ts +23 -3
  8. package/dist/app/session/index.d.ts.map +1 -1
  9. package/dist/index.d.ts +6 -3
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +251 -38
  12. package/dist/index.js.map +13 -11
  13. package/dist/types/capabilities.d.ts +3 -90
  14. package/dist/types/capabilities.d.ts.map +1 -1
  15. package/dist/types/index.d.ts +1 -1
  16. package/dist/types/index.d.ts.map +1 -1
  17. package/dist/types/message-types.d.ts +3 -1
  18. package/dist/types/message-types.d.ts.map +1 -1
  19. package/dist/types/messages/app-to-cloud.d.ts +15 -1
  20. package/dist/types/messages/app-to-cloud.d.ts.map +1 -1
  21. package/dist/types/messages/cloud-to-app.d.ts +14 -1
  22. package/dist/types/messages/cloud-to-app.d.ts.map +1 -1
  23. package/dist/utils/Observable.d.ts +92 -0
  24. package/dist/utils/Observable.d.ts.map +1 -0
  25. package/node_modules/@mentra/types/README.md +134 -0
  26. package/node_modules/@mentra/types/dist/applet.d.ts +39 -0
  27. package/node_modules/@mentra/types/dist/applet.d.ts.map +1 -0
  28. package/node_modules/@mentra/types/dist/applet.js +5 -0
  29. package/node_modules/@mentra/types/dist/capabilities/even-realities-g1.d.ts +12 -0
  30. package/node_modules/@mentra/types/dist/capabilities/even-realities-g1.d.ts.map +1 -0
  31. package/node_modules/@mentra/types/dist/capabilities/even-realities-g1.js +54 -0
  32. package/node_modules/@mentra/types/dist/capabilities/mentra-live.d.ts +12 -0
  33. package/node_modules/@mentra/types/dist/capabilities/mentra-live.d.ts.map +1 -0
  34. package/node_modules/@mentra/types/dist/capabilities/mentra-live.js +94 -0
  35. package/node_modules/@mentra/types/dist/capabilities/simulated-glasses.d.ts +13 -0
  36. package/node_modules/@mentra/types/dist/capabilities/simulated-glasses.d.ts.map +1 -0
  37. package/node_modules/@mentra/types/dist/capabilities/simulated-glasses.js +67 -0
  38. package/node_modules/@mentra/types/dist/capabilities/vuzix-z100.d.ts +12 -0
  39. package/node_modules/@mentra/types/dist/capabilities/vuzix-z100.d.ts.map +1 -0
  40. package/node_modules/@mentra/types/dist/capabilities/vuzix-z100.js +51 -0
  41. package/node_modules/@mentra/types/dist/cli.d.ts +130 -0
  42. package/node_modules/@mentra/types/dist/cli.d.ts.map +1 -0
  43. package/node_modules/@mentra/types/dist/cli.js +7 -0
  44. package/node_modules/@mentra/types/dist/device.d.ts +32 -0
  45. package/node_modules/@mentra/types/dist/device.d.ts.map +1 -0
  46. package/node_modules/@mentra/types/dist/device.js +6 -0
  47. package/node_modules/@mentra/types/dist/enums.d.ts +34 -0
  48. package/node_modules/@mentra/types/dist/enums.d.ts.map +1 -0
  49. package/node_modules/@mentra/types/dist/enums.js +39 -0
  50. package/node_modules/@mentra/types/dist/hardware.d.ts +141 -0
  51. package/node_modules/@mentra/types/dist/hardware.d.ts.map +1 -0
  52. package/node_modules/@mentra/types/dist/hardware.js +33 -0
  53. package/node_modules/@mentra/types/dist/index.d.ts +18 -0
  54. package/node_modules/@mentra/types/dist/index.d.ts.map +1 -0
  55. package/node_modules/@mentra/types/dist/index.js +25 -0
  56. package/node_modules/@mentra/types/package.json +31 -0
  57. package/package.json +6 -6
  58. package/dist/display-utils/test/ScrollView.test.d.ts +0 -2
  59. package/dist/display-utils/test/ScrollView.test.d.ts.map +0 -1
  60. package/dist/display-utils/test/TextMeasurer.test.d.ts +0 -2
  61. package/dist/display-utils/test/TextMeasurer.test.d.ts.map +0 -1
  62. package/dist/display-utils/test/TextWrapper.test.d.ts +0 -2
  63. package/dist/display-utils/test/TextWrapper.test.d.ts.map +0 -1
package/dist/index.js.map CHANGED
@@ -1,26 +1,26 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/types/streams.ts", "../src/types/message-types.ts", "../src/types/dashboard/index.ts", "../src/app/session/dashboard.ts", "../src/app/token/utils.ts", "../src/index.ts", "../src/types/messages/glasses-to-cloud.ts", "../src/types/messages/cloud-to-glasses.ts", "../src/types/messages/app-to-cloud.ts", "../src/utils/bitmap-utils.ts", "../src/utils/animation-utils.ts", "../src/types/messages/cloud-to-app.ts", "../src/types/enums.ts", "../src/types/models.ts", "../src/types/webhooks.ts", "../src/app/server/index.ts", "../src/app/session/index.ts", "../src/app/session/events.ts", "../src/types/index.ts", "../src/constants/log-messages/warning.ts", "../src/constants/log-messages/logos.ts", "../src/utils/permissions-utils.ts", "../src/app/session/layouts.ts", "../src/app/session/settings.ts", "../src/app/session/api-client.ts", "../src/logging/logger.ts", "../src/app/session/modules/location.ts", "../src/app/session/modules/camera.ts", "../src/app/session/modules/camera-managed-extension.ts", "../src/app/session/modules/led.ts", "../src/app/session/modules/audio.ts", "../src/utils/resource-tracker.ts", "../src/app/session/modules/simple-storage.ts", "../src/app/webview/index.ts", "../src/constants/log-messages/updates.ts", "../src/app/token/index.ts"],
3
+ "sources": ["../src/types/streams.ts", "../src/types/message-types.ts", "../src/types/dashboard/index.ts", "../src/app/session/dashboard.ts", "../src/app/token/utils.ts", "../src/index.ts", "../src/types/messages/glasses-to-cloud.ts", "../src/types/messages/cloud-to-glasses.ts", "../src/types/messages/app-to-cloud.ts", "../src/utils/bitmap-utils.ts", "../src/utils/animation-utils.ts", "../src/types/messages/cloud-to-app.ts", "../src/types/enums.ts", "../src/types/models.ts", "../src/types/webhooks.ts", "../src/app/server/index.ts", "../src/app/session/index.ts", "../src/app/session/events.ts", "../src/types/index.ts", "../src/constants/log-messages/warning.ts", "../src/constants/log-messages/logos.ts", "../src/utils/permissions-utils.ts", "../src/app/session/layouts.ts", "../src/app/session/settings.ts", "../src/app/session/api-client.ts", "../src/logging/logger.ts", "../src/app/session/modules/location.ts", "../src/app/session/modules/camera.ts", "../src/app/session/modules/camera-managed-extension.ts", "../src/app/session/modules/led.ts", "../src/app/session/modules/audio.ts", "../src/utils/resource-tracker.ts", "../src/app/session/modules/simple-storage.ts", "../src/utils/Observable.ts", "../src/app/session/device-state.ts", "../src/app/webview/index.ts", "../src/constants/log-messages/updates.ts", "../src/app/token/index.ts"],
4
4
  "sourcesContent": [
5
5
  "// src/streams.ts\n\n/**\n * Types of streams that Apps can subscribe to\n *\n * These are events and data that Apps can receive from the cloud.\n * Not all message types can be subscribed to as streams.\n */\nexport enum StreamType {\n // Hardware streams\n BUTTON_PRESS = \"button_press\",\n HEAD_POSITION = \"head_position\",\n TOUCH_EVENT = \"touch_event\",\n GLASSES_BATTERY_UPDATE = \"glasses_battery_update\",\n PHONE_BATTERY_UPDATE = \"phone_battery_update\",\n GLASSES_CONNECTION_STATE = \"glasses_connection_state\",\n LOCATION_UPDATE = \"location_update\",\n LOCATION_STREAM = \"location_stream\",\n VPS_COORDINATES = \"vps_coordinates\",\n\n // Audio streams\n TRANSCRIPTION = \"transcription\",\n TRANSLATION = \"translation\",\n VAD = \"VAD\",\n AUDIO_CHUNK = \"audio_chunk\",\n\n // Phone streams\n PHONE_NOTIFICATION = \"phone_notification\",\n PHONE_NOTIFICATION_DISMISSED = \"phone_notification_dismissed\",\n CALENDAR_EVENT = \"calendar_event\",\n\n // System streams\n START_APP = \"start_app\",\n STOP_APP = \"stop_app\",\n OPEN_DASHBOARD = \"open_dashboard\",\n CORE_STATUS_UPDATE = \"core_status_update\",\n\n // Video streams\n VIDEO = \"video\",\n PHOTO_REQUEST = \"photo_request\",\n PHOTO_RESPONSE = \"photo_response\",\n RTMP_STREAM_STATUS = \"rtmp_stream_status\",\n MANAGED_STREAM_STATUS = \"managed_stream_status\",\n\n // Special subscription types\n ALL = \"all\",\n WILDCARD = \"*\",\n\n // New stream type\n MENTRAOS_SETTINGS_UPDATE_REQUEST = \"settings_update_request\",\n CUSTOM_MESSAGE = \"custom_message\",\n PHOTO_TAKEN = \"photo_taken\",\n}\n\n/**\n * Extended StreamType to support language-specific streams\n * This allows us to treat language-specific strings as StreamType values\n */\nexport type ExtendedStreamType = StreamType | string\n\n/**\n * Categories of stream data\n */\nexport enum StreamCategory {\n /** Data from hardware sensors */\n HARDWARE = \"hardware\",\n\n /** Audio processing results */\n AUDIO = \"audio\",\n\n /** Phone-related events */\n PHONE = \"phone\",\n\n /** System-level events */\n SYSTEM = \"system\",\n}\n\n/**\n * Map of stream categories for each stream type\n */\nexport const STREAM_CATEGORIES: Record<StreamType, StreamCategory> = {\n [StreamType.BUTTON_PRESS]: StreamCategory.HARDWARE,\n [StreamType.HEAD_POSITION]: StreamCategory.HARDWARE,\n [StreamType.TOUCH_EVENT]: StreamCategory.HARDWARE,\n [StreamType.GLASSES_BATTERY_UPDATE]: StreamCategory.HARDWARE,\n [StreamType.PHONE_BATTERY_UPDATE]: StreamCategory.HARDWARE,\n [StreamType.GLASSES_CONNECTION_STATE]: StreamCategory.HARDWARE,\n [StreamType.LOCATION_UPDATE]: StreamCategory.HARDWARE,\n [StreamType.LOCATION_STREAM]: StreamCategory.HARDWARE,\n [StreamType.VPS_COORDINATES]: StreamCategory.HARDWARE,\n\n [StreamType.TRANSCRIPTION]: StreamCategory.AUDIO,\n [StreamType.TRANSLATION]: StreamCategory.AUDIO,\n [StreamType.VAD]: StreamCategory.AUDIO,\n [StreamType.AUDIO_CHUNK]: StreamCategory.AUDIO,\n\n [StreamType.PHONE_NOTIFICATION]: StreamCategory.PHONE,\n [StreamType.PHONE_NOTIFICATION_DISMISSED]: StreamCategory.PHONE,\n [StreamType.CALENDAR_EVENT]: StreamCategory.PHONE,\n [StreamType.START_APP]: StreamCategory.SYSTEM,\n [StreamType.STOP_APP]: StreamCategory.SYSTEM,\n [StreamType.OPEN_DASHBOARD]: StreamCategory.SYSTEM,\n [StreamType.CORE_STATUS_UPDATE]: StreamCategory.SYSTEM,\n\n [StreamType.VIDEO]: StreamCategory.HARDWARE,\n [StreamType.PHOTO_REQUEST]: StreamCategory.HARDWARE,\n [StreamType.PHOTO_RESPONSE]: StreamCategory.HARDWARE,\n [StreamType.RTMP_STREAM_STATUS]: StreamCategory.HARDWARE,\n [StreamType.MANAGED_STREAM_STATUS]: StreamCategory.HARDWARE,\n [StreamType.ALL]: StreamCategory.SYSTEM,\n [StreamType.WILDCARD]: StreamCategory.SYSTEM,\n\n [StreamType.MENTRAOS_SETTINGS_UPDATE_REQUEST]: StreamCategory.SYSTEM,\n [StreamType.CUSTOM_MESSAGE]: StreamCategory.SYSTEM,\n [StreamType.PHOTO_TAKEN]: StreamCategory.HARDWARE,\n}\n\n/**\n * Branded type for TypeScript to recognize language-specific stream types\n * This helps maintain type safety when using language-specific streams\n */\nexport type LanguageStreamType<T extends string> = T & {\n __languageStreamBrand: never\n}\n\n/**\n * Create a language-branded stream type\n * This is a type helper to ensure type safety for language-specific streams\n */\nfunction createLanguageStream<T extends string>(type: T): LanguageStreamType<T> {\n return type as LanguageStreamType<T>\n}\n\n/**\n * Structure of a parsed language stream subscription\n */\nexport interface LanguageStreamInfo {\n type: StreamType // Base stream type (e.g., TRANSCRIPTION)\n baseType: string // String representation of base type (e.g., \"transcription\")\n transcribeLanguage: string // Source language code (e.g., \"en-US\")\n translateLanguage?: string // Target language code for translations (e.g., \"es-ES\")\n options?: Record<string, string | boolean> // Query parameters/options\n original: ExtendedStreamType // Original subscription string\n}\n\n/**\n * Check if a string is a valid language code\n * Simple validation for language code format: xx-XX (e.g., en-US)\n */\nexport function isValidLanguageCode(code: string): boolean {\n return /^[a-z]{2,3}-[A-Z]{2}$/.test(code)\n}\n\n/**\n * Parse a subscription string to extract language information\n *\n * @param subscription Subscription string (e.g., \"transcription:en-US\" or \"translation:es-ES-to-en-US\" or \"transcription:en-US?no-language-identification=true\")\n * @returns Parsed language stream info or null if not a language-specific subscription\n */\nexport function parseLanguageStream(subscription: ExtendedStreamType): LanguageStreamInfo | null {\n // console.log(`🎤 Parsing language stream: ${subscription}`);\n\n if (typeof subscription !== \"string\") {\n return null\n }\n\n // Handle transcription format (transcription:en-US or transcription:en-US?options)\n if (subscription.startsWith(`${StreamType.TRANSCRIPTION}:`)) {\n const [baseType, rest] = subscription.split(\":\")\n const [languageCode, queryString] = rest?.split(\"?\") ?? []\n\n if (languageCode && isValidLanguageCode(languageCode)) {\n const options: Record<string, string | boolean> = {}\n\n // Parse query parameters if present\n if (queryString) {\n const params = new URLSearchParams(queryString)\n for (const [key, value] of params.entries()) {\n // Convert string values to boolean when appropriate\n if (value === \"true\") {\n options[key] = true\n } else if (value === \"false\") {\n options[key] = false\n } else {\n options[key] = value\n }\n }\n }\n\n return {\n type: StreamType.TRANSCRIPTION,\n baseType,\n transcribeLanguage: languageCode,\n options: Object.keys(options).length > 0 ? options : undefined,\n original: subscription,\n }\n }\n }\n\n // Handle translation format (translation:es-ES-to-en-US, translation:all-to-en-US, or with ?options)\n if (subscription.startsWith(`${StreamType.TRANSLATION}:`)) {\n const [baseType, rest] = subscription.split(\":\")\n const [languagePair, queryString] = rest?.split(\"?\") ?? []\n const [sourceLanguage, targetLanguage] = languagePair?.split(\"-to-\") ?? []\n\n // Check for \"all-to-LANG\" format (one-way translation from any language)\n const isAllToFormat = sourceLanguage === \"all\" && targetLanguage && isValidLanguageCode(targetLanguage)\n\n // Check for \"LANG-to-LANG\" format (two-way translation between specific languages)\n const isSpecificPairFormat =\n sourceLanguage && targetLanguage && isValidLanguageCode(sourceLanguage) && isValidLanguageCode(targetLanguage)\n\n if (isAllToFormat || isSpecificPairFormat) {\n const options: Record<string, string | boolean> = {}\n\n // Parse query parameters if present\n if (queryString) {\n const params = new URLSearchParams(queryString)\n for (const [key, value] of params.entries()) {\n // Convert string values to boolean when appropriate\n if (value === \"true\") {\n options[key] = true\n } else if (value === \"false\") {\n options[key] = false\n } else {\n options[key] = value\n }\n }\n }\n\n return {\n type: StreamType.TRANSLATION,\n baseType,\n transcribeLanguage: sourceLanguage, // \"all\" for all-to-LANG, or specific language code\n translateLanguage: targetLanguage,\n options: Object.keys(options).length > 0 ? options : undefined,\n original: subscription,\n }\n }\n }\n\n return null\n}\n\n/**\n * Create a transcription stream identifier for a specific language\n * Returns a type-safe stream type that can be used like a StreamType\n *\n * @param language Language code (e.g., \"en-US\") or \"auto\" for automatic detection\n * @param options Optional configuration options\n * @returns Typed stream identifier\n */\nexport function createTranscriptionStream(\n language: string,\n options?: {\n disableLanguageIdentification?: boolean\n hints?: string[]\n },\n): ExtendedStreamType {\n console.log(`🎤 Creating transcription stream for language: ${language}`)\n console.log(`🎤 Options: ${JSON.stringify(options)}`)\n\n // Defensively remove any query string from the language parameter\n const languageCode = language.split(\"?\")[0]\n\n if (languageCode !== \"auto\" && !isValidLanguageCode(languageCode)) {\n throw new Error(`Invalid language code: ${languageCode}`)\n }\n\n const base = `${StreamType.TRANSCRIPTION}:${languageCode}`\n const params = new URLSearchParams()\n\n if (options?.disableLanguageIdentification) {\n params.set(\"no-language-identification\", \"true\")\n }\n\n if (options?.hints && options.hints.length > 0) {\n params.set(\"hints\", options.hints.join(\",\"))\n }\n\n const queryString = params.toString()\n return queryString ? (`${base}?${queryString}` as ExtendedStreamType) : (base as ExtendedStreamType)\n}\n\n/**\n * Create a translation stream identifier for a language pair\n * Returns a type-safe stream type that can be used like a StreamType\n *\n * @param sourceLanguage Source language code (e.g., \"es-ES\") or \"all\" for one-way translation\n * @param targetLanguage Target language code (e.g., \"en-US\")\n * @param options Optional configuration options\n * @returns Typed stream identifier\n */\nexport function createTranslationStream(\n sourceLanguage: string,\n targetLanguage: string,\n options?: {disableLanguageIdentification?: boolean},\n): ExtendedStreamType {\n // Defensively remove any query string from the language parameters\n const cleanSourceLanguage = sourceLanguage.split(\"?\")[0]\n const cleanTargetLanguage = targetLanguage.split(\"?\")[0]\n\n // Support \"all\" as source for one-way translation (all languages → target)\n const isAllToFormat = cleanSourceLanguage === \"all\"\n\n if ((!isAllToFormat && !isValidLanguageCode(cleanSourceLanguage)) || !isValidLanguageCode(cleanTargetLanguage)) {\n throw new Error(`Invalid language code(s): ${cleanSourceLanguage}, ${cleanTargetLanguage}`)\n }\n const base = `${StreamType.TRANSLATION}:${cleanSourceLanguage}-to-${cleanTargetLanguage}`\n if (options?.disableLanguageIdentification) {\n return `${base}?no-language-identification=true` as ExtendedStreamType\n }\n return createLanguageStream(base)\n}\n\n/**\n * Parse a touch event subscription to extract gesture information\n * @param subscription Subscription string (e.g., \"touch_event:forward_swipe\")\n * @returns Gesture name or null if not a gesture-specific subscription\n */\nexport function parseTouchEventStream(subscription: ExtendedStreamType): string | null {\n if (typeof subscription !== \"string\") {\n return null\n }\n\n if (subscription.startsWith(`${StreamType.TOUCH_EVENT}:`)) {\n const [, gestureName] = subscription.split(\":\")\n const validGestures = [\n \"single_tap\",\n \"double_tap\",\n \"triple_tap\",\n \"long_press\",\n \"forward_swipe\",\n \"backward_swipe\",\n \"up_swipe\",\n \"down_swipe\",\n ]\n\n if (gestureName && validGestures.includes(gestureName)) {\n return gestureName\n }\n }\n\n return null\n}\n\n/**\n * Create a touch event subscription for a specific gesture\n * @param gesture Gesture name (e.g., \"forward_swipe\")\n * @returns Typed stream identifier\n */\nexport function createTouchEventStream(gesture: string): ExtendedStreamType {\n const validGestures = [\n \"single_tap\",\n \"double_tap\",\n \"triple_tap\",\n \"long_press\",\n \"forward_swipe\",\n \"backward_swipe\",\n \"up_swipe\",\n \"down_swipe\",\n ]\n\n if (!validGestures.includes(gesture)) {\n throw new Error(`Invalid gesture: ${gesture}`)\n }\n\n return `${StreamType.TOUCH_EVENT}:${gesture}` as ExtendedStreamType\n}\n\n/**\n * Create a universal translation stream identifier that translates from any language to target\n * This is useful when you want to support all languages translating to a single target\n * Returns a type-safe stream type that can be used like a StreamType\n *\n * Example: createUniversalTranslationStream('es-ES') creates \"translation:all-to-es-ES\"\n *\n * @param targetLanguage Target language code (e.g., \"es-ES\")\n * @param options Optional configuration options\n * @returns Typed stream identifier\n */\nexport function createUniversalTranslationStream(\n targetLanguage: string,\n options?: {disableLanguageIdentification?: boolean},\n): ExtendedStreamType {\n const cleanTargetLanguage = targetLanguage.split(\"?\")[0]\n\n if (!isValidLanguageCode(cleanTargetLanguage)) {\n throw new Error(`Invalid target language code: ${cleanTargetLanguage}`)\n }\n\n const base = `${StreamType.TRANSLATION}:all-to-${cleanTargetLanguage}`\n if (options?.disableLanguageIdentification) {\n return `${base}?no-language-identification=true` as ExtendedStreamType\n }\n return createLanguageStream(base)\n}\n\n/**\n * Check if a subscription is a valid stream type\n * This handles both enum-based StreamType values and language-specific stream formats\n *\n * @param subscription Subscription to validate\n * @returns True if valid, false otherwise\n */\nexport function isValidStreamType(subscription: ExtendedStreamType): boolean {\n // Check if it's a standard StreamType\n if (Object.values(StreamType).includes(subscription as StreamType)) {\n return true\n }\n\n // Check if it's a valid language-specific stream\n const languageStream = parseLanguageStream(subscription)\n if (languageStream !== null) {\n return true\n }\n\n // Check if it's a valid gesture-specific stream\n const gestureStream = parseTouchEventStream(subscription)\n if (gestureStream !== null) {\n return true\n }\n\n return false\n}\n\n/**\n * Helper function to check if a stream type is of a particular category\n * Works with both standard and language-specific stream types\n */\nexport function isStreamCategory(streamType: ExtendedStreamType, category: StreamCategory): boolean {\n const baseType = getBaseStreamType(streamType)\n return baseType ? STREAM_CATEGORIES[baseType] === category : false\n}\n\n/**\n * Helper function to get all stream types in a category\n */\nexport function getStreamTypesByCategory(category: StreamCategory): StreamType[] {\n return Object.entries(STREAM_CATEGORIES)\n .filter(([_, cat]) => cat === category)\n .map(([type]) => type as StreamType)\n}\n\n/**\n * Get the base StreamType for a subscription\n * Works with both standard StreamType values and language-specific formats\n *\n * @param subscription Subscription string or StreamType\n * @returns The base StreamType enum value\n */\nexport function getBaseStreamType(subscription: ExtendedStreamType): StreamType | null {\n // Check if it's already a standard StreamType\n if (Object.values(StreamType).includes(subscription as StreamType)) {\n return subscription as StreamType\n }\n\n // Check if it's a language-specific stream\n const languageStream = parseLanguageStream(subscription)\n if (languageStream) {\n return languageStream.type\n }\n\n // Check if it's a gesture-specific stream\n const gestureStream = parseTouchEventStream(subscription)\n if (gestureStream) {\n return StreamType.TOUCH_EVENT\n }\n\n return null\n}\n\n/**\n * Check if a stream is a language-specific stream\n */\nexport function isLanguageStream(subscription: ExtendedStreamType): boolean {\n return parseLanguageStream(subscription) !== null\n}\n\n/**\n * Get language information from a stream type\n * Returns null for regular stream types\n */\nexport function getLanguageInfo(subscription: ExtendedStreamType): LanguageStreamInfo | null {\n return parseLanguageStream(subscription)\n}\n\n// this is the blueprint for our new rich subscription object\n// it allows a developer to specify a rate for the location stream\nexport interface LocationStreamRequest {\n stream: \"location_stream\"\n rate: \"standard\" | \"high\" | \"realtime\" | \"tenMeters\" | \"hundredMeters\" | \"kilometer\" | \"threeKilometers\" | \"reduced\"\n}\n",
6
- "// src/message-types.ts\n\nimport {StreamType} from \"./streams\"\n\n/**\n * Types of messages from glasses to cloud\n */\nexport enum GlassesToCloudMessageType {\n // Control actions\n CONNECTION_INIT = \"connection_init\",\n REQUEST_SETTINGS = \"request_settings\",\n\n START_APP = StreamType.START_APP,\n STOP_APP = StreamType.STOP_APP,\n\n DASHBOARD_STATE = \"dashboard_state\",\n OPEN_DASHBOARD = StreamType.OPEN_DASHBOARD,\n\n // Mentra Live\n PHOTO_RESPONSE = StreamType.PHOTO_RESPONSE,\n\n // Local Transcription\n LOCAL_TRANSCRIPTION = \"local_transcription\",\n\n // RTMP streaming\n RTMP_STREAM_STATUS = StreamType.RTMP_STREAM_STATUS,\n KEEP_ALIVE_ACK = \"keep_alive_ack\",\n\n BUTTON_PRESS = StreamType.BUTTON_PRESS,\n HEAD_POSITION = StreamType.HEAD_POSITION,\n TOUCH_EVENT = StreamType.TOUCH_EVENT,\n GLASSES_BATTERY_UPDATE = StreamType.GLASSES_BATTERY_UPDATE,\n PHONE_BATTERY_UPDATE = StreamType.PHONE_BATTERY_UPDATE,\n GLASSES_CONNECTION_STATE = StreamType.GLASSES_CONNECTION_STATE,\n LOCATION_UPDATE = StreamType.LOCATION_UPDATE,\n\n // TODO(isaiah): Remove VPS_COORDINATES once confirmed we don't use this system.\n VPS_COORDINATES = StreamType.VPS_COORDINATES,\n VAD = StreamType.VAD,\n\n // TODO(isaiah): Remove PHONE_NOTIFICATION, and PHONE_NOTIFICATION_DISMISSED after moving to REST request.\n PHONE_NOTIFICATION = StreamType.PHONE_NOTIFICATION,\n PHONE_NOTIFICATION_DISMISSED = StreamType.PHONE_NOTIFICATION_DISMISSED,\n\n // TODO(isaiah): Remove CALENDAR_EVENT after moving to REST request.\n CALENDAR_EVENT = StreamType.CALENDAR_EVENT,\n MENTRAOS_SETTINGS_UPDATE_REQUEST = StreamType.MENTRAOS_SETTINGS_UPDATE_REQUEST,\n\n // TODO(isaiah): Remove CORE_STATUS_UPDATE after moving to REST request.\n CORE_STATUS_UPDATE = StreamType.CORE_STATUS_UPDATE,\n\n PHOTO_TAKEN = StreamType.PHOTO_TAKEN,\n AUDIO_PLAY_RESPONSE = \"audio_play_response\",\n\n // RGB LED control\n RGB_LED_CONTROL_RESPONSE = \"rgb_led_control_response\",\n\n // LiveKit handshake\n LIVEKIT_INIT = \"livekit_init\",\n}\n\n/**\n * Types of messages from cloud to glasses\n */\nexport enum CloudToGlassesMessageType {\n // Responses\n CONNECTION_ACK = \"connection_ack\",\n CONNECTION_ERROR = \"connection_error\",\n AUTH_ERROR = \"auth_error\",\n\n // Updates\n DISPLAY_EVENT = \"display_event\",\n APP_STATE_CHANGE = \"app_state_change\",\n MICROPHONE_STATE_CHANGE = \"microphone_state_change\",\n SETTINGS_UPDATE = \"settings_update\",\n\n // Requests\n PHOTO_REQUEST = \"photo_request\",\n AUDIO_PLAY_REQUEST = \"audio_play_request\",\n AUDIO_STOP_REQUEST = \"audio_stop_request\",\n RGB_LED_CONTROL = \"rgb_led_control\",\n SHOW_WIFI_SETUP = \"show_wifi_setup\",\n\n // RTMP streaming\n START_RTMP_STREAM = \"start_rtmp_stream\",\n STOP_RTMP_STREAM = \"stop_rtmp_stream\",\n KEEP_RTMP_STREAM_ALIVE = \"keep_rtmp_stream_alive\",\n\n // Dashboard updates\n DASHBOARD_MODE_CHANGE = \"dashboard_mode_change\",\n DASHBOARD_ALWAYS_ON_CHANGE = \"dashboard_always_on_change\",\n\n // Location Service\n SET_LOCATION_TIER = \"set_location_tier\",\n REQUEST_SINGLE_LOCATION = \"request_single_location\",\n\n WEBSOCKET_ERROR = \"websocket_error\",\n\n // LiveKit info (URL, room, token)\n LIVEKIT_INFO = \"livekit_info\",\n}\n\n/**\n * Types of messages from Apps to cloud\n */\nexport enum AppToCloudMessageType {\n // Commands\n CONNECTION_INIT = \"tpa_connection_init\",\n SUBSCRIPTION_UPDATE = \"subscription_update\",\n LOCATION_POLL_REQUEST = \"location_poll_request\",\n\n // Requests\n DISPLAY_REQUEST = \"display_event\",\n PHOTO_REQUEST = \"photo_request\",\n AUDIO_PLAY_REQUEST = \"audio_play_request\",\n AUDIO_STOP_REQUEST = \"audio_stop_request\",\n RGB_LED_CONTROL = \"rgb_led_control\",\n REQUEST_WIFI_SETUP = \"request_wifi_setup\",\n\n // RTMP streaming\n RTMP_STREAM_REQUEST = \"rtmp_stream_request\",\n RTMP_STREAM_STOP = \"rtmp_stream_stop\",\n\n // Managed RTMP streaming\n MANAGED_STREAM_REQUEST = \"managed_stream_request\",\n MANAGED_STREAM_STOP = \"managed_stream_stop\",\n\n // Stream status check (both managed and unmanaged)\n STREAM_STATUS_CHECK = \"stream_status_check\",\n\n // Dashboard requests\n DASHBOARD_CONTENT_UPDATE = \"dashboard_content_update\",\n DASHBOARD_MODE_CHANGE = \"dashboard_mode_change\",\n DASHBOARD_SYSTEM_UPDATE = \"dashboard_system_update\",\n\n // TODO(isaiah): Remove after confirming not in use.\n // App-to-App Communication\n APP_BROADCAST_MESSAGE = \"app_broadcast_message\",\n APP_DIRECT_MESSAGE = \"app_direct_message\",\n APP_USER_DISCOVERY = \"app_user_discovery\",\n APP_ROOM_JOIN = \"app_room_join\",\n APP_ROOM_LEAVE = \"app_room_leave\",\n}\n\n/**\n * Types of messages from cloud to Apps\n */\nexport enum CloudToAppMessageType {\n // Responses\n CONNECTION_ACK = \"tpa_connection_ack\",\n CONNECTION_ERROR = \"tpa_connection_error\",\n\n // Updates\n APP_STOPPED = \"app_stopped\",\n SETTINGS_UPDATE = \"settings_update\",\n CAPABILITIES_UPDATE = \"capabilities_update\",\n\n // Dashboard updates\n DASHBOARD_MODE_CHANGED = \"dashboard_mode_changed\",\n DASHBOARD_ALWAYS_ON_CHANGED = \"dashboard_always_on_changed\",\n\n // Stream data\n DATA_STREAM = \"data_stream\",\n\n // Media responses\n PHOTO_RESPONSE = \"photo_response\",\n AUDIO_PLAY_RESPONSE = \"audio_play_response\",\n RGB_LED_CONTROL_RESPONSE = \"rgb_led_control_response\",\n RTMP_STREAM_STATUS = \"rtmp_stream_status\",\n MANAGED_STREAM_STATUS = \"managed_stream_status\",\n STREAM_STATUS_CHECK_RESPONSE = \"stream_status_check_response\",\n\n WEBSOCKET_ERROR = \"websocket_error\",\n\n // Permissions\n PERMISSION_ERROR = \"permission_error\",\n\n // General purpose messaging\n CUSTOM_MESSAGE = \"custom_message\",\n\n // TODO(isaiah): Remove after confirming not in use.\n // App-to-App Communication Responses\n APP_MESSAGE_RECEIVED = \"app_message_received\",\n APP_USER_JOINED = \"app_user_joined\",\n APP_USER_LEFT = \"app_user_left\",\n APP_ROOM_UPDATED = \"app_room_updated\",\n APP_DIRECT_MESSAGE_RESPONSE = \"app_direct_message_response\",\n}\n\n/**\n * Control action message types (subset of GlassesToCloudMessageType)\n */\nexport const ControlActionTypes = [\n GlassesToCloudMessageType.CONNECTION_INIT,\n GlassesToCloudMessageType.START_APP,\n GlassesToCloudMessageType.STOP_APP,\n GlassesToCloudMessageType.DASHBOARD_STATE,\n GlassesToCloudMessageType.OPEN_DASHBOARD,\n] as const\n\n/**\n * Event message types (subset of GlassesToCloudMessageType)\n */\nexport const EventTypes = [\n GlassesToCloudMessageType.BUTTON_PRESS,\n GlassesToCloudMessageType.HEAD_POSITION,\n GlassesToCloudMessageType.GLASSES_BATTERY_UPDATE,\n GlassesToCloudMessageType.PHONE_BATTERY_UPDATE,\n GlassesToCloudMessageType.GLASSES_CONNECTION_STATE,\n GlassesToCloudMessageType.LOCATION_UPDATE,\n GlassesToCloudMessageType.VPS_COORDINATES,\n GlassesToCloudMessageType.VAD,\n GlassesToCloudMessageType.PHONE_NOTIFICATION,\n GlassesToCloudMessageType.PHONE_NOTIFICATION_DISMISSED,\n GlassesToCloudMessageType.CALENDAR_EVENT,\n GlassesToCloudMessageType.MENTRAOS_SETTINGS_UPDATE_REQUEST,\n GlassesToCloudMessageType.CORE_STATUS_UPDATE,\n GlassesToCloudMessageType.LOCAL_TRANSCRIPTION,\n] as const\n\n/**\n * Response message types (subset of CloudToGlassesMessageType)\n */\nexport const ResponseTypes = [\n CloudToGlassesMessageType.CONNECTION_ACK,\n CloudToGlassesMessageType.CONNECTION_ERROR,\n CloudToGlassesMessageType.AUTH_ERROR,\n] as const\n\n/**\n * Update message types (subset of CloudToGlassesMessageType)\n */\nexport const UpdateTypes = [\n CloudToGlassesMessageType.DISPLAY_EVENT,\n CloudToGlassesMessageType.APP_STATE_CHANGE,\n CloudToGlassesMessageType.MICROPHONE_STATE_CHANGE,\n CloudToGlassesMessageType.PHOTO_REQUEST,\n CloudToGlassesMessageType.AUDIO_PLAY_REQUEST,\n CloudToGlassesMessageType.AUDIO_STOP_REQUEST,\n CloudToGlassesMessageType.RGB_LED_CONTROL,\n CloudToGlassesMessageType.SETTINGS_UPDATE,\n CloudToGlassesMessageType.DASHBOARD_MODE_CHANGE,\n CloudToGlassesMessageType.DASHBOARD_ALWAYS_ON_CHANGE,\n CloudToGlassesMessageType.START_RTMP_STREAM,\n CloudToGlassesMessageType.STOP_RTMP_STREAM,\n CloudToGlassesMessageType.KEEP_RTMP_STREAM_ALIVE,\n CloudToGlassesMessageType.LIVEKIT_INFO,\n] as const\n\n/**\n * Dashboard message types\n */\nexport const DashboardMessageTypes = [\n AppToCloudMessageType.DASHBOARD_CONTENT_UPDATE,\n AppToCloudMessageType.DASHBOARD_MODE_CHANGE,\n AppToCloudMessageType.DASHBOARD_SYSTEM_UPDATE,\n CloudToAppMessageType.DASHBOARD_MODE_CHANGED,\n CloudToAppMessageType.DASHBOARD_ALWAYS_ON_CHANGED,\n] as const\n",
6
+ "// src/message-types.ts\n\nimport {StreamType} from \"./streams\"\n\n/**\n * Types of messages from glasses to cloud\n */\nexport enum GlassesToCloudMessageType {\n // Control actions\n CONNECTION_INIT = \"connection_init\",\n REQUEST_SETTINGS = \"request_settings\",\n\n START_APP = StreamType.START_APP,\n STOP_APP = StreamType.STOP_APP,\n\n DASHBOARD_STATE = \"dashboard_state\",\n OPEN_DASHBOARD = StreamType.OPEN_DASHBOARD,\n\n // Mentra Live\n PHOTO_RESPONSE = StreamType.PHOTO_RESPONSE,\n\n // Local Transcription\n LOCAL_TRANSCRIPTION = \"local_transcription\",\n\n // RTMP streaming\n RTMP_STREAM_STATUS = StreamType.RTMP_STREAM_STATUS,\n KEEP_ALIVE_ACK = \"keep_alive_ack\",\n\n BUTTON_PRESS = StreamType.BUTTON_PRESS,\n HEAD_POSITION = StreamType.HEAD_POSITION,\n TOUCH_EVENT = StreamType.TOUCH_EVENT,\n GLASSES_BATTERY_UPDATE = StreamType.GLASSES_BATTERY_UPDATE,\n PHONE_BATTERY_UPDATE = StreamType.PHONE_BATTERY_UPDATE,\n GLASSES_CONNECTION_STATE = StreamType.GLASSES_CONNECTION_STATE,\n LOCATION_UPDATE = StreamType.LOCATION_UPDATE,\n\n // TODO(isaiah): Remove VPS_COORDINATES once confirmed we don't use this system.\n VPS_COORDINATES = StreamType.VPS_COORDINATES,\n VAD = StreamType.VAD,\n\n // TODO(isaiah): Remove PHONE_NOTIFICATION, and PHONE_NOTIFICATION_DISMISSED after moving to REST request.\n PHONE_NOTIFICATION = StreamType.PHONE_NOTIFICATION,\n PHONE_NOTIFICATION_DISMISSED = StreamType.PHONE_NOTIFICATION_DISMISSED,\n\n // TODO(isaiah): Remove CALENDAR_EVENT after moving to REST request.\n CALENDAR_EVENT = StreamType.CALENDAR_EVENT,\n MENTRAOS_SETTINGS_UPDATE_REQUEST = StreamType.MENTRAOS_SETTINGS_UPDATE_REQUEST,\n\n // TODO(isaiah): Remove CORE_STATUS_UPDATE after moving to REST request.\n CORE_STATUS_UPDATE = StreamType.CORE_STATUS_UPDATE,\n\n PHOTO_TAKEN = StreamType.PHOTO_TAKEN,\n AUDIO_PLAY_RESPONSE = \"audio_play_response\",\n\n // RGB LED control\n RGB_LED_CONTROL_RESPONSE = \"rgb_led_control_response\",\n\n // LiveKit handshake\n LIVEKIT_INIT = \"livekit_init\",\n}\n\n/**\n * Types of messages from cloud to glasses\n */\nexport enum CloudToGlassesMessageType {\n // Responses\n CONNECTION_ACK = \"connection_ack\",\n CONNECTION_ERROR = \"connection_error\",\n AUTH_ERROR = \"auth_error\",\n\n // Updates\n DISPLAY_EVENT = \"display_event\",\n APP_STATE_CHANGE = \"app_state_change\",\n MICROPHONE_STATE_CHANGE = \"microphone_state_change\",\n SETTINGS_UPDATE = \"settings_update\",\n\n // Requests\n PHOTO_REQUEST = \"photo_request\",\n AUDIO_PLAY_REQUEST = \"audio_play_request\",\n AUDIO_STOP_REQUEST = \"audio_stop_request\",\n RGB_LED_CONTROL = \"rgb_led_control\",\n SHOW_WIFI_SETUP = \"show_wifi_setup\",\n\n // RTMP streaming\n START_RTMP_STREAM = \"start_rtmp_stream\",\n STOP_RTMP_STREAM = \"stop_rtmp_stream\",\n KEEP_RTMP_STREAM_ALIVE = \"keep_rtmp_stream_alive\",\n\n // Dashboard updates\n DASHBOARD_MODE_CHANGE = \"dashboard_mode_change\",\n DASHBOARD_ALWAYS_ON_CHANGE = \"dashboard_always_on_change\",\n\n // Location Service\n SET_LOCATION_TIER = \"set_location_tier\",\n REQUEST_SINGLE_LOCATION = \"request_single_location\",\n\n WEBSOCKET_ERROR = \"websocket_error\",\n\n // LiveKit info (URL, room, token)\n LIVEKIT_INFO = \"livekit_info\",\n}\n\n/**\n * Types of messages from Apps to cloud\n */\nexport enum AppToCloudMessageType {\n // Commands\n CONNECTION_INIT = \"tpa_connection_init\",\n SUBSCRIPTION_UPDATE = \"subscription_update\",\n LOCATION_POLL_REQUEST = \"location_poll_request\",\n\n // Requests\n DISPLAY_REQUEST = \"display_event\",\n PHOTO_REQUEST = \"photo_request\",\n AUDIO_PLAY_REQUEST = \"audio_play_request\",\n AUDIO_STOP_REQUEST = \"audio_stop_request\",\n RGB_LED_CONTROL = \"rgb_led_control\",\n REQUEST_WIFI_SETUP = \"request_wifi_setup\",\n\n // RTMP streaming\n RTMP_STREAM_REQUEST = \"rtmp_stream_request\",\n RTMP_STREAM_STOP = \"rtmp_stream_stop\",\n\n // Managed RTMP streaming\n MANAGED_STREAM_REQUEST = \"managed_stream_request\",\n MANAGED_STREAM_STOP = \"managed_stream_stop\",\n\n // Stream status check (both managed and unmanaged)\n STREAM_STATUS_CHECK = \"stream_status_check\",\n\n // Dashboard requests\n DASHBOARD_CONTENT_UPDATE = \"dashboard_content_update\",\n DASHBOARD_MODE_CHANGE = \"dashboard_mode_change\",\n DASHBOARD_SYSTEM_UPDATE = \"dashboard_system_update\",\n\n // TODO(isaiah): Remove after confirming not in use.\n // App-to-App Communication\n APP_BROADCAST_MESSAGE = \"app_broadcast_message\",\n APP_DIRECT_MESSAGE = \"app_direct_message\",\n APP_USER_DISCOVERY = \"app_user_discovery\",\n APP_ROOM_JOIN = \"app_room_join\",\n APP_ROOM_LEAVE = \"app_room_leave\",\n\n // Session lifecycle\n OWNERSHIP_RELEASE = \"ownership_release\",\n}\n\n/**\n * Types of messages from cloud to Apps\n */\nexport enum CloudToAppMessageType {\n // Responses\n CONNECTION_ACK = \"tpa_connection_ack\",\n CONNECTION_ERROR = \"tpa_connection_error\",\n\n // Updates\n APP_STOPPED = \"app_stopped\",\n SETTINGS_UPDATE = \"settings_update\",\n CAPABILITIES_UPDATE = \"capabilities_update\",\n DEVICE_STATE_UPDATE = \"device_state_update\",\n\n // Dashboard updates\n DASHBOARD_MODE_CHANGED = \"dashboard_mode_changed\",\n DASHBOARD_ALWAYS_ON_CHANGED = \"dashboard_always_on_changed\",\n\n // Stream data\n DATA_STREAM = \"data_stream\",\n\n // Media responses\n PHOTO_RESPONSE = \"photo_response\",\n AUDIO_PLAY_RESPONSE = \"audio_play_response\",\n RGB_LED_CONTROL_RESPONSE = \"rgb_led_control_response\",\n RTMP_STREAM_STATUS = \"rtmp_stream_status\",\n MANAGED_STREAM_STATUS = \"managed_stream_status\",\n STREAM_STATUS_CHECK_RESPONSE = \"stream_status_check_response\",\n\n WEBSOCKET_ERROR = \"websocket_error\",\n\n // Permissions\n PERMISSION_ERROR = \"permission_error\",\n\n // General purpose messaging\n CUSTOM_MESSAGE = \"custom_message\",\n\n // TODO(isaiah): Remove after confirming not in use.\n // App-to-App Communication Responses\n APP_MESSAGE_RECEIVED = \"app_message_received\",\n APP_USER_JOINED = \"app_user_joined\",\n APP_USER_LEFT = \"app_user_left\",\n APP_ROOM_UPDATED = \"app_room_updated\",\n APP_DIRECT_MESSAGE_RESPONSE = \"app_direct_message_response\",\n}\n\n/**\n * Control action message types (subset of GlassesToCloudMessageType)\n */\nexport const ControlActionTypes = [\n GlassesToCloudMessageType.CONNECTION_INIT,\n GlassesToCloudMessageType.START_APP,\n GlassesToCloudMessageType.STOP_APP,\n GlassesToCloudMessageType.DASHBOARD_STATE,\n GlassesToCloudMessageType.OPEN_DASHBOARD,\n] as const\n\n/**\n * Event message types (subset of GlassesToCloudMessageType)\n */\nexport const EventTypes = [\n GlassesToCloudMessageType.BUTTON_PRESS,\n GlassesToCloudMessageType.HEAD_POSITION,\n GlassesToCloudMessageType.GLASSES_BATTERY_UPDATE,\n GlassesToCloudMessageType.PHONE_BATTERY_UPDATE,\n GlassesToCloudMessageType.GLASSES_CONNECTION_STATE,\n GlassesToCloudMessageType.LOCATION_UPDATE,\n GlassesToCloudMessageType.VPS_COORDINATES,\n GlassesToCloudMessageType.VAD,\n GlassesToCloudMessageType.PHONE_NOTIFICATION,\n GlassesToCloudMessageType.PHONE_NOTIFICATION_DISMISSED,\n GlassesToCloudMessageType.CALENDAR_EVENT,\n GlassesToCloudMessageType.MENTRAOS_SETTINGS_UPDATE_REQUEST,\n GlassesToCloudMessageType.CORE_STATUS_UPDATE,\n GlassesToCloudMessageType.LOCAL_TRANSCRIPTION,\n] as const\n\n/**\n * Response message types (subset of CloudToGlassesMessageType)\n */\nexport const ResponseTypes = [\n CloudToGlassesMessageType.CONNECTION_ACK,\n CloudToGlassesMessageType.CONNECTION_ERROR,\n CloudToGlassesMessageType.AUTH_ERROR,\n] as const\n\n/**\n * Update message types (subset of CloudToGlassesMessageType)\n */\nexport const UpdateTypes = [\n CloudToGlassesMessageType.DISPLAY_EVENT,\n CloudToGlassesMessageType.APP_STATE_CHANGE,\n CloudToGlassesMessageType.MICROPHONE_STATE_CHANGE,\n CloudToGlassesMessageType.PHOTO_REQUEST,\n CloudToGlassesMessageType.AUDIO_PLAY_REQUEST,\n CloudToGlassesMessageType.AUDIO_STOP_REQUEST,\n CloudToGlassesMessageType.RGB_LED_CONTROL,\n CloudToGlassesMessageType.SETTINGS_UPDATE,\n CloudToGlassesMessageType.DASHBOARD_MODE_CHANGE,\n CloudToGlassesMessageType.DASHBOARD_ALWAYS_ON_CHANGE,\n CloudToGlassesMessageType.START_RTMP_STREAM,\n CloudToGlassesMessageType.STOP_RTMP_STREAM,\n CloudToGlassesMessageType.KEEP_RTMP_STREAM_ALIVE,\n CloudToGlassesMessageType.LIVEKIT_INFO,\n] as const\n\n/**\n * Dashboard message types\n */\nexport const DashboardMessageTypes = [\n AppToCloudMessageType.DASHBOARD_CONTENT_UPDATE,\n AppToCloudMessageType.DASHBOARD_MODE_CHANGE,\n AppToCloudMessageType.DASHBOARD_SYSTEM_UPDATE,\n CloudToAppMessageType.DASHBOARD_MODE_CHANGED,\n CloudToAppMessageType.DASHBOARD_ALWAYS_ON_CHANGED,\n] as const\n",
7
7
  "// TODO:\n/**\n * Dashboard API Types\n *\n * Type definitions for the dashboard functionality in the SDK.\n */\nimport { Layout } from '../layouts';\nimport { AppToCloudMessageType } from '../message-types';\n\n/**\n * Dashboard modes supported by the system\n */\nexport enum DashboardMode {\n MAIN = 'main', // Full dashboard experience\n EXPANDED = 'expanded', // More space for App content\n // ALWAYS_ON = 'always_on' // Persistent minimal dashboard\n}\n\n/**\n * Dashboard API for the system dashboard App\n */\nexport interface DashboardSystemAPI {\n /**\n * Set content for the top left section of the dashboard\n * @param content Content to display\n */\n setTopLeft(content: string): void;\n\n /**\n * Set content for the top right section of the dashboard\n * @param content Content to display\n */\n setTopRight(content: string): void;\n\n /**\n * Set content for the bottom left section of the dashboard\n * @param content Content to display\n */\n setBottomLeft(content: string): void;\n\n /**\n * Set content for the bottom right section of the dashboard\n * @param content Content to display\n */\n setBottomRight(content: string): void;\n\n /**\n * Set the current dashboard mode\n * @param mode Dashboard mode to set\n */\n setViewMode(mode: DashboardMode): void;\n}\n\n/**\n * Dashboard API for all Apps\n */\nexport interface DashboardContentAPI {\n /**\n * Write content to dashboard\n * @param content Content to display\n * @param targets Optional list of dashboard modes to target\n */\n write(content: string, targets?: DashboardMode[]): void;\n\n /**\n * Write content to main dashboard mode\n * @param content Content to display\n */\n writeToMain(content: string): void;\n\n /**\n * Write content to expanded dashboard mode\n * @param content Text content to display\n */\n writeToExpanded(content: string): void;\n\n /**\n * Write content to always-on dashboard mode\n * @param content Content to display\n */\n // writeToAlwaysOn(content: string): void;\n\n /**\n * Get current active dashboard mode\n * @returns Promise resolving to current mode or 'none'\n */\n getCurrentMode(): Promise<DashboardMode | 'none'>;\n\n /**\n * Check if always-on dashboard is enabled\n * @returns Promise resolving to boolean\n */\n // isAlwaysOnEnabled(): Promise<boolean>;\n\n /**\n * Register for mode change notifications\n * @param callback Function to call when mode changes\n * @returns Cleanup function to unregister callback\n */\n onModeChange(callback: (mode: DashboardMode | 'none') => void): () => void;\n\n /**\n * Register for always-on mode change notifications\n * @param callback Function to call when always-on mode changes\n * @returns Cleanup function to unregister callback\n */\n // onAlwaysOnChange(callback: (enabled: boolean) => void): () => void;\n}\n\n/**\n * Dashboard API exposed on AppSession\n */\nexport interface DashboardAPI {\n /**\n * System dashboard API (only available for system dashboard App)\n */\n system?: DashboardSystemAPI;\n\n /**\n * Content API (available to all Apps)\n */\n content: DashboardContentAPI;\n}\n\n/**\n * Message to update dashboard content\n */\nexport interface DashboardContentUpdate {\n type: AppToCloudMessageType.DASHBOARD_CONTENT_UPDATE;\n packageName: string;\n sessionId: string;\n content: string;\n modes: DashboardMode[];\n timestamp: Date;\n}\n\n/**\n * Message for dashboard mode change\n */\nexport interface DashboardModeChange {\n type: AppToCloudMessageType.DASHBOARD_MODE_CHANGE;\n packageName: string;\n sessionId: string;\n mode: DashboardMode;\n timestamp: Date;\n}\n\n/**\n * Message to update system dashboard content\n */\nexport interface DashboardSystemUpdate {\n type: AppToCloudMessageType.DASHBOARD_SYSTEM_UPDATE;\n packageName: string;\n sessionId: string;\n section: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight';\n content: string;\n timestamp: Date;\n}\n\n/**\n * Union type of all dashboard message types\n */\nexport type DashboardMessage =\n | DashboardContentUpdate\n | DashboardModeChange\n | DashboardSystemUpdate;",
8
8
  "/**\n * Dashboard API Implementation\n *\n * Provides dashboard functionality for Apps, allowing them to write content\n * to the dashboard and respond to dashboard mode changes.\n */\n// import { systemApps } from '../../constants';\nimport {\n DashboardAPI,\n DashboardContentAPI,\n DashboardMode,\n DashboardSystemAPI,\n DashboardContentUpdate,\n DashboardModeChange,\n DashboardSystemUpdate,\n} from \"../../types/dashboard\"\nimport {AppToCloudMessageType} from \"../../types/message-types\"\nimport {EventManager} from \"./events\"\n\n// Import AppSession interface for typing\nimport type {AppSession} from \"./index\"\nimport dotenv from \"dotenv\"\n// Load environment variables from .env file\ndotenv.config()\n\nconst SYSTEM_DASHBOARD_PACKAGE_NAME = process.env.SYSTEM_DASHBOARD_PACKAGE_NAME || \"system.augmentos.dashboard\"\n\n/**\n * Implementation of DashboardSystemAPI interface for system dashboard App\n */\nexport class DashboardSystemManager implements DashboardSystemAPI {\n private session: AppSession\n private packageName: string\n\n constructor(session: AppSession, packageName: string) {\n this.session = session\n this.packageName = packageName\n }\n\n setTopLeft(content: string): void {\n this.updateSystemSection(\"topLeft\", content)\n }\n\n setTopRight(content: string): void {\n this.updateSystemSection(\"topRight\", content)\n }\n\n setBottomLeft(content: string): void {\n this.updateSystemSection(\"bottomLeft\", content)\n }\n\n setBottomRight(content: string): void {\n this.updateSystemSection(\"bottomRight\", content)\n }\n\n setViewMode(mode: DashboardMode): void {\n const message: DashboardModeChange = {\n type: AppToCloudMessageType.DASHBOARD_MODE_CHANGE,\n packageName: this.packageName,\n sessionId: `${this.session.getSessionId()}-${this.packageName}`,\n mode,\n timestamp: new Date(),\n }\n this.session.sendMessage(message)\n }\n\n private updateSystemSection(section: \"topLeft\" | \"topRight\" | \"bottomLeft\" | \"bottomRight\", content: string): void {\n const message: DashboardSystemUpdate = {\n type: AppToCloudMessageType.DASHBOARD_SYSTEM_UPDATE,\n packageName: this.packageName,\n sessionId: `${this.session.getSessionId()}-${this.packageName}`,\n section,\n content,\n timestamp: new Date(),\n }\n this.session.sendMessage(message)\n }\n}\n\n/**\n * Implementation of DashboardContentAPI interface for all Apps\n */\nexport class DashboardContentManager implements DashboardContentAPI {\n private session: AppSession\n private packageName: string\n private events: EventManager\n private currentMode: DashboardMode | \"none\" = \"none\"\n // private alwaysOnEnabled: boolean = false;\n\n constructor(session: AppSession, packageName: string, events: EventManager) {\n this.session = session\n this.packageName = packageName\n this.events = events\n }\n\n write(content: string, targets: DashboardMode[] = [DashboardMode.MAIN]): void {\n const message: DashboardContentUpdate = {\n type: AppToCloudMessageType.DASHBOARD_CONTENT_UPDATE,\n packageName: this.packageName,\n sessionId: `${this.session.getSessionId()}-${this.packageName}`,\n content,\n modes: targets,\n timestamp: new Date(),\n }\n this.session.sendMessage(message)\n }\n\n writeToMain(content: string): void {\n this.write(content, [DashboardMode.MAIN])\n }\n\n writeToExpanded(content: string): void {\n const message: DashboardContentUpdate = {\n type: AppToCloudMessageType.DASHBOARD_CONTENT_UPDATE,\n packageName: this.packageName,\n sessionId: `${this.session.getSessionId()}-${this.packageName}`,\n content,\n modes: [DashboardMode.EXPANDED],\n timestamp: new Date(),\n }\n this.session.sendMessage(message)\n }\n\n // writeToAlwaysOn(content: string): void {\n // this.write(content, [DashboardMode.ALWAYS_ON]);\n // }\n\n async getCurrentMode(): Promise<DashboardMode | \"none\"> {\n return this.currentMode\n }\n\n // async isAlwaysOnEnabled(): Promise<boolean> {\n // return this.alwaysOnEnabled;\n // }\n\n onModeChange(callback: (mode: DashboardMode | \"none\") => void): () => void {\n return this.events.onDashboardModeChange((data) => {\n this.currentMode = data.mode\n callback(data.mode)\n })\n }\n\n // onAlwaysOnChange(callback: (enabled: boolean) => void): () => void {\n // return this.events.onDashboardAlwaysOnChange((data) => {\n // this.alwaysOnEnabled = data.enabled;\n // callback(data.enabled);\n // });\n // }\n\n // Internal methods to update state\n setCurrentMode(mode: DashboardMode | \"none\"): void {\n this.currentMode = mode\n this.events.emit(\"dashboard_mode_change\", {mode})\n }\n\n // setAlwaysOnEnabled(enabled: boolean): void {\n // this.alwaysOnEnabled = enabled;\n // this.events.emit('dashboard_always_on_change', { enabled });\n // }\n}\n\n/**\n * Dashboard Manager - Main class that manages dashboard functionality\n * Each AppSession instance gets its own DashboardManager instance\n */\nexport class DashboardManager implements DashboardAPI {\n public content: DashboardContentAPI\n public system?: DashboardSystemAPI\n\n constructor(session: AppSession) {\n const packageName = session.getPackageName()\n const events = session.events\n\n // Create content API (available to all Apps)\n this.content = new DashboardContentManager(session, packageName, events)\n\n // Add system API if this is the system dashboard App\n if (packageName === SYSTEM_DASHBOARD_PACKAGE_NAME) {\n session.logger.info({service: \"SDK:DashboardManager\"}, \"Initializing system dashboard manager\")\n this.system = new DashboardSystemManager(session, packageName)\n } else {\n session.logger.info({service: \"SDK:DashboardManager\"}, `Not the system dashboard: ${packageName}`)\n }\n }\n}\n",
9
9
  "/**\n * 🔐 App Token Utilities\n *\n * Provides utilities for working with App tokens.\n */\nimport * as jwt from 'jsonwebtoken';\nimport { AppTokenPayload, TokenValidationResult, TokenConfig } from '../../types/token';\n\n/**\n * Default token expiration (1 day)\n */\nconst DEFAULT_EXPIRATION = 60 * 60 * 24; // seconds * minutes * hours (1 day).\n\n/**\n * Create a App token for a user session\n *\n * @param payload - Token payload data\n * @param config - Token configuration\n * @returns JWT token string\n *\n * @example\n * ```typescript\n * const token = createToken(\n * {\n * userId: 'user123',\n * packageName: 'org.example.myapp',\n * sessionId: 'session789'\n * },\n * { secretKey: 'your_secret_key' }\n * );\n * ```\n */\nexport function createToken(\n payload: Omit<AppTokenPayload, 'iat' | 'exp'>,\n config: TokenConfig\n): string {\n return jwt.sign(\n payload,\n config.secretKey,\n { expiresIn: config.expiresIn || DEFAULT_EXPIRATION }\n );\n}\n\n/**\n * Validate and decode a App token\n *\n * @param token - JWT token string\n * @param secretKey - Secret key used for validation\n * @returns Token validation result\n *\n * @example\n * ```typescript\n * const result = validateToken('eyJhbGciOiJIUzI1...', 'your_secret_key');\n * if (result.valid) {\n * // Use result.payload\n * }\n * ```\n */\nexport function validateToken(\n token: string,\n secretKey: string\n): TokenValidationResult {\n try {\n const decoded = jwt.verify(token, secretKey) as AppTokenPayload;\n return {\n valid: true,\n payload: decoded\n };\n } catch (error) {\n return {\n valid: false,\n error: error instanceof Error ? error.message : 'Unknown error'\n };\n }\n}\n\n/**\n * Generate a webview URL with an embedded App token\n *\n * @param baseUrl - Base URL of the webview\n * @param token - JWT token string\n * @returns Full URL with token parameter\n *\n * @example\n * ```typescript\n * const url = generateWebviewUrl(\n * 'https://example.com/webview',\n * 'eyJhbGciOiJIUzI1...'\n * );\n * // Returns: https://example.com/webview?token=eyJhbGciOiJIUzI1...\n * ```\n */\nexport function generateWebviewUrl(baseUrl: string, token: string): string {\n const url = new URL(baseUrl);\n url.searchParams.append('token', token);\n return url.toString();\n}\n\n/**\n * Extract a App token from a URL\n *\n * @param url - URL string containing a token parameter\n * @returns Token string or null if not found\n *\n * @example\n * ```typescript\n * const token = extractTokenFromUrl(\n * 'https://example.com/webview?token=eyJhbGciOiJIUzI1...'\n * );\n * ```\n */\nexport function extractTokenFromUrl(url: string): string | null {\n try {\n const parsedUrl = new URL(url);\n return parsedUrl.searchParams.get('token');\n } catch (error) {\n return null;\n }\n}",
10
- "// src/index.ts\nexport * from \"./types/token\";\n\n// Message type enums\nexport * from \"./types/message-types\";\n\n// Base message type\nexport * from \"./types/messages/base\";\n\n// Messages by direction - export everything except the conflicting type guards\nexport * from \"./types/messages/glasses-to-cloud\";\nexport * from \"./types/messages/cloud-to-glasses\";\nexport * from \"./types/messages/app-to-cloud\";\n\n// Utility exports\nexport * from \"./utils/bitmap-utils\";\nexport * from \"./utils/animation-utils\";\n\n// Export cloud-to-app but exclude the conflicting type guards\nexport {\n // Types\n AppConnectionAck,\n AppConnectionError,\n AppStopped,\n SettingsUpdate as AppSettingsUpdate, // Alias to avoid conflict with cloud-to-glasses SettingsUpdate\n CapabilitiesUpdate,\n DataStream,\n CloudToAppMessage,\n TranslationData,\n ToolCall,\n StandardConnectionError,\n CustomMessage,\n ManagedStreamStatus,\n StreamStatusCheckResponse,\n OutputStatus,\n MentraosSettingsUpdate,\n TranscriptionData,\n TranscriptionMetadata,\n SonioxToken,\n AudioChunk,\n PermissionError,\n PermissionErrorDetail,\n AudioPlayResponse,\n // Type guards (excluding isPhotoResponse and isRtmpStreamStatus which conflict)\n isAppConnectionAck,\n isAppConnectionError,\n isAppStopped,\n isSettingsUpdate,\n isCapabilitiesUpdate,\n isDataStream,\n isAudioChunk,\n isStreamStatusCheckResponse,\n isDashboardModeChanged,\n isDashboardAlwaysOnChanged,\n isManagedStreamStatus,\n // Re-export the cloud-to-app versions of these type guards since they're the ones\n // that should be used when dealing with CloudToAppMessage types\n isPhotoResponse as isPhotoResponseFromCloud,\n isRgbLedControlResponse as isRgbLedControlResponseFromCloud,\n isRtmpStreamStatus as isRtmpStreamStatusFromCloud,\n} from \"./types/messages/cloud-to-app\";\n\n// Stream types\nexport * from \"./types/streams\";\n\n// Layout types\nexport * from \"./types/layouts\";\n\n// Dashboard types\nexport * from \"./types/dashboard\";\n\n// RTMP streaming types\nexport * from \"./types/rtmp-stream\";\n\n// Other system enums\nexport {\n AppType,\n LayoutType,\n ViewType,\n AppSettingType,\n HardwareType,\n HardwareRequirementLevel,\n} from \"./types/enums\";\n\n// Core model interfaces\nexport * from \"./types/models\";\n\n// Webhook interfaces\nexport * from \"./types/webhooks\";\n\n// Capability Discovery types\nexport * from \"./types/capabilities\";\n\n// App session and server exports\nexport * from \"./app/index\";\n\n// Logging exports\nexport * from \"./logging/logger\";\n\n// Re-export common types for convenience\n// This allows developers to import commonly used types directly from the package root\n// without having to know exactly which file they come from\n\n// From messages/glasses-to-cloud.ts\nexport {\n ButtonPress,\n HeadPosition,\n TouchEvent,\n GlassesBatteryUpdate,\n PhoneBatteryUpdate,\n GlassesConnectionState,\n LocationUpdate,\n CalendarEvent,\n Vad,\n PhoneNotification,\n PhoneNotificationDismissed,\n StartApp,\n StopApp,\n ConnectionInit,\n DashboardState,\n OpenDashboard,\n GlassesToCloudMessage,\n PhotoResponse,\n RgbLedControlResponse,\n PhotoErrorCode,\n PhotoStage,\n ConnectionState,\n PhotoErrorDetails,\n RtmpStreamStatus,\n KeepAliveAck,\n} from \"./types/messages/glasses-to-cloud\";\n\n// From messages/cloud-to-glasses.ts\nexport {\n ConnectionAck,\n ConnectionError,\n AuthError,\n DisplayEvent,\n AppStateChange,\n MicrophoneStateChange,\n CloudToGlassesMessage,\n PhotoRequestToGlasses,\n RgbLedControlToGlasses,\n SettingsUpdate,\n StartRtmpStream,\n StopRtmpStream,\n KeepRtmpStreamAlive,\n LedColor,\n} from \"./types/messages/cloud-to-glasses\";\n\n// From messages/app-to-cloud.ts\nexport {\n AppConnectionInit,\n AppSubscriptionUpdate,\n RtmpStreamRequest,\n RtmpStreamStopRequest,\n AppToCloudMessage,\n PhotoRequest,\n RgbLedControlRequest,\n} from \"./types/messages/app-to-cloud\";\n\n// From layout.ts\nexport {\n TextWall,\n DoubleTextWall,\n DashboardCard,\n ReferenceCard,\n Layout,\n DisplayRequest,\n BitmapView,\n ClearView,\n} from \"./types/layouts\";\n\n// Type guards - re-export the most commonly used ones for convenience\nexport {\n isButtonPress,\n isHeadPosition,\n isConnectionInit,\n isStartApp,\n isStopApp,\n isPhotoResponse as isPhotoResponseFromGlasses,\n isRgbLedControlResponse as isRgbLedControlResponseFromGlasses,\n isRtmpStreamStatus as isRtmpStreamStatusFromGlasses,\n isKeepAliveAck,\n isPhoneNotificationDismissed,\n} from \"./types/messages/glasses-to-cloud\";\n\nexport {\n isConnectionAck,\n isDisplayEvent,\n isAppStateChange,\n isPhotoRequest,\n isSettingsUpdate as isSettingsUpdateToGlasses,\n isStartRtmpStream,\n isStopRtmpStream,\n isKeepRtmpStreamAlive,\n isRgbLedControl,\n} from \"./types/messages/cloud-to-glasses\";\n\nexport {\n isAppConnectionInit,\n isAppSubscriptionUpdate,\n isDisplayRequest,\n isRtmpStreamRequest,\n isRtmpStreamStopRequest,\n isPhotoRequest as isPhotoRequestFromApp,\n isRgbLedControlRequest,\n} from \"./types/messages/app-to-cloud\";\n\n// Export setting-related types\nexport {\n BaseAppSetting,\n AppSetting,\n AppSettings,\n AppConfig,\n validateAppConfig,\n ToolSchema,\n ToolParameterSchema,\n HardwareRequirement,\n} from \"./types/models\";\n\n// Export RTMP streaming types\nexport {\n VideoConfig,\n AudioConfig,\n StreamConfig,\n StreamStatusHandler,\n} from \"./types/rtmp-stream\";\n\n// Export app session modules\nexport * from \"./app/session/modules\";\n\n// Export photo data types\nexport { PhotoData } from \"./types/photo-data\";\n\n/**\n * WebSocket error information\n */\nexport interface WebSocketError {\n code: string;\n message: string;\n details?: unknown;\n}\n\nexport { AuthenticatedRequest } from \"./types/index\";\n",
10
+ "// src/index.ts\nexport * from \"./types/token\";\n\n// Message type enums\nexport * from \"./types/message-types\";\n\n// Base message type\nexport * from \"./types/messages/base\";\n\n// Messages by direction - export everything except the conflicting type guards\nexport * from \"./types/messages/glasses-to-cloud\";\nexport * from \"./types/messages/cloud-to-glasses\";\nexport * from \"./types/messages/app-to-cloud\";\n\n// Utility exports\nexport * from \"./utils/bitmap-utils\";\nexport * from \"./utils/animation-utils\";\n\n// Export cloud-to-app but exclude the conflicting type guards\nexport {\n // Types\n AppConnectionAck,\n AppConnectionError,\n AppStopped,\n SettingsUpdate as AppSettingsUpdate, // Alias to avoid conflict with cloud-to-glasses SettingsUpdate\n CapabilitiesUpdate,\n DataStream,\n CloudToAppMessage,\n TranslationData,\n ToolCall,\n StandardConnectionError,\n CustomMessage,\n ManagedStreamStatus,\n StreamStatusCheckResponse,\n OutputStatus,\n MentraosSettingsUpdate,\n TranscriptionData,\n TranscriptionMetadata,\n SonioxToken,\n AudioChunk,\n PermissionError,\n PermissionErrorDetail,\n AudioPlayResponse,\n // Type guards (excluding isPhotoResponse and isRtmpStreamStatus which conflict)\n isAppConnectionAck,\n isAppConnectionError,\n isAppStopped,\n isSettingsUpdate,\n isCapabilitiesUpdate,\n isDataStream,\n isAudioChunk,\n isStreamStatusCheckResponse,\n isDashboardModeChanged,\n isDashboardAlwaysOnChanged,\n isManagedStreamStatus,\n // Re-export the cloud-to-app versions of these type guards since they're the ones\n // that should be used when dealing with CloudToAppMessage types\n isPhotoResponse as isPhotoResponseFromCloud,\n isRgbLedControlResponse as isRgbLedControlResponseFromCloud,\n isRtmpStreamStatus as isRtmpStreamStatusFromCloud,\n} from \"./types/messages/cloud-to-app\";\n\n// Stream types\nexport * from \"./types/streams\";\n\n// Layout types\nexport * from \"./types/layouts\";\n\n// Dashboard types\nexport * from \"./types/dashboard\";\n\n// RTMP streaming types\nexport * from \"./types/rtmp-stream\";\n\n// Other system enums\nexport { AppType, LayoutType, ViewType, AppSettingType, HardwareType, HardwareRequirementLevel } from \"./types/enums\";\n\n// Core model interfaces\nexport * from \"./types/models\";\n\n// Webhook interfaces\nexport * from \"./types/webhooks\";\n\n// Capability Discovery types\nexport * from \"./types/capabilities\";\n\n// App session and server exports\nexport * from \"./app/index\";\n\n// Logging exports\nexport * from \"./logging/logger\";\n\n// Re-export common types for convenience\n// This allows developers to import commonly used types directly from the package root\n// without having to know exactly which file they come from\n\n// From messages/glasses-to-cloud.ts\nexport {\n ButtonPress,\n HeadPosition,\n TouchEvent,\n GlassesBatteryUpdate,\n PhoneBatteryUpdate,\n GlassesConnectionState,\n LocationUpdate,\n CalendarEvent,\n Vad,\n PhoneNotification,\n PhoneNotificationDismissed,\n StartApp,\n StopApp,\n ConnectionInit,\n DashboardState,\n OpenDashboard,\n GlassesToCloudMessage,\n PhotoResponse,\n RgbLedControlResponse,\n PhotoErrorCode,\n PhotoStage,\n ConnectionState,\n PhotoErrorDetails,\n RtmpStreamStatus,\n KeepAliveAck,\n} from \"./types/messages/glasses-to-cloud\";\n\n// From messages/cloud-to-glasses.ts\nexport {\n ConnectionAck,\n ConnectionError,\n AuthError,\n DisplayEvent,\n AppStateChange,\n MicrophoneStateChange,\n CloudToGlassesMessage,\n PhotoRequestToGlasses,\n RgbLedControlToGlasses,\n SettingsUpdate,\n StartRtmpStream,\n StopRtmpStream,\n KeepRtmpStreamAlive,\n LedColor,\n} from \"./types/messages/cloud-to-glasses\";\n\n// From messages/app-to-cloud.ts\nexport {\n AppConnectionInit,\n AppSubscriptionUpdate,\n RtmpStreamRequest,\n RtmpStreamStopRequest,\n AppToCloudMessage,\n PhotoRequest,\n RgbLedControlRequest,\n} from \"./types/messages/app-to-cloud\";\n\n// From layout.ts\nexport {\n TextWall,\n DoubleTextWall,\n DashboardCard,\n ReferenceCard,\n Layout,\n DisplayRequest,\n BitmapView,\n ClearView,\n} from \"./types/layouts\";\n\n// Type guards - re-export the most commonly used ones for convenience\nexport {\n isButtonPress,\n isHeadPosition,\n isConnectionInit,\n isStartApp,\n isStopApp,\n isPhotoResponse as isPhotoResponseFromGlasses,\n isRgbLedControlResponse as isRgbLedControlResponseFromGlasses,\n isRtmpStreamStatus as isRtmpStreamStatusFromGlasses,\n isKeepAliveAck,\n isPhoneNotificationDismissed,\n} from \"./types/messages/glasses-to-cloud\";\n\nexport {\n isConnectionAck,\n isDisplayEvent,\n isAppStateChange,\n isPhotoRequest,\n isSettingsUpdate as isSettingsUpdateToGlasses,\n isStartRtmpStream,\n isStopRtmpStream,\n isKeepRtmpStreamAlive,\n isRgbLedControl,\n} from \"./types/messages/cloud-to-glasses\";\n\nexport {\n isAppConnectionInit,\n isAppSubscriptionUpdate,\n isDisplayRequest,\n isRtmpStreamRequest,\n isRtmpStreamStopRequest,\n isPhotoRequest as isPhotoRequestFromApp,\n isRgbLedControlRequest,\n isOwnershipRelease,\n} from \"./types/messages/app-to-cloud\";\n\n// Export setting-related types\nexport {\n BaseAppSetting,\n AppSetting,\n AppSettings,\n AppConfig,\n validateAppConfig,\n ToolSchema,\n ToolParameterSchema,\n HardwareRequirement,\n} from \"./types/models\";\n\n// Export RTMP streaming types\nexport { VideoConfig, AudioConfig, StreamConfig, StreamStatusHandler } from \"./types/rtmp-stream\";\n\n// Export app session modules\nexport * from \"./app/session/modules\";\n\n// Export photo data types\nexport { PhotoData } from \"./types/photo-data\";\n\n// Export device state types (WebSocket-based observables)\nexport { DeviceState } from \"./app/session/device-state\";\nexport { Observable } from \"./utils/Observable\";\n\n// Re-export types from @mentra/types so SDK users don't need to install it separately\nexport type { GlassesInfo } from \"@mentra/types\";\n\n/**\n * WebSocket error information\n */\nexport interface WebSocketError {\n code: string;\n message: string;\n details?: unknown;\n}\n\nexport { AuthenticatedRequest } from \"./types/index\";\n",
11
11
  "// src/messages/glasses-to-cloud.ts\n\nimport {BaseMessage} from \"./base\"\nimport {GlassesToCloudMessageType, ControlActionTypes, EventTypes} from \"../message-types\"\nimport {StreamType} from \"../streams\"\n\n//===========================================================\n// Control actions\n//===========================================================\n\n/**\n * Connection initialization from glasses\n */\nexport interface ConnectionInit extends BaseMessage {\n type: GlassesToCloudMessageType.CONNECTION_INIT\n userId?: string\n coreToken?: string\n}\n\n/**\n * Client requests LiveKit info (url, room, token)\n */\nexport interface LiveKitInit extends BaseMessage {\n type: GlassesToCloudMessageType.LIVEKIT_INIT\n mode?: \"publish\" | \"subscribe\" // Optional mode - defaults to 'publish' for backward compatibility\n}\n\nexport interface RequestSettings extends BaseMessage {\n type: GlassesToCloudMessageType.REQUEST_SETTINGS\n sessionId: string\n}\n\n/**\n * Start app request from glasses\n */\nexport interface StartApp extends BaseMessage {\n type: GlassesToCloudMessageType.START_APP\n packageName: string\n}\n\n/**\n * Stop app request from glasses\n */\nexport interface StopApp extends BaseMessage {\n type: GlassesToCloudMessageType.STOP_APP\n packageName: string\n}\n\n/**\n * Dashboard state update from glasses\n */\nexport interface DashboardState extends BaseMessage {\n type: GlassesToCloudMessageType.DASHBOARD_STATE\n isOpen: boolean\n}\n\n/**\n * Open dashboard request from glasses\n */\nexport interface OpenDashboard extends BaseMessage {\n type: GlassesToCloudMessageType.OPEN_DASHBOARD\n}\n\n//===========================================================\n// Events and data\n//===========================================================\n\n/**\n * Button press event from glasses\n */\nexport interface ButtonPress extends BaseMessage {\n type: GlassesToCloudMessageType.BUTTON_PRESS\n buttonId: string\n pressType: \"short\" | \"long\"\n}\n\n/**\n * Head position event from glasses\n */\nexport interface HeadPosition extends BaseMessage {\n type: GlassesToCloudMessageType.HEAD_POSITION\n position: \"up\" | \"down\"\n}\n\n/**\n * Touch gesture event from glasses\n */\nexport interface TouchEvent extends BaseMessage {\n type: GlassesToCloudMessageType.TOUCH_EVENT\n device_model: string\n gesture_name: string\n timestamp: Date\n}\n\n/**\n * Glasses battery update from glasses\n */\nexport interface GlassesBatteryUpdate extends BaseMessage {\n type: GlassesToCloudMessageType.GLASSES_BATTERY_UPDATE\n level: number // 0-100\n charging: boolean\n timeRemaining?: number // minutes\n}\n\n/**\n * Phone battery update from glasses\n */\nexport interface PhoneBatteryUpdate extends BaseMessage {\n type: GlassesToCloudMessageType.PHONE_BATTERY_UPDATE\n level: number // 0-100\n charging: boolean\n timeRemaining?: number // minutes\n}\n\n/**\n * Glasses connection state from glasses\n */\nexport interface GlassesConnectionState extends BaseMessage {\n type: GlassesToCloudMessageType.GLASSES_CONNECTION_STATE\n modelName: string\n status: string\n\n // Optional WiFi details (only present for WiFi-capable glasses)\n wifi?: {\n connected: boolean\n ssid?: string | null\n }\n}\n\n/**\n * Location update from glasses\n */\nexport interface LocationUpdate extends BaseMessage {\n type: GlassesToCloudMessageType.LOCATION_UPDATE | StreamType.LOCATION_UPDATE\n lat: number\n lng: number\n accuracy?: number // Accuracy in meters\n correlationId?: string // for poll responses\n}\n\n/**\n * VPS coordinates update from glasses\n */\nexport interface VpsCoordinates extends BaseMessage {\n type: GlassesToCloudMessageType.VPS_COORDINATES | StreamType.VPS_COORDINATES\n deviceModel: string\n requestId: string\n x: number\n y: number\n z: number\n qx: number\n qy: number\n qz: number\n qw: number\n confidence: number\n}\n\nexport interface LocalTranscription extends BaseMessage {\n type: GlassesToCloudMessageType.LOCAL_TRANSCRIPTION\n text: string\n isFinal: boolean\n startTime: number\n endTime: number\n speakerId: number\n transcribeLanguage: string\n provider: string\n}\n\nexport interface CalendarEvent extends BaseMessage {\n type: GlassesToCloudMessageType.CALENDAR_EVENT | StreamType.CALENDAR_EVENT\n eventId: string\n title: string\n dtStart: string\n dtEnd: string\n timezone: string\n timeStamp: string\n}\n\n/**\n * Voice activity detection from glasses\n */\nexport interface Vad extends BaseMessage {\n type: GlassesToCloudMessageType.VAD\n status: boolean | \"true\" | \"false\"\n}\n\n/**\n * Phone notification from glasses\n */\nexport interface PhoneNotification extends BaseMessage {\n type: GlassesToCloudMessageType.PHONE_NOTIFICATION\n notificationId: string\n app: string\n title: string\n content: string\n priority: \"low\" | \"normal\" | \"high\"\n}\n\n/**\n * Notification dismissed from glasses\n */\nexport interface PhoneNotificationDismissed extends BaseMessage {\n type: GlassesToCloudMessageType.PHONE_NOTIFICATION_DISMISSED\n notificationId: string\n app: string\n title: string\n content: string\n notificationKey: string\n}\n\n/**\n * MentraOS settings update from glasses\n */\nexport interface MentraosSettingsUpdateRequest extends BaseMessage {\n type: GlassesToCloudMessageType.MENTRAOS_SETTINGS_UPDATE_REQUEST\n}\nexport interface MentraosSettingsUpdateRequest extends BaseMessage {\n type: GlassesToCloudMessageType.MENTRAOS_SETTINGS_UPDATE_REQUEST\n}\n\n/**\n * Core status update from glasses\n */\nexport interface CoreStatusUpdate extends BaseMessage {\n type: GlassesToCloudMessageType.CORE_STATUS_UPDATE\n status: string\n details?: Record<string, any>\n}\n\n// ===========================================================\n// Mentra Live\n// ===========================================================\n\n/**\n * Photo error codes for detailed error reporting\n */\nexport enum PhotoErrorCode {\n CAMERA_INIT_FAILED = \"CAMERA_INIT_FAILED\",\n CAMERA_CAPTURE_FAILED = \"CAMERA_CAPTURE_FAILED\",\n CAMERA_TIMEOUT = \"CAMERA_TIMEOUT\",\n CAMERA_BUSY = \"CAMERA_BUSY\",\n UPLOAD_FAILED = \"UPLOAD_FAILED\",\n UPLOAD_TIMEOUT = \"UPLOAD_TIMEOUT\",\n BLE_TRANSFER_FAILED = \"BLE_TRANSFER_FAILED\",\n BLE_TRANSFER_BUSY = \"BLE_TRANSFER_BUSY\",\n BLE_TRANSFER_FAILED_TO_START = \"BLE_TRANSFER_FAILED_TO_START\",\n BLE_TRANSFER_TIMEOUT = \"BLE_TRANSFER_TIMEOUT\",\n COMPRESSION_FAILED = \"COMPRESSION_FAILED\",\n PERMISSION_DENIED = \"PERMISSION_DENIED\",\n STORAGE_FULL = \"STORAGE_FULL\",\n NETWORK_ERROR = \"NETWORK_ERROR\",\n // Phone-side error codes\n PHONE_GLASSES_NOT_CONNECTED = \"PHONE_GLASSES_NOT_CONNECTED\",\n PHONE_BLE_TRANSFER_FAILED = \"PHONE_BLE_TRANSFER_FAILED\",\n PHONE_UPLOAD_FAILED = \"PHONE_UPLOAD_FAILED\",\n PHONE_TIMEOUT = \"PHONE_TIMEOUT\",\n UNKNOWN_ERROR = \"UNKNOWN_ERROR\",\n}\n\n/**\n * Photo processing stages for error context\n */\nexport enum PhotoStage {\n REQUEST_RECEIVED = \"REQUEST_RECEIVED\",\n CAMERA_INIT = \"CAMERA_INIT\",\n PHOTO_CAPTURE = \"PHOTO_CAPTURE\",\n COMPRESSION = \"COMPRESSION\",\n UPLOAD_START = \"UPLOAD_START\",\n UPLOAD_PROGRESS = \"UPLOAD_PROGRESS\",\n BLE_TRANSFER = \"BLE_TRANSFER\",\n RESPONSE_SENT = \"RESPONSE_SENT\",\n}\n\n/**\n * Connection state information for error diagnostics\n */\nexport interface ConnectionState {\n wifi: {\n connected: boolean\n ssid?: string\n hasInternet: boolean\n }\n ble: {\n connected: boolean\n transferInProgress: boolean\n }\n camera: {\n available: boolean\n initialized: boolean\n }\n storage: {\n availableSpace: number\n totalSpace: number\n }\n}\n\n/**\n * Detailed error information for photo failures\n */\nexport interface PhotoErrorDetails {\n stage: PhotoStage\n connectionState?: ConnectionState\n retryable: boolean\n suggestedAction?: string\n diagnosticInfo?: {\n timestamp: number\n duration: number\n retryCount: number\n lastSuccessfulStage?: PhotoStage\n }\n}\n\n/**\n * Enhanced photo response with error support\n */\nexport interface PhotoResponse extends BaseMessage {\n type: GlassesToCloudMessageType.PHOTO_RESPONSE\n requestId: string // Unique ID for the photo request\n success: boolean // Explicit success/failure flag\n\n // Success fields (only present when success = true)\n photoUrl?: string // URL of the uploaded photo\n savedToGallery?: boolean // Whether the photo was saved to gallery\n\n // Error fields (only present when success = false)\n error?: {\n code: PhotoErrorCode\n message: string\n details?: PhotoErrorDetails\n }\n}\n\n/**\n * RGB LED control response from glasses\n */\nexport interface RgbLedControlResponse extends BaseMessage {\n type: GlassesToCloudMessageType.RGB_LED_CONTROL_RESPONSE\n requestId: string\n success: boolean\n error?: string\n}\n\n/**\n * RTMP stream status update from glasses\n */\nexport interface RtmpStreamStatus extends BaseMessage {\n type: GlassesToCloudMessageType.RTMP_STREAM_STATUS\n streamId?: string // Unique identifier for the stream\n status:\n | \"initializing\"\n | \"connecting\"\n | \"reconnecting\"\n | \"streaming\"\n | \"error\"\n | \"stopped\"\n | \"active\"\n | \"stopping\"\n | \"disconnected\"\n | \"timeout\"\n | \"reconnected\"\n | \"reconnect_failed\"\n errorDetails?: string\n appId?: string // ID of the app that requested the stream\n stats?: {\n bitrate: number\n fps: number\n droppedFrames: number\n duration: number\n }\n}\n\n/**\n * Keep-alive acknowledgment from glasses\n */\nexport interface KeepAliveAck extends BaseMessage {\n type: GlassesToCloudMessageType.KEEP_ALIVE_ACK\n streamId: string // ID of the stream being kept alive\n ackId: string // Acknowledgment ID that was sent by cloud\n}\n\n/**\n * Photo taken event from glasses\n */\nexport interface PhotoTaken extends BaseMessage {\n type: GlassesToCloudMessageType.PHOTO_TAKEN\n photoData: ArrayBuffer\n mimeType: string\n timestamp: Date\n}\n\n/**\n * Audio play response from glasses/core\n */\nexport interface AudioPlayResponse extends BaseMessage {\n type: GlassesToCloudMessageType.AUDIO_PLAY_RESPONSE\n requestId: string\n success: boolean\n error?: string\n duration?: number\n}\n\n/**\n * Union type for all messages from glasses to cloud\n */\nexport type GlassesToCloudMessage =\n | ConnectionInit\n | LiveKitInit\n | RequestSettings\n | StartApp\n | StopApp\n | DashboardState\n | OpenDashboard\n | ButtonPress\n | HeadPosition\n | TouchEvent\n | GlassesBatteryUpdate\n | PhoneBatteryUpdate\n | GlassesConnectionState\n | LocationUpdate\n | VpsCoordinates\n | CalendarEvent\n | Vad\n | PhoneNotification\n | PhoneNotificationDismissed\n | MentraosSettingsUpdateRequest\n | CoreStatusUpdate\n | RtmpStreamStatus\n | KeepAliveAck\n | PhotoResponse\n | RgbLedControlResponse\n | PhotoTaken\n | AudioPlayResponse\n | LocalTranscription\n\n//===========================================================\n// Type guards\n//===========================================================\n\nexport function isControlAction(message: GlassesToCloudMessage): boolean {\n return ControlActionTypes.includes(message.type as any)\n}\n\nexport function isEvent(message: GlassesToCloudMessage): boolean {\n return EventTypes.includes(message.type as any)\n}\n\n// Individual type guards\nexport function isConnectionInit(message: GlassesToCloudMessage): message is ConnectionInit {\n return message.type === GlassesToCloudMessageType.CONNECTION_INIT\n}\n\nexport function isRequestSettings(message: GlassesToCloudMessage): message is RequestSettings {\n return message.type === GlassesToCloudMessageType.REQUEST_SETTINGS\n}\n\nexport function isStartApp(message: GlassesToCloudMessage): message is StartApp {\n return message.type === GlassesToCloudMessageType.START_APP\n}\n\nexport function isStopApp(message: GlassesToCloudMessage): message is StopApp {\n return message.type === GlassesToCloudMessageType.STOP_APP\n}\n\nexport function isButtonPress(message: GlassesToCloudMessage): message is ButtonPress {\n return message.type === GlassesToCloudMessageType.BUTTON_PRESS\n}\n\nexport function isHeadPosition(message: GlassesToCloudMessage): message is HeadPosition {\n return message.type === GlassesToCloudMessageType.HEAD_POSITION\n}\n\nexport function isGlassesBatteryUpdate(message: GlassesToCloudMessage): message is GlassesBatteryUpdate {\n return message.type === GlassesToCloudMessageType.GLASSES_BATTERY_UPDATE\n}\n\nexport function isPhoneBatteryUpdate(message: GlassesToCloudMessage): message is PhoneBatteryUpdate {\n return message.type === GlassesToCloudMessageType.PHONE_BATTERY_UPDATE\n}\n\nexport function isGlassesConnectionState(message: GlassesToCloudMessage): message is GlassesConnectionState {\n return message.type === GlassesToCloudMessageType.GLASSES_CONNECTION_STATE\n}\n\nexport function isLocationUpdate(message: GlassesToCloudMessage): message is LocationUpdate {\n return message.type === GlassesToCloudMessageType.LOCATION_UPDATE\n}\n\nexport function isCalendarEvent(message: GlassesToCloudMessage): message is CalendarEvent {\n return message.type === GlassesToCloudMessageType.CALENDAR_EVENT\n}\n\nexport function isVad(message: GlassesToCloudMessage): message is Vad {\n return message.type === GlassesToCloudMessageType.VAD\n}\n\nexport function isPhoneNotification(message: GlassesToCloudMessage): message is PhoneNotification {\n return message.type === GlassesToCloudMessageType.PHONE_NOTIFICATION\n}\n\nexport function isPhoneNotificationDismissed(message: GlassesToCloudMessage): message is PhoneNotificationDismissed {\n return message.type === GlassesToCloudMessageType.PHONE_NOTIFICATION_DISMISSED\n}\n\nexport function isRtmpStreamStatus(message: GlassesToCloudMessage): message is RtmpStreamStatus {\n return message.type === GlassesToCloudMessageType.RTMP_STREAM_STATUS\n}\n\nexport function isPhotoResponse(message: GlassesToCloudMessage): message is PhotoResponse {\n return message.type === GlassesToCloudMessageType.PHOTO_RESPONSE\n}\n\nexport function isRgbLedControlResponse(message: GlassesToCloudMessage): message is RgbLedControlResponse {\n return message.type === GlassesToCloudMessageType.RGB_LED_CONTROL_RESPONSE\n}\n\nexport function isKeepAliveAck(message: GlassesToCloudMessage): message is KeepAliveAck {\n return message.type === GlassesToCloudMessageType.KEEP_ALIVE_ACK\n}\n\nexport function isPhotoTaken(message: GlassesToCloudMessage): message is PhotoTaken {\n return message.type === GlassesToCloudMessageType.PHOTO_TAKEN\n}\n\nexport function isAudioPlayResponse(message: GlassesToCloudMessage): message is AudioPlayResponse {\n return message.type === GlassesToCloudMessageType.AUDIO_PLAY_RESPONSE\n}\n\nexport function isLocalTranscription(message: GlassesToCloudMessage): message is LocalTranscription {\n return message.type === GlassesToCloudMessageType.LOCAL_TRANSCRIPTION\n}\n",
12
12
  "// src/messages/cloud-to-glasses.ts\n\nimport {BaseMessage} from \"./base\"\nimport {CloudToGlassesMessageType, ResponseTypes, UpdateTypes} from \"../message-types\"\nimport {Layout} from \"../layouts\"\n// import { UserSession } from \"../user-session\";\n\n//===========================================================\n// Responses\n//===========================================================\n\n/**\n * Connection acknowledgment to glasses\n */\nexport interface ConnectionAck extends BaseMessage {\n type: CloudToGlassesMessageType.CONNECTION_ACK\n // userSession: Partial<UserSession>;\n sessionId: string\n livekit?: {\n url: string\n roomName: string\n token: string\n }\n}\n\n/**\n * Connection error to glasses\n */\nexport interface ConnectionError extends BaseMessage {\n type: CloudToGlassesMessageType.CONNECTION_ERROR\n code?: string\n message: string\n}\n\n/**\n * Authentication error to glasses\n */\nexport interface AuthError extends BaseMessage {\n type: CloudToGlassesMessageType.AUTH_ERROR\n message: string\n}\n\n//===========================================================\n// Updates\n//===========================================================\n\n/**\n * Display update to glasses\n */\nexport interface DisplayEvent extends BaseMessage {\n type: CloudToGlassesMessageType.DISPLAY_EVENT\n layout: Layout\n durationMs?: number\n}\n\n/**\n * App state change to glasses\n */\nexport interface AppStateChange extends BaseMessage {\n type: CloudToGlassesMessageType.APP_STATE_CHANGE\n // userSession: Partial<UserSession>;\n error?: string\n}\n\n/**\n * Microphone state change to glasses\n */\nexport interface MicrophoneStateChange extends BaseMessage {\n type: CloudToGlassesMessageType.MICROPHONE_STATE_CHANGE\n // userSession: Partial<UserSession>;\n isMicrophoneEnabled: boolean\n requiredData: Array<\"pcm\" | \"transcription\" | \"pcm_or_transcription\">\n bypassVad?: boolean // NEW: PCM subscription bypass\n}\n\n/**\n * Photo request to glasses\n */\nexport interface PhotoRequestToGlasses extends BaseMessage {\n type: CloudToGlassesMessageType.PHOTO_REQUEST\n // userSession: Partial<UserSession>;\n requestId: string\n appId: string\n saveToGallery?: boolean\n webhookUrl?: string // URL where ASG should send the photo directly\n authToken?: string // Auth token for webhook authentication\n /** Desired capture size to guide device resolution selection */\n size?: \"small\" | \"medium\" | \"large\" | \"full\"\n /** Image compression level: none, medium, or heavy */\n compress?: \"none\" | \"medium\" | \"heavy\"\n}\n\n/**\n * LED color type for RGB LED control\n */\nexport type LedColor = \"red\" | \"green\" | \"blue\" | \"orange\" | \"white\"\n\n/**\n * RGB LED control request to glasses\n */\nexport interface RgbLedControlToGlasses extends BaseMessage {\n type: CloudToGlassesMessageType.RGB_LED_CONTROL\n requestId: string\n appId: string\n action: \"on\" | \"off\" // Only low-level on/off actions\n color?: LedColor // LED color name\n ontime?: number\n offtime?: number\n count?: number\n}\n\n// TODO(isaiah): Deprecated, remove this after new mobile client refactor complete, and we migrate to SettingsStateChange.\n/**\n * Settings update to glasses\n */\nexport interface SettingsUpdate extends BaseMessage {\n type: CloudToGlassesMessageType.SETTINGS_UPDATE\n sessionId: string\n settings: {\n useOnboardMic: boolean\n contextualDashboard: boolean\n metricSystemEnabled: boolean\n headUpAngle: number\n brightness: number\n autoBrightness: boolean\n sensingEnabled: boolean\n alwaysOnStatusBar: boolean\n bypassVad: boolean\n bypassAudioEncoding: boolean\n }\n}\n\n/**\n * LiveKit info for client to connect & publish\n */\nexport interface LiveKitInfo extends BaseMessage {\n type: CloudToGlassesMessageType.LIVEKIT_INFO\n url: string\n roomName: string\n token: string\n}\n\n//===========================================================\n// RTMP Streaming Commands\n//===========================================================\n\n/**\n * Start RTMP stream command to glasses\n */\nexport interface StartRtmpStream extends BaseMessage {\n type: CloudToGlassesMessageType.START_RTMP_STREAM\n rtmpUrl: string\n appId: string\n streamId?: string\n video?: any // Video configuration\n audio?: any // Audio configuration\n stream?: any // Stream configuration\n}\n\n/**\n * Stop RTMP stream command to glasses\n */\nexport interface StopRtmpStream extends BaseMessage {\n type: CloudToGlassesMessageType.STOP_RTMP_STREAM\n appId: string\n streamId?: string\n}\n\n/**\n * Keep RTMP stream alive command to glasses\n */\nexport interface KeepRtmpStreamAlive extends BaseMessage {\n type: CloudToGlassesMessageType.KEEP_RTMP_STREAM_ALIVE\n streamId: string\n ackId: string\n}\n\n//===========================================================\n// Location Service Commands\n//===========================================================\n\n/**\n * Sets the continuous location update tier on the device.\n */\nexport interface SetLocationTier extends BaseMessage {\n type: CloudToGlassesMessageType.SET_LOCATION_TIER\n tier: \"realtime\" | \"high\" | \"tenMeters\" | \"hundredMeters\" | \"kilometer\" | \"threeKilometers\" | \"reduced\" | \"standard\"\n}\n\n/**\n * Requests a single, on-demand location fix from the device.\n */\nexport interface RequestSingleLocation extends BaseMessage {\n type: CloudToGlassesMessageType.REQUEST_SINGLE_LOCATION\n accuracy: string // The accuracy tier requested by the app\n correlationId: string // To match the response with the poll request\n}\n\n/**\n * Audio play request to glasses\n */\nexport interface AudioPlayRequestToGlasses extends BaseMessage {\n type: CloudToGlassesMessageType.AUDIO_PLAY_REQUEST\n // userSession: Partial<UserSession>;\n requestId: string\n appId: string\n audioUrl: string // URL to audio file for download and play\n volume?: number // Volume level 0.0-1.0, defaults to 1.0\n stopOtherAudio?: boolean // Whether to stop other audio playback, defaults to true\n}\n\n/**\n * Audio stop request to glasses\n */\nexport interface AudioStopRequestToGlasses extends BaseMessage {\n type: CloudToGlassesMessageType.AUDIO_STOP_REQUEST\n // userSession: Partial<UserSession>;\n appId: string\n}\n\n/**\n * WiFi setup request to glasses/mobile\n */\nexport interface ShowWifiSetup extends BaseMessage {\n type: CloudToGlassesMessageType.SHOW_WIFI_SETUP\n reason?: string\n appPackageName?: string\n}\n\n/**\n * Union type for all messages from cloud to glasses\n */\nexport type CloudToGlassesMessage =\n | ConnectionAck\n | ConnectionError\n | AuthError\n | DisplayEvent\n | AppStateChange\n | MicrophoneStateChange\n | PhotoRequestToGlasses\n | RgbLedControlToGlasses\n | AudioPlayRequestToGlasses\n | AudioStopRequestToGlasses\n | SettingsUpdate\n | StartRtmpStream\n | StopRtmpStream\n | KeepRtmpStreamAlive\n | SetLocationTier\n | RequestSingleLocation\n | LiveKitInfo\n | ShowWifiSetup\n\n//===========================================================\n// Type guards\n//===========================================================\n\nexport function isResponse(message: CloudToGlassesMessage): boolean {\n return ResponseTypes.includes(message.type as any)\n}\n\nexport function isUpdate(message: CloudToGlassesMessage): boolean {\n return UpdateTypes.includes(message.type as any)\n}\n\n// Individual type guards\nexport function isConnectionAck(message: CloudToGlassesMessage): message is ConnectionAck {\n return message.type === CloudToGlassesMessageType.CONNECTION_ACK\n}\n\nexport function isConnectionError(message: CloudToGlassesMessage): message is ConnectionError {\n return message.type === CloudToGlassesMessageType.CONNECTION_ERROR\n}\n\nexport function isAuthError(message: CloudToGlassesMessage): message is AuthError {\n return message.type === CloudToGlassesMessageType.AUTH_ERROR\n}\n\nexport function isDisplayEvent(message: CloudToGlassesMessage): message is DisplayEvent {\n return message.type === CloudToGlassesMessageType.DISPLAY_EVENT\n}\n\nexport function isAppStateChange(message: CloudToGlassesMessage): message is AppStateChange {\n return message.type === CloudToGlassesMessageType.APP_STATE_CHANGE\n}\n\nexport function isMicrophoneStateChange(message: CloudToGlassesMessage): message is MicrophoneStateChange {\n return message.type === CloudToGlassesMessageType.MICROPHONE_STATE_CHANGE\n}\n\nexport function isPhotoRequest(message: CloudToGlassesMessage): message is PhotoRequestToGlasses {\n return message.type === CloudToGlassesMessageType.PHOTO_REQUEST\n}\n\nexport function isRgbLedControl(message: CloudToGlassesMessage): message is RgbLedControlToGlasses {\n return message.type === CloudToGlassesMessageType.RGB_LED_CONTROL\n}\n\nexport function isSettingsUpdate(message: CloudToGlassesMessage): message is SettingsUpdate {\n return message.type === CloudToGlassesMessageType.SETTINGS_UPDATE\n}\n\nexport function isStartRtmpStream(message: CloudToGlassesMessage): message is StartRtmpStream {\n return message.type === CloudToGlassesMessageType.START_RTMP_STREAM\n}\n\nexport function isStopRtmpStream(message: CloudToGlassesMessage): message is StopRtmpStream {\n return message.type === CloudToGlassesMessageType.STOP_RTMP_STREAM\n}\n\nexport function isKeepRtmpStreamAlive(message: CloudToGlassesMessage): message is KeepRtmpStreamAlive {\n return message.type === CloudToGlassesMessageType.KEEP_RTMP_STREAM_ALIVE\n}\n\nexport function isAudioPlayRequestToGlasses(message: CloudToGlassesMessage): message is AudioPlayRequestToGlasses {\n return message.type === CloudToGlassesMessageType.AUDIO_PLAY_REQUEST\n}\n\nexport function isAudioStopRequestToGlasses(message: CloudToGlassesMessage): message is AudioStopRequestToGlasses {\n return message.type === CloudToGlassesMessageType.AUDIO_STOP_REQUEST\n}\n",
13
- "// src/messages/app-to-cloud.ts\n\nimport {BaseMessage} from \"./base\"\nimport {AppToCloudMessageType} from \"../message-types\"\nimport {ExtendedStreamType, LocationStreamRequest} from \"../streams\"\nimport {DisplayRequest} from \"../layouts\"\nimport {DashboardContentUpdate, DashboardModeChange, DashboardSystemUpdate} from \"../dashboard\"\nimport type {VideoConfig, AudioConfig, StreamConfig} from \"../rtmp-stream\"\nimport {LedColor} from \"./cloud-to-glasses\"\n\n// a subscription can now be either a simple string or our new rich object\nexport type SubscriptionRequest = ExtendedStreamType | LocationStreamRequest\n\n/**\n * Connection initialization from App\n */\nexport interface AppConnectionInit extends BaseMessage {\n type: AppToCloudMessageType.CONNECTION_INIT\n packageName: string\n sessionId: string\n apiKey: string\n}\n\n/**\n * Subscription update from App\n */\nexport interface AppSubscriptionUpdate extends BaseMessage {\n type: AppToCloudMessageType.SUBSCRIPTION_UPDATE\n packageName: string\n subscriptions: SubscriptionRequest[]\n}\n\n/**\n * Photo request from App\n */\nexport interface PhotoRequest extends BaseMessage {\n type: AppToCloudMessageType.PHOTO_REQUEST\n packageName: string\n requestId: string // SDK-generated request ID to track the request\n saveToGallery?: boolean\n customWebhookUrl?: string // Custom webhook URL to override TPA's default\n authToken?: string // Auth token for custom webhook authentication\n /** Desired photo size sent by App. Defaults to 'medium' if omitted. */\n size?: \"small\" | \"medium\" | \"large\" | \"full\"\n /** Image compression level: none, medium, or heavy. Defaults to none. */\n compress?: \"none\" | \"medium\" | \"heavy\"\n}\n\n/**\n * RGB LED control request from App\n */\nexport interface RgbLedControlRequest extends BaseMessage {\n type: AppToCloudMessageType.RGB_LED_CONTROL\n packageName: string\n requestId: string // SDK-generated request ID to track the request\n action: \"on\" | \"off\" // Only low-level on/off actions\n color?: LedColor // LED color name\n ontime?: number // LED on duration in ms\n offtime?: number // LED off duration in ms\n count?: number // Number of on/off cycles\n}\n\n// Video, Audio and Stream configuration interfaces are imported from '../rtmp-stream'\n\n/**\n * RTMP stream request from App\n */\nexport interface RtmpStreamRequest extends BaseMessage {\n type: AppToCloudMessageType.RTMP_STREAM_REQUEST\n packageName: string\n rtmpUrl: string\n video?: VideoConfig\n audio?: AudioConfig\n stream?: StreamConfig\n}\n\n/**\n * RTMP stream stop request from App\n */\nexport interface RtmpStreamStopRequest extends BaseMessage {\n type: AppToCloudMessageType.RTMP_STREAM_STOP\n packageName: string\n streamId?: string // Optional stream ID to specify which stream to stop\n}\n\n// defines the structure for our new on-demand location poll command\nexport interface AppLocationPollRequest extends BaseMessage {\n type: AppToCloudMessageType.LOCATION_POLL_REQUEST\n packageName: string\n sessionId: string\n accuracy: string\n correlationId: string\n}\n\n/**\n * Re-stream destination for managed streams\n */\nexport interface RestreamDestination {\n /** RTMP URL like rtmp://youtube.com/live/STREAM-KEY */\n url: string\n /** Optional friendly name like \"YouTube\" or \"Twitch\" */\n name?: string\n}\n\n/**\n * Managed RTMP stream request from App\n * The cloud handles the RTMP endpoint and returns HLS/DASH URLs\n */\nexport interface ManagedStreamRequest extends BaseMessage {\n type: AppToCloudMessageType.MANAGED_STREAM_REQUEST\n packageName: string\n quality?: \"720p\" | \"1080p\"\n enableWebRTC?: boolean\n video?: VideoConfig\n audio?: AudioConfig\n stream?: StreamConfig\n /** Optional RTMP destinations to re-stream to (YouTube, Twitch, etc) */\n restreamDestinations?: RestreamDestination[]\n}\n\n/**\n * Managed RTMP stream stop request from App\n */\nexport interface ManagedStreamStopRequest extends BaseMessage {\n type: AppToCloudMessageType.MANAGED_STREAM_STOP\n packageName: string\n}\n\n/**\n * Stream status check request from App\n * Checks if there are any existing streams (managed or unmanaged) for the current user\n */\nexport interface StreamStatusCheckRequest extends BaseMessage {\n type: AppToCloudMessageType.STREAM_STATUS_CHECK\n packageName: string\n sessionId: string\n}\n\n/**\n * Audio play request from App\n */\nexport interface AudioPlayRequest extends BaseMessage {\n type: AppToCloudMessageType.AUDIO_PLAY_REQUEST\n packageName: string\n requestId: string // SDK-generated request ID to track the request\n audioUrl: string // URL to audio file for download and play\n volume?: number // Volume level 0.0-1.0, defaults to 1.0\n stopOtherAudio?: boolean // Whether to stop other audio playback, defaults to true\n /**\n * Track ID for audio playback (defaults to 0)\n * - 0: speaker (default audio playback)\n * - 1: app_audio (app-specific audio)\n * - 2: tts (text-to-speech audio)\n * Use different track IDs to play multiple audio streams simultaneously (mixing)\n */\n trackId?: number\n}\n\n/**\n * Audio stop request from App\n */\nexport interface AudioStopRequest extends BaseMessage {\n type: AppToCloudMessageType.AUDIO_STOP_REQUEST\n packageName: string\n /**\n * Track ID to stop (optional)\n * 0: speaker (default audio playback)\n * 1: app_audio (app-specific audio)\n * 2: tts (text-to-speech audio)\n * If omitted, stops all tracks\n */\n trackId?: number\n sessionId?: string // Session ID for routing\n}\n\n/**\n * WiFi setup request from App\n */\nexport interface RequestWifiSetup extends BaseMessage {\n type: AppToCloudMessageType.REQUEST_WIFI_SETUP\n packageName: string\n sessionId: string\n reason?: string\n}\n\n/**\n * Union type for all messages from Apps to cloud\n */\nexport type AppToCloudMessage =\n | AppConnectionInit\n | AppSubscriptionUpdate\n | AppLocationPollRequest\n | DisplayRequest\n | PhotoRequest\n | RgbLedControlRequest\n | AudioPlayRequest\n | AudioStopRequest\n | RtmpStreamRequest\n | RtmpStreamStopRequest\n | ManagedStreamRequest\n | ManagedStreamStopRequest\n | StreamStatusCheckRequest\n | DashboardContentUpdate\n | DashboardModeChange\n | DashboardSystemUpdate\n | RequestWifiSetup\n // New App-to-App communication messages\n | AppBroadcastMessage\n | AppDirectMessage\n | AppUserDiscovery\n | AppRoomJoin\n | AppRoomLeave\n\n/**\n * Type guard to check if a message is a App connection init\n */\nexport function isAppConnectionInit(message: AppToCloudMessage): message is AppConnectionInit {\n return message.type === AppToCloudMessageType.CONNECTION_INIT\n}\n\n/**\n * Type guard to check if a message is a App subscription update\n */\nexport function isAppSubscriptionUpdate(message: AppToCloudMessage): message is AppSubscriptionUpdate {\n return message.type === AppToCloudMessageType.SUBSCRIPTION_UPDATE\n}\n\n/**\n * Type guard to check if a message is a App display request\n */\nexport function isDisplayRequest(message: AppToCloudMessage): message is DisplayRequest {\n return message.type === AppToCloudMessageType.DISPLAY_REQUEST\n}\n\n/**\n * Type guard to check if a message is a App photo request\n */\nexport function isPhotoRequest(message: AppToCloudMessage): message is PhotoRequest {\n return message.type === AppToCloudMessageType.PHOTO_REQUEST\n}\n\n/**\n * Type guard to check if a message is a RGB LED control request\n */\nexport function isRgbLedControlRequest(message: AppToCloudMessage): message is RgbLedControlRequest {\n return message.type === AppToCloudMessageType.RGB_LED_CONTROL\n}\n\n/**\n * Type guard to check if a message is a App audio play request\n */\nexport function isAudioPlayRequest(message: AppToCloudMessage): message is AudioPlayRequest {\n return message.type === AppToCloudMessageType.AUDIO_PLAY_REQUEST\n}\n\n/**\n * Type guard to check if a message is a App audio stop request\n */\nexport function isAudioStopRequest(message: AppToCloudMessage): message is AudioStopRequest {\n return message.type === AppToCloudMessageType.AUDIO_STOP_REQUEST\n}\n\n/**\n * Type guard to check if a message is a dashboard content update\n */\nexport function isDashboardContentUpdate(message: AppToCloudMessage): message is DashboardContentUpdate {\n return message.type === AppToCloudMessageType.DASHBOARD_CONTENT_UPDATE\n}\n\n/**\n * Type guard to check if a message is a dashboard mode change\n */\nexport function isDashboardModeChange(message: AppToCloudMessage): message is DashboardModeChange {\n return message.type === AppToCloudMessageType.DASHBOARD_MODE_CHANGE\n}\n\n/**\n * Type guard to check if a message is a dashboard system update\n */\nexport function isDashboardSystemUpdate(message: AppToCloudMessage): message is DashboardSystemUpdate {\n return message.type === AppToCloudMessageType.DASHBOARD_SYSTEM_UPDATE\n}\n\n/**\n * Type guard to check if a message is a managed stream request\n */\nexport function isManagedStreamRequest(message: AppToCloudMessage): message is ManagedStreamRequest {\n return message.type === AppToCloudMessageType.MANAGED_STREAM_REQUEST\n}\n\n/**\n * Type guard to check if a message is a managed stream stop request\n */\nexport function isManagedStreamStopRequest(message: AppToCloudMessage): message is ManagedStreamStopRequest {\n return message.type === AppToCloudMessageType.MANAGED_STREAM_STOP\n}\n\n//===========================================================\n// App-to-App Communication Messages\n//===========================================================\n\n/**\n * Broadcast message to all users with the same App active\n */\nexport interface AppBroadcastMessage extends BaseMessage {\n type: AppToCloudMessageType.APP_BROADCAST_MESSAGE\n packageName: string\n sessionId: string\n payload: any\n messageId: string\n senderUserId: string\n}\n\n/**\n * Direct message to a specific user with the same App active\n */\nexport interface AppDirectMessage extends BaseMessage {\n type: AppToCloudMessageType.APP_DIRECT_MESSAGE\n packageName: string\n sessionId: string\n targetUserId: string\n payload: any\n messageId: string\n senderUserId: string\n}\n\n/**\n * Request to discover other users with the same App active\n */\nexport interface AppUserDiscovery extends BaseMessage {\n type: AppToCloudMessageType.APP_USER_DISCOVERY\n packageName: string\n sessionId: string\n includeUserProfiles?: boolean\n}\n\n/**\n * Join a communication room for group messaging\n */\nexport interface AppRoomJoin extends BaseMessage {\n type: AppToCloudMessageType.APP_ROOM_JOIN\n packageName: string\n sessionId: string\n roomId: string\n roomConfig?: {\n maxUsers?: number\n isPrivate?: boolean\n metadata?: any\n }\n}\n\n/**\n * Leave a communication room\n */\nexport interface AppRoomLeave extends BaseMessage {\n type: AppToCloudMessageType.APP_ROOM_LEAVE\n packageName: string\n sessionId: string\n roomId: string\n}\n\n/**\n * Type guard to check if a message is an RTMP stream request\n */\nexport function isRtmpStreamRequest(message: AppToCloudMessage): message is RtmpStreamRequest {\n return message.type === AppToCloudMessageType.RTMP_STREAM_REQUEST\n}\n\n/**\n * Type guard to check if a message is an RTMP stream stop request\n */\nexport function isRtmpStreamStopRequest(message: AppToCloudMessage): message is RtmpStreamStopRequest {\n return message.type === AppToCloudMessageType.RTMP_STREAM_STOP\n}\n",
13
+ "// src/messages/app-to-cloud.ts\n\nimport {BaseMessage} from \"./base\"\nimport {AppToCloudMessageType} from \"../message-types\"\nimport {ExtendedStreamType, LocationStreamRequest} from \"../streams\"\nimport {DisplayRequest} from \"../layouts\"\nimport {DashboardContentUpdate, DashboardModeChange, DashboardSystemUpdate} from \"../dashboard\"\nimport type {VideoConfig, AudioConfig, StreamConfig} from \"../rtmp-stream\"\nimport {LedColor} from \"./cloud-to-glasses\"\n\n// a subscription can now be either a simple string or our new rich object\nexport type SubscriptionRequest = ExtendedStreamType | LocationStreamRequest\n\n/**\n * Connection initialization from App\n */\nexport interface AppConnectionInit extends BaseMessage {\n type: AppToCloudMessageType.CONNECTION_INIT\n packageName: string\n sessionId: string\n apiKey: string\n}\n\n/**\n * Subscription update from App\n */\nexport interface AppSubscriptionUpdate extends BaseMessage {\n type: AppToCloudMessageType.SUBSCRIPTION_UPDATE\n packageName: string\n subscriptions: SubscriptionRequest[]\n}\n\n/**\n * Photo request from App\n */\nexport interface PhotoRequest extends BaseMessage {\n type: AppToCloudMessageType.PHOTO_REQUEST\n packageName: string\n requestId: string // SDK-generated request ID to track the request\n saveToGallery?: boolean\n customWebhookUrl?: string // Custom webhook URL to override TPA's default\n authToken?: string // Auth token for custom webhook authentication\n /** Desired photo size sent by App. Defaults to 'medium' if omitted. */\n size?: \"small\" | \"medium\" | \"large\" | \"full\"\n /** Image compression level: none, medium, or heavy. Defaults to none. */\n compress?: \"none\" | \"medium\" | \"heavy\"\n}\n\n/**\n * RGB LED control request from App\n */\nexport interface RgbLedControlRequest extends BaseMessage {\n type: AppToCloudMessageType.RGB_LED_CONTROL\n packageName: string\n requestId: string // SDK-generated request ID to track the request\n action: \"on\" | \"off\" // Only low-level on/off actions\n color?: LedColor // LED color name\n ontime?: number // LED on duration in ms\n offtime?: number // LED off duration in ms\n count?: number // Number of on/off cycles\n}\n\n// Video, Audio and Stream configuration interfaces are imported from '../rtmp-stream'\n\n/**\n * RTMP stream request from App\n */\nexport interface RtmpStreamRequest extends BaseMessage {\n type: AppToCloudMessageType.RTMP_STREAM_REQUEST\n packageName: string\n rtmpUrl: string\n video?: VideoConfig\n audio?: AudioConfig\n stream?: StreamConfig\n}\n\n/**\n * RTMP stream stop request from App\n */\nexport interface RtmpStreamStopRequest extends BaseMessage {\n type: AppToCloudMessageType.RTMP_STREAM_STOP\n packageName: string\n streamId?: string // Optional stream ID to specify which stream to stop\n}\n\n// defines the structure for our new on-demand location poll command\nexport interface AppLocationPollRequest extends BaseMessage {\n type: AppToCloudMessageType.LOCATION_POLL_REQUEST\n packageName: string\n sessionId: string\n accuracy: string\n correlationId: string\n}\n\n/**\n * Re-stream destination for managed streams\n */\nexport interface RestreamDestination {\n /** RTMP URL like rtmp://youtube.com/live/STREAM-KEY */\n url: string\n /** Optional friendly name like \"YouTube\" or \"Twitch\" */\n name?: string\n}\n\n/**\n * Managed RTMP stream request from App\n * The cloud handles the RTMP endpoint and returns HLS/DASH URLs\n */\nexport interface ManagedStreamRequest extends BaseMessage {\n type: AppToCloudMessageType.MANAGED_STREAM_REQUEST\n packageName: string\n quality?: \"720p\" | \"1080p\"\n enableWebRTC?: boolean\n video?: VideoConfig\n audio?: AudioConfig\n stream?: StreamConfig\n /** Optional RTMP destinations to re-stream to (YouTube, Twitch, etc) */\n restreamDestinations?: RestreamDestination[]\n}\n\n/**\n * Managed RTMP stream stop request from App\n */\nexport interface ManagedStreamStopRequest extends BaseMessage {\n type: AppToCloudMessageType.MANAGED_STREAM_STOP\n packageName: string\n}\n\n/**\n * Stream status check request from App\n * Checks if there are any existing streams (managed or unmanaged) for the current user\n */\nexport interface StreamStatusCheckRequest extends BaseMessage {\n type: AppToCloudMessageType.STREAM_STATUS_CHECK\n packageName: string\n sessionId: string\n}\n\n/**\n * Audio play request from App\n */\nexport interface AudioPlayRequest extends BaseMessage {\n type: AppToCloudMessageType.AUDIO_PLAY_REQUEST\n packageName: string\n requestId: string // SDK-generated request ID to track the request\n audioUrl: string // URL to audio file for download and play\n volume?: number // Volume level 0.0-1.0, defaults to 1.0\n stopOtherAudio?: boolean // Whether to stop other audio playback, defaults to true\n /**\n * Track ID for audio playback (defaults to 0)\n * - 0: speaker (default audio playback)\n * - 1: app_audio (app-specific audio)\n * - 2: tts (text-to-speech audio)\n * Use different track IDs to play multiple audio streams simultaneously (mixing)\n */\n trackId?: number\n}\n\n/**\n * Audio stop request from App\n */\nexport interface AudioStopRequest extends BaseMessage {\n type: AppToCloudMessageType.AUDIO_STOP_REQUEST\n packageName: string\n /**\n * Track ID to stop (optional)\n * 0: speaker (default audio playback)\n * 1: app_audio (app-specific audio)\n * 2: tts (text-to-speech audio)\n * If omitted, stops all tracks\n */\n trackId?: number\n sessionId?: string // Session ID for routing\n}\n\n/**\n * WiFi setup request from App\n */\nexport interface RequestWifiSetup extends BaseMessage {\n type: AppToCloudMessageType.REQUEST_WIFI_SETUP\n packageName: string\n sessionId: string\n reason?: string\n}\n\n/**\n * Ownership release message from App\n * Sent before intentional disconnect to signal clean handoff (no resurrection needed)\n */\nexport interface OwnershipReleaseMessage extends BaseMessage {\n type: AppToCloudMessageType.OWNERSHIP_RELEASE\n packageName: string\n sessionId: string\n reason: \"switching_clouds\" | \"clean_shutdown\" | \"user_logout\"\n}\n\n/**\n * Union type for all messages from Apps to cloud\n */\nexport type AppToCloudMessage =\n | AppConnectionInit\n | AppSubscriptionUpdate\n | AppLocationPollRequest\n | DisplayRequest\n | PhotoRequest\n | RgbLedControlRequest\n | AudioPlayRequest\n | AudioStopRequest\n | RtmpStreamRequest\n | RtmpStreamStopRequest\n | ManagedStreamRequest\n | ManagedStreamStopRequest\n | StreamStatusCheckRequest\n | DashboardContentUpdate\n | DashboardModeChange\n | DashboardSystemUpdate\n | RequestWifiSetup\n // Session lifecycle\n | OwnershipReleaseMessage\n // New App-to-App communication messages\n | AppBroadcastMessage\n | AppDirectMessage\n | AppUserDiscovery\n | AppRoomJoin\n | AppRoomLeave\n\n/**\n * Type guard to check if a message is a App connection init\n */\nexport function isAppConnectionInit(message: AppToCloudMessage): message is AppConnectionInit {\n return message.type === AppToCloudMessageType.CONNECTION_INIT\n}\n\n/**\n * Type guard to check if a message is a App subscription update\n */\nexport function isAppSubscriptionUpdate(message: AppToCloudMessage): message is AppSubscriptionUpdate {\n return message.type === AppToCloudMessageType.SUBSCRIPTION_UPDATE\n}\n\n/**\n * Type guard to check if a message is a App display request\n */\nexport function isDisplayRequest(message: AppToCloudMessage): message is DisplayRequest {\n return message.type === AppToCloudMessageType.DISPLAY_REQUEST\n}\n\n/**\n * Type guard to check if a message is a App photo request\n */\nexport function isPhotoRequest(message: AppToCloudMessage): message is PhotoRequest {\n return message.type === AppToCloudMessageType.PHOTO_REQUEST\n}\n\n/**\n * Type guard to check if a message is a RGB LED control request\n */\nexport function isRgbLedControlRequest(message: AppToCloudMessage): message is RgbLedControlRequest {\n return message.type === AppToCloudMessageType.RGB_LED_CONTROL\n}\n\n/**\n * Type guard to check if a message is a App audio play request\n */\nexport function isAudioPlayRequest(message: AppToCloudMessage): message is AudioPlayRequest {\n return message.type === AppToCloudMessageType.AUDIO_PLAY_REQUEST\n}\n\n/**\n * Type guard to check if a message is a App audio stop request\n */\nexport function isAudioStopRequest(message: AppToCloudMessage): message is AudioStopRequest {\n return message.type === AppToCloudMessageType.AUDIO_STOP_REQUEST\n}\n\n/**\n * Type guard to check if a message is a dashboard content update\n */\nexport function isDashboardContentUpdate(message: AppToCloudMessage): message is DashboardContentUpdate {\n return message.type === AppToCloudMessageType.DASHBOARD_CONTENT_UPDATE\n}\n\n/**\n * Type guard to check if a message is a dashboard mode change\n */\nexport function isDashboardModeChange(message: AppToCloudMessage): message is DashboardModeChange {\n return message.type === AppToCloudMessageType.DASHBOARD_MODE_CHANGE\n}\n\n/**\n * Type guard to check if a message is a dashboard system update\n */\nexport function isDashboardSystemUpdate(message: AppToCloudMessage): message is DashboardSystemUpdate {\n return message.type === AppToCloudMessageType.DASHBOARD_SYSTEM_UPDATE\n}\n\n/**\n * Type guard to check if a message is a managed stream request\n */\nexport function isManagedStreamRequest(message: AppToCloudMessage): message is ManagedStreamRequest {\n return message.type === AppToCloudMessageType.MANAGED_STREAM_REQUEST\n}\n\n/**\n * Type guard to check if a message is a managed stream stop request\n */\nexport function isManagedStreamStopRequest(message: AppToCloudMessage): message is ManagedStreamStopRequest {\n return message.type === AppToCloudMessageType.MANAGED_STREAM_STOP\n}\n\n//===========================================================\n// App-to-App Communication Messages\n//===========================================================\n\n/**\n * Broadcast message to all users with the same App active\n */\nexport interface AppBroadcastMessage extends BaseMessage {\n type: AppToCloudMessageType.APP_BROADCAST_MESSAGE\n packageName: string\n sessionId: string\n payload: any\n messageId: string\n senderUserId: string\n}\n\n/**\n * Direct message to a specific user with the same App active\n */\nexport interface AppDirectMessage extends BaseMessage {\n type: AppToCloudMessageType.APP_DIRECT_MESSAGE\n packageName: string\n sessionId: string\n targetUserId: string\n payload: any\n messageId: string\n senderUserId: string\n}\n\n/**\n * Request to discover other users with the same App active\n */\nexport interface AppUserDiscovery extends BaseMessage {\n type: AppToCloudMessageType.APP_USER_DISCOVERY\n packageName: string\n sessionId: string\n includeUserProfiles?: boolean\n}\n\n/**\n * Join a communication room for group messaging\n */\nexport interface AppRoomJoin extends BaseMessage {\n type: AppToCloudMessageType.APP_ROOM_JOIN\n packageName: string\n sessionId: string\n roomId: string\n roomConfig?: {\n maxUsers?: number\n isPrivate?: boolean\n metadata?: any\n }\n}\n\n/**\n * Leave a communication room\n */\nexport interface AppRoomLeave extends BaseMessage {\n type: AppToCloudMessageType.APP_ROOM_LEAVE\n packageName: string\n sessionId: string\n roomId: string\n}\n\n/**\n * Type guard to check if a message is an RTMP stream request\n */\nexport function isRtmpStreamRequest(message: AppToCloudMessage): message is RtmpStreamRequest {\n return message.type === AppToCloudMessageType.RTMP_STREAM_REQUEST\n}\n\n/**\n * Type guard to check if a message is an RTMP stream stop request\n */\nexport function isRtmpStreamStopRequest(message: AppToCloudMessage): message is RtmpStreamStopRequest {\n return message.type === AppToCloudMessageType.RTMP_STREAM_STOP\n}\n\n/**\n * Type guard to check if a message is an ownership release message\n */\nexport function isOwnershipRelease(message: AppToCloudMessage): message is OwnershipReleaseMessage {\n return message.type === AppToCloudMessageType.OWNERSHIP_RELEASE\n}\n",
14
14
  "/**\n * 🎨 Bitmap Utilities Module\n *\n * Provides helper functions for working with bitmap images in MentraOS applications.\n * Includes file loading, data validation, and format conversion utilities.\n *\n * @example\n * ```typescript\n * import { BitmapUtils } from '@mentra/sdk';\n *\n * // Load a single BMP file\n * const bmpHex = await BitmapUtils.loadBmpAsHex('./my-image.bmp');\n * session.layouts.showBitmapView(bmpHex);\n *\n * // Load multiple animation frames\n * const frames = await BitmapUtils.loadBmpFrames('./animations', 10);\n * session.layouts.showBitmapAnimation(frames, 1500, true);\n * ```\n */\n\nimport * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport { Jimp } from \"jimp\";\n\n/**\n * Validation result for bitmap data\n */\nexport interface BitmapValidation {\n /** Whether the bitmap data is valid */\n isValid: boolean;\n /** Total byte count of the bitmap */\n byteCount: number;\n /** Number of black (non-FF) pixels found */\n blackPixels: number;\n /** Array of validation error messages */\n errors: string[];\n /** Additional metadata about the bitmap */\n metadata?: {\n /** Expected bitmap dimensions (if detectable) */\n dimensions?: { width: number; height: number };\n /** Bitmap file format info */\n format?: string;\n };\n}\n\n/**\n * Options for loading bitmap frames\n */\nexport interface LoadFramesOptions {\n /** File name pattern (default: 'animation_10_frame_{i}.bmp') */\n filePattern?: string;\n /** Starting frame number (default: 1) */\n startFrame?: number;\n /** Validate each frame during loading (default: true) */\n validateFrames?: boolean;\n /** Continue loading if a frame is missing (default: false) */\n skipMissingFrames?: boolean;\n}\n\n/**\n * Utility class for working with bitmap images in MentraOS applications\n */\nexport class BitmapUtils {\n static async convert24BitTo1BitBMP(input24BitBmp: Buffer): Promise<Buffer> {\n // Read header information from 24-bit BMP\n const width = input24BitBmp.readUInt32LE(18);\n const height = Math.abs(input24BitBmp.readInt32LE(22)); // Height can be negative (top-down BMP)\n const isTopDown = input24BitBmp.readInt32LE(22) < 0;\n const bitsPerPixel = input24BitBmp.readUInt16LE(28);\n\n if (bitsPerPixel !== 24) {\n throw new Error(\"Input must be a 24-bit BMP\");\n }\n\n // Calculate row sizes (both must be 4-byte aligned)\n const rowSize24 = Math.ceil((width * 3) / 4) * 4;\n const rowSize1 = Math.ceil(width / 32) * 4; // 32 pixels per 4 bytes\n\n // Calculate sizes for 1-bit BMP\n const colorTableSize = 8; // 2 colors * 4 bytes each\n const headerSize = 54 + colorTableSize;\n const pixelDataSize = rowSize1 * height;\n const fileSize = headerSize + pixelDataSize;\n\n // Create new buffer for 1-bit BMP\n const output1BitBmp = Buffer.alloc(fileSize);\n let offset = 0;\n\n // Write BMP file header (14 bytes)\n output1BitBmp.write(\"BM\", offset);\n offset += 2; // Signature\n output1BitBmp.writeUInt32LE(fileSize, offset);\n offset += 4; // File size\n output1BitBmp.writeUInt16LE(0, offset);\n offset += 2; // Reserved 1\n output1BitBmp.writeUInt16LE(0, offset);\n offset += 2; // Reserved 2\n output1BitBmp.writeUInt32LE(headerSize, offset);\n offset += 4; // Pixel data offset\n\n // Write DIB header (40 bytes)\n output1BitBmp.writeUInt32LE(40, offset);\n offset += 4; // DIB header size\n output1BitBmp.writeInt32LE(width, offset);\n offset += 4; // Width\n output1BitBmp.writeInt32LE(height, offset);\n offset += 4; // Height (positive for bottom-up)\n output1BitBmp.writeUInt16LE(1, offset);\n offset += 2; // Planes\n output1BitBmp.writeUInt16LE(1, offset);\n offset += 2; // Bits per pixel (1-bit)\n output1BitBmp.writeUInt32LE(0, offset);\n offset += 4; // Compression (none)\n output1BitBmp.writeUInt32LE(pixelDataSize, offset);\n offset += 4; // Image size\n output1BitBmp.writeInt32LE(2835, offset);\n offset += 4; // X pixels per meter (72 DPI)\n output1BitBmp.writeInt32LE(2835, offset);\n offset += 4; // Y pixels per meter (72 DPI)\n output1BitBmp.writeUInt32LE(2, offset);\n offset += 4; // Colors used\n output1BitBmp.writeUInt32LE(2, offset);\n offset += 4; // Important colors\n\n // Write color table (8 bytes)\n // Black (index 0): B=0, G=0, R=0, Reserved=0\n output1BitBmp.writeUInt32LE(0x00000000, offset);\n offset += 4;\n // White (index 1): B=255, G=255, R=255, Reserved=0\n output1BitBmp.writeUInt8(255, offset++); // Blue\n output1BitBmp.writeUInt8(255, offset++); // Green\n output1BitBmp.writeUInt8(255, offset++); // Red\n output1BitBmp.writeUInt8(0, offset++); // Reserved\n\n // Convert pixel data from 24-bit to 1-bit\n const pixelDataStart24 = 54; // 24-bit BMP has no color table\n\n for (let y = 0; y < height; y++) {\n // BMP files are usually stored bottom-up\n const sourceY = isTopDown ? y : height - 1 - y;\n const destY = height - 1 - y; // Always write bottom-up for compatibility\n\n // Initialize the row with zeros\n const rowData = Buffer.alloc(rowSize1);\n\n for (let x = 0; x < width; x++) {\n // Get pixel from 24-bit BMP\n const offset24 = pixelDataStart24 + sourceY * rowSize24 + x * 3;\n const blue = input24BitBmp[offset24];\n const green = input24BitBmp[offset24 + 1];\n const red = input24BitBmp[offset24 + 2];\n\n // Determine if pixel is white (assuming pure black or white)\n // White = 1, Black = 0\n const isWhite = red > 128 || green > 128 || blue > 128 ? 1 : 0;\n\n // Calculate bit position\n const byteIndex = Math.floor(x / 8);\n const bitPosition = 7 - (x % 8); // MSB first\n\n // Set bit if white\n if (isWhite) {\n rowData[byteIndex] |= 1 << bitPosition;\n }\n }\n\n // Write row to output buffer\n const destOffset = offset + destY * rowSize1;\n rowData.copy(output1BitBmp, destOffset);\n }\n\n return output1BitBmp;\n }\n\n /**\n * Load a BMP file as hex string from filesystem\n *\n * @param filePath - Path to the BMP file\n * @returns Promise resolving to hex-encoded bitmap data\n * @throws Error if file cannot be read or is not a valid BMP\n *\n * @example\n * ```typescript\n * const bmpBase64 = await BitmapUtils.loadBmpFromFileAsBase64('./assets/icon.bmp');\n * session.layouts.showBitmapView(bmpBase64);\n * ```\n */\n static async fileToBase64(filePath: string): Promise<string> {\n try {\n const bmpData = await fs.readFile(filePath);\n\n return this.bufferToBase64(bmpData);\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(\n `Failed to load BMP file ${filePath}: ${error.message}`,\n );\n }\n throw new Error(`Failed to load BMP file ${filePath}: Unknown error`);\n }\n }\n\n static async bufferToBase64(bmpData: Buffer): Promise<string> {\n return bmpData.toString(\"base64\");\n }\n\n static async padBase64Bitmap(\n bmpBase64: string,\n padding?: { left: number; top: number },\n ): Promise<string> {\n const buffer = Buffer.from(bmpBase64, \"base64\");\n const paddedBuffer = await this.padBmpForGlasses(\n buffer,\n padding?.left,\n padding?.top,\n );\n return paddedBuffer.toString(\"base64\");\n }\n\n static async padBmpForGlasses(\n bmpData: Buffer,\n leftPadding: number = 50,\n topPadding: number = 35,\n ): Promise<Buffer> {\n try {\n // Basic BMP validation - check for BMP signature\n if (bmpData.length < 14 || bmpData[0] !== 0x42 || bmpData[1] !== 0x4d) {\n throw new Error(\n `Bmp data is not a valid BMP file (missing BM signature)`,\n );\n }\n\n let finalBmpData = bmpData;\n\n // Load the image with Jimp\n const image = await Jimp.read(bmpData);\n\n // Check if we need to add padding\n if (image.width !== 576 || image.height !== 135) {\n console.log(\n `Adding padding to BMP since it isn't 576x135 (assuming it's 526x100!)(current: ${image.width}x${image.height})`,\n );\n\n // Create a new 576x135 white canvas\n const paddedImage = new Jimp({\n width: 576,\n height: 135,\n color: 0x00000000,\n });\n\n // // Calculate position to place the original image (with padding)\n const leftPadding = 50; // 45px padding on left\n const topPadding = 35; // 35px padding on top\n\n // Composite the original image onto the white canvas\n // paddedImage.composite(image, leftPadding, topPadding);\n paddedImage.composite(image, leftPadding, topPadding);\n\n finalBmpData = await this.convert24BitTo1BitBMP(\n await paddedImage.getBuffer(\"image/bmp\"),\n );\n }\n // No padding needed, just return as hex\n console.log(`finalBmpData: ${finalBmpData.length} bytes`);\n return finalBmpData;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to load BMP data: ${error.message}`);\n }\n throw new Error(`Failed to load BMP data: Unknown error`);\n }\n }\n\n /**\n * Load multiple BMP frames as hex array for animations\n *\n * @param basePath - Directory containing the frame files\n * @param frameCount - Number of frames to load\n * @param options - Loading options and configuration\n * @returns Promise resolving to array of hex-encoded bitmap data\n *\n * @example\n * ```typescript\n * // Load 10 frames with default pattern\n * const frames = await BitmapUtils.loadBmpFrames('./animations', 10);\n *\n * // Load with custom pattern\n * const customFrames = await BitmapUtils.loadBmpFrames('./sprites', 8, {\n * filePattern: 'sprite_{i}.bmp',\n * startFrame: 0\n * });\n * ```\n */\n static async loadBmpFrames(\n basePath: string,\n frameCount: number,\n options: LoadFramesOptions = {},\n ): Promise<string[]> {\n const {\n filePattern = \"animation_10_frame_{i}.bmp\",\n startFrame = 1,\n validateFrames = true,\n skipMissingFrames = false,\n } = options;\n\n const frames: string[] = [];\n const errors: string[] = [];\n\n for (let i = 0; i < frameCount; i++) {\n const frameNumber = startFrame + i;\n const fileName = filePattern.replace(\"{i}\", frameNumber.toString());\n const filePath = path.join(basePath, fileName);\n\n try {\n const frameBase64 = await this.fileToBase64(filePath);\n\n if (validateFrames) {\n const validation = this.validateBase64Bitmap(frameBase64);\n if (!validation.isValid) {\n const errorMsg = `Frame ${frameNumber} validation failed: ${validation.errors.join(\n \", \",\n )}`;\n if (skipMissingFrames) {\n console.warn(`⚠️ ${errorMsg} - skipping`);\n continue;\n } else {\n throw new Error(errorMsg);\n }\n }\n console.log(\n `✅ Frame ${frameNumber} validated (${validation.blackPixels} black pixels)`,\n );\n }\n\n frames.push(frameBase64);\n } catch (error) {\n const errorMsg = `Failed to load frame ${frameNumber} (${fileName}): ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`;\n\n if (skipMissingFrames) {\n console.warn(`⚠️ ${errorMsg} - skipping`);\n continue;\n } else {\n errors.push(errorMsg);\n }\n }\n }\n\n if (errors.length > 0) {\n throw new Error(`Failed to load frames:\\n${errors.join(\"\\n\")}`);\n }\n\n if (frames.length === 0) {\n throw new Error(`No valid frames loaded from ${basePath}`);\n }\n\n console.log(`📚 Loaded ${frames.length} animation frames from ${basePath}`);\n return frames;\n }\n\n /**\n * Validate BMP hex data integrity and extract metadata\n *\n * @param hexString - Hex-encoded bitmap data\n * @returns Validation result with detailed information\n *\n * @example\n * ```typescript\n * const validation = BitmapUtils.validateBmpHex(bmpHex);\n * if (!validation.isValid) {\n * console.error('Invalid bitmap:', validation.errors);\n * } else {\n * console.log(`Valid bitmap: ${validation.blackPixels} black pixels`);\n * }\n * ```\n */\n static validateBase64Bitmap(bmpFrame: string): BitmapValidation {\n const errors: string[] = [];\n let byteCount = 0;\n let blackPixels = 0;\n const metadata: BitmapValidation[\"metadata\"] = {};\n\n try {\n const hexString = Buffer.from(bmpFrame, \"base64\").toString(\"hex\");\n // Basic hex validation\n if (typeof hexString !== \"string\" || hexString.length === 0) {\n errors.push(\"Hex string is empty or invalid\");\n return { isValid: false, byteCount: 0, blackPixels: 0, errors };\n }\n\n if (hexString.length % 2 !== 0) {\n errors.push(\"Hex string length must be even\");\n return { isValid: false, byteCount: 0, blackPixels: 0, errors };\n }\n\n // Convert to buffer\n const buffer = Buffer.from(hexString, \"hex\");\n byteCount = buffer.length;\n\n // BMP signature validation\n if (buffer.length < 14) {\n errors.push(\n \"File too small to be a valid BMP (minimum 14 bytes for header)\",\n );\n } else {\n if (buffer[0] !== 0x42 || buffer[1] !== 0x4d) {\n errors.push('Invalid BMP signature (should start with \"BM\")');\n }\n }\n\n // Size validation for MentraOS (576x135 = ~9782 bytes expected)\n const expectedSize = 9782;\n if (buffer.length < expectedSize - 100) {\n // Allow some tolerance\n errors.push(\n `BMP too small (${buffer.length} bytes, expected ~${expectedSize})`,\n );\n } else if (buffer.length > expectedSize + 1000) {\n // Allow some tolerance\n errors.push(\n `BMP too large (${buffer.length} bytes, expected ~${expectedSize})`,\n );\n }\n\n // Extract BMP metadata if header is valid\n if (buffer.length >= 54) {\n try {\n // BMP width and height are at offsets 18 and 22 (little-endian)\n const width = buffer.readUInt32LE(18);\n const height = buffer.readUInt32LE(22);\n metadata.dimensions = { width, height };\n metadata.format = \"BMP\";\n\n // Validate dimensions for MentraOS glasses\n if (width !== 576 || height !== 135) {\n errors.push(\n `Invalid dimensions (${width}x${height}, expected 576x135 for MentraOS)`,\n );\n }\n } catch (e) {\n errors.push(\"Failed to parse BMP header metadata\");\n }\n }\n\n // Pixel data validation (assumes 54-byte header + pixel data)\n if (buffer.length > 62) {\n const pixelData = buffer.slice(62); // Skip BMP header\n blackPixels = Array.from(pixelData).filter((b) => b !== 0xff).length;\n\n if (blackPixels === 0) {\n errors.push(\"No black pixels found (image appears to be all white)\");\n }\n } else {\n errors.push(\"File too small to contain pixel data\");\n }\n } catch (error) {\n errors.push(\n `Failed to parse hex data: ${\n error instanceof Error ? error.message : \"Unknown error\"\n }`,\n );\n }\n\n return {\n isValid: errors.length === 0,\n byteCount,\n blackPixels,\n errors,\n metadata: Object.keys(metadata).length > 0 ? metadata : undefined,\n };\n }\n\n /**\n * Convert bitmap data between different formats\n *\n * @param data - Input bitmap data\n * @param fromFormat - Source format ('hex' | 'base64' | 'buffer')\n * @param toFormat - Target format ('hex' | 'base64' | 'buffer')\n * @returns Converted bitmap data\n *\n * @example\n * ```typescript\n * const base64Data = BitmapUtils.convertFormat(hexData, 'hex', 'base64');\n * const bufferData = BitmapUtils.convertFormat(base64Data, 'base64', 'buffer');\n * ```\n */\n static convertFormat(\n data: string | Buffer,\n fromFormat: \"hex\" | \"base64\" | \"buffer\",\n toFormat: \"hex\" | \"base64\" | \"buffer\",\n ): string | Buffer {\n let buffer: Buffer;\n\n // Convert input to buffer\n switch (fromFormat) {\n case \"hex\":\n buffer = Buffer.from(data as string, \"hex\");\n break;\n case \"base64\":\n buffer = Buffer.from(data as string, \"base64\");\n break;\n case \"buffer\":\n buffer = data as Buffer;\n break;\n default:\n throw new Error(`Unsupported source format: ${fromFormat}`);\n }\n\n // Convert buffer to target format\n switch (toFormat) {\n case \"hex\":\n return buffer.toString(\"hex\");\n case \"base64\":\n return buffer.toString(\"base64\");\n case \"buffer\":\n return buffer;\n default:\n throw new Error(`Unsupported target format: ${toFormat}`);\n }\n }\n\n /**\n * Get bitmap information without full validation\n *\n * @param hexString - Hex-encoded bitmap data\n * @returns Basic bitmap information\n *\n * @example\n * ```typescript\n * const info = BitmapUtils.getBitmapInfo(bmpHex);\n * console.log(`Bitmap: ${info.width}x${info.height}, ${info.blackPixels} black pixels`);\n * ```\n */\n static getBitmapInfo(hexString: string): {\n byteCount: number;\n blackPixels: number;\n width?: number;\n height?: number;\n isValidBmp: boolean;\n } {\n try {\n const buffer = Buffer.from(hexString, \"hex\");\n const isValidBmp =\n buffer.length >= 14 && buffer[0] === 0x42 && buffer[1] === 0x4d;\n\n let width: number | undefined;\n let height: number | undefined;\n\n if (isValidBmp && buffer.length >= 54) {\n try {\n width = buffer.readUInt32LE(18);\n height = buffer.readUInt32LE(22);\n } catch (e) {\n // Ignore metadata parsing errors\n }\n }\n\n const pixelData = buffer.slice(62);\n const blackPixels = Array.from(pixelData).filter(\n (b) => b !== 0xff,\n ).length;\n\n return {\n byteCount: buffer.length,\n blackPixels,\n width,\n height,\n isValidBmp,\n };\n } catch (error) {\n return {\n byteCount: 0,\n blackPixels: 0,\n isValidBmp: false,\n };\n }\n }\n}\n",
15
15
  "/**\n * 🎬 Animation Utilities Module\n *\n * Provides helper functions for creating and managing bitmap animations in MentraOS applications.\n * Includes timing utilities, animation factories, and performance optimization helpers.\n *\n * @example\n * ```typescript\n * import { AnimationUtils } from '@mentra/sdk';\n *\n * // Create animation from files\n * const animation = await AnimationUtils.createBitmapAnimation(\n * session, './frames', 10, 1750, true\n * );\n *\n * // Simple delay utility\n * await AnimationUtils.delay(2000);\n *\n * // Stop animation\n * animation.stop();\n * ```\n */\n\nimport { AppSession } from \"../app/session\";\nimport { BitmapUtils, LoadFramesOptions } from \"./bitmap-utils\";\n\n/**\n * Configuration options for bitmap animations\n */\nexport interface AnimationConfig {\n /** Time between frames in milliseconds (default: 1750ms - optimized for MentraOS) */\n intervalMs?: number;\n /** Whether to loop the animation continuously (default: false) */\n repeat?: boolean;\n /** Validate frames before starting animation (default: true) */\n validateFrames?: boolean;\n /** Options for loading frames from files */\n loadOptions?: LoadFramesOptions;\n /** Callback fired when animation starts */\n onStart?: () => void;\n /** Callback fired when animation stops/completes */\n onStop?: () => void;\n /** Callback fired on each frame display */\n onFrame?: (frameIndex: number, totalFrames: number) => void;\n /** Callback fired if animation encounters an error */\n onError?: (error: string) => void;\n}\n\n/**\n * Animation controller interface\n */\nexport interface AnimationController {\n /** Stop the animation */\n stop: () => void;\n /** Check if animation is currently running */\n isRunning: () => boolean;\n /** Get current frame index */\n getCurrentFrame: () => number;\n /** Get total frame count */\n getTotalFrames: () => number;\n}\n\n/**\n * Performance timing information\n */\nexport interface TimingInfo {\n /** Target interval between frames */\n targetInterval: number;\n /** Actual measured interval between frames */\n actualInterval: number;\n /** Timing drift (difference between target and actual) */\n drift: number;\n /** Frame rate (frames per second) */\n fps: number;\n}\n\n/**\n * Utility class for creating and managing animations in MentraOS applications\n */\nexport class AnimationUtils {\n /**\n * Simple async delay helper\n *\n * @param ms - Milliseconds to delay\n * @returns Promise that resolves after the specified delay\n *\n * @example\n * ```typescript\n * console.log('Starting...');\n * await AnimationUtils.delay(2000);\n * console.log('2 seconds later!');\n * ```\n */\n static delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n /**\n * Create bitmap animation from files with advanced configuration\n *\n * @param session - MentraOS app session\n * @param basePath - Directory containing animation frames\n * @param frameCount - Number of frames to load\n * @param config - Animation configuration options\n * @returns Promise resolving to animation controller\n *\n * @example\n * ```typescript\n * // Simple animation\n * const animation = await AnimationUtils.createBitmapAnimation(\n * session, './animations', 10\n * );\n *\n * // Advanced configuration\n * const advancedAnimation = await AnimationUtils.createBitmapAnimation(\n * session, './sprites', 8, {\n * intervalMs: 1000,\n * repeat: true,\n * loadOptions: { filePattern: 'sprite_{i}.bmp', startFrame: 0 },\n * onFrame: (frame, total) => console.log(`Frame ${frame}/${total}`),\n * onError: (error) => console.error('Animation error:', error)\n * }\n * );\n * ```\n */\n static async createBitmapAnimation(\n session: AppSession,\n basePath: string,\n frameCount: number,\n config: AnimationConfig = {},\n ): Promise<AnimationController> {\n const {\n intervalMs = 1750, // Optimized for MentraOS hardware\n repeat = false,\n validateFrames = true,\n loadOptions = {},\n onStart,\n onStop,\n onFrame,\n onError,\n } = config;\n\n try {\n console.log(\n `🎬 Loading ${frameCount} animation frames from ${basePath}...`,\n );\n\n // Load frames with validation\n const frames = await BitmapUtils.loadBmpFrames(basePath, frameCount, {\n validateFrames,\n ...loadOptions,\n });\n\n if (frames.length === 0) {\n throw new Error(\"No frames loaded for animation\");\n }\n\n console.log(\n `📚 Animation ready: ${frames.length} frames at ${intervalMs}ms intervals`,\n );\n\n // Create enhanced animation with the loaded frames\n return this.createBitmapAnimationFromFrames(session, frames, {\n intervalMs,\n repeat,\n onStart,\n onStop,\n onFrame,\n onError,\n });\n } catch (error) {\n const errorMsg = `Failed to create animation: ${error instanceof Error ? error.message : \"Unknown error\"}`;\n console.error(`❌ ${errorMsg}`);\n if (onError) {\n onError(errorMsg);\n }\n throw new Error(errorMsg);\n }\n }\n\n /**\n * Create bitmap animation from pre-loaded frame data\n *\n * @param session - MentraOS app session\n * @param frames - Array of hex-encoded bitmap data\n * @param config - Animation configuration options\n * @returns Animation controller\n *\n * @example\n * ```typescript\n * const frames = ['424d461a...', '424d461b...', '424d461c...'];\n * const animation = AnimationUtils.createBitmapAnimationFromFrames(\n * session, frames, { intervalMs: 1500, repeat: true }\n * );\n * ```\n */\n static createBitmapAnimationFromFrames(\n session: AppSession,\n frames: string[],\n config: Omit<AnimationConfig, \"loadOptions\" | \"validateFrames\"> = {},\n ): AnimationController {\n const {\n intervalMs = 1750,\n repeat = false,\n onStart,\n onStop,\n onFrame,\n onError,\n } = config;\n\n let isRunning = false;\n const currentFrame = 0;\n let animationController: { stop: () => void } | null = null;\n\n const controller: AnimationController = {\n stop: () => {\n if (animationController) {\n animationController.stop();\n animationController = null;\n }\n isRunning = false;\n if (onStop) {\n onStop();\n }\n console.log(\"🛑 Animation stopped\");\n },\n\n isRunning: () => isRunning,\n\n getCurrentFrame: () => currentFrame,\n\n getTotalFrames: () => frames.length,\n };\n\n try {\n // Start the animation using the session's built-in method\n animationController = session.layouts.showBitmapAnimation(\n frames,\n intervalMs,\n repeat,\n );\n isRunning = true;\n\n if (onStart) {\n onStart();\n }\n\n console.log(\n `🎬 Animation started: ${frames.length} frames at ${intervalMs}ms${repeat ? \" (repeating)\" : \"\"}`,\n );\n\n // If we have frame callbacks, we need to track timing manually\n // This is a limitation of the current SDK - we can't hook into individual frame displays\n if (onFrame) {\n let frameTracker = 0;\n\n // Call onFrame for the first frame immediately\n onFrame(frameTracker, frames.length);\n\n const frameInterval = setInterval(() => {\n if (!isRunning) {\n clearInterval(frameInterval);\n return;\n }\n\n frameTracker = (frameTracker + 1) % frames.length;\n onFrame(frameTracker, frames.length);\n\n // If not repeating and we've shown all frames, stop tracking\n if (!repeat && frameTracker === frames.length - 1) {\n clearInterval(frameInterval);\n }\n }, intervalMs);\n\n // Override stop to also clear frame tracking\n const originalStop = controller.stop;\n controller.stop = () => {\n clearInterval(frameInterval);\n originalStop();\n };\n }\n } catch (error) {\n const errorMsg = `Failed to start animation: ${error instanceof Error ? error.message : \"Unknown error\"}`;\n console.error(`❌ ${errorMsg}`);\n if (onError) {\n onError(errorMsg);\n }\n throw new Error(errorMsg);\n }\n\n return controller;\n }\n\n /**\n * Create a sequence of bitmap displays with custom timing\n *\n * @param session - MentraOS app session\n * @param sequence - Array of frame data with individual timing\n * @returns Promise that resolves when sequence completes\n *\n * @example\n * ```typescript\n * await AnimationUtils.createBitmapSequence(session, [\n * { frame: frame1Hex, duration: 1000 },\n * { frame: frame2Hex, duration: 500 },\n * { frame: frame3Hex, duration: 2000 }\n * ]);\n * ```\n */\n static async createBitmapSequence(\n session: AppSession,\n sequence: Array<{ frame: string; duration: number }>,\n ): Promise<void> {\n console.log(\n `🎭 Starting bitmap sequence: ${sequence.length} frames with custom timing`,\n );\n\n for (let i = 0; i < sequence.length; i++) {\n const { frame, duration } = sequence[i];\n\n try {\n console.log(\n `📽️ Sequence frame ${i + 1}/${sequence.length} (${duration}ms)`,\n );\n session.layouts.showBitmapView(frame);\n\n if (i < sequence.length - 1) {\n // Don't delay after the last frame\n await this.delay(duration);\n }\n } catch (error) {\n console.error(`❌ Error in sequence frame ${i + 1}:`, error);\n throw error;\n }\n }\n\n console.log(\"✅ Bitmap sequence completed\");\n }\n\n /**\n * Measure animation timing performance\n *\n * @param targetInterval - Expected interval between frames in ms\n * @param measureDuration - How long to measure in ms (default: 10 seconds)\n * @returns Promise resolving to timing performance data\n *\n * @example\n * ```typescript\n * const timing = await AnimationUtils.measureTiming(1750, 10000);\n * console.log(`Target: ${timing.targetInterval}ms, Actual: ${timing.actualInterval}ms`);\n * console.log(`Drift: ${timing.drift}ms, FPS: ${timing.fps.toFixed(1)}`);\n * ```\n */\n static async measureTiming(\n targetInterval: number,\n measureDuration: number = 10000,\n ): Promise<TimingInfo> {\n return new Promise((resolve) => {\n const timestamps: number[] = [];\n const startTime = Date.now();\n\n const measureInterval = setInterval(() => {\n timestamps.push(Date.now());\n }, targetInterval);\n\n setTimeout(() => {\n clearInterval(measureInterval);\n\n if (timestamps.length < 2) {\n resolve({\n targetInterval,\n actualInterval: targetInterval,\n drift: 0,\n fps: 1000 / targetInterval,\n });\n return;\n }\n\n // Calculate actual interval\n const intervals = [];\n for (let i = 1; i < timestamps.length; i++) {\n intervals.push(timestamps[i] - timestamps[i - 1]);\n }\n\n const actualInterval =\n intervals.reduce((a, b) => a + b, 0) / intervals.length;\n const drift = actualInterval - targetInterval;\n const fps = 1000 / actualInterval;\n\n resolve({\n targetInterval,\n actualInterval,\n drift,\n fps,\n });\n }, measureDuration);\n });\n }\n\n /**\n * Create optimized animation settings for different hardware\n *\n * @param deviceType - Target device type\n * @returns Recommended animation configuration\n *\n * @example\n * ```typescript\n * const config = AnimationUtils.getOptimizedConfig('even-realities-g1');\n * const animation = await AnimationUtils.createBitmapAnimation(\n * session, './frames', 10, config\n * );\n * ```\n */\n static getOptimizedConfig(\n deviceType: \"even-realities-g1\" | \"generic\",\n ): AnimationConfig {\n switch (deviceType) {\n case \"even-realities-g1\":\n return {\n intervalMs: 1650, // Tested optimal timing for Even Realities G1\n repeat: false,\n validateFrames: true,\n loadOptions: {\n validateFrames: true,\n skipMissingFrames: false,\n },\n };\n\n case \"generic\":\n default:\n return {\n intervalMs: 1000,\n repeat: false,\n validateFrames: true,\n loadOptions: {\n validateFrames: true,\n skipMissingFrames: false,\n },\n };\n }\n }\n\n /**\n * Preload and cache animation frames for better performance\n *\n * @param basePath - Directory containing frames\n * @param frameCount - Number of frames to preload\n * @param options - Loading options\n * @returns Promise resolving to cached frame data\n *\n * @example\n * ```typescript\n * // Preload frames\n * const cachedFrames = await AnimationUtils.preloadFrames('./animations', 10);\n *\n * // Use cached frames multiple times\n * const animation1 = AnimationUtils.createBitmapAnimationFromFrames(session, cachedFrames);\n * const animation2 = AnimationUtils.createBitmapAnimationFromFrames(session, cachedFrames);\n * ```\n */\n static async preloadFrames(\n basePath: string,\n frameCount: number,\n options: LoadFramesOptions = {},\n ): Promise<string[]> {\n console.log(`📦 Preloading ${frameCount} frames from ${basePath}...`);\n\n const frames = await BitmapUtils.loadBmpFrames(basePath, frameCount, {\n validateFrames: true,\n ...options,\n });\n\n console.log(\n `✅ Preloaded ${frames.length} frames (${frames.reduce((total: number, frame: string) => total + frame.length, 0)} total characters)`,\n );\n\n return frames;\n }\n}\n",
16
- "// src/messages/cloud-to-app.ts\n\nimport {BaseMessage} from \"./base\"\nimport {CloudToAppMessageType, GlassesToCloudMessageType} from \"../message-types\"\nimport {ExtendedStreamType, StreamType} from \"../streams\"\nimport type {AppSettings, AppConfig} from \"../models\"\nimport type {DashboardMode} from \"../dashboard\"\nimport type {Capabilities} from \"../capabilities\"\nimport type {\n LocationUpdate,\n CalendarEvent,\n RtmpStreamStatus,\n PhotoResponse,\n RgbLedControlResponse,\n} from \"./glasses-to-cloud\"\nimport type {AppSession} from \"../../app/session\"\n\n//===========================================================\n// Responses\n//===========================================================\n\n/**\n * Connection acknowledgment to App\n */\nexport interface AppConnectionAck extends BaseMessage {\n type: CloudToAppMessageType.CONNECTION_ACK\n settings?: AppSettings\n mentraosSettings?: Record<string, any> // MentraOS system settings\n config?: AppConfig // App config sent from cloud\n capabilities?: Capabilities // Device capability profile\n}\n\n/**\n * Connection error to App\n */\nexport interface AppConnectionError extends BaseMessage {\n type: CloudToAppMessageType.CONNECTION_ERROR\n message: string\n code?: string\n}\n\n//===========================================================\n// Permission messages\n//===========================================================\n\n/**\n * Permission error detail for a specific stream\n */\nexport interface PermissionErrorDetail {\n /** The stream type that was rejected */\n stream: string\n /** The permission required for this stream */\n requiredPermission: string\n /** Detailed message explaining the rejection */\n message: string\n}\n\n/**\n * Permission error notification to App\n * Sent when subscriptions are rejected due to missing permissions\n */\nexport interface PermissionError extends BaseMessage {\n type: CloudToAppMessageType.PERMISSION_ERROR\n /** General error message */\n message: string\n /** Array of details for each rejected stream */\n details: PermissionErrorDetail[]\n}\n\n//===========================================================\n// Updates\n//===========================================================\n\n/**\n * App stopped notification to App\n */\nexport interface AppStopped extends BaseMessage {\n type: CloudToAppMessageType.APP_STOPPED\n reason: \"user_disabled\" | \"system_stop\" | \"error\"\n message?: string\n}\n\n/**\n * Settings update to App\n */\nexport interface SettingsUpdate extends BaseMessage {\n type: CloudToAppMessageType.SETTINGS_UPDATE\n packageName: string\n settings: AppSettings\n}\n\n/**\n * Device capabilities update to App\n * Sent when the connected glasses model changes or capabilities are updated\n */\nexport interface CapabilitiesUpdate extends BaseMessage {\n type: CloudToAppMessageType.CAPABILITIES_UPDATE\n capabilities: Capabilities | null\n modelName: string | null\n}\n\n/**\n * MentraOS settings update to App\n */\nexport interface MentraosSettingsUpdate extends BaseMessage {\n type: \"augmentos_settings_update\"\n sessionId: string\n settings: Record<string, any>\n timestamp: Date\n}\n\n//===========================================================\n// Audio-related data types\n//===========================================================\n/**\n * Transcription data\n */\nexport interface TranscriptionData extends BaseMessage {\n type: StreamType.TRANSCRIPTION\n text: string // The transcribed text\n isFinal: boolean // Whether this is a final transcription\n utteranceId?: string // Unique ID for this speech segment - interim and final for same utterance share the same ID\n transcribeLanguage?: string // Subscription language code (used for routing, e.g., \"en-US\")\n detectedLanguage?: string // Actual detected language from speech recognition (e.g., \"ja\", \"en\")\n startTime: number // Start time in milliseconds\n endTime: number // End time in milliseconds\n speakerId?: string // ID of the speaker if available (from diarization)\n duration?: number // Audio duration in milliseconds\n provider?: string // The transcription provider (e.g., \"azure\", \"soniox\")\n confidence?: number // Confidence score (0-1)\n metadata?: TranscriptionMetadata // Token-level metadata (always included)\n}\n\n/**\n * Metadata for transcription containing token-level details\n */\nexport interface TranscriptionMetadata {\n provider: \"soniox\" | \"azure\" | string\n soniox?: {\n tokens: SonioxToken[]\n }\n azure?: {\n // Azure-specific metadata can be added later\n tokens?: any[]\n }\n alibaba?: {\n // Alibaba-specific metadata can be added later\n tokens?: any[]\n }\n}\n\n/**\n * Soniox token with word-level details\n */\nexport interface SonioxToken {\n text: string\n startMs?: number\n endMs?: number\n confidence: number\n isFinal: boolean\n speaker?: string\n}\n\n/**\n * Translation data\n */\nexport interface TranslationData extends BaseMessage {\n type: StreamType.TRANSLATION\n text: string // The transcribed text\n originalText?: string // The original transcribed text before translation\n isFinal: boolean // Whether this is a final transcription\n startTime: number // Start time in milliseconds\n endTime: number // End time in milliseconds\n speakerId?: string // ID of the speaker if available\n duration?: number // Audio duration in milliseconds\n transcribeLanguage?: string // The language code of the transcribed text\n translateLanguage?: string // The language code of the translated text\n didTranslate?: boolean // Whether the text was translated\n provider?: string // The translation provider (e.g., \"azure\", \"google\")\n confidence?: number // Confidence score (0-1)\n}\n\n/**\n * Audio chunk data\n */\nexport interface AudioChunk extends BaseMessage {\n type: StreamType.AUDIO_CHUNK\n arrayBuffer: ArrayBufferLike // The audio data\n sampleRate?: number // Audio sample rate (e.g., 16000 Hz)\n}\n\n/**\n * Tool call from cloud to App\n * Represents a tool invocation with filled parameters\n */\nexport interface ToolCall {\n toolId: string // The ID of the tool that was called\n toolParameters: Record<string, string | number | boolean> // The parameters of the tool that was called\n timestamp: Date // Timestamp when the tool was called\n userId: string // ID of the user who triggered the tool call\n activeSession: AppSession | null\n}\n\n//===========================================================\n// Stream data\n//===========================================================\n\n/**\n * Stream data to App\n */\nexport interface DataStream extends BaseMessage {\n type: CloudToAppMessageType.DATA_STREAM\n streamType: ExtendedStreamType\n data: unknown // Type depends on the streamType\n}\n\n//===========================================================\n// Dashboard messages\n//===========================================================\n\n/**\n * Dashboard mode changed notification\n */\nexport interface DashboardModeChanged extends BaseMessage {\n type: CloudToAppMessageType.DASHBOARD_MODE_CHANGED\n mode: DashboardMode\n}\n\n/**\n * Dashboard always-on state changed notification\n */\nexport interface DashboardAlwaysOnChanged extends BaseMessage {\n type: CloudToAppMessageType.DASHBOARD_ALWAYS_ON_CHANGED\n enabled: boolean\n}\n\n/**\n * Standard connection error (for server compatibility)\n */\nexport interface StandardConnectionError extends BaseMessage {\n type: \"connection_error\"\n message: string\n}\n\n/**\n * Custom message for general-purpose communication (cloud to App)\n */\nexport interface CustomMessage extends BaseMessage {\n type: CloudToAppMessageType.CUSTOM_MESSAGE\n action: string // Identifies the specific action/message type\n payload: any // Custom data payload\n}\n\n/**\n * Output status for a re-stream destination\n */\nexport interface OutputStatus {\n /** The destination URL */\n url: string\n /** Friendly name if provided */\n name?: string\n /** Status of this output */\n status: \"active\" | \"error\" | \"stopped\"\n /** Error message if status is error */\n error?: string\n}\n\n/**\n * Managed RTMP stream status update\n * Sent when managed stream status changes or URLs are ready\n */\nexport interface ManagedStreamStatus extends BaseMessage {\n type: CloudToAppMessageType.MANAGED_STREAM_STATUS\n status: \"initializing\" | \"preparing\" | \"active\" | \"stopping\" | \"stopped\" | \"error\"\n hlsUrl?: string\n dashUrl?: string\n webrtcUrl?: string\n /** Cloudflare Stream player/preview URL for embedding */\n previewUrl?: string\n /** Thumbnail image URL */\n thumbnailUrl?: string\n message?: string\n streamId?: string\n /** Status of re-stream outputs if configured */\n outputs?: OutputStatus[]\n}\n\n/**\n * Stream status check response\n * Returns information about any existing streams for the user\n */\nexport interface StreamStatusCheckResponse extends BaseMessage {\n type: CloudToAppMessageType.STREAM_STATUS_CHECK_RESPONSE\n hasActiveStream: boolean\n streamInfo?: {\n type: \"managed\" | \"unmanaged\"\n streamId: string\n status: string\n createdAt: Date\n // For managed streams\n hlsUrl?: string\n dashUrl?: string\n webrtcUrl?: string\n previewUrl?: string\n thumbnailUrl?: string\n activeViewers?: number\n // For unmanaged streams\n rtmpUrl?: string\n requestingAppId?: string\n }\n}\n\n/**\n * Audio play response to App\n */\nexport interface AudioPlayResponse extends BaseMessage {\n type: CloudToAppMessageType.AUDIO_PLAY_RESPONSE\n requestId: string\n success: boolean\n error?: string // Error message (if failed)\n duration?: number // Duration of audio in milliseconds (if successful)\n}\n\n/**\n * Union type for all messages from cloud to Apps\n */\nexport type CloudToAppMessage =\n | AppConnectionAck\n | AppConnectionError\n | StandardConnectionError\n | DataStream\n | AppStopped\n | SettingsUpdate\n | CapabilitiesUpdate\n | TranscriptionData\n | TranslationData\n | AudioChunk\n | LocationUpdate\n | CalendarEvent\n | PhotoResponse\n | DashboardModeChanged\n | DashboardAlwaysOnChanged\n | CustomMessage\n | ManagedStreamStatus\n | StreamStatusCheckResponse\n | MentraosSettingsUpdate\n // New App-to-App communication response messages\n | AppMessageReceived\n | AppUserJoined\n | AppUserLeft\n | AppRoomUpdated\n | AppDirectMessageResponse\n | RtmpStreamStatus\n | PhotoResponse\n | RgbLedControlResponse\n | PermissionError\n | AudioPlayResponse\n\n//===========================================================\n// Type guards\n//===========================================================\n\nexport function isAppConnectionAck(message: CloudToAppMessage): message is AppConnectionAck {\n return message.type === CloudToAppMessageType.CONNECTION_ACK\n}\n\nexport function isAppConnectionError(message: CloudToAppMessage): message is AppConnectionError {\n return message.type === CloudToAppMessageType.CONNECTION_ERROR || (message as any).type === \"connection_error\"\n}\n\nexport function isAppStopped(message: CloudToAppMessage): message is AppStopped {\n return message.type === CloudToAppMessageType.APP_STOPPED\n}\n\nexport function isSettingsUpdate(message: CloudToAppMessage): message is SettingsUpdate {\n return message.type === CloudToAppMessageType.SETTINGS_UPDATE\n}\n\nexport function isCapabilitiesUpdate(message: CloudToAppMessage): message is CapabilitiesUpdate {\n return message.type === CloudToAppMessageType.CAPABILITIES_UPDATE\n}\n\nexport function isDataStream(message: CloudToAppMessage): message is DataStream {\n return message.type === CloudToAppMessageType.DATA_STREAM\n}\n\nexport function isAudioChunk(message: CloudToAppMessage): message is AudioChunk {\n return message.type === StreamType.AUDIO_CHUNK\n}\n\nexport function isDashboardModeChanged(message: CloudToAppMessage): message is DashboardModeChanged {\n return message.type === CloudToAppMessageType.DASHBOARD_MODE_CHANGED\n}\n\nexport function isDashboardAlwaysOnChanged(message: CloudToAppMessage): message is DashboardAlwaysOnChanged {\n return message.type === CloudToAppMessageType.DASHBOARD_ALWAYS_ON_CHANGED\n}\n\nexport function isManagedStreamStatus(message: CloudToAppMessage): message is ManagedStreamStatus {\n return message.type === CloudToAppMessageType.MANAGED_STREAM_STATUS\n}\n\nexport function isRtmpStreamStatus(message: CloudToAppMessage): message is RtmpStreamStatus {\n return message.type === GlassesToCloudMessageType.RTMP_STREAM_STATUS\n}\n\nexport function isPhotoResponse(message: CloudToAppMessage): message is PhotoResponse {\n return message.type === GlassesToCloudMessageType.PHOTO_RESPONSE\n}\n\nexport function isRgbLedControlResponse(message: CloudToAppMessage): message is RgbLedControlResponse {\n return message.type === GlassesToCloudMessageType.RGB_LED_CONTROL_RESPONSE\n}\n\nexport function isStreamStatusCheckResponse(message: CloudToAppMessage): message is StreamStatusCheckResponse {\n return message.type === CloudToAppMessageType.STREAM_STATUS_CHECK_RESPONSE\n}\n\nexport function isAudioPlayResponse(message: CloudToAppMessage): message is AudioPlayResponse {\n return message.type === CloudToAppMessageType.AUDIO_PLAY_RESPONSE\n}\n\n// New type guards for App-to-App communication\nexport function isAppMessageReceived(message: CloudToAppMessage): message is AppMessageReceived {\n return message.type === CloudToAppMessageType.APP_MESSAGE_RECEIVED\n}\n\nexport function isAppUserJoined(message: CloudToAppMessage): message is AppUserJoined {\n return message.type === CloudToAppMessageType.APP_USER_JOINED\n}\n\nexport function isAppUserLeft(message: CloudToAppMessage): message is AppUserLeft {\n return message.type === CloudToAppMessageType.APP_USER_LEFT\n}\n\n//===========================================================\n// App-to-App Communication Response Messages\n//===========================================================\n\n/**\n * Message received from another App user\n */\nexport interface AppMessageReceived extends BaseMessage {\n type: CloudToAppMessageType.APP_MESSAGE_RECEIVED\n payload: any\n messageId: string\n senderUserId: string\n senderSessionId: string\n roomId?: string\n}\n\n/**\n * Notification that a user joined the App\n */\nexport interface AppUserJoined extends BaseMessage {\n type: CloudToAppMessageType.APP_USER_JOINED\n userId: string\n sessionId: string\n joinedAt: Date\n userProfile?: any\n roomId?: string\n}\n\n/**\n * Notification that a user left the App\n */\nexport interface AppUserLeft extends BaseMessage {\n type: CloudToAppMessageType.APP_USER_LEFT\n userId: string\n sessionId: string\n leftAt: Date\n roomId?: string\n}\n\n/**\n * Room status update (members, config changes, etc.)\n */\nexport interface AppRoomUpdated extends BaseMessage {\n type: CloudToAppMessageType.APP_ROOM_UPDATED\n roomId: string\n updateType: \"user_joined\" | \"user_left\" | \"config_changed\" | \"room_closed\"\n roomData: {\n memberCount: number\n maxUsers?: number\n isPrivate?: boolean\n metadata?: any\n }\n}\n\n/**\n * Response to a direct message attempt\n */\nexport interface AppDirectMessageResponse extends BaseMessage {\n type: CloudToAppMessageType.APP_DIRECT_MESSAGE_RESPONSE\n messageId: string\n success: boolean\n error?: string\n targetUserId: string\n}\n\n//===========================================================\n// Cloud-to-Sdk Communication Response Messages\n//===========================================================\n\n/**\n * Permission data structures for permission fetch responses\n */\nexport interface Permission {\n type: string // or a union/enum if you want stricter typing\n description: string\n _id: string\n}\n\n/**\n * Package permissions response structure\n */\nexport interface PackagePermissions {\n packageName: string\n permissions: Permission[]\n}\n",
16
+ "// src/messages/cloud-to-app.ts\n\nimport {BaseMessage} from \"./base\"\nimport {CloudToAppMessageType, GlassesToCloudMessageType} from \"../message-types\"\nimport {ExtendedStreamType, StreamType} from \"../streams\"\nimport type {AppSettings, AppConfig} from \"../models\"\nimport type {DashboardMode} from \"../dashboard\"\nimport type {Capabilities} from \"../capabilities\"\nimport type {\n LocationUpdate,\n CalendarEvent,\n RtmpStreamStatus,\n PhotoResponse,\n RgbLedControlResponse,\n} from \"./glasses-to-cloud\"\nimport type {AppSession} from \"../../app/session\"\nimport type {GlassesInfo} from \"@mentra/types\"\n\n//===========================================================\n// Responses\n//===========================================================\n\n/**\n * Connection acknowledgment to App\n */\nexport interface AppConnectionAck extends BaseMessage {\n type: CloudToAppMessageType.CONNECTION_ACK\n settings?: AppSettings\n mentraosSettings?: Record<string, any> // MentraOS system settings\n config?: AppConfig // App config sent from cloud\n capabilities?: Capabilities // Device capability profile\n}\n\n/**\n * Connection error to App\n */\nexport interface AppConnectionError extends BaseMessage {\n type: CloudToAppMessageType.CONNECTION_ERROR\n message: string\n code?: string\n}\n\n//===========================================================\n// Permission messages\n//===========================================================\n\n/**\n * Permission error detail for a specific stream\n */\nexport interface PermissionErrorDetail {\n /** The stream type that was rejected */\n stream: string\n /** The permission required for this stream */\n requiredPermission: string\n /** Detailed message explaining the rejection */\n message: string\n}\n\n/**\n * Permission error notification to App\n * Sent when subscriptions are rejected due to missing permissions\n */\nexport interface PermissionError extends BaseMessage {\n type: CloudToAppMessageType.PERMISSION_ERROR\n /** General error message */\n message: string\n /** Array of details for each rejected stream */\n details: PermissionErrorDetail[]\n}\n\n//===========================================================\n// Updates\n//===========================================================\n\n/**\n * App stopped notification to App\n */\nexport interface AppStopped extends BaseMessage {\n type: CloudToAppMessageType.APP_STOPPED\n reason: \"user_disabled\" | \"system_stop\" | \"error\"\n message?: string\n}\n\n/**\n * Settings update to App\n */\nexport interface SettingsUpdate extends BaseMessage {\n type: CloudToAppMessageType.SETTINGS_UPDATE\n packageName: string\n settings: AppSettings\n}\n\n/**\n * Device capabilities update to App\n * Sent when the connected glasses model changes or capabilities are updated\n */\nexport interface CapabilitiesUpdate extends BaseMessage {\n type: CloudToAppMessageType.CAPABILITIES_UPDATE\n capabilities: Capabilities | null\n modelName: string | null\n}\n\n/**\n * Device state update to App\n * Sent when any device state changes (WiFi, battery, hotspot, connection, etc.)\n * Apps receive this automatically - no subscription needed\n */\nexport interface DeviceStateUpdate extends BaseMessage {\n type: CloudToAppMessageType.DEVICE_STATE_UPDATE\n state: Partial<GlassesInfo> // Only changed fields (or full snapshot)\n fullSnapshot?: boolean // True on initial connection or reconnection\n timestamp: Date\n}\n\n/**\n * MentraOS settings update to App\n */\nexport interface MentraosSettingsUpdate extends BaseMessage {\n type: \"augmentos_settings_update\"\n sessionId: string\n settings: Record<string, any>\n timestamp: Date\n}\n\n//===========================================================\n// Audio-related data types\n//===========================================================\n/**\n * Transcription data\n */\nexport interface TranscriptionData extends BaseMessage {\n type: StreamType.TRANSCRIPTION\n text: string // The transcribed text\n isFinal: boolean // Whether this is a final transcription\n utteranceId?: string // Unique ID for this speech segment - interim and final for same utterance share the same ID\n transcribeLanguage?: string // Subscription language code (used for routing, e.g., \"en-US\")\n detectedLanguage?: string // Actual detected language from speech recognition (e.g., \"ja\", \"en\")\n startTime: number // Start time in milliseconds\n endTime: number // End time in milliseconds\n speakerId?: string // ID of the speaker if available (from diarization)\n duration?: number // Audio duration in milliseconds\n provider?: string // The transcription provider (e.g., \"azure\", \"soniox\")\n confidence?: number // Confidence score (0-1)\n metadata?: TranscriptionMetadata // Token-level metadata (always included)\n}\n\n/**\n * Metadata for transcription containing token-level details\n */\nexport interface TranscriptionMetadata {\n provider: \"soniox\" | \"azure\" | string\n soniox?: {\n tokens: SonioxToken[]\n }\n azure?: {\n // Azure-specific metadata can be added later\n tokens?: any[]\n }\n alibaba?: {\n // Alibaba-specific metadata can be added later\n tokens?: any[]\n }\n}\n\n/**\n * Soniox token with word-level details\n */\nexport interface SonioxToken {\n text: string\n startMs?: number\n endMs?: number\n confidence: number\n isFinal: boolean\n speaker?: string\n}\n\n/**\n * Translation data\n */\nexport interface TranslationData extends BaseMessage {\n type: StreamType.TRANSLATION\n text: string // The transcribed text\n originalText?: string // The original transcribed text before translation\n isFinal: boolean // Whether this is a final transcription\n startTime: number // Start time in milliseconds\n endTime: number // End time in milliseconds\n speakerId?: string // ID of the speaker if available\n duration?: number // Audio duration in milliseconds\n transcribeLanguage?: string // The language code of the transcribed text\n translateLanguage?: string // The language code of the translated text\n didTranslate?: boolean // Whether the text was translated\n provider?: string // The translation provider (e.g., \"azure\", \"google\")\n confidence?: number // Confidence score (0-1)\n}\n\n/**\n * Audio chunk data\n */\nexport interface AudioChunk extends BaseMessage {\n type: StreamType.AUDIO_CHUNK\n arrayBuffer: ArrayBufferLike // The audio data\n sampleRate?: number // Audio sample rate (e.g., 16000 Hz)\n}\n\n/**\n * Tool call from cloud to App\n * Represents a tool invocation with filled parameters\n */\nexport interface ToolCall {\n toolId: string // The ID of the tool that was called\n toolParameters: Record<string, string | number | boolean> // The parameters of the tool that was called\n timestamp: Date // Timestamp when the tool was called\n userId: string // ID of the user who triggered the tool call\n activeSession: AppSession | null\n}\n\n//===========================================================\n// Stream data\n//===========================================================\n\n/**\n * Stream data to App\n */\nexport interface DataStream extends BaseMessage {\n type: CloudToAppMessageType.DATA_STREAM\n streamType: ExtendedStreamType\n data: unknown // Type depends on the streamType\n}\n\n//===========================================================\n// Dashboard messages\n//===========================================================\n\n/**\n * Dashboard mode changed notification\n */\nexport interface DashboardModeChanged extends BaseMessage {\n type: CloudToAppMessageType.DASHBOARD_MODE_CHANGED\n mode: DashboardMode\n}\n\n/**\n * Dashboard always-on state changed notification\n */\nexport interface DashboardAlwaysOnChanged extends BaseMessage {\n type: CloudToAppMessageType.DASHBOARD_ALWAYS_ON_CHANGED\n enabled: boolean\n}\n\n/**\n * Standard connection error (for server compatibility)\n */\nexport interface StandardConnectionError extends BaseMessage {\n type: \"connection_error\"\n message: string\n}\n\n/**\n * Custom message for general-purpose communication (cloud to App)\n */\nexport interface CustomMessage extends BaseMessage {\n type: CloudToAppMessageType.CUSTOM_MESSAGE\n action: string // Identifies the specific action/message type\n payload: any // Custom data payload\n}\n\n/**\n * Output status for a re-stream destination\n */\nexport interface OutputStatus {\n /** The destination URL */\n url: string\n /** Friendly name if provided */\n name?: string\n /** Status of this output */\n status: \"active\" | \"error\" | \"stopped\"\n /** Error message if status is error */\n error?: string\n}\n\n/**\n * Managed RTMP stream status update\n * Sent when managed stream status changes or URLs are ready\n */\nexport interface ManagedStreamStatus extends BaseMessage {\n type: CloudToAppMessageType.MANAGED_STREAM_STATUS\n status: \"initializing\" | \"preparing\" | \"active\" | \"stopping\" | \"stopped\" | \"error\"\n hlsUrl?: string\n dashUrl?: string\n webrtcUrl?: string\n /** Cloudflare Stream player/preview URL for embedding */\n previewUrl?: string\n /** Thumbnail image URL */\n thumbnailUrl?: string\n message?: string\n streamId?: string\n /** Status of re-stream outputs if configured */\n outputs?: OutputStatus[]\n}\n\n/**\n * Stream status check response\n * Returns information about any existing streams for the user\n */\nexport interface StreamStatusCheckResponse extends BaseMessage {\n type: CloudToAppMessageType.STREAM_STATUS_CHECK_RESPONSE\n hasActiveStream: boolean\n streamInfo?: {\n type: \"managed\" | \"unmanaged\"\n streamId: string\n status: string\n createdAt: Date\n // For managed streams\n hlsUrl?: string\n dashUrl?: string\n webrtcUrl?: string\n previewUrl?: string\n thumbnailUrl?: string\n activeViewers?: number\n // For unmanaged streams\n rtmpUrl?: string\n requestingAppId?: string\n }\n}\n\n/**\n * Audio play response to App\n */\nexport interface AudioPlayResponse extends BaseMessage {\n type: CloudToAppMessageType.AUDIO_PLAY_RESPONSE\n requestId: string\n success: boolean\n error?: string // Error message (if failed)\n duration?: number // Duration of audio in milliseconds (if successful)\n}\n\n/**\n * Union type for all messages from cloud to Apps\n */\nexport type CloudToAppMessage =\n | AppConnectionAck\n | AppConnectionError\n | StandardConnectionError\n | DataStream\n | AppStopped\n | SettingsUpdate\n | CapabilitiesUpdate\n | DeviceStateUpdate\n | TranscriptionData\n | TranslationData\n | AudioChunk\n | LocationUpdate\n | CalendarEvent\n | PhotoResponse\n | DashboardModeChanged\n | DashboardAlwaysOnChanged\n | CustomMessage\n | ManagedStreamStatus\n | StreamStatusCheckResponse\n | MentraosSettingsUpdate\n // New App-to-App communication response messages\n | AppMessageReceived\n | AppUserJoined\n | AppUserLeft\n | AppRoomUpdated\n | AppDirectMessageResponse\n | RtmpStreamStatus\n | PhotoResponse\n | RgbLedControlResponse\n | PermissionError\n | AudioPlayResponse\n\n//===========================================================\n// Type guards\n//===========================================================\n\nexport function isAppConnectionAck(message: CloudToAppMessage): message is AppConnectionAck {\n return message.type === CloudToAppMessageType.CONNECTION_ACK\n}\n\nexport function isAppConnectionError(message: CloudToAppMessage): message is AppConnectionError {\n return message.type === CloudToAppMessageType.CONNECTION_ERROR || (message as any).type === \"connection_error\"\n}\n\nexport function isAppStopped(message: CloudToAppMessage): message is AppStopped {\n return message.type === CloudToAppMessageType.APP_STOPPED\n}\n\nexport function isSettingsUpdate(message: CloudToAppMessage): message is SettingsUpdate {\n return message.type === CloudToAppMessageType.SETTINGS_UPDATE\n}\n\nexport function isCapabilitiesUpdate(message: CloudToAppMessage): message is CapabilitiesUpdate {\n return message.type === CloudToAppMessageType.CAPABILITIES_UPDATE\n}\n\nexport function isDeviceStateUpdate(message: CloudToAppMessage): message is DeviceStateUpdate {\n return message.type === CloudToAppMessageType.DEVICE_STATE_UPDATE\n}\n\nexport function isDataStream(message: CloudToAppMessage): message is DataStream {\n return message.type === CloudToAppMessageType.DATA_STREAM\n}\n\nexport function isAudioChunk(message: CloudToAppMessage): message is AudioChunk {\n return message.type === StreamType.AUDIO_CHUNK\n}\n\nexport function isDashboardModeChanged(message: CloudToAppMessage): message is DashboardModeChanged {\n return message.type === CloudToAppMessageType.DASHBOARD_MODE_CHANGED\n}\n\nexport function isDashboardAlwaysOnChanged(message: CloudToAppMessage): message is DashboardAlwaysOnChanged {\n return message.type === CloudToAppMessageType.DASHBOARD_ALWAYS_ON_CHANGED\n}\n\nexport function isManagedStreamStatus(message: CloudToAppMessage): message is ManagedStreamStatus {\n return message.type === CloudToAppMessageType.MANAGED_STREAM_STATUS\n}\n\nexport function isRtmpStreamStatus(message: CloudToAppMessage): message is RtmpStreamStatus {\n return message.type === GlassesToCloudMessageType.RTMP_STREAM_STATUS\n}\n\nexport function isPhotoResponse(message: CloudToAppMessage): message is PhotoResponse {\n return message.type === GlassesToCloudMessageType.PHOTO_RESPONSE\n}\n\nexport function isRgbLedControlResponse(message: CloudToAppMessage): message is RgbLedControlResponse {\n return message.type === GlassesToCloudMessageType.RGB_LED_CONTROL_RESPONSE\n}\n\nexport function isStreamStatusCheckResponse(message: CloudToAppMessage): message is StreamStatusCheckResponse {\n return message.type === CloudToAppMessageType.STREAM_STATUS_CHECK_RESPONSE\n}\n\nexport function isAudioPlayResponse(message: CloudToAppMessage): message is AudioPlayResponse {\n return message.type === CloudToAppMessageType.AUDIO_PLAY_RESPONSE\n}\n\n// New type guards for App-to-App communication\nexport function isAppMessageReceived(message: CloudToAppMessage): message is AppMessageReceived {\n return message.type === CloudToAppMessageType.APP_MESSAGE_RECEIVED\n}\n\nexport function isAppUserJoined(message: CloudToAppMessage): message is AppUserJoined {\n return message.type === CloudToAppMessageType.APP_USER_JOINED\n}\n\nexport function isAppUserLeft(message: CloudToAppMessage): message is AppUserLeft {\n return message.type === CloudToAppMessageType.APP_USER_LEFT\n}\n\n//===========================================================\n// App-to-App Communication Response Messages\n//===========================================================\n\n/**\n * Message received from another App user\n */\nexport interface AppMessageReceived extends BaseMessage {\n type: CloudToAppMessageType.APP_MESSAGE_RECEIVED\n payload: any\n messageId: string\n senderUserId: string\n senderSessionId: string\n roomId?: string\n}\n\n/**\n * Notification that a user joined the App\n */\nexport interface AppUserJoined extends BaseMessage {\n type: CloudToAppMessageType.APP_USER_JOINED\n userId: string\n sessionId: string\n joinedAt: Date\n userProfile?: any\n roomId?: string\n}\n\n/**\n * Notification that a user left the App\n */\nexport interface AppUserLeft extends BaseMessage {\n type: CloudToAppMessageType.APP_USER_LEFT\n userId: string\n sessionId: string\n leftAt: Date\n roomId?: string\n}\n\n/**\n * Room status update (members, config changes, etc.)\n */\nexport interface AppRoomUpdated extends BaseMessage {\n type: CloudToAppMessageType.APP_ROOM_UPDATED\n roomId: string\n updateType: \"user_joined\" | \"user_left\" | \"config_changed\" | \"room_closed\"\n roomData: {\n memberCount: number\n maxUsers?: number\n isPrivate?: boolean\n metadata?: any\n }\n}\n\n/**\n * Response to a direct message attempt\n */\nexport interface AppDirectMessageResponse extends BaseMessage {\n type: CloudToAppMessageType.APP_DIRECT_MESSAGE_RESPONSE\n messageId: string\n success: boolean\n error?: string\n targetUserId: string\n}\n\n//===========================================================\n// Cloud-to-Sdk Communication Response Messages\n//===========================================================\n\n/**\n * Permission data structures for permission fetch responses\n */\nexport interface Permission {\n type: string // or a union/enum if you want stricter typing\n description: string\n _id: string\n}\n\n/**\n * Package permissions response structure\n */\nexport interface PackagePermissions {\n packageName: string\n permissions: Permission[]\n}\n",
17
17
  "// src/enums.ts\n\n/**\n * Types of Third-Party Applications (Apps)\n */\nexport enum AppType {\n SYSTEM_DASHBOARD = \"system_dashboard\", // Special UI placement, system functionality\n BACKGROUND = \"background\", // Can temporarily take control of display\n STANDARD = \"standard\", // Regular App (default) only one standard app can run at a time. starting a standard App will close any other standard App that is running.\n}\n\n/**\n * Types of layouts for displaying content\n */\nexport enum LayoutType {\n TEXT_WALL = \"text_wall\",\n DOUBLE_TEXT_WALL = \"double_text_wall\",\n DASHBOARD_CARD = \"dashboard_card\",\n REFERENCE_CARD = \"reference_card\",\n BITMAP_VIEW = \"bitmap_view\",\n BITMAP_ANIMATION = \"bitmap_animation\",\n CLEAR_VIEW = \"clear_view\",\n}\n\n/**\n * Types of views for displaying content\n */\nexport enum ViewType {\n DASHBOARD = \"dashboard\", // Regular dashboard (main/expanded)\n // ALWAYS_ON = \"always_on\", // Persistent overlay dashboard\n MAIN = \"main\", // Regular app content\n}\n\n// Types for AppSettings\nexport enum AppSettingType {\n TOGGLE = \"toggle\",\n TEXT = \"text\",\n SELECT = \"select\",\n SLIDER = \"slider\",\n GROUP = \"group\",\n TEXT_NO_SAVE_BUTTON = \"text_no_save_button\",\n SELECT_WITH_SEARCH = \"select_with_search\",\n MULTISELECT = \"multiselect\",\n TITLE_VALUE = \"titleValue\",\n NUMERIC_INPUT = \"numeric_input\",\n TIME_PICKER = \"time_picker\",\n}\n// | { type: \"toggle\"; key: string; label: string; defaultValue: boolean }\n// | { type: \"text\"; key: string; label: string; defaultValue?: string }\n// | { type: \"select\"; key: string; label: string; options: { label: string; value: string }[]; defaultValue?: string };\n\n/**\n * Types of hardware components that apps can require\n */\nexport enum HardwareType {\n CAMERA = \"CAMERA\",\n DISPLAY = \"DISPLAY\",\n MICROPHONE = \"MICROPHONE\",\n SPEAKER = \"SPEAKER\",\n IMU = \"IMU\",\n BUTTON = \"BUTTON\",\n LIGHT = \"LIGHT\",\n WIFI = \"WIFI\",\n}\n\n/**\n * Levels of hardware requirements\n */\nexport enum HardwareRequirementLevel {\n REQUIRED = \"REQUIRED\", // App cannot function without this hardware\n OPTIONAL = \"OPTIONAL\", // App has enhanced features with this hardware\n}\n",
18
18
  "// @mentra/sdk\n// packages/sdk/types/src/models.ts - Core models\n\nimport {\n AppSettingType,\n AppType,\n HardwareType,\n HardwareRequirementLevel,\n} from \"./enums\";\n\n// Tool parameter type definition\nexport interface ToolParameterSchema {\n type: \"string\" | \"number\" | \"boolean\";\n description: string;\n enum?: string[];\n required?: boolean;\n}\n\n// Tool schema definition for Apps\nexport interface ToolSchema {\n id: string;\n description: string;\n activationPhrases?: string[];\n parameters?: Record<string, ToolParameterSchema>;\n}\n\n/**\n * Developer profile information\n */\nexport interface DeveloperProfile {\n company?: string;\n website?: string;\n contactEmail?: string;\n description?: string;\n logo?: string;\n}\n\n// Define PermissionType enum with legacy support\nexport enum PermissionType {\n MICROPHONE = \"MICROPHONE\",\n LOCATION = \"LOCATION\",\n BACKGROUND_LOCATION = \"BACKGROUND_LOCATION\",\n CALENDAR = \"CALENDAR\",\n CAMERA = \"CAMERA\",\n\n // Legacy notification permission (backward compatibility)\n NOTIFICATIONS = \"NOTIFICATIONS\",\n\n // New granular notification permissions\n READ_NOTIFICATIONS = \"READ_NOTIFICATIONS\",\n POST_NOTIFICATIONS = \"POST_NOTIFICATIONS\",\n\n ALL = \"ALL\",\n}\n\n// Legacy permission mapping for backward compatibility\nexport const LEGACY_PERMISSION_MAP = new Map<PermissionType, PermissionType[]>([\n [PermissionType.NOTIFICATIONS, [PermissionType.READ_NOTIFICATIONS]],\n]);\n\n// Permission interface\nexport interface Permission {\n type: PermissionType;\n description?: string;\n}\n\n/**\n * Hardware requirement for an app\n */\nexport interface HardwareRequirement {\n type: HardwareType;\n level: HardwareRequirementLevel;\n description?: string; // Why this hardware is needed\n}\n\n/**\n * Base interface for applications\n */\nexport interface AppI {\n packageName: string;\n name: string;\n publicUrl: string; // Base URL of the app server\n isSystemApp?: boolean; // Is this a system app?\n uninstallable?: boolean; // Can the app be uninstalled?\n\n webviewURL?: string; // URL for phone UI\n logoURL: string;\n appType: AppType; // Type of app\n appStoreId?: string; // Which app store registered this app\n\n /**\n * @deprecated Use organizationId instead. Will be removed after migration.\n */\n developerId?: string; // ID of the developer who created the app\n organizationId?: any; // ID of the organization that owns this app\n\n // Auth\n hashedEndpointSecret?: string;\n hashedApiKey?: string;\n\n // App details\n permissions?: Permission[];\n description?: string;\n version?: string;\n settings?: AppSettings;\n tools?: ToolSchema[];\n\n /**\n * Hardware requirements for the app\n * If not specified, app is assumed to work with any hardware\n */\n hardwareRequirements?: HardwareRequirement[];\n\n isPublic?: boolean;\n appStoreStatus?: \"DEVELOPMENT\" | \"SUBMITTED\" | \"REJECTED\" | \"PUBLISHED\";\n}\n\n/**\n * Base interface for all app settings\n */\nexport interface BaseAppSetting {\n key: string;\n label: string;\n value?: any; // User's selected value\n defaultValue?: any; // System default\n}\n\n/**\n * Setting types for applications\n */\nexport type AppSetting =\n | (BaseAppSetting & {\n type: AppSettingType.TOGGLE;\n defaultValue: boolean;\n value?: boolean;\n })\n | (BaseAppSetting & {\n type: AppSettingType.TEXT;\n defaultValue?: string;\n value?: string;\n })\n | (BaseAppSetting & {\n type: AppSettingType.TEXT_NO_SAVE_BUTTON;\n defaultValue?: string;\n value?: string;\n maxLines?: number;\n })\n | (BaseAppSetting & {\n type: AppSettingType.SELECT;\n options: { label: string; value: any }[];\n defaultValue?: any;\n value?: any;\n })\n | (BaseAppSetting & {\n type: AppSettingType.SELECT_WITH_SEARCH;\n options: { label: string; value: any }[];\n defaultValue?: any;\n value?: any;\n })\n | (BaseAppSetting & {\n type: AppSettingType.MULTISELECT;\n options: { label: string; value: any }[];\n defaultValue?: any[];\n value?: any[];\n })\n | (BaseAppSetting & {\n type: AppSettingType.SLIDER;\n min: number;\n max: number;\n defaultValue: number;\n value?: number;\n })\n | (BaseAppSetting & {\n type: AppSettingType.NUMERIC_INPUT;\n min?: number;\n max?: number;\n step?: number;\n placeholder?: string;\n defaultValue?: number;\n value?: number;\n })\n | (BaseAppSetting & {\n type: AppSettingType.TIME_PICKER;\n showSeconds?: boolean;\n defaultValue?: number; // Total seconds\n value?: number; // Total seconds\n })\n | (BaseAppSetting & {\n type: AppSettingType.GROUP;\n title: string;\n })\n | (BaseAppSetting & {\n type: AppSettingType.TITLE_VALUE;\n label: string;\n value: any;\n key?: never; // TITLE_VALUE settings don't need keys since they're display-only\n });\n\nexport type AppSettings = AppSetting[];\n\n/**\n * App configuration file structure\n * Represents the schema in app_config.json\n */\nexport interface AppConfig {\n name: string;\n description: string;\n version: string;\n settings: AppSetting[];\n tools: ToolSchema[];\n}\n\n/**\n * Validate a App configuration object\n * @param config Object to validate\n * @returns True if the config is valid\n */\nexport function validateAppConfig(config: any): config is AppConfig {\n if (!config || typeof config !== \"object\") return false;\n\n // Check required string properties\n if (\n typeof config.name !== \"string\" ||\n typeof config.description !== \"string\" ||\n typeof config.version !== \"string\"\n ) {\n return false;\n }\n\n // Check settings array\n if (!Array.isArray(config.settings)) return false;\n\n // Validate each setting\n return config.settings.every((setting: any) => {\n // Group settings just need a title\n if (setting.type === \"group\") {\n return typeof setting.title === \"string\";\n }\n\n // TITLE_VALUE settings just need label and value\n if (setting.type === \"titleValue\") {\n return typeof setting.label === \"string\" && \"value\" in setting;\n }\n\n // Regular settings need key and label\n if (typeof setting.key !== \"string\" || typeof setting.label !== \"string\") {\n return false;\n }\n\n // Type-specific validation\n switch (setting.type) {\n case AppSettingType.TOGGLE:\n return typeof setting.defaultValue === \"boolean\";\n\n case AppSettingType.TEXT:\n case AppSettingType.TEXT_NO_SAVE_BUTTON:\n return (\n setting.defaultValue === undefined ||\n typeof setting.defaultValue === \"string\"\n );\n\n case AppSettingType.SELECT:\n case AppSettingType.SELECT_WITH_SEARCH:\n return (\n Array.isArray(setting.options) &&\n setting.options.every(\n (opt: any) => typeof opt.label === \"string\" && \"value\" in opt,\n )\n );\n\n case AppSettingType.MULTISELECT:\n return (\n Array.isArray(setting.options) &&\n setting.options.every(\n (opt: any) => typeof opt.label === \"string\" && \"value\" in opt,\n ) &&\n (setting.defaultValue === undefined ||\n Array.isArray(setting.defaultValue))\n );\n\n case AppSettingType.SLIDER:\n return (\n typeof setting.defaultValue === \"number\" &&\n typeof setting.min === \"number\" &&\n typeof setting.max === \"number\" &&\n setting.min <= setting.max\n );\n\n case AppSettingType.NUMERIC_INPUT:\n return (\n (setting.defaultValue === undefined ||\n typeof setting.defaultValue === \"number\") &&\n (setting.min === undefined || typeof setting.min === \"number\") &&\n (setting.max === undefined || typeof setting.max === \"number\") &&\n (setting.step === undefined || typeof setting.step === \"number\") &&\n (setting.placeholder === undefined ||\n typeof setting.placeholder === \"string\")\n );\n\n case AppSettingType.TIME_PICKER:\n return (\n (setting.defaultValue === undefined ||\n typeof setting.defaultValue === \"number\") &&\n (setting.showSeconds === undefined ||\n typeof setting.showSeconds === \"boolean\")\n );\n\n case AppSettingType.GROUP:\n return typeof setting.title === \"string\";\n\n case AppSettingType.TITLE_VALUE:\n return typeof setting.label === \"string\" && \"value\" in setting;\n\n default:\n return false;\n }\n });\n}\n\n/**\n * Transcript segment for speech processing\n */\nexport interface TranscriptSegment {\n speakerId?: string;\n resultId: string;\n text: string;\n timestamp: Date;\n isFinal: boolean;\n}\n\n/**\n * Complete transcript\n */\nexport interface TranscriptI {\n segments: TranscriptSegment[];\n languageSegments?: Map<string, TranscriptSegment[]>; // Language-indexed map for multi-language support\n}\n",
19
19
  "// src/webhook.ts\n\n/**\n * Types of webhook requests that can be sent to Apps\n */\nexport enum WebhookRequestType {\n /** Request to start a App session */\n SESSION_REQUEST = \"session_request\",\n\n /** Request to stop a App session */\n STOP_REQUEST = \"stop_request\",\n}\n\n/**\n * Base interface for all webhook requests\n */\nexport interface BaseWebhookRequest {\n /** Type of webhook request */\n type: WebhookRequestType;\n\n /** Session ID for the request */\n sessionId: string;\n\n /** User ID associated with the session */\n userId: string;\n\n /** Timestamp of the request */\n timestamp: string;\n}\n\n/**\n * Session request webhook\n *\n * Sent to a App when a user starts the App\n */\nexport interface SessionWebhookRequest extends BaseWebhookRequest {\n type: WebhookRequestType.SESSION_REQUEST;\n mentraOSWebsocketUrl?: string;\n augmentOSWebsocketUrl?: string;\n}\n\n/**\n * Stop request webhook\n *\n * Sent to a App when a user or the system stops the App\n */\nexport interface StopWebhookRequest extends BaseWebhookRequest {\n type: WebhookRequestType.STOP_REQUEST;\n reason: \"user_disabled\" | \"system_stop\" | \"error\";\n}\n\n/**\n * Union type for all webhook requests\n */\nexport type WebhookRequest = SessionWebhookRequest | StopWebhookRequest;\n\n/**\n * Response to a webhook request\n */\nexport interface WebhookResponse {\n status: \"success\" | \"error\";\n message?: string;\n}\n\n/**\n * Type guard to check if a webhook request is a session request\n */\nexport function isSessionWebhookRequest(\n request: WebhookRequest,\n): request is SessionWebhookRequest {\n return request.type === WebhookRequestType.SESSION_REQUEST;\n}\n\n/**\n * Type guard to check if a webhook request is a stop request\n */\nexport function isStopWebhookRequest(\n request: WebhookRequest,\n): request is StopWebhookRequest {\n return request.type === WebhookRequestType.STOP_REQUEST;\n}\n",
20
- "/**\n * 🚀 App Server Module\n *\n * Creates and manages a server for Apps in the MentraOS ecosystem.\n * Handles webhook endpoints, session management, and cleanup.\n */\nimport express, { type Express } from \"express\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport { AppSession } from \"../session/index\";\nimport { createAuthMiddleware } from \"../webview\";\nimport { newSDKUpdate } from \"../../constants/log-messages/updates\";\n\nimport {\n WebhookRequest,\n WebhookResponse,\n SessionWebhookRequest,\n StopWebhookRequest,\n ToolCall,\n WebhookRequestType,\n} from \"../../types\";\n\nimport { Logger } from \"pino\";\nimport { logger as rootLogger } from \"../../logging/logger\";\nimport axios from \"axios\";\n\nexport const GIVE_APP_CONTROL_OF_TOOL_RESPONSE: string =\n \"GIVE_APP_CONTROL_OF_TOOL_RESPONSE\";\n\n/**\n * 🔧 Configuration options for App Server\n *\n * @example\n * ```typescript\n * const config: AppServerConfig = {\n * packageName: 'org.example.myapp',\n * apiKey: 'your_api_key',\n * port: 7010,\n * publicDir: './public'\n * };\n * ```\n */\nexport interface AppServerConfig {\n /** 📦 Unique identifier for your App (e.g., 'org.company.appname') must match what you specified at https://console.mentra.glass */\n packageName: string;\n /** 🔑 API key for authentication with MentraOS Cloud */\n apiKey: string;\n /** 🌐 Port number for the server (default: 7010) */\n port?: number;\n\n /** Cloud API URL (default: 'api.mentra.glass') */\n cloudApiUrl?: string;\n\n /** 🛣️ [DEPRECATED] do not set: The SDK will automatically expose an endpoint at '/webhook' */\n webhookPath?: string;\n /**\n * 📂 Directory for serving static files (e.g., images, logos)\n * Set to false to disable static file serving\n */\n publicDir?: string | false;\n\n /** ❤️ Enable health check endpoint at /health (default: true) */\n healthCheck?: boolean;\n /**\n * 🔐 Secret key used to sign session cookies\n * This must be a strong, unique secret\n */\n cookieSecret?: string;\n /** App instructions string shown to the user */\n appInstructions?: string;\n}\n\n/**\n * 🎯 App Server Implementation\n *\n * Base class for creating App servers. Handles:\n * - 🔄 Session lifecycle management\n * - 📡 Webhook endpoints for MentraOS Cloud\n * - 📂 Static file serving\n * - ❤️ Health checks\n * - 🧹 Cleanup on shutdown\n *\n * @example\n * ```typescript\n * class MyAppServer extends AppServer {\n * protected async onSession(session: AppSession, sessionId: string, userId: string) {\n * // Handle new user sessions here\n * session.events.onTranscription((data) => {\n * session.layouts.showTextWall(data.text);\n * });\n * }\n * }\n *\n * const server = new MyAppServer({\n * packageName: 'org.example.myapp',\n * apiKey: 'your_api_key',\n * publicDir: \"/public\",\n * });\n *\n * await server.start();\n * ```\n */\nexport class AppServer {\n /** Express app instance */\n private app: Express;\n /** Map of active user sessions by sessionId */\n private activeSessions = new Map<string, AppSession>();\n /** Map of active user sessions by userId */\n private activeSessionsByUserId = new Map<string, AppSession>();\n /** Array of cleanup handlers to run on shutdown */\n private cleanupHandlers: Array<() => void> = [];\n /** App instructions string shown to the user */\n private appInstructions: string | null = null;\n\n public readonly logger: Logger;\n\n constructor(private config: AppServerConfig) {\n // Set defaults and merge with provided config\n this.config = {\n port: 7010,\n webhookPath: \"/webhook\",\n publicDir: false,\n healthCheck: true,\n ...config,\n };\n\n this.logger = rootLogger.child({\n app: this.config.packageName,\n packageName: this.config.packageName,\n service: \"app-server\",\n });\n\n // Initialize Express app\n this.app = express();\n this.app.use(express.json());\n\n const cookieParser = require(\"cookie-parser\");\n this.app.use(\n cookieParser(\n this.config.cookieSecret ||\n `AOS_${this.config.packageName}_${this.config.apiKey.substring(\n 0,\n 8,\n )}`,\n ),\n );\n\n // Apply authentication middleware\n this.app.use(\n createAuthMiddleware({\n apiKey: this.config.apiKey,\n packageName: this.config.packageName,\n getAppSessionForUser: (userId: string) => {\n return this.activeSessionsByUserId.get(userId) || null;\n },\n cookieSecret:\n this.config.cookieSecret ||\n `AOS_${this.config.packageName}_${this.config.apiKey.substring(\n 0,\n 8,\n )}`,\n }) as any,\n );\n\n this.appInstructions = (config as any).appInstructions || null;\n\n // Setup server features\n this.setupWebhook();\n this.setupSettingsEndpoint();\n this.setupHealthCheck();\n this.setupToolCallEndpoint();\n this.setupPhotoUploadEndpoint();\n this.setupMentraAuthRedirect();\n this.setupPublicDir();\n this.setupShutdown();\n }\n\n // Expose Express app for custom routes.\n // This is useful for adding custom API routes or middleware.\n public getExpressApp(): Express {\n return this.app;\n }\n\n /**\n * 👥 Session Handler\n * Override this method to handle new App sessions.\n * This is where you implement your app's core functionality.\n *\n * @param session - App session instance for the user\n * @param sessionId - Unique identifier for this session\n * @param userId - User's identifier\n */\n protected async onSession(\n session: AppSession,\n sessionId: string,\n userId: string,\n ): Promise<void> {\n this.logger.info(\n `🚀 Starting new session handling for session ${sessionId} and user ${userId}`,\n );\n // Core session handling logic (onboarding removed)\n this.logger.info(\n `✅ Session handling completed for session ${sessionId} and user ${userId}`,\n );\n }\n\n /**\n * 👥 Stop Handler\n * Override this method to handle stop requests.\n * This is where you can clean up resources when a session is stopped.\n *\n * @param sessionId - Unique identifier for this session\n * @param userId - User's identifier\n * @param reason - Reason for stopping\n */\n protected async onStop(\n sessionId: string,\n userId: string,\n reason: string,\n ): Promise<void> {\n this.logger.debug(\n `Session ${sessionId} stopped for user ${userId}. Reason: ${reason}`,\n );\n\n // Default implementation: close the session if it exists\n const session = this.activeSessions.get(sessionId);\n if (session) {\n session.disconnect();\n this.activeSessions.delete(sessionId);\n this.activeSessionsByUserId.delete(userId);\n }\n }\n\n /**\n * 🛠️ Tool Call Handler\n * Override this method to handle tool calls from MentraOS Cloud.\n * This is where you implement your app's tool functionality.\n *\n * @param toolCall - The tool call request containing tool details and parameters\n * @returns Optional string response that will be sent back to MentraOS Cloud\n */\n protected async onToolCall(toolCall: ToolCall): Promise<string | undefined> {\n this.logger.debug(`Tool call received: ${toolCall.toolId}`);\n this.logger.debug(`Parameters: ${JSON.stringify(toolCall.toolParameters)}`);\n return undefined;\n }\n\n /**\n * 🚀 Start the Server\n * Starts listening for incoming connections and webhook calls.\n *\n * @returns Promise that resolves when server is ready\n */\n public start(): Promise<void> {\n return new Promise((resolve) => {\n this.app.listen(this.config.port, async () => {\n this.logger.info(\n `🎯 App server running at http://localhost:${this.config.port}`,\n );\n if (this.config.publicDir) {\n this.logger.info(\n `📂 Serving static files from ${this.config.publicDir}`,\n );\n }\n\n // 🔑 Grab SDK version\n try {\n // Look for the actual installed @mentra/sdk package.json in node_modules\n const sdkPkgPath = path.resolve(\n process.cwd(),\n \"node_modules/@mentra/sdk/package.json\",\n );\n\n let currentVersion = \"unknown\";\n\n if (fs.existsSync(sdkPkgPath)) {\n const sdkPkg = JSON.parse(fs.readFileSync(sdkPkgPath, \"utf-8\"));\n\n // Get the actual installed version\n currentVersion = sdkPkg.version || \"not-found\"; // located in the node module\n } else {\n this.logger.debug(\n { sdkPkgPath },\n \"No @mentra/sdk package.json found at path\",\n );\n }\n\n // this.logger.debug(`Developer is using SDK version: ${currentVersion}`);\n\n // Fetch latest SDK version from the API endpoint\n let latest: string | null = null;\n try {\n const cloudHost = \"api.mentra.glass\";\n const response = await axios.get(\n `https://${cloudHost}/api/sdk/version`,\n { timeout: 3000 }, // 3 second timeout\n );\n if (response.data && response.data.success && response.data.data) {\n latest = response.data.data.latest;\n }\n } catch {\n this.logger.debug(\n \"Failed to fetch latest SDK version - skipping version check (offline or API unavailable)\",\n );\n }\n\n if (currentVersion === \"not-found\") {\n this.logger.warn(\n `⚠️ @mentra/sdk not found in your project dependencies. Please install it with: npm install @mentra/sdk`,\n );\n } else if (latest && latest !== currentVersion) {\n this.logger.warn(newSDKUpdate(latest));\n }\n } catch (err) {\n this.logger.error(err, \"Version check failed\");\n }\n\n resolve();\n });\n });\n }\n\n /**\n * 🛑 Stop the Server\n * Gracefully shuts down the server and cleans up all sessions.\n */\n public stop(): void {\n this.logger.info(\"\\n🛑 Shutting down...\");\n this.cleanup();\n process.exit(0);\n }\n\n /**\n * 🔐 Generate a App token for a user\n * This should be called when handling a session webhook request.\n *\n * @param userId - User identifier\n * @param sessionId - Session identifier\n * @param secretKey - Secret key for signing the token\n * @returns JWT token string\n */\n protected generateToken(\n userId: string,\n sessionId: string,\n secretKey: string,\n ): string {\n const { createToken } = require(\"../token/utils\");\n return createToken(\n {\n userId,\n packageName: this.config.packageName,\n sessionId,\n },\n { secretKey },\n );\n }\n\n /**\n * 🧹 Add Cleanup Handler\n * Register a function to be called during server shutdown.\n *\n * @param handler - Function to call during cleanup\n */\n protected addCleanupHandler(handler: () => void): void {\n this.cleanupHandlers.push(handler);\n }\n\n /**\n * 🎯 Setup Webhook Endpoint\n * Creates the webhook endpoint that MentraOS Cloud calls to start new sessions.\n */\n private setupWebhook(): void {\n if (!this.config.webhookPath) {\n this.logger.error(\"❌ Webhook path not set\");\n throw new Error(\"Webhook path not set\");\n }\n\n this.app.post(this.config.webhookPath, async (req, res) => {\n try {\n const webhookRequest = req.body as WebhookRequest;\n\n // Handle session request\n if (webhookRequest.type === WebhookRequestType.SESSION_REQUEST) {\n await this.handleSessionRequest(webhookRequest, res);\n }\n // Handle stop request\n else if (webhookRequest.type === WebhookRequestType.STOP_REQUEST) {\n await this.handleStopRequest(webhookRequest, res);\n }\n // Unknown webhook type\n else {\n this.logger.error(\"❌ Unknown webhook request type\");\n res.status(400).json({\n status: \"error\",\n message: \"Unknown webhook request type\",\n } as WebhookResponse);\n }\n } catch (error) {\n this.logger.error(\n error,\n \"❌ Error handling webhook: \" + (error as Error).message,\n );\n res.status(500).json({\n status: \"error\",\n message: \"Error handling webhook: \" + (error as Error).message,\n } as WebhookResponse);\n }\n });\n }\n\n /**\n * 🛠️ Setup Tool Call Endpoint\n * Creates a /tool endpoint for handling tool calls from MentraOS Cloud.\n */\n private setupToolCallEndpoint(): void {\n this.app.post(\"/tool\", async (req, res) => {\n try {\n const toolCall = req.body as ToolCall;\n if (this.activeSessionsByUserId.has(toolCall.userId)) {\n toolCall.activeSession =\n this.activeSessionsByUserId.get(toolCall.userId) || null;\n } else {\n toolCall.activeSession = null;\n }\n this.logger.info(\n { body: req.body },\n `🔧 Received tool call: ${toolCall.toolId}`,\n );\n // Call the onToolCall handler and get the response\n const response = await this.onToolCall(toolCall);\n\n // Send back the response if one was provided\n if (response !== undefined) {\n res.json({ status: \"success\", reply: response });\n } else {\n res.json({ status: \"success\", reply: null });\n }\n } catch (error) {\n this.logger.error(error, \"❌ Error handling tool call:\");\n res.status(500).json({\n status: \"error\",\n message:\n error instanceof Error\n ? error.message\n : \"Unknown error occurred calling tool\",\n });\n }\n });\n this.app.get(\"/tool\", async (req, res) => {\n res.json({ status: \"success\", reply: \"Hello, world!\" });\n });\n }\n\n /**\n * Handle a session request webhook\n */\n private async handleSessionRequest(\n request: SessionWebhookRequest,\n res: express.Response,\n ): Promise<void> {\n const { sessionId, userId, mentraOSWebsocketUrl, augmentOSWebsocketUrl } =\n request;\n this.logger.info(\n { userId },\n `🗣️ Received session request for user ${userId}, session ${sessionId}\\n\\n`,\n );\n\n // Create new App session\n const session = new AppSession({\n packageName: this.config.packageName,\n apiKey: this.config.apiKey,\n mentraOSWebsocketUrl: mentraOSWebsocketUrl || augmentOSWebsocketUrl, // The websocket URL for the specific MentraOS server that this userSession is connecting to.\n appServer: this,\n userId,\n });\n\n // Setup session event handlers\n const cleanupDisconnect = session.events.onDisconnected((info) => {\n // Handle different disconnect info formats (string or object)\n if (typeof info === \"string\") {\n this.logger.info(`👋 Session ${sessionId} disconnected: ${info}`);\n } else {\n // It's an object with detailed disconnect information\n this.logger.info(\n `👋 Session ${sessionId} disconnected: ${info.message} (code: ${info.code}, reason: ${info.reason})`,\n );\n\n // Check if this is a user session end event\n // This happens when the UserSession is disposed after 1 minute grace period\n if (info.sessionEnded === true) {\n this.logger.info(\n `🛑 User session ended for session ${sessionId}, calling onStop`,\n );\n\n // Call onStop with session end reason\n // This allows apps to clean up resources when the user's session ends\n this.onStop(sessionId, userId, \"User session ended\").catch(\n (error) => {\n this.logger.error(\n error,\n `❌ Error in onStop handler for session end:`,\n );\n },\n );\n }\n // Check if this is a permanent disconnection after exhausted reconnection attempts\n else if (info.permanent === true) {\n this.logger.info(\n `🛑 Permanent disconnection detected for session ${sessionId}, calling onStop`,\n );\n\n // Keep track of the original session before removal\n // const session = this.activeSessions.get(sessionId);\n const _session = this.activeSessions.get(sessionId);\n\n // Call onStop with a reconnection failure reason\n this.onStop(\n sessionId,\n userId,\n `Connection permanently lost: ${info.reason}`,\n ).catch((error) => {\n this.logger.error(\n error,\n `❌ Error in onStop handler for permanent disconnection:`,\n );\n });\n }\n }\n\n // Remove the session from active sessions in all cases\n this.activeSessions.delete(sessionId);\n this.activeSessionsByUserId.delete(userId);\n });\n\n const cleanupError = session.events.onError((error) => {\n this.logger.error(error, `❌ [Session ${sessionId}] Error:`);\n });\n\n // Start the session\n try {\n await session.connect(sessionId);\n this.activeSessions.set(sessionId, session);\n this.activeSessionsByUserId.set(userId, session);\n await this.onSession(session, sessionId, userId);\n res.status(200).json({ status: \"success\" } as WebhookResponse);\n } catch (error) {\n this.logger.error(error, \"❌ Failed to connect:\");\n cleanupDisconnect();\n cleanupError();\n res.status(500).json({\n status: \"error\",\n message: \"Failed to connect\",\n } as WebhookResponse);\n }\n }\n\n /**\n * Handle a stop request webhook\n */\n private async handleStopRequest(\n request: StopWebhookRequest,\n res: express.Response,\n ): Promise<void> {\n const { sessionId, userId, reason } = request;\n this.logger.info(\n `\\n\\n🛑 Received stop request for user ${userId}, session ${sessionId}, reason: ${reason}\\n\\n`,\n );\n\n try {\n await this.onStop(sessionId, userId, reason);\n res.status(200).json({ status: \"success\" } as WebhookResponse);\n } catch (error) {\n this.logger.error(error, \"❌ Error handling stop request:\");\n res.status(500).json({\n status: \"error\",\n message: \"Failed to process stop request\",\n } as WebhookResponse);\n }\n }\n\n /**\n * ❤️ Setup Health Check Endpoint\n * Creates a /health endpoint for monitoring server status.\n */\n private setupHealthCheck(): void {\n if (this.config.healthCheck) {\n this.app.get(\"/health\", (req, res) => {\n res.json({\n status: \"healthy\",\n app: this.config.packageName,\n activeSessions: this.activeSessions.size,\n });\n });\n }\n }\n\n /**\n * ⚙️ Setup Settings Endpoint\n * Creates a /settings endpoint that the MentraOS Cloud can use to update settings.\n */\n private setupSettingsEndpoint(): void {\n this.app.post(\"/settings\", async (req, res) => {\n try {\n const { userIdForSettings, settings } = req.body;\n\n if (!userIdForSettings || !Array.isArray(settings)) {\n return res.status(400).json({\n status: \"error\",\n message: \"Missing userId or settings array in request body\",\n });\n }\n\n this.logger.info(\n `⚙️ Received settings update for user ${userIdForSettings}`,\n );\n\n // Find all active sessions for this user\n const userSessions: AppSession[] = [];\n\n // Look through all active sessions\n this.activeSessions.forEach((session, _sessionId) => {\n // Check if the session has this userId (not directly accessible)\n // We're relying on the webhook handler to have already verified this\n if (session.userId === userIdForSettings) {\n userSessions.push(session);\n }\n });\n\n if (userSessions.length === 0) {\n this.logger.warn(\n `⚠️ No active sessions found for user ${userIdForSettings}`,\n );\n } else {\n this.logger.info(\n `🔄 Updating settings for ${userSessions.length} active sessions`,\n );\n }\n\n // Update settings for all of the user's sessions\n for (const session of userSessions) {\n session.updateSettingsForTesting(settings);\n }\n\n // Allow subclasses to handle settings updates if they implement the method\n if (typeof (this as any).onSettingsUpdate === \"function\") {\n await (this as any).onSettingsUpdate(userIdForSettings, settings);\n }\n\n res.json({\n status: \"success\",\n message: \"Settings updated successfully\",\n sessionsUpdated: userSessions.length,\n });\n } catch (error) {\n this.logger.error(error, \"❌ Error handling settings update:\");\n res.status(500).json({\n status: \"error\",\n message: \"Internal server error processing settings update\",\n });\n }\n });\n }\n\n /**\n * 📂 Setup Static File Serving\n * Configures Express to serve static files from the specified directory.\n */\n private setupPublicDir(): void {\n if (this.config.publicDir) {\n const publicPath = path.resolve(this.config.publicDir);\n this.app.use(express.static(publicPath));\n this.logger.info(`📂 Serving static files from ${publicPath}`);\n }\n }\n\n /**\n * 🛑 Setup Shutdown Handlers\n * Registers process signal handlers for graceful shutdown.\n */\n private setupShutdown(): void {\n process.on(\"SIGTERM\", () => this.stop());\n process.on(\"SIGINT\", () => this.stop());\n }\n\n /**\n * 🧹 Cleanup\n * Closes all active sessions and runs cleanup handlers.\n */\n private cleanup(): void {\n // Close all active sessions\n for (const [sessionId, session] of this.activeSessions) {\n this.logger.info(`👋 Closing session ${sessionId}`);\n session.disconnect();\n }\n this.activeSessions.clear();\n this.activeSessionsByUserId.clear();\n\n // Run cleanup handlers\n this.cleanupHandlers.forEach((handler) => handler());\n }\n\n /**\n * 🎯 Setup Photo Upload Endpoint\n * Creates a /photo-upload endpoint for receiving photos directly from ASG glasses\n */\n private setupPhotoUploadEndpoint(): void {\n const multer = require(\"multer\");\n\n // Configure multer for handling multipart form data\n const upload = multer({\n storage: multer.memoryStorage(),\n limits: {\n fileSize: 10 * 1024 * 1024, // 10MB limit\n },\n fileFilter: (req: any, file: any, cb: any) => {\n // Accept image files only\n if (file.mimetype && file.mimetype.startsWith(\"image/\")) {\n cb(null, true);\n } else {\n cb(new Error(\"Only image files are allowed\"), false);\n }\n },\n });\n\n this.app.post(\n \"/photo-upload\",\n upload.single(\"photo\"),\n async (req: any, res: any) => {\n try {\n const { requestId, type, success, errorCode, errorMessage } =\n req.body;\n const photoFile = req.file;\n\n console.log(\"Received photo response: \", req.body);\n\n this.logger.info(\n { requestId, type, success, errorCode },\n `📸 Received photo response: ${requestId} (type: ${type})`,\n );\n\n if (!requestId) {\n this.logger.error(\"No requestId in photo response\");\n return res.status(400).json({\n success: false,\n error: \"No requestId provided\",\n });\n }\n\n // Find the corresponding session that made this photo request\n const session = this.findSessionByPhotoRequestId(requestId);\n if (!session) {\n this.logger.warn(\n { requestId },\n \"No active session found for photo request\",\n );\n return res.status(404).json({\n success: false,\n error: \"No active session found for this photo request\",\n });\n }\n\n // Handle error response (no photo file, but has error info)\n if (type === \"photo_error\" || success === false) {\n // Create error response object\n const errorResponse = {\n requestId,\n success: false as const,\n error: {\n code: errorCode || \"UNKNOWN_ERROR\",\n message: errorMessage || \"Unknown error occurred\",\n },\n };\n\n // Deliver error to the session (logging happens in camera module)\n session.camera.handlePhotoError(errorResponse);\n\n // Respond to ASG client\n return res.json({\n success: true,\n requestId,\n message: \"Photo error received successfully\",\n });\n }\n\n // Handle successful photo upload\n if (!photoFile) {\n this.logger.error(\n { requestId },\n \"No photo file in successful upload\",\n );\n return res.status(400).json({\n success: false,\n error: \"No photo file provided for successful upload\",\n });\n }\n\n // Create photo data object\n const photoData = {\n buffer: photoFile.buffer,\n mimeType: photoFile.mimetype,\n filename: photoFile.originalname || \"photo.jpg\",\n requestId,\n size: photoFile.size,\n timestamp: new Date(),\n };\n\n // Deliver photo to the session\n session.camera.handlePhotoReceived(photoData);\n\n // Respond to ASG client\n res.json({\n success: true,\n requestId,\n message: \"Photo received successfully\",\n });\n } catch (error) {\n this.logger.error(error, \"❌ Error handling photo response\");\n res.status(500).json({\n success: false,\n error: \"Internal server error processing photo response\",\n });\n }\n },\n );\n }\n\n /**\n * 🔐 Setup Mentra Auth Redirect Endpoint\n * Creates a /mentra-auth endpoint that redirects to the MentraOS OAuth flow.\n */\n private setupMentraAuthRedirect(): void {\n this.app.get(\"/mentra-auth\", (req, res) => {\n // Redirect to the account.mentra.glass OAuth flow with the app's package name\n const authUrl = `https://account.mentra.glass/auth?packagename=${encodeURIComponent(\n this.config.packageName,\n )}`;\n\n this.logger.info(`🔐 Redirecting to MentraOS OAuth flow: ${authUrl}`);\n\n res.redirect(302, authUrl);\n });\n }\n\n /**\n * Find session that has a pending photo request for the given requestId\n */\n private findSessionByPhotoRequestId(\n requestId: string,\n ): AppSession | undefined {\n for (const [_sessionId, session] of this.activeSessions) {\n if (session.camera.hasPhotoPendingRequest(requestId)) {\n return session;\n }\n }\n return undefined;\n }\n}\n\n/**\n * @deprecated Use `AppServerConfig` instead. `TpaServerConfig` is deprecated and will be removed in a future version.\n * This is an alias for backward compatibility only.\n *\n * @example\n * ```typescript\n * // ❌ Deprecated - Don't use this\n * const config: TpaServerConfig = { ... };\n *\n * // ✅ Use this instead\n * const config: AppServerConfig = { ... };\n * ```\n */\nexport type TpaServerConfig = AppServerConfig;\n\n/**\n * @deprecated Use `AppServer` instead. `TpaServer` is deprecated and will be removed in a future version.\n * This is an alias for backward compatibility only.\n *\n * @example\n * ```typescript\n * // ❌ Deprecated - Don't use this\n * class MyServer extends TpaServer { ... }\n *\n * // ✅ Use this instead\n * class MyServer extends AppServer { ... }\n * ```\n */\nexport class TpaServer extends AppServer {\n constructor(config: TpaServerConfig) {\n super(config);\n // Emit a deprecation warning to help developers migrate\n console.warn(\n \"⚠️ DEPRECATION WARNING: TpaServer is deprecated and will be removed in a future version. \" +\n \"Please use AppServer instead. \" +\n 'Simply replace \"TpaServer\" with \"AppServer\" in your code.',\n );\n }\n}\n",
21
- "/* eslint-disable import/order */\n/* eslint-disable no-restricted-imports */\n/**\n * 🎯 App Session Module\n *\n * Manages an active Third Party App session with MentraOS Cloud.\n * Handles real-time communication, event subscriptions, and display management.\n */\nimport {WebSocket} from \"ws\"\nimport {EventManager, EventData} from \"./events\"\nimport {LayoutManager} from \"./layouts\"\nimport {SettingsManager} from \"./settings\"\nimport {LocationManager} from \"./modules/location\"\nimport {CameraModule} from \"./modules/camera\"\nimport {LedModule} from \"./modules/led\"\nimport {AudioManager} from \"./modules/audio\"\nimport {ResourceTracker} from \"../../utils/resource-tracker\"\nimport {\n // Message types\n AppToCloudMessage,\n CloudToAppMessage,\n AppConnectionInit,\n AppSubscriptionUpdate,\n AudioPlayResponse,\n RequestWifiSetup,\n AppToCloudMessageType,\n CloudToAppMessageType,\n\n // Event data types\n StreamType,\n ExtendedStreamType,\n ButtonPress,\n HeadPosition,\n TouchEvent,\n PhoneNotification,\n PhoneNotificationDismissed,\n TranscriptionData,\n TranslationData,\n createTouchEventStream,\n\n // Type guards\n isAppConnectionAck,\n isAppConnectionError,\n isDataStream,\n isAppStopped,\n isSettingsUpdate,\n isDashboardModeChanged,\n isDashboardAlwaysOnChanged,\n isAudioPlayResponse,\n isCapabilitiesUpdate,\n\n // Other types\n AppSettings,\n AppSetting,\n AppConfig,\n validateAppConfig,\n AudioChunk,\n VpsCoordinates,\n PhotoTaken,\n SubscriptionRequest,\n Capabilities,\n CapabilitiesUpdate,\n} from \"../../types\"\nimport {DashboardAPI} from \"../../types/dashboard\"\nimport {MentraosSettingsUpdate} from \"../../types/messages/cloud-to-app\"\nimport {Logger} from \"pino\"\nimport {AppServer} from \"../server\"\nimport axios from \"axios\"\nimport EventEmitter from \"events\"\n\n// Import the cloud-to-app specific type guards\nimport {\n isPhotoResponse,\n isRgbLedControlResponse,\n isRtmpStreamStatus,\n isManagedStreamStatus,\n isStreamStatusCheckResponse,\n} from \"../../types/messages/cloud-to-app\"\nimport {SimpleStorage} from \"./modules/simple-storage\"\nimport {readNotificationWarnLog} from \"../../utils/permissions-utils\"\n\n/**\n * ⚙️ Configuration options for App Session\n *\n * @example\n * ```typescript\n * const config: AppSessionConfig = {\n * packageName: 'org.example.myapp',\n * apiKey: 'your_api_key',\n * // Auto-reconnection is enabled by default\n * // autoReconnect: true\n * };\n * ```\n */\nexport interface AppSessionConfig {\n /** 📦 Unique identifier for your App (e.g., 'org.company.appname') */\n packageName: string\n /** 🔑 API key for authentication with MentraOS Cloud */\n apiKey: string\n /** 🔌 WebSocket server URL (default: 'ws://localhost:7002/app-ws') */\n mentraOSWebsocketUrl?: string\n /** 🔄 Automatically attempt to reconnect on disconnect (default: true) */\n autoReconnect?: boolean\n /** 🔁 Maximum number of reconnection attempts (default: 3) */\n maxReconnectAttempts?: number\n /** ⏱️ Base delay between reconnection attempts in ms (default: 1000) */\n reconnectDelay?: number\n\n userId: string // user ID for tracking sessions (email of the user).\n appServer: AppServer // Optional App server instance for advanced features\n}\n\n// List of event types that should never be subscribed to as streams\nconst APP_TO_APP_EVENT_TYPES = [\n \"app_message_received\",\n \"app_user_joined\",\n \"app_user_left\",\n \"app_room_updated\",\n \"app_direct_message_response\",\n]\n\n/**\n * 🚀 App Session Implementation\n *\n * Manages a live connection between your App and MentraOS Cloud.\n * Provides interfaces for:\n * - 🎮 Event handling (transcription, head position, etc.)\n * - 📱 Display management in AR view\n * - 🔌 Connection lifecycle\n * - 🔄 Automatic reconnection\n *\n * @example\n * ```typescript\n * const session = new AppSession({\n * packageName: 'org.example.myapp',\n * apiKey: 'your_api_key'\n * });\n *\n * // Handle events\n * session.onTranscription((data) => {\n * session.layouts.showTextWall(data.text);\n * });\n *\n * // Connect to cloud\n * await session.connect('session_123');\n * ```\n */\nexport class AppSession {\n /** WebSocket connection to MentraOS Cloud */\n private ws: WebSocket | null = null\n /** Current session identifier */\n private sessionId: string | null = null\n /** Number of reconnection attempts made */\n private reconnectAttempts = 0\n /** Active event subscriptions */\n private subscriptions = new Set<ExtendedStreamType>()\n /** Map to store rate options for streams */\n private streamRates = new Map<ExtendedStreamType, string>()\n /** Resource tracker for automatic cleanup */\n private resources = new ResourceTracker()\n /** Internal settings storage - use public settings API instead */\n private settingsData: AppSettings = []\n /** App configuration loaded from app_config.json */\n private appConfig: AppConfig | null = null\n /** Whether to update subscriptions when settings change */\n private shouldUpdateSubscriptionsOnSettingsChange = false\n /** Custom subscription handler for settings-based subscriptions */\n private subscriptionSettingsHandler?: (settings: AppSettings) => ExtendedStreamType[]\n /** Settings that should trigger subscription updates when changed */\n private subscriptionUpdateTriggers: string[] = []\n /** Pending user discovery requests waiting for responses */\n private pendingUserDiscoveryRequests = new Map<\n string,\n {\n resolve: (userList: any) => void\n reject: (reason: any) => void\n }\n >()\n /** Pending direct message requests waiting for responses */\n private pendingDirectMessages = new Map<\n string,\n {\n resolve: (success: boolean) => void\n reject: (reason: any) => void\n }\n >()\n\n /** 🎮 Event management interface */\n public readonly events: EventManager\n /** 📱 Layout management interface */\n public readonly layouts: LayoutManager\n /** ⚙️ Settings management interface */\n public readonly settings: SettingsManager\n /** 📊 Dashboard management interface */\n public readonly dashboard: DashboardAPI\n /** 📍 Location management interface */\n public readonly location: LocationManager\n /** 📷 Camera interface for photos and streaming */\n public readonly camera: CameraModule\n /** 💡 LED interface for RGB LED control */\n public readonly led: LedModule\n /** 🔊 Audio interface for audio playback */\n public readonly audio: AudioManager\n /** 🔐 Simple key-value storage interface */\n public readonly simpleStorage: SimpleStorage\n\n public readonly appServer: AppServer\n public readonly logger: Logger\n public readonly userId: string\n\n /** 🔧 Device capabilities available for this session */\n public capabilities: Capabilities | null = null\n\n /** 📡 Latest glasses connection state (includes WiFi status) */\n private glassesConnectionState: any = null // Using any for now since GlassesConnectionState is in glasses-to-cloud types\n\n /** Dedicated emitter for App-to-App events */\n private appEvents = new EventEmitter()\n\n constructor(private config: AppSessionConfig) {\n // Set defaults and merge with provided config\n this.config = {\n mentraOSWebsocketUrl: `ws://localhost:8002/app-ws`, // Use localhost as default\n autoReconnect: true, // Enable auto-reconnection by default for better reliability\n maxReconnectAttempts: 3, // Default to 3 reconnection attempts for better resilience\n reconnectDelay: 1000, // Start with 1 second delay (uses exponential backoff)\n ...config,\n }\n\n this.appServer = this.config.appServer\n this.logger = this.appServer.logger.child({\n userId: this.config.userId,\n service: \"app-session\",\n })\n this.userId = this.config.userId\n\n // Make sure the URL is correctly formatted to prevent double protocol issues\n if (this.config.mentraOSWebsocketUrl) {\n try {\n const url = new URL(this.config.mentraOSWebsocketUrl)\n if (![\"ws:\", \"wss:\"].includes(url.protocol)) {\n // Fix URLs with incorrect protocol (e.g., 'ws://http://host')\n const fixedUrl = this.config.mentraOSWebsocketUrl.replace(/^ws:\\/\\/http:\\/\\//, \"ws://\")\n this.config.mentraOSWebsocketUrl = fixedUrl\n this.logger.warn(`⚠️ [${this.config.packageName}] Fixed malformed WebSocket URL: ${fixedUrl}`)\n }\n } catch (error) {\n this.logger.error(\n error,\n `⚠️ [${this.config.packageName}] Invalid WebSocket URL format: ${this.config.mentraOSWebsocketUrl}`,\n )\n }\n }\n\n // Log initialization\n this.logger.debug(`🚀 [${this.config.packageName}] App Session initialized`)\n this.logger.debug(`🚀 [${this.config.packageName}] WebSocket URL: ${this.config.mentraOSWebsocketUrl}`)\n\n // Validate URL format - give early warning for obvious issues\n // Check URL format but handle undefined case\n if (this.config.mentraOSWebsocketUrl) {\n try {\n const url = new URL(this.config.mentraOSWebsocketUrl)\n if (![\"ws:\", \"wss:\"].includes(url.protocol)) {\n this.logger.error(\n {config: this.config},\n `⚠️ [${this.config.packageName}] Invalid WebSocket URL protocol: ${url.protocol}. Should be ws: or wss:`,\n )\n }\n } catch (error) {\n this.logger.error(\n error,\n `⚠️ [${this.config.packageName}] Invalid WebSocket URL format: ${this.config.mentraOSWebsocketUrl}`,\n )\n }\n }\n\n this.events = new EventManager(\n this.subscribe.bind(this),\n this.unsubscribe.bind(this),\n this.config.packageName,\n this.getHttpsServerUrl() || \"\",\n )\n this.layouts = new LayoutManager(config.packageName, this.send.bind(this))\n\n // Initialize settings manager with all necessary parameters, including subscribeFn for MentraOS settings\n this.settings = new SettingsManager(\n this.settingsData,\n this.config.packageName,\n this.config.mentraOSWebsocketUrl,\n this.sessionId ?? undefined,\n async (streams: string[]) => {\n this.logger.debug({streams: JSON.stringify(streams)}, `[AppSession] subscribeFn called for streams`)\n streams.forEach((stream) => {\n if (!this.subscriptions.has(stream as ExtendedStreamType)) {\n this.subscriptions.add(stream as ExtendedStreamType)\n this.logger.debug(`[AppSession] Auto-subscribed to stream '${stream}' for MentraOS setting.`)\n } else {\n this.logger.debug(`[AppSession] Already subscribed to stream '${stream}'.`)\n }\n })\n this.logger.debug(\n {subscriptions: JSON.stringify(Array.from(this.subscriptions))},\n `[AppSession] Current subscriptions after subscribeFn`,\n )\n if (this.ws?.readyState === 1) {\n this.updateSubscriptions()\n this.logger.debug(\n `[AppSession] Sent updated subscriptions to cloud after auto-subscribing to MentraOS setting.`,\n )\n } else {\n this.logger.debug(`[AppSession] WebSocket not open, will send subscriptions when connected.`)\n }\n },\n )\n\n // Initialize dashboard API with this session instance\n // Import DashboardManager dynamically to avoid circular dependency\n const {DashboardManager} = require(\"./dashboard\")\n this.dashboard = new DashboardManager(this)\n\n // Initialize camera module with session reference\n this.camera = new CameraModule(\n this,\n this.config.packageName,\n this.sessionId || \"unknown-session-id\",\n this.logger.child({module: \"camera\"}),\n )\n\n // Initialize LED control module\n this.led = new LedModule(\n this,\n this.config.packageName,\n this.sessionId || \"unknown-session-id\",\n this.logger.child({module: \"led\"}),\n )\n\n // Initialize audio module with session reference\n this.audio = new AudioManager(\n this,\n this.config.packageName,\n this.sessionId || \"unknown-session-id\",\n this.logger.child({module: \"audio\"}),\n )\n\n this.simpleStorage = new SimpleStorage(this)\n\n this.location = new LocationManager(this)\n }\n\n /**\n * Get the current session ID\n * @returns The current session ID or 'unknown-session-id' if not connected\n */\n getSessionId(): string {\n return this.sessionId || \"unknown-session-id\"\n }\n\n /**\n * Get the package name for this App\n * @returns The package name\n */\n getPackageName(): string {\n return this.config.packageName\n }\n\n // =====================================\n // 🎮 Direct Event Handling Interface\n // =====================================\n\n /**\n * @deprecated Use session.events.onTranscription() instead\n */\n onTranscription(handler: (data: TranscriptionData) => void): () => void {\n return this.events.onTranscription(handler)\n }\n\n /**\n * 🌐 Listen for speech transcription events in a specific language\n * @param language - Language code (e.g., \"en-US\")\n * @param handler - Function to handle transcription data\n * @returns Cleanup function to remove the handler\n * @throws Error if language code is invalid\n * @deprecated Use session.events.onTranscriptionForLanguage() instead\n */\n onTranscriptionForLanguage(\n language: string,\n handler: (data: TranscriptionData) => void,\n disableLanguageIdentification = false,\n ): () => void {\n return this.events.onTranscriptionForLanguage(language, handler, disableLanguageIdentification)\n }\n\n /**\n * 🌐 Listen for speech translation events for a specific language pair\n * @param sourceLanguage - Source language code (e.g., \"es-ES\")\n * @param targetLanguage - Target language code (e.g., \"en-US\")\n * @param handler - Function to handle translation data\n * @returns Cleanup function to remove the handler\n * @throws Error if language codes are invalid\n * @deprecated Use session.events.onTranslationForLanguage() instead\n */\n onTranslationForLanguage(\n sourceLanguage: string,\n targetLanguage: string,\n handler: (data: TranslationData) => void,\n ): () => void {\n return this.events.ontranslationForLanguage(sourceLanguage, targetLanguage, handler)\n }\n\n /**\n * 👤 Listen for head position changes\n * @param handler - Function to handle head position updates\n * @returns Cleanup function to remove the handler\n * @deprecated Use session.events.onHeadPosition() instead\n */\n onHeadPosition(handler: (data: HeadPosition) => void): () => void {\n return this.events.onHeadPosition(handler)\n }\n\n /**\n * 🔘 Listen for hardware button press events\n * @param handler - Function to handle button events\n * @returns Cleanup function to remove the handler\n * @deprecated Use session.events.onButtonPress() instead\n */\n onButtonPress(handler: (data: ButtonPress) => void): () => void {\n return this.events.onButtonPress(handler)\n }\n\n /**\n * 👆 Listen for touch gesture events\n * @param gestureOrHandler - Gesture name or handler function\n * @param handler - Handler function (if first param is gesture name)\n * @returns Cleanup function\n *\n * @example\n * // Subscribe to all touch events\n * session.onTouchEvent((event) => console.log(event.gesture_name));\n *\n * // Subscribe to specific gesture\n * session.onTouchEvent(\"forward_swipe\", (event) => console.log(\"Forward swipe!\"));\n */\n onTouchEvent(\n gestureOrHandler: string | ((data: TouchEvent) => void),\n handler?: (data: TouchEvent) => void,\n ): () => void {\n return this.events.onTouchEvent(gestureOrHandler as any, handler as any)\n }\n\n /**\n * 👆 Subscribe to multiple touch gestures\n * @param gestures - Array of gesture names\n * @returns Cleanup function that unsubscribes from all\n *\n * @example\n * session.subscribeToGestures([\"forward_swipe\", \"backward_swipe\"]);\n */\n subscribeToGestures(gestures: string[]): () => void {\n gestures.forEach((gesture) => {\n const stream = createTouchEventStream(gesture)\n this.subscribe(stream)\n })\n\n return () => {\n gestures.forEach((gesture) => {\n const stream = createTouchEventStream(gesture)\n this.unsubscribe(stream)\n })\n }\n }\n\n /**\n * 📱 Listen for phone notification events\n * @param handler - Function to handle notifications\n * @returns Cleanup function to remove the handler\n * @deprecated Use session.events.onPhoneNotifications() instead\n */\n onPhoneNotifications(handler: (data: PhoneNotification) => void): () => void {\n readNotificationWarnLog(this.getHttpsServerUrl() || \"\", this.getPackageName(), \"onPhoneNotifications\")\n return this.events.onPhoneNotifications(handler)\n }\n\n /**\n * 📱 Listen for phone notification dismissed events\n * @param handler - Function to handle notification dismissal data\n * @returns Cleanup function to remove the handler\n * @deprecated Use session.events.onPhoneNotificationDismissed() instead\n */\n onPhoneNotificationDismissed(handler: (data: PhoneNotificationDismissed) => void): () => void {\n return this.events.onPhoneNotificationDismissed(handler)\n }\n\n /**\n * 📡 Listen for VPS coordinates updates\n * @param handler - Function to handle VPS coordinates\n * @returns Cleanup function to remove the handler\n * @deprecated Use session.events.onVpsCoordinates() instead\n */\n onVpsCoordinates(handler: (data: VpsCoordinates) => void): () => void {\n this.subscribe(StreamType.VPS_COORDINATES)\n return this.events.onVpsCoordinates(handler)\n }\n\n /**\n * 📸 Listen for photo responses\n * @param handler - Function to handle photo response data\n * @returns Cleanup function to remove the handler\n * @deprecated Use session.events.onPhotoTaken() instead\n */\n onPhotoTaken(handler: (data: PhotoTaken) => void): () => void {\n this.subscribe(StreamType.PHOTO_TAKEN)\n return this.events.onPhotoTaken(handler)\n }\n\n // =====================================\n // 📡 Pub/Sub Interface\n // =====================================\n\n /**\n * 📬 Subscribe to a specific event stream\n * @param sub - A string or a rich subscription object\n */\n subscribe(sub: SubscriptionRequest): void {\n let type: ExtendedStreamType\n let rate: string | undefined\n\n if (typeof sub === \"string\") {\n type = sub\n } else {\n // it's a LocationStreamRequest object\n type = sub.stream\n rate = sub.rate\n }\n\n if (APP_TO_APP_EVENT_TYPES.includes(type as string)) {\n this.logger.warn(\n `[AppSession] Attempted to subscribe to App-to-App event type '${type}', which is not a valid stream. Use the event handler (e.g., onAppMessage) instead.`,\n )\n return\n }\n\n this.subscriptions.add(type)\n if (rate) {\n this.streamRates.set(type, rate)\n }\n\n if (this.ws?.readyState === 1) {\n this.updateSubscriptions()\n }\n }\n\n /**\n * 📭 Unsubscribe from a specific event stream\n * @param sub - The subscription to remove\n */\n unsubscribe(sub: SubscriptionRequest): void {\n let type: ExtendedStreamType\n if (typeof sub === \"string\") {\n type = sub\n } else {\n type = sub.stream\n }\n\n if (APP_TO_APP_EVENT_TYPES.includes(type as string)) {\n this.logger.warn(\n `[AppSession] Attempted to unsubscribe from App-to-App event type '${type}', which is not a valid stream.`,\n )\n return\n }\n this.subscriptions.delete(type)\n this.streamRates.delete(type) // also remove from our rate map\n if (this.ws?.readyState === 1) {\n this.updateSubscriptions()\n }\n }\n\n /**\n * 🎯 Generic event listener (pub/sub style)\n * @param event - Event name to listen for\n * @param handler - Event handler function\n */\n on<T extends ExtendedStreamType>(event: T, handler: (data: EventData<T>) => void): () => void {\n return this.events.on(event, handler)\n }\n\n // =====================================\n // 🔌 Connection Management\n // =====================================\n\n /**\n * 🚀 Connect to MentraOS Cloud\n * @param sessionId - Unique session identifier\n * @returns Promise that resolves when connected\n */\n async connect(sessionId: string): Promise<void> {\n this.sessionId = sessionId\n\n // Configure settings API client with the WebSocket URL and session ID\n // This allows settings to be fetched from the correct server\n this.settings.configureApiClient(this.config.packageName, this.config.mentraOSWebsocketUrl || \"\", sessionId)\n\n // Update the sessionId in the camera module\n if (this.camera) {\n this.camera.updateSessionId(sessionId)\n }\n\n // Update the sessionId in the audio module\n if (this.audio) {\n this.audio.updateSessionId(sessionId)\n }\n\n return new Promise((resolve, reject) => {\n try {\n // Clear previous resources if reconnecting\n if (this.ws) {\n // Don't call full dispose() as that would clear subscriptions\n if (this.ws.readyState !== 3) {\n // 3 = CLOSED\n this.ws.close()\n }\n this.ws = null\n }\n\n // Validate WebSocket URL before attempting connection\n if (!this.config.mentraOSWebsocketUrl) {\n this.logger.error(\"WebSocket URL is missing or undefined\")\n reject(new Error(\"WebSocket URL is required\"))\n return\n }\n\n // Add debug logging for connection attempts\n this.logger.info(\n `🔌🔌🔌 [${this.config.packageName}] Attempting to connect to: ${this.config.mentraOSWebsocketUrl} for session ${this.sessionId}`,\n )\n\n // Create connection with error handling\n this.ws = new WebSocket(this.config.mentraOSWebsocketUrl)\n\n // Track WebSocket for automatic cleanup\n this.resources.track(() => {\n if (this.ws && this.ws.readyState !== 3) {\n // 3 = CLOSED\n this.ws.close()\n }\n })\n\n this.ws.on(\"open\", () => {\n try {\n this.sendConnectionInit()\n } catch (error: unknown) {\n this.logger.error(error, \"Error during connection initialization\")\n const errorMessage = error instanceof Error ? error.message : String(error)\n this.events.emit(\"error\", new Error(`Connection initialization failed: ${errorMessage}`))\n reject(error)\n }\n })\n\n // Message handler with comprehensive error recovery\n const messageHandler = async (data: Buffer | string, isBinary: boolean) => {\n try {\n // Handle binary messages (typically audio data)\n if (isBinary && Buffer.isBuffer(data)) {\n try {\n // Validate buffer before processing\n if (data.length === 0) {\n this.events.emit(\"error\", new Error(\"Received empty binary data\"))\n return\n }\n\n // Convert Node.js Buffer to ArrayBuffer safely\n const arrayBuf: ArrayBufferLike = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength)\n\n // Create AUDIO_CHUNK event message with validation\n const audioChunk: AudioChunk = {\n type: StreamType.AUDIO_CHUNK,\n arrayBuffer: arrayBuf,\n timestamp: new Date(), // Ensure timestamp is present\n }\n\n this.handleMessage(audioChunk)\n return\n } catch (error: unknown) {\n this.logger.error(error, \"Error processing binary message:\")\n const errorMessage = error instanceof Error ? error.message : String(error)\n this.events.emit(\"error\", new Error(`Failed to process binary message: ${errorMessage}`))\n return\n }\n }\n\n // Handle ArrayBuffer data type directly\n if (data instanceof ArrayBuffer) {\n return\n }\n\n // Handle JSON messages with validation\n try {\n // Convert string data to JSON safely\n let jsonData: string\n if (typeof data === \"string\") {\n jsonData = data\n } else if (Buffer.isBuffer(data)) {\n jsonData = data.toString(\"utf8\")\n } else {\n throw new Error(\"Unknown message format\")\n }\n\n // Validate JSON before parsing\n if (!jsonData || jsonData.trim() === \"\") {\n this.events.emit(\"error\", new Error(\"Received empty JSON message\"))\n return\n }\n\n // Parse JSON with error handling\n const message = JSON.parse(jsonData) as CloudToAppMessage\n\n // Basic schema validation\n if (!message || typeof message !== \"object\" || !(\"type\" in message)) {\n this.events.emit(\"error\", new Error(\"Malformed message: missing type property\"))\n return\n }\n\n // Process the validated message\n this.handleMessage(message)\n } catch (error: unknown) {\n this.logger.error(error, \"JSON parsing error\")\n const errorMessage = error instanceof Error ? error.message : String(error)\n this.events.emit(\"error\", new Error(`Failed to parse JSON message: ${errorMessage}`))\n }\n } catch (error: unknown) {\n // Final catch - should never reach here if individual handlers work correctly\n this.logger.error({error}, \"Unhandled message processing error\")\n const errorMessage = error instanceof Error ? error.message : String(error)\n this.events.emit(\"error\", new Error(`Unhandled message error: ${errorMessage}`))\n }\n }\n\n this.ws.on(\"message\", messageHandler)\n\n // Track event handler removal for automatic cleanup\n this.resources.track(() => {\n if (this.ws) {\n this.ws.off(\"message\", messageHandler)\n }\n })\n\n // Connection closure handler\n const closeHandler = (code: number, reason: string) => {\n const reasonStr = reason ? `: ${reason}` : \"\"\n const closeInfo = `Connection closed (code: ${code})${reasonStr}`\n\n // Emit the disconnected event with structured data for better handling\n this.events.emit(\"disconnected\", {\n message: closeInfo,\n code: code,\n reason: reason || \"\",\n wasClean: code === 1000 || code === 1001,\n })\n\n // Only attempt reconnection for abnormal closures\n // https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/code\n // 1000 (Normal Closure) and 1001 (Going Away) are normal\n // 1002-1015 are abnormal, and reason \"App stopped\" means intentional closure\n // 1008 usually when the userSession no longer exists on server. i.e user disconnected from cloud.\n const isNormalClosure = code === 1000 || code === 1001 || code === 1008\n const isManualStop = reason && reason.includes(\"App stopped\")\n const isUserSessionEnded = reason && reason.includes(\"User session ended\")\n\n // Log closure details for diagnostics\n this.logger.debug(`🔌 [${this.config.packageName}] WebSocket closed with code ${code}${reasonStr}`)\n this.logger.debug(\n `🔌 [${this.config.packageName}] isNormalClosure: ${isNormalClosure}, isManualStop: ${isManualStop}, isUserSessionEnded: ${isUserSessionEnded}`,\n )\n\n if (!isNormalClosure && !isManualStop) {\n this.logger.warn(`🔌 [${this.config.packageName}] Abnormal closure detected, attempting reconnection`)\n this.handleReconnection()\n } else {\n this.logger.debug(`🔌 [${this.config.packageName}] Normal closure detected, not attempting reconnection`)\n }\n\n // if user session ended, then trigger onStop.\n if (isUserSessionEnded) {\n this.logger.info(\n `🛑 [${this.config.packageName}] User session ended - emitting disconnected event with sessionEnded flag`,\n )\n // Emit a disconnected event with a special flag to indicate session end\n // This will be caught by AppServer which will call the onStop callback\n const disconnectInfo = {\n message: \"User session ended\",\n code: 1000, // Normal closure\n reason: \"User session ended\",\n wasClean: true,\n permanent: true, // This is permanent - no reconnection\n sessionEnded: true, // Special flag to indicate session disposal\n }\n this.events.emit(\"disconnected\", disconnectInfo)\n }\n }\n\n this.ws.on(\"close\", closeHandler)\n\n // Track event handler removal\n this.resources.track(() => {\n if (this.ws) {\n this.ws.off(\"close\", closeHandler)\n }\n })\n\n // Connection error handler\n const errorHandler = (error: Error) => {\n this.logger.error(error, \"WebSocket error\")\n this.events.emit(\"error\", error)\n }\n\n // Enhanced error handler with detailed logging\n this.ws.on(\"error\", (error: Error) => {\n this.logger.error(\n error,\n `⛔️⛔️⛔️ [${this.config.packageName}] WebSocket connection error: ${error.message}`,\n )\n\n // Try to provide more context\n const errMsg = error.message || \"\"\n if (errMsg.includes(\"ECONNREFUSED\")) {\n this.logger.error(\n `⛔️⛔️⛔️ [${this.config.packageName}] Connection refused - Check if the server is running at the specified URL`,\n )\n } else if (errMsg.includes(\"ETIMEDOUT\")) {\n this.logger.error(\n `⛔️⛔️⛔️ [${this.config.packageName}] Connection timed out - Check network connectivity and firewall rules`,\n )\n }\n\n errorHandler(error)\n })\n\n // Track event handler removal\n this.resources.track(() => {\n if (this.ws) {\n this.ws.off(\"error\", errorHandler)\n }\n })\n\n // Set up connection success handler\n const connectedCleanup = this.events.onConnected(() => resolve())\n\n // Track event handler removal\n this.resources.track(connectedCleanup)\n\n // Connection timeout with configurable duration\n const timeoutMs = 5000 // 5 seconds default\n const connectionTimeout = this.resources.setTimeout(() => {\n // Use tracked timeout that will be auto-cleared\n this.logger.error(\n {\n config: this.config,\n sessionId: this.sessionId,\n timeoutMs,\n },\n `⏱️⏱️⏱️ [${this.config.packageName}] Connection timeout after ${timeoutMs}ms`,\n )\n\n this.events.emit(\"error\", new Error(`Connection timeout after ${timeoutMs}ms`))\n reject(new Error(\"Connection timeout\"))\n }, timeoutMs)\n\n // Clear timeout on successful connection\n const timeoutCleanup = this.events.onConnected(() => {\n clearTimeout(connectionTimeout)\n resolve()\n })\n\n // Track event handler removal\n this.resources.track(timeoutCleanup)\n } catch (error: unknown) {\n this.logger.error(error, \"Connection setup error\")\n const errorMessage = error instanceof Error ? error.message : String(error)\n reject(new Error(`Failed to setup connection: ${errorMessage}`))\n }\n })\n }\n\n /**\n * 👋 Disconnect from MentraOS Cloud\n * Flushes any pending SimpleStorage writes before closing\n */\n async disconnect(): Promise<void> {\n // Flush any pending SimpleStorage writes before closing\n try {\n await this.simpleStorage.flush()\n console.log(\"SimpleStorage flushed on disconnect\")\n } catch (error) {\n console.error(\"Error flushing SimpleStorage on disconnect:\", error)\n // Continue with disconnect even if flush fails\n }\n\n // Clean up camera module first\n if (this.camera) {\n this.camera.cancelAllRequests()\n }\n\n // Clean up audio module\n if (this.audio) {\n this.audio.cancelAllRequests()\n }\n\n // Use the resource tracker to clean up everything\n this.resources.dispose()\n\n // Clean up additional resources not handled by the tracker\n this.ws = null\n this.sessionId = null\n this.subscriptions.clear()\n this.reconnectAttempts = 0\n }\n\n /**\n * 🛠️ Get all current user settings\n * @returns A copy of the current settings array\n * @deprecated Use session.settings.getAll() instead\n */\n getSettings(): AppSettings {\n return this.settings.getAll()\n }\n\n /**\n * 🔍 Get a specific setting value by key\n * @param key The setting key to look for\n * @returns The setting's value, or undefined if not found\n * @deprecated Use session.settings.get(key) instead\n */\n getSetting<T>(key: string): T | undefined {\n return this.settings.get<T>(key)\n }\n\n /**\n * ⚙️ Configure settings-based subscription updates\n * This allows Apps to automatically update their subscriptions when certain settings change\n * @param options Configuration options for settings-based subscriptions\n */\n setSubscriptionSettings(options: {\n updateOnChange: string[] // Setting keys that should trigger subscription updates\n handler: (settings: AppSettings) => ExtendedStreamType[] // Handler that returns new subscriptions\n }): void {\n this.shouldUpdateSubscriptionsOnSettingsChange = true\n this.subscriptionUpdateTriggers = options.updateOnChange\n this.subscriptionSettingsHandler = options.handler\n\n // If we already have settings, update subscriptions immediately\n if (this.settingsData.length > 0) {\n this.updateSubscriptionsFromSettings()\n }\n }\n\n /**\n * 🔄 Update subscriptions based on current settings\n * Called automatically when relevant settings change\n */\n private updateSubscriptionsFromSettings(): void {\n if (!this.subscriptionSettingsHandler) return\n\n try {\n // Get new subscriptions from handler\n const newSubscriptions = this.subscriptionSettingsHandler(this.settingsData)\n\n // Update all subscriptions at once\n this.subscriptions.clear()\n newSubscriptions.forEach((subscription) => {\n this.subscriptions.add(subscription)\n })\n\n // Send subscription update to cloud if connected\n if (this.ws && this.ws.readyState === 1) {\n this.updateSubscriptions()\n }\n } catch (error: unknown) {\n this.logger.error(error, \"Error updating subscriptions from settings\")\n const errorMessage = error instanceof Error ? error.message : String(error)\n this.events.emit(\"error\", new Error(`Failed to update subscriptions: ${errorMessage}`))\n }\n }\n\n /**\n * 🧪 For testing: Update settings locally\n * In normal operation, settings come from the cloud\n * @param newSettings The new settings to apply\n */\n updateSettingsForTesting(newSettings: AppSettings): void {\n this.settingsData = newSettings\n\n // Update the settings manager with the new settings\n this.settings.updateSettings(newSettings)\n\n // Emit update event for backwards compatibility\n this.events.emit(\"settings_update\", this.settingsData)\n\n // Check if we should update subscriptions\n if (this.shouldUpdateSubscriptionsOnSettingsChange) {\n this.updateSubscriptionsFromSettings()\n }\n }\n\n /**\n * 📝 Load configuration from a JSON file\n * @param jsonData JSON string containing App configuration\n * @returns The loaded configuration\n * @throws Error if the configuration is invalid\n */\n loadConfigFromJson(jsonData: string): AppConfig {\n try {\n const parsedConfig = JSON.parse(jsonData)\n\n if (validateAppConfig(parsedConfig)) {\n this.appConfig = parsedConfig\n return parsedConfig\n } else {\n throw new Error(\"Invalid App configuration format\")\n }\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n throw new Error(`Failed to load App configuration: ${errorMessage}`)\n }\n }\n\n /**\n * 📋 Get the loaded App configuration\n * @returns The current App configuration or null if not loaded\n */\n getConfig(): AppConfig | null {\n return this.appConfig\n }\n\n /**\n * 🔌 Get the WebSocket server URL for this session\n * @returns The WebSocket server URL used by this session\n */\n getServerUrl(): string | undefined {\n return this.config.mentraOSWebsocketUrl\n }\n\n public getHttpsServerUrl(): string | undefined {\n if (!this.config.mentraOSWebsocketUrl) {\n return undefined\n }\n return AppSession.convertToHttps(this.config.mentraOSWebsocketUrl)\n }\n\n private static convertToHttps(rawUrl: string | undefined): string {\n if (!rawUrl) return \"\"\n // Remove ws:// or wss://\n let url = rawUrl.replace(/^wss?:\\/\\//, \"\")\n // Remove trailing /app-ws\n url = url.replace(/\\/app-ws$/, \"\")\n // Prepend https://\n return `https://${url}`\n }\n\n /**\n * 🔍 Get default settings from the App configuration\n * @returns Array of settings with default values\n * @throws Error if configuration is not loaded\n */\n getDefaultSettings(): AppSettings {\n if (!this.appConfig) {\n throw new Error(\"App configuration not loaded. Call loadConfigFromJson first.\")\n }\n\n return this.appConfig.settings\n .filter((s: AppSetting | {type: \"group\"; title: string}): s is AppSetting => s.type !== \"group\")\n .map((s: AppSetting) => ({\n ...s,\n value: s.defaultValue, // Set value to defaultValue\n }))\n }\n\n /**\n * 🔍 Get setting schema from configuration\n * @param key Setting key to look up\n * @returns The setting schema or undefined if not found\n */\n getSettingSchema(key: string): AppSetting | undefined {\n if (!this.appConfig) return undefined\n\n const setting = this.appConfig.settings.find(\n (s: AppSetting | {type: \"group\"; title: string}) => s.type !== \"group\" && \"key\" in s && s.key === key,\n )\n\n return setting as AppSetting | undefined\n }\n\n /**\n * 📡 Get WiFi connection status of glasses\n * @returns WiFi status object or null if glasses don't support WiFi or status not available\n */\n getWifiStatus(): {connected: boolean; ssid?: string | null} | null {\n if (!this.capabilities?.hasWifi) {\n return null\n }\n return this.glassesConnectionState?.wifi || null\n }\n\n /**\n * ✅ Check if glasses are connected to WiFi\n * @returns true if connected to WiFi, false otherwise\n */\n isWifiConnected(): boolean {\n return this.getWifiStatus()?.connected === true\n }\n\n /**\n * 🌐 Request WiFi setup from mobile app\n * Triggers a popup on the mobile app that allows user to set up WiFi on glasses\n * @param reason Optional reason message to display to the user\n */\n requestWifiSetup(reason?: string): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n throw new Error(\"Not connected to MentraOS Cloud\")\n }\n\n const message: RequestWifiSetup = {\n type: AppToCloudMessageType.REQUEST_WIFI_SETUP,\n packageName: this.config.packageName,\n sessionId: this.sessionId || \"\",\n reason,\n timestamp: new Date(),\n }\n\n this.send(message)\n }\n\n /**\n * 👂 Listen for glasses connection state changes (includes WiFi status)\n * @param handler Callback function to handle connection state updates\n * @returns Cleanup function to remove the listener\n */\n onGlassesConnectionState(handler: (state: any) => void): () => void {\n return this.events.on(StreamType.GLASSES_CONNECTION_STATE, handler)\n }\n\n // =====================================\n // 🔧 Private Methods\n // =====================================\n\n /**\n * 📨 Handle incoming messages from cloud\n */\n private handleMessage(message: CloudToAppMessage): void {\n try {\n // Validate message before processing\n if (!this.validateMessage(message)) {\n this.events.emit(\"error\", new Error(\"Invalid message format received\"))\n return\n }\n\n // Handle binary data (audio or video)\n if (message instanceof ArrayBuffer) {\n this.handleBinaryMessage(message)\n return\n }\n\n // Using type guards to determine message type and safely handle each case\n try {\n if (isAppConnectionAck(message)) {\n // Get settings from connection acknowledgment\n const receivedSettings = message.settings || []\n this.settingsData = receivedSettings\n\n // Store config if provided\n if (message.config && validateAppConfig(message.config)) {\n this.appConfig = message.config\n }\n\n // Use default settings from config if no settings were provided\n if (receivedSettings.length === 0 && this.appConfig) {\n try {\n this.settingsData = this.getDefaultSettings()\n } catch (error) {\n this.logger.warn(error, \"Failed to load default settings from config:\")\n }\n }\n\n // Update the settings manager with the new settings\n this.settings.updateSettings(this.settingsData)\n\n // Handle MentraOS system settings if provided\n this.logger.debug(\n {mentraosSettings: JSON.stringify(message.mentraosSettings)},\n `[AppSession] CONNECTION_ACK mentraosSettings}`,\n )\n if (message.mentraosSettings) {\n this.logger.info(\n {mentraosSettings: JSON.stringify(message.mentraosSettings)},\n `[AppSession] Calling updatementraosSettings with`,\n )\n this.settings.updateMentraosSettings(message.mentraosSettings)\n } else {\n this.logger.warn(`[AppSession] CONNECTION_ACK message missing mentraosSettings field`)\n }\n\n // Handle device capabilities if provided\n if (message.capabilities) {\n this.capabilities = message.capabilities\n this.logger.info(`[AppSession] Device capabilities loaded for model: ${message.capabilities.modelName}`)\n } else {\n this.logger.debug(`[AppSession] No capabilities provided in CONNECTION_ACK`)\n }\n\n // Emit connected event with settings\n this.events.emit(\"connected\", this.settingsData)\n\n // Update subscriptions (normal flow)\n this.updateSubscriptions()\n\n // If settings-based subscriptions are enabled, update those too\n if (this.shouldUpdateSubscriptionsOnSettingsChange && this.settingsData.length > 0) {\n this.updateSubscriptionsFromSettings()\n }\n } else if (isAppConnectionError(message) || message.type === \"connection_error\") {\n // Handle both App-specific connection_error and standard connection_error\n const errorMessage = message.message || \"Unknown connection error\"\n this.events.emit(\"error\", new Error(errorMessage))\n } else if (message.type === StreamType.AUDIO_CHUNK) {\n if (this.subscriptions.has(StreamType.AUDIO_CHUNK)) {\n // Only process if we're subscribed to avoid unnecessary processing\n this.events.emit(StreamType.AUDIO_CHUNK, message)\n }\n } else if (isDataStream(message) && message.streamType === StreamType.GLASSES_CONNECTION_STATE) {\n // Store latest glasses connection state (includes WiFi info)\n this.glassesConnectionState = message.data\n\n // Emit to subscribed listeners\n if (this.subscriptions.has(StreamType.GLASSES_CONNECTION_STATE)) {\n const sanitizedData = this.sanitizeEventData(\n StreamType.GLASSES_CONNECTION_STATE,\n message.data,\n ) as EventData<typeof StreamType.GLASSES_CONNECTION_STATE>\n this.events.emit(StreamType.GLASSES_CONNECTION_STATE, sanitizedData)\n }\n } else if (isDataStream(message)) {\n // Ensure streamType exists before emitting the event\n const messageStreamType = message.streamType as ExtendedStreamType\n // if (message.streamType === StreamType.TRANSCRIPTION) {\n // const transcriptionData = message.data as TranscriptionData;\n // if (transcriptionData.transcribeLanguage) {\n // messageStreamType = createTranscriptionStream(transcriptionData.transcribeLanguage) as ExtendedStreamType;\n // }\n // } else if (message.streamType === StreamType.TRANSLATION) {\n // const translationData = message.data as TranslationData;\n // if (translationData.transcribeLanguage && translationData.translateLanguage) {\n // messageStreamType = createTranslationStream(translationData.transcribeLanguage, translationData.translateLanguage) as ExtendedStreamType;\n // }\n // }\n\n if (messageStreamType && this.subscriptions.has(messageStreamType)) {\n const sanitizedData = this.sanitizeEventData(messageStreamType, message.data) as EventData<\n typeof messageStreamType\n >\n this.events.emit(messageStreamType, sanitizedData)\n }\n } else if (isRtmpStreamStatus(message)) {\n // Emit as a standard stream event if subscribed\n if (this.subscriptions.has(StreamType.RTMP_STREAM_STATUS)) {\n this.events.emit(StreamType.RTMP_STREAM_STATUS, message)\n }\n\n // Update camera module's internal stream state\n this.camera.updateStreamState(message)\n } else if (isManagedStreamStatus(message)) {\n // Emit as a standard stream event if subscribed\n if (this.subscriptions.has(StreamType.MANAGED_STREAM_STATUS)) {\n this.events.emit(StreamType.MANAGED_STREAM_STATUS, message)\n }\n\n // Update camera module's managed stream state\n this.camera.handleManagedStreamStatus(message)\n } else if (isStreamStatusCheckResponse(message)) {\n // Handle stream status check response\n // This is a direct response, not a subscription-based event\n this.camera.handleStreamCheckResponse(message)\n } else if (isSettingsUpdate(message)) {\n // Store previous settings to check for changes\n const _prevSettings = [...this.settingsData]\n\n // Update internal settings storage\n this.settingsData = message.settings || []\n\n // Update the settings manager with the new settings\n const changes = this.settings.updateSettings(this.settingsData)\n\n // Emit settings update event (for backwards compatibility)\n this.events.emit(\"settings_update\", this.settingsData)\n\n // --- MentraOS settings update logic ---\n // If the message.settings looks like MentraOS settings (object with known keys), update mentraosSettings\n if (message.settings && typeof message.settings === \"object\") {\n this.settings.updateMentraosSettings(message.settings)\n }\n\n // Check if we should update subscriptions\n if (this.shouldUpdateSubscriptionsOnSettingsChange) {\n // Check if any subscription trigger settings changed\n const shouldUpdateSubs = this.subscriptionUpdateTriggers.some((key) => {\n return key in changes\n })\n\n if (shouldUpdateSubs) {\n this.updateSubscriptionsFromSettings()\n }\n }\n } else if (isCapabilitiesUpdate(message)) {\n // Update device capabilities\n const capabilitiesMessage = message as CapabilitiesUpdate\n this.capabilities = capabilitiesMessage.capabilities\n this.logger.info(\n capabilitiesMessage.capabilities,\n `[AppSession] Capabilities updated for model: ${capabilitiesMessage.modelName}`,\n )\n\n // Emit capabilities update event for applications to handle\n this.events.emit(\"capabilities_update\", {\n capabilities: capabilitiesMessage.capabilities,\n modelName: capabilitiesMessage.modelName,\n timestamp: capabilitiesMessage.timestamp,\n })\n } else if (isAppStopped(message)) {\n const reason = message.reason || \"unknown\"\n const displayReason = `App stopped: ${reason}`\n\n // Don't emit disconnected event here - let the WebSocket close handler do it\n // This prevents duplicate disconnected events when the session is disposed\n this.logger.info(`📤 [${this.config.packageName}] Received APP_STOPPED message: ${displayReason}`)\n\n // Clear reconnection state\n this.reconnectAttempts = 0\n }\n // Handle dashboard mode changes\n else if (isDashboardModeChanged(message)) {\n try {\n // Use proper type\n const mode = message.mode || \"none\"\n\n // Update dashboard state in the API\n if (this.dashboard && \"content\" in this.dashboard) {\n ;(this.dashboard.content as any).setCurrentMode(mode)\n }\n } catch (error) {\n this.logger.error(error, \"Error handling dashboard mode change\")\n }\n }\n // Handle always-on dashboard state changes\n else if (isDashboardAlwaysOnChanged(message)) {\n try {\n // Use proper type\n const enabled = !!message.enabled\n\n // Update dashboard state in the API\n if (this.dashboard && \"content\" in this.dashboard) {\n ;(this.dashboard.content as any).setAlwaysOnEnabled(enabled)\n }\n } catch (error) {\n this.logger.error(error, \"Error handling dashboard always-on change\")\n }\n }\n // Handle custom messages\n else if (message.type === CloudToAppMessageType.CUSTOM_MESSAGE) {\n this.events.emit(\"custom_message\", message)\n return\n }\n // Handle App-to-App communication messages\n else if ((message as any).type === \"app_message_received\") {\n this.appEvents.emit(\"app_message_received\", message as any)\n } else if ((message as any).type === \"app_user_joined\") {\n this.appEvents.emit(\"app_user_joined\", message as any)\n } else if ((message as any).type === \"app_user_left\") {\n this.appEvents.emit(\"app_user_left\", message as any)\n } else if ((message as any).type === \"app_room_updated\") {\n this.appEvents.emit(\"app_room_updated\", message as any)\n } else if ((message as any).type === \"app_direct_message_response\") {\n const response = message as any\n if (response.messageId && this.pendingDirectMessages.has(response.messageId)) {\n const {resolve} = this.pendingDirectMessages.get(response.messageId)!\n resolve(response.success)\n this.pendingDirectMessages.delete(response.messageId)\n }\n } else if (message.type === \"augmentos_settings_update\") {\n const mentraosMsg = message as MentraosSettingsUpdate\n if (mentraosMsg.settings && typeof mentraosMsg.settings === \"object\") {\n this.settings.updateMentraosSettings(mentraosMsg.settings)\n }\n }\n // Handle 'connection_error' as a specific case if cloud sends this string literal\n else if ((message as any).type === \"connection_error\") {\n // Treat 'connection_error' (string literal) like AppConnectionError\n // This handles cases where the cloud might send the type as a direct string\n // instead of the enum's 'tpa_connection_error' value.\n const errorMessage = (message as any).message || \"Unknown connection error (type: connection_error)\"\n this.logger.warn(\n `Received 'connection_error' type directly. Consider aligning cloud to send 'tpa_connection_error'. Message: ${errorMessage}`,\n )\n this.events.emit(\"error\", new Error(errorMessage))\n } else if (message.type === \"permission_error\") {\n // Handle permission errors from cloud\n this.logger.warn(\n {\n message: message.message,\n details: message.details,\n detailsCount: message.details?.length || 0,\n rejectedStreams: message.details?.map((d) => d.stream) || [],\n },\n \"Permission error received:\",\n )\n\n // Emit permission error event for application handling\n this.events.emit(\"permission_error\", {\n message: message.message,\n details: message.details,\n timestamp: message.timestamp,\n })\n\n // Optionally emit individual permission denied events for each stream\n message.details?.forEach((detail) => {\n this.events.emit(\"permission_denied\", {\n stream: detail.stream,\n requiredPermission: detail.requiredPermission,\n message: detail.message,\n })\n })\n } else if (isAudioPlayResponse(message)) {\n // Delegate audio play response handling to the audio module\n if (this.audio) {\n this.audio.handleAudioPlayResponse(message as AudioPlayResponse)\n }\n } else if (isPhotoResponse(message)) {\n // Legacy photo response handling - now photos come directly via webhook\n // This branch can be removed in the future as all photos now go through /photo-upload\n this.logger.warn(\n {message},\n \"Received legacy photo response - photos should now come via /photo-upload webhook\",\n )\n } else if (isRgbLedControlResponse(message)) {\n // LED control responses are no longer handled - fire-and-forget mode\n this.logger.debug({message}, \"Received LED control response (ignored - fire-and-forget mode)\")\n }\n // Handle unrecognized message types gracefully\n else {\n this.logger.warn(`Unrecognized message type: ${(message as any).type}`)\n this.events.emit(\"error\", new Error(`Unrecognized message type: ${(message as any).type}`))\n }\n } catch (processingError: unknown) {\n // Catch any errors during message processing to prevent App crashes\n this.logger.error(processingError, \"Error processing message:\")\n const errorMessage = processingError instanceof Error ? processingError.message : String(processingError)\n this.events.emit(\"error\", new Error(`Error processing message: ${errorMessage}`))\n }\n } catch (error: unknown) {\n // Final safety net to ensure the App doesn't crash on any unexpected errors\n this.logger.error(error, \"Unexpected error in message handler\")\n const errorMessage = error instanceof Error ? error.message : String(error)\n this.events.emit(\"error\", new Error(`Unexpected error in message handler: ${errorMessage}`))\n }\n }\n\n /**\n * 🧪 Validate incoming message structure\n * @param message - Message to validate\n * @returns boolean indicating if the message is valid\n */\n private validateMessage(message: CloudToAppMessage): boolean {\n // Handle ArrayBuffer case separately\n if (message instanceof ArrayBuffer) {\n return true // ArrayBuffers are always considered valid at this level\n }\n\n // Check if message is null or undefined\n if (!message) {\n return false\n }\n\n // Check if message has a type property\n if (!(\"type\" in message)) {\n return false\n }\n\n // All other message types should be objects with a type property\n return true\n }\n\n /**\n * 📦 Handle binary message data (audio or video)\n * @param buffer - Binary data as ArrayBuffer\n */\n private handleBinaryMessage(buffer: ArrayBuffer): void {\n try {\n // Safety check - only process if we're subscribed to avoid unnecessary work\n if (!this.subscriptions.has(StreamType.AUDIO_CHUNK)) {\n return\n }\n\n // Validate buffer has content before processing\n if (!buffer || buffer.byteLength === 0) {\n this.events.emit(\"error\", new Error(\"Received empty binary message\"))\n return\n }\n\n // Create a safety wrapped audio chunk with proper defaults\n const audioChunk: AudioChunk = {\n type: StreamType.AUDIO_CHUNK,\n timestamp: new Date(),\n arrayBuffer: buffer,\n sampleRate: 16000, // Default sample rate\n }\n\n // Emit to subscribers\n this.events.emit(StreamType.AUDIO_CHUNK, audioChunk)\n } catch (error: unknown) {\n this.logger.error(error, \"Error processing binary message\")\n const errorMessage = error instanceof Error ? error.message : String(error)\n this.events.emit(\"error\", new Error(`Error processing binary message: ${errorMessage}`))\n }\n }\n\n /**\n * 🧹 Sanitize event data to prevent crashes from malformed data\n * @param streamType - The type of stream data\n * @param data - The potentially unsafe data to sanitize\n * @returns Sanitized data safe for processing\n */\n private sanitizeEventData(streamType: ExtendedStreamType, data: unknown): any {\n try {\n // If data is null or undefined, return an empty object to prevent crashes\n if (data === null || data === undefined) {\n return {}\n }\n\n // For specific stream types, perform targeted sanitization\n switch (streamType) {\n case StreamType.TRANSCRIPTION: {\n // Ensure text field exists and is a string\n if (typeof (data as TranscriptionData).text !== \"string\") {\n return {\n text: \"\",\n isFinal: true,\n startTime: Date.now(),\n endTime: Date.now(),\n }\n }\n break\n }\n\n case StreamType.HEAD_POSITION: {\n // Ensure position data has required numeric fields\n // Handle HeadPosition - Note the property position instead of x,y,z\n const pos = data as any\n if (typeof pos?.position !== \"string\") {\n return {position: \"up\", timestamp: new Date()}\n }\n break\n }\n\n case StreamType.BUTTON_PRESS: {\n // Ensure button type is valid\n const btn = data as any\n if (!btn.buttonId || !btn.pressType) {\n return {\n buttonId: \"unknown\",\n pressType: \"short\",\n timestamp: new Date(),\n }\n }\n break\n }\n }\n\n return data\n } catch (error: unknown) {\n this.logger.error(error, `Error sanitizing ${streamType} data`)\n // Return a safe empty object if something goes wrong\n return {}\n }\n }\n\n /**\n * 🔐 Send connection initialization message\n */\n private sendConnectionInit(): void {\n const message: AppConnectionInit = {\n type: AppToCloudMessageType.CONNECTION_INIT,\n sessionId: this.sessionId!,\n packageName: this.config.packageName,\n apiKey: this.config.apiKey,\n timestamp: new Date(),\n }\n this.send(message)\n }\n\n /**\n * 📝 Update subscription list with cloud\n */\n private updateSubscriptions(): void {\n this.logger.info(\n {subscriptions: JSON.stringify(Array.from(this.subscriptions))},\n `[AppSession] updateSubscriptions: sending subscriptions to cloud`,\n )\n\n // [MODIFIED] builds the array of SubscriptionRequest objects to send to the cloud\n const subscriptionPayload: SubscriptionRequest[] = Array.from(this.subscriptions).map((stream) => {\n const rate = this.streamRates.get(stream)\n if (rate && stream === StreamType.LOCATION_STREAM) {\n return {stream: \"location_stream\", rate: rate as any}\n }\n return stream\n })\n\n const message: AppSubscriptionUpdate = {\n type: AppToCloudMessageType.SUBSCRIPTION_UPDATE,\n packageName: this.config.packageName,\n subscriptions: subscriptionPayload, // [MODIFIED]\n sessionId: this.sessionId!,\n timestamp: new Date(),\n }\n this.send(message)\n }\n\n /**\n * 🔄 Handle reconnection with exponential backoff\n */\n private async handleReconnection(): Promise<void> {\n // Check if reconnection is allowed\n if (!this.config.autoReconnect || !this.sessionId) {\n this.logger.debug(\n `🔄 Reconnection skipped: autoReconnect=${this.config.autoReconnect}, sessionId=${\n this.sessionId ? \"valid\" : \"invalid\"\n }`,\n )\n return\n }\n\n // Check if we've exceeded the maximum attempts\n const maxAttempts = this.config.maxReconnectAttempts || 3\n if (this.reconnectAttempts >= maxAttempts) {\n this.logger.info(`🔄 Maximum reconnection attempts (${maxAttempts}) reached, giving up`)\n\n // Emit a permanent disconnection event to trigger onStop in the App server\n this.events.emit(\"disconnected\", {\n message: `Connection permanently lost after ${maxAttempts} failed reconnection attempts`,\n code: 4000, // Custom code for max reconnection attempts exhausted\n reason: \"Maximum reconnection attempts exceeded\",\n wasClean: false,\n permanent: true, // Flag this as a permanent disconnection\n })\n\n return\n }\n\n // Calculate delay with exponential backoff\n const baseDelay = this.config.reconnectDelay || 1000\n const delay = baseDelay * Math.pow(2, this.reconnectAttempts)\n this.reconnectAttempts++\n\n this.logger.debug(\n `🔄 [${this.config.packageName}] Reconnection attempt ${this.reconnectAttempts}/${maxAttempts} in ${delay}ms`,\n )\n\n // Use the resource tracker for the timeout\n await new Promise<void>((resolve) => {\n this.resources.setTimeout(() => resolve(), delay)\n })\n\n try {\n this.logger.debug(`🔄 [${this.config.packageName}] Attempting to reconnect...`)\n await this.connect(this.sessionId)\n this.logger.debug(`✅ [${this.config.packageName}] Reconnection successful!`)\n this.reconnectAttempts = 0\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n this.logger.error(error, `❌ [${this.config.packageName}] Reconnection failed for user ${this.userId}`)\n this.events.emit(\"error\", new Error(`Reconnection failed: ${errorMessage}`))\n\n // Check if this was the last attempt\n if (this.reconnectAttempts >= maxAttempts) {\n this.logger.debug(\n `🔄 [${this.config.packageName}] Final reconnection attempt failed, emitting permanent disconnection`,\n )\n\n // Emit permanent disconnection event after the last failed attempt\n this.events.emit(\"disconnected\", {\n message: `Connection permanently lost after ${maxAttempts} failed reconnection attempts`,\n code: 4000, // Custom code for max reconnection attempts exhausted\n reason: \"Maximum reconnection attempts exceeded\",\n wasClean: false,\n permanent: true, // Flag this as a permanent disconnection\n })\n }\n }\n }\n\n /**\n * 📤 Public API for modules to send messages\n * Always uses current WebSocket connection\n */\n public sendMessage(message: AppToCloudMessage): void {\n return this.send(message)\n }\n\n /**\n * 📤 Send message to cloud with validation and error handling\n * @throws {Error} If WebSocket is not connected\n */\n private send(message: AppToCloudMessage): void {\n try {\n // Verify WebSocket connection is valid\n if (!this.ws) {\n throw new Error(\"WebSocket connection not established\")\n }\n\n if (this.ws.readyState !== 1) {\n const stateMap: Record<number, string> = {\n 0: \"CONNECTING\",\n 1: \"OPEN\",\n 2: \"CLOSING\",\n 3: \"CLOSED\",\n }\n const stateName = stateMap[this.ws.readyState] || \"UNKNOWN\"\n throw new Error(`WebSocket not connected (current state: ${stateName})`)\n }\n\n // Validate message before sending\n if (!message || typeof message !== \"object\") {\n throw new Error(\"Invalid message: must be an object\")\n }\n\n if (!(\"type\" in message)) {\n throw new Error('Invalid message: missing \"type\" property')\n }\n\n // Ensure message format is consistent\n if (!(\"timestamp\" in message) || !(message.timestamp instanceof Date)) {\n message.timestamp = new Date()\n }\n\n // Try to send with error handling\n try {\n const serializedMessage = JSON.stringify(message)\n this.ws.send(serializedMessage)\n } catch (sendError: unknown) {\n const errorMessage = sendError instanceof Error ? sendError.message : String(sendError)\n throw new Error(`Failed to send message: ${errorMessage}`)\n }\n } catch (error: unknown) {\n // Log the error and emit an event so App developers are aware\n this.logger.error(error, \"Message send error\")\n\n // Ensure we always emit an Error object\n if (error instanceof Error) {\n this.events.emit(\"error\", error)\n } else {\n this.events.emit(\"error\", new Error(String(error)))\n }\n\n // Re-throw to maintain the original function behavior\n throw error\n }\n }\n\n /**\n * Fetch the onboarding instructions for this session from the backend.\n * @returns Promise resolving to the instructions string or null\n */\n public async getInstructions(): Promise<string | null> {\n try {\n const baseUrl = this.getServerUrl()\n const response = await axios.get(`${baseUrl}/api/instructions`, {\n params: {userId: this.userId},\n })\n return response.data.instructions || null\n } catch (err) {\n this.logger.error(err, `Error fetching instructions from backend`)\n return null\n }\n }\n // =====================================\n // 👥 App-to-App Communication Interface\n // =====================================\n\n /**\n * 👥 Discover other users currently using the same App\n * @param includeProfiles - Whether to include user profile information\n * @returns Promise that resolves with list of active users\n */\n async discoverAppUsers(domain: string, includeProfiles = false): Promise<any> {\n // Use the domain argument as the base URL if provided\n if (!domain) {\n throw new Error(\"Domain (API base URL) is required for user discovery\")\n }\n const url = `${domain}/api/app-communication/discover-users`\n // Use the user's core token for authentication\n const appApiKey = this.config.apiKey // This may need to be updated if you store the core token elsewhere\n\n if (!appApiKey) {\n throw new Error(\"Core token (apiKey) is required for user discovery\")\n }\n const body = {\n packageName: this.config.packageName,\n userId: this.userId,\n includeUserProfiles: includeProfiles,\n }\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Authorization\": `Bearer ${appApiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n })\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(`Failed to discover users: ${response.status} ${response.statusText} - ${errorText}`)\n }\n return await response.json()\n }\n\n /**\n * 🔍 Check if a specific user is currently active\n * @param userId - User ID to check for\n * @returns Promise that resolves with boolean indicating if user is active\n */\n async isUserActive(userId: string): Promise<boolean> {\n try {\n const userList = await this.discoverAppUsers(\"\", false)\n return userList.users.some((user: any) => user.userId === userId)\n } catch (error) {\n this.logger.error({error, userId}, \"Error checking if user is active\")\n return false\n }\n }\n\n /**\n * 📊 Get user count for this App\n * @returns Promise that resolves with number of active users\n */\n async getUserCount(domain: string): Promise<number> {\n try {\n const userList = await this.discoverAppUsers(domain, false)\n return userList.totalUsers\n } catch (error) {\n this.logger.error(error, \"Error getting user count\")\n return 0\n }\n }\n\n /**\n * 📢 Send broadcast message to all users with same App active\n * @param payload - Message payload to send\n * @param roomId - Optional room ID for room-based messaging\n * @returns Promise that resolves when message is sent\n */\n async broadcastToAppUsers(payload: any, _roomId?: string): Promise<void> {\n try {\n const messageId = this.generateMessageId()\n\n const message = {\n type: \"app_broadcast_message\",\n packageName: this.config.packageName,\n sessionId: this.sessionId!,\n payload,\n messageId,\n senderUserId: this.userId,\n timestamp: new Date(),\n }\n\n this.send(message as any)\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n throw new Error(`Failed to broadcast message: ${errorMessage}`)\n }\n }\n\n /**\n * 📤 Send direct message to specific user\n * @param targetUserId - User ID to send message to\n * @param payload - Message payload to send\n * @returns Promise that resolves with success status\n */\n async sendDirectMessage(targetUserId: string, payload: any): Promise<boolean> {\n return new Promise((resolve, reject) => {\n try {\n const messageId = this.generateMessageId()\n\n // Store promise resolver\n this.pendingDirectMessages.set(messageId, {resolve, reject})\n\n const message = {\n type: \"app_direct_message\",\n packageName: this.config.packageName,\n sessionId: this.sessionId!,\n targetUserId,\n payload,\n messageId,\n senderUserId: this.userId,\n timestamp: new Date(),\n }\n\n this.send(message as any)\n\n // Set timeout to avoid hanging promises\n const timeoutMs = 15000 // 15 seconds\n this.resources.setTimeout(() => {\n if (this.pendingDirectMessages.has(messageId)) {\n this.pendingDirectMessages.get(messageId)!.reject(new Error(\"Direct message timed out\"))\n this.pendingDirectMessages.delete(messageId)\n }\n }, timeoutMs)\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n reject(new Error(`Failed to send direct message: ${errorMessage}`))\n }\n })\n }\n\n /**\n * 🏠 Join a communication room for group messaging\n * @param roomId - Room ID to join\n * @param roomConfig - Optional room configuration\n * @returns Promise that resolves when room is joined\n */\n async joinAppRoom(\n roomId: string,\n roomConfig?: {\n maxUsers?: number\n isPrivate?: boolean\n metadata?: any\n },\n ): Promise<void> {\n try {\n const message = {\n type: \"app_room_join\",\n packageName: this.config.packageName,\n sessionId: this.sessionId!,\n roomId,\n roomConfig,\n timestamp: new Date(),\n }\n\n this.send(message as any)\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n throw new Error(`Failed to join room: ${errorMessage}`)\n }\n }\n\n /**\n * 🚪 Leave a communication room\n * @param roomId - Room ID to leave\n * @returns Promise that resolves when room is left\n */\n async leaveAppRoom(roomId: string): Promise<void> {\n try {\n const message = {\n type: \"app_room_leave\",\n packageName: this.config.packageName,\n sessionId: this.sessionId!,\n roomId,\n timestamp: new Date(),\n }\n\n this.send(message as any)\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n throw new Error(`Failed to leave room: ${errorMessage}`)\n }\n }\n\n /**\n * 📨 Listen for messages from other App users\n * @param handler - Function to handle incoming messages\n * @returns Cleanup function to remove the handler\n */\n onAppMessage(handler: (message: any) => void): () => void {\n this.appEvents.on(\"app_message_received\", handler)\n return () => this.appEvents.off(\"app_message_received\", handler)\n }\n\n /**\n * 👋 Listen for user join events\n * @param handler - Function to handle user join events\n * @returns Cleanup function to remove the handler\n */\n onAppUserJoined(handler: (data: any) => void): () => void {\n this.appEvents.on(\"app_user_joined\", handler)\n return () => this.appEvents.off(\"app_user_joined\", handler)\n }\n\n /**\n * 🚪 Listen for user leave events\n * @param handler - Function to handle user leave events\n * @returns Cleanup function to remove the handler\n */\n onAppUserLeft(handler: (data: any) => void): () => void {\n this.appEvents.on(\"app_user_left\", handler)\n return () => this.appEvents.off(\"app_user_left\", handler)\n }\n\n /**\n * 🏠 Listen for room update events\n * @param handler - Function to handle room updates\n * @returns Cleanup function to remove the handler\n */\n onAppRoomUpdated(handler: (data: any) => void): () => void {\n this.appEvents.on(\"app_room_updated\", handler)\n return () => this.appEvents.off(\"app_room_updated\", handler)\n }\n\n /**\n * 🔧 Generate unique message ID\n * @returns Unique message identifier\n */\n private generateMessageId(): string {\n return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`\n }\n}\n\n/**\n * @deprecated Use `AppSessionConfig` instead. `TpaSessionConfig` is deprecated and will be removed in a future version.\n * This is an alias for backward compatibility only.\n *\n * @example\n * ```typescript\n * // ❌ Deprecated - Don't use this\n * const config: TpaSessionConfig = { ... };\n *\n * // ✅ Use this instead\n * const config: AppSessionConfig = { ... };\n * ```\n */\nexport type TpaSessionConfig = AppSessionConfig\n\n/**\n * @deprecated Use `AppSession` instead. `TpaSession` is deprecated and will be removed in a future version.\n * This is an alias for backward compatibility only.\n *\n * @example\n * ```typescript\n * // ❌ Deprecated - Don't use this\n * const session = new TpaSession(config);\n *\n * // ✅ Use this instead\n * const session = new AppSession(config);\n * ```\n */\nexport class TpaSession extends AppSession {\n constructor(config: TpaSessionConfig) {\n super(config)\n // Emit a deprecation warning to help developers migrate\n console.warn(\n \"⚠️ DEPRECATION WARNING: TpaSession is deprecated and will be removed in a future version. \" +\n \"Please use AppSession instead. \" +\n 'Simply replace \"TpaSession\" with \"AppSession\" in your code.',\n )\n }\n}\n\n// Export module types for developers\nexport {CameraModule, PhotoRequestOptions, RtmpStreamOptions} from \"./modules/camera\"\nexport {LedModule, LedControlOptions} from \"./modules/led\"\nexport {AudioManager, AudioPlayOptions, AudioPlayResult, SpeakOptions} from \"./modules/audio\"\nexport {SimpleStorage} from \"./modules/simple-storage\"\n",
22
- "/**\n * 🎮 Event Manager Module\n */\nimport EventEmitter from \"events\"\nimport {\n StreamType,\n ExtendedStreamType,\n AppSettings,\n WebSocketError,\n // Event data types\n ButtonPress,\n HeadPosition,\n PhoneNotification,\n TranscriptionData,\n TranslationData,\n GlassesBatteryUpdate,\n PhoneBatteryUpdate,\n GlassesConnectionState,\n LocationUpdate,\n Vad,\n AudioChunk,\n CalendarEvent,\n VpsCoordinates,\n // Language stream helpers\n createTranscriptionStream,\n isValidLanguageCode,\n createTranslationStream,\n CustomMessage,\n RtmpStreamStatus,\n PhotoTaken,\n ManagedStreamStatus,\n PhoneNotificationDismissed,\n Capabilities,\n TouchEvent,\n createTouchEventStream,\n} from \"../../types\"\nimport {DashboardMode} from \"../../types/dashboard\"\nimport {PermissionErrorDetail} from \"../../types/messages/cloud-to-app\"\nimport {calendarWarnLog, microPhoneWarnLog} from \"../../utils/permissions-utils\"\n\n/** 🎯 Type-safe event handler function */\ntype Handler<T> = (data: T) => void\n\n/** 🔄 System events not tied to streams */\ninterface SystemEvents {\n connected: AppSettings | undefined\n disconnected:\n | string\n | {\n message: string // Human-readable close message\n code: number // WebSocket close code (1000 = normal)\n reason: string // Reason provided by server\n wasClean: boolean // Whether this was a clean closure\n permanent?: boolean // Whether this is a permanent disconnection (no more reconnection attempts)\n sessionEnded?: boolean // Whether this disconnection is due to user session ending\n }\n error: WebSocketError | Error\n settings_update: AppSettings\n capabilities_update: {\n capabilities: Capabilities | null\n modelName: string | null\n timestamp?: Date\n }\n dashboard_mode_change: {mode: DashboardMode | \"none\"}\n dashboard_always_on_change: {enabled: boolean}\n custom_message: CustomMessage\n permission_error: {\n message: string\n details: PermissionErrorDetail[]\n timestamp?: Date\n }\n permission_denied: {\n stream: string\n requiredPermission: string\n message: string\n }\n}\n\n/** 📡 All possible event types */\ntype EventType = ExtendedStreamType | keyof SystemEvents\n\n/** 📦 Map of stream types to their data types */\nexport interface StreamDataTypes {\n [StreamType.BUTTON_PRESS]: ButtonPress\n [StreamType.HEAD_POSITION]: HeadPosition\n [StreamType.PHONE_NOTIFICATION]: PhoneNotification\n [StreamType.TRANSCRIPTION]: TranscriptionData\n [StreamType.TRANSLATION]: TranslationData\n [StreamType.GLASSES_BATTERY_UPDATE]: GlassesBatteryUpdate\n [StreamType.PHONE_BATTERY_UPDATE]: PhoneBatteryUpdate\n [StreamType.GLASSES_CONNECTION_STATE]: GlassesConnectionState\n [StreamType.LOCATION_UPDATE]: LocationUpdate\n [StreamType.CALENDAR_EVENT]: CalendarEvent\n [StreamType.VAD]: Vad\n [StreamType.PHONE_NOTIFICATION_DISMISSED]: PhoneNotificationDismissed\n [StreamType.AUDIO_CHUNK]: AudioChunk\n [StreamType.VIDEO]: ArrayBuffer\n [StreamType.RTMP_STREAM_STATUS]: RtmpStreamStatus\n [StreamType.MANAGED_STREAM_STATUS]: ManagedStreamStatus\n [StreamType.VPS_COORDINATES]: VpsCoordinates\n [StreamType.PHOTO_TAKEN]: PhotoTaken\n [StreamType.OPEN_DASHBOARD]: never\n [StreamType.START_APP]: never\n [StreamType.STOP_APP]: never\n [StreamType.ALL]: never\n [StreamType.WILDCARD]: never\n}\n\n/** 📦 Data type for an event */\nexport type EventData<T extends EventType> = T extends keyof StreamDataTypes\n ? StreamDataTypes[T]\n : T extends keyof SystemEvents\n ? SystemEvents[T]\n : T extends string\n ? T extends `${StreamType.TRANSCRIPTION}:${string}`\n ? TranscriptionData\n : T extends `${StreamType.TRANSLATION}:${string}`\n ? TranslationData\n : never\n : never\n\nexport class EventManager {\n private emitter: EventEmitter\n private handlers: Map<EventType, Set<Handler<unknown>>>\n private lastLanguageTranscriptioCleanupHandler: () => void\n private lastLanguageTranslationCleanupHandler: () => void\n\n constructor(\n private subscribe: (type: ExtendedStreamType) => void,\n private unsubscribe: (type: ExtendedStreamType) => void,\n private packageName: string,\n private baseUrl: string,\n ) {\n this.emitter = new EventEmitter()\n this.handlers = new Map()\n this.lastLanguageTranscriptioCleanupHandler = () => {}\n this.lastLanguageTranslationCleanupHandler = () => {}\n }\n\n // Convenience handlers for common event types\n\n onTranscription(handler: Handler<TranscriptionData>) {\n // Only make the API call if we have a base URL (server-side environment)\n microPhoneWarnLog(this.baseUrl, this.packageName, this.onTranscription.name)\n\n return this.addHandler(createTranscriptionStream(\"en-US\"), handler)\n }\n\n /**\n * 🎤 Listen for transcription events in a specific language\n * @param language - Language code (e.g., \"en-US\") or \"auto\" for automatic detection\n * @param handler - Function to handle transcription data\n * @param optionsOrBoolean - Optional configuration object or boolean (backward compatible)\n * @param optionsOrBoolean.disableLanguageIdentification - Disable language identification (defaults to false/enabled)\n * @param optionsOrBoolean.hints - Array of language code hints to improve detection (e.g., [\"es\", \"fr\"])\n * @returns Cleanup function to remove the handler\n * @throws Error if language code is invalid\n */\n onTranscriptionForLanguage(\n language: string,\n handler: Handler<TranscriptionData>,\n optionsOrBoolean?:\n | boolean\n | {\n disableLanguageIdentification?: boolean\n hints?: string[]\n },\n ): () => void {\n if (language !== \"auto\" && !isValidLanguageCode(language)) {\n throw new Error(`Invalid language code: ${language}`)\n }\n this.lastLanguageTranscriptioCleanupHandler()\n\n // Handle backward compatibility: boolean or options object\n const options =\n typeof optionsOrBoolean === \"boolean\" ? {disableLanguageIdentification: optionsOrBoolean} : optionsOrBoolean\n\n const streamType = createTranscriptionStream(language, options)\n this.lastLanguageTranscriptioCleanupHandler = this.addHandler(streamType, handler)\n return this.lastLanguageTranscriptioCleanupHandler\n }\n\n /**\n * 🌐 Listen for translation events for a specific language pair\n * @param sourceLanguage - Source language code (e.g., \"es-ES\")\n * @param targetLanguage - Target language code (e.g., \"en-US\")\n * @param handler - Function to handle translation data\n * @returns Cleanup function to remove the handler\n * @throws Error if language codes are invalid\n */\n ontranslationForLanguage(\n sourceLanguage: string,\n targetLanguage: string,\n handler: Handler<TranslationData>,\n ): () => void {\n microPhoneWarnLog(this.baseUrl || \"\", this.packageName, this.ontranslationForLanguage.name)\n if (!isValidLanguageCode(sourceLanguage)) {\n throw new Error(`Invalid source language code: ${sourceLanguage}`)\n }\n if (!isValidLanguageCode(targetLanguage)) {\n throw new Error(`Invalid target language code: ${targetLanguage}`)\n }\n\n this.lastLanguageTranslationCleanupHandler()\n const streamType = createTranslationStream(sourceLanguage, targetLanguage)\n this.lastLanguageTranslationCleanupHandler = this.addHandler(streamType, handler)\n\n return this.lastLanguageTranslationCleanupHandler\n }\n\n onHeadPosition(handler: Handler<HeadPosition>) {\n return this.addHandler(StreamType.HEAD_POSITION, handler)\n }\n\n onButtonPress(handler: Handler<ButtonPress>) {\n return this.addHandler(StreamType.BUTTON_PRESS, handler)\n }\n\n onTouchEvent(gestureOrHandler: string | Handler<TouchEvent>, handler?: Handler<TouchEvent>): () => void {\n // Handle both: onTouchEvent(handler) and onTouchEvent(\"forward_swipe\", handler)\n if (typeof gestureOrHandler === \"function\") {\n // Subscribe to all touch events\n return this.addHandler(StreamType.TOUCH_EVENT, gestureOrHandler)\n } else {\n // Subscribe to specific gesture\n const gestureStream = createTouchEventStream(gestureOrHandler)\n return this.addHandler(gestureStream, handler!)\n }\n }\n\n onPhoneNotifications(handler: Handler<PhoneNotification>) {\n return this.addHandler(StreamType.PHONE_NOTIFICATION, handler)\n }\n\n onPhoneNotificationDismissed(handler: Handler<PhoneNotificationDismissed>) {\n return this.addHandler(StreamType.PHONE_NOTIFICATION_DISMISSED, handler)\n }\n\n onGlassesBattery(handler: Handler<GlassesBatteryUpdate>) {\n return this.addHandler(StreamType.GLASSES_BATTERY_UPDATE, handler)\n }\n\n onPhoneBattery(handler: Handler<PhoneBatteryUpdate>) {\n return this.addHandler(StreamType.PHONE_BATTERY_UPDATE, handler)\n }\n\n onVoiceActivity(handler: Handler<Vad>) {\n microPhoneWarnLog(this.baseUrl || \"\", this.packageName, this.onVoiceActivity.name)\n return this.addHandler(StreamType.VAD, handler)\n }\n\n onLocation(handler: Handler<LocationUpdate>) {\n return this.addHandler(StreamType.LOCATION_UPDATE, handler)\n }\n\n onCalendarEvent(handler: Handler<CalendarEvent>) {\n return this.addHandler(StreamType.CALENDAR_EVENT, handler)\n }\n\n /**\n * 🎤 Listen for audio chunk data\n * @param handler - Function to handle audio chunks\n * @returns Cleanup function to remove the handler\n */\n onAudioChunk(handler: Handler<AudioChunk>) {\n return this.addHandler(StreamType.AUDIO_CHUNK, handler)\n }\n\n // System event handlers\n\n onConnected(handler: Handler<SystemEvents[\"connected\"]>) {\n this.emitter.on(\"connected\", handler)\n return () => this.emitter.off(\"connected\", handler)\n }\n\n onDisconnected(handler: Handler<SystemEvents[\"disconnected\"]>) {\n this.emitter.on(\"disconnected\", handler)\n return () => this.emitter.off(\"disconnected\", handler)\n }\n\n onError(handler: Handler<SystemEvents[\"error\"]>) {\n this.emitter.on(\"error\", handler)\n return () => this.emitter.off(\"error\", handler)\n }\n\n onSettingsUpdate(handler: Handler<SystemEvents[\"settings_update\"]>) {\n this.emitter.on(\"settings_update\", handler)\n return () => this.emitter.off(\"settings_update\", handler)\n }\n\n /**\n * 🔧 Listen for device capabilities updates\n * @param handler - Function to handle capabilities updates\n * @returns Cleanup function to remove the handler\n */\n onCapabilitiesUpdate(handler: Handler<SystemEvents[\"capabilities_update\"]>) {\n this.emitter.on(\"capabilities_update\", handler)\n return () => this.emitter.off(\"capabilities_update\", handler)\n }\n\n /**\n * 🌐 Listen for dashboard mode changes\n * @param handler - Function to handle dashboard mode changes\n * @returns Cleanup function to remove the handler\n */\n onDashboardModeChange(handler: Handler<SystemEvents[\"dashboard_mode_change\"]>) {\n this.emitter.on(\"dashboard_mode_change\", handler)\n return () => this.emitter.off(\"dashboard_mode_change\", handler)\n }\n\n /**\n * 🌐 Listen for dashboard always-on mode changes\n * @param handler - Function to handle dashboard always-on mode changes\n * @returns Cleanup function to remove the handler\n */\n onDashboardAlwaysOnChange(handler: Handler<SystemEvents[\"dashboard_always_on_change\"]>) {\n this.emitter.on(\"dashboard_always_on_change\", handler)\n return () => this.emitter.off(\"dashboard_always_on_change\", handler)\n }\n\n /**\n * 🚫 Listen for permission errors when subscriptions are rejected\n * @param handler - Function to handle permission errors\n * @returns Cleanup function to remove the handler\n */\n onPermissionError(handler: Handler<SystemEvents[\"permission_error\"]>) {\n this.emitter.on(\"permission_error\", handler)\n return () => this.emitter.off(\"permission_error\", handler)\n }\n\n /**\n * 🚫 Listen for individual permission denied events for specific streams\n * @param handler - Function to handle permission denied events\n * @returns Cleanup function to remove the handler\n */\n onPermissionDenied(handler: Handler<SystemEvents[\"permission_denied\"]>) {\n this.emitter.on(\"permission_denied\", handler)\n return () => this.emitter.off(\"permission_denied\", handler)\n }\n\n /**\n * 🔄 Listen for changes to a specific setting\n * @param key - Setting key to monitor\n * @param handler - Function to handle setting value changes\n * @returns Cleanup function to remove the handler\n */\n onSettingChange<T>(key: string, handler: (value: T, previousValue: T | undefined) => void): () => void {\n let previousValue: T | undefined = undefined\n\n const settingsHandler = (settings: AppSettings) => {\n try {\n const setting = settings.find((s) => s.key === key)\n if (setting) {\n // Only call handler if value has changed\n if (setting.value !== previousValue) {\n const newValue = setting.value as T\n handler(newValue, previousValue)\n previousValue = newValue\n }\n }\n } catch (error: unknown) {\n console.error(`Error in onSettingChange handler for key \"${key}\":`, error)\n }\n }\n\n this.emitter.on(\"settings_update\", settingsHandler)\n this.emitter.on(\"connected\", settingsHandler) // Also check when first connected\n\n return () => {\n this.emitter.off(\"settings_update\", settingsHandler)\n this.emitter.off(\"connected\", settingsHandler)\n }\n }\n\n /**\n * 🔄 Generic event handler\n *\n * Use this for stream types without specific handler methods\n */\n on<T extends ExtendedStreamType>(type: T, handler: Handler<EventData<T>>): () => void {\n // Check permissions for specific stream types\n if (type === StreamType.CALENDAR_EVENT) {\n calendarWarnLog(this.baseUrl, this.packageName, \"on\")\n }\n return this.addHandler(type, handler)\n }\n\n /**\n * ➕ Add an event handler and subscribe if needed\n */\n private addHandler<T extends ExtendedStreamType>(type: T, handler: Handler<EventData<T>>): () => void {\n const handlers = this.handlers.get(type) ?? new Set()\n\n if (handlers.size === 0) {\n this.handlers.set(type, handlers)\n this.subscribe(type)\n }\n handlers.add(handler as Handler<unknown>)\n return () => this.removeHandler(type, handler)\n }\n\n /**\n * ➖ Remove an event handler\n */\n private removeHandler<T extends ExtendedStreamType>(type: T, handler: Handler<EventData<T>>): void {\n const handlers = this.handlers.get(type)\n if (!handlers) return\n\n handlers.delete(handler as Handler<unknown>)\n if (handlers.size === 0) {\n this.handlers.delete(type)\n this.unsubscribe(type)\n }\n }\n\n /**\n * 📡 Emit an event to all registered handlers with error isolation\n */\n emit<T extends EventType>(event: T, data: EventData<T>): void {\n try {\n // Emit to EventEmitter handlers (system events)\n // console.log(`#### Emitting to ${event}`);\n this.emitter.emit(event, data)\n\n // Emit to stream handlers if applicable\n const handlers = this.handlers.get(event)\n // console.log(`#### Handlers: ${JSON.stringify(handlers)}`);\n\n if (handlers) {\n // Create array of handlers to prevent modification during iteration\n const handlersArray = Array.from(handlers)\n // console.log(`((())) HandlersArray: ${JSON.stringify(handlersArray)}`);\n\n // Execute each handler in isolated try/catch to prevent one handler\n // from crashing the entire App\n handlersArray.forEach((handler) => {\n try {\n ;(handler as Handler<EventData<T>>)(data)\n } catch (handlerError: unknown) {\n // Log the error but don't let it propagate\n console.error(`Error in handler for event '${String(event)}':`, handlerError)\n\n // Emit an error event for tracking purposes\n if (event !== \"error\") {\n // Prevent infinite recursion\n const errorMessage = handlerError instanceof Error ? handlerError.message : String(handlerError)\n\n this.emitter.emit(\"error\", new Error(`Handler error for event '${String(event)}': ${errorMessage}`))\n }\n }\n })\n }\n } catch (emitError: unknown) {\n // Catch any errors in the emission process itself\n console.error(`Fatal error emitting event '${String(event)}':`, emitError)\n\n // Try to emit an error event if we're not already handling an error\n if (event !== \"error\") {\n try {\n const errorMessage = emitError instanceof Error ? emitError.message : String(emitError)\n\n this.emitter.emit(\"error\", new Error(`Event emission error for '${String(event)}': ${errorMessage}`))\n } catch (nestedError) {\n // If even this fails, just log it - nothing more we can do\n console.error(\"Failed to emit error event:\", nestedError)\n }\n }\n }\n }\n\n /**\n * 📨 Listen for custom messages with a specific action\n * @param action - The action identifier to filter by\n * @param handler - Function to handle the message\n * @returns Cleanup function to remove the handler\n */\n onCustomMessage(action: string, handler: (payload: any) => void): () => void {\n const messageHandler = (message: CustomMessage) => {\n if (message.action === action) {\n handler(message.payload)\n }\n }\n\n this.emitter.on(\"custom_message\", messageHandler)\n return () => this.emitter.off(\"custom_message\", messageHandler)\n }\n\n onVpsCoordinates(handler: Handler<VpsCoordinates>) {\n return this.addHandler(StreamType.VPS_COORDINATES, handler)\n }\n\n /**\n * 📸 Listen for photo responses\n * @param handler - Function to handle photo response data\n * @returns Cleanup function to remove the handler\n */\n onPhotoTaken(handler: Handler<PhotoTaken>) {\n return this.addHandler(StreamType.PHOTO_TAKEN, handler)\n }\n}\n",
23
- "// src/index.ts\n\nexport * from \"./token\"\n\n// Message type enums\nexport * from \"./message-types\"\n\n// Base message type\nexport * from \"./messages/base\"\n\n// Messages by direction - export everything except the conflicting type guards\nexport * from \"./messages/glasses-to-cloud\"\nexport * from \"./messages/cloud-to-glasses\"\n\n// Export from app-to-cloud excluding isPhotoRequest which conflicts with cloud-to-glasses\nexport {\n // Types\n SubscriptionRequest,\n AppConnectionInit,\n AppSubscriptionUpdate,\n PhotoRequest,\n RgbLedControlRequest,\n RtmpStreamRequest,\n RtmpStreamStopRequest,\n AppLocationPollRequest,\n RestreamDestination,\n ManagedStreamRequest,\n ManagedStreamStopRequest,\n StreamStatusCheckRequest,\n AudioPlayRequest,\n AudioStopRequest,\n AppToCloudMessage,\n AppBroadcastMessage,\n AppDirectMessage,\n AppUserDiscovery,\n AppRoomJoin,\n AppRoomLeave,\n RequestWifiSetup,\n // Type guards - all except isPhotoRequest\n isAppConnectionInit,\n isAppSubscriptionUpdate,\n isDisplayRequest,\n isRgbLedControlRequest,\n isAudioPlayRequest,\n isAudioStopRequest,\n isDashboardContentUpdate,\n isDashboardModeChange,\n isDashboardSystemUpdate,\n isManagedStreamRequest,\n isManagedStreamStopRequest,\n isRtmpStreamRequest,\n isRtmpStreamStopRequest,\n // Export with alias to avoid conflict\n isPhotoRequest as isPhotoRequestFromApp,\n} from \"./messages/app-to-cloud\"\n\n// Export cloud-to-app but exclude the conflicting type guards\nexport {\n // Types\n AppConnectionAck,\n AppConnectionError,\n AppStopped,\n SettingsUpdate as AppSettingsUpdate, // Alias to avoid conflict with cloud-to-glasses SettingsUpdate\n CapabilitiesUpdate,\n DataStream,\n CloudToAppMessage,\n AudioPlayResponse,\n TranslationData,\n ToolCall,\n StandardConnectionError,\n CustomMessage,\n ManagedStreamStatus,\n StreamStatusCheckResponse,\n OutputStatus,\n MentraosSettingsUpdate,\n TranscriptionData,\n TranscriptionMetadata,\n SonioxToken,\n AudioChunk,\n PermissionError,\n PermissionErrorDetail,\n // Type guards (excluding isPhotoResponse and isRtmpStreamStatus which conflict)\n isAppConnectionAck,\n isAppConnectionError,\n isAppStopped,\n isSettingsUpdate,\n isCapabilitiesUpdate,\n isDataStream,\n isAudioChunk,\n isAudioPlayResponse,\n isDashboardModeChanged,\n isDashboardAlwaysOnChanged,\n isManagedStreamStatus,\n isStreamStatusCheckResponse,\n // Re-export the cloud-to-app versions of these type guards since they're the ones\n // that should be used when dealing with CloudToAppMessage types\n isPhotoResponse as isPhotoResponseFromCloud,\n isRtmpStreamStatus as isRtmpStreamStatusFromCloud,\n isRgbLedControlResponse as isRgbLedControlResponseFromCloud,\n} from \"./messages/cloud-to-app\"\n\n// Stream types\nexport * from \"./streams\"\n\n// Layout types\nexport * from \"./layouts\"\n\n// Dashboard types\nexport * from \"./dashboard\"\n\n// RTMP streaming types\nexport * from \"./rtmp-stream\"\n\n// Other system enums\nexport * from \"./enums\"\n\n// Core model interfaces\nexport * from \"./models\"\n\n// Webhook interfaces\nexport * from \"./webhooks\"\n\n// Capability Discovery types\nexport * from \"./capabilities\"\n\n// Photo data types\nexport * from \"./photo-data\"\n\n/**\n * WebSocket error information\n */\nexport interface WebSocketError {\n code: string\n message: string\n details?: unknown\n}\n\nimport type {Request} from \"express\"\nimport type {AppSession} from \"../app/session\"\n\nexport interface AuthenticatedRequest extends Request {\n authUserId?: string\n activeSession: AppSession | null\n}\n",
20
+ "/**\n * 🚀 App Server Module\n *\n * Creates and manages a server for Apps in the MentraOS ecosystem.\n * Handles webhook endpoints, session management, and cleanup.\n */\nimport express, {type Express} from \"express\"\nimport path from \"path\"\nimport fs from \"fs\"\nimport {AppSession} from \"../session/index\"\nimport {createAuthMiddleware} from \"../webview\"\nimport {newSDKUpdate} from \"../../constants/log-messages/updates\"\n\nimport {\n WebhookRequest,\n WebhookResponse,\n SessionWebhookRequest,\n StopWebhookRequest,\n ToolCall,\n WebhookRequestType,\n} from \"../../types\"\n\nimport {Logger} from \"pino\"\nimport {logger as rootLogger} from \"../../logging/logger\"\nimport axios from \"axios\"\n\nexport const GIVE_APP_CONTROL_OF_TOOL_RESPONSE: string = \"GIVE_APP_CONTROL_OF_TOOL_RESPONSE\"\n\n/**\n * 🔧 Configuration options for App Server\n *\n * @example\n * ```typescript\n * const config: AppServerConfig = {\n * packageName: 'org.example.myapp',\n * apiKey: 'your_api_key',\n * port: 7010,\n * publicDir: './public'\n * };\n * ```\n */\nexport interface AppServerConfig {\n /** 📦 Unique identifier for your App (e.g., 'org.company.appname') must match what you specified at https://console.mentra.glass */\n packageName: string\n /** 🔑 API key for authentication with MentraOS Cloud */\n apiKey: string\n /** 🌐 Port number for the server (default: 7010) */\n port?: number\n\n /** Cloud API URL (default: 'api.mentra.glass') */\n cloudApiUrl?: string\n\n /** 🛣️ [DEPRECATED] do not set: The SDK will automatically expose an endpoint at '/webhook' */\n webhookPath?: string\n /**\n * 📂 Directory for serving static files (e.g., images, logos)\n * Set to false to disable static file serving\n */\n publicDir?: string | false\n\n /** ❤️ Enable health check endpoint at /health (default: true) */\n healthCheck?: boolean\n /**\n * 🔐 Secret key used to sign session cookies\n * This must be a strong, unique secret\n */\n cookieSecret?: string\n /** App instructions string shown to the user */\n appInstructions?: string\n}\n\n/**\n * 🎯 App Server Implementation\n *\n * Base class for creating App servers. Handles:\n * - 🔄 Session lifecycle management\n * - 📡 Webhook endpoints for MentraOS Cloud\n * - 📂 Static file serving\n * - ❤️ Health checks\n * - 🧹 Cleanup on shutdown\n *\n * @example\n * ```typescript\n * class MyAppServer extends AppServer {\n * protected async onSession(session: AppSession, sessionId: string, userId: string) {\n * // Handle new user sessions here\n * session.events.onTranscription((data) => {\n * session.layouts.showTextWall(data.text);\n * });\n * }\n * }\n *\n * const server = new MyAppServer({\n * packageName: 'org.example.myapp',\n * apiKey: 'your_api_key',\n * publicDir: \"/public\",\n * });\n *\n * await server.start();\n * ```\n */\nexport class AppServer {\n /** Express app instance */\n private app: Express\n /** Map of active user sessions by sessionId */\n private activeSessions = new Map<string, AppSession>()\n /** Map of active user sessions by userId */\n private activeSessionsByUserId = new Map<string, AppSession>()\n /** Array of cleanup handlers to run on shutdown */\n private cleanupHandlers: Array<() => void> = []\n /** App instructions string shown to the user */\n private appInstructions: string | null = null\n\n public readonly logger: Logger\n\n constructor(private config: AppServerConfig) {\n // Set defaults and merge with provided config\n this.config = {\n port: 7010,\n webhookPath: \"/webhook\",\n publicDir: false,\n healthCheck: true,\n ...config,\n }\n\n this.logger = rootLogger.child({\n app: this.config.packageName,\n packageName: this.config.packageName,\n service: \"app-server\",\n })\n\n // Initialize Express app\n this.app = express()\n this.app.use(express.json())\n\n const cookieParser = require(\"cookie-parser\")\n this.app.use(\n cookieParser(this.config.cookieSecret || `AOS_${this.config.packageName}_${this.config.apiKey.substring(0, 8)}`),\n )\n\n // Apply authentication middleware\n this.app.use(\n createAuthMiddleware({\n apiKey: this.config.apiKey,\n packageName: this.config.packageName,\n getAppSessionForUser: (userId: string) => {\n return this.activeSessionsByUserId.get(userId) || null\n },\n cookieSecret:\n this.config.cookieSecret || `AOS_${this.config.packageName}_${this.config.apiKey.substring(0, 8)}`,\n }) as any,\n )\n\n this.appInstructions = (config as any).appInstructions || null\n\n // Setup server features\n this.setupWebhook()\n this.setupSettingsEndpoint()\n this.setupHealthCheck()\n this.setupToolCallEndpoint()\n this.setupPhotoUploadEndpoint()\n this.setupMentraAuthRedirect()\n this.setupPublicDir()\n this.setupShutdown()\n }\n\n // Expose Express app for custom routes.\n // This is useful for adding custom API routes or middleware.\n public getExpressApp(): Express {\n return this.app\n }\n\n /**\n * 👥 Session Handler\n * Override this method to handle new App sessions.\n * This is where you implement your app's core functionality.\n *\n * @param session - App session instance for the user\n * @param sessionId - Unique identifier for this session\n * @param userId - User's identifier\n */\n protected async onSession(session: AppSession, sessionId: string, userId: string): Promise<void> {\n this.logger.info(`🚀 Starting new session handling for session ${sessionId} and user ${userId}`)\n // Core session handling logic (onboarding removed)\n this.logger.info(`✅ Session handling completed for session ${sessionId} and user ${userId}`)\n }\n\n /**\n * 👥 Stop Handler\n * Override this method to handle stop requests.\n * This is where you can clean up resources when a session is stopped.\n *\n * @param sessionId - Unique identifier for this session\n * @param userId - User's identifier\n * @param reason - Reason for stopping\n */\n protected async onStop(sessionId: string, userId: string, reason: string): Promise<void> {\n this.logger.debug(`Session ${sessionId} stopped for user ${userId}. Reason: ${reason}`)\n\n // Default implementation: close the session if it exists\n const session = this.activeSessions.get(sessionId)\n if (session) {\n session.disconnect()\n this.activeSessions.delete(sessionId)\n this.activeSessionsByUserId.delete(userId)\n }\n }\n\n /**\n * 🛠️ Tool Call Handler\n * Override this method to handle tool calls from MentraOS Cloud.\n * This is where you implement your app's tool functionality.\n *\n * @param toolCall - The tool call request containing tool details and parameters\n * @returns Optional string response that will be sent back to MentraOS Cloud\n */\n protected async onToolCall(toolCall: ToolCall): Promise<string | undefined> {\n this.logger.debug(`Tool call received: ${toolCall.toolId}`)\n this.logger.debug(`Parameters: ${JSON.stringify(toolCall.toolParameters)}`)\n return undefined\n }\n\n /**\n * 🚀 Start the Server\n * Starts listening for incoming connections and webhook calls.\n *\n * @returns Promise that resolves when server is ready\n */\n public start(): Promise<void> {\n return new Promise((resolve) => {\n this.app.listen(this.config.port, async () => {\n this.logger.info(`🎯 App server running at http://localhost:${this.config.port}`)\n if (this.config.publicDir) {\n this.logger.info(`📂 Serving static files from ${this.config.publicDir}`)\n }\n\n // 🔑 Grab SDK version\n try {\n // Look for the actual installed @mentra/sdk package.json in node_modules\n const sdkPkgPath = path.resolve(process.cwd(), \"node_modules/@mentra/sdk/package.json\")\n\n let currentVersion = \"unknown\"\n\n if (fs.existsSync(sdkPkgPath)) {\n const sdkPkg = JSON.parse(fs.readFileSync(sdkPkgPath, \"utf-8\"))\n\n // Get the actual installed version\n currentVersion = sdkPkg.version || \"not-found\" // located in the node module\n } else {\n this.logger.debug({sdkPkgPath}, \"No @mentra/sdk package.json found at path\")\n }\n\n // this.logger.debug(`Developer is using SDK version: ${currentVersion}`);\n\n // Fetch latest SDK version from the API endpoint\n let latest: string | null = null\n try {\n const cloudHost = \"api.mentra.glass\"\n const response = await axios.get(\n `https://${cloudHost}/api/sdk/version`,\n {timeout: 3000}, // 3 second timeout\n )\n if (response.data && response.data.success && response.data.data) {\n latest = response.data.data.latest\n }\n } catch {\n this.logger.debug(\n \"Failed to fetch latest SDK version - skipping version check (offline or API unavailable)\",\n )\n }\n\n if (currentVersion === \"not-found\") {\n this.logger.warn(\n `⚠️ @mentra/sdk not found in your project dependencies. Please install it with: npm install @mentra/sdk`,\n )\n } else if (latest && latest !== currentVersion) {\n this.logger.warn(newSDKUpdate(latest))\n }\n } catch (err) {\n this.logger.error(err, \"Version check failed\")\n }\n\n resolve()\n })\n })\n }\n\n /**\n * 🛑 Stop the Server\n * Gracefully shuts down the server and cleans up all sessions.\n */\n public async stop(): Promise<void> {\n this.logger.info(\"\\n🛑 Shutting down...\")\n await this.cleanup()\n process.exit(0)\n }\n\n /**\n * 🔐 Generate a App token for a user\n * This should be called when handling a session webhook request.\n *\n * @param userId - User identifier\n * @param sessionId - Session identifier\n * @param secretKey - Secret key for signing the token\n * @returns JWT token string\n */\n protected generateToken(userId: string, sessionId: string, secretKey: string): string {\n const {createToken} = require(\"../token/utils\")\n return createToken(\n {\n userId,\n packageName: this.config.packageName,\n sessionId,\n },\n {secretKey},\n )\n }\n\n /**\n * 🧹 Add Cleanup Handler\n * Register a function to be called during server shutdown.\n *\n * @param handler - Function to call during cleanup\n */\n protected addCleanupHandler(handler: () => void): void {\n this.cleanupHandlers.push(handler)\n }\n\n /**\n * 🎯 Setup Webhook Endpoint\n * Creates the webhook endpoint that MentraOS Cloud calls to start new sessions.\n */\n private setupWebhook(): void {\n if (!this.config.webhookPath) {\n this.logger.error(\"❌ Webhook path not set\")\n throw new Error(\"Webhook path not set\")\n }\n\n this.app.post(this.config.webhookPath, async (req, res) => {\n try {\n const webhookRequest = req.body as WebhookRequest\n\n // Handle session request\n if (webhookRequest.type === WebhookRequestType.SESSION_REQUEST) {\n await this.handleSessionRequest(webhookRequest, res)\n }\n // Handle stop request\n else if (webhookRequest.type === WebhookRequestType.STOP_REQUEST) {\n await this.handleStopRequest(webhookRequest, res)\n }\n // Unknown webhook type\n else {\n this.logger.error(\"❌ Unknown webhook request type\")\n res.status(400).json({\n status: \"error\",\n message: \"Unknown webhook request type\",\n } as WebhookResponse)\n }\n } catch (error) {\n this.logger.error(error, \"❌ Error handling webhook: \" + (error as Error).message)\n res.status(500).json({\n status: \"error\",\n message: \"Error handling webhook: \" + (error as Error).message,\n } as WebhookResponse)\n }\n })\n }\n\n /**\n * 🛠️ Setup Tool Call Endpoint\n * Creates a /tool endpoint for handling tool calls from MentraOS Cloud.\n */\n private setupToolCallEndpoint(): void {\n this.app.post(\"/tool\", async (req, res) => {\n try {\n const toolCall = req.body as ToolCall\n if (this.activeSessionsByUserId.has(toolCall.userId)) {\n toolCall.activeSession = this.activeSessionsByUserId.get(toolCall.userId) || null\n } else {\n toolCall.activeSession = null\n }\n this.logger.info({body: req.body}, `🔧 Received tool call: ${toolCall.toolId}`)\n // Call the onToolCall handler and get the response\n const response = await this.onToolCall(toolCall)\n\n // Send back the response if one was provided\n if (response !== undefined) {\n res.json({status: \"success\", reply: response})\n } else {\n res.json({status: \"success\", reply: null})\n }\n } catch (error) {\n this.logger.error(error, \"❌ Error handling tool call:\")\n res.status(500).json({\n status: \"error\",\n message: error instanceof Error ? error.message : \"Unknown error occurred calling tool\",\n })\n }\n })\n this.app.get(\"/tool\", async (req, res) => {\n res.json({status: \"success\", reply: \"Hello, world!\"})\n })\n }\n\n /**\n * Handle a session request webhook\n */\n private async handleSessionRequest(request: SessionWebhookRequest, res: express.Response): Promise<void> {\n const {sessionId, userId, mentraOSWebsocketUrl, augmentOSWebsocketUrl} = request\n this.logger.info({userId}, `🗣️ Received session request for user ${userId}, session ${sessionId}\\n\\n`)\n\n // Create new App session\n const session = new AppSession({\n packageName: this.config.packageName,\n apiKey: this.config.apiKey,\n mentraOSWebsocketUrl: mentraOSWebsocketUrl || augmentOSWebsocketUrl, // The websocket URL for the specific MentraOS server that this userSession is connecting to.\n appServer: this,\n userId,\n })\n\n // Setup session event handlers\n const cleanupDisconnect = session.events.onDisconnected((info) => {\n // Handle different disconnect info formats (string or object)\n if (typeof info === \"string\") {\n this.logger.info(`👋 Session ${sessionId} disconnected: ${info}`)\n } else {\n // It's an object with detailed disconnect information\n this.logger.info(\n `👋 Session ${sessionId} disconnected: ${info.message} (code: ${info.code}, reason: ${info.reason})`,\n )\n\n // Check if this is a user session end event\n // This happens when the UserSession is disposed after 1 minute grace period\n if (info.sessionEnded === true) {\n this.logger.info(`🛑 User session ended for session ${sessionId}, calling onStop`)\n\n // Call onStop with session end reason\n // This allows apps to clean up resources when the user's session ends\n this.onStop(sessionId, userId, \"User session ended\").catch((error) => {\n this.logger.error(error, `❌ Error in onStop handler for session end:`)\n })\n }\n // Check if this is a permanent disconnection after exhausted reconnection attempts\n else if (info.permanent === true) {\n this.logger.info(`🛑 Permanent disconnection detected for session ${sessionId}, calling onStop`)\n\n // Keep track of the original session before removal\n // const session = this.activeSessions.get(sessionId);\n const _session = this.activeSessions.get(sessionId)\n\n // Call onStop with a reconnection failure reason\n this.onStop(sessionId, userId, `Connection permanently lost: ${info.reason}`).catch((error) => {\n this.logger.error(error, `❌ Error in onStop handler for permanent disconnection:`)\n })\n }\n }\n\n // Remove the session from active sessions in all cases\n this.activeSessions.delete(sessionId)\n this.activeSessionsByUserId.delete(userId)\n })\n\n const cleanupError = session.events.onError((error) => {\n this.logger.error(error, `❌ [Session ${sessionId}] Error:`)\n })\n\n // Start the session\n try {\n await session.connect(sessionId)\n this.activeSessions.set(sessionId, session)\n this.activeSessionsByUserId.set(userId, session)\n await this.onSession(session, sessionId, userId)\n res.status(200).json({status: \"success\"} as WebhookResponse)\n } catch (error) {\n this.logger.error(error, \"❌ Failed to connect:\")\n cleanupDisconnect()\n cleanupError()\n res.status(500).json({\n status: \"error\",\n message: \"Failed to connect\",\n } as WebhookResponse)\n }\n }\n\n /**\n * Handle a stop request webhook\n */\n private async handleStopRequest(request: StopWebhookRequest, res: express.Response): Promise<void> {\n const {sessionId, userId, reason} = request\n this.logger.info(`\\n\\n🛑 Received stop request for user ${userId}, session ${sessionId}, reason: ${reason}\\n\\n`)\n\n try {\n await this.onStop(sessionId, userId, reason)\n res.status(200).json({status: \"success\"} as WebhookResponse)\n } catch (error) {\n this.logger.error(error, \"❌ Error handling stop request:\")\n res.status(500).json({\n status: \"error\",\n message: \"Failed to process stop request\",\n } as WebhookResponse)\n }\n }\n\n /**\n * ❤️ Setup Health Check Endpoint\n * Creates a /health endpoint for monitoring server status.\n */\n private setupHealthCheck(): void {\n if (this.config.healthCheck) {\n this.app.get(\"/health\", (req, res) => {\n res.json({\n status: \"healthy\",\n app: this.config.packageName,\n activeSessions: this.activeSessions.size,\n })\n })\n }\n }\n\n /**\n * ⚙️ Setup Settings Endpoint\n * Creates a /settings endpoint that the MentraOS Cloud can use to update settings.\n */\n private setupSettingsEndpoint(): void {\n this.app.post(\"/settings\", async (req, res) => {\n try {\n const {userIdForSettings, settings} = req.body\n\n if (!userIdForSettings || !Array.isArray(settings)) {\n return res.status(400).json({\n status: \"error\",\n message: \"Missing userId or settings array in request body\",\n })\n }\n\n this.logger.info(`⚙️ Received settings update for user ${userIdForSettings}`)\n\n // Find all active sessions for this user\n const userSessions: AppSession[] = []\n\n // Look through all active sessions\n this.activeSessions.forEach((session, _sessionId) => {\n // Check if the session has this userId (not directly accessible)\n // We're relying on the webhook handler to have already verified this\n if (session.userId === userIdForSettings) {\n userSessions.push(session)\n }\n })\n\n if (userSessions.length === 0) {\n this.logger.warn(`⚠️ No active sessions found for user ${userIdForSettings}`)\n } else {\n this.logger.info(`🔄 Updating settings for ${userSessions.length} active sessions`)\n }\n\n // Update settings for all of the user's sessions\n for (const session of userSessions) {\n session.updateSettingsForTesting(settings)\n }\n\n // Allow subclasses to handle settings updates if they implement the method\n if (typeof (this as any).onSettingsUpdate === \"function\") {\n await (this as any).onSettingsUpdate(userIdForSettings, settings)\n }\n\n res.json({\n status: \"success\",\n message: \"Settings updated successfully\",\n sessionsUpdated: userSessions.length,\n })\n } catch (error) {\n this.logger.error(error, \"❌ Error handling settings update:\")\n res.status(500).json({\n status: \"error\",\n message: \"Internal server error processing settings update\",\n })\n }\n })\n }\n\n /**\n * 📂 Setup Static File Serving\n * Configures Express to serve static files from the specified directory.\n */\n private setupPublicDir(): void {\n if (this.config.publicDir) {\n const publicPath = path.resolve(this.config.publicDir)\n this.app.use(express.static(publicPath))\n this.logger.info(`📂 Serving static files from ${publicPath}`)\n }\n }\n\n /**\n * 🛑 Setup Shutdown Handlers\n * Registers process signal handlers for graceful shutdown.\n */\n private setupShutdown(): void {\n process.on(\"SIGTERM\", () => this.stop())\n process.on(\"SIGINT\", () => this.stop())\n }\n\n /**\n * 🧹 Cleanup\n * Closes all active sessions and runs cleanup handlers.\n * Releases ownership before disconnecting to enable clean handoffs (no resurrection).\n */\n private async cleanup(): Promise<void> {\n // Close all active sessions with ownership release for clean handoff\n for (const [sessionId, session] of this.activeSessions) {\n this.logger.info(`👋 Closing session ${sessionId} with ownership release`)\n try {\n // Release ownership first, then disconnect\n // This tells the cloud not to resurrect this app\n await session.disconnect({\n releaseOwnership: true,\n reason: \"clean_shutdown\",\n })\n } catch (error) {\n this.logger.error(error, `Error during cleanup of session ${sessionId}`)\n // Still try to disconnect even if release fails\n try {\n await session.disconnect()\n } catch {\n // Ignore secondary errors\n }\n }\n }\n this.activeSessions.clear()\n this.activeSessionsByUserId.clear()\n\n // Run cleanup handlers\n this.cleanupHandlers.forEach((handler) => handler())\n }\n\n /**\n * 🎯 Setup Photo Upload Endpoint\n * Creates a /photo-upload endpoint for receiving photos directly from ASG glasses\n */\n private setupPhotoUploadEndpoint(): void {\n const multer = require(\"multer\")\n\n // Configure multer for handling multipart form data\n const upload = multer({\n storage: multer.memoryStorage(),\n limits: {\n fileSize: 10 * 1024 * 1024, // 10MB limit\n },\n fileFilter: (req: any, file: any, cb: any) => {\n // Accept image files only\n if (file.mimetype && file.mimetype.startsWith(\"image/\")) {\n cb(null, true)\n } else {\n cb(new Error(\"Only image files are allowed\"), false)\n }\n },\n })\n\n this.app.post(\"/photo-upload\", upload.single(\"photo\"), async (req: any, res: any) => {\n try {\n const {requestId, type, success, errorCode, errorMessage} = req.body\n const photoFile = req.file\n\n console.log(\"Received photo response: \", req.body)\n\n this.logger.info(\n {requestId, type, success, errorCode},\n `📸 Received photo response: ${requestId} (type: ${type})`,\n )\n\n if (!requestId) {\n this.logger.error(\"No requestId in photo response\")\n return res.status(400).json({\n success: false,\n error: \"No requestId provided\",\n })\n }\n\n // Find the corresponding session that made this photo request\n const session = this.findSessionByPhotoRequestId(requestId)\n if (!session) {\n this.logger.warn({requestId}, \"No active session found for photo request\")\n return res.status(404).json({\n success: false,\n error: \"No active session found for this photo request\",\n })\n }\n\n // Handle error response (no photo file, but has error info)\n if (type === \"photo_error\" || success === false) {\n // Create error response object\n const errorResponse = {\n requestId,\n success: false as const,\n error: {\n code: errorCode || \"UNKNOWN_ERROR\",\n message: errorMessage || \"Unknown error occurred\",\n },\n }\n\n // Deliver error to the session (logging happens in camera module)\n session.camera.handlePhotoError(errorResponse)\n\n // Respond to ASG client\n return res.json({\n success: true,\n requestId,\n message: \"Photo error received successfully\",\n })\n }\n\n // Handle successful photo upload\n if (!photoFile) {\n this.logger.error({requestId}, \"No photo file in successful upload\")\n return res.status(400).json({\n success: false,\n error: \"No photo file provided for successful upload\",\n })\n }\n\n // Create photo data object\n const photoData = {\n buffer: photoFile.buffer,\n mimeType: photoFile.mimetype,\n filename: photoFile.originalname || \"photo.jpg\",\n requestId,\n size: photoFile.size,\n timestamp: new Date(),\n }\n\n // Deliver photo to the session\n session.camera.handlePhotoReceived(photoData)\n\n // Respond to ASG client\n res.json({\n success: true,\n requestId,\n message: \"Photo received successfully\",\n })\n } catch (error) {\n this.logger.error(error, \"❌ Error handling photo response\")\n res.status(500).json({\n success: false,\n error: \"Internal server error processing photo response\",\n })\n }\n })\n }\n\n /**\n * 🔐 Setup Mentra Auth Redirect Endpoint\n * Creates a /mentra-auth endpoint that redirects to the MentraOS OAuth flow.\n */\n private setupMentraAuthRedirect(): void {\n this.app.get(\"/mentra-auth\", (req, res) => {\n // Redirect to the account.mentra.glass OAuth flow with the app's package name\n const authUrl = `https://account.mentra.glass/auth?packagename=${encodeURIComponent(this.config.packageName)}`\n\n this.logger.info(`🔐 Redirecting to MentraOS OAuth flow: ${authUrl}`)\n\n res.redirect(302, authUrl)\n })\n }\n\n /**\n * Find session that has a pending photo request for the given requestId\n */\n private findSessionByPhotoRequestId(requestId: string): AppSession | undefined {\n for (const [_sessionId, session] of this.activeSessions) {\n if (session.camera.hasPhotoPendingRequest(requestId)) {\n return session\n }\n }\n return undefined\n }\n}\n\n/**\n * @deprecated Use `AppServerConfig` instead. `TpaServerConfig` is deprecated and will be removed in a future version.\n * This is an alias for backward compatibility only.\n *\n * @example\n * ```typescript\n * // ❌ Deprecated - Don't use this\n * const config: TpaServerConfig = { ... };\n *\n * // ✅ Use this instead\n * const config: AppServerConfig = { ... };\n * ```\n */\nexport type TpaServerConfig = AppServerConfig\n\n/**\n * @deprecated Use `AppServer` instead. `TpaServer` is deprecated and will be removed in a future version.\n * This is an alias for backward compatibility only.\n *\n * @example\n * ```typescript\n * // ❌ Deprecated - Don't use this\n * class MyServer extends TpaServer { ... }\n *\n * // ✅ Use this instead\n * class MyServer extends AppServer { ... }\n * ```\n */\nexport class TpaServer extends AppServer {\n constructor(config: TpaServerConfig) {\n super(config)\n // Emit a deprecation warning to help developers migrate\n console.warn(\n \"⚠️ DEPRECATION WARNING: TpaServer is deprecated and will be removed in a future version. \" +\n \"Please use AppServer instead. \" +\n 'Simply replace \"TpaServer\" with \"AppServer\" in your code.',\n )\n }\n}\n",
21
+ "/* eslint-disable import/order */\n \n/**\n * 🎯 App Session Module\n *\n * Manages an active Third Party App session with MentraOS Cloud.\n * Handles real-time communication, event subscriptions, and display management.\n */\n\n// Patch version for tracking Bug 007 fix (subscriptions derived from handlers)\n// v1: Derive subscriptions from handlers (single source of truth)\n// v2: Add 'terminated' flag to prevent reconnection after \"User session ended\"\n// This helps verify the correct SDK version is running in production\nconst SDK_SUBSCRIPTION_PATCH = \"bug007-fix-v2\";\nimport { WebSocket } from \"ws\";\nimport { EventManager, EventData } from \"./events\";\nimport { LayoutManager } from \"./layouts\";\nimport { SettingsManager } from \"./settings\";\nimport { LocationManager } from \"./modules/location\";\nimport { CameraModule } from \"./modules/camera\";\nimport { LedModule } from \"./modules/led\";\nimport { AudioManager } from \"./modules/audio\";\nimport { ResourceTracker } from \"../../utils/resource-tracker\";\nimport {\n // Message types\n AppToCloudMessage,\n CloudToAppMessage,\n AppConnectionInit,\n AppSubscriptionUpdate,\n AudioPlayResponse,\n RequestWifiSetup,\n OwnershipReleaseMessage,\n AppToCloudMessageType,\n CloudToAppMessageType,\n\n // Event data types\n StreamType,\n ExtendedStreamType,\n ButtonPress,\n HeadPosition,\n TouchEvent,\n PhoneNotification,\n PhoneNotificationDismissed,\n TranscriptionData,\n TranslationData,\n createTouchEventStream,\n\n // Type guards\n isAppConnectionAck,\n isAppConnectionError,\n isDataStream,\n isAppStopped,\n isSettingsUpdate,\n isDashboardModeChanged,\n isDashboardAlwaysOnChanged,\n isAudioPlayResponse,\n isCapabilitiesUpdate,\n\n // Other types\n AppSettings,\n AppSetting,\n AppConfig,\n validateAppConfig,\n AudioChunk,\n VpsCoordinates,\n PhotoTaken,\n SubscriptionRequest,\n Capabilities,\n CapabilitiesUpdate,\n} from \"../../types\";\nimport { DashboardAPI } from \"../../types/dashboard\";\nimport { MentraosSettingsUpdate } from \"../../types/messages/cloud-to-app\";\nimport { Logger } from \"pino\";\nimport { AppServer } from \"../server\";\nimport axios from \"axios\";\nimport EventEmitter from \"events\";\n\n// Import the cloud-to-app specific type guards\nimport {\n isPhotoResponse,\n isRgbLedControlResponse,\n isRtmpStreamStatus,\n isManagedStreamStatus,\n isStreamStatusCheckResponse,\n isDeviceStateUpdate,\n} from \"../../types/messages/cloud-to-app\";\nimport { SimpleStorage } from \"./modules/simple-storage\";\nimport { DeviceState } from \"./device-state\";\nimport { readNotificationWarnLog } from \"../../utils/permissions-utils\";\n\n/**\n * ⚙️ Configuration options for App Session\n *\n * @example\n * ```typescript\n * const config: AppSessionConfig = {\n * packageName: 'org.example.myapp',\n * apiKey: 'your_api_key',\n * // Auto-reconnection is enabled by default\n * // autoReconnect: true\n * };\n * ```\n */\nexport interface AppSessionConfig {\n /** 📦 Unique identifier for your App (e.g., 'org.company.appname') */\n packageName: string;\n /** 🔑 API key for authentication with MentraOS Cloud */\n apiKey: string;\n /** 🔌 WebSocket server URL (default: 'ws://localhost:7002/app-ws') */\n mentraOSWebsocketUrl?: string;\n /** 🔄 Automatically attempt to reconnect on disconnect (default: true) */\n autoReconnect?: boolean;\n /** 🔁 Maximum number of reconnection attempts (default: 3) */\n maxReconnectAttempts?: number;\n /** ⏱️ Base delay between reconnection attempts in ms (default: 1000) */\n reconnectDelay?: number;\n\n userId: string; // user ID for tracking sessions (email of the user).\n appServer: AppServer; // Optional App server instance for advanced features\n}\n\n// List of event types that should never be subscribed to as streams\nconst APP_TO_APP_EVENT_TYPES = [\n \"app_message_received\",\n \"app_user_joined\",\n \"app_user_left\",\n \"app_room_updated\",\n \"app_direct_message_response\",\n];\n\n/**\n * 🚀 App Session Implementation\n *\n * Manages a live connection between your App and MentraOS Cloud.\n * Provides interfaces for:\n * - 🎮 Event handling (transcription, head position, etc.)\n * - 📱 Display management in AR view\n * - 🔌 Connection lifecycle\n * - 🔄 Automatic reconnection\n *\n * @example\n * ```typescript\n * const session = new AppSession({\n * packageName: 'org.example.myapp',\n * apiKey: 'your_api_key'\n * });\n *\n * // Handle events\n * session.onTranscription((data) => {\n * session.layouts.showTextWall(data.text);\n * });\n *\n * // Connect to cloud\n * await session.connect('session_123');\n * ```\n */\nexport class AppSession {\n /** WebSocket connection to MentraOS Cloud */\n private ws: WebSocket | null = null;\n /** Current session identifier */\n private sessionId: string | null = null;\n /** Number of reconnection attempts made */\n private reconnectAttempts = 0;\n /** Flag to prevent reconnection after session termination (e.g., \"User session ended\") */\n private terminated = false;\n // REMOVED: private subscriptions = new Set<ExtendedStreamType>()\n // Subscriptions are now derived from EventManager.handlers (single source of truth)\n // This prevents drift between handlers and subscriptions that caused Bug 007\n // See: cloud/issues/006-captions-and-apps-stopping/011-sdk-subscription-architecture-mismatch.md\n /** Map to store rate options for streams */\n private streamRates = new Map<ExtendedStreamType, string>();\n /** Resource tracker for automatic cleanup */\n private resources = new ResourceTracker();\n /** Internal settings storage - use public settings API instead */\n private settingsData: AppSettings = [];\n /** App configuration loaded from app_config.json */\n private appConfig: AppConfig | null = null;\n /** Whether to update subscriptions when settings change */\n private shouldUpdateSubscriptionsOnSettingsChange = false;\n /** Custom subscription handler for settings-based subscriptions */\n private subscriptionSettingsHandler?: (settings: AppSettings) => ExtendedStreamType[];\n /** Settings that should trigger subscription updates when changed */\n private subscriptionUpdateTriggers: string[] = [];\n /** Pending user discovery requests waiting for responses */\n private pendingUserDiscoveryRequests = new Map<\n string,\n {\n resolve: (userList: any) => void;\n reject: (reason: any) => void;\n }\n >();\n /** Pending direct message requests waiting for responses */\n private pendingDirectMessages = new Map<\n string,\n {\n resolve: (success: boolean) => void;\n reject: (reason: any) => void;\n }\n >();\n\n /** 🎮 Event management interface */\n public readonly events: EventManager;\n /** 📱 Layout management interface */\n public readonly layouts: LayoutManager;\n /** ⚙️ Settings management interface */\n public readonly settings: SettingsManager;\n /** 📊 Dashboard management interface */\n public readonly dashboard: DashboardAPI;\n /** 📍 Location management interface */\n public readonly location: LocationManager;\n /** 📷 Camera interface for photos and streaming */\n public readonly camera: CameraModule;\n /** 💡 LED interface for RGB LED control */\n public readonly led: LedModule;\n /** 🔊 Audio interface for audio playback */\n public readonly audio: AudioManager;\n /** 🔐 Simple key-value storage interface */\n public readonly simpleStorage: SimpleStorage;\n /** 📱 Reactive device state (WebSocket-based observables) */\n public readonly device: { state: DeviceState };\n\n public readonly appServer: AppServer;\n public readonly logger: Logger;\n public readonly userId: string;\n\n /** 🔧 Device capabilities available for this session */\n public capabilities: Capabilities | null = null;\n\n /** 📡 Latest glasses connection state (includes WiFi status) */\n private glassesConnectionState: any = null; // Using any for now since GlassesConnectionState is in glasses-to-cloud types\n\n /** Dedicated emitter for App-to-App events */\n private appEvents = new EventEmitter();\n\n constructor(private config: AppSessionConfig) {\n // Set defaults and merge with provided config\n this.config = {\n mentraOSWebsocketUrl: `ws://localhost:8002/app-ws`, // Use localhost as default\n autoReconnect: true, // Enable auto-reconnection by default for better reliability\n maxReconnectAttempts: 3, // Default to 3 reconnection attempts for better resilience\n reconnectDelay: 1000, // Start with 1 second delay (uses exponential backoff)\n ...config,\n };\n\n this.appServer = this.config.appServer;\n this.logger = this.appServer.logger.child({\n userId: this.config.userId,\n service: \"app-session\",\n });\n this.userId = this.config.userId;\n\n // Make sure the URL is correctly formatted to prevent double protocol issues\n if (this.config.mentraOSWebsocketUrl) {\n try {\n const url = new URL(this.config.mentraOSWebsocketUrl);\n if (![\"ws:\", \"wss:\"].includes(url.protocol)) {\n // Fix URLs with incorrect protocol (e.g., 'ws://http://host')\n const fixedUrl = this.config.mentraOSWebsocketUrl.replace(/^ws:\\/\\/http:\\/\\//, \"ws://\");\n this.config.mentraOSWebsocketUrl = fixedUrl;\n this.logger.warn(`⚠️ [${this.config.packageName}] Fixed malformed WebSocket URL: ${fixedUrl}`);\n }\n } catch (error) {\n this.logger.error(\n error,\n `⚠️ [${this.config.packageName}] Invalid WebSocket URL format: ${this.config.mentraOSWebsocketUrl}`,\n );\n }\n }\n\n // Log initialization\n this.logger.debug(`🚀 [${this.config.packageName}] App Session initialized`);\n this.logger.debug(`🚀 [${this.config.packageName}] WebSocket URL: ${this.config.mentraOSWebsocketUrl}`);\n\n // Validate URL format - give early warning for obvious issues\n // Check URL format but handle undefined case\n if (this.config.mentraOSWebsocketUrl) {\n try {\n const url = new URL(this.config.mentraOSWebsocketUrl);\n if (![\"ws:\", \"wss:\"].includes(url.protocol)) {\n this.logger.error(\n { config: this.config },\n `⚠️ [${this.config.packageName}] Invalid WebSocket URL protocol: ${url.protocol}. Should be ws: or wss:`,\n );\n }\n } catch (error) {\n this.logger.error(\n error,\n `⚠️ [${this.config.packageName}] Invalid WebSocket URL format: ${this.config.mentraOSWebsocketUrl}`,\n );\n }\n }\n\n this.events = new EventManager(\n this.subscribe.bind(this),\n this.unsubscribe.bind(this),\n this.config.packageName,\n this.getHttpsServerUrl() || \"\",\n );\n this.layouts = new LayoutManager(config.packageName, this.send.bind(this));\n\n // Initialize settings manager with all necessary parameters, including subscribeFn for MentraOS settings\n this.settings = new SettingsManager(\n this.settingsData,\n this.config.packageName,\n this.config.mentraOSWebsocketUrl,\n this.sessionId ?? undefined,\n async (streams: string[]) => {\n // NOTE: With Bug 007 fix, subscriptions are derived from EventManager.handlers\n // This subscribeFn is called by SettingsManager to auto-subscribe to streams for MentraOS settings\n // The actual subscription intent should be tracked via handlers, not a separate Set\n this.logger.debug({ streams: JSON.stringify(streams) }, `[AppSession] subscribeFn called for streams`);\n\n // Log current handler-based subscriptions for debugging\n const currentHandlerStreams = this.events.getRegisteredStreams();\n this.logger.debug(\n {\n requestedStreams: JSON.stringify(streams),\n currentHandlerStreams: JSON.stringify(currentHandlerStreams),\n },\n `[AppSession] subscribeFn: requested streams vs current handler streams`,\n );\n\n // Send subscription update if connected\n // Note: The actual subscriptions sent are derived from handlers\n if (this.ws?.readyState === 1) {\n this.updateSubscriptions();\n this.logger.debug(`[AppSession] Sent updated subscriptions to cloud (derived from handlers).`);\n } else {\n this.logger.debug(`[AppSession] WebSocket not open, will send subscriptions when connected.`);\n }\n },\n );\n\n // Initialize dashboard API with this session instance\n // Import DashboardManager dynamically to avoid circular dependency\n const { DashboardManager } = require(\"./dashboard\");\n this.dashboard = new DashboardManager(this);\n\n // Initialize camera module with session reference\n this.camera = new CameraModule(\n this,\n this.config.packageName,\n this.sessionId || \"unknown-session-id\",\n this.logger.child({ module: \"camera\" }),\n );\n\n // Initialize LED control module\n this.led = new LedModule(\n this,\n this.config.packageName,\n this.sessionId || \"unknown-session-id\",\n this.logger.child({ module: \"led\" }),\n );\n\n // Initialize audio module with session reference\n this.audio = new AudioManager(\n this,\n this.config.packageName,\n this.sessionId || \"unknown-session-id\",\n this.logger.child({ module: \"audio\" }),\n );\n\n this.simpleStorage = new SimpleStorage(this);\n this.device = { state: new DeviceState(this) };\n\n this.location = new LocationManager(this);\n }\n\n /**\n * Get the current session ID\n * @returns The current session ID or 'unknown-session-id' if not connected\n */\n getSessionId(): string {\n return this.sessionId || \"unknown-session-id\";\n }\n\n /**\n * Get the package name for this App\n * @returns The package name\n */\n getPackageName(): string {\n return this.config.packageName;\n }\n\n // =====================================\n // 🎮 Direct Event Handling Interface\n // =====================================\n\n /**\n * @deprecated Use session.events.onTranscription() instead\n */\n onTranscription(handler: (data: TranscriptionData) => void): () => void {\n return this.events.onTranscription(handler);\n }\n\n /**\n * 🌐 Listen for speech transcription events in a specific language\n * @param language - Language code (e.g., \"en-US\")\n * @param handler - Function to handle transcription data\n * @returns Cleanup function to remove the handler\n * @throws Error if language code is invalid\n * @deprecated Use session.events.onTranscriptionForLanguage() instead\n */\n onTranscriptionForLanguage(\n language: string,\n handler: (data: TranscriptionData) => void,\n disableLanguageIdentification = false,\n ): () => void {\n return this.events.onTranscriptionForLanguage(language, handler, disableLanguageIdentification);\n }\n\n /**\n * 🌐 Listen for speech translation events for a specific language pair\n * @param sourceLanguage - Source language code (e.g., \"es-ES\")\n * @param targetLanguage - Target language code (e.g., \"en-US\")\n * @param handler - Function to handle translation data\n * @returns Cleanup function to remove the handler\n * @throws Error if language codes are invalid\n * @deprecated Use session.events.onTranslationForLanguage() instead\n */\n onTranslationForLanguage(\n sourceLanguage: string,\n targetLanguage: string,\n handler: (data: TranslationData) => void,\n ): () => void {\n return this.events.ontranslationForLanguage(sourceLanguage, targetLanguage, handler);\n }\n\n /**\n * 👤 Listen for head position changes\n * @param handler - Function to handle head position updates\n * @returns Cleanup function to remove the handler\n * @deprecated Use session.events.onHeadPosition() instead\n */\n onHeadPosition(handler: (data: HeadPosition) => void): () => void {\n return this.events.onHeadPosition(handler);\n }\n\n /**\n * 🔘 Listen for hardware button press events\n * @param handler - Function to handle button events\n * @returns Cleanup function to remove the handler\n * @deprecated Use session.events.onButtonPress() instead\n */\n onButtonPress(handler: (data: ButtonPress) => void): () => void {\n return this.events.onButtonPress(handler);\n }\n\n /**\n * 👆 Listen for touch gesture events\n * @param gestureOrHandler - Gesture name or handler function\n * @param handler - Handler function (if first param is gesture name)\n * @returns Cleanup function\n *\n * @example\n * // Subscribe to all touch events\n * session.onTouchEvent((event) => console.log(event.gesture_name));\n *\n * // Subscribe to specific gesture\n * session.onTouchEvent(\"forward_swipe\", (event) => console.log(\"Forward swipe!\"));\n */\n onTouchEvent(\n gestureOrHandler: string | ((data: TouchEvent) => void),\n handler?: (data: TouchEvent) => void,\n ): () => void {\n return this.events.onTouchEvent(gestureOrHandler as any, handler as any);\n }\n\n /**\n * 👆 Subscribe to multiple touch gestures\n * @param gestures - Array of gesture names\n * @returns Cleanup function that unsubscribes from all\n *\n * @example\n * session.subscribeToGestures([\"forward_swipe\", \"backward_swipe\"]);\n */\n subscribeToGestures(gestures: string[]): () => void {\n gestures.forEach((gesture) => {\n const stream = createTouchEventStream(gesture);\n this.subscribe(stream);\n });\n\n return () => {\n gestures.forEach((gesture) => {\n const stream = createTouchEventStream(gesture);\n this.unsubscribe(stream);\n });\n };\n }\n\n /**\n * 📱 Listen for phone notification events\n * @param handler - Function to handle notifications\n * @returns Cleanup function to remove the handler\n * @deprecated Use session.events.onPhoneNotifications() instead\n */\n onPhoneNotifications(handler: (data: PhoneNotification) => void): () => void {\n readNotificationWarnLog(this.getHttpsServerUrl() || \"\", this.getPackageName(), \"onPhoneNotifications\");\n return this.events.onPhoneNotifications(handler);\n }\n\n /**\n * 📱 Listen for phone notification dismissed events\n * @param handler - Function to handle notification dismissal data\n * @returns Cleanup function to remove the handler\n * @deprecated Use session.events.onPhoneNotificationDismissed() instead\n */\n onPhoneNotificationDismissed(handler: (data: PhoneNotificationDismissed) => void): () => void {\n return this.events.onPhoneNotificationDismissed(handler);\n }\n\n /**\n * 📡 Listen for VPS coordinates updates\n * @param handler - Function to handle VPS coordinates\n * @returns Cleanup function to remove the handler\n * @deprecated Use session.events.onVpsCoordinates() instead\n */\n onVpsCoordinates(handler: (data: VpsCoordinates) => void): () => void {\n this.subscribe(StreamType.VPS_COORDINATES);\n return this.events.onVpsCoordinates(handler);\n }\n\n /**\n * 📸 Listen for photo responses\n * @param handler - Function to handle photo response data\n * @returns Cleanup function to remove the handler\n * @deprecated Use session.events.onPhotoTaken() instead\n */\n onPhotoTaken(handler: (data: PhotoTaken) => void): () => void {\n this.subscribe(StreamType.PHOTO_TAKEN);\n return this.events.onPhotoTaken(handler);\n }\n\n // =====================================\n // 📡 Pub/Sub Interface\n // =====================================\n\n /**\n * 📬 Subscribe to a specific event stream\n * @param sub - A string or a rich subscription object\n */\n subscribe(sub: SubscriptionRequest): void {\n let type: ExtendedStreamType;\n let rate: string | undefined;\n\n if (typeof sub === \"string\") {\n type = sub;\n } else {\n // it's a LocationStreamRequest object\n type = sub.stream;\n rate = sub.rate;\n }\n\n if (APP_TO_APP_EVENT_TYPES.includes(type as string)) {\n this.logger.warn(\n `[AppSession] Attempted to subscribe to App-to-App event type '${type}', which is not a valid stream. Use the event handler (e.g., onAppMessage) instead.`,\n );\n return;\n }\n\n // NOTE: We no longer maintain this.subscriptions - subscriptions are derived from handlers\n // This prevents drift between handlers and subscriptions (Bug 007 fix)\n // The EventManager.addHandler() already tracks the subscription intent via handlers\n\n if (rate) {\n this.streamRates.set(type, rate);\n }\n\n if (this.ws?.readyState === 1) {\n this.updateSubscriptions();\n }\n }\n\n /**\n * 📭 Unsubscribe from a specific event stream\n * @param sub - The subscription to remove\n */\n unsubscribe(sub: SubscriptionRequest): void {\n let type: ExtendedStreamType;\n if (typeof sub === \"string\") {\n type = sub;\n } else {\n type = sub.stream;\n }\n\n if (APP_TO_APP_EVENT_TYPES.includes(type as string)) {\n this.logger.warn(\n `[AppSession] Attempted to unsubscribe from App-to-App event type '${type}', which is not a valid stream.`,\n );\n return;\n }\n // NOTE: We no longer maintain this.subscriptions - subscriptions are derived from handlers\n // The EventManager.removeHandler() already tracks the unsubscription intent\n\n this.streamRates.delete(type); // also remove from our rate map\n if (this.ws?.readyState === 1) {\n this.updateSubscriptions();\n }\n }\n\n /**\n * 🎯 Generic event listener (pub/sub style)\n * @param event - Event name to listen for\n * @param handler - Event handler function\n */\n on<T extends ExtendedStreamType>(event: T, handler: (data: EventData<T>) => void): () => void {\n return this.events.on(event, handler);\n }\n\n // =====================================\n // 🔌 Connection Management\n // =====================================\n\n /**\n * 🚀 Connect to MentraOS Cloud\n * @param sessionId - Unique session identifier\n * @returns Promise that resolves when connected\n */\n async connect(sessionId: string): Promise<void> {\n this.sessionId = sessionId;\n\n // Configure settings API client with the WebSocket URL and session ID\n // This allows settings to be fetched from the correct server\n this.settings.configureApiClient(this.config.packageName, this.config.mentraOSWebsocketUrl || \"\", sessionId);\n\n // Update the sessionId in the camera module\n if (this.camera) {\n this.camera.updateSessionId(sessionId);\n }\n\n // Update the sessionId in the audio module\n if (this.audio) {\n this.audio.updateSessionId(sessionId);\n }\n\n return new Promise((resolve, reject) => {\n try {\n // Clear previous resources if reconnecting\n if (this.ws) {\n // Don't call full dispose() as that would clear subscriptions\n if (this.ws.readyState !== 3) {\n // 3 = CLOSED\n this.ws.close();\n }\n this.ws = null;\n }\n\n // Validate WebSocket URL before attempting connection\n if (!this.config.mentraOSWebsocketUrl) {\n this.logger.error(\"WebSocket URL is missing or undefined\");\n reject(new Error(\"WebSocket URL is required\"));\n return;\n }\n\n // Add debug logging for connection attempts\n this.logger.info(\n `🔌🔌🔌 [${this.config.packageName}] Attempting to connect to: ${this.config.mentraOSWebsocketUrl} for session ${this.sessionId}`,\n );\n\n // Create connection with error handling\n this.ws = new WebSocket(this.config.mentraOSWebsocketUrl);\n\n // Track WebSocket for automatic cleanup\n this.resources.track(() => {\n if (this.ws && this.ws.readyState !== 3) {\n // 3 = CLOSED\n this.ws.close();\n }\n });\n\n this.ws.on(\"open\", () => {\n try {\n this.sendConnectionInit();\n } catch (error: unknown) {\n this.logger.error(error, \"Error during connection initialization\");\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.events.emit(\"error\", new Error(`Connection initialization failed: ${errorMessage}`));\n reject(error);\n }\n });\n\n // Message handler with comprehensive error recovery\n const messageHandler = async (data: Buffer | string, isBinary: boolean) => {\n try {\n // Handle binary messages (typically audio data)\n if (isBinary && Buffer.isBuffer(data)) {\n try {\n // Validate buffer before processing\n if (data.length === 0) {\n this.events.emit(\"error\", new Error(\"Received empty binary data\"));\n return;\n }\n\n // Convert Node.js Buffer to ArrayBuffer safely\n const arrayBuf: ArrayBufferLike = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);\n\n // Create AUDIO_CHUNK event message with validation\n const audioChunk: AudioChunk = {\n type: StreamType.AUDIO_CHUNK,\n arrayBuffer: arrayBuf,\n timestamp: new Date(), // Ensure timestamp is present\n };\n\n this.handleMessage(audioChunk);\n return;\n } catch (error: unknown) {\n this.logger.error(error, \"Error processing binary message:\");\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.events.emit(\"error\", new Error(`Failed to process binary message: ${errorMessage}`));\n return;\n }\n }\n\n // Handle ArrayBuffer data type directly\n if (data instanceof ArrayBuffer) {\n return;\n }\n\n // Handle JSON messages with validation\n try {\n // Convert string data to JSON safely\n let jsonData: string;\n if (typeof data === \"string\") {\n jsonData = data;\n } else if (Buffer.isBuffer(data)) {\n jsonData = data.toString(\"utf8\");\n } else {\n throw new Error(\"Unknown message format\");\n }\n\n // Validate JSON before parsing\n if (!jsonData || jsonData.trim() === \"\") {\n this.events.emit(\"error\", new Error(\"Received empty JSON message\"));\n return;\n }\n\n // Parse JSON with error handling\n const message = JSON.parse(jsonData) as CloudToAppMessage;\n\n // Basic schema validation\n if (!message || typeof message !== \"object\" || !(\"type\" in message)) {\n this.events.emit(\"error\", new Error(\"Malformed message: missing type property\"));\n return;\n }\n\n // Process the validated message\n this.handleMessage(message);\n } catch (error: unknown) {\n this.logger.error(error, \"JSON parsing error\");\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.events.emit(\"error\", new Error(`Failed to parse JSON message: ${errorMessage}`));\n }\n } catch (error: unknown) {\n // Final catch - should never reach here if individual handlers work correctly\n this.logger.error({ error }, \"Unhandled message processing error\");\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.events.emit(\"error\", new Error(`Unhandled message error: ${errorMessage}`));\n }\n };\n\n this.ws.on(\"message\", messageHandler);\n\n // Track event handler removal for automatic cleanup\n this.resources.track(() => {\n if (this.ws) {\n this.ws.off(\"message\", messageHandler);\n }\n });\n\n // Connection closure handler\n const closeHandler = (code: number, reason: string) => {\n const reasonStr = reason ? `: ${reason}` : \"\";\n const closeInfo = `Connection closed (code: ${code})${reasonStr}`;\n\n // Emit the disconnected event with structured data for better handling\n this.events.emit(\"disconnected\", {\n message: closeInfo,\n code: code,\n reason: reason || \"\",\n wasClean: code === 1000 || code === 1001,\n });\n\n // Only attempt reconnection for abnormal closures\n // https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/code\n // 1000 (Normal Closure) and 1001 (Going Away) are normal\n // 1002-1015 are abnormal, and reason \"App stopped\" means intentional closure\n // 1008 usually when the userSession no longer exists on server. i.e user disconnected from cloud.\n const isNormalClosure = code === 1000 || code === 1001 || code === 1008;\n const isManualStop = reason && reason.includes(\"App stopped\");\n const isUserSessionEnded = reason && reason.includes(\"User session ended\");\n\n // Log closure details for diagnostics\n this.logger.debug(`🔌 [${this.config.packageName}] WebSocket closed with code ${code}${reasonStr}`);\n this.logger.debug(\n `🔌 [${this.config.packageName}] isNormalClosure: ${isNormalClosure}, isManualStop: ${isManualStop}, isUserSessionEnded: ${isUserSessionEnded}`,\n );\n\n // If user session ended, mark as terminated to prevent any future reconnection\n if (isUserSessionEnded) {\n this.terminated = true;\n this.logger.info(\n `🛑 [${this.config.packageName}] User session ended - marking as terminated, no reconnection allowed`,\n );\n }\n\n if (!isNormalClosure && !isManualStop && !this.terminated) {\n this.logger.warn(`🔌 [${this.config.packageName}] Abnormal closure detected, attempting reconnection`);\n this.handleReconnection();\n } else {\n this.logger.debug(\n `🔌 [${this.config.packageName}] Normal/terminated closure detected, not attempting reconnection (terminated: ${this.terminated})`,\n );\n }\n\n // if user session ended, then trigger onStop.\n if (isUserSessionEnded) {\n this.logger.info(\n `🛑 [${this.config.packageName}] User session ended - emitting disconnected event with sessionEnded flag`,\n );\n // Emit a disconnected event with a special flag to indicate session end\n // This will be caught by AppServer which will call the onStop callback\n const disconnectInfo = {\n message: \"User session ended\",\n code: 1000, // Normal closure\n reason: \"User session ended\",\n wasClean: true,\n permanent: true, // This is permanent - no reconnection\n sessionEnded: true, // Special flag to indicate session disposal\n };\n this.events.emit(\"disconnected\", disconnectInfo);\n }\n };\n\n this.ws.on(\"close\", closeHandler);\n\n // Track event handler removal\n this.resources.track(() => {\n if (this.ws) {\n this.ws.off(\"close\", closeHandler);\n }\n });\n\n // Connection error handler\n const errorHandler = (error: Error) => {\n this.logger.error(error, \"WebSocket error\");\n this.events.emit(\"error\", error);\n };\n\n // Enhanced error handler with detailed logging\n this.ws.on(\"error\", (error: Error) => {\n this.logger.error(\n error,\n `⛔️⛔️⛔️ [${this.config.packageName}] WebSocket connection error: ${error.message}`,\n );\n\n // Try to provide more context\n const errMsg = error.message || \"\";\n if (errMsg.includes(\"ECONNREFUSED\")) {\n this.logger.error(\n `⛔️⛔️⛔️ [${this.config.packageName}] Connection refused - Check if the server is running at the specified URL`,\n );\n } else if (errMsg.includes(\"ETIMEDOUT\")) {\n this.logger.error(\n `⛔️⛔️⛔️ [${this.config.packageName}] Connection timed out - Check network connectivity and firewall rules`,\n );\n }\n\n errorHandler(error);\n });\n\n // Track event handler removal\n this.resources.track(() => {\n if (this.ws) {\n this.ws.off(\"error\", errorHandler);\n }\n });\n\n // Set up connection success handler\n const connectedCleanup = this.events.onConnected(() => resolve());\n\n // Track event handler removal\n this.resources.track(connectedCleanup);\n\n // Connection timeout with configurable duration\n const timeoutMs = 5000; // 5 seconds default\n const connectionTimeout = this.resources.setTimeout(() => {\n // Use tracked timeout that will be auto-cleared\n this.logger.error(\n {\n config: this.config,\n sessionId: this.sessionId,\n timeoutMs,\n },\n `⏱️⏱️⏱️ [${this.config.packageName}] Connection timeout after ${timeoutMs}ms`,\n );\n\n this.events.emit(\"error\", new Error(`Connection timeout after ${timeoutMs}ms`));\n reject(new Error(\"Connection timeout\"));\n }, timeoutMs);\n\n // Clear timeout on successful connection\n const timeoutCleanup = this.events.onConnected(() => {\n clearTimeout(connectionTimeout);\n resolve();\n });\n\n // Track event handler removal\n this.resources.track(timeoutCleanup);\n } catch (error: unknown) {\n this.logger.error(error, \"Connection setup error\");\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Failed to setup connection: ${errorMessage}`));\n }\n });\n }\n\n /**\n * 🔄 Release ownership of this session to allow clean handoff\n * Call this before connecting to a different cloud instance or shutting down cleanly.\n * This signals to the cloud that no resurrection is needed.\n *\n * @param reason - Why ownership is being released\n */\n async releaseOwnership(reason: \"switching_clouds\" | \"clean_shutdown\" | \"user_logout\"): Promise<void> {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n this.logger.debug(`[${this.config.packageName}] Cannot release ownership - WebSocket not open`);\n return;\n }\n\n const message: OwnershipReleaseMessage = {\n type: AppToCloudMessageType.OWNERSHIP_RELEASE,\n packageName: this.config.packageName,\n sessionId: this.sessionId || \"\",\n reason,\n timestamp: new Date(),\n };\n\n this.logger.info(\n { reason, sessionId: this.sessionId },\n `🔄 [${this.config.packageName}] Releasing ownership: ${reason}`,\n );\n\n this.send(message);\n\n // Small delay to ensure message is sent before any subsequent disconnect\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n /**\n * 👋 Disconnect from MentraOS Cloud\n * Flushes any pending SimpleStorage writes before closing\n *\n * @param options - Optional disconnect options\n * @param options.releaseOwnership - If true, send OWNERSHIP_RELEASE before disconnecting (enables clean handoff)\n * @param options.reason - Reason for ownership release (required if releaseOwnership is true)\n */\n async disconnect(options?: {\n releaseOwnership?: boolean;\n reason?: \"switching_clouds\" | \"clean_shutdown\" | \"user_logout\";\n }): Promise<void> {\n // Release ownership if requested (for clean handoffs)\n if (options?.releaseOwnership && options?.reason) {\n await this.releaseOwnership(options.reason);\n }\n\n // Flush any pending SimpleStorage writes before closing\n try {\n await this.simpleStorage.flush();\n console.log(\"SimpleStorage flushed on disconnect\");\n } catch (error) {\n console.error(\"Error flushing SimpleStorage on disconnect:\", error);\n // Continue with disconnect even if flush fails\n }\n\n // Clean up camera module first\n if (this.camera) {\n this.camera.cancelAllRequests();\n }\n\n // Clean up audio module\n if (this.audio) {\n this.audio.cancelAllRequests();\n }\n\n // Use the resource tracker to clean up everything\n this.resources.dispose();\n\n // Clean up additional resources not handled by the tracker\n this.ws = null;\n this.sessionId = null;\n // REMOVED: this.subscriptions.clear()\n // We no longer clear subscriptions here - they are derived from handlers\n // This is the key fix for Bug 007: clearing subscriptions here caused\n // empty subscription updates on reconnect when handlers still existed\n // See: cloud/issues/006-captions-and-apps-stopping/011-sdk-subscription-architecture-mismatch.md\n this.reconnectAttempts = 0;\n }\n\n /**\n * 🛠️ Get all current user settings\n * @returns A copy of the current settings array\n * @deprecated Use session.settings.getAll() instead\n */\n getSettings(): AppSettings {\n return this.settings.getAll();\n }\n\n /**\n * 🔍 Get a specific setting value by key\n * @param key The setting key to look for\n * @returns The setting's value, or undefined if not found\n * @deprecated Use session.settings.get(key) instead\n */\n getSetting<T>(key: string): T | undefined {\n return this.settings.get<T>(key);\n }\n\n /**\n * ⚙️ Configure settings-based subscription updates\n * This allows Apps to automatically update their subscriptions when certain settings change\n * @param options Configuration options for settings-based subscriptions\n */\n setSubscriptionSettings(options: {\n updateOnChange: string[]; // Setting keys that should trigger subscription updates\n handler: (settings: AppSettings) => ExtendedStreamType[]; // Handler that returns new subscriptions\n }): void {\n this.shouldUpdateSubscriptionsOnSettingsChange = true;\n this.subscriptionUpdateTriggers = options.updateOnChange;\n this.subscriptionSettingsHandler = options.handler;\n\n // If we already have settings, update subscriptions immediately\n if (this.settingsData.length > 0) {\n this.updateSubscriptionsFromSettings();\n }\n }\n\n /**\n * 🔄 Update subscriptions based on current settings\n * Called automatically when relevant settings change\n */\n private updateSubscriptionsFromSettings(): void {\n if (!this.subscriptionSettingsHandler) return;\n\n try {\n // Get desired subscriptions from settings handler\n const settingsSubscriptions = this.subscriptionSettingsHandler(this.settingsData);\n\n // NOTE: Settings-based subscriptions work differently from handler-based subscriptions\n // With the Bug 007 fix, subscriptions are now derived from EventManager.handlers\n // Apps using setSubscriptionSettings() should ensure their settings correspond to\n // registered handlers for the subscriptions to take effect.\n //\n // Log if there's a mismatch (for debugging during migration)\n const handlerStreams = this.events.getRegisteredStreams();\n if (settingsSubscriptions.length !== handlerStreams.length) {\n this.logger.warn(\n {\n settingsSubscriptions: JSON.stringify(settingsSubscriptions),\n handlerStreams: JSON.stringify(handlerStreams),\n },\n `[AppSession] Settings-based subscriptions (${settingsSubscriptions.length}) differ from handler-based subscriptions (${handlerStreams.length}). ` +\n `Subscriptions are now derived from handlers. Ensure handlers are registered for desired streams.`,\n );\n }\n\n // Send subscription update to cloud if connected\n // Note: updateSubscriptions() derives from handlers, so settings-based apps\n // should ensure their settings correspond to registered handlers\n if (this.ws && this.ws.readyState === 1) {\n this.updateSubscriptions();\n }\n } catch (error: unknown) {\n this.logger.error(error, \"Error updating subscriptions from settings\");\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.events.emit(\"error\", new Error(`Failed to update subscriptions: ${errorMessage}`));\n }\n }\n\n /**\n * 🧪 For testing: Update settings locally\n * In normal operation, settings come from the cloud\n * @param newSettings The new settings to apply\n */\n updateSettingsForTesting(newSettings: AppSettings): void {\n this.settingsData = newSettings;\n\n // Update the settings manager with the new settings\n this.settings.updateSettings(newSettings);\n\n // Emit update event for backwards compatibility\n this.events.emit(\"settings_update\", this.settingsData);\n\n // Check if we should update subscriptions\n if (this.shouldUpdateSubscriptionsOnSettingsChange) {\n this.updateSubscriptionsFromSettings();\n }\n }\n\n /**\n * 📝 Load configuration from a JSON file\n * @param jsonData JSON string containing App configuration\n * @returns The loaded configuration\n * @throws Error if the configuration is invalid\n */\n loadConfigFromJson(jsonData: string): AppConfig {\n try {\n const parsedConfig = JSON.parse(jsonData);\n\n if (validateAppConfig(parsedConfig)) {\n this.appConfig = parsedConfig;\n return parsedConfig;\n } else {\n throw new Error(\"Invalid App configuration format\");\n }\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to load App configuration: ${errorMessage}`);\n }\n }\n\n /**\n * 📋 Get the loaded App configuration\n * @returns The current App configuration or null if not loaded\n */\n getConfig(): AppConfig | null {\n return this.appConfig;\n }\n\n /**\n * 🔌 Get the WebSocket server URL for this session\n * @returns The WebSocket server URL used by this session\n */\n getServerUrl(): string | undefined {\n return this.config.mentraOSWebsocketUrl;\n }\n\n public getHttpsServerUrl(): string | undefined {\n if (!this.config.mentraOSWebsocketUrl) {\n return undefined;\n }\n return AppSession.convertToHttps(this.config.mentraOSWebsocketUrl);\n }\n\n private static convertToHttps(rawUrl: string | undefined): string {\n if (!rawUrl) return \"\";\n // Remove ws:// or wss://\n let url = rawUrl.replace(/^wss?:\\/\\//, \"\");\n // Remove trailing /app-ws\n url = url.replace(/\\/app-ws$/, \"\");\n // Prepend https://\n return `https://${url}`;\n }\n\n /**\n * 🔍 Get default settings from the App configuration\n * @returns Array of settings with default values\n * @throws Error if configuration is not loaded\n */\n getDefaultSettings(): AppSettings {\n if (!this.appConfig) {\n throw new Error(\"App configuration not loaded. Call loadConfigFromJson first.\");\n }\n\n return this.appConfig.settings\n .filter((s: AppSetting | { type: \"group\"; title: string }): s is AppSetting => s.type !== \"group\")\n .map((s: AppSetting) => ({\n ...s,\n value: s.defaultValue, // Set value to defaultValue\n }));\n }\n\n /**\n * 🔍 Get setting schema from configuration\n * @param key Setting key to look up\n * @returns The setting schema or undefined if not found\n */\n getSettingSchema(key: string): AppSetting | undefined {\n if (!this.appConfig) return undefined;\n\n const setting = this.appConfig.settings.find(\n (s: AppSetting | { type: \"group\"; title: string }) => s.type !== \"group\" && \"key\" in s && s.key === key,\n );\n\n return setting as AppSetting | undefined;\n }\n\n /**\n * 📡 Get WiFi connection status of glasses\n * @returns WiFi status object or null if glasses don't support WiFi or status not available\n */\n getWifiStatus(): { connected: boolean; ssid?: string | null } | null {\n if (!this.capabilities?.hasWifi) {\n return null;\n }\n return this.glassesConnectionState?.wifi || null;\n }\n\n /**\n * ✅ Check if glasses are connected to WiFi\n * @returns true if connected to WiFi, false otherwise\n */\n isWifiConnected(): boolean {\n return this.getWifiStatus()?.connected === true;\n }\n\n /**\n * 🌐 Request WiFi setup from mobile app\n * Triggers a popup on the mobile app that allows user to set up WiFi on glasses\n * @param reason Optional reason message to display to the user\n */\n requestWifiSetup(reason?: string): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n throw new Error(\"Not connected to MentraOS Cloud\");\n }\n\n const message: RequestWifiSetup = {\n type: AppToCloudMessageType.REQUEST_WIFI_SETUP,\n packageName: this.config.packageName,\n sessionId: this.sessionId || \"\",\n reason,\n timestamp: new Date(),\n };\n\n this.send(message);\n }\n\n /**\n * 👂 Listen for glasses connection state changes (includes WiFi status)\n * @param handler Callback function to handle connection state updates\n * @returns Cleanup function to remove the listener\n */\n onGlassesConnectionState(handler: (state: any) => void): () => void {\n return this.events.on(StreamType.GLASSES_CONNECTION_STATE, handler);\n }\n\n // =====================================\n // 🔧 Private Methods\n // =====================================\n\n /**\n * 📨 Handle incoming messages from cloud\n */\n private handleMessage(message: CloudToAppMessage): void {\n try {\n // Validate message before processing\n if (!this.validateMessage(message)) {\n this.events.emit(\"error\", new Error(\"Invalid message format received\"));\n return;\n }\n\n // Handle binary data (audio or video)\n if (message instanceof ArrayBuffer) {\n this.handleBinaryMessage(message);\n return;\n }\n\n // Using type guards to determine message type and safely handle each case\n try {\n if (isAppConnectionAck(message)) {\n // Get settings from connection acknowledgment\n const receivedSettings = message.settings || [];\n this.settingsData = receivedSettings;\n\n // Store config if provided\n if (message.config && validateAppConfig(message.config)) {\n this.appConfig = message.config;\n }\n\n // Use default settings from config if no settings were provided\n if (receivedSettings.length === 0 && this.appConfig) {\n try {\n this.settingsData = this.getDefaultSettings();\n } catch (error) {\n this.logger.warn(error, \"Failed to load default settings from config:\");\n }\n }\n\n // Update the settings manager with the new settings\n this.settings.updateSettings(this.settingsData);\n\n // Handle MentraOS system settings if provided\n this.logger.debug(\n { mentraosSettings: JSON.stringify(message.mentraosSettings) },\n `[AppSession] CONNECTION_ACK mentraosSettings}`,\n );\n if (message.mentraosSettings) {\n this.logger.info(\n { mentraosSettings: JSON.stringify(message.mentraosSettings) },\n `[AppSession] Calling updatementraosSettings with`,\n );\n this.settings.updateMentraosSettings(message.mentraosSettings);\n } else {\n this.logger.warn(`[AppSession] CONNECTION_ACK message missing mentraosSettings field`);\n }\n\n // Handle device capabilities if provided\n if (message.capabilities) {\n this.capabilities = message.capabilities;\n this.logger.info(`[AppSession] Device capabilities loaded for model: ${message.capabilities.modelName}`);\n } else {\n this.logger.debug(`[AppSession] No capabilities provided in CONNECTION_ACK`);\n }\n\n // Emit connected event with settings\n this.events.emit(\"connected\", this.settingsData);\n\n // Log once to confirm Bug 007 fix is active (subscriptions derived from handlers)\n const handlerCount = this.events.getRegisteredStreams().length;\n this.logger.info(\n { patch: SDK_SUBSCRIPTION_PATCH, handlerCount },\n `[AppSession] 🔧 SDK Patch Active: ${SDK_SUBSCRIPTION_PATCH} - Subscriptions derived from ${handlerCount} handler(s)`,\n );\n\n // Update subscriptions (normal flow)\n this.updateSubscriptions();\n\n // If settings-based subscriptions are enabled, update those too\n if (this.shouldUpdateSubscriptionsOnSettingsChange && this.settingsData.length > 0) {\n this.updateSubscriptionsFromSettings();\n }\n } else if (isAppConnectionError(message) || message.type === \"connection_error\") {\n // Handle both App-specific connection_error and standard connection_error\n const errorMessage = message.message || \"Unknown connection error\";\n this.events.emit(\"error\", new Error(errorMessage));\n } else if (message.type === StreamType.AUDIO_CHUNK) {\n // Check if we have a handler registered for AUDIO_CHUNK (derived from handlers)\n const hasAudioHandler = this.events.getRegisteredStreams().includes(StreamType.AUDIO_CHUNK);\n if (hasAudioHandler) {\n // Only process if we're subscribed to avoid unnecessary processing\n this.events.emit(StreamType.AUDIO_CHUNK, message);\n }\n } else if (isDataStream(message) && message.streamType === StreamType.GLASSES_CONNECTION_STATE) {\n // Store latest glasses connection state (includes WiFi info)\n this.glassesConnectionState = message.data;\n\n // Emit to subscribed listeners (check derived from handlers)\n const hasGlassesStateHandler = this.events\n .getRegisteredStreams()\n .includes(StreamType.GLASSES_CONNECTION_STATE);\n if (hasGlassesStateHandler) {\n const sanitizedData = this.sanitizeEventData(\n StreamType.GLASSES_CONNECTION_STATE,\n message.data,\n ) as EventData<typeof StreamType.GLASSES_CONNECTION_STATE>;\n this.events.emit(StreamType.GLASSES_CONNECTION_STATE, sanitizedData);\n }\n } else if (isDataStream(message)) {\n // Ensure streamType exists before emitting the event\n const messageStreamType = message.streamType as ExtendedStreamType;\n // if (message.streamType === StreamType.TRANSCRIPTION) {\n // const transcriptionData = message.data as TranscriptionData;\n // if (transcriptionData.transcribeLanguage) {\n // messageStreamType = createTranscriptionStream(transcriptionData.transcribeLanguage) as ExtendedStreamType;\n // }\n // } else if (message.streamType === StreamType.TRANSLATION) {\n // const translationData = message.data as TranslationData;\n // if (translationData.transcribeLanguage && translationData.translateLanguage) {\n // messageStreamType = createTranslationStream(translationData.transcribeLanguage, translationData.translateLanguage) as ExtendedStreamType;\n // }\n // }\n\n // Check if we have a handler registered for this stream type (derived from handlers)\n const hasHandler = this.events.getRegisteredStreams().includes(messageStreamType);\n if (messageStreamType && hasHandler) {\n const sanitizedData = this.sanitizeEventData(messageStreamType, message.data) as EventData<\n typeof messageStreamType\n >;\n this.events.emit(messageStreamType, sanitizedData);\n }\n } else if (isRtmpStreamStatus(message)) {\n // Emit as a standard stream event if subscribed (check derived from handlers)\n const hasRtmpHandler = this.events.getRegisteredStreams().includes(StreamType.RTMP_STREAM_STATUS);\n if (hasRtmpHandler) {\n this.events.emit(StreamType.RTMP_STREAM_STATUS, message);\n }\n\n // Update camera module's internal stream state\n this.camera.updateStreamState(message);\n } else if (isManagedStreamStatus(message)) {\n // Emit as a standard stream event if subscribed (check derived from handlers)\n const hasManagedStreamHandler = this.events.getRegisteredStreams().includes(StreamType.MANAGED_STREAM_STATUS);\n if (hasManagedStreamHandler) {\n this.events.emit(StreamType.MANAGED_STREAM_STATUS, message);\n }\n\n // Update camera module's managed stream state\n this.camera.handleManagedStreamStatus(message);\n } else if (isStreamStatusCheckResponse(message)) {\n // Handle stream status check response\n // This is a direct response, not a subscription-based event\n this.camera.handleStreamCheckResponse(message);\n } else if (isSettingsUpdate(message)) {\n // Store previous settings to check for changes\n const _prevSettings = [...this.settingsData];\n\n // Update internal settings storage\n this.settingsData = message.settings || [];\n\n // Update the settings manager with the new settings\n const changes = this.settings.updateSettings(this.settingsData);\n\n // Emit settings update event (for backwards compatibility)\n this.events.emit(\"settings_update\", this.settingsData);\n\n // --- MentraOS settings update logic ---\n // If the message.settings looks like MentraOS settings (object with known keys), update mentraosSettings\n if (message.settings && typeof message.settings === \"object\") {\n this.settings.updateMentraosSettings(message.settings);\n }\n\n // Check if we should update subscriptions\n if (this.shouldUpdateSubscriptionsOnSettingsChange) {\n // Check if any subscription trigger settings changed\n const shouldUpdateSubs = this.subscriptionUpdateTriggers.some((key) => {\n return key in changes;\n });\n\n if (shouldUpdateSubs) {\n this.updateSubscriptionsFromSettings();\n }\n }\n } else if (isCapabilitiesUpdate(message)) {\n // Update device capabilities\n const capabilitiesMessage = message as CapabilitiesUpdate;\n this.capabilities = capabilitiesMessage.capabilities;\n this.logger.info(\n capabilitiesMessage.capabilities,\n `[AppSession] Capabilities updated for model: ${capabilitiesMessage.modelName}`,\n );\n\n // Emit capabilities update event for applications to handle\n this.events.emit(\"capabilities_update\", {\n capabilities: capabilitiesMessage.capabilities,\n modelName: capabilitiesMessage.modelName,\n timestamp: capabilitiesMessage.timestamp,\n });\n } else if (isDeviceStateUpdate(message)) {\n // Update device state observables\n this.device.state.updateFromMessage(message.state);\n\n this.logger.debug(\n {\n changedFields: Object.keys(message.state),\n fullSnapshot: message.fullSnapshot,\n },\n `[AppSession] Device state updated via WebSocket`,\n );\n } else if (isAppStopped(message)) {\n const reason = message.reason || \"unknown\";\n const displayReason = `App stopped: ${reason}`;\n\n // Don't emit disconnected event here - let the WebSocket close handler do it\n // This prevents duplicate disconnected events when the session is disposed\n this.logger.info(`📤 [${this.config.packageName}] Received APP_STOPPED message: ${displayReason}`);\n\n // Clear reconnection state\n this.reconnectAttempts = 0;\n }\n // Handle dashboard mode changes\n else if (isDashboardModeChanged(message)) {\n try {\n // Use proper type\n const mode = message.mode || \"none\";\n\n // Update dashboard state in the API\n if (this.dashboard && \"content\" in this.dashboard) {\n (this.dashboard.content as any).setCurrentMode(mode);\n }\n } catch (error) {\n this.logger.error(error, \"Error handling dashboard mode change\");\n }\n }\n // Handle always-on dashboard state changes\n else if (isDashboardAlwaysOnChanged(message)) {\n try {\n // Use proper type\n const enabled = !!message.enabled;\n\n // Update dashboard state in the API\n if (this.dashboard && \"content\" in this.dashboard) {\n (this.dashboard.content as any).setAlwaysOnEnabled(enabled);\n }\n } catch (error) {\n this.logger.error(error, \"Error handling dashboard always-on change\");\n }\n }\n // Handle custom messages\n else if (message.type === CloudToAppMessageType.CUSTOM_MESSAGE) {\n this.events.emit(\"custom_message\", message);\n return;\n }\n // Handle App-to-App communication messages\n else if ((message as any).type === \"app_message_received\") {\n this.appEvents.emit(\"app_message_received\", message as any);\n } else if ((message as any).type === \"app_user_joined\") {\n this.appEvents.emit(\"app_user_joined\", message as any);\n } else if ((message as any).type === \"app_user_left\") {\n this.appEvents.emit(\"app_user_left\", message as any);\n } else if ((message as any).type === \"app_room_updated\") {\n this.appEvents.emit(\"app_room_updated\", message as any);\n } else if ((message as any).type === \"app_direct_message_response\") {\n const response = message as any;\n if (response.messageId && this.pendingDirectMessages.has(response.messageId)) {\n const { resolve } = this.pendingDirectMessages.get(response.messageId)!;\n resolve(response.success);\n this.pendingDirectMessages.delete(response.messageId);\n }\n } else if (message.type === \"augmentos_settings_update\") {\n const mentraosMsg = message as MentraosSettingsUpdate;\n if (mentraosMsg.settings && typeof mentraosMsg.settings === \"object\") {\n this.settings.updateMentraosSettings(mentraosMsg.settings);\n }\n }\n // Handle 'connection_error' as a specific case if cloud sends this string literal\n else if ((message as any).type === \"connection_error\") {\n // Treat 'connection_error' (string literal) like AppConnectionError\n // This handles cases where the cloud might send the type as a direct string\n // instead of the enum's 'tpa_connection_error' value.\n const errorMessage = (message as any).message || \"Unknown connection error (type: connection_error)\";\n this.logger.warn(\n `Received 'connection_error' type directly. Consider aligning cloud to send 'tpa_connection_error'. Message: ${errorMessage}`,\n );\n this.events.emit(\"error\", new Error(errorMessage));\n } else if (message.type === \"permission_error\") {\n // Handle permission errors from cloud\n this.logger.warn(\n {\n message: message.message,\n details: message.details,\n detailsCount: message.details?.length || 0,\n rejectedStreams: message.details?.map((d) => d.stream) || [],\n },\n \"Permission error received:\",\n );\n\n // Emit permission error event for application handling\n this.events.emit(\"permission_error\", {\n message: message.message,\n details: message.details,\n timestamp: message.timestamp,\n });\n\n // Optionally emit individual permission denied events for each stream\n message.details?.forEach((detail) => {\n this.events.emit(\"permission_denied\", {\n stream: detail.stream,\n requiredPermission: detail.requiredPermission,\n message: detail.message,\n });\n });\n } else if (isAudioPlayResponse(message)) {\n // Delegate audio play response handling to the audio module\n if (this.audio) {\n this.audio.handleAudioPlayResponse(message as AudioPlayResponse);\n }\n } else if (isPhotoResponse(message)) {\n // Legacy photo response handling - now photos come directly via webhook\n // This branch can be removed in the future as all photos now go through /photo-upload\n this.logger.warn(\n { message },\n \"Received legacy photo response - photos should now come via /photo-upload webhook\",\n );\n } else if (isRgbLedControlResponse(message)) {\n // LED control responses are no longer handled - fire-and-forget mode\n this.logger.debug({ message }, \"Received LED control response (ignored - fire-and-forget mode)\");\n }\n // Handle unrecognized message types gracefully\n else {\n this.logger.warn(`Unrecognized message type: ${(message as any).type}`);\n this.events.emit(\"error\", new Error(`Unrecognized message type: ${(message as any).type}`));\n }\n } catch (processingError: unknown) {\n // Catch any errors during message processing to prevent App crashes\n this.logger.error(processingError, \"Error processing message:\");\n const errorMessage = processingError instanceof Error ? processingError.message : String(processingError);\n this.events.emit(\"error\", new Error(`Error processing message: ${errorMessage}`));\n }\n } catch (error: unknown) {\n // Final safety net to ensure the App doesn't crash on any unexpected errors\n this.logger.error(error, \"Unexpected error in message handler\");\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.events.emit(\"error\", new Error(`Unexpected error in message handler: ${errorMessage}`));\n }\n }\n\n /**\n * 🧪 Validate incoming message structure\n * @param message - Message to validate\n * @returns boolean indicating if the message is valid\n */\n private validateMessage(message: CloudToAppMessage): boolean {\n // Handle ArrayBuffer case separately\n if (message instanceof ArrayBuffer) {\n return true; // ArrayBuffers are always considered valid at this level\n }\n\n // Check if message is null or undefined\n if (!message) {\n return false;\n }\n\n // Check if message has a type property\n if (!(\"type\" in message)) {\n return false;\n }\n\n // All other message types should be objects with a type property\n return true;\n }\n\n /**\n * 📦 Handle binary message data (audio or video)\n * @param buffer - Binary data as ArrayBuffer\n */\n private handleBinaryMessage(buffer: ArrayBuffer): void {\n try {\n // Safety check - only process if we have a handler registered (derived from handlers)\n const hasAudioHandler = this.events.getRegisteredStreams().includes(StreamType.AUDIO_CHUNK);\n if (!hasAudioHandler) {\n return;\n }\n\n // Validate buffer has content before processing\n if (!buffer || buffer.byteLength === 0) {\n this.events.emit(\"error\", new Error(\"Received empty binary message\"));\n return;\n }\n\n // Create a safety wrapped audio chunk with proper defaults\n const audioChunk: AudioChunk = {\n type: StreamType.AUDIO_CHUNK,\n timestamp: new Date(),\n arrayBuffer: buffer,\n sampleRate: 16000, // Default sample rate\n };\n\n // Emit to subscribers\n this.events.emit(StreamType.AUDIO_CHUNK, audioChunk);\n } catch (error: unknown) {\n this.logger.error(error, \"Error processing binary message\");\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.events.emit(\"error\", new Error(`Error processing binary message: ${errorMessage}`));\n }\n }\n\n /**\n * 🧹 Sanitize event data to prevent crashes from malformed data\n * @param streamType - The type of stream data\n * @param data - The potentially unsafe data to sanitize\n * @returns Sanitized data safe for processing\n */\n private sanitizeEventData(streamType: ExtendedStreamType, data: unknown): any {\n try {\n // If data is null or undefined, return an empty object to prevent crashes\n if (data === null || data === undefined) {\n return {};\n }\n\n // For specific stream types, perform targeted sanitization\n switch (streamType) {\n case StreamType.TRANSCRIPTION: {\n // Ensure text field exists and is a string\n if (typeof (data as TranscriptionData).text !== \"string\") {\n return {\n text: \"\",\n isFinal: true,\n startTime: Date.now(),\n endTime: Date.now(),\n };\n }\n break;\n }\n\n case StreamType.HEAD_POSITION: {\n // Ensure position data has required numeric fields\n // Handle HeadPosition - Note the property position instead of x,y,z\n const pos = data as any;\n if (typeof pos?.position !== \"string\") {\n return { position: \"up\", timestamp: new Date() };\n }\n break;\n }\n\n case StreamType.BUTTON_PRESS: {\n // Ensure button type is valid\n const btn = data as any;\n if (!btn.buttonId || !btn.pressType) {\n return {\n buttonId: \"unknown\",\n pressType: \"short\",\n timestamp: new Date(),\n };\n }\n break;\n }\n }\n\n return data;\n } catch (error: unknown) {\n this.logger.error(error, `Error sanitizing ${streamType} data`);\n // Return a safe empty object if something goes wrong\n return {};\n }\n }\n\n /**\n * 🔐 Send connection initialization message\n */\n private sendConnectionInit(): void {\n const message: AppConnectionInit = {\n type: AppToCloudMessageType.CONNECTION_INIT,\n sessionId: this.sessionId!,\n packageName: this.config.packageName,\n apiKey: this.config.apiKey,\n timestamp: new Date(),\n };\n this.send(message);\n }\n\n /**\n * 📝 Update subscription list with cloud\n */\n private updateSubscriptions(): void {\n // CRITICAL FIX (Bug 007): Derive subscriptions from EventManager.handlers\n // This ensures subscriptions can NEVER be empty if handlers exist\n // Previously, this.subscriptions could drift out of sync with handlers\n // See: cloud/issues/006-captions-and-apps-stopping/011-sdk-subscription-architecture-mismatch.md\n const derivedSubscriptions = this.events.getRegisteredStreams();\n\n this.logger.info(\n { subscriptions: JSON.stringify(derivedSubscriptions) },\n `[AppSession] updateSubscriptions: sending ${derivedSubscriptions.length} subscriptions to cloud (derived from handlers)`,\n );\n\n // Build the array of SubscriptionRequest objects to send to the cloud\n const subscriptionPayload: SubscriptionRequest[] = derivedSubscriptions.map((stream) => {\n const rate = this.streamRates.get(stream);\n if (rate && stream === StreamType.LOCATION_STREAM) {\n return { stream: \"location_stream\", rate: rate as any };\n }\n return stream;\n });\n\n const message: AppSubscriptionUpdate = {\n type: AppToCloudMessageType.SUBSCRIPTION_UPDATE,\n packageName: this.config.packageName,\n subscriptions: subscriptionPayload,\n sessionId: this.sessionId!,\n timestamp: new Date(),\n };\n this.send(message);\n }\n\n /**\n * 🔄 Handle reconnection with exponential backoff\n */\n private async handleReconnection(): Promise<void> {\n // Check if session was terminated (e.g., \"User session ended\")\n if (this.terminated) {\n this.logger.info(\n `🔄 Reconnection skipped: session was terminated (User session ended). ` +\n `If cloud restarts app, onSession will be called with fresh handlers.`,\n );\n return;\n }\n\n // Check if reconnection is allowed\n if (!this.config.autoReconnect || !this.sessionId) {\n this.logger.debug(\n `🔄 Reconnection skipped: autoReconnect=${this.config.autoReconnect}, sessionId=${\n this.sessionId ? \"valid\" : \"invalid\"\n }`,\n );\n return;\n }\n\n // Check if we've exceeded the maximum attempts\n const maxAttempts = this.config.maxReconnectAttempts || 3;\n if (this.reconnectAttempts >= maxAttempts) {\n this.logger.info(`🔄 Maximum reconnection attempts (${maxAttempts}) reached, giving up`);\n\n // Emit a permanent disconnection event to trigger onStop in the App server\n this.events.emit(\"disconnected\", {\n message: `Connection permanently lost after ${maxAttempts} failed reconnection attempts`,\n code: 4000, // Custom code for max reconnection attempts exhausted\n reason: \"Maximum reconnection attempts exceeded\",\n wasClean: false,\n permanent: true, // Flag this as a permanent disconnection\n });\n\n return;\n }\n\n // Calculate delay with exponential backoff\n const baseDelay = this.config.reconnectDelay || 1000;\n const delay = baseDelay * Math.pow(2, this.reconnectAttempts);\n this.reconnectAttempts++;\n\n this.logger.debug(\n `🔄 [${this.config.packageName}] Reconnection attempt ${this.reconnectAttempts}/${maxAttempts} in ${delay}ms`,\n );\n\n // Use the resource tracker for the timeout\n await new Promise<void>((resolve) => {\n this.resources.setTimeout(() => resolve(), delay);\n });\n\n try {\n this.logger.debug(`🔄 [${this.config.packageName}] Attempting to reconnect...`);\n await this.connect(this.sessionId);\n this.logger.debug(`✅ [${this.config.packageName}] Reconnection successful!`);\n this.reconnectAttempts = 0;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n this.logger.error(error, `❌ [${this.config.packageName}] Reconnection failed for user ${this.userId}`);\n this.events.emit(\"error\", new Error(`Reconnection failed: ${errorMessage}`));\n\n // Check if this was the last attempt\n if (this.reconnectAttempts >= maxAttempts) {\n this.logger.debug(\n `🔄 [${this.config.packageName}] Final reconnection attempt failed, emitting permanent disconnection`,\n );\n\n // Emit permanent disconnection event after the last failed attempt\n this.events.emit(\"disconnected\", {\n message: `Connection permanently lost after ${maxAttempts} failed reconnection attempts`,\n code: 4000, // Custom code for max reconnection attempts exhausted\n reason: \"Maximum reconnection attempts exceeded\",\n wasClean: false,\n permanent: true, // Flag this as a permanent disconnection\n });\n }\n }\n }\n\n /**\n * 📤 Public API for modules to send messages\n * Always uses current WebSocket connection\n */\n public sendMessage(message: AppToCloudMessage): void {\n return this.send(message);\n }\n\n /**\n * 📤 Send message to cloud with validation and error handling\n * @throws {Error} If WebSocket is not connected\n */\n private send(message: AppToCloudMessage): void {\n try {\n // Verify WebSocket connection is valid\n if (!this.ws) {\n throw new Error(\"WebSocket connection not established\");\n }\n\n if (this.ws.readyState !== 1) {\n const stateMap: Record<number, string> = {\n 0: \"CONNECTING\",\n 1: \"OPEN\",\n 2: \"CLOSING\",\n 3: \"CLOSED\",\n };\n const stateName = stateMap[this.ws.readyState] || \"UNKNOWN\";\n throw new Error(`WebSocket not connected (current state: ${stateName})`);\n }\n\n // Validate message before sending\n if (!message || typeof message !== \"object\") {\n throw new Error(\"Invalid message: must be an object\");\n }\n\n if (!(\"type\" in message)) {\n throw new Error('Invalid message: missing \"type\" property');\n }\n\n // Ensure message format is consistent\n if (!(\"timestamp\" in message) || !(message.timestamp instanceof Date)) {\n message.timestamp = new Date();\n }\n\n // Try to send with error handling\n try {\n const serializedMessage = JSON.stringify(message);\n this.ws.send(serializedMessage);\n } catch (sendError: unknown) {\n const errorMessage = sendError instanceof Error ? sendError.message : String(sendError);\n throw new Error(`Failed to send message: ${errorMessage}`);\n }\n } catch (error: unknown) {\n // Check if this is an expected disconnection error (not a real error)\n const isDisconnectError =\n error instanceof Error &&\n (error.message.includes(\"WebSocket not connected\") ||\n error.message.includes(\"CLOSED\") ||\n error.message.includes(\"CLOSING\"));\n\n if (isDisconnectError) {\n // Don't log as error - this is expected when user disconnects\n // Apps should handle this gracefully by checking session.isConnected\n this.logger.debug(error, \"Message send skipped - session disconnected\");\n } else {\n // This is an actual error that needs attention\n this.logger.error(error, \"Message send error\");\n }\n\n // Ensure we always emit an Error object\n if (error instanceof Error) {\n this.events.emit(\"error\", error);\n } else {\n this.events.emit(\"error\", new Error(String(error)));\n }\n\n // Re-throw to maintain the original function behavior\n throw error;\n }\n }\n\n /**\n * Fetch the onboarding instructions for this session from the backend.\n * @returns Promise resolving to the instructions string or null\n */\n public async getInstructions(): Promise<string | null> {\n try {\n const baseUrl = this.getServerUrl();\n const response = await axios.get(`${baseUrl}/api/instructions`, {\n params: { userId: this.userId },\n });\n return response.data.instructions || null;\n } catch (err) {\n this.logger.error(err, `Error fetching instructions from backend`);\n return null;\n }\n }\n // =====================================\n // 👥 App-to-App Communication Interface\n // =====================================\n\n /**\n * 👥 Discover other users currently using the same App\n * @param includeProfiles - Whether to include user profile information\n * @returns Promise that resolves with list of active users\n */\n async discoverAppUsers(domain: string, includeProfiles = false): Promise<any> {\n // Use the domain argument as the base URL if provided\n if (!domain) {\n throw new Error(\"Domain (API base URL) is required for user discovery\");\n }\n const url = `${domain}/api/app-communication/discover-users`;\n // Use the user's core token for authentication\n const appApiKey = this.config.apiKey; // This may need to be updated if you store the core token elsewhere\n\n if (!appApiKey) {\n throw new Error(\"Core token (apiKey) is required for user discovery\");\n }\n const body = {\n packageName: this.config.packageName,\n userId: this.userId,\n includeUserProfiles: includeProfiles,\n };\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${appApiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Failed to discover users: ${response.status} ${response.statusText} - ${errorText}`);\n }\n return await response.json();\n }\n\n /**\n * 🔍 Check if a specific user is currently active\n * @param userId - User ID to check for\n * @returns Promise that resolves with boolean indicating if user is active\n */\n async isUserActive(userId: string): Promise<boolean> {\n try {\n const userList = await this.discoverAppUsers(\"\", false);\n return userList.users.some((user: any) => user.userId === userId);\n } catch (error) {\n this.logger.error({ error, userId }, \"Error checking if user is active\");\n return false;\n }\n }\n\n /**\n * 📊 Get user count for this App\n * @returns Promise that resolves with number of active users\n */\n async getUserCount(domain: string): Promise<number> {\n try {\n const userList = await this.discoverAppUsers(domain, false);\n return userList.totalUsers;\n } catch (error) {\n this.logger.error(error, \"Error getting user count\");\n return 0;\n }\n }\n\n /**\n * 📢 Send broadcast message to all users with same App active\n * @param payload - Message payload to send\n * @param roomId - Optional room ID for room-based messaging\n * @returns Promise that resolves when message is sent\n */\n async broadcastToAppUsers(payload: any, _roomId?: string): Promise<void> {\n try {\n const messageId = this.generateMessageId();\n\n const message = {\n type: \"app_broadcast_message\",\n packageName: this.config.packageName,\n sessionId: this.sessionId!,\n payload,\n messageId,\n senderUserId: this.userId,\n timestamp: new Date(),\n };\n\n this.send(message as any);\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to broadcast message: ${errorMessage}`);\n }\n }\n\n /**\n * 📤 Send direct message to specific user\n * @param targetUserId - User ID to send message to\n * @param payload - Message payload to send\n * @returns Promise that resolves with success status\n */\n async sendDirectMessage(targetUserId: string, payload: any): Promise<boolean> {\n return new Promise((resolve, reject) => {\n try {\n const messageId = this.generateMessageId();\n\n // Store promise resolver\n this.pendingDirectMessages.set(messageId, { resolve, reject });\n\n const message = {\n type: \"app_direct_message\",\n packageName: this.config.packageName,\n sessionId: this.sessionId!,\n targetUserId,\n payload,\n messageId,\n senderUserId: this.userId,\n timestamp: new Date(),\n };\n\n this.send(message as any);\n\n // Set timeout to avoid hanging promises\n const timeoutMs = 15000; // 15 seconds\n this.resources.setTimeout(() => {\n if (this.pendingDirectMessages.has(messageId)) {\n this.pendingDirectMessages.get(messageId)!.reject(new Error(\"Direct message timed out\"));\n this.pendingDirectMessages.delete(messageId);\n }\n }, timeoutMs);\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n reject(new Error(`Failed to send direct message: ${errorMessage}`));\n }\n });\n }\n\n /**\n * 🏠 Join a communication room for group messaging\n * @param roomId - Room ID to join\n * @param roomConfig - Optional room configuration\n * @returns Promise that resolves when room is joined\n */\n async joinAppRoom(\n roomId: string,\n roomConfig?: {\n maxUsers?: number;\n isPrivate?: boolean;\n metadata?: any;\n },\n ): Promise<void> {\n try {\n const message = {\n type: \"app_room_join\",\n packageName: this.config.packageName,\n sessionId: this.sessionId!,\n roomId,\n roomConfig,\n timestamp: new Date(),\n };\n\n this.send(message as any);\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to join room: ${errorMessage}`);\n }\n }\n\n /**\n * 🚪 Leave a communication room\n * @param roomId - Room ID to leave\n * @returns Promise that resolves when room is left\n */\n async leaveAppRoom(roomId: string): Promise<void> {\n try {\n const message = {\n type: \"app_room_leave\",\n packageName: this.config.packageName,\n sessionId: this.sessionId!,\n roomId,\n timestamp: new Date(),\n };\n\n this.send(message as any);\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to leave room: ${errorMessage}`);\n }\n }\n\n /**\n * 📨 Listen for messages from other App users\n * @param handler - Function to handle incoming messages\n * @returns Cleanup function to remove the handler\n */\n onAppMessage(handler: (message: any) => void): () => void {\n this.appEvents.on(\"app_message_received\", handler);\n return () => this.appEvents.off(\"app_message_received\", handler);\n }\n\n /**\n * 👋 Listen for user join events\n * @param handler - Function to handle user join events\n * @returns Cleanup function to remove the handler\n */\n onAppUserJoined(handler: (data: any) => void): () => void {\n this.appEvents.on(\"app_user_joined\", handler);\n return () => this.appEvents.off(\"app_user_joined\", handler);\n }\n\n /**\n * 🚪 Listen for user leave events\n * @param handler - Function to handle user leave events\n * @returns Cleanup function to remove the handler\n */\n onAppUserLeft(handler: (data: any) => void): () => void {\n this.appEvents.on(\"app_user_left\", handler);\n return () => this.appEvents.off(\"app_user_left\", handler);\n }\n\n /**\n * 🏠 Listen for room update events\n * @param handler - Function to handle room updates\n * @returns Cleanup function to remove the handler\n */\n onAppRoomUpdated(handler: (data: any) => void): () => void {\n this.appEvents.on(\"app_room_updated\", handler);\n return () => this.appEvents.off(\"app_room_updated\", handler);\n }\n\n /**\n * 🔧 Generate unique message ID\n * @returns Unique message identifier\n */\n private generateMessageId(): string {\n return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n }\n}\n\n/**\n * @deprecated Use `AppSessionConfig` instead. `TpaSessionConfig` is deprecated and will be removed in a future version.\n * This is an alias for backward compatibility only.\n *\n * @example\n * ```typescript\n * // ❌ Deprecated - Don't use this\n * const config: TpaSessionConfig = { ... };\n *\n * // ✅ Use this instead\n * const config: AppSessionConfig = { ... };\n * ```\n */\nexport type TpaSessionConfig = AppSessionConfig;\n\n/**\n * @deprecated Use `AppSession` instead. `TpaSession` is deprecated and will be removed in a future version.\n * This is an alias for backward compatibility only.\n *\n * @example\n * ```typescript\n * // ❌ Deprecated - Don't use this\n * const session = new TpaSession(config);\n *\n * // ✅ Use this instead\n * const session = new AppSession(config);\n * ```\n */\nexport class TpaSession extends AppSession {\n constructor(config: TpaSessionConfig) {\n super(config);\n // Emit a deprecation warning to help developers migrate\n console.warn(\n \"⚠️ DEPRECATION WARNING: TpaSession is deprecated and will be removed in a future version. \" +\n \"Please use AppSession instead. \" +\n 'Simply replace \"TpaSession\" with \"AppSession\" in your code.',\n );\n }\n}\n\n// Export module types for developers\nexport { CameraModule, PhotoRequestOptions, RtmpStreamOptions } from \"./modules/camera\";\nexport { LedModule, LedControlOptions } from \"./modules/led\";\nexport { AudioManager, AudioPlayOptions, AudioPlayResult, SpeakOptions } from \"./modules/audio\";\nexport { SimpleStorage } from \"./modules/simple-storage\";\n",
22
+ "/**\n * 🎮 Event Manager Module\n */\nimport EventEmitter from \"events\"\nimport {\n StreamType,\n ExtendedStreamType,\n AppSettings,\n WebSocketError,\n // Event data types\n ButtonPress,\n HeadPosition,\n PhoneNotification,\n TranscriptionData,\n TranslationData,\n GlassesBatteryUpdate,\n PhoneBatteryUpdate,\n GlassesConnectionState,\n LocationUpdate,\n Vad,\n AudioChunk,\n CalendarEvent,\n VpsCoordinates,\n // Language stream helpers\n createTranscriptionStream,\n isValidLanguageCode,\n createTranslationStream,\n CustomMessage,\n RtmpStreamStatus,\n PhotoTaken,\n ManagedStreamStatus,\n PhoneNotificationDismissed,\n Capabilities,\n TouchEvent,\n createTouchEventStream,\n} from \"../../types\"\nimport {DashboardMode} from \"../../types/dashboard\"\nimport {PermissionErrorDetail} from \"../../types/messages/cloud-to-app\"\nimport {calendarWarnLog, microPhoneWarnLog} from \"../../utils/permissions-utils\"\n\n/** 🎯 Type-safe event handler function */\ntype Handler<T> = (data: T) => void\n\n/** 🔄 System events not tied to streams */\ninterface SystemEvents {\n connected: AppSettings | undefined\n disconnected:\n | string\n | {\n message: string // Human-readable close message\n code: number // WebSocket close code (1000 = normal)\n reason: string // Reason provided by server\n wasClean: boolean // Whether this was a clean closure\n permanent?: boolean // Whether this is a permanent disconnection (no more reconnection attempts)\n sessionEnded?: boolean // Whether this disconnection is due to user session ending\n }\n error: WebSocketError | Error\n settings_update: AppSettings\n capabilities_update: {\n capabilities: Capabilities | null\n modelName: string | null\n timestamp?: Date\n }\n dashboard_mode_change: {mode: DashboardMode | \"none\"}\n dashboard_always_on_change: {enabled: boolean}\n custom_message: CustomMessage\n permission_error: {\n message: string\n details: PermissionErrorDetail[]\n timestamp?: Date\n }\n permission_denied: {\n stream: string\n requiredPermission: string\n message: string\n }\n}\n\n/** 📡 All possible event types */\ntype EventType = ExtendedStreamType | keyof SystemEvents\n\n/** 📦 Map of stream types to their data types */\nexport interface StreamDataTypes {\n [StreamType.BUTTON_PRESS]: ButtonPress\n [StreamType.HEAD_POSITION]: HeadPosition\n [StreamType.PHONE_NOTIFICATION]: PhoneNotification\n [StreamType.TRANSCRIPTION]: TranscriptionData\n [StreamType.TRANSLATION]: TranslationData\n [StreamType.GLASSES_BATTERY_UPDATE]: GlassesBatteryUpdate\n [StreamType.PHONE_BATTERY_UPDATE]: PhoneBatteryUpdate\n [StreamType.GLASSES_CONNECTION_STATE]: GlassesConnectionState\n [StreamType.LOCATION_UPDATE]: LocationUpdate\n [StreamType.CALENDAR_EVENT]: CalendarEvent\n [StreamType.VAD]: Vad\n [StreamType.PHONE_NOTIFICATION_DISMISSED]: PhoneNotificationDismissed\n [StreamType.AUDIO_CHUNK]: AudioChunk\n [StreamType.VIDEO]: ArrayBuffer\n [StreamType.RTMP_STREAM_STATUS]: RtmpStreamStatus\n [StreamType.MANAGED_STREAM_STATUS]: ManagedStreamStatus\n [StreamType.VPS_COORDINATES]: VpsCoordinates\n [StreamType.PHOTO_TAKEN]: PhotoTaken\n [StreamType.OPEN_DASHBOARD]: never\n [StreamType.START_APP]: never\n [StreamType.STOP_APP]: never\n [StreamType.ALL]: never\n [StreamType.WILDCARD]: never\n}\n\n/** 📦 Data type for an event */\nexport type EventData<T extends EventType> = T extends keyof StreamDataTypes\n ? StreamDataTypes[T]\n : T extends keyof SystemEvents\n ? SystemEvents[T]\n : T extends string\n ? T extends `${StreamType.TRANSCRIPTION}:${string}`\n ? TranscriptionData\n : T extends `${StreamType.TRANSLATION}:${string}`\n ? TranslationData\n : never\n : never\n\nexport class EventManager {\n private emitter: EventEmitter\n private handlers: Map<EventType, Set<Handler<unknown>>>\n private lastLanguageTranscriptioCleanupHandler: () => void\n private lastLanguageTranslationCleanupHandler: () => void\n\n constructor(\n private subscribe: (type: ExtendedStreamType) => void,\n private unsubscribe: (type: ExtendedStreamType) => void,\n private packageName: string,\n private baseUrl: string,\n ) {\n this.emitter = new EventEmitter()\n this.handlers = new Map()\n this.lastLanguageTranscriptioCleanupHandler = () => {}\n this.lastLanguageTranslationCleanupHandler = () => {}\n }\n\n // Convenience handlers for common event types\n\n onTranscription(handler: Handler<TranscriptionData>) {\n // Only make the API call if we have a base URL (server-side environment)\n microPhoneWarnLog(this.baseUrl, this.packageName, this.onTranscription.name)\n\n return this.addHandler(createTranscriptionStream(\"en-US\"), handler)\n }\n\n /**\n * 🎤 Listen for transcription events in a specific language\n * @param language - Language code (e.g., \"en-US\") or \"auto\" for automatic detection\n * @param handler - Function to handle transcription data\n * @param optionsOrBoolean - Optional configuration object or boolean (backward compatible)\n * @param optionsOrBoolean.disableLanguageIdentification - Disable language identification (defaults to false/enabled)\n * @param optionsOrBoolean.hints - Array of language code hints to improve detection (e.g., [\"es\", \"fr\"])\n * @returns Cleanup function to remove the handler\n * @throws Error if language code is invalid\n */\n onTranscriptionForLanguage(\n language: string,\n handler: Handler<TranscriptionData>,\n optionsOrBoolean?:\n | boolean\n | {\n disableLanguageIdentification?: boolean\n hints?: string[]\n },\n ): () => void {\n if (language !== \"auto\" && !isValidLanguageCode(language)) {\n throw new Error(`Invalid language code: ${language}`)\n }\n this.lastLanguageTranscriptioCleanupHandler()\n\n // Handle backward compatibility: boolean or options object\n const options =\n typeof optionsOrBoolean === \"boolean\" ? {disableLanguageIdentification: optionsOrBoolean} : optionsOrBoolean\n\n const streamType = createTranscriptionStream(language, options)\n this.lastLanguageTranscriptioCleanupHandler = this.addHandler(streamType, handler)\n return this.lastLanguageTranscriptioCleanupHandler\n }\n\n /**\n * 🌐 Listen for translation events for a specific language pair\n * @param sourceLanguage - Source language code (e.g., \"es-ES\")\n * @param targetLanguage - Target language code (e.g., \"en-US\")\n * @param handler - Function to handle translation data\n * @returns Cleanup function to remove the handler\n * @throws Error if language codes are invalid\n */\n ontranslationForLanguage(\n sourceLanguage: string,\n targetLanguage: string,\n handler: Handler<TranslationData>,\n ): () => void {\n microPhoneWarnLog(this.baseUrl || \"\", this.packageName, this.ontranslationForLanguage.name)\n if (!isValidLanguageCode(sourceLanguage)) {\n throw new Error(`Invalid source language code: ${sourceLanguage}`)\n }\n if (!isValidLanguageCode(targetLanguage)) {\n throw new Error(`Invalid target language code: ${targetLanguage}`)\n }\n\n this.lastLanguageTranslationCleanupHandler()\n const streamType = createTranslationStream(sourceLanguage, targetLanguage)\n this.lastLanguageTranslationCleanupHandler = this.addHandler(streamType, handler)\n\n return this.lastLanguageTranslationCleanupHandler\n }\n\n onHeadPosition(handler: Handler<HeadPosition>) {\n return this.addHandler(StreamType.HEAD_POSITION, handler)\n }\n\n onButtonPress(handler: Handler<ButtonPress>) {\n return this.addHandler(StreamType.BUTTON_PRESS, handler)\n }\n\n onTouchEvent(gestureOrHandler: string | Handler<TouchEvent>, handler?: Handler<TouchEvent>): () => void {\n // Handle both: onTouchEvent(handler) and onTouchEvent(\"forward_swipe\", handler)\n if (typeof gestureOrHandler === \"function\") {\n // Subscribe to all touch events\n return this.addHandler(StreamType.TOUCH_EVENT, gestureOrHandler)\n } else {\n // Subscribe to specific gesture\n const gestureStream = createTouchEventStream(gestureOrHandler)\n return this.addHandler(gestureStream, handler!)\n }\n }\n\n onPhoneNotifications(handler: Handler<PhoneNotification>) {\n return this.addHandler(StreamType.PHONE_NOTIFICATION, handler)\n }\n\n onPhoneNotificationDismissed(handler: Handler<PhoneNotificationDismissed>) {\n return this.addHandler(StreamType.PHONE_NOTIFICATION_DISMISSED, handler)\n }\n\n onGlassesBattery(handler: Handler<GlassesBatteryUpdate>) {\n return this.addHandler(StreamType.GLASSES_BATTERY_UPDATE, handler)\n }\n\n onPhoneBattery(handler: Handler<PhoneBatteryUpdate>) {\n return this.addHandler(StreamType.PHONE_BATTERY_UPDATE, handler)\n }\n\n onVoiceActivity(handler: Handler<Vad>) {\n microPhoneWarnLog(this.baseUrl || \"\", this.packageName, this.onVoiceActivity.name)\n return this.addHandler(StreamType.VAD, handler)\n }\n\n onLocation(handler: Handler<LocationUpdate>) {\n return this.addHandler(StreamType.LOCATION_UPDATE, handler)\n }\n\n onCalendarEvent(handler: Handler<CalendarEvent>) {\n return this.addHandler(StreamType.CALENDAR_EVENT, handler)\n }\n\n /**\n * 🎤 Listen for audio chunk data\n * @param handler - Function to handle audio chunks\n * @returns Cleanup function to remove the handler\n */\n onAudioChunk(handler: Handler<AudioChunk>) {\n return this.addHandler(StreamType.AUDIO_CHUNK, handler)\n }\n\n // System event handlers\n\n onConnected(handler: Handler<SystemEvents[\"connected\"]>) {\n this.emitter.on(\"connected\", handler)\n return () => this.emitter.off(\"connected\", handler)\n }\n\n onDisconnected(handler: Handler<SystemEvents[\"disconnected\"]>) {\n this.emitter.on(\"disconnected\", handler)\n return () => this.emitter.off(\"disconnected\", handler)\n }\n\n onError(handler: Handler<SystemEvents[\"error\"]>) {\n this.emitter.on(\"error\", handler)\n return () => this.emitter.off(\"error\", handler)\n }\n\n onSettingsUpdate(handler: Handler<SystemEvents[\"settings_update\"]>) {\n this.emitter.on(\"settings_update\", handler)\n return () => this.emitter.off(\"settings_update\", handler)\n }\n\n /**\n * 🔧 Listen for device capabilities updates\n * @param handler - Function to handle capabilities updates\n * @returns Cleanup function to remove the handler\n */\n onCapabilitiesUpdate(handler: Handler<SystemEvents[\"capabilities_update\"]>) {\n this.emitter.on(\"capabilities_update\", handler)\n return () => this.emitter.off(\"capabilities_update\", handler)\n }\n\n /**\n * 🌐 Listen for dashboard mode changes\n * @param handler - Function to handle dashboard mode changes\n * @returns Cleanup function to remove the handler\n */\n onDashboardModeChange(handler: Handler<SystemEvents[\"dashboard_mode_change\"]>) {\n this.emitter.on(\"dashboard_mode_change\", handler)\n return () => this.emitter.off(\"dashboard_mode_change\", handler)\n }\n\n /**\n * 🌐 Listen for dashboard always-on mode changes\n * @param handler - Function to handle dashboard always-on mode changes\n * @returns Cleanup function to remove the handler\n */\n onDashboardAlwaysOnChange(handler: Handler<SystemEvents[\"dashboard_always_on_change\"]>) {\n this.emitter.on(\"dashboard_always_on_change\", handler)\n return () => this.emitter.off(\"dashboard_always_on_change\", handler)\n }\n\n /**\n * 🚫 Listen for permission errors when subscriptions are rejected\n * @param handler - Function to handle permission errors\n * @returns Cleanup function to remove the handler\n */\n onPermissionError(handler: Handler<SystemEvents[\"permission_error\"]>) {\n this.emitter.on(\"permission_error\", handler)\n return () => this.emitter.off(\"permission_error\", handler)\n }\n\n /**\n * 🚫 Listen for individual permission denied events for specific streams\n * @param handler - Function to handle permission denied events\n * @returns Cleanup function to remove the handler\n */\n onPermissionDenied(handler: Handler<SystemEvents[\"permission_denied\"]>) {\n this.emitter.on(\"permission_denied\", handler)\n return () => this.emitter.off(\"permission_denied\", handler)\n }\n\n /**\n * 🔄 Listen for changes to a specific setting\n * @param key - Setting key to monitor\n * @param handler - Function to handle setting value changes\n * @returns Cleanup function to remove the handler\n */\n onSettingChange<T>(key: string, handler: (value: T, previousValue: T | undefined) => void): () => void {\n let previousValue: T | undefined = undefined\n\n const settingsHandler = (settings: AppSettings) => {\n try {\n const setting = settings.find((s) => s.key === key)\n if (setting) {\n // Only call handler if value has changed\n if (setting.value !== previousValue) {\n const newValue = setting.value as T\n handler(newValue, previousValue)\n previousValue = newValue\n }\n }\n } catch (error: unknown) {\n console.error(`Error in onSettingChange handler for key \"${key}\":`, error)\n }\n }\n\n this.emitter.on(\"settings_update\", settingsHandler)\n this.emitter.on(\"connected\", settingsHandler) // Also check when first connected\n\n return () => {\n this.emitter.off(\"settings_update\", settingsHandler)\n this.emitter.off(\"connected\", settingsHandler)\n }\n }\n\n /**\n * 🔄 Generic event handler\n *\n * Use this for stream types without specific handler methods\n */\n on<T extends ExtendedStreamType>(type: T, handler: Handler<EventData<T>>): () => void {\n // Check permissions for specific stream types\n if (type === StreamType.CALENDAR_EVENT) {\n calendarWarnLog(this.baseUrl, this.packageName, \"on\")\n }\n return this.addHandler(type, handler)\n }\n\n /**\n * ➕ Add an event handler and subscribe if needed\n */\n private addHandler<T extends ExtendedStreamType>(type: T, handler: Handler<EventData<T>>): () => void {\n const handlers = this.handlers.get(type) ?? new Set()\n\n if (handlers.size === 0) {\n this.handlers.set(type, handlers)\n this.subscribe(type)\n }\n handlers.add(handler as Handler<unknown>)\n return () => this.removeHandler(type, handler)\n }\n\n /**\n * ➖ Remove an event handler\n */\n private removeHandler<T extends ExtendedStreamType>(type: T, handler: Handler<EventData<T>>): void {\n const handlers = this.handlers.get(type)\n if (!handlers) return\n\n handlers.delete(handler as Handler<unknown>)\n if (handlers.size === 0) {\n this.handlers.delete(type)\n this.unsubscribe(type)\n }\n }\n\n /**\n * 🔍 Get all currently registered stream types\n * Returns the streams that have at least one handler registered.\n * Used to derive subscriptions from handlers (single source of truth).\n *\n * This is the fix for Bug 007: subscriptions are now derived from handlers\n * instead of being stored separately, preventing drift between the two.\n */\n getRegisteredStreams(): ExtendedStreamType[] {\n return Array.from(this.handlers.keys()) as ExtendedStreamType[]\n }\n\n /**\n * 📡 Emit an event to all registered handlers with error isolation\n */\n emit<T extends EventType>(event: T, data: EventData<T>): void {\n try {\n // Emit to EventEmitter handlers (system events)\n // console.log(`#### Emitting to ${event}`);\n this.emitter.emit(event, data)\n\n // Emit to stream handlers if applicable\n const handlers = this.handlers.get(event)\n // console.log(`#### Handlers: ${JSON.stringify(handlers)}`);\n\n if (handlers) {\n // Create array of handlers to prevent modification during iteration\n const handlersArray = Array.from(handlers)\n // console.log(`((())) HandlersArray: ${JSON.stringify(handlersArray)}`);\n\n // Execute each handler in isolated try/catch to prevent one handler\n // from crashing the entire App\n handlersArray.forEach((handler) => {\n try {\n ;(handler as Handler<EventData<T>>)(data)\n } catch (handlerError: unknown) {\n // Log the error but don't let it propagate\n console.error(`Error in handler for event '${String(event)}':`, handlerError)\n\n // Emit an error event for tracking purposes\n if (event !== \"error\") {\n // Prevent infinite recursion\n const errorMessage = handlerError instanceof Error ? handlerError.message : String(handlerError)\n\n this.emitter.emit(\"error\", new Error(`Handler error for event '${String(event)}': ${errorMessage}`))\n }\n }\n })\n }\n } catch (emitError: unknown) {\n // Catch any errors in the emission process itself\n console.error(`Fatal error emitting event '${String(event)}':`, emitError)\n\n // Try to emit an error event if we're not already handling an error\n if (event !== \"error\") {\n try {\n const errorMessage = emitError instanceof Error ? emitError.message : String(emitError)\n\n this.emitter.emit(\"error\", new Error(`Event emission error for '${String(event)}': ${errorMessage}`))\n } catch (nestedError) {\n // If even this fails, just log it - nothing more we can do\n console.error(\"Failed to emit error event:\", nestedError)\n }\n }\n }\n }\n\n /**\n * 📨 Listen for custom messages with a specific action\n * @param action - The action identifier to filter by\n * @param handler - Function to handle the message\n * @returns Cleanup function to remove the handler\n */\n onCustomMessage(action: string, handler: (payload: any) => void): () => void {\n const messageHandler = (message: CustomMessage) => {\n if (message.action === action) {\n handler(message.payload)\n }\n }\n\n this.emitter.on(\"custom_message\", messageHandler)\n return () => this.emitter.off(\"custom_message\", messageHandler)\n }\n\n onVpsCoordinates(handler: Handler<VpsCoordinates>) {\n return this.addHandler(StreamType.VPS_COORDINATES, handler)\n }\n\n /**\n * 📸 Listen for photo responses\n * @param handler - Function to handle photo response data\n * @returns Cleanup function to remove the handler\n */\n onPhotoTaken(handler: Handler<PhotoTaken>) {\n return this.addHandler(StreamType.PHOTO_TAKEN, handler)\n }\n}\n",
23
+ "// src/index.ts\n\nexport * from \"./token\"\n\n// Message type enums\nexport * from \"./message-types\"\n\n// Base message type\nexport * from \"./messages/base\"\n\n// Messages by direction - export everything except the conflicting type guards\nexport * from \"./messages/glasses-to-cloud\"\nexport * from \"./messages/cloud-to-glasses\"\n\n// Export from app-to-cloud excluding isPhotoRequest which conflicts with cloud-to-glasses\nexport {\n // Types\n SubscriptionRequest,\n AppConnectionInit,\n AppSubscriptionUpdate,\n PhotoRequest,\n RgbLedControlRequest,\n RtmpStreamRequest,\n RtmpStreamStopRequest,\n AppLocationPollRequest,\n RestreamDestination,\n ManagedStreamRequest,\n ManagedStreamStopRequest,\n StreamStatusCheckRequest,\n AudioPlayRequest,\n AudioStopRequest,\n AppToCloudMessage,\n AppBroadcastMessage,\n AppDirectMessage,\n AppUserDiscovery,\n AppRoomJoin,\n AppRoomLeave,\n RequestWifiSetup,\n OwnershipReleaseMessage,\n // Type guards - all except isPhotoRequest\n isAppConnectionInit,\n isAppSubscriptionUpdate,\n isDisplayRequest,\n isRgbLedControlRequest,\n isAudioPlayRequest,\n isAudioStopRequest,\n isDashboardContentUpdate,\n isDashboardModeChange,\n isDashboardSystemUpdate,\n isManagedStreamRequest,\n isManagedStreamStopRequest,\n isRtmpStreamRequest,\n isRtmpStreamStopRequest,\n isOwnershipRelease,\n // Export with alias to avoid conflict\n isPhotoRequest as isPhotoRequestFromApp,\n} from \"./messages/app-to-cloud\"\n\n// Export cloud-to-app but exclude the conflicting type guards\nexport {\n // Types\n AppConnectionAck,\n AppConnectionError,\n AppStopped,\n SettingsUpdate as AppSettingsUpdate, // Alias to avoid conflict with cloud-to-glasses SettingsUpdate\n CapabilitiesUpdate,\n DataStream,\n CloudToAppMessage,\n AudioPlayResponse,\n TranslationData,\n ToolCall,\n StandardConnectionError,\n CustomMessage,\n ManagedStreamStatus,\n StreamStatusCheckResponse,\n OutputStatus,\n MentraosSettingsUpdate,\n TranscriptionData,\n TranscriptionMetadata,\n SonioxToken,\n AudioChunk,\n PermissionError,\n PermissionErrorDetail,\n // Type guards (excluding isPhotoResponse and isRtmpStreamStatus which conflict)\n isAppConnectionAck,\n isAppConnectionError,\n isAppStopped,\n isSettingsUpdate,\n isCapabilitiesUpdate,\n isDataStream,\n isAudioChunk,\n isAudioPlayResponse,\n isDashboardModeChanged,\n isDashboardAlwaysOnChanged,\n isManagedStreamStatus,\n isStreamStatusCheckResponse,\n // Re-export the cloud-to-app versions of these type guards since they're the ones\n // that should be used when dealing with CloudToAppMessage types\n isPhotoResponse as isPhotoResponseFromCloud,\n isRtmpStreamStatus as isRtmpStreamStatusFromCloud,\n isRgbLedControlResponse as isRgbLedControlResponseFromCloud,\n} from \"./messages/cloud-to-app\"\n\n// Stream types\nexport * from \"./streams\"\n\n// Layout types\nexport * from \"./layouts\"\n\n// Dashboard types\nexport * from \"./dashboard\"\n\n// RTMP streaming types\nexport * from \"./rtmp-stream\"\n\n// Other system enums\nexport * from \"./enums\"\n\n// Core model interfaces\nexport * from \"./models\"\n\n// Webhook interfaces\nexport * from \"./webhooks\"\n\n// Capability Discovery types\nexport * from \"./capabilities\"\n\n// Photo data types\nexport * from \"./photo-data\"\n\n/**\n * WebSocket error information\n */\nexport interface WebSocketError {\n code: string\n message: string\n details?: unknown\n}\n\nimport type {Request} from \"express\"\nimport type {AppSession} from \"../app/session\"\n\nexport interface AuthenticatedRequest extends Request {\n authUserId?: string\n activeSession: AppSession | null\n}\n",
24
24
  "/**\n * warning.ts\n *\n * This file defines styled warning messages that are displayed when an app\n * attempts to use functionality requiring permissions it hasn't declared.\n *\n * Each function generates a bordered terminal warning box with:\n * - ASCII art logo (left side)\n * - Permission requirement details (right side)\n * - Link to developer portal for adding permissions\n *\n * The warnings use chalk for terminal colors and boxen for bordered output,\n * creating a professional side-by-side layout that alerts developers to\n * missing permissions in their app configuration.\n *\n * These are shown during SDK runtime when permission checks fail, helping\n * developers identify and fix permission issues quickly.\n */\nimport chalk from \"chalk\";\nimport boxen from \"boxen\";\nimport { warnLog } from \"./logos\";\n\nconst createPermissionWarning = (\n permissionName: string,\n funcName?: string,\n packageName?: string,\n): string => {\n // Strip ANSI codes for width calculation\n // eslint-disable-next-line no-control-regex\n const stripAnsi = (str: string) => str.replace(/\\u001b\\[\\d+m/g, \"\");\n\n const title = chalk.bold.yellow(\"⚠️ Permission Required\");\n const message = `${chalk.yellow(funcName || \"This function\")} requires ${chalk.bold(permissionName)} permission.`;\n const instructions = chalk.dim(\n \"Please enable this permission in the developer portal at:\",\n );\n const url = chalk.cyan.underline(\n `https://console.mentra.glass/apps/${packageName}/edit`,\n );\n const hint = chalk.dim(\"under *Required Permissions*.\");\n\n // Split logo into lines (without color for width calculation)\n const logoLines = warnLog.split(\"\\n\");\n const coloredLogoLines = logoLines.map((line) => chalk.yellow(line));\n\n const textContent = [title, \"\", message, \"\", instructions, url, \"\", hint];\n\n // Find actual logo width (max line length without ANSI codes)\n const logoWidth = Math.max(\n ...logoLines.map((line) => stripAnsi(line).length),\n );\n\n // Create side-by-side layout\n const maxLines = Math.max(coloredLogoLines.length, textContent.length);\n const combinedLines: string[] = [];\n\n for (let i = 0; i < maxLines; i++) {\n const rawLogoLine = logoLines[i] || \"\";\n const coloredLogoLine = coloredLogoLines[i] || \"\";\n const actualLogoLength = stripAnsi(rawLogoLine).length;\n const padding = \" \".repeat(Math.max(0, logoWidth - actualLogoLength));\n const textLine = textContent[i] || \"\";\n combinedLines.push(`${coloredLogoLine}${padding} ${textLine}`);\n }\n\n return boxen(combinedLines.join(\"\\n\"), {\n padding: 1,\n margin: 1,\n borderStyle: \"round\",\n borderColor: \"yellow\",\n float: \"left\",\n });\n};\n\nexport const noMicrophoneWarn = (\n funcName?: string,\n packageName?: string,\n): string => {\n return createPermissionWarning(\"microphone\", funcName, packageName);\n};\n\nexport const locationWarn = (\n funcName?: string,\n packageName?: string,\n): string => {\n return createPermissionWarning(\"location\", funcName, packageName);\n};\n\nexport const baackgroundLocationWarn = (\n funcName?: string,\n packageName?: string,\n): string => {\n return createPermissionWarning(\"background location\", funcName, packageName);\n};\n\nexport const calendarWarn = (\n funcName?: string,\n packageName?: string,\n): string => {\n return createPermissionWarning(\"calendar\", funcName, packageName);\n};\n\nexport const readNotficationWarn = (\n funcName?: string,\n packageName?: string,\n): string => {\n return createPermissionWarning(\"read notification\", funcName, packageName);\n};\n\nexport const postNotficationWarn = (\n funcName?: string,\n packageName?: string,\n): string => {\n return createPermissionWarning(\"post notification\", funcName, packageName);\n};\n\nexport const cameraWarn = (funcName?: string, packageName?: string): string => {\n return createPermissionWarning(\"camera\", funcName, packageName);\n};\n",
25
25
  "export const warnLog = String.raw`\n__/\\\\\\\\____________/\\\\\\\\_ \n _\\/\\\\\\\\\\\\________/\\\\\\\\\\\\_ \n _\\/\\\\\\//\\\\\\____/\\\\\\//\\\\\\_ \n _\\/\\\\\\\\///\\\\\\/\\\\\\/_\\/\\\\\\_ \n _\\/\\\\\\__\\///\\\\\\/___\\/\\\\\\_ \n _\\/\\\\\\____\\///_____\\/\\\\\\_ \n _\\/\\\\\\_____________\\/\\\\\\_ \n _\\/\\\\\\_____________\\/\\\\\\_ \n _\\///______________\\///__`;\n\nexport const mentraLogo_1 = String.raw`\n __ __ ________ __ __ ________ _______ ______ \n| \\ / \\| \\| \\ | \\| \\| \\ / \\ \n| $$\\ / $$| $$$$$$$$| $$\\ | $$ \\$$$$$$$$| $$$$$$$\\| $$$$$$\\\n| $$$\\ / $$$| $$__ | $$$\\| $$ | $$ | $$__| $$| $$__| $$\n| $$$$\\ $$$$| $$ \\ | $$$$\\ $$ | $$ | $$ $$| $$ $$\n| $$\\$$ $$ $$| $$$$$ | $$\\$$ $$ | $$ | $$$$$$$\\| $$$$$$$$\n| $$ \\$$$| $$| $$_____ | $$ \\$$$$ | $$ | $$ | $$| $$ | $$\n| $$ \\$ | $$| $$ \\| $$ \\$$$ | $$ | $$ | $$| $$ | $$\n \\$$ \\$$ \\$$$$$$$$ \\$$ \\$$ \\$$ \\$$ \\$$ \\$$ \\$$\n`;\n\nexport const newUpdateText = `\n┬╔╗╔╔═╗╦ ╦ ╦ ╦╔═╗╔╦╗╔═╗╔╦╗╔═╗┬\n│║║║║╣ ║║║ ║ ║╠═╝ ║║╠═╣ ║ ║╣ │\no╝╚╝╚═╝╚╩╝ ╚═╝╩ ═╩╝╩ ╩ ╩ ╚═╝o\n`;\n// export const newSDKUpdate = (versionNumb: string): string => {\n// return `\n\n// /$$ /$$ /$$$$$$$$ /$$ /$$ /$$$$$$$$ /$$$$$$$ /$$$$$$\n// | $$$ /$$$| $$_____/| $$$ | $$|__ $$__/| $$__ $$ /$$__ $$\n// | $$$$ /$$$$| $$ | $$$$| $$ | $$ | $$ \\ $$| $$ \\ $$\n// | $$ $$/$$ $$| $$$$$ | $$ $$ $$ | $$ | $$$$$$$/| $$$$$$$$\n// | $$ $$$| $$| $$__/ | $$ $$$$ | $$ | $$__ $$| $$__ $$\n// | $$\\ $ | $$| $$ | $$\\ $$$ | $$ | $$ \\ $$| $$ | $$\n// | $$ \\/ | $$| $$$$$$$$| $$ \\ $$ | $$ | $$ | $$| $$ | $$\n// |__/ |__/|________/|__/ \\__/ |__/ |__/ |__/|__/ |__/\n\n// ┬╔╗╔╔═╗╦ ╦ ╦ ╦╔═╗╔╦╗╔═╗╔╦╗╔═╗┬\n// │║║║║╣ ║║║ ║ ║╠═╝ ║║╠═╣ ║ ║╣ │\n// o╝╚╝╚═╝╚╩╝ ╚═╝╩ ═╩╝╩ ╩ ╩ ╚═╝o\n// -------------------------------\n// SDK VERSION V${versionNumb} is out!\n// -------------------------------\n// bun install @mentra/sdk@latest\n// `;\n// };\n",
26
26
  "/**\n * permissions-utils.ts\n *\n * This file provides runtime permission validation utilities for the MentraOS SDK.\n *\n * Each function queries the public permissions API endpoint to check if an app\n * has declared the required permission for a specific feature. If the permission\n * is missing, a styled warning message is displayed in the terminal.\n *\n * Key features:\n * - Fetches app permissions from /api/public/permissions/:packageName\n * - Gracefully handles offline/unreachable endpoints (silent failure)\n * - Displays professional bordered warnings when permissions are missing\n * - Non-blocking - allows app execution to continue even if checks fail\n *\n * These functions are called automatically by SDK methods that require specific\n * permissions (e.g., microphone access, location tracking, camera, etc.) to help\n * developers identify missing permission declarations during development.\n */\nimport {\n noMicrophoneWarn,\n locationWarn,\n baackgroundLocationWarn,\n calendarWarn,\n readNotficationWarn,\n postNotficationWarn,\n cameraWarn,\n} from \"../constants/log-messages/warning\";\nimport {\n PackagePermissions,\n Permission,\n} from \"../../src/types/messages/cloud-to-app\";\n// Check if app has microphone permission, warn if missing\nexport const microPhoneWarnLog = (\n cloudServerUrl: string,\n packageName: string,\n funcName?: string,\n) => {\n if (!cloudServerUrl) return;\n\n const permissionsUrl = `${cloudServerUrl}/api/public/permissions/${encodeURIComponent(packageName)}`;\n\n // console.log(`Fetching permissions from: ${permissionsUrl}`);\n fetch(permissionsUrl)\n .then(async (res) => {\n const contentType = res.headers.get(\"content-type\");\n if (!res.ok) {\n console.warn(\n `Permission API returned ${res.status}: ${res.statusText}`,\n );\n return null;\n }\n\n if (contentType && contentType.includes(\"application/json\")) {\n return (await res.json()) as PackagePermissions;\n } else {\n const text = await res.text();\n console.warn(`Permission API returned non-JSON response: ${text}`);\n return null;\n }\n })\n .then((data: PackagePermissions | null) => {\n if (data) {\n const hasMic = data.permissions.some(\n (p: Permission) => p.type === \"MICROPHONE\",\n );\n\n if (!hasMic) {\n console.log(noMicrophoneWarn(funcName, packageName));\n }\n }\n })\n .catch((err) => {\n // Silently fail if endpoint is unreachable - don't block execution\n console.debug(\n \"Permission check skipped - endpoint unreachable:\",\n err.message,\n );\n });\n};\n\n// Check if app has location permission, warn if missing\nexport const locationWarnLog = (\n cloudServerUrl: string,\n packageName: string,\n funcName?: string,\n) => {\n if (!cloudServerUrl) return;\n\n const permissionsUrl = `${cloudServerUrl}/api/public/permissions/${encodeURIComponent(packageName)}`;\n\n fetch(permissionsUrl)\n .then(async (res) => {\n const contentType = res.headers.get(\"content-type\");\n if (!res.ok) {\n console.warn(\n `Permission API returned ${res.status}: ${res.statusText}`,\n );\n return null;\n }\n\n if (contentType && contentType.includes(\"application/json\")) {\n return (await res.json()) as PackagePermissions;\n } else {\n const text = await res.text();\n console.warn(`Permission API returned non-JSON response: ${text}`);\n return null;\n }\n })\n .then((data: PackagePermissions | null) => {\n if (data) {\n const hasLocation = data.permissions.some(\n (p: Permission) => p.type === \"LOCATION\",\n );\n\n if (!hasLocation) {\n console.log(locationWarn(funcName, packageName));\n }\n }\n })\n .catch((err) => {\n console.debug(\n \"Permission check skipped - endpoint unreachable:\",\n err.message,\n );\n });\n};\n\n// Check if app has background location permission, warn if missing\nexport const backgroundLocationWarnLog = (\n cloudServerUrl: string,\n packageName: string,\n funcName?: string,\n) => {\n if (!cloudServerUrl) return;\n\n const permissionsUrl = `${cloudServerUrl}/api/public/permissions/${encodeURIComponent(packageName)}`;\n\n fetch(permissionsUrl)\n .then(async (res) => {\n const contentType = res.headers.get(\"content-type\");\n if (!res.ok) {\n console.warn(\n `Permission API returned ${res.status}: ${res.statusText}`,\n );\n return null;\n }\n\n if (contentType && contentType.includes(\"application/json\")) {\n return (await res.json()) as PackagePermissions;\n } else {\n const text = await res.text();\n console.warn(`Permission API returned non-JSON response: ${text}`);\n return null;\n }\n })\n .then((data: PackagePermissions | null) => {\n if (data) {\n const hasBackgroundLocation = data.permissions.some(\n (p: Permission) => p.type === \"BACKGROUND_LOCATION\",\n );\n\n if (!hasBackgroundLocation) {\n console.log(baackgroundLocationWarn(funcName, packageName));\n }\n }\n })\n .catch((err) => {\n console.debug(\n \"Permission check skipped - endpoint unreachable:\",\n err.message,\n );\n });\n};\n\n// Check if app has calendar permission, warn if missing\nexport const calendarWarnLog = (\n cloudServerUrl: string,\n packageName: string,\n funcName?: string,\n) => {\n if (!cloudServerUrl) return;\n\n const permissionsUrl = `${cloudServerUrl}/api/public/permissions/${encodeURIComponent(packageName)}`;\n\n fetch(permissionsUrl)\n .then(async (res) => {\n const contentType = res.headers.get(\"content-type\");\n if (!res.ok) {\n console.warn(\n `Permission API returned ${res.status}: ${res.statusText}`,\n );\n return null;\n }\n\n if (contentType && contentType.includes(\"application/json\")) {\n return (await res.json()) as PackagePermissions;\n } else {\n const text = await res.text();\n console.warn(`Permission API returned non-JSON response: ${text}`);\n return null;\n }\n })\n .then((data: PackagePermissions | null) => {\n if (data) {\n const hasCalendar = data.permissions.some(\n (p: Permission) => p.type === \"CALENDAR\",\n );\n\n if (!hasCalendar) {\n console.log(calendarWarn(funcName, packageName));\n }\n }\n })\n .catch((err) => {\n console.debug(\n \"Permission check skipped - endpoint unreachable:\",\n err.message,\n );\n });\n};\n\n// Check if app has read notifications permission, warn if missing\nexport const readNotificationWarnLog = (\n cloudServerUrl: string,\n packageName: string,\n funcName?: string,\n) => {\n if (!cloudServerUrl) return;\n\n const permissionsUrl = `${cloudServerUrl}/api/public/permissions/${encodeURIComponent(packageName)}`;\n\n fetch(permissionsUrl)\n .then(async (res) => {\n const contentType = res.headers.get(\"content-type\");\n if (!res.ok) {\n console.warn(\n `Permission API returned ${res.status}: ${res.statusText}`,\n );\n return null;\n }\n\n if (contentType && contentType.includes(\"application/json\")) {\n return (await res.json()) as PackagePermissions;\n } else {\n const text = await res.text();\n console.warn(`Permission API returned non-JSON response: ${text}`);\n return null;\n }\n })\n .then((data: PackagePermissions | null) => {\n if (data) {\n const hasReadNotifications = data.permissions.some(\n (p: Permission) => p.type === \"READ_NOTIFICATIONS\",\n );\n\n if (!hasReadNotifications) {\n console.log(readNotficationWarn(funcName, packageName));\n }\n }\n })\n .catch((err) => {\n console.debug(\n \"Permission check skipped - endpoint unreachable:\",\n err.message,\n );\n });\n};\n\n// Check if app has post notifications permission, warn if missing\nexport const postNotificationWarnLog = (\n cloudServerUrl: string,\n packageName: string,\n funcName?: string,\n) => {\n if (!cloudServerUrl) return;\n\n const permissionsUrl = `${cloudServerUrl}/api/public/permissions/${encodeURIComponent(packageName)}`;\n\n fetch(permissionsUrl)\n .then(async (res) => {\n const contentType = res.headers.get(\"content-type\");\n if (!res.ok) {\n console.warn(\n `Permission API returned ${res.status}: ${res.statusText}`,\n );\n return null;\n }\n\n if (contentType && contentType.includes(\"application/json\")) {\n return (await res.json()) as PackagePermissions;\n } else {\n const text = await res.text();\n console.warn(`Permission API returned non-JSON response: ${text}`);\n return null;\n }\n })\n .then((data: PackagePermissions | null) => {\n if (data) {\n const hasPostNotifications = data.permissions.some(\n (p: Permission) => p.type === \"POST_NOTIFICATIONS\",\n );\n\n if (!hasPostNotifications) {\n console.log(postNotficationWarn(funcName, packageName));\n }\n }\n })\n .catch((err) => {\n console.debug(\n \"Permission check skipped - endpoint unreachable:\",\n err.message,\n );\n });\n};\n\n// Check if app has camera permission, warn if missing\nexport const cameraWarnLog = (\n cloudServerUrl: string,\n packageName: string,\n funcName?: string,\n) => {\n if (!cloudServerUrl) return;\n\n const permissionsUrl = `${cloudServerUrl}/api/public/permissions/${encodeURIComponent(packageName)}`;\n\n fetch(permissionsUrl)\n .then(async (res) => {\n const contentType = res.headers.get(\"content-type\");\n if (!res.ok) {\n console.warn(\n `Permission API returned ${res.status}: ${res.statusText}`,\n );\n return null;\n }\n\n if (contentType && contentType.includes(\"application/json\")) {\n return (await res.json()) as PackagePermissions;\n } else {\n const text = await res.text();\n console.warn(`Permission API returned non-JSON response: ${text}`);\n return null;\n }\n })\n .then((data: PackagePermissions | null) => {\n if (data) {\n const hasCamera = data.permissions.some(\n (p: Permission) => p.type === \"CAMERA\",\n );\n\n if (!hasCamera) {\n console.log(cameraWarn(funcName, packageName));\n }\n }\n })\n .catch((err) => {\n console.debug(\n \"Permission check skipped - endpoint unreachable:\",\n err.message,\n );\n });\n};\n",
@@ -35,11 +35,13 @@
35
35
  "/**\n * 🔊 Audio Module\n *\n * Audio functionality for App Sessions.\n * Handles audio playback on connected glasses.\n */\n\nimport {AudioPlayRequest, AudioPlayResponse, AudioStopRequest, AppToCloudMessageType} from \"../../../types\"\nimport {Logger} from \"pino\"\n\n/**\n * Options for audio playback\n */\nexport interface AudioPlayOptions {\n /** URL to audio file for download and play */\n audioUrl: string\n /** Volume level 0.0-1.0, defaults to 1.0 */\n volume?: number\n /** Whether to stop other audio playback, defaults to true */\n stopOtherAudio?: boolean\n /**\n * Track ID for audio playback (defaults to 0)\n * - 0: speaker (default audio playback)\n * - 1: app_audio (app-specific audio)\n * - 2: tts (text-to-speech audio)\n * Use different track IDs to play multiple audio streams simultaneously (mixing)\n */\n trackId?: number\n}\n\n/**\n * Options for text-to-speech\n */\nexport interface SpeakOptions {\n /** Voice ID to use (optional, defaults to server's ELEVENLABS_DEFAULT_VOICE_ID) */\n voice_id?: string\n /** Model ID to use (optional, defaults to eleven_flash_v2_5) */\n model_id?: string\n /** Voice settings object (optional) */\n voice_settings?: {\n stability?: number\n similarity_boost?: number\n style?: number\n use_speaker_boost?: boolean\n speed?: number\n }\n /** Volume level 0.0-1.0, defaults to 1.0 */\n volume?: number\n /** Whether to stop other audio playback, defaults to true */\n stopOtherAudio?: boolean\n /**\n * Track ID for audio playback (defaults to 2 for TTS)\n * - 0: speaker (default audio playback)\n * - 1: app_audio (app-specific audio)\n * - 2: tts (text-to-speech audio)\n * Use different track IDs to play multiple audio streams simultaneously (mixing)\n */\n trackId?: number\n}\n\n/**\n * Result of audio playback attempt\n */\nexport interface AudioPlayResult {\n /** Whether the audio playback was successful */\n success: boolean\n /** Error message if playback failed */\n error?: string\n /** Duration of the audio file in seconds (if available) */\n duration?: number\n}\n\n/**\n * 🔊 Audio Module Implementation\n *\n * Audio management for App Sessions.\n * Provides methods for:\n * - 🎵 Playing audio on glasses\n * - ⏹️ Stopping audio playback\n * - 🔍 Monitoring audio request status\n * - 🧹 Cleanup and cancellation\n *\n * @example\n * ```typescript\n * // Play audio\n * const result = await session.audio.playAudio({\n * audioUrl: 'https://example.com/sound.mp3',\n * volume: 0.8\n * });\n *\n * // Stop all audio\n * session.audio.stopAudio();\n * ```\n */\nexport class AudioManager {\n private session: any // Reference to AppSession\n private packageName: string\n private sessionId: string\n private logger: Logger\n\n /** Map to store pending audio play request promises */\n private pendingAudioRequests = new Map<\n string,\n {\n resolve: (value: AudioPlayResult) => void\n reject: (reason?: string) => void\n }\n >()\n\n /**\n * Create a new AudioManager\n *\n * @param packageName - The App package name\n * @param sessionId - The current session ID\n * @param send - Function to send messages to the cloud\n * @param session - Reference to the parent AppSession (optional)\n * @param logger - Logger instance for debugging\n */\n constructor(session: any, packageName: string, sessionId: string, logger?: Logger) {\n this.session = session\n this.packageName = packageName\n this.sessionId = sessionId\n this.logger = logger || (console as any)\n }\n\n // =====================================\n // 🎵 Audio Playback Functionality\n // =====================================\n\n /**\n * 🔊 Play audio on the connected glasses\n * @param options - Audio playback configuration\n * @returns Promise that resolves with playback result\n *\n * @example\n * ```typescript\n * // Play audio from URL\n * const result = await session.audio.playAudio({\n * audioUrl: 'https://example.com/sound.mp3',\n * volume: 0.8\n * });\n * ```\n */\n async playAudio(options: AudioPlayOptions): Promise<AudioPlayResult> {\n return new Promise((resolve, reject) => {\n try {\n // Validate input\n if (!options.audioUrl) {\n reject(\"audioUrl must be provided\")\n return\n }\n\n // Generate unique request ID\n const requestId = `audio_req_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`\n\n const stopOtherAudio = options.stopOtherAudio ?? true\n\n // CRITICAL: When stopOtherAudio=false (concurrent/mixing mode),\n // resolve immediately after sending the request (fire-and-forget)\n // This allows multiple audio streams to play simultaneously\n if (!stopOtherAudio) {\n // Create audio play request message\n const message: AudioPlayRequest = {\n type: AppToCloudMessageType.AUDIO_PLAY_REQUEST,\n packageName: this.packageName,\n sessionId: this.sessionId,\n requestId,\n timestamp: new Date(),\n audioUrl: options.audioUrl,\n volume: options.volume ?? 1.0,\n stopOtherAudio: false,\n trackId: options.trackId ?? 0, // Default to track 0 (speaker)\n }\n\n // Send request to cloud\n this.session.sendMessage(message)\n\n // Resolve immediately for concurrent playback (fire-and-forget)\n // The audio will play in the background without blocking\n this.logger.debug({requestId}, `🔊 Audio playback started in non-blocking mode (concurrent)`)\n resolve({\n success: true,\n duration: undefined, // Duration unknown in fire-and-forget mode\n })\n return\n }\n\n // For stopOtherAudio=true (blocking/interrupt mode),\n // wait for the COMPLETED/FAILED event before resolving\n this.pendingAudioRequests.set(requestId, {resolve, reject})\n\n // Create audio play request message\n const message: AudioPlayRequest = {\n type: AppToCloudMessageType.AUDIO_PLAY_REQUEST,\n packageName: this.packageName,\n sessionId: this.sessionId,\n requestId,\n timestamp: new Date(),\n audioUrl: options.audioUrl,\n volume: options.volume ?? 1.0,\n stopOtherAudio: true,\n trackId: options.trackId ?? 0, // Default to track 0 (speaker)\n }\n\n // Send request to cloud\n this.session.sendMessage(message)\n\n // Set timeout to avoid hanging promises (only for blocking mode)\n const timeoutMs = 60000 // 60 seconds\n if (this.session && this.session.resources) {\n // Use session's resource tracker for automatic cleeanup\n this.session.resources.setTimeout(() => {\n if (this.pendingAudioRequests.has(requestId)) {\n this.pendingAudioRequests.get(requestId)!.reject(\"Audio play request timed out\")\n this.pendingAudioRequests.delete(requestId)\n this.logger.warn({requestId}, `🔊 Audio play request timed out`)\n }\n }, timeoutMs)\n } else {\n // Fallback to regular setTimeout if session not available\n setTimeout(() => {\n if (this.pendingAudioRequests.has(requestId)) {\n this.pendingAudioRequests.get(requestId)!.reject(\"Audio play request timed out\")\n this.pendingAudioRequests.delete(requestId)\n this.logger.warn({requestId}, `🔊 Audio play request timed out`)\n }\n }, timeoutMs)\n }\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n reject(`Failed to play audio: ${errorMessage}`)\n }\n })\n }\n\n /**\n * 🔇 Stop audio playback on the connected glasses\n * @param trackId - Optional track ID to stop (0=speaker, 1=app_audio, 2=tts). If omitted, stops all tracks.\n *\n * @example\n * ```typescript\n * // Stop all currently playing audio\n * session.audio.stopAudio();\n *\n * // Stop only the speaker track (track_id 0)\n * session.audio.stopAudio(0);\n *\n * // Stop only TTS track (track_id 2)\n * session.audio.stopAudio(2);\n * ```\n */\n stopAudio(trackId?: number): void {\n try {\n // Create audio stop request message\n const message: AudioStopRequest = {\n type: AppToCloudMessageType.AUDIO_STOP_REQUEST,\n packageName: this.packageName,\n sessionId: this.sessionId,\n trackId,\n timestamp: new Date(),\n }\n\n // Send request to cloud (one-way, no response expected)\n this.session.sendMessage(message)\n\n const trackInfo = trackId !== undefined ? ` (track ${trackId})` : \" (all tracks)\"\n this.logger.info(`🔇 Audio stop request sent${trackInfo}`)\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n this.logger.error(`Failed to stop audio: ${errorMessage}`)\n }\n }\n\n /**\n * 🗣️ Convert text to speech and play it on the connected glasses\n * @param text - Text to convert to speech (required)\n * @param options - Text-to-speech configuration (optional)\n * @returns Promise that resolves with playback result\n *\n * @example\n * ```typescript\n * // Basic text-to-speech\n * const result = await session.audio.speak('Hello, world!');\n *\n * // With custom voice settings\n * const result = await session.audio.speak('Hello, world!', {\n * voice_id: 'your_voice_id',\n * voice_settings: {\n * stability: 0.5,\n * speed: 1.2\n * },\n * volume: 0.8\n * });\n *\n * // Play TTS without stopping other audio\n * const result = await session.audio.speak('Hello, world!', {\n * stopOtherAudio: false\n * });\n * ```\n */\n async speak(text: string, options: SpeakOptions = {}): Promise<AudioPlayResult> {\n // Validate input\n if (!text) {\n throw new Error(\"text must be provided\")\n }\n\n // Get the HTTPS server URL from the session\n const baseUrl = this.session?.getHttpsServerUrl?.()\n if (!baseUrl) {\n throw new Error(\"Cannot determine server URL for TTS endpoint\")\n }\n\n // Build query parameters for the TTS endpoint\n const queryParams = new URLSearchParams()\n queryParams.append(\"text\", text)\n\n if (options.voice_id) {\n queryParams.append(\"voice_id\", options.voice_id)\n }\n\n if (options.model_id) {\n queryParams.append(\"model_id\", options.model_id)\n }\n\n if (options.voice_settings) {\n queryParams.append(\"voice_settings\", JSON.stringify(options.voice_settings))\n }\n\n // Construct the TTS URL\n const ttsUrl = `${baseUrl}/api/tts?${queryParams.toString()}`\n\n this.logger.info({text, ttsUrl}, `🗣️ Generating speech from text`)\n\n // IMPORTANT: Don't call stopAudio() here - it closes tracks completely!\n // The backend will handle stopping any ongoing playback when it receives\n // the new audio play request (via stopOtherAudio flag)\n\n // Use the existing playAudio method to play the TTS audio\n // The stopOtherAudio flag will cancel ongoing playback without closing tracks\n return this.playAudio({\n audioUrl: ttsUrl,\n volume: options.volume,\n stopOtherAudio: options.stopOtherAudio ?? true, // This flag tells backend to stop current playback\n trackId: options.trackId ?? 2, // Default to track 2 (tts)\n })\n }\n\n // =====================================\n // 📥 Response Handling\n // =====================================\n\n /**\n * 📥 Handle audio play response from cloud\n *\n * This method is called internally when an audio play response is received.\n * It resolves the corresponding pending promise with the response data.\n *\n * @param response - The audio play response received\n * @internal This method is used internally by AppSession\n */\n handleAudioPlayResponse(response: AudioPlayResponse): void {\n const pendingRequest = this.pendingAudioRequests.get(response.requestId)\n\n if (pendingRequest) {\n // Resolve the promise with the response data\n pendingRequest.resolve({\n success: response.success,\n error: response.error,\n duration: response.duration,\n })\n\n // Clean up\n this.pendingAudioRequests.delete(response.requestId)\n\n this.logger.info(\n {\n requestId: response.requestId,\n success: response.success,\n duration: response.duration,\n },\n `🔊 Audio play response received`,\n )\n } else {\n this.logger.warn({requestId: response.requestId}, `🔊 Received audio play response for unknown request ID`)\n }\n }\n\n // =====================================\n // 🔍 Status and Management\n // =====================================\n\n /**\n * 🔍 Check if there are pending audio requests\n * @param requestId - Optional specific request ID to check\n * @returns True if there are pending requests (or specific request exists)\n */\n hasPendingRequest(requestId?: string): boolean {\n if (requestId) {\n return this.pendingAudioRequests.has(requestId)\n }\n return this.pendingAudioRequests.size > 0\n }\n\n /**\n * 📊 Get the number of pending audio requests\n * @returns Number of pending requests\n */\n getPendingRequestCount(): number {\n return this.pendingAudioRequests.size\n }\n\n /**\n * 📋 Get all pending request IDs\n * @returns Array of pending request IDs\n */\n getPendingRequestIds(): string[] {\n return Array.from(this.pendingAudioRequests.keys())\n }\n\n /**\n * ❌ Cancel a specific audio request\n * @param requestId - The request ID to cancel\n * @returns True if the request was found and cancelled\n */\n cancelAudioRequest(requestId: string): boolean {\n const pendingRequest = this.pendingAudioRequests.get(requestId)\n if (pendingRequest) {\n pendingRequest.reject(\"Audio request cancelled\")\n this.pendingAudioRequests.delete(requestId)\n this.logger.info({requestId}, `🔊 Audio request cancelled`)\n return true\n }\n return false\n }\n\n /**\n * 🧹 Cancel all pending audio requests\n * @returns Number of requests that were cancelled\n */\n cancelAllAudioRequests(): number {\n const count = this.pendingAudioRequests.size\n this.pendingAudioRequests.forEach((request, requestId) => {\n request.reject(\"Audio request cancelled due to cleanup\")\n this.logger.debug({requestId}, `🔊 Audio request cancelled during cleanup`)\n })\n this.pendingAudioRequests.clear()\n\n if (count > 0) {\n this.logger.info({cancelledCount: count}, `🧹 Cancelled all pending audio requests`)\n }\n\n return count\n }\n\n // =====================================\n // 🔧 Internal Management\n // =====================================\n\n /**\n * 🔄 Update the session ID when reconnecting\n * @param newSessionId - The new session ID\n * @internal Used by AppSession during reconnection\n */\n updateSessionId(newSessionId: string): void {\n this.sessionId = newSessionId\n this.logger.debug({newSessionId}, `🔄 Audio module session ID updated`)\n }\n\n /**\n * 🧹 Cancel all pending requests (cleanup)\n * @returns Object with count of cancelled requests\n * @internal Used by AppSession during cleanup\n */\n cancelAllRequests(): {audioRequests: number} {\n const audioRequests = this.cancelAllAudioRequests()\n return {audioRequests}\n }\n}\n",
36
36
  "/**\n * Resource Tracker\n * \n * A utility class for tracking and automatically cleaning up resources\n * like timers, event listeners, and other disposable objects.\n * \n * This helps prevent memory leaks by ensuring that all resources are\n * properly disposed when they're no longer needed.\n */\n\n/**\n * Type for a cleanup function that doesn't take any arguments\n */\nexport type CleanupFunction = () => void;\n\n/**\n * Type for any object with a dispose or close method\n */\nexport interface Disposable {\n dispose?: () => void;\n close?: () => void;\n}\n\n/**\n * Manages resources to prevent memory leaks\n */\nexport class ResourceTracker {\n // Collection of cleanup functions to call when dispose() is called\n private cleanupFunctions: CleanupFunction[] = [];\n \n // Flag to track if this resource tracker has been disposed\n private isDisposed = false;\n \n /**\n * Add a cleanup function to be executed when dispose() is called\n * \n * @param cleanup - The cleanup function to register\n * @returns A function that will remove this cleanup function\n */\n track(cleanup: CleanupFunction): CleanupFunction {\n if (this.isDisposed) {\n throw new Error('Cannot track resources on a disposed ResourceTracker');\n }\n \n this.cleanupFunctions.push(cleanup);\n \n // Return a function that will remove this cleanup function\n return () => {\n const index = this.cleanupFunctions.indexOf(cleanup);\n if (index !== -1) {\n this.cleanupFunctions.splice(index, 1);\n }\n };\n }\n \n /**\n * Track a disposable object (anything with a dispose or close method)\n * \n * @param disposable - The object to track\n * @returns A function that will remove this disposable\n */\n trackDisposable(disposable: Disposable): CleanupFunction {\n return this.track(() => {\n if (typeof disposable.dispose === 'function') {\n disposable.dispose();\n } else if (typeof disposable.close === 'function') {\n disposable.close();\n }\n });\n }\n \n /**\n * Track a timer and ensure it gets cleared\n * \n * @param timerId - The timer ID to track\n * @param isInterval - Whether this is an interval (true) or timeout (false)\n * @returns A function that will remove this timer\n */\n trackTimer(timerId: NodeJS.Timeout, isInterval = false): CleanupFunction {\n return this.track(() => {\n if (isInterval) {\n clearInterval(timerId);\n } else {\n clearTimeout(timerId);\n }\n });\n }\n \n /**\n * Track a timeout and ensure it gets cleared\n * \n * @param timerId - The timeout ID to track\n * @returns A function that will remove this timeout\n */\n trackTimeout(timerId: NodeJS.Timeout): CleanupFunction {\n return this.trackTimer(timerId, false);\n }\n \n /**\n * Track an interval and ensure it gets cleared\n * \n * @param timerId - The interval ID to track\n * @returns A function that will remove this interval\n */\n trackInterval(timerId: NodeJS.Timeout): CleanupFunction {\n return this.trackTimer(timerId, true);\n }\n \n /**\n * Create a tracked timeout\n * \n * @param callback - Function to call when the timeout expires\n * @param ms - Milliseconds to wait\n * @returns The timeout ID\n */\n setTimeout(callback: (...args: any[]) => void, ms: number): NodeJS.Timeout {\n const timerId = setTimeout(callback, ms);\n this.trackTimeout(timerId);\n return timerId;\n }\n \n /**\n * Create a tracked interval\n * \n * @param callback - Function to call at each interval\n * @param ms - Milliseconds between intervals\n * @returns The interval ID\n */\n setInterval(callback: (...args: any[]) => void, ms: number): NodeJS.Timeout {\n const timerId = setInterval(callback, ms);\n this.trackInterval(timerId);\n return timerId;\n }\n \n /**\n * Dispose of all tracked resources\n */\n dispose(): void {\n if (this.isDisposed) {\n return;\n }\n \n // Run all cleanup functions\n for (const cleanup of this.cleanupFunctions) {\n try {\n cleanup();\n } catch (error) {\n console.error('Error during resource cleanup:', error);\n }\n }\n \n // Clear the array\n this.cleanupFunctions = [];\n this.isDisposed = true;\n }\n \n /**\n * Check if this tracker has been disposed\n */\n get disposed(): boolean {\n return this.isDisposed;\n }\n}\n\n/**\n * Create a new ResourceTracker instance\n * \n * @returns A new ResourceTracker\n */\nexport function createResourceTracker(): ResourceTracker {\n return new ResourceTracker();\n}",
37
37
  "/**\n * Simple Storage SDK Module for MentraOS Apps\n * Provides localStorage-like API with cloud synchronization\n *\n * Mental Model: App server RAM = source of truth, MongoDB = crash recovery backup\n * - User interactions read/write to RAM instantly\n * - Changes are debounced and batched to MongoDB (3s idle / 10s max)\n * - On disconnect, pending writes are flushed automatically\n */\n\nimport {AppSession} from \"..\"\n\n/**\n * Response types for Simple Storage API\n */\ninterface StorageResponse {\n success: boolean\n data?: Record<string, string>\n}\n\ninterface StorageOperationResponse {\n success: boolean\n}\n\n/**\n * Key-value storage with local caching and debounced cloud sync\n * Data is isolated by userId and packageName\n */\nexport class SimpleStorage {\n private storage: Record<string, string> | null = null\n private appSession: AppSession\n private userId: string\n private packageName: string\n private baseUrl: string\n\n // Debounce batching state\n private pendingWrites = new Map<string, string>()\n private debounceTimer?: NodeJS.Timeout\n private maxWaitTimer?: NodeJS.Timeout\n private firstWriteTime?: number\n\n // Constants\n private static readonly MAX_VALUE_SIZE = 100_000 // 100KB\n private static readonly DEBOUNCE_MS = 3_000 // 3 seconds idle\n private static readonly MAX_WAIT_MS = 10_000 // 10 seconds max\n\n constructor(appSession: AppSession) {\n this.appSession = appSession\n this.userId = appSession.userId\n this.packageName = appSession.getPackageName()\n this.baseUrl = this.getBaseUrl()\n }\n\n // Convert WebSocket URL to HTTP for API calls\n private getBaseUrl(): string {\n const serverUrl = this.appSession.getServerUrl()\n if (!serverUrl) return \"http://localhost:8002\"\n return serverUrl.replace(/\\/app-ws$/, \"\").replace(/^ws/, \"http\")\n }\n\n // Generate auth headers for API requests\n private getAuthHeaders() {\n const apiKey = (this.appSession as any).config?.apiKey || \"unknown-api-key\"\n return {\n \"Authorization\": `Bearer ${this.packageName}:${apiKey}`,\n \"Content-Type\": \"application/json\",\n }\n }\n\n // Fetch all data from cloud and cache locally\n private async fetchStorageFromCloud(): Promise<void> {\n try {\n const response = await fetch(`${this.baseUrl}/api/sdk/simple-storage/${encodeURIComponent(this.userId)}`, {\n headers: this.getAuthHeaders(),\n })\n\n if (response.ok) {\n const result = (await response.json()) as StorageResponse\n if (result.success && result.data) {\n this.storage = result.data\n } else {\n this.storage = {}\n }\n } else {\n console.error(\"Failed to fetch storage from cloud:\", await response.text())\n this.storage = {}\n }\n } catch (error) {\n console.error(\"Error fetching storage from cloud:\", error)\n this.storage = {}\n }\n }\n\n // Get item from cache or cloud\n public async get(key: string): Promise<string | undefined> {\n try {\n if (this.storage !== null && this.storage !== undefined) {\n return this.storage[key]\n }\n\n await this.fetchStorageFromCloud()\n return this.storage?.[key]\n } catch (error) {\n console.error(\"Error getting item:\", error)\n return undefined\n }\n }\n\n // Set item with size validation and debounced batching\n // RAM updated immediately, MongoDB synced after 3s idle or 10s max\n public async set(key: string, value: string): Promise<void> {\n try {\n // Validate value size\n if (value.length > SimpleStorage.MAX_VALUE_SIZE) {\n throw new Error(\n `SimpleStorage value exceeds 100KB limit (${value.length} bytes). ` +\n `For large files, use your own S3 bucket storage.`,\n )\n }\n\n if (this.storage === null || this.storage === undefined) {\n await this.fetchStorageFromCloud()\n }\n\n // Optimistic update - RAM is source of truth (instant)\n if (this.storage) {\n this.storage[key] = value\n }\n\n // Add to pending batch for MongoDB persistence\n this.pendingWrites.set(key, value)\n\n // Schedule debounced flush\n this.scheduleFlush()\n } catch (error) {\n console.error(\"Error setting item:\", error)\n throw error\n }\n }\n\n /**\n * Schedule flush with debounce (3s idle) and max wait (10s)\n */\n private scheduleFlush(): void {\n // Track first write time for max wait\n if (!this.firstWriteTime) {\n this.firstWriteTime = Date.now()\n }\n\n // Clear existing debounce timer\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer)\n }\n\n // Calculate time until max wait\n const elapsedMs = Date.now() - this.firstWriteTime\n const remainingMaxWaitMs = SimpleStorage.MAX_WAIT_MS - elapsedMs\n\n // If we've hit max wait, flush immediately\n if (remainingMaxWaitMs <= 0) {\n this.flush().catch((err) => {\n console.error(\"Error flushing SimpleStorage:\", err)\n })\n return\n }\n\n // Set debounce timer (3s idle)\n this.debounceTimer = setTimeout(\n () => {\n this.flush().catch((err) => {\n console.error(\"Error flushing SimpleStorage:\", err)\n })\n },\n Math.min(SimpleStorage.DEBOUNCE_MS, remainingMaxWaitMs),\n )\n\n // Set max wait timer if not already set\n if (!this.maxWaitTimer && remainingMaxWaitMs > 0) {\n this.maxWaitTimer = setTimeout(() => {\n this.flush().catch((err) => {\n console.error(\"Error flushing SimpleStorage (max wait):\", err)\n })\n }, remainingMaxWaitMs)\n }\n }\n\n /**\n * Flush pending writes immediately\n * Called by: debounce timeout, max wait timeout, disconnect, or explicit flush()\n */\n public async flush(): Promise<void> {\n if (this.pendingWrites.size === 0) return\n\n // Clear all timers\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer)\n this.debounceTimer = undefined\n }\n if (this.maxWaitTimer) {\n clearTimeout(this.maxWaitTimer)\n this.maxWaitTimer = undefined\n }\n this.firstWriteTime = undefined\n\n const batch = Object.fromEntries(this.pendingWrites)\n this.pendingWrites.clear()\n\n try {\n // Persist to MongoDB (backup for crash recovery)\n const response = await fetch(`${this.baseUrl}/api/sdk/simple-storage/${encodeURIComponent(this.userId)}`, {\n method: \"PUT\",\n headers: this.getAuthHeaders(),\n body: JSON.stringify({data: batch}),\n })\n\n if (!response.ok) {\n const error = await response.text()\n console.error(\"Failed to persist SimpleStorage to MongoDB:\", error)\n\n // Re-throw with helpful message\n if (response.status === 413) {\n throw new Error(\"SimpleStorage total size exceeds 1MB limit. Delete unused keys.\")\n }\n if (response.status === 429) {\n throw new Error(\"SimpleStorage rate limit exceeded.\")\n }\n throw new Error(`SimpleStorage flush failed: ${error}`)\n }\n } catch (error) {\n console.error(\"Error flushing SimpleStorage:\", error)\n throw error\n }\n }\n\n // Delete item from cache and debounced sync to cloud\n public async delete(key: string): Promise<boolean> {\n try {\n if (this.storage === null || this.storage === undefined) {\n await this.fetchStorageFromCloud()\n }\n\n // Remove from cache (RAM = source of truth)\n if (this.storage) {\n delete this.storage[key]\n }\n\n // Remove from pending writes if exists\n this.pendingWrites.delete(key)\n\n // For deletes, we flush immediately to ensure consistency\n // (could batch this too, but deletes are rare)\n const response = await fetch(\n `${this.baseUrl}/api/sdk/simple-storage/${encodeURIComponent(this.userId)}/${encodeURIComponent(key)}`,\n {\n method: \"DELETE\",\n headers: this.getAuthHeaders(),\n },\n )\n\n if (response.ok) {\n const result = (await response.json()) as StorageOperationResponse\n return result.success\n } else {\n console.error(\"Failed to delete item from cloud:\", await response.text())\n return false\n }\n } catch (error) {\n console.error(\"Error deleting item:\", error)\n return false\n }\n }\n\n // Clear all data from cache and cloud\n public async clear(): Promise<boolean> {\n try {\n this.storage = {}\n\n const response = await fetch(`${this.baseUrl}/api/sdk/simple-storage/${encodeURIComponent(this.userId)}`, {\n method: \"DELETE\",\n headers: this.getAuthHeaders(),\n })\n\n if (response.ok) {\n const result = (await response.json()) as StorageOperationResponse\n return result.success\n } else {\n console.error(\"Failed to clear storage from cloud:\", await response.text())\n return false\n }\n } catch (error) {\n console.error(\"Error clearing storage:\", error)\n return false\n }\n }\n\n // Get all storage keys\n public async keys(): Promise<string[]> {\n try {\n if (this.storage === null || this.storage === undefined) {\n await this.fetchStorageFromCloud()\n }\n return Object.keys(this.storage || {})\n } catch (error) {\n console.error(\"Error getting keys:\", error)\n return []\n }\n }\n\n // Get number of stored items\n public async size(): Promise<number> {\n try {\n if (this.storage === null || this.storage === undefined) {\n await this.fetchStorageFromCloud()\n }\n return Object.keys(this.storage || {}).length\n } catch (error) {\n console.error(\"Error getting storage size:\", error)\n return 0\n }\n }\n\n // Check if key exists\n public async hasKey(key: string): Promise<boolean> {\n try {\n if (this.storage === null || this.storage === undefined) {\n await this.fetchStorageFromCloud()\n }\n return key in (this.storage || {})\n } catch (error) {\n console.error(\"Error checking key:\", error)\n return false\n }\n }\n\n // Get copy of all stored data\n public async getAllData(): Promise<Record<string, string>> {\n try {\n if (this.storage === null || this.storage === undefined) {\n await this.fetchStorageFromCloud()\n }\n return {...(this.storage || {})}\n } catch (error) {\n console.error(\"Error getting all data:\", error)\n return {}\n }\n }\n\n // Set multiple items at once with validation\n public async setMultiple(data: Record<string, string>): Promise<void> {\n try {\n // Validate all values first\n for (const [key, value] of Object.entries(data)) {\n if (value.length > SimpleStorage.MAX_VALUE_SIZE) {\n throw new Error(`SimpleStorage value for key \"${key}\" exceeds 100KB limit (${value.length} bytes)`)\n }\n }\n\n if (this.storage === null || this.storage === undefined) {\n await this.fetchStorageFromCloud()\n }\n\n // Update cache (RAM = source of truth)\n if (this.storage) {\n Object.assign(this.storage, data)\n }\n\n // Add all to pending batch\n for (const [key, value] of Object.entries(data)) {\n this.pendingWrites.set(key, value)\n }\n\n // Schedule debounced flush\n this.scheduleFlush()\n } catch (error) {\n console.error(\"Error setting multiple items:\", error)\n throw error\n }\n }\n}\n",
38
+ "/**\n * Observable<T> - A reactive value wrapper that notifies listeners of changes\n *\n * Provides synchronous value access and reactive subscriptions via onChange().\n * Supports implicit coercion for use in conditionals and comparisons.\n *\n * @example\n * ```typescript\n * const wifiStatus = new Observable(false);\n *\n * // Synchronous read\n * console.log(wifiStatus.value); // false\n *\n * // Implicit coercion\n * if (wifiStatus) { ... } // Works via valueOf()\n *\n * // Reactive subscription\n * const cleanup = wifiStatus.onChange((connected) => {\n * console.log(\"WiFi:\", connected);\n * });\n *\n * // Update (triggers callbacks)\n * wifiStatus.setValue(true);\n *\n * // Cleanup\n * cleanup();\n * ```\n */\nexport class Observable<T> {\n private _value: T;\n private _listeners: Set<(value: T) => void> = new Set();\n private _initialized: boolean = false; // Track if value has been set from WebSocket\n\n constructor(initialValue: T) {\n this._value = initialValue;\n }\n\n /**\n * Get the current value synchronously\n */\n get value(): T {\n return this._value;\n }\n\n /**\n * Implicit coercion to primitive value (for conditionals/comparisons)\n */\n valueOf(): T {\n return this._value;\n }\n\n /**\n * String representation\n */\n toString(): string {\n return String(this._value);\n }\n\n /**\n * Symbol.toPrimitive for implicit type coercion\n * Allows usage in conditionals: if (observable) { ... }\n */\n [Symbol.toPrimitive](hint: string): T | string {\n if (hint === 'string') {\n return String(this._value);\n }\n return this._value;\n }\n\n /**\n * Subscribe to value changes\n *\n * The callback is called immediately with the current value ONLY if\n * the Observable has been initialized (setValue() called at least once).\n * This prevents callbacks from firing with default/uninitialized values.\n *\n * @param callback - Function to call when value changes\n * @returns Cleanup function to unsubscribe\n *\n * @example\n * ```typescript\n * const cleanup = observable.onChange((value) => {\n * console.log(\"New value:\", value);\n * });\n *\n * // Later: unsubscribe\n * cleanup();\n * ```\n */\n onChange(callback: (value: T) => void): () => void {\n this._listeners.add(callback);\n // Call immediately with current value ONLY if initialized\n if (this._initialized) {\n callback(this._value);\n }\n // Return cleanup function\n return () => this._listeners.delete(callback);\n }\n\n /**\n * Update the value and notify listeners\n *\n * Triggers callbacks if:\n * 1. This is the first setValue() call (initialization from WebSocket), OR\n * 2. The new value is different from current value\n *\n * Uses strict equality (===) for comparison.\n *\n * @param value - New value to set\n *\n * @internal This method is called by DeviceState when receiving WebSocket updates\n */\n setValue(value: T): void {\n const isFirstInit = !this._initialized;\n\n // Mark as initialized (first setValue call from WebSocket)\n if (isFirstInit) {\n this._initialized = true;\n }\n\n // Notify listeners if this is initialization OR value changed\n if (isFirstInit || this._value !== value) {\n this._value = value;\n // Notify all listeners\n this._listeners.forEach((cb) => {\n try {\n cb(value);\n } catch (error) {\n console.error('Error in Observable onChange callback:', error);\n }\n });\n }\n }\n\n /**\n * Get the number of active listeners\n * @internal Used for debugging/testing\n */\n get listenerCount(): number {\n return this._listeners.size;\n }\n}\n",
39
+ "/**\n * DeviceState - Reactive device state management via WebSocket\n *\n * Provides real-time Observable properties for device state (WiFi, battery, hotspot, etc.)\n * Uses flat structure matching GlassesInfo field names exactly.\n *\n * @example\n * ```typescript\n * // Synchronous read\n * if (session.device.state.wifiConnected) {\n * console.log(\"Connected to:\", session.device.state.wifiSsid.value);\n * }\n *\n * // Reactive subscription\n * session.device.state.wifiConnected.onChange((connected) => {\n * console.log(\"WiFi status:\", connected);\n * });\n *\n * session.device.state.batteryLevel.onChange((level) => {\n * console.log(\"Battery:\", level, \"%\");\n * });\n * ```\n */\n\nimport {Observable} from '../../utils/Observable';\nimport type {GlassesInfo} from '@mentra/types';\nimport type {AppSession} from './index';\n\nexport class DeviceState {\n // ============================================================================\n // WiFi Status Observables\n // ============================================================================\n\n /** WiFi connection status */\n public readonly wifiConnected: Observable<boolean>;\n\n /** WiFi network SSID (null if not connected) */\n public readonly wifiSsid: Observable<string | null>;\n\n /** WiFi local IP address (null if not connected) */\n public readonly wifiLocalIp: Observable<string | null>;\n\n // ============================================================================\n // Battery Status Observables\n // ============================================================================\n\n /** Glasses battery level (0-100, null if unknown) */\n public readonly batteryLevel: Observable<number | null>;\n\n /** Glasses charging status (null if unknown) */\n public readonly charging: Observable<boolean | null>;\n\n /** Case battery level (0-100, null if no case or unknown) */\n public readonly caseBatteryLevel: Observable<number | null>;\n\n /** Case charging status (null if no case or unknown) */\n public readonly caseCharging: Observable<boolean | null>;\n\n /** Case open/closed status (true = open, null if no case or unknown) */\n public readonly caseOpen: Observable<boolean | null>;\n\n /** Case removed status (true = glasses not in case, null if no case or unknown) */\n public readonly caseRemoved: Observable<boolean | null>;\n\n // ============================================================================\n // Hotspot Status Observables\n // ============================================================================\n\n /** Hotspot enabled status (null if not supported or unknown) */\n public readonly hotspotEnabled: Observable<boolean | null>;\n\n /** Hotspot SSID (null if disabled or unknown) */\n public readonly hotspotSsid: Observable<string | null>;\n\n // ============================================================================\n // Connection & Device Info Observables\n // ============================================================================\n\n /** Glasses connected to phone/cloud (true = connected) */\n public readonly connected: Observable<boolean>;\n\n /** Glasses model name (e.g., \"even_g1\", \"xreal_air_2_pro\") */\n public readonly modelName: Observable<string | null>;\n\n // ============================================================================\n // Internal State\n // ============================================================================\n\n private appSession: AppSession;\n\n constructor(appSession: AppSession) {\n this.appSession = appSession;\n\n // Initialize all observables with default/safe values\n // These will be updated when cloud sends DEVICE_STATE_UPDATE\n\n // WiFi (default: disconnected)\n this.wifiConnected = new Observable<boolean>(false);\n this.wifiSsid = new Observable<string | null>(null);\n this.wifiLocalIp = new Observable<string | null>(null);\n\n // Battery (default: unknown)\n this.batteryLevel = new Observable<number | null>(null);\n this.charging = new Observable<boolean | null>(null);\n this.caseBatteryLevel = new Observable<number | null>(null);\n this.caseCharging = new Observable<boolean | null>(null);\n this.caseOpen = new Observable<boolean | null>(null);\n this.caseRemoved = new Observable<boolean | null>(null);\n\n // Hotspot (default: disabled/unknown)\n this.hotspotEnabled = new Observable<boolean | null>(null);\n this.hotspotSsid = new Observable<string | null>(null);\n\n // Connection (default: disconnected)\n this.connected = new Observable<boolean>(false);\n this.modelName = new Observable<string | null>(null);\n }\n\n /**\n * Update device state from WebSocket message\n *\n * Called internally by AppSession when DEVICE_STATE_UPDATE message is received.\n * Only updates Observables for fields present in the state object.\n * Observables automatically notify listeners only if value changed.\n *\n * @param state - Partial device state (only changed fields, or full snapshot)\n * @internal\n */\n updateFromMessage(state: Partial<GlassesInfo>): void {\n // Connection state\n if (state.connected !== undefined) {\n this.connected.setValue(state.connected);\n }\n if (state.modelName !== undefined) {\n this.modelName.setValue(state.modelName);\n }\n\n // WiFi state\n if (state.wifiConnected !== undefined) {\n this.wifiConnected.setValue(state.wifiConnected);\n }\n if (state.wifiSsid !== undefined) {\n this.wifiSsid.setValue(state.wifiSsid ?? null);\n }\n if (state.wifiLocalIp !== undefined) {\n this.wifiLocalIp.setValue(state.wifiLocalIp ?? null);\n }\n\n // Battery state\n if (state.batteryLevel !== undefined) {\n this.batteryLevel.setValue(state.batteryLevel ?? null);\n }\n if (state.charging !== undefined) {\n this.charging.setValue(state.charging ?? null);\n }\n if (state.caseBatteryLevel !== undefined) {\n this.caseBatteryLevel.setValue(state.caseBatteryLevel ?? null);\n }\n if (state.caseCharging !== undefined) {\n this.caseCharging.setValue(state.caseCharging ?? null);\n }\n if (state.caseOpen !== undefined) {\n this.caseOpen.setValue(state.caseOpen ?? null);\n }\n if (state.caseRemoved !== undefined) {\n this.caseRemoved.setValue(state.caseRemoved ?? null);\n }\n\n // Hotspot state\n if (state.hotspotEnabled !== undefined) {\n this.hotspotEnabled.setValue(state.hotspotEnabled ?? null);\n }\n if (state.hotspotSsid !== undefined) {\n this.hotspotSsid.setValue(state.hotspotSsid ?? null);\n }\n }\n\n /**\n * Get snapshot of current device state\n *\n * Returns a plain object with current values of all Observables.\n * Useful for compatibility with REST-style code or debugging.\n *\n * @returns Current device state as GlassesInfo partial object\n *\n * @example\n * ```typescript\n * const currentState = session.device.state.getSnapshot();\n * console.log(\"Current state:\", currentState);\n * ```\n */\n getSnapshot(): Partial<GlassesInfo> {\n return {\n // Connection\n connected: this.connected.value,\n modelName: this.modelName.value ?? undefined,\n\n // WiFi\n wifiConnected: this.wifiConnected.value,\n wifiSsid: this.wifiSsid.value ?? undefined,\n wifiLocalIp: this.wifiLocalIp.value ?? undefined,\n\n // Battery\n batteryLevel: this.batteryLevel.value ?? undefined,\n charging: this.charging.value ?? undefined,\n caseBatteryLevel: this.caseBatteryLevel.value ?? undefined,\n caseCharging: this.caseCharging.value ?? undefined,\n caseOpen: this.caseOpen.value ?? undefined,\n caseRemoved: this.caseRemoved.value ?? undefined,\n\n // Hotspot\n hotspotEnabled: this.hotspotEnabled.value ?? undefined,\n hotspotSsid: this.hotspotSsid.value ?? undefined,\n };\n }\n}\n",
38
40
  "// src/app/webview/index.ts\nimport axios from \"axios\";\nimport { Response, NextFunction } from \"express\";\nimport { AuthenticatedRequest } from \"../../types\";\n// Note: Your Express app needs to use cookie-parser middleware for this to work\n// Example: app.use(require('cookie-parser')());\nimport * as crypto from \"crypto\";\nimport { KEYUTIL, KJUR, RSAKey } from \"jsrsasign\";\nimport { AppSession } from \"../session\";\n\nconst userTokenPublicKey =\n process.env.MENTRAOS_CLOUD_USER_TOKEN_PUBLIC_KEY ||\n \"-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Yt2RtNOdeKQxWMY0c84\\nADpY1Jy58YWZhaEgP2A5tBwFUKgy/TH9gQLWZjQ3dQ/6XXO8qq0kluoYFqM7ZDRF\\nzJ0E4Yi0WQncioLRcCx4q8pDmqY9vPKgv6PruJdFWca0l0s3gZ3BqSeWum/C23xK\\nFPHPwi8gvRdc6ALrkcHeciM+7NykU8c0EY8PSitNL+Tchti95kGu+j6APr5vNewi\\nzRpQGOdqaLWe+ahHmtj6KtUZjm8o6lan4f/o08C6litizguZXuw2Nn/Kd9fFI1xF\\nIVNJYMy9jgGaOi71+LpGw+vIpwAawp/7IvULDppvY3DdX5nt05P1+jvVJXPxMKzD\\nTQIDAQAB\\n-----END PUBLIC KEY-----\";\n\n/**\n * Extracts the temporary token from a URL string.\n * @param url The URL string, typically window.location.href.\n * @returns The token string or null if not found.\n */\nexport function extractTempToken(url: string): string | null {\n try {\n const parsedUrl = new URL(url);\n return parsedUrl.searchParams.get(\"aos_temp_token\");\n } catch (e) {\n console.error(\"Error parsing URL for temp token:\", e);\n return null;\n }\n}\n\n/**\n * Exchanges a temporary token for a user ID with the MentraOS Cloud.\n * This should be called from the App's backend server.\n * @param cloudApiUrl The base URL of the MentraOS Cloud API.\n * @param tempToken The temporary token obtained from the webview URL.\n * @param apiKey Your App's secret API key.\n * @returns A Promise that resolves with an object containing the userId.\n * @throws Throws an error if the exchange fails (e.g., invalid token, expired, network error).\n */\nexport async function exchangeToken(\n cloudApiUrl: string,\n tempToken: string,\n apiKey: string,\n packageName: string,\n): Promise<{ userId: string }> {\n const endpoint = `${cloudApiUrl}/api/auth/exchange-user-token`;\n console.log(`Exchanging token for user at ${endpoint}`);\n try {\n const response = await axios.post(\n endpoint,\n { aos_temp_token: tempToken, packageName: packageName },\n {\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n timeout: 10000, // 10 second timeout\n },\n );\n\n if (\n response.status === 200 &&\n response.data.success &&\n response.data.userId\n ) {\n return { userId: response.data.userId };\n } else {\n // Handle specific error messages from the server if available\n const errorMessage =\n response.data?.error || `Failed with status ${response.status}`;\n throw new Error(errorMessage);\n }\n } catch (error) {\n if (axios.isAxiosError(error)) {\n const status = error.response?.status;\n const data = error.response?.data;\n const message =\n data?.error || error.message || \"Unknown error during token exchange\";\n console.error(`Token exchange failed with status ${status}: ${message}`);\n throw new Error(`Token exchange failed: ${message}`);\n } else {\n console.error(\"Unexpected error during token exchange:\", error);\n throw new Error(\"An unexpected error occurred during token exchange.\");\n }\n }\n}\n\n/**\n * Signs a user ID to create a secure session token.\n * @param userId The user ID to sign\n * @param secret The secret key used for signing\n * @returns A signed session token string\n */\nfunction signSession(userId: string, secret: string): string {\n // Format: userId.timestamp.signature\n const timestamp = Date.now();\n const data = `${userId}|${timestamp}`;\n const signature = crypto\n .createHmac(\"sha256\", secret)\n .update(data)\n .digest(\"hex\");\n\n return `${data}|${signature}`;\n}\n\n/**\n * Verifies and extracts the user ID from a signed session token.\n * @param token The signed session token\n * @param secret The secret key used for verification\n * @param maxAge The maximum age of the token in milliseconds\n * @returns The extracted user ID if valid, or null if invalid\n */\nfunction verifySession(\n token: string,\n secret: string,\n maxAge?: number,\n): string | null {\n try {\n const parts = token.split(\"|\");\n if (parts.length !== 3) return null;\n\n const [userId, timestampStr, signature] = parts;\n const timestamp = parseInt(timestampStr, 10);\n\n // Check if token has expired\n if (maxAge && Date.now() - timestamp > maxAge) {\n console.log(\n `Session token expired: ${token}. Parsed date is ${timestamp}, meaning age is ${Date.now() - timestamp}, but maxAge is ${maxAge}`,\n );\n return null;\n }\n\n // Verify signature\n const data = `${userId}|${timestamp}`;\n const expectedSignature = crypto\n .createHmac(\"sha256\", secret)\n .update(data)\n .digest(\"hex\");\n\n if (signature !== expectedSignature) {\n console.log(\n `Session token signature mismatch: ${signature} !== ${expectedSignature}`,\n );\n return null;\n }\n\n return userId;\n } catch (error) {\n console.error(\"Session verification failed:\", error);\n return null;\n }\n}\n\n/**\n * Verifies a signed user token and extracts the user ID from it\n * @param signedUserToken The JWT token to verify\n * @returns The user ID (subject) from the token, or null if invalid\n */\nasync function verifySignedUserToken(\n signedUserToken: string,\n): Promise<string | null> {\n try {\n // 1. Parse the PEM public key into a jsrsasign key object\n const publicKeyObj = KEYUTIL.getKey(userTokenPublicKey) as RSAKey;\n // 2. Verify JWT signature + claims (issuer, exp, iat) with 2-min tolerance\n const isValid = KJUR.jws.JWS.verifyJWT(signedUserToken, publicKeyObj, {\n alg: [\"RS256\"],\n iss: [\"https://prod.augmentos.cloud\"],\n verifyAt: KJUR.jws.IntDate.get(\"now\"),\n gracePeriod: 120,\n });\n if (!isValid) return null;\n\n // 3. Decode payload and return the subject (user ID)\n const parsed = KJUR.jws.JWS.parse(signedUserToken);\n return (parsed.payloadObj as { sub: string }).sub || null;\n } catch (e) {\n console.error(\"[verifySignedUserToken] Error verifying token:\", e);\n return null;\n }\n}\n\n/**\n * Verifies a frontend token by comparing it to a secure hash of the API key\n * @param frontendToken The token to verify (should be a hash of the API key)\n * @param apiKey The API key to hash and compare against\n * @param userId Optional user ID that may be embedded in the token format\n * @returns The user ID if the token is valid, or null if invalid\n */\nfunction verifyFrontendToken(\n frontendToken: string,\n apiKey: string,\n): string | null {\n try {\n // Check if the token contains a user ID and hash separated by a colon\n const tokenParts = frontendToken.split(\":\");\n\n if (tokenParts.length === 2) {\n // Format: userId:hash\n const [tokenUserId, tokenHash] = tokenParts;\n\n // Align the hashing algorithm with server-side `hashWithApiKey`\n // 1. Hash the API key first (server only stores the hashed version)\n const hashedApiKey = crypto\n .createHash(\"sha256\")\n .update(apiKey)\n .digest(\"hex\");\n // 2. Create the expected hash using userId + hashedApiKey (same order & update calls)\n const expectedHash = crypto\n .createHash(\"sha256\")\n .update(tokenUserId)\n .update(hashedApiKey)\n .digest(\"hex\");\n\n if (tokenHash === expectedHash) {\n return tokenUserId;\n }\n } else {\n throw new Error(\"Invalid frontend token format\");\n }\n\n return null;\n } catch (error) {\n console.error(\"Frontend token verification failed:\", error);\n return null;\n }\n}\n\nfunction validateCloudApiUrlChecksum(\n checksum: string,\n cloudApiUrl: string,\n apiKey: string,\n): boolean {\n const hashedApiKey = crypto.createHash(\"sha256\").update(apiKey).digest(\"hex\");\n const expectedChecksum = crypto\n .createHash(\"sha256\")\n .update(cloudApiUrl)\n .update(hashedApiKey)\n .digest(\"hex\");\n\n return expectedChecksum === checksum;\n}\n/**\n * Express middleware for automatically handling the token exchange.\n * Assumes API key and Cloud URL are available (e.g., via environment variables).\n * Adds `req.authUserId` if successful.\n *\n * @param options Configuration options.\n * @param options.cloudApiUrl The base URL of the MentraOS Cloud API.\n * @param options.apiKey Your App's secret API key.\n * @param options.tokenQueryParam The name of the query parameter containing the token (default: 'aos_temp_token').\n * @param options.cookieName The name of the cookie to store the session token (default: 'aos_session').\n * @param options.cookieSecret Secret key used to sign the session cookie. MUST be provided and kept secure.\n * @param options.cookieOptions Options for the session cookie (default: { httpOnly: true, secure: process.env.NODE_ENV === 'production' }).\n */\nexport function createAuthMiddleware(options: {\n apiKey: string;\n packageName: string;\n cookieName?: string;\n cookieSecret: string;\n getAppSessionForUser?: (userId: string) => AppSession | null;\n cookieOptions?: {\n httpOnly?: boolean;\n secure?: boolean;\n maxAge?: number;\n sameSite?: boolean | \"lax\" | \"strict\" | \"none\";\n path?: string;\n };\n}) {\n const {\n apiKey,\n packageName,\n cookieName = \"aos_session\",\n cookieSecret,\n getAppSessionForUser,\n cookieOptions = {\n httpOnly: true,\n secure: process.env.NODE_ENV === \"production\",\n maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days by default\n sameSite: process.env.NODE_ENV === \"production\" ? \"none\" : \"lax\",\n path: \"/\",\n },\n } = options;\n\n if (!apiKey) {\n throw new Error(\"API Key are required for the auth middleware.\");\n }\n\n if (\n !cookieSecret ||\n typeof cookieSecret !== \"string\" ||\n cookieSecret.length < 8\n ) {\n throw new Error(\n \"A strong cookieSecret (at least 8 characters) is required for secure session management.\",\n );\n }\n\n return async (\n req: AuthenticatedRequest,\n res: Response,\n next: NextFunction,\n ) => {\n // First check for temporary token in the query string\n const tempToken = req.query[\"aos_temp_token\"] as string;\n const frontendToken =\n (req.headers.authorization?.replace(\"Bearer \", \"\") as string) ||\n (req.query[\"aos_frontend_token\"] as string);\n const signedUserToken = req.query[\"aos_signed_user_token\"] as string;\n\n // first check for signed user token\n if (signedUserToken) {\n const userId = await verifySignedUserToken(signedUserToken);\n if (userId) {\n // Set the user ID on the request\n req.authUserId = userId;\n if (getAppSessionForUser) {\n const appSession = getAppSessionForUser(userId);\n if (appSession) {\n req.activeSession = appSession;\n } else {\n req.activeSession = null;\n }\n }\n\n // Create a signed session token and store it in a cookie\n const signedSession = signSession(userId, cookieSecret);\n res.cookie(cookieName, signedSession, cookieOptions);\n\n console.log(\n \"[auth.middleware] User ID verified from signed user token: \",\n userId,\n );\n return next();\n } else {\n console.log(\"[auth.middleware] Signed user token invalid\");\n }\n }\n // If temporary token exists, authenticate with it\n if (tempToken) {\n try {\n let cloudApiUrl = `https://api.mentra.glass`;\n const cloudApiUrlFromQuery = req.query[\"cloudApiUrl\"] as string;\n if (cloudApiUrlFromQuery) {\n const cloudApiUrlChecksum = req.query[\n \"cloudApiUrlChecksum\"\n ] as string;\n\n if (\n validateCloudApiUrlChecksum(\n cloudApiUrlChecksum,\n cloudApiUrlFromQuery,\n apiKey,\n )\n ) {\n console.log(\n `Cloud API is being routed to alternate url at request of the server: ${cloudApiUrlFromQuery}`,\n );\n cloudApiUrl = cloudApiUrlFromQuery;\n } else {\n console.error(\n `Server requested alternate cloud url of ${cloudApiUrlFromQuery} but the checksum is invalid (checksum: ${cloudApiUrlChecksum}). Using default cloud url of ${cloudApiUrl} instead.`,\n );\n }\n }\n\n const { userId } = await exchangeToken(\n cloudApiUrl,\n tempToken,\n apiKey,\n packageName,\n );\n\n // Set the user ID on the request\n req.authUserId = userId;\n if (getAppSessionForUser) {\n const appSession = getAppSessionForUser(userId);\n if (appSession) {\n req.activeSession = appSession;\n }\n }\n\n // Create a signed session token and store it in a cookie\n const signedSession = signSession(userId, cookieSecret);\n res.cookie(cookieName, signedSession, cookieOptions);\n\n console.log(\n \"[auth.middleware] User ID verified from temporary token: \",\n userId,\n );\n\n return next();\n } catch (error) {\n console.error(\"Webview token exchange failed:\", error);\n // Temporary token is invalid\n }\n }\n\n if (frontendToken) {\n // Check for user ID in headers if not embedded in token\n const userId = verifyFrontendToken(frontendToken, apiKey);\n\n if (userId) {\n req.authUserId = userId;\n if (getAppSessionForUser) {\n const appSession = getAppSessionForUser(userId);\n if (appSession) {\n req.activeSession = appSession;\n }\n }\n // Create a signed session token and store it in a cookie\n const signedSession = signSession(userId, cookieSecret);\n res.cookie(cookieName, signedSession, cookieOptions);\n console.log(\n \"[auth.middleware] User ID verified from frontend user token: \",\n userId,\n );\n return next();\n } else {\n console.log(\"[auth.middleware] Frontend token invalid\");\n }\n }\n\n // No valid temporary token, check for existing session cookie\n const sessionCookie = req.cookies?.[cookieName];\n\n if (sessionCookie) {\n try {\n // Verify the signed session cookie and extract the user ID\n const userId = verifySession(\n sessionCookie,\n cookieSecret,\n cookieOptions.maxAge,\n );\n if (userId) {\n req.authUserId = userId;\n if (getAppSessionForUser) {\n const appSession = getAppSessionForUser(userId);\n if (appSession) {\n req.activeSession = appSession;\n }\n }\n return next();\n }\n\n // Invalid or expired session, clear the cookie\n res.clearCookie(cookieName, { path: cookieOptions.path });\n } catch (error) {\n console.error(\"Invalid session cookie:\", error);\n // Clear the invalid cookie\n res.clearCookie(cookieName, { path: cookieOptions.path });\n }\n }\n\n // No valid authentication method found, proceed without setting req.authUserId\n next();\n };\n}\n",
39
41
  "/**\n * updates.ts\n *\n * This file defines constant messages that should be displayed\n * in the terminal to notify developers about new SDK releases.\n *\n * Each function generates a stylized ASCII message (banner-style)\n * that highlights the latest SDK version and provides the npm install command.\n * https://patorjk.com/software/taag/\n *\n * These messages are intended to be logged to the console or shown in\n * terminal output so developers are aware of updates in a clear\n * and visually distinct way.\n *\n *\n */\n\nimport chalk from \"chalk\";\nimport boxen from \"boxen\";\nimport { mentraLogo_1, newUpdateText } from \"./logos\";\n\nconst createUpdateNotification = (versionNumb: string): string => {\n const line = chalk.bold.gray(\"-------------------------------\");\n const logo = chalk.cyan(mentraLogo_1);\n const title = chalk.bold.cyan(newUpdateText);\n const versionMessage = `Version ${chalk.bold.cyan(`SDK VERSION V${versionNumb} is out! 🎉`)}`;\n const currentNote = chalk.yellow(\"You are running an older version\");\n const instructions = chalk.yellow(\"Update to the latest version with:\");\n const command = chalk.green.bold(\"bun install @mentra/sdk@latest\");\n\n const content = [\n logo,\n title,\n line,\n versionMessage,\n currentNote,\n line,\n instructions,\n command,\n ].join(\"\\n\");\n\n return boxen(content, {\n padding: 1,\n margin: 1,\n borderStyle: \"round\",\n borderColor: \"cyan\",\n textAlignment: \"left\",\n });\n};\n\nexport const newSDKUpdate = (versionNumb: string): string => {\n return createUpdateNotification(versionNumb);\n};\n",
40
42
  "/**\n * 🔐 App Token Module\n *\n * Provides utilities for working with App tokens.\n */\nexport * from './utils';"
41
43
  ],
42
- "mappings": "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",
43
- "debugId": "AD30D8A3207C691A64756E2164756E21",
44
+ "mappings": "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",
45
+ "debugId": "BBCA9D1CAB7CB76464756E2164756E21",
44
46
  "names": []
45
47
  }