LiveKit SFU orchestrator for Hero OS with typed OpenRPC surface and admin UI.
  • Rust 46.5%
  • Shell 27.1%
  • JavaScript 10.5%
  • HTML 5.5%
  • CSS 3.6%
  • Other 6.8%
Find a file
Sameh Abouel-saad 63f80f56d7
Some checks failed
Build & Test / check (push) Failing after 2m9s
lab release / release (push) Successful in 39m51s
feat(livekit): migrate to canonical herolib serving (#50, #51)
Migrate hero_livekit off the frozen pre-migration OSIS/hero_rpc2 stack
(hero_macros_previous@osis_oldserving) to the canonical herolib serving stack
(herolib_macros::openrpc_server! + serve_domains), matching hero_collab/hero_proc.

- Deps: drop hero_rpc2/hero_rpc_osis/hero_rpc_openrpc/hero_rpc_derive; use
  herolib_macros/herolib_oschema_server + herolib_*/hero_proc_sdk @development.
- Server: main.rs now uses openrpc_server!+serve_domains; the LiveKitService
  business logic moves livekit/rpc.rs -> sfu.rs, bridged by src/rpc/main_impl.rs.
  oschema moved to oschema/main/. SDK + admin (dashboard.js) + rhai + examples
  reconciled with the regenerated SDK (params-wrapped inputs, i64 fields).
- #51: now serves the canonical surface (/api/ping, /api/{domain}/rpc,
  /heroservice.json, /api/domains.json); legacy /rpc gone. Router discovers the
  12-method surface.
- #50: provision reads LIVEKIT_VERSION via the migrated hero_proc_sdk secret API
  (reaches /api/secrets/rpc, not the dead legacy /rpc) and self-calls
  /api/main/rpc; auto-provisions the SFU on startup. Folds in the #50 hardening
  (SecretRead Found/NotSet/Error + retry + loud-on-error + -32002-only-opt-out).
- security: sfu.rs writes credential files (livekit.yaml/backend.env/runtime.json)
  0600 + dirs 0700; api_secret now from getrandom CSPRNG (fail-closed, no LCG).

