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-04 03:49:07 +00:00
|
|
|
addresses with an in-memory compile cache. Automatic crash recovery,
|
|
|
|
|
canonicalization, and remote network access are not implemented yet. The
|
|
|
|
|
initial native graphical world client can browse and inspect actors in a
|
|
|
|
|
running local image.
|
2026-11-03 13:52:28 +00:00
|
|
|
A minimal VS Code extension can connect to the local image, list actors, and
|
2026-11-03 17:52:10 +00:00
|
|
|
inspect state, queued/reserved messages, and execution telemetry. Inspection
|
2026-11-03 18:23:43 +00:00
|
|
|
JSON is editable for inactive paused/failed actors; saving restores
|
2026-11-03 17:52:10 +00:00
|
|
|
protected fields with a warning. The image owns mutable, directory-based Rune source files with
|
2026-11-03 16:01:24 +00:00
|
|
|
independent commit history. The CLI exposes source writes, commit/history/rollback,
|
|
|
|
|
reload/become, graceful shutdown, kill, restart, pause/resume, and cancellation through a trusted 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
|
2026-11-03 19:37:05 +00:00
|
|
|
callbacks are not preemptible. The debugger foundation exposes bounded active Rune
|
|
|
|
|
stack frames and exact loaded source through read-only protocol inspection and
|
2026-11-03 19:53:43 +00:00
|
|
|
VS Code's **Inspect Execution Stack...** actor action. Actor-local source
|
2026-11-03 20:14:06 +00:00
|
|
|
breakpoints and bounded step-into/over/out are implemented through the protocol and VS
|
2026-11-03 20:36:30 +00:00
|
|
|
Code actor actions. **Debug Actor** attaches a native VS Code debug session with
|
|
|
|
|
gutter breakpoints, the call-stack view, and bounded toolbar stepping. Continue
|
2026-11-03 20:48:08 +00:00
|
|
|
resumes the actor; scheduler ticks remain explicit. The Variables view exposes
|
|
|
|
|
a read-only committed actor snapshot with expandable state and mailbox.
|
2026-11-03 21:47:18 +00:00
|
|
|
Watch and Debug Console accept snapshot paths such as `actor/committed_state`;
|
2026-11-04 00:57:37 +00:00
|
|
|
they never execute actor code. Frame locals and Rune expression evaluation
|
|
|
|
|
remain unimplemented.
|
2026-11-03 22:40:04 +00:00
|
|
|
Failed actors can also be attached for exception details and retained-snapshot
|
|
|
|
|
inspection without restarting them; post-mortem stacks are not retained.
|
2026-11-04 00:57:37 +00:00
|
|
|
Explicit disk image save/restore is implemented at handler boundaries, including
|
|
|
|
|
sources/history, actor identities, committed state, mailboxes and retained logs.
|
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 16:13:15 +00:00
|
|
|
mise run repl
|
2026-11-02 14:57:26 +00:00
|
|
|
```
|
|
|
|
|
|
2026-11-04 03:49:07 +00:00
|
|
|
To open the initial graphical world client against the same running image:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
mise run world
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The world client connects to `127.0.0.1:3737` by default. Set `RUNA_CONNECT` or
|
|
|
|
|
pass `--connect 127.0.0.1:4000` to select another loopback address. It provides
|
|
|
|
|
actor browsing and inspection, message sending, lifecycle controls, explicit
|
|
|
|
|
scheduler ticks, bounded debugger stepping, source breakpoints,
|
2026-11-04 03:56:26 +00:00
|
|
|
execution-stack inspection, and retained logs. Its source view supports
|
|
|
|
|
editing image sources with optimistic conflict checks, compilation diagnostics,
|
2026-11-04 04:11:36 +00:00
|
|
|
explicit history commits, and revision preview/rollback. Rollback requires
|
|
|
|
|
confirmation and creates a new current source version without deleting history.
|
|
|
|
|
The events view has a manual collection action:
|
2026-11-04 03:56:26 +00:00
|
|
|
collecting events consumes the image's shared event queue, so other clients do
|
|
|
|
|
not receive events collected by the world client. Rune frame locals and
|
|
|
|
|
expression evaluation are not available. The client does not create or embed a
|
|
|
|
|
separate image.
|
2026-11-04 03:49:07 +00:00
|
|
|
|
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 16:13:15 +00:00
|
|
|
use `cargo run -p runa-cli -- --connect 127.0.0.1:4000 repl` and start the server with
|
2026-11-02 14:57:26 +00:00
|
|
|
the corresponding `--listen` address. Quitting the REPL disconnects only that
|
2026-11-03 16:21:41 +00:00
|
|
|
client; actors and source files survive until the server exits. Ctrl+C and
|
|
|
|
|
Ctrl+D also exit the REPL and complete the WebSocket close handshake.
|
2026-11-03 16:13:15 +00:00
|
|
|
Reconnect and use `ps` to recover their references. REPL bindings and
|
2026-11-02 14:57:26 +00:00
|
|
|
command history are session-local and are not restored on reconnect.
|
|
|
|
|
|
2026-11-04 00:57:37 +00:00
|
|
|
### Save and restore an image
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
cargo run -p runa-cli -- save /path/to/image.runa.json
|
2026-11-04 03:30:25 +00:00
|
|
|
cargo run -p runa-cli -- save --overwrite /path/to/image.runa.json
|
2026-11-04 00:57:37 +00:00
|
|
|
cargo run -p runa-cli -- restore /path/to/image.runa.json
|
|
|
|
|
```
|
|
|
|
|
|
2026-11-04 01:03:20 +00:00
|
|
|
To open the snapshot when starting the server, use:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
cargo run -p runa -- --restore /path/to/image.runa.json
|
|
|
|
|
# Alternatively:
|
|
|
|
|
RUNA_RESTORE=/path/to/image.runa.json mise run start
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`--restore` overrides `RUNA_RESTORE`. Startup restoration validates the snapshot
|
|
|
|
|
before accepting clients and does not add or overwrite bundled sources.
|
|
|
|
|
Missing, malformed or incompatible snapshots fail startup rather than silently
|
|
|
|
|
starting a fresh image. Without either option, startup loads the bundled counter
|
|
|
|
|
source as before. Restored actors follow the same status rules as live restore;
|
|
|
|
|
the server does not execute messages until scheduler ticks are requested.
|
|
|
|
|
|
2026-11-04 03:30:25 +00:00
|
|
|
The REPL also accepts `save <file>`, `save --overwrite <file>`, and
|
|
|
|
|
`restore <file>`. VS Code provides
|
2026-11-04 00:57:37 +00:00
|
|
|
**Runa: Save Image...** and **Runa: Restore Image...**. Paths refer to the
|
2026-11-04 03:30:25 +00:00
|
|
|
server's filesystem, not the client's. Saving refuses an existing destination
|
|
|
|
|
unless overwrite is explicitly enabled; VS Code asks before replacing one.
|
|
|
|
|
Replacement atomically swaps in a fully written and synced snapshot.
|
2026-11-04 00:57:37 +00:00
|
|
|
The server captures all actors at a handler boundary and leaves runnable actors
|
|
|
|
|
paused after a successful save. Saving is rejected without changing the image
|
|
|
|
|
if any handler is unfinished, including paused or awaiting execution.
|
|
|
|
|
|
|
|
|
|
Restore replaces the whole image after validating and recompiling the snapshot.
|
|
|
|
|
Actors that were runnable when saved resume scheduling eligibility; previously
|
|
|
|
|
paused and failed actors stay that way. Execution still requires explicit ticks.
|
|
|
|
|
Actor references survive, but incarnations advance and old debug sessions end.
|
|
|
|
|
Restore also refuses to replace an image with unfinished handlers.
|
|
|
|
|
Only saved data survives server exit; this is not an automatic checkpoint,
|
|
|
|
|
durable per-message transaction log, or execution-stack serialization.
|
|
|
|
|
See [runtime persistence guarantees](docs/runtime.md#image-save-and-restore).
|
|
|
|
|
|
|
|
|
|
### Commands and connections
|
|
|
|
|
|
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
|
2026-11-03 16:13:15 +00:00
|
|
|
RUNA_CONNECT=127.0.0.1:4000 mise run repl
|
2026-11-03 14:49:35 +00:00
|
|
|
```
|
2026-11-02 13:18:45 +00:00
|
|
|
|
2026-11-03 16:13:15 +00:00
|
|
|
`runa-cli` requires a subcommand. Use `runa-cli repl` for an interactive session,
|
|
|
|
|
or run an image operation directly:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
cargo run -p runa-cli -- ps
|
2026-11-03 18:23:43 +00:00
|
|
|
actor=$(cargo run -p runa-cli -- spawn actors/counter)
|
|
|
|
|
cargo run -p runa-cli -- send "$actor" '{"op":"inc"}'
|
2026-11-03 16:13:15 +00:00
|
|
|
cargo run -p runa-cli -- tick 100
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Each image operation in the REPL has a matching subcommand; use
|
|
|
|
|
`runa-cli <command> --help` for arguments. Quote JSON as a single shell argument.
|
|
|
|
|
One-shot commands use actor references rather than session-local bindings,
|
|
|
|
|
print results without a REPL banner, and exit unsuccessfully on errors.
|
|
|
|
|
`let name = spawn ...` is session-local REPL syntax. `quit` (alias `exit`)
|
|
|
|
|
exits either interface without stopping the image. `cancel` is no longer a
|
|
|
|
|
REPL command; the underlying runtime cancellation API remains available.
|
|
|
|
|
|
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 16:01:24 +00:00
|
|
|
The server loads the bundled `source/actors/counter.rn` working file at startup.
|
|
|
|
|
Connecting a client does not modify source or create a commit:
|
2026-11-02 08:31:25 +00:00
|
|
|
|
|
|
|
|
```text
|
2026-11-03 18:23:43 +00:00
|
|
|
runa> let counter = spawn actors/counter
|
|
|
|
|
counter = @<actor-reference>
|
|
|
|
|
runa> send counter {"op": "inc"}
|
2026-11-02 08:31:25 +00:00
|
|
|
message queued
|
|
|
|
|
runa> tick 100
|
2026-11-03 18:23:43 +00:00
|
|
|
runa> pause counter
|
|
|
|
|
runa> inspect counter
|
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
|
2026-11-03 18:23:43 +00:00
|
|
|
entered directly with an `@` prefix. The counter treats missing/null state as
|
|
|
|
|
zero on its first message, increments and logs its value, then queues another
|
|
|
|
|
`inc` message to itself. It runs only when ticks advance; pause/resume controls
|
|
|
|
|
its loop. An explicit integer initial state is preserved. The REPL provides Tab
|
2026-11-03 16:01:24 +00:00
|
|
|
completion and Up/Down command history. `write actors/counter <local-file>`
|
|
|
|
|
updates the image's working source. `commit actors/counter` records a snapshot
|
|
|
|
|
with an automatically generated readable revision ID; `history actors/counter`
|
|
|
|
|
lists commits and `rollback actors/counter <revision>` restores a working file.
|
|
|
|
|
Committing is version control only: spawn always compiles the current image
|
|
|
|
|
file, including uncommitted changes. Invalid working code fails spawn without
|
|
|
|
|
creating an actor; commits can preserve invalid work in progress.
|
|
|
|
|
`reload <actor>` loads current source at its existing path, and
|
|
|
|
|
`become <actor> <path>` switches scripts, preserving state and queued messages
|
|
|
|
|
after the active handler completes. `stop` runs optional `on_shutdown(state)`
|
2026-11-03 18:23:43 +00:00
|
|
|
after the active handler and then removes the actor; `kill` removes it
|
|
|
|
|
immediately without shutdown. Removal discards identity, state, mailbox, and
|
|
|
|
|
retained logs. Failed actors remain inspectable until killed. `restart` creates
|
2026-11-03 16:01:24 +00:00
|
|
|
a new incarnation with the same state and loaded script, without reloading.
|
2026-11-03 18:23:43 +00:00
|
|
|
Restart is independent of stop/kill; a removed actor cannot be restarted.
|
2026-11-03 16:01:24 +00:00
|
|
|
Pause/resume remain cooperative controls between scheduler slices. Use `help` in
|
2026-11-02 14:19:25 +00:00
|
|
|
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,
|
2026-11-03 16:01:24 +00:00
|
|
|
lists, records, and distinct actor-reference values. `spawn <path> <json>`
|
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
|
|
|
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)
|
2026-11-03 17:26:21 +00:00
|
|
|
for Rune conversions and value limits. Protocol version 5 uses
|
2026-11-03 16:01:24 +00:00
|
|
|
`handle(ctx, state, sender, message) -> new_state`; `ctx.send(recipient, message)`
|
|
|
|
|
records sends with the calling actor as sender, and
|
|
|
|
|
`ctx.send_from(sender, recipient, message)` supports forwarding.
|
2026-11-03 18:00:18 +00:00
|
|
|
Returning state is optional: an omitted return, `return;`, or `()` retains the
|
|
|
|
|
previously committed state, discarding invocation-local state mutations.
|
|
|
|
|
Valid sends still commit and the message is acknowledged. The same rule applies
|
|
|
|
|
to `on_shutdown(state)`. To replace state, return a non-unit portable value.
|
|
|
|
|
Unit can no longer be used to reset state to null; use host state editing instead.
|
2026-11-03 16:01:24 +00:00
|
|
|
Sender metadata is separate from message data; host-originated messages have
|
|
|
|
|
unit/null sender. System messages are trusted runtime commands, not data an
|
|
|
|
|
actor can construct.
|
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
|
|
|
|
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 16:49:04 +00:00
|
|
|
in the Extension Development Host. Open the **Runa** Activity Bar sidebar.
|
|
|
|
|
Its **Actors** view lists
|
2026-11-03 19:11:39 +00:00
|
|
|
actors created through the REPL or another client as expandable directories.
|
|
|
|
|
Open `meta.json` for read-only identity/status/behavior-path metadata,
|
|
|
|
|
`config.json` for live log-level configuration, `state.json` for natural JSON
|
2026-11-03 19:20:00 +00:00
|
|
|
state, `mailbox.json` for reserved/queued messages, or `actor.log` for retained logs.
|
|
|
|
|
State and mailbox JSON use two-space indentation and preserve exact integers.
|
|
|
|
|
The `.log` file uses syslog-style lines and VS Code's built-in log highlighting.
|
2026-11-03 19:11:39 +00:00
|
|
|
State and mailbox files are writable only for inactive paused/failed actors.
|
|
|
|
|
Server notifications automatically refresh the tree and open files;
|
2026-11-03 14:57:43 +00:00
|
|
|
**Runa: Refresh Image** is also available on demand.
|
|
|
|
|
|
2026-11-03 16:49:04 +00:00
|
|
|
The **Image Sources** view in the Runa sidebar automatically shows the image's virtual
|
2026-11-03 16:37:31 +00:00
|
|
|
filesystem beneath **source**, including `actors/counter.rn`, without adding a
|
|
|
|
|
workspace folder. Open a file and save edits to update the image without
|
2026-11-03 16:01:24 +00:00
|
|
|
committing. Right-click a source file to **Spawn** (null state) or **Spawn with
|
2026-11-03 16:37:31 +00:00
|
|
|
State** (which prompts for JSON), or to commit, browse history, and roll back. Historical revisions
|
2026-11-03 16:01:24 +00:00
|
|
|
remain read-only.
|
2026-11-03 19:11:39 +00:00
|
|
|
The source toolbar and context menus support creating, renaming/moving, and
|
|
|
|
|
deleting files. Renaming an in-use behavior asks to update every actor using its
|
|
|
|
|
path; declining cancels the rename. Deleting a source used by a running actor
|
|
|
|
|
is rejected with a stop-first error.
|
|
|
|
|
|
|
|
|
|
**Edit Current Behavior** on an actor opens its loaded script (or existing
|
|
|
|
|
temporary script). Saving compiles an actor-specific override and installs it
|
|
|
|
|
at the next handler boundary without changing shared source, state, or mailbox.
|
|
|
|
|
A `behavior` file then appears inside the actor directory. **Reload Actor Source**
|
|
|
|
|
clears the override, **Go to Behavior** opens the shared source, and **Update Behavior**
|
|
|
|
|
asks before copying the temporary text into shared working source without committing.
|
2026-11-03 13:52:28 +00:00
|
|
|
|
2026-11-03 16:01:24 +00:00
|
|
|
Use **Runa: Spawn Actor** to choose a source path and supply JSON initial state.
|
|
|
|
|
Actor context menus offer structured messages and system lifecycle commands.
|
2026-11-03 14:54:07 +00:00
|
|
|
**Runa: Advance Scheduler** explicitly executes ticks; sending alone only queues
|
|
|
|
|
a message. The extension does not start or shut down the image. Disconnecting
|
2026-11-03 19:28:56 +00:00
|
|
|
leaves actors in the server. Detailed runtime event subscriptions and source-level
|
|
|
|
|
debugging are not implemented yet. Rune compilation errors and warnings
|
|
|
|
|
appear inline and in Problems for open image sources and actor-specific behavior
|
|
|
|
|
documents, including unsaved edits. Validation does not save, commit, or install
|
|
|
|
|
the editor text. See the [extension guide](vscode/README.md)
|
2026-11-03 13:52:28 +00:00
|
|
|
for connection restrictions, snapshot semantics, and tests.
|
|
|
|
|
|
2026-11-03 17:26:21 +00:00
|
|
|
## Repairing actors and reading logs
|
|
|
|
|
|
2026-11-03 18:23:43 +00:00
|
|
|
State and messages can be edited only on paused or failed actors with
|
|
|
|
|
no active invocation. An active handler must finish or be cancelled through the
|
|
|
|
|
runtime cancellation API; kill removes the actor rather than making it editable. State
|
2026-11-03 17:26:21 +00:00
|
|
|
edits preserve messages; message edits preserve state. Neither restarts an actor.
|
|
|
|
|
Reserved messages are retried first on restart; clearing the reserved array
|
|
|
|
|
removes the failed input.
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
set-state @<actor-ref> 1
|
|
|
|
|
set-messages @<actor-ref> {"reserved":[],"queued":[{"op":"add","value":2}]}
|
|
|
|
|
log-level @<actor-ref> debug
|
|
|
|
|
logs @<actor-ref>
|
|
|
|
|
logs -f
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
These are REPL commands and `runa-cli` subcommands (quote JSON when using a shell).
|
|
|
|
|
REPL log filters also accept session-local actor names. Omitting the filter selects all
|
|
|
|
|
actors. `logs` prints retained history; `logs -f` additionally subscribes to
|
|
|
|
|
future entries until Ctrl+C, which returns to the REPL or closes a one-shot CLI.
|
|
|
|
|
In VS Code, actor context menus offer **Edit Actor State...**,
|
|
|
|
|
**Edit Reserved and Queued Messages...**, and **Set Actor Log Level...**.
|
2026-11-03 19:11:39 +00:00
|
|
|
The actor directory provides editable state/mailbox files and a `config.json`
|
|
|
|
|
that remains writable while running. The **Inspect Actor** command also retains
|
|
|
|
|
the combined JSON editor; protected fields there are restored with a warning.
|
|
|
|
|
The Actors toolbar advances the scheduler,
|
2026-11-03 17:52:10 +00:00
|
|
|
and **Copy Actor Reference** copies a reference from the actor context menu.
|
2026-11-03 17:26:21 +00:00
|
|
|
|
|
|
|
|
Rune handlers can call `ctx.log("info", "message")`, or `ctx.trace`, `ctx.debug`,
|
|
|
|
|
`ctx.info`, `ctx.warn`, `ctx.error`, and `ctx.fatal` with a string message.
|
|
|
|
|
Severity order is trace < debug < info < warn < error < fatal; the default
|
|
|
|
|
threshold is info. Only entries at or above the actor's threshold are retained
|
|
|
|
|
or emitted. Logs are immediate diagnostics, not transactional effects: they
|
|
|
|
|
survive handler failure and may repeat on retries. Each actor keeps its latest
|
|
|
|
|
1,000 accepted messages in memory, each limited to 512 UTF-8 bytes. Restart
|
|
|
|
|
preserves logs and the threshold. Server exit loses them. Rebuild the server,
|
|
|
|
|
CLI, and extension together for protocol v5.
|
|
|
|
|
|
2026-11-03 17:52:10 +00:00
|
|
|
The read-only `ctx.this` field is the current actor's typed reference:
|
|
|
|
|
`ctx.send(ctx.this, message)` queues a normal transactional message to itself.
|
|
|
|
|
|
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.
|