@elizaos/plugin-facewear 2.0.3-beta.5 → 2.0.3-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/dist/actions/display-text.d.ts +4 -0
  2. package/dist/actions/display-text.d.ts.map +1 -0
  3. package/dist/actions/display-text.js +90 -0
  4. package/dist/actions/display-text.js.map +1 -0
  5. package/dist/actions/facewear-connect.d.ts +3 -0
  6. package/dist/actions/facewear-connect.d.ts.map +1 -0
  7. package/dist/actions/facewear-connect.js +70 -0
  8. package/dist/actions/facewear-connect.js.map +1 -0
  9. package/dist/actions/facewear-control.d.ts +4 -0
  10. package/dist/actions/facewear-control.d.ts.map +1 -0
  11. package/dist/actions/facewear-control.js +627 -0
  12. package/dist/actions/facewear-control.js.map +1 -0
  13. package/dist/actions/facewear-debug.d.ts +3 -0
  14. package/dist/actions/facewear-debug.d.ts.map +1 -0
  15. package/dist/actions/facewear-debug.js +62 -0
  16. package/dist/actions/facewear-debug.js.map +1 -0
  17. package/dist/actions/facewear-status.d.ts +4 -0
  18. package/dist/actions/facewear-status.d.ts.map +1 -0
  19. package/dist/actions/facewear-status.js +66 -0
  20. package/dist/actions/facewear-status.js.map +1 -0
  21. package/dist/actions/microphone.d.ts +4 -0
  22. package/dist/actions/microphone.d.ts.map +1 -0
  23. package/dist/actions/microphone.js +63 -0
  24. package/dist/actions/microphone.js.map +1 -0
  25. package/dist/actions/view-actions.d.ts +23 -0
  26. package/dist/actions/view-actions.d.ts.map +1 -0
  27. package/dist/actions/view-actions.js +314 -0
  28. package/dist/actions/view-actions.js.map +1 -0
  29. package/dist/actions/vision-query.d.ts +4 -0
  30. package/dist/actions/vision-query.d.ts.map +1 -0
  31. package/dist/actions/vision-query.js +41 -0
  32. package/dist/actions/vision-query.js.map +1 -0
  33. package/dist/actions/xr-view-actions.d.ts +14 -0
  34. package/dist/actions/xr-view-actions.d.ts.map +1 -0
  35. package/dist/actions/xr-view-actions.js +29 -0
  36. package/dist/actions/xr-view-actions.js.map +1 -0
  37. package/dist/components/FacewearSpatialView.d.ts +50 -0
  38. package/dist/components/FacewearSpatialView.d.ts.map +1 -0
  39. package/dist/components/FacewearSpatialView.js +129 -0
  40. package/dist/components/FacewearSpatialView.js.map +1 -0
  41. package/dist/components/FacewearView.d.ts +17 -0
  42. package/dist/components/FacewearView.d.ts.map +1 -0
  43. package/dist/components/FacewearView.js +88 -0
  44. package/dist/components/FacewearView.js.map +1 -0
  45. package/dist/components/SmartglassesPanelView.d.ts +22 -0
  46. package/dist/components/SmartglassesPanelView.d.ts.map +1 -0
  47. package/dist/components/SmartglassesPanelView.js +140 -0
  48. package/dist/components/SmartglassesPanelView.js.map +1 -0
  49. package/dist/components/SmartglassesSpatialView.d.ts +46 -0
  50. package/dist/components/SmartglassesSpatialView.d.ts.map +1 -0
  51. package/dist/components/SmartglassesSpatialView.js +240 -0
  52. package/dist/components/SmartglassesSpatialView.js.map +1 -0
  53. package/dist/components/facewear-profiles.d.ts +27 -0
  54. package/dist/components/facewear-profiles.d.ts.map +1 -0
  55. package/dist/components/facewear-profiles.js +40 -0
  56. package/dist/components/facewear-profiles.js.map +1 -0
  57. package/dist/devices/apple-vision-pro.d.ts +7 -0
  58. package/dist/devices/apple-vision-pro.d.ts.map +1 -0
  59. package/dist/devices/apple-vision-pro.js +21 -0
  60. package/dist/devices/apple-vision-pro.js.map +1 -0
  61. package/dist/devices/even-realities.d.ts +7 -0
  62. package/dist/devices/even-realities.d.ts.map +1 -0
  63. package/dist/devices/even-realities.js +13 -0
  64. package/dist/devices/even-realities.js.map +1 -0
  65. package/dist/devices/meta-quest.d.ts +5 -0
  66. package/dist/devices/meta-quest.d.ts.map +1 -0
  67. package/dist/devices/meta-quest.js +21 -0
  68. package/dist/devices/meta-quest.js.map +1 -0
  69. package/dist/devices/registry.d.ts +19 -0
  70. package/dist/devices/registry.d.ts.map +1 -0
  71. package/dist/devices/registry.js +96 -0
  72. package/dist/devices/registry.js.map +1 -0
  73. package/dist/devices/xreal.d.ts +7 -0
  74. package/dist/devices/xreal.d.ts.map +1 -0
  75. package/dist/devices/xreal.js +19 -0
  76. package/dist/devices/xreal.js.map +1 -0
  77. package/dist/index.d.ts +28 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +260 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/protocol/smartglasses.d.ts +306 -0
  82. package/dist/protocol/smartglasses.d.ts.map +1 -0
  83. package/dist/protocol/smartglasses.js +1485 -0
  84. package/dist/protocol/smartglasses.js.map +1 -0
  85. package/dist/protocol/xr.d.ts +137 -0
  86. package/dist/protocol/xr.d.ts.map +1 -0
  87. package/dist/protocol/xr.js +18 -0
  88. package/dist/protocol/xr.js.map +1 -0
  89. package/dist/providers/facewear-context.d.ts +3 -0
  90. package/dist/providers/facewear-context.d.ts.map +1 -0
  91. package/dist/providers/facewear-context.js +59 -0
  92. package/dist/providers/facewear-context.js.map +1 -0
  93. package/dist/providers/smartglasses-status.d.ts +3 -0
  94. package/dist/providers/smartglasses-status.d.ts.map +1 -0
  95. package/dist/providers/smartglasses-status.js +33 -0
  96. package/dist/providers/smartglasses-status.js.map +1 -0
  97. package/dist/register-terminal-view.d.ts +21 -0
  98. package/dist/register-terminal-view.d.ts.map +1 -0
  99. package/dist/register-terminal-view.js +70 -0
  100. package/dist/register-terminal-view.js.map +1 -0
  101. package/dist/register.d.ts +8 -0
  102. package/dist/register.d.ts.map +1 -0
  103. package/dist/register.js +116 -0
  104. package/dist/register.js.map +1 -0
  105. package/dist/routes/connect.d.ts +3 -0
  106. package/dist/routes/connect.d.ts.map +1 -0
  107. package/dist/routes/connect.js +86 -0
  108. package/dist/routes/connect.js.map +1 -0
  109. package/dist/routes/device-config.d.ts +5 -0
  110. package/dist/routes/device-config.d.ts.map +1 -0
  111. package/dist/routes/device-config.js +56 -0
  112. package/dist/routes/device-config.js.map +1 -0
  113. package/dist/routes/simulator-route.d.ts +8 -0
  114. package/dist/routes/simulator-route.d.ts.map +1 -0
  115. package/dist/routes/simulator-route.js +32 -0
  116. package/dist/routes/simulator-route.js.map +1 -0
  117. package/dist/routes/status.d.ts +3 -0
  118. package/dist/routes/status.d.ts.map +1 -0
  119. package/dist/routes/status.js +34 -0
  120. package/dist/routes/status.js.map +1 -0
  121. package/dist/routes/view-host.d.ts +24 -0
  122. package/dist/routes/view-host.d.ts.map +1 -0
  123. package/dist/routes/view-host.js +339 -0
  124. package/dist/routes/view-host.js.map +1 -0
  125. package/dist/routes/views.d.ts +8 -0
  126. package/dist/routes/views.d.ts.map +1 -0
  127. package/dist/routes/views.js +31 -0
  128. package/dist/routes/views.js.map +1 -0
  129. package/dist/services/audio-pipeline.d.ts +20 -0
  130. package/dist/services/audio-pipeline.d.ts.map +1 -0
  131. package/dist/services/audio-pipeline.js +87 -0
  132. package/dist/services/audio-pipeline.js.map +1 -0
  133. package/dist/services/facewear-service.d.ts +26 -0
  134. package/dist/services/facewear-service.d.ts.map +1 -0
  135. package/dist/services/facewear-service.js +45 -0
  136. package/dist/services/facewear-service.js.map +1 -0
  137. package/dist/services/smartglasses-service.d.ts +244 -0
  138. package/dist/services/smartglasses-service.d.ts.map +1 -0
  139. package/dist/services/smartglasses-service.js +821 -0
  140. package/dist/services/smartglasses-service.js.map +1 -0
  141. package/dist/services/vision-pipeline.d.ts +16 -0
  142. package/dist/services/vision-pipeline.d.ts.map +1 -0
  143. package/dist/services/vision-pipeline.js +39 -0
  144. package/dist/services/vision-pipeline.js.map +1 -0
  145. package/dist/services/xr-session-service.d.ts +54 -0
  146. package/dist/services/xr-session-service.d.ts.map +1 -0
  147. package/dist/services/xr-session-service.js +345 -0
  148. package/dist/services/xr-session-service.js.map +1 -0
  149. package/dist/status-format.d.ts +15 -0
  150. package/dist/status-format.d.ts.map +1 -0
  151. package/dist/status-format.js +89 -0
  152. package/dist/status-format.js.map +1 -0
  153. package/dist/transport/even-bridge.d.ts +69 -0
  154. package/dist/transport/even-bridge.d.ts.map +1 -0
  155. package/dist/transport/even-bridge.js +510 -0
  156. package/dist/transport/even-bridge.js.map +1 -0
  157. package/dist/transport/mock.d.ts +42 -0
  158. package/dist/transport/mock.d.ts.map +1 -0
  159. package/dist/transport/mock.js +124 -0
  160. package/dist/transport/mock.js.map +1 -0
  161. package/dist/transport/noble.d.ts +62 -0
  162. package/dist/transport/noble.d.ts.map +1 -0
  163. package/dist/transport/noble.js +256 -0
  164. package/dist/transport/noble.js.map +1 -0
  165. package/dist/transport/types.d.ts +36 -0
  166. package/dist/transport/types.d.ts.map +1 -0
  167. package/dist/transport/types.js +1 -0
  168. package/dist/transport/types.js.map +1 -0
  169. package/dist/transport/web-bluetooth.d.ts +58 -0
  170. package/dist/transport/web-bluetooth.d.ts.map +1 -0
  171. package/dist/transport/web-bluetooth.js +164 -0
  172. package/dist/transport/web-bluetooth.js.map +1 -0
  173. package/dist/ui/FacewearAppView.d.ts +4 -0
  174. package/dist/ui/FacewearAppView.d.ts.map +1 -0
  175. package/dist/ui/FacewearAppView.js +257 -0
  176. package/dist/ui/FacewearAppView.js.map +1 -0
  177. package/dist/ui/SmartglassesView.d.ts +10 -0
  178. package/dist/ui/SmartglassesView.d.ts.map +1 -0
  179. package/dist/ui/SmartglassesView.helpers.d.ts +104 -0
  180. package/dist/ui/SmartglassesView.helpers.d.ts.map +1 -0
  181. package/dist/ui/SmartglassesView.helpers.js +261 -0
  182. package/dist/ui/SmartglassesView.helpers.js.map +1 -0
  183. package/dist/ui/SmartglassesView.js +1189 -0
  184. package/dist/ui/SmartglassesView.js.map +1 -0
  185. package/dist/ui/facewear-view-bundle.d.ts +5 -0
  186. package/dist/ui/facewear-view-bundle.d.ts.map +1 -0
  187. package/dist/ui/facewear-view-bundle.js +17 -0
  188. package/dist/ui/facewear-view-bundle.js.map +1 -0
  189. package/dist/views/bundle.js +2950 -0
  190. package/dist/views/bundle.js.map +1 -0
  191. package/package.json +5 -5
