Skip to content

Commit

Permalink
feat: allow user to move jan folder (janhq#1649)
Browse files Browse the repository at this point in the history
* feat: allow user to move jan folder

Signed-off-by: James <[email protected]>

---------

Signed-off-by: James <[email protected]>
Co-authored-by: James <[email protected]>
Co-authored-by: Louis <[email protected]>
  • Loading branch information
3 people authored Jan 22, 2024
1 parent a3f2a16 commit 4cf4777
Show file tree
Hide file tree
Showing 38 changed files with 445 additions and 175 deletions.
7 changes: 7 additions & 0 deletions core/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"semi": false,
"singleQuote": true,
"quoteProps": "consistent",
"trailingComma": "es5",
"endOfLine": "auto"
}
8 changes: 6 additions & 2 deletions core/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ export enum AppRoute {
openExternalUrl = 'openExternalUrl',
openAppDirectory = 'openAppDirectory',
openFileExplore = 'openFileExplorer',
selectDirectory = 'selectDirectory',
getAppConfigurations = 'getAppConfigurations',
updateAppConfiguration = 'updateAppConfiguration',
relaunch = 'relaunch',
joinPath = 'joinPath',
baseName = 'baseName',
startServer = 'startServer',
stopServer = 'stopServer',
log = 'log'
log = 'log',
logServer = 'logServer',
}

