115 lines
3.1 KiB
TypeScript

import path from 'path'
import {
appResourcePath,
getJanDataFolderPath,
log,
SystemInformation,
} from '@janhq/core/node'
import { ProcessWatchdog } from './watchdog'
import { readdir, symlink } from 'fs/promises'
// The HOST address to use for the Nitro subprocess
const LOCAL_PORT = '39291'
let watchdog: ProcessWatchdog | undefined = undefined
/**
* Spawns a Nitro subprocess.
* @returns A promise that resolves when the Nitro subprocess is started.
*/
function run(systemInfo?: SystemInformation): Promise<any> {
log(`[CORTEX]:: Spawning cortex subprocess...`)
return new Promise<void>(async (resolve, reject) => {
let gpuVisibleDevices = systemInfo?.gpuSetting?.gpus_in_use.join(',') ?? ''
let binaryName = `cortex-server${process.platform === 'win32' ? '.exe' : ''}`
const binPath = path.join(__dirname, '..', 'bin')
await createEngineSymlinks(binPath)
const executablePath = path.join(binPath, binaryName)
const sharedPath = path.join(appResourcePath(), 'shared')
// Execute the binary
log(`[CORTEX]:: Spawn cortex at path: ${executablePath}`)
const dataFolderPath = getJanDataFolderPath()
if (watchdog) {
watchdog.terminate()
}
watchdog = new ProcessWatchdog(
executablePath,
[
'--start-server',
'--port',
LOCAL_PORT.toString(),
'--config_file_path',
`${path.join(dataFolderPath, '.janrc')}`,
'--data_folder_path',
dataFolderPath,
],
{
env: {
...process.env,
CUDA_VISIBLE_DEVICES: gpuVisibleDevices,
// Vulkan - Support 1 device at a time for now
...(gpuVisibleDevices?.length > 0 && {
GGML_VK_VISIBLE_DEVICES: gpuVisibleDevices,
}),
},
cwd: sharedPath,
}
)
watchdog.start()
resolve()
})
}
/**
* Create symlinks for the engine shared libraries
* @param binPath
*/
async function createEngineSymlinks(binPath: string) {
const sharedPath = path.join(appResourcePath(), 'shared')
const sharedLibFiles = await readdir(sharedPath)
for (const sharedLibFile of sharedLibFiles) {
if (sharedLibFile.endsWith('.dll') || sharedLibFile.endsWith('.so')) {
const targetDllPath = path.join(sharedPath, sharedLibFile)
const symlinkDllPath = path.join(binPath, sharedLibFile)
await symlink(targetDllPath, symlinkDllPath, 'file').catch(console.error)
console.log(`Symlink created: ${targetDllPath} -> ${symlinkDllPath}`)
}
}
}
/**
* Every module should have a dispose function
* This will be called when the extension is unloaded and should clean up any resources
* Also called when app is closed
*/
function dispose() {
watchdog?.terminate()
}
function addEnvPaths(dest: string) {
// Add engine path to the PATH and LD_LIBRARY_PATH
if (process.platform === 'win32') {
process.env.PATH = (process.env.PATH || '').concat(path.delimiter, dest)
} else {
process.env.LD_LIBRARY_PATH = (process.env.LD_LIBRARY_PATH || '').concat(
path.delimiter,
dest
)
}
}
/**
* Cortex process info
*/
export interface CortexProcessInfo {
isRunning: boolean
}
export default {
run,
dispose,
}