@@ -0,0 +1,510 @@
1
+ import {
2
+ encodeMicCommand,
3
+ G1Command,
4
+ G1InteractionCode,
5
+ G1SubCommand,
6
+ parseG1Notification
7
+ } from "../protocol/smartglasses.js";
8
+ function normalizeBytes(value) {
9
+ if (value instanceof Uint8Array) return value;
10
+ if (value instanceof ArrayBuffer) return new Uint8Array(value);
11
+ if (ArrayBuffer.isView(value)) {
12
+ return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
13
+ }
14
+ if (Array.isArray(value) && value.every((v) => Number.isInteger(v)))
15
+ return Uint8Array.from(value);
16
+ if (typeof value === "string" && /^[0-9a-f]+$/i.test(value) && value.length % 2 === 0) {
17
+ return Uint8Array.from(
18
+ value.match(/../g)?.map((b) => Number.parseInt(b, 16)) ?? []
19
+ );
20
+ }
21
+ return null;
22
+ }
23
+ class EvenBridgeTransport {
24
+ constructor(bridge) {
25
+ this.bridge = bridge;
26
+ }
27
+ bridge;
28
+ name = "even-bridge";
29
+ connected = false;
30
+ eventCallbacks = /* @__PURE__ */ new Set();
31
+ audioCallbacks = /* @__PURE__ */ new Set();
32
+ transcriptCallbacks = /* @__PURE__ */ new Set();
33
+ wifiCallbacks = /* @__PURE__ */ new Set();
34
+ bridgeDisposer = null;
35
+ displayChunks = /* @__PURE__ */ new Map();
36
+ evenHubStartupCreated = false;
37
+ async connect() {
38
+ this.connected = true;
39
+ const register = this.bridge.onEvenHubEvent ?? this.bridge.onEvent;
40
+ if (register) {
41
+ const subscription = register.call(
42
+ this.bridge,
43
+ (event) => this.handleBridgeEvent(event)
44
+ );
45
+ this.bridgeDisposer = normalizeBridgeSubscription(subscription);
46
+ }
47
+ }
48
+ async disconnect() {
49
+ await this.openMicrophone(false);
50
+ this.bridgeDisposer?.();
51
+ this.bridgeDisposer = null;
52
+ this.connected = false;
53
+ }
54
+ isConnected() {
55
+ return this.connected;
56
+ }
57
+ getConnectedLenses() {
58
+ if (!this.connected) return {};
59
+ return {
60
+ left: {
61
+ connected: true,
62
+ name: "Native bridge left lens"
63
+ },
64
+ right: {
65
+ connected: true,
66
+ name: "Native bridge right lens"
67
+ }
68
+ };
69
+ }
70
+ async write(side, data) {
71
+ if (this.supportsEvenHubDisplay() && data[0] === G1Command.SendResult) {
72
+ if (side === "left") await this.writeEvenHubDisplay(data);
73
+ return;
74
+ }
75
+ if (this.supportsMentraDisplay() && data[0] === G1Command.SendResult) {
76
+ if (side === "left") await this.writeMentraDisplay(data);
77
+ return;
78
+ }
79
+ if (this.bridge.clearDisplay && data[0] === G1Command.StartAi && data[1] === G1SubCommand.Stop) {
80
+ await this.bridge.clearDisplay();
81
+ return;
82
+ }
83
+ if (this.bridge.write) {
84
+ await this.bridge.write(side, data);
85
+ return;
86
+ }
87
+ if (this.bridge.send) {
88
+ await this.bridge.send(side, data);
89
+ return;
90
+ }
91
+ await this.bridge.rawBridge?.callEvenApp?.("sendData", {
92
+ side,
93
+ data: Array.from(data)
94
+ });
95
+ }
96
+ async writeBoth(data) {
97
+ await this.write("left", data);
98
+ await this.write("right", data);
99
+ }
100
+ async openMicrophone(enabled) {
101
+ if (this.bridge.setMicState) {
102
+ await this.bridge.setMicState(enabled, enabled, enabled);
103
+ return;
104
+ }
105
+ if (this.bridge.audioControl) {
106
+ await this.bridge.audioControl(enabled);
107
+ return;
108
+ }
109
+ if (this.bridge.rawBridge?.audioControl) {
110
+ await this.bridge.rawBridge.audioControl(enabled);
111
+ return;
112
+ }
113
+ if (this.bridge.rawBridge?.callEvenApp) {
114
+ await this.bridge.rawBridge.callEvenApp("audioControl", {
115
+ isOpen: enabled
116
+ });
117
+ return;
118
+ }
119
+ await this.write("right", encodeMicCommand(enabled));
120
+ }
121
+ async scanWifi() {
122
+ this.assertWifiSupported();
123
+ const raw = this.bridge.requestWifiScan ? await this.bridge.requestWifiScan() : await this.bridge.rawBridge?.callEvenApp?.("request_wifi_scan");
124
+ return normalizeWifiResult(raw, "Wi-Fi scan requested");
125
+ }
126
+ async getWifiStatus() {
127
+ this.assertWifiSupported();
128
+ const raw = this.bridge.requestWifiStatus ? await this.bridge.requestWifiStatus() : await this.bridge.rawBridge?.callEvenApp?.("request_wifi_status");
129
+ return normalizeWifiResult(raw, "Wi-Fi status requested");
130
+ }
131
+ async configureWifi(ssid, password) {
132
+ this.assertWifiSupported();
133
+ const raw = this.bridge.setWifiCredentials ? await this.bridge.setWifiCredentials(ssid, password) : this.bridge.sendWifiCredentials ? await this.bridge.sendWifiCredentials(ssid, password) : await this.bridge.rawBridge?.callEvenApp?.("set_wifi_credentials", {
134
+ ssid,
135
+ password
136
+ });
137
+ return normalizeWifiResult(raw, `Wi-Fi credentials sent for ${ssid}`);
138
+ }
139
+ async requestWifiSetup(reason) {
140
+ this.assertWifiSupported();
141
+ const raw = this.bridge.requestWifiSetup ? await this.bridge.requestWifiSetup(reason) : await this.bridge.rawBridge?.callEvenApp?.("request_wifi_setup", {
142
+ reason
143
+ });
144
+ return normalizeWifiResult(raw, "Wi-Fi setup requested");
145
+ }
146
+ supportsWifi() {
147
+ return Boolean(
148
+ this.bridge.requestWifiScan || this.bridge.requestWifiStatus || this.bridge.requestWifiSetup || this.bridge.setWifiCredentials || this.bridge.sendWifiCredentials || this.bridge.rawBridge?.callEvenApp
149
+ );
150
+ }
151
+ assertWifiSupported() {
152
+ if (!this.supportsWifi()) {
153
+ throw new Error(
154
+ "Wi-Fi is only available when the native smartglasses bridge exposes Wi-Fi APIs"
155
+ );
156
+ }
157
+ }
158
+ supportsEvenHubDisplay() {
159
+ return Boolean(
160
+ this.bridge.sendStartUpPage || this.bridge.createStartUpPageContainer
161
+ );
162
+ }
163
+ supportsMentraDisplay() {
164
+ return Boolean(this.bridge.displayText);
165
+ }
166
+ onEvent(callback) {
167
+ this.eventCallbacks.add(callback);
168
+ return () => this.eventCallbacks.delete(callback);
169
+ }
170
+ onAudio(callback) {
171
+ this.audioCallbacks.add(callback);
172
+ return () => this.audioCallbacks.delete(callback);
173
+ }
174
+ onTranscript(callback) {
175
+ this.transcriptCallbacks.add(callback);
176
+ return () => this.transcriptCallbacks.delete(callback);
177
+ }
178
+ onWifiStatus(callback) {
179
+ this.wifiCallbacks.add(callback);
180
+ return () => this.wifiCallbacks.delete(callback);
181
+ }
182
+ handleBridgeEvent(event) {
183
+ const maybe = event;
184
+ const wifi = normalizeBridgeWifiEvent(maybe);
185
+ if (wifi) {
186
+ for (const callback of this.wifiCallbacks) callback(wifi);
187
+ return;
188
+ }
189
+ const transcript = normalizeBridgeTranscriptEvent(maybe);
190
+ if (transcript) {
191
+ for (const callback of this.transcriptCallbacks)
192
+ callback(transcript.text, transcript.isFinal, transcript.metadata);
193
+ return;
194
+ }
195
+ const audio = maybe.audioEvent;
196
+ const audioPcm = normalizeBytes(audio?.audioPcm);
197
+ if (audioPcm) {
198
+ for (const callback of this.audioCallbacks)
199
+ callback(audioPcm, 16e3, "right", "pcm16");
200
+ return;
201
+ }
202
+ const mentraPcm = normalizeBytes(maybe.pcm);
203
+ if (maybe.type === "mic_pcm" && mentraPcm) {
204
+ for (const callback of this.audioCallbacks)
205
+ callback(mentraPcm, 16e3, "right", "pcm16");
206
+ return;
207
+ }
208
+ const mentraLc3 = normalizeBytes(maybe.lc3);
209
+ if (maybe.type === "mic_lc3" && mentraLc3) {
210
+ for (const callback of this.audioCallbacks)
211
+ callback(mentraLc3, 16e3, "right", "lc3");
212
+ return;
213
+ }
214
+ const inputEvent = normalizeEvenHubInputEvent(maybe);
215
+ if (inputEvent) {
216
+ for (const callback of this.eventCallbacks) callback(inputEvent);
217
+ return;
218
+ }
219
+ const side = maybe.side === "left" || maybe.side === "right" ? maybe.side : "right";
220
+ const bytes = normalizeBytes(maybe.raw ?? maybe.data ?? maybe.bytes);
221
+ if (!bytes) return;
222
+ const parsed = parseG1Notification(side, bytes);
223
+ for (const callback of this.eventCallbacks) callback(parsed);
224
+ const audioData = parsed.audioPcm ?? parsed.audioData;
225
+ if (audioData) {
226
+ for (const callback of this.audioCallbacks)
227
+ callback(
228
+ audioData,
229
+ 16e3,
230
+ parsed.side,
231
+ parsed.audioEncoding,
232
+ parsed.sequence
233
+ );
234
+ }
235
+ }
236
+ async writeEvenHubDisplay(data) {
237
+ const display = this.decodeDisplayPacket(data);
238
+ if (!display) return;
239
+ const key = `${display.seq}:${display.status}:${display.pageNumber}:${display.maxPages}`;
240
+ const chunks = this.displayChunks.get(key) ?? Array.from({ length: display.totalPackages });
241
+ chunks[display.currentPackage] = display.chunk;
242
+ this.displayChunks.set(key, chunks);
243
+ if (chunks.some((chunk) => !chunk)) return;
244
+ this.displayChunks.delete(key);
245
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
246
+ const textBytes = new Uint8Array(totalLength);
247
+ let offset = 0;
248
+ for (const chunk of chunks) {
249
+ textBytes.set(chunk, offset);
250
+ offset += chunk.length;
251
+ }
252
+ await this.sendEvenHubTextPage(textBytes);
253
+ }
254
+ async writeMentraDisplay(data) {
255
+ const display = this.decodeDisplayPacket(data);
256
+ if (!display) return;
257
+ const key = `${display.seq}:${display.status}:${display.pageNumber}:${display.maxPages}`;
258
+ const chunks = this.displayChunks.get(key) ?? Array.from({ length: display.totalPackages });
259
+ chunks[display.currentPackage] = display.chunk;
260
+ this.displayChunks.set(key, chunks);
261
+ if (chunks.some((chunk) => !chunk)) return;
262
+ this.displayChunks.delete(key);
263
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
264
+ const textBytes = new Uint8Array(totalLength);
265
+ let offset = 0;
266
+ for (const chunk of chunks) {
267
+ textBytes.set(chunk, offset);
268
+ offset += chunk.length;
269
+ }
270
+ await this.bridge.displayText?.({
271
+ text: new TextDecoder().decode(textBytes),
272
+ x: 0,
273
+ y: 0,
274
+ size: 24
275
+ });
276
+ }
277
+ async sendEvenHubTextPage(textBytes) {
278
+ const page = createEvenHubTextPage(textBytes);
279
+ if (this.bridge.sendStartUpPage) {
280
+ await this.bridge.sendStartUpPage(page);
281
+ return;
282
+ }
283
+ if (!this.bridge.createStartUpPageContainer) return;
284
+ if (!this.evenHubStartupCreated) {
285
+ assertEvenHubResult(
286
+ await this.bridge.createStartUpPageContainer(page),
287
+ "createStartUpPageContainer"
288
+ );
289
+ this.evenHubStartupCreated = true;
290
+ return;
291
+ }
292
+ const rebuild = this.bridge.rebuildPageContainer ?? this.bridge.createStartUpPageContainer;
293
+ assertEvenHubResult(
294
+ await rebuild.call(this.bridge, page),
295
+ "rebuildPageContainer"
296
+ );
297
+ }
298
+ decodeDisplayPacket(data) {
299
+ if (data.length < 9 || data[0] !== G1Command.SendResult) return null;
300
+ const totalPackages = data[2] || 1;
301
+ const currentPackage = data[3] || 0;
302
+ if (currentPackage >= totalPackages) return null;
303
+ return {
304
+ seq: data[1] ?? 0,
305
+ totalPackages,
306
+ currentPackage,
307
+ status: data[4] ?? 0,
308
+ pageNumber: data[7] ?? 1,
309
+ maxPages: data[8] ?? 1,
310
+ chunk: data.slice(9)
311
+ };
312
+ }
313
+ }
314
+ function normalizeEvenHubInputEvent(event) {
315
+ const rawEventType = getEvenHubRawEventType(event);
316
+ const label = normalizeEvenHubEventLabel(rawEventType, event);
317
+ if (!label) return null;
318
+ const code = label === "single_tap" ? G1InteractionCode.SingleTap : label === "double_tap" ? G1InteractionCode.DoubleTap : label === "long_press" ? G1InteractionCode.LongPress : G1SubCommand.PageControl;
319
+ return {
320
+ side: "right",
321
+ raw: Uint8Array.from([G1Command.StartAi, code]),
322
+ type: "state",
323
+ code,
324
+ label
325
+ };
326
+ }
327
+ function normalizeBridgeTranscriptEvent(event) {
328
+ const type = String(event.type ?? event.streamType ?? "");
329
+ if (type !== "local_transcription" && !type.startsWith("transcription") && !("transcript" in event))
330
+ return null;
331
+ const text = typeof event.text === "string" ? event.text : typeof event.transcript === "string" ? event.transcript : "";
332
+ if (!text.trim()) return null;
333
+ const isFinal = typeof event.isFinal === "boolean" ? event.isFinal : typeof event.final === "boolean" ? event.final : event.type === "local_transcription";
334
+ return { text, isFinal, metadata: { ...event } };
335
+ }
336
+ function normalizeBridgeWifiEvent(event) {
337
+ const type = String(event.type ?? event.eventType ?? event.event_type ?? "");
338
+ const values = event.values && typeof event.values === "object" ? event.values : event;
339
+ const hasWifiFields = "wifiConnected" in values || "wifiSsid" in values || "wifiLocalIp" in values || "connected" in values || "ssid" in values || "networks" in values || "results" in values;
340
+ if (type !== "wifi_status_change" && type !== "wifi_status" && type !== "wifi_scan_result" && !hasWifiFields) {
341
+ return null;
342
+ }
343
+ const connected = booleanValue(values.wifiConnected) ?? booleanValue(values.connected);
344
+ const ssid = stringValue(values.wifiSsid) ?? stringValue(values.ssid);
345
+ const localIp = stringValue(values.wifiLocalIp) ?? stringValue(values.localIp);
346
+ const networks = parseWifiNetworks(values);
347
+ const status = parseWifiStatus(values) ?? (type === "wifi_scan_result" ? networks.length > 0 ? `found ${networks.length} Wi-Fi network(s)` : "Wi-Fi scan result" : connected ? `connected to ${ssid ?? "Wi-Fi"}` : connected === false ? "disconnected" : "Wi-Fi status updated");
348
+ return {
349
+ available: true,
350
+ status,
351
+ networks,
352
+ raw: { ...event, normalized: { connected, ssid, localIp } }
353
+ };
354
+ }
355
+ function getEvenHubRawEventType(event) {
356
+ const jsonData = normalizeJsonData(event.jsonData);
357
+ return getNestedEventType(event.listEvent) ?? getNestedEventType(event.textEvent) ?? getNestedEventType(event.sysEvent) ?? event.eventType ?? jsonData?.eventType ?? jsonData?.event_type ?? jsonData?.Event_Type ?? jsonData?.type ?? event.type ?? event.action;
358
+ }
359
+ function normalizeJsonData(value) {
360
+ if (value && typeof value === "object")
361
+ return value;
362
+ if (typeof value !== "string") return null;
363
+ try {
364
+ const parsed = JSON.parse(value);
365
+ return parsed && typeof parsed === "object" ? parsed : null;
366
+ } catch {
367
+ return null;
368
+ }
369
+ }
370
+ function getNestedEventType(value) {
371
+ if (!value || typeof value !== "object") return void 0;
372
+ const event = value;
373
+ return event.eventType ?? event.event_type ?? event.Event_Type ?? event.type;
374
+ }
375
+ function normalizeEvenHubEventLabel(rawEventType, event) {
376
+ if (rawEventType === void 0 && (event.listEvent || event.textEvent || event.sysEvent))
377
+ return "single_tap";
378
+ if (typeof rawEventType === "number") {
379
+ if (rawEventType === 0) return "single_tap";
380
+ if (rawEventType === 1) return "scroll_up";
381
+ if (rawEventType === 2) return "scroll_down";
382
+ if (rawEventType === 3) return "double_tap";
383
+ return null;
384
+ }
385
+ if (typeof rawEventType === "string") {
386
+ const value = rawEventType.toUpperCase();
387
+ if (value.includes("LONG")) return "long_press";
388
+ if (value.includes("DOUBLE")) return "double_tap";
389
+ if (value.includes("SCROLL_TOP") || value.includes("SCROLL_UP"))
390
+ return "scroll_up";
391
+ if (value.includes("SCROLL_BOTTOM") || value.includes("SCROLL_DOWN"))
392
+ return "scroll_down";
393
+ if (value === "UP") return "scroll_up";
394
+ if (value === "DOWN") return "scroll_down";
395
+ if (value.includes("CLICK") || value.includes("TAP")) return "single_tap";
396
+ if (value === "BUTTON_PRESS") return normalizeButtonPressEvent(event);
397
+ }
398
+ return normalizeButtonPressEvent(event);
399
+ }
400
+ function normalizeButtonPressEvent(event) {
401
+ const buttonValue = String(
402
+ event.pressType ?? event.button ?? event.buttonId ?? event.value ?? ""
403
+ ).toUpperCase();
404
+ if (buttonValue.includes("LONG")) return "long_press";
405
+ if (buttonValue.includes("DOUBLE")) return "double_tap";
406
+ if (buttonValue.includes("SCROLL_TOP") || buttonValue.includes("UP"))
407
+ return "scroll_up";
408
+ if (buttonValue.includes("SCROLL_BOTTOM") || buttonValue.includes("DOWN"))
409
+ return "scroll_down";
410
+ if (buttonValue.includes("SINGLE") || buttonValue.includes("TAP"))
411
+ return "single_tap";
412
+ return null;
413
+ }
414
+ function normalizeBridgeSubscription(subscription) {
415
+ if (typeof subscription === "function") return subscription;
416
+ if (!subscription || typeof subscription !== "object") return null;
417
+ return subscription.unsubscribe?.bind(subscription) ?? subscription.off?.bind(subscription) ?? subscription.remove?.bind(subscription) ?? null;
418
+ }
419
+ function normalizeWifiResult(raw, fallbackStatus) {
420
+ return {
421
+ available: true,
422
+ status: parseWifiStatus(raw) ?? fallbackStatus,
423
+ networks: parseWifiNetworks(raw),
424
+ raw
425
+ };
426
+ }
427
+ function parseWifiStatus(raw) {
428
+ if (typeof raw === "string" && raw.trim()) return raw.trim();
429
+ if (!raw || typeof raw !== "object") return null;
430
+ const record = raw;
431
+ const value = record.status ?? record.state ?? record.message ?? record.result ?? record.connectedSsid ?? record.ssid;
432
+ return typeof value === "string" && value.trim() ? value.trim() : null;
433
+ }
434
+ function booleanValue(value) {
435
+ if (typeof value === "boolean") return value;
436
+ if (typeof value === "number") return value !== 0;
437
+ if (typeof value === "string") {
438
+ if (/^(true|1|yes|connected)$/i.test(value)) return true;
439
+ if (/^(false|0|no|disconnected)$/i.test(value)) return false;
440
+ }
441
+ return null;
442
+ }
443
+ function stringValue(value) {
444
+ return typeof value === "string" && value.trim() ? value.trim() : null;
445
+ }
446
+ function parseWifiNetworks(raw) {
447
+ if (!raw || typeof raw !== "object") return [];
448
+ const record = raw;
449
+ const value = record.networks ?? record.networks_neo ?? record.results;
450
+ if (!Array.isArray(value)) return [];
451
+ return value.map((network) => {
452
+ if (typeof network === "string") return network;
453
+ if (!network || typeof network !== "object") return "";
454
+ const item = network;
455
+ return String(item.ssid ?? item.SSID ?? item.name ?? "");
456
+ }).filter((ssid) => ssid.trim().length > 0);
457
+ }
458
+ function createEvenHubTextPage(textBytes) {
459
+ const text = new TextDecoder().decode(textBytes);
460
+ return {
461
+ containerTotalNum: 2,
462
+ text,
463
+ textObject: [
464
+ {
465
+ containerID: 1,
466
+ containerName: "eliza-smartglasses-text",
467
+ content: text,
468
+ xPosition: 12,
469
+ yPosition: 12,
470
+ width: 552,
471
+ height: 200,
472
+ isEventCapture: 0
473
+ }
474
+ ],
475
+ listObject: [
476
+ {
477
+ containerID: 2,
478
+ containerName: "eliza-smartglasses-input",
479
+ itemContainer: {
480
+ itemCount: 1,
481
+ itemWidth: 552,
482
+ isItemSelectBorderEn: 0,
483
+ itemName: ["Click mic on | Double click mic off"]
484
+ },
485
+ isEventCapture: 1,
486
+ xPosition: 12,
487
+ yPosition: 236,
488
+ width: 552,
489
+ height: 36
490
+ }
491
+ ]
492
+ };
493
+ }
494
+ function assertEvenHubResult(result, operation) {
495
+ if (typeof result === "number" && result !== 0) {
496
+ throw new Error(`${operation} failed with result ${result}`);
497
+ }
498
+ if (typeof result === "boolean" && !result) {
499
+ throw new Error(`${operation} failed`);
500
+ }
501
+ }
502
+ function getGlobalEvenBridgeTransport() {
503
+ const globalBridge = globalThis.__evenBridge;
504
+ return globalBridge ? new EvenBridgeTransport(globalBridge) : null;
505
+ }
506
+ export {
507
+ EvenBridgeTransport,
508
+ getGlobalEvenBridgeTransport
509
+ };
510
+ //# sourceMappingURL=even-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/transport/even-bridge.ts"],"sourcesContent":["import {\n encodeMicCommand,\n G1Command,\n type G1Event,\n G1InteractionCode,\n G1SubCommand,\n type GlassSide,\n parseG1Notification,\n type SmartglassesAudioEncoding,\n} from \"../protocol/smartglasses.js\";\nimport type {\n SmartglassesConnectedLenses,\n SmartglassesTransport,\n SmartglassesWifiResult,\n} from \"./types.js\";\n\ntype EvenBridge = {\n requestWifiScan?: () => Promise<unknown> | unknown;\n requestWifiStatus?: () => Promise<unknown> | unknown;\n requestWifiSetup?: (reason?: string) => Promise<unknown> | unknown;\n setWifiCredentials?: (\n ssid: string,\n password: string,\n ) => Promise<unknown> | unknown;\n sendWifiCredentials?: (\n ssid: string,\n password: string,\n ) => Promise<unknown> | unknown;\n rawBridge?: {\n audioControl?: (enabled: boolean) => Promise<unknown> | unknown;\n callEvenApp?: (\n name: string,\n payload?: Record<string, unknown>,\n ) => Promise<unknown> | unknown;\n };\n audioControl?: (enabled: boolean) => Promise<unknown> | unknown;\n createStartUpPageContainer?: (\n container: Record<string, unknown>,\n ) => Promise<unknown> | unknown;\n clearDisplay?: () => Promise<unknown> | unknown;\n displayText?: (params: Record<string, unknown>) => Promise<unknown> | unknown;\n onEvent?: (callback: (event: unknown) => void) => BridgeSubscription;\n onEvenHubEvent?: (callback: (event: unknown) => void) => BridgeSubscription;\n rebuildPageContainer?: (\n container: Record<string, unknown>,\n ) => Promise<unknown> | unknown;\n sendStartUpPage?: (container: unknown) => Promise<unknown> | unknown;\n setMicState?: (\n sendPcmData: boolean,\n sendTranscript: boolean,\n bypassVad: boolean,\n ) => Promise<unknown> | unknown;\n write?: (side: GlassSide, data: Uint8Array) => Promise<unknown> | unknown;\n send?: (side: GlassSide, data: Uint8Array) => Promise<unknown> | unknown;\n};\n\ntype BridgeSubscription =\n | undefined\n | (() => void)\n | { unsubscribe?: () => void; off?: () => void; remove?: () => void };\n\nfunction normalizeBytes(value: unknown): Uint8Array | null {\n if (value instanceof Uint8Array) return value;\n if (value instanceof ArrayBuffer) return new Uint8Array(value);\n if (ArrayBuffer.isView(value)) {\n return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n }\n if (Array.isArray(value) && value.every((v) => Number.isInteger(v)))\n return Uint8Array.from(value);\n if (\n typeof value === \"string\" &&\n /^[0-9a-f]+$/i.test(value) &&\n value.length % 2 === 0\n ) {\n return Uint8Array.from(\n value.match(/../g)?.map((b) => Number.parseInt(b, 16)) ?? [],\n );\n }\n return null;\n}\n\nexport class EvenBridgeTransport implements SmartglassesTransport {\n readonly name = \"even-bridge\";\n private connected = false;\n private eventCallbacks = new Set<(event: G1Event) => void>();\n private audioCallbacks = new Set<\n (\n audioData: Uint8Array,\n sampleRate: number,\n side: GlassSide,\n encoding?: SmartglassesAudioEncoding,\n sequence?: number,\n ) => void\n >();\n private transcriptCallbacks = new Set<\n (text: string, isFinal: boolean, metadata?: Record<string, unknown>) => void\n >();\n private wifiCallbacks = new Set<(status: SmartglassesWifiResult) => void>();\n private bridgeDisposer: (() => void) | null = null;\n private readonly displayChunks = new Map<string, Uint8Array[]>();\n private evenHubStartupCreated = false;\n\n constructor(private readonly bridge: EvenBridge) {}\n\n async connect(): Promise<void> {\n this.connected = true;\n const register = this.bridge.onEvenHubEvent ?? this.bridge.onEvent;\n if (register) {\n const subscription = register.call(this.bridge, (event: unknown) =>\n this.handleBridgeEvent(event),\n );\n this.bridgeDisposer = normalizeBridgeSubscription(subscription);\n }\n }\n\n async disconnect(): Promise<void> {\n await this.openMicrophone(false);\n this.bridgeDisposer?.();\n this.bridgeDisposer = null;\n this.connected = false;\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n getConnectedLenses(): SmartglassesConnectedLenses {\n if (!this.connected) return {};\n return {\n left: {\n connected: true,\n name: \"Native bridge left lens\",\n },\n right: {\n connected: true,\n name: \"Native bridge right lens\",\n },\n };\n }\n\n async write(side: GlassSide, data: Uint8Array): Promise<void> {\n if (this.supportsEvenHubDisplay() && data[0] === G1Command.SendResult) {\n if (side === \"left\") await this.writeEvenHubDisplay(data);\n return;\n }\n if (this.supportsMentraDisplay() && data[0] === G1Command.SendResult) {\n if (side === \"left\") await this.writeMentraDisplay(data);\n return;\n }\n if (\n this.bridge.clearDisplay &&\n data[0] === G1Command.StartAi &&\n data[1] === G1SubCommand.Stop\n ) {\n await this.bridge.clearDisplay();\n return;\n }\n if (this.bridge.write) {\n await this.bridge.write(side, data);\n return;\n }\n if (this.bridge.send) {\n await this.bridge.send(side, data);\n return;\n }\n await this.bridge.rawBridge?.callEvenApp?.(\"sendData\", {\n side,\n data: Array.from(data),\n });\n }\n\n async writeBoth(data: Uint8Array): Promise<void> {\n await this.write(\"left\", data);\n await this.write(\"right\", data);\n }\n\n async openMicrophone(enabled: boolean): Promise<void> {\n if (this.bridge.setMicState) {\n await this.bridge.setMicState(enabled, enabled, enabled);\n return;\n }\n if (this.bridge.audioControl) {\n await this.bridge.audioControl(enabled);\n return;\n }\n if (this.bridge.rawBridge?.audioControl) {\n await this.bridge.rawBridge.audioControl(enabled);\n return;\n }\n if (this.bridge.rawBridge?.callEvenApp) {\n await this.bridge.rawBridge.callEvenApp(\"audioControl\", {\n isOpen: enabled,\n });\n return;\n }\n await this.write(\"right\", encodeMicCommand(enabled));\n }\n\n async scanWifi(): Promise<SmartglassesWifiResult> {\n this.assertWifiSupported();\n const raw = this.bridge.requestWifiScan\n ? await this.bridge.requestWifiScan()\n : await this.bridge.rawBridge?.callEvenApp?.(\"request_wifi_scan\");\n return normalizeWifiResult(raw, \"Wi-Fi scan requested\");\n }\n\n async getWifiStatus(): Promise<SmartglassesWifiResult> {\n this.assertWifiSupported();\n const raw = this.bridge.requestWifiStatus\n ? await this.bridge.requestWifiStatus()\n : await this.bridge.rawBridge?.callEvenApp?.(\"request_wifi_status\");\n return normalizeWifiResult(raw, \"Wi-Fi status requested\");\n }\n\n async configureWifi(\n ssid: string,\n password: string,\n ): Promise<SmartglassesWifiResult> {\n this.assertWifiSupported();\n const raw = this.bridge.setWifiCredentials\n ? await this.bridge.setWifiCredentials(ssid, password)\n : this.bridge.sendWifiCredentials\n ? await this.bridge.sendWifiCredentials(ssid, password)\n : await this.bridge.rawBridge?.callEvenApp?.(\"set_wifi_credentials\", {\n ssid,\n password,\n });\n return normalizeWifiResult(raw, `Wi-Fi credentials sent for ${ssid}`);\n }\n\n async requestWifiSetup(reason?: string): Promise<SmartglassesWifiResult> {\n this.assertWifiSupported();\n const raw = this.bridge.requestWifiSetup\n ? await this.bridge.requestWifiSetup(reason)\n : await this.bridge.rawBridge?.callEvenApp?.(\"request_wifi_setup\", {\n reason,\n });\n return normalizeWifiResult(raw, \"Wi-Fi setup requested\");\n }\n\n supportsWifi(): boolean {\n return Boolean(\n this.bridge.requestWifiScan ||\n this.bridge.requestWifiStatus ||\n this.bridge.requestWifiSetup ||\n this.bridge.setWifiCredentials ||\n this.bridge.sendWifiCredentials ||\n this.bridge.rawBridge?.callEvenApp,\n );\n }\n\n private assertWifiSupported(): void {\n if (!this.supportsWifi()) {\n throw new Error(\n \"Wi-Fi is only available when the native smartglasses bridge exposes Wi-Fi APIs\",\n );\n }\n }\n\n private supportsEvenHubDisplay(): boolean {\n return Boolean(\n this.bridge.sendStartUpPage || this.bridge.createStartUpPageContainer,\n );\n }\n\n private supportsMentraDisplay(): boolean {\n return Boolean(this.bridge.displayText);\n }\n\n onEvent(callback: (event: G1Event) => void): () => void {\n this.eventCallbacks.add(callback);\n return () => this.eventCallbacks.delete(callback);\n }\n\n onAudio(\n callback: (\n audioData: Uint8Array,\n sampleRate: number,\n side: GlassSide,\n encoding?: SmartglassesAudioEncoding,\n sequence?: number,\n ) => void,\n ): () => void {\n this.audioCallbacks.add(callback);\n return () => this.audioCallbacks.delete(callback);\n }\n\n onTranscript(\n callback: (\n text: string,\n isFinal: boolean,\n metadata?: Record<string, unknown>,\n ) => void,\n ): () => void {\n this.transcriptCallbacks.add(callback);\n return () => this.transcriptCallbacks.delete(callback);\n }\n\n onWifiStatus(callback: (status: SmartglassesWifiResult) => void): () => void {\n this.wifiCallbacks.add(callback);\n return () => this.wifiCallbacks.delete(callback);\n }\n\n private handleBridgeEvent(event: unknown): void {\n const maybe = event as Record<string, unknown>;\n const wifi = normalizeBridgeWifiEvent(maybe);\n if (wifi) {\n for (const callback of this.wifiCallbacks) callback(wifi);\n return;\n }\n const transcript = normalizeBridgeTranscriptEvent(maybe);\n if (transcript) {\n for (const callback of this.transcriptCallbacks)\n callback(transcript.text, transcript.isFinal, transcript.metadata);\n return;\n }\n const audio = maybe.audioEvent as Record<string, unknown> | undefined;\n const audioPcm = normalizeBytes(audio?.audioPcm);\n if (audioPcm) {\n for (const callback of this.audioCallbacks)\n callback(audioPcm, 16_000, \"right\", \"pcm16\");\n return;\n }\n const mentraPcm = normalizeBytes(maybe.pcm);\n if (maybe.type === \"mic_pcm\" && mentraPcm) {\n for (const callback of this.audioCallbacks)\n callback(mentraPcm, 16_000, \"right\", \"pcm16\");\n return;\n }\n const mentraLc3 = normalizeBytes(maybe.lc3);\n if (maybe.type === \"mic_lc3\" && mentraLc3) {\n for (const callback of this.audioCallbacks)\n callback(mentraLc3, 16_000, \"right\", \"lc3\");\n return;\n }\n const inputEvent = normalizeEvenHubInputEvent(maybe);\n if (inputEvent) {\n for (const callback of this.eventCallbacks) callback(inputEvent);\n return;\n }\n const side =\n maybe.side === \"left\" || maybe.side === \"right\" ? maybe.side : \"right\";\n const bytes = normalizeBytes(maybe.raw ?? maybe.data ?? maybe.bytes);\n if (!bytes) return;\n const parsed = parseG1Notification(side, bytes);\n for (const callback of this.eventCallbacks) callback(parsed);\n const audioData = parsed.audioPcm ?? parsed.audioData;\n if (audioData) {\n for (const callback of this.audioCallbacks)\n callback(\n audioData,\n 16_000,\n parsed.side,\n parsed.audioEncoding,\n parsed.sequence,\n );\n }\n }\n\n private async writeEvenHubDisplay(data: Uint8Array): Promise<void> {\n const display = this.decodeDisplayPacket(data);\n if (!display) return;\n const key = `${display.seq}:${display.status}:${display.pageNumber}:${display.maxPages}`;\n const chunks =\n this.displayChunks.get(key) ??\n Array.from<Uint8Array>({ length: display.totalPackages });\n chunks[display.currentPackage] = display.chunk;\n this.displayChunks.set(key, chunks);\n if (chunks.some((chunk) => !chunk)) return;\n\n this.displayChunks.delete(key);\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const textBytes = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n textBytes.set(chunk, offset);\n offset += chunk.length;\n }\n await this.sendEvenHubTextPage(textBytes);\n }\n\n private async writeMentraDisplay(data: Uint8Array): Promise<void> {\n const display = this.decodeDisplayPacket(data);\n if (!display) return;\n const key = `${display.seq}:${display.status}:${display.pageNumber}:${display.maxPages}`;\n const chunks =\n this.displayChunks.get(key) ??\n Array.from<Uint8Array>({ length: display.totalPackages });\n chunks[display.currentPackage] = display.chunk;\n this.displayChunks.set(key, chunks);\n if (chunks.some((chunk) => !chunk)) return;\n\n this.displayChunks.delete(key);\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const textBytes = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n textBytes.set(chunk, offset);\n offset += chunk.length;\n }\n await this.bridge.displayText?.({\n text: new TextDecoder().decode(textBytes),\n x: 0,\n y: 0,\n size: 24,\n });\n }\n\n private async sendEvenHubTextPage(textBytes: Uint8Array): Promise<void> {\n const page = createEvenHubTextPage(textBytes);\n if (this.bridge.sendStartUpPage) {\n await this.bridge.sendStartUpPage(page);\n return;\n }\n if (!this.bridge.createStartUpPageContainer) return;\n if (!this.evenHubStartupCreated) {\n assertEvenHubResult(\n await this.bridge.createStartUpPageContainer(page),\n \"createStartUpPageContainer\",\n );\n this.evenHubStartupCreated = true;\n return;\n }\n const rebuild =\n this.bridge.rebuildPageContainer ??\n this.bridge.createStartUpPageContainer;\n assertEvenHubResult(\n await rebuild.call(this.bridge, page),\n \"rebuildPageContainer\",\n );\n }\n\n private decodeDisplayPacket(data: Uint8Array): {\n seq: number;\n totalPackages: number;\n currentPackage: number;\n status: number;\n pageNumber: number;\n maxPages: number;\n chunk: Uint8Array;\n } | null {\n if (data.length < 9 || data[0] !== G1Command.SendResult) return null;\n const totalPackages = data[2] || 1;\n const currentPackage = data[3] || 0;\n if (currentPackage >= totalPackages) return null;\n return {\n seq: data[1] ?? 0,\n totalPackages,\n currentPackage,\n status: data[4] ?? 0,\n pageNumber: data[7] ?? 1,\n maxPages: data[8] ?? 1,\n chunk: data.slice(9),\n };\n }\n}\n\nfunction normalizeEvenHubInputEvent(\n event: Record<string, unknown>,\n): G1Event | null {\n const rawEventType = getEvenHubRawEventType(event);\n const label = normalizeEvenHubEventLabel(rawEventType, event);\n if (!label) return null;\n const code =\n label === \"single_tap\"\n ? G1InteractionCode.SingleTap\n : label === \"double_tap\"\n ? G1InteractionCode.DoubleTap\n : label === \"long_press\"\n ? G1InteractionCode.LongPress\n : G1SubCommand.PageControl;\n return {\n side: \"right\",\n raw: Uint8Array.from([G1Command.StartAi, code]),\n type: \"state\",\n code,\n label,\n };\n}\n\nfunction normalizeBridgeTranscriptEvent(event: Record<string, unknown>): {\n text: string;\n isFinal: boolean;\n metadata: Record<string, unknown>;\n} | null {\n const type = String(event.type ?? event.streamType ?? \"\");\n if (\n type !== \"local_transcription\" &&\n !type.startsWith(\"transcription\") &&\n !(\"transcript\" in event)\n )\n return null;\n const text =\n typeof event.text === \"string\"\n ? event.text\n : typeof event.transcript === \"string\"\n ? event.transcript\n : \"\";\n if (!text.trim()) return null;\n const isFinal =\n typeof event.isFinal === \"boolean\"\n ? event.isFinal\n : typeof event.final === \"boolean\"\n ? event.final\n : event.type === \"local_transcription\";\n return { text, isFinal, metadata: { ...event } };\n}\n\nfunction normalizeBridgeWifiEvent(\n event: Record<string, unknown>,\n): SmartglassesWifiResult | null {\n const type = String(event.type ?? event.eventType ?? event.event_type ?? \"\");\n const values =\n event.values && typeof event.values === \"object\"\n ? (event.values as Record<string, unknown>)\n : event;\n const hasWifiFields =\n \"wifiConnected\" in values ||\n \"wifiSsid\" in values ||\n \"wifiLocalIp\" in values ||\n \"connected\" in values ||\n \"ssid\" in values ||\n \"networks\" in values ||\n \"results\" in values;\n if (\n type !== \"wifi_status_change\" &&\n type !== \"wifi_status\" &&\n type !== \"wifi_scan_result\" &&\n !hasWifiFields\n ) {\n return null;\n }\n const connected =\n booleanValue(values.wifiConnected) ?? booleanValue(values.connected);\n const ssid = stringValue(values.wifiSsid) ?? stringValue(values.ssid);\n const localIp =\n stringValue(values.wifiLocalIp) ?? stringValue(values.localIp);\n const networks = parseWifiNetworks(values);\n const status =\n parseWifiStatus(values) ??\n (type === \"wifi_scan_result\"\n ? networks.length > 0\n ? `found ${networks.length} Wi-Fi network(s)`\n : \"Wi-Fi scan result\"\n : connected\n ? `connected to ${ssid ?? \"Wi-Fi\"}`\n : connected === false\n ? \"disconnected\"\n : \"Wi-Fi status updated\");\n return {\n available: true,\n status,\n networks,\n raw: { ...event, normalized: { connected, ssid, localIp } },\n };\n}\n\nfunction getEvenHubRawEventType(event: Record<string, unknown>): unknown {\n const jsonData = normalizeJsonData(event.jsonData);\n return (\n getNestedEventType(event.listEvent) ??\n getNestedEventType(event.textEvent) ??\n getNestedEventType(event.sysEvent) ??\n event.eventType ??\n jsonData?.eventType ??\n jsonData?.event_type ??\n jsonData?.Event_Type ??\n jsonData?.type ??\n event.type ??\n event.action\n );\n}\n\nfunction normalizeJsonData(value: unknown): Record<string, unknown> | null {\n if (value && typeof value === \"object\")\n return value as Record<string, unknown>;\n if (typeof value !== \"string\") return null;\n try {\n const parsed = JSON.parse(value);\n return parsed && typeof parsed === \"object\"\n ? (parsed as Record<string, unknown>)\n : null;\n } catch {\n return null;\n }\n}\n\nfunction getNestedEventType(value: unknown): unknown {\n if (!value || typeof value !== \"object\") return undefined;\n const event = value as Record<string, unknown>;\n return event.eventType ?? event.event_type ?? event.Event_Type ?? event.type;\n}\n\nfunction normalizeEvenHubEventLabel(\n rawEventType: unknown,\n event: Record<string, unknown>,\n):\n | \"single_tap\"\n | \"double_tap\"\n | \"long_press\"\n | \"scroll_up\"\n | \"scroll_down\"\n | null {\n if (\n rawEventType === undefined &&\n (event.listEvent || event.textEvent || event.sysEvent)\n )\n return \"single_tap\";\n if (typeof rawEventType === \"number\") {\n if (rawEventType === 0) return \"single_tap\";\n if (rawEventType === 1) return \"scroll_up\";\n if (rawEventType === 2) return \"scroll_down\";\n if (rawEventType === 3) return \"double_tap\";\n return null;\n }\n if (typeof rawEventType === \"string\") {\n const value = rawEventType.toUpperCase();\n if (value.includes(\"LONG\")) return \"long_press\";\n if (value.includes(\"DOUBLE\")) return \"double_tap\";\n if (value.includes(\"SCROLL_TOP\") || value.includes(\"SCROLL_UP\"))\n return \"scroll_up\";\n if (value.includes(\"SCROLL_BOTTOM\") || value.includes(\"SCROLL_DOWN\"))\n return \"scroll_down\";\n if (value === \"UP\") return \"scroll_up\";\n if (value === \"DOWN\") return \"scroll_down\";\n if (value.includes(\"CLICK\") || value.includes(\"TAP\")) return \"single_tap\";\n if (value === \"BUTTON_PRESS\") return normalizeButtonPressEvent(event);\n }\n return normalizeButtonPressEvent(event);\n}\n\nfunction normalizeButtonPressEvent(\n event: Record<string, unknown>,\n):\n | \"single_tap\"\n | \"double_tap\"\n | \"long_press\"\n | \"scroll_up\"\n | \"scroll_down\"\n | null {\n const buttonValue = String(\n event.pressType ?? event.button ?? event.buttonId ?? event.value ?? \"\",\n ).toUpperCase();\n if (buttonValue.includes(\"LONG\")) return \"long_press\";\n if (buttonValue.includes(\"DOUBLE\")) return \"double_tap\";\n if (buttonValue.includes(\"SCROLL_TOP\") || buttonValue.includes(\"UP\"))\n return \"scroll_up\";\n if (buttonValue.includes(\"SCROLL_BOTTOM\") || buttonValue.includes(\"DOWN\"))\n return \"scroll_down\";\n if (buttonValue.includes(\"SINGLE\") || buttonValue.includes(\"TAP\"))\n return \"single_tap\";\n return null;\n}\n\nfunction normalizeBridgeSubscription(\n subscription: BridgeSubscription,\n): (() => void) | null {\n if (typeof subscription === \"function\") return subscription;\n if (!subscription || typeof subscription !== \"object\") return null;\n return (\n subscription.unsubscribe?.bind(subscription) ??\n subscription.off?.bind(subscription) ??\n subscription.remove?.bind(subscription) ??\n null\n );\n}\n\nfunction normalizeWifiResult(\n raw: unknown,\n fallbackStatus: string,\n): SmartglassesWifiResult {\n return {\n available: true,\n status: parseWifiStatus(raw) ?? fallbackStatus,\n networks: parseWifiNetworks(raw),\n raw,\n };\n}\n\nfunction parseWifiStatus(raw: unknown): string | null {\n if (typeof raw === \"string\" && raw.trim()) return raw.trim();\n if (!raw || typeof raw !== \"object\") return null;\n const record = raw as Record<string, unknown>;\n const value =\n record.status ??\n record.state ??\n record.message ??\n record.result ??\n record.connectedSsid ??\n record.ssid;\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\n}\n\nfunction booleanValue(value: unknown): boolean | null {\n if (typeof value === \"boolean\") return value;\n if (typeof value === \"number\") return value !== 0;\n if (typeof value === \"string\") {\n if (/^(true|1|yes|connected)$/i.test(value)) return true;\n if (/^(false|0|no|disconnected)$/i.test(value)) return false;\n }\n return null;\n}\n\nfunction stringValue(value: unknown): string | null {\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\n}\n\nfunction parseWifiNetworks(raw: unknown): string[] {\n if (!raw || typeof raw !== \"object\") return [];\n const record = raw as Record<string, unknown>;\n const value = record.networks ?? record.networks_neo ?? record.results;\n if (!Array.isArray(value)) return [];\n return value\n .map((network) => {\n if (typeof network === \"string\") return network;\n if (!network || typeof network !== \"object\") return \"\";\n const item = network as Record<string, unknown>;\n return String(item.ssid ?? item.SSID ?? item.name ?? \"\");\n })\n .filter((ssid) => ssid.trim().length > 0);\n}\n\nfunction createEvenHubTextPage(textBytes: Uint8Array): Record<string, unknown> {\n const text = new TextDecoder().decode(textBytes);\n return {\n containerTotalNum: 2,\n text,\n textObject: [\n {\n containerID: 1,\n containerName: \"eliza-smartglasses-text\",\n content: text,\n xPosition: 12,\n yPosition: 12,\n width: 552,\n height: 200,\n isEventCapture: 0,\n },\n ],\n listObject: [\n {\n containerID: 2,\n containerName: \"eliza-smartglasses-input\",\n itemContainer: {\n itemCount: 1,\n itemWidth: 552,\n isItemSelectBorderEn: 0,\n itemName: [\"Click mic on | Double click mic off\"],\n },\n isEventCapture: 1,\n xPosition: 12,\n yPosition: 236,\n width: 552,\n height: 36,\n },\n ],\n };\n}\n\nfunction assertEvenHubResult(result: unknown, operation: string): void {\n if (typeof result === \"number\" && result !== 0) {\n throw new Error(`${operation} failed with result ${result}`);\n }\n if (typeof result === \"boolean\" && !result) {\n throw new Error(`${operation} failed`);\n }\n}\n\nexport function getGlobalEvenBridgeTransport(): SmartglassesTransport | null {\n const globalBridge = (globalThis as Record<string, unknown>).__evenBridge as\n | EvenBridge\n | undefined;\n return globalBridge ? new EvenBridgeTransport(globalBridge) : null;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,42 @@
1
+ import { type G1Event, type GlassSide, type SmartglassesAudioEncoding } from "../protocol/smartglasses.js";
2
+ import type { SmartglassesConnectedLenses, SmartglassesTransport, SmartglassesWifiResult } from "./types.js";
3
+ export declare class MockSmartglassesTransport implements SmartglassesTransport {
4
+ readonly name = "mock-smartglasses";
5
+ readonly writes: Array<{
6
+ side: GlassSide;
7
+ data: Uint8Array;
8
+ }>;
9
+ readonly wifiRequests: Array<{
10
+ op: "scan" | "status" | "configure" | "setup";
11
+ ssid?: string;
12
+ password?: string;
13
+ reason?: string;
14
+ }>;
15
+ wifiResult: SmartglassesWifiResult;
16
+ private connected;
17
+ private eventCallbacks;
18
+ private audioCallbacks;
19
+ private transcriptCallbacks;
20
+ private wifiCallbacks;
21
+ connect(): Promise<void>;
22
+ disconnect(): Promise<void>;
23
+ isConnected(): boolean;
24
+ getConnectedLenses(): SmartglassesConnectedLenses;
25
+ write(side: GlassSide, data: Uint8Array): Promise<void>;
26
+ writeBoth(data: Uint8Array): Promise<void>;
27
+ openMicrophone(enabled: boolean): Promise<void>;
28
+ onEvent(callback: (event: G1Event) => void): () => void;
29
+ onAudio(callback: (audioData: Uint8Array, sampleRate: number, side: GlassSide, encoding?: SmartglassesAudioEncoding, sequence?: number) => void): () => void;
30
+ onTranscript(callback: (text: string, isFinal: boolean, metadata?: Record<string, unknown>) => void): () => void;
31
+ onWifiStatus(callback: (status: SmartglassesWifiResult) => void): () => void;
32
+ emitRaw(side: GlassSide, data: Uint8Array): void;
33
+ emitEvent(event: G1Event): void;
34
+ emitTranscript(text: string, isFinal?: boolean, metadata?: Record<string, unknown>): void;
35
+ emitWifiStatus(status: SmartglassesWifiResult): void;
36
+ scanWifi(): Promise<SmartglassesWifiResult>;
37
+ getWifiStatus(): Promise<SmartglassesWifiResult>;
38
+ configureWifi(ssid: string, password: string): Promise<SmartglassesWifiResult>;
39
+ requestWifiSetup(reason?: string): Promise<SmartglassesWifiResult>;
40
+ supportsWifi(): boolean;
41
+ }
42
+ //# sourceMappingURL=mock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../src/transport/mock.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,OAAO,EACZ,KAAK,SAAS,EAEd,KAAK,yBAAyB,EAC/B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EACV,2BAA2B,EAC3B,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAEpB,qBAAa,yBAA0B,YAAW,qBAAqB;IACrE,QAAQ,CAAC,IAAI,uBAAuB;IACpC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC,CAAM;IACnE,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAC;QAC3B,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC;QAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAM;IACR,UAAU,EAAE,sBAAsB,CAIhC;IACF,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAuC;IAC7D,OAAO,CAAC,cAAc,CAQlB;IACJ,OAAO,CAAC,mBAAmB,CAEvB;IACJ,OAAO,CAAC,aAAa,CAAuD;IAEtE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC,WAAW,IAAI,OAAO;IAItB,kBAAkB,IAAI,2BAA2B;IAgB3C,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1C,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAKrD,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI;IAKvD,OAAO,CACL,QAAQ,EAAE,CACR,SAAS,EAAE,UAAU,EACrB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,SAAS,EACf,QAAQ,CAAC,EAAE,yBAAyB,EACpC,QAAQ,CAAC,EAAE,MAAM,KACd,IAAI,GACR,MAAM,IAAI;IAKb,YAAY,CACV,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC/B,IAAI,GACR,MAAM,IAAI;IAKb,YAAY,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,IAAI,GAAG,MAAM,IAAI;IAK5E,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAKhD,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAe/B,cAAc,CACZ,IAAI,EAAE,MAAM,EACZ,OAAO,UAAO,EACd,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,IAAI;IAKP,cAAc,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI;IAI9C,QAAQ,IAAI,OAAO,CAAC,sBAAsB,CAAC;IAK3C,aAAa,IAAI,OAAO,CAAC,sBAAsB,CAAC;IAKhD,aAAa,CACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,sBAAsB,CAAC;IAQ5B,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAQxE,YAAY,IAAI,OAAO;CAGxB"}