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

228 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
```ts
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:
```ts
{
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`