Add nu_service.nu, .claude/, CLAUDE.md, hero_do_hero_livekit Rhai binary #12
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Repo is missing four standard Hero artifacts:
scripts/nu_service.nu— install/start/stop/status lifecycle module delegating to hero_proc (nu_service)..claude/— repo-local skills index + settings (synced fromhero_skills).CLAUDE.md— repo-specific context file.hero_do_hero_livekit— Rhai scripting binary + feature flag + example.rhaiscripts (rhai_bindings_generate_fix).Goals
scripts/nu_service.nufollowing theservice_proxy.nupattern; exposeinstall,start,stop,statussubcommands..claude/with a curated subset of skills relevant to this repo (seehero_skills/.claude/).CLAUDE.mdcovering architecture, sockets, how to build/run/test, and pointers to relevant skills.crates/hero_livekit_cli_rhai/(or appropriate location) binaryhero_do_hero_livekitthat exposes SDK methods to Rhai; add per-crate Makefile and at least one example script underexamples/*.rhai.Related skills:
nu_service,rhai_bindings_generate_fix,rhai_bindings_reference.no need .claude/ and CLAUDE.md
Implementation Spec for Issue #12 — nu_service.nu + hero_do_hero_livekit
Objective
Add two scripting/lifecycle artefacts to
hero_livekit: a Nushell service module (scripts/nu_service.nu) that gives the repo a standardinstall/start/stop/statussurface talking tohero_proc, and a new workspace cratehero_livekit_rhaiproducing ahero_do_hero_livekitbinary that exposes the fullLiveKitServiceOpenRPC surface to Rhai scripts. Both follow thenu_serviceandrhai_bindings_generate_fix+rhai_bindings_cmd_pathskill conventions already used across the Hero ecosystem. Nothing in the.claude/or rootCLAUDE.mdspace is touched (dropped per maintainer comment).Requirements
scripts/nu_service.numatching thenu_serviceskill: two-action (hero_livekit_server+hero_livekit_ui) pattern, usesproc.nu+services/lib.nu, socket bases$"($sock_base)/hero_livekit/{rpc,ui}.sock", subcommandsinstall/start/stop/statuswith--root/--resetflags.context_name: "core",class: "system",critical: false. Binaries:hero_livekit_server hero_livekit_ui lk-backend(lk-backendis installed but is a supervised child ofhero_livekit_server, not a hero_proc action).crates/hero_livekit_rhaiproducing binaryhero_do_hero_livekit(via[[bin]]withrequired-features = ["rhai"]), a library holding the binding registration, plus ≥5 example.rhaiscripts.SCRIPT_DIR,SCRIPT_FILE, andARGSinto the Rhai scope per therhai_bindings_cmd_pathskill.crates/hero_livekit_server/src/livekit/core/openrpc.json(12LiveKitServicemethods) plus alivekit_client(socket_path)constructor with a no-arg overload, using manualregister_fn/register_type_with_name/register_getonly.Makefilewithbuild,build-do,install,installdev,check,clippy,test,run-examples,example NAME=….Cargo.tomladdscrates/hero_livekit_rhaito[workspace] members.Makefilegets passthrough targets (build-rhai,install-rhai,run-rhai-example).Files to Modify/Create
scripts/nu_service.nuCargo.toml(workspace)crates/hero_livekit_rhaito[workspace.members]crates/hero_livekit_rhai/Cargo.toml[[bin]] hero_do_hero_livekit,rhaifeature gatecrates/hero_livekit_rhai/src/lib.rscreate_engine()+register()wiringcrates/hero_livekit_rhai/src/client.rsLiveKitClient(owns tokio runtime)crates/hero_livekit_rhai/src/bindings.rsregister_fn/register_getcallscrates/hero_livekit_rhai/src/main.rscrates/hero_livekit_rhai/examples/rhai/01_status.rhaicrates/hero_livekit_rhai/examples/rhai/02_list_rooms.rhaicrates/hero_livekit_rhai/examples/rhai/03_create_delete_room.rhaicrates/hero_livekit_rhai/examples/rhai/04_issue_token.rhaicrates/hero_livekit_rhai/examples/rhai/05_full_lifecycle.rhaicrates/hero_livekit_rhai/Makefilecrates/hero_livekit_rhai/buildenv.shPROJECT_NAME=hero_livekit_rhai,BINARIES=hero_do_hero_livekit,ALL_FEATURES=rhaiMakefile(root)build-rhai/install-rhai/run-rhai-examplepassthrough targetsREADME.mdImplementation Plan
Step 1: scripts/nu_service.nu
Files:
scripts/nu_service.nu(new)Actions:
SVX_SERVICE_NAME = "hero_livekit",SVX_FORGE_LOC = "lhumina_code/hero_livekit".SVX_BINARIES = ["hero_livekit_server" "hero_livekit_ui" "lk-backend"].SVX_ACTIONS = ["hero_livekit_server" "hero_livekit_ui"](intentionally omitslk-backend— supervised by the server).$"($sock_base)/hero_livekit/rpc.sock". UI socket:$"($sock_base)/hero_livekit/ui.sock".start_period_ms: 5000,interval_ms: 3000."hero_livekit — LiveKit SFU orchestrator for the Hero OS Suite."context_name: "core",status: "start",critical: false,class: "system".env: {RUST_LOG: "info"}— no custom HERO_LIVEKIT_* env vars need forwarding.install,start,stop,status— delegate tosvc_cargo_install,svx_drop_registration,proc action/service set/start/statushelpers from the skill template.Dependencies: none. Can run in parallel with: Steps 2–5.
Step 2: New crate crates/hero_livekit_rhai
Files:
crates/hero_livekit_rhai/{Cargo.toml,src/lib.rs,src/client.rs,src/bindings.rs,src/main.rs,buildenv.sh}(all new); workspaceCargo.toml(modify to add member).Cargo.toml (new crate):
src/client.rs — reuse the generated client via
openrpc_client!, wrap it with a tokio runtime so Rhai (sync) can call blocking methods:src/bindings.rs — manual Rhai registration. Constructors:
livekit_client()→ default socket pathlivekit_client(path: &str)→ explicit socket pathLifecycle methods (return
Stringfor ServiceState, lower-cased):install(livekit_version: String, backend_version: String) -> Stringconfigure(node_ip, api_key, api_secret, domain, livekit_port: i64, backend_port: i64, redis_address) -> Stringstart() -> String,stop() -> String,restart() -> String,status() -> StringRoom methods:
create_room(name, max_participants: i64, empty_timeout: i64, metadata) -> Roomlist_rooms() -> rhai::Array(Dynamic::from(Room)elements)delete_room(name) -> boolParticipant methods:
list_participants(room) -> rhai::Arrayremove_participant(room, identity) -> boolTokens:
issue_token(identity, room, ttl_secs: i64, can_publish: bool, can_subscribe: bool) -> AccessTokenRegistered types via
register_type_with_name+ getters +to_string/to_debug:Room—sid,name,num_participants,max_participants,empty_timeout,creation_time,metadata,statusParticipant—sid,identity,name,room_sid,state,joined_at,metadataAccessToken—sid,identity,room,issued_at,expires_at,grantsEvery fallible call uses
e.to_string().into()to produceBox<EvalAltResult>.src/lib.rs:
src/main.rs follows the
hero_do_*shape: arg dispatch for<script.rhai> [args...]/<directory>/-istdin /--run <name>/--version/--help. InjectsSCRIPT_DIR,SCRIPT_FILE,ARGSinto the Rhai scope perrhai_bindings_cmd_path. Built-in scripts viainclude_str!("../examples/rhai/*.rhai").buildenv.sh:
Workspace Cargo.toml: append
"crates/hero_livekit_rhai"tomembers.Dependencies: none. Must precede: Steps 3 & 4. Can run in parallel with: Step 1.
Step 3: Example Rhai scripts
Files:
crates/hero_livekit_rhai/examples/rhai/0{1..5}_*.rhaiEach script begins with
#!/usr/bin/env hero_do_hero_livekit. Short and direct (no try/catch, no decorative comments perrhai_check):01_status.rhai→let c = livekit_client(); print(c.status());02_list_rooms.rhai→ iteratec.list_rooms()and print each room's name + participant count03_create_delete_room.rhai→ createrhai-demo, print sid, delete, print result04_issue_token.rhai→ issue a token foralicein roomdemo, print grants05_full_lifecycle.rhai→ consume versions fromARGS, runinstall→configure→start→ create room → issue token → list participants →stopDependencies: Step 2. Can run in parallel with: Step 1, 4, 5.
Step 4: Per-crate Makefile + root passthrough
Files:
crates/hero_livekit_rhai/Makefile(new),Makefile(root, modify)Per-crate Makefile clones
hero_books_lib_rhai/Makefileshape:NAME := hero_livekit_rhai,DO := hero_do_hero_livekitbuild,build-do,build-release,install,installdev,check,clippy,test,run-examples,example NAME=<n>installcopies../../target/release/hero_do_hero_livekitto$(HOME)/hero/bin/Root Makefile additions (near end, before
clean):Add them to
.PHONY.Dependencies: Step 2. Can run in parallel with: Step 1, 3, 5.
Step 5: README.md update
Files:
README.md(modify)Append two sections after "Documentation":
use scripts/nu_service.nu+nu_service install/start/status/stopwith--rootexample.make install-rhai+hero_do_hero_livekit examples/rhai/01_status.rhai, points tocrates/hero_livekit_rhai/examples/rhai/.Dependencies: Steps 1 & 2 (for link accuracy). Can run in parallel with: Step 3, 4.
Acceptance Criteria
cargo build -p hero_livekit_rhaisucceeds.cargo build -p hero_livekit_rhai --bin hero_do_hero_livekitproducestarget/debug/hero_do_hero_livekit.make install-rhaiinstallshero_do_hero_livekitinto~/hero/bin/.hero_do_hero_livekit --helpprints the usage banner.hero_livekit_serverrunning,hero_do_hero_livekit crates/hero_livekit_rhai/examples/rhai/01_status.rhaiprints the state.hero_do_hero_livekit crates/hero_livekit_rhai/examples/rhai/02_list_rooms.rhaiconnects and enumerates.use scripts/nu_service.nu; nu_service installbuilds/installs the workspace binaries.nu_service startregisters both actions + service and starts them;nu_service statusshows running.nu_service stoptears down registrations cleanly.try/catch, no decorative comments in the.rhaiscripts (rhai_check compliant).Notes
$HERO_SOCKET_DIR/hero_livekit/rpc.sockcascading to~/hero/var/sockets/hero_livekit/rpc.sock— consistent with the recent PR #16 (issue #13) wiring.BINARIESsoinstallcopies it, but NOT a hero_proc action (supervised byhero_livekit_server).default = ["rhai"]matcheshero_books_lib_rhaiergonomics;--no-default-featuresstill builds the library.hero_books_lib_rhai).LiveKitService.*methods currently exposed. Per-entity CRUD (room.set/get/delete/etc.) is NOT in the generated client today, so not bound here. If added later it regenerates automatically.nushell in PATH,hero_procrunning under the invoking user (or root with--root),hero_skills/tools/modules/exported viaNU_LIB_DIRS.rhai = "1"withfeatures = ["sync"]— matches ecosystem convention.Test Results (Issue #12 implementation)
cargo check --workspacecargo test --workspacehero_livekit_rhailib unittests: 0 passed; 0 failed; 0 ignoredhero_do_hero_livekitbin unittests: 0 passed; 0 failed; 0 ignoredhero_livekit_rhaidoctests: 0 passed; 0 failed; 0 ignoredhero_livekit_serverlib+bin 4+4 passed; 3 doctests ignored.Notes
nu_service.nuis validated functionally by invokingnu scripts/nu_service.nu statusagainst a running hero_proc; that is a runtime smoke test not covered bycargo test.hero_do_hero_livekitruntime validation requireshero_livekit_serveron$HERO_SOCKET_DIR/hero_livekit/rpc.sock; not covered bycargo test.Implementation Summary
All 5 spec steps applied on branch
development_nu_service_rhai(branched frommain)..claude/andCLAUDE.mddeliverables dropped per comment.Changes
Nushell service module
scripts/nu_service.nu— two-action module (hero_livekit_server+hero_livekit_ui) delegating tohero_procvia theservices/lib.nuhelpers. Subcommands:install,start,stop,statuswith--root/--resetflags.lk-backendis inSVX_BINARIES(copied by install) but not an action (supervised child of the server).New workspace crate
crates/hero_livekit_rhaiCargo.toml— library +[[bin]] hero_do_hero_livekitgated onrequired-features = ["rhai"].rhai = { version = "1", features = ["sync"], optional = true }.src/client.rs— blocking wrapperLiveKitRhaiClientowning a tokioRuntime+Arc<LiveKitClient>.default_socket_path()cascades$HERO_SOCKET_DIR→~/hero/var/sockets/hero_livekit/rpc.sock.src/bindings.rs— manual Rhai registration for every method inopenrpc.json(install,configure,start,stop,restart,status,create_room,list_rooms,delete_room,list_participants,remove_participant,issue_token). RegistersRoom,Participant,AccessTokenas Rhai custom types with getters +to_string/to_debug.src/lib.rs— publicregister(&mut Engine)andcreate_engine() -> Engine.src/main.rs— CLI entry. Arg dispatch for<script.rhai> [args...],<directory>,-istdin,--run <name>,--version,--help. InjectsSCRIPT_DIR,SCRIPT_FILE,ARGSinto the Rhai scope per therhai_bindings_cmd_pathskill.buildenv.sh—PROJECT_NAME/BINARIES/ALL_FEATURES/VERSION/PATCHLEVEL.Workspace
Cargo.toml"crates/hero_livekit_rhai"to[workspace] members.Example Rhai scripts —
crates/hero_livekit_rhai/examples/rhai/01_status.rhai— prints service state.02_list_rooms.rhai— enumerate rooms with participant counts.03_create_delete_room.rhai— create + delete round-trip.04_issue_token.rhai— issue a JWT + print grants.05_full_lifecycle.rhai— install → configure → start → create → token → participants → stop. Reads versions fromARGS.chmod +x) andrhai_check-compliant (no try/catch, no decorative headers).Makefiles
crates/hero_livekit_rhai/Makefile—build,build-do,build-release,install,installdev,check,clippy,test,run-examples,example EXAMPLE=<file>.Makefile—build-rhai,install-rhai,run-rhai-examplepassthroughs; added to.PHONY.README.md
nu_service.nu.hero_do_hero_livekitwithmake install-rhaiand example invocations.Build + Test Results
cargo check --workspace— PASScargo test --workspace— 8 passed, 0 failed, 3 ignored (pre-existing rustdoc examples).rhaiscripts against a livehero_livekit_server.Runtime validation (out of scope for cargo test)
nu scripts/nu_service.nu status— requires a runninghero_proc.hero_do_hero_livekit examples/rhai/01_status.rhai— requireshero_livekit_serveron$HERO_SOCKET_DIR/hero_livekit/rpc.sock.Notes
HERO_SOCKET_DIR(same cascade as PR #16 / issue #13).openrpc_client!macro regenerates the typedLiveKitClientat build time; any future OpenRPC methods surface automatically, but Rhai bindings for new methods must be added manually.Pull request opened: #17
This PR implements the changes discussed in this issue.