@glassly/engine 0.4.0-beta.1052 → 0.4.0-beta.1076

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.
Files changed (57) hide show
  1. package/build/engine.d.ts +1 -0
  2. package/build/engine.d.ts.map +1 -1
  3. package/build/facades/permissions.d.ts.map +1 -1
  4. package/build/facades/permissions.js +0 -2
  5. package/build/facades/permissions.js.map +1 -1
  6. package/build/facades/phoneNotifications.d.ts +7 -0
  7. package/build/facades/phoneNotifications.d.ts.map +1 -1
  8. package/build/facades/phoneNotifications.js +6 -0
  9. package/build/facades/phoneNotifications.js.map +1 -1
  10. package/build/generated/releaseMetadata.js +3 -3
  11. package/build/generated/releaseMetadata.js.map +1 -1
  12. package/build/index.d.ts +1 -0
  13. package/build/index.d.ts.map +1 -1
  14. package/build/index.js.map +1 -1
  15. package/build/services/JSRouter.js +2 -2
  16. package/build/services/JSRouter.js.map +1 -1
  17. package/build/services/LocalLlmModelManager.d.ts.map +1 -1
  18. package/build/services/LocalLlmModelManager.js +4 -3
  19. package/build/services/LocalLlmModelManager.js.map +1 -1
  20. package/build/services/LocalLlmProvider.d.ts.map +1 -1
  21. package/build/services/LocalLlmProvider.js +5 -6
  22. package/build/services/LocalLlmProvider.js.map +1 -1
  23. package/build/services/LocalMiniappRuntime.d.ts +4 -0
  24. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  25. package/build/services/LocalMiniappRuntime.js +73 -4
  26. package/build/services/LocalMiniappRuntime.js.map +1 -1
  27. package/build/services/notifications/miniappNotifications.d.ts +31 -0
  28. package/build/services/notifications/miniappNotifications.d.ts.map +1 -0
  29. package/build/services/notifications/miniappNotifications.js +24 -0
  30. package/build/services/notifications/miniappNotifications.js.map +1 -0
  31. package/build/services/pages/pageEligibility.d.ts +1 -2
  32. package/build/services/pages/pageEligibility.d.ts.map +1 -1
  33. package/build/services/pages/pageEligibility.js +4 -2
  34. package/build/services/pages/pageEligibility.js.map +1 -1
  35. package/build/services/uiShim.d.ts.map +1 -1
  36. package/build/services/uiShim.js +14 -0
  37. package/build/services/uiShim.js.map +1 -1
  38. package/build/stores/settings.d.ts.map +1 -1
  39. package/build/stores/settings.js +7 -8
  40. package/build/stores/settings.js.map +1 -1
  41. package/build/types/capabilities/nimo.d.ts.map +1 -1
  42. package/build/types/capabilities/nimo.js +2 -0
  43. package/build/types/capabilities/nimo.js.map +1 -1
  44. package/package.json +15 -15
  45. package/src/facades/permissions.ts +0 -2
  46. package/src/facades/phoneNotifications.ts +10 -0
  47. package/src/generated/releaseMetadata.ts +3 -3
  48. package/src/index.ts +1 -0
  49. package/src/services/JSRouter.ts +2 -2
  50. package/src/services/LocalLlmModelManager.ts +4 -3
  51. package/src/services/LocalLlmProvider.ts +6 -7
  52. package/src/services/LocalMiniappRuntime.ts +86 -4
  53. package/src/services/notifications/miniappNotifications.ts +53 -0
  54. package/src/services/pages/pageEligibility.ts +3 -2
  55. package/src/services/uiShim.ts +14 -0
  56. package/src/stores/settings.ts +7 -8
  57. package/src/types/capabilities/nimo.ts +3 -0
package/build/engine.d.ts CHANGED
@@ -343,6 +343,7 @@ export declare const engine: {
343
343
  nativeNotifications: typeof import("./services/PhoneNotificationsSync").nativeNotificationsSupported;
344
344
  popupSecondsOptions: typeof import("./services/PhoneNotificationsSync").nativeNotificationPopupSeconds;
345
345
  presentationOwner: typeof import("./services/PhoneNotificationsSync").currentPresentationOwner;
346
+ onMiniappNotification: (listener: (event: import(".").MiniappNotificationEvent) => void) => (() => void);
346
347
  uploadToGlasses: (event: import("@glassly/crust").PhoneNotificationEvent) => Promise<void>;
347
348
  glassesStatus: () => Promise<import("@glassly/bluetooth-sdk").GlassesNotificationStatus>;
348
349
  onGlassesStatus: (listener: (status: import("@glassly/bluetooth-sdk").GlassesNotificationStatus) => void) => (() => void);
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAC,SAAS,EAAkD,aAAa,EAAC,MAAM,qBAAqB,CAAA;AAgD5G,eAAO,MAAM,MAAM;IACjB,2EAA2E;;IAE3E,8EAA8E;;IAE9E;iDAC6C;;IA2G7C;;yCAEqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAoCrC,kEAAkE;;;;;;;;;;;;;;;;;;;;;;;IAElE,wEAAwE;;;;;;;;IAExE,sEAAsE;;;;;;;;;;;;IAEtE,qFAAqF;;;;gBA7IpE,CAAC;mBAAiB,CAAC;;;gBAMlC,CAFF;mBAAiB,CAAC;;;;;;;;;;;;;;;;;IA2IlB,qEAAqE;;;;;IAErE,sFAAsF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAEtF,6EAA6E;;;;;;;;;;;;IAE7E,iFAAiF;;;;;;;;;;;;;;;;;;;;;;;;IAEjF,8CAA8C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAE9C,uDAAuD;;;;;;;;;;;;;;;;IAEvD,8EAA8E;;;;;;;;IAE9E,qFAAqF;;;;IAErF,4EAA4E;;;;;;;;;;;IAE5E,+EAA+E;;;;;;;;;;;;;;;IAE/E,qGAAqG;;;;;;IAErG,kFAAkF;;;;;+BAvKjE,CAAC;;;+BAUiC,CAAC;;;;;;;;;;;;IA+JpD,6FAA6F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAG9F,CAAA"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAC,SAAS,EAAkD,aAAa,EAAC,MAAM,qBAAqB,CAAA;AAgD5G,eAAO,MAAM,MAAM;IACjB,2EAA2E;;IAE3E,8EAA8E;;IAE9E;iDAC6C;;IA2G7C;;yCAEqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAoCrC,kEAAkE;;;;;;;;;;;;;;;;;;;;;;;IAElE,wEAAwE;;;;;;;;IAExE,sEAAsE;;;;;;;;;;;;IAEtE,qFAAqF;;;;gBA7IpE,CAAC;mBAAiB,CAAC;;;gBAMlC,CAFF;mBAAiB,CAAC;;;;;;;;;;;;;;;;;IA2IlB,qEAAqE;;;;;IAErE,sFAAsF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAEtF,6EAA6E;;;;;;;;;;;;IAE7E,iFAAiF;;;;;;;;;;;;;;;;;;;;;;;;IAEjF,8CAA8C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAE9C,uDAAuD;;;;;;;;;;;;;;;;;IAEvD,8EAA8E;;;;;;;;IAE9E,qFAAqF;;;;IAErF,4EAA4E;;;;;;;;;;;IAE5E,+EAA+E;;;;;;;;;;;;;;;IAE/E,qGAAqG;;;;;;IAErG,kFAAkF;;;;;+BAvKjE,CAAC;;;+BAUiC,CAAC;;;;;;;;;;;;IA+JpD,6FAA6F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAG9F,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/facades/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAoB,kBAAkB,EAAE,KAAK,UAAU,IAAI,iBAAiB,EAAC,MAAM,cAAc,CAAA;AAIxG,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,UAAU,CAAA;AAE9C,uEAAuE;AACvE,eAAO,MAAM,kBAAkB;;;;;;;;;;CAUrB,CAAA;AAMV,wBAAgB,6BAA6B,CAC3C,eAAe,EAAE,MAAM,EACvB,kBAAkB,GAAE,OAAO,kBAAkB,CAAC,WAAqB,GAClE,iBAAiB,CAEnB;AAgFD,eAAO,MAAM,WAAW;IACtB,gGAAgG;kCAC5D,SAAS,gBAAgB,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA6CnF,8DAA8D;mBACzC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmB9C,mFAAmF;qBAC5D,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmBhD,6EAA6E;wBAC3D,OAAO,CAAC,IAAI,CAAC;IAE/B,mEAAmE;wCACzB,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAI/E,CAAA"}
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/facades/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAoB,kBAAkB,EAAE,KAAK,UAAU,IAAI,iBAAiB,EAAC,MAAM,cAAc,CAAA;AAIxG,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,UAAU,CAAA;AAE9C,uEAAuE;AACvE,eAAO,MAAM,kBAAkB;;;;;;;;;;CAUrB,CAAA;AAMV,wBAAgB,6BAA6B,CAC3C,eAAe,EAAE,MAAM,EACvB,kBAAkB,GAAE,OAAO,kBAAkB,CAAC,WAAqB,GAClE,iBAAiB,CAEnB;AAgFD,eAAO,MAAM,WAAW;IACtB,gGAAgG;kCAC5D,SAAS,gBAAgB,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA2CnF,8DAA8D;mBACzC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmB9C,mFAAmF;qBAC5D,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmBhD,6EAA6E;wBAC3D,OAAO,CAAC,IAAI,CAAC;IAE/B,mEAAmE;wCACzB,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAI/E,CAAA"}
@@ -112,14 +112,12 @@ export const permissions = {
112
112
  features.add(PermissionFeatures.CALENDAR);
113
113
  features.add(PermissionFeatures.LOCATION);
114
114
  features.add(PermissionFeatures.BACKGROUND_LOCATION);
115
- features.add(PermissionFeatures.POST_NOTIFICATIONS);
116
115
  features.add("read_notifications");
117
116
  break;
118
117
  case "MICROPHONE":
119
118
  case "CALENDAR":
120
119
  case "LOCATION":
121
120
  case "BACKGROUND_LOCATION":
122
- case "POST_NOTIFICATIONS":
123
121
  features.add(PermissionFeatures[permission.type]);
124
122
  break;
125
123
  case "READ_NOTIFICATIONS":
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/facades/permissions.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * permissions facade — `engine.permissions`: the raw OS-permission ops the runtime\n * needs, mapped from feature keys to react-native-permissions. This is the LEAN\n * surface (check/request/openSettings/requirementsForMiniapp) — the host keeps its\n * own UI helpers (rationale dialogs, denied-warnings) on top; engine stays free of\n * i18n/theme/AlertUtils.\n */\nimport {Platform, Linking, PermissionsAndroid, type Permission as AndroidPermission} from \"react-native\"\nimport {check, request, PERMISSIONS, RESULTS, type Permission} from \"react-native-permissions\"\n\nimport appRegistry from \"../services/AppRegistry\"\nimport type {AppletPermission} from \"../types\"\n\n/** OEM-facing feature keys (mapped to OS permissions per platform). */\nexport const PermissionFeatures = {\n MICROPHONE: \"microphone\",\n CAMERA: \"camera\",\n CALENDAR: \"calendar\",\n LOCATION: \"location\",\n LOCAL_WIFI: \"local_wifi\",\n BACKGROUND_LOCATION: \"background_location\",\n BLUETOOTH: \"bluetooth\",\n PHONE_STATE: \"phone_state\",\n POST_NOTIFICATIONS: \"post_notifications\",\n} as const\n\nconst ANDROID = PermissionsAndroid.PERMISSIONS\nconst apiLevel = typeof Platform.Version === \"number\" ? Platform.Version : parseInt(String(Platform.Version), 10)\nconst requiresSeparateAndroidBackgroundLocation = apiLevel >= 29\n\nexport function localWifiPermissionForAndroid(\n androidApiLevel: number,\n androidPermissions: typeof PermissionsAndroid.PERMISSIONS = ANDROID,\n): AndroidPermission {\n return androidApiLevel >= 33 ? androidPermissions.NEARBY_WIFI_DEVICES : androidPermissions.ACCESS_FINE_LOCATION\n}\n\nasync function areAndroidPermissionsGranted(perms: AndroidPermission[]): Promise<boolean> {\n for (const p of perms) {\n if (!(await PermissionsAndroid.check(p))) return false\n }\n return true\n}\n\nasync function requestAndroidPermissions(perms: AndroidPermission[]): Promise<boolean> {\n const results = await PermissionsAndroid.requestMultiple(perms)\n return perms.every((p) => results[p] === PermissionsAndroid.RESULTS.GRANTED)\n}\n\nasync function checkAndroidBackgroundLocation(): Promise<boolean> {\n const hasForegroundLocation = await areAndroidPermissionsGranted([ANDROID.ACCESS_FINE_LOCATION])\n if (!hasForegroundLocation || !requiresSeparateAndroidBackgroundLocation) return hasForegroundLocation\n\n return PermissionsAndroid.check(ANDROID.ACCESS_BACKGROUND_LOCATION)\n}\n\nasync function requestAndroidBackgroundLocation(): Promise<boolean> {\n const hasForegroundLocation = await requestAndroidPermissions([ANDROID.ACCESS_FINE_LOCATION])\n if (!hasForegroundLocation || !requiresSeparateAndroidBackgroundLocation) return hasForegroundLocation\n\n if (await PermissionsAndroid.check(ANDROID.ACCESS_BACKGROUND_LOCATION)) return true\n\n const result = await PermissionsAndroid.request(ANDROID.ACCESS_BACKGROUND_LOCATION)\n return result === PermissionsAndroid.RESULTS.GRANTED\n}\n\nfunction iosPerms(feature: string): Permission[] {\n switch (feature) {\n case PermissionFeatures.MICROPHONE:\n return [PERMISSIONS.IOS.MICROPHONE]\n case PermissionFeatures.CAMERA:\n return [PERMISSIONS.IOS.CAMERA]\n case PermissionFeatures.CALENDAR:\n return [PERMISSIONS.IOS.CALENDARS]\n case PermissionFeatures.LOCATION:\n return [PERMISSIONS.IOS.LOCATION_WHEN_IN_USE]\n case PermissionFeatures.LOCAL_WIFI:\n return []\n case PermissionFeatures.BACKGROUND_LOCATION:\n // iOS won't grant ALWAYS without WHEN_IN_USE first — request both (matches\n // the host PermissionsUtils mapping), else a cold request can't escalate.\n return [PERMISSIONS.IOS.LOCATION_WHEN_IN_USE, PERMISSIONS.IOS.LOCATION_ALWAYS]\n case PermissionFeatures.BLUETOOTH:\n return [PERMISSIONS.IOS.BLUETOOTH]\n default:\n return []\n }\n}\n\nfunction androidPerms(feature: string): AndroidPermission[] {\n switch (feature) {\n case PermissionFeatures.MICROPHONE:\n return [ANDROID.RECORD_AUDIO]\n case PermissionFeatures.CAMERA:\n return [ANDROID.CAMERA]\n case PermissionFeatures.CALENDAR:\n // Expo Calendar requires both grants on Android, including for read APIs.\n // The miniapp-facing calendar API remains read-only.\n return [ANDROID.READ_CALENDAR, ANDROID.WRITE_CALENDAR]\n case PermissionFeatures.LOCATION:\n case PermissionFeatures.BACKGROUND_LOCATION:\n return [ANDROID.ACCESS_FINE_LOCATION]\n case PermissionFeatures.LOCAL_WIFI:\n return [localWifiPermissionForAndroid(apiLevel)]\n case PermissionFeatures.PHONE_STATE:\n return [ANDROID.READ_PHONE_STATE]\n case PermissionFeatures.BLUETOOTH:\n return apiLevel >= 31 ? [ANDROID.BLUETOOTH_SCAN, ANDROID.BLUETOOTH_CONNECT, ANDROID.BLUETOOTH_ADVERTISE] : []\n case PermissionFeatures.POST_NOTIFICATIONS:\n return apiLevel >= 33 ? [ANDROID.POST_NOTIFICATIONS] : []\n default:\n return []\n }\n}\n\nexport const permissions = {\n /** Missing required miniapp grants, checked without prompting. CAMERA is the glasses camera. */\n async missingRequired(requirements: readonly AppletPermission[]): Promise<string[]> {\n const features = new Set<string>()\n for (const permission of requirements) {\n if (permission.required === false) continue\n switch (permission.type) {\n case \"ALL\":\n features.add(PermissionFeatures.MICROPHONE)\n features.add(PermissionFeatures.CALENDAR)\n features.add(PermissionFeatures.LOCATION)\n features.add(PermissionFeatures.BACKGROUND_LOCATION)\n features.add(PermissionFeatures.POST_NOTIFICATIONS)\n features.add(\"read_notifications\")\n break\n case \"MICROPHONE\":\n case \"CALENDAR\":\n case \"LOCATION\":\n case \"BACKGROUND_LOCATION\":\n case \"POST_NOTIFICATIONS\":\n features.add(PermissionFeatures[permission.type])\n break\n case \"READ_NOTIFICATIONS\":\n features.add(\"read_notifications\")\n break\n }\n }\n\n const missing: string[] = []\n for (const feature of features) {\n let granted: boolean\n if (feature === \"read_notifications\") {\n // iOS glasses read notifications directly; Android uses the phone's listener.\n granted =\n Platform.OS !== \"android\" ||\n (await (await import(\"@glassly/crust\")).default.hasNotificationListenerPermission())\n } else if (feature === PermissionFeatures.CALENDAR && Platform.OS === \"ios\") {\n // EventKit must allow reads; a scoped/write-only OS grant is insufficient.\n granted = (await (await import(\"expo-calendar\")).getCalendarPermissions()).status === \"granted\"\n } else {\n granted = await permissions.check(feature)\n }\n if (!granted) missing.push(feature)\n }\n return missing\n },\n\n /** Is the given feature's OS permission currently granted? */\n async check(feature: string): Promise<boolean> {\n if (Platform.OS === \"android\") {\n if (feature === PermissionFeatures.BACKGROUND_LOCATION) return checkAndroidBackgroundLocation()\n\n const perms = androidPerms(feature)\n if (perms.length === 0) return true // nothing to ask on this OS/version\n // Every permission in the group must be granted (e.g. bluetooth =\n // scan+connect+advertise, calendar = read+write) — matches the iOS branch.\n return areAndroidPermissionsGranted(perms)\n }\n const perms = iosPerms(feature)\n if (perms.length === 0) return true\n for (const p of perms) {\n const status = await check(p)\n if (status !== RESULTS.GRANTED && status !== RESULTS.LIMITED) return false\n }\n return true\n },\n\n /** Request the given feature's OS permission. Resolves to whether it's granted. */\n async request(feature: string): Promise<boolean> {\n if (Platform.OS === \"android\") {\n if (feature === PermissionFeatures.BACKGROUND_LOCATION) return requestAndroidBackgroundLocation()\n\n const perms = androidPerms(feature)\n if (perms.length === 0) return true\n // Granted only when EVERY permission in the group was granted.\n return requestAndroidPermissions(perms)\n }\n const perms = iosPerms(feature)\n if (perms.length === 0) return true\n let granted = true\n for (const p of perms) {\n const result = await request(p)\n if (result !== RESULTS.GRANTED && result !== RESULTS.LIMITED) granted = false\n }\n return granted\n },\n\n /** Open the OS settings app (so the user can grant a blocked permission). */\n openSettings: (): Promise<void> => Linking.openSettings(),\n\n /** The permissions a given installed miniapp declares it needs. */\n async requirementsForMiniapp(packageName: string): Promise<AppletPermission[]> {\n const apps = await appRegistry.getInstalledMiniapps()\n return apps.find((a) => a.packageName === packageName)?.permissions ?? []\n },\n}\n"]}
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/facades/permissions.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * permissions facade — `engine.permissions`: the raw OS-permission ops the runtime\n * needs, mapped from feature keys to react-native-permissions. This is the LEAN\n * surface (check/request/openSettings/requirementsForMiniapp) — the host keeps its\n * own UI helpers (rationale dialogs, denied-warnings) on top; engine stays free of\n * i18n/theme/AlertUtils.\n */\nimport {Platform, Linking, PermissionsAndroid, type Permission as AndroidPermission} from \"react-native\"\nimport {check, request, PERMISSIONS, RESULTS, type Permission} from \"react-native-permissions\"\n\nimport appRegistry from \"../services/AppRegistry\"\nimport type {AppletPermission} from \"../types\"\n\n/** OEM-facing feature keys (mapped to OS permissions per platform). */\nexport const PermissionFeatures = {\n MICROPHONE: \"microphone\",\n CAMERA: \"camera\",\n CALENDAR: \"calendar\",\n LOCATION: \"location\",\n LOCAL_WIFI: \"local_wifi\",\n BACKGROUND_LOCATION: \"background_location\",\n BLUETOOTH: \"bluetooth\",\n PHONE_STATE: \"phone_state\",\n POST_NOTIFICATIONS: \"post_notifications\",\n} as const\n\nconst ANDROID = PermissionsAndroid.PERMISSIONS\nconst apiLevel = typeof Platform.Version === \"number\" ? Platform.Version : parseInt(String(Platform.Version), 10)\nconst requiresSeparateAndroidBackgroundLocation = apiLevel >= 29\n\nexport function localWifiPermissionForAndroid(\n androidApiLevel: number,\n androidPermissions: typeof PermissionsAndroid.PERMISSIONS = ANDROID,\n): AndroidPermission {\n return androidApiLevel >= 33 ? androidPermissions.NEARBY_WIFI_DEVICES : androidPermissions.ACCESS_FINE_LOCATION\n}\n\nasync function areAndroidPermissionsGranted(perms: AndroidPermission[]): Promise<boolean> {\n for (const p of perms) {\n if (!(await PermissionsAndroid.check(p))) return false\n }\n return true\n}\n\nasync function requestAndroidPermissions(perms: AndroidPermission[]): Promise<boolean> {\n const results = await PermissionsAndroid.requestMultiple(perms)\n return perms.every((p) => results[p] === PermissionsAndroid.RESULTS.GRANTED)\n}\n\nasync function checkAndroidBackgroundLocation(): Promise<boolean> {\n const hasForegroundLocation = await areAndroidPermissionsGranted([ANDROID.ACCESS_FINE_LOCATION])\n if (!hasForegroundLocation || !requiresSeparateAndroidBackgroundLocation) return hasForegroundLocation\n\n return PermissionsAndroid.check(ANDROID.ACCESS_BACKGROUND_LOCATION)\n}\n\nasync function requestAndroidBackgroundLocation(): Promise<boolean> {\n const hasForegroundLocation = await requestAndroidPermissions([ANDROID.ACCESS_FINE_LOCATION])\n if (!hasForegroundLocation || !requiresSeparateAndroidBackgroundLocation) return hasForegroundLocation\n\n if (await PermissionsAndroid.check(ANDROID.ACCESS_BACKGROUND_LOCATION)) return true\n\n const result = await PermissionsAndroid.request(ANDROID.ACCESS_BACKGROUND_LOCATION)\n return result === PermissionsAndroid.RESULTS.GRANTED\n}\n\nfunction iosPerms(feature: string): Permission[] {\n switch (feature) {\n case PermissionFeatures.MICROPHONE:\n return [PERMISSIONS.IOS.MICROPHONE]\n case PermissionFeatures.CAMERA:\n return [PERMISSIONS.IOS.CAMERA]\n case PermissionFeatures.CALENDAR:\n return [PERMISSIONS.IOS.CALENDARS]\n case PermissionFeatures.LOCATION:\n return [PERMISSIONS.IOS.LOCATION_WHEN_IN_USE]\n case PermissionFeatures.LOCAL_WIFI:\n return []\n case PermissionFeatures.BACKGROUND_LOCATION:\n // iOS won't grant ALWAYS without WHEN_IN_USE first — request both (matches\n // the host PermissionsUtils mapping), else a cold request can't escalate.\n return [PERMISSIONS.IOS.LOCATION_WHEN_IN_USE, PERMISSIONS.IOS.LOCATION_ALWAYS]\n case PermissionFeatures.BLUETOOTH:\n return [PERMISSIONS.IOS.BLUETOOTH]\n default:\n return []\n }\n}\n\nfunction androidPerms(feature: string): AndroidPermission[] {\n switch (feature) {\n case PermissionFeatures.MICROPHONE:\n return [ANDROID.RECORD_AUDIO]\n case PermissionFeatures.CAMERA:\n return [ANDROID.CAMERA]\n case PermissionFeatures.CALENDAR:\n // Expo Calendar requires both grants on Android, including for read APIs.\n // The miniapp-facing calendar API remains read-only.\n return [ANDROID.READ_CALENDAR, ANDROID.WRITE_CALENDAR]\n case PermissionFeatures.LOCATION:\n case PermissionFeatures.BACKGROUND_LOCATION:\n return [ANDROID.ACCESS_FINE_LOCATION]\n case PermissionFeatures.LOCAL_WIFI:\n return [localWifiPermissionForAndroid(apiLevel)]\n case PermissionFeatures.PHONE_STATE:\n return [ANDROID.READ_PHONE_STATE]\n case PermissionFeatures.BLUETOOTH:\n return apiLevel >= 31 ? [ANDROID.BLUETOOTH_SCAN, ANDROID.BLUETOOTH_CONNECT, ANDROID.BLUETOOTH_ADVERTISE] : []\n case PermissionFeatures.POST_NOTIFICATIONS:\n return apiLevel >= 33 ? [ANDROID.POST_NOTIFICATIONS] : []\n default:\n return []\n }\n}\n\nexport const permissions = {\n /** Missing required miniapp grants, checked without prompting. CAMERA is the glasses camera. */\n async missingRequired(requirements: readonly AppletPermission[]): Promise<string[]> {\n const features = new Set<string>()\n for (const permission of requirements) {\n if (permission.required === false) continue\n switch (permission.type) {\n case \"ALL\":\n features.add(PermissionFeatures.MICROPHONE)\n features.add(PermissionFeatures.CALENDAR)\n features.add(PermissionFeatures.LOCATION)\n features.add(PermissionFeatures.BACKGROUND_LOCATION)\n features.add(\"read_notifications\")\n break\n case \"MICROPHONE\":\n case \"CALENDAR\":\n case \"LOCATION\":\n case \"BACKGROUND_LOCATION\":\n features.add(PermissionFeatures[permission.type])\n break\n case \"READ_NOTIFICATIONS\":\n features.add(\"read_notifications\")\n break\n }\n }\n\n const missing: string[] = []\n for (const feature of features) {\n let granted: boolean\n if (feature === \"read_notifications\") {\n // iOS glasses read notifications directly; Android uses the phone's listener.\n granted =\n Platform.OS !== \"android\" ||\n (await (await import(\"@glassly/crust\")).default.hasNotificationListenerPermission())\n } else if (feature === PermissionFeatures.CALENDAR && Platform.OS === \"ios\") {\n // EventKit must allow reads; a scoped/write-only OS grant is insufficient.\n granted = (await (await import(\"expo-calendar\")).getCalendarPermissions()).status === \"granted\"\n } else {\n granted = await permissions.check(feature)\n }\n if (!granted) missing.push(feature)\n }\n return missing\n },\n\n /** Is the given feature's OS permission currently granted? */\n async check(feature: string): Promise<boolean> {\n if (Platform.OS === \"android\") {\n if (feature === PermissionFeatures.BACKGROUND_LOCATION) return checkAndroidBackgroundLocation()\n\n const perms = androidPerms(feature)\n if (perms.length === 0) return true // nothing to ask on this OS/version\n // Every permission in the group must be granted (e.g. bluetooth =\n // scan+connect+advertise, calendar = read+write) — matches the iOS branch.\n return areAndroidPermissionsGranted(perms)\n }\n const perms = iosPerms(feature)\n if (perms.length === 0) return true\n for (const p of perms) {\n const status = await check(p)\n if (status !== RESULTS.GRANTED && status !== RESULTS.LIMITED) return false\n }\n return true\n },\n\n /** Request the given feature's OS permission. Resolves to whether it's granted. */\n async request(feature: string): Promise<boolean> {\n if (Platform.OS === \"android\") {\n if (feature === PermissionFeatures.BACKGROUND_LOCATION) return requestAndroidBackgroundLocation()\n\n const perms = androidPerms(feature)\n if (perms.length === 0) return true\n // Granted only when EVERY permission in the group was granted.\n return requestAndroidPermissions(perms)\n }\n const perms = iosPerms(feature)\n if (perms.length === 0) return true\n let granted = true\n for (const p of perms) {\n const result = await request(p)\n if (result !== RESULTS.GRANTED && result !== RESULTS.LIMITED) granted = false\n }\n return granted\n },\n\n /** Open the OS settings app (so the user can grant a blocked permission). */\n openSettings: (): Promise<void> => Linking.openSettings(),\n\n /** The permissions a given installed miniapp declares it needs. */\n async requirementsForMiniapp(packageName: string): Promise<AppletPermission[]> {\n const apps = await appRegistry.getInstalledMiniapps()\n return apps.find((a) => a.packageName === packageName)?.permissions ?? []\n },\n}\n"]}
@@ -1,6 +1,8 @@
1
1
  import type { PhoneNotificationEvent } from "@glassly/crust";
