import type { ChannelAccountCatalogGroup, ChannelConnectionStatus } from '@src/lib/channel-types'; import { buildChannelStatusSummary, type ChannelStatusSummary } from '@electron/utils/channel-status'; import type { GatewayLifecycleState } from './process-policy'; export interface GatewayDiagnosticsSnapshot { lastAliveAt?: number; lastRpcSuccessAt?: number; lastRpcFailureAt?: number; lastRpcFailureMethod?: string; lastHeartbeatTimeoutAt?: number; consecutiveHeartbeatMisses: number; lastSocketCloseAt?: number; lastSocketCloseCode?: number; consecutiveRpcFailures: number; } export function createInitialGatewayDiagnostics(): GatewayDiagnosticsSnapshot { return { consecutiveHeartbeatMisses: 0, consecutiveRpcFailures: 0, }; } export interface GatewayHealthSnapshot { ok: boolean; status: 'connected' | 'disconnected' | 'reconnecting'; initialized: boolean; mode: 'in-process' | 'openclaw'; port?: number | null; pid?: number | null; lastError?: string; lifecycleState?: GatewayLifecycleState; gatewayReady?: boolean; diagnostics?: GatewayDiagnosticsSnapshot; } export interface GatewayDiagnosticsSummary { status: ChannelConnectionStatus; gateway: GatewayHealthSnapshot; channels: ChannelStatusSummary; } function normalizeGatewayStatus(status: GatewayHealthSnapshot['status']): ChannelConnectionStatus { if (status === 'reconnecting') return 'connecting'; return status; } export function buildGatewayDiagnosticsSummary( health: GatewayHealthSnapshot, channelGroups: readonly ChannelAccountCatalogGroup[], ): GatewayDiagnosticsSummary { const channels = buildChannelStatusSummary(channelGroups); const gatewayStatus = normalizeGatewayStatus(health.status); return { status: health.ok ? (channels.status === 'connected' ? 'connected' : channels.status === 'disconnected' ? 'degraded' : channels.status) : gatewayStatus, gateway: health, channels, }; }