@mentra/engine 3.1.0-dev.20 → 3.1.0-dev.21

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 (67) hide show
  1. package/README.md +19 -5
  2. package/build/bluetooth-sdk/ota-transport.d.ts +2 -0
  3. package/build/bluetooth-sdk/ota-transport.d.ts.map +1 -0
  4. package/build/bluetooth-sdk/ota-transport.js +2 -0
  5. package/build/bluetooth-sdk/ota-transport.js.map +1 -0
  6. package/build/facades/ota.d.ts.map +1 -1
  7. package/build/facades/ota.js +1 -2
  8. package/build/facades/ota.js.map +1 -1
  9. package/build/generated/releaseMetadata.js +4 -4
  10. package/build/generated/releaseMetadata.js.map +1 -1
  11. package/build/react/MentraLiveOtaFlow.d.ts +3 -2
  12. package/build/react/MentraLiveOtaFlow.d.ts.map +1 -1
  13. package/build/react/MentraLiveOtaFlow.js +68 -345
  14. package/build/react/MentraLiveOtaFlow.js.map +1 -1
  15. package/build/react/index.d.ts +1 -0
  16. package/build/react/index.d.ts.map +1 -1
  17. package/build/react/index.js +1 -0
  18. package/build/react/index.js.map +1 -1
  19. package/build/react/useMentraLiveOta.d.ts +69 -0
  20. package/build/react/useMentraLiveOta.d.ts.map +1 -0
  21. package/build/react/useMentraLiveOta.js +485 -0
  22. package/build/react/useMentraLiveOta.js.map +1 -0
  23. package/build/services/GlassesStatusProjection.d.ts +15 -2
  24. package/build/services/GlassesStatusProjection.d.ts.map +1 -1
  25. package/build/services/GlassesStatusProjection.js +3 -3
  26. package/build/services/GlassesStatusProjection.js.map +1 -1
  27. package/build/services/HotspotOtaTransport.d.ts.map +1 -1
  28. package/build/services/HotspotOtaTransport.js +8 -7
  29. package/build/services/HotspotOtaTransport.js.map +1 -1
  30. package/build/services/OtaInstallCoordinator.d.ts +22 -1
  31. package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
  32. package/build/services/OtaInstallCoordinator.js +8 -8
  33. package/build/services/OtaInstallCoordinator.js.map +1 -1
  34. package/build/services/OtaService.d.ts.map +1 -1
  35. package/build/services/OtaService.js +1 -1
  36. package/build/services/OtaService.js.map +1 -1
  37. package/build/services/OtaUpdateCheckService.d.ts +1 -1
  38. package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
  39. package/build/services/OtaUpdateCheckService.js +6 -2
  40. package/build/services/OtaUpdateCheckService.js.map +1 -1
  41. package/build/services/asg/localNetworkTransport.d.ts.map +1 -1
  42. package/build/services/asg/localNetworkTransport.js +13 -12
  43. package/build/services/asg/localNetworkTransport.js.map +1 -1
  44. package/build/services/glassesClockSync.js +1 -1
  45. package/build/services/glassesClockSync.js.map +1 -1
  46. package/build/stores/core.d.ts +3 -3
  47. package/build/stores/core.d.ts.map +1 -1
  48. package/build/stores/core.js.map +1 -1
  49. package/build/stores/glasses.d.ts +10 -4
  50. package/build/stores/glasses.d.ts.map +1 -1
  51. package/build/stores/glasses.js.map +1 -1
  52. package/package.json +12 -6
  53. package/src/bluetooth-sdk/ota-transport.ts +1 -0
  54. package/src/facades/ota.ts +1 -2
  55. package/src/generated/releaseMetadata.ts +4 -4
  56. package/src/react/MentraLiveOtaFlow.tsx +116 -466
  57. package/src/react/index.ts +13 -0
  58. package/src/react/useMentraLiveOta.ts +619 -0
  59. package/src/services/GlassesStatusProjection.ts +7 -6
  60. package/src/services/HotspotOtaTransport.ts +8 -7
  61. package/src/services/OtaInstallCoordinator.ts +10 -9
  62. package/src/services/OtaService.ts +1 -2
  63. package/src/services/OtaUpdateCheckService.ts +8 -5
  64. package/src/services/asg/localNetworkTransport.ts +20 -19
  65. package/src/services/glassesClockSync.ts +1 -1
  66. package/src/stores/core.ts +4 -4
  67. package/src/stores/glasses.ts +13 -6
