Skip to main content

EventLoop

Struct EventLoop 

Source
pub struct EventLoop { /* private fields */ }
Expand description

The main event loop orchestrator.

Implementations§

Source§

impl EventLoop

Source

pub fn new(config: RalphConfig) -> Self

Creates a new event loop from configuration.

Source

pub fn with_context(config: RalphConfig, context: LoopContext) -> Self

Creates a new event loop with a loop context for path resolution.

The loop context determines where events, tasks, and other state files are located. Use this for multi-loop scenarios where each loop runs in an isolated workspace (git worktree).

Source

pub fn with_context_and_diagnostics( config: RalphConfig, context: LoopContext, diagnostics: DiagnosticsCollector, ) -> Self

Creates a new event loop with explicit loop context and diagnostics.

Source

pub fn with_diagnostics( config: RalphConfig, diagnostics: DiagnosticsCollector, ) -> Self

Creates a new event loop with explicit diagnostics collector (for testing).

Source

pub fn set_robot_service(&mut self, service: Box<dyn RobotService>)

Injects a robot service for human-in-the-loop communication.

Call this after construction to enable human.interact event handling, periodic check-ins, and question/response flow. The service is typically created by the CLI layer (e.g., TelegramService) and injected here, keeping the core event loop decoupled from any specific communication platform.

Source

pub fn loop_context(&self) -> Option<&LoopContext>

Returns the loop context, if one was provided.

Source

pub fn state(&self) -> &LoopState

Returns the current loop state.

Source

pub fn reset_stale_topic_counter(&mut self)

Resets the stale-loop topic counter.

Call after processing wave results — multiple events with the same topic (e.g. review.done from parallel workers) are expected and should not trigger the stale loop detector.

Source

pub fn config(&self) -> &RalphConfig

Returns the configuration.

Source

pub fn registry(&self) -> &HatRegistry

Returns the hat registry.

Source

pub fn log_hook_run_telemetry(&self, entry: HookRunTelemetryEntry)

Records hook telemetry for diagnostics.

Source

pub fn log_prompt(&self, iteration: u32, hat: &str, prompt: &str)

Logs the full prompt for an iteration to the diagnostics session.

Source

pub fn get_hat_backend(&self, hat_id: &HatId) -> Option<&HatBackend>

Gets the backend configuration for a hat.

If the hat has a backend configured, returns that. Otherwise, returns None (caller should use global backend).

Source

pub fn add_observer<F>(&mut self, observer: F)
where F: Fn(&Event) + Send + 'static,

Adds an observer that receives all published events.

Multiple observers can be added (e.g., session recorder + TUI). Each observer is called before events are routed to subscribers.

Source

pub fn set_observer<F>(&mut self, observer: F)
where F: Fn(&Event) + Send + 'static,

👎Deprecated since 2.0.0:

Use add_observer instead

Sets a single observer, clearing any existing observers.

Prefer add_observer when multiple observers are needed.

Source

pub fn check_termination(&self) -> Option<TerminationReason>

Checks if any termination condition is met.

Source

pub fn check_cancellation_event(&mut self) -> Option<TerminationReason>

Check if a loop.cancel event was detected.

Unlike check_completion_event(), this does NOT validate required_events. Cancellation is an explicit abort — it doesn’t need the workflow to be complete.

Source

pub fn check_completion_event(&mut self) -> Option<TerminationReason>

Checks if a completion event was received and returns termination reason.

Completion is only accepted via JSONL events (e.g., ralph emit).

Source

pub fn initialize(&mut self, prompt_content: &str)

Initializes the loop by publishing the start event.

Source

pub fn initialize_resume(&mut self, prompt_content: &str)

Initializes the loop for resume mode by publishing task.resume.

Per spec: “User can run ralph resume to restart reading existing scratchpad.” The planner should read the existing scratchpad rather than doing fresh gap analysis.

Source

pub fn next_hat(&self) -> Option<&HatId>

Gets the next hat to execute (if any have pending events).

Per “Hatless Ralph” architecture: When custom hats are defined, Ralph is always the executor. Custom hats define topology (pub/sub contracts) that Ralph uses for coordination context, but Ralph handles all iterations.

  • Solo mode (no custom hats): Returns “ralph” if Ralph has pending events
  • Multi-hat mode (custom hats defined): Always returns “ralph” if ANY hat has pending events
Source

pub fn sync_event_reader_to_file_end(&mut self)

Advances the event reader to the current end of the events file.

Call this after writing observability records (e.g. start event) to the events JSONL file so they are not re-read by process_events_from_jsonl. The start event is already published to the bus via initialize(), so re-reading it from the file would cause double-delivery.

Source

pub fn has_pending_events(&self) -> bool

Checks if any hats have pending events.

Use this after process_output to detect if the LLM failed to publish an event. If false after processing, the loop will terminate on the next iteration.

Source

pub fn has_pending_human_events(&self) -> bool

Checks if any pending events are human-related (human.response, human.guidance).

