@mentra/engine 0.1.0-beta.0

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 (842) hide show
  1. package/README.md +79 -0
  2. package/build/devtools.d.ts +11 -0
  3. package/build/devtools.d.ts.map +1 -0
  4. package/build/devtools.js +13 -0
  5. package/build/devtools.js.map +1 -0
  6. package/build/engine.d.ts +261 -0
  7. package/build/engine.d.ts.map +1 -0
  8. package/build/engine.js +170 -0
  9. package/build/engine.js.map +1 -0
  10. package/build/facades/dev.d.ts +58 -0
  11. package/build/facades/dev.d.ts.map +1 -0
  12. package/build/facades/dev.js +189 -0
  13. package/build/facades/dev.js.map +1 -0
  14. package/build/facades/display.d.ts +21 -0
  15. package/build/facades/display.d.ts.map +1 -0
  16. package/build/facades/display.js +17 -0
  17. package/build/facades/display.js.map +1 -0
  18. package/build/facades/displayMirror.d.ts +15 -0
  19. package/build/facades/displayMirror.d.ts.map +1 -0
  20. package/build/facades/displayMirror.js +29 -0
  21. package/build/facades/displayMirror.js.map +1 -0
  22. package/build/facades/gallery.d.ts +62 -0
  23. package/build/facades/gallery.d.ts.map +1 -0
  24. package/build/facades/gallery.js +61 -0
  25. package/build/facades/gallery.js.map +1 -0
  26. package/build/facades/glasses.d.ts +141 -0
  27. package/build/facades/glasses.d.ts.map +1 -0
  28. package/build/facades/glasses.js +199 -0
  29. package/build/facades/glasses.js.map +1 -0
  30. package/build/facades/glassesSettings.d.ts +13 -0
  31. package/build/facades/glassesSettings.d.ts.map +1 -0
  32. package/build/facades/glassesSettings.js +54 -0
  33. package/build/facades/glassesSettings.js.map +1 -0
  34. package/build/facades/glassesWifi.d.ts +25 -0
  35. package/build/facades/glassesWifi.d.ts.map +1 -0
  36. package/build/facades/glassesWifi.js +57 -0
  37. package/build/facades/glassesWifi.js.map +1 -0
  38. package/build/facades/miniapps.d.ts +43 -0
  39. package/build/facades/miniapps.d.ts.map +1 -0
  40. package/build/facades/miniapps.js +49 -0
  41. package/build/facades/miniapps.js.map +1 -0
  42. package/build/facades/notifications.d.ts +13 -0
  43. package/build/facades/notifications.d.ts.map +1 -0
  44. package/build/facades/notifications.js +12 -0
  45. package/build/facades/notifications.js.map +1 -0
  46. package/build/facades/ota.d.ts +103 -0
  47. package/build/facades/ota.d.ts.map +1 -0
  48. package/build/facades/ota.js +156 -0
  49. package/build/facades/ota.js.map +1 -0
  50. package/build/facades/pairing.d.ts +114 -0
  51. package/build/facades/pairing.d.ts.map +1 -0
  52. package/build/facades/pairing.js +275 -0
  53. package/build/facades/pairing.js.map +1 -0
  54. package/build/facades/permissions.d.ts +33 -0
  55. package/build/facades/permissions.d.ts.map +1 -0
  56. package/build/facades/permissions.js +155 -0
  57. package/build/facades/permissions.js.map +1 -0
  58. package/build/facades/phoneNotifications.d.ts +21 -0
  59. package/build/facades/phoneNotifications.d.ts.map +1 -0
  60. package/build/facades/phoneNotifications.js +51 -0
  61. package/build/facades/phoneNotifications.js.map +1 -0
  62. package/build/facades/reports.d.ts +36 -0
  63. package/build/facades/reports.d.ts.map +1 -0
  64. package/build/facades/reports.js +134 -0
  65. package/build/facades/reports.js.map +1 -0
  66. package/build/facades/session.d.ts +21 -0
  67. package/build/facades/session.d.ts.map +1 -0
  68. package/build/facades/session.js +52 -0
  69. package/build/facades/session.js.map +1 -0
  70. package/build/facades/settings.d.ts +37 -0
  71. package/build/facades/settings.d.ts.map +1 -0
  72. package/build/facades/settings.js +55 -0
  73. package/build/facades/settings.js.map +1 -0
  74. package/build/facades/speech.d.ts +30 -0
  75. package/build/facades/speech.d.ts.map +1 -0
  76. package/build/facades/speech.js +37 -0
  77. package/build/facades/speech.js.map +1 -0
  78. package/build/index.d.ts +43 -0
  79. package/build/index.d.ts.map +1 -0
  80. package/build/index.js +45 -0
  81. package/build/index.js.map +1 -0
  82. package/build/internal.d.ts +67 -0
  83. package/build/internal.d.ts.map +1 -0
  84. package/build/internal.js +90 -0
  85. package/build/internal.js.map +1 -0
  86. package/build/runtime/bootstrap.d.ts +83 -0
  87. package/build/runtime/bootstrap.d.ts.map +1 -0
  88. package/build/runtime/bootstrap.js +56 -0
  89. package/build/runtime/bootstrap.js.map +1 -0
  90. package/build/runtime/config.d.ts +146 -0
  91. package/build/runtime/config.d.ts.map +1 -0
  92. package/build/runtime/config.js +18 -0
  93. package/build/runtime/config.js.map +1 -0
  94. package/build/runtime/streamConfig.d.ts +4 -0
  95. package/build/runtime/streamConfig.d.ts.map +1 -0
  96. package/build/runtime/streamConfig.js +38 -0
  97. package/build/runtime/streamConfig.js.map +1 -0
  98. package/build/services/AppRegistry.d.ts +269 -0
  99. package/build/services/AppRegistry.d.ts.map +1 -0
  100. package/build/services/AppRegistry.js +1079 -0
  101. package/build/services/AppRegistry.js.map +1 -0
  102. package/build/services/AudioCloudUplink.d.ts +9 -0
  103. package/build/services/AudioCloudUplink.d.ts.map +1 -0
  104. package/build/services/AudioCloudUplink.js +48 -0
  105. package/build/services/AudioCloudUplink.js.map +1 -0
  106. package/build/services/AudioPlaybackService.d.ts +175 -0
  107. package/build/services/AudioPlaybackService.d.ts.map +1 -0
  108. package/build/services/AudioPlaybackService.js +705 -0
  109. package/build/services/AudioPlaybackService.js.map +1 -0
  110. package/build/services/AutomaticReportResult.d.ts +20 -0
  111. package/build/services/AutomaticReportResult.d.ts.map +1 -0
  112. package/build/services/AutomaticReportResult.js +29 -0
  113. package/build/services/AutomaticReportResult.js.map +1 -0
  114. package/build/services/BlobStore.d.ts +91 -0
  115. package/build/services/BlobStore.d.ts.map +1 -0
  116. package/build/services/BlobStore.js +668 -0
  117. package/build/services/BlobStore.js.map +1 -0
  118. package/build/services/CaptionsTesterReportService.d.ts +4 -0
  119. package/build/services/CaptionsTesterReportService.d.ts.map +1 -0
  120. package/build/services/CaptionsTesterReportService.js +80 -0
  121. package/build/services/CaptionsTesterReportService.js.map +1 -0
  122. package/build/services/CloudAudioSubscriptionSync.d.ts +24 -0
  123. package/build/services/CloudAudioSubscriptionSync.d.ts.map +1 -0
  124. package/build/services/CloudAudioSubscriptionSync.js +39 -0
  125. package/build/services/CloudAudioSubscriptionSync.js.map +1 -0
  126. package/build/services/CloudClientService.d.ts +143 -0
  127. package/build/services/CloudClientService.d.ts.map +1 -0
  128. package/build/services/CloudClientService.js +644 -0
  129. package/build/services/CloudClientService.js.map +1 -0
  130. package/build/services/CloudTranscriptE2EMetrics.d.ts +4 -0
  131. package/build/services/CloudTranscriptE2EMetrics.d.ts.map +1 -0
  132. package/build/services/CloudTranscriptE2EMetrics.js +24 -0
  133. package/build/services/CloudTranscriptE2EMetrics.js.map +1 -0
  134. package/build/services/ConnectionCoordinator.d.ts +51 -0
  135. package/build/services/ConnectionCoordinator.d.ts.map +1 -0
  136. package/build/services/ConnectionCoordinator.js +34 -0
  137. package/build/services/ConnectionCoordinator.js.map +1 -0
  138. package/build/services/DevServerBridge.d.ts +63 -0
  139. package/build/services/DevServerBridge.d.ts.map +1 -0
  140. package/build/services/DevServerBridge.js +294 -0
  141. package/build/services/DevServerBridge.js.map +1 -0
  142. package/build/services/DeviceEventRouter.d.ts +3 -0
  143. package/build/services/DeviceEventRouter.d.ts.map +1 -0
  144. package/build/services/DeviceEventRouter.js +190 -0
  145. package/build/services/DeviceEventRouter.js.map +1 -0
  146. package/build/services/DeviceStoreHydration.d.ts +38 -0
  147. package/build/services/DeviceStoreHydration.d.ts.map +1 -0
  148. package/build/services/DeviceStoreHydration.js +124 -0
  149. package/build/services/DeviceStoreHydration.js.map +1 -0
  150. package/build/services/DisplayProcessor.d.ts +223 -0
  151. package/build/services/DisplayProcessor.d.ts.map +1 -0
  152. package/build/services/DisplayProcessor.js +552 -0
  153. package/build/services/DisplayProcessor.js.map +1 -0
  154. package/build/services/GlassesReadiness.d.ts +41 -0
  155. package/build/services/GlassesReadiness.d.ts.map +1 -0
  156. package/build/services/GlassesReadiness.js +82 -0
  157. package/build/services/GlassesReadiness.js.map +1 -0
  158. package/build/services/GlassesSettingsSync.d.ts +33 -0
  159. package/build/services/GlassesSettingsSync.d.ts.map +1 -0
  160. package/build/services/GlassesSettingsSync.js +121 -0
  161. package/build/services/GlassesSettingsSync.js.map +1 -0
  162. package/build/services/GlassesStatusProjection.d.ts +3 -0
  163. package/build/services/GlassesStatusProjection.d.ts.map +1 -0
  164. package/build/services/GlassesStatusProjection.js +65 -0
  165. package/build/services/GlassesStatusProjection.js.map +1 -0
  166. package/build/services/HeadingService.d.ts +27 -0
  167. package/build/services/HeadingService.d.ts.map +1 -0
  168. package/build/services/HeadingService.js +96 -0
  169. package/build/services/HeadingService.js.map +1 -0
  170. package/build/services/LocalDisplayManager.d.ts +139 -0
  171. package/build/services/LocalDisplayManager.d.ts.map +1 -0
  172. package/build/services/LocalDisplayManager.js +579 -0
  173. package/build/services/LocalDisplayManager.js.map +1 -0
  174. package/build/services/LocalMiniappRuntime.d.ts +439 -0
  175. package/build/services/LocalMiniappRuntime.d.ts.map +1 -0
  176. package/build/services/LocalMiniappRuntime.js +3695 -0
  177. package/build/services/LocalMiniappRuntime.js.map +1 -0
  178. package/build/services/LocalSttFallbackCoordinator.d.ts +57 -0
  179. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -0
  180. package/build/services/LocalSttFallbackCoordinator.js +137 -0
  181. package/build/services/LocalSttFallbackCoordinator.js.map +1 -0
  182. package/build/services/MentraJSCrashController.d.ts +97 -0
  183. package/build/services/MentraJSCrashController.d.ts.map +1 -0
  184. package/build/services/MentraJSCrashController.js +138 -0
  185. package/build/services/MentraJSCrashController.js.map +1 -0
  186. package/build/services/MentraJSCrashloopReportService.d.ts +9 -0
  187. package/build/services/MentraJSCrashloopReportService.d.ts.map +1 -0
  188. package/build/services/MentraJSCrashloopReportService.js +54 -0
  189. package/build/services/MentraJSCrashloopReportService.js.map +1 -0
  190. package/build/services/MentraJSLogPipeline.d.ts +87 -0
  191. package/build/services/MentraJSLogPipeline.d.ts.map +1 -0
  192. package/build/services/MentraJSLogPipeline.js +137 -0
  193. package/build/services/MentraJSLogPipeline.js.map +1 -0
  194. package/build/services/MentraJSRouter.d.ts +203 -0
  195. package/build/services/MentraJSRouter.d.ts.map +1 -0
  196. package/build/services/MentraJSRouter.js +480 -0
  197. package/build/services/MentraJSRouter.js.map +1 -0
  198. package/build/services/MentraUIRouter.d.ts +137 -0
  199. package/build/services/MentraUIRouter.d.ts.map +1 -0
  200. package/build/services/MentraUIRouter.js +210 -0
  201. package/build/services/MentraUIRouter.js.map +1 -0
  202. package/build/services/MicStateCoordinator.d.ts +37 -0
  203. package/build/services/MicStateCoordinator.d.ts.map +1 -0
  204. package/build/services/MicStateCoordinator.js +81 -0
  205. package/build/services/MicStateCoordinator.js.map +1 -0
  206. package/build/services/MiniappEngine.d.ts +31 -0
  207. package/build/services/MiniappEngine.d.ts.map +1 -0
  208. package/build/services/MiniappEngine.js +119 -0
  209. package/build/services/MiniappEngine.js.map +1 -0
  210. package/build/services/MiniappLauncher.d.ts +129 -0
  211. package/build/services/MiniappLauncher.d.ts.map +1 -0
  212. package/build/services/MiniappLauncher.js +291 -0
  213. package/build/services/MiniappLauncher.js.map +1 -0
  214. package/build/services/MiniappRunningRegistry.d.ts +24 -0
  215. package/build/services/MiniappRunningRegistry.d.ts.map +1 -0
  216. package/build/services/MiniappRunningRegistry.js +52 -0
  217. package/build/services/MiniappRunningRegistry.js.map +1 -0
  218. package/build/services/NativeHttpResponse.d.ts +3 -0
  219. package/build/services/NativeHttpResponse.d.ts.map +1 -0
  220. package/build/services/NativeHttpResponse.js +6 -0
  221. package/build/services/NativeHttpResponse.js.map +1 -0
  222. package/build/services/NavigationHandlers.d.ts +90 -0
  223. package/build/services/NavigationHandlers.d.ts.map +1 -0
  224. package/build/services/NavigationHandlers.js +379 -0
  225. package/build/services/NavigationHandlers.js.map +1 -0
  226. package/build/services/NavigationService.d.ts +254 -0
  227. package/build/services/NavigationService.d.ts.map +1 -0
  228. package/build/services/NavigationService.js +553 -0
  229. package/build/services/NavigationService.js.map +1 -0
  230. package/build/services/NotificationsEmitter.d.ts +28 -0
  231. package/build/services/NotificationsEmitter.d.ts.map +1 -0
  232. package/build/services/NotificationsEmitter.js +22 -0
  233. package/build/services/NotificationsEmitter.js.map +1 -0
  234. package/build/services/OfflineSpeechModelService.d.ts +33 -0
  235. package/build/services/OfflineSpeechModelService.d.ts.map +1 -0
  236. package/build/services/OfflineSpeechModelService.js +136 -0
  237. package/build/services/OfflineSpeechModelService.js.map +1 -0
  238. package/build/services/OtaInstallCoordinator.d.ts +195 -0
  239. package/build/services/OtaInstallCoordinator.d.ts.map +1 -0
  240. package/build/services/OtaInstallCoordinator.js +1047 -0
  241. package/build/services/OtaInstallCoordinator.js.map +1 -0
  242. package/build/services/OtaService.d.ts +3 -0
  243. package/build/services/OtaService.d.ts.map +1 -0
  244. package/build/services/OtaService.js +65 -0
  245. package/build/services/OtaService.js.map +1 -0
  246. package/build/services/OtaUpdateCheckService.d.ts +65 -0
  247. package/build/services/OtaUpdateCheckService.d.ts.map +1 -0
  248. package/build/services/OtaUpdateCheckService.js +260 -0
  249. package/build/services/OtaUpdateCheckService.js.map +1 -0
  250. package/build/services/PairingIdentity.d.ts +80 -0
  251. package/build/services/PairingIdentity.d.ts.map +1 -0
  252. package/build/services/PairingIdentity.js +145 -0
  253. package/build/services/PairingIdentity.js.map +1 -0
  254. package/build/services/PhoneCalendarHelpers.d.ts +32 -0
  255. package/build/services/PhoneCalendarHelpers.d.ts.map +1 -0
  256. package/build/services/PhoneCalendarHelpers.js +157 -0
  257. package/build/services/PhoneCalendarHelpers.js.map +1 -0
  258. package/build/services/PhoneCalendarService.d.ts +5 -0
  259. package/build/services/PhoneCalendarService.d.ts.map +1 -0
  260. package/build/services/PhoneCalendarService.js +24 -0
  261. package/build/services/PhoneCalendarService.js.map +1 -0
  262. package/build/services/PhoneCameraFovCoordinator.d.ts +28 -0
  263. package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -0
  264. package/build/services/PhoneCameraFovCoordinator.js +180 -0
  265. package/build/services/PhoneCameraFovCoordinator.js.map +1 -0
  266. package/build/services/PhoneLocationService.d.ts +36 -0
  267. package/build/services/PhoneLocationService.d.ts.map +1 -0
  268. package/build/services/PhoneLocationService.js +115 -0
  269. package/build/services/PhoneLocationService.js.map +1 -0
  270. package/build/services/PhoneNotificationsSync.d.ts +3 -0
  271. package/build/services/PhoneNotificationsSync.d.ts.map +1 -0
  272. package/build/services/PhoneNotificationsSync.js +35 -0
  273. package/build/services/PhoneNotificationsSync.js.map +1 -0
  274. package/build/services/PhonePhotoCoordinator.d.ts +103 -0
  275. package/build/services/PhonePhotoCoordinator.d.ts.map +1 -0
  276. package/build/services/PhonePhotoCoordinator.js +326 -0
  277. package/build/services/PhonePhotoCoordinator.js.map +1 -0
  278. package/build/services/PhoneStreamCoordinator.d.ts +168 -0
  279. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -0
  280. package/build/services/PhoneStreamCoordinator.js +632 -0
  281. package/build/services/PhoneStreamCoordinator.js.map +1 -0
  282. package/build/services/PhoneVideoCoordinator.d.ts +50 -0
  283. package/build/services/PhoneVideoCoordinator.d.ts.map +1 -0
  284. package/build/services/PhoneVideoCoordinator.js +147 -0
  285. package/build/services/PhoneVideoCoordinator.js.map +1 -0
  286. package/build/services/STTModelManager.d.ts +65 -0
  287. package/build/services/STTModelManager.d.ts.map +1 -0
  288. package/build/services/STTModelManager.js +292 -0
  289. package/build/services/STTModelManager.js.map +1 -0
  290. package/build/services/SceneRenderer.d.ts +90 -0
  291. package/build/services/SceneRenderer.d.ts.map +1 -0
  292. package/build/services/SceneRenderer.js +248 -0
  293. package/build/services/SceneRenderer.js.map +1 -0
  294. package/build/services/SentenceTtsPipeline.d.ts +31 -0
  295. package/build/services/SentenceTtsPipeline.d.ts.map +1 -0
  296. package/build/services/SentenceTtsPipeline.js +67 -0
  297. package/build/services/SentenceTtsPipeline.js.map +1 -0
  298. package/build/services/StreamLifecycleController.d.ts +67 -0
  299. package/build/services/StreamLifecycleController.d.ts.map +1 -0
  300. package/build/services/StreamLifecycleController.js +152 -0
  301. package/build/services/StreamLifecycleController.js.map +1 -0
  302. package/build/services/TTSModelManager.d.ts +90 -0
  303. package/build/services/TTSModelManager.d.ts.map +1 -0
  304. package/build/services/TTSModelManager.js +366 -0
  305. package/build/services/TTSModelManager.js.map +1 -0
  306. package/build/services/TranscriptionRouting.d.ts +12 -0
  307. package/build/services/TranscriptionRouting.d.ts.map +1 -0
  308. package/build/services/TranscriptionRouting.js +24 -0
  309. package/build/services/TranscriptionRouting.js.map +1 -0
  310. package/build/services/WebviewBridge.d.ts +22 -0
  311. package/build/services/WebviewBridge.d.ts.map +1 -0
  312. package/build/services/WebviewBridge.js +47 -0
  313. package/build/services/WebviewBridge.js.map +1 -0
  314. package/build/services/asg/GalleryMediaIntegrityReportService.d.ts +17 -0
  315. package/build/services/asg/GalleryMediaIntegrityReportService.d.ts.map +1 -0
  316. package/build/services/asg/GalleryMediaIntegrityReportService.js +43 -0
  317. package/build/services/asg/GalleryMediaIntegrityReportService.js.map +1 -0
  318. package/build/services/asg/asgCameraApi.d.ts +205 -0
  319. package/build/services/asg/asgCameraApi.d.ts.map +1 -0
  320. package/build/services/asg/asgCameraApi.js +1410 -0
  321. package/build/services/asg/asgCameraApi.js.map +1 -0
  322. package/build/services/asg/cameraRollExportCoordinator.d.ts +60 -0
  323. package/build/services/asg/cameraRollExportCoordinator.d.ts.map +1 -0
  324. package/build/services/asg/cameraRollExportCoordinator.js +618 -0
  325. package/build/services/asg/cameraRollExportCoordinator.js.map +1 -0
  326. package/build/services/asg/cameraRollExportLedger.d.ts +44 -0
  327. package/build/services/asg/cameraRollExportLedger.d.ts.map +1 -0
  328. package/build/services/asg/cameraRollExportLedger.js +78 -0
  329. package/build/services/asg/cameraRollExportLedger.js.map +1 -0
  330. package/build/services/asg/galleryMediaValidation.d.ts +29 -0
  331. package/build/services/asg/galleryMediaValidation.d.ts.map +1 -0
  332. package/build/services/asg/galleryMediaValidation.js +149 -0
  333. package/build/services/asg/galleryMediaValidation.js.map +1 -0
  334. package/build/services/asg/galleryNotices.d.ts +33 -0
  335. package/build/services/asg/galleryNotices.d.ts.map +1 -0
  336. package/build/services/asg/galleryNotices.js +29 -0
  337. package/build/services/asg/galleryNotices.js.map +1 -0
  338. package/build/services/asg/galleryPathMigration.d.ts +3 -0
  339. package/build/services/asg/galleryPathMigration.d.ts.map +1 -0
  340. package/build/services/asg/galleryPathMigration.js +26 -0
  341. package/build/services/asg/galleryPathMigration.js.map +1 -0
  342. package/build/services/asg/gallerySettingsService.d.ts +20 -0
  343. package/build/services/asg/gallerySettingsService.d.ts.map +1 -0
  344. package/build/services/asg/gallerySettingsService.js +53 -0
  345. package/build/services/asg/gallerySettingsService.js.map +1 -0
  346. package/build/services/asg/gallerySyncNotifications.d.ts +56 -0
  347. package/build/services/asg/gallerySyncNotifications.d.ts.map +1 -0
  348. package/build/services/asg/gallerySyncNotifications.js +198 -0
  349. package/build/services/asg/gallerySyncNotifications.js.map +1 -0
  350. package/build/services/asg/gallerySyncService.d.ts +137 -0
  351. package/build/services/asg/gallerySyncService.d.ts.map +1 -0
  352. package/build/services/asg/gallerySyncService.js +1933 -0
  353. package/build/services/asg/gallerySyncService.js.map +1 -0
  354. package/build/services/asg/galleryTransferLedger.d.ts +58 -0
  355. package/build/services/asg/galleryTransferLedger.d.ts.map +1 -0
  356. package/build/services/asg/galleryTransferLedger.js +225 -0
  357. package/build/services/asg/galleryTransferLedger.js.map +1 -0
  358. package/build/services/asg/localNetworkTransport.d.ts +15 -0
  359. package/build/services/asg/localNetworkTransport.d.ts.map +1 -0
  360. package/build/services/asg/localNetworkTransport.js +144 -0
  361. package/build/services/asg/localNetworkTransport.js.map +1 -0
  362. package/build/services/asg/localStorageService.d.ts +146 -0
  363. package/build/services/asg/localStorageService.d.ts.map +1 -0
  364. package/build/services/asg/localStorageService.js +572 -0
  365. package/build/services/asg/localStorageService.js.map +1 -0
  366. package/build/services/asg/mediaProcessingQueue.d.ts +70 -0
  367. package/build/services/asg/mediaProcessingQueue.d.ts.map +1 -0
  368. package/build/services/asg/mediaProcessingQueue.js +451 -0
  369. package/build/services/asg/mediaProcessingQueue.js.map +1 -0
  370. package/build/services/asgOtaVersionUrl.d.ts +2 -0
  371. package/build/services/asgOtaVersionUrl.d.ts.map +1 -0
  372. package/build/services/asgOtaVersionUrl.js +36 -0
  373. package/build/services/asgOtaVersionUrl.js.map +1 -0
  374. package/build/services/blobPaths.d.ts +31 -0
  375. package/build/services/blobPaths.d.ts.map +1 -0
  376. package/build/services/blobPaths.js +86 -0
  377. package/build/services/blobPaths.js.map +1 -0
  378. package/build/services/cloudStreamApi.d.ts +59 -0
  379. package/build/services/cloudStreamApi.d.ts.map +1 -0
  380. package/build/services/cloudStreamApi.js +81 -0
  381. package/build/services/cloudStreamApi.js.map +1 -0
  382. package/build/services/gallerySyncClock.d.ts +17 -0
  383. package/build/services/gallerySyncClock.d.ts.map +1 -0
  384. package/build/services/gallerySyncClock.js +21 -0
  385. package/build/services/gallerySyncClock.js.map +1 -0
  386. package/build/services/glassesClockSync.d.ts +20 -0
  387. package/build/services/glassesClockSync.d.ts.map +1 -0
  388. package/build/services/glassesClockSync.js +97 -0
  389. package/build/services/glassesClockSync.js.map +1 -0
  390. package/build/services/manifestVersionGate.d.ts +28 -0
  391. package/build/services/manifestVersionGate.d.ts.map +1 -0
  392. package/build/services/manifestVersionGate.js +41 -0
  393. package/build/services/manifestVersionGate.js.map +1 -0
  394. package/build/services/mentraUiShim.d.ts +38 -0
  395. package/build/services/mentraUiShim.d.ts.map +1 -0
  396. package/build/services/mentraUiShim.js +360 -0
  397. package/build/services/mentraUiShim.js.map +1 -0
  398. package/build/services/navigation/roadNameResolver.d.ts +67 -0
  399. package/build/services/navigation/roadNameResolver.d.ts.map +1 -0
  400. package/build/services/navigation/roadNameResolver.js +96 -0
  401. package/build/services/navigation/roadNameResolver.js.map +1 -0
  402. package/build/services/navigation/routesApiCodec.d.ts +38 -0
  403. package/build/services/navigation/routesApiCodec.d.ts.map +1 -0
  404. package/build/services/navigation/routesApiCodec.js +68 -0
  405. package/build/services/navigation/routesApiCodec.js.map +1 -0
  406. package/build/services/otaDisplayState.d.ts +42 -0
  407. package/build/services/otaDisplayState.d.ts.map +1 -0
  408. package/build/services/otaDisplayState.js +92 -0
  409. package/build/services/otaDisplayState.js.map +1 -0
  410. package/build/services/otaInstallPolicy.d.ts +81 -0
  411. package/build/services/otaInstallPolicy.d.ts.map +1 -0
  412. package/build/services/otaInstallPolicy.js +96 -0
  413. package/build/services/otaInstallPolicy.js.map +1 -0
  414. package/build/services/otaLegacyMapping.d.ts +22 -0
  415. package/build/services/otaLegacyMapping.d.ts.map +1 -0
  416. package/build/services/otaLegacyMapping.js +56 -0
  417. package/build/services/otaLegacyMapping.js.map +1 -0
  418. package/build/services/slimStreamStatus.d.ts +7 -0
  419. package/build/services/slimStreamStatus.d.ts.map +1 -0
  420. package/build/services/slimStreamStatus.js +26 -0
  421. package/build/services/slimStreamStatus.js.map +1 -0
  422. package/build/stores/apps.d.ts +104 -0
  423. package/build/stores/apps.d.ts.map +1 -0
  424. package/build/stores/apps.js +492 -0
  425. package/build/stores/apps.js.map +1 -0
  426. package/build/stores/bluetoothSettingKeys.d.ts +4 -0
  427. package/build/stores/bluetoothSettingKeys.d.ts.map +1 -0
  428. package/build/stores/bluetoothSettingKeys.js +31 -0
  429. package/build/stores/bluetoothSettingKeys.js.map +1 -0
  430. package/build/stores/cloudClientStatus.d.ts +9 -0
  431. package/build/stores/cloudClientStatus.d.ts.map +1 -0
  432. package/build/stores/cloudClientStatus.js +24 -0
  433. package/build/stores/cloudClientStatus.js.map +1 -0
  434. package/build/stores/connection.d.ts +22 -0
  435. package/build/stores/connection.d.ts.map +1 -0
  436. package/build/stores/connection.js +43 -0
  437. package/build/stores/connection.js.map +1 -0
  438. package/build/stores/core.d.ts +15 -0
  439. package/build/stores/core.d.ts.map +1 -0
  440. package/build/stores/core.js +21 -0
  441. package/build/stores/core.js.map +1 -0
  442. package/build/stores/display.d.ts +24 -0
  443. package/build/stores/display.d.ts.map +1 -0
  444. package/build/stores/display.js +96 -0
  445. package/build/stores/display.js.map +1 -0
  446. package/build/stores/gallerySync.d.ts +101 -0
  447. package/build/stores/gallerySync.d.ts.map +1 -0
  448. package/build/stores/gallerySync.js +217 -0
  449. package/build/stores/gallerySync.js.map +1 -0
  450. package/build/stores/glasses.d.ts +62 -0
  451. package/build/stores/glasses.d.ts.map +1 -0
  452. package/build/stores/glasses.js +203 -0
  453. package/build/stores/glasses.js.map +1 -0
  454. package/build/stores/settings.d.ts +37 -0
  455. package/build/stores/settings.d.ts.map +1 -0
  456. package/build/stores/settings.js +922 -0
  457. package/build/stores/settings.js.map +1 -0
  458. package/build/types/applet.d.ts +96 -0
  459. package/build/types/applet.d.ts.map +1 -0
  460. package/build/types/applet.js +5 -0
  461. package/build/types/applet.js.map +1 -0
  462. package/build/types/asg.d.ts +53 -0
  463. package/build/types/asg.d.ts.map +1 -0
  464. package/build/types/asg.js +2 -0
  465. package/build/types/asg.js.map +1 -0
  466. package/build/types/capabilities/even-realities-g1.d.ts +12 -0
  467. package/build/types/capabilities/even-realities-g1.d.ts.map +1 -0
  468. package/build/types/capabilities/even-realities-g1.js +55 -0
  469. package/build/types/capabilities/even-realities-g1.js.map +1 -0
  470. package/build/types/capabilities/even-realities-g2.d.ts +12 -0
  471. package/build/types/capabilities/even-realities-g2.d.ts.map +1 -0
  472. package/build/types/capabilities/even-realities-g2.js +75 -0
  473. package/build/types/capabilities/even-realities-g2.js.map +1 -0
  474. package/build/types/capabilities/mentra-display.d.ts +12 -0
  475. package/build/types/capabilities/mentra-display.d.ts.map +1 -0
  476. package/build/types/capabilities/mentra-display.js +63 -0
  477. package/build/types/capabilities/mentra-display.js.map +1 -0
  478. package/build/types/capabilities/mentra-live.d.ts +12 -0
  479. package/build/types/capabilities/mentra-live.d.ts.map +1 -0
  480. package/build/types/capabilities/mentra-live.js +92 -0
  481. package/build/types/capabilities/mentra-live.js.map +1 -0
  482. package/build/types/capabilities/none.d.ts +13 -0
  483. package/build/types/capabilities/none.d.ts.map +1 -0
  484. package/build/types/capabilities/none.js +65 -0
  485. package/build/types/capabilities/none.js.map +1 -0
  486. package/build/types/capabilities/simulated-glasses.d.ts +13 -0
  487. package/build/types/capabilities/simulated-glasses.d.ts.map +1 -0
  488. package/build/types/capabilities/simulated-glasses.js +65 -0
  489. package/build/types/capabilities/simulated-glasses.js.map +1 -0
  490. package/build/types/capabilities/vuzix-z100.d.ts +12 -0
  491. package/build/types/capabilities/vuzix-z100.d.ts.map +1 -0
  492. package/build/types/capabilities/vuzix-z100.js +52 -0
  493. package/build/types/capabilities/vuzix-z100.js.map +1 -0
  494. package/build/types/enums.d.ts +40 -0
  495. package/build/types/enums.d.ts.map +1 -0
  496. package/build/types/enums.js +44 -0
  497. package/build/types/enums.js.map +1 -0
  498. package/build/types/hardware.d.ts +160 -0
  499. package/build/types/hardware.d.ts.map +1 -0
  500. package/build/types/hardware.js +36 -0
  501. package/build/types/hardware.js.map +1 -0
  502. package/build/types/index.d.ts +11 -0
  503. package/build/types/index.d.ts.map +1 -0
  504. package/build/types/index.js +10 -0
  505. package/build/types/index.js.map +1 -0
  506. package/build/utils/GlobalEventEmitter.d.ts +10 -0
  507. package/build/utils/GlobalEventEmitter.d.ts.map +1 -0
  508. package/build/utils/GlobalEventEmitter.js +13 -0
  509. package/build/utils/GlobalEventEmitter.js.map +1 -0
  510. package/build/utils/cloudClient/RnUdpAdapter.d.ts +3 -0
  511. package/build/utils/cloudClient/RnUdpAdapter.d.ts.map +1 -0
  512. package/build/utils/cloudClient/RnUdpAdapter.js +41 -0
  513. package/build/utils/cloudClient/RnUdpAdapter.js.map +1 -0
  514. package/build/utils/cloudClient/cloudSecureStore.d.ts +3 -0
  515. package/build/utils/cloudClient/cloudSecureStore.d.ts.map +1 -0
  516. package/build/utils/cloudClient/cloudSecureStore.js +26 -0
  517. package/build/utils/cloudClient/cloudSecureStore.js.map +1 -0
  518. package/build/utils/debouncedPatch.d.ts +6 -0
  519. package/build/utils/debouncedPatch.d.ts.map +1 -0
  520. package/build/utils/debouncedPatch.js +25 -0
  521. package/build/utils/debouncedPatch.js.map +1 -0
  522. package/build/utils/devLogging.d.ts +26 -0
  523. package/build/utils/devLogging.d.ts.map +1 -0
  524. package/build/utils/devLogging.js +116 -0
  525. package/build/utils/devLogging.js.map +1 -0
  526. package/build/utils/devMiniappLaunch.d.ts +44 -0
  527. package/build/utils/devMiniappLaunch.d.ts.map +1 -0
  528. package/build/utils/devMiniappLaunch.js +52 -0
  529. package/build/utils/devMiniappLaunch.js.map +1 -0
  530. package/build/utils/diagnosticContext.d.ts +3 -0
  531. package/build/utils/diagnosticContext.d.ts.map +1 -0
  532. package/build/utils/diagnosticContext.js +119 -0
  533. package/build/utils/diagnosticContext.js.map +1 -0
  534. package/build/utils/display/composer/ColumnComposer.d.ts +131 -0
  535. package/build/utils/display/composer/ColumnComposer.d.ts.map +1 -0
  536. package/build/utils/display/composer/ColumnComposer.js +204 -0
  537. package/build/utils/display/composer/ColumnComposer.js.map +1 -0
  538. package/build/utils/display/composer/index.d.ts +9 -0
  539. package/build/utils/display/composer/index.d.ts.map +1 -0
  540. package/build/utils/display/composer/index.js +9 -0
  541. package/build/utils/display/composer/index.js.map +1 -0
  542. package/build/utils/display/helpers/DisplayHelpers.d.ts +165 -0
  543. package/build/utils/display/helpers/DisplayHelpers.d.ts.map +1 -0
  544. package/build/utils/display/helpers/DisplayHelpers.js +312 -0
  545. package/build/utils/display/helpers/DisplayHelpers.js.map +1 -0
  546. package/build/utils/display/helpers/ScrollView.d.ts +183 -0
  547. package/build/utils/display/helpers/ScrollView.d.ts.map +1 -0
  548. package/build/utils/display/helpers/ScrollView.js +257 -0
  549. package/build/utils/display/helpers/ScrollView.js.map +1 -0
  550. package/build/utils/display/helpers/index.d.ts +11 -0
  551. package/build/utils/display/helpers/index.d.ts.map +1 -0
  552. package/build/utils/display/helpers/index.js +10 -0
  553. package/build/utils/display/helpers/index.js.map +1 -0
  554. package/build/utils/display/index.d.ts +174 -0
  555. package/build/utils/display/index.d.ts.map +1 -0
  556. package/build/utils/display/index.js +185 -0
  557. package/build/utils/display/index.js.map +1 -0
  558. package/build/utils/display/measurer/TextMeasurer.d.ts +160 -0
  559. package/build/utils/display/measurer/TextMeasurer.d.ts.map +1 -0
  560. package/build/utils/display/measurer/TextMeasurer.js +273 -0
  561. package/build/utils/display/measurer/TextMeasurer.js.map +1 -0
  562. package/build/utils/display/measurer/index.d.ts +10 -0
  563. package/build/utils/display/measurer/index.d.ts.map +1 -0
  564. package/build/utils/display/measurer/index.js +11 -0
  565. package/build/utils/display/measurer/index.js.map +1 -0
  566. package/build/utils/display/measurer/script-detection.d.ts +53 -0
  567. package/build/utils/display/measurer/script-detection.d.ts.map +1 -0
  568. package/build/utils/display/measurer/script-detection.js +184 -0
  569. package/build/utils/display/measurer/script-detection.js.map +1 -0
  570. package/build/utils/display/profiles/g1.d.ts +33 -0
  571. package/build/utils/display/profiles/g1.d.ts.map +1 -0
  572. package/build/utils/display/profiles/g1.js +213 -0
  573. package/build/utils/display/profiles/g1.js.map +1 -0
  574. package/build/utils/display/profiles/g2.d.ts +13 -0
  575. package/build/utils/display/profiles/g2.d.ts.map +1 -0
  576. package/build/utils/display/profiles/g2.js +34 -0
  577. package/build/utils/display/profiles/g2.js.map +1 -0
  578. package/build/utils/display/profiles/index.d.ts +12 -0
  579. package/build/utils/display/profiles/index.d.ts.map +1 -0
  580. package/build/utils/display/profiles/index.js +15 -0
  581. package/build/utils/display/profiles/index.js.map +1 -0
  582. package/build/utils/display/profiles/nex.d.ts +10 -0
  583. package/build/utils/display/profiles/nex.d.ts.map +1 -0
  584. package/build/utils/display/profiles/nex.js +150 -0
  585. package/build/utils/display/profiles/nex.js.map +1 -0
  586. package/build/utils/display/profiles/types.d.ts +103 -0
  587. package/build/utils/display/profiles/types.d.ts.map +1 -0
  588. package/build/utils/display/profiles/types.js +2 -0
  589. package/build/utils/display/profiles/types.js.map +1 -0
  590. package/build/utils/display/profiles/z100.d.ts +33 -0
  591. package/build/utils/display/profiles/z100.d.ts.map +1 -0
  592. package/build/utils/display/profiles/z100.js +182 -0
  593. package/build/utils/display/profiles/z100.js.map +1 -0
  594. package/build/utils/display/scene/degrade.d.ts +25 -0
  595. package/build/utils/display/scene/degrade.d.ts.map +1 -0
  596. package/build/utils/display/scene/degrade.js +64 -0
  597. package/build/utils/display/scene/degrade.js.map +1 -0
  598. package/build/utils/display/scene/differ.d.ts +38 -0
  599. package/build/utils/display/scene/differ.d.ts.map +1 -0
  600. package/build/utils/display/scene/differ.js +107 -0
  601. package/build/utils/display/scene/differ.js.map +1 -0
  602. package/build/utils/display/scene/index.d.ts +10 -0
  603. package/build/utils/display/scene/index.d.ts.map +1 -0
  604. package/build/utils/display/scene/index.js +6 -0
  605. package/build/utils/display/scene/index.js.map +1 -0
  606. package/build/utils/display/scene/process.d.ts +35 -0
  607. package/build/utils/display/scene/process.d.ts.map +1 -0
  608. package/build/utils/display/scene/process.js +187 -0
  609. package/build/utils/display/scene/process.js.map +1 -0
  610. package/build/utils/display/scene/store.d.ts +48 -0
  611. package/build/utils/display/scene/store.d.ts.map +1 -0
  612. package/build/utils/display/scene/store.js +0 -0
  613. package/build/utils/display/scene/store.js.map +1 -0
  614. package/build/utils/display/scene/types.d.ts +120 -0
  615. package/build/utils/display/scene/types.d.ts.map +1 -0
  616. package/build/utils/display/scene/types.js +0 -0
  617. package/build/utils/display/scene/types.js.map +1 -0
  618. package/build/utils/display/wrapper/TextWrapper.d.ts +102 -0
  619. package/build/utils/display/wrapper/TextWrapper.d.ts.map +1 -0
  620. package/build/utils/display/wrapper/TextWrapper.js +471 -0
  621. package/build/utils/display/wrapper/TextWrapper.js.map +1 -0
  622. package/build/utils/display/wrapper/index.d.ts +12 -0
  623. package/build/utils/display/wrapper/index.d.ts.map +1 -0
  624. package/build/utils/display/wrapper/index.js +12 -0
  625. package/build/utils/display/wrapper/index.js.map +1 -0
  626. package/build/utils/display/wrapper/types.d.ts +75 -0
  627. package/build/utils/display/wrapper/types.d.ts.map +1 -0
  628. package/build/utils/display/wrapper/types.js +11 -0
  629. package/build/utils/display/wrapper/types.js.map +1 -0
  630. package/build/utils/e2eMetrics.d.ts +6 -0
  631. package/build/utils/e2eMetrics.d.ts.map +1 -0
  632. package/build/utils/e2eMetrics.js +27 -0
  633. package/build/utils/e2eMetrics.js.map +1 -0
  634. package/build/utils/hardware/hardware.d.ts +42 -0
  635. package/build/utils/hardware/hardware.d.ts.map +1 -0
  636. package/build/utils/hardware/hardware.js +127 -0
  637. package/build/utils/hardware/hardware.js.map +1 -0
  638. package/build/utils/hardware/index.d.ts +2 -0
  639. package/build/utils/hardware/index.d.ts.map +1 -0
  640. package/build/utils/hardware/index.js +2 -0
  641. package/build/utils/hardware/index.js.map +1 -0
  642. package/build/utils/miniappGlobals.d.ts +60 -0
  643. package/build/utils/miniappGlobals.d.ts.map +1 -0
  644. package/build/utils/miniappGlobals.js +224 -0
  645. package/build/utils/miniappGlobals.js.map +1 -0
  646. package/build/utils/permissions/MediaLibraryPermissions.d.ts +45 -0
  647. package/build/utils/permissions/MediaLibraryPermissions.d.ts.map +1 -0
  648. package/build/utils/permissions/MediaLibraryPermissions.js +145 -0
  649. package/build/utils/permissions/MediaLibraryPermissions.js.map +1 -0
  650. package/build/utils/permissions/galleryDisplayName.d.ts +8 -0
  651. package/build/utils/permissions/galleryDisplayName.d.ts.map +1 -0
  652. package/build/utils/permissions/galleryDisplayName.js +25 -0
  653. package/build/utils/permissions/galleryDisplayName.js.map +1 -0
  654. package/build/utils/storage/index.d.ts +3 -0
  655. package/build/utils/storage/index.d.ts.map +1 -0
  656. package/build/utils/storage/index.js +3 -0
  657. package/build/utils/storage/index.js.map +1 -0
  658. package/build/utils/storage/storage.d.ts +24 -0
  659. package/build/utils/storage/storage.d.ts.map +1 -0
  660. package/build/utils/storage/storage.js +85 -0
  661. package/build/utils/storage/storage.js.map +1 -0
  662. package/build/utils/storage/zip.d.ts +3 -0
  663. package/build/utils/storage/zip.d.ts.map +1 -0
  664. package/build/utils/storage/zip.js +14 -0
  665. package/build/utils/storage/zip.js.map +1 -0
  666. package/build/utils/timers/index.d.ts +3 -0
  667. package/build/utils/timers/index.d.ts.map +1 -0
  668. package/build/utils/timers/index.js +3 -0
  669. package/build/utils/timers/index.js.map +1 -0
  670. package/build/utils/timers/timers.d.ts +9 -0
  671. package/build/utils/timers/timers.d.ts.map +1 -0
  672. package/build/utils/timers/timers.js +105 -0
  673. package/build/utils/timers/timers.js.map +1 -0
  674. package/package.json +120 -0
  675. package/src/devtools.ts +13 -0
  676. package/src/engine.ts +173 -0
  677. package/src/facades/dev.ts +198 -0
  678. package/src/facades/display.ts +17 -0
  679. package/src/facades/displayMirror.ts +33 -0
  680. package/src/facades/gallery.ts +69 -0
  681. package/src/facades/glasses.ts +206 -0
  682. package/src/facades/glassesSettings.ts +56 -0
  683. package/src/facades/glassesWifi.ts +68 -0
  684. package/src/facades/miniapps.ts +55 -0
  685. package/src/facades/notifications.ts +15 -0
  686. package/src/facades/ota.ts +174 -0
  687. package/src/facades/pairing.ts +329 -0
  688. package/src/facades/permissions.ts +165 -0
  689. package/src/facades/phoneNotifications.ts +50 -0
  690. package/src/facades/reports.ts +185 -0
  691. package/src/facades/session.ts +55 -0
  692. package/src/facades/settings.ts +57 -0
  693. package/src/facades/speech.ts +38 -0
  694. package/src/index.ts +191 -0
  695. package/src/internal.ts +159 -0
  696. package/src/runtime/bootstrap.ts +118 -0
  697. package/src/runtime/config.ts +147 -0
  698. package/src/runtime/streamConfig.ts +34 -0
  699. package/src/services/AppRegistry.ts +1190 -0
  700. package/src/services/AudioCloudUplink.ts +50 -0
  701. package/src/services/AudioPlaybackService.ts +813 -0
  702. package/src/services/AutomaticReportResult.ts +48 -0
  703. package/src/services/BlobStore.ts +746 -0
  704. package/src/services/CaptionsTesterReportService.ts +107 -0
  705. package/src/services/CloudAudioSubscriptionSync.ts +41 -0
  706. package/src/services/CloudClientService.ts +689 -0
  707. package/src/services/CloudTranscriptE2EMetrics.ts +27 -0
  708. package/src/services/ConnectionCoordinator.ts +65 -0
  709. package/src/services/DevServerBridge.ts +332 -0
  710. package/src/services/DeviceEventRouter.ts +238 -0
  711. package/src/services/DeviceStoreHydration.ts +130 -0
  712. package/src/services/DisplayProcessor.ts +775 -0
  713. package/src/services/GlassesReadiness.ts +103 -0
  714. package/src/services/GlassesSettingsSync.ts +134 -0
  715. package/src/services/GlassesStatusProjection.ts +73 -0
  716. package/src/services/HeadingService.ts +98 -0
  717. package/src/services/LocalDisplayManager.ts +703 -0
  718. package/src/services/LocalMiniappRuntime.ts +4213 -0
  719. package/src/services/LocalSttFallbackCoordinator.ts +147 -0
  720. package/src/services/MentraJSCrashController.ts +189 -0
  721. package/src/services/MentraJSCrashloopReportService.ts +66 -0
  722. package/src/services/MentraJSLogPipeline.ts +166 -0
  723. package/src/services/MentraJSRouter.ts +557 -0
  724. package/src/services/MentraUIRouter.ts +244 -0
  725. package/src/services/MicStateCoordinator.ts +94 -0
  726. package/src/services/MiniappEngine.ts +143 -0
  727. package/src/services/MiniappLauncher.ts +340 -0
  728. package/src/services/MiniappRunningRegistry.ts +57 -0
  729. package/src/services/NativeHttpResponse.ts +6 -0
  730. package/src/services/NavigationHandlers.ts +423 -0
  731. package/src/services/NavigationService.ts +731 -0
  732. package/src/services/NotificationsEmitter.ts +48 -0
  733. package/src/services/OfflineSpeechModelService.ts +168 -0
  734. package/src/services/OtaInstallCoordinator.ts +1205 -0
  735. package/src/services/OtaService.ts +83 -0
  736. package/src/services/OtaUpdateCheckService.ts +386 -0
  737. package/src/services/PairingIdentity.ts +154 -0
  738. package/src/services/PhoneCalendarHelpers.ts +212 -0
  739. package/src/services/PhoneCalendarService.ts +42 -0
  740. package/src/services/PhoneCameraFovCoordinator.ts +195 -0
  741. package/src/services/PhoneLocationService.ts +122 -0
  742. package/src/services/PhoneNotificationsSync.ts +44 -0
  743. package/src/services/PhonePhotoCoordinator.ts +409 -0
  744. package/src/services/PhoneStreamCoordinator.ts +777 -0
  745. package/src/services/PhoneVideoCoordinator.ts +189 -0
  746. package/src/services/STTModelManager.ts +360 -0
  747. package/src/services/SceneRenderer.ts +292 -0
  748. package/src/services/SentenceTtsPipeline.ts +106 -0
  749. package/src/services/StreamLifecycleController.ts +213 -0
  750. package/src/services/TTSModelManager.ts +466 -0
  751. package/src/services/TranscriptionRouting.ts +37 -0
  752. package/src/services/WebviewBridge.ts +50 -0
  753. package/src/services/asg/GalleryMediaIntegrityReportService.ts +70 -0
  754. package/src/services/asg/asgCameraApi.ts +1695 -0
  755. package/src/services/asg/cameraRollExportCoordinator.ts +627 -0
  756. package/src/services/asg/cameraRollExportLedger.ts +122 -0
  757. package/src/services/asg/galleryMediaValidation.ts +183 -0
  758. package/src/services/asg/galleryNotices.ts +61 -0
  759. package/src/services/asg/galleryPathMigration.ts +22 -0
  760. package/src/services/asg/gallerySettingsService.ts +68 -0
  761. package/src/services/asg/gallerySyncNotifications.ts +236 -0
  762. package/src/services/asg/gallerySyncService.ts +2269 -0
  763. package/src/services/asg/galleryTransferLedger.ts +312 -0
  764. package/src/services/asg/localNetworkTransport.ts +173 -0
  765. package/src/services/asg/localStorageService.ts +652 -0
  766. package/src/services/asg/mediaProcessingQueue.ts +518 -0
  767. package/src/services/asgOtaVersionUrl.ts +41 -0
  768. package/src/services/blobPaths.ts +86 -0
  769. package/src/services/cloudStreamApi.ts +154 -0
  770. package/src/services/gallerySyncClock.ts +39 -0
  771. package/src/services/glassesClockSync.ts +115 -0
  772. package/src/services/manifestVersionGate.ts +43 -0
  773. package/src/services/mentraUiShim.ts +366 -0
  774. package/src/services/navigation/roadNameResolver.ts +112 -0
  775. package/src/services/navigation/routesApiCodec.ts +69 -0
  776. package/src/services/otaDisplayState.ts +115 -0
  777. package/src/services/otaInstallPolicy.ts +106 -0
  778. package/src/services/otaLegacyMapping.ts +71 -0
  779. package/src/services/slimStreamStatus.ts +28 -0
  780. package/src/stores/apps.ts +614 -0
  781. package/src/stores/bluetoothSettingKeys.ts +36 -0
  782. package/src/stores/cloudClientStatus.ts +37 -0
  783. package/src/stores/connection.ts +69 -0
  784. package/src/stores/core.ts +32 -0
  785. package/src/stores/display.ts +121 -0
  786. package/src/stores/gallerySync.ts +380 -0
  787. package/src/stores/glasses.ts +309 -0
  788. package/src/stores/settings.ts +1001 -0
  789. package/src/types/applet.ts +112 -0
  790. package/src/types/asg.ts +58 -0
  791. package/src/types/capabilities/even-realities-g1.ts +67 -0
  792. package/src/types/capabilities/even-realities-g2.ts +88 -0
  793. package/src/types/capabilities/mentra-display.ts +75 -0
  794. package/src/types/capabilities/mentra-live.ts +103 -0
  795. package/src/types/capabilities/none.ts +76 -0
  796. package/src/types/capabilities/simulated-glasses.ts +76 -0
  797. package/src/types/capabilities/vuzix-z100.ts +64 -0
  798. package/src/types/enums.ts +43 -0
  799. package/src/types/hardware.ts +203 -0
  800. package/src/types/index.ts +37 -0
  801. package/src/utils/GlobalEventEmitter.ts +14 -0
  802. package/src/utils/cloudClient/RnUdpAdapter.ts +47 -0
  803. package/src/utils/cloudClient/cloudSecureStore.ts +28 -0
  804. package/src/utils/debouncedPatch.ts +28 -0
  805. package/src/utils/devLogging.ts +140 -0
  806. package/src/utils/devMiniappLaunch.ts +68 -0
  807. package/src/utils/diagnosticContext.ts +155 -0
  808. package/src/utils/display/composer/ColumnComposer.ts +285 -0
  809. package/src/utils/display/composer/index.ts +15 -0
  810. package/src/utils/display/helpers/DisplayHelpers.ts +413 -0
  811. package/src/utils/display/helpers/ScrollView.ts +337 -0
  812. package/src/utils/display/helpers/index.ts +14 -0
  813. package/src/utils/display/index.ts +273 -0
  814. package/src/utils/display/measurer/TextMeasurer.ts +346 -0
  815. package/src/utils/display/measurer/index.ts +21 -0
  816. package/src/utils/display/measurer/script-detection.ts +218 -0
  817. package/src/utils/display/profiles/g1.ts +236 -0
  818. package/src/utils/display/profiles/g2.ts +39 -0
  819. package/src/utils/display/profiles/index.ts +28 -0
  820. package/src/utils/display/profiles/nex.ts +166 -0
  821. package/src/utils/display/profiles/types.ts +132 -0
  822. package/src/utils/display/profiles/z100.ts +198 -0
  823. package/src/utils/display/scene/degrade.ts +80 -0
  824. package/src/utils/display/scene/differ.ts +128 -0
  825. package/src/utils/display/scene/index.ts +21 -0
  826. package/src/utils/display/scene/process.ts +214 -0
  827. package/src/utils/display/scene/store.ts +0 -0
  828. package/src/utils/display/scene/types.ts +0 -0
  829. package/src/utils/display/wrapper/TextWrapper.ts +546 -0
  830. package/src/utils/display/wrapper/index.ts +15 -0
  831. package/src/utils/display/wrapper/types.ts +102 -0
  832. package/src/utils/e2eMetrics.ts +30 -0
  833. package/src/utils/hardware/hardware.ts +166 -0
  834. package/src/utils/hardware/index.ts +1 -0
  835. package/src/utils/miniappGlobals.ts +260 -0
  836. package/src/utils/permissions/MediaLibraryPermissions.ts +161 -0
  837. package/src/utils/permissions/galleryDisplayName.ts +28 -0
  838. package/src/utils/storage/index.ts +2 -0
  839. package/src/utils/storage/storage.ts +101 -0
  840. package/src/utils/storage/zip.ts +13 -0
  841. package/src/utils/timers/index.ts +2 -0
  842. package/src/utils/timers/timers.ts +139 -0
