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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (503) hide show
  1. package/README.md +55 -18
  2. package/build/bluetooth-sdk/debug.d.ts +2 -0
  3. package/build/bluetooth-sdk/debug.d.ts.map +1 -0
  4. package/build/bluetooth-sdk/debug.js +2 -0
  5. package/build/bluetooth-sdk/debug.js.map +1 -0
  6. package/build/bluetooth-sdk/index.d.ts +3 -0
  7. package/build/bluetooth-sdk/index.d.ts.map +1 -0
  8. package/build/bluetooth-sdk/index.js +3 -0
  9. package/build/bluetooth-sdk/index.js.map +1 -0
  10. package/build/bluetooth-sdk/photo-receiver.d.ts +3 -0
  11. package/build/bluetooth-sdk/photo-receiver.d.ts.map +1 -0
  12. package/build/bluetooth-sdk/photo-receiver.js +3 -0
  13. package/build/bluetooth-sdk/photo-receiver.js.map +1 -0
  14. package/build/bluetooth-sdk/react.d.ts +2 -0
  15. package/build/bluetooth-sdk/react.d.ts.map +1 -0
  16. package/build/bluetooth-sdk/react.js +2 -0
  17. package/build/bluetooth-sdk/react.js.map +1 -0
  18. package/build/bluetooth-sdk/types.d.ts +2 -0
  19. package/build/bluetooth-sdk/types.d.ts.map +1 -0
  20. package/build/bluetooth-sdk/types.js +2 -0
  21. package/build/bluetooth-sdk/types.js.map +1 -0
  22. package/build/engine.d.ts +24 -16
  23. package/build/engine.d.ts.map +1 -1
  24. package/build/engine.js +9 -4
  25. package/build/engine.js.map +1 -1
  26. package/build/facades/dev.d.ts +3 -2
  27. package/build/facades/dev.d.ts.map +1 -1
  28. package/build/facades/dev.js +18 -12
  29. package/build/facades/dev.js.map +1 -1
  30. package/build/facades/display.d.ts +1 -1
  31. package/build/facades/display.d.ts.map +1 -1
  32. package/build/facades/display.js +1 -1
  33. package/build/facades/display.js.map +1 -1
  34. package/build/facades/gallery.js +1 -1
  35. package/build/facades/gallery.js.map +1 -1
  36. package/build/facades/glasses.d.ts +4 -13
  37. package/build/facades/glasses.d.ts.map +1 -1
  38. package/build/facades/glasses.js +21 -6
  39. package/build/facades/glasses.js.map +1 -1
  40. package/build/facades/glassesSettings.d.ts.map +1 -1
  41. package/build/facades/glassesSettings.js +1 -0
  42. package/build/facades/glassesSettings.js.map +1 -1
  43. package/build/facades/miniapps.d.ts +4 -0
  44. package/build/facades/miniapps.d.ts.map +1 -1
  45. package/build/facades/miniapps.js +5 -0
  46. package/build/facades/miniapps.js.map +1 -1
  47. package/build/facades/ota.d.ts +14 -16
  48. package/build/facades/ota.d.ts.map +1 -1
  49. package/build/facades/ota.js +22 -7
  50. package/build/facades/ota.js.map +1 -1
  51. package/build/facades/pairing.d.ts +8 -5
  52. package/build/facades/pairing.d.ts.map +1 -1
  53. package/build/facades/pairing.js +12 -10
  54. package/build/facades/pairing.js.map +1 -1
  55. package/build/facades/permissions.d.ts +10 -0
  56. package/build/facades/permissions.d.ts.map +1 -1
  57. package/build/facades/permissions.js +10 -0
  58. package/build/facades/permissions.js.map +1 -1
  59. package/build/facades/phoneNotifications.d.ts +0 -4
  60. package/build/facades/phoneNotifications.d.ts.map +1 -1
  61. package/build/facades/phoneNotifications.js +4 -14
  62. package/build/facades/phoneNotifications.js.map +1 -1
  63. package/build/facades/speech.d.ts +7 -6
  64. package/build/facades/speech.d.ts.map +1 -1
  65. package/build/facades/speech.js +1 -1
  66. package/build/facades/speech.js.map +1 -1
  67. package/build/generated/releaseMetadata.d.ts +12 -0
  68. package/build/generated/releaseMetadata.d.ts.map +1 -0
  69. package/build/generated/releaseMetadata.js +10 -0
  70. package/build/generated/releaseMetadata.js.map +1 -0
  71. package/build/index.d.ts +10 -8
  72. package/build/index.d.ts.map +1 -1
  73. package/build/index.js +6 -5
  74. package/build/index.js.map +1 -1
  75. package/build/react/MentraLiveOtaFlow.d.ts +38 -0
  76. package/build/react/MentraLiveOtaFlow.d.ts.map +1 -0
  77. package/build/react/MentraLiveOtaFlow.js +528 -0
  78. package/build/react/MentraLiveOtaFlow.js.map +1 -0
  79. package/build/react/index.d.ts +2 -0
  80. package/build/react/index.d.ts.map +1 -0
  81. package/build/react/index.js +2 -0
  82. package/build/react/index.js.map +1 -0
  83. package/build/react/useEngineSnapshot.d.ts +2 -0
  84. package/build/react/useEngineSnapshot.d.ts.map +1 -0
  85. package/build/react/useEngineSnapshot.js +14 -0
  86. package/build/react/useEngineSnapshot.js.map +1 -0
  87. package/build/runtime/bootstrap.d.ts +24 -1
  88. package/build/runtime/bootstrap.d.ts.map +1 -1
  89. package/build/runtime/bootstrap.js +17 -0
  90. package/build/runtime/bootstrap.js.map +1 -1
  91. package/build/runtime/scanQrSeam.d.ts +7 -0
  92. package/build/runtime/scanQrSeam.d.ts.map +1 -0
  93. package/build/runtime/scanQrSeam.js +16 -0
  94. package/build/runtime/scanQrSeam.js.map +1 -0
  95. package/build/services/AppRegistry.d.ts +41 -57
  96. package/build/services/AppRegistry.d.ts.map +1 -1
  97. package/build/services/AppRegistry.js +208 -144
  98. package/build/services/AppRegistry.js.map +1 -1
  99. package/build/services/AudioCloudUplink.d.ts +12 -0
  100. package/build/services/AudioCloudUplink.d.ts.map +1 -1
  101. package/build/services/AudioCloudUplink.js +22 -1
  102. package/build/services/AudioCloudUplink.js.map +1 -1
  103. package/build/services/AudioPlaybackService.d.ts +41 -2
  104. package/build/services/AudioPlaybackService.d.ts.map +1 -1
  105. package/build/services/AudioPlaybackService.js +250 -33
  106. package/build/services/AudioPlaybackService.js.map +1 -1
  107. package/build/services/BlobStore.d.ts +2 -1
  108. package/build/services/BlobStore.d.ts.map +1 -1
  109. package/build/services/BlobStore.js +17 -9
  110. package/build/services/BlobStore.js.map +1 -1
  111. package/build/services/CloudAudioSubscriptionSync.d.ts.map +1 -1
  112. package/build/services/CloudAudioSubscriptionSync.js +13 -1
  113. package/build/services/CloudAudioSubscriptionSync.js.map +1 -1
  114. package/build/services/CloudClientService.d.ts +15 -0
  115. package/build/services/CloudClientService.d.ts.map +1 -1
  116. package/build/services/CloudClientService.js +93 -1
  117. package/build/services/CloudClientService.js.map +1 -1
  118. package/build/services/DeviceEventRouter.js +5 -5
  119. package/build/services/DeviceEventRouter.js.map +1 -1
  120. package/build/services/ForegroundLocationPermission.d.ts +13 -0
  121. package/build/services/ForegroundLocationPermission.d.ts.map +1 -0
  122. package/build/services/ForegroundLocationPermission.js +12 -0
  123. package/build/services/ForegroundLocationPermission.js.map +1 -0
  124. package/build/services/GlassesSettingsSync.d.ts.map +1 -1
  125. package/build/services/GlassesSettingsSync.js +9 -3
  126. package/build/services/GlassesSettingsSync.js.map +1 -1
  127. package/build/services/GlassesStatusProjection.d.ts +2 -1
  128. package/build/services/GlassesStatusProjection.d.ts.map +1 -1
  129. package/build/services/GlassesStatusProjection.js +15 -8
  130. package/build/services/GlassesStatusProjection.js.map +1 -1
  131. package/build/services/HotspotOtaTransport.d.ts +29 -0
  132. package/build/services/HotspotOtaTransport.d.ts.map +1 -0
  133. package/build/services/HotspotOtaTransport.js +146 -0
  134. package/build/services/HotspotOtaTransport.js.map +1 -0
  135. package/build/services/HotspotShutdown.d.ts +17 -0
  136. package/build/services/HotspotShutdown.d.ts.map +1 -0
  137. package/build/services/HotspotShutdown.js +29 -0
  138. package/build/services/HotspotShutdown.js.map +1 -0
  139. package/build/services/LocalDisplayManager.d.ts +15 -0
  140. package/build/services/LocalDisplayManager.d.ts.map +1 -1
  141. package/build/services/LocalDisplayManager.js +106 -20
  142. package/build/services/LocalDisplayManager.js.map +1 -1
  143. package/build/services/LocalMiniappRuntime.d.ts +74 -2
  144. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  145. package/build/services/LocalMiniappRuntime.js +785 -291
  146. package/build/services/LocalMiniappRuntime.js.map +1 -1
  147. package/build/services/LocalMiniappStorage.d.ts +32 -0
  148. package/build/services/LocalMiniappStorage.d.ts.map +1 -0
  149. package/build/services/LocalMiniappStorage.js +66 -0
  150. package/build/services/LocalMiniappStorage.js.map +1 -0
  151. package/build/services/LocalMiniappUserIdentity.d.ts +20 -0
  152. package/build/services/LocalMiniappUserIdentity.d.ts.map +1 -0
  153. package/build/services/LocalMiniappUserIdentity.js +43 -0
  154. package/build/services/LocalMiniappUserIdentity.js.map +1 -0
  155. package/build/services/LocalSttFallbackCoordinator.d.ts +9 -6
  156. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
  157. package/build/services/LocalSttFallbackCoordinator.js +18 -12
  158. package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
  159. package/build/services/MicStateCoordinator.d.ts +42 -1
  160. package/build/services/MicStateCoordinator.d.ts.map +1 -1
  161. package/build/services/MicStateCoordinator.js +141 -3
  162. package/build/services/MicStateCoordinator.js.map +1 -1
  163. package/build/services/MiniappLauncher.d.ts.map +1 -1
  164. package/build/services/MiniappLauncher.js +23 -3
  165. package/build/services/MiniappLauncher.js.map +1 -1
  166. package/build/services/MiniappLiveness.d.ts +12 -0
  167. package/build/services/MiniappLiveness.d.ts.map +1 -0
  168. package/build/services/MiniappLiveness.js +16 -0
  169. package/build/services/MiniappLiveness.js.map +1 -0
  170. package/build/services/NativeHttpResponse.d.ts +3 -0
  171. package/build/services/NativeHttpResponse.d.ts.map +1 -0
  172. package/build/services/NativeHttpResponse.js +6 -0
  173. package/build/services/NativeHttpResponse.js.map +1 -0
  174. package/build/services/OtaArtifactDownloader.d.ts +65 -0
  175. package/build/services/OtaArtifactDownloader.d.ts.map +1 -0
  176. package/build/services/OtaArtifactDownloader.js +226 -0
  177. package/build/services/OtaArtifactDownloader.js.map +1 -0
  178. package/build/services/OtaAutoChain.d.ts +34 -0
  179. package/build/services/OtaAutoChain.d.ts.map +1 -0
  180. package/build/services/OtaAutoChain.js +83 -0
  181. package/build/services/OtaAutoChain.js.map +1 -0
  182. package/build/services/OtaErrorMapping.d.ts +18 -0
  183. package/build/services/OtaErrorMapping.d.ts.map +1 -0
  184. package/build/services/OtaErrorMapping.js +63 -0
  185. package/build/services/OtaErrorMapping.js.map +1 -0
  186. package/build/services/OtaInstallCoordinator.d.ts +95 -15
  187. package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
  188. package/build/services/OtaInstallCoordinator.js +577 -130
  189. package/build/services/OtaInstallCoordinator.js.map +1 -1
  190. package/build/services/OtaService.d.ts.map +1 -1
  191. package/build/services/OtaService.js +8 -1
  192. package/build/services/OtaService.js.map +1 -1
  193. package/build/services/OtaUpdateCheckService.d.ts +39 -4
  194. package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
  195. package/build/services/OtaUpdateCheckService.js +138 -22
  196. package/build/services/OtaUpdateCheckService.js.map +1 -1
  197. package/build/services/PhoneCalendarHelpers.d.ts +32 -0
  198. package/build/services/PhoneCalendarHelpers.d.ts.map +1 -0
  199. package/build/services/PhoneCalendarHelpers.js +157 -0
  200. package/build/services/PhoneCalendarHelpers.js.map +1 -0
  201. package/build/services/PhoneCalendarService.d.ts +5 -0
  202. package/build/services/PhoneCalendarService.d.ts.map +1 -0
  203. package/build/services/PhoneCalendarService.js +45 -0
  204. package/build/services/PhoneCalendarService.js.map +1 -0
  205. package/build/services/PhoneCameraFovCoordinator.d.ts +30 -0
  206. package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -0
  207. package/build/services/PhoneCameraFovCoordinator.js +194 -0
  208. package/build/services/PhoneCameraFovCoordinator.js.map +1 -0
  209. package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
  210. package/build/services/PhoneNotificationsSync.js +12 -10
  211. package/build/services/PhoneNotificationsSync.js.map +1 -1
  212. package/build/services/PhonePhotoCoordinator.d.ts +26 -2
  213. package/build/services/PhonePhotoCoordinator.d.ts.map +1 -1
  214. package/build/services/PhonePhotoCoordinator.js +79 -9
  215. package/build/services/PhonePhotoCoordinator.js.map +1 -1
  216. package/build/services/PhoneStreamCoordinator.d.ts +8 -1
  217. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
  218. package/build/services/PhoneStreamCoordinator.js +125 -13
  219. package/build/services/PhoneStreamCoordinator.js.map +1 -1
  220. package/build/services/PhoneVideoCoordinator.d.ts +2 -0
  221. package/build/services/PhoneVideoCoordinator.d.ts.map +1 -1
  222. package/build/services/PhoneVideoCoordinator.js +10 -0
  223. package/build/services/PhoneVideoCoordinator.js.map +1 -1
  224. package/build/services/SceneRenderer.d.ts.map +1 -1
  225. package/build/services/SceneRenderer.js +15 -0
  226. package/build/services/SceneRenderer.js.map +1 -1
  227. package/build/services/SentenceTtsPipeline.d.ts +31 -0
  228. package/build/services/SentenceTtsPipeline.d.ts.map +1 -0
  229. package/build/services/SentenceTtsPipeline.js +67 -0
  230. package/build/services/SentenceTtsPipeline.js.map +1 -0
  231. package/build/services/SupportProfileSync.d.ts +22 -0
  232. package/build/services/SupportProfileSync.d.ts.map +1 -0
  233. package/build/services/SupportProfileSync.js +213 -0
  234. package/build/services/SupportProfileSync.js.map +1 -0
  235. package/build/services/TranscriptionRouting.d.ts +12 -0
  236. package/build/services/TranscriptionRouting.d.ts.map +1 -0
  237. package/build/services/TranscriptionRouting.js +24 -0
  238. package/build/services/TranscriptionRouting.js.map +1 -0
  239. package/build/services/TtsTextSanitizer.d.ts +5 -0
  240. package/build/services/TtsTextSanitizer.d.ts.map +1 -0
  241. package/build/services/TtsTextSanitizer.js +61 -0
  242. package/build/services/TtsTextSanitizer.js.map +1 -0
  243. package/build/services/WifiAdbRequest.d.ts +17 -0
  244. package/build/services/WifiAdbRequest.d.ts.map +1 -0
  245. package/build/services/WifiAdbRequest.js +35 -0
  246. package/build/services/WifiAdbRequest.js.map +1 -0
  247. package/build/services/asg/asgCameraApi.d.ts +43 -0
  248. package/build/services/asg/asgCameraApi.d.ts.map +1 -1
  249. package/build/services/asg/asgCameraApi.js +509 -26
  250. package/build/services/asg/asgCameraApi.js.map +1 -1
  251. package/build/services/asg/cameraRollExportCoordinator.d.ts +60 -0
  252. package/build/services/asg/cameraRollExportCoordinator.d.ts.map +1 -0
  253. package/build/services/asg/cameraRollExportCoordinator.js +618 -0
  254. package/build/services/asg/cameraRollExportCoordinator.js.map +1 -0
  255. package/build/services/asg/cameraRollExportLedger.d.ts +44 -0
  256. package/build/services/asg/cameraRollExportLedger.d.ts.map +1 -0
  257. package/build/services/asg/cameraRollExportLedger.js +78 -0
  258. package/build/services/asg/cameraRollExportLedger.js.map +1 -0
  259. package/build/services/asg/galleryNotices.d.ts +1 -1
  260. package/build/services/asg/galleryNotices.d.ts.map +1 -1
  261. package/build/services/asg/galleryNotices.js.map +1 -1
  262. package/build/services/asg/galleryPathMigration.d.ts +3 -0
  263. package/build/services/asg/galleryPathMigration.d.ts.map +1 -0
  264. package/build/services/asg/galleryPathMigration.js +26 -0
  265. package/build/services/asg/galleryPathMigration.js.map +1 -0
  266. package/build/services/asg/gallerySettingsService.d.ts +1 -0
  267. package/build/services/asg/gallerySettingsService.d.ts.map +1 -1
  268. package/build/services/asg/gallerySettingsService.js +2 -0
  269. package/build/services/asg/gallerySettingsService.js.map +1 -1
  270. package/build/services/asg/gallerySyncService.d.ts.map +1 -1
  271. package/build/services/asg/gallerySyncService.js +162 -56
  272. package/build/services/asg/gallerySyncService.js.map +1 -1
  273. package/build/services/asg/galleryTransferLedger.d.ts +58 -0
  274. package/build/services/asg/galleryTransferLedger.d.ts.map +1 -0
  275. package/build/services/asg/galleryTransferLedger.js +225 -0
  276. package/build/services/asg/galleryTransferLedger.js.map +1 -0
  277. package/build/services/asg/localNetworkTransport.d.ts +15 -0
  278. package/build/services/asg/localNetworkTransport.d.ts.map +1 -0
  279. package/build/services/asg/localNetworkTransport.js +144 -0
  280. package/build/services/asg/localNetworkTransport.js.map +1 -0
  281. package/build/services/asg/localStorageService.d.ts +18 -0
  282. package/build/services/asg/localStorageService.d.ts.map +1 -1
  283. package/build/services/asg/localStorageService.js +168 -19
  284. package/build/services/asg/localStorageService.js.map +1 -1
  285. package/build/services/asg/mediaProcessingQueue.d.ts +10 -0
  286. package/build/services/asg/mediaProcessingQueue.d.ts.map +1 -1
  287. package/build/services/asg/mediaProcessingQueue.js +193 -62
  288. package/build/services/asg/mediaProcessingQueue.js.map +1 -1
  289. package/build/services/audioPlaybackAssets.d.ts +8 -0
  290. package/build/services/audioPlaybackAssets.d.ts.map +1 -0
  291. package/build/services/audioPlaybackAssets.js +7 -0
  292. package/build/services/audioPlaybackAssets.js.map +1 -0
  293. package/build/services/gallerySyncClock.js +1 -1
  294. package/build/services/gallerySyncClock.js.map +1 -1
  295. package/build/services/glassesClockSync.d.ts.map +1 -1
  296. package/build/services/glassesClockSync.js +6 -2
  297. package/build/services/glassesClockSync.js.map +1 -1
  298. package/build/services/manifestActions.d.ts +7 -0
  299. package/build/services/manifestActions.d.ts.map +1 -0
  300. package/build/services/manifestActions.js +25 -0
  301. package/build/services/manifestActions.js.map +1 -0
  302. package/build/services/otaDisplayState.d.ts +23 -12
  303. package/build/services/otaDisplayState.d.ts.map +1 -1
  304. package/build/services/otaDisplayState.js +36 -14
  305. package/build/services/otaDisplayState.js.map +1 -1
  306. package/build/services/otaInstallPolicy.d.ts +16 -4
  307. package/build/services/otaInstallPolicy.d.ts.map +1 -1
  308. package/build/services/otaInstallPolicy.js +24 -3
  309. package/build/services/otaInstallPolicy.js.map +1 -1
  310. package/build/services/otaLegacyMapping.d.ts +1 -1
  311. package/build/services/otaLegacyMapping.d.ts.map +1 -1
  312. package/build/services/otaLegacyMapping.js.map +1 -1
  313. package/build/services/otaManifestPolicy.d.ts +14 -0
  314. package/build/services/otaManifestPolicy.d.ts.map +1 -0
  315. package/build/services/otaManifestPolicy.js +19 -0
  316. package/build/services/otaManifestPolicy.js.map +1 -0
  317. package/build/services/otaManifestUrl.d.ts +3 -0
  318. package/build/services/otaManifestUrl.d.ts.map +1 -0
  319. package/build/services/otaManifestUrl.js +38 -0
  320. package/build/services/otaManifestUrl.js.map +1 -0
  321. package/build/services/slimStreamStatus.d.ts +11 -0
  322. package/build/services/slimStreamStatus.d.ts.map +1 -1
  323. package/build/services/slimStreamStatus.js +14 -4
  324. package/build/services/slimStreamStatus.js.map +1 -1
  325. package/build/stores/apps.d.ts.map +1 -1
  326. package/build/stores/apps.js +11 -0
  327. package/build/stores/apps.js.map +1 -1
  328. package/build/stores/bluetoothSettingKeys.d.ts.map +1 -1
  329. package/build/stores/bluetoothSettingKeys.js +2 -0
  330. package/build/stores/bluetoothSettingKeys.js.map +1 -1
  331. package/build/stores/gallerySync.d.ts +2 -0
  332. package/build/stores/gallerySync.d.ts.map +1 -1
  333. package/build/stores/gallerySync.js +2 -0
  334. package/build/stores/gallerySync.js.map +1 -1
  335. package/build/stores/glasses.d.ts.map +1 -1
  336. package/build/stores/glasses.js +3 -0
  337. package/build/stores/glasses.js.map +1 -1
  338. package/build/stores/settings.d.ts +17 -0
  339. package/build/stores/settings.d.ts.map +1 -1
  340. package/build/stores/settings.js +157 -17
  341. package/build/stores/settings.js.map +1 -1
  342. package/build/types/applet.d.ts +2 -0
  343. package/build/types/applet.d.ts.map +1 -1
  344. package/build/types/applet.js.map +1 -1
  345. package/build/types/asg.d.ts +7 -0
  346. package/build/types/asg.d.ts.map +1 -1
  347. package/build/types/asg.js.map +1 -1
  348. package/build/types/enums.d.ts +2 -25
  349. package/build/types/enums.d.ts.map +1 -1
  350. package/build/types/enums.js +2 -27
  351. package/build/types/enums.js.map +1 -1
  352. package/build/types/hardware.d.ts +4 -13
  353. package/build/types/hardware.d.ts.map +1 -1
  354. package/build/types/hardware.js +15 -3
  355. package/build/types/hardware.js.map +1 -1
  356. package/build/types/index.d.ts +2 -6
  357. package/build/types/index.d.ts.map +1 -1
  358. package/build/types/index.js +2 -6
  359. package/build/types/index.js.map +1 -1
  360. package/build/utils/configuredDevHost.d.ts +6 -0
  361. package/build/utils/configuredDevHost.d.ts.map +1 -0
  362. package/build/utils/configuredDevHost.js +19 -0
  363. package/build/utils/configuredDevHost.js.map +1 -0
  364. package/build/utils/devMiniappLaunch.d.ts +19 -8
  365. package/build/utils/devMiniappLaunch.d.ts.map +1 -1
  366. package/build/utils/devMiniappLaunch.js +144 -21
  367. package/build/utils/devMiniappLaunch.js.map +1 -1
  368. package/build/utils/diagnosticContext.d.ts.map +1 -1
  369. package/build/utils/diagnosticContext.js +15 -17
  370. package/build/utils/diagnosticContext.js.map +1 -1
  371. package/build/utils/hardware/hardware.d.ts.map +1 -1
  372. package/build/utils/hardware/hardware.js +7 -3
  373. package/build/utils/hardware/hardware.js.map +1 -1
  374. package/build/utils/miniappDiagnostics.d.ts +64 -0
  375. package/build/utils/miniappDiagnostics.d.ts.map +1 -0
  376. package/build/utils/miniappDiagnostics.js +173 -0
  377. package/build/utils/miniappDiagnostics.js.map +1 -0
  378. package/build/utils/permissions/MediaLibraryPermissions.d.ts +11 -0
  379. package/build/utils/permissions/MediaLibraryPermissions.d.ts.map +1 -1
  380. package/build/utils/permissions/MediaLibraryPermissions.js +27 -4
  381. package/build/utils/permissions/MediaLibraryPermissions.js.map +1 -1
  382. package/build/utils/timers/timers.d.ts.map +1 -1
  383. package/build/utils/timers/timers.js +55 -18
  384. package/build/utils/timers/timers.js.map +1 -1
  385. package/package.json +59 -31
  386. package/src/assets/silence.wav +0 -0
  387. package/src/bluetooth-sdk/debug.ts +1 -0
  388. package/src/bluetooth-sdk/index.ts +2 -0
  389. package/src/bluetooth-sdk/photo-receiver.ts +2 -0
  390. package/src/bluetooth-sdk/react.ts +1 -0
  391. package/src/bluetooth-sdk/types.ts +1 -0
  392. package/src/engine.ts +9 -4
  393. package/src/facades/dev.ts +17 -12
  394. package/src/facades/display.ts +1 -1
  395. package/src/facades/gallery.ts +1 -1
  396. package/src/facades/glasses.ts +20 -7
  397. package/src/facades/glassesSettings.ts +5 -0
  398. package/src/facades/miniapps.ts +7 -0
  399. package/src/facades/ota.ts +23 -8
  400. package/src/facades/pairing.ts +15 -11
  401. package/src/facades/permissions.ts +14 -0
  402. package/src/facades/phoneNotifications.ts +4 -13
  403. package/src/facades/speech.ts +21 -7
  404. package/src/generated/releaseMetadata.ts +20 -0
  405. package/src/index.ts +39 -13
  406. package/src/react/MentraLiveOtaFlow.tsx +856 -0
  407. package/src/react/index.ts +7 -0
  408. package/src/react/useEngineSnapshot.ts +16 -0
  409. package/src/runtime/bootstrap.ts +33 -1
  410. package/src/runtime/scanQrSeam.ts +20 -0
  411. package/src/services/AppRegistry.ts +240 -149
  412. package/src/services/AudioCloudUplink.ts +23 -1
  413. package/src/services/AudioPlaybackService.ts +287 -38
  414. package/src/services/BlobStore.ts +22 -9
  415. package/src/services/CloudAudioSubscriptionSync.ts +13 -1
  416. package/src/services/CloudClientService.ts +96 -1
  417. package/src/services/DeviceEventRouter.ts +5 -5
  418. package/src/services/ForegroundLocationPermission.ts +24 -0
  419. package/src/services/GlassesSettingsSync.ts +9 -3
  420. package/src/services/GlassesStatusProjection.ts +16 -8
  421. package/src/services/HotspotOtaTransport.ts +184 -0
  422. package/src/services/HotspotShutdown.ts +41 -0
  423. package/src/services/LocalDisplayManager.ts +112 -21
  424. package/src/services/LocalMiniappRuntime.ts +967 -346
  425. package/src/services/LocalMiniappStorage.ts +82 -0
  426. package/src/services/LocalMiniappUserIdentity.ts +46 -0
  427. package/src/services/LocalSttFallbackCoordinator.ts +19 -12
  428. package/src/services/MicStateCoordinator.ts +169 -4
  429. package/src/services/MiniappLauncher.ts +30 -3
  430. package/src/services/MiniappLiveness.ts +24 -0
  431. package/src/services/NativeHttpResponse.ts +6 -0
  432. package/src/services/OtaArtifactDownloader.ts +312 -0
  433. package/src/services/OtaAutoChain.ts +106 -0
  434. package/src/services/OtaErrorMapping.ts +80 -0
  435. package/src/services/OtaInstallCoordinator.ts +649 -144
  436. package/src/services/OtaService.ts +11 -5
  437. package/src/services/OtaUpdateCheckService.ts +181 -21
  438. package/src/services/PhoneCalendarHelpers.ts +212 -0
  439. package/src/services/PhoneCalendarService.ts +65 -0
  440. package/src/services/PhoneCameraFovCoordinator.ts +210 -0
  441. package/src/services/PhoneNotificationsSync.ts +12 -10
  442. package/src/services/PhonePhotoCoordinator.ts +116 -18
  443. package/src/services/PhoneStreamCoordinator.ts +139 -25
  444. package/src/services/PhoneVideoCoordinator.ts +11 -0
  445. package/src/services/SceneRenderer.ts +16 -0
  446. package/src/services/SentenceTtsPipeline.ts +106 -0
  447. package/src/services/SupportProfileSync.ts +218 -0
  448. package/src/services/TranscriptionRouting.ts +37 -0
  449. package/src/services/TtsTextSanitizer.ts +66 -0
  450. package/src/services/WifiAdbRequest.ts +53 -0
  451. package/src/services/asg/asgCameraApi.ts +615 -33
  452. package/src/services/asg/cameraRollExportCoordinator.ts +627 -0
  453. package/src/services/asg/cameraRollExportLedger.ts +122 -0
  454. package/src/services/asg/galleryNotices.ts +1 -0
  455. package/src/services/asg/galleryPathMigration.ts +22 -0
  456. package/src/services/asg/gallerySettingsService.ts +3 -0
  457. package/src/services/asg/gallerySyncService.ts +184 -73
  458. package/src/services/asg/galleryTransferLedger.ts +312 -0
  459. package/src/services/asg/localNetworkTransport.ts +169 -0
  460. package/src/services/asg/localStorageService.ts +179 -24
  461. package/src/services/asg/mediaProcessingQueue.ts +209 -62
  462. package/src/services/audioPlaybackAssets.ts +8 -0
  463. package/src/services/gallerySyncClock.ts +1 -1
  464. package/src/services/glassesClockSync.ts +6 -2
  465. package/src/services/manifestActions.ts +30 -0
  466. package/src/services/otaDisplayState.ts +58 -17
  467. package/src/services/otaInstallPolicy.ts +30 -4
  468. package/src/services/otaLegacyMapping.ts +1 -1
  469. package/src/services/otaManifestPolicy.ts +42 -0
  470. package/src/services/otaManifestUrl.ts +44 -0
  471. package/src/services/slimStreamStatus.ts +16 -5
  472. package/src/stores/apps.ts +12 -0
  473. package/src/stores/bluetoothSettingKeys.ts +2 -0
  474. package/src/stores/gallerySync.ts +4 -0
  475. package/src/stores/glasses.ts +3 -0
  476. package/src/stores/settings.ts +179 -18
  477. package/src/types/applet.ts +2 -0
  478. package/src/types/asg.ts +7 -0
  479. package/src/types/enums.ts +3 -28
  480. package/src/types/hardware.ts +20 -13
  481. package/src/types/index.ts +2 -6
  482. package/src/utils/configuredDevHost.ts +17 -0
  483. package/src/utils/devMiniappLaunch.ts +151 -23
  484. package/src/utils/diagnosticContext.ts +17 -17
  485. package/src/utils/hardware/hardware.ts +7 -9
  486. package/src/utils/miniappDiagnostics.ts +226 -0
  487. package/src/utils/permissions/MediaLibraryPermissions.ts +35 -4
  488. package/src/utils/timers/timers.ts +57 -21
  489. package/build/devtools.d.ts +0 -11
  490. package/build/devtools.d.ts.map +0 -1
  491. package/build/devtools.js +0 -13
  492. package/build/devtools.js.map +0 -1
  493. package/build/internal.d.ts +0 -66
  494. package/build/internal.d.ts.map +0 -1
  495. package/build/internal.js +0 -89
  496. package/build/internal.js.map +0 -1
  497. package/build/services/asgOtaVersionUrl.d.ts +0 -2
  498. package/build/services/asgOtaVersionUrl.d.ts.map +0 -1
  499. package/build/services/asgOtaVersionUrl.js +0 -36
  500. package/build/services/asgOtaVersionUrl.js.map +0 -1
  501. package/src/devtools.ts +0 -13
  502. package/src/internal.ts +0 -158
  503. package/src/services/asgOtaVersionUrl.ts +0 -41
