@glassly/engine 0.1.0-dev.1 → 0.1.0-dev.26

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 (277) hide show
  1. package/README.md +53 -19
  2. package/build/bluetooth-sdk/debug.d.ts +2 -0
  3. package/build/bluetooth-sdk/debug.d.ts.map +1 -0
  4. package/build/bluetooth-sdk/debug.js +2 -0
  5. package/build/bluetooth-sdk/debug.js.map +1 -0
  6. package/build/bluetooth-sdk/index.d.ts +3 -0
  7. package/build/bluetooth-sdk/index.d.ts.map +1 -0
  8. package/build/bluetooth-sdk/index.js +3 -0
  9. package/build/bluetooth-sdk/index.js.map +1 -0
  10. package/build/bluetooth-sdk/ota-transport.d.ts +2 -0
  11. package/build/bluetooth-sdk/ota-transport.d.ts.map +1 -0
  12. package/build/bluetooth-sdk/ota-transport.js +2 -0
  13. package/build/bluetooth-sdk/ota-transport.js.map +1 -0
  14. package/build/bluetooth-sdk/photo-receiver.d.ts +3 -0
  15. package/build/bluetooth-sdk/photo-receiver.d.ts.map +1 -0
  16. package/build/bluetooth-sdk/photo-receiver.js +3 -0
  17. package/build/bluetooth-sdk/photo-receiver.js.map +1 -0
  18. package/build/bluetooth-sdk/react.d.ts +2 -0
  19. package/build/bluetooth-sdk/react.d.ts.map +1 -0
  20. package/build/bluetooth-sdk/react.js +2 -0
  21. package/build/bluetooth-sdk/react.js.map +1 -0
  22. package/build/bluetooth-sdk/types.d.ts +2 -0
  23. package/build/bluetooth-sdk/types.d.ts.map +1 -0
  24. package/build/bluetooth-sdk/types.js +2 -0
  25. package/build/bluetooth-sdk/types.js.map +1 -0
  26. package/build/engine.d.ts +23 -16
  27. package/build/engine.d.ts.map +1 -1
  28. package/build/engine.js +9 -3
  29. package/build/engine.js.map +1 -1
  30. package/build/facades/dev.d.ts +1 -1
  31. package/build/facades/display.d.ts +1 -1
  32. package/build/facades/display.d.ts.map +1 -1
  33. package/build/facades/display.js +1 -1
  34. package/build/facades/display.js.map +1 -1
  35. package/build/facades/glasses.d.ts +5 -13
  36. package/build/facades/glasses.d.ts.map +1 -1
  37. package/build/facades/glasses.js +5 -3
  38. package/build/facades/glasses.js.map +1 -1
  39. package/build/facades/ota.d.ts +19 -21
  40. package/build/facades/ota.d.ts.map +1 -1
  41. package/build/facades/ota.js +23 -9
  42. package/build/facades/ota.js.map +1 -1
  43. package/build/facades/pairing.d.ts +11 -5
  44. package/build/facades/pairing.d.ts.map +1 -1
  45. package/build/facades/pairing.js +93 -17
  46. package/build/facades/pairing.js.map +1 -1
  47. package/build/facades/speakers.d.ts +1 -1
  48. package/build/facades/speakers.d.ts.map +1 -1
  49. package/build/facades/speakers.js.map +1 -1
  50. package/build/facades/speech.d.ts +7 -6
  51. package/build/facades/speech.d.ts.map +1 -1
  52. package/build/facades/speech.js +1 -1
  53. package/build/facades/speech.js.map +1 -1
  54. package/build/generated/releaseMetadata.d.ts +12 -0
  55. package/build/generated/releaseMetadata.d.ts.map +1 -0
  56. package/build/generated/releaseMetadata.js +10 -0
  57. package/build/generated/releaseMetadata.js.map +1 -0
  58. package/build/index.d.ts +7 -4
  59. package/build/index.d.ts.map +1 -1
  60. package/build/index.js +5 -3
  61. package/build/index.js.map +1 -1
  62. package/build/react/MentraLiveOtaFlow.d.ts +39 -0
  63. package/build/react/MentraLiveOtaFlow.d.ts.map +1 -0
  64. package/build/react/MentraLiveOtaFlow.js +200 -0
  65. package/build/react/MentraLiveOtaFlow.js.map +1 -0
  66. package/build/react/index.d.ts +3 -0
  67. package/build/react/index.d.ts.map +1 -0
  68. package/build/react/index.js +3 -0
  69. package/build/react/index.js.map +1 -0
  70. package/build/react/useEngineSnapshot.d.ts +2 -0
  71. package/build/react/useEngineSnapshot.d.ts.map +1 -0
  72. package/build/react/useEngineSnapshot.js +14 -0
  73. package/build/react/useEngineSnapshot.js.map +1 -0
  74. package/build/react/useMentraLiveOta.d.ts +80 -0
  75. package/build/react/useMentraLiveOta.d.ts.map +1 -0
  76. package/build/react/useMentraLiveOta.js +550 -0
  77. package/build/react/useMentraLiveOta.js.map +1 -0
  78. package/build/services/AppRegistry.d.ts +8 -0
  79. package/build/services/AppRegistry.d.ts.map +1 -1
  80. package/build/services/AppRegistry.js +15 -0
  81. package/build/services/AppRegistry.js.map +1 -1
  82. package/build/services/BlobStore.d.ts +2 -0
  83. package/build/services/BlobStore.d.ts.map +1 -1
  84. package/build/services/BlobStore.js +63 -10
  85. package/build/services/BlobStore.js.map +1 -1
  86. package/build/services/CustomDashboardModel.d.ts +48 -0
  87. package/build/services/CustomDashboardModel.d.ts.map +1 -0
  88. package/build/services/CustomDashboardModel.js +73 -0
  89. package/build/services/CustomDashboardModel.js.map +1 -0
  90. package/build/services/CustomDashboardService.d.ts +61 -0
  91. package/build/services/CustomDashboardService.d.ts.map +1 -0
  92. package/build/services/CustomDashboardService.js +552 -0
  93. package/build/services/CustomDashboardService.js.map +1 -0
  94. package/build/services/DeviceEventRouter.d.ts.map +1 -1
  95. package/build/services/DeviceEventRouter.js +44 -3
  96. package/build/services/DeviceEventRouter.js.map +1 -1
  97. package/build/services/GestureDotsService.d.ts +35 -0
  98. package/build/services/GestureDotsService.d.ts.map +1 -0
  99. package/build/services/GestureDotsService.js +149 -0
  100. package/build/services/GestureDotsService.js.map +1 -0
  101. package/build/services/GlassesStatusProjection.d.ts +15 -1
  102. package/build/services/GlassesStatusProjection.d.ts.map +1 -1
  103. package/build/services/GlassesStatusProjection.js +18 -11
  104. package/build/services/GlassesStatusProjection.js.map +1 -1
  105. package/build/services/HotspotOtaTransport.d.ts.map +1 -1
  106. package/build/services/HotspotOtaTransport.js +8 -7
  107. package/build/services/HotspotOtaTransport.js.map +1 -1
  108. package/build/services/LocalDisplayManager.d.ts +43 -1
  109. package/build/services/LocalDisplayManager.d.ts.map +1 -1
  110. package/build/services/LocalDisplayManager.js +128 -2
  111. package/build/services/LocalDisplayManager.js.map +1 -1
  112. package/build/services/LocalMiniappRuntime.d.ts +13 -0
  113. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  114. package/build/services/LocalMiniappRuntime.js +32 -0
  115. package/build/services/LocalMiniappRuntime.js.map +1 -1
  116. package/build/services/MiniappExitGesture.d.ts +33 -0
  117. package/build/services/MiniappExitGesture.d.ts.map +1 -0
  118. package/build/services/MiniappExitGesture.js +54 -0
  119. package/build/services/MiniappExitGesture.js.map +1 -0
  120. package/build/services/OtaAutoChain.d.ts +41 -0
  121. package/build/services/OtaAutoChain.d.ts.map +1 -0
  122. package/build/services/OtaAutoChain.js +91 -0
  123. package/build/services/OtaAutoChain.js.map +1 -0
  124. package/build/services/OtaErrorMapping.d.ts +18 -0
  125. package/build/services/OtaErrorMapping.d.ts.map +1 -0
  126. package/build/services/OtaErrorMapping.js +63 -0
  127. package/build/services/OtaErrorMapping.js.map +1 -0
  128. package/build/services/OtaInstallCoordinator.d.ts +24 -3
  129. package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
  130. package/build/services/OtaInstallCoordinator.js +17 -12
  131. package/build/services/OtaInstallCoordinator.js.map +1 -1
  132. package/build/services/OtaService.d.ts.map +1 -1
  133. package/build/services/OtaService.js +1 -1
  134. package/build/services/OtaService.js.map +1 -1
  135. package/build/services/OtaUpdateCheckService.d.ts +4 -1
  136. package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
  137. package/build/services/OtaUpdateCheckService.js +28 -16
  138. package/build/services/OtaUpdateCheckService.js.map +1 -1
  139. package/build/services/asg/localNetworkTransport.d.ts.map +1 -1
  140. package/build/services/asg/localNetworkTransport.js +13 -12
  141. package/build/services/asg/localNetworkTransport.js.map +1 -1
  142. package/build/services/gestureClaims.d.ts +18 -0
  143. package/build/services/gestureClaims.d.ts.map +1 -0
  144. package/build/services/gestureClaims.js +24 -0
  145. package/build/services/gestureClaims.js.map +1 -0
  146. package/build/services/gestureDotGlyphs.d.ts +8 -0
  147. package/build/services/gestureDotGlyphs.d.ts.map +1 -0
  148. package/build/services/gestureDotGlyphs.js +12 -0
  149. package/build/services/gestureDotGlyphs.js.map +1 -0
  150. package/build/services/glassesClockSync.d.ts.map +1 -1
  151. package/build/services/glassesClockSync.js +5 -1
  152. package/build/services/glassesClockSync.js.map +1 -1
  153. package/build/services/otaDisplayState.d.ts +1 -1
  154. package/build/services/otaDisplayState.d.ts.map +1 -1
  155. package/build/services/otaDisplayState.js.map +1 -1
  156. package/build/services/otaInstallPolicy.d.ts +1 -1
  157. package/build/services/otaInstallPolicy.d.ts.map +1 -1
  158. package/build/services/otaInstallPolicy.js.map +1 -1
  159. package/build/services/otaLegacyMapping.d.ts +1 -1
  160. package/build/services/otaLegacyMapping.d.ts.map +1 -1
  161. package/build/services/otaLegacyMapping.js.map +1 -1
  162. package/build/services/otaManifestPolicy.d.ts +14 -0
  163. package/build/services/otaManifestPolicy.d.ts.map +1 -0
  164. package/build/services/otaManifestPolicy.js +20 -0
  165. package/build/services/otaManifestPolicy.js.map +1 -0
  166. package/build/services/otaManifestUrl.d.ts +2 -1
  167. package/build/services/otaManifestUrl.d.ts.map +1 -1
  168. package/build/services/otaManifestUrl.js +24 -32
  169. package/build/services/otaManifestUrl.js.map +1 -1
  170. package/build/services/otaReleaseVersion.d.ts +10 -0
  171. package/build/services/otaReleaseVersion.d.ts.map +1 -0
  172. package/build/services/otaReleaseVersion.js +14 -0
  173. package/build/services/otaReleaseVersion.js.map +1 -0
  174. package/build/stores/appVisibility.d.ts +3 -0
  175. package/build/stores/appVisibility.d.ts.map +1 -0
  176. package/build/stores/appVisibility.js +3 -0
  177. package/build/stores/appVisibility.js.map +1 -0
  178. package/build/stores/apps.d.ts.map +1 -1
  179. package/build/stores/apps.js +7 -1
  180. package/build/stores/apps.js.map +1 -1
  181. package/build/stores/core.d.ts +3 -3
  182. package/build/stores/core.d.ts.map +1 -1
  183. package/build/stores/core.js.map +1 -1
  184. package/build/stores/glasses.d.ts +10 -4
  185. package/build/stores/glasses.d.ts.map +1 -1
  186. package/build/stores/glasses.js.map +1 -1
  187. package/build/stores/settings.d.ts.map +1 -1
  188. package/build/stores/settings.js +87 -3
  189. package/build/stores/settings.js.map +1 -1
  190. package/build/types/applet.d.ts +2 -0
  191. package/build/types/applet.d.ts.map +1 -1
  192. package/build/types/applet.js +0 -3
  193. package/build/types/applet.js.map +1 -1
  194. package/build/types/enums.d.ts +1 -5
  195. package/build/types/enums.d.ts.map +1 -1
  196. package/build/types/enums.js +1 -8
  197. package/build/types/enums.js.map +1 -1
  198. package/build/types/hardware.d.ts +1 -1
  199. package/build/types/hardware.d.ts.map +1 -1
  200. package/build/types/hardware.js.map +1 -1
  201. package/build/types/index.d.ts +2 -6
  202. package/build/types/index.d.ts.map +1 -1
  203. package/build/types/index.js +2 -6
  204. package/build/types/index.js.map +1 -1
  205. package/build/utils/display/scene/process.d.ts.map +1 -1
  206. package/build/utils/display/scene/process.js +4 -3
  207. package/build/utils/display/scene/process.js.map +1 -1
  208. package/build/utils/display/scene/types.d.ts +6 -2
  209. package/build/utils/display/scene/types.d.ts.map +1 -1
  210. package/build/utils/display/scene/types.js.map +1 -1
  211. package/package.json +65 -33
  212. package/src/bluetooth-sdk/debug.ts +1 -0
  213. package/src/bluetooth-sdk/index.ts +2 -0
  214. package/src/bluetooth-sdk/ota-transport.ts +1 -0
  215. package/src/bluetooth-sdk/photo-receiver.ts +2 -0
  216. package/src/bluetooth-sdk/react.ts +1 -0
  217. package/src/bluetooth-sdk/types.ts +1 -0
  218. package/src/engine.ts +9 -3
  219. package/src/facades/display.ts +1 -1
  220. package/src/facades/glasses.ts +6 -4
  221. package/src/facades/ota.ts +33 -10
  222. package/src/facades/pairing.ts +103 -23
  223. package/src/facades/speakers.ts +1 -1
  224. package/src/facades/speech.ts +21 -7
  225. package/src/generated/releaseMetadata.ts +20 -0
  226. package/src/index.ts +29 -4
  227. package/src/react/MentraLiveOtaFlow.tsx +569 -0
  228. package/src/react/index.ts +21 -0
  229. package/src/react/useEngineSnapshot.ts +16 -0
  230. package/src/react/useMentraLiveOta.ts +707 -0
  231. package/src/services/AppRegistry.ts +16 -0
  232. package/src/services/BlobStore.ts +57 -10
  233. package/src/services/CustomDashboardModel.ts +83 -0
  234. package/src/services/CustomDashboardService.ts +575 -0
  235. package/src/services/DeviceEventRouter.ts +47 -5
  236. package/src/services/GestureDotsService.ts +147 -0
  237. package/src/services/GlassesStatusProjection.ts +20 -11
  238. package/src/services/HotspotOtaTransport.ts +8 -7
  239. package/src/services/LocalDisplayManager.ts +130 -2
  240. package/src/services/LocalMiniappRuntime.ts +37 -0
  241. package/src/services/MiniappExitGesture.ts +76 -0
  242. package/src/services/OtaAutoChain.ts +130 -0
  243. package/src/services/OtaErrorMapping.ts +80 -0
  244. package/src/services/OtaInstallCoordinator.ts +19 -13
  245. package/src/services/OtaService.ts +1 -2
  246. package/src/services/OtaUpdateCheckService.ts +33 -19
  247. package/src/services/asg/localNetworkTransport.ts +20 -19
  248. package/src/services/gestureClaims.ts +28 -0
  249. package/src/services/gestureDotGlyphs.ts +14 -0
  250. package/src/services/glassesClockSync.ts +5 -1
  251. package/src/services/otaDisplayState.ts +1 -1
  252. package/src/services/otaInstallPolicy.ts +1 -1
  253. package/src/services/otaLegacyMapping.ts +1 -1
  254. package/src/services/otaManifestPolicy.ts +43 -0
  255. package/src/services/otaManifestUrl.ts +27 -36
  256. package/src/services/otaReleaseVersion.ts +22 -0
  257. package/src/stores/appVisibility.ts +3 -0
  258. package/src/stores/apps.ts +7 -1
  259. package/src/stores/core.ts +4 -4
  260. package/src/stores/glasses.ts +13 -6
  261. package/src/stores/settings.ts +87 -3
  262. package/src/types/applet.ts +2 -0
  263. package/src/types/enums.ts +1 -9
  264. package/src/types/hardware.ts +1 -1
  265. package/src/types/index.ts +2 -6
  266. package/src/utils/display/scene/process.ts +4 -3
  267. package/src/utils/display/scene/types.ts +0 -0
  268. package/build/devtools.d.ts +0 -11
  269. package/build/devtools.d.ts.map +0 -1
  270. package/build/devtools.js +0 -13
  271. package/build/devtools.js.map +0 -1
  272. package/build/internal.d.ts +0 -67
  273. package/build/internal.d.ts.map +0 -1
  274. package/build/internal.js +0 -90
  275. package/build/internal.js.map +0 -1
  276. package/src/devtools.ts +0 -13
  277. package/src/internal.ts +0 -155
