Skip to content

Commit

Permalink
feat: pre-populate Jan's /models folder (janhq#796)
Browse files Browse the repository at this point in the history
Signed-off-by: James <[email protected]>
Co-authored-by: James <[email protected]>
  • Loading branch information
namchuai and James authored Dec 1, 2023
1 parent e6812b1 commit 1bf4c1b
Show file tree
Hide file tree
Showing 49 changed files with 361 additions and 661 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dist
build
.DS_Store
electron/renderer
electron/models
package-lock.json

*.log
Expand Down
4 changes: 4 additions & 0 deletions core/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ const getUserSpace = (): Promise<string> => window.core.api?.getUserSpace();
const openFileExplorer: (path: string) => Promise<any> = (path) =>
window.core.api?.openFileExplorer(path);

const getResourcePath: () => Promise<string> = () =>
window.core.api?.getResourcePath();

/**
* Register extension point function type definition
*/
Expand All @@ -74,4 +77,5 @@ export {
appDataPath,
getUserSpace,
openFileExplorer,
getResourcePath,
};
4 changes: 2 additions & 2 deletions core/src/extensions/model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BaseExtension } from "../extension";
import { Model, ModelCatalog } from "../types/index";
import { Model } from "../types/index";

/**
* Model extension for managing models.
Expand Down Expand Up @@ -43,5 +43,5 @@ export abstract class ModelExtension extends BaseExtension {
* Gets a list of configured models.
* @returns A Promise that resolves with an array of configured models.
*/
abstract getConfiguredModels(): Promise<ModelCatalog[]>;
abstract getConfiguredModels(): Promise<Model[]>;
}
4 changes: 4 additions & 0 deletions core/src/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ const deleteFile: (path: string) => Promise<any> = (path) =>
const appendFile: (path: string, data: string) => Promise<any> = (path, data) =>
window.core.api?.appendFile(path, data);

const copyFile: (src: string, dest: string) => Promise<any> = (src, dest) =>
window.core.api?.copyFile(src, dest);

/**
* Reads a file line by line.
* @param {string} path - The path of the file to read.
Expand All @@ -80,4 +83,5 @@ export const fs = {
deleteFile,
appendFile,
readLineByLine,
copyFile,
};
79 changes: 20 additions & 59 deletions core/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ export interface Model {
/**
* The version of the model.
*/
version: string;
version: number;

/**
* The model download source. It can be an external url or a local filepath.
Expand All @@ -197,12 +197,6 @@ export interface Model {
*/
name: string;

/**
* The organization that owns the model (you!)
* Default: "you"
*/
owned_by: string;

/**
* The Unix timestamp (in seconds) for when the model was created
*/
Expand Down Expand Up @@ -236,11 +230,16 @@ export interface Model {
metadata: ModelMetadata;
}

export type ModelMetadata = {
author: string;
tags: string[];
size: number;
};

