diff --git a/web-app/src/routes/settings/hardware.tsx b/web-app/src/routes/settings/hardware.tsx
index 242d92139..226455fb1 100644
--- a/web-app/src/routes/settings/hardware.tsx
+++ b/web-app/src/routes/settings/hardware.tsx
@@ -8,9 +8,9 @@ import { Progress } from '@/components/ui/progress'
import { useTranslation } from '@/i18n/react-i18next-compat'
import { useHardware } from '@/hooks/useHardware'
import { useLlamacppDevices } from '@/hooks/useLlamacppDevices'
-import { useEffect } from 'react'
+import { useEffect, useState } from 'react'
import { IconDeviceDesktopAnalytics } from '@tabler/icons-react'
-import { getSystemUsage } from '@/services/hardware'
+import { getHardwareInfo, getSystemUsage } from '@/services/hardware'
import { WebviewWindow } from '@tauri-apps/api/webviewWindow'
import { formatMegaBytes } from '@/lib/utils'
import { windowKey } from '@/constants/windows'
@@ -25,6 +25,7 @@ export const Route = createFileRoute(route.settings.hardware as any)({
function Hardware() {
const { t } = useTranslation()
+ const [isLoading, setIsLoading] = useState(false)
const {
hardwareData,
systemUsage,
@@ -51,6 +52,29 @@ function Hardware() {
fetchDevices()
}, [fetchDevices])
+ // Fetch initial hardware info and system usage
+ useEffect(() => {
+ setIsLoading(true)
+ Promise.all([
+ getHardwareInfo()
+ .then((data) => {
+ setHardwareData(data)
+ })
+ .catch((error) => {
+ console.error('Failed to get hardware info:', error)
+ }),
+ getSystemUsage()
+ .then((data) => {
+ updateSystemUsage(data)
+ })
+ .catch((error) => {
+ console.error('Failed to get initial system usage:', error)
+ }),
+ ]).finally(() => {
+ setIsLoading(false)
+ })
+ }, [setHardwareData, updateSystemUsage])
+
const { getProviderByName } = useModelProvider()
// Initialize llamacpp device activations from provider settings
@@ -92,13 +116,17 @@ function Hardware() {
useEffect(() => {
if (pollingPaused) return
const intervalId = setInterval(() => {
- getSystemUsage().then((data) => {
- updateSystemUsage(data)
- })
+ getSystemUsage()
+ .then((data) => {
+ updateSystemUsage(data)
+ })
+ .catch((error) => {
+ console.error('Failed to get system usage:', error)
+ })
}, 5000)
return () => clearInterval(intervalId)
- }, [setHardwareData, updateSystemUsage, pollingPaused])
+ }, [updateSystemUsage, pollingPaused])
const handleClickSystemMonitor = async () => {
try {
@@ -154,155 +182,164 @@ function Hardware() {
-
- {/* OS Information */}
-
-
- {hardwareData.os_type}
-
- }
- />
-
- {hardwareData.os_name}
-
- }
- />
-
-
- {/* CPU Information */}
-
-
- {hardwareData.cpu?.name}
-
- }
- />
-
- {hardwareData.cpu?.arch}
-
- }
- />
-
- {hardwareData.cpu?.core_count}
-
- }
- />
- {hardwareData.cpu?.extensions?.join(', ').length > 0 && (
+ {isLoading ? (
+
+
+ Loading hardware information...
+
+
+ ) : (
+
+ {/* OS Information */}
+
6}
+ title={t('settings:hardware.name')}
actions={
-
- {hardwareData.cpu?.extensions?.join(', ')}
+
+ {hardwareData.os_type}
}
/>
- )}
-
- {systemUsage.cpu > 0 && (
- <>
-
-
- {systemUsage.cpu?.toFixed(2)}%
-
- >
- )}
-
- }
- />
-
+
+ {hardwareData.os_name}
+
+ }
+ />
+
- {/* RAM Information */}
-
-
- {formatMegaBytes(hardwareData.total_memory)}
-
- }
- />
-
- {formatMegaBytes(
- hardwareData.total_memory - systemUsage.used_memory
- )}
-
- }
- />
-
- {hardwareData.total_memory > 0 && (
- <>
-
-
- {(
- toNumber(
- systemUsage.used_memory / systemUsage.total_memory
- ) * 100
- ).toFixed(2)}
- %
-
- >
- )}
-
- }
- />
-
-
- {/* Llamacpp Devices Information */}
- {!IS_MACOS && llamacpp && (
-
- {llamacppDevicesLoading ? (
- >} />
- ) : llamacppDevicesError ? (
+ {/* CPU Information */}
+
+
+ {hardwareData.cpu?.name}
+
+ }
+ />
+
+ {hardwareData.cpu?.arch}
+
+ }
+ />
+
+ {hardwareData.cpu?.core_count}
+
+ }
+ />
+ {hardwareData.cpu?.extensions?.join(', ').length > 0 && (
6}
actions={
-
- {llamacppDevicesError}
+
+ {hardwareData.cpu?.extensions?.join(', ')}
}
/>
- ) : llamacppDevices.length > 0 ? (
- llamacppDevices.map((device, index) => (
-
-
- {/*
+ )}
+
+ {systemUsage.cpu > 0 && (
+ <>
+
+
+ {systemUsage.cpu?.toFixed(2)}%
+
+ >
+ )}
+
+ }
+ />
+
+
+ {/* RAM Information */}
+
+
+ {formatMegaBytes(hardwareData.total_memory)}
+
+ }
+ />
+
+ {formatMegaBytes(
+ hardwareData.total_memory - systemUsage.used_memory
+ )}
+
+ }
+ />
+
+ {hardwareData.total_memory > 0 && (
+ <>
+
+
+ {(
+ toNumber(
+ systemUsage.used_memory /
+ systemUsage.total_memory
+ ) * 100
+ ).toFixed(2)}
+ %
+
+ >
+ )}
+
+ }
+ />
+
+
+ {/* Llamacpp Devices Information */}
+ {!IS_MACOS && llamacpp && (
+
+ {llamacppDevicesLoading ? (
+ >} />
+ ) : llamacppDevicesError ? (
+
+ {llamacppDevicesError}
+
+ }
+ />
+ ) : llamacppDevices.length > 0 ? (
+ llamacppDevices.map((device, index) => (
+
+
+ {/*
ID: {device.id}
@@ -311,36 +348,37 @@ function Hardware() {
{formatMegaBytes(device.free)} free
*/}
- {
- toggleDevice(device.id)
- stopAllModels()
- }}
- />
-
- }
- />
-
-
- {formatMegaBytes(device.mem)}{' '}
- {t('settings:hardware.freeOf')}{' '}
- {formatMegaBytes(device.free)}
-
+ {
+ toggleDevice(device.id)
+ stopAllModels()
+ }}
+ />
+
}
/>
-
-
- ))
- ) : (
- >} />
- )}
-
- )}
-
+
+
+ {formatMegaBytes(device.mem)}{' '}
+ {t('settings:hardware.freeOf')}{' '}
+ {formatMegaBytes(device.free)}
+
+ }
+ />
+
+
+ ))
+ ) : (
+ >} />
+ )}
+
+ )}
+
+ )}
diff --git a/web-app/src/routes/system-monitor.tsx b/web-app/src/routes/system-monitor.tsx
index 46717f93d..f2ede3899 100644
--- a/web-app/src/routes/system-monitor.tsx
+++ b/web-app/src/routes/system-monitor.tsx
@@ -10,6 +10,7 @@ import { useTranslation } from '@/i18n/react-i18next-compat'
import { toNumber } from '@/utils/number'
import { useLlamacppDevices } from '@/hooks/useLlamacppDevices'
import { useModelProvider } from '@/hooks/useModelProvider'
+import { getSystemUsage } from '@/services/hardware'
export const Route = createFileRoute(route.systemMonitor as any)({
component: SystemMonitor,
@@ -34,6 +35,21 @@ function SystemMonitor() {
fetchDevices()
}, [updateSystemUsage, fetchDevices])
+ // Poll system usage every 5 seconds
+ useEffect(() => {
+ const intervalId = setInterval(() => {
+ getSystemUsage()
+ .then((data) => {
+ updateSystemUsage(data)
+ })
+ .catch((error) => {
+ console.error('Failed to get system usage:', error)
+ })
+ }, 5000)
+
+ return () => clearInterval(intervalId)
+ }, [updateSystemUsage])
+
// Initialize when hardware data and llamacpp devices are available
useEffect(() => {
if (hardwareData.gpus.length > 0 && !isInitialized) {