@mentra/engine 0.1.0-dev.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 (787) 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 +57 -0
  11. package/build/facades/dev.d.ts.map +1 -0
  12. package/build/facades/dev.js +187 -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 +23 -0
  55. package/build/facades/permissions.d.ts.map +1 -0
  56. package/build/facades/permissions.js +145 -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 +66 -0
  83. package/build/internal.d.ts.map +1 -0
  84. package/build/internal.js +89 -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 +303 -0
  99. package/build/services/AppRegistry.d.ts.map +1 -0
  100. package/build/services/AppRegistry.js +1029 -0
  101. package/build/services/AppRegistry.js.map +1 -0
  102. package/build/services/AudioCloudUplink.d.ts +3 -0
  103. package/build/services/AudioCloudUplink.d.ts.map +1 -0
  104. package/build/services/AudioCloudUplink.js +33 -0
  105. package/build/services/AudioCloudUplink.js.map +1 -0
  106. package/build/services/AudioPlaybackService.d.ts +144 -0
  107. package/build/services/AudioPlaybackService.d.ts.map +1 -0
  108. package/build/services/AudioPlaybackService.js +533 -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 +627 -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 +433 -0
  175. package/build/services/LocalMiniappRuntime.d.ts.map +1 -0
  176. package/build/services/LocalMiniappRuntime.js +3561 -0
  177. package/build/services/LocalMiniappRuntime.js.map +1 -0
  178. package/build/services/LocalSttFallbackCoordinator.d.ts +54 -0
  179. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -0
  180. package/build/services/LocalSttFallbackCoordinator.js +131 -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/NavigationHandlers.d.ts +90 -0
  219. package/build/services/NavigationHandlers.d.ts.map +1 -0
  220. package/build/services/NavigationHandlers.js +379 -0
  221. package/build/services/NavigationHandlers.js.map +1 -0
  222. package/build/services/NavigationService.d.ts +254 -0
  223. package/build/services/NavigationService.d.ts.map +1 -0
  224. package/build/services/NavigationService.js +553 -0
  225. package/build/services/NavigationService.js.map +1 -0
  226. package/build/services/NotificationsEmitter.d.ts +28 -0
  227. package/build/services/NotificationsEmitter.d.ts.map +1 -0
  228. package/build/services/NotificationsEmitter.js +22 -0
  229. package/build/services/NotificationsEmitter.js.map +1 -0
  230. package/build/services/OfflineSpeechModelService.d.ts +33 -0
  231. package/build/services/OfflineSpeechModelService.d.ts.map +1 -0
  232. package/build/services/OfflineSpeechModelService.js +136 -0
  233. package/build/services/OfflineSpeechModelService.js.map +1 -0
  234. package/build/services/OtaInstallCoordinator.d.ts +195 -0
  235. package/build/services/OtaInstallCoordinator.d.ts.map +1 -0
  236. package/build/services/OtaInstallCoordinator.js +1047 -0
  237. package/build/services/OtaInstallCoordinator.js.map +1 -0
  238. package/build/services/OtaService.d.ts +3 -0
  239. package/build/services/OtaService.d.ts.map +1 -0
  240. package/build/services/OtaService.js +65 -0
  241. package/build/services/OtaService.js.map +1 -0
  242. package/build/services/OtaUpdateCheckService.d.ts +65 -0
  243. package/build/services/OtaUpdateCheckService.d.ts.map +1 -0
  244. package/build/services/OtaUpdateCheckService.js +260 -0
  245. package/build/services/OtaUpdateCheckService.js.map +1 -0
  246. package/build/services/PairingIdentity.d.ts +80 -0
  247. package/build/services/PairingIdentity.d.ts.map +1 -0
  248. package/build/services/PairingIdentity.js +145 -0
  249. package/build/services/PairingIdentity.js.map +1 -0
  250. package/build/services/PhoneLocationService.d.ts +36 -0
  251. package/build/services/PhoneLocationService.d.ts.map +1 -0
  252. package/build/services/PhoneLocationService.js +115 -0
  253. package/build/services/PhoneLocationService.js.map +1 -0
  254. package/build/services/PhoneNotificationsSync.d.ts +3 -0
  255. package/build/services/PhoneNotificationsSync.d.ts.map +1 -0
  256. package/build/services/PhoneNotificationsSync.js +35 -0
  257. package/build/services/PhoneNotificationsSync.js.map +1 -0
  258. package/build/services/PhonePhotoCoordinator.d.ts +86 -0
  259. package/build/services/PhonePhotoCoordinator.d.ts.map +1 -0
  260. package/build/services/PhonePhotoCoordinator.js +274 -0
  261. package/build/services/PhonePhotoCoordinator.js.map +1 -0
  262. package/build/services/PhoneStreamCoordinator.d.ts +168 -0
  263. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -0
  264. package/build/services/PhoneStreamCoordinator.js +632 -0
  265. package/build/services/PhoneStreamCoordinator.js.map +1 -0
  266. package/build/services/PhoneVideoCoordinator.d.ts +50 -0
  267. package/build/services/PhoneVideoCoordinator.d.ts.map +1 -0
  268. package/build/services/PhoneVideoCoordinator.js +147 -0
  269. package/build/services/PhoneVideoCoordinator.js.map +1 -0
  270. package/build/services/STTModelManager.d.ts +65 -0
  271. package/build/services/STTModelManager.d.ts.map +1 -0
  272. package/build/services/STTModelManager.js +292 -0
  273. package/build/services/STTModelManager.js.map +1 -0
  274. package/build/services/SceneRenderer.d.ts +90 -0
  275. package/build/services/SceneRenderer.d.ts.map +1 -0
  276. package/build/services/SceneRenderer.js +248 -0
  277. package/build/services/SceneRenderer.js.map +1 -0
  278. package/build/services/StreamLifecycleController.d.ts +67 -0
  279. package/build/services/StreamLifecycleController.d.ts.map +1 -0
  280. package/build/services/StreamLifecycleController.js +152 -0
  281. package/build/services/StreamLifecycleController.js.map +1 -0
  282. package/build/services/TTSModelManager.d.ts +90 -0
  283. package/build/services/TTSModelManager.d.ts.map +1 -0
  284. package/build/services/TTSModelManager.js +366 -0
  285. package/build/services/TTSModelManager.js.map +1 -0
  286. package/build/services/WebviewBridge.d.ts +22 -0
  287. package/build/services/WebviewBridge.d.ts.map +1 -0
  288. package/build/services/WebviewBridge.js +47 -0
  289. package/build/services/WebviewBridge.js.map +1 -0
  290. package/build/services/asg/GalleryMediaIntegrityReportService.d.ts +17 -0
  291. package/build/services/asg/GalleryMediaIntegrityReportService.d.ts.map +1 -0
  292. package/build/services/asg/GalleryMediaIntegrityReportService.js +43 -0
  293. package/build/services/asg/GalleryMediaIntegrityReportService.js.map +1 -0
  294. package/build/services/asg/asgCameraApi.d.ts +165 -0
  295. package/build/services/asg/asgCameraApi.d.ts.map +1 -0
  296. package/build/services/asg/asgCameraApi.js +997 -0
  297. package/build/services/asg/asgCameraApi.js.map +1 -0
  298. package/build/services/asg/galleryMediaValidation.d.ts +29 -0
  299. package/build/services/asg/galleryMediaValidation.d.ts.map +1 -0
  300. package/build/services/asg/galleryMediaValidation.js +149 -0
  301. package/build/services/asg/galleryMediaValidation.js.map +1 -0
  302. package/build/services/asg/galleryNotices.d.ts +33 -0
  303. package/build/services/asg/galleryNotices.d.ts.map +1 -0
  304. package/build/services/asg/galleryNotices.js +29 -0
  305. package/build/services/asg/galleryNotices.js.map +1 -0
  306. package/build/services/asg/gallerySettingsService.d.ts +19 -0
  307. package/build/services/asg/gallerySettingsService.d.ts.map +1 -0
  308. package/build/services/asg/gallerySettingsService.js +51 -0
  309. package/build/services/asg/gallerySettingsService.js.map +1 -0
  310. package/build/services/asg/gallerySyncNotifications.d.ts +56 -0
  311. package/build/services/asg/gallerySyncNotifications.d.ts.map +1 -0
  312. package/build/services/asg/gallerySyncNotifications.js +198 -0
  313. package/build/services/asg/gallerySyncNotifications.js.map +1 -0
  314. package/build/services/asg/gallerySyncService.d.ts +137 -0
  315. package/build/services/asg/gallerySyncService.d.ts.map +1 -0
  316. package/build/services/asg/gallerySyncService.js +1839 -0
  317. package/build/services/asg/gallerySyncService.js.map +1 -0
  318. package/build/services/asg/localStorageService.d.ts +128 -0
  319. package/build/services/asg/localStorageService.d.ts.map +1 -0
  320. package/build/services/asg/localStorageService.js +423 -0
  321. package/build/services/asg/localStorageService.js.map +1 -0
  322. package/build/services/asg/mediaProcessingQueue.d.ts +60 -0
  323. package/build/services/asg/mediaProcessingQueue.d.ts.map +1 -0
  324. package/build/services/asg/mediaProcessingQueue.js +320 -0
  325. package/build/services/asg/mediaProcessingQueue.js.map +1 -0
  326. package/build/services/asgOtaVersionUrl.d.ts +2 -0
  327. package/build/services/asgOtaVersionUrl.d.ts.map +1 -0
  328. package/build/services/asgOtaVersionUrl.js +36 -0
  329. package/build/services/asgOtaVersionUrl.js.map +1 -0
  330. package/build/services/blobPaths.d.ts +31 -0
  331. package/build/services/blobPaths.d.ts.map +1 -0
  332. package/build/services/blobPaths.js +86 -0
  333. package/build/services/blobPaths.js.map +1 -0
  334. package/build/services/cloudStreamApi.d.ts +59 -0
  335. package/build/services/cloudStreamApi.d.ts.map +1 -0
  336. package/build/services/cloudStreamApi.js +81 -0
  337. package/build/services/cloudStreamApi.js.map +1 -0
  338. package/build/services/gallerySyncClock.d.ts +17 -0
  339. package/build/services/gallerySyncClock.d.ts.map +1 -0
  340. package/build/services/gallerySyncClock.js +21 -0
  341. package/build/services/gallerySyncClock.js.map +1 -0
  342. package/build/services/glassesClockSync.d.ts +20 -0
  343. package/build/services/glassesClockSync.d.ts.map +1 -0
  344. package/build/services/glassesClockSync.js +97 -0
  345. package/build/services/glassesClockSync.js.map +1 -0
  346. package/build/services/manifestVersionGate.d.ts +28 -0
  347. package/build/services/manifestVersionGate.d.ts.map +1 -0
  348. package/build/services/manifestVersionGate.js +41 -0
  349. package/build/services/manifestVersionGate.js.map +1 -0
  350. package/build/services/mentraUiShim.d.ts +38 -0
  351. package/build/services/mentraUiShim.d.ts.map +1 -0
  352. package/build/services/mentraUiShim.js +360 -0
  353. package/build/services/mentraUiShim.js.map +1 -0
  354. package/build/services/navigation/roadNameResolver.d.ts +67 -0
  355. package/build/services/navigation/roadNameResolver.d.ts.map +1 -0
  356. package/build/services/navigation/roadNameResolver.js +96 -0
  357. package/build/services/navigation/roadNameResolver.js.map +1 -0
  358. package/build/services/navigation/routesApiCodec.d.ts +38 -0
  359. package/build/services/navigation/routesApiCodec.d.ts.map +1 -0
  360. package/build/services/navigation/routesApiCodec.js +68 -0
  361. package/build/services/navigation/routesApiCodec.js.map +1 -0
  362. package/build/services/otaDisplayState.d.ts +42 -0
  363. package/build/services/otaDisplayState.d.ts.map +1 -0
  364. package/build/services/otaDisplayState.js +92 -0
  365. package/build/services/otaDisplayState.js.map +1 -0
  366. package/build/services/otaInstallPolicy.d.ts +81 -0
  367. package/build/services/otaInstallPolicy.d.ts.map +1 -0
  368. package/build/services/otaInstallPolicy.js +96 -0
  369. package/build/services/otaInstallPolicy.js.map +1 -0
  370. package/build/services/otaLegacyMapping.d.ts +22 -0
  371. package/build/services/otaLegacyMapping.d.ts.map +1 -0
  372. package/build/services/otaLegacyMapping.js +56 -0
  373. package/build/services/otaLegacyMapping.js.map +1 -0
  374. package/build/services/slimStreamStatus.d.ts +7 -0
  375. package/build/services/slimStreamStatus.d.ts.map +1 -0
  376. package/build/services/slimStreamStatus.js +26 -0
  377. package/build/services/slimStreamStatus.js.map +1 -0
  378. package/build/stores/apps.d.ts +104 -0
  379. package/build/stores/apps.d.ts.map +1 -0
  380. package/build/stores/apps.js +492 -0
  381. package/build/stores/apps.js.map +1 -0
  382. package/build/stores/bluetoothSettingKeys.d.ts +4 -0
  383. package/build/stores/bluetoothSettingKeys.d.ts.map +1 -0
  384. package/build/stores/bluetoothSettingKeys.js +31 -0
  385. package/build/stores/bluetoothSettingKeys.js.map +1 -0
  386. package/build/stores/cloudClientStatus.d.ts +9 -0
  387. package/build/stores/cloudClientStatus.d.ts.map +1 -0
  388. package/build/stores/cloudClientStatus.js +24 -0
  389. package/build/stores/cloudClientStatus.js.map +1 -0
  390. package/build/stores/connection.d.ts +22 -0
  391. package/build/stores/connection.d.ts.map +1 -0
  392. package/build/stores/connection.js +43 -0
  393. package/build/stores/connection.js.map +1 -0
  394. package/build/stores/core.d.ts +15 -0
  395. package/build/stores/core.d.ts.map +1 -0
  396. package/build/stores/core.js +21 -0
  397. package/build/stores/core.js.map +1 -0
  398. package/build/stores/display.d.ts +24 -0
  399. package/build/stores/display.d.ts.map +1 -0
  400. package/build/stores/display.js +96 -0
  401. package/build/stores/display.js.map +1 -0
  402. package/build/stores/gallerySync.d.ts +101 -0
  403. package/build/stores/gallerySync.d.ts.map +1 -0
  404. package/build/stores/gallerySync.js +217 -0
  405. package/build/stores/gallerySync.js.map +1 -0
  406. package/build/stores/glasses.d.ts +62 -0
  407. package/build/stores/glasses.d.ts.map +1 -0
  408. package/build/stores/glasses.js +203 -0
  409. package/build/stores/glasses.js.map +1 -0
  410. package/build/stores/settings.d.ts +37 -0
  411. package/build/stores/settings.d.ts.map +1 -0
  412. package/build/stores/settings.js +915 -0
  413. package/build/stores/settings.js.map +1 -0
  414. package/build/types/applet.d.ts +96 -0
  415. package/build/types/applet.d.ts.map +1 -0
  416. package/build/types/applet.js +5 -0
  417. package/build/types/applet.js.map +1 -0
  418. package/build/types/asg.d.ts +46 -0
  419. package/build/types/asg.d.ts.map +1 -0
  420. package/build/types/asg.js +2 -0
  421. package/build/types/asg.js.map +1 -0
  422. package/build/types/capabilities/even-realities-g1.d.ts +12 -0
  423. package/build/types/capabilities/even-realities-g1.d.ts.map +1 -0
  424. package/build/types/capabilities/even-realities-g1.js +55 -0
  425. package/build/types/capabilities/even-realities-g1.js.map +1 -0
  426. package/build/types/capabilities/even-realities-g2.d.ts +12 -0
  427. package/build/types/capabilities/even-realities-g2.d.ts.map +1 -0
  428. package/build/types/capabilities/even-realities-g2.js +75 -0
  429. package/build/types/capabilities/even-realities-g2.js.map +1 -0
  430. package/build/types/capabilities/mentra-display.d.ts +12 -0
  431. package/build/types/capabilities/mentra-display.d.ts.map +1 -0
  432. package/build/types/capabilities/mentra-display.js +63 -0
  433. package/build/types/capabilities/mentra-display.js.map +1 -0
  434. package/build/types/capabilities/mentra-live.d.ts +12 -0
  435. package/build/types/capabilities/mentra-live.d.ts.map +1 -0
  436. package/build/types/capabilities/mentra-live.js +92 -0
  437. package/build/types/capabilities/mentra-live.js.map +1 -0
  438. package/build/types/capabilities/none.d.ts +13 -0
  439. package/build/types/capabilities/none.d.ts.map +1 -0
  440. package/build/types/capabilities/none.js +65 -0
  441. package/build/types/capabilities/none.js.map +1 -0
  442. package/build/types/capabilities/simulated-glasses.d.ts +13 -0
  443. package/build/types/capabilities/simulated-glasses.d.ts.map +1 -0
  444. package/build/types/capabilities/simulated-glasses.js +65 -0
  445. package/build/types/capabilities/simulated-glasses.js.map +1 -0
  446. package/build/types/capabilities/vuzix-z100.d.ts +12 -0
  447. package/build/types/capabilities/vuzix-z100.d.ts.map +1 -0
  448. package/build/types/capabilities/vuzix-z100.js +52 -0
  449. package/build/types/capabilities/vuzix-z100.js.map +1 -0
  450. package/build/types/enums.d.ts +40 -0
  451. package/build/types/enums.d.ts.map +1 -0
  452. package/build/types/enums.js +44 -0
  453. package/build/types/enums.js.map +1 -0
  454. package/build/types/hardware.d.ts +160 -0
  455. package/build/types/hardware.d.ts.map +1 -0
  456. package/build/types/hardware.js +36 -0
  457. package/build/types/hardware.js.map +1 -0
  458. package/build/types/index.d.ts +11 -0
  459. package/build/types/index.d.ts.map +1 -0
  460. package/build/types/index.js +10 -0
  461. package/build/types/index.js.map +1 -0
  462. package/build/utils/GlobalEventEmitter.d.ts +10 -0
  463. package/build/utils/GlobalEventEmitter.d.ts.map +1 -0
  464. package/build/utils/GlobalEventEmitter.js +13 -0
  465. package/build/utils/GlobalEventEmitter.js.map +1 -0
  466. package/build/utils/cloudClient/RnUdpAdapter.d.ts +3 -0
  467. package/build/utils/cloudClient/RnUdpAdapter.d.ts.map +1 -0
  468. package/build/utils/cloudClient/RnUdpAdapter.js +41 -0
  469. package/build/utils/cloudClient/RnUdpAdapter.js.map +1 -0
  470. package/build/utils/cloudClient/cloudSecureStore.d.ts +3 -0
  471. package/build/utils/cloudClient/cloudSecureStore.d.ts.map +1 -0
  472. package/build/utils/cloudClient/cloudSecureStore.js +26 -0
  473. package/build/utils/cloudClient/cloudSecureStore.js.map +1 -0
  474. package/build/utils/debouncedPatch.d.ts +6 -0
  475. package/build/utils/debouncedPatch.d.ts.map +1 -0
  476. package/build/utils/debouncedPatch.js +25 -0
  477. package/build/utils/debouncedPatch.js.map +1 -0
  478. package/build/utils/devLogging.d.ts +26 -0
  479. package/build/utils/devLogging.d.ts.map +1 -0
  480. package/build/utils/devLogging.js +116 -0
  481. package/build/utils/devLogging.js.map +1 -0
  482. package/build/utils/devMiniappLaunch.d.ts +44 -0
  483. package/build/utils/devMiniappLaunch.d.ts.map +1 -0
  484. package/build/utils/devMiniappLaunch.js +52 -0
  485. package/build/utils/devMiniappLaunch.js.map +1 -0
  486. package/build/utils/diagnosticContext.d.ts +3 -0
  487. package/build/utils/diagnosticContext.d.ts.map +1 -0
  488. package/build/utils/diagnosticContext.js +119 -0
  489. package/build/utils/diagnosticContext.js.map +1 -0
  490. package/build/utils/display/composer/ColumnComposer.d.ts +131 -0
  491. package/build/utils/display/composer/ColumnComposer.d.ts.map +1 -0
  492. package/build/utils/display/composer/ColumnComposer.js +204 -0
  493. package/build/utils/display/composer/ColumnComposer.js.map +1 -0
  494. package/build/utils/display/composer/index.d.ts +9 -0
  495. package/build/utils/display/composer/index.d.ts.map +1 -0
  496. package/build/utils/display/composer/index.js +9 -0
  497. package/build/utils/display/composer/index.js.map +1 -0
  498. package/build/utils/display/helpers/DisplayHelpers.d.ts +165 -0
  499. package/build/utils/display/helpers/DisplayHelpers.d.ts.map +1 -0
  500. package/build/utils/display/helpers/DisplayHelpers.js +312 -0
  501. package/build/utils/display/helpers/DisplayHelpers.js.map +1 -0
  502. package/build/utils/display/helpers/ScrollView.d.ts +183 -0
  503. package/build/utils/display/helpers/ScrollView.d.ts.map +1 -0
  504. package/build/utils/display/helpers/ScrollView.js +257 -0
  505. package/build/utils/display/helpers/ScrollView.js.map +1 -0
  506. package/build/utils/display/helpers/index.d.ts +11 -0
  507. package/build/utils/display/helpers/index.d.ts.map +1 -0
  508. package/build/utils/display/helpers/index.js +10 -0
  509. package/build/utils/display/helpers/index.js.map +1 -0
  510. package/build/utils/display/index.d.ts +174 -0
  511. package/build/utils/display/index.d.ts.map +1 -0
  512. package/build/utils/display/index.js +185 -0
  513. package/build/utils/display/index.js.map +1 -0
  514. package/build/utils/display/measurer/TextMeasurer.d.ts +160 -0
  515. package/build/utils/display/measurer/TextMeasurer.d.ts.map +1 -0
  516. package/build/utils/display/measurer/TextMeasurer.js +273 -0
  517. package/build/utils/display/measurer/TextMeasurer.js.map +1 -0
  518. package/build/utils/display/measurer/index.d.ts +10 -0
  519. package/build/utils/display/measurer/index.d.ts.map +1 -0
  520. package/build/utils/display/measurer/index.js +11 -0
  521. package/build/utils/display/measurer/index.js.map +1 -0
  522. package/build/utils/display/measurer/script-detection.d.ts +53 -0
  523. package/build/utils/display/measurer/script-detection.d.ts.map +1 -0
  524. package/build/utils/display/measurer/script-detection.js +184 -0
  525. package/build/utils/display/measurer/script-detection.js.map +1 -0
  526. package/build/utils/display/profiles/g1.d.ts +33 -0
  527. package/build/utils/display/profiles/g1.d.ts.map +1 -0
  528. package/build/utils/display/profiles/g1.js +213 -0
  529. package/build/utils/display/profiles/g1.js.map +1 -0
  530. package/build/utils/display/profiles/g2.d.ts +13 -0
  531. package/build/utils/display/profiles/g2.d.ts.map +1 -0
  532. package/build/utils/display/profiles/g2.js +34 -0
  533. package/build/utils/display/profiles/g2.js.map +1 -0
  534. package/build/utils/display/profiles/index.d.ts +12 -0
  535. package/build/utils/display/profiles/index.d.ts.map +1 -0
  536. package/build/utils/display/profiles/index.js +15 -0
  537. package/build/utils/display/profiles/index.js.map +1 -0
  538. package/build/utils/display/profiles/nex.d.ts +10 -0
  539. package/build/utils/display/profiles/nex.d.ts.map +1 -0
  540. package/build/utils/display/profiles/nex.js +150 -0
  541. package/build/utils/display/profiles/nex.js.map +1 -0
  542. package/build/utils/display/profiles/types.d.ts +103 -0
  543. package/build/utils/display/profiles/types.d.ts.map +1 -0
  544. package/build/utils/display/profiles/types.js +2 -0
  545. package/build/utils/display/profiles/types.js.map +1 -0
  546. package/build/utils/display/profiles/z100.d.ts +33 -0
  547. package/build/utils/display/profiles/z100.d.ts.map +1 -0
  548. package/build/utils/display/profiles/z100.js +182 -0
  549. package/build/utils/display/profiles/z100.js.map +1 -0
  550. package/build/utils/display/scene/degrade.d.ts +25 -0
  551. package/build/utils/display/scene/degrade.d.ts.map +1 -0
  552. package/build/utils/display/scene/degrade.js +64 -0
  553. package/build/utils/display/scene/degrade.js.map +1 -0
  554. package/build/utils/display/scene/differ.d.ts +38 -0
  555. package/build/utils/display/scene/differ.d.ts.map +1 -0
  556. package/build/utils/display/scene/differ.js +107 -0
  557. package/build/utils/display/scene/differ.js.map +1 -0
  558. package/build/utils/display/scene/index.d.ts +10 -0
  559. package/build/utils/display/scene/index.d.ts.map +1 -0
  560. package/build/utils/display/scene/index.js +6 -0
  561. package/build/utils/display/scene/index.js.map +1 -0
  562. package/build/utils/display/scene/process.d.ts +35 -0
  563. package/build/utils/display/scene/process.d.ts.map +1 -0
  564. package/build/utils/display/scene/process.js +187 -0
  565. package/build/utils/display/scene/process.js.map +1 -0
  566. package/build/utils/display/scene/store.d.ts +48 -0
  567. package/build/utils/display/scene/store.d.ts.map +1 -0
  568. package/build/utils/display/scene/store.js +0 -0
  569. package/build/utils/display/scene/store.js.map +1 -0
  570. package/build/utils/display/scene/types.d.ts +120 -0
  571. package/build/utils/display/scene/types.d.ts.map +1 -0
  572. package/build/utils/display/scene/types.js +0 -0
  573. package/build/utils/display/scene/types.js.map +1 -0
  574. package/build/utils/display/wrapper/TextWrapper.d.ts +102 -0
  575. package/build/utils/display/wrapper/TextWrapper.d.ts.map +1 -0
  576. package/build/utils/display/wrapper/TextWrapper.js +471 -0
  577. package/build/utils/display/wrapper/TextWrapper.js.map +1 -0
  578. package/build/utils/display/wrapper/index.d.ts +12 -0
  579. package/build/utils/display/wrapper/index.d.ts.map +1 -0
  580. package/build/utils/display/wrapper/index.js +12 -0
  581. package/build/utils/display/wrapper/index.js.map +1 -0
  582. package/build/utils/display/wrapper/types.d.ts +75 -0
  583. package/build/utils/display/wrapper/types.d.ts.map +1 -0
  584. package/build/utils/display/wrapper/types.js +11 -0
  585. package/build/utils/display/wrapper/types.js.map +1 -0
  586. package/build/utils/e2eMetrics.d.ts +6 -0
  587. package/build/utils/e2eMetrics.d.ts.map +1 -0
  588. package/build/utils/e2eMetrics.js +27 -0
  589. package/build/utils/e2eMetrics.js.map +1 -0
  590. package/build/utils/hardware/hardware.d.ts +42 -0
  591. package/build/utils/hardware/hardware.d.ts.map +1 -0
  592. package/build/utils/hardware/hardware.js +127 -0
  593. package/build/utils/hardware/hardware.js.map +1 -0
  594. package/build/utils/hardware/index.d.ts +2 -0
  595. package/build/utils/hardware/index.d.ts.map +1 -0
  596. package/build/utils/hardware/index.js +2 -0
  597. package/build/utils/hardware/index.js.map +1 -0
  598. package/build/utils/miniappGlobals.d.ts +60 -0
  599. package/build/utils/miniappGlobals.d.ts.map +1 -0
  600. package/build/utils/miniappGlobals.js +224 -0
  601. package/build/utils/miniappGlobals.js.map +1 -0
  602. package/build/utils/permissions/MediaLibraryPermissions.d.ts +34 -0
  603. package/build/utils/permissions/MediaLibraryPermissions.d.ts.map +1 -0
  604. package/build/utils/permissions/MediaLibraryPermissions.js +122 -0
  605. package/build/utils/permissions/MediaLibraryPermissions.js.map +1 -0
  606. package/build/utils/permissions/galleryDisplayName.d.ts +8 -0
  607. package/build/utils/permissions/galleryDisplayName.d.ts.map +1 -0
  608. package/build/utils/permissions/galleryDisplayName.js +25 -0
  609. package/build/utils/permissions/galleryDisplayName.js.map +1 -0
  610. package/build/utils/storage/index.d.ts +3 -0
  611. package/build/utils/storage/index.d.ts.map +1 -0
  612. package/build/utils/storage/index.js +3 -0
  613. package/build/utils/storage/index.js.map +1 -0
  614. package/build/utils/storage/storage.d.ts +24 -0
  615. package/build/utils/storage/storage.d.ts.map +1 -0
  616. package/build/utils/storage/storage.js +85 -0
  617. package/build/utils/storage/storage.js.map +1 -0
  618. package/build/utils/storage/zip.d.ts +3 -0
  619. package/build/utils/storage/zip.d.ts.map +1 -0
  620. package/build/utils/storage/zip.js +14 -0
  621. package/build/utils/storage/zip.js.map +1 -0
  622. package/build/utils/timers/index.d.ts +3 -0
  623. package/build/utils/timers/index.d.ts.map +1 -0
  624. package/build/utils/timers/index.js +3 -0
  625. package/build/utils/timers/index.js.map +1 -0
  626. package/build/utils/timers/timers.d.ts +9 -0
  627. package/build/utils/timers/timers.d.ts.map +1 -0
  628. package/build/utils/timers/timers.js +105 -0
  629. package/build/utils/timers/timers.js.map +1 -0
  630. package/package.json +119 -0
  631. package/src/devtools.ts +13 -0
  632. package/src/engine.ts +173 -0
  633. package/src/facades/dev.ts +197 -0
  634. package/src/facades/display.ts +17 -0
  635. package/src/facades/displayMirror.ts +33 -0
  636. package/src/facades/gallery.ts +69 -0
  637. package/src/facades/glasses.ts +206 -0
  638. package/src/facades/glassesSettings.ts +56 -0
  639. package/src/facades/glassesWifi.ts +68 -0
  640. package/src/facades/miniapps.ts +55 -0
  641. package/src/facades/notifications.ts +15 -0
  642. package/src/facades/ota.ts +174 -0
  643. package/src/facades/pairing.ts +329 -0
  644. package/src/facades/permissions.ts +151 -0
  645. package/src/facades/phoneNotifications.ts +50 -0
  646. package/src/facades/reports.ts +185 -0
  647. package/src/facades/session.ts +55 -0
  648. package/src/facades/settings.ts +57 -0
  649. package/src/facades/speech.ts +38 -0
  650. package/src/index.ts +191 -0
  651. package/src/internal.ts +158 -0
  652. package/src/runtime/bootstrap.ts +118 -0
  653. package/src/runtime/config.ts +147 -0
  654. package/src/runtime/streamConfig.ts +34 -0
  655. package/src/services/AppRegistry.ts +1139 -0
  656. package/src/services/AudioCloudUplink.ts +34 -0
  657. package/src/services/AudioPlaybackService.ts +624 -0
  658. package/src/services/AutomaticReportResult.ts +48 -0
  659. package/src/services/BlobStore.ts +746 -0
  660. package/src/services/CaptionsTesterReportService.ts +107 -0
  661. package/src/services/CloudAudioSubscriptionSync.ts +41 -0
  662. package/src/services/CloudClientService.ts +668 -0
  663. package/src/services/CloudTranscriptE2EMetrics.ts +27 -0
  664. package/src/services/ConnectionCoordinator.ts +65 -0
  665. package/src/services/DevServerBridge.ts +332 -0
  666. package/src/services/DeviceEventRouter.ts +238 -0
  667. package/src/services/DeviceStoreHydration.ts +130 -0
  668. package/src/services/DisplayProcessor.ts +775 -0
  669. package/src/services/GlassesReadiness.ts +103 -0
  670. package/src/services/GlassesSettingsSync.ts +134 -0
  671. package/src/services/GlassesStatusProjection.ts +73 -0
  672. package/src/services/HeadingService.ts +98 -0
  673. package/src/services/LocalDisplayManager.ts +703 -0
  674. package/src/services/LocalMiniappRuntime.ts +4038 -0
  675. package/src/services/LocalSttFallbackCoordinator.ts +140 -0
  676. package/src/services/MentraJSCrashController.ts +189 -0
  677. package/src/services/MentraJSCrashloopReportService.ts +66 -0
  678. package/src/services/MentraJSLogPipeline.ts +166 -0
  679. package/src/services/MentraJSRouter.ts +557 -0
  680. package/src/services/MentraUIRouter.ts +244 -0
  681. package/src/services/MicStateCoordinator.ts +94 -0
  682. package/src/services/MiniappEngine.ts +143 -0
  683. package/src/services/MiniappLauncher.ts +340 -0
  684. package/src/services/MiniappRunningRegistry.ts +57 -0
  685. package/src/services/NavigationHandlers.ts +423 -0
  686. package/src/services/NavigationService.ts +731 -0
  687. package/src/services/NotificationsEmitter.ts +48 -0
  688. package/src/services/OfflineSpeechModelService.ts +168 -0
  689. package/src/services/OtaInstallCoordinator.ts +1205 -0
  690. package/src/services/OtaService.ts +83 -0
  691. package/src/services/OtaUpdateCheckService.ts +386 -0
  692. package/src/services/PairingIdentity.ts +154 -0
  693. package/src/services/PhoneLocationService.ts +122 -0
  694. package/src/services/PhoneNotificationsSync.ts +44 -0
  695. package/src/services/PhonePhotoCoordinator.ts +337 -0
  696. package/src/services/PhoneStreamCoordinator.ts +777 -0
  697. package/src/services/PhoneVideoCoordinator.ts +189 -0
  698. package/src/services/STTModelManager.ts +360 -0
  699. package/src/services/SceneRenderer.ts +292 -0
  700. package/src/services/StreamLifecycleController.ts +213 -0
  701. package/src/services/TTSModelManager.ts +466 -0
  702. package/src/services/WebviewBridge.ts +50 -0
  703. package/src/services/asg/GalleryMediaIntegrityReportService.ts +70 -0
  704. package/src/services/asg/asgCameraApi.ts +1204 -0
  705. package/src/services/asg/galleryMediaValidation.ts +183 -0
  706. package/src/services/asg/galleryNotices.ts +60 -0
  707. package/src/services/asg/gallerySettingsService.ts +65 -0
  708. package/src/services/asg/gallerySyncNotifications.ts +236 -0
  709. package/src/services/asg/gallerySyncService.ts +2167 -0
  710. package/src/services/asg/localStorageService.ts +497 -0
  711. package/src/services/asg/mediaProcessingQueue.ts +371 -0
  712. package/src/services/asgOtaVersionUrl.ts +41 -0
  713. package/src/services/blobPaths.ts +86 -0
  714. package/src/services/cloudStreamApi.ts +154 -0
  715. package/src/services/gallerySyncClock.ts +39 -0
  716. package/src/services/glassesClockSync.ts +115 -0
  717. package/src/services/manifestVersionGate.ts +43 -0
  718. package/src/services/mentraUiShim.ts +366 -0
  719. package/src/services/navigation/roadNameResolver.ts +112 -0
  720. package/src/services/navigation/routesApiCodec.ts +69 -0
  721. package/src/services/otaDisplayState.ts +115 -0
  722. package/src/services/otaInstallPolicy.ts +106 -0
  723. package/src/services/otaLegacyMapping.ts +71 -0
  724. package/src/services/slimStreamStatus.ts +28 -0
  725. package/src/stores/apps.ts +614 -0
  726. package/src/stores/bluetoothSettingKeys.ts +36 -0
  727. package/src/stores/cloudClientStatus.ts +37 -0
  728. package/src/stores/connection.ts +69 -0
  729. package/src/stores/core.ts +32 -0
  730. package/src/stores/display.ts +121 -0
  731. package/src/stores/gallerySync.ts +380 -0
  732. package/src/stores/glasses.ts +309 -0
  733. package/src/stores/settings.ts +993 -0
  734. package/src/types/applet.ts +112 -0
  735. package/src/types/asg.ts +51 -0
  736. package/src/types/capabilities/even-realities-g1.ts +67 -0
  737. package/src/types/capabilities/even-realities-g2.ts +88 -0
  738. package/src/types/capabilities/mentra-display.ts +75 -0
  739. package/src/types/capabilities/mentra-live.ts +103 -0
  740. package/src/types/capabilities/none.ts +76 -0
  741. package/src/types/capabilities/simulated-glasses.ts +76 -0
  742. package/src/types/capabilities/vuzix-z100.ts +64 -0
  743. package/src/types/enums.ts +43 -0
  744. package/src/types/hardware.ts +203 -0
  745. package/src/types/index.ts +37 -0
  746. package/src/utils/GlobalEventEmitter.ts +14 -0
  747. package/src/utils/cloudClient/RnUdpAdapter.ts +47 -0
  748. package/src/utils/cloudClient/cloudSecureStore.ts +28 -0
  749. package/src/utils/debouncedPatch.ts +28 -0
  750. package/src/utils/devLogging.ts +140 -0
  751. package/src/utils/devMiniappLaunch.ts +68 -0
  752. package/src/utils/diagnosticContext.ts +155 -0
  753. package/src/utils/display/composer/ColumnComposer.ts +285 -0
  754. package/src/utils/display/composer/index.ts +15 -0
  755. package/src/utils/display/helpers/DisplayHelpers.ts +413 -0
  756. package/src/utils/display/helpers/ScrollView.ts +337 -0
  757. package/src/utils/display/helpers/index.ts +14 -0
  758. package/src/utils/display/index.ts +273 -0
  759. package/src/utils/display/measurer/TextMeasurer.ts +346 -0
  760. package/src/utils/display/measurer/index.ts +21 -0
  761. package/src/utils/display/measurer/script-detection.ts +218 -0
  762. package/src/utils/display/profiles/g1.ts +236 -0
  763. package/src/utils/display/profiles/g2.ts +39 -0
  764. package/src/utils/display/profiles/index.ts +28 -0
  765. package/src/utils/display/profiles/nex.ts +166 -0
  766. package/src/utils/display/profiles/types.ts +132 -0
  767. package/src/utils/display/profiles/z100.ts +198 -0
  768. package/src/utils/display/scene/degrade.ts +80 -0
  769. package/src/utils/display/scene/differ.ts +128 -0
  770. package/src/utils/display/scene/index.ts +21 -0
  771. package/src/utils/display/scene/process.ts +214 -0
  772. package/src/utils/display/scene/store.ts +0 -0
  773. package/src/utils/display/scene/types.ts +0 -0
  774. package/src/utils/display/wrapper/TextWrapper.ts +546 -0
  775. package/src/utils/display/wrapper/index.ts +15 -0
  776. package/src/utils/display/wrapper/types.ts +102 -0
  777. package/src/utils/e2eMetrics.ts +30 -0
  778. package/src/utils/hardware/hardware.ts +166 -0
  779. package/src/utils/hardware/index.ts +1 -0
  780. package/src/utils/miniappGlobals.ts +260 -0
  781. package/src/utils/permissions/MediaLibraryPermissions.ts +130 -0
  782. package/src/utils/permissions/galleryDisplayName.ts +28 -0
  783. package/src/utils/storage/index.ts +2 -0
  784. package/src/utils/storage/storage.ts +101 -0
  785. package/src/utils/storage/zip.ts +13 -0
  786. package/src/utils/timers/index.ts +2 -0
  787. package/src/utils/timers/timers.ts +139 -0