@@ -0,0 +1,485 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import { ota } from "../facades/ota";
3
+ import { beginOtaAutoChain, clearOtaAutoChainReconnectWait, isOtaAutoChainActive, otaAutoChainFingerprint, otaAutoChainReconnectWaitRemaining, stopOtaAutoChain, tryAdvanceOtaAutoChain, } from "../services/OtaAutoChain";
4
+ import { BES_INSTALL_RESTART_MESSAGE, getOtaErrorMessage, shouldRequireGlassesRebootForBesFailure, shouldShowChangeWifiForOtaDownloadFailure, } from "../services/OtaErrorMapping";
5
+ import { useEngineSnapshot } from "./useEngineSnapshot";
6
+ const AUTO_CHAIN_NETWORK_RETRY_DELAY_MS = 5000;
7
+ const AUTO_CHAIN_COMPLETE_DELAY_MS = 750;
8
+ function installProgress(snapshot) {
9
+ if (snapshot.displayState !== "updating")
10
+ return null;
11
+ const { otaStatus } = snapshot;
12
+ const isDownload = otaStatus?.phase === "download";
13
+ const totalSteps = otaStatus?.totalSteps ?? 1;
14
+ const rawPercent = isDownload
15
+ ? (otaStatus?.stepPercent ?? 0)
16
+ : totalSteps >= 2
17
+ ? (otaStatus?.overallPercent ?? 0)
18
+ : (otaStatus?.stepPercent ?? 0);
19
+ return Math.min(Math.max(rawPercent, snapshot.mtkInstallStallSimulatedPercent ?? 0, 0), 100);
20
+ }
21
+ function progressScreen(snapshot) {
22
+ if (snapshot.versionChangePhase === "restarting")
23
+ return "restarting";
24
+ if (snapshot.versionChangePhase === "verifying")
25
+ return "verifying";
26
+ switch (snapshot.displayState) {
27
+ case "starting":
28
+ return snapshot.hotspotPhase === "idle" || snapshot.hotspotPhase === "serving" ? "starting" : "preparing_hotspot";
29
+ case "updating":
30
+ return "updating";
31
+ case "restarting":
32
+ return "restarting";
33
+ case "complete":
34
+ return "complete";
35
+ case "failed":
36
+ return "failed";
37
+ default:
38
+ return "disconnected";
39
+ }
40
+ }
41
+ /**
42
+ * Headless Mentra Live OTA flow. Engine owns checking, hotspot staging,
43
+ * APK/MTK/BES sequencing, restart recovery, retries, and verification; the host
44
+ * renders semantic state and invokes these idempotent actions.
45
+ */
46
+ export function useMentraLiveOta(options = {}) {
47
+ const { initialPage = "check", initializeRuntime = true, onFinished, onFirmwareRestartingChange, onOpenWifiSetup, } = options;
48
+ const otaSnapshot = useEngineSnapshot(ota.snapshot, ota.onSnapshot);
49
+ const installSnapshot = useEngineSnapshot(ota.installSession.snapshot, ota.installSession.onSnapshot);
50
+ const [page, setPage] = useState(initialPage);
51
+ const [runtimeReady, setRuntimeReady] = useState(!initializeRuntime);
52
+ const [checkState, setCheckState] = useState("checking");
53
+ const [isUpdateRequired, setIsUpdateRequired] = useState(true);
54
+ const [isVersionChange, setIsVersionChange] = useState(false);
55
+ const [errorKind, setErrorKind] = useState("network");
56
+ const [updateFingerprint, setUpdateFingerprint] = useState(null);
57
+ const [checkGeneration, setCheckGeneration] = useState(0);
58
+ const performCheckGenerationRef = useRef(0);
59
+ const activeCheckKeyRef = useRef(null);
60
+ const checkStartedRef = useRef(false);
61
+ const checkCompletedRef = useRef(false);
62
+ const selectedCheckResultRef = useRef(null);
63
+ const autoChainAdvancedRef = useRef(false);
64
+ const installActionPendingRef = useRef(false);
65
+ const onFinishedRef = useRef(onFinished);
66
+ const onOpenWifiSetupRef = useRef(onOpenWifiSetup);
67
+ const onFirmwareRestartingChangeRef = useRef(onFirmwareRestartingChange);
68
+ onFinishedRef.current = onFinished;
69
+ onOpenWifiSetupRef.current = onOpenWifiSetup;
70
+ onFirmwareRestartingChangeRef.current = onFirmwareRestartingChange;
71
+ useEffect(() => {
72
+ if (!initializeRuntime) {
73
+ setRuntimeReady(true);
74
+ return;
75
+ }
76
+ let cancelled = false;
77
+ setRuntimeReady(false);
78
+ void ota.initialize().finally(() => {
79
+ if (!cancelled)
80
+ setRuntimeReady(true);
81
+ });
82
+ return () => {
83
+ cancelled = true;
84
+ };
85
+ }, [initializeRuntime]);
86
+ const returnToCheck = useCallback(() => {
87
+ installActionPendingRef.current = false;
88
+ autoChainAdvancedRef.current = false;
89
+ setPage("check");
90
+ setCheckGeneration((generation) => generation + 1);
91
+ }, []);
92
+ const navigateToProgress = useCallback(() => {
93
+ installActionPendingRef.current = true;
94
+ ota.clearProgress();
95
+ setPage("progress");
96
+ }, []);
97
+ useEffect(() => {
98
+ if (!runtimeReady || page !== "check")
99
+ return;
100
+ const MIN_DISPLAY_TIME_MS = 1100;
101
+ const MAX_WAIT_FOR_VERSION_INFO_MS = 10_000;
102
+ const checkKey = String(checkGeneration);
103
+ if (activeCheckKeyRef.current !== checkKey) {
104
+ activeCheckKeyRef.current = checkKey;
105
+ checkStartedRef.current = false;
106
+ checkCompletedRef.current = false;
107
+ selectedCheckResultRef.current = null;
108
+ installActionPendingRef.current = false;
109
+ setCheckState("checking");
110
+ }
111
+ const myGeneration = ++performCheckGenerationRef.current;
112
+ let cancelled = false;
113
+ let reconnectTimeout = null;
114
+ const performCheck = async () => {
115
+ if (checkCompletedRef.current)
116
+ return;
117
+ if (!otaSnapshot.connected) {
118
+ if (isOtaAutoChainActive()) {
119
+ const remainingMs = otaAutoChainReconnectWaitRemaining();
120
+ if (remainingMs === null)
121
+ return;
122
+ reconnectTimeout = setTimeout(() => {
123
+ if (cancelled || myGeneration !== performCheckGenerationRef.current || ota.snapshot().connected)
124
+ return;
125
+ stopOtaAutoChain();
126
+ checkCompletedRef.current = true;
127
+ setCheckState("error");
128
+ }, remainingMs);
129
+ return;
130
+ }
131
+ if (checkStartedRef.current) {
132
+ stopOtaAutoChain();
133
+ checkCompletedRef.current = true;
134
+ setCheckState("error");
135
+ return;
136
+ }
137
+ checkCompletedRef.current = true;
138
+ onFinishedRef.current?.();
139
+ return;
140
+ }
141
+ clearOtaAutoChainReconnectWait();
142
+ checkStartedRef.current = true;
143
+ const startTime = Date.now();
144
+ try {
145
+ const checkOptions = {
146
+ waitForBuildNumberMs: MAX_WAIT_FOR_VERSION_INFO_MS,
147
+ waitForBesVersionMs: 5000,
148
+ waitForMtkVersionMs: 2000,
149
+ refreshVersionInfo: true,
150
+ fixClockBeforeCheck: false,
151
+ };
152
+ let result = await ota.checkForUpdates(checkOptions);
153
+ if (cancelled || myGeneration !== performCheckGenerationRef.current)
154
+ return;
155
+ if (!result.hasCheckCompleted && result.checkFailureReason === "network" && isOtaAutoChainActive()) {
156
+ await new Promise((resolve) => setTimeout(resolve, AUTO_CHAIN_NETWORK_RETRY_DELAY_MS));
157
+ if (cancelled || myGeneration !== performCheckGenerationRef.current)
158
+ return;
159
+ result = await ota.checkForUpdates(checkOptions);
160
+ }
161
+ if (cancelled || myGeneration !== performCheckGenerationRef.current)
162
+ return;
163
+ selectedCheckResultRef.current = result;
164
+ await new Promise((resolve) => setTimeout(resolve, Math.max(0, MIN_DISPLAY_TIME_MS - (Date.now() - startTime))));
165
+ if (cancelled || myGeneration !== performCheckGenerationRef.current)
166
+ return;
167
+ if (result.skippedReason === "disconnected") {
168
+ stopOtaAutoChain();
169
+ checkCompletedRef.current = true;
170
+ setCheckState("error");
171
+ return;
172
+ }
173
+ if (result.skippedReason === "missing_build") {
174
+ checkCompletedRef.current = true;
175
+ if (isOtaAutoChainActive()) {
176
+ stopOtaAutoChain();
177
+ setCheckState("error");
178
+ }
179
+ else {
180
+ onFinishedRef.current?.();
181
+ }
182
+ return;
183
+ }
184
+ if (result.skippedReason === "dev_build") {
185
+ stopOtaAutoChain();
186
+ checkCompletedRef.current = true;
187
+ ota.clearUpdateAvailable();
188
+ setCheckState("dev_build");
189
+ return;
190
+ }
191
+ if (!result.hasCheckCompleted) {
192
+ stopOtaAutoChain();
193
+ checkCompletedRef.current = true;
194
+ setErrorKind(result.checkFailureReason === "pin_unavailable" ? "pin_unavailable" : "network");
195
+ setCheckState("error");
196
+ return;
197
+ }
198
+ if (result.updateAvailable && result.updateInfo) {
199
+ setIsUpdateRequired(result.isRequired);
200
+ setIsVersionChange(result.updateInfo.isDowngrade === true);
201
+ const fingerprint = otaAutoChainFingerprint(result);
202
+ setUpdateFingerprint(fingerprint);
203
+ if (isOtaAutoChainActive()) {
204
+ const snapshot = ota.snapshot();
205
+ if (!snapshot.wifiStatusKnown)
206
+ return;
207
+ if (!snapshot.wifiConnected && snapshot.hotspotOtaVersion !== 1) {
208
+ stopOtaAutoChain();
209
+ }
210
+ else {
211
+ const admission = tryAdvanceOtaAutoChain(fingerprint, result.updateInfo.isDowngrade === true);
212
+ if (admission.advance) {
213
+ checkCompletedRef.current = true;
214
+ ota.installSession.prepare(result);
215
+ navigateToProgress();
216
+ return;
217
+ }
218
+ }
219
+ }
220
+ checkCompletedRef.current = true;
221
+ setCheckState("update_available");
222
+ return;
223
+ }
224
+ stopOtaAutoChain();
225
+ checkCompletedRef.current = true;
226
+ ota.clearUpdateAvailable();
227
+ setCheckState("no_update");
228
+ }
229
+ catch (error) {
230
+ console.error("OTA check failed:", error);
231
+ await new Promise((resolve) => setTimeout(resolve, Math.max(0, MIN_DISPLAY_TIME_MS - (Date.now() - startTime))));
232
+ if (cancelled || myGeneration !== performCheckGenerationRef.current)
233
+ return;
234
+ stopOtaAutoChain();
235
+ checkCompletedRef.current = true;
236
+ setErrorKind("network");
237
+ setCheckState("error");
238
+ }
239
+ };
240
+ void performCheck();
241
+ return () => {
242
+ cancelled = true;
243
+ if (reconnectTimeout)
244
+ clearTimeout(reconnectTimeout);
245
+ };
246
+ }, [checkGeneration, navigateToProgress, otaSnapshot.connected, otaSnapshot.wifiStatusKnown, page, runtimeReady]);
247
+ useEffect(() => {
248
+ if (!runtimeReady || page !== "progress")
249
+ return;
250
+ ota.installSession.attach();
251
+ return () => ota.installSession.detach();
252
+ }, [page, runtimeReady]);
253
+ const firmwareRestarting = page === "progress" &&
254
+ ((!installSnapshot.connected && installSnapshot.displayState === "restarting") ||
255
+ installSnapshot.versionChangePhase === "restarting");
256
+ useEffect(() => {
257
+ if (page !== "progress")
258
+ return;
259
+ onFirmwareRestartingChangeRef.current?.(firmwareRestarting, true);
260
+ }, [firmwareRestarting, page]);
261
+ useEffect(() => {
262
+ if (page !== "progress")
263
+ return;
264
+ return () => {
265
+ onFirmwareRestartingChangeRef.current?.(false, false);
266
+ };
267
+ }, [page]);
268
+ useEffect(() => {
269
+ if (page !== "progress" ||
270
+ installSnapshot.displayState !== "complete" ||
271
+ !installSnapshot.connected ||
272
+ !isOtaAutoChainActive() ||
273
+ autoChainAdvancedRef.current) {
274
+ return;
275
+ }
276
+ const timeout = setTimeout(() => {
277
+ if (!isOtaAutoChainActive())
278
+ return;
279
+ autoChainAdvancedRef.current = true;
280
+ ota.installSession.finish();
281
+ returnToCheck();
282
+ }, AUTO_CHAIN_COMPLETE_DELAY_MS);
283
+ return () => clearTimeout(timeout);
284
+ }, [installSnapshot.connected, installSnapshot.displayState, page, returnToCheck]);
285
+ const check = useCallback(() => {
286
+ setPage("check");
287
+ setCheckState("checking");
288
+ setCheckGeneration((generation) => generation + 1);
289
+ }, []);
290
+ const install = useCallback(() => {
291
+ if (installActionPendingRef.current || page !== "check")
292
+ return;
293
+ const result = selectedCheckResultRef.current;
294
+ if (!result) {
295
+ setErrorKind("network");
296
+ setCheckState("error");
297
+ return;
298
+ }
299
+ const snapshot = ota.snapshot();
300
+ if (!snapshot.wifiStatusKnown) {
301
+ check();
302
+ return;
303
+ }
304
+ if (!snapshot.wifiConnected && snapshot.hotspotOtaVersion !== 1) {
305
+ onOpenWifiSetupRef.current?.();
306
+ return;
307
+ }
308
+ ota.installSession.prepare(result);
309
+ if (updateFingerprint)
310
+ beginOtaAutoChain(updateFingerprint, isVersionChange);
311
+ navigateToProgress();
312
+ }, [check, isVersionChange, navigateToProgress, page, updateFingerprint]);
313
+ const retryInstall = useCallback(() => {
314
+ if (page !== "progress")
315
+ return;
316
+ onFirmwareRestartingChangeRef.current?.(false, true);
317
+ ota.installSession.retry();
318
+ }, [page]);
319
+ const finish = useCallback(() => {
320
+ if (page === "check") {
321
+ onFinishedRef.current?.();
322
+ return;
323
+ }
324
+ if (installSnapshot.displayState === "restarting")
325
+ stopOtaAutoChain();
326
+ const requiresGlassesReboot = shouldRequireGlassesRebootForBesFailure(installSnapshot.otaStatus, installSnapshot.otaProgress, installSnapshot.errorMsg);
327
+ if (requiresGlassesReboot)
328
+ stopOtaAutoChain();
329
+ ota.installSession.finish();
330
+ returnToCheck();
331
+ }, [installSnapshot, page, returnToCheck]);
332
+ const discard = useCallback(() => {
333
+ if (page !== "progress")
334
+ return;
335
+ stopOtaAutoChain();
336
+ ota.installSession.discard();
337
+ returnToCheck();
338
+ }, [page, returnToCheck]);
339
+ const openWifiSetup = useCallback(() => {
340
+ if (page === "progress")
341
+ stopOtaAutoChain();
342
+ onOpenWifiSetupRef.current?.();
343
+ }, [page]);
344
+ const state = useMemo(() => {
345
+ const hotspotSupported = otaSnapshot.hotspotOtaVersion === 1;
346
+ const canInstall = otaSnapshot.wifiStatusKnown && (otaSnapshot.wifiConnected || hotspotSupported);
347
+ if (!runtimeReady) {
348
+ return {
349
+ screen: "initializing",
350
+ connected: otaSnapshot.connected,
351
+ transport: null,
352
+ updateRequired: isUpdateRequired,
353
+ versionChange: isVersionChange,
354
+ versionChangeConverged: false,
355
+ versionChangePhase: null,
356
+ wifiConnected: otaSnapshot.wifiConnected,
357
+ wifiStatusKnown: otaSnapshot.wifiStatusKnown,
358
+ hotspotSupported,
359
+ hotspotPhase: "idle",
360
+ hotspotArtifactPercent: null,
361
+ phase: null,
362
+ step: null,
363
+ currentStep: null,
364
+ totalSteps: null,
365
+ progress: null,
366
+ installingApkOnly: false,
367
+ firmwareRestarting: false,
368
+ error: null,
369
+ canInstall: false,
370
+ canRetry: false,
371
+ canFinish: false,
372
+ canDismiss: false,
373
+ canDiscard: false,
374
+ canOpenWifiSetup: false,
375
+ continueDisabled: false,
376
+ };
377
+ }
378
+ if (page === "check") {
379
+ const wifiRequired = otaSnapshot.wifiStatusKnown && !otaSnapshot.wifiConnected && !hotspotSupported;
380
+ const screen = checkState === "checking"
381
+ ? "checking"
382
+ : checkState === "update_available"
383
+ ? wifiRequired
384
+ ? "wifi_required"
385
+ : "update_available"
386
+ : checkState === "no_update"
387
+ ? "up_to_date"
388
+ : checkState === "dev_build"
389
+ ? "dev_build"
390
+ : errorKind === "pin_unavailable"
391
+ ? "update_info_unavailable"
392
+ : "check_failed";
393
+ const error = screen === "check_failed"
394
+ ? { code: "check_failed", message: "Couldn't check for updates. Please check your connection and try again." }
395
+ : screen === "update_info_unavailable"
396
+ ? { code: "update_info_unavailable", message: "Update information for this app version is unavailable." }
397
+ : null;
398
+ return {
399
+ screen,
400
+ connected: otaSnapshot.connected,
401
+ transport: otaSnapshot.wifiConnected ? "wifi" : hotspotSupported ? "hotspot" : null,
402
+ updateRequired: isUpdateRequired,
403
+ versionChange: isVersionChange,
404
+ versionChangeConverged: false,
405
+ versionChangePhase: null,
406
+ wifiConnected: otaSnapshot.wifiConnected,
407
+ wifiStatusKnown: otaSnapshot.wifiStatusKnown,
408
+ hotspotSupported,
409
+ hotspotPhase: "idle",
410
+ hotspotArtifactPercent: null,
411
+ phase: null,
412
+ step: null,
413
+ currentStep: null,
414
+ totalSteps: null,
415
+ progress: null,
416
+ installingApkOnly: false,
417
+ firmwareRestarting: false,
418
+ error,
419
+ canInstall: screen === "update_available" && canInstall,
420
+ canRetry: screen === "check_failed",
421
+ canFinish: screen === "up_to_date" || screen === "dev_build" || screen === "update_info_unavailable",
422
+ canDismiss: (screen === "update_available" || screen === "wifi_required") && !isUpdateRequired,
423
+ canDiscard: false,
424
+ canOpenWifiSetup: screen === "wifi_required",
425
+ continueDisabled: false,
426
+ };
427
+ }
428
+ const requiresGlassesReboot = shouldRequireGlassesRebootForBesFailure(installSnapshot.otaStatus, installSnapshot.otaProgress, installSnapshot.errorMsg);
429
+ const showChangeWifi = shouldShowChangeWifiForOtaDownloadFailure(installSnapshot.otaStatus, installSnapshot.otaProgress, installSnapshot.errorMsg);
430
+ const displayedError = requiresGlassesReboot
431
+ ? BES_INSTALL_RESTART_MESSAGE
432
+ : installSnapshot.errorMsg || getOtaErrorMessage(installSnapshot.otaStatus?.error);
433
+ const screen = progressScreen(installSnapshot);
434
+ const error = screen === "failed"
435
+ ? {
436
+ code: requiresGlassesReboot ? "bes_restart_required" : "install_failed",
437
+ message: displayedError,
438
+ }
439
+ : null;
440
+ const totalSteps = installSnapshot.otaStatus?.totalSteps ?? null;
441
+ return {
442
+ screen,
443
+ connected: installSnapshot.connected,
444
+ transport: installSnapshot.transport,
445
+ updateRequired: isUpdateRequired,
446
+ versionChange: installSnapshot.isVersionChange,
447
+ versionChangeConverged: installSnapshot.versionChangeConverged,
448
+ versionChangePhase: installSnapshot.versionChangePhase,
449
+ wifiConnected: otaSnapshot.wifiConnected,
450
+ wifiStatusKnown: otaSnapshot.wifiStatusKnown,
451
+ hotspotSupported,
452
+ hotspotPhase: installSnapshot.hotspotPhase,
453
+ hotspotArtifactPercent: installSnapshot.hotspotArtifactPercent,
454
+ phase: installSnapshot.otaStatus?.phase ?? installSnapshot.otaProgress?.stage ?? null,
455
+ step: installSnapshot.otaStatus?.stepType ?? null,
456
+ currentStep: installSnapshot.otaStatus?.currentStep ?? null,
457
+ totalSteps,
458
+ progress: installProgress(installSnapshot),
459
+ installingApkOnly: installSnapshot.otaStatus?.stepType === "apk" &&
460
+ installSnapshot.otaStatus.phase === "install" &&
461
+ totalSteps === 1,
462
+ firmwareRestarting,
463
+ error,
464
+ canInstall: false,
465
+ canRetry: screen === "failed" && !requiresGlassesReboot,
466
+ canFinish: screen === "complete" || screen === "restarting" || (screen === "failed" && requiresGlassesReboot),
467
+ canDismiss: false,
468
+ canDiscard: screen === "disconnected",
469
+ canOpenWifiSetup: screen === "failed" && showChangeWifi,
470
+ continueDisabled: installSnapshot.continueButtonDisabled,
471
+ };
472
+ }, [
473
+ checkState,
474
+ errorKind,
475
+ firmwareRestarting,
476
+ installSnapshot,
477
+ isUpdateRequired,
478
+ isVersionChange,
479
+ otaSnapshot,
480
+ page,
481
+ runtimeReady,
482
+ ]);
483
+ return useMemo(() => ({ state, check, retryCheck: check, install, retryInstall, finish, discard, openWifiSetup }), [check, discard, finish, install, openWifiSetup, retryInstall, state]);
484
+ }
485
+ //# sourceMappingURL=useMentraLiveOta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMentraLiveOta.js","sourceRoot":"","sources":["../../src/react/useMentraLiveOta.ts"],"names":[],"mappings":"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","sourcesContent":["import {useCallback, useEffect, useMemo, useRef, useState} from \"react\"\n\nimport {ota} from \"../facades/ota\"\nimport {\n beginOtaAutoChain,\n clearOtaAutoChainReconnectWait,\n isOtaAutoChainActive,\n otaAutoChainFingerprint,\n otaAutoChainReconnectWaitRemaining,\n stopOtaAutoChain,\n tryAdvanceOtaAutoChain,\n} from \"../services/OtaAutoChain\"\nimport {\n BES_INSTALL_RESTART_MESSAGE,\n getOtaErrorMessage,\n shouldRequireGlassesRebootForBesFailure,\n shouldShowChangeWifiForOtaDownloadFailure,\n} from \"../services/OtaErrorMapping\"\nimport type {OtaInstallSnapshot} from \"../services/OtaInstallCoordinator\"\nimport type {OtaCheckCurrentGlassesResult} from \"../services/OtaUpdateCheckService\"\nimport {useEngineSnapshot} from \"./useEngineSnapshot\"\n\nexport type MentraLiveOtaFlowPage = \"check\" | \"progress\"\n\nexport type MentraLiveOtaScreen =\n | \"initializing\"\n | \"checking\"\n | \"update_available\"\n | \"wifi_required\"\n | \"up_to_date\"\n | \"dev_build\"\n | \"check_failed\"\n | \"update_info_unavailable\"\n | \"starting\"\n | \"preparing_hotspot\"\n | \"updating\"\n | \"restarting\"\n | \"verifying\"\n | \"complete\"\n | \"failed\"\n | \"disconnected\"\n\nexport type MentraLiveOtaErrorCode =\n | \"check_failed\"\n | \"update_info_unavailable\"\n | \"install_failed\"\n | \"bes_restart_required\"\n\nexport type MentraLiveOtaError = {\n code: MentraLiveOtaErrorCode\n message: string\n}\n\nexport type MentraLiveOtaTransport = \"wifi\" | \"hotspot\"\nexport type MentraLiveOtaHotspotPhase = \"idle\" | \"downloading\" | \"starting_hotspot\" | \"joining_hotspot\" | \"serving\"\nexport type MentraLiveOtaInstallPhase = \"download\" | \"install\"\nexport type MentraLiveOtaStep = \"apk\" | \"mtk\" | \"bes\"\n\nexport type MentraLiveOtaState = {\n screen: MentraLiveOtaScreen\n connected: boolean\n transport: MentraLiveOtaTransport | null\n updateRequired: boolean\n versionChange: boolean\n versionChangeConverged: boolean\n versionChangePhase: \"installing\" | \"restarting\" | \"verifying\" | null\n wifiConnected: boolean\n wifiStatusKnown: boolean\n hotspotSupported: boolean\n hotspotPhase: MentraLiveOtaHotspotPhase\n hotspotArtifactPercent: number | null\n phase: MentraLiveOtaInstallPhase | null\n step: MentraLiveOtaStep | null\n currentStep: number | null\n totalSteps: number | null\n progress: number | null\n installingApkOnly: boolean\n firmwareRestarting: boolean\n error: MentraLiveOtaError | null\n canInstall: boolean\n canRetry: boolean\n canFinish: boolean\n canDismiss: boolean\n canDiscard: boolean\n canOpenWifiSetup: boolean\n continueDisabled: boolean\n}\n\nexport type UseMentraLiveOtaOptions = {\n /** Entry page. `progress` exists for interrupted-session recovery. */\n initialPage?: MentraLiveOtaFlowPage\n /** Start Engine's OTA-only projections. Full Engine hosts should pass false. */\n initializeRuntime?: boolean\n /** Called after the final check or when an optional update is dismissed. */\n onFinished?: () => void\n /** Host-owned Wi-Fi setup for glasses without hotspot OTA support. */\n onOpenWifiSetup?: () => void\n /** Lets a host coordinate its connection overlay with OTA firmware restarts. */\n onFirmwareRestartingChange?: (restarting: boolean, progressActive: boolean) => void\n}\n\nexport type MentraLiveOtaController = {\n state: MentraLiveOtaState\n check: () => void\n retryCheck: () => void\n install: () => void\n retryInstall: () => void\n finish: () => void\n discard: () => void\n openWifiSetup: () => void\n}\n\ntype CheckState = \"checking\" | \"update_available\" | \"no_update\" | \"dev_build\" | \"error\"\n\nconst AUTO_CHAIN_NETWORK_RETRY_DELAY_MS = 5000\nconst AUTO_CHAIN_COMPLETE_DELAY_MS = 750\n\nfunction installProgress(snapshot: OtaInstallSnapshot): number | null {\n if (snapshot.displayState !== \"updating\") return null\n const {otaStatus} = snapshot\n const isDownload = otaStatus?.phase === \"download\"\n const totalSteps = otaStatus?.totalSteps ?? 1\n const rawPercent = isDownload\n ? (otaStatus?.stepPercent ?? 0)\n : totalSteps >= 2\n ? (otaStatus?.overallPercent ?? 0)\n : (otaStatus?.stepPercent ?? 0)\n return Math.min(Math.max(rawPercent, snapshot.mtkInstallStallSimulatedPercent ?? 0, 0), 100)\n}\n\nfunction progressScreen(snapshot: OtaInstallSnapshot): MentraLiveOtaScreen {\n if (snapshot.versionChangePhase === \"restarting\") return \"restarting\"\n if (snapshot.versionChangePhase === \"verifying\") return \"verifying\"\n switch (snapshot.displayState) {\n case \"starting\":\n return snapshot.hotspotPhase === \"idle\" || snapshot.hotspotPhase === \"serving\" ? \"starting\" : \"preparing_hotspot\"\n case \"updating\":\n return \"updating\"\n case \"restarting\":\n return \"restarting\"\n case \"complete\":\n return \"complete\"\n case \"failed\":\n return \"failed\"\n default:\n return \"disconnected\"\n }\n}\n\n/**\n * Headless Mentra Live OTA flow. Engine owns checking, hotspot staging,\n * APK/MTK/BES sequencing, restart recovery, retries, and verification; the host\n * renders semantic state and invokes these idempotent actions.\n */\nexport function useMentraLiveOta(options: UseMentraLiveOtaOptions = {}): MentraLiveOtaController {\n const {\n initialPage = \"check\",\n initializeRuntime = true,\n onFinished,\n onFirmwareRestartingChange,\n onOpenWifiSetup,\n } = options\n const otaSnapshot = useEngineSnapshot(ota.snapshot, ota.onSnapshot)\n const installSnapshot = useEngineSnapshot(ota.installSession.snapshot, ota.installSession.onSnapshot)\n const [page, setPage] = useState<MentraLiveOtaFlowPage>(initialPage)\n const [runtimeReady, setRuntimeReady] = useState(!initializeRuntime)\n const [checkState, setCheckState] = useState<CheckState>(\"checking\")\n const [isUpdateRequired, setIsUpdateRequired] = useState(true)\n const [isVersionChange, setIsVersionChange] = useState(false)\n const [errorKind, setErrorKind] = useState<\"network\" | \"pin_unavailable\">(\"network\")\n const [updateFingerprint, setUpdateFingerprint] = useState<string | null>(null)\n const [checkGeneration, setCheckGeneration] = useState(0)\n const performCheckGenerationRef = useRef(0)\n const activeCheckKeyRef = useRef<string | null>(null)\n const checkStartedRef = useRef(false)\n const checkCompletedRef = useRef(false)\n const selectedCheckResultRef = useRef<OtaCheckCurrentGlassesResult | null>(null)\n const autoChainAdvancedRef = useRef(false)\n const installActionPendingRef = useRef(false)\n const onFinishedRef = useRef(onFinished)\n const onOpenWifiSetupRef = useRef(onOpenWifiSetup)\n const onFirmwareRestartingChangeRef = useRef(onFirmwareRestartingChange)\n onFinishedRef.current = onFinished\n onOpenWifiSetupRef.current = onOpenWifiSetup\n onFirmwareRestartingChangeRef.current = onFirmwareRestartingChange\n\n useEffect(() => {\n if (!initializeRuntime) {\n setRuntimeReady(true)\n return\n }\n let cancelled = false\n setRuntimeReady(false)\n void ota.initialize().finally(() => {\n if (!cancelled) setRuntimeReady(true)\n })\n return () => {\n cancelled = true\n }\n }, [initializeRuntime])\n\n const returnToCheck = useCallback(() => {\n installActionPendingRef.current = false\n autoChainAdvancedRef.current = false\n setPage(\"check\")\n setCheckGeneration((generation) => generation + 1)\n }, [])\n\n const navigateToProgress = useCallback(() => {\n installActionPendingRef.current = true\n ota.clearProgress()\n setPage(\"progress\")\n }, [])\n\n useEffect(() => {\n if (!runtimeReady || page !== \"check\") return\n const MIN_DISPLAY_TIME_MS = 1100\n const MAX_WAIT_FOR_VERSION_INFO_MS = 10_000\n const checkKey = String(checkGeneration)\n if (activeCheckKeyRef.current !== checkKey) {\n activeCheckKeyRef.current = checkKey\n checkStartedRef.current = false\n checkCompletedRef.current = false\n selectedCheckResultRef.current = null\n installActionPendingRef.current = false\n setCheckState(\"checking\")\n }\n\n const myGeneration = ++performCheckGenerationRef.current\n let cancelled = false\n let reconnectTimeout: ReturnType<typeof setTimeout> | null = null\n\n const performCheck = async () => {\n if (checkCompletedRef.current) return\n if (!otaSnapshot.connected) {\n if (isOtaAutoChainActive()) {\n const remainingMs = otaAutoChainReconnectWaitRemaining()\n if (remainingMs === null) return\n reconnectTimeout = setTimeout(() => {\n if (cancelled || myGeneration !== performCheckGenerationRef.current || ota.snapshot().connected) return\n stopOtaAutoChain()\n checkCompletedRef.current = true\n setCheckState(\"error\")\n }, remainingMs)\n return\n }\n if (checkStartedRef.current) {\n stopOtaAutoChain()\n checkCompletedRef.current = true\n setCheckState(\"error\")\n return\n }\n checkCompletedRef.current = true\n onFinishedRef.current?.()\n return\n }\n\n clearOtaAutoChainReconnectWait()\n checkStartedRef.current = true\n const startTime = Date.now()\n try {\n const checkOptions = {\n waitForBuildNumberMs: MAX_WAIT_FOR_VERSION_INFO_MS,\n waitForBesVersionMs: 5000,\n waitForMtkVersionMs: 2000,\n refreshVersionInfo: true,\n fixClockBeforeCheck: false,\n }\n let result = await ota.checkForUpdates(checkOptions)\n if (cancelled || myGeneration !== performCheckGenerationRef.current) return\n if (!result.hasCheckCompleted && result.checkFailureReason === \"network\" && isOtaAutoChainActive()) {\n await new Promise((resolve) => setTimeout(resolve, AUTO_CHAIN_NETWORK_RETRY_DELAY_MS))\n if (cancelled || myGeneration !== performCheckGenerationRef.current) return\n result = await ota.checkForUpdates(checkOptions)\n }\n if (cancelled || myGeneration !== performCheckGenerationRef.current) return\n selectedCheckResultRef.current = result\n await new Promise((resolve) => setTimeout(resolve, Math.max(0, MIN_DISPLAY_TIME_MS - (Date.now() - startTime))))\n if (cancelled || myGeneration !== performCheckGenerationRef.current) return\n\n if (result.skippedReason === \"disconnected\") {\n stopOtaAutoChain()\n checkCompletedRef.current = true\n setCheckState(\"error\")\n return\n }\n if (result.skippedReason === \"missing_build\") {\n checkCompletedRef.current = true\n if (isOtaAutoChainActive()) {\n stopOtaAutoChain()\n setCheckState(\"error\")\n } else {\n onFinishedRef.current?.()\n }\n return\n }\n if (result.skippedReason === \"dev_build\") {\n stopOtaAutoChain()\n checkCompletedRef.current = true\n ota.clearUpdateAvailable()\n setCheckState(\"dev_build\")\n return\n }\n if (!result.hasCheckCompleted) {\n stopOtaAutoChain()\n checkCompletedRef.current = true\n setErrorKind(result.checkFailureReason === \"pin_unavailable\" ? \"pin_unavailable\" : \"network\")\n setCheckState(\"error\")\n return\n }\n if (result.updateAvailable && result.updateInfo) {\n setIsUpdateRequired(result.isRequired)\n setIsVersionChange(result.updateInfo.isDowngrade === true)\n const fingerprint = otaAutoChainFingerprint(result)\n setUpdateFingerprint(fingerprint)\n if (isOtaAutoChainActive()) {\n const snapshot = ota.snapshot()\n if (!snapshot.wifiStatusKnown) return\n if (!snapshot.wifiConnected && snapshot.hotspotOtaVersion !== 1) {\n stopOtaAutoChain()\n } else {\n const admission = tryAdvanceOtaAutoChain(fingerprint, result.updateInfo.isDowngrade === true)\n if (admission.advance) {\n checkCompletedRef.current = true\n ota.installSession.prepare(result)\n navigateToProgress()\n return\n }\n }\n }\n checkCompletedRef.current = true\n setCheckState(\"update_available\")\n return\n }\n stopOtaAutoChain()\n checkCompletedRef.current = true\n ota.clearUpdateAvailable()\n setCheckState(\"no_update\")\n } catch (error) {\n console.error(\"OTA check failed:\", error)\n await new Promise((resolve) => setTimeout(resolve, Math.max(0, MIN_DISPLAY_TIME_MS - (Date.now() - startTime))))\n if (cancelled || myGeneration !== performCheckGenerationRef.current) return\n stopOtaAutoChain()\n checkCompletedRef.current = true\n setErrorKind(\"network\")\n setCheckState(\"error\")\n }\n }\n\n void performCheck()\n return () => {\n cancelled = true\n if (reconnectTimeout) clearTimeout(reconnectTimeout)\n }\n }, [checkGeneration, navigateToProgress, otaSnapshot.connected, otaSnapshot.wifiStatusKnown, page, runtimeReady])\n\n useEffect(() => {\n if (!runtimeReady || page !== \"progress\") return\n ota.installSession.attach()\n return () => ota.installSession.detach()\n }, [page, runtimeReady])\n\n const firmwareRestarting =\n page === \"progress\" &&\n ((!installSnapshot.connected && installSnapshot.displayState === \"restarting\") ||\n installSnapshot.versionChangePhase === \"restarting\")\n\n useEffect(() => {\n if (page !== \"progress\") return\n onFirmwareRestartingChangeRef.current?.(firmwareRestarting, true)\n }, [firmwareRestarting, page])\n\n useEffect(() => {\n if (page !== \"progress\") return\n return () => {\n onFirmwareRestartingChangeRef.current?.(false, false)\n }\n }, [page])\n\n useEffect(() => {\n if (\n page !== \"progress\" ||\n installSnapshot.displayState !== \"complete\" ||\n !installSnapshot.connected ||\n !isOtaAutoChainActive() ||\n autoChainAdvancedRef.current\n ) {\n return\n }\n const timeout = setTimeout(() => {\n if (!isOtaAutoChainActive()) return\n autoChainAdvancedRef.current = true\n ota.installSession.finish()\n returnToCheck()\n }, AUTO_CHAIN_COMPLETE_DELAY_MS)\n return () => clearTimeout(timeout)\n }, [installSnapshot.connected, installSnapshot.displayState, page, returnToCheck])\n\n const check = useCallback(() => {\n setPage(\"check\")\n setCheckState(\"checking\")\n setCheckGeneration((generation) => generation + 1)\n }, [])\n\n const install = useCallback(() => {\n if (installActionPendingRef.current || page !== \"check\") return\n const result = selectedCheckResultRef.current\n if (!result) {\n setErrorKind(\"network\")\n setCheckState(\"error\")\n return\n }\n const snapshot = ota.snapshot()\n if (!snapshot.wifiStatusKnown) {\n check()\n return\n }\n if (!snapshot.wifiConnected && snapshot.hotspotOtaVersion !== 1) {\n onOpenWifiSetupRef.current?.()\n return\n }\n ota.installSession.prepare(result)\n if (updateFingerprint) beginOtaAutoChain(updateFingerprint, isVersionChange)\n navigateToProgress()\n }, [check, isVersionChange, navigateToProgress, page, updateFingerprint])\n\n const retryInstall = useCallback(() => {\n if (page !== \"progress\") return\n onFirmwareRestartingChangeRef.current?.(false, true)\n ota.installSession.retry()\n }, [page])\n\n const finish = useCallback(() => {\n if (page === \"check\") {\n onFinishedRef.current?.()\n return\n }\n if (installSnapshot.displayState === \"restarting\") stopOtaAutoChain()\n const requiresGlassesReboot = shouldRequireGlassesRebootForBesFailure(\n installSnapshot.otaStatus,\n installSnapshot.otaProgress,\n installSnapshot.errorMsg,\n )\n if (requiresGlassesReboot) stopOtaAutoChain()\n ota.installSession.finish()\n returnToCheck()\n }, [installSnapshot, page, returnToCheck])\n\n const discard = useCallback(() => {\n if (page !== \"progress\") return\n stopOtaAutoChain()\n ota.installSession.discard()\n returnToCheck()\n }, [page, returnToCheck])\n\n const openWifiSetup = useCallback(() => {\n if (page === \"progress\") stopOtaAutoChain()\n onOpenWifiSetupRef.current?.()\n }, [page])\n\n const state = useMemo<MentraLiveOtaState>(() => {\n const hotspotSupported = otaSnapshot.hotspotOtaVersion === 1\n const canInstall = otaSnapshot.wifiStatusKnown && (otaSnapshot.wifiConnected || hotspotSupported)\n if (!runtimeReady) {\n return {\n screen: \"initializing\",\n connected: otaSnapshot.connected,\n transport: null,\n updateRequired: isUpdateRequired,\n versionChange: isVersionChange,\n versionChangeConverged: false,\n versionChangePhase: null,\n wifiConnected: otaSnapshot.wifiConnected,\n wifiStatusKnown: otaSnapshot.wifiStatusKnown,\n hotspotSupported,\n hotspotPhase: \"idle\",\n hotspotArtifactPercent: null,\n phase: null,\n step: null,\n currentStep: null,\n totalSteps: null,\n progress: null,\n installingApkOnly: false,\n firmwareRestarting: false,\n error: null,\n canInstall: false,\n canRetry: false,\n canFinish: false,\n canDismiss: false,\n canDiscard: false,\n canOpenWifiSetup: false,\n continueDisabled: false,\n }\n }\n\n if (page === \"check\") {\n const wifiRequired = otaSnapshot.wifiStatusKnown && !otaSnapshot.wifiConnected && !hotspotSupported\n const screen: MentraLiveOtaScreen =\n checkState === \"checking\"\n ? \"checking\"\n : checkState === \"update_available\"\n ? wifiRequired\n ? \"wifi_required\"\n : \"update_available\"\n : checkState === \"no_update\"\n ? \"up_to_date\"\n : checkState === \"dev_build\"\n ? \"dev_build\"\n : errorKind === \"pin_unavailable\"\n ? \"update_info_unavailable\"\n : \"check_failed\"\n const error: MentraLiveOtaError | null =\n screen === \"check_failed\"\n ? {code: \"check_failed\", message: \"Couldn't check for updates. Please check your connection and try again.\"}\n : screen === \"update_info_unavailable\"\n ? {code: \"update_info_unavailable\", message: \"Update information for this app version is unavailable.\"}\n : null\n return {\n screen,\n connected: otaSnapshot.connected,\n transport: otaSnapshot.wifiConnected ? \"wifi\" : hotspotSupported ? \"hotspot\" : null,\n updateRequired: isUpdateRequired,\n versionChange: isVersionChange,\n versionChangeConverged: false,\n versionChangePhase: null,\n wifiConnected: otaSnapshot.wifiConnected,\n wifiStatusKnown: otaSnapshot.wifiStatusKnown,\n hotspotSupported,\n hotspotPhase: \"idle\",\n hotspotArtifactPercent: null,\n phase: null,\n step: null,\n currentStep: null,\n totalSteps: null,\n progress: null,\n installingApkOnly: false,\n firmwareRestarting: false,\n error,\n canInstall: screen === \"update_available\" && canInstall,\n canRetry: screen === \"check_failed\",\n canFinish: screen === \"up_to_date\" || screen === \"dev_build\" || screen === \"update_info_unavailable\",\n canDismiss: (screen === \"update_available\" || screen === \"wifi_required\") && !isUpdateRequired,\n canDiscard: false,\n canOpenWifiSetup: screen === \"wifi_required\",\n continueDisabled: false,\n }\n }\n\n const requiresGlassesReboot = shouldRequireGlassesRebootForBesFailure(\n installSnapshot.otaStatus,\n installSnapshot.otaProgress,\n installSnapshot.errorMsg,\n )\n const showChangeWifi = shouldShowChangeWifiForOtaDownloadFailure(\n installSnapshot.otaStatus,\n installSnapshot.otaProgress,\n installSnapshot.errorMsg,\n )\n const displayedError = requiresGlassesReboot\n ? BES_INSTALL_RESTART_MESSAGE\n : installSnapshot.errorMsg || getOtaErrorMessage(installSnapshot.otaStatus?.error)\n const screen = progressScreen(installSnapshot)\n const error =\n screen === \"failed\"\n ? {\n code: requiresGlassesReboot ? (\"bes_restart_required\" as const) : (\"install_failed\" as const),\n message: displayedError,\n }\n : null\n const totalSteps = installSnapshot.otaStatus?.totalSteps ?? null\n return {\n screen,\n connected: installSnapshot.connected,\n transport: installSnapshot.transport,\n updateRequired: isUpdateRequired,\n versionChange: installSnapshot.isVersionChange,\n versionChangeConverged: installSnapshot.versionChangeConverged,\n versionChangePhase: installSnapshot.versionChangePhase,\n wifiConnected: otaSnapshot.wifiConnected,\n wifiStatusKnown: otaSnapshot.wifiStatusKnown,\n hotspotSupported,\n hotspotPhase: installSnapshot.hotspotPhase,\n hotspotArtifactPercent: installSnapshot.hotspotArtifactPercent,\n phase: installSnapshot.otaStatus?.phase ?? installSnapshot.otaProgress?.stage ?? null,\n step: installSnapshot.otaStatus?.stepType ?? null,\n currentStep: installSnapshot.otaStatus?.currentStep ?? null,\n totalSteps,\n progress: installProgress(installSnapshot),\n installingApkOnly:\n installSnapshot.otaStatus?.stepType === \"apk\" &&\n installSnapshot.otaStatus.phase === \"install\" &&\n totalSteps === 1,\n firmwareRestarting,\n error,\n canInstall: false,\n canRetry: screen === \"failed\" && !requiresGlassesReboot,\n canFinish: screen === \"complete\" || screen === \"restarting\" || (screen === \"failed\" && requiresGlassesReboot),\n canDismiss: false,\n canDiscard: screen === \"disconnected\",\n canOpenWifiSetup: screen === \"failed\" && showChangeWifi,\n continueDisabled: installSnapshot.continueButtonDisabled,\n }\n }, [\n checkState,\n errorKind,\n firmwareRestarting,\n installSnapshot,\n isUpdateRequired,\n isVersionChange,\n otaSnapshot,\n page,\n runtimeReady,\n ])\n\n return useMemo(\n () => ({state, check, retryCheck: check, install, retryInstall, finish, discard, openWifiSetup}),\n [check, discard, finish, install, openWifiSetup, retryInstall, state],\n )\n}\n"]}
@@ -1,4 +1,17 @@
1
- import type { GlassesStatus } from "@mentra/bluetooth-sdk/internal";
2
- export declare function startGlassesStatusProjection(forwarder?: (status: Partial<GlassesStatus>) => void): Promise<void>;
1
+ /**
2
+ * Glasses status projection engine-owned. Subscribes to the native bluetooth-sdk
3
+ * status events and projects them into the engine device stores, so engine's own
4
+ * services (which react to those stores) work for ANY host — not just the first-party
5
+ * Mentra app, where this used to live in MantleManager.
6
+ *
7
+ * This is the INBOUND mirror of GlassesSettingsSync: that pushes the settings store
8
+ * OUT to the device; this pulls device status IN to the stores. It's the feed that
9
+ * the rest of the engine runtime depends on (MicStateCoordinator, the settings-sync
10
+ * on-connect trigger, the facade read-models all read these stores).
11
+ *
12
+ * Started by `engine.start()`. Idempotent.
13
+ */
14
+ import { type PublicGlassesStatus } from "@mentra/bluetooth-sdk";
15
+ export declare function startGlassesStatusProjection(forwarder?: (status: Partial<PublicGlassesStatus>) => void): Promise<void>;
3
16
  export declare function stopGlassesStatusProjection(): void;
