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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (503) hide show
  1. package/README.md +55 -18
  2. package/build/bluetooth-sdk/debug.d.ts +2 -0
  3. package/build/bluetooth-sdk/debug.d.ts.map +1 -0
  4. package/build/bluetooth-sdk/debug.js +2 -0
  5. package/build/bluetooth-sdk/debug.js.map +1 -0
  6. package/build/bluetooth-sdk/index.d.ts +3 -0
  7. package/build/bluetooth-sdk/index.d.ts.map +1 -0
  8. package/build/bluetooth-sdk/index.js +3 -0
  9. package/build/bluetooth-sdk/index.js.map +1 -0
  10. package/build/bluetooth-sdk/photo-receiver.d.ts +3 -0
  11. package/build/bluetooth-sdk/photo-receiver.d.ts.map +1 -0
  12. package/build/bluetooth-sdk/photo-receiver.js +3 -0
  13. package/build/bluetooth-sdk/photo-receiver.js.map +1 -0
  14. package/build/bluetooth-sdk/react.d.ts +2 -0
  15. package/build/bluetooth-sdk/react.d.ts.map +1 -0
  16. package/build/bluetooth-sdk/react.js +2 -0
  17. package/build/bluetooth-sdk/react.js.map +1 -0
  18. package/build/bluetooth-sdk/types.d.ts +2 -0
  19. package/build/bluetooth-sdk/types.d.ts.map +1 -0
  20. package/build/bluetooth-sdk/types.js +2 -0
  21. package/build/bluetooth-sdk/types.js.map +1 -0
  22. package/build/engine.d.ts +24 -16
  23. package/build/engine.d.ts.map +1 -1
  24. package/build/engine.js +9 -4
  25. package/build/engine.js.map +1 -1
  26. package/build/facades/dev.d.ts +3 -2
  27. package/build/facades/dev.d.ts.map +1 -1
  28. package/build/facades/dev.js +18 -12
  29. package/build/facades/dev.js.map +1 -1
  30. package/build/facades/display.d.ts +1 -1
  31. package/build/facades/display.d.ts.map +1 -1
  32. package/build/facades/display.js +1 -1
  33. package/build/facades/display.js.map +1 -1
  34. package/build/facades/gallery.js +1 -1
  35. package/build/facades/gallery.js.map +1 -1
  36. package/build/facades/glasses.d.ts +4 -13
  37. package/build/facades/glasses.d.ts.map +1 -1
  38. package/build/facades/glasses.js +21 -6
  39. package/build/facades/glasses.js.map +1 -1
  40. package/build/facades/glassesSettings.d.ts.map +1 -1
  41. package/build/facades/glassesSettings.js +1 -0
  42. package/build/facades/glassesSettings.js.map +1 -1
  43. package/build/facades/miniapps.d.ts +4 -0
  44. package/build/facades/miniapps.d.ts.map +1 -1
  45. package/build/facades/miniapps.js +5 -0
  46. package/build/facades/miniapps.js.map +1 -1
  47. package/build/facades/ota.d.ts +14 -16
  48. package/build/facades/ota.d.ts.map +1 -1
  49. package/build/facades/ota.js +22 -7
  50. package/build/facades/ota.js.map +1 -1
  51. package/build/facades/pairing.d.ts +8 -5
  52. package/build/facades/pairing.d.ts.map +1 -1
  53. package/build/facades/pairing.js +12 -10
  54. package/build/facades/pairing.js.map +1 -1
  55. package/build/facades/permissions.d.ts +10 -0
  56. package/build/facades/permissions.d.ts.map +1 -1
  57. package/build/facades/permissions.js +10 -0
  58. package/build/facades/permissions.js.map +1 -1
  59. package/build/facades/phoneNotifications.d.ts +0 -4
  60. package/build/facades/phoneNotifications.d.ts.map +1 -1
  61. package/build/facades/phoneNotifications.js +4 -14
  62. package/build/facades/phoneNotifications.js.map +1 -1
  63. package/build/facades/speech.d.ts +7 -6
  64. package/build/facades/speech.d.ts.map +1 -1
  65. package/build/facades/speech.js +1 -1
  66. package/build/facades/speech.js.map +1 -1
  67. package/build/generated/releaseMetadata.d.ts +12 -0
  68. package/build/generated/releaseMetadata.d.ts.map +1 -0
  69. package/build/generated/releaseMetadata.js +10 -0
  70. package/build/generated/releaseMetadata.js.map +1 -0
  71. package/build/index.d.ts +10 -8
  72. package/build/index.d.ts.map +1 -1
  73. package/build/index.js +6 -5
  74. package/build/index.js.map +1 -1
  75. package/build/react/MentraLiveOtaFlow.d.ts +38 -0
  76. package/build/react/MentraLiveOtaFlow.d.ts.map +1 -0
  77. package/build/react/MentraLiveOtaFlow.js +528 -0
  78. package/build/react/MentraLiveOtaFlow.js.map +1 -0
  79. package/build/react/index.d.ts +2 -0
  80. package/build/react/index.d.ts.map +1 -0
  81. package/build/react/index.js +2 -0
  82. package/build/react/index.js.map +1 -0
  83. package/build/react/useEngineSnapshot.d.ts +2 -0
  84. package/build/react/useEngineSnapshot.d.ts.map +1 -0
  85. package/build/react/useEngineSnapshot.js +14 -0
  86. package/build/react/useEngineSnapshot.js.map +1 -0
  87. package/build/runtime/bootstrap.d.ts +24 -1
  88. package/build/runtime/bootstrap.d.ts.map +1 -1
  89. package/build/runtime/bootstrap.js +17 -0
  90. package/build/runtime/bootstrap.js.map +1 -1
  91. package/build/runtime/scanQrSeam.d.ts +7 -0
  92. package/build/runtime/scanQrSeam.d.ts.map +1 -0
  93. package/build/runtime/scanQrSeam.js +16 -0
  94. package/build/runtime/scanQrSeam.js.map +1 -0
  95. package/build/services/AppRegistry.d.ts +41 -57
  96. package/build/services/AppRegistry.d.ts.map +1 -1
  97. package/build/services/AppRegistry.js +208 -144
  98. package/build/services/AppRegistry.js.map +1 -1
  99. package/build/services/AudioCloudUplink.d.ts +12 -0
  100. package/build/services/AudioCloudUplink.d.ts.map +1 -1
  101. package/build/services/AudioCloudUplink.js +22 -1
  102. package/build/services/AudioCloudUplink.js.map +1 -1
  103. package/build/services/AudioPlaybackService.d.ts +41 -2
  104. package/build/services/AudioPlaybackService.d.ts.map +1 -1
  105. package/build/services/AudioPlaybackService.js +250 -33
  106. package/build/services/AudioPlaybackService.js.map +1 -1
  107. package/build/services/BlobStore.d.ts +2 -1
  108. package/build/services/BlobStore.d.ts.map +1 -1
  109. package/build/services/BlobStore.js +17 -9
  110. package/build/services/BlobStore.js.map +1 -1
  111. package/build/services/CloudAudioSubscriptionSync.d.ts.map +1 -1
  112. package/build/services/CloudAudioSubscriptionSync.js +13 -1
  113. package/build/services/CloudAudioSubscriptionSync.js.map +1 -1
  114. package/build/services/CloudClientService.d.ts +15 -0
  115. package/build/services/CloudClientService.d.ts.map +1 -1
  116. package/build/services/CloudClientService.js +93 -1
  117. package/build/services/CloudClientService.js.map +1 -1
  118. package/build/services/DeviceEventRouter.js +5 -5
  119. package/build/services/DeviceEventRouter.js.map +1 -1
  120. package/build/services/ForegroundLocationPermission.d.ts +13 -0
  121. package/build/services/ForegroundLocationPermission.d.ts.map +1 -0
  122. package/build/services/ForegroundLocationPermission.js +12 -0
  123. package/build/services/ForegroundLocationPermission.js.map +1 -0
  124. package/build/services/GlassesSettingsSync.d.ts.map +1 -1
  125. package/build/services/GlassesSettingsSync.js +9 -3
  126. package/build/services/GlassesSettingsSync.js.map +1 -1
  127. package/build/services/GlassesStatusProjection.d.ts +2 -1
  128. package/build/services/GlassesStatusProjection.d.ts.map +1 -1
  129. package/build/services/GlassesStatusProjection.js +15 -8
  130. package/build/services/GlassesStatusProjection.js.map +1 -1
  131. package/build/services/HotspotOtaTransport.d.ts +29 -0
  132. package/build/services/HotspotOtaTransport.d.ts.map +1 -0
  133. package/build/services/HotspotOtaTransport.js +146 -0
  134. package/build/services/HotspotOtaTransport.js.map +1 -0
  135. package/build/services/HotspotShutdown.d.ts +17 -0
  136. package/build/services/HotspotShutdown.d.ts.map +1 -0
  137. package/build/services/HotspotShutdown.js +29 -0
  138. package/build/services/HotspotShutdown.js.map +1 -0
  139. package/build/services/LocalDisplayManager.d.ts +15 -0
  140. package/build/services/LocalDisplayManager.d.ts.map +1 -1
  141. package/build/services/LocalDisplayManager.js +106 -20
  142. package/build/services/LocalDisplayManager.js.map +1 -1
  143. package/build/services/LocalMiniappRuntime.d.ts +74 -2
  144. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  145. package/build/services/LocalMiniappRuntime.js +785 -291
  146. package/build/services/LocalMiniappRuntime.js.map +1 -1
  147. package/build/services/LocalMiniappStorage.d.ts +32 -0
  148. package/build/services/LocalMiniappStorage.d.ts.map +1 -0
  149. package/build/services/LocalMiniappStorage.js +66 -0
  150. package/build/services/LocalMiniappStorage.js.map +1 -0
  151. package/build/services/LocalMiniappUserIdentity.d.ts +20 -0
  152. package/build/services/LocalMiniappUserIdentity.d.ts.map +1 -0
  153. package/build/services/LocalMiniappUserIdentity.js +43 -0
  154. package/build/services/LocalMiniappUserIdentity.js.map +1 -0
  155. package/build/services/LocalSttFallbackCoordinator.d.ts +9 -6
  156. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
  157. package/build/services/LocalSttFallbackCoordinator.js +18 -12
  158. package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
  159. package/build/services/MicStateCoordinator.d.ts +42 -1
  160. package/build/services/MicStateCoordinator.d.ts.map +1 -1
  161. package/build/services/MicStateCoordinator.js +141 -3
  162. package/build/services/MicStateCoordinator.js.map +1 -1
  163. package/build/services/MiniappLauncher.d.ts.map +1 -1
  164. package/build/services/MiniappLauncher.js +23 -3
  165. package/build/services/MiniappLauncher.js.map +1 -1
  166. package/build/services/MiniappLiveness.d.ts +12 -0
  167. package/build/services/MiniappLiveness.d.ts.map +1 -0
  168. package/build/services/MiniappLiveness.js +16 -0
  169. package/build/services/MiniappLiveness.js.map +1 -0
  170. package/build/services/NativeHttpResponse.d.ts +3 -0
  171. package/build/services/NativeHttpResponse.d.ts.map +1 -0
  172. package/build/services/NativeHttpResponse.js +6 -0
  173. package/build/services/NativeHttpResponse.js.map +1 -0
  174. package/build/services/OtaArtifactDownloader.d.ts +65 -0
  175. package/build/services/OtaArtifactDownloader.d.ts.map +1 -0
  176. package/build/services/OtaArtifactDownloader.js +226 -0
  177. package/build/services/OtaArtifactDownloader.js.map +1 -0
  178. package/build/services/OtaAutoChain.d.ts +34 -0
  179. package/build/services/OtaAutoChain.d.ts.map +1 -0
  180. package/build/services/OtaAutoChain.js +83 -0
  181. package/build/services/OtaAutoChain.js.map +1 -0
  182. package/build/services/OtaErrorMapping.d.ts +18 -0
  183. package/build/services/OtaErrorMapping.d.ts.map +1 -0
  184. package/build/services/OtaErrorMapping.js +63 -0
  185. package/build/services/OtaErrorMapping.js.map +1 -0
  186. package/build/services/OtaInstallCoordinator.d.ts +95 -15
  187. package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
  188. package/build/services/OtaInstallCoordinator.js +577 -130
  189. package/build/services/OtaInstallCoordinator.js.map +1 -1
  190. package/build/services/OtaService.d.ts.map +1 -1
  191. package/build/services/OtaService.js +8 -1
  192. package/build/services/OtaService.js.map +1 -1
  193. package/build/services/OtaUpdateCheckService.d.ts +39 -4
  194. package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
  195. package/build/services/OtaUpdateCheckService.js +138 -22
  196. package/build/services/OtaUpdateCheckService.js.map +1 -1
  197. package/build/services/PhoneCalendarHelpers.d.ts +32 -0
  198. package/build/services/PhoneCalendarHelpers.d.ts.map +1 -0
  199. package/build/services/PhoneCalendarHelpers.js +157 -0
  200. package/build/services/PhoneCalendarHelpers.js.map +1 -0
  201. package/build/services/PhoneCalendarService.d.ts +5 -0
  202. package/build/services/PhoneCalendarService.d.ts.map +1 -0
  203. package/build/services/PhoneCalendarService.js +45 -0
  204. package/build/services/PhoneCalendarService.js.map +1 -0
  205. package/build/services/PhoneCameraFovCoordinator.d.ts +30 -0
  206. package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -0
  207. package/build/services/PhoneCameraFovCoordinator.js +194 -0
  208. package/build/services/PhoneCameraFovCoordinator.js.map +1 -0
  209. package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
  210. package/build/services/PhoneNotificationsSync.js +12 -10
  211. package/build/services/PhoneNotificationsSync.js.map +1 -1
  212. package/build/services/PhonePhotoCoordinator.d.ts +26 -2
  213. package/build/services/PhonePhotoCoordinator.d.ts.map +1 -1
  214. package/build/services/PhonePhotoCoordinator.js +79 -9
  215. package/build/services/PhonePhotoCoordinator.js.map +1 -1
  216. package/build/services/PhoneStreamCoordinator.d.ts +8 -1
  217. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
  218. package/build/services/PhoneStreamCoordinator.js +125 -13
  219. package/build/services/PhoneStreamCoordinator.js.map +1 -1
  220. package/build/services/PhoneVideoCoordinator.d.ts +2 -0
  221. package/build/services/PhoneVideoCoordinator.d.ts.map +1 -1
  222. package/build/services/PhoneVideoCoordinator.js +10 -0
  223. package/build/services/PhoneVideoCoordinator.js.map +1 -1
  224. package/build/services/SceneRenderer.d.ts.map +1 -1
  225. package/build/services/SceneRenderer.js +15 -0
  226. package/build/services/SceneRenderer.js.map +1 -1
  227. package/build/services/SentenceTtsPipeline.d.ts +31 -0
  228. package/build/services/SentenceTtsPipeline.d.ts.map +1 -0
  229. package/build/services/SentenceTtsPipeline.js +67 -0
  230. package/build/services/SentenceTtsPipeline.js.map +1 -0
  231. package/build/services/SupportProfileSync.d.ts +22 -0
  232. package/build/services/SupportProfileSync.d.ts.map +1 -0
  233. package/build/services/SupportProfileSync.js +213 -0
  234. package/build/services/SupportProfileSync.js.map +1 -0
  235. package/build/services/TranscriptionRouting.d.ts +12 -0
  236. package/build/services/TranscriptionRouting.d.ts.map +1 -0
  237. package/build/services/TranscriptionRouting.js +24 -0
  238. package/build/services/TranscriptionRouting.js.map +1 -0
  239. package/build/services/TtsTextSanitizer.d.ts +5 -0
  240. package/build/services/TtsTextSanitizer.d.ts.map +1 -0
  241. package/build/services/TtsTextSanitizer.js +61 -0
  242. package/build/services/TtsTextSanitizer.js.map +1 -0
  243. package/build/services/WifiAdbRequest.d.ts +17 -0
  244. package/build/services/WifiAdbRequest.d.ts.map +1 -0
  245. package/build/services/WifiAdbRequest.js +35 -0
  246. package/build/services/WifiAdbRequest.js.map +1 -0
  247. package/build/services/asg/asgCameraApi.d.ts +43 -0
  248. package/build/services/asg/asgCameraApi.d.ts.map +1 -1
  249. package/build/services/asg/asgCameraApi.js +509 -26
  250. package/build/services/asg/asgCameraApi.js.map +1 -1
  251. package/build/services/asg/cameraRollExportCoordinator.d.ts +60 -0
  252. package/build/services/asg/cameraRollExportCoordinator.d.ts.map +1 -0
  253. package/build/services/asg/cameraRollExportCoordinator.js +618 -0
  254. package/build/services/asg/cameraRollExportCoordinator.js.map +1 -0
  255. package/build/services/asg/cameraRollExportLedger.d.ts +44 -0
  256. package/build/services/asg/cameraRollExportLedger.d.ts.map +1 -0
  257. package/build/services/asg/cameraRollExportLedger.js +78 -0
  258. package/build/services/asg/cameraRollExportLedger.js.map +1 -0
  259. package/build/services/asg/galleryNotices.d.ts +1 -1
  260. package/build/services/asg/galleryNotices.d.ts.map +1 -1
  261. package/build/services/asg/galleryNotices.js.map +1 -1
  262. package/build/services/asg/galleryPathMigration.d.ts +3 -0
  263. package/build/services/asg/galleryPathMigration.d.ts.map +1 -0
  264. package/build/services/asg/galleryPathMigration.js +26 -0
  265. package/build/services/asg/galleryPathMigration.js.map +1 -0
  266. package/build/services/asg/gallerySettingsService.d.ts +1 -0
  267. package/build/services/asg/gallerySettingsService.d.ts.map +1 -1
  268. package/build/services/asg/gallerySettingsService.js +2 -0
  269. package/build/services/asg/gallerySettingsService.js.map +1 -1
  270. package/build/services/asg/gallerySyncService.d.ts.map +1 -1
  271. package/build/services/asg/gallerySyncService.js +162 -56
  272. package/build/services/asg/gallerySyncService.js.map +1 -1
  273. package/build/services/asg/galleryTransferLedger.d.ts +58 -0
  274. package/build/services/asg/galleryTransferLedger.d.ts.map +1 -0
  275. package/build/services/asg/galleryTransferLedger.js +225 -0
  276. package/build/services/asg/galleryTransferLedger.js.map +1 -0
  277. package/build/services/asg/localNetworkTransport.d.ts +15 -0
  278. package/build/services/asg/localNetworkTransport.d.ts.map +1 -0
  279. package/build/services/asg/localNetworkTransport.js +144 -0
  280. package/build/services/asg/localNetworkTransport.js.map +1 -0
  281. package/build/services/asg/localStorageService.d.ts +18 -0
  282. package/build/services/asg/localStorageService.d.ts.map +1 -1
  283. package/build/services/asg/localStorageService.js +168 -19
  284. package/build/services/asg/localStorageService.js.map +1 -1
  285. package/build/services/asg/mediaProcessingQueue.d.ts +10 -0
  286. package/build/services/asg/mediaProcessingQueue.d.ts.map +1 -1
  287. package/build/services/asg/mediaProcessingQueue.js +193 -62
  288. package/build/services/asg/mediaProcessingQueue.js.map +1 -1
  289. package/build/services/audioPlaybackAssets.d.ts +8 -0
  290. package/build/services/audioPlaybackAssets.d.ts.map +1 -0
  291. package/build/services/audioPlaybackAssets.js +7 -0
  292. package/build/services/audioPlaybackAssets.js.map +1 -0
  293. package/build/services/gallerySyncClock.js +1 -1
  294. package/build/services/gallerySyncClock.js.map +1 -1
  295. package/build/services/glassesClockSync.d.ts.map +1 -1
  296. package/build/services/glassesClockSync.js +6 -2
  297. package/build/services/glassesClockSync.js.map +1 -1
  298. package/build/services/manifestActions.d.ts +7 -0
  299. package/build/services/manifestActions.d.ts.map +1 -0
  300. package/build/services/manifestActions.js +25 -0
  301. package/build/services/manifestActions.js.map +1 -0
  302. package/build/services/otaDisplayState.d.ts +23 -12
  303. package/build/services/otaDisplayState.d.ts.map +1 -1
  304. package/build/services/otaDisplayState.js +36 -14
  305. package/build/services/otaDisplayState.js.map +1 -1
  306. package/build/services/otaInstallPolicy.d.ts +16 -4
  307. package/build/services/otaInstallPolicy.d.ts.map +1 -1
  308. package/build/services/otaInstallPolicy.js +24 -3
  309. package/build/services/otaInstallPolicy.js.map +1 -1
  310. package/build/services/otaLegacyMapping.d.ts +1 -1
  311. package/build/services/otaLegacyMapping.d.ts.map +1 -1
  312. package/build/services/otaLegacyMapping.js.map +1 -1
  313. package/build/services/otaManifestPolicy.d.ts +14 -0
  314. package/build/services/otaManifestPolicy.d.ts.map +1 -0
  315. package/build/services/otaManifestPolicy.js +19 -0
  316. package/build/services/otaManifestPolicy.js.map +1 -0
  317. package/build/services/otaManifestUrl.d.ts +3 -0
  318. package/build/services/otaManifestUrl.d.ts.map +1 -0
  319. package/build/services/otaManifestUrl.js +38 -0
  320. package/build/services/otaManifestUrl.js.map +1 -0
  321. package/build/services/slimStreamStatus.d.ts +11 -0
  322. package/build/services/slimStreamStatus.d.ts.map +1 -1
  323. package/build/services/slimStreamStatus.js +14 -4
  324. package/build/services/slimStreamStatus.js.map +1 -1
  325. package/build/stores/apps.d.ts.map +1 -1
  326. package/build/stores/apps.js +11 -0
  327. package/build/stores/apps.js.map +1 -1
  328. package/build/stores/bluetoothSettingKeys.d.ts.map +1 -1
  329. package/build/stores/bluetoothSettingKeys.js +2 -0
  330. package/build/stores/bluetoothSettingKeys.js.map +1 -1
  331. package/build/stores/gallerySync.d.ts +2 -0
  332. package/build/stores/gallerySync.d.ts.map +1 -1
  333. package/build/stores/gallerySync.js +2 -0
  334. package/build/stores/gallerySync.js.map +1 -1
  335. package/build/stores/glasses.d.ts.map +1 -1
  336. package/build/stores/glasses.js +3 -0
  337. package/build/stores/glasses.js.map +1 -1
  338. package/build/stores/settings.d.ts +17 -0
  339. package/build/stores/settings.d.ts.map +1 -1
  340. package/build/stores/settings.js +157 -17
  341. package/build/stores/settings.js.map +1 -1
  342. package/build/types/applet.d.ts +2 -0
  343. package/build/types/applet.d.ts.map +1 -1
  344. package/build/types/applet.js.map +1 -1
  345. package/build/types/asg.d.ts +7 -0
  346. package/build/types/asg.d.ts.map +1 -1
  347. package/build/types/asg.js.map +1 -1
  348. package/build/types/enums.d.ts +2 -25
  349. package/build/types/enums.d.ts.map +1 -1
  350. package/build/types/enums.js +2 -27
  351. package/build/types/enums.js.map +1 -1
  352. package/build/types/hardware.d.ts +4 -13
  353. package/build/types/hardware.d.ts.map +1 -1
  354. package/build/types/hardware.js +15 -3
  355. package/build/types/hardware.js.map +1 -1
  356. package/build/types/index.d.ts +2 -6
  357. package/build/types/index.d.ts.map +1 -1
  358. package/build/types/index.js +2 -6
  359. package/build/types/index.js.map +1 -1
  360. package/build/utils/configuredDevHost.d.ts +6 -0
  361. package/build/utils/configuredDevHost.d.ts.map +1 -0
  362. package/build/utils/configuredDevHost.js +19 -0
  363. package/build/utils/configuredDevHost.js.map +1 -0
  364. package/build/utils/devMiniappLaunch.d.ts +19 -8
  365. package/build/utils/devMiniappLaunch.d.ts.map +1 -1
  366. package/build/utils/devMiniappLaunch.js +144 -21
  367. package/build/utils/devMiniappLaunch.js.map +1 -1
  368. package/build/utils/diagnosticContext.d.ts.map +1 -1
  369. package/build/utils/diagnosticContext.js +15 -17
  370. package/build/utils/diagnosticContext.js.map +1 -1
  371. package/build/utils/hardware/hardware.d.ts.map +1 -1
  372. package/build/utils/hardware/hardware.js +7 -3
  373. package/build/utils/hardware/hardware.js.map +1 -1
  374. package/build/utils/miniappDiagnostics.d.ts +64 -0
  375. package/build/utils/miniappDiagnostics.d.ts.map +1 -0
  376. package/build/utils/miniappDiagnostics.js +173 -0
  377. package/build/utils/miniappDiagnostics.js.map +1 -0
  378. package/build/utils/permissions/MediaLibraryPermissions.d.ts +11 -0
  379. package/build/utils/permissions/MediaLibraryPermissions.d.ts.map +1 -1
  380. package/build/utils/permissions/MediaLibraryPermissions.js +27 -4
  381. package/build/utils/permissions/MediaLibraryPermissions.js.map +1 -1
  382. package/build/utils/timers/timers.d.ts.map +1 -1
  383. package/build/utils/timers/timers.js +55 -18
  384. package/build/utils/timers/timers.js.map +1 -1
  385. package/package.json +59 -31
  386. package/src/assets/silence.wav +0 -0
  387. package/src/bluetooth-sdk/debug.ts +1 -0
  388. package/src/bluetooth-sdk/index.ts +2 -0
  389. package/src/bluetooth-sdk/photo-receiver.ts +2 -0
  390. package/src/bluetooth-sdk/react.ts +1 -0
  391. package/src/bluetooth-sdk/types.ts +1 -0
  392. package/src/engine.ts +9 -4
  393. package/src/facades/dev.ts +17 -12
  394. package/src/facades/display.ts +1 -1
  395. package/src/facades/gallery.ts +1 -1
  396. package/src/facades/glasses.ts +20 -7
  397. package/src/facades/glassesSettings.ts +5 -0
  398. package/src/facades/miniapps.ts +7 -0
  399. package/src/facades/ota.ts +23 -8
  400. package/src/facades/pairing.ts +15 -11
  401. package/src/facades/permissions.ts +14 -0
  402. package/src/facades/phoneNotifications.ts +4 -13
  403. package/src/facades/speech.ts +21 -7
  404. package/src/generated/releaseMetadata.ts +20 -0
  405. package/src/index.ts +39 -13
  406. package/src/react/MentraLiveOtaFlow.tsx +856 -0
  407. package/src/react/index.ts +7 -0
  408. package/src/react/useEngineSnapshot.ts +16 -0
  409. package/src/runtime/bootstrap.ts +33 -1
  410. package/src/runtime/scanQrSeam.ts +20 -0
  411. package/src/services/AppRegistry.ts +240 -149
  412. package/src/services/AudioCloudUplink.ts +23 -1
  413. package/src/services/AudioPlaybackService.ts +287 -38
  414. package/src/services/BlobStore.ts +22 -9
  415. package/src/services/CloudAudioSubscriptionSync.ts +13 -1
  416. package/src/services/CloudClientService.ts +96 -1
  417. package/src/services/DeviceEventRouter.ts +5 -5
  418. package/src/services/ForegroundLocationPermission.ts +24 -0
  419. package/src/services/GlassesSettingsSync.ts +9 -3
  420. package/src/services/GlassesStatusProjection.ts +16 -8
  421. package/src/services/HotspotOtaTransport.ts +184 -0
  422. package/src/services/HotspotShutdown.ts +41 -0
  423. package/src/services/LocalDisplayManager.ts +112 -21
  424. package/src/services/LocalMiniappRuntime.ts +967 -346
  425. package/src/services/LocalMiniappStorage.ts +82 -0
  426. package/src/services/LocalMiniappUserIdentity.ts +46 -0
  427. package/src/services/LocalSttFallbackCoordinator.ts +19 -12
  428. package/src/services/MicStateCoordinator.ts +169 -4
  429. package/src/services/MiniappLauncher.ts +30 -3
  430. package/src/services/MiniappLiveness.ts +24 -0
  431. package/src/services/NativeHttpResponse.ts +6 -0
  432. package/src/services/OtaArtifactDownloader.ts +312 -0
  433. package/src/services/OtaAutoChain.ts +106 -0
  434. package/src/services/OtaErrorMapping.ts +80 -0
  435. package/src/services/OtaInstallCoordinator.ts +649 -144
  436. package/src/services/OtaService.ts +11 -5
  437. package/src/services/OtaUpdateCheckService.ts +181 -21
  438. package/src/services/PhoneCalendarHelpers.ts +212 -0
  439. package/src/services/PhoneCalendarService.ts +65 -0
  440. package/src/services/PhoneCameraFovCoordinator.ts +210 -0
  441. package/src/services/PhoneNotificationsSync.ts +12 -10
  442. package/src/services/PhonePhotoCoordinator.ts +116 -18
  443. package/src/services/PhoneStreamCoordinator.ts +139 -25
  444. package/src/services/PhoneVideoCoordinator.ts +11 -0
  445. package/src/services/SceneRenderer.ts +16 -0
  446. package/src/services/SentenceTtsPipeline.ts +106 -0
  447. package/src/services/SupportProfileSync.ts +218 -0
  448. package/src/services/TranscriptionRouting.ts +37 -0
  449. package/src/services/TtsTextSanitizer.ts +66 -0
  450. package/src/services/WifiAdbRequest.ts +53 -0
  451. package/src/services/asg/asgCameraApi.ts +615 -33
  452. package/src/services/asg/cameraRollExportCoordinator.ts +627 -0
  453. package/src/services/asg/cameraRollExportLedger.ts +122 -0
  454. package/src/services/asg/galleryNotices.ts +1 -0
  455. package/src/services/asg/galleryPathMigration.ts +22 -0
  456. package/src/services/asg/gallerySettingsService.ts +3 -0
  457. package/src/services/asg/gallerySyncService.ts +184 -73
  458. package/src/services/asg/galleryTransferLedger.ts +312 -0
  459. package/src/services/asg/localNetworkTransport.ts +169 -0
  460. package/src/services/asg/localStorageService.ts +179 -24
  461. package/src/services/asg/mediaProcessingQueue.ts +209 -62
  462. package/src/services/audioPlaybackAssets.ts +8 -0
  463. package/src/services/gallerySyncClock.ts +1 -1
  464. package/src/services/glassesClockSync.ts +6 -2
  465. package/src/services/manifestActions.ts +30 -0
  466. package/src/services/otaDisplayState.ts +58 -17
  467. package/src/services/otaInstallPolicy.ts +30 -4
  468. package/src/services/otaLegacyMapping.ts +1 -1
  469. package/src/services/otaManifestPolicy.ts +42 -0
  470. package/src/services/otaManifestUrl.ts +44 -0
  471. package/src/services/slimStreamStatus.ts +16 -5
  472. package/src/stores/apps.ts +12 -0
  473. package/src/stores/bluetoothSettingKeys.ts +2 -0
  474. package/src/stores/gallerySync.ts +4 -0
  475. package/src/stores/glasses.ts +3 -0
  476. package/src/stores/settings.ts +179 -18
  477. package/src/types/applet.ts +2 -0
  478. package/src/types/asg.ts +7 -0
  479. package/src/types/enums.ts +3 -28
  480. package/src/types/hardware.ts +20 -13
  481. package/src/types/index.ts +2 -6
  482. package/src/utils/configuredDevHost.ts +17 -0
  483. package/src/utils/devMiniappLaunch.ts +151 -23
  484. package/src/utils/diagnosticContext.ts +17 -17
  485. package/src/utils/hardware/hardware.ts +7 -9
  486. package/src/utils/miniappDiagnostics.ts +226 -0
  487. package/src/utils/permissions/MediaLibraryPermissions.ts +35 -4
  488. package/src/utils/timers/timers.ts +57 -21
  489. package/build/devtools.d.ts +0 -11
  490. package/build/devtools.d.ts.map +0 -1
  491. package/build/devtools.js +0 -13
  492. package/build/devtools.js.map +0 -1
  493. package/build/internal.d.ts +0 -66
  494. package/build/internal.d.ts.map +0 -1
  495. package/build/internal.js +0 -89
  496. package/build/internal.js.map +0 -1
  497. package/build/services/asgOtaVersionUrl.d.ts +0 -2
  498. package/build/services/asgOtaVersionUrl.d.ts.map +0 -1
  499. package/build/services/asgOtaVersionUrl.js +0 -36
  500. package/build/services/asgOtaVersionUrl.js.map +0 -1
  501. package/src/devtools.ts +0 -13
  502. package/src/internal.ts +0 -158
  503. package/src/services/asgOtaVersionUrl.ts +0 -41
