@glassly/engine 0.1.0-dev.99 → 0.2.8-dev.445

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 (501) hide show
  1. package/README.md +28 -0
  2. package/build/engine.d.ts +32 -10
  3. package/build/engine.d.ts.map +1 -1
  4. package/build/engine.js +24 -16
  5. package/build/engine.js.map +1 -1
  6. package/build/facades/dev.d.ts +9 -0
  7. package/build/facades/dev.d.ts.map +1 -1
  8. package/build/facades/dev.js +9 -0
  9. package/build/facades/dev.js.map +1 -1
  10. package/build/facades/display.d.ts +10 -3
  11. package/build/facades/display.d.ts.map +1 -1
  12. package/build/facades/display.js +22 -8
  13. package/build/facades/display.js.map +1 -1
  14. package/build/facades/displayMirror.d.ts +11 -0
  15. package/build/facades/displayMirror.d.ts.map +1 -1
  16. package/build/facades/displayMirror.js +22 -0
  17. package/build/facades/displayMirror.js.map +1 -1
  18. package/build/facades/glasses.d.ts +31 -1
  19. package/build/facades/glasses.d.ts.map +1 -1
  20. package/build/facades/glasses.js +51 -0
  21. package/build/facades/glasses.js.map +1 -1
  22. package/build/facades/memory.d.ts +0 -6
  23. package/build/facades/memory.d.ts.map +1 -1
  24. package/build/facades/memory.js +1 -9
  25. package/build/facades/memory.js.map +1 -1
  26. package/build/facades/miniapps.d.ts +3 -1
  27. package/build/facades/miniapps.d.ts.map +1 -1
  28. package/build/facades/miniapps.js +3 -1
  29. package/build/facades/miniapps.js.map +1 -1
  30. package/build/facades/pairing.d.ts.map +1 -1
  31. package/build/facades/pairing.js +5 -4
  32. package/build/facades/pairing.js.map +1 -1
  33. package/build/facades/permissions.d.ts +2 -0
  34. package/build/facades/permissions.d.ts.map +1 -1
  35. package/build/facades/permissions.js +48 -0
  36. package/build/facades/permissions.js.map +1 -1
  37. package/build/facades/phoneNotifications.d.ts +20 -9
  38. package/build/facades/phoneNotifications.d.ts.map +1 -1
  39. package/build/facades/phoneNotifications.js +33 -26
  40. package/build/facades/phoneNotifications.js.map +1 -1
  41. package/build/facades/settings.d.ts.map +1 -1
  42. package/build/facades/settings.js +1 -2
  43. package/build/facades/settings.js.map +1 -1
  44. package/build/generated/releaseMetadata.js +4 -4
  45. package/build/generated/releaseMetadata.js.map +1 -1
  46. package/build/index.d.ts +6 -4
  47. package/build/index.d.ts.map +1 -1
  48. package/build/index.js +5 -4
  49. package/build/index.js.map +1 -1
  50. package/build/react/MentraLiveOtaFlow.js +2 -2
  51. package/build/react/MentraLiveOtaFlow.js.map +1 -1
  52. package/build/react/useMentraLiveOta.d.ts.map +1 -1
  53. package/build/react/useMentraLiveOta.js +8 -7
  54. package/build/react/useMentraLiveOta.js.map +1 -1
  55. package/build/runtime/config.d.ts +1 -1
  56. package/build/runtime/config.d.ts.map +1 -1
  57. package/build/runtime/config.js.map +1 -1
  58. package/build/services/AppRegistry.d.ts +4 -1
  59. package/build/services/AppRegistry.d.ts.map +1 -1
  60. package/build/services/AppRegistry.js +21 -1
  61. package/build/services/AppRegistry.js.map +1 -1
  62. package/build/services/BlobStore.d.ts +2 -2
  63. package/build/services/BlobStore.js +3 -3
  64. package/build/services/BlobStore.js.map +1 -1
  65. package/build/services/CloudClientService.d.ts +7 -3
  66. package/build/services/CloudClientService.d.ts.map +1 -1
  67. package/build/services/CloudClientService.js +34 -9
  68. package/build/services/CloudClientService.js.map +1 -1
  69. package/build/services/DevServerBridge.d.ts +1 -18
  70. package/build/services/DevServerBridge.d.ts.map +1 -1
  71. package/build/services/DevServerBridge.js +9 -8
  72. package/build/services/DevServerBridge.js.map +1 -1
  73. package/build/services/DeviceEventRouter.d.ts.map +1 -1
  74. package/build/services/DeviceEventRouter.js +58 -71
  75. package/build/services/DeviceEventRouter.js.map +1 -1
  76. package/build/services/DisplayDiagnostics.d.ts +5 -0
  77. package/build/services/DisplayDiagnostics.d.ts.map +1 -0
  78. package/build/services/DisplayDiagnostics.js +105 -0
  79. package/build/services/DisplayDiagnostics.js.map +1 -0
  80. package/build/services/DisplayProcessor.d.ts +6 -7
  81. package/build/services/DisplayProcessor.d.ts.map +1 -1
  82. package/build/services/DisplayProcessor.js +17 -45
  83. package/build/services/DisplayProcessor.js.map +1 -1
  84. package/build/services/GestureDotsService.d.ts +10 -4
  85. package/build/services/GestureDotsService.d.ts.map +1 -1
  86. package/build/services/GestureDotsService.js +70 -16
  87. package/build/services/GestureDotsService.js.map +1 -1
  88. package/build/services/GlassesKeyboardInput.d.ts +77 -0
  89. package/build/services/GlassesKeyboardInput.d.ts.map +1 -0
  90. package/build/services/GlassesKeyboardInput.js +261 -0
  91. package/build/services/GlassesKeyboardInput.js.map +1 -0
  92. package/build/services/GlassesSensorService.d.ts +47 -0
  93. package/build/services/GlassesSensorService.d.ts.map +1 -0
  94. package/build/services/GlassesSensorService.js +242 -0
  95. package/build/services/GlassesSensorService.js.map +1 -0
  96. package/build/services/GlassesTouchInput.d.ts +14 -0
  97. package/build/services/GlassesTouchInput.d.ts.map +1 -0
  98. package/build/services/GlassesTouchInput.js +107 -0
  99. package/build/services/GlassesTouchInput.js.map +1 -0
  100. package/build/services/HeadingService.d.ts +0 -6
  101. package/build/services/HeadingService.d.ts.map +1 -1
  102. package/build/services/HeadingService.js +0 -27
  103. package/build/services/HeadingService.js.map +1 -1
  104. package/build/services/HotspotShutdown.d.ts.map +1 -1
  105. package/build/services/HotspotShutdown.js +2 -1
  106. package/build/services/HotspotShutdown.js.map +1 -1
  107. package/build/services/JSCrashloopReportService.js +2 -2
  108. package/build/services/JSCrashloopReportService.js.map +1 -1
  109. package/build/services/JSRouter.d.ts +6 -4
  110. package/build/services/JSRouter.d.ts.map +1 -1
  111. package/build/services/JSRouter.js +15 -13
  112. package/build/services/JSRouter.js.map +1 -1
  113. package/build/services/LocalDisplayManager.d.ts +35 -7
  114. package/build/services/LocalDisplayManager.d.ts.map +1 -1
  115. package/build/services/LocalDisplayManager.js +105 -27
  116. package/build/services/LocalDisplayManager.js.map +1 -1
  117. package/build/services/LocalMiniappDataMigration.d.ts +1 -1
  118. package/build/services/LocalMiniappDataMigration.js +1 -1
  119. package/build/services/LocalMiniappDataMigration.js.map +1 -1
  120. package/build/services/LocalMiniappRuntime.d.ts +64 -11
  121. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  122. package/build/services/LocalMiniappRuntime.js +441 -35
  123. package/build/services/LocalMiniappRuntime.js.map +1 -1
  124. package/build/services/LocalSttFallbackCoordinator.d.ts +3 -0
  125. package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
  126. package/build/services/LocalSttFallbackCoordinator.js +27 -8
  127. package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
  128. package/build/services/MemoryStore.d.ts +8 -33
  129. package/build/services/MemoryStore.d.ts.map +1 -1
  130. package/build/services/MemoryStore.js +30 -56
  131. package/build/services/MemoryStore.js.map +1 -1
  132. package/build/services/MiniappEngine.d.ts +3 -3
  133. package/build/services/MiniappEngine.js +7 -7
  134. package/build/services/MiniappEngine.js.map +1 -1
  135. package/build/services/MiniappLauncher.d.ts +8 -0
  136. package/build/services/MiniappLauncher.d.ts.map +1 -1
  137. package/build/services/MiniappLauncher.js +19 -1
  138. package/build/services/MiniappLauncher.js.map +1 -1
  139. package/build/services/MirrorService.d.ts +24 -0
  140. package/build/services/MirrorService.d.ts.map +1 -0
  141. package/build/services/MirrorService.js +132 -0
  142. package/build/services/MirrorService.js.map +1 -0
  143. package/build/services/NativeNavigationService.d.ts +2 -3
  144. package/build/services/NativeNavigationService.d.ts.map +1 -1
  145. package/build/services/NativeNavigationService.js +24 -21
  146. package/build/services/NativeNavigationService.js.map +1 -1
  147. package/build/services/NavigationHandlers.d.ts.map +1 -1
  148. package/build/services/NavigationHandlers.js +10 -5
  149. package/build/services/NavigationHandlers.js.map +1 -1
  150. package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
  151. package/build/services/OtaInstallCoordinator.js +24 -23
  152. package/build/services/OtaInstallCoordinator.js.map +1 -1
  153. package/build/services/PairedGlassesLatch.d.ts +7 -0
  154. package/build/services/PairedGlassesLatch.d.ts.map +1 -0
  155. package/build/services/PairedGlassesLatch.js +38 -0
  156. package/build/services/PairedGlassesLatch.js.map +1 -0
  157. package/build/services/PhoneActivity.d.ts +23 -0
  158. package/build/services/PhoneActivity.d.ts.map +1 -0
  159. package/build/services/PhoneActivity.js +111 -0
  160. package/build/services/PhoneActivity.js.map +1 -0
  161. package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -1
  162. package/build/services/PhoneCameraFovCoordinator.js +4 -3
  163. package/build/services/PhoneCameraFovCoordinator.js.map +1 -1
  164. package/build/services/PhoneNotificationsSync.d.ts +40 -6
  165. package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
  166. package/build/services/PhoneNotificationsSync.js +160 -84
  167. package/build/services/PhoneNotificationsSync.js.map +1 -1
  168. package/build/services/PhonePhotoCoordinator.d.ts.map +1 -1
  169. package/build/services/PhonePhotoCoordinator.js +6 -5
  170. package/build/services/PhonePhotoCoordinator.js.map +1 -1
  171. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
  172. package/build/services/PhoneStreamCoordinator.js +8 -7
  173. package/build/services/PhoneStreamCoordinator.js.map +1 -1
  174. package/build/services/STTModelManager.d.ts +3 -0
  175. package/build/services/STTModelManager.d.ts.map +1 -1
  176. package/build/services/STTModelManager.js +15 -1
  177. package/build/services/STTModelManager.js.map +1 -1
  178. package/build/services/SceneRenderer.d.ts +43 -2
  179. package/build/services/SceneRenderer.d.ts.map +1 -1
  180. package/build/services/SceneRenderer.js +123 -8
  181. package/build/services/SceneRenderer.js.map +1 -1
  182. package/build/services/StreamLifecycleController.d.ts.map +1 -1
  183. package/build/services/StreamLifecycleController.js +6 -14
  184. package/build/services/StreamLifecycleController.js.map +1 -1
  185. package/build/services/TTSModelManager.js +1 -1
  186. package/build/services/TTSModelManager.js.map +1 -1
  187. package/build/services/UIRouter.d.ts +2 -2
  188. package/build/services/UIRouter.js +5 -5
  189. package/build/services/UIRouter.js.map +1 -1
  190. package/build/services/asg/galleryPathMigration.js +1 -1
  191. package/build/services/asg/galleryPathMigration.js.map +1 -1
  192. package/build/services/asg/gallerySyncService.js +2 -2
  193. package/build/services/asg/gallerySyncService.js.map +1 -1
  194. package/build/services/asg/localStorageService.d.ts.map +1 -1
  195. package/build/services/asg/localStorageService.js +3 -3
  196. package/build/services/asg/localStorageService.js.map +1 -1
  197. package/build/services/debug/DashboardOpenTrace.d.ts +32 -0
  198. package/build/services/debug/DashboardOpenTrace.d.ts.map +1 -0
  199. package/build/services/debug/DashboardOpenTrace.js +128 -0
  200. package/build/services/debug/DashboardOpenTrace.js.map +1 -0
  201. package/build/services/debug/dashboardOpenTimeline.d.ts +77 -0
  202. package/build/services/debug/dashboardOpenTimeline.d.ts.map +1 -0
  203. package/build/services/debug/dashboardOpenTimeline.js +195 -0
  204. package/build/services/debug/dashboardOpenTimeline.js.map +1 -0
  205. package/build/services/effectiveCapabilities.d.ts.map +1 -1
  206. package/build/services/effectiveCapabilities.js +25 -13
  207. package/build/services/effectiveCapabilities.js.map +1 -1
  208. package/build/services/gestureClaims.d.ts +34 -15
  209. package/build/services/gestureClaims.d.ts.map +1 -1
  210. package/build/services/gestureClaims.js +42 -21
  211. package/build/services/gestureClaims.js.map +1 -1
  212. package/build/services/manifestFields.d.ts +9 -0
  213. package/build/services/manifestFields.d.ts.map +1 -0
  214. package/build/services/manifestFields.js +26 -0
  215. package/build/services/manifestFields.js.map +1 -0
  216. package/build/services/memoryStoreInstance.d.ts +0 -10
  217. package/build/services/memoryStoreInstance.d.ts.map +1 -1
  218. package/build/services/memoryStoreInstance.js +2 -31
  219. package/build/services/memoryStoreInstance.js.map +1 -1
  220. package/build/services/mirrorSnapshot.d.ts +16 -0
  221. package/build/services/mirrorSnapshot.d.ts.map +1 -0
  222. package/build/services/mirrorSnapshot.js +102 -0
  223. package/build/services/mirrorSnapshot.js.map +1 -0
  224. package/build/services/nativeNavigationGate.d.ts +8 -0
  225. package/build/services/nativeNavigationGate.d.ts.map +1 -0
  226. package/build/services/nativeNavigationGate.js +12 -0
  227. package/build/services/nativeNavigationGate.js.map +1 -0
  228. package/build/services/notificationAppCatalog.d.ts +7 -0
  229. package/build/services/notificationAppCatalog.d.ts.map +1 -0
  230. package/build/services/notificationAppCatalog.js +16 -0
  231. package/build/services/notificationAppCatalog.js.map +1 -0
  232. package/build/services/notifications/notificationPolicy.d.ts +55 -0
  233. package/build/services/notifications/notificationPolicy.d.ts.map +1 -0
  234. package/build/services/notifications/notificationPolicy.js +41 -0
  235. package/build/services/notifications/notificationPolicy.js.map +1 -0
  236. package/build/services/pages/OverlayPages.d.ts +26 -0
  237. package/build/services/pages/OverlayPages.d.ts.map +1 -0
  238. package/build/services/pages/OverlayPages.js +80 -0
  239. package/build/services/pages/OverlayPages.js.map +1 -0
  240. package/build/services/pages/PageHost.d.ts +32 -0
  241. package/build/services/pages/PageHost.d.ts.map +1 -0
  242. package/build/services/pages/PageHost.js +99 -0
  243. package/build/services/pages/PageHost.js.map +1 -0
  244. package/build/services/pages/overlayApps.d.ts +25 -0
  245. package/build/services/pages/overlayApps.d.ts.map +1 -0
  246. package/build/services/pages/overlayApps.js +66 -0
  247. package/build/services/pages/overlayApps.js.map +1 -0
  248. package/build/services/pages/pageEligibility.d.ts +9 -0
  249. package/build/services/pages/pageEligibility.d.ts.map +1 -0
  250. package/build/services/pages/pageEligibility.js +27 -0
  251. package/build/services/pages/pageEligibility.js.map +1 -0
  252. package/build/services/settingsBridge.d.ts +58 -0
  253. package/build/services/settingsBridge.d.ts.map +1 -0
  254. package/build/services/settingsBridge.js +90 -0
  255. package/build/services/settingsBridge.js.map +1 -0
  256. package/build/services/speakerProfileStoreInstance.js +1 -1
  257. package/build/services/speakerProfileStoreInstance.js.map +1 -1
  258. package/build/services/uiShim.d.ts +1 -1
  259. package/build/services/uiShim.js +4 -4
  260. package/build/services/uiShim.js.map +1 -1
  261. package/build/stores/appVisibility.d.ts +28 -0
  262. package/build/stores/appVisibility.d.ts.map +1 -1
  263. package/build/stores/appVisibility.js +34 -0
  264. package/build/stores/appVisibility.js.map +1 -1
  265. package/build/stores/apps.d.ts +13 -0
  266. package/build/stores/apps.d.ts.map +1 -1
  267. package/build/stores/apps.js +66 -12
  268. package/build/stores/apps.js.map +1 -1
  269. package/build/stores/bluetoothSettingKeys.js +1 -1
  270. package/build/stores/bluetoothSettingKeys.js.map +1 -1
  271. package/build/stores/display.d.ts +3 -3
  272. package/build/stores/display.d.ts.map +1 -1
  273. package/build/stores/display.js +16 -4
  274. package/build/stores/display.js.map +1 -1
  275. package/build/stores/glasses.d.ts.map +1 -1
  276. package/build/stores/glasses.js +14 -1
  277. package/build/stores/glasses.js.map +1 -1
  278. package/build/stores/settings.d.ts +1 -0
  279. package/build/stores/settings.d.ts.map +1 -1
  280. package/build/stores/settings.js +170 -44
  281. package/build/stores/settings.js.map +1 -1
  282. package/build/types/applet.d.ts +14 -1
  283. package/build/types/applet.d.ts.map +1 -1
  284. package/build/types/applet.js.map +1 -1
  285. package/build/types/capabilities/even-realities-g2.d.ts.map +1 -1
  286. package/build/types/capabilities/even-realities-g2.js +5 -0
  287. package/build/types/capabilities/even-realities-g2.js.map +1 -1
  288. package/build/types/capabilities/simulated-glasses.d.ts +1 -1
  289. package/build/types/capabilities/simulated-glasses.d.ts.map +1 -1
  290. package/build/types/capabilities/simulated-glasses.js +7 -4
  291. package/build/types/capabilities/simulated-glasses.js.map +1 -1
  292. package/build/types/hardware.d.ts +20 -1
  293. package/build/types/hardware.d.ts.map +1 -1
  294. package/build/types/hardware.js +2 -0
  295. package/build/types/hardware.js.map +1 -1
  296. package/build/types/index.d.ts +1 -0
  297. package/build/types/index.d.ts.map +1 -1
  298. package/build/types/index.js +1 -0
  299. package/build/types/index.js.map +1 -1
  300. package/build/utils/debouncedPatch.d.ts +3 -1
  301. package/build/utils/debouncedPatch.d.ts.map +1 -1
  302. package/build/utils/debouncedPatch.js +6 -3
  303. package/build/utils/debouncedPatch.js.map +1 -1
  304. package/build/utils/devMiniappLaunch.d.ts.map +1 -1
  305. package/build/utils/devMiniappLaunch.js +4 -3
  306. package/build/utils/devMiniappLaunch.js.map +1 -1
  307. package/build/utils/display/measurer/TextMeasurer.d.ts +2 -159
  308. package/build/utils/display/measurer/TextMeasurer.d.ts.map +1 -1
  309. package/build/utils/display/measurer/TextMeasurer.js +2 -272
  310. package/build/utils/display/measurer/TextMeasurer.js.map +1 -1
  311. package/build/utils/display/measurer/script-detection.d.ts +1 -52
  312. package/build/utils/display/measurer/script-detection.d.ts.map +1 -1
  313. package/build/utils/display/measurer/script-detection.js +2 -183
  314. package/build/utils/display/measurer/script-detection.js.map +1 -1
  315. package/build/utils/display/pixelArt.d.ts +3 -0
  316. package/build/utils/display/pixelArt.d.ts.map +1 -0
  317. package/build/utils/display/pixelArt.js +3 -0
  318. package/build/utils/display/pixelArt.js.map +1 -0
  319. package/build/utils/display/profiles/g1.d.ts +1 -32
  320. package/build/utils/display/profiles/g1.d.ts.map +1 -1
  321. package/build/utils/display/profiles/g1.js +2 -212
  322. package/build/utils/display/profiles/g1.js.map +1 -1
  323. package/build/utils/display/profiles/g2.d.ts +1 -12
  324. package/build/utils/display/profiles/g2.d.ts.map +1 -1
  325. package/build/utils/display/profiles/g2.js +2 -33
  326. package/build/utils/display/profiles/g2.js.map +1 -1
  327. package/build/utils/display/profiles/nex.d.ts +1 -9
  328. package/build/utils/display/profiles/nex.d.ts.map +1 -1
  329. package/build/utils/display/profiles/nex.js +2 -149
  330. package/build/utils/display/profiles/nex.js.map +1 -1
  331. package/build/utils/display/profiles/types.d.ts +1 -102
  332. package/build/utils/display/profiles/types.d.ts.map +1 -1
  333. package/build/utils/display/profiles/types.js.map +1 -1
  334. package/build/utils/display/profiles/z100.d.ts +1 -32
  335. package/build/utils/display/profiles/z100.d.ts.map +1 -1
  336. package/build/utils/display/profiles/z100.js +2 -181
  337. package/build/utils/display/profiles/z100.js.map +1 -1
  338. package/build/utils/display/scene/degrade.d.ts.map +1 -1
  339. package/build/utils/display/scene/degrade.js +4 -1
  340. package/build/utils/display/scene/degrade.js.map +1 -1
  341. package/build/utils/display/scene/differ.d.ts +13 -1
  342. package/build/utils/display/scene/differ.d.ts.map +1 -1
  343. package/build/utils/display/scene/differ.js +22 -0
  344. package/build/utils/display/scene/differ.js.map +1 -1
  345. package/build/utils/display/scene/index.d.ts +1 -1
  346. package/build/utils/display/scene/index.d.ts.map +1 -1
  347. package/build/utils/display/scene/index.js.map +1 -1
  348. package/build/utils/display/scene/process.d.ts.map +1 -1
  349. package/build/utils/display/scene/process.js +183 -11
  350. package/build/utils/display/scene/process.js.map +1 -1
  351. package/build/utils/display/scene/store.d.ts +1 -1
  352. package/build/utils/display/scene/store.d.ts.map +1 -1
  353. package/build/utils/display/scene/store.js +0 -0
  354. package/build/utils/display/scene/store.js.map +1 -1
  355. package/build/utils/display/scene/svgPath.d.ts +9 -0
  356. package/build/utils/display/scene/svgPath.d.ts.map +1 -0
  357. package/build/utils/display/scene/svgPath.js +167 -0
  358. package/build/utils/display/scene/svgPath.js.map +1 -0
  359. package/build/utils/display/scene/types.d.ts +2 -142
  360. package/build/utils/display/scene/types.d.ts.map +1 -1
  361. package/build/utils/display/scene/types.js +0 -0
  362. package/build/utils/display/scene/types.js.map +1 -1
  363. package/build/utils/display/wrapper/TextWrapper.d.ts +1 -101
  364. package/build/utils/display/wrapper/TextWrapper.d.ts.map +1 -1
  365. package/build/utils/display/wrapper/TextWrapper.js +2 -470
  366. package/build/utils/display/wrapper/TextWrapper.js.map +1 -1
  367. package/build/utils/display/wrapper/types.d.ts +2 -74
  368. package/build/utils/display/wrapper/types.d.ts.map +1 -1
  369. package/build/utils/display/wrapper/types.js +2 -10
  370. package/build/utils/display/wrapper/types.js.map +1 -1
  371. package/build/utils/hardware/hardware.js +1 -1
  372. package/build/utils/hardware/hardware.js.map +1 -1
  373. package/build/utils/timers/timers.d.ts.map +1 -1
  374. package/build/utils/timers/timers.js +26 -4
  375. package/build/utils/timers/timers.js.map +1 -1
  376. package/package.json +8 -8
  377. package/src/engine.ts +24 -15
  378. package/src/facades/dev.ts +10 -0
  379. package/src/facades/display.ts +21 -8
  380. package/src/facades/displayMirror.ts +29 -0
  381. package/src/facades/glasses.ts +61 -1
  382. package/src/facades/memory.ts +1 -12
  383. package/src/facades/miniapps.ts +4 -1
  384. package/src/facades/pairing.ts +8 -6
  385. package/src/facades/permissions.ts +46 -0
  386. package/src/facades/phoneNotifications.ts +45 -26
  387. package/src/facades/settings.ts +1 -2
  388. package/src/generated/releaseMetadata.ts +4 -4
  389. package/src/index.ts +6 -9
  390. package/src/react/MentraLiveOtaFlow.tsx +2 -2
  391. package/src/react/useMentraLiveOta.ts +14 -8
  392. package/src/runtime/config.ts +1 -1
  393. package/src/services/AppRegistry.ts +43 -7
  394. package/src/services/BlobStore.ts +3 -3
  395. package/src/services/CloudClientService.ts +37 -10
  396. package/src/services/DevServerBridge.ts +12 -10
  397. package/src/services/DeviceEventRouter.ts +73 -74
  398. package/src/services/DisplayDiagnostics.ts +107 -0
  399. package/src/services/DisplayProcessor.ts +20 -55
  400. package/src/services/GestureDotsService.ts +77 -16
  401. package/src/services/GlassesKeyboardInput.ts +306 -0
  402. package/src/services/GlassesSensorService.ts +233 -0
  403. package/src/services/GlassesTouchInput.ts +128 -0
  404. package/src/services/HeadingService.ts +0 -24
  405. package/src/services/HotspotShutdown.ts +3 -1
  406. package/src/services/JSCrashloopReportService.ts +2 -2
  407. package/src/services/JSRouter.ts +29 -14
  408. package/src/services/LocalDisplayManager.ts +112 -26
  409. package/src/services/LocalMiniappDataMigration.ts +1 -1
  410. package/src/services/LocalMiniappRuntime.ts +500 -43
  411. package/src/services/LocalSttFallbackCoordinator.ts +28 -7
  412. package/src/services/MemoryStore.ts +32 -80
  413. package/src/services/MiniappEngine.ts +7 -7
  414. package/src/services/MiniappLauncher.ts +25 -1
  415. package/src/services/MirrorService.ts +139 -0
  416. package/src/services/NativeNavigationService.ts +29 -25
  417. package/src/services/NavigationHandlers.ts +10 -5
  418. package/src/services/OtaInstallCoordinator.ts +36 -34
  419. package/src/services/PairedGlassesLatch.ts +39 -0
  420. package/src/services/PhoneActivity.ts +116 -0
  421. package/src/services/PhoneCameraFovCoordinator.ts +6 -4
  422. package/src/services/PhoneNotificationsSync.ts +185 -103
  423. package/src/services/PhonePhotoCoordinator.ts +9 -10
  424. package/src/services/PhoneStreamCoordinator.ts +13 -11
  425. package/src/services/STTModelManager.ts +15 -1
  426. package/src/services/SceneRenderer.ts +148 -10
  427. package/src/services/StreamLifecycleController.ts +9 -7
  428. package/src/services/TTSModelManager.ts +1 -1
  429. package/src/services/UIRouter.ts +5 -5
  430. package/src/services/asg/galleryPathMigration.ts +1 -1
  431. package/src/services/asg/gallerySyncService.ts +2 -2
  432. package/src/services/asg/localStorageService.ts +3 -3
  433. package/src/services/debug/DashboardOpenTrace.ts +153 -0
  434. package/src/services/debug/dashboardOpenTimeline.ts +237 -0
  435. package/src/services/effectiveCapabilities.ts +32 -13
  436. package/src/services/gestureClaims.ts +72 -23
  437. package/src/services/manifestFields.ts +23 -0
  438. package/src/services/memoryStoreInstance.ts +2 -34
  439. package/src/services/mirrorSnapshot.ts +116 -0
  440. package/src/services/nativeNavigationGate.ts +14 -0
  441. package/src/services/notificationAppCatalog.ts +21 -0
  442. package/src/services/notifications/notificationPolicy.ts +87 -0
  443. package/src/services/pages/OverlayPages.ts +86 -0
  444. package/src/services/pages/PageHost.ts +116 -0
  445. package/src/services/pages/overlayApps.ts +72 -0
  446. package/src/services/pages/pageEligibility.ts +30 -0
  447. package/src/services/settingsBridge.ts +111 -0
  448. package/src/services/speakerProfileStoreInstance.ts +1 -1
  449. package/src/services/uiShim.ts +4 -4
  450. package/src/stores/appVisibility.ts +45 -0
  451. package/src/stores/apps.ts +110 -32
  452. package/src/stores/bluetoothSettingKeys.ts +1 -1
  453. package/src/stores/display.ts +18 -7
  454. package/src/stores/glasses.ts +15 -1
  455. package/src/stores/settings.ts +175 -51
  456. package/src/types/applet.ts +14 -1
  457. package/src/types/capabilities/even-realities-g2.ts +6 -0
  458. package/src/types/capabilities/simulated-glasses.ts +8 -4
  459. package/src/types/hardware.ts +34 -1
  460. package/src/types/index.ts +1 -0
  461. package/src/utils/debouncedPatch.ts +8 -4
  462. package/src/utils/devMiniappLaunch.ts +5 -3
  463. package/src/utils/display/measurer/TextMeasurer.ts +3 -346
  464. package/src/utils/display/measurer/script-detection.ts +10 -218
  465. package/src/utils/display/pixelArt.ts +3 -0
  466. package/src/utils/display/profiles/g1.ts +2 -236
  467. package/src/utils/display/profiles/g2.ts +2 -39
  468. package/src/utils/display/profiles/nex.ts +2 -166
  469. package/src/utils/display/profiles/types.ts +9 -132
  470. package/src/utils/display/profiles/z100.ts +2 -198
  471. package/src/utils/display/scene/degrade.ts +4 -1
  472. package/src/utils/display/scene/differ.ts +25 -1
  473. package/src/utils/display/scene/index.ts +5 -0
  474. package/src/utils/display/scene/process.ts +196 -13
  475. package/src/utils/display/scene/store.ts +0 -0
  476. package/src/utils/display/scene/svgPath.ts +163 -0
  477. package/src/utils/display/scene/types.ts +0 -0
  478. package/src/utils/display/wrapper/TextWrapper.ts +2 -546
  479. package/src/utils/display/wrapper/types.ts +3 -102
  480. package/src/utils/hardware/hardware.ts +1 -1
  481. package/src/utils/timers/timers.ts +32 -4
  482. package/build/services/CustomDashboardModel.d.ts +0 -48
  483. package/build/services/CustomDashboardModel.d.ts.map +0 -1
  484. package/build/services/CustomDashboardModel.js +0 -73
  485. package/build/services/CustomDashboardModel.js.map +0 -1
  486. package/build/services/CustomDashboardService.d.ts +0 -63
  487. package/build/services/CustomDashboardService.d.ts.map +0 -1
  488. package/build/services/CustomDashboardService.js +0 -576
  489. package/build/services/CustomDashboardService.js.map +0 -1
  490. package/build/services/DashboardCoordinator.d.ts +0 -26
  491. package/build/services/DashboardCoordinator.d.ts.map +0 -1
  492. package/build/services/DashboardCoordinator.js +0 -125
  493. package/build/services/DashboardCoordinator.js.map +0 -1
  494. package/build/services/iosNotificationAppCatalog.d.ts +0 -13
  495. package/build/services/iosNotificationAppCatalog.d.ts.map +0 -1
  496. package/build/services/iosNotificationAppCatalog.js +0 -28
  497. package/build/services/iosNotificationAppCatalog.js.map +0 -1
  498. package/src/services/CustomDashboardModel.ts +0 -83
  499. package/src/services/CustomDashboardService.ts +0 -598
  500. package/src/services/DashboardCoordinator.ts +0 -121
  501. package/src/services/iosNotificationAppCatalog.ts +0 -39
