Files
Netcatty/components/systemManager/ResourceBar.tsx
T
陈大猫 a56b868d10 fix(system-manager): show Ascend 910B NPU info from CANN 24.x npu-smi tables (#2812)
* fix(system-manager): parse CANN 24.x Ascend npu-smi info tables

ModelArts / CANN 24.1 tables include Hugepages-Usage and Bus-Id chip rows
that the old regex rejected, so the GPU tab showed zero Ascend devices
even when npu-smi was present. Parse summary+chip pairs like nputop,
always collect the info dump, and fall back to info -m for NPU IDs.

Closes #2811

Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com>

* feat(system-manager): harden Ascend parsing from nputop fixtures and polish GPU UI

Borrow real npu-smi samples from youyve/nputop (Apache-2.0) so CI covers
910B2C, 310B4, Atlas A3 multi-chip, and 310P3 process tables without
hardware. Aggregate multi-chip NPUs, parse info-dump processes, and surface
npu-smi driver versions.

GPU tab now keeps a short util/HBM sparkline history and ResourceBar uses
smooth width transitions with load-aware tones, closer to an nvtop feel
inside the existing system-manager chrome.

Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com>
2026-08-07 13:44:18 +00:00

51 lines
1.5 KiB
TypeScript

import React, { memo } from 'react';
import { cn } from '../../lib/utils';
interface ResourceBarProps {
label: string;
value: number | null | undefined;
className?: string;
/** Slightly taller track for GPU cards. */
size?: 'sm' | 'md';
}
function barTone(clamped: number): string {
if (clamped > 85) return 'bg-destructive/80';
if (clamped > 60) return 'bg-amber-500/80';
return 'bg-primary/75';
}
export const ResourceBar = memo(function ResourceBar({
label,
value,
className,
size = 'sm',
}: ResourceBarProps) {
const finite = typeof value === 'number' && Number.isFinite(value);
const clamped = finite ? Math.max(0, Math.min(100, value)) : 0;
return (
<div className={cn('flex items-center gap-2 min-w-0', className)}>
{label ? (
<span className="text-[10px] text-muted-foreground w-7 shrink-0">{label}</span>
) : null}
<div
className={cn(
'flex-1 rounded-full bg-muted/50 overflow-hidden min-w-[48px]',
size === 'md' ? 'h-1.5' : 'h-1',
)}
>
<div
className={cn(
'h-full rounded-full transition-[width,background-color] duration-500 ease-out motion-reduce:transition-none',
finite ? barTone(clamped) : 'opacity-0',
)}
style={{ width: `${clamped}%` }}
/>
</div>
<span className="text-[10px] tabular-nums text-muted-foreground w-10 text-right shrink-0">
{finite ? `${value.toFixed(1)}%` : '--'}
</span>
</div>
);
});