@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
@@ -40,8 +40,15 @@ const LOG_TAG = "LocalMiniappRuntime"
40
40
  /** Per-app blob quota: 1 GB. */
41
41
  export const BLOB_QUOTA_BYTES = 1024 * 1024 * 1024
42
42
  const ROOT_DIR_NAME = "mentra_blobs"
43
- /** Cache dir root holding short-lived, properly-named copies handed to the OS share sheet (one unique subdir per share). */
43
+ /** Cache dir root holding short-lived, properly-named copies handed to the OS share sheet (one subdir per stored blob). */
44
44
  const SHARE_DIR_NAME = "mentra_blob_share"
45
+ /**
46
+ * Keep prepared share handoffs alive long enough for recipient apps to read
47
+ * them asynchronously (for example, an email composer attaching the file).
48
+ * Stale copies are collected before the next share; the OS may evict cache
49
+ * files sooner under storage pressure.
50
+ */
51
+ const SHARE_CACHE_MAX_AGE_MS = 24 * 60 * 60 * 1000
45
52
  const META_KEY_ROOT = "mentraos_blobmeta_"
46
53
  /** Cap md5 computation so we don't block the JS thread hashing a huge file. */
47
54
  const MD5_MAX_BYTES = 50 * 1024 * 1024
@@ -97,22 +104,33 @@ interface ActiveReader {
97
104
  export class BlobStore {
98
105
  private readonly uploads = new Map<string, ActiveUpload>() // key: `${pkg} ${key}`
99
106
  private readonly readers = new Map<string, ActiveReader>() // key: host handle id
100
- /** packageName → committed usage bytes, cached; invalidated on commit/delete/clear. */
107
+ /** user + package → committed usage bytes, cached; invalidated on commit/delete/clear. */
101
108
  private readonly usageCache = new Map<string, number>()
102
109
 
103
110
  constructor(private readonly hooks: BlobStoreHooks) {}
104
111
 
105
112
  // ---- path / meta helpers -------------------------------------------------
106
113
 
114
+ private currentIdentity(packageName: string): {userId: string; scope: string} {
115
+ const userId = this.hooks.getUserId().trim()
116
+ if (!userId) throw new Error("Mentra user identity is unavailable")
117
+ const scope = `${userId}\0${packageName}`
118
+ return {userId, scope}
119
+ }
120
+
107
121
  private dirFor(packageName: string): Directory {
108
- const userId = sanitizeSegment(this.hooks.getUserId())
109
- const dir = new Directory(Paths.document, ROOT_DIR_NAME, userId, sanitizeSegment(packageName))
122
+ const dir = new Directory(
123
+ Paths.document,
124
+ ROOT_DIR_NAME,
125
+ sanitizeSegment(this.currentIdentity(packageName).userId),
126
+ sanitizeSegment(packageName),
127
+ )
110
128
  if (!dir.exists) dir.create({intermediates: true})
111
129
  return dir
112
130
  }
113
131
 
114
132
  private metaPrefix(packageName: string): string {
115
- return `${META_KEY_ROOT}${sanitizeSegment(this.hooks.getUserId())}_${packageName}_`
133
+ return `${META_KEY_ROOT}${sanitizeSegment(this.currentIdentity(packageName).userId)}_${packageName}_`
116
134
  }
117
135
 
118
136
  private metaKey(packageName: string, key: string): string {
@@ -163,17 +181,19 @@ export class BlobStore {
163
181
  }
164
182
 
165
183
  private committedUsage(packageName: string): number {
166
- const cached = this.usageCache.get(packageName)
184
+ const {scope} = this.currentIdentity(packageName)
185
+ const cached = this.usageCache.get(scope)
167
186
  if (cached !== undefined) return cached
168
187
  let total = 0
169
188
  for (const m of this.allMeta(packageName)) total += m.bytes || 0
170
- this.usageCache.set(packageName, total)
189
+ this.usageCache.set(scope, total)
171
190
  return total
172
191
  }
173
192
 
174
193
  private bumpUsage(packageName: string, delta: number): void {
175
- const cur = this.usageCache.get(packageName)
176
- if (cur !== undefined) this.usageCache.set(packageName, Math.max(0, cur + delta))
194
+ const {scope} = this.currentIdentity(packageName)
195
+ const cur = this.usageCache.get(scope)
196
+ if (cur !== undefined) this.usageCache.set(scope, Math.max(0, cur + delta))
177
197
  }
178
198
 
179
199
  private safeMd5(file: File, bytes: number): string | undefined {
@@ -509,7 +529,7 @@ export class BlobStore {
509
529
  } catch {
510
530
  /* best-effort */
511
531
  }
512
- this.usageCache.set(packageName, 0)
532
+ this.usageCache.set(this.currentIdentity(packageName).scope, 0)
513
533
  this.hooks.sendResult(packageName, requestId, true)
514
534
  } catch (err) {
515
535
  this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, err)
@@ -585,6 +605,32 @@ export class BlobStore {
585
605
 
586
606
  // ---- share ---------------------------------------------------------------
587
607
 
608
+ /** Best-effort GC for prepared share handoffs retained in the OS cache. */
609
+ private cleanupShareCache(now = Date.now()): void {
610
+ try {
611
+ const root = new Directory(Paths.cache, SHARE_DIR_NAME)
612
+ if (!root.exists) return
613
+ const cutoff = now - SHARE_CACHE_MAX_AGE_MS
614
+ for (const entry of root.list()) {
615
+ if (!(entry instanceof Directory)) continue
616
+ try {
617
+ const info = entry.info()
618
+ // modificationTime is available on both platforms; creationTime can
619
+ // be absent on Android versions before API 26. The directory id
620
+ // begins with Date.now().toString(36), which is a final fallback.
621
+ const encoded = entry.name.split("-", 1)[0]
622
+ const encodedTime = /^[0-9a-z]+$/.test(encoded) ? Number.parseInt(encoded, 36) : Number.NaN
623
+ const timestamp = info.modificationTime ?? info.creationTime ?? encodedTime
624
+ if (Number.isFinite(timestamp) && timestamp < cutoff) entry.delete()
625
+ } catch {
626
+ // Keep scanning if one cache entry disappears or is unreadable.
627
+ }
628
+ }
629
+ } catch {
630
+ // Cache cleanup must never prevent a share.
631
+ }
632
+ }
633
+
588
634
  async handleShare(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {
589
635
  const key = payload.key as string
590
636
  const meta = this.readMeta(packageName, key)
@@ -602,23 +648,33 @@ export class BlobStore {
602
648
  // applies to base64/data payloads, not file:// URLs), so sharing `file.uri`
603
649
  // directly would hand the recipient a machine-named file. Copy to a temp
604
650
  // file that carries the real display name + extension, share that, then
605
- // clean it up.
651
+ // clean it up after the recipient has had time to consume it.
606
652
  const shareName = shareFileName(meta)
607
- // Copy into a per-share unique subdir so two concurrent shares that resolve
608
- // to the same display name can't clobber each other's temp file while
609
- // Share.open still references it. The file keeps `shareName` as its basename
610
- // so the OS share sheet shows the right name + extension.
653
+ // Key the cache directory by the immutable stored filename. Repeated or
654
+ // concurrent shares of the same blob can safely reference the same bytes,
655
+ // avoiding an extra full-sized cache copy for every share. Different blobs
656
+ // still get isolated directories even when they use the same display name.
657
+ // The file keeps `shareName` as its basename so the OS share sheet shows the
658
+ // right name + extension.
611
659
  let tempDir: Directory | null = null
660
+ let cacheReady = false
612
661
  try {
613
- tempDir = new Directory(Paths.cache, SHARE_DIR_NAME, this.makeId())
614
- tempDir.create({intermediates: true})
662
+ this.cleanupShareCache()
663
+ tempDir = new Directory(Paths.cache, SHARE_DIR_NAME, sanitizeSegment(meta.fileName))
664
+ if (!tempDir.exists) tempDir.create({intermediates: true})
615
665
  const temp = new File(tempDir, shareName)
616
- file.copy(temp)
666
+ if (!temp.exists || temp.size !== meta.bytes) {
667
+ if (temp.exists) temp.delete()
668
+ file.copy(temp)
669
+ }
670
+ cacheReady = true
617
671
  await Share.open({
618
672
  url: temp.uri,
619
673
  type: meta.mimeType || OCTET,
620
674
  filename: shareName,
621
675
  })
676
+ // Share.open resolves once the OS accepts the handoff. Recipient apps may
677
+ // still read the URI asynchronously, so retain this cache copy for GC.
622
678
  this.hooks.sendResult(packageName, requestId, true, {success: true})
623
679
  } catch (error: any) {
624
680
  if (error?.message?.includes("User did not share")) {
@@ -628,7 +684,11 @@ export class BlobStore {
628
684
  this.hooks.sendResult(packageName, requestId, true, {success: false})
629
685
  }
630
686
  } finally {
631
- if (tempDir) {
687
+ // Once a reusable cache entry is ready, retain it even if this particular
688
+ // sheet is cancelled or fails: another concurrent/recent share may still
689
+ // be reading the same file. Only remove an entry whose preparation did
690
+ // not finish; ready entries are collected after the retention window.
691
+ if (tempDir && !cacheReady) {
632
692
  try {
633
693
  if (tempDir.exists) tempDir.delete()
634
694
  } catch {
@@ -19,7 +19,19 @@ export class CloudAudioSubscriptionSync {
19
19
  private pendingKey = ""
20
20
 
21
21
  public begin(nextKey: string): boolean {
22
- if (nextKey === this.lastAppliedKey || nextKey === this.pendingKey) {
22
+ // Exact duplicate of the write already in flight — nothing to do.
23
+ if (nextKey === this.pendingKey) {
24
+ return false
25
+ }
26
+ // Matches the last successfully applied set, but ONLY skip when nothing
27
+ // else is in flight. If a different write is pending (e.g. desired went
28
+ // fr-FR -> [] -> fr-FR while the [] write is still on the wire),
29
+ // lastAppliedKey is stale: it names what was applied BEFORE the in-flight
30
+ // write lands. Skipping here would drop the re-subscribe and strand the
31
+ // cloud on the intermediate (empty) set — captions silently die on any
32
+ // rapid A -> B -> A subscription churn. The cloud's own version counter
33
+ // resolves ordering between the concurrent writes, so sending both is safe.
34
+ if (nextKey === this.lastAppliedKey && this.pendingKey === "") {
23
35
  return false
24
36
  }
25
37
  this.pendingKey = nextKey
@@ -13,21 +13,26 @@
13
13
  * The local-miniapp path drives the cloud's transcription/translation through
14
14
  * this service.
15
15
  */
16
- import {CloudClient, setNativeUdp, setSecureStorage} from "@mentra/cloud-client/react-native"
16
+ import {CloudClient, setNativeHttp, setNativeUdp, setSecureStorage} from "@mentra/cloud-client/react-native"
17
17
  import type {PreinstalledMiniappRegistry, RuntimeSnapshot} from "@mentra/cloud-client/react-native"
18
18
  import type {SubjectTokenType} from "@mentra/cloud-client"
19
+ import {Platform} from "react-native"
19
20
  import type {AudioSubscription, TranscriptionData, TranslationData} from "@mentra/cloud-protocol"
20
21
 
21
22
  import BluetoothSdk from "@mentra/bluetooth-sdk/internal"
23
+ import CrustModule from "@mentra/crust"
22
24
  import {getAuth, getConfigValues} from "../runtime/bootstrap"
23
25
  import {useSettingsStore, SETTINGS} from "../stores/settings"
24
26
  import {type CloudClientStatusSnapshot, type MiniappAuthToken} from "../runtime/config"
25
27
  import {createCloudUdpSocket} from "../utils/cloudClient/RnUdpAdapter"
26
28
  import {cloudSecureStore} from "../utils/cloudClient/cloudSecureStore"
29
+ import {storage as mmkvStorage} from "../utils/storage"
27
30
  import {useCloudClientStatusStore} from "../stores/cloudClientStatus"
28
31
  import {islandNotifications} from "./NotificationsEmitter"
29
32
  import {BgTimer} from "../utils/timers"
30
33
  import {logCloudV2TranscriptMetric} from "./CloudTranscriptE2EMetrics"
34
+ import {LocalMiniappUserIdentity} from "./LocalMiniappUserIdentity"
35
+ import {nativeHttpResponseBody} from "./NativeHttpResponse"
31
36
 
32
37
  const LOG_TAG = "cloudClient"
33
38
  type CloudCore = NonNullable<CloudClient["core"]>
@@ -37,6 +42,7 @@ type CloudCore = NonNullable<CloudClient["core"]>
37
42
  // been continuously NOT connected for this long. A quick reconnect cancels it; brief
38
43
  // flaps that recover don't fire. Raised as engine.notifications(connection_failed_persistent).
39
44
  const CLOUD_PERSISTENT_FAILURE_MS = 60_000
45
+ const LOCAL_MINIAPP_USER_ID_KEY = "mentra.localMiniapp.userId"
40
46
 
41
47
  /** Cancel the pending persistent-failure alarm + re-arm for the next outage. */
42
48
  function clearPersistentFailureAlarm(): void {
@@ -72,6 +78,21 @@ let localDevRuntimeToken: {runtimeUrl: string; token: string; expiresAtMs: numbe
72
78
  let lc3FrameSizeUnsubscribe: (() => void) | null = null
73
79
  let coreTokenSyncPromise: Promise<string> | null = null
74
80
 
81
+ const localMiniappUserIdentity = new LocalMiniappUserIdentity({
82
+ get(): string | null {
83
+ const result = mmkvStorage.load<string>(LOCAL_MINIAPP_USER_ID_KEY)
84
+ return result.is_ok() ? result.value : null
85
+ },
86
+ set(userId: string): void {
87
+ const result = mmkvStorage.save(LOCAL_MINIAPP_USER_ID_KEY, userId)
88
+ if (result.is_error()) throw result.error
89
+ },
90
+ remove(): void {
91
+ const result = mmkvStorage.remove(LOCAL_MINIAPP_USER_ID_KEY)
92
+ if (result.is_error()) throw result.error
93
+ },
94
+ })
95
+
75
96
  const transcriptListeners = new Set<(d: TranscriptionData) => void>()
76
97
  const translationListeners = new Set<(d: TranslationData) => void>()
77
98
  const statusListeners = new Set<(snapshot: CloudClientStatusSnapshot) => void>()
@@ -111,6 +132,7 @@ async function syncCoreAccessTokenToBluetoothInternal(): Promise<string> {
111
132
  if (c !== client) {
112
133
  throw new Error("cloud client changed while syncing core token")
113
134
  }
135
+ localMiniappUserIdentity.remember(c.auth.identity.mentraUserId)
114
136
  const result = await useSettingsStore.getState().setSetting(SETTINGS.core_token.key, token, false)
115
137
  if (result.is_error()) {
116
138
  throw result.error
@@ -261,6 +283,13 @@ function ensureAuthWatch(): void {
261
283
  let reconnectPending = false
262
284
  try {
263
285
  const sub = auth.onStateChange((event, session) => {
286
+ if (event === "SIGNED_OUT") {
287
+ localMiniappUserIdentity.forget()
288
+ return
289
+ }
290
+ // A new sign-in may belong to a different account. Force the next
291
+ // storage request to resolve and persist that account's Core identity.
292
+ if (event === "SIGNED_IN") localMiniappUserIdentity.forget()
264
293
  if (!session?.token) return
265
294
  if (connected || reconnectPending) return
266
295
 
@@ -322,6 +351,24 @@ function ensureTransports(): void {
322
351
  transportsReady = true
323
352
  setNativeUdp(() => createCloudUdpSocket())
324
353
  setSecureStorage(cloudSecureStore)
354
+ if (Platform.OS !== "android") return
355
+ setNativeHttp(async (input, init) => {
356
+ if (typeof input !== "string" || (init?.body != null && typeof init.body !== "string")) {
357
+ return globalThis.fetch(input, init)
358
+ }
359
+ const headers = Object.fromEntries(new Headers(init?.headers).entries())
360
+ const result = await CrustModule.nativeHttpRequest(
361
+ init?.method ?? "GET",
362
+ input,
363
+ headers,
364
+ (init?.body as string | undefined) ?? null,
365
+ )
366
+ return new Response(nativeHttpResponseBody(result.status, result.body), {
367
+ status: result.status,
368
+ statusText: result.statusText,
369
+ headers: result.headers,
370
+ })
371
+ })
325
372
  }
326
373
 
327
374
  function clearRuntimeEventSubscriptions(): void {
@@ -375,6 +422,12 @@ function construct(): void {
375
422
  // LC3 at 16 kHz with the frame size the encoder emits.
376
423
  audio: {codec: "lc3", sampleRate: 16000, frameSizeBytes: frameSizeBytes()},
377
424
  auth,
425
+ timers: {
426
+ setTimeout: (callback, delayMs) => BgTimer.setTimeout(callback, delayMs),
427
+ clearTimeout: (handle) => BgTimer.clearTimeout(handle as number),
428
+ setInterval: (callback, intervalMs) => BgTimer.setInterval(callback, intervalMs),
429
+ clearInterval: (handle) => BgTimer.clearInterval(handle as number),
430
+ },
378
431
  logger: cloudLogger,
379
432
  })
380
433
 
@@ -399,6 +452,7 @@ function construct(): void {
399
452
  if (c !== client) return
400
453
  connected = true
401
454
  console.log(`${LOG_TAG}: runtime connected`)
455
+ console.log(`${LOG_TAG}: debug: ws-session-debug connected`)
402
456
  // Cloud is up — cancel any pending persistent-failure alarm and re-arm for the
403
457
  // next outage.
404
458
  clearPersistentFailureAlarm()
@@ -415,6 +469,9 @@ function construct(): void {
415
469
  if (c !== client) return
416
470
  connected = false
417
471
  console.log(`${LOG_TAG}: runtime disconnected (${info.reason})`)
472
+ console.log(
473
+ `${LOG_TAG}: debug: ws-session-debug disconnected reason=${info.reason} willStayDown=${/superseded by newer session/i.test(info.reason)}`,
474
+ )
418
475
  // Arm the persistent-failure alarm once; if we're still down when it fires, raise
419
476
  // the notification. A reconnect within the window cancels it (onConnected above).
420
477
  if (!persistentFailureTimer && !persistentFailureNotified) {
@@ -497,6 +554,34 @@ export const cloudClientService = {
497
554
  return c.core.miniapps.getRegistry()
498
555
  },
499
556
 
557
+ /**
558
+ * Resolve the stable Core-owned Mentra user id.
559
+ *
560
+ * Storage must use this identity rather than the short-lived Core access
561
+ * token. A previously verified id is restored from MMKV so local miniapps
562
+ * remain available after an offline process restart. On first sign-in,
563
+ * callers join the auth module's single-flight exchange/refresh instead of
564
+ * falling back to an anonymous namespace.
565
+ */
566
+ async resolveMentraUserId(): Promise<string> {
567
+ return localMiniappUserIdentity.resolve(async () => {
568
+ if (!client) this.init()
569
+ const c = client
570
+ if (!c) throw new Error("cloud client not initialized")
571
+
572
+ await c.auth.getCoreToken()
573
+ if (c !== client) throw new Error("cloud client changed while resolving user identity")
574
+ return c.auth.identity.mentraUserId
575
+ })
576
+ },
577
+
578
+ /** Read the stable Mentra user id after async identity resolution. */
579
+ getMentraUserId(): string {
580
+ const userId = localMiniappUserIdentity.get()
581
+ if (!userId) throw new Error("Mentra user identity is unavailable")
582
+ return userId
583
+ },
584
+
500
585
  async getMiniappAuthToken(
501
586
  packageName: string,
502
587
  opts?: {minTtlMs?: number; devAttestation?: string},
@@ -528,6 +613,11 @@ export const cloudClientService = {
528
613
  clearPersistentFailureAlarm()
529
614
  const wasConnected = connected
530
615
  client = null
616
+ // stop() is part of the logout lifecycle and runs before the host emits
617
+ // SIGNED_OUT. Remove the persisted namespace owner here so a later account
618
+ // can never inherit it. A force-stop/process kill does not call stop(), so
619
+ // the cached id still survives the offline cold-start case.
620
+ localMiniappUserIdentity.forget()
531
621
  localDevRuntimeToken = null
532
622
  connected = false
533
623
  resetRuntimeStatus()
@@ -660,6 +750,11 @@ export const cloudClientService = {
660
750
  return getCoreClient().reports.complete(...args)
661
751
  },
662
752
  },
753
+ supportProfile: {
754
+ update(...args: Parameters<CloudCore["supportProfile"]["update"]>) {
755
+ return getCoreClient().supportProfile.update(...args)
756
+ },
757
+ },
663
758
  },
664
759
 
665
760
  hasAudioSubscriptions(): boolean {
@@ -201,17 +201,17 @@ export function startDeviceEventRouter(): void {
201
201
  localMiniappRuntime.forwardEvent("head_up", {position: event.up ? "up" : "down", timestamp: Date.now()})
202
202
  }),
203
203
  )
204
- // On-device STT transcripts → local miniapps, but ONLY when local STT fallback is the
205
- // active engine (cloud STT is down). When the cloud WS is up, cloud transcripts reach
206
- // miniapps independently via the same forwardEvent, so gating on isActive() avoids
207
- // double-delivery. forwardEvent is subscriber-gated — a no-op when no miniapp listens.
204
+ // On-device STT transcripts → local miniapps only while the local engine is
205
+ // active (cloud fallback or an explicit forceLocal subscription). The runtime
206
+ // filters mixed local/cloud delivery per miniapp to avoid double-delivery.
207
+ // forwardEvent is subscriber-gated — a no-op when no miniapp listens.
208
208
  // (Was MantleManager.handle_local_transcription; its offline-captions display branch
209
209
  // went away with the pseudo captions renderer.)
210
210
  subs.push(
211
211
  BluetoothSdk.addListener("local_transcription", (event) => {
212
212
  if (!localSttFallbackCoordinator.isActive()) return
213
213
  const lang = event.transcribeLanguage ?? localSttFallbackCoordinator.getActiveLanguage() ?? "en-US"
214
- localMiniappRuntime.forwardEvent(`transcription:${lang}`, event)
214
+ localMiniappRuntime.forwardEvent(`transcription:${lang}`, event, "local")
215
215
  }),
216
216
  )
217
217
 
@@ -2,15 +2,15 @@
2
2
  * DisplayProcessor
3
3
  *
4
4
  * Processes display events with pixel-accurate text wrapping using the same
5
- * display-utils library as the cloud. This ensures the mobile preview matches
6
- * exactly what is shown on the glasses.
5
+ * Engine display utilities. This ensures the mobile preview matches exactly
6
+ * what is shown on the glasses.
7
7
  *
8
8
  * Key responsibilities:
9
9
  * 1. Intercept display events before sending to native SGC
10
10
  * 2. Wrap text using the correct device profile (G1, etc.)
11
11
  * 3. Ensure GlassesDisplayMirror shows exactly what glasses will show
12
12
  *
13
- * @see cloud/issues/026-mobile-display-processor for design docs
13
+ * @see notes/miniapp-display-api-redesign.md for the current display design
14
14
  */
15
15
 
16
16
  import {
@@ -0,0 +1,24 @@
1
+ export interface ForegroundLocationPermissionResponse {
2
+ status: string
3
+ }
4
+
5
+ export interface ForegroundLocationPermissionClient {
6
+ getForegroundPermissionsAsync(): Promise<ForegroundLocationPermissionResponse>
7
+ requestForegroundPermissionsAsync(): Promise<ForegroundLocationPermissionResponse>
8
+ }
9
+
10
+ /**
11
+ * Resolve foreground location permission without invoking an Activity-bound
12
+ * Android permission request while the app is backgrounded.
13
+ */
14
+ export async function resolveForegroundLocationPermission(
15
+ client: ForegroundLocationPermissionClient,
16
+ getAppState: () => string,
17
+ ): Promise<ForegroundLocationPermissionResponse> {
18
+ const current = await client.getForegroundPermissionsAsync()
19
+ if (current.status === "granted" || getAppState() !== "active") {
20
+ return current
21
+ }
22
+
23
+ return client.requestForegroundPermissionsAsync()
24
+ }
@@ -19,6 +19,7 @@ import {useSettingsStore, PAIRING_IDENTITY_KEYS} from "../stores/settings"
19
19
  import {useGlassesStore} from "../stores/glasses"
20
20
  import {createDebouncedPatchFlusher} from "../utils/debouncedPatch"
21
21
  import {isGlassesConnected} from "./GlassesReadiness"
22
+ import micStateCoordinator from "./MicStateCoordinator"
22
23
 
23
24
  /**
24
25
  * Change-pushes are debounced (300ms) and merged so a burst of setSetting
@@ -28,7 +29,10 @@ import {isGlassesConnected} from "./GlassesReadiness"
28
29
  const flushBluetoothSettingsPatch = createDebouncedPatchFlusher<Record<string, unknown>>((patch) => {
29
30
  // Settings can change while the glasses are disconnected — a native
30
31
  // rejection must not surface as an unhandled promise rejection.
31
- void Promise.resolve(BluetoothSdk.updateBluetoothSettings(patch)).catch((error) => {
32
+ // Apply mic overrides at flush time, not enqueue time: raw PCM can stop
33
+ // during the debounce window and a captured VAD=false would then be stale.
34
+ const runtimePatch = micStateCoordinator.applyRuntimeOverrides(patch)
35
+ void Promise.resolve(BluetoothSdk.updateBluetoothSettings(runtimePatch)).catch((error) => {
32
36
  console.warn("GlassesSettingsSync: updateBluetoothSettings failed:", error)
33
37
  })
34
38
  }, 300)
@@ -79,7 +83,8 @@ export async function pushAllBluetoothSettings(): Promise<void> {
79
83
  // Returns the native write promise so callers can await the seed before the
80
84
  // connect handshake replays settings to the glasses (otherwise the handshake
81
85
  // can race ahead and replay stale native settings).
82
- await BluetoothSdk.updateBluetoothSettings(useSettingsStore.getState().getBluetoothSettings())
86
+ const settings = useSettingsStore.getState().getBluetoothSettings()
87
+ await BluetoothSdk.updateBluetoothSettings(micStateCoordinator.applyRuntimeOverrides(settings))
83
88
  }
84
89
 
85
90
  /**
@@ -91,7 +96,8 @@ export async function pushAllBluetoothSettings(): Promise<void> {
91
96
  * with pre-promotion empties (wiping the pairing it had just made).
92
97
  */
93
98
  export async function pushDeviceSettingsOnConnect(): Promise<void> {
94
- await BluetoothSdk.updateBluetoothSettings(stripPairingIdentity(useSettingsStore.getState().getBluetoothSettings()))
99
+ const settings = stripPairingIdentity(useSettingsStore.getState().getBluetoothSettings())
100
+ await BluetoothSdk.updateBluetoothSettings(micStateCoordinator.applyRuntimeOverrides(settings))
95
101
  }
96
102
 
97
103
  export function startGlassesSettingsSync(): void {
@@ -11,22 +11,26 @@
11
11
  *
12
12
  * Started by `engine.start()`. Idempotent.
13
13
  */
14
- import BluetoothSdk from "@mentra/bluetooth-sdk/internal"
14
+ import BluetoothSdk, {type PublicGlassesStatus} from "@mentra/bluetooth-sdk"
15
15
  import {useCoreStore} from "../stores/core"
16
16
  import {useGlassesStore} from "../stores/glasses"
17
- import localMiniappRuntime from "./LocalMiniappRuntime"
18
17
 
19
18
  let unsubs: Array<() => void> = []
20
19
  let projectionRunId = 0
20
+ let glassesStatusForwarder: ((status: Partial<PublicGlassesStatus>) => void) | null = null
21
+ let hydrationPromise: Promise<void> | null = null
21
22
 
22
- export function startGlassesStatusProjection(): void {
23
- if (unsubs.length) return
23
+ export function startGlassesStatusProjection(
24
+ forwarder?: (status: Partial<PublicGlassesStatus>) => void,
25
+ ): Promise<void> {
26
+ if (forwarder) glassesStatusForwarder = forwarder
27
+ if (unsubs.length) return hydrationPromise ?? Promise.resolve()
24
28
 
25
29
  const runId = ++projectionRunId
26
30
  let bluetoothEventSeen = false
27
31
  let glassesEventSeen = false
28
32
 
29
- void BluetoothSdk.getBluetoothStatus()
33
+ const bluetoothHydration = BluetoothSdk.getBluetoothStatus()
30
34
  .then((status) => {
31
35
  if (runId !== projectionRunId || bluetoothEventSeen) return
32
36
  useCoreStore.getState().setCoreInfo(status)
@@ -35,7 +39,7 @@ export function startGlassesStatusProjection(): void {
35
39
  console.warn("GlassesStatusProjection: getBluetoothStatus failed", error)
36
40
  })
37
41
 
38
- void BluetoothSdk.getGlassesStatus()
42
+ const glassesHydration = BluetoothSdk.getGlassesStatus()
39
43
  .then((status) => {
40
44
  if (runId !== projectionRunId || glassesEventSeen) return
41
45
  useGlassesStore.getState().setGlassesInfo(status)
@@ -46,28 +50,33 @@ export function startGlassesStatusProjection(): void {
46
50
 
47
51
  // Bluetooth-adapter status -> core store.
48
52
  unsubs.push(
49
- BluetoothSdk.onBluetoothStatus((changed) => {
53
+ BluetoothSdk.subscribeBluetoothStatus((changed) => {
50
54
  bluetoothEventSeen = true
51
55
  useCoreStore.getState().setCoreInfo(changed)
52
56
  }),
53
57
  )
54
58
 
55
- // Glasses status -> glasses store (+ forward to local miniapps; clear any stale
56
- // OTA-available flag on disconnect).
59
+ // Glasses status -> glasses store (+ optional full-runtime forwarding to local
60
+ // miniapps; clear any stale OTA-available flag on disconnect).
57
61
  unsubs.push(
58
- BluetoothSdk.onGlassesStatus((changed) => {
62
+ BluetoothSdk.subscribeGlassesStatus((changed) => {
59
63
  glassesEventSeen = true
60
64
  useGlassesStore.getState().setGlassesInfo(changed)
61
- localMiniappRuntime.forwardEvent("glasses_connection_state", changed)
65
+ glassesStatusForwarder?.(changed)
62
66
  if (changed.connection?.state === "disconnected") {
63
67
  useGlassesStore.getState().setOtaUpdateAvailable(null)
64
68
  }
65
69
  }),
66
70
  )
71
+
72
+ hydrationPromise = Promise.allSettled([bluetoothHydration, glassesHydration]).then(() => undefined)
73
+ return hydrationPromise
67
74
  }
68
75
 
69
76
  export function stopGlassesStatusProjection(): void {
70
77
  projectionRunId++
71
78
  unsubs.forEach((unsub) => unsub())
72
79
  unsubs = []
80
+ glassesStatusForwarder = null
81
+ hydrationPromise = null
73
82
  }