@@ -0,0 +1,1139 @@
1
+ /**
2
+ * AppRegistry — on-disk install/uninstall registry for local miniapps.
3
+ *
4
+ * Owns the `Documents/lmas/<packageName>/<version>/` filesystem layout, the
5
+ * download/unzip pipeline, and the active-version pointer in MMKV. It does
6
+ * NOT touch the apps store directly — instead it notifies subscribers when
7
+ * the install set changes, so the host (mobile manager, OEM app) can refresh
8
+ * its own state.
9
+ *
10
+ * Public surface:
11
+ * - installFromUrl(url, opts?) install/replace a miniapp from a URL
12
+ * - installFromLocalZip(path, opts?) install/replace from a local zip
13
+ * - uninstall(packageName, version?) remove one or all versions
14
+ * - getInstalledMiniapps() ClientApp[] derived from disk
15
+ * - getActiveVersion(packageName) active version string for a package
16
+ * - getBundleDir / getMiniappManifest filesystem helpers used by hosts
17
+ * - subscribe(fn) register a refresh listener
18
+ */
19
+
20
+ import {Directory, Paths, File} from "expo-file-system"
21
+ import {unzip} from "react-native-zip-archive"
22
+ import semver from "semver"
23
+ import {AsyncResult, Result, result as Res} from "typesafe-ts"
24
+
25
+ import type {AppletPermission, AppPermissionType, AppletType, ClientApp, DeclaredAction} from "../types/applet"
26
+ import {HardwareRequirement, HardwareRequirementLevel, HardwareType} from "../types"
27
+ import {getConfigValues} from "../runtime/bootstrap"
28
+ import {storage} from "../utils/storage/storage"
29
+ import {printDirectory} from "../utils/storage/zip"
30
+ import {checkManifestVersions} from "./manifestVersionGate"
31
+ import {miniappRunningRegistry} from "./MiniappRunningRegistry"
32
+
33
+ const ALLOWED_PERMISSION_TYPES: ReadonlySet<AppPermissionType> = new Set<AppPermissionType>([
34
+ "MICROPHONE",
35
+ "CAMERA",
36
+ "CALENDAR",
37
+ "LOCATION",
38
+ "BACKGROUND_LOCATION",
39
+ "READ_NOTIFICATIONS",
40
+ "POST_NOTIFICATIONS",
41
+ ])
42
+
43
+ /**
44
+ * Normalize the `permissions` field from a miniapp.json manifest.
45
+ *
46
+ * New miniapps ship `[{type, required?, description?}]` objects. A few older
47
+ * installed bundles may have `["MICROPHONE", ...]` plain strings. Accept both.
48
+ */
49
+ export function normalizeManifestPermissions(
50
+ raw: Array<string | {type: string; required?: boolean; description?: string}> | undefined,
51
+ ): AppletPermission[] {
52
+ if (!Array.isArray(raw)) return []
53
+ const out: AppletPermission[] = []
54
+ for (const p of raw) {
55
+ if (typeof p === "string") {
56
+ if (ALLOWED_PERMISSION_TYPES.has(p as AppPermissionType)) {
57
+ out.push({type: p as AppPermissionType, required: true})
58
+ }
59
+ } else if (p && typeof p === "object" && typeof p.type === "string") {
60
+ if (ALLOWED_PERMISSION_TYPES.has(p.type as AppPermissionType)) {
61
+ out.push({
62
+ type: p.type as AppPermissionType,
63
+ ...(typeof p.required === "boolean" ? {required: p.required} : {}),
64
+ ...(typeof p.description === "string" ? {description: p.description} : {}),
65
+ })
66
+ }
67
+ }
68
+ }
69
+ return out
70
+ }
71
+
72
+ function normalizeManifestType(raw: unknown): AppletType {
73
+ return raw === "background" || raw === "system_dashboard" || raw === "standard" ? raw : "standard"
74
+ }
75
+
76
+ /**
77
+ * Normalize a manifest's `actions` into DeclaredAction[]. Defensive — keeps only
78
+ * well-formed `{id, description}` entries (installed/dev bundles may be
79
+ * malformed). Shared by installed (disk) and dev-sideload projection so both
80
+ * surface declared actions to session.miniapps.list + the invoke gate.
81
+ */
82
+ export function normalizeManifestActions(raw: unknown): DeclaredAction[] {
83
+ if (!Array.isArray(raw)) return []
84
+ const out: DeclaredAction[] = []
85
+ for (const a of raw as Array<{id?: unknown; description?: unknown; parameters?: unknown}>) {
86
+ if (a && typeof a.id === "string" && typeof a.description === "string") {
87
+ out.push({
88
+ id: a.id,
89
+ description: a.description,
90
+ ...(a.parameters && typeof a.parameters === "object"
91
+ ? {parameters: a.parameters as Record<string, unknown>}
92
+ : {}),
93
+ })
94
+ }
95
+ }
96
+ return out
97
+ }
98
+
99
+ /**
100
+ * Convert declared hardwareRequirements from a miniapp.json manifest into
101
+ * runtime `HardwareRequirement[]`, always appending `{EXIST, REQUIRED}` so
102
+ * launchers show "Glasses Required" when no glasses are connected.
103
+ *
104
+ * Malformed entries are dropped with a single warning per package so the
105
+ * rest of the manifest still works.
106
+ */
107
+ export function buildHardwareRequirements(
108
+ raw: Array<{type: string; level: string; description?: string}> | undefined,
109
+ packageName: string,
110
+ ): HardwareRequirement[] {
111
+ const out: HardwareRequirement[] = []
112
+ const validTypes = new Set(Object.values(HardwareType) as string[])
113
+ const validLevels = new Set(Object.values(HardwareRequirementLevel) as string[])
114
+
115
+ if (!Array.isArray(raw)) {
116
+ if (raw !== undefined) {
117
+ console.warn(`APP_REGISTRY: ${packageName} has invalid hardwareRequirements (not an array); treating as []`)
118
+ }
119
+ } else {
120
+ let warned = false
121
+ for (const r of raw) {
122
+ if (
123
+ !r ||
124
+ typeof r !== "object" ||
125
+ typeof r.type !== "string" ||
126
+ typeof r.level !== "string" ||
127
+ !validTypes.has(r.type) ||
128
+ !validLevels.has(r.level)
129
+ ) {
130
+ if (!warned) {
131
+ console.warn(
132
+ `APP_REGISTRY: ${packageName} has malformed hardwareRequirements entry; skipping invalid entries`,
133
+ r,
134
+ )
135
+ warned = true
136
+ }
137
+ continue
138
+ }
139
+ out.push({
140
+ type: r.type as HardwareType,
141
+ level: r.level as HardwareRequirementLevel,
142
+ ...(typeof r.description === "string" ? {description: r.description} : {}),
143
+ })
144
+ }
145
+ }
146
+
147
+ // Always require glasses to be connected for any local miniapp.
148
+ out.push({type: HardwareType.EXIST, level: HardwareRequirementLevel.REQUIRED})
149
+ return out
150
+ }
151
+
152
+ interface InstalledInfo {
153
+ name: string
154
+ logoUrl: string
155
+ }
156
+
157
+ interface InstalledLma {
158
+ packageName: string
159
+ versions: Record<string, InstalledInfo>
160
+ }
161
+
162
+ /**
163
+ * Download a miniapp zip from `url` into the cache and return its local path.
164
+ *
165
+ * `File.downloadFileAsync` is HTTP(S)-only, so this path is for remote bundles
166
+ * (dev server, store). Bundled-asset installs already have a local zip and
167
+ * should call {@link unpackMiniApp} directly.
168
+ */
169
+ async function downloadMiniAppZip(url: string): Promise<string> {
170
+ const downloadDir = new Directory(Paths.cache, "lma_downloads")
171
+ try {
172
+ if (!downloadDir.exists) {
173
+ downloadDir.create()
174
+ }
175
+ } catch (error) {
176
+ console.error("ZIP: Error creating download directory", error)
177
+ throw "CREATE_DOWNLOAD_DIR_FAILED"
178
+ }
179
+
180
+ // Pre-delete any cached file with the same name. Both `mentra-miniapp dev`
181
+ // and `mentra-miniapp release` serve their zip at /bundle.zip, so URLs
182
+ // collide on the cache filename. Without this delete, a stale dev-snapshot
183
+ // (containing the project source tree) gets unzipped instead of the
184
+ // release build → white screen because index.html points at TSX files.
185
+ const targetFileName = url.split("/").pop() ?? "bundle.zip"
186
+ const existingFile = new File(downloadDir, targetFileName)
187
+ if (existingFile.exists) {
188
+ try {
189
+ existingFile.delete()
190
+ } catch (e) {
191
+ console.warn("ZIP: failed to delete stale cached download:", e)
192
+ }
193
+ }
194
+
195
+ try {
196
+ const output = await File.downloadFileAsync(url, downloadDir)
197
+ return output.uri
198
+ } catch (error) {
199
+ console.error("ZIP: Error downloading zip file", error)
200
+ throw "DOWNLOAD_FAILED"
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Unpack a local miniapp zip and install it under
206
+ * `lmas/<packageName>/<version>/`.
207
+ *
208
+ * Zip layout: flat — files at root, `miniapp.json` at the top level. We're
209
+ * strict on shape so we fail loudly on malformed bundles.
210
+ *
211
+ * @param zipPath file:// URI of the zip on local disk.
212
+ * @param versionOverride override the manifest's version field. Used by the
213
+ * dev miniapp caching path which stamps `dev-<ms>`
214
+ * so multiple snapshots can coexist alongside
215
+ * semver-installed versions.
216
+ */
217
+ async function unpackMiniApp(
218
+ zipPath: string,
219
+ versionOverride?: string,
220
+ ): Promise<{packageName: string; version: string}> {
221
+ const unzipDir = new Directory(Paths.cache, "lma_unzip")
222
+ try {
223
+ if (unzipDir.exists) unzipDir.delete()
224
+ unzipDir.create()
225
+ } catch (error) {
226
+ console.error("ZIP: Error creating or deleting the unzip directory", error)
227
+ throw "CREATE_CACHE_DIR_FAILED"
228
+ }
229
+
230
+ try {
231
+ console.log("ZIP: unzipping", zipPath)
232
+ await unzip(zipPath, unzipDir.uri)
233
+ } catch (error) {
234
+ console.error("Error unzipping zip file", error)
235
+ throw "UNZIP_FAILED"
236
+ }
237
+
238
+ // Strict zip shape: miniapp.json at unzip root. No tolerance for an
239
+ // enclosing folder or app.json fallback — we own the dev-server emit
240
+ // format, so any deviation indicates a corrupt bundle.
241
+ const appDir = unzipDir
242
+ let packageName: string
243
+ let manifestVersion: string
244
+ try {
245
+ const miniappJsonFile = new File(appDir, "miniapp.json")
246
+ if (!miniappJsonFile.exists) throw new Error("miniapp.json missing at zip root")
247
+ const manifest = JSON.parse(miniappJsonFile.textSync())
248
+ if (!manifest.packageName) throw new Error("miniapp.json missing packageName")
249
+ if (!manifest.version) throw new Error("miniapp.json missing version")
250
+ packageName = manifest.packageName
251
+ manifestVersion = manifest.version
252
+ } catch (error) {
253
+ console.error("Error reading miniapp.json from zip:", error)
254
+ throw "READ_MANIFEST_FAILED"
255
+ }
256
+ const version = versionOverride ?? manifestVersion
257
+ console.log(`ZIP: installing ${packageName} as version ${version}`)
258
+
259
+ const basePackageDir = new Directory(Paths.document, "lmas", packageName)
260
+ try {
261
+ if (!basePackageDir.exists) {
262
+ basePackageDir.create({intermediates: true})
263
+ }
264
+ } catch (error) {
265
+ console.error("Error creating the base package directory", error)
266
+ throw "CREATE_PACKAGE_DIR_FAILED"
267
+ }
268
+
269
+ const versionDir = new Directory(basePackageDir, version)
270
+ try {
271
+ if (!versionDir.exists) {
272
+ versionDir.create()
273
+ } else {
274
+ versionDir.delete()
275
+ versionDir.create()
276
+ }
277
+ } catch (error) {
278
+ console.error("Error creating the version directory", error)
279
+ throw "CREATE_VERSION_DIR_FAILED"
280
+ }
281
+
282
+ try {
283
+ const contents = appDir.list()
284
+ for (const item of contents) {
285
+ item.move(versionDir)
286
+ }
287
+ } catch (error) {
288
+ console.error("Error moving the contents of the folder to the destination directory", error)
289
+ throw "INSTALL_CONTENTS_FAILED"
290
+ }
291
+
292
+ console.log("ZIP: local mini app installed at", versionDir.uri)
293
+ printDirectory(versionDir, 2)
294
+ return {packageName, version}
295
+ }
296
+
297
+ /**
298
+ * Download a miniapp zip from `url`, unpack it, and install it under
299
+ * `lmas/<packageName>/<version>/`. Thin composition of
300
+ * {@link downloadMiniAppZip} + {@link unpackMiniApp} for remote bundles.
301
+ *
302
+ * @param versionOverride override the manifest's version field. Used by the
303
+ * dev miniapp caching path which stamps `dev-<ms>`
304
+ * so multiple snapshots can coexist alongside
305
+ * semver-installed versions.
306
+ */
307
+ async function downloadAndInstallMiniApp(
308
+ url: string,
309
+ versionOverride?: string,
310
+ ): Promise<{packageName: string; version: string}> {
311
+ const downloadedZipPath = await downloadMiniAppZip(url)
312
+ console.log("ZIP: done downloading, starting unzip")
313
+ return unpackMiniApp(downloadedZipPath, versionOverride)
314
+ }
315
+
316
+ type Listener = () => void
317
+
318
+ class AppRegistry {
319
+ private cachedApps: ClientApp[] = []
320
+ // Offline apps live in a separate layer so they survive the disk-rebuild
321
+ // path in getInstalledMiniapps (which reassigns cachedApps).
322
+ private offlineApps: ClientApp[] = []
323
+ /** Package names whose start() requires the on-device STT model (host-declared). */
324
+ private sttModelRequired = new Set<string>()
325
+ private refreshNeeded: boolean = true
326
+ private listeners = new Set<Listener>()
327
+
328
+ private static instance: AppRegistry | null = null
329
+
330
+ private constructor() {}
331
+
332
+ public static getInstance(): AppRegistry {
333
+ if (!AppRegistry.instance) {
334
+ AppRegistry.instance = new AppRegistry()
335
+ }
336
+ return AppRegistry.instance
337
+ }
338
+
339
+ /** Subscribe to install/uninstall events. Listener fires after refreshNeeded flips. */
340
+ public subscribe(fn: Listener): () => void {
341
+ this.listeners.add(fn)
342
+ return () => {
343
+ this.listeners.delete(fn)
344
+ }
345
+ }
346
+
347
+ private notify(): void {
348
+ for (const fn of this.listeners) {
349
+ try {
350
+ fn()
351
+ } catch (e) {
352
+ console.warn("AppRegistry: listener threw", e)
353
+ }
354
+ }
355
+ }
356
+
357
+ /**
358
+ * On-disk path for a given miniapp bundle version.
359
+ */
360
+ public getBundleDir(packageName: string, version: string): string {
361
+ const bundleDir = new Directory(Paths.document, "lmas", packageName, version)
362
+ return bundleDir.uri
363
+ }
364
+
365
+ /**
366
+ * Resolve the two-layer entry paths for an installed miniapp version.
367
+ * Returns absolute file:// URIs for `background` and (when present) `ui`.
368
+ *
369
+ * Legacy single-layer bundles (no `entry` object in manifest) fall back
370
+ * to `index.html` discovery so the WebView host keeps working unchanged.
371
+ * Two-layer bundles ship `entry.background` and optional `entry.ui`
372
+ * paths relative to the bundle root.
373
+ *
374
+ * Returns null if neither shape resolves to existing files on disk.
375
+ */
376
+ public getMiniappEntryPaths(
377
+ packageName: string,
378
+ version: string,
379
+ ): {background: string | null; ui: string | null} | null {
380
+ const manifest = this.getMiniappManifest(packageName, version) as {
381
+ entry?: {background?: string; ui?: string}
382
+ } | null
383
+ const bundleDir = this.getBundleDir(packageName, version)
384
+ const resolve = (rel: string): string | null => {
385
+ const trimmed = rel.replace(/^\.?\/+/, "")
386
+ const file = new File(bundleDir, trimmed)
387
+ return file.exists ? file.uri : null
388
+ }
389
+ if (manifest?.entry) {
390
+ console.log("manifest.entry", manifest.entry)
391
+ const bg = manifest.entry.background ? resolve(manifest.entry.background) : null
392
+ console.log("bg", bg)
393
+ const ui = manifest.entry.ui ? resolve(manifest.entry.ui) : null
394
+ console.log("ui", ui)
395
+ if (bg || ui) {
396
+ return {background: bg, ui: ui}
397
+ }
398
+ }
399
+ // Legacy single-bundle fallback — `index.html` at the bundle root.
400
+ const legacy = new File(new Directory(bundleDir.replace(/^file:\/\//, "")), "index.html")
401
+ return {
402
+ background: null,
403
+ ui: legacy.exists ? legacy.uri : null,
404
+ }
405
+ }
406
+
407
+ /**
408
+ * Verify a manifest declares an SDK / host version range compatible
409
+ * with the current host. Delegates to the pure
410
+ * {@link checkManifestVersions} helper — same shape, no React Native
411
+ * imports, unit-testable. Manifests missing either field pass
412
+ * through unchanged (legacy single-layer path).
413
+ */
414
+ public checkManifestVersions(
415
+ manifest: {sdkVersion?: string; minHostVersion?: string} | null,
416
+ options: {hostVersion: string; supportedSdkRange: string},
417
+ ): {ok: true} | {ok: false; reason: string} {
418
+ return checkManifestVersions(manifest, options)
419
+ }
420
+
421
+ /**
422
+ * Read and parse the miniapp manifest (miniapp.json with app.json fallback)
423
+ * from a given bundle directory.
424
+ */
425
+ public getMiniappManifest(packageName: string, version: string): any {
426
+ const bundleDir = new Directory(Paths.document, "lmas", packageName, version)
427
+ try {
428
+ const miniappJsonFile = new File(bundleDir, "miniapp.json")
429
+ if (miniappJsonFile.exists) {
430
+ return JSON.parse(miniappJsonFile.textSync())
431
+ }
432
+ } catch (e) {
433
+ console.warn("AppRegistry: Error reading miniapp.json, trying app.json fallback", e)
434
+ }
435
+ try {
436
+ const appJsonFile = new File(bundleDir, "app.json")
437
+ if (appJsonFile.exists) {
438
+ return JSON.parse(appJsonFile.textSync())
439
+ }
440
+ } catch (e) {
441
+ console.warn("AppRegistry: Error reading app.json fallback", e)
442
+ }
443
+ return null
444
+ }
445
+
446
+ /**
447
+ * Download and install a miniapp bundle from a URL. The URL must serve a
448
+ * zip whose root contains `miniapp.json` plus the bundle entry files.
449
+ *
450
+ * @param opts.versionOverride if set, install under this version instead
451
+ * of `manifest.version`. The dev caching path uses `dev-<ms>` so multiple
452
+ * snapshots can coexist alongside semver-installed versions.
453
+ */
454
+ public installFromUrl(url: string, opts?: {versionOverride?: string}): AsyncResult<void, Error> {
455
+ return Res.try_async(async () => {
456
+ const {packageName, version} = await downloadAndInstallMiniApp(url, opts?.versionOverride)
457
+ console.log("APP_REGISTRY: Downloaded and installed mini app")
458
+ this.finalizeInstall(packageName, version)
459
+ })
460
+ }
461
+
462
+ /**
463
+ * Install a miniapp from a zip already on local disk (e.g. a bundled asset
464
+ * copied into cache). Skips the HTTP download path that `installFromUrl`
465
+ * uses — `File.downloadFileAsync` is HTTP(S)-only and rejects file:// URIs.
466
+ *
467
+ * @param zipPath file:// URI of the local zip.
468
+ */
469
+ public installFromLocalZip(
470
+ zipPath: string,
471
+ opts?: {versionOverride?: string},
472
+ ): AsyncResult<{packageName: string; version: string}, Error> {
473
+ return Res.try_async(async () => {
474
+ const {packageName, version} = await unpackMiniApp(zipPath, opts?.versionOverride)
475
+ console.log("APP_REGISTRY: Installed mini app from local zip")
476
+ this.finalizeInstall(packageName, version)
477
+ return {packageName, version}
478
+ })
479
+ }
480
+
481
+ /**
482
+ * Post-install bookkeeping shared by every install path: clear stale dev
483
+ * artifacts on release installs, point the active-version at the just-
484
+ * installed bundle, and notify subscribers to refresh.
485
+ */
486
+ private finalizeInstall(packageName: string, version: string): void {
487
+ // If this is a release install (semver, not dev-*) of a package that
488
+ // currently has dev-* snapshots, clear the dev state so the swap to
489
+ // "released" is clean. Otherwise the dev version would keep winning
490
+ // getActiveVersion's dev-precedence rule and the just-installed
491
+ // release wouldn't run.
492
+ const isDevInstall = version.startsWith("dev-")
493
+ if (!isDevInstall) {
494
+ this.clearDevArtifacts(packageName)
495
+ }
496
+
497
+ this.setActiveVersion(packageName, version)
498
+ this.refreshNeeded = true
499
+ this.notify()
500
+ }
501
+
502
+ public installFromJsonUrl(baseUrl: string): AsyncResult<{packageName: string; version: string; name: string}, Error> {
503
+ return Res.try_async(async () => {
504
+ const trimmed = baseUrl.replace(/\/$/, "")
505
+
506
+ const manifestRes = await fetch(`${trimmed}/miniapp.json`)
507
+ if (!manifestRes.ok) {
508
+ throw new Error(`Failed to fetch miniapp.json: ${manifestRes.status}`)
509
+ }
510
+ const manifest = (await manifestRes.json()) as Record<string, unknown>
511
+ const packageName = manifest.packageName as string | undefined
512
+ const version = manifest.version as string | undefined
513
+ const name = (manifest.name as string | undefined) ?? packageName ?? "Mini app"
514
+ if (!packageName) throw new Error("miniapp.json missing packageName")
515
+ if (!version) throw new Error("miniapp.json missing version")
516
+
517
+ const installRes = await appRegistry.installFromUrl(`${trimmed}/bundle.zip`)
518
+ if (installRes.is_error()) throw installRes.error
519
+
520
+ return {packageName, version, name}
521
+ })
522
+ }
523
+
524
+ /**
525
+ * Drop every dev-* version directory for a package plus ALL dev MMKV keys
526
+ * (URL/port/reachability + the home-tile metadata record). Called on a
527
+ * release install (dev → released transition) and on uninstall, so a dev
528
+ * package leaves nothing behind that `projectDevApps` could re-surface.
529
+ */
530
+ private clearDevArtifacts(packageName: string): void {
531
+ try {
532
+ const pkgDir = new Directory(Paths.document, "lmas", packageName)
533
+ if (pkgDir.exists) {
534
+ for (const item of pkgDir.list()) {
535
+ if (item instanceof Directory && item.name.startsWith("dev-")) {
536
+ try {
537
+ item.delete()
538
+ } catch (e) {
539
+ console.warn(`APP_REGISTRY: failed to delete ${item.name}:`, e)
540
+ }
541
+ }
542
+ }
543
+ }
544
+ } catch (e) {
545
+ console.warn(`APP_REGISTRY: clearDevArtifacts dir scan failed for ${packageName}:`, e)
546
+ }
547
+ storage.remove(`${packageName}_dev_url`)
548
+ storage.remove(`${packageName}_dev_port`)
549
+ storage.remove(`${packageName}_dev_last_reachable`)
550
+ // Drop the single dev slot's home-tile metadata + dev URL/port keys (all stored under
551
+ // DEV_APP_PACKAGE_NAME, not `packageName`). Dev miniapps load over HTTP and aren't on disk,
552
+ // so without this the projected tile would reappear on the next getInstalledMiniapps() refresh.
553
+ //
554
+ // Only do this when we're actually touching the dev slot: either the dev package itself, or the
555
+ // real manifest package currently occupying the slot. Otherwise a release install/uninstall of
556
+ // an UNRELATED package would wipe the active dev tile.
557
+ if (packageName === DEV_APP_PACKAGE_NAME || packageName === getDevAppSourcePackage()) {
558
+ unregisterDevApp()
559
+ }
560
+ }
561
+
562
+ /**
563
+ * Garbage-collect older `dev-*` version directories for this package,
564
+ * keeping the latest `keep` (by lexicographic sort, which matches
565
+ * timestamp ordering since dev-<ms> is zero-padded).
566
+ *
567
+ * Only touches `dev-*` versions; semver-installed versions are left alone.
568
+ */
569
+ public gcDevVersions(packageName: string, keep: number): void {
570
+ try {
571
+ const pkgDir = new Directory(Paths.document, "lmas", packageName)
572
+ if (!pkgDir.exists) return
573
+ const dirs = pkgDir
574
+ .list()
575
+ .filter((d): d is Directory => d instanceof Directory && d.name.startsWith("dev-"))
576
+ .sort((a, b) => (a.name < b.name ? 1 : -1))
577
+ for (let i = keep; i < dirs.length; i++) {
578
+ try {
579
+ dirs[i].delete()
580
+ } catch (e) {
581
+ console.warn(`APP_REGISTRY: failed to delete ${dirs[i].name}:`, e)
582
+ }
583
+ }
584
+ if (dirs.length > keep) this.refreshNeeded = true
585
+ } catch (e) {
586
+ console.warn(`APP_REGISTRY: gcDevVersions error for ${packageName}:`, e)
587
+ }
588
+ }
589
+
590
+ public uninstall(packageName: string, version?: string): AsyncResult<void, Error> {
591
+ return Res.try_async(async () => {
592
+ if (version) {
593
+ const lmaDir = new Directory(Paths.document, "lmas", packageName, version)
594
+ // Guard exists: a dev miniapp loads over HTTP and has no on-disk dir,
595
+ // so an unconditional delete() would throw and abort the cleanup below.
596
+ if (lmaDir.exists) lmaDir.delete()
597
+ console.log("APP_REGISTRY: Uninstalled mini app version", version)
598
+ const packageDir = new Directory(Paths.document, "lmas", packageName)
599
+ if (packageDir.exists && packageDir.list().length === 0) {
600
+ packageDir.delete()
601
+ }
602
+ } else {
603
+ const packageDir = new Directory(Paths.document, "lmas", packageName)
604
+ if (packageDir.exists) {
605
+ packageDir.delete()
606
+ }
607
+ console.log("APP_REGISTRY: Uninstalled all versions of mini app", packageName)
608
+ }
609
+ // Always clear dev artifacts: for HTTP-direct dev miniapps the tile is
610
+ // backed by storage records (_dev_meta + dev_apps_index), not the disk
611
+ // dir, so without this the projected tile reappears on the next refresh.
612
+ this.clearDevArtifacts(packageName)
613
+ this.refreshNeeded = true
614
+ this.notify()
615
+ })
616
+ }
617
+
618
+ public getPackageNames(): string[] {
619
+ try {
620
+ const lmasDir = new Directory(Paths.document, "lmas")
621
+ if (!lmasDir.exists) return []
622
+ let lmas = lmasDir.list()
623
+ lmas = lmas.filter((lma): lma is Directory => lma instanceof Directory && lma.list().length > 0)
624
+ return lmas.map((lma) => lma.name)
625
+ } catch (error) {
626
+ console.error("APP_REGISTRY: Error getting locally installed package names", error)
627
+ return []
628
+ }
629
+ }
630
+
631
+ public getInstalledVersions(packageName: string): string[] {
632
+ try {
633
+ const lmaDir = new Directory(Paths.document, "lmas", packageName)
634
+ // Not installed yet is an expected state (e.g. preinstall sync probing
635
+ // versions before first install) — return [] without the error noise.
636
+ if (!lmaDir.exists) {
637
+ return []
638
+ }
639
+ const lma = lmaDir.list()
640
+ return lma.map((lma) => lma.name)
641
+ } catch (error) {
642
+ console.error("APP_REGISTRY: Error getting local applet versions", error)
643
+ return []
644
+ }
645
+ }
646
+
647
+ public async getActiveVersion(packageName: string): Promise<string> {
648
+ let versions = this.getInstalledVersions(packageName)
649
+ // Treat MMKV as a hint, not authority. A stored version may have been
650
+ // GC'd off disk without this pointer being updated.
651
+ let res = storage.load<string>(`${packageName}_active_version`)
652
+ if (res.is_ok() && versions.includes(res.value)) {
653
+ return res.value
654
+ }
655
+ // Dev versions take precedence over semver-installed versions.
656
+ const devVersions = versions
657
+ .filter((v) => v.startsWith("dev-"))
658
+ .sort()
659
+ .reverse()
660
+ if (devVersions.length > 0) {
661
+ this.setActiveVersion(packageName, devVersions[0])
662
+ return devVersions[0]
663
+ }
664
+ versions = versions.filter((v) => semver.valid(v))
665
+ versions.sort((a, b) => semver.rcompare(a, b))
666
+ this.setActiveVersion(packageName, versions[0])
667
+ return versions[0]
668
+ }
669
+
670
+ public setActiveVersion(packageName: string, version: string): Result<void, Error> {
671
+ return storage.save(`${packageName}_active_version`, version)
672
+ }
673
+
674
+ public getMetadata(packageName: string, version: string): InstalledInfo {
675
+ try {
676
+ const lmaDir = new Directory(Paths.document, "lmas", packageName, version)
677
+ const miniappJsonFile = new File(lmaDir, "miniapp.json")
678
+ const manifest = JSON.parse(miniappJsonFile.textSync())
679
+ const logoUrl = new File(lmaDir, "icon.png").uri
680
+ return {name: manifest.name, logoUrl: logoUrl}
681
+ } catch (error) {
682
+ console.error("APP_REGISTRY: Error getting local miniapp metadata", error)
683
+ return {name: "error", logoUrl: ""}
684
+ }
685
+ }
686
+
687
+ public getInstalledInfo(): InstalledLma[] {
688
+ const packageNames = this.getPackageNames()
689
+ const out: InstalledLma[] = []
690
+ for (const packageName of packageNames) {
691
+ const versionStrings = this.getInstalledVersions(packageName)
692
+ const installedVersion: InstalledLma = {packageName, versions: {}}
693
+ for (const versionString of versionStrings) {
694
+ installedVersion.versions[versionString] = this.getMetadata(packageName, versionString)
695
+ }
696
+ out.push(installedVersion)
697
+ }
698
+ return out
699
+ }
700
+
701
+ /**
702
+ * Read the lmas/ tree and return one ClientApp per installed package,
703
+ * picking each package's active version. The store/host overlays runtime
704
+ * state (loading, hidden, compatibility) on top of these.
705
+ *
706
+ * `running` reflects MiniappHost mount state via miniappRunningRegistry.
707
+ */
708
+ /**
709
+ * Merge disk-derived apps with the projected dev + offline layers,
710
+ * de-duping by packageName. A real on-disk install (or offline app) wins
711
+ * over a dev tile of the same package — a dev record is just a launcher
712
+ * stub that an actual install supersedes.
713
+ */
714
+ private mergeProjectedApps(diskApps: ClientApp[]): ClientApp[] {
715
+ const seen = new Set(diskApps.map((a) => a.packageName))
716
+ const offline = this.projectOfflineApps()
717
+ for (const a of offline) seen.add(a.packageName)
718
+ const dev = this.projectDevApps().filter((a) => !seen.has(a.packageName))
719
+ return [...diskApps, ...dev, ...offline]
720
+ }
721
+
722
+ public async getInstalledMiniapps(): Promise<ClientApp[]> {
723
+ if (!this.refreshNeeded && this.cachedApps.length > 0) {
724
+ // Cache hit: re-project running from the registry. The cached array
725
+ // IS the disk-derived truth; running comes from the mount registry.
726
+ return this.mergeProjectedApps(
727
+ this.cachedApps.map((a) => ({
728
+ ...a,
729
+ running: miniappRunningRegistry.has(a.packageName),
730
+ })),
731
+ )
732
+ }
733
+
734
+ try {
735
+ const installedInfo = this.getInstalledInfo()
736
+ const out: ClientApp[] = []
737
+ for (const lmaInfo of installedInfo) {
738
+ const versionString = await this.getActiveVersion(lmaInfo.packageName)
739
+ const versionInfo = lmaInfo.versions[versionString]
740
+
741
+ const manifest = this.getMiniappManifest(lmaInfo.packageName, versionString) as {
742
+ permissions?: Array<string | {type: string; required?: boolean; description?: string}>
743
+ hardwareRequirements?: Array<{type: string; level: string; description?: string}>
744
+ type?: string
745
+ actions?: Array<{id?: unknown; description?: unknown; parameters?: unknown}>
746
+ } | null
747
+
748
+ const permissions = normalizeManifestPermissions(manifest?.permissions)
749
+ const hardwareRequirements = buildHardwareRequirements(manifest?.hardwareRequirements, lmaInfo.packageName)
750
+ const appType = normalizeManifestType(manifest?.type)
751
+
752
+ // Declared actions (for session.miniapps.list + invoke gating).
753
+ const actions = normalizeManifestActions(manifest?.actions)
754
+
755
+ // Dev miniapps live in the same lmas/ tree as installed ones, but
756
+ // their version directory name starts with "dev-".
757
+ const isMiniappDev = versionString.startsWith("dev-")
758
+ let devUrl: string | undefined
759
+ if (isMiniappDev) {
760
+ const devUrlRes = storage.load<string>(`${lmaInfo.packageName}_dev_url`)
761
+ if (devUrlRes.is_ok()) devUrl = devUrlRes.value
762
+ }
763
+
764
+ out.push({
765
+ packageName: lmaInfo.packageName,
766
+ version: versionString,
767
+ running: miniappRunningRegistry.has(lmaInfo.packageName),
768
+ local: true,
769
+ healthy: true,
770
+ loading: false,
771
+ offline: false,
772
+ hidden: false,
773
+ offlineRoute: "",
774
+ name: versionInfo.name,
775
+ webviewUrl: "",
776
+ logoUrl: versionInfo.logoUrl,
777
+ type: appType,
778
+ permissions,
779
+ hardwareRequirements,
780
+ // Always project actions (even []) so the invoke gate can enforce
781
+ // declared-action membership unconditionally — an app with no declared
782
+ // actions must reject every invoke, not bypass the check.
783
+ actions,
784
+ ...(isMiniappDev ? {isMiniappDev: true} : {}),
785
+ ...(devUrl ? {devUrl} : {}),
786
+ onStart: () => saveLocalAppRunningState(lmaInfo.packageName, true),
787
+ onStop: () => saveLocalAppRunningState(lmaInfo.packageName, false),
788
+ })
789
+ }
790
+
791
+ this.cachedApps = out
792
+ this.refreshNeeded = false
793
+ return this.mergeProjectedApps(this.cachedApps)
794
+ } catch (error) {
795
+ console.error("APP_REGISTRY: Error getting local applets", error)
796
+ return this.mergeProjectedApps(
797
+ this.cachedApps.map((a) => ({
798
+ ...a,
799
+ running: miniappRunningRegistry.has(a.packageName),
800
+ })),
801
+ )
802
+ }
803
+ }
804
+
805
+ /** Force the next getInstalledMiniapps() to re-derive from disk + records. */
806
+ public markRefreshNeeded(): void {
807
+ this.refreshNeeded = true
808
+ this.notify()
809
+ }
810
+
811
+ /**
812
+ * Project persisted dev-app metadata records into ClientApp tiles. Dev
813
+ * miniapps aren't installed to disk (they load over HTTP), so they don't
814
+ * appear in the `lmas/` scan — this surfaces them on the home screen so
815
+ * they're re-launchable without re-scanning the QR.
816
+ */
817
+ private projectDevApps(): ClientApp[] {
818
+ return getDevAppRecords().map((rec) => {
819
+ const permissions = normalizeManifestPermissions(rec.permissions)
820
+ const hardwareRequirements = buildHardwareRequirements(rec.hardwareRequirements, rec.packageName)
821
+ return {
822
+ packageName: rec.packageName,
823
+ version: undefined,
824
+ running: miniappRunningRegistry.has(rec.packageName),
825
+ local: true,
826
+ healthy: true,
827
+ loading: false,
828
+ offline: false,
829
+ hidden: false,
830
+ offlineRoute: "",
831
+ name: rec.name,
832
+ webviewUrl: "",
833
+ logoUrl: rec.iconUrl,
834
+ type: normalizeManifestType(rec.type),
835
+ permissions,
836
+ hardwareRequirements,
837
+ actions: normalizeManifestActions(rec.actions),
838
+ isMiniappDev: true,
839
+ devUrl: rec.devUrl,
840
+ devPort: rec.devPort,
841
+ onStart: () => saveLocalAppRunningState(rec.packageName, true),
842
+ onStop: () => saveLocalAppRunningState(rec.packageName, false),
843
+ }
844
+ })
845
+ }
846
+
847
+ private projectOfflineApps(): ClientApp[] {
848
+ // Offline apps don't go through miniappRunningRegistry (that's for
849
+ // MiniappHost-mounted webviews). Their running flag is persisted to
850
+ // MMKV by saveLocalAppRunningState — read it back here so refreshes
851
+ // don't blow away the active flag.
852
+ return this.offlineApps.map((a) => {
853
+ const running = getLocalAppRunningState(a.packageName)
854
+ const screenshot = getLocalAppScreenshot(a.packageName)
855
+
856
+ return {...a, running, screenshot}
857
+ })
858
+ }
859
+
860
+ // Register an offline (locally-routed) app. Survives disk rebuilds.
861
+ public installOfflineApp(app: ClientApp, opts?: {requiresLocalSttModel?: boolean}): void {
862
+ if (opts?.requiresLocalSttModel) {
863
+ this.sttModelRequired.add(app.packageName)
864
+ }
865
+ this.offlineApps.push({
866
+ ...app,
867
+ onStart: () => saveLocalAppRunningState(app.packageName, true),
868
+ onStop: () => saveLocalAppRunningState(app.packageName, false),
869
+ })
870
+ this.refreshNeeded = true
871
+ this.notify()
872
+ }
873
+
874
+ /**
875
+ * Registered as needing the on-device STT model before it can start (the
876
+ * host declares this per offline app; the apps store gates start() on it).
877
+ */
878
+ public requiresLocalSttModel(packageName: string): boolean {
879
+ return this.sttModelRequired.has(packageName)
880
+ }
881
+
882
+ public getMiniappHtml(packageName: string, version: string): Result<string, Error> {
883
+ return Res.try(() => {
884
+ const lmaDir = new Directory(Paths.document, "lmas", packageName, version)
885
+ const htmlFile = new File(lmaDir, "index.html")
886
+ return htmlFile.textSync()
887
+ })
888
+ }
889
+ }
890
+
891
+ /**
892
+ * Persist the running flag for a local miniapp (read on next cold boot so
893
+ * autostart picks the right set of apps). Exported for hosts that want to
894
+ * track running state independently.
895
+ */
896
+ export function saveLocalAppRunningState(packageName: string, status: boolean): void {
897
+ storage.save(`${packageName}_running`, status)
898
+ }
899
+
900
+ export function getLocalAppRunningState(packageName: string): boolean {
901
+ const res = storage.load<boolean>(`${packageName}_running`)
902
+ if (res.is_ok()) return res.value
903
+ return false
904
+ }
905
+
906
+ export function getLocalAppScreenshot(packageName: string): string | undefined {
907
+ const key = `${packageName}_screenshot`
908
+ const res = storage.load<string>(key)
909
+ if (res.is_error()) return undefined
910
+
911
+ const uri = res.value
912
+ if (uri.startsWith("file://")) {
913
+ try {
914
+ if (!new File(uri).exists) {
915
+ storage.remove(key)
916
+ return undefined
917
+ }
918
+ } catch {
919
+ storage.remove(key)
920
+ return undefined
921
+ }
922
+ }
923
+
924
+ return uri
925
+ }
926
+
927
+ /**
928
+ * Persisted metadata for a dev miniapp's home tile.
929
+ *
930
+ * Dev miniapps load directly off the dev server over HTTP and are NOT
931
+ * installed into `lmas/`, so the disk scan in `getInstalledMiniapps` can't
932
+ * see them. We persist a tiny record at scan / dev-URL-entry time so the
933
+ * tile survives across app launches and is re-launchable without re-scanning.
934
+ * `permissions` / `hardwareRequirements` are snapshotted from the manifest so
935
+ * the home-screen permission gate has data without a disk bundle.
936
+ */
937
+ export interface DevAppRecord {
938
+ packageName: string
939
+ name: string
940
+ iconUrl: string
941
+ devUrl: string
942
+ devPort?: number
943
+ type?: AppletType
944
+ permissions?: Array<string | {type: string; required?: boolean; description?: string}>
945
+ hardwareRequirements?: Array<{type: string; level: string; description?: string}>
946
+ /** Manifest-declared actions — so dev-sideloaded miniapps can be invoked too. */
947
+ actions?: Array<{id?: unknown; description?: unknown; parameters?: unknown}>
948
+ /**
949
+ * The dev miniapp's real manifest package name. `packageName` is overwritten to
950
+ * {@link DEV_APP_PACKAGE_NAME} so the launch chain routes consistently, so this field
951
+ * preserves the original so install/uninstall of OTHER packages don't wipe the dev slot.
952
+ */
953
+ sourcePackageName?: string
954
+ /**
955
+ * Short-lived Core-verifiable proof emitted by `mentra dev`. This lets the
956
+ * single `com.dev` slot request auto-auth for the real package without
957
+ * letting arbitrary dev URLs claim any package name.
958
+ */
959
+ devAttestation?: string
960
+ }
961
+
962
+ const DEV_APPS_INDEX_KEY = "dev_apps_index"
963
+
964
+ function configuredDevHost(): string | undefined {
965
+ // Explicit escape hatch first; otherwise the host-injected Metro host (the
966
+ // address this dev bundle was served from — always current for the network
967
+ // the phone is on). Deliberately NOT the EXPO_PUBLIC_CLOUD_* URLs: those are
968
+ // cloud endpoints, a different machine entirely from the laptop running the
969
+ // miniapp dev server, and rewriting a dev URL to a cloud host would break it.
970
+ const explicit = process.env.EXPO_PUBLIC_LOCAL_MINIAPP_HOST
971
+ if (explicit) {
972
+ try {
973
+ return new URL(explicit).hostname
974
+ } catch {
975
+ if (/^[\w.-]+$/.test(explicit)) return explicit
976
+ }
977
+ }
978
+ return getConfigValues().devServerHost?.()
979
+ }
980
+
981
+ function isPrivateLanHost(hostname: string): boolean {
982
+ return (
983
+ hostname === "localhost" ||
984
+ hostname.startsWith("192.168.") ||
985
+ hostname.startsWith("10.") ||
986
+ /^172\.(1[6-9]|2\d|3[0-1])\./.test(hostname)
987
+ )
988
+ }
989
+
990
+ function rewriteStaleDevUrl(value: string): string {
991
+ if (!__DEV__) return value
992
+ const host = configuredDevHost()
993
+ if (!host) return value
994
+
995
+ try {
996
+ const url = new URL(value)
997
+ if (url.hostname === host || !isPrivateLanHost(url.hostname)) return value
998
+ url.hostname = host
999
+ return url.toString().replace(/\/$/, "")
1000
+ } catch {
1001
+ return value
1002
+ }
1003
+ }
1004
+
1005
+ function normalizeDevAppRecord(record: DevAppRecord): DevAppRecord {
1006
+ const devUrl = rewriteStaleDevUrl(record.devUrl)
1007
+ const iconUrl = rewriteStaleDevUrl(record.iconUrl)
1008
+ return devUrl === record.devUrl && iconUrl === record.iconUrl ? record : {...record, devUrl, iconUrl}
1009
+ }
1010
+
1011
+ /**
1012
+ * The one and only package name a dev miniapp is registered under.
1013
+ *
1014
+ * There is a SINGLE dev slot: scanning a new QR (or entering a new dev URL)
1015
+ * replaces the previous dev app rather than adding a second tile. Because the
1016
+ * whole launch chain — JSContext registration, UI-router binding,
1017
+ * setForeground, dev_url/dev_port storage keys, respawn-bg lookup — keys on
1018
+ * this package name, every consumer MUST use `DEV_APP_PACKAGE_NAME` (not the
1019
+ * manifest's real packageName) so messages route consistently. Mixing the two
1020
+ * was the cause of the "CONNECT_ACK timeout" — the tile said `com.dev` while
1021
+ * the dev URL/port and foreground target used the manifest name.
1022
+ */
1023
+ export const DEV_APP_PACKAGE_NAME = "com.dev"
1024
+ export const DEV_APP_NAME = "Dev"
1025
+
1026
+ /**
1027
+ * Register (or replace) THE dev miniapp. Persists the home-tile metadata AND
1028
+ * the dev_url/dev_port keyed on {@link DEV_APP_PACKAGE_NAME}, so this function
1029
+ * is the single source of truth for the dev slot — callers must not write the
1030
+ * `*_dev_url` / `*_dev_port` keys under the manifest's real package name.
1031
+ *
1032
+ * Callers pass the manifest's REAL packageName/name. Only the packageName is
1033
+ * forced to {@link DEV_APP_PACKAGE_NAME} so the home tile and launch chain key
1034
+ * on the single dev slot (the real package survives in `sourcePackageName` for
1035
+ * clearDevArtifacts). The name + icon are kept as-is so the home tile reflects
1036
+ * the actual dev miniapp — marked as dev by the {@link DevMiniappBadge} dot
1037
+ * rather than renamed to a generic "Dev" tile.
1038
+ */
1039
+ export function registerDevApp(record: DevAppRecord): void {
1040
+ const devRecord: DevAppRecord = {
1041
+ ...record,
1042
+ // Preserve the real manifest package before overwriting packageName with the
1043
+ // single dev-slot name, so clearDevArtifacts can tell whether an install/uninstall
1044
+ // actually targets the dev slot.
1045
+ sourcePackageName: record.sourcePackageName ?? record.packageName,
1046
+ packageName: DEV_APP_PACKAGE_NAME,
1047
+ // Keep the manifest's real name + icon (display-only; routing keys on
1048
+ // packageName). Fall back to DEV_APP_NAME only if a caller omitted the name.
1049
+ name: record.name || DEV_APP_NAME,
1050
+ iconUrl: record.iconUrl,
1051
+ }
1052
+ storage.save(`${DEV_APP_PACKAGE_NAME}_dev_meta`, JSON.stringify(devRecord))
1053
+ // The launch chain (LocalMiniappView.resolveDevPort, mentraJsBootstrap
1054
+ // respawn-bg) reads these keys under DEV_APP_PACKAGE_NAME — persist them
1055
+ // here so callers can't key them on the wrong (real) package name.
1056
+ storage.save(`${DEV_APP_PACKAGE_NAME}_dev_url`, record.devUrl)
1057
+ if (typeof record.devPort === "number" && Number.isFinite(record.devPort)) {
1058
+ storage.save(`${DEV_APP_PACKAGE_NAME}_dev_port`, record.devPort)
1059
+ } else {
1060
+ storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_port`)
1061
+ }
1062
+ const idx = getDevAppIndex()
1063
+ if (!idx.includes(DEV_APP_PACKAGE_NAME)) {
1064
+ idx.push(DEV_APP_PACKAGE_NAME)
1065
+ storage.save(DEV_APPS_INDEX_KEY, JSON.stringify(idx))
1066
+ }
1067
+ appRegistry.markRefreshNeeded()
1068
+ }
1069
+
1070
+ /** Drop the dev miniapp's home-tile metadata + dev URL/port keys. */
1071
+ export function unregisterDevApp(): void {
1072
+ storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_meta`)
1073
+ storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_url`)
1074
+ storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_port`)
1075
+ storage.remove(`${DEV_APP_PACKAGE_NAME}_dev_last_reachable`)
1076
+ const idx = getDevAppIndex().filter((p) => p !== DEV_APP_PACKAGE_NAME)
1077
+ storage.save(DEV_APPS_INDEX_KEY, JSON.stringify(idx))
1078
+ appRegistry.markRefreshNeeded()
1079
+ }
1080
+
1081
+ function getDevAppIndex(): string[] {
1082
+ const res = storage.load<string>(DEV_APPS_INDEX_KEY)
1083
+ if (!res.is_ok()) return []
1084
+ try {
1085
+ const parsed = JSON.parse(res.value)
1086
+ return Array.isArray(parsed) ? (parsed as string[]) : []
1087
+ } catch {
1088
+ return []
1089
+ }
1090
+ }
1091
+
1092
+ /**
1093
+ * The real manifest package name currently occupying the dev slot, or null if no dev app is
1094
+ * registered. Used to decide whether clearing a package's artifacts should also drop the dev slot.
1095
+ */
1096
+ export function getDevAppSourcePackage(): string | null {
1097
+ const res = storage.load<string>(`${DEV_APP_PACKAGE_NAME}_dev_meta`)
1098
+ if (!res.is_ok()) return null
1099
+ try {
1100
+ const rec = JSON.parse(res.value) as DevAppRecord
1101
+ return rec.sourcePackageName ?? null
1102
+ } catch {
1103
+ return null
1104
+ }
1105
+ }
1106
+
1107
+ export function getDevAppAttestation(): string | null {
1108
+ const res = storage.load<string>(`${DEV_APP_PACKAGE_NAME}_dev_meta`)
1109
+ if (!res.is_ok()) return null
1110
+ try {
1111
+ const rec = JSON.parse(res.value) as DevAppRecord
1112
+ return rec.devAttestation ?? null
1113
+ } catch {
1114
+ return null
1115
+ }
1116
+ }
1117
+
1118
+ export function getDevAppRecords(): DevAppRecord[] {
1119
+ const out: DevAppRecord[] = []
1120
+ for (const pkg of getDevAppIndex()) {
1121
+ const res = storage.load<string>(`${pkg}_dev_meta`)
1122
+ if (!res.is_ok()) continue
1123
+ try {
1124
+ const record = JSON.parse(res.value) as DevAppRecord
1125
+ const normalized = normalizeDevAppRecord(record)
1126
+ if (normalized !== record) {
1127
+ storage.save(`${pkg}_dev_meta`, JSON.stringify(normalized))
1128
+ storage.save(`${pkg}_dev_url`, normalized.devUrl)
1129
+ }
1130
+ out.push(normalized)
1131
+ } catch {
1132
+ /* corrupt record — skip */
1133
+ }
1134
+ }
1135
+ return out
1136
+ }
1137
+
1138
+ const appRegistry = AppRegistry.getInstance()
1139
+ export default appRegistry