@mentra/engine 0.1.0-dev.0 → 3.1.0-beta.100

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 (574) hide show
  1. package/README.md +73 -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/ota-transport.d.ts +2 -0
  11. package/build/bluetooth-sdk/ota-transport.d.ts.map +1 -0
  12. package/build/bluetooth-sdk/ota-transport.js +2 -0
  13. package/build/bluetooth-sdk/ota-transport.js.map +1 -0
  14. package/build/bluetooth-sdk/photo-receiver.d.ts +3 -0
  15. package/build/bluetooth-sdk/photo-receiver.d.ts.map +1 -0
  16. package/build/bluetooth-sdk/photo-receiver.js +3 -0
  17. package/build/bluetooth-sdk/photo-receiver.js.map +1 -0
  18. package/build/bluetooth-sdk/react.d.ts +2 -0
  19. package/build/bluetooth-sdk/react.d.ts.map +1 -0
  20. package/build/bluetooth-sdk/react.js +2 -0
  21. package/build/bluetooth-sdk/react.js.map +1 -0
  22. package/build/bluetooth-sdk/types.d.ts +2 -0
  23. package/build/bluetooth-sdk/types.d.ts.map +1 -0
  24. package/build/bluetooth-sdk/types.js +2 -0
  25. package/build/bluetooth-sdk/types.js.map +1 -0
  26. package/build/engine.d.ts +29 -18
  27. package/build/engine.d.ts.map +1 -1
  28. package/build/engine.js +9 -4
  29. package/build/engine.js.map +1 -1
  30. package/build/facades/dev.d.ts +3 -2
  31. package/build/facades/dev.d.ts.map +1 -1
  32. package/build/facades/dev.js +18 -12
  33. package/build/facades/dev.js.map +1 -1
  34. package/build/facades/display.d.ts +1 -1
  35. package/build/facades/display.d.ts.map +1 -1
  36. package/build/facades/display.js +1 -1
  37. package/build/facades/display.js.map +1 -1
  38. package/build/facades/gallery.js +1 -1
  39. package/build/facades/gallery.js.map +1 -1
  40. package/build/facades/glasses.d.ts +4 -13
  41. package/build/facades/glasses.d.ts.map +1 -1
  42. package/build/facades/glasses.js +21 -6
  43. package/build/facades/glasses.js.map +1 -1
  44. package/build/facades/glassesSettings.d.ts.map +1 -1
  45. package/build/facades/glassesSettings.js +1 -0
  46. package/build/facades/glassesSettings.js.map +1 -1
  47. package/build/facades/miniapps.d.ts +4 -0
  48. package/build/facades/miniapps.d.ts.map +1 -1
  49. package/build/facades/miniapps.js +5 -0
  50. package/build/facades/miniapps.js.map +1 -1
  51. package/build/facades/ota.d.ts +24 -21
  52. package/build/facades/ota.d.ts.map +1 -1
  53. package/build/facades/ota.js +31 -12
  54. package/build/facades/ota.js.map +1 -1
  55. package/build/facades/pairing.d.ts +12 -5
  56. package/build/facades/pairing.d.ts.map +1 -1
  57. package/build/facades/pairing.js +93 -17
  58. package/build/facades/pairing.js.map +1 -1
  59. package/build/facades/permissions.d.ts +10 -0
  60. package/build/facades/permissions.d.ts.map +1 -1
  61. package/build/facades/permissions.js +10 -0
  62. package/build/facades/permissions.js.map +1 -1
  63. package/build/facades/phoneNotifications.d.ts +0 -4
  64. package/build/facades/phoneNotifications.d.ts.map +1 -1
  65. package/build/facades/phoneNotifications.js +4 -14
  66. package/build/facades/phoneNotifications.js.map +1 -1
  67. package/build/facades/speech.d.ts +7 -6
  68. package/build/facades/speech.d.ts.map +1 -1
  69. package/build/facades/speech.js +1 -1
  70. package/build/facades/speech.js.map +1 -1
  71. package/build/generated/releaseMetadata.d.ts +12 -0
  72. package/build/generated/releaseMetadata.d.ts.map +1 -0
  73. package/build/generated/releaseMetadata.js +10 -0
  74. package/build/generated/releaseMetadata.js.map +1 -0
  75. package/build/index.d.ts +12 -10
  76. package/build/index.d.ts.map +1 -1
  77. package/build/index.js +7 -6
  78. package/build/index.js.map +1 -1
  79. package/build/react/MentraLiveOtaFlow.d.ts +44 -0
  80. package/build/react/MentraLiveOtaFlow.d.ts.map +1 -0
  81. package/build/react/MentraLiveOtaFlow.js +430 -0
  82. package/build/react/MentraLiveOtaFlow.js.map +1 -0
  83. package/build/react/index.d.ts +3 -0
  84. package/build/react/index.d.ts.map +1 -0
  85. package/build/react/index.js +3 -0
  86. package/build/react/index.js.map +1 -0
  87. package/build/react/useEngineSnapshot.d.ts +2 -0
  88. package/build/react/useEngineSnapshot.d.ts.map +1 -0
  89. package/build/react/useEngineSnapshot.js +14 -0
  90. package/build/react/useEngineSnapshot.js.map +1 -0
  91. package/build/react/useMentraLiveOta.d.ts +84 -0
  92. package/build/react/useMentraLiveOta.d.ts.map +1 -0
  93. package/build/react/useMentraLiveOta.js +627 -0
  94. package/build/react/useMentraLiveOta.js.map +1 -0
  95. package/build/runtime/bootstrap.d.ts +24 -1
  96. package/build/runtime/bootstrap.d.ts.map +1 -1
  97. package/build/runtime/bootstrap.js +17 -0
  98. package/build/runtime/bootstrap.js.map +1 -1
  99. package/build/runtime/scanQrSeam.d.ts +7 -0
  100. package/build/runtime/scanQrSeam.d.ts.map +1 -0
  101. package/build/runtime/scanQrSeam.js +16 -0
  102. package/build/runtime/scanQrSeam.js.map +1 -0
  103. package/build/services/AppRegistry.d.ts +41 -57
  104. package/build/services/AppRegistry.d.ts.map +1 -1
  105. package/build/services/AppRegistry.js +208 -144
  106. package/build/services/AppRegistry.js.map +1 -1
  107. package/build/services/AudioCloudUplink.d.ts +12 -0
  108. package/build/services/AudioCloudUplink.d.ts.map +1 -1
  109. package/build/services/AudioCloudUplink.js +22 -1
  110. package/build/services/AudioCloudUplink.js.map +1 -1
  111. package/build/services/AudioPlaybackService.d.ts +41 -2
  112. package/build/services/AudioPlaybackService.d.ts.map +1 -1
  113. package/build/services/AudioPlaybackService.js +250 -33
  114. package/build/services/AudioPlaybackService.js.map +1 -1
  115. package/build/services/BlobStore.d.ts +4 -1
  116. package/build/services/BlobStore.d.ts.map +1 -1
  117. package/build/services/BlobStore.js +80 -19
  118. package/build/services/BlobStore.js.map +1 -1
  119. package/build/services/CloudAudioSubscriptionSync.d.ts.map +1 -1
  120. package/build/services/CloudAudioSubscriptionSync.js +13 -1
  121. package/build/services/CloudAudioSubscriptionSync.js.map +1 -1
  122. package/build/services/CloudClientService.d.ts +15 -0
  123. package/build/services/CloudClientService.d.ts.map +1 -1
  124. package/build/services/CloudClientService.js +93 -1
  125. package/build/services/CloudClientService.js.map +1 -1
  126. package/build/services/DeviceEventRouter.js +5 -5
  127. package/build/services/DeviceEventRouter.js.map +1 -1
  128. package/build/services/DisplayProcessor.d.ts +3 -3
  129. package/build/services/DisplayProcessor.js +3 -3
  130. package/build/services/DisplayProcessor.js.map +1 -1
  131. package/build/services/ForegroundLocationPermission.d.ts +13 -0
  132. package/build/services/ForegroundLocationPermission.d.ts.map +1 -0
  133. package/build/services/ForegroundLocationPermission.js +12 -0
  134. package/build/services/ForegroundLocationPermission.js.map +1 -0
  135. package/build/services/GlassesSettingsSync.d.ts.map +1 -1
  136. package/build/services/GlassesSettingsSync.js +9 -3
  137. package/build/services/GlassesSettingsSync.js.map +1 -1
  138. package/build/services/GlassesStatusProjection.d.ts +15 -1
  139. package/build/services/GlassesStatusProjection.d.ts.map +1 -1
  140. package/build/services/GlassesStatusProjection.js +18 -11
  141. package/build/services/GlassesStatusProjection.js.map +1 -1
  142. package/build/services/HotspotOtaTransport.d.ts +29 -0
  143. package/build/services/HotspotOtaTransport.d.ts.map +1 -0
  144. package/build/services/HotspotOtaTransport.js +147 -0
  145. package/build/services/HotspotOtaTransport.js.map +1 -0
  146. package/build/services/HotspotShutdown.d.ts +17 -0
  147. package/build/services/HotspotShutdown.d.ts.map +1 -0
  148. package/build/services/HotspotShutdown.js +29 -0
  149. package/build/services/HotspotShutdown.js.map +1 -0
  150. package/build/services/LocalDisplayManager.d.ts +17 -3
  151. package/build/services/LocalDisplayManager.d.ts.map +1 -1
  152. package/build/services/LocalDisplayManager.js +108 -23
  153. package/build/services/LocalDisplayManager.js.map +1 -1
  154. package/build/services/LocalMiniappRuntime.d.ts +74 -2
  155. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  156. package/build/services/LocalMiniappRuntime.js +785 -291
  157. package/build/services/LocalMiniappRuntime.js.map +1 -1
  158. package/build/services/LocalMiniappStorage.d.ts +32 -0
  159. package/build/services/LocalMiniappStorage.d.ts.map +1 -0
  160. package/build/services/LocalMiniappStorage.js +66 -0
  161. package/build/services/LocalMiniappStorage.js.map +1 -0
  162. package/build/services/LocalMiniappUserIdentity.d.ts +20 -0
  163. package/build/services/LocalMiniappUserIdentity.d.ts.map +1 -0
  164. package/build/services/LocalMiniappUserIdentity.js +43 -0
  165. package/build/services/LocalMiniappUserIdentity.js.map +1 -0
  166. package/build/services/LocalSttFallbackCoordinator.d.ts +9 -6
  167. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
  168. package/build/services/LocalSttFallbackCoordinator.js +18 -12
  169. package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
  170. package/build/services/MicStateCoordinator.d.ts +42 -1
  171. package/build/services/MicStateCoordinator.d.ts.map +1 -1
  172. package/build/services/MicStateCoordinator.js +141 -3
  173. package/build/services/MicStateCoordinator.js.map +1 -1
  174. package/build/services/MiniappLauncher.d.ts.map +1 -1
  175. package/build/services/MiniappLauncher.js +23 -3
  176. package/build/services/MiniappLauncher.js.map +1 -1
  177. package/build/services/MiniappLiveness.d.ts +12 -0
  178. package/build/services/MiniappLiveness.d.ts.map +1 -0
  179. package/build/services/MiniappLiveness.js +16 -0
  180. package/build/services/MiniappLiveness.js.map +1 -0
  181. package/build/services/NativeHttpResponse.d.ts +3 -0
  182. package/build/services/NativeHttpResponse.d.ts.map +1 -0
  183. package/build/services/NativeHttpResponse.js +6 -0
  184. package/build/services/NativeHttpResponse.js.map +1 -0
  185. package/build/services/OtaArtifactDownloader.d.ts +65 -0
  186. package/build/services/OtaArtifactDownloader.d.ts.map +1 -0
  187. package/build/services/OtaArtifactDownloader.js +226 -0
  188. package/build/services/OtaArtifactDownloader.js.map +1 -0
  189. package/build/services/OtaAutoChain.d.ts +41 -0
  190. package/build/services/OtaAutoChain.d.ts.map +1 -0
  191. package/build/services/OtaAutoChain.js +91 -0
  192. package/build/services/OtaAutoChain.js.map +1 -0
  193. package/build/services/OtaErrorMapping.d.ts +18 -0
  194. package/build/services/OtaErrorMapping.d.ts.map +1 -0
  195. package/build/services/OtaErrorMapping.js +63 -0
  196. package/build/services/OtaErrorMapping.js.map +1 -0
  197. package/build/services/OtaInstallCoordinator.d.ts +120 -17
  198. package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
  199. package/build/services/OtaInstallCoordinator.js +605 -136
  200. package/build/services/OtaInstallCoordinator.js.map +1 -1
  201. package/build/services/OtaService.d.ts.map +1 -1
  202. package/build/services/OtaService.js +9 -2
  203. package/build/services/OtaService.js.map +1 -1
  204. package/build/services/OtaUpdateCheckService.d.ts +42 -4
  205. package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
  206. package/build/services/OtaUpdateCheckService.js +158 -26
  207. package/build/services/OtaUpdateCheckService.js.map +1 -1
  208. package/build/services/PhoneCalendarHelpers.d.ts +32 -0
  209. package/build/services/PhoneCalendarHelpers.d.ts.map +1 -0
  210. package/build/services/PhoneCalendarHelpers.js +157 -0
  211. package/build/services/PhoneCalendarHelpers.js.map +1 -0
  212. package/build/services/PhoneCalendarService.d.ts +5 -0
  213. package/build/services/PhoneCalendarService.d.ts.map +1 -0
  214. package/build/services/PhoneCalendarService.js +45 -0
  215. package/build/services/PhoneCalendarService.js.map +1 -0
  216. package/build/services/PhoneCameraFovCoordinator.d.ts +30 -0
  217. package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -0
  218. package/build/services/PhoneCameraFovCoordinator.js +194 -0
  219. package/build/services/PhoneCameraFovCoordinator.js.map +1 -0
  220. package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
  221. package/build/services/PhoneNotificationsSync.js +12 -10
  222. package/build/services/PhoneNotificationsSync.js.map +1 -1
  223. package/build/services/PhonePhotoCoordinator.d.ts +26 -2
  224. package/build/services/PhonePhotoCoordinator.d.ts.map +1 -1
  225. package/build/services/PhonePhotoCoordinator.js +80 -10
  226. package/build/services/PhonePhotoCoordinator.js.map +1 -1
  227. package/build/services/PhoneStreamCoordinator.d.ts +8 -1
  228. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
  229. package/build/services/PhoneStreamCoordinator.js +125 -13
  230. package/build/services/PhoneStreamCoordinator.js.map +1 -1
  231. package/build/services/PhoneVideoCoordinator.d.ts +2 -0
  232. package/build/services/PhoneVideoCoordinator.d.ts.map +1 -1
  233. package/build/services/PhoneVideoCoordinator.js +10 -0
  234. package/build/services/PhoneVideoCoordinator.js.map +1 -1
  235. package/build/services/SceneRenderer.d.ts.map +1 -1
  236. package/build/services/SceneRenderer.js +15 -0
  237. package/build/services/SceneRenderer.js.map +1 -1
  238. package/build/services/SentenceTtsPipeline.d.ts +31 -0
  239. package/build/services/SentenceTtsPipeline.d.ts.map +1 -0
  240. package/build/services/SentenceTtsPipeline.js +67 -0
  241. package/build/services/SentenceTtsPipeline.js.map +1 -0
  242. package/build/services/StreamLifecycleController.d.ts +3 -3
  243. package/build/services/StreamLifecycleController.js +3 -3
  244. package/build/services/StreamLifecycleController.js.map +1 -1
  245. package/build/services/SupportProfileSync.d.ts +22 -0
  246. package/build/services/SupportProfileSync.d.ts.map +1 -0
  247. package/build/services/SupportProfileSync.js +213 -0
  248. package/build/services/SupportProfileSync.js.map +1 -0
  249. package/build/services/TranscriptionRouting.d.ts +12 -0
  250. package/build/services/TranscriptionRouting.d.ts.map +1 -0
  251. package/build/services/TranscriptionRouting.js +24 -0
  252. package/build/services/TranscriptionRouting.js.map +1 -0
  253. package/build/services/TtsTextSanitizer.d.ts +5 -0
  254. package/build/services/TtsTextSanitizer.d.ts.map +1 -0
  255. package/build/services/TtsTextSanitizer.js +61 -0
  256. package/build/services/TtsTextSanitizer.js.map +1 -0
  257. package/build/services/WifiAdbRequest.d.ts +17 -0
  258. package/build/services/WifiAdbRequest.d.ts.map +1 -0
  259. package/build/services/WifiAdbRequest.js +35 -0
  260. package/build/services/WifiAdbRequest.js.map +1 -0
  261. package/build/services/asg/asgCameraApi.d.ts +43 -0
  262. package/build/services/asg/asgCameraApi.d.ts.map +1 -1
  263. package/build/services/asg/asgCameraApi.js +509 -26
  264. package/build/services/asg/asgCameraApi.js.map +1 -1
  265. package/build/services/asg/cameraRollExportCoordinator.d.ts +60 -0
  266. package/build/services/asg/cameraRollExportCoordinator.d.ts.map +1 -0
  267. package/build/services/asg/cameraRollExportCoordinator.js +618 -0
  268. package/build/services/asg/cameraRollExportCoordinator.js.map +1 -0
  269. package/build/services/asg/cameraRollExportLedger.d.ts +44 -0
  270. package/build/services/asg/cameraRollExportLedger.d.ts.map +1 -0
  271. package/build/services/asg/cameraRollExportLedger.js +78 -0
  272. package/build/services/asg/cameraRollExportLedger.js.map +1 -0
  273. package/build/services/asg/galleryNotices.d.ts +1 -1
  274. package/build/services/asg/galleryNotices.d.ts.map +1 -1
  275. package/build/services/asg/galleryNotices.js.map +1 -1
  276. package/build/services/asg/galleryPathMigration.d.ts +3 -0
  277. package/build/services/asg/galleryPathMigration.d.ts.map +1 -0
  278. package/build/services/asg/galleryPathMigration.js +26 -0
  279. package/build/services/asg/galleryPathMigration.js.map +1 -0
  280. package/build/services/asg/gallerySettingsService.d.ts +1 -0
  281. package/build/services/asg/gallerySettingsService.d.ts.map +1 -1
  282. package/build/services/asg/gallerySettingsService.js +2 -0
  283. package/build/services/asg/gallerySettingsService.js.map +1 -1
  284. package/build/services/asg/gallerySyncService.d.ts.map +1 -1
  285. package/build/services/asg/gallerySyncService.js +162 -56
  286. package/build/services/asg/gallerySyncService.js.map +1 -1
  287. package/build/services/asg/galleryTransferLedger.d.ts +58 -0
  288. package/build/services/asg/galleryTransferLedger.d.ts.map +1 -0
  289. package/build/services/asg/galleryTransferLedger.js +225 -0
  290. package/build/services/asg/galleryTransferLedger.js.map +1 -0
  291. package/build/services/asg/localNetworkTransport.d.ts +15 -0
  292. package/build/services/asg/localNetworkTransport.d.ts.map +1 -0
  293. package/build/services/asg/localNetworkTransport.js +145 -0
  294. package/build/services/asg/localNetworkTransport.js.map +1 -0
  295. package/build/services/asg/localStorageService.d.ts +18 -0
  296. package/build/services/asg/localStorageService.d.ts.map +1 -1
  297. package/build/services/asg/localStorageService.js +168 -19
  298. package/build/services/asg/localStorageService.js.map +1 -1
  299. package/build/services/asg/mediaProcessingQueue.d.ts +10 -0
  300. package/build/services/asg/mediaProcessingQueue.d.ts.map +1 -1
  301. package/build/services/asg/mediaProcessingQueue.js +193 -62
  302. package/build/services/asg/mediaProcessingQueue.js.map +1 -1
  303. package/build/services/audioPlaybackAssets.d.ts +8 -0
  304. package/build/services/audioPlaybackAssets.d.ts.map +1 -0
  305. package/build/services/audioPlaybackAssets.js +7 -0
  306. package/build/services/audioPlaybackAssets.js.map +1 -0
  307. package/build/services/gallerySyncClock.js +1 -1
  308. package/build/services/gallerySyncClock.js.map +1 -1
  309. package/build/services/glassesClockSync.d.ts.map +1 -1
  310. package/build/services/glassesClockSync.js +7 -3
  311. package/build/services/glassesClockSync.js.map +1 -1
  312. package/build/services/manifestActions.d.ts +7 -0
  313. package/build/services/manifestActions.d.ts.map +1 -0
  314. package/build/services/manifestActions.js +25 -0
  315. package/build/services/manifestActions.js.map +1 -0
  316. package/build/services/otaDisplayState.d.ts +23 -12
  317. package/build/services/otaDisplayState.d.ts.map +1 -1
  318. package/build/services/otaDisplayState.js +36 -14
  319. package/build/services/otaDisplayState.js.map +1 -1
  320. package/build/services/otaInstallPolicy.d.ts +20 -4
  321. package/build/services/otaInstallPolicy.d.ts.map +1 -1
  322. package/build/services/otaInstallPolicy.js +28 -3
  323. package/build/services/otaInstallPolicy.js.map +1 -1
  324. package/build/services/otaLegacyMapping.d.ts +1 -1
  325. package/build/services/otaLegacyMapping.d.ts.map +1 -1
  326. package/build/services/otaLegacyMapping.js.map +1 -1
  327. package/build/services/otaManifestPolicy.d.ts +14 -0
  328. package/build/services/otaManifestPolicy.d.ts.map +1 -0
  329. package/build/services/otaManifestPolicy.js +19 -0
  330. package/build/services/otaManifestPolicy.js.map +1 -0
  331. package/build/services/otaManifestUrl.d.ts +3 -0
  332. package/build/services/otaManifestUrl.d.ts.map +1 -0
  333. package/build/services/otaManifestUrl.js +38 -0
  334. package/build/services/otaManifestUrl.js.map +1 -0
  335. package/build/services/otaReleaseVersion.d.ts +10 -0
  336. package/build/services/otaReleaseVersion.d.ts.map +1 -0
  337. package/build/services/otaReleaseVersion.js +14 -0
  338. package/build/services/otaReleaseVersion.js.map +1 -0
  339. package/build/services/slimStreamStatus.d.ts +11 -0
  340. package/build/services/slimStreamStatus.d.ts.map +1 -1
  341. package/build/services/slimStreamStatus.js +14 -4
  342. package/build/services/slimStreamStatus.js.map +1 -1
  343. package/build/stores/appVisibility.d.ts +3 -0
  344. package/build/stores/appVisibility.d.ts.map +1 -0
  345. package/build/stores/appVisibility.js +3 -0
  346. package/build/stores/appVisibility.js.map +1 -0
  347. package/build/stores/apps.d.ts.map +1 -1
  348. package/build/stores/apps.js +18 -1
  349. package/build/stores/apps.js.map +1 -1
  350. package/build/stores/bluetoothSettingKeys.d.ts.map +1 -1
  351. package/build/stores/bluetoothSettingKeys.js +2 -0
  352. package/build/stores/bluetoothSettingKeys.js.map +1 -1
  353. package/build/stores/core.d.ts +3 -3
  354. package/build/stores/core.d.ts.map +1 -1
  355. package/build/stores/core.js.map +1 -1
  356. package/build/stores/gallerySync.d.ts +2 -0
  357. package/build/stores/gallerySync.d.ts.map +1 -1
  358. package/build/stores/gallerySync.js +2 -0
  359. package/build/stores/gallerySync.js.map +1 -1
  360. package/build/stores/glasses.d.ts +10 -4
  361. package/build/stores/glasses.d.ts.map +1 -1
  362. package/build/stores/glasses.js +3 -0
  363. package/build/stores/glasses.js.map +1 -1
  364. package/build/stores/settings.d.ts +17 -0
  365. package/build/stores/settings.d.ts.map +1 -1
  366. package/build/stores/settings.js +157 -17
  367. package/build/stores/settings.js.map +1 -1
  368. package/build/types/applet.d.ts +3 -1
  369. package/build/types/applet.d.ts.map +1 -1
  370. package/build/types/applet.js +1 -1
  371. package/build/types/applet.js.map +1 -1
  372. package/build/types/asg.d.ts +7 -0
  373. package/build/types/asg.d.ts.map +1 -1
  374. package/build/types/asg.js.map +1 -1
  375. package/build/types/capabilities/even-realities-g1.d.ts.map +1 -1
  376. package/build/types/capabilities/even-realities-g1.js +2 -0
  377. package/build/types/capabilities/even-realities-g1.js.map +1 -1
  378. package/build/types/capabilities/even-realities-g2.d.ts.map +1 -1
  379. package/build/types/capabilities/even-realities-g2.js +2 -0
  380. package/build/types/capabilities/even-realities-g2.js.map +1 -1
  381. package/build/types/capabilities/mentra-display.d.ts.map +1 -1
  382. package/build/types/capabilities/mentra-display.js +2 -0
  383. package/build/types/capabilities/mentra-display.js.map +1 -1
  384. package/build/types/capabilities/mentra-live.d.ts.map +1 -1
  385. package/build/types/capabilities/mentra-live.js +2 -0
  386. package/build/types/capabilities/mentra-live.js.map +1 -1
  387. package/build/types/capabilities/nimo.d.ts +9 -0
  388. package/build/types/capabilities/nimo.d.ts.map +1 -0
  389. package/build/types/capabilities/nimo.js +57 -0
  390. package/build/types/capabilities/nimo.js.map +1 -0
  391. package/build/types/capabilities/none.d.ts.map +1 -1
  392. package/build/types/capabilities/none.js +2 -0
  393. package/build/types/capabilities/none.js.map +1 -1
  394. package/build/types/capabilities/simulated-glasses.d.ts.map +1 -1
  395. package/build/types/capabilities/simulated-glasses.js +2 -0
  396. package/build/types/capabilities/simulated-glasses.js.map +1 -1
  397. package/build/types/capabilities/vuzix-z100.d.ts.map +1 -1
  398. package/build/types/capabilities/vuzix-z100.js +2 -0
  399. package/build/types/capabilities/vuzix-z100.js.map +1 -1
  400. package/build/types/enums.d.ts +4 -26
  401. package/build/types/enums.d.ts.map +1 -1
  402. package/build/types/enums.js +3 -27
  403. package/build/types/enums.js.map +1 -1
  404. package/build/types/hardware.d.ts +6 -14
  405. package/build/types/hardware.d.ts.map +1 -1
  406. package/build/types/hardware.js +18 -4
  407. package/build/types/hardware.js.map +1 -1
  408. package/build/types/index.d.ts +3 -7
  409. package/build/types/index.d.ts.map +1 -1
  410. package/build/types/index.js +3 -7
  411. package/build/types/index.js.map +1 -1
  412. package/build/utils/configuredDevHost.d.ts +6 -0
  413. package/build/utils/configuredDevHost.d.ts.map +1 -0
  414. package/build/utils/configuredDevHost.js +19 -0
  415. package/build/utils/configuredDevHost.js.map +1 -0
  416. package/build/utils/devMiniappLaunch.d.ts +19 -8
  417. package/build/utils/devMiniappLaunch.d.ts.map +1 -1
  418. package/build/utils/devMiniappLaunch.js +144 -21
  419. package/build/utils/devMiniappLaunch.js.map +1 -1
  420. package/build/utils/diagnosticContext.d.ts.map +1 -1
  421. package/build/utils/diagnosticContext.js +15 -17
  422. package/build/utils/diagnosticContext.js.map +1 -1
  423. package/build/utils/display/composer/ColumnComposer.d.ts +1 -1
  424. package/build/utils/display/composer/ColumnComposer.js +1 -1
  425. package/build/utils/display/composer/ColumnComposer.js.map +1 -1
  426. package/build/utils/hardware/hardware.d.ts.map +1 -1
  427. package/build/utils/hardware/hardware.js +7 -3
  428. package/build/utils/hardware/hardware.js.map +1 -1
  429. package/build/utils/miniappDiagnostics.d.ts +64 -0
  430. package/build/utils/miniappDiagnostics.d.ts.map +1 -0
  431. package/build/utils/miniappDiagnostics.js +173 -0
  432. package/build/utils/miniappDiagnostics.js.map +1 -0
  433. package/build/utils/permissions/MediaLibraryPermissions.d.ts +11 -0
  434. package/build/utils/permissions/MediaLibraryPermissions.d.ts.map +1 -1
  435. package/build/utils/permissions/MediaLibraryPermissions.js +27 -4
  436. package/build/utils/permissions/MediaLibraryPermissions.js.map +1 -1
  437. package/build/utils/timers/timers.d.ts.map +1 -1
  438. package/build/utils/timers/timers.js +55 -18
  439. package/build/utils/timers/timers.js.map +1 -1
  440. package/package.json +66 -31
  441. package/src/assets/silence.wav +0 -0
  442. package/src/bluetooth-sdk/debug.ts +1 -0
  443. package/src/bluetooth-sdk/index.ts +2 -0
  444. package/src/bluetooth-sdk/ota-transport.ts +1 -0
  445. package/src/bluetooth-sdk/photo-receiver.ts +2 -0
  446. package/src/bluetooth-sdk/react.ts +1 -0
  447. package/src/bluetooth-sdk/types.ts +1 -0
  448. package/src/engine.ts +9 -4
  449. package/src/facades/dev.ts +17 -12
  450. package/src/facades/display.ts +1 -1
  451. package/src/facades/gallery.ts +1 -1
  452. package/src/facades/glasses.ts +20 -7
  453. package/src/facades/glassesSettings.ts +5 -0
  454. package/src/facades/miniapps.ts +7 -0
  455. package/src/facades/ota.ts +41 -13
  456. package/src/facades/pairing.ts +103 -23
  457. package/src/facades/permissions.ts +14 -0
  458. package/src/facades/phoneNotifications.ts +4 -13
  459. package/src/facades/speech.ts +21 -7
  460. package/src/generated/releaseMetadata.ts +20 -0
  461. package/src/index.ts +42 -13
  462. package/src/react/MentraLiveOtaFlow.tsx +754 -0
  463. package/src/react/index.ts +21 -0
  464. package/src/react/useEngineSnapshot.ts +16 -0
  465. package/src/react/useMentraLiveOta.ts +793 -0
  466. package/src/runtime/bootstrap.ts +33 -1
  467. package/src/runtime/scanQrSeam.ts +20 -0
  468. package/src/services/AppRegistry.ts +240 -149
  469. package/src/services/AudioCloudUplink.ts +23 -1
  470. package/src/services/AudioPlaybackService.ts +287 -38
  471. package/src/services/BlobStore.ts +79 -19
  472. package/src/services/CloudAudioSubscriptionSync.ts +13 -1
  473. package/src/services/CloudClientService.ts +96 -1
  474. package/src/services/DeviceEventRouter.ts +5 -5
  475. package/src/services/DisplayProcessor.ts +3 -3
  476. package/src/services/ForegroundLocationPermission.ts +24 -0
  477. package/src/services/GlassesSettingsSync.ts +9 -3
  478. package/src/services/GlassesStatusProjection.ts +20 -11
  479. package/src/services/HotspotOtaTransport.ts +185 -0
  480. package/src/services/HotspotShutdown.ts +41 -0
  481. package/src/services/LocalDisplayManager.ts +114 -24
  482. package/src/services/LocalMiniappRuntime.ts +967 -346
  483. package/src/services/LocalMiniappStorage.ts +82 -0
  484. package/src/services/LocalMiniappUserIdentity.ts +46 -0
  485. package/src/services/LocalSttFallbackCoordinator.ts +19 -12
  486. package/src/services/MicStateCoordinator.ts +169 -4
  487. package/src/services/MiniappLauncher.ts +30 -3
  488. package/src/services/MiniappLiveness.ts +24 -0
  489. package/src/services/NativeHttpResponse.ts +6 -0
  490. package/src/services/OtaArtifactDownloader.ts +312 -0
  491. package/src/services/OtaAutoChain.ts +130 -0
  492. package/src/services/OtaErrorMapping.ts +80 -0
  493. package/src/services/OtaInstallCoordinator.ts +680 -151
  494. package/src/services/OtaService.ts +12 -7
  495. package/src/services/OtaUpdateCheckService.ts +205 -27
  496. package/src/services/PhoneCalendarHelpers.ts +212 -0
  497. package/src/services/PhoneCalendarService.ts +65 -0
  498. package/src/services/PhoneCameraFovCoordinator.ts +210 -0
  499. package/src/services/PhoneNotificationsSync.ts +12 -10
  500. package/src/services/PhonePhotoCoordinator.ts +117 -19
  501. package/src/services/PhoneStreamCoordinator.ts +139 -25
  502. package/src/services/PhoneVideoCoordinator.ts +11 -0
  503. package/src/services/SceneRenderer.ts +16 -0
  504. package/src/services/SentenceTtsPipeline.ts +106 -0
  505. package/src/services/StreamLifecycleController.ts +3 -3
  506. package/src/services/SupportProfileSync.ts +218 -0
  507. package/src/services/TranscriptionRouting.ts +37 -0
  508. package/src/services/TtsTextSanitizer.ts +66 -0
  509. package/src/services/WifiAdbRequest.ts +53 -0
  510. package/src/services/asg/asgCameraApi.ts +615 -33
  511. package/src/services/asg/cameraRollExportCoordinator.ts +627 -0
  512. package/src/services/asg/cameraRollExportLedger.ts +122 -0
  513. package/src/services/asg/galleryNotices.ts +1 -0
  514. package/src/services/asg/galleryPathMigration.ts +22 -0
  515. package/src/services/asg/gallerySettingsService.ts +3 -0
  516. package/src/services/asg/gallerySyncService.ts +184 -73
  517. package/src/services/asg/galleryTransferLedger.ts +312 -0
  518. package/src/services/asg/localNetworkTransport.ts +170 -0
  519. package/src/services/asg/localStorageService.ts +179 -24
  520. package/src/services/asg/mediaProcessingQueue.ts +209 -62
  521. package/src/services/audioPlaybackAssets.ts +8 -0
  522. package/src/services/gallerySyncClock.ts +1 -1
  523. package/src/services/glassesClockSync.ts +7 -3
  524. package/src/services/manifestActions.ts +30 -0
  525. package/src/services/otaDisplayState.ts +58 -17
  526. package/src/services/otaInstallPolicy.ts +34 -4
  527. package/src/services/otaLegacyMapping.ts +1 -1
  528. package/src/services/otaManifestPolicy.ts +42 -0
  529. package/src/services/otaManifestUrl.ts +44 -0
  530. package/src/services/otaReleaseVersion.ts +22 -0
  531. package/src/services/slimStreamStatus.ts +16 -5
  532. package/src/stores/appVisibility.ts +3 -0
  533. package/src/stores/apps.ts +19 -1
  534. package/src/stores/bluetoothSettingKeys.ts +2 -0
  535. package/src/stores/core.ts +4 -4
  536. package/src/stores/gallerySync.ts +4 -0
  537. package/src/stores/glasses.ts +16 -6
  538. package/src/stores/settings.ts +179 -18
  539. package/src/types/applet.ts +3 -1
  540. package/src/types/asg.ts +7 -0
  541. package/src/types/capabilities/even-realities-g1.ts +3 -0
  542. package/src/types/capabilities/even-realities-g2.ts +3 -0
  543. package/src/types/capabilities/mentra-display.ts +3 -0
  544. package/src/types/capabilities/mentra-live.ts +3 -0
  545. package/src/types/capabilities/nimo.ts +59 -0
  546. package/src/types/capabilities/none.ts +3 -0
  547. package/src/types/capabilities/simulated-glasses.ts +3 -0
  548. package/src/types/capabilities/vuzix-z100.ts +3 -0
  549. package/src/types/enums.ts +4 -28
  550. package/src/types/hardware.ts +23 -14
  551. package/src/types/index.ts +3 -6
  552. package/src/utils/configuredDevHost.ts +17 -0
  553. package/src/utils/devMiniappLaunch.ts +151 -23
  554. package/src/utils/diagnosticContext.ts +17 -17
  555. package/src/utils/display/composer/ColumnComposer.ts +1 -1
  556. package/src/utils/hardware/hardware.ts +7 -9
  557. package/src/utils/miniappDiagnostics.ts +226 -0
  558. package/src/utils/permissions/MediaLibraryPermissions.ts +35 -4
  559. package/src/utils/timers/timers.ts +57 -21
  560. package/build/devtools.d.ts +0 -11
  561. package/build/devtools.d.ts.map +0 -1
  562. package/build/devtools.js +0 -13
  563. package/build/devtools.js.map +0 -1
  564. package/build/internal.d.ts +0 -66
  565. package/build/internal.d.ts.map +0 -1
  566. package/build/internal.js +0 -89
  567. package/build/internal.js.map +0 -1
  568. package/build/services/asgOtaVersionUrl.d.ts +0 -2
  569. package/build/services/asgOtaVersionUrl.d.ts.map +0 -1
  570. package/build/services/asgOtaVersionUrl.js +0 -36
  571. package/build/services/asgOtaVersionUrl.js.map +0 -1
  572. package/src/devtools.ts +0 -13
  573. package/src/internal.ts +0 -158
  574. package/src/services/asgOtaVersionUrl.ts +0 -41
