@mentra/engine 0.1.0-dev.1 → 3.1.0-dev.10
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 +20 -24
- package/build/bluetooth-sdk/debug.d.ts +2 -0
- package/build/bluetooth-sdk/debug.d.ts.map +1 -0
- package/build/bluetooth-sdk/debug.js +2 -0
- package/build/bluetooth-sdk/debug.js.map +1 -0
- package/build/bluetooth-sdk/index.d.ts +3 -0
- package/build/bluetooth-sdk/index.d.ts.map +1 -0
- package/build/bluetooth-sdk/index.js +3 -0
- package/build/bluetooth-sdk/index.js.map +1 -0
- package/build/bluetooth-sdk/photo-receiver.d.ts +3 -0
- package/build/bluetooth-sdk/photo-receiver.d.ts.map +1 -0
- package/build/bluetooth-sdk/photo-receiver.js +3 -0
- package/build/bluetooth-sdk/photo-receiver.js.map +1 -0
- package/build/bluetooth-sdk/react.d.ts +2 -0
- package/build/bluetooth-sdk/react.d.ts.map +1 -0
- package/build/bluetooth-sdk/react.js +2 -0
- package/build/bluetooth-sdk/react.js.map +1 -0
- package/build/bluetooth-sdk/types.d.ts +2 -0
- package/build/bluetooth-sdk/types.d.ts.map +1 -0
- package/build/bluetooth-sdk/types.js +2 -0
- package/build/bluetooth-sdk/types.js.map +1 -0
- package/build/engine.d.ts +13 -13
- package/build/engine.d.ts.map +1 -1
- package/build/engine.js +2 -2
- package/build/engine.js.map +1 -1
- package/build/facades/display.d.ts +1 -1
- package/build/facades/display.d.ts.map +1 -1
- package/build/facades/display.js +1 -1
- package/build/facades/display.js.map +1 -1
- package/build/facades/glasses.d.ts +3 -13
- package/build/facades/glasses.d.ts.map +1 -1
- package/build/facades/glasses.js +3 -3
- package/build/facades/glasses.js.map +1 -1
- package/build/facades/ota.d.ts +5 -16
- package/build/facades/ota.d.ts.map +1 -1
- package/build/facades/ota.js +3 -3
- package/build/facades/ota.js.map +1 -1
- package/build/facades/pairing.d.ts +4 -5
- package/build/facades/pairing.d.ts.map +1 -1
- package/build/facades/pairing.js +2 -2
- package/build/facades/pairing.js.map +1 -1
- package/build/facades/speech.d.ts +7 -6
- package/build/facades/speech.d.ts.map +1 -1
- package/build/facades/speech.js +1 -1
- package/build/facades/speech.js.map +1 -1
- package/build/generated/releaseMetadata.d.ts +12 -0
- package/build/generated/releaseMetadata.d.ts.map +1 -0
- package/build/generated/releaseMetadata.js +10 -0
- package/build/generated/releaseMetadata.js.map +1 -0
- package/build/index.d.ts +4 -5
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -3
- package/build/index.js.map +1 -1
- package/build/services/AppRegistry.d.ts +8 -0
- package/build/services/AppRegistry.d.ts.map +1 -1
- package/build/services/AppRegistry.js +15 -0
- package/build/services/AppRegistry.js.map +1 -1
- package/build/services/OtaInstallCoordinator.d.ts +1 -1
- package/build/services/OtaInstallCoordinator.d.ts.map +1 -1
- package/build/services/OtaInstallCoordinator.js +3 -0
- package/build/services/OtaInstallCoordinator.js.map +1 -1
- package/build/services/OtaUpdateCheckService.d.ts +1 -1
- package/build/services/OtaUpdateCheckService.d.ts.map +1 -1
- package/build/services/OtaUpdateCheckService.js +12 -16
- package/build/services/OtaUpdateCheckService.js.map +1 -1
- package/build/services/glassesClockSync.d.ts.map +1 -1
- package/build/services/glassesClockSync.js +4 -0
- package/build/services/glassesClockSync.js.map +1 -1
- package/build/services/otaDisplayState.d.ts +1 -1
- package/build/services/otaDisplayState.d.ts.map +1 -1
- package/build/services/otaDisplayState.js.map +1 -1
- package/build/services/otaInstallPolicy.d.ts +1 -1
- package/build/services/otaInstallPolicy.d.ts.map +1 -1
- package/build/services/otaInstallPolicy.js.map +1 -1
- package/build/services/otaLegacyMapping.d.ts +1 -1
- package/build/services/otaLegacyMapping.d.ts.map +1 -1
- package/build/services/otaLegacyMapping.js.map +1 -1
- package/build/services/otaManifestPolicy.d.ts +14 -0
- package/build/services/otaManifestPolicy.d.ts.map +1 -0
- package/build/services/otaManifestPolicy.js +19 -0
- package/build/services/otaManifestPolicy.js.map +1 -0
- package/build/services/otaManifestUrl.d.ts +2 -1
- package/build/services/otaManifestUrl.d.ts.map +1 -1
- package/build/services/otaManifestUrl.js +24 -32
- package/build/services/otaManifestUrl.js.map +1 -1
- package/build/stores/settings.js +3 -3
- package/build/stores/settings.js.map +1 -1
- package/build/types/enums.d.ts +1 -25
- package/build/types/enums.d.ts.map +1 -1
- package/build/types/enums.js +1 -27
- package/build/types/enums.js.map +1 -1
- package/build/types/hardware.d.ts +3 -13
- package/build/types/hardware.d.ts.map +1 -1
- package/build/types/hardware.js +1 -3
- package/build/types/hardware.js.map +1 -1
- package/build/types/index.d.ts +2 -6
- package/build/types/index.d.ts.map +1 -1
- package/build/types/index.js +2 -6
- package/build/types/index.js.map +1 -1
- package/package.json +40 -22
- package/src/bluetooth-sdk/debug.ts +1 -0
- package/src/bluetooth-sdk/index.ts +2 -0
- package/src/bluetooth-sdk/photo-receiver.ts +2 -0
- package/src/bluetooth-sdk/react.ts +1 -0
- package/src/bluetooth-sdk/types.ts +1 -0
- package/src/engine.ts +2 -2
- package/src/facades/display.ts +1 -1
- package/src/facades/glasses.ts +4 -4
- package/src/facades/ota.ts +4 -4
- package/src/facades/pairing.ts +4 -4
- package/src/facades/speech.ts +21 -7
- package/src/generated/releaseMetadata.ts +20 -0
- package/src/index.ts +13 -11
- package/src/services/AppRegistry.ts +16 -0
- package/src/services/OtaInstallCoordinator.ts +4 -1
- package/src/services/OtaUpdateCheckService.ts +20 -20
- package/src/services/glassesClockSync.ts +4 -0
- package/src/services/otaDisplayState.ts +1 -1
- package/src/services/otaInstallPolicy.ts +1 -1
- package/src/services/otaLegacyMapping.ts +1 -1
- package/src/services/otaManifestPolicy.ts +42 -0
- package/src/services/otaManifestUrl.ts +27 -36
- package/src/stores/settings.ts +3 -3
- package/src/types/enums.ts +1 -27
- package/src/types/hardware.ts +3 -13
- package/src/types/index.ts +2 -6
- package/build/devtools.d.ts +0 -11
- package/build/devtools.d.ts.map +0 -1
- package/build/devtools.js +0 -13
- package/build/devtools.js.map +0 -1
- package/build/internal.d.ts +0 -67
- package/build/internal.d.ts.map +0 -1
- package/build/internal.js +0 -90
- package/build/internal.js.map +0 -1
- package/src/devtools.ts +0 -13
- package/src/internal.ts +0 -160
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hardware.js","sourceRoot":"","sources":["../../src/types/hardware.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hardware.js","sourceRoot":"","sources":["../../src/types/hardware.ts"],"names":[],"mappings":"AAAA,oDAAoD;AAEpD,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAiKtC;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAiC;IACjE,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,eAAe;IAC5C,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,eAAe;IAC5C,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,aAAa;IACxC,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,UAAU;IAClC,CAAC,gBAAgB,CAAC,SAAS,CAAC,EAAE,gBAAgB;IAC9C,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,SAAS;IAChC,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,mDAAmD;IACnF,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE;QAClB,GAAG,eAAe;QAClB,SAAS,EAAE,WAAW,CAAC,IAAI;QAC3B,OAAO,EAAE;YACP,GAAG,eAAe,CAAC,OAAO;YAC1B,gBAAgB,EAAE,KAAK;SACxB;QACD,aAAa,EAAE,IAAI;QACnB,MAAM,EAAE,IAAI;QACZ,UAAU,EAAE;YACV,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,KAAK;SACd;KACF;IACD,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI;CACvB,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,UAAuB,EAAgB,EAAE;IAC5E,MAAM,SAAS,GAAG,UAAoB,CAAC;IACvC,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC;QACtC,OAAO,qBAAqB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,qBAAqB,CAAC,SAAS,CAAC,CAAC;AAC1C,CAAC,CAAC;AAEF,iCAAiC;AACjC,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC","sourcesContent":["/** Hardware capability types used by the Engine. */\n\nimport { evenRealitiesG1 } from \"./capabilities/even-realities-g1\";\nimport { evenRealitiesG2 } from \"./capabilities/even-realities-g2\";\nimport { mentraDisplay } from \"./capabilities/mentra-display\";\nimport { mentraLive } from \"./capabilities/mentra-live\";\nimport { simulatedGlasses } from \"./capabilities/simulated-glasses\";\nimport { vuzixZ100 } from \"./capabilities/vuzix-z100\";\nimport { none } from \"./capabilities/none\";\nimport { DeviceTypes } from \"./enums\";\n\nexport type { HardwareRequirement } from \"@mentra/miniapp/hardware\";\n\n/**\n * Camera capabilities\n */\nexport interface CameraCapabilities {\n resolution?: { width: number; height: number };\n hasHDR?: boolean;\n hasFocus?: boolean;\n video: {\n canRecord: boolean;\n canStream: boolean;\n supportedStreamTypes?: string[];\n supportedResolutions?: { width: number; height: number }[];\n };\n}\n\n/**\n * Display capabilities\n */\nexport interface DisplayCapabilities {\n count?: number;\n isColor?: boolean;\n color?: string; // e.g., \"green\", \"full_color\", \"pallet\"\n canDisplayBitmap?: boolean;\n resolution?: { width: number; height: number };\n fieldOfView?: { horizontal?: number; vertical?: number };\n maxTextLines?: number;\n adjustBrightness?: boolean;\n\n // --- Scene display API (display.render()) — typed capabilities ---\n // Pure DATA the host scene pipeline acts on generically; a device without\n // canPosition renders scenes via the host degrade path instead.\n /** Public drawable canvas in px — the raw coordinate space for render() boxes. */\n width?: number;\n height?: number;\n /** True ⇒ the device renders positioned elements (containers / canvas components). */\n canPosition?: boolean;\n /** Element budgets. Rects share the text pool on container-based devices. */\n maxTextElements?: number;\n maxImageElements?: number;\n /** Per-image dimension cap (box-level), when the firmware has one. */\n maxImagePx?: { width: number; height: number };\n shapes?: \"rect\"[];\n intensityLevels?: number;\n partialUpdate?: boolean;\n}\n\n/**\n * Microphone capabilities\n */\nexport interface MicrophoneCapabilities {\n count?: number;\n hasVAD?: boolean; // Voice Activity Detection\n}\n\n/**\n * Speaker capabilities\n */\nexport interface SpeakerCapabilities {\n count?: number;\n isPrivate?: boolean; // e.g., bone conduction\n}\n\n/**\n * IMU (Inertial Measurement Unit) capabilities\n */\nexport interface IMUCapabilities {\n axisCount?: number;\n hasAccelerometer?: boolean;\n hasCompass?: boolean;\n hasGyroscope?: boolean;\n}\n\n/**\n * Button capabilities\n */\nexport interface ButtonCapabilities {\n count?: number;\n buttons?: {\n type: \"press\" | \"swipe1d\" | \"swipe2d\";\n events: string[]; // e.g., \"press\", \"double_press\", \"long_press\", \"swipe_up\", \"swipe_down\"\n isCapacitive?: boolean;\n }[];\n}\n\n/**\n * Light capabilities\n */\nexport interface LightCapabilities {\n count?: number;\n lights?: {\n id: string; // Unique identifier for the LED (e.g., \"privacy\", \"user_feedback\")\n purpose: \"privacy\" | \"user_feedback\" | \"general\"; // LED purpose/function\n isFullColor: boolean;\n color?: string; // e.g., \"white\", \"rgb\"\n position?: \"front_facing\" | \"user_facing\" | \"side\" | \"unknown\"; // LED physical position\n }[];\n}\n\n/**\n * Power capabilities\n */\nexport interface PowerCapabilities {\n hasExternalBattery: boolean; // e.g., a case or puck\n}\n\n/**\n * Device hardware capabilities\n * Complete information about what hardware a device has\n */\nexport interface Capabilities {\n modelName: string;\n\n // Camera capabilities\n hasCamera: boolean;\n camera: CameraCapabilities | null;\n\n // Display capabilities\n hasDisplay: boolean;\n display: DisplayCapabilities | null;\n\n // Microphone capabilities\n hasMicrophone: boolean;\n microphone: MicrophoneCapabilities | null;\n\n // Speaker capabilities\n hasSpeaker: boolean;\n speaker: SpeakerCapabilities | null;\n\n // IMU capabilities\n hasIMU: boolean;\n imu: IMUCapabilities | null;\n\n // Button capabilities\n hasButton: boolean;\n button: ButtonCapabilities | null;\n\n // Light capabilities\n hasLight: boolean;\n light: LightCapabilities | null;\n\n // Power capabilities\n power: PowerCapabilities;\n\n // WiFi capability\n hasWifi: boolean;\n\n // OTA capability\n hasOta?: boolean;\n\n // Native dashboard capability\n // True when the device renders its own dashboard in firmware (e.g. Even\n // Realities' built-in dashboard on G2). MentraOS does not manage or expose\n // dashboard settings for these devices. Absent/false means MentraOS owns the\n // dashboard.\n hasNativeDashboard?: boolean;\n}\n\n/**\n * Hardware capability profiles for supported glasses models\n * Key: model_name string (e.g., \"Even Realities G1\", \"Mentra Live\")\n * Value: Capabilities object defining device features\n */\nexport const HARDWARE_CAPABILITIES: Record<string, Capabilities> = {\n [evenRealitiesG1.modelName]: evenRealitiesG1,\n [evenRealitiesG2.modelName]: evenRealitiesG2,\n [mentraDisplay.modelName]: mentraDisplay,\n [mentraLive.modelName]: mentraLive,\n [simulatedGlasses.modelName]: simulatedGlasses,\n [vuzixZ100.modelName]: vuzixZ100,\n [DeviceTypes.MACH1]: vuzixZ100, // Mach1 uses same Vuzix Ultralite hardware as Z100\n [DeviceTypes.AR99]: {\n ...evenRealitiesG1,\n modelName: DeviceTypes.AR99,\n display: {\n ...evenRealitiesG1.display,\n canDisplayBitmap: false,\n },\n hasMicrophone: true,\n hasOta: true,\n microphone: {\n count: 1,\n hasVAD: false,\n },\n },\n [none.modelName]: none,\n};\n\nexport const getModelCapabilities = (deviceType: DeviceTypes): Capabilities => {\n const modelName = deviceType as string;\n if (!HARDWARE_CAPABILITIES[modelName]) {\n return HARDWARE_CAPABILITIES[DeviceTypes.NONE];\n }\n return HARDWARE_CAPABILITIES[modelName];\n};\n\n// export * from \"./capabilities\"\nexport { simulatedGlasses, evenRealitiesG1, evenRealitiesG2, mentraLive, vuzixZ100, mentraDisplay };\n"]}
|
package/build/types/index.d.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* self-contained. Keep these in sync with cloud/packages/types/src when the
|
|
4
|
-
* canonical types change. The capability profiles also live here under
|
|
5
|
-
* ./capabilities/.
|
|
6
|
-
*/
|
|
1
|
+
/** Engine capability types and profiles. Miniapp manifest requirement types
|
|
2
|
+
* are re-exported from @mentra/miniapp, their canonical owner. */
|
|
7
3
|
export { HardwareType, HardwareRequirementLevel, DeviceTypes, ControllerTypes } from "./enums";
|
|
8
4
|
export type { HardwareRequirement, CameraCapabilities, DisplayCapabilities, MicrophoneCapabilities, SpeakerCapabilities, IMUCapabilities, ButtonCapabilities, LightCapabilities, PowerCapabilities, Capabilities, } from "./hardware";
|
|
9
5
|
export { HARDWARE_CAPABILITIES, getModelCapabilities, simulatedGlasses, evenRealitiesG1, evenRealitiesG2, mentraLive, vuzixZ100, mentraDisplay, } from "./hardware";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;kEACkE;AAGlE,OAAO,EAAC,YAAY,EAAE,wBAAwB,EAAE,WAAW,EAAE,eAAe,EAAC,MAAM,SAAS,CAAA;AAG5F,YAAY,EACV,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,GACb,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,UAAU,EACV,SAAS,EACT,aAAa,GACd,MAAM,YAAY,CAAA;AAGnB,YAAY,EAAC,UAAU,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,eAAe,EAAE,SAAS,EAAC,MAAM,UAAU,CAAA"}
|
package/build/types/index.js
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* self-contained. Keep these in sync with cloud/packages/types/src when the
|
|
4
|
-
* canonical types change. The capability profiles also live here under
|
|
5
|
-
* ./capabilities/.
|
|
6
|
-
*/
|
|
1
|
+
/** Engine capability types and profiles. Miniapp manifest requirement types
|
|
2
|
+
* are re-exported from @mentra/miniapp, their canonical owner. */
|
|
7
3
|
// Enums (runtime values)
|
|
8
4
|
export { HardwareType, HardwareRequirementLevel, DeviceTypes, ControllerTypes } from "./enums";
|
|
9
5
|
export { HARDWARE_CAPABILITIES, getModelCapabilities, simulatedGlasses, evenRealitiesG1, evenRealitiesG2, mentraLive, vuzixZ100, mentraDisplay, } from "./hardware";
|
package/build/types/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;kEACkE;AAElE,yBAAyB;AACzB,OAAO,EAAC,YAAY,EAAE,wBAAwB,EAAE,WAAW,EAAE,eAAe,EAAC,MAAM,SAAS,CAAA;AAgB5F,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,UAAU,EACV,SAAS,EACT,aAAa,GACd,MAAM,YAAY,CAAA","sourcesContent":["/** Engine capability types and profiles. Miniapp manifest requirement types\n * are re-exported from @mentra/miniapp, their canonical owner. */\n\n// Enums (runtime values)\nexport {HardwareType, HardwareRequirementLevel, DeviceTypes, ControllerTypes} from \"./enums\"\n\n// Hardware types\nexport type {\n HardwareRequirement,\n CameraCapabilities,\n DisplayCapabilities,\n MicrophoneCapabilities,\n SpeakerCapabilities,\n IMUCapabilities,\n ButtonCapabilities,\n LightCapabilities,\n PowerCapabilities,\n Capabilities,\n} from \"./hardware\"\n\nexport {\n HARDWARE_CAPABILITIES,\n getModelCapabilities,\n simulatedGlasses,\n evenRealitiesG1,\n evenRealitiesG2,\n mentraLive,\n vuzixZ100,\n mentraDisplay,\n} from \"./hardware\"\n\n// Applet types\nexport type {AppletType, AppPermissionType, AppletPermission, AppletInterface, ClientApp} from \"./applet\"\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mentra/engine",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0-dev.10",
|
|
4
4
|
"description": "Mentra Engine — miniapp registry, WebView bridge, and miniapp store",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -11,21 +11,36 @@
|
|
|
11
11
|
"react-native": "./src/index.ts",
|
|
12
12
|
"default": "./build/index.js"
|
|
13
13
|
},
|
|
14
|
-
"./internal": {
|
|
15
|
-
"types": "./build/internal.d.ts",
|
|
16
|
-
"react-native": "./src/internal.ts",
|
|
17
|
-
"default": "./build/internal.js"
|
|
18
|
-
},
|
|
19
|
-
"./devtools": {
|
|
20
|
-
"types": "./build/devtools.d.ts",
|
|
21
|
-
"react-native": "./src/devtools.ts",
|
|
22
|
-
"default": "./build/devtools.js"
|
|
23
|
-
},
|
|
24
14
|
"./ota": {
|
|
25
15
|
"types": "./build/react/index.d.ts",
|
|
26
16
|
"react-native": "./src/react/index.ts",
|
|
27
17
|
"default": "./build/react/index.js"
|
|
28
18
|
},
|
|
19
|
+
"./bluetooth-sdk": {
|
|
20
|
+
"types": "./build/bluetooth-sdk/index.d.ts",
|
|
21
|
+
"react-native": "./src/bluetooth-sdk/index.ts",
|
|
22
|
+
"default": "./build/bluetooth-sdk/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./bluetooth-sdk/react": {
|
|
25
|
+
"types": "./build/bluetooth-sdk/react.d.ts",
|
|
26
|
+
"react-native": "./src/bluetooth-sdk/react.ts",
|
|
27
|
+
"default": "./build/bluetooth-sdk/react.js"
|
|
28
|
+
},
|
|
29
|
+
"./bluetooth-sdk/types": {
|
|
30
|
+
"types": "./build/bluetooth-sdk/types.d.ts",
|
|
31
|
+
"react-native": "./src/bluetooth-sdk/types.ts",
|
|
32
|
+
"default": "./build/bluetooth-sdk/types.js"
|
|
33
|
+
},
|
|
34
|
+
"./bluetooth-sdk/photo-receiver": {
|
|
35
|
+
"types": "./build/bluetooth-sdk/photo-receiver.d.ts",
|
|
36
|
+
"react-native": "./src/bluetooth-sdk/photo-receiver.ts",
|
|
37
|
+
"default": "./build/bluetooth-sdk/photo-receiver.js"
|
|
38
|
+
},
|
|
39
|
+
"./bluetooth-sdk/debug": {
|
|
40
|
+
"types": "./build/bluetooth-sdk/debug.d.ts",
|
|
41
|
+
"react-native": "./src/bluetooth-sdk/debug.ts",
|
|
42
|
+
"default": "./build/bluetooth-sdk/debug.js"
|
|
43
|
+
},
|
|
29
44
|
"./build/*": null,
|
|
30
45
|
"./src/*": null,
|
|
31
46
|
"./package.json": "./package.json"
|
|
@@ -34,6 +49,10 @@
|
|
|
34
49
|
"build",
|
|
35
50
|
"README.md",
|
|
36
51
|
"src",
|
|
52
|
+
"!build/devtools.*",
|
|
53
|
+
"!build/internal.*",
|
|
54
|
+
"!src/devtools.ts",
|
|
55
|
+
"!src/internal.ts",
|
|
37
56
|
"!src/**/__tests__",
|
|
38
57
|
"!src/**/*.test.ts"
|
|
39
58
|
],
|
|
@@ -41,7 +60,10 @@
|
|
|
41
60
|
"build": "expo-module build",
|
|
42
61
|
"clean": "expo-module clean",
|
|
43
62
|
"lint": "expo-module lint",
|
|
44
|
-
"test": "./scripts/test.sh",
|
|
63
|
+
"test": "./scripts/test.sh && node --test scripts/*.test.mjs",
|
|
64
|
+
"write:release-metadata": "node scripts/write-release-metadata.mjs",
|
|
65
|
+
"verify:release-package": "node scripts/verify-release-package.mjs",
|
|
66
|
+
"test:public-api": "bun test src/bluetooth-sdk/__tests__/publicApi.test.ts",
|
|
45
67
|
"build:module": "expo-module prepare",
|
|
46
68
|
"prepublishOnly": "expo-module prepublishOnly",
|
|
47
69
|
"expo-module": "expo-module"
|
|
@@ -69,16 +91,17 @@
|
|
|
69
91
|
"registry": "https://registry.npmjs.org/"
|
|
70
92
|
},
|
|
71
93
|
"dependencies": {
|
|
94
|
+
"@mentra/bluetooth-sdk": "3.1.0-dev.10",
|
|
95
|
+
"@mentra/cloud-client": "3.1.0-dev.10",
|
|
96
|
+
"@mentra/cloud-protocol": "3.1.0-dev.10",
|
|
97
|
+
"@mentra/crust": "3.1.0-dev.10",
|
|
98
|
+
"@mentra/miniapp": "3.1.0-dev.10",
|
|
72
99
|
"buffer": "^6.0.3",
|
|
73
100
|
"events": "^3.3.0",
|
|
74
101
|
"semver": "^7.7.4",
|
|
75
102
|
"typesafe-ts": "^1.7.1"
|
|
76
103
|
},
|
|
77
104
|
"devDependencies": {
|
|
78
|
-
"@mentra/bluetooth-sdk": "workspace:*",
|
|
79
|
-
"@mentra/cloud-client": "workspace:*",
|
|
80
|
-
"@mentra/cloud-protocol": "workspace:*",
|
|
81
|
-
"@mentra/miniapp": "workspace:*",
|
|
82
105
|
"@types/semver": "^7.7.1",
|
|
83
106
|
"expo-module-scripts": "^55.0.2",
|
|
84
107
|
"expo-modules-core": "55.0.25",
|
|
@@ -119,11 +142,6 @@
|
|
|
119
142
|
"@react-native-community/netinfo": "*",
|
|
120
143
|
"@dr.pogodin/react-native-fs": "*",
|
|
121
144
|
"@craftzdog/react-native-buffer": "*",
|
|
122
|
-
"axios": "*"
|
|
123
|
-
"@mentra/bluetooth-sdk": "*",
|
|
124
|
-
"@mentra/crust": "^0.1.0-dev.1",
|
|
125
|
-
"@mentra/cloud-client": "^0.1.0-dev.0",
|
|
126
|
-
"@mentra/miniapp": "^0.3.0-dev.1",
|
|
127
|
-
"@mentra/cloud-protocol": "^0.1.0-dev.0"
|
|
145
|
+
"axios": "*"
|
|
128
146
|
}
|
|
129
147
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@mentra/bluetooth-sdk/debug"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@mentra/bluetooth-sdk/react"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@mentra/bluetooth-sdk/types"
|
package/src/engine.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* name stays `engine` in code; the public API surface is `engine`.)
|
|
6
6
|
*
|
|
7
7
|
* It grows one facade at a time. The migration-era flat store/service exports
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* remain in a private MentraOS host package; they shrink as screens move onto
|
|
9
|
+
* `engine.*`.
|
|
10
10
|
*/
|
|
11
11
|
import {configure, start as bootstrapStart, stop as bootstrapStop, updateUiSeams} from "./runtime/bootstrap"
|
|
12
12
|
import {cloudClientService} from "./services/CloudClientService"
|
package/src/facades/display.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* glasses display for dev tools and escape-hatch use (normal rendering goes through
|
|
5
5
|
* the engine DisplayProcessor / layout system, not these).
|
|
6
6
|
*/
|
|
7
|
-
import BluetoothSdk from "@mentra/bluetooth-sdk
|
|
7
|
+
import BluetoothSdk from "@mentra/bluetooth-sdk"
|
|
8
8
|
import {displayMirror} from "./displayMirror"
|
|
9
9
|
|
|
10
10
|
export const display = {
|
package/src/facades/glasses.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// surface, not the public entry. Relative path (the alias doesn't resolve in engine's
|
|
12
12
|
// standalone build); jest moduleNameMapper + tsconfig both resolve it.
|
|
13
13
|
import BluetoothSdk from "@mentra/bluetooth-sdk/internal"
|
|
14
|
-
import type {ButtonPressEvent, TouchEvent} from "@mentra/bluetooth-sdk
|
|
14
|
+
import type {ButtonPressEvent, ConnectOptions, Device, TouchEvent} from "@mentra/bluetooth-sdk"
|
|
15
15
|
import {useGlassesStore} from "../stores/glasses"
|
|
16
16
|
import {useSettingsStore, SETTINGS} from "../stores/settings"
|
|
17
17
|
import {hasDefaultDevice} from "../services/DeviceStoreHydration"
|
|
@@ -94,10 +94,10 @@ export const glasses = {
|
|
|
94
94
|
disconnect: (): Promise<void> => BluetoothSdk.disconnect(),
|
|
95
95
|
forget: (): Promise<void> => BluetoothSdk.forget(),
|
|
96
96
|
/** Connect to a specific (discovered) device. */
|
|
97
|
-
connect: async (
|
|
97
|
+
connect: async (device: Device, options?: ConnectOptions): Promise<void> => {
|
|
98
98
|
try {
|
|
99
99
|
await pushAllBluetoothSettings()
|
|
100
|
-
await BluetoothSdk.connect(
|
|
100
|
+
await BluetoothSdk.connect(device, options)
|
|
101
101
|
} catch (error) {
|
|
102
102
|
recordSupportProfileConnectionFailure(error, "connect")
|
|
103
103
|
throw error
|
|
@@ -106,7 +106,7 @@ export const glasses = {
|
|
|
106
106
|
/** Connect the built-in simulated glasses (dev/testing). */
|
|
107
107
|
connectSimulated: (): Promise<void> => BluetoothSdk.connectSimulated(),
|
|
108
108
|
/** Set a device as the `connectDefault()` target. */
|
|
109
|
-
setDefault: (
|
|
109
|
+
setDefault: (device: Device | null): Promise<void> => BluetoothSdk.setDefaultDevice(device),
|
|
110
110
|
/**
|
|
111
111
|
* Reconnect to the saved default glasses. Resolves `false` when there's nothing to
|
|
112
112
|
* reconnect to (no default paired) or the connect attempt fails (e.g. BLE powered
|
package/src/facades/ota.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* progress screen is a pure renderer over its snapshot + attach/detach/retry/finish.
|
|
10
10
|
*/
|
|
11
11
|
import BluetoothSdk from "@mentra/bluetooth-sdk/internal"
|
|
12
|
-
import type {OtaProgress, OtaProgressStatus, OtaStatus, OtaUpdateInfo} from "@mentra/bluetooth-sdk
|
|
12
|
+
import type {OtaProgress, OtaProgressStatus, OtaStartAckEvent, OtaStatus, OtaUpdateInfo} from "@mentra/bluetooth-sdk"
|
|
13
13
|
import {isGlassesConnected, useGlassesStore} from "../stores/glasses"
|
|
14
14
|
import {resolveOtaManifestUrl} from "../services/otaManifestUrl"
|
|
15
15
|
import {otaInstallCoordinator, type OtaInstallSnapshot} from "../services/OtaInstallCoordinator"
|
|
@@ -65,11 +65,11 @@ export const ota = {
|
|
|
65
65
|
},
|
|
66
66
|
/**
|
|
67
67
|
* Start the firmware install with the resolved OTA manifest URL. Progress lands on
|
|
68
|
-
* `status()`/`onStatus()`. (The host resolves the manifest URL —
|
|
69
|
-
* resolution stays with the OTA config; the
|
|
68
|
+
* `status()`/`onStatus()`. (The host resolves the manifest URL — developer override,
|
|
69
|
+
* host pin, or Engine release pin resolution stays with the OTA config; the stuck/retry watchdog is its own
|
|
70
70
|
* resilience layer on top of this command.)
|
|
71
71
|
*/
|
|
72
|
-
install: (
|
|
72
|
+
install: (otaVersionUrl?: string | null): Promise<OtaStartAckEvent> => BluetoothSdk.startOtaUpdate(otaVersionUrl),
|
|
73
73
|
// Deferred: this facade entry was intended to become the engine-owned retry/check
|
|
74
74
|
// action, but BluetoothSdk.checkForOtaUpdate() only returns a boolean. Exposing it
|
|
75
75
|
// here would make callers think the rich otaUpdateAvailable read model is refreshed,
|
package/src/facades/pairing.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// target hint) lives on the full surface, not the public entry (same reason
|
|
11
11
|
// the glasses facade imports internal).
|
|
12
12
|
import BluetoothSdk from "@mentra/bluetooth-sdk/internal"
|
|
13
|
-
import type {ConnectOptions, Device, PairFailureEvent, GlassesNotReadyEvent} from "@mentra/bluetooth-sdk"
|
|
13
|
+
import type {ConnectOptions, Device, DeviceModel, PairFailureEvent, GlassesNotReadyEvent} from "@mentra/bluetooth-sdk"
|
|
14
14
|
import {useCoreStore} from "../stores/core"
|
|
15
15
|
import {useGlassesStore} from "../stores/glasses"
|
|
16
16
|
import {hasDefaultDevice} from "../services/DeviceStoreHydration"
|
|
@@ -206,7 +206,7 @@ export const pairing = {
|
|
|
206
206
|
markPendingSelection: (model: string) => markPendingSelection(model),
|
|
207
207
|
|
|
208
208
|
/** Start scanning for nearby glasses. Results land on `searchResults()`/`onFound()`. */
|
|
209
|
-
scan: (
|
|
209
|
+
scan: (model: DeviceModel): Promise<void> => BluetoothSdk.startScan(model),
|
|
210
210
|
/** Whether a scan is currently in progress. */
|
|
211
211
|
scanning: (): boolean => useCoreStore.getState().searching,
|
|
212
212
|
/** Subscribe to scan-in-progress changes; fires only when it changes. Returns an unsubscribe. */
|
|
@@ -226,7 +226,7 @@ export const pairing = {
|
|
|
226
226
|
// leak as mutable references into the store.
|
|
227
227
|
searchResults: () => useCoreStore.getState().searchResults.map((result) => ({...result})),
|
|
228
228
|
/** Subscribe to scan-result changes; fires only when they change. Returns an unsubscribe. */
|
|
229
|
-
onFound: (cb: (results:
|
|
229
|
+
onFound: (cb: (results: Device[]) => void): (() => void) => {
|
|
230
230
|
let last = JSON.stringify(useCoreStore.getState().searchResults)
|
|
231
231
|
return useCoreStore.subscribe(() => {
|
|
232
232
|
const results = useCoreStore.getState().searchResults
|
|
@@ -250,7 +250,7 @@ export const pairing = {
|
|
|
250
250
|
return BluetoothSdk.connect(device, {...options, saveAsDefault: false})
|
|
251
251
|
},
|
|
252
252
|
/** Set a device as the default for subsequent `glasses.connectDefault()`. */
|
|
253
|
-
setDefault: (
|
|
253
|
+
setDefault: (device: Device | null): Promise<void> => BluetoothSdk.setDefaultDevice(device),
|
|
254
254
|
/**
|
|
255
255
|
* Prime the native Bluetooth Classic audio watcher with the picked device.
|
|
256
256
|
* The iOS Mentra Live flow pairs Classic audio BEFORE any BLE connect
|
package/src/facades/speech.ts
CHANGED
|
@@ -7,24 +7,38 @@
|
|
|
7
7
|
import BluetoothSdk from "@mentra/bluetooth-sdk/internal"
|
|
8
8
|
import sttModelManager from "../services/STTModelManager"
|
|
9
9
|
import ttsModelManager from "../services/TTSModelManager"
|
|
10
|
-
import offlineSpeechModelService
|
|
10
|
+
import offlineSpeechModelService, {
|
|
11
|
+
type DownloadStatus as OfflineModelDownloadStatus,
|
|
12
|
+
} from "../services/OfflineSpeechModelService"
|
|
13
|
+
import type {
|
|
14
|
+
DownloadProgress as SttDownloadProgress,
|
|
15
|
+
ExtractionProgress as SttExtractionProgress,
|
|
16
|
+
LanguageConfig as SttLanguageConfig,
|
|
17
|
+
LanguageInfo as SttLanguageInfo,
|
|
18
|
+
} from "../services/STTModelManager"
|
|
11
19
|
|
|
12
20
|
export const speech = {
|
|
13
21
|
/** Restart the glasses' on-device transcriber (e.g. after switching STT language). */
|
|
14
22
|
restartTranscriber: (): Promise<void> => BluetoothSdk.restartTranscriber(),
|
|
15
23
|
stt: {
|
|
16
24
|
currentLanguage: () => sttModelManager.getCurrentLanguage(),
|
|
17
|
-
languages: () => sttModelManager.getAvailableLanguages(),
|
|
18
|
-
languageInfo: () => sttModelManager.getAllLanguageInfo(),
|
|
19
|
-
download: (
|
|
25
|
+
languages: (): SttLanguageConfig[] => sttModelManager.getAvailableLanguages(),
|
|
26
|
+
languageInfo: (): Promise<SttLanguageInfo[]> => sttModelManager.getAllLanguageInfo(),
|
|
27
|
+
download: (
|
|
28
|
+
...args: [
|
|
29
|
+
code?: string,
|
|
30
|
+
onProgress?: (progress: SttDownloadProgress) => void,
|
|
31
|
+
onExtractionProgress?: (progress: SttExtractionProgress) => void,
|
|
32
|
+
]
|
|
33
|
+
): Promise<void> => sttModelManager.downloadModel(...args),
|
|
20
34
|
activate: (code: string) => sttModelManager.setCurrentLanguage(code),
|
|
21
35
|
cancelDownload: () => sttModelManager.cancelDownload(),
|
|
22
36
|
deleteModel: (...args: Parameters<typeof sttModelManager.deleteModel>) => sttModelManager.deleteModel(...args),
|
|
23
37
|
/** Current auto-download status of the offline STT model. */
|
|
24
|
-
status: () => offlineSpeechModelService.getStatus(),
|
|
38
|
+
status: (): OfflineModelDownloadStatus | null => offlineSpeechModelService.getStatus(),
|
|
25
39
|
/** Subscribe to auto-download status changes; returns an unsubscribe. */
|
|
26
|
-
onStatusChanged: (
|
|
27
|
-
offlineSpeechModelService.subscribe(
|
|
40
|
+
onStatusChanged: (listener: (status: OfflineModelDownloadStatus | null) => void): (() => void) =>
|
|
41
|
+
offlineSpeechModelService.subscribe(listener),
|
|
28
42
|
},
|
|
29
43
|
tts: {
|
|
30
44
|
currentLanguage: () => ttsModelManager.getCurrentLanguage(),
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Generated by release CI. Do not edit in a release checkout. */
|
|
2
|
+
export interface EngineReleaseMetadata {
|
|
3
|
+
schemaVersion: 1
|
|
4
|
+
familyBaseVersion: string | null
|
|
5
|
+
releaseIdentity: string | null
|
|
6
|
+
releaseSetId: string | null
|
|
7
|
+
sourceCommit: string | null
|
|
8
|
+
otaManifestUrl: string | null
|
|
9
|
+
otaManifestSha256: string | null
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({
|
|
13
|
+
"schemaVersion": 1,
|
|
14
|
+
"familyBaseVersion": "3.1.0",
|
|
15
|
+
"releaseIdentity": "3.1.0-dev.10",
|
|
16
|
+
"releaseSetId": "mentra-3.1.0-dev.10",
|
|
17
|
+
"sourceCommit": "64cf83b23a71e70261571a5f4401d1a7538f1852",
|
|
18
|
+
"otaManifestUrl": "https://github.com/Mentra-Community/MentraOS/releases/download/mentra-v3.1.0-dev.10/mentra-live-ota-3.1.0-dev.10.json",
|
|
19
|
+
"otaManifestSha256": "214d92c8894033eaab276e668cb553c79990005d3330d23aaf499a514dc08cff"
|
|
20
|
+
})
|
package/src/index.ts
CHANGED
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
* renders with (decision functions, sort/order helpers, policy constants,
|
|
7
7
|
* capability tables, timers). Judgment rule: read models, commands, pure
|
|
8
8
|
* functions and types belong here; anything that mutates runtime state or
|
|
9
|
-
* exposes a raw store/service
|
|
10
|
-
* (migration-era surface) or `@mentra/engine/devtools` (debug-only) instead.
|
|
9
|
+
* exposes a raw store/service remains private to the MentraOS host.
|
|
11
10
|
* See cloud-v2/docs/issues/020-glasses-status-boundary/integration-review.md §D.
|
|
12
11
|
*/
|
|
13
12
|
|
|
@@ -47,12 +46,7 @@ export {MENTRA_LIVE_SETTING_KEYS, getBluetoothSettingKeysForDevice} from "./stor
|
|
|
47
46
|
|
|
48
47
|
// Runtime-shared constants and contract DTOs.
|
|
49
48
|
export {ISLAND_SETTINGS_KEYS} from "./runtime/config"
|
|
50
|
-
export type {
|
|
51
|
-
CloudClientStatusSnapshot,
|
|
52
|
-
MiniappAuthToken,
|
|
53
|
-
InteropAuditEvent,
|
|
54
|
-
TtsSynthesisResult,
|
|
55
|
-
} from "./runtime/config"
|
|
49
|
+
export type {CloudClientStatusSnapshot, MiniappAuthToken, InteropAuditEvent, TtsSynthesisResult} from "./runtime/config"
|
|
56
50
|
|
|
57
51
|
// Pure readiness predicates over glasses connection state.
|
|
58
52
|
export {
|
|
@@ -132,11 +126,19 @@ export {
|
|
|
132
126
|
export type {GalleryNotice, GalleryNoticeCode} from "./services/asg/galleryNotices"
|
|
133
127
|
export {MediaLibraryPermissions} from "./utils/permissions/MediaLibraryPermissions"
|
|
134
128
|
export {deriveGalleryDisplayName} from "./utils/permissions/galleryDisplayName"
|
|
135
|
-
export type {
|
|
129
|
+
export type {
|
|
130
|
+
PhotoInfo,
|
|
131
|
+
CaptureFile,
|
|
132
|
+
CaptureGroup,
|
|
133
|
+
GalleryResponse,
|
|
134
|
+
ServerStatus,
|
|
135
|
+
HealthResponse,
|
|
136
|
+
GalleryEvent,
|
|
137
|
+
} from "./types/asg"
|
|
136
138
|
|
|
137
139
|
// Bluetooth SDK event types host UI subscribes to via engine facades (the
|
|
138
140
|
// BluetoothSdk singleton passthrough itself is internal).
|
|
139
|
-
export type {PairFailureEvent, GlassesNotReadyEvent} from "@mentra/bluetooth-sdk
|
|
141
|
+
export type {PairFailureEvent, GlassesNotReadyEvent} from "@mentra/bluetooth-sdk"
|
|
140
142
|
|
|
141
143
|
// Cloud connection status enum (read model; the connection store is internal).
|
|
142
144
|
export {WebSocketStatus} from "./stores/connection"
|
|
@@ -181,7 +183,7 @@ export {
|
|
|
181
183
|
export {HardwareCompatibility, type CompatibilityResult} from "./utils/hardware"
|
|
182
184
|
export {BgTimer, throttle, debounce} from "./utils/timers"
|
|
183
185
|
|
|
184
|
-
//
|
|
186
|
+
// Hardware types and capability profiles.
|
|
185
187
|
export {
|
|
186
188
|
HardwareType,
|
|
187
189
|
HardwareRequirementLevel,
|
|
@@ -871,6 +871,22 @@ class AppRegistry {
|
|
|
871
871
|
this.notify()
|
|
872
872
|
}
|
|
873
873
|
|
|
874
|
+
/**
|
|
875
|
+
* Update whether a registered offline app is projected into launcher UIs.
|
|
876
|
+
*
|
|
877
|
+
* Offline apps are registered once at host startup, so settings-backed
|
|
878
|
+
* visibility changes need to update the projection without reinstalling or
|
|
879
|
+
* duplicating the app. No-op when the app is missing or already matches.
|
|
880
|
+
*/
|
|
881
|
+
public setOfflineAppHidden(packageName: string, hidden: boolean): void {
|
|
882
|
+
const app = this.offlineApps.find((candidate) => candidate.packageName === packageName)
|
|
883
|
+
if (!app || app.hidden === hidden) return
|
|
884
|
+
|
|
885
|
+
app.hidden = hidden
|
|
886
|
+
this.refreshNeeded = true
|
|
887
|
+
this.notify()
|
|
888
|
+
}
|
|
889
|
+
|
|
874
890
|
/**
|
|
875
891
|
* Registered as needing the on-device STT model before it can start (the
|
|
876
892
|
* host declares this per offline app; the apps store gates start() on it).
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* during React effects scheduled a re-render after the current effect batch.
|
|
19
19
|
*/
|
|
20
20
|
import BluetoothSdk from "@mentra/bluetooth-sdk/internal"
|
|
21
|
-
import type {OtaProgress, OtaStatus} from "@mentra/bluetooth-sdk
|
|
21
|
+
import type {OtaProgress, OtaStatus} from "@mentra/bluetooth-sdk"
|
|
22
22
|
import GlobalEventEmitter from "../utils/GlobalEventEmitter"
|
|
23
23
|
import {isGlassesConnected, useGlassesStore} from "../stores/glasses"
|
|
24
24
|
import {resolveOtaManifestUrl} from "./otaManifestUrl"
|
|
@@ -1492,6 +1492,9 @@ class OtaInstallCoordinator {
|
|
|
1492
1492
|
otaVersionUrl = this.hotspotManifestUrl
|
|
1493
1493
|
this.maybeArmStuckWatchdog()
|
|
1494
1494
|
}
|
|
1495
|
+
if (!otaVersionUrl) {
|
|
1496
|
+
throw new Error("OTA is disabled because this build has no immutable manifest pin")
|
|
1497
|
+
}
|
|
1495
1498
|
console.log(`[OTA_PROGRESS] sending ota_start with ${this.selectedTransport} manifest URL: ${otaVersionUrl}`)
|
|
1496
1499
|
nativeStartAttempted = true
|
|
1497
1500
|
await BluetoothSdk.startOtaUpdate(otaVersionUrl)
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import BluetoothSdk from "@mentra/bluetooth-sdk/internal"
|
|
2
|
-
import type {OtaUpdateInfo} from "@mentra/bluetooth-sdk
|
|
2
|
+
import type {OtaUpdateInfo} from "@mentra/bluetooth-sdk"
|
|
3
3
|
import {getGlassesSystemTimeMs, isGlassesConnected, useGlassesStore, waitForGlassesState} from "../stores/glasses"
|
|
4
|
-
import {SETTINGS, useSettingsStore} from "../stores/settings"
|
|
5
4
|
import {maybeFixGlassesClockFromVersionInfo} from "./glassesClockSync"
|
|
6
|
-
import {resolveOtaManifestUrl} from "./otaManifestUrl"
|
|
5
|
+
import {hasConfiguredModernOtaManifestPin, resolveOtaManifestUrl} from "./otaManifestUrl"
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Phone-side mirror of ASG's `DOWNGRADE_FLOOR_VERSION_CODE`. Set to the versionCode of the first
|
|
@@ -127,7 +126,10 @@ async function fetchVersionInfoDetailed(url: string): Promise<ManifestFetchResul
|
|
|
127
126
|
// 4xx: the manifest does not exist (or is gone) — permanent for this app
|
|
128
127
|
// build, retrying cannot help. Everything else is transient server/network
|
|
129
128
|
// trouble and retryable.
|
|
130
|
-
return {
|
|
129
|
+
return {
|
|
130
|
+
json: null,
|
|
131
|
+
failureReason: response.status >= 400 && response.status < 500 ? "pin_unavailable" : "network",
|
|
132
|
+
}
|
|
131
133
|
}
|
|
132
134
|
try {
|
|
133
135
|
return {json: await response.json()}
|
|
@@ -194,12 +196,7 @@ export function getApkUpdateDirection(
|
|
|
194
196
|
// Downgrades require an exact pin AND a target at/above the enabled floor. A non-positive floor
|
|
195
197
|
// disables downgrades entirely, matching ASG's fail-closed DowngradeGate — so the phone never
|
|
196
198
|
// offers what the glasses would refuse.
|
|
197
|
-
if (
|
|
198
|
-
serverVersion < currentVersion &&
|
|
199
|
-
exactPin &&
|
|
200
|
-
floorVersionCode > 0 &&
|
|
201
|
-
serverVersion >= floorVersionCode
|
|
202
|
-
) {
|
|
199
|
+
if (serverVersion < currentVersion && exactPin && floorVersionCode > 0 && serverVersion >= floorVersionCode) {
|
|
203
200
|
return "downgrade"
|
|
204
201
|
}
|
|
205
202
|
return null
|
|
@@ -403,17 +400,10 @@ export async function checkCurrentGlassesForUpdate(
|
|
|
403
400
|
return emptyCheckResult("disconnected")
|
|
404
401
|
}
|
|
405
402
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
const overrideUrl = useSettingsStore.getState().getSetting(SETTINGS.ota_version_url.key)
|
|
409
|
-
const overrideActive = superMode && typeof overrideUrl === "string" && overrideUrl.trim() !== ""
|
|
410
|
-
if (!embeddedManifestUrl && !overrideActive) {
|
|
411
|
-
console.log("OTA: check skipped - mobile app has no embedded OTA manifest pin")
|
|
403
|
+
if (!hasConfiguredModernOtaManifestPin()) {
|
|
404
|
+
console.log("OTA: check skipped - this app or Engine package has no embedded OTA manifest pin")
|
|
412
405
|
return emptyCheckResult("dev_build")
|
|
413
406
|
}
|
|
414
|
-
if (!embeddedManifestUrl) {
|
|
415
|
-
console.log("OTA: no embedded manifest pin, but super-mode manifest override is active - checking anyway")
|
|
416
|
-
}
|
|
417
407
|
|
|
418
408
|
if (refreshVersionInfo) {
|
|
419
409
|
void BluetoothSdk.requestVersionInfo().catch((error) => {
|
|
@@ -472,7 +462,17 @@ export async function checkCurrentGlassesForUpdate(
|
|
|
472
462
|
}
|
|
473
463
|
|
|
474
464
|
const manifestUrl = resolveOtaManifestUrl(useGlassesStore.getState().otaVersionUrl, buildNumber)
|
|
475
|
-
|
|
465
|
+
if (!manifestUrl) {
|
|
466
|
+
console.log("OTA: check skipped - no OTA manifest pin resolved")
|
|
467
|
+
return emptyCheckResult("dev_build")
|
|
468
|
+
}
|
|
469
|
+
const result = await checkForOtaUpdate(
|
|
470
|
+
manifestUrl,
|
|
471
|
+
buildNumber,
|
|
472
|
+
mtkFirmwareVersion,
|
|
473
|
+
besFirmwareVersion,
|
|
474
|
+
floorVersionCode,
|
|
475
|
+
)
|
|
476
476
|
|
|
477
477
|
if (!result.hasCheckCompleted) {
|
|
478
478
|
return {
|
|
@@ -87,6 +87,10 @@ export async function handleOtaClockSkewFromGlasses(
|
|
|
87
87
|
lastOtaClockFixAt = Date.now()
|
|
88
88
|
const {buildNumber, otaVersionUrl} = useGlassesStore.getState()
|
|
89
89
|
const manifestUrl = resolveOtaManifestUrl(otaVersionUrl, buildNumber)
|
|
90
|
+
if (!manifestUrl) {
|
|
91
|
+
console.warn("[GlassesClockSync] OTA restart skipped because this build has no manifest pin")
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
90
94
|
console.log("[GlassesClockSync] ⏰ Restarting OTA with ota_start after clock fix")
|
|
91
95
|
await BluetoothSdk.startOtaUpdate(manifestUrl)
|
|
92
96
|
return true
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Shared OTA progress watchdog timings (see progress-legacy.tsx / progress.tsx). */
|
|
2
|
-
import type {OtaProgress, OtaStatus} from "@mentra/bluetooth-sdk
|
|
2
|
+
import type {OtaProgress, OtaStatus} from "@mentra/bluetooth-sdk"
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* First glasses `build_number` (ASG `versionCode`) that uses `progress.tsx` with unified
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {OtaProgress, OtaProgressStatus, OtaStatus} from "@mentra/bluetooth-sdk
|
|
1
|
+
import type {OtaProgress, OtaProgressStatus, OtaStatus} from "@mentra/bluetooth-sdk"
|
|
2
2
|
|
|
3
3
|
/** Normalized ota_status fields (snake_case) after bridging Core/expo (snake or camel). */
|
|
4
4
|
export type NormalizedOtaStatusEvent = {
|