/**
* The Model transition states.
*/
export enum ModelState {
ToDownload = "to_download",
Downloading = "downloading",
Ready = "ready",
Running = "running",
Expand All @@ -250,65 +249,27 @@ export enum ModelState {
* The available model settings.
*/
export type ModelSettingParams = {
ctx_len: number;
ngl: number;
embedding: boolean;
n_parallel: number;
ctx_len?: number;
ngl?: number;
embedding?: boolean;
n_parallel?: number;
system_prompt?: string;
user_prompt?: string;
ai_prompt?: string;
};

/**
* The available model runtime parameters.
*/
export type ModelRuntimeParam = {
temperature: number;
token_limit: number;
top_k: number;
top_p: number;
stream: boolean;
temperature?: number;
token_limit?: number;
top_k?: number;
top_p?: number;
stream?: boolean;
max_tokens?: number;
};

/**
* The metadata of the model.
*/
export type ModelMetadata = {
engine: string;
quantization: string;
size: number;
binaries: string[];
maxRamRequired: number;
author: string;
avatarUrl: string;
};

/**
* Model type of the presentation object which will be presented to the user
* @data_transfer_object
*/
export interface ModelCatalog {
/** The unique id of the model.*/
id: string;
/** The name of the model.*/
name: string;
/** The avatar url of the model.*/
avatarUrl: string;
/** The short description of the model.*/
shortDescription: string;
/** The long description of the model.*/
longDescription: string;
/** The author name of the model.*/
author: string;
/** The version of the model.*/
version: string;
/** The origin url of the model repo.*/
modelUrl: string;
/** The timestamp indicating when this model was released.*/
releaseDate: number;
/** The tags attached to the model description **/
tags: string[];
/** The available versions of this model to download. */
availableVersions: Model[];
}

/**
* Assistant type defines the shape of an assistant object.
* @stored
Expand Down
8 changes: 4 additions & 4 deletions electron/handlers/app.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { app, ipcMain, shell } from 'electron'
import { ModuleManager } from '../managers/module'
import { ModuleManager } from './../managers/module'
import { join } from 'path'
import { ExtensionManager } from '../managers/extension'
import { WindowManager } from '../managers/window'
import { userSpacePath } from '../utils/path'
import { ExtensionManager } from './../managers/extension'
import { WindowManager } from './../managers/window'
import { userSpacePath } from './../utils/path'

export function handleAppIPCs() {
/**
Expand Down
11 changes: 8 additions & 3 deletions electron/handlers/download.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { app, ipcMain } from 'electron'
import { DownloadManager } from '../managers/download'
import { DownloadManager } from './../managers/download'
import { resolve, join } from 'path'
import { WindowManager } from '../managers/window'
import { WindowManager } from './../managers/window'
import request from 'request'
import { createWriteStream, unlink } from 'fs'
import { createWriteStream } from 'fs'
import { getResourcePath } from './../utils/path'
const progress = require('request-progress')

export function handleDownloaderIPCs() {
Expand Down Expand Up @@ -37,6 +38,10 @@ export function handleDownloaderIPCs() {
rq?.abort()
})

ipcMain.handle('getResourcePath', async (_event) => {
return getResourcePath()
})

/**
* Downloads a file from a given URL.
* @param _event - The IPC event object.
Expand Down
25 changes: 9 additions & 16 deletions electron/handlers/extension.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import { app, ipcMain, webContents } from 'electron'
import { readdirSync, rmdir, writeFileSync } from 'fs'
import { ModuleManager } from '../managers/module'
import { ipcMain, webContents } from 'electron'
import { readdirSync } from 'fs'
import { ModuleManager } from './../managers/module'
import { join, extname } from 'path'
import { ExtensionManager } from '../managers/extension'
import { WindowManager } from '../managers/window'
import { manifest, tarball } from 'pacote'
import {
getActiveExtensions,
getAllExtensions,
installExtensions,
} from '../extension/store'
import { getExtension } from '../extension/store'
import { removeExtension } from '../extension/store'
import Extension from '../extension/extension'
import { userSpacePath } from '../utils/path'
} from './../extension/store'
import { getExtension } from './../extension/store'
import { removeExtension } from './../extension/store'
import Extension from './../extension/extension'
import { getResourcePath, userSpacePath } from './../utils/path'

export function handleExtensionIPCs() {
/**MARK: General handlers */
Expand Down Expand Up @@ -48,11 +45,7 @@ export function handleExtensionIPCs() {
* @returns An array of paths to the base extensions.
*/
ipcMain.handle('extension:baseExtensions', async (_event) => {
const baseExtensionPath = join(
__dirname,
'../',
app.isPackaged ? '../../app.asar.unpacked/pre-install' : '../pre-install'
)
const baseExtensionPath = join(getResourcePath(), 'pre-install')
return readdirSync(baseExtensionPath)
.filter((file) => extname(file) === '.tgz')
.map((file) => join(baseExtensionPath, file))
Expand Down
11 changes: 9 additions & 2 deletions electron/handlers/fs.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { app, ipcMain } from 'electron'
import { ipcMain } from 'electron'
import * as fs from 'fs'
import fse from 'fs-extra'
import { join } from 'path'
import readline from 'readline'
import { userSpacePath } from '../utils/path'
import { userSpacePath } from './../utils/path'

/**
* Handles file system operations.
Expand Down Expand Up @@ -145,6 +146,12 @@ export function handleFsIPCs() {
}
})

ipcMain.handle('copyFile', async (_event, src: string, dest: string) => {
console.debug(`Copying file from ${src} to ${dest}`)

return fse.copySync(src, dest, { overwrite: false })
})

/**
* Reads a file line by line.
* @param event - The event object.
Expand Down
2 changes: 1 addition & 1 deletion electron/handlers/update.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { app, dialog } from "electron";
import { WindowManager } from "../managers/window";
import { WindowManager } from "./../managers/window";
import { autoUpdater } from "electron-updater";

export function handleAppUpdates() {
Expand Down
14 changes: 14 additions & 0 deletions electron/invokers/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,20 @@ export function fsInvokers() {
* @param {string} path - The path of the directory to remove.
*/
rmdir: (path: string) => ipcRenderer.invoke('rmdir', path),

/**
* Copies a file from the source path to the destination path.
* @param {string} src - The source path of the file to copy.
* @param {string} dest - The destination path where the file should be copied.
*/
copyFile: (src: string, dest: string) => ipcRenderer.invoke('copyFile', src, dest),

/**
* Retrieves the resource path.
* @returns {Promise<string>} A promise that resolves to the resource path.
*/
getResourcePath: () => ipcRenderer.invoke('getResourcePath'),

}

return interfaces
Expand Down
6 changes: 4 additions & 2 deletions electron/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { app, BrowserWindow } from 'electron'
import { join } from 'path'
import { setupMenu } from './utils/menu'
import { handleFsIPCs } from './handlers/fs'
import { createUserSpace, getResourcePath } from './utils/path'

/**
* Managers
Expand All @@ -18,9 +18,11 @@ import { handleThemesIPCs } from './handlers/theme'
import { handleExtensionIPCs } from './handlers/extension'
import { handleAppIPCs } from './handlers/app'
import { handleAppUpdates } from './handlers/update'
import { handleFsIPCs } from './handlers/fs'

app
.whenReady()
.then(createUserSpace)
.then(ExtensionManager.instance.migrateExtensions)
.then(ExtensionManager.instance.setupExtensions)
.then(setupMenu)
Expand Down Expand Up @@ -56,7 +58,7 @@ function createMainWindow() {
})

const startURL = app.isPackaged
? `file://${join(__dirname, '../renderer/index.html')}`
? `file://${join(__dirname, '..', 'renderer', 'index.html')}`
: 'http://localhost:3000'

/* Load frontend app to the window */
Expand Down
4 changes: 2 additions & 2 deletions electron/managers/extension.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { app } from 'electron'
import { init } from '../extension'
import { init } from './../extension'
import { join, resolve } from 'path'
import { rmdir } from 'fs'
import Store from 'electron-store'
import { existsSync, mkdirSync, writeFileSync } from 'fs'
import { userSpacePath } from '../utils/path'
import { userSpacePath } from './../utils/path'
/**
* Manages extension installation and migration.
*/
Expand Down
2 changes: 1 addition & 1 deletion electron/managers/module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { dispose } from "../utils/disposable";
import { dispose } from "./../utils/disposable";

/**
* Manages imported modules.
Expand Down
7 changes: 5 additions & 2 deletions electron/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
"renderer/**/*",
"build/*.{js,map}",
"build/**/*.{js,map}",
"pre-install"
"pre-install",
"models/**/*"
],
"asarUnpack": [
"pre-install"
"pre-install",
"models"
],
"publish": [
{
Expand Down Expand Up @@ -70,6 +72,7 @@
"@uiball/loaders": "^1.3.0",
"electron-store": "^8.1.0",
"electron-updater": "^6.1.4",
"fs-extra": "^11.2.0",
"pacote": "^17.0.4",
"request": "^2.88.2",
"request-progress": "^3.0.0",
Expand Down
15 changes: 15 additions & 0 deletions electron/utils/path.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
import { join } from 'path'
import { app } from 'electron'
import { mkdir } from 'fs-extra'

export async function createUserSpace(): Promise<void> {
return mkdir(userSpacePath).catch(() => {})
}

export const userSpacePath = join(app.getPath('home'), 'jan')

export function getResourcePath() {
let appPath = join(app.getAppPath(), '..', 'app.asar.unpacked')

if (!app.isPackaged) {
// for development mode
appPath = join(__dirname, '..', '..')
}
return appPath
}
Loading

0 comments on commit 1bf4c1b

Please sign in to comment.