@mentra/engine 0.1.0-beta.0 → 0.1.0-dev.1

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 (355) hide show
  1. package/README.md +42 -1
  2. package/build/engine.d.ts +11 -3
  3. package/build/engine.d.ts.map +1 -1
  4. package/build/engine.js +7 -2
  5. package/build/engine.js.map +1 -1
  6. package/build/facades/dev.d.ts.map +1 -1
  7. package/build/facades/dev.js +9 -5
  8. package/build/facades/dev.js.map +1 -1
  9. package/build/facades/gallery.js +1 -1
  10. package/build/facades/gallery.js.map +1 -1
  11. package/build/facades/glasses.d.ts +1 -0
  12. package/build/facades/glasses.d.ts.map +1 -1
  13. package/build/facades/glasses.js +19 -4
  14. package/build/facades/glasses.js.map +1 -1
  15. package/build/facades/glassesSettings.d.ts.map +1 -1
  16. package/build/facades/glassesSettings.js +1 -0
  17. package/build/facades/glassesSettings.js.map +1 -1
  18. package/build/facades/miniapps.d.ts +4 -0
  19. package/build/facades/miniapps.d.ts.map +1 -1
  20. package/build/facades/miniapps.js +5 -0
  21. package/build/facades/miniapps.js.map +1 -1
  22. package/build/facades/ota.d.ts +11 -2
  23. package/build/facades/ota.d.ts.map +1 -1
  24. package/build/facades/ota.js +19 -4
  25. package/build/facades/ota.js.map +1 -1
  26. package/build/facades/pairing.d.ts +4 -0
  27. package/build/facades/pairing.d.ts.map +1 -1
  28. package/build/facades/pairing.js +10 -8
  29. package/build/facades/pairing.js.map +1 -1
  30. package/build/facades/phoneNotifications.d.ts +0 -4
  31. package/build/facades/phoneNotifications.d.ts.map +1 -1
  32. package/build/facades/phoneNotifications.js +4 -14
  33. package/build/facades/phoneNotifications.js.map +1 -1
  34. package/build/index.d.ts +6 -3
  35. package/build/index.d.ts.map +1 -1
  36. package/build/index.js +4 -2
  37. package/build/index.js.map +1 -1
  38. package/build/internal.d.ts +2 -2
  39. package/build/internal.d.ts.map +1 -1
  40. package/build/internal.js +1 -1
  41. package/build/internal.js.map +1 -1
  42. package/build/react/MentraLiveOtaFlow.d.ts +38 -0
  43. package/build/react/MentraLiveOtaFlow.d.ts.map +1 -0
  44. package/build/react/MentraLiveOtaFlow.js +528 -0
  45. package/build/react/MentraLiveOtaFlow.js.map +1 -0
  46. package/build/react/index.d.ts +2 -0
  47. package/build/react/index.d.ts.map +1 -0
  48. package/build/react/index.js +2 -0
  49. package/build/react/index.js.map +1 -0
  50. package/build/react/useEngineSnapshot.d.ts +2 -0
  51. package/build/react/useEngineSnapshot.d.ts.map +1 -0
  52. package/build/react/useEngineSnapshot.js +14 -0
  53. package/build/react/useEngineSnapshot.js.map +1 -0
  54. package/build/runtime/bootstrap.d.ts +24 -1
  55. package/build/runtime/bootstrap.d.ts.map +1 -1
  56. package/build/runtime/bootstrap.js +17 -0
  57. package/build/runtime/bootstrap.js.map +1 -1
  58. package/build/runtime/scanQrSeam.d.ts +7 -0
  59. package/build/runtime/scanQrSeam.d.ts.map +1 -0
  60. package/build/runtime/scanQrSeam.js +16 -0
  61. package/build/runtime/scanQrSeam.js.map +1 -0
  62. package/build/services/AppRegistry.d.ts +18 -8
  63. package/build/services/AppRegistry.d.ts.map +1 -1
  64. package/build/services/AppRegistry.js +44 -45
  65. package/build/services/AppRegistry.js.map +1 -1
  66. package/build/services/AudioCloudUplink.d.ts +9 -3
  67. package/build/services/AudioCloudUplink.d.ts.map +1 -1
  68. package/build/services/AudioCloudUplink.js +9 -3
  69. package/build/services/AudioCloudUplink.js.map +1 -1
  70. package/build/services/AudioPlaybackService.d.ts +9 -1
  71. package/build/services/AudioPlaybackService.d.ts.map +1 -1
  72. package/build/services/AudioPlaybackService.js +77 -32
  73. package/build/services/AudioPlaybackService.js.map +1 -1
  74. package/build/services/BlobStore.d.ts +2 -1
  75. package/build/services/BlobStore.d.ts.map +1 -1
  76. package/build/services/BlobStore.js +17 -9
  77. package/build/services/BlobStore.js.map +1 -1
  78. package/build/services/CloudAudioSubscriptionSync.d.ts.map +1 -1
  79. package/build/services/CloudAudioSubscriptionSync.js +13 -1
  80. package/build/services/CloudAudioSubscriptionSync.js.map +1 -1
  81. package/build/services/CloudClientService.d.ts +15 -0
  82. package/build/services/CloudClientService.d.ts.map +1 -1
  83. package/build/services/CloudClientService.js +75 -0
  84. package/build/services/CloudClientService.js.map +1 -1
  85. package/build/services/ForegroundLocationPermission.d.ts +13 -0
  86. package/build/services/ForegroundLocationPermission.d.ts.map +1 -0
  87. package/build/services/ForegroundLocationPermission.js +12 -0
  88. package/build/services/ForegroundLocationPermission.js.map +1 -0
  89. package/build/services/GlassesSettingsSync.d.ts.map +1 -1
  90. package/build/services/GlassesSettingsSync.js +9 -3
  91. package/build/services/GlassesSettingsSync.js.map +1 -1
  92. package/build/services/GlassesStatusProjection.d.ts +2 -1
  93. package/build/services/GlassesStatusProjection.d.ts.map +1 -1
  94. package/build/services/GlassesStatusProjection.js +15 -8
  95. package/build/services/GlassesStatusProjection.js.map +1 -1
  96. package/build/services/HotspotOtaTransport.d.ts +29 -0
  97. package/build/services/HotspotOtaTransport.d.ts.map +1 -0
  98. package/build/services/HotspotOtaTransport.js +146 -0
  99. package/build/services/HotspotOtaTransport.js.map +1 -0
  100. package/build/services/HotspotShutdown.d.ts +17 -0
  101. package/build/services/HotspotShutdown.d.ts.map +1 -0
  102. package/build/services/HotspotShutdown.js +29 -0
  103. package/build/services/HotspotShutdown.js.map +1 -0
  104. package/build/services/LocalDisplayManager.d.ts +15 -0
  105. package/build/services/LocalDisplayManager.d.ts.map +1 -1
  106. package/build/services/LocalDisplayManager.js +106 -20
  107. package/build/services/LocalDisplayManager.js.map +1 -1
  108. package/build/services/LocalMiniappRuntime.d.ts +67 -1
  109. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  110. package/build/services/LocalMiniappRuntime.js +486 -126
  111. package/build/services/LocalMiniappRuntime.js.map +1 -1
  112. package/build/services/LocalMiniappStorage.d.ts +32 -0
  113. package/build/services/LocalMiniappStorage.d.ts.map +1 -0
  114. package/build/services/LocalMiniappStorage.js +66 -0
  115. package/build/services/LocalMiniappStorage.js.map +1 -0
  116. package/build/services/LocalMiniappUserIdentity.d.ts +20 -0
  117. package/build/services/LocalMiniappUserIdentity.d.ts.map +1 -0
  118. package/build/services/LocalMiniappUserIdentity.js +43 -0
  119. package/build/services/LocalMiniappUserIdentity.js.map +1 -0
  120. package/build/services/MicStateCoordinator.d.ts +42 -1
  121. package/build/services/MicStateCoordinator.d.ts.map +1 -1
  122. package/build/services/MicStateCoordinator.js +141 -3
  123. package/build/services/MicStateCoordinator.js.map +1 -1
  124. package/build/services/MiniappLauncher.d.ts.map +1 -1
  125. package/build/services/MiniappLauncher.js +23 -3
  126. package/build/services/MiniappLauncher.js.map +1 -1
  127. package/build/services/MiniappLiveness.d.ts +12 -0
  128. package/build/services/MiniappLiveness.d.ts.map +1 -0
  129. package/build/services/MiniappLiveness.js +16 -0
  130. package/build/services/MiniappLiveness.js.map +1 -0
  131. package/build/services/OtaArtifactDownloader.d.ts +65 -0
  132. package/build/services/OtaArtifactDownloader.d.ts.map +1 -0
  133. package/build/services/OtaArtifactDownloader.js +226 -0
  134. package/build/services/OtaArtifactDownloader.js.map +1 -0
  135. package/build/services/OtaAutoChain.d.ts +34 -0
  136. package/build/services/OtaAutoChain.d.ts.map +1 -0
  137. package/build/services/OtaAutoChain.js +83 -0
  138. package/build/services/OtaAutoChain.js.map +1 -0
  139. package/build/services/OtaErrorMapping.d.ts +18 -0
  140. package/build/services/OtaErrorMapping.d.ts.map +1 -0
  141. package/build/services/OtaErrorMapping.js +63 -0
  142. package/build/services/OtaErrorMapping.js.map +1 -0
  143. package/build/services/OtaInstallCoordinator.d.ts +94 -14
  144. package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
  145. package/build/services/OtaInstallCoordinator.js +574 -130
  146. package/build/services/OtaInstallCoordinator.js.map +1 -1
  147. package/build/services/OtaService.d.ts.map +1 -1
  148. package/build/services/OtaService.js +8 -1
  149. package/build/services/OtaService.js.map +1 -1
  150. package/build/services/OtaUpdateCheckService.d.ts +38 -3
  151. package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
  152. package/build/services/OtaUpdateCheckService.js +142 -22
  153. package/build/services/OtaUpdateCheckService.js.map +1 -1
  154. package/build/services/PhoneCalendarService.d.ts.map +1 -1
  155. package/build/services/PhoneCalendarService.js +22 -1
  156. package/build/services/PhoneCalendarService.js.map +1 -1
  157. package/build/services/PhoneCameraFovCoordinator.d.ts +2 -0
  158. package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -1
  159. package/build/services/PhoneCameraFovCoordinator.js +14 -0
  160. package/build/services/PhoneCameraFovCoordinator.js.map +1 -1
  161. package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
  162. package/build/services/PhoneNotificationsSync.js +12 -10
  163. package/build/services/PhoneNotificationsSync.js.map +1 -1
  164. package/build/services/PhonePhotoCoordinator.d.ts +10 -3
  165. package/build/services/PhonePhotoCoordinator.d.ts.map +1 -1
  166. package/build/services/PhonePhotoCoordinator.js +21 -3
  167. package/build/services/PhonePhotoCoordinator.js.map +1 -1
  168. package/build/services/PhoneStreamCoordinator.d.ts +8 -1
  169. package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
  170. package/build/services/PhoneStreamCoordinator.js +125 -13
  171. package/build/services/PhoneStreamCoordinator.js.map +1 -1
  172. package/build/services/PhoneVideoCoordinator.d.ts +2 -0
  173. package/build/services/PhoneVideoCoordinator.d.ts.map +1 -1
  174. package/build/services/PhoneVideoCoordinator.js +10 -0
  175. package/build/services/PhoneVideoCoordinator.js.map +1 -1
  176. package/build/services/SceneRenderer.d.ts.map +1 -1
  177. package/build/services/SceneRenderer.js +15 -0
  178. package/build/services/SceneRenderer.js.map +1 -1
  179. package/build/services/SupportProfileSync.d.ts +22 -0
  180. package/build/services/SupportProfileSync.d.ts.map +1 -0
  181. package/build/services/SupportProfileSync.js +213 -0
  182. package/build/services/SupportProfileSync.js.map +1 -0
  183. package/build/services/TtsTextSanitizer.d.ts +5 -0
  184. package/build/services/TtsTextSanitizer.d.ts.map +1 -0
  185. package/build/services/TtsTextSanitizer.js +61 -0
  186. package/build/services/TtsTextSanitizer.js.map +1 -0
  187. package/build/services/WifiAdbRequest.d.ts +17 -0
  188. package/build/services/WifiAdbRequest.d.ts.map +1 -0
  189. package/build/services/WifiAdbRequest.js +35 -0
  190. package/build/services/WifiAdbRequest.js.map +1 -0
  191. package/build/services/asg/asgCameraApi.d.ts +3 -0
  192. package/build/services/asg/asgCameraApi.d.ts.map +1 -1
  193. package/build/services/asg/asgCameraApi.js +72 -2
  194. package/build/services/asg/asgCameraApi.js.map +1 -1
  195. package/build/services/asg/gallerySyncService.d.ts.map +1 -1
  196. package/build/services/asg/gallerySyncService.js +26 -14
  197. package/build/services/asg/gallerySyncService.js.map +1 -1
  198. package/build/services/asg/localNetworkTransport.d.ts +2 -2
  199. package/build/services/asg/localNetworkTransport.d.ts.map +1 -1
  200. package/build/services/asg/localNetworkTransport.js +6 -6
  201. package/build/services/asg/localNetworkTransport.js.map +1 -1
  202. package/build/services/audioPlaybackAssets.d.ts +8 -0
  203. package/build/services/audioPlaybackAssets.d.ts.map +1 -0
  204. package/build/services/audioPlaybackAssets.js +7 -0
  205. package/build/services/audioPlaybackAssets.js.map +1 -0
  206. package/build/services/glassesClockSync.js +2 -2
  207. package/build/services/glassesClockSync.js.map +1 -1
  208. package/build/services/manifestActions.d.ts +7 -0
  209. package/build/services/manifestActions.d.ts.map +1 -0
  210. package/build/services/manifestActions.js +25 -0
  211. package/build/services/manifestActions.js.map +1 -0
  212. package/build/services/otaDisplayState.d.ts +22 -11
  213. package/build/services/otaDisplayState.d.ts.map +1 -1
  214. package/build/services/otaDisplayState.js +36 -14
  215. package/build/services/otaDisplayState.js.map +1 -1
  216. package/build/services/otaInstallPolicy.d.ts +15 -3
  217. package/build/services/otaInstallPolicy.d.ts.map +1 -1
  218. package/build/services/otaInstallPolicy.js +24 -3
  219. package/build/services/otaInstallPolicy.js.map +1 -1
  220. package/build/services/otaManifestUrl.d.ts +2 -0
  221. package/build/services/otaManifestUrl.d.ts.map +1 -0
  222. package/build/services/{asgOtaVersionUrl.js → otaManifestUrl.js} +15 -5
  223. package/build/services/otaManifestUrl.js.map +1 -0
  224. package/build/services/slimStreamStatus.d.ts +11 -0
  225. package/build/services/slimStreamStatus.d.ts.map +1 -1
  226. package/build/services/slimStreamStatus.js +14 -4
  227. package/build/services/slimStreamStatus.js.map +1 -1
  228. package/build/stores/apps.d.ts.map +1 -1
  229. package/build/stores/apps.js +11 -0
  230. package/build/stores/apps.js.map +1 -1
  231. package/build/stores/bluetoothSettingKeys.d.ts.map +1 -1
  232. package/build/stores/bluetoothSettingKeys.js +2 -0
  233. package/build/stores/bluetoothSettingKeys.js.map +1 -1
  234. package/build/stores/gallerySync.d.ts +2 -0
  235. package/build/stores/gallerySync.d.ts.map +1 -1
  236. package/build/stores/gallerySync.js +2 -0
  237. package/build/stores/gallerySync.js.map +1 -1
  238. package/build/stores/glasses.d.ts.map +1 -1
  239. package/build/stores/glasses.js +3 -0
  240. package/build/stores/glasses.js.map +1 -1
  241. package/build/stores/settings.d.ts +17 -0
  242. package/build/stores/settings.d.ts.map +1 -1
  243. package/build/stores/settings.js +152 -19
  244. package/build/stores/settings.js.map +1 -1
  245. package/build/types/applet.d.ts +2 -0
  246. package/build/types/applet.d.ts.map +1 -1
  247. package/build/types/applet.js.map +1 -1
  248. package/build/types/enums.d.ts +1 -0
  249. package/build/types/enums.d.ts.map +1 -1
  250. package/build/types/enums.js +1 -0
  251. package/build/types/enums.js.map +1 -1
  252. package/build/types/hardware.d.ts +1 -0
  253. package/build/types/hardware.d.ts.map +1 -1
  254. package/build/types/hardware.js +14 -0
  255. package/build/types/hardware.js.map +1 -1
  256. package/build/utils/configuredDevHost.d.ts +6 -0
  257. package/build/utils/configuredDevHost.d.ts.map +1 -0
  258. package/build/utils/configuredDevHost.js +19 -0
  259. package/build/utils/configuredDevHost.js.map +1 -0
  260. package/build/utils/devMiniappLaunch.d.ts +19 -8
  261. package/build/utils/devMiniappLaunch.d.ts.map +1 -1
  262. package/build/utils/devMiniappLaunch.js +144 -21
  263. package/build/utils/devMiniappLaunch.js.map +1 -1
  264. package/build/utils/diagnosticContext.d.ts.map +1 -1
  265. package/build/utils/diagnosticContext.js +15 -17
  266. package/build/utils/diagnosticContext.js.map +1 -1
  267. package/build/utils/hardware/hardware.d.ts.map +1 -1
  268. package/build/utils/hardware/hardware.js +7 -3
  269. package/build/utils/hardware/hardware.js.map +1 -1
  270. package/build/utils/miniappDiagnostics.d.ts +64 -0
  271. package/build/utils/miniappDiagnostics.d.ts.map +1 -0
  272. package/build/utils/miniappDiagnostics.js +173 -0
  273. package/build/utils/miniappDiagnostics.js.map +1 -0
  274. package/build/utils/timers/timers.d.ts.map +1 -1
  275. package/build/utils/timers/timers.js +55 -18
  276. package/build/utils/timers/timers.js.map +1 -1
  277. package/package.json +27 -18
  278. package/src/assets/silence.wav +0 -0
  279. package/src/engine.ts +7 -2
  280. package/src/facades/dev.ts +9 -5
  281. package/src/facades/gallery.ts +1 -1
  282. package/src/facades/glasses.ts +17 -4
  283. package/src/facades/glassesSettings.ts +5 -0
  284. package/src/facades/miniapps.ts +7 -0
  285. package/src/facades/ota.ts +19 -4
  286. package/src/facades/pairing.ts +11 -7
  287. package/src/facades/phoneNotifications.ts +4 -13
  288. package/src/index.ts +26 -2
  289. package/src/internal.ts +2 -1
  290. package/src/react/MentraLiveOtaFlow.tsx +856 -0
  291. package/src/react/index.ts +7 -0
  292. package/src/react/useEngineSnapshot.ts +16 -0
  293. package/src/runtime/bootstrap.ts +33 -1
  294. package/src/runtime/scanQrSeam.ts +20 -0
  295. package/src/services/AppRegistry.ts +72 -48
  296. package/src/services/AudioCloudUplink.ts +9 -3
  297. package/src/services/AudioPlaybackService.ts +94 -34
  298. package/src/services/BlobStore.ts +22 -9
  299. package/src/services/CloudAudioSubscriptionSync.ts +13 -1
  300. package/src/services/CloudClientService.ts +74 -0
  301. package/src/services/ForegroundLocationPermission.ts +24 -0
  302. package/src/services/GlassesSettingsSync.ts +9 -3
  303. package/src/services/GlassesStatusProjection.ts +16 -8
  304. package/src/services/HotspotOtaTransport.ts +184 -0
  305. package/src/services/HotspotShutdown.ts +41 -0
  306. package/src/services/LocalDisplayManager.ts +112 -21
  307. package/src/services/LocalMiniappRuntime.ts +576 -130
  308. package/src/services/LocalMiniappStorage.ts +82 -0
  309. package/src/services/LocalMiniappUserIdentity.ts +46 -0
  310. package/src/services/MicStateCoordinator.ts +169 -4
  311. package/src/services/MiniappLauncher.ts +30 -3
  312. package/src/services/MiniappLiveness.ts +24 -0
  313. package/src/services/OtaArtifactDownloader.ts +312 -0
  314. package/src/services/OtaAutoChain.ts +106 -0
  315. package/src/services/OtaErrorMapping.ts +80 -0
  316. package/src/services/OtaInstallCoordinator.ts +645 -143
  317. package/src/services/OtaService.ts +11 -5
  318. package/src/services/OtaUpdateCheckService.ts +180 -20
  319. package/src/services/PhoneCalendarService.ts +27 -4
  320. package/src/services/PhoneCameraFovCoordinator.ts +15 -0
  321. package/src/services/PhoneNotificationsSync.ts +12 -10
  322. package/src/services/PhonePhotoCoordinator.ts +33 -7
  323. package/src/services/PhoneStreamCoordinator.ts +139 -25
  324. package/src/services/PhoneVideoCoordinator.ts +11 -0
  325. package/src/services/SceneRenderer.ts +16 -0
  326. package/src/services/SupportProfileSync.ts +218 -0
  327. package/src/services/TtsTextSanitizer.ts +66 -0
  328. package/src/services/WifiAdbRequest.ts +53 -0
  329. package/src/services/asg/asgCameraApi.ts +99 -8
  330. package/src/services/asg/gallerySyncService.ts +28 -19
  331. package/src/services/asg/localNetworkTransport.ts +7 -11
  332. package/src/services/audioPlaybackAssets.ts +8 -0
  333. package/src/services/glassesClockSync.ts +2 -2
  334. package/src/services/manifestActions.ts +30 -0
  335. package/src/services/otaDisplayState.ts +57 -16
  336. package/src/services/otaInstallPolicy.ts +29 -3
  337. package/src/services/{asgOtaVersionUrl.ts → otaManifestUrl.ts} +16 -4
  338. package/src/services/slimStreamStatus.ts +16 -5
  339. package/src/stores/apps.ts +12 -0
  340. package/src/stores/bluetoothSettingKeys.ts +2 -0
  341. package/src/stores/gallerySync.ts +4 -0
  342. package/src/stores/glasses.ts +3 -0
  343. package/src/stores/settings.ts +174 -21
  344. package/src/types/applet.ts +2 -0
  345. package/src/types/enums.ts +2 -1
  346. package/src/types/hardware.ts +17 -0
  347. package/src/utils/configuredDevHost.ts +17 -0
  348. package/src/utils/devMiniappLaunch.ts +151 -23
  349. package/src/utils/diagnosticContext.ts +17 -17
  350. package/src/utils/hardware/hardware.ts +7 -9
  351. package/src/utils/miniappDiagnostics.ts +226 -0
  352. package/src/utils/timers/timers.ts +57 -21
  353. package/build/services/asgOtaVersionUrl.d.ts +0 -2
  354. package/build/services/asgOtaVersionUrl.d.ts.map +0 -1
  355. package/build/services/asgOtaVersionUrl.js.map +0 -1
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Phone-local SimpleStorage for bundled miniapps.
3
+ *
4
+ * Keys are scoped to the stable Mentra user id and package name. Access tokens
5
+ * must never be part of the namespace: Core access tokens rotate and are held
6
+ * in memory only, so using one makes every app restart look like a new user.
7
+ */
8
+ export interface LocalMiniappStorageBackend {
9
+ get(key: string): unknown | null;
10
+ has(key: string): boolean;
11
+ set(key: string, value: unknown): void;
12
+ remove(key: string): void;
13
+ keys(): string[];
14
+ }
15
+ export interface LocalMiniappStorageHooks {
16
+ getUserId: () => Promise<string>;
17
+ backend: LocalMiniappStorageBackend;
18
+ }
19
+ export declare class LocalMiniappStorage {
20
+ private readonly hooks;
21
+ constructor(hooks: LocalMiniappStorageHooks);
22
+ get(packageName: string, key: string): Promise<unknown | null>;
23
+ set(packageName: string, key: string, value: unknown): Promise<void>;
24
+ delete(packageName: string, key: string): Promise<void>;
25
+ keys(packageName: string): Promise<string[]>;
26
+ clear(packageName: string): Promise<void>;
27
+ has(packageName: string, key: string): Promise<boolean>;
28
+ getAll(packageName: string): Promise<Record<string, string>>;
29
+ setMultiple(packageName: string, values: Record<string, unknown>): Promise<void>;
30
+ private prefix;
31
+ }
32
+ //# sourceMappingURL=LocalMiniappStorage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalMiniappStorage.d.ts","sourceRoot":"","sources":["../../src/services/LocalMiniappStorage.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,0BAA0B;IACzC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAA;IAChC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IACzB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;IACtC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,IAAI,IAAI,MAAM,EAAE,CAAA;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IAChC,OAAO,EAAE,0BAA0B,CAAA;CACpC;AAID,qBAAa,mBAAmB;IAClB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,wBAAwB;IAEtD,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAI9D,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAQ5C,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOzC,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIvD,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAY5D,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;YAOxE,MAAM;CAKrB"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Phone-local SimpleStorage for bundled miniapps.
3
+ *
4
+ * Keys are scoped to the stable Mentra user id and package name. Access tokens
5
+ * must never be part of the namespace: Core access tokens rotate and are held
6
+ * in memory only, so using one makes every app restart look like a new user.
7
+ */
8
+ const KEY_ROOT = "mentraos_localstorage_";
9
+ export class LocalMiniappStorage {
10
+ hooks;
11
+ constructor(hooks) {
12
+ this.hooks = hooks;
13
+ }
14
+ async get(packageName, key) {
15
+ return this.hooks.backend.get((await this.prefix(packageName)) + key);
16
+ }
17
+ async set(packageName, key, value) {
18
+ this.hooks.backend.set((await this.prefix(packageName)) + key, value);
19
+ }
20
+ async delete(packageName, key) {
21
+ this.hooks.backend.remove((await this.prefix(packageName)) + key);
22
+ }
23
+ async keys(packageName) {
24
+ const prefix = await this.prefix(packageName);
25
+ return this.hooks.backend
26
+ .keys()
27
+ .filter((key) => key.startsWith(prefix))
28
+ .map((key) => key.slice(prefix.length));
29
+ }
30
+ async clear(packageName) {
31
+ const prefix = await this.prefix(packageName);
32
+ for (const key of this.hooks.backend.keys()) {
33
+ if (key.startsWith(prefix))
34
+ this.hooks.backend.remove(key);
35
+ }
36
+ }
37
+ async has(packageName, key) {
38
+ return this.hooks.backend.has((await this.prefix(packageName)) + key);
39
+ }
40
+ async getAll(packageName) {
41
+ const prefix = await this.prefix(packageName);
42
+ const values = {};
43
+ for (const key of this.hooks.backend.keys()) {
44
+ if (!key.startsWith(prefix))
45
+ continue;
46
+ if (!this.hooks.backend.has(key))
47
+ continue;
48
+ const value = this.hooks.backend.get(key);
49
+ values[key.slice(prefix.length)] = typeof value === "string" ? value : String(value ?? "");
50
+ }
51
+ return values;
52
+ }
53
+ async setMultiple(packageName, values) {
54
+ const prefix = await this.prefix(packageName);
55
+ for (const [key, value] of Object.entries(values)) {
56
+ this.hooks.backend.set(prefix + key, value ?? null);
57
+ }
58
+ }
59
+ async prefix(packageName) {
60
+ const userId = (await this.hooks.getUserId()).trim();
61
+ if (!userId)
62
+ throw new Error("Mentra user identity is unavailable");
63
+ return `${KEY_ROOT}${userId}_${packageName}_`;
64
+ }
65
+ }
66
+ //# sourceMappingURL=LocalMiniappStorage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalMiniappStorage.js","sourceRoot":"","sources":["../../src/services/LocalMiniappStorage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Phone-local SimpleStorage for bundled miniapps.\n *\n * Keys are scoped to the stable Mentra user id and package name. Access tokens\n * must never be part of the namespace: Core access tokens rotate and are held\n * in memory only, so using one makes every app restart look like a new user.\n */\n\nexport interface LocalMiniappStorageBackend {\n get(key: string): unknown | null\n has(key: string): boolean\n set(key: string, value: unknown): void\n remove(key: string): void\n keys(): string[]\n}\n\nexport interface LocalMiniappStorageHooks {\n getUserId: () => Promise<string>\n backend: LocalMiniappStorageBackend\n}\n\nconst KEY_ROOT = \"mentraos_localstorage_\"\n\nexport class LocalMiniappStorage {\n constructor(private readonly hooks: LocalMiniappStorageHooks) {}\n\n async get(packageName: string, key: string): Promise<unknown | null> {\n return this.hooks.backend.get((await this.prefix(packageName)) + key)\n }\n\n async set(packageName: string, key: string, value: unknown): Promise<void> {\n this.hooks.backend.set((await this.prefix(packageName)) + key, value)\n }\n\n async delete(packageName: string, key: string): Promise<void> {\n this.hooks.backend.remove((await this.prefix(packageName)) + key)\n }\n\n async keys(packageName: string): Promise<string[]> {\n const prefix = await this.prefix(packageName)\n return this.hooks.backend\n .keys()\n .filter((key) => key.startsWith(prefix))\n .map((key) => key.slice(prefix.length))\n }\n\n async clear(packageName: string): Promise<void> {\n const prefix = await this.prefix(packageName)\n for (const key of this.hooks.backend.keys()) {\n if (key.startsWith(prefix)) this.hooks.backend.remove(key)\n }\n }\n\n async has(packageName: string, key: string): Promise<boolean> {\n return this.hooks.backend.has((await this.prefix(packageName)) + key)\n }\n\n async getAll(packageName: string): Promise<Record<string, string>> {\n const prefix = await this.prefix(packageName)\n const values: Record<string, string> = {}\n for (const key of this.hooks.backend.keys()) {\n if (!key.startsWith(prefix)) continue\n if (!this.hooks.backend.has(key)) continue\n const value = this.hooks.backend.get(key)\n values[key.slice(prefix.length)] = typeof value === \"string\" ? value : String(value ?? \"\")\n }\n return values\n }\n\n async setMultiple(packageName: string, values: Record<string, unknown>): Promise<void> {\n const prefix = await this.prefix(packageName)\n for (const [key, value] of Object.entries(values)) {\n this.hooks.backend.set(prefix + key, value ?? null)\n }\n }\n\n private async prefix(packageName: string): Promise<string> {\n const userId = (await this.hooks.getUserId()).trim()\n if (!userId) throw new Error(\"Mentra user identity is unavailable\")\n return `${KEY_ROOT}${userId}_${packageName}_`\n }\n}\n"]}
@@ -0,0 +1,20 @@
1
+ export interface LocalMiniappUserIdentityBackend {
2
+ get(): string | null;
3
+ set(userId: string): void;
4
+ remove(): void;
5
+ }
6
+ /**
7
+ * Keeps the stable Mentra user id available to local miniapps across process
8
+ * restarts. The id is non-secret and is deliberately stored separately from
9
+ * the short-lived Core access token.
10
+ */
11
+ export declare class LocalMiniappUserIdentity {
12
+ private readonly backend;
13
+ private current;
14
+ constructor(backend: LocalMiniappUserIdentityBackend);
15
+ resolve(resolveOnline: () => Promise<string>): Promise<string>;
16
+ get(): string | null;
17
+ remember(userId: string): void;
18
+ forget(): void;
19
+ }
20
+ //# sourceMappingURL=LocalMiniappUserIdentity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalMiniappUserIdentity.d.ts","sourceRoot":"","sources":["../../src/services/LocalMiniappUserIdentity.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,+BAA+B;IAC9C,GAAG,IAAI,MAAM,GAAG,IAAI,CAAA;IACpB,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,MAAM,IAAI,IAAI,CAAA;CACf;AAED;;;;GAIG;AACH,qBAAa,wBAAwB;IAGvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,OAAO,CAAsB;gBAER,OAAO,EAAE,+BAA+B;IAE/D,OAAO,CAAC,aAAa,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAUpE,GAAG,IAAI,MAAM,GAAG,IAAI;IAQpB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAO9B,MAAM,IAAI,IAAI;CAIf"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Keeps the stable Mentra user id available to local miniapps across process
3
+ * restarts. The id is non-secret and is deliberately stored separately from
4
+ * the short-lived Core access token.
5
+ */
6
+ export class LocalMiniappUserIdentity {
7
+ backend;
8
+ current = null;
9
+ constructor(backend) {
10
+ this.backend = backend;
11
+ }
12
+ async resolve(resolveOnline) {
13
+ const available = this.get();
14
+ if (available)
15
+ return available;
16
+ const resolved = (await resolveOnline()).trim();
17
+ if (!resolved)
18
+ throw new Error("Mentra user identity is unavailable");
19
+ this.remember(resolved);
20
+ return resolved;
21
+ }
22
+ get() {
23
+ if (this.current)
24
+ return this.current;
25
+ const cached = this.backend.get()?.trim() ?? "";
26
+ if (!cached)
27
+ return null;
28
+ this.current = cached;
29
+ return cached;
30
+ }
31
+ remember(userId) {
32
+ const resolved = userId.trim();
33
+ if (!resolved)
34
+ throw new Error("Mentra user identity is unavailable");
35
+ this.backend.set(resolved);
36
+ this.current = resolved;
37
+ }
38
+ forget() {
39
+ this.current = null;
40
+ this.backend.remove();
41
+ }
42
+ }
43
+ //# sourceMappingURL=LocalMiniappUserIdentity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalMiniappUserIdentity.js","sourceRoot":"","sources":["../../src/services/LocalMiniappUserIdentity.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,MAAM,OAAO,wBAAwB;IAGN;IAFrB,OAAO,GAAkB,IAAI,CAAA;IAErC,YAA6B,OAAwC;QAAxC,YAAO,GAAP,OAAO,CAAiC;IAAG,CAAC;IAEzE,KAAK,CAAC,OAAO,CAAC,aAAoC;QAChD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC5B,IAAI,SAAS;YAAE,OAAO,SAAS,CAAA;QAE/B,MAAM,QAAQ,GAAG,CAAC,MAAM,aAAa,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QAC/C,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;QACrE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QACvB,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,GAAG;QACD,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC,OAAO,CAAA;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;QAC/C,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAA;QACxB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,OAAO,MAAM,CAAA;IACf,CAAC;IAED,QAAQ,CAAC,MAAc;QACrB,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;QAC9B,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;QACrE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC1B,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAA;IACzB,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QACnB,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAA;IACvB,CAAC;CACF","sourcesContent":["export interface LocalMiniappUserIdentityBackend {\n get(): string | null\n set(userId: string): void\n remove(): void\n}\n\n/**\n * Keeps the stable Mentra user id available to local miniapps across process\n * restarts. The id is non-secret and is deliberately stored separately from\n * the short-lived Core access token.\n */\nexport class LocalMiniappUserIdentity {\n private current: string | null = null\n\n constructor(private readonly backend: LocalMiniappUserIdentityBackend) {}\n\n async resolve(resolveOnline: () => Promise<string>): Promise<string> {\n const available = this.get()\n if (available) return available\n\n const resolved = (await resolveOnline()).trim()\n if (!resolved) throw new Error(\"Mentra user identity is unavailable\")\n this.remember(resolved)\n return resolved\n }\n\n get(): string | null {\n if (this.current) return this.current\n const cached = this.backend.get()?.trim() ?? \"\"\n if (!cached) return null\n this.current = cached\n return cached\n }\n\n remember(userId: string): void {\n const resolved = userId.trim()\n if (!resolved) throw new Error(\"Mentra user identity is unavailable\")\n this.backend.set(resolved)\n this.current = resolved\n }\n\n forget(): void {\n this.current = null\n this.backend.remove()\n }\n}\n"]}
@@ -7,10 +7,20 @@
7
7
  * This coordinator pushes the aggregate local requirement set to BluetoothSdk
