@mentra/bluetooth-sdk 3.3.0-dev.788 → 3.3.0-dev.791

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.
@@ -3,9 +3,9 @@ package com.mentra.bluetoothsdk
3
3
  /** Generated by release CI. Do not edit in a release checkout. */
4
4
  internal object GeneratedReleaseMetadata {
5
5
  const val FAMILY_BASE_VERSION: String = "3.3.0"
6
- const val RELEASE_IDENTITY: String = "3.3.0-dev.788"
7
- const val RELEASE_SET_ID: String = "mentra-3.3.0-dev.788"
8
- const val SOURCE_COMMIT: String = "557a9faa3f9c43bee85ab7cc3509e4770a000c22"
9
- const val OTA_MANIFEST_URL: String = "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.788.json"
10
- const val OTA_MANIFEST_SHA256: String = "a7fe57f5a3cb130c5615133b733fd46b880e6367ce07a283750cc7bf83d2415a"
6
+ const val RELEASE_IDENTITY: String = "3.3.0-dev.791"
7
+ const val RELEASE_SET_ID: String = "mentra-3.3.0-dev.791"
8
+ const val SOURCE_COMMIT: String = "97e2f51340fbd1ff1b1d0e5711910fcc306a4459"
9
+ const val OTA_MANIFEST_URL: String = "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.791.json"
10
+ const val OTA_MANIFEST_SHA256: String = "716e6e1fa00d8a3ec71e09d2e69e7e6920555ef4f0cb9ee8d21befb734819b50"
11
11
  }
@@ -1,10 +1,10 @@
1
1
  export const BLUETOOTH_SDK_RELEASE_METADATA = Object.freeze({
2
2
  "schemaVersion": 1,
3
3
  "familyBaseVersion": "3.3.0",
4
- "releaseIdentity": "3.3.0-dev.788",
5
- "releaseSetId": "mentra-3.3.0-dev.788",
6
- "sourceCommit": "557a9faa3f9c43bee85ab7cc3509e4770a000c22",
7
- "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.788.json",
8
- "otaManifestSha256": "a7fe57f5a3cb130c5615133b733fd46b880e6367ce07a283750cc7bf83d2415a"
4
+ "releaseIdentity": "3.3.0-dev.791",
5
+ "releaseSetId": "mentra-3.3.0-dev.791",
6
+ "sourceCommit": "97e2f51340fbd1ff1b1d0e5711910fcc306a4459",
7
+ "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.791.json",
8
+ "otaManifestSha256": "716e6e1fa00d8a3ec71e09d2e69e7e6920555ef4f0cb9ee8d21befb734819b50"
9
9
  });
10
10
  //# sourceMappingURL=releaseMetadata.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"releaseMetadata.js","sourceRoot":"","sources":["../../src/generated/releaseMetadata.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,8BAA8B,GAA0C,MAAM,CAAC,MAAM,CAAC;IACjG,eAAe,EAAE,CAAC;IAClB,mBAAmB,EAAE,OAAO;IAC5B,iBAAiB,EAAE,eAAe;IAClC,cAAc,EAAE,sBAAsB;IACtC,cAAc,EAAE,0CAA0C;IAC1D,gBAAgB,EAAE,iIAAiI;IACnJ,mBAAmB,EAAE,kEAAkE;CACxF,CAAC,CAAA","sourcesContent":["/** Generated by release CI. Do not edit in a release checkout. */\nexport interface BluetoothSdkReleaseMetadata {\n schemaVersion: 1\n familyBaseVersion: string | null\n releaseIdentity: string | null\n releaseSetId: string | null\n sourceCommit: string | null\n otaManifestUrl: string | null\n otaManifestSha256: string | null\n}\n\nexport const BLUETOOTH_SDK_RELEASE_METADATA: Readonly<BluetoothSdkReleaseMetadata> = Object.freeze({\n \"schemaVersion\": 1,\n \"familyBaseVersion\": \"3.3.0\",\n \"releaseIdentity\": \"3.3.0-dev.788\",\n \"releaseSetId\": \"mentra-3.3.0-dev.788\",\n \"sourceCommit\": \"557a9faa3f9c43bee85ab7cc3509e4770a000c22\",\n \"otaManifestUrl\": \"https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.788.json\",\n \"otaManifestSha256\": \"a7fe57f5a3cb130c5615133b733fd46b880e6367ce07a283750cc7bf83d2415a\"\n})\n"]}
