@mentra/engine 0.1.0-dev.0 → 3.1.0-dev.10

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 (503) hide show
  1. package/README.md +55 -18
  2. package/build/bluetooth-sdk/debug.d.ts +2 -0
  3. package/build/bluetooth-sdk/debug.d.ts.map +1 -0
  4. package/build/bluetooth-sdk/debug.js +2 -0
  5. package/build/bluetooth-sdk/debug.js.map +1 -0
  6. package/build/bluetooth-sdk/index.d.ts +3 -0
  7. package/build/bluetooth-sdk/index.d.ts.map +1 -0
  8. package/build/bluetooth-sdk/index.js +3 -0
  9. package/build/bluetooth-sdk/index.js.map +1 -0
  10. package/build/bluetooth-sdk/photo-receiver.d.ts +3 -0
  11. package/build/bluetooth-sdk/photo-receiver.d.ts.map +1 -0
  12. package/build/bluetooth-sdk/photo-receiver.js +3 -0
  13. package/build/bluetooth-sdk/photo-receiver.js.map +1 -0
  14. package/build/bluetooth-sdk/react.d.ts +2 -0
  15. package/build/bluetooth-sdk/react.d.ts.map +1 -0
  16. package/build/bluetooth-sdk/react.js +2 -0
  17. package/build/bluetooth-sdk/react.js.map +1 -0
  18. package/build/bluetooth-sdk/types.d.ts +2 -0
  19. package/build/bluetooth-sdk/types.d.ts.map +1 -0
  20. package/build/bluetooth-sdk/types.js +2 -0
  21. package/build/bluetooth-sdk/types.js.map +1 -0
  22. package/build/engine.d.ts +24 -16
  23. package/build/engine.d.ts.map +1 -1
  24. package/build/engine.js +9 -4
  25. package/build/engine.js.map +1 -1
  26. package/build/facades/dev.d.ts +3 -2
  27. package/build/facades/dev.d.ts.map +1 -1
  28. package/build/facades/dev.js +18 -12
  29. package/build/facades/dev.js.map +1 -1
  30. package/build/facades/display.d.ts +1 -1
  31. package/build/facades/display.d.ts.map +1 -1
  32. package/build/facades/display.js +1 -1
  33. package/build/facades/display.js.map +1 -1
  34. package/build/facades/gallery.js +1 -1
  35. package/build/facades/gallery.js.map +1 -1
  36. package/build/facades/glasses.d.ts +4 -13
  37. package/build/facades/glasses.d.ts.map +1 -1
  38. package/build/facades/glasses.js +21 -6
  39. package/build/facades/glasses.js.map +1 -1
  40. package/build/facades/glassesSettings.d.ts.map +1 -1
  41. package/build/facades/glassesSettings.js +1 -0
  42. package/build/facades/glassesSettings.js.map +1 -1
  43. package/build/facades/miniapps.d.ts +4 -0
  44. package/build/facades/miniapps.d.ts.map +1 -1
  45. package/build/facades/miniapps.js +5 -0
  46. package/build/facades/miniapps.js.map +1 -1
  47. package/build/facades/ota.d.ts +14 -16
  48. package/build/facades/ota.d.ts.map +1 -1
  49. package/build/facades/ota.js +22 -7
  50. package/build/facades/ota.js.map +1 -1
  51. package/build/facades/pairing.d.ts +8 -5
  52. package/build/facades/pairing.d.ts.map +1 -1
  53. package/build/facades/pairing.js +12 -10
  54. package/build/facades/pairing.js.map +1 -1
  55. package/build/facades/permissions.d.ts +10 -0
  56. package/build/facades/permissions.d.ts.map +1 -1
  57. package/build/facades/permissions.js +10 -0
  58. package/build/facades/permissions.js.map +1 -1
  59. package/build/facades/phoneNotifications.d.ts +0 -4
  60. package/build/facades/phoneNotifications.d.ts.map +1 -1
  61. package/build/facades/phoneNotifications.js +4 -14
  62. package/build/facades/phoneNotifications.js.map +1 -1
  63. package/build/facades/speech.d.ts +7 -6
  64. package/build/facades/speech.d.ts.map +1 -1
  65. package/build/facades/speech.js +1 -1
  66. package/build/facades/speech.js.map +1 -1
  67. package/build/generated/releaseMetadata.d.ts +12 -0
  68. package/build/generated/releaseMetadata.d.ts.map +1 -0
  69. package/build/generated/releaseMetadata.js +10 -0
  70. package/build/generated/releaseMetadata.js.map +1 -0
  71. package/build/index.d.ts +10 -8
  72. package/build/index.d.ts.map +1 -1
  73. package/build/index.js +6 -5
  74. package/build/index.js.map +1 -1
  75. package/build/react/MentraLiveOtaFlow.d.ts +38 -0
  76. package/build/react/MentraLiveOtaFlow.d.ts.map +1 -0
  77. package/build/react/MentraLiveOtaFlow.js +528 -0
  78. package/build/react/MentraLiveOtaFlow.js.map +1 -0
  79. package/build/react/index.d.ts +2 -0
  80. package/build/react/index.d.ts.map +1 -0
  81. package/build/react/index.js +2 -0
  82. package/build/react/index.js.map +1 -0
  83. package/build/react/useEngineSnapshot.d.ts +2 -0
  84. package/build/react/useEngineSnapshot.d.ts.map +1 -0
  85. package/build/react/useEngineSnapshot.js +14 -0
  86. package/build/react/useEngineSnapshot.js.map +1 -0
  87. package/build/runtime/bootstrap.d.ts +24 -1
  88. package/build/runtime/bootstrap.d.ts.map +1 -1
  89. package/build/runtime/bootstrap.js +17 -0
  90. package/build/runtime/bootstrap.js.map +1 -1
  91. package/build/runtime/scanQrSeam.d.ts +7 -0
  92. package/build/runtime/scanQrSeam.d.ts.map +1 -0
  93. package/build/runtime/scanQrSeam.js +16 -0
  94. package/build/runtime/scanQrSeam.js.map +1 -0
  95. package/build/services/AppRegistry.d.ts +41 -57
  96. package/build/services/AppRegistry.d.ts.map +1 -1
  97. package/build/services/AppRegistry.js +208 -144
  98. package/build/services/AppRegistry.js.map +1 -1
  99. package/build/services/AudioCloudUplink.d.ts +12 -0
  100. package/build/services/AudioCloudUplink.d.ts.map +1 -1
  101. package/build/services/AudioCloudUplink.js +22 -1
  102. package/build/services/AudioCloudUplink.js.map +1 -1
  103. package/build/services/AudioPlaybackService.d.ts +41 -2
  104. package/build/services/AudioPlaybackService.d.ts.map +1 -1
  105. package/build/services/AudioPlaybackService.js +250 -33
  106. package/build/services/AudioPlaybackService.js.map +1 -1
  107. package/build/services/BlobStore.d.ts +2 -1
  108. package/build/services/BlobStore.d.ts.map +1 -1
  109. package/build/services/BlobStore.js +17 -9
  110. package/build/services/BlobStore.js.map +1 -1
  111. package/build/services/CloudAudioSubscriptionSync.d.ts.map +1 -1
  112. package/build/services/CloudAudioSubscriptionSync.js +13 -1
  113. package/build/services/CloudAudioSubscriptionSync.js.map +1 -1
  114. package/build/services/CloudClientService.d.ts +15 -0
  115. package/build/services/CloudClientService.d.ts.map +1 -1
  116. package/build/services/CloudClientService.js +93 -1
  117. package/build/services/CloudClientService.js.map +1 -1
  118. package/build/services/DeviceEventRouter.js +5 -5
  119. package/build/services/DeviceEventRouter.js.map +1 -1
  120. package/build/services/ForegroundLocationPermission.d.ts +13 -0
  121. package/build/services/ForegroundLocationPermission.d.ts.map +1 -0
  122. package/build/services/ForegroundLocationPermission.js +12 -0
  123. package/build/services/ForegroundLocationPermission.js.map +1 -0
  124. package/build/services/GlassesSettingsSync.d.ts.map +1 -1
  125. package/build/services/GlassesSettingsSync.js +9 -3
  126. package/build/services/GlassesSettingsSync.js.map +1 -1
  127. package/build/services/GlassesStatusProjection.d.ts +2 -1
  128. package/build/services/GlassesStatusProjection.d.ts.map +1 -1
  129. package/build/services/GlassesStatusProjection.js +15 -8
  130. package/build/services/GlassesStatusProjection.js.map +1 -1
  131. package/build/services/HotspotOtaTransport.d.ts +29 -0
  132. package/build/services/HotspotOtaTransport.d.ts.map +1 -0
  133. package/build/services/HotspotOtaTransport.js +146 -0
  134. package/build/services/HotspotOtaTransport.js.map +1 -0
  135. package/build/services/HotspotShutdown.d.ts +17 -0
  136. package/build/services/HotspotShutdown.d.ts.map +1 -0
  137. package/build/services/HotspotShutdown.js +29 -0
  138. package/build/services/HotspotShutdown.js.map +1 -0
  139. package/build/services/LocalDisplayManager.d.ts +15 -0
  140. package/build/services/LocalDisplayManager.d.ts.map +1 -1
  141. package/build/services/LocalDisplayManager.js +106 -20
  142. package/build/services/LocalDisplayManager.js.map +1 -1
  143. package/build/services/LocalMiniappRuntime.d.ts +74 -2
  144. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  145. package/build/services/LocalMiniappRuntime.js +785 -291
  146. package/build/services/LocalMiniappRuntime.js.map +1 -1
  147. package/build/services/LocalMiniappStorage.d.ts +32 -0
  148. package/build/services/LocalMiniappStorage.d.ts.map +1 -0
  149. package/build/services/LocalMiniappStorage.js +66 -0
  150. package/build/services/LocalMiniappStorage.js.map +1 -0
  151. package/build/services/LocalMiniappUserIdentity.d.ts +20 -0
  152. package/build/services/LocalMiniappUserIdentity.d.ts.map +1 -0
  153. package/build/services/LocalMiniappUserIdentity.js +43 -0
  154. package/build/services/LocalMiniappUserIdentity.js.map +1 -0
  155. package/build/services/LocalSttFallbackCoordinator.d.ts +9 -6
  156. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
  157. package/build/services/LocalSttFallbackCoordinator.js +18 -12
  158. package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
  159. package/build/services/MicStateCoordinator.d.ts +42 -1
  160. package/build/services/MicStateCoordinator.d.ts.map +1 -1
  161. package/build/services/MicStateCoordinator.js +141 -3
  162. package/build/services/MicStateCoordinator.js.map +1 -1
  163. package/build/services/MiniappLauncher.d.ts.map +1 -1
  164. package/build/services/MiniappLauncher.js +23 -3
  165. package/build/services/MiniappLauncher.js.map +1 -1
  166. package/build/services/MiniappLiveness.d.ts +12 -0
  167. package/build/services/MiniappLiveness.d.ts.map +1 -0
  168. package/build/services/MiniappLiveness.js +16 -0
  169. package/build/services/MiniappLiveness.js.map +1 -0
  170. package/build/services/NativeHttpResponse.d.ts +3 -0
  171. package/build/services/NativeHttpResponse.d.ts.map +1 -0
  172. package/build/services/NativeHttpResponse.js +6 -0
  173. package/build/services/NativeHttpResponse.js.map +1 -0
  174. package/build/services/OtaArtifactDownloader.d.ts +65 -0
  175. package/build/services/OtaArtifactDownloader.d.ts.map +1 -0
  176. package/build/services/OtaArtifactDownloader.js +226 -0
  177. package/build/services/OtaArtifactDownloader.js.map +1 -0
  178. package/build/services/OtaAutoChain.d.ts +34 -0
  179. package/build/services/OtaAutoChain.d.ts.map +1 -0
  180. package/build/services/OtaAutoChain.js +83 -0
  181. package/build/services/OtaAutoChain.js.map +1 -0
  182. package/build/services/OtaErrorMapping.d.ts +18 -0
  183. package/build/services/OtaErrorMapping.d.ts.map +1 -0
  184. package/build/services/OtaErrorMapping.js +63 -0
  185. package/build/services/OtaErrorMapping.js.map +1 -0
  186. package/build/services/OtaInstallCoordinator.d.ts +95 -15
  187. package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
  188. package/build/services/OtaInstallCoordinator.js +577 -130
  189. package/build/services/OtaInstallCoordinator.js.map +1 -1
  190. package/build/services/OtaService.d.ts.map +1 -1
  191. package/build/services/OtaService.js +8 -1
  192. package/build/services/OtaService.js.map +1 -1
  193. package/build/services/OtaUpdateCheckService.d.ts +39 -4
  194. package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
  195. package/build/services/OtaUpdateCheckService.js +138 -22
  196. package/build/services/OtaUpdateCheckService.js.map +1 -1
  197. package/build/services/PhoneCalendarHelpers.d.ts +32 -0
  198. package/build/services/PhoneCalendarHelpers.d.ts.map +1 -0
  199. package/build/services/PhoneCalendarHelpers.js +157 -0
  200. package/build/services/PhoneCalendarHelpers.js.map +1 -0
  201. package/build/services/PhoneCalendarService.d.ts +5 -0
  202. package/build/services/PhoneCalendarService.d.ts.map +1 -0
  203. package/build/services/PhoneCalendarService.js +45 -0
  204. package/build/services/PhoneCalendarService.js.map +1 -0
  205. package/build/services/PhoneCameraFovCoordinator.d.ts +30 -0
  206. package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -0
  207. package/build/services/PhoneCameraFovCoordinator.js +194 -0
  208. package/build/services/PhoneCameraFovCoordinator.js.map +1 -0
  209. package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
  210. package/build/services/PhoneNotificationsSync.js +12 -10
  211. package/build/services/PhoneNotificationsSync.js.map +1 -1
  212. package/build/services/PhonePhotoCoordinator.d.ts +26 -2
  213. package/build/services/PhonePhotoCoordinator.d.ts.map +1 -1
  214. package/build/services/PhonePhotoCoordinator.js +79 -9
  215. package/build/services/PhonePhotoCoordinator.js.map +1 -1
  216. package/build/services/PhoneStreamCoordinator.d.ts +8 -1
  217. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
  218. package/build/services/PhoneStreamCoordinator.js +125 -13
  219. package/build/services/PhoneStreamCoordinator.js.map +1 -1
  220. package/build/services/PhoneVideoCoordinator.d.ts +2 -0
  221. package/build/services/PhoneVideoCoordinator.d.ts.map +1 -1
  222. package/build/services/PhoneVideoCoordinator.js +10 -0
  223. package/build/services/PhoneVideoCoordinator.js.map +1 -1
  224. package/build/services/SceneRenderer.d.ts.map +1 -1
  225. package/build/services/SceneRenderer.js +15 -0
  226. package/build/services/SceneRenderer.js.map +1 -1
  227. package/build/services/SentenceTtsPipeline.d.ts +31 -0
  228. package/build/services/SentenceTtsPipeline.d.ts.map +1 -0
  229. package/build/services/SentenceTtsPipeline.js +67 -0
  230. package/build/services/SentenceTtsPipeline.js.map +1 -0
  231. package/build/services/SupportProfileSync.d.ts +22 -0
  232. package/build/services/SupportProfileSync.d.ts.map +1 -0
  233. package/build/services/SupportProfileSync.js +213 -0
  234. package/build/services/SupportProfileSync.js.map +1 -0
  235. package/build/services/TranscriptionRouting.d.ts +12 -0
  236. package/build/services/TranscriptionRouting.d.ts.map +1 -0
  237. package/build/services/TranscriptionRouting.js +24 -0
  238. package/build/services/TranscriptionRouting.js.map +1 -0
  239. package/build/services/TtsTextSanitizer.d.ts +5 -0
  240. package/build/services/TtsTextSanitizer.d.ts.map +1 -0
  241. package/build/services/TtsTextSanitizer.js +61 -0
  242. package/build/services/TtsTextSanitizer.js.map +1 -0
  243. package/build/services/WifiAdbRequest.d.ts +17 -0
  244. package/build/services/WifiAdbRequest.d.ts.map +1 -0
  245. package/build/services/WifiAdbRequest.js +35 -0
  246. package/build/services/WifiAdbRequest.js.map +1 -0
  247. package/build/services/asg/asgCameraApi.d.ts +43 -0
  248. package/build/services/asg/asgCameraApi.d.ts.map +1 -1
  249. package/build/services/asg/asgCameraApi.js +509 -26
  250. package/build/services/asg/asgCameraApi.js.map +1 -1
  251. package/build/services/asg/cameraRollExportCoordinator.d.ts +60 -0
  252. package/build/services/asg/cameraRollExportCoordinator.d.ts.map +1 -0
  253. package/build/services/asg/cameraRollExportCoordinator.js +618 -0
  254. package/build/services/asg/cameraRollExportCoordinator.js.map +1 -0
  255. package/build/services/asg/cameraRollExportLedger.d.ts +44 -0
  256. package/build/services/asg/cameraRollExportLedger.d.ts.map +1 -0
  257. package/build/services/asg/cameraRollExportLedger.js +78 -0
  258. package/build/services/asg/cameraRollExportLedger.js.map +1 -0
  259. package/build/services/asg/galleryNotices.d.ts +1 -1
  260. package/build/services/asg/galleryNotices.d.ts.map +1 -1
  261. package/build/services/asg/galleryNotices.js.map +1 -1
  262. package/build/services/asg/galleryPathMigration.d.ts +3 -0
  263. package/build/services/asg/galleryPathMigration.d.ts.map +1 -0
  264. package/build/services/asg/galleryPathMigration.js +26 -0
  265. package/build/services/asg/galleryPathMigration.js.map +1 -0
  266. package/build/services/asg/gallerySettingsService.d.ts +1 -0
  267. package/build/services/asg/gallerySettingsService.d.ts.map +1 -1
  268. package/build/services/asg/gallerySettingsService.js +2 -0
  269. package/build/services/asg/gallerySettingsService.js.map +1 -1
  270. package/build/services/asg/gallerySyncService.d.ts.map +1 -1
  271. package/build/services/asg/gallerySyncService.js +162 -56
  272. package/build/services/asg/gallerySyncService.js.map +1 -1
  273. package/build/services/asg/galleryTransferLedger.d.ts +58 -0
  274. package/build/services/asg/galleryTransferLedger.d.ts.map +1 -0
  275. package/build/services/asg/galleryTransferLedger.js +225 -0
  276. package/build/services/asg/galleryTransferLedger.js.map +1 -0
  277. package/build/services/asg/localNetworkTransport.d.ts +15 -0
  278. package/build/services/asg/localNetworkTransport.d.ts.map +1 -0
  279. package/build/services/asg/localNetworkTransport.js +144 -0
  280. package/build/services/asg/localNetworkTransport.js.map +1 -0
  281. package/build/services/asg/localStorageService.d.ts +18 -0
  282. package/build/services/asg/localStorageService.d.ts.map +1 -1
  283. package/build/services/asg/localStorageService.js +168 -19
  284. package/build/services/asg/localStorageService.js.map +1 -1
  285. package/build/services/asg/mediaProcessingQueue.d.ts +10 -0
  286. package/build/services/asg/mediaProcessingQueue.d.ts.map +1 -1
  287. package/build/services/asg/mediaProcessingQueue.js +193 -62
  288. package/build/services/asg/mediaProcessingQueue.js.map +1 -1
  289. package/build/services/audioPlaybackAssets.d.ts +8 -0
  290. package/build/services/audioPlaybackAssets.d.ts.map +1 -0
  291. package/build/services/audioPlaybackAssets.js +7 -0
  292. package/build/services/audioPlaybackAssets.js.map +1 -0
  293. package/build/services/gallerySyncClock.js +1 -1
  294. package/build/services/gallerySyncClock.js.map +1 -1
  295. package/build/services/glassesClockSync.d.ts.map +1 -1
  296. package/build/services/glassesClockSync.js +6 -2
  297. package/build/services/glassesClockSync.js.map +1 -1
  298. package/build/services/manifestActions.d.ts +7 -0
  299. package/build/services/manifestActions.d.ts.map +1 -0
  300. package/build/services/manifestActions.js +25 -0
  301. package/build/services/manifestActions.js.map +1 -0
  302. package/build/services/otaDisplayState.d.ts +23 -12
  303. package/build/services/otaDisplayState.d.ts.map +1 -1
  304. package/build/services/otaDisplayState.js +36 -14
  305. package/build/services/otaDisplayState.js.map +1 -1
  306. package/build/services/otaInstallPolicy.d.ts +16 -4
  307. package/build/services/otaInstallPolicy.d.ts.map +1 -1
  308. package/build/services/otaInstallPolicy.js +24 -3
  309. package/build/services/otaInstallPolicy.js.map +1 -1
  310. package/build/services/otaLegacyMapping.d.ts +1 -1
  311. package/build/services/otaLegacyMapping.d.ts.map +1 -1
  312. package/build/services/otaLegacyMapping.js.map +1 -1
  313. package/build/services/otaManifestPolicy.d.ts +14 -0
  314. package/build/services/otaManifestPolicy.d.ts.map +1 -0
  315. package/build/services/otaManifestPolicy.js +19 -0
  316. package/build/services/otaManifestPolicy.js.map +1 -0
  317. package/build/services/otaManifestUrl.d.ts +3 -0
  318. package/build/services/otaManifestUrl.d.ts.map +1 -0
  319. package/build/services/otaManifestUrl.js +38 -0
  320. package/build/services/otaManifestUrl.js.map +1 -0
  321. package/build/services/slimStreamStatus.d.ts +11 -0
  322. package/build/services/slimStreamStatus.d.ts.map +1 -1
  323. package/build/services/slimStreamStatus.js +14 -4
  324. package/build/services/slimStreamStatus.js.map +1 -1
  325. package/build/stores/apps.d.ts.map +1 -1
  326. package/build/stores/apps.js +11 -0
  327. package/build/stores/apps.js.map +1 -1
  328. package/build/stores/bluetoothSettingKeys.d.ts.map +1 -1
  329. package/build/stores/bluetoothSettingKeys.js +2 -0
  330. package/build/stores/bluetoothSettingKeys.js.map +1 -1
  331. package/build/stores/gallerySync.d.ts +2 -0
  332. package/build/stores/gallerySync.d.ts.map +1 -1
  333. package/build/stores/gallerySync.js +2 -0
  334. package/build/stores/gallerySync.js.map +1 -1
  335. package/build/stores/glasses.d.ts.map +1 -1
  336. package/build/stores/glasses.js +3 -0
  337. package/build/stores/glasses.js.map +1 -1
  338. package/build/stores/settings.d.ts +17 -0
  339. package/build/stores/settings.d.ts.map +1 -1
  340. package/build/stores/settings.js +157 -17
  341. package/build/stores/settings.js.map +1 -1
  342. package/build/types/applet.d.ts +2 -0
  343. package/build/types/applet.d.ts.map +1 -1
  344. package/build/types/applet.js.map +1 -1
  345. package/build/types/asg.d.ts +7 -0
  346. package/build/types/asg.d.ts.map +1 -1
  347. package/build/types/asg.js.map +1 -1
  348. package/build/types/enums.d.ts +2 -25
  349. package/build/types/enums.d.ts.map +1 -1
  350. package/build/types/enums.js +2 -27
  351. package/build/types/enums.js.map +1 -1
  352. package/build/types/hardware.d.ts +4 -13
  353. package/build/types/hardware.d.ts.map +1 -1
  354. package/build/types/hardware.js +15 -3
  355. package/build/types/hardware.js.map +1 -1
  356. package/build/types/index.d.ts +2 -6
  357. package/build/types/index.d.ts.map +1 -1
  358. package/build/types/index.js +2 -6
  359. package/build/types/index.js.map +1 -1
  360. package/build/utils/configuredDevHost.d.ts +6 -0
  361. package/build/utils/configuredDevHost.d.ts.map +1 -0
  362. package/build/utils/configuredDevHost.js +19 -0
  363. package/build/utils/configuredDevHost.js.map +1 -0
  364. package/build/utils/devMiniappLaunch.d.ts +19 -8
  365. package/build/utils/devMiniappLaunch.d.ts.map +1 -1
  366. package/build/utils/devMiniappLaunch.js +144 -21
  367. package/build/utils/devMiniappLaunch.js.map +1 -1
  368. package/build/utils/diagnosticContext.d.ts.map +1 -1
  369. package/build/utils/diagnosticContext.js +15 -17
  370. package/build/utils/diagnosticContext.js.map +1 -1
  371. package/build/utils/hardware/hardware.d.ts.map +1 -1
  372. package/build/utils/hardware/hardware.js +7 -3
  373. package/build/utils/hardware/hardware.js.map +1 -1
  374. package/build/utils/miniappDiagnostics.d.ts +64 -0
  375. package/build/utils/miniappDiagnostics.d.ts.map +1 -0
  376. package/build/utils/miniappDiagnostics.js +173 -0
  377. package/build/utils/miniappDiagnostics.js.map +1 -0
  378. package/build/utils/permissions/MediaLibraryPermissions.d.ts +11 -0
  379. package/build/utils/permissions/MediaLibraryPermissions.d.ts.map +1 -1
  380. package/build/utils/permissions/MediaLibraryPermissions.js +27 -4
  381. package/build/utils/permissions/MediaLibraryPermissions.js.map +1 -1
  382. package/build/utils/timers/timers.d.ts.map +1 -1
  383. package/build/utils/timers/timers.js +55 -18
  384. package/build/utils/timers/timers.js.map +1 -1
  385. package/package.json +59 -31
  386. package/src/assets/silence.wav +0 -0
  387. package/src/bluetooth-sdk/debug.ts +1 -0
  388. package/src/bluetooth-sdk/index.ts +2 -0
  389. package/src/bluetooth-sdk/photo-receiver.ts +2 -0
  390. package/src/bluetooth-sdk/react.ts +1 -0
  391. package/src/bluetooth-sdk/types.ts +1 -0
  392. package/src/engine.ts +9 -4
  393. package/src/facades/dev.ts +17 -12
  394. package/src/facades/display.ts +1 -1
  395. package/src/facades/gallery.ts +1 -1
  396. package/src/facades/glasses.ts +20 -7
  397. package/src/facades/glassesSettings.ts +5 -0
  398. package/src/facades/miniapps.ts +7 -0
  399. package/src/facades/ota.ts +23 -8
  400. package/src/facades/pairing.ts +15 -11
  401. package/src/facades/permissions.ts +14 -0
  402. package/src/facades/phoneNotifications.ts +4 -13
  403. package/src/facades/speech.ts +21 -7
  404. package/src/generated/releaseMetadata.ts +20 -0
  405. package/src/index.ts +39 -13
  406. package/src/react/MentraLiveOtaFlow.tsx +856 -0
  407. package/src/react/index.ts +7 -0
  408. package/src/react/useEngineSnapshot.ts +16 -0
  409. package/src/runtime/bootstrap.ts +33 -1
  410. package/src/runtime/scanQrSeam.ts +20 -0
  411. package/src/services/AppRegistry.ts +240 -149
  412. package/src/services/AudioCloudUplink.ts +23 -1
  413. package/src/services/AudioPlaybackService.ts +287 -38
  414. package/src/services/BlobStore.ts +22 -9
  415. package/src/services/CloudAudioSubscriptionSync.ts +13 -1
  416. package/src/services/CloudClientService.ts +96 -1
  417. package/src/services/DeviceEventRouter.ts +5 -5
  418. package/src/services/ForegroundLocationPermission.ts +24 -0
  419. package/src/services/GlassesSettingsSync.ts +9 -3
  420. package/src/services/GlassesStatusProjection.ts +16 -8
  421. package/src/services/HotspotOtaTransport.ts +184 -0
  422. package/src/services/HotspotShutdown.ts +41 -0
  423. package/src/services/LocalDisplayManager.ts +112 -21
  424. package/src/services/LocalMiniappRuntime.ts +967 -346
  425. package/src/services/LocalMiniappStorage.ts +82 -0
  426. package/src/services/LocalMiniappUserIdentity.ts +46 -0
  427. package/src/services/LocalSttFallbackCoordinator.ts +19 -12
  428. package/src/services/MicStateCoordinator.ts +169 -4
  429. package/src/services/MiniappLauncher.ts +30 -3
  430. package/src/services/MiniappLiveness.ts +24 -0
  431. package/src/services/NativeHttpResponse.ts +6 -0
  432. package/src/services/OtaArtifactDownloader.ts +312 -0
  433. package/src/services/OtaAutoChain.ts +106 -0
  434. package/src/services/OtaErrorMapping.ts +80 -0
  435. package/src/services/OtaInstallCoordinator.ts +649 -144
  436. package/src/services/OtaService.ts +11 -5
  437. package/src/services/OtaUpdateCheckService.ts +181 -21
  438. package/src/services/PhoneCalendarHelpers.ts +212 -0
  439. package/src/services/PhoneCalendarService.ts +65 -0
  440. package/src/services/PhoneCameraFovCoordinator.ts +210 -0
  441. package/src/services/PhoneNotificationsSync.ts +12 -10
  442. package/src/services/PhonePhotoCoordinator.ts +116 -18
  443. package/src/services/PhoneStreamCoordinator.ts +139 -25
  444. package/src/services/PhoneVideoCoordinator.ts +11 -0
  445. package/src/services/SceneRenderer.ts +16 -0
  446. package/src/services/SentenceTtsPipeline.ts +106 -0
  447. package/src/services/SupportProfileSync.ts +218 -0
  448. package/src/services/TranscriptionRouting.ts +37 -0
  449. package/src/services/TtsTextSanitizer.ts +66 -0
  450. package/src/services/WifiAdbRequest.ts +53 -0
  451. package/src/services/asg/asgCameraApi.ts +615 -33
  452. package/src/services/asg/cameraRollExportCoordinator.ts +627 -0
  453. package/src/services/asg/cameraRollExportLedger.ts +122 -0
  454. package/src/services/asg/galleryNotices.ts +1 -0
  455. package/src/services/asg/galleryPathMigration.ts +22 -0
  456. package/src/services/asg/gallerySettingsService.ts +3 -0
  457. package/src/services/asg/gallerySyncService.ts +184 -73
  458. package/src/services/asg/galleryTransferLedger.ts +312 -0
  459. package/src/services/asg/localNetworkTransport.ts +169 -0
  460. package/src/services/asg/localStorageService.ts +179 -24
  461. package/src/services/asg/mediaProcessingQueue.ts +209 -62
  462. package/src/services/audioPlaybackAssets.ts +8 -0
  463. package/src/services/gallerySyncClock.ts +1 -1
  464. package/src/services/glassesClockSync.ts +6 -2
  465. package/src/services/manifestActions.ts +30 -0
  466. package/src/services/otaDisplayState.ts +58 -17
  467. package/src/services/otaInstallPolicy.ts +30 -4
  468. package/src/services/otaLegacyMapping.ts +1 -1
  469. package/src/services/otaManifestPolicy.ts +42 -0
  470. package/src/services/otaManifestUrl.ts +44 -0
  471. package/src/services/slimStreamStatus.ts +16 -5
  472. package/src/stores/apps.ts +12 -0
  473. package/src/stores/bluetoothSettingKeys.ts +2 -0
  474. package/src/stores/gallerySync.ts +4 -0
  475. package/src/stores/glasses.ts +3 -0
  476. package/src/stores/settings.ts +179 -18
  477. package/src/types/applet.ts +2 -0
  478. package/src/types/asg.ts +7 -0
  479. package/src/types/enums.ts +3 -28
  480. package/src/types/hardware.ts +20 -13
  481. package/src/types/index.ts +2 -6
  482. package/src/utils/configuredDevHost.ts +17 -0
  483. package/src/utils/devMiniappLaunch.ts +151 -23
  484. package/src/utils/diagnosticContext.ts +17 -17
  485. package/src/utils/hardware/hardware.ts +7 -9
  486. package/src/utils/miniappDiagnostics.ts +226 -0
  487. package/src/utils/permissions/MediaLibraryPermissions.ts +35 -4
  488. package/src/utils/timers/timers.ts +57 -21
  489. package/build/devtools.d.ts +0 -11
  490. package/build/devtools.d.ts.map +0 -1
  491. package/build/devtools.js +0 -13
  492. package/build/devtools.js.map +0 -1
  493. package/build/internal.d.ts +0 -66
  494. package/build/internal.d.ts.map +0 -1
  495. package/build/internal.js +0 -89
  496. package/build/internal.js.map +0 -1
  497. package/build/services/asgOtaVersionUrl.d.ts +0 -2
  498. package/build/services/asgOtaVersionUrl.d.ts.map +0 -1
  499. package/build/services/asgOtaVersionUrl.js +0 -36
  500. package/build/services/asgOtaVersionUrl.js.map +0 -1
  501. package/src/devtools.ts +0 -13
  502. package/src/internal.ts +0 -158
  503. package/src/services/asgOtaVersionUrl.ts +0 -41
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ForegroundLocationPermission.d.ts","sourceRoot":"","sources":["../../src/services/ForegroundLocationPermission.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oCAAoC;IACnD,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,kCAAkC;IACjD,6BAA6B,IAAI,OAAO,CAAC,oCAAoC,CAAC,CAAA;IAC9E,iCAAiC,IAAI,OAAO,CAAC,oCAAoC,CAAC,CAAA;CACnF;AAED;;;GAGG;AACH,wBAAsB,mCAAmC,CACvD,MAAM,EAAE,kCAAkC,EAC1C,WAAW,EAAE,MAAM,MAAM,GACxB,OAAO,CAAC,oCAAoC,CAAC,CAO/C"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Resolve foreground location permission without invoking an Activity-bound
3
+ * Android permission request while the app is backgrounded.
4
+ */
5
+ export async function resolveForegroundLocationPermission(client, getAppState) {
6
+ const current = await client.getForegroundPermissionsAsync();
7
+ if (current.status === "granted" || getAppState() !== "active") {
8
+ return current;
9
+ }
10
+ return client.requestForegroundPermissionsAsync();
11
+ }
12
+ //# sourceMappingURL=ForegroundLocationPermission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ForegroundLocationPermission.js","sourceRoot":"","sources":["../../src/services/ForegroundLocationPermission.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mCAAmC,CACvD,MAA0C,EAC1C,WAAyB;IAEzB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,6BAA6B,EAAE,CAAA;IAC5D,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,WAAW,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC/D,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,OAAO,MAAM,CAAC,iCAAiC,EAAE,CAAA;AACnD,CAAC","sourcesContent":["export interface ForegroundLocationPermissionResponse {\n status: string\n}\n\nexport interface ForegroundLocationPermissionClient {\n getForegroundPermissionsAsync(): Promise<ForegroundLocationPermissionResponse>\n requestForegroundPermissionsAsync(): Promise<ForegroundLocationPermissionResponse>\n}\n\n/**\n * Resolve foreground location permission without invoking an Activity-bound\n * Android permission request while the app is backgrounded.\n */\nexport async function resolveForegroundLocationPermission(\n client: ForegroundLocationPermissionClient,\n getAppState: () => string,\n): Promise<ForegroundLocationPermissionResponse> {\n const current = await client.getForegroundPermissionsAsync()\n if (current.status === \"granted\" || getAppState() !== \"active\") {\n return current\n }\n\n return client.requestForegroundPermissionsAsync()\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"GlassesSettingsSync.d.ts","sourceRoot":"","sources":["../../src/services/GlassesSettingsSync.ts"],"names":[],"mappings":"AAmCA;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOzB;AAED,uEAAuE;AACvE,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAO/F;AAKD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC,CAK9D;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC,CAEjE;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CA8B/C;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAK9C"}
1
+ {"version":3,"file":"GlassesSettingsSync.d.ts","sourceRoot":"","sources":["../../src/services/GlassesSettingsSync.ts"],"names":[],"mappings":"AAuCA;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOzB;AAED,uEAAuE;AACvE,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAO/F;AAKD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC,CAM9D;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC,CAGjE;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CA8B/C;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAK9C"}
@@ -18,6 +18,7 @@ import { useSettingsStore, PAIRING_IDENTITY_KEYS } from "../stores/settings";
18
18
  import { useGlassesStore } from "../stores/glasses";