8
8
  * so the mic runs whenever at least one local consumer needs it.
9
9
  */
10
+ type MicGate = "vad" | "loudnessGate";
11
+ interface ConfiguredMicGates {
12
+ vadEnabled?: boolean | null;
13
+ loudnessGateEnabled?: boolean | null;
14
+ }
10
15
  declare class MicStateCoordinator {
11
16
  private static instance;
12
17
  private localWantsPcm;
13
18
  private localWantsLc3;
19
+ private configuredVad;
20
+ private configuredLoudnessGate;
21
+ private readonly miniappVadOverrides;
22
+ private readonly miniappLoudnessGateOverrides;
23
+ private overrideSequence;
14
24
  private constructor();
15
25
  static getInstance(): MicStateCoordinator;
16
26
  /**
@@ -20,12 +30,43 @@ declare class MicStateCoordinator {
20
30
  setLocalRequirements(req: {
21
31
  pcm: boolean;
22
32
  lc3: boolean;
23
- }): void;
33
+ } & ConfiguredMicGates): void;
34
+ /**
35
+ * Apply a miniapp-owned gate override without changing the OS preference.
36
+ * Overrides are lifecycle-scoped and last-live-owner-wins independently for
37
+ * VAD and Barrier.
38
+ */
39
+ setMiniappGateOverride(packageName: string, gate: MicGate, enabled: boolean, configured?: ConfiguredMicGates): Promise<void>;
40
+ /**
41
+ * Remove every gate override owned by a miniapp. This is synchronous so
42
+ * unregister can drop ownership before recomputing aggregate mic state.
43
+ */
44
+ clearMiniappGateOverrides(packageName: string): boolean;
45
+ /** Re-apply the current runtime policy after an owner is released. */
46
+ syncEffectiveGatePolicy(configured?: ConfiguredMicGates): Promise<void>;
47
+ /**
48
+ * Preserve the runtime microphone contract when the persisted device
49
+ * settings are replayed (for example after a glasses reconnect). Active
50
+ * miniapp gate overrides replace the OS values, and raw PCM keeps VAD off
51
+ * until the last raw-audio consumer unsubscribes.
52
+ */
53
+ applyRuntimeOverrides(settings: Record<string, unknown>): Record<string, unknown>;
54
+ /**
55
+ * Apply the complete current gate policy without treating the input as an OS
56
+ * preference update. Used by debounced mic-requirement writes, whose queued
57
+ * gate values may be stale after an override is acquired or released.
58
+ */
59
+ applyEffectiveGatePolicy(settings: Record<string, unknown>): Record<string, unknown>;
60
+ private applyActiveRuntimeOverrides;
24
61
  /**
25
62
  * Push local requirements to BluetoothSdk. `should_send_pcm` is strictly for
26
63
  * on-device PCM consumers; cloud audio uses LC3 through AudioCloudUplink.
27
64
  */
28
65
  private applyUnion;
66
+ private rememberConfiguredGates;
67
+ private overridesFor;
68
+ private latestOverride;
69
+ private effectiveGatePatch;
29
70
  /**
30
71
  * Reset all requirements to off. Called during cleanup.
31
72
  */
@@ -1 +1 @@
1
- {"version":3,"file":"MicStateCoordinator.d.ts","sourceRoot":"","sources":["../../src/services/MicStateCoordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoBH,cAAM,mBAAmB;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAmC;IAG1D,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,aAAa,CAAQ;IAE7B,OAAO;WAEO,WAAW,IAAI,mBAAmB;IAOhD;;;OAGG;IACI,oBAAoB,CAAC,GAAG,EAAE;QAAC,GAAG,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,OAAO,CAAA;KAAC,GAAG,IAAI;IAOpE;;;OAGG;IACH,OAAO,CAAC,UAAU;IAiBlB;;OAEG;IACI,KAAK,IAAI,IAAI;IAMb,OAAO,IAAI,IAAI;CAKvB;AAED,QAAA,MAAM,mBAAmB,qBAAoC,CAAA;AAC7D,eAAe,mBAAmB,CAAA"}
1
+ {"version":3,"file":"MicStateCoordinator.d.ts","sourceRoot":"","sources":["../../src/services/MicStateCoordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,KAAK,OAAO,GAAG,KAAK,GAAG,cAAc,CAAA;AAOrC,UAAU,kBAAkB;IAC1B,UAAU,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAC3B,mBAAmB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;CACrC;AAkBD,cAAM,mBAAmB;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAmC;IAG1D,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,sBAAsB,CAAqB;IACnD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAkC;IACtE,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAkC;IAC/E,OAAO,CAAC,gBAAgB,CAAI;IAE5B,OAAO;WAEO,WAAW,IAAI,mBAAmB;IAOhD;;;OAGG;IACI,oBAAoB,CAAC,GAAG,EAAE;QAAC,GAAG,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,OAAO,CAAA;KAAC,GAAG,kBAAkB,GAAG,IAAI;IAQzF;;;;OAIG;IACU,sBAAsB,CACjC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,OAAO,EAChB,UAAU,GAAE,kBAAuB,GAClC,OAAO,CAAC,IAAI,CAAC;IAoBhB;;;OAGG;IACI,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAM9D,sEAAsE;IACzD,uBAAuB,CAAC,UAAU,GAAE,kBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxF;;;;;OAKG;IACI,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAaxF;;;;OAIG;IACI,wBAAwB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAO3F,OAAO,CAAC,2BAA2B;IAiBnC;;;OAGG;IACH,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,uBAAuB;IAW/B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,kBAAkB;IAmB1B;;OAEG;IACI,KAAK,IAAI,IAAI;IAMb,OAAO,IAAI,IAAI;CAOvB;AAED,QAAA,MAAM,mBAAmB,qBAAoC,CAAA;AAC7D,eAAe,mBAAmB,CAAA"}
@@ -14,7 +14,11 @@ const LOG_TAG = "MIC_COORDINATOR";
14
14
  * (wire v2 keeps BLE JSON small and infrequent). */
15
15
  const flushMicRequirementsPatch = createDebouncedPatchFlusher((patch) => {
16
16
  try {
17
- void Promise.resolve(BluetoothSdk.updateBluetoothSettings(patch)).catch((err) => {
17
+ // Resolve runtime overrides at flush time. A miniapp can acquire/release a
18
+ // gate override during the debounce window, and a captured stale value
19
+ // must not win after that lifecycle transition.
20
+ const runtimePatch = micStateCoordinator.applyEffectiveGatePolicy(patch);
21
+ void Promise.resolve(BluetoothSdk.updateBluetoothSettings(runtimePatch)).catch((err) => {
18
22
  console.error(`${LOG_TAG}: failed to apply mic requirements:`, err);
19
23
  });
20
24
  }
@@ -27,6 +31,11 @@ class MicStateCoordinator {
27
31
  // Local miniapp requirements (set when miniapps subscribe to audio streams)
28
32
  localWantsPcm = false;
29
33
  localWantsLc3 = false;
34
+ configuredVad;
35
+ configuredLoudnessGate;
36
+ miniappVadOverrides = new Map();
37
+ miniappLoudnessGateOverrides = new Map();
38
+ overrideSequence = 0;
30
39
  constructor() { }
31
40
  static getInstance() {
32
41
  if (!MicStateCoordinator.instance) {
@@ -41,9 +50,94 @@ class MicStateCoordinator {
41
50
  setLocalRequirements(req) {
42
51
  this.localWantsPcm = req.pcm;
43
52
  this.localWantsLc3 = req.lc3;
53
+ this.rememberConfiguredGates(req);
44
54
  console.log(`${LOG_TAG}: local requirements updated — pcm=${req.pcm} lc3=${req.lc3}`);
45
55
  this.applyUnion();
46
56
  }
57
+ /**
58
+ * Apply a miniapp-owned gate override without changing the OS preference.
59
+ * Overrides are lifecycle-scoped and last-live-owner-wins independently for
60
+ * VAD and Barrier.
61
+ */
62
+ async setMiniappGateOverride(packageName, gate, enabled, configured = {}) {
63
+ this.rememberConfiguredGates(configured);
64
+ const overrides = this.overridesFor(gate);
65
+ const previous = overrides.get(packageName);
66
+ const next = { enabled, order: ++this.overrideSequence };
67
+ overrides.set(packageName, next);
68
+ try {
69
+ await BluetoothSdk.updateBluetoothSettings(this.effectiveGatePatch());
70
+ }
71
+ catch (error) {
72
+ // Do not roll back a newer request from the same package that landed
73
+ // while this native write was in flight.
74
+ if (overrides.get(packageName) === next) {
75
+ if (previous)
76
+ overrides.set(packageName, previous);
77
+ else
78
+ overrides.delete(packageName);
79
+ }
80
+ throw error;
81
+ }
82
+ }
83
+ /**
84
+ * Remove every gate override owned by a miniapp. This is synchronous so
85
+ * unregister can drop ownership before recomputing aggregate mic state.
86
+ */
87
+ clearMiniappGateOverrides(packageName) {
88
+ const removedVad = this.miniappVadOverrides.delete(packageName);
89
+ const removedLoudness = this.miniappLoudnessGateOverrides.delete(packageName);
90
+ return removedVad || removedLoudness;
91
+ }
92
+ /** Re-apply the current runtime policy after an owner is released. */
93
+ async syncEffectiveGatePolicy(configured = {}) {
94
+ this.rememberConfiguredGates(configured);
95
+ const patch = this.effectiveGatePatch();
96
+ if (Object.keys(patch).length === 0)
97
+ return;
98
+ await BluetoothSdk.updateBluetoothSettings(patch);
99
+ }
100
+ /**
101
+ * Preserve the runtime microphone contract when the persisted device
102
+ * settings are replayed (for example after a glasses reconnect). Active
103
+ * miniapp gate overrides replace the OS values, and raw PCM keeps VAD off
104
+ * until the last raw-audio consumer unsubscribes.
105
+ */
106
+ applyRuntimeOverrides(settings) {
107
+ this.rememberConfiguredGates({
108
+ vadEnabled: typeof settings.voice_activity_detection_enabled === "boolean"
109
+ ? settings.voice_activity_detection_enabled
110
+ : undefined,
111
+ loudnessGateEnabled: typeof settings.loudness_gate_enabled === "boolean" ? settings.loudness_gate_enabled : undefined,
112
+ });
113
+ return this.applyActiveRuntimeOverrides(settings);
114
+ }
115
+ /**
116
+ * Apply the complete current gate policy without treating the input as an OS
117
+ * preference update. Used by debounced mic-requirement writes, whose queued
118
+ * gate values may be stale after an override is acquired or released.
119
+ */
120
+ applyEffectiveGatePolicy(settings) {
121
+ return {
122
+ ...settings,
123
+ ...this.effectiveGatePatch(),
124
+ };
125
+ }
126
+ applyActiveRuntimeOverrides(settings) {
127
+ const runtimeSettings = { ...settings };
128
+ const vadOverride = this.latestOverride(this.miniappVadOverrides);
129
+ const loudnessOverride = this.latestOverride(this.miniappLoudnessGateOverrides);
130
+ if (this.localWantsPcm) {
131
+ runtimeSettings.voice_activity_detection_enabled = false;
132
+ }
133
+ else if (vadOverride) {
134
+ runtimeSettings.voice_activity_detection_enabled = vadOverride.enabled;
135
+ }
136
+ if (loudnessOverride) {
137
+ runtimeSettings.loudness_gate_enabled = loudnessOverride.enabled;
138
+ }
139
+ return runtimeSettings;
140
+ }
47
141
  /**
48
142
  * Push local requirements to BluetoothSdk. `should_send_pcm` is strictly for
49
143
  * on-device PCM consumers; cloud audio uses LC3 through AudioCloudUplink.
@@ -56,11 +150,53 @@ class MicStateCoordinator {
56
150
  // )
57
151
  // The mic control plane is a direct btsdk call now (was a host setMicRequirements
58
152
  // hook) so a bare OEM streams audio without wiring it.
59
- flushMicRequirementsPatch({
153
+ const patch = {
60
154
  should_send_pcm: shouldSendPcm,
61
155
  should_send_lc3: shouldSendLc3,
62
156
  should_send_transcript: false,
63
- });
157
+ ...this.effectiveGatePatch(),
158
+ };
159
+ flushMicRequirementsPatch(patch);
160
+ }
161
+ rememberConfiguredGates(configured) {
162
+ // null means the connected device intentionally omits that setting.
163
+ // undefined means the caller is not updating the remembered preference.
164
+ if (configured.vadEnabled !== undefined) {
165
+ this.configuredVad = configured.vadEnabled ?? undefined;
166
+ }
167
+ if (configured.loudnessGateEnabled !== undefined) {
168
+ this.configuredLoudnessGate = configured.loudnessGateEnabled ?? undefined;
169
+ }
170
+ }
171
+ overridesFor(gate) {
172
+ return gate === "vad" ? this.miniappVadOverrides : this.miniappLoudnessGateOverrides;
173
+ }
174
+ latestOverride(overrides) {
175
+ let latest;
176
+ for (const entry of overrides.values()) {
177
+ if (!latest || entry.order > latest.order)
178
+ latest = entry;
179
+ }
180
+ return latest;
181
+ }
182
+ effectiveGatePatch() {
183
+ const patch = {};
184
+ const vadOverride = this.latestOverride(this.miniappVadOverrides);
185
+ const loudnessOverride = this.latestOverride(this.miniappLoudnessGateOverrides);
186
+ // Hardware VAD suppresses silence. Raw-audio consumers need a continuous
187
+ // timeline, so their requirement wins over both OS and miniapp VAD values.
188
+ if (this.localWantsPcm)
189
+ patch.voice_activity_detection_enabled = false;
190
+ else if (vadOverride)
191
+ patch.voice_activity_detection_enabled = vadOverride.enabled;
192
+ else if (this.configuredVad !== undefined)
193
+ patch.voice_activity_detection_enabled = this.configuredVad;
194
+ if (loudnessOverride)
195
+ patch.loudness_gate_enabled = loudnessOverride.enabled;
196
+ else if (this.configuredLoudnessGate !== undefined) {
197
+ patch.loudness_gate_enabled = this.configuredLoudnessGate;
198
+ }
199
+ return patch;
64
200
  }
65
201
  /**
66
202
  * Reset all requirements to off. Called during cleanup.
@@ -72,6 +208,8 @@ class MicStateCoordinator {
72
208
  }
73
209
  cleanup() {
74
210
  console.log(`${LOG_TAG}: cleanup()`);
211
+ this.miniappVadOverrides.clear();
212
+ this.miniappLoudnessGateOverrides.clear();
75
213
  this.reset();
76
214
  MicStateCoordinator.instance = null;
77
215
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MicStateCoordinator.js","sourceRoot":"","sources":["../../src/services/MicStateCoordinator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,YAAY,MAAM,gCAAgC,CAAA;AAEzD,OAAO,EAAC,2BAA2B,EAAC,MAAM,yBAAyB,CAAA;AAEnE,MAAM,OAAO,GAAG,iBAAiB,CAAA;AAEjC;qDACqD;AACrD,MAAM,yBAAyB,GAAG,2BAA2B,CAA0B,CAAC,KAAK,EAAE,EAAE;IAC/F,IAAI,CAAC;QACH,KAAK,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YAC9E,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,qCAAqC,EAAE,GAAG,CAAC,CAAA;QACrE,CAAC,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,qCAAqC,EAAE,GAAG,CAAC,CAAA;IACrE,CAAC;AACH,CAAC,EAAE,GAAG,CAAC,CAAA;AAEP,MAAM,mBAAmB;IACf,MAAM,CAAC,QAAQ,GAA+B,IAAI,CAAA;IAE1D,4EAA4E;IACpE,aAAa,GAAG,KAAK,CAAA;IACrB,aAAa,GAAG,KAAK,CAAA;IAE7B,gBAAuB,CAAC;IAEjB,MAAM,CAAC,WAAW;QACvB,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC;YAClC,mBAAmB,CAAC,QAAQ,GAAG,IAAI,mBAAmB,EAAE,CAAA;QAC1D,CAAC;QACD,OAAO,mBAAmB,CAAC,QAAQ,CAAA;IACrC,CAAC;IAED;;;OAGG;IACI,oBAAoB,CAAC,GAAiC;QAC3D,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC,GAAG,CAAA;QAC5B,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC,GAAG,CAAA;QAC5B,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,sCAAsC,GAAG,CAAC,GAAG,QAAQ,GAAG,CAAC,GAAG,EAAE,CAAC,CAAA;QACrF,IAAI,CAAC,UAAU,EAAE,CAAA;IACnB,CAAC;IAED;;;OAGG;IACK,UAAU;QAChB,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAA;QACxC,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAA;QAExC,eAAe;QACf,qFAAqF;QACrF,IAAI;QAEJ,kFAAkF;QAClF,uDAAuD;QACvD,yBAAyB,CAAC;YACxB,eAAe,EAAE,aAAa;YAC9B,eAAe,EAAE,aAAa;YAC9B,sBAAsB,EAAE,KAAK;SAC9B,CAAC,CAAA;IACJ,CAAC;IAED;;OAEG;IACI,KAAK;QACV,IAAI,CAAC,aAAa,GAAG,KAAK,CAAA;QAC1B,IAAI,CAAC,aAAa,GAAG,KAAK,CAAA;QAC1B,IAAI,CAAC,UAAU,EAAE,CAAA;IACnB,CAAC;IAEM,OAAO;QACZ,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,aAAa,CAAC,CAAA;QACpC,IAAI,CAAC,KAAK,EAAE,CAAA;QACZ,mBAAmB,CAAC,QAAQ,GAAG,IAAI,CAAA;IACrC,CAAC;;AAGH,MAAM,mBAAmB,GAAG,mBAAmB,CAAC,WAAW,EAAE,CAAA;AAC7D,eAAe,mBAAmB,CAAA","sourcesContent":["/**\n * MicStateCoordinator\n *\n * Owns local-miniapp-driven microphone requirements.\n *\n * Local miniapps subscribe to audio_chunk / transcription streams.\n * This coordinator pushes the aggregate local requirement set to BluetoothSdk\n * so the mic runs whenever at least one local consumer needs it.\n */\n\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\n\nimport {createDebouncedPatchFlusher} from \"../utils/debouncedPatch\"\n\nconst LOG_TAG = \"MIC_COORDINATOR\"\n\n/** Mic-requirement flips are debounced (300ms) and merged into one BLE write\n * (wire v2 keeps BLE JSON small and infrequent). */\nconst flushMicRequirementsPatch = createDebouncedPatchFlusher<Record<string, unknown>>((patch) => {\n try {\n void Promise.resolve(BluetoothSdk.updateBluetoothSettings(patch)).catch((err) => {\n console.error(`${LOG_TAG}: failed to apply mic requirements:`, err)\n })\n } catch (err) {\n console.error(`${LOG_TAG}: failed to apply mic requirements:`, err)\n }\n}, 300)\n\nclass MicStateCoordinator {\n private static instance: MicStateCoordinator | null = null\n\n // Local miniapp requirements (set when miniapps subscribe to audio streams)\n private localWantsPcm = false\n private localWantsLc3 = false\n\n private constructor() {}\n\n public static getInstance(): MicStateCoordinator {\n if (!MicStateCoordinator.instance) {\n MicStateCoordinator.instance = new MicStateCoordinator()\n }\n return MicStateCoordinator.instance\n }\n\n /**\n * Update local miniapp requirements. Called by LocalMiniappRuntime when\n * the aggregated set of local subscriptions changes.\n */\n public setLocalRequirements(req: {pcm: boolean; lc3: boolean}): void {\n this.localWantsPcm = req.pcm\n this.localWantsLc3 = req.lc3\n console.log(`${LOG_TAG}: local requirements updated — pcm=${req.pcm} lc3=${req.lc3}`)\n this.applyUnion()\n }\n\n /**\n * Push local requirements to BluetoothSdk. `should_send_pcm` is strictly for\n * on-device PCM consumers; cloud audio uses LC3 through AudioCloudUplink.\n */\n private applyUnion(): void {\n const shouldSendPcm = this.localWantsPcm\n const shouldSendLc3 = this.localWantsLc3\n\n // console.log(\n // `${LOG_TAG}: applying requirements — pcm=${shouldSendPcm} lc3=${shouldSendLc3}`,\n // )\n\n // The mic control plane is a direct btsdk call now (was a host setMicRequirements\n // hook) so a bare OEM streams audio without wiring it.\n flushMicRequirementsPatch({\n should_send_pcm: shouldSendPcm,\n should_send_lc3: shouldSendLc3,\n should_send_transcript: false,\n })\n }\n\n /**\n * Reset all requirements to off. Called during cleanup.\n */\n public reset(): void {\n this.localWantsPcm = false\n this.localWantsLc3 = false\n this.applyUnion()\n }\n\n public cleanup(): void {\n console.log(`${LOG_TAG}: cleanup()`)\n this.reset()\n MicStateCoordinator.instance = null\n }\n}\n\nconst micStateCoordinator = MicStateCoordinator.getInstance()\nexport default micStateCoordinator\n"]}
1
+ {"version":3,"file":"MicStateCoordinator.js","sourceRoot":"","sources":["../../src/services/MicStateCoordinator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MicStateCoordinator\n *\n * Owns local-miniapp-driven microphone requirements.\n *\n * Local miniapps subscribe to audio_chunk / transcription streams.\n * This coordinator pushes the aggregate local requirement set to BluetoothSdk\n * so the mic runs whenever at least one local consumer needs it.\n */\n\nimport BluetoothSdk from \"@mentra/bluetooth-sdk/internal\"\n\nimport {createDebouncedPatchFlusher} from \"../utils/debouncedPatch\"\n\nconst LOG_TAG = \"MIC_COORDINATOR\"\n\ntype MicGate = \"vad\" | \"loudnessGate\"\n\ninterface GateOverride {\n enabled: boolean\n order: number\n}\n\ninterface ConfiguredMicGates {\n vadEnabled?: boolean | null\n loudnessGateEnabled?: boolean | null\n}\n\n/** Mic-requirement flips are debounced (300ms) and merged into one BLE write\n * (wire v2 keeps BLE JSON small and infrequent). */\nconst flushMicRequirementsPatch = createDebouncedPatchFlusher<Record<string, unknown>>((patch) => {\n try {\n // Resolve runtime overrides at flush time. A miniapp can acquire/release a\n // gate override during the debounce window, and a captured stale value\n // must not win after that lifecycle transition.\n const runtimePatch = micStateCoordinator.applyEffectiveGatePolicy(patch)\n void Promise.resolve(BluetoothSdk.updateBluetoothSettings(runtimePatch)).catch((err) => {\n console.error(`${LOG_TAG}: failed to apply mic requirements:`, err)\n })\n } catch (err) {\n console.error(`${LOG_TAG}: failed to apply mic requirements:`, err)\n }\n}, 300)\n\nclass MicStateCoordinator {\n private static instance: MicStateCoordinator | null = null\n\n // Local miniapp requirements (set when miniapps subscribe to audio streams)\n private localWantsPcm = false\n private localWantsLc3 = false\n private configuredVad: boolean | undefined\n private configuredLoudnessGate: boolean | undefined\n private readonly miniappVadOverrides = new Map<string, GateOverride>()\n private readonly miniappLoudnessGateOverrides = new Map<string, GateOverride>()\n private overrideSequence = 0\n\n private constructor() {}\n\n public static getInstance(): MicStateCoordinator {\n if (!MicStateCoordinator.instance) {\n MicStateCoordinator.instance = new MicStateCoordinator()\n }\n return MicStateCoordinator.instance\n }\n\n /**\n * Update local miniapp requirements. Called by LocalMiniappRuntime when\n * the aggregated set of local subscriptions changes.\n */\n public setLocalRequirements(req: {pcm: boolean; lc3: boolean} & ConfiguredMicGates): void {\n this.localWantsPcm = req.pcm\n this.localWantsLc3 = req.lc3\n this.rememberConfiguredGates(req)\n console.log(`${LOG_TAG}: local requirements updated — pcm=${req.pcm} lc3=${req.lc3}`)\n this.applyUnion()\n }\n\n /**\n * Apply a miniapp-owned gate override without changing the OS preference.\n * Overrides are lifecycle-scoped and last-live-owner-wins independently for\n * VAD and Barrier.\n */\n public async setMiniappGateOverride(\n packageName: string,\n gate: MicGate,\n enabled: boolean,\n configured: ConfiguredMicGates = {},\n ): Promise<void> {\n this.rememberConfiguredGates(configured)\n const overrides = this.overridesFor(gate)\n const previous = overrides.get(packageName)\n const next = {enabled, order: ++this.overrideSequence}\n overrides.set(packageName, next)\n\n try {\n await BluetoothSdk.updateBluetoothSettings(this.effectiveGatePatch())\n } catch (error) {\n // Do not roll back a newer request from the same package that landed\n // while this native write was in flight.\n if (overrides.get(packageName) === next) {\n if (previous) overrides.set(packageName, previous)\n else overrides.delete(packageName)\n }\n throw error\n }\n }\n\n /**\n * Remove every gate override owned by a miniapp. This is synchronous so\n * unregister can drop ownership before recomputing aggregate mic state.\n */\n public clearMiniappGateOverrides(packageName: string): boolean {\n const removedVad = this.miniappVadOverrides.delete(packageName)\n const removedLoudness = this.miniappLoudnessGateOverrides.delete(packageName)\n return removedVad || removedLoudness\n }\n\n /** Re-apply the current runtime policy after an owner is released. */\n public async syncEffectiveGatePolicy(configured: ConfiguredMicGates = {}): Promise<void> {\n this.rememberConfiguredGates(configured)\n const patch = this.effectiveGatePatch()\n if (Object.keys(patch).length === 0) return\n await BluetoothSdk.updateBluetoothSettings(patch)\n }\n\n /**\n * Preserve the runtime microphone contract when the persisted device\n * settings are replayed (for example after a glasses reconnect). Active\n * miniapp gate overrides replace the OS values, and raw PCM keeps VAD off\n * until the last raw-audio consumer unsubscribes.\n */\n public applyRuntimeOverrides(settings: Record<string, unknown>): Record<string, unknown> {\n this.rememberConfiguredGates({\n vadEnabled:\n typeof settings.voice_activity_detection_enabled === \"boolean\"\n ? settings.voice_activity_detection_enabled\n : undefined,\n loudnessGateEnabled:\n typeof settings.loudness_gate_enabled === \"boolean\" ? settings.loudness_gate_enabled : undefined,\n })\n\n return this.applyActiveRuntimeOverrides(settings)\n }\n\n /**\n * Apply the complete current gate policy without treating the input as an OS\n * preference update. Used by debounced mic-requirement writes, whose queued\n * gate values may be stale after an override is acquired or released.\n */\n public applyEffectiveGatePolicy(settings: Record<string, unknown>): Record<string, unknown> {\n return {\n ...settings,\n ...this.effectiveGatePatch(),\n }\n }\n\n private applyActiveRuntimeOverrides(settings: Record<string, unknown>): Record<string, unknown> {\n const runtimeSettings = {...settings}\n const vadOverride = this.latestOverride(this.miniappVadOverrides)\n const loudnessOverride = this.latestOverride(this.miniappLoudnessGateOverrides)\n\n if (this.localWantsPcm) {\n runtimeSettings.voice_activity_detection_enabled = false\n } else if (vadOverride) {\n runtimeSettings.voice_activity_detection_enabled = vadOverride.enabled\n }\n if (loudnessOverride) {\n runtimeSettings.loudness_gate_enabled = loudnessOverride.enabled\n }\n\n return runtimeSettings\n }\n\n /**\n * Push local requirements to BluetoothSdk. `should_send_pcm` is strictly for\n * on-device PCM consumers; cloud audio uses LC3 through AudioCloudUplink.\n */\n private applyUnion(): void {\n const shouldSendPcm = this.localWantsPcm\n const shouldSendLc3 = this.localWantsLc3\n\n // console.log(\n // `${LOG_TAG}: applying requirements — pcm=${shouldSendPcm} lc3=${shouldSendLc3}`,\n // )\n\n // The mic control plane is a direct btsdk call now (was a host setMicRequirements\n // hook) so a bare OEM streams audio without wiring it.\n const patch: Record<string, unknown> = {\n should_send_pcm: shouldSendPcm,\n should_send_lc3: shouldSendLc3,\n should_send_transcript: false,\n ...this.effectiveGatePatch(),\n }\n\n flushMicRequirementsPatch(patch)\n }\n\n private rememberConfiguredGates(configured: ConfiguredMicGates): void {\n // null means the connected device intentionally omits that setting.\n // undefined means the caller is not updating the remembered preference.\n if (configured.vadEnabled !== undefined) {\n this.configuredVad = configured.vadEnabled ?? undefined\n }\n if (configured.loudnessGateEnabled !== undefined) {\n this.configuredLoudnessGate = configured.loudnessGateEnabled ?? undefined\n }\n }\n\n private overridesFor(gate: MicGate): Map<string, GateOverride> {\n return gate === \"vad\" ? this.miniappVadOverrides : this.miniappLoudnessGateOverrides\n }\n\n private latestOverride(overrides: Map<string, GateOverride>): GateOverride | undefined {\n let latest: GateOverride | undefined\n for (const entry of overrides.values()) {\n if (!latest || entry.order > latest.order) latest = entry\n }\n return latest\n }\n\n private effectiveGatePatch(): Record<string, unknown> {\n const patch: Record<string, unknown> = {}\n const vadOverride = this.latestOverride(this.miniappVadOverrides)\n const loudnessOverride = this.latestOverride(this.miniappLoudnessGateOverrides)\n\n // Hardware VAD suppresses silence. Raw-audio consumers need a continuous\n // timeline, so their requirement wins over both OS and miniapp VAD values.\n if (this.localWantsPcm) patch.voice_activity_detection_enabled = false\n else if (vadOverride) patch.voice_activity_detection_enabled = vadOverride.enabled\n else if (this.configuredVad !== undefined) patch.voice_activity_detection_enabled = this.configuredVad\n\n if (loudnessOverride) patch.loudness_gate_enabled = loudnessOverride.enabled\n else if (this.configuredLoudnessGate !== undefined) {\n patch.loudness_gate_enabled = this.configuredLoudnessGate\n }\n\n return patch\n }\n\n /**\n * Reset all requirements to off. Called during cleanup.\n */\n public reset(): void {\n this.localWantsPcm = false\n this.localWantsLc3 = false\n this.applyUnion()\n }\n\n public cleanup(): void {\n console.log(`${LOG_TAG}: cleanup()`)\n this.miniappVadOverrides.clear()\n this.miniappLoudnessGateOverrides.clear()\n this.reset()\n MicStateCoordinator.instance = null\n }\n}\n\nconst micStateCoordinator = MicStateCoordinator.getInstance()\nexport default micStateCoordinator\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"MiniappLauncher.d.ts","sourceRoot":"","sources":["../../src/services/MiniappLauncher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAQH,OAA4B,EAAC,KAAK,wBAAwB,EAAC,MAAM,uBAAuB,CAAA;AACxF,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAEpD,UAAU,YAAY;IACpB,oEAAoE;IACpE,MAAM,EAAE,cAAc,CAAA;CACvB;AAED,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7B,iBAAiB,CAAC,EAAE,wBAAwB,CAAA;IAC5C,yEAAyE;IACzE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED,uDAAuD;AACvD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,cAAM,eAAe;IACnB,OAAO,CAAC,IAAI,CAA4B;IAExC;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2C;IAEpE,uEAAuE;IACvE,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAInC,OAAO,CAAC,aAAa;IAOrB,yEAAyE;IACzE,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIvC;;;;;;OAMG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAmF7F;;;;;;;;;;OAUG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAwBpF,iFAAiF;YACnE,KAAK;IAiCnB;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACG,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB7C;;;;OAIG;IACG,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,gBAAgB,SAAS,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzG,mDAAmD;IAC7C,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB9C,OAAO,CAAC,YAAY;IAKpB,4EAA4E;IAC5E,OAAO,CAAC,cAAc;CASvB;AAED,eAAO,MAAM,eAAe,iBAAwB,CAAA"}
1
+ {"version":3,"file":"MiniappLauncher.d.ts","sourceRoot":"","sources":["../../src/services/MiniappLauncher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAQH,OAA4B,EAAC,KAAK,wBAAwB,EAAC,MAAM,uBAAuB,CAAA;AACxF,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAEpD,UAAU,YAAY;IACpB,oEAAoE;IACpE,MAAM,EAAE,cAAc,CAAA;CACvB;AAED,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7B,iBAAiB,CAAC,EAAE,wBAAwB,CAAA;IAC5C,yEAAyE;IACzE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED,uDAAuD;AACvD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,cAAM,eAAe;IACnB,OAAO,CAAC,IAAI,CAA4B;IAExC;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2C;IAEpE,uEAAuE;IACvE,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAInC,OAAO,CAAC,aAAa;IAOrB,yEAAyE;IACzE,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIvC;;;;;;OAMG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IA8G7F;;;;;;;;;;OAUG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAwBpF,iFAAiF;YACnE,KAAK;IAiCnB;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACG,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB7C;;;;OAIG;IACG,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,gBAAgB,SAAS,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzG,mDAAmD;IAC7C,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB9C,OAAO,CAAC,YAAY;IAKpB,4EAA4E;IAC5E,OAAO,CAAC,cAAc;CASvB;AAED,eAAO,MAAM,eAAe,iBAAwB,CAAA"}
@@ -70,7 +70,9 @@ class MiniappLauncher {
70
70
  const entry = manifest.entry;
71
71
  if (!entry?.background)
72
72
  return null;
73
- const base = devUrl.replace(/\/$/, "");
73
+ // Use the host that actually answered — may differ from the stored IP
74
+ // after a laptop Wi-Fi change (mDNS / Metro failover inside decideDevLaunchRoute).
75
+ const base = route.resolvedUrl.replace(/\/$/, "");
74
76
  // entry.* are bundle-root paths (dist/ stripped); the dev server serves
75
77
  // files relative to cwd, so prepend dist/.
76
78
  const bgUrl = `${base}/dist/${entry.background.replace(/^\.?\/+/, "")}`;
@@ -80,9 +82,16 @@ class MiniappLauncher {
80
82
  .map((p) => (typeof p === "string" ? p : p?.type))
81
83
  .filter((t) => typeof t === "string");
82
84
  const installedManifest = {
85
+ packageName: typeof manifest.packageName === "string" ? manifest.packageName : packageName,
83
86
  name: manifest.name,
87
+ version: typeof manifest.version === "string" ? manifest.version : undefined,
88
+ sdkVersion: typeof manifest.sdkVersion === "string" ? manifest.sdkVersion : undefined,
89
+ minHostVersion: typeof manifest.minHostVersion === "string" ? manifest.minHostVersion : undefined,
90
+ type: typeof manifest.type === "string" ? manifest.type : undefined,
91
+ entry: manifest.entry,
84
92
  permissions: manifest.permissions,
85
93
  hardwareRequirements: manifest.hardwareRequirements,
94
+ actions: manifest.actions,
86
95
  };
87
96
  let bgSource;
88
97
  try {
@@ -100,7 +109,7 @@ class MiniappLauncher {
100
109
  uiBaseDir: uiUri ? uiUri.replace(/\/[^/]+$/, "/") : null,
101
110
  declaredPermissions,
102
111
  installedManifest,
103
- devUrl,
112
+ devUrl: route.resolvedUrl,
104
113
  devPort: this.resolveDevPort(hints?.devPort, packageName),
105
114
  };
106
115
  }
@@ -116,7 +125,18 @@ class MiniappLauncher {
116
125
  .map((p) => p.type)
117
126
  .filter((t) => typeof t === "string");
118
127
  const installedManifest = manifest
119
- ? { name: manifest.name, permissions: manifest.permissions, hardwareRequirements: manifest.hardwareRequirements }
128
+ ? {
129
+ packageName: manifest.packageName ?? packageName,
130
+ name: manifest.name,
131
+ version: manifest.version ?? version,
132
+ sdkVersion: manifest.sdkVersion,
133
+ minHostVersion: manifest.minHostVersion,
134
+ type: manifest.type,
135
+ entry: manifest.entry,
136
+ permissions: manifest.permissions,
137
+ hardwareRequirements: manifest.hardwareRequirements,
138
+ actions: manifest.actions,
139
+ }
120
140
  : undefined;
121
141
  let bgSource;
122
142
  try {