@glassly/engine 0.4.0 → 0.4.1-dev.1137
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 +3 -1
- package/build/engine.d.ts.map +1 -1
- package/build/engine.js +6 -4
- package/build/engine.js.map +1 -1
- package/build/facades/display.d.ts +1 -1
- package/build/facades/display.d.ts.map +1 -1
- package/build/facades/display.js +1 -1
- package/build/facades/display.js.map +1 -1
- package/build/facades/glasses.js +1 -1
- package/build/facades/glasses.js.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/facades/providerKeys.d.ts +1 -1
- package/build/facades/providerKeys.js +1 -1
- package/build/facades/providerKeys.js.map +1 -1
- package/build/facades/reports.d.ts +15 -0
- package/build/facades/reports.d.ts.map +1 -1
- package/build/facades/reports.js +37 -0
- package/build/facades/reports.js.map +1 -1
- package/build/facades/settings.js +1 -1
- package/build/facades/settings.js.map +1 -1
- package/build/generated/releaseMetadata.js +4 -4
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts +2 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/react/useMentraLiveOta.d.ts.map +1 -1
- package/build/react/useMentraLiveOta.js.map +1 -1
- package/build/runtime/config.d.ts.map +1 -1
- package/build/runtime/config.js.map +1 -1
- package/build/services/AiTierResolution.d.ts +1 -1
- package/build/services/AiTierResolution.d.ts.map +1 -1
- package/build/services/AiTierResolution.js.map +1 -1
- package/build/services/AppRegistry.d.ts +12 -1
- package/build/services/AppRegistry.d.ts.map +1 -1
- package/build/services/AppRegistry.js +33 -0
- package/build/services/AppRegistry.js.map +1 -1
- package/build/services/AutomaticReportResult.d.ts.map +1 -1
- package/build/services/AutomaticReportResult.js.map +1 -1
- package/build/services/CloudClientService.d.ts +7 -5
- package/build/services/CloudClientService.d.ts.map +1 -1
- package/build/services/CloudClientService.js +17 -14
- package/build/services/CloudClientService.js.map +1 -1
- package/build/services/DisplayProcessor.d.ts.map +1 -1
- package/build/services/DisplayProcessor.js +2 -1
- package/build/services/DisplayProcessor.js.map +1 -1
- package/build/services/GestureDotsService.js +1 -1
- package/build/services/GestureDotsService.js.map +1 -1
- package/build/services/HotspotOtaTransport.d.ts.map +1 -1
- package/build/services/HotspotOtaTransport.js +0 -1
- package/build/services/HotspotOtaTransport.js.map +1 -1
- package/build/services/JSRouter.js +2 -2
- package/build/services/JSRouter.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 +10 -3
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +142 -30
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
- package/build/services/NativeNavigationService.d.ts.map +1 -1
- package/build/services/NativeNavigationService.js.map +1 -1
- package/build/services/NavigationHandlers.d.ts +1 -1
- package/build/services/NavigationHandlers.js +2 -2
- package/build/services/NavigationHandlers.js.map +1 -1
- package/build/services/NavigationService.d.ts +2 -2
- package/build/services/NavigationService.d.ts.map +1 -1
- package/build/services/NavigationService.js +11 -11
- package/build/services/NavigationService.js.map +1 -1
- package/build/services/PairingIdentity.d.ts.map +1 -1
- package/build/services/PairingIdentity.js.map +1 -1
- package/build/services/PhoneCalendarService.d.ts.map +1 -1
- package/build/services/PhoneCalendarService.js.map +1 -1
- package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
- package/build/services/PhoneNotificationsSync.js +2 -1
- package/build/services/PhoneNotificationsSync.js.map +1 -1
- package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
- package/build/services/PhoneStreamCoordinator.js.map +1 -1
- package/build/services/ProviderKeyValidation.d.ts +1 -1
- package/build/services/ProviderKeyValidation.js +1 -1
- package/build/services/ProviderKeyValidation.js.map +1 -1
- package/build/services/STTModelManager.d.ts.map +1 -1
- package/build/services/STTModelManager.js +1 -6
- package/build/services/STTModelManager.js.map +1 -1
- package/build/services/SupportProfileSync.d.ts.map +1 -1
- package/build/services/SupportProfileSync.js +3 -0
- package/build/services/SupportProfileSync.js.map +1 -1
- package/build/services/TranscriptionRouting.d.ts +3 -0
- package/build/services/TranscriptionRouting.d.ts.map +1 -1
- package/build/services/TranscriptionRouting.js +14 -0
- package/build/services/TranscriptionRouting.js.map +1 -1
- package/build/services/UIRouter.d.ts.map +1 -1
- package/build/services/UIRouter.js.map +1 -1
- package/build/services/controllers.d.ts.map +1 -1
- package/build/services/controllers.js +1 -0
- package/build/services/controllers.js.map +1 -1
- package/build/services/effectiveCapabilities.js +3 -2
- package/build/services/effectiveCapabilities.js.map +1 -1
- package/build/services/gestureDotGlyphs.d.ts.map +1 -1
- package/build/services/gestureDotGlyphs.js.map +1 -1
- package/build/services/manifestActions.d.ts.map +1 -1
- package/build/services/manifestActions.js.map +1 -1
- package/build/services/neuralBand/MetaAuth.d.ts +1 -0
- package/build/services/neuralBand/MetaAuth.d.ts.map +1 -1
- package/build/services/neuralBand/MetaAuth.js +36 -8
- package/build/services/neuralBand/MetaAuth.js.map +1 -1
- package/build/services/notificationAppPayload.d.ts +14 -0
- package/build/services/notificationAppPayload.d.ts.map +1 -0
- package/build/services/notificationAppPayload.js +15 -0
- package/build/services/notificationAppPayload.js.map +1 -0
- 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/settingsBridge.d.ts.map +1 -1
- package/build/services/settingsBridge.js +0 -2
- package/build/services/settingsBridge.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/appVisibility.d.ts.map +1 -1
- package/build/stores/appVisibility.js.map +1 -1
- package/build/stores/gallerySync.d.ts.map +1 -1
- package/build/stores/gallerySync.js.map +1 -1
- package/build/stores/glasses.d.ts.map +1 -1
- package/build/stores/glasses.js +1 -0
- package/build/stores/glasses.js.map +1 -1
- package/build/stores/settings.d.ts.map +1 -1
- package/build/stores/settings.js +27 -28
- package/build/stores/settings.js.map +1 -1
- package/build/types/capabilities/even-realities-g1.d.ts.map +1 -1
- package/build/types/capabilities/even-realities-g1.js +4 -0
- package/build/types/capabilities/even-realities-g1.js.map +1 -1
- package/build/types/capabilities/nimo.d.ts.map +1 -1
- package/build/types/capabilities/nimo.js +21 -7
- package/build/types/capabilities/nimo.js.map +1 -1
- package/build/types/enums.d.ts +2 -1
- package/build/types/enums.d.ts.map +1 -1
- package/build/types/enums.js +1 -0
- package/build/types/enums.js.map +1 -1
- package/build/utils/display/index.d.ts +1 -0
- package/build/utils/display/index.d.ts.map +1 -1
- package/build/utils/display/index.js +2 -2
- package/build/utils/display/index.js.map +1 -1
- package/build/utils/display/profiles/index.d.ts +1 -0
- package/build/utils/display/profiles/index.d.ts.map +1 -1
- package/build/utils/display/profiles/index.js +1 -0
- package/build/utils/display/profiles/index.js.map +1 -1
- package/build/utils/display/profiles/nimo.d.ts +2 -0
- package/build/utils/display/profiles/nimo.d.ts.map +1 -0
- package/build/utils/display/profiles/nimo.js +3 -0
- package/build/utils/display/profiles/nimo.js.map +1 -0
- package/build/utils/display/scene/svgPath.js.map +1 -1
- package/build/utils/memory/search.d.ts.map +1 -1
- package/build/utils/memory/search.js +17 -7
- package/build/utils/memory/search.js.map +1 -1
- package/package.json +15 -15
- package/src/engine.ts +9 -7
- package/src/facades/display.ts +1 -1
- package/src/facades/glasses.ts +1 -1
- package/src/facades/permissions.ts +0 -2
- package/src/facades/phoneNotifications.ts +10 -0
- package/src/facades/providerKeys.ts +1 -1
- package/src/facades/reports.ts +41 -0
- package/src/facades/settings.ts +1 -1
- package/src/generated/releaseMetadata.ts +4 -4
- package/src/index.ts +2 -0
- package/src/react/useMentraLiveOta.ts +1 -4
- package/src/runtime/config.ts +1 -6
- package/src/services/AiTierResolution.ts +1 -1
- package/src/services/AppRegistry.ts +38 -1
- package/src/services/AutomaticReportResult.ts +1 -3
- package/src/services/CloudClientService.ts +17 -11
- package/src/services/DisplayProcessor.ts +2 -0
- package/src/services/GestureDotsService.ts +1 -1
- package/src/services/HotspotOtaTransport.ts +1 -5
- package/src/services/JSRouter.ts +2 -2
- package/src/services/LocalLlmModelManager.ts +4 -3
- package/src/services/LocalLlmProvider.ts +6 -7
- package/src/services/LocalMiniappRuntime.ts +170 -40
- package/src/services/LocalSttFallbackCoordinator.ts +1 -5
- package/src/services/NativeNavigationService.ts +1 -2
- package/src/services/NavigationHandlers.ts +2 -2
- package/src/services/NavigationService.ts +12 -11
- package/src/services/PairingIdentity.ts +1 -3
- package/src/services/PhoneCalendarService.ts +1 -3
- package/src/services/PhoneNotificationsSync.ts +2 -1
- package/src/services/PhoneStreamCoordinator.ts +1 -2
- package/src/services/ProviderKeyValidation.ts +1 -1
- package/src/services/STTModelManager.ts +1 -6
- package/src/services/SupportProfileSync.ts +2 -0
- package/src/services/TranscriptionRouting.ts +18 -0
- package/src/services/UIRouter.ts +3 -9
- package/src/services/controllers.ts +1 -0
- package/src/services/effectiveCapabilities.ts +3 -2
- package/src/services/gestureDotGlyphs.ts +10 -5
- package/src/services/manifestActions.ts +2 -1
- package/src/services/neuralBand/MetaAuth.ts +37 -8
- package/src/services/notificationAppPayload.ts +15 -0
- package/src/services/notifications/miniappNotifications.ts +53 -0
- package/src/services/pages/pageEligibility.ts +3 -2
- package/src/services/settingsBridge.ts +1 -4
- package/src/services/uiShim.ts +14 -0
- package/src/stores/appVisibility.ts +2 -5
- package/src/stores/gallerySync.ts +1 -7
- package/src/stores/glasses.ts +1 -0
- package/src/stores/settings.ts +27 -28
- package/src/types/capabilities/even-realities-g1.ts +5 -0
- package/src/types/capabilities/nimo.ts +23 -7
- package/src/types/enums.ts +1 -0
- package/src/utils/display/index.ts +2 -2
- package/src/utils/display/profiles/index.ts +2 -0
- package/src/utils/display/profiles/nimo.ts +2 -0
- package/src/utils/display/scene/svgPath.ts +1 -1
- package/src/utils/memory/search.ts +17 -7
|
@@ -23,6 +23,9 @@ import {
|
|
|
23
23
|
nativeNotificationsSupported,
|
|
24
24
|
uploadPhoneNotification,
|
|
25
25
|
} from "../services/PhoneNotificationsSync"
|
|
26
|
+
import {onMiniappNotification, type MiniappNotificationEvent} from "../services/notifications/miniappNotifications"
|
|
27
|
+
|
|
28
|
+
export type {MiniappNotificationEvent} from "../services/notifications/miniappNotifications"
|
|
26
29
|
|
|
27
30
|
export const phoneNotifications = {
|
|
28
31
|
/**
|
|
@@ -65,6 +68,13 @@ export const phoneNotifications = {
|
|
|
65
68
|
* surface runs and draw only when the answer is `host`.
|
|
66
69
|
*/
|
|
67
70
|
presentationOwner: currentPresentationOwner,
|
|
71
|
+
/**
|
|
72
|
+
* Notifications miniapps post and dismiss. Hosts feed them to the same
|
|
73
|
+
* fan-out as the phone's, marked `system: false` with `source` set.
|
|
74
|
+
*/
|
|
75
|
+
onMiniappNotification: (listener: (event: MiniappNotificationEvent) => void): (() => void) =>
|
|
76
|
+
onMiniappNotification(listener),
|
|
77
|
+
|
|
68
78
|
/** Hand a captured notification to firmware that presents uploaded content (owner `firmware`, Android). */
|
|
69
79
|
uploadToGlasses: (event: PhoneNotificationEvent): Promise<void> => uploadPhoneNotification(event),
|
|
70
80
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* providerKeys facade — `engine.providerKeys.{anthropic,gemini,openai,deepseek,elevenlabs}`:
|
|
3
3
|
* validate-before-save probes for the user-supplied AI/voice provider keys
|
|
4
|
-
* (Settings > API Keys). Same per-provider shape as `engine.maps.mapbox` /
|
|
4
|
+
* (Settings > Privacy > API Keys). Same per-provider shape as `engine.maps.mapbox` /
|
|
5
5
|
* `engine.speech.sonioxDirect` so the Keys screen treats providers uniformly.
|
|
6
6
|
*/
|
|
7
7
|
import {
|
package/src/facades/reports.ts
CHANGED
|
@@ -169,10 +169,51 @@ async function submitReportInternal(input: InternalSubmitReportInput): Promise<R
|
|
|
169
169
|
return {status: "submitted", reportId, reportStatus}
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
+
/** A debug-console log upload: the report it went to, and whether it replaced an earlier upload. */
|
|
173
|
+
export type LogUploadResult =
|
|
174
|
+
| {status: "created" | "updated"; reportId: string}
|
|
175
|
+
| {status: "busy"}
|
|
176
|
+
| {status: "failed"; error: string}
|
|
177
|
+
|
|
178
|
+
/** Uploads within this window after a report's creation replace its phone logs. */
|
|
179
|
+
export const LOG_UPLOAD_WINDOW_MS = 5 * 60_000
|
|
180
|
+
let logUpload: {reportId: string; createdAt: number} | null = null
|
|
181
|
+
let logUploadInFlight = false
|
|
182
|
+
|
|
183
|
+
/** Phone logs only, as a manual bug report; repeated taps cannot spam reports. */
|
|
184
|
+
async function uploadLogs(): Promise<LogUploadResult> {
|
|
185
|
+
if (logUploadInFlight) return {status: "busy"}
|
|
186
|
+
logUploadInFlight = true
|
|
187
|
+
try {
|
|
188
|
+
const logs = logBuffer.getRecentLogs()
|
|
189
|
+
const now = Date.now()
|
|
190
|
+
if (logUpload && now - logUpload.createdAt < LOG_UPLOAD_WINDOW_MS) {
|
|
191
|
+
await cloudClientService.core.reports.addLogs(logUpload.reportId, "phone", logs, {replace: true})
|
|
192
|
+
return {status: "updated", reportId: logUpload.reportId}
|
|
193
|
+
}
|
|
194
|
+
const context = await collectDiagnosticContext()
|
|
195
|
+
const res = await cloudClientService.core.reports.submit({
|
|
196
|
+
kind: "bug",
|
|
197
|
+
trigger: {type: "manual", source: "debug_console", reason: "log_upload"},
|
|
198
|
+
report: {actualBehavior: "Debug console log upload"},
|
|
199
|
+
context,
|
|
200
|
+
})
|
|
201
|
+
logUpload = {reportId: res.reportId, createdAt: now}
|
|
202
|
+
if (logs.length > 0) await cloudClientService.core.reports.addLogs(res.reportId, "phone", logs)
|
|
203
|
+
await cloudClientService.core.reports.complete(res.reportId)
|
|
204
|
+
return {status: "created", reportId: res.reportId}
|
|
205
|
+
} catch (error) {
|
|
206
|
+
return {status: "failed", error: error instanceof Error ? error.message : String(error)}
|
|
207
|
+
} finally {
|
|
208
|
+
logUploadInFlight = false
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
172
212
|
export const reports = {
|
|
173
213
|
submit(input: EngineSubmitReportInput): Promise<ReportSubmitResult> {
|
|
174
214
|
return submitReportInternal(input)
|
|
175
215
|
},
|
|
216
|
+
uploadLogs,
|
|
176
217
|
}
|
|
177
218
|
|
|
178
219
|
export function submitAutomaticReport(input: EngineSubmitAutomaticReportInput): Promise<ReportSubmitResult> {
|
package/src/facades/settings.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* settings facade — `engine.settings`: the typed keyed user-settings surface over
|
|
3
3
|
* the engine-owned settings store. This is the OEM contract.
|
|
4
4
|
*
|
|
5
|
-
* Keys + their schema live in `SETTINGS` (theme, devMode,
|
|
5
|
+
* Keys + their schema live in `SETTINGS` (theme, devMode, metric_system,
|
|
6
6
|
* notifications, onboarding flags, …); `descriptor(key)`/`keys()` expose them.
|
|
7
7
|
*/
|
|
8
8
|
import {useSettingsStore, SETTINGS} from "../stores/settings"
|
|
@@ -11,10 +11,10 @@ export interface EngineReleaseMetadata {
|
|
|
11
11
|
|
|
12
12
|
export const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({
|
|
13
13
|
"schemaVersion": 1,
|
|
14
|
-
"familyBaseVersion": "0.4.
|
|
15
|
-
"releaseIdentity": "0.4.
|
|
16
|
-
"releaseSetId": "glassly-0.4.
|
|
17
|
-
"sourceCommit": "
|
|
14
|
+
"familyBaseVersion": "0.4.1",
|
|
15
|
+
"releaseIdentity": "0.4.1-dev.1137",
|
|
16
|
+
"releaseSetId": "glassly-0.4.1-dev.1137",
|
|
17
|
+
"sourceCommit": "71bec7fa9156ff40639ef61147d437c9f8db3c07",
|
|
18
18
|
"otaManifestUrl": null,
|
|
19
19
|
"otaManifestSha256": null
|
|
20
20
|
})
|
package/src/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ export type {
|
|
|
23
23
|
} from "./facades/reports"
|
|
24
24
|
export type {IslandNotification, IslandNotificationKind} from "./facades/notifications"
|
|
25
25
|
export type {PresentationOwner} from "./services/notifications/notificationPolicy"
|
|
26
|
+
export type {MiniappNotificationEvent} from "./services/notifications/miniappNotifications"
|
|
26
27
|
export {DEFAULT_HIDDEN_PACKAGES, isGatedByDevTools, isSystemMiniapp} from "./stores/appVisibility"
|
|
27
28
|
export type {WifiSearchResult} from "./facades/glassesWifi"
|
|
28
29
|
export type {IdentitySnapshot} from "./services/PairingIdentity"
|
|
@@ -230,6 +231,7 @@ export {
|
|
|
230
231
|
authEntryUrl,
|
|
231
232
|
callbackMatches,
|
|
232
233
|
callbackQuery,
|
|
234
|
+
callbackShape,
|
|
233
235
|
decryptBlob,
|
|
234
236
|
isLoginCallback,
|
|
235
237
|
login,
|
|
@@ -48,10 +48,7 @@ export type MentraLiveOtaScreen =
|
|
|
48
48
|
| "disconnected"
|
|
49
49
|
|
|
50
50
|
export type MentraLiveOtaErrorCode =
|
|
51
|
-
| "
|
|
52
|
-
| "update_info_unavailable"
|
|
53
|
-
| "install_failed"
|
|
54
|
-
| "bes_restart_required"
|
|
51
|
+
"check_failed" | "update_info_unavailable" | "install_failed" | "bes_restart_required"
|
|
55
52
|
|
|
56
53
|
export type MentraLiveOtaError = {
|
|
57
54
|
code: MentraLiveOtaErrorCode
|
package/src/runtime/config.ts
CHANGED
|
@@ -66,12 +66,7 @@ export type NavErrorEvent = {kind: "error"; message: string}
|
|
|
66
66
|
/** Synthesized by the host when the trip is cancelled outside the miniapp (e.g. wearer exited nav mode on the glasses). */
|
|
67
67
|
export type NavCancelledEvent = {kind: "cancelled"; reason?: string}
|
|
68
68
|
export type NavUpdate =
|
|
69
|
-
|
|
|
70
|
-
| NavOffRouteEvent
|
|
71
|
-
| NavReroutingEvent
|
|
72
|
-
| NavArrivedEvent
|
|
73
|
-
| NavErrorEvent
|
|
74
|
-
| NavCancelledEvent
|
|
69
|
+
NavManeuverEvent | NavOffRouteEvent | NavReroutingEvent | NavArrivedEvent | NavErrorEvent | NavCancelledEvent
|
|
75
70
|
|
|
76
71
|
export type NavLocation = {
|
|
77
72
|
lat: number
|
|
@@ -51,7 +51,7 @@ export const TIER_MODEL_OPTIONS: Record<AiTier, TierModelOption[]> = {
|
|
|
51
51
|
],
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
/** Which providers currently have a user key saved (Settings > API Keys). */
|
|
54
|
+
/** Which providers currently have a user key saved (Settings > Privacy > API Keys). */
|
|
55
55
|
export type SavedLlmKeys = Record<AiTierProvider, boolean>
|
|
56
56
|
|
|
57
57
|
/**
|
|
@@ -143,12 +143,19 @@ interface InstalledLma {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
export interface MiniappReleaseIdentity {
|
|
146
|
-
source: "direct_download" | "bundled_asset" | "preinstalled_registry" | "dev_snapshot" | "store"
|
|
146
|
+
source: "direct_download" | "bundled_asset" | "preinstalled_registry" | "dev_snapshot" | "store" | "sideload"
|
|
147
147
|
releaseId?: string
|
|
148
148
|
bundleSha256?: string
|
|
149
149
|
channel?: string
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
export interface MiniappZipManifest {
|
|
153
|
+
packageName: string
|
|
154
|
+
version: string
|
|
155
|
+
name: string
|
|
156
|
+
permissions: Array<{type: string; required?: boolean}>
|
|
157
|
+
}
|
|
158
|
+
|
|
152
159
|
function releaseIdentityKey(packageName: string, version: string): string {
|
|
153
160
|
return `miniapp_release_identity:${packageName}:${version}`
|
|
154
161
|
}
|
|
@@ -480,6 +487,36 @@ class AppRegistry {
|
|
|
480
487
|
})
|
|
481
488
|
}
|
|
482
489
|
|
|
490
|
+
/** Reads miniapp.json out of a local zip without installing anything. */
|
|
491
|
+
public inspectLocalZip(zipPath: string): AsyncResult<MiniappZipManifest, Error> {
|
|
492
|
+
return Res.try_async(async () => {
|
|
493
|
+
const peekDir = new Directory(Paths.cache, "lma_peek")
|
|
494
|
+
if (peekDir.exists) peekDir.delete()
|
|
495
|
+
peekDir.create()
|
|
496
|
+
try {
|
|
497
|
+
await unzip(zipPath, peekDir.uri)
|
|
498
|
+
const manifestFile = new File(peekDir, "miniapp.json")
|
|
499
|
+
if (!manifestFile.exists) throw new Error("miniapp.json missing at zip root")
|
|
500
|
+
const manifest = JSON.parse(manifestFile.textSync()) as Record<string, unknown>
|
|
501
|
+
const {packageName, version, name} = manifest
|
|
502
|
+
if (typeof packageName !== "string" || !packageName) throw new Error("miniapp.json missing packageName")
|
|
503
|
+
if (typeof version !== "string" || !version) throw new Error("miniapp.json missing version")
|
|
504
|
+
const permissions = Array.isArray(manifest.permissions)
|
|
505
|
+
? manifest.permissions.filter(
|
|
506
|
+
(entry): entry is {type: string; required?: boolean} => typeof entry?.type === "string",
|
|
507
|
+
)
|
|
508
|
+
: []
|
|
509
|
+
return {packageName, version, name: typeof name === "string" && name ? name : packageName, permissions}
|
|
510
|
+
} finally {
|
|
511
|
+
try {
|
|
512
|
+
peekDir.delete()
|
|
513
|
+
} catch {
|
|
514
|
+
// cache only
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
})
|
|
518
|
+
}
|
|
519
|
+
|
|
483
520
|
/**
|
|
484
521
|
* Post-install bookkeeping shared by every install path: clear stale dev
|
|
485
522
|
* artifacts on release installs, point the active-version at the just-
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type {ReportSubmitResult} from "../facades/reports"
|
|
2
2
|
|
|
3
3
|
export type AutomaticReportSubmissionStatus =
|
|
4
|
-
|
|
5
|
-
| {status: "skipped"; reason: string}
|
|
6
|
-
| {status: "failed"; error: string}
|
|
4
|
+
{status: "filed"; reportId: string} | {status: "skipped"; reason: string} | {status: "failed"; error: string}
|
|
7
5
|
|
|
8
6
|
export function toAutomaticReportSubmissionStatus(result: ReportSubmitResult): AutomaticReportSubmissionStatus {
|
|
9
7
|
if (result.status === "submitted") {
|
|
@@ -20,6 +20,7 @@ import type {
|
|
|
20
20
|
StoreCatalogResponse,
|
|
21
21
|
StoreListing,
|
|
22
22
|
StoreReleasesResponse,
|
|
23
|
+
StoreHostOptions,
|
|
23
24
|
} from "@glassly/cloud-client/react-native"
|
|
24
25
|
import type {SubjectTokenType} from "@glassly/cloud-client"
|
|
25
26
|
import {AppState, Platform} from "react-native"
|
|
@@ -190,9 +191,16 @@ function resolveEndpoints(): {core: string; runtime: string} {
|
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
193
|
|
|
194
|
+
// Via init(), never construct(): init() holds the disable-cloud gate, and a
|
|
195
|
+
// client built past it opens the runtime socket and retries it forever.
|
|
196
|
+
function requireClient(): CloudClient {
|
|
197
|
+
if (!client) cloudClientService.init()
|
|
198
|
+
if (!client) throw new Error("Glassly cloud is disabled")
|
|
199
|
+
return client
|
|
200
|
+
}
|
|
201
|
+
|
|
193
202
|
function getCoreClient(): CloudCore {
|
|
194
|
-
|
|
195
|
-
const core = client?.core
|
|
203
|
+
const core = requireClient().core
|
|
196
204
|
if (!core) throw new Error("cloud client core not configured")
|
|
197
205
|
return core
|
|
198
206
|
}
|
|
@@ -207,9 +215,7 @@ function syncCoreAccessTokenToBluetooth(): Promise<string> {
|
|
|
207
215
|
}
|
|
208
216
|
|
|
209
217
|
async function syncCoreAccessTokenToBluetoothInternal(): Promise<string> {
|
|
210
|
-
|
|
211
|
-
const c = client
|
|
212
|
-
if (!c) throw new Error("cloud client not initialized")
|
|
218
|
+
const c = requireClient()
|
|
213
219
|
|
|
214
220
|
const token = await c.auth.getCoreToken()
|
|
215
221
|
if (c !== client) {
|
|
@@ -765,25 +771,25 @@ export const cloudClientService = {
|
|
|
765
771
|
return c.core.miniapps.getRegistry()
|
|
766
772
|
},
|
|
767
773
|
|
|
768
|
-
async getStoreCatalog(): Promise<StoreCatalogResponse> {
|
|
774
|
+
async getStoreCatalog(opts?: StoreHostOptions): Promise<StoreCatalogResponse> {
|
|
769
775
|
if (!client) this.init()
|
|
770
776
|
const c = client
|
|
771
777
|
if (!c?.core) throw new Error("cloud client core is unavailable")
|
|
772
|
-
return c.core.store.list()
|
|
778
|
+
return c.core.store.list(opts)
|
|
773
779
|
},
|
|
774
780
|
|
|
775
|
-
async getStoreListing(packageName: string): Promise<StoreListing> {
|
|
781
|
+
async getStoreListing(packageName: string, opts?: StoreHostOptions): Promise<StoreListing> {
|
|
776
782
|
if (!client) this.init()
|
|
777
783
|
const c = client
|
|
778
784
|
if (!c?.core) throw new Error("cloud client core is unavailable")
|
|
779
|
-
return c.core.store.get(packageName)
|
|
785
|
+
return c.core.store.get(packageName, opts)
|
|
780
786
|
},
|
|
781
787
|
|
|
782
|
-
async getStoreReleases(packageName: string): Promise<StoreReleasesResponse> {
|
|
788
|
+
async getStoreReleases(packageName: string, opts?: StoreHostOptions): Promise<StoreReleasesResponse> {
|
|
783
789
|
if (!client) this.init()
|
|
784
790
|
const c = client
|
|
785
791
|
if (!c?.core) throw new Error("cloud client core is unavailable")
|
|
786
|
-
return c.core.store.releases(packageName)
|
|
792
|
+
return c.core.store.releases(packageName, opts)
|
|
787
793
|
},
|
|
788
794
|
|
|
789
795
|
/** Bytes of a store icon or screenshot; these routes need the user Bearer. */
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
NEX_PROFILE,
|
|
22
22
|
RAYNEO_IO_PROFILE,
|
|
23
23
|
MEMOMIND_ONE_PROFILE,
|
|
24
|
+
NIMO_PROFILE,
|
|
24
25
|
RAYNEO_IO_CFW_PROFILE,
|
|
25
26
|
TextMeasurer,
|
|
26
27
|
TextWrapper,
|
|
@@ -206,6 +207,7 @@ const DEVICE_PROFILES: Partial<Record<DeviceTypes, DisplayProfile>> = {
|
|
|
206
207
|
[DeviceTypes.MACH1]: Z100_PROFILE, // Mach1 uses same hardware as Vuzix Z100
|
|
207
208
|
[DeviceTypes.RAYNEO_IO]: RAYNEO_IO_PROFILE,
|
|
208
209
|
[DeviceTypes.MEMOMIND_ONE]: MEMOMIND_ONE_PROFILE,
|
|
210
|
+
[DeviceTypes.NIMO]: NIMO_PROFILE,
|
|
209
211
|
}
|
|
210
212
|
|
|
211
213
|
/**
|
|
@@ -50,7 +50,7 @@ const MIDDLE_FINGER_GLYPHS: Partial<Record<GestureDotGlyph, GestureDotGlyph>> =
|
|
|
50
50
|
|
|
51
51
|
/** `glyph` as `finger` draws it: the middle finger's shapes are hollow. */
|
|
52
52
|
function fingerGlyph(glyph: GestureDotGlyph, finger: number): GestureDotGlyph {
|
|
53
|
-
return finger === 1 ? MIDDLE_FINGER_GLYPHS[glyph] ?? glyph : glyph
|
|
53
|
+
return finger === 1 ? (MIDDLE_FINGER_GLYPHS[glyph] ?? glyph) : glyph
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
function fingerKey(controllerId: string | undefined, finger: number): string {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import BluetoothSdk, {isEnabledHotspotStatus} from "@glassly/bluetooth-sdk"
|
|
2
2
|
import {otaServer} from "@glassly/bluetooth-sdk/ota-transport"
|
|
3
3
|
// One coordinator selects the native Android or iOS staging implementation at runtime.
|
|
4
|
-
// eslint-disable-next-line react-native/split-platform-components
|
|
5
4
|
import {PermissionsAndroid, Platform} from "react-native"
|
|
6
5
|
import type {OtaCheckCurrentGlassesResult} from "./OtaUpdateCheckService"
|
|
7
6
|
import {
|
|
@@ -24,10 +23,7 @@ export type HotspotOtaProgress = {
|
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
export type HotspotOtaErrorCode =
|
|
27
|
-
| "
|
|
28
|
-
| "hotspot_start_failed"
|
|
29
|
-
| "hotspot_join_failed"
|
|
30
|
-
| "hotspot_server_failed"
|
|
26
|
+
"hotspot_wifi_permission_denied" | "hotspot_start_failed" | "hotspot_join_failed" | "hotspot_server_failed"
|
|
31
27
|
|
|
32
28
|
export class HotspotOtaTransportError extends Error {
|
|
33
29
|
constructor(
|
package/src/services/JSRouter.ts
CHANGED
|
@@ -381,6 +381,8 @@ export class JSRouter {
|
|
|
381
381
|
BgTimer.clearTimeout(pending)
|
|
382
382
|
this.respawnTimers.delete(packageName)
|
|
383
383
|
}
|
|
384
|
+
miniappRunningRegistry.remove(packageName)
|
|
385
|
+
this.runtime.releaseWidgetHost(packageName)
|
|
384
386
|
await this.runtime.notifyWillDisconnect(packageName, "stopped")
|
|
385
387
|
this.spawnCache.delete(packageName)
|
|
386
388
|
this.crashController?.onKill(packageName)
|
|
@@ -388,8 +390,6 @@ export class JSRouter {
|
|
|
388
390
|
// drop out of native nav mode (crash-respawns don't take this path).
|
|
389
391
|
this.runtime.unregisterApp(packageName, {endNavigation: true})
|
|
390
392
|
this.registered.delete(packageName)
|
|
391
|
-
// JSContext torn down → miniapp is no longer "running".
|
|
392
|
-
miniappRunningRegistry.remove(packageName)
|
|
393
393
|
if (this.crust.jsKill) {
|
|
394
394
|
try {
|
|
395
395
|
await this.crust.jsKill(packageName)
|
|
@@ -56,9 +56,10 @@ export interface LocalLlmDownloadStatus {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// XNNPACK 8da4w exports from software-mansion/react-native-executorch-qwen-3,
|
|
59
|
-
// pinned to the v0.10.0 release tag
|
|
60
|
-
//
|
|
61
|
-
//
|
|
59
|
+
// pinned to the v0.10.0 release tag. They export every method the 0.11 text
|
|
60
|
+
// runner validates; moving to the v0.11.0 re-exports changes the file sizes and
|
|
61
|
+
// makes every existing download re-fetch. modelBytes are the .pte sizes on the
|
|
62
|
+
// Hub; sizeBytes adds the tokenizer files (~11 MB).
|
|
62
63
|
const QWEN3_BASE = "https://huggingface.co/software-mansion/react-native-executorch-qwen-3/resolve/v0.10.0"
|
|
63
64
|
const TOKENIZER_BYTES = 11_431_080
|
|
64
65
|
const MB = 1024 * 1024
|
|
@@ -33,7 +33,7 @@ type Rne = typeof import("react-native-executorch")
|
|
|
33
33
|
// The runner API lives on the `llm` namespace; derive its types from there so
|
|
34
34
|
// the import stays a type-only reference (no native module at load time).
|
|
35
35
|
type Tokenizer = ReturnType<Rne["nlp"]["loadTokenizer"]>
|
|
36
|
-
type LLMRunner = ReturnType<Rne["llm"]["createLLMRunner"]
|
|
36
|
+
type LLMRunner = Awaited<ReturnType<Rne["llm"]["createLLMRunner"]>>
|
|
37
37
|
type LLMGenerationStats = ReturnType<LLMRunner["generate"]>
|
|
38
38
|
type LLMGenerationConfig = NonNullable<Parameters<LLMRunner["generate"]>[1]>
|
|
39
39
|
|
|
@@ -238,15 +238,15 @@ class LocalLlmProvider {
|
|
|
238
238
|
|
|
239
239
|
const elapsedMs = Date.now() - startedAt
|
|
240
240
|
console.log(
|
|
241
|
-
`${LOG_TAG}: ${model.modelId} prompt=${generated.stats.
|
|
241
|
+
`${LOG_TAG}: ${model.modelId} prompt=${generated.stats.prefill.numTokens} out=${generated.stats.numTokens} tokens in ${elapsedMs} ms`,
|
|
242
242
|
)
|
|
243
243
|
|
|
244
244
|
const seed = `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`
|
|
245
245
|
const completion = finalizeLocalResult(
|
|
246
246
|
{
|
|
247
247
|
text: generated.text,
|
|
248
|
-
promptTokens: generated.stats.
|
|
249
|
-
generatedTokens: generated.stats.
|
|
248
|
+
promptTokens: generated.stats.prefill.numTokens,
|
|
249
|
+
generatedTokens: generated.stats.numTokens,
|
|
250
250
|
maxNewTokens,
|
|
251
251
|
},
|
|
252
252
|
{jsonMode, toolsOffered: Boolean(tools), makeToolCallId: (index) => `local_${seed}_${index}`},
|
|
@@ -290,11 +290,10 @@ class LocalLlmProvider {
|
|
|
290
290
|
const template = new Template(tokenizerConfig.chatTemplate)
|
|
291
291
|
|
|
292
292
|
const startedAt = Date.now()
|
|
293
|
-
const
|
|
294
|
-
const runner = await createRunner(paths.model, paths.tokenizer, [])
|
|
293
|
+
const runner = await rne.llm.createLLMRunner(paths.model, paths.tokenizer, [])
|
|
295
294
|
let tokenizer: Tokenizer | undefined
|
|
296
295
|
try {
|
|
297
|
-
const maxSeqLen = runner.getKVCacheState().
|
|
296
|
+
const maxSeqLen = runner.getKVCacheState().maxContextLen
|
|
298
297
|
if (!Number.isInteger(maxSeqLen) || maxSeqLen <= CONTEXT_MARGIN_TOKENS + 16) {
|
|
299
298
|
throw new Error(`On-device model ${modelId} reported an invalid context size: ${maxSeqLen}`)
|
|
300
299
|
}
|