@@ -0,0 +1,185 @@
1
+ import BluetoothSdk, {isEnabledHotspotStatus} from "@mentra/bluetooth-sdk"
2
+ import {otaServer} from "@mentra/bluetooth-sdk/ota-transport"
3
+ // One coordinator selects the native Android or iOS staging implementation at runtime.
4
+ // eslint-disable-next-line react-native/split-platform-components
5
+ import {PermissionsAndroid, Platform} from "react-native"
6
+ import type {OtaCheckCurrentGlassesResult} from "./OtaUpdateCheckService"
7
+ import {
8
+ cleanupArtifacts,
9
+ OtaArtifactError,
10
+ planArtifacts,
11
+ prepareArtifacts,
12
+ rewriteManifestForLocalServer,
13
+ type OtaArtifactDownloadProgress,
14
+ type PreparedOtaArtifact,
15
+ } from "./OtaArtifactDownloader"
16
+ import {disableHotspotWithRetry} from "./HotspotShutdown"
17
+ import {localNetworkTransport} from "./asg/localNetworkTransport"
18
+
19
+ export type HotspotOtaPhase = "idle" | "downloading" | "starting_hotspot" | "joining_hotspot" | "serving"
20
+
21
+ export type HotspotOtaProgress = {
22
+ phase: HotspotOtaPhase
23
+ artifact?: OtaArtifactDownloadProgress
24
+ }
25
+
26
+ export type HotspotOtaErrorCode =
27
+ | "hotspot_wifi_permission_denied"
28
+ | "hotspot_start_failed"
29
+ | "hotspot_join_failed"
30
+ | "hotspot_server_failed"
31
+
32
+ export class HotspotOtaTransportError extends Error {
33
+ constructor(
34
+ public readonly code: HotspotOtaErrorCode,
35
+ message: string,
36
+ ) {
37
+ super(message)
38
+ this.name = "HotspotOtaTransportError"
39
+ }
40
+ }
41
+
42
+ /** Owns the single phone-side endpoint and network lease for one hotspot OTA attempt. */
43
+ class HotspotOtaTransport {
44
+ private active = false
45
+ private prepared: PreparedOtaArtifact[] = []
46
+ private hotspotRequested = false
47
+ private localNetworkConnected = false
48
+ private serverStarted = false
49
+ private teardownPromise: Promise<void> | null = null
50
+
51
+ async prepare(
52
+ checkResult: OtaCheckCurrentGlassesResult,
53
+ onProgress?: (progress: HotspotOtaProgress) => void,
54
+ ): Promise<string> {
55
+ if (this.teardownPromise) await this.teardownPromise
56
+ if (this.active) {
57
+ throw new Error("A hotspot OTA transport is already active")
58
+ }
59
+ if (!checkResult.manifestBody) {
60
+ throw new Error("The selected OTA check has no manifest body")
61
+ }
62
+
63
+ let phase: HotspotOtaPhase = "downloading"
64
+ try {
65
+ await this.ensureAndroidWifiPermission()
66
+ onProgress?.({phase: "downloading"})
67
+ this.prepared = await prepareArtifacts(
68
+ planArtifacts(checkResult),
69
+ (artifact) => onProgress?.({phase: "downloading", artifact}),
70
+ Platform.OS === "ios" ? this.downloadIosArtifact : undefined,
71
+ )
72
+
73
+ phase = "starting_hotspot"
74
+ onProgress?.({phase: "starting_hotspot"})
75
+ this.hotspotRequested = true
76
+ const hotspot = await BluetoothSdk.setHotspotState(true)
77
+ if (!isEnabledHotspotStatus(hotspot)) {
78
+ throw new HotspotOtaTransportError("hotspot_start_failed", "Mentra Live did not return hotspot credentials")
79
+ }
80
+ phase = "joining_hotspot"
81
+ onProgress?.({phase: "joining_hotspot"})
82
+ const scopedAddress = await localNetworkTransport.connect(hotspot.ssid, hotspot.password)
83
+ this.localNetworkConnected = true
84
+ let localAddress = scopedAddress
85
+ if (Platform.OS === "ios") {
86
+ try {
87
+ localAddress = await otaServer.waitForWifiAddress(hotspot.localIp, 15_000)
88
+ } catch (error) {
89
+ throw new HotspotOtaTransportError(
90
+ "hotspot_join_failed",
91
+ error instanceof Error ? error.message : String(error),
92
+ )
93
+ }
94
+ }
95
+ const artifactPaths = Object.fromEntries(this.prepared.map((artifact) => [artifact.sha256, artifact.filePath]))
96
+ // Start exactly one native listener to learn its selected port, then atomically replace
97
+ // the placeholder with the immutable rewritten manifest before ota_start is sent.
98
+ const server = await otaServer.start("{}", artifactPaths, localAddress)
99
+ this.serverStarted = true
100
+ const manifest = rewriteManifestForLocalServer(checkResult.manifestBody, this.prepared, server.baseUrl)
101
+ const published = await otaServer.start(manifest, artifactPaths, server.host)
102
+ if (published.manifestUrl !== server.manifestUrl) {
103
+ throw new Error("Local OTA server endpoint changed while publishing the manifest")
104
+ }
105
+ this.active = true
106
+ onProgress?.({phase: "serving"})
107
+ return published.manifestUrl
108
+ } catch (error) {
109
+ const joined = this.localNetworkConnected
110
+ await this.teardown()
111
+ if (error instanceof OtaArtifactError || error instanceof HotspotOtaTransportError) {
112
+ throw error
113
+ }
114
+ const message = error instanceof Error ? error.message : String(error)
115
+ if (phase === "starting_hotspot") {
116
+ throw new HotspotOtaTransportError("hotspot_start_failed", message)
117
+ }
118
+ if (phase === "joining_hotspot" && !joined) {
119
+ throw new HotspotOtaTransportError("hotspot_join_failed", message)
120
+ }
121
+ throw new HotspotOtaTransportError("hotspot_server_failed", message)
122
+ }
123
+ }
124
+
125
+ /** Android 13+ requires the nearby-WiFi runtime grant before WifiNetworkSpecifier is usable. */
126
+ private async ensureAndroidWifiPermission(): Promise<void> {
127
+ if (Platform.OS !== "android") return
128
+
129
+ const permission = PermissionsAndroid.PERMISSIONS.NEARBY_WIFI_DEVICES
130
+ if (await PermissionsAndroid.check(permission)) return
131
+ const result = await PermissionsAndroid.request(permission)
132
+ if (result !== PermissionsAndroid.RESULTS.GRANTED) {
133
+ throw new HotspotOtaTransportError(
134
+ "hotspot_wifi_permission_denied",
135
+ "Nearby devices permission is required to connect to the glasses hotspot",
136
+ )
137
+ }
138
+ }
139
+
140
+ private downloadIosArtifact = async (
141
+ entry: {url: string},
142
+ destination: string,
143
+ onProgress?: (bytesWritten: number, contentLength: number) => void,
144
+ ): Promise<{statusCode: number}> => {
145
+ const subscription = otaServer.onArtifactDownloadProgress((event) => {
146
+ if (event.destination === destination) onProgress?.(event.bytesWritten, event.contentLength)
147
+ })
148
+ try {
149
+ return await otaServer.downloadArtifact(entry.url, destination)
150
+ } finally {
151
+ subscription.remove()
152
+ }
153
+ }
154
+
155
+ async teardown(): Promise<void> {
156
+ if (this.teardownPromise) return this.teardownPromise
157
+ this.teardownPromise = (async () => {
158
+ if (this.hotspotRequested) {
159
+ const hotspotStopped = await disableHotspotWithRetry(() => BluetoothSdk.setHotspotState(false), {
160
+ // A completed APK step has just replaced ASG. Let the new command path
161
+ // settle before asking it to tear down the SystemUI-owned access point.
162
+ initialDelayMs: this.serverStarted ? 750 : 0,
163
+ })
164
+ if (!hotspotStopped) {
165
+ console.warn("[OTA_PROGRESS] glasses hotspot shutdown was not confirmed after bounded retries")
166
+ }
167
+ }
168
+ if (this.serverStarted) await otaServer.stop().catch(() => {})
169
+ if (this.localNetworkConnected) await localNetworkTransport.disconnect().catch(() => {})
170
+ await cleanupArtifacts().catch(() => {})
171
+ this.prepared = []
172
+ this.active = false
173
+ this.serverStarted = false
174
+ this.localNetworkConnected = false
175
+ this.hotspotRequested = false
176
+ })()
177
+ try {
178
+ await this.teardownPromise
179
+ } finally {
180
+ this.teardownPromise = null
181
+ }
182
+ }
183
+ }
184
+
185
+ export const hotspotOtaTransport = new HotspotOtaTransport()
@@ -0,0 +1,41 @@
1
+ type HotspotState = {state: "disabled" | "enabled"}
2
+
3
+ type HotspotShutdownOptions = {
4
+ attempts?: number
5
+ initialDelayMs?: number
6
+ retryDelayMs?: number
7
+ sleep?: (delayMs: number) => Promise<void>
8
+ }
9
+
10
+ const sleep = (delayMs: number) => new Promise<void>((resolve) => setTimeout(resolve, delayMs))
11
+
12
+ /**
13
+ * Disable a glasses hotspot with a bounded retry. ASG APK replacement keeps the
14
+ * BLE link alive through BES, but the first command after the new ASG process
15
+ * appears can still land while its command path is settling.
16
+ */
17
+ export async function disableHotspotWithRetry(
18
+ requestDisabled: () => Promise<HotspotState>,
19
+ options: HotspotShutdownOptions = {},
20
+ ): Promise<boolean> {
21
+ const attempts = Math.max(1, options.attempts ?? 2)
22
+ const initialDelayMs = Math.max(0, options.initialDelayMs ?? 0)
23
+ const retryDelayMs = Math.max(0, options.retryDelayMs ?? 500)
24
+ const wait = options.sleep ?? sleep
25
+
26
+ if (initialDelayMs > 0) await wait(initialDelayMs)
27
+
28
+ for (let attempt = 1; attempt <= attempts; attempt += 1) {
29
+ try {
30
+ const status = await requestDisabled()
31
+ if (status.state === "disabled") return true
32
+ } catch {
33
+ // A lost command is indistinguishable from a response timeout here. Retry
34
+ // while the phone still owns the hotspot network and local server.
35
+ }
36
+
37
+ if (attempt < attempts && retryDelayMs > 0) await wait(retryDelayMs)
38
+ }
39
+
40
+ return false
41
+ }
@@ -2,9 +2,8 @@
2
2
  * LocalDisplayManager
