@elizaos/plugin-facewear 2.0.3-beta.5 → 2.0.3-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,"sources":["../../src/ui/SmartglassesView.tsx"],"sourcesContent":["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.js\";\nimport { EvenBridgeTransport } from \"../transport/even-bridge.js\";\nimport type { SmartglassesTransport } from \"../transport/types.js\";\nimport {\n getWebBluetoothG1Transport,\n WebBluetoothG1Transport,\n} from \"../transport/web-bluetooth.js\";\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.js\";\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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","names":["current"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { FacewearView } from "../components/FacewearView.js";
|
|
2
|
+
export { SmartglassesPanelView } from "../components/SmartglassesPanelView.js";
|
|
3
|
+
export { FacewearAppView, FacewearTuiView, SmartglassesTuiView, } from "./FacewearAppView.js";
|
|
4
|
+
export { SmartglassesView } from "./SmartglassesView.js";
|
|
5
|
+
//# sourceMappingURL=facewear-view-bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facewear-view-bundle.d.ts","sourceRoot":"","sources":["../../src/ui/facewear-view-bundle.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAChF,OAAO,EACL,eAAe,EACf,eAAe,EACf,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FacewearView } from "../components/FacewearView.js";
|
|
2
|
+
import { SmartglassesPanelView } from "../components/SmartglassesPanelView.js";
|
|
3
|
+
import {
|
|
4
|
+
FacewearAppView,
|
|
5
|
+
FacewearTuiView,
|
|
6
|
+
SmartglassesTuiView
|
|
7
|
+
} from "./FacewearAppView.js";
|
|
8
|
+
import { SmartglassesView } from "./SmartglassesView.js";
|
|
9
|
+
export {
|
|
10
|
+
FacewearAppView,
|
|
11
|
+
FacewearTuiView,
|
|
12
|
+
FacewearView,
|
|
13
|
+
SmartglassesPanelView,
|
|
14
|
+
SmartglassesTuiView,
|
|
15
|
+
SmartglassesView
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=facewear-view-bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/ui/facewear-view-bundle.ts"],"sourcesContent":["// Vite view-bundle entry. Re-exports the view components the facewear plugin\n// manifest declares (see the `views` array in src/index.ts) so the built bundle\n// (dist/views/bundle.js) exposes the named exports the view loader reads.\n//\n// The two own views collapse to one tri-modal declaration each:\n// - `FacewearView` → the gui/xr/tui Facewear data wrapper\n// - `SmartglassesPanelView` → the gui/xr/tui Smartglasses operator panel\n// Both render the single spatial source (FacewearSpatialView /\n// SmartglassesSpatialView). The legacy full-screen dashboards (FacewearAppView,\n// SmartglassesView) and the TUI shims stay exported because the app shell mounts\n// them as overlay pages.\nexport { FacewearView } from \"../components/FacewearView.js\";\nexport { SmartglassesPanelView } from \"../components/SmartglassesPanelView.js\";\nexport {\n FacewearAppView,\n FacewearTuiView,\n SmartglassesTuiView,\n} from \"./FacewearAppView.js\";\nexport { SmartglassesView } from \"./SmartglassesView.js\";\n"],"mappings":"AAWA,SAAS,oBAAoB;AAC7B,SAAS,6BAA6B;AACtC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,wBAAwB;","names":[]}
|