Used to skip cooldown delays when a human event is next, since we don’t want to artificially delay the response to a human interaction.

Source

pub fn inject_human_guidance<I, S>(&mut self, messages: I)
where I: IntoIterator<Item = S>, S: Into<String>,

Injects human.guidance events directly into the in-memory bus.

This is used for local TUI/RPC guidance so the next prompt boundary sees the message immediately without waiting for a JSONL reread.

Source

pub fn has_pending_plan_events_in_jsonl(&self) -> Result<bool>

Returns whether unread JSONL events include any semantic plan.* topics.

This allows callers to dispatch pre.plan.created hooks before event publication handling without consuming unread events.

Source

pub fn pending_human_interact_context_in_jsonl(&self) -> Result<Option<Value>>

Returns structured context for the first unread human.interact event, if one is present in JSONL without consuming reader state.

Source

pub fn get_hat_publishes(&self, hat_id: &HatId) -> Vec<String>

Gets the topics a hat is allowed to publish.

Used to build retry prompts when the LLM forgets to publish an event.

Source

pub fn inject_fallback_event(&mut self) -> bool

Injects a fallback event to recover from a stalled loop.

When no hats have pending events (agent failed to publish), this method injects a task.resume event which Ralph will handle to attempt recovery.

Returns true if a fallback event was injected, false if recovery is not possible.

Source

pub fn build_prompt(&mut self, hat_id: &HatId) -> Option<String>

Builds the prompt for a hat’s execution.

Per “Hatless Ralph” architecture:

  • Solo mode: Ralph handles everything with his own prompt
  • Multi-hat mode: Ralph is the sole executor, custom hats define topology only

When in multi-hat mode, this method collects ALL pending events across all hats and builds Ralph’s prompt with that context. The ## HATS section in Ralph’s prompt documents the topology for coordination awareness.

If memories are configured with inject: auto, this method also prepends primed memories to the prompt context. If a scratchpad file exists and is non-empty, its content is also prepended (before memories).

Source

pub fn build_ralph_prompt(&self, prompt_content: &str) -> String

Builds the Ralph prompt (coordination mode).

Source

pub fn get_active_hat_id(&self) -> HatId

Returns the primary active hat ID for display purposes. Returns the first active hat, or “ralph” if no specific hat is active. BTreeMap iteration is already sorted by key.

Source

pub fn check_default_publishes(&mut self, hat_id: &HatId)

Injects a default event for a hat when the agent wrote no events.

Call this after process_events_from_jsonl returns Ok(false) (no events found). If the hat has default_publishes configured, this injects the default event.

If the default topic matches the completion promise, completion_requested is set so the loop can terminate. Without this, completion events injected via default_publishes would only be published to the bus (triggering downstream hats) but never detected by check_completion_event, causing an infinite loop.

Source

pub fn bus(&mut self) -> &mut EventBus

Returns a mutable reference to the event bus for direct event publishing.

This is primarily used for planning sessions to inject user responses as events into the orchestration loop.

Source

pub fn process_output( &mut self, hat_id: &HatId, output: &str, success: bool, ) -> Option<TerminationReason>

Processes output from a hat execution.

Returns the termination reason if the loop should stop.

Source

pub fn add_cost(&mut self, cost: f64)

Adds cost to the cumulative total.

Source

pub fn process_events_from_jsonl(&mut self) -> Result<ProcessedEvents>

Processes events from JSONL and routes orphaned events to Ralph.

Also handles backpressure for malformed JSONL lines by:

  1. Emitting event.malformed system events for each parse failure
  2. Tracking consecutive failures for termination check
  3. Resetting counter when valid events are parsed

Returns ProcessedEvents indicating whether events were found, whether semantic plan.* topics were published, structured human.interact context/outcome metadata, and whether any were orphans that Ralph should handle.

Source

pub fn process_events_from_jsonl_with_waves( &mut self, ) -> Result<ProcessedEventsWithWaves>

Process events from JSONL, partitioning wave events from regular events.

Wave events (those with wave_id set and targeting a concurrent hat) are extracted and returned separately. Regular events go through the full backpressure pipeline via process_parse_result.

Source

pub fn check_ralph_completion(&self, output: &str) -> bool

Checks if output contains a completion event from Ralph.

Completion must be emitted as an <event> tag, not plain text.

Source

pub fn publish_terminate_event(&mut self, reason: &TerminationReason) -> Event

Publishes the loop.terminate system event to observers.

Per spec: “Published by the orchestrator (not agents) when the loop exits.” This is an observer-only event—hats cannot trigger on it.

Returns the event for logging purposes.

Source

pub fn robot_shutdown_flag(&self) -> Option<Arc<AtomicBool>>

Returns the robot service’s shutdown flag, if active.

Signal handlers can set this flag to interrupt wait_for_response() without waiting for the full timeout.

Source

pub fn check_for_user_prompt(&self, events: &[Event]) -> Option<UserPrompt>

Check if any event is a user.prompt event.

Returns the first user prompt event found, or None.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more