diff --git a/extensions/llamacpp-extension/src/backend.ts b/extensions/llamacpp-extension/src/backend.ts index d60ecc138..a313e01c6 100644 --- a/extensions/llamacpp-extension/src/backend.ts +++ b/extensions/llamacpp-extension/src/backend.ts @@ -1,9 +1,8 @@ import { getJanDataFolderPath, fs, joinPath, events } from '@janhq/core' import { invoke } from '@tauri-apps/api/core' -import { getProxyConfig } from './util' +import { getProxyConfig, basenameNoExt } from './util' import { dirname, basename } from '@tauri-apps/api/path' import { getSystemInfo } from '@janhq/tauri-plugin-hardware-api' - /* * Reads currently installed backends in janDataFolderPath * @@ -73,10 +72,7 @@ async function fetchRemoteSupportedBackends( if (!name.startsWith(prefix)) continue - const backend = name - .replace(prefix, '') - .replace('.tar.gz', '') - .replace('.zip', '') + const backend = basenameNoExt(name).slice(prefix.length) if (supportedBackends.includes(backend)) { remote.push({ version, backend }) diff --git a/extensions/llamacpp-extension/src/util.ts b/extensions/llamacpp-extension/src/util.ts index 1511eafec..b72766579 100644 --- a/extensions/llamacpp-extension/src/util.ts +++ b/extensions/llamacpp-extension/src/util.ts @@ -1,3 +1,23 @@ +// File path utilities +export function basenameNoExt(filePath: string): string { + const VALID_EXTENSIONS = [".tar.gz", ".zip"]; + + // handle VALID extensions first + for (const ext of VALID_EXTENSIONS) { + if (filePath.toLowerCase().endsWith(ext)) { + return filePath.slice(0, -ext.length); + } + } + + // fallback: remove only the last extension + const lastDotIndex = filePath.lastIndexOf('.'); + if (lastDotIndex > 0) { + return filePath.slice(0, lastDotIndex); + } + + return filePath; +} + // Zustand proxy state structure interface ProxyState { proxyEnabled: boolean diff --git a/src-tauri/src/core/downloads/helpers.rs b/src-tauri/src/core/downloads/helpers.rs index 137bbdd3d..e46d18868 100644 --- a/src-tauri/src/core/downloads/helpers.rs +++ b/src-tauri/src/core/downloads/helpers.rs @@ -465,7 +465,11 @@ async fn download_single_file( .await .map_err(err_to_string)?; - log::info!("Started downloading: {}", item.url); + // Decode URL for better readability in logs + let decoded_url = url::Url::parse(&item.url) + .map(|u| u.to_string()) + .unwrap_or_else(|_| item.url.clone()); + log::info!("Started downloading: {}", decoded_url); let client = _get_client_for_item(item, &header_map).map_err(err_to_string)?; let mut download_delta = 0u64; let mut initial_progress = 0u64; @@ -584,7 +588,11 @@ async fn download_single_file( .await .map_err(err_to_string)?; - log::info!("Finished downloading: {}", item.url); + // Decode URL for better readability in logs + let decoded_url = url::Url::parse(&item.url) + .map(|u| u.to_string()) + .unwrap_or_else(|_| item.url.clone()); + log::info!("Finished downloading: {}", decoded_url); Ok(save_path.to_path_buf()) } diff --git a/web-app/src/lib/utils.ts b/web-app/src/lib/utils.ts index 60a055720..d9bfa0ecb 100644 --- a/web-app/src/lib/utils.ts +++ b/web-app/src/lib/utils.ts @@ -1,11 +1,28 @@ import { type ClassValue, clsx } from 'clsx' import { twMerge } from 'tailwind-merge' import { ExtensionManager } from './extension' +import path from "path" 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"]; + + // handle VALID extensions first + for (const ext of VALID_EXTENSIONS) { + if (base.toLowerCase().endsWith(ext)) { + return base.slice(0, -ext.length); + } + } + + // fallback: remove only the last extension + return base.slice(0, -path.extname(base).length); +} + 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 06fed3713..c2fc293de 100644 --- a/web-app/src/routes/settings/providers/$providerName.tsx +++ b/web-app/src/routes/settings/providers/$providerName.tsx @@ -41,6 +41,7 @@ import { useLlamacppDevices } from '@/hooks/useLlamacppDevices' import { PlatformFeatures } from '@/lib/platform/const' import { PlatformFeature } from '@/lib/platform/types' import { useBackendUpdater } from '@/hooks/useBackendUpdater' +import { basenameNoExt } from '@/lib/utils' // as route.threadsDetail export const Route = createFileRoute('/settings/providers/$providerName')({ @@ -382,7 +383,7 @@ function ProviderDetail() { filters: [ { name: 'Backend Archives', - extensions: ['tar.gz', 'zip'], + extensions: ['tar.gz', 'zip', 'gz'], }, ], }) @@ -394,9 +395,7 @@ function ProviderDetail() { await installBackend(selectedFile) // Extract filename from the selected file path and replace spaces with dashes - const fileName = ( - selectedFile.split(/[/\\]/).pop() || selectedFile - ).replace(/\s+/g, '-') + const fileName = basenameNoExt(selectedFile).replace(/\s+/g, "-") toast.success(t('settings:backendInstallSuccess'), { description: `Llamacpp ${fileName} installed`, diff --git a/web-app/src/services/dialog/tauri.ts b/web-app/src/services/dialog/tauri.ts index faafbb3c8..1b4efad28 100644 --- a/web-app/src/services/dialog/tauri.ts +++ b/web-app/src/services/dialog/tauri.ts @@ -9,7 +9,16 @@ import { DefaultDialogService } from './default' export class TauriDialogService extends DefaultDialogService { async open(options?: DialogOpenOptions): Promise { try { - return await open(options) + console.log('TauriDialogService: Opening dialog with options:', options) + if (options?.filters) { + console.log('TauriDialogService: File filters:', options.filters) + options.filters.forEach((filter, index) => { + console.log(`TauriDialogService: Filter ${index} - Name: "${filter.name}", Extensions:`, filter.extensions) + }) + } + const result = await open(options) + console.log('TauriDialogService: Dialog result:', result) + return result } catch (error) { console.error('Error opening dialog in Tauri:', error) return null diff --git a/web-app/src/services/dialog/web.ts b/web-app/src/services/dialog/web.ts index bb24024f1..c735cbf41 100644 --- a/web-app/src/services/dialog/web.ts +++ b/web-app/src/services/dialog/web.ts @@ -19,10 +19,14 @@ export class WebDialogService implements DialogService { } if (options?.filters) { + console.log('WebDialogService: Processing file filters:', options.filters) const extensions = options.filters.flatMap(filter => filter.extensions.map(ext => `.${ext}`) ) - input.accept = extensions.join(',') + console.log('WebDialogService: Generated extensions with dots:', extensions) + const acceptString = extensions.join(',') + console.log('WebDialogService: Final accept attribute:', acceptString) + input.accept = acceptString } input.onchange = (e) => {