feat: add approval checkpoint UX across renderer

- ChatPane: approval banner with approve/reject, final-response preview, error handling
- PatternEditor: approval checkpoints section with toggles and agent scope selector
- Sidebar: amber awaiting-approval badge replaces running indicator when pending
- ActivityPanel: shield icon approval badge in header
- RunTimeline: approval kind badge, detail text, status-aware colors

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-03-24 19:52:23 +01:00
co-authored by Copilot
parent 2aa8d73b2d
commit f54cbdb6b1
6 changed files with 371 additions and 13 deletions
+10 -2
View File
@@ -1,5 +1,5 @@
import { useMemo, type ReactNode } from 'react';
import { Activity, Clock, Server, Code, Sparkles, Users } from 'lucide-react';
import { Activity, Clock, Server, Code, ShieldAlert, Sparkles, Users } from 'lucide-react';
import {
buildAgentActivityRows,
@@ -183,6 +183,7 @@ export function ActivityPanel({
const selection = useMemo(() => resolveSessionToolingSelection(session), [session]);
const isBusy = session.status === 'running';
const hasPendingApproval = session.pendingApproval?.status === 'pending';
const toolsDisabled = isBusy || projectIsScratchpad;
const accent = modeAccent[pattern.mode] ?? modeAccent.single;
const hasTools = mcpServers.length > 0 || lspProfiles.length > 0;
@@ -196,7 +197,14 @@ export function ActivityPanel({
<span className="text-[12px] font-semibold uppercase tracking-[0.12em] text-zinc-400">
Activity
</span>
{isBusy && <span className="size-1.5 animate-pulse rounded-full bg-blue-400" />}
{hasPendingApproval ? (
<span className="flex items-center gap-1">
<ShieldAlert className="size-3 text-amber-400" />
<span className="text-[9px] font-semibold uppercase tracking-wider text-amber-400">Approval</span>
</span>
) : isBusy ? (
<span className="size-1.5 animate-pulse rounded-full bg-blue-400" />
) : null}
</div>
</div>