Skip to content

JavaScript SDK

The JavaScript SDK (sdk/js/) provides Node.js tooling for interacting with world-runner from scripts and headless test suites.

Requirements

  • Node.js ≥ 22
  • plant_world_runner binary built with server + brand-plugin features

Setup

cd sdk/js
npm install

Running tests

npm test             # all suites
npm run test:smoke   # server lifecycle, auth, clock, stream
npm run test:hob     # HobDriver observation + Phase II stubs

The binary path defaults to ../../target/debug/plant_world_runner. Override with WORLD_RUNNER_BIN.


WorldRunnerHarness

test/harness.js — spawn and terminate world-runner for testing.

import { WorldRunnerHarness } from "./test/harness.js";

const harness = new WorldRunnerHarness({ adminEmail: "me@example.com" });
await harness.start(); // spawns process, waits for ready, bootstraps auth
const client = harness.client();
await harness.stop();

Constructor options

Option Type Default Description
binaryPath string ../../target/debug/plant_world_runner Absolute path to binary
adminEmail string test@harness.local Email for admin magic-link session
extraArgs string[] [] Additional CLI args for world-runner

Properties

Property Type Description
baseUrl string e.g. http://127.0.0.1:43829
port number Bound TCP port
sessionCookie string Raw key=value session cookie

Methods

Method Returns Description
start() Promise<this> Spawn, wait for ready, bootstrap auth
client() WorldRunnerClient Authenticated client for this session
stop() Promise<void> SIGTERM + drain

WorldRunnerClient

src/world-client.js — authenticated HTTP + WebSocket client.

import { WorldRunnerClient } from "./src/world-client.js";

const client = new WorldRunnerClient("http://127.0.0.1:8080", sessionCookie);

Clock

Method Description
status() GET /status — clock/frame status (no auth required)
clockStep() POST /clock {"action":"step"} — advance one tick
clockSetInterval(ms) Start continuous clock at ms milliseconds/tick
clockPause() Pause continuous clock
clockResume() Resume paused clock

Atoms

Method Description
getAtomKinds() GET /atoms — list of kind strings
getAtoms(kind) GET /atoms/:kind — all instances of a kind
getAtom(kind, id) GET /atoms/:kind/:id — single atom, throws on 404

Services

Method Description
getServices() GET /services — service descriptor list
getService(kind) GET /services/:kind
getServiceRegistry(kind) GET /services/:kind/registry

WebSocket stream

// Open a stream (optionally filtered)
const ws = client.openStream({ prefix: "hob/", entityId: "hob-1" });

// Wait for a matching event
const event = await client.waitForStreamEvent(
  ws,
  (e) => e.event === "heartbeat",
  5_000, // timeout ms
);

ws.close();

The ws package is used instead of the native WebSocket API so that the session cookie can be forwarded on the HTTP upgrade request.


HobDriver

src/hob-driver.js — high-level per-hob wrapper.

import { HobDriver } from "./src/hob-driver.js";

const driver = new HobDriver(client, "hob-1");

Reading state

const state = await driver.getState();
// → raw atom JSON from /atoms/hob/hob-1

const ids = await HobDriver.listHobs(client);
// → ['hob-1', 'hob-2', ...]

Observing the stream

// Open an entity-filtered WebSocket
const ws = driver.openStream();

// Step clock + wait for any event (returns event or null on timeout)
const event = await driver.stepAndObserve(3_000);

Phase II movement (stubs)

The following methods are planned for implementation once world-runner exposes hob input patch endpoints:

  • walkToNode(nodeId)
  • walkAlongSegment(segmentId)
  • setStance(stance)'idle' | 'walking' | 'stationary_watch'
  • awaitLocation(predicate, timeoutMs)