export enum AppEvent {
Expand Down Expand Up @@ -55,7 +59,7 @@ export enum FileSystemRoute {
}
export enum FileManagerRoute {
syncFile = 'syncFile',
getUserSpace = 'getUserSpace',
getJanDataFolderPath = 'getJanDataFolderPath',
getResourcePath = 'getResourcePath',
fileStat = 'fileStat',
}
Expand Down
11 changes: 6 additions & 5 deletions core/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ const abortDownload: (fileName: string) => Promise<any> = (fileName) =>
global.core.api?.abortDownload(fileName)

/**
* Gets the user space path.
* @returns {Promise<any>} A Promise that resolves with the user space path.
* Gets Jan's data folder path.
*
* @returns {Promise<string>} A Promise that resolves with Jan's data folder path.
*/
const getUserSpace = (): Promise<string> => global.core.api?.getUserSpace()
const getJanDataFolderPath = (): Promise<string> => global.core.api?.getJanDataFolderPath()

/**
* Opens the file explorer at a specific path.
Expand Down Expand Up @@ -103,12 +104,12 @@ export {
executeOnMain,
downloadFile,
abortDownload,
getUserSpace,
getJanDataFolderPath,
openFileExplorer,
getResourcePath,
joinPath,
openExternalUrl,
baseName,
log,
FileStat
FileStat,
}
34 changes: 17 additions & 17 deletions core/src/node/api/common/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ import fs from 'fs'
import { JanApiRouteConfiguration, RouteConfiguration } from './configuration'
import { join } from 'path'
import { ContentType, MessageStatus, Model, ThreadMessage } from './../../../index'

const os = require('os')

const path = join(os.homedir(), 'jan')
import { getJanDataFolderPath } from '../../utils'

export const getBuilder = async (configuration: RouteConfiguration) => {
const directoryPath = join(path, configuration.dirName)
const directoryPath = join(getJanDataFolderPath(), configuration.dirName)
try {
if (!fs.existsSync(directoryPath)) {
console.debug('model folder not found')
Expand Down Expand Up @@ -72,7 +69,7 @@ export const deleteBuilder = async (configuration: RouteConfiguration, id: strin
}
}

const directoryPath = join(path, configuration.dirName)
const directoryPath = join(getJanDataFolderPath(), configuration.dirName)
try {
const data = await retrieveBuilder(configuration, id)
if (!data) {
Expand All @@ -94,7 +91,7 @@ export const deleteBuilder = async (configuration: RouteConfiguration, id: strin
}

export const getMessages = async (threadId: string): Promise<ThreadMessage[]> => {
const threadDirPath = join(path, 'threads', threadId)
const threadDirPath = join(getJanDataFolderPath(), 'threads', threadId)
const messageFile = 'messages.jsonl'
try {
const files: string[] = fs.readdirSync(threadDirPath)
Expand Down Expand Up @@ -155,7 +152,7 @@ export const createThread = async (thread: any) => {
created: Date.now(),
updated: Date.now(),
}
const threadDirPath = join(path, 'threads', updatedThread.id)
const threadDirPath = join(getJanDataFolderPath(), 'threads', updatedThread.id)
const threadJsonPath = join(threadDirPath, threadMetadataFileName)

if (!fs.existsSync(threadDirPath)) {
Expand Down Expand Up @@ -189,7 +186,7 @@ export const updateThread = async (threadId: string, thread: any) => {
updated: Date.now(),
}
try {
const threadDirPath = join(path, 'threads', updatedThread.id)
const threadDirPath = join(getJanDataFolderPath(), 'threads', updatedThread.id)
const threadJsonPath = join(threadDirPath, threadMetadataFileName)

await fs.writeFileSync(threadJsonPath, JSON.stringify(updatedThread, null, 2))
Expand Down Expand Up @@ -231,7 +228,7 @@ export const createMessage = async (threadId: string, message: any) => {
],
}

const threadDirPath = join(path, 'threads', threadId)
const threadDirPath = join(getJanDataFolderPath(), 'threads', threadId)
const threadMessagePath = join(threadDirPath, threadMessagesFileName)

if (!fs.existsSync(threadDirPath)) {
Expand All @@ -246,17 +243,20 @@ export const createMessage = async (threadId: string, message: any) => {
}
}

export const downloadModel = async (modelId: string, network?: { proxy?: string, ignoreSSL?: boolean }) => {
const strictSSL = !network?.ignoreSSL;
const proxy = network?.proxy?.startsWith('http') ? network.proxy : undefined;
export const downloadModel = async (
modelId: string,
network?: { proxy?: string; ignoreSSL?: boolean }
) => {
const strictSSL = !network?.ignoreSSL
const proxy = network?.proxy?.startsWith('http') ? network.proxy : undefined
const model = await retrieveBuilder(JanApiRouteConfiguration.models, modelId)
if (!model || model.object !== 'model') {
return {
message: 'Model not found',
}
}

const directoryPath = join(path, 'models', modelId)
const directoryPath = join(getJanDataFolderPath(), 'models', modelId)
if (!fs.existsSync(directoryPath)) {
fs.mkdirSync(directoryPath)
}
Expand All @@ -265,7 +265,7 @@ export const downloadModel = async (modelId: string, network?: { proxy?: string,
const modelBinaryPath = join(directoryPath, modelId)

const request = require('request')
const rq = request({url: model.source_url, strictSSL, proxy })
const rq = request({ url: model.source_url, strictSSL, proxy })
const progress = require('request-progress')
progress(rq, {})
.on('progress', function (state: any) {
Expand Down Expand Up @@ -316,7 +316,7 @@ export const chatCompletions = async (request: any, reply: any) => {
reply.raw.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive',
'Connection': 'keep-alive',
})

const headers: Record<string, any> = {
Expand Down Expand Up @@ -347,7 +347,7 @@ const getEngineConfiguration = async (engineId: string) => {
if (engineId !== 'openai') {
return undefined
}
const directoryPath = join(path, 'engines')
const directoryPath = join(getJanDataFolderPath(), 'engines')
const filePath = join(directoryPath, `${engineId}.json`)
const data = await fs.readFileSync(filePath, 'utf-8')
return JSON.parse(data)
Expand Down
16 changes: 8 additions & 8 deletions core/src/node/api/routes/download.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { DownloadRoute } from "../../../api";
import { join } from "path";
import { userSpacePath } from "../../extension/manager";
import { DownloadManager } from "../../download";
import { HttpServer } from "../HttpServer";
import { createWriteStream } from "fs";
import { DownloadRoute } from '../../../api'
import { join } from 'path'
import { DownloadManager } from '../../download'
import { HttpServer } from '../HttpServer'
import { createWriteStream } from 'fs'
import { getJanDataFolderPath } from '../../utils'
import { normalizeFilePath } from "../../path";

export const downloadRouter = async (app: HttpServer) => {
Expand All @@ -13,7 +13,7 @@ export const downloadRouter = async (app: HttpServer) => {
const body = JSON.parse(req.body as any);
const normalizedArgs = body.map((arg: any) => {
if (typeof arg === "string") {
return join(userSpacePath, normalizeFilePath(arg));
return join(getJanDataFolderPath(), normalizeFilePath(arg));
}
return arg;
});
Expand Down Expand Up @@ -44,7 +44,7 @@ export const downloadRouter = async (app: HttpServer) => {
const body = JSON.parse(req.body as any);
const normalizedArgs = body.map((arg: any) => {
if (typeof arg === "string") {
return join(userSpacePath, normalizeFilePath(arg));
return join(getJanDataFolderPath(), normalizeFilePath(arg));
}
return arg;
});
Expand Down
10 changes: 5 additions & 5 deletions core/src/node/api/routes/extension.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { join, extname } from 'path'
import { ExtensionRoute } from '../../../api/index'
import { userSpacePath } from '../../extension/manager'
import { ModuleManager } from '../../module'
import { getActiveExtensions, installExtensions } from '../../extension/store'
import { HttpServer } from '../HttpServer'

import { readdirSync } from 'fs'
import { getJanExtensionsPath } from '../../utils'

export const extensionRouter = async (app: HttpServer) => {
// TODO: Share code between node projects
app.post(`/${ExtensionRoute.getActiveExtensions}`, async (req, res) => {
app.post(`/${ExtensionRoute.getActiveExtensions}`, async (_req, res) => {
const activeExtensions = await getActiveExtensions()
res.status(200).send(activeExtensions)
})

app.post(`/${ExtensionRoute.baseExtensions}`, async (req, res) => {
app.post(`/${ExtensionRoute.baseExtensions}`, async (_req, res) => {
const baseExtensionPath = join(__dirname, '..', '..', '..', 'pre-install')
const extensions = readdirSync(baseExtensionPath)
.filter((file) => extname(file) === '.tgz')
Expand All @@ -23,7 +23,7 @@ export const extensionRouter = async (app: HttpServer) => {
res.status(200).send(extensions)
})

app.post(`/${ExtensionRoute.installExtension}`, async (req, res) => {
app.post(`/${ExtensionRoute.installExtension}`, async (req) => {
const extensions = req.body as any
const installed = await installExtensions(JSON.parse(extensions)[0])
return JSON.parse(JSON.stringify(installed))
Expand All @@ -32,7 +32,7 @@ export const extensionRouter = async (app: HttpServer) => {
app.post(`/${ExtensionRoute.invokeExtensionFunc}`, async (req, res) => {
const args = JSON.parse(req.body as any)
console.debug(args)
const module = await import(join(userSpacePath, 'extensions', args[0]))
const module = await import(join(getJanExtensionsPath(), args[0]))

ModuleManager.instance.setModule(args[0], module)
const method = args[1]
Expand Down
2 changes: 1 addition & 1 deletion core/src/node/api/routes/fileManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { HttpServer } from '../../index'
export const fsRouter = async (app: HttpServer) => {
app.post(`/app/${FileManagerRoute.syncFile}`, async (request: any, reply: any) => {})

app.post(`/app/${FileManagerRoute.getUserSpace}`, async (request: any, reply: any) => {})
app.post(`/app/${FileManagerRoute.getJanDataFolderPath}`, async (request: any, reply: any) => {})

app.post(`/app/${FileManagerRoute.getResourcePath}`, async (request: any, reply: any) => {})

Expand Down
4 changes: 2 additions & 2 deletions core/src/node/api/routes/fs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FileSystemRoute } from '../../../api'
import { join } from 'path'
import { HttpServer } from '../HttpServer'
import { userSpacePath } from '../../extension/manager'
import { getJanDataFolderPath } from '../../utils'

export const fsRouter = async (app: HttpServer) => {
const moduleName = 'fs'
Expand All @@ -14,7 +14,7 @@ export const fsRouter = async (app: HttpServer) => {
return mdl[route](
...body.map((arg: any) =>
typeof arg === 'string' && arg.includes('file:/')
? join(userSpacePath, arg.replace('file:/', ''))
? join(getJanDataFolderPath(), arg.replace('file:/', ''))
: arg,
),
)
Expand Down
13 changes: 7 additions & 6 deletions core/src/node/extension/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export default class Extension {
const pacote = await import('pacote')
await pacote.extract(
this.specifier,
join(ExtensionManager.instance.extensionsPath ?? '', this.name ?? ''),
join(ExtensionManager.instance.getExtensionsPath() ?? '', this.name ?? ''),
this.installOptions,
)

Expand Down Expand Up @@ -166,9 +166,9 @@ export default class Extension {
* @returns the latest available version if a new version is available or false if not.
*/
async isUpdateAvailable() {
return import('pacote').then((pacote) => {
if (this.origin) {
return pacote.manifest(this.origin).then((mnf) => {
return import('pacote').then((pacote) => {
if (this.origin) {
return pacote.manifest(this.origin).then((mnf) => {
return mnf.version !== this.version ? mnf.version : false
})
}
Expand All @@ -179,8 +179,9 @@ export default class Extension {
* Remove extension and refresh renderers.
* @returns {Promise}
*/
async uninstall() {
const extPath = resolve(ExtensionManager.instance.extensionsPath ?? '', this.name ?? '')
async uninstall(): Promise<void> {
const path = ExtensionManager.instance.getExtensionsPath()
const extPath = resolve(path ?? '', this.name ?? '')
await rmdirSync(extPath, { recursive: true })

this.emitUpdate()
Expand Down
10 changes: 5 additions & 5 deletions core/src/node/extension/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@ async function registerExtensionProtocol() {
let electron: any = undefined

try {
const moduleName = "electron"
const moduleName = 'electron'
electron = await import(moduleName)
} catch (err) {
console.error('Electron is not available')
}

const extensionPath = ExtensionManager.instance.getExtensionsPath()
if (electron) {
return electron.protocol.registerFileProtocol('extension', (request: any, callback: any) => {
const entry = request.url.substr('extension://'.length - 1)

const url = normalize(ExtensionManager.instance.extensionsPath + entry)
const url = normalize(extensionPath + entry)
callback({ path: url })
})
}
Expand Down Expand Up @@ -120,7 +120,7 @@ function loadExtension(ext: any) {
* @returns {extensionManager} A set of functions used to manage the extension lifecycle.
*/
export function getStore() {
if (!ExtensionManager.instance.extensionsPath) {
if (!ExtensionManager.instance.getExtensionsFile()) {
throw new Error(
'The extension path has not yet been set up. Please run useExtensions before accessing the store',
)
Expand All @@ -133,4 +133,4 @@ export function getStore() {
getActiveExtensions,
removeExtension,
}
}
}
Loading

0 comments on commit 4cf4777

Please sign in to comment.