@@ -1,6 +1,4 @@
1
- /**
2
- * @mentra/types - Hardware capability types
3
- */
1
+ /** Hardware capability types used by the Engine. */
4
2
 
5
3
  import { evenRealitiesG1 } from "./capabilities/even-realities-g1";
6
4
  import { evenRealitiesG2 } from "./capabilities/even-realities-g2";
@@ -9,17 +7,9 @@ import { mentraLive } from "./capabilities/mentra-live";
9
7
  import { simulatedGlasses } from "./capabilities/simulated-glasses";
10
8
  import { vuzixZ100 } from "./capabilities/vuzix-z100";
11
9
  import { none } from "./capabilities/none";
12
- import { DeviceTypes, HardwareRequirementLevel, HardwareType } from "./enums";
10
+ import { DeviceTypes } from "./enums";
13
11
 
14
- /**
15
- * Hardware requirement for an app
16
- * Specifies what hardware components an app needs
17
- */
18
- export interface HardwareRequirement {
19
- type: HardwareType;
20
- level: HardwareRequirementLevel;
21
- description?: string; // Why this hardware is needed
22
- }
12
+ export type { HardwareRequirement } from "@mentra/miniapp/hardware";
23
13
 
24
14
  /**
25
15
  * Camera capabilities
@@ -167,6 +157,9 @@ export interface Capabilities {
167
157
  // WiFi capability
168
158
  hasWifi: boolean;
169
159
 
160
+ // OTA capability
161
+ hasOta?: boolean;
162
+
170
163
  // Native dashboard capability
171
164
  // True when the device renders its own dashboard in firmware (e.g. Even
172
165
  // Realities' built-in dashboard on G2). MentraOS does not manage or expose
@@ -188,6 +181,20 @@ export const HARDWARE_CAPABILITIES: Record<string, Capabilities> = {
188
181
  [simulatedGlasses.modelName]: simulatedGlasses,
189
182
  [vuzixZ100.modelName]: vuzixZ100,
190
183
  [DeviceTypes.MACH1]: vuzixZ100, // Mach1 uses same Vuzix Ultralite hardware as Z100
184
+ [DeviceTypes.AR99]: {
185
+ ...evenRealitiesG1,
186
+ modelName: DeviceTypes.AR99,
187
+ display: {
188
+ ...evenRealitiesG1.display,
189
+ canDisplayBitmap: false,
190
+ },
191
+ hasMicrophone: true,
192
+ hasOta: true,
193
+ microphone: {
194
+ count: 1,
195
+ hasVAD: false,
196
+ },
197
+ },
191
198
  [none.modelName]: none,
192
199
  };
193
200
 
@@ -1,9 +1,5 @@
1
- /**
2
- * Engine shared types — copied verbatim from @mentra/types so the module is
3
- * self-contained. Keep these in sync with cloud/packages/types/src when the
4
- * canonical types change. The capability profiles also live here under
5
- * ./capabilities/.
6
- */
1
+ /** Engine capability types and profiles. Miniapp manifest requirement types
2
+ * are re-exported from @mentra/miniapp, their canonical owner. */
7
3
 
