@glassly/engine 0.3.8-dev.1004 → 0.3.8-dev.1006
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 +9 -0
- package/build/engine.d.ts.map +1 -1
- package/build/facades/glasses.d.ts +10 -1
- package/build/facades/glasses.d.ts.map +1 -1
- package/build/facades/glasses.js +14 -0
- package/build/facades/glasses.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 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.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/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/package.json +7 -7
- package/src/facades/glasses.ts +18 -0
- package/src/generated/releaseMetadata.ts +3 -3
- package/src/index.ts +1 -0
- package/src/services/DeviceEventRouter.ts +1 -0
- package/src/services/neuralBand/NeuralBandInput.ts +37 -1
package/build/engine.d.ts
CHANGED
|
@@ -83,6 +83,15 @@ export declare const engine: {
|
|
|
83
83
|
onHandwritingStatus: (cb: (update: import(".").NeuralBandHandwritingUpdate) => void) => (() => void);
|
|
84
84
|
setPointer: (id: string, enabled: boolean) => Promise<void>;
|
|
85
85
|
setHand: (id: string, hand: "left" | "right") => Promise<void>;
|
|
86
|
+
firmwareStatus: (id: string) => import(".").NeuralBandFirmwareStatus;
|
|
87
|
+
onFirmwareStatus: (cb: (update: {
|
|
88
|
+
id: string;
|
|
89
|
+
status: import(".").NeuralBandFirmwareStatus;
|
|
90
|
+
}) => void) => (() => void);
|
|
91
|
+
refreshFirmware: (id: string) => Promise<import(".").NeuralBandFirmwareStatus>;
|
|
92
|
+
requestFirmwareStatus: (id: string) => Promise<void>;
|
|
93
|
+
checkFirmware: (id: string) => Promise<void>;
|
|
94
|
+
updateFirmware: (id: string, mode: "update" | "cancel" | "key" | "send" | "trial" | "install") => Promise<void>;
|
|
86
95
|
};
|
|
87
96
|
watch: {
|
|
88
97
|
availability: () => Promise<import("@glassly/bluetooth-sdk").WatchAvailability>;
|
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;;IAyG7C;;yCAEqC
|
|
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;;IAyG7C;;yCAEqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAoCrC,kEAAkE;;;;;;;;;;;;;;;;;;;;IAElE,wEAAwE;;;;;;;;IAExE,sEAAsE;;;;;;;;;;;;IAEtE,qFAAqF;;;;gBA3IpE,CAAC;mBAAiB,CAAC;;;gBAMlC,CAFF;mBAAiB,CAAC;;;;;;;;;;;;;;;;;IAyIlB,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;;;;;+BArKjE,CAAC;;;+BAUiC,CAAC;;;;;;;;;;;;IA6JpD,mFAAmF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGpF,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { WatchAvailability, ButtonPressEvent, ConnectOptions, ControllerStatus, Device, KeyboardAdvertEvent, KeyboardPairingEvent, PairedController, TouchEvent } from "@glassly/bluetooth-sdk";
|
|
2
|
-
import { type NeuralBandClaimStatus, type NeuralBandHandwritingStatus, type NeuralBandHandwritingUpdate } from "../services/neuralBand/NeuralBandInput";
|
|
2
|
+
import { type NeuralBandClaimStatus, type NeuralBandFirmwareStatus, type NeuralBandHandwritingStatus, type NeuralBandHandwritingUpdate } from "../services/neuralBand/NeuralBandInput";
|
|
3
3
|
declare function projectStatus(): {
|
|
4
4
|
state: "connecting" | "connected" | "disconnected" | "scanning" | "bonding";
|
|
5
5
|
fullyBooted: boolean;
|
|
@@ -164,6 +164,15 @@ export declare const glasses: {
|
|
|
164
164
|
/** The band's air mouse; movement reaches miniapps on the pointer stream. */
|
|
165
165
|
setPointer: (id: string, enabled: boolean) => Promise<void>;
|
|
166
166
|
setHand: (id: string, hand: "left" | "right") => Promise<void>;
|
|
167
|
+
firmwareStatus: (id: string) => NeuralBandFirmwareStatus;
|
|
168
|
+
onFirmwareStatus: (cb: (update: {
|
|
169
|
+
id: string;
|
|
170
|
+
status: NeuralBandFirmwareStatus;
|
|
171
|
+
}) => void) => (() => void);
|
|
172
|
+
refreshFirmware: (id: string) => Promise<NeuralBandFirmwareStatus>;
|
|
173
|
+
requestFirmwareStatus: (id: string) => Promise<void>;
|
|
174
|
+
checkFirmware: (id: string) => Promise<void>;
|
|
175
|
+
updateFirmware: (id: string, mode: "update" | "cancel" | "key" | "send" | "trial" | "install") => Promise<void>;
|
|
167
176
|
};
|
|
168
177
|
watch: {
|
|
169
178
|
/** Whether this phone has a paired watch and the Glassly watch app is on it. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glasses.d.ts","sourceRoot":"","sources":["../../src/facades/glasses.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,MAAM,EACN,mBAAmB,EACnB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"glasses.d.ts","sourceRoot":"","sources":["../../src/facades/glasses.ts"],"names":[],"mappings":"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"}
|
package/build/facades/glasses.js
CHANGED
|
@@ -301,6 +301,20 @@ export const glasses = {
|
|
|
301
301
|
/** The band's air mouse; movement reaches miniapps on the pointer stream. */
|
|
302
302
|
setPointer: (id, enabled) => BluetoothSdk.neuralBandSetPointer(id, enabled),
|
|
303
303
|
setHand: (id, hand) => BluetoothSdk.neuralBandSetHand(id, hand),
|
|
304
|
+
firmwareStatus: (id) => ({ ...neuralBandInput.firmwareStatus(id) }),
|
|
305
|
+
onFirmwareStatus: (cb) => neuralBandInput.onFirmwareStatus(cb),
|
|
306
|
+
refreshFirmware: async (id) => {
|
|
307
|
+
const info = await BluetoothSdk.neuralBandFirmwareInfo(id);
|
|
308
|
+
neuralBandInput.handleFirmware({
|
|
309
|
+
...info,
|
|
310
|
+
type: "neural_band_firmware",
|
|
311
|
+
controllerId: id,
|
|
312
|
+
});
|
|
313
|
+
return neuralBandInput.firmwareStatus(id);
|
|
314
|
+
},
|
|
315
|
+
requestFirmwareStatus: (id) => BluetoothSdk.neuralBandRequestFirmwareStatus(id),
|
|
316
|
+
checkFirmware: (id) => BluetoothSdk.neuralBandCheckFirmware(id),
|
|
317
|
+
updateFirmware: (id, mode) => BluetoothSdk.neuralBandUpdateFirmware(id, mode),
|
|
304
318
|
},
|
|
305
319
|
// --- watch: an Apple Watch over WatchConnectivity (iOS), a Wear OS watch over the Data Layer (Android) ---
|
|
306
320
|
watch: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glasses.js","sourceRoot":"","sources":["../../src/facades/glasses.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,kFAAkF;AAClF,sFAAsF;AACtF,uEAAuE;AACvE,OAAO,YAAY,MAAM,iCAAiC,CAAA;AAY1D,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAC,gBAAgB,EAAE,QAAQ,EAAC,MAAM,oBAAoB,CAAA;AAC7D,OAAO,EAAC,gBAAgB,EAAC,MAAM,kCAAkC,CAAA;AACjE,OAAO,mBAAmB,MAAM,iCAAiC,CAAA;AACjE,OAAO,EAAC,sBAAsB,EAAC,MAAM,6BAA6B,CAAA;AAClE,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,WAAW,EACX,aAAa,EACb,gBAAgB,GACjB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAC,kBAAkB,EAAE,cAAc,EAAC,MAAM,8BAA8B,CAAA;AAC/E,OAAO,EAAC,wBAAwB,EAAC,MAAM,iCAAiC,CAAA;AACxE,OAAO,EAAC,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAC,MAAM,yBAAyB,CAAA;AAClG,OAAO,eAIN,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAC,qCAAqC,EAAC,MAAM,gCAAgC,CAAA;AACpF,OAAO,EAAC,oBAAoB,EAAmB,MAAM,UAAU,CAAA;AAC/D,OAAO,EAAC,YAAY,EAAC,MAAM,yBAAyB,CAAA;AACpD,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAA;AACzC,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAA;AAEjD,IAAI,qBAAqB,GAAG,CAAC,CAAA;AAE7B,0EAA0E;AAC1E,gFAAgF;AAChF,SAAS,aAAa;IACpB,MAAM,CAAC,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAA;IACpC,OAAO,aAAa,CAClB;QACE,KAAK,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK;QACzB,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC;QACzC,OAAO,EAAE,CAAC,CAAC,YAAY;QACvB,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,IAAI,EAAE,EAAC,OAAO,EAAE,CAAC,CAAC,gBAAgB,EAAE,QAAQ,EAAE,CAAC,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,WAAW,EAAC;QACvG,MAAM,EAAE,CAAC,CAAC,cAAc;QACxB,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,UAAU,EAAE,CAAC,CAAC,6BAA6B;QAC3C,SAAS,EAAE,CAAC,CAAC,yBAAyB;QACtC,gFAAgF;QAChF,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC;KAC1C,EACD,sBAAsB,EAAE,CACzB,CAAA;AACH,CAAC;AAED,SAAS,qBAAqB;IAC5B,OAAO,qBAAqB,CAC1B,qBAAqB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,EACvF,sBAAsB,EAAE,CACzB,CAAA;AACH,CAAC;AAED,6EAA6E;AAC7E,SAAS,yBAAyB;IAChC,MAAM,QAAQ,GAAqC,EAAE,CAAA;IACrD,KAAK,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,CAAC;QACxF,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAC,GAAG,MAAM,EAAC,CAAA;IAC5B,CAAC;IACD,OAAO,yBAAyB,CAAC,QAAQ,EAAE,sBAAsB,EAAE,CAAC,CAAA;AACtE,CAAC;AAED,2EAA2E;AAC3E,8EAA8E;AAC9E,2EAA2E;AAC3E,SAAS,mBAAmB,CAAI,OAAgB,EAAE,EAAyB;IACzE,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAA;IACpC,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;QAChC,IAAI,GAAG,KAAK,IAAI;YAAE,OAAM;QACxB,IAAI,GAAG,GAAG,CAAA;QACV,EAAE,CAAC,IAAI,CAAC,CAAA;IACV,CAAC,CAAA;IACD,MAAM,kBAAkB,GAAG,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IAC5D,MAAM,mBAAmB,GAAG,gBAAgB,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAE,CAAC,CAAA;IAC9F,OAAO,GAAG,EAAE;QACV,kBAAkB,EAAE,CAAA;QACpB,mBAAmB,EAAE,CAAA;IACvB,CAAC,CAAA;AACH,CAAC;AAED,SAAS,qBAAqB;IAC5B,MAAM,CAAC,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAA;IACpC,OAAO;QACL,sFAAsF;QACtF,SAAS,EAAE,CAAC,CAAC,cAAc,KAAK,IAAI;QACpC,SAAS,EAAE,CAAC,CAAC,iBAAiB,KAAK,IAAI;QACvC,IAAI,EAAE,CAAC,CAAC,YAAY,IAAI,EAAE;QAC1B,6DAA6D;QAC7D,KAAK,EAAE,CAAC,CAAC,aAAa,KAAK,IAAI;QAC/B,KAAK,EAAE,CAAC,CAAC,aAAa,IAAI,MAAM;QAChC,KAAK,EAAE,CAAC,CAAC,aAAa,IAAI,EAAE;KAC7B,CAAA;AACH,CAAC;AAED,SAAS,WAAW;IAClB,MAAM,CAAC,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAA;IACpC,OAAO,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,sBAAsB,EAAE,CAAC,CAAA;AACjE,CAAC;AAED,SAAS,cAAc,CAAC,CAA8C;IACpE,OAAO;QACL,KAAK,EAAE,CAAC,CAAC,WAAW;QACpB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,aAAa,EAAE,CAAC,CAAC,aAAa;QAC9B,eAAe,EAAE,CAAC,CAAC,eAAe;QAClC,WAAW,EAAE,CAAC,CAAC,kBAAkB;QACjC,WAAW,EAAE,CAAC,CAAC,kBAAkB;QACjC,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,cAAc,EAAE,CAAC,CAAC,cAAc;QAChC,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,KAAK,EAAE,CAAC,CAAC,mBAAmB;QAC5B,OAAO,EAAE,CAAC,CAAC,cAAc;QACzB,OAAO,EAAE,CAAC,CAAC,cAAc;QACzB,QAAQ,EAAE,CAAC,CAAC,eAAe;QAC3B,gBAAgB,EAAE,CAAC,CAAC,gBAAgB;QACpC,iBAAiB,EAAE,CAAC,CAAC,iBAAiB;QACtC,UAAU,EAAE,CAAC,CAAC,UAAU,KAAK,IAAI;QACjC,uBAAuB,EAAE,CAAC,CAAC,uBAAuB,KAAK,IAAI;QAC3D,+EAA+E;QAC/E,IAAI,EAAE,EAAC,GAAG,CAAC,CAAC,IAAI,EAAC;KAClB,CAAA;AACH,CAAC;AAMD,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,iDAAiD;IACjD;;;;OAIG;IACH,cAAc,EAAE,KAAK,IAAmB,EAAE;QACxC,IAAI,CAAC;YACH,MAAM,wBAAwB,EAAE,CAAA;YAChC,MAAM,YAAY,CAAC,cAAc,EAAE,CAAA;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,qCAAqC,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAA;YAC/D,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IACD,UAAU,EAAE,GAAkB,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE;IAC1D,MAAM,EAAE,GAAkB,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE;IAClD,iDAAiD;IACjD,OAAO,EAAE,KAAK,EAAE,MAAc,EAAE,OAAwB,EAAiB,EAAE;QACzE,IAAI,CAAC;YACH,MAAM,wBAAwB,EAAE,CAAA;YAChC,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,qCAAqC,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;YACvD,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IACD,4DAA4D;IAC5D,gBAAgB,EAAE,GAAkB,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE;IACtE,qDAAqD;IACrD,UAAU,EAAE,CAAC,MAAqB,EAAiB,EAAE,CAAC,YAAY,CAAC,gBAAgB,CAAC,MAAM,CAAC;IAC3F;;;;;;OAMG;IACH,SAAS,EAAE,KAAK,IAAsB,EAAE;QACtC,MAAM,eAAe,GAAG,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAA;QAC7F,IAAI,CAAC,eAAe;YAAE,OAAO,KAAK,CAAA;QAClC,IAAI,kBAAkB,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAA;QAC1E,IAAI,CAAC;YACH,MAAM,wBAAwB,EAAE,CAAA;YAChC,MAAM,YAAY,CAAC,cAAc,EAAE,CAAA;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,qCAAqC,CAAC,KAAK,EAAE,WAAW,CAAC,CAAA;YACzD,OAAO,CAAC,IAAI,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAA;YACvD,OAAO,KAAK,CAAA;QACd,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IACD;;;iEAG6D;IAC7D,cAAc,EAAE,GAAY,EAAE,CAAC,sBAAsB,EAAE,CAAC,IAAI,KAAK,MAAM;IACvE;;;;;;;;;;OAUG;IACH,gBAAgB,EAAE,GAAqB,EAAE,CAAC,gBAAgB,EAAE;IAE5D,qEAAqE;IACrE,MAAM,EAAE,GAA0B,EAAE,CAAC,aAAa,EAAE;IACpD,QAAQ,EAAE,CAAC,EAA2C,EAAgB,EAAE,CAAC,mBAAmB,CAAC,aAAa,EAAE,EAAE,CAAC;IAC/G,IAAI,EAAE,GAAwB,EAAE,CAAC,WAAW,EAAE;IAC9C,MAAM,EAAE,CAAC,EAAuC,EAAgB,EAAE,CAAC,mBAAmB,CAAC,WAAW,EAAE,EAAE,CAAC;IACvG,YAAY,EAAE,GAAG,EAAE,CAAC,oBAAoB,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,WAA0B,CAAC;IAC/F,iFAAiF;IACjF,kBAAkB,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,kBAAkB,EAAE;IAE3D,wDAAwD;IACxD,aAAa,EAAE,CAAC,EAAqC,EAAgB,EAAE;QACrE,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,CAAC,cAAc,EAAE,EAAE,CAAC,CAAA;QACxD,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAA;IAC3B,CAAC;IACD,cAAc,EAAE,CAAC,EAA+B,EAAgB,EAAE;QAChE,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,CAAC,aAAa,EAAE,EAAE,CAAC,CAAA;QACvD,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAA;IAC3B,CAAC;IAED,qEAAqE;IACrE,QAAQ,EAAE;QACR,2FAA2F;QAC3F,IAAI,EAAE,GAAmC,EAAE,CAAC,YAAY,CAAC,cAAc,EAAE;QACzE,oFAAoF;QACpF,OAAO,EAAE,KAAK,EAAE,MAA4D,EAAiB,EAAE;YAC7F,MAAM,YAAY,CAAC,iBAAiB,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;YACrF,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;QACjF,CAAC;QACD,SAAS,EAAE,GAAkB,EAAE,CAAC,YAAY,CAAC,mBAAmB,EAAE;QAClE,UAAU,EAAE,GAAkB,EAAE,CAAC,YAAY,CAAC,oBAAoB,EAAE;QACpE,MAAM,EAAE,KAAK,IAAmB,EAAE;YAChC,MAAM,YAAY,CAAC,gBAAgB,EAAE,CAAA;YACrC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;QACxE,CAAC;QACD,OAAO,EAAE,CAAC,GAAW,EAAiB,EAAE,CAAC,YAAY,CAAC,iBAAiB,CAAC,GAAG,CAAC;QAC5E,OAAO,EAAE,CAAC,MAAe,EAAiB,EAAE,CAAC,YAAY,CAAC,iBAAiB,CAAC,MAAM,CAAC;QACnF,MAAM,EAAE,GAA2B,EAAE,CAAC,qBAAqB,EAAE;QAC7D,QAAQ,EAAE,CAAC,EAA4C,EAAgB,EAAE;YACvE,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,qBAAqB,EAAE,CAAC,CAAA;YAClD,OAAO,eAAe,CAAC,SAAS,CAAC,GAAG,EAAE;gBACpC,MAAM,IAAI,GAAG,qBAAqB,EAAE,CAAA;gBACpC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;gBAChC,IAAI,GAAG,KAAK,IAAI;oBAAE,OAAM;gBACxB,IAAI,GAAG,GAAG,CAAA;gBACV,EAAE,CAAC,IAAI,CAAC,CAAA;YACV,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,QAAQ,EAAE,CAAC,EAAyC,EAAgB,EAAE;YACpE,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAA;YAC3D,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAA;QAC3B,CAAC;QACD,SAAS,EAAE,CAAC,EAA0C,EAAgB,EAAE;YACtE,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAA;YAC5D,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAA;QAC3B,CAAC;KACF;IAED,8EAA8E;IAC9E,WAAW,EAAE;QACX,2CAA2C;QAC3C,IAAI,EAAE,GAAuB,EAAE,CAAC,qBAAqB,EAAE;QACvD,MAAM,EAAE,CAAC,EAA6C,EAAgB,EAAE;YACtE,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,qBAAqB,EAAE,CAAC,CAAA;YAClD,OAAO,gBAAgB,CAAC,SAAS,CAAC,GAAG,EAAE;gBACrC,MAAM,IAAI,GAAG,qBAAqB,EAAE,CAAA;gBACpC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;gBAChC,IAAI,GAAG,KAAK,IAAI;oBAAE,OAAM;gBACxB,IAAI,GAAG,GAAG,CAAA;gBACV,EAAE,CAAC,IAAI,CAAC,CAAA;YACV,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,gFAAgF;QAChF,QAAQ,EAAE,GAAqC,EAAE,CAAC,yBAAyB,EAAE;QAC7E,MAAM,EAAE,CAAC,EAAU,EAAgC,EAAE,CAAC,yBAAyB,EAAE,CAAC,EAAE,CAAC;QACrF,QAAQ,EAAE,CAAC,EAAwD,EAAgB,EAAE,CACnF,mBAAmB,CAAC,yBAAyB,EAAE,EAAE,CAAC;QACpD,kEAAkE;QAClE,SAAS,EAAE,GAAuB,EAAE,CAAC,gBAAgB,CAAC,yBAAyB,EAAE,CAAC;QAClF,WAAW,EAAE,CAAC,KAAc,EAAW,EAAE,CACvC,MAAM,CAAC,MAAM,CAAC,yBAAyB,EAAE,CAAC,CAAC,IAAI,CAC7C,CAAC,MAAM,EAAE,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC,CACzF;QACH,OAAO,EAAE,CAAC,EAAU,EAAiB,EAAE,CAAC,YAAY,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC1E,+DAA+D;QAC/D,UAAU,EAAE,GAAkB,EAAE,CAAC,YAAY,CAAC,kBAAkB,EAAE;QAClE,kFAAkF;QAClF,aAAa,EAAE,GAAkB,EAAE,CAAC,YAAY,CAAC,uBAAuB,EAAE;QAC1E,+CAA+C;QAC/C,UAAU,EAAE,CAAC,EAAU,EAAiB,EAAE,CAAC,YAAY,CAAC,oBAAoB,CAAC,EAAE,CAAC;QAChF,MAAM,EAAE,KAAK,EAAE,EAAU,EAAiB,EAAE;YAC1C,MAAM,YAAY,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;YACvC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAC5B,CAAC;KACF;IAED,mGAAmG;IACnG,UAAU,EAAE;QACV,kFAAkF;QAClF,cAAc,EAAE,CAAC,WAAmB,EAAE,MAAc,EAAiB,EAAE,CACrE,YAAY,CAAC,wBAAwB,CAAC,WAAW,EAAE,MAAM,CAAC;QAC5D,gBAAgB,EAAE,GAAkB,EAAE,CAAC,YAAY,CAAC,0BAA0B,EAAE;QAChF,cAAc,EAAE,GAAqB,EAAE,CAAC,YAAY,CAAC,wBAAwB,EAAE;QAC/E,sFAAsF;QACtF,SAAS,EAAE,CAAC,EAAU,EAAoB,EAAE,CAAC,YAAY,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACjF,4FAA4F;QAC5F,WAAW,EAAE,GAA0B,EAAE,CAAC,CAAC,EAAC,GAAG,eAAe,CAAC,WAAW,EAAE,EAAC,CAAC;QAC9E,UAAU,EAAE,GAAS,EAAE,CAAC,eAAe,CAAC,UAAU,EAAE;QACpD,aAAa,EAAE,CAAC,EAA2C,EAAgB,EAAE,CAAC,eAAe,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/G,oFAAoF;QACpF,cAAc,EAAE,CAAC,EAAU,EAAE,OAAgB,EAAiB,EAAE,CAAC,YAAY,CAAC,wBAAwB,CAAC,EAAE,EAAE,OAAO,CAAC;QACnH,iBAAiB,EAAE,CAAC,EAAU,EAA+B,EAAE,CAAC,CAAC,EAAC,GAAG,eAAe,CAAC,iBAAiB,CAAC,EAAE,CAAC,EAAC,CAAC;QAC5G,mBAAmB,EAAE,CAAC,EAAiD,EAAgB,EAAE,CACvF,eAAe,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACzC,6EAA6E;QAC7E,UAAU,EAAE,CAAC,EAAU,EAAE,OAAgB,EAAiB,EAAE,CAAC,YAAY,CAAC,oBAAoB,CAAC,EAAE,EAAE,OAAO,CAAC;QAC3G,OAAO,EAAE,CAAC,EAAU,EAAE,IAAsB,EAAiB,EAAE,CAAC,YAAY,CAAC,iBAAiB,CAAC,EAAE,EAAE,IAAI,CAAC;KACzG;IAED,4GAA4G;IAC5G,KAAK,EAAE;QACL,gFAAgF;QAChF,YAAY,EAAE,GAA+B,EAAE,CAAC,YAAY,CAAC,iBAAiB,EAAE;KACjF;IAED,8EAA8E;IAC9E,KAAK,EAAE;QACL,8CAA8C;QAC9C,cAAc,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,qBAAqB,EAAE;QAC1D,qCAAqC;QACrC,cAAc,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,YAAY,CAAC,qBAAqB,CAAC,KAAK,CAAC;QAC5E,6EAA6E;QAC7E,gBAAgB,EAAE,CAAC,OAAgB,EAAiB,EAAE,CAAC,YAAY,CAAC,qBAAqB,CAAC,OAAO,CAAC;QAClG;;;;WAIG;QACH,UAAU,EAAE,CAAC,EAA0B,EAAgB,EAAE;YACvD,MAAM,KAAK,GAAG,aAAa,EAAE,qBAAqB,EAAE,CAAA;YACpD,mBAAmB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;YACzC,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC,KAAsC,EAAE,EAAE;gBACzF,IAAI,KAAK,EAAE,GAAG;oBAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;YAC7C,CAAC,CAAC,CAAA;YACF,OAAO,GAAG,EAAE;gBACV,GAAG,CAAC,MAAM,EAAE,CAAA;gBACZ,mBAAmB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;YAC3C,CAAC,CAAA;QACH,CAAC;KACF;IAED,sBAAsB;IACtB,IAAI,EAAE,WAAW;IACjB,QAAQ,EAAE,eAAe;CAC1B,CAAA","sourcesContent":["/**\n * glasses facade — the core `engine.glasses.*` surface: connection actions (over\n * the bluetooth-sdk passthrough), a curated status/info read-model (projected from\n * the engine-owned glasses store), capabilities (from the model table), and the\n * discrete input events. The `wifi` sub-facade is nested here.\n *\n * Read-models project the raw glasses store into the stable shape OEM UIs consume,\n * so the device store's field layout doesn't leak into every screen.\n */\n// Internal btsdk surface — connectSimulated/reconnect/controller live on the full\n// surface, not the public entry. Relative path (the alias doesn't resolve in engine's\n// standalone build); jest moduleNameMapper + tsconfig both resolve it.\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport type {\n WatchAvailability,\n ButtonPressEvent,\n ConnectOptions,\n ControllerStatus,\n Device,\n KeyboardAdvertEvent,\n KeyboardPairingEvent,\n PairedController,\n TouchEvent,\n} from \"@glassly/bluetooth-sdk\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore, SETTINGS} from \"../stores/settings\"\nimport {hasDefaultDevice} from \"../services/DeviceStoreHydration\"\nimport micStateCoordinator from \"../services/MicStateCoordinator\"\nimport {projectPairingIdentity} from \"../services/PairingIdentity\"\nimport {\n fixtureControllerList,\n fixtureControllerStatuses,\n fixtureInfo,\n fixtureStatus,\n isScreenshotMode,\n} from \"../services/ScreenshotFixture\"\nimport {isGlassesConnected, isGlassesReady} from \"../services/GlassesReadiness\"\nimport {pushAllBluetoothSettings} from \"../services/GlassesSettingsSync\"\nimport {isControllerReady, pairedControllersFrom, readyControllers} from \"../services/controllers\"\nimport neuralBandInput, {\n type NeuralBandClaimStatus,\n type NeuralBandHandwritingStatus,\n type NeuralBandHandwritingUpdate,\n} from \"../services/neuralBand/NeuralBandInput\"\nimport {recordSupportProfileConnectionFailure} from \"../services/SupportProfileSync\"\nimport {getModelCapabilities, type DeviceTypes} from \"../types\"\nimport {pcmLevelDbfs} from \"../utils/audio/pcmLevel\"\nimport {glassesWifi} from \"./glassesWifi\"\nimport {glassesSettings} from \"./glassesSettings\"\n\nlet micLevelSubscriptions = 0\n\n// The screenshot fixture (ScreenshotFixture.ts) dresses these read-models\n// while the identity is the simulated device; it is a no-op outside that build.\nfunction projectStatus() {\n const s = useGlassesStore.getState()\n return fixtureStatus(\n {\n state: s.connection.state,\n fullyBooted: isGlassesReady(s.connection),\n battery: s.batteryLevel,\n charging: s.charging,\n case: {battery: s.caseBatteryLevel, charging: s.caseCharging, open: s.caseOpen, removed: s.caseRemoved},\n signal: s.signalStrength,\n micEnabled: s.micEnabled,\n vadEnabled: s.voiceActivityDetectionEnabled,\n btClassic: s.bluetoothClassicConnected,\n // iOS: glasses may read the phone's ANCS stream (\"Share System Notifications\").\n ancsAuthorized: Boolean(s.ancsAuthorized),\n },\n projectPairingIdentity(),\n )\n}\n\nfunction projectControllerList(): PairedController[] {\n return fixtureControllerList(\n pairedControllersFrom(useSettingsStore.getState().getSetting(SETTINGS.controllers.key)),\n projectPairingIdentity(),\n )\n}\n\n// Copies: snapshots must not hand callers mutable references into the store.\nfunction projectControllerStatuses(): Record<string, ControllerStatus> {\n const statuses: Record<string, ControllerStatus> = {}\n for (const [id, status] of Object.entries(useGlassesStore.getState().controllers ?? {})) {\n statuses[id] = {...status}\n }\n return fixtureControllerStatuses(statuses, projectPairingIdentity())\n}\n\n// Dedupe on the projected snapshot: the store updates on many fields; fire\n// only when the projection changes. The fixture's read-models also follow the\n// identity (a settings key), so that build watches the settings store too.\nfunction subscribeProjection<T>(project: () => T, cb: (snapshot: T) => void): () => void {\n let last = JSON.stringify(project())\n const notify = () => {\n const snap = project()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n }\n const unsubscribeGlasses = useGlassesStore.subscribe(notify)\n const unsubscribeSettings = isScreenshotMode() ? useSettingsStore.subscribe(notify) : () => {}\n return () => {\n unsubscribeGlasses()\n unsubscribeSettings()\n }\n}\n\nfunction projectKeyboardStatus() {\n const s = useGlassesStore.getState()\n return {\n /** Connected glasses run a firmware that can host a keyboard (G2 Glassly CFW 39+). */\n available: s.keyboardBridge === true,\n connected: s.keyboardConnected === true,\n name: s.keyboardName ?? \"\",\n /** A keyboard is remembered and reconnects automatically. */\n saved: s.keyboardSaved === true,\n state: s.keyboardState ?? \"idle\",\n error: s.keyboardError ?? \"\",\n }\n}\n\nfunction projectInfo() {\n const s = useGlassesStore.getState()\n return fixtureInfo(projectRawInfo(s), projectPairingIdentity())\n}\n\nfunction projectRawInfo(s: ReturnType<typeof useGlassesStore.getState>) {\n return {\n model: s.deviceModel,\n style: s.style,\n color: s.color,\n bluetoothName: s.bluetoothName,\n firmwareVersion: s.firmwareVersion,\n mtkFirmware: s.mtkFirmwareVersion,\n besFirmware: s.besFirmwareVersion,\n appVersion: s.appVersion,\n androidVersion: s.androidVersion,\n serialNumber: s.serialNumber,\n buildNumber: s.buildNumber,\n btMac: s.bluetoothMacAddress,\n wifiMac: s.wifiMacAddress,\n leftMac: s.leftMacAddress,\n rightMac: s.rightMacAddress,\n sceneCanvasWidth: s.sceneCanvasWidth,\n sceneCanvasHeight: s.sceneCanvasHeight,\n volumeGate: s.volumeGate === true,\n firmwareUpdateAvailable: s.firmwareUpdateAvailable === true,\n // Copy: the snapshot must not hand callers a mutable reference into the store.\n wifi: {...s.wifi},\n }\n}\n\nexport type GlassesStatusSnapshot = ReturnType<typeof projectStatus>\nexport type KeyboardStatusSnapshot = ReturnType<typeof projectKeyboardStatus>\nexport type GlassesInfoSnapshot = ReturnType<typeof projectInfo>\n\nexport const glasses = {\n // --- connection (bluetooth-sdk passthrough) ---\n /**\n * Reconnect the default wearable. Seeds the phone's current device settings to\n * native first, so they're primed before the connect handshake replays them to\n * the glasses (this used to be a host-side step before `connectDefault`).\n */\n connectDefault: async (): Promise<void> => {\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connectDefault()\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"connect_default\")\n throw error\n }\n },\n disconnect: (): Promise<void> => BluetoothSdk.disconnect(),\n forget: (): Promise<void> => BluetoothSdk.forget(),\n /** Connect to a specific (discovered) device. */\n connect: async (device: Device, options?: ConnectOptions): Promise<void> => {\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connect(device, options)\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"connect\")\n throw error\n }\n },\n /** Connect the built-in simulated glasses (dev/testing). */\n connectSimulated: (): Promise<void> => BluetoothSdk.connectSimulated(),\n /** Set a device as the `connectDefault()` target. */\n setDefault: (device: Device | null): Promise<void> => BluetoothSdk.setDefaultDevice(device),\n /**\n * Reconnect to the saved default glasses. Resolves `false` when there's nothing to\n * reconnect to (no default paired) or the connect attempt fails (e.g. BLE powered\n * off), `true` when already connected or after kicking off the connect. Never\n * rejects — the boolean contract holds. The host gates connectivity/permissions\n * (its UI) before calling.\n */\n reconnect: async (): Promise<boolean> => {\n const defaultWearable = useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key)\n if (!defaultWearable) return false\n if (isGlassesConnected(useGlassesStore.getState().connection)) return true\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connectDefault()\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"reconnect\")\n console.warn(\"engine.glasses.reconnect failed:\", error)\n return false\n }\n return true\n },\n /** True when no glasses has ever been paired NOR selected (the pairing-identity\n * lifecycle is in its `none` state) — e.g. to route a first-run host into the\n * pairing/onboarding flow. A pending selection is not \"first\" — the host should\n * offer finish-pairing (see `engine.pairing.identity()`). */\n isFirstPairing: (): boolean => projectPairingIdentity().kind === \"none\",\n /**\n * True when the SDK has an actual default DEVICE to reconnect to. Distinct from\n * `default_wearable` (a model string that a pending or orphaned selection can\n * hold without any paired device): connectDefault() throws without a device, so\n * hosts should route to the pairing flow when this is false.\n *\n * Hydration-aware: awaits the device-store seed internally, so a cold-start\n * read can't see a false \"absent\" for genuinely-paired users. Rejects if\n * hydration failed — callers guarding destructive or routing decisions must\n * fail open (treat as \"has a device\").\n */\n hasDefaultDevice: (): Promise<boolean> => hasDefaultDevice(),\n\n // --- read-model (projected from the engine-owned glasses store) ---\n status: (): GlassesStatusSnapshot => projectStatus(),\n onStatus: (cb: (status: GlassesStatusSnapshot) => void): (() => void) => subscribeProjection(projectStatus, cb),\n info: (): GlassesInfoSnapshot => projectInfo(),\n onInfo: (cb: (info: GlassesInfoSnapshot) => void): (() => void) => subscribeProjection(projectInfo, cb),\n capabilities: () => getModelCapabilities(useGlassesStore.getState().deviceModel as DeviceTypes),\n /** Ask the glasses to report fresh firmware/version info (updates the store). */\n requestVersionInfo: () => BluetoothSdk.requestVersionInfo(),\n\n // --- discrete input events (passthrough listeners) ---\n onButtonPress: (cb: (event: ButtonPressEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"button_press\", cb)\n return () => sub.remove()\n },\n onTouchGesture: (cb: (event: TouchEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"touch_event\", cb)\n return () => sub.remove()\n },\n\n // --- BLE keyboard bridged through G2 Glassly CFW (revision 39+) ---\n keyboard: {\n /** Five-second scan; distinct advertisers, HID ones flagged. Also streams via onAdvert. */\n scan: (): Promise<KeyboardAdvertEvent[]> => BluetoothSdk.g2KeyboardScan(),\n /** Connect, pair and subscribe; the keyboard is remembered and auto-reconnected. */\n connect: async (device: {address: string; addressType: number; name: string}): Promise<void> => {\n await BluetoothSdk.g2KeyboardConnect(device.address, device.addressType, device.name)\n useSettingsStore.getState().setSetting(SETTINGS.keyboard_name.key, device.name)\n },\n reconnect: (): Promise<void> => BluetoothSdk.g2KeyboardReconnect(),\n disconnect: (): Promise<void> => BluetoothSdk.g2KeyboardDisconnect(),\n forget: async (): Promise<void> => {\n await BluetoothSdk.g2KeyboardForget()\n useSettingsStore.getState().setSetting(SETTINGS.keyboard_name.key, \"\")\n },\n passkey: (pin: number): Promise<void> => BluetoothSdk.g2KeyboardPasskey(pin),\n compare: (accept: boolean): Promise<void> => BluetoothSdk.g2KeyboardCompare(accept),\n status: (): KeyboardStatusSnapshot => projectKeyboardStatus(),\n onStatus: (cb: (status: KeyboardStatusSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectKeyboardStatus())\n return useGlassesStore.subscribe(() => {\n const snap = projectKeyboardStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n onAdvert: (cb: (advert: KeyboardAdvertEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"keyboard_advert\", cb)\n return () => sub.remove()\n },\n onPairing: (cb: (prompt: KeyboardPairingEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"keyboard_pairing\", cb)\n return () => sub.remove()\n },\n },\n\n // --- controllers (input accessories linked to the phone), by registry id ---\n controllers: {\n /** Paired controllers in pairing order. */\n list: (): PairedController[] => projectControllerList(),\n onList: (cb: (controllers: PairedController[]) => void): (() => void) => {\n let last = JSON.stringify(projectControllerList())\n return useSettingsStore.subscribe(() => {\n const list = projectControllerList()\n const key = JSON.stringify(list)\n if (key === last) return\n last = key\n cb(list)\n })\n },\n /** Live driver statuses by id; a paired controller without an entry is idle. */\n statuses: (): Record<string, ControllerStatus> => projectControllerStatuses(),\n status: (id: string): ControllerStatus | undefined => projectControllerStatuses()[id],\n onStatus: (cb: (statuses: Record<string, ControllerStatus>) => void): (() => void) =>\n subscribeProjection(projectControllerStatuses, cb),\n /** Controllers delivering input (linked, route or claim done). */\n connected: (): ControllerStatus[] => readyControllers(projectControllerStatuses()),\n isConnected: (model?: string): boolean =>\n Object.values(projectControllerStatuses()).some(\n (status) => isControllerReady(status) && (model === undefined || status.model === model),\n ),\n connect: (id: string): Promise<void> => BluetoothSdk.connectController(id),\n /** Reconnect every paired controller that is not connected. */\n connectAll: (): Promise<void> => BluetoothSdk.connectControllers(),\n /** Drop an in-flight controller scan or pairing; paired records are untouched. */\n cancelAttempt: (): Promise<void> => BluetoothSdk.cancelControllerAttempt(),\n /** Disconnect; the controller stays paired. */\n disconnect: (id: string): Promise<void> => BluetoothSdk.disconnectController(id),\n forget: async (id: string): Promise<void> => {\n await BluetoothSdk.forgetController(id)\n neuralBandInput.forget(id)\n },\n },\n\n // --- Meta Neural Band (a controller with a claim step and its own features), by controller id ---\n neuralBand: {\n /** Store the Meta account session the one-time band claim uses (account-wide). */\n setMetaSession: (accessToken: string, userId: string): Promise<void> =>\n BluetoothSdk.neuralBandSetMetaSession(accessToken, userId),\n clearMetaSession: (): Promise<void> => BluetoothSdk.neuralBandClearMetaSession(),\n hasMetaSession: (): Promise<boolean> => BluetoothSdk.neuralBandHasMetaSession(),\n /** This band's identity is stored on this phone, so it reconnects without a claim. */\n isClaimed: (id: string): Promise<boolean> => BluetoothSdk.neuralBandIsClaimed(id),\n /** The latest claim progress of any band (with its `controllerId`), kept across screens. */\n claimStatus: (): NeuralBandClaimStatus => ({...neuralBandInput.claimStatus()}),\n resetClaim: (): void => neuralBandInput.resetClaim(),\n onClaimStatus: (cb: (status: NeuralBandClaimStatus) => void): (() => void) => neuralBandInput.onClaimStatus(cb),\n /** The band's handwriting model; writing arrives on the miniapp keyboard stream. */\n setHandwriting: (id: string, enabled: boolean): Promise<void> => BluetoothSdk.neuralBandSetHandwriting(id, enabled),\n handwritingStatus: (id: string): NeuralBandHandwritingStatus => ({...neuralBandInput.handwritingStatus(id)}),\n onHandwritingStatus: (cb: (update: NeuralBandHandwritingUpdate) => void): (() => void) =>\n neuralBandInput.onHandwritingStatus(cb),\n /** The band's air mouse; movement reaches miniapps on the pointer stream. */\n setPointer: (id: string, enabled: boolean): Promise<void> => BluetoothSdk.neuralBandSetPointer(id, enabled),\n setHand: (id: string, hand: \"left\" | \"right\"): Promise<void> => BluetoothSdk.neuralBandSetHand(id, hand),\n },\n\n // --- watch: an Apple Watch over WatchConnectivity (iOS), a Wear OS watch over the Data Layer (Android) ---\n watch: {\n /** Whether this phone has a paired watch and the Glassly watch app is on it. */\n availability: (): Promise<WatchAvailability> => BluetoothSdk.watchAvailability(),\n },\n\n // --- audio (glasses media-volume, own-app playback hint, live mic level) ---\n audio: {\n /** Read the glasses' current media volume. */\n getMediaVolume: () => BluetoothSdk.getGlassesMediaVolume(),\n /** Set the glasses' media volume. */\n setMediaVolume: (level: number) => BluetoothSdk.setGlassesMediaVolume(level),\n /** Tell native whether THIS app is currently playing audio (for ducking). */\n setOwnAppPlaying: (playing: boolean): Promise<void> => BluetoothSdk.setOwnAppAudioPlaying(playing),\n /**\n * Stream the active mic's level in dBFS, one reading per PCM chunk. Holds\n * raw PCM open while subscribed, so the mic runs with no miniapp listening,\n * and holds the G2 volume gate open so the meter shows the ambient level.\n */\n onMicLevel: (cb: (dbfs: number) => void): (() => void) => {\n const owner = `mic_level_${++micLevelSubscriptions}`\n micStateCoordinator.acquireHostPcm(owner)\n const sub = BluetoothSdk.addListener(\"mic_pcm\", (event: {pcm: ArrayBuffer | Uint8Array}) => {\n if (event?.pcm) cb(pcmLevelDbfs(event.pcm))\n })\n return () => {\n sub.remove()\n micStateCoordinator.releaseHostPcm(owner)\n }\n },\n },\n\n // --- sub-facades ---\n wifi: glassesWifi,\n settings: glassesSettings,\n}\n"]}
|
|
1
|
+
{"version":3,"file":"glasses.js","sourceRoot":"","sources":["../../src/facades/glasses.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * glasses facade — the core `engine.glasses.*` surface: connection actions (over\n * the bluetooth-sdk passthrough), a curated status/info read-model (projected from\n * the engine-owned glasses store), capabilities (from the model table), and the\n * discrete input events. The `wifi` sub-facade is nested here.\n *\n * Read-models project the raw glasses store into the stable shape OEM UIs consume,\n * so the device store's field layout doesn't leak into every screen.\n */\n// Internal btsdk surface — connectSimulated/reconnect/controller live on the full\n// surface, not the public entry. Relative path (the alias doesn't resolve in engine's\n// standalone build); jest moduleNameMapper + tsconfig both resolve it.\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport type {\n WatchAvailability,\n ButtonPressEvent,\n ConnectOptions,\n ControllerStatus,\n Device,\n KeyboardAdvertEvent,\n KeyboardPairingEvent,\n NeuralBandFirmwareEvent,\n PairedController,\n TouchEvent,\n} from \"@glassly/bluetooth-sdk\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore, SETTINGS} from \"../stores/settings\"\nimport {hasDefaultDevice} from \"../services/DeviceStoreHydration\"\nimport micStateCoordinator from \"../services/MicStateCoordinator\"\nimport {projectPairingIdentity} from \"../services/PairingIdentity\"\nimport {\n fixtureControllerList,\n fixtureControllerStatuses,\n fixtureInfo,\n fixtureStatus,\n isScreenshotMode,\n} from \"../services/ScreenshotFixture\"\nimport {isGlassesConnected, isGlassesReady} from \"../services/GlassesReadiness\"\nimport {pushAllBluetoothSettings} from \"../services/GlassesSettingsSync\"\nimport {isControllerReady, pairedControllersFrom, readyControllers} from \"../services/controllers\"\nimport neuralBandInput, {\n type NeuralBandClaimStatus,\n type NeuralBandFirmwareStatus,\n type NeuralBandHandwritingStatus,\n type NeuralBandHandwritingUpdate,\n} from \"../services/neuralBand/NeuralBandInput\"\nimport {recordSupportProfileConnectionFailure} from \"../services/SupportProfileSync\"\nimport {getModelCapabilities, type DeviceTypes} from \"../types\"\nimport {pcmLevelDbfs} from \"../utils/audio/pcmLevel\"\nimport {glassesWifi} from \"./glassesWifi\"\nimport {glassesSettings} from \"./glassesSettings\"\n\nlet micLevelSubscriptions = 0\n\n// The screenshot fixture (ScreenshotFixture.ts) dresses these read-models\n// while the identity is the simulated device; it is a no-op outside that build.\nfunction projectStatus() {\n const s = useGlassesStore.getState()\n return fixtureStatus(\n {\n state: s.connection.state,\n fullyBooted: isGlassesReady(s.connection),\n battery: s.batteryLevel,\n charging: s.charging,\n case: {battery: s.caseBatteryLevel, charging: s.caseCharging, open: s.caseOpen, removed: s.caseRemoved},\n signal: s.signalStrength,\n micEnabled: s.micEnabled,\n vadEnabled: s.voiceActivityDetectionEnabled,\n btClassic: s.bluetoothClassicConnected,\n // iOS: glasses may read the phone's ANCS stream (\"Share System Notifications\").\n ancsAuthorized: Boolean(s.ancsAuthorized),\n },\n projectPairingIdentity(),\n )\n}\n\nfunction projectControllerList(): PairedController[] {\n return fixtureControllerList(\n pairedControllersFrom(useSettingsStore.getState().getSetting(SETTINGS.controllers.key)),\n projectPairingIdentity(),\n )\n}\n\n// Copies: snapshots must not hand callers mutable references into the store.\nfunction projectControllerStatuses(): Record<string, ControllerStatus> {\n const statuses: Record<string, ControllerStatus> = {}\n for (const [id, status] of Object.entries(useGlassesStore.getState().controllers ?? {})) {\n statuses[id] = {...status}\n }\n return fixtureControllerStatuses(statuses, projectPairingIdentity())\n}\n\n// Dedupe on the projected snapshot: the store updates on many fields; fire\n// only when the projection changes. The fixture's read-models also follow the\n// identity (a settings key), so that build watches the settings store too.\nfunction subscribeProjection<T>(project: () => T, cb: (snapshot: T) => void): () => void {\n let last = JSON.stringify(project())\n const notify = () => {\n const snap = project()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n }\n const unsubscribeGlasses = useGlassesStore.subscribe(notify)\n const unsubscribeSettings = isScreenshotMode() ? useSettingsStore.subscribe(notify) : () => {}\n return () => {\n unsubscribeGlasses()\n unsubscribeSettings()\n }\n}\n\nfunction projectKeyboardStatus() {\n const s = useGlassesStore.getState()\n return {\n /** Connected glasses run a firmware that can host a keyboard (G2 Glassly CFW 39+). */\n available: s.keyboardBridge === true,\n connected: s.keyboardConnected === true,\n name: s.keyboardName ?? \"\",\n /** A keyboard is remembered and reconnects automatically. */\n saved: s.keyboardSaved === true,\n state: s.keyboardState ?? \"idle\",\n error: s.keyboardError ?? \"\",\n }\n}\n\nfunction projectInfo() {\n const s = useGlassesStore.getState()\n return fixtureInfo(projectRawInfo(s), projectPairingIdentity())\n}\n\nfunction projectRawInfo(s: ReturnType<typeof useGlassesStore.getState>) {\n return {\n model: s.deviceModel,\n style: s.style,\n color: s.color,\n bluetoothName: s.bluetoothName,\n firmwareVersion: s.firmwareVersion,\n mtkFirmware: s.mtkFirmwareVersion,\n besFirmware: s.besFirmwareVersion,\n appVersion: s.appVersion,\n androidVersion: s.androidVersion,\n serialNumber: s.serialNumber,\n buildNumber: s.buildNumber,\n btMac: s.bluetoothMacAddress,\n wifiMac: s.wifiMacAddress,\n leftMac: s.leftMacAddress,\n rightMac: s.rightMacAddress,\n sceneCanvasWidth: s.sceneCanvasWidth,\n sceneCanvasHeight: s.sceneCanvasHeight,\n volumeGate: s.volumeGate === true,\n firmwareUpdateAvailable: s.firmwareUpdateAvailable === true,\n // Copy: the snapshot must not hand callers a mutable reference into the store.\n wifi: {...s.wifi},\n }\n}\n\nexport type GlassesStatusSnapshot = ReturnType<typeof projectStatus>\nexport type KeyboardStatusSnapshot = ReturnType<typeof projectKeyboardStatus>\nexport type GlassesInfoSnapshot = ReturnType<typeof projectInfo>\n\nexport const glasses = {\n // --- connection (bluetooth-sdk passthrough) ---\n /**\n * Reconnect the default wearable. Seeds the phone's current device settings to\n * native first, so they're primed before the connect handshake replays them to\n * the glasses (this used to be a host-side step before `connectDefault`).\n */\n connectDefault: async (): Promise<void> => {\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connectDefault()\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"connect_default\")\n throw error\n }\n },\n disconnect: (): Promise<void> => BluetoothSdk.disconnect(),\n forget: (): Promise<void> => BluetoothSdk.forget(),\n /** Connect to a specific (discovered) device. */\n connect: async (device: Device, options?: ConnectOptions): Promise<void> => {\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connect(device, options)\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"connect\")\n throw error\n }\n },\n /** Connect the built-in simulated glasses (dev/testing). */\n connectSimulated: (): Promise<void> => BluetoothSdk.connectSimulated(),\n /** Set a device as the `connectDefault()` target. */\n setDefault: (device: Device | null): Promise<void> => BluetoothSdk.setDefaultDevice(device),\n /**\n * Reconnect to the saved default glasses. Resolves `false` when there's nothing to\n * reconnect to (no default paired) or the connect attempt fails (e.g. BLE powered\n * off), `true` when already connected or after kicking off the connect. Never\n * rejects — the boolean contract holds. The host gates connectivity/permissions\n * (its UI) before calling.\n */\n reconnect: async (): Promise<boolean> => {\n const defaultWearable = useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key)\n if (!defaultWearable) return false\n if (isGlassesConnected(useGlassesStore.getState().connection)) return true\n try {\n await pushAllBluetoothSettings()\n await BluetoothSdk.connectDefault()\n } catch (error) {\n recordSupportProfileConnectionFailure(error, \"reconnect\")\n console.warn(\"engine.glasses.reconnect failed:\", error)\n return false\n }\n return true\n },\n /** True when no glasses has ever been paired NOR selected (the pairing-identity\n * lifecycle is in its `none` state) — e.g. to route a first-run host into the\n * pairing/onboarding flow. A pending selection is not \"first\" — the host should\n * offer finish-pairing (see `engine.pairing.identity()`). */\n isFirstPairing: (): boolean => projectPairingIdentity().kind === \"none\",\n /**\n * True when the SDK has an actual default DEVICE to reconnect to. Distinct from\n * `default_wearable` (a model string that a pending or orphaned selection can\n * hold without any paired device): connectDefault() throws without a device, so\n * hosts should route to the pairing flow when this is false.\n *\n * Hydration-aware: awaits the device-store seed internally, so a cold-start\n * read can't see a false \"absent\" for genuinely-paired users. Rejects if\n * hydration failed — callers guarding destructive or routing decisions must\n * fail open (treat as \"has a device\").\n */\n hasDefaultDevice: (): Promise<boolean> => hasDefaultDevice(),\n\n // --- read-model (projected from the engine-owned glasses store) ---\n status: (): GlassesStatusSnapshot => projectStatus(),\n onStatus: (cb: (status: GlassesStatusSnapshot) => void): (() => void) => subscribeProjection(projectStatus, cb),\n info: (): GlassesInfoSnapshot => projectInfo(),\n onInfo: (cb: (info: GlassesInfoSnapshot) => void): (() => void) => subscribeProjection(projectInfo, cb),\n capabilities: () => getModelCapabilities(useGlassesStore.getState().deviceModel as DeviceTypes),\n /** Ask the glasses to report fresh firmware/version info (updates the store). */\n requestVersionInfo: () => BluetoothSdk.requestVersionInfo(),\n\n // --- discrete input events (passthrough listeners) ---\n onButtonPress: (cb: (event: ButtonPressEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"button_press\", cb)\n return () => sub.remove()\n },\n onTouchGesture: (cb: (event: TouchEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"touch_event\", cb)\n return () => sub.remove()\n },\n\n // --- BLE keyboard bridged through G2 Glassly CFW (revision 39+) ---\n keyboard: {\n /** Five-second scan; distinct advertisers, HID ones flagged. Also streams via onAdvert. */\n scan: (): Promise<KeyboardAdvertEvent[]> => BluetoothSdk.g2KeyboardScan(),\n /** Connect, pair and subscribe; the keyboard is remembered and auto-reconnected. */\n connect: async (device: {address: string; addressType: number; name: string}): Promise<void> => {\n await BluetoothSdk.g2KeyboardConnect(device.address, device.addressType, device.name)\n useSettingsStore.getState().setSetting(SETTINGS.keyboard_name.key, device.name)\n },\n reconnect: (): Promise<void> => BluetoothSdk.g2KeyboardReconnect(),\n disconnect: (): Promise<void> => BluetoothSdk.g2KeyboardDisconnect(),\n forget: async (): Promise<void> => {\n await BluetoothSdk.g2KeyboardForget()\n useSettingsStore.getState().setSetting(SETTINGS.keyboard_name.key, \"\")\n },\n passkey: (pin: number): Promise<void> => BluetoothSdk.g2KeyboardPasskey(pin),\n compare: (accept: boolean): Promise<void> => BluetoothSdk.g2KeyboardCompare(accept),\n status: (): KeyboardStatusSnapshot => projectKeyboardStatus(),\n onStatus: (cb: (status: KeyboardStatusSnapshot) => void): (() => void) => {\n let last = JSON.stringify(projectKeyboardStatus())\n return useGlassesStore.subscribe(() => {\n const snap = projectKeyboardStatus()\n const key = JSON.stringify(snap)\n if (key === last) return\n last = key\n cb(snap)\n })\n },\n onAdvert: (cb: (advert: KeyboardAdvertEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"keyboard_advert\", cb)\n return () => sub.remove()\n },\n onPairing: (cb: (prompt: KeyboardPairingEvent) => void): (() => void) => {\n const sub = BluetoothSdk.addListener(\"keyboard_pairing\", cb)\n return () => sub.remove()\n },\n },\n\n // --- controllers (input accessories linked to the phone), by registry id ---\n controllers: {\n /** Paired controllers in pairing order. */\n list: (): PairedController[] => projectControllerList(),\n onList: (cb: (controllers: PairedController[]) => void): (() => void) => {\n let last = JSON.stringify(projectControllerList())\n return useSettingsStore.subscribe(() => {\n const list = projectControllerList()\n const key = JSON.stringify(list)\n if (key === last) return\n last = key\n cb(list)\n })\n },\n /** Live driver statuses by id; a paired controller without an entry is idle. */\n statuses: (): Record<string, ControllerStatus> => projectControllerStatuses(),\n status: (id: string): ControllerStatus | undefined => projectControllerStatuses()[id],\n onStatus: (cb: (statuses: Record<string, ControllerStatus>) => void): (() => void) =>\n subscribeProjection(projectControllerStatuses, cb),\n /** Controllers delivering input (linked, route or claim done). */\n connected: (): ControllerStatus[] => readyControllers(projectControllerStatuses()),\n isConnected: (model?: string): boolean =>\n Object.values(projectControllerStatuses()).some(\n (status) => isControllerReady(status) && (model === undefined || status.model === model),\n ),\n connect: (id: string): Promise<void> => BluetoothSdk.connectController(id),\n /** Reconnect every paired controller that is not connected. */\n connectAll: (): Promise<void> => BluetoothSdk.connectControllers(),\n /** Drop an in-flight controller scan or pairing; paired records are untouched. */\n cancelAttempt: (): Promise<void> => BluetoothSdk.cancelControllerAttempt(),\n /** Disconnect; the controller stays paired. */\n disconnect: (id: string): Promise<void> => BluetoothSdk.disconnectController(id),\n forget: async (id: string): Promise<void> => {\n await BluetoothSdk.forgetController(id)\n neuralBandInput.forget(id)\n },\n },\n\n // --- Meta Neural Band (a controller with a claim step and its own features), by controller id ---\n neuralBand: {\n /** Store the Meta account session the one-time band claim uses (account-wide). */\n setMetaSession: (accessToken: string, userId: string): Promise<void> =>\n BluetoothSdk.neuralBandSetMetaSession(accessToken, userId),\n clearMetaSession: (): Promise<void> => BluetoothSdk.neuralBandClearMetaSession(),\n hasMetaSession: (): Promise<boolean> => BluetoothSdk.neuralBandHasMetaSession(),\n /** This band's identity is stored on this phone, so it reconnects without a claim. */\n isClaimed: (id: string): Promise<boolean> => BluetoothSdk.neuralBandIsClaimed(id),\n /** The latest claim progress of any band (with its `controllerId`), kept across screens. */\n claimStatus: (): NeuralBandClaimStatus => ({...neuralBandInput.claimStatus()}),\n resetClaim: (): void => neuralBandInput.resetClaim(),\n onClaimStatus: (cb: (status: NeuralBandClaimStatus) => void): (() => void) => neuralBandInput.onClaimStatus(cb),\n /** The band's handwriting model; writing arrives on the miniapp keyboard stream. */\n setHandwriting: (id: string, enabled: boolean): Promise<void> => BluetoothSdk.neuralBandSetHandwriting(id, enabled),\n handwritingStatus: (id: string): NeuralBandHandwritingStatus => ({...neuralBandInput.handwritingStatus(id)}),\n onHandwritingStatus: (cb: (update: NeuralBandHandwritingUpdate) => void): (() => void) =>\n neuralBandInput.onHandwritingStatus(cb),\n /** The band's air mouse; movement reaches miniapps on the pointer stream. */\n setPointer: (id: string, enabled: boolean): Promise<void> => BluetoothSdk.neuralBandSetPointer(id, enabled),\n setHand: (id: string, hand: \"left\" | \"right\"): Promise<void> => BluetoothSdk.neuralBandSetHand(id, hand),\n firmwareStatus: (id: string): NeuralBandFirmwareStatus => ({...neuralBandInput.firmwareStatus(id)}),\n onFirmwareStatus: (cb: (update: {id: string; status: NeuralBandFirmwareStatus}) => void): (() => void) =>\n neuralBandInput.onFirmwareStatus(cb),\n refreshFirmware: async (id: string): Promise<NeuralBandFirmwareStatus> => {\n const info = await BluetoothSdk.neuralBandFirmwareInfo(id)\n neuralBandInput.handleFirmware({\n ...(info as object),\n type: \"neural_band_firmware\",\n controllerId: id,\n } as NeuralBandFirmwareEvent)\n return neuralBandInput.firmwareStatus(id)\n },\n requestFirmwareStatus: (id: string): Promise<void> => BluetoothSdk.neuralBandRequestFirmwareStatus(id),\n checkFirmware: (id: string): Promise<void> => BluetoothSdk.neuralBandCheckFirmware(id),\n updateFirmware: (id: string, mode: \"update\" | \"cancel\" | \"key\" | \"send\" | \"trial\" | \"install\"): Promise<void> =>\n BluetoothSdk.neuralBandUpdateFirmware(id, mode),\n },\n\n // --- watch: an Apple Watch over WatchConnectivity (iOS), a Wear OS watch over the Data Layer (Android) ---\n watch: {\n /** Whether this phone has a paired watch and the Glassly watch app is on it. */\n availability: (): Promise<WatchAvailability> => BluetoothSdk.watchAvailability(),\n },\n\n // --- audio (glasses media-volume, own-app playback hint, live mic level) ---\n audio: {\n /** Read the glasses' current media volume. */\n getMediaVolume: () => BluetoothSdk.getGlassesMediaVolume(),\n /** Set the glasses' media volume. */\n setMediaVolume: (level: number) => BluetoothSdk.setGlassesMediaVolume(level),\n /** Tell native whether THIS app is currently playing audio (for ducking). */\n setOwnAppPlaying: (playing: boolean): Promise<void> => BluetoothSdk.setOwnAppAudioPlaying(playing),\n /**\n * Stream the active mic's level in dBFS, one reading per PCM chunk. Holds\n * raw PCM open while subscribed, so the mic runs with no miniapp listening,\n * and holds the G2 volume gate open so the meter shows the ambient level.\n */\n onMicLevel: (cb: (dbfs: number) => void): (() => void) => {\n const owner = `mic_level_${++micLevelSubscriptions}`\n micStateCoordinator.acquireHostPcm(owner)\n const sub = BluetoothSdk.addListener(\"mic_pcm\", (event: {pcm: ArrayBuffer | Uint8Array}) => {\n if (event?.pcm) cb(pcmLevelDbfs(event.pcm))\n })\n return () => {\n sub.remove()\n micStateCoordinator.releaseHostPcm(owner)\n }\n },\n },\n\n // --- sub-facades ---\n wifi: glassesWifi,\n settings: glassesSettings,\n}\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export const ENGINE_RELEASE_METADATA = Object.freeze({
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"familyBaseVersion": "0.3.8",
|
|
4
|
-
"releaseIdentity": "0.3.8-dev.
|
|
5
|
-
"releaseSetId": "glassly-0.3.8-dev.
|
|
6
|
-
"sourceCommit": "
|
|
4
|
+
"releaseIdentity": "0.3.8-dev.1006",
|
|
5
|
+
"releaseSetId": "glassly-0.3.8-dev.1006",
|
|
6
|
+
"sourceCommit": "659d87701629ff1aa6865e2325c3181a7d19fe6a",
|
|
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,gBAAgB;IACnC,cAAc,EAAE,wBAAwB;IACxC,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.3.8\",\n \"releaseIdentity\": \"0.3.8-dev.
|
|
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,gBAAgB;IACnC,cAAc,EAAE,wBAAwB;IACxC,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.3.8\",\n \"releaseIdentity\": \"0.3.8-dev.1006\",\n \"releaseSetId\": \"glassly-0.3.8-dev.1006\",\n \"sourceCommit\": \"659d87701629ff1aa6865e2325c3181a7d19fe6a\",\n \"otaManifestUrl\": null,\n \"otaManifestSha256\": null\n})\n"]}
|
package/build/index.d.ts
CHANGED
|
@@ -55,7 +55,7 @@ export { decideDevLaunchRoute, type DecideDevLaunchOptions, type DevLaunchResult
|
|
|
55
55
|
export { HardwareCompatibility, type CompatibilityResult } from "./utils/hardware";
|
|
56
56
|
export { BgTimer } from "./utils/timers";
|
|
57
57
|
export { MetaAuthError, authEntryUrl, callbackMatches, callbackQuery, decryptBlob, isLoginCallback, login, tokensQuery, type MetaSession, type MetaSsoTokens, } from "./services/neuralBand/MetaAuth";
|
|
58
|
-
export type { NeuralBandClaimStatus, NeuralBandHandwritingStatus, NeuralBandHandwritingUpdate, } from "./services/neuralBand/NeuralBandInput";
|
|
58
|
+
export type { NeuralBandClaimStatus, NeuralBandFirmwareStatus, NeuralBandHandwritingStatus, NeuralBandHandwritingUpdate, } from "./services/neuralBand/NeuralBandInput";
|
|
59
59
|
export { HardwareType, HardwareRequirementLevel, DeviceTypes, ControllerTypes, HARDWARE_CAPABILITIES, getModelCapabilities, simulatedGlasses, evenRealitiesG1, evenRealitiesG2, mentraLive, nimo, rayneoIO, vuzixZ100, mentraDisplay, } from "./types";
|
|
60
60
|
export type { HardwareRequirement, CameraCapabilities, DisplayCapabilities, MicrophoneCapabilities, SpeakerCapabilities, IMUCapabilities, ButtonCapabilities, LightCapabilities, PowerCapabilities, Capabilities, AppletType, AppPermissionType, AppletPermission, AppletInterface, ClientApp, } from "./types";
|
|
61
61
|
//# sourceMappingURL=index.d.ts.map
|
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":"AAAA;;;;;;;;;;GAUG;AAEH,2EAA2E;AAC3E,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAY/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;AAOvC,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 {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 NeuralBandHandwritingStatus,\n NeuralBandHandwritingUpdate,\n} from \"./services/neuralBand/NeuralBandInput\"\n\n// Hardware types and capability profiles.\nexport {\n HardwareType,\n HardwareRequirementLevel,\n DeviceTypes,\n ControllerTypes,\n HARDWARE_CAPABILITIES,\n getModelCapabilities,\n simulatedGlasses,\n evenRealitiesG1,\n evenRealitiesG2,\n mentraLive,\n nimo,\n rayneoIO,\n vuzixZ100,\n mentraDisplay,\n} from \"./types\"\nexport type {\n HardwareRequirement,\n CameraCapabilities,\n DisplayCapabilities,\n MicrophoneCapabilities,\n SpeakerCapabilities,\n IMUCapabilities,\n ButtonCapabilities,\n LightCapabilities,\n PowerCapabilities,\n Capabilities,\n AppletType,\n AppPermissionType,\n AppletPermission,\n AppletInterface,\n ClientApp,\n} from \"./types\"\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `@glassly/engine` — the OEM-facing main entry.\n *\n * The `engine` namespace (configure/start/stop + typed domain facades), the\n * public contract/read-model types, and the pure helpers host UI legitimately\n * renders with (decision functions, sort/order helpers, policy constants,\n * capability tables, timers). Judgment rule: read models, commands, pure\n * functions and types belong here; anything that mutates runtime state or\n * exposes a raw store/service remains private to the Glassly host.\n * See cloud/docs/issues/020-glasses-status-boundary/integration-review.md §D.\n */\n\n// The namespaced OEM-facing engine API (the \"(A) host API\"). See ./engine.\nexport {engine} from \"./engine\"\nexport type {\n ReportAttachmentInput,\n ReportContext,\n ReportDetails,\n ReportStatus,\n ReportTrigger,\n ReportSubmitResult,\n EngineSubmitReportInput,\n} from \"./facades/reports\"\nexport type {IslandNotification, IslandNotificationKind} from \"./facades/notifications\"\nexport type {PresentationOwner} from \"./services/notifications/notificationPolicy\"\nexport {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":"DeviceEventRouter.d.ts","sourceRoot":"","sources":["../../src/services/DeviceEventRouter.ts"],"names":[],"mappings":"AAiDA,wBAAgB,sBAAsB,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"DeviceEventRouter.d.ts","sourceRoot":"","sources":["../../src/services/DeviceEventRouter.ts"],"names":[],"mappings":"AAiDA,wBAAgB,sBAAsB,IAAI,IAAI,CAgQ7C;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAI5C"}
|
|
@@ -190,6 +190,7 @@ export function startDeviceEventRouter() {
|
|
|
190
190
|
subs.push(BluetoothSdk.addListener("neural_band_claim", (event) => neuralBandInput.handleClaim(event)));
|
|
191
191
|
subs.push(BluetoothSdk.addListener("neural_band_handwriting", (event) => neuralBandInput.handleHandwriting(event)));
|
|
192
192
|
subs.push(BluetoothSdk.addListener("neural_band_pointer", (event) => neuralBandInput.handlePointer(event)));
|
|
193
|
+
subs.push(BluetoothSdk.addListener("neural_band_firmware", (event) => neuralBandInput.handleFirmware(event)));
|
|
193
194
|
subs.push({
|
|
194
195
|
remove: useGlassesStore.subscribe((s) => s.keyboardConnected === true, (connected) => {
|
|
195
196
|
if (!connected)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeviceEventRouter.js","sourceRoot":"","sources":["../../src/services/DeviceEventRouter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Device-event router — engine-owned. Subscribes to the inbound native BLE/device\n * events and routes them into the engine runtime: device stores, the process event\n * bus, the photo/stream coordinators, and local miniapps (via forwardEvent).\n *\n * Why this exists: engine owns the stores, coordinators, miniapp runtime, and facades,\n * but it never *subscribed to the device* for most events — the host MantleManager was\n * still the event router the whole runtime secretly depended on. So a bare OEM that\n * imported engine + called engine.start() got a connected runtime with almost no device\n * data flowing in (no miniapp input, dead gallery sync, starved coordinators). This\n * service moves those inbound bridges into engine so ANY host gets them.\n *\n * Scope: the engine legs only. The Cloud V1 relays that used to live beside them in\n * MantleManager (touch→cloud, the cloud-SDK stream/photo legs, etc.) were deleted with\n * Cloud V1 app end-of-life.\n *\n * Started by `engine.start()`. Idempotent.\n */\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport {shallow} from \"zustand/shallow\"\n\nimport localMiniappRuntime from \"./LocalMiniappRuntime\"\nimport glassesKeyboardInput from \"./GlassesKeyboardInput\"\nimport glassesSensorService from \"./GlassesSensorService\"\nimport localSttFallbackCoordinator from \"./LocalSttFallbackCoordinator\"\nimport localTranslationService from \"./LocalTranslationService\"\nimport speakerLabelResolver from \"./SpeakerLabelResolver\"\nimport {phonePhotoCoordinator} from \"./PhonePhotoCoordinator\"\nimport {phoneStreamCoordinator} from \"./PhoneStreamCoordinator\"\nimport {isGlassesConnected} from \"./GlassesReadiness\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore} from \"../stores/settings\"\nimport {useAppStatusStore} from \"../stores/apps\"\nimport {retirePendingSelectionOnPromotion} from \"./PairingIdentity\"\nimport GlobalEventEmitter from \"../utils/GlobalEventEmitter\"\nimport {asgCameraApi} from \"./asg/asgCameraApi\"\nimport {dispatchTouchEvent, resetTouchInput} from \"./GlassesTouchInput\"\nimport neuralBandInput from \"./neuralBand/NeuralBandInput\"\nimport dashboardOpenTrace from \"./debug/DashboardOpenTrace\"\n\nlet subs: Array<{remove: () => void}> = []\n\n// Array/object echoes (the controller registry) arrive as fresh objects.\nfunction sameSettingValue(current: unknown, next: unknown): boolean {\n if (current === next) return true\n if (typeof current !== \"object\" || typeof next !== \"object\" || current === null || next === null) return false\n return JSON.stringify(current) === JSON.stringify(next)\n}\n\nexport function startDeviceEventRouter(): void {\n if (subs.length) return\n\n subs.push(\n BluetoothSdk.addListener(\"light_sensor\", ({type: _type, ...reading}) => {\n localMiniappRuntime.forwardEvent(\"light_sensor\", reading)\n }),\n // Stock firmware emits these only inside its nav UI; custom firmware whenever the\n // raw compass runs. Either way they feed the one session.compass stream.\n BluetoothSdk.addListener(\"compass_heading\", ({type: _type, heading, ...reading}) => {\n localMiniappRuntime.forwardEvent(\"glasses_compass\", {degrees: heading, ...reading})\n }),\n BluetoothSdk.addListener(\"compass_calibration\", ({type: _type, ...reading}) => {\n localMiniappRuntime.forwardEvent(\"compass_calibration\", reading)\n }),\n {\n remove: useGlassesStore.subscribe(\n (s) => s.connection,\n (connection) => {\n if (isGlassesConnected(connection)) void glassesSensorService.resync()\n else glassesSensorService.disconnected()\n },\n ),\n },\n {\n // CFW classification lands after device-ready; compass demand recorded before\n // that only reaches the firmware once the scene canvas is published.\n remove: useGlassesStore.subscribe(\n (s) => s.sceneCanvasWidth,\n (width) => {\n if ((width ?? 0) > 0) void glassesSensorService.resync()\n },\n ),\n },\n )\n\n // --- device state → engine stores ---\n\n // Standalone WiFi status → glasses store.\n subs.push(\n BluetoothSdk.addListener(\"wifi_status_change\", (event) => {\n const {type: _type, ...wifi} = event\n useGlassesStore.getState().setGlassesInfo({wifi})\n }),\n )\n\n // Forward glasses Wi-Fi to miniapps (session.glasses.onWifi) from the STORE — the\n // single source of truth — so every path converges here: wifi_status_change,\n // onGlassesStatus, and BLE disconnect. Effective connectivity requires the glasses\n // to be connected AND on Wi-Fi, so a disconnect correctly flips `connected` false.\n subs.push({\n remove: useGlassesStore.subscribe(\n (s) => {\n const connected = isGlassesConnected(s.connection) && s.wifi.state === \"connected\"\n return {\n connected,\n ssid: s.wifi.state === \"connected\" ? s.wifi.ssid : undefined,\n localIp: s.wifi.state === \"connected\" ? s.wifi.localIp : undefined,\n }\n },\n (wifi) => localMiniappRuntime.forwardEvent(\"glasses_wifi\", wifi),\n {equalityFn: shallow},\n ),\n })\n\n // Battery streams follow the store, including initial native hydration and\n // onGlassesStatus patches. G2 can report its level without battery_status;\n // forwarding only that legacy event leaves a running dashboard ring-only.\n subs.push({\n remove: useGlassesStore.subscribe(\n (s) => ({level: s.batteryLevel, charging: s.charging}),\n (battery) => {\n localMiniappRuntime.forwardEvent(\"glasses_battery_update\", {\n type: \"glasses_battery_update\",\n ...battery,\n timestamp: Date.now(),\n })\n },\n {equalityFn: shallow},\n ),\n })\n\n // Legacy standalone events feed the same store subscription.\n subs.push(\n BluetoothSdk.addListener(\"battery_status\", (event) => {\n const state = useGlassesStore.getState()\n state.setBatteryInfo(event.level, event.charging, state.caseBatteryLevel, state.caseCharging)\n }),\n )\n\n // Hotspot status → glasses store + event bus. engine's own gallerySyncService listens\n // on the bus for these, so without this bridge engine's gallery sync is dead.\n subs.push(\n BluetoothSdk.addListener(\"hotspot_status_change\", (event) => {\n const enabled = event.state === \"enabled\"\n const ssid = enabled ? event.ssid : \"\"\n const password = enabled ? event.password : \"\"\n const localIp = enabled ? event.localIp : \"\"\n useGlassesStore.getState().setHotspotInfo(enabled, ssid, password, localIp)\n // Always retarget the ASG camera client: on disable (or an event with no\n // IP) fall back to the localhost default so later calls fail fast instead\n // of hitting the previous network's stale glasses IP.\n asgCameraApi.setServer(localIp || \"localhost\", 8089)\n GlobalEventEmitter.emit(\"hotspot_status_change\", {enabled, ssid, password, local_ip: localIp})\n }),\n )\n subs.push(\n BluetoothSdk.addListener(\"hotspot_error\", (event) => {\n GlobalEventEmitter.emit(\"hotspot_error\", {error_message: event.errorMessage, timestamp: event.timestamp})\n }),\n )\n\n // Glasses gallery content counts → event bus (consumed by gallerySyncService).\n subs.push(\n BluetoothSdk.addListener(\"gallery_status\", (event) => {\n GlobalEventEmitter.emit(\"gallery_status\", {\n photos: event.photos,\n videos: event.videos,\n total: event.total,\n has_content: event.hasContent,\n camera_busy: event.cameraBusy,\n })\n }),\n )\n\n // Hardware-originated setting changes (user changes a setting ON the glasses) → store.\n // The inbound complement to GlassesSettingsSync (which only pushes store→device).\n subs.push(\n BluetoothSdk.addListener(\"save_setting\", async (event) => {\n const settings = useSettingsStore.getState()\n // Damp the relay: native re-echoes some settings unconditionally (e.g.\n // the identity block at every handleDeviceReady) — a same-value echo\n // must not become a store write (persistence churn + change-push noise).\n if (!sameSettingValue(settings.getSetting(event.key), event.value)) {\n await settings.setSetting(event.key, event.value)\n }\n // Two-phase identity: a promoted default retires the pending selection\n // marker. The rule lives with PairingIdentity (a no-op for other keys).\n await retirePendingSelectionOnPromotion(event.key, event.value)\n }),\n )\n\n // --- coordinators (owns()-gated) ---\n\n // Phone-owned photo errors settle the in-flight long-poll fast (vs. timeout).\n // Non-owned photo responses used to forward to the Cloud V1 photo pipeline via\n // restComms; that relay was removed with Cloud V1 app end-of-life, so they drop.\n // Wire v2 sends a short 4-hex BLE requestId; the coordinator maps it back to\n // the cloud requestId (resolveCloudRequestId) before ownership checks.\n subs.push(\n BluetoothSdk.addListener(\"photo_response\", (event) => {\n const cloudRequestId = event.requestId ? phonePhotoCoordinator.resolveCloudRequestId(event.requestId) : \"\"\n if (cloudRequestId && phonePhotoCoordinator.owns(cloudRequestId)) {\n if (event.state === \"error\") {\n phonePhotoCoordinator.handlePhotoError(\n event.requestId ?? cloudRequestId,\n event.errorCode ?? \"GLASSES_ERROR\",\n event.errorMessage ?? \"Glasses reported an error\",\n )\n }\n }\n }),\n )\n\n // Phone-owned stream status / keep-alive → the stream coordinator. The Cloud V1 relay\n // for non-owned streams was removed with Cloud V1 app end-of-life.\n subs.push(\n BluetoothSdk.addListener(\"stream_status\", (event) => {\n if (event.streamId && phoneStreamCoordinator.owns(event.streamId)) {\n phoneStreamCoordinator.handleGlassesStatus(event)\n }\n }),\n )\n subs.push(\n BluetoothSdk.addListener(\"keep_alive_ack\", (event) => {\n if (event.streamId && phoneStreamCoordinator.owns(event.streamId)) {\n phoneStreamCoordinator.handleKeepAliveAck(event)\n }\n }),\n )\n\n // --- device input → local miniapps (forwardEvent is subscriber-gated; a no-op when\n // no miniapp listens). The v1 SocketComms cloud legs for these were removed with\n // the Cloud V1 ripout. ---\n\n subs.push(\n BluetoothSdk.addListener(\"button_press\", (event) => {\n localMiniappRuntime.forwardEvent(\"button_press\", event)\n }),\n )\n subs.push(BluetoothSdk.addListener(\"touch_event\", dispatchTouchEvent))\n // Physical keyboard bridged through G2 Glassly CFW: raw HID transitions →\n // layout-translated keyboard_event stream (with synthesized auto-repeat).\n subs.push(BluetoothSdk.addListener(\"keyboard_key\", (event) => glassesKeyboardInput.handle(event)))\n // Meta Neural Band: its gestures ride touch_event above; these are its own streams.\n subs.push(BluetoothSdk.addListener(\"neural_band_claim\", (event) => neuralBandInput.handleClaim(event)))\n subs.push(BluetoothSdk.addListener(\"neural_band_handwriting\", (event) => neuralBandInput.handleHandwriting(event)))\n subs.push(BluetoothSdk.addListener(\"neural_band_pointer\", (event) => neuralBandInput.handlePointer(event)))\n subs.push({\n remove: useGlassesStore.subscribe(\n (s) => s.keyboardConnected === true,\n (connected) => {\n if (!connected) glassesKeyboardInput.reset()\n },\n ),\n })\n // G2 IMU accelerometer — payload already matches the miniapp AccelData shape.\n subs.push(\n BluetoothSdk.addListener(\"accel_event\", (event) => {\n localMiniappRuntime.forwardEvent(\"accel_event\", {\n x: event.x,\n y: event.y,\n z: event.z,\n timestamp: typeof event.timestamp === \"number\" ? event.timestamp : Date.now(),\n })\n }),\n )\n subs.push({remove: dashboardOpenTrace.start()})\n // On-device STT transcripts → local miniapps only while the local engine is\n // active (cloud fallback or an explicit forceLocal subscription). The runtime\n // filters mixed local/cloud delivery per miniapp to avoid double-delivery.\n // forwardEvent is subscriber-gated — a no-op when no miniapp listens.\n // (Was MantleManager.handle_local_transcription; its offline-captions display branch\n // went away with the pseudo captions renderer.)\n subs.push(\n BluetoothSdk.addListener(\"local_transcription\", (event) => {\n if (!localSttFallbackCoordinator.isActive()) return\n const lang = event.transcribeLanguage ?? localSttFallbackCoordinator.getActiveLanguage() ?? \"en-US\"\n // Native stamps resolvedSpeakerId when the voice matched the enrolled\n // profile; surface that as `isUser` (the native join has no\n // confident-other signal, so unmatched stays unannotated).\n localMiniappRuntime.forwardEvent(\n `transcription:${lang}`,\n speakerLabelResolver.annotateLocalTranscript(event),\n \"local\",\n )\n localTranslationService.onLocalTranscript(event, lang)\n }),\n )\n\n // --- glasses swipe-menu app launcher (G2) ---\n subs.push(\n BluetoothSdk.addListener(\"miniapp_selected\", (event) => {\n const packageName = event.packageName as string\n if (!packageName) return\n const app = useAppStatusStore.getState().apps.find((a) => a.packageName === packageName)\n if (!app) return\n // Toggle: stop if running, else start.\n if (app.running) {\n useAppStatusStore.getState().stop(packageName)\n } else {\n useAppStatusStore.getState().start(app, {skipNavigation: true, launchSource: \"glasses\"})\n }\n }),\n )\n}\n\nexport function stopDeviceEventRouter(): void {\n for (const sub of subs) sub.remove()\n subs = []\n resetTouchInput()\n}\n"]}
|
|
1
|
+
{"version":3,"file":"DeviceEventRouter.js","sourceRoot":"","sources":["../../src/services/DeviceEventRouter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Device-event router — engine-owned. Subscribes to the inbound native BLE/device\n * events and routes them into the engine runtime: device stores, the process event\n * bus, the photo/stream coordinators, and local miniapps (via forwardEvent).\n *\n * Why this exists: engine owns the stores, coordinators, miniapp runtime, and facades,\n * but it never *subscribed to the device* for most events — the host MantleManager was\n * still the event router the whole runtime secretly depended on. So a bare OEM that\n * imported engine + called engine.start() got a connected runtime with almost no device\n * data flowing in (no miniapp input, dead gallery sync, starved coordinators). This\n * service moves those inbound bridges into engine so ANY host gets them.\n *\n * Scope: the engine legs only. The Cloud V1 relays that used to live beside them in\n * MantleManager (touch→cloud, the cloud-SDK stream/photo legs, etc.) were deleted with\n * Cloud V1 app end-of-life.\n *\n * Started by `engine.start()`. Idempotent.\n */\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport {shallow} from \"zustand/shallow\"\n\nimport localMiniappRuntime from \"./LocalMiniappRuntime\"\nimport glassesKeyboardInput from \"./GlassesKeyboardInput\"\nimport glassesSensorService from \"./GlassesSensorService\"\nimport localSttFallbackCoordinator from \"./LocalSttFallbackCoordinator\"\nimport localTranslationService from \"./LocalTranslationService\"\nimport speakerLabelResolver from \"./SpeakerLabelResolver\"\nimport {phonePhotoCoordinator} from \"./PhonePhotoCoordinator\"\nimport {phoneStreamCoordinator} from \"./PhoneStreamCoordinator\"\nimport {isGlassesConnected} from \"./GlassesReadiness\"\nimport {useGlassesStore} from \"../stores/glasses\"\nimport {useSettingsStore} from \"../stores/settings\"\nimport {useAppStatusStore} from \"../stores/apps\"\nimport {retirePendingSelectionOnPromotion} from \"./PairingIdentity\"\nimport GlobalEventEmitter from \"../utils/GlobalEventEmitter\"\nimport {asgCameraApi} from \"./asg/asgCameraApi\"\nimport {dispatchTouchEvent, resetTouchInput} from \"./GlassesTouchInput\"\nimport neuralBandInput from \"./neuralBand/NeuralBandInput\"\nimport dashboardOpenTrace from \"./debug/DashboardOpenTrace\"\n\nlet subs: Array<{remove: () => void}> = []\n\n// Array/object echoes (the controller registry) arrive as fresh objects.\nfunction sameSettingValue(current: unknown, next: unknown): boolean {\n if (current === next) return true\n if (typeof current !== \"object\" || typeof next !== \"object\" || current === null || next === null) return false\n return JSON.stringify(current) === JSON.stringify(next)\n}\n\nexport function startDeviceEventRouter(): void {\n if (subs.length) return\n\n subs.push(\n BluetoothSdk.addListener(\"light_sensor\", ({type: _type, ...reading}) => {\n localMiniappRuntime.forwardEvent(\"light_sensor\", reading)\n }),\n // Stock firmware emits these only inside its nav UI; custom firmware whenever the\n // raw compass runs. Either way they feed the one session.compass stream.\n BluetoothSdk.addListener(\"compass_heading\", ({type: _type, heading, ...reading}) => {\n localMiniappRuntime.forwardEvent(\"glasses_compass\", {degrees: heading, ...reading})\n }),\n BluetoothSdk.addListener(\"compass_calibration\", ({type: _type, ...reading}) => {\n localMiniappRuntime.forwardEvent(\"compass_calibration\", reading)\n }),\n {\n remove: useGlassesStore.subscribe(\n (s) => s.connection,\n (connection) => {\n if (isGlassesConnected(connection)) void glassesSensorService.resync()\n else glassesSensorService.disconnected()\n },\n ),\n },\n {\n // CFW classification lands after device-ready; compass demand recorded before\n // that only reaches the firmware once the scene canvas is published.\n remove: useGlassesStore.subscribe(\n (s) => s.sceneCanvasWidth,\n (width) => {\n if ((width ?? 0) > 0) void glassesSensorService.resync()\n },\n ),\n },\n )\n\n // --- device state → engine stores ---\n\n // Standalone WiFi status → glasses store.\n subs.push(\n BluetoothSdk.addListener(\"wifi_status_change\", (event) => {\n const {type: _type, ...wifi} = event\n useGlassesStore.getState().setGlassesInfo({wifi})\n }),\n )\n\n // Forward glasses Wi-Fi to miniapps (session.glasses.onWifi) from the STORE — the\n // single source of truth — so every path converges here: wifi_status_change,\n // onGlassesStatus, and BLE disconnect. Effective connectivity requires the glasses\n // to be connected AND on Wi-Fi, so a disconnect correctly flips `connected` false.\n subs.push({\n remove: useGlassesStore.subscribe(\n (s) => {\n const connected = isGlassesConnected(s.connection) && s.wifi.state === \"connected\"\n return {\n connected,\n ssid: s.wifi.state === \"connected\" ? s.wifi.ssid : undefined,\n localIp: s.wifi.state === \"connected\" ? s.wifi.localIp : undefined,\n }\n },\n (wifi) => localMiniappRuntime.forwardEvent(\"glasses_wifi\", wifi),\n {equalityFn: shallow},\n ),\n })\n\n // Battery streams follow the store, including initial native hydration and\n // onGlassesStatus patches. G2 can report its level without battery_status;\n // forwarding only that legacy event leaves a running dashboard ring-only.\n subs.push({\n remove: useGlassesStore.subscribe(\n (s) => ({level: s.batteryLevel, charging: s.charging}),\n (battery) => {\n localMiniappRuntime.forwardEvent(\"glasses_battery_update\", {\n type: \"glasses_battery_update\",\n ...battery,\n timestamp: Date.now(),\n })\n },\n {equalityFn: shallow},\n ),\n })\n\n // Legacy standalone events feed the same store subscription.\n subs.push(\n BluetoothSdk.addListener(\"battery_status\", (event) => {\n const state = useGlassesStore.getState()\n state.setBatteryInfo(event.level, event.charging, state.caseBatteryLevel, state.caseCharging)\n }),\n )\n\n // Hotspot status → glasses store + event bus. engine's own gallerySyncService listens\n // on the bus for these, so without this bridge engine's gallery sync is dead.\n subs.push(\n BluetoothSdk.addListener(\"hotspot_status_change\", (event) => {\n const enabled = event.state === \"enabled\"\n const ssid = enabled ? event.ssid : \"\"\n const password = enabled ? event.password : \"\"\n const localIp = enabled ? event.localIp : \"\"\n useGlassesStore.getState().setHotspotInfo(enabled, ssid, password, localIp)\n // Always retarget the ASG camera client: on disable (or an event with no\n // IP) fall back to the localhost default so later calls fail fast instead\n // of hitting the previous network's stale glasses IP.\n asgCameraApi.setServer(localIp || \"localhost\", 8089)\n GlobalEventEmitter.emit(\"hotspot_status_change\", {enabled, ssid, password, local_ip: localIp})\n }),\n )\n subs.push(\n BluetoothSdk.addListener(\"hotspot_error\", (event) => {\n GlobalEventEmitter.emit(\"hotspot_error\", {error_message: event.errorMessage, timestamp: event.timestamp})\n }),\n )\n\n // Glasses gallery content counts → event bus (consumed by gallerySyncService).\n subs.push(\n BluetoothSdk.addListener(\"gallery_status\", (event) => {\n GlobalEventEmitter.emit(\"gallery_status\", {\n photos: event.photos,\n videos: event.videos,\n total: event.total,\n has_content: event.hasContent,\n camera_busy: event.cameraBusy,\n })\n }),\n )\n\n // Hardware-originated setting changes (user changes a setting ON the glasses) → store.\n // The inbound complement to GlassesSettingsSync (which only pushes store→device).\n subs.push(\n BluetoothSdk.addListener(\"save_setting\", async (event) => {\n const settings = useSettingsStore.getState()\n // Damp the relay: native re-echoes some settings unconditionally (e.g.\n // the identity block at every handleDeviceReady) — a same-value echo\n // must not become a store write (persistence churn + change-push noise).\n if (!sameSettingValue(settings.getSetting(event.key), event.value)) {\n await settings.setSetting(event.key, event.value)\n }\n // Two-phase identity: a promoted default retires the pending selection\n // marker. The rule lives with PairingIdentity (a no-op for other keys).\n await retirePendingSelectionOnPromotion(event.key, event.value)\n }),\n )\n\n // --- coordinators (owns()-gated) ---\n\n // Phone-owned photo errors settle the in-flight long-poll fast (vs. timeout).\n // Non-owned photo responses used to forward to the Cloud V1 photo pipeline via\n // restComms; that relay was removed with Cloud V1 app end-of-life, so they drop.\n // Wire v2 sends a short 4-hex BLE requestId; the coordinator maps it back to\n // the cloud requestId (resolveCloudRequestId) before ownership checks.\n subs.push(\n BluetoothSdk.addListener(\"photo_response\", (event) => {\n const cloudRequestId = event.requestId ? phonePhotoCoordinator.resolveCloudRequestId(event.requestId) : \"\"\n if (cloudRequestId && phonePhotoCoordinator.owns(cloudRequestId)) {\n if (event.state === \"error\") {\n phonePhotoCoordinator.handlePhotoError(\n event.requestId ?? cloudRequestId,\n event.errorCode ?? \"GLASSES_ERROR\",\n event.errorMessage ?? \"Glasses reported an error\",\n )\n }\n }\n }),\n )\n\n // Phone-owned stream status / keep-alive → the stream coordinator. The Cloud V1 relay\n // for non-owned streams was removed with Cloud V1 app end-of-life.\n subs.push(\n BluetoothSdk.addListener(\"stream_status\", (event) => {\n if (event.streamId && phoneStreamCoordinator.owns(event.streamId)) {\n phoneStreamCoordinator.handleGlassesStatus(event)\n }\n }),\n )\n subs.push(\n BluetoothSdk.addListener(\"keep_alive_ack\", (event) => {\n if (event.streamId && phoneStreamCoordinator.owns(event.streamId)) {\n phoneStreamCoordinator.handleKeepAliveAck(event)\n }\n }),\n )\n\n // --- device input → local miniapps (forwardEvent is subscriber-gated; a no-op when\n // no miniapp listens). The v1 SocketComms cloud legs for these were removed with\n // the Cloud V1 ripout. ---\n\n subs.push(\n BluetoothSdk.addListener(\"button_press\", (event) => {\n localMiniappRuntime.forwardEvent(\"button_press\", event)\n }),\n )\n subs.push(BluetoothSdk.addListener(\"touch_event\", dispatchTouchEvent))\n // Physical keyboard bridged through G2 Glassly CFW: raw HID transitions →\n // layout-translated keyboard_event stream (with synthesized auto-repeat).\n subs.push(BluetoothSdk.addListener(\"keyboard_key\", (event) => glassesKeyboardInput.handle(event)))\n // Meta Neural Band: its gestures ride touch_event above; these are its own streams.\n subs.push(BluetoothSdk.addListener(\"neural_band_claim\", (event) => neuralBandInput.handleClaim(event)))\n subs.push(BluetoothSdk.addListener(\"neural_band_handwriting\", (event) => neuralBandInput.handleHandwriting(event)))\n subs.push(BluetoothSdk.addListener(\"neural_band_pointer\", (event) => neuralBandInput.handlePointer(event)))\n subs.push(BluetoothSdk.addListener(\"neural_band_firmware\", (event) => neuralBandInput.handleFirmware(event)))\n subs.push({\n remove: useGlassesStore.subscribe(\n (s) => s.keyboardConnected === true,\n (connected) => {\n if (!connected) glassesKeyboardInput.reset()\n },\n ),\n })\n // G2 IMU accelerometer — payload already matches the miniapp AccelData shape.\n subs.push(\n BluetoothSdk.addListener(\"accel_event\", (event) => {\n localMiniappRuntime.forwardEvent(\"accel_event\", {\n x: event.x,\n y: event.y,\n z: event.z,\n timestamp: typeof event.timestamp === \"number\" ? event.timestamp : Date.now(),\n })\n }),\n )\n subs.push({remove: dashboardOpenTrace.start()})\n // On-device STT transcripts → local miniapps only while the local engine is\n // active (cloud fallback or an explicit forceLocal subscription). The runtime\n // filters mixed local/cloud delivery per miniapp to avoid double-delivery.\n // forwardEvent is subscriber-gated — a no-op when no miniapp listens.\n // (Was MantleManager.handle_local_transcription; its offline-captions display branch\n // went away with the pseudo captions renderer.)\n subs.push(\n BluetoothSdk.addListener(\"local_transcription\", (event) => {\n if (!localSttFallbackCoordinator.isActive()) return\n const lang = event.transcribeLanguage ?? localSttFallbackCoordinator.getActiveLanguage() ?? \"en-US\"\n // Native stamps resolvedSpeakerId when the voice matched the enrolled\n // profile; surface that as `isUser` (the native join has no\n // confident-other signal, so unmatched stays unannotated).\n localMiniappRuntime.forwardEvent(\n `transcription:${lang}`,\n speakerLabelResolver.annotateLocalTranscript(event),\n \"local\",\n )\n localTranslationService.onLocalTranscript(event, lang)\n }),\n )\n\n // --- glasses swipe-menu app launcher (G2) ---\n subs.push(\n BluetoothSdk.addListener(\"miniapp_selected\", (event) => {\n const packageName = event.packageName as string\n if (!packageName) return\n const app = useAppStatusStore.getState().apps.find((a) => a.packageName === packageName)\n if (!app) return\n // Toggle: stop if running, else start.\n if (app.running) {\n useAppStatusStore.getState().stop(packageName)\n } else {\n useAppStatusStore.getState().start(app, {skipNavigation: true, launchSource: \"glasses\"})\n }\n }),\n )\n}\n\nexport function stopDeviceEventRouter(): void {\n for (const sub of subs) sub.remove()\n subs = []\n resetTouchInput()\n}\n"]}
|
|
@@ -6,7 +6,7 @@
|
|
|
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 { NeuralBandClaimEvent, NeuralBandHandwritingEvent, NeuralBandPointerEvent } from "@glassly/bluetooth-sdk";
|
|
9
|
+
import type { NeuralBandClaimEvent, NeuralBandFirmwareEvent, NeuralBandHandwritingEvent, NeuralBandPointerEvent } from "@glassly/bluetooth-sdk";
|
|
10
10
|
import type { KeyboardEventPayload } from "../GlassesKeyboardInput";
|
|
11
11
|
export interface NeuralBandClaimStatus {
|
|
12
12
|
stage: "idle" | "progress" | "completed" | "failed";
|
|
@@ -27,6 +27,9 @@ export interface NeuralBandHandwritingUpdate {
|
|
|
27
27
|
id: string;
|
|
28
28
|
status: NeuralBandHandwritingStatus;
|
|
29
29
|
}
|
|
30
|
+
export type NeuralBandFirmwareStatus = Omit<NeuralBandFirmwareEvent, "type" | "controllerId"> & {
|
|
31
|
+
known: boolean;
|
|
32
|
+
};
|
|
30
33
|
export interface NeuralBandInputOptions {
|
|
31
34
|
forward?: (stream: string, payload: unknown) => void;
|
|
32
35
|
now?: () => number;
|
|
@@ -37,8 +40,10 @@ export declare class NeuralBandInput {
|
|
|
37
40
|
private latestClaim;
|
|
38
41
|
private claims;
|
|
39
42
|
private handwriting;
|
|
43
|
+
private firmware;
|
|
40
44
|
private claimListeners;
|
|
41
45
|
private handwritingListeners;
|
|
46
|
+
private firmwareListeners;
|
|
42
47
|
private readonly forward;
|
|
43
48
|
private readonly now;
|
|
44
49
|
constructor(options?: NeuralBandInputOptions);
|
|
@@ -47,10 +52,16 @@ export declare class NeuralBandInput {
|
|
|
47
52
|
onClaimStatus(cb: (status: NeuralBandClaimStatus) => void): () => void;
|
|
48
53
|
handwritingStatus(controllerId: string): NeuralBandHandwritingStatus;
|
|
49
54
|
onHandwritingStatus(cb: (update: NeuralBandHandwritingUpdate) => void): () => void;
|
|
55
|
+
firmwareStatus(controllerId: string): NeuralBandFirmwareStatus;
|
|
56
|
+
onFirmwareStatus(cb: (update: {
|
|
57
|
+
id: string;
|
|
58
|
+
status: NeuralBandFirmwareStatus;
|
|
59
|
+
}) => void): () => void;
|
|
50
60
|
/** A new pairing attempt starts from a clean slate. */
|
|
51
61
|
resetClaim(): void;
|
|
52
62
|
/** Drop an unpaired band's state. */
|
|
53
63
|
forget(controllerId: string): void;
|
|
64
|
+
handleFirmware(event: NeuralBandFirmwareEvent): void;
|
|
54
65
|
handleClaim(event: NeuralBandClaimEvent): void;
|
|
55
66
|
handleHandwriting(event: NeuralBandHandwritingEvent): void;
|
|
56
67
|
handlePointer(event: NeuralBandPointerEvent): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NeuralBandInput.d.ts","sourceRoot":"","sources":["../../../src/services/neuralBand/NeuralBandInput.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"NeuralBandInput.d.ts","sourceRoot":"","sources":["../../../src/services/neuralBand/NeuralBandInput.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,12 +32,24 @@ function codeFor(char) {
|
|
|
32
32
|
}
|
|
33
33
|
const IDLE_CLAIM = { stage: "idle", sessionExpired: false };
|
|
34
34
|
const IDLE_HANDWRITING = { phase: "idle", message: "", text: "" };
|
|
35
|
+
const IDLE_FIRMWARE = {
|
|
36
|
+
known: false,
|
|
37
|
+
connected: false,
|
|
38
|
+
busy: false,
|
|
39
|
+
cancellable: true,
|
|
40
|
+
hasMetaSession: false,
|
|
41
|
+
hasSerial: false,
|
|
42
|
+
log: [],
|
|
43
|
+
items: [],
|
|
44
|
+
};
|
|
35
45
|
export class NeuralBandInput {
|
|
36
46
|
latestClaim = IDLE_CLAIM;
|
|
37
47
|
claims = new Map();
|
|
38
48
|
handwriting = new Map();
|
|
49
|
+
firmware = new Map();
|
|
39
50
|
claimListeners = new Set();
|
|
40
51
|
handwritingListeners = new Set();
|
|
52
|
+
firmwareListeners = new Set();
|
|
41
53
|
forward;
|
|
42
54
|
now;
|
|
43
55
|
constructor(options = {}) {
|
|
@@ -61,6 +73,13 @@ export class NeuralBandInput {
|
|
|
61
73
|
this.handwritingListeners.add(cb);
|
|
62
74
|
return () => this.handwritingListeners.delete(cb);
|
|
63
75
|
}
|
|
76
|
+
firmwareStatus(controllerId) {
|
|
77
|
+
return this.firmware.get(controllerId) ?? IDLE_FIRMWARE;
|
|
78
|
+
}
|
|
79
|
+
onFirmwareStatus(cb) {
|
|
80
|
+
this.firmwareListeners.add(cb);
|
|
81
|
+
return () => this.firmwareListeners.delete(cb);
|
|
82
|
+
}
|
|
64
83
|
/** A new pairing attempt starts from a clean slate. */
|
|
65
84
|
resetClaim() {
|
|
66
85
|
this.latestClaim = IDLE_CLAIM;
|
|
@@ -71,6 +90,14 @@ export class NeuralBandInput {
|
|
|
71
90
|
forget(controllerId) {
|
|
72
91
|
this.claims.delete(controllerId);
|
|
73
92
|
this.handwriting.delete(controllerId);
|
|
93
|
+
this.firmware.delete(controllerId);
|
|
94
|
+
}
|
|
95
|
+
handleFirmware(event) {
|
|
96
|
+
const { type: _type, controllerId, ...rest } = event;
|
|
97
|
+
const status = { ...rest, known: true };
|
|
98
|
+
this.firmware.set(controllerId, status);
|
|
99
|
+
for (const cb of this.firmwareListeners)
|
|
100
|
+
cb({ id: controllerId, status });
|
|
74
101
|
}
|
|
75
102
|
handleClaim(event) {
|
|
76
103
|
const status = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NeuralBandInput.js","sourceRoot":"","sources":["../../../src/services/neuralBand/NeuralBandInput.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The Meta Neural Band's own event streams, past the gestures that ride `touch_event`:\n * claim progress (for the pairing screens), the handwriting model (typed into the\n * miniapp keyboard stream as synthesized key presses) and the air mouse (forwarded\n * to miniapps on the pointer stream). State is per band (`controllerId`); the\n * latest claim is also kept on its own, since the pairing screen runs before\n * the band's id reaches JS.\n */\nimport type {NeuralBandClaimEvent, NeuralBandHandwritingEvent, NeuralBandPointerEvent} from \"@glassly/bluetooth-sdk\"\nimport {MiniappStreamType} from \"@glassly/miniapp\"\n\nimport type {KeyboardEventPayload} from \"../GlassesKeyboardInput\"\nimport localMiniappRuntime from \"../LocalMiniappRuntime\"\n\nexport interface NeuralBandClaimStatus {\n stage: \"idle\" | \"progress\" | \"completed\" | \"failed\"\n message?: string\n sessionExpired: boolean\n bandName?: string\n /** The band being claimed; absent until a claim event arrives. */\n controllerId?: string\n}\n\nexport interface NeuralBandHandwritingStatus {\n phase: \"idle\" | \"preparing\" | \"ready\" | \"restoring\" | \"finished\"\n message: string\n problem?: string\n /** The last text the band produced since handwriting was switched on. */\n text: string\n}\n\nexport interface NeuralBandHandwritingUpdate {\n id: string\n status: NeuralBandHandwritingStatus\n}\n\nexport interface NeuralBandInputOptions {\n forward?: (stream: string, payload: unknown) => void\n now?: () => number\n}\n\nconst MODIFIERS = {shift: false, ctrl: false, alt: false, meta: false}\n\n/** One handwriting change as the key presses that would have typed it. */\nexport function keyEventsForTextChange(previous: string, next: string, timestamp: number): KeyboardEventPayload[] {\n let common = 0\n while (common < previous.length && common < next.length && previous[common] === next[common]) common++\n const events: KeyboardEventPayload[] = []\n const press = (key: string, code: string, text?: string) => {\n events.push({phase: \"down\", key, code, modifiers: MODIFIERS, text, repeat: false, timestamp})\n events.push({phase: \"up\", key, code, modifiers: MODIFIERS, repeat: false, timestamp})\n }\n for (let i = common; i < previous.length; i++) press(\"Backspace\", \"Backspace\")\n for (const char of Array.from(next.slice(common))) {\n if (char === \"\\n\") press(\"Enter\", \"Enter\")\n else if (char === \" \") press(\" \", \"Space\", \" \")\n else press(char, codeFor(char), char)\n }\n return events\n}\n\nfunction codeFor(char: string): string {\n if (/^[a-z]$/i.test(char)) return `Key${char.toUpperCase()}`\n if (/^[0-9]$/.test(char)) return `Digit${char}`\n return \"Unidentified\"\n}\n\nconst IDLE_CLAIM: NeuralBandClaimStatus = {stage: \"idle\", sessionExpired: false}\nconst IDLE_HANDWRITING: NeuralBandHandwritingStatus = {phase: \"idle\", message: \"\", text: \"\"}\n\nexport class NeuralBandInput {\n private latestClaim: NeuralBandClaimStatus = IDLE_CLAIM\n private claims = new Map<string, NeuralBandClaimStatus>()\n private handwriting = new Map<string, NeuralBandHandwritingStatus>()\n private claimListeners = new Set<(status: NeuralBandClaimStatus) => void>()\n private handwritingListeners = new Set<(update: NeuralBandHandwritingUpdate) => void>()\n private readonly forward: (stream: string, payload: unknown) => void\n private readonly now: () => number\n\n constructor(options: NeuralBandInputOptions = {}) {\n this.forward = options.forward ?? ((stream, payload) => localMiniappRuntime.forwardEvent(stream, payload))\n this.now = options.now ?? (() => Date.now())\n }\n\n /** One band's claim, or the latest claim of any band without an id. */\n claimStatus(controllerId?: string): NeuralBandClaimStatus {\n if (controllerId === undefined) return this.latestClaim\n return this.claims.get(controllerId) ?? IDLE_CLAIM\n }\n\n onClaimStatus(cb: (status: NeuralBandClaimStatus) => void): () => void {\n this.claimListeners.add(cb)\n return () => this.claimListeners.delete(cb)\n }\n\n handwritingStatus(controllerId: string): NeuralBandHandwritingStatus {\n return this.handwriting.get(controllerId) ?? IDLE_HANDWRITING\n }\n\n onHandwritingStatus(cb: (update: NeuralBandHandwritingUpdate) => void): () => void {\n this.handwritingListeners.add(cb)\n return () => this.handwritingListeners.delete(cb)\n }\n\n /** A new pairing attempt starts from a clean slate. */\n resetClaim(): void {\n this.latestClaim = IDLE_CLAIM\n for (const cb of this.claimListeners) cb(IDLE_CLAIM)\n }\n\n /** Drop an unpaired band's state. */\n forget(controllerId: string): void {\n this.claims.delete(controllerId)\n this.handwriting.delete(controllerId)\n }\n\n handleClaim(event: NeuralBandClaimEvent): void {\n const status: NeuralBandClaimStatus = {\n stage: event.stage,\n message: event.message,\n sessionExpired: event.sessionExpired === true,\n bandName: event.bandName,\n controllerId: event.controllerId,\n }\n if (event.controllerId) this.claims.set(event.controllerId, status)\n this.latestClaim = status\n for (const cb of this.claimListeners) cb(status)\n }\n\n handleHandwriting(event: NeuralBandHandwritingEvent): void {\n const id = event.controllerId\n const current = this.handwritingStatus(id)\n if (event.kind === \"state\") {\n const text = event.phase === \"preparing\" ? \"\" : current.text\n this.setHandwriting(id, {phase: event.phase, message: event.message, problem: event.problem, text})\n return\n }\n if (event.text !== current.text) {\n for (const key of keyEventsForTextChange(current.text, event.text, this.now())) {\n this.forward(MiniappStreamType.KEYBOARD_EVENT, key)\n }\n }\n this.setHandwriting(id, {...current, text: event.text})\n }\n\n handlePointer(event: NeuralBandPointerEvent): void {\n if (event.kind === \"move\") {\n this.forward(MiniappStreamType.POINTER_EVENT, {\n kind: \"move\",\n dx: event.dx,\n dy: event.dy,\n timestamp: event.timestamp,\n controllerId: event.controllerId,\n })\n } else {\n this.forward(MiniappStreamType.POINTER_EVENT, {\n kind: \"buttons\",\n buttons: event.buttons,\n timestamp: event.timestamp,\n controllerId: event.controllerId,\n })\n }\n }\n\n private setHandwriting(id: string, status: NeuralBandHandwritingStatus): void {\n this.handwriting.set(id, status)\n for (const cb of this.handwritingListeners) cb({id, status})\n }\n}\n\nconst neuralBandInput = new NeuralBandInput()\nexport default neuralBandInput\n"]}
|
|
1
|
+
{"version":3,"file":"NeuralBandInput.js","sourceRoot":"","sources":["../../../src/services/neuralBand/NeuralBandInput.ts"],"names":[],"mappings":"AAcA,OAAO,EAAC,iBAAiB,EAAC,MAAM,kBAAkB,CAAA;AAGlD,OAAO,mBAAmB,MAAM,wBAAwB,CAAA;AA+BxD,MAAM,SAAS,GAAG,EAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAC,CAAA;AAEtE,0EAA0E;AAC1E,MAAM,UAAU,sBAAsB,CAAC,QAAgB,EAAE,IAAY,EAAE,SAAiB;IACtF,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,OAAO,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC;QAAE,MAAM,EAAE,CAAA;IACtG,MAAM,MAAM,GAA2B,EAAE,CAAA;IACzC,MAAM,KAAK,GAAG,CAAC,GAAW,EAAE,IAAY,EAAE,IAAa,EAAE,EAAE;QACzD,MAAM,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAC,CAAC,CAAA;QAC7F,MAAM,CAAC,IAAI,CAAC,EAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAC,CAAC,CAAA;IACvF,CAAC,CAAA;IACD,KAAK,IAAI,CAAC,GAAG,MAAM,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;IAC9E,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAClD,IAAI,IAAI,KAAK,IAAI;YAAE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;aACrC,IAAI,IAAI,KAAK,GAAG;YAAE,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;;YAC1C,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAA;IACvC,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,OAAO,CAAC,IAAY;IAC3B,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,MAAM,IAAI,CAAC,WAAW,EAAE,EAAE,CAAA;IAC5D,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,QAAQ,IAAI,EAAE,CAAA;IAC/C,OAAO,cAAc,CAAA;AACvB,CAAC;AAED,MAAM,UAAU,GAA0B,EAAC,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAC,CAAA;AAChF,MAAM,gBAAgB,GAAgC,EAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAC,CAAA;AAC5F,MAAM,aAAa,GAA6B;IAC9C,KAAK,EAAE,KAAK;IACZ,SAAS,EAAE,KAAK;IAChB,IAAI,EAAE,KAAK;IACX,WAAW,EAAE,IAAI;IACjB,cAAc,EAAE,KAAK;IACrB,SAAS,EAAE,KAAK;IAChB,GAAG,EAAE,EAAE;IACP,KAAK,EAAE,EAAE;CACV,CAAA;AAED,MAAM,OAAO,eAAe;IAClB,WAAW,GAA0B,UAAU,CAAA;IAC/C,MAAM,GAAG,IAAI,GAAG,EAAiC,CAAA;IACjD,WAAW,GAAG,IAAI,GAAG,EAAuC,CAAA;IAC5D,QAAQ,GAAG,IAAI,GAAG,EAAoC,CAAA;IACtD,cAAc,GAAG,IAAI,GAAG,EAA2C,CAAA;IACnE,oBAAoB,GAAG,IAAI,GAAG,EAAiD,CAAA;IAC/E,iBAAiB,GAAG,IAAI,GAAG,EAAoE,CAAA;IACtF,OAAO,CAA4C;IACnD,GAAG,CAAc;IAElC,YAAY,UAAkC,EAAE;QAC9C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,mBAAmB,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;QAC1G,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;IAC9C,CAAC;IAED,uEAAuE;IACvE,WAAW,CAAC,YAAqB;QAC/B,IAAI,YAAY,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,WAAW,CAAA;QACvD,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,UAAU,CAAA;IACpD,CAAC;IAED,aAAa,CAAC,EAA2C;QACvD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC3B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAC7C,CAAC;IAED,iBAAiB,CAAC,YAAoB;QACpC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,gBAAgB,CAAA;IAC/D,CAAC;IAED,mBAAmB,CAAC,EAAiD;QACnE,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACjC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACnD,CAAC;IAED,cAAc,CAAC,YAAoB;QACjC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,aAAa,CAAA;IACzD,CAAC;IAED,gBAAgB,CAAC,EAAoE;QACnF,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC9B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAChD,CAAC;IAED,uDAAuD;IACvD,UAAU;QACR,IAAI,CAAC,WAAW,GAAG,UAAU,CAAA;QAC7B,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,cAAc;YAAE,EAAE,CAAC,UAAU,CAAC,CAAA;IACtD,CAAC;IAED,qCAAqC;IACrC,MAAM,CAAC,YAAoB;QACzB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;QAChC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;QACrC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;IACpC,CAAC;IAED,cAAc,CAAC,KAA8B;QAC3C,MAAM,EAAC,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI,EAAC,GAAG,KAAK,CAAA;QAClD,MAAM,MAAM,GAA6B,EAAC,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,EAAC,CAAA;QAC/D,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;QACvC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,iBAAiB;YAAE,EAAE,CAAC,EAAC,EAAE,EAAE,YAAY,EAAE,MAAM,EAAC,CAAC,CAAA;IACzE,CAAC;IAED,WAAW,CAAC,KAA2B;QACrC,MAAM,MAAM,GAA0B;YACpC,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,cAAc,EAAE,KAAK,CAAC,cAAc,KAAK,IAAI;YAC7C,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,YAAY,EAAE,KAAK,CAAC,YAAY;SACjC,CAAA;QACD,IAAI,KAAK,CAAC,YAAY;YAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;QACnE,IAAI,CAAC,WAAW,GAAG,MAAM,CAAA;QACzB,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,cAAc;YAAE,EAAE,CAAC,MAAM,CAAC,CAAA;IAClD,CAAC;IAED,iBAAiB,CAAC,KAAiC;QACjD,MAAM,EAAE,GAAG,KAAK,CAAC,YAAY,CAAA;QAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAA;QAC1C,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAA;YAC5D,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,EAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAC,CAAC,CAAA;YACnG,OAAM;QACR,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC;YAChC,KAAK,MAAM,GAAG,IAAI,sBAAsB,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;gBAC/E,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,cAAc,EAAE,GAAG,CAAC,CAAA;YACrD,CAAC;QACH,CAAC;QACD,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,EAAC,GAAG,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAC,CAAC,CAAA;IACzD,CAAC;IAED,aAAa,CAAC,KAA6B;QACzC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,aAAa,EAAE;gBAC5C,IAAI,EAAE,MAAM;gBACZ,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;aACjC,CAAC,CAAA;QACJ,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,aAAa,EAAE;gBAC5C,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;aACjC,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAEO,cAAc,CAAC,EAAU,EAAE,MAAmC;QACpE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;QAChC,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,oBAAoB;YAAE,EAAE,CAAC,EAAC,EAAE,EAAE,MAAM,EAAC,CAAC,CAAA;IAC9D,CAAC;CACF;AAED,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAA;AAC7C,eAAe,eAAe,CAAA","sourcesContent":["/**\n * The Meta Neural Band's own event streams, past the gestures that ride `touch_event`:\n * claim progress (for the pairing screens), the handwriting model (typed into the\n * miniapp keyboard stream as synthesized key presses) and the air mouse (forwarded\n * to miniapps on the pointer stream). State is per band (`controllerId`); the\n * latest claim is also kept on its own, since the pairing screen runs before\n * the band's id reaches JS.\n */\nimport type {\n NeuralBandClaimEvent,\n NeuralBandFirmwareEvent,\n NeuralBandHandwritingEvent,\n NeuralBandPointerEvent,\n} from \"@glassly/bluetooth-sdk\"\nimport {MiniappStreamType} from \"@glassly/miniapp\"\n\nimport type {KeyboardEventPayload} from \"../GlassesKeyboardInput\"\nimport localMiniappRuntime from \"../LocalMiniappRuntime\"\n\nexport interface NeuralBandClaimStatus {\n stage: \"idle\" | \"progress\" | \"completed\" | \"failed\"\n message?: string\n sessionExpired: boolean\n bandName?: string\n /** The band being claimed; absent until a claim event arrives. */\n controllerId?: string\n}\n\nexport interface NeuralBandHandwritingStatus {\n phase: \"idle\" | \"preparing\" | \"ready\" | \"restoring\" | \"finished\"\n message: string\n problem?: string\n /** The last text the band produced since handwriting was switched on. */\n text: string\n}\n\nexport interface NeuralBandHandwritingUpdate {\n id: string\n status: NeuralBandHandwritingStatus\n}\n\nexport type NeuralBandFirmwareStatus = Omit<NeuralBandFirmwareEvent, \"type\" | \"controllerId\"> & {known: boolean}\n\nexport interface NeuralBandInputOptions {\n forward?: (stream: string, payload: unknown) => void\n now?: () => number\n}\n\nconst MODIFIERS = {shift: false, ctrl: false, alt: false, meta: false}\n\n/** One handwriting change as the key presses that would have typed it. */\nexport function keyEventsForTextChange(previous: string, next: string, timestamp: number): KeyboardEventPayload[] {\n let common = 0\n while (common < previous.length && common < next.length && previous[common] === next[common]) common++\n const events: KeyboardEventPayload[] = []\n const press = (key: string, code: string, text?: string) => {\n events.push({phase: \"down\", key, code, modifiers: MODIFIERS, text, repeat: false, timestamp})\n events.push({phase: \"up\", key, code, modifiers: MODIFIERS, repeat: false, timestamp})\n }\n for (let i = common; i < previous.length; i++) press(\"Backspace\", \"Backspace\")\n for (const char of Array.from(next.slice(common))) {\n if (char === \"\\n\") press(\"Enter\", \"Enter\")\n else if (char === \" \") press(\" \", \"Space\", \" \")\n else press(char, codeFor(char), char)\n }\n return events\n}\n\nfunction codeFor(char: string): string {\n if (/^[a-z]$/i.test(char)) return `Key${char.toUpperCase()}`\n if (/^[0-9]$/.test(char)) return `Digit${char}`\n return \"Unidentified\"\n}\n\nconst IDLE_CLAIM: NeuralBandClaimStatus = {stage: \"idle\", sessionExpired: false}\nconst IDLE_HANDWRITING: NeuralBandHandwritingStatus = {phase: \"idle\", message: \"\", text: \"\"}\nconst IDLE_FIRMWARE: NeuralBandFirmwareStatus = {\n known: false,\n connected: false,\n busy: false,\n cancellable: true,\n hasMetaSession: false,\n hasSerial: false,\n log: [],\n items: [],\n}\n\nexport class NeuralBandInput {\n private latestClaim: NeuralBandClaimStatus = IDLE_CLAIM\n private claims = new Map<string, NeuralBandClaimStatus>()\n private handwriting = new Map<string, NeuralBandHandwritingStatus>()\n private firmware = new Map<string, NeuralBandFirmwareStatus>()\n private claimListeners = new Set<(status: NeuralBandClaimStatus) => void>()\n private handwritingListeners = new Set<(update: NeuralBandHandwritingUpdate) => void>()\n private firmwareListeners = new Set<(update: {id: string; status: NeuralBandFirmwareStatus}) => void>()\n private readonly forward: (stream: string, payload: unknown) => void\n private readonly now: () => number\n\n constructor(options: NeuralBandInputOptions = {}) {\n this.forward = options.forward ?? ((stream, payload) => localMiniappRuntime.forwardEvent(stream, payload))\n this.now = options.now ?? (() => Date.now())\n }\n\n /** One band's claim, or the latest claim of any band without an id. */\n claimStatus(controllerId?: string): NeuralBandClaimStatus {\n if (controllerId === undefined) return this.latestClaim\n return this.claims.get(controllerId) ?? IDLE_CLAIM\n }\n\n onClaimStatus(cb: (status: NeuralBandClaimStatus) => void): () => void {\n this.claimListeners.add(cb)\n return () => this.claimListeners.delete(cb)\n }\n\n handwritingStatus(controllerId: string): NeuralBandHandwritingStatus {\n return this.handwriting.get(controllerId) ?? IDLE_HANDWRITING\n }\n\n onHandwritingStatus(cb: (update: NeuralBandHandwritingUpdate) => void): () => void {\n this.handwritingListeners.add(cb)\n return () => this.handwritingListeners.delete(cb)\n }\n\n firmwareStatus(controllerId: string): NeuralBandFirmwareStatus {\n return this.firmware.get(controllerId) ?? IDLE_FIRMWARE\n }\n\n onFirmwareStatus(cb: (update: {id: string; status: NeuralBandFirmwareStatus}) => void): () => void {\n this.firmwareListeners.add(cb)\n return () => this.firmwareListeners.delete(cb)\n }\n\n /** A new pairing attempt starts from a clean slate. */\n resetClaim(): void {\n this.latestClaim = IDLE_CLAIM\n for (const cb of this.claimListeners) cb(IDLE_CLAIM)\n }\n\n /** Drop an unpaired band's state. */\n forget(controllerId: string): void {\n this.claims.delete(controllerId)\n this.handwriting.delete(controllerId)\n this.firmware.delete(controllerId)\n }\n\n handleFirmware(event: NeuralBandFirmwareEvent): void {\n const {type: _type, controllerId, ...rest} = event\n const status: NeuralBandFirmwareStatus = {...rest, known: true}\n this.firmware.set(controllerId, status)\n for (const cb of this.firmwareListeners) cb({id: controllerId, status})\n }\n\n handleClaim(event: NeuralBandClaimEvent): void {\n const status: NeuralBandClaimStatus = {\n stage: event.stage,\n message: event.message,\n sessionExpired: event.sessionExpired === true,\n bandName: event.bandName,\n controllerId: event.controllerId,\n }\n if (event.controllerId) this.claims.set(event.controllerId, status)\n this.latestClaim = status\n for (const cb of this.claimListeners) cb(status)\n }\n\n handleHandwriting(event: NeuralBandHandwritingEvent): void {\n const id = event.controllerId\n const current = this.handwritingStatus(id)\n if (event.kind === \"state\") {\n const text = event.phase === \"preparing\" ? \"\" : current.text\n this.setHandwriting(id, {phase: event.phase, message: event.message, problem: event.problem, text})\n return\n }\n if (event.text !== current.text) {\n for (const key of keyEventsForTextChange(current.text, event.text, this.now())) {\n this.forward(MiniappStreamType.KEYBOARD_EVENT, key)\n }\n }\n this.setHandwriting(id, {...current, text: event.text})\n }\n\n handlePointer(event: NeuralBandPointerEvent): void {\n if (event.kind === \"move\") {\n this.forward(MiniappStreamType.POINTER_EVENT, {\n kind: \"move\",\n dx: event.dx,\n dy: event.dy,\n timestamp: event.timestamp,\n controllerId: event.controllerId,\n })\n } else {\n this.forward(MiniappStreamType.POINTER_EVENT, {\n kind: \"buttons\",\n buttons: event.buttons,\n timestamp: event.timestamp,\n controllerId: event.controllerId,\n })\n }\n }\n\n private setHandwriting(id: string, status: NeuralBandHandwritingStatus): void {\n this.handwriting.set(id, status)\n for (const cb of this.handwritingListeners) cb({id, status})\n }\n}\n\nconst neuralBandInput = new NeuralBandInput()\nexport default neuralBandInput\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glassly/engine",
|
|
3
|
-
"version": "0.3.8-dev.
|
|
3
|
+
"version": "0.3.8-dev.1006",
|
|
4
4
|
"description": "Glassly Engine — miniapp registry, WebView bridge, and miniapp store",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -97,17 +97,17 @@
|
|
|
97
97
|
"registry": "https://registry.npmjs.org/"
|
|
98
98
|
},
|
|
99
99
|
"dependencies": {
|
|
100
|
-
"@glassly/bluetooth-sdk": "0.3.8-dev.
|
|
101
|
-
"@glassly/cloud-client": "0.3.8-dev.
|
|
102
|
-
"@glassly/cloud-protocol": "0.3.8-dev.
|
|
103
|
-
"@glassly/crust": "0.3.8-dev.
|
|
104
|
-
"@glassly/miniapp": "0.3.8-dev.
|
|
100
|
+
"@glassly/bluetooth-sdk": "0.3.8-dev.1006",
|
|
101
|
+
"@glassly/cloud-client": "0.3.8-dev.1006",
|
|
102
|
+
"@glassly/cloud-protocol": "0.3.8-dev.1006",
|
|
103
|
+
"@glassly/crust": "0.3.8-dev.1006",
|
|
104
|
+
"@glassly/miniapp": "0.3.8-dev.1006",
|
|
105
105
|
"buffer": "^6.0.3",
|
|
106
106
|
"events": "^3.3.0",
|
|
107
107
|
"react-native-marked": "8.3.2",
|
|
108
108
|
"semver": "^7.7.4",
|
|
109
109
|
"typesafe-ts": "^1.7.1",
|
|
110
|
-
"@glassly/llm-providers": "0.3.8-dev.
|
|
110
|
+
"@glassly/llm-providers": "0.3.8-dev.1006",
|
|
111
111
|
"@huggingface/jinja": "^0.5.9",
|
|
112
112
|
"jsonrepair": "^3.12.0"
|
|
113
113
|
},
|
package/src/facades/glasses.ts
CHANGED
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
Device,
|
|
20
20
|
KeyboardAdvertEvent,
|
|
21
21
|
KeyboardPairingEvent,
|
|
22
|
+
NeuralBandFirmwareEvent,
|
|
22
23
|
PairedController,
|
|
23
24
|
TouchEvent,
|
|
24
25
|
} from "@glassly/bluetooth-sdk"
|
|
@@ -39,6 +40,7 @@ import {pushAllBluetoothSettings} from "../services/GlassesSettingsSync"
|
|
|
39
40
|
import {isControllerReady, pairedControllersFrom, readyControllers} from "../services/controllers"
|
|
40
41
|
import neuralBandInput, {
|
|
41
42
|
type NeuralBandClaimStatus,
|
|
43
|
+
type NeuralBandFirmwareStatus,
|
|
42
44
|
type NeuralBandHandwritingStatus,
|
|
43
45
|
type NeuralBandHandwritingUpdate,
|
|
44
46
|
} from "../services/neuralBand/NeuralBandInput"
|
|
@@ -344,6 +346,22 @@ export const glasses = {
|
|
|
344
346
|
/** The band's air mouse; movement reaches miniapps on the pointer stream. */
|
|
345
347
|
setPointer: (id: string, enabled: boolean): Promise<void> => BluetoothSdk.neuralBandSetPointer(id, enabled),
|
|
346
348
|
setHand: (id: string, hand: "left" | "right"): Promise<void> => BluetoothSdk.neuralBandSetHand(id, hand),
|
|
349
|
+
firmwareStatus: (id: string): NeuralBandFirmwareStatus => ({...neuralBandInput.firmwareStatus(id)}),
|
|
350
|
+
onFirmwareStatus: (cb: (update: {id: string; status: NeuralBandFirmwareStatus}) => void): (() => void) =>
|
|
351
|
+
neuralBandInput.onFirmwareStatus(cb),
|
|
352
|
+
refreshFirmware: async (id: string): Promise<NeuralBandFirmwareStatus> => {
|
|
353
|
+
const info = await BluetoothSdk.neuralBandFirmwareInfo(id)
|
|
354
|
+
neuralBandInput.handleFirmware({
|
|
355
|
+
...(info as object),
|
|
356
|
+
type: "neural_band_firmware",
|
|
357
|
+
controllerId: id,
|
|
358
|
+
} as NeuralBandFirmwareEvent)
|
|
359
|
+
return neuralBandInput.firmwareStatus(id)
|
|
360
|
+
},
|
|
361
|
+
requestFirmwareStatus: (id: string): Promise<void> => BluetoothSdk.neuralBandRequestFirmwareStatus(id),
|
|
362
|
+
checkFirmware: (id: string): Promise<void> => BluetoothSdk.neuralBandCheckFirmware(id),
|
|
363
|
+
updateFirmware: (id: string, mode: "update" | "cancel" | "key" | "send" | "trial" | "install"): Promise<void> =>
|
|
364
|
+
BluetoothSdk.neuralBandUpdateFirmware(id, mode),
|
|
347
365
|
},
|
|
348
366
|
|
|
349
367
|
// --- watch: an Apple Watch over WatchConnectivity (iOS), a Wear OS watch over the Data Layer (Android) ---
|
|
@@ -12,9 +12,9 @@ export interface EngineReleaseMetadata {
|
|
|
12
12
|
export const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({
|
|
13
13
|
"schemaVersion": 1,
|
|
14
14
|
"familyBaseVersion": "0.3.8",
|
|
15
|
-
"releaseIdentity": "0.3.8-dev.
|
|
16
|
-
"releaseSetId": "glassly-0.3.8-dev.
|
|
17
|
-
"sourceCommit": "
|
|
15
|
+
"releaseIdentity": "0.3.8-dev.1006",
|
|
16
|
+
"releaseSetId": "glassly-0.3.8-dev.1006",
|
|
17
|
+
"sourceCommit": "659d87701629ff1aa6865e2325c3181a7d19fe6a",
|
|
18
18
|
"otaManifestUrl": null,
|
|
19
19
|
"otaManifestSha256": null
|
|
20
20
|
})
|
package/src/index.ts
CHANGED
|
@@ -245,6 +245,7 @@ export function startDeviceEventRouter(): void {
|
|
|
245
245
|
subs.push(BluetoothSdk.addListener("neural_band_claim", (event) => neuralBandInput.handleClaim(event)))
|
|
246
246
|
subs.push(BluetoothSdk.addListener("neural_band_handwriting", (event) => neuralBandInput.handleHandwriting(event)))
|
|
247
247
|
subs.push(BluetoothSdk.addListener("neural_band_pointer", (event) => neuralBandInput.handlePointer(event)))
|
|
248
|
+
subs.push(BluetoothSdk.addListener("neural_band_firmware", (event) => neuralBandInput.handleFirmware(event)))
|
|
248
249
|
subs.push({
|
|
249
250
|
remove: useGlassesStore.subscribe(
|
|
250
251
|
(s) => s.keyboardConnected === true,
|
|
@@ -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
|
+
busy: false,
|
|
81
|
+
cancellable: true,
|
|
82
|
+
hasMetaSession: false,
|
|
83
|
+
hasSerial: false,
|
|
84
|
+
log: [],
|
|
85
|
+
items: [],
|
|
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 {
|