@elizaos/plugin-facewear 2.0.3-beta.2
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/LICENSE +21 -0
- package/README.md +10 -0
- package/assets/hero-facewear.png +0 -0
- package/assets/hero-facewear.svg +70 -0
- package/assets/hero-smartglasses.png +0 -0
- package/assets/hero-smartglasses.svg +70 -0
- package/docs/smartglasses-completion-audit.md +118 -0
- package/docs/smartglasses-upstream-audit.md +127 -0
- package/docs/smartglasses.md +429 -0
- package/package.json +139 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shaw Walters and elizaOS Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# @elizaos/plugin-facewear
|
|
2
|
+
|
|
3
|
+
Unified facewear integration for XR headsets and smartglasses.
|
|
4
|
+
|
|
5
|
+
- View Manager pages at `/apps/facewear` and `/apps/smartglasses`.
|
|
6
|
+
- Even Realities G1/G2 whole-headset pairing, display, microphone, side-tap, diagnostics, and bridge Wi-Fi setup.
|
|
7
|
+
- XR session/view hosting for Meta Quest, XReal, Apple Vision Pro, simulator, and other WebXR clients.
|
|
8
|
+
|
|
9
|
+
Detailed Even Realities implementation notes and hardware proof workflow live in
|
|
10
|
+
`docs/smartglasses.md`.
|
|
Binary file
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1024" height="1024" role="img" aria-label="Facewear">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg-facewear" x1="0" y1="0" x2="1" y2="1">
|
|
4
|
+
<stop offset="0" stop-color="#152528"/>
|
|
5
|
+
<stop offset="1" stop-color="#0b1319"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<radialGradient id="blobA-facewear" cx="0.5" cy="0.5" r="0.5">
|
|
8
|
+
<stop offset="0" stop-color="#2fbeda" stop-opacity="0.55"/>
|
|
9
|
+
<stop offset="1" stop-color="#2fbeda" stop-opacity="0"/>
|
|
10
|
+
</radialGradient>
|
|
11
|
+
<radialGradient id="blobB-facewear" cx="0.5" cy="0.5" r="0.5">
|
|
12
|
+
<stop offset="0" stop-color="#2861c3" stop-opacity="0.5"/>
|
|
13
|
+
<stop offset="1" stop-color="#2861c3" stop-opacity="0"/>
|
|
14
|
+
</radialGradient>
|
|
15
|
+
<radialGradient id="vig-facewear" cx="0.5" cy="0.42" r="0.75">
|
|
16
|
+
<stop offset="0" stop-color="#000000" stop-opacity="0"/>
|
|
17
|
+
<stop offset="0.72" stop-color="#000000" stop-opacity="0"/>
|
|
18
|
+
<stop offset="1" stop-color="#000000" stop-opacity="0.5"/>
|
|
19
|
+
</radialGradient>
|
|
20
|
+
<linearGradient id="label-facewear" x1="0" y1="0" x2="0" y2="1">
|
|
21
|
+
<stop offset="0" stop-color="#000000" stop-opacity="0"/>
|
|
22
|
+
<stop offset="1" stop-color="#000000" stop-opacity="0.55"/>
|
|
23
|
+
</linearGradient>
|
|
24
|
+
<filter id="soft-facewear" x="-30%" y="-30%" width="160%" height="160%">
|
|
25
|
+
<feGaussianBlur stdDeviation="46"/>
|
|
26
|
+
</filter>
|
|
27
|
+
<filter id="iglow-facewear" x="-40%" y="-40%" width="180%" height="180%">
|
|
28
|
+
<feDropShadow dx="0" dy="0" stdDeviation="14" flood-color="#45d1ed" flood-opacity="0.45"/>
|
|
29
|
+
</filter>
|
|
30
|
+
</defs>
|
|
31
|
+
|
|
32
|
+
<rect width="1024" height="1024" fill="url(#bg-facewear)"/>
|
|
33
|
+
|
|
34
|
+
<g opacity="0.9">
|
|
35
|
+
<circle cx="232" cy="220" r="300" fill="url(#blobA-facewear)" filter="url(#soft-facewear)"/>
|
|
36
|
+
<circle cx="840" cy="800" r="340" fill="url(#blobB-facewear)" filter="url(#soft-facewear)"/>
|
|
37
|
+
</g>
|
|
38
|
+
|
|
39
|
+
<g stroke="#d7e7ea" stroke-width="1.4" opacity="0.06">
|
|
40
|
+
<line x1="0" y1="256" x2="1024" y2="256"/>
|
|
41
|
+
<line x1="0" y1="512" x2="1024" y2="512"/>
|
|
42
|
+
<line x1="0" y1="768" x2="1024" y2="768"/>
|
|
43
|
+
<line x1="256" y1="0" x2="256" y2="1024"/>
|
|
44
|
+
<line x1="512" y1="0" x2="512" y2="1024"/>
|
|
45
|
+
<line x1="768" y1="0" x2="768" y2="1024"/>
|
|
46
|
+
</g>
|
|
47
|
+
|
|
48
|
+
<g opacity="0.5">
|
|
49
|
+
<path d="M120 470 A 400 400 0 0 1 904 470" fill="none" stroke="#45d1ed" stroke-width="3" opacity="0.35"/>
|
|
50
|
+
</g>
|
|
51
|
+
|
|
52
|
+
<g transform="translate(512 432)" filter="url(#iglow-facewear)"
|
|
53
|
+
color="#d7e7ea" stroke="#d7e7ea" stroke-width="20"
|
|
54
|
+
stroke-linecap="round" stroke-linejoin="round" fill="none">
|
|
55
|
+
<path d="M-140 30 V-10 A140 140 0 0 1 140 -10 V30"/>
|
|
56
|
+
<rect x="-160" y="26" width="58" height="110" rx="26" fill="currentColor" stroke-width="0"/>
|
|
57
|
+
<rect x="102" y="26" width="58" height="110" rx="26" fill="currentColor" stroke-width="0"/>
|
|
58
|
+
<rect x="-160" y="26" width="58" height="110" rx="26"/>
|
|
59
|
+
<rect x="102" y="26" width="58" height="110" rx="26"/>
|
|
60
|
+
</g>
|
|
61
|
+
|
|
62
|
+
<rect x="0" y="784" width="1024" height="240" fill="url(#label-facewear)"/>
|
|
63
|
+
<text x="512" y="892" text-anchor="middle"
|
|
64
|
+
font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
|
|
65
|
+
font-size="76" font-weight="600" letter-spacing="0.5"
|
|
66
|
+
fill="#d7e7ea">Facewear</text>
|
|
67
|
+
<rect x="460" y="924" width="104" height="6" rx="3" fill="#45d1ed"/>
|
|
68
|
+
|
|
69
|
+
<rect width="1024" height="1024" fill="url(#vig-facewear)"/>
|
|
70
|
+
</svg>
|
|
Binary file
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024" width="1024" height="1024" role="img" aria-label="Smartglasses">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="bg-smartglasses" x1="0" y1="0" x2="1" y2="1">
|
|
4
|
+
<stop offset="0" stop-color="#281528"/>
|
|
5
|
+
<stop offset="1" stop-color="#190b16"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
<radialGradient id="blobA-smartglasses" cx="0.5" cy="0.5" r="0.5">
|
|
8
|
+
<stop offset="0" stop-color="#da2fda" stop-opacity="0.55"/>
|
|
9
|
+
<stop offset="1" stop-color="#da2fda" stop-opacity="0"/>
|
|
10
|
+
</radialGradient>
|
|
11
|
+
<radialGradient id="blobB-smartglasses" cx="0.5" cy="0.5" r="0.5">
|
|
12
|
+
<stop offset="0" stop-color="#c3287a" stop-opacity="0.5"/>
|
|
13
|
+
<stop offset="1" stop-color="#c3287a" stop-opacity="0"/>
|
|
14
|
+
</radialGradient>
|
|
15
|
+
<radialGradient id="vig-smartglasses" cx="0.5" cy="0.42" r="0.75">
|
|
16
|
+
<stop offset="0" stop-color="#000000" stop-opacity="0"/>
|
|
17
|
+
<stop offset="0.72" stop-color="#000000" stop-opacity="0"/>
|
|
18
|
+
<stop offset="1" stop-color="#000000" stop-opacity="0.5"/>
|
|
19
|
+
</radialGradient>
|
|
20
|
+
<linearGradient id="label-smartglasses" x1="0" y1="0" x2="0" y2="1">
|
|
21
|
+
<stop offset="0" stop-color="#000000" stop-opacity="0"/>
|
|
22
|
+
<stop offset="1" stop-color="#000000" stop-opacity="0.55"/>
|
|
23
|
+
</linearGradient>
|
|
24
|
+
<filter id="soft-smartglasses" x="-30%" y="-30%" width="160%" height="160%">
|
|
25
|
+
<feGaussianBlur stdDeviation="46"/>
|
|
26
|
+
</filter>
|
|
27
|
+
<filter id="iglow-smartglasses" x="-40%" y="-40%" width="180%" height="180%">
|
|
28
|
+
<feDropShadow dx="0" dy="0" stdDeviation="14" flood-color="#ed45ed" flood-opacity="0.45"/>
|
|
29
|
+
</filter>
|
|
30
|
+
</defs>
|
|
31
|
+
|
|
32
|
+
<rect width="1024" height="1024" fill="url(#bg-smartglasses)"/>
|
|
33
|
+
|
|
34
|
+
<g opacity="0.9">
|
|
35
|
+
<circle cx="232" cy="220" r="300" fill="url(#blobA-smartglasses)" filter="url(#soft-smartglasses)"/>
|
|
36
|
+
<circle cx="840" cy="800" r="340" fill="url(#blobB-smartglasses)" filter="url(#soft-smartglasses)"/>
|
|
37
|
+
</g>
|
|
38
|
+
|
|
39
|
+
<g stroke="#ead7ea" stroke-width="1.4" opacity="0.06">
|
|
40
|
+
<line x1="0" y1="256" x2="1024" y2="256"/>
|
|
41
|
+
<line x1="0" y1="512" x2="1024" y2="512"/>
|
|
42
|
+
<line x1="0" y1="768" x2="1024" y2="768"/>
|
|
43
|
+
<line x1="256" y1="0" x2="256" y2="1024"/>
|
|
44
|
+
<line x1="512" y1="0" x2="512" y2="1024"/>
|
|
45
|
+
<line x1="768" y1="0" x2="768" y2="1024"/>
|
|
46
|
+
</g>
|
|
47
|
+
|
|
48
|
+
<g opacity="0.5">
|
|
49
|
+
<path d="M120 470 A 400 400 0 0 1 904 470" fill="none" stroke="#ed45ed" stroke-width="3" opacity="0.35"/>
|
|
50
|
+
</g>
|
|
51
|
+
|
|
52
|
+
<g transform="translate(512 432)" filter="url(#iglow-smartglasses)"
|
|
53
|
+
color="#ead7ea" stroke="#ead7ea" stroke-width="20"
|
|
54
|
+
stroke-linecap="round" stroke-linejoin="round" fill="none">
|
|
55
|
+
<circle cx="-86" cy="20" r="68"/>
|
|
56
|
+
<circle cx="86" cy="20" r="68"/>
|
|
57
|
+
<path d="M-18 20 Q0 -2 18 20"/>
|
|
58
|
+
<line x1="-154" y1="-12" x2="-180" y2="-44"/>
|
|
59
|
+
<line x1="154" y1="-12" x2="180" y2="-44"/>
|
|
60
|
+
</g>
|
|
61
|
+
|
|
62
|
+
<rect x="0" y="784" width="1024" height="240" fill="url(#label-smartglasses)"/>
|
|
63
|
+
<text x="512" y="892" text-anchor="middle"
|
|
64
|
+
font-family="system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
|
|
65
|
+
font-size="76" font-weight="600" letter-spacing="0.5"
|
|
66
|
+
fill="#ead7ea">Smartglasses</text>
|
|
67
|
+
<rect x="460" y="924" width="104" height="6" rx="3" fill="#ed45ed"/>
|
|
68
|
+
|
|
69
|
+
<rect width="1024" height="1024" fill="url(#vig-smartglasses)"/>
|
|
70
|
+
</svg>
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Smartglasses Completion Audit
|
|
2
|
+
|
|
3
|
+
This audit tracks the requested Even Realities smartglasses objective against
|
|
4
|
+
current repository evidence. It is intentionally stricter than the software
|
|
5
|
+
test suite: the goal is not complete until real hardware evidence proves the
|
|
6
|
+
physical microphone and tap path.
|
|
7
|
+
|
|
8
|
+
## Requirements
|
|
9
|
+
|
|
10
|
+
| Requirement | Evidence | Status |
|
|
11
|
+
| --- | --- | --- |
|
|
12
|
+
| Pull the 12 requested upstream repositories into a gitignored research folder. | `.gitignore` ignores `research/even-realities/`; `docs/smartglasses-upstream-audit.md` lists all 12 local checkouts and reviewed files. | Complete |
|
|
13
|
+
| Review upstream command, display, BLE, bridge, and simulator behavior. | `docs/smartglasses-upstream-audit.md` maps each upstream source to implemented files and tests. | Complete |
|
|
14
|
+
| Implement `plugins/plugin-facewear`. | `src/index.ts`, `src/protocol/smartglasses.ts`, `src/services/smartglasses-service.ts`, `src/actions/*.ts`, `src/providers/smartglasses-status.ts`, and `src/transport/*.ts`. | Complete |
|
|
15
|
+
| Stream and format display text properly. | `src/protocol/smartglasses.ts` implements G1 glyph-width wrapping, page/chunk encoding, Even AI and Text Show modes, and RSVP display; covered by `src/__tests__/protocol-smartglasses.test.ts` and example smokes. | Complete |
|
|
16
|
+
| Receive microphone data. | Direct G1 LC3 packets and bridge PCM/LC3/transcript events are handled in `SmartglassesService` and transports; covered by service, bridge, package, runtime, and parser tests. | Software-complete |
|
|
17
|
+
| Side tap enables/disables microphone input. | `SmartglassesService` maps single tap/long press to right-lens mic enable and double tap/stop recording to mic disable; covered by service and example tests. | Software-complete |
|
|
18
|
+
| Connect the whole headset, not a single lens. | Web Bluetooth, Noble, Bleak, bridge, and View Manager flows require left and right lens records; validators reject missing lens evidence. Web Bluetooth rejects visible side mismatches and duplicate device IDs during picker flow so a wrong or repeated lens selection cannot satisfy whole-headset pairing. Public Web Bluetooth and Noble whole-headset `connect()` calls clean up partial connections on failure. Native bridge status exposes both virtual lens records when the bridge is connected. | Software-complete |
|
|
19
|
+
| Provide an Eliza View Manager view for connect/test/setup. | `src/index.ts` declares Facewear and Smartglasses views and app nav tabs; `src/register.ts` registers `/apps/facewear` and `/apps/smartglasses`; `src/ui/SmartglassesView.tsx` implements connect, diagnostics, Wi-Fi bridge, and guided validation; exported diagnostics now include pairing `scanDiagnosis`, `physicalBlocker`, setup hint, next action, observed serial number, packet writes, and audio chunk metadata; `packages/app-core/src/registry/entries/plugins/facewear.json` launches the internal tab and advertises whole-headset pairing, side-tap mic control, and Wi-Fi provisioning; `bun run --cwd plugins/plugin-facewear verify:app` covers app registry and registration tests. | Complete |
|
|
20
|
+
| Support iOS, Android, desktop setup paths where possible. | View Manager setup copy and transports cover native bridge, Web Bluetooth, Noble/Bleak, and EvenHub/Mentra bridge APIs. Bridge-backed Wi-Fi now supports scan/status/configure plus Mentra-style native `requestWifiSetup(reason)` setup prompts for hosts that expose a setup flow instead of direct credentials. The Even Realities Android companion now scans for `_L_` and `_R_` lenses, connects the whole headset, uses current G1 command framing, and forwards `g1_raw`/`mic_lc3` events to the agent. Direct G1 BLE Wi-Fi provisioning remains unverified upstream and is bridge-only. | Complete with documented Wi-Fi limit |
|
|
21
|
+
| Add an example in `packages/examples`. | `packages/examples/smartglasses` contains package/runtime/simulator/browser/Noble/Bleak smokes, validation helpers, and docs. | Complete |
|
|
22
|
+
| Test with Eliza end to end. | `npm run verify:smartglasses-software` passed on 2026-05-20 after the Facewear build scripts were hardened to use the workspace `tsup` binary for `build:js` and stable `vite@7.2.7` for `build:views`. The root verifier now runs Facewear plugin lint/typecheck/test/app-registration gates, then the full smartglasses example software gate, repairs any Bun lock churn back to `@elizaos/plugin-facewear`, and reruns the consolidation, Even research self-test, Even research audit, and completion self-test guards before the completion gate is evaluated. `bun run --cwd plugins/plugin-facewear test` passed with all 20 plugin test files / 185 tests, including view bundle build and CLI emulator build before Vitest. `bun run --cwd packages/examples/smartglasses verify:software` passed end to end: example lint, Bun tests, protocol tests, Bleak parser test, hardware doctor syntax check, dependency-aware Turbo typecheck, public package smoke, AgentRuntime smoke with setup-friendly aliases, and simulator display/tap automation. `bun run --cwd packages/examples/smartglasses smoke:package` covers 92 mock whole-headset writes, including start AI, clear display, exit dashboard/function, side-specific page-up/page-down, silent mode, brightness, head-up angle, wear detection, app allowlist, notification, BMP transfer, Wi-Fi setup, navigation, translation, notes, display, mic, audio, transcript, and status provider assertions. The same software gate includes `hardware:test-doctor`, a non-hardware syntax check for the macOS Bluetooth/headset diagnostic, and its `typecheck` script builds Facewear dependencies through Turbo before invoking `tsc` so missing workspace declaration artifacts cannot hide dependency-resolution failures. `verify:app` passed with the Facewear app registration tests. The focused action tests prove display/microphone actions fail cleanly without transport, the control action returns structured operation results for invalid parameters and generated commands, package smoke verifies public action failure behavior plus G1 setup/navigation packet counts, and AgentRuntime smoke verifies display/mic return values, invalid control failure payloads, setup-friendly alias canonicalization, alias Wi-Fi requests, alias app allowlist packets, alias QuickNote packets, and previous/next-page alias packet routing. The standalone consolidation guard passed after lock repair and scanned 34,567 files across `packages`, `plugins`, `apps`, and `scripts`; the stale `plugin-smartglasses` spot check was empty after the repair, and the completion gate now also checks critical lockfile/manifest paths plus the stable Facewear build scripts. Earlier focused passes also covered Web Bluetooth side-mismatch/duplicate-device hardening, whole-headset partial-connect cleanup, bridge lens status reporting, View Manager diagnostics, Wi-Fi setup prompts, voice-note list/fetch/delete/delete-all, battery status, dashboard positioning, native Android bridge routing, package/runtime/simulator smokes, hardware doctor paired-but-not-advertising diagnosis coverage, ordered tap-to-mic hardware validator requirements, View Manager ordered tap-to-mic report requirements, and View Manager display packet sequencing. | Software-complete |
|
|
23
|
+
| Prove physical hardware tap and microphone path. | Earlier `/tmp/smartglasses-hardware-report-latest.json` from 2026-05-20 06:38:56Z connected both lenses and observed serial `S110LABC040019`, 17 writes, 14 parsed events, init/display/settings responses, heartbeat packets, and a right-lens mic-disable response, but no physical-state packet, taps, right-lens mic-enable write, or audio. A Noble attempt from 2026-05-20 07:26:42Z wrote a fresh report but failed before scanning because the native Noble binding is unavailable for the current macOS ARM64 Node/Bun ABI, reported as `physicalBlocker: "transport_unavailable"`. The freshest Bleak attempt from 2026-05-20 10:39:00Z found 30 BLE devices but zero Even/G1 name matches and zero Nordic UART-service candidates, so it reports `physicalBlocker: "headset_not_found"` with `status.connected: false`, no serial, no writes, no taps, and no audio. The hardware doctor confirms macOS Bluetooth is on and both lenses are paired (`Even G1_51_L_138507` and `Even G1_51_R_8C0CDF`) but listed under "Not Connected", so the remaining blocker is physical advertising/availability rather than software wiring. | Blocked on physical headset advertising/availability |
|
|
24
|
+
|
|
25
|
+
## Hardware Completion Gate
|
|
26
|
+
|
|
27
|
+
Completion requires a hardware report that passes:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm run smartglasses:hardware:validate
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
For the final physical attempt, the latest-report proof helpers run the smoke,
|
|
34
|
+
print the status summary even on failure, then invoke the validator:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm run smartglasses:hardware:prove
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm run smartglasses:hardware:prove:noble
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The report must include:
|
|
45
|
+
|
|
46
|
+
- left and right lens connection records
|
|
47
|
+
- final service status with both lenses connected
|
|
48
|
+
- connection-ready/init writes
|
|
49
|
+
- display writes
|
|
50
|
+
- serial request and observed serial response
|
|
51
|
+
- settings writes
|
|
52
|
+
- `wearing` physical state
|
|
53
|
+
- single-tap or long-press mic-enable event followed by a right-lens `0x0E 0x01` mic-enable write
|
|
54
|
+
- non-empty right-lens microphone audio
|
|
55
|
+
- double-tap or stop-recording mic-disable event followed by a right-lens `0x0E 0x00` mic-disable write
|
|
56
|
+
- final service status audio counters
|
|
57
|
+
|
|
58
|
+
For upstream research evidence, use the standalone Node guard:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npm run audit:even-research
|
|
62
|
+
npm run audit:even-research:self-test
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
For a single completion gate that also inspects the latest physical report, use:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npm run audit:smartglasses-completion
|
|
69
|
+
npm run audit:smartglasses-completion:self-test
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The current latest report from 2026-05-20 10:39:00Z refreshed the physical
|
|
73
|
+
proof attempt, but it now fails the completion gate with `reportStale`.
|
|
74
|
+
CoreBluetooth was scanning and discovered 30 BLE devices, but
|
|
75
|
+
zero matched Even/G1 names and zero advertised the G1 UART service UUID. It
|
|
76
|
+
therefore did not discover either lens, and `npm run smartglasses:hardware:status` summarizes
|
|
77
|
+
it with `wholeHeadsetConnected: false`, `wearingReady: false`, and
|
|
78
|
+
`physicalBlocker: "headset_not_found"`. The completion gate hardware summary
|
|
79
|
+
now also includes `pairedG1Devices`, `pairedG1DeviceCount`,
|
|
80
|
+
`pairedWholeHeadset`, and `bluetoothAdapter`; for older latest reports that
|
|
81
|
+
predate those fields, it augments the summary from the live macOS Bluetooth
|
|
82
|
+
inventory. The latest-report status and validator summaries also echo those
|
|
83
|
+
fields once the Bleak proof report contains them, and include
|
|
84
|
+
`bluetoothPreflightSource` to distinguish report data from local fallback data.
|
|
85
|
+
macOS Bluetooth system state still lists
|
|
86
|
+
both G1 lenses as paired (`Even G1_51_L_138507` and `Even G1_51_R_8C0CDF`), but
|
|
87
|
+
they are under "Not Connected"; `npm run smartglasses:hardware:doctor` reports this paired-but-not-
|
|
88
|
+
advertising state directly. A Noble report from
|
|
89
|
+
2026-05-20 07:26:42Z failed before scanning because the Noble native binding is
|
|
90
|
+
unavailable for the current runtime and reported
|
|
91
|
+
`physicalBlocker: "transport_unavailable"`. An earlier 2026-05-20 06:38:56Z
|
|
92
|
+
Bleak run
|
|
93
|
+
proved direct BLE connectivity and command/response coverage for both lenses
|
|
94
|
+
(`Even G1_51_L_138507` and `Even G1_51_R_8C0CDF`) and serial
|
|
95
|
+
`S110LABC040019`, but it is stale and did not observe `wearing`, tap events,
|
|
96
|
+
a right-lens mic-enable write, or right-lens audio. Remove both lenses from the
|
|
97
|
+
charging base, keep them near this device, wear the glasses until the report
|
|
98
|
+
shows `physical: "wearing"`, then perform single tap, speech, and double tap.
|
|
99
|
+
Use the watch helper for a longer discovery and worn-state window:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm run smartglasses:hardware:prove
|
|
103
|
+
npm run smartglasses:hardware:validate
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npm run smartglasses:hardware:prove:watch
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
or the full watch proof wrapper:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npm run smartglasses:hardware:prove:watch
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npm run smartglasses:hardware:prove:noble:watch
|
|
118
|
+
```
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Smartglasses Upstream Audit
|
|
2
|
+
|
|
3
|
+
This plugin was built from the gitignored research checkouts under
|
|
4
|
+
`research/even-realities/`. The repository root `.gitignore` ignores that
|
|
5
|
+
checkout folder, so these upstream repos remain local evidence and are not part
|
|
6
|
+
of the committed package.
|
|
7
|
+
|
|
8
|
+
## Repository Coverage
|
|
9
|
+
|
|
10
|
+
| Requested source | Local checkout | Primary files reviewed | Capability carried into `@elizaos/plugin-facewear` |
|
|
11
|
+
| --- | --- | --- | --- |
|
|
12
|
+
| `fabioglimb/even-toolkit` | `research/even-realities/even-toolkit` | `glasses/bridge.ts`, `glasses/glass-format.ts`, `glasses/paginate-text.ts`, `glasses/gestures.ts`, `stt/sources/glass-bridge.ts`, `stt/audio/pcm-utils.ts` | G2/EvenHub bridge display, event, and PCM audio assumptions; text pagination and gesture normalization informed `src/transport/even-bridge.ts` and `src/protocol/smartglasses.ts`. |
|
|
13
|
+
| `BxNxM/even-dev` | `research/even-realities/even-dev` | `apps/_shared/even-events.ts`, `apps/_shared/autoconnect.ts`, `apps/base_app/src/base-template.ts`, `README.md` | Simulator bridge lifecycle, `sendStartUpPage`, app bridge readiness, and click/double-click input expectations used by `packages/examples/smartglasses/evenhub-smoke.ts` and `simulator-automation-smoke.ts`. |
|
|
14
|
+
| `emingenc/even_glasses` | `research/even-realities/even_glasses` | `even_glasses/models.py`, `even_glasses/utils.py`, `even_glasses/commands.py`, `even_glasses/notification_handlers.py`, `even_glasses/bluetooth_manager.py`, `even_glasses/README.md` | G1 command constants, display packet framing, RSVP, mic control, mic response parsing, LC3 notification parsing, heartbeat, dashboard/settings, BMP, and notification handling in `src/protocol/smartglasses.ts` and `src/services/smartglasses-service.ts`. |
|
|
15
|
+
| `binarythinktank/eveng1_python_sdk` | `research/even-realities/eveng1_python_sdk` | `connector/bluetooth_manager.py`, `services/commands.py`, `services/notification_handlers.py`, `utils/message_utils.py`, `examples/*.py` | Nordic UART UUIDs, broad scan plus `_L_`/`_R_` lens matching, heartbeat bytes, LC3 mic chunks, and display packet shape used by `src/transport/noble.ts`, `src/transport/web-bluetooth.ts`, and protocol tests. |
|
|
16
|
+
| `meyskens/fahrplan` | `research/even-realities/fahrplan` | `lib/bluetooth_manager.dart`, `lib/services/*`, `lib/features/*`, `README.md` | Practical G1 app coverage for dashboard/checklist display, notification mirroring, navigation, translation, QuickNote/voice-note list/fetch/delete/delete-all packets, and live transcription expectations reflected in `src/actions/facewear-control.ts`, `src/protocol/smartglasses.ts`, and package smoke coverage. |
|
|
17
|
+
| `nickustinov/weather-even-g2` | `research/even-realities/weather-even-g2` | `g2/index.ts`, `g2/events.ts`, `g2/ui.tsx`, `_shared/*`, `README.md` | G2 captured-event behavior, list/text/system event handling, and zero-value index edge cases used by EvenHub event normalization. |
|
|
18
|
+
| `jappyjan/even-realities` | `research/even-realities/even-realities` | `packages/*`, `apps/*`, SDK/app examples | EvenHub SDK wrapper patterns for page startup, rebuild, and listener registration used by `EvenBridgeTransport`. |
|
|
19
|
+
| `emingenc/g1_flutter_blue_plus` | `research/even-realities/g1_flutter_blue_plus` | `lib/services/commands.dart`, `lib/services/reciever.dart`, `lib/services/bluetooth_manager.dart`, `lib/main.dart` | Flutter BLE discovery and direct G1 receiver behavior cross-checked command constants, `_L_`/`_R_` pairing, `0xF5` taps, `0x0E` mic responses, and `0xF1` voice data. |
|
|
20
|
+
| `nickustinov/tesla-even-g2` | `research/even-realities/tesla-even-g2` | `g2/events.ts`, `g2/renderer.ts`, `g2/navigation.ts`, `g2/ui.tsx`, `README.md` | G2 bridge event normalization for nested event keys, click/double-click/scroll fallback, and dashboard/menu rendering expectations used by `src/transport/even-bridge.ts` and simulator smoke. |
|
|
21
|
+
| `galfaroth/awesome-even-realities-g1` | `research/even-realities/awesome-even-realities-g1` | `README.md` | Ecosystem cross-check for the G1 SDK/demo sources and command families. |
|
|
22
|
+
| `even-realities/EvenDemoApp` | `research/even-realities/EvenDemoApp` | `lib/ble_manager.dart`, `lib/services/ble.dart`, `lib/services/evenai.dart`, `lib/services/features_services.dart`, `lib/controllers/bmp_update_manager.dart`, `ios/Runner/BluetoothManager.swift`, `android/app/src/main/kotlin/com/example/demo_ai_even/bluetooth/BleManager.kt` | Official demo behavior for right-lens mic, LC3 audio, text streaming, native exit, serial request, app whitelist, iOS same-init (`0x4D 0x01` to both lenses), Android same-init (`0xF4 0x01` to both lenses), notification flows, and BMP transfer. |
|
|
23
|
+
| `Mentra-Community/MentraOS` | `research/even-realities/MentraOS` | `cloud/docs/sdk/display-layouts.mdx`, `cloud/docs/cloud-architecture/managers/audio-manager.mdx`, `cloud/docs/cloud-architecture/managers/microphone-manager.mdx`, `cloud/docs/cloud-architecture/managers/transcription-manager.mdx`, `sdk/*`, `mobile/*` | Bridge/native display APIs, `setMicState`, `mic_pcm`/`mic_lc3`, local transcription streams, display width/glyph constraints, G1 dashboard height/depth position packets, `0x2C 0x01` battery status request/response parsing, and hardware validation requirements used by `src/transport/even-bridge.ts`, display wrapping, transcript events, dashboard position controls, battery status, and hardware smoke evidence. |
|
|
24
|
+
|
|
25
|
+
## Implemented Surface
|
|
26
|
+
|
|
27
|
+
The upstream review maps to the following local implementation:
|
|
28
|
+
|
|
29
|
+
- Direct G1 BLE packet protocol and parsing: `src/protocol/smartglasses.ts`
|
|
30
|
+
- Eliza service lifecycle, display streaming, mic control, tap handling,
|
|
31
|
+
audio/transcript events, heartbeat, and settings: `src/services/smartglasses-service.ts`
|
|
32
|
+
- Eliza actions/providers: `src/actions/*.ts`,
|
|
33
|
+
`src/providers/smartglasses-status.ts`
|
|
34
|
+
- Direct BLE transports: `src/transport/web-bluetooth.ts`, `src/transport/noble.ts`
|
|
35
|
+
- EvenHub/G2/Mentra bridge transport: `src/transport/even-bridge.ts`
|
|
36
|
+
- Mock transport for deterministic Eliza tests: `src/transport/mock.ts`
|
|
37
|
+
- Physical validation harnesses:
|
|
38
|
+
- `packages/examples/smartglasses/hardware-smoke.ts`
|
|
39
|
+
- `packages/examples/smartglasses/noble-hardware-smoke.ts`
|
|
40
|
+
- `packages/examples/smartglasses/hardware-evidence.ts`
|
|
41
|
+
- Simulator validation harness:
|
|
42
|
+
- `packages/examples/smartglasses/evenhub-smoke.ts`
|
|
43
|
+
- `packages/examples/smartglasses/simulator-automation-smoke.ts`
|
|
44
|
+
|
|
45
|
+
## Test Coverage
|
|
46
|
+
|
|
47
|
+
The implementation is covered by:
|
|
48
|
+
|
|
49
|
+
- `src/__tests__/protocol-smartglasses.test.ts`: packet encoding, pixel-aware display
|
|
50
|
+
wrapping, display chunking, mic commands, tap/audio/serial parsing, settings,
|
|
51
|
+
dashboard position/content, navigation, translation, notifications, notes, voice-note
|
|
52
|
+
list/fetch/delete/delete-all, BMP, heartbeat, init modes, and app whitelist/setup.
|
|
53
|
+
- `src/__tests__/facewear-service.test.ts`: Eliza service display streaming, RSVP,
|
|
54
|
+
sequence counters, mic toggle state, side tap behavior, long press/stop
|
|
55
|
+
recording, raw and decoded audio paths, transcript events, startup auto-init,
|
|
56
|
+
heartbeat loop, pre-connected transport listener attachment, and transport
|
|
57
|
+
preference.
|
|
58
|
+
- `src/__tests__/functional-parity.test.ts`: exported action/provider/service wiring.
|
|
59
|
+
- `src/__tests__/even-bridge.test.ts`: G2/EvenHub/Mentra bridge rendering,
|
|
60
|
+
audio, transcription, and input normalization.
|
|
61
|
+
- `src/__tests__/web-bluetooth.test.ts` and `src/__tests__/noble.test.ts`:
|
|
62
|
+
direct BLE lens pairing, UART subscription/write behavior, and notification
|
|
63
|
+
parsing.
|
|
64
|
+
- `packages/examples/smartglasses/smartglasses.test.ts`: package example packet
|
|
65
|
+
path plus physical evidence helper requirements.
|
|
66
|
+
- `packages/examples/smartglasses/package-smoke.ts`: public package export,
|
|
67
|
+
Eliza event emission, status provider, and action path.
|
|
68
|
+
|
|
69
|
+
## Remaining Physical Gate
|
|
70
|
+
|
|
71
|
+
The code includes physical G1 validation paths and direct BLE smoke coverage.
|
|
72
|
+
An earlier report from `2026-05-20T06:38:56Z` reached both lenses on the
|
|
73
|
+
plugged-in headset and proved whole-headset direct BLE connectivity, serial
|
|
74
|
+
response, init/display/settings responses, heartbeats, and right-lens
|
|
75
|
+
mic-disable response for serial `S110LABC040019`. It did not complete the
|
|
76
|
+
physical gate because that run did not observe a physical-state packet with
|
|
77
|
+
`wearing`, so tap and microphone audio evidence could not be observed. The
|
|
78
|
+
freshest short Bleak attempt from `2026-05-20T07:42:31Z` did not discover
|
|
79
|
+
either lens. CoreBluetooth did discover 36 BLE devices, but zero matched
|
|
80
|
+
Even/G1 names and zero advertised the G1 UART service UUID. Both status and
|
|
81
|
+
validator output report
|
|
82
|
+
`physicalBlocker: "headset_not_found"` for that case, which means the next
|
|
83
|
+
Bleak attempt needs both lenses out of the charging base, nearby, advertising,
|
|
84
|
+
and worn before the tap/audio validation window. The Bleak raw report also
|
|
85
|
+
records `status.connected: false`, service UUID/manufacturer scan inventory,
|
|
86
|
+
and the same blocker-aware setup hint when no lenses are found. A Noble attempt from
|
|
87
|
+
`2026-05-20T07:26:42Z` failed before scanning because the native Noble BLE
|
|
88
|
+
binding is unavailable for the current macOS ARM64 Node/Bun ABI; that path now
|
|
89
|
+
writes a report and reports `physicalBlocker: "transport_unavailable"` instead
|
|
90
|
+
of silently leaving an older hardware report in place.
|
|
91
|
+
|
|
92
|
+
Use the root helpers for the next hardware proof attempt:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npm run smartglasses:hardware:prove:watch
|
|
96
|
+
npm run smartglasses:hardware:status
|
|
97
|
+
npm run smartglasses:hardware:validate
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The lower-level package commands remain available when debugging inside the
|
|
101
|
+
example:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
bun run --cwd packages/examples/smartglasses hardware:prove:bleak
|
|
105
|
+
bun run --cwd packages/examples/smartglasses hardware:status-latest
|
|
106
|
+
bun run --cwd packages/examples/smartglasses hardware:validate-latest
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The Noble/Web Bluetooth paths are still available for adapter/browser-specific
|
|
110
|
+
checks:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npm run smartglasses:hardware:prove:noble
|
|
114
|
+
npm run smartglasses:dev:hardware
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The required evidence checklist is enforced by
|
|
118
|
+
`packages/examples/smartglasses/hardware-evidence.ts`: connected lenses,
|
|
119
|
+
connection-ready/init writes, display packets, serial request and response,
|
|
120
|
+
settings writes, `wearing` physical state, single-tap mic enable, right-lens
|
|
121
|
+
mic-enable write, microphone audio, double-tap mic disable, and right-lens
|
|
122
|
+
mic-disable write.
|
|
123
|
+
|
|
124
|
+
The Bleak/CoreBluetooth proof report also captures macOS Bluetooth preflight
|
|
125
|
+
metadata (`bluetoothAdapter` and `pairedG1Devices`) before scanning. That keeps
|
|
126
|
+
the latest JSON artifact self-contained when diagnosing the paired-but-not-
|
|
127
|
+
advertising state that blocks the physical tap/audio gate.
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
# @elizaos/plugin-facewear
|
|
2
|
+
|
|
3
|
+
Even Realities G1/G2 smartglasses integration for ElizaOS.
|
|
4
|
+
|
|
5
|
+
## Implemented Surfaces
|
|
6
|
+
|
|
7
|
+
- View Manager page at `/apps/smartglasses` for whole-headset pairing,
|
|
8
|
+
diagnostics, platform setup guidance, report export, and bridge-backed Wi-Fi
|
|
9
|
+
scan/configuration/setup prompts when a native bridge exposes those APIs.
|
|
10
|
+
The page uses a native Even/Mentra bridge when present for iOS/Android-style
|
|
11
|
+
hosts and falls back to direct Web Bluetooth for desktop browsers.
|
|
12
|
+
- G1 UART protocol constants for Nordic UART service:
|
|
13
|
+
- service `6E400001-B5A3-F393-E0A9-E50E24DCCA9E`
|
|
14
|
+
- TX `6E400002-B5A3-F393-E0A9-E50E24DCCA9E`
|
|
15
|
+
- RX `6E400003-B5A3-F393-E0A9-E50E24DCCA9E`
|
|
16
|
+
- Display text streaming with G1 `0x4E` packets, five-line page wrapping using the hardware-derived G1 glyph width profile, official 191-byte payload chunking, Even AI in-progress/completion status (`0x31`/`0x40`), and direct Text Show status (`0x71`).
|
|
17
|
+
- RSVP word-group display using the same wrapped G1 display path for rapid reading-style presentation.
|
|
18
|
+
- Microphone open/close with G1 `0x0E` packets and right-lens mic routing.
|
|
19
|
+
- Direct G1 `0xF1` mic data is exposed as raw LC3 audio (`audioData`, `audioEncoding: "lc3"`) with packet sequence tracking and gap counts. A native/platform LC3 decoder can be injected with `setAudioDecoder` or `setSmartglassesAudioDecoderForRuntime` to convert those chunks into PCM16 for `onAudio` callbacks. EvenHub/G2 bridge `audioEvent.audioPcm` data and MentraOS `mic_pcm` events are exposed as 16 kHz PCM16 and converted to float samples automatically; MentraOS `mic_lc3` events are preserved as LC3.
|
|
20
|
+
- MentraOS/G2 `local_transcription` and `transcription:*` bridge events are normalized into `SMARTGLASSES_TRANSCRIPT` runtime events and `onTranscript` callbacks, so host STT output from the glasses microphone reaches Eliza.
|
|
21
|
+
- Side tap handling:
|
|
22
|
+
- single tap enables mic
|
|
23
|
+
- double tap disables mic
|
|
24
|
+
- long press / Even AI activation (`0xF5 0x17`) enables mic
|
|
25
|
+
- Even AI recording stop (`0xF5 0x18`) disables mic
|
|
26
|
+
- EvenHub simulator click/double-click events are normalized to the same tap labels, so simulator input exercises the same microphone toggle path.
|
|
27
|
+
- EvenHub/G2 scroll-up and scroll-down events are normalized and routed to the same manual page controls as direct G1 page-up/page-down.
|
|
28
|
+
- Incoming hardware event parsing for interaction, physical, battery, device, init, display-result, notification, dashboard, serial-number response, heartbeat, mic response, mic data, response, and error categories.
|
|
29
|
+
- Runtime events:
|
|
30
|
+
- `SMARTGLASSES_EVENT`
|
|
31
|
+
- `SMARTGLASSES_AUDIO`
|
|
32
|
+
- `SMARTGLASSES_TRANSCRIPT`
|
|
33
|
+
- Managed heartbeat loop for G1 connection maintenance, matching the upstream SDK pattern of periodic `0x25` packets.
|
|
34
|
+
- G1 controls:
|
|
35
|
+
- clear display
|
|
36
|
+
- start AI, connection-ready init (`0x4D 0x01` left / `0xF4 0x01` right by default, official EvenDemoApp iOS same-init `0x4D 0x01` to both lenses, or EvenDemoApp Android `0xF4 0x01` to both lenses), exit to dashboard, native function exit (`0x18`), serial request/response (`0x34`), app whitelist (`0x04`), raw packet writes, one-shot heartbeat, and managed heartbeat start/stop
|
|
37
|
+
- manual-mode page up/down (`0xF5 0x01`, left for page-up and right for page-down)
|
|
38
|
+
- silent mode
|
|
39
|
+
- brightness
|
|
40
|
+
- dashboard show/hide, legacy position, and official height/depth positioning
|
|
41
|
+
- dashboard layout, calendar item, time/weather, and setup payload packets from the Fahrplan G1 dashboard model
|
|
42
|
+
- navigation init, direction text, primary/secondary image, poller, and end packets
|
|
43
|
+
- translation setup/start/language/original/translated text overlay packets
|
|
44
|
+
- head-up angle
|
|
45
|
+
- wear detection
|
|
46
|
+
- notes add/delete
|
|
47
|
+
- QuickNote voice-note list parsing plus voice-note audio fetch/delete subcommands
|
|
48
|
+
- notifications, including notification ID packet headers
|
|
49
|
+
- 1-bit BMP generation/transfer framing with CRC for native `576x136` image payloads
|
|
50
|
+
- Dual-lens writes are serialized left-then-right for commands that target both lenses, matching the native G1 guidance. Microphone activation remains right-lens only.
|
|
51
|
+
- Transports:
|
|
52
|
+
- `EvenBridgeTransport` for EvenHub/G2-style bridge hosts, including simulator-style `sendStartUpPage`, `onEvenHubEvent`, and `audioControl`, plus MentraOS Bluetooth SDK `displayText`, `clearDisplay`, `setMicState`, `mic_pcm`, `mic_lc3`, and local transcription events
|
|
53
|
+
- `WebBluetoothG1Transport` for direct browser BLE
|
|
54
|
+
- `NobleG1Transport` for optional Node/Bun BLE through `@abandonware/noble`
|
|
55
|
+
- `MockSmartglassesTransport` for tests and examples
|
|
56
|
+
|
|
57
|
+
Direct G1 BLE does not expose a verified Wi-Fi provisioning command in the
|
|
58
|
+
reviewed upstreams. Wi-Fi scan/configuration is therefore available only through
|
|
59
|
+
native/bridge APIs such as Mentra/ASG bridge surfaces.
|
|
60
|
+
|
|
61
|
+
## Eliza Actions
|
|
62
|
+
|
|
63
|
+
- `SMARTGLASSES_DISPLAY_TEXT`
|
|
64
|
+
- `SMARTGLASSES_MICROPHONE`
|
|
65
|
+
- `SMARTGLASSES_CONTROL`
|
|
66
|
+
- `SMARTGLASSES_STATUS`
|
|
67
|
+
|
|
68
|
+
`SMARTGLASSES_DISPLAY_TEXT` accepts plain text or JSON:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{ "text": "Show this on the glasses", "mode": "text" }
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Use `mode: "ai"` for the default Even AI streaming/completion display path or
|
|
75
|
+
`mode: "text"` for the direct Text Show path documented by EvenDemoApp. JSON
|
|
76
|
+
input can also include `pageHoldMs` between pages and `completionDelayMs`
|
|
77
|
+
before sending the final completion frame:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{ "text": "Paced multi-page display", "mode": "ai", "pageHoldMs": 1200, "completionDelayMs": 250 }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`SMARTGLASSES_CONTROL` accepts JSON such as:
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{ "op": "brightness", "level": 10, "auto": true }
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Supported `op` values: `connect`, `disconnect`, `clear`, `exit_dashboard`, `exit_function`, `start_ai`, `connection_ready`, `page_up`, `page_down`, `rsvp_text`, `heartbeat`, `heartbeat_start`, `heartbeat_stop`, `battery_status`, `raw`, `get_serial`, `app_whitelist`, `g1_setup`, `silent_mode`, `brightness`, `wifi_scan`, `wifi_status`, `wifi_configure`, `wifi_setup`, `dashboard`, `dashboard_position`, `dashboard_layout`, `dashboard_calendar`, `dashboard_time_weather`, `headup_angle`, `wear_detection`, `navigation_start`, `navigation_directions`, `navigation_primary_image`, `navigation_secondary_image`, `navigation_poller`, `navigation_end`, `translate_setup`, `translate_start`, `translate_languages`, `translate_original`, `translate_translated`, `note_add`, `note_delete`, `voice_note_list`, `voice_note_fetch`, `voice_note_delete`, `voice_note_delete_all`, `notification`, `bmp_image`.
|
|
90
|
+
|
|
91
|
+
`connect` pairs or reconnects the whole headset through the configured
|
|
92
|
+
transport and sends connection-ready init packets by default. Aliases include
|
|
93
|
+
`pair`, `pair_headset`, and `connect_headset`. Pass `init: false` to reconnect
|
|
94
|
+
without sending init packets:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{ "op": "connect", "init": false }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`disconnect` closes the active headset transport. Aliases include `unpair` and
|
|
101
|
+
`disconnect_headset`.
|
|
102
|
+
|
|
103
|
+
Bridge-backed Wi-Fi actions are available only when the active transport
|
|
104
|
+
exposes native phone/headset setup APIs:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{ "op": "wifi_scan" }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{ "op": "wifi_configure", "ssid": "Home Wi-Fi", "password": "secret" }
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Mentra-style SDK hosts can expose a native setup prompt instead of direct
|
|
115
|
+
credential APIs:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{ "op": "wifi_setup", "reason": "Eliza needs headset Wi-Fi" }
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`heartbeat_start` accepts optional `intervalMs` and `immediate` fields. By
|
|
122
|
+
default it sends a heartbeat immediately and then every 8 seconds until
|
|
123
|
+
`heartbeat_stop`, service disconnect, or service stop.
|
|
124
|
+
|
|
125
|
+
`rsvp_text` accepts `text`, optional `wordsPerGroup`, `wpm`, `paddingChar`,
|
|
126
|
+
`mode`, and `skipDelay`. It mirrors the RSVP display pattern from the Python
|
|
127
|
+
examples while still using the plugin's normal display packet encoder:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{ "op": "rsvp_text", "text": "Rapid serial visual presentation", "wordsPerGroup": 2, "wpm": 250 }
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
`raw` accepts `data`, `bytes`, `hex`, or `base64` plus optional `side`/`target`
|
|
134
|
+
(`left`, `right`, or `both`). This keeps low-level SDK commands such as native
|
|
135
|
+
connection-ready packets reachable while `connection_ready` covers the common
|
|
136
|
+
left/right initialization pair directly. Pass `initMode: "official"` to send
|
|
137
|
+
the EvenDemoApp iOS same-init form (`0x4D 0x01`) to both lenses, or
|
|
138
|
+
`initMode: "android-f4"` to send the EvenDemoApp Android form (`0xF4 0x01`) to
|
|
139
|
+
both lenses:
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{ "op": "connection_ready", "initMode": "official" }
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`bmp_image` accepts prebuilt BMP bytes through `hex`, `base64`, or `data`.
|
|
146
|
+
It can also generate a native 1-bit BMP from grayscale pixels:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{ "op": "bmp_image", "pixels": [0, 255, 255, 0], "width": 2, "height": 2 }
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Dashboard/navigation/translation operations expose the packet families used by
|
|
153
|
+
Fahrplan in addition to plain text display:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{ "op": "dashboard_position", "height": 3, "depth": 7 }
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
{ "op": "dashboard_calendar", "name": "Standup", "time": "13:30-14:30", "location": "Lab" }
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
{ "op": "navigation_directions", "totalDuration": "4 min", "totalDistance": "1 km", "direction": "Main St", "distance": "200 m", "speed": "30", "directionTurn": 3 }
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Navigation image operations accept `image` as an array, hex, or base64 bit
|
|
168
|
+
plane. `overlay` uses the same formats and defaults to an all-zero overlay when
|
|
169
|
+
omitted, which keeps secondary navigation image action payloads compact enough
|
|
170
|
+
for Eliza JSON extraction:
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{ "op": "navigation_secondary_image", "image": "<base64 bit plane>" }
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
{ "op": "translate_translated", "text": "bonjour", "syncId": 3 }
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Configuration
|
|
181
|
+
|
|
182
|
+
- `SMARTGLASSES_TRANSPORT`: `auto` (default), `even-bridge`, `web-bluetooth`, or `noble`.
|
|
183
|
+
- `SMARTGLASSES_SCAN_TIMEOUT_MS`: optional Noble BLE scan timeout in milliseconds.
|
|
184
|
+
- `SMARTGLASSES_AUTO_INIT`: send left/right initialization packets after Eliza-managed startup. Defaults to `true`.
|
|
185
|
+
- `SMARTGLASSES_INIT_MODE`: `lens-specific` (default) sends `0x4D 0x01` to the left lens and `0xF4 0x01` to the right lens; `official` sends `0x4D 0x01` to both lenses as in EvenDemoApp iOS; `android-f4` sends `0xF4 0x01` to both lenses as in EvenDemoApp Android.
|
|
186
|
+
|
|
187
|
+
## Microphone Audio
|
|
188
|
+
|
|
189
|
+
EvenHub/G2 bridge hosts and the EvenHub simulator deliver `audioEvent.audioPcm`
|
|
190
|
+
as signed 16 kHz PCM16, which the service converts to `Float32Array` samples for
|
|
191
|
+
`onAudio`. MentraOS Bluetooth SDK bridge hosts can also deliver `mic_pcm` events
|
|
192
|
+
with signed 16 kHz PCM16, or `mic_lc3` events that flow through the same LC3
|
|
193
|
+
decoder hook as direct G1 packets.
|
|
194
|
+
|
|
195
|
+
Direct G1 hardware sends `0xF1` packets containing LC3 frames. The upstream
|
|
196
|
+
Android/iOS examples decode those frames with platform-native LC3 code, so this
|
|
197
|
+
package preserves raw LC3 by default and exposes a decoder hook for host apps
|
|
198
|
+
that have a native or WASM LC3 decoder:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
service.setAudioDecoder(async (audio, context) => {
|
|
202
|
+
if (context.encoding !== "lc3") return null;
|
|
203
|
+
return decodeLc3ToPcm16(audio);
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
For plugin-managed startup, register the same hook before the service starts:
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
setSmartglassesAudioDecoderForRuntime(decodeLc3ToPcm16);
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Upstream Evidence
|
|
214
|
+
|
|
215
|
+
The implementation was derived from the ignored research checkouts in
|
|
216
|
+
`research/even-realities/`. The reviewed sources and resulting implementation
|
|
217
|
+
choices are:
|
|
218
|
+
|
|
219
|
+
See `docs/smartglasses-upstream-audit.md` for the full
|
|
220
|
+
source-to-implementation audit with local file references and test coverage.
|
|
221
|
+
|
|
222
|
+
| Source | Relevant findings applied here |
|
|
223
|
+
| --- | --- |
|
|
224
|
+
| `fabioglimb/even-toolkit` | EvenHub/G2 bridge audio uses `rawBridge.audioControl` or `callEvenApp("audioControl", { isOpen })`; PCM arrives as `event.audioEvent.audioPcm` at 16 kHz. |
|
|
225
|
+
| `BxNxM/even-dev` | Simulator apps use `waitForEvenAppBridge`, `onEvenHubEvent`, `sendStartUpPage`, `createStartUpPageContainer`, `rebuildPageContainer`, click/double-click event codes, and the `@evenrealities/evenhub-simulator` automation/audio model. |
|
|
226
|
+
| `emingenc/even_glasses` | G1 command models for `0x4E` display, RSVP word-group display, `0x0E` mic control, `0x25` heartbeat, settings, notes, notifications, BMP transfer, and incoming notification handlers for init/display/notification events; BLE discovery identifies lenses by `_L_` and `_R_`. |
|
|
227
|
+
| `binarythinktank/eveng1_python_sdk` | Nordic UART UUIDs, heartbeat packet `[0x25, 0x06, 0x00, seq, 0x04, seq]`, managed heartbeat loop for connection health, display packet header shape, mic response semantics, LC3 mic chunks, and broad BLE scan followed by left/right name matching. |
|
|
228
|
+
| `meyskens/fahrplan` | Confirms practical G1 app surfaces: notification mirroring, dashboard/checklist style display, dashboard calendar/time-weather/setup packet families, navigation mode packets, translation overlay packets, QuickNote/voice-note `0x21` metadata, `0x1E` voice-note audio fetch/delete subcommands, and live transcription using the glasses microphone; Linux BLE caveats informed the explicit hardware smoke paths. |
|
|
229
|
+
| `nickustinov/weather-even-g2` | G2 app event handling treats captured `listEvent`, `textEvent`, and `sysEvent` payloads as click/scroll sources and handles missing zero-value list indices from protobuf. |
|
|
230
|
+
| `jappyjan/even-realities` | EvenHub SDK wrapper patterns for startup/rebuild page containers and event listener registration. |
|
|
231
|
+
| `emingenc/g1_flutter_blue_plus` | Flutter BLE connection flow scans broadly, matches `_L_`/`_R_`, then discovers the Nordic UART service and TX/RX characteristics. |
|
|
232
|
+
| `nickustinov/tesla-even-g2` | G2 bridge event normalization for nested `eventType`, `event_type`, `Event_Type`, click/double-click/scroll codes, and captured-event fallback to click. |
|
|
233
|
+
| `galfaroth/awesome-even-realities-g1` | Cross-check index for the G1 ecosystem and the Python wrapper sources used above. |
|
|
234
|
+
| `even-realities/EvenDemoApp` | Official demo evidence for mic on the right lens, `0xF1` LC3 mic packet shape, text streaming, notification flows, native function exit, serial request, app whitelist packetization, connection-ready same-init packets (`0x4D 0x01` to both lenses), and BMP data/end/CRC framing. |
|
|
235
|
+
| `MentraOS/MentraOS` | Confirmed official-style dashboard height/depth position packets (`0x26 0x08 0x00 seq 0x02 0x01 height depth`) and G1 battery status requests/responses. |
|
|
236
|
+
| `Mentra-Community/MentraOS` | Architecture context for smartglasses apps as BLE-to-phone/cloud pipelines, native bridge display APIs (`displayText`, `clearDisplay`), `setMicState`, `mic_pcm`/`mic_lc3` event streams, `local_transcription`/`transcription:*` events, G1 glyph-width display profile for pixel-aware wrapping, display bandwidth limits, and hardware-dependent verification requirements. |
|
|
237
|
+
|
|
238
|
+
The implementation intentionally separates direct G1 BLE transports from the EvenHub/G2 bridge transport because the upstream projects expose those as different runtime surfaces.
|
|
239
|
+
|
|
240
|
+
## Verification
|
|
241
|
+
|
|
242
|
+
For the full software proof from the repository root:
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
npm run verify:smartglasses-software
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
That command runs the Facewear plugin lint/typecheck/test/app-registration
|
|
249
|
+
gates, then the example software gate, repairs Facewear lockfile churn, and
|
|
250
|
+
reruns the consolidation, Even research self-test, Even research audit, and
|
|
251
|
+
completion self-test guards.
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
bun run --cwd plugins/plugin-facewear lint
|
|
255
|
+
bun run --cwd plugins/plugin-facewear typecheck
|
|
256
|
+
bun run --cwd plugins/plugin-facewear test
|
|
257
|
+
bun run --cwd plugins/plugin-facewear build
|
|
258
|
+
bun run --cwd packages/examples/smartglasses test
|
|
259
|
+
bun run --cwd packages/examples/smartglasses start
|
|
260
|
+
bun run --cwd packages/examples/smartglasses smoke:package
|
|
261
|
+
bun run --cwd packages/examples/smartglasses smoke:simulator
|
|
262
|
+
bun run --cwd packages/examples/smartglasses typecheck
|
|
263
|
+
bun run --cwd packages/examples/smartglasses verify:software
|
|
264
|
+
bun run --cwd packages/examples/smartglasses hardware:status-latest
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Hardware Smoke
|
|
268
|
+
|
|
269
|
+
The browser hardware smoke example exercises the direct G1 BLE path:
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
npm run smartglasses:dev:hardware
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
bun run --cwd packages/examples/smartglasses dev:hardware
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Open `http://127.0.0.1:5178/hardware-smoke.html` in a Web Bluetooth-capable
|
|
280
|
+
browser. Use **Connect Headset** for the two-step whole-headset flow; the same
|
|
281
|
+
button prompts for the left lens and then the right lens because browsers
|
|
282
|
+
require a user gesture for each Bluetooth picker. The page sends
|
|
283
|
+
connection-ready/init, serial request, display, mic, brightness, dashboard,
|
|
284
|
+
head-up angle, and wear-detection commands, then logs a structured evidence
|
|
285
|
+
checklist for single-tap mic enable, double-tap mic disable, LC3 audio
|
|
286
|
+
notifications, serial responses, packet writes, and final service status.
|
|
287
|
+
|
|
288
|
+
The View Manager page at `/apps/smartglasses` exposes the same setup and
|
|
289
|
+
diagnostic intent inside Eliza. Its copied/downloaded report includes
|
|
290
|
+
whole-headset `scanDiagnosis`, `physicalBlocker`, setup hint, next action,
|
|
291
|
+
observed serial number, outbound G1 write evidence, and microphone audio
|
|
292
|
+
metadata including sample rate, encoding, sequence when available, side, and
|
|
293
|
+
byte count. The View Manager checklist treats serial request and observed
|
|
294
|
+
serial response as separate evidence so a request packet alone does not satisfy
|
|
295
|
+
the serial proof.
|
|
296
|
+
|
|
297
|
+
The EvenHub simulator can exercise the G2 bridge surface without physical hardware:
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
npm run smartglasses:dev:simulator
|
|
301
|
+
npm run smartglasses:simulator
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
bun run --cwd packages/examples/smartglasses dev:simulator
|
|
306
|
+
bun run --cwd packages/examples/smartglasses simulator
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
An automated simulator smoke harness is also available:
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
npm run smartglasses:smoke:simulator
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
bun run --cwd packages/examples/smartglasses smoke:simulator
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
The simulator currently publishes 16 kHz signed PCM audio events through the EvenHub bridge. It is useful for bridge display, input, audio-control, and automation checks, but it is not a replacement for physical G1/G2 validation.
|
|
320
|
+
|
|
321
|
+
To exercise simulator microphone delivery, pass an EvenHub simulator audio
|
|
322
|
+
input ID. The automated smoke will forward it as `--aid`, click to enable the
|
|
323
|
+
bridge microphone, and wait for an `audioEvent.audioPcm` event:
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
SMARTGLASSES_SIMULATOR_AUDIO_DEVICE="coreaudio:BuiltInMicrophoneDevice" bun run --cwd packages/examples/smartglasses smoke:simulator
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
The Node/Bun hardware smoke exercises the Noble transport:
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
bun run --cwd packages/examples/smartglasses hardware:noble
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
It scans for left/right lenses, connects to the UART service, sends
|
|
336
|
+
connection-ready/init, serial request, display, and settings packets, disables
|
|
337
|
+
the right microphone, waits for a `wearing` physical state, then requires a
|
|
338
|
+
single tap to enable microphone capture, speech audio, and a double tap to
|
|
339
|
+
disable capture during the smoke window. The glasses must be out of the
|
|
340
|
+
charging cradle and worn for tap and microphone evidence.
|
|
341
|
+
`SMARTGLASSES_SCAN_TIMEOUT_MS`, `SMARTGLASSES_HOLD_MS`,
|
|
342
|
+
`SMARTGLASSES_WEARING_TIMEOUT_MS=30000`,
|
|
343
|
+
`SMARTGLASSES_INIT_MODE=official|lens-specific|android-f4`, and
|
|
344
|
+
`SMARTGLASSES_DIRECT_MIC_MS=15000` can tune scan, microphone wait time, wearing
|
|
345
|
+
wait, init variant, and direct mic diagnostics. Set
|
|
346
|
+
`SMARTGLASSES_REPORT_PATH=./smartglasses-hardware-report.json` to write a
|
|
347
|
+
structured evidence artifact covering packet writes, serial state, headset
|
|
348
|
+
physical/battery/device state, side-tap mic state, audio chunks, and final
|
|
349
|
+
service status.
|
|
350
|
+
|
|
351
|
+
For the final auditable hardware proof run, use the bundled latest-report
|
|
352
|
+
helpers. They write `/tmp/smartglasses-hardware-report-latest.json`, print a
|
|
353
|
+
setup/status summary even when the smoke fails, and then run the strict
|
|
354
|
+
validator:
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
npm run smartglasses:hardware:prove
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
bun run --cwd packages/examples/smartglasses hardware:prove:bleak
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
npm run smartglasses:hardware:prove:noble
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
bun run --cwd packages/examples/smartglasses hardware:prove:noble
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
If the short proof run connects both lenses but never observes worn state, run
|
|
373
|
+
the watch proof wrapper. It waits longer while preserving the same
|
|
374
|
+
latest-report, status, and freshness-validation flow:
|
|
375
|
+
|
|
376
|
+
If the status summary reports `physicalBlocker: "headset_not_found"`, the scan
|
|
377
|
+
did not discover either lens. Remove both lenses from the charging base, keep
|
|
378
|
+
them near this device, and rerun the watch proof. Failed Bleak reports include
|
|
379
|
+
`discoveredDevices`, `discoveredDeviceCount`, and `discoveredG1DeviceCount` to
|
|
380
|
+
show whether CoreBluetooth saw nearby BLE devices but no Even/G1 lenses.
|
|
381
|
+
If Noble reports `physicalBlocker: "transport_unavailable"` on macOS, the
|
|
382
|
+
native Noble binding is not usable for this runtime; use the Bleak/CoreBluetooth
|
|
383
|
+
proof or rebuild `@abandonware/noble` for the current Node/Bun ABI.
|
|
384
|
+
|
|
385
|
+
```bash
|
|
386
|
+
npm run smartglasses:hardware:prove:watch
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
```bash
|
|
390
|
+
bun run --cwd packages/examples/smartglasses hardware:prove:bleak:watch
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
```bash
|
|
394
|
+
npm run smartglasses:hardware:prove:noble:watch
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
```bash
|
|
398
|
+
bun run --cwd packages/examples/smartglasses hardware:prove:noble:watch
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
Inspect and validate that latest artifact independently before treating
|
|
402
|
+
physical hardware support as proven. The latest validator requires the `/tmp`
|
|
403
|
+
report to be fresh within ten minutes; use `hardware:validate-report <path>`
|
|
404
|
+
for historical artifacts:
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
npm run smartglasses:hardware:status
|
|
408
|
+
npm run smartglasses:hardware:validate
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
bun run --cwd packages/examples/smartglasses hardware:status-latest
|
|
413
|
+
bun run --cwd packages/examples/smartglasses hardware:validate-latest
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
A passing report must show real lens connection, connection-ready/init writes,
|
|
417
|
+
display packet writes, serial request and observed serial response, settings
|
|
418
|
+
writes, observed tap events, single-tap microphone enable, double-tap
|
|
419
|
+
microphone disable, non-empty microphone audio, and final connected service
|
|
420
|
+
status with serial and audio counters. Simulator and mock tests are useful
|
|
421
|
+
regression coverage, but they do not satisfy this physical hardware gate. The
|
|
422
|
+
validator reports `headsetInCradle` and `wearingStateNotObserved` separately
|
|
423
|
+
when the setup state explains missing tap or microphone evidence.
|
|
424
|
+
|
|
425
|
+
To validate a custom report path instead of the latest helper output:
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
bun run --cwd packages/examples/smartglasses hardware:validate-report ./smartglasses-hardware-report.json
|
|
429
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elizaos/plugin-facewear",
|
|
3
|
+
"version": "2.0.3-beta.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Unified facewear plugin — Meta Quest 3, XReal, Even Realities G1/G2, Apple Vision Pro. Bidirectional voice+camera streaming, smartglasses display, view panels, device management.",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./package.json": "./package.json",
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"eliza-source": {
|
|
12
|
+
"types": "./src/index.ts",
|
|
13
|
+
"import": "./src/index.ts",
|
|
14
|
+
"default": "./src/index.ts"
|
|
15
|
+
},
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./register": {
|
|
20
|
+
"types": "./dist/register.d.ts",
|
|
21
|
+
"import": "./dist/register.js",
|
|
22
|
+
"default": "./dist/register.js"
|
|
23
|
+
},
|
|
24
|
+
"./*": {
|
|
25
|
+
"types": "./dist/*.d.ts",
|
|
26
|
+
"eliza-source": {
|
|
27
|
+
"types": "./src/*.ts",
|
|
28
|
+
"import": "./src/*.ts",
|
|
29
|
+
"default": "./src/*.ts"
|
|
30
|
+
},
|
|
31
|
+
"import": "./dist/*.js",
|
|
32
|
+
"default": "./dist/*.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"typecheck": "bunx tsc --noEmit -p tsconfig.json",
|
|
37
|
+
"lint": "bunx @biomejs/biome check src",
|
|
38
|
+
"test": "bun run build:views && bun run emulator:build && NODE_OPTIONS='--experimental-sqlite' vitest run --config ./vitest.config.ts",
|
|
39
|
+
"build": "bun run build:js && bun run build:views && bun run build:types",
|
|
40
|
+
"build:js": "tsup --config ../tsup.plugin-packages.shared.ts",
|
|
41
|
+
"build:types": "bunx tsc --noCheck -p tsconfig.build.json",
|
|
42
|
+
"build:views": "bunx --bun vite build --config vite.config.views.ts",
|
|
43
|
+
"emulator:build": "cd emulator && bun install --force && bun run build",
|
|
44
|
+
"emulator:watch": "cd emulator && bun run build:watch",
|
|
45
|
+
"emulator:cli": "bun run --cwd emulator src/cli.ts",
|
|
46
|
+
"verify:app": "bunx vitest --root ../.. run packages/app-core/src/registry/facewear-registry.test.ts packages/app/src/plugin-registrations.test.ts"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@elizaos/agent": "2.0.3-beta.2",
|
|
50
|
+
"@elizaos/core": "2.0.3-beta.2",
|
|
51
|
+
"@elizaos/ui": "2.0.3-beta.2",
|
|
52
|
+
"lucide-react": "^1.0.0",
|
|
53
|
+
"ws": "^8.18.0",
|
|
54
|
+
"zod": "^4.4.3"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"react": "^19.0.0",
|
|
58
|
+
"react-dom": "^19.0.0"
|
|
59
|
+
},
|
|
60
|
+
"optionalDependencies": {
|
|
61
|
+
"@abandonware/noble": "^1.9.2-25"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@biomejs/biome": "^2.4.14",
|
|
65
|
+
"@types/node": "^25.0.3",
|
|
66
|
+
"@types/react": "^19.2.3",
|
|
67
|
+
"@types/react-dom": "^19.2.3",
|
|
68
|
+
"@types/ws": "^8.5.10",
|
|
69
|
+
"bun-types": "^1.3.14",
|
|
70
|
+
"react": "^19.0.0",
|
|
71
|
+
"react-dom": "^19.0.0",
|
|
72
|
+
"tsup": "^8.5.1",
|
|
73
|
+
"typescript": "^6.0.3",
|
|
74
|
+
"vite": "8.0.16",
|
|
75
|
+
"vitest": "^4.0.17"
|
|
76
|
+
},
|
|
77
|
+
"elizaos": {
|
|
78
|
+
"plugin": {
|
|
79
|
+
"displayName": "Facewear",
|
|
80
|
+
"category": "hardware"
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"agentConfig": {
|
|
84
|
+
"pluginType": "elizaos:plugin:1.0.0",
|
|
85
|
+
"pluginParameters": {
|
|
86
|
+
"FACEWEAR_WS_PORT": {
|
|
87
|
+
"type": "number",
|
|
88
|
+
"description": "WebSocket port for XR streaming (Quest 3, XReal, Vision Pro).",
|
|
89
|
+
"required": false,
|
|
90
|
+
"default": 31338
|
|
91
|
+
},
|
|
92
|
+
"FACEWEAR_SMARTGLASSES_TRANSPORT": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"description": "Even Realities transport selection.",
|
|
95
|
+
"required": false,
|
|
96
|
+
"default": "auto",
|
|
97
|
+
"enum": [
|
|
98
|
+
"auto",
|
|
99
|
+
"even-bridge",
|
|
100
|
+
"web-bluetooth",
|
|
101
|
+
"noble"
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
"FACEWEAR_SCAN_TIMEOUT_MS": {
|
|
105
|
+
"type": "number",
|
|
106
|
+
"description": "BLE scan timeout (ms) for Noble transport.",
|
|
107
|
+
"required": false,
|
|
108
|
+
"default": 10000
|
|
109
|
+
},
|
|
110
|
+
"FACEWEAR_AUTO_INIT": {
|
|
111
|
+
"type": "boolean",
|
|
112
|
+
"description": "Send G1 connection-ready init packets automatically.",
|
|
113
|
+
"required": false,
|
|
114
|
+
"default": true
|
|
115
|
+
},
|
|
116
|
+
"FACEWEAR_INIT_MODE": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"description": "G1 connection-ready init mode.",
|
|
119
|
+
"required": false,
|
|
120
|
+
"default": "lens-specific",
|
|
121
|
+
"enum": [
|
|
122
|
+
"lens-specific",
|
|
123
|
+
"official",
|
|
124
|
+
"android-f4"
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"publishConfig": {
|
|
130
|
+
"access": "public"
|
|
131
|
+
},
|
|
132
|
+
"types": "./dist/index.d.ts",
|
|
133
|
+
"files": [
|
|
134
|
+
"assets",
|
|
135
|
+
"dist",
|
|
136
|
+
"docs"
|
|
137
|
+
],
|
|
138
|
+
"gitHead": "82fe0f44215954c2417328203f5bd6510985c1fc"
|
|
139
|
+
}
|