pub struct EventLoop { /* private fields */ }Expand description
The main event loop orchestrator.
Implementations§
Source§impl EventLoop
impl EventLoop
Sourcepub fn new(config: RalphConfig) -> Self
pub fn new(config: RalphConfig) -> Self
Creates a new event loop from configuration.
Sourcepub fn with_context(config: RalphConfig, context: LoopContext) -> Self
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).
Sourcepub fn with_context_and_diagnostics(
config: RalphConfig,
context: LoopContext,
diagnostics: DiagnosticsCollector,
) -> Self
pub fn with_context_and_diagnostics( config: RalphConfig, context: LoopContext, diagnostics: DiagnosticsCollector, ) -> Self
Creates a new event loop with explicit loop context and diagnostics.
Sourcepub fn with_diagnostics(
config: RalphConfig,
diagnostics: DiagnosticsCollector,
) -> Self
pub fn with_diagnostics( config: RalphConfig, diagnostics: DiagnosticsCollector, ) -> Self
Creates a new event loop with explicit diagnostics collector (for testing).
Sourcepub fn set_robot_service(&mut self, service: Box<dyn RobotService>)
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.
Sourcepub fn loop_context(&self) -> Option<&LoopContext>
pub fn loop_context(&self) -> Option<&LoopContext>
Returns the loop context, if one was provided.
Sourcepub fn reset_stale_topic_counter(&mut self)
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.
Sourcepub fn config(&self) -> &RalphConfig
pub fn config(&self) -> &RalphConfig
Returns the configuration.
Sourcepub fn registry(&self) -> &HatRegistry
pub fn registry(&self) -> &HatRegistry
Returns the hat registry.
Sourcepub fn log_hook_run_telemetry(&self, entry: HookRunTelemetryEntry)
pub fn log_hook_run_telemetry(&self, entry: HookRunTelemetryEntry)
Records hook telemetry for diagnostics.
Sourcepub fn log_prompt(&self, iteration: u32, hat: &str, prompt: &str)
pub fn log_prompt(&self, iteration: u32, hat: &str, prompt: &str)
Logs the full prompt for an iteration to the diagnostics session.
Sourcepub fn get_hat_backend(&self, hat_id: &HatId) -> Option<&HatBackend>
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).
Sourcepub fn add_observer<F>(&mut self, observer: F)
pub fn add_observer<F>(&mut self, observer: F)
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.
Sourcepub fn set_observer<F>(&mut self, observer: F)
👎Deprecated since 2.0.0: Use add_observer instead
pub fn set_observer<F>(&mut self, observer: F)
Use add_observer instead
Sets a single observer, clearing any existing observers.
Prefer add_observer when multiple observers are needed.
Sourcepub fn check_termination(&self) -> Option<TerminationReason>
pub fn check_termination(&self) -> Option<TerminationReason>
Checks if any termination condition is met.
Sourcepub fn check_cancellation_event(&mut self) -> Option<TerminationReason>
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.
Sourcepub fn check_completion_event(&mut self) -> Option<TerminationReason>
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).
Sourcepub fn initialize(&mut self, prompt_content: &str)
pub fn initialize(&mut self, prompt_content: &str)
Initializes the loop by publishing the start event.
Sourcepub fn initialize_resume(&mut self, prompt_content: &str)
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.
Sourcepub fn next_hat(&self) -> Option<&HatId>
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
Sourcepub fn sync_event_reader_to_file_end(&mut self)
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.
Sourcepub fn has_pending_events(&self) -> bool
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.
Sourcepub fn has_pending_human_events(&self) -> bool
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.
Sourcepub fn inject_human_guidance<I, S>(&mut self, messages: I)
pub fn inject_human_guidance<I, S>(&mut self, messages: I)
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.
Sourcepub fn has_pending_plan_events_in_jsonl(&self) -> Result<bool>
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.
Sourcepub fn pending_human_interact_context_in_jsonl(&self) -> Result<Option<Value>>
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.
Sourcepub fn get_hat_publishes(&self, hat_id: &HatId) -> Vec<String>
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.
Sourcepub fn inject_fallback_event(&mut self) -> bool
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.
Sourcepub fn build_prompt(&mut self, hat_id: &HatId) -> Option<String>
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).
Sourcepub fn build_ralph_prompt(&self, prompt_content: &str) -> String
pub fn build_ralph_prompt(&self, prompt_content: &str) -> String
Builds the Ralph prompt (coordination mode).
Sourcepub fn get_active_hat_id(&self) -> HatId
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.
Sourcepub fn check_default_publishes(&mut self, hat_id: &HatId)
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.
Sourcepub fn bus(&mut self) -> &mut EventBus
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.
Sourcepub fn process_output(
&mut self,
hat_id: &HatId,
output: &str,
success: bool,
) -> Option<TerminationReason>
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.
Sourcepub fn process_events_from_jsonl(&mut self) -> Result<ProcessedEvents>
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:
- Emitting
event.malformedsystem events for each parse failure - Tracking consecutive failures for termination check
- 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.
Sourcepub fn process_events_from_jsonl_with_waves(
&mut self,
) -> Result<ProcessedEventsWithWaves>
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.
Sourcepub fn check_ralph_completion(&self, output: &str) -> bool
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.
Sourcepub fn publish_terminate_event(&mut self, reason: &TerminationReason) -> Event
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.
Sourcepub fn robot_shutdown_flag(&self) -> Option<Arc<AtomicBool>>
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.
Sourcepub fn check_for_user_prompt(&self, events: &[Event]) -> Option<UserPrompt>
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.