From 1e95699a54e31f86de22372b28ea7c8120cf1191 Mon Sep 17 00:00:00 2001 From: Kapu Date: Mon, 6 Apr 2026 23:09:43 -0700 Subject: [PATCH 1/9] feat: add ROCm powered-by banner with version to GPU section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backend (api/system/metrics): - Expose rocmDetected (boolean) and rocmRuntimeVersion (string) in the metrics response — only populated when rocmGpus.length > 0 Frontend (SystemMetricsDashboard): - Insert ROCm powered-by section above "Hardware Details" in primary GPU card - Shows AMD ROCm logo (public/amd/rocgfx-logo.png) with styled text fallback - Displays "Powered by ROCm v{runtimeVersion}" badge - Graceful degradation: text badge shown if logo image is absent To add the logo: place amd-rocgfx-logo.png in public/amd/ (see public/amd/README.txt) --- public/amd/README.txt | 6 ++++ src/app/api/system/metrics/route.ts | 9 ++++- src/components/SystemMetricsDashboard.tsx | 40 +++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 public/amd/README.txt diff --git a/public/amd/README.txt b/public/amd/README.txt new file mode 100644 index 0000000..83c969c --- /dev/null +++ b/public/amd/README.txt @@ -0,0 +1,6 @@ +Place amd-rocgfx-logo.png here. + +Download from: https://rocm.docs.amd.com/en/latest/_static/amd-rocgfx-logo.png +Alternative: https://raw.githubusercontent.com/RadeonOpenCompute/ROCm//docs/_static/amd-rocgfx-logo.png + +The component falls back to a styled text badge if this image is absent. diff --git a/src/app/api/system/metrics/route.ts b/src/app/api/system/metrics/route.ts index f314d6c..716c893 100644 --- a/src/app/api/system/metrics/route.ts +++ b/src/app/api/system/metrics/route.ts @@ -75,6 +75,9 @@ export interface SystemMetrics { uptime: number; hostname: string; platform: string; + // ROCm system-level info (available when rocmGpus.length > 0) + rocmDetected: boolean; + rocmRuntimeVersion: string; // GPU fallback source info (indicates which detection method was used) gpuDetectionMethod?: "rocm" | "systeminfo" | "basic-sysfs" | "none"; } @@ -135,9 +138,11 @@ export async function GET( let rocmGpus: ROCmGPUInfo[] = []; let basicGpus: BasicGPUInfo[] = []; let gpuDetectionMethod: SystemMetrics["gpuDetectionMethod"] = "none"; + // Keep rocmInfo in scope so we can read runtimeVersion for the response + let rocmInfo: { detected: boolean; gpus: ROCmGPUInfo[]; runtimeVersion?: string } = { detected: false, gpus: [] }; try { - const rocmInfo = await detectROCm(); + rocmInfo = await detectROCm(); if (rocmInfo.detected && rocmInfo.gpus.length > 0) { rocmGpus = rocmInfo.gpus; } @@ -263,6 +268,8 @@ export async function GET( uptime: Math.round(process.uptime()), hostname: osInfo.hostname, platform: `${osInfo.platform} ${osInfo.arch}`, + rocmDetected: rocmGpus.length > 0, + rocmRuntimeVersion: rocmInfo.runtimeVersion ?? "", gpuDetectionMethod, }; diff --git a/src/components/SystemMetricsDashboard.tsx b/src/components/SystemMetricsDashboard.tsx index ac393e6..03c9d3c 100644 --- a/src/components/SystemMetricsDashboard.tsx +++ b/src/components/SystemMetricsDashboard.tsx @@ -1,5 +1,6 @@ "use client"; +import Image from "next/image"; import { useEffect, useState, useCallback } from "react"; import { Cpu, @@ -84,6 +85,9 @@ interface SystemMetrics { uptime: number; hostname: string; platform: string; + // ROCm system-level info (only populated when rocmGpus.length > 0) + rocmDetected: boolean; + rocmRuntimeVersion: string; } function MetricRow({ @@ -537,6 +541,42 @@ export function SystemMetricsDashboard() { )} + {/* ROCm Powered By — shown when ROCm is detected */} + {metrics.rocmDetected && ( +
+ {/* AMD ROCm logo — public/amd/rocgfx-logo.png or fallback text badge */} +
+ AMD ROCm { + // Fallback: hide broken image and show styled text badge instead + const target = e.currentTarget as HTMLImageElement; + target.style.display = "none"; + const badge = target.nextElementSibling as HTMLElement | null; + if (badge) badge.style.display = "flex"; + }} + /> + + AMD ROCm + +
+ + Powered by ROCm + + {metrics.rocmRuntimeVersion && ( + + v{metrics.rocmRuntimeVersion} + + )} +
+ )} + {/* GPU Hardware Details — collapsible */} {(primaryGpu.deviceId || primaryGpu.driverVersion || primaryGpu.vbiosVersion) && (
From 219f0630e55b9de30575768a72dbc8760e866e80 Mon Sep 17 00:00:00 2001 From: Kapu Date: Mon, 6 Apr 2026 23:14:17 -0700 Subject: [PATCH 2/9] fix(rocm): edit the correct gateway-metrics route, use AMD GitHub avatar URL - The SystemMetricsDashboard fetches from /api/gateway-metrics, not /api/system/metrics. Added rocmDetected/rocmRuntimeVersion to the correct gateway-metrics route instead. - Fixed rocmInfo scope: moved out of try block so runtimeVersion is accessible at the return statement. - Updated Image src to https://avatars.githubusercontent.com/u/16900649 (AMD ROCm GitHub org avatar). --- src/app/api/gateway-metrics/route.ts | 8 +++++++- src/components/SystemMetricsDashboard.tsx | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/app/api/gateway-metrics/route.ts b/src/app/api/gateway-metrics/route.ts index 2ea765a..89633d5 100644 --- a/src/app/api/gateway-metrics/route.ts +++ b/src/app/api/gateway-metrics/route.ts @@ -84,6 +84,9 @@ export interface SystemMetrics { uptime: number; hostname: string; platform: string; + // ROCm system-level info (available when rocmGpus.length > 0) + rocmDetected: boolean; + rocmRuntimeVersion: string; } interface GatewayPresence { @@ -134,8 +137,9 @@ async function getLocalMetrics(): Promise { // Detect ROCm GPU data if available let rocmGpus: ROCmGPUInfo[] = []; + let rocmInfo: { detected: boolean; gpus: ROCmGPUInfo[]; runtimeVersion?: string } = { detected: false, gpus: [] }; try { - const rocmInfo = await detectROCm(); + rocmInfo = await detectROCm(); if (rocmInfo.detected && rocmInfo.gpus.length > 0) { rocmGpus = rocmInfo.gpus; } @@ -255,6 +259,8 @@ async function getLocalMetrics(): Promise { uptime: Math.round(process.uptime()), hostname: osInfo.hostname, platform: `${osInfo.platform} ${osInfo.arch}`, + rocmDetected: rocmGpus.length > 0, + rocmRuntimeVersion: rocmInfo.runtimeVersion ?? "", }; } diff --git a/src/components/SystemMetricsDashboard.tsx b/src/components/SystemMetricsDashboard.tsx index 03c9d3c..6d0a92a 100644 --- a/src/components/SystemMetricsDashboard.tsx +++ b/src/components/SystemMetricsDashboard.tsx @@ -547,7 +547,7 @@ export function SystemMetricsDashboard() { {/* AMD ROCm logo — public/amd/rocgfx-logo.png or fallback text badge */}
AMD ROCm Date: Mon, 6 Apr 2026 23:16:37 -0700 Subject: [PATCH 3/9] fix: allow next/image to load from avatars.githubusercontent.com --- next.config.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/next.config.ts b/next.config.ts index a3e6800..eae6515 100644 --- a/next.config.ts +++ b/next.config.ts @@ -25,6 +25,14 @@ const nextConfig: NextConfig = { ]; return config; }, + images: { + remotePatterns: [ + { + protocol: "https", + hostname: "avatars.githubusercontent.com", + }, + ], + }, }; export default nextConfig; From e3c8889531d79a57b42feba02b736158905a1c3f Mon Sep 17 00:00:00 2001 From: Kapu Date: Mon, 6 Apr 2026 23:19:34 -0700 Subject: [PATCH 4/9] fix(rocm): remove white-on-white AMD avatar, use styled text badge instead MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The avatars.githubusercontent.com image is white-on-transparent, invisible on light backgrounds. Replaced with a red AMD ROCm text badge that reads 'AMD ROCm v{version}' with a subtle red tint — works on both light/dark. --- next.config.ts | 8 ------- src/components/SystemMetricsDashboard.tsx | 26 ++++++----------------- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/next.config.ts b/next.config.ts index eae6515..a3e6800 100644 --- a/next.config.ts +++ b/next.config.ts @@ -25,14 +25,6 @@ const nextConfig: NextConfig = { ]; return config; }, - images: { - remotePatterns: [ - { - protocol: "https", - hostname: "avatars.githubusercontent.com", - }, - ], - }, }; export default nextConfig; diff --git a/src/components/SystemMetricsDashboard.tsx b/src/components/SystemMetricsDashboard.tsx index 6d0a92a..6ab9268 100644 --- a/src/components/SystemMetricsDashboard.tsx +++ b/src/components/SystemMetricsDashboard.tsx @@ -1,6 +1,5 @@ "use client"; -import Image from "next/image"; import { useEffect, useState, useCallback } from "react"; import { Cpu, @@ -544,27 +543,16 @@ export function SystemMetricsDashboard() { {/* ROCm Powered By — shown when ROCm is detected */} {metrics.rocmDetected && (
- {/* AMD ROCm logo — public/amd/rocgfx-logo.png or fallback text badge */} + {/* AMD ROCm badge */}
- AMD ROCm { - // Fallback: hide broken image and show styled text badge instead - const target = e.currentTarget as HTMLImageElement; - target.style.display = "none"; - const badge = target.nextElementSibling as HTMLElement | null; - if (badge) badge.style.display = "flex"; - }} - /> - + AMD ROCm + {metrics.rocmRuntimeVersion && ( + + v{metrics.rocmRuntimeVersion} + + )}
Powered by ROCm From 5ca953b5e2574df8a115b90e217444cfc244a9cc Mon Sep 17 00:00:00 2001 From: Kapu Date: Mon, 6 Apr 2026 23:20:44 -0700 Subject: [PATCH 5/9] fix(rocm): simplify and enlarge ROCm badge Combine into single 'AMD ROCm v{version}' badge at text-xs size instead of fragmented multi-line display. Cleaner, more readable. --- src/components/SystemMetricsDashboard.tsx | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/components/SystemMetricsDashboard.tsx b/src/components/SystemMetricsDashboard.tsx index 6ab9268..6990962 100644 --- a/src/components/SystemMetricsDashboard.tsx +++ b/src/components/SystemMetricsDashboard.tsx @@ -543,25 +543,12 @@ export function SystemMetricsDashboard() { {/* ROCm Powered By — shown when ROCm is detected */} {metrics.rocmDetected && (
- {/* AMD ROCm badge */} -
- - AMD ROCm - - {metrics.rocmRuntimeVersion && ( - - v{metrics.rocmRuntimeVersion} - - )} -
- + + AMD ROCm v{metrics.rocmRuntimeVersion} + + Powered by ROCm - {metrics.rocmRuntimeVersion && ( - - v{metrics.rocmRuntimeVersion} - - )}
)} From 29d48cc622dec6c762a2cdf8d92cfe74e2ae3c24 Mon Sep 17 00:00:00 2001 From: Kapu Date: Mon, 6 Apr 2026 23:28:21 -0700 Subject: [PATCH 6/9] feat(rocm): restore AMD ROCm logo + versioned 'Powered by' text - Re-add next/image with avatars.githubusercontent.com remote pattern - Display logo at 80x32px with object-contain - Show 'Powered by ROCm v{version}' text beside logo - Removed broken text-only badge --- next.config.ts | 8 ++++++++ src/components/SystemMetricsDashboard.tsx | 13 +++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/next.config.ts b/next.config.ts index a3e6800..eae6515 100644 --- a/next.config.ts +++ b/next.config.ts @@ -25,6 +25,14 @@ const nextConfig: NextConfig = { ]; return config; }, + images: { + remotePatterns: [ + { + protocol: "https", + hostname: "avatars.githubusercontent.com", + }, + ], + }, }; export default nextConfig; diff --git a/src/components/SystemMetricsDashboard.tsx b/src/components/SystemMetricsDashboard.tsx index 6990962..6a26dd1 100644 --- a/src/components/SystemMetricsDashboard.tsx +++ b/src/components/SystemMetricsDashboard.tsx @@ -1,5 +1,6 @@ "use client"; +import Image from "next/image"; import { useEffect, useState, useCallback } from "react"; import { Cpu, @@ -543,11 +544,15 @@ export function SystemMetricsDashboard() { {/* ROCm Powered By — shown when ROCm is detected */} {metrics.rocmDetected && (
- - AMD ROCm v{metrics.rocmRuntimeVersion} - + AMD ROCm - Powered by ROCm + Powered by ROCm v{metrics.rocmRuntimeVersion}
)} From ba96cd97348ebfcad025e7729f8ae3d40a612543 Mon Sep 17 00:00:00 2001 From: Kapu Date: Mon, 6 Apr 2026 23:30:41 -0700 Subject: [PATCH 7/9] fix(rocm): remove version from Powered by ROCm text --- src/components/SystemMetricsDashboard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SystemMetricsDashboard.tsx b/src/components/SystemMetricsDashboard.tsx index 6a26dd1..0a38a66 100644 --- a/src/components/SystemMetricsDashboard.tsx +++ b/src/components/SystemMetricsDashboard.tsx @@ -552,7 +552,7 @@ export function SystemMetricsDashboard() { className="h-8 w-auto object-contain" /> - Powered by ROCm v{metrics.rocmRuntimeVersion} + Powered by ROCm
)} From a087a3d44376c7937e1c43bf73ee51f668accefd Mon Sep 17 00:00:00 2001 From: Kapu Date: Tue, 7 Apr 2026 10:49:49 -0700 Subject: [PATCH 8/9] show ROCm runtime version in powered-by banner --- src/components/SystemMetricsDashboard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SystemMetricsDashboard.tsx b/src/components/SystemMetricsDashboard.tsx index 0a38a66..84b508c 100644 --- a/src/components/SystemMetricsDashboard.tsx +++ b/src/components/SystemMetricsDashboard.tsx @@ -552,7 +552,7 @@ export function SystemMetricsDashboard() { className="h-8 w-auto object-contain" /> - Powered by ROCm + Powered by ROCm {metrics.rocmRuntimeVersion}
)} From 3ff3f63aeb8b4cfdc073ec37fbb6d339032e06cd Mon Sep 17 00:00:00 2001 From: Kapu Date: Tue, 7 Apr 2026 10:53:34 -0700 Subject: [PATCH 9/9] fix: read ROCm release version from /opt/rocm/.info/version-rocm instead of rocminfo --- src/lib/system/rocm.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/lib/system/rocm.ts b/src/lib/system/rocm.ts index db41ce9..611ea17 100644 --- a/src/lib/system/rocm.ts +++ b/src/lib/system/rocm.ts @@ -448,8 +448,35 @@ async function getComprehensiveGpuInfo(rocmSmiPath: string): Promise<{ /** * Get ROCm runtime version + * Prefers /opt/rocm/.info/version-rocm (e.g. "7.2.1-81") which reflects the actual + * ROCm stack version. Falls back to rocminfo parsing which reports the GFX + * runtime version (e.g. "1.18" for gfx1151) rather than the ROCm release version. */ async function getRocmVersion(rocmInfoPath: string): Promise { + // Try the ROCm version file first — this is the actual ROCm release version + const versionFilePaths = [ + "/opt/rocm/.info/version-rocm", + "/opt/rocm/.info/version", + ]; + + for (const versionFile of versionFilePaths) { + try { + const { stdout } = await execAsync(`cat ${versionFile} 2>/dev/null`); + const trimmed = stdout.trim(); + // version files are in format "7.2.1-81" — strip the package suffix + const match = trimmed.match(/^(\d+\.\d+\.\d+)/); + if (match) { + return match[1]; + } + if (trimmed) { + return trimmed; + } + } catch { + // Continue to next file + } + } + + // Fallback: parse rocminfo output (less reliable — gives GFX runtime version) try { const { stdout } = await execAsync(`${rocmInfoPath} 2>&1`); const versionMatch = stdout.match(/Runtime Version:\s*([\d.]+)/);