elizaos--eliza
426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
181 行
12 KiB
Markdown
181 行
12 KiB
Markdown
# @elizaos/capacitor-gateway
|
|
|
|
Capacitor plugin that connects an elizaOS app to an Eliza Gateway server with discovery, WebSocket RPC, and realtime event streaming — across web, iOS, and Android.
|
|
|
|
## Purpose / role
|
|
|
|
This is a [Capacitor](https://capacitorjs.com/) plugin, not an elizaOS runtime plugin. It ships a cross-platform JavaScript API backed by platform-specific implementations (Swift on iOS, Kotlin on Android, browser WebSocket on web). It is registered as a Capacitor plugin named `"Gateway"` and consumed by the app layer to establish authenticated WebSocket sessions to a running Eliza Gateway.
|
|
|
|
This package is **not** loaded by the elizaOS `AgentRuntime`. It is a client-side networking primitive for the UI layer.
|
|
|
|
## Plugin surface
|
|
|
|
The `Gateway` object (exported from `src/index.ts`) is the single entry point. It implements `GatewayPlugin` (defined in `src/definitions.ts`):
|
|
|
|
| Method | Description |
|
|
|---|---|
|
|
| `startDiscovery(options?)` | Start Bonjour/mDNS discovery for gateways on the local network (LAN + optional wide-area DNS-SD). Not available on web. |
|
|
| `stopDiscovery()` | Stop active discovery. |
|
|
| `getDiscoveredGateways()` | Return the current snapshot of discovered `GatewayEndpoint[]`. |
|
|
| `connect(options)` | Open an authenticated WebSocket to a gateway URL; negotiates protocol v3; returns session ID, role, scopes, and available methods/events. |
|
|
| `disconnect()` | Close the active WebSocket; cancels reconnect timer. |
|
|
| `isConnected()` | Returns `{ connected: boolean }`. |
|
|
| `send(options)` | Send an RPC request (`method` + `params`); returns `GatewaySendResult` with `ok`, `payload`, or `error`. |
|
|
| `getConnectionInfo()` | Returns current `url`, `sessionId`, `protocol`, `role`. |
|
|
| `addListener("gatewayEvent", fn)` | Receive server-pushed events (`GatewayEvent`: `event`, `payload`, `seq`). |
|
|
| `addListener("stateChange", fn)` | Connection lifecycle: `connecting` / `connected` / `disconnected` / `reconnecting`. |
|
|
| `addListener("error", fn)` | Receive `GatewayErrorEvent` (`message`, `code`, `willRetry`). |
|
|
| `addListener("discovery", fn)` | Receive `GatewayDiscoveryEvent` (`found` / `lost` / `updated` + `GatewayEndpoint`). |
|
|
| `removeAllListeners()` | Remove all event listeners. |
|
|
|
|
## Layout
|
|
|
|
```
|
|
plugins/plugin-native-gateway/
|
|
src/
|
|
index.ts Capacitor registerPlugin call; exports Gateway singleton + all types
|
|
definitions.ts All TypeScript interfaces: GatewayPlugin, GatewayEndpoint, events, DTOs
|
|
web.ts Browser WebSocket implementation (GatewayWeb extends WebPlugin)
|
|
ios/
|
|
Sources/GatewayPlugin/
|
|
GatewayPlugin.swift Swift implementation using URLSessionWebSocketTask + NWBrowser
|
|
android/
|
|
src/main/java/ai/eliza/plugins/gateway/
|
|
GatewayPlugin.kt Kotlin implementation using OkHttp WebSocket + NsdManager
|
|
ElizaosCapacitorGateway.podspec CocoaPods spec (pod name: ElizaosCapacitorGateway)
|
|
rollup.config.mjs Bundler config producing CJS + ESM dist
|
|
tsconfig.json
|
|
```
|
|
|
|
## Commands
|
|
|
|
Scripts are defined in `package.json`; run them from the repo root with `bun run --cwd`:
|
|
|
|
```bash
|
|
bun run --cwd plugins/plugin-native-gateway clean # remove build output
|
|
bun run --cwd plugins/plugin-native-gateway build # build package artifacts
|
|
bun run --cwd plugins/plugin-native-gateway build:docs # generate docs and build artifacts
|
|
bun run --cwd plugins/plugin-native-gateway typecheck # TypeScript typecheck
|
|
bun run --cwd plugins/plugin-native-gateway lint # mutating Biome check plus native lint tail
|
|
bun run --cwd plugins/plugin-native-gateway lint:check # read-only Biome check plus native lint tail
|
|
bun run --cwd plugins/plugin-native-gateway format # write formatting
|
|
bun run --cwd plugins/plugin-native-gateway format:check # read-only formatting check
|
|
bun run --cwd plugins/plugin-native-gateway test # run package tests
|
|
bun run --cwd plugins/plugin-native-gateway prepublishOnly # publish-time build hook
|
|
bun run --cwd plugins/plugin-native-gateway watch # watch TypeScript sources
|
|
bun run --cwd plugins/plugin-native-gateway build:unlocked # bun run clean && tsc && bunx rollup -c rollup.config.mjs
|
|
bun run --cwd plugins/plugin-native-gateway docgen # docgen --api GatewayPlugin --output-readme README.md --output-json dist/docs.json
|
|
bun run --cwd plugins/plugin-native-gateway fmt # bunx @biomejs/biome check --write --unsafe . && bash -c 'if command -v swiftlint >/dev/null 2>&1; then bun run swiftlint -- lint --fix; fi'
|
|
bun run --cwd plugins/plugin-native-gateway swiftlint # node-swiftlint
|
|
bun run --cwd plugins/plugin-native-gateway verify # bun run verify:ios && bun run verify:android && bun run verify:web
|
|
bun run --cwd plugins/plugin-native-gateway verify:android # cd android && ./gradlew clean build test && cd ..
|
|
bun run --cwd plugins/plugin-native-gateway verify:ios # cd ios && pod install && xcodebuild -workspace Plugin.xcworkspace -scheme Plugin -destination generic/platform=iOS && cd ..
|
|
bun run --cwd plugins/plugin-native-gateway verify:web # bun run build
|
|
```
|
|
|
|
## Config / env vars
|
|
|
|
This plugin reads **no env vars** and has **no elizaOS config schema**. All configuration is passed at runtime through the `GatewayConnectOptions` argument to `Gateway.connect()`:
|
|
|
|
| Field | Type | Required | Description |
|
|
|---|---|---|---|
|
|
| `url` | `string` | Yes | WebSocket URL of the gateway (e.g. `wss://host:8080`) |
|
|
| `token` | `string` | No | JWT or bearer token for auth |
|
|
| `password` | `string` | No | Password-based auth alternative to token |
|
|
| `clientName` | `string` | No | Sent in connect frame; defaults to `"eliza-capacitor"` |
|
|
| `clientVersion` | `string` | No | Defaults to `"1.0.0"` |
|
|
| `sessionKey` | `string` | No | Optional session key for chat sessions |
|
|
| `role` | `string` | No | Role to request; defaults to `"operator"` |
|
|
| `scopes` | `string[]` | No | Defaults to `["operator.admin"]` |
|
|
|
|
Discovery options via `GatewayDiscoveryOptions`:
|
|
|
|
| Field | Type | Description |
|
|
|---|---|---|
|
|
| `wideAreaDomain` | `string` | Optional DNS-SD domain for wide-area discovery (e.g. a Tailscale domain) |
|
|
| `timeout` | `number` | Discovery timeout in ms; default 10000 |
|
|
|
|
## Protocol
|
|
|
|
The gateway protocol uses JSON frames over WebSocket. Three frame types:
|
|
|
|
- `req` — client request: `{ type: "req", id: UUID, method: string, params: object }`
|
|
- `res` — server response: `{ type: "res", id: UUID, ok: boolean, payload?, error? }`
|
|
- `event` — server push: `{ type: "event", event: string, payload?, seq?: number }`
|
|
|
|
Connection is established by sending a `connect` method frame with protocol range `minProtocol: 3, maxProtocol: 3`. Reconnection uses exponential backoff starting at 800 ms, capped at 15 s (web, iOS, and Android). Request timeout is 60 s for `send()`.
|
|
|
|
mDNS service type: `_eliza-gw._tcp` (local.) on iOS/Android; `_eliza-gw._tcp.` on Android NsdManager.
|
|
|
|
## How to extend
|
|
|
|
**Add a typed helper around `send()`** (preferred pattern — do not modify this package):
|
|
- Import `Gateway` from `@elizaos/capacitor-gateway` in your app code.
|
|
- Call `Gateway.send({ method: "your.method", params: { ... } })` and type the result.
|
|
|
|
**Add a new method to the plugin interface:**
|
|
1. Add the signature to `GatewayPlugin` in `src/definitions.ts`.
|
|
2. Implement it in `src/web.ts` (`GatewayWeb` class).
|
|
3. Implement it in `ios/Sources/GatewayPlugin/GatewayPlugin.swift` with `@objc func <name>(_ call: CAPPluginCall)` and register in `pluginMethods`.
|
|
4. Implement it in `android/src/main/java/ai/eliza/plugins/gateway/GatewayPlugin.kt` with `@PluginMethod`.
|
|
5. Run `bun run --cwd plugins/plugin-native-gateway build:docs` to regenerate README.
|
|
|
|
**Add a new event type:**
|
|
1. Add the interface to `src/definitions.ts`.
|
|
2. Add the `addListener` overload to `GatewayPlugin`.
|
|
3. Emit via `this.notifyListeners(eventName, payload)` in all three implementations.
|
|
|
|
## Conventions / gotchas
|
|
|
|
- **This is a Capacitor plugin, not an elizaOS runtime plugin.** It does not integrate with `AgentRuntime`, actions, providers, or evaluators. The elizaOS `"elizaos"` field in `package.json` is metadata for platform support, not a runtime hook.
|
|
- **No Bonjour/mDNS on web.** `startDiscovery()` and `getDiscoveredGateways()` return empty lists on the browser platform with a status message; only iOS (NWBrowser) and Android (NsdManager) perform real LAN discovery.
|
|
- **One active connection per plugin instance.** `connect()` closes any existing WebSocket before opening a new one.
|
|
- **Sequence gaps are logged but not fatal.** The web implementation warns on gaps in the `seq` field of event frames; native implementations may differ.
|
|
- **iOS minimum deployment target:** iOS 15.0 (Swift 5.9). See `.podspec`.
|
|
- **Android dependency:** OkHttp for WebSocket; coroutines (kotlinx.coroutines) for async ops.
|
|
- **Build output:** `dist/esm/index.js` (ESM), `dist/plugin.cjs.js` (CJS), `dist/plugin.js` (IIFE for unpkg).
|
|
- **`docgen` rewrites README.md.** Running `bun run build:docs` or `bun run docgen` regenerates README from JSDoc in `definitions.ts`. Manual edits to README may be overwritten.
|
|
- See root `AGENTS.md` for repo-wide conventions (logger-only, ESM, architecture rules, naming).
|
|
|
|
<!-- BEGIN: evidence-and-e2e-mandate (managed; canonical standard = repo-root AGENTS.md) -->
|
|
## ⛔ NON-NEGOTIABLE — evidence, trajectories & real end-to-end tests
|
|
|
|
> The binding, repo-wide standard is **[AGENTS.md](../../AGENTS.md)**. Read it.
|
|
> Nothing in this package is *done* until it is *proven* done — a reviewer must confirm it
|
|
> works **without reading the code**, from the artifacts you attach. This applies to **every**
|
|
> feature, fix, refactor, and chore here. "Tests pass" is not proof; "CI is green" is not proof.
|
|
|
|
- **Record AND read model trajectories.** Capture the *actual* inputs and outputs of the model
|
|
from a **live** LLM — not the deterministic proxy, not a mock: the prompt, the
|
|
providers/context, the raw model output, every tool/action call, and the result. Then **open
|
|
the trajectory and review it by hand.** A captured-but-unread trajectory is not evidence
|
|
(`packages/scenario-runner/bin/eliza-scenarios run <scenario> --report <out>`).
|
|
- **Real, full-featured E2E — no larp.** Every feature ships detailed end-to-end tests that
|
|
drive the *real* path end to end. Not the happy "front door" only: cover error paths,
|
|
edge/empty/invalid input, concurrency, roles/permissions, and adversarial input. A test that
|
|
asserts against a mock/stub/fixture standing in for the thing under test **does not count**.
|
|
If the real model/device/chain/connector/account is hard to reach, **make it reachable — that
|
|
is the work**, not an excuse to mock. If the existing tests here are shallow or mocked, fixing
|
|
them is part of your change.
|
|
- **Screenshots + logs at every phase**, plus a **complete walkthrough video/run-through** of
|
|
the entire feature or view, start to finish (`bun run test:e2e:record`).
|
|
- **Manually review every artifact the change touches** — never just the green check: client
|
|
logs (console + network), server logs (`[ClassName] …`), the model trajectories in and out,
|
|
before/after full-page screenshots, **and the domain artifacts listed below for this package.**
|
|
- **No residuals. No shortcuts.** The goal is not "done" — it is *everything* done. Clear every
|
|
blocker by the **hard path**: build the real architecture, stand up the real
|
|
model/device/service, actually test it. Never leave a TODO, a stub, a stepping-stone, or a
|
|
"follow-up." When unsure, research thoroughly, weigh the options, and ship the best,
|
|
highest-effort, production-ready version. Keep going until every possibility is exhausted.
|
|
|
|
Artifacts → attached inline in the PR (MP4 video, JPG screenshots, logs in `<details>`); attach each evidence type **or**
|
|
explicitly mark it N/A with a reason — never leave it blank. If `develop` moved and changed
|
|
behavior, **re-capture** evidence; stale proof is worse than none.
|
|
|
|
**Capture & manually review for this package — native / on-device bridge:**
|
|
- The capability run on a **real device or simulator** — not desktop Chromium against a mocked bridge (see #9967/#9580): device logs + the captured output (photo, OCR text, detection boxes, transcript, sensor reading).
|
|
- Parity vs the reference implementation where one exists (e.g. the Python/Ultralytics reference), with the numeric tolerances actually met.
|
|
- Permission-denied, no-hardware, and background/foreground lifecycle paths.
|
|
- A short recording of the on-device run; confirm the build under test is yours (versionName / a known on-screen change), not a stale install.
|
|
<!-- END: evidence-and-e2e-mandate -->
|