8
4
  // Enums (runtime values)
9
5
  export {HardwareType, HardwareRequirementLevel, DeviceTypes, ControllerTypes} from "./enums"
@@ -0,0 +1,17 @@
1
+ import {getConfigValues} from "../runtime/bootstrap"
2
+
3
+ /**
4
+ * Explicit Metro / laptop host override used by stale-URL rewrite and launch
5
+ * failover. One source of truth so AppRegistry and decideDevLaunchRoute stay aligned.
6
+ */
7
+ export function configuredDevHost(): string | undefined {
8
+ const explicit = process.env.EXPO_PUBLIC_LOCAL_MINIAPP_HOST
9
+ if (explicit) {
10
+ try {
11
+ return new URL(explicit).hostname
12
+ } catch {
13
+ if (/^[\w.-]+$/.test(explicit)) return explicit
14
+ }
15
+ }
16
+ return getConfigValues().devServerHost?.()
17
+ }
@@ -12,12 +12,27 @@
12
12
  * get it in the same round trip — no second fetch.
13
13
  *
14
14
  * Pre-flighting at the call site keeps /applet/local a pure mount route.
15
+ *
16
+ * When the laptop's Wi-Fi IP changes, the URL stored from the last QR scan
17
+ * goes stale. We then retry alternate hosts (Metro / EXPO_PUBLIC_LOCAL_MINIAPP_HOST,
18
+ * plus an mDNS name captured at scan time) and persist the working URL so
19
+ * the next launch doesn't need a re-scan.
15
20
  */
