@mentra/engine 3.4.0-dev.950 → 3.4.0-dev.953

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,10 @@
1
1
  export const ENGINE_RELEASE_METADATA = Object.freeze({
2
2
  "schemaVersion": 1,
3
3
  "familyBaseVersion": "3.4.0",
4
- "releaseIdentity": "3.4.0-dev.950",
5
- "releaseSetId": "mentra-3.4.0-dev.950",
6
- "sourceCommit": "6f46eab024e3d74343690a342b8a4f6700c9f6fd",
7
- "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.4.0/mentra-live-ota-3.4.0-dev.950.json",
8
- "otaManifestSha256": "57c401448f58ce9fba105991f4fd3ddfe0fe4f8ed6e7da35dd49da80b8145b1d"
4
+ "releaseIdentity": "3.4.0-dev.953",
5
+ "releaseSetId": "mentra-3.4.0-dev.953",
6
+ "sourceCommit": "c92cc365b1b592e1c926572eb32c50a48d040943",
7
+ "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.4.0/mentra-live-ota-3.4.0-dev.953.json",
8
+ "otaManifestSha256": "14e2f5dbe312a0f296b35fc6e87a81e9300bd8ba229f82dfd0ee75e80eb43fe6"
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,uBAAuB,GAAoC,MAAM,CAAC,MAAM,CAAC;IACpF,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 EngineReleaseMetadata {\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 ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({\n \"schemaVersion\": 1,\n \"familyBaseVersion\": \"3.4.0\",\n \"releaseIdentity\": \"3.4.0-dev.950\",\n \"releaseSetId\": \"mentra-3.4.0-dev.950\",\n \"sourceCommit\": \"6f46eab024e3d74343690a342b8a4f6700c9f6fd\",\n \"otaManifestUrl\": \"https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.4.0/mentra-live-ota-3.4.0-dev.950.json\",\n \"otaManifestSha256\": \"57c401448f58ce9fba105991f4fd3ddfe0fe4f8ed6e7da35dd49da80b8145b1d\"\n})\n"]}
1
+ {"version":3,"file":"releaseMetadata.js","sourceRoot":"","sources":["../../src/generated/releaseMetadata.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,uBAAuB,GAAoC,MAAM,CAAC,MAAM,CAAC;IACpF,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 EngineReleaseMetadata {\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 ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({\n \"schemaVersion\": 1,\n \"familyBaseVersion\": \"3.4.0\",\n \"releaseIdentity\": \"3.4.0-dev.953\",\n \"releaseSetId\": \"mentra-3.4.0-dev.953\",\n \"sourceCommit\": \"c92cc365b1b592e1c926572eb32c50a48d040943\",\n \"otaManifestUrl\": \"https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.4.0/mentra-live-ota-3.4.0-dev.953.json\",\n \"otaManifestSha256\": \"14e2f5dbe312a0f296b35fc6e87a81e9300bd8ba229f82dfd0ee75e80eb43fe6\"\n})\n"]}
@@ -218,7 +218,7 @@ class HotspotOtaTransport {
218
218
  }
219
219
  if (this.localNetworkRequested) {
220
220
  try {
221
- await localNetworkTransport.disconnect(this.networkOwner);
221
+ await localNetworkTransport.disconnect(this.networkOwner, true);
222
222
  this.localNetworkRequested = false;
223
223
  this.localNetworkConnected = false;
224
224
  }
@@ -1 +1 @@
1
- {"version":3,"file":"HotspotOtaTransport.js","sourceRoot":"","sources":["../../src/services/HotspotOtaTransport.ts"],"names":[],"mappings":"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","sourcesContent":["import BluetoothSdk, {isEnabledHotspotStatus} from \"@mentra/bluetooth-sdk\"\nimport {otaServer} from \"@mentra/bluetooth-sdk/ota-transport\"\n// One coordinator selects the native Android or iOS staging implementation at runtime.\n// eslint-disable-next-line react-native/split-platform-components\nimport {PermissionsAndroid, Platform} from \"react-native\"\nimport {otaDeviceSessionRevision} from \"./OtaDeviceSession\"\nimport type {OtaCheckCurrentGlassesResult} from \"./OtaUpdateCheckService\"\nimport {\n cleanupArtifacts,\n OtaArtifactError,\n planArtifacts,\n prepareArtifacts,\n rewriteManifestForLocalServer,\n type OtaArtifactDownloadProgress,\n type PreparedOtaArtifact,\n} from \"./OtaArtifactDownloader\"\nimport {acquireGlassesHotspot} from \"./GlassesHotspotLease\"\nimport {disableHotspotWithRetry} from \"./HotspotShutdown\"\nimport {\n localNetworkErrorDetails,\n localNetworkTransport,\n type LocalNetworkErrorDetails,\n} from \"./asg/localNetworkTransport\"\n\nexport type HotspotOtaPhase = \"idle\" | \"downloading\" | \"starting_hotspot\" | \"joining_hotspot\" | \"serving\"\n\nexport type HotspotOtaProgress = {\n phase: HotspotOtaPhase\n artifact?: OtaArtifactDownloadProgress\n}\n\nexport type HotspotOtaErrorCode =\n | \"hotspot_wifi_permission_denied\"\n | \"hotspot_start_failed\"\n | \"hotspot_join_failed\"\n | \"hotspot_server_failed\"\n\nexport class HotspotOtaTransportError extends Error {\n constructor(\n public readonly code: HotspotOtaErrorCode,\n message: string,\n public readonly nativeError?: LocalNetworkErrorDetails,\n ) {\n super(message)\n this.name = \"HotspotOtaTransportError\"\n }\n}\n\n/** Owns the single phone-side endpoint and network lease for one hotspot OTA attempt. */\nclass HotspotOtaTransport {\n private readonly networkOwner = Symbol(\"hotspot-ota\")\n private releaseHotspot: (() => void) | null = null\n private active = false\n private prepared: PreparedOtaArtifact[] = []\n private hotspotRequested = false\n private localNetworkConnected = false\n private localNetworkRequested = false\n private serverStarted = false\n private teardownPromise: Promise<void> | null = null\n private preparing: Promise<string> | null = null\n private generation = 0\n private ownerRevision = 0\n\n async prepare(\n checkResult: OtaCheckCurrentGlassesResult,\n onProgress?: (progress: HotspotOtaProgress) => void,\n ): Promise<string> {\n const ownerRevision = otaDeviceSessionRevision()\n if (this.teardownPromise) await this.teardownPromise\n if (ownerRevision !== otaDeviceSessionRevision()) throw new Error(\"The OTA glasses have changed\")\n if (\n this.releaseHotspot ||\n this.active ||\n this.preparing ||\n this.localNetworkRequested ||\n this.serverStarted ||\n this.hotspotRequested ||\n this.prepared.length\n ) {\n throw new Error(\"A hotspot OTA transport is active or still needs cleanup\")\n }\n if (!checkResult.manifestBody) throw new Error(\"The selected OTA check has no manifest body\")\n // Refusal happens before downloading or changing the glasses AP.\n this.releaseHotspot = acquireGlassesHotspot()\n this.ownerRevision = ownerRevision\n const generation = ++this.generation\n const assertCurrent = () => {\n if (generation !== this.generation || ownerRevision !== otaDeviceSessionRevision()) {\n throw new Error(\"The OTA glasses have changed\")\n }\n }\n const preparation = this.prepareAttempt(checkResult, assertCurrent, onProgress)\n this.preparing = preparation\n try {\n return await preparation\n } catch (error) {\n // Remove our promise before waiting on teardown, which joins preparation.\n if (this.preparing === preparation) this.preparing = null\n try {\n await this.teardown(ownerRevision === otaDeviceSessionRevision())\n } catch (cleanupError) {\n console.warn(\"[OTA_PROGRESS] cleanup failed\", localNetworkErrorDetails(cleanupError))\n }\n throw error\n } finally {\n if (this.preparing === preparation) this.preparing = null\n }\n }\n\n private async prepareAttempt(\n checkResult: OtaCheckCurrentGlassesResult,\n assertCurrent: () => void,\n onProgress?: (progress: HotspotOtaProgress) => void,\n ): Promise<string> {\n const manifestBody = checkResult.manifestBody\n if (!manifestBody) throw new Error(\"The selected OTA check has no manifest body\")\n let phase: HotspotOtaPhase = \"downloading\"\n try {\n await this.ensureAndroidWifiPermission()\n assertCurrent()\n onProgress?.({phase: \"downloading\"})\n this.prepared = await prepareArtifacts(\n planArtifacts(checkResult),\n (artifact) => onProgress?.({phase: \"downloading\", artifact}),\n Platform.OS === \"ios\" ? this.downloadIosArtifact : undefined,\n )\n\n assertCurrent()\n phase = \"starting_hotspot\"\n onProgress?.({phase: \"starting_hotspot\"})\n assertCurrent()\n this.hotspotRequested = true\n const hotspot = await BluetoothSdk.setHotspotState(true)\n assertCurrent()\n if (!isEnabledHotspotStatus(hotspot)) {\n throw new HotspotOtaTransportError(\"hotspot_start_failed\", \"Mentra Live did not return hotspot credentials\")\n }\n phase = \"joining_hotspot\"\n onProgress?.({phase: \"joining_hotspot\"})\n assertCurrent()\n this.localNetworkRequested = true\n const scopedAddress = await localNetworkTransport.connect(this.networkOwner, hotspot.ssid, hotspot.password, {\n retryIosInternalError: true,\n assertCurrent,\n gateway: hotspot.localIp,\n // The glasses download from our listener; OTA never calls the Gallery server.\n purpose: \"incoming-server\",\n })\n this.localNetworkConnected = true\n assertCurrent()\n let localAddress = scopedAddress\n if (Platform.OS === \"ios\" && !localAddress) {\n try {\n localAddress = await otaServer.waitForWifiAddress(hotspot.localIp, 15_000)\n assertCurrent()\n } catch (error) {\n throw new HotspotOtaTransportError(\n \"hotspot_join_failed\",\n error instanceof Error ? error.message : String(error),\n )\n }\n }\n const artifactPaths = Object.fromEntries(this.prepared.map((artifact) => [artifact.sha256, artifact.filePath]))\n // Start exactly one native listener to learn its selected port, then atomically replace\n // the placeholder with the immutable rewritten manifest before ota_start is sent.\n const server = await otaServer.start(\"{}\", artifactPaths, localAddress)\n this.serverStarted = true\n assertCurrent()\n const manifest = rewriteManifestForLocalServer(manifestBody, this.prepared, server.baseUrl)\n const published = await otaServer.start(manifest, artifactPaths, server.host)\n assertCurrent()\n if (published.manifestUrl !== server.manifestUrl) {\n throw new Error(\"Local OTA server endpoint changed while publishing the manifest\")\n }\n this.active = true\n onProgress?.({phase: \"serving\"})\n return published.manifestUrl\n } catch (error) {\n const joined = this.localNetworkConnected\n if (error instanceof OtaArtifactError || error instanceof HotspotOtaTransportError) {\n throw error\n }\n const message = error instanceof Error ? error.message : String(error)\n if (phase === \"starting_hotspot\") {\n throw new HotspotOtaTransportError(\"hotspot_start_failed\", message)\n }\n if (phase === \"joining_hotspot\" && !joined) {\n throw new HotspotOtaTransportError(\"hotspot_join_failed\", message, localNetworkErrorDetails(error))\n }\n throw new HotspotOtaTransportError(\"hotspot_server_failed\", message)\n }\n }\n\n /** Android 13+ requires the nearby-WiFi runtime grant before WifiNetworkSpecifier is usable. */\n private async ensureAndroidWifiPermission(): Promise<void> {\n if (Platform.OS !== \"android\") return\n\n const permission = PermissionsAndroid.PERMISSIONS.NEARBY_WIFI_DEVICES\n if (await PermissionsAndroid.check(permission)) return\n const result = await PermissionsAndroid.request(permission)\n if (result !== PermissionsAndroid.RESULTS.GRANTED) {\n throw new HotspotOtaTransportError(\n \"hotspot_wifi_permission_denied\",\n \"Nearby devices permission is required to connect to the glasses hotspot\",\n )\n }\n }\n\n private downloadIosArtifact = async (\n entry: {url: string},\n destination: string,\n onProgress?: (bytesWritten: number, contentLength: number) => void,\n ): Promise<{statusCode: number}> => {\n const subscription = otaServer.onArtifactDownloadProgress((event) => {\n if (event.destination === destination) onProgress?.(event.bytesWritten, event.contentLength)\n })\n try {\n return await otaServer.downloadArtifact(entry.url, destination)\n } finally {\n subscription.remove()\n }\n }\n\n async teardown(disableGlassesHotspot = true): Promise<void> {\n this.generation += 1\n if (this.teardownPromise) return this.teardownPromise\n this.teardownPromise = (async () => {\n if (!this.releaseHotspot) return\n await this.preparing?.catch(() => {})\n const errors: unknown[] = []\n if (disableGlassesHotspot && this.ownerRevision === otaDeviceSessionRevision() && this.hotspotRequested) {\n try {\n const hotspotStopped = await disableHotspotWithRetry(\n () =>\n this.ownerRevision === otaDeviceSessionRevision()\n ? BluetoothSdk.setHotspotState(false)\n : Promise.resolve({state: \"enabled\" as const}),\n {\n // A completed APK step has just replaced ASG. Let the new command path\n // settle before asking it to tear down the SystemUI-owned access point.\n initialDelayMs: this.serverStarted ? 750 : 0,\n },\n )\n if (hotspotStopped) this.hotspotRequested = false\n else errors.push(new Error(\"The glasses hotspot shutdown was not confirmed\"))\n } catch (error) {\n errors.push(error)\n }\n } else this.hotspotRequested = false\n if (this.serverStarted) {\n try {\n await otaServer.stop()\n this.serverStarted = false\n } catch (error) {\n errors.push(error)\n }\n }\n if (this.localNetworkRequested) {\n try {\n await localNetworkTransport.disconnect(this.networkOwner)\n this.localNetworkRequested = false\n this.localNetworkConnected = false\n } catch (error) {\n errors.push(error)\n }\n }\n if (!this.serverStarted) {\n // A server that has not stopped can still read these files.\n try {\n await cleanupArtifacts()\n this.prepared = []\n } catch (error) {\n errors.push(error)\n }\n }\n this.active = false\n if (errors.length) throw errors[0]\n this.releaseHotspot()\n this.releaseHotspot = null\n })()\n try {\n await this.teardownPromise\n } finally {\n this.teardownPromise = null\n }\n }\n}\n\nexport const hotspotOtaTransport = new HotspotOtaTransport()\n"]}
1
+ {"version":3,"file":"HotspotOtaTransport.js","sourceRoot":"","sources":["../../src/services/HotspotOtaTransport.ts"],"names":[],"mappings":"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","sourcesContent":["import BluetoothSdk, {isEnabledHotspotStatus} from \"@mentra/bluetooth-sdk\"\nimport {otaServer} from \"@mentra/bluetooth-sdk/ota-transport\"\n// One coordinator selects the native Android or iOS staging implementation at runtime.\n// eslint-disable-next-line react-native/split-platform-components\nimport {PermissionsAndroid, Platform} from \"react-native\"\nimport {otaDeviceSessionRevision} from \"./OtaDeviceSession\"\nimport type {OtaCheckCurrentGlassesResult} from \"./OtaUpdateCheckService\"\nimport {\n cleanupArtifacts,\n OtaArtifactError,\n planArtifacts,\n prepareArtifacts,\n rewriteManifestForLocalServer,\n type OtaArtifactDownloadProgress,\n type PreparedOtaArtifact,\n} from \"./OtaArtifactDownloader\"\nimport {acquireGlassesHotspot} from \"./GlassesHotspotLease\"\nimport {disableHotspotWithRetry} from \"./HotspotShutdown\"\nimport {\n localNetworkErrorDetails,\n localNetworkTransport,\n type LocalNetworkErrorDetails,\n} from \"./asg/localNetworkTransport\"\n\nexport type HotspotOtaPhase = \"idle\" | \"downloading\" | \"starting_hotspot\" | \"joining_hotspot\" | \"serving\"\n\nexport type HotspotOtaProgress = {\n phase: HotspotOtaPhase\n artifact?: OtaArtifactDownloadProgress\n}\n\nexport type HotspotOtaErrorCode =\n | \"hotspot_wifi_permission_denied\"\n | \"hotspot_start_failed\"\n | \"hotspot_join_failed\"\n | \"hotspot_server_failed\"\n\nexport class HotspotOtaTransportError extends Error {\n constructor(\n public readonly code: HotspotOtaErrorCode,\n message: string,\n public readonly nativeError?: LocalNetworkErrorDetails,\n ) {\n super(message)\n this.name = \"HotspotOtaTransportError\"\n }\n}\n\n/** Owns the single phone-side endpoint and network lease for one hotspot OTA attempt. */\nclass HotspotOtaTransport {\n private readonly networkOwner = Symbol(\"hotspot-ota\")\n private releaseHotspot: (() => void) | null = null\n private active = false\n private prepared: PreparedOtaArtifact[] = []\n private hotspotRequested = false\n private localNetworkConnected = false\n private localNetworkRequested = false\n private serverStarted = false\n private teardownPromise: Promise<void> | null = null\n private preparing: Promise<string> | null = null\n private generation = 0\n private ownerRevision = 0\n\n async prepare(\n checkResult: OtaCheckCurrentGlassesResult,\n onProgress?: (progress: HotspotOtaProgress) => void,\n ): Promise<string> {\n const ownerRevision = otaDeviceSessionRevision()\n if (this.teardownPromise) await this.teardownPromise\n if (ownerRevision !== otaDeviceSessionRevision()) throw new Error(\"The OTA glasses have changed\")\n if (\n this.releaseHotspot ||\n this.active ||\n this.preparing ||\n this.localNetworkRequested ||\n this.serverStarted ||\n this.hotspotRequested ||\n this.prepared.length\n ) {\n throw new Error(\"A hotspot OTA transport is active or still needs cleanup\")\n }\n if (!checkResult.manifestBody) throw new Error(\"The selected OTA check has no manifest body\")\n // Refusal happens before downloading or changing the glasses AP.\n this.releaseHotspot = acquireGlassesHotspot()\n this.ownerRevision = ownerRevision\n const generation = ++this.generation\n const assertCurrent = () => {\n if (generation !== this.generation || ownerRevision !== otaDeviceSessionRevision()) {\n throw new Error(\"The OTA glasses have changed\")\n }\n }\n const preparation = this.prepareAttempt(checkResult, assertCurrent, onProgress)\n this.preparing = preparation\n try {\n return await preparation\n } catch (error) {\n // Remove our promise before waiting on teardown, which joins preparation.\n if (this.preparing === preparation) this.preparing = null\n try {\n await this.teardown(ownerRevision === otaDeviceSessionRevision())\n } catch (cleanupError) {\n console.warn(\"[OTA_PROGRESS] cleanup failed\", localNetworkErrorDetails(cleanupError))\n }\n throw error\n } finally {\n if (this.preparing === preparation) this.preparing = null\n }\n }\n\n private async prepareAttempt(\n checkResult: OtaCheckCurrentGlassesResult,\n assertCurrent: () => void,\n onProgress?: (progress: HotspotOtaProgress) => void,\n ): Promise<string> {\n const manifestBody = checkResult.manifestBody\n if (!manifestBody) throw new Error(\"The selected OTA check has no manifest body\")\n let phase: HotspotOtaPhase = \"downloading\"\n try {\n await this.ensureAndroidWifiPermission()\n assertCurrent()\n onProgress?.({phase: \"downloading\"})\n this.prepared = await prepareArtifacts(\n planArtifacts(checkResult),\n (artifact) => onProgress?.({phase: \"downloading\", artifact}),\n Platform.OS === \"ios\" ? this.downloadIosArtifact : undefined,\n )\n\n assertCurrent()\n phase = \"starting_hotspot\"\n onProgress?.({phase: \"starting_hotspot\"})\n assertCurrent()\n this.hotspotRequested = true\n const hotspot = await BluetoothSdk.setHotspotState(true)\n assertCurrent()\n if (!isEnabledHotspotStatus(hotspot)) {\n throw new HotspotOtaTransportError(\"hotspot_start_failed\", \"Mentra Live did not return hotspot credentials\")\n }\n phase = \"joining_hotspot\"\n onProgress?.({phase: \"joining_hotspot\"})\n assertCurrent()\n this.localNetworkRequested = true\n const scopedAddress = await localNetworkTransport.connect(this.networkOwner, hotspot.ssid, hotspot.password, {\n retryIosInternalError: true,\n assertCurrent,\n gateway: hotspot.localIp,\n // The glasses download from our listener; OTA never calls the Gallery server.\n purpose: \"incoming-server\",\n })\n this.localNetworkConnected = true\n assertCurrent()\n let localAddress = scopedAddress\n if (Platform.OS === \"ios\" && !localAddress) {\n try {\n localAddress = await otaServer.waitForWifiAddress(hotspot.localIp, 15_000)\n assertCurrent()\n } catch (error) {\n throw new HotspotOtaTransportError(\n \"hotspot_join_failed\",\n error instanceof Error ? error.message : String(error),\n )\n }\n }\n const artifactPaths = Object.fromEntries(this.prepared.map((artifact) => [artifact.sha256, artifact.filePath]))\n // Start exactly one native listener to learn its selected port, then atomically replace\n // the placeholder with the immutable rewritten manifest before ota_start is sent.\n const server = await otaServer.start(\"{}\", artifactPaths, localAddress)\n this.serverStarted = true\n assertCurrent()\n const manifest = rewriteManifestForLocalServer(manifestBody, this.prepared, server.baseUrl)\n const published = await otaServer.start(manifest, artifactPaths, server.host)\n assertCurrent()\n if (published.manifestUrl !== server.manifestUrl) {\n throw new Error(\"Local OTA server endpoint changed while publishing the manifest\")\n }\n this.active = true\n onProgress?.({phase: \"serving\"})\n return published.manifestUrl\n } catch (error) {\n const joined = this.localNetworkConnected\n if (error instanceof OtaArtifactError || error instanceof HotspotOtaTransportError) {\n throw error\n }\n const message = error instanceof Error ? error.message : String(error)\n if (phase === \"starting_hotspot\") {\n throw new HotspotOtaTransportError(\"hotspot_start_failed\", message)\n }\n if (phase === \"joining_hotspot\" && !joined) {\n throw new HotspotOtaTransportError(\"hotspot_join_failed\", message, localNetworkErrorDetails(error))\n }\n throw new HotspotOtaTransportError(\"hotspot_server_failed\", message)\n }\n }\n\n /** Android 13+ requires the nearby-WiFi runtime grant before WifiNetworkSpecifier is usable. */\n private async ensureAndroidWifiPermission(): Promise<void> {\n if (Platform.OS !== \"android\") return\n\n const permission = PermissionsAndroid.PERMISSIONS.NEARBY_WIFI_DEVICES\n if (await PermissionsAndroid.check(permission)) return\n const result = await PermissionsAndroid.request(permission)\n if (result !== PermissionsAndroid.RESULTS.GRANTED) {\n throw new HotspotOtaTransportError(\n \"hotspot_wifi_permission_denied\",\n \"Nearby devices permission is required to connect to the glasses hotspot\",\n )\n }\n }\n\n private downloadIosArtifact = async (\n entry: {url: string},\n destination: string,\n onProgress?: (bytesWritten: number, contentLength: number) => void,\n ): Promise<{statusCode: number}> => {\n const subscription = otaServer.onArtifactDownloadProgress((event) => {\n if (event.destination === destination) onProgress?.(event.bytesWritten, event.contentLength)\n })\n try {\n return await otaServer.downloadArtifact(entry.url, destination)\n } finally {\n subscription.remove()\n }\n }\n\n async teardown(disableGlassesHotspot = true): Promise<void> {\n this.generation += 1\n if (this.teardownPromise) return this.teardownPromise\n this.teardownPromise = (async () => {\n if (!this.releaseHotspot) return\n await this.preparing?.catch(() => {})\n const errors: unknown[] = []\n if (disableGlassesHotspot && this.ownerRevision === otaDeviceSessionRevision() && this.hotspotRequested) {\n try {\n const hotspotStopped = await disableHotspotWithRetry(\n () =>\n this.ownerRevision === otaDeviceSessionRevision()\n ? BluetoothSdk.setHotspotState(false)\n : Promise.resolve({state: \"enabled\" as const}),\n {\n // A completed APK step has just replaced ASG. Let the new command path\n // settle before asking it to tear down the SystemUI-owned access point.\n initialDelayMs: this.serverStarted ? 750 : 0,\n },\n )\n if (hotspotStopped) this.hotspotRequested = false\n else errors.push(new Error(\"The glasses hotspot shutdown was not confirmed\"))\n } catch (error) {\n errors.push(error)\n }\n } else this.hotspotRequested = false\n if (this.serverStarted) {\n try {\n await otaServer.stop()\n this.serverStarted = false\n } catch (error) {\n errors.push(error)\n }\n }\n if (this.localNetworkRequested) {\n try {\n await localNetworkTransport.disconnect(this.networkOwner, true)\n this.localNetworkRequested = false\n this.localNetworkConnected = false\n } catch (error) {\n errors.push(error)\n }\n }\n if (!this.serverStarted) {\n // A server that has not stopped can still read these files.\n try {\n await cleanupArtifacts()\n this.prepared = []\n } catch (error) {\n errors.push(error)\n }\n }\n this.active = false\n if (errors.length) throw errors[0]\n this.releaseHotspot()\n this.releaseHotspot = null\n })()\n try {\n await this.teardownPromise\n } finally {\n this.teardownPromise = null\n }\n }\n}\n\nexport const hotspotOtaTransport = new HotspotOtaTransport()\n"]}
@@ -31,7 +31,7 @@ export declare const localNetworkTransport: {
31
31
  gateway?: string;
32
32
  purpose?: "outgoing-client" | "incoming-server";
33
33
  }): Promise<string | undefined>;
34
- disconnect(caller: symbol): Promise<void>;
34
+ disconnect(caller: symbol, waitForInternet?: boolean): Promise<void>;
35
35
  fetch(url: string | URL | Request, init?: RequestInit, timeoutMs?: number): Promise<Response>;
36
36
  downloadFile(options: DownloadOptions): DownloadHandle;
37
37
  stopDownload(jobId: number): void;
@@ -1 +1 @@
1
- {"version":3,"file":"localNetworkTransport.d.ts","sourceRoot":"","sources":["../../../src/services/asg/localNetworkTransport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,6BAA6B,CAAA;AASnD,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;AAC9D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,CAAA;AAS1D,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,CAAA;IACtD,MAAM,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,IAAI,CAAC;QAAC,UAAU,CAAC,EAAE;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAC,CAAA;KAAC,CAAA;CACtG,CAAA;AAmCD,uFAAuF;AACvF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CA2DjF;AAED,wBAAgB,2BAA2B,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,GAAG,OAAO,CAEzF;AAuBD,eAAO,MAAM,qBAAqB;oCACF,OAAO;oCACP,OAAO;oBAG3B,MAAM,QACR,MAAM,YACF,MAAM,YACN;QACR,qBAAqB,CAAC,EAAE,IAAI,CAAA;QAC5B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;QAC1B,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,OAAO,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,CAAA;KAChD,GACA,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;uBAsEL,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;eAe9B,MAAM,GAAG,GAAG,GAAG,OAAO,SAAS,WAAW,uBAAuB,OAAO,CAAC,QAAQ,CAAC;0BA8B7E,eAAe,GAAG,cAAc;wBA8DlC,MAAM,GAAG,IAAI;CASlC,CAAA"}
1
+ {"version":3,"file":"localNetworkTransport.d.ts","sourceRoot":"","sources":["../../../src/services/asg/localNetworkTransport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,6BAA6B,CAAA;AASnD,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;AAC9D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,CAAA;AAS1D,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,CAAA;IACtD,MAAM,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,IAAI,CAAC;QAAC,UAAU,CAAC,EAAE;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAC,CAAA;KAAC,CAAA;CACtG,CAAA;AAmCD,uFAAuF;AACvF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CA2DjF;AAED,wBAAgB,2BAA2B,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,GAAG,OAAO,CAEzF;AAuBD,eAAO,MAAM,qBAAqB;oCACF,OAAO;oCACP,OAAO;oBAG3B,MAAM,QACR,MAAM,YACF,MAAM,YACN;QACR,qBAAqB,CAAC,EAAE,IAAI,CAAA;QAC5B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;QAC1B,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,OAAO,CAAC,EAAE,iBAAiB,GAAG,iBAAiB,CAAA;KAChD,GACA,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;uBAsEL,MAAM,8BAA4B,OAAO,CAAC,IAAI,CAAC;eAevD,MAAM,GAAG,GAAG,GAAG,OAAO,SAAS,WAAW,uBAAuB,OAAO,CAAC,QAAQ,CAAC;0BA8B7E,eAAe,GAAG,cAAc;wBA8DlC,MAAM,GAAG,IAAI;CASlC,CAAA"}
@@ -196,13 +196,13 @@ export const localNetworkTransport = {
196
196
  scopedConnectionActive = true;
197
197
  return result.localAddress;
198
198
  },
199
- async disconnect(caller) {
199
+ async disconnect(caller, waitForInternet = false) {
200
200
  if (macHotspotOwner && macHotspotOwner.caller !== caller)
201
201
  return;
202
202
  connectionGeneration += 1;
203
203
  if (macHotspotOwner) {
204
204
  const owner = macHotspotOwner.nativeId;
205
- await glassesHotspot.leave(owner);
205
+ await glassesHotspot.leave(owner, waitForInternet);
206
206
  if (macHotspotOwner?.nativeId === owner)
207
207
  macHotspotOwner = null;
208
208
  }
@@ -1 +1 @@
1
- {"version":3,"file":"localNetworkTransport.js","sourceRoot":"","sources":["../../../src/services/asg/localNetworkTransport.ts"],"names":[],"mappings":"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","sourcesContent":["import * as RNFS from \"@dr.pogodin/react-native-fs\"\nimport {otaLocalNetwork, type OtaLocalNetworkDownloadProgress} from \"@mentra/bluetooth-sdk/ota-transport\"\nimport CrustModule from \"@mentra/crust\"\nimport {glassesHotspot} from \"@mentra/glasses-media\"\nimport {Buffer} from \"buffer\"\nimport {Platform} from \"react-native\"\nimport WifiManager from \"react-native-wifi-reborn\"\nimport {BgTimer} from \"../../utils/timers\"\n\ntype DownloadOptions = Parameters<typeof RNFS.downloadFile>[0]\ntype DownloadHandle = ReturnType<typeof RNFS.downloadFile>\n\nlet connectionGeneration = 0\nlet scopedConnectionActive = false\nlet nextJobId = 1_000_000\nconst nativeJobs = new Map<number, string>()\nconst cancelledNativeJobs = new Set<number>()\nlet macHotspotOwner: {caller: symbol; nativeId: string} | null = null\n\nexport type LocalNetworkErrorDetails = {\n code?: string | number\n domain?: string\n message?: string\n underlying?: {code?: string | number; domain?: string}\n native?: {code: number; domain: string; completed: true; underlying?: {code: number; domain: string}}\n}\n\n// Existing native builds wrap these app-authored LocalMediaError causes in ERR_UNEXPECTED.\n// Expo keeps the cause in Error.message, but normal Error serialization omits it.\n// Recover only exact owned causes, never arbitrary NSError descriptions or network identities.\nconst legacyHotspotCauses = new Set([\n \"Previous hotspot session has not been released\",\n \"Previous hotspot session has not finished cleaning up\",\n \"Invalid hotspot access purpose\",\n \"The glasses reported an invalid hotspot gateway\",\n \"The glasses did not report their hotspot gateway\",\n \"The glasses hotspot is already in use\",\n \"Hotspot join timed out\",\n \"Hotspot join cancelled\",\n \"Location access is required to identify the glasses hotspot on Mac\",\n \"Mac hotspot Location authorization is unavailable\",\n \"Location access is required to verify the current Mac Wi-Fi network\",\n \"Mac Wi-Fi did not associate with the requested glasses hotspot\",\n \"Mac Wi-Fi framework is unavailable\",\n \"Mac Wi-Fi interface is unavailable\",\n \"Mac Wi-Fi interface does not support hotspot association\",\n \"Mac Wi-Fi interface has no identity\",\n \"Mac Wi-Fi interface disappeared during association\",\n \"The requested glasses hotspot was not found by Mac Wi-Fi\",\n \"Mac Wi-Fi has no verified glasses hotspot address\",\n \"Local connection to the glasses timed out\",\n])\n\nfunction legacyHotspotCause(message: string): string | undefined {\n if (message.length > 2048) return undefined\n const cause = message.split(\"\\n→ Caused by: \").at(-1)!\n if (legacyHotspotCauses.has(cause)) return cause\n return /^Mac Wi-Fi (scan|association) failed \\([A-Za-z0-9_.-]{1,128}, -?\\d{1,12}\\)$/.test(cause) ? cause : undefined\n}\n\n/** Keep native connection facts ahead of large stacks and private NSError userInfo. */\nexport function localNetworkErrorDetails(error: unknown): LocalNetworkErrorDetails {\n const facts = (value: unknown): {code?: string | number; domain?: string} => {\n if (!value || typeof value !== \"object\") return {}\n const {code, domain} = value as {code?: unknown; domain?: unknown}\n return {\n ...(typeof code === \"number\" && Number.isFinite(code)\n ? {code}\n : typeof code === \"string\" && /^[A-Za-z0-9_.-]{1,128}$/.test(code)\n ? {code}\n : {}),\n ...(typeof domain === \"string\" && /^[A-Za-z0-9_.-]{1,128}$/.test(domain) ? {domain} : {}),\n }\n }\n const details = facts(error)\n const message = error && typeof error === \"object\" && \"message\" in error && typeof error.message === \"string\"\n ? error.message\n : undefined\n const hotspotMessage =\n typeof details.code === \"string\" &&\n [\"ERR_HOTSPOT_JOIN\", \"ERR_HOTSPOT_CANCELLED\", \"ERR_HOTSPOT_NATIVE\"].includes(details.code) &&\n message !== undefined\n ? message.replace(/[\\u0000-\\u001f\\u007f-\\u009f]/g, \"\").slice(0, 512)\n : details.code === \"ERR_UNEXPECTED\" && message !== undefined ? legacyHotspotCause(message) : undefined\n const userInfo = (error as {userInfo?: unknown} | null | undefined)?.userInfo\n const underlying = facts(\n userInfo && typeof userInfo === \"object\"\n ? (userInfo as {NSUnderlyingError?: unknown}).NSUnderlyingError\n : undefined,\n )\n const nativeValue =\n userInfo && typeof userInfo === \"object\" ? (userInfo as {RNWifiNativeError?: unknown}).RNWifiNativeError : undefined\n const nativeFacts = facts(nativeValue)\n const native =\n nativeValue &&\n typeof nativeValue === \"object\" &&\n (nativeValue as {completed?: unknown}).completed === true &&\n typeof nativeFacts.code === \"number\" &&\n Number.isSafeInteger(nativeFacts.code) &&\n nativeFacts.domain\n ? {code: nativeFacts.code, domain: nativeFacts.domain, completed: true as const}\n : undefined\n const nativeUnderlying = facts((nativeValue as {underlying?: unknown} | undefined)?.underlying)\n return {\n ...details,\n ...(hotspotMessage ? {message: hotspotMessage} : {}),\n ...(Object.keys(underlying).length ? {underlying} : {}),\n ...(native\n ? {\n native: {\n ...native,\n ...(typeof nativeUnderlying.code === \"number\" &&\n Number.isSafeInteger(nativeUnderlying.code) &&\n nativeUnderlying.domain\n ? {underlying: {code: nativeUnderlying.code, domain: nativeUnderlying.domain}}\n : {}),\n },\n }\n : {}),\n }\n}\n\nexport function shouldUseScopedLocalNetwork(os: string, moduleAvailable: boolean): boolean {\n return os === \"android\" && moduleAvailable\n}\n\nfunction supportsScopedConnection(): boolean {\n return shouldUseScopedLocalNetwork(Platform.OS, otaLocalNetwork.isAvailable())\n}\n\nfunction normalizeHeaders(headers?: HeadersInit): Record<string, string> {\n if (!headers) return {}\n if (headers instanceof Headers) {\n const result: Record<string, string> = {}\n headers.forEach((value, key) => {\n result[key] = value\n })\n return result\n }\n if (Array.isArray(headers)) return Object.fromEntries(headers)\n return {...headers}\n}\n\nfunction requestId(prefix: string): string {\n return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2)}`\n}\n\nexport const localNetworkTransport = {\n supportsScopedConnection: (): boolean => supportsScopedConnection(),\n isScopedConnectionActive: (): boolean => scopedConnectionActive,\n\n async connect(\n caller: symbol,\n ssid: string,\n password: string,\n options?: {\n retryIosInternalError?: true\n assertCurrent?: () => void\n gateway?: string\n purpose?: \"outgoing-client\" | \"incoming-server\"\n },\n ): Promise<string | undefined> {\n const isMac = Platform.OS === \"ios\" && CrustModule.isIOSAppOnMac === true\n if (isMac && macHotspotOwner) throw new Error(\"Previous Mac hotspot session has not been released\")\n const generation = ++connectionGeneration\n const assertCurrent = () => {\n if (generation !== connectionGeneration) throw new Error(\"Local network connection was superseded\")\n options?.assertCurrent?.()\n }\n assertCurrent()\n scopedConnectionActive = false\n nativeJobs.clear()\n if (isMac) {\n const owner = requestId(\"mac_hotspot\")\n macHotspotOwner = {caller, nativeId: owner}\n try {\n const address = await glassesHotspot.join(\n owner,\n ssid,\n password,\n options?.gateway,\n options?.purpose ?? \"outgoing-client\",\n )\n assertCurrent()\n return address\n } catch (error) {\n try {\n await glassesHotspot.leave(owner)\n } catch (cleanupError) {\n console.warn(\"[LocalNetworkTransport] Mac hotspot cleanup failed\", localNetworkErrorDetails(cleanupError))\n throw error\n }\n if (macHotspotOwner?.nativeId === owner) macHotspotOwner = null\n throw error\n }\n }\n if (!supportsScopedConnection()) {\n // Gallery already owns its retry loop. OTA opts into this same-network\n // policy only with current-attempt authority; never race a pending native call.\n const retryDeadline = Date.now() + 30_000\n for (let attempt = 1; ; attempt += 1) {\n assertCurrent()\n try {\n await WifiManager.connectToProtectedSSID(ssid, password, false, false)\n // Report acquisition first; the caller records it before its own\n // identity check and normal teardown of a replaced OTA attempt.\n return undefined\n } catch (error) {\n assertCurrent()\n const details = localNetworkErrorDetails(error)\n console.warn(\"[LocalNetworkTransport] hotspot join rejected\", {attempt, ...details})\n if (\n !options?.retryIosInternalError ||\n Platform.OS !== \"ios\" ||\n attempt >= 3 ||\n details.native?.domain !== \"NEHotspotConfigurationErrorDomain\" ||\n details.native.code !== 8 ||\n Date.now() + 3_000 > retryDeadline\n )\n throw error\n await new Promise<void>((resolve) => BgTimer.setTimeout(resolve, 3_000))\n assertCurrent()\n if (Date.now() > retryDeadline) throw error\n }\n }\n }\n const result = await otaLocalNetwork.connect(ssid, password)\n scopedConnectionActive = true\n return result.localAddress\n },\n\n async disconnect(caller: symbol): Promise<void> {\n if (macHotspotOwner && macHotspotOwner.caller !== caller) return\n connectionGeneration += 1\n if (macHotspotOwner) {\n const owner = macHotspotOwner.nativeId\n await glassesHotspot.leave(owner)\n if (macHotspotOwner?.nativeId === owner) macHotspotOwner = null\n }\n if (supportsScopedConnection()) {\n await otaLocalNetwork.disconnect()\n }\n scopedConnectionActive = false\n nativeJobs.clear()\n },\n\n async fetch(url: string | URL | Request, init?: RequestInit, timeoutMs = 30_000): Promise<Response> {\n if (!scopedConnectionActive || !otaLocalNetwork.isAvailable() || typeof url !== \"string\") {\n return globalThis.fetch(url, init)\n }\n\n const nativeModule = otaLocalNetwork\n const id = requestId(\"request\")\n const signal = init?.signal\n const cancel = () => void nativeModule.cancel(id)\n if (signal?.aborted) throw new Error(\"Request aborted\")\n signal?.addEventListener(\"abort\", cancel, {once: true})\n try {\n const result = await nativeModule.request(\n id,\n url,\n init?.method || \"GET\",\n normalizeHeaders(init?.headers),\n typeof init?.body === \"string\" ? init.body : null,\n timeoutMs,\n )\n const bytes = Buffer.from(result.bodyBase64, \"base64\")\n return new Response(bytes as unknown as BodyInit, {\n status: result.status,\n headers: result.headers,\n })\n } finally {\n signal?.removeEventListener(\"abort\", cancel)\n }\n },\n\n downloadFile(options: DownloadOptions): DownloadHandle {\n if (!scopedConnectionActive || !otaLocalNetwork.isAvailable()) return RNFS.downloadFile(options)\n\n const jobId = nextJobId++\n const id = requestId(\"download\")\n let began = false\n nativeJobs.set(jobId, id)\n const subscription = otaLocalNetwork.onDownloadProgress((event: OtaLocalNetworkDownloadProgress) => {\n if (event.requestId !== id) return\n if (!began) {\n began = true\n options.begin?.({\n jobId,\n statusCode: event.statusCode || 200,\n contentLength: event.contentLength,\n headers: event.headers || {},\n })\n }\n options.progress?.({\n jobId,\n contentLength: event.contentLength,\n bytesWritten: event.bytesWritten,\n })\n })\n\n const promise = otaLocalNetwork\n .download(\n id,\n options.fromUrl,\n options.toFile,\n options.headers || {},\n options.connectionTimeout || 30_000,\n options.readTimeout || 30_000,\n )\n .then((result) => {\n if (!began) {\n options.begin?.({\n jobId,\n statusCode: result.statusCode,\n contentLength: result.bytesWritten,\n headers: result.headers,\n })\n }\n return {\n jobId,\n statusCode: result.statusCode,\n bytesWritten: result.bytesWritten,\n }\n })\n .catch((error) => {\n if (cancelledNativeJobs.has(jobId)) throw new Error(\"Sync cancelled\")\n throw error\n })\n .finally(() => {\n nativeJobs.delete(jobId)\n cancelledNativeJobs.delete(jobId)\n subscription.remove()\n })\n\n return {jobId, promise} as DownloadHandle\n },\n\n stopDownload(jobId: number): void {\n const nativeId = nativeJobs.get(jobId)\n if (nativeId && otaLocalNetwork.isAvailable()) {\n cancelledNativeJobs.add(jobId)\n void otaLocalNetwork.cancel(nativeId)\n return\n }\n RNFS.stopDownload(jobId)\n },\n}\n\notaLocalNetwork.onNetworkLost(() => {\n scopedConnectionActive = false\n nativeJobs.clear()\n})\n"]}
1
+ {"version":3,"file":"localNetworkTransport.js","sourceRoot":"","sources":["../../../src/services/asg/localNetworkTransport.ts"],"names":[],"mappings":"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","sourcesContent":["import * as RNFS from \"@dr.pogodin/react-native-fs\"\nimport {otaLocalNetwork, type OtaLocalNetworkDownloadProgress} from \"@mentra/bluetooth-sdk/ota-transport\"\nimport CrustModule from \"@mentra/crust\"\nimport {glassesHotspot} from \"@mentra/glasses-media\"\nimport {Buffer} from \"buffer\"\nimport {Platform} from \"react-native\"\nimport WifiManager from \"react-native-wifi-reborn\"\nimport {BgTimer} from \"../../utils/timers\"\n\ntype DownloadOptions = Parameters<typeof RNFS.downloadFile>[0]\ntype DownloadHandle = ReturnType<typeof RNFS.downloadFile>\n\nlet connectionGeneration = 0\nlet scopedConnectionActive = false\nlet nextJobId = 1_000_000\nconst nativeJobs = new Map<number, string>()\nconst cancelledNativeJobs = new Set<number>()\nlet macHotspotOwner: {caller: symbol; nativeId: string} | null = null\n\nexport type LocalNetworkErrorDetails = {\n code?: string | number\n domain?: string\n message?: string\n underlying?: {code?: string | number; domain?: string}\n native?: {code: number; domain: string; completed: true; underlying?: {code: number; domain: string}}\n}\n\n// Existing native builds wrap these app-authored LocalMediaError causes in ERR_UNEXPECTED.\n// Expo keeps the cause in Error.message, but normal Error serialization omits it.\n// Recover only exact owned causes, never arbitrary NSError descriptions or network identities.\nconst legacyHotspotCauses = new Set([\n \"Previous hotspot session has not been released\",\n \"Previous hotspot session has not finished cleaning up\",\n \"Invalid hotspot access purpose\",\n \"The glasses reported an invalid hotspot gateway\",\n \"The glasses did not report their hotspot gateway\",\n \"The glasses hotspot is already in use\",\n \"Hotspot join timed out\",\n \"Hotspot join cancelled\",\n \"Location access is required to identify the glasses hotspot on Mac\",\n \"Mac hotspot Location authorization is unavailable\",\n \"Location access is required to verify the current Mac Wi-Fi network\",\n \"Mac Wi-Fi did not associate with the requested glasses hotspot\",\n \"Mac Wi-Fi framework is unavailable\",\n \"Mac Wi-Fi interface is unavailable\",\n \"Mac Wi-Fi interface does not support hotspot association\",\n \"Mac Wi-Fi interface has no identity\",\n \"Mac Wi-Fi interface disappeared during association\",\n \"The requested glasses hotspot was not found by Mac Wi-Fi\",\n \"Mac Wi-Fi has no verified glasses hotspot address\",\n \"Local connection to the glasses timed out\",\n])\n\nfunction legacyHotspotCause(message: string): string | undefined {\n if (message.length > 2048) return undefined\n const cause = message.split(\"\\n→ Caused by: \").at(-1)!\n if (legacyHotspotCauses.has(cause)) return cause\n return /^Mac Wi-Fi (scan|association) failed \\([A-Za-z0-9_.-]{1,128}, -?\\d{1,12}\\)$/.test(cause) ? cause : undefined\n}\n\n/** Keep native connection facts ahead of large stacks and private NSError userInfo. */\nexport function localNetworkErrorDetails(error: unknown): LocalNetworkErrorDetails {\n const facts = (value: unknown): {code?: string | number; domain?: string} => {\n if (!value || typeof value !== \"object\") return {}\n const {code, domain} = value as {code?: unknown; domain?: unknown}\n return {\n ...(typeof code === \"number\" && Number.isFinite(code)\n ? {code}\n : typeof code === \"string\" && /^[A-Za-z0-9_.-]{1,128}$/.test(code)\n ? {code}\n : {}),\n ...(typeof domain === \"string\" && /^[A-Za-z0-9_.-]{1,128}$/.test(domain) ? {domain} : {}),\n }\n }\n const details = facts(error)\n const message = error && typeof error === \"object\" && \"message\" in error && typeof error.message === \"string\"\n ? error.message\n : undefined\n const hotspotMessage =\n typeof details.code === \"string\" &&\n [\"ERR_HOTSPOT_JOIN\", \"ERR_HOTSPOT_CANCELLED\", \"ERR_HOTSPOT_NATIVE\"].includes(details.code) &&\n message !== undefined\n ? message.replace(/[\\u0000-\\u001f\\u007f-\\u009f]/g, \"\").slice(0, 512)\n : details.code === \"ERR_UNEXPECTED\" && message !== undefined ? legacyHotspotCause(message) : undefined\n const userInfo = (error as {userInfo?: unknown} | null | undefined)?.userInfo\n const underlying = facts(\n userInfo && typeof userInfo === \"object\"\n ? (userInfo as {NSUnderlyingError?: unknown}).NSUnderlyingError\n : undefined,\n )\n const nativeValue =\n userInfo && typeof userInfo === \"object\" ? (userInfo as {RNWifiNativeError?: unknown}).RNWifiNativeError : undefined\n const nativeFacts = facts(nativeValue)\n const native =\n nativeValue &&\n typeof nativeValue === \"object\" &&\n (nativeValue as {completed?: unknown}).completed === true &&\n typeof nativeFacts.code === \"number\" &&\n Number.isSafeInteger(nativeFacts.code) &&\n nativeFacts.domain\n ? {code: nativeFacts.code, domain: nativeFacts.domain, completed: true as const}\n : undefined\n const nativeUnderlying = facts((nativeValue as {underlying?: unknown} | undefined)?.underlying)\n return {\n ...details,\n ...(hotspotMessage ? {message: hotspotMessage} : {}),\n ...(Object.keys(underlying).length ? {underlying} : {}),\n ...(native\n ? {\n native: {\n ...native,\n ...(typeof nativeUnderlying.code === \"number\" &&\n Number.isSafeInteger(nativeUnderlying.code) &&\n nativeUnderlying.domain\n ? {underlying: {code: nativeUnderlying.code, domain: nativeUnderlying.domain}}\n : {}),\n },\n }\n : {}),\n }\n}\n\nexport function shouldUseScopedLocalNetwork(os: string, moduleAvailable: boolean): boolean {\n return os === \"android\" && moduleAvailable\n}\n\nfunction supportsScopedConnection(): boolean {\n return shouldUseScopedLocalNetwork(Platform.OS, otaLocalNetwork.isAvailable())\n}\n\nfunction normalizeHeaders(headers?: HeadersInit): Record<string, string> {\n if (!headers) return {}\n if (headers instanceof Headers) {\n const result: Record<string, string> = {}\n headers.forEach((value, key) => {\n result[key] = value\n })\n return result\n }\n if (Array.isArray(headers)) return Object.fromEntries(headers)\n return {...headers}\n}\n\nfunction requestId(prefix: string): string {\n return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2)}`\n}\n\nexport const localNetworkTransport = {\n supportsScopedConnection: (): boolean => supportsScopedConnection(),\n isScopedConnectionActive: (): boolean => scopedConnectionActive,\n\n async connect(\n caller: symbol,\n ssid: string,\n password: string,\n options?: {\n retryIosInternalError?: true\n assertCurrent?: () => void\n gateway?: string\n purpose?: \"outgoing-client\" | \"incoming-server\"\n },\n ): Promise<string | undefined> {\n const isMac = Platform.OS === \"ios\" && CrustModule.isIOSAppOnMac === true\n if (isMac && macHotspotOwner) throw new Error(\"Previous Mac hotspot session has not been released\")\n const generation = ++connectionGeneration\n const assertCurrent = () => {\n if (generation !== connectionGeneration) throw new Error(\"Local network connection was superseded\")\n options?.assertCurrent?.()\n }\n assertCurrent()\n scopedConnectionActive = false\n nativeJobs.clear()\n if (isMac) {\n const owner = requestId(\"mac_hotspot\")\n macHotspotOwner = {caller, nativeId: owner}\n try {\n const address = await glassesHotspot.join(\n owner,\n ssid,\n password,\n options?.gateway,\n options?.purpose ?? \"outgoing-client\",\n )\n assertCurrent()\n return address\n } catch (error) {\n try {\n await glassesHotspot.leave(owner)\n } catch (cleanupError) {\n console.warn(\"[LocalNetworkTransport] Mac hotspot cleanup failed\", localNetworkErrorDetails(cleanupError))\n throw error\n }\n if (macHotspotOwner?.nativeId === owner) macHotspotOwner = null\n throw error\n }\n }\n if (!supportsScopedConnection()) {\n // Gallery already owns its retry loop. OTA opts into this same-network\n // policy only with current-attempt authority; never race a pending native call.\n const retryDeadline = Date.now() + 30_000\n for (let attempt = 1; ; attempt += 1) {\n assertCurrent()\n try {\n await WifiManager.connectToProtectedSSID(ssid, password, false, false)\n // Report acquisition first; the caller records it before its own\n // identity check and normal teardown of a replaced OTA attempt.\n return undefined\n } catch (error) {\n assertCurrent()\n const details = localNetworkErrorDetails(error)\n console.warn(\"[LocalNetworkTransport] hotspot join rejected\", {attempt, ...details})\n if (\n !options?.retryIosInternalError ||\n Platform.OS !== \"ios\" ||\n attempt >= 3 ||\n details.native?.domain !== \"NEHotspotConfigurationErrorDomain\" ||\n details.native.code !== 8 ||\n Date.now() + 3_000 > retryDeadline\n )\n throw error\n await new Promise<void>((resolve) => BgTimer.setTimeout(resolve, 3_000))\n assertCurrent()\n if (Date.now() > retryDeadline) throw error\n }\n }\n }\n const result = await otaLocalNetwork.connect(ssid, password)\n scopedConnectionActive = true\n return result.localAddress\n },\n\n async disconnect(caller: symbol, waitForInternet = false): Promise<void> {\n if (macHotspotOwner && macHotspotOwner.caller !== caller) return\n connectionGeneration += 1\n if (macHotspotOwner) {\n const owner = macHotspotOwner.nativeId\n await glassesHotspot.leave(owner, waitForInternet)\n if (macHotspotOwner?.nativeId === owner) macHotspotOwner = null\n }\n if (supportsScopedConnection()) {\n await otaLocalNetwork.disconnect()\n }\n scopedConnectionActive = false\n nativeJobs.clear()\n },\n\n async fetch(url: string | URL | Request, init?: RequestInit, timeoutMs = 30_000): Promise<Response> {\n if (!scopedConnectionActive || !otaLocalNetwork.isAvailable() || typeof url !== \"string\") {\n return globalThis.fetch(url, init)\n }\n\n const nativeModule = otaLocalNetwork\n const id = requestId(\"request\")\n const signal = init?.signal\n const cancel = () => void nativeModule.cancel(id)\n if (signal?.aborted) throw new Error(\"Request aborted\")\n signal?.addEventListener(\"abort\", cancel, {once: true})\n try {\n const result = await nativeModule.request(\n id,\n url,\n init?.method || \"GET\",\n normalizeHeaders(init?.headers),\n typeof init?.body === \"string\" ? init.body : null,\n timeoutMs,\n )\n const bytes = Buffer.from(result.bodyBase64, \"base64\")\n return new Response(bytes as unknown as BodyInit, {\n status: result.status,\n headers: result.headers,\n })\n } finally {\n signal?.removeEventListener(\"abort\", cancel)\n }\n },\n\n downloadFile(options: DownloadOptions): DownloadHandle {\n if (!scopedConnectionActive || !otaLocalNetwork.isAvailable()) return RNFS.downloadFile(options)\n\n const jobId = nextJobId++\n const id = requestId(\"download\")\n let began = false\n nativeJobs.set(jobId, id)\n const subscription = otaLocalNetwork.onDownloadProgress((event: OtaLocalNetworkDownloadProgress) => {\n if (event.requestId !== id) return\n if (!began) {\n began = true\n options.begin?.({\n jobId,\n statusCode: event.statusCode || 200,\n contentLength: event.contentLength,\n headers: event.headers || {},\n })\n }\n options.progress?.({\n jobId,\n contentLength: event.contentLength,\n bytesWritten: event.bytesWritten,\n })\n })\n\n const promise = otaLocalNetwork\n .download(\n id,\n options.fromUrl,\n options.toFile,\n options.headers || {},\n options.connectionTimeout || 30_000,\n options.readTimeout || 30_000,\n )\n .then((result) => {\n if (!began) {\n options.begin?.({\n jobId,\n statusCode: result.statusCode,\n contentLength: result.bytesWritten,\n headers: result.headers,\n })\n }\n return {\n jobId,\n statusCode: result.statusCode,\n bytesWritten: result.bytesWritten,\n }\n })\n .catch((error) => {\n if (cancelledNativeJobs.has(jobId)) throw new Error(\"Sync cancelled\")\n throw error\n })\n .finally(() => {\n nativeJobs.delete(jobId)\n cancelledNativeJobs.delete(jobId)\n subscription.remove()\n })\n\n return {jobId, promise} as DownloadHandle\n },\n\n stopDownload(jobId: number): void {\n const nativeId = nativeJobs.get(jobId)\n if (nativeId && otaLocalNetwork.isAvailable()) {\n cancelledNativeJobs.add(jobId)\n void otaLocalNetwork.cancel(nativeId)\n return\n }\n RNFS.stopDownload(jobId)\n },\n}\n\notaLocalNetwork.onNetworkLost(() => {\n scopedConnectionActive = false\n nativeJobs.clear()\n})\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mentra/engine",
3
- "version": "3.4.0-dev.950",
3
+ "version": "3.4.0-dev.953",
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,13 +97,13 @@
97
97
  "registry": "https://registry.npmjs.org/"
98
98
  },
99
99
  "dependencies": {
100
- "@mentra/acs-meeting": "3.4.0-dev.950",
101
- "@mentra/glasses-media": "3.4.0-dev.950",
102
- "@mentra/bluetooth-sdk": "3.4.0-dev.950",
103
- "@mentra/cloud-client": "3.4.0-dev.950",
104
- "@mentra/cloud-protocol": "3.4.0-dev.950",
105
- "@mentra/crust": "3.4.0-dev.950",
106
- "@mentra/miniapp": "3.4.0-dev.950",
100
+ "@mentra/acs-meeting": "3.4.0-dev.953",
101
+ "@mentra/glasses-media": "3.4.0-dev.953",
102
+ "@mentra/bluetooth-sdk": "3.4.0-dev.953",
103
+ "@mentra/cloud-client": "3.4.0-dev.953",
104
+ "@mentra/cloud-protocol": "3.4.0-dev.953",
105
+ "@mentra/crust": "3.4.0-dev.953",
106
+ "@mentra/miniapp": "3.4.0-dev.953",
107
107
  "buffer": "^6.0.3",
108
108
  "events": "^3.3.0",
109
109
  "jszip": "^3.10.1",
@@ -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.4.0",
15
- "releaseIdentity": "3.4.0-dev.950",
16
- "releaseSetId": "mentra-3.4.0-dev.950",
17
- "sourceCommit": "6f46eab024e3d74343690a342b8a4f6700c9f6fd",
18
- "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.4.0/mentra-live-ota-3.4.0-dev.950.json",
19
- "otaManifestSha256": "57c401448f58ce9fba105991f4fd3ddfe0fe4f8ed6e7da35dd49da80b8145b1d"
15
+ "releaseIdentity": "3.4.0-dev.953",
16
+ "releaseSetId": "mentra-3.4.0-dev.953",
17
+ "sourceCommit": "c92cc365b1b592e1c926572eb32c50a48d040943",
18
+ "otaManifestUrl": "https://artifactscdn.mentraglass.com/Mentra-Community/MentraOS/releases/mentra-builds-v3.4.0/mentra-live-ota-3.4.0-dev.953.json",
19
+ "otaManifestSha256": "14e2f5dbe312a0f296b35fc6e87a81e9300bd8ba229f82dfd0ee75e80eb43fe6"
20
20
  })
@@ -257,7 +257,7 @@ class HotspotOtaTransport {
257
257
  }
258
258
  if (this.localNetworkRequested) {
259
259
  try {
260
- await localNetworkTransport.disconnect(this.networkOwner)
260
+ await localNetworkTransport.disconnect(this.networkOwner, true)
261
261
  this.localNetworkRequested = false
262
262
  this.localNetworkConnected = false
263
263
  } catch (error) {
@@ -229,12 +229,12 @@ export const localNetworkTransport = {
229
229
  return result.localAddress
230
230
  },
231
231
 
232
- async disconnect(caller: symbol): Promise<void> {
232
+ async disconnect(caller: symbol, waitForInternet = false): Promise<void> {
233
233
  if (macHotspotOwner && macHotspotOwner.caller !== caller) return
234
234
  connectionGeneration += 1
235
235
  if (macHotspotOwner) {
236
236
  const owner = macHotspotOwner.nativeId
237
- await glassesHotspot.leave(owner)
237
+ await glassesHotspot.leave(owner, waitForInternet)
238
238
  if (macHotspotOwner?.nativeId === owner) macHotspotOwner = null
239
239
  }
240
240
  if (supportsScopedConnection()) {