feat: move run timeline from side panel into inline chat turn activity panels

Replace the separate RunTimeline in the ActivityPanel with a generalized
TurnActivityPanel that renders inline in the chat pane between user
messages and assistant responses.

The new component:
- Shows all turn activities (thinking steps, tool calls, approvals,
  handoffs, run status) in a single collapsible panel
- Merges chat thinking messages with run timeline events into a
  chronological activity stream
- Auto-expands when a turn starts, auto-collapses on completion
- Displays a compact summary header (elapsed time, tool call count,
  handoff count, etc.) when collapsed
- Includes post-run git change summary with discard/commit actions
- Uses subtle entrance animations for rows

Removed components:
- ThinkingProcess.tsx (subsumed by TurnActivityPanel)
- RunTimeline.tsx (no longer needed as a standalone component)

The ActivityPanel retains its agents, session usage, and turn events
(diagnostics/hooks) sections.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-04-07 09:47:19 +02:00
co-authored by Copilot
parent a3e0bd9244
commit 3a71baf104
8 changed files with 468 additions and 615 deletions
+1 -30
View File
@@ -1,5 +1,5 @@
import { useMemo, type ReactNode } from 'react';
import { Activity, AlertTriangle, ArrowRight, BarChart3, CheckCircle2, Clock, Cog, ShieldAlert, Sparkles, Users, Zap } from 'lucide-react';
import { Activity, AlertTriangle, ArrowRight, BarChart3, CheckCircle2, Cog, ShieldAlert, Sparkles, Users, Zap } from 'lucide-react';
import {
buildAgentActivityRows,
@@ -15,10 +15,8 @@ import {
type SessionRequestUsageState,
type TurnEventLog,
} from '@renderer/lib/sessionActivity';
import { RunTimeline } from '@renderer/components/RunTimeline';
import { inferProvider } from '@shared/domain/models';
import { resolveWorkflowAgentNodes, type AgentNodeConfig, type WorkflowDefinition, type WorkflowOrchestrationMode } from '@shared/domain/workflow';
import type { ProjectGitFileReference } from '@shared/domain/project';
import type { SessionRecord } from '@shared/domain/session';
import { ProviderIcon } from './ProviderIcons';
@@ -208,9 +206,6 @@ function formatTurnEventTimestamp(iso: string): string {
interface ActivityPanelProps {
activity?: SessionActivityState;
onJumpToMessage?: (messageId: string) => void;
onDiscard?: (sessionId: string, runId: string, files?: ProjectGitFileReference[]) => Promise<unknown>;
onOpenCommitComposer?: () => void;
workflow: WorkflowDefinition;
session: SessionRecord;
sessionRequestUsage?: SessionRequestUsageState;
@@ -219,9 +214,6 @@ interface ActivityPanelProps {
export function ActivityPanel({
activity,
onJumpToMessage,
onDiscard,
onOpenCommitComposer,
workflow,
session,
sessionRequestUsage,
@@ -346,27 +338,6 @@ export function ActivityPanel({
</div>
)}
{/* ── Run timeline section ─────────────────────────── */}
<div className="mb-4">
<SectionHeader>
<Clock className="size-3" />
<span>Timeline</span>
{session.runs.length > 0 && (
<span className="font-mono rounded-full bg-[var(--color-surface-2)] px-1.5 py-0.5 text-[9px] tabular-nums text-[var(--color-text-muted)]">
{session.runs.length}
</span>
)}
</SectionHeader>
<RunTimeline
onDiscard={onDiscard}
onJumpToMessage={onJumpToMessage}
onOpenCommitComposer={onOpenCommitComposer}
runs={session.runs}
sessionId={session.id}
/>
</div>
{/* ── Turn events section ─────────────────────────── */}
{turnEvents && turnEvents.length > 0 && (
<div className="mb-4">