16
21
 
22
+ import {configuredDevHost} from "./configuredDevHost"
17
23
  import {storage} from "./storage/storage"
18
24
 
19
25
  const REACHABILITY_TIMEOUT_MS = 1500
20
26
 
27
+ // A single dropped DNS lookup or momentary Wi-Fi blip (AP roam, DHCP renewal,
28
+ // phone hopping to cellular for a beat) looks identical to a dead dev server —
29
+ // both throw out of fetch(). Retrying once absorbs that transient case instead
30
+ // of bouncing straight to the offline screen. We do NOT retry a real HTTP
31
+ // response (res.ok === false): that's the server telling us something
32
+ // definitive, not a network-layer hiccup.
33
+ const REACHABILITY_MAX_ATTEMPTS = 2
34
+ const REACHABILITY_RETRY_DELAY_MS = 400
35
+
21
36
  export type DevManifest = {
22
37
  packageName?: string
23
38
  name?: string
@@ -29,40 +44,153 @@ export type DevManifest = {
29
44
  }
30
45
 
31
46
  export type DevLaunchResult =
32
- | {decision: "live"; manifest: DevManifest}
33
- | {decision: "offline"; manifest: null}
47
+ | {decision: "live"; manifest: DevManifest; resolvedUrl: string}
48
+ | {decision: "offline"; manifest: null; resolvedUrl?: undefined}
49
+
50
+ export type DecideDevLaunchOptions = {
51
+ /** Extra hostnames / IPs to try if `devUrl` is unreachable (no scheme/port). */
52
+ alternateHosts?: string[]
53
+ }
54
+
55
+ function delay(ms: number): Promise<void> {
56
+ return new Promise((resolve) => setTimeout(resolve, ms))
57
+ }
58
+
59
+ /** Single GET <devUrl>/miniapp.json attempt with a hard timeout. */
60
+ async function fetchManifestOnce(devUrl: string): Promise<DevManifest | null> {
61
+ const controller = new AbortController()
62
+ const timer = setTimeout(() => controller.abort(), REACHABILITY_TIMEOUT_MS)
63
+ try {
64
+ const res = await fetch(`${devUrl.replace(/\/$/, "")}/miniapp.json`, {
65
+ method: "GET",
66
+ signal: controller.signal,
67
+ })
68
+ if (!res.ok) return null
69
+ return (await res.json()) as DevManifest
70
+ } finally {
71
+ clearTimeout(timer)
72
+ }
73
+ }
74
+
75
+ function rewriteHost(devUrl: string, host: string): string | null {
76
+ const trimmed = host.trim()
77
+ if (!trimmed) return null
78
+ try {
79
+ const url = new URL(devUrl)
80
+ if (url.hostname === trimmed) return null
81
+ url.hostname = trimmed
82
+ return url.toString().replace(/\/$/, "")
83
+ } catch {
84
+ return null
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Point an http(s) icon at the host that actually answered. Cached dev icons are
90
+ * local `file://` paths and third-party icons live on unrelated hosts, so only
91
+ * icons still served by the stale dev host are rewritten.
92
+ */
93
+ function rewriteIconHost(iconUrl: string, staleDevUrl: string, resolvedDevUrl: string): string | null {
94
+ try {
95
+ const icon = new URL(iconUrl)
96
+ if (icon.protocol !== "http:" && icon.protocol !== "https:") return null
97
+ const stale = new URL(staleDevUrl)
98
+ const resolved = new URL(resolvedDevUrl)
99
+ // Compare host (hostname+port) so an icon on the same hostname but a
100
+ // different service port is left alone.
101
+ if (icon.host !== stale.host) return null
102
+ icon.host = resolved.host
103
+ return icon.toString()
104
+ } catch {
105
+ return null
106
+ }
107
+ }
108
+
109
+ function collectAlternateHosts(packageName: string, extra?: string[]): string[] {
110
+ const hosts: string[] = []
111
+ const push = (h: string | undefined | null) => {
112
+ const v = h?.trim()
113
+ if (v && !hosts.includes(v)) hosts.push(v)
114
+ }
115
+
116
+ push(configuredDevHost())
117
+
118
+ if (packageName) {
119
+ const mdns = storage.load<string>(`${packageName}_dev_mdns`)
120
+ if (mdns.is_ok()) push(mdns.value)
121
+ }
122
+
123
+ for (const h of extra ?? []) push(h)
124
+ return hosts
125
+ }
126
+
127
+ async function probeUrl(devUrl: string): Promise<DevManifest | null | "network-error"> {
128
+ for (let attempt = 1; attempt <= REACHABILITY_MAX_ATTEMPTS; attempt++) {
129
+ try {
130
+ const manifest = await fetchManifestOnce(devUrl)
131
+ // Definitive HTTP failure — do not retry this URL further.
132
+ if (!manifest) return null
133
+ return manifest
134
+ } catch {
135
+ if (attempt < REACHABILITY_MAX_ATTEMPTS) {
136
+ await delay(REACHABILITY_RETRY_DELAY_MS)
137
+ continue
138
+ }
139
+ return "network-error"
140
+ }
141
+ }
142
+ return "network-error"
143
+ }
34
144
 
35
145
  /**
36
- * GET <devUrl>/miniapp.json with a hard timeout. Returns the parsed
146
+ * GET <devUrl>/miniapp.json with a hard timeout, retrying once on a
147
+ * network-layer failure (DNS/connection/abort) before trying alternate
148
+ * hosts (Metro laptop IP, mDNS name from the QR). Returns the parsed
37
149
  * manifest on success ("live") or null ("offline").
38
150
  *
39
- * Side effect: on success, writes <packageName>_dev_last_reachable so
40
- * the dev-offline screen can show "Last reached: N min ago" the next
41
- * time the user lands there.
42
- *
43
- * The fetch doubles as the reachability probe AND the manifest source —
44
- * one request per launch attempt instead of two.
151
+ * Side effects on success:
152
+ * - writes <packageName>_dev_last_reachable
153
+ * - if an alternate host worked, rewrites <packageName>_dev_url so the
154
+ * next launch skips the stale IP
45
155
  */
46
156
  export async function decideDevLaunchRoute(
47
157
  packageName: string,
48
158
  devUrl: string,
159
+ options?: DecideDevLaunchOptions,
49
160
  ): Promise<DevLaunchResult> {
50
- const controller = new AbortController()
51
- const timer = setTimeout(() => controller.abort(), REACHABILITY_TIMEOUT_MS)
52
- try {
53
- const res = await fetch(`${devUrl.replace(/\/$/, "")}/miniapp.json`, {
54
- method: "GET",
55
- signal: controller.signal,
56
- })
57
- if (!res.ok) return {decision: "offline", manifest: null}
58
- const manifest = (await res.json()) as DevManifest
161
+ const candidates: string[] = [devUrl]
162
+ for (const host of collectAlternateHosts(packageName, options?.alternateHosts)) {
163
+ const rewritten = rewriteHost(devUrl, host)
164
+ if (rewritten && !candidates.includes(rewritten)) candidates.push(rewritten)
165
+ }
166
+
167
+ for (const candidate of candidates) {
168
+ const result = await probeUrl(candidate)
169
+ if (result === "network-error" || result === null) continue
170
+
59
171
  if (packageName) {
60
172
  storage.save(`${packageName}_dev_last_reachable`, Date.now())
173
+ if (candidate !== devUrl) {
174
+ storage.save(`${packageName}_dev_url`, candidate)
175
+ // Keep _dev_meta.devUrl in sync when present so home-tile reads match.
176
+ const metaRes = storage.load<string>(`${packageName}_dev_meta`)
177
+ if (metaRes.is_ok()) {
178
+ try {
179
+ const meta = JSON.parse(metaRes.value) as {devUrl?: string; iconUrl?: string}
180
+ meta.devUrl = candidate
181
+ if (typeof meta.iconUrl === "string") {
182
+ const rewritten = rewriteIconHost(meta.iconUrl, devUrl, candidate)
183
+ if (rewritten) meta.iconUrl = rewritten
184
+ }
185
+ storage.save(`${packageName}_dev_meta`, JSON.stringify(meta))
186
+ } catch {
187
+ /* ignore malformed meta */
188
+ }
189
+ }
190
+ }
61
191
  }
62
- return {decision: "live", manifest}
63
- } catch {
64
- return {decision: "offline", manifest: null}
65
- } finally {
66
- clearTimeout(timer)
192
+ return {decision: "live", manifest: result, resolvedUrl: candidate}
67
193
  }
194
+
195
+ return {decision: "offline", manifest: null}
68
196
  }
@@ -4,11 +4,14 @@ import * as Location from "expo-location"
4
4
  import {Platform} from "react-native"
5
5
  import type {ReportContext} from "@mentra/cloud-client"
6
6
 
7
- import {useAppStatusStore} from "../stores/apps"
7
+ import appRegistry from "../services/AppRegistry"
8
+ import localMiniappRuntime from "../services/LocalMiniappRuntime"
9
+ import {getLastOpenTime, useAppStatusStore} from "../stores/apps"
8
10
  import {useConnectionStore} from "../stores/connection"
9
11
  import {useCoreStore} from "../stores/core"
10
12
  import {useGlassesStore} from "../stores/glasses"
11
13
  import {SETTINGS, useSettingsStore} from "../stores/settings"
14
+ import {buildMiniappDiagnosticContext} from "./miniappDiagnostics"
12
15
 
13
16
  const SENSITIVE_SETTINGS_KEYS = ["core_token", "auth_token", "auth_email"] as const
14
17
  const SENSITIVE_GLASSES_KEYS = ["hotspotPassword"] as const
@@ -108,17 +111,17 @@ export async function collectDiagnosticContext(extra?: Partial<ReportContext>):
108
111
 
109
112
  const offlineMode = await useSettingsStore.getState().getSetting(SETTINGS.offline_mode.key)
110
113
  const defaultWearable = await useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key)
111
- const apps = appletState.apps.map((app) => ({
112
- packageName: app.packageName,
113
- name: app.name,
114
- running: app.running,
115
- loading: app.loading,
116
- healthy: app.healthy,
117
- hidden: app.hidden,
118
- type: app.type,
119
- offline: app.offline,
120
- local: app.local,
121
- }))
114
+ const miniappRuntime = localMiniappRuntime.getDiagnosticSnapshot()
115
+ const miniapps = buildMiniappDiagnosticContext({
116
+ apps: appletState.apps,
117
+ foregroundedPackage: appletState.foregroundedPackage,
118
+ runtime: miniappRuntime,
119
+ getLastOpenedAtMs: (app) => getLastOpenTime(app.packageName),
120
+ getManifest: (app) =>
121
+ app.local && app.version ? appRegistry.getMiniappManifest(app.packageName, app.version) : undefined,
122
+ getReleaseIdentity: (app) =>
123
+ app.local && app.version ? appRegistry.getReleaseIdentity(app.packageName, app.version) : undefined,
124
+ })
122
125
 
123
126
  return {
124
127
  app: {
@@ -139,12 +142,9 @@ export async function collectDiagnosticContext(extra?: Partial<ReportContext>):
139
142
  runtime: {
140
143
  core: coreState,
141
144
  connection: connectionState,
145
+ miniapps: miniappRuntime,
142
146
  },
143
- apps: {
144
- apps,
145
- installed: apps.map((app) => app.packageName),
146
- running: apps.filter((app) => app.running).map((app) => app.packageName),
147
- },
147
+ apps: miniapps,
148
148
  settings: {
149
149
  ...filteredSettings,
150
150
  offlineMode: !!offlineMode,
@@ -1,11 +1,4 @@
1
- import {
2
- Capabilities,
3
- HardwareRequirement,
4
- HardwareType,
5
- HardwareRequirementLevel,
6
- DeviceTypes,
7
- } from "../../types"
8
- import {simulatedGlasses} from "../../types"
1
+ import {Capabilities, DeviceTypes, HardwareRequirement, HardwareRequirementLevel, HardwareType, simulatedGlasses} from "../../types"
9
2
 
10
3
  /**
11
4
  * Result of a hardware compatibility check
@@ -86,7 +79,12 @@ export class HardwareCompatibility {
86
79
  return capabilities.hasDisplay
87
80
 
88
81
  case HardwareType.MICROPHONE:
89
- return capabilities.hasMicrophone
82
+ // MentraOS always provides an audio-input path. When the connected
83
+ // glasses do not have an onboard microphone, the engine falls back to
84
+ // the phone microphone. Keep `capabilities.hasMicrophone` reserved for
85
+ // physical-device/source selection; app compatibility is about whether
86
+ // the requested input is available to the miniapp.
87
+ return true
90
88
 
91
89
  case HardwareType.SPEAKER:
92
90
  return capabilities.hasSpeaker
@@ -0,0 +1,226 @@
1
+ import type {ClientApp} from "../types/applet"
2
+
3
+ const MAX_DIAGNOSTIC_STRING_LENGTH = 512
4
+ const MAX_DIAGNOSTIC_LIST_ITEMS = 100
5
+ const MAX_RECENT_MINIAPPS = 20
6
+
7
+ export interface MiniappManifestSnapshot {
8
+ packageName: string
9
+ name?: string
10
+ version?: string
11
+ sdkVersion?: string
12
+ minHostVersion?: string
13
+ type?: string
14
+ entry?: {
15
+ background?: string
16
+ ui?: string
17
+ }
18
+ permissions: Array<{type: string; required?: boolean}>
19
+ hardwareRequirements: Array<{type: string; level: string}>
20
+ actionIds: string[]
21
+ }
22
+
23
+ export interface MiniappRuntimeAppSnapshot {
24
+ packageName: string
25
+ handshakeComplete: boolean
26
+ subscriptions: string[]
27
+ lastMessageAgeMs: number
28
+ requestedLocationRate: string | null
29
+ hasActiveSpeakerStream: boolean
30
+ manifest?: MiniappManifestSnapshot
31
+ }
32
+
33
+ export interface MiniappRuntimeDiagnosticSnapshot {
34
+ connectedApps: MiniappRuntimeAppSnapshot[]
35
+ subscriptionsByStream: Record<string, string[]>
36
+ resources: {
37
+ display: Record<string, unknown>
38
+ camera: Record<string, unknown>
39
+ video: Record<string, unknown>
40
+ stream: Record<string, unknown>
41
+ cameraFov: Record<string, unknown>
42
+ }
43
+ }
44
+
45
+ type ManifestFallback = {
46
+ packageName: string
47
+ name?: string
48
+ version?: string
49
+ type?: string
50
+ }
51
+
52
+ function boundedString(value: unknown): string | undefined {
53
+ if (typeof value !== "string") return undefined
54
+ const trimmed = value.trim()
55
+ if (!trimmed) return undefined
56
+ return trimmed.slice(0, MAX_DIAGNOSTIC_STRING_LENGTH)
57
+ }
58
+
59
+ function recordValue(value: unknown): Record<string, unknown> | null {
60
+ return value && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : null
61
+ }
62
+
63
+ function diagnosticPermissions(value: unknown): Array<{type: string; required?: boolean}> {
64
+ if (!Array.isArray(value)) return []
65
+ const permissions: Array<{type: string; required?: boolean}> = []
66
+ for (const raw of value) {
67
+ if (typeof raw === "string") {
68
+ const type = boundedString(raw)
69
+ if (type) permissions.push({type})
70
+ continue
71
+ }
72
+ const permission = recordValue(raw)
73
+ const type = boundedString(permission?.type)
74
+ if (!type) continue
75
+ permissions.push({
76
+ type,
77
+ ...(typeof permission?.required === "boolean" ? {required: permission.required} : {}),
78
+ })
79
+ }
80
+ return permissions.slice(0, MAX_DIAGNOSTIC_LIST_ITEMS)
81
+ }
82
+
83
+ function diagnosticHardwareRequirements(value: unknown): Array<{type: string; level: string}> {
84
+ if (!Array.isArray(value)) return []
85
+ const requirements: Array<{type: string; level: string}> = []
86
+ for (const raw of value) {
87
+ const requirement = recordValue(raw)
88
+ const type = boundedString(requirement?.type)
89
+ const level = boundedString(requirement?.level)
90
+ if (type && level) requirements.push({type, level})
91
+ }
92
+ return requirements.slice(0, MAX_DIAGNOSTIC_LIST_ITEMS)
93
+ }
94
+
95
+ function diagnosticActionIds(value: unknown): string[] {
96
+ if (!Array.isArray(value)) return []
97
+ return value
98
+ .map((raw) => boundedString(typeof raw === "string" ? raw : recordValue(raw)?.id))
99
+ .filter((id): id is string => id !== undefined)
100
+ .sort()
101
+ .slice(0, MAX_DIAGNOSTIC_LIST_ITEMS)
102
+ }
103
+
104
+ /**
105
+ * Keep the routing/build fields from miniapp.json while excluding arbitrary
106
+ * free-form manifest content from reports. Descriptions, URLs, and unknown
107
+ * extension fields are intentionally omitted.
108
+ */
109
+ export function buildMiniappManifestSnapshot(raw: unknown, fallback: ManifestFallback): MiniappManifestSnapshot {
110
+ const manifest = recordValue(raw)
111
+ const entry = recordValue(manifest?.entry)
112
+ const packageName = boundedString(manifest?.packageName) ?? boundedString(fallback.packageName) ?? "unknown"
113
+ const name = boundedString(manifest?.name) ?? boundedString(fallback.name)
114
+ const version = boundedString(manifest?.version) ?? boundedString(fallback.version)
115
+ const type = boundedString(manifest?.type) ?? boundedString(fallback.type)
116
+ const background = boundedString(entry?.background)
117
+ const ui = boundedString(entry?.ui)
118
+
119
+ return {
120
+ packageName,
121
+ ...(name ? {name} : {}),
122
+ ...(version ? {version} : {}),
123
+ ...(boundedString(manifest?.sdkVersion) ? {sdkVersion: boundedString(manifest?.sdkVersion)} : {}),
124
+ ...(boundedString(manifest?.minHostVersion) ? {minHostVersion: boundedString(manifest?.minHostVersion)} : {}),
125
+ ...(type ? {type} : {}),
126
+ ...(background || ui ? {entry: {...(background ? {background} : {}), ...(ui ? {ui} : {})}} : {}),
127
+ permissions: diagnosticPermissions(manifest?.permissions),
128
+ hardwareRequirements: diagnosticHardwareRequirements(manifest?.hardwareRequirements),
129
+ actionIds: diagnosticActionIds(manifest?.actions ?? manifest?.actionIds),
130
+ }
131
+ }
132
+
133
+ function executionMode(app: ClientApp): "built_in" | "dev_server" | "dev_snapshot" | "installed_bundle" {
134
+ if (app.offline) return "built_in"
135
+ if (app.isMiniappDev && app.devUrl && !app.version) return "dev_server"
136
+ if (app.isMiniappDev) return "dev_snapshot"
137
+ return "installed_bundle"
138
+ }
139
+
140
+ function safeReleaseIdentity(value: unknown): Record<string, string> | undefined {
141
+ const identity = recordValue(value)
142
+ if (!identity) return undefined
143
+ const out: Record<string, string> = {}
144
+ for (const key of ["source", "releaseId", "bundleSha256", "channel"] as const) {
145
+ const field = boundedString(identity[key])
146
+ if (field) out[key] = field
147
+ }
148
+ return Object.keys(out).length > 0 ? out : undefined
149
+ }
150
+
151
+ export function buildMiniappDiagnosticContext(input: {
152
+ apps: ClientApp[]
153
+ foregroundedPackage: string | null
154
+ runtime: MiniappRuntimeDiagnosticSnapshot
155
+ getLastOpenedAtMs: (app: ClientApp) => number
156
+ getManifest: (app: ClientApp) => unknown
157
+ getReleaseIdentity: (app: ClientApp) => unknown
158
+ }): Record<string, unknown> {
159
+ const runtimeByPackage = new Map(input.runtime.connectedApps.map((app) => [app.packageName, app]))
160
+ const appSnapshots = input.apps.map((app) => {
161
+ const lastOpenedAtMs = input.getLastOpenedAtMs(app)
162
+ const packageName = boundedString(app.packageName) ?? "unknown"
163
+ return {
164
+ packageName,
165
+ name: boundedString(app.name) ?? packageName,
166
+ version: boundedString(app.version) ?? null,
167
+ executionMode: executionMode(app),
168
+ running: app.running,
169
+ foregrounded: app.packageName === input.foregroundedPackage,
170
+ loading: app.loading,
171
+ healthy: app.healthy,
172
+ hidden: app.hidden,
173
+ type: app.type,
174
+ offline: app.offline,
175
+ local: app.local,
176
+ lastOpenedAtMs: Number.isFinite(lastOpenedAtMs) ? lastOpenedAtMs : 0,
177
+ }
178
+ })
179
+
180
+ const recentlyInteracted = [...appSnapshots]
181
+ .filter((app) => app.lastOpenedAtMs > 0)
182
+ .sort((a, b) => b.lastOpenedAtMs - a.lastOpenedAtMs)
183
+ .slice(0, MAX_RECENT_MINIAPPS)
184
+ .map((app) => ({packageName: app.packageName, lastOpenedAtMs: app.lastOpenedAtMs}))
185
+
186
+ const runningMiniapps = input.apps
187
+ .filter((app) => app.running)
188
+ .map((app) => {
189
+ const runtime = runtimeByPackage.get(app.packageName)
190
+ const releaseIdentity = safeReleaseIdentity(input.getReleaseIdentity(app))
191
+ const packageName = boundedString(app.packageName) ?? "unknown"
192
+ const manifest = buildMiniappManifestSnapshot(input.getManifest(app) ?? runtime?.manifest, {
193
+ packageName,
194
+ name: app.name,
195
+ version: app.version,
196
+ type: app.type,
197
+ })
198
+ return {
199
+ packageName,
200
+ version: boundedString(app.version) ?? manifest.version ?? null,
201
+ executionMode: executionMode(app),
202
+ foregrounded: app.packageName === input.foregroundedPackage,
203
+ manifest,
204
+ ...(releaseIdentity ? {releaseIdentity} : {}),
205
+ runtime: runtime
206
+ ? {
207
+ handshakeComplete: runtime.handshakeComplete,
208
+ subscriptions: runtime.subscriptions,
209
+ lastMessageAgeMs: runtime.lastMessageAgeMs,
210
+ requestedLocationRate: runtime.requestedLocationRate,
211
+ hasActiveSpeakerStream: runtime.hasActiveSpeakerStream,
212
+ }
213
+ : null,
214
+ }
215
+ })
216
+
217
+ return {
218
+ apps: appSnapshots,
219
+ installed: appSnapshots.map((app) => app.packageName),
220
+ running: runningMiniapps.map((app) => app.packageName),
221
+ foregroundedPackage: boundedString(input.foregroundedPackage) ?? null,
222
+ mostRecentlyInteractedPackage: recentlyInteracted[0]?.packageName ?? null,
223
+ recentlyInteracted,
224
+ runningMiniapps,
225
+ }
226
+ }
@@ -5,6 +5,14 @@ import CrustModule from "@mentra/crust"
5
5
 
6
6
  import {deriveGalleryDisplayName} from "./galleryDisplayName"
7
7
 
8
+ export interface MediaLibrarySaveReceipt {
9
+ success: boolean
10
+ platform: "ios" | "android" | "unknown"
11
+ uri?: string
12
+ identifier?: string
13
+ error?: string
14
+ }
15
+
8
16
  /**
9
17
  * MediaLibraryPermissions - Handles save-only permissions for camera roll
10
18
  *
@@ -14,6 +22,18 @@ import {deriveGalleryDisplayName} from "./galleryDisplayName"
14
22
  * - Android 9-: Uses WRITE_EXTERNAL_STORAGE (legacy)
15
23
  */
16
24
  export class MediaLibraryPermissions {
25
+ /** Limited iOS access cannot see historical, unselected assets for duplicate reconciliation. */
26
+ static async hasLimitedAccess(): Promise<boolean> {
27
+ if (Platform.OS !== "ios") return false
28
+ try {
29
+ return (await check(PERMISSIONS.IOS.PHOTO_LIBRARY)) === RESULTS.LIMITED
30
+ } catch (error) {
31
+ console.error("[MediaLibrary] Error checking limited-library access:", error)
32
+ // Conservatively block legacy reconciliation when the scope cannot be verified.
33
+ return true
34
+ }
35
+ }
36
+
17
37
  /**
18
38
  * Check if we have permission to save to the camera roll
19
39
  * Note: On Android 10+, this always returns true since no permission is needed
@@ -85,6 +105,12 @@ export class MediaLibraryPermissions {
85
105
  * @param creationTime - Optional creation/capture time in milliseconds (Unix timestamp)
86
106
  */
87
107
  static async saveToLibrary(filePath: string, creationTime?: number): Promise<boolean> {
108
+ return (await this.saveToLibraryWithReceipt(filePath, creationTime)).success
109
+ }
110
+
111
+ /** Save and return the durable MediaStore/PhotoKit identifier used as the export receipt. */
112
+ static async saveToLibraryWithReceipt(filePath: string, creationTime?: number): Promise<MediaLibrarySaveReceipt> {
113
+ const platform = Platform.OS === "ios" || Platform.OS === "android" ? Platform.OS : "unknown"
88
114
  try {
89
115
  // On Android 10+, we can save without permission
90
116
  // On iOS and older Android, check permission first
@@ -95,7 +121,7 @@ export class MediaLibraryPermissions {
95
121
  const granted = await this.requestPermission()
96
122
  if (!granted) {
97
123
  console.warn("[MediaLibrary] No permission to save to library - photos saved to app storage only")
98
- return false
124
+ return {success: false, platform, error: "permission denied"}
99
125
  }
100
126
  }
101
127
  }
@@ -117,14 +143,19 @@ export class MediaLibraryPermissions {
117
143
  } else {
118
144
  console.log(`[MediaLibrary] Saved to camera roll: ${cleanPath}`)
119
145
  }
120
- return true
146
+ return {
147
+ success: true,
148
+ platform,
149
+ uri: result.uri,
150
+ identifier: result.identifier,
151
+ }
121
152
  } else {
122
153
  console.error(`[MediaLibrary] Failed to save to library: ${result.error}`)
123
- return false
154
+ return {success: false, platform, error: result.error || "native export failed"}
124
155
  }
125
156
  } catch (error) {
126
157
  console.error("[MediaLibrary] Error saving to library:", error)
127
- return false
158
+ return {success: false, platform, error: error instanceof Error ? error.message : String(error)}
128
159
  }
129
160
  }
130
161
  }