feat: event-type icons for agent event feeds
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m7s
CI / docker (push) Successful in 1m0s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 53s

Icons now reflect event type (UserPlus for registration, Skull
for dead, HeartPulse for recovery, Route for state changes, etc.)
while severity still drives the color. Updated in both
AgentInstance and AgentHealth pages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-02 23:06:01 +02:00
parent 9b401558a5
commit 62b5c56c56
2 changed files with 65 additions and 20 deletions

View File

@@ -1,6 +1,6 @@
import { useState, useMemo, useCallback } from 'react';
import { useParams, useNavigate } from 'react-router';
import { ExternalLink, RefreshCw, Pencil } from 'lucide-react';
import { ExternalLink, RefreshCw, Pencil, UserPlus, UserMinus, Play, Square, Clock, Skull, HeartPulse, Route, Send, Activity } from 'lucide-react';
import {
StatCard, StatusDot, Badge, MonoText,
GroupCard, DataTable, EventFeed,
@@ -195,22 +195,44 @@ export default function AgentHealth() {
// Map events to FeedEvent
const feedEvents: FeedEvent[] = useMemo(() => {
const eventIcon = (type: string) => {
switch (type) {
case 'REGISTERED': return <UserPlus size={14} />;
case 'DEREGISTERED': return <UserMinus size={14} />;
case 'AGENT_STARTED': return <Play size={14} />;
case 'AGENT_STOPPED': return <Square size={14} />;
case 'WENT_STALE': return <Clock size={14} />;
case 'WENT_DEAD': return <Skull size={14} />;
case 'RECOVERED': return <HeartPulse size={14} />;
case 'ROUTE_STATE_CHANGED': return <Route size={14} />;
case 'COMMAND_DELIVERED':
case 'COMMAND_ACKNOWLEDGED': return <Send size={14} />;
default: return <Activity size={14} />;
}
};
const eventSeverity = (type: string): FeedEvent['severity'] => {
switch (type) {
case 'WENT_DEAD':
case 'AGENT_STOPPED':
case 'DEREGISTERED': return 'error';
case 'WENT_STALE': return 'warning';
case 'RECOVERED':
case 'REGISTERED':
case 'AGENT_STARTED': return 'success';
default: return 'running';
}
};
const mapped = (events ?? []).map((e: { id: number; instanceId: string; eventType: string; detail: string; timestamp: string }) => ({
id: String(e.id),
severity:
e.eventType === 'WENT_DEAD'
? ('error' as const)
: e.eventType === 'WENT_STALE'
? ('warning' as const)
: e.eventType === 'RECOVERED'
? ('success' as const)
: ('running' as const),
severity: eventSeverity(e.eventType),
icon: eventIcon(e.eventType),
message: `${e.instanceId}: ${e.eventType}${e.detail ? ' \u2014 ' + e.detail : ''}`,
timestamp: new Date(e.timestamp),
}));
return eventSortAsc ? mapped.toReversed() : mapped;
}, [events, eventSortAsc],
);
}, [events, eventSortAsc]);
// Column definitions for the instance DataTable
const instanceColumns: Column<AgentInstance>[] = useMemo(

View File

@@ -1,6 +1,6 @@
import { useMemo, useState } from 'react';
import { useParams, Link } from 'react-router';
import { RefreshCw, ChevronRight } from 'lucide-react';
import { RefreshCw, ChevronRight, UserPlus, UserMinus, Play, Square, Clock, Skull, HeartPulse, Route, Send, Activity } from 'lucide-react';
import {
StatCard, StatusDot, Badge, LineChart, AreaChart, BarChart,
EventFeed, Spinner, EmptyState, SectionHeader, MonoText,
@@ -82,18 +82,41 @@ export default function AgentInstance() {
);
const feedEvents = useMemo<FeedEvent[]>(() => {
const eventIcon = (type: string) => {
switch (type) {
case 'REGISTERED': return <UserPlus size={14} />;
case 'DEREGISTERED': return <UserMinus size={14} />;
case 'AGENT_STARTED': return <Play size={14} />;
case 'AGENT_STOPPED': return <Square size={14} />;
case 'WENT_STALE': return <Clock size={14} />;
case 'WENT_DEAD': return <Skull size={14} />;
case 'RECOVERED': return <HeartPulse size={14} />;
case 'ROUTE_STATE_CHANGED': return <Route size={14} />;
case 'COMMAND_DELIVERED':
case 'COMMAND_ACKNOWLEDGED': return <Send size={14} />;
default: return <Activity size={14} />;
}
};
const eventSeverity = (type: string): FeedEvent['severity'] => {
switch (type) {
case 'WENT_DEAD':
case 'AGENT_STOPPED':
case 'DEREGISTERED': return 'error';
case 'WENT_STALE': return 'warning';
case 'RECOVERED':
case 'REGISTERED':
case 'AGENT_STARTED': return 'success';
default: return 'running';
}
};
const mapped = (events || [])
.filter((e: any) => !instanceId || e.instanceId === instanceId)
.map((e: any) => ({
id: String(e.id),
severity:
e.eventType === 'WENT_DEAD'
? ('error' as const)
: e.eventType === 'WENT_STALE'
? ('warning' as const)
: e.eventType === 'RECOVERED'
? ('success' as const)
: ('running' as const),
severity: eventSeverity(e.eventType),
icon: eventIcon(e.eventType),
message: `${e.eventType}${e.detail ? ' \u2014 ' + e.detail : ''}`,
timestamp: new Date(e.timestamp),
}));