@@ -0,0 +1,1205 @@
1
+ /**
2
+ * OtaInstallCoordinator — engine-owned OTA install state machine (WP 8B).
3
+ *
4
+ * Owns every timer/retry/sequencing rule that used to live in the host screen
5
+ * `mobile/src/app/ota/progress.tsx`: the global session timeout, the no-ack
6
+ * retry watchdog, the stuck-at-zero watchdog, the progress-stall watchdog keyed
7
+ * on a staleness signature, connect-edge arbitration (initial mount vs
8
+ * reconnect vs post-APK reboot), the ota_query_status reply fallback, the ping
9
+ * keepalive, the ota_start_ack / mtk_update_complete listeners, and terminal
10
+ * cleanup. The host progress screen is a pure renderer over
11
+ * `snapshot()`/`onSnapshot()` plus the `attach()/detach()/retry()/finish()`
12
+ * commands (exposed as `engine.ota.installSession`).
13
+ *
14
+ * Behavior contract: everything here was MOVED, not changed — every timer
15
+ * duration (see ./otaInstallPolicy), arbitration rule, and "[OTA_PROGRESS]"
16
+ * log line is a field-debugging contract and stays byte-identical to the old
17
+ * screen. The reaction pass mirrors the old component's effect ordering: a
18
+ * pass diffs the store-derived inputs (connected / otaStatus / otaProgress /
19
+ * displayState / stall signature) exactly like the old effect dep arrays, and
20
+ * state written mid-pass queues a follow-up pass — the same way a setState
21
+ * during React effects scheduled a re-render after the current effect batch.
22
+ */
23
+ import BluetoothSdk from "@mentra/bluetooth-sdk/internal"
24
+ import type {OtaProgress, OtaStatus} from "@mentra/bluetooth-sdk/internal"
25
+ import GlobalEventEmitter from "../utils/GlobalEventEmitter"
26
+ import {isGlassesConnected, useGlassesStore} from "../stores/glasses"
27
+ import {getAsgOtaVersionUrl} from "./asgOtaVersionUrl"
28
+ import {deriveDisplayState, type DisplayState} from "./otaDisplayState"
29
+ import {
30
+ BES_CONTINUE_LOCKOUT_MS,
31
+ DOWNLOAD_STUCK_TIMEOUT_MS,
32
+ GLOBAL_OTA_TIMEOUT_MS,
33
+ LEGACY_APK_COMPLETION_SETTLE_MS,
34
+ LEGACY_BES_CONTINUE_LOCKOUT_MS,
35
+ LEGACY_DOWNLOAD_STUCK_TIMEOUT_MS,
36
+ LEGACY_GLOBAL_OTA_TIMEOUT_MS,
37
+ LEGACY_MTK_INSTALL_TIMEOUT_MS,
38
+ LEGACY_MTK_SIM_CAP_PERCENT,
39
+ LEGACY_MTK_SIM_FLOOR_PERCENT,
40
+ LEGACY_MTK_SIM_TICK_MS,
41
+ LEGACY_MTK_STALL_DETECT_MS,
42
+ LEGACY_MTK_STALL_ZONE_MAX_PERCENT,
43
+ LEGACY_MTK_STALL_ZONE_MIN_PERCENT,
44
+ LEGACY_PING_INTERVAL_MS,
45
+ LEGACY_PROGRESS_TIMEOUT_MS,
46
+ LEGACY_RETRY_INTERVAL_MS,
47
+ MAX_RETRIES,
48
+ MTK_INSTALL_TIMEOUT_MS,
49
+ OtaProgressMessages,
50
+ PING_INTERVAL_MS,
51
+ POST_APK_OTA_START_DELAY_MS,
52
+ PROGRESS_TIMEOUT_MS,
53
+ QUERY_REPLY_TIMEOUT_MS,
54
+ RETRY_INTERVAL_MS,
55
+ isLegacyShapedOtaSession,
56
+ isLegacyShapedOtaStatus,
57
+ } from "./otaInstallPolicy"
58
+
59
+ function isTerminalForWatchdog(d: DisplayState): boolean {
60
+ return d === "complete" || d === "failed" || d === "restarting"
61
+ }
62
+
63
+ /** Non-empty when glasses are actively reporting work — drives stall timeout reset. */
64
+ function buildProgressStalenessSignature(
65
+ otaStatus: OtaStatus | null,
66
+ otaProgress: OtaProgress | null,
67
+ displayState: DisplayState,
68
+ ): string {
69
+ if (displayState !== "starting" && displayState !== "updating") return ""
70
+ if (otaStatus && (otaStatus.status === "in_progress" || otaStatus.status === "step_complete")) {
71
+ return `s:${otaStatus.sessionId}|${otaStatus.status}|${otaStatus.phase}|${otaStatus.stepType}|${otaStatus.stepPercent}|${otaStatus.overallPercent}`
72
+ }
73
+ // Legacy-shaped BES download FINISHED (WP 8C): the legacy screen kept a progress
74
+ // watchdog armed while waiting for the BES install events to start; keep the stall
75
+ // watchdog armed here too so a wedged flash still fails instead of hanging.
76
+ if (
77
+ isLegacyShapedOtaStatus(otaStatus) &&
78
+ otaStatus?.stepType === "bes" &&
79
+ otaStatus.phase === "download" &&
80
+ otaStatus.status === "complete"
81
+ ) {
82
+ return "s:legacy-bes-download-complete-await-install"
83
+ }
84
+ if (otaProgress && (otaProgress.status === "PROGRESS" || otaProgress.status === "STARTED")) {
85
+ return `p:${otaProgress.currentUpdate}|${otaProgress.stage}|${otaProgress.status}|${otaProgress.progress}`
86
+ }
87
+ return ""
88
+ }
89
+
90
+ function progressTimeoutDurationMs(
91
+ otaStatus: OtaStatus | null,
92
+ otaProgress: OtaProgress | null,
93
+ legacySession: boolean,
94
+ ): number {
95
+ if (otaStatus?.stepType === "mtk" && otaStatus.phase === "install") {
96
+ return legacySession ? LEGACY_MTK_INSTALL_TIMEOUT_MS : MTK_INSTALL_TIMEOUT_MS
97
+ }
98
+ if (otaProgress?.currentUpdate === "mtk" && otaProgress.stage === "install") {
99
+ return legacySession ? LEGACY_MTK_INSTALL_TIMEOUT_MS : MTK_INSTALL_TIMEOUT_MS
100
+ }
101
+ return legacySession ? LEGACY_PROGRESS_TIMEOUT_MS : PROGRESS_TIMEOUT_MS
102
+ }
103
+
104
+ function latestPercentForStuck(otaStatus: OtaStatus | null, otaProgress: OtaProgress | null): number {
105
+ if (otaProgress?.progress != null) return otaProgress.progress
106
+ if (otaStatus?.status === "in_progress" || otaStatus?.status === "step_complete") {
107
+ return Math.max(otaStatus.overallPercent ?? 0, otaStatus.stepPercent ?? 0)
108
+ }
109
+ return 0
110
+ }
111
+
112
+ /**
113
+ * "idle" ota_status means the glasses have no active session — that is NOT a
114
+ * recovery signal, so the query-reply fallback must keep firing and retry
115
+ * ota_start. Only treat real progress or a non-idle ota_status as a useful
116
+ * reply that cancels the fallback.
117
+ */
118
+ function hasRecoveringOtaReply(otaStatus: OtaStatus | null, otaProgress: OtaProgress | null): boolean {
119
+ if (otaProgress) return true
120
+ return !!otaStatus && otaStatus.status !== "idle"
121
+ }
122
+
123
+ /** Read model the host progress screen renders from. */
124
+ export interface OtaInstallSnapshot {
125
+ displayState: DisplayState
126
+ errorMsg: string
127
+ continueButtonDisabled: boolean
128
+ connected: boolean
129
+ otaStatus: OtaStatus | null
130
+ otaProgress: OtaProgress | null
131
+ /**
132
+ * Display-only simulated percent for legacy (< 37) MTK install stalls (WP 8C-e), or
133
+ * null. The MTK system install goes quiet around 49-50%; the legacy screen simulated
134
+ * +1% ticks up to 60% purely to reassure the user. Render max(real, simulated).
135
+ */
136
+ mtkInstallStallSimulatedPercent: number | null
137
+ }
138
+
139
+ class OtaInstallCoordinator {
140
+ private attached = false
141
+
142
+ // Genuinely session-local state (was component state/refs).
143
+ private errorMsg = ""
144
+ private sawReconnectEdge = false
145
+ private continueButtonDisabled = false
146
+ // True once this session reported an APK step. After an APK install the ASG
147
+ // process restarts with a new build number, so finish() must clear the stale
148
+ // one before check-for-updates re-checks (mirrors the legacy screen).
149
+ private apkStepSeen = false
150
+ private prevConnected = false
151
+
152
+ // Legacy (< 37) compatibility state, ported from progress-legacy.tsx (WP 8C).
153
+ // Build number at session start — legacy APK completion is detected by the build
154
+ // number increasing past it when the explicit reconnect status never arrives.
155
+ private initialBuildNumber: string | null = null
156
+ // Captured with initialBuildNumber: whether the selected update includes an APK step.
157
+ private apkExpectedInSession = false
158
+ // Latched when the legacy build-number completion fires; projected as "complete".
159
+ private apkCompletedViaBuildIncrease = false
160
+ // Holds a legacy apk install FINISHED out of "complete" for the settle window.
161
+ private legacyApkSettleHold = false
162
+ // Display-only legacy MTK install stall simulation.
163
+ private mtkSimulatedPercent: number | null = null
164
+ private lastRealMtkProgress = 0
165
+
166
+ // Timer handles
167
+ private globalTimeout: ReturnType<typeof setTimeout> | null = null
168
+ private globalTimeoutStarted = false
169
+ private retryTimeout: ReturnType<typeof setTimeout> | null = null
170
+ private stuckTimeout: ReturnType<typeof setTimeout> | null = null
171
+ private progressTimeout: ReturnType<typeof setTimeout> | null = null
172
+ private postApkDelay: ReturnType<typeof setTimeout> | null = null
173
+ private pingInterval: ReturnType<typeof setInterval> | null = null
174
+ private queryReplyTimeout: ReturnType<typeof setTimeout> | null = null
175
+ private continueLockoutTimer: ReturnType<typeof setTimeout> | null = null
176
+ private legacyApkSettleTimer: ReturnType<typeof setTimeout> | null = null
177
+ private mtkStallDetectTimer: ReturnType<typeof setTimeout> | null = null
178
+ private mtkSimTickTimer: ReturnType<typeof setInterval> | null = null
179
+
180
+ // Retry / ack bookkeeping (no glasses source)
181
+ private hasReceivedAck = false
182
+ private hasFirstActivity = false
183
+ // Stuck-at-zero watchdog clears only on first NON-ZERO progress; "first activity"
184
+ // alone (e.g. ota_status with stepPercent=0) used to clear it too eagerly.
185
+ private hasFirstNonZeroProgress = false
186
+ private retryCount = 0
187
+
188
+ // Log displayState transitions only (not every pass).
189
+ private prevDisplayState: DisplayState | null = null
190
+
191
+ // Last-handled reaction inputs — the equivalents of the old effect dep arrays.
192
+ private lastConnected = false
193
+ private lastOtaStatus: OtaStatus | null = null
194
+ private lastOtaProgress: OtaProgress | null = null
195
+ private lastBuildNumber = ""
196
+ private lastDisplayState: DisplayState | null = null
197
+ private lastStallSig = ""
198
+
199
+ // Reaction pass re-entrancy guard (mirrors React deferring a setState-during-
200
+ // effects re-render until the current effect batch finished).
201
+ private reacting = false
202
+ private reactQueued = false
203
+
204
+ private storeUnsubscribe: (() => void) | null = null
205
+ private snapshotCheckers = new Set<() => void>()
206
+
207
+ // --- public surface (engine.ota.installSession) ---
208
+
209
+ /**
210
+ * Bind the state machine to a mounted progress screen. Idempotent per
211
+ * attach/detach cycle. Runs the initial-mount arbitration (send ota_start
212
+ * when connected with no session; otherwise ota_query_status + reply
213
+ * fallback) and starts reacting to store changes + BLE OTA events.
214
+ */
215
+ attach(): void {
216
+ if (this.attached) return
217
+ this.attached = true
218
+ this.resetSessionState()
219
+ this.prevConnected = isGlassesConnected(useGlassesStore.getState().connection)
220
+ this.storeUnsubscribe = useGlassesStore.subscribe(() => this.react())
221
+ // Mount pass: every reaction block runs once (like all effects on mount),
222
+ // then any passes queued by state written during the blocks.
223
+ this.reacting = true
224
+ try {
225
+ this.runPass(true)
226
+ while (this.reactQueued) {
227
+ this.reactQueued = false
228
+ this.runPass(false)
229
+ }
230
+ } finally {
231
+ this.reacting = false
232
+ }
233
+ }
234
+
235
+ /**
236
+ * Unbind on screen unmount: clears ALL timers/subscriptions/listeners and
237
+ * resets the session-local state (the old component state died with the
238
+ * component) so a re-attach is a fresh session.
239
+ */
240
+ detach(): void {
241
+ if (!this.attached) return
242
+ this.attached = false
243
+ if (this.storeUnsubscribe) {
244
+ this.storeUnsubscribe()
245
+ this.storeUnsubscribe = null
246
+ }
247
+ GlobalEventEmitter.off("ota_start_ack", this.handleAck)
248
+ GlobalEventEmitter.off("mtk_update_complete", this.handleMtkComplete)
249
+ this.clearAllOtaTimers()
250
+ this.clearContinueLockoutTimer()
251
+ this.resetSessionState()
252
+ }
253
+
254
+ /** Retry after a failure: clear state and re-send ota_start (if connected). */
255
+ retry(): void {
256
+ console.log("[OTA_PROGRESS] retry pressed, clearing state and re-sending ota_start")
257
+ // Batch like the old event handler: React ran the whole handler (including
258
+ // the ota_start send) before re-rendering + re-running effects.
259
+ const wasReacting = this.reacting
260
+ this.reacting = true
261
+ try {
262
+ this.clearPerStepTimers()
263
+ this.clearLegacyApkSettleTimer()
264
+ this.clearMtkSimulationTimers()
265
+ this.retryCount = 0
266
+ this.hasFirstActivity = false
267
+ this.hasReceivedAck = false
268
+ this.setSawReconnectEdge(false)
269
+ this.setErrorMsg("")
270
+ this.setApkCompletedViaBuildIncrease(false)
271
+ this.setLegacyApkSettleHold(false)
272
+ this.setMtkSimulatedPercent(null)
273
+ this.lastRealMtkProgress = 0
274
+ const store = useGlassesStore.getState()
275
+ store.setOtaProgress(null)
276
+ store.setOtaStatus(null)
277
+ if (isGlassesConnected(useGlassesStore.getState().connection)) {
278
+ void this.sendOtaStartWithWatchdogs()
279
+ }
280
+ } finally {
281
+ this.reacting = wasReacting
282
+ }
283
+ if (!wasReacting) this.react()
284
+ }
285
+
286
+ /**
287
+ * Terminal-state cleanup half of the old Continue/Done handlers (navigation
288
+ * stays in the screen): clear the selected update, and after an APK step
289
+ * clear the stale build number so the next check re-reads version_info.
290
+ */
291
+ finish(): void {
292
+ useGlassesStore.getState().setOtaUpdateAvailable(null)
293
+ if (this.apkStepSeen) {
294
+ BluetoothSdk.updateGlasses({buildNumber: ""})
295
+ useGlassesStore.getState().setGlassesInfo({buildNumber: ""})
296
+ }
297
+ }
298
+
299
+ /**
300
+ * Abandon an interrupted session (the super-mode skip): terminal cleanup
301
+ * plus dropping the session's status/progress read-state, so
302
+ * deriveDisplayState doesn't resurrect the stale install when the host
303
+ * navigates away and back through /ota routes.
304
+ */
305
+ discard(): void {
306
+ this.finish()
307
+ const store = useGlassesStore.getState()
308
+ store.setOtaStatus(null)
309
+ store.setOtaProgress(null)
310
+ }
311
+
312
+ snapshot(): OtaInstallSnapshot {
313
+ const state = useGlassesStore.getState()
314
+ const connected = isGlassesConnected(state.connection)
315
+ const otaStatus = state.otaStatus
316
+ const otaProgress = state.otaProgress
317
+ return {
318
+ displayState: deriveDisplayState({
319
+ otaStatus,
320
+ otaProgress,
321
+ connected,
322
+ errorMsg: this.errorMsg,
323
+ sawReconnectEdge: this.sawReconnectEdge,
324
+ legacyApkSettleHold: this.legacyApkSettleHold,
325
+ apkCompletedViaBuildIncrease: this.apkCompletedViaBuildIncrease,
326
+ }),
327
+ errorMsg: this.errorMsg,
328
+ continueButtonDisabled: this.continueButtonDisabled,
329
+ connected,
330
+ // Copies: the snapshot must not hand callers mutable references into the store.
331
+ otaStatus: otaStatus ? {...otaStatus} : null,
332
+ otaProgress: otaProgress ? {...otaProgress} : null,
333
+ mtkInstallStallSimulatedPercent: this.mtkSimulatedPercent,
334
+ }
335
+ }
336
+
337
+ /**
338
+ * Subscribe to install snapshot changes, deduped on the projected JSON.
339
+ * Fires on glasses-store changes AND coordinator-internal state changes
340
+ * (errorMsg / reconnect edge / continue lockout). Returns an unsubscribe.
341
+ */
342
+ onSnapshot(cb: (snapshot: OtaInstallSnapshot) => void): () => void {
343
+ let last = JSON.stringify(this.snapshot())
344
+ const check = () => {
345
+ const snap = this.snapshot()
346
+ const key = JSON.stringify(snap)
347
+ if (key === last) return
348
+ last = key
349
+ cb(snap)
350
+ }
351
+ this.snapshotCheckers.add(check)
352
+ const unsubscribeStore = useGlassesStore.subscribe(check)
353
+ return () => {
354
+ this.snapshotCheckers.delete(check)
355
+ unsubscribeStore()
356
+ }
357
+ }
358
+
359
+ // --- internal state plumbing ---
360
+
361
+ private resetSessionState(): void {
362
+ this.errorMsg = ""
363
+ this.sawReconnectEdge = false
364
+ this.continueButtonDisabled = false
365
+ this.apkStepSeen = false
366
+ this.prevConnected = false
367
+ this.initialBuildNumber = null
368
+ this.apkExpectedInSession = false
369
+ this.apkCompletedViaBuildIncrease = false
370
+ this.legacyApkSettleHold = false
371
+ this.mtkSimulatedPercent = null
372
+ this.lastRealMtkProgress = 0
373
+ this.hasReceivedAck = false
374
+ this.hasFirstActivity = false
375
+ this.hasFirstNonZeroProgress = false
376
+ this.retryCount = 0
377
+ this.globalTimeoutStarted = false
378
+ this.prevDisplayState = null
379
+ this.lastConnected = false
380
+ this.lastOtaStatus = null
381
+ this.lastOtaProgress = null
382
+ this.lastBuildNumber = ""
383
+ this.lastDisplayState = null
384
+ this.lastStallSig = ""
385
+ this.reactQueued = false
386
+ }
387
+
388
+ /** Notify snapshot subscribers of a coordinator-internal state change. */
389
+ private emitInternalChange(): void {
390
+ for (const check of Array.from(this.snapshotCheckers)) check()
391
+ }
392
+
393
+ // Setters mirror the old setState calls: bail on identical values (React's
394
+ // setState bailout), notify snapshot subscribers, and queue a reaction pass.
395
+ private setErrorMsg(next: string): void {
396
+ if (this.errorMsg === next) return
397
+ this.errorMsg = next
398
+ this.emitInternalChange()
399
+ this.react()
400
+ }
401
+
402
+ private setSawReconnectEdge(next: boolean): void {
403
+ if (this.sawReconnectEdge === next) return
404
+ this.sawReconnectEdge = next
405
+ this.emitInternalChange()
406
+ this.react()
407
+ }
408
+
409
+ private setContinueButtonDisabled(next: boolean): void {
410
+ if (this.continueButtonDisabled === next) return
411
+ this.continueButtonDisabled = next
412
+ this.emitInternalChange()
413
+ this.react()
414
+ }
415
+
416
+ private setApkCompletedViaBuildIncrease(next: boolean): void {
417
+ if (this.apkCompletedViaBuildIncrease === next) return
418
+ this.apkCompletedViaBuildIncrease = next
419
+ this.emitInternalChange()
420
+ this.react()
421
+ }
422
+
423
+ private setLegacyApkSettleHold(next: boolean): void {
424
+ if (this.legacyApkSettleHold === next) return
425
+ this.legacyApkSettleHold = next
426
+ this.emitInternalChange()
427
+ this.react()
428
+ }
429
+
430
+ /** Display-only (WP 8C-e): notifies snapshot subscribers but never queues a reaction pass. */
431
+ private setMtkSimulatedPercent(next: number | null): void {
432
+ if (this.mtkSimulatedPercent === next) return
433
+ this.mtkSimulatedPercent = next
434
+ this.emitInternalChange()
435
+ }
436
+
437
+ /**
438
+ * Legacy-session shape (WP 8C): event shape wins once events exist; before any event
439
+ * only the session-start build number can tell (falls back to the live build number
440
+ * until it is captured). Old builds get the LEGACY_* padded policy durations.
441
+ */
442
+ private isLegacySessionShapeNow(): boolean {
443
+ const state = useGlassesStore.getState()
444
+ return isLegacyShapedOtaSession(
445
+ state.otaStatus,
446
+ state.otaProgress,
447
+ this.initialBuildNumber || state.buildNumber,
448
+ )
449
+ }
450
+
451
+ private react(): void {
452
+ if (!this.attached) return
453
+ if (this.reacting) {
454
+ this.reactQueued = true
455
+ return
456
+ }
457
+ this.reacting = true
458
+ try {
459
+ do {
460
+ this.reactQueued = false
461
+ this.runPass(false)
462
+ } while (this.reactQueued)
463
+ } finally {
464
+ this.reacting = false
465
+ }
466
+ }
467
+
468
+ /**
469
+ * One reaction pass = one render + its changed-dep effects of the old
470
+ * component, in the old declaration order.
471
+ */
472
+ private runPass(isMount: boolean): void {
473
+ const state = useGlassesStore.getState()
474
+ const connected = isGlassesConnected(state.connection)
475
+ const otaStatus = state.otaStatus
476
+ const otaProgress = state.otaProgress
477
+ const buildNumber = state.buildNumber
478
+
479
+ const connectedChanged = isMount || connected !== this.lastConnected
480
+ const otaStatusChanged = isMount || otaStatus !== this.lastOtaStatus
481
+ const otaProgressChanged = isMount || otaProgress !== this.lastOtaProgress
482
+ const buildNumberChanged = isMount || buildNumber !== this.lastBuildNumber
483
+
484
+ // Session-start build capture (legacy build-number APK completion, WP 8C-c) —
485
+ // mirrors the legacy screen capturing initialBuildNumber on its first truthy value,
486
+ // marked for APK only when the selected update sequence includes an apk step.
487
+ if (!this.initialBuildNumber && buildNumber) {
488
+ this.initialBuildNumber = buildNumber
489
+ this.apkExpectedInSession = !!state.otaUpdateAvailable?.updates?.includes("apk")
490
+ }
491
+
492
+ // Legacy pre-derivation compat (WP 8C): must run BEFORE deriveDisplayState so a
493
+ // legacy apk install "complete" is held by the settle window in the same pass it
494
+ // lands (never leaking a premature terminal pass to the watchdog blocks below).
495
+ if (otaStatusChanged) {
496
+ this.handleLegacyInstallCompleteEdge(otaStatus)
497
+ }
498
+
499
+ const legacySession = this.isLegacySessionShapeNow()
500
+
501
+ // Derived UI state — the glasses data IS the source of truth.
502
+ const displayState = deriveDisplayState({
503
+ otaStatus,
504
+ otaProgress,
505
+ connected,
506
+ errorMsg: this.errorMsg,
507
+ sawReconnectEdge: this.sawReconnectEdge,
508
+ legacyApkSettleHold: this.legacyApkSettleHold,
509
+ apkCompletedViaBuildIncrease: this.apkCompletedViaBuildIncrease,
510
+ })
511
+ const stallSig = buildProgressStalenessSignature(otaStatus, otaProgress, displayState)
512
+ const stallDuration = progressTimeoutDurationMs(otaStatus, otaProgress, legacySession)
513
+
514
+ const displayStateChanged = isMount || displayState !== this.lastDisplayState
515
+ const stallSigChanged = isMount || stallSig !== this.lastStallSig
516
+
517
+ // Commit this pass's inputs BEFORE running the blocks so state written
518
+ // mid-pass (which queues a follow-up pass) diffs against what this pass
519
+ // already handled — like React committing the render before its effects.
520
+ this.lastConnected = connected
521
+ this.lastOtaStatus = otaStatus
522
+ this.lastOtaProgress = otaProgress
523
+ this.lastBuildNumber = buildNumber
524
+ this.lastDisplayState = displayState
525
+ this.lastStallSig = stallSig
526
+
527
+ if (this.prevDisplayState !== displayState) {
528
+ console.log(
529
+ `[OTA_PROGRESS] displayState ${this.prevDisplayState ?? "<init>"} -> ${displayState}`,
530
+ JSON.stringify({
531
+ connected,
532
+ sawReconnectEdge: this.sawReconnectEdge,
533
+ errorMsg: this.errorMsg || null,
534
+ otaStatus: otaStatus
535
+ ? {
536
+ stepType: otaStatus.stepType,
537
+ phase: otaStatus.phase,
538
+ status: otaStatus.status,
539
+ step: `${otaStatus.currentStep}/${otaStatus.totalSteps}`,
540
+ pct: otaStatus.overallPercent,
541
+ }
542
+ : null,
543
+ otaProgress: otaProgress
544
+ ? {
545
+ currentUpdate: otaProgress.currentUpdate,
546
+ stage: otaProgress.stage,
547
+ status: otaProgress.status,
548
+ progress: otaProgress.progress,
549
+ }
550
+ : null,
551
+ }),
552
+ )
553
+ this.prevDisplayState = displayState
554
+ }
555
+
556
+ // APK-step latch (was the [otaStatus] effect above the timers).
557
+ if (otaStatusChanged && otaStatus?.stepType === "apk") {
558
+ this.apkStepSeen = true
559
+ }
560
+
561
+ // Legacy MTK completion side effect (WP 8C-a): old builds never send the
562
+ // mtk_update_complete BLE event; their install FINISHED is the completion signal,
563
+ // and the legacy screen marked MTK as updated this session right there.
564
+ if (
565
+ otaStatusChanged &&
566
+ isLegacyShapedOtaStatus(otaStatus) &&
567
+ otaStatus?.stepType === "mtk" &&
568
+ otaStatus.phase === "install" &&
569
+ otaStatus.status === "complete"
570
+ ) {
571
+ console.log("[OTA_PROGRESS] legacy mtk install complete — marking MTK updated this session")
572
+ useGlassesStore.getState().setMtkUpdatedThisSession(true)
573
+ }
574
+
575
+ // Legacy APK completion by build-number increase (WP 8C-c): old builds reboot into
576
+ // the new build without a reliable explicit reconnect status; the fresh version_info
577
+ // build number is the completion signal (ported from progress-legacy.tsx, which
578
+ // completed from installing-with-apk and from starting/failed).
579
+ if (
580
+ buildNumberChanged &&
581
+ !this.apkCompletedViaBuildIncrease &&
582
+ this.apkExpectedInSession &&
583
+ legacySession &&
584
+ this.initialBuildNumber
585
+ ) {
586
+ const currentBuild = Number.parseInt(buildNumber, 10)
587
+ const initialBuild = Number.parseInt(this.initialBuildNumber, 10)
588
+ const increased = Number.isFinite(currentBuild) && Number.isFinite(initialBuild) && currentBuild > initialBuild
589
+ const apkStepCurrent = otaStatus?.stepType === "apk" || otaProgress?.currentUpdate === "apk"
590
+ const detectable =
591
+ displayState === "starting" || displayState === "failed" || (displayState === "updating" && apkStepCurrent)
592
+ if (increased && detectable) {
593
+ console.log(
594
+ `[OTA_PROGRESS] legacy apk complete via build-number increase (${initialBuild} -> ${currentBuild}), completing session`,
595
+ )
596
+ this.clearPerStepTimers()
597
+ this.clearLegacyApkSettleTimer()
598
+ this.setLegacyApkSettleHold(false)
599
+ this.apkStepSeen = true
600
+ this.setErrorMsg("")
601
+ this.setApkCompletedViaBuildIncrease(true)
602
+ }
603
+ }
604
+
605
+ // Cancel the query-reply fallback as soon as the glasses reply with a useful
606
+ // status (in_progress / step_complete / complete / failed) or any progress
607
+ // event. An "idle" ota_status means glasses have no active session, so we
608
+ // must keep the fallback armed and let it retry ota_start.
609
+ if (otaStatusChanged || otaProgressChanged) {
610
+ if (this.queryReplyTimeout && hasRecoveringOtaReply(otaStatus, otaProgress)) {
611
+ this.clearQueryReplyTimeout()
612
+ }
613
+ }
614
+
615
+ /**
616
+ * Connect-edge — the only place that decides to send ota_start /
617
+ * ota_query_status, handles POST_APK delay, and flips sawReconnectEdge
618
+ * on the false -> true transition that signals the BES reboot completed.
619
+ */
620
+ if (connectedChanged) {
621
+ this.runConnectEdge(connected)
622
+ }
623
+
624
+ if (displayStateChanged && isTerminalForWatchdog(displayState)) {
625
+ this.clearGlobalTimeout()
626
+ }
627
+
628
+ if (isMount) {
629
+ GlobalEventEmitter.on("ota_start_ack", this.handleAck)
630
+ GlobalEventEmitter.on("mtk_update_complete", this.handleMtkComplete)
631
+ }
632
+
633
+ // Ping keepalive while an OTA is actively running (legacy sessions pinged on the
634
+ // padded interval — old builds slept less eagerly and pings are costlier for them).
635
+ if (connectedChanged || displayStateChanged) {
636
+ this.clearPingInterval()
637
+ const active = connected && (displayState === "starting" || displayState === "updating")
638
+ if (active) {
639
+ void BluetoothSdk.ping().catch(() => {})
640
+ const pingIntervalMs = legacySession ? LEGACY_PING_INTERVAL_MS : PING_INTERVAL_MS
641
+ this.pingInterval = setInterval(() => {
642
+ void BluetoothSdk.ping().catch(() => {})
643
+ }, pingIntervalMs)
644
+ }
645
+ }
646
+
647
+ // Any glasses activity (ota_status or otaProgress) clears the no-ack retry watchdog.
648
+ if ((otaStatusChanged || otaProgressChanged) && (otaStatus || otaProgress)) {
649
+ this.onFirstActivity()
650
+ }
651
+
652
+ // The stuck-at-zero watchdog clears only on the FIRST real (>0%) progress.
653
+ // Without this distinction, an ota_status reply with stepPercent=0 would
654
+ // disable the watchdog before any download had actually started, hiding
655
+ // wedged downloads from the user.
656
+ if (otaStatusChanged || otaProgressChanged) {
657
+ const stepPct = otaStatus?.stepPercent ?? 0
658
+ const overallPct = otaStatus?.overallPercent ?? 0
659
+ const legacyPct = otaProgress?.progress ?? 0
660
+ if (stepPct > 0 || overallPct > 0 || legacyPct > 0) {
661
+ this.onFirstNonZeroProgress()
662
+ }
663
+ }
664
+
665
+ // Progress stall watchdog — fails the update if glasses go silent mid-step.
666
+ // Keyed on the staleness SIGNATURE string (not the object refs) so a store
667
+ // update that doesn't change the signature keeps the same timer running
668
+ // instead of forever re-extending the deadline.
669
+ if (stallSigChanged || displayStateChanged) {
670
+ if (displayState !== "starting" && displayState !== "updating") {
671
+ this.clearProgressTimeout()
672
+ } else if (!stallSig) {
673
+ this.clearProgressTimeout()
674
+ } else {
675
+ const duration = stallDuration
676
+ this.clearProgressTimeout()
677
+ this.progressTimeout = setTimeout(() => {
678
+ this.progressTimeout = null
679
+ if (isTerminalForWatchdog(this.computeDisplayStateNow())) return
680
+ console.log(`[OTA_PROGRESS] watchdog: progress stalled for ${duration}ms, failing`)
681
+ this.setErrorMsg(OtaProgressMessages.stalledOrStuck)
682
+ }, duration)
683
+ }
684
+ }
685
+
686
+ // Lockout on Continue button after BES restart to prevent accidental tap
687
+ // (15s unified, 35s for legacy-shaped sessions — WP 8C-f).
688
+ if (displayStateChanged) {
689
+ this.clearContinueLockoutTimer()
690
+ if (displayState === "restarting") {
691
+ const lockoutMs = legacySession ? LEGACY_BES_CONTINUE_LOCKOUT_MS : BES_CONTINUE_LOCKOUT_MS
692
+ this.setContinueButtonDisabled(true)
693
+ this.continueLockoutTimer = setTimeout(() => {
694
+ this.continueLockoutTimer = null
695
+ this.setContinueButtonDisabled(false)
696
+ }, lockoutMs)
697
+ }
698
+ }
699
+
700
+ if (displayStateChanged && displayState === "failed") {
701
+ this.clearPerStepTimers()
702
+ }
703
+
704
+ // Legacy MTK install stall simulation (WP 8C-e): display-only. The simulation
705
+ // timers only ever touch the projected snapshot percent — they never feed back
706
+ // into arbitration (no reaction pass, no watchdog resets).
707
+ if (otaProgressChanged) {
708
+ this.runMtkStallSimulationPass(otaProgress, legacySession)
709
+ }
710
+
711
+ // Clear the selected update once this session reaches any terminal UI state.
712
+ // Catches paths the MantleManager ota_status listener misses — notably BES success
713
+ // (which terminates as `step_complete`, not `complete`) and APK build-number fallback
714
+ // completions (which never produce a `complete` ota_status).
715
+ if (
716
+ displayStateChanged &&
717
+ (displayState === "complete" || displayState === "restarting" || displayState === "failed")
718
+ ) {
719
+ useGlassesStore.getState().setOtaUpdateAvailable(null)
720
+ }
721
+ }
722
+
723
+ private runConnectEdge(connected: boolean): void {
724
+ const prev = this.prevConnected
725
+ this.prevConnected = connected
726
+
727
+ if (!connected) {
728
+ console.log("[OTA_PROGRESS] connect-edge: disconnected")
729
+ this.clearPostApkDelay()
730
+ // Also drop a pending query-reply fallback: firing ota_start into a dead
731
+ // link can only produce a false "failed" state, and the reconnect edge
732
+ // re-queries and re-arms this fallback anyway.
733
+ this.clearQueryReplyTimeout()
734
+ return
735
+ }
736
+
737
+ const becameConnected = prev === false && connected === true
738
+ if (becameConnected) {
739
+ console.log("[OTA_PROGRESS] connect-edge: false->true, flipping sawReconnectEdge=true")
740
+ this.setSawReconnectEdge(true)
741
+ }
742
+
743
+ // Legacy apk settle window (WP 8C): the glasses restarting into the new build is
744
+ // the EXPECTED reconnect here — the legacy screen took no action on it. Skip the
745
+ // query/fallback; the settle timer (or the build-number increase) completes.
746
+ if (becameConnected && this.legacyApkSettleHold) {
747
+ console.log("[OTA_PROGRESS] connect-edge: reconnect during legacy apk settle hold — no query")
748
+ return
749
+ }
750
+
751
+ const storeState = useGlassesStore.getState()
752
+ const s = storeState.otaStatus
753
+ const postApkAwaiting =
754
+ s?.stepType === "apk" && (s?.totalSteps ?? 0) > 1 && (s.status === "step_complete" || s.status === "complete")
755
+
756
+ if (becameConnected && postApkAwaiting) {
757
+ console.log("[OTA_PROGRESS] connect-edge: post-APK reboot detected, arming POST_APK delay for sendOtaStart")
758
+ this.clearPostApkDelay()
759
+ this.postApkDelay = setTimeout(() => {
760
+ this.postApkDelay = null
761
+ this.retryCount = 0
762
+ this.hasFirstActivity = false
763
+ this.hasFirstNonZeroProgress = false
764
+ this.hasReceivedAck = false
765
+ console.log("[OTA_PROGRESS] POST_APK delay fired, sending ota_start")
766
+ void this.sendOtaStartWithWatchdogs()
767
+ }, POST_APK_OTA_START_DELAY_MS)
768
+ return
769
+ }
770
+
771
+ if (becameConnected) {
772
+ console.log("[OTA_PROGRESS] connect-edge: reconnected, sending ota_query_status")
773
+ void BluetoothSdk.sendOtaQueryStatus()
774
+ this.armQueryReplyFallback("reconnect")
775
+ return
776
+ }
777
+
778
+ // Initial mount (prev === current === true). If no session yet, kick off ota_start.
779
+ // An idle ota_status has an empty sessionId; treat it as no session so ota_start
780
+ // still begins an explicit install.
781
+ const isIdleStatus = !!storeState.otaStatus && storeState.otaStatus.sessionId === ""
782
+ const noSessionYet = (!storeState.otaStatus && !storeState.otaProgress) || isIdleStatus
783
+ if (noSessionYet) {
784
+ console.log(
785
+ isIdleStatus
786
+ ? "[OTA_PROGRESS] initial mount, idle status (no sessionId), sending ota_start"
787
+ : "[OTA_PROGRESS] initial mount, no session in store, sending ota_start",
788
+ )
789
+ this.retryCount = 0
790
+ this.hasFirstActivity = false
791
+ this.hasFirstNonZeroProgress = false
792
+ this.hasReceivedAck = false
793
+ void this.sendOtaStartWithWatchdogs()
794
+ } else {
795
+ console.log("[OTA_PROGRESS] initial mount, session exists, sending ota_query_status")
796
+ void BluetoothSdk.sendOtaQueryStatus()
797
+ this.armQueryReplyFallback("initial-mount")
798
+ }
799
+ }
800
+
801
+ // --- BLE OTA event listeners (engine GlobalEventEmitter, fed by OtaService) ---
802
+
803
+ private readonly handleAck = (): void => {
804
+ if (this.hasReceivedAck) return
805
+ console.log("[OTA_PROGRESS] ota_start_ack received")
806
+ this.hasReceivedAck = true
807
+ this.clearRetryTimeout()
808
+ }
809
+
810
+ private readonly handleMtkComplete = (): void => {
811
+ console.log("[OTA_PROGRESS] mtk_update_complete received")
812
+ this.clearProgressTimeout()
813
+ this.onFirstActivity()
814
+ this.onFirstNonZeroProgress()
815
+ void BluetoothSdk.sendOtaQueryStatus()
816
+ useGlassesStore.getState().setMtkUpdatedThisSession(true)
817
+ }
818
+
819
+ // --- legacy (< 37) compatibility, ported from progress-legacy.tsx (WP 8C) ---
820
+
821
+ /**
822
+ * Reacts to a NEW legacy-shaped install-phase "complete" (an old build's
823
+ * `install FINISHED`). Two ports from the legacy screen:
824
+ * - last-write-wins: completion arriving after a watchdog failure overrides it
825
+ * (the old screen completed from "failed" too);
826
+ * - apk settle window: an apk install FINISHED observed in flight is held out of
827
+ * "complete" for LEGACY_APK_COMPLETION_SETTLE_MS so the ASG process restart
828
+ * settles (and fresh version_info lands) before the user can continue. From
829
+ * starting/failed (post-reboot explicit signal) completion is immediate.
830
+ */
831
+ private handleLegacyInstallCompleteEdge(otaStatus: OtaStatus | null): void {
832
+ if (!isLegacyShapedOtaStatus(otaStatus) || otaStatus?.phase !== "install" || otaStatus.status !== "complete") {
833
+ return
834
+ }
835
+
836
+ if (this.errorMsg) {
837
+ console.log("[OTA_PROGRESS] legacy install complete arrived after a failure — completing (legacy last-write-wins)")
838
+ this.setErrorMsg("")
839
+ this.clearLegacyApkSettleTimer()
840
+ this.setLegacyApkSettleHold(false)
841
+ return
842
+ }
843
+
844
+ if (
845
+ otaStatus.stepType === "apk" &&
846
+ !this.apkCompletedViaBuildIncrease &&
847
+ !this.legacyApkSettleHold &&
848
+ this.legacyApkSettleTimer === null &&
849
+ this.lastDisplayState === "updating"
850
+ ) {
851
+ console.log(
852
+ `[OTA_PROGRESS] legacy apk install complete — holding complete for ${LEGACY_APK_COMPLETION_SETTLE_MS}ms settle window`,
853
+ )
854
+ this.setLegacyApkSettleHold(true)
855
+ this.legacyApkSettleTimer = setTimeout(() => {
856
+ this.legacyApkSettleTimer = null
857
+ console.log("[OTA_PROGRESS] legacy apk settle window elapsed — releasing complete")
858
+ this.setLegacyApkSettleHold(false)
859
+ }, LEGACY_APK_COMPLETION_SETTLE_MS)
860
+ }
861
+ }
862
+
863
+ /**
864
+ * Legacy MTK install stall simulation (WP 8C-e), ported verbatim: the MTK system
865
+ * install typically stalls around 49-50%. Every real event restarts stall detection;
866
+ * after LEGACY_MTK_STALL_DETECT_MS of silence inside the [45, 55) zone, simulate +1%
867
+ * every LEGACY_MTK_SIM_TICK_MS from max(stall+1, 51), capped at 60. Real progress
868
+ * beyond the simulated value clears it. Display-only by construction: the timers call
869
+ * only {@link setMtkSimulatedPercent}, which never queues a reaction pass.
870
+ */
871
+ private runMtkStallSimulationPass(otaProgress: OtaProgress | null, legacySession: boolean): void {
872
+ const isLegacyMtkInstall =
873
+ legacySession &&
874
+ otaProgress?.currentUpdate === "mtk" &&
875
+ otaProgress.stage === "install" &&
876
+ (otaProgress.status === "STARTED" || otaProgress.status === "PROGRESS")
877
+
878
+ if (!isLegacyMtkInstall) {
879
+ this.clearMtkSimulationTimers()
880
+ this.setMtkSimulatedPercent(null)
881
+ return
882
+ }
883
+
884
+ const realProgress = otaProgress.progress ?? 0
885
+ if (realProgress > 0 && realProgress !== this.lastRealMtkProgress) {
886
+ this.lastRealMtkProgress = realProgress
887
+ if (this.mtkSimulatedPercent !== null && realProgress > this.mtkSimulatedPercent) {
888
+ this.setMtkSimulatedPercent(null)
889
+ }
890
+ }
891
+
892
+ // A real event arrived: restart stall detection (and stop any running ticker).
893
+ this.clearMtkSimulationTimers()
894
+ const inStallZone =
895
+ realProgress >= LEGACY_MTK_STALL_ZONE_MIN_PERCENT && realProgress < LEGACY_MTK_STALL_ZONE_MAX_PERCENT
896
+ if (!inStallZone) return
897
+
898
+ this.mtkStallDetectTimer = setTimeout(() => {
899
+ this.mtkStallDetectTimer = null
900
+ const stalledAt = this.lastRealMtkProgress
901
+ const prev = this.mtkSimulatedPercent
902
+ const target = Math.max(
903
+ prev !== null ? Math.max(prev, stalledAt + 1) : stalledAt + 1,
904
+ LEGACY_MTK_SIM_FLOOR_PERCENT,
905
+ )
906
+ console.log(
907
+ `[OTA_PROGRESS] legacy mtk install stalled at ${stalledAt}%, simulating display progress from ${target}%`,
908
+ )
909
+ this.setMtkSimulatedPercent(target)
910
+ this.mtkSimTickTimer = setInterval(() => {
911
+ const current = this.mtkSimulatedPercent ?? stalledAt + 1
912
+ const capped = Math.min(current + 1, LEGACY_MTK_SIM_CAP_PERCENT)
913
+ this.setMtkSimulatedPercent(capped)
914
+ if (capped >= LEGACY_MTK_SIM_CAP_PERCENT && this.mtkSimTickTimer) {
915
+ clearInterval(this.mtkSimTickTimer)
916
+ this.mtkSimTickTimer = null
917
+ }
918
+ }, LEGACY_MTK_SIM_TICK_MS)
919
+ }, LEGACY_MTK_STALL_DETECT_MS)
920
+ }
921
+
922
+ // --- watchdogs / send path ---
923
+
924
+ /**
925
+ * Read the current derived display state from the store + internal state
926
+ * synchronously — used inside setTimeout callbacks.
927
+ */
928
+ private computeDisplayStateNow(): DisplayState {
929
+ const state = useGlassesStore.getState()
930
+ return deriveDisplayState({
931
+ otaStatus: state.otaStatus,
932
+ otaProgress: state.otaProgress,
933
+ connected: isGlassesConnected(state.connection),
934
+ errorMsg: this.errorMsg,
935
+ sawReconnectEdge: this.sawReconnectEdge,
936
+ legacyApkSettleHold: this.legacyApkSettleHold,
937
+ apkCompletedViaBuildIncrease: this.apkCompletedViaBuildIncrease,
938
+ })
939
+ }
940
+
941
+ /**
942
+ * "Glasses are talking to us" — clears the no-ack retry watchdog only.
943
+ * Important: this does NOT clear the stuck-at-zero watchdog; that one fires
944
+ * on real progress > 0% (see {@link onFirstNonZeroProgress}).
945
+ */
946
+ private onFirstActivity(): void {
947
+ if (this.hasFirstActivity) return
948
+ this.hasFirstActivity = true
949
+ this.clearRetryTimeout()
950
+ }
951
+
952
+ /**
953
+ * "Real download progress arrived" — clears the stuck-at-zero watchdog. We
954
+ * deliberately wait for non-zero progress before clearing this so that an
955
+ * ota_status reply with stepPercent: 0 (which is "first activity" but not
956
+ * "real progress") doesn't disable the only watchdog that catches a wedged
957
+ * download.
958
+ */
959
+ private onFirstNonZeroProgress(): void {
960
+ if (this.hasFirstNonZeroProgress) return
961
+ this.hasFirstNonZeroProgress = true
962
+ this.clearStuckTimeout()
963
+ }
964
+
965
+ private maybeStartGlobalTimeout(): void {
966
+ if (this.globalTimeoutStarted) return
967
+ this.globalTimeoutStarted = true
968
+ // Legacy-shape check happens once, when the session cap is armed at the first
969
+ // ota_start send (WP 8C-b): old builds get the padded legacy cap for the whole
970
+ // session; a session that starts unified keeps the unified cap.
971
+ const globalTimeoutMs = this.isLegacySessionShapeNow() ? LEGACY_GLOBAL_OTA_TIMEOUT_MS : GLOBAL_OTA_TIMEOUT_MS
972
+ this.globalTimeout = setTimeout(() => {
973
+ this.globalTimeout = null
974
+ this.globalTimeoutStarted = false
975
+ if (isTerminalForWatchdog(this.computeDisplayStateNow())) return
976
+ console.log("[OTA_PROGRESS] watchdog: global timeout fired, failing session")
977
+ this.clearPerStepTimers()
978
+ // Legacy parity: the old screen's global-timeout handler also killed the apk
979
+ // completion timer and the MTK stall simulation (the flags/percent stay put —
980
+ // errorMsg outranks them in the projection, and retry()/last-write-wins reset them).
981
+ this.clearLegacyApkSettleTimer()
982
+ this.clearMtkSimulationTimers()
983
+ this.setErrorMsg(OtaProgressMessages.globalTimeout)
984
+ }, globalTimeoutMs)
985
+ }
986
+
987
+ private armAckAndStuckWatchdogsOnly(): void {
988
+ this.clearRetryTimeout()
989
+ this.clearStuckTimeout()
990
+
991
+ // Durations resolved at arm time (WP 8C-b): legacy-shaped sessions get the
992
+ // padded values progress-legacy.tsx used for old (< 37) builds.
993
+ const legacySession = this.isLegacySessionShapeNow()
994
+ const retryIntervalMs = legacySession ? LEGACY_RETRY_INTERVAL_MS : RETRY_INTERVAL_MS
995
+ const stuckTimeoutMs = legacySession ? LEGACY_DOWNLOAD_STUCK_TIMEOUT_MS : DOWNLOAD_STUCK_TIMEOUT_MS
996
+
997
+ this.retryTimeout = setTimeout(() => {
998
+ this.retryTimeout = null
999
+ if (this.hasReceivedAck || this.hasFirstActivity) return
1000
+ if (this.computeDisplayStateNow() !== "starting") return
1001
+ if (this.retryCount < MAX_RETRIES - 1) {
1002
+ this.retryCount += 1
1003
+ this.hasReceivedAck = false
1004
+ console.log(
1005
+ `[OTA_PROGRESS] watchdog: no ack in ${retryIntervalMs}ms, retrying ota_start (attempt ${this.retryCount})`,
1006
+ )
1007
+ void this.sendOtaStartWithWatchdogs(true)
1008
+ .then(() => {
1009
+ this.armAckAndStuckWatchdogsOnly()
1010
+ })
1011
+ .catch(() => {})
1012
+ } else {
1013
+ console.log(`[OTA_PROGRESS] watchdog: ota_start ack never received after ${MAX_RETRIES} attempts, failing`)
1014
+ this.setErrorMsg(OtaProgressMessages.noAckResponse)
1015
+ }
1016
+ }, retryIntervalMs)
1017
+
1018
+ this.stuckTimeout = setTimeout(() => {
1019
+ this.stuckTimeout = null
1020
+ const d = this.computeDisplayStateNow()
1021
+ const state = useGlassesStore.getState()
1022
+ if (d !== "starting" && !(d === "updating" && state.otaStatus?.phase === "download")) {
1023
+ return
1024
+ }
1025
+ const pct = latestPercentForStuck(state.otaStatus, state.otaProgress)
1026
+ if (pct !== 0) return
1027
+ console.log(`[OTA_PROGRESS] watchdog: stuck at 0% for ${stuckTimeoutMs}ms, failing`)
1028
+ this.clearRetryTimeout()
1029
+ this.setErrorMsg(OtaProgressMessages.stalledOrStuck)
1030
+ }, stuckTimeoutMs)
1031
+ }
1032
+
1033
+ private async sendOtaStartWithWatchdogs(retryAlreadyCounted = false): Promise<void> {
1034
+ this.maybeStartGlobalTimeout()
1035
+ this.hasReceivedAck = false
1036
+ this.armAckAndStuckWatchdogsOnly()
1037
+ try {
1038
+ const state = useGlassesStore.getState()
1039
+ const otaVersionUrl = getAsgOtaVersionUrl(state.otaVersionUrl, state.buildNumber)
1040
+ console.log(`[OTA_PROGRESS] sending ota_start with manifest URL: ${otaVersionUrl}`)
1041
+ await BluetoothSdk.startOtaUpdate(otaVersionUrl)
1042
+ } catch (err) {
1043
+ console.warn("[OTA_PROGRESS] sendOtaStart threw", err)
1044
+ this.clearRetryTimeout()
1045
+ this.clearStuckTimeout()
1046
+ if (this.retryCount < MAX_RETRIES - 1) {
1047
+ if (!retryAlreadyCounted) {
1048
+ this.retryCount += 1
1049
+ }
1050
+ const retryIntervalMs = this.isLegacySessionShapeNow() ? LEGACY_RETRY_INTERVAL_MS : RETRY_INTERVAL_MS
1051
+ this.retryTimeout = setTimeout(() => {
1052
+ this.retryTimeout = null
1053
+ void this.sendOtaStartWithWatchdogs()
1054
+ }, retryIntervalMs)
1055
+ } else {
1056
+ console.log("[OTA_PROGRESS] sendOtaStart failed after max retries, failing session")
1057
+ this.setErrorMsg(OtaProgressMessages.sendOtaStartFailed)
1058
+ }
1059
+ }
1060
+ }
1061
+
1062
+ /**
1063
+ * After sending ota_query_status, wait QUERY_REPLY_TIMEOUT_MS for the glasses
1064
+ * to reply with a useful ota_status. If nothing arrives (e.g. the glasses'
1065
+ * OTA session was wiped between mount and reconnect), or the glasses reply
1066
+ * with an explicit "idle" status (no session), fall back to ota_start so the
1067
+ * user doesn't sit on a spinner forever.
1068
+ *
1069
+ * Cleared as soon as a non-idle otaStatus or any otaProgress lands in the
1070
+ * store (see the reaction block above). An idle reply intentionally does NOT
1071
+ * cancel the fallback, so reconnects against a wiped/lost session still recover.
1072
+ */
1073
+ private armQueryReplyFallback(reason: "reconnect" | "initial-mount"): void {
1074
+ this.clearQueryReplyTimeout()
1075
+ this.queryReplyTimeout = setTimeout(() => {
1076
+ this.queryReplyTimeout = null
1077
+ const state = useGlassesStore.getState()
1078
+ // If we already got a useful reply, we'd have been cleared. Defensive
1079
+ // re-check: idle replies must not block the retry. Legacy-shaped state is
1080
+ // exempt (WP 8C-b): old (< 37) builds ignore ota_query_status entirely, so
1081
+ // whatever legacy-shaped status/progress sits in the store is a pre-query
1082
+ // leftover, not a reply — a NEW legacy event would have cleared this timer
1083
+ // through the reaction pass. Only a unified reply suppresses the fallback.
1084
+ const legacySession = isLegacyShapedOtaSession(
1085
+ state.otaStatus,
1086
+ state.otaProgress,
1087
+ this.initialBuildNumber || state.buildNumber,
1088
+ )
1089
+ if (!legacySession && hasRecoveringOtaReply(state.otaStatus, state.otaProgress)) return
1090
+ // Don't fire if we've left the active phase (e.g. user backed out, error overlay).
1091
+ if (isTerminalForWatchdog(this.computeDisplayStateNow())) return
1092
+ console.log(
1093
+ `[OTA_PROGRESS] watchdog: ota_query_status got no useful reply in ${QUERY_REPLY_TIMEOUT_MS}ms (reason=${reason}), falling back to ota_start`,
1094
+ )
1095
+ this.retryCount = 0
1096
+ this.hasFirstActivity = false
1097
+ this.hasFirstNonZeroProgress = false
1098
+ this.hasReceivedAck = false
1099
+ void this.sendOtaStartWithWatchdogs()
1100
+ }, QUERY_REPLY_TIMEOUT_MS)
1101
+ }
1102
+
1103
+ // --- timer cleanup helpers ---
1104
+
1105
+ private clearProgressTimeout(): void {
1106
+ if (this.progressTimeout) {
1107
+ clearTimeout(this.progressTimeout)
1108
+ this.progressTimeout = null
1109
+ }
1110
+ }
1111
+
1112
+ private clearRetryTimeout(): void {
1113
+ if (this.retryTimeout) {
1114
+ clearTimeout(this.retryTimeout)
1115
+ this.retryTimeout = null
1116
+ }
1117
+ }
1118
+
1119
+ private clearStuckTimeout(): void {
1120
+ if (this.stuckTimeout) {
1121
+ clearTimeout(this.stuckTimeout)
1122
+ this.stuckTimeout = null
1123
+ }
1124
+ }
1125
+
1126
+ private clearGlobalTimeout(): void {
1127
+ if (this.globalTimeout) {
1128
+ clearTimeout(this.globalTimeout)
1129
+ this.globalTimeout = null
1130
+ }
1131
+ this.globalTimeoutStarted = false
1132
+ }
1133
+
1134
+ private clearPostApkDelay(): void {
1135
+ if (this.postApkDelay) {
1136
+ clearTimeout(this.postApkDelay)
1137
+ this.postApkDelay = null
1138
+ }
1139
+ }
1140
+
1141
+ private clearPingInterval(): void {
1142
+ if (this.pingInterval) {
1143
+ clearInterval(this.pingInterval)
1144
+ this.pingInterval = null
1145
+ }
1146
+ }
1147
+
1148
+ private clearQueryReplyTimeout(): void {
1149
+ if (this.queryReplyTimeout) {
1150
+ clearTimeout(this.queryReplyTimeout)
1151
+ this.queryReplyTimeout = null
1152
+ }
1153
+ }
1154
+
1155
+ private clearContinueLockoutTimer(): void {
1156
+ if (this.continueLockoutTimer) {
1157
+ clearTimeout(this.continueLockoutTimer)
1158
+ this.continueLockoutTimer = null
1159
+ }
1160
+ }
1161
+
1162
+ private clearLegacyApkSettleTimer(): void {
1163
+ if (this.legacyApkSettleTimer) {
1164
+ clearTimeout(this.legacyApkSettleTimer)
1165
+ this.legacyApkSettleTimer = null
1166
+ }
1167
+ }
1168
+
1169
+ private clearMtkSimulationTimers(): void {
1170
+ if (this.mtkStallDetectTimer) {
1171
+ clearTimeout(this.mtkStallDetectTimer)
1172
+ this.mtkStallDetectTimer = null
1173
+ }
1174
+ if (this.mtkSimTickTimer) {
1175
+ clearInterval(this.mtkSimTickTimer)
1176
+ this.mtkSimTickTimer = null
1177
+ }
1178
+ }
1179
+
1180
+ /**
1181
+ * NOTE (WP 8C): the legacy apk settle timer and the MTK stall simulation timers are
1182
+ * deliberately NOT per-step watchdogs — a per-step failure must not kill them (the
1183
+ * legacy screen kept the simulation ticking through a watchdog failure, and the
1184
+ * settle latch resolves completion, not liveness). They are cleared on detach,
1185
+ * retry(), global timeout, and their own supersession paths.
1186
+ */
1187
+ private clearPerStepTimers(): void {
1188
+ this.clearRetryTimeout()
1189
+ this.clearStuckTimeout()
1190
+ this.clearProgressTimeout()
1191
+ this.clearPostApkDelay()
1192
+ this.clearQueryReplyTimeout()
1193
+ }
1194
+
1195
+ private clearAllOtaTimers(): void {
1196
+ this.clearPerStepTimers()
1197
+ this.clearGlobalTimeout()
1198
+ this.clearPingInterval()
1199
+ this.clearLegacyApkSettleTimer()
1200
+ this.clearMtkSimulationTimers()
1201
+ }
1202
+ }
1203
+
1204
+ /** Singleton — one install session machine per app process (matches the single progress screen). */
1205
+ export const otaInstallCoordinator = new OtaInstallCoordinator()