diff --git a/web-app/src/containers/SetupScreen.tsx b/web-app/src/containers/SetupScreen.tsx
index 4144e4e0a..e9867b38a 100644
--- a/web-app/src/containers/SetupScreen.tsx
+++ b/web-app/src/containers/SetupScreen.tsx
@@ -5,6 +5,7 @@ import { route } from '@/constants/routes'
import HeaderPage from './HeaderPage'
import { isProd } from '@/lib/version'
import { useTranslation } from '@/i18n/react-i18next-compat'
+import { localStorageKey } from '@/constants/localStorage'
function SetupScreen() {
const { t } = useTranslation()
@@ -12,6 +13,10 @@ function SetupScreen() {
const firstItemRemoteProvider =
providers.length > 0 ? providers[1].provider : 'openai'
+ // Check if setup tour has been completed
+ const isSetupCompleted =
+ localStorage.getItem(localStorageKey.setupCompleted) === 'true'
+
return (
@@ -50,7 +55,9 @@ function SetupScreen() {
providerName: firstItemRemoteProvider,
}}
search={{
- step: 'setup_remote_provider',
+ ...(!isSetupCompleted
+ ? { step: 'setup_remote_provider' }
+ : {}),
}}
>
diff --git a/web-app/src/containers/dialogs/LoadModelErrorDialog.tsx b/web-app/src/containers/dialogs/LoadModelErrorDialog.tsx
index 140aae03a..136f13853 100644
--- a/web-app/src/containers/dialogs/LoadModelErrorDialog.tsx
+++ b/web-app/src/containers/dialogs/LoadModelErrorDialog.tsx
@@ -7,7 +7,7 @@ import {
DialogTitle,
} from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
-import { AlertTriangle } from 'lucide-react'
+import { AlertTriangle, ChevronDown, ChevronRight } from 'lucide-react'
import { IconCopy, IconCopyCheck } from '@tabler/icons-react'
import { useTranslation } from '@/i18n/react-i18next-compat'
import { useModelLoad } from '@/hooks/useModelLoad'
@@ -18,11 +18,47 @@ export default function LoadModelErrorDialog() {
const { t } = useTranslation()
const { modelLoadError, setModelLoadError } = useModelLoad()
const [isCopying, setIsCopying] = useState(false)
+ const [isDetailExpanded, setIsDetailExpanded] = useState(true)
+
+ const getErrorDetail = (error: string | object | undefined) => {
+ if (!error || typeof error !== 'object') return null
+ if ('details' in error) {
+ return (error as { details?: string }).details
+ }
+ return null
+ }
+
+ const hasErrorDetail = (error: string | object | undefined) => {
+ return Boolean(getErrorDetail(error))
+ }
+
+ const formatErrorForCopy = (error: string | object | undefined) => {
+ if (!error) return ''
+
+ if (typeof error === 'string') return error
+
+ if (typeof error === 'object' && 'code' in error && 'message' in error) {
+ const errorObj = error as {
+ code?: string
+ message: string
+ details?: string
+ }
+ let copyText = errorObj.code
+ ? `${errorObj.code}: ${errorObj.message}`
+ : errorObj.message
+ if (errorObj.details) {
+ copyText += `\n\nDetails:\n${errorObj.details}`
+ }
+ return copyText
+ }
+
+ return JSON.stringify(error)
+ }
const handleCopy = async () => {
setIsCopying(true)
try {
- await navigator.clipboard.writeText(modelLoadError ?? '')
+ await navigator.clipboard.writeText(formatErrorForCopy(modelLoadError))
toast.success('Copy successful', {
id: 'copy-model',
description: 'Model load error information copied to clipboard',
@@ -58,17 +94,59 @@ export default function LoadModelErrorDialog() {
-
-
{
- if (el) {
- el.scrollTop = el.scrollHeight
- }
- }}
- >
- {modelLoadError}
-
+
+ {typeof modelLoadError === 'object' &&
+ modelLoadError &&
+ 'code' in modelLoadError &&
+ 'message' in modelLoadError ? (
+
+ {(modelLoadError as { code?: string }).code && (
+
+
+ {(modelLoadError as { code: string }).code}
+
+
+ )}
+
+
+ {(modelLoadError as { message: string }).message}
+
+
+
+ ) : (
+
+ {String(modelLoadError)}
+
+ )}
+
+ {hasErrorDetail(modelLoadError) && (
+
+
+
+ {isDetailExpanded && (
+
{
+ if (el) {
+ el.scrollTop = el.scrollHeight
+ }
+ }}
+ >
+ {getErrorDetail(modelLoadError)}
+
+ )}
+
+ )}
diff --git a/web-app/src/containers/dynamicControllerSetting/DropdownControl.tsx b/web-app/src/containers/dynamicControllerSetting/DropdownControl.tsx
index 4487004e1..65d44f076 100644
--- a/web-app/src/containers/dynamicControllerSetting/DropdownControl.tsx
+++ b/web-app/src/containers/dynamicControllerSetting/DropdownControl.tsx
@@ -5,12 +5,6 @@ import {
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
-import {
- Tooltip,
- TooltipTrigger,
- TooltipContent,
-} from '@/components/ui/tooltip'
-import { IconStarFilled } from '@tabler/icons-react'
import { cn } from '@/lib/utils'
// Dropdown component
@@ -24,7 +18,6 @@ type DropdownControlProps = {
export function DropdownControl({
value,
options = [],
- recommended,
onChange,
}: DropdownControlProps) {
const isSelected =
@@ -48,18 +41,6 @@ export function DropdownControl({
)}
>
{option.name}
- {recommended === option.value && (
-
-
-
-
-
-
-
- Recommended
-
-
- )}
))}
diff --git a/web-app/src/hooks/__tests__/useHardware.test.ts b/web-app/src/hooks/__tests__/useHardware.test.ts
index 94c6ed50a..8c2143822 100644
--- a/web-app/src/hooks/__tests__/useHardware.test.ts
+++ b/web-app/src/hooks/__tests__/useHardware.test.ts
@@ -1,14 +1,6 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { renderHook, act } from '@testing-library/react'
-import {
- useHardware,
- HardwareData,
- SystemUsage,
- CPU,
- GPU,
- OS,
- RAM,
-} from '../useHardware'
+import { useHardware, HardwareData, OS, RAM } from '../useHardware'
// Mock dependencies
vi.mock('@/constants/localStorage', () => ({
@@ -43,7 +35,6 @@ describe('useHardware', () => {
name: '',
usage: 0,
},
- gpus: [],
os_type: '',
os_name: '',
total_memory: 0,
@@ -52,9 +43,7 @@ describe('useHardware', () => {
cpu: 0,
used_memory: 0,
total_memory: 0,
- gpus: [],
})
- expect(result.current.gpuLoading).toEqual({})
expect(result.current.pollingPaused).toBe(false)
})
@@ -74,26 +63,6 @@ describe('useHardware', () => {
available: 0,
total: 0,
},
- gpus: [
- {
- name: 'NVIDIA RTX 3080',
- total_memory: 10737418240,
- vendor: 'NVIDIA',
- uuid: 'GPU-12345',
- driver_version: '470.57.02',
- activated: true,
- nvidia_info: {
- index: 0,
- compute_capability: '8.6',
- },
- vulkan_info: {
- index: 0,
- device_id: 8704,
- device_type: 'discrete',
- api_version: '1.2.0',
- },
- },
- ],
os_type: 'linux',
os_name: 'Ubuntu',
total_memory: 17179869184,
@@ -124,37 +93,6 @@ describe('useHardware', () => {
expect(result.current.hardwareData.cpu).toEqual(testCPU)
})
- it('should set GPUs data', () => {
- const { result } = renderHook(() => useHardware())
-
- const testGPUs = [
- {
- name: 'NVIDIA RTX 3080',
- total_memory: 10737418240,
- vendor: 'NVIDIA',
- uuid: 'GPU-12345',
- driver_version: '470.57.02',
- activated: true,
- nvidia_info: {
- index: 0,
- compute_capability: '8.6',
- },
- vulkan_info: {
- index: 0,
- device_id: 8704,
- device_type: 'discrete',
- api_version: '1.2.0',
- },
- },
- ]
-
- act(() => {
- result.current.setGPUs(testGPUs)
- })
-
- expect(result.current.hardwareData.gpus).toEqual(testGPUs)
- })
-
it('should update system usage', () => {
const { result } = renderHook(() => useHardware())
@@ -162,13 +100,6 @@ describe('useHardware', () => {
cpu: 45.2,
used_memory: 8589934592,
total_memory: 17179869184,
- gpus: [
- {
- uuid: 'GPU-12345',
- used_memory: 2147483648,
- total_memory: 10737418240,
- },
- ],
}
act(() => {
@@ -178,48 +109,6 @@ describe('useHardware', () => {
expect(result.current.systemUsage).toEqual(testSystemUsage)
})
- it('should manage GPU loading state', () => {
- const { result } = renderHook(() => useHardware())
-
- // First set up some GPU data so we have a UUID to work with
- const testGPUs = [
- {
- name: 'NVIDIA RTX 3080',
- total_memory: 10737418240,
- vendor: 'NVIDIA',
- uuid: 'GPU-12345',
- driver_version: '470.57.02',
- activated: true,
- nvidia_info: {
- index: 0,
- compute_capability: '8.6',
- },
- vulkan_info: {
- index: 0,
- device_id: 8704,
- device_type: 'discrete',
- api_version: '1.2.0',
- },
- },
- ]
-
- act(() => {
- result.current.setGPUs(testGPUs)
- })
-
- act(() => {
- result.current.setGpuLoading(0, true)
- })
-
- expect(result.current.gpuLoading['GPU-12345']).toBe(true)
-
- act(() => {
- result.current.setGpuLoading(0, false)
- })
-
- expect(result.current.gpuLoading['GPU-12345']).toBe(false)
- })
-
it('should manage polling state', () => {
const { result } = renderHook(() => useHardware())
@@ -271,179 +160,4 @@ describe('useHardware', () => {
expect(result.current.hardwareData.ram).toEqual(ram)
})
})
-
- describe('updateGPU', () => {
- it('should update specific GPU at index', () => {
- const { result } = renderHook(() => useHardware())
-
- const initialGpus: GPU[] = [
- {
- name: 'GPU 1',
- total_memory: 8192,
- vendor: 'NVIDIA',
- uuid: 'gpu-1',
- driver_version: '1.0',
- activated: false,
- nvidia_info: { index: 0, compute_capability: '8.0' },
- vulkan_info: {
- index: 0,
- device_id: 1,
- device_type: 'discrete',
- api_version: '1.0',
- },
- },
- {
- name: 'GPU 2',
- total_memory: 4096,
- vendor: 'AMD',
- uuid: 'gpu-2',
- driver_version: '2.0',
- activated: false,
- nvidia_info: { index: 1, compute_capability: '7.0' },
- vulkan_info: {
- index: 1,
- device_id: 2,
- device_type: 'discrete',
- api_version: '1.0',
- },
- },
- ]
-
- act(() => {
- result.current.setGPUs(initialGpus)
- })
-
- const updatedGpu: GPU = {
- ...initialGpus[0],
- name: 'Updated GPU 1',
- activated: true,
- }
-
- act(() => {
- result.current.updateGPU(0, updatedGpu)
- })
-
- expect(result.current.hardwareData.gpus[0].name).toBe('Updated GPU 1')
- expect(result.current.hardwareData.gpus[0].activated).toBe(true)
- expect(result.current.hardwareData.gpus[1]).toEqual(initialGpus[1])
- })
-
- it('should handle invalid index gracefully', () => {
- const { result } = renderHook(() => useHardware())
-
- const initialGpus: GPU[] = [
- {
- name: 'GPU 1',
- total_memory: 8192,
- vendor: 'NVIDIA',
- uuid: 'gpu-1',
- driver_version: '1.0',
- activated: false,
- nvidia_info: { index: 0, compute_capability: '8.0' },
- vulkan_info: {
- index: 0,
- device_id: 1,
- device_type: 'discrete',
- api_version: '1.0',
- },
- },
- ]
-
- act(() => {
- result.current.setGPUs(initialGpus)
- })
-
- const updatedGpu: GPU = {
- ...initialGpus[0],
- name: 'Updated GPU',
- }
-
- act(() => {
- result.current.updateGPU(5, updatedGpu)
- })
-
- expect(result.current.hardwareData.gpus[0]).toEqual(initialGpus[0])
- })
- })
-
- describe('setHardwareData with GPU activation', () => {
- it('should initialize GPUs as inactive when activated is not specified', () => {
- const { result } = renderHook(() => useHardware())
-
- const hardwareData: HardwareData = {
- cpu: {
- arch: 'x86_64',
- core_count: 4,
- extensions: [],
- name: 'CPU',
- usage: 0,
- },
- gpus: [
- {
- name: 'GPU 1',
- total_memory: 8192,
- vendor: 'NVIDIA',
- uuid: 'gpu-1',
- driver_version: '1.0',
- nvidia_info: { index: 0, compute_capability: '8.0' },
- vulkan_info: {
- index: 0,
- device_id: 1,
- device_type: 'discrete',
- api_version: '1.0',
- },
- },
- ],
- os_type: 'windows',
- os_name: 'Windows 11',
- total_memory: 16384,
- }
-
- act(() => {
- result.current.setHardwareData(hardwareData)
- })
-
- expect(result.current.hardwareData.gpus[0].activated).toBe(false)
- })
-
- it('should preserve existing activation states when set', () => {
- const { result } = renderHook(() => useHardware())
-
- const hardwareData: HardwareData = {
- cpu: {
- arch: 'x86_64',
- core_count: 4,
- extensions: [],
- name: 'CPU',
- usage: 0,
- },
- gpus: [
- {
- name: 'GPU 1',
- total_memory: 8192,
- vendor: 'NVIDIA',
- uuid: 'gpu-1',
- driver_version: '1.0',
- activated: true,
- nvidia_info: { index: 0, compute_capability: '8.0' },
- vulkan_info: {
- index: 0,
- device_id: 1,
- device_type: 'discrete',
- api_version: '1.0',
- },
- },
- ],
- os_type: 'windows',
- os_name: 'Windows 11',
- total_memory: 16384,
- }
-
- act(() => {
- result.current.setHardwareData(hardwareData)
- })
-
- expect(result.current.hardwareData.gpus[0].activated).toBe(true)
- })
- })
})
diff --git a/web-app/src/hooks/useChat.ts b/web-app/src/hooks/useChat.ts
index 0a5e07d36..09c0473c6 100644
--- a/web-app/src/hooks/useChat.ts
+++ b/web-app/src/hooks/useChat.ts
@@ -428,11 +428,11 @@ export const useChat = () => {
}
} catch (error) {
if (!abortController.signal.aborted) {
- const errorMessage =
- error && typeof error === 'object' && 'message' in error
- ? error.message
- : error
- setModelLoadError(`${errorMessage}`)
+ if (error && typeof error === 'object' && 'message' in error) {
+ setModelLoadError(error as ErrorObject)
+ } else {
+ setModelLoadError(`${error}`)
+ }
}
} finally {
updateLoadingModel(false)
@@ -453,6 +453,7 @@ export const useChat = () => {
setPrompt,
selectedModel,
currentAssistant,
+ experimentalFeatures,
tools,
updateLoadingModel,
getDisabledToolsForThread,
diff --git a/web-app/src/hooks/useHardware.ts b/web-app/src/hooks/useHardware.ts
index 183fa2490..5467aea06 100644
--- a/web-app/src/hooks/useHardware.ts
+++ b/web-app/src/hooks/useHardware.ts
@@ -12,30 +12,6 @@ export interface CPU {
instructions?: string[] // Cortex migration: ensure instructions data ready
}
-export interface GPUAdditionalInfo {
- compute_cap: string
- driver_version: string
-}
-
-export interface GPU {
- name: string
- total_memory: number
- vendor: string
- uuid: string
- driver_version: string
- activated?: boolean
- nvidia_info: {
- index: number
- compute_capability: string
- }
- vulkan_info: {
- index: number
- device_id: number
- device_type: string
- api_version: string
- }
-}
-
export interface OS {
name: string
version: string
@@ -48,7 +24,6 @@ export interface RAM {
export interface HardwareData {
cpu: CPU
- gpus: GPU[]
os_type: string
os_name: string
total_memory: number
@@ -60,11 +35,6 @@ export interface SystemUsage {
cpu: number
used_memory: number
total_memory: number
- gpus: {
- uuid: string
- used_memory: number
- total_memory: number
- }[]
}
// Default values
@@ -76,7 +46,6 @@ const defaultHardwareData: HardwareData = {
name: '',
usage: 0,
},
- gpus: [],
os_type: '',
os_name: '',
total_memory: 0,
@@ -86,7 +55,6 @@ const defaultSystemUsage: SystemUsage = {
cpu: 0,
used_memory: 0,
total_memory: 0,
- gpus: [],
}
interface HardwareStore {
@@ -96,22 +64,17 @@ interface HardwareStore {
// Update functions
setCPU: (cpu: CPU) => void
- setGPUs: (gpus: GPU[]) => void
setOS: (os: OS) => void
setRAM: (ram: RAM) => void
// Update entire hardware data at once
setHardwareData: (data: HardwareData) => void
- // Update individual GPU
- updateGPU: (index: number, gpu: GPU) => void
-
// Update RAM available
updateSystemUsage: (usage: SystemUsage) => void
// GPU loading state
gpuLoading: { [index: number]: boolean }
- setGpuLoading: (index: number, loading: boolean) => void
// Polling control
pollingPaused: boolean
@@ -126,13 +89,6 @@ export const useHardware = create()(
systemUsage: defaultSystemUsage,
gpuLoading: {},
pollingPaused: false,
- setGpuLoading: (index, loading) =>
- set((state) => ({
- gpuLoading: {
- ...state.gpuLoading,
- [state.hardwareData.gpus[index].uuid]: loading,
- },
- })),
pausePolling: () => set({ pollingPaused: true }),
resumePolling: () => set({ pollingPaused: false }),
@@ -144,14 +100,6 @@ export const useHardware = create()(
},
})),
- setGPUs: (gpus) =>
- set((state) => ({
- hardwareData: {
- ...state.hardwareData,
- gpus,
- },
- })),
-
setOS: (os) =>
set((state) => ({
hardwareData: {
@@ -181,27 +129,9 @@ export const useHardware = create()(
available: 0,
total: 0,
},
- gpus: data.gpus.map((gpu) => ({
- ...gpu,
- activated: gpu.activated ?? false,
- })),
},
}),
- updateGPU: (index, gpu) =>
- set((state) => {
- const newGPUs = [...state.hardwareData.gpus]
- if (index >= 0 && index < newGPUs.length) {
- newGPUs[index] = gpu
- }
- return {
- hardwareData: {
- ...state.hardwareData,
- gpus: newGPUs,
- },
- }
- }),
-
updateSystemUsage: (systemUsage) =>
set(() => ({
systemUsage,
diff --git a/web-app/src/hooks/useModelLoad.ts b/web-app/src/hooks/useModelLoad.ts
index c4b57a3a8..262391181 100644
--- a/web-app/src/hooks/useModelLoad.ts
+++ b/web-app/src/hooks/useModelLoad.ts
@@ -1,8 +1,8 @@
import { create } from 'zustand'
type ModelLoadState = {
- modelLoadError?: string
- setModelLoadError: (error: string | undefined) => void
+ modelLoadError?: string | ErrorObject
+ setModelLoadError: (error: string | ErrorObject | undefined) => void
}
export const useModelLoad = create()((set) => ({
diff --git a/web-app/src/hooks/useModelProvider.ts b/web-app/src/hooks/useModelProvider.ts
index e6c1ae74c..b1a988183 100644
--- a/web-app/src/hooks/useModelProvider.ts
+++ b/web-app/src/hooks/useModelProvider.ts
@@ -276,9 +276,34 @@ export const useModelProvider = create()(
})
}
+ // Migration for override_tensor_buffer_type key (version 2 -> 3)
+ if (version === 2 && state?.providers) {
+ state.providers.forEach((provider) => {
+ if (provider.models) {
+ provider.models.forEach((model) => {
+ // Initialize settings if it doesn't exist
+ if (!model.settings) {
+ model.settings = {}
+ }
+
+ // Add missing override_tensor_buffer_type setting if it doesn't exist
+ if (!model.settings.override_tensor_buffer_t) {
+ model.settings.override_tensor_buffer_t = {
+ ...modelSettings.override_tensor_buffer_t,
+ controller_props: {
+ ...modelSettings.override_tensor_buffer_t
+ .controller_props,
+ },
+ }
+ }
+ })
+ }
+ })
+ }
+
return state
},
- version: 2,
+ version: 3,
}
)
)
diff --git a/web-app/src/lib/predefined.ts b/web-app/src/lib/predefined.ts
index 1d73fbacc..b4d5164e7 100644
--- a/web-app/src/lib/predefined.ts
+++ b/web-app/src/lib/predefined.ts
@@ -133,4 +133,15 @@ export const modelSettings = {
textAlign: 'right',
},
},
+ override_tensor_buffer_t: {
+ key: 'override_tensor_buffer_t',
+ title: 'Override Tensor Buffer Type',
+ description: 'Override the tensor buffer type for the model',
+ controller_type: 'input',
+ controller_props: {
+ value: '',
+ placeholder: 'e.g., layers\\.\\d+\\.ffn_.*=CPU',
+ type: 'text',
+ },
+ },
}
diff --git a/web-app/src/routes/hub/index.tsx b/web-app/src/routes/hub/index.tsx
index 66e079412..08e8602ba 100644
--- a/web-app/src/routes/hub/index.tsx
+++ b/web-app/src/routes/hub/index.tsx
@@ -501,7 +501,7 @@ function Hub() {
- {loading ? (
+ {loading && !filteredModels.length ? (
{t('hub:loadingModels')}
diff --git a/web-app/src/routes/settings/providers/$providerName.tsx b/web-app/src/routes/settings/providers/$providerName.tsx
index 326500273..bb0ed844e 100644
--- a/web-app/src/routes/settings/providers/$providerName.tsx
+++ b/web-app/src/routes/settings/providers/$providerName.tsx
@@ -15,7 +15,6 @@ import {
import {
createFileRoute,
Link,
- useNavigate,
useParams,
useSearch,
} from '@tanstack/react-router'
@@ -32,6 +31,7 @@ import { CustomTooltipJoyRide } from '@/containers/CustomeTooltipJoyRide'
import { route } from '@/constants/routes'
import DeleteProvider from '@/containers/dialogs/DeleteProvider'
import { updateSettings, fetchModelsFromProvider } from '@/services/providers'
+import { localStorageKey } from '@/constants/localStorage'
import { Button } from '@/components/ui/button'
import { IconFolderPlus, IconLoader, IconRefresh } from '@tabler/icons-react'
import { getProviders } from '@/services/providers'
@@ -83,7 +83,6 @@ function ProviderDetail() {
const { getProviderByName, setProviders, updateProvider } = useModelProvider()
const provider = getProviderByName(providerName)
const isSetup = step === 'setup_remote_provider'
- const navigate = useNavigate()
// Check if llamacpp provider needs backend configuration
const needsBackendConfig =
@@ -137,9 +136,7 @@ function ProviderDetail() {
const { status } = data
if (status === STATUS.FINISHED) {
- navigate({
- to: route.home,
- })
+ localStorage.setItem(localStorageKey.setupCompleted, 'true')
}
}
@@ -214,7 +211,11 @@ function ProviderDetail() {
})
.catch((error) => {
console.error('Error starting model:', error)
- setModelLoadError(`${error.message}`)
+ if (error && typeof error === 'object' && 'message' in error) {
+ setModelLoadError(error)
+ } else {
+ setModelLoadError(`${error}`)
+ }
})
.finally(() => {
// Remove model from loading state
@@ -387,29 +388,43 @@ function ProviderDetail() {
: false
}
description={
-
{
- return (
-
- )
- },
- p: ({ ...props }) => (
-
- ),
- }}
- />
+ <>
+ {
+ return (
+
+ )
+ },
+ p: ({ ...props }) => (
+
+ ),
+ }}
+ />
+ {setting.key === 'version_backend' &&
+ setting.controller_props?.recommended && (
+
+
+ {setting.controller_props.recommended
+ ?.split('/')
+ .pop() ||
+ setting.controller_props.recommended}
+
+ is the recommended backend.
+
+ )}
+ >
}
actions={actionComponent}
/>
diff --git a/web-app/src/routes/system-monitor.tsx b/web-app/src/routes/system-monitor.tsx
index e7eac9dad..f09d2061b 100644
--- a/web-app/src/routes/system-monitor.tsx
+++ b/web-app/src/routes/system-monitor.tsx
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { createFileRoute } from '@tanstack/react-router'
-import { useEffect, useState } from 'react'
+import { useEffect } from 'react'
import { useHardware } from '@/hooks/useHardware'
import { Progress } from '@/components/ui/progress'
import { route } from '@/constants/routes'
@@ -19,12 +19,7 @@ function SystemMonitor() {
const { t } = useTranslation()
const { hardwareData, systemUsage, updateSystemUsage } = useHardware()
- const {
- devices: llamacppDevices,
- fetchDevices,
- } = useLlamacppDevices()
-
- const [isInitialized, setIsInitialized] = useState(false)
+ const { devices: llamacppDevices, fetchDevices } = useLlamacppDevices()
useEffect(() => {
// Fetch llamacpp devices
@@ -46,14 +41,6 @@ function SystemMonitor() {
return () => clearInterval(intervalId)
}, [updateSystemUsage])
- // Initialize when hardware data and llamacpp devices are available
- useEffect(() => {
- if (hardwareData.gpus.length > 0 && !isInitialized) {
- setIsInitialized(true)
- }
- }, [hardwareData.gpus.length, isInitialized])
-
-
// Calculate RAM usage percentage
const ramUsagePercentage =
toNumber(systemUsage.used_memory / hardwareData.total_memory) * 100
diff --git a/web-app/src/types/app.d.ts b/web-app/src/types/app.d.ts
index e265cec94..4cccaccde 100644
--- a/web-app/src/types/app.d.ts
+++ b/web-app/src/types/app.d.ts
@@ -5,3 +5,9 @@ interface LogEntry {
target: string
message: string
}
+
+type ErrorObject = {
+ code?: string
+ message: string
+ details?: string
+}
diff --git a/web-app/src/types/modelProviders.d.ts b/web-app/src/types/modelProviders.d.ts
index d09ffc00b..eb035e471 100644
--- a/web-app/src/types/modelProviders.d.ts
+++ b/web-app/src/types/modelProviders.d.ts
@@ -7,6 +7,7 @@ type ControllerProps = {
type?: string
options?: Array<{ value: number | string; name: string }>
input_actions?: string[]
+ recommended?: string
}
/**