Files
aryx/HANDOVER.md
T
David KayaandCopilot 0d3f1cbd50 feat: add rich run timeline UI with collapsible cards and jump-to-message
- Add RunTimeline component with vertical event timeline, collapsible run
  cards, per-kind icons, status animations, and agent lane badges
- Add runTimelineFormatting helpers for timestamps, durations, labels,
  content truncation, and consecutive thinking-event collapsing
- Integrate Timeline section into ActivityPanel between Agents and Tools
- Wire jump-to-message in App.tsx using DOM data-message-id attributes
  on ChatPane messages with smooth scroll and temporary highlight ring
- Add comprehensive unit tests for all formatting helpers
- Update HANDOVER.md to document completed frontend implementation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-24 00:17:14 +01:00

8.1 KiB
Raw Blame History

Rich run timeline handover

This change implements the backend half of the Rich run timeline roadmap item and leaves the actual timeline UI/UX for the next agent.

What is done

  • Persisted structured run history on every SessionRecord
  • Added a shared run/timeline domain model for durable per-run metadata and ordered timeline events
  • Started a new run record whenever sendSessionMessage(...) kicks off a turn
  • Grouped streamed assistant output into a single timeline message event keyed by messageId
  • Persisted timeline updates during agent activity, message streaming, completion, and failure
  • Added explicit handoff source metadata so the future UI can draw source/target handoff edges
  • Added a live run-updated session event so the renderer can receive timeline changes incrementally without waiting for a full workspace refresh
  • Kept duplicate-session behavior simple and safe: duplicated sessions copy transcript/tooling config but start with runs: []

Important files

  • src/shared/domain/runTimeline.ts
    • New shared types and helpers:
      • SessionRunRecord
      • RunTimelineEventRecord
      • createSessionRunRecord(...)
      • appendRunActivityEvent(...)
      • upsertRunMessageEvent(...)
      • completeSessionRunRecord(...)
      • failSessionRunRecord(...)
  • src/shared/domain/session.ts
    • SessionRecord now includes runs: SessionRunRecord[]
  • src/main/persistence/workspaceRepository.ts
    • Normalizes persisted session.runs
  • src/main/EryxAppService.ts
    • Creates and updates run records during turn execution
    • Emits live run-updated session events
  • src/shared/domain/event.ts
    • Added session event kind run-updated
    • Added optional run payload on SessionEventRecord
  • src/renderer/lib/sessionWorkspace.ts
    • Applies run-updated events by replacing/inserting the full run snapshot
  • src/shared/contracts/sidecar.ts
    • AgentActivityEvent now carries optional sourceAgentId / sourceAgentName
  • sidecar/src/Eryx.AgentHost/Contracts/ProtocolModels.cs
    • C# DTO mirror for the new handoff source fields
  • sidecar/src/Eryx.AgentHost/Services/CopilotWorkflowRunner.cs
    • Handoff activity now includes the active/source agent when available

Backend contract

Session shape

Every session now has:

runs: SessionRunRecord[]

Runs are stored newest-first.

SessionRunRecord

Key fields:

  • id
  • requestId
  • projectId
  • projectPath
  • workspaceKind
  • patternId
  • patternName
  • patternMode
  • triggerMessageId
  • startedAt
  • completedAt?
  • status
  • agents
  • events

agents is the per-run lane metadata the UI should use for lane headers / agent grouping.

RunTimelineEventRecord

Event kinds:

  • run-started
  • thinking
  • handoff
  • tool-call
  • message
  • run-completed
  • run-failed

Useful payload fields:

  • occurredAt
  • updatedAt?
  • status
  • agentId / agentName
  • sourceAgentId / sourceAgentName
  • targetAgentId / targetAgentName
  • toolName
  • messageId
  • content
  • error

Live update event

The renderer now receives:

{
  sessionId: string;
  kind: 'run-updated';
  occurredAt: string;
  run: SessionRunRecord;
}

This is a full run snapshot, not a delta patch. The reducer already replaces/upserts the run for the selected session.

Current runtime behavior

Run start

