Files
oikos/web/src/lib/components/AgentIndicator.svelte
dtoro 6a8efd22bb feat(web): redesign task rail — Plan/Event log polish, entity graph resize fix
- Plan/Activity panels: humanize step titles, richer icons, empty states
  matching Scope's illustration style, pretty-printed expandable detail
- Activity log renamed to Event log; every step now expandable
- Chat: middle-truncate header title, remove redundant task-list rail and
  header stat cluster (duplicated in the sidebar), simplify markdown styling
- Fix --font-mono actually being a monospace font (was aliased to DM Sans)
- Replace rotating loader-circle spinner with a smoother fading-blade Spinner
- SessionGraph entity detail panel: resizable and self-clamping against its
  live container size (was overflowing into sibling sections), close button
- Dev launch config: fetch bearer token from the running api container so
  `npm run dev` works against the local compose stack without a hardcoded
  secret in a tracked file

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 08:22:08 +02:00

43 lines
1.3 KiB
Svelte

<script lang="ts">
import type { ActivityEntry } from '$lib/stores/activity'
import Spinner from './Spinner.svelte'
import CheckIcon from '@lucide/svelte/icons/check'
import XIcon from '@lucide/svelte/icons/x'
let { active = false, lastActivity = null as ActivityEntry | null, error = '' }: { active?: boolean; lastActivity?: ActivityEntry | null; error?: string } = $props()
let done = $state(false)
let wasActive = $state(false)
$effect(() => {
if (active) { done = false; wasActive = true }
if (!active && wasActive) {
done = true
const t = setTimeout(() => { done = false; wasActive = false }, 3000)
return () => clearTimeout(t)
}
})
const label = $derived.by(() => {
if (error) return error
if (!active && done) return 'Done'
if (lastActivity) return lastActivity.description
return 'Agent is thinking…'
})
</script>
{#if active || done || error}
<div class="flex items-center gap-2 py-2 text-xs transition-opacity {error ? 'text-destructive' : done ? 'text-success opacity-50' : 'text-muted-foreground'}">
<span class="shrink-0">
{#if error}
<XIcon class="size-3" />
{:else if done}
<CheckIcon class="size-3" />
{:else}
<Spinner class="size-3 text-primary" />
{/if}
</span>
<span>{label}</span>
</div>
{/if}