@@ -10,9 +10,10 @@
10
10
  // target hint) lives on the full surface, not the public entry (same reason
11
11
  // the glasses facade imports internal).
12
12
  import BluetoothSdk from "@glassly/bluetooth-sdk/internal"
13
- import type {ConnectOptions, Device, PairFailureEvent, GlassesNotReadyEvent} from "@glassly/bluetooth-sdk"
13
+ import type {ConnectOptions, Device, DeviceModel, PairFailureEvent, GlassesNotReadyEvent} from "@glassly/bluetooth-sdk"
14
14
  import {useCoreStore} from "../stores/core"
15
15
  import {useGlassesStore} from "../stores/glasses"
16
+ import {SETTINGS, useSettingsStore} from "../stores/settings"
16
17
  import {hasDefaultDevice} from "../services/DeviceStoreHydration"
17
18
  import {
18
19
  markPendingSelection,
@@ -20,18 +21,14 @@ import {
20
21
  subscribePairingIdentity,
21
22
  type IdentitySnapshot,
22
23
  } from "../services/PairingIdentity"
23
- import {
24
- isGlassesConnected,
25
- isGlassesLinkLayerBusy,
26
- isGlassesReady,
27
- waitForGlassesReady,
28
- } from "../services/GlassesReadiness"
24
+ import {isGlassesConnected, isGlassesLinkLayerBusy, isGlassesReady} from "../services/GlassesReadiness"
29
25
  import {
30
26
  logAutomaticReportSubmissionStatus,
31
27
  toAutomaticReportSubmissionStatus,
32
28
  type AutomaticReportSubmissionStatus,
33
29
  } from "../services/AutomaticReportResult"
34
30
  import {pushAllBluetoothSettings} from "../services/GlassesSettingsSync"
31
+ import {ControllerTypes} from "../types"
35
32
  import {submitAutomaticReport} from "./reports"
36
33
 
37
34
  export type {IdentitySnapshot} from "../services/PairingIdentity"
@@ -60,6 +57,82 @@ function projectReadiness() {
60
57
  }
61
58
  }
