From 67d37a01f475f58aa29288395ccf8f36ff071b1c Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Tue, 16 Jul 2024 23:00:03 +0700 Subject: [PATCH 1/7] add checksum --- .../download-manager.service.ts | 45 +++++++++++++++---- .../src/usecases/models/models.usecases.ts | 40 +++++++++++++---- cortex-js/src/utils/huggingface.ts | 6 ++- 3 files changed, 72 insertions(+), 19 deletions(-) diff --git a/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts b/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts index 3c018ab77..ce0b951a0 100644 --- a/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts +++ b/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts @@ -11,6 +11,7 @@ import { Presets, SingleBar } from 'cli-progress'; import { createWriteStream } from 'node:fs'; import { basename } from 'node:path'; import { firstValueFrom } from 'rxjs'; +import crypto from 'crypto'; @Injectable() export class DownloadManagerService { @@ -41,7 +42,13 @@ export class DownloadManagerService { downloadId: string, title: string, downloadType: DownloadType, - urlToDestination: Record, + urlToDestination: Record< + string, + { + destination: string; + checksum?: string; + } + >, finishedCallback?: () => Promise, inSequence: boolean = true, ) { @@ -52,10 +59,10 @@ export class DownloadManagerService { ) { return; } - + console.log('asdfsdf', urlToDestination); const downloadItems: DownloadItem[] = Object.keys(urlToDestination).map( (url) => { - const destination = urlToDestination[url]; + const { destination, checksum } = urlToDestination[url]; const downloadItem: DownloadItem = { id: destination, time: { @@ -67,6 +74,7 @@ export class DownloadManagerService { transferred: 0, }, status: DownloadStatus.Downloading, + checksum, }; return downloadItem; @@ -105,15 +113,15 @@ export class DownloadManagerService { if (!inSequence) { return Promise.all( Object.keys(urlToDestination).map((url) => { - const destination = urlToDestination[url]; - return this.downloadFile(downloadId, url, destination); + const { destination, checksum } = urlToDestination[url]; + return this.downloadFile(downloadId, url, destination, checksum); }), ).then(callBack); } else { // Download model file in sequence for (const url of Object.keys(urlToDestination)) { - const destination = urlToDestination[url]; - await this.downloadFile(downloadId, url, destination); + const { destination, checksum } = urlToDestination[url]; + await this.downloadFile(downloadId, url, destination, checksum); } return callBack(); } @@ -123,11 +131,18 @@ export class DownloadManagerService { downloadId: string, url: string, destination: string, + checksum?: string, ) { + console.log('Downloading', { + downloadId, + url, + destination, + checksum, + }); const controller = new AbortController(); // adding to abort controllers this.abortControllers[downloadId][destination] = controller; - return new Promise(async (resolve, reject) => { + return new Promise(async (resolve) => { const response = await firstValueFrom( this.httpService.get(url, { responseType: 'stream', @@ -141,6 +156,7 @@ export class DownloadManagerService { } const writer = createWriteStream(destination); + const hash = crypto.createHash('sha256'); const totalBytes = Number(response.headers['content-length']); // update download state @@ -177,8 +193,18 @@ export class DownloadManagerService { const downloadItem = currentDownloadState?.children.find( (downloadItem) => downloadItem.id === destination, ); + const isFileBroken = checksum && checksum === hash.digest('hex'); if (downloadItem) { - downloadItem.status = DownloadStatus.Downloaded; + downloadItem.status = isFileBroken + ? DownloadStatus.Error + : DownloadStatus.Downloaded; + if (isFileBroken) { + downloadItem.error = 'Checksum is not matched'; + } + } + if (isFileBroken) { + currentDownloadState.status = DownloadStatus.Error; + currentDownloadState.error = 'Checksum is not matched'; } this.eventEmitter.emit('download.event', this.allDownloadStates); @@ -219,6 +245,7 @@ export class DownloadManagerService { }); response.data.on('data', (chunk: any) => { + hash.update(chunk); transferredBytes += chunk.length; const currentDownloadState = this.allDownloadStates.find( diff --git a/cortex-js/src/usecases/models/models.usecases.ts b/cortex-js/src/usecases/models/models.usecases.ts index 9c3824a17..4f55b7a08 100644 --- a/cortex-js/src/usecases/models/models.usecases.ts +++ b/cortex-js/src/usecases/models/models.usecases.ts @@ -344,11 +344,11 @@ export class ModelsUsecases { await promises.mkdir(modelFolder, { recursive: true }).catch(() => {}); let files = (await fetchJanRepoData(originModelId)).siblings; - + // HuggingFace GGUF Repo - Only one file is downloaded if (originModelId.includes('/') && selection && files.length) { try { - files = [await selection(files)]; + files = [await selection(files)]; } catch (e) { const modelEvent: ModelEvent = { model: modelId, @@ -363,14 +363,36 @@ export class ModelsUsecases { } // Start downloading the model - const toDownloads: Record = files + console.log('Downloading model:', modelId, files); + const toDownloads: Record< + string, + { + destination: string; + checksum?: string; + } + > = files .filter((e) => this.validFileDownload(e)) - .reduce((acc: Record, file) => { - if (file.downloadUrl) - acc[file.downloadUrl] = join(modelFolder, file.rfilename); - return acc; - }, {}); - + .reduce( + ( + acc: Record< + string, + { + destination: string; + checksum?: string; + } + >, + file, + ) => { + if (file.downloadUrl) + acc[file.downloadUrl] = { + destination: join(modelFolder, file.rfilename), + checksum: file.lfs.oid, + }; + return acc; + }, + {}, + ); + console.log('Downloading model:', toDownloads); return this.downloadManagerService.submitDownloadRequest( modelId, modelId, diff --git a/cortex-js/src/utils/huggingface.ts b/cortex-js/src/utils/huggingface.ts index 099e1aacf..cf31eb44c 100644 --- a/cortex-js/src/utils/huggingface.ts +++ b/cortex-js/src/utils/huggingface.ts @@ -125,6 +125,7 @@ export async function fetchJanRepoData( const res = await fetch(url); const jsonData = await res.json(); + console.log('Jan repo data:', jsonData); if ('siblings' in jsonData) { AllQuantizations.forEach((quantization) => { jsonData.siblings.forEach((sibling: HuggingFaceRepoSibling) => { @@ -137,6 +138,7 @@ export async function fetchJanRepoData( } }); }); + console.log('Jan repo data:', jsonData); return jsonData as HuggingFaceRepoData; } @@ -144,6 +146,7 @@ export async function fetchJanRepoData( | { path: string; size: number; + lfs?: { oid?: string }; }[] | { error: string } = jsonData; @@ -159,6 +162,7 @@ export async function fetchJanRepoData( rfilename: e.path, downloadUrl: HUGGING_FACE_TREE_REF_URL(repo, tree, e.path), fileSize: e.size ?? 0, + lfs: e.lfs ?? { oid: '' }, }; }) : [], @@ -186,7 +190,7 @@ export async function fetchJanRepoData( }); data.modelUrl = url; - + console.log('Jan repo data:', data); return data; } From 671a30358ccb1894a560c9005842a07ac1200f7e Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Wed, 7 Aug 2024 04:17:01 +0700 Subject: [PATCH 2/7] add engine version, fix cortex client not found --- cortex-js/package.json | 2 +- .../src/domain/models/huggingface.interface.ts | 2 ++ .../src/infrastructure/commanders/base.command.ts | 3 +++ .../src/infrastructure/commanders/chat.command.ts | 13 ++++++++++++- .../infrastructure/commanders/engines.command.ts | 1 + .../src/infrastructure/commanders/models.command.ts | 1 + .../src/infrastructure/commanders/run.command.ts | 5 +++++ .../download-manager/download-manager.service.ts | 5 +++++ cortex-js/src/main.ts | 3 +-- cortex-js/src/usecases/engines/engines.usecase.ts | 4 ++-- cortex-js/src/utils/huggingface.ts | 8 ++++---- 11 files changed, 37 insertions(+), 10 deletions(-) diff --git a/cortex-js/package.json b/cortex-js/package.json index d8ceb5063..aaf92f5d5 100644 --- a/cortex-js/package.json +++ b/cortex-js/package.json @@ -38,7 +38,7 @@ "preuninstall": "node ./uninstall.js" }, "dependencies": { - "@cortexso/cortex.js": "^0.1.5", + "@cortexso/cortex.js": "^0.1.7", "@nestjs/axios": "^3.0.2", "@nestjs/common": "^10.0.0", "@nestjs/config": "^3.2.2", diff --git a/cortex-js/src/domain/models/huggingface.interface.ts b/cortex-js/src/domain/models/huggingface.interface.ts index 2ab46dc79..ae5b9a4a1 100644 --- a/cortex-js/src/domain/models/huggingface.interface.ts +++ b/cortex-js/src/domain/models/huggingface.interface.ts @@ -10,6 +10,7 @@ export interface HuggingFaceRepoSibling { downloadUrl?: string; fileSize?: number; quantization?: Quantization; + lfs?: { oid?: string }; } export interface HuggingFaceRepoData { id: string; @@ -27,6 +28,7 @@ export interface HuggingFaceRepoData { cardData: Record; siblings: HuggingFaceRepoSibling[]; createdAt: string; + verified?: boolean; } const CardDataKeys = [ diff --git a/cortex-js/src/infrastructure/commanders/base.command.ts b/cortex-js/src/infrastructure/commanders/base.command.ts index e0839fcb2..5d3be2b98 100644 --- a/cortex-js/src/infrastructure/commanders/base.command.ts +++ b/cortex-js/src/infrastructure/commanders/base.command.ts @@ -34,4 +34,7 @@ export abstract class BaseCommand extends CommandRunner { } await this.runCommand(passedParam, options); } + protected setCortex(cortex: CortexClient) { + this.cortex = cortex; + } } diff --git a/cortex-js/src/infrastructure/commanders/chat.command.ts b/cortex-js/src/infrastructure/commanders/chat.command.ts index b23a9b956..c20845394 100644 --- a/cortex-js/src/infrastructure/commanders/chat.command.ts +++ b/cortex-js/src/infrastructure/commanders/chat.command.ts @@ -18,7 +18,6 @@ import { Cortex } from '@cortexso/cortex.js'; import { ChatClient } from './services/chat-client'; import { downloadProgress } from '@/utils/download-progress'; import { DownloadType } from '@/domain/models/download.interface'; -import { CortexClient } from './services/cortex.client'; type ChatOptions = { threadId?: string; @@ -96,6 +95,18 @@ export class ChatCommand extends BaseCommand { await downloadProgress(this.cortex, undefined, DownloadType.Engine); } + const { version: engineVersion } = + await this.cortex.engines.retrieve(engine); + if ( + existingModel.engine_version && + existingModel.engine_version > engineVersion + ) { + console.log( + `Model engine version ${existingModel.engine_version} is not compatible with engine version ${engineVersion}`, + ); + process.exit(1); + } + if (!message) options.attach = true; this.telemetryUsecases.sendEvent( [ diff --git a/cortex-js/src/infrastructure/commanders/engines.command.ts b/cortex-js/src/infrastructure/commanders/engines.command.ts index 9f3e84b82..c4861f325 100644 --- a/cortex-js/src/infrastructure/commanders/engines.command.ts +++ b/cortex-js/src/infrastructure/commanders/engines.command.ts @@ -61,6 +61,7 @@ export class EnginesCommand extends BaseCommand { ) { const commandInstance = this.moduleRef.get(commandClass, { strict: false }); if (commandInstance) { + commandInstance.setCortex(this.cortex); await commandInstance.runCommand(params, options); } else { console.error('Command not found.'); diff --git a/cortex-js/src/infrastructure/commanders/models.command.ts b/cortex-js/src/infrastructure/commanders/models.command.ts index ab3f562b4..d66dd0989 100644 --- a/cortex-js/src/infrastructure/commanders/models.command.ts +++ b/cortex-js/src/infrastructure/commanders/models.command.ts @@ -67,6 +67,7 @@ export class ModelsCommand extends BaseCommand { ) { const commandInstance = this.moduleRef.get(commandClass, { strict: false }); if (commandInstance) { + commandInstance.setCortex(this.cortex); await commandInstance.runCommand(params, options); } else { console.error('Command not found.'); diff --git a/cortex-js/src/infrastructure/commanders/run.command.ts b/cortex-js/src/infrastructure/commanders/run.command.ts index 1ae5fc9a4..08f9cea19 100644 --- a/cortex-js/src/infrastructure/commanders/run.command.ts +++ b/cortex-js/src/infrastructure/commanders/run.command.ts @@ -98,6 +98,11 @@ export class RunCommand extends BaseCommand { await this.cortex.engines.init(engine); await downloadProgress(this.cortex, undefined, DownloadType.Engine); } + const { version: engineVersion } = await this.cortex.engines.retrieve(engine); + if(existingModel.engine_version && existingModel.engine_version > engineVersion) { + console.log(`Model engine version ${existingModel.engine_version} is not compatible with engine version ${engineVersion}`); + process.exit(1); + } const startingSpinner = ora('Loading model...').start(); diff --git a/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts b/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts index e347fab05..c14d24e04 100644 --- a/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts +++ b/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts @@ -237,6 +237,11 @@ export class DownloadManagerService { : DownloadStatus.Downloaded; if (isFileBroken) { downloadItem.error = 'Checksum is not matched'; + this.handleError( + new Error('Checksum is not matched'), + downloadId, + destination, + ); } } if (isFileBroken) { diff --git a/cortex-js/src/main.ts b/cortex-js/src/main.ts index 1a43ca318..988e55426 100644 --- a/cortex-js/src/main.ts +++ b/cortex-js/src/main.ts @@ -6,11 +6,10 @@ import { getApp } from './app'; import chalk from 'chalk'; async function bootstrap() { - const app = await getApp(); // getting port from env const host = process.env.CORTEX_JS_HOST || defaultCortexJsHost; const port = process.env.CORTEX_JS_PORT || defaultCortexJsPort; - + const app = await getApp(host, Number(port)); try { await app.listen(port, host); console.log(chalk.blue(`Started server at http://${host}:${port}`)); diff --git a/cortex-js/src/usecases/engines/engines.usecase.ts b/cortex-js/src/usecases/engines/engines.usecase.ts index 7df0a23e3..ae8d50f55 100644 --- a/cortex-js/src/usecases/engines/engines.usecase.ts +++ b/cortex-js/src/usecases/engines/engines.usecase.ts @@ -199,7 +199,7 @@ export class EnginesUsecases { url, 'Cuda Toolkit Dependencies', DownloadType.Engine, - { [url]: destination }, + { [url]: { destination } }, async () => { try { await decompress( @@ -274,7 +274,7 @@ export class EnginesUsecases { toDownloadAsset.browser_download_url, engine, DownloadType.Engine, - { [toDownloadAsset.browser_download_url]: destination }, + { [toDownloadAsset.browser_download_url]: { destination } }, // On completed - post processing async () => { try { diff --git a/cortex-js/src/utils/huggingface.ts b/cortex-js/src/utils/huggingface.ts index 4ab3be1d6..180f681bd 100644 --- a/cortex-js/src/utils/huggingface.ts +++ b/cortex-js/src/utils/huggingface.ts @@ -125,7 +125,6 @@ export async function fetchJanRepoData( const res = await fetch(url); const jsonData = await res.json(); - console.log('Jan repo data:', jsonData); if ('siblings' in jsonData) { AllQuantizations.forEach((quantization) => { jsonData.siblings.forEach((sibling: HuggingFaceRepoSibling) => { @@ -138,7 +137,6 @@ export async function fetchJanRepoData( } }); }); - console.log('Jan repo data:', jsonData); return jsonData as HuggingFaceRepoData; } @@ -146,7 +144,7 @@ export async function fetchJanRepoData( | { path: string; size: number; - lfs?: { oid?: string }; + oid?: string; }[] | { error: string } = jsonData; @@ -162,7 +160,9 @@ export async function fetchJanRepoData( rfilename: e.path, downloadUrl: HUGGING_FACE_TREE_REF_URL(repo, tree, e.path), fileSize: e.size ?? 0, - lfs: e.lfs ?? { oid: '' }, + lfs: { + oid: e.oid, + }, }; }) : [], From ec879f321cc67b65e9b56d1640f44652b9a8a5a6 Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Wed, 7 Aug 2024 09:46:11 +0700 Subject: [PATCH 3/7] remove log --- .../services/download-manager/download-manager.service.ts | 2 +- cortex-js/src/usecases/models/models.usecases.ts | 2 -- cortex-js/src/utils/huggingface.ts | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts b/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts index c14d24e04..6ae6550fb 100644 --- a/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts +++ b/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts @@ -69,7 +69,7 @@ export class DownloadManagerService { ) { return; } - console.log('asdfsdf', urlToDestination); + const downloadItems: DownloadItem[] = Object.keys(urlToDestination).map( (url) => { const { destination, checksum } = urlToDestination[url]; diff --git a/cortex-js/src/usecases/models/models.usecases.ts b/cortex-js/src/usecases/models/models.usecases.ts index 78e2f0dc6..7c631e6f9 100644 --- a/cortex-js/src/usecases/models/models.usecases.ts +++ b/cortex-js/src/usecases/models/models.usecases.ts @@ -399,7 +399,6 @@ export class ModelsUsecases { } // Start downloading the model - console.log('Downloading model:', modelId, files); const toDownloads: Record< string, { @@ -428,7 +427,6 @@ export class ModelsUsecases { }, {}, ); - console.log('Downloading model:', toDownloads); return this.downloadManagerService.submitDownloadRequest( modelId, modelId, diff --git a/cortex-js/src/utils/huggingface.ts b/cortex-js/src/utils/huggingface.ts index 180f681bd..38b642ad0 100644 --- a/cortex-js/src/utils/huggingface.ts +++ b/cortex-js/src/utils/huggingface.ts @@ -190,7 +190,6 @@ export async function fetchJanRepoData( }); data.modelUrl = url; - console.log('Jan repo data:', data); return data; } From b724cafc2b79e26467765ffa2982108b54da8352 Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Wed, 7 Aug 2024 09:55:32 +0700 Subject: [PATCH 4/7] remove unused field --- cortex-js/src/domain/models/huggingface.interface.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/cortex-js/src/domain/models/huggingface.interface.ts b/cortex-js/src/domain/models/huggingface.interface.ts index ae5b9a4a1..2c2274b3e 100644 --- a/cortex-js/src/domain/models/huggingface.interface.ts +++ b/cortex-js/src/domain/models/huggingface.interface.ts @@ -28,7 +28,6 @@ export interface HuggingFaceRepoData { cardData: Record; siblings: HuggingFaceRepoSibling[]; createdAt: string; - verified?: boolean; } const CardDataKeys = [ From fab7dc3013e040c064eaedf63c727fb1b6c713e2 Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Wed, 7 Aug 2024 10:20:24 +0700 Subject: [PATCH 5/7] update check version function --- .../infrastructure/commanders/chat.command.ts | 5 +++-- .../src/infrastructure/commanders/run.command.ts | 4 ++-- cortex-js/src/utils/model-check.ts | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/cortex-js/src/infrastructure/commanders/chat.command.ts b/cortex-js/src/infrastructure/commanders/chat.command.ts index c20845394..35b2ef5ba 100644 --- a/cortex-js/src/infrastructure/commanders/chat.command.ts +++ b/cortex-js/src/infrastructure/commanders/chat.command.ts @@ -18,6 +18,7 @@ import { Cortex } from '@cortexso/cortex.js'; import { ChatClient } from './services/chat-client'; import { downloadProgress } from '@/utils/download-progress'; import { DownloadType } from '@/domain/models/download.interface'; +import { checkRequiredVersion } from '@/utils/model-check'; type ChatOptions = { threadId?: string; @@ -99,7 +100,7 @@ export class ChatCommand extends BaseCommand { await this.cortex.engines.retrieve(engine); if ( existingModel.engine_version && - existingModel.engine_version > engineVersion + !checkRequiredVersion(existingModel.engine_version, engineVersion) ) { console.log( `Model engine version ${existingModel.engine_version} is not compatible with engine version ${engineVersion}`, @@ -108,7 +109,7 @@ export class ChatCommand extends BaseCommand { } if (!message) options.attach = true; - this.telemetryUsecases.sendEvent( + void this.telemetryUsecases.sendEvent( [ { name: EventName.CHAT, diff --git a/cortex-js/src/infrastructure/commanders/run.command.ts b/cortex-js/src/infrastructure/commanders/run.command.ts index 08f9cea19..a0dcdcb84 100644 --- a/cortex-js/src/infrastructure/commanders/run.command.ts +++ b/cortex-js/src/infrastructure/commanders/run.command.ts @@ -5,7 +5,7 @@ import ora from 'ora'; import { existsSync } from 'fs'; import { join } from 'path'; import { Engines } from './types/engine.interface'; -import { checkModelCompatibility } from '@/utils/model-check'; +import { checkModelCompatibility, checkRequiredVersion } from '@/utils/model-check'; import { BaseCommand } from './base.command'; import { isRemoteEngine } from '@/utils/normalize-model-id'; import { ChatClient } from './services/chat-client'; @@ -99,7 +99,7 @@ export class RunCommand extends BaseCommand { await downloadProgress(this.cortex, undefined, DownloadType.Engine); } const { version: engineVersion } = await this.cortex.engines.retrieve(engine); - if(existingModel.engine_version && existingModel.engine_version > engineVersion) { + if(existingModel.engine_version && !checkRequiredVersion(existingModel.engine_version, engineVersion)) { console.log(`Model engine version ${existingModel.engine_version} is not compatible with engine version ${engineVersion}`); process.exit(1); } diff --git a/cortex-js/src/utils/model-check.ts b/cortex-js/src/utils/model-check.ts index 78ca84b60..05cd8827f 100644 --- a/cortex-js/src/utils/model-check.ts +++ b/cortex-js/src/utils/model-check.ts @@ -45,3 +45,19 @@ export const checkModelCompatibility = async ( } } }; + +export const parseVersion = (version: string) => { + return version.split('.').map(Number); +}; + +export const checkRequiredVersion = (version: string, minVersion: string) => { + const [currentMajor, currentMinor, currentPatch] = parseVersion(version); + const [requiredMajor, requiredMinor, requiredPatch] = + parseVersion(minVersion); + return ( + currentMajor > requiredMajor || + (currentMajor === requiredMajor && + (currentMinor > requiredMinor || + (currentMinor === requiredMinor && currentPatch >= requiredPatch))) + ); +}; From e22fc45587b0eaea5bb8a73f07a1329cd9369131 Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Wed, 7 Aug 2024 11:22:01 +0700 Subject: [PATCH 6/7] change config file name --- .../file-manager/file-manager.service.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts b/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts index 071f95b12..035bdd8c0 100644 --- a/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts +++ b/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts @@ -28,7 +28,6 @@ const writeAsync = promisify(write); @Injectable() export class FileManagerService { - private configFile = '.cortexrc'; private cortexDirectoryName = 'cortex'; private modelFolderName = 'models'; private presetFolderName = 'presets'; @@ -44,7 +43,7 @@ export class FileManagerService { */ async getConfig(dataFolderPath?: string): Promise { const homeDir = os.homedir(); - const configPath = join(homeDir, this.configFile); + const configPath = join(homeDir, this.getConfigFileName()); const config = this.defaultConfig(); const dataFolderPathUsed = dataFolderPath || config.dataFolderPath; if (!existsSync(configPath) || !existsSync(dataFolderPathUsed)) { @@ -72,7 +71,7 @@ export class FileManagerService { async writeConfigFile(config: Config & object): Promise { const homeDir = os.homedir(); - const configPath = join(homeDir, this.configFile); + const configPath = join(homeDir, this.getConfigFileName()); // write config to file as yaml if (!existsSync(configPath)) { @@ -345,7 +344,7 @@ export class FileManagerService { */ getServerConfig(): { host: string; port: number } { const homeDir = os.homedir(); - const configPath = join(homeDir, this.configFile); + const configPath = join(homeDir, this.getConfigFileName()); let config = this.defaultConfig(); try { const content = readFileSync(configPath, 'utf8'); @@ -366,7 +365,7 @@ export class FileManagerService { } public profileConfigExists(profile: string): boolean { const homeDir = os.homedir(); - const configPath = join(homeDir, this.configFile); + const configPath = join(homeDir, this.getConfigFileName()); try { const content = readFileSync(configPath, 'utf8'); const configs = (yaml.load(content) as Record) ?? {}; @@ -375,6 +374,13 @@ export class FileManagerService { return false; } } + + private getConfigFileName(): string { + if (this.configProfile === 'default') { + return '.cortexrc'; + } + return `.${this.configProfile}rc`; + } } export const fileManagerService = new FileManagerService(); From a05f4600224b8f2697164a9dcd7e8565ecbfc2aa Mon Sep 17 00:00:00 2001 From: marknguyen1302 Date: Wed, 7 Aug 2024 11:31:09 +0700 Subject: [PATCH 7/7] update config file --- .../file-manager/file-manager.service.ts | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts b/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts index 035bdd8c0..5043028cd 100644 --- a/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts +++ b/cortex-js/src/infrastructure/services/file-manager/file-manager.service.ts @@ -43,7 +43,10 @@ export class FileManagerService { */ async getConfig(dataFolderPath?: string): Promise { const homeDir = os.homedir(); - const configPath = join(homeDir, this.getConfigFileName()); + const configPath = join( + homeDir, + this.getConfigFileName(this.configProfile), + ); const config = this.defaultConfig(); const dataFolderPathUsed = dataFolderPath || config.dataFolderPath; if (!existsSync(configPath) || !existsSync(dataFolderPathUsed)) { @@ -54,8 +57,7 @@ export class FileManagerService { try { const content = await promises.readFile(configPath, 'utf8'); - const configs = yaml.load(content) as Record; - const config = configs?.[this.configProfile] ?? {}; + const config = yaml.load(content) as Config & object; return { ...this.defaultConfig(), ...config, @@ -71,17 +73,20 @@ export class FileManagerService { async writeConfigFile(config: Config & object): Promise { const homeDir = os.homedir(); - const configPath = join(homeDir, this.getConfigFileName()); + const configPath = join( + homeDir, + this.getConfigFileName(this.configProfile), + ); // write config to file as yaml if (!existsSync(configPath)) { await promises.writeFile(configPath, '', 'utf8'); } const content = await promises.readFile(configPath, 'utf8'); - const currentConfig = yaml.load(content) as Record; + const currentConfig = yaml.load(content) as Config & object; const configString = yaml.dump({ ...currentConfig, - [this.configProfile]: config, + ...config, }); await promises.writeFile(configPath, configString, 'utf8'); } @@ -344,12 +349,17 @@ export class FileManagerService { */ getServerConfig(): { host: string; port: number } { const homeDir = os.homedir(); - const configPath = join(homeDir, this.getConfigFileName()); + const configPath = join( + homeDir, + this.getConfigFileName(this.configProfile), + ); let config = this.defaultConfig(); try { const content = readFileSync(configPath, 'utf8'); - const configs = (yaml.load(content) as Record) ?? {}; - config = configs?.[this.configProfile] ?? config; + const currentConfig = (yaml.load(content) as Config & object) ?? {}; + if (currentConfig) { + config = currentConfig; + } } catch {} return { host: config.apiServerHost ?? '127.0.0.1', @@ -365,21 +375,21 @@ export class FileManagerService { } public profileConfigExists(profile: string): boolean { const homeDir = os.homedir(); - const configPath = join(homeDir, this.getConfigFileName()); + const configPath = join(homeDir, this.getConfigFileName(profile)); try { const content = readFileSync(configPath, 'utf8'); - const configs = (yaml.load(content) as Record) ?? {}; - return !!configs[profile]; + const config = yaml.load(content) as Config & object; + return !!config; } catch { return false; } } - private getConfigFileName(): string { - if (this.configProfile === 'default') { + private getConfigFileName(configProfile: string): string { + if (configProfile === 'default') { return '.cortexrc'; } - return `.${this.configProfile}rc`; + return `.${configProfile}rc`; } }