@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
@@ -0,0 +1,7 @@
1
+ export {
2
+ MentraLiveOtaFlow,
3
+ type MentraLiveOtaFlowPage,
4
+ type MentraLiveOtaFlowProps,
5
+ type MentraLiveOtaFlowTheme,
6
+ type MentraLiveOtaFlowTranslate,
7
+ } from "./MentraLiveOtaFlow"
@@ -0,0 +1,16 @@
1
+ import {useEffect, useRef, useState} from "react"
2
+
3
+ export function useEngineSnapshot<T>(getSnapshot: () => T, subscribe: (onChange: () => void) => () => void): T {
4
+ const getSnapshotRef = useRef(getSnapshot)
5
+ const subscribeRef = useRef(subscribe)
6
+ getSnapshotRef.current = getSnapshot
7
+ subscribeRef.current = subscribe
8
+ const [snapshot, setSnapshot] = useState(() => getSnapshot())
9
+
10
+ useEffect(() => {
11
+ setSnapshot(getSnapshotRef.current())
12
+ return subscribeRef.current(() => setSnapshot(getSnapshotRef.current()))
13
+ }, [])
14
+
15
+ return snapshot
16
+ }
@@ -50,9 +50,22 @@ export interface IslandUiSeams {
50
50
  * `session.glasses.requestWifiSetup` — open the host's glasses Wi-Fi setup
51
51
  * flow. Absent ⇒ miniapps get NOT_IMPLEMENTED for the request.
52
52
  */
53
- requestWifiSetup?: (reason?: string) => Promise<void> | void
53
+ requestWifiSetup?: (reason?: string, packageName?: string) => Promise<void> | void
54
+ /**
55
+ * `session.system.scanQr` — open a phone-camera QR scanner overlay. Must NOT
56
+ * clear miniapp foreground: UI_CLOSE on a live call hangs it up. Absent ⇒
57
+ * miniapps get NOT_IMPLEMENTED.
58
+ */
59
+ scanQr?: (options?: ScanQrOptions) => Promise<ScanQrResult>
60
+ }
61
+
62
+ export interface ScanQrOptions {
63
+ title?: string
64
+ hint?: string
54
65
  }
55
66
 
