diff --git a/web/app/servers/[id]/page.tsx b/web/app/servers/[id]/page.tsx
index 8754391..aa9f8a2 100644
--- a/web/app/servers/[id]/page.tsx
+++ b/web/app/servers/[id]/page.tsx
@@ -4,7 +4,7 @@ import { useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useParams, useRouter } from "next/navigation";
import Link from "next/link";
-import { api, ServerStatus, GenerateKeyOptions, PackageUpdate } from "@/lib/api";
+import { api, ServerStatus, GenerateKeyOptions, PackageUpdate, Inventory } from "@/lib/api";
import { Badge, Button, Card, CardHeader, CardTitle } from "@/components/ui";
import { Table, Thead, Tbody, Tr, Th, Td } from "@/components/ui";
@@ -23,6 +23,60 @@ function formatDate(dateStr: string) {
return new Date(dateStr).toLocaleString();
}
+function formatBytes(n: number): string {
+ if (!n) return "0 B";
+ const u = ["B", "KB", "MB", "GB", "TB"];
+ const i = Math.floor(Math.log(n) / Math.log(1024));
+ return `${(n / Math.pow(1024, i)).toFixed(1)} ${u[i]}`;
+}
+
+function UsageBar({ used, total }: { used: number; total: number }) {
+ const pct = total > 0 ? Math.min(100, (used / total) * 100) : 0;
+ return (
+
+
90 ? "bg-danger" : "bg-accent"}`} style={{ width: `${pct}%` }} />
+
+ );
+}
+
+function InventoryPanel({ inv }: { inv: Inventory }) {
+ return (
+
+ Inventory
+
+
+
CPU{inv.cpu.usage_pct.toFixed(0)}%
+
+
{inv.cpu.model} · {inv.cpu.cores} cores · load {inv.cpu.load1?.toFixed(2)}
+
+
+
Memory{formatBytes(inv.memory.used_bytes)} / {formatBytes(inv.memory.total_bytes)}
+
+
Swap{formatBytes(inv.swap_used_bytes)} / {formatBytes(inv.swap_total_bytes)}
+
+
+
+ {inv.partitions && inv.partitions.length > 0 && (
+
+
Partitions
+
+ {inv.partitions.map((p) => (
+
+
+ {p.mountpoint}
+ {formatBytes(p.used_bytes)} / {formatBytes(p.total_bytes)} · {p.fstype}
+
+
+
+ ))}
+
+
+ )}
+ {inv.kernel && Kernel {inv.kernel}
}
+
+ );
+}
+
const KEY_SIZES: Record
= {
rsa: [2048, 3072, 4096],
ecdsa: [256, 384, 521],
@@ -432,6 +486,12 @@ export default function ServerDetailPage() {
+ {server.inventory && (
+
+
+
+ )}
+
diff --git a/web/lib/api.ts b/web/lib/api.ts
index 77a66f1..92f89f8 100644
--- a/web/lib/api.ts
+++ b/web/lib/api.ts
@@ -7,6 +7,17 @@ export interface PackageUpdate {
new_version: string;
}
+export interface Inventory {
+ cpu: { model?: string; cores?: number; usage_pct: number; load1?: number };
+ memory: { total_bytes: number; used_bytes: number };
+ swap_total_bytes: number;
+ swap_used_bytes: number;
+ partitions?: { device: string; mountpoint: string; fstype?: string; total_bytes: number; used_bytes: number }[];
+ kernel?: string;
+ metrics_at?: string;
+ static_at?: string;
+}
+
export interface Server {
id: string;
server_id: string;
@@ -20,6 +31,7 @@ export interface Server {
available_updates?: PackageUpdate[];
updates_checked_at?: string;
console_protocols?: string[];
+ inventory?: Inventory;
}
export interface ConsoleConnectRequest {