2026-11-01 18:39:19 +00:00
|
|
|
# Runa — Rune Actors
|
|
|
|
|
|
|
|
|
|
Runa (short for **Rune Actors**) is an experimental project to build a
|
|
|
|
|
persistent, live programming world around isolated actors written in Rune.
|
|
|
|
|
The long-term vision combines an inspectable graphical environment with a
|
|
|
|
|
programmatic API and a VS Code extension, all connected to the same running
|
|
|
|
|
image.
|
|
|
|
|
|
|
|
|
|
## Status
|
|
|
|
|
|
2026-11-02 08:19:04 +00:00
|
|
|
Runa is at an early prototype stage. The executable runs a Phase 0 feasibility
|
|
|
|
|
experiment using Rune 0.14.2: script execution, native calls, async suspension,
|
|
|
|
|
instruction budgets, stepping, and compiled-code sharing. It also runs a minimal
|
|
|
|
|
single-worker actor demonstration with bounded mailboxes and explicit message
|
2026-11-02 09:08:49 +00:00
|
|
|
effects. Source and compiled implementation identities are BLAKE3 content
|
2026-11-02 13:50:30 +00:00
|
|
|
addresses with an in-memory compile cache. Persistence, canonicalization,
|
2026-11-03 13:52:28 +00:00
|
|
|
remote network access, and the graphical world are not implemented yet.
|
|
|
|
|
A minimal VS Code extension can connect to the local image, list actors, and
|
|
|
|
|
inspect state, queued/reserved messages, and execution telemetry in read-only
|
|
|
|
|
documents. The code library now supports an in-memory versioned behavior
|
2026-11-02 12:11:11 +00:00
|
|
|
registry, and the CLI exposes publishing, history, rollback, safe-boundary
|
2026-11-02 12:20:45 +00:00
|
|
|
installation, pause/resume, and cancellation through a trusted in-process image
|
2026-11-02 12:36:32 +00:00
|
|
|
API. A versioned transport-neutral protocol contract is now defined, but no
|
2026-11-03 14:49:35 +00:00
|
|
|
authentication is implemented. The `runa` server provides an unauthenticated
|
|
|
|
|
WebSocket listener restricted to localhost, with bounded request sizes.
|
|
|
|
|
The `runa-cli` REPL and VS Code connect with
|
2026-11-03 14:36:21 +00:00
|
|
|
the `runa-debug` WebSocket subprotocol, so clients share one server-owned image.
|
|
|
|
|
Server change notifications automatically refresh VS Code's actor tree and inspectors.
|
2026-11-01 18:39:19 +00:00
|
|
|
|
2026-11-02 08:19:04 +00:00
|
|
|
The prototype uses worker-local invocation stacks and cooperative instruction
|
2026-11-02 12:11:11 +00:00
|
|
|
slices, and actor snapshots report basic active-execution progress. Native
|
|
|
|
|
callbacks are not preemptible; source-level debugging and persistent storage
|
|
|
|
|
are not implemented.
|
2026-11-01 18:39:19 +00:00
|
|
|
|
|
|
|
|
## Design goals
|
|
|
|
|
|
|
|
|
|
- Keep actor identity, mailbox, private state, behavior, and incarnation
|
|
|
|
|
separate.
|
|
|
|
|
- Use message passing rather than shared mutable state for actor interaction.
|
|
|
|
|
- Keep behavior implementations immutable and support safe, versioned updates.
|
|
|
|
|
- Expose the same runtime capabilities to in-world tools and external clients.
|
|
|
|
|
- Be explicit about execution, delivery, and persistence guarantees.
|
|
|
|
|
|
2026-11-01 19:15:00 +00:00
|
|
|
See [the architecture spec](docs/architecture.md) for the full vision,
|
2026-11-01 18:39:19 +00:00
|
|
|
architecture, roadmap, and open questions.
|
|
|
|
|
|
|
|
|
|
## Getting started
|
|
|
|
|
|
|
|
|
|
You need a Rust toolchain that supports the workspace's Rust 2024 edition.
|
|
|
|
|
|
2026-11-02 14:57:26 +00:00
|
|
|
Start the live image from the repository root:
|
2026-11-01 18:39:19 +00:00
|
|
|
|
|
|
|
|
```sh
|
2026-11-03 14:49:35 +00:00
|
|
|
mise run start
|
2026-11-01 18:39:19 +00:00
|
|
|
```
|
|
|
|
|
|
2026-11-02 14:57:26 +00:00
|
|
|
In another terminal, connect the REPL:
|
|
|
|
|
|
|
|
|
|
```sh
|
2026-11-03 14:49:35 +00:00
|
|
|
mise run cli
|
2026-11-02 14:57:26 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The REPL defaults to `127.0.0.1:3737`. To select another loopback endpoint,
|
2026-11-03 14:49:35 +00:00
|
|
|
use `cargo run -p runa-cli -- --connect 127.0.0.1:4000` and start the server with
|
2026-11-02 14:57:26 +00:00
|
|
|
the corresponding `--listen` address. Quitting the REPL disconnects only that
|
|
|
|
|
client; actors and published behaviors survive until the server exits.
|
|
|
|
|
Reconnect and use `actors` to recover their references. REPL bindings and
|
|
|
|
|
command history are session-local and are not restored on reconnect.
|
|
|
|
|
|
2026-11-03 14:49:35 +00:00
|
|
|
Both executables use Clap for `--help`, `--version`, and argument validation.
|
|
|
|
|
`runa` listens on `127.0.0.1:3737` without arguments. Set `RUNA_LISTEN` to change
|
|
|
|
|
the server address and `RUNA_CONNECT` to change the REPL address; explicit
|
|
|
|
|
`--listen` and `--connect` flags override their respective environment variables.
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
RUNA_LISTEN=127.0.0.1:4000 mise run start
|
|
|
|
|
RUNA_CONNECT=127.0.0.1:4000 mise run cli
|
|
|
|
|
```
|
2026-11-02 13:18:45 +00:00
|
|
|
|
2026-11-03 14:49:35 +00:00
|
|
|
The server is WebSocket-only; stdio transport has been removed. By default it listens on
|
2026-11-03 14:36:21 +00:00
|
|
|
`ws://127.0.0.1:3737/` and requires the `runa-debug` subprotocol, with up to 16
|
2026-11-02 13:50:30 +00:00
|
|
|
simultaneous clients sharing one live image. The listener rejects non-loopback
|
|
|
|
|
addresses and has no authentication; any local process that can connect has
|
|
|
|
|
full access to the development API. Use it only on a trusted local machine.
|
|
|
|
|
|
2026-11-03 14:49:35 +00:00
|
|
|
The `runa-client` crate connects over loopback
|
2026-11-03 14:36:21 +00:00
|
|
|
WebSockets and exchange typed protocol requests with request/response correlation.
|
|
|
|
|
Network connection establishment is limited to 5 seconds and response waits/writes to 30
|
2026-11-02 14:57:26 +00:00
|
|
|
seconds. Transport failures disconnect the client and are never automatically
|
|
|
|
|
retried: an operation may have committed even if its response was lost.
|
2026-11-03 13:52:28 +00:00
|
|
|
The VS Code extension connects over the network to this same live image; actors remain in
|
2026-11-02 13:50:30 +00:00
|
|
|
the image regardless of how clients connect. Remote network access requires
|
|
|
|
|
authentication and authorization, which are not implemented.
|
2026-11-02 13:40:56 +00:00
|
|
|
|
2026-11-03 14:36:21 +00:00
|
|
|
The WebSocket server publishes the bundled `counter` behavior once at startup;
|
2026-11-02 14:57:26 +00:00
|
|
|
connecting a client does not publish or reset behavior revisions:
|
2026-11-02 08:31:25 +00:00
|
|
|
|
|
|
|
|
```text
|
2026-11-02 14:19:25 +00:00
|
|
|
runa> let sender = spawn counter 0
|
|
|
|
|
sender = @<actor-reference>
|
|
|
|
|
runa> let receiver = spawn counter 10
|
|
|
|
|
receiver = @<actor-reference>
|
feat!: add structured actor state and messages
Introduce owned portable values with distinct actor references, bounded Rune conversion, JSON REPL literals, and nested reference completion. Preserve isolation and atomic transitions across state, messages, effects, migration, inspection, and TCP clients.
BREAKING CHANGE: protocol v3 replaces integer state and kind/value/target_ref messages with tagged values. Rune handlers now take (state, message) and return (new_state, [(actor_reference, message)]). The REPL send command accepts one JSON message.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-11-02 15:56:03 +00:00
|
|
|
runa> send sender {"op": "send", "value": 5, "target": {"$actor": "receiver"}}
|
2026-11-02 08:31:25 +00:00
|
|
|
message queued
|
|
|
|
|
runa> tick 100
|
2026-11-02 14:19:25 +00:00
|
|
|
runa> inspect sender
|
|
|
|
|
runa> inspect receiver
|
2026-11-02 08:31:25 +00:00
|
|
|
runa> events
|
|
|
|
|
```
|
|
|
|
|
|
2026-11-02 14:19:25 +00:00
|
|
|
Actor references are generated NanoIDs rather than sequential numbers. The
|
|
|
|
|
`let` form binds each spawned actor to a local name; references can also be
|
|
|
|
|
entered directly with an `@` prefix. The sender commits state `1` and sends a
|
|
|
|
|
message to the receiver, which commits state `15`. The REPL provides Tab
|
|
|
|
|
completion and Up/Down command history. It also supports publishing Rune source
|
|
|
|
|
files as named, versioned behaviors, viewing history, rolling back a behavior
|
|
|
|
|
reference, installing the current version on an idle actor, and cooperatively
|
|
|
|
|
pausing and resuming or cancelling actor invocations between scheduler ticks.
|
|
|
|
|
Runtime users can also supply an explicit state migration closure during
|
|
|
|
|
installation; the CLI's install command preserves state as-is. Use `help` in
|
|
|
|
|
the session for the complete command list.
|
feat!: add structured actor state and messages
Introduce owned portable values with distinct actor references, bounded Rune conversion, JSON REPL literals, and nested reference completion. Preserve isolation and atomic transitions across state, messages, effects, migration, inspection, and TCP clients.
BREAKING CHANGE: protocol v3 replaces integer state and kind/value/target_ref messages with tagged values. Rune handlers now take (state, message) and return (new_state, [(actor_reference, message)]). The REPL send command accepts one JSON message.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-11-02 15:56:03 +00:00
|
|
|
State and messages support null, booleans, signed 64-bit integers, strings,
|
|
|
|
|
lists, records, and distinct actor-reference values. `spawn <behavior> <json>`
|
|
|
|
|
sets initial state; `send <actor> <json>` sends any supported value. JSON
|
|
|
|
|
objects of the form `{"$actor": "name-or-@reference"}` embed an actor reference,
|
|
|
|
|
including inside a record or list. See the [runtime guide](docs/runtime.md)
|
|
|
|
|
for Rune conversions and value limits. This is protocol version 3; old
|
|
|
|
|
four-argument Rune handlers and kind/value/target message envelopes must be
|
|
|
|
|
updated to the two-argument handler contract.
|
|
|
|
|
|
2026-11-02 08:31:25 +00:00
|
|
|
See [the feasibility report](docs/rune-feasibility.md) for verified Rune
|
|
|
|
|
capabilities and limitations, and [the runtime guide](docs/runtime.md) for
|
|
|
|
|
the runtime contract.
|
2026-11-01 18:39:19 +00:00
|
|
|
|
2026-11-03 13:52:28 +00:00
|
|
|
## VS Code client
|
|
|
|
|
|
|
|
|
|
With Node.js 22+ and npm installed, run `npm --prefix vscode ci`. In VS Code,
|
|
|
|
|
open this repository and launch **Run Runa Extension** from Run and Debug
|
2026-11-03 14:49:35 +00:00
|
|
|
(F5). Start `mise run start`, then use **Runa: Connect to Local Image**
|
2026-11-03 13:52:28 +00:00
|
|
|
in the Extension Development Host. The **Runa Actors** view in Explorer lists
|
|
|
|
|
actors created through the REPL or another client. Click an actor to inspect
|
2026-11-03 14:36:21 +00:00
|
|
|
it. Server notifications automatically refresh the tree and open snapshots;
|
2026-11-03 14:57:43 +00:00
|
|
|
**Runa: Refresh Image** is also available on demand.
|
|
|
|
|
|
|
|
|
|
The **Runa Behaviors** view shows published behaviors and their revision
|
|
|
|
|
history. Click a behavior for its current source, or expand it to open an older
|
|
|
|
|
revision. **Runa: Open Behavior Source** also offers a revision picker.
|
|
|
|
|
Source documents are read-only and remain unchanged when new revisions appear.
|
2026-11-03 13:52:28 +00:00
|
|
|
|
2026-11-03 14:54:07 +00:00
|
|
|
Use **Runa: Spawn Actor** to choose a behavior and supply JSON initial state.
|
|
|
|
|
Actor context menus offer structured message sending and pause/resume/stop/restart.
|
|
|
|
|
**Runa: Advance Scheduler** explicitly executes ticks; sending alone only queues
|
|
|
|
|
a message. The extension does not start or shut down the image. Disconnecting
|
|
|
|
|
leaves actors in the server. Behavior editing and detailed runtime event
|
|
|
|
|
subscriptions are not implemented yet. See the [extension guide](vscode/README.md)
|
2026-11-03 13:52:28 +00:00
|
|
|
for connection restrictions, snapshot semantics, and tests.
|
|
|
|
|
|
2026-11-01 19:28:32 +00:00
|
|
|
## Development
|
|
|
|
|
|
|
|
|
|
Install [mise](https://mise.jdx.dev/) and run `mise install` to install Tombi.
|
2026-11-03 13:52:28 +00:00
|
|
|
Rust, rustfmt, Clippy, Node.js 22+, and npm must also be available on your PATH.
|
|
|
|
|
Install the extension's locked dependencies with `npm --prefix vscode ci`.
|
2026-11-01 19:28:32 +00:00
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
mise run format
|
|
|
|
|
mise run lint
|
|
|
|
|
mise run test
|
|
|
|
|
mise run pre-commit
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The pre-commit task runs formatting, linting, and tests in that order, stopping
|
|
|
|
|
on the first failure. Run it successfully before committing and review any
|
|
|
|
|
formatter changes. This is a task, not an automatically installed Git hook.
|
|
|
|
|
|
2026-11-03 13:52:28 +00:00
|
|
|
Tombi formats TOML files offline; rustfmt formats all workspace Rust code;
|
|
|
|
|
Prettier formats the extension. Clippy checks all workspace targets with
|
|
|
|
|
warnings treated as errors. Extension checks include strict TypeScript and
|
|
|
|
|
Prettier. The test task runs the Rust workspace tests, extension unit tests,
|
2026-11-03 14:36:21 +00:00
|
|
|
and a TypeScript-to-Rust WebSocket interoperability test.
|
2026-11-03 13:52:28 +00:00
|
|
|
`mise run test-extension-host` additionally downloads VS Code 1.96.4 into an
|
|
|
|
|
ignored test cache and tests the actual inspector commands in an isolated
|
|
|
|
|
Extension Development Host. It requires a graphical display; on headless Linux,
|
|
|
|
|
use `xvfb-run -a mise run test-extension-host`.
|
2026-11-01 19:28:32 +00:00
|
|
|
|
2026-11-01 18:39:19 +00:00
|
|
|
## Project structure
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
.
|
|
|
|
|
├── Cargo.toml
|
|
|
|
|
├── crates/
|
2026-11-03 14:49:35 +00:00
|
|
|
│ ├── runa/ # Image server, protocol dispatcher, WebSocket transport
|
|
|
|
|
│ ├── runa-cli/ # Interactive REPL client
|
feat!: add structured actor state and messages
Introduce owned portable values with distinct actor references, bounded Rune conversion, JSON REPL literals, and nested reference completion. Preserve isolation and atomic transitions across state, messages, effects, migration, inspection, and TCP clients.
BREAKING CHANGE: protocol v3 replaces integer state and kind/value/target_ref messages with tagged values. Rune handlers now take (state, message) and return (new_state, [(actor_reference, message)]). The REPL send command accepts one JSON message.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-11-02 15:56:03 +00:00
|
|
|
│ ├── runa-core/ # Shared stable identities and portable actor values
|
2026-11-02 08:19:04 +00:00
|
|
|
│ ├── runa-actor/ # Actor value contracts
|
2026-11-02 09:08:49 +00:00
|
|
|
│ ├── runa-code/ # Source identities and compile cache
|
2026-11-02 08:19:04 +00:00
|
|
|
│ ├── runa-rune/ # Phase 0 Rune experiments
|
2026-11-02 12:20:45 +00:00
|
|
|
│ ├── runa-runtime/ # Single-worker actor prototype
|
2026-11-02 12:36:32 +00:00
|
|
|
│ ├── runa-image-api/ # Trusted in-process image operations
|
2026-11-02 12:44:33 +00:00
|
|
|
│ ├── runa-protocol/ # Versioned transport-neutral wire DTOs
|
2026-11-03 14:49:35 +00:00
|
|
|
│ └── runa-client/ # Loopback WebSocket client
|
2026-11-01 19:15:00 +00:00
|
|
|
├── docs/
|
|
|
|
|
│ ├── architecture.md
|
2026-11-02 12:36:32 +00:00
|
|
|
│ ├── protocol.md
|
2026-11-01 19:15:00 +00:00
|
|
|
│ └── decisions/
|
|
|
|
|
├── runa-std/
|
|
|
|
|
│ ├── core/
|
|
|
|
|
│ ├── actors/
|
|
|
|
|
│ ├── ui/
|
|
|
|
|
│ └── tools/
|
|
|
|
|
├── scripts/
|
|
|
|
|
├── vscode/
|
|
|
|
|
├── examples/
|
|
|
|
|
└── tests/
|
2026-11-01 18:39:19 +00:00
|
|
|
```
|
2026-11-01 19:15:00 +00:00
|
|
|
|
|
|
|
|
`runa-std/` is reserved for the default Rune scripts loaded into an image.
|
|
|
|
|
`scripts/` is for general-purpose development automation. Root-level `tests/`
|
|
|
|
|
is reserved for system and end-to-end tests; it is not automatically discovered
|
|
|
|
|
by Cargo. Add an explicit runner when those tests are introduced, keeping Rust
|
|
|
|
|
crate integration tests within each crate.
|
|
|
|
|
|
2026-11-02 08:19:04 +00:00
|
|
|
Only the Phase 0 and minimal Phase 1 crates are present. Remaining crates will
|
2026-11-01 19:15:00 +00:00
|
|
|
be added as their functionality is implemented.
|