diff --git a/core/src/api/index.ts b/core/src/api/index.ts index 8e41da0d17..91d6ae755a 100644 --- a/core/src/api/index.ts +++ b/core/src/api/index.ts @@ -82,9 +82,9 @@ export enum FileSystemRoute { unlinkSync = 'unlinkSync', existsSync = 'existsSync', readdirSync = 'readdirSync', - mkdirSync = 'mkdirSync', + rm = 'rm', + mkdir = 'mkdir', readFileSync = 'readFileSync', - rmdirSync = 'rmdirSync', writeFileSync = 'writeFileSync', } export enum FileManagerRoute { @@ -95,8 +95,6 @@ export enum FileManagerRoute { getUserHomePath = 'getUserHomePath', fileStat = 'fileStat', writeBlob = 'writeBlob', - mkdir = 'mkdir', - rm = 'rm', } export type ApiFunction = (...args: any[]) => any diff --git a/core/src/extensions/ai-engines/AIEngine.ts b/core/src/extensions/ai-engines/AIEngine.ts index c65c081fd0..8af89f3365 100644 --- a/core/src/extensions/ai-engines/AIEngine.ts +++ b/core/src/extensions/ai-engines/AIEngine.ts @@ -36,7 +36,7 @@ export abstract class AIEngine extends BaseExtension { // Attempt to create the model folder joinPath([janDataFolder, this.modelFolder, model.id]).then((path) => fs - .mkdirSync(path) + .mkdir(path) .catch() .then(() => path) ) diff --git a/core/src/fs.ts b/core/src/fs.ts index 2eb22f9d68..3a9a20afb7 100644 --- a/core/src/fs.ts +++ b/core/src/fs.ts @@ -35,18 +35,13 @@ const readdirSync = (...args: any[]) => globalThis.core.api?.readdirSync(...args * Creates a directory at the specified path. * @returns {Promise} A Promise that resolves when the directory is created successfully. */ -const mkdirSync = (...args: any[]) => globalThis.core.api?.mkdirSync(...args) - const mkdir = (...args: any[]) => globalThis.core.api?.mkdir(...args) /** * Removes a directory at the specified path. * @returns {Promise} A Promise that resolves when the directory is removed successfully. */ -const rmdirSync = (...args: any[]) => - globalThis.core.api?.rmdirSync(...args, { recursive: true, force: true }) - -const rm = (path: string) => globalThis.core.api?.rm(path) +const rm = (...args: any[]) => globalThis.core.api?.rm(...args, { recursive: true, force: true }) /** * Deletes a file from the local file system. @@ -96,9 +91,7 @@ export const fs = { readFileSync, existsSync, readdirSync, - mkdirSync, mkdir, - rmdirSync, rm, unlinkSync, appendFileSync, diff --git a/core/src/node/api/processors/fs.ts b/core/src/node/api/processors/fs.ts index 93a5f19057..a66f5a0e95 100644 --- a/core/src/node/api/processors/fs.ts +++ b/core/src/node/api/processors/fs.ts @@ -2,6 +2,7 @@ import { join } from 'path' import { normalizeFilePath } from '../../helper/path' import { getJanDataFolderPath } from '../../helper' import { Processor } from './Processor' +import fs from 'fs' export class FileSystem implements Processor { observer?: Function @@ -11,15 +12,65 @@ export class FileSystem implements Processor { this.observer = observer } - process(route: string, ...args: any[]): any { - return import(FileSystem.moduleName).then((mdl) => - mdl[route]( - ...args.map((arg: any) => - typeof arg === 'string' && (arg.startsWith(`file:/`) || arg.startsWith(`file:\\`)) - ? join(getJanDataFolderPath(), normalizeFilePath(arg)) - : arg + process(route: string, ...args: any): any { + const instance = this as any + const func = instance[route] + + if (func) { + return func(...args) + } else { + return import(FileSystem.moduleName).then((mdl) => + mdl[route]( + ...args.map((arg: any) => { + return typeof arg === 'string' && + (arg.startsWith(`file:/`) || arg.startsWith(`file:\\`)) + ? join(getJanDataFolderPath(), normalizeFilePath(arg)) + : arg + }) ) ) - ) + } + } + + rm(...args: any): Promise { + if (typeof args[0] !== 'string') { + throw new Error(`rm error: Invalid argument ${JSON.stringify(args)}`) + } + + let path = args[0] + if (path.startsWith(`file:/`) || path.startsWith(`file:\\`)) { + path = join(getJanDataFolderPath(), normalizeFilePath(path)) + } + + return new Promise((resolve, reject) => { + fs.rm(path, { recursive: true, force: true }, (err) => { + if (err) { + reject(err) + } else { + resolve() + } + }) + }) + } + + mkdir(...args: any): Promise { + if (typeof args[0] !== 'string') { + throw new Error(`mkdir error: Invalid argument ${JSON.stringify(args)}`) + } + + let path = args[0] + if (path.startsWith(`file:/`) || path.startsWith(`file:\\`)) { + path = join(getJanDataFolderPath(), normalizeFilePath(path)) + } + + return new Promise((resolve, reject) => { + fs.mkdir(path, { recursive: true }, (err) => { + if (err) { + reject(err) + } else { + resolve() + } + }) + }) } } diff --git a/core/src/node/api/processors/fsExt.ts b/core/src/node/api/processors/fsExt.ts index 7b08e24c9d..4787da65b3 100644 --- a/core/src/node/api/processors/fsExt.ts +++ b/core/src/node/api/processors/fsExt.ts @@ -88,28 +88,4 @@ export class FSExt implements Processor { }) }) } - - mkdir(path: string): Promise { - return new Promise((resolve, reject) => { - fs.mkdir(path, { recursive: true }, (err) => { - if (err) { - reject(err) - } else { - resolve() - } - }) - }) - } - - rm(path: string): Promise { - return new Promise((resolve, reject) => { - fs.rm(path, { recursive: true }, (err) => { - if (err) { - reject(err) - } else { - resolve() - } - }) - }) - } } diff --git a/core/src/node/extension/extension.ts b/core/src/node/extension/extension.ts index 1f8dfa3ec2..8780b3ffe1 100644 --- a/core/src/node/extension/extension.ts +++ b/core/src/node/extension/extension.ts @@ -182,7 +182,7 @@ export default class Extension { async uninstall(): Promise { const path = ExtensionManager.instance.getExtensionsPath() const extPath = resolve(path ?? '', this.name ?? '') - await rmdirSync(extPath, { recursive: true }) + rmdirSync(extPath, { recursive: true }) this.emitUpdate() } diff --git a/extensions/assistant-extension/src/index.ts b/extensions/assistant-extension/src/index.ts index de695e6d52..97a1cb2207 100644 --- a/extensions/assistant-extension/src/index.ts +++ b/extensions/assistant-extension/src/index.ts @@ -29,7 +29,7 @@ export default class JanAssistantExtension extends AssistantExtension { localStorage.getItem(`${EXTENSION_NAME}-version`) !== VERSION || !assistantDirExist ) { - if (!assistantDirExist) await fs.mkdirSync(JanAssistantExtension._homeDir) + if (!assistantDirExist) await fs.mkdir(JanAssistantExtension._homeDir) // Write assistant metadata await this.createJanAssistant() @@ -184,7 +184,7 @@ export default class JanAssistantExtension extends AssistantExtension { JanAssistantExtension._homeDir, assistant.id, ]) - if (!(await fs.existsSync(assistantDir))) await fs.mkdirSync(assistantDir) + if (!(await fs.existsSync(assistantDir))) await fs.mkdir(assistantDir) // store the assistant metadata json const assistantMetadataPath = await joinPath([ @@ -247,8 +247,7 @@ export default class JanAssistantExtension extends AssistantExtension { JanAssistantExtension._homeDir, assistant.id, ]) - await fs.rmdirSync(assistantDir) - return Promise.resolve() + return fs.rm(assistantDir) } private async createJanAssistant(): Promise { diff --git a/extensions/conversational-extension/src/index.ts b/extensions/conversational-extension/src/index.ts index 1982d90c4a..210e7868dc 100644 --- a/extensions/conversational-extension/src/index.ts +++ b/extensions/conversational-extension/src/index.ts @@ -4,7 +4,6 @@ import { ConversationalExtension, Thread, ThreadMessage, - events, } from '@janhq/core' /** @@ -21,7 +20,7 @@ export default class JSONConversationalExtension extends ConversationalExtension */ async onLoad() { if (!(await fs.existsSync(JSONConversationalExtension._threadFolder))) { - await fs.mkdirSync(JSONConversationalExtension._threadFolder) + await fs.mkdir(JSONConversationalExtension._threadFolder) } } @@ -76,7 +75,7 @@ export default class JSONConversationalExtension extends ConversationalExtension JSONConversationalExtension._threadInfoFileName, ]) if (!(await fs.existsSync(threadDirPath))) { - await fs.mkdirSync(threadDirPath) + await fs.mkdir(threadDirPath) } await fs.writeFileSync(threadJsonPath, JSON.stringify(thread, null, 2)) @@ -96,11 +95,7 @@ export default class JSONConversationalExtension extends ConversationalExtension `${threadId}`, ]) try { - if (await fs.existsSync(path)) { - await fs.rmdirSync(path, { recursive: true }) - } else { - console.debug(`${path} does not exist`) - } + await fs.rm(path) } catch (err) { console.error(err) } @@ -117,11 +112,11 @@ export default class JSONConversationalExtension extends ConversationalExtension JSONConversationalExtension._threadMessagesFileName, ]) if (!(await fs.existsSync(threadDirPath))) - await fs.mkdirSync(threadDirPath) + await fs.mkdir(threadDirPath) if (message.content[0]?.type === 'image') { const filesPath = await joinPath([threadDirPath, 'files']) - if (!(await fs.existsSync(filesPath))) await fs.mkdirSync(filesPath) + if (!(await fs.existsSync(filesPath))) await fs.mkdir(filesPath) const imagePath = await joinPath([filesPath, `${message.id}.png`]) const base64 = message.content[0].text.annotations[0] @@ -134,7 +129,7 @@ export default class JSONConversationalExtension extends ConversationalExtension if (message.content[0]?.type === 'pdf') { const filesPath = await joinPath([threadDirPath, 'files']) - if (!(await fs.existsSync(filesPath))) await fs.mkdirSync(filesPath) + if (!(await fs.existsSync(filesPath))) await fs.mkdir(filesPath) const filePath = await joinPath([filesPath, `${message.id}.pdf`]) const blob = message.content[0].text.annotations[0] @@ -184,8 +179,7 @@ export default class JSONConversationalExtension extends ConversationalExtension threadDirPath, JSONConversationalExtension._threadMessagesFileName, ]) - if (!(await fs.existsSync(threadDirPath))) - await fs.mkdirSync(threadDirPath) + if (!(await fs.existsSync(threadDirPath))) await fs.mkdir(threadDirPath) await fs.writeFileSync( threadMessagePath, messages.map((msg) => JSON.stringify(msg)).join('\n') + diff --git a/extensions/huggingface-extension/src/index.ts b/extensions/huggingface-extension/src/index.ts index 88292ce582..b703a3e33f 100644 --- a/extensions/huggingface-extension/src/index.ts +++ b/extensions/huggingface-extension/src/index.ts @@ -15,7 +15,6 @@ import { log, DownloadRequest, } from '@janhq/core' -import { ggufMetadata } from 'hyllama' declare global { interface Window { @@ -138,7 +137,7 @@ export default class JanHuggingFaceExtension extends HuggingFaceExtension { ): Promise { if (this.interrupted) return const modelDirPath = await this.getModelDirPath(repoID) - if (!(await fs.existsSync(modelDirPath))) await fs.mkdirSync(modelDirPath) + if (!(await fs.existsSync(modelDirPath))) await fs.mkdir(modelDirPath) const files = this.getFileList(repoData) const filePaths: string[] = [] @@ -394,7 +393,6 @@ export default class JanHuggingFaceExtension extends HuggingFaceExtension { const localPath = await joinPath([modelDirPath, filePath]) await abortDownload(localPath) } - // ;(await fs.existsSync(modelDirPath)) && (await fs.rmdirSync(modelDirPath)) executeOnMain(NODE_MODULE_PATH, 'killProcesses') } diff --git a/extensions/inference-groq-extension/src/index.ts b/extensions/inference-groq-extension/src/index.ts index f4dc23d1ca..cd22c62f97 100644 --- a/extensions/inference-groq-extension/src/index.ts +++ b/extensions/inference-groq-extension/src/index.ts @@ -41,7 +41,7 @@ export default class JanInferenceGroqExtension extends RemoteOAIEngine { super.onLoad() if (!(await fs.existsSync(this._engineDir))) { - await fs.mkdirSync(this._engineDir).catch((err) => console.debug(err)) + await fs.mkdir(this._engineDir) } this.writeDefaultEngineSettings() diff --git a/extensions/inference-openai-extension/src/index.ts b/extensions/inference-openai-extension/src/index.ts index ad5b73a1e6..eb60540fa8 100644 --- a/extensions/inference-openai-extension/src/index.ts +++ b/extensions/inference-openai-extension/src/index.ts @@ -45,9 +45,7 @@ export default class JanInferenceOpenAIExtension extends RemoteOAIEngine { super.onLoad() if (!(await fs.existsSync(JanInferenceOpenAIExtension._engineDir))) { - await fs - .mkdirSync(JanInferenceOpenAIExtension._engineDir) - .catch((err) => console.debug(err)) + await fs.mkdir(JanInferenceOpenAIExtension._engineDir) } this.writeDefaultEngineSettings() diff --git a/extensions/inference-triton-trtllm-extension/src/index.ts b/extensions/inference-triton-trtllm-extension/src/index.ts index 0df64acf18..6f9a01d9b7 100644 --- a/extensions/inference-triton-trtllm-extension/src/index.ts +++ b/extensions/inference-triton-trtllm-extension/src/index.ts @@ -40,7 +40,7 @@ export default class JanInferenceTritonTrtLLMExtension extends RemoteOAIEngine { async onLoad() { super.onLoad() if (!(await fs.existsSync(this._engineDir))) { - await fs.mkdirSync(this._engineDir).catch((err) => console.debug(err)) + await fs.mkdir(this._engineDir) } this.writeDefaultEngineSettings() diff --git a/extensions/model-extension/src/index.ts b/extensions/model-extension/src/index.ts index 6072758842..d56e2e8242 100644 --- a/extensions/model-extension/src/index.ts +++ b/extensions/model-extension/src/index.ts @@ -100,7 +100,7 @@ export default class JanModelExtension extends ModelExtension { ): Promise { // create corresponding directory const modelDirPath = await joinPath([JanModelExtension._homeDir, model.id]) - if (!(await fs.existsSync(modelDirPath))) await fs.mkdirSync(modelDirPath) + if (!(await fs.existsSync(modelDirPath))) await fs.mkdir(modelDirPath) if (model.engine === InferenceEngine.nitro_tensorrt_llm) { if (!gpuSettings || gpuSettings.gpus.length === 0) { @@ -249,7 +249,7 @@ export default class JanModelExtension extends ModelExtension { modelInfo.metadata?.author?.toLowerCase() === 'user' if (isUserImportModel) { // just delete the folder - return fs.rmdirSync(dirPath) + return fs.rm(dirPath) } // remove all files under dirPath except model.json @@ -630,7 +630,7 @@ export default class JanModelExtension extends ModelExtension { } const modelFolderPath = await this.getModelFolderName(modelFolderName) - await fs.mkdirSync(modelFolderPath) + await fs.mkdir(modelFolderPath) const uniqueFolderName = await baseName(modelFolderPath) const modelBinaryFile = binaryName.endsWith( diff --git a/extensions/tensorrt-llm-extension/src/index.ts b/extensions/tensorrt-llm-extension/src/index.ts index 3af128886a..ce89beca26 100644 --- a/extensions/tensorrt-llm-extension/src/index.ts +++ b/extensions/tensorrt-llm-extension/src/index.ts @@ -151,10 +151,11 @@ export default class TensorRTLLMExtension extends LocalOAIEngine { for (const model of models) { const modelPath = await joinPath([modelFolderPath, model.id]) - console.debug(`modelPath: ${modelPath}`) - if (await fs.existsSync(modelPath)) { - console.debug(`Removing model ${modelPath}`) - await fs.rmdirSync(modelPath) + + try { + await fs.rm(modelPath) + } catch (err) { + console.error(`Error removing model ${modelPath}`, err) } } events.emit(ModelEvent.OnModelsUpdate, {}) diff --git a/web/screens/Settings/Advanced/index.tsx b/web/screens/Settings/Advanced/index.tsx index 67ebf81d52..035119accd 100644 --- a/web/screens/Settings/Advanced/index.tsx +++ b/web/screens/Settings/Advanced/index.tsx @@ -138,9 +138,12 @@ const Advanced = () => { }, [readSettings, setGpuList, setGpuEnabled, setGpusInUse, setVulkanEnabled]) const clearLogs = async () => { - if (await fs.existsSync(`file://logs`)) { - await fs.rmdirSync(`file://logs`, { recursive: true }) + try { + await fs.rm(`file://logs`) + } catch (err) { + console.error('Error clearing logs: ', err) } + toaster({ title: 'Logs cleared', description: 'All logs have been cleared.',