sidebar activity timeline replaces tool display in chat
- New ActivityTimeline: unified timeline in sidebar showing all agent actions (goal, plan steps, tool calls, knowledge, completion) in reverse chron order - activityLog derived store merges messages + planSteps + currentTask - AgentIndicator stays in chat (thinking/working indicator), simplified props - ToolCallGroup removed from chat — tools visible only in sidebar timeline - SessionDigest replaced by ActivityTimeline - PlanProgress restored in sidebar (conceptual steps, separate from timeline)
This commit is contained in:
133
plans/2026-07-14-activity-timeline.md
Normal file
133
plans/2026-07-14-activity-timeline.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# 2026-07-14 — Unified sidebar activity timeline
|
||||
|
||||
**Status:** Planned
|
||||
|
||||
## Current state (broken)
|
||||
|
||||
The sidebar has three sections that appear/disappear independently:
|
||||
|
||||
| Section | When visible | Shows |
|
||||
|---|---|---|
|
||||
| Plan (top) | When `$planSteps.length > 0` | Plan step names with progress bar |
|
||||
| Tool activity (middle) | When `toolCount > 0` | Compact tool list, grouped by turn |
|
||||
| This session (bottom) | When `digest.total_executions > 0` | Post-hoc execution count + knowledge |
|
||||
|
||||
State changes cause sections to **pop in/out** as the agent moves between
|
||||
planning → executing → done. The "0 tools · 0 running" counter flashes
|
||||
briefly then vanishes. Tool activity appears/disappears between turns.
|
||||
|
||||
## Target: single unified timeline
|
||||
|
||||
One section, always present when a session is loaded. Every agent action
|
||||
appears as an entry in reverse-chronological order (newest at top).
|
||||
|
||||
```
|
||||
┌─ Activity ───────────────────────── ─┐
|
||||
│ │
|
||||
│ ✓ Task completed: "Upgraded 4 LXCs" │ ← newest
|
||||
│ ◉ Running: apt upgrade on lxc:dns │
|
||||
│ ✓ run: apt upgrade on lxc:gitea │ ← tool completed
|
||||
│ ✓ Verified gitea: HTTP 200 │
|
||||
│ ◉ Step 3/5 — Upgrade dns │ ← plan step running
|
||||
│ ✓ Step 2/5 — Upgrade gitea │ ← plan step done
|
||||
│ ✓ run: apt upgrade on lxc:nfs-export │
|
||||
│ ◉ Step 1/5 — Upgrade nfs-export │
|
||||
│ ✓ Knowledge recorded │
|
||||
│ 📋 Plan set: 5 steps │ ← plan proposed
|
||||
│ 🎯 Goal: Upgrade 4 low-risk LXCs │ ← goal set
|
||||
│ │ ← oldest
|
||||
└───────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Entry types
|
||||
|
||||
| Type | Icon | Example description |
|
||||
|---|---|---|
|
||||
| `goal` | 🎯 | "Audit all LXCs for updates" |
|
||||
| `plan` | 📋 | "Plan set: 5 steps" |
|
||||
| `step_start` | ◉ spinner | "Step 2/5 — Upgrade gitea" |
|
||||
| `step_done` | ✓ | "Step 2/5 — Upgrade gitea" |
|
||||
| `tool_start` | ◉ spinner | "run: Upgrade nfs-export (21 pkgs)" |
|
||||
| `tool_done` | ✓ | "run: 0 upgraded, 0 newly installed" |
|
||||
| `tool_error` | ✗ | "run: SSH handshake failed" |
|
||||
| `knowledge` | ✨ | "Recorded: How to run fleet upgrades" |
|
||||
| `complete` | ✓ | "Task completed: success" |
|
||||
| `question` | ❓ | "Asked: Which host for the LXC?" |
|
||||
| `error` | ✗ | "Auto-resume failed: context deadline exceeded" |
|
||||
|
||||
### Data source
|
||||
|
||||
Entries come from all available sources, merged and deduplicated:
|
||||
1. **`toolTimeline` store** (live tool_use/tool_result pairs)
|
||||
2. **`planSteps` store** (step status transitions)
|
||||
3. **Session digest API** (knowledge created, final outcome)
|
||||
4. **`currentTask` store** (goal, status)
|
||||
|
||||
Deduplication: when a plan step links to a tool call via `execution_id`, show
|
||||
them as one entry instead of two (e.g. "Step 3: Upgrade dns ◉ running" includes
|
||||
the tool — don't show a separate "run: apt upgrade" entry).
|
||||
|
||||
### Behavior
|
||||
|
||||
- **Always visible** when `$currentSession` is set
|
||||
- **Reverse chronological** — newest entries at top, scrolls naturally
|
||||
- **Auto-expands** the entry for the currently-running tool/step
|
||||
- **Collapses** completed entries to one line (expandable)
|
||||
- **Polls** every 3s for live updates (same as current startPolling)
|
||||
- **No flashing** — entries only change status in place (tool_start → tool_done), never removed
|
||||
- **Persists** across page navigation (rehydrated from REST on load)
|
||||
- **Empty state** when no session: "Open a session to see agent activity"
|
||||
|
||||
### What gets removed from chat
|
||||
|
||||
- **ToolCallGroup** — the compact tool counter. Tools live in the timeline now.
|
||||
- **AgentIndicator at bottom** — partially. Keep it ONLY for the initial
|
||||
"thinking" state (before any tools fire). Once the first tool fires, the
|
||||
timeline is the source of truth and the chat indicator is redundant.
|
||||
Actually: remove it entirely. The timeline IS the indicator.
|
||||
|
||||
### What stays in chat
|
||||
|
||||
- **Agent text responses** — the thinking, conclusions, reports
|
||||
- **InlineApproval cards** — approvals need operator action, must be in chat
|
||||
- **Inline tool renderers** — entity cards, health summary, etc. (informational)
|
||||
- **User messages** — obviously
|
||||
|
||||
## Implementation
|
||||
|
||||
### 1. Data layer: `activityLog` derived store
|
||||
|
||||
Add to `chat.ts`:
|
||||
|
||||
```ts
|
||||
export interface ActivityEntry {
|
||||
id: string
|
||||
type: 'goal' | 'plan' | 'step_start' | 'step_done' | 'step_failed' |
|
||||
'tool_start' | 'tool_done' | 'tool_error' |
|
||||
'knowledge' | 'complete' | 'question' | 'error'
|
||||
description: string
|
||||
detail?: string // tool result text, step detail, etc.
|
||||
timestamp: number // Date.now() when created
|
||||
seq?: number // plan step seq, for ordering
|
||||
toolName?: string // for tool entries
|
||||
status: 'running' | 'done' | 'failed'
|
||||
collapsed: boolean // initial collapsed state (true for completed)
|
||||
}
|
||||
```
|
||||
|
||||
Derived reactively from `messages`, `planSteps`, `currentTask`, and session
|
||||
digest data. Uses `$derived.by()` to recompute when any source changes.
|
||||
|
||||
### 2. New component: `ActivityTimeline.svelte`
|
||||
|
||||
Replaces all three sidebar sections. Renders `activityLog` entries as a
|
||||
vertical timeline with connecting lines.
|
||||
|
||||
### 3. Remove from chat
|
||||
|
||||
- `<ToolCallGroup>` rendered in chat
|
||||
- `<AgentIndicator>` at bottom
|
||||
|
||||
### 4. Update TaskContextPanel
|
||||
|
||||
Replace PlanProgress + SessionDigest with ActivityTimeline.
|
||||
Reference in New Issue
Block a user