@mentra/engine 3.1.0-dev.31 → 3.1.0-dev.37

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 (48) hide show
  1. package/build/engine.d.ts +3 -0
  2. package/build/engine.d.ts.map +1 -1
  3. package/build/facades/ota.d.ts +5 -2
  4. package/build/facades/ota.d.ts.map +1 -1
  5. package/build/facades/ota.js +3 -0
  6. package/build/facades/ota.js.map +1 -1
  7. package/build/facades/pairing.d.ts +4 -0
  8. package/build/facades/pairing.d.ts.map +1 -1
  9. package/build/facades/pairing.js +81 -7
  10. package/build/facades/pairing.js.map +1 -1
  11. package/build/generated/releaseMetadata.js +5 -5
  12. package/build/generated/releaseMetadata.js.map +1 -1
  13. package/build/index.d.ts +1 -1
  14. package/build/index.d.ts.map +1 -1
  15. package/build/index.js.map +1 -1
  16. package/build/react/MentraLiveOtaFlow.d.ts.map +1 -1
  17. package/build/react/MentraLiveOtaFlow.js +39 -1
  18. package/build/react/MentraLiveOtaFlow.js.map +1 -1
  19. package/build/react/index.d.ts +1 -1
  20. package/build/react/index.d.ts.map +1 -1
  21. package/build/react/index.js.map +1 -1
  22. package/build/react/useMentraLiveOta.d.ts +11 -0
  23. package/build/react/useMentraLiveOta.d.ts.map +1 -1
  24. package/build/react/useMentraLiveOta.js +73 -8
  25. package/build/react/useMentraLiveOta.js.map +1 -1
  26. package/build/services/OtaAutoChain.d.ts +9 -2
  27. package/build/services/OtaAutoChain.d.ts.map +1 -1
  28. package/build/services/OtaAutoChain.js +10 -2
  29. package/build/services/OtaAutoChain.js.map +1 -1
  30. package/build/services/OtaUpdateCheckService.d.ts +3 -0
  31. package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
  32. package/build/services/OtaUpdateCheckService.js +12 -0
  33. package/build/services/OtaUpdateCheckService.js.map +1 -1
  34. package/build/services/otaReleaseVersion.d.ts +10 -0
  35. package/build/services/otaReleaseVersion.d.ts.map +1 -0
  36. package/build/services/otaReleaseVersion.js +14 -0
  37. package/build/services/otaReleaseVersion.js.map +1 -0
  38. package/package.json +6 -6
  39. package/src/facades/ota.ts +13 -1
  40. package/src/facades/pairing.ts +88 -12
  41. package/src/generated/releaseMetadata.ts +5 -5
  42. package/src/index.ts +1 -0
  43. package/src/react/MentraLiveOtaFlow.tsx +72 -9
  44. package/src/react/index.ts +1 -0
  45. package/src/react/useMentraLiveOta.ts +106 -18
  46. package/src/services/OtaAutoChain.ts +26 -2
  47. package/src/services/OtaUpdateCheckService.ts +15 -0
  48. package/src/services/otaReleaseVersion.ts +22 -0
@@ -6,10 +6,18 @@ export const OTA_AUTO_CHAIN_RECONNECT_TIMEOUT_MS = 120_000
6
6
  type OtaAutoChainSession = {
7
7
  approvedDowngrade: boolean
8
8
  passCount: number
9
+ releaseRange: OtaAutoChainReleaseRange
9
10
  reconnectDeadline: number | null
10
11
  seenFingerprints: Set<string>
11
12
  }
12
13
 
14
+ export type OtaAutoChainReleaseRange = {
15
+ fromVersion: string | null
16
+ toVersion: string | null
17
+ /** Exact coordinated release identity for the OTA pin, absent for legacy manifests. */
18
+ releaseVersion?: string | null
19
+ }
20
+
13
21
  export type OtaAutoChainAdvanceResult =
