Plan Real-Time Updates
Plan views subscribe to the EventHub so log entries, state transitions, and newly created plans appear instantly. The server broadcasts three event types; two Dioxus hooks consume them on the client.
Event Types
Section titled “Event Types”| Constant | Value | Payload | Published when |
|---|---|---|---|
EVT_PLAN_LOG_NEW | plan.log.new | PlanLogEvent | A log entry is created or updated |
EVT_PLAN_STATE_CHANGED | plan.state.changed | PlanStateChanged | A plan transitions state |
EVT_PLAN_CREATED | plan.created | Plan | A new plan is created from a call |
Constants live in src/mods/plan/types/plan_event_type.rs.
Payloads
Section titled “Payloads”PlanLogEvent
Section titled “PlanLogEvent”pub struct PlanLogEvent { pub plan_id: Uuid, #[serde(flatten)] pub log: PlanLogDisplay, // id, entry, created_at}The plan_id field lets clients filter events for a specific plan. The log field flattens into the same shape the detail API returns, so the client can merge it directly.
PlanStateChanged
Section titled “PlanStateChanged”pub struct PlanStateChanged { pub plan_id: Uuid, pub state: PlanState,}Server Broadcasting
Section titled “Server Broadcasting”All publishing goes through publish_plan_event_service.rs, which wraps event_hub().publish_org():
pub fn publish_plan_log(org_id: Uuid, plan_id: Uuid, log_display: &PlanLogDisplay);pub fn publish_plan_state(org_id: Uuid, plan_id: Uuid, state: &PlanState);pub fn publish_plan_created(org_id: Uuid, plan: &Plan);Broadcast Points
Section titled “Broadcast Points”| Location | Event |
|---|---|
log_tool_call.rs — create_log_entry() | plan.log.new on every new log entry |
log_tool_call.rs — update_log_entry() | plan.log.new when a log entry is updated (approval, rejection) |
execute_plan_service.rs | plan.state.changed on execution start/end/failure |
approve_plan_api.rs, reject_plan_api.rs | plan.state.changed on plan approval/rejection |
approve_log_entry_api.rs, reject_log_entry_api.rs, answer_question_api.rs | plan.log.new after updating the log entry |
create_plans_from_call_service.rs | plan.created when new plans are created |
execute_scheduled_tool_calls_job.rs | plan.log.new + plan.state.changed after executing scheduled tools |
Client Hooks
Section titled “Client Hooks”use_realtime_plan
Section titled “use_realtime_plan”Subscribes to events for a single plan. Used by PlanDetailsView.
pub fn use_realtime_plan(plan_id: Uuid) -> (Signal<Vec<PlanLogDisplay>>, Signal<Option<PlanState>>)Returns:
live_logs— log entries received after the initial fetch. New entries append; updates replace byid.live_state— the latest state change, orNoneif unchanged.
Merge strategy in PlanDetailsView:
- Start with server-fetched logs.
- For each live log, find by
id— update if it exists, append if new. - Sort merged logs by
created_at. - Use
live_stateif present, otherwise fall back to server-fetched state.
When plan_id changes, both signals reset to empty.
use_realtime_plans
Section titled “use_realtime_plans”Subscribes to list-level events. Used by PlanListView.
pub fn use_realtime_plans() -> (Signal<Vec<PlanStateChanged>>, Signal<Vec<Plan>>)Returns:
state_changes— accumulated state transitions. Deduped byplan_id(latest wins).new_plans— plans created after the initial fetch. Deduped byid.
Merge strategy in PlanListView:
- Start with server-fetched plan list.
- Apply each
PlanStateChangedto the matching plan’sstatefield. - Prepend new plans that aren’t already in the list.
Key Files
Section titled “Key Files”| File | Purpose |
|---|---|
src/mods/plan/types/plan_event_type.rs | Event type constants |
src/mods/plan/types/plan_log_event_type.rs | PlanLogEvent payload |
src/mods/plan/types/plan_state_changed_type.rs | PlanStateChanged payload |
src/mods/plan/services/publish_plan_event_service.rs | Server-side publish helpers |
src/mods/plan/hooks/use_realtime_plan.rs | Detail view hook |
src/mods/plan/hooks/use_realtime_plans.rs | List view hook |
src/mods/plan/views/plan_details_view.rs | Detail view merge logic |
src/mods/plan/views/plan_list_view.rs | List view merge logic |