sendSessionMessage(...) now:

  1. appends the user message
  2. creates a new SessionRunRecord
  3. persists the workspace
  4. starts the turn

The initial run contains a run-started event pointing at triggerMessageId.

Thinking / handoff / tool activity

Agent activity events now append timeline entries:

  • thinking
  • handoff
  • tool-call

For handoffs, the backend now stores both source and target when the source agent is known.

Streamed assistant output

Message streaming is grouped into one message event per messageId.

During streaming:

  • the existing message event is updated in place
  • status stays running
  • content holds the latest snapshot
  • updatedAt advances

On completion:

  • the same event becomes status: 'completed'
  • final content is persisted

Run completion / failure

Successful runs append run-completed.

Failed runs append run-failed and also mark any still-running message events as errored.

Notes for the UI/UX agent

You do not need new IPC or backend endpoints for the first timeline UI pass.

Use:

  • session.runs for initial render / reload
  • live run-updated session events for in-flight changes

Suggested UI plan:

  1. Replace or reframe the current agent-activity tiles around the run model instead of mixing unrelated tiles together.
  2. Show runs newest-first in the side panel.
  3. Inside a run, render a vertical timeline ordered by events[].
  4. Use agents[] to build per-agent lanes or grouped headers.
  5. Render message events as the coherent answer step for streamed assistant output.
  6. Use messageId and triggerMessageId for jump-to-message actions.
  7. Use agentId, sourceAgentId, and targetAgentId for jump-to-agent / handoff visuals.

UX-specific suggestions

  • run-started: compact start card linked to the triggering user message
  • thinking: lightweight state card or inline badge in the agent lane
  • handoff: directional edge/card from source -> target
  • tool-call: small tool chip/card with tool name and agent
  • message: the main rich output card; this is the item that should expand/collapse cleanly
  • run-completed / run-failed: footer-style terminal state card

Known limitations / open questions

  • There is no dedicated persisted completed activity event. Final assistant output plus run-completed is the canonical completion signal for now.
  • Tool results are not persisted yet; only tool invocation metadata is stored.
  • Pattern version metadata is not persisted yet; only patternId, patternName, and patternMode are captured.
  • Duplicate sessions intentionally start with empty run history. If product wants copied traces later, that needs an explicit decision.
  • Live run-updated events currently send the full run snapshot each time. That keeps the reducer simple; optimize later only if payload size becomes a problem.

Frontend implementation (completed)

The UI has been implemented with the following files:

  • src/renderer/lib/runTimelineFormatting.ts — formatting helpers for timestamps, durations, event labels, and a thinking-event collapsing algorithm
  • src/renderer/components/RunTimeline.tsx — the main timeline UI component with collapsible run cards, vertical timeline connector lines, event icons, and jump-to-message support
  • src/renderer/components/ActivityPanel.tsx — updated to include a Timeline section between Agents and Tools
  • src/renderer/App.tsx — wired onJumpToMessage callback that scrolls to the target message with a temporary highlight ring
  • src/renderer/components/ChatPane.tsx — added data-message-id attributes on message elements for DOM-based scroll targeting
  • tests/renderer/runTimelineFormatting.test.ts — unit tests for all formatting helpers

UI features

  • Collapsible run cards — newest first, auto-expanded for the latest run, with pattern name and live status badge
  • Vertical timeline — ordered event list with connector lines and per-kind icons (Brain for thinking, ArrowRight for handoff, Wrench for tool-call, MessageSquare for message, etc.)
  • Thinking collapse — consecutive thinking events from the same agent are collapsed into a single "×N" row
  • Message preview — message events show a truncated content preview
  • Jump to message — clicking a message or run-started event scrolls the ChatPane to the corresponding message with a brief indigo highlight ring
  • Agent badges — multi-agent runs show agent lane badges at the top of the expanded timeline
  • Duration footer — completed runs show total wall-clock duration
  • Status animations — running events pulse, completed events show green checks, failed events show red alerts

Validation completed

  • bun run typecheck
  • bun test (81 tests, 0 failures)
  • bun run sidecar:test (55 tests, 0 failures)
  • bun run build