From 24cc3b1f4eda1527f9148016eba4e9a6c13a3f40 Mon Sep 17 00:00:00 2001 From: dtoro Date: Tue, 14 Jul 2026 13:07:49 +0200 Subject: [PATCH] approval lifecycle entries in Activity timeline - activityLog now detects 'requires approval' in tool results - Adds approval entries with shield icon + description + execution ID - Works for both run and remaining approval paths --- VERSION | 2 +- .../lib/components/ActivityTimeline.svelte | 2 ++ web/src/lib/stores/activity.ts | 24 ++++++++++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 6678432..940ac09 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.3.8 +0.3.9 diff --git a/web/src/lib/components/ActivityTimeline.svelte b/web/src/lib/components/ActivityTimeline.svelte index 692d1e3..5827712 100644 --- a/web/src/lib/components/ActivityTimeline.svelte +++ b/web/src/lib/components/ActivityTimeline.svelte @@ -8,6 +8,7 @@ import SparklesIcon from '@lucide/svelte/icons/sparkles' import HelpCircleIcon from '@lucide/svelte/icons/help-circle' import FlagIcon from '@lucide/svelte/icons/flag' + import ShieldIcon from '@lucide/svelte/icons/shield' import ChevronDownIcon from '@lucide/svelte/icons/chevron-down' import ChevronRightIcon from '@lucide/svelte/icons/chevron-right' @@ -29,6 +30,7 @@ case 'knowledge': return SparklesIcon case 'complete': return FlagIcon case 'question': return HelpCircleIcon + case 'approval': return ShieldIcon default: return null } } diff --git a/web/src/lib/stores/activity.ts b/web/src/lib/stores/activity.ts index 3caf4d7..2313c76 100644 --- a/web/src/lib/stores/activity.ts +++ b/web/src/lib/stores/activity.ts @@ -8,7 +8,8 @@ export interface ActivityEntry { id: string type: 'goal' | 'plan' | 'step_running' | 'step_done' | 'step_failed' | 'tool_running' | 'tool_done' | 'tool_error' | - 'knowledge' | 'complete' | 'question' | 'error' + 'knowledge' | 'complete' | 'question' | 'error' | + 'approval' description: string detail?: string timestamp: number @@ -127,6 +128,27 @@ export const activityLog = derived([messages, planSteps, currentTask], ([$msgs, }) } + // Approvals — detect from tool results containing 'requires approval' + for (let mi = 0; mi < $msgs.length; mi++) { + for (const t of $msgs[mi].tools) { + if (t.type !== 'tool_result') continue + const text = typeof t.result === 'string' ? t.result : JSON.stringify(t.result ?? '') + if (text.includes('requires approval')) { + const m = text.match(/execution\s+([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/i) + const execId = m ? m[1] : '' + const target = (t.args as any)?.target ?? '' + const purpose = (t.args as any)?.purpose ?? '' + entries.push({ + id: execId || `approval_${mi}`, + type: 'approval', + description: purpose ? `Approval: ${purpose.slice(0, 60)}` : `Approval required${target ? ` for ${target}` : ''}`, + timestamp: now - ($msgs.length - mi) * 1000, + status: 'running' + }) + } + } + } + // Sort oldest first entries.sort((a, b) => a.timestamp - b.timestamp)