67
+ export type ScanQrResult = {data: string} | {cancelled: true}
68
+
56
69
  export interface IslandConfigureOptions {
57
70
  /** REQUIRED — the only must-have seam. The host owns login; engine owns the rest. */
58
71
  auth: IslandAuth
@@ -81,6 +94,19 @@ export function configure(opts: IslandConfigureOptions): void {
81
94
  options = opts
82
95
  }
83
96
 
97
+ /**
98
+ * Merge host-UI seams after configure/start. UI capabilities (scan overlay,
99
+ * wifi setup) are looked up per request, so this is safe on a running runtime.
100
+ * Used so Metro reloads can attach seams that missed the original configure().
101
+ */
102
+ export function updateUiSeams(ui: IslandUiSeams): void {
103
+ if (!options) {
104
+ console.warn("engine.updateUiSeams() called before engine.configure(); ignored")
105
+ return
106
+ }
107
+ options = {...options, ui: {...options.ui, ...ui}}
108
+ }
109
+
84
110
  /** Mark the runtime started. Idempotent. */
85
111
  export async function start(): Promise<void> {
86
112
  if (started) return
@@ -99,6 +125,12 @@ export function isStarted(): boolean {
99
125
  return started
100
126
  }
101
127
 
128
+ /** Test-only: wipe configure state so suites can start from a cold host. */
129
+ export function resetForTests(): void {
130
+ options = null
131
+ started = false
132
+ }
133
+
102
134
  /** The host-supplied auth provider, or null if not configured yet. */
103
135
  export function getAuth(): IslandAuth | null {
104
136
  return options?.auth ?? null
@@ -0,0 +1,20 @@
1
+ import type {ScanQrOptions, ScanQrResult} from "./bootstrap"
2
+
3
+ export class ScanQrNotConfiguredError extends Error {
4
+ readonly code = "NOT_IMPLEMENTED"
5
+ constructor() {
6
+ super("QR scanning is not configured on this host. Reload the Mentra App and try again.")
7
+ this.name = "ScanQrNotConfiguredError"
8
+ }
9
+ }
10
+
11
+ export async function invokeScanQrSeam(
12
+ scanQr: ((options?: ScanQrOptions) => Promise<ScanQrResult>) | undefined,
13
+ payload: Record<string, unknown> = {},
14
+ ): Promise<ScanQrResult> {
15
+ if (!scanQr) throw new ScanQrNotConfiguredError()
16
+ return scanQr({
17
+ title: typeof payload.title === "string" ? payload.title : undefined,
18
+ hint: typeof payload.hint === "string" ? payload.hint : undefined,
19
+ })
20
+ }
@@ -22,14 +22,17 @@ import {unzip} from "react-native-zip-archive"
22
22
  import semver from "semver"
23
23
  import {AsyncResult, Result, result as Res} from "typesafe-ts"
24
24
 
25
- import type {AppletPermission, AppPermissionType, AppletType, ClientApp, DeclaredAction} from "../types/applet"
25
+ import type {AppletPermission, AppPermissionType, AppletType, ClientApp} from "../types/applet"
26
26
  import {HardwareRequirement, HardwareRequirementLevel, HardwareType} from "../types"
27
- import {getConfigValues} from "../runtime/bootstrap"
27
+ import {configuredDevHost} from "../utils/configuredDevHost"
28
28
  import {storage} from "../utils/storage/storage"
29
29
  import {printDirectory} from "../utils/storage/zip"
30
30
  import {checkManifestVersions} from "./manifestVersionGate"
31
+ import {normalizeManifestActions} from "./manifestActions"
31
32
  import {miniappRunningRegistry} from "./MiniappRunningRegistry"
32
33
 
34
+ export {normalizeManifestActions} from "./manifestActions"
35
+
33
36
  const ALLOWED_PERMISSION_TYPES: ReadonlySet<AppPermissionType> = new Set<AppPermissionType>([
34
37
  "MICROPHONE",
35
38
  "CAMERA",
@@ -73,29 +76,6 @@ function normalizeManifestType(raw: unknown): AppletType {
73
76
  return raw === "background" || raw === "system_dashboard" || raw === "standard" ? raw : "standard"
74
77
  }
75
78
 
76
- /**
77
- * Normalize a manifest's `actions` into DeclaredAction[]. Defensive — keeps only
78
- * well-formed `{id, description}` entries (installed/dev bundles may be
79
- * malformed). Shared by installed (disk) and dev-sideload projection so both
80
- * surface declared actions to session.miniapps.list + the invoke gate.
81
- */
82
- export function normalizeManifestActions(raw: unknown): DeclaredAction[] {
83
- if (!Array.isArray(raw)) return []
84
- const out: DeclaredAction[] = []
85
- for (const a of raw as Array<{id?: unknown; description?: unknown; parameters?: unknown}>) {
86
- if (a && typeof a.id === "string" && typeof a.description === "string") {
87
- out.push({
88
- id: a.id,
89
- description: a.description,
90
- ...(a.parameters && typeof a.parameters === "object"
91
- ? {parameters: a.parameters as Record<string, unknown>}
92
- : {}),
93
- })
94
- }
95
- }
96
- return out
97
- }
98
-
99
79
  /**
100
80
  * Convert declared hardwareRequirements from a miniapp.json manifest into
101
81
  * runtime `HardwareRequirement[]`, always appending `{EXIST, REQUIRED}` so
@@ -159,6 +139,17 @@ interface InstalledLma {
159
139
  versions: Record<string, InstalledInfo>
160
140
  }
161
141
 
142
+ export interface MiniappReleaseIdentity {
143
+ source: "direct_download" | "bundled_asset" | "preinstalled_registry" | "dev_snapshot"
144
+ releaseId?: string
145
+ bundleSha256?: string
146
+ channel?: string
147
+ }
148
+
149
+ function releaseIdentityKey(packageName: string, version: string): string {
150
+ return `miniapp_release_identity:${packageName}:${version}`
151
+ }
152
+
162
153
  /**
163
154
  * Download a miniapp zip from `url` into the cache and return its local path.
164
155
  *
@@ -451,11 +442,18 @@ class AppRegistry {
451
442
  * of `manifest.version`. The dev caching path uses `dev-<ms>` so multiple
452
443
  * snapshots can coexist alongside semver-installed versions.
453
444
  */
454
- public installFromUrl(url: string, opts?: {versionOverride?: string}): AsyncResult<void, Error> {
445
+ public installFromUrl(
446
+ url: string,
447
+ opts?: {versionOverride?: string; releaseIdentity?: MiniappReleaseIdentity},
448
+ ): AsyncResult<void, Error> {
455
449
  return Res.try_async(async () => {
456
450
  const {packageName, version} = await downloadAndInstallMiniApp(url, opts?.versionOverride)
457
451
  console.log("APP_REGISTRY: Downloaded and installed mini app")
458
- this.finalizeInstall(packageName, version)
452
+ this.finalizeInstall(
453
+ packageName,
454
+ version,
455
+ opts?.releaseIdentity ?? {source: version.startsWith("dev-") ? "dev_snapshot" : "direct_download"},
456
+ )
459
457
  })
460
458
  }
461
459
 
@@ -468,12 +466,12 @@ class AppRegistry {
468
466
  */
469
467
  public installFromLocalZip(
470
468
  zipPath: string,
471
- opts?: {versionOverride?: string},
469
+ opts?: {versionOverride?: string; releaseIdentity?: MiniappReleaseIdentity},
472
470
  ): AsyncResult<{packageName: string; version: string}, Error> {
473
471
  return Res.try_async(async () => {
474
472
  const {packageName, version} = await unpackMiniApp(zipPath, opts?.versionOverride)
475
473
  console.log("APP_REGISTRY: Installed mini app from local zip")
476
- this.finalizeInstall(packageName, version)
474
+ this.finalizeInstall(packageName, version, opts?.releaseIdentity ?? {source: "bundled_asset"})
477
475
  return {packageName, version}
478
476
  })
479
477
  }
@@ -483,7 +481,7 @@ class AppRegistry {
483
481
  * artifacts on release installs, point the active-version at the just-
484
482
  * installed bundle, and notify subscribers to refresh.
485
483
  */
486
- private finalizeInstall(packageName: string, version: string): void {
484
+ private finalizeInstall(packageName: string, version: string, releaseIdentity: MiniappReleaseIdentity): void {
487
485
  // If this is a release install (semver, not dev-*) of a package that
488
486
  // currently has dev-* snapshots, clear the dev state so the swap to
489
487
  // "released" is clean. Otherwise the dev version would keep winning
@@ -495,10 +493,16 @@ class AppRegistry {
495
493
  }
496
494
 
497
495
  this.setActiveVersion(packageName, version)
496
+ storage.save(releaseIdentityKey(packageName, version), releaseIdentity)
498
497
  this.refreshNeeded = true
499
498
  this.notify()
500
499
  }
501
500
 
501
+ public getReleaseIdentity(packageName: string, version: string): MiniappReleaseIdentity | null {
502
+ const result = storage.load<MiniappReleaseIdentity>(releaseIdentityKey(packageName, version))
503
+ return result.is_ok() ? result.value : null
504
+ }
505
+
502
506
  public installFromJsonUrl(baseUrl: string): AsyncResult<{packageName: string; version: string; name: string}, Error> {
503
507
  return Res.try_async(async () => {
504
508
  const trimmed = baseUrl.replace(/\/$/, "")
@@ -534,6 +538,7 @@ class AppRegistry {
534
538
  for (const item of pkgDir.list()) {
535
539
  if (item instanceof Directory && item.name.startsWith("dev-")) {
536
540
  try {
541
+ storage.remove(releaseIdentityKey(packageName, item.name))
537
542
  item.delete()
538
543
  } catch (e) {
539
544
  console.warn(`APP_REGISTRY: failed to delete ${item.name}:`, e)
@@ -546,17 +551,12 @@ class AppRegistry {
546
551
  }
547
552
  storage.remove(`${packageName}_dev_url`)
548
553
  storage.remove(`${packageName}_dev_port`)
554
+ storage.remove(`${packageName}_dev_mdns`)
549
555
  storage.remove(`${packageName}_dev_last_reachable`)
550
- // Drop the single dev slot's home-tile metadata + dev URL/port keys (all stored under
551
- // DEV_APP_PACKAGE_NAME, not `packageName`). Dev miniapps load over HTTP and aren't on disk,
552
- // so without this the projected tile would reappear on the next getInstalledMiniapps() refresh.
553
- //
554
- // Only do this when we're actually touching the dev slot: either the dev package itself, or the
555
- // real manifest package currently occupying the slot. Otherwise a release install/uninstall of
556
- // an UNRELATED package would wipe the active dev tile.
557
- if (packageName === DEV_APP_PACKAGE_NAME || packageName === getDevAppSourcePackage()) {
558
- unregisterDevApp()
559
- }
556
+ // HTTP-direct dev miniapps are indexed by their real package name. A
557
+ // release install/uninstall of that same package should remove only its
558
+ // dev tile; unrelated dev miniapps must remain available.
559
+ if (readDevAppRecord(packageName)) unregisterDevApp(packageName)
560
560
  }
561
561
 
562
562
  /**
@@ -594,12 +594,16 @@ class AppRegistry {
594
594
  // Guard exists: a dev miniapp loads over HTTP and has no on-disk dir,
595
595
  // so an unconditional delete() would throw and abort the cleanup below.
596
596
  if (lmaDir.exists) lmaDir.delete()
597
+ storage.remove(releaseIdentityKey(packageName, version))
597
598
  console.log("APP_REGISTRY: Uninstalled mini app version", version)
598
599
  const packageDir = new Directory(Paths.document, "lmas", packageName)
599
600
  if (packageDir.exists && packageDir.list().length === 0) {
600
601
  packageDir.delete()
601
602
  }
602
603
  } else {
604
+ for (const installedVersion of this.getInstalledVersions(packageName)) {
605
+ storage.remove(releaseIdentityKey(packageName, installedVersion))
606
+ }
603
607
  const packageDir = new Directory(Paths.document, "lmas", packageName)
604
608
  if (packageDir.exists) {
605
609
  packageDir.delete()
@@ -698,25 +702,21 @@ class AppRegistry {
698
702
  return out
699
703
  }
700
704
 
701
- /**
702
- * Read the lmas/ tree and return one ClientApp per installed package,
703
- * picking each package's active version. The store/host overlays runtime
704
- * state (loading, hidden, compatibility) on top of these.
705
- *
706
- * `running` reflects MiniappHost mount state via miniappRunningRegistry.
707
- */
708
705
  /**
709
706
  * Merge disk-derived apps with the projected dev + offline layers,
710
- * de-duping by packageName. A real on-disk install (or offline app) wins
711
- * over a dev tile of the same package a dev record is just a launcher
712
- * stub that an actual install supersedes.
707
+ * de-duping by packageName. An active dev registration wins over an older
708
+ * disk install of the same package; installing a release clears that dev
709
+ * registration in finalizeInstall. Native offline apps keep top priority.
713
710
  */
714
711
  private mergeProjectedApps(diskApps: ClientApp[]): ClientApp[] {
715
- const seen = new Set(diskApps.map((a) => a.packageName))
716
712
  const offline = this.projectOfflineApps()
717
- for (const a of offline) seen.add(a.packageName)
718
- const dev = this.projectDevApps().filter((a) => !seen.has(a.packageName))
719
- return [...diskApps, ...dev, ...offline]
713
+ const offlinePackages = new Set(offline.map((app) => app.packageName))
714
+ const dev = this.projectDevApps().filter((app) => !offlinePackages.has(app.packageName))
715
+ const devPackages = new Set(dev.map((app) => app.packageName))
716
+ const installed = diskApps.filter(
717
+ (app) => !offlinePackages.has(app.packageName) && !devPackages.has(app.packageName),
718
+ )
719
+ return [...installed, ...dev, ...offline]
720
720
  }
721
721
 
722
722
  public async getInstalledMiniapps(): Promise<ClientApp[]> {
@@ -742,7 +742,7 @@ class AppRegistry {
742
742
  permissions?: Array<string | {type: string; required?: boolean; description?: string}>
743
743
  hardwareRequirements?: Array<{type: string; level: string; description?: string}>
744
744
  type?: string
745
- actions?: Array<{id?: unknown; description?: unknown; parameters?: unknown}>
745
+ actions?: Array<{id?: unknown; description?: unknown; parameters?: unknown; outputSchema?: unknown}>
746
746
  } | null
747
747
 
748
748
  const permissions = normalizeManifestPermissions(manifest?.permissions)
@@ -871,6 +871,22 @@ class AppRegistry {
871
871
  this.notify()
872
872
  }
873
873
 
874
+ /**
875
+ * Update whether a registered offline app is projected into launcher UIs.
876
+ *
877
+ * Offline apps are registered once at host startup, so settings-backed
878
+ * visibility changes need to update the projection without reinstalling or
879
+ * duplicating the app. No-op when the app is missing or already matches.
880
+ */
881
+ public setOfflineAppHidden(packageName: string, hidden: boolean): void {
882
+ const app = this.offlineApps.find((candidate) => candidate.packageName === packageName)
883
+ if (!app || app.hidden === hidden) return
884
+
885
+ app.hidden = hidden
886
+ this.refreshNeeded = true
887
+ this.notify()
888
+ }
889
+
874
890
  /**
875
891
  * Registered as needing the on-device STT model before it can start (the
876
892
  * host declares this per offline app; the apps store gates start() on it).
@@ -940,43 +956,30 @@ export interface DevAppRecord {
940
956
  iconUrl: string
941
957
  devUrl: string
942
958
  devPort?: number
959
+ /**
960
+ * Bonjour / mDNS hostname from the QR (`ComputerName.local`). Used as a
961
+ * failover host when the raw LAN IP in `devUrl` goes stale after a Wi-Fi
962
+ * change — phones that resolve `.local` can relaunch without re-scanning.
963
+ */
964
+ mdnsHost?: string
943
965
  type?: AppletType
944
966
  permissions?: Array<string | {type: string; required?: boolean; description?: string}>
945
967
  hardwareRequirements?: Array<{type: string; level: string; description?: string}>
946
968
  /** Manifest-declared actions — so dev-sideloaded miniapps can be invoked too. */
947
- actions?: Array<{id?: unknown; description?: unknown; parameters?: unknown}>
948
- /**
949
- * The dev miniapp's real manifest package name. `packageName` is overwritten to
950
- * {@link DEV_APP_PACKAGE_NAME} so the launch chain routes consistently, so this field
951
- * preserves the original so install/uninstall of OTHER packages don't wipe the dev slot.
952
- */
969
+ actions?: Array<{id?: unknown; description?: unknown; parameters?: unknown; outputSchema?: unknown}>
970
+ /** Legacy single-slot migration field. New records use the real packageName directly. */
953
971
  sourcePackageName?: string
954
972
  /**
955
973
  * Short-lived Core-verifiable proof emitted by `mentra dev`. This lets the
956
- * single `com.dev` slot request auto-auth for the real package without
957
- * letting arbitrary dev URLs claim any package name.
974
+ * dev runtime request auto-auth for the manifest package without letting
975
+ * arbitrary dev URLs claim any package name.
958
976
  */
959
977
  devAttestation?: string
960
978
  }
961
979
 
962
980
  const DEV_APPS_INDEX_KEY = "dev_apps_index"
981
+ const DEV_APP_ICONS_DIR = "dev-miniapp-icons"
963
982
 
964
- function configuredDevHost(): string | undefined {
965
- // Explicit escape hatch first; otherwise the host-injected Metro host (the
966
- // address this dev bundle was served from — always current for the network
967
- // the phone is on). Deliberately NOT the EXPO_PUBLIC_CLOUD_* URLs: those are
968
- // cloud endpoints, a different machine entirely from the laptop running the
969
- // miniapp dev server, and rewriting a dev URL to a cloud host would break it.
970
- const explicit = process.env.EXPO_PUBLIC_LOCAL_MINIAPP_HOST
971
- if (explicit) {
972
- try {
973
- return new URL(explicit).hostname
974
- } catch {
975
- if (/^[\w.-]+$/.test(explicit)) return explicit
976
- }
977
- }
978
- return getConfigValues().devServerHost?.()
979
- }
980
983
 
981
984
  function isPrivateLanHost(hostname: string): boolean {
982
985
  return (
@@ -1008,72 +1011,173 @@ function normalizeDevAppRecord(record: DevAppRecord): DevAppRecord {
1008
1011
  return devUrl === record.devUrl && iconUrl === record.iconUrl ? record : {...record, devUrl, iconUrl}
1009
1012
  }
1010
1013
 
1011
- /**
1012
- * The one and only package name a dev miniapp is registered under.
1013
- *
1014
- * There is a SINGLE dev slot: scanning a new QR (or entering a new dev URL)
1015
- * replaces the previous dev app rather than adding a second tile. Because the
1016
- * whole launch chain — JSContext registration, UI-router binding,
1017
- * setForeground, dev_url/dev_port storage keys, respawn-bg lookup — keys on
1018
- * this package name, every consumer MUST use `DEV_APP_PACKAGE_NAME` (not the
1019
- * manifest's real packageName) so messages route consistently. Mixing the two
1020
- * was the cause of the "CONNECT_ACK timeout" — the tile said `com.dev` while
1021
- * the dev URL/port and foreground target used the manifest name.
1022
- */
1014
+ /** Legacy package used by builds that supported only one dev miniapp. */
1023
1015
  export const DEV_APP_PACKAGE_NAME = "com.dev"
1024
1016
  export const DEV_APP_NAME = "Dev"
1025
1017
 
1026
1018
  /**
1027
- * Register (or replace) THE dev miniapp. Persists the home-tile metadata AND
1028
- * the dev_url/dev_port keyed on {@link DEV_APP_PACKAGE_NAME}, so this function
1029
- * is the single source of truth for the dev slot — callers must not write the
1030
- * `*_dev_url` / `*_dev_port` keys under the manifest's real package name.
1031
- *
1032
- * Callers pass the manifest's REAL packageName/name. Only the packageName is
1033
- * forced to {@link DEV_APP_PACKAGE_NAME} so the home tile and launch chain key
1034
- * on the single dev slot (the real package survives in `sourcePackageName` for
1035
- * clearDevArtifacts). The name + icon are kept as-is so the home tile reflects
1036
- * the actual dev miniapp — marked as dev by the {@link DevMiniappBadge} dot
1037
- * rather than renamed to a generic "Dev" tile.
1019
+ * Copy a dev-server icon into Documents so the tile remains branded after the
1020
+ * laptop/server disappears. A failed download is non-fatal: the remote URL is
1021
+ * retained and can still render while the server is reachable.
1038
1022
  */
1039
- export function registerDevApp(record: DevAppRecord): void {
1023
+ async function cacheDevAppIcon(packageName: string, iconUrl: string): Promise<string> {
1024
+ if (!/^https?:\/\//.test(iconUrl)) return iconUrl
1025
+
1026
+ try {
1027
+ const dir = new Directory(Paths.document, DEV_APP_ICONS_DIR)
1028
+ if (!dir.exists) dir.create({intermediates: true})
1029
+
1030
+ const safePackageName = packageName.replace(/[^a-zA-Z0-9._-]/g, "_")
1031
+ let extension = ".png"
1032
+ try {
1033
+ const match = new URL(iconUrl).pathname.match(/\.(png|jpe?g|webp|gif|svg)$/i)
1034
+ if (match) extension = `.${match[1].toLowerCase()}`
1035
+ } catch {
1036
+ // Keep the decoder-friendly .png fallback; image loaders sniff content.
1037
+ }
1038
+
1039
+ const target = new File(dir, `${safePackageName}${extension}`)
1040
+ const downloaded = await File.downloadFileAsync(iconUrl, target, {idempotent: true})
1041
+
1042
+ // Only remove older extensions AFTER the replacement is safely on disk;
1043
+ // a broken icon URL must not destroy the last known-good cached logo.
1044
+ for (const item of dir.list()) {
1045
+ if (item instanceof File && item.uri !== downloaded.uri && item.name.startsWith(`${safePackageName}.`)) {
1046
+ try {
1047
+ item.delete()
1048
+ } catch {
1049
+ // Best effort; the current icon has already been persisted.
1050
+ }
1051
+ }
1052
+ }
1053
+ return downloaded.uri
1054
+ } catch (error) {
1055
+ console.warn(`APP_REGISTRY: failed to cache dev icon for ${packageName}:`, error)
1056
+ return readDevAppRecord(packageName)?.iconUrl ?? iconUrl
1057
+ }
1058
+ }
1059
+
1060
+ function removeDevRecordKeys(packageName: string): void {
1061
+ const existing = readDevAppRecord(packageName)
1062
+ if (existing?.iconUrl.startsWith("file://")) {
1063
+ try {
1064
+ const icon = new File(existing.iconUrl)
1065
+ if (icon.exists) icon.delete()
1066
+ } catch (error) {
1067
+ console.warn(`APP_REGISTRY: failed to delete dev icon for ${packageName}:`, error)
1068
+ }
1069
+ }
1070
+ storage.remove(`${packageName}_dev_meta`)
1071
+ storage.remove(`${packageName}_dev_url`)
1072
+ storage.remove(`${packageName}_dev_port`)
1073
+ storage.remove(`${packageName}_dev_mdns`)
1074
+ storage.remove(`${packageName}_dev_last_reachable`)
1075
+ }
1076
+
1077
+ function readDevAppRecord(packageName: string): DevAppRecord | null {
1078
+ const res = storage.load<string>(`${packageName}_dev_meta`)
1079
+ if (!res.is_ok()) return null
1080
+ try {
1081
+ return JSON.parse(res.value) as DevAppRecord
1082
+ } catch {
1083
+ return null
1084
+ }
1085
+ }
1086
+
1087
+ /** Move the historical `com.dev` record onto its real manifest package key. */
1088
+ function migrateLegacyDevSlot(): void {
1089
+ const legacy = readDevAppRecord(DEV_APP_PACKAGE_NAME)
1090
+ const targetPackage = legacy?.sourcePackageName?.trim()
1091
+ if (!legacy || !targetPackage || targetPackage === DEV_APP_PACKAGE_NAME) return
1092
+
1093
+ const existingTarget = readDevAppRecord(targetPackage)
1094
+ const migrated: DevAppRecord = existingTarget ?? {
1095
+ ...legacy,
1096
+ packageName: targetPackage,
1097
+ sourcePackageName: targetPackage,
1098
+ }
1099
+ if (!existingTarget) storage.save(`${targetPackage}_dev_meta`, JSON.stringify(migrated))
1100
+
1101
+ const legacyUrl = storage.load<string>(`${DEV_APP_PACKAGE_NAME}_dev_url`)
1102
+ const targetUrl = storage.load<string>(`${targetPackage}_dev_url`)
1103
+ if (!targetUrl.is_ok()) {
1104
+ storage.save(`${targetPackage}_dev_url`, legacyUrl.is_ok() ? legacyUrl.value : migrated.devUrl)
1105
+ }
1106
+ const legacyPort = storage.load<number>(`${DEV_APP_PACKAGE_NAME}_dev_port`)
1107
+ const targetPort = storage.load<number>(`${targetPackage}_dev_port`)
1108
+ if (!targetPort.is_ok()) {
1109
+ const port = migrated.devPort ?? (legacyPort.is_ok() ? legacyPort.value : undefined)
1110
+ if (typeof port === "number" && Number.isFinite(port)) storage.save(`${targetPackage}_dev_port`, port)
1111
+ }
1112
+ const legacyMdns = storage.load<string>(`${DEV_APP_PACKAGE_NAME}_dev_mdns`)
1113
+ const targetMdns = storage.load<string>(`${targetPackage}_dev_mdns`)
1114
+ if (!targetMdns.is_ok() && legacyMdns.is_ok() && legacyMdns.value.trim()) {
1115
+ storage.save(`${targetPackage}_dev_mdns`, legacyMdns.value.trim())
1116
+ }
1117
+
1118
+ storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_meta`)
1119
+ storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_url`)
1120
+ storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_port`)
1121
+ storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_mdns`)
1122
+ storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_last_reachable`)
1123
+
1124
+ const index = Array.from(new Set(getDevAppIndex().map((pkg) => (pkg === DEV_APP_PACKAGE_NAME ? targetPackage : pkg))))
1125
+ storage.save(DEV_APPS_INDEX_KEY, JSON.stringify(index))
1126
+ }
1127
+
1128
+ function readStoredMdnsHost(packageName: string): string | undefined {
1129
+ const res = storage.load<string>(`${packageName}_dev_mdns`)
1130
+ if (!res.is_ok()) return undefined
1131
+ return res.value.trim() || undefined
1132
+ }
1133
+
1134
+ /**
1135
+ * Register or update one dev miniapp under its real manifest package. Different
1136
+ * package names coexist; rescanning the same package updates that package only.
1137
+ */
1138
+ export async function registerDevApp(record: DevAppRecord): Promise<void> {
1139
+ migrateLegacyDevSlot()
1140
+ const packageName = record.packageName.trim()
1141
+ if (!packageName) throw new Error("Dev miniapp manifest is missing packageName")
1142
+
1143
+ const iconUrl = await cacheDevAppIcon(packageName, record.iconUrl)
1144
+ // Relaunch paths (developer-URL screen, loadDevMiniapp) omit mdnsHost, so an
1145
+ // omitted field keeps whatever the QR scan stored instead of wiping the
1146
+ // `.local` failover host.
1147
+ const mdnsHost =
1148
+ record.mdnsHost !== undefined ? record.mdnsHost.trim() || undefined : readStoredMdnsHost(packageName)
1040
1149
  const devRecord: DevAppRecord = {
1041
1150
  ...record,
1042
- // Preserve the real manifest package before overwriting packageName with the
1043
- // single dev-slot name, so clearDevArtifacts can tell whether an install/uninstall
1044
- // actually targets the dev slot.
1045
- sourcePackageName: record.sourcePackageName ?? record.packageName,
1046
- packageName: DEV_APP_PACKAGE_NAME,
1047
- // Keep the manifest's real name + icon (display-only; routing keys on
1048
- // packageName). Fall back to DEV_APP_NAME only if a caller omitted the name.
1151
+ packageName,
1152
+ sourcePackageName: packageName,
1049
1153
  name: record.name || DEV_APP_NAME,
1050
- iconUrl: record.iconUrl,
1154
+ iconUrl,
1155
+ mdnsHost,
1051
1156
  }
1052
- storage.save(`${DEV_APP_PACKAGE_NAME}_dev_meta`, JSON.stringify(devRecord))
1053
- // The launch chain (LocalMiniappView.resolveDevPort, mentraJsBootstrap
1054
- // respawn-bg) reads these keys under DEV_APP_PACKAGE_NAME — persist them
1055
- // here so callers can't key them on the wrong (real) package name.
1056
- storage.save(`${DEV_APP_PACKAGE_NAME}_dev_url`, record.devUrl)
1157
+ storage.save(`${packageName}_dev_meta`, JSON.stringify(devRecord))
1158
+ storage.save(`${packageName}_dev_url`, record.devUrl)
1057
1159
  if (typeof record.devPort === "number" && Number.isFinite(record.devPort)) {
1058
- storage.save(`${DEV_APP_PACKAGE_NAME}_dev_port`, record.devPort)
1160
+ storage.save(`${packageName}_dev_port`, record.devPort)
1161
+ } else {
1162
+ storage.remove(`${packageName}_dev_port`)
1163
+ }
1164
+ if (mdnsHost) {
1165
+ storage.save(`${packageName}_dev_mdns`, mdnsHost)
1059
1166
  } else {
1060
- storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_port`)
1167
+ storage.remove(`${packageName}_dev_mdns`)
1061
1168
  }
1062
1169
  const idx = getDevAppIndex()
1063
- if (!idx.includes(DEV_APP_PACKAGE_NAME)) {
1064
- idx.push(DEV_APP_PACKAGE_NAME)
1170
+ if (!idx.includes(packageName)) {
1171
+ idx.push(packageName)
1065
1172
  storage.save(DEV_APPS_INDEX_KEY, JSON.stringify(idx))
1066
1173
  }
1067
1174
  appRegistry.markRefreshNeeded()
1068
1175
  }
1069
1176
 
1070
- /** Drop the dev miniapp's home-tile metadata + dev URL/port keys. */
1071
- export function unregisterDevApp(): void {
1072
- storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_meta`)
1073
- storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_url`)
1074
- storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_port`)
1075
- storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_last_reachable`)
1076
- const idx = getDevAppIndex().filter((p) => p !== DEV_APP_PACKAGE_NAME)
1177
+ /** Drop one dev miniapp's metadata, routing keys, and cached icon. */
1178
+ export function unregisterDevApp(packageName = DEV_APP_PACKAGE_NAME): void {
1179
+ removeDevRecordKeys(packageName)
1180
+ const idx = getDevAppIndex().filter((p) => p !== packageName)
1077
1181
  storage.save(DEV_APPS_INDEX_KEY, JSON.stringify(idx))
1078
1182
  appRegistry.markRefreshNeeded()
1079
1183
  }
@@ -1089,33 +1193,20 @@ function getDevAppIndex(): string[] {
1089
1193
  }
1090
1194
  }
1091
1195
 
1092
- /**
1093
- * The real manifest package name currently occupying the dev slot, or null if no dev app is
1094
- * registered. Used to decide whether clearing a package's artifacts should also drop the dev slot.
1095
- */
1096
- export function getDevAppSourcePackage(): string | null {
1097
- const res = storage.load<string>(`${DEV_APP_PACKAGE_NAME}_dev_meta`)
1098
- if (!res.is_ok()) return null
1099
- try {
1100
- const rec = JSON.parse(res.value) as DevAppRecord
1101
- return rec.sourcePackageName ?? null
1102
- } catch {
1103
- return null
1104
- }
1196
+ /** Resolve the manifest package for a dev runtime (including the legacy slot). */
1197
+ export function getDevAppSourcePackage(packageName = DEV_APP_PACKAGE_NAME): string | null {
1198
+ migrateLegacyDevSlot()
1199
+ const rec = readDevAppRecord(packageName)
1200
+ return rec?.sourcePackageName ?? rec?.packageName ?? null
1105
1201
  }
1106
1202
 
1107
- export function getDevAppAttestation(): string | null {
1108
- const res = storage.load<string>(`${DEV_APP_PACKAGE_NAME}_dev_meta`)
1109
- if (!res.is_ok()) return null
1110
- try {
1111
- const rec = JSON.parse(res.value) as DevAppRecord
1112
- return rec.devAttestation ?? null
1113
- } catch {
1114
- return null
1115
- }
1203
+ export function getDevAppAttestation(packageName = DEV_APP_PACKAGE_NAME): string | null {
1204
+ migrateLegacyDevSlot()
1205
+ return readDevAppRecord(packageName)?.devAttestation ?? null
1116
1206
  }
1117
1207
 
1118
1208
  export function getDevAppRecords(): DevAppRecord[] {
1209
+ migrateLegacyDevSlot()
1119
1210
  const out: DevAppRecord[] = []
1120
1211
  for (const pkg of getDevAppIndex()) {
1121
1212
  const res = storage.load<string>(`${pkg}_dev_meta`)