Skip to main content

Crate rig_harness

Crate rig_harness 

Source
Expand description

rig-harness: the harness of the rig coding agent, a Bevy app on the rig_ecs kernel. It holds what the binary needs to run and be relaunched (the session, the rig launcher protocol, how the agent was started: Invoked) and the services every plugin shares. Everything else, the terminal view, --print, /reload and the built-in tools included, is a plugin crate in the repository’s plugins/ folder, built only on this crate’s public API.

HeadlessPlugins is what a terminal app takes from Bevy, and RigHarnessPlugins is the harness. The launcher’s generated main.rs adds the plugins plugins.toml lists with load. The error handler is the application’s to set:

use rig_harness::load;
use rig_harness::prelude::*;

#[derive(Default)]
struct HelloPlugin;

impl Plugin for HelloPlugin {
    fn build(&self, _app: &mut App) {}
}

fn main() -> AppExit {
    let mut app = App::new();
    app.set_error_handler(rig_harness::error::warn)
        .add_plugins((HeadlessPlugins, RigHarnessPlugins));
    load::<HelloPlugin>(&mut app, "rig-hello", "path plugins/hello");
    app.run()
}

plugin_guide is the guide to writing a plugin; rig plugin new <name> makes one.

Re-exports§

pub use describe::run;
pub use rig_core;
pub use rig_ecs;
pub use rig_harness_protocol as harness_protocol;
pub use rig_memory;
pub use rig_tools;

Modules§

agent_title
An agent’s title, saved where a library program reads it.
ask
Questions for the user that any front answers: an approval, a choice or a line of text. An Ask is an open effect, recorded like any and answered by deciding it (Decision) with Answer::outcome; the first decision wins. A plugin that waits on the answer spawns it as a hold (HoldOf(call)) on what it asks about, so stopping the turn closes it in every front at once.
clock
Waking the loop that sleeps while nothing happens. Bevy’s clock, which timers and delayed commands run on, stops while the machine sleeps; a WakeAt is a wall-clock instant instead. Once it passes, the entity gets Due in First, and the headless loop sleeps no longer than until the earliest one. A plugin reacts to Add<Due>, and arms the next time by inserting a new WakeAt, which takes Due away. A KeepAwake keeps the loop running at its pace while it lives.
commands
Slash commands. A command is an entity: its Name is the /name typed, its SlashCommand says what it does, and it is the one-shot system that runs it, so despawning it unregisters both. A plugin adds one with AppCommandsExt::add_command, a system that reads the CommandArgs, such as one that triggers an event.
describe
How the built agent tells the rig launcher what its plugins add to the command line: their commands, their options and the secrets they ask for (AgentDescription). The launcher asks after each build, by running the binary with env::DESCRIBE naming a file; run, which the generated main.rs ends with, then builds the app (every plugin’s build, finish and cleanup), writes the report to that file and exits without running a frame. While it describes, no front takes the run, so no front sets itself up, and the session has no directory.
error
Bevy’s error handlers, for App::set_error_handler: warn logs a failing system, observer or command instead of stopping the app. Error handling for Bevy systems, commands, and observers.
host
What the binary needs to run as a process and be relaunched: the session directory and its log, the loop and its signals, the rig launcher protocol with the plugins’ options and fronts, and why the app exits.
main_agent
The agent the user talks to when no agent is named, such as the one a front shows first and --print sends to: of the agents nothing spawned, the first by id; and the agent the user looks at (ShownAgent).
per_call
Tools whose every call is built for where it works (AppPerCallExt::add_tool_per_call): the app’s workspace, the calling agent’s WorkDir or else the ProjectRoot, and, for a tool that reports its output as it runs, where it reports it (CallPlace). A plugin builds such a call somewhere else, such as on an overlay of the workspace, with PerCallTools.
pick
Choices for the user that any front shows and answers: a plugin’s Picker, a filterable list on an entity of the plugin’s. Inserting a new Picker replaces what it shows, and despawning it closes it. A front that shows pickers (Query<(Entity, &Picker)>) triggers Pick on the one the user picked from, or closed: the harness then runs the item’s command, for the picker’s agent or else the agent the user is looking at (ShownAgent), triggers Picked on it, and despawns it. A picker may take several items (Picker::multiple): the harness runs each one’s command in list order. A Chosen holds the items picked and the text typed, either or both. A front answers an open Ask the same way: a Pick on it decides the answer, a question’s choices with the note typed on them.
plugin_data
Where a plugin keeps files of its own, by how long they live: PluginData, in every run. A plugin names its files under its own name, such as vim/registers.json.
plugin_guide
Writing a plugin for the rig agent: the rules every plugin follows, then a short, copy-ready example per extension point.
prelude
What a plugin needs, so a typical one imports only this: the kernel’s prelude and the harness’s services. A plugin crate’s own types come from that crate, such as the terminal view’s panels from rig-tui.
progress
How far a running call got, for every front: ToolProgress, and the output a running call’s tool reports as it works (CallOutput).
secrets
Secrets a plugin needs before any front runs, such as the passphrase of an encrypted session store, which opens before the session is restored.
services
What every plugin shares about the process it runs in, as resources: the RIG_HOME layout (RigHome), the project the session works on (ProjectRoot) and the directory an agent works in when not that one (WorkDir), how child processes start (Processes), and the tokio runtime rig’s HTTP requests run on (TokioRuntime). Each is taken from the environment unless the app inserted one first, which is how a test points a plugin at a directory of its own; a plugin that should also work in an app without the harness’s plugins inits the ones it reads (app.init_resource::<ProjectRoot>()).
settings
The user’s settings for plugins: RIG_HOME/settings.toml, one table per plugin. A plugin names its table and a type that reads it, and gets that type as a resource, its Default where the user set nothing. A table that does not read as the type leaves the default and says why at startup, as does a file that is not TOML.
successor
Following an effect to its successor. Any plugin may take an effect over by spawning a successor it is SupersededBy, such as a watchdog sending a stalled call again (resend): the old effect then settles as superseded, with no outcome applied. The plugin that owns the effect, and waits for its outcome by a marker of its own, follows it with the kernel’s follow_successor, so the successor’s outcome is the one it takes.
timings
How long each system ran, as data: SystemTimings, read per plugin through PluginTimings. It is filled when the harness is built with its trace feature, which turns on Bevy’s spans around every system and schedule run; a plugin crate turns it on by depending on rig-harness with features = ["trace"]. The spans are info level, so a RUST_LOG that sets bevy_ecs below info leaves it empty. A run is charged to the plugin that added the system or observer (PluginSystems, ProvidedBy), and kept with the schedule it ran in: a run in AgentPass (a stage system, or an observer its commands set off) is work an agent’s pass waited on.
watch
Watching files. An entity with a FileWatch on a file or a directory gets a FileChanges message naming the files there when it was armed, then one for each batch of files created, changed or removed under it, as the system reports them, and the loop is woken for each; despawning it, or removing the FileWatch, stops the watch. A plugin that reloads templates or skills from a directory watches it, and reads them on its first FileChanges, so no file made in between is missed.
workspace
The workspace the agent works in: ProjectWorkspace.