3
3
  *
4
4
  * Phone-side arbiter for display requests originating from LOCAL miniapps
5
- * (the @mentra/miniapp SDK). Mirrors the user-facing behavior of the cloud
6
- * DisplayManager (cloud/packages/cloud/src/services/layout/DisplayManager6.1.ts)
7
- * for the features that matter on the phone:
5
+ * (the @mentra/miniapp SDK). Preserves the retired cloud display manager's
6
+ * user-facing behavior for the features that matter on the phone:
8
7
  *
9
8
  * - boot message ("Starting <AppName>…") with a bounded window
10
9
  * - durationMs auto-clear
@@ -98,6 +97,12 @@ const BACKGROUND_LOCK_TIMEOUT_MS = 10_000
98
97
  // Sentinel package name used as the "source" of the system boot message.
99
98
  const SYSTEM_BOOT_PKG = "system.boot"
100
99
 
100
+ /** "Render nothing" — an empty scene or an explicit clear_view layout. */
101
+ function isClearPayload(payload: DisplayPayload): boolean {
102
+ if (payload.scene) return payload.scene.length === 0
103
+ return payload.layout?.layoutType === "clear_view"
104
+ }
105
+
101
106
  // =============================================================================
102
107
  // LocalDisplayManager
103
108
  // =============================================================================
