diff --git a/HANDOVER.md b/HANDOVER.md deleted file mode 100644 index 114af7e..0000000 --- a/HANDOVER.md +++ /dev/null @@ -1,227 +0,0 @@ -# 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`