feat: use hardware information api

This commit is contained in:
Louis 2025-06-30 13:11:20 +07:00
parent d264220245
commit 9b730058b4
No known key found for this signature in database
GPG Key ID: 44FA9F4D33C37DE2
5 changed files with 180 additions and 181 deletions

View File

@ -24,7 +24,14 @@ impl CpuStaticInfo {
let name = system let name = system
.cpus() .cpus()
.first() .first()
.map(|cpu| cpu.brand()) .map(|cpu| {
let brand = cpu.brand();
if brand.is_empty() {
cpu.name()
} else {
brand
}
})
.unwrap_or("unknown") .unwrap_or("unknown")
.to_string(); .to_string();

View File

@ -6,9 +6,9 @@ import { setActiveGpus } from '@/services/hardware'
// Hardware data types // Hardware data types
export interface CPU { export interface CPU {
arch: string arch: string
cores: number core_count: number
instructions: string[] extensions: string[]
model: string name: string
usage: number usage: number
} }
@ -18,14 +18,21 @@ export interface GPUAdditionalInfo {
} }
export interface GPU { export interface GPU {
activated: boolean
additional_information: GPUAdditionalInfo
free_vram: number
id: string
name: string name: string
total_vram: number total_memory: number
vendor: string
uuid: string uuid: string
version: string driver_version: string
nvidia_info: {
index: number
compute_capability: string
}
vulkan_info: {
index: number
device_id: number
device_type: string
api_version: string
}
} }
export interface OS { export interface OS {
@ -41,33 +48,48 @@ export interface RAM {
export interface HardwareData { export interface HardwareData {
cpu: CPU cpu: CPU
gpus: GPU[] gpus: GPU[]
os: OS os_type: string
ram: RAM os_name: string
total_memory: number
}
export interface SystemUsage {
cpu: number
used_memory: number
total_memory: number
gpus: {
uuid: string
used_memory: number
total_memory: number
}[]
} }
// Default values // Default values
const defaultHardwareData: HardwareData = { const defaultHardwareData: HardwareData = {
cpu: { cpu: {
arch: '', arch: '',
cores: 0, core_count: 0,
instructions: [], extensions: [],
model: '', name: '',
usage: 0, usage: 0,
}, },
gpus: [], gpus: [],
os: { os_type: '',
name: '', os_name: '',
version: '', total_memory: 0,
}, }
ram: {
available: 0, const defaultSystemUsage: SystemUsage = {
total: 0, cpu: 0,
}, used_memory: 0,
total_memory: 0,
gpus: [],
} }
interface HardwareStore { interface HardwareStore {
// Hardware data // Hardware data
hardwareData: HardwareData hardwareData: HardwareData
systemUsage: SystemUsage
// Update functions // Update functions
setCPU: (cpu: CPU) => void setCPU: (cpu: CPU) => void
@ -81,11 +103,8 @@ interface HardwareStore {
// Update individual GPU // Update individual GPU
updateGPU: (index: number, gpu: GPU) => void updateGPU: (index: number, gpu: GPU) => void
// Update CPU usage
updateCPUUsage: (usage: number) => void
// Update RAM available // Update RAM available
updateRAMAvailable: (available: number) => void updateSystemUsage: (usage: SystemUsage) => void
// Toggle GPU activation (async, with loading) // Toggle GPU activation (async, with loading)
toggleGPUActivation: (index: number) => Promise<void> toggleGPUActivation: (index: number) => Promise<void>
@ -107,11 +126,15 @@ export const useHardware = create<HardwareStore>()(
persist( persist(
(set, get) => ({ (set, get) => ({
hardwareData: defaultHardwareData, hardwareData: defaultHardwareData,
systemUsage: defaultSystemUsage,
gpuLoading: {}, gpuLoading: {},
pollingPaused: false, pollingPaused: false,
setGpuLoading: (index, loading) => setGpuLoading: (index, loading) =>
set((state) => ({ set((state) => ({
gpuLoading: { ...state.gpuLoading, [state.hardwareData.gpus[index].uuid]: loading }, gpuLoading: {
...state.gpuLoading,
[state.hardwareData.gpus[index].uuid]: loading,
},
})), })),
pausePolling: () => set({ pollingPaused: true }), pausePolling: () => set({ pollingPaused: true }),
resumePolling: () => set({ pollingPaused: false }), resumePolling: () => set({ pollingPaused: false }),
@ -167,56 +190,41 @@ export const useHardware = create<HardwareStore>()(
} }
}), }),
updateCPUUsage: (usage) => updateSystemUsage: (systemUsage) =>
set((state) => ({ set(() => ({
hardwareData: { systemUsage,
...state.hardwareData,
cpu: {
...state.hardwareData.cpu,
usage,
},
},
})),
updateRAMAvailable: (available) =>
set((state) => ({
hardwareData: {
...state.hardwareData,
ram: {
...state.hardwareData.ram,
available,
},
},
})), })),
toggleGPUActivation: async (index) => { toggleGPUActivation: async (index) => {
const { pausePolling, setGpuLoading, resumePolling } = get(); const { pausePolling, setGpuLoading, resumePolling } = get()
pausePolling(); pausePolling()
setGpuLoading(index, true); setGpuLoading(index, true)
try { // try {
await new Promise((resolve) => setTimeout(resolve, 200)); // Simulate async, replace with real API if needed // await new Promise((resolve) => setTimeout(resolve, 200)) // Simulate async, replace with real API if needed
set((state) => { // set((state) => {
const newGPUs = [...state.hardwareData.gpus]; // const newGPUs = [...state.hardwareData.gpus]
if (index >= 0 && index < newGPUs.length) { // if (index >= 0 && index < newGPUs.length) {
newGPUs[index] = { // newGPUs[index] = {
...newGPUs[index], // ...newGPUs[index],
activated: !newGPUs[index].activated, // activated: !newGPUs[index].activated,
}; // }
} // }
setActiveGpus({ // setActiveGpus({
gpus: newGPUs.filter((e) => e.activated).map((e) => parseInt(e.id)), // gpus: newGPUs
}); // .filter((e) => e.activated)
return { // .map((e) => parseInt(e.id)),
hardwareData: { // })
...state.hardwareData, // return {
gpus: newGPUs, // hardwareData: {
}, // ...state.hardwareData,
}; // gpus: newGPUs,
}); // },
} finally { // }
setGpuLoading(index, false); // })
setTimeout(resumePolling, 1000); // Resume polling after 1s // } finally {
} // setGpuLoading(index, false)
// setTimeout(resumePolling, 1000) // Resume polling after 1s
// }
}, },
reorderGPUs: (oldIndex, newIndex) => reorderGPUs: (oldIndex, newIndex) =>

View File

@ -29,10 +29,11 @@ import {
IconGripVertical, IconGripVertical,
IconDeviceDesktopAnalytics, IconDeviceDesktopAnalytics,
} from '@tabler/icons-react' } from '@tabler/icons-react'
import { getHardwareInfo } from '@/services/hardware' import { getHardwareInfo, getSystemUsage } from '@/services/hardware'
import { WebviewWindow } from '@tauri-apps/api/webviewWindow' import { WebviewWindow } from '@tauri-apps/api/webviewWindow'
import { formatMegaBytes } from '@/lib/utils' import { formatMegaBytes } from '@/lib/utils'
import { windowKey } from '@/constants/windows' import { windowKey } from '@/constants/windows'
import { toNumber } from '@/utils/number'
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
export const Route = createFileRoute(route.settings.hardware as any)({ export const Route = createFileRoute(route.settings.hardware as any)({
@ -47,10 +48,11 @@ function SortableGPUItem({ gpu, index }: { gpu: GPU; index: number }) {
transform, transform,
transition, transition,
isDragging, isDragging,
} = useSortable({ id: gpu.id || index }) } = useSortable({ id: index })
const { t } = useTranslation() const { t } = useTranslation()
const { toggleGPUActivation, gpuLoading } = useHardware() const { systemUsage, toggleGPUActivation, gpuLoading } = useHardware()
const usage = systemUsage.gpus[index]
const style = { const style = {
transform: CSS.Transform.toString(transform), transform: CSS.Transform.toString(transform),
@ -78,7 +80,7 @@ function SortableGPUItem({ gpu, index }: { gpu: GPU; index: number }) {
actions={ actions={
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<Switch <Switch
checked={gpu.activated} checked={true}
disabled={!!gpuLoading[index]} disabled={!!gpuLoading[index]}
onCheckedChange={() => toggleGPUActivation(index)} onCheckedChange={() => toggleGPUActivation(index)}
/> />
@ -90,8 +92,9 @@ function SortableGPUItem({ gpu, index }: { gpu: GPU; index: number }) {
title={t('settings:hardware.vram')} title={t('settings:hardware.vram')}
actions={ actions={
<span className="text-main-view-fg/80"> <span className="text-main-view-fg/80">
{formatMegaBytes(gpu.free_vram)} {t('settings:hardware.freeOf')}{' '} {formatMegaBytes(usage?.used_memory)}{' '}
{formatMegaBytes(gpu.total_vram)} {t('settings:hardware.freeOf')}{' '}
{formatMegaBytes(gpu.total_memory)}
</span> </span>
} }
/> />
@ -99,7 +102,7 @@ function SortableGPUItem({ gpu, index }: { gpu: GPU; index: number }) {
title={t('settings:hardware.driverVersion')} title={t('settings:hardware.driverVersion')}
actions={ actions={
<span className="text-main-view-fg/80"> <span className="text-main-view-fg/80">
{gpu.additional_information?.driver_version || '-'} {gpu.driver_version?.slice(0, 50) || '-'}
</span> </span>
} }
/> />
@ -107,7 +110,8 @@ function SortableGPUItem({ gpu, index }: { gpu: GPU; index: number }) {
title={t('settings:hardware.computeCapability')} title={t('settings:hardware.computeCapability')}
actions={ actions={
<span className="text-main-view-fg/80"> <span className="text-main-view-fg/80">
{gpu.additional_information?.compute_cap || '-'} {gpu.nvidia_info?.compute_capability ??
gpu.vulkan_info?.api_version}
</span> </span>
} }
/> />
@ -120,9 +124,9 @@ function Hardware() {
const { t } = useTranslation() const { t } = useTranslation()
const { const {
hardwareData, hardwareData,
systemUsage,
setHardwareData, setHardwareData,
updateCPUUsage, updateSystemUsage,
updateRAMAvailable,
reorderGPUs, reorderGPUs,
pollingPaused, pollingPaused,
} = useHardware() } = useHardware()
@ -147,9 +151,11 @@ function Hardware() {
if (over && active.id !== over.id) { if (over && active.id !== over.id) {
// Find the indices of the dragged item and the drop target // Find the indices of the dragged item and the drop target
const oldIndex = hardwareData.gpus.findIndex( const oldIndex = hardwareData.gpus.findIndex(
(gpu) => gpu.id === active.id (gpu, index) => index === active.id
)
const newIndex = hardwareData.gpus.findIndex(
(gpu, index) => index === over.id
) )
const newIndex = hardwareData.gpus.findIndex((gpu) => gpu.id === over.id)
if (oldIndex !== -1 && newIndex !== -1) { if (oldIndex !== -1 && newIndex !== -1) {
reorderGPUs(oldIndex, newIndex) reorderGPUs(oldIndex, newIndex)
@ -160,14 +166,13 @@ function Hardware() {
useEffect(() => { useEffect(() => {
if (pollingPaused) return if (pollingPaused) return
const intervalId = setInterval(() => { const intervalId = setInterval(() => {
getHardwareInfo().then((data) => { getSystemUsage().then((data) => {
updateCPUUsage(data.cpu.usage) updateSystemUsage(data)
updateRAMAvailable(data.ram.available)
}) })
}, 5000) }, 5000)
return () => clearInterval(intervalId) return () => clearInterval(intervalId)
}, [setHardwareData, updateCPUUsage, updateRAMAvailable, pollingPaused]) }, [setHardwareData, updateSystemUsage, pollingPaused])
const handleClickSystemMonitor = async () => { const handleClickSystemMonitor = async () => {
try { try {
@ -229,8 +234,8 @@ function Hardware() {
<CardItem <CardItem
title={t('settings:hardware.name')} title={t('settings:hardware.name')}
actions={ actions={
<span className="text-main-view-fg/80"> <span className="text-main-view-fg/80 capitalize">
{hardwareData.os?.name} {hardwareData.os_type}
</span> </span>
} }
/> />
@ -238,7 +243,7 @@ function Hardware() {
title={t('settings:hardware.version')} title={t('settings:hardware.version')}
actions={ actions={
<span className="text-main-view-fg/80"> <span className="text-main-view-fg/80">
{hardwareData.os?.version} {hardwareData.os_name}
</span> </span>
} }
/> />
@ -250,7 +255,7 @@ function Hardware() {
title={t('settings:hardware.model')} title={t('settings:hardware.model')}
actions={ actions={
<span className="text-main-view-fg/80"> <span className="text-main-view-fg/80">
{hardwareData.cpu?.model} {hardwareData.cpu?.name}
</span> </span>
} }
/> />
@ -266,17 +271,17 @@ function Hardware() {
title={t('settings:hardware.cores')} title={t('settings:hardware.cores')}
actions={ actions={
<span className="text-main-view-fg/80"> <span className="text-main-view-fg/80">
{hardwareData.cpu?.cores} {hardwareData.cpu?.core_count}
</span> </span>
} }
/> />
{hardwareData.cpu?.instructions.join(', ').length > 0 && ( {hardwareData.cpu?.extensions?.join(', ').length > 0 && (
<CardItem <CardItem
title={t('settings:hardware.instructions')} title={t('settings:hardware.instructions')}
column={hardwareData.cpu?.instructions.length > 6} column={hardwareData.cpu?.extensions.length > 6}
actions={ actions={
<span className="text-main-view-fg/80 break-words"> <span className="text-main-view-fg/80 break-words">
{hardwareData.cpu?.instructions?.join(', ')} {hardwareData.cpu?.extensions?.join(', ')}
</span> </span>
} }
/> />
@ -285,14 +290,14 @@ function Hardware() {
title={t('settings:hardware.usage')} title={t('settings:hardware.usage')}
actions={ actions={
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{hardwareData.cpu?.usage > 0 && ( {systemUsage.cpu > 0 && (
<> <>
<Progress <Progress
value={hardwareData.cpu?.usage} value={systemUsage.cpu}
className="h-2 w-10" className="h-2 w-10"
/> />
<span className="text-main-view-fg/80"> <span className="text-main-view-fg/80">
{hardwareData.cpu?.usage?.toFixed(2)}% {systemUsage.cpu?.toFixed(2)}%
</span> </span>
</> </>
)} )}
@ -307,7 +312,7 @@ function Hardware() {
title={t('settings:hardware.totalRam')} title={t('settings:hardware.totalRam')}
actions={ actions={
<span className="text-main-view-fg/80"> <span className="text-main-view-fg/80">
{formatMegaBytes(hardwareData.ram.total)} {formatMegaBytes(hardwareData.total_memory)}
</span> </span>
} }
/> />
@ -315,7 +320,9 @@ function Hardware() {
title={t('settings:hardware.availableRam')} title={t('settings:hardware.availableRam')}
actions={ actions={
<span className="text-main-view-fg/80"> <span className="text-main-view-fg/80">
{formatMegaBytes(hardwareData.ram?.available)} {formatMegaBytes(
hardwareData.total_memory - systemUsage.used_memory
)}
</span> </span>
} }
/> />
@ -323,23 +330,21 @@ function Hardware() {
title={t('settings:hardware.usage')} title={t('settings:hardware.usage')}
actions={ actions={
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{hardwareData.ram?.total > 0 && ( {hardwareData.total_memory > 0 && (
<> <>
<Progress <Progress
value={ value={
((hardwareData.ram?.total - toNumber(
hardwareData.ram?.available) / systemUsage.used_memory / systemUsage.total_memory
hardwareData.ram?.total) * ) * 100
100
} }
className="h-2 w-10" className="h-2 w-10"
/> />
<span className="text-main-view-fg/80"> <span className="text-main-view-fg/80">
{( {(
((hardwareData.ram?.total - toNumber(
hardwareData.ram?.available) / systemUsage.used_memory / systemUsage.total_memory
hardwareData.ram?.total) * ) * 100
100
).toFixed(2)} ).toFixed(2)}
% %
</span> </span>
@ -383,15 +388,11 @@ function Hardware() {
onDragEnd={handleDragEnd} onDragEnd={handleDragEnd}
> >
<SortableContext <SortableContext
items={hardwareData.gpus.map((gpu) => gpu.id)} items={hardwareData.gpus.map((gpu, index) => index)}
strategy={verticalListSortingStrategy} strategy={verticalListSortingStrategy}
> >
{hardwareData.gpus.map((gpu, index) => ( {hardwareData.gpus.map((gpu, index) => (
<SortableGPUItem <SortableGPUItem key={index} gpu={gpu} index={index} />
key={gpu.id || index}
gpu={gpu}
index={index}
/>
))} ))}
</SortableContext> </SortableContext>
</DndContext> </DndContext>

View File

@ -1,7 +1,7 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { useHardware } from '@/hooks/useHardware' import { useHardware } from '@/hooks/useHardware'
import { getHardwareInfo } from '@/services/hardware' import { getHardwareInfo, getSystemUsage } from '@/services/hardware'
import { Progress } from '@/components/ui/progress' import { Progress } from '@/components/ui/progress'
import type { HardwareData } from '@/hooks/useHardware' import type { HardwareData } from '@/hooks/useHardware'
import { route } from '@/constants/routes' import { route } from '@/constants/routes'
@ -10,6 +10,7 @@ import { IconDeviceDesktopAnalytics } from '@tabler/icons-react'
import { getActiveModels, stopModel } from '@/services/models' import { getActiveModels, stopModel } from '@/services/models'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { useTranslation } from '@/i18n/react-i18next-compat' import { useTranslation } from '@/i18n/react-i18next-compat'
import { toNumber } from '@/utils/number'
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
export const Route = createFileRoute(route.systemMonitor as any)({ export const Route = createFileRoute(route.systemMonitor as any)({
@ -18,7 +19,7 @@ export const Route = createFileRoute(route.systemMonitor as any)({
function SystemMonitor() { function SystemMonitor() {
const { t } = useTranslation() const { t } = useTranslation()
const { hardwareData, setHardwareData, updateCPUUsage, updateRAMAvailable } = const { hardwareData, systemUsage, setHardwareData, updateSystemUsage } =
useHardware() useHardware()
const [activeModels, setActiveModels] = useState<string[]>([]) const [activeModels, setActiveModels] = useState<string[]>([])
@ -31,16 +32,15 @@ function SystemMonitor() {
// Set up interval for real-time updates // Set up interval for real-time updates
const intervalId = setInterval(() => { const intervalId = setInterval(() => {
getHardwareInfo().then((data) => { getSystemUsage().then((data) => {
setHardwareData(data as unknown as HardwareData) // setHardwareData(data as unknown as HardwareData)
updateCPUUsage(data.cpu?.usage) updateSystemUsage(data)
updateRAMAvailable(data.ram?.available)
}) })
getActiveModels().then(setActiveModels) getActiveModels().then(setActiveModels)
}, 5000) }, 5000)
return () => clearInterval(intervalId) return () => clearInterval(intervalId)
}, [setHardwareData, setActiveModels, updateCPUUsage, updateRAMAvailable]) }, [setHardwareData, setActiveModels, updateSystemUsage])
const stopRunningModel = (modelId: string) => { const stopRunningModel = (modelId: string) => {
stopModel(modelId) stopModel(modelId)
@ -56,9 +56,10 @@ function SystemMonitor() {
// Calculate RAM usage percentage // Calculate RAM usage percentage
const ramUsagePercentage = const ramUsagePercentage =
((hardwareData.ram.total - hardwareData.ram.available) / toNumber(
hardwareData.ram.total) * (hardwareData.total_memory - systemUsage.used_memory) /
100 hardwareData.total_memory
) * 100
return ( return (
<div className="flex flex-col h-full bg-main-view overflow-y-auto p-6"> <div className="flex flex-col h-full bg-main-view overflow-y-auto p-6">
@ -80,16 +81,14 @@ function SystemMonitor() {
<span className="text-main-view-fg/70"> <span className="text-main-view-fg/70">
{t('system-monitor:model')} {t('system-monitor:model')}
</span> </span>
<span className="text-main-view-fg"> <span className="text-main-view-fg">{hardwareData.cpu.name}</span>
{hardwareData.cpu.model}
</span>
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<span className="text-main-view-fg/70"> <span className="text-main-view-fg/70">
{t('system-monitor:cores')} {t('system-monitor:cores')}
</span> </span>
<span className="text-main-view-fg"> <span className="text-main-view-fg">
{hardwareData.cpu.cores} {hardwareData.cpu.core_count}
</span> </span>
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
@ -104,10 +103,10 @@ function SystemMonitor() {
{t('system-monitor:currentUsage')} {t('system-monitor:currentUsage')}
</span> </span>
<span className="text-main-view-fg font-bold"> <span className="text-main-view-fg font-bold">
{hardwareData.cpu.usage.toFixed(2)}% {systemUsage.cpu.toFixed(2)}%
</span> </span>
</div> </div>
<Progress value={hardwareData.cpu.usage} className="h-3 w-full" /> <Progress value={systemUsage.cpu} className="h-3 w-full" />
</div> </div>
</div> </div>
</div> </div>
@ -123,7 +122,7 @@ function SystemMonitor() {
{t('system-monitor:totalRam')} {t('system-monitor:totalRam')}
</span> </span>
<span className="text-main-view-fg"> <span className="text-main-view-fg">
{formatMegaBytes(hardwareData.ram.total)} {formatMegaBytes(hardwareData.total_memory)}
</span> </span>
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
@ -131,7 +130,9 @@ function SystemMonitor() {
{t('system-monitor:availableRam')} {t('system-monitor:availableRam')}
</span> </span>
<span className="text-main-view-fg"> <span className="text-main-view-fg">
{formatMegaBytes(hardwareData.ram.available)} {formatMegaBytes(
hardwareData.total_memory - systemUsage.used_memory
)}
</span> </span>
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
@ -140,7 +141,7 @@ function SystemMonitor() {
</span> </span>
<span className="text-main-view-fg"> <span className="text-main-view-fg">
{formatMegaBytes( {formatMegaBytes(
hardwareData.ram.total - hardwareData.ram.available hardwareData.total_memory - systemUsage.used_memory
)} )}
</span> </span>
</div> </div>
@ -222,10 +223,10 @@ function SystemMonitor() {
{hardwareData.gpus.length > 0 ? ( {hardwareData.gpus.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{hardwareData.gpus {hardwareData.gpus
.filter((gpu) => gpu.activated) // .filter((gpu) => gpu.activated)
.map((gpu, index) => ( .map((gpu, index) => (
<div <div
key={gpu.id || index} key={gpu.uuid || index}
className="bg-main-view-fg/3 rounded-lg p-4" className="bg-main-view-fg/3 rounded-lg p-4"
> >
<div className="flex justify-between items-center mb-2"> <div className="flex justify-between items-center mb-2">
@ -242,8 +243,11 @@ function SystemMonitor() {
{t('system-monitor:vramUsage')} {t('system-monitor:vramUsage')}
</span> </span>
<span className="text-main-view-fg"> <span className="text-main-view-fg">
{formatMegaBytes(gpu.total_vram - gpu.free_vram)} /{' '} {formatMegaBytes(
{formatMegaBytes(gpu.total_vram)} gpu.total_memory -
systemUsage.gpus[index]?.used_memory
)}{' '}
/ {formatMegaBytes(gpu.total_memory)}
</span> </span>
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
@ -251,7 +255,7 @@ function SystemMonitor() {
{t('system-monitor:driverVersion')} {t('system-monitor:driverVersion')}
</span> </span>
<span className="text-main-view-fg"> <span className="text-main-view-fg">
{gpu.additional_information?.driver_version || '-'} {gpu.driver_version || '-'}
</span> </span>
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
@ -259,13 +263,16 @@ function SystemMonitor() {
{t('system-monitor:computeCapability')} {t('system-monitor:computeCapability')}
</span> </span>
<span className="text-main-view-fg"> <span className="text-main-view-fg">
{gpu.additional_information?.compute_cap || '-'} {gpu.nvidia_info?.compute_capability ||
gpu.vulkan_info.api_version}
</span> </span>
</div> </div>
<div className="mt-2"> <div className="mt-2">
<Progress <Progress
value={ value={
((gpu.total_vram - gpu.free_vram) / gpu.total_vram) * ((gpu.total_memory -
systemUsage.gpus[index]?.used_memory) /
gpu.total_memory) *
100 100
} }
className="h-2 w-full" className="h-2 w-full"
@ -280,12 +287,6 @@ function SystemMonitor() {
{t('system-monitor:noGpus')} {t('system-monitor:noGpus')}
</div> </div>
)} )}
{hardwareData.gpus.length > 0 &&
!hardwareData.gpus.some((gpu) => gpu.activated) && (
<div className="text-center text-main-view-fg/50 py-4">
{t('system-monitor:noActiveGpus')}
</div>
)}
</div> </div>
</div> </div>
) )

View File

@ -1,24 +1,20 @@
import { ExtensionManager } from '@/lib/extension' import { HardwareData, SystemUsage } from '@/hooks/useHardware'
import { ExtensionTypeEnum, HardwareManagementExtension } from '@janhq/core' import { invoke } from '@tauri-apps/api/core'
/** /**
* Get hardware information from the HardwareManagementExtension. * Get hardware information from the HardwareManagementExtension.
* @returns {Promise<HardwareInfo>} A promise that resolves to the hardware information. * @returns {Promise<HardwareInfo>} A promise that resolves to the hardware information.
*/ */
export const getHardwareInfo = async () => { export const getHardwareInfo = async () => {
const extension = return invoke('get_system_info') as Promise<HardwareData>
ExtensionManager.getInstance().get<HardwareManagementExtension>(
ExtensionTypeEnum.Hardware
)
if (!extension) throw new Error('Hardware extension not found')
try {
return await extension?.getHardware()
} catch (error) {
console.error('Failed to download model:', error)
throw error
} }
/**
* Get hardware information from the HardwareManagementExtension.
* @returns {Promise<HardwareInfo>} A promise that resolves to the hardware information.
*/
export const getSystemUsage = async () => {
return invoke('get_system_usage') as Promise<SystemUsage>
} }
/** /**
@ -26,20 +22,6 @@ export const getHardwareInfo = async () => {
* @returns A Promise that resolves set gpus activate. * @returns A Promise that resolves set gpus activate.
*/ */
export const setActiveGpus = async (data: { gpus: number[] }) => { export const setActiveGpus = async (data: { gpus: number[] }) => {
const extension = // TODO: llama.cpp extension should handle this
ExtensionManager.getInstance().get<HardwareManagementExtension>( console.log(data)
ExtensionTypeEnum.Hardware
)
if (!extension) {
throw new Error('Extension is not available')
}
try {
const response = await extension.setActiveGpu(data)
return response
} catch (error) {
console.error('Failed to install engine variant:', error)
throw error
}
} }