@glassly/engine 0.4.0-beta.1059 → 0.4.0-beta.1079
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/engine.d.ts +1 -0
- package/build/engine.d.ts.map +1 -1
- package/build/facades/permissions.d.ts.map +1 -1
- package/build/facades/permissions.js +0 -2
- package/build/facades/permissions.js.map +1 -1
- package/build/facades/phoneNotifications.d.ts +7 -0
- package/build/facades/phoneNotifications.d.ts.map +1 -1
- package/build/facades/phoneNotifications.js +6 -0
- package/build/facades/phoneNotifications.js.map +1 -1
- package/build/generated/releaseMetadata.js +3 -3
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js.map +1 -1
- package/build/services/LocalLlmModelManager.d.ts.map +1 -1
- package/build/services/LocalLlmModelManager.js +4 -3
- package/build/services/LocalLlmModelManager.js.map +1 -1
- package/build/services/LocalLlmProvider.d.ts.map +1 -1
- package/build/services/LocalLlmProvider.js +5 -6
- package/build/services/LocalLlmProvider.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts +3 -0
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +67 -1
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/notifications/miniappNotifications.d.ts +31 -0
- package/build/services/notifications/miniappNotifications.d.ts.map +1 -0
- package/build/services/notifications/miniappNotifications.js +24 -0
- package/build/services/notifications/miniappNotifications.js.map +1 -0
- package/build/services/pages/pageEligibility.d.ts +1 -2
- package/build/services/pages/pageEligibility.d.ts.map +1 -1
- package/build/services/pages/pageEligibility.js +4 -2
- package/build/services/pages/pageEligibility.js.map +1 -1
- package/build/services/uiShim.d.ts.map +1 -1
- package/build/services/uiShim.js +14 -0
- package/build/services/uiShim.js.map +1 -1
- package/build/stores/settings.d.ts.map +1 -1
- package/build/stores/settings.js +14 -8
- package/build/stores/settings.js.map +1 -1
- package/build/types/capabilities/nimo.d.ts.map +1 -1
- package/build/types/capabilities/nimo.js +2 -0
- package/build/types/capabilities/nimo.js.map +1 -1
- package/package.json +15 -15
- package/src/facades/permissions.ts +0 -2
- package/src/facades/phoneNotifications.ts +10 -0
- package/src/generated/releaseMetadata.ts +3 -3
- package/src/index.ts +1 -0
- package/src/services/LocalLlmModelManager.ts +4 -3
- package/src/services/LocalLlmProvider.ts +6 -7
- package/src/services/LocalMiniappRuntime.ts +79 -1
- package/src/services/notifications/miniappNotifications.ts +53 -0
- package/src/services/pages/pageEligibility.ts +3 -2
- package/src/services/uiShim.ts +14 -0
- package/src/stores/settings.ts +14 -8
- 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);
|
package/build/engine.d.ts.map
CHANGED
|
@@ -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
|
|
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;
|
|
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;
|
|
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;
|
|
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.
|
|
5
|
-
"releaseSetId": "glassly-0.4.0-beta.
|
|
6
|
-
"sourceCommit": "
|
|
4
|
+
"releaseIdentity": "0.4.0-beta.1079",
|
|
5
|
+
"releaseSetId": "glassly-0.4.0-beta.1079",
|
|
6
|
+
"sourceCommit": "101ebbc475e7b838c66525fc6ab7d61ae2729e83",
|
|
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.
|
|
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.1079\",\n \"releaseSetId\": \"glassly-0.4.0-beta.1079\",\n \"sourceCommit\": \"101ebbc475e7b838c66525fc6ab7d61ae2729e83\",\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";
|
package/build/index.d.ts.map
CHANGED
|
@@ -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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"}
|
package/build/index.js.map
CHANGED
|
@@ -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":"AAAA;;;;;;;;;;GAUG;AAEH,2EAA2E;AAC3E,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAa/B,OAAO,EAAC,uBAAuB,EAAE,iBAAiB,EAAE,eAAe,EAAC,MAAM,wBAAwB,CAAA;AAiBlG,2EAA2E;AAC3E,6EAA6E;AAC7E,yEAAyE;AACzE,qEAAqE;AACrE,kDAAkD;AAClD,OAAO,EAAC,QAAQ,EAAE,UAAU,EAAE,uBAAuB,EAAC,MAAM,mBAAmB,CAAA;AAC/E,OAAO,EAAC,oBAAoB,EAAE,yBAAyB,EAAC,MAAM,kCAAkC,CAAA;AAChG,OAAO,EAAC,wBAAwB,EAAC,MAAM,kCAAkC,CAAA;AACzE,OAAO,EAAC,iBAAiB,EAAE,iBAAiB,EAAC,MAAM,wBAAwB,CAAA;AAE3E,4EAA4E;AAC5E,yEAAyE;AACzE,6EAA6E;AAC7E,OAAO,EAAC,QAAQ,EAAE,kBAAkB,EAAE,gBAAgB,EAAC,MAAM,6BAA6B,CAAA;AAU1F,OAAO,EAAC,uBAAuB,EAAE,iBAAiB,EAAC,MAAM,iCAAiC,CAAA;AAiB1F,OAAO,EAAC,wBAAwB,EAAE,gCAAgC,EAAC,MAAM,+BAA+B,CAAA;AAExG,8CAA8C;AAC9C,OAAO,EAAC,oBAAoB,EAAC,MAAM,kBAAkB,CAAA;AAGrD,2DAA2D;AAC3D,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,sBAAsB,EACtB,mBAAmB,GAGpB,MAAM,6BAA6B,CAAA;AACpC,yEAAyE;AACzE,OAAO,EACL,eAAe,EACf,yBAAyB,GAI1B,MAAM,kCAAkC,CAAA;AAazC,uEAAuE;AACvE,2DAA2D;AAC3D,OAAO,EACL,wBAAwB,EACxB,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,yBAAyB,EACzB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAAC,kBAAkB,EAAC,MAAM,4BAA4B,CAAA;AAW7D,OAAO,EACL,iBAAiB,EACjB,8BAA8B,EAC9B,oBAAoB,EACpB,uBAAuB,EACvB,kCAAkC,EAClC,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,mCAAmC,GACpC,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,2BAA2B,EAC3B,kBAAkB,EAClB,uCAAuC,EACvC,yCAAyC,GAC1C,MAAM,4BAA4B,CAAA;AAMnC,OAAO,EAAC,uBAAuB,EAAC,MAAM,6CAA6C,CAAA;AACnF,OAAO,EAAC,wBAAwB,EAAC,MAAM,wCAAwC,CAAA;AAe/E,+EAA+E;AAC/E,OAAO,EAAC,eAAe,EAAC,MAAM,qBAAqB,CAAA;AAEnD,yEAAyE;AACzE,6CAA6C;AAC7C,OAAO,EACL,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,6BAA6B,EAC7B,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EACtB,OAAO,EACP,QAAQ,EACR,OAAO,EACP,gBAAgB,EAChB,kBAAkB,EAClB,UAAU,EACV,UAAU,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,sBAAsB,EACtB,aAAa,EACb,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAChB,4BAA4B,EAC5B,gBAAgB,GAGjB,MAAM,eAAe,CAAA;AAEtB,4EAA4E;AAC5E,OAAO,EACL,oBAAoB,GAIrB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAC,qBAAqB,EAA2B,MAAM,kBAAkB,CAAA;AAChF,OAAO,EAAC,OAAO,EAAC,MAAM,gBAAgB,CAAA;AACtC,uFAAuF;AACvF,OAAO,EACL,aAAa,EACb,YAAY,EACZ,eAAe,EACf,aAAa,EACb,WAAW,EACX,eAAe,EACf,KAAK,EACL,WAAW,GAGZ,MAAM,gCAAgC,CAAA;AAQvC,0CAA0C;AAC1C,OAAO,EACL,YAAY,EACZ,wBAAwB,EACxB,WAAW,EACX,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,aAAa,GACd,MAAM,SAAS,CAAA","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"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalLlmModelManager.d.ts","sourceRoot":"","sources":["../../src/services/LocalLlmModelManager.ts"],"names":[],"mappings":"AAmBA,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,YAAY,GAAG,UAAU,CAAA;AAEtE,eAAO,MAAM,uBAAuB,EAAE,eAA8B,CAAA;AAEpE,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,eAAe,CAAA;IACnB,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAA;IACb,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAA;IACjB,oFAAoF;IACpF,UAAU,EAAE,MAAM,CAAA;IAClB,yFAAyF;IACzF,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAA;QACb,SAAS,EAAE,MAAM,CAAA;QACjB,eAAe,EAAE,MAAM,CAAA;KACxB,CAAA;CACF;AAED,qGAAqG;AACrG,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,QAAQ,CAAA;AAElF,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,eAAe,CAAA;IACxB,KAAK,EAAE,qBAAqB,CAAA;IAC5B,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;
|
|
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
|
|
21
|
-
//
|
|
22
|
-
//
|
|
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;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalLlmModelManager.js","sourceRoot":"","sources":["../../src/services/LocalLlmModelManager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * LocalLlmModelManager — the on-device LLM model files: a catalog of\n * ExecuTorch exports (Software Mansion's Qwen3 .pte builds on Hugging Face),\n * their download into Documents/llm_models/<id>/, availability checks, and a\n * status stream the Settings > AI Models screen renders. Modelled on\n * STTModelManager; the download itself is RNFS so the Settings screen can\n * list, cancel, and delete models with the same calls the STT rows use.\n *\n * Which model is \"the\" on-device model is the `local_llm_model` setting\n * (Settings > AI Models). Downloads are on demand: the first request that\n * routes on-device without a model present starts one (ensureSelectedModel),\n * and the Settings screen can start one explicitly.\n */\nimport {Platform} from \"react-native\"\nimport * as RNFS from \"@dr.pogodin/react-native-fs\"\n\nimport {SETTINGS, useSettingsStore} from \"../stores/settings\"\nimport {storage} from \"../utils/storage\"\n\nexport type LocalLlmModelId = \"qwen3-0.6b\" | \"qwen3-1.7b\" | \"qwen3-4b\"\n\nexport const DEFAULT_LOCAL_LLM_MODEL: LocalLlmModelId = \"qwen3-1.7b\"\n\nexport interface LocalLlmModelConfig {\n id: LocalLlmModelId\n /** Human label for the Settings dropdown. */\n label: string\n /** Total download size in bytes (the .pte dominates). */\n sizeBytes: number\n /** Exact size of the published .pte; the availability check compares against it. */\n modelBytes: number\n /** Rough resident memory while loaded; `fitsDevice` holds it against the phone's RAM. */\n ramBytes: number\n urls: {\n model: string\n tokenizer: string\n tokenizerConfig: string\n }\n}\n\n/** The three files every model directory holds; names are fixed so paths never depend on the URL. */\nexport interface LocalLlmModelPaths {\n model: string\n tokenizer: string\n tokenizerConfig: string\n}\n\nexport type LocalLlmDownloadStage = \"idle\" | \"downloading\" | \"complete\" | \"failed\"\n\nexport interface LocalLlmDownloadStatus {\n modelId: LocalLlmModelId\n stage: LocalLlmDownloadStage\n /** 0–100, meaningful while stage is \"downloading\". */\n percent: number\n error?: string\n}\n\n// XNNPACK 8da4w exports from software-mansion/react-native-executorch-qwen-3,\n// pinned to the v0.10.0 release tag that react-native-executorch 0.10.x\n// expects. modelBytes are the .pte sizes on the Hub; sizeBytes adds the\n// tokenizer files (~11 MB).\nconst QWEN3_BASE = \"https://huggingface.co/software-mansion/react-native-executorch-qwen-3/resolve/v0.10.0\"\nconst TOKENIZER_BYTES = 11_431_080\nconst MB = 1024 * 1024\nconst GB = 1024 * MB\n\nconst MODELS: Record<LocalLlmModelId, LocalLlmModelConfig> = {\n \"qwen3-0.6b\": {\n id: \"qwen3-0.6b\",\n label: \"Qwen3 0.6B\",\n sizeBytes: 505_686_400 + TOKENIZER_BYTES,\n modelBytes: 505_686_400,\n ramBytes: 0.9 * GB,\n urls: {\n model: `${QWEN3_BASE}/0_6b/xnnpack/qwen_3_0_6b_xnnpack_8da4w.pte`,\n tokenizer: `${QWEN3_BASE}/tokenizer.json`,\n tokenizerConfig: `${QWEN3_BASE}/tokenizer_config.json`,\n },\n },\n \"qwen3-1.7b\": {\n id: \"qwen3-1.7b\",\n label: \"Qwen3 1.7B\",\n sizeBytes: 1_303_738_496 + TOKENIZER_BYTES,\n modelBytes: 1_303_738_496,\n ramBytes: 1.8 * GB,\n urls: {\n model: `${QWEN3_BASE}/1_7b/xnnpack/qwen_3_1_7b_xnnpack_8da4w.pte`,\n tokenizer: `${QWEN3_BASE}/tokenizer.json`,\n tokenizerConfig: `${QWEN3_BASE}/tokenizer_config.json`,\n },\n },\n \"qwen3-4b\": {\n id: \"qwen3-4b\",\n label: \"Qwen3 4B\",\n sizeBytes: 2_681_646_976 + TOKENIZER_BYTES,\n modelBytes: 2_681_646_976,\n ramBytes: 3.4 * GB,\n urls: {\n model: `${QWEN3_BASE}/4b/xnnpack/qwen_3_4b_xnnpack_8da4w.pte`,\n tokenizer: `${QWEN3_BASE}/tokenizer.json`,\n tokenizerConfig: `${QWEN3_BASE}/tokenizer_config.json`,\n },\n },\n}\n\nexport function isLocalLlmModelId(value: unknown): value is LocalLlmModelId {\n return typeof value === \"string\" && value in MODELS\n}\n\n// Without the increased-memory-limit entitlement iOS kills a foreground app\n// at roughly 60% of physical RAM (Android's low-memory killer is no kinder),\n// and the host holds about 1 GB besides the model: JS runtimes, WebViews,\n// the speech model. A 4 GB phone fits the 0.6B model and nothing larger.\nconst APP_MEMORY_SHARE = 0.6\nconst HOST_BASELINE_BYTES = 1 * GB\n\nexport function modelFitsMemory(model: LocalLlmModelConfig, deviceMemoryBytes: number | null): boolean {\n if (!deviceMemoryBytes) return true\n return model.ramBytes + HOST_BASELINE_BYTES <= deviceMemoryBytes * APP_MEMORY_SHARE\n}\n\nlet deviceMemory: number | null | undefined\nfunction deviceMemoryBytes(): number | null {\n if (deviceMemory === undefined) {\n try {\n deviceMemory = (require(\"expo-device\") as {totalMemory?: number | null}).totalMemory ?? null\n } catch {\n deviceMemory = null\n }\n }\n return deviceMemory\n}\n\n// Written before a model's first load and generation, cleared after either\n// ends. A marker still there at the next launch means the OS killed the app\n// mid-load (out of memory), so that model stays off until picked again.\nconst COLD_LOAD_KEY = \"local_llm_cold_load\"\nconst BLOCKED_MODELS_KEY = \"local_llm_blocked_models\"\n\ntype StatusListener = (status: LocalLlmDownloadStatus | null) => void\n\nclass LocalLlmModelManager {\n private static instance: LocalLlmModelManager\n\n private downloadJobId?: number\n private inFlight: {modelId: LocalLlmModelId; promise: Promise<void>} | null = null\n private cancelled = false\n private coldLoadRecovered = false\n private currentStatus: LocalLlmDownloadStatus | null = null\n private listeners = new Set<StatusListener>()\n private modelReadyListeners = new Set<(modelId: LocalLlmModelId) => void>()\n\n private constructor() {}\n\n static getInstance(): LocalLlmModelManager {\n if (!LocalLlmModelManager.instance) {\n LocalLlmModelManager.instance = new LocalLlmModelManager()\n }\n return LocalLlmModelManager.instance\n }\n\n models(): LocalLlmModelConfig[] {\n return Object.values(MODELS)\n }\n\n model(id: LocalLlmModelId): LocalLlmModelConfig {\n return MODELS[id]\n }\n\n /**\n * The model on-device requests use: the Settings > Offline Models pick\n * (garbage resolves to the default) while it is usable, else the largest\n * model that is. With nothing usable it stays the pick, and loading it\n * fails with `unusableReason`.\n */\n selectedModelId(): LocalLlmModelId {\n const raw = useSettingsStore.getState().getSetting(SETTINGS.local_llm_model.key)\n const picked = isLocalLlmModelId(raw) ? raw : DEFAULT_LOCAL_LLM_MODEL\n if (this.isUsable(picked)) return picked\n const fallback = this.models()\n .filter((m) => this.isUsable(m.id))\n .sort((a, b) => b.ramBytes - a.ramBytes)[0]\n return fallback?.id ?? picked\n }\n\n /** Picking a model in Settings is also the way to retry one that crashed the app. */\n async select(id: LocalLlmModelId): Promise<void> {\n this.unblock(id)\n await useSettingsStore.getState().setSetting(SETTINGS.local_llm_model.key, id)\n }\n\n fitsDevice(id: LocalLlmModelId): boolean {\n return modelFitsMemory(MODELS[id], deviceMemoryBytes())\n }\n\n /** The OS killed the app while this model loaded; it stays off until picked again. */\n isBlocked(id: LocalLlmModelId): boolean {\n return this.blockedModelIds().includes(id)\n }\n\n isUsable(id: LocalLlmModelId): boolean {\n return this.fitsDevice(id) && !this.isBlocked(id)\n }\n\n /** Why `id` will not load on this phone, or null when it can. */\n unusableReason(id: LocalLlmModelId): string | null {\n const label = MODELS[id].label\n if (!this.fitsDevice(id)) {\n return `${label} needs more memory than this phone has. Pick a smaller model in Settings > Offline Models.`\n }\n if (this.isBlocked(id)) {\n return `${label} closed the app the last time it loaded. Pick it again in Settings > Offline Models to retry, or pick a smaller model.`\n }\n return null\n }\n\n /** Mark the start of a model's first load and generation in this process. */\n beginColdLoad(id: LocalLlmModelId): void {\n this.recoverColdLoad()\n storage.save(COLD_LOAD_KEY, id)\n }\n\n endColdLoad(): void {\n storage.removeMultiple([COLD_LOAD_KEY])\n }\n\n private blockedModelIds(): LocalLlmModelId[] {\n this.recoverColdLoad()\n const stored = storage.load<unknown>(BLOCKED_MODELS_KEY)\n const ids = stored.is_ok() ? stored.value : []\n return Array.isArray(ids) ? ids.filter(isLocalLlmModelId) : []\n }\n\n private unblock(id: LocalLlmModelId): void {\n const remaining = this.blockedModelIds().filter((blocked) => blocked !== id)\n storage.save(BLOCKED_MODELS_KEY, remaining)\n }\n\n // A cold-load marker left by an earlier process: that load never finished.\n private recoverColdLoad(): void {\n if (this.coldLoadRecovered) return\n this.coldLoadRecovered = true\n const marker = storage.load<unknown>(COLD_LOAD_KEY)\n if (!marker.is_ok() || !isLocalLlmModelId(marker.value)) return\n const id = marker.value\n console.warn(`LOCAL_LLM: the app was killed while ${id} loaded; keeping it off until it is picked again`)\n const stored = storage.load<unknown>(BLOCKED_MODELS_KEY)\n const blocked = stored.is_ok() && Array.isArray(stored.value) ? stored.value.filter(isLocalLlmModelId) : []\n if (!blocked.includes(id)) storage.save(BLOCKED_MODELS_KEY, [...blocked, id])\n storage.removeMultiple([COLD_LOAD_KEY])\n }\n\n getModelDirectory(): string {\n return `${RNFS.DocumentDirectoryPath}/llm_models`\n }\n\n paths(id: LocalLlmModelId = this.selectedModelId()): LocalLlmModelPaths {\n const dir = `${this.getModelDirectory()}/${id}`\n return {\n model: `${dir}/model.pte`,\n tokenizer: `${dir}/tokenizer.json`,\n tokenizerConfig: `${dir}/tokenizer_config.json`,\n }\n }\n\n async isModelAvailable(id: LocalLlmModelId = this.selectedModelId()): Promise<boolean> {\n const paths = this.paths(id)\n try {\n for (const path of [paths.tokenizerConfig, paths.tokenizer, paths.model]) {\n if (!(await RNFS.exists(path))) return false\n }\n // A truncated .pte loads as garbage or crashes the runtime: insist on\n // most of the published size. Downloads land in a .part file and are\n // renamed only once whole, so this only catches external tampering.\n const stat = await RNFS.stat(paths.model)\n return Number(stat.size) >= MODELS[id].modelBytes * 0.95\n } catch (error) {\n console.warn(\"LOCAL_LLM: availability check failed:\", error)\n return false\n }\n }\n\n async downloadedModelIds(): Promise<LocalLlmModelId[]> {\n const ids: LocalLlmModelId[] = []\n for (const id of Object.keys(MODELS) as LocalLlmModelId[]) {\n if (await this.isModelAvailable(id)) ids.push(id)\n }\n return ids\n }\n\n /** Subscribe to download status changes. Fires immediately with the current status. */\n subscribe(listener: StatusListener): () => void {\n this.listeners.add(listener)\n listener(this.currentStatus)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n getStatus(): LocalLlmDownloadStatus | null {\n return this.currentStatus\n }\n\n /** Fired once a model's files are complete on disk. */\n onModelReady(listener: (modelId: LocalLlmModelId) => void): () => void {\n this.modelReadyListeners.add(listener)\n return () => this.modelReadyListeners.delete(listener)\n }\n\n /**\n * True when the selected model is on disk. Otherwise starts (or joins) its\n * download in the background and returns false — the caller reports\n * \"downloading\" rather than waiting out a multi-GB transfer.\n */\n async ensureSelectedModel(): Promise<boolean> {\n const id = this.selectedModelId()\n if (await this.isModelAvailable(id)) return true\n if (!this.fitsDevice(id)) return false\n void this.downloadModel(id).catch((error) => {\n console.warn(`LOCAL_LLM: background download of ${id} failed:`, error)\n })\n return false\n }\n\n /**\n * Download one model (three files, model last). Concurrent calls for the\n * same model share the transfer; a call for a different model waits for\n * the running one — the RNFS job slot is singular.\n */\n async downloadModel(id: LocalLlmModelId = this.selectedModelId()): Promise<void> {\n if (!this.fitsDevice(id)) throw new Error(this.unusableReason(id) ?? `${MODELS[id].label} does not fit this phone.`)\n if (this.inFlight) {\n if (this.inFlight.modelId === id) return this.inFlight.promise\n await this.inFlight.promise.catch(() => undefined)\n }\n const promise = this.downloadInner(id).finally(() => {\n this.inFlight = null\n })\n this.inFlight = {modelId: id, promise}\n return promise\n }\n\n private async downloadInner(id: LocalLlmModelId): Promise<void> {\n const config = MODELS[id]\n const paths = this.paths(id)\n const dir = `${this.getModelDirectory()}/${id}`\n this.cancelled = false\n this.setStatus({modelId: id, stage: \"downloading\", percent: 0})\n\n try {\n await RNFS.mkdir(dir, {NSURLIsExcludedFromBackupKey: true})\n // Tokenizer files first (small), the weights last: a model directory\n // is only \"available\" once model.pte exists, so an interrupted run\n // never leaves a complete-looking directory behind.\n await this.fetchFile(config.urls.tokenizerConfig, paths.tokenizerConfig)\n await this.fetchFile(config.urls.tokenizer, paths.tokenizer)\n await this.fetchFile(config.urls.model, paths.model, (percent) =>\n this.setStatus({modelId: id, stage: \"downloading\", percent}),\n )\n if (!(await this.isModelAvailable(id))) {\n throw new Error(`downloaded model is smaller than the expected ${config.modelBytes} bytes`)\n }\n this.setStatus({modelId: id, stage: \"complete\", percent: 100})\n for (const listener of this.modelReadyListeners) {\n try {\n listener(id)\n } catch (error) {\n console.warn(\"LOCAL_LLM: model-ready listener failed:\", error)\n }\n }\n } catch (error) {\n const message = this.cancelled ? \"download cancelled\" : error instanceof Error ? error.message : String(error)\n this.setStatus({modelId: id, stage: this.cancelled ? \"idle\" : \"failed\", percent: 0, error: message})\n try {\n if (await RNFS.exists(`${paths.model}.part`)) await RNFS.unlink(`${paths.model}.part`)\n } catch (cleanupError) {\n console.warn(\"LOCAL_LLM: partial cleanup failed:\", cleanupError)\n }\n throw error\n } finally {\n this.downloadJobId = undefined\n }\n }\n\n private async fetchFile(url: string, dest: string, onPercent?: (percent: number) => void): Promise<void> {\n if (this.cancelled) throw new Error(\"download cancelled\")\n const partial = `${dest}.part`\n const download = RNFS.downloadFile({\n fromUrl: url,\n toFile: partial,\n // iOS keeps a background URLSession transfer going while the app is\n // suspended; the files here are large enough to need it.\n background: Platform.OS === \"ios\",\n discretionary: false,\n progressDivider: 1,\n connectionTimeout: 30_000,\n readTimeout: 60_000,\n progress: (res) => {\n if (!onPercent || res.contentLength <= 0) return\n onPercent(Math.min(99, Math.floor((res.bytesWritten / res.contentLength) * 100)))\n },\n })\n this.downloadJobId = download.jobId\n const result = await download.promise\n if (result.statusCode !== 200) {\n throw new Error(`download failed with status ${result.statusCode}`)\n }\n if (await RNFS.exists(dest)) await RNFS.unlink(dest)\n await RNFS.moveFile(partial, dest)\n }\n\n async cancelDownload(): Promise<void> {\n if (this.downloadJobId === undefined) return\n this.cancelled = true\n await RNFS.stopDownload(this.downloadJobId)\n this.downloadJobId = undefined\n }\n\n async deleteModel(id: LocalLlmModelId = this.selectedModelId()): Promise<void> {\n const dir = `${this.getModelDirectory()}/${id}`\n if (await RNFS.exists(dir)) await RNFS.unlink(dir)\n if (this.currentStatus?.modelId === id) this.setStatus(null)\n }\n\n private setStatus(status: LocalLlmDownloadStatus | null): void {\n this.currentStatus = status\n for (const listener of this.listeners) {\n try {\n listener(status)\n } catch (error) {\n console.warn(\"LOCAL_LLM: status listener threw:\", error)\n }\n }\n }\n\n static formatBytes(bytes: number): string {\n if (bytes >= GB) return `${(bytes / GB).toFixed(1)} GB`\n return `${Math.round(bytes / MB)} MB`\n }\n}\n\nconst instance = LocalLlmModelManager.getInstance()\nexport {LocalLlmModelManager}\nexport default instance\n"]}
|
|
1
|
+
{"version":3,"file":"LocalLlmModelManager.js","sourceRoot":"","sources":["../../src/services/LocalLlmModelManager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * LocalLlmModelManager — the on-device LLM model files: a catalog of\n * ExecuTorch exports (Software Mansion's Qwen3 .pte builds on Hugging Face),\n * their download into Documents/llm_models/<id>/, availability checks, and a\n * status stream the Settings > AI Models screen renders. Modelled on\n * STTModelManager; the download itself is RNFS so the Settings screen can\n * list, cancel, and delete models with the same calls the STT rows use.\n *\n * Which model is \"the\" on-device model is the `local_llm_model` setting\n * (Settings > AI Models). Downloads are on demand: the first request that\n * routes on-device without a model present starts one (ensureSelectedModel),\n * and the Settings screen can start one explicitly.\n */\nimport {Platform} from \"react-native\"\nimport * as RNFS from \"@dr.pogodin/react-native-fs\"\n\nimport {SETTINGS, useSettingsStore} from \"../stores/settings\"\nimport {storage} from \"../utils/storage\"\n\nexport type LocalLlmModelId = \"qwen3-0.6b\" | \"qwen3-1.7b\" | \"qwen3-4b\"\n\nexport const DEFAULT_LOCAL_LLM_MODEL: LocalLlmModelId = \"qwen3-1.7b\"\n\nexport interface LocalLlmModelConfig {\n id: LocalLlmModelId\n /** Human label for the Settings dropdown. */\n label: string\n /** Total download size in bytes (the .pte dominates). */\n sizeBytes: number\n /** Exact size of the published .pte; the availability check compares against it. */\n modelBytes: number\n /** Rough resident memory while loaded; `fitsDevice` holds it against the phone's RAM. */\n ramBytes: number\n urls: {\n model: string\n tokenizer: string\n tokenizerConfig: string\n }\n}\n\n/** The three files every model directory holds; names are fixed so paths never depend on the URL. */\nexport interface LocalLlmModelPaths {\n model: string\n tokenizer: string\n tokenizerConfig: string\n}\n\nexport type LocalLlmDownloadStage = \"idle\" | \"downloading\" | \"complete\" | \"failed\"\n\nexport interface LocalLlmDownloadStatus {\n modelId: LocalLlmModelId\n stage: LocalLlmDownloadStage\n /** 0–100, meaningful while stage is \"downloading\". */\n percent: number\n error?: string\n}\n\n// XNNPACK 8da4w exports from software-mansion/react-native-executorch-qwen-3,\n// pinned to the v0.10.0 release tag. They export every method the 0.11 text\n// runner validates; moving to the v0.11.0 re-exports changes the file sizes and\n// makes every existing download re-fetch. modelBytes are the .pte sizes on the\n// Hub; sizeBytes adds the tokenizer files (~11 MB).\nconst QWEN3_BASE = \"https://huggingface.co/software-mansion/react-native-executorch-qwen-3/resolve/v0.10.0\"\nconst TOKENIZER_BYTES = 11_431_080\nconst MB = 1024 * 1024\nconst GB = 1024 * MB\n\nconst MODELS: Record<LocalLlmModelId, LocalLlmModelConfig> = {\n \"qwen3-0.6b\": {\n id: \"qwen3-0.6b\",\n label: \"Qwen3 0.6B\",\n sizeBytes: 505_686_400 + TOKENIZER_BYTES,\n modelBytes: 505_686_400,\n ramBytes: 0.9 * GB,\n urls: {\n model: `${QWEN3_BASE}/0_6b/xnnpack/qwen_3_0_6b_xnnpack_8da4w.pte`,\n tokenizer: `${QWEN3_BASE}/tokenizer.json`,\n tokenizerConfig: `${QWEN3_BASE}/tokenizer_config.json`,\n },\n },\n \"qwen3-1.7b\": {\n id: \"qwen3-1.7b\",\n label: \"Qwen3 1.7B\",\n sizeBytes: 1_303_738_496 + TOKENIZER_BYTES,\n modelBytes: 1_303_738_496,\n ramBytes: 1.8 * GB,\n urls: {\n model: `${QWEN3_BASE}/1_7b/xnnpack/qwen_3_1_7b_xnnpack_8da4w.pte`,\n tokenizer: `${QWEN3_BASE}/tokenizer.json`,\n tokenizerConfig: `${QWEN3_BASE}/tokenizer_config.json`,\n },\n },\n \"qwen3-4b\": {\n id: \"qwen3-4b\",\n label: \"Qwen3 4B\",\n sizeBytes: 2_681_646_976 + TOKENIZER_BYTES,\n modelBytes: 2_681_646_976,\n ramBytes: 3.4 * GB,\n urls: {\n model: `${QWEN3_BASE}/4b/xnnpack/qwen_3_4b_xnnpack_8da4w.pte`,\n tokenizer: `${QWEN3_BASE}/tokenizer.json`,\n tokenizerConfig: `${QWEN3_BASE}/tokenizer_config.json`,\n },\n },\n}\n\nexport function isLocalLlmModelId(value: unknown): value is LocalLlmModelId {\n return typeof value === \"string\" && value in MODELS\n}\n\n// Without the increased-memory-limit entitlement iOS kills a foreground app\n// at roughly 60% of physical RAM (Android's low-memory killer is no kinder),\n// and the host holds about 1 GB besides the model: JS runtimes, WebViews,\n// the speech model. A 4 GB phone fits the 0.6B model and nothing larger.\nconst APP_MEMORY_SHARE = 0.6\nconst HOST_BASELINE_BYTES = 1 * GB\n\nexport function modelFitsMemory(model: LocalLlmModelConfig, deviceMemoryBytes: number | null): boolean {\n if (!deviceMemoryBytes) return true\n return model.ramBytes + HOST_BASELINE_BYTES <= deviceMemoryBytes * APP_MEMORY_SHARE\n}\n\nlet deviceMemory: number | null | undefined\nfunction deviceMemoryBytes(): number | null {\n if (deviceMemory === undefined) {\n try {\n deviceMemory = (require(\"expo-device\") as {totalMemory?: number | null}).totalMemory ?? null\n } catch {\n deviceMemory = null\n }\n }\n return deviceMemory\n}\n\n// Written before a model's first load and generation, cleared after either\n// ends. A marker still there at the next launch means the OS killed the app\n// mid-load (out of memory), so that model stays off until picked again.\nconst COLD_LOAD_KEY = \"local_llm_cold_load\"\nconst BLOCKED_MODELS_KEY = \"local_llm_blocked_models\"\n\ntype StatusListener = (status: LocalLlmDownloadStatus | null) => void\n\nclass LocalLlmModelManager {\n private static instance: LocalLlmModelManager\n\n private downloadJobId?: number\n private inFlight: {modelId: LocalLlmModelId; promise: Promise<void>} | null = null\n private cancelled = false\n private coldLoadRecovered = false\n private currentStatus: LocalLlmDownloadStatus | null = null\n private listeners = new Set<StatusListener>()\n private modelReadyListeners = new Set<(modelId: LocalLlmModelId) => void>()\n\n private constructor() {}\n\n static getInstance(): LocalLlmModelManager {\n if (!LocalLlmModelManager.instance) {\n LocalLlmModelManager.instance = new LocalLlmModelManager()\n }\n return LocalLlmModelManager.instance\n }\n\n models(): LocalLlmModelConfig[] {\n return Object.values(MODELS)\n }\n\n model(id: LocalLlmModelId): LocalLlmModelConfig {\n return MODELS[id]\n }\n\n /**\n * The model on-device requests use: the Settings > Offline Models pick\n * (garbage resolves to the default) while it is usable, else the largest\n * model that is. With nothing usable it stays the pick, and loading it\n * fails with `unusableReason`.\n */\n selectedModelId(): LocalLlmModelId {\n const raw = useSettingsStore.getState().getSetting(SETTINGS.local_llm_model.key)\n const picked = isLocalLlmModelId(raw) ? raw : DEFAULT_LOCAL_LLM_MODEL\n if (this.isUsable(picked)) return picked\n const fallback = this.models()\n .filter((m) => this.isUsable(m.id))\n .sort((a, b) => b.ramBytes - a.ramBytes)[0]\n return fallback?.id ?? picked\n }\n\n /** Picking a model in Settings is also the way to retry one that crashed the app. */\n async select(id: LocalLlmModelId): Promise<void> {\n this.unblock(id)\n await useSettingsStore.getState().setSetting(SETTINGS.local_llm_model.key, id)\n }\n\n fitsDevice(id: LocalLlmModelId): boolean {\n return modelFitsMemory(MODELS[id], deviceMemoryBytes())\n }\n\n /** The OS killed the app while this model loaded; it stays off until picked again. */\n isBlocked(id: LocalLlmModelId): boolean {\n return this.blockedModelIds().includes(id)\n }\n\n isUsable(id: LocalLlmModelId): boolean {\n return this.fitsDevice(id) && !this.isBlocked(id)\n }\n\n /** Why `id` will not load on this phone, or null when it can. */\n unusableReason(id: LocalLlmModelId): string | null {\n const label = MODELS[id].label\n if (!this.fitsDevice(id)) {\n return `${label} needs more memory than this phone has. Pick a smaller model in Settings > Offline Models.`\n }\n if (this.isBlocked(id)) {\n return `${label} closed the app the last time it loaded. Pick it again in Settings > Offline Models to retry, or pick a smaller model.`\n }\n return null\n }\n\n /** Mark the start of a model's first load and generation in this process. */\n beginColdLoad(id: LocalLlmModelId): void {\n this.recoverColdLoad()\n storage.save(COLD_LOAD_KEY, id)\n }\n\n endColdLoad(): void {\n storage.removeMultiple([COLD_LOAD_KEY])\n }\n\n private blockedModelIds(): LocalLlmModelId[] {\n this.recoverColdLoad()\n const stored = storage.load<unknown>(BLOCKED_MODELS_KEY)\n const ids = stored.is_ok() ? stored.value : []\n return Array.isArray(ids) ? ids.filter(isLocalLlmModelId) : []\n }\n\n private unblock(id: LocalLlmModelId): void {\n const remaining = this.blockedModelIds().filter((blocked) => blocked !== id)\n storage.save(BLOCKED_MODELS_KEY, remaining)\n }\n\n // A cold-load marker left by an earlier process: that load never finished.\n private recoverColdLoad(): void {\n if (this.coldLoadRecovered) return\n this.coldLoadRecovered = true\n const marker = storage.load<unknown>(COLD_LOAD_KEY)\n if (!marker.is_ok() || !isLocalLlmModelId(marker.value)) return\n const id = marker.value\n console.warn(`LOCAL_LLM: the app was killed while ${id} loaded; keeping it off until it is picked again`)\n const stored = storage.load<unknown>(BLOCKED_MODELS_KEY)\n const blocked = stored.is_ok() && Array.isArray(stored.value) ? stored.value.filter(isLocalLlmModelId) : []\n if (!blocked.includes(id)) storage.save(BLOCKED_MODELS_KEY, [...blocked, id])\n storage.removeMultiple([COLD_LOAD_KEY])\n }\n\n getModelDirectory(): string {\n return `${RNFS.DocumentDirectoryPath}/llm_models`\n }\n\n paths(id: LocalLlmModelId = this.selectedModelId()): LocalLlmModelPaths {\n const dir = `${this.getModelDirectory()}/${id}`\n return {\n model: `${dir}/model.pte`,\n tokenizer: `${dir}/tokenizer.json`,\n tokenizerConfig: `${dir}/tokenizer_config.json`,\n }\n }\n\n async isModelAvailable(id: LocalLlmModelId = this.selectedModelId()): Promise<boolean> {\n const paths = this.paths(id)\n try {\n for (const path of [paths.tokenizerConfig, paths.tokenizer, paths.model]) {\n if (!(await RNFS.exists(path))) return false\n }\n // A truncated .pte loads as garbage or crashes the runtime: insist on\n // most of the published size. Downloads land in a .part file and are\n // renamed only once whole, so this only catches external tampering.\n const stat = await RNFS.stat(paths.model)\n return Number(stat.size) >= MODELS[id].modelBytes * 0.95\n } catch (error) {\n console.warn(\"LOCAL_LLM: availability check failed:\", error)\n return false\n }\n }\n\n async downloadedModelIds(): Promise<LocalLlmModelId[]> {\n const ids: LocalLlmModelId[] = []\n for (const id of Object.keys(MODELS) as LocalLlmModelId[]) {\n if (await this.isModelAvailable(id)) ids.push(id)\n }\n return ids\n }\n\n /** Subscribe to download status changes. Fires immediately with the current status. */\n subscribe(listener: StatusListener): () => void {\n this.listeners.add(listener)\n listener(this.currentStatus)\n return () => {\n this.listeners.delete(listener)\n }\n }\n\n getStatus(): LocalLlmDownloadStatus | null {\n return this.currentStatus\n }\n\n /** Fired once a model's files are complete on disk. */\n onModelReady(listener: (modelId: LocalLlmModelId) => void): () => void {\n this.modelReadyListeners.add(listener)\n return () => this.modelReadyListeners.delete(listener)\n }\n\n /**\n * True when the selected model is on disk. Otherwise starts (or joins) its\n * download in the background and returns false — the caller reports\n * \"downloading\" rather than waiting out a multi-GB transfer.\n */\n async ensureSelectedModel(): Promise<boolean> {\n const id = this.selectedModelId()\n if (await this.isModelAvailable(id)) return true\n if (!this.fitsDevice(id)) return false\n void this.downloadModel(id).catch((error) => {\n console.warn(`LOCAL_LLM: background download of ${id} failed:`, error)\n })\n return false\n }\n\n /**\n * Download one model (three files, model last). Concurrent calls for the\n * same model share the transfer; a call for a different model waits for\n * the running one — the RNFS job slot is singular.\n */\n async downloadModel(id: LocalLlmModelId = this.selectedModelId()): Promise<void> {\n if (!this.fitsDevice(id)) throw new Error(this.unusableReason(id) ?? `${MODELS[id].label} does not fit this phone.`)\n if (this.inFlight) {\n if (this.inFlight.modelId === id) return this.inFlight.promise\n await this.inFlight.promise.catch(() => undefined)\n }\n const promise = this.downloadInner(id).finally(() => {\n this.inFlight = null\n })\n this.inFlight = {modelId: id, promise}\n return promise\n }\n\n private async downloadInner(id: LocalLlmModelId): Promise<void> {\n const config = MODELS[id]\n const paths = this.paths(id)\n const dir = `${this.getModelDirectory()}/${id}`\n this.cancelled = false\n this.setStatus({modelId: id, stage: \"downloading\", percent: 0})\n\n try {\n await RNFS.mkdir(dir, {NSURLIsExcludedFromBackupKey: true})\n // Tokenizer files first (small), the weights last: a model directory\n // is only \"available\" once model.pte exists, so an interrupted run\n // never leaves a complete-looking directory behind.\n await this.fetchFile(config.urls.tokenizerConfig, paths.tokenizerConfig)\n await this.fetchFile(config.urls.tokenizer, paths.tokenizer)\n await this.fetchFile(config.urls.model, paths.model, (percent) =>\n this.setStatus({modelId: id, stage: \"downloading\", percent}),\n )\n if (!(await this.isModelAvailable(id))) {\n throw new Error(`downloaded model is smaller than the expected ${config.modelBytes} bytes`)\n }\n this.setStatus({modelId: id, stage: \"complete\", percent: 100})\n for (const listener of this.modelReadyListeners) {\n try {\n listener(id)\n } catch (error) {\n console.warn(\"LOCAL_LLM: model-ready listener failed:\", error)\n }\n }\n } catch (error) {\n const message = this.cancelled ? \"download cancelled\" : error instanceof Error ? error.message : String(error)\n this.setStatus({modelId: id, stage: this.cancelled ? \"idle\" : \"failed\", percent: 0, error: message})\n try {\n if (await RNFS.exists(`${paths.model}.part`)) await RNFS.unlink(`${paths.model}.part`)\n } catch (cleanupError) {\n console.warn(\"LOCAL_LLM: partial cleanup failed:\", cleanupError)\n }\n throw error\n } finally {\n this.downloadJobId = undefined\n }\n }\n\n private async fetchFile(url: string, dest: string, onPercent?: (percent: number) => void): Promise<void> {\n if (this.cancelled) throw new Error(\"download cancelled\")\n const partial = `${dest}.part`\n const download = RNFS.downloadFile({\n fromUrl: url,\n toFile: partial,\n // iOS keeps a background URLSession transfer going while the app is\n // suspended; the files here are large enough to need it.\n background: Platform.OS === \"ios\",\n discretionary: false,\n progressDivider: 1,\n connectionTimeout: 30_000,\n readTimeout: 60_000,\n progress: (res) => {\n if (!onPercent || res.contentLength <= 0) return\n onPercent(Math.min(99, Math.floor((res.bytesWritten / res.contentLength) * 100)))\n },\n })\n this.downloadJobId = download.jobId\n const result = await download.promise\n if (result.statusCode !== 200) {\n throw new Error(`download failed with status ${result.statusCode}`)\n }\n if (await RNFS.exists(dest)) await RNFS.unlink(dest)\n await RNFS.moveFile(partial, dest)\n }\n\n async cancelDownload(): Promise<void> {\n if (this.downloadJobId === undefined) return\n this.cancelled = true\n await RNFS.stopDownload(this.downloadJobId)\n this.downloadJobId = undefined\n }\n\n async deleteModel(id: LocalLlmModelId = this.selectedModelId()): Promise<void> {\n const dir = `${this.getModelDirectory()}/${id}`\n if (await RNFS.exists(dir)) await RNFS.unlink(dir)\n if (this.currentStatus?.modelId === id) this.setStatus(null)\n }\n\n private setStatus(status: LocalLlmDownloadStatus | null): void {\n this.currentStatus = status\n for (const listener of this.listeners) {\n try {\n listener(status)\n } catch (error) {\n console.warn(\"LOCAL_LLM: status listener threw:\", error)\n }\n }\n }\n\n static formatBytes(bytes: number): string {\n if (bytes >= GB) return `${(bytes / GB).toFixed(1)} GB`\n return `${Math.round(bytes / MB)} MB`\n }\n}\n\nconst instance = LocalLlmModelManager.getInstance()\nexport {LocalLlmModelManager}\nexport default instance\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalLlmProvider.d.ts","sourceRoot":"","sources":["../../src/services/LocalLlmProvider.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,6BAA6B,CAAA;AAEnE,OAA6B,EAAC,KAAK,eAAe,EAAC,MAAM,wBAAwB,CAAA;AACjF,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,kBAAkB,CAAA;AA6CzB,MAAM,WAAW,sBAAuB,SAAQ,eAAe;IAC7D,OAAO,EAAE,eAAe,CAAA;CACzB;AA0BD,cAAM,gBAAgB;IACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkB;IAEzC,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,GAAG,CAAmB;IAE9B,OAAO;IAUP,MAAM,CAAC,WAAW,IAAI,gBAAgB;IAKtC,mFAAmF;IACnF,QAAQ,IAAI,OAAO;IAInB,aAAa,IAAI,eAAe,GAAG,IAAI;IAIvC,oGAAoG;IACpG,QAAQ,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAqBtE,kGAAkG;IAC5F,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAe7B,yEAAyE;IACzE,OAAO,CAAC,aAAa;YAaP,aAAa;YAyEb,YAAY;YAgBZ,IAAI;
|
|
1
|
+
{"version":3,"file":"LocalLlmProvider.d.ts","sourceRoot":"","sources":["../../src/services/LocalLlmProvider.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,6BAA6B,CAAA;AAEnE,OAA6B,EAAC,KAAK,eAAe,EAAC,MAAM,wBAAwB,CAAA;AACjF,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,kBAAkB,CAAA;AA6CzB,MAAM,WAAW,sBAAuB,SAAQ,eAAe;IAC7D,OAAO,EAAE,eAAe,CAAA;CACzB;AA0BD,cAAM,gBAAgB;IACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkB;IAEzC,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,KAAK,CAAsC;IACnD,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,GAAG,CAAmB;IAE9B,OAAO;IAUP,MAAM,CAAC,WAAW,IAAI,gBAAgB;IAKtC,mFAAmF;IACnF,QAAQ,IAAI,OAAO;IAInB,aAAa,IAAI,eAAe,GAAG,IAAI;IAIvC,oGAAoG;IACpG,QAAQ,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAqBtE,kGAAkG;IAC5F,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAe7B,yEAAyE;IACzE,OAAO,CAAC,aAAa;YAaP,aAAa;YAyEb,YAAY;YAgBZ,IAAI;YA0CJ,OAAO;IASrB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,cAAc;CAMvB;AAED,QAAA,MAAM,gBAAgB,kBAAiC,CAAA;AACvD,OAAO,EAAC,gBAAgB,EAAC,CAAA;AACzB,eAAe,gBAAgB,CAAA"}
|
|
@@ -165,12 +165,12 @@ class LocalLlmProvider {
|
|
|
165
165
|
BgTimer.clearTimeout(deadline);
|
|
166
166
|
}
|
|
167
167
|
const elapsedMs = Date.now() - startedAt;
|
|
168
|
-
console.log(`${LOG_TAG}: ${model.modelId} prompt=${generated.stats.
|
|
168
|
+
console.log(`${LOG_TAG}: ${model.modelId} prompt=${generated.stats.prefill.numTokens} out=${generated.stats.numTokens} tokens in ${elapsedMs} ms`);
|
|
169
169
|
const seed = `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`;
|
|
170
170
|
const completion = finalizeLocalResult({
|
|
171
171
|
text: generated.text,
|
|
172
|
-
promptTokens: generated.stats.
|
|
173
|
-
generatedTokens: generated.stats.
|
|
172
|
+
promptTokens: generated.stats.prefill.numTokens,
|
|
173
|
+
generatedTokens: generated.stats.numTokens,
|
|
174
174
|
maxNewTokens,
|
|
175
175
|
}, { jsonMode, toolsOffered: Boolean(tools), makeToolCallId: (index) => `local_${seed}_${index}` });
|
|
176
176
|
return { ...completion, modelId: model.modelId };
|
|
@@ -212,11 +212,10 @@ class LocalLlmProvider {
|
|
|
212
212
|
const tokenizerConfig = rne.llm.parseTokenizerConfig(JSON.parse(await RNFS.readFile(paths.tokenizerConfig, "utf8")));
|
|
213
213
|
const template = new Template(tokenizerConfig.chatTemplate);
|
|
214
214
|
const startedAt = Date.now();
|
|
215
|
-
const
|
|
216
|
-
const runner = await createRunner(paths.model, paths.tokenizer, []);
|
|
215
|
+
const runner = await rne.llm.createLLMRunner(paths.model, paths.tokenizer, []);
|
|
217
216
|
let tokenizer;
|
|
218
217
|
try {
|
|
219
|
-
const maxSeqLen = runner.getKVCacheState().
|
|
218
|
+
const maxSeqLen = runner.getKVCacheState().maxContextLen;
|
|
220
219
|
if (!Number.isInteger(maxSeqLen) || maxSeqLen <= CONTEXT_MARGIN_TOKENS + 16) {
|
|
221
220
|
throw new Error(`On-device model ${modelId} reported an invalid context size: ${maxSeqLen}`);
|
|
222
221
|
}
|