@glassly/engine 0.3.8-dev.999 → 0.4.0-beta.1023
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 +11 -0
- package/build/engine.d.ts.map +1 -1
- package/build/facades/ai.d.ts +6 -0
- package/build/facades/ai.d.ts.map +1 -1
- package/build/facades/ai.js +6 -0
- package/build/facades/ai.js.map +1 -1
- package/build/facades/glasses.d.ts +9 -1
- package/build/facades/glasses.d.ts.map +1 -1
- package/build/facades/glasses.js +13 -0
- package/build/facades/glasses.js.map +1 -1
- package/build/generated/releaseMetadata.js +4 -4
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js.map +1 -1
- package/build/services/CloudClientService.d.ts +2 -1
- package/build/services/CloudClientService.d.ts.map +1 -1
- package/build/services/CloudClientService.js +8 -0
- package/build/services/CloudClientService.js.map +1 -1
- package/build/services/DeviceEventRouter.d.ts.map +1 -1
- package/build/services/DeviceEventRouter.js +1 -0
- package/build/services/DeviceEventRouter.js.map +1 -1
- package/build/services/GlassesSensorService.js +1 -1
- package/build/services/GlassesSensorService.js.map +1 -1
- package/build/services/LlmRouting.d.ts +1 -1
- package/build/services/LlmRouting.js.map +1 -1
- package/build/services/LocalLlmModelManager.d.ts +22 -2
- package/build/services/LocalLlmModelManager.d.ts.map +1 -1
- package/build/services/LocalLlmModelManager.js +104 -2
- package/build/services/LocalLlmModelManager.js.map +1 -1
- package/build/services/LocalLlmProvider.d.ts.map +1 -1
- package/build/services/LocalLlmProvider.js +11 -0
- package/build/services/LocalLlmProvider.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts +13 -0
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +61 -5
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/NavigationHandlers.js +1 -1
- package/build/services/NavigationHandlers.js.map +1 -1
- package/build/services/NavigationService.js +6 -6
- package/build/services/NavigationService.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/neuralBand/HandwritingGate.d.ts +38 -0
- package/build/services/neuralBand/HandwritingGate.d.ts.map +1 -0
- package/build/services/neuralBand/HandwritingGate.js +89 -0
- package/build/services/neuralBand/HandwritingGate.js.map +1 -0
- package/build/services/neuralBand/NeuralBandInput.d.ts +12 -1
- package/build/services/neuralBand/NeuralBandInput.d.ts.map +1 -1
- package/build/services/neuralBand/NeuralBandInput.js +27 -0
- package/build/services/neuralBand/NeuralBandInput.js.map +1 -1
- package/build/services/neuralBand/NeuralBandSettingsSync.d.ts.map +1 -1
- package/build/services/neuralBand/NeuralBandSettingsSync.js +36 -3
- package/build/services/neuralBand/NeuralBandSettingsSync.js.map +1 -1
- package/build/stores/appVisibility.d.ts.map +1 -1
- package/build/stores/appVisibility.js +0 -1
- package/build/stores/appVisibility.js.map +1 -1
- package/build/stores/settings.d.ts.map +1 -1
- package/build/stores/settings.js +26 -0
- package/build/stores/settings.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/package.json +7 -7
- package/src/facades/ai.ts +6 -0
- package/src/facades/glasses.ts +17 -0
- package/src/generated/releaseMetadata.ts +4 -4
- package/src/index.ts +1 -0
- package/src/services/CloudClientService.ts +8 -0
- package/src/services/DeviceEventRouter.ts +1 -0
- package/src/services/GlassesSensorService.ts +1 -1
- package/src/services/LlmRouting.ts +1 -1
- package/src/services/LocalLlmModelManager.ts +110 -3
- package/src/services/LocalLlmProvider.ts +8 -0
- package/src/services/LocalMiniappRuntime.ts +66 -5
- package/src/services/NavigationHandlers.ts +1 -1
- package/src/services/NavigationService.ts +6 -6
- package/src/services/controllers.ts +1 -0
- package/src/services/neuralBand/HandwritingGate.ts +111 -0
- package/src/services/neuralBand/NeuralBandInput.ts +37 -1
- package/src/services/neuralBand/NeuralBandSettingsSync.ts +46 -3
- package/src/stores/appVisibility.ts +0 -1
- package/src/stores/settings.ts +26 -0
- package/src/types/enums.ts +1 -0
|
@@ -6,7 +6,12 @@
|
|
|
6
6
|
* latest claim is also kept on its own, since the pairing screen runs before
|
|
7
7
|
* the band's id reaches JS.
|
|
8
8
|
*/
|
|
9
|
-
import type {
|
|
9
|
+
import type {
|
|
10
|
+
NeuralBandClaimEvent,
|
|
11
|
+
NeuralBandFirmwareEvent,
|
|
12
|
+
NeuralBandHandwritingEvent,
|
|
13
|
+
NeuralBandPointerEvent,
|
|
14
|
+
} from "@glassly/bluetooth-sdk"
|
|
10
15
|
import {MiniappStreamType} from "@glassly/miniapp"
|
|
11
16
|
|
|
12
17
|
import type {KeyboardEventPayload} from "../GlassesKeyboardInput"
|
|
@@ -34,6 +39,8 @@ export interface NeuralBandHandwritingUpdate {
|
|
|
34
39
|
status: NeuralBandHandwritingStatus
|
|
35
40
|
}
|
|
36
41
|
|
|
42
|
+
export type NeuralBandFirmwareStatus = Omit<NeuralBandFirmwareEvent, "type" | "controllerId"> & {known: boolean}
|
|
43
|
+
|
|
37
44
|
export interface NeuralBandInputOptions {
|
|
38
45
|
forward?: (stream: string, payload: unknown) => void
|
|
39
46
|
now?: () => number
|
|
@@ -67,13 +74,25 @@ function codeFor(char: string): string {
|
|
|
67
74
|
|
|
68
75
|
const IDLE_CLAIM: NeuralBandClaimStatus = {stage: "idle", sessionExpired: false}
|
|
69
76
|
const IDLE_HANDWRITING: NeuralBandHandwritingStatus = {phase: "idle", message: "", text: ""}
|
|
77
|
+
const IDLE_FIRMWARE: NeuralBandFirmwareStatus = {
|
|
78
|
+
known: false,
|
|
79
|
+
connected: false,
|
|
80
|
+
hasMetaSession: false,
|
|
81
|
+
checked: false,
|
|
82
|
+
updateAvailable: false,
|
|
83
|
+
phase: "idle",
|
|
84
|
+
progress: 0,
|
|
85
|
+
message: "",
|
|
86
|
+
}
|
|
70
87
|
|
|
71
88
|
export class NeuralBandInput {
|
|
72
89
|
private latestClaim: NeuralBandClaimStatus = IDLE_CLAIM
|
|
73
90
|
private claims = new Map<string, NeuralBandClaimStatus>()
|
|
74
91
|
private handwriting = new Map<string, NeuralBandHandwritingStatus>()
|
|
92
|
+
private firmware = new Map<string, NeuralBandFirmwareStatus>()
|
|
75
93
|
private claimListeners = new Set<(status: NeuralBandClaimStatus) => void>()
|
|
76
94
|
private handwritingListeners = new Set<(update: NeuralBandHandwritingUpdate) => void>()
|
|
95
|
+
private firmwareListeners = new Set<(update: {id: string; status: NeuralBandFirmwareStatus}) => void>()
|
|
77
96
|
private readonly forward: (stream: string, payload: unknown) => void
|
|
78
97
|
private readonly now: () => number
|
|
79
98
|
|
|
@@ -102,6 +121,15 @@ export class NeuralBandInput {
|
|
|
102
121
|
return () => this.handwritingListeners.delete(cb)
|
|
103
122
|
}
|
|
104
123
|
|
|
124
|
+
firmwareStatus(controllerId: string): NeuralBandFirmwareStatus {
|
|
125
|
+
return this.firmware.get(controllerId) ?? IDLE_FIRMWARE
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
onFirmwareStatus(cb: (update: {id: string; status: NeuralBandFirmwareStatus}) => void): () => void {
|
|
129
|
+
this.firmwareListeners.add(cb)
|
|
130
|
+
return () => this.firmwareListeners.delete(cb)
|
|
131
|
+
}
|
|
132
|
+
|
|
105
133
|
/** A new pairing attempt starts from a clean slate. */
|
|
106
134
|
resetClaim(): void {
|
|
107
135
|
this.latestClaim = IDLE_CLAIM
|
|
@@ -112,6 +140,14 @@ export class NeuralBandInput {
|
|
|
112
140
|
forget(controllerId: string): void {
|
|
113
141
|
this.claims.delete(controllerId)
|
|
114
142
|
this.handwriting.delete(controllerId)
|
|
143
|
+
this.firmware.delete(controllerId)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
handleFirmware(event: NeuralBandFirmwareEvent): void {
|
|
147
|
+
const {type: _type, controllerId, ...rest} = event
|
|
148
|
+
const status: NeuralBandFirmwareStatus = {...rest, known: true}
|
|
149
|
+
this.firmware.set(controllerId, status)
|
|
150
|
+
for (const cb of this.firmwareListeners) cb({id: controllerId, status})
|
|
115
151
|
}
|
|
116
152
|
|
|
117
153
|
handleClaim(event: NeuralBandClaimEvent): void {
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pushes the Neural Band user settings (air mouse, wearing hand) to
|
|
3
|
-
* connected band: to each band as it connects, and to all of them
|
|
4
|
-
*
|
|
2
|
+
* Pushes the Neural Band user settings (air mouse, wearing hand, vibration) to
|
|
3
|
+
* every connected band: to each band as it connects, and to all of them
|
|
4
|
+
* whenever a setting changes. The native side keeps nothing across
|
|
5
|
+
* connections. Handwriting is gated, not pushed: HandwritingGate runs it while
|
|
6
|
+
* the setting is on and a miniapp has a text field open.
|
|
5
7
|
*/
|
|
6
8
|
import BluetoothSdk from "@glassly/bluetooth-sdk/internal"
|
|
7
9
|
|
|
8
10
|
import {useGlassesStore} from "../../stores/glasses"
|
|
9
11
|
import {SETTINGS, useSettingsStore} from "../../stores/settings"
|
|
10
12
|
import {ControllerTypes} from "../../types/enums"
|
|
13
|
+
import {BgTimer} from "../../utils/timers"
|
|
11
14
|
import {readyControllers} from "../controllers"
|
|
15
|
+
import localMiniappRuntime from "../LocalMiniappRuntime"
|
|
16
|
+
import {HandwritingGate} from "./HandwritingGate"
|
|
17
|
+
import neuralBandInput from "./NeuralBandInput"
|
|
12
18
|
|
|
13
19
|
let unsubscribers: (() => void)[] = []
|
|
20
|
+
let handwriting: HandwritingGate | null = null
|
|
14
21
|
|
|
15
22
|
function connectedBandIds(): string[] {
|
|
16
23
|
return readyControllers(useGlassesStore.getState().controllers)
|
|
@@ -32,10 +39,39 @@ function pushHand(id: string): void {
|
|
|
32
39
|
)
|
|
33
40
|
}
|
|
34
41
|
|
|
42
|
+
function pushVibration(id: string): void {
|
|
43
|
+
const enabled = useSettingsStore.getState().getSetting(SETTINGS.neural_band_vibration.key) !== false
|
|
44
|
+
void BluetoothSdk.neuralBandSetGestureHaptics(id, enabled).catch((err) =>
|
|
45
|
+
console.warn("NeuralBandSettingsSync: vibration push failed:", err),
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function startHandwritingGate(): (() => void)[] {
|
|
50
|
+
const gate = new HandwritingGate({
|
|
51
|
+
enabled: () => useSettingsStore.getState().getSetting(SETTINGS.neural_band_handwriting.key) !== false,
|
|
52
|
+
textFieldOpen: () => localMiniappRuntime.hasOpenTextField(),
|
|
53
|
+
setHandwriting: (id, enabled) => BluetoothSdk.neuralBandSetHandwriting(id, enabled),
|
|
54
|
+
setTimeout: (fn, ms) => BgTimer.setTimeout(fn, ms),
|
|
55
|
+
clearTimeout: (handle) => BgTimer.clearTimeout(handle as number),
|
|
56
|
+
})
|
|
57
|
+
handwriting = gate
|
|
58
|
+
gate.setBands(connectedBandIds())
|
|
59
|
+
return [
|
|
60
|
+
useSettingsStore.subscribe(
|
|
61
|
+
(s) => s.getSetting(SETTINGS.neural_band_handwriting.key),
|
|
62
|
+
() => gate.update(),
|
|
63
|
+
),
|
|
64
|
+
localMiniappRuntime.onTextFieldChange(() => gate.update()),
|
|
65
|
+
neuralBandInput.onHandwritingStatus(({id, status}) => gate.status(id, status.phase)),
|
|
66
|
+
() => gate.dispose(),
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
|
|
35
70
|
export function startNeuralBandSettingsSync(): void {
|
|
36
71
|
if (unsubscribers.length > 0) return
|
|
37
72
|
let connected = new Set(connectedBandIds())
|
|
38
73
|
unsubscribers = [
|
|
74
|
+
...startHandwritingGate(),
|
|
39
75
|
useGlassesStore.subscribe(
|
|
40
76
|
() => connectedBandIds().sort().join(","),
|
|
41
77
|
() => {
|
|
@@ -44,8 +80,10 @@ export function startNeuralBandSettingsSync(): void {
|
|
|
44
80
|
if (connected.has(id)) continue
|
|
45
81
|
pushAirMouse(id)
|
|
46
82
|
pushHand(id)
|
|
83
|
+
pushVibration(id)
|
|
47
84
|
}
|
|
48
85
|
connected = next
|
|
86
|
+
handwriting?.setBands([...next])
|
|
49
87
|
},
|
|
50
88
|
),
|
|
51
89
|
useSettingsStore.subscribe(
|
|
@@ -56,10 +94,15 @@ export function startNeuralBandSettingsSync(): void {
|
|
|
56
94
|
(s) => s.getSetting(SETTINGS.neural_band_hand.key),
|
|
57
95
|
() => connectedBandIds().forEach(pushHand),
|
|
58
96
|
),
|
|
97
|
+
useSettingsStore.subscribe(
|
|
98
|
+
(s) => s.getSetting(SETTINGS.neural_band_vibration.key),
|
|
99
|
+
() => connectedBandIds().forEach(pushVibration),
|
|
100
|
+
),
|
|
59
101
|
]
|
|
60
102
|
}
|
|
61
103
|
|
|
62
104
|
export function stopNeuralBandSettingsSync(): void {
|
|
63
105
|
for (const unsubscribe of unsubscribers) unsubscribe()
|
|
64
106
|
unsubscribers = []
|
|
107
|
+
handwriting = null
|
|
65
108
|
}
|
package/src/stores/settings.ts
CHANGED
|
@@ -848,6 +848,24 @@ export const SETTINGS: Record<string, Setting> = {
|
|
|
848
848
|
saveOnServer: false,
|
|
849
849
|
persist: true,
|
|
850
850
|
},
|
|
851
|
+
// Meta Neural Band handwriting typing into miniapps. Enabled means the band runs
|
|
852
|
+
// its handwriting model while a miniapp has a text field open on the glasses
|
|
853
|
+
// (HandwritingGate); the model streams the whole time it runs, so never otherwise.
|
|
854
|
+
neural_band_handwriting: {
|
|
855
|
+
key: "neural_band_handwriting",
|
|
856
|
+
defaultValue: () => true,
|
|
857
|
+
writable: true,
|
|
858
|
+
saveOnServer: false,
|
|
859
|
+
persist: true,
|
|
860
|
+
},
|
|
861
|
+
// The band's own buzz on each gesture (its haptics pattern 1; pattern 2 is silent).
|
|
862
|
+
neural_band_vibration: {
|
|
863
|
+
key: "neural_band_vibration",
|
|
864
|
+
defaultValue: () => true,
|
|
865
|
+
writable: true,
|
|
866
|
+
saveOnServer: false,
|
|
867
|
+
persist: true,
|
|
868
|
+
},
|
|
851
869
|
// Watch (Apple Watch, Wear OS): draw the glasses' current frame behind the watch
|
|
852
870
|
// trackpad. Frames cross the watch link while the watch app is up, so it stays off
|
|
853
871
|
// unless asked for.
|
|
@@ -970,6 +988,13 @@ export const SETTINGS: Record<string, Setting> = {
|
|
|
970
988
|
saveOnServer: true,
|
|
971
989
|
persist: true,
|
|
972
990
|
},
|
|
991
|
+
dashboard_size: {
|
|
992
|
+
key: "dashboard_size",
|
|
993
|
+
defaultValue: () => 340,
|
|
994
|
+
writable: true,
|
|
995
|
+
saveOnServer: true,
|
|
996
|
+
persist: true,
|
|
997
|
+
},
|
|
973
998
|
menu_apps: {
|
|
974
999
|
key: "menu_apps",
|
|
975
1000
|
defaultValue: () => null,
|
|
@@ -1241,6 +1266,7 @@ export const BLUETOOTH_SETTING_KEYS: string[] = [
|
|
|
1241
1266
|
SETTINGS.auto_brightness.key,
|
|
1242
1267
|
SETTINGS.dashboard_height.key,
|
|
1243
1268
|
SETTINGS.dashboard_depth.key,
|
|
1269
|
+
SETTINGS.dashboard_size.key,
|
|
1244
1270
|
SETTINGS.menu_apps.key,
|
|
1245
1271
|
SETTINGS.calendar_events.key,
|
|
1246
1272
|
SETTINGS.cfw_scene_renderer.key,
|