diff --git a/core/src/browser/fs.ts b/core/src/browser/fs.ts index cca9bb1d3..9240b3876 100644 --- a/core/src/browser/fs.ts +++ b/core/src/browser/fs.ts @@ -58,6 +58,15 @@ const appendFileSync = (...args: any[]) => globalThis.core.api?.appendFileSync(. const copyFile: (src: string, dest: string) => Promise = (src, dest) => globalThis.core.api?.copyFile(src, dest) +/** + * Gets the list of gguf files in a directory + * + * @param path - The paths to the file. + * @returns {Promise<{any}>} - A promise that resolves with the list of gguf and non-gguf files + */ +const getGgufFiles: (paths: string[]) => Promise = ( + paths) => globalThis.core.api?.getGgufFiles(paths) + /** * Gets the file's stats. * @@ -84,4 +93,5 @@ export const fs = { copyFile, fileStat, writeBlob, + getGgufFiles, } diff --git a/core/src/node/api/processors/fsExt.ts b/core/src/node/api/processors/fsExt.ts index 5ddd26a78..4d113e1ee 100644 --- a/core/src/node/api/processors/fsExt.ts +++ b/core/src/node/api/processors/fsExt.ts @@ -1,5 +1,5 @@ -import { join } from 'path' -import fs from 'fs' +import { basename, join } from 'path' +import fs, { readdirSync } from 'fs' import { appResourcePath, normalizeFilePath, validatePath } from '../../helper/path' import { defaultAppConfig, getJanDataFolderPath, getJanDataFolderPath as getPath } from '../../helper' import { Processor } from './Processor' @@ -80,4 +80,53 @@ export class FSExt implements Processor { }) }) } + + async getGgufFiles(paths: string[]) { + const sanitizedFilePaths: { + path: string + name: string + size: number + }[] = [] + for (const filePath of paths) { + const normalizedPath = normalizeFilePath(filePath) + + const isExist = fs.existsSync(normalizedPath) + if (!isExist) continue + const fileStats = fs.statSync(normalizedPath) + if (!fileStats) continue + if (!fileStats.isDirectory()) { + const fileName = await basename(normalizedPath) + sanitizedFilePaths.push({ + path: normalizedPath, + name: fileName, + size: fileStats.size, + }) + } else { + // allowing only one level of directory + const files = await readdirSync(normalizedPath) + + for (const file of files) { + const fullPath = await join(normalizedPath, file) + const fileStats = await fs.statSync(fullPath) + if (!fileStats || fileStats.isDirectory()) continue + + sanitizedFilePaths.push({ + path: fullPath, + name: file, + size: fileStats.size, + }) + } + } + } + const unsupportedFiles = sanitizedFilePaths.filter( + (file) => !file.path.endsWith('.gguf') + ) + const supportedFiles = sanitizedFilePaths.filter((file) => + file.path.endsWith('.gguf') + ) + return { + unsupportedFiles, + supportedFiles, + } + } } diff --git a/core/src/types/api/index.ts b/core/src/types/api/index.ts index e50dce6de..e1d1b28da 100644 --- a/core/src/types/api/index.ts +++ b/core/src/types/api/index.ts @@ -105,6 +105,7 @@ export enum FileManagerRoute { getUserHomePath = 'getUserHomePath', fileStat = 'fileStat', writeBlob = 'writeBlob', + getGgufFiles = 'getGgufFiles', } export type ApiFunction = (...args: any[]) => any diff --git a/web/hooks/useImportModel.ts b/web/hooks/useImportModel.ts index 170f03b5e..b23f5a6fb 100644 --- a/web/hooks/useImportModel.ts +++ b/web/hooks/useImportModel.ts @@ -66,44 +66,13 @@ const useImportModel = () => { const sanitizeFilePaths = useCallback( async (filePaths: string[]) => { if (!filePaths || filePaths.length === 0) return - - const sanitizedFilePaths: FilePathWithSize[] = [] - for (const filePath of filePaths) { - const fileStats = await fs.fileStat(filePath, true) - if (!fileStats) continue - - if (!fileStats.isDirectory) { - const fileName = await baseName(filePath) - sanitizedFilePaths.push({ - path: filePath, - name: fileName, - size: fileStats.size, - }) - } else { - // allowing only one level of directory - const files = await fs.readdirSync(filePath) - - for (const file of files) { - const fullPath = await joinPath([filePath, file]) - const fileStats = await fs.fileStat(fullPath, true) - if (!fileStats || fileStats.isDirectory) continue - - sanitizedFilePaths.push({ - path: fullPath, - name: file, - size: fileStats.size, - }) - } - } + const { unsupportedFiles, supportedFiles } = (await fs.getGgufFiles( + filePaths + )) as unknown as { + unsupportedFiles: FilePathWithSize[] + supportedFiles: FilePathWithSize[] } - const unsupportedFiles = sanitizedFilePaths.filter( - (file) => !file.path.endsWith('.gguf') - ) - const supportedFiles = sanitizedFilePaths.filter((file) => - file.path.endsWith('.gguf') - ) - const importingModels: ImportingModel[] = supportedFiles.map( ({ path, name, size }: FilePathWithSize) => ({ importId: uuidv4(),