19
19
  import { createDebouncedPatchFlusher } from "../utils/debouncedPatch";
20
20
  import { isGlassesConnected } from "./GlassesReadiness";
21
+ import micStateCoordinator from "./MicStateCoordinator";
21
22
  /**
22
23
  * Change-pushes are debounced (300ms) and merged so a burst of setSetting
23
24
  * calls becomes ONE BLE write (wire v2 keeps BLE JSON small and infrequent).
@@ -26,7 +27,10 @@ import { isGlassesConnected } from "./GlassesReadiness";
26
27
  const flushBluetoothSettingsPatch = createDebouncedPatchFlusher((patch) => {
27
28
  // Settings can change while the glasses are disconnected — a native
28
29
  // rejection must not surface as an unhandled promise rejection.
29
- void Promise.resolve(BluetoothSdk.updateBluetoothSettings(patch)).catch((error) => {
30
+ // Apply mic overrides at flush time, not enqueue time: raw PCM can stop
31
+ // during the debounce window and a captured VAD=false would then be stale.
32
+ const runtimePatch = micStateCoordinator.applyRuntimeOverrides(patch);
33
+ void Promise.resolve(BluetoothSdk.updateBluetoothSettings(runtimePatch)).catch((error) => {
30
34
  console.warn("GlassesSettingsSync: updateBluetoothSettings failed:", error);
31
35
  });
32
36
  }, 300);
@@ -73,7 +77,8 @@ export async function pushAllBluetoothSettings() {
73
77
  // Returns the native write promise so callers can await the seed before the
74
78
  // connect handshake replays settings to the glasses (otherwise the handshake
75
79
  // can race ahead and replay stale native settings).
76
- await BluetoothSdk.updateBluetoothSettings(useSettingsStore.getState().getBluetoothSettings());
80
+ const settings = useSettingsStore.getState().getBluetoothSettings();
81
+ await BluetoothSdk.updateBluetoothSettings(micStateCoordinator.applyRuntimeOverrides(settings));
77
82
  }
78
83
  /**
79
84
  * Push the device-settings set MINUS the pairing identity. The on-connect
@@ -84,7 +89,8 @@ export async function pushAllBluetoothSettings() {
84
89
  * with pre-promotion empties (wiping the pairing it had just made).
85
90
  */
