import { IconLayoutDashboard } from '@tabler/icons-react' import { StatusDot, type StatusTone } from '@/components/status-dot' import { Button } from '@/components/ui/button' import { Tip } from '@/components/ui/tooltip' import { useI18n } from '@/i18n' import { Activity, AlertCircle } from '@/lib/icons' import type { RuntimeReadinessResult } from '@/lib/runtime-readiness' import { cn } from '@/lib/utils' import type { StatusResponse } from '@/types/hermes' interface GatewayMenuPanelProps { gatewayState: string inferenceStatus: RuntimeReadinessResult | null logLines: readonly string[] onOpenSystem: () => void statusSnapshot: StatusResponse | null } const PLATFORM_TONE: Record = { connected: 'good', connecting: 'warn', retrying: 'warn', pending_restart: 'warn', startup_failed: 'bad', fatal: 'bad' } const prettyState = (state: string) => state.replace(/_/g, ' ').replace(/^./, c => c.toUpperCase()) // Strip leading "YYYY-MM-DD HH:MM:SS,mmm " and "[runtime_id] " prefixes from // log lines so they don't dominate the display. Full text preserved on hover. const TIMESTAMP_RE = /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}[,.\d]*\s+/ const RUNTIME_BRACKET_RE = /^\[[^\]]+]\s+/ const trimLogLine = (raw: string) => raw.trim().replace(TIMESTAMP_RE, '').replace(RUNTIME_BRACKET_RE, '') export function GatewayMenuPanel({ gatewayState, inferenceStatus, logLines, onOpenSystem, statusSnapshot }: GatewayMenuPanelProps) { const { t } = useI18n() const copy = t.shell.gatewayMenu const gatewayOpen = gatewayState === 'open' const gatewayConnecting = gatewayState === 'connecting' const inferenceReady = gatewayOpen && inferenceStatus?.ready === true const connectionLabel = gatewayOpen ? copy.connected : gatewayConnecting ? copy.connecting : prettyState(gatewayState || copy.offline) const inferenceLabel = gatewayOpen ? inferenceStatus?.ready ? copy.inferenceReady : inferenceStatus ? copy.inferenceNotReady : copy.checkingInference : copy.disconnected const platforms = Object.entries(statusSnapshot?.gateway_platforms || {}).sort(([l], [r]) => l.localeCompare(r)) const recentLogs = logLines.slice(-5) return (
{inferenceReady ? ( ) : ( )} {copy.gateway} {inferenceLabel}
{copy.connection(connectionLabel)}
{inferenceStatus?.reason &&
{inferenceStatus.reason}
}
{recentLogs.length > 0 && (
{copy.recentActivity}
    {recentLogs.map((line, index) => (
  • {trimLogLine(line) || '\u00A0'}
  • ))}
)} {platforms.length > 0 && (
{copy.messagingPlatforms}
    {platforms.map(([name, platform]) => (
  • {name} {prettyState(platform.state)}
  • ))}
)}
) } function SectionLabel({ children }: { children: string }) { return (
{children}
) }