1
+ {"version":3,"file":"releaseMetadata.js","sourceRoot":"","sources":["../../src/generated/releaseMetadata.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,8BAA8B,GAA0C,MAAM,CAAC,MAAM,CAAC;IACjG,eAAe,EAAE,CAAC;IAClB,mBAAmB,EAAE,OAAO;IAC5B,iBAAiB,EAAE,eAAe;IAClC,cAAc,EAAE,sBAAsB;IACtC,cAAc,EAAE,0CAA0C;IAC1D,gBAAgB,EAAE,iIAAiI;IACnJ,mBAAmB,EAAE,kEAAkE;CACxF,CAAC,CAAA","sourcesContent":["/** Generated by release CI. Do not edit in a release checkout. */\nexport interface BluetoothSdkReleaseMetadata {\n schemaVersion: 1\n familyBaseVersion: string | null\n releaseIdentity: string | null\n releaseSetId: string | null\n sourceCommit: string | null\n otaManifestUrl: string | null\n otaManifestSha256: string | null\n}\n\nexport const BLUETOOTH_SDK_RELEASE_METADATA: Readonly<BluetoothSdkReleaseMetadata> = Object.freeze({\n \"schemaVersion\": 1,\n \"familyBaseVersion\": \"3.3.0\",\n \"releaseIdentity\": \"3.3.0-dev.791\",\n \"releaseSetId\": \"mentra-3.3.0-dev.791\",\n \"sourceCommit\": \"97e2f51340fbd1ff1b1d0e5711910fcc306a4459\",\n \"otaManifestUrl\": \"https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.791.json\",\n \"otaManifestSha256\": \"716e6e1fa00d8a3ec71e09d2e69e7e6920555ef4f0cb9ee8d21befb734819b50\"\n})\n"]}
@@ -16,7 +16,7 @@ enum BluetoothSdkDefaults {
16
16
  /// silently disable it on every pair the app touches.
17
17
  static let autoPowerOffEnabled = false
18
18
  private static let infoSdkVersionKey = "MentraBluetoothSdkVersion"
19
- private static let swiftPackageSdkVersion = "3.3.0-dev.788"
19
+ private static let swiftPackageSdkVersion = "3.3.0-dev.791"
20
20
  private static let swiftPackageSdkVersionPlaceholder = "__MENTRA" + "_BLUETOOTH_SDK_VERSION__"
21
21
 
22
22
  private static func normalizedSdkVersion(_ value: String?) -> String? {
@@ -3,9 +3,9 @@ import Foundation
3
3
  /// Generated by release CI. Do not edit in a release checkout.
4
4
  enum GeneratedReleaseMetadata {
5
5
  static let familyBaseVersion = "3.3.0"
6
- static let releaseIdentity = "3.3.0-dev.788"
7
- static let releaseSetId = "mentra-3.3.0-dev.788"
8
- static let sourceCommit = "557a9faa3f9c43bee85ab7cc3509e4770a000c22"
9
- static let otaManifestUrl = "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.788.json"
10
- static let otaManifestSha256 = "a7fe57f5a3cb130c5615133b733fd46b880e6367ce07a283750cc7bf83d2415a"
6
+ static let releaseIdentity = "3.3.0-dev.791"
7
+ static let releaseSetId = "mentra-3.3.0-dev.791"
8
+ static let sourceCommit = "97e2f51340fbd1ff1b1d0e5711910fcc306a4459"
9
+ static let otaManifestUrl = "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.791.json"
10
+ static let otaManifestSha256 = "716e6e1fa00d8a3ec71e09d2e69e7e6920555ef4f0cb9ee8d21befb734819b50"
11
11
  }
@@ -923,7 +923,7 @@ extension MentraLive: CBCentralManagerDelegate {
923
923
  self.isConnecting = false
924
924
 
925
925
  self.connectedPeripheral = nil
926
- self.fullyBooted = false
926
+ self.clearPhysicalReadiness()
927
927
  self.connected = false
928
928
  self.glassesSessionId = nil // Fresh BLE session starts with no sid known
929
929
  self.streamControlVersion = 0
@@ -1617,6 +1617,16 @@ class MentraLive: NSObject, SGCManager {
1617
1617
  set { DeviceStore.shared.apply("glasses", "connected", newValue) }
1618
1618
  }
1619
1619
 
1620
+ private func clearPhysicalReadiness() {
1621
+ let readinessWasPending = connected && !fullyBooted
1622
+ fullyBooted = false
1623
+ if readinessWasPending {
1624
+ // Logical ASG readiness already emitted false without disconnecting.
1625
+ // The real disconnect must still perform the cleanup apply deduplicates.
1626
+ DeviceManager.shared.handleDeviceDisconnected()
1627
+ }
1628
+ }
1629
+
1620
1630
  // Queue Management
1621
1631
  private let commandQueue = CommandQueue()
1622
1632
  private let bluetoothQueue = DispatchQueue(label: "MentraLiveBluetooth", qos: .userInitiated)
@@ -1744,8 +1754,8 @@ class MentraLive: NSObject, SGCManager {
1744
1754
  // Publish disconnect immediately for Phone A UI. didDisconnectPeripheral may lag
1745
1755
  // or race with cancelPeripheralConnection; do not wait on it for stand-down.
1746
1756
  isConnecting = false
1757
+ clearPhysicalReadiness()
1747
1758
  connected = false
1748
- fullyBooted = false
1749
1759
  glassesSessionId = nil
1750
1760
  streamControlVersion = 0
1751
1761
  readinessCompletedThisBleSession = false
@@ -2523,8 +2533,8 @@ class MentraLive: NSObject, SGCManager {
2523
2533
  Bridge.log("LIVE: Maximum reconnection attempts reached (\(MAX_RECONNECT_ATTEMPTS))")
2524
2534
  reconnectAttempts = 0
2525
2535
  updateConnectionState(ConnTypes.DISCONNECTED)
2536
+ clearPhysicalReadiness()
2526
2537
  connected = false
2527
- fullyBooted = false
2528
2538
  glassesSessionId = nil
2529
2539
  streamControlVersion = 0
2530
2540
  readinessCompletedThisBleSession = false
@@ -3138,6 +3148,11 @@ class MentraLive: NSObject, SGCManager {
3138
3148
  if type.hasPrefix("version_info") {
3139
3149
  Bridge.log("LIVE: Received \(type)")
3140
3150
 
3151
+ // A new process can report its build before glasses_ready resets the
3152
+ // wire epoch. Publish its pending readiness before those version fields
3153
+ // can complete OTA and trigger the next request.
3154
+ handleGlassesSessionId(json)
3155
+
3141
3156
  // Extract all fields from JSON (except "type")
3142
3157
  var fields: [String: Any] = [:]
3143
3158
  fields["version_info_type"] = type
@@ -3210,7 +3225,6 @@ class MentraLive: NSObject, SGCManager {
3210
3225
  // running them per chunk is safe.
3211
3226
  parsePeerWireCaps(json)
3212
3227
  maybeSendWireHandshake()
3213
- handleGlassesSessionId(json)
3214
3228
 
3215
3229
  Bridge.sendVersionInfo(fields, responseChunk: type)
3216
3230
  } else {
@@ -5737,7 +5751,7 @@ class MentraLive: NSObject, SGCManager {
5737
5751
  stopReadinessCheckLoop()
5738
5752
 
5739
5753
  readinessCheckCounter = 0
5740
- fullyBooted = false
5754
+ clearPhysicalReadiness()
5741
5755
  connected = false
5742
5756
  glassesSessionId = nil
5743
5757
  streamControlVersion = 0
@@ -6018,8 +6032,8 @@ class MentraLive: NSObject, SGCManager {
6018
6032
  centralManager?.cancelPeripheralConnection(peripheral)
6019
6033
  }
6020
6034
 
6035
+ clearPhysicalReadiness()
6021
6036
  DeviceStore.shared.apply("glasses", "connected", false)
6022
- DeviceStore.shared.apply("glasses", "fullyBooted", false)
6023
6037
  DeviceStore.shared.apply("glasses", "wifiConnected", false)
6024
6038
  DeviceStore.shared.apply("glasses", "wifiSsid", "")
6025
6039
  DeviceStore.shared.apply("glasses", "wifiLocalIp", "")
@@ -6156,8 +6170,8 @@ extension MentraLive {
6156
6170
  /// pre-sid build) or differing from the recorded one = restart; same sid = no action.
6157
6171
  /// A restart is a LOGICAL session reset: send phone_ready immediately (bypassing the
6158
6172
  /// sr_hrt heartbeat's stale-readiness suppression); the returning glasses_ready runs
6159
- /// the full existing remote-wire-reset flow. fullyBooted is deliberately untouched -
6160
- /// the physical link never dropped, so the connection UI must not flap.
6173
+ /// the full existing remote-wire-reset flow. Keep the physical connection intact,
6174
+ /// but mark readiness pending until that new wire epoch has been established.
6161
6175
  private func handleGlassesSessionId(_ json: [String: Any]) {
6162
6176
  guard let sid = json["sid"] as? String, !sid.isEmpty else { return }
6163
6177
  let previous = glassesSessionId
@@ -6172,6 +6186,9 @@ extension MentraLive {
6172
6186
  "LIVE: 🔁 Glasses session changed (\(previous ?? "<pre-sid build>") -> \(sid)) - " +
6173
6187
  "asg restarted under a live link, re-running readiness"
6174
6188
  )
6189
+ // Emit the existing connected-but-not-ready status without invoking the
6190
+ // physical-disconnect side effects of DeviceStore.apply(fullyBooted: false).
6191
+ DeviceStore.shared.set("glasses", "fullyBooted", false)
6175
6192
  sendPhoneReady(reason: "glasses session changed")
6176
6193
  Bridge.sendTypedMessage(
6177
6194
  "glasses_session_changed",
@@ -0,0 +1,163 @@
1
+ @testable import MentraBluetoothSDK
2
+ import XCTest
3
+
4
+ @MainActor
5
+ private final class SessionReadinessTransport: MentraLive {
6
+ var commands: [[String: Any]] = []
7
+
8
+ override func sendJson(_ jsonOriginal: [String: Any], wakeUp: Bool, requireAck: Bool) {
9
+ commands.append(jsonOriginal)
10
+ }
11
+ }
12
+
13
+ @MainActor
14
+ final class MentraLiveSessionReadinessTests: XCTestCase {
15
+ func testChangedSessionPublishesPendingReadinessBeforeItsBuildAndRecoversAtGlassesReady() throws {
16
+ let store = DeviceStore.shared.store
17
+ let saved = ["bluetooth", "glasses"].map { ($0, store.getCategory($0)) }
18
+ let previous = DeviceManager.shared.sgc
19
+ let transport = SessionReadinessTransport()
20
+ let sdk = MentraBluetoothSDK()
21
+ DeviceManager.shared.sgc = transport
22
+ var observations: [(key: String, ready: Bool, connected: Bool)] = []
23
+ let listener = store.addListener { category, changed in
24
+ guard category == "glasses" else { return }
25
+ for key in changed.keys where key == "fullyBooted" || key == "buildNumber" {
26
+ observations.append((key, sdk.glassesStatus.fullyBooted, sdk.glassesStatus.connected))
27
+ }
28
+ }
29
+ var sessionEvents: [Bool] = []
30
+ let sink = Bridge.addEventSink { event, body in
31
+ if event == "glasses_session_changed" {
32
+ sessionEvents.append(sdk.glassesStatus.fullyBooted)
33
+ }
34
+ }
35
+ defer {
36
+ store.removeListener(listener)
37
+ Bridge.removeEventSink(sink)
38
+ sdk.invalidate()
39
+ transport.cleanup()
40
+ DeviceManager.shared.sgc = previous
41
+ for (category, values) in saved {
42
+ for key in store.getCategory(category).keys where values[key] == nil {
43
+ store.remove(category, key)
44
+ }
45
+ for (key, value) in values { store.set(category, key, value) }
46
+ }
47
+ }
48
+
49
+ func receive(_ value: [String: Any]) throws {
50
+ try transport.processReceivedData(JSONSerialization.data(withJSONObject: value))
51
+ }
52
+ try receive(["type": "glasses_ready", "sid": "original"])
53
+ observations.removeAll()
54
+ transport.commands.removeAll()
55
+
56
+ // The physical BLE link remains live across APK replacement. Its first
57
+ // version chunk can prove the target build before remote wire readiness.
58
+ try receive(["type": "version_info_1", "sid": "replacement", "build_number": "302010070"])
59
+ XCTAssertEqual(observations.map(\.key), ["fullyBooted", "buildNumber"])
60
+ XCTAssertTrue(observations.allSatisfy { !$0.ready && $0.connected })
61
+ XCTAssertEqual(sessionEvents, [false])
62
+ XCTAssertEqual(transport.commands.compactMap { $0["type"] as? String }, ["phone_ready"])
63
+
64
+ // Another chunk from the same pending process must not restart readiness.
65
+ try receive(["type": "version_info_3", "sid": "replacement"])
66
+ XCTAssertEqual(sessionEvents, [false])
67
+ XCTAssertFalse(sdk.glassesStatus.fullyBooted)
68
+
69
+ try receive(["type": "glasses_ready", "sid": "replacement"])
70
+ XCTAssertTrue(sdk.glassesStatus.connected)
71
+ XCTAssertTrue(sdk.glassesStatus.fullyBooted)
72
+ XCTAssertEqual(observations.last?.key, "fullyBooted")
73
+ XCTAssertEqual(observations.last?.ready, true)
74
+ XCTAssertEqual(transport.commands.filter { $0["type"] as? String == "request_version" }.count, 1)
75
+
76
+ observations.removeAll()
77
+ try receive(["type": "version_info_1", "sid": "replacement", "build_number": "302010070"])
78
+ XCTAssertTrue(sdk.glassesStatus.fullyBooted)
79
+ XCTAssertFalse(observations.contains { $0.key == "fullyBooted" })
80
+ XCTAssertEqual(sessionEvents, [false])
81
+
82
+ // A physical teardown before the next logical restart becomes ready must
83
+ // still run disconnect cleanup, even though readiness is already false.
84
+ try receive(["type": "version_info_1", "sid": "third", "build_number": "303000267"])
85
+ store.set("glasses", "headUp", true)
86
+ store.set("glasses", "voiceActivityDetectionEnabled", !BluetoothSdkDefaults.voiceActivityDetectionEnabled)
87
+ XCTAssertFalse(sdk.glassesStatus.fullyBooted)
88
+ XCTAssertTrue(sdk.glassesStatus.connected)
89
+ transport.cleanup()
90
+ XCTAssertFalse(sdk.glassesStatus.connected)
91
+ XCTAssertEqual(store.get("glasses", "headUp") as? Bool, false)
92
+ XCTAssertEqual(store.get("glasses", "voiceActivityDetectionEnabled") as? Bool,
93
+ BluetoothSdkDefaults.voiceActivityDetectionEnabled)
94
+ }
95
+
96
+ func testPairingYieldDuringPendingReadinessCleansUpAndReclaimsAfterItsWindow() async throws {
97
+ let store = DeviceStore.shared.store
98
+ let saved = ["bluetooth", "glasses"].map { ($0, store.getCategory($0)) }
99
+ let previous = DeviceManager.shared.sgc
100
+ let transport = SessionReadinessTransport()
101
+ let sdk = MentraBluetoothSDK()
102
+ DeviceManager.shared.sgc = transport
103
+ defer {
104
+ sdk.invalidate()
105
+ transport.cleanup()
106
+ DeviceManager.shared.sgc = previous
107
+ for (category, values) in saved {
108
+ for key in store.getCategory(category).keys where values[key] == nil {
109
+ store.remove(category, key)
110
+ }
111
+ for (key, value) in values { store.set(category, key, value) }
112
+ }
113
+ }
114
+
115
+ func receive(_ value: [String: Any]) throws {
116
+ try transport.processReceivedData(JSONSerialization.data(withJSONObject: value))
117
+ }
118
+ try receive(["type": "glasses_ready", "sid": "original"])
119
+ try receive(["type": "version_info_1", "sid": "replacement", "build_number": "302010070"])
120
+ XCTAssertTrue(sdk.glassesStatus.connected)
121
+ XCTAssertFalse(sdk.glassesStatus.fullyBooted)
122
+ store.set("glasses", "headUp", true)
123
+ store.set("glasses", "voiceActivityDetectionEnabled", !BluetoothSdkDefaults.voiceActivityDetectionEnabled)
124
+
125
+ try receive(["type": "entering_pairing_mode", "window_ms": 5000])
126
+ XCTAssertTrue(transport.isPairingYieldActive())
127
+ XCTAssertFalse(sdk.glassesStatus.connected)
128
+ XCTAssertFalse(sdk.glassesStatus.fullyBooted)
129
+ XCTAssertEqual(store.get("glasses", "headUp") as? Bool, false)
130
+ XCTAssertEqual(store.get("glasses", "voiceActivityDetectionEnabled") as? Bool,
131
+ BluetoothSdkDefaults.voiceActivityDetectionEnabled)
132
+
133
+ // Readiness queued on the relinquished GATT must not close the yield.
134
+ try receive(["type": "glasses_ready", "sid": "replacement"])
135
+ XCTAssertTrue(transport.isPairingYieldActive())
136
+ XCTAssertFalse(sdk.glassesStatus.fullyBooted)
137
+
138
+ // Let the existing minimum yield expire, then accept a fresh readiness.
139
+ try await Task.sleep(nanoseconds: 5_100_000_000)
140
+ XCTAssertFalse(transport.isPairingYieldActive())
141
+ try receive(["type": "glasses_ready", "sid": "reclaimed"])
142
+ XCTAssertTrue(sdk.glassesStatus.connected)
143
+ XCTAssertTrue(sdk.glassesStatus.fullyBooted)
144
+ }
145
+
146
+ func testInitialVersionChunkDoesNotStartAnExtraReadinessExchange() throws {
147
+ let store = DeviceStore.shared.store
148
+ let saved = store.getCategory("glasses")
149
+ let transport = SessionReadinessTransport()
150
+ defer {
151
+ transport.cleanup()
152
+ for key in store.getCategory("glasses").keys where saved[key] == nil { store.remove("glasses", key) }
153
+ for (key, value) in saved { store.set("glasses", key, value) }
154
+ }
155
+ store.set("glasses", "fullyBooted", false)
156
+ try transport.processReceivedData(JSONSerialization.data(withJSONObject: [
157
+ "type": "version_info_1", "sid": "initial", "build_number": "303000267",
158
+ ]))
159
+ XCTAssertTrue(transport.commands.isEmpty)
160
+ XCTAssertEqual(store.get("glasses", "buildNumber") as? String, "303000267")
161
+ XCTAssertEqual(store.get("glasses", "fullyBooted") as? Bool, false)
162
+ }
163
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mentra/bluetooth-sdk",
3
- "version": "3.3.0-dev.788",
3
+ "version": "3.3.0-dev.791",
4
4
  "description": "SDK for communicating with smart glasses",
5
5
  "main": "build/index.js",
6
6
  "react-native": "src/index.ts",
@@ -114,7 +114,7 @@
114
114
  "registry": "https://registry.npmjs.org/"
115
115
  },
116
116
  "dependencies": {
117
- "@mentra/cloud-protocol": "3.3.0-dev.788"
117
+ "@mentra/cloud-protocol": "3.3.0-dev.791"
118
118
  },
119
119
  "devDependencies": {
120
120
  "@types/node": "^25.9.3",
@@ -12,9 +12,9 @@ export interface BluetoothSdkReleaseMetadata {
12
12
  export const BLUETOOTH_SDK_RELEASE_METADATA: Readonly<BluetoothSdkReleaseMetadata> = Object.freeze({
13
13
  "schemaVersion": 1,
14
14
  "familyBaseVersion": "3.3.0",
15
- "releaseIdentity": "3.3.0-dev.788",
16
- "releaseSetId": "mentra-3.3.0-dev.788",
17
- "sourceCommit": "557a9faa3f9c43bee85ab7cc3509e4770a000c22",
18
- "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.788.json",
19
- "otaManifestSha256": "a7fe57f5a3cb130c5615133b733fd46b880e6367ce07a283750cc7bf83d2415a"
15
+ "releaseIdentity": "3.3.0-dev.791",
16
+ "releaseSetId": "mentra-3.3.0-dev.791",
17
+ "sourceCommit": "97e2f51340fbd1ff1b1d0e5711910fcc306a4459",
18
+ "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.3.0/mentra-live-ota-3.3.0-dev.791.json",
19
+ "otaManifestSha256": "716e6e1fa00d8a3ec71e09d2e69e7e6920555ef4f0cb9ee8d21befb734819b50"
20
20
  })