diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index 85a90422a..ca75cbd77 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -5323,6 +5323,7 @@ dependencies = [
"sysinfo",
"tauri",
"tauri-plugin",
+ "tauri-plugin-hardware",
"thiserror 2.0.12",
"tokio",
]
diff --git a/web-app/src/containers/DropdownModelProvider.tsx b/web-app/src/containers/DropdownModelProvider.tsx
index 8f9ea35a8..a8614f89d 100644
--- a/web-app/src/containers/DropdownModelProvider.tsx
+++ b/web-app/src/containers/DropdownModelProvider.tsx
@@ -6,7 +6,7 @@ import {
PopoverTrigger,
} from '@/components/ui/popover'
import { useModelProvider } from '@/hooks/useModelProvider'
-import { cn, getProviderTitle } from '@/lib/utils'
+import { cn, getProviderTitle, getModelDisplayName } from '@/lib/utils'
import { highlightFzfMatch } from '@/utils/highlight'
import Capabilities from './Capabilities'
import { IconSettings, IconX } from '@tabler/icons-react'
@@ -240,7 +240,7 @@ const DropdownModelProvider = ({
// Update display model when selection changes
useEffect(() => {
if (selectedProvider && selectedModel) {
- setDisplayModel(selectedModel.id)
+ setDisplayModel(getModelDisplayName(selectedModel))
} else {
setDisplayModel(t('common:selectAModel'))
}
@@ -326,7 +326,7 @@ const DropdownModelProvider = ({
// Create Fzf instance for fuzzy search
const fzfInstance = useMemo(() => {
return new Fzf(searchableItems, {
- selector: (item) => item.model.id.toLowerCase(),
+ selector: (item) => `${getModelDisplayName(item.model)} ${item.model.id}`.toLowerCase(),
})
}, [searchableItems])
@@ -390,7 +390,7 @@ const DropdownModelProvider = ({
const handleSelect = useCallback(
async (searchableModel: SearchableModel) => {
// Immediately update display to prevent double-click issues
- setDisplayModel(searchableModel.model.id)
+ setDisplayModel(getModelDisplayName(searchableModel.model))
setSearchValue('')
setOpen(false)
@@ -576,7 +576,7 @@ const DropdownModelProvider = ({
/>
- {searchableModel.model.id}
+ {getModelDisplayName(searchableModel.model)}
{capabilities.length > 0 && (
@@ -669,7 +669,7 @@ const DropdownModelProvider = ({
className="text-main-view-fg/80 text-sm"
title={searchableModel.model.id}
>
- {searchableModel.model.id}
+ {getModelDisplayName(searchableModel.model)}
{capabilities.length > 0 && (
diff --git a/web-app/src/containers/ModelSetting.tsx b/web-app/src/containers/ModelSetting.tsx
index 9a3bfd814..079b735aa 100644
--- a/web-app/src/containers/ModelSetting.tsx
+++ b/web-app/src/containers/ModelSetting.tsx
@@ -14,7 +14,7 @@ import { Button } from '@/components/ui/button'
import { DynamicControllerSetting } from '@/containers/dynamicControllerSetting'
import { useModelProvider } from '@/hooks/useModelProvider'
import { useServiceHub } from '@/hooks/useServiceHub'
-import { cn } from '@/lib/utils'
+import { cn, getModelDisplayName } from '@/lib/utils'
import { useTranslation } from '@/i18n/react-i18next-compat'
type ModelSettingProps = {
@@ -261,7 +261,7 @@ export function ModelSetting({
- {t('common:modelSettings.title', { modelId: model.id })}
+ {t('common:modelSettings.title', { modelId: getModelDisplayName(model) })}
{t('common:modelSettings.description')}
diff --git a/web-app/src/containers/dialogs/EditModel.tsx b/web-app/src/containers/dialogs/EditModel.tsx
index e1406f4f0..2b9cc098a 100644
--- a/web-app/src/containers/dialogs/EditModel.tsx
+++ b/web-app/src/containers/dialogs/EditModel.tsx
@@ -39,8 +39,8 @@ export const DialogEditModel = ({
const { t } = useTranslation()
const { updateProvider, setProviders } = useModelProvider()
const [selectedModelId, setSelectedModelId] = useState('')
- const [modelName, setModelName] = useState('')
- const [originalModelName, setOriginalModelName] = useState('')
+ const [displayName, setDisplayName] = useState('')
+ const [originalDisplayName, setOriginalDisplayName] = useState('')
const [originalCapabilities, setOriginalCapabilities] = useState<
Record
>({})
@@ -86,7 +86,7 @@ export const DialogEditModel = ({
(m: any) => m.id === selectedModelId
)
- // Initialize capabilities and model name from selected model
+ // Initialize capabilities and display name from selected model
useEffect(() => {
if (selectedModel) {
const modelCapabilities = selectedModel.capabilities || []
@@ -98,9 +98,10 @@ export const DialogEditModel = ({
web_search: modelCapabilities.includes('web_search'),
reasoning: modelCapabilities.includes('reasoning'),
})
- const modelNameValue = selectedModel.id
- setModelName(modelNameValue)
- setOriginalModelName(modelNameValue)
+ // Use existing displayName if available, otherwise fall back to model ID
+ const displayNameValue = (selectedModel as any).displayName || selectedModel.id
+ setDisplayName(displayNameValue)
+ setOriginalDisplayName(displayNameValue)
const originalCaps = {
completion: modelCapabilities.includes('completion'),
@@ -122,14 +123,14 @@ export const DialogEditModel = ({
}))
}
- // Handle model name change
- const handleModelNameChange = (newName: string) => {
- setModelName(newName)
+ // Handle display name change
+ const handleDisplayNameChange = (newName: string) => {
+ setDisplayName(newName)
}
// Check if there are unsaved changes
const hasUnsavedChanges = () => {
- const nameChanged = modelName !== originalModelName
+ const nameChanged = displayName !== originalDisplayName
const capabilitiesChanged =
JSON.stringify(capabilities) !== JSON.stringify(originalCapabilities)
return nameChanged || capabilitiesChanged
@@ -141,13 +142,21 @@ export const DialogEditModel = ({
setIsLoading(true)
try {
- // Update model name if changed
- if (modelName !== originalModelName) {
- await serviceHub
- .models()
- .updateModel(selectedModel.id, { id: modelName })
- setOriginalModelName(modelName)
- await serviceHub.providers().getProviders().then(setProviders)
+ let updatedModels = provider.models
+
+ // Update display name if changed
+ if (displayName !== originalDisplayName) {
+ // Update the model in the provider models array with displayName
+ updatedModels = updatedModels.map((m: any) => {
+ if (m.id === selectedModelId) {
+ return {
+ ...m,
+ displayName: displayName,
+ }
+ }
+ return m
+ })
+ setOriginalDisplayName(displayName)
}
// Update capabilities if changed
@@ -159,8 +168,7 @@ export const DialogEditModel = ({
.map(([capName]) => capName)
// Find and update the model in the provider
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const updatedModels = provider.models.map((m: any) => {
+ updatedModels = updatedModels.map((m: any) => {
if (m.id === selectedModelId) {
return {
...m,
@@ -172,15 +180,15 @@ export const DialogEditModel = ({
return m
})
- // Update the provider with the updated models
- updateProvider(provider.provider, {
- ...provider,
- models: updatedModels,
- })
-
setOriginalCapabilities(capabilities)
}
+ // Update the provider with the updated models
+ updateProvider(provider.provider, {
+ ...provider,
+ models: updatedModels,
+ })
+
// Show success toast and close dialog
toast.success('Model updated successfully')
setIsOpen(false)
@@ -213,22 +221,25 @@ export const DialogEditModel = ({
- {/* Model Name Section */}
+ {/* Model Display Name Section */}
{/* Warning Banner */}
diff --git a/web-app/src/hooks/useModelProvider.ts b/web-app/src/hooks/useModelProvider.ts
index bd3dbc49b..a0b5a96ce 100644
--- a/web-app/src/hooks/useModelProvider.ts
+++ b/web-app/src/hooks/useModelProvider.ts
@@ -104,6 +104,7 @@ export const useModelProvider = create()(
...model,
settings: settings,
capabilities: existingModel?.capabilities || model.capabilities,
+ displayName: existingModel?.displayName || model.displayName,
}
})
diff --git a/web-app/src/lib/utils.ts b/web-app/src/lib/utils.ts
index d9bfa0ecb..663a5051b 100644
--- a/web-app/src/lib/utils.ts
+++ b/web-app/src/lib/utils.ts
@@ -7,7 +7,6 @@ export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
-
export function basenameNoExt(filePath: string): string {
const base = path.basename(filePath);
const VALID_EXTENSIONS = [".tar.gz", ".zip"];
@@ -23,6 +22,13 @@ export function basenameNoExt(filePath: string): string {
return base.slice(0, -path.extname(base).length);
}
+/**
+ * Get the display name for a model, falling back to the model ID if no display name is set
+ */
+export function getModelDisplayName(model: Model): string {
+ return model.displayName || model.id
+}
+
export function getProviderLogo(provider: string) {
switch (provider) {
case 'jan':
diff --git a/web-app/src/routes/settings/providers/$providerName.tsx b/web-app/src/routes/settings/providers/$providerName.tsx
index c2fc293de..de978da1e 100644
--- a/web-app/src/routes/settings/providers/$providerName.tsx
+++ b/web-app/src/routes/settings/providers/$providerName.tsx
@@ -3,7 +3,7 @@ import { Card, CardItem } from '@/containers/Card'
import HeaderPage from '@/containers/HeaderPage'
import SettingsMenu from '@/containers/SettingsMenu'
import { useModelProvider } from '@/hooks/useModelProvider'
-import { cn, getProviderTitle } from '@/lib/utils'
+import { cn, getProviderTitle, getModelDisplayName } from '@/lib/utils'
import {
createFileRoute,
Link,
@@ -777,7 +777,7 @@ function ProviderDetail() {
className="font-medium line-clamp-1"
title={model.id}
>
- {model.id}
+ {getModelDisplayName(model)}
diff --git a/web-app/src/services/models/default.ts b/web-app/src/services/models/default.ts
index 39c80f551..746f869d1 100644
--- a/web-app/src/services/models/default.ts
+++ b/web-app/src/services/models/default.ts
@@ -163,15 +163,14 @@ export class DefaultModelsService implements ModelsService {
}
async updateModel(modelId: string, model: Partial): Promise {
- if (model.settings)
+ if (model.settings) {
this.getEngine()?.updateSettings(
model.settings as SettingComponentProps[]
)
- if (modelId !== model.id) {
- await this.getEngine()
- ?.update(modelId, model)
- .then(() => console.log('Model updated successfully'))
}
+ // Note: Model name/ID updates are handled at the provider level in the frontend
+ // The engine doesn't have an update method for model metadata
+ console.log('Model update request processed for modelId:', modelId)
}
async pullModel(
diff --git a/web-app/src/types/modelProviders.d.ts b/web-app/src/types/modelProviders.d.ts
index eb035e471..93cdd0df2 100644
--- a/web-app/src/types/modelProviders.d.ts
+++ b/web-app/src/types/modelProviders.d.ts
@@ -28,6 +28,7 @@ type Model = {
id: string
model?: string
name?: string
+ displayName?: string
version?: number | string
description?: string
format?: string