86
91
  export async function pushDeviceSettingsOnConnect() {
87
- await BluetoothSdk.updateBluetoothSettings(stripPairingIdentity(useSettingsStore.getState().getBluetoothSettings()));
92
+ const settings = stripPairingIdentity(useSettingsStore.getState().getBluetoothSettings());
93
+ await BluetoothSdk.updateBluetoothSettings(micStateCoordinator.applyRuntimeOverrides(settings));
88
94
  }
89
95
  export function startGlassesSettingsSync() {
90
96
  if (unsubChange || unsubConnect)
@@ -1 +1 @@
1
- {"version":3,"file":"GlassesSettingsSync.js","sourceRoot":"","sources":["../../src/services/GlassesSettingsSync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Glasses settings sync — engine-owned. Keeps the connected glasses in sync with\n * the phone's device settings (`BLUETOOTH_SETTING_KEYS`) over the bluetooth-sdk, so\n * `engine.glasses.settings.set()` (and any other settings-store write) reaches the\n * device for ANY host — not just the first-party Mentra app, where this used to live\n * in MantleManager.\n *\n * Two triggers:\n * 1. on change — push the keys that changed.\n * 2. on (re)connect — push the FULL set, so a freshly-connected device gets the\n * phone's current settings (not just future changes).\n *\n * Started by `engine.start()`. Idempotent.\n */\nimport {shallow} from \"zustand/shallow\"\n\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport {useSettingsStore, PAIRING_IDENTITY_KEYS} from \"../stores/settings\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {createDebouncedPatchFlusher} from \"../utils/debouncedPatch\"\nimport {isGlassesConnected} from \"./GlassesReadiness\"\n\n/**\n * Change-pushes are debounced (300ms) and merged so a burst of setSetting\n * calls becomes ONE BLE write (wire v2 keeps BLE JSON small and infrequent).\n * The full on-connect/seed pushes stay direct — callers await their ordering.\n */\nconst flushBluetoothSettingsPatch = createDebouncedPatchFlusher<Record<string, unknown>>((patch) => {\n // Settings can change while the glasses are disconnected — a native\n // rejection must not surface as an unhandled promise rejection.\n void Promise.resolve(BluetoothSdk.updateBluetoothSettings(patch)).catch((error) => {\n console.warn(\"GlassesSettingsSync: updateBluetoothSettings failed:\", error)\n })\n}, 300)\n\n/**\n * The changed-keys diff for the change-push, MINUS the pairing-identity keys.\n * Identity is native-authoritative (promoted on pairing success, cleared on\n * forget, echoed down via save_setting) and reaches native only through the\n * explicit full seeds. Pushing identity from the change subscription would\n * close a feedback loop: native echo → store setSetting → change-push →\n * native apply → echo…, which self-sustains the moment two different values\n * are in flight (e.g. a boot demotion crossing a native promotion) and flaps\n * the pairing UI.\n */\nexport function diffBluetoothSettingsForPush(\n settings: Record<string, unknown>,\n previous: Record<string, unknown>,\n): Record<string, unknown> {\n const changed: Record<string, unknown> = {}\n for (const key in settings) {\n if (PAIRING_IDENTITY_KEYS.includes(key)) continue\n if (settings[key] !== previous[key]) changed[key] = settings[key]\n }\n return changed\n}\n\n/** A copy of the settings record without the pairing-identity keys. */\nexport function stripPairingIdentity(settings: Record<string, unknown>): Record<string, unknown> {\n const stripped: Record<string, unknown> = {}\n for (const key in settings) {\n if (PAIRING_IDENTITY_KEYS.includes(key)) continue\n stripped[key] = settings[key]\n }\n return stripped\n}\n\nlet unsubChange: (() => void) | null = null\nlet unsubConnect: (() => void) | null = null\n\n/**\n * Push the FULL current device-settings set — identity included — to native.\n * This is the explicit identity SEED, for the flows where native genuinely\n * needs the phone's persisted identity BEFORE it can act: the device-store\n * hydration at start, the pre-connect seed (connectDefault targets the seeded\n * identity), the post-demotion re-push, and the abandon re-seed.\n */\nexport async function pushAllBluetoothSettings(): Promise<void> {\n // Returns the native write promise so callers can await the seed before the\n // connect handshake replays settings to the glasses (otherwise the handshake\n // can race ahead and replay stale native settings).\n await BluetoothSdk.updateBluetoothSettings(useSettingsStore.getState().getBluetoothSettings())\n}\n\n/**\n * Push the device-settings set MINUS the pairing identity. The on-connect\n * replay uses this: while connected, NATIVE owns the identity (it promotes at\n * device-ready and echoes down), and the JS snapshot can be mid-relay stale —\n * on Mentra Live \"connected\" lands together with device-ready, and a full\n * replay raced the promotion echoes and overwrote the just-promoted identity\n * with pre-promotion empties (wiping the pairing it had just made).\n */\nexport async function pushDeviceSettingsOnConnect(): Promise<void> {\n await BluetoothSdk.updateBluetoothSettings(stripPairingIdentity(useSettingsStore.getState().getBluetoothSettings()))\n}\n\nexport function startGlassesSettingsSync(): void {\n if (unsubChange || unsubConnect) return\n\n // 1. Push only the keys that changed (matching the prior MantleManager sync).\n // Pairing identity is excluded — see diffBluetoothSettingsForPush.\n unsubChange = useSettingsStore.subscribe(\n (state) => state.getBluetoothSettings(),\n (settings: Record<string, unknown>, previous: Record<string, unknown>) => {\n const changed = diffBluetoothSettingsForPush(settings, previous)\n if (Object.keys(changed).length > 0) {\n flushBluetoothSettingsPatch(changed)\n }\n },\n {equalityFn: shallow},\n )\n\n // 2. Push the device settings whenever the glasses transition to connected —\n // identity EXCLUDED: native owns the identity it just promoted, and a full\n // replay here raced the promotion echoes (see pushDeviceSettingsOnConnect).\n let wasConnected = isGlassesConnected(useGlassesStore.getState().connection)\n unsubConnect = useGlassesStore.subscribe(() => {\n const connected = isGlassesConnected(useGlassesStore.getState().connection)\n if (connected && !wasConnected) {\n // Background sync: log-and-continue if the device drops right after connect.\n void pushDeviceSettingsOnConnect().catch((error) => {\n console.warn(\"GlassesSettingsSync: on-connect settings push failed:\", error)\n })\n }\n wasConnected = connected\n })\n}\n\nexport function stopGlassesSettingsSync(): void {\n unsubChange?.()\n unsubConnect?.()\n unsubChange = null\n unsubConnect = null\n}\n"]}
1
+ {"version":3,"file":"GlassesSettingsSync.js","sourceRoot":"","sources":["../../src/services/GlassesSettingsSync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Glasses settings sync — engine-owned. Keeps the connected glasses in sync with\n * the phone's device settings (`BLUETOOTH_SETTING_KEYS`) over the bluetooth-sdk, so\n * `engine.glasses.settings.set()` (and any other settings-store write) reaches the\n * device for ANY host — not just the first-party Mentra app, where this used to live\n * in MantleManager.\n *\n * Two triggers:\n * 1. on change — push the keys that changed.\n * 2. on (re)connect — push the FULL set, so a freshly-connected device gets the\n * phone's current settings (not just future changes).\n *\n * Started by `engine.start()`. Idempotent.\n */\nimport {shallow} from \"zustand/shallow\"\n\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport {useSettingsStore, PAIRING_IDENTITY_KEYS} from \"../stores/settings\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {createDebouncedPatchFlusher} from \"../utils/debouncedPatch\"\nimport {isGlassesConnected} from \"./GlassesReadiness\"\nimport micStateCoordinator from \"./MicStateCoordinator\"\n\n/**\n * Change-pushes are debounced (300ms) and merged so a burst of setSetting\n * calls becomes ONE BLE write (wire v2 keeps BLE JSON small and infrequent).\n * The full on-connect/seed pushes stay direct — callers await their ordering.\n */\nconst flushBluetoothSettingsPatch = createDebouncedPatchFlusher<Record<string, unknown>>((patch) => {\n // Settings can change while the glasses are disconnected — a native\n // rejection must not surface as an unhandled promise rejection.\n // Apply mic overrides at flush time, not enqueue time: raw PCM can stop\n // during the debounce window and a captured VAD=false would then be stale.\n const runtimePatch = micStateCoordinator.applyRuntimeOverrides(patch)\n void Promise.resolve(BluetoothSdk.updateBluetoothSettings(runtimePatch)).catch((error) => {\n console.warn(\"GlassesSettingsSync: updateBluetoothSettings failed:\", error)\n })\n}, 300)\n\n/**\n * The changed-keys diff for the change-push, MINUS the pairing-identity keys.\n * Identity is native-authoritative (promoted on pairing success, cleared on\n * forget, echoed down via save_setting) and reaches native only through the\n * explicit full seeds. Pushing identity from the change subscription would\n * close a feedback loop: native echo → store setSetting → change-push →\n * native apply → echo…, which self-sustains the moment two different values\n * are in flight (e.g. a boot demotion crossing a native promotion) and flaps\n * the pairing UI.\n */\nexport function diffBluetoothSettingsForPush(\n settings: Record<string, unknown>,\n previous: Record<string, unknown>,\n): Record<string, unknown> {\n const changed: Record<string, unknown> = {}\n for (const key in settings) {\n if (PAIRING_IDENTITY_KEYS.includes(key)) continue\n if (settings[key] !== previous[key]) changed[key] = settings[key]\n }\n return changed\n}\n\n/** A copy of the settings record without the pairing-identity keys. */\nexport function stripPairingIdentity(settings: Record<string, unknown>): Record<string, unknown> {\n const stripped: Record<string, unknown> = {}\n for (const key in settings) {\n if (PAIRING_IDENTITY_KEYS.includes(key)) continue\n stripped[key] = settings[key]\n }\n return stripped\n}\n\nlet unsubChange: (() => void) | null = null\nlet unsubConnect: (() => void) | null = null\n\n/**\n * Push the FULL current device-settings set — identity included — to native.\n * This is the explicit identity SEED, for the flows where native genuinely\n * needs the phone's persisted identity BEFORE it can act: the device-store\n * hydration at start, the pre-connect seed (connectDefault targets the seeded\n * identity), the post-demotion re-push, and the abandon re-seed.\n */\nexport async function pushAllBluetoothSettings(): Promise<void> {\n // Returns the native write promise so callers can await the seed before the\n // connect handshake replays settings to the glasses (otherwise the handshake\n // can race ahead and replay stale native settings).\n const settings = useSettingsStore.getState().getBluetoothSettings()\n await BluetoothSdk.updateBluetoothSettings(micStateCoordinator.applyRuntimeOverrides(settings))\n}\n\n/**\n * Push the device-settings set MINUS the pairing identity. The on-connect\n * replay uses this: while connected, NATIVE owns the identity (it promotes at\n * device-ready and echoes down), and the JS snapshot can be mid-relay stale —\n * on Mentra Live \"connected\" lands together with device-ready, and a full\n * replay raced the promotion echoes and overwrote the just-promoted identity\n * with pre-promotion empties (wiping the pairing it had just made).\n */\nexport async function pushDeviceSettingsOnConnect(): Promise<void> {\n const settings = stripPairingIdentity(useSettingsStore.getState().getBluetoothSettings())\n await BluetoothSdk.updateBluetoothSettings(micStateCoordinator.applyRuntimeOverrides(settings))\n}\n\nexport function startGlassesSettingsSync(): void {\n if (unsubChange || unsubConnect) return\n\n // 1. Push only the keys that changed (matching the prior MantleManager sync).\n // Pairing identity is excluded — see diffBluetoothSettingsForPush.\n unsubChange = useSettingsStore.subscribe(\n (state) => state.getBluetoothSettings(),\n (settings: Record<string, unknown>, previous: Record<string, unknown>) => {\n const changed = diffBluetoothSettingsForPush(settings, previous)\n if (Object.keys(changed).length > 0) {\n flushBluetoothSettingsPatch(changed)\n }\n },\n {equalityFn: shallow},\n )\n\n // 2. Push the device settings whenever the glasses transition to connected —\n // identity EXCLUDED: native owns the identity it just promoted, and a full\n // replay here raced the promotion echoes (see pushDeviceSettingsOnConnect).\n let wasConnected = isGlassesConnected(useGlassesStore.getState().connection)\n unsubConnect = useGlassesStore.subscribe(() => {\n const connected = isGlassesConnected(useGlassesStore.getState().connection)\n if (connected && !wasConnected) {\n // Background sync: log-and-continue if the device drops right after connect.\n void pushDeviceSettingsOnConnect().catch((error) => {\n console.warn(\"GlassesSettingsSync: on-connect settings push failed:\", error)\n })\n }\n wasConnected = connected\n })\n}\n\nexport function stopGlassesSettingsSync(): void {\n unsubChange?.()\n unsubConnect?.()\n unsubChange = null\n unsubConnect = null\n}\n"]}
@@ -1,3 +1,4 @@
1
- export declare function startGlassesStatusProjection(): void;
1
+ import type { GlassesStatus } from "@mentra/bluetooth-sdk/internal";
2
+ export declare function startGlassesStatusProjection(forwarder?: (status: Partial<GlassesStatus>) => void): Promise<void>;
2
3
  export declare function stopGlassesStatusProjection(): void;
3
4
  //# sourceMappingURL=GlassesStatusProjection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GlassesStatusProjection.d.ts","sourceRoot":"","sources":["../../src/services/GlassesStatusProjection.ts"],"names":[],"mappings":"AAqBA,wBAAgB,4BAA4B,IAAI,IAAI,CA6CnD;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAIlD"}
1
+ {"version":3,"file":"GlassesStatusProjection.d.ts","sourceRoot":"","sources":["../../src/services/GlassesStatusProjection.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,gCAAgC,CAAA;AASjE,wBAAgB,4BAA4B,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDhH;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAMlD"}
@@ -14,16 +14,19 @@
14
14
  import BluetoothSdk from "@mentra/bluetooth-sdk/internal";
15
15
  import { useCoreStore } from "../stores/core";
16
16
  import { useGlassesStore } from "../stores/glasses";
17
- import localMiniappRuntime from "./LocalMiniappRuntime";
18
17
  let unsubs = [];
19
18
  let projectionRunId = 0;
20
- export function startGlassesStatusProjection() {
19
+ let glassesStatusForwarder = null;
20
+ let hydrationPromise = null;
21
+ export function startGlassesStatusProjection(forwarder) {
22
+ if (forwarder)
23
+ glassesStatusForwarder = forwarder;
21
24
  if (unsubs.length)
22
- return;
25
+ return hydrationPromise ?? Promise.resolve();
23
26
  const runId = ++projectionRunId;
24
27
  let bluetoothEventSeen = false;
25
28
  let glassesEventSeen = false;
26
- void BluetoothSdk.getBluetoothStatus()
29
+ const bluetoothHydration = BluetoothSdk.getBluetoothStatus()
27
30
  .then((status) => {
28
31
  if (runId !== projectionRunId || bluetoothEventSeen)
29
32
  return;
@@ -32,7 +35,7 @@ export function startGlassesStatusProjection() {
32
35
  .catch((error) => {
33
36
  console.warn("GlassesStatusProjection: getBluetoothStatus failed", error);
34
37
  });
35
- void BluetoothSdk.getGlassesStatus()
38
+ const glassesHydration = BluetoothSdk.getGlassesStatus()
36
39
  .then((status) => {
37
40
  if (runId !== projectionRunId || glassesEventSeen)
38
41
  return;
@@ -46,20 +49,24 @@ export function startGlassesStatusProjection() {
46
49
  bluetoothEventSeen = true;
47
50
  useCoreStore.getState().setCoreInfo(changed);
48
51
  }));
49
- // Glasses status -> glasses store (+ forward to local miniapps; clear any stale
50
- // OTA-available flag on disconnect).
52
+ // Glasses status -> glasses store (+ optional full-runtime forwarding to local
53
+ // miniapps; clear any stale OTA-available flag on disconnect).
51
54
  unsubs.push(BluetoothSdk.onGlassesStatus((changed) => {
52
55
  glassesEventSeen = true;
53
56
  useGlassesStore.getState().setGlassesInfo(changed);
54
- localMiniappRuntime.forwardEvent("glasses_connection_state", changed);
57
+ glassesStatusForwarder?.(changed);
55
58
  if (changed.connection?.state === "disconnected") {
56
59
  useGlassesStore.getState().setOtaUpdateAvailable(null);
57
60
  }
58
61
  }));
62
+ hydrationPromise = Promise.allSettled([bluetoothHydration, glassesHydration]).then(() => undefined);
63
+ return hydrationPromise;
59
64
  }
60
65
  export function stopGlassesStatusProjection() {
61
66
  projectionRunId++;
62
67
  unsubs.forEach((unsub) => unsub());
63
68
  unsubs = [];
69
+ glassesStatusForwarder = null;
70
+ hydrationPromise = null;
64
71
  }
65
72
  //# sourceMappingURL=GlassesStatusProjection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GlassesStatusProjection.js","sourceRoot":"","sources":["../../src/services/GlassesStatusProjection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,YAAY,MAAM,gCAAgC,CAAA;AACzD,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAA;AACjD,OAAO,mBAAmB,MAAM,uBAAuB,CAAA;AAEvD,IAAI,MAAM,GAAsB,EAAE,CAAA;AAClC,IAAI,eAAe,GAAG,CAAC,CAAA;AAEvB,MAAM,UAAU,4BAA4B;IAC1C,IAAI,MAAM,CAAC,MAAM;QAAE,OAAM;IAEzB,MAAM,KAAK,GAAG,EAAE,eAAe,CAAA;IAC/B,IAAI,kBAAkB,GAAG,KAAK,CAAA;IAC9B,IAAI,gBAAgB,GAAG,KAAK,CAAA;IAE5B,KAAK,YAAY,CAAC,kBAAkB,EAAE;SACnC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;QACf,IAAI,KAAK,KAAK,eAAe,IAAI,kBAAkB;YAAE,OAAM;QAC3D,YAAY,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IAC7C,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACf,OAAO,CAAC,IAAI,CAAC,oDAAoD,EAAE,KAAK,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IAEJ,KAAK,YAAY,CAAC,gBAAgB,EAAE;SACjC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;QACf,IAAI,KAAK,KAAK,eAAe,IAAI,gBAAgB;YAAE,OAAM;QACzD,eAAe,CAAC,QAAQ,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA;IACnD,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACf,OAAO,CAAC,IAAI,CAAC,kDAAkD,EAAE,KAAK,CAAC,CAAA;IACzE,CAAC,CAAC,CAAA;IAEJ,0CAA0C;IAC1C,MAAM,CAAC,IAAI,CACT,YAAY,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE,EAAE;QACzC,kBAAkB,GAAG,IAAI,CAAA;QACzB,YAAY,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;IAC9C,CAAC,CAAC,CACH,CAAA;IAED,gFAAgF;IAChF,qCAAqC;IACrC,MAAM,CAAC,IAAI,CACT,YAAY,CAAC,eAAe,CAAC,CAAC,OAAO,EAAE,EAAE;QACvC,gBAAgB,GAAG,IAAI,CAAA;QACvB,eAAe,CAAC,QAAQ,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,CAAA;QAClD,mBAAmB,CAAC,YAAY,CAAC,0BAA0B,EAAE,OAAO,CAAC,CAAA;QACrE,IAAI,OAAO,CAAC,UAAU,EAAE,KAAK,KAAK,cAAc,EAAE,CAAC;YACjD,eAAe,CAAC,QAAQ,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAA;QACxD,CAAC;IACH,CAAC,CAAC,CACH,CAAA;AACH,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,eAAe,EAAE,CAAA;IACjB,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAA;IAClC,MAAM,GAAG,EAAE,CAAA;AACb,CAAC","sourcesContent":["/**\n * Glasses status projection — engine-owned. Subscribes to the native bluetooth-sdk\n * status events and projects them into the engine device stores, so engine's own\n * services (which react to those stores) work for ANY host — not just the first-party\n * Mentra app, where this used to live in MantleManager.\n *\n * This is the INBOUND mirror of GlassesSettingsSync: that pushes the settings store\n * OUT to the device; this pulls device status IN to the stores. It's the feed that\n * the rest of the engine runtime depends on (MicStateCoordinator, the settings-sync\n * on-connect trigger, the facade read-models all read these stores).\n *\n * Started by `engine.start()`. Idempotent.\n */\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport {useCoreStore} from \"../stores/core\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport localMiniappRuntime from \"./LocalMiniappRuntime\"\n\nlet unsubs: Array<() => void> = []\nlet projectionRunId = 0\n\nexport function startGlassesStatusProjection(): void {\n if (unsubs.length) return\n\n const runId = ++projectionRunId\n let bluetoothEventSeen = false\n let glassesEventSeen = false\n\n void BluetoothSdk.getBluetoothStatus()\n .then((status) => {\n if (runId !== projectionRunId || bluetoothEventSeen) return\n useCoreStore.getState().setCoreInfo(status)\n })\n .catch((error) => {\n console.warn(\"GlassesStatusProjection: getBluetoothStatus failed\", error)\n })\n\n void BluetoothSdk.getGlassesStatus()\n .then((status) => {\n if (runId !== projectionRunId || glassesEventSeen) return\n useGlassesStore.getState().setGlassesInfo(status)\n })\n .catch((error) => {\n console.warn(\"GlassesStatusProjection: getGlassesStatus failed\", error)\n })\n\n // Bluetooth-adapter status -> core store.\n unsubs.push(\n BluetoothSdk.onBluetoothStatus((changed) => {\n bluetoothEventSeen = true\n useCoreStore.getState().setCoreInfo(changed)\n }),\n )\n\n // Glasses status -> glasses store (+ forward to local miniapps; clear any stale\n // OTA-available flag on disconnect).\n unsubs.push(\n BluetoothSdk.onGlassesStatus((changed) => {\n glassesEventSeen = true\n useGlassesStore.getState().setGlassesInfo(changed)\n localMiniappRuntime.forwardEvent(\"glasses_connection_state\", changed)\n if (changed.connection?.state === \"disconnected\") {\n useGlassesStore.getState().setOtaUpdateAvailable(null)\n }\n }),\n )\n}\n\nexport function stopGlassesStatusProjection(): void {\n projectionRunId++\n unsubs.forEach((unsub) => unsub())\n unsubs = []\n}\n"]}
1
+ {"version":3,"file":"GlassesStatusProjection.js","sourceRoot":"","sources":["../../src/services/GlassesStatusProjection.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Glasses status projection — engine-owned. Subscribes to the native bluetooth-sdk\n * status events and projects them into the engine device stores, so engine's own\n * services (which react to those stores) work for ANY host — not just the first-party\n * Mentra app, where this used to live in MantleManager.\n *\n * This is the INBOUND mirror of GlassesSettingsSync: that pushes the settings store\n * OUT to the device; this pulls device status IN to the stores. It's the feed that\n * the rest of the engine runtime depends on (MicStateCoordinator, the settings-sync\n * on-connect trigger, the facade read-models all read these stores).\n *\n * Started by `engine.start()`. Idempotent.\n */\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport type {GlassesStatus} from \"@mentra/bluetooth-sdk/internal\"\nimport {useCoreStore} from \"../stores/core\"\nimport {useGlassesStore} from \"../stores/glasses\"\n\nlet unsubs: Array<() => void> = []\nlet projectionRunId = 0\nlet glassesStatusForwarder: ((status: Partial<GlassesStatus>) => void) | null = null\nlet hydrationPromise: Promise<void> | null = null\n\nexport function startGlassesStatusProjection(forwarder?: (status: Partial<GlassesStatus>) => void): Promise<void> {\n if (forwarder) glassesStatusForwarder = forwarder\n if (unsubs.length) return hydrationPromise ?? Promise.resolve()\n\n const runId = ++projectionRunId\n let bluetoothEventSeen = false\n let glassesEventSeen = false\n\n const bluetoothHydration = BluetoothSdk.getBluetoothStatus()\n .then((status) => {\n if (runId !== projectionRunId || bluetoothEventSeen) return\n useCoreStore.getState().setCoreInfo(status)\n })\n .catch((error) => {\n console.warn(\"GlassesStatusProjection: getBluetoothStatus failed\", error)\n })\n\n const glassesHydration = BluetoothSdk.getGlassesStatus()\n .then((status) => {\n if (runId !== projectionRunId || glassesEventSeen) return\n useGlassesStore.getState().setGlassesInfo(status)\n })\n .catch((error) => {\n console.warn(\"GlassesStatusProjection: getGlassesStatus failed\", error)\n })\n\n // Bluetooth-adapter status -> core store.\n unsubs.push(\n BluetoothSdk.onBluetoothStatus((changed) => {\n bluetoothEventSeen = true\n useCoreStore.getState().setCoreInfo(changed)\n }),\n )\n\n // Glasses status -> glasses store (+ optional full-runtime forwarding to local\n // miniapps; clear any stale OTA-available flag on disconnect).\n unsubs.push(\n BluetoothSdk.onGlassesStatus((changed) => {\n glassesEventSeen = true\n useGlassesStore.getState().setGlassesInfo(changed)\n glassesStatusForwarder?.(changed)\n if (changed.connection?.state === \"disconnected\") {\n useGlassesStore.getState().setOtaUpdateAvailable(null)\n }\n }),\n )\n\n hydrationPromise = Promise.allSettled([bluetoothHydration, glassesHydration]).then(() => undefined)\n return hydrationPromise\n}\n\nexport function stopGlassesStatusProjection(): void {\n projectionRunId++\n unsubs.forEach((unsub) => unsub())\n unsubs = []\n glassesStatusForwarder = null\n hydrationPromise = null\n}\n"]}
@@ -0,0 +1,29 @@
1
+ import type { OtaCheckCurrentGlassesResult } from "./OtaUpdateCheckService";
2
+ import { type OtaArtifactDownloadProgress } from "./OtaArtifactDownloader";
3
+ export type HotspotOtaPhase = "idle" | "downloading" | "starting_hotspot" | "joining_hotspot" | "serving";
4
+ export type HotspotOtaProgress = {
5
+ phase: HotspotOtaPhase;
6
+ artifact?: OtaArtifactDownloadProgress;
7
+ };
8
+ export type HotspotOtaErrorCode = "hotspot_wifi_permission_denied" | "hotspot_start_failed" | "hotspot_join_failed" | "hotspot_server_failed";
9
+ export declare class HotspotOtaTransportError extends Error {
10
+ readonly code: HotspotOtaErrorCode;
11
+ constructor(code: HotspotOtaErrorCode, message: string);
12
+ }
13
+ /** Owns the single phone-side endpoint and network lease for one hotspot OTA attempt. */
14
+ declare class HotspotOtaTransport {
15
+ private active;
16
+ private prepared;
17
+ private hotspotRequested;
18
+ private localNetworkConnected;
19
+ private serverStarted;
20
+ private teardownPromise;
21
+ prepare(checkResult: OtaCheckCurrentGlassesResult, onProgress?: (progress: HotspotOtaProgress) => void): Promise<string>;
22
+ /** Android 13+ requires the nearby-WiFi runtime grant before WifiNetworkSpecifier is usable. */
23
+ private ensureAndroidWifiPermission;
24
+ private downloadIosArtifact;
25
+ teardown(): Promise<void>;
26
+ }
27
+ export declare const hotspotOtaTransport: HotspotOtaTransport;
28
+ export {};
29
+ //# sourceMappingURL=HotspotOtaTransport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HotspotOtaTransport.d.ts","sourceRoot":"","sources":["../../src/services/HotspotOtaTransport.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,yBAAyB,CAAA;AACzE,OAAO,EAML,KAAK,2BAA2B,EAEjC,MAAM,yBAAyB,CAAA;AAIhC,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,aAAa,GAAG,kBAAkB,GAAG,iBAAiB,GAAG,SAAS,CAAA;AAEzG,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,eAAe,CAAA;IACtB,QAAQ,CAAC,EAAE,2BAA2B,CAAA;CACvC,CAAA;AAED,MAAM,MAAM,mBAAmB,GAC3B,gCAAgC,GAChC,sBAAsB,GACtB,qBAAqB,GACrB,uBAAuB,CAAA;AAE3B,qBAAa,wBAAyB,SAAQ,KAAK;aAE/B,IAAI,EAAE,mBAAmB;gBAAzB,IAAI,EAAE,mBAAmB,EACzC,OAAO,EAAE,MAAM;CAKlB;AAED,yFAAyF;AACzF,cAAM,mBAAmB;IACvB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,gBAAgB,CAAQ;IAChC,OAAO,CAAC,qBAAqB,CAAQ;IACrC,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,eAAe,CAA6B;IAE9C,OAAO,CACX,WAAW,EAAE,4BAA4B,EACzC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,GAClD,OAAO,CAAC,MAAM,CAAC;IAuElB,gGAAgG;YAClF,2BAA2B;IAczC,OAAO,CAAC,mBAAmB,CAa1B;IAEK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CA4BhC;AAED,eAAO,MAAM,mBAAmB,qBAA4B,CAAA"}
@@ -0,0 +1,146 @@
1
+ import BluetoothSdk, { isEnabledHotspotStatus, MentraOtaServer } from "@mentra/bluetooth-sdk/internal";
2
+ // One coordinator selects the native Android or iOS staging implementation at runtime.
3
+ // eslint-disable-next-line react-native/split-platform-components
4
+ import { PermissionsAndroid, Platform } from "react-native";
5
+ import { cleanupArtifacts, OtaArtifactError, planArtifacts, prepareArtifacts, rewriteManifestForLocalServer, } from "./OtaArtifactDownloader";
6
+ import { disableHotspotWithRetry } from "./HotspotShutdown";
7
+ import { localNetworkTransport } from "./asg/localNetworkTransport";
8
+ export class HotspotOtaTransportError extends Error {
9
+ code;
10
+ constructor(code, message) {
11
+ super(message);
12
+ this.code = code;
13
+ this.name = "HotspotOtaTransportError";
14
+ }
15
+ }
16
+ /** Owns the single phone-side endpoint and network lease for one hotspot OTA attempt. */
17
+ class HotspotOtaTransport {
18
+ active = false;
19
+ prepared = [];
20
+ hotspotRequested = false;
21
+ localNetworkConnected = false;
22
+ serverStarted = false;
23
+ teardownPromise = null;
24
+ async prepare(checkResult, onProgress) {
25
+ if (this.teardownPromise)
26
+ await this.teardownPromise;
27
+ if (this.active) {
28
+ throw new Error("A hotspot OTA transport is already active");
29
+ }
30
+ if (!checkResult.manifestBody) {
31
+ throw new Error("The selected OTA check has no manifest body");
32
+ }
33
+ let phase = "downloading";
34
+ try {
35
+ await this.ensureAndroidWifiPermission();
36
+ onProgress?.({ phase: "downloading" });
37
+ this.prepared = await prepareArtifacts(planArtifacts(checkResult), (artifact) => onProgress?.({ phase: "downloading", artifact }), Platform.OS === "ios" ? this.downloadIosArtifact : undefined);
38
+ phase = "starting_hotspot";
39
+ onProgress?.({ phase: "starting_hotspot" });
40
+ this.hotspotRequested = true;
41
+ const hotspot = await BluetoothSdk.setHotspotState(true);
42
+ if (!isEnabledHotspotStatus(hotspot)) {
43
+ throw new HotspotOtaTransportError("hotspot_start_failed", "Mentra Live did not return hotspot credentials");
44
+ }
45
+ phase = "joining_hotspot";
46
+ onProgress?.({ phase: "joining_hotspot" });
47
+ const scopedAddress = await localNetworkTransport.connect(hotspot.ssid, hotspot.password);
48
+ this.localNetworkConnected = true;
49
+ let localAddress = scopedAddress;
50
+ if (Platform.OS === "ios") {
51
+ try {
52
+ localAddress = await MentraOtaServer.waitForWifiAddress(hotspot.localIp, 15_000);
53
+ }
54
+ catch (error) {
55
+ throw new HotspotOtaTransportError("hotspot_join_failed", error instanceof Error ? error.message : String(error));
56
+ }
57
+ }
58
+ const artifactPaths = Object.fromEntries(this.prepared.map((artifact) => [artifact.sha256, artifact.filePath]));
59
+ // Start exactly one native listener to learn its selected port, then atomically replace
60
+ // the placeholder with the immutable rewritten manifest before ota_start is sent.
61
+ const server = await MentraOtaServer.startOtaServer("{}", artifactPaths, localAddress);
62
+ this.serverStarted = true;
63
+ const manifest = rewriteManifestForLocalServer(checkResult.manifestBody, this.prepared, server.baseUrl);
64
+ const published = await MentraOtaServer.startOtaServer(manifest, artifactPaths, server.host);
65
+ if (published.manifestUrl !== server.manifestUrl) {
66
+ throw new Error("Local OTA server endpoint changed while publishing the manifest");
67
+ }
68
+ this.active = true;
69
+ onProgress?.({ phase: "serving" });
70
+ return published.manifestUrl;
71
+ }
72
+ catch (error) {
73
+ const joined = this.localNetworkConnected;
74
+ await this.teardown();
75
+ if (error instanceof OtaArtifactError || error instanceof HotspotOtaTransportError) {
76
+ throw error;
77
+ }
78
+ const message = error instanceof Error ? error.message : String(error);
79
+ if (phase === "starting_hotspot") {
80
+ throw new HotspotOtaTransportError("hotspot_start_failed", message);
81
+ }
82
+ if (phase === "joining_hotspot" && !joined) {
83
+ throw new HotspotOtaTransportError("hotspot_join_failed", message);
84
+ }
85
+ throw new HotspotOtaTransportError("hotspot_server_failed", message);
86
+ }
87
+ }
88
+ /** Android 13+ requires the nearby-WiFi runtime grant before WifiNetworkSpecifier is usable. */
89
+ async ensureAndroidWifiPermission() {
90
+ if (Platform.OS !== "android")
91
+ return;
92
+ const permission = PermissionsAndroid.PERMISSIONS.NEARBY_WIFI_DEVICES;
93
+ if (await PermissionsAndroid.check(permission))
94
+ return;
95
+ const result = await PermissionsAndroid.request(permission);
96
+ if (result !== PermissionsAndroid.RESULTS.GRANTED) {
97
+ throw new HotspotOtaTransportError("hotspot_wifi_permission_denied", "Nearby devices permission is required to connect to the glasses hotspot");
98
+ }
99
+ }
100
+ downloadIosArtifact = async (entry, destination, onProgress) => {
101
+ const subscription = MentraOtaServer.addListener("artifactDownloadProgress", (event) => {
102
+ if (event.destination === destination)
103
+ onProgress?.(event.bytesWritten, event.contentLength);
104
+ });
105
+ try {
106
+ return await MentraOtaServer.downloadArtifact(entry.url, destination);
107
+ }
108
+ finally {
109
+ subscription.remove();
110
+ }
111
+ };
112
+ async teardown() {
113
+ if (this.teardownPromise)
114
+ return this.teardownPromise;
115
+ this.teardownPromise = (async () => {
116
+ if (this.hotspotRequested) {
117
+ const hotspotStopped = await disableHotspotWithRetry(() => BluetoothSdk.setHotspotState(false), {
118
+ // A completed APK step has just replaced ASG. Let the new command path
119
+ // settle before asking it to tear down the SystemUI-owned access point.
120
+ initialDelayMs: this.serverStarted ? 750 : 0,
121
+ });
122
+ if (!hotspotStopped) {
123
+ console.warn("[OTA_PROGRESS] glasses hotspot shutdown was not confirmed after bounded retries");
124
+ }
125
+ }
126
+ if (this.serverStarted)
127
+ await MentraOtaServer.stopOtaServer().catch(() => { });
128
+ if (this.localNetworkConnected)
129
+ await localNetworkTransport.disconnect().catch(() => { });
130
+ await cleanupArtifacts().catch(() => { });
131
+ this.prepared = [];
132
+ this.active = false;
133
+ this.serverStarted = false;
134
+ this.localNetworkConnected = false;
135
+ this.hotspotRequested = false;
136
+ })();
137
+ try {
138
+ await this.teardownPromise;
139
+ }
140
+ finally {
141
+ this.teardownPromise = null;
142
+ }
143
+ }
144
+ }
145
+ export const hotspotOtaTransport = new HotspotOtaTransport();
146
+ //# sourceMappingURL=HotspotOtaTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HotspotOtaTransport.js","sourceRoot":"","sources":["../../src/services/HotspotOtaTransport.ts"],"names":[],"mappings":"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","sourcesContent":["import BluetoothSdk, {isEnabledHotspotStatus, MentraOtaServer} from \"@mentra/bluetooth-sdk/internal\"\n// One coordinator selects the native Android or iOS staging implementation at runtime.\n// eslint-disable-next-line react-native/split-platform-components\nimport {PermissionsAndroid, Platform} from \"react-native\"\nimport type {OtaCheckCurrentGlassesResult} from \"./OtaUpdateCheckService\"\nimport {\n cleanupArtifacts,\n OtaArtifactError,\n planArtifacts,\n prepareArtifacts,\n rewriteManifestForLocalServer,\n type OtaArtifactDownloadProgress,\n type PreparedOtaArtifact,\n} from \"./OtaArtifactDownloader\"\nimport {disableHotspotWithRetry} from \"./HotspotShutdown\"\nimport {localNetworkTransport} from \"./asg/localNetworkTransport\"\n\nexport type HotspotOtaPhase = \"idle\" | \"downloading\" | \"starting_hotspot\" | \"joining_hotspot\" | \"serving\"\n\nexport type HotspotOtaProgress = {\n phase: HotspotOtaPhase\n artifact?: OtaArtifactDownloadProgress\n}\n\nexport type HotspotOtaErrorCode =\n | \"hotspot_wifi_permission_denied\"\n | \"hotspot_start_failed\"\n | \"hotspot_join_failed\"\n | \"hotspot_server_failed\"\n\nexport class HotspotOtaTransportError extends Error {\n constructor(\n public readonly code: HotspotOtaErrorCode,\n message: string,\n ) {\n super(message)\n this.name = \"HotspotOtaTransportError\"\n }\n}\n\n/** Owns the single phone-side endpoint and network lease for one hotspot OTA attempt. */\nclass HotspotOtaTransport {\n private active = false\n private prepared: PreparedOtaArtifact[] = []\n private hotspotRequested = false\n private localNetworkConnected = false\n private serverStarted = false\n private teardownPromise: Promise<void> | null = null\n\n async prepare(\n checkResult: OtaCheckCurrentGlassesResult,\n onProgress?: (progress: HotspotOtaProgress) => void,\n ): Promise<string> {\n if (this.teardownPromise) await this.teardownPromise\n if (this.active) {\n throw new Error(\"A hotspot OTA transport is already active\")\n }\n if (!checkResult.manifestBody) {\n throw new Error(\"The selected OTA check has no manifest body\")\n }\n\n let phase: HotspotOtaPhase = \"downloading\"\n try {\n await this.ensureAndroidWifiPermission()\n onProgress?.({phase: \"downloading\"})\n this.prepared = await prepareArtifacts(\n planArtifacts(checkResult),\n (artifact) => onProgress?.({phase: \"downloading\", artifact}),\n Platform.OS === \"ios\" ? this.downloadIosArtifact : undefined,\n )\n\n phase = \"starting_hotspot\"\n onProgress?.({phase: \"starting_hotspot\"})\n this.hotspotRequested = true\n const hotspot = await BluetoothSdk.setHotspotState(true)\n if (!isEnabledHotspotStatus(hotspot)) {\n throw new HotspotOtaTransportError(\"hotspot_start_failed\", \"Mentra Live did not return hotspot credentials\")\n }\n phase = \"joining_hotspot\"\n onProgress?.({phase: \"joining_hotspot\"})\n const scopedAddress = await localNetworkTransport.connect(hotspot.ssid, hotspot.password)\n this.localNetworkConnected = true\n let localAddress = scopedAddress\n if (Platform.OS === \"ios\") {\n try {\n localAddress = await MentraOtaServer.waitForWifiAddress(hotspot.localIp, 15_000)\n } catch (error) {\n throw new HotspotOtaTransportError(\n \"hotspot_join_failed\",\n error instanceof Error ? error.message : String(error),\n )\n }\n }\n const artifactPaths = Object.fromEntries(this.prepared.map((artifact) => [artifact.sha256, artifact.filePath]))\n // Start exactly one native listener to learn its selected port, then atomically replace\n // the placeholder with the immutable rewritten manifest before ota_start is sent.\n const server = await MentraOtaServer.startOtaServer(\"{}\", artifactPaths, localAddress)\n this.serverStarted = true\n const manifest = rewriteManifestForLocalServer(checkResult.manifestBody, this.prepared, server.baseUrl)\n const published = await MentraOtaServer.startOtaServer(manifest, artifactPaths, server.host)\n if (published.manifestUrl !== server.manifestUrl) {\n throw new Error(\"Local OTA server endpoint changed while publishing the manifest\")\n }\n this.active = true\n onProgress?.({phase: \"serving\"})\n return published.manifestUrl\n } catch (error) {\n const joined = this.localNetworkConnected\n await this.teardown()\n if (error instanceof OtaArtifactError || error instanceof HotspotOtaTransportError) {\n throw error\n }\n const message = error instanceof Error ? error.message : String(error)\n if (phase === \"starting_hotspot\") {\n throw new HotspotOtaTransportError(\"hotspot_start_failed\", message)\n }\n if (phase === \"joining_hotspot\" && !joined) {\n throw new HotspotOtaTransportError(\"hotspot_join_failed\", message)\n }\n throw new HotspotOtaTransportError(\"hotspot_server_failed\", message)\n }\n }\n\n /** Android 13+ requires the nearby-WiFi runtime grant before WifiNetworkSpecifier is usable. */\n private async ensureAndroidWifiPermission(): Promise<void> {\n if (Platform.OS !== \"android\") return\n\n const permission = PermissionsAndroid.PERMISSIONS.NEARBY_WIFI_DEVICES\n if (await PermissionsAndroid.check(permission)) return\n const result = await PermissionsAndroid.request(permission)\n if (result !== PermissionsAndroid.RESULTS.GRANTED) {\n throw new HotspotOtaTransportError(\n \"hotspot_wifi_permission_denied\",\n \"Nearby devices permission is required to connect to the glasses hotspot\",\n )\n }\n }\n\n private downloadIosArtifact = async (\n entry: {url: string},\n destination: string,\n onProgress?: (bytesWritten: number, contentLength: number) => void,\n ): Promise<{statusCode: number}> => {\n const subscription = MentraOtaServer.addListener(\"artifactDownloadProgress\", (event) => {\n if (event.destination === destination) onProgress?.(event.bytesWritten, event.contentLength)\n })\n try {\n return await MentraOtaServer.downloadArtifact(entry.url, destination)\n } finally {\n subscription.remove()\n }\n }\n\n async teardown(): Promise<void> {\n if (this.teardownPromise) return this.teardownPromise\n this.teardownPromise = (async () => {\n if (this.hotspotRequested) {\n const hotspotStopped = await disableHotspotWithRetry(() => BluetoothSdk.setHotspotState(false), {\n // A completed APK step has just replaced ASG. Let the new command path\n // settle before asking it to tear down the SystemUI-owned access point.\n initialDelayMs: this.serverStarted ? 750 : 0,\n })\n if (!hotspotStopped) {\n console.warn(\"[OTA_PROGRESS] glasses hotspot shutdown was not confirmed after bounded retries\")\n }\n }\n if (this.serverStarted) await MentraOtaServer.stopOtaServer().catch(() => {})\n if (this.localNetworkConnected) await localNetworkTransport.disconnect().catch(() => {})\n await cleanupArtifacts().catch(() => {})\n this.prepared = []\n this.active = false\n this.serverStarted = false\n this.localNetworkConnected = false\n this.hotspotRequested = false\n })()\n try {\n await this.teardownPromise\n } finally {\n this.teardownPromise = null\n }\n }\n}\n\nexport const hotspotOtaTransport = new HotspotOtaTransport()\n"]}
@@ -0,0 +1,17 @@
1
+ type HotspotState = {
2
+ state: "disabled" | "enabled";
3
+ };
4
+ type HotspotShutdownOptions = {
5
+ attempts?: number;
6
+ initialDelayMs?: number;
7
+ retryDelayMs?: number;
8
+ sleep?: (delayMs: number) => Promise<void>;
9
+ };
10
+ /**
11
+ * Disable a glasses hotspot with a bounded retry. ASG APK replacement keeps the
12
+ * BLE link alive through BES, but the first command after the new ASG process
13
+ * appears can still land while its command path is settling.
14
+ */
15
+ export declare function disableHotspotWithRetry(requestDisabled: () => Promise<HotspotState>, options?: HotspotShutdownOptions): Promise<boolean>;
16
+ export {};
17
+ //# sourceMappingURL=HotspotShutdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HotspotShutdown.d.ts","sourceRoot":"","sources":["../../src/services/HotspotShutdown.ts"],"names":[],"mappings":"AAAA,KAAK,YAAY,GAAG;IAAC,KAAK,EAAE,UAAU,GAAG,SAAS,CAAA;CAAC,CAAA;AAEnD,KAAK,sBAAsB,GAAG;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3C,CAAA;AAID;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,eAAe,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,EAC5C,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,OAAO,CAAC,CAqBlB"}
@@ -0,0 +1,29 @@
1
+ const sleep = (delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs));
2
+ /**
3
+ * Disable a glasses hotspot with a bounded retry. ASG APK replacement keeps the
4
+ * BLE link alive through BES, but the first command after the new ASG process
5
+ * appears can still land while its command path is settling.
6
+ */
7
+ export async function disableHotspotWithRetry(requestDisabled, options = {}) {
8
+ const attempts = Math.max(1, options.attempts ?? 2);
9
+ const initialDelayMs = Math.max(0, options.initialDelayMs ?? 0);
10
+ const retryDelayMs = Math.max(0, options.retryDelayMs ?? 500);
11
+ const wait = options.sleep ?? sleep;
12
+ if (initialDelayMs > 0)
13
+ await wait(initialDelayMs);
14
+ for (let attempt = 1; attempt <= attempts; attempt += 1) {
15
+ try {
16
+ const status = await requestDisabled();
17
+ if (status.state === "disabled")
18
+ return true;
19
+ }
20
+ catch {
21
+ // A lost command is indistinguishable from a response timeout here. Retry
22
+ // while the phone still owns the hotspot network and local server.
23
+ }
24
+ if (attempt < attempts && retryDelayMs > 0)
25
+ await wait(retryDelayMs);
26
+ }
27
+ return false;
28
+ }
29
+ //# sourceMappingURL=HotspotShutdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HotspotShutdown.js","sourceRoot":"","sources":["../../src/services/HotspotShutdown.ts"],"names":[],"mappings":"AASA,MAAM,KAAK,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;AAE/F;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,eAA4C,EAC5C,UAAkC,EAAE;IAEpC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAA;IACnD,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,cAAc,IAAI,CAAC,CAAC,CAAA;IAC/D,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,IAAI,GAAG,CAAC,CAAA;IAC7D,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAA;IAEnC,IAAI,cAAc,GAAG,CAAC;QAAE,MAAM,IAAI,CAAC,cAAc,CAAC,CAAA;IAElD,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,QAAQ,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QACxD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,eAAe,EAAE,CAAA;YACtC,IAAI,MAAM,CAAC,KAAK,KAAK,UAAU;gBAAE,OAAO,IAAI,CAAA;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,0EAA0E;YAC1E,mEAAmE;QACrE,CAAC;QAED,IAAI,OAAO,GAAG,QAAQ,IAAI,YAAY,GAAG,CAAC;YAAE,MAAM,IAAI,CAAC,YAAY,CAAC,CAAA;IACtE,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["type HotspotState = {state: \"disabled\" | \"enabled\"}\n\ntype HotspotShutdownOptions = {\n attempts?: number\n initialDelayMs?: number\n retryDelayMs?: number\n sleep?: (delayMs: number) => Promise<void>\n}\n\nconst sleep = (delayMs: number) => new Promise<void>((resolve) => setTimeout(resolve, delayMs))\n\n/**\n * Disable a glasses hotspot with a bounded retry. ASG APK replacement keeps the\n * BLE link alive through BES, but the first command after the new ASG process\n * appears can still land while its command path is settling.\n */\nexport async function disableHotspotWithRetry(\n requestDisabled: () => Promise<HotspotState>,\n options: HotspotShutdownOptions = {},\n): Promise<boolean> {\n const attempts = Math.max(1, options.attempts ?? 2)\n const initialDelayMs = Math.max(0, options.initialDelayMs ?? 0)\n const retryDelayMs = Math.max(0, options.retryDelayMs ?? 500)\n const wait = options.sleep ?? sleep\n\n if (initialDelayMs > 0) await wait(initialDelayMs)\n\n for (let attempt = 1; attempt <= attempts; attempt += 1) {\n try {\n const status = await requestDisabled()\n if (status.state === \"disabled\") return true\n } catch {\n // A lost command is indistinguishable from a response timeout here. Retry\n // while the phone still owns the hotspot network and local server.\n }\n\n if (attempt < attempts && retryDelayMs > 0) await wait(retryDelayMs)\n }\n\n return false\n}\n"]}
@@ -74,6 +74,8 @@ declare class LocalDisplayManager {
74
74
  * miniapp is foreground.
75
75
  */
76
76
  onCoreAppChange(packageName: string | null): void;
77
+ /** Report-safe ownership snapshot for incident diagnostics. */
78
+ getDiagnosticSnapshot(): Record<string, unknown>;
77
79
  /**
78
80
  * A local miniapp is going away. Clean up all state associated with it.
79
81
  */
@@ -88,7 +90,20 @@ declare class LocalDisplayManager {
88
90
  * the boot queue (resolved when drained or superseded).
89
91
  */
90
92
  request(packageName: string, payload: DisplayPayload, resolve?: DisplayRequestResolver): void;
93
+ /**
94
+ * End a package's temporary display early. If it currently owns the main
95
+ * view, release its background lock and restore the foreground miniapp's
96
+ * saved frame. A dismissal for a package that is no longer visible is a
97
+ * no-op.
98
+ */
99
+ dismiss(packageName: string): void;
91
100
  private arbitrateAndSend;
101
+ /**
102
+ * An app cleared its display ("render nothing"). Same semantics as its
103
+ * frame expiring: give up ownership, restore the core app's still-valid
104
+ * display if there is one, otherwise clear the glasses.
105
+ */
106
+ private handleAppClear;
92
107
  private sendNow;
93
108
  /**
94
109
  * Send a scene through SceneRenderer. On positioning devices this emits a
@@ -1 +1 @@
1
- {"version":3,"file":"LocalDisplayManager.d.ts","sourceRoot":"","sources":["../../src/services/LocalDisplayManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAQH,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,wBAAwB,CAAA;AAO7D,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAA;IACpC,kFAAkF;IAClF,MAAM,CAAC,EAAE;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAC,CAAA;IACrD,qEAAqE;IACrE,KAAK,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,+EAA+E;AAC/E,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,sBAAsB,GAAG,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAA;AA6C3E,cAAM,mBAAmB;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAmC;IAE1D,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,cAAc,CAA8B;IAEpD,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,SAAS,CAAsF;IAEvG,OAAO,CAAC,aAAa,CAAsB;IAE3C,6DAA6D;IAC7D,OAAO,CAAC,eAAe,CAAQ;IAC/B,OAAO,CAAC,mBAAmB,CAAQ;IACnC,OAAO,CAAC,wBAAwB,CAA4B;IAE5D,4BAA4B;IAC5B,OAAO,CAAC,GAAG,CAAiC;IAE5C,OAAO;WAEO,WAAW,IAAI,mBAAmB;IAWhD;;;;OAIG;IACI,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAmC9D;;;OAGG;IACI,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAexD;;OAEG;IACI,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAyC3C;;;;;;;;OAQG;IACI,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,IAAI;IA2BpG,OAAO,CAAC,gBAAgB;IAoExB,OAAO,CAAC,OAAO;IAmDf;;;;OAIG;IACH,OAAO,CAAC,SAAS;IAsCjB,OAAO,CAAC,YAAY;IAkCpB,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,qBAAqB;IAW7B,OAAO,CAAC,SAAS;IAiBjB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,OAAO;IAsCf;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAqCtB;;;;OAIG;IACI,eAAe,IAAI,IAAI;IAgB9B;;;;OAIG;IACI,aAAa,IAAI,IAAI;IAoB5B,OAAO,CAAC,gBAAgB;IAWxB,mCAAmC;IAC5B,cAAc,CAAC,EAAE,EAAE,MAAM,MAAM,GAAG,IAAI;IAI7C,+BAA+B;IACxB,aAAa,IAAI,IAAI;IAgB5B,6CAA6C;IACtC,YAAY,IAAI;QACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;QACtB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;QAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;QACxB,SAAS,EAAE,OAAO,CAAA;KACnB;CAQF;AAED,QAAA,MAAM,mBAAmB,qBAAoC,CAAA;AAC7D,eAAe,mBAAmB,CAAA;AAClC,OAAO,EAAC,mBAAmB,EAAC,CAAA"}
1
+ {"version":3,"file":"LocalDisplayManager.d.ts","sourceRoot":"","sources":["../../src/services/LocalDisplayManager.ts"],"names":[],"mappings":"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"}