@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
@@ -10,16 +10,11 @@
10
10
  *
11
11
  * Started by `engine.start()`. Idempotent.
12
12
  */
13
- import BluetoothSdk from "@mentra/bluetooth-sdk/internal"
14
- import type {OtaStatus} from "@mentra/bluetooth-sdk/internal"
13
+ import BluetoothSdk, {type OtaStatus} from "@mentra/bluetooth-sdk"
15
14
  import GlobalEventEmitter from "../utils/GlobalEventEmitter"
16
15
  import {useGlassesStore} from "../stores/glasses"
17
16
  import {handleOtaClockSkewFromGlasses} from "./glassesClockSync"
18
- import {
19
- legacyOtaProgressFromOtaStatusEvent,
20
- normalizeOtaStatusEvent,
21
- otaStatusFromNormalized,
22
- } from "./otaLegacyMapping"
17
+ import {legacyOtaProgressFromOtaStatusEvent, normalizeOtaStatusEvent, otaStatusFromNormalized} from "./otaLegacyMapping"
23
18
 
24
19
  let subs: Array<{remove: () => void}> = []
25
20
 
@@ -40,6 +35,16 @@ export function startOtaService(): void {
40
35
  }),
41
36
  )
42
37
 
38
+ // The glasses process restarted under a live BLE link (sid changed in
39
+ // glasses_ready/version_info_1). The physical connection never dropped, so this is
40
+ // the ONLY reconnect-edge signal the OTA coordinator gets after an APK install.
41
+ subs.push(
42
+ BluetoothSdk.addListener("glasses_session_changed", (event) => {
43
+ console.log(`[OTA] glasses_session_changed ${event.previous_sid || "<none>"} -> ${event.sid}`)
44
+ GlobalEventEmitter.emit("glasses_session_changed", {previousSid: event.previous_sid, sid: event.sid})
45
+ }),
46
+ )
47
+
43
48
  // Install progress / lifecycle. Updates both the new (otaStatus) and the legacy
44
49
  // (otaProgress) store shapes; auto-fixes clock skew on the relevant failures.
