@elizaos/plugin-facewear 2.0.3-beta.6 → 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.
- package/dist/actions/display-text.d.ts +4 -0
- package/dist/actions/display-text.d.ts.map +1 -0
- package/dist/actions/display-text.js +90 -0
- package/dist/actions/display-text.js.map +1 -0
- package/dist/actions/facewear-connect.d.ts +3 -0
- package/dist/actions/facewear-connect.d.ts.map +1 -0
- package/dist/actions/facewear-connect.js +70 -0
- package/dist/actions/facewear-connect.js.map +1 -0
- package/dist/actions/facewear-control.d.ts +4 -0
- package/dist/actions/facewear-control.d.ts.map +1 -0
- package/dist/actions/facewear-control.js +627 -0
- package/dist/actions/facewear-control.js.map +1 -0
- package/dist/actions/facewear-debug.d.ts +3 -0
- package/dist/actions/facewear-debug.d.ts.map +1 -0
- package/dist/actions/facewear-debug.js +62 -0
- package/dist/actions/facewear-debug.js.map +1 -0
- package/dist/actions/facewear-status.d.ts +4 -0
- package/dist/actions/facewear-status.d.ts.map +1 -0
- package/dist/actions/facewear-status.js +66 -0
- package/dist/actions/facewear-status.js.map +1 -0
- package/dist/actions/microphone.d.ts +4 -0
- package/dist/actions/microphone.d.ts.map +1 -0
- package/dist/actions/microphone.js +63 -0
- package/dist/actions/microphone.js.map +1 -0
- package/dist/actions/view-actions.d.ts +23 -0
- package/dist/actions/view-actions.d.ts.map +1 -0
- package/dist/actions/view-actions.js +314 -0
- package/dist/actions/view-actions.js.map +1 -0
- package/dist/actions/vision-query.d.ts +4 -0
- package/dist/actions/vision-query.d.ts.map +1 -0
- package/dist/actions/vision-query.js +41 -0
- package/dist/actions/vision-query.js.map +1 -0
- package/dist/actions/xr-view-actions.d.ts +14 -0
- package/dist/actions/xr-view-actions.d.ts.map +1 -0
- package/dist/actions/xr-view-actions.js +29 -0
- package/dist/actions/xr-view-actions.js.map +1 -0
- package/dist/components/FacewearSpatialView.d.ts +50 -0
- package/dist/components/FacewearSpatialView.d.ts.map +1 -0
- package/dist/components/FacewearSpatialView.js +129 -0
- package/dist/components/FacewearSpatialView.js.map +1 -0
- package/dist/components/FacewearView.d.ts +17 -0
- package/dist/components/FacewearView.d.ts.map +1 -0
- package/dist/components/FacewearView.js +88 -0
- package/dist/components/FacewearView.js.map +1 -0
- package/dist/components/SmartglassesPanelView.d.ts +22 -0
- package/dist/components/SmartglassesPanelView.d.ts.map +1 -0
- package/dist/components/SmartglassesPanelView.js +140 -0
- package/dist/components/SmartglassesPanelView.js.map +1 -0
- package/dist/components/SmartglassesSpatialView.d.ts +46 -0
- package/dist/components/SmartglassesSpatialView.d.ts.map +1 -0
- package/dist/components/SmartglassesSpatialView.js +240 -0
- package/dist/components/SmartglassesSpatialView.js.map +1 -0
- package/dist/components/facewear-profiles.d.ts +27 -0
- package/dist/components/facewear-profiles.d.ts.map +1 -0
- package/dist/components/facewear-profiles.js +40 -0
- package/dist/components/facewear-profiles.js.map +1 -0
- package/dist/devices/apple-vision-pro.d.ts +7 -0
- package/dist/devices/apple-vision-pro.d.ts.map +1 -0
- package/dist/devices/apple-vision-pro.js +21 -0
- package/dist/devices/apple-vision-pro.js.map +1 -0
- package/dist/devices/even-realities.d.ts +7 -0
- package/dist/devices/even-realities.d.ts.map +1 -0
- package/dist/devices/even-realities.js +13 -0
- package/dist/devices/even-realities.js.map +1 -0
- package/dist/devices/meta-quest.d.ts +5 -0
- package/dist/devices/meta-quest.d.ts.map +1 -0
- package/dist/devices/meta-quest.js +21 -0
- package/dist/devices/meta-quest.js.map +1 -0
- package/dist/devices/registry.d.ts +19 -0
- package/dist/devices/registry.d.ts.map +1 -0
- package/dist/devices/registry.js +96 -0
- package/dist/devices/registry.js.map +1 -0
- package/dist/devices/xreal.d.ts +7 -0
- package/dist/devices/xreal.d.ts.map +1 -0
- package/dist/devices/xreal.js +19 -0
- package/dist/devices/xreal.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +260 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol/smartglasses.d.ts +306 -0
- package/dist/protocol/smartglasses.d.ts.map +1 -0
- package/dist/protocol/smartglasses.js +1485 -0
- package/dist/protocol/smartglasses.js.map +1 -0
- package/dist/protocol/xr.d.ts +137 -0
- package/dist/protocol/xr.d.ts.map +1 -0
- package/dist/protocol/xr.js +18 -0
- package/dist/protocol/xr.js.map +1 -0
- package/dist/providers/facewear-context.d.ts +3 -0
- package/dist/providers/facewear-context.d.ts.map +1 -0
- package/dist/providers/facewear-context.js +59 -0
- package/dist/providers/facewear-context.js.map +1 -0
- package/dist/providers/smartglasses-status.d.ts +3 -0
- package/dist/providers/smartglasses-status.d.ts.map +1 -0
- package/dist/providers/smartglasses-status.js +33 -0
- package/dist/providers/smartglasses-status.js.map +1 -0
- package/dist/register-terminal-view.d.ts +21 -0
- package/dist/register-terminal-view.d.ts.map +1 -0
- package/dist/register-terminal-view.js +70 -0
- package/dist/register-terminal-view.js.map +1 -0
- package/dist/register.d.ts +8 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +116 -0
- package/dist/register.js.map +1 -0
- package/dist/routes/connect.d.ts +3 -0
- package/dist/routes/connect.d.ts.map +1 -0
- package/dist/routes/connect.js +86 -0
- package/dist/routes/connect.js.map +1 -0
- package/dist/routes/device-config.d.ts +5 -0
- package/dist/routes/device-config.d.ts.map +1 -0
- package/dist/routes/device-config.js +56 -0
- package/dist/routes/device-config.js.map +1 -0
- package/dist/routes/simulator-route.d.ts +8 -0
- package/dist/routes/simulator-route.d.ts.map +1 -0
- package/dist/routes/simulator-route.js +32 -0
- package/dist/routes/simulator-route.js.map +1 -0
- package/dist/routes/status.d.ts +3 -0
- package/dist/routes/status.d.ts.map +1 -0
- package/dist/routes/status.js +34 -0
- package/dist/routes/status.js.map +1 -0
- package/dist/routes/view-host.d.ts +24 -0
- package/dist/routes/view-host.d.ts.map +1 -0
- package/dist/routes/view-host.js +339 -0
- package/dist/routes/view-host.js.map +1 -0
- package/dist/routes/views.d.ts +8 -0
- package/dist/routes/views.d.ts.map +1 -0
- package/dist/routes/views.js +31 -0
- package/dist/routes/views.js.map +1 -0
- package/dist/services/audio-pipeline.d.ts +20 -0
- package/dist/services/audio-pipeline.d.ts.map +1 -0
- package/dist/services/audio-pipeline.js +87 -0
- package/dist/services/audio-pipeline.js.map +1 -0
- package/dist/services/facewear-service.d.ts +26 -0
- package/dist/services/facewear-service.d.ts.map +1 -0
- package/dist/services/facewear-service.js +45 -0
- package/dist/services/facewear-service.js.map +1 -0
- package/dist/services/smartglasses-service.d.ts +244 -0
- package/dist/services/smartglasses-service.d.ts.map +1 -0
- package/dist/services/smartglasses-service.js +821 -0
- package/dist/services/smartglasses-service.js.map +1 -0
- package/dist/services/vision-pipeline.d.ts +16 -0
- package/dist/services/vision-pipeline.d.ts.map +1 -0
- package/dist/services/vision-pipeline.js +39 -0
- package/dist/services/vision-pipeline.js.map +1 -0
- package/dist/services/xr-session-service.d.ts +54 -0
- package/dist/services/xr-session-service.d.ts.map +1 -0
- package/dist/services/xr-session-service.js +345 -0
- package/dist/services/xr-session-service.js.map +1 -0
- package/dist/status-format.d.ts +15 -0
- package/dist/status-format.d.ts.map +1 -0
- package/dist/status-format.js +89 -0
- package/dist/status-format.js.map +1 -0
- package/dist/transport/even-bridge.d.ts +69 -0
- package/dist/transport/even-bridge.d.ts.map +1 -0
- package/dist/transport/even-bridge.js +510 -0
- package/dist/transport/even-bridge.js.map +1 -0
- package/dist/transport/mock.d.ts +42 -0
- package/dist/transport/mock.d.ts.map +1 -0
- package/dist/transport/mock.js +124 -0
- package/dist/transport/mock.js.map +1 -0
- package/dist/transport/noble.d.ts +62 -0
- package/dist/transport/noble.d.ts.map +1 -0
- package/dist/transport/noble.js +256 -0
- package/dist/transport/noble.js.map +1 -0
- package/dist/transport/types.d.ts +36 -0
- package/dist/transport/types.d.ts.map +1 -0
- package/dist/transport/types.js +1 -0
- package/dist/transport/types.js.map +1 -0
- package/dist/transport/web-bluetooth.d.ts +58 -0
- package/dist/transport/web-bluetooth.d.ts.map +1 -0
- package/dist/transport/web-bluetooth.js +164 -0
- package/dist/transport/web-bluetooth.js.map +1 -0
- package/dist/ui/FacewearAppView.d.ts +4 -0
- package/dist/ui/FacewearAppView.d.ts.map +1 -0
- package/dist/ui/FacewearAppView.js +257 -0
- package/dist/ui/FacewearAppView.js.map +1 -0
- package/dist/ui/SmartglassesView.d.ts +10 -0
- package/dist/ui/SmartglassesView.d.ts.map +1 -0
- package/dist/ui/SmartglassesView.helpers.d.ts +104 -0
- package/dist/ui/SmartglassesView.helpers.d.ts.map +1 -0
- package/dist/ui/SmartglassesView.helpers.js +261 -0
- package/dist/ui/SmartglassesView.helpers.js.map +1 -0
- package/dist/ui/SmartglassesView.js +1189 -0
- package/dist/ui/SmartglassesView.js.map +1 -0
- package/dist/ui/facewear-view-bundle.d.ts +5 -0
- package/dist/ui/facewear-view-bundle.d.ts.map +1 -0
- package/dist/ui/facewear-view-bundle.js +17 -0
- package/dist/ui/facewear-view-bundle.js.map +1 -0
- package/dist/views/bundle.js +2950 -0
- package/dist/views/bundle.js.map +1 -0
- package/package.json +5 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.js","names":[],"sources":["../../src/components/FacewearSpatialView.tsx","../../src/components/facewear-profiles.ts","../../src/components/FacewearView.tsx","../../src/protocol/smartglasses.ts","../../src/ui/SmartglassesView.helpers.ts","../../src/components/SmartglassesSpatialView.tsx","../../src/components/SmartglassesPanelView.tsx","../../src/ui/FacewearAppView.tsx","../../src/transport/even-bridge.ts","../../src/transport/web-bluetooth.ts","../../src/ui/SmartglassesView.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.ts\";\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","// Pure facewear device-profile data + connected-state derivation, shared by the\n// legacy GUI dashboard (FacewearAppView.tsx) and the unified data wrapper\n// (FacewearView.tsx). Split out so the .tsx files export only React components\n// and stay Fast-Refresh-compatible (Vite full-reloads a component file that also\n// exports plain data/functions).\n\nimport type { FacewearDeviceType } from \"../devices/registry.ts\";\n\n/** A connected facewear device, mirrored from `/api/facewear/status`. */\nexport interface ConnectedDevice {\n id: string;\n kind: \"xr\" | \"smartglasses\";\n deviceType?: string;\n}\n\nexport interface FacewearStatusResponse {\n connected: boolean;\n devices: ConnectedDevice[];\n}\n\n/** A supported device the operator can connect/manage. */\nexport interface FacewearDeviceProfileRow {\n type: FacewearDeviceType;\n name: string;\n manufacturer: string;\n connectionType: string;\n description: string;\n}\n\nexport const FACEWEAR_DEVICE_PROFILES: readonly FacewearDeviceProfileRow[] = [\n {\n type: \"meta-quest\",\n name: \"Meta Quest 3 / 3S / Pro\",\n manufacturer: \"Meta\",\n connectionType: \"WebXR\",\n description: \"Passthrough AR/VR\",\n },\n {\n type: \"xreal\",\n name: \"XReal Air 3 / One Pro\",\n manufacturer: \"XREAL\",\n connectionType: \"WebXR\",\n description: \"Spatial display\",\n },\n {\n type: \"even-realities\",\n name: \"Even Realities G1 / G2\",\n manufacturer: \"Even Realities\",\n connectionType: \"Bluetooth BLE\",\n description: \"OLED display and mic\",\n },\n {\n type: \"apple-vision-pro\",\n name: \"Apple Vision Pro\",\n manufacturer: \"Apple\",\n connectionType: \"WebXR\",\n description: \"visionOS headset\",\n },\n];\n\n/**\n * A profile is connected when a live device matches it directly (deviceType),\n * via the Even Realities smartglasses rule (kind === \"smartglasses\"), or via the\n * WebXR rule (any xr-kind device lights up every WebXR profile).\n */\nexport function isProfileConnected(\n profile: FacewearDeviceProfileRow,\n devices: readonly ConnectedDevice[],\n): boolean {\n return devices.some(\n (device) =>\n device.deviceType === profile.type ||\n (profile.type === \"even-realities\" && device.kind === \"smartglasses\") ||\n (profile.connectionType === \"WebXR\" && device.kind === \"xr\"),\n );\n}\n","/**\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.ts\";\nimport {\n type FacewearSnapshot,\n FacewearSpatialView,\n} from \"./FacewearSpatialView.tsx\";\nimport {\n type ConnectedDevice,\n FACEWEAR_DEVICE_PROFILES,\n type FacewearStatusResponse,\n isProfileConnected,\n} from \"./facewear-profiles.ts\";\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","export type GlassSide = \"left\" | \"right\";\nexport type G1ConnectionReadyMode = \"lens-specific\" | \"official\" | \"android-f4\";\nexport type SmartglassesAudioEncoding = \"pcm16\" | \"lc3\" | \"unknown\";\n\nexport const EVEN_G1_UART = {\n service: \"6e400001-b5a3-f393-e0a9-e50e24dcca9e\",\n tx: \"6e400002-b5a3-f393-e0a9-e50e24dcca9e\",\n rx: \"6e400003-b5a3-f393-e0a9-e50e24dcca9e\",\n} as const;\n\nexport enum G1Command {\n StartAi = 0xf5,\n OpenMic = 0x0e,\n ReceiveMicData = 0xf1,\n Init = 0x4d,\n RightInit = 0xf4,\n Heartbeat = 0x25,\n Battery = 0x2c,\n SendResult = 0x4e,\n QuickNote = 0x21,\n Dashboard = 0x22,\n Notification = 0x4b,\n DashboardContent = 0x06,\n Navigation = 0x0a,\n TranslateSetup = 0x39,\n TranslateStart = 0x50,\n TranslateLanguages = 0x1c,\n TranslateOriginalText = 0x0f,\n TranslateTranslatedText = 0x0d,\n AppWhitelist = 0x04,\n ExitFunction = 0x18,\n SilentMode = 0x03,\n Brightness = 0x01,\n DashboardPosition = 0x26,\n HeadUpAngle = 0x0b,\n GlassesWear = 0x27,\n BmpData = 0x15,\n BmpCrc = 0x16,\n BmpEnd = 0x20,\n Note = 0x1e,\n GetSerial = 0x34,\n}\n\nexport enum G1DashboardLayout {\n Full = \"full\",\n Dual = \"dual\",\n Minimal = \"minimal\",\n}\n\nexport enum G1WeatherIcon {\n Nothing = 0x00,\n Night = 0x01,\n Clouds = 0x02,\n Drizzle = 0x03,\n HeavyDrizzle = 0x04,\n Rain = 0x05,\n HeavyRain = 0x06,\n Thunder = 0x07,\n Thunderstorm = 0x08,\n Snow = 0x09,\n Mist = 0x0a,\n Fog = 0x0b,\n Sand = 0x0c,\n Squalls = 0x0d,\n Tornado = 0x0e,\n FreezingRain = 0x0f,\n Sunny = 0x10,\n}\n\nexport enum G1TemperatureUnit {\n Celsius = \"celsius\",\n Fahrenheit = \"fahrenheit\",\n}\n\nexport enum G1TimeFormat {\n TwentyFourHour = \"24h\",\n TwelveHour = \"12h\",\n}\n\nexport enum G1NavigationTurn {\n StraightDot = 0x01,\n Straight = 0x02,\n Right = 0x03,\n Left = 0x04,\n SlightRight = 0x05,\n SlightLeft = 0x06,\n StrongRight = 0x07,\n StrongLeft = 0x08,\n UTurnLeft = 0x09,\n UTurnRight = 0x0a,\n Merge = 0x0b,\n SlightRightAtFork = 0x22,\n SlightLeftAtFork = 0x23,\n}\n\nexport enum G1TranslateLanguage {\n Chinese = 0x01,\n English = 0x02,\n French = 0x05,\n Dutch = 0x09,\n}\n\nexport enum G1SubCommand {\n Exit = 0x00,\n PageControl = 0x01,\n Start = 0x17,\n Stop = 0x18,\n}\n\nexport enum G1MicStatus {\n Disable = 0x00,\n Enable = 0x01,\n}\n\nexport enum G1ResponseStatus {\n Success = 0xc9,\n Failure = 0xca,\n}\n\nexport enum G1ScreenAction {\n NewContent = 0x01,\n}\n\nexport enum G1AiStatus {\n Displaying = 0x30,\n DisplayComplete = 0x40,\n ManualMode = 0x50,\n NetworkError = 0x60,\n}\n\nexport enum G1TextStatus {\n TextShow = 0x70,\n}\n\nexport enum G1SilentModeStatus {\n Off = 0x0a,\n On = 0x0c,\n}\n\nexport enum G1DashboardState {\n Off = 0x00,\n On = 0x01,\n}\n\nexport enum G1GlassesWearStatus {\n Off = 0x00,\n On = 0x01,\n}\n\nexport enum G1VoiceNoteSubCommand {\n RequestAudioInfo = 0x01,\n RequestAudioData = 0x02,\n DeleteAudioStream = 0x04,\n DeleteAll = 0x05,\n}\n\nexport enum G1InteractionCode {\n DoubleTap = 0x00,\n SingleTap = 0x01,\n LongPress = 0x17,\n StopAiRecording = 0x18,\n SilentModeOn = 0x04,\n SilentModeOff = 0x05,\n OpenDashboardStart = 0x02,\n CloseDashboardStart = 0x03,\n OpenDashboardConfirm = 0x1e,\n CloseDashboardConfirm = 0x1f,\n}\n\nexport interface DisplayPage {\n pageNumber: number;\n maxPages: number;\n text: string;\n screenStatus: number;\n}\n\nexport interface G1NotificationPayload {\n msgId?: number;\n type?: number;\n appIdentifier: string;\n title: string;\n subtitle?: string;\n message: string;\n displayName?: string;\n timeS?: number;\n date?: string;\n}\n\nexport interface G1DashboardTimeWeatherPayload {\n seqId?: number;\n timestampMs?: number;\n timezoneOffsetSeconds?: number;\n temperatureInCelsius: number;\n weatherIcon?: number;\n temperatureUnit?: G1TemperatureUnit;\n timeFormat?: G1TimeFormat;\n}\n\nexport interface G1NavigationDirectionsPayload {\n seqId: number;\n totalDuration: string;\n totalDistance: string;\n direction: string;\n distance: string;\n speed: string;\n directionTurn: number;\n customX?: [number, number] | number[];\n customY?: number;\n}\n\nexport interface G1VoiceNoteEntry {\n index: number;\n timestamp: number;\n crc: number;\n}\n\nexport interface G1Event {\n side: GlassSide;\n raw: Uint8Array;\n type:\n | \"state\"\n | \"dashboard\"\n | \"init\"\n | \"mic-response\"\n | \"mic-data\"\n | \"display-result\"\n | \"notification\"\n | \"voice-note-list\"\n | \"voice-note-audio\"\n | \"serial\"\n | \"battery-status\"\n | \"heartbeat\"\n | \"response\"\n | \"error\"\n | \"unknown\";\n code?: number;\n label?: string;\n micEnabled?: boolean;\n micRequested?: boolean;\n responseStatus?: number;\n responseOk?: boolean;\n stateCategory?: \"interaction\" | \"physical\" | \"battery\" | \"device\";\n stateName?: string;\n audioData?: Uint8Array;\n audioEncoding?: SmartglassesAudioEncoding;\n /**\n * Decoded 16-bit PCM bytes. Direct G1 0xF1 microphone notifications are LC3\n * and are exposed through audioData instead.\n */\n audioPcm?: Uint8Array;\n sequence?: number;\n syncId?: number;\n subcommand?: number;\n displaySeq?: number;\n totalPackages?: number;\n currentPackage?: number;\n screenStatus?: number;\n charPosition?: number;\n pageNumber?: number;\n maxPages?: number;\n text?: string;\n notificationId?: number;\n notificationChunk?: Uint8Array;\n voiceNotes?: G1VoiceNoteEntry[];\n serialNumber?: string;\n totalPackets?: number;\n currentPacket?: number;\n noteIndex?: number;\n batteryPercent?: number;\n batteryFlags?: number;\n batteryVoltageMv?: number;\n}\n\nexport type G1MicrophoneInteractionAction = \"enable\" | \"disable\";\n\nexport function microphoneActionForInteractionEvent(\n event: Pick<G1Event, \"type\" | \"label\">,\n): G1MicrophoneInteractionAction | null {\n if (event.type !== \"state\") return null;\n if (event.label === \"single_tap\" || event.label === \"long_press\") {\n return \"enable\";\n }\n if (event.label === \"double_tap\" || event.label === \"stop_ai_recording\") {\n return \"disable\";\n }\n return null;\n}\n\nexport const G1_DISPLAY = {\n displayWidthPx: 576,\n charsPerLine: 40,\n linesPerPage: 5,\n maxTextLength: 40 * 5,\n maxPayloadBytes: 191,\n};\n\nconst G1_GLYPH_WIDTHS = new Map<string, number>(\n Object.entries({\n \" \": 2,\n \"!\": 1,\n '\"': 2,\n \"#\": 6,\n $: 5,\n \"%\": 6,\n \"&\": 7,\n \"'\": 1,\n \"(\": 2,\n \")\": 2,\n \"*\": 3,\n \"+\": 4,\n \",\": 1,\n \"-\": 4,\n \".\": 1,\n \"/\": 3,\n \"0\": 5,\n \"1\": 3,\n \"2\": 5,\n \"3\": 5,\n \"4\": 5,\n \"5\": 5,\n \"6\": 5,\n \"7\": 5,\n \"8\": 5,\n \"9\": 5,\n \":\": 1,\n \";\": 1,\n \"<\": 4,\n \"=\": 4,\n \">\": 4,\n \"?\": 5,\n \"@\": 7,\n A: 6,\n B: 5,\n C: 5,\n D: 5,\n E: 4,\n F: 4,\n G: 5,\n H: 5,\n I: 2,\n J: 3,\n K: 5,\n L: 4,\n M: 7,\n N: 5,\n O: 5,\n P: 5,\n Q: 5,\n R: 5,\n S: 5,\n T: 5,\n U: 5,\n V: 6,\n W: 7,\n X: 6,\n Y: 6,\n Z: 5,\n \"[\": 2,\n \"\\\\\": 3,\n \"]\": 2,\n \"^\": 4,\n _: 3,\n \"`\": 2,\n a: 5,\n b: 4,\n c: 4,\n d: 4,\n e: 4,\n f: 4,\n g: 4,\n h: 4,\n i: 1,\n j: 2,\n k: 4,\n l: 1,\n m: 7,\n n: 4,\n o: 4,\n p: 4,\n q: 4,\n r: 3,\n s: 4,\n t: 3,\n u: 5,\n v: 5,\n w: 7,\n x: 5,\n y: 5,\n z: 4,\n \"{\": 3,\n \"|\": 1,\n \"}\": 3,\n \"~\": 7,\n }),\n);\n\nexport const G1_BMP = {\n width: 576,\n height: 136,\n bitsPerPixel: 1,\n};\n\nconst INTERACTION_LABELS = new Map<number, string>([\n [G1InteractionCode.DoubleTap, \"double_tap\"],\n [G1InteractionCode.SingleTap, \"single_tap\"],\n [G1InteractionCode.LongPress, \"long_press\"],\n [G1InteractionCode.StopAiRecording, \"stop_ai_recording\"],\n [G1InteractionCode.SilentModeOn, \"silent_mode_on\"],\n [G1InteractionCode.SilentModeOff, \"silent_mode_off\"],\n [G1InteractionCode.OpenDashboardStart, \"open_dashboard_start\"],\n [G1InteractionCode.CloseDashboardStart, \"close_dashboard_start\"],\n [G1InteractionCode.OpenDashboardConfirm, \"open_dashboard_confirm\"],\n [G1InteractionCode.CloseDashboardConfirm, \"close_dashboard_confirm\"],\n]);\n\nconst PHYSICAL_LABELS = new Map<number, string>([\n [0x06, \"wearing\"],\n [0x07, \"transitioning\"],\n [0x08, \"cradle_open\"],\n [0x09, \"charged_in_cradle\"],\n [0x0b, \"cradle_closed\"],\n]);\n\nconst BATTERY_LABELS = new Map<number, string>([\n [0x09, \"glasses_fully_charged\"],\n [0x0e, \"cradle_charging_cable_changed\"],\n [0x0f, \"cradle_fully_charged\"],\n]);\n\nconst DEVICE_LABELS = new Map<number, string>([\n [0x0a, \"device_unknown_0a\"],\n [0x11, \"connected\"],\n [0x12, \"device_unknown_12\"],\n [0x14, \"device_unknown_14\"],\n [0x15, \"device_unknown_15\"],\n]);\n\nfunction classifyStateCode(code: number | undefined): {\n category: NonNullable<G1Event[\"stateCategory\"]>;\n label: string;\n name: string;\n} | null {\n if (code === undefined) return null;\n const interaction = INTERACTION_LABELS.get(code);\n if (interaction)\n return { category: \"interaction\", label: interaction, name: interaction };\n const physical = PHYSICAL_LABELS.get(code);\n if (physical)\n return { category: \"physical\", label: physical, name: physical };\n const battery = BATTERY_LABELS.get(code);\n if (battery) return { category: \"battery\", label: battery, name: battery };\n const device = DEVICE_LABELS.get(code);\n if (device) return { category: \"device\", label: device, name: device };\n return null;\n}\n\nexport function measureG1DisplayText(text: string): number {\n let width = 0;\n for (const char of text) width += measureG1DisplayChar(char);\n return width;\n}\n\nfunction measureG1DisplayChar(char: string): number {\n const codePoint = char.codePointAt(0) ?? 0;\n if (isKorean(codePoint)) return 24;\n if (isCjk(codePoint) || isHiragana(codePoint) || isKatakana(codePoint))\n return 18;\n if (isCyrillic(codePoint)) return 18;\n const glyphWidth = G1_GLYPH_WIDTHS.get(char);\n return glyphWidth === undefined ? 16 : (glyphWidth + 1) * 2;\n}\n\nfunction isCjk(codePoint: number): boolean {\n return (\n (codePoint >= 0x3400 && codePoint <= 0x4dbf) ||\n (codePoint >= 0x4e00 && codePoint <= 0x9fff) ||\n (codePoint >= 0xf900 && codePoint <= 0xfaff)\n );\n}\n\nfunction isHiragana(codePoint: number): boolean {\n return codePoint >= 0x3040 && codePoint <= 0x309f;\n}\n\nfunction isKatakana(codePoint: number): boolean {\n return codePoint >= 0x30a0 && codePoint <= 0x30ff;\n}\n\nfunction isKorean(codePoint: number): boolean {\n return codePoint >= 0xac00 && codePoint <= 0xd7af;\n}\n\nfunction isCyrillic(codePoint: number): boolean {\n return codePoint >= 0x0400 && codePoint <= 0x04ff;\n}\n\nfunction fitsG1DisplayLine(text: string, maxWidthPx: number): boolean {\n return measureG1DisplayText(text) <= maxWidthPx;\n}\n\nexport function formatDisplayLines(\n text: string,\n options: number | { charsPerLine?: number; maxWidthPx?: number } = {},\n): string[] {\n const charsPerLine =\n typeof options === \"number\" ? options : options.charsPerLine;\n const maxWidthPx =\n typeof options === \"number\"\n ? undefined\n : (options.maxWidthPx ?? G1_DISPLAY.displayWidthPx);\n if (charsPerLine !== undefined)\n return formatDisplayLinesByCharacters(text, charsPerLine);\n return formatDisplayLinesByPixels(\n text,\n maxWidthPx ?? G1_DISPLAY.displayWidthPx,\n );\n}\n\nfunction formatDisplayLinesByCharacters(\n text: string,\n charsPerLine: number,\n): string[] {\n const lines: string[] = [];\n for (const paragraph of text\n .split(/\\r?\\n/)\n .map((p) => p.trim())\n .filter(Boolean)) {\n let rest = paragraph;\n while (rest.length > charsPerLine) {\n let splitAt = rest.lastIndexOf(\" \", charsPerLine);\n if (splitAt < 1) splitAt = charsPerLine;\n lines.push(rest.slice(0, splitAt).trimEnd());\n rest = rest.slice(splitAt).trimStart();\n }\n if (rest) lines.push(rest);\n }\n return lines.length ? lines : [\"\"];\n}\n\nfunction formatDisplayLinesByPixels(\n text: string,\n maxWidthPx: number,\n): string[] {\n const lines: string[] = [];\n for (const paragraph of text.split(/\\r?\\n/)) {\n const trimmed = paragraph.trim();\n if (!trimmed) {\n if (lines.length > 0) lines.push(\"\");\n continue;\n }\n lines.push(...wrapDisplayParagraphByPixels(trimmed, maxWidthPx));\n }\n return lines.length ? lines : [\"\"];\n}\n\nfunction wrapDisplayParagraphByPixels(\n paragraph: string,\n maxWidthPx: number,\n): string[] {\n if (fitsG1DisplayLine(paragraph, maxWidthPx)) return [paragraph];\n const lines: string[] = [];\n let current = \"\";\n for (const word of paragraph.split(/\\s+/).filter(Boolean)) {\n const candidate = current ? `${current} ${word}` : word;\n if (fitsG1DisplayLine(candidate, maxWidthPx)) {\n current = candidate;\n continue;\n }\n if (current) {\n lines.push(current);\n current = \"\";\n }\n const wordLines = breakDisplayTokenByPixels(word, maxWidthPx);\n lines.push(...wordLines.slice(0, -1));\n current = wordLines.at(-1) ?? \"\";\n }\n if (current) lines.push(current);\n return lines;\n}\n\nfunction breakDisplayTokenByPixels(\n token: string,\n maxWidthPx: number,\n): string[] {\n const lines: string[] = [];\n let current = \"\";\n for (const char of Array.from(token)) {\n const candidate = current + char;\n if (fitsG1DisplayLine(candidate, maxWidthPx)) {\n current = candidate;\n continue;\n }\n if (current) lines.push(current);\n current = char;\n }\n if (current) lines.push(current);\n return lines.length ? lines : [\"\"];\n}\n\nexport function paginateDisplayText(\n text: string,\n options: { charsPerLine?: number; linesPerPage?: number } = {},\n): DisplayPage[] {\n const charsPerLine = options.charsPerLine ?? G1_DISPLAY.charsPerLine;\n const linesPerPage = options.linesPerPage ?? G1_DISPLAY.linesPerPage;\n const lines = formatDisplayLines(\n text,\n options.charsPerLine === undefined\n ? { maxWidthPx: G1_DISPLAY.displayWidthPx }\n : { charsPerLine },\n );\n const maxPages = Math.max(1, Math.ceil(lines.length / linesPerPage));\n const pages: DisplayPage[] = [];\n\n for (let pageIndex = 0; pageIndex < maxPages; pageIndex++) {\n const pageLines = lines.slice(\n pageIndex * linesPerPage,\n (pageIndex + 1) * linesPerPage,\n );\n const missing = linesPerPage - pageLines.length;\n if (missing > 0) {\n const before = Math.floor(missing / 2);\n const after = missing - before;\n pageLines.unshift(...Array.from({ length: before }, () => \"\"));\n pageLines.push(...Array.from({ length: after }, () => \"\"));\n }\n pages.push({\n pageNumber: pageIndex + 1,\n maxPages,\n text: pageLines.join(\"\\n\"),\n screenStatus:\n pageIndex === maxPages - 1\n ? G1AiStatus.DisplayComplete\n : G1AiStatus.Displaying | G1ScreenAction.NewContent,\n });\n }\n return pages;\n}\n\nexport function encodeTextPacket(page: DisplayPage, seq = 0): Uint8Array {\n const data = new TextEncoder().encode(page.text);\n if (data.byteLength > G1_DISPLAY.maxPayloadBytes) {\n throw new RangeError(\n `G1 display payload is ${data.byteLength} bytes; use encodeTextPackets for payloads over ${G1_DISPLAY.maxPayloadBytes} bytes`,\n );\n }\n return encodeTextPacketChunk(page, data, seq, 1, 0);\n}\n\nexport function encodeTextPackets(page: DisplayPage, seq = 0): Uint8Array[] {\n const chunks = splitUtf8Chunks(page.text, G1_DISPLAY.maxPayloadBytes);\n const totalPackages = chunks.length;\n const packets: Uint8Array[] = [];\n let charPosition = 0;\n for (const [currentPackage, chunk] of chunks.entries()) {\n packets.push(\n encodeTextPacketChunk(\n page,\n chunk,\n seq,\n totalPackages,\n currentPackage,\n charPosition,\n ),\n );\n charPosition += chunk.length;\n }\n return packets;\n}\n\nfunction splitUtf8Chunks(text: string, maxBytes: number): Uint8Array[] {\n const encoder = new TextEncoder();\n if (text.length === 0) return [new Uint8Array()];\n const chunks: Uint8Array[] = [];\n let current = \"\";\n for (const char of text) {\n const next = current + char;\n const nextBytes = encoder.encode(next);\n if (nextBytes.byteLength > maxBytes && current) {\n chunks.push(encoder.encode(current));\n current = char;\n continue;\n }\n if (nextBytes.byteLength > maxBytes) {\n throw new RangeError(\n `Single UTF-8 character exceeds G1 display packet payload limit of ${maxBytes} bytes`,\n );\n }\n current = next;\n }\n if (current || chunks.length === 0) chunks.push(encoder.encode(current));\n return chunks;\n}\n\nfunction encodeTextPacketChunk(\n page: DisplayPage,\n data: Uint8Array,\n seq: number,\n totalPackages: number,\n currentPackage: number,\n charPosition = 0,\n): Uint8Array {\n const packet = new Uint8Array(9 + data.length);\n packet.set([\n G1Command.SendResult,\n seq & 0xff,\n totalPackages & 0xff,\n currentPackage & 0xff,\n page.screenStatus & 0xff,\n (charPosition >>> 8) & 0xff,\n charPosition & 0xff,\n page.pageNumber & 0xff,\n page.maxPages & 0xff,\n ]);\n packet.set(data, 9);\n return packet;\n}\n\nexport function encodeMicCommand(enabled: boolean): Uint8Array {\n return Uint8Array.from([\n G1Command.OpenMic,\n enabled ? G1MicStatus.Enable : G1MicStatus.Disable,\n ]);\n}\n\nexport function encodeHeartbeat(seq: number): Uint8Array {\n const s = seq & 0xff;\n return Uint8Array.from([G1Command.Heartbeat, 0x06, 0x00, s, 0x04, s]);\n}\n\nexport function encodeBatteryStatusRequest(): Uint8Array {\n return Uint8Array.from([G1Command.Battery, 0x01]);\n}\n\nexport function encodeConnectionReady(\n side: GlassSide,\n mode: G1ConnectionReadyMode = \"lens-specific\",\n): Uint8Array {\n return Uint8Array.from([\n mode === \"android-f4\"\n ? G1Command.RightInit\n : mode === \"official\" || side === \"left\"\n ? G1Command.Init\n : G1Command.RightInit,\n 0x01,\n ]);\n}\n\nexport function encodeStartAi(\n subcommand: G1SubCommand,\n param: Uint8Array = new Uint8Array(),\n): Uint8Array {\n const packet = new Uint8Array(2 + param.length);\n packet.set([G1Command.StartAi, subcommand]);\n packet.set(param, 2);\n return packet;\n}\n\nexport function encodeExitFunction(): Uint8Array {\n return Uint8Array.from([G1Command.ExitFunction]);\n}\n\nexport function encodeGetSerial(): Uint8Array {\n return Uint8Array.from([G1Command.GetSerial]);\n}\n\nexport function encodeClearScreen(): Uint8Array {\n return Uint8Array.from([\n G1Command.StartAi,\n G1SubCommand.Stop,\n 0x00,\n 0x00,\n 0x00,\n ]);\n}\n\nexport function encodeSilentMode(enabled: boolean): Uint8Array {\n return Uint8Array.from([\n G1Command.SilentMode,\n enabled ? G1SilentModeStatus.On : G1SilentModeStatus.Off,\n 0x00,\n ]);\n}\n\nexport function encodeBrightness(level: number, auto = false): Uint8Array {\n if (!Number.isInteger(level) || level < 0 || level > 0x29) {\n throw new RangeError(\n \"Brightness level must be an integer between 0 and 0x29\",\n );\n }\n return Uint8Array.from([\n G1Command.Brightness,\n level & 0xff,\n auto ? 0x01 : 0x00,\n ]);\n}\n\nexport function encodeDashboard(\n state: G1DashboardState | boolean,\n position = 0,\n): Uint8Array {\n if (!Number.isInteger(position) || position < 0 || position > 8) {\n throw new RangeError(\n \"Dashboard position must be an integer between 0 and 8\",\n );\n }\n const stateValue =\n typeof state === \"boolean\"\n ? state\n ? G1DashboardState.On\n : G1DashboardState.Off\n : state;\n return Uint8Array.from([\n G1Command.DashboardPosition,\n 0x07,\n 0x00,\n 0x01,\n 0x02,\n stateValue,\n position & 0xff,\n ]);\n}\n\nexport function encodeDashboardPosition(\n height: number,\n depth: number,\n seqId = 1,\n): Uint8Array {\n if (!Number.isInteger(height) || height < 0 || height > 8) {\n throw new RangeError(\"Dashboard height must be an integer between 0 and 8\");\n }\n if (!Number.isInteger(depth) || depth < 1 || depth > 9) {\n throw new RangeError(\"Dashboard depth must be an integer between 1 and 9\");\n }\n return Uint8Array.from([\n G1Command.DashboardPosition,\n 0x08,\n 0x00,\n seqId & 0xff,\n 0x02,\n 0x01,\n height & 0xff,\n depth & 0xff,\n ]);\n}\n\nexport function encodeDashboardLayout(layout: G1DashboardLayout): Uint8Array {\n const layoutBytes =\n layout === G1DashboardLayout.Full\n ? [0x08, 0x06, 0x00, 0x00]\n : layout === G1DashboardLayout.Dual\n ? [0x1e, 0x06, 0x01, 0x00]\n : [0x31, 0x06, 0x02, 0x00];\n return Uint8Array.from([\n G1Command.DashboardContent,\n 0x07,\n 0x00,\n ...layoutBytes,\n ]);\n}\n\nexport function encodeDashboardCalendarItem(payload: {\n name: string;\n time: string;\n location: string;\n}): Uint8Array {\n const name = new TextEncoder().encode(payload.name);\n const time = new TextEncoder().encode(payload.time);\n const location = new TextEncoder().encode(payload.location);\n for (const [field, bytes] of [\n [\"name\", name],\n [\"time\", time],\n [\"location\", location],\n ] as const) {\n if (bytes.length > 255)\n throw new RangeError(\n `Dashboard calendar ${field} must be at most 255 bytes`,\n );\n }\n const prefix = [\n 0x00, 0x6d, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x01,\n ];\n const body = new Uint8Array(\n prefix.length + 6 + name.length + time.length + location.length,\n );\n let offset = 0;\n body.set(prefix, offset);\n offset += prefix.length;\n body.set([0x01, name.length], offset);\n offset += 2;\n body.set(name, offset);\n offset += name.length;\n body.set([0x02, time.length], offset);\n offset += 2;\n body.set(time, offset);\n offset += time.length;\n body.set([0x03, location.length], offset);\n offset += 2;\n body.set(location, offset);\n return Uint8Array.from([\n G1Command.DashboardContent,\n (body.length + 2) & 0xff,\n ...body,\n ]);\n}\n\nexport function encodeDashboardTimeWeather(\n payload: G1DashboardTimeWeatherPayload,\n): Uint8Array {\n if (\n !Number.isInteger(payload.temperatureInCelsius) ||\n payload.temperatureInCelsius < -128 ||\n payload.temperatureInCelsius > 127\n ) {\n throw new RangeError(\"Dashboard temperature must fit in signed 8 bits\");\n }\n const seqId = payload.seqId ?? 0;\n const timestampMs = payload.timestampMs ?? Date.now();\n const timezoneOffsetSeconds =\n payload.timezoneOffsetSeconds ??\n -new Date(timestampMs).getTimezoneOffset() * 60;\n const localMs = timestampMs + timezoneOffsetSeconds * 1000;\n const out = new Uint8Array(21);\n const view = new DataView(out.buffer);\n out.set([G1Command.DashboardContent, 0x15, 0x00, seqId & 0xff, 0x01]);\n view.setUint32(5, Math.floor(localMs / 1000), true);\n view.setBigUint64(9, BigInt(Math.trunc(localMs)), true);\n out[17] = (payload.weatherIcon ?? G1WeatherIcon.Nothing) & 0xff;\n out[18] = payload.temperatureInCelsius & 0xff;\n out[19] =\n payload.temperatureUnit === G1TemperatureUnit.Fahrenheit ? 0x01 : 0x00;\n out[20] = payload.timeFormat === G1TimeFormat.TwelveHour ? 0x01 : 0x00;\n return out;\n}\n\nexport function encodeHeadUpAngle(angle: number): Uint8Array {\n if (!Number.isInteger(angle) || angle < 0 || angle > 60) {\n throw new RangeError(\n \"Head-up display angle must be an integer between 0 and 60\",\n );\n }\n return Uint8Array.from([G1Command.HeadUpAngle, angle & 0xff, 0x01]);\n}\n\nexport function encodeG1Setup(\n payload: string | Record<string, unknown> | unknown[],\n): Uint8Array[] {\n const text = typeof payload === \"string\" ? payload : JSON.stringify(payload);\n const data = new TextEncoder().encode(text);\n const maxPayload = 176;\n const totalPackets = Math.max(1, Math.ceil(data.byteLength / maxPayload));\n const packets: Uint8Array[] = [];\n for (let index = 0; index < totalPackets; index++) {\n const chunk = data.slice(index * maxPayload, (index + 1) * maxPayload);\n const packet = new Uint8Array(3 + chunk.length);\n packet.set([G1Command.AppWhitelist, totalPackets & 0xff, index & 0xff]);\n packet.set(chunk, 3);\n packets.push(packet);\n }\n return packets;\n}\n\nexport function encodeNavigationInit(seqId: number): Uint8Array {\n return Uint8Array.from([\n G1Command.Navigation,\n 0x06,\n 0x00,\n seqId & 0xff,\n 0x00,\n 0x01,\n ]);\n}\n\nexport function encodeNavigationDirections(\n payload: G1NavigationDirectionsPayload,\n): Uint8Array {\n const encoder = new TextEncoder();\n const totalDuration = encoder.encode(payload.totalDuration);\n const totalDistance = encoder.encode(payload.totalDistance);\n const direction = encoder.encode(payload.direction);\n const distance = encoder.encode(payload.distance);\n const speed = encoder.encode(payload.speed);\n const customX = payload.customX ?? [0x00, 0x00];\n const body = new Uint8Array(\n 8 +\n totalDuration.length +\n totalDistance.length +\n direction.length +\n distance.length +\n speed.length +\n 5,\n );\n let offset = 0;\n body.set(\n [\n 0x00,\n payload.seqId & 0xff,\n 0x01,\n payload.directionTurn & 0xff,\n customX[0] ?? 0,\n customX[1] ?? 0,\n payload.customY ?? 0,\n 0x00,\n ],\n offset,\n );\n offset += 8;\n for (const bytes of [\n totalDuration,\n totalDistance,\n direction,\n distance,\n speed,\n ]) {\n body.set(bytes, offset);\n offset += bytes.length;\n body[offset++] = 0x00;\n }\n return Uint8Array.from([\n G1Command.Navigation,\n (body.length + 2) & 0xff,\n ...body,\n ]);\n}\n\nexport function encodeNavigationPrimaryImage(\n image: ArrayLike<number>,\n overlay: ArrayLike<number>,\n seqId = 0,\n): Uint8Array[] {\n validateBitPlanes(image, overlay, 136 * 136, \"primary navigation image\");\n return encodeNavigationImagePackets(\n runLengthEncodeBits([...Array.from(image), ...Array.from(overlay)]),\n 0x02,\n seqId,\n false,\n );\n}\n\nexport function encodeNavigationSecondaryImage(\n image: ArrayLike<number>,\n overlay: ArrayLike<number>,\n seqId = 0,\n): Uint8Array[] {\n validateBitPlanes(image, overlay, 488 * 136, \"secondary navigation image\");\n return encodeNavigationImagePackets(\n [...Array.from(image), ...Array.from(overlay)],\n 0x03,\n seqId,\n true,\n );\n}\n\nexport function encodeNavigationPoller(\n seqId: number,\n pollerSeqId: number,\n): Uint8Array {\n return Uint8Array.from([\n G1Command.Navigation,\n 0x06,\n 0x00,\n seqId & 0xff,\n 0x04,\n pollerSeqId & 0xff,\n ]);\n}\n\nexport function encodeNavigationEnd(seqId: number): Uint8Array {\n return Uint8Array.from([\n G1Command.Navigation,\n 0x06,\n 0x00,\n seqId & 0xff,\n 0x05,\n 0x01,\n ]);\n}\n\nexport function encodeTranslateSetup(): Uint8Array {\n return Uint8Array.from([G1Command.TranslateSetup, 0x05, 0x00, 0x00, 0x13]);\n}\n\nexport function encodeTranslateStart(): Uint8Array {\n return Uint8Array.from([\n G1Command.TranslateStart,\n 0x06,\n 0x00,\n 0x00,\n 0x01,\n 0x01,\n ]);\n}\n\nexport function encodeTranslateLanguages(\n fromLanguage: number,\n toLanguage: number,\n): Uint8Array {\n return Uint8Array.from([\n G1Command.TranslateLanguages,\n 0x00,\n fromLanguage & 0xff,\n toLanguage & 0xff,\n ]);\n}\n\nexport function encodeTranslateText(\n kind: \"original\" | \"translated\",\n text: string,\n syncId: number,\n): Uint8Array {\n const encoded = new TextEncoder().encode(text);\n const command =\n kind === \"original\"\n ? G1Command.TranslateOriginalText\n : G1Command.TranslateTranslatedText;\n return Uint8Array.from([\n command,\n syncId & 0xff,\n 0x01,\n 0x00,\n 0x00,\n 0x00,\n text ? 0x20 : 0x00,\n 0x0d,\n ...encoded,\n ]);\n}\n\nexport function encodeGlassesWear(enabled: boolean): Uint8Array {\n return Uint8Array.from([\n G1Command.GlassesWear,\n enabled ? G1GlassesWearStatus.On : G1GlassesWearStatus.Off,\n ]);\n}\n\nexport function encodeAppWhitelist(\n whitelist: string | Record<string, unknown> | unknown[],\n): Uint8Array[] {\n const text =\n typeof whitelist === \"string\" ? whitelist : JSON.stringify(whitelist);\n const data = new TextEncoder().encode(text);\n const maxPayload = 177;\n const totalPackets = Math.max(1, Math.ceil(data.byteLength / maxPayload));\n const packets: Uint8Array[] = [];\n for (let seq = 0; seq < totalPackets; seq++) {\n const start = seq * maxPayload;\n const chunk = data.slice(start, start + maxPayload);\n const packet = new Uint8Array(3 + chunk.length);\n packet.set([G1Command.AppWhitelist, totalPackets & 0xff, seq & 0xff]);\n packet.set(chunk, 3);\n packets.push(packet);\n }\n return packets;\n}\n\nexport function encodeNoteDelete(noteNumber: number): Uint8Array {\n validateNoteNumber(noteNumber);\n return Uint8Array.from([\n G1Command.Note,\n 0x10,\n 0x00,\n 0xe0,\n 0x03,\n 0x01,\n 0x00,\n 0x01,\n 0x00,\n noteNumber,\n 0x00,\n 0x01,\n 0x00,\n 0x01,\n 0x00,\n 0x00,\n ]);\n}\n\nexport function encodeNoteAdd(\n noteNumber: number,\n title: string,\n text: string,\n version = Date.now(),\n): Uint8Array {\n validateNoteNumber(noteNumber);\n const titleBytes = new TextEncoder().encode(title);\n const textBytes = new TextEncoder().encode(text);\n if (titleBytes.length > 255 || textBytes.length > 255) {\n throw new RangeError(\n \"G1 note title and text must each encode to at most 255 bytes\",\n );\n }\n const fixed = Uint8Array.from([0x03, 0x01, 0x00, 0x01, 0x00]);\n const payloadLength =\n 1 +\n 1 +\n fixed.length +\n 1 +\n 1 +\n 1 +\n titleBytes.length +\n 1 +\n 1 +\n textBytes.length +\n 2;\n const out = new Uint8Array(\n 4 + fixed.length + 3 + titleBytes.length + 2 + textBytes.length,\n );\n let offset = 0;\n out.set(\n [\n G1Command.Note,\n payloadLength & 0xff,\n 0x00,\n Math.floor(version / 1000) & 0xff,\n ],\n offset,\n );\n offset += 4;\n out.set(fixed, offset);\n offset += fixed.length;\n out.set([noteNumber, 0x01, titleBytes.length & 0xff], offset);\n offset += 3;\n out.set(titleBytes, offset);\n offset += titleBytes.length;\n out.set([textBytes.length & 0xff, 0x00], offset);\n offset += 2;\n out.set(textBytes, offset);\n return out;\n}\n\nexport function encodeVoiceNoteFetch(\n noteIndex: number,\n syncId: number,\n): Uint8Array {\n validateVoiceNoteIndex(noteIndex);\n return Uint8Array.from([\n G1Command.Note,\n 0x06,\n 0x00,\n syncId & 0xff,\n G1VoiceNoteSubCommand.RequestAudioData,\n noteIndex & 0xff,\n ]);\n}\n\nexport function encodeVoiceNoteList(syncId: number): Uint8Array {\n return Uint8Array.from([\n G1Command.Note,\n 0x06,\n 0x00,\n syncId & 0xff,\n G1VoiceNoteSubCommand.RequestAudioInfo,\n 0x00,\n ]);\n}\n\nexport function encodeVoiceNoteDelete(\n noteIndex: number,\n syncId: number,\n): Uint8Array {\n validateVoiceNoteIndex(noteIndex);\n return Uint8Array.from([\n G1Command.Note,\n 0x06,\n 0x00,\n syncId & 0xff,\n G1VoiceNoteSubCommand.DeleteAudioStream,\n noteIndex & 0xff,\n ]);\n}\n\nexport function encodeVoiceNoteDeleteAll(syncId: number): Uint8Array {\n return Uint8Array.from([\n G1Command.Note,\n 0x06,\n 0x00,\n syncId & 0xff,\n G1VoiceNoteSubCommand.DeleteAll,\n 0x00,\n ]);\n}\n\nexport function encodeNotification(\n payload: G1NotificationPayload,\n): Uint8Array[] {\n const nowSeconds = Math.floor(Date.now() / 1000);\n const model = {\n ncs_notification: {\n msg_id: payload.msgId ?? nowSeconds,\n type: payload.type ?? 1,\n app_identifier: payload.appIdentifier,\n title: payload.title,\n subtitle: payload.subtitle ?? \"\",\n message: payload.message,\n time_s: payload.timeS ?? nowSeconds,\n date:\n payload.date ??\n new Date((payload.timeS ?? nowSeconds) * 1000)\n .toISOString()\n .slice(0, 19)\n .replace(\"T\", \" \"),\n display_name: payload.displayName ?? payload.appIdentifier,\n },\n type: \"Add\",\n };\n const bytes = new TextEncoder().encode(JSON.stringify(model));\n const chunkSize = 176;\n const chunks: Uint8Array[] = [];\n const total = Math.max(1, Math.ceil(bytes.length / chunkSize));\n const packetMessageId = (payload.msgId ?? 0) & 0xff;\n for (let index = 0; index < total; index++) {\n const chunk = bytes.slice(index * chunkSize, (index + 1) * chunkSize);\n const packet = new Uint8Array(4 + chunk.length);\n packet.set([\n G1Command.Notification,\n packetMessageId,\n total & 0xff,\n index & 0xff,\n ]);\n packet.set(chunk, 4);\n chunks.push(packet);\n }\n return chunks;\n}\n\nexport function encodeBmpTransfer(imageData: Uint8Array): Uint8Array[] {\n const packets: Uint8Array[] = [];\n const packetSize = 194;\n for (\n let offset = 0, seq = 0;\n offset < imageData.length;\n offset += packetSize, seq++\n ) {\n const chunk = imageData.slice(offset, offset + packetSize);\n const prefix =\n seq === 0\n ? [G1Command.BmpData, seq & 0xff, 0x00, 0x1c, 0x00, 0x00]\n : [G1Command.BmpData, seq & 0xff];\n const packet = new Uint8Array(prefix.length + chunk.length);\n packet.set(prefix);\n packet.set(chunk, prefix.length);\n packets.push(packet);\n }\n packets.push(Uint8Array.from([G1Command.BmpEnd, 0x0d, 0x0e]));\n const crcInput = new Uint8Array(4 + imageData.length);\n crcInput.set([0x00, 0x1c, 0x00, 0x00]);\n crcInput.set(imageData, 4);\n const crc = crc32(crcInput);\n packets.push(\n Uint8Array.from([\n G1Command.BmpCrc,\n (crc >>> 24) & 0xff,\n (crc >>> 16) & 0xff,\n (crc >>> 8) & 0xff,\n crc & 0xff,\n ]),\n );\n return packets;\n}\n\nexport function encodeG1MonochromeBmp(\n pixels: ArrayLike<number> | Uint8Array,\n options: { width?: number; height?: number; threshold?: number } = {},\n): Uint8Array {\n const width = options.width ?? G1_BMP.width;\n const height = options.height ?? G1_BMP.height;\n const threshold = options.threshold ?? 128;\n if (!Number.isInteger(width) || width <= 0) {\n throw new RangeError(\"BMP width must be a positive integer\");\n }\n if (!Number.isInteger(height) || height <= 0) {\n throw new RangeError(\"BMP height must be a positive integer\");\n }\n const expectedPixels = width * height;\n if (pixels.length !== expectedPixels) {\n throw new RangeError(\n `Expected ${expectedPixels} monochrome pixels, got ${pixels.length}`,\n );\n }\n\n const rowStride = Math.ceil(width / 32) * 4;\n const pixelDataSize = rowStride * height;\n const pixelOffset = 14 + 40 + 8;\n const fileSize = pixelOffset + pixelDataSize;\n const out = new Uint8Array(fileSize);\n const view = new DataView(out.buffer);\n\n out.set([0x42, 0x4d], 0);\n view.setUint32(2, fileSize, true);\n view.setUint32(10, pixelOffset, true);\n view.setUint32(14, 40, true);\n view.setInt32(18, width, true);\n view.setInt32(22, height, true);\n view.setUint16(26, 1, true);\n view.setUint16(28, 1, true);\n view.setUint32(34, pixelDataSize, true);\n view.setUint32(46, 2, true);\n view.setUint32(50, 2, true);\n out.set([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00], 54);\n\n for (let y = 0; y < height; y++) {\n const sourceY = height - 1 - y;\n const rowOffset = pixelOffset + y * rowStride;\n for (let x = 0; x < width; x++) {\n const source = pixels[sourceY * width + x] ?? 0;\n if (source < threshold) continue;\n out[rowOffset + (x >> 3)] |= 0x80 >> (x & 0x07);\n }\n }\n return out;\n}\n\nexport function parseG1Notification(\n side: GlassSide,\n data: Uint8Array,\n): G1Event {\n const command = data[0];\n if (command === G1Command.StartAi) {\n const code = data[1];\n const state = classifyStateCode(code);\n return {\n side,\n raw: data,\n type: \"state\",\n code,\n label: state?.label ?? `unknown_0x${code?.toString(16)}`,\n stateCategory: state?.category,\n stateName: state?.name,\n };\n }\n if (command === G1Command.OpenMic) {\n const responseStatus = data.length >= 3 ? data[1] : undefined;\n const requested = data[data.length - 1];\n const responseOk =\n responseStatus === undefined ||\n responseStatus === G1ResponseStatus.Success;\n const micRequested = requested === G1MicStatus.Enable;\n return {\n side,\n raw: data,\n type: \"mic-response\",\n micEnabled: responseOk ? micRequested : !micRequested,\n micRequested,\n responseStatus,\n responseOk,\n code: requested,\n label:\n responseOk && micRequested\n ? \"mic_enabled\"\n : responseOk\n ? \"mic_disabled\"\n : \"mic_failed\",\n };\n }\n if (command === G1Command.ReceiveMicData) {\n return {\n side,\n raw: data,\n type: \"mic-data\",\n sequence: data[1],\n audioData: data.slice(2),\n audioEncoding: \"lc3\",\n label: \"mic_data\",\n };\n }\n if (command === G1Command.Init || command === G1Command.RightInit) {\n return {\n side,\n raw: data,\n type: \"init\",\n code: data[1],\n label: command === G1Command.RightInit ? \"right_init\" : \"init\",\n };\n }\n if (command === G1Command.SendResult) {\n return parseDisplayResult(side, data);\n }\n if (command === G1Command.Notification) {\n return parseNotificationChunk(side, data);\n }\n if (command === G1Command.QuickNote) {\n return parseVoiceNoteList(side, data);\n }\n if (\n command === G1Command.Note &&\n data.length >= 11 &&\n data[4] === G1VoiceNoteSubCommand.RequestAudioData\n ) {\n const totalPackets = readUint16LE(data, 5);\n const currentPacket = readUint16LE(data, 7);\n const noteIndex = Math.max(0, (data[9] ?? 1) - 1);\n return {\n side,\n raw: data,\n type: \"voice-note-audio\",\n syncId: data[3],\n subcommand: data[4],\n totalPackets,\n currentPacket,\n noteIndex,\n sequence: currentPacket,\n audioData: data.slice(10),\n audioEncoding: \"lc3\",\n label: \"voice_note_audio\",\n };\n }\n if (command === G1Command.Dashboard) {\n const code = data[1];\n return {\n side,\n raw: data,\n type: \"dashboard\",\n code,\n label: `dashboard_0x${code?.toString(16).padStart(2, \"0\")}`,\n };\n }\n if (command === G1Command.GetSerial) {\n const serialNumber = new TextDecoder()\n .decode(data.slice(2, 18))\n .replace(/\\0+$/g, \"\");\n return {\n side,\n raw: data,\n type: \"serial\",\n code: data[1],\n responseStatus: data[1],\n responseOk: data[1] === undefined || data[1] === G1ResponseStatus.Success,\n serialNumber,\n label: \"serial_number\",\n };\n }\n if (command === G1Command.Heartbeat) {\n return { side, raw: data, type: \"heartbeat\", label: \"heartbeat\" };\n }\n if (command === G1Command.Battery) {\n return parseBatteryStatus(side, data);\n }\n if (command === 0x03) {\n return {\n side,\n raw: data,\n type: \"response\",\n code: data[1],\n label: \"response\",\n };\n }\n if (command === 0x04) {\n return {\n side,\n raw: data,\n type: \"error\",\n code: data[1],\n label: `error_0x${data[1]?.toString(16).padStart(2, \"0\")}`,\n };\n }\n return {\n side,\n raw: data,\n type: \"unknown\",\n code: command,\n label: `unknown_0x${command?.toString(16)}`,\n };\n}\n\nfunction parseBatteryStatus(side: GlassSide, data: Uint8Array): G1Event {\n if (data.length < 6 || data[1] !== 0x66) {\n return {\n side,\n raw: data,\n type: \"battery-status\",\n responseStatus: data[1],\n responseOk: false,\n label: \"battery_status_invalid\",\n };\n }\n return {\n side,\n raw: data,\n type: \"battery-status\",\n responseStatus: data[1],\n responseOk: true,\n batteryPercent: data[2],\n batteryFlags: data[3],\n batteryVoltageMv: (((data[5] ?? 0) << 8) | (data[4] ?? 0)) / 10,\n label: \"battery_status\",\n };\n}\n\nfunction parseDisplayResult(side: GlassSide, data: Uint8Array): G1Event {\n if (data.length < 9) {\n return {\n side,\n raw: data,\n type: \"display-result\",\n label: \"display_result_invalid\",\n };\n }\n const textBytes = data.slice(9);\n return {\n side,\n raw: data,\n type: \"display-result\",\n displaySeq: data[1],\n totalPackages: data[2],\n currentPackage: data[3],\n screenStatus: data[4],\n charPosition: readUint16BE(data, 5),\n pageNumber: data[7],\n maxPages: data[8],\n text: new TextDecoder().decode(textBytes),\n label: \"display_result\",\n };\n}\n\nfunction parseNotificationChunk(side: GlassSide, data: Uint8Array): G1Event {\n if (data.length < 4) {\n return {\n side,\n raw: data,\n type: \"notification\",\n label: \"notification_invalid\",\n };\n }\n const notificationChunk = data.slice(4);\n return {\n side,\n raw: data,\n type: \"notification\",\n notificationId: data[1],\n totalPackages: data[2],\n currentPackage: data[3],\n notificationChunk,\n text: new TextDecoder().decode(notificationChunk),\n label: \"notification\",\n };\n}\n\nfunction parseVoiceNoteList(side: GlassSide, data: Uint8Array): G1Event {\n const length = readUint16LE(data, 1);\n const syncId = data[3];\n const subcommand = data[4];\n if (\n data.length < 6 ||\n subcommand !== G1VoiceNoteSubCommand.RequestAudioInfo\n ) {\n return {\n side,\n raw: data,\n type: \"voice-note-list\",\n syncId,\n subcommand,\n voiceNotes: [],\n label: \"voice_note_list_invalid\",\n };\n }\n const noteCount = data[5] ?? 0;\n const expectedLength = 6 + noteCount * 9;\n const boundedLength = Math.min(data.length, Math.max(length, expectedLength));\n const voiceNotes: G1VoiceNoteEntry[] = [];\n for (\n let offset = 6;\n offset + 8 < boundedLength && voiceNotes.length < noteCount;\n offset += 9\n ) {\n voiceNotes.push({\n index: data[offset],\n timestamp: readUint32LE(data, offset + 1),\n crc: readUint32LE(data, offset + 5),\n });\n }\n return {\n side,\n raw: data,\n type: \"voice-note-list\",\n syncId,\n subcommand,\n voiceNotes,\n label: \"voice_note_list\",\n };\n}\n\nexport function pcm16ToFloat32(bytes: Uint8Array): Float32Array {\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const out = new Float32Array(Math.floor(bytes.byteLength / 2));\n for (let i = 0; i < out.length; i++)\n out[i] = view.getInt16(i * 2, true) / 32768;\n return out;\n}\n\nfunction validateNoteNumber(noteNumber: number): void {\n if (!Number.isInteger(noteNumber) || noteNumber < 1 || noteNumber > 4) {\n throw new RangeError(\"Note number must be an integer between 1 and 4\");\n }\n}\n\nfunction validateVoiceNoteIndex(noteIndex: number): void {\n if (!Number.isInteger(noteIndex) || noteIndex < 0 || noteIndex > 255) {\n throw new RangeError(\n \"G1 voice note index must be an integer from 0 to 255\",\n );\n }\n}\n\nfunction validateBitPlanes(\n image: ArrayLike<number>,\n overlay: ArrayLike<number>,\n expectedLength: number,\n label: string,\n): void {\n if (image.length !== expectedLength || overlay.length !== expectedLength) {\n throw new RangeError(\n `Expected ${expectedLength} bits for ${label} and overlay`,\n );\n }\n}\n\nfunction runLengthEncodeBits(data: number[]): number[] {\n if (data.length === 0) return [];\n const encoded: number[] = [];\n let current = data[0] ? 1 : 0;\n let count = 1;\n for (let index = 1; index < data.length; index++) {\n const bit = data[index] ? 1 : 0;\n if (bit === current && count < 255) {\n count += 1;\n continue;\n }\n encoded.push(count, current);\n current = bit;\n count = 1;\n }\n encoded.push(count, current);\n return encoded;\n}\n\nfunction encodeNavigationImagePackets(\n bytes: number[],\n partType: number,\n startSeqId: number,\n includeExtraZero: boolean,\n): Uint8Array[] {\n const maxPayload = 185;\n const packetCount = Math.max(1, Math.ceil(bytes.length / maxPayload));\n const packets: Uint8Array[] = [];\n let seqId = startSeqId & 0xff;\n for (let index = 0; index < packetCount; index++) {\n const chunk = bytes.slice(index * maxPayload, (index + 1) * maxPayload);\n const part = [\n 0x00,\n seqId,\n partType,\n packetCount & 0xff,\n 0x00,\n (index + 1) & 0xff,\n 0x00,\n ...(includeExtraZero ? [0x00] : []),\n ...chunk.map((byte) => byte & 0xff),\n ];\n packets.push(\n Uint8Array.from([\n G1Command.Navigation,\n (part.length + 2) & 0xff,\n ...part,\n ]),\n );\n seqId = (seqId + 1) & 0xff;\n }\n return packets;\n}\n\nfunction readUint16LE(data: Uint8Array, offset: number): number {\n return (data[offset] ?? 0) | ((data[offset + 1] ?? 0) << 8);\n}\n\nfunction readUint16BE(data: Uint8Array, offset: number): number {\n return ((data[offset] ?? 0) << 8) | (data[offset + 1] ?? 0);\n}\n\nfunction readUint32LE(data: Uint8Array, offset: number): number {\n return (\n ((data[offset] ?? 0) |\n ((data[offset + 1] ?? 0) << 8) |\n ((data[offset + 2] ?? 0) << 16) |\n ((data[offset + 3] ?? 0) << 24)) >>>\n 0\n );\n}\n\nfunction crc32(bytes: Uint8Array): number {\n let crc = 0xffffffff;\n for (const byte of bytes) {\n crc ^= byte;\n for (let bit = 0; bit < 8; bit++) {\n crc = crc & 1 ? (crc >>> 1) ^ 0xedb88320 : crc >>> 1;\n }\n }\n return (crc ^ 0xffffffff) >>> 0;\n}\n","// Pure smartglasses report/diagnostics helpers split out of SmartglassesView.tsx\n// so that file exports only the React component and stays Fast-Refresh-compatible\n// (Vite full-reloads a component file that also exports plain functions/types).\n// SmartglassesView.tsx and the report test both import from here.\n\nimport {\n type DisplayPage,\n encodeTextPackets,\n G1AiStatus,\n G1ScreenAction,\n G1TextStatus,\n type GlassSide,\n paginateDisplayText,\n type SmartglassesAudioEncoding,\n} from \"../protocol/smartglasses.ts\";\n\nexport type LensState = \"idle\" | \"prompting\" | \"connected\" | \"failed\";\nexport type ViewScanDiagnosis =\n | \"not_scanned\"\n | \"left_lens_missing\"\n | \"right_lens_missing\"\n | \"whole_headset_seen\"\n | \"pairing_failed\";\nexport type ViewPhysicalBlocker =\n | \"not_connected\"\n | \"partial_headset\"\n | \"in_charging_base\"\n | \"wearing_state_missing\"\n | \"evidence_missing\"\n | null;\n\nexport interface ReportEvent {\n at: string;\n type: string;\n detail: string;\n}\n\nexport interface ReportWrite {\n at: string;\n side: GlassSide | \"both\";\n command: string;\n bytes: number;\n hex: string;\n}\n\nexport interface ReportAudio {\n at: string;\n side: GlassSide;\n sampleRate: number;\n encoding: SmartglassesAudioEncoding | null;\n sequence?: number;\n bytes: number;\n}\n\nexport interface HardwareReport {\n ok: boolean;\n generatedAt: string;\n transport: string | null;\n connected: boolean;\n lenses: Record<GlassSide, LensState>;\n scanDiagnosis: ViewScanDiagnosis;\n physicalBlocker: ViewPhysicalBlocker;\n setupHint: string | null;\n nextAction: string | null;\n serialNumber: string | null;\n tests: Record<string, boolean>;\n missingEvidence: string[];\n events: ReportEvent[];\n writes: ReportWrite[];\n audio: ReportAudio[];\n wifi: {\n available: boolean;\n status: string;\n networks: string[];\n };\n headsetState: {\n physical: string | null;\n battery: string | null;\n batteryLevels: Partial<Record<GlassSide, number>>;\n device: string | null;\n };\n}\n\ntype BridgeResult = unknown;\ntype BridgeSubscription =\n | undefined\n | (() => void)\n | { unsubscribe?: () => void; off?: () => void; remove?: () => void };\n\nexport type SmartglassesBridge = {\n requestWifiScan?: () => Promise<BridgeResult> | BridgeResult;\n requestWifiStatus?: () => Promise<BridgeResult> | BridgeResult;\n requestWifiSetup?: (reason?: string) => Promise<BridgeResult> | BridgeResult;\n setWifiCredentials?: (\n ssid: string,\n password: string,\n ) => Promise<BridgeResult> | BridgeResult;\n sendWifiCredentials?: (\n ssid: string,\n password: string,\n ) => Promise<BridgeResult> | BridgeResult;\n audioControl?: (enabled: boolean) => Promise<BridgeResult> | BridgeResult;\n clearDisplay?: () => Promise<BridgeResult> | BridgeResult;\n createStartUpPageContainer?: (\n container: Record<string, unknown>,\n ) => Promise<BridgeResult> | BridgeResult;\n displayText?: (\n params: Record<string, unknown>,\n ) => Promise<BridgeResult> | BridgeResult;\n onEvent?: (callback: (event: unknown) => void) => BridgeSubscription;\n onEvenHubEvent?: (callback: (event: unknown) => void) => BridgeSubscription;\n rebuildPageContainer?: (\n container: Record<string, unknown>,\n ) => Promise<BridgeResult> | BridgeResult;\n sendStartUpPage?: (\n container: unknown,\n ) => Promise<BridgeResult> | BridgeResult;\n setMicState?: (\n sendPcmData: boolean,\n sendTranscript: boolean,\n bypassVad: boolean,\n ) => Promise<BridgeResult> | BridgeResult;\n write?: (\n side: GlassSide,\n data: Uint8Array,\n ) => Promise<BridgeResult> | BridgeResult;\n send?: (\n side: GlassSide,\n data: Uint8Array,\n ) => Promise<BridgeResult> | BridgeResult;\n rawBridge?: {\n audioControl?: (enabled: boolean) => Promise<BridgeResult> | BridgeResult;\n callEvenApp?: (\n name: string,\n payload?: Record<string, unknown>,\n ) => Promise<BridgeResult> | BridgeResult;\n };\n};\n\nexport function isMicEnableTap(label?: string | null): boolean {\n return label === \"single_tap\" || label === \"long_press\";\n}\n\nexport function isMicDisableTap(label?: string | null): boolean {\n return label === \"double_tap\" || label === \"stop_ai_recording\";\n}\n\nfunction reportTimeMs(value: string): number | null {\n const ms = Date.parse(value);\n return Number.isFinite(ms) ? ms : null;\n}\n\nfunction reportHappenedAfter(\n later: { at: string },\n earlier: { at: string },\n): boolean {\n const laterMs = reportTimeMs(later.at);\n const earlierMs = reportTimeMs(earlier.at);\n return laterMs !== null && earlierMs !== null ? laterMs >= earlierMs : false;\n}\n\nfunction hasTapDrivenViewMicWrite(\n events: ReportEvent[],\n writes: ReportWrite[],\n mode: \"enable\" | \"disable\",\n): boolean {\n const isTap = mode === \"enable\" ? isMicEnableTap : isMicDisableTap;\n const expectedHex = mode === \"enable\" ? \"0e01\" : \"0e00\";\n const tapEvents = events.filter((event) => isTap(event.detail));\n const micWrites = writes.filter(\n (write) =>\n write.side === \"right\" &&\n write.command === \"open-mic\" &&\n write.hex.startsWith(expectedHex),\n );\n return tapEvents.some((event) =>\n micWrites.some((write) => reportHappenedAfter(write, event)),\n );\n}\n\nexport function isCradleOrChargingState(\n physicalState: string | null,\n batteryState: string | null,\n): boolean {\n return (\n physicalState === \"cradle_open\" ||\n physicalState === \"cradle_closed\" ||\n physicalState === \"charged_in_cradle\" ||\n batteryState === \"glasses_fully_charged\" ||\n batteryState === \"cradle_charging_cable_changed\" ||\n batteryState === \"cradle_fully_charged\"\n );\n}\n\nexport function headsetValidationBlocker(\n physicalState: string | null,\n batteryState: string | null,\n): string | null {\n if (physicalState === \"wearing\") return null;\n const stateText =\n [physicalState, batteryState].filter(Boolean).join(\" / \") ||\n \"no wearing state observed\";\n if (isCradleOrChargingState(physicalState, batteryState)) {\n return `Glasses are still reporting ${stateText}. Remove them from the charging base and wear them before tap or microphone validation.`;\n }\n return `Tap and microphone validation requires a wearing state; current state is ${stateText}.`;\n}\n\nexport function missingViewEvidence(\n tests: Record<string, boolean>,\n lenses: Record<GlassSide, LensState>,\n physicalState: string | null,\n batteryState: string | null,\n events: ReportEvent[] = [],\n writes: ReportWrite[] = [],\n): string[] {\n const hasTapDrivenEnableWrite = hasTapDrivenViewMicWrite(\n events,\n writes,\n \"enable\",\n );\n const hasTapDrivenDisableWrite = hasTapDrivenViewMicWrite(\n events,\n writes,\n \"disable\",\n );\n const missing = [\n lenses.left !== \"connected\" && \"leftLensConnected\",\n lenses.right !== \"connected\" && \"rightLensConnected\",\n physicalState !== \"wearing\" && \"wearingStateObserved\",\n isCradleOrChargingState(physicalState, batteryState) && \"headsetInCradle\",\n !tests.init && \"connectionReadySent\",\n !tests.display && \"displayPacketsSent\",\n !tests.serial && \"serialRequested\",\n !tests.serialObserved && \"serialObserved\",\n !tests.settings && \"settingsSent\",\n !hasTapDrivenEnableWrite && \"rightMicEnableWrite\",\n !hasTapDrivenDisableWrite && \"rightMicDisableWrite\",\n !tests.tapMicEnable && \"tapMicEnable\",\n !tests.tapMicDisable && \"tapMicDisable\",\n !tests.audio && \"rightOrBridgeAudio\",\n ].filter((value): value is string => typeof value === \"string\");\n return [...new Set(missing)];\n}\n\nexport function viewScanDiagnosis(\n lenses: Record<GlassSide, LensState>,\n): ViewScanDiagnosis {\n if (lenses.left === \"connected\" && lenses.right === \"connected\") {\n return \"whole_headset_seen\";\n }\n if (lenses.left === \"failed\" || lenses.right === \"failed\") {\n return \"pairing_failed\";\n }\n if (lenses.left === \"connected\") return \"right_lens_missing\";\n if (lenses.right === \"connected\") return \"left_lens_missing\";\n return \"not_scanned\";\n}\n\nexport function viewPhysicalBlocker(\n tests: Record<string, boolean>,\n lenses: Record<GlassSide, LensState>,\n physicalState: string | null,\n batteryState: string | null,\n events: ReportEvent[] = [],\n writes: ReportWrite[] = [],\n): ViewPhysicalBlocker {\n const wholeHeadset =\n lenses.left === \"connected\" && lenses.right === \"connected\";\n if (\n !wholeHeadset &&\n (lenses.left === \"connected\" || lenses.right === \"connected\")\n ) {\n return \"partial_headset\";\n }\n if (!wholeHeadset) return \"not_connected\";\n if (isCradleOrChargingState(physicalState, batteryState)) {\n return \"in_charging_base\";\n }\n if (physicalState !== \"wearing\") return \"wearing_state_missing\";\n return missingViewEvidence(\n tests,\n lenses,\n physicalState,\n batteryState,\n events,\n writes,\n ).length\n ? \"evidence_missing\"\n : null;\n}\n\nexport function viewSetupHint(\n blocker: ViewPhysicalBlocker,\n physicalState: string | null,\n batteryState: string | null,\n): string | null {\n if (blocker === \"not_connected\") {\n return \"Connect both left and right lenses as one headset before running validation.\";\n }\n if (blocker === \"partial_headset\") {\n return \"Reconnect the whole headset so both left and right lenses are present.\";\n }\n if (blocker === \"in_charging_base\" || blocker === \"wearing_state_missing\") {\n return headsetValidationBlocker(physicalState, batteryState);\n }\n if (blocker === \"evidence_missing\") {\n return \"Run check, then guided validation to capture display, settings, side taps, mic writes, and audio.\";\n }\n return null;\n}\n\nexport function viewNextAction(blocker: ViewPhysicalBlocker): string | null {\n if (blocker === \"not_connected\") return \"Connect Headset\";\n if (blocker === \"partial_headset\") return \"Reconnect the missing lens\";\n if (blocker === \"in_charging_base\") {\n return \"Remove the glasses from the charging base and wear them\";\n }\n if (blocker === \"wearing_state_missing\") {\n return \"Wear the glasses until wearing state appears\";\n }\n if (blocker === \"evidence_missing\") return \"Run Check and Guided Validation\";\n return null;\n}\n\nexport function viewCommandName(data: Uint8Array): string {\n switch (data[0]) {\n case 0x01:\n return \"brightness\";\n case 0x0e:\n return \"open-mic\";\n case 0x1c:\n return \"silent-mode\";\n case 0x2c:\n return \"battery-status\";\n case 0x34:\n return \"get-serial\";\n case 0x4d:\n return \"init\";\n case 0x4e:\n return \"display-result\";\n case 0xf4:\n return \"right-init\";\n default:\n return data.length > 0\n ? `0x${data[0].toString(16).padStart(2, \"0\")}`\n : \"empty\";\n }\n}\n\nfunction withViewScreenStatus(\n page: DisplayPage,\n screenStatus: number,\n): DisplayPage {\n return { ...page, screenStatus };\n}\n\nfunction viewStreamingStatus(mode: \"ai\" | \"text\", pageIndex: number): number {\n if (mode === \"text\") return G1TextStatus.TextShow | G1ScreenAction.NewContent;\n return pageIndex === 0\n ? G1AiStatus.Displaying | G1ScreenAction.NewContent\n : G1AiStatus.Displaying;\n}\n\nexport function buildViewDisplayPackets(\n text: string,\n options: {\n startSeq?: number;\n mode?: \"ai\" | \"text\";\n includeCompletion?: boolean;\n } = {},\n): { packets: Uint8Array[]; pages: number; nextSeq: number } {\n const mode = options.mode ?? \"ai\";\n let seq = options.startSeq ?? 0;\n const packets: Uint8Array[] = [];\n const pages = paginateDisplayText(text);\n for (const [pageIndex, page] of pages.entries()) {\n packets.push(\n ...encodeTextPackets(\n withViewScreenStatus(page, viewStreamingStatus(mode, pageIndex)),\n seq,\n ),\n );\n seq = (seq + 1) & 0xff;\n }\n if (mode !== \"text\" && options.includeCompletion !== false) {\n const lastPage = pages.at(-1);\n if (lastPage) {\n packets.push(\n ...encodeTextPackets(\n withViewScreenStatus(lastPage, G1AiStatus.DisplayComplete),\n seq,\n ),\n );\n seq = (seq + 1) & 0xff;\n }\n }\n return { packets, pages: pages.length, nextSeq: seq };\n}\n\nexport function parseWifiNetworks(result: unknown): string[] {\n if (!result || typeof result !== \"object\") return [];\n const value = result as Record<string, unknown>;\n const networks =\n value.networks ??\n value.wifiNetworks ??\n value.accessPoints ??\n value.networks_neo ??\n value.results;\n if (!Array.isArray(networks)) return [];\n return networks\n .map((network) => {\n if (typeof network === \"string\") return network;\n if (network && typeof network === \"object\") {\n const record = network as Record<string, unknown>;\n return String(record.ssid ?? record.SSID ?? record.name ?? \"\");\n }\n return \"\";\n })\n .map((network) => network.trim())\n .filter((network) => network.length > 0);\n}\n\nexport function formatWifiStatus(\n result: unknown,\n fallback = \"Wi-Fi status requested\",\n): string {\n if (!result || typeof result !== \"object\") return fallback;\n const value = result as Record<string, unknown>;\n const explicitStatus = value.status ?? value.state ?? value.message;\n if (typeof explicitStatus === \"string\" && explicitStatus.trim()) {\n return explicitStatus.trim();\n }\n const connected = value.connected ?? value.wifiConnected;\n const ssid = value.ssid ?? value.wifiSsid ?? value.SSID;\n const localIp = value.localIp ?? value.wifiLocalIp ?? value.ipAddress;\n if (connected === true) {\n return `Connected to ${String(ssid ?? \"Wi-Fi\")}${\n localIp ? ` at ${String(localIp)}` : \"\"\n }`;\n }\n if (connected === false) return \"Wi-Fi disconnected\";\n return fallback;\n}\n\nexport async function callWifiBridge(\n bridge: SmartglassesBridge,\n command: string,\n payload?: Record<string, unknown>,\n): Promise<unknown> {\n if (command === \"request_wifi_scan\" && bridge.requestWifiScan) {\n return bridge.requestWifiScan();\n }\n if (command === \"request_wifi_status\" && bridge.requestWifiStatus) {\n return bridge.requestWifiStatus();\n }\n if (command === \"request_wifi_setup\" && bridge.requestWifiSetup) {\n return bridge.requestWifiSetup(String(payload?.reason ?? \"\"));\n }\n if (command === \"set_wifi_credentials\") {\n const ssid = String(payload?.ssid ?? \"\");\n const password = String(payload?.password ?? \"\");\n if (bridge.setWifiCredentials) {\n return bridge.setWifiCredentials(ssid, password);\n }\n if (bridge.sendWifiCredentials) {\n return bridge.sendWifiCredentials(ssid, password);\n }\n }\n if (bridge.rawBridge?.callEvenApp) {\n return bridge.rawBridge.callEvenApp(command, payload);\n }\n throw new Error(\n `Native smartglasses bridge does not support Wi-Fi command: ${command}`,\n );\n}\n","/**\n * SmartglassesSpatialView - the Even Realities smartglasses diagnostics surface\n * authored once with the spatial vocabulary, so it renders correctly wherever\n * it is displayed:\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 smartglasses report (`HardwareReport`, `GlassSide`), so it is safe to\n * render in the Node agent process where the terminal lives (no transport or\n * BLE runtime import).\n *\n * The full GUI dashboard (`SmartglassesView.tsx`) is unchanged; this view is the\n * shared operator panel that reads the same computed `HardwareReport` the GUI\n * builds, plus the live state the GUI tracks (Wi-Fi, mic, test text, events).\n */\n\nimport {\n Button,\n Card,\n Divider,\n Field,\n HStack,\n List,\n type SpatialTone,\n Text,\n} from \"@elizaos/ui/spatial\";\nimport type { GlassSide } from \"../protocol/smartglasses.ts\";\nimport type {\n HardwareReport,\n LensState,\n} from \"../ui/SmartglassesView.helpers.ts\";\n\n/** Visible row caps - mirror the GUI dashboard (`SmartglassesView.tsx`). */\nconst VISIBLE_TEST_LIMIT = 8;\nconst VISIBLE_EVENT_LIMIT = 12;\nconst VISIBLE_WIFI_LIMIT = 5;\n\nexport type SmartglassesPlatform = \"desktop\" | \"ios\" | \"android\";\n\nexport interface SmartglassesSnapshot {\n /** The computed hardware report - identical shape to the GUI's `report`. */\n report: HardwareReport;\n /** Live operator state the GUI tracks alongside the report. */\n micEnabled: boolean;\n wifiSsid: string;\n wifiPassword: string;\n testText: string;\n activePlatform: SmartglassesPlatform;\n /** Label of the in-flight operation, or null when idle. */\n busy: string | null;\n /** Last operator-facing error, or null. */\n error: string | null;\n}\n\nfunction lensTone(state: LensState): SpatialTone {\n switch (state) {\n case \"connected\":\n return \"success\";\n case \"failed\":\n return \"danger\";\n case \"prompting\":\n return \"warning\";\n default:\n return \"muted\";\n }\n}\n\nfunction lensMark(state: LensState): string {\n switch (state) {\n case \"connected\":\n return \"[ok]\";\n case \"failed\":\n return \"[x]\";\n case \"prompting\":\n return \"[..]\";\n default:\n return \"[ ]\";\n }\n}\n\nfunction passTone(pass: boolean): SpatialTone {\n return pass ? \"success\" : \"muted\";\n}\n\nfunction passMark(pass: boolean): string {\n return pass ? \"[ok]\" : \"[ ]\";\n}\n\n/** Human-friendly battery summary from the report headset state. */\nfunction batterySummary(\n levels: Partial<Record<GlassSide, number>>,\n): string | null {\n const parts: string[] = [];\n if (typeof levels.left === \"number\") parts.push(`L ${levels.left}%`);\n if (typeof levels.right === \"number\") parts.push(`R ${levels.right}%`);\n return parts.length > 0 ? parts.join(\" \") : null;\n}\n\nexport interface SmartglassesSpatialViewProps {\n snapshot: SmartglassesSnapshot;\n /**\n * Dispatch by agent id: `connect`, `run-check`, `clear-display`,\n * `display-test`, `mic-toggle`, `wifi-scan`, `wifi-status`, `wifi-save`,\n * `platform:<desktop|ios|android>`.\n */\n onAction?: (action: string) => void;\n}\n\nexport function SmartglassesSpatialView({\n snapshot,\n onAction,\n}: SmartglassesSpatialViewProps) {\n const dispatch = (action: string) => () => onAction?.(action);\n const { report } = snapshot;\n const testEntries = Object.entries(report.tests);\n const hiddenTests = Math.max(0, testEntries.length - VISIBLE_TEST_LIMIT);\n const hiddenEvents = Math.max(0, report.events.length - VISIBLE_EVENT_LIMIT);\n const hiddenWifi = Math.max(\n 0,\n report.wifi.networks.length - VISIBLE_WIFI_LIMIT,\n );\n const battery = batterySummary(report.headsetState.batteryLevels);\n // Newest-first window over the event log, keyed by absolute index so keys are\n // stable across renders even when two events share a timestamp.\n const eventStart = Math.max(0, report.events.length - VISIBLE_EVENT_LIMIT);\n const recentEvents = report.events\n .slice(eventStart)\n .map((event, offset) => ({ ...event, key: eventStart + offset }))\n .reverse();\n\n return (\n <Card gap={1} padding={1}>\n <HStack gap={1} align=\"center\">\n <Text\n style=\"caption\"\n tone={report.ok ? \"success\" : report.connected ? \"warning\" : \"danger\"}\n grow={1}\n >\n {report.ok\n ? \"validated\"\n : report.connected\n ? \"connected\"\n : \"disconnected\"}\n </Text>\n <Text style=\"caption\" tone=\"muted\">\n {snapshot.busy ? snapshot.busy : (report.transport ?? \"no transport\")}\n </Text>\n </HStack>\n\n {snapshot.error ? (\n <Text tone=\"danger\" style=\"caption\">\n {snapshot.error}\n </Text>\n ) : null}\n\n <HStack gap={1} align=\"center\">\n <Text style=\"caption\" tone={lensTone(report.lenses.left)} grow={1}>\n {lensMark(report.lenses.left)} left\n </Text>\n <Text style=\"caption\" tone={lensTone(report.lenses.right)} grow={1}>\n {lensMark(report.lenses.right)} right\n </Text>\n </HStack>\n\n <HStack gap={1} align=\"center\">\n <Text style=\"caption\" tone=\"muted\" grow={1}>\n {report.serialNumber ? `sn ${report.serialNumber}` : \"sn unknown\"}\n </Text>\n {battery ? (\n <Text style=\"caption\" tone=\"muted\">\n {battery}\n </Text>\n ) : null}\n </HStack>\n\n {report.setupHint ? (\n <Text style=\"caption\" tone=\"warning\">\n {report.setupHint}\n </Text>\n ) : null}\n\n <Divider label=\"diagnostics\" />\n <List gap={0}>\n {testEntries.slice(0, VISIBLE_TEST_LIMIT).map(([name, pass]) => (\n <HStack key={name} gap={1} align=\"center\" agent={`test-${name}`}>\n <Text tone={passTone(pass)}>{passMark(pass)}</Text>\n <Text style=\"caption\" grow={1} wrap={false}>\n {name}\n </Text>\n </HStack>\n ))}\n </List>\n {hiddenTests > 0 ? (\n <Text style=\"caption\" tone=\"muted\">\n +{hiddenTests} checks\n </Text>\n ) : null}\n\n <Divider label=\"controls\" />\n <HStack gap={1} wrap>\n <Button\n grow={1}\n tone={report.connected ? \"default\" : \"primary\"}\n variant={report.connected ? \"outline\" : \"solid\"}\n agent=\"connect\"\n onPress={dispatch(\"connect\")}\n >\n {report.connected ? \"Reconnect\" : \"Connect\"}\n </Button>\n <Button\n variant=\"outline\"\n tone=\"default\"\n grow={1}\n agent=\"run-check\"\n onPress={dispatch(\"run-check\")}\n >\n Run Check\n </Button>\n <Button\n variant={snapshot.micEnabled ? \"solid\" : \"outline\"}\n tone={snapshot.micEnabled ? \"success\" : \"default\"}\n agent=\"mic-toggle\"\n onPress={dispatch(\"mic-toggle\")}\n >\n {snapshot.micEnabled ? \"Mic on\" : \"Mic off\"}\n </Button>\n </HStack>\n\n <Field\n label=\"Display text\"\n value={snapshot.testText}\n placeholder=\"Text to send to both lenses\"\n agent=\"test-text\"\n />\n <HStack gap={1} wrap>\n <Button\n grow={1}\n agent=\"display-test\"\n onPress={dispatch(\"display-test\")}\n >\n Send Display\n </Button>\n <Button\n variant=\"ghost\"\n tone=\"danger\"\n agent=\"clear-display\"\n onPress={dispatch(\"clear-display\")}\n >\n Clear\n </Button>\n </HStack>\n\n <Divider label=\"wi-fi\" />\n <HStack gap={1} align=\"center\">\n <Text style=\"caption\" tone=\"muted\" grow={1} wrap={false}>\n {report.wifi.status}\n </Text>\n <Text style=\"caption\" tone={report.wifi.available ? \"muted\" : \"danger\"}>\n {report.wifi.available ? \"bridge\" : \"no bridge\"}\n </Text>\n </HStack>\n <Field\n label=\"SSID\"\n value={snapshot.wifiSsid}\n placeholder=\"Network name\"\n agent=\"wifi-ssid\"\n />\n <Field\n label=\"Password\"\n kind=\"password\"\n value={snapshot.wifiPassword}\n placeholder=\"Network password\"\n agent=\"wifi-password\"\n />\n <HStack gap={1} wrap>\n <Button\n variant=\"outline\"\n tone=\"default\"\n grow={1}\n agent=\"wifi-scan\"\n onPress={dispatch(\"wifi-scan\")}\n >\n Scan\n </Button>\n <Button\n variant=\"outline\"\n tone=\"default\"\n grow={1}\n agent=\"wifi-status\"\n onPress={dispatch(\"wifi-status\")}\n >\n Status\n </Button>\n <Button grow={1} agent=\"wifi-save\" onPress={dispatch(\"wifi-save\")}>\n Save Wi-Fi\n </Button>\n </HStack>\n {report.wifi.networks.length === 0 ? (\n <Text style=\"caption\" tone=\"muted\">\n None\n </Text>\n ) : (\n <List gap={0}>\n {report.wifi.networks.slice(0, VISIBLE_WIFI_LIMIT).map((network) => (\n <Text key={network} style=\"caption\" wrap={false}>\n {network}\n </Text>\n ))}\n </List>\n )}\n {hiddenWifi > 0 ? (\n <Text style=\"caption\" tone=\"muted\">\n +{hiddenWifi} more\n </Text>\n ) : null}\n\n <Divider label=\"events\" />\n {report.events.length === 0 ? (\n <Text style=\"caption\" tone=\"muted\" align=\"center\">\n None\n </Text>\n ) : (\n <List gap={0}>\n {recentEvents.map((event) => (\n <HStack key={event.key} gap={1} align=\"center\">\n <Text style=\"caption\" tone=\"primary\" wrap={false}>\n {event.type}\n </Text>\n <Text style=\"caption\" tone=\"muted\" grow={1} wrap={false}>\n {event.detail}\n </Text>\n </HStack>\n ))}\n </List>\n )}\n {hiddenEvents > 0 ? (\n <Text style=\"caption\" tone=\"muted\">\n +{hiddenEvents} older events\n </Text>\n ) : null}\n </Card>\n );\n}\n","/**\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.ts\";\nimport {\n type SmartglassesPlatform,\n type SmartglassesSnapshot,\n SmartglassesSpatialView,\n} from \"./SmartglassesSpatialView.tsx\";\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","import { TerminalPluginView } from \"@elizaos/ui\";\nimport { useAgentElement } from \"@elizaos/ui/agent-surface\";\nimport { Bluetooth, Glasses, Wifi, Zap } from \"lucide-react\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport {\n type ConnectedDevice,\n FACEWEAR_DEVICE_PROFILES,\n type FacewearDeviceProfileRow,\n type FacewearStatusResponse,\n isProfileConnected,\n} from \"../components/facewear-profiles.ts\";\nimport type { FacewearDeviceType } from \"../devices/registry.ts\";\n\nconst ACTIVE_DEVICE_LIMIT = 4;\n\nfunction ConnectionIcon({ connectionType }: { connectionType: string }) {\n if (connectionType.toLowerCase().includes(\"bluetooth\")) {\n return <Bluetooth className=\"h-4 w-4\" />;\n }\n if (connectionType.toLowerCase().includes(\"wifi\")) {\n return <Wifi className=\"h-4 w-4\" />;\n }\n return <Zap className=\"h-4 w-4\" />;\n}\n\nfunction DeviceCard({\n profile,\n connectedDevices,\n onConnect,\n}: {\n profile: FacewearDeviceProfileRow;\n connectedDevices: ConnectedDevice[];\n onConnect: (type: FacewearDeviceType) => void;\n}) {\n const isConnected = isProfileConnected(profile, connectedDevices);\n const Icon = profile.connectionType.toLowerCase().includes(\"bluetooth\")\n ? Bluetooth\n : Glasses;\n const actionLabel = isConnected\n ? `Manage ${profile.name}`\n : `Connect ${profile.name}`;\n const { ref: connectRef, agentProps: connectAgentProps } =\n useAgentElement<HTMLButtonElement>({\n id: `device-${profile.type}`,\n role: \"button\",\n label: actionLabel,\n group: \"devices\",\n status: isConnected ? \"active\" : \"inactive\",\n description: `${isConnected ? \"Manage\" : \"Connect\"} the ${profile.name} device`,\n });\n\n return (\n <div className=\"py-3 transition-colors\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3 min-w-0\">\n <div className=\"flex h-10 w-10 flex-shrink-0 items-center justify-center\">\n <Icon\n className={`h-5 w-5 ${isConnected ? \"text-green-500\" : \"text-muted\"}`}\n />\n </div>\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-semibold text-txt\">\n {profile.name}\n </p>\n <p className=\"text-xs text-muted\">{profile.manufacturer}</p>\n </div>\n </div>\n <span\n className={`flex-shrink-0 inline-flex items-center gap-1 px-1.5 py-0.5 text-xs font-medium ${\n isConnected ? \"text-green-600 dark:text-green-400\" : \"text-muted\"\n }`}\n >\n {isConnected ? \"On\" : \"Off\"}\n </span>\n </div>\n <div className=\"mt-2 flex items-center justify-between gap-2\">\n <span className=\"inline-flex items-center gap-1.5 text-xs text-muted\">\n <ConnectionIcon connectionType={profile.connectionType} />\n {profile.connectionType}\n </span>\n <button\n ref={connectRef}\n type=\"button\"\n onClick={() => onConnect(profile.type)}\n aria-label={actionLabel}\n className=\"inline-flex h-8 items-center gap-1.5 px-3 text-xs font-medium hover:bg-muted/20 transition-colors\"\n {...connectAgentProps}\n >\n {isConnected ? \"Manage\" : \"Connect\"}\n </button>\n </div>\n </div>\n );\n}\n\nexport function FacewearAppView() {\n const [status, setStatus] = useState<FacewearStatusResponse>({\n connected: false,\n devices: [],\n });\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 setStatus(data);\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 useEffect(() => {\n void fetchStatus();\n const interval = setInterval(() => void fetchStatus(), 5000);\n return () => clearInterval(interval);\n }, [fetchStatus]);\n\n function handleConnect(deviceType: FacewearDeviceType): void {\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\n const activeCount = status.devices.length;\n\n const { ref: xrConnectRef, agentProps: xrConnectAgentProps } =\n useAgentElement<HTMLAnchorElement>({\n id: \"link-xr-connect\",\n role: \"link\",\n label: \"Connect\",\n group: \"quick-actions\",\n description: \"Open the XR device connect page in a new tab\",\n });\n const { ref: xrStatusRef, agentProps: xrStatusAgentProps } =\n useAgentElement<HTMLAnchorElement>({\n id: \"link-xr-status\",\n role: \"link\",\n label: \"Status\",\n group: \"quick-actions\",\n description: \"Open the XR status API in a new tab\",\n });\n const { ref: refreshRef, agentProps: refreshAgentProps } =\n useAgentElement<HTMLButtonElement>({\n id: \"action-refresh\",\n role: \"button\",\n label: \"Refresh\",\n group: \"quick-actions\",\n description: \"Refresh the connected device status\",\n });\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col overflow-y-auto bg-bg text-txt\">\n <div className=\"px-4 py-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div>\n <div className=\"flex items-center gap-2\">\n <Glasses className=\"h-4 w-4 text-accent\" />\n <h1 className=\"text-sm font-semibold\">Facewear</h1>\n </div>\n </div>\n <span\n className={`inline-flex h-7 items-center gap-1.5 px-1.5 text-xs font-medium ${\n activeCount > 0\n ? \"text-green-700 dark:text-green-300\"\n : \"text-muted\"\n }`}\n >\n <Zap className=\"h-3.5 w-3.5\" />\n {activeCount > 0 ? `${activeCount} on` : \"0 on\"}\n </span>\n </div>\n </div>\n\n <div className=\"mx-auto w-full max-w-3xl p-4\">\n {loading && (\n <div className=\"flex items-center justify-center py-8\">\n <div className=\"h-6 w-6 animate-spin rounded-full border-2 border-border border-t-accent\" />\n </div>\n )}\n\n {error && (\n <div className=\"mb-4 px-1 py-2 text-xs text-destructive\">{error}</div>\n )}\n\n {!loading && (\n <>\n {activeCount > 0 && (\n <div className=\"mb-3\">\n <div className=\"flex flex-wrap gap-2\">\n {status.devices\n .slice(0, ACTIVE_DEVICE_LIMIT)\n .map((device) => (\n <span\n key={device.id}\n className=\"inline-flex items-center gap-1 px-1.5 py-0.5 text-xs text-green-700 dark:text-green-300\"\n >\n {device.deviceType ?? device.kind}\n </span>\n ))}\n {status.devices.length > ACTIVE_DEVICE_LIMIT ? (\n <span className=\"inline-flex items-center px-1.5 py-0.5 text-xs text-muted\">\n +{status.devices.length - ACTIVE_DEVICE_LIMIT}\n </span>\n ) : null}\n </div>\n </div>\n )}\n\n <div className=\"grid gap-3\">\n {FACEWEAR_DEVICE_PROFILES.map((profile) => (\n <DeviceCard\n key={profile.type}\n profile={profile}\n connectedDevices={status.devices}\n onConnect={handleConnect}\n />\n ))}\n </div>\n\n <div className=\"mt-4\">\n <div className=\"flex flex-wrap gap-2\">\n <a\n ref={xrConnectRef}\n href=\"/api/xr/connect\"\n target=\"_blank\"\n rel=\"noreferrer\"\n aria-label=\"XR connect\"\n className=\"inline-flex h-8 items-center gap-1.5 px-3 text-xs font-medium hover:bg-muted/20 transition-colors\"\n {...xrConnectAgentProps}\n >\n <Zap className=\"h-3.5 w-3.5\" />\n Connect\n </a>\n <a\n ref={xrStatusRef}\n href=\"/api/xr/status\"\n target=\"_blank\"\n rel=\"noreferrer\"\n aria-label=\"XR status\"\n className=\"inline-flex h-8 items-center gap-1.5 px-3 text-xs font-medium hover:bg-muted/20 transition-colors\"\n {...xrStatusAgentProps}\n >\n Status\n </a>\n <button\n ref={refreshRef}\n type=\"button\"\n onClick={() => void fetchStatus()}\n aria-label=\"Refresh\"\n className=\"inline-flex h-8 items-center gap-1.5 px-3 text-xs font-medium hover:bg-muted/20 transition-colors\"\n {...refreshAgentProps}\n >\n Refresh\n </button>\n </div>\n </div>\n </>\n )}\n </div>\n </div>\n );\n}\n\nexport function FacewearTuiView() {\n return (\n <TerminalPluginView\n id=\"facewear\"\n label=\"Facewear TUI\"\n description=\"Status\"\n commands={[]}\n endpoints={[\n \"/api/facewear/status\",\n \"/api/facewear/devices\",\n \"/api/facewear/views\",\n ]}\n />\n );\n}\n\nexport function SmartglassesTuiView() {\n return (\n <TerminalPluginView\n id=\"smartglasses\"\n label=\"Smartglasses TUI\"\n description=\"Status\"\n commands={[]}\n endpoints={[\"/api/facewear/status\", \"/api/facewear/devices\"]}\n />\n );\n}\n","import {\n encodeMicCommand,\n G1Command,\n type G1Event,\n G1InteractionCode,\n G1SubCommand,\n type GlassSide,\n parseG1Notification,\n type SmartglassesAudioEncoding,\n} from \"../protocol/smartglasses.ts\";\nimport type {\n SmartglassesConnectedLenses,\n SmartglassesTransport,\n SmartglassesWifiResult,\n} from \"./types.ts\";\n\ntype EvenBridge = {\n requestWifiScan?: () => Promise<unknown> | unknown;\n requestWifiStatus?: () => Promise<unknown> | unknown;\n requestWifiSetup?: (reason?: string) => Promise<unknown> | unknown;\n setWifiCredentials?: (\n ssid: string,\n password: string,\n ) => Promise<unknown> | unknown;\n sendWifiCredentials?: (\n ssid: string,\n password: string,\n ) => Promise<unknown> | unknown;\n rawBridge?: {\n audioControl?: (enabled: boolean) => Promise<unknown> | unknown;\n callEvenApp?: (\n name: string,\n payload?: Record<string, unknown>,\n ) => Promise<unknown> | unknown;\n };\n audioControl?: (enabled: boolean) => Promise<unknown> | unknown;\n createStartUpPageContainer?: (\n container: Record<string, unknown>,\n ) => Promise<unknown> | unknown;\n clearDisplay?: () => Promise<unknown> | unknown;\n displayText?: (params: Record<string, unknown>) => Promise<unknown> | unknown;\n onEvent?: (callback: (event: unknown) => void) => BridgeSubscription;\n onEvenHubEvent?: (callback: (event: unknown) => void) => BridgeSubscription;\n rebuildPageContainer?: (\n container: Record<string, unknown>,\n ) => Promise<unknown> | unknown;\n sendStartUpPage?: (container: unknown) => Promise<unknown> | unknown;\n setMicState?: (\n sendPcmData: boolean,\n sendTranscript: boolean,\n bypassVad: boolean,\n ) => Promise<unknown> | unknown;\n write?: (side: GlassSide, data: Uint8Array) => Promise<unknown> | unknown;\n send?: (side: GlassSide, data: Uint8Array) => Promise<unknown> | unknown;\n};\n\ntype BridgeSubscription =\n | undefined\n | (() => void)\n | { unsubscribe?: () => void; off?: () => void; remove?: () => void };\n\nfunction normalizeBytes(value: unknown): Uint8Array | null {\n if (value instanceof Uint8Array) return value;\n if (value instanceof ArrayBuffer) return new Uint8Array(value);\n if (ArrayBuffer.isView(value)) {\n return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n }\n if (Array.isArray(value) && value.every((v) => Number.isInteger(v)))\n return Uint8Array.from(value);\n if (\n typeof value === \"string\" &&\n /^[0-9a-f]+$/i.test(value) &&\n value.length % 2 === 0\n ) {\n return Uint8Array.from(\n value.match(/../g)?.map((b) => Number.parseInt(b, 16)) ?? [],\n );\n }\n return null;\n}\n\nexport class EvenBridgeTransport implements SmartglassesTransport {\n readonly name = \"even-bridge\";\n private connected = false;\n private eventCallbacks = new Set<(event: G1Event) => void>();\n private audioCallbacks = new Set<\n (\n audioData: Uint8Array,\n sampleRate: number,\n side: GlassSide,\n encoding?: SmartglassesAudioEncoding,\n sequence?: number,\n ) => void\n >();\n private transcriptCallbacks = new Set<\n (text: string, isFinal: boolean, metadata?: Record<string, unknown>) => void\n >();\n private wifiCallbacks = new Set<(status: SmartglassesWifiResult) => void>();\n private bridgeDisposer: (() => void) | null = null;\n private readonly displayChunks = new Map<string, Uint8Array[]>();\n private evenHubStartupCreated = false;\n\n constructor(private readonly bridge: EvenBridge) {}\n\n async connect(): Promise<void> {\n this.connected = true;\n const register = this.bridge.onEvenHubEvent ?? this.bridge.onEvent;\n if (register) {\n const subscription = register.call(this.bridge, (event: unknown) =>\n this.handleBridgeEvent(event),\n );\n this.bridgeDisposer = normalizeBridgeSubscription(subscription);\n }\n }\n\n async disconnect(): Promise<void> {\n await this.openMicrophone(false);\n this.bridgeDisposer?.();\n this.bridgeDisposer = null;\n this.connected = false;\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n getConnectedLenses(): SmartglassesConnectedLenses {\n if (!this.connected) return {};\n return {\n left: {\n connected: true,\n name: \"Native bridge left lens\",\n },\n right: {\n connected: true,\n name: \"Native bridge right lens\",\n },\n };\n }\n\n async write(side: GlassSide, data: Uint8Array): Promise<void> {\n if (this.supportsEvenHubDisplay() && data[0] === G1Command.SendResult) {\n if (side === \"left\") await this.writeEvenHubDisplay(data);\n return;\n }\n if (this.supportsMentraDisplay() && data[0] === G1Command.SendResult) {\n if (side === \"left\") await this.writeMentraDisplay(data);\n return;\n }\n if (\n this.bridge.clearDisplay &&\n data[0] === G1Command.StartAi &&\n data[1] === G1SubCommand.Stop\n ) {\n await this.bridge.clearDisplay();\n return;\n }\n if (this.bridge.write) {\n await this.bridge.write(side, data);\n return;\n }\n if (this.bridge.send) {\n await this.bridge.send(side, data);\n return;\n }\n await this.bridge.rawBridge?.callEvenApp?.(\"sendData\", {\n side,\n data: Array.from(data),\n });\n }\n\n async writeBoth(data: Uint8Array): Promise<void> {\n await this.write(\"left\", data);\n await this.write(\"right\", data);\n }\n\n async openMicrophone(enabled: boolean): Promise<void> {\n if (this.bridge.setMicState) {\n await this.bridge.setMicState(enabled, enabled, enabled);\n return;\n }\n if (this.bridge.audioControl) {\n await this.bridge.audioControl(enabled);\n return;\n }\n if (this.bridge.rawBridge?.audioControl) {\n await this.bridge.rawBridge.audioControl(enabled);\n return;\n }\n if (this.bridge.rawBridge?.callEvenApp) {\n await this.bridge.rawBridge.callEvenApp(\"audioControl\", {\n isOpen: enabled,\n });\n return;\n }\n await this.write(\"right\", encodeMicCommand(enabled));\n }\n\n async scanWifi(): Promise<SmartglassesWifiResult> {\n this.assertWifiSupported();\n const raw = this.bridge.requestWifiScan\n ? await this.bridge.requestWifiScan()\n : await this.bridge.rawBridge?.callEvenApp?.(\"request_wifi_scan\");\n return normalizeWifiResult(raw, \"Wi-Fi scan requested\");\n }\n\n async getWifiStatus(): Promise<SmartglassesWifiResult> {\n this.assertWifiSupported();\n const raw = this.bridge.requestWifiStatus\n ? await this.bridge.requestWifiStatus()\n : await this.bridge.rawBridge?.callEvenApp?.(\"request_wifi_status\");\n return normalizeWifiResult(raw, \"Wi-Fi status requested\");\n }\n\n async configureWifi(\n ssid: string,\n password: string,\n ): Promise<SmartglassesWifiResult> {\n this.assertWifiSupported();\n const raw = this.bridge.setWifiCredentials\n ? await this.bridge.setWifiCredentials(ssid, password)\n : this.bridge.sendWifiCredentials\n ? await this.bridge.sendWifiCredentials(ssid, password)\n : await this.bridge.rawBridge?.callEvenApp?.(\"set_wifi_credentials\", {\n ssid,\n password,\n });\n return normalizeWifiResult(raw, `Wi-Fi credentials sent for ${ssid}`);\n }\n\n async requestWifiSetup(reason?: string): Promise<SmartglassesWifiResult> {\n this.assertWifiSupported();\n const raw = this.bridge.requestWifiSetup\n ? await this.bridge.requestWifiSetup(reason)\n : await this.bridge.rawBridge?.callEvenApp?.(\"request_wifi_setup\", {\n reason,\n });\n return normalizeWifiResult(raw, \"Wi-Fi setup requested\");\n }\n\n supportsWifi(): boolean {\n return Boolean(\n this.bridge.requestWifiScan ||\n this.bridge.requestWifiStatus ||\n this.bridge.requestWifiSetup ||\n this.bridge.setWifiCredentials ||\n this.bridge.sendWifiCredentials ||\n this.bridge.rawBridge?.callEvenApp,\n );\n }\n\n private assertWifiSupported(): void {\n if (!this.supportsWifi()) {\n throw new Error(\n \"Wi-Fi is only available when the native smartglasses bridge exposes Wi-Fi APIs\",\n );\n }\n }\n\n private supportsEvenHubDisplay(): boolean {\n return Boolean(\n this.bridge.sendStartUpPage || this.bridge.createStartUpPageContainer,\n );\n }\n\n private supportsMentraDisplay(): boolean {\n return Boolean(this.bridge.displayText);\n }\n\n onEvent(callback: (event: G1Event) => void): () => void {\n this.eventCallbacks.add(callback);\n return () => this.eventCallbacks.delete(callback);\n }\n\n onAudio(\n callback: (\n audioData: Uint8Array,\n sampleRate: number,\n side: GlassSide,\n encoding?: SmartglassesAudioEncoding,\n sequence?: number,\n ) => void,\n ): () => void {\n this.audioCallbacks.add(callback);\n return () => this.audioCallbacks.delete(callback);\n }\n\n onTranscript(\n callback: (\n text: string,\n isFinal: boolean,\n metadata?: Record<string, unknown>,\n ) => void,\n ): () => void {\n this.transcriptCallbacks.add(callback);\n return () => this.transcriptCallbacks.delete(callback);\n }\n\n onWifiStatus(callback: (status: SmartglassesWifiResult) => void): () => void {\n this.wifiCallbacks.add(callback);\n return () => this.wifiCallbacks.delete(callback);\n }\n\n private handleBridgeEvent(event: unknown): void {\n const maybe = event as Record<string, unknown>;\n const wifi = normalizeBridgeWifiEvent(maybe);\n if (wifi) {\n for (const callback of this.wifiCallbacks) callback(wifi);\n return;\n }\n const transcript = normalizeBridgeTranscriptEvent(maybe);\n if (transcript) {\n for (const callback of this.transcriptCallbacks)\n callback(transcript.text, transcript.isFinal, transcript.metadata);\n return;\n }\n const audio = maybe.audioEvent as Record<string, unknown> | undefined;\n const audioPcm = normalizeBytes(audio?.audioPcm);\n if (audioPcm) {\n for (const callback of this.audioCallbacks)\n callback(audioPcm, 16_000, \"right\", \"pcm16\");\n return;\n }\n const mentraPcm = normalizeBytes(maybe.pcm);\n if (maybe.type === \"mic_pcm\" && mentraPcm) {\n for (const callback of this.audioCallbacks)\n callback(mentraPcm, 16_000, \"right\", \"pcm16\");\n return;\n }\n const mentraLc3 = normalizeBytes(maybe.lc3);\n if (maybe.type === \"mic_lc3\" && mentraLc3) {\n for (const callback of this.audioCallbacks)\n callback(mentraLc3, 16_000, \"right\", \"lc3\");\n return;\n }\n const inputEvent = normalizeEvenHubInputEvent(maybe);\n if (inputEvent) {\n for (const callback of this.eventCallbacks) callback(inputEvent);\n return;\n }\n const side =\n maybe.side === \"left\" || maybe.side === \"right\" ? maybe.side : \"right\";\n const bytes = normalizeBytes(maybe.raw ?? maybe.data ?? maybe.bytes);\n if (!bytes) return;\n const parsed = parseG1Notification(side, bytes);\n for (const callback of this.eventCallbacks) callback(parsed);\n const audioData = parsed.audioPcm ?? parsed.audioData;\n if (audioData) {\n for (const callback of this.audioCallbacks)\n callback(\n audioData,\n 16_000,\n parsed.side,\n parsed.audioEncoding,\n parsed.sequence,\n );\n }\n }\n\n private async writeEvenHubDisplay(data: Uint8Array): Promise<void> {\n const display = this.decodeDisplayPacket(data);\n if (!display) return;\n const key = `${display.seq}:${display.status}:${display.pageNumber}:${display.maxPages}`;\n const chunks =\n this.displayChunks.get(key) ??\n Array.from<Uint8Array>({ length: display.totalPackages });\n chunks[display.currentPackage] = display.chunk;\n this.displayChunks.set(key, chunks);\n if (chunks.some((chunk) => !chunk)) return;\n\n this.displayChunks.delete(key);\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const textBytes = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n textBytes.set(chunk, offset);\n offset += chunk.length;\n }\n await this.sendEvenHubTextPage(textBytes);\n }\n\n private async writeMentraDisplay(data: Uint8Array): Promise<void> {\n const display = this.decodeDisplayPacket(data);\n if (!display) return;\n const key = `${display.seq}:${display.status}:${display.pageNumber}:${display.maxPages}`;\n const chunks =\n this.displayChunks.get(key) ??\n Array.from<Uint8Array>({ length: display.totalPackages });\n chunks[display.currentPackage] = display.chunk;\n this.displayChunks.set(key, chunks);\n if (chunks.some((chunk) => !chunk)) return;\n\n this.displayChunks.delete(key);\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const textBytes = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n textBytes.set(chunk, offset);\n offset += chunk.length;\n }\n await this.bridge.displayText?.({\n text: new TextDecoder().decode(textBytes),\n x: 0,\n y: 0,\n size: 24,\n });\n }\n\n private async sendEvenHubTextPage(textBytes: Uint8Array): Promise<void> {\n const page = createEvenHubTextPage(textBytes);\n if (this.bridge.sendStartUpPage) {\n await this.bridge.sendStartUpPage(page);\n return;\n }\n if (!this.bridge.createStartUpPageContainer) return;\n if (!this.evenHubStartupCreated) {\n assertEvenHubResult(\n await this.bridge.createStartUpPageContainer(page),\n \"createStartUpPageContainer\",\n );\n this.evenHubStartupCreated = true;\n return;\n }\n const rebuild =\n this.bridge.rebuildPageContainer ??\n this.bridge.createStartUpPageContainer;\n assertEvenHubResult(\n await rebuild.call(this.bridge, page),\n \"rebuildPageContainer\",\n );\n }\n\n private decodeDisplayPacket(data: Uint8Array): {\n seq: number;\n totalPackages: number;\n currentPackage: number;\n status: number;\n pageNumber: number;\n maxPages: number;\n chunk: Uint8Array;\n } | null {\n if (data.length < 9 || data[0] !== G1Command.SendResult) return null;\n const totalPackages = data[2] || 1;\n const currentPackage = data[3] || 0;\n if (currentPackage >= totalPackages) return null;\n return {\n seq: data[1] ?? 0,\n totalPackages,\n currentPackage,\n status: data[4] ?? 0,\n pageNumber: data[7] ?? 1,\n maxPages: data[8] ?? 1,\n chunk: data.slice(9),\n };\n }\n}\n\nfunction normalizeEvenHubInputEvent(\n event: Record<string, unknown>,\n): G1Event | null {\n const rawEventType = getEvenHubRawEventType(event);\n const label = normalizeEvenHubEventLabel(rawEventType, event);\n if (!label) return null;\n const code =\n label === \"single_tap\"\n ? G1InteractionCode.SingleTap\n : label === \"double_tap\"\n ? G1InteractionCode.DoubleTap\n : label === \"long_press\"\n ? G1InteractionCode.LongPress\n : G1SubCommand.PageControl;\n return {\n side: \"right\",\n raw: Uint8Array.from([G1Command.StartAi, code]),\n type: \"state\",\n code,\n label,\n };\n}\n\nfunction normalizeBridgeTranscriptEvent(event: Record<string, unknown>): {\n text: string;\n isFinal: boolean;\n metadata: Record<string, unknown>;\n} | null {\n const type = String(event.type ?? event.streamType ?? \"\");\n if (\n type !== \"local_transcription\" &&\n !type.startsWith(\"transcription\") &&\n !(\"transcript\" in event)\n )\n return null;\n const text =\n typeof event.text === \"string\"\n ? event.text\n : typeof event.transcript === \"string\"\n ? event.transcript\n : \"\";\n if (!text.trim()) return null;\n const isFinal =\n typeof event.isFinal === \"boolean\"\n ? event.isFinal\n : typeof event.final === \"boolean\"\n ? event.final\n : event.type === \"local_transcription\";\n return { text, isFinal, metadata: { ...event } };\n}\n\nfunction normalizeBridgeWifiEvent(\n event: Record<string, unknown>,\n): SmartglassesWifiResult | null {\n const type = String(event.type ?? event.eventType ?? event.event_type ?? \"\");\n const values =\n event.values && typeof event.values === \"object\"\n ? (event.values as Record<string, unknown>)\n : event;\n const hasWifiFields =\n \"wifiConnected\" in values ||\n \"wifiSsid\" in values ||\n \"wifiLocalIp\" in values ||\n \"connected\" in values ||\n \"ssid\" in values ||\n \"networks\" in values ||\n \"results\" in values;\n if (\n type !== \"wifi_status_change\" &&\n type !== \"wifi_status\" &&\n type !== \"wifi_scan_result\" &&\n !hasWifiFields\n ) {\n return null;\n }\n const connected =\n booleanValue(values.wifiConnected) ?? booleanValue(values.connected);\n const ssid = stringValue(values.wifiSsid) ?? stringValue(values.ssid);\n const localIp =\n stringValue(values.wifiLocalIp) ?? stringValue(values.localIp);\n const networks = parseWifiNetworks(values);\n const status =\n parseWifiStatus(values) ??\n (type === \"wifi_scan_result\"\n ? networks.length > 0\n ? `found ${networks.length} Wi-Fi network(s)`\n : \"Wi-Fi scan result\"\n : connected\n ? `connected to ${ssid ?? \"Wi-Fi\"}`\n : connected === false\n ? \"disconnected\"\n : \"Wi-Fi status updated\");\n return {\n available: true,\n status,\n networks,\n raw: { ...event, normalized: { connected, ssid, localIp } },\n };\n}\n\nfunction getEvenHubRawEventType(event: Record<string, unknown>): unknown {\n const jsonData = normalizeJsonData(event.jsonData);\n return (\n getNestedEventType(event.listEvent) ??\n getNestedEventType(event.textEvent) ??\n getNestedEventType(event.sysEvent) ??\n event.eventType ??\n jsonData?.eventType ??\n jsonData?.event_type ??\n jsonData?.Event_Type ??\n jsonData?.type ??\n event.type ??\n event.action\n );\n}\n\nfunction normalizeJsonData(value: unknown): Record<string, unknown> | null {\n if (value && typeof value === \"object\")\n return value as Record<string, unknown>;\n if (typeof value !== \"string\") return null;\n try {\n const parsed = JSON.parse(value);\n return parsed && typeof parsed === \"object\"\n ? (parsed as Record<string, unknown>)\n : null;\n } catch {\n return null;\n }\n}\n\nfunction getNestedEventType(value: unknown): unknown {\n if (!value || typeof value !== \"object\") return undefined;\n const event = value as Record<string, unknown>;\n return event.eventType ?? event.event_type ?? event.Event_Type ?? event.type;\n}\n\nfunction normalizeEvenHubEventLabel(\n rawEventType: unknown,\n event: Record<string, unknown>,\n):\n | \"single_tap\"\n | \"double_tap\"\n | \"long_press\"\n | \"scroll_up\"\n | \"scroll_down\"\n | null {\n if (\n rawEventType === undefined &&\n (event.listEvent || event.textEvent || event.sysEvent)\n )\n return \"single_tap\";\n if (typeof rawEventType === \"number\") {\n if (rawEventType === 0) return \"single_tap\";\n if (rawEventType === 1) return \"scroll_up\";\n if (rawEventType === 2) return \"scroll_down\";\n if (rawEventType === 3) return \"double_tap\";\n return null;\n }\n if (typeof rawEventType === \"string\") {\n const value = rawEventType.toUpperCase();\n if (value.includes(\"LONG\")) return \"long_press\";\n if (value.includes(\"DOUBLE\")) return \"double_tap\";\n if (value.includes(\"SCROLL_TOP\") || value.includes(\"SCROLL_UP\"))\n return \"scroll_up\";\n if (value.includes(\"SCROLL_BOTTOM\") || value.includes(\"SCROLL_DOWN\"))\n return \"scroll_down\";\n if (value === \"UP\") return \"scroll_up\";\n if (value === \"DOWN\") return \"scroll_down\";\n if (value.includes(\"CLICK\") || value.includes(\"TAP\")) return \"single_tap\";\n if (value === \"BUTTON_PRESS\") return normalizeButtonPressEvent(event);\n }\n return normalizeButtonPressEvent(event);\n}\n\nfunction normalizeButtonPressEvent(\n event: Record<string, unknown>,\n):\n | \"single_tap\"\n | \"double_tap\"\n | \"long_press\"\n | \"scroll_up\"\n | \"scroll_down\"\n | null {\n const buttonValue = String(\n event.pressType ?? event.button ?? event.buttonId ?? event.value ?? \"\",\n ).toUpperCase();\n if (buttonValue.includes(\"LONG\")) return \"long_press\";\n if (buttonValue.includes(\"DOUBLE\")) return \"double_tap\";\n if (buttonValue.includes(\"SCROLL_TOP\") || buttonValue.includes(\"UP\"))\n return \"scroll_up\";\n if (buttonValue.includes(\"SCROLL_BOTTOM\") || buttonValue.includes(\"DOWN\"))\n return \"scroll_down\";\n if (buttonValue.includes(\"SINGLE\") || buttonValue.includes(\"TAP\"))\n return \"single_tap\";\n return null;\n}\n\nfunction normalizeBridgeSubscription(\n subscription: BridgeSubscription,\n): (() => void) | null {\n if (typeof subscription === \"function\") return subscription;\n if (!subscription || typeof subscription !== \"object\") return null;\n return (\n subscription.unsubscribe?.bind(subscription) ??\n subscription.off?.bind(subscription) ??\n subscription.remove?.bind(subscription) ??\n null\n );\n}\n\nfunction normalizeWifiResult(\n raw: unknown,\n fallbackStatus: string,\n): SmartglassesWifiResult {\n return {\n available: true,\n status: parseWifiStatus(raw) ?? fallbackStatus,\n networks: parseWifiNetworks(raw),\n raw,\n };\n}\n\nfunction parseWifiStatus(raw: unknown): string | null {\n if (typeof raw === \"string\" && raw.trim()) return raw.trim();\n if (!raw || typeof raw !== \"object\") return null;\n const record = raw as Record<string, unknown>;\n const value =\n record.status ??\n record.state ??\n record.message ??\n record.result ??\n record.connectedSsid ??\n record.ssid;\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\n}\n\nfunction booleanValue(value: unknown): boolean | null {\n if (typeof value === \"boolean\") return value;\n if (typeof value === \"number\") return value !== 0;\n if (typeof value === \"string\") {\n if (/^(true|1|yes|connected)$/i.test(value)) return true;\n if (/^(false|0|no|disconnected)$/i.test(value)) return false;\n }\n return null;\n}\n\nfunction stringValue(value: unknown): string | null {\n return typeof value === \"string\" && value.trim() ? value.trim() : null;\n}\n\nfunction parseWifiNetworks(raw: unknown): string[] {\n if (!raw || typeof raw !== \"object\") return [];\n const record = raw as Record<string, unknown>;\n const value = record.networks ?? record.networks_neo ?? record.results;\n if (!Array.isArray(value)) return [];\n return value\n .map((network) => {\n if (typeof network === \"string\") return network;\n if (!network || typeof network !== \"object\") return \"\";\n const item = network as Record<string, unknown>;\n return String(item.ssid ?? item.SSID ?? item.name ?? \"\");\n })\n .filter((ssid) => ssid.trim().length > 0);\n}\n\nfunction createEvenHubTextPage(textBytes: Uint8Array): Record<string, unknown> {\n const text = new TextDecoder().decode(textBytes);\n return {\n containerTotalNum: 2,\n text,\n textObject: [\n {\n containerID: 1,\n containerName: \"eliza-smartglasses-text\",\n content: text,\n xPosition: 12,\n yPosition: 12,\n width: 552,\n height: 200,\n isEventCapture: 0,\n },\n ],\n listObject: [\n {\n containerID: 2,\n containerName: \"eliza-smartglasses-input\",\n itemContainer: {\n itemCount: 1,\n itemWidth: 552,\n isItemSelectBorderEn: 0,\n itemName: [\"Click mic on | Double click mic off\"],\n },\n isEventCapture: 1,\n xPosition: 12,\n yPosition: 236,\n width: 552,\n height: 36,\n },\n ],\n };\n}\n\nfunction assertEvenHubResult(result: unknown, operation: string): void {\n if (typeof result === \"number\" && result !== 0) {\n throw new Error(`${operation} failed with result ${result}`);\n }\n if (typeof result === \"boolean\" && !result) {\n throw new Error(`${operation} failed`);\n }\n}\n\nexport function getGlobalEvenBridgeTransport(): SmartglassesTransport | null {\n const globalBridge = (globalThis as Record<string, unknown>).__evenBridge as\n | EvenBridge\n | undefined;\n return globalBridge ? new EvenBridgeTransport(globalBridge) : null;\n}\n","import {\n EVEN_G1_UART,\n encodeMicCommand,\n type G1Event,\n type GlassSide,\n parseG1Notification,\n type SmartglassesAudioEncoding,\n} from \"../protocol/smartglasses.ts\";\nimport type {\n SmartglassesConnectedLenses,\n SmartglassesTransport,\n} from \"./types.ts\";\n\ntype BluetoothRemoteGATTCharacteristicLike = {\n value?: DataView;\n writeValueWithoutResponse?: (data: ArrayBuffer) => Promise<void>;\n writeValueWithResponse?: (data: ArrayBuffer) => Promise<void>;\n writeValue?: (data: ArrayBuffer) => Promise<void>;\n startNotifications: () => Promise<BluetoothRemoteGATTCharacteristicLike>;\n stopNotifications?: () => Promise<void>;\n addEventListener: (type: string, listener: (event: Event) => void) => void;\n removeEventListener?: (\n type: string,\n listener: (event: Event) => void,\n ) => void;\n};\n\ntype BluetoothRemoteGATTServerLike = {\n connected?: boolean;\n getPrimaryService: (service: string) => Promise<{\n getCharacteristic: (\n characteristic: string,\n ) => Promise<BluetoothRemoteGATTCharacteristicLike>;\n }>;\n disconnect?: () => void;\n};\n\ntype BluetoothDeviceLike = {\n name?: string;\n id?: string;\n gatt?: {\n connect: () => Promise<BluetoothRemoteGATTServerLike>;\n };\n};\n\ntype NavigatorBluetoothLike = {\n requestDevice: (options: {\n filters?: Array<{ namePrefix?: string; services?: string[] }>;\n optionalServices?: string[];\n }) => Promise<BluetoothDeviceLike>;\n};\n\ntype SideConnection = {\n device: BluetoothDeviceLike;\n server: BluetoothRemoteGATTServerLike;\n tx: BluetoothRemoteGATTCharacteristicLike;\n rx: BluetoothRemoteGATTCharacteristicLike;\n listener: (event: Event) => void;\n};\n\nexport class WebBluetoothG1Transport implements SmartglassesTransport {\n readonly name = \"web-bluetooth-g1\";\n private readonly sides = new Map<GlassSide, SideConnection>();\n private eventCallbacks = new Set<(event: G1Event) => void>();\n private audioCallbacks = new Set<\n (\n audioData: Uint8Array,\n sampleRate: number,\n side: GlassSide,\n encoding?: SmartglassesAudioEncoding,\n sequence?: number,\n ) => void\n >();\n\n constructor(\n private readonly bluetooth: NavigatorBluetoothLike = getNavigatorBluetooth(),\n ) {}\n\n async connect(): Promise<void> {\n try {\n await this.connectLens(\"left\");\n await this.connectLens(\"right\");\n } catch (error) {\n await this.disconnect();\n throw error;\n }\n }\n\n async disconnect(): Promise<void> {\n for (const [side, connection] of this.sides) {\n await connection.rx.stopNotifications?.();\n connection.rx.removeEventListener?.(\n \"characteristicvaluechanged\",\n connection.listener,\n );\n connection.server.disconnect?.();\n this.sides.delete(side);\n }\n }\n\n isConnected(): boolean {\n return (\n this.sides.size === 2 &&\n [...this.sides.values()].every(\n (connection) => connection.server.connected !== false,\n )\n );\n }\n\n getConnectedLenses(): SmartglassesConnectedLenses {\n const lenses: SmartglassesConnectedLenses = {};\n for (const [side, connection] of this.sides) {\n lenses[side] = {\n connected: connection.server.connected !== false,\n name: connection.device.name,\n address: connection.device.id,\n };\n }\n return lenses;\n }\n\n async write(side: GlassSide, data: Uint8Array): Promise<void> {\n const connection = this.sides.get(side);\n if (!connection) throw new Error(`G1 ${side} lens is not connected`);\n const buffer = toArrayBuffer(data);\n if (connection.tx.writeValueWithoutResponse) {\n await connection.tx.writeValueWithoutResponse(buffer);\n return;\n }\n if (connection.tx.writeValueWithResponse) {\n await connection.tx.writeValueWithResponse(buffer);\n return;\n }\n await connection.tx.writeValue?.(buffer);\n }\n\n async writeBoth(data: Uint8Array): Promise<void> {\n await this.write(\"left\", data);\n await this.write(\"right\", data);\n }\n\n async openMicrophone(enabled: boolean): Promise<void> {\n await this.write(\"right\", encodeMicCommand(enabled));\n }\n\n onEvent(callback: (event: G1Event) => void): () => void {\n this.eventCallbacks.add(callback);\n return () => this.eventCallbacks.delete(callback);\n }\n\n onAudio(\n callback: (\n audioData: Uint8Array,\n sampleRate: number,\n side: GlassSide,\n encoding?: SmartglassesAudioEncoding,\n sequence?: number,\n ) => void,\n ): () => void {\n this.audioCallbacks.add(callback);\n return () => this.audioCallbacks.delete(callback);\n }\n\n async connectLens(side: GlassSide): Promise<void> {\n if (this.sides.has(side)) return;\n const nameMarker = side === \"left\" ? \"_L_\" : \"_R_\";\n const device = await this.bluetooth.requestDevice({\n filters: [\n { namePrefix: \"Even\" },\n { namePrefix: \"G1\" },\n { namePrefix: \"ER\" },\n ],\n optionalServices: [EVEN_G1_UART.service],\n });\n if (device.name && !device.name.includes(nameMarker)) {\n throw new Error(\n `Selected ${device.name} for ${side}, expected a lens name containing ${nameMarker}`,\n );\n }\n const duplicateSide = this.findConnectedDeviceSide(device);\n if (duplicateSide) {\n throw new Error(\n `Selected the ${duplicateSide} lens again while connecting the ${side} lens`,\n );\n }\n if (!device.gatt)\n throw new Error(`Selected G1 ${side} device does not expose GATT`);\n const server = await device.gatt.connect();\n const service = await server.getPrimaryService(EVEN_G1_UART.service);\n const tx = await service.getCharacteristic(EVEN_G1_UART.tx);\n const rx = await service.getCharacteristic(EVEN_G1_UART.rx);\n const listener = (event: Event) => {\n const value = (\n event.target as BluetoothRemoteGATTCharacteristicLike | null\n )?.value;\n if (!value) return;\n const bytes = new Uint8Array(\n value.buffer.slice(\n value.byteOffset,\n value.byteOffset + value.byteLength,\n ),\n );\n this.emitParsed(parseG1Notification(side, bytes));\n };\n rx.addEventListener(\"characteristicvaluechanged\", listener);\n await rx.startNotifications();\n this.sides.set(side, { device, server, tx, rx, listener });\n }\n\n private findConnectedDeviceSide(\n device: BluetoothDeviceLike,\n ): GlassSide | null {\n for (const [side, connection] of this.sides) {\n if (connection.device === device) return side;\n if (device.id && connection.device.id === device.id) return side;\n }\n return null;\n }\n\n private emitParsed(event: G1Event): void {\n for (const callback of this.eventCallbacks) callback(event);\n const audioData = event.audioPcm ?? event.audioData;\n if (audioData) {\n for (const callback of this.audioCallbacks)\n callback(\n audioData,\n 16_000,\n event.side,\n event.audioEncoding,\n event.sequence,\n );\n }\n }\n}\n\nfunction toArrayBuffer(data: Uint8Array): ArrayBuffer {\n const buffer = new ArrayBuffer(data.byteLength);\n new Uint8Array(buffer).set(data);\n return buffer;\n}\n\nexport function getWebBluetoothG1Transport(): SmartglassesTransport | null {\n const nav = (\n globalThis as { navigator?: { bluetooth?: NavigatorBluetoothLike } }\n ).navigator;\n return nav?.bluetooth ? new WebBluetoothG1Transport(nav.bluetooth) : null;\n}\n\nfunction getNavigatorBluetooth(): NavigatorBluetoothLike {\n const nav = (\n globalThis as { navigator?: { bluetooth?: NavigatorBluetoothLike } }\n ).navigator;\n if (!nav?.bluetooth)\n throw new Error(\"Web Bluetooth is not available in this runtime\");\n return nav.bluetooth;\n}\n","import { useAgentElement } from \"@elizaos/ui/agent-surface\";\nimport {\n BatteryCharging,\n Bluetooth,\n CheckCircle2,\n Circle,\n Clipboard,\n Download,\n Glasses,\n Mic,\n RefreshCw,\n Settings2,\n Wifi,\n XCircle,\n} from \"lucide-react\";\nimport { type ReactNode, useMemo, useRef, useState } from \"react\";\nimport {\n encodeBatteryStatusRequest,\n encodeBrightness,\n encodeClearScreen,\n encodeConnectionReady,\n encodeGetSerial,\n encodeSilentMode,\n type G1Event,\n type GlassSide,\n} from \"../protocol/smartglasses.ts\";\nimport { EvenBridgeTransport } from \"../transport/even-bridge.ts\";\nimport type { SmartglassesTransport } from \"../transport/types.ts\";\nimport {\n getWebBluetoothG1Transport,\n WebBluetoothG1Transport,\n} from \"../transport/web-bluetooth.ts\";\nimport {\n buildViewDisplayPackets,\n callWifiBridge,\n formatWifiStatus,\n type HardwareReport,\n headsetValidationBlocker,\n isCradleOrChargingState,\n isMicDisableTap,\n isMicEnableTap,\n type LensState,\n missingViewEvidence,\n parseWifiNetworks,\n type ReportAudio,\n type ReportEvent,\n type ReportWrite,\n type SmartglassesBridge,\n viewCommandName,\n viewNextAction,\n viewPhysicalBlocker,\n viewScanDiagnosis,\n viewSetupHint,\n} from \"./SmartglassesView.helpers.ts\";\n\ntype PlatformKey = \"desktop\" | \"ios\" | \"android\";\n\nconst VISIBLE_TEST_LIMIT = 8;\nconst VISIBLE_EVENT_LIMIT = 12;\nconst VISIBLE_WIFI_LIMIT = 5;\n\ndeclare global {\n interface Window {\n __evenBridge?: SmartglassesBridge;\n __mentraBridge?: SmartglassesBridge;\n facewearSmartglassesReport?: HardwareReport;\n }\n}\n\nconst PLATFORM_COPY: Record<\n PlatformKey,\n { label: string; primary: string; secondary: string }\n> = {\n desktop: {\n label: \"Desktop\",\n primary: \"Chrome/Edge Web Bluetooth\",\n secondary: \"Pair both lenses.\",\n },\n ios: {\n label: \"iOS\",\n primary: \"Native bridge required\",\n secondary: \"Use the host bridge.\",\n },\n android: {\n label: \"Android\",\n primary: \"Native bridge preferred\",\n secondary: \"Pair and configure in the host.\",\n },\n};\n\nconst DISPLAY_PRESETS = [\n {\n id: \"status\",\n label: \"Status\",\n text: \"elizaOS smartglasses link online.\",\n className: \"border-green-500/40 bg-green-500/10 text-green-700\",\n },\n {\n id: \"ping\",\n label: \"Ping\",\n text: \"Display ping. Confirm both lenses render this page.\",\n className: \"border-accent/45 bg-accent/10 text-accent\",\n },\n {\n id: \"nav\",\n label: \"Nav\",\n text: \"Navigation card ready. Keep eyes forward.\",\n className: \"border-amber-500/40 bg-amber-500/10 text-amber-700\",\n },\n] as const;\n\nfunction now(): string {\n return new Date().toISOString();\n}\n\nfunction timeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n message: string,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const id = window.setTimeout(() => reject(new Error(message)), timeoutMs);\n promise.then(\n (value) => {\n window.clearTimeout(id);\n resolve(value);\n },\n (err) => {\n window.clearTimeout(id);\n reject(err);\n },\n );\n });\n}\n\nfunction normalizeError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => window.setTimeout(resolve, ms));\n}\n\nfunction getBridge(): SmartglassesBridge | null {\n if (typeof window === \"undefined\") return null;\n return window.__mentraBridge ?? window.__evenBridge ?? null;\n}\n\nfunction bytesToHex(data: Uint8Array): string {\n return [...data].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nexport function SmartglassesView() {\n const [transport, setTransport] = useState<SmartglassesTransport | null>(\n null,\n );\n const [lenses, setLenses] = useState<Record<GlassSide, LensState>>({\n left: \"idle\",\n right: \"idle\",\n });\n const [events, setEvents] = useState<ReportEvent[]>([]);\n const [writes, setWrites] = useState<ReportWrite[]>([]);\n const [audioChunks, setAudioChunks] = useState<ReportAudio[]>([]);\n const [busy, setBusy] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [testText, setTestText] = useState(\"Smartglasses display test.\");\n const [micEnabled, setMicEnabled] = useState(false);\n const [wifiSsid, setWifiSsid] = useState(\"\");\n const [wifiPassword, setWifiPassword] = useState(\"\");\n const [wifiStatus, setWifiStatus] = useState(\"Not checked\");\n const [wifiNetworks, setWifiNetworks] = useState<string[]>([]);\n const [activePlatform, setActivePlatform] = useState<PlatformKey>(\"desktop\");\n const [physicalState, setPhysicalState] = useState<string | null>(null);\n const [batteryState, setBatteryState] = useState<string | null>(null);\n const [batteryLevels, setBatteryLevels] = useState<\n Partial<Record<GlassSide, number>>\n >({});\n const [deviceState, setDeviceState] = useState<string | null>(null);\n const [serialNumber, setSerialNumber] = useState<string | null>(null);\n const [tests, setTests] = useState<Record<string, boolean>>({\n headsetConnected: false,\n init: false,\n display: false,\n serial: false,\n serialObserved: false,\n settings: false,\n microphone: false,\n micEnableWrite: false,\n micDisableWrite: false,\n tapMicEnable: false,\n tapMicDisable: false,\n audio: false,\n transcript: false,\n eventStream: false,\n });\n const testsRef = useRef(tests);\n const displaySeqRef = useRef(0);\n\n const bridge = getBridge();\n const webBluetoothAvailable = Boolean(getWebBluetoothG1Transport());\n const headsetConnected =\n lenses.left === \"connected\" && lenses.right === \"connected\";\n const missingEvidence = useMemo(\n () =>\n missingViewEvidence(\n tests,\n lenses,\n physicalState,\n batteryState,\n events,\n writes,\n ),\n [batteryState, events, lenses, physicalState, tests, writes],\n );\n const physicalBlocker = useMemo(\n () =>\n viewPhysicalBlocker(\n tests,\n lenses,\n physicalState,\n batteryState,\n events,\n writes,\n ),\n [batteryState, events, lenses, physicalState, tests, writes],\n );\n const report = useMemo<HardwareReport>(\n () => ({\n ok: missingEvidence.length === 0,\n generatedAt: now(),\n transport: transport?.name ?? (bridge ? \"native-bridge\" : null),\n connected: headsetConnected,\n lenses,\n scanDiagnosis: viewScanDiagnosis(lenses),\n physicalBlocker,\n setupHint: viewSetupHint(physicalBlocker, physicalState, batteryState),\n nextAction: viewNextAction(physicalBlocker),\n serialNumber,\n tests,\n missingEvidence,\n events,\n writes,\n audio: audioChunks,\n wifi: {\n available: Boolean(bridge),\n status: wifiStatus,\n networks: wifiNetworks,\n },\n headsetState: {\n physical: physicalState,\n battery: batteryState,\n batteryLevels,\n device: deviceState,\n },\n }),\n [\n bridge,\n audioChunks,\n events,\n headsetConnected,\n lenses,\n missingEvidence,\n physicalBlocker,\n physicalState,\n serialNumber,\n tests,\n transport,\n batteryState,\n batteryLevels,\n deviceState,\n wifiNetworks,\n wifiStatus,\n writes,\n ],\n );\n\n const { ref: connectRef, agentProps: connectAgentProps } =\n useAgentElement<HTMLButtonElement>({\n id: \"setup-connect-headset\",\n role: \"button\",\n label: \"Connect\",\n group: \"setup\",\n status: headsetConnected ? \"active\" : \"inactive\",\n description:\n \"Pair both left and right smartglasses lenses as one headset\",\n });\n const { ref: runCheckRef, agentProps: runCheckAgentProps } =\n useAgentElement<HTMLButtonElement>({\n id: \"test-run-check\",\n role: \"button\",\n label: \"Run Check\",\n group: \"test\",\n description: \"Request serial/battery and send display/settings packets\",\n });\n const { ref: wifiSsidRef, agentProps: wifiSsidAgentProps } =\n useAgentElement<HTMLInputElement>({\n id: \"wifi-ssid\",\n role: \"text-input\",\n label: \"Wi-Fi SSID\",\n group: \"wifi\",\n description: \"SSID of the Wi-Fi network to configure on the glasses\",\n getValue: () => wifiSsid,\n onFill: (value: string) => setWifiSsid(value),\n });\n const { ref: wifiPasswordRef, agentProps: wifiPasswordAgentProps } =\n useAgentElement<HTMLInputElement>({\n id: \"wifi-password\",\n role: \"text-input\",\n label: \"Wi-Fi password\",\n group: \"wifi\",\n description: \"Password for the Wi-Fi network to configure on the glasses\",\n getValue: () => wifiPassword,\n onFill: (value: string) => setWifiPassword(value),\n });\n\n function appendEvent(type: string, detail: string): void {\n setEvents((current) =>\n [...current, { at: now(), type, detail }].slice(-80),\n );\n }\n\n function markTest(id: string, value = true): void {\n setTests((current) => {\n const next = { ...current, [id]: value };\n testsRef.current = next;\n return next;\n });\n }\n\n function recordWrite(side: GlassSide | \"both\", data: Uint8Array): void {\n setWrites((current) =>\n [\n ...current,\n {\n at: now(),\n side,\n command: viewCommandName(data),\n bytes: data.length,\n hex: bytesToHex(data.slice(0, 24)),\n },\n ].slice(-120),\n );\n }\n\n async function writeSide(\n nextTransport: SmartglassesTransport,\n side: GlassSide,\n data: Uint8Array,\n ): Promise<void> {\n await nextTransport.write(side, data);\n recordWrite(side, data);\n }\n\n async function writeBoth(\n nextTransport: SmartglassesTransport,\n data: Uint8Array,\n ): Promise<void> {\n await nextTransport.writeBoth(data);\n recordWrite(\"both\", data);\n }\n\n async function setTransportMic(\n nextTransport: SmartglassesTransport,\n enabled: boolean,\n ): Promise<void> {\n await nextTransport.openMicrophone(enabled);\n recordWrite(\"right\", Uint8Array.from([0x0e, enabled ? 1 : 0]));\n }\n\n async function connectHeadset(): Promise<void> {\n setBusy(\"connect\");\n setError(null);\n try {\n const nextTransport =\n transport ??\n (bridge\n ? new EvenBridgeTransport(bridge)\n : new WebBluetoothG1Transport());\n setTransport(nextTransport);\n const eventDispose = nextTransport.onEvent((event: G1Event) => {\n markTest(\"eventStream\");\n if (event.stateCategory === \"physical\") {\n setPhysicalState(event.stateName ?? event.label ?? null);\n } else if (event.stateCategory === \"battery\") {\n setBatteryState(event.stateName ?? event.label ?? null);\n } else if (event.stateCategory === \"device\") {\n setDeviceState(event.stateName ?? event.label ?? null);\n }\n if (\n event.type === \"battery-status\" &&\n typeof event.batteryPercent === \"number\"\n ) {\n setBatteryLevels((current) => ({\n ...current,\n [event.side]: event.batteryPercent,\n }));\n }\n if (event.type === \"serial\" && event.serialNumber) {\n setSerialNumber(event.serialNumber);\n markTest(\"serialObserved\");\n }\n if (isMicEnableTap(event.label)) {\n markTest(\"tapMicEnable\");\n setMicEnabled(true);\n const eventAt = now();\n setEvents((current) =>\n [\n ...current,\n { at: eventAt, type: \"tap\", detail: event.label ?? \"\" },\n ].slice(-80),\n );\n void nextTransport\n .openMicrophone(true)\n .then(() => {\n recordWrite(\"right\", Uint8Array.from([0x0e, 1]));\n markTest(\"microphone\");\n markTest(\"micEnableWrite\");\n appendEvent(\"microphone\", \"Enabled by tap\");\n })\n .catch((err) => appendEvent(\"error\", normalizeError(err)));\n }\n if (isMicDisableTap(event.label)) {\n markTest(\"tapMicDisable\");\n setMicEnabled(false);\n const eventAt = now();\n setEvents((current) =>\n [\n ...current,\n { at: eventAt, type: \"tap\", detail: event.label ?? \"\" },\n ].slice(-80),\n );\n void nextTransport\n .openMicrophone(false)\n .then(() => {\n recordWrite(\"right\", Uint8Array.from([0x0e, 0]));\n markTest(\"microphone\");\n markTest(\"micDisableWrite\");\n appendEvent(\"microphone\", \"Disabled by tap\");\n })\n .catch((err) => appendEvent(\"error\", normalizeError(err)));\n }\n appendEvent(\n \"event\",\n `${event.side} ${event.type}${event.label ? ` ${event.label}` : \"\"}`,\n );\n });\n const audioDispose = nextTransport.onAudio(\n (audio, sampleRate, side, encoding, sequence) => {\n if (audio.byteLength > 0) markTest(\"audio\");\n setAudioChunks((current) =>\n [\n ...current,\n {\n at: now(),\n side,\n sampleRate,\n encoding: encoding ?? null,\n sequence,\n bytes: audio.byteLength,\n },\n ].slice(-80),\n );\n appendEvent(\n \"audio\",\n `${side} ${audio.byteLength} bytes @ ${sampleRate}Hz${\n encoding ? ` ${encoding}` : \"\"\n }`,\n );\n },\n );\n const transcriptDispose =\n \"onTranscript\" in nextTransport && nextTransport.onTranscript\n ? nextTransport.onTranscript((text, isFinal) => {\n markTest(\"transcript\");\n appendEvent(\n \"transcript\",\n `${isFinal ? \"final\" : \"partial\"} ${text}`,\n );\n })\n : undefined;\n try {\n if (nextTransport instanceof WebBluetoothG1Transport) {\n await connectLens(nextTransport, \"left\");\n await connectLens(nextTransport, \"right\");\n } else {\n await nextTransport.connect();\n setLenses({ left: \"connected\", right: \"connected\" });\n }\n } catch (err) {\n eventDispose();\n audioDispose();\n transcriptDispose?.();\n throw err;\n }\n await writeSide(nextTransport, \"left\", encodeConnectionReady(\"left\"));\n await writeSide(nextTransport, \"right\", encodeConnectionReady(\"right\"));\n markTest(\"headsetConnected\");\n markTest(\"init\");\n appendEvent(\"connect\", \"Whole headset connected\");\n } catch (err) {\n setError(normalizeError(err));\n appendEvent(\"error\", normalizeError(err));\n } finally {\n setBusy(null);\n }\n }\n\n async function connectLens(\n nextTransport: WebBluetoothG1Transport,\n side: GlassSide,\n ): Promise<void> {\n setLenses((current) => ({ ...current, [side]: \"prompting\" }));\n appendEvent(\"pairing\", `Select the ${side} lens in the Bluetooth picker`);\n try {\n await timeout(\n nextTransport.connectLens(side),\n 60_000,\n `Timed out connecting the ${side} lens`,\n );\n setLenses((current) => ({ ...current, [side]: \"connected\" }));\n appendEvent(\"connect\", `${side} lens connected`);\n } catch (err) {\n setLenses((current) => ({ ...current, [side]: \"failed\" }));\n throw err;\n }\n }\n\n async function requireTransport(): Promise<SmartglassesTransport> {\n if (!transport || !headsetConnected) {\n throw new Error(\"Connect the whole headset before running this test\");\n }\n return transport;\n }\n\n async function sendDisplay(): Promise<void> {\n setBusy(\"display\");\n setError(null);\n try {\n const nextTransport = await requireTransport();\n const display = buildViewDisplayPackets(testText, {\n startSeq: displaySeqRef.current,\n });\n displaySeqRef.current = display.nextSeq;\n for (const packet of display.packets) {\n await writeBoth(nextTransport, packet);\n }\n markTest(\"display\");\n appendEvent(\"display\", `Sent ${display.pages} display page(s)`);\n } catch (err) {\n setError(normalizeError(err));\n appendEvent(\"error\", normalizeError(err));\n } finally {\n setBusy(null);\n }\n }\n\n async function clearDisplay(): Promise<void> {\n setBusy(\"clear\");\n setError(null);\n try {\n const nextTransport = await requireTransport();\n await writeBoth(nextTransport, encodeClearScreen());\n appendEvent(\"display\", \"Cleared display\");\n } catch (err) {\n setError(normalizeError(err));\n appendEvent(\"error\", normalizeError(err));\n } finally {\n setBusy(null);\n }\n }\n\n async function runHardwareCheck(): Promise<void> {\n setBusy(\"check\");\n setError(null);\n try {\n const nextTransport = await requireTransport();\n await writeSide(nextTransport, \"left\", encodeGetSerial());\n await writeBoth(nextTransport, encodeBatteryStatusRequest());\n await writeBoth(nextTransport, encodeBrightness(32));\n await writeBoth(nextTransport, encodeSilentMode(false));\n markTest(\"serial\");\n markTest(\"settings\");\n appendEvent(\"test\", \"Requested serial/battery and sent settings packets\");\n await sendDisplay();\n } catch (err) {\n setError(normalizeError(err));\n appendEvent(\"error\", normalizeError(err));\n setBusy(null);\n }\n }\n\n async function runGuidedValidation(): Promise<void> {\n setBusy(\"guided\");\n setError(null);\n let nextTransport: SmartglassesTransport | null = null;\n try {\n nextTransport = await requireTransport();\n const blocker = headsetValidationBlocker(physicalState, batteryState);\n if (blocker) {\n throw new Error(blocker);\n }\n await setTransportMic(nextTransport, false);\n setMicEnabled(false);\n markTest(\"microphone\");\n markTest(\"micDisableWrite\");\n\n const display = buildViewDisplayPackets(\n \"Validation: single tap, speak clearly, then double tap.\",\n { startSeq: displaySeqRef.current },\n );\n displaySeqRef.current = display.nextSeq;\n for (const packet of display.packets) {\n await writeBoth(nextTransport, packet);\n }\n markTest(\"display\");\n appendEvent(\"validation\", \"Single tap, speak clearly, then double tap\");\n\n const deadline = Date.now() + 60_000;\n while (Date.now() < deadline) {\n const current = testsRef.current;\n if (current.tapMicEnable && current.audio && current.tapMicDisable) {\n appendEvent(\"validation\", \"Side-tap microphone validation passed\");\n return;\n }\n await sleep(500);\n }\n\n const current = testsRef.current;\n const missing = [\n !current.tapMicEnable && \"tap mic enable\",\n !current.audio && \"right/bridge audio\",\n !current.tapMicDisable && \"tap mic disable\",\n ].filter(Boolean);\n throw new Error(`Guided validation missing: ${missing.join(\", \")}`);\n } catch (err) {\n setError(normalizeError(err));\n appendEvent(\"error\", normalizeError(err));\n } finally {\n try {\n if (nextTransport) {\n await setTransportMic(nextTransport, false);\n setMicEnabled(false);\n }\n } catch {\n // The validation result should preserve the original failure.\n }\n setBusy(null);\n }\n }\n\n async function toggleMic(enabled: boolean): Promise<void> {\n setBusy(enabled ? \"mic-on\" : \"mic-off\");\n setError(null);\n try {\n const nextTransport = await requireTransport();\n await setTransportMic(nextTransport, enabled);\n setMicEnabled(enabled);\n markTest(\"microphone\");\n markTest(enabled ? \"micEnableWrite\" : \"micDisableWrite\");\n appendEvent(\"microphone\", enabled ? \"Enabled\" : \"Disabled\");\n } catch (err) {\n setError(normalizeError(err));\n appendEvent(\"error\", normalizeError(err));\n } finally {\n setBusy(null);\n }\n }\n\n async function scanWifi(): Promise<void> {\n setBusy(\"wifi-scan\");\n setError(null);\n try {\n if (!bridge) throw new Error(\"Unavailable\");\n const result = await callWifiBridge(bridge, \"request_wifi_scan\");\n const networks = parseWifiNetworks(result);\n setWifiNetworks(networks);\n setWifiStatus(\n networks.length > 0\n ? `Found ${networks.length} network(s)`\n : \"Scan requested; waiting for bridge results\",\n );\n appendEvent(\"wifi\", \"Requested Wi-Fi scan through bridge\");\n } catch (err) {\n setError(normalizeError(err));\n setWifiStatus(normalizeError(err));\n appendEvent(\"error\", normalizeError(err));\n } finally {\n setBusy(null);\n }\n }\n\n async function refreshWifiStatus(): Promise<void> {\n setBusy(\"wifi-status\");\n setError(null);\n try {\n if (!bridge) throw new Error(\"Unavailable\");\n const result = await callWifiBridge(bridge, \"request_wifi_status\");\n const networks = parseWifiNetworks(result);\n if (networks.length > 0) setWifiNetworks(networks);\n setWifiStatus(formatWifiStatus(result));\n appendEvent(\"wifi\", \"Requested Wi-Fi status through bridge\");\n } catch (err) {\n setError(normalizeError(err));\n setWifiStatus(normalizeError(err));\n appendEvent(\"error\", normalizeError(err));\n } finally {\n setBusy(null);\n }\n }\n\n async function configureWifi(): Promise<void> {\n setBusy(\"wifi-configure\");\n setError(null);\n try {\n if (!bridge) throw new Error(\"Unavailable\");\n if (!wifiSsid.trim()) throw new Error(\"Enter a Wi-Fi SSID\");\n await callWifiBridge(bridge, \"set_wifi_credentials\", {\n ssid: wifiSsid.trim(),\n password: wifiPassword,\n });\n setWifiStatus(`Credentials sent for ${wifiSsid.trim()}`);\n appendEvent(\"wifi\", `Sent credentials for ${wifiSsid.trim()}`);\n } catch (err) {\n setError(normalizeError(err));\n setWifiStatus(normalizeError(err));\n appendEvent(\"error\", normalizeError(err));\n } finally {\n setBusy(null);\n }\n }\n\n async function requestWifiSetup(): Promise<void> {\n setBusy(\"wifi-setup\");\n setError(null);\n try {\n if (!bridge) throw new Error(\"Unavailable\");\n await callWifiBridge(bridge, \"request_wifi_setup\", {\n reason: \"Smartglasses setup\",\n });\n setWifiStatus(\"Native Wi-Fi setup requested\");\n appendEvent(\"wifi\", \"Requested native Wi-Fi setup flow\");\n } catch (err) {\n setError(normalizeError(err));\n setWifiStatus(normalizeError(err));\n appendEvent(\"error\", normalizeError(err));\n } finally {\n setBusy(null);\n }\n }\n\n async function copyReport(): Promise<void> {\n window.facewearSmartglassesReport = report;\n await navigator.clipboard?.writeText(JSON.stringify(report, null, 2));\n appendEvent(\"report\", \"Copied diagnostics report\");\n }\n\n function downloadReport(): void {\n window.facewearSmartglassesReport = report;\n const blob = new Blob([JSON.stringify(report, null, 2)], {\n type: \"application/json\",\n });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = `smartglasses-report-${Date.now()}.json`;\n anchor.click();\n URL.revokeObjectURL(url);\n appendEvent(\"report\", \"Downloaded diagnostics report\");\n }\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col overflow-y-auto bg-bg text-txt\">\n <div className=\"px-4 py-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2\">\n <Glasses className=\"h-4 w-4 text-accent\" />\n <h1 className=\"text-sm font-semibold\">Smartglasses</h1>\n </div>\n </div>\n <StatusPill\n ok={headsetConnected}\n label={headsetConnected ? \"Connected\" : \"Offline\"}\n />\n </div>\n </div>\n\n <div className=\"mx-auto flex w-full max-w-3xl flex-col gap-3 p-4\">\n <Panel>\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div>\n <h2 className=\"text-sm font-semibold\">Setup</h2>\n </div>\n <button\n ref={connectRef}\n type=\"button\"\n onClick={() => void connectHeadset()}\n disabled={(!bridge && !webBluetoothAvailable) || busy !== null}\n aria-label=\"Connect\"\n 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\"\n {...connectAgentProps}\n >\n <Bluetooth className=\"h-4 w-4\" />\n Connect\n </button>\n </div>\n <div className=\"mt-4 grid gap-3 sm:grid-cols-2\">\n <LensStatus side=\"left\" state={lenses.left} />\n <LensStatus side=\"right\" state={lenses.right} />\n </div>\n {!webBluetoothAvailable && (\n <p className=\"mt-3 px-1 text-xs text-muted\">\n Web Bluetooth unavailable\n </p>\n )}\n <HeadsetStateHint\n physicalState={physicalState}\n batteryState={batteryState}\n deviceState={deviceState}\n />\n </Panel>\n\n <Panel>\n <h2 className=\"text-sm font-semibold\">Platform</h2>\n <div className=\"mt-3 grid grid-cols-3 gap-1\">\n {(Object.keys(PLATFORM_COPY) as PlatformKey[]).map((key) => (\n <PlatformTabButton\n key={key}\n platformKey={key}\n isActive={activePlatform === key}\n onSelect={setActivePlatform}\n />\n ))}\n </div>\n <p className=\"mt-3 text-xs text-txt\">\n {PLATFORM_COPY[activePlatform].primary}\n </p>\n <p className=\"mt-2 text-xs text-muted\">\n {PLATFORM_COPY[activePlatform].secondary}\n </p>\n </Panel>\n\n <Panel>\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <h2 className=\"text-sm font-semibold\">Test</h2>\n </div>\n <button\n ref={runCheckRef}\n type=\"button\"\n onClick={() => void runHardwareCheck()}\n disabled={!headsetConnected || busy !== null}\n aria-label=\"Run Check\"\n 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\"\n {...runCheckAgentProps}\n >\n <RefreshCw className=\"h-4 w-4\" />\n Check\n </button>\n </div>\n <div className=\"mt-4 grid grid-cols-3 gap-2\">\n {DISPLAY_PRESETS.map((preset) => (\n <button\n key={preset.id}\n type=\"button\"\n onClick={() => setTestText(preset.text)}\n aria-pressed={testText === preset.text}\n className={`h-14 px-3 text-left text-xs font-semibold transition ${\n testText === preset.text\n ? preset.className\n : \"text-muted hover:text-txt\"\n }`}\n >\n {preset.label}\n </button>\n ))}\n </div>\n <div className=\"mt-3 flex flex-wrap gap-2\">\n <ActionButton\n onClick={sendDisplay}\n disabled={!headsetConnected || busy !== null}\n agentId=\"test-send-display\"\n agentLabel=\"Send Display\"\n agentGroup=\"test\"\n agentDescription=\"Send the display test text to the smartglasses\"\n >\n Display\n </ActionButton>\n <ActionButton\n onClick={clearDisplay}\n disabled={!headsetConnected || busy !== null}\n agentId=\"test-clear-display\"\n agentLabel=\"Clear Display\"\n agentGroup=\"test\"\n agentDescription=\"Clear the smartglasses display\"\n >\n Clear\n </ActionButton>\n <ActionButton\n onClick={() => toggleMic(!micEnabled)}\n disabled={!headsetConnected || busy !== null}\n agentId=\"test-toggle-mic\"\n agentLabel={micEnabled ? \"Turn Mic Off\" : \"Turn Mic On\"}\n agentGroup=\"test\"\n agentDescription=\"Toggle the smartglasses microphone on or off\"\n >\n <Mic className=\"h-4 w-4\" />\n {micEnabled ? \"Mic Off\" : \"Mic On\"}\n </ActionButton>\n <ActionButton\n onClick={runGuidedValidation}\n disabled={!headsetConnected || busy !== null}\n agentId=\"test-guided-validation\"\n agentLabel=\"Guided Validation\"\n agentGroup=\"test\"\n agentDescription=\"Run the guided side-tap and microphone validation flow\"\n >\n Validate\n </ActionButton>\n </div>\n <div className=\"mt-4 grid gap-2 sm:grid-cols-2\">\n {(Object.entries(tests) as Array<[string, boolean]>)\n .slice(0, VISIBLE_TEST_LIMIT)\n .map(([id, ok]) => (\n <CheckRow key={id} ok={ok} label={labelForTest(id)} />\n ))}\n {Object.keys(tests).length > VISIBLE_TEST_LIMIT ? (\n <div className=\"px-3 py-2 text-xs text-muted\">\n +{Object.keys(tests).length - VISIBLE_TEST_LIMIT} checks\n </div>\n ) : null}\n </div>\n </Panel>\n\n <Panel>\n <div className=\"flex items-center gap-2\">\n <Wifi className=\"h-4 w-4 text-accent\" />\n <h2 className=\"text-sm font-semibold\">Wi-Fi</h2>\n </div>\n <div className=\"mt-4 grid gap-2 sm:grid-cols-2\">\n <input\n ref={wifiSsidRef}\n value={wifiSsid}\n onChange={(event) => setWifiSsid(event.target.value)}\n placeholder=\"SSID\"\n aria-label=\"Wi-Fi SSID\"\n className=\"h-9 rounded-md border border-border bg-bg px-3 text-sm outline-none focus:ring-2 focus:ring-ring\"\n {...wifiSsidAgentProps}\n />\n <input\n ref={wifiPasswordRef}\n value={wifiPassword}\n onChange={(event) => setWifiPassword(event.target.value)}\n placeholder=\"Password\"\n type=\"password\"\n aria-label=\"Wi-Fi password\"\n className=\"h-9 rounded-md border border-border bg-bg px-3 text-sm outline-none focus:ring-2 focus:ring-ring\"\n {...wifiPasswordAgentProps}\n />\n </div>\n <div className=\"mt-3 flex flex-wrap gap-2\">\n <ActionButton\n onClick={scanWifi}\n disabled={!bridge || busy !== null}\n agentId=\"wifi-scan\"\n agentLabel=\"Scan Wi-Fi\"\n agentGroup=\"wifi\"\n agentDescription=\"Scan for nearby Wi-Fi networks through the native bridge\"\n >\n Scan\n </ActionButton>\n <ActionButton\n onClick={refreshWifiStatus}\n disabled={!bridge || busy !== null}\n agentId=\"wifi-status\"\n agentLabel=\"Refresh Wi-Fi Status\"\n agentGroup=\"wifi\"\n agentDescription=\"Refresh the current Wi-Fi connection status\"\n >\n Status\n </ActionButton>\n <ActionButton\n onClick={configureWifi}\n disabled={!bridge || busy !== null}\n agentId=\"wifi-configure\"\n agentLabel=\"Configure Wi-Fi\"\n agentGroup=\"wifi\"\n agentDescription=\"Send the entered SSID and password to the glasses\"\n >\n Configure\n </ActionButton>\n <ActionButton\n onClick={requestWifiSetup}\n disabled={!bridge || busy !== null}\n agentId=\"wifi-native-setup\"\n agentLabel=\"Native Wi-Fi Setup\"\n agentGroup=\"wifi\"\n agentDescription=\"Launch the native bridge Wi-Fi setup flow\"\n >\n Setup\n </ActionButton>\n </div>\n <p className=\"mt-3 text-xs text-muted\">{wifiStatus}</p>\n {wifiNetworks.length > 0 && (\n <div className=\"mt-2 flex flex-wrap gap-1\">\n {wifiNetworks.slice(0, VISIBLE_WIFI_LIMIT).map((network) => (\n <span key={network} className=\"px-1.5 py-1 text-xs text-muted\">\n {network}\n </span>\n ))}\n {wifiNetworks.length > VISIBLE_WIFI_LIMIT ? (\n <span className=\"px-1.5 py-1 text-xs text-muted\">\n +{wifiNetworks.length - VISIBLE_WIFI_LIMIT}\n </span>\n ) : null}\n </div>\n )}\n </Panel>\n\n <Panel>\n <div className=\"flex items-center gap-2\">\n <BatteryCharging className=\"h-4 w-4 text-accent\" />\n <h2 className=\"text-sm font-semibold\">Report</h2>\n </div>\n <div className=\"mt-3 grid gap-2 text-xs\">\n <ReportRow label=\"Transport\" value={report.transport ?? \"none\"} />\n <ReportRow label=\"Complete\" value={report.ok ? \"yes\" : \"no\"} />\n <ReportRow\n label=\"Serial\"\n value={report.serialNumber ?? \"unknown\"}\n />\n <ReportRow label=\"Next\" value={report.nextAction ?? \"none\"} />\n <ReportRow\n label=\"Missing\"\n value={\n report.missingEvidence.length === 0\n ? \"none\"\n : String(report.missingEvidence.length)\n }\n />\n <ReportRow label=\"Bridge\" value={bridge ? \"available\" : \"none\"} />\n <ReportRow\n label=\"State\"\n value={\n [physicalState, batteryState, deviceState]\n .filter(Boolean)\n .join(\" / \") || \"none\"\n }\n />\n <ReportRow\n label=\"Battery\"\n value={formatBatteryLevels(batteryLevels)}\n />\n <ReportRow label=\"Events\" value={String(events.length)} />\n </div>\n <div className=\"mt-4 flex flex-wrap gap-2\">\n <ActionButton\n onClick={copyReport}\n agentId=\"report-copy\"\n agentLabel=\"Copy Report\"\n agentGroup=\"report\"\n agentDescription=\"Copy the smartglasses diagnostics report to the clipboard\"\n >\n <Clipboard className=\"h-4 w-4\" />\n Copy\n </ActionButton>\n <ActionButton\n onClick={downloadReport}\n agentId=\"report-download\"\n agentLabel=\"Download Report\"\n agentGroup=\"report\"\n agentDescription=\"Download the smartglasses diagnostics report as JSON\"\n >\n <Download className=\"h-4 w-4\" />\n Download\n </ActionButton>\n </div>\n </Panel>\n\n <Panel>\n <div className=\"flex items-center gap-2\">\n <Settings2 className=\"h-4 w-4 text-accent\" />\n <h2 className=\"text-sm font-semibold\">Events</h2>\n </div>\n <div className=\"mt-3 max-h-72 overflow-y-auto\">\n {events.length === 0 ? (\n <p className=\"px-1 py-2 text-xs text-muted\">None</p>\n ) : (\n events\n .slice()\n .reverse()\n .slice(0, VISIBLE_EVENT_LIMIT)\n .map((event) => (\n <div\n key={`${event.at}:${event.type}:${event.detail}`}\n className=\"px-1 py-2\"\n >\n <p className=\"text-xs font-medium text-txt\">{event.type}</p>\n <p className=\"mt-0.5 text-xs text-muted\">{event.detail}</p>\n </div>\n ))\n )}\n {events.length > VISIBLE_EVENT_LIMIT ? (\n <div className=\"px-3 py-2 text-xs text-muted\">\n +{events.length - VISIBLE_EVENT_LIMIT} older events\n </div>\n ) : null}\n </div>\n </Panel>\n </div>\n {error && (\n <div className=\"mx-4 mb-4 px-1 py-2 text-xs text-destructive\">\n {error}\n </div>\n )}\n </div>\n );\n}\n\nfunction Panel({ children }: { children: ReactNode }) {\n return <div className=\"py-2\">{children}</div>;\n}\n\nfunction ActionButton({\n children,\n disabled,\n onClick,\n agentId,\n agentLabel,\n agentGroup,\n agentDescription,\n}: {\n children: ReactNode;\n disabled?: boolean;\n onClick: () => void | Promise<void>;\n agentId: string;\n agentLabel: string;\n agentGroup: string;\n agentDescription: string;\n}) {\n const { ref, agentProps } = useAgentElement<HTMLButtonElement>({\n id: agentId,\n role: \"button\",\n label: agentLabel,\n group: agentGroup,\n description: agentDescription,\n onActivate: () => void onClick(),\n });\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={() => void onClick()}\n disabled={disabled}\n aria-label={agentLabel}\n 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\"\n {...agentProps}\n >\n {children}\n </button>\n );\n}\n\nfunction PlatformTabButton({\n platformKey,\n isActive,\n onSelect,\n}: {\n key?: PlatformKey;\n platformKey: PlatformKey;\n isActive: boolean;\n onSelect: (key: PlatformKey) => void;\n}) {\n const label = PLATFORM_COPY[platformKey].label;\n const { ref, agentProps } = useAgentElement<HTMLButtonElement>({\n id: `platform-tab-${platformKey}`,\n role: \"tab\",\n label: `${label} platform`,\n group: \"platform-setup\",\n status: isActive ? \"active\" : \"inactive\",\n description: `Show ${label} smartglasses pairing instructions`,\n onActivate: () => onSelect(platformKey),\n });\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={() => onSelect(platformKey)}\n aria-current={isActive ? \"page\" : undefined}\n aria-label={`${label} platform`}\n className={`h-8 px-2 text-xs font-medium transition-colors ${\n isActive ? \"text-accent\" : \"text-muted hover:bg-muted/20 hover:text-txt\"\n }`}\n {...agentProps}\n >\n {label}\n </button>\n );\n}\n\nfunction StatusPill({ ok, label }: { ok: boolean; label: string }) {\n return (\n <span\n className={`inline-flex h-7 items-center gap-1.5 px-1.5 text-xs font-medium ${\n ok ? \"text-green-700 dark:text-green-300\" : \"text-muted\"\n }`}\n >\n {ok ? (\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n ) : (\n <XCircle className=\"h-3.5 w-3.5\" />\n )}\n {label}\n </span>\n );\n}\n\nfunction LensStatus({ side, state }: { side: GlassSide; state: LensState }) {\n const ok = state === \"connected\";\n return (\n <div className=\"flex items-center justify-between px-1 py-2\">\n <div className=\"flex items-center gap-2\">\n <Glasses className=\"h-4 w-4 text-muted\" />\n <span className=\"text-sm capitalize\">{side}</span>\n </div>\n <StatusPill ok={ok} label={state} />\n </div>\n );\n}\n\nfunction HeadsetStateHint({\n physicalState,\n batteryState,\n deviceState,\n}: {\n physicalState: string | null;\n batteryState: string | null;\n deviceState: string | null;\n}) {\n const chips: Array<{ key: string; value: string }> = [\n { key: \"physical\", value: physicalState ?? \"\" },\n { key: \"battery\", value: batteryState ?? \"\" },\n { key: \"device\", value: deviceState ?? \"\" },\n ].filter((c) => c.value.length > 0);\n const blocked = isCradleOrChargingState(physicalState, batteryState);\n const ready = physicalState === \"wearing\";\n const tone = blocked\n ? \"text-amber-800 dark:text-amber-200\"\n : ready\n ? \"text-green-700 dark:text-green-300\"\n : \"text-muted\";\n const hint = blocked\n ? \"Remove from charger and wear before validation.\"\n : ready\n ? \"Ready for tap/audio validation.\"\n : \"Wear state required for tap/audio validation.\";\n return (\n <div className={`mt-3 px-1 py-2 ${tone}`}>\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <span className=\"text-2xs font-semibold uppercase tracking-wider opacity-70\">\n Headset\n </span>\n {chips.length > 0 ? (\n chips.map((chip) => (\n <span\n key={chip.key}\n className=\"inline-flex items-center gap-1 px-1.5 py-0.5 text-2xs font-medium\"\n >\n <span\n className=\"h-1 w-1 rounded-full bg-current opacity-70\"\n aria-hidden\n />\n {chip.value}\n </span>\n ))\n ) : (\n <span className=\"text-2xs italic opacity-70\">no state yet</span>\n )}\n </div>\n <p className=\"mt-1.5 text-2xs leading-4 opacity-80\">{hint}</p>\n </div>\n );\n}\n\nfunction CheckRow({ ok, label }: { ok: boolean; label: string; key?: string }) {\n return (\n <div className=\"flex items-center justify-between gap-2 px-1 py-2 transition-colors\">\n <span className={`text-xs ${ok ? \"font-medium text-txt\" : \"text-muted\"}`}>\n {label}\n </span>\n <span\n className={`inline-flex items-center gap-1.5 rounded-full px-1.5 py-0.5 ${\n ok ? \"text-green-600 dark:text-green-400\" : \"text-muted\"\n }`}\n >\n <span\n className={`h-1.5 w-1.5 rounded-full ${\n ok ? \"bg-green-500\" : \"bg-muted/40\"\n }`}\n aria-hidden\n />\n {ok ? (\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n ) : (\n <Circle className=\"h-3.5 w-3.5\" />\n )}\n </span>\n </div>\n );\n}\n\nfunction ReportRow({ label, value }: { label: string; value: string }) {\n return (\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-muted\">{label}</span>\n <span className=\"truncate font-medium text-txt\">{value}</span>\n </div>\n );\n}\n\nfunction formatBatteryLevels(\n levels: Partial<Record<GlassSide, number>>,\n): string {\n const left = levels.left === undefined ? \"unknown\" : `${levels.left}%`;\n const right = levels.right === undefined ? \"unknown\" : `${levels.right}%`;\n return `L ${left} / R ${right}`;\n}\n\nfunction labelForTest(id: string): string {\n const labels: Record<string, string> = {\n headsetConnected: \"Whole headset\",\n init: \"Init packets\",\n display: \"Display\",\n serial: \"Serial request\",\n serialObserved: \"Serial observed\",\n settings: \"Settings\",\n microphone: \"Microphone\",\n micEnableWrite: \"Mic enable write\",\n micDisableWrite: \"Mic disable write\",\n tapMicEnable: \"Tap mic enable\",\n tapMicDisable: \"Tap mic disable\",\n audio: \"Audio\",\n transcript: \"Transcript\",\n eventStream: \"Events\",\n };\n return labels[id] ?? id;\n}\n"],"mappings":"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"}
|