@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 @@
1
+ {"version":3,"sources":["../../src/components/FacewearSpatialView.tsx"],"sourcesContent":["/**\n * FacewearSpatialView - the facewear device-management surface authored once\n * with the spatial vocabulary, so it renders correctly wherever it is shown:\n *\n * - GUI / XR - mounted in `<SpatialSurface>` (DOM; XR scales up).\n * - TUI - rendered to real terminal lines by the agent terminal, via\n * `registerSpatialTerminalView` (see `register-terminal-view.tsx`).\n *\n * It is purely presentational (a snapshot + an action callback in, primitives\n * out) and imports only the cross-modality primitives plus a type-only view of\n * the device registry, so it is safe to render in the Node agent process where\n * the terminal lives (no fetch/Capacitor runtime import).\n */\n\nimport {\n Button,\n Card,\n Divider,\n HStack,\n List,\n type SpatialTone,\n Text,\n VStack,\n} from \"@elizaos/ui/spatial\";\nimport type { FacewearDeviceType } from \"../devices/registry.js\";\n\n/** A connected facewear device, mirrored from `/api/facewear/status`. */\nexport interface FacewearDeviceRow {\n id: string;\n kind: \"xr\" | \"smartglasses\";\n deviceType?: string;\n}\n\n/** A supported device the operator can connect/manage. */\nexport interface FacewearProfileRow {\n type: FacewearDeviceType;\n name: string;\n manufacturer: string;\n connectionType: string;\n connected: boolean;\n}\n\nexport interface FacewearSnapshot {\n /** Supported device profiles with their derived connected state. */\n profiles: FacewearProfileRow[];\n /** The live connected devices the status route reports. */\n devices: FacewearDeviceRow[];\n /** Number of connected devices (the header pill count). */\n connectedCount: number;\n loading?: boolean;\n error?: string | null;\n}\n\nconst VISIBLE_DEVICE_LIMIT = 4;\n\n/** Empty snapshot used by the terminal registry before live data arrives. */\nexport const EMPTY_FACEWEAR_SNAPSHOT: FacewearSnapshot = {\n profiles: [],\n devices: [],\n connectedCount: 0,\n loading: false,\n error: null,\n};\n\nfunction connectionTone(connected: boolean): SpatialTone {\n return connected ? \"success\" : \"muted\";\n}\n\nexport interface FacewearSpatialViewProps {\n snapshot: FacewearSnapshot;\n /**\n * Dispatch by agent id: `connect:<deviceType>` (connect/manage a profile),\n * `refresh`, `xr-connect`, `xr-status`.\n */\n onAction?: (action: string) => void;\n}\n\nexport function FacewearSpatialView({\n snapshot,\n onAction,\n}: FacewearSpatialViewProps) {\n const dispatch = (action: string) => () => onAction?.(action);\n const { connectedCount } = snapshot;\n const visibleDevices = snapshot.devices.slice(0, VISIBLE_DEVICE_LIMIT);\n const hiddenDevices = Math.max(\n 0,\n snapshot.devices.length - VISIBLE_DEVICE_LIMIT,\n );\n\n return (\n <Card gap={1} padding={1}>\n <HStack gap={1} align=\"center\">\n <Text\n style=\"caption\"\n tone={connectedCount > 0 ? \"success\" : \"muted\"}\n grow={1}\n >\n {connectedCount > 0\n ? `${connectedCount} device${connectedCount === 1 ? \"\" : \"s\"} connected`\n : \"None\"}\n </Text>\n <Text style=\"caption\" tone=\"muted\">\n {snapshot.loading ? \"loading\" : `${snapshot.profiles.length} models`}\n </Text>\n </HStack>\n\n {snapshot.error ? (\n <Text tone=\"danger\" style=\"caption\">\n {snapshot.error}\n </Text>\n ) : null}\n\n {visibleDevices.length > 0 ? (\n <>\n <Divider label=\"active\" />\n <HStack gap={1} wrap>\n {visibleDevices.map((device) => (\n <Text key={device.id} style=\"caption\" tone=\"success\" wrap={false}>\n {device.deviceType ?? device.kind}\n </Text>\n ))}\n {hiddenDevices > 0 ? (\n <Text style=\"caption\" tone=\"muted\">\n +{hiddenDevices}\n </Text>\n ) : null}\n </HStack>\n </>\n ) : null}\n\n <Divider label=\"devices\" />\n {snapshot.profiles.length === 0 ? (\n <Text tone=\"muted\" align=\"center\" style=\"caption\">\n {snapshot.loading ? \"Loading\" : \"None\"}\n </Text>\n ) : (\n <List gap={0}>\n {snapshot.profiles.map((profile) => (\n <HStack\n key={profile.type}\n gap={1}\n align=\"center\"\n agent={`device-${profile.type}`}\n >\n <Text tone={connectionTone(profile.connected)}>\n {profile.connected ? \"[ok]\" : \"[ ]\"}\n </Text>\n <VStack gap={0} grow={1}>\n <Text bold wrap={false}>\n {profile.name}\n </Text>\n <Text style=\"caption\" tone=\"muted\" wrap={false}>\n {profile.manufacturer} · {profile.connectionType}\n </Text>\n </VStack>\n <Button\n variant={profile.connected ? \"outline\" : \"solid\"}\n tone={profile.connected ? \"default\" : \"primary\"}\n agent={`connect:${profile.type}`}\n onPress={dispatch(`connect:${profile.type}`)}\n >\n {profile.connected ? \"Manage\" : \"Connect\"}\n </Button>\n </HStack>\n ))}\n </List>\n )}\n\n <Divider label=\"actions\" />\n <HStack gap={1} wrap>\n <Button\n variant=\"outline\"\n tone=\"default\"\n grow={1}\n agent=\"xr-connect\"\n onPress={dispatch(\"xr-connect\")}\n >\n XR Connect\n </Button>\n <Button\n variant=\"outline\"\n tone=\"default\"\n grow={1}\n agent=\"xr-status\"\n onPress={dispatch(\"xr-status\")}\n >\n XR Status\n </Button>\n <Button\n variant=\"ghost\"\n tone=\"default\"\n agent=\"refresh\"\n onPress={dispatch(\"refresh\")}\n >\n Refresh\n </Button>\n </HStack>\n </Card>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * FacewearView — the single GUI/XR data wrapper for the Facewear surface.
3
+ *
4
+ * It owns the live device data (status fetch + 5s poll, connect routing, XR
5
+ * connect/status links, refresh) and renders the one presentational
6
+ * {@link FacewearSpatialView} inside a {@link SpatialSurface}. Omitting the
7
+ * `modality` prop lets `SpatialSurface` auto-detect GUI vs XR via
8
+ * `window.__elizaXRContext`, so the SAME component serves both surfaces. The TUI
9
+ * surface renders the same `FacewearSpatialView` through the terminal registry
10
+ * (see `register-terminal-view.tsx`).
11
+ *
12
+ * The full-screen GUI dashboard (`../ui/FacewearAppView.tsx`) is unchanged; it
13
+ * stays mounted as the app-shell page while this wrapper drives the
14
+ * manager/XR/TUI surfaces from the same status DTO.
15
+ */
16
+ export declare function FacewearView(): import("react/jsx-runtime").JSX.Element;
17
+ //# sourceMappingURL=FacewearView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FacewearView.d.ts","sourceRoot":"","sources":["../../src/components/FacewearView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA+BH,wBAAgB,YAAY,4CAuE3B"}
@@ -0,0 +1,88 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { SpatialSurface } from "@elizaos/ui/spatial";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ import {
5
+ FacewearSpatialView
6
+ } from "./FacewearSpatialView.js";
7
+ import {
8
+ FACEWEAR_DEVICE_PROFILES,
9
+ isProfileConnected
10
+ } from "./facewear-profiles.js";
11
+ function routeConnect(deviceType) {
12
+ if (typeof window === "undefined") return;
13
+ if (deviceType === "even-realities") {
14
+ window.location.assign("/apps/smartglasses");
15
+ return;
16
+ }
17
+ window.open("/api/xr/connect", "_blank", "noopener,noreferrer");
18
+ }
19
+ function openXrPage(path) {
20
+ if (typeof window === "undefined") return;
21
+ window.open(path, "_blank", "noopener,noreferrer");
22
+ }
23
+ function FacewearView() {
24
+ const [devices, setDevices] = useState([]);
25
+ const [loading, setLoading] = useState(true);
26
+ const [error, setError] = useState(null);
27
+ const fetchStatus = useCallback(async () => {
28
+ try {
29
+ const res = await fetch("/api/facewear/status");
30
+ if (res.ok) {
31
+ const data = await res.json();
32
+ setDevices(data.devices);
33
+ setError(null);
34
+ }
35
+ } catch (err) {
36
+ setError(err instanceof Error ? err.message : String(err));
37
+ } finally {
38
+ setLoading(false);
39
+ }
40
+ }, []);
41
+ const autoLoadedRef = useRef(false);
42
+ useEffect(() => {
43
+ if (!autoLoadedRef.current) {
44
+ autoLoadedRef.current = true;
45
+ void fetchStatus();
46
+ }
47
+ const interval = setInterval(() => void fetchStatus(), 5e3);
48
+ return () => clearInterval(interval);
49
+ }, [fetchStatus]);
50
+ const onAction = useCallback(
51
+ (action) => {
52
+ if (action.startsWith("connect:")) {
53
+ routeConnect(action.slice("connect:".length));
54
+ return;
55
+ }
56
+ switch (action) {
57
+ case "refresh":
58
+ void fetchStatus();
59
+ return;
60
+ case "xr-connect":
61
+ openXrPage("/api/xr/connect");
62
+ return;
63
+ case "xr-status":
64
+ openXrPage("/api/xr/status");
65
+ return;
66
+ }
67
+ },
68
+ [fetchStatus]
69
+ );
70
+ const snapshot = {
71
+ profiles: FACEWEAR_DEVICE_PROFILES.map((profile) => ({
72
+ type: profile.type,
73
+ name: profile.name,
74
+ manufacturer: profile.manufacturer,
75
+ connectionType: profile.connectionType,
76
+ connected: isProfileConnected(profile, devices)
77
+ })),
78
+ devices,
79
+ connectedCount: devices.length,
80
+ loading,
81
+ error
82
+ };
83
+ return /* @__PURE__ */ jsx(SpatialSurface, { children: /* @__PURE__ */ jsx(FacewearSpatialView, { snapshot, onAction }) });
84
+ }
85
+ export {
86
+ FacewearView
87
+ };
88
+ //# sourceMappingURL=FacewearView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/FacewearView.tsx"],"sourcesContent":["/**\n * FacewearView — the single GUI/XR data wrapper for the Facewear surface.\n *\n * It owns the live device data (status fetch + 5s poll, connect routing, XR\n * connect/status links, refresh) and renders the one presentational\n * {@link FacewearSpatialView} inside a {@link SpatialSurface}. Omitting the\n * `modality` prop lets `SpatialSurface` auto-detect GUI vs XR via\n * `window.__elizaXRContext`, so the SAME component serves both surfaces. The TUI\n * surface renders the same `FacewearSpatialView` through the terminal registry\n * (see `register-terminal-view.tsx`).\n *\n * The full-screen GUI dashboard (`../ui/FacewearAppView.tsx`) is unchanged; it\n * stays mounted as the app-shell page while this wrapper drives the\n * manager/XR/TUI surfaces from the same status DTO.\n */\n\nimport { SpatialSurface } from \"@elizaos/ui/spatial\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { FacewearDeviceType } from \"../devices/registry.js\";\nimport {\n type FacewearSnapshot,\n FacewearSpatialView,\n} from \"./FacewearSpatialView.js\";\nimport {\n type ConnectedDevice,\n FACEWEAR_DEVICE_PROFILES,\n type FacewearStatusResponse,\n isProfileConnected,\n} from \"./facewear-profiles.js\";\n\n/** Route a connect/manage request the same way the legacy dashboard does. */\nfunction routeConnect(deviceType: FacewearDeviceType): void {\n if (typeof window === \"undefined\") return;\n if (deviceType === \"even-realities\") {\n window.location.assign(\"/apps/smartglasses\");\n return;\n }\n window.open(\"/api/xr/connect\", \"_blank\", \"noopener,noreferrer\");\n}\n\nfunction openXrPage(path: string): void {\n if (typeof window === \"undefined\") return;\n window.open(path, \"_blank\", \"noopener,noreferrer\");\n}\n\nexport function FacewearView() {\n const [devices, setDevices] = useState<ConnectedDevice[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n const fetchStatus = useCallback(async (): Promise<void> => {\n try {\n const res = await fetch(\"/api/facewear/status\");\n if (res.ok) {\n const data = (await res.json()) as FacewearStatusResponse;\n setDevices(data.devices);\n setError(null);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setLoading(false);\n }\n }, []);\n\n // Load on mount, then keep fresh with a quiet 5s poll. Torn down on unmount.\n const autoLoadedRef = useRef(false);\n useEffect(() => {\n if (!autoLoadedRef.current) {\n autoLoadedRef.current = true;\n void fetchStatus();\n }\n const interval = setInterval(() => void fetchStatus(), 5000);\n return () => clearInterval(interval);\n }, [fetchStatus]);\n\n const onAction = useCallback(\n (action: string) => {\n if (action.startsWith(\"connect:\")) {\n routeConnect(action.slice(\"connect:\".length) as FacewearDeviceType);\n return;\n }\n switch (action) {\n case \"refresh\":\n void fetchStatus();\n return;\n case \"xr-connect\":\n openXrPage(\"/api/xr/connect\");\n return;\n case \"xr-status\":\n openXrPage(\"/api/xr/status\");\n return;\n }\n },\n [fetchStatus],\n );\n\n const snapshot: FacewearSnapshot = {\n profiles: FACEWEAR_DEVICE_PROFILES.map((profile) => ({\n type: profile.type,\n name: profile.name,\n manufacturer: profile.manufacturer,\n connectionType: profile.connectionType,\n connected: isProfileConnected(profile, devices),\n })),\n devices,\n connectedCount: devices.length,\n loading,\n error,\n };\n\n return (\n <SpatialSurface>\n <FacewearSpatialView snapshot={snapshot} onAction={onAction} />\n </SpatialSurface>\n );\n}\n"],"mappings":"AAiHM;AAjGN,SAAS,sBAAsB;AAC/B,SAAS,aAAa,WAAW,QAAQ,gBAAgB;AAEzD;AAAA,EAEE;AAAA,OACK;AACP;AAAA,EAEE;AAAA,EAEA;AAAA,OACK;AAGP,SAAS,aAAa,YAAsC;AAC1D,MAAI,OAAO,WAAW,YAAa;AACnC,MAAI,eAAe,kBAAkB;AACnC,WAAO,SAAS,OAAO,oBAAoB;AAC3C;AAAA,EACF;AACA,SAAO,KAAK,mBAAmB,UAAU,qBAAqB;AAChE;AAEA,SAAS,WAAW,MAAoB;AACtC,MAAI,OAAO,WAAW,YAAa;AACnC,SAAO,KAAK,MAAM,UAAU,qBAAqB;AACnD;AAEO,SAAS,eAAe;AAC7B,QAAM,CAAC,SAAS,UAAU,IAAI,SAA4B,CAAC,CAAC;AAC5D,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AAEtD,QAAM,cAAc,YAAY,YAA2B;AACzD,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,sBAAsB;AAC9C,UAAI,IAAI,IAAI;AACV,cAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,mBAAW,KAAK,OAAO;AACvB,iBAAS,IAAI;AAAA,MACf;AAAA,IACF,SAAS,KAAK;AACZ,eAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC3D,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,QAAM,gBAAgB,OAAO,KAAK;AAClC,YAAU,MAAM;AACd,QAAI,CAAC,cAAc,SAAS;AAC1B,oBAAc,UAAU;AACxB,WAAK,YAAY;AAAA,IACnB;AACA,UAAM,WAAW,YAAY,MAAM,KAAK,YAAY,GAAG,GAAI;AAC3D,WAAO,MAAM,cAAc,QAAQ;AAAA,EACrC,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,WAAW;AAAA,IACf,CAAC,WAAmB;AAClB,UAAI,OAAO,WAAW,UAAU,GAAG;AACjC,qBAAa,OAAO,MAAM,WAAW,MAAM,CAAuB;AAClE;AAAA,MACF;AACA,cAAQ,QAAQ;AAAA,QACd,KAAK;AACH,eAAK,YAAY;AACjB;AAAA,QACF,KAAK;AACH,qBAAW,iBAAiB;AAC5B;AAAA,QACF,KAAK;AACH,qBAAW,gBAAgB;AAC3B;AAAA,MACJ;AAAA,IACF;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,WAA6B;AAAA,IACjC,UAAU,yBAAyB,IAAI,CAAC,aAAa;AAAA,MACnD,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd,cAAc,QAAQ;AAAA,MACtB,gBAAgB,QAAQ;AAAA,MACxB,WAAW,mBAAmB,SAAS,OAAO;AAAA,IAChD,EAAE;AAAA,IACF;AAAA,IACA,gBAAgB,QAAQ;AAAA,IACxB;AAAA,IACA;AAAA,EACF;AAEA,SACE,oBAAC,kBACC,8BAAC,uBAAoB,UAAoB,UAAoB,GAC/D;AAEJ;","names":[]}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * SmartglassesPanelView — the single GUI/XR data wrapper for the Smartglasses
3
+ * operator panel.
4
+ *
5
+ * It owns a live subset of the smartglasses diagnostics (the computed
6
+ * {@link HardwareReport} the full dashboard publishes on
7
+ * `window.facewearSmartglassesReport`, plus the headset connected-state from
8
+ * `/api/facewear/status`) and renders the one presentational
9
+ * {@link SmartglassesSpatialView} inside a {@link SpatialSurface}. Omitting the
10
+ * `modality` prop lets `SpatialSurface` auto-detect GUI vs XR, so the SAME
11
+ * component serves both surfaces. The TUI surface renders the same
12
+ * `SmartglassesSpatialView` through the terminal registry (see
13
+ * `register-terminal-view.tsx`).
14
+ *
15
+ * The full BLE/transport dashboard (`../ui/SmartglassesView.tsx`) is unchanged;
16
+ * it stays mounted as the app-shell page (and is what publishes the live report
17
+ * this panel reads). Operator actions (`connect`, `run-check`, Wi-Fi, mic,
18
+ * display) are dispatched to the same native bridge the dashboard drives, so the
19
+ * panel is a real control surface rather than a static mirror.
20
+ */
21
+ export declare function SmartglassesPanelView(): import("react/jsx-runtime").JSX.Element;
22
+ //# sourceMappingURL=SmartglassesPanelView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SmartglassesPanelView.d.ts","sourceRoot":"","sources":["../../src/components/SmartglassesPanelView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAuDH,wBAAgB,qBAAqB,4CAiHpC"}
@@ -0,0 +1,140 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { SpatialSurface } from "@elizaos/ui/spatial";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ import {
5
+ callWifiBridge,
6
+ formatWifiStatus,
7
+ parseWifiNetworks
8
+ } from "../ui/SmartglassesView.helpers.js";
9
+ import {
10
+ SmartglassesSpatialView
11
+ } from "./SmartglassesSpatialView.js";
12
+ const DEFAULT_REPORT = {
13
+ ok: false,
14
+ generatedAt: "",
15
+ transport: null,
16
+ connected: false,
17
+ lenses: { left: "idle", right: "idle" },
18
+ scanDiagnosis: "not_scanned",
19
+ physicalBlocker: "not_connected",
20
+ setupHint: "Connect both left and right lenses as one headset before running validation.",
21
+ nextAction: "Connect Headset",
22
+ serialNumber: null,
23
+ tests: {},
24
+ missingEvidence: [],
25
+ events: [],
26
+ writes: [],
27
+ audio: [],
28
+ wifi: { available: false, status: "Not checked", networks: [] },
29
+ headsetState: {
30
+ physical: null,
31
+ battery: null,
32
+ batteryLevels: {},
33
+ device: null
34
+ }
35
+ };
36
+ function getBridge() {
37
+ if (typeof window === "undefined") return null;
38
+ return window.__mentraBridge ?? window.__evenBridge ?? null;
39
+ }
40
+ function readPublishedReport() {
41
+ if (typeof window === "undefined") return DEFAULT_REPORT;
42
+ return window.facewearSmartglassesReport ?? DEFAULT_REPORT;
43
+ }
44
+ function SmartglassesPanelView() {
45
+ const [report, setReport] = useState(readPublishedReport);
46
+ const [micEnabled, setMicEnabled] = useState(false);
47
+ const [activePlatform, setActivePlatform] = useState("desktop");
48
+ const [busy, setBusy] = useState(null);
49
+ const [error, setError] = useState(null);
50
+ const wifiSsid = report.wifi.networks[0] ?? "";
51
+ const wifiPassword = "";
52
+ const testText = "Smartglasses display test.";
53
+ const autoLoadedRef = useRef(false);
54
+ useEffect(() => {
55
+ const sync = () => setReport(readPublishedReport());
56
+ if (!autoLoadedRef.current) {
57
+ autoLoadedRef.current = true;
58
+ sync();
59
+ }
60
+ const interval = setInterval(sync, 5e3);
61
+ return () => clearInterval(interval);
62
+ }, []);
63
+ const runBridge = useCallback(
64
+ async (label, command, payload) => {
65
+ const bridge = getBridge();
66
+ if (!bridge) {
67
+ setError("Unavailable");
68
+ return;
69
+ }
70
+ setBusy(label);
71
+ setError(null);
72
+ try {
73
+ const result = await callWifiBridge(bridge, command, payload);
74
+ const networks = parseWifiNetworks(result);
75
+ setReport((current) => ({
76
+ ...current,
77
+ wifi: {
78
+ available: true,
79
+ status: formatWifiStatus(result, current.wifi.status),
80
+ networks: networks.length > 0 ? networks : current.wifi.networks
81
+ }
82
+ }));
83
+ } catch (err) {
84
+ setError(err instanceof Error ? err.message : String(err));
85
+ } finally {
86
+ setBusy(null);
87
+ }
88
+ },
89
+ []
90
+ );
91
+ const onAction = useCallback(
92
+ (action) => {
93
+ if (action.startsWith("platform:")) {
94
+ setActivePlatform(
95
+ action.slice("platform:".length)
96
+ );
97
+ return;
98
+ }
99
+ switch (action) {
100
+ case "mic-toggle":
101
+ setMicEnabled((prev) => !prev);
102
+ return;
103
+ case "wifi-scan":
104
+ void runBridge("wifi-scan", "request_wifi_scan");
105
+ return;
106
+ case "wifi-status":
107
+ void runBridge("wifi-status", "request_wifi_status");
108
+ return;
109
+ case "wifi-save":
110
+ void runBridge("wifi-save", "set_wifi_credentials", {
111
+ ssid: wifiSsid.trim(),
112
+ password: wifiPassword
113
+ });
114
+ return;
115
+ case "connect":
116
+ case "run-check":
117
+ case "display-test":
118
+ case "clear-display":
119
+ setError("Open Smartglasses.");
120
+ return;
121
+ }
122
+ },
123
+ [runBridge, wifiSsid]
124
+ );
125
+ const snapshot = {
126
+ report,
127
+ micEnabled,
128
+ wifiSsid,
129
+ wifiPassword,
130
+ testText,
131
+ activePlatform,
132
+ busy,
133
+ error
134
+ };
135
+ return /* @__PURE__ */ jsx(SpatialSurface, { children: /* @__PURE__ */ jsx(SmartglassesSpatialView, { snapshot, onAction }) });
136
+ }
137
+ export {
138
+ SmartglassesPanelView
139
+ };
140
+ //# sourceMappingURL=SmartglassesPanelView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/SmartglassesPanelView.tsx"],"sourcesContent":["/**\n * SmartglassesPanelView — the single GUI/XR data wrapper for the Smartglasses\n * operator panel.\n *\n * It owns a live subset of the smartglasses diagnostics (the computed\n * {@link HardwareReport} the full dashboard publishes on\n * `window.facewearSmartglassesReport`, plus the headset connected-state from\n * `/api/facewear/status`) and renders the one presentational\n * {@link SmartglassesSpatialView} inside a {@link SpatialSurface}. Omitting the\n * `modality` prop lets `SpatialSurface` auto-detect GUI vs XR, so the SAME\n * component serves both surfaces. The TUI surface renders the same\n * `SmartglassesSpatialView` through the terminal registry (see\n * `register-terminal-view.tsx`).\n *\n * The full BLE/transport dashboard (`../ui/SmartglassesView.tsx`) is unchanged;\n * it stays mounted as the app-shell page (and is what publishes the live report\n * this panel reads). Operator actions (`connect`, `run-check`, Wi-Fi, mic,\n * display) are dispatched to the same native bridge the dashboard drives, so the\n * panel is a real control surface rather than a static mirror.\n */\n\nimport { SpatialSurface } from \"@elizaos/ui/spatial\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n callWifiBridge,\n formatWifiStatus,\n type HardwareReport,\n parseWifiNetworks,\n type SmartglassesBridge,\n} from \"../ui/SmartglassesView.helpers.js\";\nimport {\n type SmartglassesPlatform,\n type SmartglassesSnapshot,\n SmartglassesSpatialView,\n} from \"./SmartglassesSpatialView.js\";\n\n/** Disconnected default report until the dashboard publishes a live one. */\nconst DEFAULT_REPORT: HardwareReport = {\n ok: false,\n generatedAt: \"\",\n transport: null,\n connected: false,\n lenses: { left: \"idle\", right: \"idle\" },\n scanDiagnosis: \"not_scanned\",\n physicalBlocker: \"not_connected\",\n setupHint:\n \"Connect both left and right lenses as one headset before running validation.\",\n nextAction: \"Connect Headset\",\n serialNumber: null,\n tests: {},\n missingEvidence: [],\n events: [],\n writes: [],\n audio: [],\n wifi: { available: false, status: \"Not checked\", networks: [] },\n headsetState: {\n physical: null,\n battery: null,\n batteryLevels: {},\n device: null,\n },\n};\n\nfunction getBridge(): SmartglassesBridge | null {\n if (typeof window === \"undefined\") return null;\n return window.__mentraBridge ?? window.__evenBridge ?? null;\n}\n\n/** Read the live report the full dashboard publishes, falling back to default. */\nfunction readPublishedReport(): HardwareReport {\n if (typeof window === \"undefined\") return DEFAULT_REPORT;\n return window.facewearSmartglassesReport ?? DEFAULT_REPORT;\n}\n\nexport function SmartglassesPanelView() {\n const [report, setReport] = useState<HardwareReport>(readPublishedReport);\n const [micEnabled, setMicEnabled] = useState(false);\n const [activePlatform, setActivePlatform] =\n useState<SmartglassesPlatform>(\"desktop\");\n const [busy, setBusy] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n // SSID / password / display text are typed in the full dashboard; the panel\n // mirrors the dashboard's published values so its Wi-Fi/display Fields stay in\n // sync (and `wifi-save` forwards them to the same bridge).\n const wifiSsid = report.wifi.networks[0] ?? \"\";\n const wifiPassword = \"\";\n const testText = \"Smartglasses display test.\";\n\n // Poll the published report so the panel tracks the dashboard's live state\n // (the dashboard owns the transport; this panel mirrors + drives the bridge).\n const autoLoadedRef = useRef(false);\n useEffect(() => {\n const sync = () => setReport(readPublishedReport());\n if (!autoLoadedRef.current) {\n autoLoadedRef.current = true;\n sync();\n }\n const interval = setInterval(sync, 5000);\n return () => clearInterval(interval);\n }, []);\n\n const runBridge = useCallback(\n async (\n label: string,\n command: string,\n payload?: Record<string, unknown>,\n ) => {\n const bridge = getBridge();\n if (!bridge) {\n setError(\"Unavailable\");\n return;\n }\n setBusy(label);\n setError(null);\n try {\n const result = await callWifiBridge(bridge, command, payload);\n const networks = parseWifiNetworks(result);\n setReport((current) => ({\n ...current,\n wifi: {\n available: true,\n status: formatWifiStatus(result, current.wifi.status),\n networks: networks.length > 0 ? networks : current.wifi.networks,\n },\n }));\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setBusy(null);\n }\n },\n [],\n );\n\n const onAction = useCallback(\n (action: string) => {\n if (action.startsWith(\"platform:\")) {\n setActivePlatform(\n action.slice(\"platform:\".length) as SmartglassesPlatform,\n );\n return;\n }\n switch (action) {\n case \"mic-toggle\":\n setMicEnabled((prev) => !prev);\n return;\n case \"wifi-scan\":\n void runBridge(\"wifi-scan\", \"request_wifi_scan\");\n return;\n case \"wifi-status\":\n void runBridge(\"wifi-status\", \"request_wifi_status\");\n return;\n case \"wifi-save\":\n void runBridge(\"wifi-save\", \"set_wifi_credentials\", {\n ssid: wifiSsid.trim(),\n password: wifiPassword,\n });\n return;\n case \"connect\":\n case \"run-check\":\n case \"display-test\":\n case \"clear-display\":\n // The transport is owned by the full dashboard; surface the next step.\n setError(\"Open Smartglasses.\");\n return;\n }\n },\n [runBridge, wifiSsid],\n );\n\n const snapshot: SmartglassesSnapshot = {\n report,\n micEnabled,\n wifiSsid,\n wifiPassword,\n testText,\n activePlatform,\n busy,\n error,\n };\n\n return (\n <SpatialSurface>\n <SmartglassesSpatialView snapshot={snapshot} onAction={onAction} />\n </SpatialSurface>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * SmartglassesSpatialView - the Even Realities smartglasses diagnostics surface
3
+ * authored once with the spatial vocabulary, so it renders correctly wherever
4
+ * it is displayed:
5
+ *
6
+ * - GUI / XR - mounted in `<SpatialSurface>` (DOM; XR scales up).
7
+ * - TUI - rendered to real terminal lines by the agent terminal, via
8
+ * `registerSpatialTerminalView` (see `register-terminal-view.tsx`).
9
+ *
10
+ * It is purely presentational (a snapshot + an action callback in, primitives
11
+ * out) and imports only the cross-modality primitives plus a type-only view of
12
+ * the smartglasses report (`HardwareReport`, `GlassSide`), so it is safe to
13
+ * render in the Node agent process where the terminal lives (no transport or
14
+ * BLE runtime import).
15
+ *
16
+ * The full GUI dashboard (`SmartglassesView.tsx`) is unchanged; this view is the
17
+ * shared operator panel that reads the same computed `HardwareReport` the GUI
18
+ * builds, plus the live state the GUI tracks (Wi-Fi, mic, test text, events).
19
+ */
20
+ import type { HardwareReport } from "../ui/SmartglassesView.helpers.js";
21
+ export type SmartglassesPlatform = "desktop" | "ios" | "android";
22
+ export interface SmartglassesSnapshot {
23
+ /** The computed hardware report - identical shape to the GUI's `report`. */
24
+ report: HardwareReport;
25
+ /** Live operator state the GUI tracks alongside the report. */
26
+ micEnabled: boolean;
27
+ wifiSsid: string;
28
+ wifiPassword: string;
29
+ testText: string;
30
+ activePlatform: SmartglassesPlatform;
31
+ /** Label of the in-flight operation, or null when idle. */
32
+ busy: string | null;
33
+ /** Last operator-facing error, or null. */
34
+ error: string | null;
35
+ }
36
+ export interface SmartglassesSpatialViewProps {
37
+ snapshot: SmartglassesSnapshot;
38
+ /**
39
+ * Dispatch by agent id: `connect`, `run-check`, `clear-display`,
40
+ * `display-test`, `mic-toggle`, `wifi-scan`, `wifi-status`, `wifi-save`,
41
+ * `platform:<desktop|ios|android>`.
42
+ */
43
+ onAction?: (action: string) => void;
44
+ }
45
+ export declare function SmartglassesSpatialView({ snapshot, onAction, }: SmartglassesSpatialViewProps): import("react/jsx-runtime").JSX.Element;
46
+ //# sourceMappingURL=SmartglassesSpatialView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SmartglassesSpatialView.d.ts","sourceRoot":"","sources":["../../src/components/SmartglassesSpatialView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAaH,OAAO,KAAK,EACV,cAAc,EAEf,MAAM,mCAAmC,CAAC;AAO3C,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,KAAK,GAAG,SAAS,CAAC;AAEjE,MAAM,WAAW,oBAAoB;IACnC,4EAA4E;IAC5E,MAAM,EAAE,cAAc,CAAC;IACvB,+DAA+D;IAC/D,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,oBAAoB,CAAC;IACrC,2DAA2D;IAC3D,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AA8CD,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,oBAAoB,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACR,QAAQ,GACT,EAAE,4BAA4B,2CAuO9B"}
@@ -0,0 +1,240 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import {
3
+ Button,
4
+ Card,
5
+ Divider,
6
+ Field,
7
+ HStack,
8
+ List,
9
+ Text
10
+ } from "@elizaos/ui/spatial";
11
+ const VISIBLE_TEST_LIMIT = 8;
12
+ const VISIBLE_EVENT_LIMIT = 12;
13
+ const VISIBLE_WIFI_LIMIT = 5;
14
+ function lensTone(state) {
15
+ switch (state) {
16
+ case "connected":
17
+ return "success";
18
+ case "failed":
19
+ return "danger";
20
+ case "prompting":
21
+ return "warning";
22
+ default:
23
+ return "muted";
24
+ }
25
+ }
26
+ function lensMark(state) {
27
+ switch (state) {
28
+ case "connected":
29
+ return "[ok]";
30
+ case "failed":
31
+ return "[x]";
32
+ case "prompting":
33
+ return "[..]";
34
+ default:
35
+ return "[ ]";
36
+ }
37
+ }
38
+ function passTone(pass) {
39
+ return pass ? "success" : "muted";
40
+ }
41
+ function passMark(pass) {
42
+ return pass ? "[ok]" : "[ ]";
43
+ }
44
+ function batterySummary(levels) {
45
+ const parts = [];
46
+ if (typeof levels.left === "number") parts.push(`L ${levels.left}%`);
47
+ if (typeof levels.right === "number") parts.push(`R ${levels.right}%`);
48
+ return parts.length > 0 ? parts.join(" ") : null;
49
+ }
50
+ function SmartglassesSpatialView({
51
+ snapshot,
52
+ onAction
53
+ }) {
54
+ const dispatch = (action) => () => onAction?.(action);
55
+ const { report } = snapshot;
56
+ const testEntries = Object.entries(report.tests);
57
+ const hiddenTests = Math.max(0, testEntries.length - VISIBLE_TEST_LIMIT);
58
+ const hiddenEvents = Math.max(0, report.events.length - VISIBLE_EVENT_LIMIT);
59
+ const hiddenWifi = Math.max(
60
+ 0,
61
+ report.wifi.networks.length - VISIBLE_WIFI_LIMIT
62
+ );
63
+ const battery = batterySummary(report.headsetState.batteryLevels);
64
+ const eventStart = Math.max(0, report.events.length - VISIBLE_EVENT_LIMIT);
65
+ const recentEvents = report.events.slice(eventStart).map((event, offset) => ({ ...event, key: eventStart + offset })).reverse();
66
+ return /* @__PURE__ */ jsxs(Card, { gap: 1, padding: 1, children: [
67
+ /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", children: [
68
+ /* @__PURE__ */ jsx(
69
+ Text,
70
+ {
71
+ style: "caption",
72
+ tone: report.ok ? "success" : report.connected ? "warning" : "danger",
73
+ grow: 1,
74
+ children: report.ok ? "validated" : report.connected ? "connected" : "disconnected"
75
+ }
76
+ ),
77
+ /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", children: snapshot.busy ? snapshot.busy : report.transport ?? "no transport" })
78
+ ] }),
79
+ snapshot.error ? /* @__PURE__ */ jsx(Text, { tone: "danger", style: "caption", children: snapshot.error }) : null,
80
+ /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", children: [
81
+ /* @__PURE__ */ jsxs(Text, { style: "caption", tone: lensTone(report.lenses.left), grow: 1, children: [
82
+ lensMark(report.lenses.left),
83
+ " left"
84
+ ] }),
85
+ /* @__PURE__ */ jsxs(Text, { style: "caption", tone: lensTone(report.lenses.right), grow: 1, children: [
86
+ lensMark(report.lenses.right),
87
+ " right"
88
+ ] })
89
+ ] }),
90
+ /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", children: [
91
+ /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", grow: 1, children: report.serialNumber ? `sn ${report.serialNumber}` : "sn unknown" }),
92
+ battery ? /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", children: battery }) : null
93
+ ] }),
94
+ report.setupHint ? /* @__PURE__ */ jsx(Text, { style: "caption", tone: "warning", children: report.setupHint }) : null,
95
+ /* @__PURE__ */ jsx(Divider, { label: "diagnostics" }),
96
+ /* @__PURE__ */ jsx(List, { gap: 0, children: testEntries.slice(0, VISIBLE_TEST_LIMIT).map(([name, pass]) => /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", agent: `test-${name}`, children: [
97
+ /* @__PURE__ */ jsx(Text, { tone: passTone(pass), children: passMark(pass) }),
98
+ /* @__PURE__ */ jsx(Text, { style: "caption", grow: 1, wrap: false, children: name })
99
+ ] }, name)) }),
100
+ hiddenTests > 0 ? /* @__PURE__ */ jsxs(Text, { style: "caption", tone: "muted", children: [
101
+ "+",
102
+ hiddenTests,
103
+ " checks"
104
+ ] }) : null,
105
+ /* @__PURE__ */ jsx(Divider, { label: "controls" }),
106
+ /* @__PURE__ */ jsxs(HStack, { gap: 1, wrap: true, children: [
107
+ /* @__PURE__ */ jsx(
108
+ Button,
109
+ {
110
+ grow: 1,
111
+ tone: report.connected ? "default" : "primary",
112
+ variant: report.connected ? "outline" : "solid",
113
+ agent: "connect",
114
+ onPress: dispatch("connect"),
115
+ children: report.connected ? "Reconnect" : "Connect"
116
+ }
117
+ ),
118
+ /* @__PURE__ */ jsx(
119
+ Button,
120
+ {
121
+ variant: "outline",
122
+ tone: "default",
123
+ grow: 1,
124
+ agent: "run-check",
125
+ onPress: dispatch("run-check"),
126
+ children: "Run Check"
127
+ }
128
+ ),
129
+ /* @__PURE__ */ jsx(
130
+ Button,
131
+ {
132
+ variant: snapshot.micEnabled ? "solid" : "outline",
133
+ tone: snapshot.micEnabled ? "success" : "default",
134
+ agent: "mic-toggle",
135
+ onPress: dispatch("mic-toggle"),
136
+ children: snapshot.micEnabled ? "Mic on" : "Mic off"
137
+ }
138
+ )
139
+ ] }),
140
+ /* @__PURE__ */ jsx(
141
+ Field,
142
+ {
143
+ label: "Display text",
144
+ value: snapshot.testText,
145
+ placeholder: "Text to send to both lenses",
146
+ agent: "test-text"
147
+ }
148
+ ),
149
+ /* @__PURE__ */ jsxs(HStack, { gap: 1, wrap: true, children: [
150
+ /* @__PURE__ */ jsx(
151
+ Button,
152
+ {
153
+ grow: 1,
154
+ agent: "display-test",
155
+ onPress: dispatch("display-test"),
156
+ children: "Send Display"
157
+ }
158
+ ),
159
+ /* @__PURE__ */ jsx(
160
+ Button,
161
+ {
162
+ variant: "ghost",
163
+ tone: "danger",
164
+ agent: "clear-display",
165
+ onPress: dispatch("clear-display"),
166
+ children: "Clear"
167
+ }
168
+ )
169
+ ] }),
170
+ /* @__PURE__ */ jsx(Divider, { label: "wi-fi" }),
171
+ /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", children: [
172
+ /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", grow: 1, wrap: false, children: report.wifi.status }),
173
+ /* @__PURE__ */ jsx(Text, { style: "caption", tone: report.wifi.available ? "muted" : "danger", children: report.wifi.available ? "bridge" : "no bridge" })
174
+ ] }),
175
+ /* @__PURE__ */ jsx(
176
+ Field,
177
+ {
178
+ label: "SSID",
179
+ value: snapshot.wifiSsid,
180
+ placeholder: "Network name",
181
+ agent: "wifi-ssid"
182
+ }
183
+ ),
184
+ /* @__PURE__ */ jsx(
185
+ Field,
186
+ {
187
+ label: "Password",
188
+ kind: "password",
189
+ value: snapshot.wifiPassword,
190
+ placeholder: "Network password",
191
+ agent: "wifi-password"
192
+ }
193
+ ),
194
+ /* @__PURE__ */ jsxs(HStack, { gap: 1, wrap: true, children: [
195
+ /* @__PURE__ */ jsx(
196
+ Button,
197
+ {
198
+ variant: "outline",
199
+ tone: "default",
200
+ grow: 1,
201
+ agent: "wifi-scan",
202
+ onPress: dispatch("wifi-scan"),
203
+ children: "Scan"
204
+ }
205
+ ),
206
+ /* @__PURE__ */ jsx(
207
+ Button,
208
+ {
209
+ variant: "outline",
210
+ tone: "default",
211
+ grow: 1,
212
+ agent: "wifi-status",
213
+ onPress: dispatch("wifi-status"),
214
+ children: "Status"
215
+ }
216
+ ),
217
+ /* @__PURE__ */ jsx(Button, { grow: 1, agent: "wifi-save", onPress: dispatch("wifi-save"), children: "Save Wi-Fi" })
218
+ ] }),
219
+ report.wifi.networks.length === 0 ? /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", children: "None" }) : /* @__PURE__ */ jsx(List, { gap: 0, children: report.wifi.networks.slice(0, VISIBLE_WIFI_LIMIT).map((network) => /* @__PURE__ */ jsx(Text, { style: "caption", wrap: false, children: network }, network)) }),
220
+ hiddenWifi > 0 ? /* @__PURE__ */ jsxs(Text, { style: "caption", tone: "muted", children: [
221
+ "+",
222
+ hiddenWifi,
223
+ " more"
224
+ ] }) : null,
225
+ /* @__PURE__ */ jsx(Divider, { label: "events" }),
226
+ report.events.length === 0 ? /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", align: "center", children: "None" }) : /* @__PURE__ */ jsx(List, { gap: 0, children: recentEvents.map((event) => /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", children: [
227
+ /* @__PURE__ */ jsx(Text, { style: "caption", tone: "primary", wrap: false, children: event.type }),
228
+ /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", grow: 1, wrap: false, children: event.detail })
229
+ ] }, event.key)) }),
230
+ hiddenEvents > 0 ? /* @__PURE__ */ jsxs(Text, { style: "caption", tone: "muted", children: [
231
+ "+",
232
+ hiddenEvents,
233
+ " older events"
234
+ ] }) : null
235
+ ] });
236
+ }
237
+ export {
238
+ SmartglassesSpatialView
239
+ };
240
+ //# sourceMappingURL=SmartglassesSpatialView.js.map