2
2
  import type { GlassesNotificationStatus, NotificationUploadResult } from "@glassly/bluetooth-sdk";
3
3
  import { captureAuthorization, currentPresentationOwner, installedNotificationApps, nativeNotificationPopupSeconds, nativeNotificationsSupported } from "../services/PhoneNotificationsSync";
4
+ import { type MiniappNotificationEvent } from "../services/notifications/miniappNotifications";
5
+ export type { MiniappNotificationEvent } from "../services/notifications/miniappNotifications";
4
6
  export declare const phoneNotifications: {
5
7
  /**
6
8
  * Apps to show in the notification filter UI (package/bundle id, name, icon).
@@ -27,6 +29,11 @@ export declare const phoneNotifications: {
27
29
  * surface runs and draw only when the answer is `host`.
28
30
  */
29
31
  presentationOwner: typeof currentPresentationOwner;
32
+ /**
33
+ * Notifications miniapps post and dismiss. Hosts feed them to the same
34
+ * fan-out as the phone's, marked `system: false` with `source` set.
35
+ */
36
+ onMiniappNotification: (listener: (event: MiniappNotificationEvent) => void) => (() => void);
30
37
  /** Hand a captured notification to firmware that presents uploaded content (owner `firmware`, Android). */
31
38
  uploadToGlasses: (event: PhoneNotificationEvent) => Promise<void>;
32
39
  /** The driver's view of its notification surface. */
@@ -1 +1 @@
1
- {"version":3,"file":"phoneNotifications.d.ts","sourceRoot":"","sources":["../../src/facades/phoneNotifications.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,gBAAgB,CAAA;AAE1D,OAAO,KAAK,EAAC,yBAAyB,EAAE,wBAAwB,EAAC,MAAM,wBAAwB,CAAA;AAE/F,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,EACzB,8BAA8B,EAC9B,4BAA4B,EAE7B,MAAM,oCAAoC,CAAA;AAE3C,eAAO,MAAM,kBAAkB;IAC7B;;;;OAIG;;IAGH,wFAAwF;qBACzE,MAAM,EAAE;IAIvB,qCAAqC;iCACR,MAAM,EAAE;IAGrC,qFAAqF;iCAC1D,OAAO,CAAC,OAAO,CAAC;IAI3C,yFAAyF;;IAMzF,qGAAqG;;IAGrG,8DAA8D;;IAE9D,kGAAkG;;IAGlG;;;OAGG;;IAEH,2GAA2G;6BAClF,sBAAsB,KAAG,OAAO,CAAC,IAAI,CAAC;IAE/D,qDAAqD;yBAClC,OAAO,CAAC,yBAAyB,CAAC;gCACzB,CAAC,MAAM,EAAE,yBAAyB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAItF,yDAAyD;+BAC9B,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;CAIrF,CAAA"}
1
+ {"version":3,"file":"phoneNotifications.d.ts","sourceRoot":"","sources":["../../src/facades/phoneNotifications.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,gBAAgB,CAAA;AAE1D,OAAO,KAAK,EAAC,yBAAyB,EAAE,wBAAwB,EAAC,MAAM,wBAAwB,CAAA;AAE/F,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,EACzB,8BAA8B,EAC9B,4BAA4B,EAE7B,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EAAwB,KAAK,wBAAwB,EAAC,MAAM,gDAAgD,CAAA;AAEnH,YAAY,EAAC,wBAAwB,EAAC,MAAM,gDAAgD,CAAA;AAE5F,eAAO,MAAM,kBAAkB;IAC7B;;;;OAIG;;IAGH,wFAAwF;qBACzE,MAAM,EAAE;IAIvB,qCAAqC;iCACR,MAAM,EAAE;IAGrC,qFAAqF;iCAC1D,OAAO,CAAC,OAAO,CAAC;IAI3C,yFAAyF;;IAMzF,qGAAqG;;IAGrG,8DAA8D;;IAE9D,kGAAkG;;IAGlG;;;OAGG;;IAEH;;;OAGG;sCAC+B,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAG1F,2GAA2G;6BAClF,sBAAsB,KAAG,OAAO,CAAC,IAAI,CAAC;IAE/D,qDAAqD;yBAClC,OAAO,CAAC,yBAAyB,CAAC;gCACzB,CAAC,MAAM,EAAE,yBAAyB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;IAItF,yDAAyD;+BAC9B,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC;CAIrF,CAAA"}
@@ -14,6 +14,7 @@ import CrustModule from "@glassly/crust";
14
14
  import BluetoothSdk from "@glassly/bluetooth-sdk/internal";
15
15
  import { useSettingsStore, SETTINGS } from "../stores/settings";
16
16
  import { captureAuthorization, currentPresentationOwner, installedNotificationApps, nativeNotificationPopupSeconds, nativeNotificationsSupported, uploadPhoneNotification, } from "../services/PhoneNotificationsSync";
17
+ import { onMiniappNotification } from "../services/notifications/miniappNotifications";
17
18
  export const phoneNotifications = {
18
19
  /**
19
20
  * Apps to show in the notification filter UI (package/bundle id, name, icon).
@@ -51,6 +52,11 @@ export const phoneNotifications = {
51
52
  * surface runs and draw only when the answer is `host`.
52
53
  */
53
54
  presentationOwner: currentPresentationOwner,
55
+ /**
56
+ * Notifications miniapps post and dismiss. Hosts feed them to the same
57
+ * fan-out as the phone's, marked `system: false` with `source` set.
58
+ */
59
+ onMiniappNotification: (listener) => onMiniappNotification(listener),
54
60
  /** Hand a captured notification to firmware that presents uploaded content (owner `firmware`, Android). */
55
61
  uploadToGlasses: (event) => uploadPhoneNotification(event),
56
62
  /** The driver's view of its notification surface. */
@@ -1 +1 @@
1
- {"version":3,"file":"phoneNotifications.js","sourceRoot":"","sources":["../../src/facades/phoneNotifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAC,QAAQ,EAAC,MAAM,cAAc,CAAA;AACrC,OAAO,WAAW,MAAM,gBAAgB,CAAA;AAExC,OAAO,YAAY,MAAM,iCAAiC,CAAA;AAE1D,OAAO,EAAC,gBAAgB,EAAE,QAAQ,EAAC,MAAM,oBAAoB,CAAA;AAC7D,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,EACzB,8BAA8B,EAC9B,4BAA4B,EAC5B,uBAAuB,GACxB,MAAM,oCAAoC,CAAA;AAE3C,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC;;;;OAIG;IACH,aAAa,EAAE,yBAAyB;IAExC,wFAAwF;IACxF,SAAS,EAAE,GAAa,EAAE;QACxB,MAAM,CAAC,GAAG,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAA;QACtF,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAClC,CAAC;IACD,qCAAqC;IACrC,YAAY,EAAE,CAAC,YAAsB,EAAE,EAAE,CACvC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,uBAAuB,CAAC,GAAG,EAAE,YAAY,CAAC;IAE5F,qFAAqF;IACrF,qBAAqB,EAAE,GAAqB,EAAE;QAC5C,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAC5D,OAAO,WAAW,CAAC,iCAAiC,EAAE,CAAA;IACxD,CAAC;IACD,yFAAyF;IACzF,yBAAyB,EAAE,GAAG,EAAE;QAC9B,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS;YAAE,OAAM;QACrC,OAAO,WAAW,CAAC,gCAAgC,EAAE,CAAA;IACvD,CAAC;IAED,qGAAqG;IACrG,oBAAoB;IAEpB,8DAA8D;IAC9D,mBAAmB,EAAE,4BAA4B;IACjD,kGAAkG;IAClG,mBAAmB,EAAE,8BAA8B;IAEnD;;;OAGG;IACH,iBAAiB,EAAE,wBAAwB;IAC3C,2GAA2G;IAC3G,eAAe,EAAE,CAAC,KAA6B,EAAiB,EAAE,CAAC,uBAAuB,CAAC,KAAK,CAAC;IAEjG,qDAAqD;IACrD,aAAa,EAAE,GAAuC,EAAE,CAAC,YAAY,CAAC,4BAA4B,EAAE;IACpG,eAAe,EAAE,CAAC,QAAqD,EAAgB,EAAE;QACvF,MAAM,YAAY,GAAG,YAAY,CAAC,WAAW,CAAC,6BAA6B,EAAE,QAAQ,CAAC,CAAA;QACtF,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAA;IACpC,CAAC;IACD,yDAAyD;IACzD,cAAc,EAAE,CAAC,QAAoD,EAAgB,EAAE;QACrF,MAAM,YAAY,GAAG,YAAY,CAAC,WAAW,CAAC,4BAA4B,EAAE,QAAQ,CAAC,CAAA;QACrF,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAA;IACpC,CAAC;CACF,CAAA","sourcesContent":["/**\n * phoneNotifications facade — `engine.phoneNotifications`: phone notifications\n * on the glasses, with a per-app blocklist and one presentation owner.\n *\n * Capture is the phone's (Android listener) or the glasses' (iOS, reading the\n * phone's stream) business and is never gated here. Presentation is decided\n * by `presentationOwner`: the engine's viewer on Glassly CFW glasses, the\n * firmware on glasses with their own notification centre, else the host's\n * card while its surface (Notify) runs. The four display settings drive\n * firmware and viewer alike; PhoneNotificationsSync pushes them.\n */\nimport {Platform} from \"react-native\"\nimport CrustModule from \"@glassly/crust\"\nimport type {PhoneNotificationEvent} from \"@glassly/crust\"\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport type {GlassesNotificationStatus, NotificationUploadResult} from \"@glassly/bluetooth-sdk\"\nimport {useSettingsStore, SETTINGS} from \"../stores/settings\"\nimport {\n captureAuthorization,\n currentPresentationOwner,\n installedNotificationApps,\n nativeNotificationPopupSeconds,\n nativeNotificationsSupported,\n uploadPhoneNotification,\n} from \"../services/PhoneNotificationsSync\"\n\nexport const phoneNotifications = {\n /**\n * Apps to show in the notification filter UI (package/bundle id, name, icon).\n * Android: installed apps. iOS: seeded catalog ∪ glasses-reported apps\n * (icons unavailable — iOS offers no cross-app icon lookup).\n */\n installedApps: installedNotificationApps,\n\n /** The per-app blocklist (package/bundle ids whose notifications are NOT forwarded). */\n blocklist: (): string[] => {\n const b = useSettingsStore.getState().getSetting(SETTINGS.notifications_blocklist.key)\n return Array.isArray(b) ? b : []\n },\n /** Replace the per-app blocklist. */\n setBlocklist: (packageNames: string[]) =>\n useSettingsStore.getState().setSetting(SETTINGS.notifications_blocklist.key, packageNames),\n\n /** Does the app have the Android notification-listener permission? (false on iOS) */\n hasListenerPermission: (): Promise<boolean> => {\n if (Platform.OS !== \"android\") return Promise.resolve(false)\n return CrustModule.hasNotificationListenerPermission()\n },\n /** Open the OS settings to grant the notification-listener permission. (no-op on iOS) */\n requestListenerPermission: () => {\n if (Platform.OS !== \"android\") return\n return CrustModule.openNotificationListenerSettings()\n },\n\n /** Whether the glasses may read the phone's notifications; `not_needed` where the phone captures. */\n captureAuthorization,\n\n /** The connected model presents notifications in firmware. */\n nativeNotifications: nativeNotificationsSupported,\n /** Popup durations the firmware accepts (seconds, 0 = its default); empty when any value goes. */\n popupSecondsOptions: nativeNotificationPopupSeconds,\n\n /**\n * Who presents the next phone notification. Hosts pass whether their own\n * surface runs and draw only when the answer is `host`.\n */\n presentationOwner: currentPresentationOwner,\n /** Hand a captured notification to firmware that presents uploaded content (owner `firmware`, Android). */\n uploadToGlasses: (event: PhoneNotificationEvent): Promise<void> => uploadPhoneNotification(event),\n\n /** The driver's view of its notification surface. */\n glassesStatus: (): Promise<GlassesNotificationStatus> => BluetoothSdk.getGlassesNotificationStatus(),\n onGlassesStatus: (listener: (status: GlassesNotificationStatus) => void): (() => void) => {\n const subscription = BluetoothSdk.addListener(\"glasses_notification_status\", listener)\n return () => subscription.remove()\n },\n /** Upload outcomes by id; content never travels back. */\n onUploadResult: (listener: (result: NotificationUploadResult) => void): (() => void) => {\n const subscription = BluetoothSdk.addListener(\"notification_upload_result\", listener)\n return () => subscription.remove()\n },\n}\n"]}
1
+ {"version":3,"file":"phoneNotifications.js","sourceRoot":"","sources":["../../src/facades/phoneNotifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAC,QAAQ,EAAC,MAAM,cAAc,CAAA;AACrC,OAAO,WAAW,MAAM,gBAAgB,CAAA;AAExC,OAAO,YAAY,MAAM,iCAAiC,CAAA;AAE1D,OAAO,EAAC,gBAAgB,EAAE,QAAQ,EAAC,MAAM,oBAAoB,CAAA;AAC7D,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,yBAAyB,EACzB,8BAA8B,EAC9B,4BAA4B,EAC5B,uBAAuB,GACxB,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EAAC,qBAAqB,EAAgC,MAAM,gDAAgD,CAAA;AAInH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC;;;;OAIG;IACH,aAAa,EAAE,yBAAyB;IAExC,wFAAwF;IACxF,SAAS,EAAE,GAAa,EAAE;QACxB,MAAM,CAAC,GAAG,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAA;QACtF,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAClC,CAAC;IACD,qCAAqC;IACrC,YAAY,EAAE,CAAC,YAAsB,EAAE,EAAE,CACvC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,uBAAuB,CAAC,GAAG,EAAE,YAAY,CAAC;IAE5F,qFAAqF;IACrF,qBAAqB,EAAE,GAAqB,EAAE;QAC5C,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAC5D,OAAO,WAAW,CAAC,iCAAiC,EAAE,CAAA;IACxD,CAAC;IACD,yFAAyF;IACzF,yBAAyB,EAAE,GAAG,EAAE;QAC9B,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS;YAAE,OAAM;QACrC,OAAO,WAAW,CAAC,gCAAgC,EAAE,CAAA;IACvD,CAAC;IAED,qGAAqG;IACrG,oBAAoB;IAEpB,8DAA8D;IAC9D,mBAAmB,EAAE,4BAA4B;IACjD,kGAAkG;IAClG,mBAAmB,EAAE,8BAA8B;IAEnD;;;OAGG;IACH,iBAAiB,EAAE,wBAAwB;IAC3C;;;OAGG;IACH,qBAAqB,EAAE,CAAC,QAAmD,EAAgB,EAAE,CAC3F,qBAAqB,CAAC,QAAQ,CAAC;IAEjC,2GAA2G;IAC3G,eAAe,EAAE,CAAC,KAA6B,EAAiB,EAAE,CAAC,uBAAuB,CAAC,KAAK,CAAC;IAEjG,qDAAqD;IACrD,aAAa,EAAE,GAAuC,EAAE,CAAC,YAAY,CAAC,4BAA4B,EAAE;IACpG,eAAe,EAAE,CAAC,QAAqD,EAAgB,EAAE;QACvF,MAAM,YAAY,GAAG,YAAY,CAAC,WAAW,CAAC,6BAA6B,EAAE,QAAQ,CAAC,CAAA;QACtF,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAA;IACpC,CAAC;IACD,yDAAyD;IACzD,cAAc,EAAE,CAAC,QAAoD,EAAgB,EAAE;QACrF,MAAM,YAAY,GAAG,YAAY,CAAC,WAAW,CAAC,4BAA4B,EAAE,QAAQ,CAAC,CAAA;QACrF,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAA;IACpC,CAAC;CACF,CAAA","sourcesContent":["/**\n * phoneNotifications facade — `engine.phoneNotifications`: phone notifications\n * on the glasses, with a per-app blocklist and one presentation owner.\n *\n * Capture is the phone's (Android listener) or the glasses' (iOS, reading the\n * phone's stream) business and is never gated here. Presentation is decided\n * by `presentationOwner`: the engine's viewer on Glassly CFW glasses, the\n * firmware on glasses with their own notification centre, else the host's\n * card while its surface (Notify) runs. The four display settings drive\n * firmware and viewer alike; PhoneNotificationsSync pushes them.\n */\nimport {Platform} from \"react-native\"\nimport CrustModule from \"@glassly/crust\"\nimport type {PhoneNotificationEvent} from \"@glassly/crust\"\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport type {GlassesNotificationStatus, NotificationUploadResult} from \"@glassly/bluetooth-sdk\"\nimport {useSettingsStore, SETTINGS} from \"../stores/settings\"\nimport {\n captureAuthorization,\n currentPresentationOwner,\n installedNotificationApps,\n nativeNotificationPopupSeconds,\n nativeNotificationsSupported,\n uploadPhoneNotification,\n} from \"../services/PhoneNotificationsSync\"\nimport {onMiniappNotification, type MiniappNotificationEvent} from \"../services/notifications/miniappNotifications\"\n\nexport type {MiniappNotificationEvent} from \"../services/notifications/miniappNotifications\"\n\nexport const phoneNotifications = {\n /**\n * Apps to show in the notification filter UI (package/bundle id, name, icon).\n * Android: installed apps. iOS: seeded catalog ∪ glasses-reported apps\n * (icons unavailable — iOS offers no cross-app icon lookup).\n */\n installedApps: installedNotificationApps,\n\n /** The per-app blocklist (package/bundle ids whose notifications are NOT forwarded). */\n blocklist: (): string[] => {\n const b = useSettingsStore.getState().getSetting(SETTINGS.notifications_blocklist.key)\n return Array.isArray(b) ? b : []\n },\n /** Replace the per-app blocklist. */\n setBlocklist: (packageNames: string[]) =>\n useSettingsStore.getState().setSetting(SETTINGS.notifications_blocklist.key, packageNames),\n\n /** Does the app have the Android notification-listener permission? (false on iOS) */\n hasListenerPermission: (): Promise<boolean> => {\n if (Platform.OS !== \"android\") return Promise.resolve(false)\n return CrustModule.hasNotificationListenerPermission()\n },\n /** Open the OS settings to grant the notification-listener permission. (no-op on iOS) */\n requestListenerPermission: () => {\n if (Platform.OS !== \"android\") return\n return CrustModule.openNotificationListenerSettings()\n },\n\n /** Whether the glasses may read the phone's notifications; `not_needed` where the phone captures. */\n captureAuthorization,\n\n /** The connected model presents notifications in firmware. */\n nativeNotifications: nativeNotificationsSupported,\n /** Popup durations the firmware accepts (seconds, 0 = its default); empty when any value goes. */\n popupSecondsOptions: nativeNotificationPopupSeconds,\n\n /**\n * Who presents the next phone notification. Hosts pass whether their own\n * surface runs and draw only when the answer is `host`.\n */\n presentationOwner: currentPresentationOwner,\n /**\n * Notifications miniapps post and dismiss. Hosts feed them to the same\n * fan-out as the phone's, marked `system: false` with `source` set.\n */\n onMiniappNotification: (listener: (event: MiniappNotificationEvent) => void): (() => void) =>\n onMiniappNotification(listener),\n\n /** Hand a captured notification to firmware that presents uploaded content (owner `firmware`, Android). */\n uploadToGlasses: (event: PhoneNotificationEvent): Promise<void> => uploadPhoneNotification(event),\n\n /** The driver's view of its notification surface. */\n glassesStatus: (): Promise<GlassesNotificationStatus> => BluetoothSdk.getGlassesNotificationStatus(),\n onGlassesStatus: (listener: (status: GlassesNotificationStatus) => void): (() => void) => {\n const subscription = BluetoothSdk.addListener(\"glasses_notification_status\", listener)\n return () => subscription.remove()\n },\n /** Upload outcomes by id; content never travels back. */\n onUploadResult: (listener: (result: NotificationUploadResult) => void): (() => void) => {\n const subscription = BluetoothSdk.addListener(\"notification_upload_result\", listener)\n return () => subscription.remove()\n },\n}\n"]}
@@ -1,9 +1,9 @@
1
1
  export const ENGINE_RELEASE_METADATA = Object.freeze({
2
2
  "schemaVersion": 1,
3
3
  "familyBaseVersion": "0.4.0",
4
- "releaseIdentity": "0.4.0-beta.1052",
5
- "releaseSetId": "glassly-0.4.0-beta.1052",
6
- "sourceCommit": "0e343b6f2c083cb6e4ce58f4fa533cf84cae4760",
4
+ "releaseIdentity": "0.4.0-beta.1076",
5
+ "releaseSetId": "glassly-0.4.0-beta.1076",
6
+ "sourceCommit": "3021c69f679562e3de8a57d76c806d1c8173c22a",
7
7
  "otaManifestUrl": null,
8
8
  "otaManifestSha256": null
9
9
  });
@@ -1 +1 @@
1
- {"version":3,"file":"releaseMetadata.js","sourceRoot":"","sources":["../../src/generated/releaseMetadata.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,uBAAuB,GAAoC,MAAM,CAAC,MAAM,CAAC;IACpF,eAAe,EAAE,CAAC;IAClB,mBAAmB,EAAE,OAAO;IAC5B,iBAAiB,EAAE,iBAAiB;IACpC,cAAc,EAAE,yBAAyB;IACzC,cAAc,EAAE,0CAA0C;IAC1D,gBAAgB,EAAE,IAAI;IACtB,mBAAmB,EAAE,IAAI;CAC1B,CAAC,CAAA","sourcesContent":["/** Generated by release CI. Do not edit in a release checkout. */\nexport interface EngineReleaseMetadata {\n schemaVersion: 1\n familyBaseVersion: string | null\n releaseIdentity: string | null\n releaseSetId: string | null\n sourceCommit: string | null\n otaManifestUrl: string | null\n otaManifestSha256: string | null\n}\n\nexport const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({\n \"schemaVersion\": 1,\n \"familyBaseVersion\": \"0.4.0\",\n \"releaseIdentity\": \"0.4.0-beta.1052\",\n \"releaseSetId\": \"glassly-0.4.0-beta.1052\",\n \"sourceCommit\": \"0e343b6f2c083cb6e4ce58f4fa533cf84cae4760\",\n \"otaManifestUrl\": null,\n \"otaManifestSha256\": null\n})\n"]}
1
+ {"version":3,"file":"releaseMetadata.js","sourceRoot":"","sources":["../../src/generated/releaseMetadata.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,uBAAuB,GAAoC,MAAM,CAAC,MAAM,CAAC;IACpF,eAAe,EAAE,CAAC;IAClB,mBAAmB,EAAE,OAAO;IAC5B,iBAAiB,EAAE,iBAAiB;IACpC,cAAc,EAAE,yBAAyB;IACzC,cAAc,EAAE,0CAA0C;IAC1D,gBAAgB,EAAE,IAAI;IACtB,mBAAmB,EAAE,IAAI;CAC1B,CAAC,CAAA","sourcesContent":["/** Generated by release CI. Do not edit in a release checkout. */\nexport interface EngineReleaseMetadata {\n schemaVersion: 1\n familyBaseVersion: string | null\n releaseIdentity: string | null\n releaseSetId: string | null\n sourceCommit: string | null\n otaManifestUrl: string | null\n otaManifestSha256: string | null\n}\n\nexport const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({\n \"schemaVersion\": 1,\n \"familyBaseVersion\": \"0.4.0\",\n \"releaseIdentity\": \"0.4.0-beta.1076\",\n \"releaseSetId\": \"glassly-0.4.0-beta.1076\",\n \"sourceCommit\": \"3021c69f679562e3de8a57d76c806d1c8173c22a\",\n \"otaManifestUrl\": null,\n \"otaManifestSha256\": null\n})\n"]}
package/build/index.d.ts CHANGED
@@ -13,6 +13,7 @@ export { engine } from "./engine";
13
13
  export type { ReportAttachmentInput, ReportContext, ReportDetails, ReportStatus, ReportTrigger, ReportSubmitResult, EngineSubmitReportInput, } from "./facades/reports";
14
14
  export type { IslandNotification, IslandNotificationKind } from "./facades/notifications";
15
15
  export type { PresentationOwner } from "./services/notifications/notificationPolicy";
16
+ export type { MiniappNotificationEvent } from "./services/notifications/miniappNotifications";
16
17
  export { DEFAULT_HIDDEN_PACKAGES, isGatedByDevTools, isSystemMiniapp } from "./stores/appVisibility";
17
18
  export type { WifiSearchResult } from "./facades/glassesWifi";
18
19
  export type { IdentitySnapshot } from "./services/PairingIdentity";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `@glassly/engine` — the OEM-facing main entry.\n *\n * The `engine` namespace (configure/start/stop + typed domain facades), the\n * public contract/read-model types, and the pure helpers host UI legitimately\n * renders with (decision functions, sort/order helpers, policy constants,\n * capability tables, timers). Judgment rule: read models, commands, pure\n * functions and types belong here; anything that mutates runtime state or\n * exposes a raw store/service remains private to the Glassly host.\n * See cloud/docs/issues/020-glasses-status-boundary/integration-review.md §D.\n */\n\n// The namespaced OEM-facing engine API (the \"(A) host API\"). See ./engine.\nexport {engine} from \"./engine\"\nexport type {\n ReportAttachmentInput,\n ReportContext,\n ReportDetails,\n ReportStatus,\n ReportTrigger,\n ReportSubmitResult,\n EngineSubmitReportInput,\n} from \"./facades/reports\"\nexport type {IslandNotification, IslandNotificationKind} from \"./facades/notifications\"\nexport type {PresentationOwner} from \"./services/notifications/notificationPolicy\"\nexport {DEFAULT_HIDDEN_PACKAGES, isGatedByDevTools, isSystemMiniapp} from \"./stores/appVisibility\"\nexport type {WifiSearchResult} from \"./facades/glassesWifi\"\nexport type {IdentitySnapshot} from \"./services/PairingIdentity\"\nexport type {DisplayMirrorEvent} from \"./facades/displayMirror\"\nexport type {\n IslandConfigureOptions,\n IslandAuth,\n IslandConfigValues,\n IslandAnalytics,\n IslandUiSeams,\n ScanQrOptions,\n ScanQrResult,\n WebLoginOptions,\n WebLoginResult,\n SubjectTokenType,\n} from \"./runtime/bootstrap\"\n\n// Settings contract: the typed key registry (schema descriptors — the same\n// surface engine.settings.descriptor()/keys() reads), the per-key React hook\n// (the hook layer, same precedent as the apps hooks below), and the pure\n// device-model key helpers. The raw useSettingsStore stays internal;\n// imperative access goes through engine.settings.\nexport {SETTINGS, useSetting, AI_DATA_CONSENT_VERSION} from \"./stores/settings\"\nexport {isCfwFirmwareVersion, isCustomDashboardEligible} from \"./services/pages/pageEligibility\"\nexport {getEffectiveCapabilities} from \"./services/effectiveCapabilities\"\nexport {isControllerModel, isControllerReady} from \"./services/controllers\"\n\n// AI tier registry: the curated per-tier model dropdown options and helpers\n// the Settings > AI Models screen renders. Resolution itself runs inside\n// LocalMiniappRuntime; the screen only reads/writes the ai_model_* settings.\nexport {AI_TIERS, TIER_MODEL_OPTIONS, parseTierSetting} from \"./services/AiTierResolution\"\nexport type {AiTier, AiTierProvider, TierModelOption} from \"./services/AiTierResolution\"\n// On-device LLM: the model catalog and download status the same screen\n// renders for the phone-side model (engine.ai.local).\nexport type {\n LocalLlmDownloadStage,\n LocalLlmDownloadStatus,\n LocalLlmModelConfig,\n LocalLlmModelId,\n} from \"./services/LocalLlmModelManager\"\nexport {DEFAULT_LOCAL_LLM_MODEL, isLocalLlmModelId} from \"./services/LocalLlmModelManager\"\nexport type {\n OfflineActivity,\n OfflineActivityReason,\n OfflineLlmActivity,\n OfflineTranscriptionActivity,\n OfflineTranslationActivity,\n OfflineTranslationPair,\n} from \"./services/OfflineActivity\"\n\n// Shared user memory timeline (engine.memory / Settings > Memory). Entry and\n// session shapes are canonical in @glassly/miniapp (the session.memory\n// surface); the stats read model is engine-side.\nexport type {MemoryStats} from \"./services/MemoryStore\"\nexport type {AppStateExportResult, AppStateRestoreOptions, AppStateRestoreResult} from \"./services/appStateBackupFile\"\nexport type {SpeakerProfile} from \"./services/SpeakerProfileStore\"\nexport type {EnrollOutcome} from \"./facades/speakers\"\nexport {MENTRA_LIVE_SETTING_KEYS, getBluetoothSettingKeysForDevice} from \"./stores/bluetoothSettingKeys\"\n\n// Runtime-shared constants and contract DTOs.\nexport {ISLAND_SETTINGS_KEYS} from \"./runtime/config\"\nexport type {CloudClientStatusSnapshot, MiniappAuthToken, InteropAuditEvent, TtsSynthesisResult} from \"./runtime/config\"\n\n// Pure readiness predicates over glasses connection state.\nexport {\n isGlassesConnected,\n isGlassesReady,\n isGlassesLinkLayerBusy,\n waitForGlassesReady,\n type GlassesConnectionStatus,\n type WaitForGlassesReadyOptions,\n} from \"./services/GlassesReadiness\"\n// Pure connect/reconnect decision helpers (host UI renders the outcome).\nexport {\n decideReconnect,\n decideConnectButtonAction,\n type ReconnectDecision,\n type ReconnectDecisionInput,\n type ConnectButtonAction,\n} from \"./services/ConnectionCoordinator\"\n\n// OTA read-model types for host OTA UI (progress screen, error mapping,\n// progress section) — the check/install machinery itself is internal.\nexport type {\n VersionInfo,\n MtkPatch,\n BesFirmware,\n VersionJson,\n OtaCheckResult,\n OtaCheckCurrentGlassesResult,\n OtaCheckCurrentGlassesOptions,\n} from \"./services/OtaUpdateCheckService\"\n// OTA install policy (watchdog timings + failure copy) + display-state\n// derivation, consumed by the OTA screens and their tests.\nexport {\n MINIMUM_OTA_STATUS_BUILD,\n MAX_RETRIES,\n RETRY_INTERVAL_MS,\n PROGRESS_TIMEOUT_MS,\n DOWNLOAD_STUCK_TIMEOUT_MS,\n MTK_INSTALL_TIMEOUT_MS,\n GLOBAL_OTA_TIMEOUT_MS,\n PING_INTERVAL_MS,\n QUERY_REPLY_TIMEOUT_MS,\n BES_RESTART_TIMEOUT_MS,\n OtaProgressMessages,\n} from \"./services/otaInstallPolicy\"\nexport {deriveDisplayState} from \"./services/otaDisplayState\"\nexport type {DisplayState} from \"./services/otaDisplayState\"\nexport type {\n OtaProgress,\n OtaProgressStatus,\n OtaStatus,\n OtaUpdateInfo,\n ReleaseChangelog,\n OtaSnapshot,\n OtaInstallSnapshot,\n} from \"./facades/ota\"\nexport {\n beginOtaAutoChain,\n clearOtaAutoChainReconnectWait,\n isOtaAutoChainActive,\n otaAutoChainFingerprint,\n otaAutoChainReconnectWaitRemaining,\n stopOtaAutoChain,\n tryAdvanceOtaAutoChain,\n MAX_OTA_AUTO_CHAIN_PASSES,\n OTA_AUTO_CHAIN_RECONNECT_TIMEOUT_MS,\n} from \"./services/OtaAutoChain\"\nexport type {OtaAutoChainAdvanceResult} from \"./services/OtaAutoChain\"\nexport {\n BES_INSTALL_RESTART_MESSAGE,\n getOtaErrorMessage,\n shouldRequireGlassesRebootForBesFailure,\n shouldShowChangeWifiForOtaDownloadFailure,\n} from \"./services/OtaErrorMapping\"\n\n// Gallery read models: engine.gallery.onNotice payload types, the media\n// permission helper + display-name derivation host gallery UI uses, and the\n// glasses-camera DTO types (re-exported through the host @/types/asg shim).\nexport type {GalleryNotice, GalleryNoticeCode} from \"./services/asg/galleryNotices\"\nexport {MediaLibraryPermissions} from \"./utils/permissions/MediaLibraryPermissions\"\nexport {deriveGalleryDisplayName} from \"./utils/permissions/galleryDisplayName\"\nexport type {\n PhotoInfo,\n CaptureFile,\n CaptureGroup,\n GalleryResponse,\n ServerStatus,\n HealthResponse,\n GalleryEvent,\n} from \"./types/asg\"\n\n// Bluetooth SDK event types host UI subscribes to via engine facades (the\n// BluetoothSdk singleton passthrough itself is internal).\nexport type {PairFailureEvent, GlassesNotReadyEvent, PairedController, ControllerStatus} from \"@glassly/bluetooth-sdk\"\n\n// Cloud connection status enum (read model; the connection store is internal).\nexport {WebSocketStatus} from \"./stores/connection\"\n\n// App-list hook layer + pure list helpers (the raw useAppStatusStore and\n// installAppStoreHooks wiring are internal).\nexport {\n DUMMY_APPLET,\n saveAppsOrder,\n getAppsOrder,\n sortAppsByPackageNamePriority,\n saveLastOpenTime,\n getLastOpenTime,\n sortAppsByLastOpenTime,\n useApps,\n useStart,\n useStop,\n useSetForeground,\n useClearForeground,\n useRefresh,\n useStopAll,\n useInstall,\n useUninstall,\n useActiveApps,\n useRunningAlwaysOnApps,\n useWidgetApps,\n useActiveBackgroundApps,\n useBackgroundApps,\n useActiveForegroundApp,\n useForegroundApp,\n useActiveBackgroundAppsCount,\n useLocalMiniApps,\n type StartOptions,\n type OrderMap,\n} from \"./stores/apps\"\n\n// Pure dev-miniapp launch-route decision (registration itself is internal).\nexport {\n decideDevLaunchRoute,\n type DecideDevLaunchOptions,\n type DevLaunchResult,\n type DevManifest,\n} from \"./utils/devMiniappLaunch\"\nexport {HardwareCompatibility, type CompatibilityResult} from \"./utils/hardware\"\nexport {BgTimer} from \"./utils/timers\"\n// Meta Neural Band: the account sign-in a claim needs (the WebView lives in the host).\nexport {\n MetaAuthError,\n authEntryUrl,\n callbackMatches,\n callbackQuery,\n decryptBlob,\n isLoginCallback,\n login,\n tokensQuery,\n type MetaSession,\n type MetaSsoTokens,\n} from \"./services/neuralBand/MetaAuth\"\nexport type {\n NeuralBandClaimStatus,\n NeuralBandFirmwareStatus,\n NeuralBandHandwritingStatus,\n NeuralBandHandwritingUpdate,\n} from \"./services/neuralBand/NeuralBandInput\"\n\n// Hardware types and capability profiles.\nexport {\n HardwareType,\n HardwareRequirementLevel,\n DeviceTypes,\n ControllerTypes,\n HARDWARE_CAPABILITIES,\n getModelCapabilities,\n simulatedGlasses,\n evenRealitiesG1,\n evenRealitiesG2,\n mentraLive,\n nimo,\n rayneoIO,\n vuzixZ100,\n mentraDisplay,\n} from \"./types\"\nexport type {\n HardwareRequirement,\n CameraCapabilities,\n DisplayCapabilities,\n MicrophoneCapabilities,\n SpeakerCapabilities,\n IMUCapabilities,\n ButtonCapabilities,\n LightCapabilities,\n PowerCapabilities,\n Capabilities,\n AppletType,\n AppPermissionType,\n AppletPermission,\n AppletInterface,\n ClientApp,\n} from \"./types\"\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `@glassly/engine` — the OEM-facing main entry.\n *\n * The `engine` namespace (configure/start/stop + typed domain facades), the\n * public contract/read-model types, and the pure helpers host UI legitimately\n * renders with (decision functions, sort/order helpers, policy constants,\n * capability tables, timers). Judgment rule: read models, commands, pure\n * functions and types belong here; anything that mutates runtime state or\n * exposes a raw store/service remains private to the Glassly host.\n * See cloud/docs/issues/020-glasses-status-boundary/integration-review.md §D.\n */\n\n// The namespaced OEM-facing engine API (the \"(A) host API\"). See ./engine.\nexport {engine} from \"./engine\"\nexport type {\n ReportAttachmentInput,\n ReportContext,\n ReportDetails,\n ReportStatus,\n ReportTrigger,\n ReportSubmitResult,\n EngineSubmitReportInput,\n} from \"./facades/reports\"\nexport type {IslandNotification, IslandNotificationKind} from \"./facades/notifications\"\nexport type {PresentationOwner} from \"./services/notifications/notificationPolicy\"\nexport type {MiniappNotificationEvent} from \"./services/notifications/miniappNotifications\"\nexport {DEFAULT_HIDDEN_PACKAGES, isGatedByDevTools, isSystemMiniapp} from \"./stores/appVisibility\"\nexport type {WifiSearchResult} from \"./facades/glassesWifi\"\nexport type {IdentitySnapshot} from \"./services/PairingIdentity\"\nexport type {DisplayMirrorEvent} from \"./facades/displayMirror\"\nexport type {\n IslandConfigureOptions,\n IslandAuth,\n IslandConfigValues,\n IslandAnalytics,\n IslandUiSeams,\n ScanQrOptions,\n ScanQrResult,\n WebLoginOptions,\n WebLoginResult,\n SubjectTokenType,\n} from \"./runtime/bootstrap\"\n\n// Settings contract: the typed key registry (schema descriptors — the same\n// surface engine.settings.descriptor()/keys() reads), the per-key React hook\n// (the hook layer, same precedent as the apps hooks below), and the pure\n// device-model key helpers. The raw useSettingsStore stays internal;\n// imperative access goes through engine.settings.\nexport {SETTINGS, useSetting, AI_DATA_CONSENT_VERSION} from \"./stores/settings\"\nexport {isCfwFirmwareVersion, isCustomDashboardEligible} from \"./services/pages/pageEligibility\"\nexport {getEffectiveCapabilities} from \"./services/effectiveCapabilities\"\nexport {isControllerModel, isControllerReady} from \"./services/controllers\"\n\n// AI tier registry: the curated per-tier model dropdown options and helpers\n// the Settings > AI Models screen renders. Resolution itself runs inside\n// LocalMiniappRuntime; the screen only reads/writes the ai_model_* settings.\nexport {AI_TIERS, TIER_MODEL_OPTIONS, parseTierSetting} from \"./services/AiTierResolution\"\nexport type {AiTier, AiTierProvider, TierModelOption} from \"./services/AiTierResolution\"\n// On-device LLM: the model catalog and download status the same screen\n// renders for the phone-side model (engine.ai.local).\nexport type {\n LocalLlmDownloadStage,\n LocalLlmDownloadStatus,\n LocalLlmModelConfig,\n LocalLlmModelId,\n} from \"./services/LocalLlmModelManager\"\nexport {DEFAULT_LOCAL_LLM_MODEL, isLocalLlmModelId} from \"./services/LocalLlmModelManager\"\nexport type {\n OfflineActivity,\n OfflineActivityReason,\n OfflineLlmActivity,\n OfflineTranscriptionActivity,\n OfflineTranslationActivity,\n OfflineTranslationPair,\n} from \"./services/OfflineActivity\"\n\n// Shared user memory timeline (engine.memory / Settings > Memory). Entry and\n// session shapes are canonical in @glassly/miniapp (the session.memory\n// surface); the stats read model is engine-side.\nexport type {MemoryStats} from \"./services/MemoryStore\"\nexport type {AppStateExportResult, AppStateRestoreOptions, AppStateRestoreResult} from \"./services/appStateBackupFile\"\nexport type {SpeakerProfile} from \"./services/SpeakerProfileStore\"\nexport type {EnrollOutcome} from \"./facades/speakers\"\nexport {MENTRA_LIVE_SETTING_KEYS, getBluetoothSettingKeysForDevice} from \"./stores/bluetoothSettingKeys\"\n\n// Runtime-shared constants and contract DTOs.\nexport {ISLAND_SETTINGS_KEYS} from \"./runtime/config\"\nexport type {CloudClientStatusSnapshot, MiniappAuthToken, InteropAuditEvent, TtsSynthesisResult} from \"./runtime/config\"\n\n// Pure readiness predicates over glasses connection state.\nexport {\n isGlassesConnected,\n isGlassesReady,\n isGlassesLinkLayerBusy,\n waitForGlassesReady,\n type GlassesConnectionStatus,\n type WaitForGlassesReadyOptions,\n} from \"./services/GlassesReadiness\"\n// Pure connect/reconnect decision helpers (host UI renders the outcome).\nexport {\n decideReconnect,\n decideConnectButtonAction,\n type ReconnectDecision,\n type ReconnectDecisionInput,\n type ConnectButtonAction,\n} from \"./services/ConnectionCoordinator\"\n\n// OTA read-model types for host OTA UI (progress screen, error mapping,\n// progress section) — the check/install machinery itself is internal.\nexport type {\n VersionInfo,\n MtkPatch,\n BesFirmware,\n VersionJson,\n OtaCheckResult,\n OtaCheckCurrentGlassesResult,\n OtaCheckCurrentGlassesOptions,\n} from \"./services/OtaUpdateCheckService\"\n// OTA install policy (watchdog timings + failure copy) + display-state\n// derivation, consumed by the OTA screens and their tests.\nexport {\n MINIMUM_OTA_STATUS_BUILD,\n MAX_RETRIES,\n RETRY_INTERVAL_MS,\n PROGRESS_TIMEOUT_MS,\n DOWNLOAD_STUCK_TIMEOUT_MS,\n MTK_INSTALL_TIMEOUT_MS,\n GLOBAL_OTA_TIMEOUT_MS,\n PING_INTERVAL_MS,\n QUERY_REPLY_TIMEOUT_MS,\n BES_RESTART_TIMEOUT_MS,\n OtaProgressMessages,\n} from \"./services/otaInstallPolicy\"\nexport {deriveDisplayState} from \"./services/otaDisplayState\"\nexport type {DisplayState} from \"./services/otaDisplayState\"\nexport type {\n OtaProgress,\n OtaProgressStatus,\n OtaStatus,\n OtaUpdateInfo,\n ReleaseChangelog,\n OtaSnapshot,\n OtaInstallSnapshot,\n} from \"./facades/ota\"\nexport {\n beginOtaAutoChain,\n clearOtaAutoChainReconnectWait,\n isOtaAutoChainActive,\n otaAutoChainFingerprint,\n otaAutoChainReconnectWaitRemaining,\n stopOtaAutoChain,\n tryAdvanceOtaAutoChain,\n MAX_OTA_AUTO_CHAIN_PASSES,\n OTA_AUTO_CHAIN_RECONNECT_TIMEOUT_MS,\n} from \"./services/OtaAutoChain\"\nexport type {OtaAutoChainAdvanceResult} from \"./services/OtaAutoChain\"\nexport {\n BES_INSTALL_RESTART_MESSAGE,\n getOtaErrorMessage,\n shouldRequireGlassesRebootForBesFailure,\n shouldShowChangeWifiForOtaDownloadFailure,\n} from \"./services/OtaErrorMapping\"\n\n// Gallery read models: engine.gallery.onNotice payload types, the media\n// permission helper + display-name derivation host gallery UI uses, and the\n// glasses-camera DTO types (re-exported through the host @/types/asg shim).\nexport type {GalleryNotice, GalleryNoticeCode} from \"./services/asg/galleryNotices\"\nexport {MediaLibraryPermissions} from \"./utils/permissions/MediaLibraryPermissions\"\nexport {deriveGalleryDisplayName} from \"./utils/permissions/galleryDisplayName\"\nexport type {\n PhotoInfo,\n CaptureFile,\n CaptureGroup,\n GalleryResponse,\n ServerStatus,\n HealthResponse,\n GalleryEvent,\n} from \"./types/asg\"\n\n// Bluetooth SDK event types host UI subscribes to via engine facades (the\n// BluetoothSdk singleton passthrough itself is internal).\nexport type {PairFailureEvent, GlassesNotReadyEvent, PairedController, ControllerStatus} from \"@glassly/bluetooth-sdk\"\n\n// Cloud connection status enum (read model; the connection store is internal).\nexport {WebSocketStatus} from \"./stores/connection\"\n\n// App-list hook layer + pure list helpers (the raw useAppStatusStore and\n// installAppStoreHooks wiring are internal).\nexport {\n DUMMY_APPLET,\n saveAppsOrder,\n getAppsOrder,\n sortAppsByPackageNamePriority,\n saveLastOpenTime,\n getLastOpenTime,\n sortAppsByLastOpenTime,\n useApps,\n useStart,\n useStop,\n useSetForeground,\n useClearForeground,\n useRefresh,\n useStopAll,\n useInstall,\n useUninstall,\n useActiveApps,\n useRunningAlwaysOnApps,\n useWidgetApps,\n useActiveBackgroundApps,\n useBackgroundApps,\n useActiveForegroundApp,\n useForegroundApp,\n useActiveBackgroundAppsCount,\n useLocalMiniApps,\n type StartOptions,\n type OrderMap,\n} from \"./stores/apps\"\n\n// Pure dev-miniapp launch-route decision (registration itself is internal).\nexport {\n decideDevLaunchRoute,\n type DecideDevLaunchOptions,\n type DevLaunchResult,\n type DevManifest,\n} from \"./utils/devMiniappLaunch\"\nexport {HardwareCompatibility, type CompatibilityResult} from \"./utils/hardware\"\nexport {BgTimer} from \"./utils/timers\"\n// Meta Neural Band: the account sign-in a claim needs (the WebView lives in the host).\nexport {\n MetaAuthError,\n authEntryUrl,\n callbackMatches,\n callbackQuery,\n decryptBlob,\n isLoginCallback,\n login,\n tokensQuery,\n type MetaSession,\n type MetaSsoTokens,\n} from \"./services/neuralBand/MetaAuth\"\nexport type {\n NeuralBandClaimStatus,\n NeuralBandFirmwareStatus,\n NeuralBandHandwritingStatus,\n NeuralBandHandwritingUpdate,\n} from \"./services/neuralBand/NeuralBandInput\"\n\n// Hardware types and capability profiles.\nexport {\n HardwareType,\n HardwareRequirementLevel,\n DeviceTypes,\n ControllerTypes,\n HARDWARE_CAPABILITIES,\n getModelCapabilities,\n simulatedGlasses,\n evenRealitiesG1,\n evenRealitiesG2,\n mentraLive,\n nimo,\n rayneoIO,\n vuzixZ100,\n mentraDisplay,\n} from \"./types\"\nexport type {\n HardwareRequirement,\n CameraCapabilities,\n DisplayCapabilities,\n MicrophoneCapabilities,\n SpeakerCapabilities,\n IMUCapabilities,\n ButtonCapabilities,\n LightCapabilities,\n PowerCapabilities,\n Capabilities,\n AppletType,\n AppPermissionType,\n AppletPermission,\n AppletInterface,\n ClientApp,\n} from \"./types\"\n"]}
@@ -298,6 +298,8 @@ export class JSRouter {
298
298
  BgTimer.clearTimeout(pending);
299
299
  this.respawnTimers.delete(packageName);
300
300
  }
301
+ miniappRunningRegistry.remove(packageName);
302
+ this.runtime.releaseWidgetHost(packageName);
301
303
  await this.runtime.notifyWillDisconnect(packageName, "stopped");
302
304
  this.spawnCache.delete(packageName);
303
305
  this.crashController?.onKill(packageName);
@@ -305,8 +307,6 @@ export class JSRouter {
305
307
  // drop out of native nav mode (crash-respawns don't take this path).
306
308
  this.runtime.unregisterApp(packageName, { endNavigation: true });
307
309
  this.registered.delete(packageName);
308
- // JSContext torn down → miniapp is no longer "running".
309
- miniappRunningRegistry.remove(packageName);
310
310
  if (this.crust.jsKill) {
311
311
  try {
312
312
  await this.crust.jsKill(packageName);
@@ -1 +1 @@
1
- {"version":3,"file":"JSRouter.js","sourceRoot":"","sources":["../../src/services/JSRouter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview JSRouter — RN-side host that bridges the per-miniapp\n * JS contexts (iOS-JSC and Android-QuickJS via Zipline) into the existing\n * {@link LocalMiniappRuntime} handler set.\n *\n * Rather than re-implement the 33 dispatch arms inline, the router\n * consumes Crust's `js_message` Expo event and forwards its\n * `__bridge.send(raw)` payloads to {@link LocalMiniappRuntime.handleRawMessage}.\n * The SDK envelope shape (`{type: \"DISPLAY\", ...}` etc.) is unchanged from\n * the WebView path, so every existing handler runs verbatim. What changes\n * is the *transport*:\n *\n * - **Inbound** (background JS → host): `__dispatch(\"__bridge\", \"send\",\n * [rawJsonString])` → `js_message` event → router →\n * `LocalMiniappRuntime.handleRawMessage(packageName, raw)`.\n * - **Outbound** (host → background JS): every package registered with\n * the router gets a `sendMessage(raw)` fn that calls\n * `Crust.jsDispatchToJs(packageName, {kind: \"bridge\", raw})`.\n * The polyfill's `__deliver` recognises `kind === \"bridge\"` and calls\n * `__deliverBridgeRaw(raw)`, which routes into the SDK's\n * {@link DispatchTransport.onMessage} handler.\n *\n * Host-side handler bodies (display fan-out, mic state, transcription,\n * navigation, etc.) live untouched in `LocalMiniappRuntime.ts`.\n *\n * Cloud-message routing (`phone_stream_status`, `phone_managed_stream_status`)\n * goes straight through `LocalMiniappRuntime.handleCloudMessage` — nothing\n * for the router to do; the responses arrive inside an envelope whose\n * `sendMessage` was already registered via the same path here.\n *\n * The router also bridges native error / log / unhandled-rejection\n * events (`iface: \"__log\"`, `iface: \"__error\"`) into the standard\n * `console.*` + Sentry breadcrumb pipeline so miniapp telemetry is\n * visible without bringing up a separate sink.\n */\n\nimport type {EventSubscription} from \"expo-modules-core\"\n\nimport devServerBridge from \"./DevServerBridge\"\nimport type localMiniappRuntime from \"./LocalMiniappRuntime\"\nimport type {MiniappLaunchSource} from \"@glassly/miniapp\"\n\nimport type {InstalledMiniappManifest} from \"./LocalMiniappRuntime\"\nimport type {JSCrashController} from \"./JSCrashController\"\nimport {JSLogRingBuffer, JSLogThrottle, redactSecrets} from \"./JSLogPipeline\"\nimport {islandNotifications} from \"./NotificationsEmitter\"\nimport type {UIRouter} from \"./UIRouter\"\nimport {miniappRunningRegistry} from \"./MiniappRunningRegistry\"\n\nimport {BgTimer} from \"../utils/timers\"\n\n/** The runtime's runtime instance type — the singleton exported from\n * LocalMiniappRuntime.ts (the file's `export default` is the instance,\n * not the class).\n */\ntype LocalMiniappRuntime = typeof localMiniappRuntime\n\n/**\n * Minimal subset of the Crust native module the router uses. Keeping the\n * binding loose lets us mock the module in unit tests without bringing\n * the whole Expo module surface along.\n */\nexport interface JSCrustBinding {\n jsDispatchToJs(packageName: string, envelope: Record<string, unknown>): Promise<void> | void\n jsSetManifest(packageName: string, permissions: string[]): Promise<void> | void\n jsLoadPolyfillBundle?: () => string\n jsSpawn?: (packageName: string, polyfill: string, miniappJs: string) => Promise<boolean> | boolean\n jsKill?: (packageName: string) => Promise<void> | void\n jsAlivePackages?: () => string[]\n addListener: (event: string, handler: (payload: Record<string, unknown>) => void) => EventSubscription\n}\n\nexport interface OutboundMessagePayload {\n packageName: string\n iface: string\n method: string\n argsJson?: string\n args?: unknown[]\n reqId?: string\n // Implementation-internal: any extra fields the dispatcher attached on\n // .forwardToRn (e.g. payload metadata) are passed through verbatim.\n [extra: string]: unknown\n}\n\nexport type RouterLogger = {\n log: (message: string, payload?: unknown) => void\n warn: (message: string, payload?: unknown) => void\n error: (message: string, payload?: unknown) => void\n}\n\nconst defaultLogger: RouterLogger = {\n log: (m, p) => console.log(`[JSRouter] ${m}`, p ?? \"\"),\n\n warn: (m, p) => console.warn(`[JSRouter] ${m}`, p ?? \"\"),\n\n error: (m, p) => console.error(`[JSRouter] ${m}`, p ?? \"\"),\n}\n\ninterface SpawnCache {\n miniappJs: string\n permissions: string[]\n installedManifest?: InstalledMiniappManifest\n launchSource?: MiniappLaunchSource\n}\n\nexport class JSRouter {\n private subscription: EventSubscription | null = null\n private readonly registered: Set<string> = new Set()\n /** Cached spawn arguments so the crash controller can respawn after a backoff. */\n private readonly spawnCache: Map<string, SpawnCache> = new Map()\n /** Active respawn timers (so unregister() can cancel a pending respawn). */\n private readonly respawnTimers: Map<string, number> = new Map()\n\n /**\n * Optional crash controller. When wired, every `__error` frame from a\n * JSContext drives the state machine; an Outcome with\n * scheduleRespawnAfterMs queues a setTimeout that re-spawns the\n * miniapp's last-known JS source after the backoff delay.\n */\n crashController: JSCrashController | null = null\n\n /** Hook called when a package transitions to CRASHLOOP_DISABLED. */\n onCrashloop: ((packageName: string, reason: string) => void) | null = null\n /** Hook called on the 2nd-within-window crash (toast UX). */\n onRestartToast: ((packageName: string, reason: string) => void) | null = null\n\n /**\n * Logging plumbing. Every `__log` frame passes through `redactSecrets`\n * (token/password/etc. scrubbed), then the throttle (100/min sustained\n * per pkg, 500 burst), then lands in the ring buffer + the host\n * logger. The ring buffer holds the last 200 lines/pkg so a crash\n * report can attach \"last words\" context.\n *\n * Replace with new instances in tests; production code uses the\n * defaults.\n */\n logThrottle: JSLogThrottle = new JSLogThrottle()\n logRing: JSLogRingBuffer = new JSLogRingBuffer()\n\n /**\n * Optional UI router — when wired, `__bridge.send` envelopes whose\n * inner payload type is `UI_SEND` get routed to the bound WebView\n * instead of through LocalMiniappRuntime. Two-layer miniapps set\n * this; legacy single-bundle WebView miniapps don't and the bridge\n * frames pass through unchanged.\n */\n uiRouter: UIRouter | null = null\n\n /** Teardowns in progress, so a stop and a racing start or stop see the same one. */\n private readonly unregistering = new Map<string, Promise<void>>()\n\n constructor(\n private readonly runtime: LocalMiniappRuntime,\n private readonly crust: JSCrustBinding,\n private readonly logger: RouterLogger = defaultLogger,\n ) {}\n\n /**\n * Subscribe to Crust's `js_message` event. Idempotent — calling\n * start() twice attaches a single listener.\n */\n start(): void {\n if (this.subscription) return\n this.subscription = this.crust.addListener(\"js_message\", (raw) => {\n try {\n this.handleOutbound(raw as unknown as OutboundMessagePayload)\n } catch (e) {\n this.logger.error(`outbound handler threw`, {error: String(e), raw})\n }\n })\n // A background script unregistered for missing liveness pings is dead\n // weight: its subscriptions are gone (so the mic releases) while the\n // webview keeps rendering stale state. Route it through the same\n // respawn machinery as a crash so it comes back automatically, with\n // the crash controller's backoff + crash-loop protection.\n this.runtime.onLivenessTimeout = (packageName) => {\n this.handleCrash(packageName, \"liveness: missed pings\")\n }\n }\n\n /**\n * Detach the Crust subscription. The router can be restarted later\n * with start(); registrations survive (the runtime's app map is the\n * source of truth).\n */\n stop(): void {\n this.subscription?.remove()\n this.subscription = null\n this.runtime.onLivenessTimeout = null\n }\n\n /**\n * Register a JSContext with the runtime so its handlers can fire\n * `sendMessage(raw)` against the right context. The router builds a\n * `sendMessage` that calls `Crust.jsDispatchToJs(packageName,\n * {kind: \"bridge\", raw})`; the polyfill's `__deliver` then hands the\n * envelope to `DispatchTransport.onMessage` inside the miniapp.\n *\n * Mirrors `MiniappHost.registerRuntime` on the WebView side. Callers\n * (e.g. {@link spawnAndRegister} below, or the host's miniapp launch\n * pipeline) should call this once per spawn.\n */\n registerApp(\n packageName: string,\n installedManifest?: InstalledMiniappManifest,\n launchSource?: MiniappLaunchSource,\n ): void {\n this.runtime.registerApp(\n packageName,\n (raw: string) => {\n this.dispatchBridgeRaw(packageName, raw)\n },\n installedManifest,\n launchSource,\n )\n this.registered.add(packageName)\n // JSContext is the source-of-truth for \"miniapp running\". The\n // home tile / tray reads this registry to project the `running`\n // flag — UI WebView open/close is separate.\n miniappRunningRegistry.add(packageName)\n }\n\n /**\n * Convenience: spawn a JSContext via Crust, register the app, and\n * set its declared permissions. Returns true on successful spawn.\n *\n * The host's miniapp launch path\n * (`mobile/src/services/miniapps/launchLocalMiniapp.ts`) calls this\n * once per JSContext mount.\n */\n async spawnAndRegister(\n packageName: string,\n miniappJs: string,\n options?: {\n permissions?: string[]\n installedManifest?: InstalledMiniappManifest\n launchSource?: MiniappLaunchSource\n },\n ): Promise<boolean> {\n if (!this.crust.jsSpawn) {\n this.logger.warn(\"jsSpawn not available — host binding missing native function\")\n return false\n }\n const polyfill = this.crust.jsLoadPolyfillBundle?.() ?? \"\"\n if (!polyfill) {\n this.logger.warn(`no polyfill bundle loaded for ${packageName}; spawn will likely fail`)\n }\n const ok = await this.crust.jsSpawn(packageName, polyfill, miniappJs)\n if (!ok) {\n this.logger.error(`spawn failed for ${packageName}`)\n return false\n }\n // Two distinct permission gates:\n // 1. Native dispatcher (JSContext → native bridge): `jsSetManifest`\n // checks per-call iface, e.g. __dispatch(\"mic\", \"start\", ...) requires\n // MICROPHONE.\n // 2. LocalMiniappRuntime (SUBSCRIBE envelope): `registerApp(...,\n // installedManifest)` carries the full manifest so SUBSCRIBE's gate\n // can match stream → permission against declared types.\n if (options?.permissions && options.permissions.length > 0) {\n await this.crust.jsSetManifest(packageName, options.permissions)\n }\n this.registerApp(packageName, options?.installedManifest, options?.launchSource)\n // Cache spawn arguments so the crash controller can respawn the\n // same code after a backoff. permissions + manifest are cached too\n // because the native side resets setManifest on every spawn and\n // LocalMiniappRuntime's installedManifest entry is keyed by\n // connect-time registration.\n this.spawnCache.set(packageName, {\n miniappJs,\n permissions: options?.permissions ?? [],\n installedManifest: options?.installedManifest,\n launchSource: options?.launchSource,\n })\n this.crashController?.onSpawn(packageName)\n\n // Fire the `init` envelope so the polyfill's __deliver handler\n // resolves `__initCallback(sessionId)`. The SDK's\n // `registerMiniapp(handler)` wires that callback to construct\n // MiniappSession and call the user's handler. Without this\n // dispatch the user's code never runs — `registerMiniapp` just\n // assigns to a global and waits.\n const sessionId = `${packageName}-${Date.now().toString(36)}`\n void this.crust.jsDispatchToJs(packageName, {kind: \"init\", sessionId})\n\n return true\n }\n\n /**\n * Crash-controller integration. Called from the `__error` frame\n * handler. The controller returns an outcome that tells us whether\n * to respawn (with delay) or leave the context dead.\n */\n private handleCrash(packageName: string, reason: string): void {\n // The native context is dead the instant a crash is observed — invalidate\n // its CONNECT handshake NOW so waitForConnect() blocks through the respawn\n // backoff window instead of resolving immediately against the dead context\n // (an action invoked mid-backoff would otherwise be delivered to nothing).\n this.runtime.resetHandshake(packageName)\n const controller = this.crashController\n if (!controller) return\n const cached = this.spawnCache.get(packageName)\n if (!cached) {\n this.logger.warn(`crash for ${packageName} but no cached spawn args — cannot respawn`)\n controller.onCrash(packageName, reason)\n return\n }\n const outcome = controller.onCrash(packageName, reason)\n if (outcome.surfaceCrashloopBanner) {\n this.onCrashloop?.(packageName, reason)\n islandNotifications.emit({kind: \"miniapp_crashloop\", packageName, reason, timestamp: Date.now()})\n return\n }\n if (outcome.showRestartToast) {\n this.onRestartToast?.(packageName, reason)\n }\n if (outcome.scheduleRespawnAfterMs == null) return\n // Cancel any prior pending respawn before scheduling a new one.\n const existing = this.respawnTimers.get(packageName)\n if (existing) BgTimer.clearTimeout(existing)\n const timer = BgTimer.setTimeout(() => {\n this.respawnTimers.delete(packageName)\n void (async () => {\n try {\n await this.crust.jsKill?.(packageName)\n } catch {\n /* native may have already torn down */\n }\n const ok = await this.crust.jsSpawn?.(packageName, this.crust.jsLoadPolyfillBundle?.() ?? \"\", cached.miniappJs)\n if (!ok) {\n this.logger.error(`crash respawn failed for ${packageName}`)\n return\n }\n if (cached.permissions.length > 0) {\n await this.crust.jsSetManifest(packageName, cached.permissions)\n }\n this.registerApp(packageName, cached.installedManifest, cached.launchSource)\n controller.onSpawn(packageName)\n // Re-fire the init envelope so the respawned context's\n // `registerMiniapp` handler runs again.\n const sessionId = `${packageName}-${Date.now().toString(36)}`\n void this.crust.jsDispatchToJs(packageName, {kind: \"init\", sessionId})\n this.logger.log(`respawned ${packageName} after crash`)\n })()\n }, outcome.scheduleRespawnAfterMs)\n this.respawnTimers.set(packageName, timer)\n }\n\n private summarizeReason(payload: unknown, method: string): string {\n if (payload && typeof payload === \"object\" && \"message\" in (payload as Record<string, unknown>)) {\n return `${method}: ${(payload as {message: string}).message}`\n }\n return method\n }\n\n /**\n * Tear down a JSContext and unregister from the runtime. The session's\n * `onBeforeDisconnect` handlers get a short grace window first, so a\n * miniapp can clear what it drew and end its own work while its messages\n * still reach the host. Concurrent calls share one teardown.\n */\n unregister(packageName: string): Promise<void> {\n if (!this.registered.has(packageName)) return Promise.resolve()\n const inFlight = this.unregistering.get(packageName)\n if (inFlight) return inFlight\n const teardown = this.teardown(packageName).finally(() => this.unregistering.delete(packageName))\n this.unregistering.set(packageName, teardown)\n return teardown\n }\n\n /** Resolves once an in-flight {@link unregister} of this package has finished. */\n async whenUnregistered(packageName: string): Promise<void> {\n await this.unregistering.get(packageName)\n }\n\n private async teardown(packageName: string): Promise<void> {\n // Cancel any pending crash-respawn before tearing down — we don't\n // want a stale timer to re-spawn a miniapp the user just disabled.\n const pending = this.respawnTimers.get(packageName)\n if (pending) {\n BgTimer.clearTimeout(pending)\n this.respawnTimers.delete(packageName)\n }\n await this.runtime.notifyWillDisconnect(packageName, \"stopped\")\n this.spawnCache.delete(packageName)\n this.crashController?.onKill(packageName)\n // User-initiated close/disable: end any active nav trip so the glasses\n // drop out of native nav mode (crash-respawns don't take this path).\n this.runtime.unregisterApp(packageName, {endNavigation: true})\n this.registered.delete(packageName)\n // JSContext torn down → miniapp is no longer \"running\".\n miniappRunningRegistry.remove(packageName)\n if (this.crust.jsKill) {\n try {\n await this.crust.jsKill(packageName)\n } catch (e) {\n this.logger.warn(`jsKill threw for ${packageName}: ${String(e)}`)\n }\n }\n }\n\n /** List packages the router has registered. */\n /** The user opened a running miniapp again; the source rides the next respawn too. */\n notifyLaunch(packageName: string, launchSource: MiniappLaunchSource): void {\n if (!this.registered.has(packageName)) return\n const cached = this.spawnCache.get(packageName)\n if (cached) cached.launchSource = launchSource\n this.runtime.sendLaunchChange(packageName, launchSource)\n }\n\n registeredPackages(): string[] {\n return Array.from(this.registered)\n }\n\n /**\n * Validate that a reused background JSContext is still responsive when its\n * WebView comes foreground. The runtime owns the ping/timeout mechanics; the\n * router gates this to registered packages and keeps LocalMiniappView from\n * reaching into runtime internals.\n */\n probeForegroundLiveness(packageName: string, reason = \"foreground-open\"): void {\n if (!this.registered.has(packageName)) return\n this.runtime.probeForegroundLiveness(packageName, reason)\n }\n\n // ----------------------------------------------------------------\n // Outbound message handling\n // ----------------------------------------------------------------\n\n private handleOutbound(msg: OutboundMessagePayload): void {\n const {packageName, iface, method} = msg\n if (!packageName || !iface || !method) {\n this.logger.warn(`bad js_message — missing fields`, msg)\n return\n }\n\n // 1) Bridge frames: the SDK's DispatchTransport.send(raw) lands here.\n // Forward raw envelope into LocalMiniappRuntime.handleRawMessage\n // so every existing handler arm runs verbatim.\n if (iface === \"__bridge\" && method === \"send\") {\n const raw = this.coerceArgsToBridgeRaw(msg)\n if (raw == null) {\n this.logger.warn(`__bridge.send had no raw payload`, msg)\n return\n }\n // If the payload is a UI_SEND envelope, route it to the bound\n // WebView instead of LocalMiniappRuntime.\n // session.ui.send → DispatchTransport.send → here.\n if (this.uiRouter) {\n const innerPayload = this.peekBridgePayloadType(raw)\n if (innerPayload?.type === \"UI_SEND\") {\n this.uiRouter.routeFromBackground(packageName, innerPayload)\n return\n }\n }\n this.runtime.handleRawMessage(packageName, raw)\n return\n }\n\n // 2) Log frames — console.* rewired through host. We tag with the\n // packageName so Sentry breadcrumbs can be filtered downstream.\n // Pipeline:\n // raw args → redactSecrets → throttle decision → ring buffer\n // → host logger (which surfaces to dev console / Sentry)\n if (iface === \"__log\") {\n const rawArgs = this.tryParseArgs(msg.argsJson)\n const safeArgs = redactSecrets(rawArgs)\n const decision = this.logThrottle.consume(packageName)\n const tag = `[${packageName}]`\n const fn =\n method === \"warn\"\n ? this.logger.warn\n : method === \"error\" || method === \"fatal\"\n ? this.logger.error\n : this.logger.log\n // Emit a synthetic \"[throttled N]\" line in place of the next\n // would-be-allowed log to summarise drops.\n if (!decision.allowed) {\n if (decision.throttledLine) {\n fn(`${tag} ${decision.throttledLine}`)\n this.logRing.push(packageName, `${decision.throttledLine}`)\n }\n return\n }\n const formatted = `${tag} console.${method}`\n fn(formatted, safeArgs)\n // Stringify into the ring buffer for crash-report attachment.\n let line: string\n try {\n line = `${method}: ${JSON.stringify(safeArgs)}`\n } catch {\n line = `${method}: <unserializable>`\n }\n this.logRing.push(packageName, line)\n // Forward to the `glassly dev` sidecar (if one is connected\n // for this package). Source=\"background\" so the CLI tags lines as\n // [JSRuntime]. The bridge silently drops when no dev server is up,\n // which makes this safe to call unconditionally in prod.\n const argsForBridge = Array.isArray(safeArgs) ? (safeArgs as unknown[]) : [safeArgs]\n devServerBridge.forwardLog(packageName, method, argsForBridge, Date.now(), \"background\")\n return\n }\n\n // 3) Error / unhandled rejection frames — surface as warnings AND\n // drive the crash state machine when one is attached. The\n // controller's outcome may schedule a respawn after a backoff;\n // if it doesn't (CRASHLOOP_DISABLED), we leave the JSContext\n // dead and let the host surface a \"tap to retry\" banner.\n if (iface === \"__error\") {\n const payload = this.tryParseArgs(msg.argsJson)\n this.logger.error(`[${packageName}] ${method}`, payload)\n // Crashes reach the `glassly dev` terminal too, not only console calls.\n const summary = this.summarizeReason(payload, method)\n const stack = (payload as {stack?: unknown} | null)?.stack\n const errorArgs = typeof stack === \"string\" && stack ? [summary, stack] : [summary]\n devServerBridge.forwardLog(packageName, \"error\", errorArgs, Date.now(), \"background\")\n if (this.crashController) {\n // Only treat \"exception\" + \"unhandledRejection\" + \"uncaught\" as\n // crash signals. `console.error` calls also flow through the\n // log path — those don't end the JSContext.\n const isCrash = method === \"exception\" || method === \"unhandledRejection\" || method === \"uncaught\"\n if (isCrash) {\n this.handleCrash(packageName, summary)\n }\n }\n return\n }\n\n // 4) Anything else is a `forwardToRn` from the dispatcher — a\n // handler the native dispatcher didn't know about. We don't have\n // inline handlers for any of these; the runtime's existing path\n // treats them as legacy WebView envelopes by falling through.\n // Log so unknown ifaces surface in dev.\n this.logger.log(`unhandled iface=${iface} method=${method} from ${packageName}`)\n }\n\n /**\n * The wire format for `__bridge.send` is `argsJson = JSON.stringify([raw])`\n * — a single-element array containing the original raw envelope. The\n * dispatcher passes the parsed array through as either:\n * - `msg.args` when the dispatcher unpacked (Android path that turns\n * `argsJson` into a List on the way to RN), or\n * - `msg.argsJson` (iOS path that ships the string verbatim).\n * Cover both shapes here.\n */\n /**\n * Parse a raw bridge envelope just enough to peek at the inner\n * payload's `type` field. Used by the UI_SEND interception path.\n * Returns null if the envelope isn't a valid bridge frame.\n */\n private peekBridgePayloadType(raw: string): {type: string; [k: string]: unknown} | null {\n try {\n const env = JSON.parse(raw) as {payload?: {type?: string}}\n if (env && typeof env.payload === \"object\" && env.payload && typeof env.payload.type === \"string\") {\n return env.payload as {type: string; [k: string]: unknown}\n }\n } catch {\n return null\n }\n return null\n }\n\n private coerceArgsToBridgeRaw(msg: OutboundMessagePayload): string | null {\n if (Array.isArray(msg.args)) {\n const v = msg.args[0]\n return typeof v === \"string\" ? v : null\n }\n if (typeof msg.argsJson === \"string\") {\n try {\n const parsed = JSON.parse(msg.argsJson) as unknown\n if (Array.isArray(parsed) && typeof parsed[0] === \"string\") {\n return parsed[0]\n }\n } catch {\n // fall through\n }\n }\n return null\n }\n\n private tryParseArgs(argsJson: string | undefined): unknown {\n if (!argsJson) return null\n try {\n return JSON.parse(argsJson)\n } catch {\n return argsJson\n }\n }\n\n /**\n * Push a `kind=\"bridge\"` envelope into the named JSContext's\n * `globalThis.__deliver`. Used both by the per-app `sendMessage`\n * registered via {@link registerApp} and by ad-hoc callers (e.g.\n * cloud-relayed stream-status responses route through\n * `LocalMiniappRuntime.handleCloudMessage`, which then calls the\n * `app.sendMessage(serialized)` registered above).\n */\n private dispatchBridgeRaw(packageName: string, raw: string): void {\n void this.crust.jsDispatchToJs(packageName, {kind: \"bridge\", raw})\n }\n}\n"]}
1
+ {"version":3,"file":"JSRouter.js","sourceRoot":"","sources":["../../src/services/JSRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAIH,OAAO,eAAe,MAAM,mBAAmB,CAAA;AAM/C,OAAO,EAAC,eAAe,EAAE,aAAa,EAAE,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7E,OAAO,EAAC,mBAAmB,EAAC,MAAM,wBAAwB,CAAA;AAE1D,OAAO,EAAC,sBAAsB,EAAC,MAAM,0BAA0B,CAAA;AAE/D,OAAO,EAAC,OAAO,EAAC,MAAM,iBAAiB,CAAA;AAyCvC,MAAM,aAAa,GAAiB;IAClC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;IAEtD,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;IAExD,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;CAC3D,CAAA;AASD,MAAM,OAAO,QAAQ;IA+CA;IACA;IACA;IAhDX,YAAY,GAA6B,IAAI,CAAA;IACpC,UAAU,GAAgB,IAAI,GAAG,EAAE,CAAA;IACpD,kFAAkF;IACjE,UAAU,GAA4B,IAAI,GAAG,EAAE,CAAA;IAChE,4EAA4E;IAC3D,aAAa,GAAwB,IAAI,GAAG,EAAE,CAAA;IAE/D;;;;;OAKG;IACH,eAAe,GAA6B,IAAI,CAAA;IAEhD,oEAAoE;IACpE,WAAW,GAA2D,IAAI,CAAA;IAC1E,6DAA6D;IAC7D,cAAc,GAA2D,IAAI,CAAA;IAE7E;;;;;;;;;OASG;IACH,WAAW,GAAkB,IAAI,aAAa,EAAE,CAAA;IAChD,OAAO,GAAoB,IAAI,eAAe,EAAE,CAAA;IAEhD;;;;;;OAMG;IACH,QAAQ,GAAoB,IAAI,CAAA;IAEhC,oFAAoF;IACnE,aAAa,GAAG,IAAI,GAAG,EAAyB,CAAA;IAEjE,YACmB,OAA4B,EAC5B,KAAqB,EACrB,SAAuB,aAAa;QAFpC,YAAO,GAAP,OAAO,CAAqB;QAC5B,UAAK,GAAL,KAAK,CAAgB;QACrB,WAAM,GAAN,MAAM,CAA8B;IACpD,CAAC;IAEJ;;;OAGG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,YAAY;YAAE,OAAM;QAC7B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE;YAC/D,IAAI,CAAC;gBACH,IAAI,CAAC,cAAc,CAAC,GAAwC,CAAC,CAAA;YAC/D,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,EAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAC,CAAC,CAAA;YACtE,CAAC;QACH,CAAC,CAAC,CAAA;QACF,sEAAsE;QACtE,qEAAqE;QACrE,iEAAiE;QACjE,oEAAoE;QACpE,0DAA0D;QAC1D,IAAI,CAAC,OAAO,CAAC,iBAAiB,GAAG,CAAC,WAAW,EAAE,EAAE;YAC/C,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,wBAAwB,CAAC,CAAA;QACzD,CAAC,CAAA;IACH,CAAC;IAED;;;;OAIG;IACH,IAAI;QACF,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,CAAA;QAC3B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAA;QACxB,IAAI,CAAC,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAA;IACvC,CAAC;IAED;;;;;;;;;;OAUG;IACH,WAAW,CACT,WAAmB,EACnB,iBAA4C,EAC5C,YAAkC;QAElC,IAAI,CAAC,OAAO,CAAC,WAAW,CACtB,WAAW,EACX,CAAC,GAAW,EAAE,EAAE;YACd,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;QAC1C,CAAC,EACD,iBAAiB,EACjB,YAAY,CACb,CAAA;QACD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAChC,8DAA8D;QAC9D,gEAAgE;QAChE,4CAA4C;QAC5C,sBAAsB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACzC,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,gBAAgB,CACpB,WAAmB,EACnB,SAAiB,EACjB,OAIC;QAED,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAA;YAChF,OAAO,KAAK,CAAA;QACd,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,EAAE,IAAI,EAAE,CAAA;QAC1D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iCAAiC,WAAW,0BAA0B,CAAC,CAAA;QAC1F,CAAC;QACD,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAA;QACrE,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,WAAW,EAAE,CAAC,CAAA;YACpD,OAAO,KAAK,CAAA;QACd,CAAC;QACD,iCAAiC;QACjC,sEAAsE;QACtE,4EAA4E;QAC5E,mBAAmB;QACnB,mEAAmE;QACnE,yEAAyE;QACzE,6DAA6D;QAC7D,IAAI,OAAO,EAAE,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;QAClE,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,YAAY,CAAC,CAAA;QAChF,gEAAgE;QAChE,mEAAmE;QACnE,gEAAgE;QAChE,4DAA4D;QAC5D,6BAA6B;QAC7B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE;YAC/B,SAAS;YACT,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,EAAE;YACvC,iBAAiB,EAAE,OAAO,EAAE,iBAAiB;YAC7C,YAAY,EAAE,OAAO,EAAE,YAAY;SACpC,CAAC,CAAA;QACF,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;QAE1C,+DAA+D;QAC/D,kDAAkD;QAClD,8DAA8D;QAC9D,2DAA2D;QAC3D,+DAA+D;QAC/D,iCAAiC;QACjC,MAAM,SAAS,GAAG,GAAG,WAAW,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAA;QAC7D,KAAK,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,EAAE,EAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAC,CAAC,CAAA;QAEtE,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;OAIG;IACK,WAAW,CAAC,WAAmB,EAAE,MAAc;QACrD,0EAA0E;QAC1E,2EAA2E;QAC3E,2EAA2E;QAC3E,2EAA2E;QAC3E,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,WAAW,CAAC,CAAA;QACxC,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAA;QACvC,IAAI,CAAC,UAAU;YAAE,OAAM;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC/C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,WAAW,4CAA4C,CAAC,CAAA;YACtF,UAAU,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;YACvC,OAAM;QACR,CAAC;QACD,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QACvD,IAAI,OAAO,CAAC,sBAAsB,EAAE,CAAC;YACnC,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;YACvC,mBAAmB,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAC,CAAC,CAAA;YACjG,OAAM;QACR,CAAC;QACD,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC7B,IAAI,CAAC,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QAC5C,CAAC;QACD,IAAI,OAAO,CAAC,sBAAsB,IAAI,IAAI;YAAE,OAAM;QAClD,gEAAgE;QAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACpD,IAAI,QAAQ;YAAE,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;QAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE;YACpC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;YACtC,KAAK,CAAC,KAAK,IAAI,EAAE;gBACf,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,CAAA;gBACxC,CAAC;gBAAC,MAAM,CAAC;oBACP,uCAAuC;gBACzC,CAAC;gBACD,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,EAAE,IAAI,EAAE,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;gBAC/G,IAAI,CAAC,EAAE,EAAE,CAAC;oBACR,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,WAAW,EAAE,CAAC,CAAA;oBAC5D,OAAM;gBACR,CAAC;gBACD,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAClC,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;gBACjE,CAAC;gBACD,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,YAAY,CAAC,CAAA;gBAC5E,UAAU,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;gBAC/B,uDAAuD;gBACvD,wCAAwC;gBACxC,MAAM,SAAS,GAAG,GAAG,WAAW,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAA;gBAC7D,KAAK,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,EAAE,EAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAC,CAAC,CAAA;gBACtE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,WAAW,cAAc,CAAC,CAAA;YACzD,CAAC,CAAC,EAAE,CAAA;QACN,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAA;QAClC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;IAC5C,CAAC;IAEO,eAAe,CAAC,OAAgB,EAAE,MAAc;QACtD,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,SAAS,IAAK,OAAmC,EAAE,CAAC;YAChG,OAAO,GAAG,MAAM,KAAM,OAA6B,CAAC,OAAO,EAAE,CAAA;QAC/D,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,WAAmB;QAC5B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;QAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACpD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAA;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAA;QACjG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;QAC7C,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,kFAAkF;IAClF,KAAK,CAAC,gBAAgB,CAAC,WAAmB;QACxC,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IAC3C,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,WAAmB;QACxC,kEAAkE;QAClE,mEAAmE;QACnE,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACnD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;YAC7B,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;QACxC,CAAC;QACD,sBAAsB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;QAC1C,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAA;QAC3C,MAAM,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;QAC/D,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;QACnC,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;QACzC,uEAAuE;QACvE,qEAAqE;QACrE,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,WAAW,EAAE,EAAC,aAAa,EAAE,IAAI,EAAC,CAAC,CAAA;QAC9D,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;QACnC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;YACtC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;YACnE,CAAC;QACH,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,sFAAsF;IACtF,YAAY,CAAC,WAAmB,EAAE,YAAiC;QACjE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC;YAAE,OAAM;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC/C,IAAI,MAAM;YAAE,MAAM,CAAC,YAAY,GAAG,YAAY,CAAA;QAC9C,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAA;IAC1D,CAAC;IAED,kBAAkB;QAChB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACpC,CAAC;IAED;;;;;OAKG;IACH,uBAAuB,CAAC,WAAmB,EAAE,MAAM,GAAG,iBAAiB;QACrE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC;YAAE,OAAM;QAC7C,IAAI,CAAC,OAAO,CAAC,uBAAuB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;IAC3D,CAAC;IAED,mEAAmE;IACnE,4BAA4B;IAC5B,mEAAmE;IAE3D,cAAc,CAAC,GAA2B;QAChD,MAAM,EAAC,WAAW,EAAE,KAAK,EAAE,MAAM,EAAC,GAAG,GAAG,CAAA;QACxC,IAAI,CAAC,WAAW,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YACtC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE,GAAG,CAAC,CAAA;YACxD,OAAM;QACR,CAAC;QAED,sEAAsE;QACtE,oEAAoE;QACpE,kDAAkD;QAClD,IAAI,KAAK,KAAK,UAAU,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAA;YAC3C,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;gBAChB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,kCAAkC,EAAE,GAAG,CAAC,CAAA;gBACzD,OAAM;YACR,CAAC;YACD,8DAA8D;YAC9D,0CAA0C;YAC1C,mDAAmD;YACnD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,MAAM,YAAY,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAA;gBACpD,IAAI,YAAY,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;oBACrC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAA;oBAC5D,OAAM;gBACR,CAAC;YACH,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;YAC/C,OAAM;QACR,CAAC;QAED,kEAAkE;QAClE,mEAAmE;QACnE,eAAe;QACf,kEAAkE;QAClE,uEAAuE;QACvE,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YAC/C,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;YACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;YACtD,MAAM,GAAG,GAAG,IAAI,WAAW,GAAG,CAAA;YAC9B,MAAM,EAAE,GACN,MAAM,KAAK,MAAM;gBACf,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI;gBAClB,CAAC,CAAC,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,OAAO;oBACxC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK;oBACnB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAA;YACvB,6DAA6D;YAC7D,2CAA2C;YAC3C,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACtB,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;oBAC3B,EAAE,CAAC,GAAG,GAAG,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAA;oBACtC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAA;gBAC7D,CAAC;gBACD,OAAM;YACR,CAAC;YACD,MAAM,SAAS,GAAG,GAAG,GAAG,YAAY,MAAM,EAAE,CAAA;YAC5C,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;YACvB,8DAA8D;YAC9D,IAAI,IAAY,CAAA;YAChB,IAAI,CAAC;gBACH,IAAI,GAAG,GAAG,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAA;YACjD,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,GAAG,GAAG,MAAM,oBAAoB,CAAA;YACtC,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;YACpC,4DAA4D;YAC5D,kEAAkE;YAClE,mEAAmE;YACnE,yDAAyD;YACzD,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAE,QAAsB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;YACpF,eAAe,CAAC,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,CAAA;YACxF,OAAM;QACR,CAAC;QAED,kEAAkE;QAClE,6DAA6D;QAC7D,kEAAkE;QAClE,gEAAgE;QAChE,4DAA4D;QAC5D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YAC/C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,WAAW,KAAK,MAAM,EAAE,EAAE,OAAO,CAAC,CAAA;YACxD,wEAAwE;YACxE,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;YACrD,MAAM,KAAK,GAAI,OAAoC,EAAE,KAAK,CAAA;YAC1D,MAAM,SAAS,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;YACnF,eAAe,CAAC,UAAU,CAAC,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,CAAA;YACrF,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBACzB,gEAAgE;gBAChE,6DAA6D;gBAC7D,4CAA4C;gBAC5C,MAAM,OAAO,GAAG,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,oBAAoB,IAAI,MAAM,KAAK,UAAU,CAAA;gBAClG,IAAI,OAAO,EAAE,CAAC;oBACZ,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;gBACxC,CAAC;YACH,CAAC;YACD,OAAM;QACR,CAAC;QAED,8DAA8D;QAC9D,oEAAoE;QACpE,mEAAmE;QACnE,iEAAiE;QACjE,2CAA2C;QAC3C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,mBAAmB,KAAK,WAAW,MAAM,SAAS,WAAW,EAAE,CAAC,CAAA;IAClF,CAAC;IAED;;;;;;;;OAQG;IACH;;;;OAIG;IACK,qBAAqB,CAAC,GAAW;QACvC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgC,CAAA;YAC1D,IAAI,GAAG,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,IAAI,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAClG,OAAO,GAAG,CAAC,OAA+C,CAAA;YAC5D,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAEO,qBAAqB,CAAC,GAA2B;QACvD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACrB,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QACzC,CAAC;QACD,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACrC,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAY,CAAA;gBAClD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;oBAC3D,OAAO,MAAM,CAAC,CAAC,CAAC,CAAA;gBAClB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,eAAe;YACjB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAEO,YAAY,CAAC,QAA4B;QAC/C,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAA;QAC1B,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,QAAQ,CAAA;QACjB,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACK,iBAAiB,CAAC,WAAmB,EAAE,GAAW;QACxD,KAAK,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAC,CAAC,CAAA;IACpE,CAAC;CACF","sourcesContent":["/**\n * @fileoverview JSRouter — RN-side host that bridges the per-miniapp\n * JS contexts (iOS-JSC and Android-QuickJS via Zipline) into the existing\n * {@link LocalMiniappRuntime} handler set.\n *\n * Rather than re-implement the 33 dispatch arms inline, the router\n * consumes Crust's `js_message` Expo event and forwards its\n * `__bridge.send(raw)` payloads to {@link LocalMiniappRuntime.handleRawMessage}.\n * The SDK envelope shape (`{type: \"DISPLAY\", ...}` etc.) is unchanged from\n * the WebView path, so every existing handler runs verbatim. What changes\n * is the *transport*:\n *\n * - **Inbound** (background JS → host): `__dispatch(\"__bridge\", \"send\",\n * [rawJsonString])` → `js_message` event → router →\n * `LocalMiniappRuntime.handleRawMessage(packageName, raw)`.\n * - **Outbound** (host → background JS): every package registered with\n * the router gets a `sendMessage(raw)` fn that calls\n * `Crust.jsDispatchToJs(packageName, {kind: \"bridge\", raw})`.\n * The polyfill's `__deliver` recognises `kind === \"bridge\"` and calls\n * `__deliverBridgeRaw(raw)`, which routes into the SDK's\n * {@link DispatchTransport.onMessage} handler.\n *\n * Host-side handler bodies (display fan-out, mic state, transcription,\n * navigation, etc.) live untouched in `LocalMiniappRuntime.ts`.\n *\n * Cloud-message routing (`phone_stream_status`, `phone_managed_stream_status`)\n * goes straight through `LocalMiniappRuntime.handleCloudMessage` — nothing\n * for the router to do; the responses arrive inside an envelope whose\n * `sendMessage` was already registered via the same path here.\n *\n * The router also bridges native error / log / unhandled-rejection\n * events (`iface: \"__log\"`, `iface: \"__error\"`) into the standard\n * `console.*` + Sentry breadcrumb pipeline so miniapp telemetry is\n * visible without bringing up a separate sink.\n */\n\nimport type {EventSubscription} from \"expo-modules-core\"\n\nimport devServerBridge from \"./DevServerBridge\"\nimport type localMiniappRuntime from \"./LocalMiniappRuntime\"\nimport type {MiniappLaunchSource} from \"@glassly/miniapp\"\n\nimport type {InstalledMiniappManifest} from \"./LocalMiniappRuntime\"\nimport type {JSCrashController} from \"./JSCrashController\"\nimport {JSLogRingBuffer, JSLogThrottle, redactSecrets} from \"./JSLogPipeline\"\nimport {islandNotifications} from \"./NotificationsEmitter\"\nimport type {UIRouter} from \"./UIRouter\"\nimport {miniappRunningRegistry} from \"./MiniappRunningRegistry\"\n\nimport {BgTimer} from \"../utils/timers\"\n\n/** The runtime's runtime instance type — the singleton exported from\n * LocalMiniappRuntime.ts (the file's `export default` is the instance,\n * not the class).\n */\ntype LocalMiniappRuntime = typeof localMiniappRuntime\n\n/**\n * Minimal subset of the Crust native module the router uses. Keeping the\n * binding loose lets us mock the module in unit tests without bringing\n * the whole Expo module surface along.\n */\nexport interface JSCrustBinding {\n jsDispatchToJs(packageName: string, envelope: Record<string, unknown>): Promise<void> | void\n jsSetManifest(packageName: string, permissions: string[]): Promise<void> | void\n jsLoadPolyfillBundle?: () => string\n jsSpawn?: (packageName: string, polyfill: string, miniappJs: string) => Promise<boolean> | boolean\n jsKill?: (packageName: string) => Promise<void> | void\n jsAlivePackages?: () => string[]\n addListener: (event: string, handler: (payload: Record<string, unknown>) => void) => EventSubscription\n}\n\nexport interface OutboundMessagePayload {\n packageName: string\n iface: string\n method: string\n argsJson?: string\n args?: unknown[]\n reqId?: string\n // Implementation-internal: any extra fields the dispatcher attached on\n // .forwardToRn (e.g. payload metadata) are passed through verbatim.\n [extra: string]: unknown\n}\n\nexport type RouterLogger = {\n log: (message: string, payload?: unknown) => void\n warn: (message: string, payload?: unknown) => void\n error: (message: string, payload?: unknown) => void\n}\n\nconst defaultLogger: RouterLogger = {\n log: (m, p) => console.log(`[JSRouter] ${m}`, p ?? \"\"),\n\n warn: (m, p) => console.warn(`[JSRouter] ${m}`, p ?? \"\"),\n\n error: (m, p) => console.error(`[JSRouter] ${m}`, p ?? \"\"),\n}\n\ninterface SpawnCache {\n miniappJs: string\n permissions: string[]\n installedManifest?: InstalledMiniappManifest\n launchSource?: MiniappLaunchSource\n}\n\nexport class JSRouter {\n private subscription: EventSubscription | null = null\n private readonly registered: Set<string> = new Set()\n /** Cached spawn arguments so the crash controller can respawn after a backoff. */\n private readonly spawnCache: Map<string, SpawnCache> = new Map()\n /** Active respawn timers (so unregister() can cancel a pending respawn). */\n private readonly respawnTimers: Map<string, number> = new Map()\n\n /**\n * Optional crash controller. When wired, every `__error` frame from a\n * JSContext drives the state machine; an Outcome with\n * scheduleRespawnAfterMs queues a setTimeout that re-spawns the\n * miniapp's last-known JS source after the backoff delay.\n */\n crashController: JSCrashController | null = null\n\n /** Hook called when a package transitions to CRASHLOOP_DISABLED. */\n onCrashloop: ((packageName: string, reason: string) => void) | null = null\n /** Hook called on the 2nd-within-window crash (toast UX). */\n onRestartToast: ((packageName: string, reason: string) => void) | null = null\n\n /**\n * Logging plumbing. Every `__log` frame passes through `redactSecrets`\n * (token/password/etc. scrubbed), then the throttle (100/min sustained\n * per pkg, 500 burst), then lands in the ring buffer + the host\n * logger. The ring buffer holds the last 200 lines/pkg so a crash\n * report can attach \"last words\" context.\n *\n * Replace with new instances in tests; production code uses the\n * defaults.\n */\n logThrottle: JSLogThrottle = new JSLogThrottle()\n logRing: JSLogRingBuffer = new JSLogRingBuffer()\n\n /**\n * Optional UI router — when wired, `__bridge.send` envelopes whose\n * inner payload type is `UI_SEND` get routed to the bound WebView\n * instead of through LocalMiniappRuntime. Two-layer miniapps set\n * this; legacy single-bundle WebView miniapps don't and the bridge\n * frames pass through unchanged.\n */\n uiRouter: UIRouter | null = null\n\n /** Teardowns in progress, so a stop and a racing start or stop see the same one. */\n private readonly unregistering = new Map<string, Promise<void>>()\n\n constructor(\n private readonly runtime: LocalMiniappRuntime,\n private readonly crust: JSCrustBinding,\n private readonly logger: RouterLogger = defaultLogger,\n ) {}\n\n /**\n * Subscribe to Crust's `js_message` event. Idempotent — calling\n * start() twice attaches a single listener.\n */\n start(): void {\n if (this.subscription) return\n this.subscription = this.crust.addListener(\"js_message\", (raw) => {\n try {\n this.handleOutbound(raw as unknown as OutboundMessagePayload)\n } catch (e) {\n this.logger.error(`outbound handler threw`, {error: String(e), raw})\n }\n })\n // A background script unregistered for missing liveness pings is dead\n // weight: its subscriptions are gone (so the mic releases) while the\n // webview keeps rendering stale state. Route it through the same\n // respawn machinery as a crash so it comes back automatically, with\n // the crash controller's backoff + crash-loop protection.\n this.runtime.onLivenessTimeout = (packageName) => {\n this.handleCrash(packageName, \"liveness: missed pings\")\n }\n }\n\n /**\n * Detach the Crust subscription. The router can be restarted later\n * with start(); registrations survive (the runtime's app map is the\n * source of truth).\n */\n stop(): void {\n this.subscription?.remove()\n this.subscription = null\n this.runtime.onLivenessTimeout = null\n }\n\n /**\n * Register a JSContext with the runtime so its handlers can fire\n * `sendMessage(raw)` against the right context. The router builds a\n * `sendMessage` that calls `Crust.jsDispatchToJs(packageName,\n * {kind: \"bridge\", raw})`; the polyfill's `__deliver` then hands the\n * envelope to `DispatchTransport.onMessage` inside the miniapp.\n *\n * Mirrors `MiniappHost.registerRuntime` on the WebView side. Callers\n * (e.g. {@link spawnAndRegister} below, or the host's miniapp launch\n * pipeline) should call this once per spawn.\n */\n registerApp(\n packageName: string,\n installedManifest?: InstalledMiniappManifest,\n launchSource?: MiniappLaunchSource,\n ): void {\n this.runtime.registerApp(\n packageName,\n (raw: string) => {\n this.dispatchBridgeRaw(packageName, raw)\n },\n installedManifest,\n launchSource,\n )\n this.registered.add(packageName)\n // JSContext is the source-of-truth for \"miniapp running\". The\n // home tile / tray reads this registry to project the `running`\n // flag — UI WebView open/close is separate.\n miniappRunningRegistry.add(packageName)\n }\n\n /**\n * Convenience: spawn a JSContext via Crust, register the app, and\n * set its declared permissions. Returns true on successful spawn.\n *\n * The host's miniapp launch path\n * (`mobile/src/services/miniapps/launchLocalMiniapp.ts`) calls this\n * once per JSContext mount.\n */\n async spawnAndRegister(\n packageName: string,\n miniappJs: string,\n options?: {\n permissions?: string[]\n installedManifest?: InstalledMiniappManifest\n launchSource?: MiniappLaunchSource\n },\n ): Promise<boolean> {\n if (!this.crust.jsSpawn) {\n this.logger.warn(\"jsSpawn not available — host binding missing native function\")\n return false\n }\n const polyfill = this.crust.jsLoadPolyfillBundle?.() ?? \"\"\n if (!polyfill) {\n this.logger.warn(`no polyfill bundle loaded for ${packageName}; spawn will likely fail`)\n }\n const ok = await this.crust.jsSpawn(packageName, polyfill, miniappJs)\n if (!ok) {\n this.logger.error(`spawn failed for ${packageName}`)\n return false\n }\n // Two distinct permission gates:\n // 1. Native dispatcher (JSContext → native bridge): `jsSetManifest`\n // checks per-call iface, e.g. __dispatch(\"mic\", \"start\", ...) requires\n // MICROPHONE.\n // 2. LocalMiniappRuntime (SUBSCRIBE envelope): `registerApp(...,\n // installedManifest)` carries the full manifest so SUBSCRIBE's gate\n // can match stream → permission against declared types.\n if (options?.permissions && options.permissions.length > 0) {\n await this.crust.jsSetManifest(packageName, options.permissions)\n }\n this.registerApp(packageName, options?.installedManifest, options?.launchSource)\n // Cache spawn arguments so the crash controller can respawn the\n // same code after a backoff. permissions + manifest are cached too\n // because the native side resets setManifest on every spawn and\n // LocalMiniappRuntime's installedManifest entry is keyed by\n // connect-time registration.\n this.spawnCache.set(packageName, {\n miniappJs,\n permissions: options?.permissions ?? [],\n installedManifest: options?.installedManifest,\n launchSource: options?.launchSource,\n })\n this.crashController?.onSpawn(packageName)\n\n // Fire the `init` envelope so the polyfill's __deliver handler\n // resolves `__initCallback(sessionId)`. The SDK's\n // `registerMiniapp(handler)` wires that callback to construct\n // MiniappSession and call the user's handler. Without this\n // dispatch the user's code never runs — `registerMiniapp` just\n // assigns to a global and waits.\n const sessionId = `${packageName}-${Date.now().toString(36)}`\n void this.crust.jsDispatchToJs(packageName, {kind: \"init\", sessionId})\n\n return true\n }\n\n /**\n * Crash-controller integration. Called from the `__error` frame\n * handler. The controller returns an outcome that tells us whether\n * to respawn (with delay) or leave the context dead.\n */\n private handleCrash(packageName: string, reason: string): void {\n // The native context is dead the instant a crash is observed — invalidate\n // its CONNECT handshake NOW so waitForConnect() blocks through the respawn\n // backoff window instead of resolving immediately against the dead context\n // (an action invoked mid-backoff would otherwise be delivered to nothing).\n this.runtime.resetHandshake(packageName)\n const controller = this.crashController\n if (!controller) return\n const cached = this.spawnCache.get(packageName)\n if (!cached) {\n this.logger.warn(`crash for ${packageName} but no cached spawn args — cannot respawn`)\n controller.onCrash(packageName, reason)\n return\n }\n const outcome = controller.onCrash(packageName, reason)\n if (outcome.surfaceCrashloopBanner) {\n this.onCrashloop?.(packageName, reason)\n islandNotifications.emit({kind: \"miniapp_crashloop\", packageName, reason, timestamp: Date.now()})\n return\n }\n if (outcome.showRestartToast) {\n this.onRestartToast?.(packageName, reason)\n }\n if (outcome.scheduleRespawnAfterMs == null) return\n // Cancel any prior pending respawn before scheduling a new one.\n const existing = this.respawnTimers.get(packageName)\n if (existing) BgTimer.clearTimeout(existing)\n const timer = BgTimer.setTimeout(() => {\n this.respawnTimers.delete(packageName)\n void (async () => {\n try {\n await this.crust.jsKill?.(packageName)\n } catch {\n /* native may have already torn down */\n }\n const ok = await this.crust.jsSpawn?.(packageName, this.crust.jsLoadPolyfillBundle?.() ?? \"\", cached.miniappJs)\n if (!ok) {\n this.logger.error(`crash respawn failed for ${packageName}`)\n return\n }\n if (cached.permissions.length > 0) {\n await this.crust.jsSetManifest(packageName, cached.permissions)\n }\n this.registerApp(packageName, cached.installedManifest, cached.launchSource)\n controller.onSpawn(packageName)\n // Re-fire the init envelope so the respawned context's\n // `registerMiniapp` handler runs again.\n const sessionId = `${packageName}-${Date.now().toString(36)}`\n void this.crust.jsDispatchToJs(packageName, {kind: \"init\", sessionId})\n this.logger.log(`respawned ${packageName} after crash`)\n })()\n }, outcome.scheduleRespawnAfterMs)\n this.respawnTimers.set(packageName, timer)\n }\n\n private summarizeReason(payload: unknown, method: string): string {\n if (payload && typeof payload === \"object\" && \"message\" in (payload as Record<string, unknown>)) {\n return `${method}: ${(payload as {message: string}).message}`\n }\n return method\n }\n\n /**\n * Tear down a JSContext and unregister from the runtime. The session's\n * `onBeforeDisconnect` handlers get a short grace window first, so a\n * miniapp can clear what it drew and end its own work while its messages\n * still reach the host. Concurrent calls share one teardown.\n */\n unregister(packageName: string): Promise<void> {\n if (!this.registered.has(packageName)) return Promise.resolve()\n const inFlight = this.unregistering.get(packageName)\n if (inFlight) return inFlight\n const teardown = this.teardown(packageName).finally(() => this.unregistering.delete(packageName))\n this.unregistering.set(packageName, teardown)\n return teardown\n }\n\n /** Resolves once an in-flight {@link unregister} of this package has finished. */\n async whenUnregistered(packageName: string): Promise<void> {\n await this.unregistering.get(packageName)\n }\n\n private async teardown(packageName: string): Promise<void> {\n // Cancel any pending crash-respawn before tearing down — we don't\n // want a stale timer to re-spawn a miniapp the user just disabled.\n const pending = this.respawnTimers.get(packageName)\n if (pending) {\n BgTimer.clearTimeout(pending)\n this.respawnTimers.delete(packageName)\n }\n miniappRunningRegistry.remove(packageName)\n this.runtime.releaseWidgetHost(packageName)\n await this.runtime.notifyWillDisconnect(packageName, \"stopped\")\n this.spawnCache.delete(packageName)\n this.crashController?.onKill(packageName)\n // User-initiated close/disable: end any active nav trip so the glasses\n // drop out of native nav mode (crash-respawns don't take this path).\n this.runtime.unregisterApp(packageName, {endNavigation: true})\n this.registered.delete(packageName)\n if (this.crust.jsKill) {\n try {\n await this.crust.jsKill(packageName)\n } catch (e) {\n this.logger.warn(`jsKill threw for ${packageName}: ${String(e)}`)\n }\n }\n }\n\n /** List packages the router has registered. */\n /** The user opened a running miniapp again; the source rides the next respawn too. */\n notifyLaunch(packageName: string, launchSource: MiniappLaunchSource): void {\n if (!this.registered.has(packageName)) return\n const cached = this.spawnCache.get(packageName)\n if (cached) cached.launchSource = launchSource\n this.runtime.sendLaunchChange(packageName, launchSource)\n }\n\n registeredPackages(): string[] {\n return Array.from(this.registered)\n }\n\n /**\n * Validate that a reused background JSContext is still responsive when its\n * WebView comes foreground. The runtime owns the ping/timeout mechanics; the\n * router gates this to registered packages and keeps LocalMiniappView from\n * reaching into runtime internals.\n */\n probeForegroundLiveness(packageName: string, reason = \"foreground-open\"): void {\n if (!this.registered.has(packageName)) return\n this.runtime.probeForegroundLiveness(packageName, reason)\n }\n\n // ----------------------------------------------------------------\n // Outbound message handling\n // ----------------------------------------------------------------\n\n private handleOutbound(msg: OutboundMessagePayload): void {\n const {packageName, iface, method} = msg\n if (!packageName || !iface || !method) {\n this.logger.warn(`bad js_message — missing fields`, msg)\n return\n }\n\n // 1) Bridge frames: the SDK's DispatchTransport.send(raw) lands here.\n // Forward raw envelope into LocalMiniappRuntime.handleRawMessage\n // so every existing handler arm runs verbatim.\n if (iface === \"__bridge\" && method === \"send\") {\n const raw = this.coerceArgsToBridgeRaw(msg)\n if (raw == null) {\n this.logger.warn(`__bridge.send had no raw payload`, msg)\n return\n }\n // If the payload is a UI_SEND envelope, route it to the bound\n // WebView instead of LocalMiniappRuntime.\n // session.ui.send → DispatchTransport.send → here.\n if (this.uiRouter) {\n const innerPayload = this.peekBridgePayloadType(raw)\n if (innerPayload?.type === \"UI_SEND\") {\n this.uiRouter.routeFromBackground(packageName, innerPayload)\n return\n }\n }\n this.runtime.handleRawMessage(packageName, raw)\n return\n }\n\n // 2) Log frames — console.* rewired through host. We tag with the\n // packageName so Sentry breadcrumbs can be filtered downstream.\n // Pipeline:\n // raw args → redactSecrets → throttle decision → ring buffer\n // → host logger (which surfaces to dev console / Sentry)\n if (iface === \"__log\") {\n const rawArgs = this.tryParseArgs(msg.argsJson)\n const safeArgs = redactSecrets(rawArgs)\n const decision = this.logThrottle.consume(packageName)\n const tag = `[${packageName}]`\n const fn =\n method === \"warn\"\n ? this.logger.warn\n : method === \"error\" || method === \"fatal\"\n ? this.logger.error\n : this.logger.log\n // Emit a synthetic \"[throttled N]\" line in place of the next\n // would-be-allowed log to summarise drops.\n if (!decision.allowed) {\n if (decision.throttledLine) {\n fn(`${tag} ${decision.throttledLine}`)\n this.logRing.push(packageName, `${decision.throttledLine}`)\n }\n return\n }\n const formatted = `${tag} console.${method}`\n fn(formatted, safeArgs)\n // Stringify into the ring buffer for crash-report attachment.\n let line: string\n try {\n line = `${method}: ${JSON.stringify(safeArgs)}`\n } catch {\n line = `${method}: <unserializable>`\n }\n this.logRing.push(packageName, line)\n // Forward to the `glassly dev` sidecar (if one is connected\n // for this package). Source=\"background\" so the CLI tags lines as\n // [JSRuntime]. The bridge silently drops when no dev server is up,\n // which makes this safe to call unconditionally in prod.\n const argsForBridge = Array.isArray(safeArgs) ? (safeArgs as unknown[]) : [safeArgs]\n devServerBridge.forwardLog(packageName, method, argsForBridge, Date.now(), \"background\")\n return\n }\n\n // 3) Error / unhandled rejection frames — surface as warnings AND\n // drive the crash state machine when one is attached. The\n // controller's outcome may schedule a respawn after a backoff;\n // if it doesn't (CRASHLOOP_DISABLED), we leave the JSContext\n // dead and let the host surface a \"tap to retry\" banner.\n if (iface === \"__error\") {\n const payload = this.tryParseArgs(msg.argsJson)\n this.logger.error(`[${packageName}] ${method}`, payload)\n // Crashes reach the `glassly dev` terminal too, not only console calls.\n const summary = this.summarizeReason(payload, method)\n const stack = (payload as {stack?: unknown} | null)?.stack\n const errorArgs = typeof stack === \"string\" && stack ? [summary, stack] : [summary]\n devServerBridge.forwardLog(packageName, \"error\", errorArgs, Date.now(), \"background\")\n if (this.crashController) {\n // Only treat \"exception\" + \"unhandledRejection\" + \"uncaught\" as\n // crash signals. `console.error` calls also flow through the\n // log path — those don't end the JSContext.\n const isCrash = method === \"exception\" || method === \"unhandledRejection\" || method === \"uncaught\"\n if (isCrash) {\n this.handleCrash(packageName, summary)\n }\n }\n return\n }\n\n // 4) Anything else is a `forwardToRn` from the dispatcher — a\n // handler the native dispatcher didn't know about. We don't have\n // inline handlers for any of these; the runtime's existing path\n // treats them as legacy WebView envelopes by falling through.\n // Log so unknown ifaces surface in dev.\n this.logger.log(`unhandled iface=${iface} method=${method} from ${packageName}`)\n }\n\n /**\n * The wire format for `__bridge.send` is `argsJson = JSON.stringify([raw])`\n * — a single-element array containing the original raw envelope. The\n * dispatcher passes the parsed array through as either:\n * - `msg.args` when the dispatcher unpacked (Android path that turns\n * `argsJson` into a List on the way to RN), or\n * - `msg.argsJson` (iOS path that ships the string verbatim).\n * Cover both shapes here.\n */\n /**\n * Parse a raw bridge envelope just enough to peek at the inner\n * payload's `type` field. Used by the UI_SEND interception path.\n * Returns null if the envelope isn't a valid bridge frame.\n */\n private peekBridgePayloadType(raw: string): {type: string; [k: string]: unknown} | null {\n try {\n const env = JSON.parse(raw) as {payload?: {type?: string}}\n if (env && typeof env.payload === \"object\" && env.payload && typeof env.payload.type === \"string\") {\n return env.payload as {type: string; [k: string]: unknown}\n }\n } catch {\n return null\n }\n return null\n }\n\n private coerceArgsToBridgeRaw(msg: OutboundMessagePayload): string | null {\n if (Array.isArray(msg.args)) {\n const v = msg.args[0]\n return typeof v === \"string\" ? v : null\n }\n if (typeof msg.argsJson === \"string\") {\n try {\n const parsed = JSON.parse(msg.argsJson) as unknown\n if (Array.isArray(parsed) && typeof parsed[0] === \"string\") {\n return parsed[0]\n }\n } catch {\n // fall through\n }\n }\n return null\n }\n\n private tryParseArgs(argsJson: string | undefined): unknown {\n if (!argsJson) return null\n try {\n return JSON.parse(argsJson)\n } catch {\n return argsJson\n }\n }\n\n /**\n * Push a `kind=\"bridge\"` envelope into the named JSContext's\n * `globalThis.__deliver`. Used both by the per-app `sendMessage`\n * registered via {@link registerApp} and by ad-hoc callers (e.g.\n * cloud-relayed stream-status responses route through\n * `LocalMiniappRuntime.handleCloudMessage`, which then calls the\n * `app.sendMessage(serialized)` registered above).\n */\n private dispatchBridgeRaw(packageName: string, raw: string): void {\n void this.crust.jsDispatchToJs(packageName, {kind: \"bridge\", raw})\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"LocalLlmModelManager.d.ts","sourceRoot":"","sources":["../../src/services/LocalLlmModelManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LocalLlmModelManager.d.ts","sourceRoot":"","sources":["../../src/services/LocalLlmModelManager.ts"],"names":[],"mappings":"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"}
@@ -17,9 +17,10 @@ import { SETTINGS, useSettingsStore } from "../stores/settings";
17
17
  import { storage } from "../utils/storage";
18
18
  export const DEFAULT_LOCAL_LLM_MODEL = "qwen3-1.7b";
19
19
  // XNNPACK 8da4w exports from software-mansion/react-native-executorch-qwen-3,
20
- // pinned to the v0.10.0 release tag that react-native-executorch 0.10.x
21
- // expects. modelBytes are the .pte sizes on the Hub; sizeBytes adds the
22
- // tokenizer files (~11 MB).
20
+ // pinned to the v0.10.0 release tag. They export every method the 0.11 text
21
+ // runner validates; moving to the v0.11.0 re-exports changes the file sizes and
22
+ // makes every existing download re-fetch. modelBytes are the .pte sizes on the
23
+ // Hub; sizeBytes adds the tokenizer files (~11 MB).
23
24
  const QWEN3_BASE = "https://huggingface.co/software-mansion/react-native-executorch-qwen-3/resolve/v0.10.0";
24
25
  const TOKENIZER_BYTES = 11_431_080;
25
26
  const MB = 1024 * 1024;