62
59
 
60
+ function projectTargetReady(options: Pick<PairingReadyWaitOptions, "deviceModel" | "deviceName">): boolean {
61
+ const {deviceModel, deviceName} = options
62
+ const glasses = useGlassesStore.getState()
63
+
64
+ if (deviceModel === ControllerTypes.R1) {
65
+ if (!glasses.controllerConnected || !glasses.controllerFullyBooted) return false
66
+ const settings = useSettingsStore.getState()
67
+ const pairedModel = settings.getSetting(SETTINGS.default_controller.key)
68
+ const pairedName = settings.getSetting(SETTINGS.controller_device_name.key)
69
+ return (!deviceModel || pairedModel === deviceModel) && (!deviceName || pairedName === deviceName)
70
+ }
71
+
72
+ if (!isGlassesReady(glasses.connection)) return false
73
+ const identity = projectPairingIdentity()
74
+ if (!deviceModel && !deviceName) return true
75
+ return (
76
+ identity.kind === "paired" &&
77
+ (!deviceModel || identity.model === deviceModel) &&
78
+ (!deviceName || identity.name === deviceName)
79
+ )
80
+ }
81
+
82
+ function subscribeTargetReady(
83
+ options: Pick<PairingReadyWaitOptions, "deviceModel" | "deviceName">,
84
+ cb: (ready: boolean) => void,
85
+ ): () => void {
86
+ let last = projectTargetReady(options)
87
+ const notify = () => {
88
+ const ready = projectTargetReady(options)
89
+ if (ready === last) return
90
+ last = ready
91
+ cb(ready)
92
+ }
93
+ const unsubscribeGlasses = useGlassesStore.subscribe(notify)
94
+ const unsubscribeSettings = useSettingsStore.subscribe(notify)
95
+ return () => {
96
+ unsubscribeGlasses()
97
+ unsubscribeSettings()
98
+ }
99
+ }
100
+
101
+ async function waitForTargetReady(options: PairingReadyWaitOptions, timeoutMs: number): Promise<boolean> {
102
+ return new Promise((resolve) => {
103
+ if (options.signal?.aborted) {
104
+ resolve(false)
105
+ return
106
+ }
107
+ if (projectTargetReady(options)) {
108
+ resolve(true)
109
+ return
110
+ }
111
+
112
+ let settled = false
113
+ let timeout: ReturnType<typeof setTimeout> | null = null
114
+ let unsubscribe: (() => void) | null = null
115
+ let onAbort: (() => void) | null = null
116
+ const finish = (ready: boolean) => {
117
+ if (settled) return
118
+ settled = true
119
+ if (timeout) clearTimeout(timeout)
120
+ if (unsubscribe) unsubscribe()
121
+ if (onAbort && options.signal) options.signal.removeEventListener("abort", onAbort)
122
+ resolve(ready)
123
+ }
124
+
125
+ unsubscribe = subscribeTargetReady(options, (ready) => {
126
+ if (ready) finish(true)
127
+ })
128
+ if (options.signal) {
129
+ onAbort = () => finish(false)
130
+ options.signal.addEventListener("abort", onAbort)
131
+ }
132
+ timeout = setTimeout(() => finish(projectTargetReady(options)), timeoutMs)
133
+ })
134
+ }
135
+
63
136
  export type PairingReadinessSnapshot = ReturnType<typeof projectReadiness>
