fix: update agent field names in frontend to match backend DTO
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m6s
CI / docker (push) Successful in 57s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 37s

The AgentInstanceResponse backend DTO uses instanceId, displayName,
applicationId, status — but the stale schema.d.ts still had id, name,
application, state. This caused the runtime table to show no data.

- Update schema.d.ts AgentInstanceResponse fields
- Fix AgentHealth: row.id→instanceId, row.name→displayName,
  row.application→applicationId, inst.id→instanceId
- Fix AgentInstance: agent.id→instanceId, agent.name→displayName
- Fix ExchangeHeader: agent.id→instanceId, agent.state→status
- Fix LayoutShell search: agent.state→status, agentTps→tps

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-01 20:36:31 +02:00
parent f82aa26371
commit a028905e41
5 changed files with 21 additions and 21 deletions

View File

@@ -1916,9 +1916,9 @@ export interface components {
}; };
/** @description Agent instance summary with runtime metrics */ /** @description Agent instance summary with runtime metrics */
AgentInstanceResponse: { AgentInstanceResponse: {
id: string; instanceId: string;
name: string; displayName: string;
application: string; applicationId: string;
status: string; status: string;
routeIds: string[]; routeIds: string[];
/** Format: date-time */ /** Format: date-time */

View File

@@ -51,12 +51,12 @@ function buildSearchData(
if (agents) { if (agents) {
for (const agent of agents) { for (const agent of agents) {
results.push({ results.push({
id: agent.id, id: agent.instanceId,
category: 'agent', category: 'agent',
title: agent.name, title: agent.displayName,
badges: [{ label: (agent.state || 'unknown').toUpperCase(), color: healthToColor((agent.state || '').toLowerCase()) }], badges: [{ label: (agent.status || 'unknown').toUpperCase(), color: healthToColor((agent.status || '').toLowerCase()) }],
meta: `${agent.application} · ${agent.version || ''}${agent.agentTps != null ? ` · ${agent.agentTps.toFixed(1)} msg/s` : ''}`, meta: `${agent.applicationId} · ${agent.version || ''}${agent.tps != null ? ` · ${agent.tps.toFixed(1)} msg/s` : ''}`,
path: `/runtime/${agent.application}/${agent.id}`, path: `/runtime/${agent.applicationId}/${agent.instanceId}`,
}); });
} }
} }

View File

@@ -70,7 +70,7 @@ interface AppGroup {
function groupByApp(agentList: AgentInstance[]): AppGroup[] { function groupByApp(agentList: AgentInstance[]): AppGroup[] {
const map = new Map<string, AgentInstance[]>(); const map = new Map<string, AgentInstance[]>();
for (const a of agentList) { for (const a of agentList) {
const app = a.application; const app = a.applicationId;
const list = map.get(app) ?? []; const list = map.get(app) ?? [];
list.push(a); list.push(a);
map.set(app, list); map.set(app, list);
@@ -225,7 +225,7 @@ export default function AgentHealth() {
title="Open instance page" title="Open instance page"
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
navigate(`/agents/${row.application}/${row.id}`); navigate(`/agents/${row.applicationId}/${row.instanceId}`);
}} }}
> >
<ExternalLink size={14} /> <ExternalLink size={14} />
@@ -236,7 +236,7 @@ export default function AgentHealth() {
key: 'name', key: 'name',
header: 'Instance', header: 'Instance',
render: (_val, row) => ( render: (_val, row) => (
<MonoText size="sm" className={styles.instanceName}>{row.name ?? row.id}</MonoText> <MonoText size="sm" className={styles.instanceName}>{row.displayName ?? row.instanceId}</MonoText>
), ),
}, },
{ {
@@ -298,7 +298,7 @@ export default function AgentHealth() {
); );
function handleInstanceClick(inst: AgentInstance) { function handleInstanceClick(inst: AgentInstance) {
navigate(`/runtime/${inst.application}/${inst.id}`); navigate(`/runtime/${inst.applicationId}/${inst.instanceId}`);
} }
const isFullWidth = !!appId; const isFullWidth = !!appId;
@@ -526,9 +526,9 @@ export default function AgentHealth() {
) : undefined ) : undefined
} }
> >
<DataTable<AgentInstance> <DataTable<AgentInstance & { id: string }>
columns={instanceColumns} columns={instanceColumns as Column<AgentInstance & { id: string }>[]}
data={group.instances} data={group.instances.map(i => ({ ...i, id: i.instanceId }))}
onRowClick={handleInstanceClick} onRowClick={handleInstanceClick}
pageSize={50} pageSize={50}
flush flush

View File

@@ -48,13 +48,13 @@ export default function AgentInstance() {
const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, undefined, appId); const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, undefined, appId);
const agent = useMemo( const agent = useMemo(
() => (agents || []).find((a: any) => a.id === instanceId) as any, () => (agents || []).find((a: any) => a.instanceId === instanceId) as any,
[agents, instanceId], [agents, instanceId],
); );
// Stat card metrics (latest 1 bucket) // Stat card metrics (latest 1 bucket)
const { data: latestMetrics } = useAgentMetrics( const { data: latestMetrics } = useAgentMetrics(
agent?.id || null, agent?.instanceId || null,
['jvm.cpu.process', 'jvm.memory.heap.used', 'jvm.memory.heap.max'], ['jvm.cpu.process', 'jvm.memory.heap.used', 'jvm.memory.heap.max'],
1, 1,
); );
@@ -65,7 +65,7 @@ export default function AgentInstance() {
// Chart metrics (60 buckets) // Chart metrics (60 buckets)
const { data: jvmMetrics } = useAgentMetrics( const { data: jvmMetrics } = useAgentMetrics(
agent?.id || null, agent?.instanceId || null,
['jvm.cpu.process', 'jvm.memory.heap.used', 'jvm.memory.heap.max', 'jvm.threads.count', 'jvm.gc.time'], ['jvm.cpu.process', 'jvm.memory.heap.used', 'jvm.memory.heap.max', 'jvm.threads.count', 'jvm.gc.time'],
60, 60,
); );
@@ -236,7 +236,7 @@ export default function AgentInstance() {
{appId} {appId}
</Link> </Link>
<span className={styles.scopeSep}><ChevronRight size={12} /></span> <span className={styles.scopeSep}><ChevronRight size={12} /></span>
<span className={styles.scopeCurrent}>{agent.name}</span> <span className={styles.scopeCurrent}>{agent.displayName}</span>
<StatusDot variant={statusVariant} /> <StatusDot variant={statusVariant} />
<Badge label={agent.status} color={statusColor} /> <Badge label={agent.status} color={statusColor} />
{agent.version && <Badge label={agent.version} variant="outlined" color="auto" />} {agent.version && <Badge label={agent.version} variant="outlined" color="auto" />}

View File

@@ -54,9 +54,9 @@ export function ExchangeHeader({ detail, onCorrelatedSelect, onClearSelection }:
const { agentState, hasRouteControl, hasReplay } = useMemo(() => { const { agentState, hasRouteControl, hasReplay } = useMemo(() => {
if (!agents) return { agentState: undefined, hasRouteControl: false, hasReplay: false }; if (!agents) return { agentState: undefined, hasRouteControl: false, hasReplay: false };
const agentList = agents as any[]; const agentList = agents as any[];
const agent = detail.instanceId ? agentList.find((a: any) => a.id === detail.instanceId) : undefined; const agent = detail.instanceId ? agentList.find((a: any) => a.instanceId === detail.instanceId) : undefined;
return { return {
agentState: agent?.state?.toLowerCase() as 'live' | 'stale' | 'dead' | undefined, agentState: agent?.status?.toLowerCase() as 'live' | 'stale' | 'dead' | undefined,
hasRouteControl: agentList.some((a: any) => a.capabilities?.routeControl === true), hasRouteControl: agentList.some((a: any) => a.capabilities?.routeControl === true),
hasReplay: agentList.some((a: any) => a.capabilities?.replay === true), hasReplay: agentList.some((a: any) => a.capabilities?.replay === true),
}; };