Skip to content

Plan Timeline

The plan timeline renders log entries as a flat chronological list grouped by execution run. It serves as the secondary view (behind the campaign graph) on the plan details page, useful for auditing every action the executor took.

Log entries are grouped into collapsible sections by execution run. Each group is bounded by ExecutionStarted / ExecutionEnded system events.

src/mods/plan/components/plan_timeline_component.rs
struct ExecutionGroup {
timestamp: String, // From ExecutionEnded, or first entry
entries: Vec<PlanLogDisplay>, // Visible entries (ExecutionStarted excluded)
}

The group_by_execution() function walks entries chronologically, splitting on ExecutionEnded markers. If entries exist without a closing marker, they form a “currently running” group.

  • The most recent group opens by default.
  • All older groups start collapsed.
  • State is tracked in a HashSet<usize> of open group indices.
  • Each group header shows a timestamp badge and entry count.

The timeline separates entries into two sections:

SectionPositionContent
PendingTopTool calls awaiting approval or user answers
HistoryBelowCompleted entries grouped by execution run

Pending entries render with approve/reject buttons (or an answer form for AskUser calls). Once resolved, they move into the history section on the next data refresh.

All text content renders through the Markdown component (powered by pulldown-cmark with tables, strikethrough, and tasklists enabled):

ContentWhere
Email bodySendEmail tool call card
SMS bodySendSms tool call card
Note contentWriteInteractionNote, UpdateSystemNote cards
QuestionsAskUser card
Plan descriptionDetails header
Completion summaryCompletePlan card
Failure reasonFailPlan card
Model reasoningCollapsibleReasoning component

Three components handle expandable data retrieved by the executor:

Wraps ModelReasoning system entries. Shows a “Reasoning” header with a brain icon — click to expand the AI’s internal reasoning text.

Renders notes retrieved by GetContactNotes. Shows a “N note(s) retrieved” toggle. Each note displays its timestamp, a “System” badge if applicable, and markdown content.

Renders messages retrieved by GetConversationHistory. Shows a “N message(s) retrieved” toggle. Inbound messages use bg-muted/30, outbound use bg-primary/10. Each shows direction, channel badge, timestamp, and body.

Each tool call renders inside a Card with:

  1. Header — icon + tool name + status badge (Pending, Approved, Rejected, Expired, Failed)
  2. Structured detail — fields specific to the tool type
  3. Action controls — approve/reject buttons or answer form for pending entries
ToolIconKey Fields
Send EmailMailTo, Subject, Body (markdown), Scheduled/Expires
Send SMSMessageSquareTo, Body (markdown), Scheduled/Expires
List ContactsUsersContact name badges
Get Contact DetailsUserName, Email, Phone
Get Contact NotesFileTextExpandable notes list
Conversation HistoryMessagesSquareExpandable messages list
Write NotePenLineMarkdown content
Update System NoteSettingsMarkdown content
QuestionMessageCircleQuestionMarkQuestion text, option badges, answer
Plan CompletedCircleCheckSummary (markdown)
Plan FailedCircleXReason (markdown)
ScheduledClockDelay minutes, reason, scheduled time

When the executor asks a question, the timeline shows:

  1. The question rendered as markdown
  2. If options exist — clickable badges that submit the answer on click
  3. If allow_free_text — a text input with submit button
  4. After answered — the selected option highlighted in primary color, others dimmed
FilePurpose
src/mods/plan/components/plan_timeline_component.rsTimeline component, grouping logic, all sub-components
src/mods/plan/views/plan_details_view.rsParent view with tab switcher (Graph / Timeline)
src/mods/plan/types/plan_log_entry_type.rsPlanLogEntry, PlanLogEntryToolCall, PlanLogEntrySystem enums