64
137
 
65
138
  export async function submitPairingBootTimeoutReport(params: {
@@ -108,12 +181,7 @@ async function waitForReadyDuringPairing(options: PairingReadyWaitOptions = {}):
108
181
  })
109
182
 
110
183
  try {
111
- const ready = await waitForGlassesReady({
112
- getConnection: () => useGlassesStore.getState().connection,
113
- subscribe: (listener) => useGlassesStore.subscribe((state) => state.connection, listener),
114
- timeoutMs,
115
- signal: options.signal,
116
- })
184
+ const ready = await waitForTargetReady(options, timeoutMs)
117
185
 
118
186
  if (!ready && !options.signal?.aborted) {
119
187
  void submitPairingBootTimeoutReport({
@@ -193,6 +261,14 @@ export const pairing = {
193
261
  cb(snap)
194
262
  })
195
263
  },
264
+ /** Whether the exact wearable or controller selected on the scan screen is ready. */
265
+ targetReady: (options: Pick<PairingReadyWaitOptions, "deviceModel" | "deviceName">): boolean =>
266
+ projectTargetReady(options),
267
+ /** Subscribe to readiness for the exact selected target, excluding stale devices. */
268
+ onTargetReady: (
269
+ options: Pick<PairingReadyWaitOptions, "deviceModel" | "deviceName">,
270
+ cb: (ready: boolean) => void,
271
+ ): (() => void) => subscribeTargetReady(options, cb),
196
272
 
197
273
  // --- pairing-identity lifecycle (the PairingIdentity read-model + the JS-owned
198
274
  // identity writes; promotion to `paired` only ever happens natively) ---
@@ -206,7 +282,7 @@ export const pairing = {
206
282
  markPendingSelection: (model: string) => markPendingSelection(model),
207
283
 
208
284
  /** Start scanning for nearby glasses. Results land on `searchResults()`/`onFound()`. */
209
- scan: (...args: Parameters<typeof BluetoothSdk.startScan>) => BluetoothSdk.startScan(...args),
285
+ scan: (model: DeviceModel): Promise<void> => BluetoothSdk.startScan(model),
210
286
  /** Whether a scan is currently in progress. */
211
287
  scanning: (): boolean => useCoreStore.getState().searching,
212
288
  /** Subscribe to scan-in-progress changes; fires only when it changes. Returns an unsubscribe. */
@@ -226,7 +302,7 @@ export const pairing = {
226
302
  // leak as mutable references into the store.
227
303
  searchResults: () => useCoreStore.getState().searchResults.map((result) => ({...result})),
228
304
  /** Subscribe to scan-result changes; fires only when they change. Returns an unsubscribe. */
229
- onFound: (cb: (results: ReturnType<typeof useCoreStore.getState>["searchResults"]) => void): (() => void) => {
305
+ onFound: (cb: (results: Device[]) => void): (() => void) => {
230
306
  let last = JSON.stringify(useCoreStore.getState().searchResults)
231
307
  return useCoreStore.subscribe(() => {
232
308
  const results = useCoreStore.getState().searchResults
@@ -250,7 +326,7 @@ export const pairing = {
250
326
  return BluetoothSdk.connect(device, {...options, saveAsDefault: false})
251
327
  },
252
328
  /** Set a device as the default for subsequent `glasses.connectDefault()`. */
253
- setDefault: (...args: Parameters<typeof BluetoothSdk.setDefaultDevice>) => BluetoothSdk.setDefaultDevice(...args),
329
+ setDefault: (device: Device | null): Promise<void> => BluetoothSdk.setDefaultDevice(device),
254
330
  /**
255
331
  * Prime the native Bluetooth Classic audio watcher with the picked device.
256
332
  * The iOS Mentra Live flow pairs Classic audio BEFORE any BLE connect
@@ -291,25 +367,29 @@ export const pairing = {
291
367
  await BluetoothSdk.stopScan()
292
368
  return
293
369
  }
294
- await BluetoothSdk.disconnect()
295
370
  if (projectPairingIdentity().kind === "paired") {
296
371
  // The persisted settings describe a COMPLETE pairing: restore it to
297
372
  // native (the attempt's connect-by-name overwrote the native
298
373
  // device_name; and if native somehow lost its default entirely, this
299
374
  // repairs the divergence instead of forgetting a real pairing).
300
375
  console.log("PairingIdentity: abandonAttempt — preserving pairing; attempt cancelled, native identity re-seeded")
376
+ await BluetoothSdk.disconnect()
301
377
  await pushAllBluetoothSettings()
302
- } else if (nativeHasDefault) {
378
+ return
379
+ }
380
+ if (nativeHasDefault) {
303
381
  // Mid-relay: native promoted and its echoes are still landing — the
304
382
  // incomplete JS snapshot must not be pushed over the fresher native
305
383
  // identity (the on-connect replay's race). Native holds the truth.
306
384
  console.log("PairingIdentity: abandonAttempt — preserving pairing; JS identity mid-relay, native kept as-is")
307
- } else {
308
- // Forgetting requires CONSENSUS: no native default AND no complete
309
- // persisted pairing — a genuinely partial attempt.
310
- console.log("PairingIdentity: abandonAttempt — no pairing on either layer; forgetting the partial attempt")
311
- await BluetoothSdk.forget()
385
+ await BluetoothSdk.disconnect()
386
+ return
312
387
  }
388
+ // Partial attempt: forget owns teardown. Do NOT disconnect() first — that
389
+ // nulls the MentraLive SGC and used to skip Classic removeBond, leaving
390
+ // IBRT ACL up so glasses never re-advertise for the next scan.
391
+ console.log("PairingIdentity: abandonAttempt — no pairing on either layer; forgetting the partial attempt")
392
+ await BluetoothSdk.forget()
313
393
  },
314
394
 
315
395
  /** Subscribe to pairing failures; returns an unsubscribe. */
@@ -13,7 +13,7 @@
13
13
  * store push back to native happens via SpeakerIdSync.
14
14
  */
15
15
  import BluetoothSdk from "@glassly/bluetooth-sdk/internal"
16
- import type {SpeakerEnrollProgressEvent, SpeakerEnrollResultEvent} from "@glassly/bluetooth-sdk/internal"
16
+ import type {SpeakerEnrollProgressEvent, SpeakerEnrollResultEvent} from "@glassly/bluetooth-sdk"
17
17
 
18
18
  import speakerIdModelManager, {type SpeakerIdModelProgress} from "../services/SpeakerIdModelManager"
19
19
  import type {SpeakerProfile} from "../services/SpeakerProfileStore"
@@ -7,25 +7,39 @@
7
7
  import BluetoothSdk from "@glassly/bluetooth-sdk/internal"
8
8
  import sttModelManager from "../services/STTModelManager"
9
9
  import ttsModelManager from "../services/TTSModelManager"
10
- import offlineSpeechModelService from "../services/OfflineSpeechModelService"
10
+ import offlineSpeechModelService, {
11
+ type DownloadStatus as OfflineModelDownloadStatus,
12
+ } from "../services/OfflineSpeechModelService"
11
13
  import sonioxDirectService from "../services/soniox/SonioxDirectService"
14
+ import type {
15
+ DownloadProgress as SttDownloadProgress,
16
+ ExtractionProgress as SttExtractionProgress,
17
+ LanguageConfig as SttLanguageConfig,
18
+ LanguageInfo as SttLanguageInfo,
19
+ } from "../services/STTModelManager"
12
20
 
13
21
  export const speech = {
14
22
  /** Restart the glasses' on-device transcriber (e.g. after switching STT language). */
15
23
  restartTranscriber: (): Promise<void> => BluetoothSdk.restartTranscriber(),
16
24
  stt: {
17
25
  currentLanguage: () => sttModelManager.getCurrentLanguage(),
18
- languages: () => sttModelManager.getAvailableLanguages(),
19
- languageInfo: () => sttModelManager.getAllLanguageInfo(),
20
- download: (...args: Parameters<typeof sttModelManager.downloadModel>) => sttModelManager.downloadModel(...args),
26
+ languages: (): SttLanguageConfig[] => sttModelManager.getAvailableLanguages(),
27
+ languageInfo: (): Promise<SttLanguageInfo[]> => sttModelManager.getAllLanguageInfo(),
28
+ download: (
29
+ ...args: [
30
+ code?: string,
31
+ onProgress?: (progress: SttDownloadProgress) => void,
32
+ onExtractionProgress?: (progress: SttExtractionProgress) => void,
33
+ ]
34
+ ): Promise<void> => sttModelManager.downloadModel(...args),
21
35
  activate: (code: string) => sttModelManager.setCurrentLanguage(code),
22
36
  cancelDownload: () => sttModelManager.cancelDownload(),
23
37
  deleteModel: (...args: Parameters<typeof sttModelManager.deleteModel>) => sttModelManager.deleteModel(...args),
24
38
  /** Current auto-download status of the offline STT model. */
25
- status: () => offlineSpeechModelService.getStatus(),
39
+ status: (): OfflineModelDownloadStatus | null => offlineSpeechModelService.getStatus(),
26
40
  /** Subscribe to auto-download status changes; returns an unsubscribe. */
27
- onStatusChanged: (...args: Parameters<typeof offlineSpeechModelService.subscribe>) =>
28
- offlineSpeechModelService.subscribe(...args),
41
+ onStatusChanged: (listener: (status: OfflineModelDownloadStatus | null) => void): (() => void) =>
42
+ offlineSpeechModelService.subscribe(listener),
29
43
  },
30
44
  /** Phone → Soniox direct transcription (user-supplied API key, Settings > Keys). */
31
45
  sonioxDirect: {
@@ -0,0 +1,20 @@
1
+ /** Generated by release CI. Do not edit in a release checkout. */
2
+ export interface EngineReleaseMetadata {
3
+ schemaVersion: 1
4
+ familyBaseVersion: string | null
5
+ releaseIdentity: string | null
6
+ releaseSetId: string | null
7
+ sourceCommit: string | null
8
+ otaManifestUrl: string | null
9
+ otaManifestSha256: string | null
10
+ }
11
+
12
+ export const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({
13
+ "schemaVersion": 1,
14
+ "familyBaseVersion": "0.1.0",
15
+ "releaseIdentity": "0.1.0-dev.26",
16
+ "releaseSetId": "glassly-0.1.0-dev.26",
17
+ "sourceCommit": "b63f66924c61de31540b5093d05ff036c756ed74",
18
+ "otaManifestUrl": null,
19
+ "otaManifestSha256": null
20
+ })
package/src/index.ts CHANGED
@@ -6,8 +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 lives on `@glassly/engine/internal`
10
- * (migration-era surface) or `@glassly/engine/devtools` (debug-only) instead.
9
+ * exposes a raw store/service remains private to the GlasslyOS host.
11
10
  * See cloud-v2/docs/issues/020-glasses-status-boundary/integration-review.md §D.
12
11
  */
13
12
 
@@ -43,6 +42,13 @@ export type {
43
42
  // device-model key helpers. The raw useSettingsStore stays internal;
44
43
  // imperative access goes through engine.settings.
45
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
52
 
47
53
  // AI tier registry: the curated per-tier model dropdown options and helpers
48
54
  // the Settings > AI Models screen renders. Resolution itself runs inside
@@ -112,9 +118,28 @@ export type {
112
118
  OtaProgressStatus,
113
119
  OtaStatus,
114
120
  OtaUpdateInfo,
121
+ ReleaseChangelog,
115
122
  OtaSnapshot,
116
123
  OtaInstallSnapshot,
117
124
  } from "./facades/ota"
125
+ export {
126
+ beginOtaAutoChain,
127
+ clearOtaAutoChainReconnectWait,
128
+ isOtaAutoChainActive,
129
+ otaAutoChainFingerprint,
130
+ otaAutoChainReconnectWaitRemaining,
131
+ stopOtaAutoChain,
132
+ tryAdvanceOtaAutoChain,
133
+ MAX_OTA_AUTO_CHAIN_PASSES,
134
+ OTA_AUTO_CHAIN_RECONNECT_TIMEOUT_MS,
135
+ } from "./services/OtaAutoChain"
136
+ export type {OtaAutoChainAdvanceResult} from "./services/OtaAutoChain"
137
+ export {
138
+ BES_INSTALL_RESTART_MESSAGE,
139
+ getOtaErrorMessage,
140
+ shouldRequireGlassesRebootForBesFailure,
141
+ shouldShowChangeWifiForOtaDownloadFailure,
142
+ } from "./services/OtaErrorMapping"
118
143
 
119
144
  // Gallery read models: engine.gallery.onNotice payload types, the media
120
145
  // permission helper + display-name derivation host gallery UI uses, and the
@@ -134,7 +159,7 @@ export type {
134
159
 
135
160
  // Bluetooth SDK event types host UI subscribes to via engine facades (the
136
161
  // BluetoothSdk singleton passthrough itself is internal).
137
- export type {PairFailureEvent, GlassesNotReadyEvent} from "@glassly/bluetooth-sdk/internal"
162
+ export type {PairFailureEvent, GlassesNotReadyEvent} from "@glassly/bluetooth-sdk"
138
163
 
139
164
  // Cloud connection status enum (read model; the connection store is internal).
140
165
  export {WebSocketStatus} from "./stores/connection"
@@ -179,7 +204,7 @@ export {
179
204
  export {HardwareCompatibility, type CompatibilityResult} from "./utils/hardware"
180
205
  export {BgTimer, throttle, debounce} from "./utils/timers"
181
206
 
182
- // Types (hardware requirement types are canonical in @glassly/miniapp; the rest are engine-owned)
207
+ // Hardware types and capability profiles.
183
208
  export {
184
209
  HardwareType,
185
210
  HardwareRequirementLevel,