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
141 lines
4.9 KiB
Markdown
141 lines
4.9 KiB
Markdown
# @elizaos/capacitor-canvas
|
|
|
|
A [Capacitor](https://capacitorjs.com/) plugin for elizaOS that provides an interactive 2D canvas with layer management, drawing primitives, web view embedding, and an A2UI bridge for building rich visual UIs in Eliza agent surfaces.
|
|
|
|
Supported platforms: **browser**, **node** (Electrobun desktop), **iOS**, **Android**.
|
|
|
|
## What it does
|
|
|
|
- **Canvas with layers** — create canvases of any size, manage named composited layers with independent opacity, z-index, and transform.
|
|
- **Drawing primitives** — rectangles (with corner radius), ellipses, lines, arbitrary paths (Bezier, arc, ellipse, closePath), text with font/align/baseline control, and images (URL or base64).
|
|
- **Batch drawing** — submit a typed array of draw commands in a single call for efficient rendering.
|
|
- **Gradients, blend modes, shadows, transforms** — applied per draw call or globally.
|
|
- **Export** — capture the canvas to a base64 PNG/JPEG/WEBP image or read raw pixel data.
|
|
- **Web view** — load any URL inline, fullscreen, or in a popup; evaluate JavaScript in it; capture a screenshot.
|
|
- **A2UI bridge** — push structured agent-to-UI messages (text cards, action buttons, forms, status indicators) into a loaded web view and receive back action events.
|
|
- **Touch/pointer events** — emit normalized `CanvasTouchEvent` on touch start/move/end/cancel and equivalent mouse drag.
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
bun add @elizaos/capacitor-canvas
|
|
```
|
|
|
|
Peer dependency (must be installed by the host):
|
|
|
|
```bash
|
|
bun add @capacitor/core
|
|
```
|
|
|
|
For iOS add the pod:
|
|
|
|
```bash
|
|
npx cap sync ios
|
|
```
|
|
|
|
The podspec is `ElizaosCapacitorCanvas.podspec`. iOS deployment target is 15.0, Swift 5.9, frameworks UIKit / CoreGraphics / WebKit.
|
|
|
|
## Usage
|
|
|
|
```ts
|
|
import { Canvas } from "@elizaos/capacitor-canvas";
|
|
|
|
// Create a canvas
|
|
const { canvasId } = await Canvas.create({ size: { width: 800, height: 600 } });
|
|
|
|
// Add a layer
|
|
const { layerId } = await Canvas.createLayer({
|
|
canvasId,
|
|
layer: { visible: true, opacity: 1, zIndex: 1 },
|
|
});
|
|
|
|
// Draw on it
|
|
await Canvas.drawRect({
|
|
canvasId,
|
|
rect: { x: 10, y: 10, width: 200, height: 100 },
|
|
fill: { color: { r: 255, g: 100, b: 0, a: 0.9 } },
|
|
cornerRadius: 8,
|
|
drawOptions: { layerId },
|
|
});
|
|
|
|
// Batch draw
|
|
await Canvas.drawBatch({
|
|
canvasId,
|
|
commands: [
|
|
{ type: "ellipse", args: { center: { x: 400, y: 300 }, radiusX: 50, radiusY: 50, fill: { color: "#3399ff" } } },
|
|
{ type: "text", args: { text: "Hello", position: { x: 400, y: 300 }, style: { font: "sans-serif", size: 24, color: "#fff", align: "center" } } },
|
|
],
|
|
});
|
|
|
|
// Export to image
|
|
const image = await Canvas.toImage({ canvasId, format: "png" });
|
|
// image.base64, image.width, image.height
|
|
|
|
// Attach to DOM (browser/desktop)
|
|
await Canvas.attach({ canvasId, element: document.getElementById("canvas-host")! });
|
|
|
|
// Enable touch events
|
|
await Canvas.setTouchEnabled({ canvasId, enabled: true });
|
|
const handle = await Canvas.addListener("touch", (evt) => {
|
|
console.log(evt.type, evt.touches);
|
|
});
|
|
|
|
// Embed a web view
|
|
await Canvas.navigate({ url: "https://example.com", placement: "inline" });
|
|
|
|
// Evaluate JS in it
|
|
const { result } = await Canvas.eval({ script: "document.title" });
|
|
|
|
// Push A2UI messages
|
|
await Canvas.a2uiPush({
|
|
messages: [
|
|
{ role: "assistant", type: "text", content: "Hello from the agent!" },
|
|
],
|
|
});
|
|
|
|
// Listen for A2UI actions triggered in the web content
|
|
await Canvas.addListener("a2uiAction", (evt) => {
|
|
console.log(evt.action, evt.data);
|
|
});
|
|
|
|
// Cleanup
|
|
await handle.remove();
|
|
await Canvas.destroy({ canvasId });
|
|
```
|
|
|
|
## A2UI message types
|
|
|
|
| `type` | Use |
|
|
|-----------|-----|
|
|
| `text` | Plain text bubble |
|
|
| `card` | Structured card with title/body |
|
|
| `action` | Clickable action button |
|
|
| `form` | Input form |
|
|
| `list` | Ordered/unordered list |
|
|
| `image` | Image display |
|
|
| `status` | Status indicator |
|
|
|
|
## Web view events
|
|
|
|
| Event | Payload | When |
|
|
|-------|---------|------|
|
|
| `webViewReady` | `{ url, title }` | Navigation completed |
|
|
| `navigationError` | `{ url, code, message }` | Load failed |
|
|
| `deepLink` | `{ url, path, params }` | `eliza://` URL intercepted |
|
|
| `a2uiAction` | `{ action, data, messageId? }` | Web content triggered an action |
|
|
|
|
## Canvas events
|
|
|
|
| Event | Payload | When |
|
|
|-------|---------|------|
|
|
| `touch` | `CanvasTouchEvent` | Touch or mouse drag on canvas |
|
|
| `render` | `CanvasRenderEvent` | Each rendered frame (FPS telemetry) |
|
|
|
|
## Notes
|
|
|
|
- `snapshot()` only works with `placement: "inline"` or `"fullscreen"`. Cross-origin iframes render an unavailable frame.
|
|
- `eval()` requires the loaded page to handle `eliza:eval` postMessages and reply with `eliza:evalResult`; times out after 5 seconds.
|
|
- `a2uiPush` and `a2uiReset` prefer the `window.elizaA2UI` bridge when present; otherwise fall back to `postMessage`.
|
|
- Call `attach()` before calling `setTouchEnabled()` — touch handlers are wired on attach.
|
|
- Layer canvases are absolute-positioned siblings of the base canvas element; the host container should be `position: relative`.
|