@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,2950 @@
1
+ import { Button as e, Card as t, Divider as n, Field as r, HStack as i, List as a, SpatialSurface as o, Text as s, VStack as c } from "@elizaos/ui/spatial";
2
+ import { useCallback as l, useEffect as u, useMemo as d, useRef as f, useState as p } from "react";
3
+ import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
4
+ import { TerminalPluginView as _ } from "@elizaos/ui";
5
+ import { useAgentElement as v } from "@elizaos/ui/agent-surface";
6
+ import { BatteryCharging as ee, Bluetooth as te, CheckCircle2 as y, Circle as ne, Clipboard as re, Download as ie, Glasses as ae, Mic as oe, RefreshCw as se, Settings2 as ce, Wifi as le, XCircle as ue, Zap as b } from "lucide-react";
7
+ //#region src/components/FacewearSpatialView.tsx
8
+ var x = 4;
9
+ function S(e) {
10
+ return e ? "success" : "muted";
11
+ }
12
+ function de({ snapshot: r, onAction: o }) {
13
+ let l = (e) => () => o?.(e), { connectedCount: u } = r, d = r.devices.slice(0, x), f = Math.max(0, r.devices.length - x);
14
+ return /* @__PURE__ */ g(t, {
15
+ gap: 1,
16
+ padding: 1,
17
+ children: [
18
+ /* @__PURE__ */ g(i, {
19
+ gap: 1,
20
+ align: "center",
21
+ children: [/* @__PURE__ */ h(s, {
22
+ style: "caption",
23
+ tone: u > 0 ? "success" : "muted",
24
+ grow: 1,
25
+ children: u > 0 ? `${u} device${u === 1 ? "" : "s"} connected` : "None"
26
+ }), /* @__PURE__ */ h(s, {
27
+ style: "caption",
28
+ tone: "muted",
29
+ children: r.loading ? "loading" : `${r.profiles.length} models`
30
+ })]
31
+ }),
32
+ r.error ? /* @__PURE__ */ h(s, {
33
+ tone: "danger",
34
+ style: "caption",
35
+ children: r.error
36
+ }) : null,
37
+ d.length > 0 ? /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h(n, { label: "active" }), /* @__PURE__ */ g(i, {
38
+ gap: 1,
39
+ wrap: !0,
40
+ children: [d.map((e) => /* @__PURE__ */ h(s, {
41
+ style: "caption",
42
+ tone: "success",
43
+ wrap: !1,
44
+ children: e.deviceType ?? e.kind
45
+ }, e.id)), f > 0 ? /* @__PURE__ */ g(s, {
46
+ style: "caption",
47
+ tone: "muted",
48
+ children: ["+", f]
49
+ }) : null]
50
+ })] }) : null,
51
+ /* @__PURE__ */ h(n, { label: "devices" }),
52
+ r.profiles.length === 0 ? /* @__PURE__ */ h(s, {
53
+ tone: "muted",
54
+ align: "center",
55
+ style: "caption",
56
+ children: r.loading ? "Loading" : "None"
57
+ }) : /* @__PURE__ */ h(a, {
58
+ gap: 0,
59
+ children: r.profiles.map((t) => /* @__PURE__ */ g(i, {
60
+ gap: 1,
61
+ align: "center",
62
+ agent: `device-${t.type}`,
63
+ children: [
64
+ /* @__PURE__ */ h(s, {
65
+ tone: S(t.connected),
66
+ children: t.connected ? "[ok]" : "[ ]"
67
+ }),
68
+ /* @__PURE__ */ g(c, {
69
+ gap: 0,
70
+ grow: 1,
71
+ children: [/* @__PURE__ */ h(s, {
72
+ bold: !0,
73
+ wrap: !1,
74
+ children: t.name
75
+ }), /* @__PURE__ */ g(s, {
76
+ style: "caption",
77
+ tone: "muted",
78
+ wrap: !1,
79
+ children: [
80
+ t.manufacturer,
81
+ " · ",
82
+ t.connectionType
83
+ ]
84
+ })]
85
+ }),
86
+ /* @__PURE__ */ h(e, {
87
+ variant: t.connected ? "outline" : "solid",
88
+ tone: t.connected ? "default" : "primary",
89
+ agent: `connect:${t.type}`,
90
+ onPress: l(`connect:${t.type}`),
91
+ children: t.connected ? "Manage" : "Connect"
92
+ })
93
+ ]
94
+ }, t.type))
95
+ }),
96
+ /* @__PURE__ */ h(n, { label: "actions" }),
97
+ /* @__PURE__ */ g(i, {
98
+ gap: 1,
99
+ wrap: !0,
100
+ children: [
101
+ /* @__PURE__ */ h(e, {
102
+ variant: "outline",
103
+ tone: "default",
104
+ grow: 1,
105
+ agent: "xr-connect",
106
+ onPress: l("xr-connect"),
107
+ children: "XR Connect"
108
+ }),
109
+ /* @__PURE__ */ h(e, {
110
+ variant: "outline",
111
+ tone: "default",
112
+ grow: 1,
113
+ agent: "xr-status",
114
+ onPress: l("xr-status"),
115
+ children: "XR Status"
116
+ }),
117
+ /* @__PURE__ */ h(e, {
118
+ variant: "ghost",
119
+ tone: "default",
120
+ agent: "refresh",
121
+ onPress: l("refresh"),
122
+ children: "Refresh"
123
+ })
124
+ ]
125
+ })
126
+ ]
127
+ });
128
+ }
129
+ //#endregion
130
+ //#region src/components/facewear-profiles.ts
131
+ var C = [
132
+ {
133
+ type: "meta-quest",
134
+ name: "Meta Quest 3 / 3S / Pro",
135
+ manufacturer: "Meta",
136
+ connectionType: "WebXR",
137
+ description: "Passthrough AR/VR"
138
+ },
139
+ {
140
+ type: "xreal",
141
+ name: "XReal Air 3 / One Pro",
142
+ manufacturer: "XREAL",
143
+ connectionType: "WebXR",
144
+ description: "Spatial display"
145
+ },
146
+ {
147
+ type: "even-realities",
148
+ name: "Even Realities G1 / G2",
149
+ manufacturer: "Even Realities",
150
+ connectionType: "Bluetooth BLE",
151
+ description: "OLED display and mic"
152
+ },
153
+ {
154
+ type: "apple-vision-pro",
155
+ name: "Apple Vision Pro",
156
+ manufacturer: "Apple",
157
+ connectionType: "WebXR",
158
+ description: "visionOS headset"
159
+ }
160
+ ];
161
+ function w(e, t) {
162
+ return t.some((t) => t.deviceType === e.type || e.type === "even-realities" && t.kind === "smartglasses" || e.connectionType === "WebXR" && t.kind === "xr");
163
+ }
164
+ //#endregion
165
+ //#region src/components/FacewearView.tsx
166
+ function T(e) {
167
+ if (!(typeof window > "u")) {
168
+ if (e === "even-realities") {
169
+ window.location.assign("/apps/smartglasses");
170
+ return;
171
+ }
172
+ window.open("/api/xr/connect", "_blank", "noopener,noreferrer");
173
+ }
174
+ }
175
+ function E(e) {
176
+ typeof window > "u" || window.open(e, "_blank", "noopener,noreferrer");
177
+ }
178
+ function D() {
179
+ let [e, t] = p([]), [n, r] = p(!0), [i, a] = p(null), s = l(async () => {
180
+ try {
181
+ let e = await fetch("/api/facewear/status");
182
+ e.ok && (t((await e.json()).devices), a(null));
183
+ } catch (e) {
184
+ a(e instanceof Error ? e.message : String(e));
185
+ } finally {
186
+ r(!1);
187
+ }
188
+ }, []), c = f(!1);
189
+ u(() => {
190
+ c.current || (c.current = !0, s());
191
+ let e = setInterval(() => void s(), 5e3);
192
+ return () => clearInterval(e);
193
+ }, [s]);
194
+ let d = l((e) => {
195
+ if (e.startsWith("connect:")) {
196
+ T(e.slice(8));
197
+ return;
198
+ }
199
+ switch (e) {
200
+ case "refresh":
201
+ s();
202
+ return;
203
+ case "xr-connect":
204
+ E("/api/xr/connect");
205
+ return;
206
+ case "xr-status":
207
+ E("/api/xr/status");
208
+ return;
209
+ }
210
+ }, [s]);
211
+ return /* @__PURE__ */ h(o, { children: /* @__PURE__ */ h(de, {
212
+ snapshot: {
213
+ profiles: C.map((t) => ({
214
+ type: t.type,
215
+ name: t.name,
216
+ manufacturer: t.manufacturer,
217
+ connectionType: t.connectionType,
218
+ connected: w(t, e)
219
+ })),
220
+ devices: e,
221
+ connectedCount: e.length,
222
+ loading: n,
223
+ error: i
224
+ },
225
+ onAction: d
226
+ }) });
227
+ }
228
+ //#endregion
229
+ //#region src/protocol/smartglasses.ts
230
+ var O = {
231
+ service: "6e400001-b5a3-f393-e0a9-e50e24dcca9e",
232
+ tx: "6e400002-b5a3-f393-e0a9-e50e24dcca9e",
233
+ rx: "6e400003-b5a3-f393-e0a9-e50e24dcca9e"
234
+ }, k = /* @__PURE__ */ function(e) {
235
+ return e[e.StartAi = 245] = "StartAi", e[e.OpenMic = 14] = "OpenMic", e[e.ReceiveMicData = 241] = "ReceiveMicData", e[e.Init = 77] = "Init", e[e.RightInit = 244] = "RightInit", e[e.Heartbeat = 37] = "Heartbeat", e[e.Battery = 44] = "Battery", e[e.SendResult = 78] = "SendResult", e[e.QuickNote = 33] = "QuickNote", e[e.Dashboard = 34] = "Dashboard", e[e.Notification = 75] = "Notification", e[e.DashboardContent = 6] = "DashboardContent", e[e.Navigation = 10] = "Navigation", e[e.TranslateSetup = 57] = "TranslateSetup", e[e.TranslateStart = 80] = "TranslateStart", e[e.TranslateLanguages = 28] = "TranslateLanguages", e[e.TranslateOriginalText = 15] = "TranslateOriginalText", e[e.TranslateTranslatedText = 13] = "TranslateTranslatedText", e[e.AppWhitelist = 4] = "AppWhitelist", e[e.ExitFunction = 24] = "ExitFunction", e[e.SilentMode = 3] = "SilentMode", e[e.Brightness = 1] = "Brightness", e[e.DashboardPosition = 38] = "DashboardPosition", e[e.HeadUpAngle = 11] = "HeadUpAngle", e[e.GlassesWear = 39] = "GlassesWear", e[e.BmpData = 21] = "BmpData", e[e.BmpCrc = 22] = "BmpCrc", e[e.BmpEnd = 32] = "BmpEnd", e[e.Note = 30] = "Note", e[e.GetSerial = 52] = "GetSerial", e;
236
+ }({}), fe = /* @__PURE__ */ function(e) {
237
+ return e[e.Exit = 0] = "Exit", e[e.PageControl = 1] = "PageControl", e[e.Start = 23] = "Start", e[e.Stop = 24] = "Stop", e;
238
+ }({}), A = /* @__PURE__ */ function(e) {
239
+ return e[e.NewContent = 1] = "NewContent", e;
240
+ }({}), pe = /* @__PURE__ */ function(e) {
241
+ return e[e.Displaying = 48] = "Displaying", e[e.DisplayComplete = 64] = "DisplayComplete", e[e.ManualMode = 80] = "ManualMode", e[e.NetworkError = 96] = "NetworkError", e;
242
+ }({}), j = /* @__PURE__ */ function(e) {
243
+ return e[e.TextShow = 112] = "TextShow", e;
244
+ }({}), M = /* @__PURE__ */ function(e) {
245
+ return e[e.DoubleTap = 0] = "DoubleTap", e[e.SingleTap = 1] = "SingleTap", e[e.LongPress = 23] = "LongPress", e[e.StopAiRecording = 24] = "StopAiRecording", e[e.SilentModeOn = 4] = "SilentModeOn", e[e.SilentModeOff = 5] = "SilentModeOff", e[e.OpenDashboardStart = 2] = "OpenDashboardStart", e[e.CloseDashboardStart = 3] = "CloseDashboardStart", e[e.OpenDashboardConfirm = 30] = "OpenDashboardConfirm", e[e.CloseDashboardConfirm = 31] = "CloseDashboardConfirm", e;
246
+ }({}), N = {
247
+ displayWidthPx: 576,
248
+ charsPerLine: 40,
249
+ linesPerPage: 5,
250
+ maxTextLength: 200,
251
+ maxPayloadBytes: 191
252
+ }, me = new Map(Object.entries({
253
+ " ": 2,
254
+ "!": 1,
255
+ "\"": 2,
256
+ "#": 6,
257
+ $: 5,
258
+ "%": 6,
259
+ "&": 7,
260
+ "'": 1,
261
+ "(": 2,
262
+ ")": 2,
263
+ "*": 3,
264
+ "+": 4,
265
+ ",": 1,
266
+ "-": 4,
267
+ ".": 1,
268
+ "/": 3,
269
+ 0: 5,
270
+ 1: 3,
271
+ 2: 5,
272
+ 3: 5,
273
+ 4: 5,
274
+ 5: 5,
275
+ 6: 5,
276
+ 7: 5,
277
+ 8: 5,
278
+ 9: 5,
279
+ ":": 1,
280
+ ";": 1,
281
+ "<": 4,
282
+ "=": 4,
283
+ ">": 4,
284
+ "?": 5,
285
+ "@": 7,
286
+ A: 6,
287
+ B: 5,
288
+ C: 5,
289
+ D: 5,
290
+ E: 4,
291
+ F: 4,
292
+ G: 5,
293
+ H: 5,
294
+ I: 2,
295
+ J: 3,
296
+ K: 5,
297
+ L: 4,
298
+ M: 7,
299
+ N: 5,
300
+ O: 5,
301
+ P: 5,
302
+ Q: 5,
303
+ R: 5,
304
+ S: 5,
305
+ T: 5,
306
+ U: 5,
307
+ V: 6,
308
+ W: 7,
309
+ X: 6,
310
+ Y: 6,
311
+ Z: 5,
312
+ "[": 2,
313
+ "\\": 3,
314
+ "]": 2,
315
+ "^": 4,
316
+ _: 3,
317
+ "`": 2,
318
+ a: 5,
319
+ b: 4,
320
+ c: 4,
321
+ d: 4,
322
+ e: 4,
323
+ f: 4,
324
+ g: 4,
325
+ h: 4,
326
+ i: 1,
327
+ j: 2,
328
+ k: 4,
329
+ l: 1,
330
+ m: 7,
331
+ n: 4,
332
+ o: 4,
333
+ p: 4,
334
+ q: 4,
335
+ r: 3,
336
+ s: 4,
337
+ t: 3,
338
+ u: 5,
339
+ v: 5,
340
+ w: 7,
341
+ x: 5,
342
+ y: 5,
343
+ z: 4,
344
+ "{": 3,
345
+ "|": 1,
346
+ "}": 3,
347
+ "~": 7
348
+ })), P = new Map([
349
+ [0, "double_tap"],
350
+ [1, "single_tap"],
351
+ [23, "long_press"],
352
+ [24, "stop_ai_recording"],
353
+ [4, "silent_mode_on"],
354
+ [5, "silent_mode_off"],
355
+ [2, "open_dashboard_start"],
356
+ [3, "close_dashboard_start"],
357
+ [30, "open_dashboard_confirm"],
358
+ [31, "close_dashboard_confirm"]
359
+ ]), he = new Map([
360
+ [6, "wearing"],
361
+ [7, "transitioning"],
362
+ [8, "cradle_open"],
363
+ [9, "charged_in_cradle"],
364
+ [11, "cradle_closed"]
365
+ ]), ge = new Map([
366
+ [9, "glasses_fully_charged"],
367
+ [14, "cradle_charging_cable_changed"],
368
+ [15, "cradle_fully_charged"]
369
+ ]), _e = new Map([
370
+ [10, "device_unknown_0a"],
371
+ [17, "connected"],
372
+ [18, "device_unknown_12"],
373
+ [20, "device_unknown_14"],
374
+ [21, "device_unknown_15"]
375
+ ]);
376
+ function F(e) {
377
+ if (e === void 0) return null;
378
+ let t = P.get(e);
379
+ if (t) return {
380
+ category: "interaction",
381
+ label: t,
382
+ name: t
383
+ };
384
+ let n = he.get(e);
385
+ if (n) return {
386
+ category: "physical",
387
+ label: n,
388
+ name: n
389
+ };
390
+ let r = ge.get(e);
391
+ if (r) return {
392
+ category: "battery",
393
+ label: r,
394
+ name: r
395
+ };
396
+ let i = _e.get(e);
397
+ return i ? {
398
+ category: "device",
399
+ label: i,
400
+ name: i
401
+ } : null;
402
+ }
403
+ function ve(e) {
404
+ let t = 0;
405
+ for (let n of e) t += ye(n);
406
+ return t;
407
+ }
408
+ function ye(e) {
409
+ let t = e.codePointAt(0) ?? 0;
410
+ if (R(t)) return 24;
411
+ if (I(t) || L(t) || be(t) || xe(t)) return 18;
412
+ let n = me.get(e);
413
+ return n === void 0 ? 16 : (n + 1) * 2;
414
+ }
415
+ function I(e) {
416
+ return e >= 13312 && e <= 19903 || e >= 19968 && e <= 40959 || e >= 63744 && e <= 64255;
417
+ }
418
+ function L(e) {
419
+ return e >= 12352 && e <= 12447;
420
+ }
421
+ function be(e) {
422
+ return e >= 12448 && e <= 12543;
423
+ }
424
+ function R(e) {
425
+ return e >= 44032 && e <= 55215;
426
+ }
427
+ function xe(e) {
428
+ return e >= 1024 && e <= 1279;
429
+ }
430
+ function z(e, t) {
431
+ return ve(e) <= t;
432
+ }
433
+ function B(e, t = {}) {
434
+ let n = typeof t == "number" ? t : t.charsPerLine, r = typeof t == "number" ? void 0 : t.maxWidthPx ?? N.displayWidthPx;
435
+ return n === void 0 ? Ce(e, r ?? N.displayWidthPx) : Se(e, n);
436
+ }
437
+ function Se(e, t) {
438
+ let n = [];
439
+ for (let r of e.split(/\r?\n/).map((e) => e.trim()).filter(Boolean)) {
440
+ let e = r;
441
+ for (; e.length > t;) {
442
+ let r = e.lastIndexOf(" ", t);
443
+ r < 1 && (r = t), n.push(e.slice(0, r).trimEnd()), e = e.slice(r).trimStart();
444
+ }
445
+ e && n.push(e);
446
+ }
447
+ return n.length ? n : [""];
448
+ }
449
+ function Ce(e, t) {
450
+ let n = [];
451
+ for (let r of e.split(/\r?\n/)) {
452
+ let e = r.trim();
453
+ if (!e) {
454
+ n.length > 0 && n.push("");
455
+ continue;
456
+ }
457
+ n.push(...we(e, t));
458
+ }
459
+ return n.length ? n : [""];
460
+ }
461
+ function we(e, t) {
462
+ if (z(e, t)) return [e];
463
+ let n = [], r = "";
464
+ for (let i of e.split(/\s+/).filter(Boolean)) {
465
+ let e = r ? `${r} ${i}` : i;
466
+ if (z(e, t)) {
467
+ r = e;
468
+ continue;
469
+ }
470
+ r &&= (n.push(r), "");
471
+ let a = Te(i, t);
472
+ n.push(...a.slice(0, -1)), r = a.at(-1) ?? "";
473
+ }
474
+ return r && n.push(r), n;
475
+ }
476
+ function Te(e, t) {
477
+ let n = [], r = "";
478
+ for (let i of Array.from(e)) {
479
+ let e = r + i;
480
+ if (z(e, t)) {
481
+ r = e;
482
+ continue;
483
+ }
484
+ r && n.push(r), r = i;
485
+ }
486
+ return r && n.push(r), n.length ? n : [""];
487
+ }
488
+ function Ee(e, t = {}) {
489
+ let n = t.charsPerLine ?? N.charsPerLine, r = t.linesPerPage ?? N.linesPerPage, i = B(e, t.charsPerLine === void 0 ? { maxWidthPx: N.displayWidthPx } : { charsPerLine: n }), a = Math.max(1, Math.ceil(i.length / r)), o = [];
490
+ for (let e = 0; e < a; e++) {
491
+ let t = i.slice(e * r, (e + 1) * r), n = r - t.length;
492
+ if (n > 0) {
493
+ let e = Math.floor(n / 2), r = n - e;
494
+ t.unshift(...Array.from({ length: e }, () => "")), t.push(...Array.from({ length: r }, () => ""));
495
+ }
496
+ o.push({
497
+ pageNumber: e + 1,
498
+ maxPages: a,
499
+ text: t.join("\n"),
500
+ screenStatus: e === a - 1 ? 64 : 49
501
+ });
502
+ }
503
+ return o;
504
+ }
505
+ function De(e, t = 0) {
506
+ let n = Oe(e.text, N.maxPayloadBytes), r = n.length, i = [], a = 0;
507
+ for (let [o, s] of n.entries()) i.push(ke(e, s, t, r, o, a)), a += s.length;
508
+ return i;
509
+ }
510
+ function Oe(e, t) {
511
+ let n = new TextEncoder();
512
+ if (e.length === 0) return [new Uint8Array()];
513
+ let r = [], i = "";
514
+ for (let a of e) {
515
+ let e = i + a, o = n.encode(e);
516
+ if (o.byteLength > t && i) {
517
+ r.push(n.encode(i)), i = a;
518
+ continue;
519
+ }
520
+ if (o.byteLength > t) throw RangeError(`Single UTF-8 character exceeds G1 display packet payload limit of ${t} bytes`);
521
+ i = e;
522
+ }
523
+ return (i || r.length === 0) && r.push(n.encode(i)), r;
524
+ }
525
+ function ke(e, t, n, r, i, a = 0) {
526
+ let o = new Uint8Array(9 + t.length);
527
+ return o.set([
528
+ 78,
529
+ n & 255,
530
+ r & 255,
531
+ i & 255,
532
+ e.screenStatus & 255,
533
+ a >>> 8 & 255,
534
+ a & 255,
535
+ e.pageNumber & 255,
536
+ e.maxPages & 255
537
+ ]), o.set(t, 9), o;
538
+ }
539
+ function V(e) {
540
+ return Uint8Array.from([14, +!!e]);
541
+ }
542
+ function Ae() {
543
+ return Uint8Array.from([44, 1]);
544
+ }
545
+ function je(e, t = "lens-specific") {
546
+ return Uint8Array.from([t === "android-f4" ? 244 : t === "official" || e === "left" ? 77 : 244, 1]);
547
+ }
548
+ function Me() {
549
+ return Uint8Array.from([52]);
550
+ }
551
+ function Ne() {
552
+ return Uint8Array.from([
553
+ 245,
554
+ 24,
555
+ 0,
556
+ 0,
557
+ 0
558
+ ]);
559
+ }
560
+ function Pe(e) {
561
+ return Uint8Array.from([
562
+ 3,
563
+ e ? 12 : 10,
564
+ 0
565
+ ]);
566
+ }
567
+ function Fe(e, t = !1) {
568
+ if (!Number.isInteger(e) || e < 0 || e > 41) throw RangeError("Brightness level must be an integer between 0 and 0x29");
569
+ return Uint8Array.from([
570
+ 1,
571
+ e & 255,
572
+ +!!t
573
+ ]);
574
+ }
575
+ function H(e, t) {
576
+ let n = t[0];
577
+ if (n === 245) {
578
+ let n = t[1], r = F(n);
579
+ return {
580
+ side: e,
581
+ raw: t,
582
+ type: "state",
583
+ code: n,
584
+ label: r?.label ?? `unknown_0x${n?.toString(16)}`,
585
+ stateCategory: r?.category,
586
+ stateName: r?.name
587
+ };
588
+ }
589
+ if (n === 14) {
590
+ let n = t.length >= 3 ? t[1] : void 0, r = t[t.length - 1], i = n === void 0 || n === 201, a = r === 1;
591
+ return {
592
+ side: e,
593
+ raw: t,
594
+ type: "mic-response",
595
+ micEnabled: i ? a : !a,
596
+ micRequested: a,
597
+ responseStatus: n,
598
+ responseOk: i,
599
+ code: r,
600
+ label: i && a ? "mic_enabled" : i ? "mic_disabled" : "mic_failed"
601
+ };
602
+ }
603
+ if (n === 241) return {
604
+ side: e,
605
+ raw: t,
606
+ type: "mic-data",
607
+ sequence: t[1],
608
+ audioData: t.slice(2),
609
+ audioEncoding: "lc3",
610
+ label: "mic_data"
611
+ };
612
+ if (n === 77 || n === 244) return {
613
+ side: e,
614
+ raw: t,
615
+ type: "init",
616
+ code: t[1],
617
+ label: n === 244 ? "right_init" : "init"
618
+ };
619
+ if (n === 78) return Ie(e, t);
620
+ if (n === 75) return W(e, t);
621
+ if (n === 33) return Le(e, t);
622
+ if (n === 30 && t.length >= 11 && t[4] === 2) {
623
+ let n = Re(t, 5), r = Re(t, 7), i = Math.max(0, (t[9] ?? 1) - 1);
624
+ return {
625
+ side: e,
626
+ raw: t,
627
+ type: "voice-note-audio",
628
+ syncId: t[3],
629
+ subcommand: t[4],
630
+ totalPackets: n,
631
+ currentPacket: r,
632
+ noteIndex: i,
633
+ sequence: r,
634
+ audioData: t.slice(10),
635
+ audioEncoding: "lc3",
636
+ label: "voice_note_audio"
637
+ };
638
+ }
639
+ if (n === 34) {
640
+ let n = t[1];
641
+ return {
642
+ side: e,
643
+ raw: t,
644
+ type: "dashboard",
645
+ code: n,
646
+ label: `dashboard_0x${n?.toString(16).padStart(2, "0")}`
647
+ };
648
+ }
649
+ if (n === 52) {
650
+ let n = new TextDecoder().decode(t.slice(2, 18)).replace(/\0+$/g, "");
651
+ return {
652
+ side: e,
653
+ raw: t,
654
+ type: "serial",
655
+ code: t[1],
656
+ responseStatus: t[1],
657
+ responseOk: t[1] === void 0 || t[1] === 201,
658
+ serialNumber: n,
659
+ label: "serial_number"
660
+ };
661
+ }
662
+ return n === 37 ? {
663
+ side: e,
664
+ raw: t,
665
+ type: "heartbeat",
666
+ label: "heartbeat"
667
+ } : n === 44 ? U(e, t) : n === 3 ? {
668
+ side: e,
669
+ raw: t,
670
+ type: "response",
671
+ code: t[1],
672
+ label: "response"
673
+ } : n === 4 ? {
674
+ side: e,
675
+ raw: t,
676
+ type: "error",
677
+ code: t[1],
678
+ label: `error_0x${t[1]?.toString(16).padStart(2, "0")}`
679
+ } : {
680
+ side: e,
681
+ raw: t,
682
+ type: "unknown",
683
+ code: n,
684
+ label: `unknown_0x${n?.toString(16)}`
685
+ };
686
+ }
687
+ function U(e, t) {
688
+ return t.length < 6 || t[1] !== 102 ? {
689
+ side: e,
690
+ raw: t,
691
+ type: "battery-status",
692
+ responseStatus: t[1],
693
+ responseOk: !1,
694
+ label: "battery_status_invalid"
695
+ } : {
696
+ side: e,
697
+ raw: t,
698
+ type: "battery-status",
699
+ responseStatus: t[1],
700
+ responseOk: !0,
701
+ batteryPercent: t[2],
702
+ batteryFlags: t[3],
703
+ batteryVoltageMv: ((t[5] ?? 0) << 8 | (t[4] ?? 0)) / 10,
704
+ label: "battery_status"
705
+ };
706
+ }
707
+ function Ie(e, t) {
708
+ if (t.length < 9) return {
709
+ side: e,
710
+ raw: t,
711
+ type: "display-result",
712
+ label: "display_result_invalid"
713
+ };
714
+ let n = t.slice(9);
715
+ return {
716
+ side: e,
717
+ raw: t,
718
+ type: "display-result",
719
+ displaySeq: t[1],
720
+ totalPackages: t[2],
721
+ currentPackage: t[3],
722
+ screenStatus: t[4],
723
+ charPosition: ze(t, 5),
724
+ pageNumber: t[7],
725
+ maxPages: t[8],
726
+ text: new TextDecoder().decode(n),
727
+ label: "display_result"
728
+ };
729
+ }
730
+ function W(e, t) {
731
+ if (t.length < 4) return {
732
+ side: e,
733
+ raw: t,
734
+ type: "notification",
735
+ label: "notification_invalid"
736
+ };
737
+ let n = t.slice(4);
738
+ return {
739
+ side: e,
740
+ raw: t,
741
+ type: "notification",
742
+ notificationId: t[1],
743
+ totalPackages: t[2],
744
+ currentPackage: t[3],
745
+ notificationChunk: n,
746
+ text: new TextDecoder().decode(n),
747
+ label: "notification"
748
+ };
749
+ }
750
+ function Le(e, t) {
751
+ let n = Re(t, 1), r = t[3], i = t[4];
752
+ if (t.length < 6 || i !== 1) return {
753
+ side: e,
754
+ raw: t,
755
+ type: "voice-note-list",
756
+ syncId: r,
757
+ subcommand: i,
758
+ voiceNotes: [],
759
+ label: "voice_note_list_invalid"
760
+ };
761
+ let a = t[5] ?? 0, o = 6 + a * 9, s = Math.min(t.length, Math.max(n, o)), c = [];
762
+ for (let e = 6; e + 8 < s && c.length < a; e += 9) c.push({
763
+ index: t[e],
764
+ timestamp: G(t, e + 1),
765
+ crc: G(t, e + 5)
766
+ });
767
+ return {
768
+ side: e,
769
+ raw: t,
770
+ type: "voice-note-list",
771
+ syncId: r,
772
+ subcommand: i,
773
+ voiceNotes: c,
774
+ label: "voice_note_list"
775
+ };
776
+ }
777
+ function Re(e, t) {
778
+ return (e[t] ?? 0) | (e[t + 1] ?? 0) << 8;
779
+ }
780
+ function ze(e, t) {
781
+ return (e[t] ?? 0) << 8 | (e[t + 1] ?? 0);
782
+ }
783
+ function G(e, t) {
784
+ return ((e[t] ?? 0) | (e[t + 1] ?? 0) << 8 | (e[t + 2] ?? 0) << 16 | (e[t + 3] ?? 0) << 24) >>> 0;
785
+ }
786
+ //#endregion
787
+ //#region src/ui/SmartglassesView.helpers.ts
788
+ function Be(e) {
789
+ return e === "single_tap" || e === "long_press";
790
+ }
791
+ function Ve(e) {
792
+ return e === "double_tap" || e === "stop_ai_recording";
793
+ }
794
+ function He(e) {
795
+ let t = Date.parse(e);
796
+ return Number.isFinite(t) ? t : null;
797
+ }
798
+ function Ue(e, t) {
799
+ let n = He(e.at), r = He(t.at);
800
+ return n !== null && r !== null ? n >= r : !1;
801
+ }
802
+ function We(e, t, n) {
803
+ let r = n === "enable" ? Be : Ve, i = n === "enable" ? "0e01" : "0e00", a = e.filter((e) => r(e.detail)), o = t.filter((e) => e.side === "right" && e.command === "open-mic" && e.hex.startsWith(i));
804
+ return a.some((e) => o.some((t) => Ue(t, e)));
805
+ }
806
+ function K(e, t) {
807
+ return e === "cradle_open" || e === "cradle_closed" || e === "charged_in_cradle" || t === "glasses_fully_charged" || t === "cradle_charging_cable_changed" || t === "cradle_fully_charged";
808
+ }
809
+ function Ge(e, t) {
810
+ if (e === "wearing") return null;
811
+ let n = [e, t].filter(Boolean).join(" / ") || "no wearing state observed";
812
+ return K(e, t) ? `Glasses are still reporting ${n}. Remove them from the charging base and wear them before tap or microphone validation.` : `Tap and microphone validation requires a wearing state; current state is ${n}.`;
813
+ }
814
+ function Ke(e, t, n, r, i = [], a = []) {
815
+ let o = We(i, a, "enable"), s = We(i, a, "disable"), c = [
816
+ t.left !== "connected" && "leftLensConnected",
817
+ t.right !== "connected" && "rightLensConnected",
818
+ n !== "wearing" && "wearingStateObserved",
819
+ K(n, r) && "headsetInCradle",
820
+ !e.init && "connectionReadySent",
821
+ !e.display && "displayPacketsSent",
822
+ !e.serial && "serialRequested",
823
+ !e.serialObserved && "serialObserved",
824
+ !e.settings && "settingsSent",
825
+ !o && "rightMicEnableWrite",
826
+ !s && "rightMicDisableWrite",
827
+ !e.tapMicEnable && "tapMicEnable",
828
+ !e.tapMicDisable && "tapMicDisable",
829
+ !e.audio && "rightOrBridgeAudio"
830
+ ].filter((e) => typeof e == "string");
831
+ return [...new Set(c)];
832
+ }
833
+ function qe(e) {
834
+ return e.left === "connected" && e.right === "connected" ? "whole_headset_seen" : e.left === "failed" || e.right === "failed" ? "pairing_failed" : e.left === "connected" ? "right_lens_missing" : e.right === "connected" ? "left_lens_missing" : "not_scanned";
835
+ }
836
+ function Je(e, t, n, r, i = [], a = []) {
837
+ let o = t.left === "connected" && t.right === "connected";
838
+ return !o && (t.left === "connected" || t.right === "connected") ? "partial_headset" : o ? K(n, r) ? "in_charging_base" : n === "wearing" ? Ke(e, t, n, r, i, a).length ? "evidence_missing" : null : "wearing_state_missing" : "not_connected";
839
+ }
840
+ function Ye(e, t, n) {
841
+ return e === "not_connected" ? "Connect both left and right lenses as one headset before running validation." : e === "partial_headset" ? "Reconnect the whole headset so both left and right lenses are present." : e === "in_charging_base" || e === "wearing_state_missing" ? Ge(t, n) : e === "evidence_missing" ? "Run check, then guided validation to capture display, settings, side taps, mic writes, and audio." : null;
842
+ }
843
+ function Xe(e) {
844
+ return e === "not_connected" ? "Connect Headset" : e === "partial_headset" ? "Reconnect the missing lens" : e === "in_charging_base" ? "Remove the glasses from the charging base and wear them" : e === "wearing_state_missing" ? "Wear the glasses until wearing state appears" : e === "evidence_missing" ? "Run Check and Guided Validation" : null;
845
+ }
846
+ function Ze(e) {
847
+ switch (e[0]) {
848
+ case 1: return "brightness";
849
+ case 14: return "open-mic";
850
+ case 28: return "silent-mode";
851
+ case 44: return "battery-status";
852
+ case 52: return "get-serial";
853
+ case 77: return "init";
854
+ case 78: return "display-result";
855
+ case 244: return "right-init";
856
+ default: return e.length > 0 ? `0x${e[0].toString(16).padStart(2, "0")}` : "empty";
857
+ }
858
+ }
859
+ function Qe(e, t) {
860
+ return {
861
+ ...e,
862
+ screenStatus: t
863
+ };
864
+ }
865
+ function $e(e, t) {
866
+ return e === "text" ? j.TextShow | A.NewContent : t === 0 ? pe.Displaying | A.NewContent : pe.Displaying;
867
+ }
868
+ function et(e, t = {}) {
869
+ let n = t.mode ?? "ai", r = t.startSeq ?? 0, i = [], a = Ee(e);
870
+ for (let [e, t] of a.entries()) i.push(...De(Qe(t, $e(n, e)), r)), r = r + 1 & 255;
871
+ if (n !== "text" && t.includeCompletion !== !1) {
872
+ let e = a.at(-1);
873
+ e && (i.push(...De(Qe(e, pe.DisplayComplete), r)), r = r + 1 & 255);
874
+ }
875
+ return {
876
+ packets: i,
877
+ pages: a.length,
878
+ nextSeq: r
879
+ };
880
+ }
881
+ function tt(e) {
882
+ if (!e || typeof e != "object") return [];
883
+ let t = e, n = t.networks ?? t.wifiNetworks ?? t.accessPoints ?? t.networks_neo ?? t.results;
884
+ return Array.isArray(n) ? n.map((e) => {
885
+ if (typeof e == "string") return e;
886
+ if (e && typeof e == "object") {
887
+ let t = e;
888
+ return String(t.ssid ?? t.SSID ?? t.name ?? "");
889
+ }
890
+ return "";
891
+ }).map((e) => e.trim()).filter((e) => e.length > 0) : [];
892
+ }
893
+ function nt(e, t = "Wi-Fi status requested") {
894
+ if (!e || typeof e != "object") return t;
895
+ let n = e, r = n.status ?? n.state ?? n.message;
896
+ if (typeof r == "string" && r.trim()) return r.trim();
897
+ let i = n.connected ?? n.wifiConnected, a = n.ssid ?? n.wifiSsid ?? n.SSID, o = n.localIp ?? n.wifiLocalIp ?? n.ipAddress;
898
+ return i === !0 ? `Connected to ${String(a ?? "Wi-Fi")}${o ? ` at ${String(o)}` : ""}` : i === !1 ? "Wi-Fi disconnected" : t;
899
+ }
900
+ async function q(e, t, n) {
901
+ if (t === "request_wifi_scan" && e.requestWifiScan) return e.requestWifiScan();
902
+ if (t === "request_wifi_status" && e.requestWifiStatus) return e.requestWifiStatus();
903
+ if (t === "request_wifi_setup" && e.requestWifiSetup) return e.requestWifiSetup(String(n?.reason ?? ""));
904
+ if (t === "set_wifi_credentials") {
905
+ let t = String(n?.ssid ?? ""), r = String(n?.password ?? "");
906
+ if (e.setWifiCredentials) return e.setWifiCredentials(t, r);
907
+ if (e.sendWifiCredentials) return e.sendWifiCredentials(t, r);
908
+ }
909
+ if (e.rawBridge?.callEvenApp) return e.rawBridge.callEvenApp(t, n);
910
+ throw Error(`Native smartglasses bridge does not support Wi-Fi command: ${t}`);
911
+ }
912
+ //#endregion
913
+ //#region src/components/SmartglassesSpatialView.tsx
914
+ var rt = 8, it = 12, at = 5;
915
+ function ot(e) {
916
+ switch (e) {
917
+ case "connected": return "success";
918
+ case "failed": return "danger";
919
+ case "prompting": return "warning";
920
+ default: return "muted";
921
+ }
922
+ }
923
+ function st(e) {
924
+ switch (e) {
925
+ case "connected": return "[ok]";
926
+ case "failed": return "[x]";
927
+ case "prompting": return "[..]";
928
+ default: return "[ ]";
929
+ }
930
+ }
931
+ function ct(e) {
932
+ return e ? "success" : "muted";
933
+ }
934
+ function lt(e) {
935
+ return e ? "[ok]" : "[ ]";
936
+ }
937
+ function ut(e) {
938
+ let t = [];
939
+ return typeof e.left == "number" && t.push(`L ${e.left}%`), typeof e.right == "number" && t.push(`R ${e.right}%`), t.length > 0 ? t.join(" ") : null;
940
+ }
941
+ function dt({ snapshot: o, onAction: c }) {
942
+ let l = (e) => () => c?.(e), { report: u } = o, d = Object.entries(u.tests), f = Math.max(0, d.length - rt), p = Math.max(0, u.events.length - it), m = Math.max(0, u.wifi.networks.length - at), _ = ut(u.headsetState.batteryLevels), v = Math.max(0, u.events.length - it), ee = u.events.slice(v).map((e, t) => ({
943
+ ...e,
944
+ key: v + t
945
+ })).reverse();
946
+ return /* @__PURE__ */ g(t, {
947
+ gap: 1,
948
+ padding: 1,
949
+ children: [
950
+ /* @__PURE__ */ g(i, {
951
+ gap: 1,
952
+ align: "center",
953
+ children: [/* @__PURE__ */ h(s, {
954
+ style: "caption",
955
+ tone: u.ok ? "success" : u.connected ? "warning" : "danger",
956
+ grow: 1,
957
+ children: u.ok ? "validated" : u.connected ? "connected" : "disconnected"
958
+ }), /* @__PURE__ */ h(s, {
959
+ style: "caption",
960
+ tone: "muted",
961
+ children: o.busy ? o.busy : u.transport ?? "no transport"
962
+ })]
963
+ }),
964
+ o.error ? /* @__PURE__ */ h(s, {
965
+ tone: "danger",
966
+ style: "caption",
967
+ children: o.error
968
+ }) : null,
969
+ /* @__PURE__ */ g(i, {
970
+ gap: 1,
971
+ align: "center",
972
+ children: [/* @__PURE__ */ g(s, {
973
+ style: "caption",
974
+ tone: ot(u.lenses.left),
975
+ grow: 1,
976
+ children: [st(u.lenses.left), " left"]
977
+ }), /* @__PURE__ */ g(s, {
978
+ style: "caption",
979
+ tone: ot(u.lenses.right),
980
+ grow: 1,
981
+ children: [st(u.lenses.right), " right"]
982
+ })]
983
+ }),
984
+ /* @__PURE__ */ g(i, {
985
+ gap: 1,
986
+ align: "center",
987
+ children: [/* @__PURE__ */ h(s, {
988
+ style: "caption",
989
+ tone: "muted",
990
+ grow: 1,
991
+ children: u.serialNumber ? `sn ${u.serialNumber}` : "sn unknown"
992
+ }), _ ? /* @__PURE__ */ h(s, {
993
+ style: "caption",
994
+ tone: "muted",
995
+ children: _
996
+ }) : null]
997
+ }),
998
+ u.setupHint ? /* @__PURE__ */ h(s, {
999
+ style: "caption",
1000
+ tone: "warning",
1001
+ children: u.setupHint
1002
+ }) : null,
1003
+ /* @__PURE__ */ h(n, { label: "diagnostics" }),
1004
+ /* @__PURE__ */ h(a, {
1005
+ gap: 0,
1006
+ children: d.slice(0, rt).map(([e, t]) => /* @__PURE__ */ g(i, {
1007
+ gap: 1,
1008
+ align: "center",
1009
+ agent: `test-${e}`,
1010
+ children: [/* @__PURE__ */ h(s, {
1011
+ tone: ct(t),
1012
+ children: lt(t)
1013
+ }), /* @__PURE__ */ h(s, {
1014
+ style: "caption",
1015
+ grow: 1,
1016
+ wrap: !1,
1017
+ children: e
1018
+ })]
1019
+ }, e))
1020
+ }),
1021
+ f > 0 ? /* @__PURE__ */ g(s, {
1022
+ style: "caption",
1023
+ tone: "muted",
1024
+ children: [
1025
+ "+",
1026
+ f,
1027
+ " checks"
1028
+ ]
1029
+ }) : null,
1030
+ /* @__PURE__ */ h(n, { label: "controls" }),
1031
+ /* @__PURE__ */ g(i, {
1032
+ gap: 1,
1033
+ wrap: !0,
1034
+ children: [
1035
+ /* @__PURE__ */ h(e, {
1036
+ grow: 1,
1037
+ tone: u.connected ? "default" : "primary",
1038
+ variant: u.connected ? "outline" : "solid",
1039
+ agent: "connect",
1040
+ onPress: l("connect"),
1041
+ children: u.connected ? "Reconnect" : "Connect"
1042
+ }),
1043
+ /* @__PURE__ */ h(e, {
1044
+ variant: "outline",
1045
+ tone: "default",
1046
+ grow: 1,
1047
+ agent: "run-check",
1048
+ onPress: l("run-check"),
1049
+ children: "Run Check"
1050
+ }),
1051
+ /* @__PURE__ */ h(e, {
1052
+ variant: o.micEnabled ? "solid" : "outline",
1053
+ tone: o.micEnabled ? "success" : "default",
1054
+ agent: "mic-toggle",
1055
+ onPress: l("mic-toggle"),
1056
+ children: o.micEnabled ? "Mic on" : "Mic off"
1057
+ })
1058
+ ]
1059
+ }),
1060
+ /* @__PURE__ */ h(r, {
1061
+ label: "Display text",
1062
+ value: o.testText,
1063
+ placeholder: "Text to send to both lenses",
1064
+ agent: "test-text"
1065
+ }),
1066
+ /* @__PURE__ */ g(i, {
1067
+ gap: 1,
1068
+ wrap: !0,
1069
+ children: [/* @__PURE__ */ h(e, {
1070
+ grow: 1,
1071
+ agent: "display-test",
1072
+ onPress: l("display-test"),
1073
+ children: "Send Display"
1074
+ }), /* @__PURE__ */ h(e, {
1075
+ variant: "ghost",
1076
+ tone: "danger",
1077
+ agent: "clear-display",
1078
+ onPress: l("clear-display"),
1079
+ children: "Clear"
1080
+ })]
1081
+ }),
1082
+ /* @__PURE__ */ h(n, { label: "wi-fi" }),
1083
+ /* @__PURE__ */ g(i, {
1084
+ gap: 1,
1085
+ align: "center",
1086
+ children: [/* @__PURE__ */ h(s, {
1087
+ style: "caption",
1088
+ tone: "muted",
1089
+ grow: 1,
1090
+ wrap: !1,
1091
+ children: u.wifi.status
1092
+ }), /* @__PURE__ */ h(s, {
1093
+ style: "caption",
1094
+ tone: u.wifi.available ? "muted" : "danger",
1095
+ children: u.wifi.available ? "bridge" : "no bridge"
1096
+ })]
1097
+ }),
1098
+ /* @__PURE__ */ h(r, {
1099
+ label: "SSID",
1100
+ value: o.wifiSsid,
1101
+ placeholder: "Network name",
1102
+ agent: "wifi-ssid"
1103
+ }),
1104
+ /* @__PURE__ */ h(r, {
1105
+ label: "Password",
1106
+ kind: "password",
1107
+ value: o.wifiPassword,
1108
+ placeholder: "Network password",
1109
+ agent: "wifi-password"
1110
+ }),
1111
+ /* @__PURE__ */ g(i, {
1112
+ gap: 1,
1113
+ wrap: !0,
1114
+ children: [
1115
+ /* @__PURE__ */ h(e, {
1116
+ variant: "outline",
1117
+ tone: "default",
1118
+ grow: 1,
1119
+ agent: "wifi-scan",
1120
+ onPress: l("wifi-scan"),
1121
+ children: "Scan"
1122
+ }),
1123
+ /* @__PURE__ */ h(e, {
1124
+ variant: "outline",
1125
+ tone: "default",
1126
+ grow: 1,
1127
+ agent: "wifi-status",
1128
+ onPress: l("wifi-status"),
1129
+ children: "Status"
1130
+ }),
1131
+ /* @__PURE__ */ h(e, {
1132
+ grow: 1,
1133
+ agent: "wifi-save",
1134
+ onPress: l("wifi-save"),
1135
+ children: "Save Wi-Fi"
1136
+ })
1137
+ ]
1138
+ }),
1139
+ u.wifi.networks.length === 0 ? /* @__PURE__ */ h(s, {
1140
+ style: "caption",
1141
+ tone: "muted",
1142
+ children: "None"
1143
+ }) : /* @__PURE__ */ h(a, {
1144
+ gap: 0,
1145
+ children: u.wifi.networks.slice(0, at).map((e) => /* @__PURE__ */ h(s, {
1146
+ style: "caption",
1147
+ wrap: !1,
1148
+ children: e
1149
+ }, e))
1150
+ }),
1151
+ m > 0 ? /* @__PURE__ */ g(s, {
1152
+ style: "caption",
1153
+ tone: "muted",
1154
+ children: [
1155
+ "+",
1156
+ m,
1157
+ " more"
1158
+ ]
1159
+ }) : null,
1160
+ /* @__PURE__ */ h(n, { label: "events" }),
1161
+ u.events.length === 0 ? /* @__PURE__ */ h(s, {
1162
+ style: "caption",
1163
+ tone: "muted",
1164
+ align: "center",
1165
+ children: "None"
1166
+ }) : /* @__PURE__ */ h(a, {
1167
+ gap: 0,
1168
+ children: ee.map((e) => /* @__PURE__ */ g(i, {
1169
+ gap: 1,
1170
+ align: "center",
1171
+ children: [/* @__PURE__ */ h(s, {
1172
+ style: "caption",
1173
+ tone: "primary",
1174
+ wrap: !1,
1175
+ children: e.type
1176
+ }), /* @__PURE__ */ h(s, {
1177
+ style: "caption",
1178
+ tone: "muted",
1179
+ grow: 1,
1180
+ wrap: !1,
1181
+ children: e.detail
1182
+ })]
1183
+ }, e.key))
1184
+ }),
1185
+ p > 0 ? /* @__PURE__ */ g(s, {
1186
+ style: "caption",
1187
+ tone: "muted",
1188
+ children: [
1189
+ "+",
1190
+ p,
1191
+ " older events"
1192
+ ]
1193
+ }) : null
1194
+ ]
1195
+ });
1196
+ }
1197
+ //#endregion
1198
+ //#region src/components/SmartglassesPanelView.tsx
1199
+ var ft = {
1200
+ ok: !1,
1201
+ generatedAt: "",
1202
+ transport: null,
1203
+ connected: !1,
1204
+ lenses: {
1205
+ left: "idle",
1206
+ right: "idle"
1207
+ },
1208
+ scanDiagnosis: "not_scanned",
1209
+ physicalBlocker: "not_connected",
1210
+ setupHint: "Connect both left and right lenses as one headset before running validation.",
1211
+ nextAction: "Connect Headset",
1212
+ serialNumber: null,
1213
+ tests: {},
1214
+ missingEvidence: [],
1215
+ events: [],
1216
+ writes: [],
1217
+ audio: [],
1218
+ wifi: {
1219
+ available: !1,
1220
+ status: "Not checked",
1221
+ networks: []
1222
+ },
1223
+ headsetState: {
1224
+ physical: null,
1225
+ battery: null,
1226
+ batteryLevels: {},
1227
+ device: null
1228
+ }
1229
+ };
1230
+ function pt() {
1231
+ return typeof window > "u" ? null : window.__mentraBridge ?? window.__evenBridge ?? null;
1232
+ }
1233
+ function mt() {
1234
+ return typeof window > "u" ? ft : window.facewearSmartglassesReport ?? ft;
1235
+ }
1236
+ function ht() {
1237
+ let [e, t] = p(mt), [n, r] = p(!1), [i, a] = p("desktop"), [s, c] = p(null), [d, m] = p(null), g = e.wifi.networks[0] ?? "", _ = f(!1);
1238
+ u(() => {
1239
+ let e = () => t(mt());
1240
+ _.current || (_.current = !0, e());
1241
+ let n = setInterval(e, 5e3);
1242
+ return () => clearInterval(n);
1243
+ }, []);
1244
+ let v = l(async (e, n, r) => {
1245
+ let i = pt();
1246
+ if (!i) {
1247
+ m("Unavailable");
1248
+ return;
1249
+ }
1250
+ c(e), m(null);
1251
+ try {
1252
+ let e = await q(i, n, r), a = tt(e);
1253
+ t((t) => ({
1254
+ ...t,
1255
+ wifi: {
1256
+ available: !0,
1257
+ status: nt(e, t.wifi.status),
1258
+ networks: a.length > 0 ? a : t.wifi.networks
1259
+ }
1260
+ }));
1261
+ } catch (e) {
1262
+ m(e instanceof Error ? e.message : String(e));
1263
+ } finally {
1264
+ c(null);
1265
+ }
1266
+ }, []), ee = l((e) => {
1267
+ if (e.startsWith("platform:")) {
1268
+ a(e.slice(9));
1269
+ return;
1270
+ }
1271
+ switch (e) {
1272
+ case "mic-toggle":
1273
+ r((e) => !e);
1274
+ return;
1275
+ case "wifi-scan":
1276
+ v("wifi-scan", "request_wifi_scan");
1277
+ return;
1278
+ case "wifi-status":
1279
+ v("wifi-status", "request_wifi_status");
1280
+ return;
1281
+ case "wifi-save":
1282
+ v("wifi-save", "set_wifi_credentials", {
1283
+ ssid: g.trim(),
1284
+ password: ""
1285
+ });
1286
+ return;
1287
+ case "connect":
1288
+ case "run-check":
1289
+ case "display-test":
1290
+ case "clear-display":
1291
+ m("Open Smartglasses.");
1292
+ return;
1293
+ }
1294
+ }, [v, g]);
1295
+ return /* @__PURE__ */ h(o, { children: /* @__PURE__ */ h(dt, {
1296
+ snapshot: {
1297
+ report: e,
1298
+ micEnabled: n,
1299
+ wifiSsid: g,
1300
+ wifiPassword: "",
1301
+ testText: "Smartglasses display test.",
1302
+ activePlatform: i,
1303
+ busy: s,
1304
+ error: d
1305
+ },
1306
+ onAction: ee
1307
+ }) });
1308
+ }
1309
+ //#endregion
1310
+ //#region src/ui/FacewearAppView.tsx
1311
+ var gt = 4;
1312
+ function _t({ connectionType: e }) {
1313
+ return e.toLowerCase().includes("bluetooth") ? /* @__PURE__ */ h(te, { className: "h-4 w-4" }) : e.toLowerCase().includes("wifi") ? /* @__PURE__ */ h(le, { className: "h-4 w-4" }) : /* @__PURE__ */ h(b, { className: "h-4 w-4" });
1314
+ }
1315
+ function vt({ profile: e, connectedDevices: t, onConnect: n }) {
1316
+ let r = w(e, t), i = e.connectionType.toLowerCase().includes("bluetooth") ? te : ae, a = r ? `Manage ${e.name}` : `Connect ${e.name}`, { ref: o, agentProps: s } = v({
1317
+ id: `device-${e.type}`,
1318
+ role: "button",
1319
+ label: a,
1320
+ group: "devices",
1321
+ status: r ? "active" : "inactive",
1322
+ description: `${r ? "Manage" : "Connect"} the ${e.name} device`
1323
+ });
1324
+ return /* @__PURE__ */ g("div", {
1325
+ className: "py-3 transition-colors",
1326
+ children: [/* @__PURE__ */ g("div", {
1327
+ className: "flex items-start justify-between gap-3",
1328
+ children: [/* @__PURE__ */ g("div", {
1329
+ className: "flex items-center gap-3 min-w-0",
1330
+ children: [/* @__PURE__ */ h("div", {
1331
+ className: "flex h-10 w-10 flex-shrink-0 items-center justify-center",
1332
+ children: /* @__PURE__ */ h(i, { className: `h-5 w-5 ${r ? "text-green-500" : "text-muted"}` })
1333
+ }), /* @__PURE__ */ g("div", {
1334
+ className: "min-w-0",
1335
+ children: [/* @__PURE__ */ h("p", {
1336
+ className: "truncate text-sm font-semibold text-txt",
1337
+ children: e.name
1338
+ }), /* @__PURE__ */ h("p", {
1339
+ className: "text-xs text-muted",
1340
+ children: e.manufacturer
1341
+ })]
1342
+ })]
1343
+ }), /* @__PURE__ */ h("span", {
1344
+ className: `flex-shrink-0 inline-flex items-center gap-1 px-1.5 py-0.5 text-xs font-medium ${r ? "text-green-600 dark:text-green-400" : "text-muted"}`,
1345
+ children: r ? "On" : "Off"
1346
+ })]
1347
+ }), /* @__PURE__ */ g("div", {
1348
+ className: "mt-2 flex items-center justify-between gap-2",
1349
+ children: [/* @__PURE__ */ g("span", {
1350
+ className: "inline-flex items-center gap-1.5 text-xs text-muted",
1351
+ children: [/* @__PURE__ */ h(_t, { connectionType: e.connectionType }), e.connectionType]
1352
+ }), /* @__PURE__ */ h("button", {
1353
+ ref: o,
1354
+ type: "button",
1355
+ onClick: () => n(e.type),
1356
+ "aria-label": a,
1357
+ className: "inline-flex h-8 items-center gap-1.5 px-3 text-xs font-medium hover:bg-muted/20 transition-colors",
1358
+ ...s,
1359
+ children: r ? "Manage" : "Connect"
1360
+ })]
1361
+ })]
1362
+ });
1363
+ }
1364
+ function yt() {
1365
+ let [e, t] = p({
1366
+ connected: !1,
1367
+ devices: []
1368
+ }), [n, r] = p(!0), [i, a] = p(null), o = l(async () => {
1369
+ try {
1370
+ let e = await fetch("/api/facewear/status");
1371
+ e.ok && (t(await e.json()), a(null));
1372
+ } catch (e) {
1373
+ a(e instanceof Error ? e.message : String(e));
1374
+ } finally {
1375
+ r(!1);
1376
+ }
1377
+ }, []);
1378
+ u(() => {
1379
+ o();
1380
+ let e = setInterval(() => void o(), 5e3);
1381
+ return () => clearInterval(e);
1382
+ }, [o]);
1383
+ function s(e) {
1384
+ if (e === "even-realities") {
1385
+ window.location.assign("/apps/smartglasses");
1386
+ return;
1387
+ }
1388
+ window.open("/api/xr/connect", "_blank", "noopener,noreferrer");
1389
+ }
1390
+ let c = e.devices.length, { ref: d, agentProps: f } = v({
1391
+ id: "link-xr-connect",
1392
+ role: "link",
1393
+ label: "Connect",
1394
+ group: "quick-actions",
1395
+ description: "Open the XR device connect page in a new tab"
1396
+ }), { ref: _, agentProps: ee } = v({
1397
+ id: "link-xr-status",
1398
+ role: "link",
1399
+ label: "Status",
1400
+ group: "quick-actions",
1401
+ description: "Open the XR status API in a new tab"
1402
+ }), { ref: te, agentProps: y } = v({
1403
+ id: "action-refresh",
1404
+ role: "button",
1405
+ label: "Refresh",
1406
+ group: "quick-actions",
1407
+ description: "Refresh the connected device status"
1408
+ });
1409
+ return /* @__PURE__ */ g("div", {
1410
+ className: "flex min-h-0 flex-1 flex-col overflow-y-auto bg-bg text-txt",
1411
+ children: [/* @__PURE__ */ h("div", {
1412
+ className: "px-4 py-3",
1413
+ children: /* @__PURE__ */ g("div", {
1414
+ className: "flex flex-wrap items-center justify-between gap-3",
1415
+ children: [/* @__PURE__ */ h("div", { children: /* @__PURE__ */ g("div", {
1416
+ className: "flex items-center gap-2",
1417
+ children: [/* @__PURE__ */ h(ae, { className: "h-4 w-4 text-accent" }), /* @__PURE__ */ h("h1", {
1418
+ className: "text-sm font-semibold",
1419
+ children: "Facewear"
1420
+ })]
1421
+ }) }), /* @__PURE__ */ g("span", {
1422
+ className: `inline-flex h-7 items-center gap-1.5 px-1.5 text-xs font-medium ${c > 0 ? "text-green-700 dark:text-green-300" : "text-muted"}`,
1423
+ children: [/* @__PURE__ */ h(b, { className: "h-3.5 w-3.5" }), c > 0 ? `${c} on` : "0 on"]
1424
+ })]
1425
+ })
1426
+ }), /* @__PURE__ */ g("div", {
1427
+ className: "mx-auto w-full max-w-3xl p-4",
1428
+ children: [
1429
+ n && /* @__PURE__ */ h("div", {
1430
+ className: "flex items-center justify-center py-8",
1431
+ children: /* @__PURE__ */ h("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-border border-t-accent" })
1432
+ }),
1433
+ i && /* @__PURE__ */ h("div", {
1434
+ className: "mb-4 px-1 py-2 text-xs text-destructive",
1435
+ children: i
1436
+ }),
1437
+ !n && /* @__PURE__ */ g(m, { children: [
1438
+ c > 0 && /* @__PURE__ */ h("div", {
1439
+ className: "mb-3",
1440
+ children: /* @__PURE__ */ g("div", {
1441
+ className: "flex flex-wrap gap-2",
1442
+ children: [e.devices.slice(0, gt).map((e) => /* @__PURE__ */ h("span", {
1443
+ className: "inline-flex items-center gap-1 px-1.5 py-0.5 text-xs text-green-700 dark:text-green-300",
1444
+ children: e.deviceType ?? e.kind
1445
+ }, e.id)), e.devices.length > gt ? /* @__PURE__ */ g("span", {
1446
+ className: "inline-flex items-center px-1.5 py-0.5 text-xs text-muted",
1447
+ children: ["+", e.devices.length - gt]
1448
+ }) : null]
1449
+ })
1450
+ }),
1451
+ /* @__PURE__ */ h("div", {
1452
+ className: "grid gap-3",
1453
+ children: C.map((t) => /* @__PURE__ */ h(vt, {
1454
+ profile: t,
1455
+ connectedDevices: e.devices,
1456
+ onConnect: s
1457
+ }, t.type))
1458
+ }),
1459
+ /* @__PURE__ */ h("div", {
1460
+ className: "mt-4",
1461
+ children: /* @__PURE__ */ g("div", {
1462
+ className: "flex flex-wrap gap-2",
1463
+ children: [
1464
+ /* @__PURE__ */ g("a", {
1465
+ ref: d,
1466
+ href: "/api/xr/connect",
1467
+ target: "_blank",
1468
+ rel: "noreferrer",
1469
+ "aria-label": "XR connect",
1470
+ className: "inline-flex h-8 items-center gap-1.5 px-3 text-xs font-medium hover:bg-muted/20 transition-colors",
1471
+ ...f,
1472
+ children: [/* @__PURE__ */ h(b, { className: "h-3.5 w-3.5" }), "Connect"]
1473
+ }),
1474
+ /* @__PURE__ */ h("a", {
1475
+ ref: _,
1476
+ href: "/api/xr/status",
1477
+ target: "_blank",
1478
+ rel: "noreferrer",
1479
+ "aria-label": "XR status",
1480
+ className: "inline-flex h-8 items-center gap-1.5 px-3 text-xs font-medium hover:bg-muted/20 transition-colors",
1481
+ ...ee,
1482
+ children: "Status"
1483
+ }),
1484
+ /* @__PURE__ */ h("button", {
1485
+ ref: te,
1486
+ type: "button",
1487
+ onClick: () => void o(),
1488
+ "aria-label": "Refresh",
1489
+ className: "inline-flex h-8 items-center gap-1.5 px-3 text-xs font-medium hover:bg-muted/20 transition-colors",
1490
+ ...y,
1491
+ children: "Refresh"
1492
+ })
1493
+ ]
1494
+ })
1495
+ })
1496
+ ] })
1497
+ ]
1498
+ })]
1499
+ });
1500
+ }
1501
+ function bt() {
1502
+ return /* @__PURE__ */ h(_, {
1503
+ id: "facewear",
1504
+ label: "Facewear TUI",
1505
+ description: "Status",
1506
+ commands: [],
1507
+ endpoints: [
1508
+ "/api/facewear/status",
1509
+ "/api/facewear/devices",
1510
+ "/api/facewear/views"
1511
+ ]
1512
+ });
1513
+ }
1514
+ function xt() {
1515
+ return /* @__PURE__ */ h(_, {
1516
+ id: "smartglasses",
1517
+ label: "Smartglasses TUI",
1518
+ description: "Status",
1519
+ commands: [],
1520
+ endpoints: ["/api/facewear/status", "/api/facewear/devices"]
1521
+ });
1522
+ }
1523
+ //#endregion
1524
+ //#region src/transport/even-bridge.ts
1525
+ function St(e) {
1526
+ return e instanceof Uint8Array ? e : e instanceof ArrayBuffer ? new Uint8Array(e) : ArrayBuffer.isView(e) ? new Uint8Array(e.buffer, e.byteOffset, e.byteLength) : Array.isArray(e) && e.every((e) => Number.isInteger(e)) ? Uint8Array.from(e) : typeof e == "string" && /^[0-9a-f]+$/i.test(e) && e.length % 2 == 0 ? Uint8Array.from(e.match(/../g)?.map((e) => Number.parseInt(e, 16)) ?? []) : null;
1527
+ }
1528
+ var Ct = class {
1529
+ bridge;
1530
+ name = "even-bridge";
1531
+ connected = !1;
1532
+ eventCallbacks = /* @__PURE__ */ new Set();
1533
+ audioCallbacks = /* @__PURE__ */ new Set();
1534
+ transcriptCallbacks = /* @__PURE__ */ new Set();
1535
+ wifiCallbacks = /* @__PURE__ */ new Set();
1536
+ bridgeDisposer = null;
1537
+ displayChunks = /* @__PURE__ */ new Map();
1538
+ evenHubStartupCreated = !1;
1539
+ constructor(e) {
1540
+ this.bridge = e;
1541
+ }
1542
+ async connect() {
1543
+ this.connected = !0;
1544
+ let e = this.bridge.onEvenHubEvent ?? this.bridge.onEvent;
1545
+ if (e) {
1546
+ let t = e.call(this.bridge, (e) => this.handleBridgeEvent(e));
1547
+ this.bridgeDisposer = Mt(t);
1548
+ }
1549
+ }
1550
+ async disconnect() {
1551
+ await this.openMicrophone(!1), this.bridgeDisposer?.(), this.bridgeDisposer = null, this.connected = !1;
1552
+ }
1553
+ isConnected() {
1554
+ return this.connected;
1555
+ }
1556
+ getConnectedLenses() {
1557
+ return this.connected ? {
1558
+ left: {
1559
+ connected: !0,
1560
+ name: "Native bridge left lens"
1561
+ },
1562
+ right: {
1563
+ connected: !0,
1564
+ name: "Native bridge right lens"
1565
+ }
1566
+ } : {};
1567
+ }
1568
+ async write(e, t) {
1569
+ if (this.supportsEvenHubDisplay() && t[0] === k.SendResult) {
1570
+ e === "left" && await this.writeEvenHubDisplay(t);
1571
+ return;
1572
+ }
1573
+ if (this.supportsMentraDisplay() && t[0] === k.SendResult) {
1574
+ e === "left" && await this.writeMentraDisplay(t);
1575
+ return;
1576
+ }
1577
+ if (this.bridge.clearDisplay && t[0] === k.StartAi && t[1] === fe.Stop) {
1578
+ await this.bridge.clearDisplay();
1579
+ return;
1580
+ }
1581
+ if (this.bridge.write) {
1582
+ await this.bridge.write(e, t);
1583
+ return;
1584
+ }
1585
+ if (this.bridge.send) {
1586
+ await this.bridge.send(e, t);
1587
+ return;
1588
+ }
1589
+ await this.bridge.rawBridge?.callEvenApp?.("sendData", {
1590
+ side: e,
1591
+ data: Array.from(t)
1592
+ });
1593
+ }
1594
+ async writeBoth(e) {
1595
+ await this.write("left", e), await this.write("right", e);
1596
+ }
1597
+ async openMicrophone(e) {
1598
+ if (this.bridge.setMicState) {
1599
+ await this.bridge.setMicState(e, e, e);
1600
+ return;
1601
+ }
1602
+ if (this.bridge.audioControl) {
1603
+ await this.bridge.audioControl(e);
1604
+ return;
1605
+ }
1606
+ if (this.bridge.rawBridge?.audioControl) {
1607
+ await this.bridge.rawBridge.audioControl(e);
1608
+ return;
1609
+ }
1610
+ if (this.bridge.rawBridge?.callEvenApp) {
1611
+ await this.bridge.rawBridge.callEvenApp("audioControl", { isOpen: e });
1612
+ return;
1613
+ }
1614
+ await this.write("right", V(e));
1615
+ }
1616
+ async scanWifi() {
1617
+ return this.assertWifiSupported(), Nt(this.bridge.requestWifiScan ? await this.bridge.requestWifiScan() : await this.bridge.rawBridge?.callEvenApp?.("request_wifi_scan"), "Wi-Fi scan requested");
1618
+ }
1619
+ async getWifiStatus() {
1620
+ return this.assertWifiSupported(), Nt(this.bridge.requestWifiStatus ? await this.bridge.requestWifiStatus() : await this.bridge.rawBridge?.callEvenApp?.("request_wifi_status"), "Wi-Fi status requested");
1621
+ }
1622
+ async configureWifi(e, t) {
1623
+ return this.assertWifiSupported(), Nt(this.bridge.setWifiCredentials ? await this.bridge.setWifiCredentials(e, t) : this.bridge.sendWifiCredentials ? await this.bridge.sendWifiCredentials(e, t) : await this.bridge.rawBridge?.callEvenApp?.("set_wifi_credentials", {
1624
+ ssid: e,
1625
+ password: t
1626
+ }), `Wi-Fi credentials sent for ${e}`);
1627
+ }
1628
+ async requestWifiSetup(e) {
1629
+ return this.assertWifiSupported(), Nt(this.bridge.requestWifiSetup ? await this.bridge.requestWifiSetup(e) : await this.bridge.rawBridge?.callEvenApp?.("request_wifi_setup", { reason: e }), "Wi-Fi setup requested");
1630
+ }
1631
+ supportsWifi() {
1632
+ return !!(this.bridge.requestWifiScan || this.bridge.requestWifiStatus || this.bridge.requestWifiSetup || this.bridge.setWifiCredentials || this.bridge.sendWifiCredentials || this.bridge.rawBridge?.callEvenApp);
1633
+ }
1634
+ assertWifiSupported() {
1635
+ if (!this.supportsWifi()) throw Error("Wi-Fi is only available when the native smartglasses bridge exposes Wi-Fi APIs");
1636
+ }
1637
+ supportsEvenHubDisplay() {
1638
+ return !!(this.bridge.sendStartUpPage || this.bridge.createStartUpPageContainer);
1639
+ }
1640
+ supportsMentraDisplay() {
1641
+ return !!this.bridge.displayText;
1642
+ }
1643
+ onEvent(e) {
1644
+ return this.eventCallbacks.add(e), () => this.eventCallbacks.delete(e);
1645
+ }
1646
+ onAudio(e) {
1647
+ return this.audioCallbacks.add(e), () => this.audioCallbacks.delete(e);
1648
+ }
1649
+ onTranscript(e) {
1650
+ return this.transcriptCallbacks.add(e), () => this.transcriptCallbacks.delete(e);
1651
+ }
1652
+ onWifiStatus(e) {
1653
+ return this.wifiCallbacks.add(e), () => this.wifiCallbacks.delete(e);
1654
+ }
1655
+ handleBridgeEvent(e) {
1656
+ let t = e, n = Et(t);
1657
+ if (n) {
1658
+ for (let e of this.wifiCallbacks) e(n);
1659
+ return;
1660
+ }
1661
+ let r = Tt(t);
1662
+ if (r) {
1663
+ for (let e of this.transcriptCallbacks) e(r.text, r.isFinal, r.metadata);
1664
+ return;
1665
+ }
1666
+ let i = t.audioEvent, a = St(i?.audioPcm);
1667
+ if (a) {
1668
+ for (let e of this.audioCallbacks) e(a, 16e3, "right", "pcm16");
1669
+ return;
1670
+ }
1671
+ let o = St(t.pcm);
1672
+ if (t.type === "mic_pcm" && o) {
1673
+ for (let e of this.audioCallbacks) e(o, 16e3, "right", "pcm16");
1674
+ return;
1675
+ }
1676
+ let s = St(t.lc3);
1677
+ if (t.type === "mic_lc3" && s) {
1678
+ for (let e of this.audioCallbacks) e(s, 16e3, "right", "lc3");
1679
+ return;
1680
+ }
1681
+ let c = wt(t);
1682
+ if (c) {
1683
+ for (let e of this.eventCallbacks) e(c);
1684
+ return;
1685
+ }
1686
+ let l = t.side === "left" || t.side === "right" ? t.side : "right", u = St(t.raw ?? t.data ?? t.bytes);
1687
+ if (!u) return;
1688
+ let d = H(l, u);
1689
+ for (let e of this.eventCallbacks) e(d);
1690
+ let f = d.audioPcm ?? d.audioData;
1691
+ if (f) for (let e of this.audioCallbacks) e(f, 16e3, d.side, d.audioEncoding, d.sequence);
1692
+ }
1693
+ async writeEvenHubDisplay(e) {
1694
+ let t = this.decodeDisplayPacket(e);
1695
+ if (!t) return;
1696
+ let n = `${t.seq}:${t.status}:${t.pageNumber}:${t.maxPages}`, r = this.displayChunks.get(n) ?? Array.from({ length: t.totalPackages });
1697
+ if (r[t.currentPackage] = t.chunk, this.displayChunks.set(n, r), r.some((e) => !e)) return;
1698
+ this.displayChunks.delete(n);
1699
+ let i = r.reduce((e, t) => e + t.length, 0), a = new Uint8Array(i), o = 0;
1700
+ for (let e of r) a.set(e, o), o += e.length;
1701
+ await this.sendEvenHubTextPage(a);
1702
+ }
1703
+ async writeMentraDisplay(e) {
1704
+ let t = this.decodeDisplayPacket(e);
1705
+ if (!t) return;
1706
+ let n = `${t.seq}:${t.status}:${t.pageNumber}:${t.maxPages}`, r = this.displayChunks.get(n) ?? Array.from({ length: t.totalPackages });
1707
+ if (r[t.currentPackage] = t.chunk, this.displayChunks.set(n, r), r.some((e) => !e)) return;
1708
+ this.displayChunks.delete(n);
1709
+ let i = r.reduce((e, t) => e + t.length, 0), a = new Uint8Array(i), o = 0;
1710
+ for (let e of r) a.set(e, o), o += e.length;
1711
+ await this.bridge.displayText?.({
1712
+ text: new TextDecoder().decode(a),
1713
+ x: 0,
1714
+ y: 0,
1715
+ size: 24
1716
+ });
1717
+ }
1718
+ async sendEvenHubTextPage(e) {
1719
+ let t = Rt(e);
1720
+ if (this.bridge.sendStartUpPage) {
1721
+ await this.bridge.sendStartUpPage(t);
1722
+ return;
1723
+ }
1724
+ if (this.bridge.createStartUpPageContainer) {
1725
+ if (!this.evenHubStartupCreated) {
1726
+ zt(await this.bridge.createStartUpPageContainer(t), "createStartUpPageContainer"), this.evenHubStartupCreated = !0;
1727
+ return;
1728
+ }
1729
+ zt(await (this.bridge.rebuildPageContainer ?? this.bridge.createStartUpPageContainer).call(this.bridge, t), "rebuildPageContainer");
1730
+ }
1731
+ }
1732
+ decodeDisplayPacket(e) {
1733
+ if (e.length < 9 || e[0] !== k.SendResult) return null;
1734
+ let t = e[2] || 1, n = e[3] || 0;
1735
+ return n >= t ? null : {
1736
+ seq: e[1] ?? 0,
1737
+ totalPackages: t,
1738
+ currentPackage: n,
1739
+ status: e[4] ?? 0,
1740
+ pageNumber: e[7] ?? 1,
1741
+ maxPages: e[8] ?? 1,
1742
+ chunk: e.slice(9)
1743
+ };
1744
+ }
1745
+ };
1746
+ function wt(e) {
1747
+ let t = At(Dt(e), e);
1748
+ if (!t) return null;
1749
+ let n = t === "single_tap" ? M.SingleTap : t === "double_tap" ? M.DoubleTap : t === "long_press" ? M.LongPress : fe.PageControl;
1750
+ return {
1751
+ side: "right",
1752
+ raw: Uint8Array.from([k.StartAi, n]),
1753
+ type: "state",
1754
+ code: n,
1755
+ label: t
1756
+ };
1757
+ }
1758
+ function Tt(e) {
1759
+ let t = String(e.type ?? e.streamType ?? "");
1760
+ if (t !== "local_transcription" && !t.startsWith("transcription") && !("transcript" in e)) return null;
1761
+ let n = typeof e.text == "string" ? e.text : typeof e.transcript == "string" ? e.transcript : "";
1762
+ return n.trim() ? {
1763
+ text: n,
1764
+ isFinal: typeof e.isFinal == "boolean" ? e.isFinal : typeof e.final == "boolean" ? e.final : e.type === "local_transcription",
1765
+ metadata: { ...e }
1766
+ } : null;
1767
+ }
1768
+ function Et(e) {
1769
+ let t = String(e.type ?? e.eventType ?? e.event_type ?? ""), n = e.values && typeof e.values == "object" ? e.values : e, r = "wifiConnected" in n || "wifiSsid" in n || "wifiLocalIp" in n || "connected" in n || "ssid" in n || "networks" in n || "results" in n;
1770
+ if (t !== "wifi_status_change" && t !== "wifi_status" && t !== "wifi_scan_result" && !r) return null;
1771
+ let i = Ft(n.wifiConnected) ?? Ft(n.connected), a = It(n.wifiSsid) ?? It(n.ssid), o = It(n.wifiLocalIp) ?? It(n.localIp), s = Lt(n);
1772
+ return {
1773
+ available: !0,
1774
+ status: Pt(n) ?? (t === "wifi_scan_result" ? s.length > 0 ? `found ${s.length} Wi-Fi network(s)` : "Wi-Fi scan result" : i ? `connected to ${a ?? "Wi-Fi"}` : i === !1 ? "disconnected" : "Wi-Fi status updated"),
1775
+ networks: s,
1776
+ raw: {
1777
+ ...e,
1778
+ normalized: {
1779
+ connected: i,
1780
+ ssid: a,
1781
+ localIp: o
1782
+ }
1783
+ }
1784
+ };
1785
+ }
1786
+ function Dt(e) {
1787
+ let t = Ot(e.jsonData);
1788
+ return kt(e.listEvent) ?? kt(e.textEvent) ?? kt(e.sysEvent) ?? e.eventType ?? t?.eventType ?? t?.event_type ?? t?.Event_Type ?? t?.type ?? e.type ?? e.action;
1789
+ }
1790
+ function Ot(e) {
1791
+ if (e && typeof e == "object") return e;
1792
+ if (typeof e != "string") return null;
1793
+ try {
1794
+ let t = JSON.parse(e);
1795
+ return t && typeof t == "object" ? t : null;
1796
+ } catch {
1797
+ return null;
1798
+ }
1799
+ }
1800
+ function kt(e) {
1801
+ if (!e || typeof e != "object") return;
1802
+ let t = e;
1803
+ return t.eventType ?? t.event_type ?? t.Event_Type ?? t.type;
1804
+ }
1805
+ function At(e, t) {
1806
+ if (e === void 0 && (t.listEvent || t.textEvent || t.sysEvent)) return "single_tap";
1807
+ if (typeof e == "number") return e === 0 ? "single_tap" : e === 1 ? "scroll_up" : e === 2 ? "scroll_down" : e === 3 ? "double_tap" : null;
1808
+ if (typeof e == "string") {
1809
+ let n = e.toUpperCase();
1810
+ if (n.includes("LONG")) return "long_press";
1811
+ if (n.includes("DOUBLE")) return "double_tap";
1812
+ if (n.includes("SCROLL_TOP") || n.includes("SCROLL_UP")) return "scroll_up";
1813
+ if (n.includes("SCROLL_BOTTOM") || n.includes("SCROLL_DOWN")) return "scroll_down";
1814
+ if (n === "UP") return "scroll_up";
1815
+ if (n === "DOWN") return "scroll_down";
1816
+ if (n.includes("CLICK") || n.includes("TAP")) return "single_tap";
1817
+ if (n === "BUTTON_PRESS") return jt(t);
1818
+ }
1819
+ return jt(t);
1820
+ }
1821
+ function jt(e) {
1822
+ let t = String(e.pressType ?? e.button ?? e.buttonId ?? e.value ?? "").toUpperCase();
1823
+ return t.includes("LONG") ? "long_press" : t.includes("DOUBLE") ? "double_tap" : t.includes("SCROLL_TOP") || t.includes("UP") ? "scroll_up" : t.includes("SCROLL_BOTTOM") || t.includes("DOWN") ? "scroll_down" : t.includes("SINGLE") || t.includes("TAP") ? "single_tap" : null;
1824
+ }
1825
+ function Mt(e) {
1826
+ return typeof e == "function" ? e : !e || typeof e != "object" ? null : e.unsubscribe?.bind(e) ?? e.off?.bind(e) ?? e.remove?.bind(e) ?? null;
1827
+ }
1828
+ function Nt(e, t) {
1829
+ return {
1830
+ available: !0,
1831
+ status: Pt(e) ?? t,
1832
+ networks: Lt(e),
1833
+ raw: e
1834
+ };
1835
+ }
1836
+ function Pt(e) {
1837
+ if (typeof e == "string" && e.trim()) return e.trim();
1838
+ if (!e || typeof e != "object") return null;
1839
+ let t = e, n = t.status ?? t.state ?? t.message ?? t.result ?? t.connectedSsid ?? t.ssid;
1840
+ return typeof n == "string" && n.trim() ? n.trim() : null;
1841
+ }
1842
+ function Ft(e) {
1843
+ if (typeof e == "boolean") return e;
1844
+ if (typeof e == "number") return e !== 0;
1845
+ if (typeof e == "string") {
1846
+ if (/^(true|1|yes|connected)$/i.test(e)) return !0;
1847
+ if (/^(false|0|no|disconnected)$/i.test(e)) return !1;
1848
+ }
1849
+ return null;
1850
+ }
1851
+ function It(e) {
1852
+ return typeof e == "string" && e.trim() ? e.trim() : null;
1853
+ }
1854
+ function Lt(e) {
1855
+ if (!e || typeof e != "object") return [];
1856
+ let t = e, n = t.networks ?? t.networks_neo ?? t.results;
1857
+ return Array.isArray(n) ? n.map((e) => {
1858
+ if (typeof e == "string") return e;
1859
+ if (!e || typeof e != "object") return "";
1860
+ let t = e;
1861
+ return String(t.ssid ?? t.SSID ?? t.name ?? "");
1862
+ }).filter((e) => e.trim().length > 0) : [];
1863
+ }
1864
+ function Rt(e) {
1865
+ let t = new TextDecoder().decode(e);
1866
+ return {
1867
+ containerTotalNum: 2,
1868
+ text: t,
1869
+ textObject: [{
1870
+ containerID: 1,
1871
+ containerName: "eliza-smartglasses-text",
1872
+ content: t,
1873
+ xPosition: 12,
1874
+ yPosition: 12,
1875
+ width: 552,
1876
+ height: 200,
1877
+ isEventCapture: 0
1878
+ }],
1879
+ listObject: [{
1880
+ containerID: 2,
1881
+ containerName: "eliza-smartglasses-input",
1882
+ itemContainer: {
1883
+ itemCount: 1,
1884
+ itemWidth: 552,
1885
+ isItemSelectBorderEn: 0,
1886
+ itemName: ["Click mic on | Double click mic off"]
1887
+ },
1888
+ isEventCapture: 1,
1889
+ xPosition: 12,
1890
+ yPosition: 236,
1891
+ width: 552,
1892
+ height: 36
1893
+ }]
1894
+ };
1895
+ }
1896
+ function zt(e, t) {
1897
+ if (typeof e == "number" && e !== 0) throw Error(`${t} failed with result ${e}`);
1898
+ if (typeof e == "boolean" && !e) throw Error(`${t} failed`);
1899
+ }
1900
+ //#endregion
1901
+ //#region src/transport/web-bluetooth.ts
1902
+ var Bt = class {
1903
+ bluetooth;
1904
+ name = "web-bluetooth-g1";
1905
+ sides = /* @__PURE__ */ new Map();
1906
+ eventCallbacks = /* @__PURE__ */ new Set();
1907
+ audioCallbacks = /* @__PURE__ */ new Set();
1908
+ constructor(e = Ut()) {
1909
+ this.bluetooth = e;
1910
+ }
1911
+ async connect() {
1912
+ try {
1913
+ await this.connectLens("left"), await this.connectLens("right");
1914
+ } catch (e) {
1915
+ throw await this.disconnect(), e;
1916
+ }
1917
+ }
1918
+ async disconnect() {
1919
+ for (let [e, t] of this.sides) await t.rx.stopNotifications?.(), t.rx.removeEventListener?.("characteristicvaluechanged", t.listener), t.server.disconnect?.(), this.sides.delete(e);
1920
+ }
1921
+ isConnected() {
1922
+ return this.sides.size === 2 && [...this.sides.values()].every((e) => e.server.connected !== !1);
1923
+ }
1924
+ getConnectedLenses() {
1925
+ let e = {};
1926
+ for (let [t, n] of this.sides) e[t] = {
1927
+ connected: n.server.connected !== !1,
1928
+ name: n.device.name,
1929
+ address: n.device.id
1930
+ };
1931
+ return e;
1932
+ }
1933
+ async write(e, t) {
1934
+ let n = this.sides.get(e);
1935
+ if (!n) throw Error(`G1 ${e} lens is not connected`);
1936
+ let r = Vt(t);
1937
+ if (n.tx.writeValueWithoutResponse) {
1938
+ await n.tx.writeValueWithoutResponse(r);
1939
+ return;
1940
+ }
1941
+ if (n.tx.writeValueWithResponse) {
1942
+ await n.tx.writeValueWithResponse(r);
1943
+ return;
1944
+ }
1945
+ await n.tx.writeValue?.(r);
1946
+ }
1947
+ async writeBoth(e) {
1948
+ await this.write("left", e), await this.write("right", e);
1949
+ }
1950
+ async openMicrophone(e) {
1951
+ await this.write("right", V(e));
1952
+ }
1953
+ onEvent(e) {
1954
+ return this.eventCallbacks.add(e), () => this.eventCallbacks.delete(e);
1955
+ }
1956
+ onAudio(e) {
1957
+ return this.audioCallbacks.add(e), () => this.audioCallbacks.delete(e);
1958
+ }
1959
+ async connectLens(e) {
1960
+ if (this.sides.has(e)) return;
1961
+ let t = e === "left" ? "_L_" : "_R_", n = await this.bluetooth.requestDevice({
1962
+ filters: [
1963
+ { namePrefix: "Even" },
1964
+ { namePrefix: "G1" },
1965
+ { namePrefix: "ER" }
1966
+ ],
1967
+ optionalServices: [O.service]
1968
+ });
1969
+ if (n.name && !n.name.includes(t)) throw Error(`Selected ${n.name} for ${e}, expected a lens name containing ${t}`);
1970
+ let r = this.findConnectedDeviceSide(n);
1971
+ if (r) throw Error(`Selected the ${r} lens again while connecting the ${e} lens`);
1972
+ if (!n.gatt) throw Error(`Selected G1 ${e} device does not expose GATT`);
1973
+ let i = await n.gatt.connect(), a = await i.getPrimaryService(O.service), o = await a.getCharacteristic(O.tx), s = await a.getCharacteristic(O.rx), c = (t) => {
1974
+ let n = t.target?.value;
1975
+ if (!n) return;
1976
+ let r = new Uint8Array(n.buffer.slice(n.byteOffset, n.byteOffset + n.byteLength));
1977
+ this.emitParsed(H(e, r));
1978
+ };
1979
+ s.addEventListener("characteristicvaluechanged", c), await s.startNotifications(), this.sides.set(e, {
1980
+ device: n,
1981
+ server: i,
1982
+ tx: o,
1983
+ rx: s,
1984
+ listener: c
1985
+ });
1986
+ }
1987
+ findConnectedDeviceSide(e) {
1988
+ for (let [t, n] of this.sides) if (n.device === e || e.id && n.device.id === e.id) return t;
1989
+ return null;
1990
+ }
1991
+ emitParsed(e) {
1992
+ for (let t of this.eventCallbacks) t(e);
1993
+ let t = e.audioPcm ?? e.audioData;
1994
+ if (t) for (let n of this.audioCallbacks) n(t, 16e3, e.side, e.audioEncoding, e.sequence);
1995
+ }
1996
+ };
1997
+ function Vt(e) {
1998
+ let t = new ArrayBuffer(e.byteLength);
1999
+ return new Uint8Array(t).set(e), t;
2000
+ }
2001
+ function Ht() {
2002
+ let e = globalThis.navigator;
2003
+ return e?.bluetooth ? new Bt(e.bluetooth) : null;
2004
+ }
2005
+ function Ut() {
2006
+ let e = globalThis.navigator;
2007
+ if (!e?.bluetooth) throw Error("Web Bluetooth is not available in this runtime");
2008
+ return e.bluetooth;
2009
+ }
2010
+ //#endregion
2011
+ //#region src/ui/SmartglassesView.tsx
2012
+ var Wt = 8, Gt = 12, Kt = 5, J = {
2013
+ desktop: {
2014
+ label: "Desktop",
2015
+ primary: "Chrome/Edge Web Bluetooth",
2016
+ secondary: "Pair both lenses."
2017
+ },
2018
+ ios: {
2019
+ label: "iOS",
2020
+ primary: "Native bridge required",
2021
+ secondary: "Use the host bridge."
2022
+ },
2023
+ android: {
2024
+ label: "Android",
2025
+ primary: "Native bridge preferred",
2026
+ secondary: "Pair and configure in the host."
2027
+ }
2028
+ }, qt = [
2029
+ {
2030
+ id: "status",
2031
+ label: "Status",
2032
+ text: "elizaOS smartglasses link online.",
2033
+ className: "border-green-500/40 bg-green-500/10 text-green-700"
2034
+ },
2035
+ {
2036
+ id: "ping",
2037
+ label: "Ping",
2038
+ text: "Display ping. Confirm both lenses render this page.",
2039
+ className: "border-accent/45 bg-accent/10 text-accent"
2040
+ },
2041
+ {
2042
+ id: "nav",
2043
+ label: "Nav",
2044
+ text: "Navigation card ready. Keep eyes forward.",
2045
+ className: "border-amber-500/40 bg-amber-500/10 text-amber-700"
2046
+ }
2047
+ ];
2048
+ function Y() {
2049
+ return (/* @__PURE__ */ new Date()).toISOString();
2050
+ }
2051
+ function Jt(e, t, n) {
2052
+ return new Promise((r, i) => {
2053
+ let a = window.setTimeout(() => i(Error(n)), t);
2054
+ e.then((e) => {
2055
+ window.clearTimeout(a), r(e);
2056
+ }, (e) => {
2057
+ window.clearTimeout(a), i(e);
2058
+ });
2059
+ });
2060
+ }
2061
+ function X(e) {
2062
+ return e instanceof Error ? e.message : String(e);
2063
+ }
2064
+ function Yt(e) {
2065
+ return new Promise((t) => window.setTimeout(t, e));
2066
+ }
2067
+ function Xt() {
2068
+ return typeof window > "u" ? null : window.__mentraBridge ?? window.__evenBridge ?? null;
2069
+ }
2070
+ function Zt(e) {
2071
+ return [...e].map((e) => e.toString(16).padStart(2, "0")).join("");
2072
+ }
2073
+ function Qt() {
2074
+ let [e, t] = p(null), [n, r] = p({
2075
+ left: "idle",
2076
+ right: "idle"
2077
+ }), [i, a] = p([]), [o, s] = p([]), [c, l] = p([]), [u, m] = p(null), [_, y] = p(null), [ne, ue] = p("Smartglasses display test."), [b, x] = p(!1), [S, de] = p(""), [C, w] = p(""), [T, E] = p("Not checked"), [D, O] = p([]), [k, fe] = p("desktop"), [A, pe] = p(null), [j, M] = p(null), [N, me] = p({}), [P, he] = p(null), [ge, _e] = p(null), [F, ve] = p({
2078
+ headsetConnected: !1,
2079
+ init: !1,
2080
+ display: !1,
2081
+ serial: !1,
2082
+ serialObserved: !1,
2083
+ settings: !1,
2084
+ microphone: !1,
2085
+ micEnableWrite: !1,
2086
+ micDisableWrite: !1,
2087
+ tapMicEnable: !1,
2088
+ tapMicDisable: !1,
2089
+ audio: !1,
2090
+ transcript: !1,
2091
+ eventStream: !1
2092
+ }), ye = f(F), I = f(0), L = Xt(), be = !!Ht(), R = n.left === "connected" && n.right === "connected", xe = d(() => Ke(F, n, A, j, i, o), [
2093
+ j,
2094
+ i,
2095
+ n,
2096
+ A,
2097
+ F,
2098
+ o
2099
+ ]), z = d(() => Je(F, n, A, j, i, o), [
2100
+ j,
2101
+ i,
2102
+ n,
2103
+ A,
2104
+ F,
2105
+ o
2106
+ ]), B = d(() => ({
2107
+ ok: xe.length === 0,
2108
+ generatedAt: Y(),
2109
+ transport: e?.name ?? (L ? "native-bridge" : null),
2110
+ connected: R,
2111
+ lenses: n,
2112
+ scanDiagnosis: qe(n),
2113
+ physicalBlocker: z,
2114
+ setupHint: Ye(z, A, j),
2115
+ nextAction: Xe(z),
2116
+ serialNumber: ge,
2117
+ tests: F,
2118
+ missingEvidence: xe,
2119
+ events: i,
2120
+ writes: o,
2121
+ audio: c,
2122
+ wifi: {
2123
+ available: !!L,
2124
+ status: T,
2125
+ networks: D
2126
+ },
2127
+ headsetState: {
2128
+ physical: A,
2129
+ battery: j,
2130
+ batteryLevels: N,
2131
+ device: P
2132
+ }
2133
+ }), [
2134
+ L,
2135
+ c,
2136
+ i,
2137
+ R,
2138
+ n,
2139
+ xe,
2140
+ z,
2141
+ A,
2142
+ ge,
2143
+ F,
2144
+ e,
2145
+ j,
2146
+ N,
2147
+ P,
2148
+ D,
2149
+ T,
2150
+ o
2151
+ ]), { ref: Se, agentProps: Ce } = v({
2152
+ id: "setup-connect-headset",
2153
+ role: "button",
2154
+ label: "Connect",
2155
+ group: "setup",
2156
+ status: R ? "active" : "inactive",
2157
+ description: "Pair both left and right smartglasses lenses as one headset"
2158
+ }), { ref: we, agentProps: Te } = v({
2159
+ id: "test-run-check",
2160
+ role: "button",
2161
+ label: "Run Check",
2162
+ group: "test",
2163
+ description: "Request serial/battery and send display/settings packets"
2164
+ }), { ref: Ee, agentProps: De } = v({
2165
+ id: "wifi-ssid",
2166
+ role: "text-input",
2167
+ label: "Wi-Fi SSID",
2168
+ group: "wifi",
2169
+ description: "SSID of the Wi-Fi network to configure on the glasses",
2170
+ getValue: () => S,
2171
+ onFill: (e) => de(e)
2172
+ }), { ref: Oe, agentProps: ke } = v({
2173
+ id: "wifi-password",
2174
+ role: "text-input",
2175
+ label: "Wi-Fi password",
2176
+ group: "wifi",
2177
+ description: "Password for the Wi-Fi network to configure on the glasses",
2178
+ getValue: () => C,
2179
+ onFill: (e) => w(e)
2180
+ });
2181
+ function V(e, t) {
2182
+ a((n) => [...n, {
2183
+ at: Y(),
2184
+ type: e,
2185
+ detail: t
2186
+ }].slice(-80));
2187
+ }
2188
+ function H(e, t = !0) {
2189
+ ve((n) => {
2190
+ let r = {
2191
+ ...n,
2192
+ [e]: t
2193
+ };
2194
+ return ye.current = r, r;
2195
+ });
2196
+ }
2197
+ function U(e, t) {
2198
+ s((n) => [...n, {
2199
+ at: Y(),
2200
+ side: e,
2201
+ command: Ze(t),
2202
+ bytes: t.length,
2203
+ hex: Zt(t.slice(0, 24))
2204
+ }].slice(-120));
2205
+ }
2206
+ async function Ie(e, t, n) {
2207
+ await e.write(t, n), U(t, n);
2208
+ }
2209
+ async function W(e, t) {
2210
+ await e.writeBoth(t), U("both", t);
2211
+ }
2212
+ async function Le(e, t) {
2213
+ await e.openMicrophone(t), U("right", Uint8Array.from([14, +!!t]));
2214
+ }
2215
+ async function Re() {
2216
+ m("connect"), y(null);
2217
+ try {
2218
+ let n = e ?? (L ? new Ct(L) : new Bt());
2219
+ t(n);
2220
+ let i = n.onEvent((e) => {
2221
+ if (H("eventStream"), e.stateCategory === "physical" ? pe(e.stateName ?? e.label ?? null) : e.stateCategory === "battery" ? M(e.stateName ?? e.label ?? null) : e.stateCategory === "device" && he(e.stateName ?? e.label ?? null), e.type === "battery-status" && typeof e.batteryPercent == "number" && me((t) => ({
2222
+ ...t,
2223
+ [e.side]: e.batteryPercent
2224
+ })), e.type === "serial" && e.serialNumber && (_e(e.serialNumber), H("serialObserved")), Be(e.label)) {
2225
+ H("tapMicEnable"), x(!0);
2226
+ let t = Y();
2227
+ a((n) => [...n, {
2228
+ at: t,
2229
+ type: "tap",
2230
+ detail: e.label ?? ""
2231
+ }].slice(-80)), n.openMicrophone(!0).then(() => {
2232
+ U("right", Uint8Array.from([14, 1])), H("microphone"), H("micEnableWrite"), V("microphone", "Enabled by tap");
2233
+ }).catch((e) => V("error", X(e)));
2234
+ }
2235
+ if (Ve(e.label)) {
2236
+ H("tapMicDisable"), x(!1);
2237
+ let t = Y();
2238
+ a((n) => [...n, {
2239
+ at: t,
2240
+ type: "tap",
2241
+ detail: e.label ?? ""
2242
+ }].slice(-80)), n.openMicrophone(!1).then(() => {
2243
+ U("right", Uint8Array.from([14, 0])), H("microphone"), H("micDisableWrite"), V("microphone", "Disabled by tap");
2244
+ }).catch((e) => V("error", X(e)));
2245
+ }
2246
+ V("event", `${e.side} ${e.type}${e.label ? ` ${e.label}` : ""}`);
2247
+ }), o = n.onAudio((e, t, n, r, i) => {
2248
+ e.byteLength > 0 && H("audio"), l((a) => [...a, {
2249
+ at: Y(),
2250
+ side: n,
2251
+ sampleRate: t,
2252
+ encoding: r ?? null,
2253
+ sequence: i,
2254
+ bytes: e.byteLength
2255
+ }].slice(-80)), V("audio", `${n} ${e.byteLength} bytes @ ${t}Hz${r ? ` ${r}` : ""}`);
2256
+ }), s = "onTranscript" in n && n.onTranscript ? n.onTranscript((e, t) => {
2257
+ H("transcript"), V("transcript", `${t ? "final" : "partial"} ${e}`);
2258
+ }) : void 0;
2259
+ try {
2260
+ n instanceof Bt ? (await ze(n, "left"), await ze(n, "right")) : (await n.connect(), r({
2261
+ left: "connected",
2262
+ right: "connected"
2263
+ }));
2264
+ } catch (e) {
2265
+ throw i(), o(), s?.(), e;
2266
+ }
2267
+ await Ie(n, "left", je("left")), await Ie(n, "right", je("right")), H("headsetConnected"), H("init"), V("connect", "Whole headset connected");
2268
+ } catch (e) {
2269
+ y(X(e)), V("error", X(e));
2270
+ } finally {
2271
+ m(null);
2272
+ }
2273
+ }
2274
+ async function ze(e, t) {
2275
+ r((e) => ({
2276
+ ...e,
2277
+ [t]: "prompting"
2278
+ })), V("pairing", `Select the ${t} lens in the Bluetooth picker`);
2279
+ try {
2280
+ await Jt(e.connectLens(t), 6e4, `Timed out connecting the ${t} lens`), r((e) => ({
2281
+ ...e,
2282
+ [t]: "connected"
2283
+ })), V("connect", `${t} lens connected`);
2284
+ } catch (e) {
2285
+ throw r((e) => ({
2286
+ ...e,
2287
+ [t]: "failed"
2288
+ })), e;
2289
+ }
2290
+ }
2291
+ async function G() {
2292
+ if (!e || !R) throw Error("Connect the whole headset before running this test");
2293
+ return e;
2294
+ }
2295
+ async function He() {
2296
+ m("display"), y(null);
2297
+ try {
2298
+ let e = await G(), t = et(ne, { startSeq: I.current });
2299
+ I.current = t.nextSeq;
2300
+ for (let n of t.packets) await W(e, n);
2301
+ H("display"), V("display", `Sent ${t.pages} display page(s)`);
2302
+ } catch (e) {
2303
+ y(X(e)), V("error", X(e));
2304
+ } finally {
2305
+ m(null);
2306
+ }
2307
+ }
2308
+ async function Ue() {
2309
+ m("clear"), y(null);
2310
+ try {
2311
+ await W(await G(), Ne()), V("display", "Cleared display");
2312
+ } catch (e) {
2313
+ y(X(e)), V("error", X(e));
2314
+ } finally {
2315
+ m(null);
2316
+ }
2317
+ }
2318
+ async function We() {
2319
+ m("check"), y(null);
2320
+ try {
2321
+ let e = await G();
2322
+ await Ie(e, "left", Me()), await W(e, Ae()), await W(e, Fe(32)), await W(e, Pe(!1)), H("serial"), H("settings"), V("test", "Requested serial/battery and sent settings packets"), await He();
2323
+ } catch (e) {
2324
+ y(X(e)), V("error", X(e)), m(null);
2325
+ }
2326
+ }
2327
+ async function K() {
2328
+ m("guided"), y(null);
2329
+ let e = null;
2330
+ try {
2331
+ e = await G();
2332
+ let t = Ge(A, j);
2333
+ if (t) throw Error(t);
2334
+ await Le(e, !1), x(!1), H("microphone"), H("micDisableWrite");
2335
+ let n = et("Validation: single tap, speak clearly, then double tap.", { startSeq: I.current });
2336
+ I.current = n.nextSeq;
2337
+ for (let t of n.packets) await W(e, t);
2338
+ H("display"), V("validation", "Single tap, speak clearly, then double tap");
2339
+ let r = Date.now() + 6e4;
2340
+ for (; Date.now() < r;) {
2341
+ let e = ye.current;
2342
+ if (e.tapMicEnable && e.audio && e.tapMicDisable) {
2343
+ V("validation", "Side-tap microphone validation passed");
2344
+ return;
2345
+ }
2346
+ await Yt(500);
2347
+ }
2348
+ let i = ye.current, a = [
2349
+ !i.tapMicEnable && "tap mic enable",
2350
+ !i.audio && "right/bridge audio",
2351
+ !i.tapMicDisable && "tap mic disable"
2352
+ ].filter(Boolean);
2353
+ throw Error(`Guided validation missing: ${a.join(", ")}`);
2354
+ } catch (e) {
2355
+ y(X(e)), V("error", X(e));
2356
+ } finally {
2357
+ try {
2358
+ e && (await Le(e, !1), x(!1));
2359
+ } catch {}
2360
+ m(null);
2361
+ }
2362
+ }
2363
+ async function Qe(e) {
2364
+ m(e ? "mic-on" : "mic-off"), y(null);
2365
+ try {
2366
+ await Le(await G(), e), x(e), H("microphone"), H(e ? "micEnableWrite" : "micDisableWrite"), V("microphone", e ? "Enabled" : "Disabled");
2367
+ } catch (e) {
2368
+ y(X(e)), V("error", X(e));
2369
+ } finally {
2370
+ m(null);
2371
+ }
2372
+ }
2373
+ async function $e() {
2374
+ m("wifi-scan"), y(null);
2375
+ try {
2376
+ if (!L) throw Error("Unavailable");
2377
+ let e = tt(await q(L, "request_wifi_scan"));
2378
+ O(e), E(e.length > 0 ? `Found ${e.length} network(s)` : "Scan requested; waiting for bridge results"), V("wifi", "Requested Wi-Fi scan through bridge");
2379
+ } catch (e) {
2380
+ y(X(e)), E(X(e)), V("error", X(e));
2381
+ } finally {
2382
+ m(null);
2383
+ }
2384
+ }
2385
+ async function rt() {
2386
+ m("wifi-status"), y(null);
2387
+ try {
2388
+ if (!L) throw Error("Unavailable");
2389
+ let e = await q(L, "request_wifi_status"), t = tt(e);
2390
+ t.length > 0 && O(t), E(nt(e)), V("wifi", "Requested Wi-Fi status through bridge");
2391
+ } catch (e) {
2392
+ y(X(e)), E(X(e)), V("error", X(e));
2393
+ } finally {
2394
+ m(null);
2395
+ }
2396
+ }
2397
+ async function it() {
2398
+ m("wifi-configure"), y(null);
2399
+ try {
2400
+ if (!L) throw Error("Unavailable");
2401
+ if (!S.trim()) throw Error("Enter a Wi-Fi SSID");
2402
+ await q(L, "set_wifi_credentials", {
2403
+ ssid: S.trim(),
2404
+ password: C
2405
+ }), E(`Credentials sent for ${S.trim()}`), V("wifi", `Sent credentials for ${S.trim()}`);
2406
+ } catch (e) {
2407
+ y(X(e)), E(X(e)), V("error", X(e));
2408
+ } finally {
2409
+ m(null);
2410
+ }
2411
+ }
2412
+ async function at() {
2413
+ m("wifi-setup"), y(null);
2414
+ try {
2415
+ if (!L) throw Error("Unavailable");
2416
+ await q(L, "request_wifi_setup", { reason: "Smartglasses setup" }), E("Native Wi-Fi setup requested"), V("wifi", "Requested native Wi-Fi setup flow");
2417
+ } catch (e) {
2418
+ y(X(e)), E(X(e)), V("error", X(e));
2419
+ } finally {
2420
+ m(null);
2421
+ }
2422
+ }
2423
+ async function ot() {
2424
+ window.facewearSmartglassesReport = B, await navigator.clipboard?.writeText(JSON.stringify(B, null, 2)), V("report", "Copied diagnostics report");
2425
+ }
2426
+ function st() {
2427
+ window.facewearSmartglassesReport = B;
2428
+ let e = new Blob([JSON.stringify(B, null, 2)], { type: "application/json" }), t = URL.createObjectURL(e), n = document.createElement("a");
2429
+ n.href = t, n.download = `smartglasses-report-${Date.now()}.json`, n.click(), URL.revokeObjectURL(t), V("report", "Downloaded diagnostics report");
2430
+ }
2431
+ return /* @__PURE__ */ g("div", {
2432
+ className: "flex min-h-0 flex-1 flex-col overflow-y-auto bg-bg text-txt",
2433
+ children: [
2434
+ /* @__PURE__ */ h("div", {
2435
+ className: "px-4 py-3",
2436
+ children: /* @__PURE__ */ g("div", {
2437
+ className: "flex flex-wrap items-center justify-between gap-3",
2438
+ children: [/* @__PURE__ */ h("div", {
2439
+ className: "min-w-0",
2440
+ children: /* @__PURE__ */ g("div", {
2441
+ className: "flex items-center gap-2",
2442
+ children: [/* @__PURE__ */ h(ae, { className: "h-4 w-4 text-accent" }), /* @__PURE__ */ h("h1", {
2443
+ className: "text-sm font-semibold",
2444
+ children: "Smartglasses"
2445
+ })]
2446
+ })
2447
+ }), /* @__PURE__ */ h(en, {
2448
+ ok: R,
2449
+ label: R ? "Connected" : "Offline"
2450
+ })]
2451
+ })
2452
+ }),
2453
+ /* @__PURE__ */ g("div", {
2454
+ className: "mx-auto flex w-full max-w-3xl flex-col gap-3 p-4",
2455
+ children: [
2456
+ /* @__PURE__ */ g(Z, { children: [
2457
+ /* @__PURE__ */ g("div", {
2458
+ className: "flex flex-wrap items-center justify-between gap-3",
2459
+ children: [/* @__PURE__ */ h("div", { children: /* @__PURE__ */ h("h2", {
2460
+ className: "text-sm font-semibold",
2461
+ children: "Setup"
2462
+ }) }), /* @__PURE__ */ g("button", {
2463
+ ref: Se,
2464
+ type: "button",
2465
+ onClick: () => void Re(),
2466
+ disabled: !L && !be || u !== null,
2467
+ "aria-label": "Connect",
2468
+ className: "inline-flex h-9 items-center gap-2 rounded-md bg-accent px-3 text-sm font-medium text-accent-foreground disabled:cursor-not-allowed disabled:opacity-50",
2469
+ ...Ce,
2470
+ children: [/* @__PURE__ */ h(te, { className: "h-4 w-4" }), "Connect"]
2471
+ })]
2472
+ }),
2473
+ /* @__PURE__ */ g("div", {
2474
+ className: "mt-4 grid gap-3 sm:grid-cols-2",
2475
+ children: [/* @__PURE__ */ h(tn, {
2476
+ side: "left",
2477
+ state: n.left
2478
+ }), /* @__PURE__ */ h(tn, {
2479
+ side: "right",
2480
+ state: n.right
2481
+ })]
2482
+ }),
2483
+ !be && /* @__PURE__ */ h("p", {
2484
+ className: "mt-3 px-1 text-xs text-muted",
2485
+ children: "Web Bluetooth unavailable"
2486
+ }),
2487
+ /* @__PURE__ */ h(nn, {
2488
+ physicalState: A,
2489
+ batteryState: j,
2490
+ deviceState: P
2491
+ })
2492
+ ] }),
2493
+ /* @__PURE__ */ g(Z, { children: [
2494
+ /* @__PURE__ */ h("h2", {
2495
+ className: "text-sm font-semibold",
2496
+ children: "Platform"
2497
+ }),
2498
+ /* @__PURE__ */ h("div", {
2499
+ className: "mt-3 grid grid-cols-3 gap-1",
2500
+ children: Object.keys(J).map((e) => /* @__PURE__ */ h($t, {
2501
+ platformKey: e,
2502
+ isActive: k === e,
2503
+ onSelect: fe
2504
+ }, e))
2505
+ }),
2506
+ /* @__PURE__ */ h("p", {
2507
+ className: "mt-3 text-xs text-txt",
2508
+ children: J[k].primary
2509
+ }),
2510
+ /* @__PURE__ */ h("p", {
2511
+ className: "mt-2 text-xs text-muted",
2512
+ children: J[k].secondary
2513
+ })
2514
+ ] }),
2515
+ /* @__PURE__ */ g(Z, { children: [
2516
+ /* @__PURE__ */ g("div", {
2517
+ className: "flex items-center justify-between gap-3",
2518
+ children: [/* @__PURE__ */ h("div", { children: /* @__PURE__ */ h("h2", {
2519
+ className: "text-sm font-semibold",
2520
+ children: "Test"
2521
+ }) }), /* @__PURE__ */ g("button", {
2522
+ ref: we,
2523
+ type: "button",
2524
+ onClick: () => void We(),
2525
+ disabled: !R || u !== null,
2526
+ "aria-label": "Run Check",
2527
+ className: "inline-flex h-9 items-center gap-2 rounded-md border border-border px-3 text-sm font-medium disabled:cursor-not-allowed disabled:opacity-50",
2528
+ ...Te,
2529
+ children: [/* @__PURE__ */ h(se, { className: "h-4 w-4" }), "Check"]
2530
+ })]
2531
+ }),
2532
+ /* @__PURE__ */ h("div", {
2533
+ className: "mt-4 grid grid-cols-3 gap-2",
2534
+ children: qt.map((e) => /* @__PURE__ */ h("button", {
2535
+ type: "button",
2536
+ onClick: () => ue(e.text),
2537
+ "aria-pressed": ne === e.text,
2538
+ className: `h-14 px-3 text-left text-xs font-semibold transition ${ne === e.text ? e.className : "text-muted hover:text-txt"}`,
2539
+ children: e.label
2540
+ }, e.id))
2541
+ }),
2542
+ /* @__PURE__ */ g("div", {
2543
+ className: "mt-3 flex flex-wrap gap-2",
2544
+ children: [
2545
+ /* @__PURE__ */ h(Q, {
2546
+ onClick: He,
2547
+ disabled: !R || u !== null,
2548
+ agentId: "test-send-display",
2549
+ agentLabel: "Send Display",
2550
+ agentGroup: "test",
2551
+ agentDescription: "Send the display test text to the smartglasses",
2552
+ children: "Display"
2553
+ }),
2554
+ /* @__PURE__ */ h(Q, {
2555
+ onClick: Ue,
2556
+ disabled: !R || u !== null,
2557
+ agentId: "test-clear-display",
2558
+ agentLabel: "Clear Display",
2559
+ agentGroup: "test",
2560
+ agentDescription: "Clear the smartglasses display",
2561
+ children: "Clear"
2562
+ }),
2563
+ /* @__PURE__ */ g(Q, {
2564
+ onClick: () => Qe(!b),
2565
+ disabled: !R || u !== null,
2566
+ agentId: "test-toggle-mic",
2567
+ agentLabel: b ? "Turn Mic Off" : "Turn Mic On",
2568
+ agentGroup: "test",
2569
+ agentDescription: "Toggle the smartglasses microphone on or off",
2570
+ children: [/* @__PURE__ */ h(oe, { className: "h-4 w-4" }), b ? "Mic Off" : "Mic On"]
2571
+ }),
2572
+ /* @__PURE__ */ h(Q, {
2573
+ onClick: K,
2574
+ disabled: !R || u !== null,
2575
+ agentId: "test-guided-validation",
2576
+ agentLabel: "Guided Validation",
2577
+ agentGroup: "test",
2578
+ agentDescription: "Run the guided side-tap and microphone validation flow",
2579
+ children: "Validate"
2580
+ })
2581
+ ]
2582
+ }),
2583
+ /* @__PURE__ */ g("div", {
2584
+ className: "mt-4 grid gap-2 sm:grid-cols-2",
2585
+ children: [Object.entries(F).slice(0, Wt).map(([e, t]) => /* @__PURE__ */ h(rn, {
2586
+ ok: t,
2587
+ label: on(e)
2588
+ }, e)), Object.keys(F).length > Wt ? /* @__PURE__ */ g("div", {
2589
+ className: "px-3 py-2 text-xs text-muted",
2590
+ children: [
2591
+ "+",
2592
+ Object.keys(F).length - Wt,
2593
+ " checks"
2594
+ ]
2595
+ }) : null]
2596
+ })
2597
+ ] }),
2598
+ /* @__PURE__ */ g(Z, { children: [
2599
+ /* @__PURE__ */ g("div", {
2600
+ className: "flex items-center gap-2",
2601
+ children: [/* @__PURE__ */ h(le, { className: "h-4 w-4 text-accent" }), /* @__PURE__ */ h("h2", {
2602
+ className: "text-sm font-semibold",
2603
+ children: "Wi-Fi"
2604
+ })]
2605
+ }),
2606
+ /* @__PURE__ */ g("div", {
2607
+ className: "mt-4 grid gap-2 sm:grid-cols-2",
2608
+ children: [/* @__PURE__ */ h("input", {
2609
+ ref: Ee,
2610
+ value: S,
2611
+ onChange: (e) => de(e.target.value),
2612
+ placeholder: "SSID",
2613
+ "aria-label": "Wi-Fi SSID",
2614
+ className: "h-9 rounded-md border border-border bg-bg px-3 text-sm outline-none focus:ring-2 focus:ring-ring",
2615
+ ...De
2616
+ }), /* @__PURE__ */ h("input", {
2617
+ ref: Oe,
2618
+ value: C,
2619
+ onChange: (e) => w(e.target.value),
2620
+ placeholder: "Password",
2621
+ type: "password",
2622
+ "aria-label": "Wi-Fi password",
2623
+ className: "h-9 rounded-md border border-border bg-bg px-3 text-sm outline-none focus:ring-2 focus:ring-ring",
2624
+ ...ke
2625
+ })]
2626
+ }),
2627
+ /* @__PURE__ */ g("div", {
2628
+ className: "mt-3 flex flex-wrap gap-2",
2629
+ children: [
2630
+ /* @__PURE__ */ h(Q, {
2631
+ onClick: $e,
2632
+ disabled: !L || u !== null,
2633
+ agentId: "wifi-scan",
2634
+ agentLabel: "Scan Wi-Fi",
2635
+ agentGroup: "wifi",
2636
+ agentDescription: "Scan for nearby Wi-Fi networks through the native bridge",
2637
+ children: "Scan"
2638
+ }),
2639
+ /* @__PURE__ */ h(Q, {
2640
+ onClick: rt,
2641
+ disabled: !L || u !== null,
2642
+ agentId: "wifi-status",
2643
+ agentLabel: "Refresh Wi-Fi Status",
2644
+ agentGroup: "wifi",
2645
+ agentDescription: "Refresh the current Wi-Fi connection status",
2646
+ children: "Status"
2647
+ }),
2648
+ /* @__PURE__ */ h(Q, {
2649
+ onClick: it,
2650
+ disabled: !L || u !== null,
2651
+ agentId: "wifi-configure",
2652
+ agentLabel: "Configure Wi-Fi",
2653
+ agentGroup: "wifi",
2654
+ agentDescription: "Send the entered SSID and password to the glasses",
2655
+ children: "Configure"
2656
+ }),
2657
+ /* @__PURE__ */ h(Q, {
2658
+ onClick: at,
2659
+ disabled: !L || u !== null,
2660
+ agentId: "wifi-native-setup",
2661
+ agentLabel: "Native Wi-Fi Setup",
2662
+ agentGroup: "wifi",
2663
+ agentDescription: "Launch the native bridge Wi-Fi setup flow",
2664
+ children: "Setup"
2665
+ })
2666
+ ]
2667
+ }),
2668
+ /* @__PURE__ */ h("p", {
2669
+ className: "mt-3 text-xs text-muted",
2670
+ children: T
2671
+ }),
2672
+ D.length > 0 && /* @__PURE__ */ g("div", {
2673
+ className: "mt-2 flex flex-wrap gap-1",
2674
+ children: [D.slice(0, Kt).map((e) => /* @__PURE__ */ h("span", {
2675
+ className: "px-1.5 py-1 text-xs text-muted",
2676
+ children: e
2677
+ }, e)), D.length > Kt ? /* @__PURE__ */ g("span", {
2678
+ className: "px-1.5 py-1 text-xs text-muted",
2679
+ children: ["+", D.length - Kt]
2680
+ }) : null]
2681
+ })
2682
+ ] }),
2683
+ /* @__PURE__ */ g(Z, { children: [
2684
+ /* @__PURE__ */ g("div", {
2685
+ className: "flex items-center gap-2",
2686
+ children: [/* @__PURE__ */ h(ee, { className: "h-4 w-4 text-accent" }), /* @__PURE__ */ h("h2", {
2687
+ className: "text-sm font-semibold",
2688
+ children: "Report"
2689
+ })]
2690
+ }),
2691
+ /* @__PURE__ */ g("div", {
2692
+ className: "mt-3 grid gap-2 text-xs",
2693
+ children: [
2694
+ /* @__PURE__ */ h($, {
2695
+ label: "Transport",
2696
+ value: B.transport ?? "none"
2697
+ }),
2698
+ /* @__PURE__ */ h($, {
2699
+ label: "Complete",
2700
+ value: B.ok ? "yes" : "no"
2701
+ }),
2702
+ /* @__PURE__ */ h($, {
2703
+ label: "Serial",
2704
+ value: B.serialNumber ?? "unknown"
2705
+ }),
2706
+ /* @__PURE__ */ h($, {
2707
+ label: "Next",
2708
+ value: B.nextAction ?? "none"
2709
+ }),
2710
+ /* @__PURE__ */ h($, {
2711
+ label: "Missing",
2712
+ value: B.missingEvidence.length === 0 ? "none" : String(B.missingEvidence.length)
2713
+ }),
2714
+ /* @__PURE__ */ h($, {
2715
+ label: "Bridge",
2716
+ value: L ? "available" : "none"
2717
+ }),
2718
+ /* @__PURE__ */ h($, {
2719
+ label: "State",
2720
+ value: [
2721
+ A,
2722
+ j,
2723
+ P
2724
+ ].filter(Boolean).join(" / ") || "none"
2725
+ }),
2726
+ /* @__PURE__ */ h($, {
2727
+ label: "Battery",
2728
+ value: an(N)
2729
+ }),
2730
+ /* @__PURE__ */ h($, {
2731
+ label: "Events",
2732
+ value: String(i.length)
2733
+ })
2734
+ ]
2735
+ }),
2736
+ /* @__PURE__ */ g("div", {
2737
+ className: "mt-4 flex flex-wrap gap-2",
2738
+ children: [/* @__PURE__ */ g(Q, {
2739
+ onClick: ot,
2740
+ agentId: "report-copy",
2741
+ agentLabel: "Copy Report",
2742
+ agentGroup: "report",
2743
+ agentDescription: "Copy the smartglasses diagnostics report to the clipboard",
2744
+ children: [/* @__PURE__ */ h(re, { className: "h-4 w-4" }), "Copy"]
2745
+ }), /* @__PURE__ */ g(Q, {
2746
+ onClick: st,
2747
+ agentId: "report-download",
2748
+ agentLabel: "Download Report",
2749
+ agentGroup: "report",
2750
+ agentDescription: "Download the smartglasses diagnostics report as JSON",
2751
+ children: [/* @__PURE__ */ h(ie, { className: "h-4 w-4" }), "Download"]
2752
+ })]
2753
+ })
2754
+ ] }),
2755
+ /* @__PURE__ */ g(Z, { children: [/* @__PURE__ */ g("div", {
2756
+ className: "flex items-center gap-2",
2757
+ children: [/* @__PURE__ */ h(ce, { className: "h-4 w-4 text-accent" }), /* @__PURE__ */ h("h2", {
2758
+ className: "text-sm font-semibold",
2759
+ children: "Events"
2760
+ })]
2761
+ }), /* @__PURE__ */ g("div", {
2762
+ className: "mt-3 max-h-72 overflow-y-auto",
2763
+ children: [i.length === 0 ? /* @__PURE__ */ h("p", {
2764
+ className: "px-1 py-2 text-xs text-muted",
2765
+ children: "None"
2766
+ }) : i.slice().reverse().slice(0, Gt).map((e) => /* @__PURE__ */ g("div", {
2767
+ className: "px-1 py-2",
2768
+ children: [/* @__PURE__ */ h("p", {
2769
+ className: "text-xs font-medium text-txt",
2770
+ children: e.type
2771
+ }), /* @__PURE__ */ h("p", {
2772
+ className: "mt-0.5 text-xs text-muted",
2773
+ children: e.detail
2774
+ })]
2775
+ }, `${e.at}:${e.type}:${e.detail}`)), i.length > Gt ? /* @__PURE__ */ g("div", {
2776
+ className: "px-3 py-2 text-xs text-muted",
2777
+ children: [
2778
+ "+",
2779
+ i.length - Gt,
2780
+ " older events"
2781
+ ]
2782
+ }) : null]
2783
+ })] })
2784
+ ]
2785
+ }),
2786
+ _ && /* @__PURE__ */ h("div", {
2787
+ className: "mx-4 mb-4 px-1 py-2 text-xs text-destructive",
2788
+ children: _
2789
+ })
2790
+ ]
2791
+ });
2792
+ }
2793
+ function Z({ children: e }) {
2794
+ return /* @__PURE__ */ h("div", {
2795
+ className: "py-2",
2796
+ children: e
2797
+ });
2798
+ }
2799
+ function Q({ children: e, disabled: t, onClick: n, agentId: r, agentLabel: i, agentGroup: a, agentDescription: o }) {
2800
+ let { ref: s, agentProps: c } = v({
2801
+ id: r,
2802
+ role: "button",
2803
+ label: i,
2804
+ group: a,
2805
+ description: o,
2806
+ onActivate: () => void n()
2807
+ });
2808
+ return /* @__PURE__ */ h("button", {
2809
+ ref: s,
2810
+ type: "button",
2811
+ onClick: () => void n(),
2812
+ disabled: t,
2813
+ "aria-label": i,
2814
+ className: "inline-flex h-9 items-center gap-2 px-3 text-sm font-medium hover:bg-muted/20 disabled:cursor-not-allowed disabled:opacity-50",
2815
+ ...c,
2816
+ children: e
2817
+ });
2818
+ }
2819
+ function $t({ platformKey: e, isActive: t, onSelect: n }) {
2820
+ let r = J[e].label, { ref: i, agentProps: a } = v({
2821
+ id: `platform-tab-${e}`,
2822
+ role: "tab",
2823
+ label: `${r} platform`,
2824
+ group: "platform-setup",
2825
+ status: t ? "active" : "inactive",
2826
+ description: `Show ${r} smartglasses pairing instructions`,
2827
+ onActivate: () => n(e)
2828
+ });
2829
+ return /* @__PURE__ */ h("button", {
2830
+ ref: i,
2831
+ type: "button",
2832
+ onClick: () => n(e),
2833
+ "aria-current": t ? "page" : void 0,
2834
+ "aria-label": `${r} platform`,
2835
+ className: `h-8 px-2 text-xs font-medium transition-colors ${t ? "text-accent" : "text-muted hover:bg-muted/20 hover:text-txt"}`,
2836
+ ...a,
2837
+ children: r
2838
+ });
2839
+ }
2840
+ function en({ ok: e, label: t }) {
2841
+ return /* @__PURE__ */ g("span", {
2842
+ className: `inline-flex h-7 items-center gap-1.5 px-1.5 text-xs font-medium ${e ? "text-green-700 dark:text-green-300" : "text-muted"}`,
2843
+ children: [h(e ? y : ue, { className: "h-3.5 w-3.5" }), t]
2844
+ });
2845
+ }
2846
+ function tn({ side: e, state: t }) {
2847
+ return /* @__PURE__ */ g("div", {
2848
+ className: "flex items-center justify-between px-1 py-2",
2849
+ children: [/* @__PURE__ */ g("div", {
2850
+ className: "flex items-center gap-2",
2851
+ children: [/* @__PURE__ */ h(ae, { className: "h-4 w-4 text-muted" }), /* @__PURE__ */ h("span", {
2852
+ className: "text-sm capitalize",
2853
+ children: e
2854
+ })]
2855
+ }), /* @__PURE__ */ h(en, {
2856
+ ok: t === "connected",
2857
+ label: t
2858
+ })]
2859
+ });
2860
+ }
2861
+ function nn({ physicalState: e, batteryState: t, deviceState: n }) {
2862
+ let r = [
2863
+ {
2864
+ key: "physical",
2865
+ value: e ?? ""
2866
+ },
2867
+ {
2868
+ key: "battery",
2869
+ value: t ?? ""
2870
+ },
2871
+ {
2872
+ key: "device",
2873
+ value: n ?? ""
2874
+ }
2875
+ ].filter((e) => e.value.length > 0), i = K(e, t), a = e === "wearing", o = i ? "text-amber-800 dark:text-amber-200" : a ? "text-green-700 dark:text-green-300" : "text-muted", s = i ? "Remove from charger and wear before validation." : a ? "Ready for tap/audio validation." : "Wear state required for tap/audio validation.";
2876
+ return /* @__PURE__ */ g("div", {
2877
+ className: `mt-3 px-1 py-2 ${o}`,
2878
+ children: [/* @__PURE__ */ g("div", {
2879
+ className: "flex flex-wrap items-center gap-1.5",
2880
+ children: [/* @__PURE__ */ h("span", {
2881
+ className: "text-2xs font-semibold uppercase tracking-wider opacity-70",
2882
+ children: "Headset"
2883
+ }), r.length > 0 ? r.map((e) => /* @__PURE__ */ g("span", {
2884
+ className: "inline-flex items-center gap-1 px-1.5 py-0.5 text-2xs font-medium",
2885
+ children: [/* @__PURE__ */ h("span", {
2886
+ className: "h-1 w-1 rounded-full bg-current opacity-70",
2887
+ "aria-hidden": !0
2888
+ }), e.value]
2889
+ }, e.key)) : /* @__PURE__ */ h("span", {
2890
+ className: "text-2xs italic opacity-70",
2891
+ children: "no state yet"
2892
+ })]
2893
+ }), /* @__PURE__ */ h("p", {
2894
+ className: "mt-1.5 text-2xs leading-4 opacity-80",
2895
+ children: s
2896
+ })]
2897
+ });
2898
+ }
2899
+ function rn({ ok: e, label: t }) {
2900
+ return /* @__PURE__ */ g("div", {
2901
+ className: "flex items-center justify-between gap-2 px-1 py-2 transition-colors",
2902
+ children: [/* @__PURE__ */ h("span", {
2903
+ className: `text-xs ${e ? "font-medium text-txt" : "text-muted"}`,
2904
+ children: t
2905
+ }), /* @__PURE__ */ g("span", {
2906
+ className: `inline-flex items-center gap-1.5 rounded-full px-1.5 py-0.5 ${e ? "text-green-600 dark:text-green-400" : "text-muted"}`,
2907
+ children: [/* @__PURE__ */ h("span", {
2908
+ className: `h-1.5 w-1.5 rounded-full ${e ? "bg-green-500" : "bg-muted/40"}`,
2909
+ "aria-hidden": !0
2910
+ }), h(e ? y : ne, { className: "h-3.5 w-3.5" })]
2911
+ })]
2912
+ });
2913
+ }
2914
+ function $({ label: e, value: t }) {
2915
+ return /* @__PURE__ */ g("div", {
2916
+ className: "flex items-center justify-between gap-3",
2917
+ children: [/* @__PURE__ */ h("span", {
2918
+ className: "text-muted",
2919
+ children: e
2920
+ }), /* @__PURE__ */ h("span", {
2921
+ className: "truncate font-medium text-txt",
2922
+ children: t
2923
+ })]
2924
+ });
2925
+ }
2926
+ function an(e) {
2927
+ return `L ${e.left === void 0 ? "unknown" : `${e.left}%`} / R ${e.right === void 0 ? "unknown" : `${e.right}%`}`;
2928
+ }
2929
+ function on(e) {
2930
+ return {
2931
+ headsetConnected: "Whole headset",
2932
+ init: "Init packets",
2933
+ display: "Display",
2934
+ serial: "Serial request",
2935
+ serialObserved: "Serial observed",
2936
+ settings: "Settings",
2937
+ microphone: "Microphone",
2938
+ micEnableWrite: "Mic enable write",
2939
+ micDisableWrite: "Mic disable write",
2940
+ tapMicEnable: "Tap mic enable",
2941
+ tapMicDisable: "Tap mic disable",
2942
+ audio: "Audio",
2943
+ transcript: "Transcript",
2944
+ eventStream: "Events"
2945
+ }[e] ?? e;
2946
+ }
2947
+ //#endregion
2948
+ export { yt as FacewearAppView, bt as FacewearTuiView, D as FacewearView, ht as SmartglassesPanelView, xt as SmartglassesTuiView, Qt as SmartglassesView };
2949
+
2950
+ //# sourceMappingURL=bundle.js.map