45
50
  subs.push(
@@ -1,8 +1,19 @@
1
- import BluetoothSdk from "@mentra/bluetooth-sdk/internal"
2
- import type {OtaUpdateInfo} from "@mentra/bluetooth-sdk/internal"
1
+ import BluetoothSdk, {type OtaUpdateInfo} from "@mentra/bluetooth-sdk"
2
+ import {ENGINE_RELEASE_METADATA} from "../generated/releaseMetadata"
3
3
  import {getGlassesSystemTimeMs, isGlassesConnected, useGlassesStore, waitForGlassesState} from "../stores/glasses"
4
4
  import {maybeFixGlassesClockFromVersionInfo} from "./glassesClockSync"
5
- import {getAsgOtaVersionUrl} from "./asgOtaVersionUrl"
5
+ import {hasConfiguredModernOtaManifestPin, resolveOtaManifestUrl} from "./otaManifestUrl"
6
+ import {resolveOtaReleaseVersion} from "./otaReleaseVersion"
7
+
8
+ /**
9
+ * Phone-side mirror of ASG's `DOWNGRADE_FLOOR_VERSION_CODE`. Set to the versionCode of the first
10
+ * release shipping the shared media root (the first downgrade-safe build). A non-positive value
11
+ * means downgrades are disabled, so the phone must NOT offer them — offering a downgrade the
12
+ * glasses' `DowngradeGate` will refuse leaves the version-change session with no install and the
13
+ * glasses reporting a bare "complete", which would otherwise present as false success. Keep this
14
+ * in lockstep with the ASG/recovery constant at release time.
15
+ */
16
+ export const DOWNGRADE_FLOOR_VERSION_CODE = 0
6
17
 
7
18
  export interface VersionInfo {
8
19
  versionCode: number
@@ -18,14 +29,17 @@ export interface MtkPatch {
18
29
  start_firmware: string
19
30
  end_firmware: string
20
31
  url: string
32
+ sha256?: string
21
33
  }
22
34
 
23
35
  export interface BesFirmware {
24
36
  version: string
25
37
  url: string
38
+ sha256?: string
26
39
  }
27
40
 
28
41
  export interface VersionJson {
42
+ releaseVersion?: string
29
43
  apps?: {
30
44
  [packageName: string]: VersionInfo
31
45
  }
@@ -46,9 +60,25 @@ export interface OtaCheckResult {
46
60
  updates: string[]
47
61
  mtkPatch: MtkPatch | null
48
62
  besVersion: string | null
63
+ /** True when the pending APK step installs an OLDER build than the glasses currently run. */
64
+ isApkDowngrade: boolean
65
+ /**
66
+ * Raw manifest JSON (stringified) this check actually fetched, or null when the
67
+ * fetch failed. Lets change-watchers baseline on exactly what the check saw,
68
+ * instead of racing it with a second fetch of the same URL.
69
+ */
70
+ manifestBody: string | null
71
+ /** Coordinated release identity for the selected OTA pin. */
72
+ releaseVersion: string | null
73
+ /**
74
+ * Why the check failed, when it did. "network" is retryable (connection/server
75
+ * trouble); "pin_unavailable" is permanent for this app build (manifest 404/gone,
76
+ * unparseable, or carrying no valid ASG pin) — the remedy is updating the app.
77
+ */
78
+ checkFailureReason?: "network" | "pin_unavailable"
49
79
  }
50
80
 
51
- export type OtaCheckSkippedReason = "disconnected" | "missing_build"
81
+ export type OtaCheckSkippedReason = "disconnected" | "missing_build" | "dev_build"
52
82
 
53
83
  export interface OtaCheckCurrentGlassesResult extends OtaCheckResult {
54
84
  updateInfo: OtaUpdateInfo | null
@@ -66,6 +96,8 @@ export interface OtaCheckCurrentGlassesOptions {
66
96
  waitForMtkVersionMs?: number
67
97
  refreshVersionInfo?: boolean
68
98
  fixClockBeforeCheck?: boolean
99
+ /** Downgrade floor override (defaults to DOWNGRADE_FLOOR_VERSION_CODE); for tests. */
100
+ floorVersionCode?: number
69
101
  }
70
102
 
71
103
  function emptyCheckResult(skippedReason?: OtaCheckSkippedReason): OtaCheckCurrentGlassesResult {
@@ -76,6 +108,9 @@ function emptyCheckResult(skippedReason?: OtaCheckSkippedReason): OtaCheckCurren
76
108
  updates: [],
77
109
  mtkPatch: null,
78
110
  besVersion: null,
111
+ isApkDowngrade: false,
112
+ manifestBody: null,
113
+ releaseVersion: null,
79
114
  updateInfo: null,
80
115
  isRequired: true,
81
116
  skippedReason,
@@ -86,46 +121,90 @@ function glassesConnectedNow(): boolean {
86
121
  return isGlassesConnected(useGlassesStore.getState().connection)
87
122
  }
88
123
 
89
- export async function fetchVersionInfo(url: string): Promise<VersionJson | null> {
124
+ type ManifestFetchResult = {json: VersionJson | null; failureReason?: "network" | "pin_unavailable"}
125
+
126
+ async function fetchVersionInfoDetailed(url: string): Promise<ManifestFetchResult> {
90
127
  try {
91
128
  const response = await fetch(url)
92
129
  if (!response.ok) {
93
- console.error("Failed to fetch version info:", response.status)
94
- return null
130
+ console.warn("Failed to fetch version info:", response.status)
131
+ // 4xx: the manifest does not exist (or is gone) — permanent for this app
132
+ // build, retrying cannot help. Everything else is transient server/network
133
+ // trouble and retryable.
134
+ return {
135
+ json: null,
136
+ failureReason: response.status >= 400 && response.status < 500 ? "pin_unavailable" : "network",
137
+ }
138
+ }
139
+ try {
140
+ return {json: await response.json()}
141
+ } catch (parseError) {
142
+ console.warn("OTA: manifest is not valid JSON:", parseError)
143
+ return {json: null, failureReason: "pin_unavailable"}
95
144
  }
96
- return await response.json()
97
145
  } catch (error) {
98
- console.error("OTA: Error fetching version info:", error)
99
- return null
146
+ console.warn("OTA: Error fetching version info:", error)
147
+ return {json: null, failureReason: "network"}
100
148
  }
101
149
  }
102
150
 
151
+ export async function fetchVersionInfo(url: string): Promise<VersionJson | null> {
152
+ return (await fetchVersionInfoDetailed(url)).json
153
+ }
154
+
103
155
  export function checkVersionUpdateAvailable(
104
156
  currentBuildNumber: string | undefined,
105
157
  versionJson: VersionJson | null,
158
+ floorVersionCode: number = DOWNGRADE_FLOOR_VERSION_CODE,
106
159
  ): boolean {
160
+ return getApkUpdateDirection(currentBuildNumber, versionJson, floorVersionCode) !== null
161
+ }
162
+
163
+ /**
164
+ * Direction of the pending APK change, or null when the glasses already match the manifest.
165
+ * Every apps-shaped manifest the phone drives is an exact pin, so both directions are
166
+ * actionable (mirroring the glasses-side `DowngradeGate`); the ancient top-level manifest
167
+ * shape stays upgrade-only, and zeroed rescue pins are never actionable.
168
+ */
169
+ export function getApkUpdateDirection(
170
+ currentBuildNumber: string | undefined,
171
+ versionJson: VersionJson | null,
172
+ floorVersionCode: number = DOWNGRADE_FLOOR_VERSION_CODE,
173
+ ): "upgrade" | "downgrade" | null {
107
174
  if (!currentBuildNumber || !versionJson) {
108
- return false
175
+ return null
109
176
  }
110
177
 
111
178
  const currentVersion = parseInt(currentBuildNumber, 10)
112
179
  if (isNaN(currentVersion)) {
113
- return false
180
+ return null
114
181
  }
115
182
 
116
183
  let serverVersion: number | undefined
184
+ let exactPin = false
117
185
 
118
- if (versionJson.apps?.["com.mentra.asg_client"]) {
119
- serverVersion = versionJson.apps["com.mentra.asg_client"].versionCode
186
+ const appEntry = versionJson.apps?.["com.mentra.asg_client"]
187
+ if (appEntry) {
188
+ serverVersion = appEntry.versionCode
189
+ exactPin = true
120
190
  } else if (versionJson.versionCode) {
121
191
  serverVersion = versionJson.versionCode
122
192
  }
123
193
 
124
194
  if (!serverVersion || isNaN(serverVersion)) {
125
- return false
195
+ return null
126
196
  }
127
197
 
128
- return serverVersion > currentVersion
198
+ if (serverVersion > currentVersion) {
199
+ return "upgrade"
200
+ }
201
+ // Downgrades require an exact pin AND a target at/above the enabled floor. A non-positive floor
202
+ // disables downgrades entirely, matching ASG's fail-closed DowngradeGate — so the phone never
203
+ // offers what the glasses would refuse.
204
+ if (serverVersion < currentVersion && exactPin && floorVersionCode > 0 && serverVersion >= floorVersionCode) {
205
+ return "downgrade"
206
+ }
207
+ return null
129
208
  }
130
209
 
131
210
  export function getLatestVersionInfo(versionJson: VersionJson | null): VersionInfo | null {
@@ -184,7 +263,7 @@ export function checkBesUpdate(besFirmware: BesFirmware | undefined, currentVers
184
263
  return compareVersions(besFirmware.version, currentVersion) > 0
185
264
  }
186
265
 
187
- function compareVersions(version1: string, version2: string): number {
266
+ export function compareVersions(version1: string, version2: string): number {
188
267
  if (version1.includes(".") && version2.includes(".")) {
189
268
  const parts1 = version1.split(".")
190
269
  const parts2 = version2.split(".")
@@ -208,14 +287,64 @@ export async function checkForOtaUpdate(
208
287
  currentBuildNumber: string,
209
288
  currentMtkVersion?: string,
210
289
  currentBesVersion?: string,
290
+ floorVersionCode: number = DOWNGRADE_FLOOR_VERSION_CODE,
211
291
  ): Promise<OtaCheckResult> {
212
292
  try {
213
293
  console.log("OTA: Checking for OTA update - URL: " + otaVersionUrl + ", current build: " + currentBuildNumber)
214
- const versionJson = await fetchVersionInfo(otaVersionUrl)
294
+ const fetched = await fetchVersionInfoDetailed(otaVersionUrl)
295
+ const versionJson = fetched.json
296
+ if (!versionJson) {
297
+ return {
298
+ hasCheckCompleted: false,
299
+ updateAvailable: false,
300
+ latestVersionInfo: null,
301
+ updates: [],
302
+ mtkPatch: null,
303
+ besVersion: null,
304
+ isApkDowngrade: false,
305
+ manifestBody: null,
306
+ releaseVersion: null,
307
+ checkFailureReason: fetched.failureReason ?? "network",
308
+ }
309
+ }
215
310
  const latestVersionInfo = getLatestVersionInfo(versionJson)
216
311
 
217
- const apkUpdateAvailable = checkVersionUpdateAvailable(currentBuildNumber, versionJson)
218
- console.log(`OTA: APK update available: ${apkUpdateAvailable} (current: ${currentBuildNumber})`)
312
+ // A manifest whose ASG pin is missing/zeroed cannot verify anything for modern
313
+ // glasses (zeroed pins are only legitimate in the frozen legacy rescue manifests
314
+ // that pre-39 glasses are checked against). Report the check as FAILED rather
315
+ // than silently completing as "up to date" — an unverifiable state must never
316
+ // present as a verified one.
317
+ const currentVersionNumber = parseInt(currentBuildNumber, 10)
318
+ const pinnedEntry = versionJson?.apps?.["com.mentra.asg_client"]
319
+ const pinnedVersion = pinnedEntry?.versionCode ?? versionJson?.versionCode
320
+ if (
321
+ versionJson &&
322
+ Number.isFinite(currentVersionNumber) &&
323
+ currentVersionNumber >= 39 &&
324
+ !(typeof pinnedVersion === "number" && pinnedVersion > 0)
325
+ ) {
326
+ console.error(
327
+ `OTA: manifest at ${otaVersionUrl} has no valid ASG pin (versionCode=${String(pinnedVersion)}) - treating check as failed`,
328
+ )
329
+ return {
330
+ hasCheckCompleted: false,
331
+ updateAvailable: false,
332
+ latestVersionInfo: null,
333
+ updates: [],
334
+ mtkPatch: null,
335
+ besVersion: null,
336
+ isApkDowngrade: false,
337
+ manifestBody: null,
338
+ releaseVersion: null,
339
+ checkFailureReason: "pin_unavailable",
340
+ }
341
+ }
342
+
343
+ const apkDirection = getApkUpdateDirection(currentBuildNumber, versionJson, floorVersionCode)
344
+ const apkUpdateAvailable = apkDirection !== null
345
+ console.log(
346
+ `OTA: APK update available: ${apkUpdateAvailable} (current: ${currentBuildNumber}, direction: ${apkDirection ?? "none"})`,
347
+ )
219
348
 
220
349
  const mtkPatch = findMatchingMtkPatch(versionJson?.mtk_patches, currentMtkVersion)
221
350
  const mtkUpdateAvailable = mtkPatch !== null
@@ -243,6 +372,14 @@ export async function checkForOtaUpdate(
243
372
  updates,
244
373
  mtkPatch,
245
374
  besVersion: versionJson?.bes_firmware?.version || null,
375
+ isApkDowngrade: apkDirection === "downgrade",
376
+ manifestBody: versionJson ? JSON.stringify(versionJson) : null,
377
+ releaseVersion: resolveOtaReleaseVersion({
378
+ manifestReleaseVersion: versionJson.releaseVersion,
379
+ manifestUrl: otaVersionUrl,
380
+ packagedManifestUrl: ENGINE_RELEASE_METADATA.otaManifestUrl,
381
+ packagedReleaseIdentity: ENGINE_RELEASE_METADATA.releaseIdentity,
382
+ }),
246
383
  }
247
384
  } catch (error) {
248
385
  console.error("Error checking for OTA update:", error)
@@ -253,6 +390,10 @@ export async function checkForOtaUpdate(
253
390
  updates: [],
254
391
  mtkPatch: null,
255
392
  besVersion: null,
393
+ isApkDowngrade: false,
394
+ manifestBody: null,
395
+ releaseVersion: null,
396
+ checkFailureReason: "network",
256
397
  }
257
398
  }
258
399
  }
@@ -266,16 +407,26 @@ export async function checkCurrentGlassesForUpdate(
266
407
  waitForMtkVersionMs = 2000,
267
408
  refreshVersionInfo = true,
268
409
  fixClockBeforeCheck = true,
410
+ floorVersionCode = DOWNGRADE_FLOOR_VERSION_CODE,
269
411
  } = options
270
412
 
271
413
  if (!glassesConnectedNow()) {
272
414
  return emptyCheckResult("disconnected")
273
415
  }
274
416
 
417
+ if (!hasConfiguredModernOtaManifestPin()) {
418
+ console.log("OTA: check skipped - this app or Engine package has no embedded OTA manifest pin")
419
+ return emptyCheckResult("dev_build")
420
+ }
421
+
275
422
  if (refreshVersionInfo) {
276
- void BluetoothSdk.requestVersionInfo().catch((error) => {
277
- console.warn("OTA: Failed to request version_info from glasses:", error)
278
- })
423
+ void BluetoothSdk.requestVersionInfo()
424
+ .then((versionInfo) => {
425
+ useGlassesStore.getState().setGlassesInfo(versionInfo)
426
+ })
427
+ .catch((error) => {
428
+ console.warn("OTA: Failed to request version_info from glasses:", error)
429
+ })
279
430
  }
280
431
 
281
432
  let buildNumber = useGlassesStore.getState().buildNumber
@@ -284,7 +435,10 @@ export async function checkCurrentGlassesForUpdate(
284
435
  buildNumber = useGlassesStore.getState().buildNumber
285
436
  }
286
437
 
287
- if (!buildNumber) {
438
+ if (!buildNumber || !(parseInt(buildNumber, 10) > 0)) {
439
+ // Covers absent, non-numeric, and zero build numbers: a glasses version we
440
+ // cannot parse means nothing is verifiable, so skip rather than ghost an
441
+ // "up to date" result from a comparison that never really ran.
288
442
  return emptyCheckResult("missing_build")
289
443
  }
290
444
 
@@ -325,8 +479,18 @@ export async function checkCurrentGlassesForUpdate(
325
479
  })
326
480
  }
327
481
 
328
- const manifestUrl = getAsgOtaVersionUrl(useGlassesStore.getState().otaVersionUrl, buildNumber)
329
- const result = await checkForOtaUpdate(manifestUrl, buildNumber, mtkFirmwareVersion, besFirmwareVersion)
482
+ const manifestUrl = resolveOtaManifestUrl(useGlassesStore.getState().otaVersionUrl, buildNumber)
483
+ if (!manifestUrl) {
484
+ console.log("OTA: check skipped - no OTA manifest pin resolved")
485
+ return emptyCheckResult("dev_build")
486
+ }
487
+ const result = await checkForOtaUpdate(
488
+ manifestUrl,
489
+ buildNumber,
490
+ mtkFirmwareVersion,
491
+ besFirmwareVersion,
492
+ floorVersionCode,
493
+ )
330
494
 
331
495
  if (!result.hasCheckCompleted) {
332
496
  return {
@@ -360,6 +524,7 @@ export async function checkCurrentGlassesForUpdate(
360
524
  )
361
525
  }
362
526
  const updateAvailable = filteredUpdates.length > 0 && !!result.latestVersionInfo
527
+ const isApkDowngrade = result.isApkDowngrade && filteredUpdates.includes("apk")
363
528
  const updateInfo = updateAvailable
364
529
  ? {
365
530
  available: true,
@@ -367,6 +532,8 @@ export async function checkCurrentGlassesForUpdate(
367
532
  versionName: result.latestVersionInfo?.versionName || "",
368
533
  updates: filteredUpdates,
369
534
  totalSize: 0,
535
+ ...(filteredUpdates.includes("bes") && result.besVersion ? {besVersion: result.besVersion} : {}),
536
+ isDowngrade: isApkDowngrade,
370
537
  }
371
538
  : null
372
539
 
@@ -376,8 +543,19 @@ export async function checkCurrentGlassesForUpdate(
376
543
  ...result,
377
544
  updateAvailable,
378
545
  updates: filteredUpdates,
546
+ isApkDowngrade,
379
547
  updateInfo,
380
- isRequired: result.latestVersionInfo?.isRequired !== false,
548
+ // Required-update policy: an EXPLICIT isRequired in the manifest is the
549
+ // release-engineering escape hatch and wins in both directions. When absent,
550
+ // upgrades keep the historical forced default, but downgrades are always
551
+ // skippable — a version change that resets glasses settings must be
552
+ // declinable unless someone explicitly forced it.
553
+ isRequired:
554
+ result.latestVersionInfo?.isRequired === true
555
+ ? true
556
+ : result.latestVersionInfo?.isRequired === false
557
+ ? false
558
+ : !isApkDowngrade,
381
559
  manifestUrl,
382
560
  buildNumber,
383
561
  mtkFirmwareVersion,
@@ -0,0 +1,212 @@
1
+ import {MiniappErrorCode, type CalendarEvent} from "@mentra/miniapp"
2
+
3
+ const DEFAULT_LIMIT = 50
4
+ const MAX_LIMIT = 100
5
+ const MAX_RANGE_MS = 31 * 24 * 60 * 60 * 1000
6
+
7
+ export interface CalendarListRequest {
8
+ startsAt?: unknown
9
+ endsAt?: unknown
10
+ limit?: unknown
11
+ }
12
+
13
+ export class PhoneCalendarError extends Error {
14
+ constructor(
15
+ public readonly code: MiniappErrorCode,
16
+ message: string,
17
+ ) {
18
+ super(message)
19
+ this.name = "PhoneCalendarError"
20
+ }
21
+ }
22
+
23
+ export interface ValidatedCalendarListRequest {
24
+ startsAt: Date
25
+ endsAt: Date
26
+ limit: number
27
+ }
28
+
29
+ export interface RawCalendarEvent {
30
+ id?: string
31
+ calendarId?: string
32
+ title?: string | null
33
+ startDate: string | Date
34
+ endDate: string | Date
35
+ timeZone?: string | null
36
+ allDay?: boolean
37
+ location?: string | null
38
+ notes?: string | null
39
+ url?: string | null
40
+ }
41
+
42
+ export function validateCalendarListRequest(request: CalendarListRequest): ValidatedCalendarListRequest {
43
+ const startsAt = parseDate(request.startsAt, "startsAt")
44
+ const endsAt = parseDate(request.endsAt, "endsAt")
45
+ if (endsAt.getTime() <= startsAt.getTime()) {
46
+ throw new PhoneCalendarError(MiniappErrorCode.INVALID_ARGUMENT, "endsAt must be after startsAt")
47
+ }
48
+ if (endsAt.getTime() - startsAt.getTime() > MAX_RANGE_MS) {
49
+ throw new PhoneCalendarError(MiniappErrorCode.INVALID_ARGUMENT, "Calendar query range may not exceed 31 days")
50
+ }
51
+
52
+ const limit = request.limit === undefined ? DEFAULT_LIMIT : request.limit
53
+ if (typeof limit !== "number" || !Number.isInteger(limit) || limit < 1 || limit > MAX_LIMIT) {
54
+ throw new PhoneCalendarError(
55
+ MiniappErrorCode.INVALID_ARGUMENT,
56
+ `limit must be an integer between 1 and ${MAX_LIMIT}`,
57
+ )
58
+ }
59
+ return {startsAt, endsAt, limit}
60
+ }
61
+
62
+ function parseDate(value: unknown, field: string): Date {
63
+ if (typeof value !== "string") {
64
+ throw new PhoneCalendarError(MiniappErrorCode.INVALID_ARGUMENT, `${field} must be an ISO 8601 string`)
65
+ }
66
+ const date = new Date(value)
67
+ if (Number.isNaN(date.getTime())) {
68
+ throw new PhoneCalendarError(MiniappErrorCode.INVALID_ARGUMENT, `${field} must be a valid ISO 8601 string`)
69
+ }
70
+ return date
71
+ }
72
+
73
+ export function extractHttpsLinks(...values: Array<string | null | undefined>): string[] {
74
+ const links = new Set<string>()
75
+ for (const value of values) {
76
+ for (const match of value?.match(/https:\/\/[^\s<>"']+/gi) ?? []) {
77
+ let link = match
78
+ while (".,;:!?)]}".includes(link[link.length - 1] ?? "")) link = link.slice(0, -1)
79
+ if (link) links.add(link)
80
+ }
81
+ }
82
+ return [...links]
83
+ }
84
+
85
+ interface CalendarDateParts {
86
+ year: number
87
+ month: number
88
+ day: number
89
+ hour: number
90
+ minute: number
91
+ second: number
92
+ }
93
+
94
+ function localDateParts(date: Date): CalendarDateParts {
95
+ return {
96
+ year: date.getFullYear(),
97
+ month: date.getMonth() + 1,
98
+ day: date.getDate(),
99
+ hour: date.getHours(),
100
+ minute: date.getMinutes(),
101
+ second: date.getSeconds(),
102
+ }
103
+ }
104
+
105
+ function datePartsInTimeZone(date: Date, timeZone: string): CalendarDateParts | undefined {
106
+ try {
107
+ const parts = new Intl.DateTimeFormat("en-US", {
108
+ timeZone,
109
+ year: "numeric",
110
+ month: "2-digit",
111
+ day: "2-digit",
112
+ hour: "2-digit",
113
+ minute: "2-digit",
114
+ second: "2-digit",
115
+ hourCycle: "h23",
116
+ }).formatToParts(date)
117
+ const value = (type: Intl.DateTimeFormatPartTypes) => Number(parts.find((part) => part.type === type)?.value)
118
+ return {
119
+ year: value("year"),
120
+ month: value("month"),
121
+ day: value("day"),
122
+ hour: value("hour"),
123
+ minute: value("minute"),
124
+ second: value("second"),
125
+ }
126
+ } catch {
127
+ return undefined
128
+ }
129
+ }
130
+
131
+ function timeZoneOffsetMinutes(date: Date, timeZone: string): number | undefined {
132
+ const parts = datePartsInTimeZone(date, timeZone)
133
+ if (!parts) return undefined
134
+ const representedAsUtc = Date.UTC(
135
+ parts.year,
136
+ parts.month - 1,
137
+ parts.day,
138
+ parts.hour,
139
+ parts.minute,
140
+ parts.second,
141
+ date.getUTCMilliseconds(),
142
+ )
143
+ return Math.round((representedAsUtc - date.getTime()) / 60_000)
144
+ }
145
+
146
+ function pad(value: number, length = 2): string {
147
+ return String(value).padStart(length, "0")
148
+ }
149
+
150
+ function formatOffset(offsetMinutes: number): string {
151
+ if (offsetMinutes === 0) return "Z"
152
+ const sign = offsetMinutes < 0 ? "-" : "+"
153
+ const absolute = Math.abs(offsetMinutes)
154
+ return `${sign}${pad(Math.floor(absolute / 60))}:${pad(absolute % 60)}`
155
+ }
156
+
157
+ function formatAllDayDate(value: string | Date, timeZone?: string | null): string {
158
+ const dateOnly = typeof value === "string" ? /^(\d{4})-(\d{2})-(\d{2})$/.exec(value) : null
159
+ if (dateOnly) {
160
+ const [, year, month, day] = dateOnly
161
+ const localMidnight = new Date(Number(year), Number(month) - 1, Number(day))
162
+ let offsetMinutes = -localMidnight.getTimezoneOffset()
163
+ if (timeZone) {
164
+ // Resolve the offset at midnight in the event timezone. Repeating once
165
+ // accounts for the initial UTC guess landing across a DST boundary.
166
+ const wallTime = Date.UTC(Number(year), Number(month) - 1, Number(day))
167
+ let instant = new Date(wallTime)
168
+ for (let attempt = 0; attempt < 2; attempt += 1) {
169
+ const offset = timeZoneOffsetMinutes(instant, timeZone)
170
+ if (offset === undefined) break
171
+ offsetMinutes = offset
172
+ instant = new Date(wallTime - offset * 60_000)
173
+ }
174
+ }
175
+ return `${year}-${month}-${day}T00:00:00.000${formatOffset(offsetMinutes)}`
176
+ }
177
+
178
+ const date = new Date(value)
179
+ const zonedParts = timeZone ? datePartsInTimeZone(date, timeZone) : undefined
180
+ const parts = zonedParts ?? localDateParts(date)
181
+ const offsetMinutes =
182
+ timeZone && zonedParts
183
+ ? (timeZoneOffsetMinutes(date, timeZone) ?? -date.getTimezoneOffset())
184
+ : -date.getTimezoneOffset()
185
+ return `${pad(parts.year, 4)}-${pad(parts.month)}-${pad(parts.day)}T${pad(parts.hour)}:${pad(parts.minute)}:${pad(parts.second)}.${pad(date.getUTCMilliseconds(), 3)}${formatOffset(offsetMinutes)}`
186
+ }
187
+
188
+ export function normalizeCalendarEvent(event: RawCalendarEvent): CalendarEvent {
189
+ const startsAt = event.allDay
190
+ ? formatAllDayDate(event.startDate, event.timeZone)
191
+ : new Date(event.startDate).toISOString()
192
+ const endsAt = event.allDay ? formatAllDayDate(event.endDate, event.timeZone) : new Date(event.endDate).toISOString()
193
+ const calendarId = event.calendarId ?? ""
194
+ const eventId = event.id ?? ""
195
+ return {
196
+ id: `${calendarId}:${eventId}:${startsAt}`,
197
+ calendarId,
198
+ title: event.title ?? "",
199
+ startsAt,
200
+ endsAt,
201
+ ...(event.timeZone ? {timezone: event.timeZone} : {}),
202
+ allDay: !!event.allDay,
203
+ ...(event.location ? {location: event.location} : {}),
204
+ ...(event.notes ? {notes: event.notes} : {}),
205
+ ...(event.url ? {url: event.url} : {}),
206
+ links: extractHttpsLinks(event.url, event.location, event.notes),
207
+ }
208
+ }
209
+
210
+ export function calendarEventOverlapsWindow(event: CalendarEvent, startsAt: Date, endsAt: Date): boolean {
211
+ return Date.parse(event.endsAt) > startsAt.getTime() && Date.parse(event.startsAt) < endsAt.getTime()
212
+ }