From 526e532e2d02bebc1927c768a9e7f8a206c855c9 Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 14 Aug 2025 10:50:50 +0700 Subject: [PATCH] fix: normalize model id from source preparation --- web-app/src/hooks/useModelSources.ts | 11 ++++++++++- web-app/src/lib/utils.ts | 2 +- web-app/src/routes/hub/index.tsx | 14 +++++--------- web-app/src/services/models.ts | 6 +++--- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/web-app/src/hooks/useModelSources.ts b/web-app/src/hooks/useModelSources.ts index 72d011582..3357947e1 100644 --- a/web-app/src/hooks/useModelSources.ts +++ b/web-app/src/hooks/useModelSources.ts @@ -2,6 +2,7 @@ import { create } from 'zustand' import { localStorageKey } from '@/constants/localStorage' import { createJSONStorage, persist } from 'zustand/middleware' import { fetchModelCatalog, CatalogModel } from '@/services/models' +import { sanitizeModelId } from '@/lib/utils' // Zustand store for model sources type ModelSourcesState = { @@ -20,7 +21,15 @@ export const useModelSources = create()( fetchSources: async () => { set({ loading: true, error: null }) try { - const newSources = await fetchModelCatalog() + const newSources = await fetchModelCatalog().then((catalogs) => + catalogs.map((catalog) => ({ + ...catalog, + quants: catalog.quants.map((quant) => ({ + ...quant, + model_id: sanitizeModelId(quant.model_id), + })), + })) + ) set({ sources: newSources.length ? newSources : get().sources, diff --git a/web-app/src/lib/utils.ts b/web-app/src/lib/utils.ts index 38d3dd672..ed2ec2bab 100644 --- a/web-app/src/lib/utils.ts +++ b/web-app/src/lib/utils.ts @@ -157,5 +157,5 @@ export function formatDuration(startTime: number, endTime?: number): string { } export function sanitizeModelId(modelId: string): string { - return modelId.replace(/[^a-zA-Z0-9/_\-.]/g, '') + return modelId.replace(/[^a-zA-Z0-9/_\-.]/g, '').replace(".", "_") } diff --git a/web-app/src/routes/hub/index.tsx b/web-app/src/routes/hub/index.tsx index e7e89490c..9ec2088df 100644 --- a/web-app/src/routes/hub/index.tsx +++ b/web-app/src/routes/hub/index.tsx @@ -3,7 +3,7 @@ import { useVirtualizer } from '@tanstack/react-virtual' import { createFileRoute, useNavigate, useSearch } from '@tanstack/react-router' import { route } from '@/constants/routes' import { useModelSources } from '@/hooks/useModelSources' -import { cn, sanitizeModelId } from '@/lib/utils' +import { cn } from '@/lib/utils' import { useState, useMemo, @@ -291,8 +291,8 @@ function Hub() { const handleDownload = () => { // Immediately set local downloading state - addLocalDownloadingModel(sanitizeModelId(modelId)) - pullModel(sanitizeModelId(modelId), modelUrl) + addLocalDownloadingModel(modelId) + pullModel(modelId, modelUrl) } return ( @@ -764,14 +764,10 @@ function Hub() { title={t('hub:downloadModel')} onClick={() => { addLocalDownloadingModel( - sanitizeModelId( - variant.model_id - ) + variant.model_id ) pullModel( - sanitizeModelId( - variant.model_id - ), + variant.model_id, variant.path ) }} diff --git a/web-app/src/services/models.ts b/web-app/src/services/models.ts index 36b72c895..9cd9c7978 100644 --- a/web-app/src/services/models.ts +++ b/web-app/src/services/models.ts @@ -1,3 +1,4 @@ +import { sanitizeModelId } from '@/lib/utils' import { AIEngine, EngineManager, @@ -5,7 +6,6 @@ import { SettingComponentProps, } from '@janhq/core' import { Model as CoreModel } from '@janhq/core' -import { sanitizeModelId } from '@/lib/utils' // Types for model catalog export interface ModelQuant { model_id: string @@ -163,10 +163,10 @@ export const convertHfRepoToCatalogModel = ( } // Generate model_id from filename (remove .gguf extension, case-insensitive) - const modelId = sanitizeModelId(file.rfilename.replace(/\.gguf$/i, '')) + const modelId = file.rfilename.replace(/\.gguf$/i, '') return { - model_id: modelId, + model_id: sanitizeModelId(modelId), path: `https://huggingface.co/${repo.modelId}/resolve/main/${file.rfilename}`, file_size: formatFileSize(file.size), }