From 4cdbcdaeea099135aead060f773fb31980a47d20 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Wed, 1 Apr 2026 18:22:16 +0200 Subject: [PATCH] fix: update frontend field names for identity rename (applicationId, instanceId) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The backend identity rename (applicationName → applicationId, agentId → instanceId) was not reflected in the frontend. This caused drilldown to fail (detail.applicationName was undefined, disabling the diagram fetch) and various display issues. Updated schema.d.ts, ExchangeHeader, ExecutionDiagram, Dashboard, AgentHealth, AgentInstance, LayoutShell, LogTab, InfoTab, DetailPanel, ExchangesPage, and tracing-store. Co-Authored-By: Claude Opus 4.6 (1M context) --- ui/src/api/schema.d.ts | 12 ++++---- .../ExecutionDiagram/DetailPanel.tsx | 2 +- .../ExecutionDiagram/ExecutionDiagram.tsx | 2 +- .../ExecutionDiagram/tabs/InfoTab.tsx | 2 +- .../ExecutionDiagram/tabs/LogTab.tsx | 6 ++-- ui/src/components/LayoutShell.tsx | 10 +++---- ui/src/pages/AgentHealth/AgentHealth.tsx | 2 +- ui/src/pages/AgentInstance/AgentInstance.tsx | 2 +- ui/src/pages/Dashboard/Dashboard.tsx | 12 ++++---- ui/src/pages/Exchanges/ExchangeHeader.tsx | 30 +++++++++---------- ui/src/pages/Exchanges/ExchangesPage.tsx | 12 ++++---- ui/src/stores/tracing-store.ts | 2 +- 12 files changed, 47 insertions(+), 47 deletions(-) diff --git a/ui/src/api/schema.d.ts b/ui/src/api/schema.d.ts index a2e35ae4..90afbf8a 100644 --- a/ui/src/api/schema.d.ts +++ b/ui/src/api/schema.d.ts @@ -1487,8 +1487,8 @@ export interface components { ExecutionSummary: { executionId: string; routeId: string; - agentId: string; - applicationName: string; + instanceId: string; + applicationId: string; status: string; /** Format: date-time */ startTime: string; @@ -1807,8 +1807,8 @@ export interface components { ExecutionDetail: { executionId: string; routeId: string; - agentId: string; - applicationName: string; + instanceId: string; + applicationId: string; status: string; /** Format: date-time */ startTime: string; @@ -1959,8 +1959,8 @@ export interface components { AgentEventResponse: { /** Format: int64 */ id: number; - agentId: string; - appId: string; + instanceId: string; + applicationId: string; eventType: string; detail: string; /** Format: date-time */ diff --git a/ui/src/components/ExecutionDiagram/DetailPanel.tsx b/ui/src/components/ExecutionDiagram/DetailPanel.tsx index 1b2b9771..9de312bc 100644 --- a/ui/src/components/ExecutionDiagram/DetailPanel.tsx +++ b/ui/src/components/ExecutionDiagram/DetailPanel.tsx @@ -159,7 +159,7 @@ export function DetailPanel({ )} {activeTab === 'log' && ( diff --git a/ui/src/components/ExecutionDiagram/ExecutionDiagram.tsx b/ui/src/components/ExecutionDiagram/ExecutionDiagram.tsx index b5239b74..11e923f6 100644 --- a/ui/src/components/ExecutionDiagram/ExecutionDiagram.tsx +++ b/ui/src/components/ExecutionDiagram/ExecutionDiagram.tsx @@ -193,7 +193,7 @@ export function ExecutionDiagram({ ↓ JSON - +
Status
diff --git a/ui/src/components/ExecutionDiagram/tabs/LogTab.tsx b/ui/src/components/ExecutionDiagram/tabs/LogTab.tsx index 6495c540..34f076ac 100644 --- a/ui/src/components/ExecutionDiagram/tabs/LogTab.tsx +++ b/ui/src/components/ExecutionDiagram/tabs/LogTab.tsx @@ -4,7 +4,7 @@ import type { LogEntryResponse } from '../../../api/queries/logs'; import styles from '../ExecutionDiagram.module.css'; interface LogTabProps { - applicationName: string; + applicationId: string; exchangeId?: string; processorId: string | null; } @@ -28,11 +28,11 @@ function formatTime(iso: string): string { return `${h}:${m}:${s}.${ms}`; } -export function LogTab({ applicationName, exchangeId, processorId }: LogTabProps) { +export function LogTab({ applicationId, exchangeId, processorId }: LogTabProps) { const [filter, setFilter] = useState(''); const { data: logs, isLoading } = useApplicationLogs( - applicationName, + applicationId, undefined, { exchangeId, limit: 500 }, ); diff --git a/ui/src/components/LayoutShell.tsx b/ui/src/components/LayoutShell.tsx index bc3b033a..2827f7ff 100644 --- a/ui/src/components/LayoutShell.tsx +++ b/ui/src/components/LayoutShell.tsx @@ -138,8 +138,8 @@ function LayoutContent() { category: 'exchange' as const, title: e.executionId, badges: [{ label: e.status, color: statusToColor(e.status) }], - meta: `${e.routeId} · ${e.applicationName ?? ''} · ${formatDuration(e.durationMs)}`, - path: `/exchanges/${e.applicationName ?? ''}/${e.routeId}/${e.executionId}`, + meta: `${e.routeId} · ${e.applicationId ?? ''} · ${formatDuration(e.durationMs)}`, + path: `/exchanges/${e.applicationId ?? ''}/${e.routeId}/${e.executionId}`, serverFiltered: true, matchContext: e.highlight ?? undefined, })); @@ -156,8 +156,8 @@ function LayoutContent() { category: 'attribute' as const, title: `${key} = "${value}"`, badges: [{ label: e.status, color: statusToColor(e.status) }], - meta: `${e.executionId} · ${e.routeId} · ${e.applicationName ?? ''}`, - path: `/exchanges/${e.applicationName ?? ''}/${e.routeId}/${e.executionId}`, + meta: `${e.executionId} · ${e.routeId} · ${e.applicationId ?? ''}`, + path: `/exchanges/${e.applicationId ?? ''}/${e.routeId}/${e.executionId}`, serverFiltered: true, }); } @@ -218,7 +218,7 @@ function LayoutContent() { if (parts.length === 4 && parts[0] === 'exchanges') { state.selectedExchange = { executionId: parts[3], - applicationName: parts[1], + applicationId: parts[1], routeId: parts[2], }; } diff --git a/ui/src/pages/AgentHealth/AgentHealth.tsx b/ui/src/pages/AgentHealth/AgentHealth.tsx index fd0da9d5..b897111d 100644 --- a/ui/src/pages/AgentHealth/AgentHealth.tsx +++ b/ui/src/pages/AgentHealth/AgentHealth.tsx @@ -199,7 +199,7 @@ export default function AgentHealth() { : e.eventType === 'RECOVERED' ? ('success' as const) : ('running' as const), - message: `${e.agentId}: ${e.eventType}${e.detail ? ' \u2014 ' + e.detail : ''}`, + message: `${e.instanceId}: ${e.eventType}${e.detail ? ' \u2014 ' + e.detail : ''}`, timestamp: new Date(e.timestamp), })); return eventSortAsc ? mapped.toReversed() : mapped; diff --git a/ui/src/pages/AgentInstance/AgentInstance.tsx b/ui/src/pages/AgentInstance/AgentInstance.tsx index d202f666..77817c2b 100644 --- a/ui/src/pages/AgentInstance/AgentInstance.tsx +++ b/ui/src/pages/AgentInstance/AgentInstance.tsx @@ -83,7 +83,7 @@ export default function AgentInstance() { const feedEvents = useMemo(() => { const mapped = (events || []) - .filter((e: any) => !instanceId || e.agentId === instanceId) + .filter((e: any) => !instanceId || e.instanceId === instanceId) .map((e: any) => ({ id: String(e.id), severity: diff --git a/ui/src/pages/Dashboard/Dashboard.tsx b/ui/src/pages/Dashboard/Dashboard.tsx index 540f0058..0465b228 100644 --- a/ui/src/pages/Dashboard/Dashboard.tsx +++ b/ui/src/pages/Dashboard/Dashboard.tsx @@ -92,11 +92,11 @@ function buildBaseColumns(): Column[] { ), }, { - key: 'applicationName', + key: 'applicationId', header: 'Application', sortable: true, render: (_: unknown, row: Row) => ( - {row.applicationName ?? ''} + {row.applicationId ?? ''} ), }, { @@ -147,12 +147,12 @@ function buildBaseColumns(): Column[] { ), }, { - key: 'agentId', + key: 'instanceId', header: 'Agent', render: (_: unknown, row: Row) => ( - {row.agentId} + {row.instanceId} ), }, @@ -163,7 +163,7 @@ function buildBaseColumns(): Column[] { export interface SelectedExchange { executionId: string; - applicationName: string; + applicationId: string; routeId: string; } @@ -226,7 +226,7 @@ export default function Dashboard({ onExchangeSelect }: DashboardProps = {}) { if (onExchangeSelect) { onExchangeSelect({ executionId: row.executionId, - applicationName: row.applicationName ?? '', + applicationId: row.applicationId ?? '', routeId: row.routeId, }) } diff --git a/ui/src/pages/Exchanges/ExchangeHeader.tsx b/ui/src/pages/Exchanges/ExchangeHeader.tsx index bf409507..07ff4d34 100644 --- a/ui/src/pages/Exchanges/ExchangeHeader.tsx +++ b/ui/src/pages/Exchanges/ExchangeHeader.tsx @@ -12,7 +12,7 @@ import styles from './ExchangeHeader.module.css'; interface ExchangeHeaderProps { detail: ExecutionDetail; - onCorrelatedSelect?: (executionId: string, applicationName: string, routeId: string) => void; + onCorrelatedSelect?: (executionId: string, applicationId: string, routeId: string) => void; onClearSelection?: () => void; } @@ -50,17 +50,17 @@ export function ExchangeHeader({ detail, onCorrelatedSelect, onClearSelection }: const attrs = Object.entries(detail.attributes ?? {}); // Look up agent state for icon coloring + route control capability - const { data: agents } = useAgents(undefined, detail.applicationName); + const { data: agents } = useAgents(undefined, detail.applicationId); const { agentState, hasRouteControl, hasReplay } = useMemo(() => { if (!agents) return { agentState: undefined, hasRouteControl: false, hasReplay: false }; const agentList = agents as any[]; - const agent = detail.agentId ? agentList.find((a: any) => a.id === detail.agentId) : undefined; + const agent = detail.instanceId ? agentList.find((a: any) => a.id === detail.instanceId) : undefined; return { agentState: agent?.state?.toLowerCase() as 'live' | 'stale' | 'dead' | undefined, hasRouteControl: agentList.some((a: any) => a.capabilities?.routeControl === true), hasReplay: agentList.some((a: any) => a.capabilities?.replay === true), }; - }, [agents, detail.agentId]); + }, [agents, detail.instanceId]); const roles = useAuthStore((s) => s.roles); const canControl = roles.some(r => r === 'OPERATOR' || r === 'ADMIN'); @@ -80,21 +80,21 @@ export function ExchangeHeader({ detail, onCorrelatedSelect, onClearSelection }: )} - - - {detail.agentId && ( + {detail.instanceId && ( <> - - @@ -105,11 +105,11 @@ export function ExchangeHeader({ detail, onCorrelatedSelect, onClearSelection }: {/* Route control / replay — only if agent supports it AND user has operator+ role */} {canControl && (hasRouteControl || hasReplay) && ( { if (!isCurrent && onCorrelatedSelect) { - onCorrelatedSelect(ce.executionId, ce.applicationName ?? detail.applicationName, ce.routeId); + onCorrelatedSelect(ce.executionId, ce.applicationId ?? detail.applicationId, ce.routeId); } }} title={`${ce.executionId}\n${ce.routeId} \u2014 ${formatDuration(ce.durationMs)}${isReplay ? '\n(replay)' : ''}`} diff --git a/ui/src/pages/Exchanges/ExchangesPage.tsx b/ui/src/pages/Exchanges/ExchangesPage.tsx index 69a7606f..c1ab76bd 100644 --- a/ui/src/pages/Exchanges/ExchangesPage.tsx +++ b/ui/src/pages/Exchanges/ExchangesPage.tsx @@ -29,7 +29,7 @@ export default function ExchangesPage() { // Derive selection from URL params when no state-based selection exists (Cmd-K, bookmarks) const urlDerivedExchange: SelectedExchange | null = (scopedExchangeId && scopedAppId && scopedRouteId) - ? { executionId: scopedExchangeId, applicationName: scopedAppId, routeId: scopedRouteId } + ? { executionId: scopedExchangeId, applicationId: scopedAppId, routeId: scopedRouteId } : null; const [selected, setSelectedInternal] = useState(stateSelected ?? urlDerivedExchange); @@ -42,7 +42,7 @@ export default function ExchangesPage() { } else if (scopedExchangeId && scopedAppId && scopedRouteId) { setSelectedInternal({ executionId: scopedExchangeId, - applicationName: scopedAppId, + applicationId: scopedAppId, routeId: scopedRouteId, }); } else { @@ -62,8 +62,8 @@ export default function ExchangesPage() { }, [navigate, location.pathname, location.search, location.state]); // Select a correlated exchange: push another history entry - const handleCorrelatedSelect = useCallback((executionId: string, applicationName: string, routeId: string) => { - const exchange = { executionId, applicationName, routeId }; + const handleCorrelatedSelect = useCallback((executionId: string, applicationId: string, routeId: string) => { + const exchange = { executionId, applicationId, routeId }; setSelectedInternal(exchange); navigate(location.pathname + location.search, { state: { ...location.state, selectedExchange: exchange }, @@ -106,7 +106,7 @@ export default function ExchangesPage() { } // Determine what the right panel shows - const panelAppId = selected?.applicationName ?? scopedAppId!; + const panelAppId = selected?.applicationId ?? scopedAppId!; const panelRouteId = selected?.routeId ?? scopedRouteId!; const panelExchangeId = selected?.executionId ?? undefined; @@ -135,7 +135,7 @@ interface DiagramPanelProps { appId: string; routeId: string; exchangeId?: string; - onCorrelatedSelect: (executionId: string, applicationName: string, routeId: string) => void; + onCorrelatedSelect: (executionId: string, applicationId: string, routeId: string) => void; onClearSelection: () => void; } diff --git a/ui/src/stores/tracing-store.ts b/ui/src/stores/tracing-store.ts index cb506f2d..7fdff759 100644 --- a/ui/src/stores/tracing-store.ts +++ b/ui/src/stores/tracing-store.ts @@ -3,7 +3,7 @@ import { create } from 'zustand' type CaptureMode = 'NONE' | 'INPUT' | 'OUTPUT' | 'BOTH' interface TracingState { - /** Key: applicationName → { processorId: captureMode } */ + /** Key: applicationId → { processorId: captureMode } */ tracedProcessors: Record> isTraced: (app: string, processorId: string) => boolean /** Toggle processor tracing (BOTH on, remove on off). Returns the full map for the app. */