@@ -17,14 +17,28 @@
17
17
  * short-circuit our long-poll with a typed error (CAMERA_BUSY, BATTERY_LOW,
18
18
  * etc.) instead of waiting 30s for cloud's timeout.
19
19
  */
20
+ import type { PhotoTransferMethod } from "@mentra/bluetooth-sdk/internal";
20
21
  export interface PhotoOpts {
21
22
  /** Legacy cloud size names are normalized before the native take_photo command. */
22
23
  size?: "low" | "medium" | "high" | "max" | "small" | "large" | "full";
23
24
  mode?: "photo" | "text";
25
+ /** Select direct-only, phone-relayed BLE, or the default Wi-Fi/BLE fallback policy. */
26
+ transferMethod?: PhotoTransferMethod;
24
27
  compress?: "none" | "low" | "medium" | "high";
25
28
  sound?: boolean;
26
29
  saveToGallery?: boolean;
27
30
  exposureTimeNs?: number;
31
+ iso?: number | null;
32
+ aeExposureDivisor?: number;
33
+ isoCap?: number;
34
+ noiseReduction?: boolean;
35
+ edgeEnhancement?: boolean;
36
+ /** ZSL preview buffering. */
37
+ zsl?: boolean;
38
+ /** MFNR still capture. */
39
+ mfnr?: boolean;
40
+ ispDigitalGain?: number;
41
+ ispAnalogGain?: string;
28
42
  }