4
17
  //# sourceMappingURL=GlassesStatusProjection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GlassesStatusProjection.d.ts","sourceRoot":"","sources":["../../src/services/GlassesStatusProjection.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,gCAAgC,CAAA;AASjE,wBAAgB,4BAA4B,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDhH;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAMlD"}
1
+ {"version":3,"file":"GlassesStatusProjection.d.ts","sourceRoot":"","sources":["../../src/services/GlassesStatusProjection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAqB,EAAC,KAAK,mBAAmB,EAAC,MAAM,uBAAuB,CAAA;AAS5E,wBAAgB,4BAA4B,CAC1C,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,mBAAmB,CAAC,KAAK,IAAI,GACzD,OAAO,CAAC,IAAI,CAAC,CAiDf;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAMlD"}
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * Started by `engine.start()`. Idempotent.
13
13
  */
14
- import BluetoothSdk from "@mentra/bluetooth-sdk/internal";
14
+ import BluetoothSdk from "@mentra/bluetooth-sdk";
15
15
  import { useCoreStore } from "../stores/core";
16
16
  import { useGlassesStore } from "../stores/glasses";
17
17
  let unsubs = [];
@@ -45,13 +45,13 @@ export function startGlassesStatusProjection(forwarder) {
45
45
  console.warn("GlassesStatusProjection: getGlassesStatus failed", error);
46
46
  });
47
47
  // Bluetooth-adapter status -> core store.
48
- unsubs.push(BluetoothSdk.onBluetoothStatus((changed) => {
48
+ unsubs.push(BluetoothSdk.subscribeBluetoothStatus((changed) => {
49
49
  bluetoothEventSeen = true;
50
50
  useCoreStore.getState().setCoreInfo(changed);
51
51
  }));
52
52
  // Glasses status -> glasses store (+ optional full-runtime forwarding to local
53
53
  // miniapps; clear any stale OTA-available flag on disconnect).
54
- unsubs.push(BluetoothSdk.onGlassesStatus((changed) => {
54
+ unsubs.push(BluetoothSdk.subscribeGlassesStatus((changed) => {
55
55
  glassesEventSeen = true;
56
56
  useGlassesStore.getState().setGlassesInfo(changed);
57
57
  glassesStatusForwarder?.(changed);