@mentra/engine 0.1.0-beta.0 → 0.1.0-dev.1
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.
- package/README.md +42 -1
- package/build/engine.d.ts +11 -3
- package/build/engine.d.ts.map +1 -1
- package/build/engine.js +7 -2
- package/build/engine.js.map +1 -1
- package/build/facades/dev.d.ts.map +1 -1
- package/build/facades/dev.js +9 -5
- package/build/facades/dev.js.map +1 -1
- package/build/facades/gallery.js +1 -1
- package/build/facades/gallery.js.map +1 -1
- package/build/facades/glasses.d.ts +1 -0
- package/build/facades/glasses.d.ts.map +1 -1
- package/build/facades/glasses.js +19 -4
- package/build/facades/glasses.js.map +1 -1
- package/build/facades/glassesSettings.d.ts.map +1 -1
- package/build/facades/glassesSettings.js +1 -0
- package/build/facades/glassesSettings.js.map +1 -1
- package/build/facades/miniapps.d.ts +4 -0
- package/build/facades/miniapps.d.ts.map +1 -1
- package/build/facades/miniapps.js +5 -0
- package/build/facades/miniapps.js.map +1 -1
- package/build/facades/ota.d.ts +11 -2
- package/build/facades/ota.d.ts.map +1 -1
- package/build/facades/ota.js +19 -4
- package/build/facades/ota.js.map +1 -1
- package/build/facades/pairing.d.ts +4 -0
- package/build/facades/pairing.d.ts.map +1 -1
- package/build/facades/pairing.js +10 -8
- package/build/facades/pairing.js.map +1 -1
- package/build/facades/phoneNotifications.d.ts +0 -4
- package/build/facades/phoneNotifications.d.ts.map +1 -1
- package/build/facades/phoneNotifications.js +4 -14
- package/build/facades/phoneNotifications.js.map +1 -1
- package/build/index.d.ts +6 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +4 -2
- package/build/index.js.map +1 -1
- package/build/internal.d.ts +2 -2
- package/build/internal.d.ts.map +1 -1
- package/build/internal.js +1 -1
- package/build/internal.js.map +1 -1
- package/build/react/MentraLiveOtaFlow.d.ts +38 -0
- package/build/react/MentraLiveOtaFlow.d.ts.map +1 -0
- package/build/react/MentraLiveOtaFlow.js +528 -0
- package/build/react/MentraLiveOtaFlow.js.map +1 -0
- package/build/react/index.d.ts +2 -0
- package/build/react/index.d.ts.map +1 -0
- package/build/react/index.js +2 -0
- package/build/react/index.js.map +1 -0
- package/build/react/useEngineSnapshot.d.ts +2 -0
- package/build/react/useEngineSnapshot.d.ts.map +1 -0
- package/build/react/useEngineSnapshot.js +14 -0
- package/build/react/useEngineSnapshot.js.map +1 -0
- package/build/runtime/bootstrap.d.ts +24 -1
- package/build/runtime/bootstrap.d.ts.map +1 -1
- package/build/runtime/bootstrap.js +17 -0
- package/build/runtime/bootstrap.js.map +1 -1
- package/build/runtime/scanQrSeam.d.ts +7 -0
- package/build/runtime/scanQrSeam.d.ts.map +1 -0
- package/build/runtime/scanQrSeam.js +16 -0
- package/build/runtime/scanQrSeam.js.map +1 -0
- package/build/services/AppRegistry.d.ts +18 -8
- package/build/services/AppRegistry.d.ts.map +1 -1
- package/build/services/AppRegistry.js +44 -45
- package/build/services/AppRegistry.js.map +1 -1
- package/build/services/AudioCloudUplink.d.ts +9 -3
- package/build/services/AudioCloudUplink.d.ts.map +1 -1
- package/build/services/AudioCloudUplink.js +9 -3
- package/build/services/AudioCloudUplink.js.map +1 -1
- package/build/services/AudioPlaybackService.d.ts +9 -1
- package/build/services/AudioPlaybackService.d.ts.map +1 -1
- package/build/services/AudioPlaybackService.js +77 -32
- package/build/services/AudioPlaybackService.js.map +1 -1
- package/build/services/BlobStore.d.ts +2 -1
- package/build/services/BlobStore.d.ts.map +1 -1
- package/build/services/BlobStore.js +17 -9
- package/build/services/BlobStore.js.map +1 -1
- package/build/services/CloudAudioSubscriptionSync.d.ts.map +1 -1
- package/build/services/CloudAudioSubscriptionSync.js +13 -1
- package/build/services/CloudAudioSubscriptionSync.js.map +1 -1
- package/build/services/CloudClientService.d.ts +15 -0
- package/build/services/CloudClientService.d.ts.map +1 -1
- package/build/services/CloudClientService.js +75 -0
- package/build/services/CloudClientService.js.map +1 -1
- package/build/services/ForegroundLocationPermission.d.ts +13 -0
- package/build/services/ForegroundLocationPermission.d.ts.map +1 -0
- package/build/services/ForegroundLocationPermission.js +12 -0
- package/build/services/ForegroundLocationPermission.js.map +1 -0
- package/build/services/GlassesSettingsSync.d.ts.map +1 -1
- package/build/services/GlassesSettingsSync.js +9 -3
- package/build/services/GlassesSettingsSync.js.map +1 -1
- package/build/services/GlassesStatusProjection.d.ts +2 -1
- package/build/services/GlassesStatusProjection.d.ts.map +1 -1
- package/build/services/GlassesStatusProjection.js +15 -8
- package/build/services/GlassesStatusProjection.js.map +1 -1
- package/build/services/HotspotOtaTransport.d.ts +29 -0
- package/build/services/HotspotOtaTransport.d.ts.map +1 -0
- package/build/services/HotspotOtaTransport.js +146 -0
- package/build/services/HotspotOtaTransport.js.map +1 -0
- package/build/services/HotspotShutdown.d.ts +17 -0
- package/build/services/HotspotShutdown.d.ts.map +1 -0
- package/build/services/HotspotShutdown.js +29 -0
- package/build/services/HotspotShutdown.js.map +1 -0
- package/build/services/LocalDisplayManager.d.ts +15 -0
- package/build/services/LocalDisplayManager.d.ts.map +1 -1
- package/build/services/LocalDisplayManager.js +106 -20
- package/build/services/LocalDisplayManager.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts +67 -1
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +486 -126
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/LocalMiniappStorage.d.ts +32 -0
- package/build/services/LocalMiniappStorage.d.ts.map +1 -0
- package/build/services/LocalMiniappStorage.js +66 -0
- package/build/services/LocalMiniappStorage.js.map +1 -0
- package/build/services/LocalMiniappUserIdentity.d.ts +20 -0
- package/build/services/LocalMiniappUserIdentity.d.ts.map +1 -0
- package/build/services/LocalMiniappUserIdentity.js +43 -0
- package/build/services/LocalMiniappUserIdentity.js.map +1 -0
- package/build/services/MicStateCoordinator.d.ts +42 -1
- package/build/services/MicStateCoordinator.d.ts.map +1 -1
- package/build/services/MicStateCoordinator.js +141 -3
- package/build/services/MicStateCoordinator.js.map +1 -1
- package/build/services/MiniappLauncher.d.ts.map +1 -1
- package/build/services/MiniappLauncher.js +23 -3
- package/build/services/MiniappLauncher.js.map +1 -1
- package/build/services/MiniappLiveness.d.ts +12 -0
- package/build/services/MiniappLiveness.d.ts.map +1 -0
- package/build/services/MiniappLiveness.js +16 -0
- package/build/services/MiniappLiveness.js.map +1 -0
- package/build/services/OtaArtifactDownloader.d.ts +65 -0
- package/build/services/OtaArtifactDownloader.d.ts.map +1 -0
- package/build/services/OtaArtifactDownloader.js +226 -0
- package/build/services/OtaArtifactDownloader.js.map +1 -0
- package/build/services/OtaAutoChain.d.ts +34 -0
- package/build/services/OtaAutoChain.d.ts.map +1 -0
- package/build/services/OtaAutoChain.js +83 -0
- package/build/services/OtaAutoChain.js.map +1 -0
- package/build/services/OtaErrorMapping.d.ts +18 -0
- package/build/services/OtaErrorMapping.d.ts.map +1 -0
- package/build/services/OtaErrorMapping.js +63 -0
- package/build/services/OtaErrorMapping.js.map +1 -0
- package/build/services/OtaInstallCoordinator.d.ts +94 -14
- package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
- package/build/services/OtaInstallCoordinator.js +574 -130
- package/build/services/OtaInstallCoordinator.js.map +1 -1
- package/build/services/OtaService.d.ts.map +1 -1
- package/build/services/OtaService.js +8 -1
- package/build/services/OtaService.js.map +1 -1
- package/build/services/OtaUpdateCheckService.d.ts +38 -3
- package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
- package/build/services/OtaUpdateCheckService.js +142 -22
- package/build/services/OtaUpdateCheckService.js.map +1 -1
- package/build/services/PhoneCalendarService.d.ts.map +1 -1
- package/build/services/PhoneCalendarService.js +22 -1
- package/build/services/PhoneCalendarService.js.map +1 -1
- package/build/services/PhoneCameraFovCoordinator.d.ts +2 -0
- package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -1
- package/build/services/PhoneCameraFovCoordinator.js +14 -0
- package/build/services/PhoneCameraFovCoordinator.js.map +1 -1
- package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
- package/build/services/PhoneNotificationsSync.js +12 -10
- package/build/services/PhoneNotificationsSync.js.map +1 -1
- package/build/services/PhonePhotoCoordinator.d.ts +10 -3
- package/build/services/PhonePhotoCoordinator.d.ts.map +1 -1
- package/build/services/PhonePhotoCoordinator.js +21 -3
- package/build/services/PhonePhotoCoordinator.js.map +1 -1
- package/build/services/PhoneStreamCoordinator.d.ts +8 -1
- package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
- package/build/services/PhoneStreamCoordinator.js +125 -13
- package/build/services/PhoneStreamCoordinator.js.map +1 -1
- package/build/services/PhoneVideoCoordinator.d.ts +2 -0
- package/build/services/PhoneVideoCoordinator.d.ts.map +1 -1
- package/build/services/PhoneVideoCoordinator.js +10 -0
- package/build/services/PhoneVideoCoordinator.js.map +1 -1
- package/build/services/SceneRenderer.d.ts.map +1 -1
- package/build/services/SceneRenderer.js +15 -0
- package/build/services/SceneRenderer.js.map +1 -1
- package/build/services/SupportProfileSync.d.ts +22 -0
- package/build/services/SupportProfileSync.d.ts.map +1 -0
- package/build/services/SupportProfileSync.js +213 -0
- package/build/services/SupportProfileSync.js.map +1 -0
- package/build/services/TtsTextSanitizer.d.ts +5 -0
- package/build/services/TtsTextSanitizer.d.ts.map +1 -0
- package/build/services/TtsTextSanitizer.js +61 -0
- package/build/services/TtsTextSanitizer.js.map +1 -0
- package/build/services/WifiAdbRequest.d.ts +17 -0
- package/build/services/WifiAdbRequest.d.ts.map +1 -0
- package/build/services/WifiAdbRequest.js +35 -0
- package/build/services/WifiAdbRequest.js.map +1 -0
- package/build/services/asg/asgCameraApi.d.ts +3 -0
- package/build/services/asg/asgCameraApi.d.ts.map +1 -1
- package/build/services/asg/asgCameraApi.js +72 -2
- package/build/services/asg/asgCameraApi.js.map +1 -1
- package/build/services/asg/gallerySyncService.d.ts.map +1 -1
- package/build/services/asg/gallerySyncService.js +26 -14
- package/build/services/asg/gallerySyncService.js.map +1 -1
- package/build/services/asg/localNetworkTransport.d.ts +2 -2
- package/build/services/asg/localNetworkTransport.d.ts.map +1 -1
- package/build/services/asg/localNetworkTransport.js +6 -6
- package/build/services/asg/localNetworkTransport.js.map +1 -1
- package/build/services/audioPlaybackAssets.d.ts +8 -0
- package/build/services/audioPlaybackAssets.d.ts.map +1 -0
- package/build/services/audioPlaybackAssets.js +7 -0
- package/build/services/audioPlaybackAssets.js.map +1 -0
- package/build/services/glassesClockSync.js +2 -2
- package/build/services/glassesClockSync.js.map +1 -1
- package/build/services/manifestActions.d.ts +7 -0
- package/build/services/manifestActions.d.ts.map +1 -0
- package/build/services/manifestActions.js +25 -0
- package/build/services/manifestActions.js.map +1 -0
- package/build/services/otaDisplayState.d.ts +22 -11
- package/build/services/otaDisplayState.d.ts.map +1 -1
- package/build/services/otaDisplayState.js +36 -14
- package/build/services/otaDisplayState.js.map +1 -1
- package/build/services/otaInstallPolicy.d.ts +15 -3
- package/build/services/otaInstallPolicy.d.ts.map +1 -1
- package/build/services/otaInstallPolicy.js +24 -3
- package/build/services/otaInstallPolicy.js.map +1 -1
- package/build/services/otaManifestUrl.d.ts +2 -0
- package/build/services/otaManifestUrl.d.ts.map +1 -0
- package/build/services/{asgOtaVersionUrl.js → otaManifestUrl.js} +15 -5
- package/build/services/otaManifestUrl.js.map +1 -0
- package/build/services/slimStreamStatus.d.ts +11 -0
- package/build/services/slimStreamStatus.d.ts.map +1 -1
- package/build/services/slimStreamStatus.js +14 -4
- package/build/services/slimStreamStatus.js.map +1 -1
- package/build/stores/apps.d.ts.map +1 -1
- package/build/stores/apps.js +11 -0
- package/build/stores/apps.js.map +1 -1
- package/build/stores/bluetoothSettingKeys.d.ts.map +1 -1
- package/build/stores/bluetoothSettingKeys.js +2 -0
- package/build/stores/bluetoothSettingKeys.js.map +1 -1
- package/build/stores/gallerySync.d.ts +2 -0
- package/build/stores/gallerySync.d.ts.map +1 -1
- package/build/stores/gallerySync.js +2 -0
- package/build/stores/gallerySync.js.map +1 -1
- package/build/stores/glasses.d.ts.map +1 -1
- package/build/stores/glasses.js +3 -0
- package/build/stores/glasses.js.map +1 -1
- package/build/stores/settings.d.ts +17 -0
- package/build/stores/settings.d.ts.map +1 -1
- package/build/stores/settings.js +152 -19
- package/build/stores/settings.js.map +1 -1
- package/build/types/applet.d.ts +2 -0
- package/build/types/applet.d.ts.map +1 -1
- package/build/types/applet.js.map +1 -1
- package/build/types/enums.d.ts +1 -0
- package/build/types/enums.d.ts.map +1 -1
- package/build/types/enums.js +1 -0
- package/build/types/enums.js.map +1 -1
- package/build/types/hardware.d.ts +1 -0
- package/build/types/hardware.d.ts.map +1 -1
- package/build/types/hardware.js +14 -0
- package/build/types/hardware.js.map +1 -1
- package/build/utils/configuredDevHost.d.ts +6 -0
- package/build/utils/configuredDevHost.d.ts.map +1 -0
- package/build/utils/configuredDevHost.js +19 -0
- package/build/utils/configuredDevHost.js.map +1 -0
- package/build/utils/devMiniappLaunch.d.ts +19 -8
- package/build/utils/devMiniappLaunch.d.ts.map +1 -1
- package/build/utils/devMiniappLaunch.js +144 -21
- package/build/utils/devMiniappLaunch.js.map +1 -1
- package/build/utils/diagnosticContext.d.ts.map +1 -1
- package/build/utils/diagnosticContext.js +15 -17
- package/build/utils/diagnosticContext.js.map +1 -1
- package/build/utils/hardware/hardware.d.ts.map +1 -1
- package/build/utils/hardware/hardware.js +7 -3
- package/build/utils/hardware/hardware.js.map +1 -1
- package/build/utils/miniappDiagnostics.d.ts +64 -0
- package/build/utils/miniappDiagnostics.d.ts.map +1 -0
- package/build/utils/miniappDiagnostics.js +173 -0
- package/build/utils/miniappDiagnostics.js.map +1 -0
- package/build/utils/timers/timers.d.ts.map +1 -1
- package/build/utils/timers/timers.js +55 -18
- package/build/utils/timers/timers.js.map +1 -1
- package/package.json +27 -18
- package/src/assets/silence.wav +0 -0
- package/src/engine.ts +7 -2
- package/src/facades/dev.ts +9 -5
- package/src/facades/gallery.ts +1 -1
- package/src/facades/glasses.ts +17 -4
- package/src/facades/glassesSettings.ts +5 -0
- package/src/facades/miniapps.ts +7 -0
- package/src/facades/ota.ts +19 -4
- package/src/facades/pairing.ts +11 -7
- package/src/facades/phoneNotifications.ts +4 -13
- package/src/index.ts +26 -2
- package/src/internal.ts +2 -1
- package/src/react/MentraLiveOtaFlow.tsx +856 -0
- package/src/react/index.ts +7 -0
- package/src/react/useEngineSnapshot.ts +16 -0
- package/src/runtime/bootstrap.ts +33 -1
- package/src/runtime/scanQrSeam.ts +20 -0
- package/src/services/AppRegistry.ts +72 -48
- package/src/services/AudioCloudUplink.ts +9 -3
- package/src/services/AudioPlaybackService.ts +94 -34
- package/src/services/BlobStore.ts +22 -9
- package/src/services/CloudAudioSubscriptionSync.ts +13 -1
- package/src/services/CloudClientService.ts +74 -0
- package/src/services/ForegroundLocationPermission.ts +24 -0
- package/src/services/GlassesSettingsSync.ts +9 -3
- package/src/services/GlassesStatusProjection.ts +16 -8
- package/src/services/HotspotOtaTransport.ts +184 -0
- package/src/services/HotspotShutdown.ts +41 -0
- package/src/services/LocalDisplayManager.ts +112 -21
- package/src/services/LocalMiniappRuntime.ts +576 -130
- package/src/services/LocalMiniappStorage.ts +82 -0
- package/src/services/LocalMiniappUserIdentity.ts +46 -0
- package/src/services/MicStateCoordinator.ts +169 -4
- package/src/services/MiniappLauncher.ts +30 -3
- package/src/services/MiniappLiveness.ts +24 -0
- package/src/services/OtaArtifactDownloader.ts +312 -0
- package/src/services/OtaAutoChain.ts +106 -0
- package/src/services/OtaErrorMapping.ts +80 -0
- package/src/services/OtaInstallCoordinator.ts +645 -143
- package/src/services/OtaService.ts +11 -5
- package/src/services/OtaUpdateCheckService.ts +180 -20
- package/src/services/PhoneCalendarService.ts +27 -4
- package/src/services/PhoneCameraFovCoordinator.ts +15 -0
- package/src/services/PhoneNotificationsSync.ts +12 -10
- package/src/services/PhonePhotoCoordinator.ts +33 -7
- package/src/services/PhoneStreamCoordinator.ts +139 -25
- package/src/services/PhoneVideoCoordinator.ts +11 -0
- package/src/services/SceneRenderer.ts +16 -0
- package/src/services/SupportProfileSync.ts +218 -0
- package/src/services/TtsTextSanitizer.ts +66 -0
- package/src/services/WifiAdbRequest.ts +53 -0
- package/src/services/asg/asgCameraApi.ts +99 -8
- package/src/services/asg/gallerySyncService.ts +28 -19
- package/src/services/asg/localNetworkTransport.ts +7 -11
- package/src/services/audioPlaybackAssets.ts +8 -0
- package/src/services/glassesClockSync.ts +2 -2
- package/src/services/manifestActions.ts +30 -0
- package/src/services/otaDisplayState.ts +57 -16
- package/src/services/otaInstallPolicy.ts +29 -3
- package/src/services/{asgOtaVersionUrl.ts → otaManifestUrl.ts} +16 -4
- package/src/services/slimStreamStatus.ts +16 -5
- package/src/stores/apps.ts +12 -0
- package/src/stores/bluetoothSettingKeys.ts +2 -0
- package/src/stores/gallerySync.ts +4 -0
- package/src/stores/glasses.ts +3 -0
- package/src/stores/settings.ts +174 -21
- package/src/types/applet.ts +2 -0
- package/src/types/enums.ts +2 -1
- package/src/types/hardware.ts +17 -0
- package/src/utils/configuredDevHost.ts +17 -0
- package/src/utils/devMiniappLaunch.ts +151 -23
- package/src/utils/diagnosticContext.ts +17 -17
- package/src/utils/hardware/hardware.ts +7 -9
- package/src/utils/miniappDiagnostics.ts +226 -0
- package/src/utils/timers/timers.ts +57 -21
- package/build/services/asgOtaVersionUrl.d.ts +0 -2
- package/build/services/asgOtaVersionUrl.d.ts.map +0 -1
- package/build/services/asgOtaVersionUrl.js.map +0 -1
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
const MAX_DIAGNOSTIC_STRING_LENGTH = 512;
|
|
2
|
+
const MAX_DIAGNOSTIC_LIST_ITEMS = 100;
|
|
3
|
+
const MAX_RECENT_MINIAPPS = 20;
|
|
4
|
+
function boundedString(value) {
|
|
5
|
+
if (typeof value !== "string")
|
|
6
|
+
return undefined;
|
|
7
|
+
const trimmed = value.trim();
|
|
8
|
+
if (!trimmed)
|
|
9
|
+
return undefined;
|
|
10
|
+
return trimmed.slice(0, MAX_DIAGNOSTIC_STRING_LENGTH);
|
|
11
|
+
}
|
|
12
|
+
function recordValue(value) {
|
|
13
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
14
|
+
}
|
|
15
|
+
function diagnosticPermissions(value) {
|
|
16
|
+
if (!Array.isArray(value))
|
|
17
|
+
return [];
|
|
18
|
+
const permissions = [];
|
|
19
|
+
for (const raw of value) {
|
|
20
|
+
if (typeof raw === "string") {
|
|
21
|
+
const type = boundedString(raw);
|
|
22
|
+
if (type)
|
|
23
|
+
permissions.push({ type });
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const permission = recordValue(raw);
|
|
27
|
+
const type = boundedString(permission?.type);
|
|
28
|
+
if (!type)
|
|
29
|
+
continue;
|
|
30
|
+
permissions.push({
|
|
31
|
+
type,
|
|
32
|
+
...(typeof permission?.required === "boolean" ? { required: permission.required } : {}),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return permissions.slice(0, MAX_DIAGNOSTIC_LIST_ITEMS);
|
|
36
|
+
}
|
|
37
|
+
function diagnosticHardwareRequirements(value) {
|
|
38
|
+
if (!Array.isArray(value))
|
|
39
|
+
return [];
|
|
40
|
+
const requirements = [];
|
|
41
|
+
for (const raw of value) {
|
|
42
|
+
const requirement = recordValue(raw);
|
|
43
|
+
const type = boundedString(requirement?.type);
|
|
44
|
+
const level = boundedString(requirement?.level);
|
|
45
|
+
if (type && level)
|
|
46
|
+
requirements.push({ type, level });
|
|
47
|
+
}
|
|
48
|
+
return requirements.slice(0, MAX_DIAGNOSTIC_LIST_ITEMS);
|
|
49
|
+
}
|
|
50
|
+
function diagnosticActionIds(value) {
|
|
51
|
+
if (!Array.isArray(value))
|
|
52
|
+
return [];
|
|
53
|
+
return value
|
|
54
|
+
.map((raw) => boundedString(typeof raw === "string" ? raw : recordValue(raw)?.id))
|
|
55
|
+
.filter((id) => id !== undefined)
|
|
56
|
+
.sort()
|
|
57
|
+
.slice(0, MAX_DIAGNOSTIC_LIST_ITEMS);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Keep the routing/build fields from miniapp.json while excluding arbitrary
|
|
61
|
+
* free-form manifest content from reports. Descriptions, URLs, and unknown
|
|
62
|
+
* extension fields are intentionally omitted.
|
|
63
|
+
*/
|
|
64
|
+
export function buildMiniappManifestSnapshot(raw, fallback) {
|
|
65
|
+
const manifest = recordValue(raw);
|
|
66
|
+
const entry = recordValue(manifest?.entry);
|
|
67
|
+
const packageName = boundedString(manifest?.packageName) ?? boundedString(fallback.packageName) ?? "unknown";
|
|
68
|
+
const name = boundedString(manifest?.name) ?? boundedString(fallback.name);
|
|
69
|
+
const version = boundedString(manifest?.version) ?? boundedString(fallback.version);
|
|
70
|
+
const type = boundedString(manifest?.type) ?? boundedString(fallback.type);
|
|
71
|
+
const background = boundedString(entry?.background);
|
|
72
|
+
const ui = boundedString(entry?.ui);
|
|
73
|
+
return {
|
|
74
|
+
packageName,
|
|
75
|
+
...(name ? { name } : {}),
|
|
76
|
+
...(version ? { version } : {}),
|
|
77
|
+
...(boundedString(manifest?.sdkVersion) ? { sdkVersion: boundedString(manifest?.sdkVersion) } : {}),
|
|
78
|
+
...(boundedString(manifest?.minHostVersion) ? { minHostVersion: boundedString(manifest?.minHostVersion) } : {}),
|
|
79
|
+
...(type ? { type } : {}),
|
|
80
|
+
...(background || ui ? { entry: { ...(background ? { background } : {}), ...(ui ? { ui } : {}) } } : {}),
|
|
81
|
+
permissions: diagnosticPermissions(manifest?.permissions),
|
|
82
|
+
hardwareRequirements: diagnosticHardwareRequirements(manifest?.hardwareRequirements),
|
|
83
|
+
actionIds: diagnosticActionIds(manifest?.actions ?? manifest?.actionIds),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function executionMode(app) {
|
|
87
|
+
if (app.offline)
|
|
88
|
+
return "built_in";
|
|
89
|
+
if (app.isMiniappDev && app.devUrl && !app.version)
|
|
90
|
+
return "dev_server";
|
|
91
|
+
if (app.isMiniappDev)
|
|
92
|
+
return "dev_snapshot";
|
|
93
|
+
return "installed_bundle";
|
|
94
|
+
}
|
|
95
|
+
function safeReleaseIdentity(value) {
|
|
96
|
+
const identity = recordValue(value);
|
|
97
|
+
if (!identity)
|
|
98
|
+
return undefined;
|
|
99
|
+
const out = {};
|
|
100
|
+
for (const key of ["source", "releaseId", "bundleSha256", "channel"]) {
|
|
101
|
+
const field = boundedString(identity[key]);
|
|
102
|
+
if (field)
|
|
103
|
+
out[key] = field;
|
|
104
|
+
}
|
|
105
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
106
|
+
}
|
|
107
|
+
export function buildMiniappDiagnosticContext(input) {
|
|
108
|
+
const runtimeByPackage = new Map(input.runtime.connectedApps.map((app) => [app.packageName, app]));
|
|
109
|
+
const appSnapshots = input.apps.map((app) => {
|
|
110
|
+
const lastOpenedAtMs = input.getLastOpenedAtMs(app);
|
|
111
|
+
const packageName = boundedString(app.packageName) ?? "unknown";
|
|
112
|
+
return {
|
|
113
|
+
packageName,
|
|
114
|
+
name: boundedString(app.name) ?? packageName,
|
|
115
|
+
version: boundedString(app.version) ?? null,
|
|
116
|
+
executionMode: executionMode(app),
|
|
117
|
+
running: app.running,
|
|
118
|
+
foregrounded: app.packageName === input.foregroundedPackage,
|
|
119
|
+
loading: app.loading,
|
|
120
|
+
healthy: app.healthy,
|
|
121
|
+
hidden: app.hidden,
|
|
122
|
+
type: app.type,
|
|
123
|
+
offline: app.offline,
|
|
124
|
+
local: app.local,
|
|
125
|
+
lastOpenedAtMs: Number.isFinite(lastOpenedAtMs) ? lastOpenedAtMs : 0,
|
|
126
|
+
};
|
|
127
|
+
});
|
|
128
|
+
const recentlyInteracted = [...appSnapshots]
|
|
129
|
+
.filter((app) => app.lastOpenedAtMs > 0)
|
|
130
|
+
.sort((a, b) => b.lastOpenedAtMs - a.lastOpenedAtMs)
|
|
131
|
+
.slice(0, MAX_RECENT_MINIAPPS)
|
|
132
|
+
.map((app) => ({ packageName: app.packageName, lastOpenedAtMs: app.lastOpenedAtMs }));
|
|
133
|
+
const runningMiniapps = input.apps
|
|
134
|
+
.filter((app) => app.running)
|
|
135
|
+
.map((app) => {
|
|
136
|
+
const runtime = runtimeByPackage.get(app.packageName);
|
|
137
|
+
const releaseIdentity = safeReleaseIdentity(input.getReleaseIdentity(app));
|
|
138
|
+
const packageName = boundedString(app.packageName) ?? "unknown";
|
|
139
|
+
const manifest = buildMiniappManifestSnapshot(input.getManifest(app) ?? runtime?.manifest, {
|
|
140
|
+
packageName,
|
|
141
|
+
name: app.name,
|
|
142
|
+
version: app.version,
|
|
143
|
+
type: app.type,
|
|
144
|
+
});
|
|
145
|
+
return {
|
|
146
|
+
packageName,
|
|
147
|
+
version: boundedString(app.version) ?? manifest.version ?? null,
|
|
148
|
+
executionMode: executionMode(app),
|
|
149
|
+
foregrounded: app.packageName === input.foregroundedPackage,
|
|
150
|
+
manifest,
|
|
151
|
+
...(releaseIdentity ? { releaseIdentity } : {}),
|
|
152
|
+
runtime: runtime
|
|
153
|
+
? {
|
|
154
|
+
handshakeComplete: runtime.handshakeComplete,
|
|
155
|
+
subscriptions: runtime.subscriptions,
|
|
156
|
+
lastMessageAgeMs: runtime.lastMessageAgeMs,
|
|
157
|
+
requestedLocationRate: runtime.requestedLocationRate,
|
|
158
|
+
hasActiveSpeakerStream: runtime.hasActiveSpeakerStream,
|
|
159
|
+
}
|
|
160
|
+
: null,
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
return {
|
|
164
|
+
apps: appSnapshots,
|
|
165
|
+
installed: appSnapshots.map((app) => app.packageName),
|
|
166
|
+
running: runningMiniapps.map((app) => app.packageName),
|
|
167
|
+
foregroundedPackage: boundedString(input.foregroundedPackage) ?? null,
|
|
168
|
+
mostRecentlyInteractedPackage: recentlyInteracted[0]?.packageName ?? null,
|
|
169
|
+
recentlyInteracted,
|
|
170
|
+
runningMiniapps,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=miniappDiagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"miniappDiagnostics.js","sourceRoot":"","sources":["../../src/utils/miniappDiagnostics.ts"],"names":[],"mappings":"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","sourcesContent":["import type {ClientApp} from \"../types/applet\"\n\nconst MAX_DIAGNOSTIC_STRING_LENGTH = 512\nconst MAX_DIAGNOSTIC_LIST_ITEMS = 100\nconst MAX_RECENT_MINIAPPS = 20\n\nexport interface MiniappManifestSnapshot {\n packageName: string\n name?: string\n version?: string\n sdkVersion?: string\n minHostVersion?: string\n type?: string\n entry?: {\n background?: string\n ui?: string\n }\n permissions: Array<{type: string; required?: boolean}>\n hardwareRequirements: Array<{type: string; level: string}>\n actionIds: string[]\n}\n\nexport interface MiniappRuntimeAppSnapshot {\n packageName: string\n handshakeComplete: boolean\n subscriptions: string[]\n lastMessageAgeMs: number\n requestedLocationRate: string | null\n hasActiveSpeakerStream: boolean\n manifest?: MiniappManifestSnapshot\n}\n\nexport interface MiniappRuntimeDiagnosticSnapshot {\n connectedApps: MiniappRuntimeAppSnapshot[]\n subscriptionsByStream: Record<string, string[]>\n resources: {\n display: Record<string, unknown>\n camera: Record<string, unknown>\n video: Record<string, unknown>\n stream: Record<string, unknown>\n cameraFov: Record<string, unknown>\n }\n}\n\ntype ManifestFallback = {\n packageName: string\n name?: string\n version?: string\n type?: string\n}\n\nfunction boundedString(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined\n const trimmed = value.trim()\n if (!trimmed) return undefined\n return trimmed.slice(0, MAX_DIAGNOSTIC_STRING_LENGTH)\n}\n\nfunction recordValue(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as Record<string, unknown>) : null\n}\n\nfunction diagnosticPermissions(value: unknown): Array<{type: string; required?: boolean}> {\n if (!Array.isArray(value)) return []\n const permissions: Array<{type: string; required?: boolean}> = []\n for (const raw of value) {\n if (typeof raw === \"string\") {\n const type = boundedString(raw)\n if (type) permissions.push({type})\n continue\n }\n const permission = recordValue(raw)\n const type = boundedString(permission?.type)\n if (!type) continue\n permissions.push({\n type,\n ...(typeof permission?.required === \"boolean\" ? {required: permission.required} : {}),\n })\n }\n return permissions.slice(0, MAX_DIAGNOSTIC_LIST_ITEMS)\n}\n\nfunction diagnosticHardwareRequirements(value: unknown): Array<{type: string; level: string}> {\n if (!Array.isArray(value)) return []\n const requirements: Array<{type: string; level: string}> = []\n for (const raw of value) {\n const requirement = recordValue(raw)\n const type = boundedString(requirement?.type)\n const level = boundedString(requirement?.level)\n if (type && level) requirements.push({type, level})\n }\n return requirements.slice(0, MAX_DIAGNOSTIC_LIST_ITEMS)\n}\n\nfunction diagnosticActionIds(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n return value\n .map((raw) => boundedString(typeof raw === \"string\" ? raw : recordValue(raw)?.id))\n .filter((id): id is string => id !== undefined)\n .sort()\n .slice(0, MAX_DIAGNOSTIC_LIST_ITEMS)\n}\n\n/**\n * Keep the routing/build fields from miniapp.json while excluding arbitrary\n * free-form manifest content from reports. Descriptions, URLs, and unknown\n * extension fields are intentionally omitted.\n */\nexport function buildMiniappManifestSnapshot(raw: unknown, fallback: ManifestFallback): MiniappManifestSnapshot {\n const manifest = recordValue(raw)\n const entry = recordValue(manifest?.entry)\n const packageName = boundedString(manifest?.packageName) ?? boundedString(fallback.packageName) ?? \"unknown\"\n const name = boundedString(manifest?.name) ?? boundedString(fallback.name)\n const version = boundedString(manifest?.version) ?? boundedString(fallback.version)\n const type = boundedString(manifest?.type) ?? boundedString(fallback.type)\n const background = boundedString(entry?.background)\n const ui = boundedString(entry?.ui)\n\n return {\n packageName,\n ...(name ? {name} : {}),\n ...(version ? {version} : {}),\n ...(boundedString(manifest?.sdkVersion) ? {sdkVersion: boundedString(manifest?.sdkVersion)} : {}),\n ...(boundedString(manifest?.minHostVersion) ? {minHostVersion: boundedString(manifest?.minHostVersion)} : {}),\n ...(type ? {type} : {}),\n ...(background || ui ? {entry: {...(background ? {background} : {}), ...(ui ? {ui} : {})}} : {}),\n permissions: diagnosticPermissions(manifest?.permissions),\n hardwareRequirements: diagnosticHardwareRequirements(manifest?.hardwareRequirements),\n actionIds: diagnosticActionIds(manifest?.actions ?? manifest?.actionIds),\n }\n}\n\nfunction executionMode(app: ClientApp): \"built_in\" | \"dev_server\" | \"dev_snapshot\" | \"installed_bundle\" {\n if (app.offline) return \"built_in\"\n if (app.isMiniappDev && app.devUrl && !app.version) return \"dev_server\"\n if (app.isMiniappDev) return \"dev_snapshot\"\n return \"installed_bundle\"\n}\n\nfunction safeReleaseIdentity(value: unknown): Record<string, string> | undefined {\n const identity = recordValue(value)\n if (!identity) return undefined\n const out: Record<string, string> = {}\n for (const key of [\"source\", \"releaseId\", \"bundleSha256\", \"channel\"] as const) {\n const field = boundedString(identity[key])\n if (field) out[key] = field\n }\n return Object.keys(out).length > 0 ? out : undefined\n}\n\nexport function buildMiniappDiagnosticContext(input: {\n apps: ClientApp[]\n foregroundedPackage: string | null\n runtime: MiniappRuntimeDiagnosticSnapshot\n getLastOpenedAtMs: (app: ClientApp) => number\n getManifest: (app: ClientApp) => unknown\n getReleaseIdentity: (app: ClientApp) => unknown\n}): Record<string, unknown> {\n const runtimeByPackage = new Map(input.runtime.connectedApps.map((app) => [app.packageName, app]))\n const appSnapshots = input.apps.map((app) => {\n const lastOpenedAtMs = input.getLastOpenedAtMs(app)\n const packageName = boundedString(app.packageName) ?? \"unknown\"\n return {\n packageName,\n name: boundedString(app.name) ?? packageName,\n version: boundedString(app.version) ?? null,\n executionMode: executionMode(app),\n running: app.running,\n foregrounded: app.packageName === input.foregroundedPackage,\n loading: app.loading,\n healthy: app.healthy,\n hidden: app.hidden,\n type: app.type,\n offline: app.offline,\n local: app.local,\n lastOpenedAtMs: Number.isFinite(lastOpenedAtMs) ? lastOpenedAtMs : 0,\n }\n })\n\n const recentlyInteracted = [...appSnapshots]\n .filter((app) => app.lastOpenedAtMs > 0)\n .sort((a, b) => b.lastOpenedAtMs - a.lastOpenedAtMs)\n .slice(0, MAX_RECENT_MINIAPPS)\n .map((app) => ({packageName: app.packageName, lastOpenedAtMs: app.lastOpenedAtMs}))\n\n const runningMiniapps = input.apps\n .filter((app) => app.running)\n .map((app) => {\n const runtime = runtimeByPackage.get(app.packageName)\n const releaseIdentity = safeReleaseIdentity(input.getReleaseIdentity(app))\n const packageName = boundedString(app.packageName) ?? \"unknown\"\n const manifest = buildMiniappManifestSnapshot(input.getManifest(app) ?? runtime?.manifest, {\n packageName,\n name: app.name,\n version: app.version,\n type: app.type,\n })\n return {\n packageName,\n version: boundedString(app.version) ?? manifest.version ?? null,\n executionMode: executionMode(app),\n foregrounded: app.packageName === input.foregroundedPackage,\n manifest,\n ...(releaseIdentity ? {releaseIdentity} : {}),\n runtime: runtime\n ? {\n handshakeComplete: runtime.handshakeComplete,\n subscriptions: runtime.subscriptions,\n lastMessageAgeMs: runtime.lastMessageAgeMs,\n requestedLocationRate: runtime.requestedLocationRate,\n hasActiveSpeakerStream: runtime.hasActiveSpeakerStream,\n }\n : null,\n }\n })\n\n return {\n apps: appSnapshots,\n installed: appSnapshots.map((app) => app.packageName),\n running: runningMiniapps.map((app) => app.packageName),\n foregroundedPackage: boundedString(input.foregroundedPackage) ?? null,\n mostRecentlyInteractedPackage: recentlyInteracted[0]?.packageName ?? null,\n recentlyInteracted,\n runningMiniapps,\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timers.d.ts","sourceRoot":"","sources":["../../../src/utils/timers/timers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"timers.d.ts","sourceRoot":"","sources":["../../../src/utils/timers/timers.ts"],"names":[],"mappings":"AAwHA,qBAAa,OAAO;IAClB,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAO/D,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAO9C,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAO9D,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CAM7C;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAU/G;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAY/G"}
|
|
@@ -1,27 +1,63 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
1
|
+
// BgTimer — background-safe timers for the engine.
|
|
2
|
+
//
|
|
3
|
+
// Everything timing-critical in the engine runs through this class: the
|
|
4
|
+
// miniapp liveness watchdog, display durationMs expiries, boot windows,
|
|
5
|
+
// auth-token refresh. On Android, React Native PAUSES plain JS timers while
|
|
6
|
+
// the app is backgrounded, so those features only keep working in the
|
|
7
|
+
// background when the native implementation (react-native-nitro-bg-timer)
|
|
8
|
+
// is active.
|
|
9
|
+
//
|
|
10
|
+
// Who actually gets native timers:
|
|
11
|
+
// - Android, dev AND release: always attempted — dev must match production
|
|
12
|
+
// background behavior. There is no opt-in/opt-out env var. If the native
|
|
13
|
+
// module is unavailable (a dev client whose binary predates it, or a
|
|
14
|
+
// broken release binary), the failure is LOUD: a console.error with the
|
|
15
|
+
// remediation, plus a blocking dev alert. The JS-timer fallback still
|
|
16
|
+
// engages so foreground behavior keeps working, but backgrounded
|
|
17
|
+
// behavior is broken until the native rebuild — the error says exactly
|
|
18
|
+
// that. (A silent dev fallback previously cost a full debugging day of
|
|
19
|
+
// phantom "zombie miniapp" bugs; see OS-1790.)
|
|
20
|
+
// - iOS: never, dev or prod — the package is disabled pending
|
|
21
|
+
// https://github.com/tconns/react-native-nitro-bg-timer/issues/2. iOS
|
|
22
|
+
// suspends the whole process in background anyway, so background timing
|
|
23
|
+
// there is handled by native per-device queues, not JS timers.
|
|
24
|
+
import { Alert, Platform } from "react-native";
|
|
3
25
|
let nitroTimer;
|
|
4
26
|
let nitroDisabled = false;
|
|
5
|
-
let
|
|
6
|
-
|
|
7
|
-
|
|
27
|
+
let failedLoud = false;
|
|
28
|
+
/**
|
|
29
|
+
* The native background timer is unavailable — say so ONCE, loudly, with the
|
|
30
|
+
* remediation. The JS-timer fallback keeps foreground behavior working, but
|
|
31
|
+
* everything timing-driven freezes while the app is backgrounded, which
|
|
32
|
+
* presents as phantom miniapp bugs (frozen captions, missed wake words,
|
|
33
|
+
* watchdog kills on resume). A quiet warning here has already cost a full
|
|
34
|
+
* debugging day; never downgrade this to console.warn.
|
|
35
|
+
*/
|
|
36
|
+
function failUnavailable(reason) {
|
|
37
|
+
if (failedLoud) {
|
|
8
38
|
return;
|
|
9
39
|
}
|
|
10
|
-
|
|
11
|
-
|
|
40
|
+
failedLoud = true;
|
|
41
|
+
const message = `BgTimer: native background timer unavailable (${reason}). ` +
|
|
42
|
+
"Backgrounded behavior IS BROKEN until you rebuild the Android app: run `bun android`. " +
|
|
43
|
+
"Engine timers and local miniapps (captions, wake words) freeze whenever the app is not foregrounded.";
|
|
44
|
+
console.error(message);
|
|
45
|
+
if (__DEV__) {
|
|
46
|
+
// A stale dev client may ALSO show the library's own require-time red box
|
|
47
|
+
// (bridgeless LogBox surfaces it even though we catch below) — this alert
|
|
48
|
+
// is the actionable one: it names the fix.
|
|
49
|
+
try {
|
|
50
|
+
Alert.alert("Background timers unavailable", message);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
/* Alert not available (tests / headless) — the console.error stands. */
|
|
54
|
+
}
|
|
55
|
+
}
|
|
12
56
|
}
|
|
13
57
|
function getNitroTimer() {
|
|
14
58
|
if (nitroDisabled || Platform.OS !== "android") {
|
|
15
59
|
return null;
|
|
16
60
|
}
|
|
17
|
-
// react-native-nitro-bg-timer calls createHybridObject() at require() time. On dev
|
|
18
|
-
// builds with a stale native binary that throws NPE, React Native still surfaces a
|
|
19
|
-
// red LogBox error even when the exception is caught. Skip nitro in __DEV__ unless
|
|
20
|
-
// explicitly enabled after a native rebuild (bun android).
|
|
21
|
-
if (__DEV__ && process.env.EXPO_PUBLIC_USE_NITRO_BG_TIMER !== "true") {
|
|
22
|
-
warnUnavailable("nitro bg-timer disabled in dev (set EXPO_PUBLIC_USE_NITRO_BG_TIMER=true after native rebuild)");
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
61
|
if (nitroTimer !== undefined) {
|
|
26
62
|
return nitroTimer;
|
|
27
63
|
}
|
|
@@ -29,7 +65,7 @@ function getNitroTimer() {
|
|
|
29
65
|
const { isRuntimeAlive } = require("react-native-nitro-modules");
|
|
30
66
|
if (typeof isRuntimeAlive === "function" && !isRuntimeAlive()) {
|
|
31
67
|
nitroTimer = null;
|
|
32
|
-
|
|
68
|
+
failUnavailable("nitro runtime is not alive");
|
|
33
69
|
return nitroTimer;
|
|
34
70
|
}
|
|
35
71
|
const { BackgroundTimer } = require("react-native-nitro-bg-timer");
|
|
@@ -47,7 +83,7 @@ function getNitroTimer() {
|
|
|
47
83
|
nitroDisabled = true;
|
|
48
84
|
}
|
|
49
85
|
if (!nitroTimer) {
|
|
50
|
-
|
|
86
|
+
failUnavailable("react-native-nitro-bg-timer failed to load");
|
|
51
87
|
}
|
|
52
88
|
return nitroTimer;
|
|
53
89
|
}
|
|
@@ -62,7 +98,8 @@ function withNitro(run, fallback) {
|
|
|
62
98
|
catch (error) {
|
|
63
99
|
nitroDisabled = true;
|
|
64
100
|
nitroTimer = null;
|
|
65
|
-
|
|
101
|
+
failedLoud = false; // a mid-session failure is new information — re-announce
|
|
102
|
+
failUnavailable(`nitro timer call threw: ${String(error)}`);
|
|
66
103
|
return fallback();
|
|
67
104
|
}
|
|
68
105
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timers.js","sourceRoot":"","sources":["../../../src/utils/timers/timers.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"timers.js","sourceRoot":"","sources":["../../../src/utils/timers/timers.ts"],"names":[],"mappings":"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","sourcesContent":["// BgTimer — background-safe timers for the engine.\n//\n// Everything timing-critical in the engine runs through this class: the\n// miniapp liveness watchdog, display durationMs expiries, boot windows,\n// auth-token refresh. On Android, React Native PAUSES plain JS timers while\n// the app is backgrounded, so those features only keep working in the\n// background when the native implementation (react-native-nitro-bg-timer)\n// is active.\n//\n// Who actually gets native timers:\n// - Android, dev AND release: always attempted — dev must match production\n// background behavior. There is no opt-in/opt-out env var. If the native\n// module is unavailable (a dev client whose binary predates it, or a\n// broken release binary), the failure is LOUD: a console.error with the\n// remediation, plus a blocking dev alert. The JS-timer fallback still\n// engages so foreground behavior keeps working, but backgrounded\n// behavior is broken until the native rebuild — the error says exactly\n// that. (A silent dev fallback previously cost a full debugging day of\n// phantom \"zombie miniapp\" bugs; see OS-1790.)\n// - iOS: never, dev or prod — the package is disabled pending\n// https://github.com/tconns/react-native-nitro-bg-timer/issues/2. iOS\n// suspends the whole process in background anyway, so background timing\n// there is handled by native per-device queues, not JS timers.\n\nimport {Alert, Platform} from \"react-native\"\n\ntype NitroTimerApi = {\n setInterval: (callback: () => void, delay: number) => number\n clearInterval: (intervalId: number) => void\n setTimeout: (callback: () => void, delay: number) => number\n clearTimeout: (timeoutId: number) => void\n}\n\nlet nitroTimer: NitroTimerApi | null | undefined\nlet nitroDisabled = false\nlet failedLoud = false\n\n/**\n * The native background timer is unavailable — say so ONCE, loudly, with the\n * remediation. The JS-timer fallback keeps foreground behavior working, but\n * everything timing-driven freezes while the app is backgrounded, which\n * presents as phantom miniapp bugs (frozen captions, missed wake words,\n * watchdog kills on resume). A quiet warning here has already cost a full\n * debugging day; never downgrade this to console.warn.\n */\nfunction failUnavailable(reason: string) {\n if (failedLoud) {\n return\n }\n failedLoud = true\n const message =\n `BgTimer: native background timer unavailable (${reason}). ` +\n \"Backgrounded behavior IS BROKEN until you rebuild the Android app: run `bun android`. \" +\n \"Engine timers and local miniapps (captions, wake words) freeze whenever the app is not foregrounded.\"\n console.error(message)\n if (__DEV__) {\n // A stale dev client may ALSO show the library's own require-time red box\n // (bridgeless LogBox surfaces it even though we catch below) — this alert\n // is the actionable one: it names the fix.\n try {\n Alert.alert(\"Background timers unavailable\", message)\n } catch {\n /* Alert not available (tests / headless) — the console.error stands. */\n }\n }\n}\n\nfunction getNitroTimer(): NitroTimerApi | null {\n if (nitroDisabled || Platform.OS !== \"android\") {\n return null\n }\n\n if (nitroTimer !== undefined) {\n return nitroTimer\n }\n\n try {\n const {isRuntimeAlive} = require(\"react-native-nitro-modules\") as {isRuntimeAlive?: () => boolean}\n if (typeof isRuntimeAlive === \"function\" && !isRuntimeAlive()) {\n nitroTimer = null\n failUnavailable(\"nitro runtime is not alive\")\n return nitroTimer\n }\n\n const {BackgroundTimer} = require(\"react-native-nitro-bg-timer\") as {BackgroundTimer?: NitroTimerApi}\n nitroTimer =\n BackgroundTimer &&\n typeof BackgroundTimer.setTimeout === \"function\" &&\n typeof BackgroundTimer.setInterval === \"function\" &&\n typeof BackgroundTimer.clearTimeout === \"function\" &&\n typeof BackgroundTimer.clearInterval === \"function\"\n ? BackgroundTimer\n : null\n } catch {\n nitroTimer = null\n nitroDisabled = true\n }\n\n if (!nitroTimer) {\n failUnavailable(\"react-native-nitro-bg-timer failed to load\")\n }\n return nitroTimer\n}\n\nfunction withNitro<T>(run: (api: NitroTimerApi) => T, fallback: () => T): T {\n const api = getNitroTimer()\n if (!api) {\n return fallback()\n }\n try {\n return run(api)\n } catch (error) {\n nitroDisabled = true\n nitroTimer = null\n failedLoud = false // a mid-session failure is new information — re-announce\n failUnavailable(`nitro timer call threw: ${String(error)}`)\n return fallback()\n }\n}\n\nexport class BgTimer {\n static setInterval(callback: () => void, delay: number): number {\n return withNitro(\n (api) => api.setInterval(callback, delay),\n () => setInterval(callback, delay) as unknown as number,\n )\n }\n\n static clearInterval(intervalId: number): void {\n withNitro(\n (api) => api.clearInterval(intervalId),\n () => clearInterval(intervalId),\n )\n }\n\n static setTimeout(callback: () => void, delay: number): number {\n return withNitro(\n (api) => api.setTimeout(callback, delay),\n () => setTimeout(callback, delay) as unknown as number,\n )\n }\n\n static clearTimeout(timeoutId: number): void {\n withNitro(\n (api) => api.clearTimeout(timeoutId),\n () => clearTimeout(timeoutId),\n )\n }\n}\n\nexport function throttle<T extends (...args: any[]) => any>(fn: T, ms: number): (...args: Parameters<T>) => void {\n let lastCalled = 0\n\n return (...args: Parameters<T>) => {\n const now = Date.now()\n if (now - lastCalled >= ms) {\n lastCalled = now\n fn(...args)\n }\n }\n}\n\nexport function debounce<T extends (...args: any[]) => any>(fn: T, ms: number): (...args: Parameters<T>) => void {\n let timeoutId: number | null = null\n\n return (...args: Parameters<T>) => {\n if (timeoutId) {\n BgTimer.clearTimeout(timeoutId)\n }\n timeoutId = BgTimer.setTimeout(() => {\n fn(...args)\n timeoutId = null\n }, ms)\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mentra/engine",
|
|
3
|
-
"version": "0.1.0-
|
|
3
|
+
"version": "0.1.0-dev.1",
|
|
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",
|
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
"react-native": "./src/devtools.ts",
|
|
22
22
|
"default": "./build/devtools.js"
|
|
23
23
|
},
|
|
24
|
+
"./ota": {
|
|
25
|
+
"types": "./build/react/index.d.ts",
|
|
26
|
+
"react-native": "./src/react/index.ts",
|
|
27
|
+
"default": "./build/react/index.js"
|
|
28
|
+
},
|
|
24
29
|
"./build/*": null,
|
|
25
30
|
"./src/*": null,
|
|
26
31
|
"./package.json": "./package.json"
|
|
@@ -36,7 +41,7 @@
|
|
|
36
41
|
"build": "expo-module build",
|
|
37
42
|
"clean": "expo-module clean",
|
|
38
43
|
"lint": "expo-module lint",
|
|
39
|
-
"test": "
|
|
44
|
+
"test": "./scripts/test.sh",
|
|
40
45
|
"build:module": "expo-module prepare",
|
|
41
46
|
"prepublishOnly": "expo-module prepublishOnly",
|
|
42
47
|
"expo-module": "expo-module"
|
|
@@ -81,27 +86,31 @@
|
|
|
81
86
|
"typescript": "~5.9.2"
|
|
82
87
|
},
|
|
83
88
|
"peerDependencies": {
|
|
84
|
-
"expo": "
|
|
85
|
-
"expo-modules-core": "
|
|
89
|
+
"expo": "~55.0.24",
|
|
90
|
+
"expo-modules-core": "~55.0.25",
|
|
86
91
|
"react": "*",
|
|
87
92
|
"react-native": "*",
|
|
93
|
+
"react-native-safe-area-context": "*",
|
|
94
|
+
"react-native-svg": "*",
|
|
88
95
|
"react-native-udp": "*",
|
|
89
96
|
"@types/react": "*",
|
|
90
97
|
"react-native-mmkv": "*",
|
|
91
98
|
"react-native-nitro-bg-timer": "*",
|
|
92
99
|
"react-native-nitro-modules": "*",
|
|
93
|
-
"react-native-reanimated": "
|
|
94
|
-
"
|
|
100
|
+
"react-native-reanimated": "4.2.1",
|
|
101
|
+
"react-native-worklets": "0.7.4",
|
|
102
|
+
"expo-file-system": "~55.0.20",
|
|
95
103
|
"react-native-zip-archive": "*",
|
|
96
104
|
"zustand": "*",
|
|
97
|
-
"expo-battery": "
|
|
98
|
-
"expo-audio": "
|
|
99
|
-
"expo-clipboard": "
|
|
100
|
-
"expo-calendar": "
|
|
101
|
-
"expo-constants": "
|
|
102
|
-
"expo-
|
|
103
|
-
"expo-
|
|
104
|
-
"expo-
|
|
105
|
+
"expo-battery": "^55.0.13",
|
|
106
|
+
"expo-audio": "~55.0.14",
|
|
107
|
+
"expo-clipboard": "~55.0.13",
|
|
108
|
+
"expo-calendar": "~55.0.14",
|
|
109
|
+
"expo-constants": "~55.0.16",
|
|
110
|
+
"expo-device": "~55.0.17",
|
|
111
|
+
"expo-location": "~55.1.10",
|
|
112
|
+
"expo-task-manager": "~55.0.16",
|
|
113
|
+
"expo-notifications": "~55.0.23",
|
|
105
114
|
"react-native-share": "*",
|
|
106
115
|
"react-native-localize": "*",
|
|
107
116
|
"react-native-ble-manager": "*",
|
|
@@ -112,9 +121,9 @@
|
|
|
112
121
|
"@craftzdog/react-native-buffer": "*",
|
|
113
122
|
"axios": "*",
|
|
114
123
|
"@mentra/bluetooth-sdk": "*",
|
|
115
|
-
"@mentra/crust": "^0.1.0-
|
|
116
|
-
"@mentra/cloud-client": "^0.1.0-
|
|
117
|
-
"@mentra/miniapp": "^0.3.0-
|
|
118
|
-
"@mentra/cloud-protocol": "^0.1.0-
|
|
124
|
+
"@mentra/crust": "^0.1.0-dev.1",
|
|
125
|
+
"@mentra/cloud-client": "^0.1.0-dev.0",
|
|
126
|
+
"@mentra/miniapp": "^0.3.0-dev.1",
|
|
127
|
+
"@mentra/cloud-protocol": "^0.1.0-dev.0"
|
|
119
128
|
}
|
|
120
129
|
}
|
|
Binary file
|
package/src/engine.ts
CHANGED
|
@@ -8,13 +8,14 @@
|
|
|
8
8
|
* live on the `@mentra/engine/internal` entry (and the debug singletons on
|
|
9
9
|
* `@mentra/engine/devtools`); they shrink as screens move onto `engine.*`.
|
|
10
10
|
*/
|
|
11
|
-
import {configure, start as bootstrapStart, stop as bootstrapStop} from "./runtime/bootstrap"
|
|
11
|
+
import {configure, start as bootstrapStart, stop as bootstrapStop, updateUiSeams} from "./runtime/bootstrap"
|
|
12
12
|
import {cloudClientService} from "./services/CloudClientService"
|
|
13
13
|
import {hydrateDeviceStore, demoteOrphanedDefaultWearable} from "./services/DeviceStoreHydration"
|
|
14
14
|
import {startGlassesSettingsSync, stopGlassesSettingsSync} from "./services/GlassesSettingsSync"
|
|
15
15
|
import {startGlassesStatusProjection, stopGlassesStatusProjection} from "./services/GlassesStatusProjection"
|
|
16
16
|
import {startOtaService, stopOtaService} from "./services/OtaService"
|
|
17
17
|
import {startAudioCloudUplink, stopAudioCloudUplink} from "./services/AudioCloudUplink"
|
|
18
|
+
import {startSupportProfileSync, stopSupportProfileSync} from "./services/SupportProfileSync"
|
|
18
19
|
import {startDeviceEventRouter, stopDeviceEventRouter} from "./services/DeviceEventRouter"
|
|
19
20
|
import {startPhoneNotificationsSync, stopPhoneNotificationsSync} from "./services/PhoneNotificationsSync"
|
|
20
21
|
import {startCaptionsTesterReportService, stopCaptionsTesterReportService} from "./services/CaptionsTesterReportService"
|
|
@@ -45,6 +46,8 @@ import {logBuffer} from "./utils/devLogging"
|
|
|
45
46
|
export const engine = {
|
|
46
47
|
/** Front door — hand engine auth + config, then start/stop the runtime. */
|
|
47
48
|
configure,
|
|
49
|
+
/** Merge host-UI seams on a running runtime (scan overlay, wifi setup, …). */
|
|
50
|
+
updateUiSeams,
|
|
48
51
|
/** Start the runtime: mark started + construct/connect the cloud client + begin
|
|
49
52
|
* syncing device settings to the glasses. */
|
|
50
53
|
async start() {
|
|
@@ -59,7 +62,7 @@ export const engine = {
|
|
|
59
62
|
// Project native device status -> the engine stores (the inbound feed the rest
|
|
60
63
|
// of the runtime reads). Established first so the stores are live before the
|
|
61
64
|
// syncs below react to them.
|
|
62
|
-
startGlassesStatusProjection()
|
|
65
|
+
startGlassesStatusProjection((changed) => localMiniappRuntime.forwardEvent("glasses_connection_state", changed))
|
|
63
66
|
// Route the rest of the inbound device events (wifi/hotspot/gallery -> stores+bus,
|
|
64
67
|
// photo/stream -> coordinators, button/touch/accel/head -> miniapps, save_setting ->
|
|
65
68
|
// store, miniapp_selected -> launcher) so a bare OEM gets device data, not just the
|
|
@@ -96,6 +99,7 @@ export const engine = {
|
|
|
96
99
|
error instanceof Error ? error.message : error,
|
|
97
100
|
)
|
|
98
101
|
}
|
|
102
|
+
startSupportProfileSync()
|
|
99
103
|
// Push device-setting changes to the glasses for ANY host, so
|
|
100
104
|
// engine.glasses.settings.set() reaches the device (not just the Mentra app).
|
|
101
105
|
startGlassesSettingsSync()
|
|
@@ -135,6 +139,7 @@ export const engine = {
|
|
|
135
139
|
await safely("device event router", stopDeviceEventRouter)
|
|
136
140
|
await safely("ota service", stopOtaService)
|
|
137
141
|
await safely("audio cloud uplink", stopAudioCloudUplink)
|
|
142
|
+
await safely("support profile sync", stopSupportProfileSync)
|
|
138
143
|
await safely("phone notifications sync", stopPhoneNotificationsSync)
|
|
139
144
|
await safely("captions tester report service", stopCaptionsTesterReportService)
|
|
140
145
|
await safely("mentrajs crashloop report service", stopMentraJSCrashloopReportService)
|
package/src/facades/dev.ts
CHANGED
|
@@ -143,25 +143,29 @@ export const dev = {
|
|
|
143
143
|
return {ok: false, error: "dev server unreachable, or no miniapp.json served there"}
|
|
144
144
|
}
|
|
145
145
|
const manifest = result.manifest
|
|
146
|
+
const appName = name ?? manifest.name ?? "Dev Miniapp"
|
|
147
|
+
const packageName = (manifest.packageName as string | undefined) ?? DEV_APP_PACKAGE_NAME
|
|
148
|
+
// Persist the host that answered — not the stale input IP — so home-tile
|
|
149
|
+
// relaunches skip a dead LAN address after mDNS/Metro failover.
|
|
150
|
+
const resolvedUrl = result.resolvedUrl || devUrl
|
|
146
151
|
// The `mentra-miniapp dev` server puts the hot-reload/log sidecar on the
|
|
147
152
|
// user port PLUS ONE — same convention as the first-party developer-URL
|
|
148
153
|
// screen's deriveDevPort.
|
|
149
154
|
let devPort: number | undefined
|
|
150
155
|
try {
|
|
151
|
-
const parsed = Number(new URL(
|
|
156
|
+
const parsed = Number(new URL(resolvedUrl).port)
|
|
152
157
|
devPort = Number.isFinite(parsed) && parsed > 0 ? parsed + 1 : undefined
|
|
153
158
|
} catch {
|
|
154
159
|
devPort = undefined
|
|
155
160
|
}
|
|
156
|
-
const appName = name ?? manifest.name ?? "Dev Miniapp"
|
|
157
|
-
const packageName = (manifest.packageName as string | undefined) ?? DEV_APP_PACKAGE_NAME
|
|
158
161
|
const existing = useAppStatusStore.getState().apps.find((app) => app.packageName === packageName)
|
|
159
162
|
if (existing?.running) await useAppStatusStore.getState().stop(packageName)
|
|
160
163
|
await registerDevApp({
|
|
161
164
|
packageName,
|
|
162
165
|
name: appName,
|
|
163
|
-
iconUrl: manifest.icon ? new URL(manifest.icon, `${
|
|
164
|
-
|
|
166
|
+
iconUrl: manifest.icon ? new URL(manifest.icon, `${resolvedUrl}/`).toString() : `${resolvedUrl}/icon.png`,
|
|
167
|
+
// Persist the host that answered — not the stale input IP.
|
|
168
|
+
devUrl: resolvedUrl,
|
|
165
169
|
devPort,
|
|
166
170
|
type: manifest.type as DevAppRecord["type"],
|
|
167
171
|
permissions: manifest.permissions as DevAppRecord["permissions"],
|
package/src/facades/gallery.ts
CHANGED
|
@@ -22,7 +22,7 @@ function projectStatus() {
|
|
|
22
22
|
processingFiles: Array.from(progress.processingFiles),
|
|
23
23
|
processedFiles: s.processedFiles,
|
|
24
24
|
isSyncing: selectIssyncing(s),
|
|
25
|
-
isStarting:
|
|
25
|
+
isStarting: s.syncStarting,
|
|
26
26
|
glassesGallery: selectGlassesGalleryStatus(s),
|
|
27
27
|
// Copy: the snapshot must not hand callers a mutable reference into the store
|
|
28
28
|
// (each queue item is copied too — callers must not mutate them in place).
|
package/src/facades/glasses.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {hasDefaultDevice} from "../services/DeviceStoreHydration"
|
|
|
18
18
|
import {projectPairingIdentity} from "../services/PairingIdentity"
|
|
19
19
|
import {isGlassesConnected, isGlassesReady} from "../services/GlassesReadiness"
|
|
20
20
|
import {pushAllBluetoothSettings} from "../services/GlassesSettingsSync"
|
|
21
|
+
import {recordSupportProfileConnectionFailure} from "../services/SupportProfileSync"
|
|
21
22
|
import {getModelCapabilities, type DeviceTypes} from "../types"
|
|
22
23
|
import {glassesWifi} from "./glassesWifi"
|
|
23
24
|
import {glassesSettings} from "./glassesSettings"
|
|
@@ -62,6 +63,7 @@ function projectInfo() {
|
|
|
62
63
|
serialNumber: s.serialNumber,
|
|
63
64
|
buildNumber: s.buildNumber,
|
|
64
65
|
btMac: s.bluetoothMacAddress,
|
|
66
|
+
wifiMac: s.wifiMacAddress,
|
|
65
67
|
leftMac: s.leftMacAddress,
|
|
66
68
|
rightMac: s.rightMacAddress,
|
|
67
69
|
// Copy: the snapshot must not hand callers a mutable reference into the store.
|
|
@@ -81,15 +83,25 @@ export const glasses = {
|
|
|
81
83
|
* the glasses (this used to be a host-side step before `connectDefault`).
|
|
82
84
|
*/
|
|
83
85
|
connectDefault: async (): Promise<void> => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
try {
|
|
87
|
+
await pushAllBluetoothSettings()
|
|
88
|
+
await BluetoothSdk.connectDefault()
|
|
89
|
+
} catch (error) {
|
|
90
|
+
recordSupportProfileConnectionFailure(error, "connect_default")
|
|
91
|
+
throw error
|
|
92
|
+
}
|
|
86
93
|
},
|
|
87
94
|
disconnect: (): Promise<void> => BluetoothSdk.disconnect(),
|
|
88
95
|
forget: (): Promise<void> => BluetoothSdk.forget(),
|
|
89
96
|
/** Connect to a specific (discovered) device. */
|
|
90
97
|
connect: async (...args: Parameters<typeof BluetoothSdk.connect>): Promise<void> => {
|
|
91
|
-
|
|
92
|
-
|
|
98
|
+
try {
|
|
99
|
+
await pushAllBluetoothSettings()
|
|
100
|
+
await BluetoothSdk.connect(...args)
|
|
101
|
+
} catch (error) {
|
|
102
|
+
recordSupportProfileConnectionFailure(error, "connect")
|
|
103
|
+
throw error
|
|
104
|
+
}
|
|
93
105
|
},
|
|
94
106
|
/** Connect the built-in simulated glasses (dev/testing). */
|
|
95
107
|
connectSimulated: (): Promise<void> => BluetoothSdk.connectSimulated(),
|
|
@@ -110,6 +122,7 @@ export const glasses = {
|
|
|
110
122
|
await pushAllBluetoothSettings()
|
|
111
123
|
await BluetoothSdk.connectDefault()
|
|
112
124
|
} catch (error) {
|
|
125
|
+
recordSupportProfileConnectionFailure(error, "reconnect")
|
|
113
126
|
console.warn("engine.glasses.reconnect failed:", error)
|
|
114
127
|
return false
|
|
115
128
|
}
|
|
@@ -22,6 +22,7 @@ const INTERNAL_KEYS = new Set<string>([
|
|
|
22
22
|
SETTINGS.default_wearable.key,
|
|
23
23
|
SETTINGS.device_name.key,
|
|
24
24
|
SETTINGS.device_address.key,
|
|
25
|
+
SETTINGS.project_name.key,
|
|
25
26
|
SETTINGS.pending_controller.key,
|
|
26
27
|
SETTINGS.default_controller.key,
|
|
27
28
|
SETTINGS.controller_device_name.key,
|
|
@@ -54,3 +55,7 @@ export const glassesSettings = {
|
|
|
54
55
|
// Copy: callers must not be able to mutate the module-level key list.
|
|
55
56
|
available: (): string[] => [...DEVICE_KEYS],
|
|
56
57
|
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|