@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
|
@@ -45,21 +45,27 @@ export class BlobStore {
|
|
|
45
45
|
hooks;
|
|
46
46
|
uploads = new Map(); // key: `${pkg} ${key}`
|
|
47
47
|
readers = new Map(); // key: host handle id
|
|
48
|
-
/**
|
|
48
|
+
/** user + package → committed usage bytes, cached; invalidated on commit/delete/clear. */
|
|
49
49
|
usageCache = new Map();
|
|
50
50
|
constructor(hooks) {
|
|
51
51
|
this.hooks = hooks;
|
|
52
52
|
}
|
|
53
53
|
// ---- path / meta helpers -------------------------------------------------
|
|
54
|
+
currentIdentity(packageName) {
|
|
55
|
+
const userId = this.hooks.getUserId().trim();
|
|
56
|
+
if (!userId)
|
|
57
|
+
throw new Error("Mentra user identity is unavailable");
|
|
58
|
+
const scope = `${userId}\0${packageName}`;
|
|
59
|
+
return { userId, scope };
|
|
60
|
+
}
|
|
54
61
|
dirFor(packageName) {
|
|
55
|
-
const
|
|
56
|
-
const dir = new Directory(Paths.document, ROOT_DIR_NAME, userId, sanitizeSegment(packageName));
|
|
62
|
+
const dir = new Directory(Paths.document, ROOT_DIR_NAME, sanitizeSegment(this.currentIdentity(packageName).userId), sanitizeSegment(packageName));
|
|
57
63
|
if (!dir.exists)
|
|
58
64
|
dir.create({ intermediates: true });
|
|
59
65
|
return dir;
|
|
60
66
|
}
|
|
61
67
|
metaPrefix(packageName) {
|
|
62
|
-
return `${META_KEY_ROOT}${sanitizeSegment(this.
|
|
68
|
+
return `${META_KEY_ROOT}${sanitizeSegment(this.currentIdentity(packageName).userId)}_${packageName}_`;
|
|
63
69
|
}
|
|
64
70
|
metaKey(packageName, key) {
|
|
65
71
|
return this.metaPrefix(packageName) + key;
|
|
@@ -104,19 +110,21 @@ export class BlobStore {
|
|
|
104
110
|
};
|
|
105
111
|
}
|
|
106
112
|
committedUsage(packageName) {
|
|
107
|
-
const
|
|
113
|
+
const { scope } = this.currentIdentity(packageName);
|
|
114
|
+
const cached = this.usageCache.get(scope);
|
|
108
115
|
if (cached !== undefined)
|
|
109
116
|
return cached;
|
|
110
117
|
let total = 0;
|
|
111
118
|
for (const m of this.allMeta(packageName))
|
|
112
119
|
total += m.bytes || 0;
|
|
113
|
-
this.usageCache.set(
|
|
120
|
+
this.usageCache.set(scope, total);
|
|
114
121
|
return total;
|
|
115
122
|
}
|
|
116
123
|
bumpUsage(packageName, delta) {
|
|
117
|
-
const
|
|
124
|
+
const { scope } = this.currentIdentity(packageName);
|
|
125
|
+
const cur = this.usageCache.get(scope);
|
|
118
126
|
if (cur !== undefined)
|
|
119
|
-
this.usageCache.set(
|
|
127
|
+
this.usageCache.set(scope, Math.max(0, cur + delta));
|
|
120
128
|
}
|
|
121
129
|
safeMd5(file, bytes) {
|
|
122
130
|
if (bytes > MD5_MAX_BYTES)
|
|
@@ -427,7 +435,7 @@ export class BlobStore {
|
|
|
427
435
|
catch {
|
|
428
436
|
/* best-effort */
|
|
429
437
|
}
|
|
430
|
-
this.usageCache.set(packageName, 0);
|
|
438
|
+
this.usageCache.set(this.currentIdentity(packageName).scope, 0);
|
|
431
439
|
this.hooks.sendResult(packageName, requestId, true);
|
|
432
440
|
}
|
|
433
441
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlobStore.js","sourceRoot":"","sources":["../../src/services/BlobStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * BlobStore\n *\n * Host-side implementation of `session.blob` — persistent, per-(userId,\n * packageName) BINARY storage for local miniapps, keyed like SimpleStorage (its\n * small-string sibling). Extracted from LocalMiniappRuntime the same way\n * NavigationHandlers is, to keep the runtime file small.\n *\n * Generic byte store — it knows nothing about any specific format. Highlights:\n * - chunked write/read (BLOB_CREATE/WRITE/COMMIT, BLOB_OPEN_READ/READ) so no\n * single bridge message is large;\n * - `setFromUrl` downloads a URL straight to disk (File.downloadFileAsync) and\n * `importFile` runs the OS picker (File.pickFileAsync) — both keep bytes\n * entirely host-side;\n * - `share` hands a stored file to the OS share sheet.\n *\n * Layout (mirrors SimpleStorage's scoping):\n * bytes: Paths.document/mentra_blobs/{userId}/{packageName}/{fileName}\n * metadata: MMKV key mentraos_blobmeta_{userId}_{packageName}_{key} → StoredBlobMeta JSON\n *\n * The on-disk file name is a generated id plus a mime-derived extension (iOS\n * AVPlayer keys a local file's format off the path extension, so blobs played\n * via `session.speaker.play` must carry one); the logical `key` (caller-chosen)\n * is the MMKV key. This decouples the filesystem from arbitrary caller keys.\n *\n * expo-file-system's new API is synchronous (create/writeBytes/md5/size), so\n * streaming chunk writes do no async work.\n */\n\nimport {Buffer} from \"buffer\"\nimport Share from \"react-native-share\"\nimport {Directory, File, Paths, type FileHandle} from \"expo-file-system\"\n\nimport {MiniappErrorCode} from \"@mentra/miniapp\"\nimport {storage as mmkvStorage} from \"../utils/storage/storage\"\nimport {sanitizeSegment, shareFileName, withDiskExt} from \"./blobPaths\"\n\nconst LOG_TAG = \"LocalMiniappRuntime\"\n\n/** Per-app blob quota: 1 GB. */\nexport const BLOB_QUOTA_BYTES = 1024 * 1024 * 1024\nconst ROOT_DIR_NAME = \"mentra_blobs\"\n/** Cache dir root holding short-lived, properly-named copies handed to the OS share sheet (one unique subdir per share). */\nconst SHARE_DIR_NAME = \"mentra_blob_share\"\nconst META_KEY_ROOT = \"mentraos_blobmeta_\"\n/** Cap md5 computation so we don't block the JS thread hashing a huge file. */\nconst MD5_MAX_BYTES = 50 * 1024 * 1024\n\n// Matches LocalMiniappRuntime.sendResult (see NavigationHandlers).\ntype SendResult = (\n packageName: string,\n requestId: string | undefined,\n ok: boolean,\n result?: unknown,\n error?: {code: MiniappErrorCode; message: string},\n) => void\n\nexport interface BlobStoreHooks {\n sendResult: SendResult\n /** Resolve the current user id (same source SimpleStorage uses). */\n getUserId: () => string\n}\n\ninterface StoredBlobMeta {\n key: string\n fileName: string\n name?: string\n mimeType: string\n bytes: number\n createdAt: number\n updatedAt: number\n md5?: string\n meta?: Record<string, string | number | boolean>\n}\n\ninterface ActiveUpload {\n packageName: string\n key: string\n fileName: string\n partFile: File\n handle: FileHandle\n bytes: number\n /** Bytes already committed under this key (overwrite target) — excluded from the quota check. */\n priorBytes: number\n name?: string\n mimeType: string\n meta?: Record<string, string | number | boolean>\n createdAt: number\n}\n\ninterface ActiveReader {\n packageName: string\n handle: FileHandle\n remaining: number\n}\n\nexport class BlobStore {\n private readonly uploads = new Map<string, ActiveUpload>() // key: `${pkg} ${key}`\n private readonly readers = new Map<string, ActiveReader>() // key: host handle id\n /** packageName → committed usage bytes, cached; invalidated on commit/delete/clear. */\n private readonly usageCache = new Map<string, number>()\n\n constructor(private readonly hooks: BlobStoreHooks) {}\n\n // ---- path / meta helpers -------------------------------------------------\n\n private dirFor(packageName: string): Directory {\n const userId = sanitizeSegment(this.hooks.getUserId())\n const dir = new Directory(Paths.document, ROOT_DIR_NAME, userId, sanitizeSegment(packageName))\n if (!dir.exists) dir.create({intermediates: true})\n return dir\n }\n\n private metaPrefix(packageName: string): string {\n return `${META_KEY_ROOT}${sanitizeSegment(this.hooks.getUserId())}_${packageName}_`\n }\n\n private metaKey(packageName: string, key: string): string {\n return this.metaPrefix(packageName) + key\n }\n\n private uploadKey(packageName: string, key: string): string {\n return `${packageName} ${key}`\n }\n\n private readMeta(packageName: string, key: string): StoredBlobMeta | null {\n const r = mmkvStorage.load<StoredBlobMeta>(this.metaKey(packageName, key))\n return r.is_ok() ? r.value : null\n }\n\n private writeMeta(packageName: string, meta: StoredBlobMeta): void {\n mmkvStorage.save(this.metaKey(packageName, meta.key), meta)\n }\n\n private allMeta(packageName: string): StoredBlobMeta[] {\n const prefix = this.metaPrefix(packageName)\n const out: StoredBlobMeta[] = []\n for (const k of mmkvStorage.getAllKeys()) {\n if (!k.startsWith(prefix)) continue\n const r = mmkvStorage.load<StoredBlobMeta>(k)\n if (r.is_ok() && r.value) out.push(r.value)\n }\n return out\n }\n\n private fileFor(packageName: string, fileName: string): File {\n return new File(this.dirFor(packageName), fileName)\n }\n\n /** Public API shape: stored meta + derived file:// uri. */\n private toBlobMeta(packageName: string, m: StoredBlobMeta) {\n return {\n key: m.key,\n name: m.name,\n mimeType: m.mimeType,\n bytes: m.bytes,\n createdAt: m.createdAt,\n updatedAt: m.updatedAt,\n md5: m.md5,\n uri: this.fileFor(packageName, m.fileName).uri,\n meta: m.meta,\n }\n }\n\n private committedUsage(packageName: string): number {\n const cached = this.usageCache.get(packageName)\n if (cached !== undefined) return cached\n let total = 0\n for (const m of this.allMeta(packageName)) total += m.bytes || 0\n this.usageCache.set(packageName, total)\n return total\n }\n\n private bumpUsage(packageName: string, delta: number): void {\n const cur = this.usageCache.get(packageName)\n if (cur !== undefined) this.usageCache.set(packageName, Math.max(0, cur + delta))\n }\n\n private safeMd5(file: File, bytes: number): string | undefined {\n if (bytes > MD5_MAX_BYTES) return undefined\n try {\n return file.md5 ?? undefined\n } catch {\n return undefined\n }\n }\n\n private makeId(): string {\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}${Math.random()\n .toString(36)\n .slice(2, 6)}`\n }\n\n /** Would storing `incoming` bytes under `key` exceed the per-app quota? */\n private overQuota(packageName: string, key: string, incoming: number): boolean {\n const priorBytes = this.readMeta(packageName, key)?.bytes ?? 0\n return this.committedUsage(packageName) - priorBytes + incoming > BLOB_QUOTA_BYTES\n }\n\n /** Publish a file already sitting at `fileName` as the blob for `key`; returns its public meta. */\n private commitFile(\n packageName: string,\n key: string,\n fileName: string,\n mimeType: string,\n name: string | undefined,\n extraMeta: Record<string, string | number | boolean> | undefined,\n ) {\n // Attach a mime-derived extension to the on-disk name. Consumers that key\n // format off the path — iOS AVPlayer under `session.speaker.play` — cannot\n // open an extension-less file, even though the bytes are valid.\n const named = withDiskExt(fileName, mimeType)\n if (named !== fileName) {\n try {\n this.fileFor(packageName, fileName).rename(named)\n fileName = named\n } catch {\n /* keep the extension-less name — the blob still stores and shares fine */\n }\n }\n const prior = this.readMeta(packageName, key)\n if (prior && prior.fileName !== fileName) {\n this.deleteFileQuiet(packageName, prior.fileName)\n this.bumpUsage(packageName, -(prior.bytes || 0))\n }\n const finalFile = this.fileFor(packageName, fileName)\n const bytes = finalFile.size ?? 0\n const now = Date.now()\n const meta: StoredBlobMeta = {\n key,\n fileName,\n name,\n mimeType,\n bytes,\n createdAt: prior?.createdAt ?? now,\n updatedAt: now,\n md5: this.safeMd5(finalFile, bytes),\n meta: extraMeta,\n }\n this.writeMeta(packageName, meta)\n this.bumpUsage(packageName, bytes)\n return this.toBlobMeta(packageName, meta)\n }\n\n // ---- streaming write -----------------------------------------------------\n\n handleCreate(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n try {\n const key = (typeof payload.key === \"string\" && payload.key) || this.makeId()\n const mapKey = this.uploadKey(packageName, key)\n const existing = this.uploads.get(mapKey)\n if (existing) this.discardUpload(existing)\n\n const fileName = this.makeId()\n const partFile = this.fileFor(packageName, fileName + \".part\")\n partFile.create({intermediates: true, overwrite: true})\n const handle = partFile.open()\n\n this.uploads.set(mapKey, {\n packageName,\n key,\n fileName,\n partFile,\n handle,\n bytes: 0,\n priorBytes: this.readMeta(packageName, key)?.bytes ?? 0,\n name: typeof payload.name === \"string\" ? payload.name : undefined,\n mimeType: typeof payload.mimeType === \"string\" ? payload.mimeType : \"application/octet-stream\",\n meta: (payload.meta as Record<string, string | number | boolean>) ?? undefined,\n createdAt: Date.now(),\n })\n this.hooks.sendResult(packageName, requestId, true, {key})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_WRITE_FAILED, err)\n }\n }\n\n handleWrite(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const up = this.uploads.get(this.uploadKey(packageName, key))\n if (!up) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_HANDLE_INVALID,\n message: `No open blob writer for key ${key}`,\n })\n return\n }\n try {\n const chunk = Buffer.from((payload.base64 as string) ?? \"\", \"base64\")\n const bytes = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength)\n // A seek write (offset present) patches existing bytes in place — used to\n // rewrite a container header on finalize; it does not grow the blob.\n if (typeof payload.offset === \"number\") {\n if (payload.offset < 0 || payload.offset + bytes.length > up.bytes) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_WRITE_FAILED,\n message: \"writeAt offset out of range (must stay within written bytes)\",\n })\n return\n }\n up.handle.offset = payload.offset\n up.handle.writeBytes(bytes)\n up.handle.offset = up.bytes // restore append position\n this.hooks.sendResult(packageName, requestId, true, {bytesWritten: up.bytes})\n return\n }\n // Exclude the prior blob under this key — it's freed on commit (overwrite).\n if (this.committedUsage(packageName) - up.priorBytes + up.bytes + bytes.length > BLOB_QUOTA_BYTES) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_QUOTA_EXCEEDED,\n message: `Blob quota (${BLOB_QUOTA_BYTES} bytes) exceeded`,\n })\n return\n }\n up.handle.offset = up.bytes\n up.handle.writeBytes(bytes)\n up.bytes += bytes.length\n this.hooks.sendResult(packageName, requestId, true, {bytesWritten: up.bytes})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_WRITE_FAILED, err)\n }\n }\n\n handleCommit(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const mapKey = this.uploadKey(packageName, key)\n const up = this.uploads.get(mapKey)\n if (!up) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_HANDLE_INVALID,\n message: `No open blob writer for key ${key}`,\n })\n return\n }\n try {\n up.handle.close()\n up.partFile.rename(up.fileName) // drop \".part\"\n const extraMeta = {\n ...(up.meta ?? {}),\n ...((payload.meta as Record<string, string | number | boolean>) ?? {}),\n }\n const meta = this.commitFile(packageName, key, up.fileName, up.mimeType, up.name, extraMeta)\n this.uploads.delete(mapKey)\n this.hooks.sendResult(packageName, requestId, true, meta)\n } catch (err) {\n this.discardUpload(up)\n this.uploads.delete(mapKey)\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_WRITE_FAILED, err)\n }\n }\n\n handleAbort(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const mapKey = this.uploadKey(packageName, payload.key as string)\n const up = this.uploads.get(mapKey)\n if (up) {\n this.discardUpload(up)\n this.uploads.delete(mapKey)\n }\n this.hooks.sendResult(packageName, requestId, true)\n }\n\n // ---- download / import (host-side; no bytes cross the bridge) -------------\n\n async handleSetFromUrl(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n const key = payload.key as string\n const url = payload.url as string\n if (!key || !url) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, new Error(\"setFromUrl requires key + url\"))\n return\n }\n if (url.startsWith(\"file:\") || url.startsWith(\"javascript:\")) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_DOWNLOAD_FAILED,\n message: \"Unsupported URL scheme\",\n })\n return\n }\n const headers = payload.headers as Record<string, string> | undefined\n const fileName = this.makeId()\n const partFile = this.fileFor(packageName, fileName + \".part\")\n try {\n const dl = await File.downloadFileAsync(url, partFile, {idempotent: true, ...(headers ? {headers} : {})})\n const size = dl.size ?? 0\n if (this.overQuota(packageName, key, size)) {\n try {\n dl.delete()\n } catch {\n /* ignore */\n }\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_QUOTA_EXCEEDED,\n message: `Blob quota (${BLOB_QUOTA_BYTES} bytes) exceeded`,\n })\n return\n }\n partFile.rename(fileName)\n const mimeType =\n (payload.mimeType as string) || inferMime(basename(url)) || this.fileFor(packageName, fileName).type || OCTET\n const name = (payload.name as string) || basename(url) || key\n const meta = this.commitFile(\n packageName,\n key,\n fileName,\n mimeType,\n name,\n payload.meta as Record<string, string | number | boolean> | undefined,\n )\n this.hooks.sendResult(packageName, requestId, true, meta)\n } catch (err) {\n try {\n if (partFile.exists) partFile.delete()\n } catch {\n /* ignore */\n }\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_DOWNLOAD_FAILED, err)\n }\n }\n\n async handleImport(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n const key = (typeof payload.key === \"string\" && payload.key) || this.makeId()\n const mimeFilter = payload.mimeType as string | undefined\n\n let picked: File | File[] | null = null\n try {\n picked = await File.pickFileAsync(undefined, mimeFilter)\n } catch (err) {\n // Picker dismissed / cancelled (or unavailable) → resolve to null, not an error.\n console.log(`${LOG_TAG}: blob import picker dismissed`, err)\n this.hooks.sendResult(packageName, requestId, true, null)\n return\n }\n const file = Array.isArray(picked) ? picked[0] : picked\n if (!file) {\n this.hooks.sendResult(packageName, requestId, true, null)\n return\n }\n try {\n const size = file.size ?? 0\n if (this.overQuota(packageName, key, size)) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_QUOTA_EXCEEDED,\n message: `Blob quota (${BLOB_QUOTA_BYTES} bytes) exceeded`,\n })\n return\n }\n const fileName = this.makeId()\n file.copy(this.fileFor(packageName, fileName))\n const name = basename(file.uri) || key\n const mimeType = mimeFilter || file.type || inferMime(name) || OCTET\n const meta = this.commitFile(\n packageName,\n key,\n fileName,\n mimeType,\n name,\n payload.meta as Record<string, string | number | boolean> | undefined,\n )\n this.hooks.sendResult(packageName, requestId, true, meta)\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_IMPORT_FAILED, err)\n }\n }\n\n // ---- read ----------------------------------------------------------------\n\n handleGet(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const meta = this.readMeta(packageName, key)\n if (!meta || !this.fileFor(packageName, meta.fileName).exists) {\n if (meta) this.dropMeta(packageName, meta) // reconcile dangling meta\n this.hooks.sendResult(packageName, requestId, true, null)\n return\n }\n this.hooks.sendResult(packageName, requestId, true, this.toBlobMeta(packageName, meta))\n }\n\n handleList(packageName: string, _payload: Record<string, unknown>, requestId?: string): void {\n const blobs = this.allMeta(packageName)\n .filter((m) => this.fileFor(packageName, m.fileName).exists)\n .sort((a, b) => b.createdAt - a.createdAt)\n .map((m) => this.toBlobMeta(packageName, m))\n this.hooks.sendResult(packageName, requestId, true, {blobs})\n }\n\n handleUsage(packageName: string, _payload: Record<string, unknown>, requestId?: string): void {\n const metas = this.allMeta(packageName)\n this.hooks.sendResult(packageName, requestId, true, {\n bytes: metas.reduce((s, m) => s + (m.bytes || 0), 0),\n count: metas.length,\n quotaBytes: BLOB_QUOTA_BYTES,\n })\n }\n\n handleDelete(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const meta = this.readMeta(packageName, payload.key as string)\n if (meta) this.dropMeta(packageName, meta)\n this.hooks.sendResult(packageName, requestId, true)\n }\n\n handleClear(packageName: string, _payload: Record<string, unknown>, requestId?: string): void {\n try {\n // Abort any in-flight uploads / open readers first so nothing keeps writing\n // to a .part file in the directory we're about to delete.\n this.closeAppHandles(packageName)\n for (const m of this.allMeta(packageName)) mmkvStorage.remove(this.metaKey(packageName, m.key))\n const dir = this.dirFor(packageName)\n try {\n if (dir.exists) dir.delete()\n } catch {\n /* best-effort */\n }\n this.usageCache.set(packageName, 0)\n this.hooks.sendResult(packageName, requestId, true)\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, err)\n }\n }\n\n handleOpenRead(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const meta = this.readMeta(packageName, key)\n const file = meta ? this.fileFor(packageName, meta.fileName) : null\n if (!meta || !file || !file.exists) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_NOT_FOUND,\n message: `Blob ${key} not found`,\n })\n return\n }\n try {\n const handle = file.open()\n const handleId = `r_${this.makeId()}`\n this.readers.set(handleId, {packageName, handle, remaining: meta.bytes})\n this.hooks.sendResult(packageName, requestId, true, {handle: handleId, meta: this.toBlobMeta(packageName, meta)})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, err)\n }\n }\n\n handleRead(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const handleId = payload.handle as string\n const reader = this.readers.get(handleId)\n if (!reader || reader.packageName !== packageName) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_HANDLE_INVALID,\n message: \"Unknown blob read handle\",\n })\n return\n }\n try {\n const want = Math.max(0, Math.min(Number(payload.maxBytes) || 1024 * 1024, reader.remaining))\n const bytes = want > 0 ? reader.handle.readBytes(want) : new Uint8Array(0)\n reader.remaining -= bytes.length\n const done = reader.remaining <= 0\n const base64 = bytes.length\n ? Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString(\"base64\")\n : \"\"\n if (done) {\n try {\n reader.handle.close()\n } catch {\n /* ignore */\n }\n this.readers.delete(handleId)\n }\n this.hooks.sendResult(packageName, requestId, true, {base64, done})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, err)\n }\n }\n\n handleCloseRead(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const handleId = payload.handle as string\n const reader = this.readers.get(handleId)\n if (reader && reader.packageName === packageName) {\n try {\n reader.handle.close()\n } catch {\n /* ignore */\n }\n this.readers.delete(handleId)\n }\n this.hooks.sendResult(packageName, requestId, true)\n }\n\n // ---- share ---------------------------------------------------------------\n\n async handleShare(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n const key = payload.key as string\n const meta = this.readMeta(packageName, key)\n const file = meta ? this.fileFor(packageName, meta.fileName) : null\n if (!meta || !file || !file.exists) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_NOT_FOUND,\n message: `Blob ${key} not found`,\n })\n return\n }\n // The on-disk blob name is a generated id (mime extension attached at\n // commit; legacy blobs may lack it). react-native-share derives the shared\n // file's name + extension from the URL's path (its `filename` option only\n // applies to base64/data payloads, not file:// URLs), so sharing `file.uri`\n // directly would hand the recipient a machine-named file. Copy to a temp\n // file that carries the real display name + extension, share that, then\n // clean it up.\n const shareName = shareFileName(meta)\n // Copy into a per-share unique subdir so two concurrent shares that resolve\n // to the same display name can't clobber each other's temp file while\n // Share.open still references it. The file keeps `shareName` as its basename\n // so the OS share sheet shows the right name + extension.\n let tempDir: Directory | null = null\n try {\n tempDir = new Directory(Paths.cache, SHARE_DIR_NAME, this.makeId())\n tempDir.create({intermediates: true})\n const temp = new File(tempDir, shareName)\n file.copy(temp)\n await Share.open({\n url: temp.uri,\n type: meta.mimeType || OCTET,\n filename: shareName,\n })\n this.hooks.sendResult(packageName, requestId, true, {success: true})\n } catch (error: any) {\n if (error?.message?.includes(\"User did not share\")) {\n this.hooks.sendResult(packageName, requestId, true, {success: false, cancelled: true})\n } else {\n console.error(`${LOG_TAG}: blob share error:`, error)\n this.hooks.sendResult(packageName, requestId, true, {success: false})\n }\n } finally {\n if (tempDir) {\n try {\n if (tempDir.exists) tempDir.delete()\n } catch {\n /* ignore */\n }\n }\n }\n }\n\n // ---- lifecycle / cleanup -------------------------------------------------\n\n /** Called from LocalMiniappRuntime.unregisterApp — drop this app's in-flight state. */\n onAppGone(packageName: string): void {\n this.closeAppHandles(packageName)\n }\n\n /** Abort in-flight uploads + close open read handles for an app (no-op if none). */\n private closeAppHandles(packageName: string): void {\n for (const [k, up] of this.uploads) {\n if (up.packageName === packageName) {\n this.discardUpload(up)\n this.uploads.delete(k)\n }\n }\n for (const [k, reader] of this.readers) {\n if (reader.packageName === packageName) {\n try {\n reader.handle.close()\n } catch {\n /* ignore */\n }\n this.readers.delete(k)\n }\n }\n }\n\n private discardUpload(up: ActiveUpload): void {\n try {\n up.handle.close()\n } catch {\n /* ignore */\n }\n try {\n if (up.partFile.exists) up.partFile.delete()\n } catch {\n /* ignore */\n }\n }\n\n private dropMeta(packageName: string, meta: StoredBlobMeta): void {\n this.deleteFileQuiet(packageName, meta.fileName)\n mmkvStorage.remove(this.metaKey(packageName, meta.key))\n this.bumpUsage(packageName, -(meta.bytes || 0))\n }\n\n private deleteFileQuiet(packageName: string, fileName: string): void {\n try {\n const f = this.fileFor(packageName, fileName)\n if (f.exists) f.delete()\n } catch {\n /* ignore */\n }\n }\n\n private fail(packageName: string, requestId: string | undefined, code: MiniappErrorCode, err: unknown): void {\n console.error(`${LOG_TAG}: blob error [${code}]:`, err)\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code,\n message: err instanceof Error ? err.message : \"Blob error\",\n })\n }\n}\n\nconst OCTET = \"application/octet-stream\"\n\n/** Last path segment of a URL/URI, query stripped + percent-decoded. */\nfunction basename(uri: string): string {\n const noQuery = uri.split(\"?\")[0].split(\"#\")[0]\n const seg = noQuery.substring(noQuery.lastIndexOf(\"/\") + 1)\n try {\n return decodeURIComponent(seg)\n } catch {\n return seg\n }\n}\n\n/** Best-effort MIME from a filename extension. Returns undefined when unknown. */\nfunction inferMime(name: string): string | undefined {\n const dot = name.lastIndexOf(\".\")\n if (dot < 0) return undefined\n const ext = name.slice(dot + 1).toLowerCase()\n const map: Record<string, string> = {\n pdf: \"application/pdf\",\n epub: \"application/epub+zip\",\n zip: \"application/zip\",\n json: \"application/json\",\n txt: \"text/plain\",\n csv: \"text/csv\",\n html: \"text/html\",\n mp4: \"video/mp4\",\n mov: \"video/quicktime\",\n webm: \"video/webm\",\n mp3: \"audio/mpeg\",\n m4a: \"audio/mp4\",\n wav: \"audio/wav\",\n ogg: \"audio/ogg\",\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n }\n return map[ext]\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BlobStore.js","sourceRoot":"","sources":["../../src/services/BlobStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * BlobStore\n *\n * Host-side implementation of `session.blob` — persistent, per-(userId,\n * packageName) BINARY storage for local miniapps, keyed like SimpleStorage (its\n * small-string sibling). Extracted from LocalMiniappRuntime the same way\n * NavigationHandlers is, to keep the runtime file small.\n *\n * Generic byte store — it knows nothing about any specific format. Highlights:\n * - chunked write/read (BLOB_CREATE/WRITE/COMMIT, BLOB_OPEN_READ/READ) so no\n * single bridge message is large;\n * - `setFromUrl` downloads a URL straight to disk (File.downloadFileAsync) and\n * `importFile` runs the OS picker (File.pickFileAsync) — both keep bytes\n * entirely host-side;\n * - `share` hands a stored file to the OS share sheet.\n *\n * Layout (mirrors SimpleStorage's scoping):\n * bytes: Paths.document/mentra_blobs/{userId}/{packageName}/{fileName}\n * metadata: MMKV key mentraos_blobmeta_{userId}_{packageName}_{key} → StoredBlobMeta JSON\n *\n * The on-disk file name is a generated id plus a mime-derived extension (iOS\n * AVPlayer keys a local file's format off the path extension, so blobs played\n * via `session.speaker.play` must carry one); the logical `key` (caller-chosen)\n * is the MMKV key. This decouples the filesystem from arbitrary caller keys.\n *\n * expo-file-system's new API is synchronous (create/writeBytes/md5/size), so\n * streaming chunk writes do no async work.\n */\n\nimport {Buffer} from \"buffer\"\nimport Share from \"react-native-share\"\nimport {Directory, File, Paths, type FileHandle} from \"expo-file-system\"\n\nimport {MiniappErrorCode} from \"@mentra/miniapp\"\nimport {storage as mmkvStorage} from \"../utils/storage/storage\"\nimport {sanitizeSegment, shareFileName, withDiskExt} from \"./blobPaths\"\n\nconst LOG_TAG = \"LocalMiniappRuntime\"\n\n/** Per-app blob quota: 1 GB. */\nexport const BLOB_QUOTA_BYTES = 1024 * 1024 * 1024\nconst ROOT_DIR_NAME = \"mentra_blobs\"\n/** Cache dir root holding short-lived, properly-named copies handed to the OS share sheet (one unique subdir per share). */\nconst SHARE_DIR_NAME = \"mentra_blob_share\"\nconst META_KEY_ROOT = \"mentraos_blobmeta_\"\n/** Cap md5 computation so we don't block the JS thread hashing a huge file. */\nconst MD5_MAX_BYTES = 50 * 1024 * 1024\n\n// Matches LocalMiniappRuntime.sendResult (see NavigationHandlers).\ntype SendResult = (\n packageName: string,\n requestId: string | undefined,\n ok: boolean,\n result?: unknown,\n error?: {code: MiniappErrorCode; message: string},\n) => void\n\nexport interface BlobStoreHooks {\n sendResult: SendResult\n /** Resolve the current user id (same source SimpleStorage uses). */\n getUserId: () => string\n}\n\ninterface StoredBlobMeta {\n key: string\n fileName: string\n name?: string\n mimeType: string\n bytes: number\n createdAt: number\n updatedAt: number\n md5?: string\n meta?: Record<string, string | number | boolean>\n}\n\ninterface ActiveUpload {\n packageName: string\n key: string\n fileName: string\n partFile: File\n handle: FileHandle\n bytes: number\n /** Bytes already committed under this key (overwrite target) — excluded from the quota check. */\n priorBytes: number\n name?: string\n mimeType: string\n meta?: Record<string, string | number | boolean>\n createdAt: number\n}\n\ninterface ActiveReader {\n packageName: string\n handle: FileHandle\n remaining: number\n}\n\nexport class BlobStore {\n private readonly uploads = new Map<string, ActiveUpload>() // key: `${pkg} ${key}`\n private readonly readers = new Map<string, ActiveReader>() // key: host handle id\n /** user + package → committed usage bytes, cached; invalidated on commit/delete/clear. */\n private readonly usageCache = new Map<string, number>()\n\n constructor(private readonly hooks: BlobStoreHooks) {}\n\n // ---- path / meta helpers -------------------------------------------------\n\n private currentIdentity(packageName: string): {userId: string; scope: string} {\n const userId = this.hooks.getUserId().trim()\n if (!userId) throw new Error(\"Mentra user identity is unavailable\")\n const scope = `${userId}\\0${packageName}`\n return {userId, scope}\n }\n\n private dirFor(packageName: string): Directory {\n const dir = new Directory(\n Paths.document,\n ROOT_DIR_NAME,\n sanitizeSegment(this.currentIdentity(packageName).userId),\n sanitizeSegment(packageName),\n )\n if (!dir.exists) dir.create({intermediates: true})\n return dir\n }\n\n private metaPrefix(packageName: string): string {\n return `${META_KEY_ROOT}${sanitizeSegment(this.currentIdentity(packageName).userId)}_${packageName}_`\n }\n\n private metaKey(packageName: string, key: string): string {\n return this.metaPrefix(packageName) + key\n }\n\n private uploadKey(packageName: string, key: string): string {\n return `${packageName} ${key}`\n }\n\n private readMeta(packageName: string, key: string): StoredBlobMeta | null {\n const r = mmkvStorage.load<StoredBlobMeta>(this.metaKey(packageName, key))\n return r.is_ok() ? r.value : null\n }\n\n private writeMeta(packageName: string, meta: StoredBlobMeta): void {\n mmkvStorage.save(this.metaKey(packageName, meta.key), meta)\n }\n\n private allMeta(packageName: string): StoredBlobMeta[] {\n const prefix = this.metaPrefix(packageName)\n const out: StoredBlobMeta[] = []\n for (const k of mmkvStorage.getAllKeys()) {\n if (!k.startsWith(prefix)) continue\n const r = mmkvStorage.load<StoredBlobMeta>(k)\n if (r.is_ok() && r.value) out.push(r.value)\n }\n return out\n }\n\n private fileFor(packageName: string, fileName: string): File {\n return new File(this.dirFor(packageName), fileName)\n }\n\n /** Public API shape: stored meta + derived file:// uri. */\n private toBlobMeta(packageName: string, m: StoredBlobMeta) {\n return {\n key: m.key,\n name: m.name,\n mimeType: m.mimeType,\n bytes: m.bytes,\n createdAt: m.createdAt,\n updatedAt: m.updatedAt,\n md5: m.md5,\n uri: this.fileFor(packageName, m.fileName).uri,\n meta: m.meta,\n }\n }\n\n private committedUsage(packageName: string): number {\n const {scope} = this.currentIdentity(packageName)\n const cached = this.usageCache.get(scope)\n if (cached !== undefined) return cached\n let total = 0\n for (const m of this.allMeta(packageName)) total += m.bytes || 0\n this.usageCache.set(scope, total)\n return total\n }\n\n private bumpUsage(packageName: string, delta: number): void {\n const {scope} = this.currentIdentity(packageName)\n const cur = this.usageCache.get(scope)\n if (cur !== undefined) this.usageCache.set(scope, Math.max(0, cur + delta))\n }\n\n private safeMd5(file: File, bytes: number): string | undefined {\n if (bytes > MD5_MAX_BYTES) return undefined\n try {\n return file.md5 ?? undefined\n } catch {\n return undefined\n }\n }\n\n private makeId(): string {\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}${Math.random()\n .toString(36)\n .slice(2, 6)}`\n }\n\n /** Would storing `incoming` bytes under `key` exceed the per-app quota? */\n private overQuota(packageName: string, key: string, incoming: number): boolean {\n const priorBytes = this.readMeta(packageName, key)?.bytes ?? 0\n return this.committedUsage(packageName) - priorBytes + incoming > BLOB_QUOTA_BYTES\n }\n\n /** Publish a file already sitting at `fileName` as the blob for `key`; returns its public meta. */\n private commitFile(\n packageName: string,\n key: string,\n fileName: string,\n mimeType: string,\n name: string | undefined,\n extraMeta: Record<string, string | number | boolean> | undefined,\n ) {\n // Attach a mime-derived extension to the on-disk name. Consumers that key\n // format off the path — iOS AVPlayer under `session.speaker.play` — cannot\n // open an extension-less file, even though the bytes are valid.\n const named = withDiskExt(fileName, mimeType)\n if (named !== fileName) {\n try {\n this.fileFor(packageName, fileName).rename(named)\n fileName = named\n } catch {\n /* keep the extension-less name — the blob still stores and shares fine */\n }\n }\n const prior = this.readMeta(packageName, key)\n if (prior && prior.fileName !== fileName) {\n this.deleteFileQuiet(packageName, prior.fileName)\n this.bumpUsage(packageName, -(prior.bytes || 0))\n }\n const finalFile = this.fileFor(packageName, fileName)\n const bytes = finalFile.size ?? 0\n const now = Date.now()\n const meta: StoredBlobMeta = {\n key,\n fileName,\n name,\n mimeType,\n bytes,\n createdAt: prior?.createdAt ?? now,\n updatedAt: now,\n md5: this.safeMd5(finalFile, bytes),\n meta: extraMeta,\n }\n this.writeMeta(packageName, meta)\n this.bumpUsage(packageName, bytes)\n return this.toBlobMeta(packageName, meta)\n }\n\n // ---- streaming write -----------------------------------------------------\n\n handleCreate(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n try {\n const key = (typeof payload.key === \"string\" && payload.key) || this.makeId()\n const mapKey = this.uploadKey(packageName, key)\n const existing = this.uploads.get(mapKey)\n if (existing) this.discardUpload(existing)\n\n const fileName = this.makeId()\n const partFile = this.fileFor(packageName, fileName + \".part\")\n partFile.create({intermediates: true, overwrite: true})\n const handle = partFile.open()\n\n this.uploads.set(mapKey, {\n packageName,\n key,\n fileName,\n partFile,\n handle,\n bytes: 0,\n priorBytes: this.readMeta(packageName, key)?.bytes ?? 0,\n name: typeof payload.name === \"string\" ? payload.name : undefined,\n mimeType: typeof payload.mimeType === \"string\" ? payload.mimeType : \"application/octet-stream\",\n meta: (payload.meta as Record<string, string | number | boolean>) ?? undefined,\n createdAt: Date.now(),\n })\n this.hooks.sendResult(packageName, requestId, true, {key})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_WRITE_FAILED, err)\n }\n }\n\n handleWrite(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const up = this.uploads.get(this.uploadKey(packageName, key))\n if (!up) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_HANDLE_INVALID,\n message: `No open blob writer for key ${key}`,\n })\n return\n }\n try {\n const chunk = Buffer.from((payload.base64 as string) ?? \"\", \"base64\")\n const bytes = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength)\n // A seek write (offset present) patches existing bytes in place — used to\n // rewrite a container header on finalize; it does not grow the blob.\n if (typeof payload.offset === \"number\") {\n if (payload.offset < 0 || payload.offset + bytes.length > up.bytes) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_WRITE_FAILED,\n message: \"writeAt offset out of range (must stay within written bytes)\",\n })\n return\n }\n up.handle.offset = payload.offset\n up.handle.writeBytes(bytes)\n up.handle.offset = up.bytes // restore append position\n this.hooks.sendResult(packageName, requestId, true, {bytesWritten: up.bytes})\n return\n }\n // Exclude the prior blob under this key — it's freed on commit (overwrite).\n if (this.committedUsage(packageName) - up.priorBytes + up.bytes + bytes.length > BLOB_QUOTA_BYTES) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_QUOTA_EXCEEDED,\n message: `Blob quota (${BLOB_QUOTA_BYTES} bytes) exceeded`,\n })\n return\n }\n up.handle.offset = up.bytes\n up.handle.writeBytes(bytes)\n up.bytes += bytes.length\n this.hooks.sendResult(packageName, requestId, true, {bytesWritten: up.bytes})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_WRITE_FAILED, err)\n }\n }\n\n handleCommit(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const mapKey = this.uploadKey(packageName, key)\n const up = this.uploads.get(mapKey)\n if (!up) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_HANDLE_INVALID,\n message: `No open blob writer for key ${key}`,\n })\n return\n }\n try {\n up.handle.close()\n up.partFile.rename(up.fileName) // drop \".part\"\n const extraMeta = {\n ...(up.meta ?? {}),\n ...((payload.meta as Record<string, string | number | boolean>) ?? {}),\n }\n const meta = this.commitFile(packageName, key, up.fileName, up.mimeType, up.name, extraMeta)\n this.uploads.delete(mapKey)\n this.hooks.sendResult(packageName, requestId, true, meta)\n } catch (err) {\n this.discardUpload(up)\n this.uploads.delete(mapKey)\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_WRITE_FAILED, err)\n }\n }\n\n handleAbort(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const mapKey = this.uploadKey(packageName, payload.key as string)\n const up = this.uploads.get(mapKey)\n if (up) {\n this.discardUpload(up)\n this.uploads.delete(mapKey)\n }\n this.hooks.sendResult(packageName, requestId, true)\n }\n\n // ---- download / import (host-side; no bytes cross the bridge) -------------\n\n async handleSetFromUrl(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n const key = payload.key as string\n const url = payload.url as string\n if (!key || !url) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, new Error(\"setFromUrl requires key + url\"))\n return\n }\n if (url.startsWith(\"file:\") || url.startsWith(\"javascript:\")) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_DOWNLOAD_FAILED,\n message: \"Unsupported URL scheme\",\n })\n return\n }\n const headers = payload.headers as Record<string, string> | undefined\n const fileName = this.makeId()\n const partFile = this.fileFor(packageName, fileName + \".part\")\n try {\n const dl = await File.downloadFileAsync(url, partFile, {idempotent: true, ...(headers ? {headers} : {})})\n const size = dl.size ?? 0\n if (this.overQuota(packageName, key, size)) {\n try {\n dl.delete()\n } catch {\n /* ignore */\n }\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_QUOTA_EXCEEDED,\n message: `Blob quota (${BLOB_QUOTA_BYTES} bytes) exceeded`,\n })\n return\n }\n partFile.rename(fileName)\n const mimeType =\n (payload.mimeType as string) || inferMime(basename(url)) || this.fileFor(packageName, fileName).type || OCTET\n const name = (payload.name as string) || basename(url) || key\n const meta = this.commitFile(\n packageName,\n key,\n fileName,\n mimeType,\n name,\n payload.meta as Record<string, string | number | boolean> | undefined,\n )\n this.hooks.sendResult(packageName, requestId, true, meta)\n } catch (err) {\n try {\n if (partFile.exists) partFile.delete()\n } catch {\n /* ignore */\n }\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_DOWNLOAD_FAILED, err)\n }\n }\n\n async handleImport(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n const key = (typeof payload.key === \"string\" && payload.key) || this.makeId()\n const mimeFilter = payload.mimeType as string | undefined\n\n let picked: File | File[] | null = null\n try {\n picked = await File.pickFileAsync(undefined, mimeFilter)\n } catch (err) {\n // Picker dismissed / cancelled (or unavailable) → resolve to null, not an error.\n console.log(`${LOG_TAG}: blob import picker dismissed`, err)\n this.hooks.sendResult(packageName, requestId, true, null)\n return\n }\n const file = Array.isArray(picked) ? picked[0] : picked\n if (!file) {\n this.hooks.sendResult(packageName, requestId, true, null)\n return\n }\n try {\n const size = file.size ?? 0\n if (this.overQuota(packageName, key, size)) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_QUOTA_EXCEEDED,\n message: `Blob quota (${BLOB_QUOTA_BYTES} bytes) exceeded`,\n })\n return\n }\n const fileName = this.makeId()\n file.copy(this.fileFor(packageName, fileName))\n const name = basename(file.uri) || key\n const mimeType = mimeFilter || file.type || inferMime(name) || OCTET\n const meta = this.commitFile(\n packageName,\n key,\n fileName,\n mimeType,\n name,\n payload.meta as Record<string, string | number | boolean> | undefined,\n )\n this.hooks.sendResult(packageName, requestId, true, meta)\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.BLOB_IMPORT_FAILED, err)\n }\n }\n\n // ---- read ----------------------------------------------------------------\n\n handleGet(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const meta = this.readMeta(packageName, key)\n if (!meta || !this.fileFor(packageName, meta.fileName).exists) {\n if (meta) this.dropMeta(packageName, meta) // reconcile dangling meta\n this.hooks.sendResult(packageName, requestId, true, null)\n return\n }\n this.hooks.sendResult(packageName, requestId, true, this.toBlobMeta(packageName, meta))\n }\n\n handleList(packageName: string, _payload: Record<string, unknown>, requestId?: string): void {\n const blobs = this.allMeta(packageName)\n .filter((m) => this.fileFor(packageName, m.fileName).exists)\n .sort((a, b) => b.createdAt - a.createdAt)\n .map((m) => this.toBlobMeta(packageName, m))\n this.hooks.sendResult(packageName, requestId, true, {blobs})\n }\n\n handleUsage(packageName: string, _payload: Record<string, unknown>, requestId?: string): void {\n const metas = this.allMeta(packageName)\n this.hooks.sendResult(packageName, requestId, true, {\n bytes: metas.reduce((s, m) => s + (m.bytes || 0), 0),\n count: metas.length,\n quotaBytes: BLOB_QUOTA_BYTES,\n })\n }\n\n handleDelete(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const meta = this.readMeta(packageName, payload.key as string)\n if (meta) this.dropMeta(packageName, meta)\n this.hooks.sendResult(packageName, requestId, true)\n }\n\n handleClear(packageName: string, _payload: Record<string, unknown>, requestId?: string): void {\n try {\n // Abort any in-flight uploads / open readers first so nothing keeps writing\n // to a .part file in the directory we're about to delete.\n this.closeAppHandles(packageName)\n for (const m of this.allMeta(packageName)) mmkvStorage.remove(this.metaKey(packageName, m.key))\n const dir = this.dirFor(packageName)\n try {\n if (dir.exists) dir.delete()\n } catch {\n /* best-effort */\n }\n this.usageCache.set(this.currentIdentity(packageName).scope, 0)\n this.hooks.sendResult(packageName, requestId, true)\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, err)\n }\n }\n\n handleOpenRead(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const key = payload.key as string\n const meta = this.readMeta(packageName, key)\n const file = meta ? this.fileFor(packageName, meta.fileName) : null\n if (!meta || !file || !file.exists) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_NOT_FOUND,\n message: `Blob ${key} not found`,\n })\n return\n }\n try {\n const handle = file.open()\n const handleId = `r_${this.makeId()}`\n this.readers.set(handleId, {packageName, handle, remaining: meta.bytes})\n this.hooks.sendResult(packageName, requestId, true, {handle: handleId, meta: this.toBlobMeta(packageName, meta)})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, err)\n }\n }\n\n handleRead(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const handleId = payload.handle as string\n const reader = this.readers.get(handleId)\n if (!reader || reader.packageName !== packageName) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_HANDLE_INVALID,\n message: \"Unknown blob read handle\",\n })\n return\n }\n try {\n const want = Math.max(0, Math.min(Number(payload.maxBytes) || 1024 * 1024, reader.remaining))\n const bytes = want > 0 ? reader.handle.readBytes(want) : new Uint8Array(0)\n reader.remaining -= bytes.length\n const done = reader.remaining <= 0\n const base64 = bytes.length\n ? Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString(\"base64\")\n : \"\"\n if (done) {\n try {\n reader.handle.close()\n } catch {\n /* ignore */\n }\n this.readers.delete(handleId)\n }\n this.hooks.sendResult(packageName, requestId, true, {base64, done})\n } catch (err) {\n this.fail(packageName, requestId, MiniappErrorCode.INTERNAL, err)\n }\n }\n\n handleCloseRead(packageName: string, payload: Record<string, unknown>, requestId?: string): void {\n const handleId = payload.handle as string\n const reader = this.readers.get(handleId)\n if (reader && reader.packageName === packageName) {\n try {\n reader.handle.close()\n } catch {\n /* ignore */\n }\n this.readers.delete(handleId)\n }\n this.hooks.sendResult(packageName, requestId, true)\n }\n\n // ---- share ---------------------------------------------------------------\n\n async handleShare(packageName: string, payload: Record<string, unknown>, requestId?: string): Promise<void> {\n const key = payload.key as string\n const meta = this.readMeta(packageName, key)\n const file = meta ? this.fileFor(packageName, meta.fileName) : null\n if (!meta || !file || !file.exists) {\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code: MiniappErrorCode.BLOB_NOT_FOUND,\n message: `Blob ${key} not found`,\n })\n return\n }\n // The on-disk blob name is a generated id (mime extension attached at\n // commit; legacy blobs may lack it). react-native-share derives the shared\n // file's name + extension from the URL's path (its `filename` option only\n // applies to base64/data payloads, not file:// URLs), so sharing `file.uri`\n // directly would hand the recipient a machine-named file. Copy to a temp\n // file that carries the real display name + extension, share that, then\n // clean it up.\n const shareName = shareFileName(meta)\n // Copy into a per-share unique subdir so two concurrent shares that resolve\n // to the same display name can't clobber each other's temp file while\n // Share.open still references it. The file keeps `shareName` as its basename\n // so the OS share sheet shows the right name + extension.\n let tempDir: Directory | null = null\n try {\n tempDir = new Directory(Paths.cache, SHARE_DIR_NAME, this.makeId())\n tempDir.create({intermediates: true})\n const temp = new File(tempDir, shareName)\n file.copy(temp)\n await Share.open({\n url: temp.uri,\n type: meta.mimeType || OCTET,\n filename: shareName,\n })\n this.hooks.sendResult(packageName, requestId, true, {success: true})\n } catch (error: any) {\n if (error?.message?.includes(\"User did not share\")) {\n this.hooks.sendResult(packageName, requestId, true, {success: false, cancelled: true})\n } else {\n console.error(`${LOG_TAG}: blob share error:`, error)\n this.hooks.sendResult(packageName, requestId, true, {success: false})\n }\n } finally {\n if (tempDir) {\n try {\n if (tempDir.exists) tempDir.delete()\n } catch {\n /* ignore */\n }\n }\n }\n }\n\n // ---- lifecycle / cleanup -------------------------------------------------\n\n /** Called from LocalMiniappRuntime.unregisterApp — drop this app's in-flight state. */\n onAppGone(packageName: string): void {\n this.closeAppHandles(packageName)\n }\n\n /** Abort in-flight uploads + close open read handles for an app (no-op if none). */\n private closeAppHandles(packageName: string): void {\n for (const [k, up] of this.uploads) {\n if (up.packageName === packageName) {\n this.discardUpload(up)\n this.uploads.delete(k)\n }\n }\n for (const [k, reader] of this.readers) {\n if (reader.packageName === packageName) {\n try {\n reader.handle.close()\n } catch {\n /* ignore */\n }\n this.readers.delete(k)\n }\n }\n }\n\n private discardUpload(up: ActiveUpload): void {\n try {\n up.handle.close()\n } catch {\n /* ignore */\n }\n try {\n if (up.partFile.exists) up.partFile.delete()\n } catch {\n /* ignore */\n }\n }\n\n private dropMeta(packageName: string, meta: StoredBlobMeta): void {\n this.deleteFileQuiet(packageName, meta.fileName)\n mmkvStorage.remove(this.metaKey(packageName, meta.key))\n this.bumpUsage(packageName, -(meta.bytes || 0))\n }\n\n private deleteFileQuiet(packageName: string, fileName: string): void {\n try {\n const f = this.fileFor(packageName, fileName)\n if (f.exists) f.delete()\n } catch {\n /* ignore */\n }\n }\n\n private fail(packageName: string, requestId: string | undefined, code: MiniappErrorCode, err: unknown): void {\n console.error(`${LOG_TAG}: blob error [${code}]:`, err)\n this.hooks.sendResult(packageName, requestId, false, undefined, {\n code,\n message: err instanceof Error ? err.message : \"Blob error\",\n })\n }\n}\n\nconst OCTET = \"application/octet-stream\"\n\n/** Last path segment of a URL/URI, query stripped + percent-decoded. */\nfunction basename(uri: string): string {\n const noQuery = uri.split(\"?\")[0].split(\"#\")[0]\n const seg = noQuery.substring(noQuery.lastIndexOf(\"/\") + 1)\n try {\n return decodeURIComponent(seg)\n } catch {\n return seg\n }\n}\n\n/** Best-effort MIME from a filename extension. Returns undefined when unknown. */\nfunction inferMime(name: string): string | undefined {\n const dot = name.lastIndexOf(\".\")\n if (dot < 0) return undefined\n const ext = name.slice(dot + 1).toLowerCase()\n const map: Record<string, string> = {\n pdf: \"application/pdf\",\n epub: \"application/epub+zip\",\n zip: \"application/zip\",\n json: \"application/json\",\n txt: \"text/plain\",\n csv: \"text/csv\",\n html: \"text/html\",\n mp4: \"video/mp4\",\n mov: \"video/quicktime\",\n webm: \"video/webm\",\n mp3: \"audio/mpeg\",\n m4a: \"audio/mp4\",\n wav: \"audio/wav\",\n ogg: \"audio/ogg\",\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n }\n return map[ext]\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CloudAudioSubscriptionSync.d.ts","sourceRoot":"","sources":["../../src/services/CloudAudioSubscriptionSync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,0BAA0B;IACrC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAAK;IAEhB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;
|
|
1
|
+
{"version":3,"file":"CloudAudioSubscriptionSync.d.ts","sourceRoot":"","sources":["../../src/services/CloudAudioSubscriptionSync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,0BAA0B;IACrC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAAK;IAEhB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAoB/B,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAO5B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAKjC"}
|
|
@@ -18,7 +18,19 @@ export class CloudAudioSubscriptionSync {
|
|
|
18
18
|
lastAppliedKey = "";
|
|
19
19
|
pendingKey = "";
|
|
20
20
|
begin(nextKey) {
|
|
21
|
-
|
|
21
|
+
// Exact duplicate of the write already in flight — nothing to do.
|
|
22
|
+
if (nextKey === this.pendingKey) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
// Matches the last successfully applied set, but ONLY skip when nothing
|
|
26
|
+
// else is in flight. If a different write is pending (e.g. desired went
|
|
27
|
+
// fr-FR -> [] -> fr-FR while the [] write is still on the wire),
|
|
28
|
+
// lastAppliedKey is stale: it names what was applied BEFORE the in-flight
|
|
29
|
+
// write lands. Skipping here would drop the re-subscribe and strand the
|
|
30
|
+
// cloud on the intermediate (empty) set — captions silently die on any
|
|
31
|
+
// rapid A -> B -> A subscription churn. The cloud's own version counter
|
|
32
|
+
// resolves ordering between the concurrent writes, so sending both is safe.
|
|
33
|
+
if (nextKey === this.lastAppliedKey && this.pendingKey === "") {
|
|
22
34
|
return false;
|
|
23
35
|
}
|
|
24
36
|
this.pendingKey = nextKey;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CloudAudioSubscriptionSync.js","sourceRoot":"","sources":["../../src/services/CloudAudioSubscriptionSync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,0BAA0B;IAC7B,cAAc,GAAG,EAAE,CAAA;IACnB,UAAU,GAAG,EAAE,CAAA;IAEhB,KAAK,CAAC,OAAe;QAC1B,IAAI,OAAO,KAAK,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"CloudAudioSubscriptionSync.js","sourceRoot":"","sources":["../../src/services/CloudAudioSubscriptionSync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,0BAA0B;IAC7B,cAAc,GAAG,EAAE,CAAA;IACnB,UAAU,GAAG,EAAE,CAAA;IAEhB,KAAK,CAAC,OAAe;QAC1B,kEAAkE;QAClE,IAAI,OAAO,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;YAChC,OAAO,KAAK,CAAA;QACd,CAAC;QACD,wEAAwE;QACxE,wEAAwE;QACxE,iEAAiE;QACjE,0EAA0E;QAC1E,wEAAwE;QACxE,uEAAuE;QACvE,wEAAwE;QACxE,4EAA4E;QAC5E,IAAI,OAAO,KAAK,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,UAAU,KAAK,EAAE,EAAE,CAAC;YAC9D,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,OAAO,CAAA;QACzB,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,SAAS,CAAC,GAAW;QAC1B,IAAI,IAAI,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;YAC5B,IAAI,CAAC,UAAU,GAAG,EAAE,CAAA;QACtB,CAAC;QACD,IAAI,CAAC,cAAc,GAAG,GAAG,CAAA;IAC3B,CAAC;IAEM,MAAM,CAAC,GAAW;QACvB,IAAI,IAAI,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;YAC5B,IAAI,CAAC,UAAU,GAAG,EAAE,CAAA;QACtB,CAAC;IACH,CAAC;CACF","sourcesContent":["/**\n * Tracks cloud-audio subscription writes so LocalMiniappRuntime can dedupe\n * successful writes without losing retryability after transient Core/network\n * failures.\n *\n * Failure mode this protects:\n * 1. Local captions subscribes to transcription.\n * 2. The first Cloud V2 `PUT /api/audio/subscriptions` throws while the socket\n * is reconnecting or Core is briefly unreachable.\n * 3. A reconnect/resync recomputes the same desired subscription set.\n *\n * If we mark the set as \"last applied\" before the PUT succeeds, step 3 is\n * incorrectly deduped and captions can wait forever even though Cloud V2 later\n * reconnects. So `begin()` only blocks exact duplicates while a write is in\n * flight; only `succeeded()` promotes that key to the applied state.\n */\nexport class CloudAudioSubscriptionSync {\n private lastAppliedKey = \"\"\n private pendingKey = \"\"\n\n public begin(nextKey: string): boolean {\n // Exact duplicate of the write already in flight — nothing to do.\n if (nextKey === this.pendingKey) {\n return false\n }\n // Matches the last successfully applied set, but ONLY skip when nothing\n // else is in flight. If a different write is pending (e.g. desired went\n // fr-FR -> [] -> fr-FR while the [] write is still on the wire),\n // lastAppliedKey is stale: it names what was applied BEFORE the in-flight\n // write lands. Skipping here would drop the re-subscribe and strand the\n // cloud on the intermediate (empty) set — captions silently die on any\n // rapid A -> B -> A subscription churn. The cloud's own version counter\n // resolves ordering between the concurrent writes, so sending both is safe.\n if (nextKey === this.lastAppliedKey && this.pendingKey === \"\") {\n return false\n }\n this.pendingKey = nextKey\n return true\n }\n\n public succeeded(key: string): void {\n if (this.pendingKey === key) {\n this.pendingKey = \"\"\n }\n this.lastAppliedKey = key\n }\n\n public failed(key: string): void {\n if (this.pendingKey === key) {\n this.pendingKey = \"\"\n }\n }\n}\n"]}
|
|
@@ -39,6 +39,18 @@ export declare const cloudClientService: {
|
|
|
39
39
|
runtime: string;
|
|
40
40
|
} | null): void;
|
|
41
41
|
getPreinstalledMiniappRegistry(): Promise<PreinstalledMiniappRegistry>;
|
|
42
|
+
/**
|
|
43
|
+
* Resolve the stable Core-owned Mentra user id.
|
|
44
|
+
*
|
|
45
|
+
* Storage must use this identity rather than the short-lived Core access
|
|
46
|
+
* token. A previously verified id is restored from MMKV so local miniapps
|
|
47
|
+
* remain available after an offline process restart. On first sign-in,
|
|
48
|
+
* callers join the auth module's single-flight exchange/refresh instead of
|
|
49
|
+
* falling back to an anonymous namespace.
|
|
50
|
+
*/
|
|
51
|
+
resolveMentraUserId(): Promise<string>;
|
|
52
|
+
/** Read the stable Mentra user id after async identity resolution. */
|
|
53
|
+
getMentraUserId(): string;
|
|
42
54
|
getMiniappAuthToken(packageName: string, opts?: {
|
|
43
55
|
minTtlMs?: number;
|
|
44
56
|
devAttestation?: string;
|
|
@@ -136,6 +148,9 @@ export declare const cloudClientService: {
|
|
|
136
148
|
status: import("@mentra/cloud-client").ReportStatus;
|
|
137
149
|
}>;
|
|
138
150
|
};
|
|
151
|
+
supportProfile: {
|
|
152
|
+
update(input: import("@mentra/cloud-client").SupportStateInput): Promise<import("@mentra/cloud-client").SupportProfileUpdateResult>;
|
|
153
|
+
};
|
|
139
154
|
};
|
|
140
155
|
hasAudioSubscriptions(): boolean;
|
|
141
156
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CloudClientService.d.ts","sourceRoot":"","sources":["../../src/services/CloudClientService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAC,WAAW,EAAgD,MAAM,mCAAmC,CAAA;AAC5G,OAAO,KAAK,EAAC,2BAA2B,EAAkB,MAAM,mCAAmC,CAAA;AAGnG,OAAO,KAAK,EAAC,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAC,MAAM,wBAAwB,CAAA;AAMjG,OAAO,EAAC,KAAK,yBAAyB,EAAE,KAAK,gBAAgB,EAAC,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"CloudClientService.d.ts","sourceRoot":"","sources":["../../src/services/CloudClientService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAC,WAAW,EAAgD,MAAM,mCAAmC,CAAA;AAC5G,OAAO,KAAK,EAAC,2BAA2B,EAAkB,MAAM,mCAAmC,CAAA;AAGnG,OAAO,KAAK,EAAC,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAC,MAAM,wBAAwB,CAAA;AAMjG,OAAO,EAAC,KAAK,yBAAyB,EAAE,KAAK,gBAAgB,EAAC,MAAM,mBAAmB,CAAA;AAYvF,KAAK,SAAS,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAA;AAudjD;;;GAGG;AACH,eAAO,MAAM,kBAAkB;IAC7B;;;;OAIG;YACK,IAAI;IAMZ;;;;OAIG;0BACmB;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,GAAG,IAAI,GAAG,IAAI;sCAoB3B,OAAO,CAAC,2BAA2B,CAAC;IAO5E;;;;;;;;OAQG;2BAC0B,OAAO,CAAC,MAAM,CAAC;IAY5C,sEAAsE;uBACnD,MAAM;qCAOV,MAAM,SACZ;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAC,GAClD,OAAO,CAAC,gBAAgB,CAAC;IAe5B,uEAAuE;YAC/D,IAAI;IAuBZ,qFAAqF;6BAC7D,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;sCAIb,MAAM;;;;IAKxC,2EAA2E;8BAClD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;qCAIf,MAAM;;;;;;;;gCAIX,MAAM;IAKlC,mEAAmE;mBACpD,OAAO;IAItB,4EAA4E;iCAC/C,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAOtE,0EAA0E;2BAC7C,iBAAiB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;0BAU1C,UAAU,GAAG,IAAI;qBAItB,CAAC,CAAC,EAAE,iBAAiB,KAAK,IAAI,GAAG,MAAM,IAAI;sBAO1C,CAAC,CAAC,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI;iBAO9C,yBAAyB;kBAIxB,MAAM;gCAIQ,OAAO,CAAC,MAAM,CAAC;wBAIvB,CAAC,QAAQ,EAAE,yBAAyB,KAAK,IAAI,GAAG,MAAM,IAAI;;oBAQhE,MAAM,YAAY,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;;;wBAOnE,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;8BAIrD,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;;;;+BAI9D,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;;;;;;;0BAIvE,UAAU,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;6BA4BxD,OAAO;CAGjC,CAAA"}
|
|
@@ -21,10 +21,12 @@ import { getAuth, getConfigValues } from "../runtime/bootstrap";
|
|
|
21
21
|
import { useSettingsStore, SETTINGS } from "../stores/settings";
|
|
22
22
|
import { createCloudUdpSocket } from "../utils/cloudClient/RnUdpAdapter";
|
|
23
23
|
import { cloudSecureStore } from "../utils/cloudClient/cloudSecureStore";
|
|
24
|
+
import { storage as mmkvStorage } from "../utils/storage";
|
|
24
25
|
import { useCloudClientStatusStore } from "../stores/cloudClientStatus";
|
|
25
26
|
import { islandNotifications } from "./NotificationsEmitter";
|
|
26
27
|
import { BgTimer } from "../utils/timers";
|
|
27
28
|
import { logCloudV2TranscriptMetric } from "./CloudTranscriptE2EMetrics";
|
|
29
|
+
import { LocalMiniappUserIdentity } from "./LocalMiniappUserIdentity";
|
|
28
30
|
import { nativeHttpResponseBody } from "./NativeHttpResponse";
|
|
29
31
|
const LOG_TAG = "cloudClient";
|
|
30
32
|
// Persistent cloud-disconnect detector: the cloud-client reconnect loop is infinite
|
|
@@ -32,6 +34,7 @@ const LOG_TAG = "cloudClient";
|
|
|
32
34
|
// been continuously NOT connected for this long. A quick reconnect cancels it; brief
|
|
33
35
|
// flaps that recover don't fire. Raised as engine.notifications(connection_failed_persistent).
|
|
34
36
|
const CLOUD_PERSISTENT_FAILURE_MS = 60_000;
|
|
37
|
+
const LOCAL_MINIAPP_USER_ID_KEY = "mentra.localMiniapp.userId";
|
|
35
38
|
/** Cancel the pending persistent-failure alarm + re-arm for the next outage. */
|
|
36
39
|
function clearPersistentFailureAlarm() {
|
|
37
40
|
if (persistentFailureTimer) {
|
|
@@ -61,6 +64,22 @@ let authStateUnsubscribe = null;
|
|
|
61
64
|
let localDevRuntimeToken = null;
|
|
62
65
|
let lc3FrameSizeUnsubscribe = null;
|
|
63
66
|
let coreTokenSyncPromise = null;
|
|
67
|
+
const localMiniappUserIdentity = new LocalMiniappUserIdentity({
|
|
68
|
+
get() {
|
|
69
|
+
const result = mmkvStorage.load(LOCAL_MINIAPP_USER_ID_KEY);
|
|
70
|
+
return result.is_ok() ? result.value : null;
|
|
71
|
+
},
|
|
72
|
+
set(userId) {
|
|
73
|
+
const result = mmkvStorage.save(LOCAL_MINIAPP_USER_ID_KEY, userId);
|
|
74
|
+
if (result.is_error())
|
|
75
|
+
throw result.error;
|
|
76
|
+
},
|
|
77
|
+
remove() {
|
|
78
|
+
const result = mmkvStorage.remove(LOCAL_MINIAPP_USER_ID_KEY);
|
|
79
|
+
if (result.is_error())
|
|
80
|
+
throw result.error;
|
|
81
|
+
},
|
|
82
|
+
});
|
|
64
83
|
const transcriptListeners = new Set();
|
|
65
84
|
const translationListeners = new Set();
|
|
66
85
|
const statusListeners = new Set();
|
|
@@ -100,6 +119,7 @@ async function syncCoreAccessTokenToBluetoothInternal() {
|
|
|
100
119
|
if (c !== client) {
|
|
101
120
|
throw new Error("cloud client changed while syncing core token");
|
|
102
121
|
}
|
|
122
|
+
localMiniappUserIdentity.remember(c.auth.identity.mentraUserId);
|
|
103
123
|
const result = await useSettingsStore.getState().setSetting(SETTINGS.core_token.key, token, false);
|
|
104
124
|
if (result.is_error()) {
|
|
105
125
|
throw result.error;
|
|
@@ -238,6 +258,14 @@ function ensureAuthWatch() {
|
|
|
238
258
|
let reconnectPending = false;
|
|
239
259
|
try {
|
|
240
260
|
const sub = auth.onStateChange((event, session) => {
|
|
261
|
+
if (event === "SIGNED_OUT") {
|
|
262
|
+
localMiniappUserIdentity.forget();
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
// A new sign-in may belong to a different account. Force the next
|
|
266
|
+
// storage request to resolve and persist that account's Core identity.
|
|
267
|
+
if (event === "SIGNED_IN")
|
|
268
|
+
localMiniappUserIdentity.forget();
|
|
241
269
|
if (!session?.token)
|
|
242
270
|
return;
|
|
243
271
|
if (connected || reconnectPending)
|
|
@@ -360,6 +388,12 @@ function construct() {
|
|
|
360
388
|
// LC3 at 16 kHz with the frame size the encoder emits.
|
|
361
389
|
audio: { codec: "lc3", sampleRate: 16000, frameSizeBytes: frameSizeBytes() },
|
|
362
390
|
auth,
|
|
391
|
+
timers: {
|
|
392
|
+
setTimeout: (callback, delayMs) => BgTimer.setTimeout(callback, delayMs),
|
|
393
|
+
clearTimeout: (handle) => BgTimer.clearTimeout(handle),
|
|
394
|
+
setInterval: (callback, intervalMs) => BgTimer.setInterval(callback, intervalMs),
|
|
395
|
+
clearInterval: (handle) => BgTimer.clearInterval(handle),
|
|
396
|
+
},
|
|
363
397
|
logger: cloudLogger,
|
|
364
398
|
});
|
|
365
399
|
const c = client;
|
|
@@ -386,6 +420,7 @@ function construct() {
|
|
|
386
420
|
return;
|
|
387
421
|
connected = true;
|
|
388
422
|
console.log(`${LOG_TAG}: runtime connected`);
|
|
423
|
+
console.log(`${LOG_TAG}: debug: ws-session-debug connected`);
|
|
389
424
|
// Cloud is up — cancel any pending persistent-failure alarm and re-arm for the
|
|
390
425
|
// next outage.
|
|
391
426
|
clearPersistentFailureAlarm();
|
|
@@ -401,6 +436,7 @@ function construct() {
|
|
|
401
436
|
return;
|
|
402
437
|
connected = false;
|
|
403
438
|
console.log(`${LOG_TAG}: runtime disconnected (${info.reason})`);
|
|
439
|
+
console.log(`${LOG_TAG}: debug: ws-session-debug disconnected reason=${info.reason} willStayDown=${/superseded by newer session/i.test(info.reason)}`);
|
|
404
440
|
// Arm the persistent-failure alarm once; if we're still down when it fires, raise
|
|
405
441
|
// the notification. A reconnect within the window cancels it (onConnected above).
|
|
406
442
|
if (!persistentFailureTimer && !persistentFailureNotified) {
|
|
@@ -479,6 +515,35 @@ export const cloudClientService = {
|
|
|
479
515
|
throw new Error("cloud client core is unavailable");
|
|
480
516
|
return c.core.miniapps.getRegistry();
|
|
481
517
|
},
|
|
518
|
+
/**
|
|
519
|
+
* Resolve the stable Core-owned Mentra user id.
|
|
520
|
+
*
|
|
521
|
+
* Storage must use this identity rather than the short-lived Core access
|
|
522
|
+
* token. A previously verified id is restored from MMKV so local miniapps
|
|
523
|
+
* remain available after an offline process restart. On first sign-in,
|
|
524
|
+
* callers join the auth module's single-flight exchange/refresh instead of
|
|
525
|
+
* falling back to an anonymous namespace.
|
|
526
|
+
*/
|
|
527
|
+
async resolveMentraUserId() {
|
|
528
|
+
return localMiniappUserIdentity.resolve(async () => {
|
|
529
|
+
if (!client)
|
|
530
|
+
this.init();
|
|
531
|
+
const c = client;
|
|
532
|
+
if (!c)
|
|
533
|
+
throw new Error("cloud client not initialized");
|
|
534
|
+
await c.auth.getCoreToken();
|
|
535
|
+
if (c !== client)
|
|
536
|
+
throw new Error("cloud client changed while resolving user identity");
|
|
537
|
+
return c.auth.identity.mentraUserId;
|
|
538
|
+
});
|
|
539
|
+
},
|
|
540
|
+
/** Read the stable Mentra user id after async identity resolution. */
|
|
541
|
+
getMentraUserId() {
|
|
542
|
+
const userId = localMiniappUserIdentity.get();
|
|
543
|
+
if (!userId)
|
|
544
|
+
throw new Error("Mentra user identity is unavailable");
|
|
545
|
+
return userId;
|
|
546
|
+
},
|
|
482
547
|
async getMiniappAuthToken(packageName, opts) {
|
|
483
548
|
if (!client)
|
|
484
549
|
this.init();
|
|
@@ -508,6 +573,11 @@ export const cloudClientService = {
|
|
|
508
573
|
clearPersistentFailureAlarm();
|
|
509
574
|
const wasConnected = connected;
|
|
510
575
|
client = null;
|
|
576
|
+
// stop() is part of the logout lifecycle and runs before the host emits
|
|
577
|
+
// SIGNED_OUT. Remove the persisted namespace owner here so a later account
|
|
578
|
+
// can never inherit it. A force-stop/process kill does not call stop(), so
|
|
579
|
+
// the cached id still survives the offline cold-start case.
|
|
580
|
+
localMiniappUserIdentity.forget();
|
|
511
581
|
localDevRuntimeToken = null;
|
|
512
582
|
connected = false;
|
|
513
583
|
resetRuntimeStatus();
|
|
@@ -636,6 +706,11 @@ export const cloudClientService = {
|
|
|
636
706
|
return getCoreClient().reports.complete(...args);
|
|
637
707
|
},
|
|
638
708
|
},
|
|
709
|
+
supportProfile: {
|
|
710
|
+
update(...args) {
|
|
711
|
+
return getCoreClient().supportProfile.update(...args);
|
|
712
|
+
},
|
|
713
|
+
},
|
|
639
714
|
},
|
|
640
715
|
hasAudioSubscriptions() {
|
|
641
716
|
return audioSubscriptions.length > 0;
|