@mentra/engine 3.1.0-dev.28 → 3.1.0-dev.33

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.
@@ -1,10 +1,29 @@
1
1
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
2
  import { ota } from "../facades/ota";
3
- import { beginOtaAutoChain, clearOtaAutoChainReconnectWait, isOtaAutoChainActive, otaAutoChainFingerprint, otaAutoChainReconnectWaitRemaining, stopOtaAutoChain, tryAdvanceOtaAutoChain, } from "../services/OtaAutoChain";
3
+ import { beginOtaAutoChain, clearOtaAutoChainReconnectWait, isOtaAutoChainActive, otaAutoChainFingerprint, otaAutoChainReleaseRange, otaAutoChainReconnectWaitRemaining, stopOtaAutoChain, tryAdvanceOtaAutoChain, } from "../services/OtaAutoChain";
4
4
  import { BES_INSTALL_RESTART_MESSAGE, getOtaErrorMessage, shouldRequireGlassesRebootForBesFailure, shouldShowChangeWifiForOtaDownloadFailure, } from "../services/OtaErrorMapping";
5
5
  import { useEngineSnapshot } from "./useEngineSnapshot";
6
6
  const AUTO_CHAIN_NETWORK_RETRY_DELAY_MS = 5000;
7
7
  const AUTO_CHAIN_COMPLETE_DELAY_MS = 750;
