@glassly/engine 0.1.0-dev.99 → 0.2.9-beta.448
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 +28 -0
- package/build/engine.d.ts +32 -10
- package/build/engine.d.ts.map +1 -1
- package/build/engine.js +24 -16
- package/build/engine.js.map +1 -1
- package/build/facades/dev.d.ts +9 -0
- package/build/facades/dev.d.ts.map +1 -1
- package/build/facades/dev.js +9 -0
- package/build/facades/dev.js.map +1 -1
- package/build/facades/display.d.ts +10 -3
- package/build/facades/display.d.ts.map +1 -1
- package/build/facades/display.js +22 -8
- package/build/facades/display.js.map +1 -1
- package/build/facades/displayMirror.d.ts +11 -0
- package/build/facades/displayMirror.d.ts.map +1 -1
- package/build/facades/displayMirror.js +22 -0
- package/build/facades/displayMirror.js.map +1 -1
- package/build/facades/glasses.d.ts +31 -1
- package/build/facades/glasses.d.ts.map +1 -1
- package/build/facades/glasses.js +51 -0
- package/build/facades/glasses.js.map +1 -1
- package/build/facades/memory.d.ts +0 -6
- package/build/facades/memory.d.ts.map +1 -1
- package/build/facades/memory.js +1 -9
- package/build/facades/memory.js.map +1 -1
- package/build/facades/miniapps.d.ts +3 -1
- package/build/facades/miniapps.d.ts.map +1 -1
- package/build/facades/miniapps.js +3 -1
- package/build/facades/miniapps.js.map +1 -1
- package/build/facades/pairing.d.ts.map +1 -1
- package/build/facades/pairing.js +5 -4
- package/build/facades/pairing.js.map +1 -1
- package/build/facades/permissions.d.ts +2 -0
- package/build/facades/permissions.d.ts.map +1 -1
- package/build/facades/permissions.js +48 -0
- package/build/facades/permissions.js.map +1 -1
- package/build/facades/phoneNotifications.d.ts +20 -9
- package/build/facades/phoneNotifications.d.ts.map +1 -1
- package/build/facades/phoneNotifications.js +33 -26
- package/build/facades/phoneNotifications.js.map +1 -1
- package/build/facades/settings.d.ts.map +1 -1
- package/build/facades/settings.js +1 -2
- package/build/facades/settings.js.map +1 -1
- package/build/generated/releaseMetadata.js +4 -4
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts +6 -4
- package/build/index.d.ts.map +1 -1
- package/build/index.js +5 -4
- package/build/index.js.map +1 -1
- package/build/react/MentraLiveOtaFlow.js +2 -2
- package/build/react/MentraLiveOtaFlow.js.map +1 -1
- package/build/react/useMentraLiveOta.d.ts.map +1 -1
- package/build/react/useMentraLiveOta.js +8 -7
- package/build/react/useMentraLiveOta.js.map +1 -1
- package/build/runtime/config.d.ts +1 -1
- package/build/runtime/config.d.ts.map +1 -1
- package/build/runtime/config.js.map +1 -1
- package/build/services/AppRegistry.d.ts +4 -1
- package/build/services/AppRegistry.d.ts.map +1 -1
- package/build/services/AppRegistry.js +21 -1
- package/build/services/AppRegistry.js.map +1 -1
- package/build/services/BlobStore.d.ts +2 -2
- package/build/services/BlobStore.js +3 -3
- package/build/services/BlobStore.js.map +1 -1
- package/build/services/CloudClientService.d.ts +7 -3
- package/build/services/CloudClientService.d.ts.map +1 -1
- package/build/services/CloudClientService.js +34 -9
- package/build/services/CloudClientService.js.map +1 -1
- package/build/services/DevServerBridge.d.ts +1 -18
- package/build/services/DevServerBridge.d.ts.map +1 -1
- package/build/services/DevServerBridge.js +9 -8
- package/build/services/DevServerBridge.js.map +1 -1
- package/build/services/DeviceEventRouter.d.ts.map +1 -1
- package/build/services/DeviceEventRouter.js +58 -71
- package/build/services/DeviceEventRouter.js.map +1 -1
- package/build/services/DisplayDiagnostics.d.ts +5 -0
- package/build/services/DisplayDiagnostics.d.ts.map +1 -0
- package/build/services/DisplayDiagnostics.js +105 -0
- package/build/services/DisplayDiagnostics.js.map +1 -0
- package/build/services/DisplayProcessor.d.ts +6 -7
- package/build/services/DisplayProcessor.d.ts.map +1 -1
- package/build/services/DisplayProcessor.js +17 -45
- package/build/services/DisplayProcessor.js.map +1 -1
- package/build/services/GestureDotsService.d.ts +10 -4
- package/build/services/GestureDotsService.d.ts.map +1 -1
- package/build/services/GestureDotsService.js +70 -16
- package/build/services/GestureDotsService.js.map +1 -1
- package/build/services/GlassesKeyboardInput.d.ts +77 -0
- package/build/services/GlassesKeyboardInput.d.ts.map +1 -0
- package/build/services/GlassesKeyboardInput.js +261 -0
- package/build/services/GlassesKeyboardInput.js.map +1 -0
- package/build/services/GlassesSensorService.d.ts +47 -0
- package/build/services/GlassesSensorService.d.ts.map +1 -0
- package/build/services/GlassesSensorService.js +242 -0
- package/build/services/GlassesSensorService.js.map +1 -0
- package/build/services/GlassesTouchInput.d.ts +14 -0
- package/build/services/GlassesTouchInput.d.ts.map +1 -0
- package/build/services/GlassesTouchInput.js +107 -0
- package/build/services/GlassesTouchInput.js.map +1 -0
- package/build/services/HeadingService.d.ts +0 -6
- package/build/services/HeadingService.d.ts.map +1 -1
- package/build/services/HeadingService.js +0 -27
- package/build/services/HeadingService.js.map +1 -1
- package/build/services/HotspotShutdown.d.ts.map +1 -1
- package/build/services/HotspotShutdown.js +2 -1
- package/build/services/HotspotShutdown.js.map +1 -1
- package/build/services/JSCrashloopReportService.js +2 -2
- package/build/services/JSCrashloopReportService.js.map +1 -1
- package/build/services/JSRouter.d.ts +6 -4
- package/build/services/JSRouter.d.ts.map +1 -1
- package/build/services/JSRouter.js +15 -13
- package/build/services/JSRouter.js.map +1 -1
- package/build/services/LocalDisplayManager.d.ts +35 -7
- package/build/services/LocalDisplayManager.d.ts.map +1 -1
- package/build/services/LocalDisplayManager.js +105 -27
- package/build/services/LocalDisplayManager.js.map +1 -1
- package/build/services/LocalMiniappDataMigration.d.ts +1 -1
- package/build/services/LocalMiniappDataMigration.js +1 -1
- package/build/services/LocalMiniappDataMigration.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts +64 -11
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +441 -35
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.d.ts +3 -0
- package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.js +27 -8
- package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
- package/build/services/MemoryStore.d.ts +8 -33
- package/build/services/MemoryStore.d.ts.map +1 -1
- package/build/services/MemoryStore.js +30 -56
- package/build/services/MemoryStore.js.map +1 -1
- package/build/services/MiniappEngine.d.ts +3 -3
- package/build/services/MiniappEngine.js +7 -7
- package/build/services/MiniappEngine.js.map +1 -1
- package/build/services/MiniappLauncher.d.ts +8 -0
- package/build/services/MiniappLauncher.d.ts.map +1 -1
- package/build/services/MiniappLauncher.js +19 -1
- package/build/services/MiniappLauncher.js.map +1 -1
- package/build/services/MirrorService.d.ts +24 -0
- package/build/services/MirrorService.d.ts.map +1 -0
- package/build/services/MirrorService.js +132 -0
- package/build/services/MirrorService.js.map +1 -0
- package/build/services/NativeNavigationService.d.ts +2 -3
- package/build/services/NativeNavigationService.d.ts.map +1 -1
- package/build/services/NativeNavigationService.js +24 -21
- package/build/services/NativeNavigationService.js.map +1 -1
- package/build/services/NavigationHandlers.d.ts.map +1 -1
- package/build/services/NavigationHandlers.js +10 -5
- package/build/services/NavigationHandlers.js.map +1 -1
- package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
- package/build/services/OtaInstallCoordinator.js +24 -23
- package/build/services/OtaInstallCoordinator.js.map +1 -1
- package/build/services/PairedGlassesLatch.d.ts +7 -0
- package/build/services/PairedGlassesLatch.d.ts.map +1 -0
- package/build/services/PairedGlassesLatch.js +38 -0
- package/build/services/PairedGlassesLatch.js.map +1 -0
- package/build/services/PhoneActivity.d.ts +23 -0
- package/build/services/PhoneActivity.d.ts.map +1 -0
- package/build/services/PhoneActivity.js +111 -0
- package/build/services/PhoneActivity.js.map +1 -0
- package/build/services/PhoneCameraFovCoordinator.d.ts.map +1 -1
- package/build/services/PhoneCameraFovCoordinator.js +4 -3
- package/build/services/PhoneCameraFovCoordinator.js.map +1 -1
- package/build/services/PhoneNotificationsSync.d.ts +40 -6
- package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
- package/build/services/PhoneNotificationsSync.js +160 -84
- package/build/services/PhoneNotificationsSync.js.map +1 -1
- package/build/services/PhonePhotoCoordinator.d.ts.map +1 -1
- package/build/services/PhonePhotoCoordinator.js +6 -5
- package/build/services/PhonePhotoCoordinator.js.map +1 -1
- package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
- package/build/services/PhoneStreamCoordinator.js +8 -7
- package/build/services/PhoneStreamCoordinator.js.map +1 -1
- package/build/services/STTModelManager.d.ts +3 -0
- package/build/services/STTModelManager.d.ts.map +1 -1
- package/build/services/STTModelManager.js +15 -1
- package/build/services/STTModelManager.js.map +1 -1
- package/build/services/SceneRenderer.d.ts +43 -2
- package/build/services/SceneRenderer.d.ts.map +1 -1
- package/build/services/SceneRenderer.js +123 -8
- package/build/services/SceneRenderer.js.map +1 -1
- package/build/services/StreamLifecycleController.d.ts.map +1 -1
- package/build/services/StreamLifecycleController.js +6 -14
- package/build/services/StreamLifecycleController.js.map +1 -1
- package/build/services/TTSModelManager.js +1 -1
- package/build/services/TTSModelManager.js.map +1 -1
- package/build/services/UIRouter.d.ts +2 -2
- package/build/services/UIRouter.js +5 -5
- package/build/services/UIRouter.js.map +1 -1
- package/build/services/asg/galleryPathMigration.js +1 -1
- package/build/services/asg/galleryPathMigration.js.map +1 -1
- package/build/services/asg/gallerySyncService.js +2 -2
- package/build/services/asg/gallerySyncService.js.map +1 -1
- package/build/services/asg/localStorageService.d.ts.map +1 -1
- package/build/services/asg/localStorageService.js +3 -3
- package/build/services/asg/localStorageService.js.map +1 -1
- package/build/services/debug/DashboardOpenTrace.d.ts +32 -0
- package/build/services/debug/DashboardOpenTrace.d.ts.map +1 -0
- package/build/services/debug/DashboardOpenTrace.js +128 -0
- package/build/services/debug/DashboardOpenTrace.js.map +1 -0
- package/build/services/debug/dashboardOpenTimeline.d.ts +77 -0
- package/build/services/debug/dashboardOpenTimeline.d.ts.map +1 -0
- package/build/services/debug/dashboardOpenTimeline.js +195 -0
- package/build/services/debug/dashboardOpenTimeline.js.map +1 -0
- package/build/services/effectiveCapabilities.d.ts.map +1 -1
- package/build/services/effectiveCapabilities.js +25 -13
- package/build/services/effectiveCapabilities.js.map +1 -1
- package/build/services/gestureClaims.d.ts +34 -15
- package/build/services/gestureClaims.d.ts.map +1 -1
- package/build/services/gestureClaims.js +42 -21
- package/build/services/gestureClaims.js.map +1 -1
- package/build/services/manifestFields.d.ts +9 -0
- package/build/services/manifestFields.d.ts.map +1 -0
- package/build/services/manifestFields.js +26 -0
- package/build/services/manifestFields.js.map +1 -0
- package/build/services/memoryStoreInstance.d.ts +0 -10
- package/build/services/memoryStoreInstance.d.ts.map +1 -1
- package/build/services/memoryStoreInstance.js +2 -31
- package/build/services/memoryStoreInstance.js.map +1 -1
- package/build/services/mirrorSnapshot.d.ts +16 -0
- package/build/services/mirrorSnapshot.d.ts.map +1 -0
- package/build/services/mirrorSnapshot.js +102 -0
- package/build/services/mirrorSnapshot.js.map +1 -0
- package/build/services/nativeNavigationGate.d.ts +8 -0
- package/build/services/nativeNavigationGate.d.ts.map +1 -0
- package/build/services/nativeNavigationGate.js +12 -0
- package/build/services/nativeNavigationGate.js.map +1 -0
- package/build/services/notificationAppCatalog.d.ts +7 -0
- package/build/services/notificationAppCatalog.d.ts.map +1 -0
- package/build/services/notificationAppCatalog.js +16 -0
- package/build/services/notificationAppCatalog.js.map +1 -0
- package/build/services/notifications/notificationPolicy.d.ts +55 -0
- package/build/services/notifications/notificationPolicy.d.ts.map +1 -0
- package/build/services/notifications/notificationPolicy.js +41 -0
- package/build/services/notifications/notificationPolicy.js.map +1 -0
- package/build/services/pages/OverlayPages.d.ts +26 -0
- package/build/services/pages/OverlayPages.d.ts.map +1 -0
- package/build/services/pages/OverlayPages.js +80 -0
- package/build/services/pages/OverlayPages.js.map +1 -0
- package/build/services/pages/PageHost.d.ts +32 -0
- package/build/services/pages/PageHost.d.ts.map +1 -0
- package/build/services/pages/PageHost.js +99 -0
- package/build/services/pages/PageHost.js.map +1 -0
- package/build/services/pages/overlayApps.d.ts +25 -0
- package/build/services/pages/overlayApps.d.ts.map +1 -0
- package/build/services/pages/overlayApps.js +66 -0
- package/build/services/pages/overlayApps.js.map +1 -0
- package/build/services/pages/pageEligibility.d.ts +9 -0
- package/build/services/pages/pageEligibility.d.ts.map +1 -0
- package/build/services/pages/pageEligibility.js +27 -0
- package/build/services/pages/pageEligibility.js.map +1 -0
- package/build/services/settingsBridge.d.ts +58 -0
- package/build/services/settingsBridge.d.ts.map +1 -0
- package/build/services/settingsBridge.js +90 -0
- package/build/services/settingsBridge.js.map +1 -0
- package/build/services/speakerProfileStoreInstance.js +1 -1
- package/build/services/speakerProfileStoreInstance.js.map +1 -1
- package/build/services/uiShim.d.ts +1 -1
- package/build/services/uiShim.js +4 -4
- package/build/services/uiShim.js.map +1 -1
- package/build/stores/appVisibility.d.ts +28 -0
- package/build/stores/appVisibility.d.ts.map +1 -1
- package/build/stores/appVisibility.js +34 -0
- package/build/stores/appVisibility.js.map +1 -1
- package/build/stores/apps.d.ts +13 -0
- package/build/stores/apps.d.ts.map +1 -1
- package/build/stores/apps.js +66 -12
- package/build/stores/apps.js.map +1 -1
- package/build/stores/bluetoothSettingKeys.js +1 -1
- package/build/stores/bluetoothSettingKeys.js.map +1 -1
- package/build/stores/display.d.ts +3 -3
- package/build/stores/display.d.ts.map +1 -1
- package/build/stores/display.js +16 -4
- package/build/stores/display.js.map +1 -1
- package/build/stores/glasses.d.ts.map +1 -1
- package/build/stores/glasses.js +14 -1
- package/build/stores/glasses.js.map +1 -1
- package/build/stores/settings.d.ts +1 -0
- package/build/stores/settings.d.ts.map +1 -1
- package/build/stores/settings.js +170 -44
- package/build/stores/settings.js.map +1 -1
- package/build/types/applet.d.ts +14 -1
- package/build/types/applet.d.ts.map +1 -1
- package/build/types/applet.js.map +1 -1
- package/build/types/capabilities/even-realities-g2.d.ts.map +1 -1
- package/build/types/capabilities/even-realities-g2.js +5 -0
- package/build/types/capabilities/even-realities-g2.js.map +1 -1
- package/build/types/capabilities/simulated-glasses.d.ts +1 -1
- package/build/types/capabilities/simulated-glasses.d.ts.map +1 -1
- package/build/types/capabilities/simulated-glasses.js +7 -4
- package/build/types/capabilities/simulated-glasses.js.map +1 -1
- package/build/types/hardware.d.ts +20 -1
- package/build/types/hardware.d.ts.map +1 -1
- package/build/types/hardware.js +2 -0
- package/build/types/hardware.js.map +1 -1
- package/build/types/index.d.ts +1 -0
- package/build/types/index.d.ts.map +1 -1
- package/build/types/index.js +1 -0
- package/build/types/index.js.map +1 -1
- package/build/utils/debouncedPatch.d.ts +3 -1
- package/build/utils/debouncedPatch.d.ts.map +1 -1
- package/build/utils/debouncedPatch.js +6 -3
- package/build/utils/debouncedPatch.js.map +1 -1
- package/build/utils/devMiniappLaunch.d.ts.map +1 -1
- package/build/utils/devMiniappLaunch.js +4 -3
- package/build/utils/devMiniappLaunch.js.map +1 -1
- package/build/utils/display/measurer/TextMeasurer.d.ts +2 -159
- package/build/utils/display/measurer/TextMeasurer.d.ts.map +1 -1
- package/build/utils/display/measurer/TextMeasurer.js +2 -272
- package/build/utils/display/measurer/TextMeasurer.js.map +1 -1
- package/build/utils/display/measurer/script-detection.d.ts +1 -52
- package/build/utils/display/measurer/script-detection.d.ts.map +1 -1
- package/build/utils/display/measurer/script-detection.js +2 -183
- package/build/utils/display/measurer/script-detection.js.map +1 -1
- package/build/utils/display/pixelArt.d.ts +3 -0
- package/build/utils/display/pixelArt.d.ts.map +1 -0
- package/build/utils/display/pixelArt.js +3 -0
- package/build/utils/display/pixelArt.js.map +1 -0
- package/build/utils/display/profiles/g1.d.ts +1 -32
- package/build/utils/display/profiles/g1.d.ts.map +1 -1
- package/build/utils/display/profiles/g1.js +2 -212
- package/build/utils/display/profiles/g1.js.map +1 -1
- package/build/utils/display/profiles/g2.d.ts +1 -12
- package/build/utils/display/profiles/g2.d.ts.map +1 -1
- package/build/utils/display/profiles/g2.js +2 -33
- package/build/utils/display/profiles/g2.js.map +1 -1
- package/build/utils/display/profiles/nex.d.ts +1 -9
- package/build/utils/display/profiles/nex.d.ts.map +1 -1
- package/build/utils/display/profiles/nex.js +2 -149
- package/build/utils/display/profiles/nex.js.map +1 -1
- package/build/utils/display/profiles/types.d.ts +1 -102
- package/build/utils/display/profiles/types.d.ts.map +1 -1
- package/build/utils/display/profiles/types.js.map +1 -1
- package/build/utils/display/profiles/z100.d.ts +1 -32
- package/build/utils/display/profiles/z100.d.ts.map +1 -1
- package/build/utils/display/profiles/z100.js +2 -181
- package/build/utils/display/profiles/z100.js.map +1 -1
- package/build/utils/display/scene/degrade.d.ts.map +1 -1
- package/build/utils/display/scene/degrade.js +4 -1
- package/build/utils/display/scene/degrade.js.map +1 -1
- package/build/utils/display/scene/differ.d.ts +13 -1
- package/build/utils/display/scene/differ.d.ts.map +1 -1
- package/build/utils/display/scene/differ.js +22 -0
- package/build/utils/display/scene/differ.js.map +1 -1
- package/build/utils/display/scene/index.d.ts +1 -1
- package/build/utils/display/scene/index.d.ts.map +1 -1
- package/build/utils/display/scene/index.js.map +1 -1
- package/build/utils/display/scene/process.d.ts.map +1 -1
- package/build/utils/display/scene/process.js +183 -11
- package/build/utils/display/scene/process.js.map +1 -1
- package/build/utils/display/scene/store.d.ts +1 -1
- package/build/utils/display/scene/store.d.ts.map +1 -1
- package/build/utils/display/scene/store.js +0 -0
- package/build/utils/display/scene/store.js.map +1 -1
- package/build/utils/display/scene/svgPath.d.ts +9 -0
- package/build/utils/display/scene/svgPath.d.ts.map +1 -0
- package/build/utils/display/scene/svgPath.js +167 -0
- package/build/utils/display/scene/svgPath.js.map +1 -0
- package/build/utils/display/scene/types.d.ts +2 -142
- package/build/utils/display/scene/types.d.ts.map +1 -1
- package/build/utils/display/scene/types.js +0 -0
- package/build/utils/display/scene/types.js.map +1 -1
- package/build/utils/display/wrapper/TextWrapper.d.ts +1 -101
- package/build/utils/display/wrapper/TextWrapper.d.ts.map +1 -1
- package/build/utils/display/wrapper/TextWrapper.js +2 -470
- package/build/utils/display/wrapper/TextWrapper.js.map +1 -1
- package/build/utils/display/wrapper/types.d.ts +2 -74
- package/build/utils/display/wrapper/types.d.ts.map +1 -1
- package/build/utils/display/wrapper/types.js +2 -10
- package/build/utils/display/wrapper/types.js.map +1 -1
- package/build/utils/hardware/hardware.js +1 -1
- package/build/utils/hardware/hardware.js.map +1 -1
- package/build/utils/timers/timers.d.ts.map +1 -1
- package/build/utils/timers/timers.js +26 -4
- package/build/utils/timers/timers.js.map +1 -1
- package/package.json +8 -8
- package/src/engine.ts +24 -15
- package/src/facades/dev.ts +10 -0
- package/src/facades/display.ts +21 -8
- package/src/facades/displayMirror.ts +29 -0
- package/src/facades/glasses.ts +61 -1
- package/src/facades/memory.ts +1 -12
- package/src/facades/miniapps.ts +4 -1
- package/src/facades/pairing.ts +8 -6
- package/src/facades/permissions.ts +46 -0
- package/src/facades/phoneNotifications.ts +45 -26
- package/src/facades/settings.ts +1 -2
- package/src/generated/releaseMetadata.ts +4 -4
- package/src/index.ts +6 -9
- package/src/react/MentraLiveOtaFlow.tsx +2 -2
- package/src/react/useMentraLiveOta.ts +14 -8
- package/src/runtime/config.ts +1 -1
- package/src/services/AppRegistry.ts +43 -7
- package/src/services/BlobStore.ts +3 -3
- package/src/services/CloudClientService.ts +37 -10
- package/src/services/DevServerBridge.ts +12 -10
- package/src/services/DeviceEventRouter.ts +73 -74
- package/src/services/DisplayDiagnostics.ts +107 -0
- package/src/services/DisplayProcessor.ts +20 -55
- package/src/services/GestureDotsService.ts +77 -16
- package/src/services/GlassesKeyboardInput.ts +306 -0
- package/src/services/GlassesSensorService.ts +233 -0
- package/src/services/GlassesTouchInput.ts +128 -0
- package/src/services/HeadingService.ts +0 -24
- package/src/services/HotspotShutdown.ts +3 -1
- package/src/services/JSCrashloopReportService.ts +2 -2
- package/src/services/JSRouter.ts +29 -14
- package/src/services/LocalDisplayManager.ts +112 -26
- package/src/services/LocalMiniappDataMigration.ts +1 -1
- package/src/services/LocalMiniappRuntime.ts +500 -43
- package/src/services/LocalSttFallbackCoordinator.ts +28 -7
- package/src/services/MemoryStore.ts +32 -80
- package/src/services/MiniappEngine.ts +7 -7
- package/src/services/MiniappLauncher.ts +25 -1
- package/src/services/MirrorService.ts +139 -0
- package/src/services/NativeNavigationService.ts +29 -25
- package/src/services/NavigationHandlers.ts +10 -5
- package/src/services/OtaInstallCoordinator.ts +36 -34
- package/src/services/PairedGlassesLatch.ts +39 -0
- package/src/services/PhoneActivity.ts +116 -0
- package/src/services/PhoneCameraFovCoordinator.ts +6 -4
- package/src/services/PhoneNotificationsSync.ts +185 -103
- package/src/services/PhonePhotoCoordinator.ts +9 -10
- package/src/services/PhoneStreamCoordinator.ts +13 -11
- package/src/services/STTModelManager.ts +15 -1
- package/src/services/SceneRenderer.ts +148 -10
- package/src/services/StreamLifecycleController.ts +9 -7
- package/src/services/TTSModelManager.ts +1 -1
- package/src/services/UIRouter.ts +5 -5
- package/src/services/asg/galleryPathMigration.ts +1 -1
- package/src/services/asg/gallerySyncService.ts +2 -2
- package/src/services/asg/localStorageService.ts +3 -3
- package/src/services/debug/DashboardOpenTrace.ts +153 -0
- package/src/services/debug/dashboardOpenTimeline.ts +237 -0
- package/src/services/effectiveCapabilities.ts +32 -13
- package/src/services/gestureClaims.ts +72 -23
- package/src/services/manifestFields.ts +23 -0
- package/src/services/memoryStoreInstance.ts +2 -34
- package/src/services/mirrorSnapshot.ts +116 -0
- package/src/services/nativeNavigationGate.ts +14 -0
- package/src/services/notificationAppCatalog.ts +21 -0
- package/src/services/notifications/notificationPolicy.ts +87 -0
- package/src/services/pages/OverlayPages.ts +86 -0
- package/src/services/pages/PageHost.ts +116 -0
- package/src/services/pages/overlayApps.ts +72 -0
- package/src/services/pages/pageEligibility.ts +30 -0
- package/src/services/settingsBridge.ts +111 -0
- package/src/services/speakerProfileStoreInstance.ts +1 -1
- package/src/services/uiShim.ts +4 -4
- package/src/stores/appVisibility.ts +45 -0
- package/src/stores/apps.ts +110 -32
- package/src/stores/bluetoothSettingKeys.ts +1 -1
- package/src/stores/display.ts +18 -7
- package/src/stores/glasses.ts +15 -1
- package/src/stores/settings.ts +175 -51
- package/src/types/applet.ts +14 -1
- package/src/types/capabilities/even-realities-g2.ts +6 -0
- package/src/types/capabilities/simulated-glasses.ts +8 -4
- package/src/types/hardware.ts +34 -1
- package/src/types/index.ts +1 -0
- package/src/utils/debouncedPatch.ts +8 -4
- package/src/utils/devMiniappLaunch.ts +5 -3
- package/src/utils/display/measurer/TextMeasurer.ts +3 -346
- package/src/utils/display/measurer/script-detection.ts +10 -218
- package/src/utils/display/pixelArt.ts +3 -0
- package/src/utils/display/profiles/g1.ts +2 -236
- package/src/utils/display/profiles/g2.ts +2 -39
- package/src/utils/display/profiles/nex.ts +2 -166
- package/src/utils/display/profiles/types.ts +9 -132
- package/src/utils/display/profiles/z100.ts +2 -198
- package/src/utils/display/scene/degrade.ts +4 -1
- package/src/utils/display/scene/differ.ts +25 -1
- package/src/utils/display/scene/index.ts +5 -0
- package/src/utils/display/scene/process.ts +196 -13
- package/src/utils/display/scene/store.ts +0 -0
- package/src/utils/display/scene/svgPath.ts +163 -0
- package/src/utils/display/scene/types.ts +0 -0
- package/src/utils/display/wrapper/TextWrapper.ts +2 -546
- package/src/utils/display/wrapper/types.ts +3 -102
- package/src/utils/hardware/hardware.ts +1 -1
- package/src/utils/timers/timers.ts +32 -4
- package/build/services/CustomDashboardModel.d.ts +0 -48
- package/build/services/CustomDashboardModel.d.ts.map +0 -1
- package/build/services/CustomDashboardModel.js +0 -73
- package/build/services/CustomDashboardModel.js.map +0 -1
- package/build/services/CustomDashboardService.d.ts +0 -63
- package/build/services/CustomDashboardService.d.ts.map +0 -1
- package/build/services/CustomDashboardService.js +0 -576
- package/build/services/CustomDashboardService.js.map +0 -1
- package/build/services/DashboardCoordinator.d.ts +0 -26
- package/build/services/DashboardCoordinator.d.ts.map +0 -1
- package/build/services/DashboardCoordinator.js +0 -125
- package/build/services/DashboardCoordinator.js.map +0 -1
- package/build/services/iosNotificationAppCatalog.d.ts +0 -13
- package/build/services/iosNotificationAppCatalog.d.ts.map +0 -1
- package/build/services/iosNotificationAppCatalog.js +0 -28
- package/build/services/iosNotificationAppCatalog.js.map +0 -1
- package/src/services/CustomDashboardModel.ts +0 -83
- package/src/services/CustomDashboardService.ts +0 -598
- package/src/services/DashboardCoordinator.ts +0 -121
- package/src/services/iosNotificationAppCatalog.ts +0 -39
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MemoryStore.js","sourceRoot":"","sources":["../../src/services/MemoryStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MemoryStore — the user's shared, phone-local memory timeline.\n *\n * One unified per-hour stream of what happened around the user — spoken\n * transcript lines AND notes (manual, voice, auto) in one timeline — plus the\n * hourly conversation summary that heads each session. Scoped to the Glassly\n * USER (not to a miniapp): every miniapp that declares the MEMORY manifest\n * permission reads and writes the same store through LocalMiniappRuntime's\n * MEMORY_* handlers, and Settings > Memory manages it via engine.memory.\n *\n * A \"session\" is one clock hour that has entries, derived from entry\n * timestamps at read time — nothing is stored per-session, so there is no\n * session id to keep in sync.\n *\n * The store began life inside the Assist miniapp (its SessionStore); on first\n * load it migrates Assist's per-app storage namespace into the shared\n * user-scoped keys so existing history survives the move.\n */\n\nimport type {MemoryEntry, MemoryNoteSource, MemorySession, MemorySummary} from \"@glassly/miniapp\"\n\nimport {searchMemoryEntries} from \"../utils/memory/search\"\n\nconst KEY_ROOT = \"memory_\"\nconst LOG_SUFFIX = \"log\"\nconst SUMMARY_SUFFIX = \"summaries\"\n\n/** The pre-memory-layer Assist miniapp whose storage namespace we migrate. */\nconst LEGACY_ASSIST_PACKAGE = \"com.tetramo.assistant\"\nconst LEGACY_STORAGE_ROOT = \"localstorage_\"\nconst LEGACY_LOG_KEY = \"assistant:session-log\"\nconst LEGACY_SUMMARY_KEY = \"assistant:hourly-summaries\"\n// Assist's own pre-unification keys, migrated for users who never ran the\n// unified-schema Assist build.\nconst LEGACY_TRANSCRIPT_KEY = \"assistant:transcript-log\"\nconst LEGACY_NOTES_KEY = \"assistant:notes\"\n\nconst HOUR_MS = 60 * 60 * 1000\nconst DAY_MS = 24 * HOUR_MS\n\n/**\n * How much timeline a tier can SEE. Retention gating is a read window, not a\n * delete: pruning always keeps {@link EXTENDED_RETENTION}'s worth of data, and\n * the active policy decides how far back reads reach. A lapsed subscriber's\n * older timeline is frozen, not lost — upgrading again restores it instantly.\n */\nexport interface MemoryRetentionPolicy {\n maxAgeMs: number\n maxEntries: number\n maxSummaries: number\n}\n\n/** Free-tier visibility: a 14-day rolling window. */\nexport const STANDARD_RETENTION: MemoryRetentionPolicy = {\n maxAgeMs: 14 * DAY_MS,\n maxEntries: 4000,\n maxSummaries: 24 * 14,\n}\n\n/**\n * Plus/Pro visibility — and the store's PHYSICAL bounds for every tier. The\n * entry cap also bounds the write cost — every persist re-serializes the\n * whole timeline, so this cap is a perf ceiling as much as a product number.\n */\nexport const EXTENDED_RETENTION: MemoryRetentionPolicy = {\n maxAgeMs: 180 * DAY_MS,\n maxEntries: 24_000,\n maxSummaries: 24 * 180,\n}\nconst QUERY_LIMIT_CAP = 200\nconst QUERY_LIMIT_DEFAULT = 60\n/**\n * How long transcript appends coalesce before hitting disk. Each write\n * re-serializes the entire timeline, so at conversational pace (a final\n * utterance every few seconds) this turns O(n) work per line into O(n) per\n * window. Short enough that an unexpected kill loses only the last few lines.\n */\nconst DEFAULT_WRITE_DEBOUNCE_MS = 3000\n\nexport interface MemoryStoreBackend {\n get(key: string): unknown | null\n set(key: string, value: unknown): void\n remove(key: string): void\n}\n\nexport interface MemoryStoreHooks {\n getUserId: () => Promise<string>\n backend: MemoryStoreBackend\n /**\n * Debounce window for transcript-line writes, in ms. Appends coalesce into\n * one serialization instead of re-stringifying the whole timeline per\n * utterance. Set to 0 to persist synchronously (tests).\n */\n writeDebounceMs?: number\n /**\n * Visibility policy resolver, consulted at every read. A function (not a\n * value) so the host can flip between STANDARD and EXTENDED as the user's\n * subscription changes without rebuilding the store. Absent = standard.\n * Never affects what is STORED — pruning is fixed at EXTENDED bounds.\n */\n getRetention?: () => MemoryRetentionPolicy\n}\n\nexport interface MemoryStats {\n entryCount: number\n lineCount: number\n noteCount: number\n summaryCount: number\n /** Epoch ms of the oldest entry, or null when empty. */\n oldestAt: number | null\n}\n\nexport function hourStartOf(ms: number): number {\n return Math.floor(ms / HOUR_MS) * HOUR_MS\n}\n\nexport function dayStartOf(ms: number): number {\n const d = new Date(ms)\n d.setHours(0, 0, 0, 0)\n return d.getTime()\n}\n\nfunction makeId(): string {\n return `e-${Date.now()}-${Math.random().toString(36).slice(2)}`\n}\n\nexport class MemoryStore {\n private entries: MemoryEntry[] = []\n private summaries: MemorySummary[] = []\n /** User the in-memory cache was loaded for; reload when identity changes. */\n private loadedUserId: string | null = null\n private loadPromise: Promise<void> | null = null\n private readonly changeListeners = new Set<() => void>()\n /** Pending debounced log write (transcript appends), if any. */\n private logFlushTimer: ReturnType<typeof setTimeout> | null = null\n private logDirty = false\n\n constructor(private readonly hooks: MemoryStoreHooks) {}\n\n /**\n * Write any debounced changes out now. Call before the app backgrounds or\n * terminates so a crash can't lose the coalesced tail of the timeline.\n */\n async flush(): Promise<void> {\n if (this.logFlushTimer) {\n clearTimeout(this.logFlushTimer)\n this.logFlushTimer = null\n }\n if (this.logDirty) await this.persistLog()\n }\n\n /** Subscribe to mutations (adds, edits, deletes, clears). */\n onChanged(listener: () => void): () => void {\n this.changeListeners.add(listener)\n return () => this.changeListeners.delete(listener)\n }\n\n // === Writes ===\n\n async appendLine(input: {\n text: string\n speakerId: string | null\n /** Resolved enrolled-speaker name (on-device speaker ID), when known. */\n resolvedSpeakerName?: string | null\n language: string | null\n at: number\n }): Promise<void> {\n if (!input.text.trim()) return\n await this.ensureLoaded()\n this.entries.push({\n id: makeId(),\n kind: \"line\",\n text: input.text.trim(),\n at: input.at,\n speakerId: input.speakerId,\n ...(input.resolvedSpeakerName ? {resolvedSpeakerName: input.resolvedSpeakerName} : {}),\n language: input.language,\n })\n this.prune()\n // Transcript lines are the hot path (one per final utterance) and each\n // persist re-serializes the whole timeline, so coalesce them. Everything\n // else — notes, edits, deletes, summaries — still writes through\n // immediately; those are user-visible and rare.\n this.schedulePersistLog()\n this.emitChanged()\n }\n\n /**\n * Add a note. `at` targets the hour it belongs to — pass a timestamp inside\n * a past hour to append to that session. Dedupes on normalized text within\n * the same hour (auto-notes re-extract); resolves null on duplicate/empty.\n */\n async addNote(text: string, source: MemoryNoteSource, at: number = Date.now()): Promise<MemoryEntry | null> {\n const body = text.trim()\n if (!body) return null\n await this.ensureLoaded()\n const hour = hourStartOf(at)\n const key = normalize(body)\n if (this.entries.some((e) => e.kind === \"note\" && hourStartOf(e.at) === hour && normalize(e.text) === key)) {\n return null\n }\n const entry: MemoryEntry = {id: makeId(), kind: \"note\", text: body, at, speakerId: null, language: null, source}\n this.entries.push(entry)\n this.entries.sort((a, b) => a.at - b.at)\n this.prune()\n await this.persistLog()\n this.emitChanged()\n return entry\n }\n\n /** Rewrite a note's text in place (Settings > Memory edit). */\n async updateNote(id: string, text: string): Promise<boolean> {\n const body = text.trim()\n if (!body) return false\n await this.ensureLoaded()\n const entry = this.entries.find((e) => e.id === id && e.kind === \"note\")\n if (!entry) return false\n entry.text = body\n await this.persistLog()\n this.emitChanged()\n return true\n }\n\n async removeEntry(id: string): Promise<boolean> {\n await this.ensureLoaded()\n const before = this.entries.length\n this.entries = this.entries.filter((e) => e.id !== id)\n if (this.entries.length === before) return false\n await this.persistLog()\n this.emitChanged()\n return true\n }\n\n /** Delete every entry (and summary) in an hour, or a whole day of hours. */\n async removeScope(scope: \"session\" | \"day\", at: number): Promise<void> {\n await this.ensureLoaded()\n const inScope =\n scope === \"day\"\n ? (ms: number) => dayStartOf(ms) === dayStartOf(at)\n : (ms: number) => hourStartOf(ms) === hourStartOf(at)\n this.entries = this.entries.filter((e) => !inScope(e.at))\n this.summaries = this.summaries.filter((s) => !inScope(s.hourStart))\n await this.persistLog()\n await this.persistSummaries()\n this.emitChanged()\n }\n\n /** Drop the entire timeline: every entry and every summary. */\n async clear(): Promise<void> {\n await this.ensureLoaded()\n this.entries = []\n this.summaries = []\n await this.persistLog()\n await this.persistSummaries()\n this.emitChanged()\n }\n\n async addSummary(summary: MemorySummary): Promise<void> {\n await this.ensureLoaded()\n const {maxSummaries} = EXTENDED_RETENTION\n this.summaries = this.summaries.filter((s) => s.hourStart !== summary.hourStart)\n this.summaries.push(summary)\n if (this.summaries.length > maxSummaries) {\n this.summaries = this.summaries.sort((a, b) => a.hourStart - b.hourStart).slice(-maxSummaries)\n }\n await this.persistSummaries()\n this.emitChanged()\n }\n\n // === Reads ===\n //\n // Every read goes through the VISIBLE view: entries inside the active\n // tier's window. Older data may still be stored (see prune) — it is frozen,\n // not deleted, so an upgrade widens these views instantly.\n\n /** Entries in [sinceMs, untilMs), newest last. */\n async window(sinceMs: number, untilMs: number = Date.now()): Promise<MemoryEntry[]> {\n await this.ensureLoaded()\n return this.visibleEntries().filter((e) => e.at >= sinceMs && e.at < untilMs)\n }\n\n /** All note entries, newest first (Settings > Memory list). */\n async notes(): Promise<MemoryEntry[]> {\n await this.ensureLoaded()\n return this.visibleEntries()\n .filter((e) => e.kind === \"note\")\n .sort((a, b) => b.at - a.at)\n }\n\n async stats(): Promise<MemoryStats> {\n await this.ensureLoaded()\n const visible = this.visibleEntries()\n const noteCount = visible.filter((e) => e.kind === \"note\").length\n return {\n entryCount: visible.length,\n lineCount: visible.length - noteCount,\n noteCount,\n summaryCount: this.visibleSummaries().filter((s) => s.text.trim()).length,\n oldestAt: visible.length > 0 ? visible[0].at : null,\n }\n }\n\n /** All sessions (hours with entries), newest hour first. */\n async sessionList(): Promise<MemorySession[]> {\n await this.ensureLoaded()\n const byHour = new Map<number, MemoryEntry[]>()\n for (const e of this.visibleEntries()) {\n const h = hourStartOf(e.at)\n const list = byHour.get(h) ?? []\n list.push(e)\n byHour.set(h, list)\n }\n const summaryByHour = new Map(this.visibleSummaries().map((s) => [s.hourStart, s.text]))\n return [...byHour.entries()]\n .map(([hourStart, entries]) => {\n entries.sort((a, b) => a.at - b.at)\n return {\n hourStart,\n entries,\n summary: (summaryByHour.get(hourStart) ?? \"\").trim() || null,\n lineCount: entries.filter((e) => e.kind === \"line\").length,\n noteCount: entries.filter((e) => e.kind === \"note\").length,\n }\n })\n .sort((a, b) => b.hourStart - a.hourStart)\n }\n\n /**\n * Query the FULL store by absolute-time window and keyword — the executor\n * behind LLM history-search tools. Newest last, so the limit keeps the most\n * recent matches. `contains` is an exact substring; `terms` is fuzzy any-of\n * matching (mistranscribed-name tolerant) — see utils/memory/search.ts.\n */\n async query(q: {\n sinceMs?: number\n untilMs?: number\n contains?: string\n terms?: string[]\n limit?: number\n }): Promise<MemoryEntry[]> {\n return (await this.search(q)).entries\n }\n\n /**\n * query() plus `windowCount` — how many entries the TIME window held before\n * keyword filtering, so an LLM caller can distinguish \"keyword matched\n * nothing\" from \"history doesn't reach that far back\" without a retry.\n */\n async search(q: {\n sinceMs?: number\n untilMs?: number\n contains?: string\n terms?: string[]\n limit?: number\n }): Promise<{entries: MemoryEntry[]; windowCount: number}> {\n await this.ensureLoaded()\n const limit = q.limit && q.limit > 0 ? Math.min(q.limit, QUERY_LIMIT_CAP) : QUERY_LIMIT_DEFAULT\n return searchMemoryEntries(this.visibleEntries(), {\n sinceMs: q.sinceMs,\n untilMs: q.untilMs,\n contains: q.contains,\n terms: q.terms,\n limit,\n })\n }\n\n async summaryList(): Promise<MemorySummary[]> {\n await this.ensureLoaded()\n return this.visibleSummaries().sort((a, b) => b.hourStart - a.hourStart)\n }\n\n /** Most recent COMPLETED hour with lines but no summary, or null. */\n async pendingSummaryHour(nowMs: number = Date.now()): Promise<number | null> {\n await this.ensureLoaded()\n const currentHour = hourStartOf(nowMs)\n const summarized = new Set(this.summaries.map((s) => s.hourStart))\n const hours = new Set<number>()\n for (const e of this.visibleEntries()) {\n if (e.kind !== \"line\") continue\n const h = hourStartOf(e.at)\n if (h < currentHour && !summarized.has(h)) hours.add(h)\n }\n if (hours.size === 0) return null\n return Math.max(...hours)\n }\n\n /** Plain-text export of a scope, for the OS share sheet. */\n async exportText(scope: \"session\" | \"day\" | \"all\", at?: number): Promise<string> {\n const sessions = (await this.sessionList()).filter((s) => {\n if (scope === \"all\") return true\n if (at == null) return false\n if (scope === \"day\") return dayStartOf(s.hourStart) === dayStartOf(at)\n return s.hourStart === hourStartOf(at)\n })\n if (sessions.length === 0) return \"No session history to export.\"\n\n const dayFmt = (ms: number) =>\n new Date(ms).toLocaleDateString(undefined, {weekday: \"long\", year: \"numeric\", month: \"long\", day: \"numeric\"})\n const hourFmt = (ms: number) => new Date(ms).toLocaleTimeString(undefined, {hour: \"numeric\"})\n const timeFmt = (ms: number) => new Date(ms).toLocaleTimeString(undefined, {hour: \"numeric\", minute: \"2-digit\"})\n\n const parts: string[] = []\n let lastDay: number | null = null\n for (const s of [...sessions].sort((a, b) => a.hourStart - b.hourStart)) {\n const day = dayStartOf(s.hourStart)\n if (day !== lastDay) {\n parts.push(`\\n=== ${dayFmt(day)} ===`)\n lastDay = day\n }\n parts.push(`\\n[${hourFmt(s.hourStart)}–${hourFmt(s.hourStart + HOUR_MS)}]`)\n if (s.summary) parts.push(`Summary: ${s.summary}`)\n for (const e of s.entries) {\n const who = e.kind === \"note\" ? \"NOTE\" : (e.speakerId ?? \"—\")\n parts.push(` ${timeFmt(e.at)} ${who}: ${e.text}`)\n }\n }\n return `Memory session history\\n${parts.join(\"\\n\").trim()}\\n`\n }\n\n // === Load / persist ===\n\n private async ensureLoaded(): Promise<void> {\n const userId = (await this.hooks.getUserId()).trim()\n if (!userId) throw new Error(\"Glassly user identity is unavailable\")\n if (this.loadedUserId === userId) return\n if (!this.loadPromise) {\n this.loadPromise = this.loadFor(userId).finally(() => {\n this.loadPromise = null\n })\n }\n await this.loadPromise\n }\n\n private async loadFor(userId: string): Promise<void> {\n // Don't let an identity switch discard lines still sitting in the debounce\n // window — they belong to the OUTGOING user, whose key is still loaded.\n await this.flush()\n this.entries = []\n this.summaries = []\n const rawLog = this.hooks.backend.get(this.key(userId, LOG_SUFFIX))\n if (rawLog != null) {\n this.entries = parseArray(rawLog).filter(isEntry)\n } else {\n this.migrateFromAssist(userId)\n }\n const rawSummaries = this.hooks.backend.get(this.key(userId, SUMMARY_SUFFIX))\n if (rawSummaries != null) {\n this.summaries = parseArray(rawSummaries).filter(isSummary)\n }\n this.loadedUserId = userId\n this.prune()\n }\n\n /**\n * One-time migration: fold the Assist miniapp's per-app store (the previous\n * home of this timeline) into the shared user-scoped keys. Assist's old keys\n * are left in place; its new build reads through the memory bridge instead.\n */\n private migrateFromAssist(userId: string): void {\n const legacyPrefix = `${LEGACY_STORAGE_ROOT}${userId}_${LEGACY_ASSIST_PACKAGE}_`\n try {\n const migrated: MemoryEntry[] = []\n const rawLog = this.hooks.backend.get(legacyPrefix + LEGACY_LOG_KEY)\n if (rawLog != null) {\n migrated.push(...parseArray(rawLog).filter(isEntry))\n } else {\n // Pre-unification Assist: separate transcript log + notes stores.\n for (const v of parseArray(this.hooks.backend.get(legacyPrefix + LEGACY_TRANSCRIPT_KEY))) {\n const e = v as Record<string, unknown>\n if (typeof e.text === \"string\" && typeof e.at === \"number\") {\n migrated.push({\n id: makeId(),\n kind: \"line\",\n text: e.text,\n at: e.at,\n speakerId: typeof e.speakerId === \"string\" ? e.speakerId : null,\n language: typeof e.language === \"string\" ? e.language : null,\n })\n }\n }\n for (const v of parseArray(this.hooks.backend.get(legacyPrefix + LEGACY_NOTES_KEY))) {\n const n = v as Record<string, unknown>\n if (typeof n.text === \"string\" && typeof n.createdAt === \"number\") {\n migrated.push({\n id: makeId(),\n kind: \"note\",\n text: n.text,\n at: n.createdAt,\n speakerId: null,\n language: null,\n source: n.source === \"voice\" || n.source === \"auto\" ? n.source : \"ui\",\n })\n }\n }\n }\n migrated.sort((a, b) => a.at - b.at)\n this.entries = migrated\n if (migrated.length > 0) this.hooks.backend.set(this.key(userId, LOG_SUFFIX), JSON.stringify(migrated))\n\n const rawSummaries = this.hooks.backend.get(legacyPrefix + LEGACY_SUMMARY_KEY)\n if (rawSummaries != null) {\n const summaries = parseArray(rawSummaries).filter(isSummary)\n this.summaries = summaries\n if (summaries.length > 0) this.hooks.backend.set(this.key(userId, SUMMARY_SUFFIX), JSON.stringify(summaries))\n }\n if (this.entries.length > 0 || this.summaries.length > 0) {\n console.log(\n `MemoryStore: migrated ${this.entries.length} entries + ${this.summaries.length} summaries from Assist`,\n )\n }\n } catch (err) {\n console.warn(\"MemoryStore: Assist migration failed:\", err instanceof Error ? err.message : err)\n }\n }\n\n private retention(): MemoryRetentionPolicy {\n return this.hooks.getRetention?.() ?? STANDARD_RETENTION\n }\n\n /** Entries inside the active tier's visibility window, oldest first. */\n private visibleEntries(): MemoryEntry[] {\n const cutoff = Date.now() - this.retention().maxAgeMs\n return this.entries.filter((e) => e.at >= cutoff)\n }\n\n private visibleSummaries(): MemorySummary[] {\n const cutoff = Date.now() - this.retention().maxAgeMs\n return this.summaries.filter((s) => s.hourStart >= cutoff)\n }\n\n /**\n * Physical bounds, ALWAYS the extended policy regardless of tier. A free or\n * lapsed user's older timeline stays on disk (reads just can't see past\n * their window) so upgrading — or re-upgrading — restores it rather than\n * finding it deleted. Deleting remains the user's call: clear()/removeScope\n * operate on the physical store.\n */\n private prune(): void {\n const {maxAgeMs, maxEntries} = EXTENDED_RETENTION\n const cutoff = Date.now() - maxAgeMs\n this.entries = this.entries.filter((e) => e.at >= cutoff)\n if (this.entries.length > maxEntries) this.entries = this.entries.slice(-maxEntries)\n }\n\n private key(userId: string, suffix: string): string {\n return `${KEY_ROOT}${userId}_${suffix}`\n }\n\n /**\n * Mark the log dirty and arm the debounce timer. Repeated appends inside the\n * window collapse into a single serialization; the first append after a\n * flush starts a fresh window (trailing-edge, so a steady stream of speech\n * still lands on disk every `writeDebounceMs`).\n */\n private schedulePersistLog(): void {\n const delay = this.hooks.writeDebounceMs ?? DEFAULT_WRITE_DEBOUNCE_MS\n if (delay <= 0) {\n void this.persistLog()\n return\n }\n this.logDirty = true\n if (this.logFlushTimer) return\n this.logFlushTimer = setTimeout(() => {\n this.logFlushTimer = null\n void this.persistLog().catch((err) =>\n console.warn(\"MemoryStore: debounced log write failed:\", err instanceof Error ? err.message : err),\n )\n }, delay)\n }\n\n private async persistLog(): Promise<void> {\n // Any write of the full array satisfies whatever the debounce was holding.\n this.logDirty = false\n if (this.logFlushTimer) {\n clearTimeout(this.logFlushTimer)\n this.logFlushTimer = null\n }\n if (this.loadedUserId == null) return\n this.hooks.backend.set(this.key(this.loadedUserId, LOG_SUFFIX), JSON.stringify(this.entries))\n }\n\n private async persistSummaries(): Promise<void> {\n if (this.loadedUserId == null) return\n this.hooks.backend.set(this.key(this.loadedUserId, SUMMARY_SUFFIX), JSON.stringify(this.summaries))\n }\n\n private emitChanged(): void {\n for (const listener of this.changeListeners) {\n try {\n listener()\n } catch (err) {\n console.warn(\"MemoryStore: onChanged listener threw:\", err instanceof Error ? err.message : err)\n }\n }\n }\n}\n\n/** Stored values may be a JSON string (SimpleStorage writes) or a raw array. */\nfunction parseArray(raw: unknown): unknown[] {\n try {\n if (typeof raw === \"string\") {\n const parsed = JSON.parse(raw) as unknown\n return Array.isArray(parsed) ? parsed : []\n }\n return Array.isArray(raw) ? raw : []\n } catch {\n return []\n }\n}\n\nfunction normalize(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \" \")\n .trim()\n}\n\nfunction isEntry(v: unknown): v is MemoryEntry {\n if (!v || typeof v !== \"object\") return false\n const e = v as Record<string, unknown>\n return (\n typeof e.id === \"string\" &&\n (e.kind === \"line\" || e.kind === \"note\") &&\n typeof e.text === \"string\" &&\n typeof e.at === \"number\"\n )\n}\n\nfunction isSummary(v: unknown): v is MemorySummary {\n if (!v || typeof v !== \"object\") return false\n const s = v as Record<string, unknown>\n return typeof s.hourStart === \"number\" && typeof s.text === \"string\" && typeof s.createdAt === \"number\"\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MemoryStore.js","sourceRoot":"","sources":["../../src/services/MemoryStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAAC,mBAAmB,EAAC,MAAM,wBAAwB,CAAA;AAE1D,OAAO,EAAC,OAAO,EAAC,MAAM,iBAAiB,CAAA;AAEvC,MAAM,QAAQ,GAAG,SAAS,CAAA;AAC1B,MAAM,UAAU,GAAG,KAAK,CAAA;AACxB,MAAM,cAAc,GAAG,WAAW,CAAA;AAElC;;;;;GAKG;AACH,MAAM,qBAAqB,GAAG,uBAAuB,CAAA;AACrD,MAAM,mBAAmB,GAAG,eAAe,CAAA;AAC3C,MAAM,cAAc,GAAG,uBAAuB,CAAA;AAC9C,MAAM,kBAAkB,GAAG,4BAA4B,CAAA;AACvD,0EAA0E;AAC1E,+BAA+B;AAC/B,MAAM,qBAAqB,GAAG,0BAA0B,CAAA;AACxD,MAAM,gBAAgB,GAAG,iBAAiB,CAAA;AAE1C,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAE9B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,UAAU,EAAE,MAAM;IAClB,YAAY,EAAE,IAAI;CACnB,CAAA;AACD,MAAM,eAAe,GAAG,GAAG,CAAA;AAC3B,MAAM,mBAAmB,GAAG,EAAE,CAAA;AAC9B;;;;;GAKG;AACH,MAAM,yBAAyB,GAAG,IAAI,CAAA;AA4BtC,MAAM,UAAU,WAAW,CAAC,EAAU;IACpC,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,OAAO,CAAA;AAC3C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;IACtB,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IACtB,OAAO,CAAC,CAAC,OAAO,EAAE,CAAA;AACpB,CAAC;AAED,SAAS,MAAM;IACb,OAAO,KAAK,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;AACjE,CAAC;AAED,MAAM,OAAO,WAAW;IAWO;IAVrB,OAAO,GAAkB,EAAE,CAAA;IAC3B,SAAS,GAAoB,EAAE,CAAA;IACvC,6EAA6E;IACrE,YAAY,GAAkB,IAAI,CAAA;IAClC,WAAW,GAAyB,IAAI,CAAA;IAC/B,eAAe,GAAG,IAAI,GAAG,EAAc,CAAA;IACxD,gEAAgE;IACxD,aAAa,GAAkB,IAAI,CAAA;IACnC,QAAQ,GAAG,KAAK,CAAA;IAExB,YAA6B,KAAuB;QAAvB,UAAK,GAAL,KAAK,CAAkB;IAAG,CAAC;IAExD;;;OAGG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;YACxC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAA;QAC3B,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,CAAC,UAAU,EAAE,CAAA;IAC5C,CAAC;IAED,6DAA6D;IAC7D,SAAS,CAAC,QAAoB;QAC5B,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAClC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IACpD,CAAC;IAED,iBAAiB;IAEjB,KAAK,CAAC,UAAU,CAAC,KAOhB;QACC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,OAAM;QAC9B,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YAChB,EAAE,EAAE,MAAM,EAAE;YACZ,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE;YACvB,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,GAAG,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAC,mBAAmB,EAAE,KAAK,CAAC,mBAAmB,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACtF,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACzB,CAAC,CAAA;QACF,IAAI,CAAC,KAAK,EAAE,CAAA;QACZ,uEAAuE;QACvE,yEAAyE;QACzE,iEAAiE;QACjE,gDAAgD;QAChD,IAAI,CAAC,kBAAkB,EAAE,CAAA;QACzB,IAAI,CAAC,WAAW,EAAE,CAAA;IACpB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,MAAwB,EAAE,KAAa,IAAI,CAAC,GAAG,EAAE;QAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;QACxB,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAA;QACtB,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,MAAM,IAAI,GAAG,WAAW,CAAC,EAAE,CAAC,CAAA;QAC5B,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;QAC3B,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,IAAI,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;YAC3G,OAAO,IAAI,CAAA;QACb,CAAC;QACD,MAAM,KAAK,GAAgB,EAAC,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAC,CAAA;QAChH,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACxB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAA;QACxC,IAAI,CAAC,KAAK,EAAE,CAAA;QACZ,MAAM,IAAI,CAAC,UAAU,EAAE,CAAA;QACvB,IAAI,CAAC,WAAW,EAAE,CAAA;QAClB,OAAO,KAAK,CAAA;IACd,CAAC;IAED,+DAA+D;IAC/D,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,IAAY;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;QACxB,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAA;QACvB,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAA;QACxE,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAA;QACxB,KAAK,CAAC,IAAI,GAAG,IAAI,CAAA;QACjB,MAAM,IAAI,CAAC,UAAU,EAAE,CAAA;QACvB,IAAI,CAAC,WAAW,EAAE,CAAA;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,EAAU;QAC1B,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAA;QAClC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;QACtD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO,KAAK,CAAA;QAChD,MAAM,IAAI,CAAC,UAAU,EAAE,CAAA;QACvB,IAAI,CAAC,WAAW,EAAE,CAAA;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,WAAW,CAAC,KAAwB,EAAE,EAAU;QACpD,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,MAAM,OAAO,GACX,KAAK,KAAK,KAAK;YACb,CAAC,CAAC,CAAC,EAAU,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,UAAU,CAAC,EAAE,CAAC;YACnD,CAAC,CAAC,CAAC,EAAU,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,WAAW,CAAC,EAAE,CAAC,CAAA;QACzD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QACzD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAA;QACpE,MAAM,IAAI,CAAC,UAAU,EAAE,CAAA;QACvB,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAA;QAC7B,IAAI,CAAC,WAAW,EAAE,CAAA;IACpB,CAAC;IAED,+DAA+D;IAC/D,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;QACjB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;QACnB,MAAM,IAAI,CAAC,UAAU,EAAE,CAAA;QACvB,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAA;QAC7B,IAAI,CAAC,WAAW,EAAE,CAAA;IACpB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAsB;QACrC,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,MAAM,EAAC,YAAY,EAAC,GAAG,aAAa,CAAA;QACpC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,OAAO,CAAC,SAAS,CAAC,CAAA;QAChF,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC5B,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;YACzC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAA;QAChG,CAAC;QACD,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAA;QAC7B,IAAI,CAAC,WAAW,EAAE,CAAA;IACpB,CAAC;IAED,sEAAsE;IAEtE,kDAAkD;IAClD,KAAK,CAAC,MAAM,CAAC,OAAe,EAAE,UAAkB,IAAI,CAAC,GAAG,EAAE;QACxD,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,OAAO,IAAI,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAA;IACtE,CAAC;IAED,+DAA+D;IAC/D,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAA;IAClF,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;QAC5B,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,MAAM,CAAA;QACjE,OAAO;YACL,UAAU,EAAE,OAAO,CAAC,MAAM;YAC1B,SAAS,EAAE,OAAO,CAAC,MAAM,GAAG,SAAS;YACrC,SAAS;YACT,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM;YAChE,QAAQ,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI;SACpD,CAAA;IACH,CAAC;IAED,4DAA4D;IAC5D,KAAK,CAAC,WAAW;QACf,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAyB,CAAA;QAC/C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;YAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;YAChC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACZ,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;QACrB,CAAC;QACD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC/E,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;aACzB,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE;YAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAA;YACnC,OAAO;gBACL,SAAS;gBACT,OAAO;gBACP,OAAO,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI;gBAC5D,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,MAAM;gBAC1D,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,MAAM;aAC3D,CAAA;QACH,CAAC,CAAC;aACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAA;IAC9C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAK,CAAC,CAMX;QACC,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;IACvC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,CAMZ;QACC,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAA;QAC/F,OAAO,mBAAmB,CAAC,IAAI,CAAC,OAAO,EAAE;YACvC,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,KAAK;SACN,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,WAAW;QACf,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAA;IACtE,CAAC;IAED,qEAAqE;IACrE,KAAK,CAAC,kBAAkB,CAAC,QAAgB,IAAI,CAAC,GAAG,EAAE;QACjD,MAAM,IAAI,CAAC,YAAY,EAAE,CAAA;QACzB,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAA;QACtC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAA;QAClE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAA;QAC/B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;gBAAE,SAAQ;YAC/B,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;YAC3B,IAAI,CAAC,GAAG,WAAW,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACzD,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;QACjC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAA;IAC3B,CAAC;IAED,4DAA4D;IAC5D,KAAK,CAAC,UAAU,CAAC,KAAgC,EAAE,EAAW;QAC5D,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACvD,IAAI,KAAK,KAAK,KAAK;gBAAE,OAAO,IAAI,CAAA;YAChC,IAAI,EAAE,IAAI,IAAI;gBAAE,OAAO,KAAK,CAAA;YAC5B,IAAI,KAAK,KAAK,KAAK;gBAAE,OAAO,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,UAAU,CAAC,EAAE,CAAC,CAAA;YACtE,OAAO,CAAC,CAAC,SAAS,KAAK,WAAW,CAAC,EAAE,CAAC,CAAA;QACxC,CAAC,CAAC,CAAA;QACF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,+BAA+B,CAAA;QAEjE,MAAM,MAAM,GAAG,CAAC,EAAU,EAAE,EAAE,CAC5B,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,kBAAkB,CAAC,SAAS,EAAE,EAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAC,CAAC,CAAA;QAC/G,MAAM,OAAO,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,kBAAkB,CAAC,SAAS,EAAE,EAAC,IAAI,EAAE,SAAS,EAAC,CAAC,CAAA;QAC7F,MAAM,OAAO,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,kBAAkB,CAAC,SAAS,EAAE,EAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAC,CAAC,CAAA;QAEhH,MAAM,KAAK,GAAa,EAAE,CAAA;QAC1B,IAAI,OAAO,GAAkB,IAAI,CAAA;QACjC,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC;YACxE,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;YACnC,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;gBACpB,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;gBACtC,OAAO,GAAG,GAAG,CAAA;YACf,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;YAC3E,IAAI,CAAC,CAAC,OAAO;gBAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;YAClD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBAC1B,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,CAAA;gBAC7D,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;YACrD,CAAC;QACH,CAAC;QACD,OAAO,2BAA2B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,CAAA;IAC/D,CAAC;IAED,yBAAyB;IAEjB,KAAK,CAAC,YAAY;QACxB,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QACpD,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;QACpE,IAAI,IAAI,CAAC,YAAY,KAAK,MAAM;YAAE,OAAM;QACxC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;gBACnD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAA;YACzB,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,MAAM,IAAI,CAAC,WAAW,CAAA;IACxB,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,MAAc;QAClC,2EAA2E;QAC3E,wEAAwE;QACxE,MAAM,IAAI,CAAC,KAAK,EAAE,CAAA;QAClB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;QACjB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAA;QACnE,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACnD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAA;QAChC,CAAC;QACD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAA;QAC7E,IAAI,YAAY,IAAI,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAC7D,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,MAAM,CAAA;QAC1B,IAAI,CAAC,KAAK,EAAE,CAAA;IACd,CAAC;IAED;;;;OAIG;IACK,iBAAiB,CAAC,MAAc;QACtC,MAAM,YAAY,GAAG,GAAG,mBAAmB,GAAG,MAAM,IAAI,qBAAqB,GAAG,CAAA;QAChF,IAAI,CAAC;YACH,MAAM,QAAQ,GAAkB,EAAE,CAAA;YAClC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,cAAc,CAAC,CAAA;YACpE,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;gBACnB,QAAQ,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;YACtD,CAAC;iBAAM,CAAC;gBACN,kEAAkE;gBAClE,KAAK,MAAM,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,qBAAqB,CAAC,CAAC,EAAE,CAAC;oBACzF,MAAM,CAAC,GAAG,CAA4B,CAAA;oBACtC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;wBAC3D,QAAQ,CAAC,IAAI,CAAC;4BACZ,EAAE,EAAE,MAAM,EAAE;4BACZ,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,CAAC,CAAC,IAAI;4BACZ,EAAE,EAAE,CAAC,CAAC,EAAE;4BACR,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;4BAC/D,QAAQ,EAAE,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI;yBAC7D,CAAC,CAAA;oBACJ,CAAC;gBACH,CAAC;gBACD,KAAK,MAAM,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,gBAAgB,CAAC,CAAC,EAAE,CAAC;oBACpF,MAAM,CAAC,GAAG,CAA4B,CAAA;oBACtC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;wBAClE,QAAQ,CAAC,IAAI,CAAC;4BACZ,EAAE,EAAE,MAAM,EAAE;4BACZ,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,CAAC,CAAC,IAAI;4BACZ,EAAE,EAAE,CAAC,CAAC,SAAS;4BACf,SAAS,EAAE,IAAI;4BACf,QAAQ,EAAE,IAAI;4BACd,MAAM,EAAE,CAAC,CAAC,MAAM,KAAK,OAAO,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;yBACtE,CAAC,CAAA;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAA;YACpC,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAA;YACvB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;gBAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAA;YAEvG,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,kBAAkB,CAAC,CAAA;YAC9E,IAAI,YAAY,IAAI,IAAI,EAAE,CAAC;gBACzB,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;gBAC5D,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;gBAC1B,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;oBAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAA;YAC/G,CAAC;YACD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzD,OAAO,CAAC,GAAG,CACT,yBAAyB,IAAI,CAAC,OAAO,CAAC,MAAM,cAAc,IAAI,CAAC,SAAS,CAAC,MAAM,wBAAwB,CACxG,CAAA;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,uCAAuC,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACjG,CAAC;IACH,CAAC;IAED,oGAAoG;IAC5F,KAAK;QACX,MAAM,EAAC,UAAU,EAAC,GAAG,aAAa,CAAA;QAClC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,UAAU;YAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAA;IACtF,CAAC;IAEO,GAAG,CAAC,MAAc,EAAE,MAAc;QACxC,OAAO,GAAG,QAAQ,GAAG,MAAM,IAAI,MAAM,EAAE,CAAA;IACzC,CAAC;IAED;;;;;OAKG;IACK,kBAAkB;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,IAAI,yBAAyB,CAAA;QACrE,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YACf,KAAK,IAAI,CAAC,UAAU,EAAE,CAAA;YACtB,OAAM;QACR,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;QACpB,IAAI,IAAI,CAAC,aAAa;YAAE,OAAM;QAC9B,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE;YAC3C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAA;YACzB,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CACnC,OAAO,CAAC,IAAI,CAAC,0CAA0C,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CACnG,CAAA;QACH,CAAC,EAAE,KAAK,CAAC,CAAA;IACX,CAAC;IAEO,KAAK,CAAC,UAAU;QACtB,2EAA2E;QAC3E,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAA;QACrB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;YACxC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAA;QAC3B,CAAC;QACD,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI;YAAE,OAAM;QACrC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;IAC/F,CAAC;IAEO,KAAK,CAAC,gBAAgB;QAC5B,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI;YAAE,OAAM;QACrC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAA;IACrG,CAAC;IAEO,WAAW;QACjB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YAC5C,IAAI,CAAC;gBACH,QAAQ,EAAE,CAAA;YACZ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,wCAAwC,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;YAClG,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAED,gFAAgF;AAChF,SAAS,UAAU,CAAC,GAAY;IAC9B,IAAI,CAAC;QACH,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAA;YACzC,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;QAC5C,CAAC;QACD,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI;SACR,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,IAAI,EAAE,CAAA;AACX,CAAC;AAED,SAAS,OAAO,CAAC,CAAU;IACzB,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC7C,MAAM,CAAC,GAAG,CAA4B,CAAA;IACtC,OAAO,CACL,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;QACxB,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;QACxC,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAC1B,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CACzB,CAAA;AACH,CAAC;AAED,SAAS,SAAS,CAAC,CAAU;IAC3B,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC7C,MAAM,CAAC,GAAG,CAA4B,CAAA;IACtC,OAAO,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAA;AACzG,CAAC","sourcesContent":["/**\n * MemoryStore — the user's shared, phone-local memory timeline.\n *\n * One unified per-hour stream of what happened around the user — spoken\n * transcript lines AND notes (manual, voice, auto) in one timeline — plus the\n * hourly conversation summary that heads each session. Scoped to the Glassly\n * USER (not to a miniapp): every miniapp that declares the MEMORY manifest\n * permission reads and writes the same store through LocalMiniappRuntime's\n * MEMORY_* handlers, and Settings > Memory manages it via engine.memory.\n *\n * A \"session\" is one clock hour that has entries, derived from entry\n * timestamps at read time — nothing is stored per-session, so there is no\n * session id to keep in sync.\n *\n * The store began life inside the Assist miniapp (its SessionStore); on first\n * load it migrates Assist's per-app storage namespace into the shared\n * user-scoped keys so existing history survives the move.\n */\n\nimport type {MemoryEntry, MemoryNoteSource, MemorySession, MemorySummary} from \"@glassly/miniapp\"\n\nimport {searchMemoryEntries} from \"../utils/memory/search\"\n\nimport {BgTimer} from \"../utils/timers\"\n\nconst KEY_ROOT = \"memory_\"\nconst LOG_SUFFIX = \"log\"\nconst SUMMARY_SUFFIX = \"summaries\"\n\n/**\n * The pre-memory-layer Assist miniapp whose storage namespace we migrate.\n * Assist now ships as com.glassly.assistant; the timeline it reads is\n * user-scoped (KEY_ROOT below), so the rename needs no second migration and\n * this constant stays pinned to the old namespace.\n */\nconst LEGACY_ASSIST_PACKAGE = \"com.tetramo.assistant\"\nconst LEGACY_STORAGE_ROOT = \"localstorage_\"\nconst LEGACY_LOG_KEY = \"assistant:session-log\"\nconst LEGACY_SUMMARY_KEY = \"assistant:hourly-summaries\"\n// Assist's own pre-unification keys, migrated for users who never ran the\n// unified-schema Assist build.\nconst LEGACY_TRANSCRIPT_KEY = \"assistant:transcript-log\"\nconst LEGACY_NOTES_KEY = \"assistant:notes\"\n\nconst HOUR_MS = 60 * 60 * 1000\n\n/**\n * Physical bounds. There is no age cap: the timeline stays until the user\n * deletes it (clear()/removeScope). The entry cap bounds the write cost —\n * every persist re-serializes the whole timeline, so it is a perf ceiling as\n * much as a product number — and the summary cap keeps one row per hour for\n * about half a year of round-the-clock use, far longer at a normal pace.\n */\nexport const MEMORY_BOUNDS = {\n maxEntries: 24_000,\n maxSummaries: 4320,\n}\nconst QUERY_LIMIT_CAP = 200\nconst QUERY_LIMIT_DEFAULT = 60\n/**\n * How long transcript appends coalesce before hitting disk. Each write\n * re-serializes the entire timeline, so at conversational pace (a final\n * utterance every few seconds) this turns O(n) work per line into O(n) per\n * window. Short enough that an unexpected kill loses only the last few lines.\n */\nconst DEFAULT_WRITE_DEBOUNCE_MS = 3000\n\nexport interface MemoryStoreBackend {\n get(key: string): unknown | null\n set(key: string, value: unknown): void\n remove(key: string): void\n}\n\nexport interface MemoryStoreHooks {\n getUserId: () => Promise<string>\n backend: MemoryStoreBackend\n /**\n * Debounce window for transcript-line writes, in ms. Appends coalesce into\n * one serialization instead of re-stringifying the whole timeline per\n * utterance. Set to 0 to persist synchronously (tests).\n */\n writeDebounceMs?: number\n}\n\nexport interface MemoryStats {\n entryCount: number\n lineCount: number\n noteCount: number\n summaryCount: number\n /** Epoch ms of the oldest entry, or null when empty. */\n oldestAt: number | null\n}\n\nexport function hourStartOf(ms: number): number {\n return Math.floor(ms / HOUR_MS) * HOUR_MS\n}\n\nexport function dayStartOf(ms: number): number {\n const d = new Date(ms)\n d.setHours(0, 0, 0, 0)\n return d.getTime()\n}\n\nfunction makeId(): string {\n return `e-${Date.now()}-${Math.random().toString(36).slice(2)}`\n}\n\nexport class MemoryStore {\n private entries: MemoryEntry[] = []\n private summaries: MemorySummary[] = []\n /** User the in-memory cache was loaded for; reload when identity changes. */\n private loadedUserId: string | null = null\n private loadPromise: Promise<void> | null = null\n private readonly changeListeners = new Set<() => void>()\n /** Pending debounced log write (transcript appends), if any. */\n private logFlushTimer: number | null = null\n private logDirty = false\n\n constructor(private readonly hooks: MemoryStoreHooks) {}\n\n /**\n * Write any debounced changes out now. Call before the app backgrounds or\n * terminates so a crash can't lose the coalesced tail of the timeline.\n */\n async flush(): Promise<void> {\n if (this.logFlushTimer) {\n BgTimer.clearTimeout(this.logFlushTimer)\n this.logFlushTimer = null\n }\n if (this.logDirty) await this.persistLog()\n }\n\n /** Subscribe to mutations (adds, edits, deletes, clears). */\n onChanged(listener: () => void): () => void {\n this.changeListeners.add(listener)\n return () => this.changeListeners.delete(listener)\n }\n\n // === Writes ===\n\n async appendLine(input: {\n text: string\n speakerId: string | null\n /** Resolved enrolled-speaker name (on-device speaker ID), when known. */\n resolvedSpeakerName?: string | null\n language: string | null\n at: number\n }): Promise<void> {\n if (!input.text.trim()) return\n await this.ensureLoaded()\n this.entries.push({\n id: makeId(),\n kind: \"line\",\n text: input.text.trim(),\n at: input.at,\n speakerId: input.speakerId,\n ...(input.resolvedSpeakerName ? {resolvedSpeakerName: input.resolvedSpeakerName} : {}),\n language: input.language,\n })\n this.prune()\n // Transcript lines are the hot path (one per final utterance) and each\n // persist re-serializes the whole timeline, so coalesce them. Everything\n // else — notes, edits, deletes, summaries — still writes through\n // immediately; those are user-visible and rare.\n this.schedulePersistLog()\n this.emitChanged()\n }\n\n /**\n * Add a note. `at` targets the hour it belongs to — pass a timestamp inside\n * a past hour to append to that session. Dedupes on normalized text within\n * the same hour (auto-notes re-extract); resolves null on duplicate/empty.\n */\n async addNote(text: string, source: MemoryNoteSource, at: number = Date.now()): Promise<MemoryEntry | null> {\n const body = text.trim()\n if (!body) return null\n await this.ensureLoaded()\n const hour = hourStartOf(at)\n const key = normalize(body)\n if (this.entries.some((e) => e.kind === \"note\" && hourStartOf(e.at) === hour && normalize(e.text) === key)) {\n return null\n }\n const entry: MemoryEntry = {id: makeId(), kind: \"note\", text: body, at, speakerId: null, language: null, source}\n this.entries.push(entry)\n this.entries.sort((a, b) => a.at - b.at)\n this.prune()\n await this.persistLog()\n this.emitChanged()\n return entry\n }\n\n /** Rewrite a note's text in place (Settings > Memory edit). */\n async updateNote(id: string, text: string): Promise<boolean> {\n const body = text.trim()\n if (!body) return false\n await this.ensureLoaded()\n const entry = this.entries.find((e) => e.id === id && e.kind === \"note\")\n if (!entry) return false\n entry.text = body\n await this.persistLog()\n this.emitChanged()\n return true\n }\n\n async removeEntry(id: string): Promise<boolean> {\n await this.ensureLoaded()\n const before = this.entries.length\n this.entries = this.entries.filter((e) => e.id !== id)\n if (this.entries.length === before) return false\n await this.persistLog()\n this.emitChanged()\n return true\n }\n\n /** Delete every entry (and summary) in an hour, or a whole day of hours. */\n async removeScope(scope: \"session\" | \"day\", at: number): Promise<void> {\n await this.ensureLoaded()\n const inScope =\n scope === \"day\"\n ? (ms: number) => dayStartOf(ms) === dayStartOf(at)\n : (ms: number) => hourStartOf(ms) === hourStartOf(at)\n this.entries = this.entries.filter((e) => !inScope(e.at))\n this.summaries = this.summaries.filter((s) => !inScope(s.hourStart))\n await this.persistLog()\n await this.persistSummaries()\n this.emitChanged()\n }\n\n /** Drop the entire timeline: every entry and every summary. */\n async clear(): Promise<void> {\n await this.ensureLoaded()\n this.entries = []\n this.summaries = []\n await this.persistLog()\n await this.persistSummaries()\n this.emitChanged()\n }\n\n async addSummary(summary: MemorySummary): Promise<void> {\n await this.ensureLoaded()\n const {maxSummaries} = MEMORY_BOUNDS\n this.summaries = this.summaries.filter((s) => s.hourStart !== summary.hourStart)\n this.summaries.push(summary)\n if (this.summaries.length > maxSummaries) {\n this.summaries = this.summaries.sort((a, b) => a.hourStart - b.hourStart).slice(-maxSummaries)\n }\n await this.persistSummaries()\n this.emitChanged()\n }\n\n // === Reads === (the whole stored timeline; nothing is hidden by age)\n\n /** Entries in [sinceMs, untilMs), newest last. */\n async window(sinceMs: number, untilMs: number = Date.now()): Promise<MemoryEntry[]> {\n await this.ensureLoaded()\n return this.entries.filter((e) => e.at >= sinceMs && e.at < untilMs)\n }\n\n /** All note entries, newest first (Settings > Memory list). */\n async notes(): Promise<MemoryEntry[]> {\n await this.ensureLoaded()\n return this.entries.filter((e) => e.kind === \"note\").sort((a, b) => b.at - a.at)\n }\n\n async stats(): Promise<MemoryStats> {\n await this.ensureLoaded()\n const visible = this.entries\n const noteCount = visible.filter((e) => e.kind === \"note\").length\n return {\n entryCount: visible.length,\n lineCount: visible.length - noteCount,\n noteCount,\n summaryCount: this.summaries.filter((s) => s.text.trim()).length,\n oldestAt: visible.length > 0 ? visible[0].at : null,\n }\n }\n\n /** All sessions (hours with entries), newest hour first. */\n async sessionList(): Promise<MemorySession[]> {\n await this.ensureLoaded()\n const byHour = new Map<number, MemoryEntry[]>()\n for (const e of this.entries) {\n const h = hourStartOf(e.at)\n const list = byHour.get(h) ?? []\n list.push(e)\n byHour.set(h, list)\n }\n const summaryByHour = new Map(this.summaries.map((s) => [s.hourStart, s.text]))\n return [...byHour.entries()]\n .map(([hourStart, entries]) => {\n entries.sort((a, b) => a.at - b.at)\n return {\n hourStart,\n entries,\n summary: (summaryByHour.get(hourStart) ?? \"\").trim() || null,\n lineCount: entries.filter((e) => e.kind === \"line\").length,\n noteCount: entries.filter((e) => e.kind === \"note\").length,\n }\n })\n .sort((a, b) => b.hourStart - a.hourStart)\n }\n\n /**\n * Query the FULL store by absolute-time window and keyword — the executor\n * behind LLM history-search tools. Newest last, so the limit keeps the most\n * recent matches. `contains` is an exact substring; `terms` is fuzzy any-of\n * matching (mistranscribed-name tolerant) — see utils/memory/search.ts.\n */\n async query(q: {\n sinceMs?: number\n untilMs?: number\n contains?: string\n terms?: string[]\n limit?: number\n }): Promise<MemoryEntry[]> {\n return (await this.search(q)).entries\n }\n\n /**\n * query() plus `windowCount` — how many entries the TIME window held before\n * keyword filtering, so an LLM caller can distinguish \"keyword matched\n * nothing\" from \"history doesn't reach that far back\" without a retry.\n */\n async search(q: {\n sinceMs?: number\n untilMs?: number\n contains?: string\n terms?: string[]\n limit?: number\n }): Promise<{entries: MemoryEntry[]; windowCount: number}> {\n await this.ensureLoaded()\n const limit = q.limit && q.limit > 0 ? Math.min(q.limit, QUERY_LIMIT_CAP) : QUERY_LIMIT_DEFAULT\n return searchMemoryEntries(this.entries, {\n sinceMs: q.sinceMs,\n untilMs: q.untilMs,\n contains: q.contains,\n terms: q.terms,\n limit,\n })\n }\n\n async summaryList(): Promise<MemorySummary[]> {\n await this.ensureLoaded()\n return [...this.summaries].sort((a, b) => b.hourStart - a.hourStart)\n }\n\n /** Most recent COMPLETED hour with lines but no summary, or null. */\n async pendingSummaryHour(nowMs: number = Date.now()): Promise<number | null> {\n await this.ensureLoaded()\n const currentHour = hourStartOf(nowMs)\n const summarized = new Set(this.summaries.map((s) => s.hourStart))\n const hours = new Set<number>()\n for (const e of this.entries) {\n if (e.kind !== \"line\") continue\n const h = hourStartOf(e.at)\n if (h < currentHour && !summarized.has(h)) hours.add(h)\n }\n if (hours.size === 0) return null\n return Math.max(...hours)\n }\n\n /** Plain-text export of a scope, for the OS share sheet. */\n async exportText(scope: \"session\" | \"day\" | \"all\", at?: number): Promise<string> {\n const sessions = (await this.sessionList()).filter((s) => {\n if (scope === \"all\") return true\n if (at == null) return false\n if (scope === \"day\") return dayStartOf(s.hourStart) === dayStartOf(at)\n return s.hourStart === hourStartOf(at)\n })\n if (sessions.length === 0) return \"No session history to export.\"\n\n const dayFmt = (ms: number) =>\n new Date(ms).toLocaleDateString(undefined, {weekday: \"long\", year: \"numeric\", month: \"long\", day: \"numeric\"})\n const hourFmt = (ms: number) => new Date(ms).toLocaleTimeString(undefined, {hour: \"numeric\"})\n const timeFmt = (ms: number) => new Date(ms).toLocaleTimeString(undefined, {hour: \"numeric\", minute: \"2-digit\"})\n\n const parts: string[] = []\n let lastDay: number | null = null\n for (const s of [...sessions].sort((a, b) => a.hourStart - b.hourStart)) {\n const day = dayStartOf(s.hourStart)\n if (day !== lastDay) {\n parts.push(`\\n=== ${dayFmt(day)} ===`)\n lastDay = day\n }\n parts.push(`\\n[${hourFmt(s.hourStart)}–${hourFmt(s.hourStart + HOUR_MS)}]`)\n if (s.summary) parts.push(`Summary: ${s.summary}`)\n for (const e of s.entries) {\n const who = e.kind === \"note\" ? \"NOTE\" : (e.speakerId ?? \"—\")\n parts.push(` ${timeFmt(e.at)} ${who}: ${e.text}`)\n }\n }\n return `Memory session history\\n${parts.join(\"\\n\").trim()}\\n`\n }\n\n // === Load / persist ===\n\n private async ensureLoaded(): Promise<void> {\n const userId = (await this.hooks.getUserId()).trim()\n if (!userId) throw new Error(\"Glassly user identity is unavailable\")\n if (this.loadedUserId === userId) return\n if (!this.loadPromise) {\n this.loadPromise = this.loadFor(userId).finally(() => {\n this.loadPromise = null\n })\n }\n await this.loadPromise\n }\n\n private async loadFor(userId: string): Promise<void> {\n // Don't let an identity switch discard lines still sitting in the debounce\n // window — they belong to the OUTGOING user, whose key is still loaded.\n await this.flush()\n this.entries = []\n this.summaries = []\n const rawLog = this.hooks.backend.get(this.key(userId, LOG_SUFFIX))\n if (rawLog != null) {\n this.entries = parseArray(rawLog).filter(isEntry)\n } else {\n this.migrateFromAssist(userId)\n }\n const rawSummaries = this.hooks.backend.get(this.key(userId, SUMMARY_SUFFIX))\n if (rawSummaries != null) {\n this.summaries = parseArray(rawSummaries).filter(isSummary)\n }\n this.loadedUserId = userId\n this.prune()\n }\n\n /**\n * One-time migration: fold the Assist miniapp's per-app store (the previous\n * home of this timeline) into the shared user-scoped keys. Assist's old keys\n * are left in place; its new build reads through the memory bridge instead.\n */\n private migrateFromAssist(userId: string): void {\n const legacyPrefix = `${LEGACY_STORAGE_ROOT}${userId}_${LEGACY_ASSIST_PACKAGE}_`\n try {\n const migrated: MemoryEntry[] = []\n const rawLog = this.hooks.backend.get(legacyPrefix + LEGACY_LOG_KEY)\n if (rawLog != null) {\n migrated.push(...parseArray(rawLog).filter(isEntry))\n } else {\n // Pre-unification Assist: separate transcript log + notes stores.\n for (const v of parseArray(this.hooks.backend.get(legacyPrefix + LEGACY_TRANSCRIPT_KEY))) {\n const e = v as Record<string, unknown>\n if (typeof e.text === \"string\" && typeof e.at === \"number\") {\n migrated.push({\n id: makeId(),\n kind: \"line\",\n text: e.text,\n at: e.at,\n speakerId: typeof e.speakerId === \"string\" ? e.speakerId : null,\n language: typeof e.language === \"string\" ? e.language : null,\n })\n }\n }\n for (const v of parseArray(this.hooks.backend.get(legacyPrefix + LEGACY_NOTES_KEY))) {\n const n = v as Record<string, unknown>\n if (typeof n.text === \"string\" && typeof n.createdAt === \"number\") {\n migrated.push({\n id: makeId(),\n kind: \"note\",\n text: n.text,\n at: n.createdAt,\n speakerId: null,\n language: null,\n source: n.source === \"voice\" || n.source === \"auto\" ? n.source : \"ui\",\n })\n }\n }\n }\n migrated.sort((a, b) => a.at - b.at)\n this.entries = migrated\n if (migrated.length > 0) this.hooks.backend.set(this.key(userId, LOG_SUFFIX), JSON.stringify(migrated))\n\n const rawSummaries = this.hooks.backend.get(legacyPrefix + LEGACY_SUMMARY_KEY)\n if (rawSummaries != null) {\n const summaries = parseArray(rawSummaries).filter(isSummary)\n this.summaries = summaries\n if (summaries.length > 0) this.hooks.backend.set(this.key(userId, SUMMARY_SUFFIX), JSON.stringify(summaries))\n }\n if (this.entries.length > 0 || this.summaries.length > 0) {\n console.log(\n `MemoryStore: migrated ${this.entries.length} entries + ${this.summaries.length} summaries from Assist`,\n )\n }\n } catch (err) {\n console.warn(\"MemoryStore: Assist migration failed:\", err instanceof Error ? err.message : err)\n }\n }\n\n /** Keep the newest MEMORY_BOUNDS.maxEntries; nothing goes for age — deleting is the user's call. */\n private prune(): void {\n const {maxEntries} = MEMORY_BOUNDS\n if (this.entries.length > maxEntries) this.entries = this.entries.slice(-maxEntries)\n }\n\n private key(userId: string, suffix: string): string {\n return `${KEY_ROOT}${userId}_${suffix}`\n }\n\n /**\n * Mark the log dirty and arm the debounce timer. Repeated appends inside the\n * window collapse into a single serialization; the first append after a\n * flush starts a fresh window (trailing-edge, so a steady stream of speech\n * still lands on disk every `writeDebounceMs`).\n */\n private schedulePersistLog(): void {\n const delay = this.hooks.writeDebounceMs ?? DEFAULT_WRITE_DEBOUNCE_MS\n if (delay <= 0) {\n void this.persistLog()\n return\n }\n this.logDirty = true\n if (this.logFlushTimer) return\n this.logFlushTimer = BgTimer.setTimeout(() => {\n this.logFlushTimer = null\n void this.persistLog().catch((err) =>\n console.warn(\"MemoryStore: debounced log write failed:\", err instanceof Error ? err.message : err),\n )\n }, delay)\n }\n\n private async persistLog(): Promise<void> {\n // Any write of the full array satisfies whatever the debounce was holding.\n this.logDirty = false\n if (this.logFlushTimer) {\n BgTimer.clearTimeout(this.logFlushTimer)\n this.logFlushTimer = null\n }\n if (this.loadedUserId == null) return\n this.hooks.backend.set(this.key(this.loadedUserId, LOG_SUFFIX), JSON.stringify(this.entries))\n }\n\n private async persistSummaries(): Promise<void> {\n if (this.loadedUserId == null) return\n this.hooks.backend.set(this.key(this.loadedUserId, SUMMARY_SUFFIX), JSON.stringify(this.summaries))\n }\n\n private emitChanged(): void {\n for (const listener of this.changeListeners) {\n try {\n listener()\n } catch (err) {\n console.warn(\"MemoryStore: onChanged listener threw:\", err instanceof Error ? err.message : err)\n }\n }\n }\n}\n\n/** Stored values may be a JSON string (SimpleStorage writes) or a raw array. */\nfunction parseArray(raw: unknown): unknown[] {\n try {\n if (typeof raw === \"string\") {\n const parsed = JSON.parse(raw) as unknown\n return Array.isArray(parsed) ? parsed : []\n }\n return Array.isArray(raw) ? raw : []\n } catch {\n return []\n }\n}\n\nfunction normalize(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \" \")\n .trim()\n}\n\nfunction isEntry(v: unknown): v is MemoryEntry {\n if (!v || typeof v !== \"object\") return false\n const e = v as Record<string, unknown>\n return (\n typeof e.id === \"string\" &&\n (e.kind === \"line\" || e.kind === \"note\") &&\n typeof e.text === \"string\" &&\n typeof e.at === \"number\"\n )\n}\n\nfunction isSummary(v: unknown): v is MemorySummary {\n if (!v || typeof v !== \"object\") return false\n const s = v as Record<string, unknown>\n return typeof s.hourStart === \"number\" && typeof s.text === \"string\" && typeof s.createdAt === \"number\"\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MiniappEngine — constructs the
|
|
2
|
+
* MiniappEngine — constructs the JSRuntime router singletons (crash controller,
|
|
3
3
|
* UI router, JS router), binds them to the native Crust module + the launcher,
|
|
4
4
|
* wires the dev-server background-respawn signal, and starts the message pump.
|
|
5
5
|
*
|
|
@@ -20,11 +20,11 @@ export interface MiniappEngine {
|
|
|
20
20
|
crashController: JSCrashController;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
* Construct (once) and return the
|
|
23
|
+
* Construct (once) and return the JSRuntime engine singletons. Starts the router's
|
|
24
24
|
* message pump on first call. Subsequent calls return the same instances.
|
|
25
25
|
*/
|
|
26
26
|
export declare function ensureMiniappEngine(): MiniappEngine;
|
|
27
|
-
/** Stop the
|
|
27
|
+
/** Stop the JSRuntime message pump and tear down router-managed JSContexts. */
|
|
28
28
|
export declare function stopMiniappEngine(): Promise<void>;
|
|
29
29
|
/** Returns the engine singletons if already constructed, else null. */
|
|
30
30
|
export declare function getMiniappEngine(): MiniappEngine | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MiniappEngine — constructs the
|
|
2
|
+
* MiniappEngine — constructs the JSRuntime router singletons (crash controller,
|
|
3
3
|
* UI router, JS router), binds them to the native Crust module + the launcher,
|
|
4
4
|
* wires the dev-server background-respawn signal, and starts the message pump.
|
|
5
5
|
*
|
|
@@ -30,7 +30,7 @@ function wireDevServerRespawnBackground(router, uiRouter) {
|
|
|
30
30
|
// hot-reload.
|
|
31
31
|
const resolved = await miniappLauncher.resolveBundle(packageName);
|
|
32
32
|
if (!resolved) {
|
|
33
|
-
console.warn(`
|
|
33
|
+
console.warn(`JSRuntime: respawn-bg could not resolve bundle for ${packageName}`);
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
36
|
// Force a respawn (kill + spawn) rather than launcher.ensureRunning,
|
|
@@ -41,7 +41,7 @@ function wireDevServerRespawnBackground(router, uiRouter) {
|
|
|
41
41
|
installedManifest: resolved.installedManifest,
|
|
42
42
|
});
|
|
43
43
|
if (!ok) {
|
|
44
|
-
console.warn(`
|
|
44
|
+
console.warn(`JSRuntime: respawn-bg failed for ${packageName}`);
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
// The respawned JSContext is a fresh MiniappSession with ui.bound false.
|
|
@@ -51,12 +51,12 @@ function wireDevServerRespawnBackground(router, uiRouter) {
|
|
|
51
51
|
uiRouter.notifyReopen(packageName);
|
|
52
52
|
}
|
|
53
53
|
catch (e) {
|
|
54
|
-
console.warn(`
|
|
54
|
+
console.warn(`JSRuntime: respawn-bg threw for ${packageName}:`, e);
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
* Construct (once) and return the
|
|
59
|
+
* Construct (once) and return the JSRuntime engine singletons. Starts the router's
|
|
60
60
|
* message pump on first call. Subsequent calls return the same instances.
|
|
61
61
|
*/
|
|
62
62
|
export function ensureMiniappEngine() {
|
|
@@ -90,7 +90,7 @@ export function ensureMiniappEngine() {
|
|
|
90
90
|
engine = { router, uiRouter, crashController };
|
|
91
91
|
return engine;
|
|
92
92
|
}
|
|
93
|
-
/** Stop the
|
|
93
|
+
/** Stop the JSRuntime message pump and tear down router-managed JSContexts. */
|
|
94
94
|
export async function stopMiniappEngine() {
|
|
95
95
|
const current = engine;
|
|
96
96
|
if (!current)
|
|
@@ -108,7 +108,7 @@ export async function stopMiniappEngine() {
|
|
|
108
108
|
await current.router.unregister(packageName);
|
|
109
109
|
}
|
|
110
110
|
catch (err) {
|
|
111
|
-
console.warn(`
|
|
111
|
+
console.warn(`JSRuntime: failed to unregister ${packageName} during stop:`, err);
|
|
112
112
|
}
|
|
113
113
|
}));
|
|
114
114
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MiniappEngine.js","sourceRoot":"","sources":["../../src/services/MiniappEngine.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MiniappEngine — constructs the
|
|
1
|
+
{"version":3,"file":"MiniappEngine.js","sourceRoot":"","sources":["../../src/services/MiniappEngine.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MiniappEngine — constructs the JSRuntime router singletons (crash controller,\n * UI router, JS router), binds them to the native Crust module + the launcher,\n * wires the dev-server background-respawn signal, and starts the message pump.\n *\n * Engine owns this so a bare OEM's `engine.start()` brings up the local-miniapp\n * engine with no host construction step. Host-only concerns that remain outside\n * engine, such as Glassly-app crashloop telemetry, are attached by the host after\n * this returns via `router.onCrashloop` / `router.onRestartToast`.\n *\n * Idempotent — `ensureMiniappEngine()` returns the same singletons on every call,\n * so it's safe to call from both `engine.start()` and the host bootstrap.\n */\n\nimport CrustModule from \"@glassly/crust\"\n\nimport devServerBridge from \"./DevServerBridge\"\nimport localMiniappRuntime from \"./LocalMiniappRuntime\"\nimport {miniappLauncher} from \"./MiniappLauncher\"\nimport {JSCrashController} from \"./JSCrashController\"\nimport {JSRouter, type JSCrustBinding} from \"./JSRouter\"\nimport {UIRouter} from \"./UIRouter\"\n\nexport interface MiniappEngine {\n router: JSRouter\n uiRouter: UIRouter\n crashController: JSCrashController\n}\n\nlet engine: MiniappEngine | null = null\n\nfunction wireDevServerRespawnBackground(router: JSRouter, uiRouter: UIRouter): void {\n devServerBridge.onRespawnBackground(async (packageName) => {\n try {\n // Re-resolve the freshly built bundle (dev: HTTP off the dev server;\n // released: file:// snapshot) via the launcher's shared recipe. Carries\n // the declared permissions + manifest across the respawn — omitting them\n // would respawn the JSContext with no permissions, so SUBSCRIBE gates and\n // per-call dispatch checks would start rejecting after a background\n // hot-reload.\n const resolved = await miniappLauncher.resolveBundle(packageName)\n if (!resolved) {\n console.warn(`JSRuntime: respawn-bg could not resolve bundle for ${packageName}`)\n return\n }\n // Force a respawn (kill + spawn) rather than launcher.ensureRunning,\n // which is idempotent and would no-op an already-registered context.\n await router.unregister(packageName)\n const ok = await router.spawnAndRegister(packageName, resolved.bgSource, {\n permissions: resolved.declaredPermissions,\n installedManifest: resolved.installedManifest,\n })\n if (!ok) {\n console.warn(`JSRuntime: respawn-bg failed for ${packageName}`)\n return\n }\n // The respawned JSContext is a fresh MiniappSession with ui.bound false.\n // The mounted WebView won't re-fire glassly.ready() (it's latched), so\n // re-announce it so RPC replies (glassly.request) reach the UI again\n // instead of being dropped while unbound.\n uiRouter.notifyReopen(packageName)\n } catch (e) {\n console.warn(`JSRuntime: respawn-bg threw for ${packageName}:`, e)\n }\n })\n}\n\n/**\n * Construct (once) and return the JSRuntime engine singletons. Starts the router's\n * message pump on first call. Subsequent calls return the same instances.\n */\nexport function ensureMiniappEngine(): MiniappEngine {\n if (engine) {\n wireDevServerRespawnBackground(engine.router, engine.uiRouter)\n engine.router.start()\n return engine\n }\n\n // The Crust native module's published TS typing doesn't include the new\n // js* functions until expo prebuild regenerates it; cast to the binding\n // shapes the routers expect.\n const crust = CrustModule as unknown as JSCrustBinding\n\n const crashController = new JSCrashController({\n maxRetries: 3,\n })\n const uiRouter = new UIRouter({\n jsDispatchToJs: (packageName: string, envelope: Record<string, unknown>) =>\n (\n CrustModule as unknown as {\n jsDispatchToJs: (p: string, e: Record<string, unknown>) => Promise<void>\n }\n ).jsDispatchToJs(packageName, envelope),\n })\n const router = new JSRouter(localMiniappRuntime, crust)\n router.crashController = crashController\n router.uiRouter = uiRouter\n\n // Hand the router to the engine MiniappLauncher so headless launch/teardown\n // (apps.ts start/stop, the action broker, the WebView mount path) all spawn\n // through one place.\n miniappLauncher.configure({router})\n\n // Wire up the dev server's \"respawn-bg\" signal so a touch under\n // src/background/ kills + re-spawns the JSContext with the latest bundle.\n // The WebView reload path stays separate (devServerBridge.onReload).\n wireDevServerRespawnBackground(router, uiRouter)\n\n router.start()\n\n engine = {router, uiRouter, crashController}\n return engine\n}\n\n/** Stop the JSRuntime message pump and tear down router-managed JSContexts. */\nexport async function stopMiniappEngine(): Promise<void> {\n const current = engine\n if (!current) return\n // Null the singleton BEFORE the async teardown below: a concurrent\n // ensureMiniappEngine() must construct fresh instead of re-starting (and\n // re-subscribing) the router that is mid-teardown, which would leak a zombie\n // Crust subscription once this function finishes.\n engine = null\n\n devServerBridge.clearRespawnBackgroundHandler()\n current.router.stop()\n\n const packages = current.router.registeredPackages()\n await Promise.all(\n packages.map(async (packageName) => {\n try {\n await current.router.unregister(packageName)\n } catch (err) {\n console.warn(`JSRuntime: failed to unregister ${packageName} during stop:`, err)\n }\n }),\n )\n}\n\n/** Returns the engine singletons if already constructed, else null. */\nexport function getMiniappEngine(): MiniappEngine | null {\n return engine\n}\n"]}
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
* resolved UI entry so the host can mount its `<WebView>`.
|
|
24
24
|
*/
|
|
25
25
|
import { type InstalledMiniappManifest } from "./LocalMiniappRuntime";
|
|
26
|
+
import type { MiniappLaunchSource } from "@glassly/miniapp";
|
|
26
27
|
import type { JSRouter } from "./JSRouter";
|
|
27
28
|
interface LauncherDeps {
|
|
28
29
|
/** The host-constructed router (needs the native Crust binding). */
|
|
@@ -33,6 +34,8 @@ export interface LaunchHints {
|
|
|
33
34
|
devUrl?: string;
|
|
34
35
|
version?: string;
|
|
35
36
|
devPort?: string;
|
|
37
|
+
/** Who started the app; reported to the miniapp on connect. */
|
|
38
|
+
launchSource?: MiniappLaunchSource;
|
|
36
39
|
}
|
|
37
40
|
/** Everything the launcher resolved for a package — bg source + UI entry. */
|
|
38
41
|
export interface ResolvedBundle {
|
|
@@ -108,6 +111,11 @@ declare class MiniappLauncher {
|
|
|
108
111
|
* Not compatibility-gated: a previously-running background app shouldn't be
|
|
109
112
|
* dropped just because glasses are momentarily disconnected at boot — it
|
|
110
113
|
* resumes when they reconnect, same as mid-session.
|
|
114
|
+
*
|
|
115
|
+
* Persistent apps (the dashboard) start whether or not they were running
|
|
116
|
+
* when the app was last killed, and get a switcher card like any other app.
|
|
117
|
+
* Both restore paths skip apps missing required OS permissions without
|
|
118
|
+
* prompting or clearing their saved running/persistent choice.
|
|
111
119
|
*/
|
|
112
120
|
autostartLocalMiniapps(): Promise<void>;
|
|
113
121
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MiniappLauncher.d.ts","sourceRoot":"","sources":["../../src/services/MiniappLauncher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;
|
|
1
|
+
{"version":3,"file":"MiniappLauncher.d.ts","sourceRoot":"","sources":["../../src/services/MiniappLauncher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AASH,OAA4B,EAAC,KAAK,wBAAwB,EAAC,MAAM,uBAAuB,CAAA;AACxF,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,kBAAkB,CAAA;AACzD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAA;AAExC,UAAU,YAAY;IACpB,oEAAoE;IACpE,MAAM,EAAE,QAAQ,CAAA;CACjB;AAED,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,mBAAmB,CAAA;CACnC;AAED,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,mBAAmB,EAAE,MAAM,EAAE,CAAA;IAC7B,iBAAiB,CAAC,EAAE,wBAAwB,CAAA;IAC5C,yEAAyE;IACzE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED,uDAAuD;AACvD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,cAAM,eAAe;IACnB,OAAO,CAAC,IAAI,CAA4B;IAExC;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2C;IAEpE,uEAAuE;IACvE,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAInC,OAAO,CAAC,aAAa;IAOrB,yEAAyE;IACzE,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIvC;;;;;;OAMG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IA8G7F;;;;;;;;;;OAUG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAwBpF,iFAAiF;YACnE,KAAK;IAkCnB;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACG,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAgC7C;;;;OAIG;IACG,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,gBAAgB,SAAS,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKzG,mDAAmD;IAC7C,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB9C,OAAO,CAAC,YAAY;IAKpB,4EAA4E;IAC5E,OAAO,CAAC,cAAc;CASvB;AAED,eAAO,MAAM,eAAe,iBAAwB,CAAA"}
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
* resolved UI entry so the host can mount its `<WebView>`.
|
|
24
24
|
*/
|
|
25
25
|
import { File } from "expo-file-system";
|
|
26
|
+
import { permissions } from "../facades/permissions";
|
|
26
27
|
import { decideDevLaunchRoute } from "../utils/devMiniappLaunch";
|
|
27
28
|
import { storage } from "../utils/storage/storage";
|
|
28
29
|
import appRegistry, { getLocalAppRunningState, saveLocalAppRunningState } from "./AppRegistry";
|
|
@@ -201,6 +202,7 @@ class MiniappLauncher {
|
|
|
201
202
|
const ok = await router.spawnAndRegister(packageName, resolved.bgSource, {
|
|
202
203
|
permissions: resolved.declaredPermissions,
|
|
203
204
|
installedManifest: resolved.installedManifest,
|
|
205
|
+
launchSource: hints?.launchSource,
|
|
204
206
|
});
|
|
205
207
|
if (!ok) {
|
|
206
208
|
throw new Error(`MiniappLauncher: spawn failed for ${packageName}`);
|
|
@@ -240,6 +242,11 @@ class MiniappLauncher {
|
|
|
240
242
|
* Not compatibility-gated: a previously-running background app shouldn't be
|
|
241
243
|
* dropped just because glasses are momentarily disconnected at boot — it
|
|
242
244
|
* resumes when they reconnect, same as mid-session.
|
|
245
|
+
*
|
|
246
|
+
* Persistent apps (the dashboard) start whether or not they were running
|
|
247
|
+
* when the app was last killed, and get a switcher card like any other app.
|
|
248
|
+
* Both restore paths skip apps missing required OS permissions without
|
|
249
|
+
* prompting or clearing their saved running/persistent choice.
|
|
243
250
|
*/
|
|
244
251
|
async autostartLocalMiniapps() {
|
|
245
252
|
const apps = await appRegistry.getInstalledMiniapps();
|
|
@@ -249,10 +256,21 @@ class MiniappLauncher {
|
|
|
249
256
|
// state elsewhere and have no bundle to launch.
|
|
250
257
|
if (!app.local)
|
|
251
258
|
continue;
|
|
252
|
-
if (!getLocalAppRunningState(app.packageName))
|
|
259
|
+
if (!app.persistent && !getLocalAppRunningState(app.packageName))
|
|
253
260
|
continue;
|
|
254
261
|
if (this.isRunning(app.packageName))
|
|
255
262
|
continue;
|
|
263
|
+
try {
|
|
264
|
+
const missing = await permissions.missingRequired(app.permissions ?? []);
|
|
265
|
+
if (missing.length > 0) {
|
|
266
|
+
console.info(`MiniappLauncher: skipping autostart for ${app.packageName} — missing required permissions: ${missing.join(", ")}`);
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
catch (e) {
|
|
271
|
+
console.warn(`MiniappLauncher: skipping autostart for ${app.packageName} — permission check failed`, e);
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
256
274
|
try {
|
|
257
275
|
await this.ensureRunning(app.packageName);
|
|
258
276
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MiniappLauncher.js","sourceRoot":"","sources":["../../src/services/MiniappLauncher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAErC,OAAO,EAAC,oBAAoB,EAAC,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAC,OAAO,EAAC,MAAM,0BAA0B,CAAA;AAChD,OAAO,WAAW,EAAE,EAAC,uBAAuB,EAAE,wBAAwB,EAAC,MAAM,eAAe,CAAA;AAC5F,OAAO,eAAe,MAAM,mBAAmB,CAAA;AAC/C,OAAO,mBAAoD,MAAM,uBAAuB,CAAA;AAiCxF,MAAM,eAAe;IACX,IAAI,GAAwB,IAAI,CAAA;IAExC;;;;;;OAMG;IACc,QAAQ,GAAG,IAAI,GAAG,EAAiC,CAAA;IAEpE,uEAAuE;IACvE,SAAS,CAAC,IAAkB;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAEO,aAAa;QACnB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAA;QACvF,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAA;IACzB,CAAC;IAED,yEAAyE;IACzE,SAAS,CAAC,WAAmB;QAC3B,OAAO,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,kBAAkB,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,CAAA;IAC9E,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,aAAa,CAAC,WAAmB,EAAE,KAAmB;QAC1D,MAAM,MAAM,GAAG,KAAK,EAAE,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;QAE9D,iEAAiE;QACjE,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,KAAK,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;YAC7D,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,QAAQ;gBAAE,OAAO,IAAI,CAAA;YAChE,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAA;YAC/B,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAuD,CAAA;YAC9E,IAAI,CAAC,KAAK,EAAE,UAAU;gBAAE,OAAO,IAAI,CAAA;YAEnC,sEAAsE;YACtE,mFAAmF;YACnF,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YACjD,wEAAwE;YACxE,2CAA2C;YAC3C,MAAM,KAAK,GAAG,GAAG,IAAI,SAAS,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,CAAA;YACvE,MAAM,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;YAEjF,MAAM,KAAK,GAAG,QAAQ,CAAC,WAA0D,CAAA;YACjF,MAAM,mBAAmB,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;iBACtC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;iBACjD,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAA;YACpD,MAAM,iBAAiB,GAA6B;gBAClD,WAAW,EAAE,OAAO,QAAQ,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW;gBAC1F,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,OAAO,EAAE,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;gBAC5E,UAAU,EAAE,OAAO,QAAQ,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;gBACrF,cAAc,EAAE,OAAO,QAAQ,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS;gBACjG,IAAI,EAAE,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;gBACnE,KAAK,EAAE,QAAQ,CAAC,KAA0C;gBAC1D,WAAW,EAAE,QAAQ,CAAC,WAAsD;gBAC5E,oBAAoB,EAAE,QAAQ,CAAC,oBAAwE;gBACvG,OAAO,EAAE,QAAQ,CAAC,OAA8C;aACjE,CAAA;YAED,IAAI,QAAgB,CAAA;YACpB,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,CAAA;gBAC9B,IAAI,CAAC,GAAG,CAAC,EAAE;oBAAE,OAAO,IAAI,CAAA;gBACxB,QAAQ,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;YAC7B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAA;YACb,CAAC;YAED,OAAO;gBACL,QAAQ;gBACR,KAAK;gBACL,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;gBACxD,mBAAmB;gBACnB,iBAAiB;gBACjB,MAAM,EAAE,KAAK,CAAC,WAAW;gBACzB,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC;aAC1D,CAAA;QACH,CAAC;QAED,iEAAiE;QACjE,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,IAAI,CAAC,MAAM,WAAW,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAA;QACnF,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAA;QACzB,MAAM,UAAU,GAAG,WAAW,CAAC,oBAAoB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QACzE,IAAI,CAAC,UAAU,EAAE,UAAU;YAAE,OAAO,IAAI,CAAA;QAExC,MAAM,QAAQ,GAAG,WAAW,CAAC,kBAAkB,CAAC,WAAW,EAAE,OAAO,CAW5D,CAAA;QACR,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,WAAW,IAAI,EAAE,CAAC;aACtD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;aAClB,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAA;QACpD,MAAM,iBAAiB,GAAyC,QAAQ;YACtE,CAAC,CAAC;gBACE,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,WAAW;gBAChD,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,OAAO,EAAE,QAAQ,CAAC,OAAO,IAAI,OAAO;gBACpC,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,cAAc,EAAE,QAAQ,CAAC,cAAc;gBACvC,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,oBAAoB,EAAE,QAAQ,CAAC,oBAAoB;gBACnD,OAAO,EAAE,QAAQ,CAAC,OAAO;aAC1B;YACH,CAAC,CAAC,SAAS,CAAA;QAEb,IAAI,QAAgB,CAAA;QACpB,IAAI,CAAC;YACH,QAAQ,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,CAAA;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;QAED,OAAO;YACL,QAAQ;YACR,KAAK,EAAE,UAAU,CAAC,EAAE,IAAI,IAAI;YAC5B,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;YACxE,mBAAmB;YACnB,iBAAiB;YACjB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,IAAI;SACd,CAAA;IACH,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,aAAa,CAAC,WAAmB,EAAE,KAAmB;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAA;QAEnC,uEAAuE;QACvE,wEAAwE;QACxE,oCAAoC;QACpC,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACtD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;YAC/E,OAAO,EAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,IAAI,IAAI,EAAC,CAAA;QACjF,CAAC;QAED,qEAAqE;QACrE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC9C,IAAI,OAAO;YAAE,OAAO,OAAO,CAAA;QAE3B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;QAC7C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QACtC,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,CAAA;QACrB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;IAED,iFAAiF;IACzE,KAAK,CAAC,KAAK,CAAC,WAAmB,EAAE,KAAmB;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAA;QACnC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;QAC7D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,8CAA8C,WAAW,EAAE,CAAC,CAAA;QAC9E,CAAC;QAED,yEAAyE;QACzE,6CAA6C;QAC7C,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACvD,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,QAAQ,CAAC,QAAQ,EAAE;gBACvE,WAAW,EAAE,QAAQ,CAAC,mBAAmB;gBACzC,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;aAC9C,CAAC,CAAA;YACF,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,MAAM,IAAI,KAAK,CAAC,qCAAqC,WAAW,EAAE,CAAC,CAAA;YACrE,CAAC;YAED,mEAAmE;YACnE,0DAA0D;YAC1D,IAAI,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;gBAChD,eAAe,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;YACzE,CAAC;iBAAM,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;gBAC3B,mEAAmE;gBACnE,uEAAuE;gBACvE,iEAAiE;gBACjE,OAAO,CAAC,IAAI,CAAC,oBAAoB,WAAW,yDAAyD,CAAC,CAAA;YACxG,CAAC;QACH,CAAC;QAED,OAAO,EAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAC,CAAA;IAC/D,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,KAAK,CAAC,sBAAsB;QAC1B,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,oBAAoB,EAAE,CAAA;QACrD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,mEAAmE;YACnE,uEAAuE;YACvE,gDAAgD;YAChD,IAAI,CAAC,GAAG,CAAC,KAAK;gBAAE,SAAQ;YACxB,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,WAAW,CAAC;gBAAE,SAAQ;YACvD,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC;gBAAE,SAAQ;YAC7C,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;YAC3C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC,yCAAyC,GAAG,CAAC,WAAW,gCAAgC,EAAE,CAAC,CAAC,CAAA;gBACzG,wBAAwB,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,eAAe,CAAC,WAAmB,EAAE,gBAAgB,GAAG,MAAM,EAAE,KAAmB;QACvF,MAAM,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;QAC5C,MAAM,mBAAmB,CAAC,cAAc,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAA;IACzE,CAAC;IAED,mDAAmD;IACnD,KAAK,CAAC,IAAI,CAAC,WAAmB;QAC5B,wEAAwE;QACxE,sEAAsE;QACtE,kEAAkE;QAClE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC9C,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC;gBACH,MAAM,OAAO,CAAA;YACf,CAAC;YAAC,MAAM,CAAC;gBACP,mEAAmE;YACrE,CAAC;QACH,CAAC;QACD,MAAM,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAA;IACjD,CAAC;IAED,4EAA4E;IAEpE,YAAY,CAAC,WAAmB;QACtC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAS,GAAG,WAAW,UAAU,CAAC,CAAA;QACxD,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;IACxC,CAAC;IAED,4EAA4E;IACpE,cAAc,CAAC,WAA+B,EAAE,WAAmB;QACzE,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,CAAC,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;YACnC,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,OAAO,CAAC,CAAA;QAClC,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAS,GAAG,WAAW,WAAW,CAAC,CAAA;QAC9D,IAAI,MAAM,CAAC,KAAK,EAAE;YAAE,OAAO,MAAM,CAAC,KAAK,CAAA;QACvC,OAAO,IAAI,CAAA;IACb,CAAC;CACF;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAA","sourcesContent":["/**\n * MiniappLauncher — headless launch/teardown of a local miniapp's background\n * JS context.\n *\n * This is the one piece of \"run a miniapp\" that used to live inside the\n * `LocalMiniappView` React component (resolve the bundle → read the manifest →\n * `spawnAndRegister`), triggered only when the Compositor mounted that\n * component on foreground. Pulling it into the runtime means:\n *\n * - `start()` can actually spawn an app even when nothing foregrounds it\n * (e.g. a system app launching another miniapp via `session.miniapps`).\n * - the action broker can wake a stopped target headlessly — no UI at all.\n * - the dev hot-reload respawn path and the WebView mount path share one\n * resolve+spawn recipe instead of three copies.\n *\n * The launcher is **headless**: no React, no RN components. The engine-owned\n * MiniappEngine hands it the {@link JSRouter} instance once during\n * engine construction. OEMs embedding the runtime drive miniapp lifecycle\n * through the engine facade and stores, not a separate launcher configure API.\n *\n * Boundary: the launcher owns the **background** context. WebView *rendering*\n * (the UI layer) stays with the host — the launcher just hands back the\n * resolved UI entry so the host can mount its `<WebView>`.\n */\n\nimport {File} from \"expo-file-system\"\n\nimport {decideDevLaunchRoute} from \"../utils/devMiniappLaunch\"\nimport {storage} from \"../utils/storage/storage\"\nimport appRegistry, {getLocalAppRunningState, saveLocalAppRunningState} from \"./AppRegistry\"\nimport devServerBridge from \"./DevServerBridge\"\nimport localMiniappRuntime, {type InstalledMiniappManifest} from \"./LocalMiniappRuntime\"\nimport type {JSRouter} from \"./JSRouter\"\n\ninterface LauncherDeps {\n /** The host-constructed router (needs the native Crust binding). */\n router: JSRouter\n}\n\n/** Hints the host may pass from a view's props to avoid re-deriving them. */\nexport interface LaunchHints {\n devUrl?: string\n version?: string\n devPort?: string\n}\n\n/** Everything the launcher resolved for a package — bg source + UI entry. */\nexport interface ResolvedBundle {\n bgSource: string\n uiUri: string | null\n uiBaseDir: string | null\n declaredPermissions: string[]\n installedManifest?: InstalledMiniappManifest\n /** Set for dev miniapps (HTTP off the dev server); null for released. */\n devUrl: string | null\n devPort: number | null\n}\n\n/** What the host needs back to render the UI layer. */\nexport interface LaunchResult {\n uiUri: string | null\n uiBaseDir: string | null\n}\n\nclass MiniappLauncher {\n private deps: LauncherDeps | null = null\n\n /**\n * In-flight launches keyed by packageName. Both apps.ts start() and the\n * WebView mount call ensureRunning() before the first spawnAndRegister\n * resolves — without this, neither sees the package in registeredPackages()\n * yet and both spawn the same context (a clobber/double-spawn). Concurrent\n * callers share the same promise.\n */\n private readonly inFlight = new Map<string, Promise<LaunchResult>>()\n\n /** Wire the router in. Called once from MiniappEngine construction. */\n configure(deps: LauncherDeps): void {\n this.deps = deps\n }\n\n private requireRouter(): JSRouter {\n if (!this.deps) {\n throw new Error(\"MiniappLauncher not configured — ensureMiniappEngine() has not run\")\n }\n return this.deps.router\n }\n\n /** True iff the package's background JS context is currently spawned. */\n isRunning(packageName: string): boolean {\n return this.deps?.router.registeredPackages().includes(packageName) ?? false\n }\n\n /**\n * Resolve the background JS source + UI entry + declared permissions for a\n * package. Handles both dev (HTTP off the running dev server) and released\n * (file:// from the installed snapshot). Reads disk/network/storage; does\n * NOT spawn. Returns null when the bundle can't be resolved (dev server\n * unreachable, missing entry, no installed version).\n */\n async resolveBundle(packageName: string, hints?: LaunchHints): Promise<ResolvedBundle | null> {\n const devUrl = hints?.devUrl ?? this.storedDevUrl(packageName)\n\n // --- Dev: load directly off the local dev server over HTTP. ---\n if (devUrl) {\n const route = await decideDevLaunchRoute(packageName, devUrl)\n if (route.decision === \"offline\" || !route.manifest) return null\n const manifest = route.manifest\n const entry = manifest.entry as {background?: string; ui?: string} | undefined\n if (!entry?.background) return null\n\n // Use the host that actually answered — may differ from the stored IP\n // after a laptop Wi-Fi change (mDNS / Metro failover inside decideDevLaunchRoute).\n const base = route.resolvedUrl.replace(/\\/$/, \"\")\n // entry.* are bundle-root paths (dist/ stripped); the dev server serves\n // files relative to cwd, so prepend dist/.\n const bgUrl = `${base}/dist/${entry.background.replace(/^\\.?\\/+/, \"\")}`\n const uiUri = entry.ui ? `${base}/dist/${entry.ui.replace(/^\\.?\\/+/, \"\")}` : null\n\n const perms = manifest.permissions as Array<{type?: string} | string> | undefined\n const declaredPermissions = (perms ?? [])\n .map((p) => (typeof p === \"string\" ? p : p?.type))\n .filter((t): t is string => typeof t === \"string\")\n const installedManifest: InstalledMiniappManifest = {\n packageName: typeof manifest.packageName === \"string\" ? manifest.packageName : packageName,\n name: manifest.name,\n version: typeof manifest.version === \"string\" ? manifest.version : undefined,\n sdkVersion: typeof manifest.sdkVersion === \"string\" ? manifest.sdkVersion : undefined,\n minHostVersion: typeof manifest.minHostVersion === \"string\" ? manifest.minHostVersion : undefined,\n type: typeof manifest.type === \"string\" ? manifest.type : undefined,\n entry: manifest.entry as InstalledMiniappManifest[\"entry\"],\n permissions: manifest.permissions as InstalledMiniappManifest[\"permissions\"],\n hardwareRequirements: manifest.hardwareRequirements as InstalledMiniappManifest[\"hardwareRequirements\"],\n actions: manifest.actions as InstalledMiniappManifest[\"actions\"],\n }\n\n let bgSource: string\n try {\n const res = await fetch(bgUrl)\n if (!res.ok) return null\n bgSource = await res.text()\n } catch {\n return null\n }\n\n return {\n bgSource,\n uiUri,\n uiBaseDir: uiUri ? uiUri.replace(/\\/[^/]+$/, \"/\") : null,\n declaredPermissions,\n installedManifest,\n devUrl: route.resolvedUrl,\n devPort: this.resolveDevPort(hints?.devPort, packageName),\n }\n }\n\n // --- Released: resolve from the installed file:// snapshot. ---\n const version = hints?.version ?? (await appRegistry.getActiveVersion(packageName))\n if (!version) return null\n const entryPaths = appRegistry.getMiniappEntryPaths(packageName, version)\n if (!entryPaths?.background) return null\n\n const manifest = appRegistry.getMiniappManifest(packageName, version) as {\n packageName?: string\n name?: string\n version?: string\n sdkVersion?: string\n minHostVersion?: string\n type?: string\n entry?: {background?: string; ui?: string}\n permissions?: Array<{type: string; required?: boolean; description?: string}>\n hardwareRequirements?: Array<{type: string; level: string; description?: string}>\n actions?: Array<{id?: unknown; description?: unknown; parameters?: unknown; outputSchema?: unknown}>\n } | null\n const declaredPermissions = (manifest?.permissions ?? [])\n .map((p) => p.type)\n .filter((t): t is string => typeof t === \"string\")\n const installedManifest: InstalledMiniappManifest | undefined = manifest\n ? {\n packageName: manifest.packageName ?? packageName,\n name: manifest.name,\n version: manifest.version ?? version,\n sdkVersion: manifest.sdkVersion,\n minHostVersion: manifest.minHostVersion,\n type: manifest.type,\n entry: manifest.entry,\n permissions: manifest.permissions,\n hardwareRequirements: manifest.hardwareRequirements,\n actions: manifest.actions,\n }\n : undefined\n\n let bgSource: string\n try {\n bgSource = new File(entryPaths.background).textSync()\n } catch {\n return null\n }\n\n return {\n bgSource,\n uiUri: entryPaths.ui ?? null,\n uiBaseDir: entryPaths.ui ? entryPaths.ui.replace(/\\/[^/]+$/, \"/\") : null,\n declaredPermissions,\n installedManifest,\n devUrl: null,\n devPort: null,\n }\n }\n\n /**\n * Ensure a miniapp's background JS context is spawned. Idempotent — if the\n * context is already alive this is a no-op spawn-wise (it still resolves the\n * UI entry so a re-mounting host gets its `<WebView>` source back).\n *\n * Resolves once the context is SPAWNED. It does NOT block on the context's\n * CONNECT handshake — the host's WebView mount shouldn't wait on background\n * JS. Callers that need the context to be connected and ready to receive\n * messages (the action broker) follow up with\n * {@link LocalMiniappRuntime.waitForConnect}.\n */\n async ensureRunning(packageName: string, hints?: LaunchHints): Promise<LaunchResult> {\n const router = this.requireRouter()\n\n // Already spawned: best-effort resolve for the UI entry, never throw —\n // a headless caller that doesn't need UI gets {null, null} fast even if\n // the dev server has since dropped.\n if (router.registeredPackages().includes(packageName)) {\n const existing = await this.resolveBundle(packageName, hints).catch(() => null)\n return {uiUri: existing?.uiUri ?? null, uiBaseDir: existing?.uiBaseDir ?? null}\n }\n\n // Coalesce concurrent launches of the same package onto one promise.\n const pending = this.inFlight.get(packageName)\n if (pending) return pending\n\n const launch = this.spawn(packageName, hints)\n this.inFlight.set(packageName, launch)\n try {\n return await launch\n } finally {\n this.inFlight.delete(packageName)\n }\n }\n\n /** Resolve the bundle and spawn the context. Serialized via {@link inFlight}. */\n private async spawn(packageName: string, hints?: LaunchHints): Promise<LaunchResult> {\n const router = this.requireRouter()\n const resolved = await this.resolveBundle(packageName, hints)\n if (!resolved) {\n throw new Error(`MiniappLauncher: cannot resolve bundle for ${packageName}`)\n }\n\n // Re-check after the async resolve: a different path may have spawned it\n // while we were fetching/reading the bundle.\n if (!router.registeredPackages().includes(packageName)) {\n const ok = await router.spawnAndRegister(packageName, resolved.bgSource, {\n permissions: resolved.declaredPermissions,\n installedManifest: resolved.installedManifest,\n })\n if (!ok) {\n throw new Error(`MiniappLauncher: spawn failed for ${packageName}`)\n }\n\n // Dev: wire the hot-reload + log-forwarding sidecar. No-op in prod\n // (devServerBridge silently drops when no sidecar is up).\n if (resolved.devUrl && resolved.devPort != null) {\n devServerBridge.connect(packageName, resolved.devUrl, resolved.devPort)\n } else if (resolved.devUrl) {\n // Dev miniapp with no resolvable port — it still launches, but hot\n // reload + log forwarding won't connect. Surface it instead of failing\n // silently (the old inline path hard-failed with \"no dev port\").\n console.warn(`MiniappLauncher: ${packageName} has no dev port — hot reload + log forwarding disabled`)\n }\n }\n\n return {uiUri: resolved.uiUri, uiBaseDir: resolved.uiBaseDir}\n }\n\n /**\n * Re-spawn local miniapps that were running when the app was last killed.\n *\n * Miniapps run in the phone's own JS engine, so a host-process kill tears\n * down their JSContext with nothing to resurrect them. Without this they\n * would silently stay stopped on the next launch even though the user left\n * them running.\n *\n * Each local miniapp persists its running flag to disk on start/stop\n * (`saveLocalAppRunningState`, via the applet's `onStart`/`onStop`). We read\n * those flags back and re-spawn the background context headlessly (no\n * foreground, no navigation) — the spawn registers the package so the home\n * tray/switcher project it as running, exactly as a normal start would. The\n * WebView, if any, re-attaches lazily when the user opens the app.\n *\n * Idempotent and best-effort: skips already-spawned contexts, and clears the\n * persisted flag for any app whose bundle can no longer be resolved\n * (uninstalled, or dev server gone) so a dead entry doesn't retry every boot.\n * Not compatibility-gated: a previously-running background app shouldn't be\n * dropped just because glasses are momentarily disconnected at boot — it\n * resumes when they reconnect, same as mid-session.\n */\n async autostartLocalMiniapps(): Promise<void> {\n const apps = await appRegistry.getInstalledMiniapps()\n for (const app of apps) {\n // Only phone-hosted miniapps have a JSContext to re-spawn. Offline\n // built-ins (`local:false, offline:true`) restore their native running\n // state elsewhere and have no bundle to launch.\n if (!app.local) continue\n if (!getLocalAppRunningState(app.packageName)) continue\n if (this.isRunning(app.packageName)) continue\n try {\n await this.ensureRunning(app.packageName)\n } catch (e) {\n console.warn(`MiniappLauncher: autostart failed for ${app.packageName} — clearing stale running flag`, e)\n saveLocalAppRunningState(app.packageName, false)\n }\n }\n }\n\n /**\n * Ensure the context is running AND has completed its CONNECT handshake.\n * Used by the action broker, which must not deliver to a context that hasn't\n * come up yet. Throws on spawn failure or connect timeout.\n */\n async ensureConnected(packageName: string, connectTimeoutMs = 10_000, hints?: LaunchHints): Promise<void> {\n await this.ensureRunning(packageName, hints)\n await localMiniappRuntime.waitForConnect(packageName, connectTimeoutMs)\n }\n\n /** Tear down a miniapp's background JS context. */\n async stop(packageName: string): Promise<void> {\n // If a launch is in flight, let it finish first. Otherwise unregister()\n // no-ops on the not-yet-registered package and the pending spawn then\n // re-registers the context — leaving it running despite the stop.\n const pending = this.inFlight.get(packageName)\n if (pending) {\n try {\n await pending\n } catch {\n // Launch failed — nothing got registered, so nothing to tear down.\n }\n }\n await this.deps?.router.unregister(packageName)\n }\n\n // --- internals -----------------------------------------------------------\n\n private storedDevUrl(packageName: string): string | undefined {\n const r = storage.load<string>(`${packageName}_dev_url`)\n return r.is_ok() ? r.value : undefined\n }\n\n /** resolveDevPort — moved verbatim from the old LocalMiniappView helper. */\n private resolveDevPort(searchParam: string | undefined, packageName: string): number | null {\n if (searchParam) {\n const n = parseInt(searchParam, 10)\n if (Number.isFinite(n)) return n\n }\n const stored = storage.load<number>(`${packageName}_dev_port`)\n if (stored.is_ok()) return stored.value\n return null\n }\n}\n\nexport const miniappLauncher = new MiniappLauncher()\n"]}
|
|
1
|
+
{"version":3,"file":"MiniappLauncher.js","sourceRoot":"","sources":["../../src/services/MiniappLauncher.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MiniappLauncher — headless launch/teardown of a local miniapp's background\n * JS context.\n *\n * This is the one piece of \"run a miniapp\" that used to live inside the\n * `LocalMiniappView` React component (resolve the bundle → read the manifest →\n * `spawnAndRegister`), triggered only when the Compositor mounted that\n * component on foreground. Pulling it into the runtime means:\n *\n * - `start()` can actually spawn an app even when nothing foregrounds it\n * (e.g. a system app launching another miniapp via `session.miniapps`).\n * - the action broker can wake a stopped target headlessly — no UI at all.\n * - the dev hot-reload respawn path and the WebView mount path share one\n * resolve+spawn recipe instead of three copies.\n *\n * The launcher is **headless**: no React, no RN components. The engine-owned\n * MiniappEngine hands it the {@link JSRouter} instance once during\n * engine construction. OEMs embedding the runtime drive miniapp lifecycle\n * through the engine facade and stores, not a separate launcher configure API.\n *\n * Boundary: the launcher owns the **background** context. WebView *rendering*\n * (the UI layer) stays with the host — the launcher just hands back the\n * resolved UI entry so the host can mount its `<WebView>`.\n */\n\nimport {File} from \"expo-file-system\"\n\nimport {permissions} from \"../facades/permissions\"\nimport {decideDevLaunchRoute} from \"../utils/devMiniappLaunch\"\nimport {storage} from \"../utils/storage/storage\"\nimport appRegistry, {getLocalAppRunningState, saveLocalAppRunningState} from \"./AppRegistry\"\nimport devServerBridge from \"./DevServerBridge\"\nimport localMiniappRuntime, {type InstalledMiniappManifest} from \"./LocalMiniappRuntime\"\nimport type {MiniappLaunchSource} from \"@glassly/miniapp\"\nimport type {JSRouter} from \"./JSRouter\"\n\ninterface LauncherDeps {\n /** The host-constructed router (needs the native Crust binding). */\n router: JSRouter\n}\n\n/** Hints the host may pass from a view's props to avoid re-deriving them. */\nexport interface LaunchHints {\n devUrl?: string\n version?: string\n devPort?: string\n /** Who started the app; reported to the miniapp on connect. */\n launchSource?: MiniappLaunchSource\n}\n\n/** Everything the launcher resolved for a package — bg source + UI entry. */\nexport interface ResolvedBundle {\n bgSource: string\n uiUri: string | null\n uiBaseDir: string | null\n declaredPermissions: string[]\n installedManifest?: InstalledMiniappManifest\n /** Set for dev miniapps (HTTP off the dev server); null for released. */\n devUrl: string | null\n devPort: number | null\n}\n\n/** What the host needs back to render the UI layer. */\nexport interface LaunchResult {\n uiUri: string | null\n uiBaseDir: string | null\n}\n\nclass MiniappLauncher {\n private deps: LauncherDeps | null = null\n\n /**\n * In-flight launches keyed by packageName. Both apps.ts start() and the\n * WebView mount call ensureRunning() before the first spawnAndRegister\n * resolves — without this, neither sees the package in registeredPackages()\n * yet and both spawn the same context (a clobber/double-spawn). Concurrent\n * callers share the same promise.\n */\n private readonly inFlight = new Map<string, Promise<LaunchResult>>()\n\n /** Wire the router in. Called once from MiniappEngine construction. */\n configure(deps: LauncherDeps): void {\n this.deps = deps\n }\n\n private requireRouter(): JSRouter {\n if (!this.deps) {\n throw new Error(\"MiniappLauncher not configured — ensureMiniappEngine() has not run\")\n }\n return this.deps.router\n }\n\n /** True iff the package's background JS context is currently spawned. */\n isRunning(packageName: string): boolean {\n return this.deps?.router.registeredPackages().includes(packageName) ?? false\n }\n\n /**\n * Resolve the background JS source + UI entry + declared permissions for a\n * package. Handles both dev (HTTP off the running dev server) and released\n * (file:// from the installed snapshot). Reads disk/network/storage; does\n * NOT spawn. Returns null when the bundle can't be resolved (dev server\n * unreachable, missing entry, no installed version).\n */\n async resolveBundle(packageName: string, hints?: LaunchHints): Promise<ResolvedBundle | null> {\n const devUrl = hints?.devUrl ?? this.storedDevUrl(packageName)\n\n // --- Dev: load directly off the local dev server over HTTP. ---\n if (devUrl) {\n const route = await decideDevLaunchRoute(packageName, devUrl)\n if (route.decision === \"offline\" || !route.manifest) return null\n const manifest = route.manifest\n const entry = manifest.entry as {background?: string; ui?: string} | undefined\n if (!entry?.background) return null\n\n // Use the host that actually answered — may differ from the stored IP\n // after a laptop Wi-Fi change (mDNS / Metro failover inside decideDevLaunchRoute).\n const base = route.resolvedUrl.replace(/\\/$/, \"\")\n // entry.* are bundle-root paths (dist/ stripped); the dev server serves\n // files relative to cwd, so prepend dist/.\n const bgUrl = `${base}/dist/${entry.background.replace(/^\\.?\\/+/, \"\")}`\n const uiUri = entry.ui ? `${base}/dist/${entry.ui.replace(/^\\.?\\/+/, \"\")}` : null\n\n const perms = manifest.permissions as Array<{type?: string} | string> | undefined\n const declaredPermissions = (perms ?? [])\n .map((p) => (typeof p === \"string\" ? p : p?.type))\n .filter((t): t is string => typeof t === \"string\")\n const installedManifest: InstalledMiniappManifest = {\n packageName: typeof manifest.packageName === \"string\" ? manifest.packageName : packageName,\n name: manifest.name,\n version: typeof manifest.version === \"string\" ? manifest.version : undefined,\n sdkVersion: typeof manifest.sdkVersion === \"string\" ? manifest.sdkVersion : undefined,\n minHostVersion: typeof manifest.minHostVersion === \"string\" ? manifest.minHostVersion : undefined,\n type: typeof manifest.type === \"string\" ? manifest.type : undefined,\n entry: manifest.entry as InstalledMiniappManifest[\"entry\"],\n permissions: manifest.permissions as InstalledMiniappManifest[\"permissions\"],\n hardwareRequirements: manifest.hardwareRequirements as InstalledMiniappManifest[\"hardwareRequirements\"],\n actions: manifest.actions as InstalledMiniappManifest[\"actions\"],\n }\n\n let bgSource: string\n try {\n const res = await fetch(bgUrl)\n if (!res.ok) return null\n bgSource = await res.text()\n } catch {\n return null\n }\n\n return {\n bgSource,\n uiUri,\n uiBaseDir: uiUri ? uiUri.replace(/\\/[^/]+$/, \"/\") : null,\n declaredPermissions,\n installedManifest,\n devUrl: route.resolvedUrl,\n devPort: this.resolveDevPort(hints?.devPort, packageName),\n }\n }\n\n // --- Released: resolve from the installed file:// snapshot. ---\n const version = hints?.version ?? (await appRegistry.getActiveVersion(packageName))\n if (!version) return null\n const entryPaths = appRegistry.getMiniappEntryPaths(packageName, version)\n if (!entryPaths?.background) return null\n\n const manifest = appRegistry.getMiniappManifest(packageName, version) as {\n packageName?: string\n name?: string\n version?: string\n sdkVersion?: string\n minHostVersion?: string\n type?: string\n entry?: {background?: string; ui?: string}\n permissions?: Array<{type: string; required?: boolean; description?: string}>\n hardwareRequirements?: Array<{type: string; level: string; description?: string}>\n actions?: Array<{id?: unknown; description?: unknown; parameters?: unknown; outputSchema?: unknown}>\n } | null\n const declaredPermissions = (manifest?.permissions ?? [])\n .map((p) => p.type)\n .filter((t): t is string => typeof t === \"string\")\n const installedManifest: InstalledMiniappManifest | undefined = manifest\n ? {\n packageName: manifest.packageName ?? packageName,\n name: manifest.name,\n version: manifest.version ?? version,\n sdkVersion: manifest.sdkVersion,\n minHostVersion: manifest.minHostVersion,\n type: manifest.type,\n entry: manifest.entry,\n permissions: manifest.permissions,\n hardwareRequirements: manifest.hardwareRequirements,\n actions: manifest.actions,\n }\n : undefined\n\n let bgSource: string\n try {\n bgSource = new File(entryPaths.background).textSync()\n } catch {\n return null\n }\n\n return {\n bgSource,\n uiUri: entryPaths.ui ?? null,\n uiBaseDir: entryPaths.ui ? entryPaths.ui.replace(/\\/[^/]+$/, \"/\") : null,\n declaredPermissions,\n installedManifest,\n devUrl: null,\n devPort: null,\n }\n }\n\n /**\n * Ensure a miniapp's background JS context is spawned. Idempotent — if the\n * context is already alive this is a no-op spawn-wise (it still resolves the\n * UI entry so a re-mounting host gets its `<WebView>` source back).\n *\n * Resolves once the context is SPAWNED. It does NOT block on the context's\n * CONNECT handshake — the host's WebView mount shouldn't wait on background\n * JS. Callers that need the context to be connected and ready to receive\n * messages (the action broker) follow up with\n * {@link LocalMiniappRuntime.waitForConnect}.\n */\n async ensureRunning(packageName: string, hints?: LaunchHints): Promise<LaunchResult> {\n const router = this.requireRouter()\n\n // Already spawned: best-effort resolve for the UI entry, never throw —\n // a headless caller that doesn't need UI gets {null, null} fast even if\n // the dev server has since dropped.\n if (router.registeredPackages().includes(packageName)) {\n const existing = await this.resolveBundle(packageName, hints).catch(() => null)\n return {uiUri: existing?.uiUri ?? null, uiBaseDir: existing?.uiBaseDir ?? null}\n }\n\n // Coalesce concurrent launches of the same package onto one promise.\n const pending = this.inFlight.get(packageName)\n if (pending) return pending\n\n const launch = this.spawn(packageName, hints)\n this.inFlight.set(packageName, launch)\n try {\n return await launch\n } finally {\n this.inFlight.delete(packageName)\n }\n }\n\n /** Resolve the bundle and spawn the context. Serialized via {@link inFlight}. */\n private async spawn(packageName: string, hints?: LaunchHints): Promise<LaunchResult> {\n const router = this.requireRouter()\n const resolved = await this.resolveBundle(packageName, hints)\n if (!resolved) {\n throw new Error(`MiniappLauncher: cannot resolve bundle for ${packageName}`)\n }\n\n // Re-check after the async resolve: a different path may have spawned it\n // while we were fetching/reading the bundle.\n if (!router.registeredPackages().includes(packageName)) {\n const ok = await router.spawnAndRegister(packageName, resolved.bgSource, {\n permissions: resolved.declaredPermissions,\n installedManifest: resolved.installedManifest,\n launchSource: hints?.launchSource,\n })\n if (!ok) {\n throw new Error(`MiniappLauncher: spawn failed for ${packageName}`)\n }\n\n // Dev: wire the hot-reload + log-forwarding sidecar. No-op in prod\n // (devServerBridge silently drops when no sidecar is up).\n if (resolved.devUrl && resolved.devPort != null) {\n devServerBridge.connect(packageName, resolved.devUrl, resolved.devPort)\n } else if (resolved.devUrl) {\n // Dev miniapp with no resolvable port — it still launches, but hot\n // reload + log forwarding won't connect. Surface it instead of failing\n // silently (the old inline path hard-failed with \"no dev port\").\n console.warn(`MiniappLauncher: ${packageName} has no dev port — hot reload + log forwarding disabled`)\n }\n }\n\n return {uiUri: resolved.uiUri, uiBaseDir: resolved.uiBaseDir}\n }\n\n /**\n * Re-spawn local miniapps that were running when the app was last killed.\n *\n * Miniapps run in the phone's own JS engine, so a host-process kill tears\n * down their JSContext with nothing to resurrect them. Without this they\n * would silently stay stopped on the next launch even though the user left\n * them running.\n *\n * Each local miniapp persists its running flag to disk on start/stop\n * (`saveLocalAppRunningState`, via the applet's `onStart`/`onStop`). We read\n * those flags back and re-spawn the background context headlessly (no\n * foreground, no navigation) — the spawn registers the package so the home\n * tray/switcher project it as running, exactly as a normal start would. The\n * WebView, if any, re-attaches lazily when the user opens the app.\n *\n * Idempotent and best-effort: skips already-spawned contexts, and clears the\n * persisted flag for any app whose bundle can no longer be resolved\n * (uninstalled, or dev server gone) so a dead entry doesn't retry every boot.\n * Not compatibility-gated: a previously-running background app shouldn't be\n * dropped just because glasses are momentarily disconnected at boot — it\n * resumes when they reconnect, same as mid-session.\n *\n * Persistent apps (the dashboard) start whether or not they were running\n * when the app was last killed, and get a switcher card like any other app.\n * Both restore paths skip apps missing required OS permissions without\n * prompting or clearing their saved running/persistent choice.\n */\n async autostartLocalMiniapps(): Promise<void> {\n const apps = await appRegistry.getInstalledMiniapps()\n for (const app of apps) {\n // Only phone-hosted miniapps have a JSContext to re-spawn. Offline\n // built-ins (`local:false, offline:true`) restore their native running\n // state elsewhere and have no bundle to launch.\n if (!app.local) continue\n if (!app.persistent && !getLocalAppRunningState(app.packageName)) continue\n if (this.isRunning(app.packageName)) continue\n try {\n const missing = await permissions.missingRequired(app.permissions ?? [])\n if (missing.length > 0) {\n console.info(\n `MiniappLauncher: skipping autostart for ${app.packageName} — missing required permissions: ${missing.join(\n \", \",\n )}`,\n )\n continue\n }\n } catch (e) {\n console.warn(`MiniappLauncher: skipping autostart for ${app.packageName} — permission check failed`, e)\n continue\n }\n try {\n await this.ensureRunning(app.packageName)\n } catch (e) {\n console.warn(`MiniappLauncher: autostart failed for ${app.packageName} — clearing stale running flag`, e)\n saveLocalAppRunningState(app.packageName, false)\n }\n }\n }\n\n /**\n * Ensure the context is running AND has completed its CONNECT handshake.\n * Used by the action broker, which must not deliver to a context that hasn't\n * come up yet. Throws on spawn failure or connect timeout.\n */\n async ensureConnected(packageName: string, connectTimeoutMs = 10_000, hints?: LaunchHints): Promise<void> {\n await this.ensureRunning(packageName, hints)\n await localMiniappRuntime.waitForConnect(packageName, connectTimeoutMs)\n }\n\n /** Tear down a miniapp's background JS context. */\n async stop(packageName: string): Promise<void> {\n // If a launch is in flight, let it finish first. Otherwise unregister()\n // no-ops on the not-yet-registered package and the pending spawn then\n // re-registers the context — leaving it running despite the stop.\n const pending = this.inFlight.get(packageName)\n if (pending) {\n try {\n await pending\n } catch {\n // Launch failed — nothing got registered, so nothing to tear down.\n }\n }\n await this.deps?.router.unregister(packageName)\n }\n\n // --- internals -----------------------------------------------------------\n\n private storedDevUrl(packageName: string): string | undefined {\n const r = storage.load<string>(`${packageName}_dev_url`)\n return r.is_ok() ? r.value : undefined\n }\n\n /** resolveDevPort — moved verbatim from the old LocalMiniappView helper. */\n private resolveDevPort(searchParam: string | undefined, packageName: string): number | null {\n if (searchParam) {\n const n = parseInt(searchParam, 10)\n if (Number.isFinite(n)) return n\n }\n const stored = storage.load<number>(`${packageName}_dev_port`)\n if (stored.is_ok()) return stored.value\n return null\n }\n}\n\nexport const miniappLauncher = new MiniappLauncher()\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { MirrorSnapshot } from "@glassly/miniapp";
|
|
2
|
+
/** One host-wide preview producer, observed only while miniapps subscribe. */
|
|
3
|
+
declare class MirrorService {
|
|
4
|
+
private revision;
|
|
5
|
+
private lastKey;
|
|
6
|
+
private lastEvent;
|
|
7
|
+
private snapshot;
|
|
8
|
+
private model;
|
|
9
|
+
private initialized;
|
|
10
|
+
private listeners;
|
|
11
|
+
private stops;
|
|
12
|
+
private lastEmittedRevision;
|
|
13
|
+
private pendingEvent;
|
|
14
|
+
private pendingFrames;
|
|
15
|
+
private timer;
|
|
16
|
+
private selectedModel;
|
|
17
|
+
initialize(): void;
|
|
18
|
+
invalidate(reason: string): void;
|
|
19
|
+
current(): MirrorSnapshot;
|
|
20
|
+
subscribe(cb: (snapshot: MirrorSnapshot) => void): () => void;
|
|
21
|
+
}
|
|
22
|
+
export declare const mirrorService: MirrorService;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=MirrorService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MirrorService.d.ts","sourceRoot":"","sources":["../../src/services/MirrorService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAapD,8EAA8E;AAC9E,cAAM,aAAa;IACjB,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,SAAS,CAAgD;IACjE,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,mBAAmB,CAAI;IAC/B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,KAAK,CAAqD;IAElE,OAAO,CAAC,aAAa;IAQrB,UAAU,IAAI,IAAI;IAgBlB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIhC,OAAO,IAAI,cAAc;IA8BzB,SAAS,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,GAAG,MAAM,IAAI;CAkD9D;AAED,eAAO,MAAM,aAAa,eAAsB,CAAA"}
|