@@ -114,6 +114,52 @@ function androidPerms(feature: string): AndroidPermission[] {
114
114
  }
115
115
 
116
116
  export const permissions = {
117
+ /** Missing required miniapp grants, checked without prompting. CAMERA is the glasses camera. */
118
+ async missingRequired(requirements: readonly AppletPermission[]): Promise<string[]> {
119
+ const features = new Set<string>()
120
+ for (const permission of requirements) {
121
+ if (permission.required === false) continue
122
+ switch (permission.type) {
123
+ case "ALL":
124
+ features.add(PermissionFeatures.MICROPHONE)
125
+ features.add(PermissionFeatures.CALENDAR)
126
+ features.add(PermissionFeatures.LOCATION)
127
+ features.add(PermissionFeatures.BACKGROUND_LOCATION)
128
+ features.add(PermissionFeatures.POST_NOTIFICATIONS)
129
+ features.add("read_notifications")
130
+ break
131
+ case "MICROPHONE":
132
+ case "CALENDAR":
133
+ case "LOCATION":
134
+ case "BACKGROUND_LOCATION":
135
+ case "POST_NOTIFICATIONS":
136
+ features.add(PermissionFeatures[permission.type])
137
+ break
138
+ case "READ_NOTIFICATIONS":
139
+ features.add("read_notifications")
140
+ break
141
+ }
142
+ }
143
+
144
+ const missing: string[] = []
145
+ for (const feature of features) {
146
+ let granted: boolean
147
+ if (feature === "read_notifications") {
148
+ // iOS glasses read notifications directly; Android uses the phone's listener.
149
+ granted =
150
+ Platform.OS !== "android" ||
151
+ (await (await import("@glassly/crust")).default.hasNotificationListenerPermission())
152
+ } else if (feature === PermissionFeatures.CALENDAR && Platform.OS === "ios") {
153
+ // EventKit must allow reads; a scoped/write-only OS grant is insufficient.
154
+ granted = (await (await import("expo-calendar")).getCalendarPermissions()).status === "granted"
155
+ } else {
156
+ granted = await permissions.check(feature)
157
+ }
158
+ if (!granted) missing.push(feature)
159
+ }
160
+ return missing
161
+ },
162
+
117
163
  /** Is the given feature's OS permission currently granted? */
118
164
  async check(feature: string): Promise<boolean> {
119
165
  if (Platform.OS === "android") {
@@ -1,20 +1,28 @@
1
1
  /**
2
- * phoneNotifications facade — `engine.phoneNotifications`: forward phone
3
- * notifications to the glasses, with a per-app blocklist.
2
+ * phoneNotifications facade — `engine.phoneNotifications`: phone notifications
3
+ * on the glasses, with a per-app blocklist and one presentation owner.
4
4
  *
5
- * Android: apps come from the NotificationListenerService's installed-apps
6
- * enumeration and the blocklist filters capture phone-side.
7
- * iOS: apps are the seeded catalog plus what the glasses' ANCS client has
8
- * reported posting notifications (`ios_notification_seen_apps`); the blocklist
9
- * is mapped onto the G2's on-glass allowlist by PhoneNotificationsSync.
10
- * Capture itself is controlled by Android notification access / iOS ANCS
11
- * authorization (`glasses.ancsAuthorized`), not by this facade.
5
+ * Capture is the phone's (Android listener) or the glasses' (iOS, reading the
6
+ * phone's stream) business and is never gated here. Presentation is decided
7
+ * by `presentationOwner`: the engine's viewer on Glassly CFW glasses, the
8
+ * firmware on glasses with their own notification centre, else the host's
9
+ * card while its surface (Notify) runs. The four display settings drive
10
+ * firmware and viewer alike; PhoneNotificationsSync pushes them.
12
11
  */
13
12
  import {Platform} from "react-native"
14
13
  import CrustModule from "@glassly/crust"
14
+ import type {PhoneNotificationEvent} from "@glassly/crust"
15
+ import BluetoothSdk from "@glassly/bluetooth-sdk/internal"
16
+ import type {GlassesNotificationStatus, NotificationUploadResult} from "@glassly/bluetooth-sdk"
15
17
  import {useSettingsStore, SETTINGS} from "../stores/settings"
16
- import {useGlassesStore} from "../stores/glasses"
17
- import {getKnownNotificationApps} from "../services/PhoneNotificationsSync"
18
+ import {
19
+ captureAuthorization,
20
+ currentPresentationOwner,
21
+ installedNotificationApps,
22
+ nativeNotificationPopupSeconds,
23
+ nativeNotificationsSupported,
24
+ uploadPhoneNotification,
25
+ } from "../services/PhoneNotificationsSync"
18
26
 
19
27
  export const phoneNotifications = {
20
28
  /**
@@ -22,17 +30,7 @@ export const phoneNotifications = {
22
30
  * Android: installed apps. iOS: seeded catalog ∪ glasses-reported apps
23
31
  * (icons unavailable — iOS offers no cross-app icon lookup).
24
32
  */
25
- installedApps: (): Promise<Array<{packageName: string; appName: string; icon: string | null}>> => {
26
- if (Platform.OS === "android") return CrustModule.getInstalledApps()
27
- if (Platform.OS !== "ios") return Promise.resolve([])
28
- return Promise.resolve(
29
- getKnownNotificationApps().map((app) => ({
30
- packageName: app.appId,
31
- appName: app.displayName,
32
- icon: null,
33
- })),
34
- )
35
- },
33
+ installedApps: installedNotificationApps,
36
34
 
37
35
  /** The per-app blocklist (package/bundle ids whose notifications are NOT forwarded). */
38
36
  blocklist: (): string[] => {
@@ -54,10 +52,31 @@ export const phoneNotifications = {
54
52
  return CrustModule.openNotificationListenerSettings()
55
53
  },
56
54
 
55
+ /** Whether the glasses may read the phone's notifications; `not_needed` where the phone captures. */
56
+ captureAuthorization,
57
+
58
+ /** The connected model presents notifications in firmware. */
59
+ nativeNotifications: nativeNotificationsSupported,
60
+ /** Popup durations the firmware accepts (seconds, 0 = its default); empty when any value goes. */
61
+ popupSecondsOptions: nativeNotificationPopupSeconds,
62
+
57
63
  /**
58
- * iOS: whether the connected glasses may read the phone's ANCS notification
59
- * stream (the "Share System Notifications" Bluetooth consent). Always false
60
- * on Android — Android capture is the notification listener instead.
64
+ * Who presents the next phone notification. Hosts pass whether their own
65
+ * surface runs and draw only when the answer is `host`.
61
66
  */
62
- ancsAuthorized: (): boolean => Boolean(useGlassesStore.getState().ancsAuthorized),
67
+ presentationOwner: currentPresentationOwner,
68
+ /** Hand a captured notification to firmware that presents uploaded content (owner `firmware`, Android). */
69
+ uploadToGlasses: (event: PhoneNotificationEvent): Promise<void> => uploadPhoneNotification(event),
70
+
71
+ /** The driver's view of its notification surface. */
72
+ glassesStatus: (): Promise<GlassesNotificationStatus> => BluetoothSdk.getGlassesNotificationStatus(),
73
+ onGlassesStatus: (listener: (status: GlassesNotificationStatus) => void): (() => void) => {
74
+ const subscription = BluetoothSdk.addListener("glasses_notification_status", listener)
75
+ return () => subscription.remove()
76
+ },
77
+ /** Upload outcomes by id; content never travels back. */
78
+ onUploadResult: (listener: (result: NotificationUploadResult) => void): (() => void) => {
79
+ const subscription = BluetoothSdk.addListener("notification_upload_result", listener)
80
+ return () => subscription.remove()
81
+ },
63
82
  }
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * settings facade — `engine.settings`: the typed keyed user-settings surface over
3
- * the engine-owned settings store. This is the (A) OEM contract; the raw store at
4
- * `engine.stores.settings` is the Glassly-app escape hatch.
3
+ * the engine-owned settings store. This is the OEM contract.
5
4
  *
6
5
  * Keys + their schema live in `SETTINGS` (theme, devMode, metric/twelveHourTime,
7
6
  * notifications, onboarding flags, …); `descriptor(key)`/`keys()` expose them.
@@ -11,10 +11,10 @@ export interface EngineReleaseMetadata {
11
11
 
12
12
  export const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({
13
13
  "schemaVersion": 1,
14
- "familyBaseVersion": "0.1.0",
15
- "releaseIdentity": "0.1.0-dev.99",
16
- "releaseSetId": "glassly-0.1.0-dev.99",
17
- "sourceCommit": "2aeea5db8ad4e84303faf84a92d025f0d1930ebf",
14
+ "familyBaseVersion": "0.2.8",
15
+ "releaseIdentity": "0.2.8-dev.445",
16
+ "releaseSetId": "glassly-0.2.8-dev.445",
17
+ "sourceCommit": "7e82d274d259dc795d05a3aef988d261d871106a",
18
18
  "otaManifestUrl": null,
19
19
  "otaManifestSha256": null
20
20
  })
package/src/index.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * renders with (decision functions, sort/order helpers, policy constants,
7
7
  * capability tables, timers). Judgment rule: read models, commands, pure
8
8
  * functions and types belong here; anything that mutates runtime state or
9
- * exposes a raw store/service remains private to the GlasslyOS host.
9
+ * exposes a raw store/service remains private to the Glassly host.
10
10
  * See cloud-v2/docs/issues/020-glasses-status-boundary/integration-review.md §D.
11
11
  */
12
12
 
@@ -22,6 +22,8 @@ export type {
22
22
  EngineSubmitReportInput,
23
23
  } from "./facades/reports"
24
24
  export type {IslandNotification, IslandNotificationKind} from "./facades/notifications"
25
+ export type {PresentationOwner} from "./services/notifications/notificationPolicy"
26
+ export {DEFAULT_HIDDEN_PACKAGES} from "./stores/appVisibility"
25
27
  export type {WifiSearchResult} from "./facades/glassesWifi"
26
28
  export type {IdentitySnapshot} from "./services/PairingIdentity"
27
29
  export type {DisplayMirrorEvent} from "./facades/displayMirror"
@@ -41,14 +43,8 @@ export type {
41
43
  // (the hook layer, same precedent as the apps hooks below), and the pure
42
44
  // device-model key helpers. The raw useSettingsStore stays internal;
43
45
  // imperative access goes through engine.settings.
44
- export {SETTINGS, useSetting} from "./stores/settings"
45
- export {
46
- isCustomDashboardEligible,
47
- normalizeDashboardWidgets,
48
- DASHBOARD_WIDGET_IDS,
49
- type DashboardWidgetId,
50
- type DashboardWidgetSetting,
51
- } from "./services/CustomDashboardModel"
46
+ export {SETTINGS, useSetting, AI_DATA_CONSENT_VERSION} from "./stores/settings"
47
+ export {isCfwFirmwareVersion, isCustomDashboardEligible} from "./services/pages/pageEligibility"
52
48
 
53
49
  // AI tier registry: the curated per-tier model dropdown options and helpers
54
50
  // the Settings > AI Models screen renders. Resolution itself runs inside
@@ -185,6 +181,7 @@ export {
185
181
  useInstall,
186
182
  useUninstall,
187
183
  useActiveApps,
184
+ useRunningPersistentApps,
188
185
  useActiveBackgroundApps,
189
186
  useBackgroundApps,
190
187
  useActiveForegroundApp,
@@ -159,7 +159,7 @@ export function MentraLiveOtaFlow({
159
159
  <SafeAreaView style={[styles.safeArea, {backgroundColor: colors.background}, style]}>
160
160
  <View style={styles.header}>
161
161
  <View />
162
- <GlasslyMark color={colors.primary} />
162
+ <BrandMark color={colors.primary} />
163
163
  </View>
164
164
  <OtaFlowContent
165
165
  allowDevSkip={allowDevSkip}
@@ -688,7 +688,7 @@ function FlowButton({
688
688
  )
689
689
  }
690
690
 
691
- function GlasslyMark({color}: {color: string}) {
691
+ function BrandMark({color}: {color: string}) {
692
692
  return (
693
693
  <Svg width={33} height={18} viewBox="0 0 50 27" fill="none">
694
694
  <Rect y={14.8072} width={11.8457} height={11.8457} fill={color} />
@@ -23,6 +23,8 @@ import type {OtaCheckCurrentGlassesResult} from "../services/OtaUpdateCheckServi
23
23
  import type {ReleaseChangelog} from "../facades/ota"
24
24
  import {useEngineSnapshot} from "./useEngineSnapshot"
25
25
 
26
+ import {BgTimer} from "../utils/timers"
27
+
26
28
  export type MentraLiveOtaFlowPage = "check" | "progress"
27
29
 
28
30
  export type MentraLiveOtaScreen =
@@ -306,14 +308,14 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
306
308
 
307
309
  const myGeneration = ++performCheckGenerationRef.current
308
310
  let cancelled = false
309
- let reconnectTimeout: ReturnType<typeof setTimeout> | null = null
311
+ let reconnectTimeout: number | null = null
310
312
 
311
313
  const performCheck = async () => {
312
314
  if (checkCompletedRef.current) return
313
315
  if (isOtaAutoChainActive() && !otaSnapshot.ready) {
314
316
  const remainingMs = otaAutoChainReconnectWaitRemaining()
315
317
  if (remainingMs === null) return
316
- reconnectTimeout = setTimeout(() => {
318
+ reconnectTimeout = BgTimer.setTimeout(() => {
317
319
  if (cancelled || myGeneration !== performCheckGenerationRef.current || ota.snapshot().ready) return
318
320
  stopOtaAutoChain()
319
321
  checkCompletedRef.current = true
@@ -347,13 +349,15 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
347
349
  let result = await ota.checkForUpdates(checkOptions)
348
350
  if (cancelled || myGeneration !== performCheckGenerationRef.current) return
349
351
  if (!result.hasCheckCompleted && result.checkFailureReason === "network" && isOtaAutoChainActive()) {
350
- await new Promise((resolve) => setTimeout(resolve, AUTO_CHAIN_NETWORK_RETRY_DELAY_MS))
352
+ await new Promise<void>((resolve) => BgTimer.setTimeout(resolve, AUTO_CHAIN_NETWORK_RETRY_DELAY_MS))
351
353
  if (cancelled || myGeneration !== performCheckGenerationRef.current) return
352
354
  result = await ota.checkForUpdates(checkOptions)
353
355
  }
354
356
  if (cancelled || myGeneration !== performCheckGenerationRef.current) return
355
357
  selectedCheckResultRef.current = result
356
- await new Promise((resolve) => setTimeout(resolve, Math.max(0, MIN_DISPLAY_TIME_MS - (Date.now() - startTime))))
358
+ await new Promise<void>((resolve) =>
359
+ BgTimer.setTimeout(resolve, Math.max(0, MIN_DISPLAY_TIME_MS - (Date.now() - startTime))),
360
+ )
357
361
  if (cancelled || myGeneration !== performCheckGenerationRef.current) return
358
362
 
359
363
  if (result.skippedReason === "disconnected") {
@@ -416,7 +420,9 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
416
420
  setCheckState("no_update")
417
421
  } catch (error) {
418
422
  console.error("OTA check failed:", error)
419
- await new Promise((resolve) => setTimeout(resolve, Math.max(0, MIN_DISPLAY_TIME_MS - (Date.now() - startTime))))
423
+ await new Promise<void>((resolve) =>
424
+ BgTimer.setTimeout(resolve, Math.max(0, MIN_DISPLAY_TIME_MS - (Date.now() - startTime))),
425
+ )
420
426
  if (cancelled || myGeneration !== performCheckGenerationRef.current) return
421
427
  stopOtaAutoChain()
422
428
  checkCompletedRef.current = true
@@ -428,7 +434,7 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
428
434
  void performCheck()
429
435
  return () => {
430
436
  cancelled = true
431
- if (reconnectTimeout) clearTimeout(reconnectTimeout)
437
+ if (reconnectTimeout) BgTimer.clearTimeout(reconnectTimeout)
432
438
  }
433
439
  }, [
434
440
  checkGeneration,
@@ -500,13 +506,13 @@ export function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraL
500
506
  ) {
501
507
  return
502
508
  }
503
- const timeout = setTimeout(async () => {
509
+ const timeout = BgTimer.setTimeout(async () => {
504
510
  if (!isOtaAutoChainActive()) return
505
511
  autoChainAdvancedRef.current = true
506
512
  await ota.installSession.finish()
507
513
  returnToCheck()
508
514
  }, AUTO_CHAIN_COMPLETE_DELAY_MS)
509
- return () => clearTimeout(timeout)
515
+ return () => BgTimer.clearTimeout(timeout)
510
516
  }, [installSnapshot.connected, installSnapshot.displayState, page, returnToCheck])
511
517
 
512
518
  const check = useCallback(() => {
@@ -15,7 +15,7 @@ export interface CloudClientStatusSnapshot {
15
15
  }
16
16
 
17
17
  export interface MiniappAuthToken {
18
- glasslyUserId: string
18
+ userId: string
19
19
  tenantId?: string
20
20
  token: string
21
21
  expiresAt: number
@@ -29,6 +29,7 @@ import {storage} from "../utils/storage/storage"
29
29
  import {printDirectory} from "../utils/storage/zip"
30
30
  import {checkManifestVersions} from "./manifestVersionGate"
31
31
  import {normalizeManifestActions} from "./manifestActions"
32
+ import {normalizeManifestTags, normalizeManifestText} from "./manifestFields"
32
33
  import {miniappRunningRegistry} from "./MiniappRunningRegistry"
33
34
 
34
35
  export {normalizeManifestActions} from "./manifestActions"
@@ -40,6 +41,7 @@ const ALLOWED_PERMISSION_TYPES: ReadonlySet<AppPermissionType> = new Set<AppPerm
40
41
  "LOCATION",
41
42
  "BACKGROUND_LOCATION",
42
43
  "READ_NOTIFICATIONS",
44
+ "DISPLAY_MIRROR",
43
45
  "POST_NOTIFICATIONS",
44
46
  "API_KEYS",
45
47
  ])
@@ -141,7 +143,7 @@ interface InstalledLma {
141
143
  }
142
144
 
143
145
  export interface MiniappReleaseIdentity {
144
- source: "direct_download" | "bundled_asset" | "preinstalled_registry" | "dev_snapshot"
146
+ source: "direct_download" | "bundled_asset" | "preinstalled_registry" | "dev_snapshot" | "store"
145
147
  releaseId?: string
146
148
  bundleSha256?: string
147
149
  channel?: string
@@ -750,12 +752,25 @@ class AppRegistry {
750
752
  permissions?: Array<string | {type: string; required?: boolean; description?: string}>
751
753
  hardwareRequirements?: Array<{type: string; level: string; description?: string}>
752
754
  type?: string
753
- actions?: Array<{id?: unknown; description?: unknown; parameters?: unknown; outputSchema?: unknown; visibility?: unknown}>
755
+ persistent?: unknown
756
+ description?: unknown
757
+ tagline?: unknown
758
+ tags?: unknown
759
+ actions?: Array<{
760
+ id?: unknown
761
+ description?: unknown
762
+ parameters?: unknown
763
+ outputSchema?: unknown
764
+ visibility?: unknown
765
+ }>
754
766
  } | null
755
767
 
756
768
  const permissions = normalizeManifestPermissions(manifest?.permissions)
757
769
  const hardwareRequirements = buildHardwareRequirements(manifest?.hardwareRequirements, lmaInfo.packageName)
758
770
  const appType = normalizeManifestType(manifest?.type)
771
+ const description = normalizeManifestText(manifest?.description)
772
+ const tagline = normalizeManifestText(manifest?.tagline)
773
+ const tags = normalizeManifestTags(manifest?.tags)
759
774
 
760
775
  // Declared actions (for session.miniapps.list + invoke gating).
761
776
  const actions = normalizeManifestActions(manifest?.actions)
@@ -783,8 +798,12 @@ class AppRegistry {
783
798
  webviewUrl: "",
784
799
  logoUrl: versionInfo.logoUrl,
785
800
  type: appType,
801
+ persistent: getPersistentOverride(lmaInfo.packageName) ?? manifest?.persistent === true,
786
802
  permissions,
787
803
  hardwareRequirements,
804
+ ...(description ? {description} : {}),
805
+ ...(tagline ? {tagline} : {}),
806
+ ...(tags.length > 0 ? {tags} : {}),
788
807
  // Always project actions (even []) so the invoke gate can enforce
789
808
  // declared-action membership unconditionally — an app with no declared
790
809
  // actions must reject every invoke, not bypass the check.
@@ -927,6 +946,16 @@ export function getLocalAppRunningState(packageName: string): boolean {
927
946
  return false
928
947
  }
929
948
 
949
+ /** The wearer's persistent choice for a miniapp, beside the `_hidden` flag; null when they never chose. */
950
+ export function getPersistentOverride(packageName: string): boolean | null {
951
+ const res = storage.load<boolean>(`${packageName}_persistent`)
952
+ return res.is_ok() ? res.value : null
953
+ }
954
+
955
+ export function savePersistentOverride(packageName: string, status: boolean): void {
956
+ storage.save(`${packageName}_persistent`, status)
957
+ }
958
+
930
959
  export function getLocalAppScreenshot(packageName: string): string | undefined {
931
960
  const key = `${packageName}_screenshot`
932
961
  const res = storage.load<string>(key)
@@ -974,7 +1003,13 @@ export interface DevAppRecord {
974
1003
  permissions?: Array<string | {type: string; required?: boolean; description?: string}>
975
1004
  hardwareRequirements?: Array<{type: string; level: string; description?: string}>
976
1005
  /** Manifest-declared actions — so dev-sideloaded miniapps can be invoked too. */
977
- actions?: Array<{id?: unknown; description?: unknown; parameters?: unknown; outputSchema?: unknown; visibility?: unknown}>
1006
+ actions?: Array<{
1007
+ id?: unknown
1008
+ description?: unknown
1009
+ parameters?: unknown
1010
+ outputSchema?: unknown
1011
+ visibility?: unknown
1012
+ }>
978
1013
  /** Legacy single-slot migration field. New records use the real packageName directly. */
979
1014
  sourcePackageName?: string
980
1015
  /**
@@ -988,7 +1023,6 @@ export interface DevAppRecord {
988
1023
  const DEV_APPS_INDEX_KEY = "dev_apps_index"
989
1024
  const DEV_APP_ICONS_DIR = "dev-miniapp-icons"
990
1025
 
991
-
992
1026
  function isPrivateLanHost(hostname: string): boolean {
993
1027
  return (
994
1028
  hostname === "localhost" ||
@@ -1044,7 +1078,10 @@ async function cacheDevAppIcon(packageName: string, iconUrl: string): Promise<st
1044
1078
  // Keep the decoder-friendly .png fallback; image loaders sniff content.
1045
1079
  }
1046
1080
 
1047
- const target = new File(dir, `${safePackageName}${extension}`)
1081
+ // Image loaders cache file:// URIs too. Replacing bytes at the same path
1082
+ // leaves the old decoded icon visible after rescanning the development QR.
1083
+ const revision = `${Date.now()}-${Math.random().toString(36).slice(2)}`
1084
+ const target = new File(dir, `${safePackageName}.${revision}${extension}`)
1048
1085
  const downloaded = await File.downloadFileAsync(iconUrl, target, {idempotent: true})
1049
1086
 
1050
1087
  // Only remove older extensions AFTER the replacement is safely on disk;
@@ -1174,8 +1211,7 @@ export async function registerDevApp(record: DevAppRecord): Promise<DevAppRecord
1174
1211
  // Relaunch paths (developer-URL screen, loadDevMiniapp) omit mdnsHost, so an
1175
1212
  // omitted field keeps whatever the QR scan stored instead of wiping the
1176
1213
  // `.local` failover host.
1177
- const mdnsHost =
1178
- record.mdnsHost !== undefined ? record.mdnsHost.trim() || undefined : readStoredMdnsHost(packageName)
1214
+ const mdnsHost = record.mdnsHost !== undefined ? record.mdnsHost.trim() || undefined : readStoredMdnsHost(packageName)
1179
1215
  const devRecord: DevAppRecord = {
1180
1216
  ...record,
1181
1217
  packageName,
@@ -15,7 +15,7 @@
15
15
  * - `share` hands a stored file to the OS share sheet.
16
16
  *
17
17
  * Layout (mirrors SimpleStorage's scoping):
18
- * bytes: Paths.document/glassly_blobs/{userId}/{packageName}/{fileName}
18
+ * bytes: Paths.document/blobs/{userId}/{packageName}/{fileName}
19
19
  * metadata: MMKV key glassly_blobmeta_{userId}_{packageName}_{key} → StoredBlobMeta JSON
20
20
  *
21
21
  * The on-disk file name is a generated id plus a mime-derived extension (iOS
@@ -39,7 +39,7 @@ const LOG_TAG = "LocalMiniappRuntime"
39
39
 
40
40
  /** Per-app blob quota: 1 GB. */
41
41
  export const BLOB_QUOTA_BYTES = 1024 * 1024 * 1024
42
- const ROOT_DIR_NAME = "glassly_blobs"
42
+ const ROOT_DIR_NAME = "blobs"
43
43
  /** Cache dir root holding short-lived, properly-named copies handed to the OS share sheet (one subdir per stored blob). */
44
44
  const SHARE_DIR_NAME = "blob_share"
45
45
  /**
@@ -115,7 +115,7 @@ export class BlobStore {
115
115
  * Move blob *bytes* from a device-local user directory into the account's on
116
116
  * first sign-in. The matching metadata keys are moved by
117
117
  * migrateLocalMiniappData(); this half owns the filesystem because the path
118
- * scheme (`glassly_blobs/{userId}/{pkg}/`) is private to BlobStore.
118
+ * scheme (`blobs/{userId}/{pkg}/`) is private to BlobStore.
119
119
  *
120
120
  * Per-package so an account directory that already exists wins for that
121
121
  * package only — mirroring the key-level "account data wins" rule instead of
@@ -14,7 +14,12 @@
14
14
  * this service.
15
15
  */
16
16
  import {CloudClient, setNativeHttp, setNativeUdp, setSecureStorage} from "@glassly/cloud-client/react-native"
17
- import type {PreinstalledMiniappRegistry, RuntimeSnapshot} from "@glassly/cloud-client/react-native"
17
+ import type {
18
+ PreinstalledMiniappRegistry,
19
+ RuntimeSnapshot,
20
+ StoreCatalogResponse,
21
+ StoreListing,
22
+ } from "@glassly/cloud-client/react-native"
18
23
  import type {SubjectTokenType} from "@glassly/cloud-client"
19
24
  import {Platform} from "react-native"
20
25
  import type {AudioSubscription, QuotaStatusPayload, TranscriptionData, TranslationData} from "@glassly/cloud-protocol"
@@ -206,8 +211,8 @@ async function syncCoreAccessTokenToBluetoothInternal(): Promise<string> {
206
211
  if (c !== client) {
207
212
  throw new Error("cloud client changed while syncing core token")
208
213
  }
209
- adoptLocalNamespace(c.auth.identity.glasslyUserId)
210
- localMiniappUserIdentity.remember(c.auth.identity.glasslyUserId)
214
+ adoptLocalNamespace(c.auth.identity.userId)
215
+ localMiniappUserIdentity.remember(c.auth.identity.userId)
211
216
  const result = await useSettingsStore.getState().setSetting(SETTINGS.core_token.key, token, false)
212
217
  if (result.is_error()) {
213
218
  throw result.error
@@ -380,7 +385,7 @@ function ensureAuthWatch(): void {
380
385
  try {
381
386
  cloudClientService.reconnect()
382
387
  } finally {
383
- setTimeout(() => {
388
+ BgTimer.setTimeout(() => {
384
389
  reconnectPending = false
385
390
  }, 0)
386
391
  }
@@ -734,6 +739,28 @@ export const cloudClientService = {
734
739
  return c.core.miniapps.getRegistry()
735
740
  },
736
741
 
742
+ async getStoreCatalog(): Promise<StoreCatalogResponse> {
743
+ if (!client) this.init()
744
+ const c = client
745
+ if (!c?.core) throw new Error("cloud client core is unavailable")
746
+ return c.core.store.list()
747
+ },
748
+
749
+ async getStoreListing(packageName: string): Promise<StoreListing> {
750
+ if (!client) this.init()
751
+ const c = client
752
+ if (!c?.core) throw new Error("cloud client core is unavailable")
753
+ return c.core.store.get(packageName)
754
+ },
755
+
756
+ /** Bytes of a store icon or screenshot; these routes need the user Bearer. */
757
+ async fetchStoreAsset(url: string): Promise<Uint8Array> {
758
+ if (!client) this.init()
759
+ const c = client
760
+ if (!c?.core) throw new Error("cloud client core is unavailable")
761
+ return c.core.store.fetchAsset(url)
762
+ },
763
+
737
764
  /**
738
765
  * Resolve the stable Core-owned Glassly user id.
739
766
  *
@@ -743,7 +770,7 @@ export const cloudClientService = {
743
770
  * callers join the auth module's single-flight exchange/refresh instead of
744
771
  * falling back to an anonymous namespace.
745
772
  */
746
- async resolveGlasslyUserId(): Promise<string> {
773
+ async resolveUserId(): Promise<string> {
747
774
  // With cloud off there is no client to exchange a token with and never will
748
775
  // be, so the online path below would throw on every storage call and take
749
776
  // offline-capable local miniapps down with it. Fall back to a device-local
@@ -759,14 +786,14 @@ export const cloudClientService = {
759
786
  if (c !== client) throw new Error("cloud client changed while resolving user identity")
760
787
  // Runs before resolve() persists the id, so the local namespace is adopted
761
788
  // whichever path reaches Core identity first (this or the token sync).
762
- adoptLocalNamespace(c.auth.identity.glasslyUserId)
763
- return c.auth.identity.glasslyUserId
789
+ adoptLocalNamespace(c.auth.identity.userId)
790
+ return c.auth.identity.userId
764
791
  })
765
792
  },
766
793
 
767
794
  /** Read the stable Glassly user id after async identity resolution. */
768
- getGlasslyUserId(): string {
769
- // Mirrors resolveGlasslyUserId(): with cloud off, minting is synchronous and
795
+ getUserId(): string {
796
+ // Mirrors resolveUserId(): with cloud off, minting is synchronous and
770
797
  // cannot fail, so sync callers (BlobStore) don't depend on an async resolve
771
798
  // having run first.
772
799
  if (cloudDisabled()) return localMiniappUserIdentity.resolveLocal()
@@ -786,7 +813,7 @@ export const cloudClientService = {
786
813
  const {token, expiresAt} = await c.auth.getMiniappToken(packageName, opts)
787
814
  const identity = c.auth.identity
788
815
  return {
789
- glasslyUserId: identity.glasslyUserId,
816
+ userId: identity.userId,
790
817
  tenantId: identity.tenantId,
791
818
  token,
792
819
  expiresAt: normalizeExpiresAt(expiresAt),
@@ -1,3 +1,5 @@
1
+ import {BgTimer} from "../utils/timers"
2
+
1
3
  /**
2
4
  * DevServerBridge — phone-side WebSocket connection to a `glassly-miniapp dev`
3
5
  * sidecar running on a developer's laptop.
@@ -44,7 +46,7 @@ interface BridgeEntry {
44
46
  ringBuffer: BufferedLog[]
45
47
  ringBytes: number
46
48
  reloadHandler: ((packageName: string) => void) | null
47
- reconnectTimer: ReturnType<typeof setTimeout> | null
49
+ reconnectTimer: number | null
48
50
  }
49
51
 
50
52
  class DevServerBridge {
@@ -116,7 +118,7 @@ class DevServerBridge {
116
118
  * side (`UIRouter.routeFromWebView` for `type:"log"` frames).
117
119
  *
118
120
  * `source` distinguishes the two halves so the CLI can prefix lines
119
- * `[UI]` vs `[GlasslyJS]`. Logs are silently dropped when no bridge
121
+ * `[UI]` vs `[JSRuntime]`. Logs are silently dropped when no bridge
120
122
  * exists for the package (no `glassly-miniapp dev` running) and
121
123
  * buffered in the per-bridge ring while disconnected.
122
124
  */
@@ -155,7 +157,7 @@ class DevServerBridge {
155
157
  .split(":")[0]
156
158
  .split("/")[0]
157
159
  }
158
- return `ws://${host}:${devPort}/__glassly_dev`
160
+ return `ws://${host}:${devPort}/__host_dev`
159
161
  }
160
162
 
161
163
  private openSocket(packageName: string, entry: BridgeEntry): void {
@@ -164,12 +166,12 @@ class DevServerBridge {
164
166
  const ws = new WebSocket(entry.url)
165
167
  entry.ws = ws
166
168
 
167
- let helloTimer: ReturnType<typeof setTimeout> | null = null
169
+ let helloTimer: number | null = null
168
170
  let helloAcked = false
169
171
 
170
172
  const teardown = (reason: string): void => {
171
173
  if (helloTimer) {
172
- clearTimeout(helloTimer)
174
+ BgTimer.clearTimeout(helloTimer)
173
175
  helloTimer = null
174
176
  }
175
177
  try {
@@ -195,7 +197,7 @@ class DevServerBridge {
195
197
  teardown("hello send failed")
196
198
  return
197
199
  }
198
- helloTimer = setTimeout(() => {
200
+ helloTimer = BgTimer.setTimeout(() => {
199
201
  if (!helloAcked) {
200
202
  teardown("hello-ack timeout")
201
203
  }
@@ -220,7 +222,7 @@ class DevServerBridge {
220
222
  }
221
223
  helloAcked = true
222
224
  if (helloTimer) {
223
- clearTimeout(helloTimer)
225
+ BgTimer.clearTimeout(helloTimer)
224
226
  helloTimer = null
225
227
  }
226
228
  entry.state = "connected"
@@ -257,9 +259,9 @@ class DevServerBridge {
257
259
 
258
260
  private scheduleReconnect(packageName: string, entry: BridgeEntry): void {
259
261
  if (entry.state === "closed") return
260
- if (entry.reconnectTimer) clearTimeout(entry.reconnectTimer)
262
+ if (entry.reconnectTimer) BgTimer.clearTimeout(entry.reconnectTimer)
261
263
  const delay = this.backoffMs(entry.attempts)
262
- entry.reconnectTimer = setTimeout(() => {
264
+ entry.reconnectTimer = BgTimer.setTimeout(() => {
263
265
  entry.reconnectTimer = null
264
266
  // Verify still alive and still in the bridge map.
265
267
  const current = this.entries.get(packageName)
@@ -316,7 +318,7 @@ class DevServerBridge {
316
318
 
317
319
  private teardownEntry(entry: BridgeEntry): void {
318
320
  if (entry.reconnectTimer) {
319
- clearTimeout(entry.reconnectTimer)
321
+ BgTimer.clearTimeout(entry.reconnectTimer)
320
322
  entry.reconnectTimer = null
321
323
  }
322
324
  if (entry.ws) {