feat(health): System Health in three groups, a score that sees lag; admin user detail
Dashboard → System Health is grouped into AgentHub, Machine and Agent
activity. The machine (GET /api/host, every signed-in user) is drawn by
components/health/HostHealth.tsx: host card beside the CPU/memory history,
then CPU (threads as compact cells + temperatures/GPUs), disks & network,
busiest processes, and per-user tiles. Concurrency bars each show their own
agent type on hover.
The Health Score (client/src/lib/healthScore.ts) is now 100 minus what each
check costs, between an amber and a red threshold: event-loop p99
(server/lib/loop-delay.js, shared with /api/metrics), Linux PSI pressure for
CPU, memory and disk I/O (/api/host `pressure`; load per core without PSI),
RAM, the database's disk, V8 heap, hooks silent while agents work, and agent
errors in the last 24 h. All-time success rate, API errors and the transcript
cache hit rate no longer count. /api/settings/info adds server.event_loop and
activity {last_event_at, working_agents, agents_24h}.
Administration: a user row opens its detail in place (GET
/api/users/:id/details — spend, account pool share, live panes, workspaces,
newest sessions); the server panel is gone, member tmux folded into the table;
the Sessions list shows each row's owner in server mode.
This commit is contained in:
+99
-2
@@ -71,7 +71,7 @@ tags:
|
||||
- name: Artifacts
|
||||
description: 'What agents produced, shared as a SNAPSHOT: a claude.ai page link, a pinned or uploaded file, a skill or a plugin. A viewer reads only the snapshot copy (sandbox CSP, nosniff); an install writes into the caller''s own account only. Every write is same-origin.'
|
||||
- name: Host
|
||||
description: 'Administration → Server: the machine''s hardware, load, disks and each user''s share of CPU and memory. Read-only, staff only in server mode.'
|
||||
description: 'Dashboard → System Health: the machine''s hardware, load, disks and each user''s share of CPU and memory. Read-only, every signed-in user.'
|
||||
- name: Locks
|
||||
description: Cross-lane named locks (server/lib/named-lock.js). Single-shot — the server never waits for a lock; `agenthub lock acquire` owns the polling loop.
|
||||
- name: Projects
|
||||
@@ -262,6 +262,21 @@ components:
|
||||
agent_count:
|
||||
type: integer
|
||||
nullable: true
|
||||
owner_id:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: 'Server mode, list only: the account owning the session''s workspace (its lane, else the lane of a dashboard run holding it); null when none. Absent in local mode.'
|
||||
owner_name:
|
||||
type: string
|
||||
nullable: true
|
||||
description: That owner's username.
|
||||
owner_display_name:
|
||||
type: string
|
||||
nullable: true
|
||||
owner_avatar_at:
|
||||
type: string
|
||||
format: date-time
|
||||
nullable: true
|
||||
last_activity:
|
||||
type: string
|
||||
format: date-time
|
||||
@@ -1578,6 +1593,32 @@ components:
|
||||
type: string
|
||||
ws_connections:
|
||||
type: integer
|
||||
event_loop:
|
||||
type: object
|
||||
description: Event-loop delay over the last minute in ms (p50, p99, max) — how long requests, hooks and terminal echo waited.
|
||||
properties:
|
||||
p50:
|
||||
type: number
|
||||
p99:
|
||||
type: number
|
||||
max:
|
||||
type: number
|
||||
activity:
|
||||
type: object
|
||||
description: 'For the System Health score: when the newest event (hook) landed, agents working now, and how the agents that ended in the last 24 h ended (scoped to the caller''s rows).'
|
||||
properties:
|
||||
last_event_at:
|
||||
type: string
|
||||
nullable: true
|
||||
working_agents:
|
||||
type: integer
|
||||
agents_24h:
|
||||
type: object
|
||||
properties:
|
||||
completed:
|
||||
type: integer
|
||||
error:
|
||||
type: integer
|
||||
transcript_cache:
|
||||
type: object
|
||||
required:
|
||||
@@ -15014,6 +15055,38 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
/api/users/{id}/details:
|
||||
get:
|
||||
tags:
|
||||
- Auth
|
||||
operationId: getServerUserDetails
|
||||
summary: 'One account in full for the Administration page (admin/analyst): sign-ins, session counts, spend today/7d/30d, per local day (`tz_offset`), per AI tool and per model, its workspaces and live panes, newest sessions, the audit entries naming it, and per pool tool its pin, group and the accounts it may run on — each account''s quota beside this user''s own 5 h / 7 d share. Never a token'
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
- name: tz_offset
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
description: The browser's getTimezoneOffset(), for the daily buckets
|
||||
responses:
|
||||
'200':
|
||||
description: Account details
|
||||
'403':
|
||||
description: EADMIN — a developer
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
'404':
|
||||
description: ENOUSER
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
/api/users/{id}:
|
||||
get:
|
||||
tags:
|
||||
@@ -17749,13 +17822,37 @@ paths:
|
||||
description: 'Cached 3 s. `usage` is null off Linux. Server mode: admin/analyst only (403 EADMIN for a developer).'
|
||||
responses:
|
||||
'200':
|
||||
description: '`{at, hostname, os, uptime, cpu, memory, disks, homesMount, gpus, usage}` — see docs/API.md.'
|
||||
description: '`{at, hostname, os, uptime, bootTime, cpu (+physicalCores, perCore), memory, disks, homesMount, gpus, usage, network, diskIo, temperatures, pressure, topProcesses, process}` — see docs/API.md.'
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
'500':
|
||||
description: EHOST
|
||||
/api/host/history:
|
||||
get:
|
||||
tags:
|
||||
- Host
|
||||
summary: The machine's CPU/memory history since the server started
|
||||
operationId: getHostHistory
|
||||
description: 'In memory only: one point every 30 s for 24 h, kept by a server-mode server on Linux (empty otherwise, `running: false`). Averaged down to at most 360 points. Server mode: admin/analyst only.'
|
||||
parameters:
|
||||
- name: range
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- 1h
|
||||
- 6h
|
||||
- 24h
|
||||
default: 1h
|
||||
responses:
|
||||
'200':
|
||||
description: '`{range, intervalMs, running, startedAt, points: [{at, cpu, memory, memoryUsed, swapUsed, load1, users: {<userId>: {cpu, memory}}}]}`.'
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
/api/lanes:
|
||||
get:
|
||||
tags:
|
||||
|
||||
Reference in New Issue
Block a user