Verified on box (build #11): auto-provision binds :7880 + survives 2 restarts
with no manual start; canonical /api/ping=pong; node_ip routable (no loopback);
huddle SFU reachable + huddle_start mints a room; collab+planner unaffected
(/api/ping pong, proc+router panels healthy). Built from development HEAD with
a HEAD-matching lockfile. cargo test + clippy green.

Closes #50.
Closes #51.
2026-06-16 22:57:04 +03:00
.cargo ci(workflows): rewrite build/release around build_lib.sh + ARM64 matrix 2026-04-27 13:16:59 +00:00
.forgejo/workflows ci: canonical lab-release (cargo check + multi-arch + hero.releaser) 2026-06-10 20:32:36 +02:00
crates feat(livekit): migrate to canonical herolib serving (#50, #51) 2026-06-16 22:57:04 +03:00
docs feat(livekit): migrate to canonical herolib serving (#50, #51) 2026-06-16 22:57:04 +03:00
scripts refactor: rename hero_livekit_ui -> hero_livekit_admin (ui.sock -> admin.sock) (#38) 2026-05-08 02:06:12 +00:00
sdk/js refactor(oschema): align layout with canonical hero_osis/hero_voice pattern 2026-04-23 10:13:41 +02:00
.gitignore feat(livekit): port server to the main OSIS framework; align deps to hero_lib main 2026-06-04 11:49:46 +02:00
buildenv.sh refactor: rename hero_livekit_ui -> hero_livekit_admin (ui.sock -> admin.sock) (#38) 2026-05-08 02:06:12 +00:00
Cargo.lock feat(livekit): migrate to canonical herolib serving (#50, #51) 2026-06-16 22:57:04 +03:00
Cargo.toml feat(livekit): migrate to canonical herolib serving (#50, #51) 2026-06-16 22:57:04 +03:00
Cargo.toml.hero_builder_backup chore(deps): bump dependency versions and add workspace resolver = "3" 2026-05-13 17:20:15 +02:00
Makefile fix(deps): restore buildable main — pin to pre-simplification deps + --locked 2026-06-04 19:40:19 +03:00
README.md refactor: rename hero_livekit_ui -> hero_livekit_admin (ui.sock -> admin.sock) (#38) 2026-05-08 02:06:12 +00:00
rust-toolchain.toml feat(livekit): port server to the main OSIS framework; align deps to hero_lib main 2026-06-04 11:49:46 +02:00
rustfmt.toml build: default cargo fmt to edition 2024 2026-04-28 07:29:18 +00:00

hero_livekit

LiveKit SFU orchestrator for the Hero OS Suite. Downloads, configures, and supervises the upstream livekit-server and lk-backend binaries, and exposes a typed OpenRPC surface plus an admin + meeting UI.

HERO_SOCKET_DIR defaults to ~/hero/var/sockets when unset. All socket paths below resolve to $HERO_SOCKET_DIR/hero_livekit/<sock>.

                 ┌───────────────────────────────────────────────────┐
                 │   hero_livekit_admin  (Askama/Bootstrap dashboard)   │
                 │   - Server lifecycle tab                          │
                 │   - Rooms / Tokens / Join                         │
                 │   - /join/{room}  (livekit-client meeting page)   │
                 └───────────────┬────────────────┬──────────────────┘
                                 │ JSON-RPC       │ ws://host:7880
                                 ▼                │
            ┌────────────────────────────────┐    │
            │    hero_livekit_server         │    │
            │    (OServer, OSchema-based)    │    │
            │    rpc.sock + admin.sock          │    │
            │    spawns & supervises:        │    │
            │      livekit-server            │────┘
            │      lk-backend                │
            └────────────────────────────────┘
                    │              │
                    ▼              ▼
             ~/hero/bin/      Redis (127.0.0.1:6379)
             livekit-server
             lk-backend

Crates

Crate Purpose
hero_livekit_server OServer-backed supervisor. Generates types + CRUD + OpenRPC spec from schemas/livekit/livekit.oschema.
hero_livekit_admin Axum-based admin dashboard + meeting page (embeds livekit-client).
hero_livekit_examples Tiny CLI programs that call the generated OpenRPC client.

Quickstart

Prerequisites on the host: Redis running at 127.0.0.1:6379.

# Build and install both binaries to ~/hero/bin/
make install

# Start the supervisor (foreground — hero_proc can also manage it via --start)
~/hero/bin/hero_livekit_server &

# Start the admin UI (binds to $HERO_SOCKET_DIR/hero_livekit/ui.sock)
~/hero/bin/hero_livekit_admin &

Then open the hero_router dashboard (usually http://127.0.0.1:9988/) and click Hero LiveKit Admin, or go directly to http://127.0.0.1:9988/hero_livekit/ui/.

In the UI, run the Server tab flow once:

  1. Install — downloads livekit-server + lk-backend to ~/hero/bin/
  2. Configure — generates livekit.yaml + backend.env with a random API secret, persists to runtime.json
  3. Start — spawns both processes

Then go to Join and click Start a new meeting to open a browser meeting page backed by livekit-client.

Documentation

Service lifecycle via hero_proc

scripts/nu_service.nu is a Nushell module that registers and supervises hero_livekit_server and hero_livekit_admin under hero_proc. It provides four subcommands: install, start, stop, status.

use scripts/nu_service.nu
nu_service install         # cargo-install the binaries into ~/hero/bin
nu_service start           # register + start actions and service in hero_proc
nu_service status          # show current state
nu_service stop            # tear down the registrations

Add --root to any subcommand when hero_proc is running as root. Prerequisite: the hero_skills tools/modules/ directory must be reachable via NU_LIB_DIRS, and hero_proc must be running.

Scripting (Rhai)

crates/hero_livekit_rhai ships a hero_do_hero_livekit binary that exposes the full LiveKitService OpenRPC surface to Rhai scripts. Build and install it with:

make install-rhai

then run one of the bundled examples:

hero_do_hero_livekit crates/hero_livekit_rhai/examples/rhai/01_status.rhai
hero_do_hero_livekit crates/hero_livekit_rhai/examples/rhai/02_list_rooms.rhai

The binary auto-injects SCRIPT_DIR, SCRIPT_FILE, and ARGS into the Rhai scope. See the files under crates/hero_livekit_rhai/examples/rhai/ for patterns:

  • 01_status.rhai — connect + print the current service state
  • 02_list_rooms.rhai — enumerate active rooms
  • 03_create_delete_room.rhai — room CRUD round-trip
  • 04_issue_token.rhai — mint a JWT with grants
  • 05_full_lifecycle.rhai — install → configure → start → create → token → stop

Scripts default to $HERO_SOCKET_DIR/hero_livekit/rpc.sock (falling back to ~/hero/var/sockets/hero_livekit/rpc.sock); pass an explicit path to livekit_client("/custom/path/rpc.sock") to override.

License

See individual crates.