Structs§

App
App is the primary API for writing user applications. It automates the setup of a standard lifecycle and provides interface glue for plugins.
HeadlessPlugins
What a terminal app takes from Bevy where a windowed one has DefaultPlugins: Bevy’s MinimalPlugins with task pools sized for an agent and the frame count and clock, the log written to the session with its warnings and errors passed on as data, a clean exit on SIGINT, SIGTERM and SIGHUP, and in place of Bevy’s ScheduleRunnerPlugin a loop that runs the schedules on the main thread and sleeps until Waked or until the clock’s next deadline. Added before RigHarnessPlugins, so the kernel runs on its clock; a windowing plugin added later through windowed sets its own runner in place of this loop (see plugin_guide).
Keeps
What a plugin keeps with the session, on the entity load spawned for it: the saved values it owns, by their saved key (the type path, such as my_plugin::Counter, or a stable one such as rig::model), and its folders of session files in PluginData::session, such as vim. A plugin says so in build, finish or cleanup (AppKeepsExt); nothing infers it. A saved value no plugin keeps is the kernel’s or the harness’s, or one whose plugin did not say.
PluginEntity
The entity load spawned for the plugin P, for what P spawns while the app runs.
PluginSource
Where a plugin comes from, on the entity load spawns for it.
PluginSystems
Which plugin added each schedule system, by the system’s name and its schedule’s label (such as AgentPass), as load saw it. Two plugins that add a system of the same name to one schedule are told apart by neither; a system a plugin adds later, while the app runs, is no plugin’s.
ProvidedBy
The plugin that spawned this entity.
Provides
What a plugin spawned.
RigHarnessPlugins
The harness: the session and its log, the kernel (rig_ecs::AgentPlugin, rig_ecs::session_log::SessionLogPlugin), the launcher protocol, and the services every agent uses: slash commands, the clock the loop sleeps by, file watches, the questions and pickers every front answers, and tool progress. Everything else is a plugin plugins.toml lists, which can leave it out.
SavedAs
A saved value’s key, as AppKeepsExt::saved_as recorded it.

Enums§

AppExit
A Message that indicates the App should exit. If one or more of these are present at the end of an update, the runner will end and (maybe) return control to the caller.

Constants§

PLUGIN_GUIDE
Where the plugin guide (plugin_guide) is on disk, for an agent that reads it: in this crate’s own source, from a checkout or from crates.io alike.

Traits§

AppKeepsExt
Saying what a plugin keeps with the session, in its build, finish or cleanup, onto its Keeps. A plugin added without load has no entity to say it on, and nothing is recorded.

Functions§

check_stages_at_start
Shows each of the app’s stage_conflicts as a warning notice at its start. The generated main.rs adds it to a debug build.
load
Adds P, unless the app has it already (another plugin added it), as the generated main.rs adds each plugin plugins.toml lists: with an entity of its own, named after it, from package at source.
stage_conflicts
Each pair of systems of one AgentPass stage that use the same data, one writing it, with no order between them, so which runs first is chance: one line each, naming their plugins (by type, or the harness for the harness’s, the kernel’s and Bevy’s own), the systems and the data. It initializes the agent loop, as the loop’s first run would; an app without one has none. rig plugin check --build reports these for the plugins plugins.toml lists, and a debug build at its start (check_stages_at_start).
task_pools
Bevy’s pools sized for an agent rather than a game. Model calls stream on the IO pool and tool calls run on the async compute pool, each with 2 to 4 threads, so a few agents’ calls run side by side; blocking tool work runs on threads of its own through prelude::blocking. Bevy’s own systems keep the rest of the cores. HeadlessPlugins sets them; a test app sets them too, so it runs its calls as the agent does.
windowed
plugins, such as Bevy’s DefaultPlugins, without what HeadlessPlugins already sets: the log, the task pools, the frame count, the clock, the signal handler and the loop. Its windowing plugin then runs the loop; plugin_guide shows how a window plugin wakes it.