/** * health-report.ts — Build a structured health report for the * `/agents → Health check` command. * * The report is a plain JSON-serializable object (no class instances, * no functions) so the TUI view can render it as text without leaking * implementation details and the test suite can compare snapshots * directly. Pure data + a single builder function. * * Why a separate module: keeps `output-handler.ts` / `ui/health-view.ts` * free of business logic and lets tests pin down the report shape * independently of the rendering choice. */ import type { AgentManager } from "./agent-manager.js"; import { type DispatchHistogram } from "./dispatch-history.js"; import type { SubagentScheduler } from "./schedule.js"; import type { SettingsGetters } from "./settings.js"; import type { SwarmCoordinator } from "./swarm-join.js"; import type { AgentStatus } from "./types.js"; export interface HealthReportDeps { manager: AgentManager; scheduler: SubagentScheduler; swarmJoin?: SwarmCoordinator | null; getters: SettingsGetters; /** * Override for tests — when omitted, reads the live global circuit * breaker. Accepts a plain object so tests can supply a deterministic * snapshot without mutating module state. */ circuitBreakerState?: { state: string; failures: number; lastFailureAt: number; }; /** Override for tests — when omitted, uses `new Date()`. */ now?: () => Date; } export interface HealthReport { timestamp: string; process: { nodeVersion: string; platform: string; uptimeMs: number; memoryRssMB: number; memoryHeapUsedMB: number; }; tracing: { enabled: boolean; tracerName: string; tracerVersion: string; }; circuitBreaker: { state: string; failures: number; lastFailureAt: number; }; schedule: { active: boolean; jobCount: number; enabled: boolean; }; swarm: { available: boolean; swarmCount: number; totalAgents: number; totalDeliveries: number; }; agents: { total: number; byStatus: Record; running: number; queued: number; sessionUsage: { spawnedAgents: number; totalTurns: number; }; sessionLimits: { maxAgentsPerSession?: number; maxTotalTurnsPerSession?: number; }; }; settings: { defaultMaxTurns: number | null; graceTurns: number; maxEndHookRevisions: number; defaultJoinMode: string; schedulingEnabled: boolean; tracingEnabled: boolean; animationStyle: string; uiStyle: string; orchestrationMode: string; dashboardRefreshInterval: number; maxConcurrent: number; promptCompressionLevel: string; }; recentErrors: Array<{ id: string; type: string; error: string; completedAt: number; correlationId?: string; }>; /** * Histogram of orchestration dispatch decisions over the most recent N * spawns (`dispatch-history.ts`). `byKind` and `bySource` give the * at-a-glance view; `autoPicks` lets the user answer "of the prompts the * auto-heuristic saw, how many did it route to each kind?". */ dispatchHistogram: DispatchHistogram; } /** * Build a health report snapshot from the current runtime state. Cheap * to call (one `listAgents` walk, one scheduler read, one swarm read) * but not free, so the TUI view re-builds on open rather than on every * keystroke. * * Atomicity: every registry-derived field is read into a local at the * top of the function, so a hook firing between sections cannot produce * a torn read (e.g. `tracing.enabled: true` paired with * `settings.tracingEnabled: false`). The locals are the source of * truth for the returned object. */ export declare function buildHealthReport(deps: HealthReportDeps): HealthReport; /** * Render a `HealthReport` as a fixed-width text block suitable for * `ctx.ui.editor(...)`. Sections are separated by a single blank line * and a comment header so the user can scroll the report in their * editor buffer. */ export declare function formatHealthReport(r: HealthReport): string; /** Format a duration in ms as a compact `1d2h3m4s` string (no spaces between units, drops zero-leading units, always shows all units from the highest non-zero down to seconds). */ declare function formatDuration(ms: number): string; export { formatDuration };