export type SignalTone = 'healthy' | 'attention' | 'critical' | 'stale' | 'unknown'; export type SignalSource = { state?: string; freshness?: string; }; export type SignalContainer = { state?: string; health?: string; intentionalStop?: boolean; }; export const signalToneRank: Record = { critical: 0, attention: 1, stale: 2, unknown: 3, healthy: 4, }; export function signalToneFromState(state: string | undefined): SignalTone { const normalized = state?.trim().toLowerCase(); if (normalized === 'critical' || normalized === 'faulted' || normalized === 'down' || normalized === 'failed' || normalized === 'error') return 'critical'; if (normalized === 'attention' || normalized === 'degraded' || normalized === 'warning' || normalized === 'restarting' || normalized === 'paused' || normalized === 'removing') return 'attention'; if (normalized === 'stale') return 'stale'; if (normalized === 'healthy' || normalized === 'normal' || normalized === 'up' || normalized === 'running' || normalized === 'fresh') return 'healthy'; return 'unknown'; } export function worstSignalTone(tones: SignalTone[]): SignalTone { if (tones.length === 0) return 'unknown'; return tones.reduce((worst, tone) => signalToneRank[tone] < signalToneRank[worst] ? tone : worst, 'healthy'); } /** A successful HTTP response is not healthy when its provenance is stale or unknown. */ export function sourceSignalTone(source: SignalSource | undefined): SignalTone { if (!source) return 'unknown'; const freshness = source.freshness?.trim().toLowerCase(); if (freshness === 'stale') return 'stale'; if (freshness !== 'fresh') return 'unknown'; return signalToneFromState(source.state); } /** Mirrors the backend application-state projection without treating an intentional stop as a failure. */ export function containerSignalTone(container: SignalContainer): SignalTone { const state = container.state?.trim().toLowerCase(); const health = container.health?.trim().toLowerCase(); if (state === 'running') { if (health === 'healthy') return 'healthy'; if (health === 'unhealthy') return 'attention'; return 'unknown'; } if (state === 'restarting' || state === 'paused' || state === 'removing') return 'attention'; if (state === 'exited' || state === 'dead' || state === 'stopped') return container.intentionalStop ? 'unknown' : 'critical'; return 'unknown'; }