web: unify Agent management and add a draggable link board

Replace Probe pages with directed Agent links, shared deployment controls and unified display data. Add node dragging, canvas pan and zoom, saved layouts, and per-direction link controls.
This commit is contained in:
justme committed 2026-10-21 11:55:50 +08:00
1 parent 016dbc2bbf
commit 15f0023614
32 files changed
+937 -1093

No files matched your search

+128 -405
View File
@@ -164,7 +164,7 @@ export interface paths {
path?: never;
cookie?: never;
};
/** Latest host resource usage of every visible agent and probe (no hardware model, no addresses) */
/** Latest host resource usage of every visible node (no hardware model, no addresses) */
get: operations["hosts_list"];
put?: never;
post?: never;
@@ -181,7 +181,7 @@ export interface paths {
path?: never;
cookie?: never;
};
/** Host resource usage history of one agent or probe (columnar, averaged per step) */
/** Host resource usage history of one node (columnar, averaged per step) */
get: operations["hosts_history"];
put?: never;
post?: never;
@@ -198,7 +198,7 @@ export interface paths {
path?: never;
cookie?: never;
};
/** Display info of the visible agents and probes: system, architecture, country and ISP (never an address) */
/** Display info of the visible nodes: system, architecture, country and ISP (never an address) */
get: operations["nodes_list"];
put?: never;
post?: never;
@@ -472,7 +472,7 @@ export interface paths {
path?: never;
cookie?: never;
};
/** All agents including pending and disabled ones */
/** All nodes (agents) including pending and disabled ones; each says whether it listens, which dialers are connected to it and which listeners it dials */
get: operations["agents_list"];
put?: never;
post?: never;
@@ -497,7 +497,7 @@ export interface paths {
delete: operations["agents_delete"];
options?: never;
head?: never;
/** Update name, labels, public host or visibility (merge-patch, If-Match supported) */
/** Update name, labels, public host, ISP or visibility (merge-patch, If-Match supported) */
patch: operations["agents_update"];
trace?: never;
};
@@ -508,7 +508,7 @@ export interface paths {
path?: never;
cookie?: never;
};
/** Recent Agent or Probe runtime logs */
/** Recent runtime logs of a node */
get: operations["node_runtime_logs"];
put?: never;
post?: never;
@@ -596,7 +596,7 @@ export interface paths {
/** Join tokens */
get: operations["join_tokens_list"];
put?: never;
/** Create a join token for an agent or a probe (role); the plaintext is returned only once */
/** Create a join token for an agent; the plaintext is returned only once */
post: operations["join_tokens_create"];
delete?: never;
options?: never;
@@ -621,43 +621,7 @@ export interface paths {
patch?: never;
trace?: never;
};
"/api/admin/probes": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** All probes, with the agents each one is connected to */
get: operations["probes_list"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/admin/probes/{id}": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** One probe */
get: operations["probes_get"];
put?: never;
post?: never;
/** Delete a probe and its lines; stored data expires with the retention policy */
delete: operations["probes_delete"];
options?: never;
head?: never;
/** Rename a probe */
patch: operations["probes_update"];
trace?: never;
};
"/api/admin/probes/{id}/revoke": {
"/api/admin/agents/{id}/dialers/{dialer_id}/disconnect": {
parameters: {
query?: never;
header?: never;
@@ -666,25 +630,8 @@ export interface paths {
};
get?: never;
put?: never;
/** Revoke a probe: every agent drops its session and refuses it; history stays until it expires */
post: operations["probes_revoke"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/api/admin/agents/{id}/probes/{probe_id}/disconnect": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/** Make an agent drop one probe's session (the probe reconnects unless it is revoked) */
post: operations["agents_probe_disconnect"];
/** Make a listening node drop one dialer's session (the dialer reconnects unless it is disabled) */
post: operations["agents_dialer_disconnect"];
delete?: never;
options?: never;
head?: never;
@@ -978,7 +925,7 @@ export interface paths {
path?: never;
cookie?: never;
};
/** Version, tag, commit, build time and update state of the backend and every agent and probe */
/** Version, tag, commit, build time and update state of the backend and every node */
get: operations["build_info_get"];
put?: never;
post?: never;
@@ -1014,7 +961,7 @@ export interface paths {
};
get?: never;
put?: never;
/** Ask an online agent or probe to install the release it has been offered */
/** Ask an online node to install the release it has been offered */
post: operations["nodes_update"];
delete?: never;
options?: never;
@@ -1083,7 +1030,7 @@ export interface paths {
path?: never;
cookie?: never;
};
/** Every probe/agent pair: whether it is linked, the manual override and whether it is connected */
/** Every possible dialer/listener pair: whether it is linked, the manual override and whether it is connected; plus the nodes and which of them listen */
get: operations["links_list"];
put?: never;
post?: never;
@@ -1093,7 +1040,7 @@ export interface paths {
patch?: never;
trace?: never;
};
"/api/admin/links/{probe_id}/{agent_id}": {
"/api/admin/links/{dialer_id}/{listener_id}": {
parameters: {
query?: never;
header?: never;
@@ -1101,7 +1048,7 @@ export interface paths {
cookie?: never;
};
get?: never;
/** Force a link on or off, or give it back to the automatic setting (enabled: null) */
/** Connect a node to a listening node (enabled: true), force the link off (false), or give it back to the automatic setting (null) */
put: operations["links_set"];
post?: never;
delete?: never;
@@ -1110,7 +1057,7 @@ export interface paths {
patch?: never;
trace?: never;
};
"/api/admin/links/{probe_id}/{agent_id}/retry": {
"/api/admin/links/{dialer_id}/{listener_id}/retry": {
parameters: {
query?: never;
header?: never;
@@ -1119,7 +1066,7 @@ export interface paths {
};
get?: never;
put?: never;
/** Enable and immediately retry the Probe-to-Agent connection */
/** Enable and immediately retry the dialer-to-listener connection */
post: operations["links_retry"];
delete?: never;
options?: never;
@@ -1168,24 +1115,8 @@ export interface paths {
path?: never;
cookie?: never;
};
get: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description OK */
200: {
headers: {
[name: string]: unknown;
};
content?: never;
};
};
};
/** The static native OpenWrt installer and updater (Agent) */
get: operations["install_openwrt"];
put?: never;
post?: never;
delete?: never;
@@ -1218,7 +1149,7 @@ export interface paths {
path?: never;
cookie?: never;
};
/** The signed release manifest of the component an install code is for (exact signed bytes) */
/** The signed release manifest an install code may fetch (exact signed bytes) */
get: operations["install_manifest"];
put?: never;
post?: never;
@@ -1252,7 +1183,7 @@ export interface paths {
path?: never;
cookie?: never;
};
/** The static compose file of agent, probe or backend (agent.yaml, probe.yaml, backend.yaml; same bytes for everyone) */
/** The static compose file of the agent or the backend (agent.yaml, backend.yaml; same bytes for everyone) */
get: operations["install_compose"];
put?: never;
post?: never;
@@ -1269,7 +1200,7 @@ export interface paths {
path?: never;
cookie?: never;
};
/** The static Podman Quadlet unit of agent or probe (agent.container, probe.container; same bytes for everyone) */
/** The static Podman Quadlet unit of the agent (agent.container; same bytes for everyone) */
get: operations["install_quadlet"];
put?: never;
post?: never;
@@ -1360,14 +1291,15 @@ export interface components {
name: string;
status: string;
online: boolean;
probe_connected: boolean;
probes: components["schemas"]["ConnectedProbeDto"][];
listens: boolean;
dialer_connected: boolean;
dialers: components["schemas"]["ConnectedDialerDto"][];
outgoing: components["schemas"]["OutgoingConnectionDto"][];
host: null | components["schemas"]["HostDto"];
public_host: string;
/** Format: int32 */
probe_tcp_port: number | string;
probe_udp_ports: (number | string)[];
probe_quic_ports: (number | string)[];
tcp_port: number | string;
quic_ports: (number | string)[];
labels: string[];
public_visible: boolean;
kinds: string[];
@@ -1411,6 +1343,7 @@ export interface components {
ipv6_host?: null | string;
public_host_auto?: null | boolean;
ipv6_host_auto?: null | boolean;
isp?: null | string;
};
ApiTokenDto: {
id: string;
@@ -1522,8 +1455,8 @@ export interface components {
/** Format: int64 */
seq: number | string;
};
ConnectedProbeDto: {
probe_id: string;
ConnectedDialerDto: {
dialer_id: string;
version: null | string;
remote: null | string;
/** Format: date-time */
@@ -1680,7 +1613,6 @@ export interface components {
};
HostItemDto: {
id: string;
kind: string;
name: string;
online: boolean;
stale: boolean;
@@ -1734,8 +1666,6 @@ export interface components {
revoked_at: unknown;
/** Format: date-time */
created_at: unknown;
/** @default agent */
role: string;
created_by?: null | string;
};
JsonElement: unknown;
@@ -1751,12 +1681,12 @@ export interface components {
LineDto: {
id: string;
agent_id: string;
probe_id: string;
probe_name: string;
dialer_id: string;
dialer_name: string;
name: string;
labels: string[];
online: boolean;
probe_connected: boolean;
dialer_connected: boolean;
/** Format: date-time */
data_since: unknown;
kinds: string[];
@@ -1768,16 +1698,16 @@ export interface components {
quic_health?: null | components["schemas"]["QuicLineHealthDto"];
};
LinkDto: {
probe_id: string;
probe_name: string;
agent_id: string;
agent_name: string;
dialer_id: string;
dialer_name: string;
listener_id: string;
listener_name: string;
linked: boolean;
override: null | boolean;
connected: boolean;
probe_runtime_status: components["schemas"]["NodeRuntimeStatus"];
agent_runtime_status: components["schemas"]["NodeRuntimeStatus"];
/** @default connecting */
dialer_runtime_status: components["schemas"]["NodeRuntimeStatus"];
listener_runtime_status: components["schemas"]["NodeRuntimeStatus"];
/** @default control_connecting */
connection_state: string;
connection_reason?: null | string;
last_error?: null | string;
@@ -1791,8 +1721,16 @@ export interface components {
};
LinkMatrixDto: {
auto_link: boolean;
nodes: components["schemas"]["LinkNodeDto"][];
items: components["schemas"]["LinkDto"][];
};
LinkNodeDto: {
id: string;
name: string;
listens: boolean;
online: boolean;
runtime_status: components["schemas"]["NodeRuntimeStatus"];
};
LinkRetryDto: {
queued: boolean;
link: components["schemas"]["LinkDto"];
@@ -1852,7 +1790,6 @@ export interface components {
};
NodeBuildDto: {
id: string;
kind: string;
os: null | string;
os_name: null | string;
arch: null | string;
@@ -1865,7 +1802,6 @@ export interface components {
};
NodeInfoDto: {
id: string;
kind: string;
os: null | string;
os_name: null | string;
arch: null | string;
@@ -1899,7 +1835,7 @@ export interface components {
dropped: number | string;
};
/** @enum {unknown} */
NodeRuntimeStatus: "initializing" | "running" | "probe_paused" | "maintenance" | "stopping" | "offline" | "updating";
NodeRuntimeStatus: "initializing" | "running" | "idle" | "maintenance" | "stopping" | "offline" | "updating";
NodeUpdateDto: {
state: string;
current_digest: null | string;
@@ -1909,6 +1845,17 @@ export interface components {
/** Format: date-time */
at: unknown;
};
OutgoingConnectionDto: {
listener_id: string;
listener_name: string;
listener_online: boolean;
version: null | string;
remote: null | string;
/** Format: date-time */
connected_since: unknown;
/** @default ipv4 */
ip_version: string;
};
OverviewDto: {
range: string;
/** Format: date-time */
@@ -1923,12 +1870,12 @@ export interface components {
OverviewLineDto: {
id: string;
agent_id: string;
probe_id: string;
probe_name: string;
dialer_id: string;
dialer_name: string;
name: string;
labels: string[];
online: boolean;
probe_connected: boolean;
dialer_connected: boolean;
/** Format: int32 */
endpoint_changes: number | string;
summary: components["schemas"]["SummaryDto"];
@@ -1993,10 +1940,6 @@ export interface components {
items: components["schemas"]["PresetDto"][];
next_cursor: null | string;
};
PageDtoOfProbeDto: {
items: components["schemas"]["ProbeDto"][];
next_cursor: null | string;
};
PageDtoOfRawChunkMetaDto: {
items: components["schemas"]["RawChunkMetaDto"][];
next_cursor: null | string;
@@ -2066,10 +2009,6 @@ export interface components {
timeout_ms: number | string;
allow_credentials?: null | string[];
};
PatchProbeRequest: {
name: null | string;
isp?: null | string;
};
PatchTaskRequest: {
params: null | Record<string, never>;
schedule: null | string;
@@ -2093,31 +2032,6 @@ export interface components {
label: string;
metrics: string[];
};
ProbeConnectionDto: {
agent_id: string;
agent_name: string;
agent_online: boolean;
version: null | string;
remote: null | string;
/** Format: date-time */
connected_since: unknown;
/** @default ipv4 */
ip_version: string;
};
ProbeDto: {
id: string;
name: string;
/** Format: date-time */
created_at: unknown;
/** Format: date-time */
revoked_at: unknown;
revoked: boolean;
online: boolean;
connections: components["schemas"]["ProbeConnectionDto"][];
runtime_status: components["schemas"]["NodeRuntimeStatus"];
ipv6?: null | components["schemas"]["Ipv6DiagnosticDto"];
added_by?: null | string;
};
ProblemDto: {
type: string;
title: string;
@@ -2187,6 +2101,8 @@ export interface components {
retry_attempt: number | string;
/** Format: int64 */
retry_in_ms?: null | number | string;
/** @default dialing */
control_state: string;
};
RawChunkMetaDto: {
chunk_id: string;
@@ -2260,7 +2176,7 @@ export interface components {
SeriesDto: {
line_id: string;
agent_id: string;
probe_id: string;
dialer_id: string;
/** Format: date-time */
from: unknown;
/** Format: date-time */
@@ -2346,7 +2262,7 @@ export interface components {
TestDto: {
id: string;
agent_id: string;
probe_id: string;
dialer_id: string;
plan: string;
phases: string[];
status: string;
@@ -4307,260 +4223,13 @@ export interface operations {
};
};
};
probes_list: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description OK */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["PageDtoOfProbeDto"];
};
};
/** @description Unauthorized */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
};
};
probes_get: {
agents_dialer_disconnect: {
parameters: {
query?: never;
header?: never;
path: {
id: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description OK */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ProbeDto"];
};
};
/** @description Unauthorized */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Not Found */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
};
};
probes_delete: {
parameters: {
query?: never;
header?: never;
path: {
id: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description No Content */
204: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": unknown;
};
};
/** @description Unauthorized */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
};
};
probes_update: {
parameters: {
query?: never;
header?: never;
path: {
id: string;
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["PatchProbeRequest"];
};
};
responses: {
/** @description OK */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ProbeDto"];
};
};
/** @description Bad Request */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Unauthorized */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Not Found */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Conflict */
409: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
};
};
probes_revoke: {
parameters: {
query?: never;
header?: never;
path: {
id: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description OK */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ProbeDto"];
};
};
/** @description Unauthorized */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Forbidden */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Not Found */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
};
};
agents_probe_disconnect: {
parameters: {
query?: never;
header?: never;
path: {
id: string;
probe_id: string;
dialer_id: string;
};
cookie?: never;
};
@@ -6227,8 +5896,8 @@ export interface operations {
query?: never;
header?: never;
path: {
probe_id: string;
agent_id: string;
dialer_id: string;
listener_id: string;
};
cookie?: never;
};
@@ -6283,6 +5952,24 @@ export interface operations {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Conflict */
409: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Unprocessable Entity */
422: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
};
};
links_retry: {
@@ -6290,8 +5977,8 @@ export interface operations {
query?: never;
header?: never;
path: {
probe_id: string;
agent_id: string;
dialer_id: string;
listener_id: string;
};
cookie?: never;
};
@@ -6333,6 +6020,24 @@ export interface operations {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Conflict */
409: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
/** @description Unprocessable Entity */
422: {
headers: {
[name: string]: unknown;
};
content: {
"application/problem+json": components["schemas"]["ProblemDto"];
};
};
};
};
health_get: {
@@ -6400,6 +6105,24 @@ export interface operations {
};
};
};
install_openwrt: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description OK */
200: {
headers: {
[name: string]: unknown;
};
content?: never;
};
};
};
install_sh: {
parameters: {
query?: never;