2026-03-28 15:16:54 +01:00
import { useMemo } from 'react' ;
2026-03-28 15:00:45 +01:00
import { useNavigate } from 'react-router' ;
2026-03-30 23:26:55 +02:00
import { GitBranch , Server , RotateCcw } from 'lucide-react' ;
2026-03-28 13:55:13 +01:00
import { StatusDot , MonoText , Badge } from '@cameleer/design-system' ;
import { useCorrelationChain } from '../../api/queries/correlation' ;
2026-03-28 15:16:54 +01:00
import { useAgents } from '../../api/queries/agents' ;
2026-03-30 21:42:06 +02:00
import { useAuthStore } from '../../auth/auth-store' ;
2026-03-28 13:55:13 +01:00
import type { ExecutionDetail } from '../../components/ExecutionDiagram/types' ;
2026-03-28 15:37:49 +01:00
import { attributeBadgeColor } from '../../utils/attribute-color' ;
2026-03-30 21:42:06 +02:00
import { RouteControlBar } from './RouteControlBar' ;
2026-03-28 14:49:45 +01:00
import styles from './ExchangeHeader.module.css' ;
2026-03-28 13:55:13 +01:00
interface ExchangeHeaderProps {
detail : ExecutionDetail ;
fix: update frontend field names for identity rename (applicationId, instanceId)
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) <noreply@anthropic.com>
2026-04-01 18:22:16 +02:00
onCorrelatedSelect ? : ( executionId : string , applicationId : string , routeId : string ) = > void ;
2026-03-28 15:42:45 +01:00
onClearSelection ? : ( ) = > void ;
2026-03-28 13:55:13 +01:00
}
type StatusVariant = 'success' | 'error' | 'running' | 'warning' ;
function statusVariant ( s : string ) : StatusVariant {
switch ( s ) {
case 'COMPLETED' : return 'success' ;
case 'FAILED' : return 'error' ;
case 'RUNNING' : return 'running' ;
default : return 'warning' ;
}
}
2026-03-28 15:00:45 +01:00
function statusLabel ( s : string ) : string {
switch ( s ) {
case 'COMPLETED' : return 'OK' ;
case 'FAILED' : return 'ERR' ;
case 'RUNNING' : return 'RUN' ;
default : return s ;
}
}
2026-03-28 13:55:13 +01:00
function formatDuration ( ms : number ) : string {
if ( ms >= 60 _000 ) return ` ${ ( ms / 1000 ) . toFixed ( 0 ) } s ` ;
if ( ms >= 1000 ) return ` ${ ( ms / 1000 ) . toFixed ( 2 ) } s ` ;
return ` ${ ms } ms ` ;
}
2026-03-28 15:42:45 +01:00
export function ExchangeHeader ( { detail , onCorrelatedSelect , onClearSelection } : ExchangeHeaderProps ) {
2026-03-28 15:00:45 +01:00
const navigate = useNavigate ( ) ;
2026-03-28 13:55:13 +01:00
const { data : chainResult } = useCorrelationChain ( detail . correlationId ? ? null ) ;
const chain = chainResult ? . data ;
const showChain = chain && chain . length > 1 ;
2026-03-28 15:07:23 +01:00
const attrs = Object . entries ( detail . attributes ? ? { } ) ;
2026-03-28 13:55:13 +01:00
2026-03-30 21:42:06 +02:00
// Look up agent state for icon coloring + route control capability
fix: update frontend field names for identity rename (applicationId, instanceId)
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) <noreply@anthropic.com>
2026-04-01 18:22:16 +02:00
const { data : agents } = useAgents ( undefined , detail . applicationId ) ;
2026-03-30 21:42:06 +02:00
const { agentState , hasRouteControl , hasReplay } = useMemo ( ( ) = > {
if ( ! agents ) return { agentState : undefined , hasRouteControl : false , hasReplay : false } ;
const agentList = agents as any [ ] ;
fix: update agent field names in frontend to match backend DTO
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>
2026-04-01 20:36:31 +02:00
const agent = detail . instanceId ? agentList . find ( ( a : any ) = > a . instanceId === detail . instanceId ) : undefined ;
2026-03-30 21:42:06 +02:00
return {
fix: update agent field names in frontend to match backend DTO
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>
2026-04-01 20:36:31 +02:00
agentState : agent?.status?.toLowerCase ( ) as 'live' | 'stale' | 'dead' | undefined ,
2026-03-30 21:42:06 +02:00
hasRouteControl : agentList.some ( ( a : any ) = > a . capabilities ? . routeControl === true ) ,
hasReplay : agentList.some ( ( a : any ) = > a . capabilities ? . replay === true ) ,
} ;
fix: update frontend field names for identity rename (applicationId, instanceId)
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) <noreply@anthropic.com>
2026-04-01 18:22:16 +02:00
} , [ agents , detail . instanceId ] ) ;
2026-03-28 15:16:54 +01:00
2026-03-30 21:42:06 +02:00
const roles = useAuthStore ( ( s ) = > s . roles ) ;
const canControl = roles . some ( r = > r === 'OPERATOR' || r === 'ADMIN' ) ;
2026-03-28 13:55:13 +01:00
return (
2026-03-28 14:49:45 +01:00
< div className = { styles . header } >
2026-03-28 15:00:45 +01:00
{ /* Exchange info — always shown */ }
< div className = { styles . info } >
< StatusDot variant = { statusVariant ( detail . status ) } / >
< Badge label = { statusLabel ( detail . status ) } color = { statusVariant ( detail . status ) } / >
2026-03-28 15:07:23 +01:00
{ attrs . length > 0 && (
< >
< span className = { styles . separator } / >
{ attrs . map ( ( [ k , v ] ) = > (
2026-03-28 15:37:49 +01:00
< Badge key = { k } label = { ` ${ k } : ${ v } ` } color = { attributeBadgeColor ( String ( v ) ) } / >
2026-03-28 15:07:23 +01:00
) ) }
< / >
) }
< span className = { styles . separator } / >
fix: update frontend field names for identity rename (applicationId, instanceId)
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) <noreply@anthropic.com>
2026-04-01 18:22:16 +02:00
< button className = { styles . linkBtn } onClick = { ( ) = > { onClearSelection ? . ( ) ; navigate ( ` /exchanges/ ${ detail . applicationId } ` ) ; } } title = "Show all exchanges for this application" >
< span className = { styles . app } > { detail . applicationId } < / span >
2026-03-28 15:14:48 +01:00
< / button >
fix: update frontend field names for identity rename (applicationId, instanceId)
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) <noreply@anthropic.com>
2026-04-01 18:22:16 +02:00
< button className = { styles . linkBtn } onClick = { ( ) = > { onClearSelection ? . ( ) ; navigate ( ` /exchanges/ ${ detail . applicationId } / ${ detail . routeId } ` ) ; } } title = "Show all exchanges for this route" >
2026-03-28 15:14:48 +01:00
< span className = { styles . route } > { detail . routeId } < / span >
< GitBranch size = { 12 } className = { styles . icon } / >
< / button >
fix: update frontend field names for identity rename (applicationId, instanceId)
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) <noreply@anthropic.com>
2026-04-01 18:22:16 +02:00
{ detail . instanceId && (
2026-03-28 15:07:58 +01:00
< >
< span className = { styles . separator } / >
fix: update frontend field names for identity rename (applicationId, instanceId)
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) <noreply@anthropic.com>
2026-04-01 18:22:16 +02:00
< button className = { styles . linkBtn } onClick = { ( ) = > navigate ( ` /runtime/ ${ detail . applicationId } ` ) } title = "All agents for this application" >
< span className = { styles . app } > { detail . applicationId } < / span >
2026-03-28 15:16:54 +01:00
< / button >
fix: update frontend field names for identity rename (applicationId, instanceId)
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) <noreply@anthropic.com>
2026-04-01 18:22:16 +02:00
< button className = { styles . linkBtn } onClick = { ( ) = > navigate ( ` /runtime/ ${ detail . applicationId } / ${ detail . instanceId } ` ) } title = "Agent details" >
< MonoText size = "xs" > { detail . instanceId } < / MonoText >
2026-03-28 15:16:54 +01:00
< Server size = { 12 } className = { agentState === 'live' ? styles.iconLive : agentState === 'stale' ? styles.iconStale : agentState === 'dead' ? styles.iconDead : styles.icon } / >
2026-03-28 15:14:48 +01:00
< / button >
2026-03-28 15:07:58 +01:00
< / >
) }
2026-03-28 15:09:00 +01:00
< span className = { styles . duration } > { formatDuration ( detail . durationMs ) } < / span >
2026-03-28 15:00:45 +01:00
< / div >
2026-03-30 21:42:06 +02:00
{ /* Route control / replay — only if agent supports it AND user has operator+ role */ }
{ canControl && ( hasRouteControl || hasReplay ) && (
< RouteControlBar
fix: update frontend field names for identity rename (applicationId, instanceId)
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) <noreply@anthropic.com>
2026-04-01 18:22:16 +02:00
application = { detail . applicationId }
2026-03-30 21:42:06 +02:00
routeId = { detail . routeId }
hasRouteControl = { hasRouteControl }
hasReplay = { hasReplay }
fix: update frontend field names for identity rename (applicationId, instanceId)
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) <noreply@anthropic.com>
2026-04-01 18:22:16 +02:00
agentId = { detail . instanceId }
2026-03-30 21:42:06 +02:00
exchangeId = { detail . exchangeId }
inputHeaders = { detail . inputHeaders }
inputBody = { detail . inputBody }
/ >
) }
2026-03-28 15:24:20 +01:00
{ /* Correlation chain */ }
< div className = { styles . chain } >
< span className = { styles . chainLabel } > Correlated < / span >
{ showChain ? chain . map ( ( ce : any , i : number ) = > {
2026-03-28 14:49:45 +01:00
const isCurrent = ce . executionId === detail . executionId ;
const variant = statusVariant ( ce . status ) ;
2026-03-31 14:39:40 +02:00
const isReplay = ! ! ce . isReplay ;
2026-03-28 14:49:45 +01:00
const statusCls =
variant === 'success' ? styles . chainNodeSuccess
: variant === 'error' ? styles . chainNodeError
: variant === 'running' ? styles . chainNodeRunning
: styles . chainNodeWarning ;
return (
2026-03-28 15:00:45 +01:00
< span key = { ce . executionId } className = { styles . chainEntry } >
{ i > 0 && < span className = { styles . chainArrow } > & rarr ; < / span > }
< button
className = { ` ${ styles . chainNode } ${ statusCls } ${ isCurrent ? styles . chainNodeCurrent : '' } ` }
onClick = { ( ) = > {
2026-03-28 15:26:01 +01:00
if ( ! isCurrent && onCorrelatedSelect ) {
fix: update frontend field names for identity rename (applicationId, instanceId)
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) <noreply@anthropic.com>
2026-04-01 18:22:16 +02:00
onCorrelatedSelect ( ce . executionId , ce . applicationId ? ? detail . applicationId , ce . routeId ) ;
2026-03-28 15:00:45 +01:00
}
} }
2026-03-30 23:26:55 +02:00
title = { ` ${ ce . executionId } \ n ${ ce . routeId } \ u2014 ${ formatDuration ( ce . durationMs ) } ${ isReplay ? '\n(replay)' : '' } ` }
2026-03-28 15:00:45 +01:00
>
< StatusDot variant = { variant } / >
2026-03-30 23:26:55 +02:00
{ isReplay && < RotateCcw size = { 9 } className = { styles . replayIcon } / > }
2026-03-28 15:00:45 +01:00
< span className = { styles . chainRoute } > { ce . routeId } < / span >
< span className = { styles . chainDuration } > { formatDuration ( ce . durationMs ) } < / span >
< / button >
< / span >
2026-03-28 14:49:45 +01:00
) ;
2026-03-28 15:24:20 +01:00
} ) : (
< span className = { styles . chainNone } > no correlated exchanges found < / span >
) }
2026-03-28 15:29:35 +01:00
{ showChain && ( ( ) = > {
const starts = chain . map ( ( ce : any ) = > new Date ( ce . startTime ) . getTime ( ) ) . filter ( ( t : number ) = > ! isNaN ( t ) ) ;
const ends = chain . map ( ( ce : any ) = > new Date ( ce . endTime ? ? ce . startTime ) . getTime ( ) + ( ce . durationMs ? ? 0 ) ) . filter ( ( t : number ) = > ! isNaN ( t ) ) ;
const totalMs = starts . length > 0 && ends . length > 0 ? Math . max ( . . . ends ) - Math . min ( . . . starts ) : 0 ;
2026-03-28 15:30:22 +01:00
return totalMs > 0 ? < span className = { styles . chainTotal } > { formatDuration ( totalMs ) } < / span > : null ;
2026-03-28 15:29:35 +01:00
} ) ( ) }
2026-03-28 15:24:20 +01:00
< / div >
2026-03-28 13:55:13 +01:00
< / div >
) ;
}