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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (503) hide show
  1. package/README.md +55 -18
  2. package/build/bluetooth-sdk/debug.d.ts +2 -0
  3. package/build/bluetooth-sdk/debug.d.ts.map +1 -0
  4. package/build/bluetooth-sdk/debug.js +2 -0
  5. package/build/bluetooth-sdk/debug.js.map +1 -0
  6. package/build/bluetooth-sdk/index.d.ts +3 -0
  7. package/build/bluetooth-sdk/index.d.ts.map +1 -0
  8. package/build/bluetooth-sdk/index.js +3 -0
  9. package/build/bluetooth-sdk/index.js.map +1 -0
  10. package/build/bluetooth-sdk/photo-receiver.d.ts +3 -0
  11. package/build/bluetooth-sdk/photo-receiver.d.ts.map +1 -0
  12. package/build/bluetooth-sdk/photo-receiver.js +3 -0
  13. package/build/bluetooth-sdk/photo-receiver.js.map +1 -0
  14. package/build/bluetooth-sdk/react.d.ts +2 -0
  15. package/build/bluetooth-sdk/react.d.ts.map +1 -0
  16. package/build/bluetooth-sdk/react.js +2 -0
  17. package/build/bluetooth-sdk/react.js.map +1 -0
  18. package/build/bluetooth-sdk/types.d.ts +2 -0
  19. package/build/bluetooth-sdk/types.d.ts.map +1 -0
  20. package/build/bluetooth-sdk/types.js +2 -0
  21. package/build/bluetooth-sdk/types.js.map +1 -0
  22. package/build/engine.d.ts +24 -16
  23. package/build/engine.d.ts.map +1 -1
  24. package/build/engine.js +9 -4
  25. package/build/engine.js.map +1 -1
  26. package/build/facades/dev.d.ts +3 -2
  27. package/build/facades/dev.d.ts.map +1 -1
  28. package/build/facades/dev.js +18 -12
  29. package/build/facades/dev.js.map +1 -1
  30. package/build/facades/display.d.ts +1 -1
  31. package/build/facades/display.d.ts.map +1 -1
  32. package/build/facades/display.js +1 -1
  33. package/build/facades/display.js.map +1 -1
  34. package/build/facades/gallery.js +1 -1
  35. package/build/facades/gallery.js.map +1 -1
  36. package/build/facades/glasses.d.ts +4 -13
  37. package/build/facades/glasses.d.ts.map +1 -1
  38. package/build/facades/glasses.js +21 -6
  39. package/build/facades/glasses.js.map +1 -1
  40. package/build/facades/glassesSettings.d.ts.map +1 -1
  41. package/build/facades/glassesSettings.js +1 -0
  42. package/build/facades/glassesSettings.js.map +1 -1
  43. package/build/facades/miniapps.d.ts +4 -0
  44. package/build/facades/miniapps.d.ts.map +1 -1
  45. package/build/facades/miniapps.js +5 -0
  46. package/build/facades/miniapps.js.map +1 -1
  47. package/build/facades/ota.d.ts +14 -16
  48. package/build/facades/ota.d.ts.map +1 -1
  49. package/build/facades/ota.js +22 -7
  50. package/build/facades/ota.js.map +1 -1
  51. package/build/facades/pairing.d.ts +8 -5
  52. package/build/facades/pairing.d.ts.map +1 -1
  53. package/build/facades/pairing.js +12 -10
  54. package/build/facades/pairing.js.map +1 -1
  55. package/build/facades/permissions.d.ts +10 -0
  56. package/build/facades/permissions.d.ts.map +1 -1
  57. package/build/facades/permissions.js +10 -0
  58. package/build/facades/permissions.js.map +1 -1
  59. package/build/facades/phoneNotifications.d.ts +0 -4
  60. package/build/facades/phoneNotifications.d.ts.map +1 -1
  61. package/build/facades/phoneNotifications.js +4 -14
  62. package/build/facades/phoneNotifications.js.map +1 -1
  63. package/build/facades/speech.d.ts +7 -6
  64. package/build/facades/speech.d.ts.map +1 -1
  65. package/build/facades/speech.js +1 -1
  66. package/build/facades/speech.js.map +1 -1
  67. package/build/generated/releaseMetadata.d.ts +12 -0
  68. package/build/generated/releaseMetadata.d.ts.map +1 -0
  69. package/build/generated/releaseMetadata.js +10 -0
  70. package/build/generated/releaseMetadata.js.map +1 -0
  71. package/build/index.d.ts +10 -8
  72. package/build/index.d.ts.map +1 -1
  73. package/build/index.js +6 -5
  74. package/build/index.js.map +1 -1
  75. package/build/react/MentraLiveOtaFlow.d.ts +38 -0
  76. package/build/react/MentraLiveOtaFlow.d.ts.map +1 -0
  77. package/build/react/MentraLiveOtaFlow.js +528 -0
  78. package/build/react/MentraLiveOtaFlow.js.map +1 -0
  79. package/build/react/index.d.ts +2 -0
  80. package/build/react/index.d.ts.map +1 -0
  81. package/build/react/index.js +2 -0
  82. package/build/react/index.js.map +1 -0
  83. package/build/react/useEngineSnapshot.d.ts +2 -0
  84. package/build/react/useEngineSnapshot.d.ts.map +1 -0
  85. package/build/react/useEngineSnapshot.js +14 -0
  86. package/build/react/useEngineSnapshot.js.map +1 -0
  87. package/build/runtime/bootstrap.d.ts +24 -1
  88. package/build/runtime/bootstrap.d.ts.map +1 -1
  89. package/build/runtime/bootstrap.js +17 -0
  90. package/build/runtime/bootstrap.js.map +1 -1
  91. package/build/runtime/scanQrSeam.d.ts +7 -0
  92. package/build/runtime/scanQrSeam.d.ts.map +1 -0
  93. package/build/runtime/scanQrSeam.js +16 -0
  94. package/build/runtime/scanQrSeam.js.map +1 -0
  95. package/build/services/AppRegistry.d.ts +41 -57
  96. package/build/services/AppRegistry.d.ts.map +1 -1
  97. package/build/services/AppRegistry.js +208 -144
  98. package/build/services/AppRegistry.js.map +1 -1
  99. package/build/services/AudioCloudUplink.d.ts +12 -0
  100. package/build/services/AudioCloudUplink.d.ts.map +1 -1
  101. package/build/services/AudioCloudUplink.js +22 -1
  102. package/build/services/AudioCloudUplink.js.map +1 -1
  103. package/build/services/AudioPlaybackService.d.ts +41 -2
  104. package/build/services/AudioPlaybackService.d.ts.map +1 -1
  105. package/build/services/AudioPlaybackService.js +250 -33
  106. package/build/services/AudioPlaybackService.js.map +1 -1
  107. package/build/services/BlobStore.d.ts +2 -1
  108. package/build/services/BlobStore.d.ts.map +1 -1
  109. package/build/services/BlobStore.js +17 -9
  110. package/build/services/BlobStore.js.map +1 -1
  111. package/build/services/CloudAudioSubscriptionSync.d.ts.map +1 -1
  112. package/build/services/CloudAudioSubscriptionSync.js +13 -1
  113. package/build/services/CloudAudioSubscriptionSync.js.map +1 -1
  114. package/build/services/CloudClientService.d.ts +15 -0
  115. package/build/services/CloudClientService.d.ts.map +1 -1
  116. package/build/services/CloudClientService.js +93 -1
  117. package/build/services/CloudClientService.js.map +1 -1
  118. package/build/services/DeviceEventRouter.js +5 -5
  119. package/build/services/DeviceEventRouter.js.map +1 -1
  120. package/build/services/ForegroundLocationPermission.d.ts +13 -0
  121. package/build/services/ForegroundLocationPermission.d.ts.map +1 -0
  122. package/build/services/ForegroundLocationPermission.js +12 -0
  123. package/build/services/ForegroundLocationPermission.js.map +1 -0
  124. package/build/services/GlassesSettingsSync.d.ts.map +1 -1
  125. package/build/services/GlassesSettingsSync.js +9 -3
  126. package/build/services/GlassesSettingsSync.js.map +1 -1
  127. package/build/services/GlassesStatusProjection.d.ts +2 -1
  128. package/build/services/GlassesStatusProjection.d.ts.map +1 -1
  129. package/build/services/GlassesStatusProjection.js +15 -8
  130. package/build/services/GlassesStatusProjection.js.map +1 -1
  131. package/build/services/HotspotOtaTransport.d.ts +29 -0
  132. package/build/services/HotspotOtaTransport.d.ts.map +1 -0
  133. package/build/services/HotspotOtaTransport.js +146 -0
  134. package/build/services/HotspotOtaTransport.js.map +1 -0
  135. package/build/services/HotspotShutdown.d.ts +17 -0
  136. package/build/services/HotspotShutdown.d.ts.map +1 -0
  137. package/build/services/HotspotShutdown.js +29 -0
  138. package/build/services/HotspotShutdown.js.map +1 -0
  139. package/build/services/LocalDisplayManager.d.ts +15 -0
  140. package/build/services/LocalDisplayManager.d.ts.map +1 -1
  141. package/build/services/LocalDisplayManager.js +106 -20
  142. package/build/services/LocalDisplayManager.js.map +1 -1
  143. package/build/services/LocalMiniappRuntime.d.ts +74 -2
  144. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  145. package/build/services/LocalMiniappRuntime.js +785 -291
  146. package/build/services/LocalMiniappRuntime.js.map +1 -1
  147. package/build/services/LocalMiniappStorage.d.ts +32 -0
  148. package/build/services/LocalMiniappStorage.d.ts.map +1 -0
  149. package/build/services/LocalMiniappStorage.js +66 -0
  150. package/build/services/LocalMiniappStorage.js.map +1 -0
  151. package/build/services/LocalMiniappUserIdentity.d.ts +20 -0
  152. package/build/services/LocalMiniappUserIdentity.d.ts.map +1 -0
  153. package/build/services/LocalMiniappUserIdentity.js +43 -0
  154. package/build/services/LocalMiniappUserIdentity.js.map +1 -0
  155. package/build/services/LocalSttFallbackCoordinator.d.ts +9 -6
  156. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
  157. package/build/services/LocalSttFallbackCoordinator.js +18 -12
  158. package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
  159. package/build/services/MicStateCoordinator.d.ts +42 -1
  160. package/build/services/MicStateCoordinator.d.ts.map +1 -1
  161. package/build/services/MicStateCoordinator.js +141 -3
  162. package/build/services/MicStateCoordinator.js.map +1 -1
  163. package/build/services/MiniappLauncher.d.ts.map +1 -1
  164. package/build/services/MiniappLauncher.js +23 -3
  165. package/build/services/MiniappLauncher.js.map +1 -1
  166. package/build/services/MiniappLiveness.d.ts +12 -0
  167. package/build/services/MiniappLiveness.d.ts.map +1 -0
  168. package/build/services/MiniappLiveness.js +16 -0
  169. package/build/services/MiniappLiveness.js.map +1 -0
  170. package/build/services/NativeHttpResponse.d.ts +3 -0
  171. package/build/services/NativeHttpResponse.d.ts.map +1 -0
  172. package/build/services/NativeHttpResponse.js +6 -0
  173. package/build/services/NativeHttpResponse.js.map +1 -0
  174. package/build/services/OtaArtifactDownloader.d.ts +65 -0
  175. package/build/services/OtaArtifactDownloader.d.ts.map +1 -0
  176. package/build/services/OtaArtifactDownloader.js +226 -0
  177. package/build/services/OtaArtifactDownloader.js.map +1 -0
  178. package/build/services/OtaAutoChain.d.ts +34 -0
  179. package/build/services/OtaAutoChain.d.ts.map +1 -0
  180. package/build/services/OtaAutoChain.js +83 -0
  181. package/build/services/OtaAutoChain.js.map +1 -0
  182. package/build/services/OtaErrorMapping.d.ts +18 -0
  183. package/build/services/OtaErrorMapping.d.ts.map +1 -0
  184. package/build/services/OtaErrorMapping.js +63 -0
  185. package/build/services/OtaErrorMapping.js.map +1 -0
  186. package/build/services/OtaInstallCoordinator.d.ts +95 -15
  187. package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
  188. package/build/services/OtaInstallCoordinator.js +577 -130
  189. package/build/services/OtaInstallCoordinator.js.map +1 -1
  190. package/build/services/OtaService.d.ts.map +1 -1
  191. package/build/services/OtaService.js +8 -1
  192. package/build/services/OtaService.js.map +1 -1
  193. package/build/services/OtaUpdateCheckService.d.ts +39 -4
  194. package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
  195. package/build/services/OtaUpdateCheckService.js +138 -22
  196. package/build/services/OtaUpdateCheckService.js.map +1 -1
  197. package/build/services/PhoneCalendarHelpers.d.ts +32 -0
  198. package/build/services/PhoneCalendarHelpers.d.ts.map +1 -0
  199. package/build/services/PhoneCalendarHelpers.js +157 -0
  200. package/build/services/PhoneCalendarHelpers.js.map +1 -0
  201. package/build/services/PhoneCalendarService.d.ts +5 -0
  202. package/build/services/PhoneCalendarService.d.ts.map +1 -0
  203. package/build/services/PhoneCalendarService.js +45 -0
  204. package/build/services/PhoneCalendarService.js.map +1 -0
  205. package/build/services/PhoneCameraFovCoordinator.d.ts +30 -0
  206. package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -0
  207. package/build/services/PhoneCameraFovCoordinator.js +194 -0
  208. package/build/services/PhoneCameraFovCoordinator.js.map +1 -0
  209. package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
  210. package/build/services/PhoneNotificationsSync.js +12 -10
  211. package/build/services/PhoneNotificationsSync.js.map +1 -1
  212. package/build/services/PhonePhotoCoordinator.d.ts +26 -2
  213. package/build/services/PhonePhotoCoordinator.d.ts.map +1 -1
  214. package/build/services/PhonePhotoCoordinator.js +79 -9
  215. package/build/services/PhonePhotoCoordinator.js.map +1 -1
  216. package/build/services/PhoneStreamCoordinator.d.ts +8 -1
  217. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
  218. package/build/services/PhoneStreamCoordinator.js +125 -13
  219. package/build/services/PhoneStreamCoordinator.js.map +1 -1
  220. package/build/services/PhoneVideoCoordinator.d.ts +2 -0
  221. package/build/services/PhoneVideoCoordinator.d.ts.map +1 -1
  222. package/build/services/PhoneVideoCoordinator.js +10 -0
  223. package/build/services/PhoneVideoCoordinator.js.map +1 -1
  224. package/build/services/SceneRenderer.d.ts.map +1 -1
  225. package/build/services/SceneRenderer.js +15 -0
  226. package/build/services/SceneRenderer.js.map +1 -1
  227. package/build/services/SentenceTtsPipeline.d.ts +31 -0
  228. package/build/services/SentenceTtsPipeline.d.ts.map +1 -0
  229. package/build/services/SentenceTtsPipeline.js +67 -0
  230. package/build/services/SentenceTtsPipeline.js.map +1 -0
  231. package/build/services/SupportProfileSync.d.ts +22 -0
  232. package/build/services/SupportProfileSync.d.ts.map +1 -0
  233. package/build/services/SupportProfileSync.js +213 -0
  234. package/build/services/SupportProfileSync.js.map +1 -0
  235. package/build/services/TranscriptionRouting.d.ts +12 -0
  236. package/build/services/TranscriptionRouting.d.ts.map +1 -0
  237. package/build/services/TranscriptionRouting.js +24 -0
  238. package/build/services/TranscriptionRouting.js.map +1 -0
  239. package/build/services/TtsTextSanitizer.d.ts +5 -0
  240. package/build/services/TtsTextSanitizer.d.ts.map +1 -0
  241. package/build/services/TtsTextSanitizer.js +61 -0
  242. package/build/services/TtsTextSanitizer.js.map +1 -0
  243. package/build/services/WifiAdbRequest.d.ts +17 -0
  244. package/build/services/WifiAdbRequest.d.ts.map +1 -0
  245. package/build/services/WifiAdbRequest.js +35 -0
  246. package/build/services/WifiAdbRequest.js.map +1 -0
  247. package/build/services/asg/asgCameraApi.d.ts +43 -0
  248. package/build/services/asg/asgCameraApi.d.ts.map +1 -1
  249. package/build/services/asg/asgCameraApi.js +509 -26
  250. package/build/services/asg/asgCameraApi.js.map +1 -1
  251. package/build/services/asg/cameraRollExportCoordinator.d.ts +60 -0
  252. package/build/services/asg/cameraRollExportCoordinator.d.ts.map +1 -0
  253. package/build/services/asg/cameraRollExportCoordinator.js +618 -0
  254. package/build/services/asg/cameraRollExportCoordinator.js.map +1 -0
  255. package/build/services/asg/cameraRollExportLedger.d.ts +44 -0
  256. package/build/services/asg/cameraRollExportLedger.d.ts.map +1 -0
  257. package/build/services/asg/cameraRollExportLedger.js +78 -0
  258. package/build/services/asg/cameraRollExportLedger.js.map +1 -0
  259. package/build/services/asg/galleryNotices.d.ts +1 -1
  260. package/build/services/asg/galleryNotices.d.ts.map +1 -1
  261. package/build/services/asg/galleryNotices.js.map +1 -1
  262. package/build/services/asg/galleryPathMigration.d.ts +3 -0
  263. package/build/services/asg/galleryPathMigration.d.ts.map +1 -0
  264. package/build/services/asg/galleryPathMigration.js +26 -0
  265. package/build/services/asg/galleryPathMigration.js.map +1 -0
  266. package/build/services/asg/gallerySettingsService.d.ts +1 -0
  267. package/build/services/asg/gallerySettingsService.d.ts.map +1 -1
  268. package/build/services/asg/gallerySettingsService.js +2 -0
  269. package/build/services/asg/gallerySettingsService.js.map +1 -1
  270. package/build/services/asg/gallerySyncService.d.ts.map +1 -1
  271. package/build/services/asg/gallerySyncService.js +162 -56
  272. package/build/services/asg/gallerySyncService.js.map +1 -1
  273. package/build/services/asg/galleryTransferLedger.d.ts +58 -0
  274. package/build/services/asg/galleryTransferLedger.d.ts.map +1 -0
  275. package/build/services/asg/galleryTransferLedger.js +225 -0
  276. package/build/services/asg/galleryTransferLedger.js.map +1 -0
  277. package/build/services/asg/localNetworkTransport.d.ts +15 -0
  278. package/build/services/asg/localNetworkTransport.d.ts.map +1 -0
  279. package/build/services/asg/localNetworkTransport.js +144 -0
  280. package/build/services/asg/localNetworkTransport.js.map +1 -0
  281. package/build/services/asg/localStorageService.d.ts +18 -0
  282. package/build/services/asg/localStorageService.d.ts.map +1 -1
  283. package/build/services/asg/localStorageService.js +168 -19
  284. package/build/services/asg/localStorageService.js.map +1 -1
  285. package/build/services/asg/mediaProcessingQueue.d.ts +10 -0
  286. package/build/services/asg/mediaProcessingQueue.d.ts.map +1 -1
  287. package/build/services/asg/mediaProcessingQueue.js +193 -62
  288. package/build/services/asg/mediaProcessingQueue.js.map +1 -1
  289. package/build/services/audioPlaybackAssets.d.ts +8 -0
  290. package/build/services/audioPlaybackAssets.d.ts.map +1 -0
  291. package/build/services/audioPlaybackAssets.js +7 -0
  292. package/build/services/audioPlaybackAssets.js.map +1 -0
  293. package/build/services/gallerySyncClock.js +1 -1
  294. package/build/services/gallerySyncClock.js.map +1 -1
  295. package/build/services/glassesClockSync.d.ts.map +1 -1
  296. package/build/services/glassesClockSync.js +6 -2
  297. package/build/services/glassesClockSync.js.map +1 -1
  298. package/build/services/manifestActions.d.ts +7 -0
  299. package/build/services/manifestActions.d.ts.map +1 -0
  300. package/build/services/manifestActions.js +25 -0
  301. package/build/services/manifestActions.js.map +1 -0
  302. package/build/services/otaDisplayState.d.ts +23 -12
  303. package/build/services/otaDisplayState.d.ts.map +1 -1
  304. package/build/services/otaDisplayState.js +36 -14
  305. package/build/services/otaDisplayState.js.map +1 -1
  306. package/build/services/otaInstallPolicy.d.ts +16 -4
  307. package/build/services/otaInstallPolicy.d.ts.map +1 -1
  308. package/build/services/otaInstallPolicy.js +24 -3
  309. package/build/services/otaInstallPolicy.js.map +1 -1
  310. package/build/services/otaLegacyMapping.d.ts +1 -1
  311. package/build/services/otaLegacyMapping.d.ts.map +1 -1
  312. package/build/services/otaLegacyMapping.js.map +1 -1
  313. package/build/services/otaManifestPolicy.d.ts +14 -0
  314. package/build/services/otaManifestPolicy.d.ts.map +1 -0
  315. package/build/services/otaManifestPolicy.js +19 -0
  316. package/build/services/otaManifestPolicy.js.map +1 -0
  317. package/build/services/otaManifestUrl.d.ts +3 -0
  318. package/build/services/otaManifestUrl.d.ts.map +1 -0
  319. package/build/services/otaManifestUrl.js +38 -0
  320. package/build/services/otaManifestUrl.js.map +1 -0
  321. package/build/services/slimStreamStatus.d.ts +11 -0
  322. package/build/services/slimStreamStatus.d.ts.map +1 -1
  323. package/build/services/slimStreamStatus.js +14 -4
  324. package/build/services/slimStreamStatus.js.map +1 -1
  325. package/build/stores/apps.d.ts.map +1 -1
  326. package/build/stores/apps.js +11 -0
  327. package/build/stores/apps.js.map +1 -1
  328. package/build/stores/bluetoothSettingKeys.d.ts.map +1 -1
  329. package/build/stores/bluetoothSettingKeys.js +2 -0
  330. package/build/stores/bluetoothSettingKeys.js.map +1 -1
  331. package/build/stores/gallerySync.d.ts +2 -0
  332. package/build/stores/gallerySync.d.ts.map +1 -1
  333. package/build/stores/gallerySync.js +2 -0
  334. package/build/stores/gallerySync.js.map +1 -1
  335. package/build/stores/glasses.d.ts.map +1 -1
  336. package/build/stores/glasses.js +3 -0
  337. package/build/stores/glasses.js.map +1 -1
  338. package/build/stores/settings.d.ts +17 -0
  339. package/build/stores/settings.d.ts.map +1 -1
  340. package/build/stores/settings.js +157 -17
  341. package/build/stores/settings.js.map +1 -1
  342. package/build/types/applet.d.ts +2 -0
  343. package/build/types/applet.d.ts.map +1 -1
  344. package/build/types/applet.js.map +1 -1
  345. package/build/types/asg.d.ts +7 -0
  346. package/build/types/asg.d.ts.map +1 -1
  347. package/build/types/asg.js.map +1 -1
  348. package/build/types/enums.d.ts +2 -25
  349. package/build/types/enums.d.ts.map +1 -1
  350. package/build/types/enums.js +2 -27
  351. package/build/types/enums.js.map +1 -1
  352. package/build/types/hardware.d.ts +4 -13
  353. package/build/types/hardware.d.ts.map +1 -1
  354. package/build/types/hardware.js +15 -3
  355. package/build/types/hardware.js.map +1 -1
  356. package/build/types/index.d.ts +2 -6
  357. package/build/types/index.d.ts.map +1 -1
  358. package/build/types/index.js +2 -6
  359. package/build/types/index.js.map +1 -1
  360. package/build/utils/configuredDevHost.d.ts +6 -0
  361. package/build/utils/configuredDevHost.d.ts.map +1 -0
  362. package/build/utils/configuredDevHost.js +19 -0
  363. package/build/utils/configuredDevHost.js.map +1 -0
  364. package/build/utils/devMiniappLaunch.d.ts +19 -8
  365. package/build/utils/devMiniappLaunch.d.ts.map +1 -1
  366. package/build/utils/devMiniappLaunch.js +144 -21
  367. package/build/utils/devMiniappLaunch.js.map +1 -1
  368. package/build/utils/diagnosticContext.d.ts.map +1 -1
  369. package/build/utils/diagnosticContext.js +15 -17
  370. package/build/utils/diagnosticContext.js.map +1 -1
  371. package/build/utils/hardware/hardware.d.ts.map +1 -1
  372. package/build/utils/hardware/hardware.js +7 -3
  373. package/build/utils/hardware/hardware.js.map +1 -1
  374. package/build/utils/miniappDiagnostics.d.ts +64 -0
  375. package/build/utils/miniappDiagnostics.d.ts.map +1 -0
  376. package/build/utils/miniappDiagnostics.js +173 -0
  377. package/build/utils/miniappDiagnostics.js.map +1 -0
  378. package/build/utils/permissions/MediaLibraryPermissions.d.ts +11 -0
  379. package/build/utils/permissions/MediaLibraryPermissions.d.ts.map +1 -1
  380. package/build/utils/permissions/MediaLibraryPermissions.js +27 -4
  381. package/build/utils/permissions/MediaLibraryPermissions.js.map +1 -1
  382. package/build/utils/timers/timers.d.ts.map +1 -1
  383. package/build/utils/timers/timers.js +55 -18
  384. package/build/utils/timers/timers.js.map +1 -1
  385. package/package.json +59 -31
  386. package/src/assets/silence.wav +0 -0
  387. package/src/bluetooth-sdk/debug.ts +1 -0
  388. package/src/bluetooth-sdk/index.ts +2 -0
  389. package/src/bluetooth-sdk/photo-receiver.ts +2 -0
  390. package/src/bluetooth-sdk/react.ts +1 -0
  391. package/src/bluetooth-sdk/types.ts +1 -0
  392. package/src/engine.ts +9 -4
  393. package/src/facades/dev.ts +17 -12
  394. package/src/facades/display.ts +1 -1
  395. package/src/facades/gallery.ts +1 -1
  396. package/src/facades/glasses.ts +20 -7
  397. package/src/facades/glassesSettings.ts +5 -0
  398. package/src/facades/miniapps.ts +7 -0
  399. package/src/facades/ota.ts +23 -8
  400. package/src/facades/pairing.ts +15 -11
  401. package/src/facades/permissions.ts +14 -0
  402. package/src/facades/phoneNotifications.ts +4 -13
  403. package/src/facades/speech.ts +21 -7
  404. package/src/generated/releaseMetadata.ts +20 -0
  405. package/src/index.ts +39 -13
  406. package/src/react/MentraLiveOtaFlow.tsx +856 -0
  407. package/src/react/index.ts +7 -0
  408. package/src/react/useEngineSnapshot.ts +16 -0
  409. package/src/runtime/bootstrap.ts +33 -1
  410. package/src/runtime/scanQrSeam.ts +20 -0
  411. package/src/services/AppRegistry.ts +240 -149
  412. package/src/services/AudioCloudUplink.ts +23 -1
  413. package/src/services/AudioPlaybackService.ts +287 -38
  414. package/src/services/BlobStore.ts +22 -9
  415. package/src/services/CloudAudioSubscriptionSync.ts +13 -1
  416. package/src/services/CloudClientService.ts +96 -1
  417. package/src/services/DeviceEventRouter.ts +5 -5
  418. package/src/services/ForegroundLocationPermission.ts +24 -0
  419. package/src/services/GlassesSettingsSync.ts +9 -3
  420. package/src/services/GlassesStatusProjection.ts +16 -8
  421. package/src/services/HotspotOtaTransport.ts +184 -0
  422. package/src/services/HotspotShutdown.ts +41 -0
  423. package/src/services/LocalDisplayManager.ts +112 -21
  424. package/src/services/LocalMiniappRuntime.ts +967 -346
  425. package/src/services/LocalMiniappStorage.ts +82 -0
  426. package/src/services/LocalMiniappUserIdentity.ts +46 -0
  427. package/src/services/LocalSttFallbackCoordinator.ts +19 -12
  428. package/src/services/MicStateCoordinator.ts +169 -4
  429. package/src/services/MiniappLauncher.ts +30 -3
  430. package/src/services/MiniappLiveness.ts +24 -0
  431. package/src/services/NativeHttpResponse.ts +6 -0
  432. package/src/services/OtaArtifactDownloader.ts +312 -0
  433. package/src/services/OtaAutoChain.ts +106 -0
  434. package/src/services/OtaErrorMapping.ts +80 -0
  435. package/src/services/OtaInstallCoordinator.ts +649 -144
  436. package/src/services/OtaService.ts +11 -5
  437. package/src/services/OtaUpdateCheckService.ts +181 -21
  438. package/src/services/PhoneCalendarHelpers.ts +212 -0
  439. package/src/services/PhoneCalendarService.ts +65 -0
  440. package/src/services/PhoneCameraFovCoordinator.ts +210 -0
  441. package/src/services/PhoneNotificationsSync.ts +12 -10
  442. package/src/services/PhonePhotoCoordinator.ts +116 -18
  443. package/src/services/PhoneStreamCoordinator.ts +139 -25
  444. package/src/services/PhoneVideoCoordinator.ts +11 -0
  445. package/src/services/SceneRenderer.ts +16 -0
  446. package/src/services/SentenceTtsPipeline.ts +106 -0
  447. package/src/services/SupportProfileSync.ts +218 -0
  448. package/src/services/TranscriptionRouting.ts +37 -0
  449. package/src/services/TtsTextSanitizer.ts +66 -0
  450. package/src/services/WifiAdbRequest.ts +53 -0
  451. package/src/services/asg/asgCameraApi.ts +615 -33
  452. package/src/services/asg/cameraRollExportCoordinator.ts +627 -0
  453. package/src/services/asg/cameraRollExportLedger.ts +122 -0
  454. package/src/services/asg/galleryNotices.ts +1 -0
  455. package/src/services/asg/galleryPathMigration.ts +22 -0
  456. package/src/services/asg/gallerySettingsService.ts +3 -0
  457. package/src/services/asg/gallerySyncService.ts +184 -73
  458. package/src/services/asg/galleryTransferLedger.ts +312 -0
  459. package/src/services/asg/localNetworkTransport.ts +169 -0
  460. package/src/services/asg/localStorageService.ts +179 -24
  461. package/src/services/asg/mediaProcessingQueue.ts +209 -62
  462. package/src/services/audioPlaybackAssets.ts +8 -0
  463. package/src/services/gallerySyncClock.ts +1 -1
  464. package/src/services/glassesClockSync.ts +6 -2
  465. package/src/services/manifestActions.ts +30 -0
  466. package/src/services/otaDisplayState.ts +58 -17
  467. package/src/services/otaInstallPolicy.ts +30 -4
  468. package/src/services/otaLegacyMapping.ts +1 -1
  469. package/src/services/otaManifestPolicy.ts +42 -0
  470. package/src/services/otaManifestUrl.ts +44 -0
  471. package/src/services/slimStreamStatus.ts +16 -5
  472. package/src/stores/apps.ts +12 -0
  473. package/src/stores/bluetoothSettingKeys.ts +2 -0
  474. package/src/stores/gallerySync.ts +4 -0
  475. package/src/stores/glasses.ts +3 -0
  476. package/src/stores/settings.ts +179 -18
  477. package/src/types/applet.ts +2 -0
  478. package/src/types/asg.ts +7 -0
  479. package/src/types/enums.ts +3 -28
  480. package/src/types/hardware.ts +20 -13
  481. package/src/types/index.ts +2 -6
  482. package/src/utils/configuredDevHost.ts +17 -0
  483. package/src/utils/devMiniappLaunch.ts +151 -23
  484. package/src/utils/diagnosticContext.ts +17 -17
  485. package/src/utils/hardware/hardware.ts +7 -9
  486. package/src/utils/miniappDiagnostics.ts +226 -0
  487. package/src/utils/permissions/MediaLibraryPermissions.ts +35 -4
  488. package/src/utils/timers/timers.ts +57 -21
  489. package/build/devtools.d.ts +0 -11
  490. package/build/devtools.d.ts.map +0 -1
  491. package/build/devtools.js +0 -13
  492. package/build/devtools.js.map +0 -1
  493. package/build/internal.d.ts +0 -66
  494. package/build/internal.d.ts.map +0 -1
  495. package/build/internal.js +0 -89
  496. package/build/internal.js.map +0 -1
  497. package/build/services/asgOtaVersionUrl.d.ts +0 -2
  498. package/build/services/asgOtaVersionUrl.d.ts.map +0 -1
  499. package/build/services/asgOtaVersionUrl.js +0 -36
  500. package/build/services/asgOtaVersionUrl.js.map +0 -1
  501. package/src/devtools.ts +0 -13
  502. package/src/internal.ts +0 -158
  503. package/src/services/asgOtaVersionUrl.ts +0 -41
