diff --git a/apps/web/src/hooks/use-service-resources.ts b/apps/web/src/hooks/use-service-resources.ts index 06c9a5f7..5cc06ba5 100644 --- a/apps/web/src/hooks/use-service-resources.ts +++ b/apps/web/src/hooks/use-service-resources.ts @@ -1,124 +1,25 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { api } from "@/lib/api"; +import type { ServiceResourcesResponse } from "../../../server/src/observability/service-resources"; +import type { SubsystemHealthState } from "../../../server/src/observability/subsystem-tracker"; -export type ResourceHealthState = - | "healthy" - | "degraded" - | "unavailable" - | "running" - | "idle" - | "disabled" - | "unknown"; - -export type ResourceSample = { - at: number; - serverCpuPercent: number; - serverRssBytes: number; - serverHeapBytes: number; - agentCpuPercent: number | null; - agentRssBytes: number | null; - hostLoad1: number; - subsystems: Record; -}; - -export type SubsystemResourceSample = { - p95DurationMs: number | null; - failures: number; - metadata: Record; -}; +export type { + ResourceSample, + ServiceResourcesResponse, + SubsystemResourceSample, +} from "../../../server/src/observability/service-resources"; +export type { SubsystemSnapshot } from "../../../server/src/observability/subsystem-tracker"; -export type SubsystemSnapshot = { - id: string; - label: string; - description: string; - state: ResourceHealthState; - statusReason: "failure" | "stale" | "stuck" | null; - expectedCadenceMs: number | null; - lastStartedAt: number | null; - lastCompletedAt: number | null; - lastSucceededAt: number | null; - lastFailedAt: number | null; - lastDurationMs: number | null; - p95DurationMs: number | null; - inFlight: number; - runs: number; - failures: number; - lastError: string | null; - metadata: Record; -}; - -export type ServiceResourcesResponse = { - collectionEnabled: boolean; - generatedAt: number; - processStartedAt: number; - availableHistoryMs: number; - sampleIntervalMs: number; - overall: { - state: "healthy" | "degraded" | "unavailable" | "unknown"; - reasons: Array<{ code: string; message: string }>; - }; - capabilities: { - processTreeMetrics: "available" | "unsupported" | "error"; - eventLoopMetrics: "available"; - }; - current: { - server: { - cpuPercent: number; - rssBytes: number; - heapUsedBytes: number; - heapTotalBytes: number; - externalBytes: number; - uptimeSeconds: number; - }; - host: { - load1: number; - load5: number; - load15: number; - cpuCount: number; - totalMemoryBytes: number; - freeMemoryBytes: number; - }; - agents: { - supported: boolean; - cpuPercent: number | null; - rssBytes: number | null; - processCount: number | null; - sampledAt: number | null; - error: string | null; - }; - database: { - state: "healthy" | "unavailable" | "unknown"; - latencyMs: number | null; - sampledAt: number | null; - pool: { total: number; idle: number; waiting: number; max: number }; - }; - eventLoop: { p95DelayMs: number }; - http: { - requestsPerMinute: number; - inFlight: number; - errorRatePercent: number; - p95DurationMs: number | null; - }; - workloads: { - runningAgents: number; - sseClients: number; - streams: number; - streamViewers: number; - terminalObservers: number; - terminalViewers: number; - scheduledJobs: number; - jobMonitors: number; - gitRefreshesInFlight: number; - uiEventsPublished: number; - uiWriteFailures: number; - terminalPolls: number; - terminalPollFailures: number; - }; - }; - subsystems: SubsystemSnapshot[]; - series: ResourceSample[]; -}; +/** + * Every state the resource dashboard renders a badge for. `stateLabel` and + * `stateBadgeVariant` are called with both `subsystem.state` and + * `overall.state`, so this tracks both server unions rather than restating + * where they differ. + */ +export type ResourceHealthState = + | SubsystemHealthState + | ServiceResourcesResponse["overall"]["state"]; export type ResourceWindow = "15m" | "1h";