Skip to content

Releases: arcships/rutis

rutis v0.10.0

Choose a tag to compare

@github-actions github-actions released this 13 Oct 01:07
ea487b2

rutis 0.10.0

中文 · 0.9.1 release notes

0.10.0 is a quality release. Following the second quality step, it adds tests across processes and platforms and fixes the defects those tests found. It adds three features: a format version in rutis.json, link states and listening addresses in rutis-host run, and runtime output passed on a whole line at a time. Everything else is fixes. A few behaviours now fail explicitly; see "Compatibility".

Packages

All of these are at 0.10.0:

Registry Packages
crates.io rutis (the core), rutis-bridge, rutis-loader, rutis-host; the dylib toolchain rutis-sdk, rutis-dylib, rutis-dylib-meta, rutis-dylib-launcher
npm @arcships/rutis, @arcships/rutis-runtime, @arcships/rutis-bun, @arcships/rutis-host, and the five platform host packages
PyPI rutis, rutis-host
Go github.com/arcships/rutis/go/rutis (tag go/rutis/v0.10.0)
GitHub rutis-host binaries for Linux / macOS (x64 / arm64) and Windows (x64), with SHA-256 files

rutis-cli is still released on its own.

New

  • A format version in rutis.json (#207): top-level "format": 1. It can be left out, and a file without it reads as format 1, so existing files need no change. When a file's format is newer than the one rutis-host supports, rutis-host refuses it before reading any other field and says to upgrade rutis-host. rutis-host new writes the field. Every released rutis.json since 0.8.0 is kept as a sample, and tests check that each still reads as it did. dsh's cordis.patch.yml is Cordis's configuration format and gets no version.
  • rutis-host run prints link states and listening addresses (#321): at start, each listener prints the address it actually bound: rutis-host: listening on <name> <address>. When the link of a node row changes state, rutis-host prints one line: link connected, link down (<reason>); retrying in …, link refused: auth-rejected (<reason>), or link stopped: incompatible (<reason>). You can now tell from the output whether a token was refused, a certificate was not trusted, or the far end is not up. Tokens never appear in the output.
  • Runtime output is passed on a whole line at a time (#332): each line that a Node, Bun, Python or Go runtime writes to stdout or stderr appears whole and unchanged on the same stream of rutis-host. It no longer runs into rutis-host's own lines, even when a plugin writes a line in several pieces. Runtimes now see pipes, not a terminal, on stdout and stderr, so libraries that choose colours by whether they write to a terminal print without colours. On the Rust side, Stdio::Lines is new; the library default is still Inherit.
  • A protocol version mismatch says which end to upgrade (#293): in all five implementations (Rust, Node, Bun, Python, Go), handshake refusals and WebSocket subprotocol refusals name the end to upgrade and its package. The error category is still incompatible.

Fixes

Values across processes

  • A value may nest at most 64 levels deep (#279). Before, a value deeper than serde_json's recursion limit on the receiving side ended the whole session, so every other call on it failed. Now the side that sends the value checks it before sending, and a value nested too deep fails only that call; the session goes on.
  • Floating-point numbers reach the Rust side bit for bit (#290). Before, they could change by one or two ULPs.
  • On Node 24 and later, JSON.parse reads some object keys that contain escapes as other keys (#302). The Node runtime now works around it, so plugins no longer receive silently changed values.
  • The Go runtime ends the session on a frame with invalid UTF-8 (#294), as the other runtimes do. Before, it replaced the invalid bytes with U+FFFD and went on.
  • When Python sends an integer outside ±(2^53−1), that call fails explicitly (#356). Before, nothing checked it: integers over 2^64 silently became floats when relayed through Rust, and integers over 2^53 were not exact on the JS and Go sides either. The limit is the same as in JS and Go.

Sessions and links

  • When a call chain crosses processes over links, a process no longer takes another process's calls for its own (#325). Session tags are now unique across processes; the wire format is unchanged.
  • When a client certificate is invalid, the listener sends its TLS alert before it closes the connection (#300). The dialer now gets AuthRejected on Windows too, instead of a connection reset.
  • On macOS, the system sometimes killed a runtime process (SIGKILL) as it started (#287). This happened when another thread was initialising libnotify during a fork. rutis now finishes that initialisation before its first fork. The problem appeared on macOS 26 and 27.

Boundary rules of Cordis plugins (#281, #282)

  • A synchronous bail on the Cordis side for an event forwarded to rutis now fails explicitly and suggests serial. Before, it silently got a Promise.
  • When a waterfall passes through the rutis side, rutis's listeners run as one asynchronous step, and the chain goes on to the listeners after it on the Cordis side.
  • A mount that lists an internal/* event in events or emits fails, with the error reported before the process starts.

Core and loader

  • A failed plugin is retried only when its dependencies actually change (#327). Before, repeated notices about the same dependencies could load it again, and it could stay in Loading.
  • The inject and listener lists under one key shrink back once they hold fewer entries (#291).
  • Go runtimes: a restart whose caller stopped waiting still finishes, so two processes of the same name no longer run at once (#307). The manifest of a binary that was just replaced is read again when the first read failed, and ETXTBSY on Linux is retried (#306).
  • rutis-host reports that it has started only after its runtimes have actually let their rows through (#314).
  • When the host is killed (kill -9), its runtimes exit too (#353). Before, on Unix, a Node runtime kept running whenever a plugin left a timer, and a cleanup that never returned made the Node, Bun and Python runtimes hang. Now, once the session ends, all four runtimes unload their rows within a deadline and exit. The deadline is rutis-host's --shutdown-timeout, passed to the runtimes in the environment variable RUTIS_SHUTDOWN_TIMEOUT, 10 seconds by default. Past it, the remaining cleanups are given up and the exit code is 1.

Python

  • On CPython 3.13.6, listen("wss://…") refuses to start (#304). That patch release has an SSL regression (python/cpython#137583) that hangs every TLS connection. Use 3.13.7 or later. ws:// is not affected.

Tests and quality

Most of the work in this release went into tests, which bring no direct change for users. This section only lists what they cover:

  • End-to-end scenarios: real rutis-host processes with probe plugins in every language. They cover the plugin development loop, combinations of languages and runtime crashes, moving an implementation, nodes in two separate processes, and running right after installing. They run on Linux, macOS and Windows.
  • The conformance suites have Windows and loopback columns. Fault injection is wired into sessions and links. There are negative TLS tests, and property tests for values crossing languages and for reference release counts.
  • The testing tools (@arcships/rutis/testing, rutis.testing) and the real runtimes are checked against the same expectations file (#206).
  • Core guarantees are covered: event order, lifecycle and reclamation. Assertions no longer depend on the real clock, and randomised tests take a seed.
  • The guarantee registry records rutis's core promises and contract behaviours, and the tests that verify them. 0.10 publishes it as a baseline; from 0.11 on, it is checked before every release.

Compatibility

  • Protocol versions are unchanged: local sessions are still protocol 2, sessions with endpoint identities protocol 3, and PLUGIN_API is still 1. 0.9 and 0.10 hosts and runtimes work together. Only between two 0.9 processes is #325 still possible.
  • rutis.json: files from 0.10's rutis-host new have "format": 1. A 0.9 rutis-host does not know the field and reports it as an unknown field. To read such a file with 0.9, delete that line.
  • Behaviours that now fail explicitly:
    • A synchronous bail from Cordis on an event forwarded to rutis throws (support to come: #358).
    • A mount that lists internal/* fails (support to come: #359).
    • A value nested more than 64 levels deep cannot cross processes.
    • A wss:// listener cannot start on ...
Read more

rutis v0.9.1

Choose a tag to compare

@github-actions github-actions released this 11 Oct 12:39
ebf0711

rutis 0.9.1

中文 · 0.9.0 release notes

0.9.1 fixes the launcher in the npm package @arcships/rutis-host: one Ctrl-C in a terminal made rutis-host exit at once without running cleanups (#267). The other packages have no changes and move to 0.9.1 only to stay on the train.

Fixes

  • The npm launcher no longer forwards Ctrl-C: npx rutis-host … and a project's node_modules/.bin/rutis-host are a Node launcher, which forwarded every signal it got to rutis-host. A terminal already sends Ctrl-C to the whole process group, so rutis-host got it twice and took the second as "exit at once": plugin cleanups did not run, runtime processes were killed, and the exit code was 2. The launcher now leaves SIGINT and SIGHUP to rutis-host (it gets them itself) and forwards only SIGTERM (which service managers and docker stop send to the main process alone). On Windows, forwarding Ctrl-C used to terminate rutis-host outright; the launcher now forwards nothing, and rutis-host handles the console events itself.
  • A SIGINT or SIGHUP sent to the launcher's pid alone (kill -INT <pid>) no longer reaches rutis-host; send SIGTERM instead.

uvx rutis-host, rutis-host installed from PyPI, and the binaries on the release page are not affected.

Packages

All of these are at 0.9.1: on crates.io rutis, rutis-bridge, rutis-loader, rutis-host, rutis-sdk, rutis-dylib, rutis-dylib-meta, rutis-dylib-launcher; on npm @arcships/rutis, @arcships/rutis-runtime, @arcships/rutis-bun, @arcships/rutis-host and the five platform packages; on PyPI rutis, rutis-host; the Go module github.com/arcships/rutis/go/rutis (tag go/rutis/v0.9.1); the rutis-host binaries on the release page.

Compatibility

  • Fully compatible with 0.9.0: no API, protocol or configuration changes; 0.9.0 and 0.9.1 hosts and runtimes work together.
  • Projects that install rutis-host from npm should upgrade; other setups can stay on 0.9.0.
  • Dylib: the SDK identity includes the package versions in its dependency tree. After rebuilding the SDK and the host with 0.9.1, dylib plugins built for 0.9.0 must be rebuilt with the new SDK; keeping the existing SDK bundle is unaffected.

rutis v0.9.0

Choose a tag to compare

@github-actions github-actions released this 11 Oct 10:56
d4999aa

rutis 0.9.0

中文 · Migration guide

0.9.0 adds Bun and Go as plugin runtimes. The host refuses a synchronous call that would close a wait cycle across runtimes, rutis-host check finds services nothing provides, and stopping and local channels are more reliable. The minimum Python goes down to 3.10 and the minimum Node to 22.

Packages

All of these are at 0.9.0:

Registry Packages
crates.io rutis (the core), rutis-bridge, rutis-loader, rutis-host; the dylib toolchain rutis-sdk, rutis-dylib, rutis-dylib-meta, rutis-dylib-launcher
npm @arcships/rutis, @arcships/rutis-runtime, @arcships/rutis-bun (first release), @arcships/rutis-host, and the five platform host packages
PyPI rutis, rutis-host
Go github.com/arcships/rutis/go/rutis (first release, tag go/rutis/v0.9.0)
GitHub rutis-host binaries for Linux / macOS (x64 / arm64) and Windows (x64), with SHA-256 checksums

rutis-cli keeps its own version.

What's new

  • Bun runtime (@arcships/rutis-bun, Bun 1.4+): JavaScript and TypeScript plugins can run in Bun; plugin code still uses @arcships/rutis. The host takes runtimes.bun, rutis-host new --lang bun creates a project, and rutis-host dev recognizes Bun projects and reloads them. In Rust: Launcher::bun / LocalRuntime::bun (feature bun) and the loader's bun:<module> rows. Synchronous calls are re-entrant. A plugin with a syntax error is reported with file:line:column. Remote listening and Windows come in a later release.
  • Go runtime (go/rutis, Go 1.24+): a Go plugin is compiled into a binary, and each binary is one runtime with only the standard library as a dependency. Write plugins with Define / Plugin[C] / Serve; the config struct gives the JSON Schema, --rutis-manifest prints the manifest, and rutistest tests plugins. The host takes runtimes.go (dir / binaries / start / idle) and starts a runtime when a row needs it and stops it when idle; rutis-host new --lang go, rutis-host go add <module>@<version>; dev builds Go projects and restarts only the Go runtime. In Rust: Launcher::go / LocalRuntime::go and the loader's GoResolver / GoRuntimes (feature go).
  • Wait cycles across runtimes: before forwarding a synchronous call, the host checks who waits for whom; a call that would close a cycle (for example Python → Node → Python, each waiting synchronously) fails with SyncWaitCycle instead of deadlocking. The Node, Python and Bun runtimes declare sync-wait. A nested call's origin carries a session label, so nested calls such as Python → Node → Python now complete.
  • rutis-host check: without running plugins, it checks that every service a row injects is provided by some row, and exits with 1 when one is not (when the provider is on another node, it only notes it). Disabled rows are no longer resolved. In Rust: Loader::check. It also prints each runtime's implementation and engine, and the Go binaries.
  • Stopping and signals: run / dev handle SIGINT / SIGTERM / SIGHUP (Ctrl-C / Ctrl-Break / closing the console on Windows), unload the rows and exit. --shutdown-timeout <seconds> (or RUTIS_SHUTDOWN_TIMEOUT, 10 by default) bounds the cleanup, and the exit code is 2 when it did not finish. Runtime processes run in their own process group, so Ctrl-C in the terminal reaches only the host.
  • A runtime process's standard streams: stdin / stdout / stderr on Launcher / LocalRuntime can each be Stdio::Null or Stdio::Inherit, for example to give stdin to a plugin that reads the terminal.
  • A plugin that disposes itself: when a plugin in a Node row unloads itself, the host gets SelfDisposed and the row becomes disabled (a copy in an instance becomes Stopped) instead of staying shown as running. New: the rows.ended message and Process::on_row_ended.
  • Local channels: one message is at most 16 MiB (the same in Rust and every language runtime); a larger one closes the channel, and a stream that ends in the middle of a message is a failure everywhere.
  • Configuration: with rutis.json given as a relative path, rows such as ./plugin.mjs now resolve against the configuration file; unknown fields in rows are warned about; a listener with only cert or only key is an error instead of silently running without TLS; runtime names must be unique.
  • Python (3.10 minimum): on 3.10 / 3.11 rutis starts plugin methods eagerly itself, the same way as the native implementation on 3.12+. A cancel that arrives during a plugin method's first step is no longer ignored; a WebSocket listener whose accept() fails ends as a failure; python -m rutis prints an error and exits with 1; Listener.close() works with websockets older than 17. The optional network dependency needs websockets 15+.
  • Other fixes:
    • Child processes inherit only fds 0–3, which fixes occasional Broken pipe errors and hangs when runtimes start concurrently on macOS.
    • A process that ends has its exit status reported, including one that closed its channel but has not exited after 10 s, and how it ended when a send fails.
    • A protocol version mismatch reliably gives Handshake::Incompatible on both sides.
    • Calling the root's dispose() and Ctx::shutdown() at the same time no longer makes dispose() return Closed now and then.
    • A crashed Go runtime is Down instead of staying "Starting".

Compatibility

  • Upgrade the host and the language runtimes to 0.9 together: protocol versions are unchanged (local sessions use protocol 2, sessions with endpoint identity protocol 3) and PLUGIN_API is still 1, but a 0.9 host forwards call origins with a session label that 0.8 runtimes do not accept; they end the session.
  • Rust API: Launcher and Spawn in rutis-bridge are #[non_exhaustive], and RowSchema has a new field version; rutis and rutis-loader have no incompatible changes. Dylib plugins must be rebuilt with the 0.9.0 SDK.
  • rutis-host: check fails on a service nothing provides; exit code 2 is new.
  • Minimum versions: Rust 1.88 (was 1.85), Node 22 (was 24), Python 3.10 (was 3.12), Bun 1.4, Go 1.24.

See the migration guide.

Getting started

npx @arcships/rutis-host@0.9.0 new greeter --lang node
npx @arcships/rutis-host@0.9.0 new greeter-bun --lang bun
npx @arcships/rutis-host@0.9.0 new greeter-go --lang go
uvx --from rutis-host==0.9.0 rutis-host new greeter-py --lang python

Then read TypeScript plugins, Bun plugins, Python plugins, Go plugins, embedding in Rust or connecting nodes.

rutis v0.8.0

Choose a tag to compare

@github-actions github-actions released this 08 Oct 14:29
d6ba86a

rutis 0.8.0

中文 · Migration guide

0.8.0 adds native Windows support and per-instance plugin management, and brings the core and the dylib toolchain into the release train: from this release on, every rutis package shares one version number.

Packages

All of these are at 0.8.0:

Registry Packages
crates.io rutis (the core), rutis-bridge, rutis-loader, rutis-host; the dylib toolchain rutis-sdk, rutis-dylib, rutis-dylib-meta, rutis-dylib-launcher (first release on crates.io)
npm @arcships/rutis, @arcships/rutis-runtime, @arcships/rutis-host, and the five platform host packages
PyPI rutis, rutis-host
GitHub rutis-host binaries for Linux / macOS (x64 / arm64) and Windows (x64), with SHA-256 checksums

The core has no code changes; it moves from 0.6.1 straight to 0.8.0 to line up with the train. rutis-cli keeps its own version.

What's new

  • Native Windows (x64, MSVC): embedded in Rust, Node / Python language runtimes, remote runtimes and cross-language shared services run on Windows. A local runtime gets its channel over a loopback address with a one-time token. Runtime processes join a Job Object that closes with the host, so none outlives the host however it exits. Exit reasons are reported as RuntimeState::Down as usual. The Process::launch / Process::mount compatibility API and the Cordis mount bindings generated with it start their runtimes the same way. The rutis-host command runs on Windows too: a release binary, npx @arcships/rutis-host (@arcships/rutis-host-win32-x64) and uvx rutis-host (a Windows wheel); it finds a project's virtual environment at .venv\Scripts\python.exe and uses python otherwise.
  • Instanced groups: the loader manages plugins inside instances the application creates at runtime, for example one set per session. Set instanced: true on a group and manage instances with create_instance / remove_instance / restart_instance. Configuration edits, reload and restart reach every copy; if any copy fails, the change is rolled back.
  • Service names inside instances: a service name can belong to a kind of instance and resolve to each instance's own key. Configuration and plugin code (Rust, TypeScript, Python) write only the name. Language runtimes and node links are isolated per instance.
  • Fixes:
    • A local process that exits right after starting reports its exit status on send too, not just Broken pipe.
    • Another local process that connects to the loopback listener and sends nothing no longer delays the runtime's start.
    • The Python runtime now applies a row's isolate.
  • Release: the two PyPI projects are published from separate environments.

Compatibility

A few public Rust APIs changed incompatibly: Resolved is now built with Resolved::new; EntryStatus gains Stopped and Handover gains Loopback; EntryStatus, EntryInfo, InstanceInfo, Handover and Resolved are #[non_exhaustive], so later fields and variants are no longer breaking changes. Dylib plugins must be rebuilt with the 0.8.0 SDK. See the migration guide.

Protocol versions are unchanged: local sessions use protocol 2, sessions with endpoint identity protocol 3. Use the same train version for the host and the language runtimes; instance services need 0.8 runtimes. Node 24+ and Python 3.12+ are required.

Getting started

npx @arcships/rutis-host@0.8.0 new greeter --lang node
uvx --from rutis-host==0.8.0 rutis-host new greeter-py --lang python

Then read TypeScript plugins, Python plugins, embedding in Rust or connecting nodes.

rutis v0.7.0

Choose a tag to compare

@github-actions github-actions released this 06 Oct 14:11
e607e4f

rutis 0.7.0

中文 · Migration guide

0.7.0 is the first release of the release train: the plugin control plane, language runtimes and networked nodes in one developer workflow. With rutis-host, TypeScript, JavaScript and Python authors can scaffold, check, run and reload plugins without writing a Rust host.

Packages

These packages are versioned 0.7.0 and build on the rutis core 0.6.1:

Registry Packages
crates.io rutis-bridge, rutis-loader, rutis-host
npm @arcships/rutis, @arcships/rutis-runtime, @arcships/rutis-host, and four platform host packages
PyPI rutis, rutis-host
GitHub rutis-host binaries and SHA-256 checksums for Linux/macOS, x64/arm64

The rutis core is not part of this release and stays at 0.6.1. rutis-cli, the agent examples, aimux-llm and dylib tools keep their own versions.

What's in it

  • Plugin control plane: layered configuration, dynamic edits, persistence, service catalogs, expressions, multiple plugin sources, volatile configuration and self-disposal through rutis-loader.
  • Language plugins: JS/TS and Python leaf plugins, named runtimes, service sharing, lifecycle cleanup, cross-session references and module refresh.
  • Remote runtimes: loader rows on other machines, controller leases, release and takeover.
  • Nodes: shared connections, service imports/exports, hosted plugins, events, multi-hop calls and reconnection.
  • Transports: local and inherited Unix sockets, in-memory channels, WebSocket with TLS, authentication and shared listeners.
  • Standalone host: rutis-host new, check, run and dev, with matching Node/Python project templates.
  • Guides and validation: Chinese/English role-based guides, channel/session/runtime/node conformance suites, and reconnect/process-lifecycle soak tests.

Compatibility

rutis-interop is folded into rutis-bridge, and the old packages are no longer updated. The npm SDK and runtime are now @arcships/rutis and @arcships/rutis-runtime. Users of the old packages must migrate dependencies, imports, features and generated bindings using the migration guide. Hosts and language runtimes should come from the same train version.

Package versions are separate from protocol versions: local sessions use protocol 2; endpoint sessions use protocol 3.

rutis-host and local language runtimes support Linux/macOS; use WSL on Windows. Node 24+ and Python 3.12+ are required.

Getting started

npx @arcships/rutis-host@0.7.0 new greeter --lang node
uvx --from rutis-host==0.7.0 rutis-host new greeter-py --lang python

Read the developer guides for plugins, embedding and networking.

rutis 0.6.0

Choose a tag to compare

@eric8810 eric8810 released this 02 Oct 08:10
114189a

rutis 0.6.0

This release is for the rutis core crate. rutis-cli binary releases are unaffected by this tag.

Highlights

  • Public types that keep growing are #[non_exhaustive]: errors (CordisError, ServiceReadFailure, ServiceWriteFailure, DisposeWaitError, ServiceReadError, ServiceWriteError), diagnostics and observation records (RuntimeDiagnostics, PluginDiagnostics, DependencyDiagnostics, DependencyStatus, ResolvedDependency, ServiceAccess, BindingDiagnostics, EffectMeta, DispatchAttempt, DispatchMode, FiberStatusChanged) and EventOptions. Adding fields or variants to them is no longer a breaking change. (#84)
  • EventOptions::default().prepend(true).once(true) builds registration options outside the crate.
  • Same-key emit backlogs are visible: RuntimeDiagnostics::event_backlogs lists, per event key, the accepted emits not yet finished and how long the oldest has waited (EventBacklog). Backpressure is deliberately not added; see the performance notes. (#90)
  • Fix: root shutdown cancels descendants before draining instance events, so a listener waiting for its owner's cancellation no longer keeps shutdown waiting. (#79)
  • The development handbook's examples compile as doctests. (#78)
  • Releases check semver against the previous crates.io version before publishing.

See the 0.5 → 0.6 migration guide.

Compatibility notes

  • Build EventOptions with EventOptions::default() and its setters instead of a struct literal.
  • match on the errors and on DependencyStatus / DispatchMode needs a wildcard arm.
  • Destructuring the diagnostics and observation records needs ..; field access is unchanged. Snapshot, FiberState, EffectPhase and Effect are unchanged.
  • The dylib SDK moves to rutis-sdk 0.4.0; hosts and plugins must be rebuilt together.

Install with cargo add rutis@0.6.0.

rutis-interop 0.1.0

Choose a tag to compare

@eric8810 eric8810 released this 02 Oct 08:10
114189a

rutis-interop 0.1.0

First release of rutis-interop: mount published Cordis (Node) plugins in rutis applications across processes, with Rust bindings generated from the plugins' type declarations at build time.

  • crate rutis-interop 0.1.0 on crates.io (depends on rutis 0.6)
  • npm runtime @arcships/rutis-interop 0.1.0, published with provenance

Both are released together from the same tag and must speak the same protocol version (checked at build time). Unix only; Node 26 or later.

Highlights

  • Declare mounts in Cargo.toml ([package.metadata.rutis-interop]) and call rutis_interop::build::from_manifest() in build.rs; each mount becomes a module with a Plugin, typed service proxies, events and host-service traits.
  • Services in both directions: Cordis services become ordinary rutis services; the rutis application can provide services the mounted plugins inject.
  • Live objects, callbacks, cancellation by dropping futures, events in both directions, group mounts, crash handling (services are withdrawn when the Node process ends).
  • Relocatable deployments: RUTIS_INTEROP_ROOT names a deployed copy of the npm project.

Getting started: the rutis-interop guide (Chinese). crates/rutis-dsh runs the full dsh web UI in a rutis host with it.

rutis 0.5.0

Choose a tag to compare

@eric8810 eric8810 released this 28 Sep 06:49
ace04fe

rutis 0.5.0

This release is for the rutis core crate. 0.4.0 was never published; its content ships here as 0.5.0. rutis-cli binary releases are unaffected by this tag.

Highlights

  • Typed EventKey<E> unifies default, named and instance channels behind one set of methods: on, once, emit, parallel, serial, waterfall all take a key; EventKey::named builds const static keys without allocation.
  • EventPattern<E>::prefix("room/") subscribes to groups of dynamic names; PatternListener receives the actually matched key, and patterns share registration order with exact listeners (prepend, once).
  • Synchronous decision points: events implementing SyncEvent use on_sync + bail_sync and on_waterfall_sync + waterfall_sync; terminals are local FnOnce and may borrow stack variables or MutexGuard. Same-thread reentry on the same full key returns ReentrantEvent.
  • EventOptions gains once; emit now reports whether the call was admitted, and instance out-of-range/closed become errors.
  • Service strict declared reads and mutable-write/strict-read interception; labeled effect ownership tree; dispatch observation before listener selection (nested dispatch from observer reentry supported).
  • Fixes: replaced and candidate StoredValue dropped outside framework locks, nested failure causes in Display, early cleanup error consumption, instance subtree follow-ups, notification error routing to ErrorSink.
  • Workspace additions: Linux dylib SDK (rutis-sdk 0.3.0, rutis-dylib, rutis-dylib-launcher) with pre-execution and pre-dlopen verification.

See the 0.3 → 0.5 migration guide for the full API mapping and semantics.

Compatibility notes

  • on(ctx, listener) becomes on(ctx, &EventKey::of(), listener); the old *_keyed / *_instance methods remain as deprecated wrappers (since 0.5.0).
  • Direct EventOptions construction needs once: false or ..Default::default().
  • DispatchMode gains BailSync / WaterfallSync; CordisError gains SyncEventPanicked. Exhaustive matches must add the new arms.
  • dylib SDK identity follows version and locked dependencies; hosts and plugins must be rebuilt together against rutis-sdk 0.3.0.

Install with cargo add rutis@0.5.0.

rutis 0.3.0

Choose a tag to compare

@eric8810 eric8810 released this 24 Sep 02:58

rutis 0.3.0

This release is for the rutis core crate. rutis-cli remains at 0.2.0; this tag does not trigger the CLI binary release workflow.

Highlights

  • Fiber-owned InstanceId and instance-aware TypeKey, with subtree checks for service registration, reads, dependency gating, and diagnostics.
  • EventBus::{on,emit,serial,parallel}_instance with isolated listener tables and independent ordered emit chains per instance.
  • FiberView::shutdown() for permanent subtree closure, shared completion, dependency-aware disposal, and reclamation of parent/index/bus records.
  • Final root Ctx::shutdown() and bounded disposal waits; the root dispose/restart behavior remains available.
  • Review fixes for queued settle, listener removal versus dispatch snapshots, dependency declaration consistency, and synchronous listener panic reporting.

See PR #25 for the implementation and issue #30 for selected follow-up work.

Compatibility notes

  • TypeKey is Clone, as in 0.2.x; dynamic qualifiers prevent Copy.
  • Instance keys enforce subtree visibility at runtime. TypeKey::of::<T>() still compiles for every service type; compile-time service-scope markers belong in the consuming runtime.
  • Listener registration after root or subtree closure now returns Closed, including the existing unscoped and named registration methods.

Install with cargo add rutis@0.3.0.

rutis-cli 0.2.0

Choose a tag to compare

@github-actions github-actions released this 22 Sep 12:53

Binary release of rutis-cli (minimal coding agent: bash + replace_text).

Install: download the tar.gz for your platform, verify the .sha256, extract, and put rutis-cli on your PATH. (cargo install rutis-cli installs the older crates.io build without the rutui TUI.)

Requires an aimux provider key at runtime (e.g. DEEPSEEK_API_KEY); try rutis-cli --scripted for an offline demo.