@@ -4,7 +4,7 @@
4
4
  * glasses display for dev tools and escape-hatch use (normal rendering goes through
5
5
  * the engine DisplayProcessor / layout system, not these).
6
6
  */
7
- import BluetoothSdk from "@mentra/bluetooth-sdk/internal";
7
+ import BluetoothSdk from "@mentra/bluetooth-sdk";
8
8
  export declare const display: {
9
9
  /** Mirrored-view read-model (current/onMirror/view/setView). */
10
10
  mirror: {
@@ -1 +1 @@
1
- {"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../../src/facades/display.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,YAAY,MAAM,gCAAgC,CAAA;AAGzD,eAAO,MAAM,OAAO;IAClB,gEAAgE;;;;;;;IAEhE,wEAAwE;;IAExE,iCAAiC;iBACtB,OAAO,CAAC,IAAI,CAAC;CACzB,CAAA"}
1
+ {"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../../src/facades/display.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,YAAY,MAAM,uBAAuB,CAAA;AAGhD,eAAO,MAAM,OAAO;IAClB,gEAAgE;;;;;;;IAEhE,wEAAwE;;IAExE,iCAAiC;iBACtB,OAAO,CAAC,IAAI,CAAC;CACzB,CAAA"}
@@ -4,7 +4,7 @@
4
4
  * glasses display for dev tools and escape-hatch use (normal rendering goes through
5
5
  * the engine DisplayProcessor / layout system, not these).
6
6
  */
7
- import BluetoothSdk from "@mentra/bluetooth-sdk/internal";
7
+ import BluetoothSdk from "@mentra/bluetooth-sdk";
8
8
  import { displayMirror } from "./displayMirror";
9
9
  export const display = {
10
10
  /** Mirrored-view read-model (current/onMirror/view/setView). */
@@ -1 +1 @@
1
- {"version":3,"file":"display.js","sourceRoot":"","sources":["../../src/facades/display.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,YAAY,MAAM,gCAAgC,CAAA;AACzD,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAE7C,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,gEAAgE;IAChE,MAAM,EAAE,aAAa;IACrB,wEAAwE;IACxE,IAAI,EAAE,CAAC,GAAG,IAAiD,EAAE,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;IACjG,iCAAiC;IACjC,KAAK,EAAE,GAAkB,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE;CACxD,CAAA","sourcesContent":["/**\n * display facade — `engine.display`: the host/OEM display surface. `mirror`\n * exposes the mirrored-view read-model; `text`/`clear` are raw passthroughs to the\n * glasses display for dev tools and escape-hatch use (normal rendering goes through\n * the engine DisplayProcessor / layout system, not these).\n */\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport {displayMirror} from \"./displayMirror\"\n\nexport const display = {\n /** Mirrored-view read-model (current/onMirror/view/setView). */\n mirror: displayMirror,\n /** Write raw text to the glasses display at (x, y) with a font size. */\n text: (...args: Parameters<typeof BluetoothSdk.displayText>) => BluetoothSdk.displayText(...args),\n /** Clear the glasses display. */\n clear: (): Promise<void> => BluetoothSdk.clearDisplay(),\n}\n"]}
1
+ {"version":3,"file":"display.js","sourceRoot":"","sources":["../../src/facades/display.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,YAAY,MAAM,uBAAuB,CAAA;AAChD,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAE7C,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,gEAAgE;IAChE,MAAM,EAAE,aAAa;IACrB,wEAAwE;IACxE,IAAI,EAAE,CAAC,GAAG,IAAiD,EAAE,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;IACjG,iCAAiC;IACjC,KAAK,EAAE,GAAkB,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE;CACxD,CAAA","sourcesContent":["/**\n * display facade — `engine.display`: the host/OEM display surface. `mirror`\n * exposes the mirrored-view read-model; `text`/`clear` are raw passthroughs to the\n * glasses display for dev tools and escape-hatch use (normal rendering goes through\n * the engine DisplayProcessor / layout system, not these).\n */\nimport BluetoothSdk from \"@mentra/bluetooth-sdk\"\nimport {displayMirror} from \"./displayMirror\"\n\nexport const display = {\n /** Mirrored-view read-model (current/onMirror/view/setView). */\n mirror: displayMirror,\n /** Write raw text to the glasses display at (x, y) with a font size. */\n text: (...args: Parameters<typeof BluetoothSdk.displayText>) => BluetoothSdk.displayText(...args),\n /** Clear the glasses display. */\n clear: (): Promise<void> => BluetoothSdk.clearDisplay(),\n}\n"]}
@@ -16,7 +16,7 @@ function projectStatus() {
16
16
  processingFiles: Array.from(progress.processingFiles),
17
17
  processedFiles: s.processedFiles,
18
18
  isSyncing: selectIssyncing(s),
19
- isStarting: gallerySyncService.isSyncStarting(),
19
+ isStarting: s.syncStarting,
20
20
  glassesGallery: selectGlassesGalleryStatus(s),
21
21
  // Copy: the snapshot must not hand callers a mutable reference into the store
22
22
  // (each queue item is copied too — callers must not mutate them in place).
@@ -1 +1 @@
1
- {"version":3,"file":"gallery.js","sourceRoot":"","sources":["../../src/facades/gallery.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,0BAA0B,GAC3B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAC,kBAAkB,EAAC,MAAM,oCAAoC,CAAA;AACrE,OAAO,EAAC,eAAe,EAAqB,MAAM,gCAAgC,CAAA;AAElF,SAAS,aAAa;IACpB,MAAM,CAAC,GAAG,mBAAmB,CAAC,QAAQ,EAAE,CAAA;IACxC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAA;IACtC,OAAO;QACL,GAAG,QAAQ;QACX,eAAe,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC;QACrD,cAAc,EAAE,CAAC,CAAC,cAAc;QAChC,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC;QAC7B,UAAU,EAAE,kBAAkB,CAAC,cAAc,EAAE;QAC/C,cAAc,EAAE,0BAA0B,CAAC,CAAC,CAAC;QAC7C,8EAA8E;QAC9E,2EAA2E;QAC3E,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAC,GAAG,IAAI,EAAC,CAAC,CAAC;QACzC,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM;QAC3B,UAAU,EAAE,CAAC,CAAC,UAAU;KACzB,CAAA;AACH,CAAC;AAID,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,qDAAqD;IACrD,MAAM,EAAE,GAAsB,EAAE,CAAC,aAAa,EAAE;IAChD;;;6BAGyB;IACzB,QAAQ,EAAE,CAAC,EAAuC,EAAgB,EAAE;QAClE,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAA;QAC1C,OAAO,mBAAmB,CAAC,SAAS,CAAC,GAAG,EAAE;YACxC,MAAM,MAAM,GAAG,aAAa,EAAE,CAAA;YAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;YACzC,IAAI,UAAU,KAAK,IAAI;gBAAE,OAAM;YAC/B,IAAI,GAAG,UAAU,CAAA;YACjB,EAAE,CAAC,MAAM,CAAC,CAAA;QACZ,CAAC,CAAC,CAAA;IACJ,CAAC;IACD,wFAAwF;IACxF,QAAQ,EAAE,CAAC,EAAmC,EAAgB,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC;IAEpF,4EAA4E;IAC5E,IAAI,EAAE,GAAkB,EAAE,CAAC,kBAAkB,CAAC,SAAS,EAAE;IACzD,kCAAkC;IAClC,MAAM,EAAE,GAAkB,EAAE,CAAC,kBAAkB,CAAC,UAAU,EAAE;IAC5D,2DAA2D;IAC3D,aAAa,EAAE,GAAkB,EAAE,CAAC,kBAAkB,CAAC,yBAAyB,EAAE;IAClF,gGAAgG;IAChG,oBAAoB,EAAE,CAAC,SAAmB,EAAQ,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC;IACnH,qFAAqF;IACrF,UAAU,EAAE,GAAS,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE;IACnE,oFAAoF;IACpF,yBAAyB,EAAE,GAAS,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC,yBAAyB,EAAE;CAClG,CAAA","sourcesContent":["/**\n * gallery facade — `engine.gallery`: the OEM-facing gallery-sync surface. Engine's\n * gallerySyncService orchestrates the sync (hotspot → wifi → HTTP fetch → process →\n * store); this facade exposes the projected status + the structured notices the host\n * renders its own UI from, plus the sync/cancel actions. No host-injected UI — the host\n * owns all alerts/navigation/i18n (it renders them off `onNotice`).\n */\nimport {\n useGallerySyncStore,\n selectSyncProgress,\n selectIssyncing,\n selectGlassesGalleryStatus,\n} from \"../stores/gallerySync\"\nimport {gallerySyncService} from \"../services/asg/gallerySyncService\"\nimport {onGalleryNotice, type GalleryNotice} from \"../services/asg/galleryNotices\"\n\nfunction projectStatus() {\n const s = useGallerySyncStore.getState()\n const progress = selectSyncProgress(s)\n return {\n ...progress,\n processingFiles: Array.from(progress.processingFiles),\n processedFiles: s.processedFiles,\n isSyncing: selectIssyncing(s),\n isStarting: gallerySyncService.isSyncStarting(),\n glassesGallery: selectGlassesGalleryStatus(s),\n // Copy: the snapshot must not hand callers a mutable reference into the store\n // (each queue item is copied too — callers must not mutate them in place).\n queue: s.queue.map((item) => ({...item})),\n queueLength: s.queue.length,\n queueIndex: s.queueIndex,\n }\n}\n\nexport type GallerySyncStatus = ReturnType<typeof projectStatus>\n\nexport const gallery = {\n /** Snapshot of the current sync state + progress. */\n status: (): GallerySyncStatus => projectStatus(),\n /** Subscribe to sync-state changes; returns an unsubscribe. Deduped on the projected\n * status (the gallerySync store mutates many unrelated fields during a sync), so the\n * host only re-renders when the projection actually changes — matches the other\n * read-model facades. */\n onStatus: (cb: (status: GallerySyncStatus) => void): (() => void) => {\n let last = JSON.stringify(projectStatus())\n return useGallerySyncStore.subscribe(() => {\n const status = projectStatus()\n const serialized = JSON.stringify(status)\n if (serialized === last) return\n last = serialized\n cb(status)\n })\n },\n /** Subscribe to user-actionable notices (host renders alerts / settings deep-links). */\n onNotice: (cb: (notice: GalleryNotice) => void): (() => void) => onGalleryNotice(cb),\n\n /** Start a gallery sync (the host gates connectivity/permissions first). */\n sync: (): Promise<void> => gallerySyncService.startSync(),\n /** Cancel an in-progress sync. */\n cancel: (): Promise<void> => gallerySyncService.cancelSync(),\n /** Ask glasses to refresh their gallery summary counts. */\n refreshStatus: (): Promise<void> => gallerySyncService.queryGlassesGalleryStatus(),\n /** Remove local files from the current gallery queue after host-owned deletion UI completes. */\n removeFilesFromQueue: (fileNames: string[]): void => useGallerySyncStore.getState().removeFilesFromQueue(fileNames),\n /** Clear the current gallery sync queue after host-owned bulk deletion completes. */\n clearQueue: (): void => useGallerySyncStore.getState().clearQueue(),\n /** Clear the cached glasses gallery summary when product UI observes disconnect. */\n clearGlassesGalleryStatus: (): void => useGallerySyncStore.getState().clearGlassesGalleryStatus(),\n}\n"]}
1
+ {"version":3,"file":"gallery.js","sourceRoot":"","sources":["../../src/facades/gallery.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,0BAA0B,GAC3B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAC,kBAAkB,EAAC,MAAM,oCAAoC,CAAA;AACrE,OAAO,EAAC,eAAe,EAAqB,MAAM,gCAAgC,CAAA;AAElF,SAAS,aAAa;IACpB,MAAM,CAAC,GAAG,mBAAmB,CAAC,QAAQ,EAAE,CAAA;IACxC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAA;IACtC,OAAO;QACL,GAAG,QAAQ;QACX,eAAe,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC;QACrD,cAAc,EAAE,CAAC,CAAC,cAAc;QAChC,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC;QAC7B,UAAU,EAAE,CAAC,CAAC,YAAY;QAC1B,cAAc,EAAE,0BAA0B,CAAC,CAAC,CAAC;QAC7C,8EAA8E;QAC9E,2EAA2E;QAC3E,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAC,GAAG,IAAI,EAAC,CAAC,CAAC;QACzC,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM;QAC3B,UAAU,EAAE,CAAC,CAAC,UAAU;KACzB,CAAA;AACH,CAAC;AAID,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,qDAAqD;IACrD,MAAM,EAAE,GAAsB,EAAE,CAAC,aAAa,EAAE;IAChD;;;6BAGyB;IACzB,QAAQ,EAAE,CAAC,EAAuC,EAAgB,EAAE;QAClE,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAA;QAC1C,OAAO,mBAAmB,CAAC,SAAS,CAAC,GAAG,EAAE;YACxC,MAAM,MAAM,GAAG,aAAa,EAAE,CAAA;YAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;YACzC,IAAI,UAAU,KAAK,IAAI;gBAAE,OAAM;YAC/B,IAAI,GAAG,UAAU,CAAA;YACjB,EAAE,CAAC,MAAM,CAAC,CAAA;QACZ,CAAC,CAAC,CAAA;IACJ,CAAC;IACD,wFAAwF;IACxF,QAAQ,EAAE,CAAC,EAAmC,EAAgB,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC;IAEpF,4EAA4E;IAC5E,IAAI,EAAE,GAAkB,EAAE,CAAC,kBAAkB,CAAC,SAAS,EAAE;IACzD,kCAAkC;IAClC,MAAM,EAAE,GAAkB,EAAE,CAAC,kBAAkB,CAAC,UAAU,EAAE;IAC5D,2DAA2D;IAC3D,aAAa,EAAE,GAAkB,EAAE,CAAC,kBAAkB,CAAC,yBAAyB,EAAE;IAClF,gGAAgG;IAChG,oBAAoB,EAAE,CAAC,SAAmB,EAAQ,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC;IACnH,qFAAqF;IACrF,UAAU,EAAE,GAAS,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE;IACnE,oFAAoF;IACpF,yBAAyB,EAAE,GAAS,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC,yBAAyB,EAAE;CAClG,CAAA","sourcesContent":["/**\n * gallery facade — `engine.gallery`: the OEM-facing gallery-sync surface. Engine's\n * gallerySyncService orchestrates the sync (hotspot → wifi → HTTP fetch → process →\n * store); this facade exposes the projected status + the structured notices the host\n * renders its own UI from, plus the sync/cancel actions. No host-injected UI — the host\n * owns all alerts/navigation/i18n (it renders them off `onNotice`).\n */\nimport {\n useGallerySyncStore,\n selectSyncProgress,\n selectIssyncing,\n selectGlassesGalleryStatus,\n} from \"../stores/gallerySync\"\nimport {gallerySyncService} from \"../services/asg/gallerySyncService\"\nimport {onGalleryNotice, type GalleryNotice} from \"../services/asg/galleryNotices\"\n\nfunction projectStatus() {\n const s = useGallerySyncStore.getState()\n const progress = selectSyncProgress(s)\n return {\n ...progress,\n processingFiles: Array.from(progress.processingFiles),\n processedFiles: s.processedFiles,\n isSyncing: selectIssyncing(s),\n isStarting: s.syncStarting,\n glassesGallery: selectGlassesGalleryStatus(s),\n // Copy: the snapshot must not hand callers a mutable reference into the store\n // (each queue item is copied too — callers must not mutate them in place).\n queue: s.queue.map((item) => ({...item})),\n queueLength: s.queue.length,\n queueIndex: s.queueIndex,\n }\n}\n\nexport type GallerySyncStatus = ReturnType<typeof projectStatus>\n\nexport const gallery = {\n /** Snapshot of the current sync state + progress. */\n status: (): GallerySyncStatus => projectStatus(),\n /** Subscribe to sync-state changes; returns an unsubscribe. Deduped on the projected\n * status (the gallerySync store mutates many unrelated fields during a sync), so the\n * host only re-renders when the projection actually changes — matches the other\n * read-model facades. */\n onStatus: (cb: (status: GallerySyncStatus) => void): (() => void) => {\n let last = JSON.stringify(projectStatus())\n return useGallerySyncStore.subscribe(() => {\n const status = projectStatus()\n const serialized = JSON.stringify(status)\n if (serialized === last) return\n last = serialized\n cb(status)\n })\n },\n /** Subscribe to user-actionable notices (host renders alerts / settings deep-links). */\n onNotice: (cb: (notice: GalleryNotice) => void): (() => void) => onGalleryNotice(cb),\n\n /** Start a gallery sync (the host gates connectivity/permissions first). */\n sync: (): Promise<void> => gallerySyncService.startSync(),\n /** Cancel an in-progress sync. */\n cancel: (): Promise<void> => gallerySyncService.cancelSync(),\n /** Ask glasses to refresh their gallery summary counts. */\n refreshStatus: (): Promise<void> => gallerySyncService.queryGlassesGalleryStatus(),\n /** Remove local files from the current gallery queue after host-owned deletion UI completes. */\n removeFilesFromQueue: (fileNames: string[]): void => useGallerySyncStore.getState().removeFilesFromQueue(fileNames),\n /** Clear the current gallery sync queue after host-owned bulk deletion completes. */\n clearQueue: (): void => useGallerySyncStore.getState().clearQueue(),\n /** Clear the cached glasses gallery summary when product UI observes disconnect. */\n clearGlassesGalleryStatus: (): void => useGallerySyncStore.getState().clearGlassesGalleryStatus(),\n}\n"]}
@@ -1,14 +1,4 @@
1
- /**
2
- * glasses facade — the core `engine.glasses.*` surface: connection actions (over
3
- * the bluetooth-sdk passthrough), a curated status/info read-model (projected from
4
- * the engine-owned glasses store), capabilities (from the model table), and the
5
- * discrete input events. The `wifi` sub-facade is nested here.
6
- *
7
- * Read-models project the raw glasses store into the stable shape OEM UIs consume,
8
- * so the device store's field layout doesn't leak into every screen.
9
- */
10
- import BluetoothSdk from "@mentra/bluetooth-sdk/internal";
11
- import type { ButtonPressEvent, TouchEvent } from "@mentra/bluetooth-sdk/internal";
1
+ import type { ButtonPressEvent, ConnectOptions, Device, TouchEvent } from "@mentra/bluetooth-sdk";
12
2
  declare function projectStatus(): {
13
3
  state: "connecting" | "connected" | "disconnected" | "scanning" | "bonding";
14
4
  fullyBooted: boolean;
@@ -44,6 +34,7 @@ declare function projectInfo(): {
44
34
  serialNumber: string;
45
35
  buildNumber: string;
46
36
  btMac: string;
37
+ wifiMac: string;
47
38
  leftMac: string;
48
39
  rightMac: string;
49
40
  wifi: {
@@ -67,11 +58,11 @@ export declare const glasses: {
67
58
  disconnect: () => Promise<void>;
68
59
  forget: () => Promise<void>;
69
60
  /** Connect to a specific (discovered) device. */
70
- connect: (device: import("@mentra/bluetooth-sdk").Device, options?: import("@mentra/bluetooth-sdk").ConnectOptions | undefined) => Promise<void>;
61
+ connect: (device: Device, options?: ConnectOptions) => Promise<void>;
71
62
  /** Connect the built-in simulated glasses (dev/testing). */
72
63
  connectSimulated: () => Promise<void>;
73
64
  /** Set a device as the `connectDefault()` target. */
74
- setDefault: (device: import("@mentra/bluetooth-sdk").Device | null) => Promise<void>;
65
+ setDefault: (device: Device | null) => Promise<void>;
75
66
  /**
76
67
  * Reconnect to the saved default glasses. Resolves `false` when there's nothing to
77
68
  * reconnect to (no default paired) or the connect attempt fails (e.g. BLE powered
@@ -1 +1 @@
1
- {"version":3,"file":"glasses.d.ts","sourceRoot":"","sources":["../../src/facades/glasses.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,YAAY,MAAM,gCAAgC,CAAA;AACzD,OAAO,KAAK,EAAC,gBAAgB,EAAE,UAAU,EAAC,MAAM,gCAAgC,CAAA;AAWhF,iBAAS,aAAa;;;;;;;;;;;;;;;EAarB;AAED,iBAAS,uBAAuB;;;;;EAQ/B;AAED,iBAAS,WAAW;;;;;;;;;;;;;;;;;;;;;;EAoBnB;AAED,MAAM,MAAM,qBAAqB,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAA;AACpE,MAAM,MAAM,wBAAwB,GAAG,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAA;AACjF,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;AAEhE,eAAO,MAAM,OAAO;IAElB;;;;OAIG;0BACuB,OAAO,CAAC,IAAI,CAAC;sBAIvB,OAAO,CAAC,IAAI,CAAC;kBACjB,OAAO,CAAC,IAAI,CAAC;IACzB,iDAAiD;uIACkB,OAAO,CAAC,IAAI,CAAC;IAIhF,4DAA4D;4BACtC,OAAO,CAAC,IAAI,CAAC;IACnC,qDAAqD;;IAErD;;;;;;OAMG;qBACkB,OAAO,CAAC,OAAO,CAAC;IAarC;;;iEAG6D;0BACzC,OAAO;IAC3B;;;;;;;;;;OAUG;4BACmB,OAAO,CAAC,OAAO,CAAC;kBAG1B,qBAAqB;mBAClB,CAAC,MAAM,EAAE,qBAAqB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;gBAY3D,mBAAmB;iBAChB,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;;IAW/D,iFAAiF;;wBAI7D,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;yBAI/C,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;;8BAOzC,OAAO,CAAC,IAAI,CAAC;0BACjB,OAAO,CAAC,IAAI,CAAC;sBACjB,OAAO,CAAC,IAAI,CAAC;sBACb,wBAAwB;uBACrB,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;;;QAcxE,8CAA8C;;QAE9C,qCAAqC;gCACb,MAAM;QAC9B,6EAA6E;oCACjD,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;CAMtD,CAAA"}
1
+ {"version":3,"file":"glasses.d.ts","sourceRoot":"","sources":["../../src/facades/glasses.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,gBAAgB,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,EAAC,MAAM,uBAAuB,CAAA;AAY/F,iBAAS,aAAa;;;;;;;;;;;;;;;EAarB;AAED,iBAAS,uBAAuB;;;;;EAQ/B;AAED,iBAAS,WAAW;;;;;;;;;;;;;;;;;;;;;;;EAqBnB;AAED,MAAM,MAAM,qBAAqB,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAA;AACpE,MAAM,MAAM,wBAAwB,GAAG,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAA;AACjF,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;AAEhE,eAAO,MAAM,OAAO;IAElB;;;;OAIG;0BACuB,OAAO,CAAC,IAAI,CAAC;sBASvB,OAAO,CAAC,IAAI,CAAC;kBACjB,OAAO,CAAC,IAAI,CAAC;IACzB,iDAAiD;sBACzB,MAAM,YAAY,cAAc,KAAG,OAAO,CAAC,IAAI,CAAC;IASxE,4DAA4D;4BACtC,OAAO,CAAC,IAAI,CAAC;IACnC,qDAAqD;yBAChC,MAAM,GAAG,IAAI,KAAG,OAAO,CAAC,IAAI,CAAC;IAClD;;;;;;OAMG;qBACkB,OAAO,CAAC,OAAO,CAAC;IAcrC;;;iEAG6D;0BACzC,OAAO;IAC3B;;;;;;;;;;OAUG;4BACmB,OAAO,CAAC,OAAO,CAAC;kBAG1B,qBAAqB;mBAClB,CAAC,MAAM,EAAE,qBAAqB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;gBAY3D,mBAAmB;iBAChB,CAAC,IAAI,EAAE,mBAAmB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;;IAW/D,iFAAiF;;wBAI7D,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;yBAI/C,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;;8BAOzC,OAAO,CAAC,IAAI,CAAC;0BACjB,OAAO,CAAC,IAAI,CAAC;sBACjB,OAAO,CAAC,IAAI,CAAC;sBACb,wBAAwB;uBACrB,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;;;QAcxE,8CAA8C;;QAE9C,qCAAqC;gCACb,MAAM;QAC9B,6EAA6E;oCACjD,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;CAMtD,CAAA"}
@@ -17,6 +17,7 @@ import { hasDefaultDevice } from "../services/DeviceStoreHydration";
17
17
  import { projectPairingIdentity } from "../services/PairingIdentity";
18
18
  import { isGlassesConnected, isGlassesReady } from "../services/GlassesReadiness";
19
19
  import { pushAllBluetoothSettings } from "../services/GlassesSettingsSync";
20
+ import { recordSupportProfileConnectionFailure } from "../services/SupportProfileSync";
20
21
  import { getModelCapabilities } from "../types";
21
22
  import { glassesWifi } from "./glassesWifi";
22
23
  import { glassesSettings } from "./glassesSettings";
@@ -58,6 +59,7 @@ function projectInfo() {
58
59
  serialNumber: s.serialNumber,
59
60
  buildNumber: s.buildNumber,
60
61
  btMac: s.bluetoothMacAddress,
62
+ wifiMac: s.wifiMacAddress,
61
63
  leftMac: s.leftMacAddress,
62
64
  rightMac: s.rightMacAddress,
63
65
  // Copy: the snapshot must not hand callers a mutable reference into the store.
@@ -72,20 +74,32 @@ export const glasses = {
72
74
  * the glasses (this used to be a host-side step before `connectDefault`).
73
75
  */
74
76
  connectDefault: async () => {
75
- await pushAllBluetoothSettings();
76
- return BluetoothSdk.connectDefault();
77
+ try {
78
+ await pushAllBluetoothSettings();
79
+ await BluetoothSdk.connectDefault();
80
+ }
81
+ catch (error) {
82
+ recordSupportProfileConnectionFailure(error, "connect_default");
83
+ throw error;
84
+ }
77
85
  },
78
86
  disconnect: () => BluetoothSdk.disconnect(),
79
87
  forget: () => BluetoothSdk.forget(),
80
88
  /** Connect to a specific (discovered) device. */
81
- connect: async (...args) => {
82
- await pushAllBluetoothSettings();
83
- return BluetoothSdk.connect(...args);
89
+ connect: async (device, options) => {
90
+ try {
91
+ await pushAllBluetoothSettings();
92
+ await BluetoothSdk.connect(device, options);
93
+ }
94
+ catch (error) {
95
+ recordSupportProfileConnectionFailure(error, "connect");
96
+ throw error;
97
+ }
84
98
  },
85
99
  /** Connect the built-in simulated glasses (dev/testing). */
86
100
  connectSimulated: () => BluetoothSdk.connectSimulated(),
87
101
  /** Set a device as the `connectDefault()` target. */
88
- setDefault: (...args) => BluetoothSdk.setDefaultDevice(...args),
102
+ setDefault: (device) => BluetoothSdk.setDefaultDevice(device),
89
103
  /**
90
104
  * Reconnect to the saved default glasses. Resolves `false` when there's nothing to
91
105
  * reconnect to (no default paired) or the connect attempt fails (e.g. BLE powered
@@ -104,6 +118,7 @@ export const glasses = {
104
118
  await BluetoothSdk.connectDefault();
105
119
  }
106
120
  catch (error) {
121
+ recordSupportProfileConnectionFailure(error, "reconnect");
107
122
  console.warn("engine.glasses.reconnect failed:", error);
108
123
  return false;
109
124
  }
@@ -1 +1 @@
1
- {"version":3,"file":"glasses.js","sourceRoot":"","sources":["../../src/facades/glasses.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * glasses facade — the core `engine.glasses.*` surface: connection actions (over\n * the bluetooth-sdk passthrough), a curated status/info read-model (projected from\n * the engine-owned glasses store), capabilities (from the model table), and the\n * discrete input events. The `wifi` sub-facade is nested here.\n *\n * Read-models project the raw glasses store into the stable shape OEM UIs consume,\n * so the device store's field layout doesn't leak into every screen.\n */\n// Internal btsdk surface — connectSimulated/reconnect/controller live on the full\n// surface, not the public entry. Relative path (the alias doesn't resolve in engine's\n// standalone build); jest moduleNameMapper + tsconfig both resolve it.\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport type {ButtonPressEvent, TouchEvent} from \"@mentra/bluetooth-sdk/internal\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore, SETTINGS} from \"../stores/settings\"\nimport {hasDefaultDevice} from \"../services/DeviceStoreHydration\"\nimport {projectPairingIdentity} from \"../services/PairingIdentity\"\nimport {isGlassesConnected, isGlassesReady} from \"../services/GlassesReadiness\"\nimport {pushAllBluetoothSettings} from \"../services/GlassesSettingsSync\"\nimport {getModelCapabilities, type DeviceTypes} from \"../types\"\nimport {glassesWifi} from \"./glassesWifi\"\nimport {glassesSettings} from \"./glassesSettings\"\n\nfunction projectStatus() {\n const s = useGlassesStore.getState()\n return {\n state: s.connection.state,\n fullyBooted: isGlassesReady(s.connection),\n battery: s.batteryLevel,\n charging: s.charging,\n case: {battery: s.caseBatteryLevel, charging: s.caseCharging, open: s.caseOpen, removed: s.caseRemoved},\n signal: s.signalStrength,\n micEnabled: s.micEnabled,\n vadEnabled: s.voiceActivityDetectionEnabled,\n btClassic: s.bluetoothClassicConnected,\n }\n}\n\nfunction projectControllerStatus() {\n const s = useGlassesStore.getState()\n return {\n connected: s.controllerConnected,\n fullyBooted: s.controllerFullyBooted,\n battery: s.controllerBatteryLevel,\n signal: s.controllerSignalStrength,\n }\n}\n\nfunction projectInfo() {\n const s = useGlassesStore.getState()\n return {\n model: s.deviceModel,\n style: s.style,\n color: s.color,\n bluetoothName: s.bluetoothName,\n firmwareVersion: s.firmwareVersion,\n mtkFirmware: s.mtkFirmwareVersion,\n besFirmware: s.besFirmwareVersion,\n appVersion: s.appVersion,\n androidVersion: s.androidVersion,\n serialNumber: s.serialNumber,\n buildNumber: s.buildNumber,\n btMac: s.bluetoothMacAddress,\n leftMac: s.leftMacAddress,\n rightMac: s.rightMacAddress,\n // Copy: the snapshot must not hand callers a mutable reference into the store.\n wifi: {...s.wifi},\n }\n}\n\nexport type GlassesStatusSnapshot = ReturnType<typeof projectStatus>\nexport type ControllerStatusSnapshot = ReturnType<typeof projectControllerStatus>\nexport type GlassesInfoSnapshot = ReturnType<typeof projectInfo>\n\nexport const glasses = {\n // --- connection (bluetooth-sdk passthrough) ---\n /**\n * Reconnect the default wearable. Seeds the phone's current device settings to\n * native first, so they're primed before the connect handshake replays them to\n * the glasses (this used to be a host-side step before `connectDefault`).\n */\n connectDefault: async (): Promise<void> => {\n await pushAllBluetoothSettings()\n return BluetoothSdk.connectDefault()\n },\n disconnect: (): Promise<void> => BluetoothSdk.disconnect(),\n forget: (): Promise<void> => BluetoothSdk.forget(),\n /** Connect to a specific (discovered) device. */\n connect: async (...args: Parameters<typeof BluetoothSdk.connect>): Promise<void> => {\n await pushAllBluetoothSettings()\n return BluetoothSdk.connect(...args)\n },\n /** Connect the built-in simulated glasses (dev/testing). */\n connectSimulated: (): Promise<void> => BluetoothSdk.connectSimulated(),\n /** Set a device as the `connectDefault()` target. */\n setDefault: (...args: Parameters<typeof BluetoothSdk.setDefaultDevice>) => BluetoothSdk.setDefaultDevice(...args),\n /**\n * Reconnect to the saved default glasses. Resolves `false` when there's nothing to\n * reconnect to (no default paired) or the connect attempt fails (e.g. BLE powered\n * off), `true` when already connected or after kicking off the connect. Never\n * rejects — the boolean contract holds. The host gates connectivity/permissions\n * (its UI) before calling.\n */\n reconnect: async (): Promise<boolean> => {\n const defaultWearable = useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key)\n if (!defaultWearable) return false\n if (isGlassesConnected(useGlassesStore.getState().connection)) return true\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connectDefault()\n } catch (error) {\n console.warn(\"engine.glasses.reconnect failed:\", error)\n return false\n }\n return true\n },\n /** True when no glasses has ever been paired NOR selected (the pairing-identity\n * lifecycle is in its `none` state) — e.g. to route a first-run host into the\n * pairing/onboarding flow. A pending selection is not \"first\" — the host should\n * offer finish-pairing (see `engine.pairing.identity()`). */\n isFirstPairing: (): boolean => projectPairingIdentity().kind === \"none\",\n /**\n * True when the SDK has an actual default DEVICE to reconnect to. Distinct from\n * `default_wearable` (a model string that a pending or orphaned selection can\n * hold without any paired device): connectDefault() throws without a device, so\n * hosts should route to the pairing flow when this is false.\n *\n * Hydration-aware: awaits the device-store seed internally, so a cold-start\n * read can't see a false \"absent\" for genuinely-paired users. Rejects if\n * hydration failed — callers guarding destructive or routing decisions must\n * fail open (treat as \"has a device\").\n */\n hasDefaultDevice: (): Promise<boolean> => hasDefaultDevice(),\n\n // --- read-model (projected from the engine-owned glasses store) ---\n status: (): GlassesStatusSnapshot => projectStatus(),\n onStatus: (cb: (status: GlassesStatusSnapshot) => void): (() => void) => {\n // Dedupe: the glasses store updates on many fields; only fire when the\n // projected status snapshot actually changes.\n let last = JSON.stringify(projectStatus())\n return useGlassesStore.subscribe(() => {\n const snap = projectStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n info: (): GlassesInfoSnapshot => projectInfo(),\n onInfo: (cb: (info: GlassesInfoSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectInfo())\n return useGlassesStore.subscribe(() => {\n const snap = projectInfo()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n capabilities: () => getModelCapabilities(useGlassesStore.getState().deviceModel as DeviceTypes),\n /** Ask the glasses to report fresh firmware/version info (updates the store). */\n requestVersionInfo: () => BluetoothSdk.requestVersionInfo(),\n\n // --- discrete input events (passthrough listeners) ---\n onButtonPress: (cb: (event: ButtonPressEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"button_press\", cb)\n return () => sub.remove()\n },\n onTouchGesture: (cb: (event: TouchEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"touch_event\", cb)\n return () => sub.remove()\n },\n\n // --- ring controller (optional input device) ---\n controller: {\n connectDefault: (): Promise<void> => BluetoothSdk.connectDefaultController(),\n disconnect: (): Promise<void> => BluetoothSdk.disconnectController(),\n forget: (): Promise<void> => BluetoothSdk.forgetController(),\n status: (): ControllerStatusSnapshot => projectControllerStatus(),\n onStatus: (cb: (status: ControllerStatusSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectControllerStatus())\n return useGlassesStore.subscribe(() => {\n const snap = projectControllerStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n },\n\n // --- audio (glasses media-volume + own-app playback hint) ---\n audio: {\n /** Read the glasses' current media volume. */\n getMediaVolume: () => BluetoothSdk.getGlassesMediaVolume(),\n /** Set the glasses' media volume. */\n setMediaVolume: (level: number) => BluetoothSdk.setGlassesMediaVolume(level),\n /** Tell native whether THIS app is currently playing audio (for ducking). */\n setOwnAppPlaying: (playing: boolean): Promise<void> => BluetoothSdk.setOwnAppAudioPlaying(playing),\n },\n\n // --- sub-facades ---\n wifi: glassesWifi,\n settings: glassesSettings,\n}\n"]}
1
+ {"version":3,"file":"glasses.js","sourceRoot":"","sources":["../../src/facades/glasses.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * glasses facade — the core `engine.glasses.*` surface: connection actions (over\n * the bluetooth-sdk passthrough), a curated status/info read-model (projected from\n * the engine-owned glasses store), capabilities (from the model table), and the\n * discrete input events. The `wifi` sub-facade is nested here.\n *\n * Read-models project the raw glasses store into the stable shape OEM UIs consume,\n * so the device store's field layout doesn't leak into every screen.\n */\n// Internal btsdk surface — connectSimulated/reconnect/controller live on the full\n// surface, not the public entry. Relative path (the alias doesn't resolve in engine's\n// standalone build); jest moduleNameMapper + tsconfig both resolve it.\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport type {ButtonPressEvent, ConnectOptions, Device, TouchEvent} from \"@mentra/bluetooth-sdk\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore, SETTINGS} from \"../stores/settings\"\nimport {hasDefaultDevice} from \"../services/DeviceStoreHydration\"\nimport {projectPairingIdentity} from \"../services/PairingIdentity\"\nimport {isGlassesConnected, isGlassesReady} from \"../services/GlassesReadiness\"\nimport {pushAllBluetoothSettings} from \"../services/GlassesSettingsSync\"\nimport {recordSupportProfileConnectionFailure} from \"../services/SupportProfileSync\"\nimport {getModelCapabilities, type DeviceTypes} from \"../types\"\nimport {glassesWifi} from \"./glassesWifi\"\nimport {glassesSettings} from \"./glassesSettings\"\n\nfunction projectStatus() {\n const s = useGlassesStore.getState()\n return {\n state: s.connection.state,\n fullyBooted: isGlassesReady(s.connection),\n battery: s.batteryLevel,\n charging: s.charging,\n case: {battery: s.caseBatteryLevel, charging: s.caseCharging, open: s.caseOpen, removed: s.caseRemoved},\n signal: s.signalStrength,\n micEnabled: s.micEnabled,\n vadEnabled: s.voiceActivityDetectionEnabled,\n btClassic: s.bluetoothClassicConnected,\n }\n}\n\nfunction projectControllerStatus() {\n const s = useGlassesStore.getState()\n return {\n connected: s.controllerConnected,\n fullyBooted: s.controllerFullyBooted,\n battery: s.controllerBatteryLevel,\n signal: s.controllerSignalStrength,\n }\n}\n\nfunction projectInfo() {\n const s = useGlassesStore.getState()\n return {\n model: s.deviceModel,\n style: s.style,\n color: s.color,\n bluetoothName: s.bluetoothName,\n firmwareVersion: s.firmwareVersion,\n mtkFirmware: s.mtkFirmwareVersion,\n besFirmware: s.besFirmwareVersion,\n appVersion: s.appVersion,\n androidVersion: s.androidVersion,\n serialNumber: s.serialNumber,\n buildNumber: s.buildNumber,\n btMac: s.bluetoothMacAddress,\n wifiMac: s.wifiMacAddress,\n leftMac: s.leftMacAddress,\n rightMac: s.rightMacAddress,\n // Copy: the snapshot must not hand callers a mutable reference into the store.\n wifi: {...s.wifi},\n }\n}\n\nexport type GlassesStatusSnapshot = ReturnType<typeof projectStatus>\nexport type ControllerStatusSnapshot = ReturnType<typeof projectControllerStatus>\nexport type GlassesInfoSnapshot = ReturnType<typeof projectInfo>\n\nexport const glasses = {\n // --- connection (bluetooth-sdk passthrough) ---\n /**\n * Reconnect the default wearable. Seeds the phone's current device settings to\n * native first, so they're primed before the connect handshake replays them to\n * the glasses (this used to be a host-side step before `connectDefault`).\n */\n connectDefault: async (): Promise<void> => {\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connectDefault()\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"connect_default\")\n throw error\n }\n },\n disconnect: (): Promise<void> => BluetoothSdk.disconnect(),\n forget: (): Promise<void> => BluetoothSdk.forget(),\n /** Connect to a specific (discovered) device. */\n connect: async (device: Device, options?: ConnectOptions): Promise<void> => {\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connect(device, options)\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"connect\")\n throw error\n }\n },\n /** Connect the built-in simulated glasses (dev/testing). */\n connectSimulated: (): Promise<void> => BluetoothSdk.connectSimulated(),\n /** Set a device as the `connectDefault()` target. */\n setDefault: (device: Device | null): Promise<void> => BluetoothSdk.setDefaultDevice(device),\n /**\n * Reconnect to the saved default glasses. Resolves `false` when there's nothing to\n * reconnect to (no default paired) or the connect attempt fails (e.g. BLE powered\n * off), `true` when already connected or after kicking off the connect. Never\n * rejects — the boolean contract holds. The host gates connectivity/permissions\n * (its UI) before calling.\n */\n reconnect: async (): Promise<boolean> => {\n const defaultWearable = useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key)\n if (!defaultWearable) return false\n if (isGlassesConnected(useGlassesStore.getState().connection)) return true\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connectDefault()\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"reconnect\")\n console.warn(\"engine.glasses.reconnect failed:\", error)\n return false\n }\n return true\n },\n /** True when no glasses has ever been paired NOR selected (the pairing-identity\n * lifecycle is in its `none` state) — e.g. to route a first-run host into the\n * pairing/onboarding flow. A pending selection is not \"first\" — the host should\n * offer finish-pairing (see `engine.pairing.identity()`). */\n isFirstPairing: (): boolean => projectPairingIdentity().kind === \"none\",\n /**\n * True when the SDK has an actual default DEVICE to reconnect to. Distinct from\n * `default_wearable` (a model string that a pending or orphaned selection can\n * hold without any paired device): connectDefault() throws without a device, so\n * hosts should route to the pairing flow when this is false.\n *\n * Hydration-aware: awaits the device-store seed internally, so a cold-start\n * read can't see a false \"absent\" for genuinely-paired users. Rejects if\n * hydration failed — callers guarding destructive or routing decisions must\n * fail open (treat as \"has a device\").\n */\n hasDefaultDevice: (): Promise<boolean> => hasDefaultDevice(),\n\n // --- read-model (projected from the engine-owned glasses store) ---\n status: (): GlassesStatusSnapshot => projectStatus(),\n onStatus: (cb: (status: GlassesStatusSnapshot) => void): (() => void) => {\n // Dedupe: the glasses store updates on many fields; only fire when the\n // projected status snapshot actually changes.\n let last = JSON.stringify(projectStatus())\n return useGlassesStore.subscribe(() => {\n const snap = projectStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n info: (): GlassesInfoSnapshot => projectInfo(),\n onInfo: (cb: (info: GlassesInfoSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectInfo())\n return useGlassesStore.subscribe(() => {\n const snap = projectInfo()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n capabilities: () => getModelCapabilities(useGlassesStore.getState().deviceModel as DeviceTypes),\n /** Ask the glasses to report fresh firmware/version info (updates the store). */\n requestVersionInfo: () => BluetoothSdk.requestVersionInfo(),\n\n // --- discrete input events (passthrough listeners) ---\n onButtonPress: (cb: (event: ButtonPressEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"button_press\", cb)\n return () => sub.remove()\n },\n onTouchGesture: (cb: (event: TouchEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"touch_event\", cb)\n return () => sub.remove()\n },\n\n // --- ring controller (optional input device) ---\n controller: {\n connectDefault: (): Promise<void> => BluetoothSdk.connectDefaultController(),\n disconnect: (): Promise<void> => BluetoothSdk.disconnectController(),\n forget: (): Promise<void> => BluetoothSdk.forgetController(),\n status: (): ControllerStatusSnapshot => projectControllerStatus(),\n onStatus: (cb: (status: ControllerStatusSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectControllerStatus())\n return useGlassesStore.subscribe(() => {\n const snap = projectControllerStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n },\n\n // --- audio (glasses media-volume + own-app playback hint) ---\n audio: {\n /** Read the glasses' current media volume. */\n getMediaVolume: () => BluetoothSdk.getGlassesMediaVolume(),\n /** Set the glasses' media volume. */\n setMediaVolume: (level: number) => BluetoothSdk.setGlassesMediaVolume(level),\n /** Tell native whether THIS app is currently playing audio (for ducking). */\n setOwnAppPlaying: (playing: boolean): Promise<void> => BluetoothSdk.setOwnAppAudioPlaying(playing),\n },\n\n // --- sub-facades ---\n wifi: glassesWifi,\n settings: glassesSettings,\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"glassesSettings.d.ts","sourceRoot":"","sources":["../../src/facades/glassesSettings.ts"],"names":[],"mappings":"AAyCA,eAAO,MAAM,eAAe;IAC1B,6EAA6E;UACvE,CAAC,iBAAiB,MAAM,KAAG,CAAC,GAAG,SAAS;IAE9C,iFAAiF;UAC3E,CAAC,iBAAiB,MAAM,SAAS,CAAC;IACxC,+EAA+E;gBACnE,CAAC,iBAAiB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAEvF,+EAA+E;sBAC7D,MAAM;IACxB,mFAAmF;qBAEpE,MAAM,EAAE;CACxB,CAAA"}
1
+ {"version":3,"file":"glassesSettings.d.ts","sourceRoot":"","sources":["../../src/facades/glassesSettings.ts"],"names":[],"mappings":"AA0CA,eAAO,MAAM,eAAe;IAC1B,6EAA6E;UACvE,CAAC,iBAAiB,MAAM,KAAG,CAAC,GAAG,SAAS;IAE9C,iFAAiF;UAC3E,CAAC,iBAAiB,MAAM,SAAS,CAAC;IACxC,+EAA+E;gBACnE,CAAC,iBAAiB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,GAAG,SAAS,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAEvF,+EAA+E;sBAC7D,MAAM;IACxB,mFAAmF;qBAEpE,MAAM,EAAE;CACxB,CAAA"}
@@ -21,6 +21,7 @@ const INTERNAL_KEYS = new Set([
21
21
  SETTINGS.default_wearable.key,
22
22
  SETTINGS.device_name.key,
23
23
  SETTINGS.device_address.key,
24
+ SETTINGS.project_name.key,
24
25
  SETTINGS.pending_controller.key,
25
26
  SETTINGS.default_controller.key,
26
27
  SETTINGS.controller_device_name.key,
@@ -1 +1 @@
1
- {"version":3,"file":"glassesSettings.js","sourceRoot":"","sources":["../../src/facades/glassesSettings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAC,gBAAgB,EAAE,QAAQ,EAAE,sBAAsB,EAAC,MAAM,oBAAoB,CAAA;AAErF,+EAA+E;AAC/E,iFAAiF;AACjF,4EAA4E;AAC5E,MAAM,aAAa,GAAG,IAAI,GAAG,CAAS;IACpC,OAAO;IACP,QAAQ,CAAC,UAAU,CAAC,GAAG;IACvB,QAAQ,CAAC,UAAU,CAAC,GAAG;IACvB,mEAAmE;IACnE,QAAQ,CAAC,gBAAgB,CAAC,GAAG;IAC7B,QAAQ,CAAC,gBAAgB,CAAC,GAAG;IAC7B,QAAQ,CAAC,WAAW,CAAC,GAAG;IACxB,QAAQ,CAAC,cAAc,CAAC,GAAG;IAC3B,QAAQ,CAAC,kBAAkB,CAAC,GAAG;IAC/B,QAAQ,CAAC,kBAAkB,CAAC,GAAG;IAC/B,QAAQ,CAAC,sBAAsB,CAAC,GAAG;IACnC,QAAQ,CAAC,kBAAkB,CAAC,GAAG;IAC/B,yBAAyB;IACzB,QAAQ,CAAC,yBAAyB,CAAC,GAAG;CACvC,CAAC,CAAA;AACF,MAAM,WAAW,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AAE/E,+EAA+E;AAC/E,wEAAwE;AACxE,SAAS,gBAAgB,CAAI,KAAQ;IACnC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,GAAG,KAAK,CAAM,CAAA;IAChD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAC,GAAI,KAAgB,EAAM,CAAA;IAC1E,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,6EAA6E;IAC7E,GAAG,EAAE,CAAc,GAAW,EAAiB,EAAE,CAC/C,gBAAgB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,GAAG,CAAkB,CAAC;IAChF,iFAAiF;IACjF,GAAG,EAAE,CAAc,GAAW,EAAE,KAAQ,EAAE,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC;IAC/F,+EAA+E;IAC/E,SAAS,EAAE,CAAc,GAAW,EAAE,EAAkC,EAAgB,EAAE,CACxF,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAkB,EAAE,EAAE,CAAC;IAC3E,+EAA+E;IAC/E,UAAU,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;IAC1C,mFAAmF;IACnF,sEAAsE;IACtE,SAAS,EAAE,GAAa,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC;CAC5C,CAAA","sourcesContent":["/**\n * glasses.settings facade — `engine.glasses.settings`: the keyed DEVICE-settings\n * surface (brightness, head-up angle, dashboard, camera/button, sensing, …). These\n * are the settings the engine store auto-syncs to the glasses over the bluetooth-sdk\n * (`BLUETOOTH_SETTING_KEYS`), so `set()` both persists and pushes to the device.\n *\n * Distinct from `engine.settings` (user/app prefs): this is scoped to the\n * hardware-facing keys, minus the internal sync keys (auth/token) that aren't\n * user-tunable device settings.\n */\nimport {useSettingsStore, SETTINGS, BLUETOOTH_SETTING_KEYS} from \"../stores/settings\"\n\n// Keys carried on BLUETOOTH_SETTING_KEYS for the device handshake that are NOT\n// user-tunable settings — auth, device/controller IDENTITY (set by pairing), and\n// internal RUNTIME flags. Kept out of the OEM-facing `available()` surface.\nconst INTERNAL_KEYS = new Set<string>([\n // auth\n SETTINGS.core_token.key,\n SETTINGS.auth_email.key,\n // glasses + controller identity (managed by pairing, not the user)\n SETTINGS.pending_wearable.key,\n SETTINGS.default_wearable.key,\n SETTINGS.device_name.key,\n SETTINGS.device_address.key,\n SETTINGS.pending_controller.key,\n SETTINGS.default_controller.key,\n SETTINGS.controller_device_name.key,\n SETTINGS.controller_address.key,\n // internal runtime flags\n SETTINGS.local_stt_fallback_active.key,\n])\nconst DEVICE_KEYS = BLUETOOTH_SETTING_KEYS.filter((k) => !INTERNAL_KEYS.has(k))\n\n// Copy: object/array-valued settings must not hand callers a mutable reference\n// into the store (mutations would bypass persistence + Bluetooth sync).\nfunction copySettingValue<T>(value: T): T {\n if (Array.isArray(value)) return [...value] as T\n if (value && typeof value === \"object\") return {...(value as object)} as T\n return value\n}\n\nexport const glassesSettings = {\n /** Read a device setting by key (object/array values are shallow copies). */\n get: <T = unknown>(key: string): T | undefined =>\n copySettingValue(useSettingsStore.getState().getSetting(key) as T | undefined),\n /** Write a device setting — persists and auto-syncs to the connected glasses. */\n set: <T = unknown>(key: string, value: T) => useSettingsStore.getState().setSetting(key, value),\n /** Subscribe to changes for one device-setting key; returns an unsubscribe. */\n onChanged: <T = unknown>(key: string, cb: (value: T | undefined) => void): (() => void) =>\n useSettingsStore.subscribe((s) => s.getSetting(key) as T | undefined, cb),\n /** The schema descriptor for a key (type, default, options…), or undefined. */\n descriptor: (key: string) => SETTINGS[key],\n /** The device-setting keys synced to the glasses (excludes internal sync keys). */\n // Copy: callers must not be able to mutate the module-level key list.\n available: (): string[] => [...DEVICE_KEYS],\n}\n"]}
1
+ {"version":3,"file":"glassesSettings.js","sourceRoot":"","sources":["../../src/facades/glassesSettings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAC,gBAAgB,EAAE,QAAQ,EAAE,sBAAsB,EAAC,MAAM,oBAAoB,CAAA;AAErF,+EAA+E;AAC/E,iFAAiF;AACjF,4EAA4E;AAC5E,MAAM,aAAa,GAAG,IAAI,GAAG,CAAS;IACpC,OAAO;IACP,QAAQ,CAAC,UAAU,CAAC,GAAG;IACvB,QAAQ,CAAC,UAAU,CAAC,GAAG;IACvB,mEAAmE;IACnE,QAAQ,CAAC,gBAAgB,CAAC,GAAG;IAC7B,QAAQ,CAAC,gBAAgB,CAAC,GAAG;IAC7B,QAAQ,CAAC,WAAW,CAAC,GAAG;IACxB,QAAQ,CAAC,cAAc,CAAC,GAAG;IAC3B,QAAQ,CAAC,YAAY,CAAC,GAAG;IACzB,QAAQ,CAAC,kBAAkB,CAAC,GAAG;IAC/B,QAAQ,CAAC,kBAAkB,CAAC,GAAG;IAC/B,QAAQ,CAAC,sBAAsB,CAAC,GAAG;IACnC,QAAQ,CAAC,kBAAkB,CAAC,GAAG;IAC/B,yBAAyB;IACzB,QAAQ,CAAC,yBAAyB,CAAC,GAAG;CACvC,CAAC,CAAA;AACF,MAAM,WAAW,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AAE/E,+EAA+E;AAC/E,wEAAwE;AACxE,SAAS,gBAAgB,CAAI,KAAQ;IACnC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,GAAG,KAAK,CAAM,CAAA;IAChD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAC,GAAI,KAAgB,EAAM,CAAA;IAC1E,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,6EAA6E;IAC7E,GAAG,EAAE,CAAc,GAAW,EAAiB,EAAE,CAC/C,gBAAgB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,GAAG,CAAkB,CAAC;IAChF,iFAAiF;IACjF,GAAG,EAAE,CAAc,GAAW,EAAE,KAAQ,EAAE,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC;IAC/F,+EAA+E;IAC/E,SAAS,EAAE,CAAc,GAAW,EAAE,EAAkC,EAAgB,EAAE,CACxF,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAkB,EAAE,EAAE,CAAC;IAC3E,+EAA+E;IAC/E,UAAU,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;IAC1C,mFAAmF;IACnF,sEAAsE;IACtE,SAAS,EAAE,GAAa,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC;CAC5C,CAAA","sourcesContent":["/**\n * glasses.settings facade — `engine.glasses.settings`: the keyed DEVICE-settings\n * surface (brightness, head-up angle, dashboard, camera/button, sensing, …). These\n * are the settings the engine store auto-syncs to the glasses over the bluetooth-sdk\n * (`BLUETOOTH_SETTING_KEYS`), so `set()` both persists and pushes to the device.\n *\n * Distinct from `engine.settings` (user/app prefs): this is scoped to the\n * hardware-facing keys, minus the internal sync keys (auth/token) that aren't\n * user-tunable device settings.\n */\nimport {useSettingsStore, SETTINGS, BLUETOOTH_SETTING_KEYS} from \"../stores/settings\"\n\n// Keys carried on BLUETOOTH_SETTING_KEYS for the device handshake that are NOT\n// user-tunable settings — auth, device/controller IDENTITY (set by pairing), and\n// internal RUNTIME flags. Kept out of the OEM-facing `available()` surface.\nconst INTERNAL_KEYS = new Set<string>([\n // auth\n SETTINGS.core_token.key,\n SETTINGS.auth_email.key,\n // glasses + controller identity (managed by pairing, not the user)\n SETTINGS.pending_wearable.key,\n SETTINGS.default_wearable.key,\n SETTINGS.device_name.key,\n SETTINGS.device_address.key,\n SETTINGS.project_name.key,\n SETTINGS.pending_controller.key,\n SETTINGS.default_controller.key,\n SETTINGS.controller_device_name.key,\n SETTINGS.controller_address.key,\n // internal runtime flags\n SETTINGS.local_stt_fallback_active.key,\n])\nconst DEVICE_KEYS = BLUETOOTH_SETTING_KEYS.filter((k) => !INTERNAL_KEYS.has(k))\n\n// Copy: object/array-valued settings must not hand callers a mutable reference\n// into the store (mutations would bypass persistence + Bluetooth sync).\nfunction copySettingValue<T>(value: T): T {\n if (Array.isArray(value)) return [...value] as T\n if (value && typeof value === \"object\") return {...(value as object)} as T\n return value\n}\n\nexport const glassesSettings = {\n /** Read a device setting by key (object/array values are shallow copies). */\n get: <T = unknown>(key: string): T | undefined =>\n copySettingValue(useSettingsStore.getState().getSetting(key) as T | undefined),\n /** Write a device setting — persists and auto-syncs to the connected glasses. */\n set: <T = unknown>(key: string, value: T) => useSettingsStore.getState().setSetting(key, value),\n /** Subscribe to changes for one device-setting key; returns an unsubscribe. */\n onChanged: <T = unknown>(key: string, cb: (value: T | undefined) => void): (() => void) =>\n useSettingsStore.subscribe((s) => s.getSetting(key) as T | undefined, cb),\n /** The schema descriptor for a key (type, default, options…), or undefined. */\n descriptor: (key: string) => SETTINGS[key],\n /** The device-setting keys synced to the glasses (excludes internal sync keys). */\n // Copy: callers must not be able to mutate the module-level key list.\n available: (): string[] => [...DEVICE_KEYS],\n}\n\n\n\n\n"]}
@@ -16,6 +16,10 @@ export declare const miniapps: {
16
16
  list: () => ClientApp[];
17
17
  /** Subscribe to the installed-app set; fires only when it changes. Returns an unsubscribe. */
18
18
  onChanged: (cb: (apps: ClientApp[]) => void) => (() => void);
19
+ /** Miniapps actively subscribed to Mentra Live hardware-button events. */
20
+ buttonPressSubscribers: () => string[];
21
+ /** Observe the active Mentra Live hardware-button subscriber set. */
22
+ onButtonPressSubscribersChanged: (cb: (packageNames: string[]) => void) => (() => void);
19
23
  /** Re-fetch the installed-app list from the backend. */
20
24
  refresh: () => Promise<void>;
21
25
  /** Start (foreground) a miniapp. */
@@ -1 +1 @@
1
- {"version":3,"file":"miniapps.d.ts","sourceRoot":"","sources":["../../src/facades/miniapps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAC,iBAAiB,EAAC,MAAM,gBAAgB,CAAA;AAChD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,UAAU,CAAA;AAEvC,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,QAAQ,CAAC,CAAA;AAE9D,eAAO,MAAM,QAAQ;IACnB,yCAAyC;gBAE/B,SAAS,EAAE;IACrB,8FAA8F;oBAC9E,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAW1D,wDAAwD;;IAExD,oCAAoC;;IAEpC,sBAAsB;;IAEtB,iDAAiD;;IAGjD,4CAA4C;;IAE5C,iCAAiC;;IAEjC,2CAA2C;;;;IAE3C,2BAA2B;;IAE3B,2EAA2E;;IAG3E,gDAAgD;;CAGjD,CAAA"}
1
+ {"version":3,"file":"miniapps.d.ts","sourceRoot":"","sources":["../../src/facades/miniapps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAC,iBAAiB,EAAC,MAAM,gBAAgB,CAAA;AAEhD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,UAAU,CAAA;AAEvC,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,QAAQ,CAAC,CAAA;AAE9D,eAAO,MAAM,QAAQ;IACnB,yCAAyC;gBAE/B,SAAS,EAAE;IACrB,8FAA8F;oBAC9E,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAW1D,0EAA0E;kCAC9C,MAAM,EAAE;IACpC,qEAAqE;0CAC/B,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAGrF,wDAAwD;;IAExD,oCAAoC;;IAEpC,sBAAsB;;IAEtB,iDAAiD;;IAGjD,4CAA4C;;IAE5C,iCAAiC;;IAEjC,2CAA2C;;;;IAE3C,2BAA2B;;IAE3B,2EAA2E;;IAG3E,gDAAgD;;CAGjD,CAAA"}
@@ -9,6 +9,7 @@
9
9
  * `<WebView>` wired to them. This facade is the lifecycle half.
10
10
  */
11
11
  import { useAppStatusStore } from "../stores/apps";
12
+ import localMiniappRuntime from "../services/LocalMiniappRuntime";
12
13
  export const miniapps = {
13
14
  /** All installed miniapps (snapshot). */
14
15
  // Copy: the snapshot must not hand callers a mutable reference into the store.
@@ -25,6 +26,10 @@ export const miniapps = {
25
26
  cb(apps);
26
27
  });
27
28
  },
29
+ /** Miniapps actively subscribed to Mentra Live hardware-button events. */
30
+ buttonPressSubscribers: () => localMiniappRuntime.getButtonPressSubscribers(),
31
+ /** Observe the active Mentra Live hardware-button subscriber set. */
32
+ onButtonPressSubscribersChanged: (cb) => localMiniappRuntime.onButtonPressSubscribersChanged(cb),
28
33
  /** Re-fetch the installed-app list from the backend. */
29
34
  refresh: () => useAppStatusStore.getState().refresh(),
30
35
  /** Start (foreground) a miniapp. */
@@ -1 +1 @@
1
- {"version":3,"file":"miniapps.js","sourceRoot":"","sources":["../../src/facades/miniapps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAC,iBAAiB,EAAC,MAAM,gBAAgB,CAAA;AAKhD,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,yCAAyC;IACzC,+EAA+E;IAC/E,IAAI,EAAE,GAAgB,EAAE,CAAC,CAAC,GAAG,iBAAiB,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC;IAC/D,8FAA8F;IAC9F,SAAS,EAAE,CAAC,EAA+B,EAAgB,EAAE;QAC3D,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAA;QAC5D,OAAO,iBAAiB,CAAC,SAAS,CAAC,GAAG,EAAE;YACtC,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAA;YAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;YAChC,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAM;YACxB,IAAI,GAAG,GAAG,CAAA;YACV,EAAE,CAAC,IAAI,CAAC,CAAA;QACV,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,wDAAwD;IACxD,OAAO,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;IACrD,oCAAoC;IACpC,KAAK,EAAE,CAAC,GAAG,IAAoC,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAC/F,sBAAsB;IACtB,IAAI,EAAE,CAAC,GAAG,IAAmC,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC5F,iDAAiD;IACjD,aAAa,EAAE,CAAC,GAAG,IAA4C,EAAE,EAAE,CACjE,iBAAiB,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IACrD,4CAA4C;IAC5C,eAAe,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,eAAe,EAAE;IACrE,iCAAiC;IACjC,OAAO,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;IACrD,2CAA2C;IAC3C,OAAO,EAAE,CAAC,GAAG,IAAsC,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IACrG,2BAA2B;IAC3B,SAAS,EAAE,CAAC,GAAG,IAAwC,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC3G,2EAA2E;IAC3E,cAAc,EAAE,CAAC,GAAG,IAA6C,EAAE,EAAE,CACnE,iBAAiB,CAAC,QAAQ,EAAE,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC;IACtD,gDAAgD;IAChD,eAAe,EAAE,CAAC,GAAG,IAA8C,EAAE,EAAE,CACrE,iBAAiB,CAAC,QAAQ,EAAE,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC;CACxD,CAAA","sourcesContent":["/**\n * miniapps facade — `engine.miniapps`: miniapp lifecycle over the engine-owned\n * apps store. Thin forwarding (args via Parameters<>), so the facade never drifts\n * from the store's actions.\n *\n * The miniapp WebView is a HOST component (engine ships the bridge, not the view) —\n * the bridge primitives (`buildMiniappGlobalsScript`, `buildMentraUiShim`, the\n * MentraJS router) are exported from `@mentra/engine` directly; the host mounts a\n * `<WebView>` wired to them. This facade is the lifecycle half.\n */\nimport {useAppStatusStore} from \"../stores/apps\"\nimport type {ClientApp} from \"../types\"\n\ntype AppsState = ReturnType<typeof useAppStatusStore.getState>\n\nexport const miniapps = {\n /** All installed miniapps (snapshot). */\n // Copy: the snapshot must not hand callers a mutable reference into the store.\n list: (): ClientApp[] => [...useAppStatusStore.getState().apps],\n /** Subscribe to the installed-app set; fires only when it changes. Returns an unsubscribe. */\n onChanged: (cb: (apps: ClientApp[]) => void): (() => void) => {\n let last = JSON.stringify(useAppStatusStore.getState().apps)\n return useAppStatusStore.subscribe(() => {\n const apps = useAppStatusStore.getState().apps\n const key = JSON.stringify(apps)\n if (key === last) return\n last = key\n cb(apps)\n })\n },\n\n /** Re-fetch the installed-app list from the backend. */\n refresh: () => useAppStatusStore.getState().refresh(),\n /** Start (foreground) a miniapp. */\n start: (...args: Parameters<AppsState[\"start\"]>) => useAppStatusStore.getState().start(...args),\n /** Stop a miniapp. */\n stop: (...args: Parameters<AppsState[\"stop\"]>) => useAppStatusStore.getState().stop(...args),\n /** Bring a running miniapp to the foreground. */\n setForeground: (...args: Parameters<AppsState[\"setForeground\"]>) =>\n useAppStatusStore.getState().setForeground(...args),\n /** Clear the current foreground miniapp. */\n clearForeground: () => useAppStatusStore.getState().clearForeground(),\n /** Stop all running miniapps. */\n stopAll: () => useAppStatusStore.getState().stopAll(),\n /** Install a miniapp from a bundle URL. */\n install: (...args: Parameters<AppsState[\"install\"]>) => useAppStatusStore.getState().install(...args),\n /** Uninstall a miniapp. */\n uninstall: (...args: Parameters<AppsState[\"uninstall\"]>) => useAppStatusStore.getState().uninstall(...args),\n /** Persist a miniapp's captured screenshot (the switcher/card preview). */\n saveScreenshot: (...args: Parameters<AppsState[\"saveScreenshot\"]>) =>\n useAppStatusStore.getState().saveScreenshot(...args),\n /** Hide/show a miniapp on the home surfaces. */\n setHiddenStatus: (...args: Parameters<AppsState[\"setHiddenStatus\"]>) =>\n useAppStatusStore.getState().setHiddenStatus(...args),\n}\n"]}
1
+ {"version":3,"file":"miniapps.js","sourceRoot":"","sources":["../../src/facades/miniapps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAC,iBAAiB,EAAC,MAAM,gBAAgB,CAAA;AAChD,OAAO,mBAAmB,MAAM,iCAAiC,CAAA;AAKjE,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,yCAAyC;IACzC,+EAA+E;IAC/E,IAAI,EAAE,GAAgB,EAAE,CAAC,CAAC,GAAG,iBAAiB,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC;IAC/D,8FAA8F;IAC9F,SAAS,EAAE,CAAC,EAA+B,EAAgB,EAAE;QAC3D,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAA;QAC5D,OAAO,iBAAiB,CAAC,SAAS,CAAC,GAAG,EAAE;YACtC,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAA;YAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;YAChC,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAM;YACxB,IAAI,GAAG,GAAG,CAAA;YACV,EAAE,CAAC,IAAI,CAAC,CAAA;QACV,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,0EAA0E;IAC1E,sBAAsB,EAAE,GAAa,EAAE,CAAC,mBAAmB,CAAC,yBAAyB,EAAE;IACvF,qEAAqE;IACrE,+BAA+B,EAAE,CAAC,EAAoC,EAAgB,EAAE,CACtF,mBAAmB,CAAC,+BAA+B,CAAC,EAAE,CAAC;IAEzD,wDAAwD;IACxD,OAAO,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;IACrD,oCAAoC;IACpC,KAAK,EAAE,CAAC,GAAG,IAAoC,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAC/F,sBAAsB;IACtB,IAAI,EAAE,CAAC,GAAG,IAAmC,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC5F,iDAAiD;IACjD,aAAa,EAAE,CAAC,GAAG,IAA4C,EAAE,EAAE,CACjE,iBAAiB,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IACrD,4CAA4C;IAC5C,eAAe,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,eAAe,EAAE;IACrE,iCAAiC;IACjC,OAAO,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;IACrD,2CAA2C;IAC3C,OAAO,EAAE,CAAC,GAAG,IAAsC,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IACrG,2BAA2B;IAC3B,SAAS,EAAE,CAAC,GAAG,IAAwC,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC3G,2EAA2E;IAC3E,cAAc,EAAE,CAAC,GAAG,IAA6C,EAAE,EAAE,CACnE,iBAAiB,CAAC,QAAQ,EAAE,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC;IACtD,gDAAgD;IAChD,eAAe,EAAE,CAAC,GAAG,IAA8C,EAAE,EAAE,CACrE,iBAAiB,CAAC,QAAQ,EAAE,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC;CACxD,CAAA","sourcesContent":["/**\n * miniapps facade — `engine.miniapps`: miniapp lifecycle over the engine-owned\n * apps store. Thin forwarding (args via Parameters<>), so the facade never drifts\n * from the store's actions.\n *\n * The miniapp WebView is a HOST component (engine ships the bridge, not the view) —\n * the bridge primitives (`buildMiniappGlobalsScript`, `buildMentraUiShim`, the\n * MentraJS router) are exported from `@mentra/engine` directly; the host mounts a\n * `<WebView>` wired to them. This facade is the lifecycle half.\n */\nimport {useAppStatusStore} from \"../stores/apps\"\nimport localMiniappRuntime from \"../services/LocalMiniappRuntime\"\nimport type {ClientApp} from \"../types\"\n\ntype AppsState = ReturnType<typeof useAppStatusStore.getState>\n\nexport const miniapps = {\n /** All installed miniapps (snapshot). */\n // Copy: the snapshot must not hand callers a mutable reference into the store.\n list: (): ClientApp[] => [...useAppStatusStore.getState().apps],\n /** Subscribe to the installed-app set; fires only when it changes. Returns an unsubscribe. */\n onChanged: (cb: (apps: ClientApp[]) => void): (() => void) => {\n let last = JSON.stringify(useAppStatusStore.getState().apps)\n return useAppStatusStore.subscribe(() => {\n const apps = useAppStatusStore.getState().apps\n const key = JSON.stringify(apps)\n if (key === last) return\n last = key\n cb(apps)\n })\n },\n\n /** Miniapps actively subscribed to Mentra Live hardware-button events. */\n buttonPressSubscribers: (): string[] => localMiniappRuntime.getButtonPressSubscribers(),\n /** Observe the active Mentra Live hardware-button subscriber set. */\n onButtonPressSubscribersChanged: (cb: (packageNames: string[]) => void): (() => void) =>\n localMiniappRuntime.onButtonPressSubscribersChanged(cb),\n\n /** Re-fetch the installed-app list from the backend. */\n refresh: () => useAppStatusStore.getState().refresh(),\n /** Start (foreground) a miniapp. */\n start: (...args: Parameters<AppsState[\"start\"]>) => useAppStatusStore.getState().start(...args),\n /** Stop a miniapp. */\n stop: (...args: Parameters<AppsState[\"stop\"]>) => useAppStatusStore.getState().stop(...args),\n /** Bring a running miniapp to the foreground. */\n setForeground: (...args: Parameters<AppsState[\"setForeground\"]>) =>\n useAppStatusStore.getState().setForeground(...args),\n /** Clear the current foreground miniapp. */\n clearForeground: () => useAppStatusStore.getState().clearForeground(),\n /** Stop all running miniapps. */\n stopAll: () => useAppStatusStore.getState().stopAll(),\n /** Install a miniapp from a bundle URL. */\n install: (...args: Parameters<AppsState[\"install\"]>) => useAppStatusStore.getState().install(...args),\n /** Uninstall a miniapp. */\n uninstall: (...args: Parameters<AppsState[\"uninstall\"]>) => useAppStatusStore.getState().uninstall(...args),\n /** Persist a miniapp's captured screenshot (the switcher/card preview). */\n saveScreenshot: (...args: Parameters<AppsState[\"saveScreenshot\"]>) =>\n useAppStatusStore.getState().saveScreenshot(...args),\n /** Hide/show a miniapp on the home surfaces. */\n setHiddenStatus: (...args: Parameters<AppsState[\"setHiddenStatus\"]>) =>\n useAppStatusStore.getState().setHiddenStatus(...args),\n}\n"]}
@@ -1,15 +1,4 @@
1
- /**
2
- * ota facade — `engine.ota`: the OEM-facing OTA read/observe surface. Engine's
3
- * OtaService projects the glasses' OTA BLE events into the engine store; this facade
4
- * exposes the snapshot + change subscriptions the host renders its update prompt and
5
- * progress UI from. No host-injected UI — the host owns all alerts/navigation/i18n.
6
- *
7
- * Availability checks live in engine. Install orchestration lives in engine too:
8
- * `installSession` fronts the OtaInstallCoordinator state machine (WP 8B) — the host
9
- * progress screen is a pure renderer over its snapshot + attach/detach/retry/finish.
10
- */
11
- import BluetoothSdk from "@mentra/bluetooth-sdk/internal";
12
- import type { OtaProgress, OtaProgressStatus, OtaStatus, OtaUpdateInfo } from "@mentra/bluetooth-sdk/internal";
1
+ import type { OtaProgress, OtaProgressStatus, OtaStartAckEvent, OtaStatus, OtaUpdateInfo } from "@mentra/bluetooth-sdk";
13
2
  import { type OtaInstallSnapshot } from "../services/OtaInstallCoordinator";
14
3
  import { type OtaCheckCurrentGlassesOptions, type OtaCheckCurrentGlassesResult } from "../services/OtaUpdateCheckService";
15
4
  declare function projectSnapshot(): {
@@ -17,9 +6,10 @@ declare function projectSnapshot(): {
17
6
  buildNumber: string | null;
18
7
  mtkFirmwareVersion: string | null;
19
8
  besFirmwareVersion: string | null;
9
+ hotspotOtaVersion: number;
20
10
  wifiConnected: boolean;
21
11
  wifiStatusKnown: boolean;
22
- manifestUrl: string;
12
+ manifestUrl: string | null;
23
13
  updateAvailable: OtaUpdateInfo | null;
24
14
  status: OtaStatus | null;
25
15
  legacyProgress: OtaProgress | null;
@@ -29,13 +19,19 @@ declare function projectSnapshot(): {
29
19
  export type OtaSnapshot = ReturnType<typeof projectSnapshot>;
30
20
  export type { OtaProgress, OtaProgressStatus, OtaStatus, OtaUpdateInfo, OtaInstallSnapshot, OtaCheckCurrentGlassesOptions, OtaCheckCurrentGlassesResult, };
31
21
  export declare const ota: {
22
+ /**
23
+ * Start the device-status and OTA projections without starting the authenticated
24
+ * cloud/miniapp runtime. This is the explicit entry point for Bluetooth-only hosts.
25
+ * Idempotent and safe when the full engine runtime is already running.
26
+ */
27
+ initialize: () => Promise<void>;
32
28
  /**
33
29
  * Start the firmware install with the resolved OTA manifest URL. Progress lands on
34
- * `status()`/`onStatus()`. (The host resolves the manifest URL — dev-override/env/prod
35
- * resolution stays with the OTA config; the host-side stuck/retry watchdog is its own
30
+ * `status()`/`onStatus()`. (The host resolves the manifest URL — developer override,
31
+ * host pin, or Engine release pin resolution stays with the OTA config; the stuck/retry watchdog is its own
36
32
  * resilience layer on top of this command.)
37
33
  */
38
- install: (otaVersionUrl?: string | null | undefined) => Promise<import("@mentra/bluetooth-sdk").OtaStartAckEvent>;
34
+ install: (otaVersionUrl?: string | null) => Promise<OtaStartAckEvent>;
39
35
  /**
40
36
  * Keep glasses awake while an OTA session is actively progressing.
41
37
  * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.
@@ -72,6 +68,8 @@ export declare const ota: {
72
68
  * the snapshot; every watchdog/retry/reconnect rule lives in the coordinator.
73
69
  */
74
70
  installSession: {
71
+ /** Select Wi-Fi or capability-gated hotspot transport for this checked manifest. */
72
+ prepare: (result: OtaCheckCurrentGlassesResult) => "wifi" | "hotspot";
75
73
  /** Bind the machine to the mounted progress screen. Idempotent per attach/detach cycle. */
76
74
  attach: () => void;
77
75
  /** Unbind on unmount: clears all timers/listeners and resets session state. */
@@ -1 +1 @@
1
- {"version":3,"file":"ota.d.ts","sourceRoot":"","sources":["../../src/facades/ota.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,YAAY,MAAM,gCAAgC,CAAA;AACzD,OAAO,KAAK,EAAC,WAAW,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,EAAC,MAAM,gCAAgC,CAAA;AAG5G,OAAO,EAAwB,KAAK,kBAAkB,EAAC,MAAM,mCAAmC,CAAA;AAChG,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,4BAA4B,EAClC,MAAM,mCAAmC,CAAA;AAE1C,iBAAS,eAAe;;;;;;;;;;;;;EAgBvB;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAA;AAC5D,YAAY,EACV,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,aAAa,EACb,kBAAkB,EAClB,6BAA6B,EAC7B,4BAA4B,GAC7B,CAAA;AAED,eAAO,MAAM,GAAG;IAEd;;;;;OAKG;;IASH;;;OAGG;;IAEH,sGAAsG;gCAC1E,6BAA6B;IACzD,+CAA+C;;IAE/C,yEAAyE;;IAMzE;;;;;OAKG;4CACqC,aAAa,CAAC,SAAS,CAAC,KAAG,aAAa,GAAG,IAAI;IAQvF;;;;;OAKG;;IAKH;;;OAGG;yCACkC,OAAO;IAE5C;;;;OAIG;;QAED,2FAA2F;;QAE3F,+EAA+E;;QAE/E,+EAA+E;;QAE/E,2EAA2E;;QAE3E,uGAAuG;;QAEvG,qFAAqF;wBACvE,kBAAkB;QAChC,iGAAiG;yBAChF,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;;IAGxE,8EAA8E;2BACzD,aAAa,GAAG,IAAI;IACzC,iFAAiF;kBACrE,SAAS,GAAG,IAAI;IAC5B,iEAAiE;oBACnD,WAAW;IAEzB,iGAAiG;4BACzE,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAU3E,uEAAuE;mBACxD,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAUhE,iEAAiE;qBAChD,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;CAUhE,CAAA"}
1
+ {"version":3,"file":"ota.d.ts","sourceRoot":"","sources":["../../src/facades/ota.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAC,WAAW,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAC,MAAM,uBAAuB,CAAA;AAGrH,OAAO,EAAwB,KAAK,kBAAkB,EAAC,MAAM,mCAAmC,CAAA;AAGhG,OAAO,EAEL,KAAK,6BAA6B,EAClC,KAAK,4BAA4B,EAClC,MAAM,mCAAmC,CAAA;AAE1C,iBAAS,eAAe;;;;;;;;;;;;;;EAiBvB;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAA;AAC5D,YAAY,EACV,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,aAAa,EACb,kBAAkB,EAClB,6BAA6B,EAC7B,4BAA4B,GAC7B,CAAA;AAED,eAAO,MAAM,GAAG;IAEd;;;;OAIG;;IAMH;;;;;OAKG;8BACuB,MAAM,GAAG,IAAI,KAAG,OAAO,CAAC,gBAAgB,CAAC;IAQnE;;;OAGG;;IAEH,sGAAsG;gCAC1E,6BAA6B;IACzD,+CAA+C;;IAE/C,yEAAyE;;IAMzE;;;;;OAKG;4CACqC,aAAa,CAAC,SAAS,CAAC,KAAG,aAAa,GAAG,IAAI;IAQvF;;;;;OAKG;;IAKH;;;OAGG;yCACkC,OAAO;IAE5C;;;;OAIG;;QAED,oFAAoF;0BAClE,4BAA4B;QAC9C,2FAA2F;;QAE3F,+EAA+E;;QAE/E,+EAA+E;;QAE/E,2EAA2E;;QAE3E,uGAAuG;;QAEvG,qFAAqF;wBACvE,kBAAkB;QAChC,iGAAiG;yBAChF,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;;IAGxE,8EAA8E;2BACzD,aAAa,GAAG,IAAI;IACzC,iFAAiF;kBACrE,SAAS,GAAG,IAAI;IAC5B,iEAAiE;oBACnD,WAAW;IAEzB,iGAAiG;4BACzE,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAU3E,uEAAuE;mBACxD,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAUhE,iEAAiE;qBAChD,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;CAUhE,CAAA"}
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * ota facade — `engine.ota`: the OEM-facing OTA read/observe surface. Engine's
3
3
  * OtaService projects the glasses' OTA BLE events into the engine store; this facade
4
- * exposes the snapshot + change subscriptions the host renders its update prompt and
5
- * progress UI from. No host-injected UI the host owns all alerts/navigation/i18n.
4
+ * exposes the snapshot + change subscriptions behind the shared OTA flow exported by
5
+ * `@mentra/engine/ota`. Hosts retain only their surrounding navigation and theme/i18n adapters.
6
6
  *
7
7
  * Availability checks live in engine. Install orchestration lives in engine too:
8
8
  * `installSession` fronts the OtaInstallCoordinator state machine (WP 8B) — the host
@@ -10,8 +10,10 @@
10
10
  */
11
11
  import BluetoothSdk from "@mentra/bluetooth-sdk/internal";
12
12
  import { isGlassesConnected, useGlassesStore } from "../stores/glasses";
13
- import { getAsgOtaVersionUrl } from "../services/asgOtaVersionUrl";
13
+ import { resolveOtaManifestUrl } from "../services/otaManifestUrl";
14
14
  import { otaInstallCoordinator } from "../services/OtaInstallCoordinator";
15
+ import { startGlassesStatusProjection } from "../services/GlassesStatusProjection";
16
+ import { startOtaService } from "../services/OtaService";
15
17
  import { checkCurrentGlassesForUpdate, } from "../services/OtaUpdateCheckService";
16
18
  function projectSnapshot() {
17
19
  const s = useGlassesStore.getState();
@@ -20,9 +22,10 @@ function projectSnapshot() {
20
22
  buildNumber: s.buildNumber || null,
21
23
  mtkFirmwareVersion: s.mtkFirmwareVersion || null,
22
24
  besFirmwareVersion: s.besFirmwareVersion || null,
25
+ hotspotOtaVersion: s.hotspotOtaVersion ?? 0,
23
26
  wifiConnected: s.wifi.state === "connected",
24
27
  wifiStatusKnown: s.wifiStatusKnown,
25
- manifestUrl: getAsgOtaVersionUrl(s.otaVersionUrl, s.buildNumber),
28
+ manifestUrl: resolveOtaManifestUrl(s.otaVersionUrl, s.buildNumber),
26
29
  updateAvailable: s.otaUpdateAvailable,
27
30
  status: s.otaStatus,
28
31
  legacyProgress: s.otaProgress,
@@ -32,13 +35,23 @@ function projectSnapshot() {
32
35
  }
33
36
  export const ota = {
34
37
  // --- actions ---
38
+ /**
39
+ * Start the device-status and OTA projections without starting the authenticated
40
+ * cloud/miniapp runtime. This is the explicit entry point for Bluetooth-only hosts.
41
+ * Idempotent and safe when the full engine runtime is already running.
42
+ */
43
+ initialize: async () => {
44
+ const hydrated = startGlassesStatusProjection();
45
+ startOtaService();
46
+ await hydrated;
47
+ },
35
48
  /**
36
49
  * Start the firmware install with the resolved OTA manifest URL. Progress lands on
37
- * `status()`/`onStatus()`. (The host resolves the manifest URL — dev-override/env/prod
38
- * resolution stays with the OTA config; the host-side stuck/retry watchdog is its own
50
+ * `status()`/`onStatus()`. (The host resolves the manifest URL — developer override,
51
+ * host pin, or Engine release pin resolution stays with the OTA config; the stuck/retry watchdog is its own
39
52
  * resilience layer on top of this command.)
40
53
  */
41
- install: (...args) => BluetoothSdk.startOtaUpdate(...args),
54
+ install: (otaVersionUrl) => BluetoothSdk.startOtaUpdate(otaVersionUrl),
42
55
  // Deferred: this facade entry was intended to become the engine-owned retry/check
43
56
  // action, but BluetoothSdk.checkForOtaUpdate() only returns a boolean. Exposing it
44
57
  // here would make callers think the rich otaUpdateAvailable read model is refreshed,
@@ -97,6 +110,8 @@ export const ota = {
97
110
  * the snapshot; every watchdog/retry/reconnect rule lives in the coordinator.
98
111
  */
99
112
  installSession: {
113
+ /** Select Wi-Fi or capability-gated hotspot transport for this checked manifest. */
114
+ prepare: (result) => otaInstallCoordinator.prepare(result),
100
115
  /** Bind the machine to the mounted progress screen. Idempotent per attach/detach cycle. */
101
116
  attach: () => otaInstallCoordinator.attach(),
102
117
  /** Unbind on unmount: clears all timers/listeners and resets session state. */
@@ -1 +1 @@
1
- {"version":3,"file":"ota.js","sourceRoot":"","sources":["../../src/facades/ota.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ota facade — `engine.ota`: the OEM-facing OTA read/observe surface. Engine's\n * OtaService projects the glasses' OTA BLE events into the engine store; this facade\n * exposes the snapshot + change subscriptions the host renders its update prompt and\n * progress UI from. No host-injected UI — the host owns all alerts/navigation/i18n.\n *\n * Availability checks live in engine. Install orchestration lives in engine too:\n * `installSession` fronts the OtaInstallCoordinator state machine (WP 8B) — the host\n * progress screen is a pure renderer over its snapshot + attach/detach/retry/finish.\n */\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport type {OtaProgress, OtaProgressStatus, OtaStatus, OtaUpdateInfo} from \"@mentra/bluetooth-sdk/internal\"\nimport {isGlassesConnected, useGlassesStore} from \"../stores/glasses\"\nimport {getAsgOtaVersionUrl} from \"../services/asgOtaVersionUrl\"\nimport {otaInstallCoordinator, type OtaInstallSnapshot} from \"../services/OtaInstallCoordinator\"\nimport {\n checkCurrentGlassesForUpdate,\n type OtaCheckCurrentGlassesOptions,\n type OtaCheckCurrentGlassesResult,\n} from \"../services/OtaUpdateCheckService\"\n\nfunction projectSnapshot() {\n const s = useGlassesStore.getState()\n return {\n connected: isGlassesConnected(s.connection),\n buildNumber: s.buildNumber || null,\n mtkFirmwareVersion: s.mtkFirmwareVersion || null,\n besFirmwareVersion: s.besFirmwareVersion || null,\n wifiConnected: s.wifi.state === \"connected\",\n wifiStatusKnown: s.wifiStatusKnown,\n manifestUrl: getAsgOtaVersionUrl(s.otaVersionUrl, s.buildNumber),\n updateAvailable: s.otaUpdateAvailable,\n status: s.otaStatus,\n legacyProgress: s.otaProgress,\n inProgress: s.otaInProgress,\n mtkUpdatedThisSession: s.mtkUpdatedThisSession,\n }\n}\n\nexport type OtaSnapshot = ReturnType<typeof projectSnapshot>\nexport type {\n OtaProgress,\n OtaProgressStatus,\n OtaStatus,\n OtaUpdateInfo,\n OtaInstallSnapshot,\n OtaCheckCurrentGlassesOptions,\n OtaCheckCurrentGlassesResult,\n}\n\nexport const ota = {\n // --- actions ---\n /**\n * Start the firmware install with the resolved OTA manifest URL. Progress lands on\n * `status()`/`onStatus()`. (The host resolves the manifest URL — dev-override/env/prod\n * resolution stays with the OTA config; the host-side stuck/retry watchdog is its own\n * resilience layer on top of this command.)\n */\n install: (...args: Parameters<typeof BluetoothSdk.startOtaUpdate>) => BluetoothSdk.startOtaUpdate(...args),\n // Deferred: this facade entry was intended to become the engine-owned retry/check\n // action, but BluetoothSdk.checkForOtaUpdate() only returns a boolean. Exposing it\n // here would make callers think the rich otaUpdateAvailable read model is refreshed,\n // while the original view still depends on the host-side manifest compare to build\n // versionName/updates/totalSize. Keep that behavior unchanged until the whole rich\n // availability check moves into engine.\n // retry: () => BluetoothSdk.checkForOtaUpdate(),\n /**\n * Keep glasses awake while an OTA session is actively progressing.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n ping: () => BluetoothSdk.ping(),\n /** Resolve and compare the current glasses against the OTA manifest, then update the OTA snapshot. */\n checkForUpdates: (options?: OtaCheckCurrentGlassesOptions) => checkCurrentGlassesForUpdate(options),\n /** Clear the available-update prompt state. */\n clearUpdateAvailable: () => useGlassesStore.getState().setOtaUpdateAvailable(null),\n /** Clear active progress/status before entering a fresh install flow. */\n clearProgress: () => {\n const store = useGlassesStore.getState()\n store.setOtaProgress(null)\n store.setOtaStatus(null)\n },\n /**\n * Replace the pending update sequence after an in-flow firmware revalidation.\n * Kept as a named OTA policy operation so host screens do not mutate the raw\n * glasses store.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n replacePendingUpdateSequence: (updates: OtaUpdateInfo[\"updates\"]): OtaUpdateInfo | null => {\n const store = useGlassesStore.getState()\n const current = store.otaUpdateAvailable\n if (!current) return null\n const next = {...current, updates}\n store.setOtaUpdateAvailable(next)\n return next\n },\n /**\n * Clear stale build metadata before returning to the update-check screen.\n * This forces the next version_info event through both the native observable\n * store and the engine projection after an APK reboot.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n clearBuildNumberForNextCheck: () => {\n BluetoothSdk.updateGlasses({buildNumber: \"\"})\n useGlassesStore.getState().setGlassesInfo({buildNumber: \"\"})\n },\n /**\n * Mark MTK as already applied during this app session until the glasses reboot/disconnect.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n markMtkUpdatedThisSession: (updated: boolean) => useGlassesStore.getState().setMtkUpdatedThisSession(updated),\n\n /**\n * The OTA install state machine (unified `ota_status` sessions, build >= 37).\n * The host progress screen attaches on mount, detaches on unmount, and renders\n * the snapshot; every watchdog/retry/reconnect rule lives in the coordinator.\n */\n installSession: {\n /** Bind the machine to the mounted progress screen. Idempotent per attach/detach cycle. */\n attach: () => otaInstallCoordinator.attach(),\n /** Unbind on unmount: clears all timers/listeners and resets session state. */\n detach: () => otaInstallCoordinator.detach(),\n /** Retry after a failure: clear state and re-send ota_start (if connected). */\n retry: () => otaInstallCoordinator.retry(),\n /** Terminal cleanup for Continue/Done (navigation stays in the screen). */\n finish: () => otaInstallCoordinator.finish(),\n /** Abandon an interrupted session (super-mode skip): finish() + drop the session's status/progress. */\n discard: () => otaInstallCoordinator.discard(),\n /** Current install read model (displayState/errorMsg/lockout + glasses OTA data). */\n snapshot: (): OtaInstallSnapshot => otaInstallCoordinator.snapshot(),\n /** Subscribe to install snapshot changes (deduped on projected JSON). Returns an unsubscribe. */\n onSnapshot: (cb: (snapshot: OtaInstallSnapshot) => void): (() => void) => otaInstallCoordinator.onSnapshot(cb),\n },\n\n /** Current available-update info (versionName/updates/totalSize), or null. */\n updateAvailable: (): OtaUpdateInfo | null => useGlassesStore.getState().otaUpdateAvailable,\n /** Current OTA install status (stepType/phase/percent/status/error), or null. */\n status: (): OtaStatus | null => useGlassesStore.getState().otaStatus,\n /** Current OTA read model for update prompt/progress screens. */\n snapshot: (): OtaSnapshot => projectSnapshot(),\n\n /** Subscribe to OTA availability changes (info or null when cleared). Returns an unsubscribe. */\n onUpdateAvailable: (cb: (info: OtaUpdateInfo | null) => void): (() => void) => {\n let last = useGlassesStore.getState().otaUpdateAvailable\n return useGlassesStore.subscribe(() => {\n const info = useGlassesStore.getState().otaUpdateAvailable\n if (info === last) return\n last = info\n cb(info)\n })\n },\n\n /** Subscribe to OTA install status changes. Returns an unsubscribe. */\n onStatus: (cb: (status: OtaStatus | null) => void): (() => void) => {\n let last = useGlassesStore.getState().otaStatus\n return useGlassesStore.subscribe(() => {\n const status = useGlassesStore.getState().otaStatus\n if (status === last) return\n last = status\n cb(status)\n })\n },\n\n /** Subscribe to OTA snapshot changes. Returns an unsubscribe. */\n onSnapshot: (cb: (snapshot: OtaSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectSnapshot())\n return useGlassesStore.subscribe(() => {\n const snap = projectSnapshot()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n}\n"]}
1
+ {"version":3,"file":"ota.js","sourceRoot":"","sources":["../../src/facades/ota.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ota facade — `engine.ota`: the OEM-facing OTA read/observe surface. Engine's\n * OtaService projects the glasses' OTA BLE events into the engine store; this facade\n * exposes the snapshot + change subscriptions behind the shared OTA flow exported by\n * `@mentra/engine/ota`. Hosts retain only their surrounding navigation and theme/i18n adapters.\n *\n * Availability checks live in engine. Install orchestration lives in engine too:\n * `installSession` fronts the OtaInstallCoordinator state machine (WP 8B) — the host\n * progress screen is a pure renderer over its snapshot + attach/detach/retry/finish.\n */\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport type {OtaProgress, OtaProgressStatus, OtaStartAckEvent, OtaStatus, OtaUpdateInfo} from \"@mentra/bluetooth-sdk\"\nimport {isGlassesConnected, useGlassesStore} from \"../stores/glasses\"\nimport {resolveOtaManifestUrl} from \"../services/otaManifestUrl\"\nimport {otaInstallCoordinator, type OtaInstallSnapshot} from \"../services/OtaInstallCoordinator\"\nimport {startGlassesStatusProjection} from \"../services/GlassesStatusProjection\"\nimport {startOtaService} from \"../services/OtaService\"\nimport {\n checkCurrentGlassesForUpdate,\n type OtaCheckCurrentGlassesOptions,\n type OtaCheckCurrentGlassesResult,\n} from \"../services/OtaUpdateCheckService\"\n\nfunction projectSnapshot() {\n const s = useGlassesStore.getState()\n return {\n connected: isGlassesConnected(s.connection),\n buildNumber: s.buildNumber || null,\n mtkFirmwareVersion: s.mtkFirmwareVersion || null,\n besFirmwareVersion: s.besFirmwareVersion || null,\n hotspotOtaVersion: s.hotspotOtaVersion ?? 0,\n wifiConnected: s.wifi.state === \"connected\",\n wifiStatusKnown: s.wifiStatusKnown,\n manifestUrl: resolveOtaManifestUrl(s.otaVersionUrl, s.buildNumber),\n updateAvailable: s.otaUpdateAvailable,\n status: s.otaStatus,\n legacyProgress: s.otaProgress,\n inProgress: s.otaInProgress,\n mtkUpdatedThisSession: s.mtkUpdatedThisSession,\n }\n}\n\nexport type OtaSnapshot = ReturnType<typeof projectSnapshot>\nexport type {\n OtaProgress,\n OtaProgressStatus,\n OtaStatus,\n OtaUpdateInfo,\n OtaInstallSnapshot,\n OtaCheckCurrentGlassesOptions,\n OtaCheckCurrentGlassesResult,\n}\n\nexport const ota = {\n // --- actions ---\n /**\n * Start the device-status and OTA projections without starting the authenticated\n * cloud/miniapp runtime. This is the explicit entry point for Bluetooth-only hosts.\n * Idempotent and safe when the full engine runtime is already running.\n */\n initialize: async () => {\n const hydrated = startGlassesStatusProjection()\n startOtaService()\n await hydrated\n },\n /**\n * Start the firmware install with the resolved OTA manifest URL. Progress lands on\n * `status()`/`onStatus()`. (The host resolves the manifest URL — developer override,\n * host pin, or Engine release pin resolution stays with the OTA config; the stuck/retry watchdog is its own\n * resilience layer on top of this command.)\n */\n install: (otaVersionUrl?: string | null): Promise<OtaStartAckEvent> => BluetoothSdk.startOtaUpdate(otaVersionUrl),\n // Deferred: this facade entry was intended to become the engine-owned retry/check\n // action, but BluetoothSdk.checkForOtaUpdate() only returns a boolean. Exposing it\n // here would make callers think the rich otaUpdateAvailable read model is refreshed,\n // while the original view still depends on the host-side manifest compare to build\n // versionName/updates/totalSize. Keep that behavior unchanged until the whole rich\n // availability check moves into engine.\n // retry: () => BluetoothSdk.checkForOtaUpdate(),\n /**\n * Keep glasses awake while an OTA session is actively progressing.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n ping: () => BluetoothSdk.ping(),\n /** Resolve and compare the current glasses against the OTA manifest, then update the OTA snapshot. */\n checkForUpdates: (options?: OtaCheckCurrentGlassesOptions) => checkCurrentGlassesForUpdate(options),\n /** Clear the available-update prompt state. */\n clearUpdateAvailable: () => useGlassesStore.getState().setOtaUpdateAvailable(null),\n /** Clear active progress/status before entering a fresh install flow. */\n clearProgress: () => {\n const store = useGlassesStore.getState()\n store.setOtaProgress(null)\n store.setOtaStatus(null)\n },\n /**\n * Replace the pending update sequence after an in-flow firmware revalidation.\n * Kept as a named OTA policy operation so host screens do not mutate the raw\n * glasses store.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n replacePendingUpdateSequence: (updates: OtaUpdateInfo[\"updates\"]): OtaUpdateInfo | null => {\n const store = useGlassesStore.getState()\n const current = store.otaUpdateAvailable\n if (!current) return null\n const next = {...current, updates}\n store.setOtaUpdateAvailable(next)\n return next\n },\n /**\n * Clear stale build metadata before returning to the update-check screen.\n * This forces the next version_info event through both the native observable\n * store and the engine projection after an APK reboot.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n clearBuildNumberForNextCheck: () => {\n BluetoothSdk.updateGlasses({buildNumber: \"\"})\n useGlassesStore.getState().setGlassesInfo({buildNumber: \"\"})\n },\n /**\n * Mark MTK as already applied during this app session until the glasses reboot/disconnect.\n * @deprecated Legacy progress route (build < 37) only — removed with WP 8D.\n */\n markMtkUpdatedThisSession: (updated: boolean) => useGlassesStore.getState().setMtkUpdatedThisSession(updated),\n\n /**\n * The OTA install state machine (unified `ota_status` sessions, build >= 37).\n * The host progress screen attaches on mount, detaches on unmount, and renders\n * the snapshot; every watchdog/retry/reconnect rule lives in the coordinator.\n */\n installSession: {\n /** Select Wi-Fi or capability-gated hotspot transport for this checked manifest. */\n prepare: (result: OtaCheckCurrentGlassesResult) => otaInstallCoordinator.prepare(result),\n /** Bind the machine to the mounted progress screen. Idempotent per attach/detach cycle. */\n attach: () => otaInstallCoordinator.attach(),\n /** Unbind on unmount: clears all timers/listeners and resets session state. */\n detach: () => otaInstallCoordinator.detach(),\n /** Retry after a failure: clear state and re-send ota_start (if connected). */\n retry: () => otaInstallCoordinator.retry(),\n /** Terminal cleanup for Continue/Done (navigation stays in the screen). */\n finish: () => otaInstallCoordinator.finish(),\n /** Abandon an interrupted session (super-mode skip): finish() + drop the session's status/progress. */\n discard: () => otaInstallCoordinator.discard(),\n /** Current install read model (displayState/errorMsg/lockout + glasses OTA data). */\n snapshot: (): OtaInstallSnapshot => otaInstallCoordinator.snapshot(),\n /** Subscribe to install snapshot changes (deduped on projected JSON). Returns an unsubscribe. */\n onSnapshot: (cb: (snapshot: OtaInstallSnapshot) => void): (() => void) => otaInstallCoordinator.onSnapshot(cb),\n },\n\n /** Current available-update info (versionName/updates/totalSize), or null. */\n updateAvailable: (): OtaUpdateInfo | null => useGlassesStore.getState().otaUpdateAvailable,\n /** Current OTA install status (stepType/phase/percent/status/error), or null. */\n status: (): OtaStatus | null => useGlassesStore.getState().otaStatus,\n /** Current OTA read model for update prompt/progress screens. */\n snapshot: (): OtaSnapshot => projectSnapshot(),\n\n /** Subscribe to OTA availability changes (info or null when cleared). Returns an unsubscribe. */\n onUpdateAvailable: (cb: (info: OtaUpdateInfo | null) => void): (() => void) => {\n let last = useGlassesStore.getState().otaUpdateAvailable\n return useGlassesStore.subscribe(() => {\n const info = useGlassesStore.getState().otaUpdateAvailable\n if (info === last) return\n last = info\n cb(info)\n })\n },\n\n /** Subscribe to OTA install status changes. Returns an unsubscribe. */\n onStatus: (cb: (status: OtaStatus | null) => void): (() => void) => {\n let last = useGlassesStore.getState().otaStatus\n return useGlassesStore.subscribe(() => {\n const status = useGlassesStore.getState().otaStatus\n if (status === last) return\n last = status\n cb(status)\n })\n },\n\n /** Subscribe to OTA snapshot changes. Returns an unsubscribe. */\n onSnapshot: (cb: (snapshot: OtaSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectSnapshot())\n return useGlassesStore.subscribe(() => {\n const snap = projectSnapshot()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n}\n"]}