@@ -144,14 +149,20 @@ class LocalDisplayManager {
144
149
  public onMount(packageName: string, displayName: string): void {
145
150
  console.log(`${LOG_TAG}: onMount(${packageName}, "${displayName}")`)
146
151
 
147
- // Cancel any in-flight boot for a prior app.
148
- this.cancelBoot()
149
-
150
152
  // Snapshot whatever's on the glasses BEFORE the boot text overwrites it.
151
153
  // registerApp fires onMount for every spawn — including a background app or
152
154
  // a crash-respawn while another app is foreground — so a boot that times out
153
155
  // without rendering must put the prior frame back rather than blank it.
154
- const preBoot = this.currentDisplay
156
+ // Never snapshot the boot text itself: back-to-back mounts (the autostart
157
+ // restore loop, crash-respawn chains) land while the previous app's
158
+ // "Starting X…" is still on the glasses, and endBoot would "restore" that
159
+ // stale, expiry-less frame permanently. Across chained boots, inherit the
160
+ // original pre-boot frame instead.
161
+ const inherited = this.bootingApp ? this.bootingApp.preBoot : this.currentDisplay
162
+ const preBoot = inherited?.packageName === SYSTEM_BOOT_PKG ? null : inherited
163
+
164
+ // Cancel any in-flight boot for a prior app.
165
+ this.cancelBoot()
155
166
 
156
167
  // Send the boot message directly (bypass arbitration — this is a system
157
168
  // display). Goes through sendNow so scene devices render it as a scene:
@@ -163,7 +174,7 @@ class LocalDisplayManager {
163
174
  })
164
175
 
165
176
  const timerId = BgTimer.setTimeout(() => {
166
- this.endBoot(/* triggeredByFirstDisplay */ false)
177
+ this.endBoot()
167
178
  }, BOOT_DURATION_MS)
168
179
 
169
180
  this.bootingApp = {
@@ -195,15 +206,39 @@ class LocalDisplayManager {
195
206
  }
196
207
  }
197
208
 
209
+ /** Report-safe ownership snapshot for incident diagnostics. */
210
+ public getDiagnosticSnapshot(): Record<string, unknown> {
211
+ return {
212
+ coreAppPackageName: this.coreApp,
213
+ currentDisplayPackageName: this.currentDisplay?.packageName ?? null,
214
+ backgroundLockPackageName: this.backgroundLock?.packageName ?? null,
215
+ bootingPackageName: this.bootingApp?.packageName ?? null,
216
+ }
217
+ }
218
+
198
219
  /**
199
220
  * A local miniapp is going away. Clean up all state associated with it.
200
221
  */
201
222
  public onUnmount(packageName: string): void {
202
223
  console.log(`${LOG_TAG}: onUnmount(${packageName})`)
203
224
 
204
- // If this was the booting app, cancel boot.
225
+ // If this was the booting app, cancel boot — and don't strand its
226
+ // "Starting X…" text (a system frame with no expiry): put back what the
227
+ // boot covered, or clear.
205
228
  if (this.bootingApp?.packageName === packageName) {
229
+ const preBoot = this.bootingApp.preBoot
206
230
  this.cancelBoot()
231
+ if (this.currentDisplay?.packageName === SYSTEM_BOOT_PKG) {
232
+ // The preBoot owner may have forfeited its frame during the boot
233
+ // window (a clear parked in the boot queue) — don't resurrect it.
234
+ const ownerQueued = preBoot ? this.bootQueue.get(preBoot.packageName) : undefined
235
+ const preBootForfeited = ownerQueued !== undefined && isClearPayload(ownerQueued.payload)
236
+ if (preBoot && !preBootForfeited && (preBoot.expiresAt === null || preBoot.expiresAt > this.now())) {
237
+ this.restoreDisplay(preBoot)
238
+ } else {
239
+ this.sendClear()
240
+ }
241
+ }
207
242
  }
208
243
  this.bootQueue.get(packageName)?.resolve?.({status: "blocked", reason: "app stopped"})
209
244
  this.bootQueue.delete(packageName)
@@ -216,10 +251,17 @@ class LocalDisplayManager {
216
251
  this.backgroundLock = null
217
252
  }
218
253
 
219
- // Clear saved core app display if the core is going away.
254
+ // Drop the saved core frame if the core's context is going away — the
255
+ // frame belongs to a dead context and must not be restored later. The
256
+ // coreApp POINTER itself is NOT cleared here: it is derived state owned
257
+ // by the apps-store reconciler. A liveness/crash respawn tears the
258
+ // context down (this path) without any store change — the app is still
259
+ // "running" — and clearing the pointer here would leave the respawned
260
+ // foreground app arbitrating as background until an unrelated store
261
+ // write happened to re-run the reconciler. Real stops release the slot
262
+ // via the store (running → false → reconciler → onCoreAppChange(null)).
220
263
  if (this.coreApp === packageName) {
221
264
  this.coreAppDisplay = null
222
- this.coreApp = null
223
265
  }
224
266
 
225
267
  // If this app owned the current on-glasses display, clear it (and maybe
@@ -263,7 +305,7 @@ class LocalDisplayManager {
263
305
  superseded?.resolve?.({status: "blocked", reason: "superseded by a newer frame"})
264
306
  this.bootQueue.set(packageName, {payload, resolve})
265
307
  if (this.bootingApp.packageName === packageName) {
266
- this.endBoot(/* triggeredByFirstDisplay */ true)
308
+ this.endBoot()
267
309
  }
268
310
  return
269
311
  }
@@ -271,6 +313,16 @@ class LocalDisplayManager {
271
313
  this.arbitrateAndSend(packageName, payload, resolve)
272
314
  }
273
315
 
316
+ /**
317
+ * End a package's temporary display early. If it currently owns the main
318
+ * view, release its background lock and restore the foreground miniapp's
319
+ * saved frame. A dismissal for a package that is no longer visible is a
320
+ * no-op.
321
+ */
322
+ public dismiss(packageName: string): void {
323
+ this.handleExpiry(packageName)
324
+ }
325
+
274
326
  // ===========================================================================
275
327
  // Internals — arbitration
276
328
  // ===========================================================================
@@ -283,6 +335,16 @@ class LocalDisplayManager {
283
335
  this.backgroundLock = null
284
336
  }
285
337
 
338
+ // A clear ("render nothing") means "I'm done with the display" — it is a
339
+ // forfeit, not a frame. A background app releases its lock and the core
340
+ // app's still-valid display comes back; treating it as a render instead
341
+ // would RENEW the lock with an empty frame and blank the glasses while
342
+ // still blocking everyone else.
343
+ if (isClearPayload(payload)) {
344
+ this.handleAppClear(packageName, resolve)
345
+ return
346
+ }
347
+
286
348
  const isCore = packageName === this.coreApp
287
349
 
288
350
  if (isCore) {
@@ -339,6 +401,33 @@ class LocalDisplayManager {
339
401
  this.sendNow(packageName, payload, resolve)
340
402
  }
341
403
 
404
+ /**
405
+ * An app cleared its display ("render nothing"). Same semantics as its
406
+ * frame expiring: give up ownership, restore the core app's still-valid
407
+ * display if there is one, otherwise clear the glasses.
408
+ */
409
+ private handleAppClear(packageName: string, resolve?: DisplayRequestResolver): void {
410
+ // Forget the app's retained scene state — its next render starts fresh.
411
+ sceneRenderer.clearApp(packageName)
412
+
413
+ if (this.backgroundLock?.packageName === packageName) {
414
+ this.backgroundLock = null
415
+ }
416
+ if (this.coreApp === packageName) {
417
+ this.coreAppDisplay = null
418
+ }
419
+
420
+ if (this.currentDisplay?.packageName === packageName) {
421
+ this.clearExpiryTimer()
422
+ this.currentDisplay = null
423
+ this.tryRestoreCoreDisplay()
424
+ if (!this.currentDisplay) {
425
+ this.sendClear()
426
+ }
427
+ }
428
+ resolve?.({status: "displayed"})
429
+ }
430
+
342
431
  // ===========================================================================
343
432
  // Internals — send
344
433
  // ===========================================================================
@@ -523,7 +612,7 @@ class LocalDisplayManager {
523
612
  this.bootingApp = null
524
613
  }
525
614
 
526
- private endBoot(triggeredByFirstDisplay: boolean): void {
615
+ private endBoot(): void {
527
616
  if (!this.bootingApp) return
528
617
  const preBoot = this.bootingApp.preBoot
529
618
  BgTimer.clearTimeout(this.bootingApp.timerId)
@@ -543,17 +632,18 @@ class LocalDisplayManager {
543
632
  this.arbitrateAndSend(pkg, entry.payload, entry.resolve)
544
633
  }
545
634
 
546
- // Boot ended on the timeout with nothing queued and no first display — the
547
- // app just never rendered. Restore whatever was on the glasses before the
548
- // boot text so a background app or crash-respawn can't blank a foreground
549
- // app's frame (registerApp fires onMount for every spawn, and the core app
550
- // isn't wired on the local path yet). If the glasses were empty before,
551
- // clear the lingering "Starting …" instead — otherwise a miniapp that never
552
- // renders (e.g. audio-only) would strand it.
553
- if (!triggeredByFirstDisplay && queued.length === 0) {
554
- // Only restore a frame that's still valid — one whose duration elapsed
555
- // during the boot window should clear, not come back.
556
- if (preBoot && (preBoot.expiresAt === null || preBoot.expiresAt > this.now())) {
635
+ // If the boot text is still on the glasses — nothing was queued, or every
636
+ // drained request lost arbitration — it must not strand: it's a system
637
+ // frame with no expiry. Restore whatever was on the glasses before the
638
+ // boot, else clear. Two reasons NOT to restore: the frame's duration
639
+ // elapsed during the boot window, or its owner FORFEITED it during the
640
+ // window (its final queued intent — the queue keeps last-wins per app —
641
+ // was a clear, which the drain above processed as a forfeit; restoring
642
+ // would resurrect content the clear removed).
643
+ if (this.currentDisplay?.packageName === SYSTEM_BOOT_PKG) {
644
+ const ownerEntry = preBoot ? queued.find(([pkg]) => pkg === preBoot.packageName) : undefined
645
+ const preBootForfeited = ownerEntry !== undefined && isClearPayload(ownerEntry[1].payload)
646
+ if (preBoot && !preBootForfeited && (preBoot.expiresAt === null || preBoot.expiresAt > this.now())) {
557
647
  this.restoreDisplay(preBoot)
558
648
  } else {
559
649
  this.sendClear()