29
43
  export interface PhotoTaken {
30
44
  photoUrl: string;
@@ -53,25 +67,35 @@ export declare class PhotoError extends Error {
53
67
  * rejected successful captures while their upload was still in progress.
54
68
  */
55
69
  export declare const CAPTURE_PIPELINE_TIMEOUT_MS = 45000;
70
+ export declare const CAMERA_WARM_UP_DEFAULT_DURATION_MS = 15000;
71
+ export declare const CAMERA_WARM_UP_MAX_DURATION_MS = 60000;
56
72
  export declare class PhonePhotoCoordinator {
57
73
  private readonly activeRequests;
58
74
  /** Short BLE correlation id (4-char hex) → full cloud requestId. */
59
75
  private readonly bleIdToCloud;
76
+ private readonly activeWarmUps;
77
+ /** Report-safe camera ownership snapshot for incident diagnostics. */
78
+ getDiagnosticSnapshot(): Record<string, unknown>;
60
79
  takePhoto(packageName: string, opts: PhotoOpts): Promise<PhotoTaken>;
61
80
  /** Map a short BLE requestId from photo_response back to the cloud requestId. */
62
81
  resolveCloudRequestId(bleOrCloudId: string): string;
63
82
  /**
64
83
  * Pre-warm the glasses camera so the next takePhoto() is near-instant.
65
84
  *
66
- * Pure BLE — NO cloud presign, NO upload, NO long-poll. The SDK mints the
67
- * requestId, sends the warm-up command, and resolves when the camera reports
85
+ * Pure BLE — NO cloud presign, NO upload, NO long-poll. The phone mints and owns
86
+ * the requestId, sends the warm-up command, and resolves when the camera reports
68
87
  * ready (the native promise resolves on the ready status event).
69
88
  */
70
89
  warmUpCamera(packageName: string, opts: {
71
90
  size?: "low" | "medium" | "high" | "max";
91
+ mode?: "photo" | "text";
72
92
  exposureTimeNs?: number;
73
93
  durationMs?: number;
94
+ zsl?: boolean;
95
+ mfnr?: boolean;
74
96
  }): Promise<void>;
97
+ /** Release a miniapp's warm-up even if its original warmUpCamera promise is still opening. */
98
+ stopWarmUpForApp(packageName: string): Promise<void>;
75
99
  /** True iff this requestId (short BLE id or cloud id) is one we're currently waiting on. */
76
100
  owns(requestId: string): boolean;
77
101
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"PhonePhotoCoordinator.d.ts","sourceRoot":"","sources":["../../src/services/PhonePhotoCoordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AA6BH,MAAM,WAAW,SAAS;IACxB,mFAAmF;IACnF,IAAI,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAA;IACrE,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;IAC7C,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;iEACiE;AACjE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAA;AAC9E,iDAAiD;AACjD,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,CAAA;AAEjE,qBAAa,UAAW,SAAQ,KAAK;aAEjB,IAAI,EAAE,MAAM;aAEZ,KAAK,CAAC,EAAE,UAAU;aAClB,SAAS,CAAC,EAAE,cAAc;gBAH1B,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,UAAU,YAAA,EAClB,SAAS,CAAC,EAAE,cAAc,YAAA;CAK7C;AASD;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,QAAS,CAAA;AAiBjD,qBAAa,qBAAqB;IAIhC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAmC;IAClE,oEAAoE;IACpE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA4B;IAEnD,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC;IAgJ1E,iFAAiF;IACjF,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAInD;;;;;;OAMG;IACG,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;QAAC,IAAI,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAC,GAC7F,OAAO,CAAC,IAAI,CAAC;IAkBhB,4FAA4F;IAC5F,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAKhC;;;;OAIG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAWlF,OAAO,CAAC,YAAY;CAWrB;AAGD,eAAO,MAAM,qBAAqB,uBAA8B,CAAA"}
1
+ {"version":3,"file":"PhonePhotoCoordinator.d.ts","sourceRoot":"","sources":["../../src/services/PhonePhotoCoordinator.ts"],"names":[],"mappings":"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"}
@@ -48,6 +48,13 @@ export class PhotoError extends Error {
48
48
  this.name = "PhotoError";
49
49
  }
50
50
  }
51
+ function parsePhotoTransferMethod(value) {
52
+ if (value === undefined)
53
+ return undefined;
54
+ if (value === "auto" || value === "direct" || value === "ble")
55
+ return value;
56
+ throw new PhotoError("INVALID_ARGUMENT", `Invalid transferMethod ${JSON.stringify(value)}. Expected "auto", "direct", or "ble".`);
57
+ }
51
58
  /**
52
59
  * Last-resort ceiling for the complete capture + encode + transfer + upload
53
60
  * pipeline. This must exceed the managed-photo service's 30s ready-push
@@ -58,6 +65,8 @@ export class PhotoError extends Error {
58
65
  * rejected successful captures while their upload was still in progress.
59
66
  */
60
67
  export const CAPTURE_PIPELINE_TIMEOUT_MS = 45_000;
68
+ export const CAMERA_WARM_UP_DEFAULT_DURATION_MS = 15_000;
69
+ export const CAMERA_WARM_UP_MAX_DURATION_MS = 60_000;
61
70
  let bleRequestCounter = 0;
62
71
  /** Short 4-hex-char correlation id sent over BLE instead of the full cloud
63
72
  * requestId UUID (wire v2 keeps BLE JSON small). */
@@ -79,7 +88,17 @@ export class PhonePhotoCoordinator {
79
88
  activeRequests = new Map();
80
89
  /** Short BLE correlation id (4-char hex) → full cloud requestId. */
81
90
  bleIdToCloud = new Map();
91
+ activeWarmUps = new Map();
92
+ /** Report-safe camera ownership snapshot for incident diagnostics. */
93
+ getDiagnosticSnapshot() {
94
+ return {
95
+ captureOwners: [...new Set([...this.activeRequests.values()].map((request) => request.packageName))].sort(),
96
+ warmUpOwners: [...this.activeWarmUps.keys()].sort(),
97
+ activeCaptureCount: this.activeRequests.size,
98
+ };
99
+ }
82
100
  async takePhoto(packageName, opts) {
101
+ const transferMethod = parsePhotoTransferMethod(opts.transferMethod);
83
102
  // Pre-check: if glasses aren't even connected, the BLE photo command
84
103
  // would be sent into the void and we'd wait 30s for the cloud long-poll
85
104
  // to time out. Fail fast with a typed error.
@@ -94,6 +113,9 @@ export class PhonePhotoCoordinator {
94
113
  if (!isGlassesConnected(useGlassesStore.getState().connection)) {
95
114
  throw new PhotoError("GLASSES_NOT_CONNECTED", "Glasses are not connected", "command", "ble");
96
115
  }
116
+ // Text-mode sensor resolution is owned by ASG constants; keep cloud metadata on a stable
117
+ // high-capacity tier and let the glasses ignore the public size when mode=text.
118
+ const captureSize = opts.size ?? "medium";
97
119
  // 1) Presign via the cloud-v2 managed-photo service. Local miniapps use
98
120
  // ONLY the cloud-v2 path: the runtime presigns upload+read URLs and the
99
121
  // phone (as the device controller) delivers the bytes; the legacy
@@ -104,10 +126,12 @@ export class PhonePhotoCoordinator {
104
126
  const flowStarted = performance.now();
105
127
  try {
106
128
  const presignStarted = performance.now();
107
- const r = await cloudClientService.startManagedPhoto({ size: opts.size ?? "medium" });
129
+ const r = await cloudClientService.startManagedPhoto({
130
+ size: opts.mode === "text" ? "max" : captureSize,
131
+ });
108
132
  const presignMs = Math.round(performance.now() - presignStarted);
109
133
  if (typeof __DEV__ !== "undefined" && __DEV__) {
110
- console.debug(`[PhonePhotoCoordinator] presign ${presignMs}ms size=${opts.size ?? "medium"}`);
134
+ console.debug(`[PhonePhotoCoordinator] presign ${presignMs}ms size=${opts.mode === "text" ? "max" : captureSize} mode=${opts.mode ?? "photo"}`);
111
135
  }
112
136
  requestId = r.requestId;
113
137
  uploadUrl = r.uploadUrl;
@@ -151,21 +175,30 @@ export class PhonePhotoCoordinator {
151
175
  void outcome.then(clearWatchdog, clearWatchdog);
152
176
  // 3) Drive glasses over BLE. requestPhoto now resolves at terminal
153
177
  // photo_response success, so run it beside the cloud poll instead of
154
- // awaiting it before polling. iOS auto-injects transferMethod: "auto"
155
- // (WiFi direct with BLE fallback) see MentraLive.swift.
178
+ // awaiting it before polling. Native defaults transferMethod to "auto"
179
+ // (Wi-Fi direct with BLE fallback) unless the miniapp forces BLE.
156
180
  try {
157
181
  void BluetoothSdk.requestPhoto({
158
182
  requestId: bleRequestId,
159
183
  appId: packageName,
160
- size: normalizePhotoSize(opts.size ?? "medium"),
184
+ size: normalizePhotoSize(captureSize),
161
185
  mode: opts.mode ?? "photo",
162
186
  webhookUrl: uploadUrl,
163
187
  authToken: null,
164
- ...(isLoopbackUpload ? { transferMethod: "ble" } : {}),
188
+ ...(isLoopbackUpload ? { transferMethod: "ble" } : transferMethod ? { transferMethod } : {}),
165
189
  compress: toNativeCompression(opts.compress),
166
190
  save: opts.saveToGallery ?? false,
167
191
  sound: opts.sound ?? true,
168
192
  exposureTimeNs: opts.exposureTimeNs ?? null,
193
+ iso: opts.iso,
194
+ aeExposureDivisor: opts.aeExposureDivisor,
195
+ isoCap: opts.isoCap,
196
+ noiseReduction: opts.noiseReduction,
197
+ edgeEnhancement: opts.edgeEnhancement,
198
+ ...(opts.zsl != null ? { zsl: opts.zsl } : {}),
199
+ ...(opts.mfnr != null ? { mfnr: opts.mfnr } : {}),
200
+ ispDigitalGain: opts.ispDigitalGain,
201
+ ispAnalogGain: opts.ispAnalogGain,
169
202
  }).catch((err) => {
170
203
  const e = this.activeRequests.get(requestId);
171
204
  if (!e)
@@ -219,8 +252,8 @@ export class PhonePhotoCoordinator {
219
252
  /**
220
253
  * Pre-warm the glasses camera so the next takePhoto() is near-instant.
221
254
  *
222
- * Pure BLE — NO cloud presign, NO upload, NO long-poll. The SDK mints the
223
- * requestId, sends the warm-up command, and resolves when the camera reports
255
+ * Pure BLE — NO cloud presign, NO upload, NO long-poll. The phone mints and owns
256
+ * the requestId, sends the warm-up command, and resolves when the camera reports
224
257
  * ready (the native promise resolves on the ready status event).
225
258
  */
226
259
  async warmUpCamera(packageName, opts) {
@@ -229,17 +262,54 @@ export class PhonePhotoCoordinator {
229
262
  if (!isGlassesConnected(useGlassesStore.getState().connection)) {
230
263
  throw new PhotoError("GLASSES_NOT_CONNECTED", "Glasses are not connected", "command", "ble");
231
264
  }
265
+ let lease;
232
266
  try {
267
+ await this.stopWarmUpForApp(packageName);
268
+ const requestId = mintBleRequestId();
269
+ const requestedDuration = typeof opts.durationMs === "number" && Number.isFinite(opts.durationMs) && opts.durationMs > 0
270
+ ? Math.round(opts.durationMs)
271
+ : CAMERA_WARM_UP_DEFAULT_DURATION_MS;
272
+ const durationMs = Math.min(requestedDuration, CAMERA_WARM_UP_MAX_DURATION_MS);
273
+ lease = { requestId, durationMs };
274
+ this.activeWarmUps.set(packageName, lease);
233
275
  await BluetoothSdk.warmUpCamera({
276
+ requestId,
234
277
  size: normalizePhotoSize(opts.size ?? "medium"),
278
+ mode: opts.mode ?? "photo",
235
279
  exposureTimeNs: opts.exposureTimeNs ?? null,
236
- durationMs: opts.durationMs ?? 15000,
280
+ durationMs,
281
+ ...(opts.zsl != null ? { zsl: opts.zsl } : {}),
282
+ ...(opts.mfnr != null ? { mfnr: opts.mfnr } : {}),
237
283
  });
284
+ if (this.activeWarmUps.get(packageName) === lease) {
285
+ lease.expiryTimer = setTimeout(() => {
286
+ if (this.activeWarmUps.get(packageName) === lease) {
287
+ this.activeWarmUps.delete(packageName);
288
+ }
289
+ }, durationMs);
290
+ }
238
291
  }
239
292
  catch (err) {
293
+ if (lease && this.activeWarmUps.get(packageName) === lease) {
294
+ if (lease.expiryTimer)
295
+ clearTimeout(lease.expiryTimer);
296
+ this.activeWarmUps.delete(packageName);
297
+ }
240
298
  throw this.toPhotoError(err, "WARM_UP_FAILED", "command", "ble");
241
299
  }
242
300
  }
301
+ /** Release a miniapp's warm-up even if its original warmUpCamera promise is still opening. */
302
+ async stopWarmUpForApp(packageName) {
303
+ const active = this.activeWarmUps.get(packageName);
304
+ if (!active)
305
+ return;
306
+ await BluetoothSdk.stopCameraWarmUp(active.requestId);
307
+ if (this.activeWarmUps.get(packageName) === active) {
308
+ this.activeWarmUps.delete(packageName);
309
+ if (active.expiryTimer)
310
+ clearTimeout(active.expiryTimer);
311
+ }
312
+ }
243
313
  /** True iff this requestId (short BLE id or cloud id) is one we're currently waiting on. */
244
314
  owns(requestId) {
245
315
  const cloudId = this.resolveCloudRequestId(requestId);
@@ -1 +1 @@
1
- {"version":3,"file":"PhonePhotoCoordinator.js","sourceRoot":"","sources":["../../src/services/PhonePhotoCoordinator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PhonePhotoCoordinator — owns local-miniapp takePhoto() end-to-end.\n *\n * Architecture:\n * miniapp → SDK → LocalMiniappRuntime → photo runtime hook\n * → coordinator.takePhoto(packageName, opts)\n * ├── (precheck) glasses connected + hasCamera\n * ├── cloudClientService.startManagedPhoto → {requestId, uploadUrl, readUrl} (cloud-v2 runtime presign)\n * ├── BluetoothSdk.requestPhoto(requestId, size, uploadUrl, compress, sound)\n * └── race:\n * - cloudClientService.awaitManagedPhotoReady(requestId) resolves on photo.ready push\n * - BluetoothSdk.requestPhoto rejects if terminal photo_response is an error\n * - handlePhotoError(requestId, code, message) rejects if MantleManager observes\n * the same BLE photo_response error before the native promise crosses the bridge\n *\n * `activeRequests` lets MantleManager's gated `photo_response` listener\n * short-circuit our long-poll with a typed error (CAMERA_BUSY, BATTERY_LOW,\n * etc.) instead of waiting 30s for cloud's timeout.\n */\n\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport type {PhotoSize} from \"@mentra/bluetooth-sdk/internal\"\nimport {cloudClientService} from \"./CloudClientService\"\nimport {isGlassesConnected} from \"./GlassesReadiness\"\nimport {useGlassesStore} from \"../stores/glasses\"\n\ninterface PhotoResult {\n photoUrl: string\n mimeType: string\n size: number\n}\n\n/** Map legacy/cloud size names onto the native take_photo enum. */\nfunction normalizePhotoSize(value: unknown): PhotoSize {\n if (typeof value !== \"string\") return \"medium\"\n switch (value) {\n case \"small\":\n return \"low\"\n case \"large\":\n return \"high\"\n case \"full\":\n return \"max\"\n default:\n return ([\"low\", \"medium\", \"high\", \"max\"] as const).includes(value as PhotoSize) ? (value as PhotoSize) : \"medium\"\n }\n}\n\nexport interface PhotoOpts {\n /** Legacy cloud size names are normalized before the native take_photo command. */\n size?: \"low\" | \"medium\" | \"high\" | \"max\" | \"small\" | \"large\" | \"full\"\n mode?: \"photo\" | \"text\"\n compress?: \"none\" | \"low\" | \"medium\" | \"high\"\n sound?: boolean\n saveToGallery?: boolean\n exposureTimeNs?: number\n}\n\nexport interface PhotoTaken {\n photoUrl: string\n mimeType: string\n size: number\n requestId: string\n}\n\n/** Pipeline stage a photo request failed at — surfaced to the miniapp so a dev\n * sees exactly where it broke, not just a flattened message. */\nexport type PhotoStage = \"presign\" | \"command\" | \"capture\" | \"upload\" | \"push\"\n/** Transport in play at the point of failure. */\nexport type PhotoTransport = \"cloud-rest\" | \"ble\" | \"wifi\" | \"ws\"\n\nexport class PhotoError extends Error {\n constructor(\n public readonly code: string,\n message: string,\n public readonly stage?: PhotoStage,\n public readonly transport?: PhotoTransport,\n ) {\n super(message)\n this.name = \"PhotoError\"\n }\n}\n\ninterface ActiveRequest {\n packageName: string\n abort: AbortController\n resolve: (r: PhotoResult) => void\n reject: (err: Error) => void\n}\n\n/**\n * Last-resort ceiling for the complete capture + encode + transfer + upload\n * pipeline. This must exceed the managed-photo service's 30s ready-push\n * timeout so the cloud can return its more specific failure first.\n *\n * Text mode commonly spends several seconds detecting/cropping the region and\n * can take another 10s+ to transfer over BLE. A 15s ceiling incorrectly\n * rejected successful captures while their upload was still in progress.\n */\nexport const CAPTURE_PIPELINE_TIMEOUT_MS = 45_000\n\nlet bleRequestCounter = 0\n\n/** Short 4-hex-char correlation id sent over BLE instead of the full cloud\n * requestId UUID (wire v2 keeps BLE JSON small). */\nfunction mintBleRequestId(): string {\n bleRequestCounter = (bleRequestCounter + 1) & 0xffff\n return bleRequestCounter.toString(16).padStart(4, \"0\")\n}\n\nfunction toNativeCompression(compress: PhotoOpts[\"compress\"]): \"none\" | \"medium\" | \"heavy\" {\n if (compress === \"high\") return \"heavy\"\n if (compress === \"low\" || compress === \"medium\") return \"medium\"\n return \"none\"\n}\n\nexport class PhonePhotoCoordinator {\n // Cloud requestId → in-flight slot. The gated photo_response listener\n // (DeviceEventRouter) resolves short BLE ids via bleIdToCloud before calling\n // owns() / handlePhotoError().\n private readonly activeRequests = new Map<string, ActiveRequest>()\n /** Short BLE correlation id (4-char hex) → full cloud requestId. */\n private readonly bleIdToCloud = new Map<string, string>()\n\n async takePhoto(packageName: string, opts: PhotoOpts): Promise<PhotoTaken> {\n // Pre-check: if glasses aren't even connected, the BLE photo command\n // would be sent into the void and we'd wait 30s for the cloud long-poll\n // to time out. Fail fast with a typed error.\n //\n // We DON'T pre-check `hasCamera` here — the canonical capability data\n // lives in `getModelCapabilities(deviceModel)` from @mentra/types and\n // pulling that into this file would add a cross-package import. If a\n // cameraless device receives the BLE photo command, the glasses-side\n // handler will return a photo_response error within ~1s and the gated\n // photo_response listener in MantleManager will short-circuit our\n // long-poll. Slower but correct.\n if (!isGlassesConnected(useGlassesStore.getState().connection)) {\n throw new PhotoError(\"GLASSES_NOT_CONNECTED\", \"Glasses are not connected\", \"command\", \"ble\")\n }\n\n // 1) Presign via the cloud-v2 managed-photo service. Local miniapps use\n // ONLY the cloud-v2 path: the runtime presigns upload+read URLs and the\n // phone (as the device controller) delivers the bytes; the legacy\n // backend_url mint is gone from this flow.\n let requestId: string\n let uploadUrl: string\n let readUrl: string\n const flowStarted = performance.now()\n try {\n const presignStarted = performance.now()\n const r = await cloudClientService.startManagedPhoto({size: opts.size ?? \"medium\"})\n const presignMs = Math.round(performance.now() - presignStarted)\n if (typeof __DEV__ !== \"undefined\" && __DEV__) {\n console.debug(`[PhonePhotoCoordinator] presign ${presignMs}ms size=${opts.size ?? \"medium\"}`)\n }\n requestId = r.requestId\n uploadUrl = r.uploadUrl\n readUrl = r.readUrl\n } catch (err) {\n throw this.toPhotoError(err, \"PHOTO_REQUEST_FAILED\", \"presign\", \"cloud-rest\")\n }\n\n // 2) Build the outcome Promise FIRST so both resolve+reject handles\n // are wired into activeRequests BEFORE any code path can produce\n // an error. Without this, a fast BLE photo_response (BATTERY_LOW\n // etc.) racing with the Promise constructor could fire\n // handlePhotoError() against a no-op rejectFn and silently drop\n // the error.\n // When the managed-photo upload URL is loopback (the local storage provider\n // reached over `adb reverse`), the glasses cannot reach it over WiFi —\n // localhost on the glasses is the glasses. Force BLE transfer so the phone\n // (which CAN reach the reversed runtime) relays the bytes; a public r2/s3\n // presigned URL stays on \"auto\".\n const isLoopbackUpload = /^https?:\\/\\/(localhost|127\\.0\\.0\\.1|10\\.0\\.2\\.2)\\b/.test(uploadUrl)\n\n const abort = new AbortController()\n const bleRequestId = mintBleRequestId()\n this.bleIdToCloud.set(bleRequestId, requestId)\n\n const outcome = new Promise<PhotoResult>((resolve, reject) => {\n this.activeRequests.set(requestId, {packageName, abort, resolve, reject})\n })\n\n // Last-resort watchdog for a wedged pipeline. The managed-photo ready push\n // normally resolves or rejects first; this only prevents an indefinite hang\n // if both the native terminal response and cloud push disappear.\n const captureWatchdog = setTimeout(() => {\n const e = this.activeRequests.get(requestId)\n if (!e) return\n e.abort.abort()\n e.reject(\n new PhotoError(\n \"CAPTURE_TIMEOUT\",\n \"Photo capture did not complete. The take_photo command, media processing, transfer, or upload may have stalled.\",\n \"capture\",\n isLoopbackUpload ? \"ble\" : \"wifi\",\n ),\n )\n }, CAPTURE_PIPELINE_TIMEOUT_MS)\n // Clear the watchdog on BOTH arms. Not `.finally()`: that would mint a new\n // promise that re-rejects unobserved whenever the photo fails (the caller\n // only awaits `outcome` itself), i.e. an unhandled rejection per failure.\n const clearWatchdog = () => clearTimeout(captureWatchdog)\n void outcome.then(clearWatchdog, clearWatchdog)\n\n // 3) Drive glasses over BLE. requestPhoto now resolves at terminal\n // photo_response success, so run it beside the cloud poll instead of\n // awaiting it before polling. iOS auto-injects transferMethod: \"auto\"\n // (WiFi direct with BLE fallback) — see MentraLive.swift.\n try {\n void BluetoothSdk.requestPhoto({\n requestId: bleRequestId,\n appId: packageName,\n size: normalizePhotoSize(opts.size ?? \"medium\"),\n mode: opts.mode ?? \"photo\",\n webhookUrl: uploadUrl,\n authToken: null,\n ...(isLoopbackUpload ? {transferMethod: \"ble\" as const} : {}),\n compress: toNativeCompression(opts.compress),\n save: opts.saveToGallery ?? false,\n sound: opts.sound ?? true,\n exposureTimeNs: opts.exposureTimeNs ?? null,\n }).catch((err) => {\n const e = this.activeRequests.get(requestId)\n if (!e) return\n e.abort.abort()\n e.reject(this.toPhotoError(err, \"BLE_SEND_FAILED\", \"command\", \"ble\"))\n })\n } catch (err) {\n this.activeRequests.delete(requestId)\n this.bleIdToCloud.delete(bleRequestId)\n throw this.toPhotoError(err, \"BLE_SEND_FAILED\", \"command\", \"ble\")\n }\n\n // 4) Await the runtime's photo.ready push (replaces the legacy long-poll).\n // handlePhotoError races against it and uses the same entry to reject\n // first.\n cloudClientService\n .awaitManagedPhotoReady(requestId)\n .then((res) => {\n const e = this.activeRequests.get(requestId)\n if (!e) return // already settled by handlePhotoError\n e.resolve({photoUrl: res.readUrl ?? readUrl, mimeType: \"image/jpeg\", size: -1})\n })\n .catch((err) => {\n const e = this.activeRequests.get(requestId)\n if (e) e.reject(this.toPhotoError(err, \"POLL_FAILED\", \"push\", \"ws\"))\n })\n\n try {\n const result = await outcome\n if (typeof __DEV__ !== \"undefined\" && __DEV__) {\n console.debug(\n `[PhonePhotoCoordinator] takePhoto complete ${Math.round(performance.now() - flowStarted)}ms requestId=${requestId}`,\n )\n }\n return {\n photoUrl: result.photoUrl,\n mimeType: result.mimeType,\n size: result.size,\n requestId,\n }\n } finally {\n this.activeRequests.delete(requestId)\n this.bleIdToCloud.delete(bleRequestId)\n }\n }\n\n /** Map a short BLE requestId from photo_response back to the cloud requestId. */\n resolveCloudRequestId(bleOrCloudId: string): string {\n return this.bleIdToCloud.get(bleOrCloudId) ?? bleOrCloudId\n }\n\n /**\n * Pre-warm the glasses camera so the next takePhoto() is near-instant.\n *\n * Pure BLE — NO cloud presign, NO upload, NO long-poll. The SDK mints the\n * requestId, sends the warm-up command, and resolves when the camera reports\n * ready (the native promise resolves on the ready status event).\n */\n async warmUpCamera(\n packageName: string,\n opts: {size?: \"low\" | \"medium\" | \"high\" | \"max\"; exposureTimeNs?: number; durationMs?: number},\n ): Promise<void> {\n // Pre-check: if glasses aren't connected, the BLE warm-up command would be\n // sent into the void. Fail fast with a typed error.\n if (!isGlassesConnected(useGlassesStore.getState().connection)) {\n throw new PhotoError(\"GLASSES_NOT_CONNECTED\", \"Glasses are not connected\", \"command\", \"ble\")\n }\n\n try {\n await BluetoothSdk.warmUpCamera({\n size: normalizePhotoSize(opts.size ?? \"medium\"),\n exposureTimeNs: opts.exposureTimeNs ?? null,\n durationMs: opts.durationMs ?? 15000,\n })\n } catch (err) {\n throw this.toPhotoError(err, \"WARM_UP_FAILED\", \"command\", \"ble\")\n }\n }\n\n /** True iff this requestId (short BLE id or cloud id) is one we're currently waiting on. */\n owns(requestId: string): boolean {\n const cloudId = this.resolveCloudRequestId(requestId)\n return this.activeRequests.has(cloudId)\n }\n\n /**\n * Called by MantleManager's gated photo_response listener when glasses\n * report an error (BATTERY_LOW, CAMERA_BUSY, etc.) for a phone-owned\n * requestId. Rejects the in-flight takePhoto Promise immediately.\n */\n handlePhotoError(requestId: string, errorCode: string, errorMessage: string): void {\n const cloudId = this.resolveCloudRequestId(requestId)\n const entry = this.activeRequests.get(cloudId)\n if (!entry) return\n this.bleIdToCloud.delete(requestId)\n // Abort the in-flight long-poll first so we don't double-resolve.\n entry.abort.abort()\n entry.reject(new PhotoError(errorCode || \"GLASSES_ERROR\", errorMessage || \"Glasses error\", \"capture\", \"ble\"))\n // cloud-v2 pending photo requests TTL out on their own; nothing to free.\n }\n\n private toPhotoError(\n err: unknown,\n fallbackCode: string,\n stage?: PhotoStage,\n transport?: PhotoTransport,\n ): PhotoError {\n if (err instanceof PhotoError) return err\n const code = (err as {code?: string})?.code\n const message = err instanceof Error ? err.message : String(err)\n return new PhotoError(code || fallbackCode, message, stage, transport)\n }\n}\n\n// Singleton — coordinator state is process-wide (mirrors phoneStreamCoordinator).\nexport const phonePhotoCoordinator = new PhonePhotoCoordinator()\n"]}
1
+ {"version":3,"file":"PhonePhotoCoordinator.js","sourceRoot":"","sources":["../../src/services/PhonePhotoCoordinator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PhonePhotoCoordinator — owns local-miniapp takePhoto() end-to-end.\n *\n * Architecture:\n * miniapp → SDK → LocalMiniappRuntime → photo runtime hook\n * → coordinator.takePhoto(packageName, opts)\n * ├── (precheck) glasses connected + hasCamera\n * ├── cloudClientService.startManagedPhoto → {requestId, uploadUrl, readUrl} (cloud-v2 runtime presign)\n * ├── BluetoothSdk.requestPhoto(requestId, size, uploadUrl, compress, sound)\n * └── race:\n * - cloudClientService.awaitManagedPhotoReady(requestId) resolves on photo.ready push\n * - BluetoothSdk.requestPhoto rejects if terminal photo_response is an error\n * - handlePhotoError(requestId, code, message) rejects if MantleManager observes\n * the same BLE photo_response error before the native promise crosses the bridge\n *\n * `activeRequests` lets MantleManager's gated `photo_response` listener\n * short-circuit our long-poll with a typed error (CAMERA_BUSY, BATTERY_LOW,\n * etc.) instead of waiting 30s for cloud's timeout.\n */\n\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\nimport type {PhotoSize, PhotoTransferMethod} from \"@mentra/bluetooth-sdk/internal\"\nimport {cloudClientService} from \"./CloudClientService\"\nimport {isGlassesConnected} from \"./GlassesReadiness\"\nimport {useGlassesStore} from \"../stores/glasses\"\n\ninterface PhotoResult {\n photoUrl: string\n mimeType: string\n size: number\n}\n\n/** Map legacy/cloud size names onto the native take_photo enum. */\nfunction normalizePhotoSize(value: unknown): PhotoSize {\n if (typeof value !== \"string\") return \"medium\"\n switch (value) {\n case \"small\":\n return \"low\"\n case \"large\":\n return \"high\"\n case \"full\":\n return \"max\"\n default:\n return ([\"low\", \"medium\", \"high\", \"max\"] as const).includes(value as PhotoSize) ? (value as PhotoSize) : \"medium\"\n }\n}\n\nexport interface PhotoOpts {\n /** Legacy cloud size names are normalized before the native take_photo command. */\n size?: \"low\" | \"medium\" | \"high\" | \"max\" | \"small\" | \"large\" | \"full\"\n mode?: \"photo\" | \"text\"\n /** Select direct-only, phone-relayed BLE, or the default Wi-Fi/BLE fallback policy. */\n transferMethod?: PhotoTransferMethod\n compress?: \"none\" | \"low\" | \"medium\" | \"high\"\n sound?: boolean\n saveToGallery?: boolean\n exposureTimeNs?: number\n iso?: number | null\n aeExposureDivisor?: number\n isoCap?: number\n noiseReduction?: boolean\n edgeEnhancement?: boolean\n /** ZSL preview buffering. */\n zsl?: boolean\n /** MFNR still capture. */\n mfnr?: boolean\n ispDigitalGain?: number\n ispAnalogGain?: string\n}\n\nexport interface PhotoTaken {\n photoUrl: string\n mimeType: string\n size: number\n requestId: string\n}\n\n/** Pipeline stage a photo request failed at — surfaced to the miniapp so a dev\n * sees exactly where it broke, not just a flattened message. */\nexport type PhotoStage = \"presign\" | \"command\" | \"capture\" | \"upload\" | \"push\"\n/** Transport in play at the point of failure. */\nexport type PhotoTransport = \"cloud-rest\" | \"ble\" | \"wifi\" | \"ws\"\n\nexport class PhotoError extends Error {\n constructor(\n public readonly code: string,\n message: string,\n public readonly stage?: PhotoStage,\n public readonly transport?: PhotoTransport,\n ) {\n super(message)\n this.name = \"PhotoError\"\n }\n}\n\nfunction parsePhotoTransferMethod(value: unknown): PhotoTransferMethod | undefined {\n if (value === undefined) return undefined\n if (value === \"auto\" || value === \"direct\" || value === \"ble\") return value\n throw new PhotoError(\n \"INVALID_ARGUMENT\",\n `Invalid transferMethod ${JSON.stringify(value)}. Expected \"auto\", \"direct\", or \"ble\".`,\n )\n}\n\ninterface ActiveRequest {\n packageName: string\n abort: AbortController\n resolve: (r: PhotoResult) => void\n reject: (err: Error) => void\n}\n\n/**\n * Last-resort ceiling for the complete capture + encode + transfer + upload\n * pipeline. This must exceed the managed-photo service's 30s ready-push\n * timeout so the cloud can return its more specific failure first.\n *\n * Text mode commonly spends several seconds detecting/cropping the region and\n * can take another 10s+ to transfer over BLE. A 15s ceiling incorrectly\n * rejected successful captures while their upload was still in progress.\n */\nexport const CAPTURE_PIPELINE_TIMEOUT_MS = 45_000\nexport const CAMERA_WARM_UP_DEFAULT_DURATION_MS = 15_000\nexport const CAMERA_WARM_UP_MAX_DURATION_MS = 60_000\n\nlet bleRequestCounter = 0\n\n/** Short 4-hex-char correlation id sent over BLE instead of the full cloud\n * requestId UUID (wire v2 keeps BLE JSON small). */\nfunction mintBleRequestId(): string {\n bleRequestCounter = (bleRequestCounter + 1) & 0xffff\n return bleRequestCounter.toString(16).padStart(4, \"0\")\n}\n\nfunction toNativeCompression(compress: PhotoOpts[\"compress\"]): \"none\" | \"medium\" | \"heavy\" {\n if (compress === \"high\") return \"heavy\"\n if (compress === \"low\" || compress === \"medium\") return \"medium\"\n return \"none\"\n}\n\nexport class PhonePhotoCoordinator {\n // Cloud requestId → in-flight slot. The gated photo_response listener\n // (DeviceEventRouter) resolves short BLE ids via bleIdToCloud before calling\n // owns() / handlePhotoError().\n private readonly activeRequests = new Map<string, ActiveRequest>()\n /** Short BLE correlation id (4-char hex) → full cloud requestId. */\n private readonly bleIdToCloud = new Map<string, string>()\n private readonly activeWarmUps = new Map<\n string,\n {requestId: string; durationMs: number; expiryTimer?: ReturnType<typeof setTimeout>}\n >()\n\n /** Report-safe camera ownership snapshot for incident diagnostics. */\n getDiagnosticSnapshot(): Record<string, unknown> {\n return {\n captureOwners: [...new Set([...this.activeRequests.values()].map((request) => request.packageName))].sort(),\n warmUpOwners: [...this.activeWarmUps.keys()].sort(),\n activeCaptureCount: this.activeRequests.size,\n }\n }\n\n async takePhoto(packageName: string, opts: PhotoOpts): Promise<PhotoTaken> {\n const transferMethod = parsePhotoTransferMethod(opts.transferMethod)\n\n // Pre-check: if glasses aren't even connected, the BLE photo command\n // would be sent into the void and we'd wait 30s for the cloud long-poll\n // to time out. Fail fast with a typed error.\n //\n // We DON'T pre-check `hasCamera` here — the canonical capability data\n // lives in `getModelCapabilities(deviceModel)` from @mentra/types and\n // pulling that into this file would add a cross-package import. If a\n // cameraless device receives the BLE photo command, the glasses-side\n // handler will return a photo_response error within ~1s and the gated\n // photo_response listener in MantleManager will short-circuit our\n // long-poll. Slower but correct.\n if (!isGlassesConnected(useGlassesStore.getState().connection)) {\n throw new PhotoError(\"GLASSES_NOT_CONNECTED\", \"Glasses are not connected\", \"command\", \"ble\")\n }\n\n // Text-mode sensor resolution is owned by ASG constants; keep cloud metadata on a stable\n // high-capacity tier and let the glasses ignore the public size when mode=text.\n const captureSize = opts.size ?? \"medium\"\n\n // 1) Presign via the cloud-v2 managed-photo service. Local miniapps use\n // ONLY the cloud-v2 path: the runtime presigns upload+read URLs and the\n // phone (as the device controller) delivers the bytes; the legacy\n // backend_url mint is gone from this flow.\n let requestId: string\n let uploadUrl: string\n let readUrl: string\n const flowStarted = performance.now()\n try {\n const presignStarted = performance.now()\n const r = await cloudClientService.startManagedPhoto({\n size: opts.mode === \"text\" ? \"max\" : captureSize,\n })\n const presignMs = Math.round(performance.now() - presignStarted)\n if (typeof __DEV__ !== \"undefined\" && __DEV__) {\n console.debug(\n `[PhonePhotoCoordinator] presign ${presignMs}ms size=${opts.mode === \"text\" ? \"max\" : captureSize} mode=${\n opts.mode ?? \"photo\"\n }`,\n )\n }\n requestId = r.requestId\n uploadUrl = r.uploadUrl\n readUrl = r.readUrl\n } catch (err) {\n throw this.toPhotoError(err, \"PHOTO_REQUEST_FAILED\", \"presign\", \"cloud-rest\")\n }\n\n // 2) Build the outcome Promise FIRST so both resolve+reject handles\n // are wired into activeRequests BEFORE any code path can produce\n // an error. Without this, a fast BLE photo_response (BATTERY_LOW\n // etc.) racing with the Promise constructor could fire\n // handlePhotoError() against a no-op rejectFn and silently drop\n // the error.\n // When the managed-photo upload URL is loopback (the local storage provider\n // reached over `adb reverse`), the glasses cannot reach it over WiFi —\n // localhost on the glasses is the glasses. Force BLE transfer so the phone\n // (which CAN reach the reversed runtime) relays the bytes; a public r2/s3\n // presigned URL stays on \"auto\".\n const isLoopbackUpload = /^https?:\\/\\/(localhost|127\\.0\\.0\\.1|10\\.0\\.2\\.2)\\b/.test(uploadUrl)\n\n const abort = new AbortController()\n const bleRequestId = mintBleRequestId()\n this.bleIdToCloud.set(bleRequestId, requestId)\n\n const outcome = new Promise<PhotoResult>((resolve, reject) => {\n this.activeRequests.set(requestId, {packageName, abort, resolve, reject})\n })\n\n // Last-resort watchdog for a wedged pipeline. The managed-photo ready push\n // normally resolves or rejects first; this only prevents an indefinite hang\n // if both the native terminal response and cloud push disappear.\n const captureWatchdog = setTimeout(() => {\n const e = this.activeRequests.get(requestId)\n if (!e) return\n e.abort.abort()\n e.reject(\n new PhotoError(\n \"CAPTURE_TIMEOUT\",\n \"Photo capture did not complete. The take_photo command, media processing, transfer, or upload may have stalled.\",\n \"capture\",\n isLoopbackUpload ? \"ble\" : \"wifi\",\n ),\n )\n }, CAPTURE_PIPELINE_TIMEOUT_MS)\n // Clear the watchdog on BOTH arms. Not `.finally()`: that would mint a new\n // promise that re-rejects unobserved whenever the photo fails (the caller\n // only awaits `outcome` itself), i.e. an unhandled rejection per failure.\n const clearWatchdog = () => clearTimeout(captureWatchdog)\n void outcome.then(clearWatchdog, clearWatchdog)\n\n // 3) Drive glasses over BLE. requestPhoto now resolves at terminal\n // photo_response success, so run it beside the cloud poll instead of\n // awaiting it before polling. Native defaults transferMethod to \"auto\"\n // (Wi-Fi direct with BLE fallback) unless the miniapp forces BLE.\n try {\n void BluetoothSdk.requestPhoto({\n requestId: bleRequestId,\n appId: packageName,\n size: normalizePhotoSize(captureSize),\n mode: opts.mode ?? \"photo\",\n webhookUrl: uploadUrl,\n authToken: null,\n ...(isLoopbackUpload ? {transferMethod: \"ble\" as const} : transferMethod ? {transferMethod} : {}),\n compress: toNativeCompression(opts.compress),\n save: opts.saveToGallery ?? false,\n sound: opts.sound ?? true,\n exposureTimeNs: opts.exposureTimeNs ?? null,\n iso: opts.iso,\n aeExposureDivisor: opts.aeExposureDivisor,\n isoCap: opts.isoCap,\n noiseReduction: opts.noiseReduction,\n edgeEnhancement: opts.edgeEnhancement,\n ...(opts.zsl != null ? {zsl: opts.zsl} : {}),\n ...(opts.mfnr != null ? {mfnr: opts.mfnr} : {}),\n ispDigitalGain: opts.ispDigitalGain,\n ispAnalogGain: opts.ispAnalogGain,\n }).catch((err) => {\n const e = this.activeRequests.get(requestId)\n if (!e) return\n e.abort.abort()\n e.reject(this.toPhotoError(err, \"BLE_SEND_FAILED\", \"command\", \"ble\"))\n })\n } catch (err) {\n this.activeRequests.delete(requestId)\n this.bleIdToCloud.delete(bleRequestId)\n throw this.toPhotoError(err, \"BLE_SEND_FAILED\", \"command\", \"ble\")\n }\n\n // 4) Await the runtime's photo.ready push (replaces the legacy long-poll).\n // handlePhotoError races against it and uses the same entry to reject\n // first.\n cloudClientService\n .awaitManagedPhotoReady(requestId)\n .then((res) => {\n const e = this.activeRequests.get(requestId)\n if (!e) return // already settled by handlePhotoError\n e.resolve({photoUrl: res.readUrl ?? readUrl, mimeType: \"image/jpeg\", size: -1})\n })\n .catch((err) => {\n const e = this.activeRequests.get(requestId)\n if (e) e.reject(this.toPhotoError(err, \"POLL_FAILED\", \"push\", \"ws\"))\n })\n\n try {\n const result = await outcome\n if (typeof __DEV__ !== \"undefined\" && __DEV__) {\n console.debug(\n `[PhonePhotoCoordinator] takePhoto complete ${Math.round(\n performance.now() - flowStarted,\n )}ms requestId=${requestId}`,\n )\n }\n return {\n photoUrl: result.photoUrl,\n mimeType: result.mimeType,\n size: result.size,\n requestId,\n }\n } finally {\n this.activeRequests.delete(requestId)\n this.bleIdToCloud.delete(bleRequestId)\n }\n }\n\n /** Map a short BLE requestId from photo_response back to the cloud requestId. */\n resolveCloudRequestId(bleOrCloudId: string): string {\n return this.bleIdToCloud.get(bleOrCloudId) ?? bleOrCloudId\n }\n\n /**\n * Pre-warm the glasses camera so the next takePhoto() is near-instant.\n *\n * Pure BLE — NO cloud presign, NO upload, NO long-poll. The phone mints and owns\n * the requestId, sends the warm-up command, and resolves when the camera reports\n * ready (the native promise resolves on the ready status event).\n */\n async warmUpCamera(\n packageName: string,\n opts: {\n size?: \"low\" | \"medium\" | \"high\" | \"max\"\n mode?: \"photo\" | \"text\"\n exposureTimeNs?: number\n durationMs?: number\n zsl?: boolean\n mfnr?: boolean\n },\n ): Promise<void> {\n // Pre-check: if glasses aren't connected, the BLE warm-up command would be\n // sent into the void. Fail fast with a typed error.\n if (!isGlassesConnected(useGlassesStore.getState().connection)) {\n throw new PhotoError(\"GLASSES_NOT_CONNECTED\", \"Glasses are not connected\", \"command\", \"ble\")\n }\n\n let lease: {requestId: string; durationMs: number; expiryTimer?: ReturnType<typeof setTimeout>} | undefined\n try {\n await this.stopWarmUpForApp(packageName)\n const requestId = mintBleRequestId()\n const requestedDuration =\n typeof opts.durationMs === \"number\" && Number.isFinite(opts.durationMs) && opts.durationMs > 0\n ? Math.round(opts.durationMs)\n : CAMERA_WARM_UP_DEFAULT_DURATION_MS\n const durationMs = Math.min(requestedDuration, CAMERA_WARM_UP_MAX_DURATION_MS)\n lease = {requestId, durationMs}\n this.activeWarmUps.set(packageName, lease)\n await BluetoothSdk.warmUpCamera({\n requestId,\n size: normalizePhotoSize(opts.size ?? \"medium\"),\n mode: opts.mode ?? \"photo\",\n exposureTimeNs: opts.exposureTimeNs ?? null,\n durationMs,\n ...(opts.zsl != null ? {zsl: opts.zsl} : {}),\n ...(opts.mfnr != null ? {mfnr: opts.mfnr} : {}),\n })\n if (this.activeWarmUps.get(packageName) === lease) {\n lease.expiryTimer = setTimeout(() => {\n if (this.activeWarmUps.get(packageName) === lease) {\n this.activeWarmUps.delete(packageName)\n }\n }, durationMs)\n }\n } catch (err) {\n if (lease && this.activeWarmUps.get(packageName) === lease) {\n if (lease.expiryTimer) clearTimeout(lease.expiryTimer)\n this.activeWarmUps.delete(packageName)\n }\n throw this.toPhotoError(err, \"WARM_UP_FAILED\", \"command\", \"ble\")\n }\n }\n\n /** Release a miniapp's warm-up even if its original warmUpCamera promise is still opening. */\n async stopWarmUpForApp(packageName: string): Promise<void> {\n const active = this.activeWarmUps.get(packageName)\n if (!active) return\n await BluetoothSdk.stopCameraWarmUp(active.requestId)\n if (this.activeWarmUps.get(packageName) === active) {\n this.activeWarmUps.delete(packageName)\n if (active.expiryTimer) clearTimeout(active.expiryTimer)\n }\n }\n\n /** True iff this requestId (short BLE id or cloud id) is one we're currently waiting on. */\n owns(requestId: string): boolean {\n const cloudId = this.resolveCloudRequestId(requestId)\n return this.activeRequests.has(cloudId)\n }\n\n /**\n * Called by MantleManager's gated photo_response listener when glasses\n * report an error (BATTERY_LOW, CAMERA_BUSY, etc.) for a phone-owned\n * requestId. Rejects the in-flight takePhoto Promise immediately.\n */\n handlePhotoError(requestId: string, errorCode: string, errorMessage: string): void {\n const cloudId = this.resolveCloudRequestId(requestId)\n const entry = this.activeRequests.get(cloudId)\n if (!entry) return\n this.bleIdToCloud.delete(requestId)\n // Abort the in-flight long-poll first so we don't double-resolve.\n entry.abort.abort()\n entry.reject(new PhotoError(errorCode || \"GLASSES_ERROR\", errorMessage || \"Glasses error\", \"capture\", \"ble\"))\n // cloud-v2 pending photo requests TTL out on their own; nothing to free.\n }\n\n private toPhotoError(err: unknown, fallbackCode: string, stage?: PhotoStage, transport?: PhotoTransport): PhotoError {\n if (err instanceof PhotoError) return err\n const code = (err as {code?: string})?.code\n const message = err instanceof Error ? err.message : String(err)\n return new PhotoError(code || fallbackCode, message, stage, transport)\n }\n}\n\n// Singleton — coordinator state is process-wide (mirrors phoneStreamCoordinator).\nexport const phonePhotoCoordinator = new PhonePhotoCoordinator()\n"]}
@@ -38,6 +38,7 @@ declare const DEFAULT_TIMINGS: {
38
38
  readonly ackTimeoutMs: 10000;
39
39
  readonly maxMissedAcks: 3;
40
40
  readonly cloudflareStatusPollMs: 5000;
41
+ readonly cloudflareStartupPollInitialMs: 500;
41
42
  readonly hlsReadinessInitialDelayMs: 5000;
42
43
  readonly hlsReadinessPollMs: 2000;
43
44
  readonly hlsReadinessMaxAttempts: 30;
@@ -51,6 +52,8 @@ export interface StartUnmanagedOptions {
51
52
  video?: StreamStartRequest["video"];
52
53
  audio?: StreamStartRequest["audio"];
53
54
  sound?: boolean;
55
+ /** Optional Bearer token for WHIP Authorization (custom authenticated endpoints). */
56
+ authToken?: string;
54
57
  }
55
58
  export interface StartManagedOptions {
56
59
  restreamDestinations?: RestreamDestinationInput[];
@@ -64,8 +67,10 @@ export interface StartManagedOptions {
64
67
  * - "whip": WebRTC ingest -> WHEP playback (<1s glass-to-screen), but NO
65
68
  * HLS/DASH playback and NO recording (Cloudflare limitation; the returned
66
69
  * hlsUrl will serve 204 forever).
70
+ * - "rtmp": RTMPS ingest over TCP 443 -> HLS playback. Survives networks
71
+ * that drop WHIP/SRT UDP.
67
72
  */
68
- ingest?: "srt" | "whip";
73
+ ingest?: "srt" | "whip" | "rtmp";
69
74
  }
70
75
  export interface StreamPublisherStartResult {
71
76
  streamId: string;
@@ -139,6 +144,8 @@ export declare class PhoneStreamCoordinator {
139
144
  * check covers the multi-subscriber case.
140
145
  */
141
146
  owns(streamId: string): boolean;
147
+ /** Report-safe stream ownership snapshot for incident diagnostics. */
148
+ getDiagnosticSnapshot(): Record<string, unknown>;
142
149
  startUnmanaged(packageName: string, opts: StartUnmanagedOptions): Promise<StreamPublisherStartResult>;
143
150
  startManaged(packageName: string, opts: StartManagedOptions): Promise<ManagedStartResult>;
144
151
  stop(packageName: string, streamId?: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"PhoneStreamCoordinator.d.ts","sourceRoot":"","sources":["../../src/services/PhoneStreamCoordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,KAAK,EACV,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,gCAAgC,CAAA;AAMvC,OAAO,EAML,KAAK,wBAAwB,EAC9B,MAAM,kBAAkB,CAAA;AAEzB;;;GAGG;AACH,QAAA,MAAM,eAAe;;;;;;;;CASX,CAAA;AAEV,KAAK,YAAY,GAAG;KAAE,CAAC,IAAI,MAAM,OAAO,eAAe,GAAG,MAAM;CAAC,CAAA;AACjE,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;AAetD,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAA;IACnC,KAAK,CAAC,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAA;IACnC,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,oBAAoB,CAAC,EAAE,wBAAwB,EAAE,CAAA;IACjD,KAAK,CAAC,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAA;IACnC,KAAK,CAAC,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAA;IACnC,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,CAAC,EAAE,oBAAoB,CAAA;CACtC;AAED,MAAM,WAAW,kBAAmB,SAAQ,0BAA0B;IACpE,WAAW,EAAE,MAAM,CAAA;IACnB;;6CAEyC;IACzC,IAAI,EAAE,KAAK,GAAG,QAAQ,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,aAAa,CAAA;IAChD,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAA;AAkCxF,qBAAa,mBAAoB,SAAQ,KAAK;aAE1B,IAAI,EAAE,MAAM;IAE5B,6EAA6E;aAC7D,KAAK,CAAC,EAAE,MAAM;IAC9B,kEAAkE;aAClD,SAAS,CAAC,EAAE,MAAM;gBALlB,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM;IACf,6EAA6E;IAC7D,KAAK,CAAC,EAAE,MAAM,YAAA;IAC9B,kEAAkE;IAClD,SAAS,CAAC,EAAE,MAAM,YAAA;CAKrC;AAkBD,qBAAa,sBAAsB;IACjC,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,SAAS,CAAyC;IAC1D,OAAO,CAAC,gBAAgB,CAAgC;IACxD,OAAO,CAAC,SAAS,CAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ,CAAmC;IACnD,+DAA+D;IAC/D,OAAO,CAAC,mBAAmB,CAAsB;IACjD,6DAA6D;IAC7D,OAAO,CAAC,uBAAuB,CAAQ;gBAE3B,OAAO,GAAE,kBAAuB;IAI5C;;;;OAIG;YACW,YAAY;IAY1B;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,EAAE,gBAAgB,GAAG,IAAI;IAI/C;;;;OAIG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIzB,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,0BAA0B,CAAC;IA+ChC,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,kBAAkB,CAAC;IAuGxB,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBjE;;;OAGG;IACH,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;IA2CnD,yEAAyE;IACzE,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;IASlD,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,cAAc;IAqCtB,OAAO,CAAC,yBAAyB;IAoEjC,OAAO,CAAC,qBAAqB;IA+D7B,OAAO,CAAC,MAAM;IAed;;;;;;OAMG;YACW,cAAc;CA4C7B;AAgDD,eAAO,MAAM,sBAAsB,wBAA+B,CAAA"}
1
+ {"version":3,"file":"PhoneStreamCoordinator.d.ts","sourceRoot":"","sources":["../../src/services/PhoneStreamCoordinator.ts"],"names":[],"mappings":"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"}