ralph-proto¶
Protocol types shared across all Ralph crates.
Overview¶
ralph-proto defines the core data structures used throughout Ralph:
- Events and Topics for communication
- Hats for persona definitions
- EventBus for routing
Key Types¶
Event¶
A message with topic, payload, and routing information.
pub struct Event {
pub topic: Topic,
pub payload: Option<String>,
pub source_hat: Option<HatId>,
pub target_hat: Option<HatId>,
pub timestamp: DateTime<Utc>,
}
Creating events:
use ralph_proto::Event;
// Simple event
let event = Event::new("build.done");
// With payload
let event = Event::new("build.done")
.with_payload("tests: pass, lint: pass, typecheck: pass, audit: pass, coverage: pass");
// With source hat
let event = Event::new("build.done")
.from_hat("builder");
Topic¶
Event routing with glob pattern matching.
Pattern matching:
let topic = Topic::new("build.done");
topic.matches("build.done"); // true
topic.matches("build.*"); // true
topic.matches("*.done"); // true
topic.matches("test.*"); // false
Hat¶
A specialized Ralph persona.
pub struct Hat {
pub id: HatId,
pub name: String,
pub description: Option<String>,
pub triggers: Vec<String>, // Subscription patterns
pub publishes: Vec<String>, // Allowed event types
pub default_publishes: Option<String>,
pub instructions: String,
pub backend: Option<String>,
pub max_activations: Option<usize>,
}
Creating hats:
use ralph_proto::Hat;
let hat = Hat::builder("builder")
.name("Builder")
.triggers(vec!["task.start", "plan.ready"])
.publishes(vec!["build.done", "build.failed"])
.instructions("Implement the task...")
.build();
HatId¶
Unique identifier for a hat.
EventBus¶
Registry of hats and event routing.
pub struct EventBus {
hats: HashMap<HatId, Hat>,
pending_events: VecDeque<Event>,
event_history: Vec<Event>,
}
impl EventBus {
pub fn register_hat(&mut self, hat: Hat);
pub fn publish(&mut self, event: Event);
pub fn next_event(&mut self) -> Option<Event>;
pub fn matching_hat(&self, event: &Event) -> Option<&Hat>;
}
Using EventBus:
use ralph_proto::{EventBus, Event, Hat};
let mut bus = EventBus::new();
// Register hats
bus.register_hat(planner_hat);
bus.register_hat(builder_hat);
// Publish events
bus.publish(Event::new("task.start"));
// Get next event and matching hat
if let Some(event) = bus.next_event() {
if let Some(hat) = bus.matching_hat(&event) {
// Execute hat with event
}
}
UX Events¶
Events for TUI interaction.
pub enum UxEvent {
TerminalWrite(String),
Resize { width: u16, height: u16 },
FrameCapture(Vec<u8>),
}
Error Types¶
Feature Flags¶
| Flag | Description |
|---|---|
default | Standard features |
serde | Serialization support |
Example: Event Flow¶
use ralph_proto::{EventBus, Event, Hat};
// Setup
let mut bus = EventBus::new();
let planner = Hat::builder("planner")
.triggers(vec!["task.start"])
.publishes(vec!["plan.ready"])
.instructions("Create a plan")
.build();
let builder = Hat::builder("builder")
.triggers(vec!["plan.ready"])
.publishes(vec!["build.done"])
.instructions("Implement the plan")
.build();
bus.register_hat(planner);
bus.register_hat(builder);
// Start flow
bus.publish(Event::new("task.start"));
// First event matches planner
let event = bus.next_event().unwrap();
let hat = bus.matching_hat(&event).unwrap();
assert_eq!(hat.id.as_str(), "planner");
// Planner publishes plan.ready
bus.publish(Event::new("plan.ready").from_hat("planner"));
// Second event matches builder
let event = bus.next_event().unwrap();
let hat = bus.matching_hat(&event).unwrap();
assert_eq!(hat.id.as_str(), "builder");