Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: set cortex data folder path when starting jan #3252

Merged
merged 6 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/src/types/file/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,5 @@ export interface DownloadStateEvent {
export enum DownloadType2 {
Model = 'model',
Miscelanous = 'miscelanous',
Engine = 'engine',
}
64 changes: 35 additions & 29 deletions electron/handlers/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@ import {
} from '@janhq/core/node'
import { menu } from '../utils/menu'
import { join } from 'path'
import { getJanDataFolderPath } from './../utils/path'
import { getAppConfigurations, getJanDataFolderPath } from './../utils/path'
import {
readdirSync,
writeFileSync,
readFileSync,
existsSync,
mkdirSync
mkdirSync,
} from 'fs'
import { dump } from 'js-yaml'
import os from 'os'

const isMac = process.platform === 'darwin'

Expand Down Expand Up @@ -178,7 +177,7 @@ export function handleAppIPCs() {
}
)

ipcMain.handle(NativeRoute.showOpenMenu, function (e, args) {
ipcMain.handle(NativeRoute.showOpenMenu, function (_e, args) {
if (!isMac && windowManager.mainWindow) {
menu.popup({
window: windowManager.mainWindow,
Expand Down Expand Up @@ -209,10 +208,11 @@ export function handleAppIPCs() {
})

ipcMain.handle(NativeRoute.openAppLog, async (_event): Promise<void> => {
const cortexHomeDir = join(os.homedir(), 'cortex')
const configuration = getAppConfigurations()
const dataFolder = configuration.data_folder

try {
const errorMessage = await shell.openPath(join(cortexHomeDir))
const errorMessage = await shell.openPath(join(dataFolder))
if (errorMessage) {
console.error(`An error occurred: ${errorMessage}`)
} else {
Expand All @@ -227,21 +227,19 @@ export function handleAppIPCs() {
const janModelFolderPath = join(getJanDataFolderPath(), 'models')
const allModelFolders = readdirSync(janModelFolderPath)

const cortexHomeDir = join(os.homedir(), 'cortex')
const cortexModelFolderPath = join(cortexHomeDir, 'models')
const configration = getAppConfigurations()
const destinationFolderPath = join(configration.data_folder, 'models')

if(!existsSync(cortexModelFolderPath))
mkdirSync(cortexModelFolderPath)
console.log('cortexModelFolderPath', cortexModelFolderPath)
if (!existsSync(destinationFolderPath)) mkdirSync(destinationFolderPath)
console.log('destinationFolderPath', destinationFolderPath)
const reflect = require('@alumna/reflect')

for (const modelName of allModelFolders) {
const modelFolderPath = join(janModelFolderPath, modelName)
try {

const filesInModelFolder = readdirSync(modelFolderPath)

const destinationPath = join(cortexModelFolderPath, modelName)
const destinationPath = join(destinationFolderPath, modelName)

const modelJsonFullPath = join(
janModelFolderPath,
Expand All @@ -253,23 +251,29 @@ export function handleAppIPCs() {
const fileNames: string[] = model.sources.map((x: any) => x.filename)
let files: string[] = []

if(filesInModelFolder.length > 1) {
// prepend fileNames with cortexModelFolderPath
if (filesInModelFolder.length > 1) {
// prepend fileNames with model folder path
files = fileNames.map((x: string) =>
join(cortexModelFolderPath, model.id, x)
join(destinationFolderPath, model.id, x)
)
} else if(model.sources.length && !/^(http|https):\/\/[^/]+\/.*/.test(model.sources[0].url)) {
} else if (
model.sources.length &&
!/^(http|https):\/\/[^/]+\/.*/.test(model.sources[0].url)
) {
// Symlink case
files = [ model.sources[0].url ]
} else continue;
files = [model.sources[0].url]
} else continue

// create folder if not exist
// only for local model files
if (!existsSync(destinationPath) && filesInModelFolder.length > 1) {
mkdirSync(destinationPath, { recursive: true })
}

const engine = (model.engine === 'nitro' || model.engine === 'cortex') ? 'cortex.llamacpp' : (model.engine ?? 'cortex.llamacpp')
const engine =
model.engine === 'nitro' || model.engine === 'cortex'
? 'cortex.llamacpp'
: (model.engine ?? 'cortex.llamacpp')

const updatedModelFormat = {
id: model.id,
Expand All @@ -296,7 +300,7 @@ export function handleAppIPCs() {
max_tokens: model.parameters?.max_tokens ?? 2048,
stream: model.parameters?.stream ?? true,
}
if(filesInModelFolder.length > 1 ) {
if (filesInModelFolder.length > 1) {
const { err } = await reflect({
src: modelFolderPath,
dest: destinationPath,
Expand All @@ -307,14 +311,14 @@ export function handleAppIPCs() {
errorOnExist: false,
})

if (err) {
console.error(err);
continue;
if (err) {
console.error(err)
continue
}
}
// create the model.yml file
const modelYamlData = dump(updatedModelFormat)
const modelYamlPath = join(cortexModelFolderPath, `${modelName}.yaml`)
const modelYamlPath = join(destinationFolderPath, `${modelName}.yaml`)

writeFileSync(modelYamlPath, modelYamlData)
} catch (err) {
Expand Down Expand Up @@ -354,11 +358,11 @@ export function handleAppIPCs() {
'messages.jsonl'
)

if(!existsSync(messageFullPath)) continue;
if (!existsSync(messageFullPath)) continue
const lines = readFileSync(messageFullPath, 'utf-8')
.toString()
.split('\n')
.filter((line: any) => line !== '')
.toString()
.split('\n')
.filter((line: any) => line !== '')
for (const line of lines) {
messages.push(JSON.parse(line))
}
Expand All @@ -379,8 +383,10 @@ export function handleAppIPCs() {
const janModelsFolderPath = join(getJanDataFolderPath(), 'models')

if (!existsSync(janModelsFolderPath)) {
console.debug('No local models found')
return false
}

// get children of thread folder
const allModelsFolders = readdirSync(janModelsFolderPath)
let hasLocalModels = false
Expand Down
29 changes: 24 additions & 5 deletions electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { handleAppIPCs } from './handlers/native'
* Utils
**/
import { setupMenu } from './utils/menu'
import { createUserSpace } from './utils/path'
import { createUserSpace, getAppConfigurations } from './utils/path'
import { migrate } from './utils/migration'
import { cleanUpAndQuit } from './utils/clean'
import { setupCore } from './utils/setup'
Expand Down Expand Up @@ -58,12 +58,31 @@ Object.assign(console, log.functions)

let cortexService: ChildProcess | undefined = undefined

const cortexJsPort = 1338
const cortexCppPort = 3940
const host = '127.0.0.1'

app
.whenReady()
.then(() => killProcessesOnPort(3929))
.then(() => killProcessesOnPort(1337))
.then(() => killProcessesOnPort(cortexCppPort))
.then(() => killProcessesOnPort(cortexJsPort))
.then(() => {
const command = `${cortexPath} -a 127.0.0.1 -p 1337`
const appConfiguration = getAppConfigurations()
const janDataFolder = appConfiguration.data_folder

const cortexParams: Record<string, string> = {
'-n': 'jan',
'-a': host,
'-p': cortexJsPort.toString(),
'-ep': cortexCppPort.toString(),
'--dataFolder': janDataFolder,
}

// add cortex parameters to the command
const command = Object.entries(cortexParams).reduce(
(acc, [key, value]) => `${acc} ${key} ${value}`,
`${cortexPath}`
)

log.info('Starting cortex with command:', command)
// init cortex
Expand Down Expand Up @@ -154,7 +173,7 @@ async function stopCortexService() {
async function stopApiServer() {
// this function is not meant to be success. It will throw an error.
try {
await fetch('http://localhost:1337/v1/system', {
await fetch(`http://${host}:${cortexJsPort}/v1/system`, {
method: 'DELETE',
})
} catch (error) {
Expand Down
2 changes: 1 addition & 1 deletion electron/resources/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.5.0-27
0.5.0-29
9 changes: 7 additions & 2 deletions web/containers/Layout/BottomPanel/DownloadingStatus/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,21 @@ const DownloadStatus: React.FC = () => {
? ((totalTransfferedSize / totalDownloadSize) * 100).toFixed(2)
: 0

const downloadTitle = `Downloading ${downloadStates
.map((state) => state.type)
.join(', ')
.trim()}`

return (
<Fragment>
{Object.values(downloadStates)?.length > 0 && (
<Modal
title="Downloading model"
title={downloadTitle}
trigger={
<div className="flex cursor-pointer items-center gap-2">
<Button size="small" theme="ghost">
<span className="font-medium">
Downloading model{' '}
{downloadTitle}{' '}
{Object.values(downloadStates).length > 1 &&
`1/${Object.values(downloadStates).length}`}
</span>
Expand Down
33 changes: 33 additions & 0 deletions web/containers/Layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import TopPanel from '@/containers/Layout/TopPanel'

import { getImportModelStageAtom } from '@/hooks/useImportModel'

import useMigratingData from '@/hooks/useMigratingData'

import DownloadLocalModelModal from '@/screens/HubScreen2/components/DownloadLocalModelModal'
import InferenceErrorModal from '@/screens/HubScreen2/components/InferenceErrorModal'
import SetUpApiKeyModal from '@/screens/HubScreen2/components/SetUpApiKeyModal'
Expand All @@ -33,24 +35,54 @@ import LoadingModal from '../LoadingModal'

import MainViewContainer from '../MainViewContainer'

import ModalMigrations, {
showMigrationModalAtom,
} from '../Providers/ModalMigrations'
import WaitingForCortexModal from '../WaitingCortexModal'

import InstallingExtensionModal from './BottomPanel/InstallingExtension/InstallingExtensionModal'

import { MainViewState, mainViewStateAtom } from '@/helpers/atoms/App.atom'
import { didShowMigrationWarningAtom } from '@/helpers/atoms/AppConfig.atom'
import { reduceTransparentAtom } from '@/helpers/atoms/Setting.atom'

const BaseLayout = () => {
const didShowMigrationWarning = useAtomValue(didShowMigrationWarningAtom)
const setShowMigrationModal = useSetAtom(showMigrationModalAtom)
const setMainViewState = useSetAtom(mainViewStateAtom)
const importModelStage = useAtomValue(getImportModelStageAtom)
const reduceTransparent = useAtomValue(reduceTransparentAtom)
const { getJanThreadsAndMessages, getJanLocalModels } = useMigratingData()

useEffect(() => {
if (localStorage.getItem(SUCCESS_SET_NEW_DESTINATION) === 'true') {
setMainViewState(MainViewState.Settings)
}
}, [setMainViewState])

useEffect(() => {
if (didShowMigrationWarning) return

const isUserHaveData = async (): Promise<boolean> => {
const threadAndMessageData = await getJanThreadsAndMessages()
const isUserHaveAnyModel = await getJanLocalModels()
return threadAndMessageData.threads.length > 0 || isUserHaveAnyModel
}

isUserHaveData()
.then((isUserHaveData) => {
if (isUserHaveData === true) {
setShowMigrationModal(true)
}
})
.catch((e) => console.error('Error checking user data', e))
}, [
didShowMigrationWarning,
getJanThreadsAndMessages,
getJanLocalModels,
setShowMigrationModal,
])

return (
<div
className={twMerge(
Expand Down Expand Up @@ -92,6 +124,7 @@ const BaseLayout = () => {
<ChooseWhatToImportModal />
<InstallingExtensionModal />
<HuggingFaceRepoDetailModal />
<ModalMigrations />
</div>
<BottomPanel />
</div>
Expand Down
Loading
Loading