14
22
  | {advance: true; passCount: number}
15
23
  | {advance: false; reason: "inactive" | "duplicate" | "max_passes" | "downgrade_not_approved"}
@@ -42,10 +50,15 @@ export function otaAutoChainFingerprint(result: OtaCheckCurrentGlassesResult): s
42
50
  }
43
51
 
44
52
  /** Start a chain after the user explicitly approves its first update pass. */
45
- export function beginOtaAutoChain(initialFingerprint: string, approvedDowngrade: boolean): void {
53
+ export function beginOtaAutoChain(
54
+ initialFingerprint: string,
55
+ approvedDowngrade: boolean,
56
+ releaseRange: OtaAutoChainReleaseRange,
57
+ ): void {
46
58
  session = {
47
59
  approvedDowngrade,
48
60
  passCount: 1,
61
+ releaseRange: {...releaseRange},
49
62
  reconnectDeadline: null,
50
63
  seenFingerprints: new Set([initialFingerprint]),
51
64
  }
@@ -55,6 +68,10 @@ export function isOtaAutoChainActive(): boolean {
55
68
  return session !== null
56
69
  }
57
70
 
71
+ export function otaAutoChainReleaseRange(): OtaAutoChainReleaseRange | null {
72
+ return session ? {...session.releaseRange} : null
73
+ }
74
+
58
75
  /** End the current chain. Safe to call when no chain is active. */
59
76
  export function stopOtaAutoChain(): void {
60
77
  session = null
@@ -80,7 +97,12 @@ export function clearOtaAutoChainReconnectWait(): void {
80
97
  * Admit the next pass of an active chain. Repeated offers, unexpectedly
81
98
  * destructive downgrades, and runaway chains fail closed and end automation.
82
99
  */
83
- export function tryAdvanceOtaAutoChain(fingerprint: string, isDowngrade: boolean): OtaAutoChainAdvanceResult {
100
+ export function tryAdvanceOtaAutoChain(
101
+ fingerprint: string,
102
+ isDowngrade: boolean,
103
+ targetVersion: string | null,
104
+ releaseVersion: string | null = null,
105
+ ): OtaAutoChainAdvanceResult {
84
106
  if (!session) {
85
107
  return {advance: false, reason: "inactive"}
86
108
  }
@@ -102,5 +124,7 @@ export function tryAdvanceOtaAutoChain(fingerprint: string, isDowngrade: boolean
102
124
 
103
125
  session.seenFingerprints.add(fingerprint)
104
126
  session.passCount += 1
127
+ if (targetVersion) session.releaseRange.toVersion = targetVersion
128
+ if (releaseVersion) session.releaseRange.releaseVersion = releaseVersion
105
129
  return {advance: true, passCount: session.passCount}
106
130
  }
@@ -1,7 +1,9 @@
1
1
  import BluetoothSdk, {type OtaUpdateInfo} from "@mentra/bluetooth-sdk"
2
+ import {ENGINE_RELEASE_METADATA} from "../generated/releaseMetadata"
2
3
  import {getGlassesSystemTimeMs, isGlassesConnected, useGlassesStore, waitForGlassesState} from "../stores/glasses"
3
4
  import {maybeFixGlassesClockFromVersionInfo} from "./glassesClockSync"
4
5
  import {hasConfiguredModernOtaManifestPin, resolveOtaManifestUrl} from "./otaManifestUrl"
6
+ import {resolveOtaReleaseVersion} from "./otaReleaseVersion"
5
7
 
6
8
  /**
7
9
  * Phone-side mirror of ASG's `DOWNGRADE_FLOOR_VERSION_CODE`. Set to the versionCode of the first
@@ -37,6 +39,7 @@ export interface BesFirmware {
37
39
  }
38
40
 
39
41
  export interface VersionJson {
42
+ releaseVersion?: string
40
43
  apps?: {
41
44
  [packageName: string]: VersionInfo
42
45
  }
@@ -65,6 +68,8 @@ export interface OtaCheckResult {
65
68
  * instead of racing it with a second fetch of the same URL.
66
69
  */
67
70
  manifestBody: string | null
71
+ /** Coordinated release identity for the selected OTA pin. */
72
+ releaseVersion: string | null
68
73
  /**
69
74
  * Why the check failed, when it did. "network" is retryable (connection/server
70
75
  * trouble); "pin_unavailable" is permanent for this app build (manifest 404/gone,
@@ -105,6 +110,7 @@ function emptyCheckResult(skippedReason?: OtaCheckSkippedReason): OtaCheckCurren
105
110
  besVersion: null,
106
111
  isApkDowngrade: false,
107
112
  manifestBody: null,
113
+ releaseVersion: null,
108
114
  updateInfo: null,
109
115
  isRequired: true,
110
116
  skippedReason,
@@ -297,6 +303,7 @@ export async function checkForOtaUpdate(
297
303
  besVersion: null,
298
304
  isApkDowngrade: false,
299
305
  manifestBody: null,
306
+ releaseVersion: null,
300
307
  checkFailureReason: fetched.failureReason ?? "network",
301
308
  }
302
309
  }
@@ -328,6 +335,7 @@ export async function checkForOtaUpdate(
328
335
  besVersion: null,
329
336
  isApkDowngrade: false,
330
337
  manifestBody: null,
338
+ releaseVersion: null,
331
339
  checkFailureReason: "pin_unavailable",
332
340
  }
333
341
  }
@@ -366,6 +374,12 @@ export async function checkForOtaUpdate(
366
374
  besVersion: versionJson?.bes_firmware?.version || null,
367
375
  isApkDowngrade: apkDirection === "downgrade",
368
376
  manifestBody: versionJson ? JSON.stringify(versionJson) : null,
377
+ releaseVersion: resolveOtaReleaseVersion({
378
+ manifestReleaseVersion: versionJson.releaseVersion,
379
+ manifestUrl: otaVersionUrl,
380
+ packagedManifestUrl: ENGINE_RELEASE_METADATA.otaManifestUrl,
381
+ packagedReleaseIdentity: ENGINE_RELEASE_METADATA.releaseIdentity,
382
+ }),
369
383
  }
370
384
  } catch (error) {
371
385
  console.error("Error checking for OTA update:", error)
@@ -378,6 +392,7 @@ export async function checkForOtaUpdate(
378
392
  besVersion: null,
379
393
  isApkDowngrade: false,
380
394
  manifestBody: null,
395
+ releaseVersion: null,
381
396
  checkFailureReason: "network",
382
397
  }
383
398
  }
@@ -0,0 +1,22 @@
1
+ const COORDINATED_RELEASE_VERSION = /^\d+\.\d+\.\d+(?:-(?:dev|beta)\.[1-9]\d*)?$/
2
+
3
+ type OtaReleaseVersionInput = {
4
+ manifestReleaseVersion?: string | null
5
+ manifestUrl: string
6
+ packagedManifestUrl?: string | null
7
+ packagedReleaseIdentity?: string | null
8
+ }
9
+
10
+ function validReleaseVersion(version: string | null | undefined): string | null {
11
+ const trimmed = version?.trim()
12
+ return trimmed && COORDINATED_RELEASE_VERSION.test(trimmed) ? trimmed : null
13
+ }
14
+
15
+ /** Resolve the label for the selected OTA pin, including stable promotion of exact beta OTA bytes. */
16
+ export function resolveOtaReleaseVersion(input: OtaReleaseVersionInput): string | null {
17
+ const packagedRelease = validReleaseVersion(input.packagedReleaseIdentity)
18
+ if (packagedRelease && input.packagedManifestUrl?.trim() === input.manifestUrl.trim()) {
19
+ return packagedRelease
20
+ }
21
+ return validReleaseVersion(input.manifestReleaseVersion)
22
+ }