8
+ function targetVersion(result) {
9
+ return result.updateInfo?.versionName ?? result.latestVersionInfo?.versionName ?? null;
10
+ }
11
+ function releaseChangelogsForActiveChain() {
12
+ const range = otaAutoChainReleaseRange();
13
+ if (!range?.toVersion)
14
+ return [];
15
+ try {
16
+ return ota.getReleaseChangelogs(range.fromVersion, range.toVersion);
17
+ }
18
+ catch {
19
+ try {
20
+ return ota.getReleaseChangelogs(null, range.toVersion);
21
+ }
22
+ catch {
23
+ return [];
24
+ }
25
+ }
26
+ }
8
27
  function installProgress(snapshot) {
9
28
  if (snapshot.displayState !== "updating")
10
29
  return null;
@@ -12,10 +31,10 @@ function installProgress(snapshot) {
12
31
  const isDownload = otaStatus?.phase === "download";
13
32
  const totalSteps = otaStatus?.totalSteps ?? 1;
14
33
  const rawPercent = isDownload
15
- ? (otaStatus?.stepPercent ?? 0)
34
+ ? otaStatus?.stepPercent ?? 0
16
35
  : totalSteps >= 2
17
- ? (otaStatus?.overallPercent ?? 0)
18
- : (otaStatus?.stepPercent ?? 0);
36
+ ? otaStatus?.overallPercent ?? 0
37
+ : otaStatus?.stepPercent ?? 0;
19
38
  return Math.min(Math.max(rawPercent, snapshot.mtkInstallStallSimulatedPercent ?? 0, 0), 100);
20
39
  }
21
40
  function progressScreen(snapshot) {
@@ -54,6 +73,7 @@ export function useMentraLiveOta(options = {}) {
54
73
  const [isVersionChange, setIsVersionChange] = useState(false);
55
74
  const [errorKind, setErrorKind] = useState("network");
56
75
  const [updateFingerprint, setUpdateFingerprint] = useState(null);
76
+ const [completedChangelogs, setCompletedChangelogs] = useState([]);
57
77
  const [checkGeneration, setCheckGeneration] = useState(0);
58
78
  const performCheckGenerationRef = useRef(0);
59
79
  const activeCheckKeyRef = useRef(null);
@@ -208,7 +228,7 @@ export function useMentraLiveOta(options = {}) {
208
228
  stopOtaAutoChain();
209
229
  }
210
230
  else {
211
- const admission = tryAdvanceOtaAutoChain(fingerprint, result.updateInfo.isDowngrade === true);
231
+ const admission = tryAdvanceOtaAutoChain(fingerprint, result.updateInfo.isDowngrade === true, targetVersion(result));
212
232
  if (admission.advance) {
213
233
  checkCompletedRef.current = true;
214
234
  ota.installSession.prepare(result);
@@ -221,6 +241,8 @@ export function useMentraLiveOta(options = {}) {
221
241
  setCheckState("update_available");
222
242
  return;
223
243
  }
244
+ if (isOtaAutoChainActive())
245
+ setCompletedChangelogs(releaseChangelogsForActiveChain());
224
246
  stopOtaAutoChain();
225
247
  checkCompletedRef.current = true;
226
248
  ota.clearUpdateAvailable();
@@ -283,6 +305,7 @@ export function useMentraLiveOta(options = {}) {
283
305
  return () => clearTimeout(timeout);
284
306
  }, [installSnapshot.connected, installSnapshot.displayState, page, returnToCheck]);
285
307
  const check = useCallback(() => {
308
+ setCompletedChangelogs([]);
286
309
  setPage("check");
287
310
  setCheckState("checking");
288
311
  setCheckGeneration((generation) => generation + 1);
@@ -306,8 +329,13 @@ export function useMentraLiveOta(options = {}) {
306
329
  return;
307
330
  }
308
331
  ota.installSession.prepare(result);
309
- if (updateFingerprint)
310
- beginOtaAutoChain(updateFingerprint, isVersionChange);
332
+ setCompletedChangelogs([]);
333
+ if (updateFingerprint) {
334
+ beginOtaAutoChain(updateFingerprint, isVersionChange, {
335
+ fromVersion: snapshot.appVersion,
336
+ toVersion: targetVersion(result),
337
+ });
338
+ }
311
339
  navigateToProgress();
312
340
  }, [check, isVersionChange, navigateToProgress, page, updateFingerprint]);
313
341
  const retryInstall = useCallback(() => {
@@ -373,6 +401,7 @@ export function useMentraLiveOta(options = {}) {
373
401
  canDiscard: false,
374
402
  canOpenWifiSetup: false,
375
403
  continueDisabled: false,
404
+ changelogs: [],
376
405
  };
377
406
  }
378
407
  if (page === "check") {
@@ -423,6 +452,7 @@ export function useMentraLiveOta(options = {}) {
423
452
  canDiscard: false,
424
453
  canOpenWifiSetup: screen === "wifi_required",
425
454
  continueDisabled: false,
455
+ changelogs: screen === "up_to_date" ? completedChangelogs : [],
426
456
  };
427
457
  }
428
458
  const requiresGlassesReboot = shouldRequireGlassesRebootForBesFailure(installSnapshot.otaStatus, installSnapshot.otaProgress, installSnapshot.errorMsg);
@@ -438,6 +468,7 @@ export function useMentraLiveOta(options = {}) {
438
468
  }
439
469
  : null;
440
470
  const totalSteps = installSnapshot.otaStatus?.totalSteps ?? null;
471
+ const changelogs = screen === "complete" ? releaseChangelogsForActiveChain() : [];
441
472
  return {
442
473
  screen,
443
474
  connected: installSnapshot.connected,
@@ -468,9 +499,11 @@ export function useMentraLiveOta(options = {}) {
468
499
  canDiscard: screen === "disconnected",
469
500
  canOpenWifiSetup: screen === "failed" && showChangeWifi,
470
501
  continueDisabled: installSnapshot.continueButtonDisabled,
502
+ changelogs,
471
503
  };
472
504
  }, [
473
505
  checkState,
506
+ completedChangelogs,
474
507
  errorKind,
475
508
  firmwareRestarting,
476
509
  installSnapshot,
@@ -1 +1 @@
1
- {"version":3,"file":"useMentraLiveOta.js","sourceRoot":"","sources":["../../src/react/useMentraLiveOta.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAA;AAEvE,OAAO,EAAC,GAAG,EAAC,MAAM,gBAAgB,CAAA;AAClC,OAAO,EACL,iBAAiB,EACjB,8BAA8B,EAC9B,oBAAoB,EACpB,uBAAuB,EACvB,kCAAkC,EAClC,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,2BAA2B,EAC3B,kBAAkB,EAClB,uCAAuC,EACvC,yCAAyC,GAC1C,MAAM,6BAA6B,CAAA;AAGpC,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAA;AA8FrD,MAAM,iCAAiC,GAAG,IAAI,CAAA;AAC9C,MAAM,4BAA4B,GAAG,GAAG,CAAA;AAExC,SAAS,eAAe,CAAC,QAA4B;IACnD,IAAI,QAAQ,CAAC,YAAY,KAAK,UAAU;QAAE,OAAO,IAAI,CAAA;IACrD,MAAM,EAAC,SAAS,EAAC,GAAG,QAAQ,CAAA;IAC5B,MAAM,UAAU,GAAG,SAAS,EAAE,KAAK,KAAK,UAAU,CAAA;IAClD,MAAM,UAAU,GAAG,SAAS,EAAE,UAAU,IAAI,CAAC,CAAA;IAC7C,MAAM,UAAU,GAAG,UAAU;QAC3B,CAAC,CAAC,CAAC,SAAS,EAAE,WAAW,IAAI,CAAC,CAAC;QAC/B,CAAC,CAAC,UAAU,IAAI,CAAC;YACf,CAAC,CAAC,CAAC,SAAS,EAAE,cAAc,IAAI,CAAC,CAAC;YAClC,CAAC,CAAC,CAAC,SAAS,EAAE,WAAW,IAAI,CAAC,CAAC,CAAA;IACnC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,+BAA+B,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AAC9F,CAAC;AAED,SAAS,cAAc,CAAC,QAA4B;IAClD,IAAI,QAAQ,CAAC,kBAAkB,KAAK,YAAY;QAAE,OAAO,YAAY,CAAA;IACrE,IAAI,QAAQ,CAAC,kBAAkB,KAAK,WAAW;QAAE,OAAO,WAAW,CAAA;IACnE,QAAQ,QAAQ,CAAC,YAAY,EAAE,CAAC;QAC9B,KAAK,UAAU;YACb,OAAO,QAAQ,CAAC,YAAY,KAAK,MAAM,IAAI,QAAQ,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAA;QACnH,KAAK,UAAU;YACb,OAAO,UAAU,CAAA;QACnB,KAAK,YAAY;YACf,OAAO,YAAY,CAAA;QACrB,KAAK,UAAU;YACb,OAAO,UAAU,CAAA;QACnB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAA;QACjB;YACE,OAAO,cAAc,CAAA;IACzB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAmC,EAAE;IACpE,MAAM,EACJ,WAAW,GAAG,OAAO,EACrB,iBAAiB,GAAG,IAAI,EACxB,UAAU,EACV,0BAA0B,EAC1B,eAAe,GAChB,GAAG,OAAO,CAAA;IACX,MAAM,WAAW,GAAG,iBAAiB,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,UAAU,CAAC,CAAA;IACnE,MAAM,eAAe,GAAG,iBAAiB,CAAC,GAAG,CAAC,cAAc,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,CAAA;IACrG,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAwB,WAAW,CAAC,CAAA;IACpE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,CAAC,iBAAiB,CAAC,CAAA;IACpE,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAa,UAAU,CAAC,CAAA;IACpE,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC9D,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC7D,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAgC,SAAS,CAAC,CAAA;IACpF,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAA;IAC/E,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IACzD,MAAM,yBAAyB,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;IAC3C,MAAM,iBAAiB,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAA;IACrD,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IACrC,MAAM,iBAAiB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IACvC,MAAM,sBAAsB,GAAG,MAAM,CAAsC,IAAI,CAAC,CAAA;IAChF,MAAM,oBAAoB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAC1C,MAAM,uBAAuB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAC7C,MAAM,aAAa,GAAG,MAAM,CAAC,UAAU,CAAC,CAAA;IACxC,MAAM,kBAAkB,GAAG,MAAM,CAAC,eAAe,CAAC,CAAA;IAClD,MAAM,6BAA6B,GAAG,MAAM,CAAC,0BAA0B,CAAC,CAAA;IACxE,aAAa,CAAC,OAAO,GAAG,UAAU,CAAA;IAClC,kBAAkB,CAAC,OAAO,GAAG,eAAe,CAAA;IAC5C,6BAA6B,CAAC,OAAO,GAAG,0BAA0B,CAAA;IAElE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,eAAe,CAAC,IAAI,CAAC,CAAA;YACrB,OAAM;QACR,CAAC;QACD,IAAI,SAAS,GAAG,KAAK,CAAA;QACrB,eAAe,CAAC,KAAK,CAAC,CAAA;QACtB,KAAK,GAAG,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;YACjC,IAAI,CAAC,SAAS;gBAAE,eAAe,CAAC,IAAI,CAAC,CAAA;QACvC,CAAC,CAAC,CAAA;QACF,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAA;QAClB,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAA;IAEvB,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,EAAE;QACrC,uBAAuB,CAAC,OAAO,GAAG,KAAK,CAAA;QACvC,oBAAoB,CAAC,OAAO,GAAG,KAAK,CAAA;QACpC,OAAO,CAAC,OAAO,CAAC,CAAA;QAChB,kBAAkB,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC,CAAA;IACpD,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,kBAAkB,GAAG,WAAW,CAAC,GAAG,EAAE;QAC1C,uBAAuB,CAAC,OAAO,GAAG,IAAI,CAAA;QACtC,GAAG,CAAC,aAAa,EAAE,CAAA;QACnB,OAAO,CAAC,UAAU,CAAC,CAAA;IACrB,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,YAAY,IAAI,IAAI,KAAK,OAAO;YAAE,OAAM;QAC7C,MAAM,mBAAmB,GAAG,IAAI,CAAA;QAChC,MAAM,4BAA4B,GAAG,MAAM,CAAA;QAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,eAAe,CAAC,CAAA;QACxC,IAAI,iBAAiB,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC3C,iBAAiB,CAAC,OAAO,GAAG,QAAQ,CAAA;YACpC,eAAe,CAAC,OAAO,GAAG,KAAK,CAAA;YAC/B,iBAAiB,CAAC,OAAO,GAAG,KAAK,CAAA;YACjC,sBAAsB,CAAC,OAAO,GAAG,IAAI,CAAA;YACrC,uBAAuB,CAAC,OAAO,GAAG,KAAK,CAAA;YACvC,aAAa,CAAC,UAAU,CAAC,CAAA;QAC3B,CAAC;QAED,MAAM,YAAY,GAAG,EAAE,yBAAyB,CAAC,OAAO,CAAA;QACxD,IAAI,SAAS,GAAG,KAAK,CAAA;QACrB,IAAI,gBAAgB,GAAyC,IAAI,CAAA;QAEjE,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;YAC9B,IAAI,iBAAiB,CAAC,OAAO;gBAAE,OAAM;YACrC,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;gBAC3B,IAAI,oBAAoB,EAAE,EAAE,CAAC;oBAC3B,MAAM,WAAW,GAAG,kCAAkC,EAAE,CAAA;oBACxD,IAAI,WAAW,KAAK,IAAI;wBAAE,OAAM;oBAChC,gBAAgB,GAAG,UAAU,CAAC,GAAG,EAAE;wBACjC,IAAI,SAAS,IAAI,YAAY,KAAK,yBAAyB,CAAC,OAAO,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC,SAAS;4BAAE,OAAM;wBACvG,gBAAgB,EAAE,CAAA;wBAClB,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;wBAChC,aAAa,CAAC,OAAO,CAAC,CAAA;oBACxB,CAAC,EAAE,WAAW,CAAC,CAAA;oBACf,OAAM;gBACR,CAAC;gBACD,IAAI,eAAe,CAAC,OAAO,EAAE,CAAC;oBAC5B,gBAAgB,EAAE,CAAA;oBAClB,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;oBAChC,aAAa,CAAC,OAAO,CAAC,CAAA;oBACtB,OAAM;gBACR,CAAC;gBACD,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;gBAChC,aAAa,CAAC,OAAO,EAAE,EAAE,CAAA;gBACzB,OAAM;YACR,CAAC;YAED,8BAA8B,EAAE,CAAA;YAChC,eAAe,CAAC,OAAO,GAAG,IAAI,CAAA;YAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YAC5B,IAAI,CAAC;gBACH,MAAM,YAAY,GAAG;oBACnB,oBAAoB,EAAE,4BAA4B;oBAClD,mBAAmB,EAAE,IAAI;oBACzB,mBAAmB,EAAE,IAAI;oBACzB,kBAAkB,EAAE,IAAI;oBACxB,mBAAmB,EAAE,KAAK;iBAC3B,CAAA;gBACD,IAAI,MAAM,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,YAAY,CAAC,CAAA;gBACpD,IAAI,SAAS,IAAI,YAAY,KAAK,yBAAyB,CAAC,OAAO;oBAAE,OAAM;gBAC3E,IAAI,CAAC,MAAM,CAAC,iBAAiB,IAAI,MAAM,CAAC,kBAAkB,KAAK,SAAS,IAAI,oBAAoB,EAAE,EAAE,CAAC;oBACnG,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,iCAAiC,CAAC,CAAC,CAAA;oBACtF,IAAI,SAAS,IAAI,YAAY,KAAK,yBAAyB,CAAC,OAAO;wBAAE,OAAM;oBAC3E,MAAM,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,YAAY,CAAC,CAAA;gBAClD,CAAC;gBACD,IAAI,SAAS,IAAI,YAAY,KAAK,yBAAyB,CAAC,OAAO;oBAAE,OAAM;gBAC3E,sBAAsB,CAAC,OAAO,GAAG,MAAM,CAAA;gBACvC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,mBAAmB,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;gBAChH,IAAI,SAAS,IAAI,YAAY,KAAK,yBAAyB,CAAC,OAAO;oBAAE,OAAM;gBAE3E,IAAI,MAAM,CAAC,aAAa,KAAK,cAAc,EAAE,CAAC;oBAC5C,gBAAgB,EAAE,CAAA;oBAClB,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;oBAChC,aAAa,CAAC,OAAO,CAAC,CAAA;oBACtB,OAAM;gBACR,CAAC;gBACD,IAAI,MAAM,CAAC,aAAa,KAAK,eAAe,EAAE,CAAC;oBAC7C,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;oBAChC,IAAI,oBAAoB,EAAE,EAAE,CAAC;wBAC3B,gBAAgB,EAAE,CAAA;wBAClB,aAAa,CAAC,OAAO,CAAC,CAAA;oBACxB,CAAC;yBAAM,CAAC;wBACN,aAAa,CAAC,OAAO,EAAE,EAAE,CAAA;oBAC3B,CAAC;oBACD,OAAM;gBACR,CAAC;gBACD,IAAI,MAAM,CAAC,aAAa,KAAK,WAAW,EAAE,CAAC;oBACzC,gBAAgB,EAAE,CAAA;oBAClB,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;oBAChC,GAAG,CAAC,oBAAoB,EAAE,CAAA;oBAC1B,aAAa,CAAC,WAAW,CAAC,CAAA;oBAC1B,OAAM;gBACR,CAAC;gBACD,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;oBAC9B,gBAAgB,EAAE,CAAA;oBAClB,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;oBAChC,YAAY,CAAC,MAAM,CAAC,kBAAkB,KAAK,iBAAiB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;oBAC7F,aAAa,CAAC,OAAO,CAAC,CAAA;oBACtB,OAAM;gBACR,CAAC;gBACD,IAAI,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;oBAChD,mBAAmB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;oBACtC,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,KAAK,IAAI,CAAC,CAAA;oBAC1D,MAAM,WAAW,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAA;oBACnD,oBAAoB,CAAC,WAAW,CAAC,CAAA;oBACjC,IAAI,oBAAoB,EAAE,EAAE,CAAC;wBAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAA;wBAC/B,IAAI,CAAC,QAAQ,CAAC,eAAe;4BAAE,OAAM;wBACrC,IAAI,CAAC,QAAQ,CAAC,aAAa,IAAI,QAAQ,CAAC,iBAAiB,KAAK,CAAC,EAAE,CAAC;4BAChE,gBAAgB,EAAE,CAAA;wBACpB,CAAC;6BAAM,CAAC;4BACN,MAAM,SAAS,GAAG,sBAAsB,CAAC,WAAW,EAAE,MAAM,CAAC,UAAU,CAAC,WAAW,KAAK,IAAI,CAAC,CAAA;4BAC7F,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;gCACtB,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;gCAChC,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;gCAClC,kBAAkB,EAAE,CAAA;gCACpB,OAAM;4BACR,CAAC;wBACH,CAAC;oBACH,CAAC;oBACD,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;oBAChC,aAAa,CAAC,kBAAkB,CAAC,CAAA;oBACjC,OAAM;gBACR,CAAC;gBACD,gBAAgB,EAAE,CAAA;gBAClB,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;gBAChC,GAAG,CAAC,oBAAoB,EAAE,CAAA;gBAC1B,aAAa,CAAC,WAAW,CAAC,CAAA;YAC5B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAA;gBACzC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,mBAAmB,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;gBAChH,IAAI,SAAS,IAAI,YAAY,KAAK,yBAAyB,CAAC,OAAO;oBAAE,OAAM;gBAC3E,gBAAgB,EAAE,CAAA;gBAClB,iBAAiB,CAAC,OAAO,GAAG,IAAI,CAAA;gBAChC,YAAY,CAAC,SAAS,CAAC,CAAA;gBACvB,aAAa,CAAC,OAAO,CAAC,CAAA;YACxB,CAAC;QACH,CAAC,CAAA;QAED,KAAK,YAAY,EAAE,CAAA;QACnB,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAA;YAChB,IAAI,gBAAgB;gBAAE,YAAY,CAAC,gBAAgB,CAAC,CAAA;QACtD,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,eAAe,EAAE,kBAAkB,EAAE,WAAW,CAAC,SAAS,EAAE,WAAW,CAAC,eAAe,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAA;IAEjH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,YAAY,IAAI,IAAI,KAAK,UAAU;YAAE,OAAM;QAChD,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,CAAA;QAC3B,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,CAAA;IAC1C,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAA;IAExB,MAAM,kBAAkB,GACtB,IAAI,KAAK,UAAU;QACnB,CAAC,CAAC,CAAC,eAAe,CAAC,SAAS,IAAI,eAAe,CAAC,YAAY,KAAK,YAAY,CAAC;YAC5E,eAAe,CAAC,kBAAkB,KAAK,YAAY,CAAC,CAAA;IAExD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,IAAI,KAAK,UAAU;YAAE,OAAM;QAC/B,6BAA6B,CAAC,OAAO,EAAE,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAA;IACnE,CAAC,EAAE,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC,CAAA;IAE9B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,IAAI,KAAK,UAAU;YAAE,OAAM;QAC/B,OAAO,GAAG,EAAE;YACV,6BAA6B,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QACvD,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;IAEV,SAAS,CAAC,GAAG,EAAE;QACb,IACE,IAAI,KAAK,UAAU;YACnB,eAAe,CAAC,YAAY,KAAK,UAAU;YAC3C,CAAC,eAAe,CAAC,SAAS;YAC1B,CAAC,oBAAoB,EAAE;YACvB,oBAAoB,CAAC,OAAO,EAC5B,CAAC;YACD,OAAM;QACR,CAAC;QACD,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,IAAI,EAAE;YACpC,IAAI,CAAC,oBAAoB,EAAE;gBAAE,OAAM;YACnC,oBAAoB,CAAC,OAAO,GAAG,IAAI,CAAA;YACnC,MAAM,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,CAAA;YACjC,aAAa,EAAE,CAAA;QACjB,CAAC,EAAE,4BAA4B,CAAC,CAAA;QAChC,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;IACpC,CAAC,EAAE,CAAC,eAAe,CAAC,SAAS,EAAE,eAAe,CAAC,YAAY,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAA;IAElF,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,OAAO,CAAC,OAAO,CAAC,CAAA;QAChB,aAAa,CAAC,UAAU,CAAC,CAAA;QACzB,kBAAkB,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC,CAAA;IACpD,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;QAC/B,IAAI,uBAAuB,CAAC,OAAO,IAAI,IAAI,KAAK,OAAO;YAAE,OAAM;QAC/D,MAAM,MAAM,GAAG,sBAAsB,CAAC,OAAO,CAAA;QAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,YAAY,CAAC,SAAS,CAAC,CAAA;YACvB,aAAa,CAAC,OAAO,CAAC,CAAA;YACtB,OAAM;QACR,CAAC;QACD,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAA;QAC/B,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC;YAC9B,KAAK,EAAE,CAAA;YACP,OAAM;QACR,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,aAAa,IAAI,QAAQ,CAAC,iBAAiB,KAAK,CAAC,EAAE,CAAC;YAChE,kBAAkB,CAAC,OAAO,EAAE,EAAE,CAAA;YAC9B,OAAM;QACR,CAAC;QACD,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAClC,IAAI,iBAAiB;YAAE,iBAAiB,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAA;QAC5E,kBAAkB,EAAE,CAAA;IACtB,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAA;IAEzE,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE;QACpC,IAAI,IAAI,KAAK,UAAU;YAAE,OAAM;QAC/B,6BAA6B,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACpD,GAAG,CAAC,cAAc,CAAC,KAAK,EAAE,CAAA;IAC5B,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;IAEV,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACpC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,aAAa,CAAC,OAAO,EAAE,EAAE,CAAA;YACzB,OAAM;QACR,CAAC;QACD,IAAI,eAAe,CAAC,YAAY,KAAK,YAAY;YAAE,gBAAgB,EAAE,CAAA;QACrE,MAAM,qBAAqB,GAAG,uCAAuC,CACnE,eAAe,CAAC,SAAS,EACzB,eAAe,CAAC,WAAW,EAC3B,eAAe,CAAC,QAAQ,CACzB,CAAA;QACD,IAAI,qBAAqB;YAAE,gBAAgB,EAAE,CAAA;QAC7C,MAAM,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,CAAA;QACjC,aAAa,EAAE,CAAA;IACjB,CAAC,EAAE,CAAC,eAAe,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC,CAAA;IAE1C,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACrC,IAAI,IAAI,KAAK,UAAU;YAAE,OAAM;QAC/B,gBAAgB,EAAE,CAAA;QAClB,MAAM,GAAG,CAAC,cAAc,CAAC,OAAO,EAAE,CAAA;QAClC,aAAa,EAAE,CAAA;IACjB,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAA;IAEzB,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,EAAE;QACrC,IAAI,IAAI,KAAK,UAAU;YAAE,gBAAgB,EAAE,CAAA;QAC3C,kBAAkB,CAAC,OAAO,EAAE,EAAE,CAAA;IAChC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;IAEV,MAAM,KAAK,GAAG,OAAO,CAAqB,GAAG,EAAE;QAC7C,MAAM,gBAAgB,GAAG,WAAW,CAAC,iBAAiB,KAAK,CAAC,CAAA;QAC5D,MAAM,UAAU,GAAG,WAAW,CAAC,eAAe,IAAI,CAAC,WAAW,CAAC,aAAa,IAAI,gBAAgB,CAAC,CAAA;QACjG,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO;gBACL,MAAM,EAAE,cAAc;gBACtB,SAAS,EAAE,WAAW,CAAC,SAAS;gBAChC,SAAS,EAAE,IAAI;gBACf,cAAc,EAAE,gBAAgB;gBAChC,aAAa,EAAE,eAAe;gBAC9B,sBAAsB,EAAE,KAAK;gBAC7B,kBAAkB,EAAE,IAAI;gBACxB,aAAa,EAAE,WAAW,CAAC,aAAa;gBACxC,eAAe,EAAE,WAAW,CAAC,eAAe;gBAC5C,gBAAgB;gBAChB,YAAY,EAAE,MAAM;gBACpB,sBAAsB,EAAE,IAAI;gBAC5B,KAAK,EAAE,IAAI;gBACX,IAAI,EAAE,IAAI;gBACV,WAAW,EAAE,IAAI;gBACjB,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE,IAAI;gBACd,iBAAiB,EAAE,KAAK;gBACxB,kBAAkB,EAAE,KAAK;gBACzB,KAAK,EAAE,IAAI;gBACX,UAAU,EAAE,KAAK;gBACjB,QAAQ,EAAE,KAAK;gBACf,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,KAAK;gBACjB,UAAU,EAAE,KAAK;gBACjB,gBAAgB,EAAE,KAAK;gBACvB,gBAAgB,EAAE,KAAK;aACxB,CAAA;QACH,CAAC;QAED,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,MAAM,YAAY,GAAG,WAAW,CAAC,eAAe,IAAI,CAAC,WAAW,CAAC,aAAa,IAAI,CAAC,gBAAgB,CAAA;YACnG,MAAM,MAAM,GACV,UAAU,KAAK,UAAU;gBACvB,CAAC,CAAC,UAAU;gBACZ,CAAC,CAAC,UAAU,KAAK,kBAAkB;oBACjC,CAAC,CAAC,YAAY;wBACZ,CAAC,CAAC,eAAe;wBACjB,CAAC,CAAC,kBAAkB;oBACtB,CAAC,CAAC,UAAU,KAAK,WAAW;wBAC1B,CAAC,CAAC,YAAY;wBACd,CAAC,CAAC,UAAU,KAAK,WAAW;4BAC1B,CAAC,CAAC,WAAW;4BACb,CAAC,CAAC,SAAS,KAAK,iBAAiB;gCAC/B,CAAC,CAAC,yBAAyB;gCAC3B,CAAC,CAAC,cAAc,CAAA;YAC5B,MAAM,KAAK,GACT,MAAM,KAAK,cAAc;gBACvB,CAAC,CAAC,EAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,yEAAyE,EAAC;gBAC5G,CAAC,CAAC,MAAM,KAAK,yBAAyB;oBACpC,CAAC,CAAC,EAAC,IAAI,EAAE,yBAAyB,EAAE,OAAO,EAAE,yDAAyD,EAAC;oBACvG,CAAC,CAAC,IAAI,CAAA;YACZ,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,WAAW,CAAC,SAAS;gBAChC,SAAS,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;gBACnF,cAAc,EAAE,gBAAgB;gBAChC,aAAa,EAAE,eAAe;gBAC9B,sBAAsB,EAAE,KAAK;gBAC7B,kBAAkB,EAAE,IAAI;gBACxB,aAAa,EAAE,WAAW,CAAC,aAAa;gBACxC,eAAe,EAAE,WAAW,CAAC,eAAe;gBAC5C,gBAAgB;gBAChB,YAAY,EAAE,MAAM;gBACpB,sBAAsB,EAAE,IAAI;gBAC5B,KAAK,EAAE,IAAI;gBACX,IAAI,EAAE,IAAI;gBACV,WAAW,EAAE,IAAI;gBACjB,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE,IAAI;gBACd,iBAAiB,EAAE,KAAK;gBACxB,kBAAkB,EAAE,KAAK;gBACzB,KAAK;gBACL,UAAU,EAAE,MAAM,KAAK,kBAAkB,IAAI,UAAU;gBACvD,QAAQ,EAAE,MAAM,KAAK,cAAc;gBACnC,SAAS,EAAE,MAAM,KAAK,YAAY,IAAI,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,yBAAyB;gBACpG,UAAU,EAAE,CAAC,MAAM,KAAK,kBAAkB,IAAI,MAAM,KAAK,eAAe,CAAC,IAAI,CAAC,gBAAgB;gBAC9F,UAAU,EAAE,KAAK;gBACjB,gBAAgB,EAAE,MAAM,KAAK,eAAe;gBAC5C,gBAAgB,EAAE,KAAK;aACxB,CAAA;QACH,CAAC;QAED,MAAM,qBAAqB,GAAG,uCAAuC,CACnE,eAAe,CAAC,SAAS,EACzB,eAAe,CAAC,WAAW,EAC3B,eAAe,CAAC,QAAQ,CACzB,CAAA;QACD,MAAM,cAAc,GAAG,yCAAyC,CAC9D,eAAe,CAAC,SAAS,EACzB,eAAe,CAAC,WAAW,EAC3B,eAAe,CAAC,QAAQ,CACzB,CAAA;QACD,MAAM,cAAc,GAAG,qBAAqB;YAC1C,CAAC,CAAC,2BAA2B;YAC7B,CAAC,CAAC,eAAe,CAAC,QAAQ,IAAI,kBAAkB,CAAC,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;QACpF,MAAM,MAAM,GAAG,cAAc,CAAC,eAAe,CAAC,CAAA;QAC9C,MAAM,KAAK,GACT,MAAM,KAAK,QAAQ;YACjB,CAAC,CAAC;gBACE,IAAI,EAAE,qBAAqB,CAAC,CAAC,CAAE,sBAAgC,CAAC,CAAC,CAAE,gBAA0B;gBAC7F,OAAO,EAAE,cAAc;aACxB;YACH,CAAC,CAAC,IAAI,CAAA;QACV,MAAM,UAAU,GAAG,eAAe,CAAC,SAAS,EAAE,UAAU,IAAI,IAAI,CAAA;QAChE,OAAO;YACL,MAAM;YACN,SAAS,EAAE,eAAe,CAAC,SAAS;YACpC,SAAS,EAAE,eAAe,CAAC,SAAS;YACpC,cAAc,EAAE,gBAAgB;YAChC,aAAa,EAAE,eAAe,CAAC,eAAe;YAC9C,sBAAsB,EAAE,eAAe,CAAC,sBAAsB;YAC9D,kBAAkB,EAAE,eAAe,CAAC,kBAAkB;YACtD,aAAa,EAAE,WAAW,CAAC,aAAa;YACxC,eAAe,EAAE,WAAW,CAAC,eAAe;YAC5C,gBAAgB;YAChB,YAAY,EAAE,eAAe,CAAC,YAAY;YAC1C,sBAAsB,EAAE,eAAe,CAAC,sBAAsB;YAC9D,KAAK,EAAE,eAAe,CAAC,SAAS,EAAE,KAAK,IAAI,eAAe,CAAC,WAAW,EAAE,KAAK,IAAI,IAAI;YACrF,IAAI,EAAE,eAAe,CAAC,SAAS,EAAE,QAAQ,IAAI,IAAI;YACjD,WAAW,EAAE,eAAe,CAAC,SAAS,EAAE,WAAW,IAAI,IAAI;YAC3D,UAAU;YACV,QAAQ,EAAE,eAAe,CAAC,eAAe,CAAC;YAC1C,iBAAiB,EACf,eAAe,CAAC,SAAS,EAAE,QAAQ,KAAK,KAAK;gBAC7C,eAAe,CAAC,SAAS,CAAC,KAAK,KAAK,SAAS;gBAC7C,UAAU,KAAK,CAAC;YAClB,kBAAkB;YAClB,KAAK;YACL,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,MAAM,KAAK,QAAQ,IAAI,CAAC,qBAAqB;YACvD,SAAS,EAAE,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,YAAY,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,qBAAqB,CAAC;YAC7G,UAAU,EAAE,KAAK;YACjB,UAAU,EAAE,MAAM,KAAK,cAAc;YACrC,gBAAgB,EAAE,MAAM,KAAK,QAAQ,IAAI,cAAc;YACvD,gBAAgB,EAAE,eAAe,CAAC,sBAAsB;SACzD,CAAA;IACH,CAAC,EAAE;QACD,UAAU;QACV,SAAS;QACT,kBAAkB;QAClB,eAAe;QACf,gBAAgB;QAChB,eAAe;QACf,WAAW;QACX,IAAI;QACJ,YAAY;KACb,CAAC,CAAA;IAEF,OAAO,OAAO,CACZ,GAAG,EAAE,CAAC,CAAC,EAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAC,CAAC,EAChG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,CAAC,CACtE,CAAA;AACH,CAAC","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(async () => {\n if (!isOtaAutoChainActive()) return\n autoChainAdvancedRef.current = true\n await 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(async () => {\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 await ota.installSession.finish()\n returnToCheck()\n }, [installSnapshot, page, returnToCheck])\n\n const discard = useCallback(async () => {\n if (page !== \"progress\") return\n stopOtaAutoChain()\n await 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
+ {"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 otaAutoChainReleaseRange,\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 type {ReleaseChangelog} from \"../facades/ota\"\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 /** Release notes crossed by this update, newest first. Populated on completion. */\n changelogs: ReleaseChangelog[]\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 targetVersion(result: OtaCheckCurrentGlassesResult): string | null {\n return result.updateInfo?.versionName ?? result.latestVersionInfo?.versionName ?? null\n}\n\nfunction releaseChangelogsForActiveChain(): ReleaseChangelog[] {\n const range = otaAutoChainReleaseRange()\n if (!range?.toVersion) return []\n try {\n return ota.getReleaseChangelogs(range.fromVersion, range.toVersion)\n } catch {\n try {\n return ota.getReleaseChangelogs(null, range.toVersion)\n } catch {\n return []\n }\n }\n}\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 [completedChangelogs, setCompletedChangelogs] = useState<ReleaseChangelog[]>([])\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(\n fingerprint,\n result.updateInfo.isDowngrade === true,\n targetVersion(result),\n )\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 if (isOtaAutoChainActive()) setCompletedChangelogs(releaseChangelogsForActiveChain())\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(async () => {\n if (!isOtaAutoChainActive()) return\n autoChainAdvancedRef.current = true\n await 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 setCompletedChangelogs([])\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 setCompletedChangelogs([])\n if (updateFingerprint) {\n beginOtaAutoChain(updateFingerprint, isVersionChange, {\n fromVersion: snapshot.appVersion,\n toVersion: targetVersion(result),\n })\n }\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(async () => {\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 await ota.installSession.finish()\n returnToCheck()\n }, [installSnapshot, page, returnToCheck])\n\n const discard = useCallback(async () => {\n if (page !== \"progress\") return\n stopOtaAutoChain()\n await 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 changelogs: [],\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 changelogs: screen === \"up_to_date\" ? completedChangelogs : [],\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 const changelogs = screen === \"complete\" ? releaseChangelogsForActiveChain() : []\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 changelogs,\n }\n }, [\n checkState,\n completedChangelogs,\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,6 +1,10 @@
1
1
  import type { OtaCheckCurrentGlassesResult } from "./OtaUpdateCheckService";
2
2
  export declare const MAX_OTA_AUTO_CHAIN_PASSES = 8;
3
3
  export declare const OTA_AUTO_CHAIN_RECONNECT_TIMEOUT_MS = 120000;
4
+ export type OtaAutoChainReleaseRange = {
5
+ fromVersion: string | null;
6
+ toVersion: string | null;
7
+ };
4
8
  export type OtaAutoChainAdvanceResult = {
5
9
  advance: true;
6
10
  passCount: number;
@@ -15,8 +19,9 @@ export type OtaAutoChainAdvanceResult = {
15
19
  */
16
20
  export declare function otaAutoChainFingerprint(result: OtaCheckCurrentGlassesResult): string;
17
21
  /** Start a chain after the user explicitly approves its first update pass. */
18
- export declare function beginOtaAutoChain(initialFingerprint: string, approvedDowngrade: boolean): void;
22
+ export declare function beginOtaAutoChain(initialFingerprint: string, approvedDowngrade: boolean, releaseRange: OtaAutoChainReleaseRange): void;
19
23
  export declare function isOtaAutoChainActive(): boolean;
24
+ export declare function otaAutoChainReleaseRange(): OtaAutoChainReleaseRange | null;
20
25
  /** End the current chain. Safe to call when no chain is active. */
21
26
  export declare function stopOtaAutoChain(): void;
22
27
  /**
@@ -30,5 +35,5 @@ export declare function clearOtaAutoChainReconnectWait(): void;
30
35
  * Admit the next pass of an active chain. Repeated offers, unexpectedly
31
36
  * destructive downgrades, and runaway chains fail closed and end automation.
32
37
  */
33
- export declare function tryAdvanceOtaAutoChain(fingerprint: string, isDowngrade: boolean): OtaAutoChainAdvanceResult;
38
+ export declare function tryAdvanceOtaAutoChain(fingerprint: string, isDowngrade: boolean, targetVersion: string | null): OtaAutoChainAdvanceResult;
34
39
  //# sourceMappingURL=OtaAutoChain.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"OtaAutoChain.d.ts","sourceRoot":"","sources":["../../src/services/OtaAutoChain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,yBAAyB,CAAA;AAEzE,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAC1C,eAAO,MAAM,mCAAmC,SAAU,CAAA;AAS1D,MAAM,MAAM,yBAAyB,GACjC;IAAC,OAAO,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,GAClC;IAAC,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,YAAY,GAAG,wBAAwB,CAAA;CAAC,CAAA;AAIhG;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,4BAA4B,GAAG,MAAM,CAkBpF;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,kBAAkB,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,GAAG,IAAI,CAO9F;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,mEAAmE;AACnE,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,GAAG,SAAoB,GAAG,MAAM,GAAG,IAAI,CAKzF;AAED,6EAA6E;AAC7E,wBAAgB,8BAA8B,IAAI,IAAI,CAErD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,yBAAyB,CAuB3G"}
1
+ {"version":3,"file":"OtaAutoChain.d.ts","sourceRoot":"","sources":["../../src/services/OtaAutoChain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,4BAA4B,EAAC,MAAM,yBAAyB,CAAA;AAEzE,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAC1C,eAAO,MAAM,mCAAmC,SAAU,CAAA;AAU1D,MAAM,MAAM,wBAAwB,GAAG;IACrC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,yBAAyB,GACjC;IAAC,OAAO,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,GAClC;IAAC,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,YAAY,GAAG,wBAAwB,CAAA;CAAC,CAAA;AAIhG;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,4BAA4B,GAAG,MAAM,CAkBpF;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAC/B,kBAAkB,EAAE,MAAM,EAC1B,iBAAiB,EAAE,OAAO,EAC1B,YAAY,EAAE,wBAAwB,GACrC,IAAI,CAQN;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,wBAAgB,wBAAwB,IAAI,wBAAwB,GAAG,IAAI,CAE1E;AAED,mEAAmE;AACnE,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,GAAG,SAAoB,GAAG,MAAM,GAAG,IAAI,CAKzF;AAED,6EAA6E;AAC7E,wBAAgB,8BAA8B,IAAI,IAAI,CAErD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,OAAO,EACpB,aAAa,EAAE,MAAM,GAAG,IAAI,GAC3B,yBAAyB,CAwB3B"}
@@ -26,10 +26,11 @@ export function otaAutoChainFingerprint(result) {
26
26
  });
27
27
  }
28
28
  /** Start a chain after the user explicitly approves its first update pass. */
29
- export function beginOtaAutoChain(initialFingerprint, approvedDowngrade) {
29
+ export function beginOtaAutoChain(initialFingerprint, approvedDowngrade, releaseRange) {
30
30
  session = {
31
31
  approvedDowngrade,
32
32
  passCount: 1,
33
+ releaseRange: { ...releaseRange },
33
34
  reconnectDeadline: null,
34
35
  seenFingerprints: new Set([initialFingerprint]),
35
36
  };
@@ -37,6 +38,9 @@ export function beginOtaAutoChain(initialFingerprint, approvedDowngrade) {
37
38
  export function isOtaAutoChainActive() {
38
39
  return session !== null;
39
40
  }
41
+ export function otaAutoChainReleaseRange() {
42
+ return session ? { ...session.releaseRange } : null;
43
+ }
40
44
  /** End the current chain. Safe to call when no chain is active. */
41
45
  export function stopOtaAutoChain() {
42
46
  session = null;
@@ -60,7 +64,7 @@ export function clearOtaAutoChainReconnectWait() {
60
64
  * Admit the next pass of an active chain. Repeated offers, unexpectedly
61
65
  * destructive downgrades, and runaway chains fail closed and end automation.
62
66
  */
63
- export function tryAdvanceOtaAutoChain(fingerprint, isDowngrade) {
67
+ export function tryAdvanceOtaAutoChain(fingerprint, isDowngrade, targetVersion) {
64
68
  if (!session) {
65
69
  return { advance: false, reason: "inactive" };
66
70
  }
@@ -78,6 +82,8 @@ export function tryAdvanceOtaAutoChain(fingerprint, isDowngrade) {
78
82
  }
79
83
  session.seenFingerprints.add(fingerprint);
80
84
  session.passCount += 1;
85
+ if (targetVersion)
86
+ session.releaseRange.toVersion = targetVersion;
81
87
  return { advance: true, passCount: session.passCount };
82
88
  }
83
89
  //# sourceMappingURL=OtaAutoChain.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"OtaAutoChain.js","sourceRoot":"","sources":["../../src/services/OtaAutoChain.ts"],"names":[],"mappings":"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","sourcesContent":["import type {OtaCheckCurrentGlassesResult} from \"./OtaUpdateCheckService\"\n\nexport const MAX_OTA_AUTO_CHAIN_PASSES = 8\nexport const OTA_AUTO_CHAIN_RECONNECT_TIMEOUT_MS = 120_000\n\ntype OtaAutoChainSession = {\n approvedDowngrade: boolean\n passCount: number\n reconnectDeadline: number | null\n seenFingerprints: Set<string>\n}\n\nexport type OtaAutoChainAdvanceResult =\n | {advance: true; passCount: number}\n | {advance: false; reason: \"inactive\" | \"duplicate\" | \"max_passes\" | \"downgrade_not_approved\"}\n\nlet session: OtaAutoChainSession | null = null\n\n/**\n * Identify the exact update offer that produced one OTA pass. Including the\n * observed versions and manifest body lets a changed manifest advance while a\n * stale post-install version_info response is rejected as a duplicate.\n */\nexport function otaAutoChainFingerprint(result: OtaCheckCurrentGlassesResult): string {\n return JSON.stringify({\n manifestUrl: result.manifestUrl ?? \"\",\n manifestBody: result.manifestBody ?? \"\",\n buildNumber: result.buildNumber ?? \"\",\n mtkFirmwareVersion: result.mtkFirmwareVersion ?? \"\",\n besFirmwareVersion: result.besFirmwareVersion ?? \"\",\n updates: result.updates,\n targetBuildNumber: result.updateInfo?.versionCode ?? result.latestVersionInfo?.versionCode ?? 0,\n targetBesVersion: result.besVersion ?? \"\",\n mtkPatch: result.mtkPatch\n ? {\n startFirmware: result.mtkPatch.start_firmware,\n endFirmware: result.mtkPatch.end_firmware,\n url: result.mtkPatch.url,\n }\n : null,\n })\n}\n\n/** Start a chain after the user explicitly approves its first update pass. */\nexport function beginOtaAutoChain(initialFingerprint: string, approvedDowngrade: boolean): void {\n session = {\n approvedDowngrade,\n passCount: 1,\n reconnectDeadline: null,\n seenFingerprints: new Set([initialFingerprint]),\n }\n}\n\nexport function isOtaAutoChainActive(): boolean {\n return session !== null\n}\n\n/** End the current chain. Safe to call when no chain is active. */\nexport function stopOtaAutoChain(): void {\n session = null\n}\n\n/**\n * Start (or continue) the bounded wait for glasses that are rebooting between\n * passes. Re-renders must not extend the original deadline indefinitely.\n */\nexport function otaAutoChainReconnectWaitRemaining(now = performance.now()): number | null {\n if (!session) return null\n\n session.reconnectDeadline ??= now + OTA_AUTO_CHAIN_RECONNECT_TIMEOUT_MS\n return Math.max(0, session.reconnectDeadline - now)\n}\n\n/** A successful reconnect allows a future pass to establish a fresh wait. */\nexport function clearOtaAutoChainReconnectWait(): void {\n if (session) session.reconnectDeadline = null\n}\n\n/**\n * Admit the next pass of an active chain. Repeated offers, unexpectedly\n * destructive downgrades, and runaway chains fail closed and end automation.\n */\nexport function tryAdvanceOtaAutoChain(fingerprint: string, isDowngrade: boolean): OtaAutoChainAdvanceResult {\n if (!session) {\n return {advance: false, reason: \"inactive\"}\n }\n\n if (isDowngrade && !session.approvedDowngrade) {\n stopOtaAutoChain()\n return {advance: false, reason: \"downgrade_not_approved\"}\n }\n\n if (session.seenFingerprints.has(fingerprint)) {\n stopOtaAutoChain()\n return {advance: false, reason: \"duplicate\"}\n }\n\n if (session.passCount >= MAX_OTA_AUTO_CHAIN_PASSES) {\n stopOtaAutoChain()\n return {advance: false, reason: \"max_passes\"}\n }\n\n session.seenFingerprints.add(fingerprint)\n session.passCount += 1\n return {advance: true, passCount: session.passCount}\n}\n"]}
1
+ {"version":3,"file":"OtaAutoChain.js","sourceRoot":"","sources":["../../src/services/OtaAutoChain.ts"],"names":[],"mappings":"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","sourcesContent":["import type {OtaCheckCurrentGlassesResult} from \"./OtaUpdateCheckService\"\n\nexport const MAX_OTA_AUTO_CHAIN_PASSES = 8\nexport const OTA_AUTO_CHAIN_RECONNECT_TIMEOUT_MS = 120_000\n\ntype OtaAutoChainSession = {\n approvedDowngrade: boolean\n passCount: number\n releaseRange: OtaAutoChainReleaseRange\n reconnectDeadline: number | null\n seenFingerprints: Set<string>\n}\n\nexport type OtaAutoChainReleaseRange = {\n fromVersion: string | null\n toVersion: string | null\n}\n\nexport type OtaAutoChainAdvanceResult =\n | {advance: true; passCount: number}\n | {advance: false; reason: \"inactive\" | \"duplicate\" | \"max_passes\" | \"downgrade_not_approved\"}\n\nlet session: OtaAutoChainSession | null = null\n\n/**\n * Identify the exact update offer that produced one OTA pass. Including the\n * observed versions and manifest body lets a changed manifest advance while a\n * stale post-install version_info response is rejected as a duplicate.\n */\nexport function otaAutoChainFingerprint(result: OtaCheckCurrentGlassesResult): string {\n return JSON.stringify({\n manifestUrl: result.manifestUrl ?? \"\",\n manifestBody: result.manifestBody ?? \"\",\n buildNumber: result.buildNumber ?? \"\",\n mtkFirmwareVersion: result.mtkFirmwareVersion ?? \"\",\n besFirmwareVersion: result.besFirmwareVersion ?? \"\",\n updates: result.updates,\n targetBuildNumber: result.updateInfo?.versionCode ?? result.latestVersionInfo?.versionCode ?? 0,\n targetBesVersion: result.besVersion ?? \"\",\n mtkPatch: result.mtkPatch\n ? {\n startFirmware: result.mtkPatch.start_firmware,\n endFirmware: result.mtkPatch.end_firmware,\n url: result.mtkPatch.url,\n }\n : null,\n })\n}\n\n/** Start a chain after the user explicitly approves its first update pass. */\nexport function beginOtaAutoChain(\n initialFingerprint: string,\n approvedDowngrade: boolean,\n releaseRange: OtaAutoChainReleaseRange,\n): void {\n session = {\n approvedDowngrade,\n passCount: 1,\n releaseRange: {...releaseRange},\n reconnectDeadline: null,\n seenFingerprints: new Set([initialFingerprint]),\n }\n}\n\nexport function isOtaAutoChainActive(): boolean {\n return session !== null\n}\n\nexport function otaAutoChainReleaseRange(): OtaAutoChainReleaseRange | null {\n return session ? {...session.releaseRange} : null\n}\n\n/** End the current chain. Safe to call when no chain is active. */\nexport function stopOtaAutoChain(): void {\n session = null\n}\n\n/**\n * Start (or continue) the bounded wait for glasses that are rebooting between\n * passes. Re-renders must not extend the original deadline indefinitely.\n */\nexport function otaAutoChainReconnectWaitRemaining(now = performance.now()): number | null {\n if (!session) return null\n\n session.reconnectDeadline ??= now + OTA_AUTO_CHAIN_RECONNECT_TIMEOUT_MS\n return Math.max(0, session.reconnectDeadline - now)\n}\n\n/** A successful reconnect allows a future pass to establish a fresh wait. */\nexport function clearOtaAutoChainReconnectWait(): void {\n if (session) session.reconnectDeadline = null\n}\n\n/**\n * Admit the next pass of an active chain. Repeated offers, unexpectedly\n * destructive downgrades, and runaway chains fail closed and end automation.\n */\nexport function tryAdvanceOtaAutoChain(\n fingerprint: string,\n isDowngrade: boolean,\n targetVersion: string | null,\n): OtaAutoChainAdvanceResult {\n if (!session) {\n return {advance: false, reason: \"inactive\"}\n }\n\n if (isDowngrade && !session.approvedDowngrade) {\n stopOtaAutoChain()\n return {advance: false, reason: \"downgrade_not_approved\"}\n }\n\n if (session.seenFingerprints.has(fingerprint)) {\n stopOtaAutoChain()\n return {advance: false, reason: \"duplicate\"}\n }\n\n if (session.passCount >= MAX_OTA_AUTO_CHAIN_PASSES) {\n stopOtaAutoChain()\n return {advance: false, reason: \"max_passes\"}\n }\n\n session.seenFingerprints.add(fingerprint)\n session.passCount += 1\n if (targetVersion) session.releaseRange.toVersion = targetVersion\n return {advance: true, passCount: session.passCount}\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mentra/engine",
3
- "version": "3.1.0-dev.28",
3
+ "version": "3.1.0-dev.33",
4
4
  "description": "Mentra Engine — miniapp registry, WebView bridge, and miniapp store",
5
5
  "main": "build/index.js",
6
6
  "react-native": "src/index.ts",
@@ -97,11 +97,11 @@
97
97
  "registry": "https://registry.npmjs.org/"
98
98
  },
99
99
  "dependencies": {
100
- "@mentra/bluetooth-sdk": "3.1.0-dev.28",
101
- "@mentra/cloud-client": "3.1.0-dev.28",
102
- "@mentra/cloud-protocol": "3.1.0-dev.28",
103
- "@mentra/crust": "3.1.0-dev.28",
104
- "@mentra/miniapp": "3.1.0-dev.28",
100
+ "@mentra/bluetooth-sdk": "3.1.0-dev.33",
101
+ "@mentra/cloud-client": "3.1.0-dev.33",
102
+ "@mentra/cloud-protocol": "3.1.0-dev.33",
103
+ "@mentra/crust": "3.1.0-dev.33",
104
+ "@mentra/miniapp": "3.1.0-dev.33",
105
105
  "buffer": "^6.0.3",
106
106
  "events": "^3.3.0",
107
107
  "semver": "^7.7.4",
@@ -9,7 +9,14 @@
9
9
  * progress screen is a pure renderer over its snapshot + attach/detach/retry/finish.
10
10
  */
11
11
  import BluetoothSdk from "@mentra/bluetooth-sdk"
12
- import type {OtaProgress, OtaProgressStatus, OtaStartAckEvent, OtaStatus, OtaUpdateInfo} from "@mentra/bluetooth-sdk"
12
+ import type {
13
+ OtaProgress,
14
+ OtaProgressStatus,
15
+ OtaStartAckEvent,
16
+ OtaStatus,
17
+ OtaUpdateInfo,
18
+ ReleaseChangelog,
19
+ } from "@mentra/bluetooth-sdk"
13
20
  import {isGlassesConnected, useGlassesStore} from "../stores/glasses"
14
21
  import {resolveOtaManifestUrl} from "../services/otaManifestUrl"
15
22
  import {otaInstallCoordinator, type OtaInstallSnapshot} from "../services/OtaInstallCoordinator"
@@ -26,6 +33,7 @@ function projectSnapshot() {
26
33
  return {
27
34
  connected: isGlassesConnected(s.connection),
28
35
  buildNumber: s.buildNumber || null,
36
+ appVersion: s.appVersion || null,
29
37
  mtkFirmwareVersion: s.mtkFirmwareVersion || null,
30
38
  besFirmwareVersion: s.besFirmwareVersion || null,
31
39
  hotspotOtaVersion: s.hotspotOtaVersion ?? 0,
@@ -46,6 +54,7 @@ export type {
46
54
  OtaProgressStatus,
47
55
  OtaStatus,
48
56
  OtaUpdateInfo,
57
+ ReleaseChangelog,
49
58
  OtaInstallSnapshot,
50
59
  OtaCheckCurrentGlassesOptions,
51
60
  OtaCheckCurrentGlassesResult,
@@ -84,6 +93,9 @@ export const ota = {
84
93
  ping: () => BluetoothSdk.ping(),
85
94
  /** Resolve and compare the current glasses against the OTA manifest, then update the OTA snapshot. */
86
95
  checkForUpdates: (options?: OtaCheckCurrentGlassesOptions) => checkCurrentGlassesForUpdate(options),
96
+ /** Return bundled release changelogs crossed between two coordinated product versions, newest first. */
97
+ getReleaseChangelogs: (fromVersion?: string | null, toVersion?: string | null): ReleaseChangelog[] =>
98
+ BluetoothSdk.getReleaseChangelogs(fromVersion, toVersion),
87
99
  /** Clear the available-update prompt state. */
88
100
  clearUpdateAvailable: () => useGlassesStore.getState().setOtaUpdateAvailable(null),
89
101
  /** Clear active progress/status before entering a fresh install flow. */
@@ -12,9 +12,9 @@ export interface EngineReleaseMetadata {
12
12
  export const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({
13
13
  "schemaVersion": 1,
14
14
  "familyBaseVersion": "3.1.0",
15
- "releaseIdentity": "3.1.0-dev.28",
16
- "releaseSetId": "mentra-3.1.0-dev.28",
17
- "sourceCommit": "dd6c542fdd71a3484aae4ee620236c33ddc27788",
18
- "otaManifestUrl": "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-v3.1.0-dev.28/mentra-live-ota-3.1.0-dev.28.json",
19
- "otaManifestSha256": "ea869252f5ed1ce809b51e8477a05c48859097a3542d22285165546e30f23e45"
15
+ "releaseIdentity": "3.1.0-dev.33",
16
+ "releaseSetId": "mentra-3.1.0-dev.33",
17
+ "sourceCommit": "b1b492d91b29548ebedb4d4b7e98faf4a02b2d36",
18
+ "otaManifestUrl": "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-builds-v3.1.0/mentra-live-ota-3.1.0-dev.33.json",
19
+ "otaManifestSha256": "d1dbac07a41c51e52f56fef3f62aa6f62b46a23bfc1870cbf9a87b9b3eaa3e27"
20
20
  })
package/src/index.ts CHANGED
@@ -98,6 +98,7 @@ export type {
98
98
  OtaProgressStatus,
99
99
  OtaStatus,
100
100
  OtaUpdateInfo,
101
+ ReleaseChangelog,
101
102
  OtaSnapshot,
102
103
  OtaInstallSnapshot,
103
104
  } from "./facades/ota"