From ed5413a1eea38710f1608b2cd172c3ce28d31dca Mon Sep 17 00:00:00 2001 From: Linh Tran Date: Tue, 28 Nov 2023 00:18:36 +0700 Subject: [PATCH 01/42] Base server code (mirrored from electron + removed unnecessary handlers --- server/core/plugin/facade.ts | 30 +++++ server/core/plugin/globals.ts | 36 ++++++ server/core/plugin/index.ts | 149 +++++++++++++++++++++ server/core/plugin/plugin.ts | 213 +++++++++++++++++++++++++++++++ server/core/plugin/router.ts | 97 ++++++++++++++ server/core/plugin/store.ts | 131 +++++++++++++++++++ server/core/pre-install/.gitkeep | 0 server/handlers/download.ts | 108 ++++++++++++++++ server/handlers/fs.ts | 156 ++++++++++++++++++++++ server/handlers/plugin.ts | 118 +++++++++++++++++ server/icons/icon.png | Bin 0 -> 38651 bytes server/main.ts | 32 +++++ server/managers/download.ts | 24 ++++ server/managers/module.ts | 33 +++++ server/managers/plugin.ts | 60 +++++++++ server/managers/window.ts | 37 ++++++ server/package.json | 97 ++++++++++++++ server/tsconfig.json | 20 +++ server/utils/disposable.ts | 8 ++ server/utils/menu.ts | 111 ++++++++++++++++ server/utils/versionDiff.ts | 21 +++ 21 files changed, 1481 insertions(+) create mode 100644 server/core/plugin/facade.ts create mode 100644 server/core/plugin/globals.ts create mode 100644 server/core/plugin/index.ts create mode 100644 server/core/plugin/plugin.ts create mode 100644 server/core/plugin/router.ts create mode 100644 server/core/plugin/store.ts create mode 100644 server/core/pre-install/.gitkeep create mode 100644 server/handlers/download.ts create mode 100644 server/handlers/fs.ts create mode 100644 server/handlers/plugin.ts create mode 100644 server/icons/icon.png create mode 100644 server/main.ts create mode 100644 server/managers/download.ts create mode 100644 server/managers/module.ts create mode 100644 server/managers/plugin.ts create mode 100644 server/managers/window.ts create mode 100644 server/package.json create mode 100644 server/tsconfig.json create mode 100644 server/utils/disposable.ts create mode 100644 server/utils/menu.ts create mode 100644 server/utils/versionDiff.ts diff --git a/server/core/plugin/facade.ts b/server/core/plugin/facade.ts new file mode 100644 index 000000000..bd1089109 --- /dev/null +++ b/server/core/plugin/facade.ts @@ -0,0 +1,30 @@ +const { ipcRenderer, contextBridge } = require("electron"); + +export function useFacade() { + const interfaces = { + install(plugins: any[]) { + return ipcRenderer.invoke("pluggable:install", plugins); + }, + uninstall(plugins: any[], reload: boolean) { + return ipcRenderer.invoke("pluggable:uninstall", plugins, reload); + }, + getActive() { + return ipcRenderer.invoke("pluggable:getActivePlugins"); + }, + update(plugins: any[], reload: boolean) { + return ipcRenderer.invoke("pluggable:update", plugins, reload); + }, + updatesAvailable(plugin: any) { + return ipcRenderer.invoke("pluggable:updatesAvailable", plugin); + }, + toggleActive(plugin: any, active: boolean) { + return ipcRenderer.invoke("pluggable:togglePluginActive", plugin, active); + }, + }; + + if (contextBridge) { + contextBridge.exposeInMainWorld("pluggableElectronIpc", interfaces); + } + + return interfaces; +} diff --git a/server/core/plugin/globals.ts b/server/core/plugin/globals.ts new file mode 100644 index 000000000..69df7925c --- /dev/null +++ b/server/core/plugin/globals.ts @@ -0,0 +1,36 @@ +import { existsSync, mkdirSync, writeFileSync } from "fs"; +import { join, resolve } from "path"; + +export let pluginsPath: string | undefined = undefined; + +/** + * @private + * Set path to plugins directory and create the directory if it does not exist. + * @param {string} plgPath path to plugins directory + */ +export function setPluginsPath(plgPath: string) { + // Create folder if it does not exist + let plgDir; + try { + plgDir = resolve(plgPath); + if (plgDir.length < 2) throw new Error(); + + if (!existsSync(plgDir)) mkdirSync(plgDir); + + const pluginsJson = join(plgDir, "plugins.json"); + if (!existsSync(pluginsJson)) writeFileSync(pluginsJson, "{}", "utf8"); + + pluginsPath = plgDir; + } catch (error) { + throw new Error("Invalid path provided to the plugins folder"); + } +} + +/** + * @private + * Get the path to the plugins.json file. + * @returns location of plugins.json + */ +export function getPluginsFile() { + return join(pluginsPath ?? "", "plugins.json"); +} \ No newline at end of file diff --git a/server/core/plugin/index.ts b/server/core/plugin/index.ts new file mode 100644 index 000000000..e8c64747b --- /dev/null +++ b/server/core/plugin/index.ts @@ -0,0 +1,149 @@ +import { readFileSync } from "fs"; +import { protocol } from "electron"; +import { normalize } from "path"; + +import Plugin from "./plugin"; +import { + getAllPlugins, + removePlugin, + persistPlugins, + installPlugins, + getPlugin, + getActivePlugins, + addPlugin, +} from "./store"; +import { + pluginsPath as storedPluginsPath, + setPluginsPath, + getPluginsFile, +} from "./globals"; +import router from "./router"; + +/** + * Sets up the required communication between the main and renderer processes. + * Additionally sets the plugins up using {@link usePlugins} if a pluginsPath is provided. + * @param {Object} options configuration for setting up the renderer facade. + * @param {confirmInstall} [options.confirmInstall] Function to validate that a plugin should be installed. + * @param {Boolean} [options.useFacade=true] Whether to make a facade to the plugins available in the renderer. + * @param {string} [options.pluginsPath] Optional path to the plugins folder. + * @returns {pluginManager|Object} A set of functions used to manage the plugin lifecycle if usePlugins is provided. + * @function + */ +export function init(options: any) { + if ( + !Object.prototype.hasOwnProperty.call(options, "useFacade") || + options.useFacade + ) { + // Enable IPC to be used by the facade + router(); + } + + // Create plugins protocol to serve plugins to renderer + registerPluginProtocol(); + + // perform full setup if pluginsPath is provided + if (options.pluginsPath) { + return usePlugins(options.pluginsPath); + } + + return {}; +} + +/** + * Create plugins protocol to provide plugins to renderer + * @private + * @returns {boolean} Whether the protocol registration was successful + */ +function registerPluginProtocol() { + return protocol.registerFileProtocol("plugin", (request, callback) => { + const entry = request.url.substr(8); + const url = normalize(storedPluginsPath + entry); + callback({ path: url }); + }); +} + +/** + * Set Pluggable Electron up to run from the pluginPath folder if it is provided and + * load plugins persisted in that folder. + * @param {string} pluginsPath Path to the plugins folder. Required if not yet set up. + * @returns {pluginManager} A set of functions used to manage the plugin lifecycle. + */ +export function usePlugins(pluginsPath: string) { + if (!pluginsPath) + throw Error( + "A path to the plugins folder is required to use Pluggable Electron" + ); + // Store the path to the plugins folder + setPluginsPath(pluginsPath); + + // Remove any registered plugins + for (const plugin of getAllPlugins()) { + if (plugin.name) removePlugin(plugin.name, false); + } + + // Read plugin list from plugins folder + const plugins = JSON.parse(readFileSync(getPluginsFile(), "utf-8")); + try { + // Create and store a Plugin instance for each plugin in list + for (const p in plugins) { + loadPlugin(plugins[p]); + } + persistPlugins(); + } catch (error) { + // Throw meaningful error if plugin loading fails + throw new Error( + "Could not successfully rebuild list of installed plugins.\n" + + error + + "\nPlease check the plugins.json file in the plugins folder." + ); + } + + // Return the plugin lifecycle functions + return getStore(); +} + +/** + * Check the given plugin object. If it is marked for uninstalling, the plugin files are removed. + * Otherwise a Plugin instance for the provided object is created and added to the store. + * @private + * @param {Object} plg Plugin info + */ +function loadPlugin(plg: any) { + // Create new plugin, populate it with plg details and save it to the store + const plugin = new Plugin(); + + for (const key in plg) { + if (Object.prototype.hasOwnProperty.call(plg, key)) { + // Use Object.defineProperty to set the properties as writable + Object.defineProperty(plugin, key, { + value: plg[key], + writable: true, + enumerable: true, + configurable: true, + }); + } + } + + addPlugin(plugin, false); + plugin.subscribe("pe-persist", persistPlugins); +} + +/** + * Returns the publicly available store functions. + * @returns {pluginManager} A set of functions used to manage the plugin lifecycle. + */ +export function getStore() { + if (!storedPluginsPath) { + throw new Error( + "The plugin path has not yet been set up. Please run usePlugins before accessing the store" + ); + } + + return { + installPlugins, + getPlugin, + getAllPlugins, + getActivePlugins, + removePlugin, + }; +} diff --git a/server/core/plugin/plugin.ts b/server/core/plugin/plugin.ts new file mode 100644 index 000000000..f0fc073d7 --- /dev/null +++ b/server/core/plugin/plugin.ts @@ -0,0 +1,213 @@ +import { rmdir } from "fs/promises"; +import { resolve, join } from "path"; +import { manifest, extract } from "pacote"; +import * as Arborist from "@npmcli/arborist"; + +import { pluginsPath } from "./globals"; + +/** + * An NPM package that can be used as a Pluggable Electron plugin. + * Used to hold all the information and functions necessary to handle the plugin lifecycle. + */ +class Plugin { + /** + * @property {string} origin Original specification provided to fetch the package. + * @property {Object} installOptions Options provided to pacote when fetching the manifest. + * @property {name} name The name of the plugin as defined in the manifest. + * @property {string} url Electron URL where the package can be accessed. + * @property {string} version Version of the package as defined in the manifest. + * @property {Array} activationPoints List of {@link ./Execution-API#activationPoints|activation points}. + * @property {string} main The entry point as defined in the main entry of the manifest. + * @property {string} description The description of plugin as defined in the manifest. + * @property {string} icon The icon of plugin as defined in the manifest. + */ + origin?: string; + installOptions: any; + name?: string; + url?: string; + version?: string; + activationPoints?: Array; + main?: string; + description?: string; + icon?: string; + + /** @private */ + _active = false; + + /** + * @private + * @property {Object.} #listeners A list of callbacks to be executed when the Plugin is updated. + */ + listeners: Record void> = {}; + + /** + * Set installOptions with defaults for options that have not been provided. + * @param {string} [origin] Original specification provided to fetch the package. + * @param {Object} [options] Options provided to pacote when fetching the manifest. + */ + constructor(origin?: string, options = {}) { + const defaultOpts = { + version: false, + fullMetadata: false, + Arborist, + }; + + this.origin = origin; + this.installOptions = { ...defaultOpts, ...options }; + } + + /** + * Package name with version number. + * @type {string} + */ + get specifier() { + return ( + this.origin + + (this.installOptions.version ? "@" + this.installOptions.version : "") + ); + } + + /** + * Whether the plugin should be registered with its activation points. + * @type {boolean} + */ + get active() { + return this._active; + } + + /** + * Set Package details based on it's manifest + * @returns {Promise.} Resolves to true when the action completed + */ + async getManifest() { + // Get the package's manifest (package.json object) + try { + const mnf = await manifest(this.specifier, this.installOptions); + + // set the Package properties based on the it's manifest + this.name = mnf.name; + this.version = mnf.version; + this.activationPoints = mnf.activationPoints + ? (mnf.activationPoints as string[]) + : undefined; + this.main = mnf.main; + this.description = mnf.description; + this.icon = mnf.icon as any; + } catch (error) { + throw new Error( + `Package ${this.origin} does not contain a valid manifest: ${error}` + ); + } + + return true; + } + + /** + * Extract plugin to plugins folder. + * @returns {Promise.} This plugin + * @private + */ + async _install() { + try { + // import the manifest details + await this.getManifest(); + + // Install the package in a child folder of the given folder + await extract( + this.specifier, + join(pluginsPath ?? "", this.name ?? ""), + this.installOptions + ); + + if (!Array.isArray(this.activationPoints)) + throw new Error("The plugin does not contain any activation points"); + + // Set the url using the custom plugins protocol + this.url = `plugin://${this.name}/${this.main}`; + + this.emitUpdate(); + } catch (err) { + // Ensure the plugin is not stored and the folder is removed if the installation fails + this.setActive(false); + throw err; + } + + return [this]; + } + + /** + * Subscribe to updates of this plugin + * @param {string} name name of the callback to register + * @param {callback} cb The function to execute on update + */ + subscribe(name: string, cb: () => void) { + this.listeners[name] = cb; + } + + /** + * Remove subscription + * @param {string} name name of the callback to remove + */ + unsubscribe(name: string) { + delete this.listeners[name]; + } + + /** + * Execute listeners + */ + emitUpdate() { + for (const cb in this.listeners) { + this.listeners[cb].call(null, this); + } + } + + /** + * Check for updates and install if available. + * @param {string} version The version to update to. + * @returns {boolean} Whether an update was performed. + */ + async update(version = false) { + if (await this.isUpdateAvailable()) { + this.installOptions.version = version; + await this._install(); + return true; + } + + return false; + } + + /** + * Check if a new version of the plugin is available at the origin. + * @returns the latest available version if a new version is available or false if not. + */ + async isUpdateAvailable() { + if (this.origin) { + const mnf = await manifest(this.origin); + return mnf.version !== this.version ? mnf.version : false; + } + } + + /** + * Remove plugin and refresh renderers. + * @returns {Promise} + */ + async uninstall() { + const plgPath = resolve(pluginsPath ?? "", this.name ?? ""); + await rmdir(plgPath, { recursive: true }); + + this.emitUpdate(); + } + + /** + * Set a plugin's active state. This determines if a plugin should be loaded on initialisation. + * @param {boolean} active State to set _active to + * @returns {Plugin} This plugin + */ + setActive(active: boolean) { + this._active = active; + this.emitUpdate(); + return this; + } +} + +export default Plugin; diff --git a/server/core/plugin/router.ts b/server/core/plugin/router.ts new file mode 100644 index 000000000..09c79485b --- /dev/null +++ b/server/core/plugin/router.ts @@ -0,0 +1,97 @@ +import { ipcMain, webContents } from "electron"; + +import { + getPlugin, + getActivePlugins, + installPlugins, + removePlugin, + getAllPlugins, +} from "./store"; +import { pluginsPath } from "./globals"; +import Plugin from "./plugin"; + +// Throw an error if pluginsPath has not yet been provided by usePlugins. +const checkPluginsPath = () => { + if (!pluginsPath) + throw Error("Path to plugins folder has not yet been set up."); +}; +let active = false; +/** + * Provide the renderer process access to the plugins. + **/ +export default function () { + if (active) return; + // Register IPC route to install a plugin + ipcMain.handle("pluggable:install", async (e, plugins) => { + checkPluginsPath(); + + // Install and activate all provided plugins + const installed = await installPlugins(plugins); + return JSON.parse(JSON.stringify(installed)); + }); + + // Register IPC route to uninstall a plugin + ipcMain.handle("pluggable:uninstall", async (e, plugins, reload) => { + checkPluginsPath(); + + // Uninstall all provided plugins + for (const plg of plugins) { + const plugin = getPlugin(plg); + await plugin.uninstall(); + if (plugin.name) removePlugin(plugin.name); + } + + // Reload all renderer pages if needed + reload && webContents.getAllWebContents().forEach((wc) => wc.reload()); + return true; + }); + + // Register IPC route to update a plugin + ipcMain.handle("pluggable:update", async (e, plugins, reload) => { + checkPluginsPath(); + + // Update all provided plugins + const updated: Plugin[] = []; + for (const plg of plugins) { + const plugin = getPlugin(plg); + const res = await plugin.update(); + if (res) updated.push(plugin); + } + + // Reload all renderer pages if needed + if (updated.length && reload) + webContents.getAllWebContents().forEach((wc) => wc.reload()); + + return JSON.parse(JSON.stringify(updated)); + }); + + // Register IPC route to check if updates are available for a plugin + ipcMain.handle("pluggable:updatesAvailable", (e, names) => { + checkPluginsPath(); + + const plugins = names + ? names.map((name: string) => getPlugin(name)) + : getAllPlugins(); + + const updates: Record = {}; + for (const plugin of plugins) { + updates[plugin.name] = plugin.isUpdateAvailable(); + } + return updates; + }); + + // Register IPC route to get the list of active plugins + ipcMain.handle("pluggable:getActivePlugins", () => { + checkPluginsPath(); + return JSON.parse(JSON.stringify(getActivePlugins())); + }); + + // Register IPC route to toggle the active state of a plugin + ipcMain.handle("pluggable:togglePluginActive", (e, plg, active) => { + checkPluginsPath(); + const plugin = getPlugin(plg); + return JSON.parse(JSON.stringify(plugin.setActive(active))); + }); + + active = true; +} diff --git a/server/core/plugin/store.ts b/server/core/plugin/store.ts new file mode 100644 index 000000000..cfd25e5ca --- /dev/null +++ b/server/core/plugin/store.ts @@ -0,0 +1,131 @@ +/** + * Provides access to the plugins stored by Pluggable Electron + * @typedef {Object} pluginManager + * @prop {getPlugin} getPlugin + * @prop {getAllPlugins} getAllPlugins + * @prop {getActivePlugins} getActivePlugins + * @prop {installPlugins} installPlugins + * @prop {removePlugin} removePlugin + */ + +import { writeFileSync } from "fs"; +import Plugin from "./plugin"; +import { getPluginsFile } from "./globals"; + +/** + * @module store + * @private + */ + +/** + * Register of installed plugins + * @type {Object.} plugin - List of installed plugins + */ +const plugins: Record = {}; + +/** + * Get a plugin from the stored plugins. + * @param {string} name Name of the plugin to retrieve + * @returns {Plugin} Retrieved plugin + * @alias pluginManager.getPlugin + */ +export function getPlugin(name: string) { + if (!Object.prototype.hasOwnProperty.call(plugins, name)) { + throw new Error(`Plugin ${name} does not exist`); + } + + return plugins[name]; +} + +/** + * Get list of all plugin objects. + * @returns {Array.} All plugin objects + * @alias pluginManager.getAllPlugins + */ +export function getAllPlugins() { + return Object.values(plugins); +} + +/** + * Get list of active plugin objects. + * @returns {Array.} Active plugin objects + * @alias pluginManager.getActivePlugins + */ +export function getActivePlugins() { + return Object.values(plugins).filter((plugin) => plugin.active); +} + +/** + * Remove plugin from store and maybe save stored plugins to file + * @param {string} name Name of the plugin to remove + * @param {boolean} persist Whether to save the changes to plugins to file + * @returns {boolean} Whether the delete was successful + * @alias pluginManager.removePlugin + */ +export function removePlugin(name: string, persist = true) { + const del = delete plugins[name]; + if (persist) persistPlugins(); + return del; +} + +/** + * Add plugin to store and maybe save stored plugins to file + * @param {Plugin} plugin Plugin to add to store + * @param {boolean} persist Whether to save the changes to plugins to file + * @returns {void} + */ +export function addPlugin(plugin: Plugin, persist = true) { + if (plugin.name) plugins[plugin.name] = plugin; + if (persist) { + persistPlugins(); + plugin.subscribe("pe-persist", persistPlugins); + } +} + +/** + * Save stored plugins to file + * @returns {void} + */ +export function persistPlugins() { + const persistData: Record = {}; + for (const name in plugins) { + persistData[name] = plugins[name]; + } + writeFileSync(getPluginsFile(), JSON.stringify(persistData), "utf8"); +} + +/** + * Create and install a new plugin for the given specifier. + * @param {Array.} plugins A list of NPM specifiers, or installation configuration objects. + * @param {boolean} [store=true] Whether to store the installed plugins in the store + * @returns {Promise.>} New plugin + * @alias pluginManager.installPlugins + */ +export async function installPlugins(plugins: any, store = true) { + const installed: Plugin[] = []; + for (const plg of plugins) { + // Set install options and activation based on input type + const isObject = typeof plg === "object"; + const spec = isObject ? [plg.specifier, plg] : [plg]; + const activate = isObject ? plg.activate !== false : true; + + // Install and possibly activate plugin + const plugin = new Plugin(...spec); + await plugin._install(); + if (activate) plugin.setActive(true); + + // Add plugin to store if needed + if (store) addPlugin(plugin); + installed.push(plugin); + } + + // Return list of all installed plugins + return installed; +} + +/** + * @typedef {Object.} installOptions The {@link https://www.npmjs.com/package/pacote|pacote} + * options used to install the plugin with some extra options. + * @param {string} specifier the NPM specifier that identifies the package. + * @param {boolean} [activate] Whether this plugin should be activated after installation. Defaults to true. + */ diff --git a/server/core/pre-install/.gitkeep b/server/core/pre-install/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/server/handlers/download.ts b/server/handlers/download.ts new file mode 100644 index 000000000..3a1fc36d1 --- /dev/null +++ b/server/handlers/download.ts @@ -0,0 +1,108 @@ +import { app, ipcMain } from 'electron' +import { DownloadManager } from '../managers/download' +import { resolve, join } from 'path' +import { WindowManager } from '../managers/window' +import request from 'request' +import { createWriteStream, unlink } from 'fs' +const progress = require('request-progress') + +export function handleDownloaderIPCs() { + /** + * Handles the "pauseDownload" IPC message by pausing the download associated with the provided fileName. + * @param _event - The IPC event object. + * @param fileName - The name of the file being downloaded. + */ + ipcMain.handle('pauseDownload', async (_event, fileName) => { + DownloadManager.instance.networkRequests[fileName]?.pause() + }) + + /** + * Handles the "resumeDownload" IPC message by resuming the download associated with the provided fileName. + * @param _event - The IPC event object. + * @param fileName - The name of the file being downloaded. + */ + ipcMain.handle('resumeDownload', async (_event, fileName) => { + DownloadManager.instance.networkRequests[fileName]?.resume() + }) + + /** + * Handles the "abortDownload" IPC message by aborting the download associated with the provided fileName. + * The network request associated with the fileName is then removed from the networkRequests object. + * @param _event - The IPC event object. + * @param fileName - The name of the file being downloaded. + */ + ipcMain.handle('abortDownload', async (_event, fileName) => { + const rq = DownloadManager.instance.networkRequests[fileName] + DownloadManager.instance.networkRequests[fileName] = undefined + const userDataPath = app.getPath('userData') + const fullPath = join(userDataPath, fileName) + rq?.abort() + let result = 'NULL' + unlink(fullPath, function (err) { + if (err && err.code == 'ENOENT') { + result = `File not exist: ${err}` + } else if (err) { + result = `File delete error: ${err}` + } else { + result = 'File deleted successfully' + } + console.debug( + `Delete file ${fileName} from ${fullPath} result: ${result}` + ) + }) + }) + + /** + * Downloads a file from a given URL. + * @param _event - The IPC event object. + * @param url - The URL to download the file from. + * @param fileName - The name to give the downloaded file. + */ + ipcMain.handle('downloadFile', async (_event, url, fileName) => { + const userDataPath = join(app.getPath('home'), 'jan') + const destination = resolve(userDataPath, fileName) + const rq = request(url) + + progress(rq, {}) + .on('progress', function (state: any) { + WindowManager?.instance.currentWindow?.webContents.send( + 'FILE_DOWNLOAD_UPDATE', + { + ...state, + fileName, + } + ) + }) + .on('error', function (err: Error) { + WindowManager?.instance.currentWindow?.webContents.send( + 'FILE_DOWNLOAD_ERROR', + { + fileName, + err, + } + ) + }) + .on('end', function () { + if (DownloadManager.instance.networkRequests[fileName]) { + WindowManager?.instance.currentWindow?.webContents.send( + 'FILE_DOWNLOAD_COMPLETE', + { + fileName, + } + ) + DownloadManager.instance.setRequest(fileName, undefined) + } else { + WindowManager?.instance.currentWindow?.webContents.send( + 'FILE_DOWNLOAD_ERROR', + { + fileName, + err: 'Download cancelled', + } + ) + } + }) + .pipe(createWriteStream(destination)) + + DownloadManager.instance.setRequest(fileName, rq) + }) +} diff --git a/server/handlers/fs.ts b/server/handlers/fs.ts new file mode 100644 index 000000000..c1e8a85e4 --- /dev/null +++ b/server/handlers/fs.ts @@ -0,0 +1,156 @@ +import { app, ipcMain } from 'electron' +import * as fs from 'fs' +import { join } from 'path' + +/** + * Handles file system operations. + */ +export function handleFsIPCs() { + const userSpacePath = join(app.getPath('home'), 'jan') + + /** + * Gets the path to the user data directory. + * @param event - The event object. + * @returns A promise that resolves with the path to the user data directory. + */ + ipcMain.handle( + 'getUserSpace', + (): Promise => Promise.resolve(userSpacePath) + ) + + /** + * Checks whether the path is a directory. + * @param event - The event object. + * @param path - The path to check. + * @returns A promise that resolves with a boolean indicating whether the path is a directory. + */ + ipcMain.handle('isDirectory', (_event, path: string): Promise => { + const fullPath = join(userSpacePath, path) + return Promise.resolve( + fs.existsSync(fullPath) && fs.lstatSync(fullPath).isDirectory() + ) + }) + + /** + * Reads a file from the user data directory. + * @param event - The event object. + * @param path - The path of the file to read. + * @returns A promise that resolves with the contents of the file. + */ + ipcMain.handle('readFile', async (event, path: string): Promise => { + return new Promise((resolve, reject) => { + fs.readFile(join(userSpacePath, path), 'utf8', (err, data) => { + if (err) { + reject(err) + } else { + resolve(data) + } + }) + }) + }) + + /** + * Writes data to a file in the user data directory. + * @param event - The event object. + * @param path - The path of the file to write to. + * @param data - The data to write to the file. + * @returns A promise that resolves when the file has been written. + */ + ipcMain.handle( + 'writeFile', + async (event, path: string, data: string): Promise => { + return new Promise((resolve, reject) => { + fs.writeFile(join(userSpacePath, path), data, 'utf8', (err) => { + if (err) { + reject(err) + } else { + resolve() + } + }) + }) + } + ) + + /** + * Creates a directory in the user data directory. + * @param event - The event object. + * @param path - The path of the directory to create. + * @returns A promise that resolves when the directory has been created. + */ + ipcMain.handle('mkdir', async (event, path: string): Promise => { + return new Promise((resolve, reject) => { + fs.mkdir(join(userSpacePath, path), { recursive: true }, (err) => { + if (err) { + reject(err) + } else { + resolve() + } + }) + }) + }) + + /** + * Removes a directory in the user data directory. + * @param event - The event object. + * @param path - The path of the directory to remove. + * @returns A promise that resolves when the directory is removed successfully. + */ + ipcMain.handle('rmdir', async (event, path: string): Promise => { + return new Promise((resolve, reject) => { + fs.rmdir(join(userSpacePath, path), { recursive: true }, (err) => { + if (err) { + reject(err) + } else { + resolve() + } + }) + }) + }) + + /** + * Lists the files in a directory in the user data directory. + * @param event - The event object. + * @param path - The path of the directory to list files from. + * @returns A promise that resolves with an array of file names. + */ + ipcMain.handle( + 'listFiles', + async (event, path: string): Promise => { + return new Promise((resolve, reject) => { + fs.readdir(join(userSpacePath, path), (err, files) => { + if (err) { + reject(err) + } else { + resolve(files) + } + }) + }) + } + ) + + /** + * Deletes a file from the user data folder. + * @param _event - The IPC event object. + * @param filePath - The path to the file to delete. + * @returns A string indicating the result of the operation. + */ + ipcMain.handle('deleteFile', async (_event, filePath) => { + const fullPath = join(userSpacePath, filePath) + + let result = 'NULL' + fs.unlink(fullPath, function (err) { + if (err && err.code == 'ENOENT') { + result = `File not exist: ${err}` + } else if (err) { + result = `File delete error: ${err}` + } else { + result = 'File deleted successfully' + } + console.debug( + `Delete file ${filePath} from ${fullPath} result: ${result}` + ) + }) + + return result + }) +} diff --git a/server/handlers/plugin.ts b/server/handlers/plugin.ts new file mode 100644 index 000000000..22bf253e6 --- /dev/null +++ b/server/handlers/plugin.ts @@ -0,0 +1,118 @@ +import { app, ipcMain } from "electron"; +import { readdirSync, rmdir, writeFileSync } from "fs"; +import { ModuleManager } from "../managers/module"; +import { join, extname } from "path"; +import { PluginManager } from "../managers/plugin"; +import { WindowManager } from "../managers/window"; +import { manifest, tarball } from "pacote"; + +export function handlePluginIPCs() { + /** + * Invokes a function from a plugin module in main node process. + * @param _event - The IPC event object. + * @param modulePath - The path to the plugin module. + * @param method - The name of the function to invoke. + * @param args - The arguments to pass to the function. + * @returns The result of the invoked function. + */ + ipcMain.handle( + "invokePluginFunc", + async (_event, modulePath, method, ...args) => { + const module = require( + /* webpackIgnore: true */ join( + app.getPath("userData"), + "plugins", + modulePath + ) + ); + ModuleManager.instance.setModule(modulePath, module); + + if (typeof module[method] === "function") { + return module[method](...args); + } else { + console.debug(module[method]); + console.error(`Function "${method}" does not exist in the module.`); + } + } + ); + + /** + * Returns the paths of the base plugins. + * @param _event - The IPC event object. + * @returns An array of paths to the base plugins. + */ + ipcMain.handle("basePlugins", async (_event) => { + const basePluginPath = join( + __dirname, + "../", + app.isPackaged + ? "../../app.asar.unpacked/core/pre-install" + : "../core/pre-install" + ); + return readdirSync(basePluginPath) + .filter((file) => extname(file) === ".tgz") + .map((file) => join(basePluginPath, file)); + }); + + /** + * Returns the path to the user's plugin directory. + * @param _event - The IPC event object. + * @returns The path to the user's plugin directory. + */ + ipcMain.handle("pluginPath", async (_event) => { + return join(app.getPath("userData"), "plugins"); + }); + + /** + * Deletes the `plugins` directory in the user data path and disposes of required modules. + * If the app is packaged, the function relaunches the app and exits. + * Otherwise, the function deletes the cached modules and sets up the plugins and reloads the main window. + * @param _event - The IPC event object. + * @param url - The URL to reload. + */ + ipcMain.handle("reloadPlugins", async (_event, url) => { + const userDataPath = app.getPath("userData"); + const fullPath = join(userDataPath, "plugins"); + + rmdir(fullPath, { recursive: true }, function (err) { + if (err) console.error(err); + ModuleManager.instance.clearImportedModules(); + + // just relaunch if packaged, should launch manually in development mode + if (app.isPackaged) { + app.relaunch(); + app.exit(); + } else { + for (const modulePath in ModuleManager.instance.requiredModules) { + delete require.cache[ + require.resolve( + join(app.getPath("userData"), "plugins", modulePath) + ) + ]; + } + PluginManager.instance.setupPlugins(); + WindowManager.instance.currentWindow?.reload(); + } + }); + }); + + /** + * Installs a remote plugin by downloading its tarball and writing it to a tgz file. + * @param _event - The IPC event object. + * @param pluginName - The name of the remote plugin to install. + * @returns A Promise that resolves to the path of the installed plugin file. + */ + ipcMain.handle("installRemotePlugin", async (_event, pluginName) => { + const destination = join( + app.getPath("userData"), + pluginName.replace(/^@.*\//, "") + ".tgz" + ); + return manifest(pluginName) + .then(async (manifest: any) => { + await tarball(manifest._resolved).then((data: Buffer) => { + writeFileSync(destination, data); + }); + }) + .then(() => destination); + }); +} diff --git a/server/icons/icon.png b/server/icons/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..289f99ded85e1e3cc91b17af6b607d2cafd97cd7 GIT binary patch literal 38651 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 + PluginManager.instance.migratePlugins() + PluginManager.instance.setupPlugins() + setupMenu() + handleIPCs() +}) + +/** + * Handles various IPC messages from the renderer process. + */ +function handleIPCs() { + handleFsIPCs() + handleDownloaderIPCs() + handlePluginIPCs() +} diff --git a/server/managers/download.ts b/server/managers/download.ts new file mode 100644 index 000000000..08c089b74 --- /dev/null +++ b/server/managers/download.ts @@ -0,0 +1,24 @@ +import { Request } from "request"; + +/** + * Manages file downloads and network requests. + */ +export class DownloadManager { + public networkRequests: Record = {}; + + public static instance: DownloadManager = new DownloadManager(); + + constructor() { + if (DownloadManager.instance) { + return DownloadManager.instance; + } + } + /** + * Sets a network request for a specific file. + * @param {string} fileName - The name of the file. + * @param {Request | undefined} request - The network request to set, or undefined to clear the request. + */ + setRequest(fileName: string, request: Request | undefined) { + this.networkRequests[fileName] = request; + } +} diff --git a/server/managers/module.ts b/server/managers/module.ts new file mode 100644 index 000000000..43dda0fb6 --- /dev/null +++ b/server/managers/module.ts @@ -0,0 +1,33 @@ +import { dispose } from "../utils/disposable"; + +/** + * Manages imported modules. + */ +export class ModuleManager { + public requiredModules: Record = {}; + + public static instance: ModuleManager = new ModuleManager(); + + constructor() { + if (ModuleManager.instance) { + return ModuleManager.instance; + } + } + + /** + * Sets a module. + * @param {string} moduleName - The name of the module. + * @param {any | undefined} nodule - The module to set, or undefined to clear the module. + */ + setModule(moduleName: string, nodule: any | undefined) { + this.requiredModules[moduleName] = nodule; + } + + /** + * Clears all imported modules. + */ + clearImportedModules() { + dispose(this.requiredModules); + this.requiredModules = {}; + } +} diff --git a/server/managers/plugin.ts b/server/managers/plugin.ts new file mode 100644 index 000000000..227eab34e --- /dev/null +++ b/server/managers/plugin.ts @@ -0,0 +1,60 @@ +import { app } from "electron"; +import { init } from "../core/plugin/index"; +import { join } from "path"; +import { rmdir } from "fs"; +import Store from "electron-store"; + +/** + * Manages plugin installation and migration. + */ +export class PluginManager { + public static instance: PluginManager = new PluginManager(); + + constructor() { + if (PluginManager.instance) { + return PluginManager.instance; + } + } + + /** + * Sets up the plugins by initializing the `plugins` module with the `confirmInstall` and `pluginsPath` options. + * The `confirmInstall` function always returns `true` to allow plugin installation. + * The `pluginsPath` option specifies the path to install plugins to. + */ + setupPlugins() { + init({ + // Function to check from the main process that user wants to install a plugin + confirmInstall: async (_plugins: string[]) => { + return true; + }, + // Path to install plugin to + pluginsPath: join(app.getPath("userData"), "plugins"), + }); + } + + /** + * Migrates the plugins by deleting the `plugins` directory in the user data path. + * If the `migrated_version` key in the `Store` object does not match the current app version, + * the function deletes the `plugins` directory and sets the `migrated_version` key to the current app version. + * @returns A Promise that resolves when the migration is complete. + */ + migratePlugins() { + return new Promise((resolve) => { + const store = new Store(); + if (store.get("migrated_version") !== app.getVersion()) { + console.debug("start migration:", store.get("migrated_version")); + const userDataPath = app.getPath("userData"); + const fullPath = join(userDataPath, "plugins"); + + rmdir(fullPath, { recursive: true }, function (err) { + if (err) console.error(err); + store.set("migrated_version", app.getVersion()); + console.debug("migrate plugins done"); + resolve(undefined); + }); + } else { + resolve(undefined); + } + }); + } +} diff --git a/server/managers/window.ts b/server/managers/window.ts new file mode 100644 index 000000000..c930dd5ec --- /dev/null +++ b/server/managers/window.ts @@ -0,0 +1,37 @@ +import { BrowserWindow } from "electron"; + +/** + * Manages the current window instance. + */ +export class WindowManager { + public static instance: WindowManager = new WindowManager(); + public currentWindow?: BrowserWindow; + + constructor() { + if (WindowManager.instance) { + return WindowManager.instance; + } + } + + /** + * Creates a new window instance. + * @param {Electron.BrowserWindowConstructorOptions} options - The options to create the window with. + * @returns The created window instance. + */ + createWindow(options?: Electron.BrowserWindowConstructorOptions | undefined) { + this.currentWindow = new BrowserWindow({ + width: 1200, + minWidth: 800, + height: 800, + show: false, + trafficLightPosition: { + x: 10, + y: 15, + }, + titleBarStyle: "hidden", + vibrancy: "sidebar", + ...options, + }); + return this.currentWindow; + } +} diff --git a/server/package.json b/server/package.json new file mode 100644 index 000000000..8185f37d9 --- /dev/null +++ b/server/package.json @@ -0,0 +1,97 @@ +{ + "name": "jan-server", + "version": "0.1.3", + "main": "./build/main.js", + "author": "Jan ", + "license": "MIT", + "homepage": "https://github.com/janhq/jan/tree/main/electron", + "description": "Use offline LLMs with your own data. Run open source models like Llama2 or Falcon on your internal computers/servers.", + "build": { + "appId": "jan.ai.app", + "productName": "Jan", + "files": [ + "renderer/**/*", + "build/*.{js,map}", + "build/**/*.{js,map}", + "core/pre-install", + "core/plugin-manager/facade" + ], + "asarUnpack": [ + "core/pre-install" + ], + "publish": [ + { + "provider": "github", + "owner": "janhq", + "repo": "jan" + } + ], + "extends": null, + "mac": { + "type": "distribution", + "entitlements": "./entitlements.mac.plist", + "entitlementsInherit": "./entitlements.mac.plist", + "notarize": { + "teamId": "YT49P7GXG4" + }, + "icon": "icons/icon.png" + }, + "linux": { + "target": [ + "deb" + ], + "category": "Utility", + "icon": "icons/" + }, + "win": { + "icon": "icons/icon.png" + }, + "artifactName": "jan-${os}-${arch}-${version}.${ext}" + }, + "scripts": { + "lint": "eslint . --ext \".js,.jsx,.ts,.tsx\"", + "test:e2e": "playwright test --workers=1", + "dev": "tsc -p . && electron .", + "build": "run-script-os", + "build:test": "run-script-os", + "build:test:darwin": "tsc -p . && electron-builder -p never -m --dir", + "build:test:win32": "tsc -p . && electron-builder -p never -w --dir", + "build:test:linux": "tsc -p . && electron-builder -p never -l --dir", + "build:darwin": "tsc -p . && electron-builder -p never -m", + "build:win32": "tsc -p . && electron-builder -p never -w", + "build:linux": "tsc -p . && electron-builder -p never --linux deb", + "build:publish": "run-script-os", + "build:publish:darwin": "tsc -p . && electron-builder -p onTagOrDraft -m --x64 --arm64", + "build:publish:win32": "tsc -p . && electron-builder -p onTagOrDraft -w", + "build:publish:linux": "tsc -p . && electron-builder -p onTagOrDraft -l deb" + }, + "dependencies": { + "@npmcli/arborist": "^7.1.0", + "@types/express": "^4.17.21", + "@types/request": "^2.48.12", + "@uiball/loaders": "^1.3.0", + "electron-store": "^8.1.0", + "electron-updater": "^6.1.4", + "express": "^4.18.2", + "pacote": "^17.0.4", + "request": "^2.88.2", + "request-progress": "^3.0.0", + "use-debounce": "^9.0.4" + }, + "devDependencies": { + "@electron/notarize": "^2.1.0", + "@playwright/test": "^1.38.1", + "@types/npmcli__arborist": "^5.6.4", + "@types/pacote": "^11.1.7", + "@typescript-eslint/eslint-plugin": "^6.7.3", + "@typescript-eslint/parser": "^6.7.3", + "electron": "26.2.1", + "electron-builder": "^24.6.4", + "electron-playwright-helpers": "^1.6.0", + "eslint-plugin-react": "^7.33.2", + "run-script-os": "^1.1.6" + }, + "installConfig": { + "hoistingLimits": "workspaces" + } +} diff --git a/server/tsconfig.json b/server/tsconfig.json new file mode 100644 index 000000000..3cc218f93 --- /dev/null +++ b/server/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "noImplicitAny": true, + "sourceMap": true, + "strict": true, + "outDir": "./build", + "rootDir": "./", + "noEmitOnError": true, + "esModuleInterop": true, + "baseUrl": ".", + "allowJs": true, + "skipLibCheck": true, + "paths": { "*": ["node_modules/*"] }, + "typeRoots": ["node_modules/@types"] + }, + "include": ["./**/*.ts"], + "exclude": ["core", "build", "dist", "tests", "node_modules"] +} diff --git a/server/utils/disposable.ts b/server/utils/disposable.ts new file mode 100644 index 000000000..462f7e3e5 --- /dev/null +++ b/server/utils/disposable.ts @@ -0,0 +1,8 @@ +export function dispose(requiredModules: Record) { + for (const key in requiredModules) { + const module = requiredModules[key]; + if (typeof module["dispose"] === "function") { + module["dispose"](); + } + } +} diff --git a/server/utils/menu.ts b/server/utils/menu.ts new file mode 100644 index 000000000..65e009aef --- /dev/null +++ b/server/utils/menu.ts @@ -0,0 +1,111 @@ +// @ts-nocheck +const { app, Menu, dialog } = require("electron"); +const isMac = process.platform === "darwin"; +const { autoUpdater } = require("electron-updater"); +import { compareSemanticVersions } from "./versionDiff"; + +const template: (Electron.MenuItemConstructorOptions | Electron.MenuItem)[] = [ + ...(isMac + ? [ + { + label: app.name, + submenu: [ + { role: "about" }, + { + label: "Check for Updates...", + click: () => + autoUpdater.checkForUpdatesAndNotify().then((e) => { + if ( + !e || + compareSemanticVersions( + app.getVersion(), + e.updateInfo.version + ) >= 0 + ) + dialog.showMessageBox({ + message: `There are currently no updates available.`, + }); + }), + }, + { type: "separator" }, + { role: "services" }, + { type: "separator" }, + { role: "hide" }, + { role: "hideOthers" }, + { role: "unhide" }, + { type: "separator" }, + { role: "quit" }, + ], + }, + ] + : []), + { + label: "Edit", + submenu: [ + { role: "undo" }, + { role: "redo" }, + { type: "separator" }, + { role: "cut" }, + { role: "copy" }, + { role: "paste" }, + ...(isMac + ? [ + { role: "pasteAndMatchStyle" }, + { role: "delete" }, + { role: "selectAll" }, + { type: "separator" }, + { + label: "Speech", + submenu: [{ role: "startSpeaking" }, { role: "stopSpeaking" }], + }, + ] + : [{ role: "delete" }, { type: "separator" }, { role: "selectAll" }]), + ], + }, + { + label: "View", + submenu: [ + { role: "reload" }, + { role: "forceReload" }, + { role: "toggleDevTools" }, + { type: "separator" }, + { role: "resetZoom" }, + { role: "zoomIn" }, + { role: "zoomOut" }, + { type: "separator" }, + { role: "togglefullscreen" }, + ], + }, + { + label: "Window", + submenu: [ + { role: "minimize" }, + { role: "zoom" }, + ...(isMac + ? [ + { type: "separator" }, + { role: "front" }, + { type: "separator" }, + { role: "window" }, + ] + : [{ role: "close" }]), + ], + }, + { + role: "help", + submenu: [ + { + label: "Learn More", + click: async () => { + const { shell } = require("electron"); + await shell.openExternal("https://jan.ai/"); + }, + }, + ], + }, +]; + +export const setupMenu = () => { + const menu = Menu.buildFromTemplate(template); + Menu.setApplicationMenu(menu); +}; diff --git a/server/utils/versionDiff.ts b/server/utils/versionDiff.ts new file mode 100644 index 000000000..25934e87f --- /dev/null +++ b/server/utils/versionDiff.ts @@ -0,0 +1,21 @@ +export const compareSemanticVersions = (a: string, b: string) => { + + // 1. Split the strings into their parts. + const a1 = a.split('.'); + const b1 = b.split('.'); + // 2. Contingency in case there's a 4th or 5th version + const len = Math.min(a1.length, b1.length); + // 3. Look through each version number and compare. + for (let i = 0; i < len; i++) { + const a2 = +a1[ i ] || 0; + const b2 = +b1[ i ] || 0; + + if (a2 !== b2) { + return a2 > b2 ? 1 : -1; + } + } + + // 4. We hit this if the all checked versions so far are equal + // + return b1.length - a1.length; +}; \ No newline at end of file From 64a58d1e15242402caaa1bd0aff2e2cc5b312732 Mon Sep 17 00:00:00 2001 From: Linh Tran Date: Wed, 29 Nov 2023 09:29:04 +0700 Subject: [PATCH 02/42] WIP: fs adapter calling server API --- Makefile | 2 +- core/src/fs.ts | 143 +++++++++++++++++++++++++++++++++++++++----- server/main.ts | 35 ++++++----- server/package.json | 3 +- 4 files changed, 147 insertions(+), 36 deletions(-) diff --git a/Makefile b/Makefile index af416304c..e0f6cb274 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ install-and-build: build-uikit ifeq ($(OS),Windows_NT) powershell -Command "yarn config set network-timeout 300000; \ $$env:NITRO_VERSION = Get-Content .\\plugins\\inference-plugin\\nitro\\version.txt; \ - Write-Output \"Nitro version: $$env:NITRO_VERSION\"; yarn build:core; yarn install; yarn build:plugins" + Write-Output \"Nitro version: $$env:NITRO_VERSION\"; yarn build:core; yarn install; yarn build:plugins" else yarn build:core yarn install diff --git a/core/src/fs.ts b/core/src/fs.ts index 2c94a2ce8..b8722e1a6 100644 --- a/core/src/fs.ts +++ b/core/src/fs.ts @@ -1,59 +1,170 @@ +const fetchRetry = require("fetch-retry")(global.fetch); + +const PORT = 1337; +const LOCAL_HOST = "127.0.0.1"; +const JAN_HTTP_SERVER_URL = `http://${LOCAL_HOST}:${PORT}`; +const JAN_FS_API = `${JAN_HTTP_SERVER_URL}/fs`; /** * Writes data to a file at the specified path. * @param {string} path - The path to the file. * @param {string} data - The data to write to the file. * @returns {Promise} A Promise that resolves when the file is written successfully. */ -const writeFile: (path: string, data: string) => Promise = (path, data) => - window.coreAPI?.writeFile(path, data) ?? - window.electronAPI?.writeFile(path, data); - +const writeFile = (path: string, data: string): Promise => { + return fetchRetry(JAN_FS_API, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + op: 'writeFile', + path, + data + }), + retries: 3, + retryDelay: 500, + }).catch((err: any) => { + console.error(err); + throw new Error(`writeFile: ${path} failed`); + }) +} + /** * Checks whether the path is a directory. * @param path - The path to check. * @returns {boolean} A boolean indicating whether the path is a directory. */ -const isDirectory = (path: string): Promise => - window.coreAPI?.isDirectory(path) ?? window.electronAPI?.isDirectory(path); +const isDirectory = (path: string): Promise => { + return fetchRetry(JAN_FS_API, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + op: 'isDirectory', + path, + }), + retries: 3, + retryDelay: 500, + }).catch((err: any) => { + console.error(err); + throw new Error(`isDirectory: ${path} failed`); + }) +} /** * Reads the contents of a file at the specified path. * @param {string} path - The path of the file to read. * @returns {Promise} A Promise that resolves with the contents of the file. */ -const readFile: (path: string) => Promise = (path) => - window.coreAPI?.readFile(path) ?? window.electronAPI?.readFile(path); +const readFile = (path: string): Promise => { + return fetchRetry(JAN_FS_API, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + op: 'readFile', + path, + }), + retries: 3, + retryDelay: 500, + }).catch((err: any) => { + console.error(err); + throw new Error(`readFile: ${path} failed`); + }) +} /** * List the directory files * @param {string} path - The path of the directory to list files. * @returns {Promise} A Promise that resolves with the contents of the directory. */ -const listFiles: (path: string) => Promise = (path) => - window.coreAPI?.listFiles(path) ?? window.electronAPI?.listFiles(path); +const listFiles = (path: string): Promise => { + return fetchRetry(JAN_FS_API, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + op: 'listFiles', + path, + }), + retries: 3, + retryDelay: 500, + }).catch((err: any) => { + console.error(err); + throw new Error(`listFiles: ${path} failed`); + }) +} /** * Creates a directory at the specified path. * @param {string} path - The path of the directory to create. * @returns {Promise} A Promise that resolves when the directory is created successfully. */ -const mkdir: (path: string) => Promise = (path) => - window.coreAPI?.mkdir(path) ?? window.electronAPI?.mkdir(path); +const mkdir = (path: string): Promise => { + return fetchRetry(JAN_FS_API, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + op: 'mkdir', + path, + }), + retries: 3, + retryDelay: 500, + }).catch((err: any) => { + console.error(err); + throw new Error(`mkdir: ${path} failed`); + }) +} /** * Removes a directory at the specified path. * @param {string} path - The path of the directory to remove. * @returns {Promise} A Promise that resolves when the directory is removed successfully. */ -const rmdir: (path: string) => Promise = (path) => - window.coreAPI?.rmdir(path) ?? window.electronAPI?.rmdir(path); +const rmdir = (path: string): Promise => { + return fetchRetry(JAN_FS_API, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + op: 'rmdir', + path, + }), + retries: 3, + retryDelay: 500, + }).catch((err: any) => { + console.error(err); + throw new Error(`rmdir: ${path} failed`); + }) +} /** * Deletes a file from the local file system. * @param {string} path - The path of the file to delete. * @returns {Promise} A Promise that resolves when the file is deleted. */ -const deleteFile: (path: string) => Promise = (path) => - window.coreAPI?.deleteFile(path) ?? window.electronAPI?.deleteFile(path); +const deleteFile = (path: string): Promise => { + return fetchRetry(JAN_FS_API, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + op: 'deleteFile', + path, + }), + retries: 3, + retryDelay: 500, + }).catch((err: any) => { + console.error(err); + throw new Error(`deleteFile: ${path} failed`); + }) +} export const fs = { isDirectory, diff --git a/server/main.ts b/server/main.ts index a4f4df1bb..5ba2045c1 100644 --- a/server/main.ts +++ b/server/main.ts @@ -1,32 +1,31 @@ -import { join } from 'path' import { setupMenu } from './utils/menu' -import { handleFsIPCs } from './handlers/fs' import app from 'express' - +import bodyParser from 'body-parser' +import fs from 'fs' /** * Managers **/ import { ModuleManager } from './managers/module' import { PluginManager } from './managers/plugin' -/** - * IPC Handlers - **/ -import { handleDownloaderIPCs } from './handlers/download' -import { handlePluginIPCs } from './handlers/plugin' -app().listen(6969, ()=>{ +const server = app() +server.use(bodyParser) + +const USER_ROOT_DIR = '.data' +server.post("fs", (req, res) => { + let op = req.body.op; + switch(op){ + case 'readFile': + fs.readFile(req.body.path, ()=>{}) + case 'writeFile': + fs.writeFile(req.body.path, Buffer.from(req.body.data, "base64"), ()=>{}) + } +}) + +server.listen(1337, ()=>{ PluginManager.instance.migratePlugins() PluginManager.instance.setupPlugins() setupMenu() - handleIPCs() }) -/** - * Handles various IPC messages from the renderer process. - */ -function handleIPCs() { - handleFsIPCs() - handleDownloaderIPCs() - handlePluginIPCs() -} diff --git a/server/package.json b/server/package.json index 8185f37d9..9523fa000 100644 --- a/server/package.json +++ b/server/package.json @@ -67,7 +67,6 @@ }, "dependencies": { "@npmcli/arborist": "^7.1.0", - "@types/express": "^4.17.21", "@types/request": "^2.48.12", "@uiball/loaders": "^1.3.0", "electron-store": "^8.1.0", @@ -81,6 +80,8 @@ "devDependencies": { "@electron/notarize": "^2.1.0", "@playwright/test": "^1.38.1", + "@types/body-parser": "^1.19.5", + "@types/express": "^4.17.21", "@types/npmcli__arborist": "^5.6.4", "@types/pacote": "^11.1.7", "@typescript-eslint/eslint-plugin": "^6.7.3", From e5f57b853bd334f724ef059b138fedd47228f04c Mon Sep 17 00:00:00 2001 From: Linh Tran Date: Fri, 1 Dec 2023 09:35:51 +0700 Subject: [PATCH 03/42] boilerplate for express server --- server/core/plugin/facade.ts | 30 --- server/core/plugin/globals.ts | 36 ---- server/core/plugin/index.ts | 149 -------------- server/core/plugin/plugin.ts | 213 --------------------- server/core/plugin/router.ts | 97 ---------- server/core/plugin/store.ts | 131 ------------- server/{core/pre-install => data}/.gitkeep | 0 server/handlers/download.ts | 108 ----------- server/handlers/fs.ts | 156 --------------- server/handlers/plugin.ts | 118 ------------ server/lib/.gitkeep | 0 server/main.ts | 43 ++--- server/managers/download.ts | 24 --- server/managers/module.ts | 33 ---- server/managers/plugin.ts | 60 ------ server/managers/window.ts | 37 ---- server/nodemon.json | 5 + server/package.json | 24 +-- server/tsconfig.json | 2 + server/utils/disposable.ts | 8 - server/utils/menu.ts | 111 ----------- server/utils/versionDiff.ts | 21 -- server/v1/assistants/index.ts | 5 + server/v1/chat/index.ts | 5 + server/v1/index.ts | 20 ++ server/v1/models/downloadModel.ts | 5 + server/v1/models/index.ts | 18 ++ server/v1/threads/index.ts | 5 + 28 files changed, 90 insertions(+), 1374 deletions(-) delete mode 100644 server/core/plugin/facade.ts delete mode 100644 server/core/plugin/globals.ts delete mode 100644 server/core/plugin/index.ts delete mode 100644 server/core/plugin/plugin.ts delete mode 100644 server/core/plugin/router.ts delete mode 100644 server/core/plugin/store.ts rename server/{core/pre-install => data}/.gitkeep (100%) delete mode 100644 server/handlers/download.ts delete mode 100644 server/handlers/fs.ts delete mode 100644 server/handlers/plugin.ts create mode 100644 server/lib/.gitkeep delete mode 100644 server/managers/download.ts delete mode 100644 server/managers/module.ts delete mode 100644 server/managers/plugin.ts delete mode 100644 server/managers/window.ts create mode 100644 server/nodemon.json delete mode 100644 server/utils/disposable.ts delete mode 100644 server/utils/menu.ts delete mode 100644 server/utils/versionDiff.ts create mode 100644 server/v1/assistants/index.ts create mode 100644 server/v1/chat/index.ts create mode 100644 server/v1/index.ts create mode 100644 server/v1/models/downloadModel.ts create mode 100644 server/v1/models/index.ts create mode 100644 server/v1/threads/index.ts diff --git a/server/core/plugin/facade.ts b/server/core/plugin/facade.ts deleted file mode 100644 index bd1089109..000000000 --- a/server/core/plugin/facade.ts +++ /dev/null @@ -1,30 +0,0 @@ -const { ipcRenderer, contextBridge } = require("electron"); - -export function useFacade() { - const interfaces = { - install(plugins: any[]) { - return ipcRenderer.invoke("pluggable:install", plugins); - }, - uninstall(plugins: any[], reload: boolean) { - return ipcRenderer.invoke("pluggable:uninstall", plugins, reload); - }, - getActive() { - return ipcRenderer.invoke("pluggable:getActivePlugins"); - }, - update(plugins: any[], reload: boolean) { - return ipcRenderer.invoke("pluggable:update", plugins, reload); - }, - updatesAvailable(plugin: any) { - return ipcRenderer.invoke("pluggable:updatesAvailable", plugin); - }, - toggleActive(plugin: any, active: boolean) { - return ipcRenderer.invoke("pluggable:togglePluginActive", plugin, active); - }, - }; - - if (contextBridge) { - contextBridge.exposeInMainWorld("pluggableElectronIpc", interfaces); - } - - return interfaces; -} diff --git a/server/core/plugin/globals.ts b/server/core/plugin/globals.ts deleted file mode 100644 index 69df7925c..000000000 --- a/server/core/plugin/globals.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { existsSync, mkdirSync, writeFileSync } from "fs"; -import { join, resolve } from "path"; - -export let pluginsPath: string | undefined = undefined; - -/** - * @private - * Set path to plugins directory and create the directory if it does not exist. - * @param {string} plgPath path to plugins directory - */ -export function setPluginsPath(plgPath: string) { - // Create folder if it does not exist - let plgDir; - try { - plgDir = resolve(plgPath); - if (plgDir.length < 2) throw new Error(); - - if (!existsSync(plgDir)) mkdirSync(plgDir); - - const pluginsJson = join(plgDir, "plugins.json"); - if (!existsSync(pluginsJson)) writeFileSync(pluginsJson, "{}", "utf8"); - - pluginsPath = plgDir; - } catch (error) { - throw new Error("Invalid path provided to the plugins folder"); - } -} - -/** - * @private - * Get the path to the plugins.json file. - * @returns location of plugins.json - */ -export function getPluginsFile() { - return join(pluginsPath ?? "", "plugins.json"); -} \ No newline at end of file diff --git a/server/core/plugin/index.ts b/server/core/plugin/index.ts deleted file mode 100644 index e8c64747b..000000000 --- a/server/core/plugin/index.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { readFileSync } from "fs"; -import { protocol } from "electron"; -import { normalize } from "path"; - -import Plugin from "./plugin"; -import { - getAllPlugins, - removePlugin, - persistPlugins, - installPlugins, - getPlugin, - getActivePlugins, - addPlugin, -} from "./store"; -import { - pluginsPath as storedPluginsPath, - setPluginsPath, - getPluginsFile, -} from "./globals"; -import router from "./router"; - -/** - * Sets up the required communication between the main and renderer processes. - * Additionally sets the plugins up using {@link usePlugins} if a pluginsPath is provided. - * @param {Object} options configuration for setting up the renderer facade. - * @param {confirmInstall} [options.confirmInstall] Function to validate that a plugin should be installed. - * @param {Boolean} [options.useFacade=true] Whether to make a facade to the plugins available in the renderer. - * @param {string} [options.pluginsPath] Optional path to the plugins folder. - * @returns {pluginManager|Object} A set of functions used to manage the plugin lifecycle if usePlugins is provided. - * @function - */ -export function init(options: any) { - if ( - !Object.prototype.hasOwnProperty.call(options, "useFacade") || - options.useFacade - ) { - // Enable IPC to be used by the facade - router(); - } - - // Create plugins protocol to serve plugins to renderer - registerPluginProtocol(); - - // perform full setup if pluginsPath is provided - if (options.pluginsPath) { - return usePlugins(options.pluginsPath); - } - - return {}; -} - -/** - * Create plugins protocol to provide plugins to renderer - * @private - * @returns {boolean} Whether the protocol registration was successful - */ -function registerPluginProtocol() { - return protocol.registerFileProtocol("plugin", (request, callback) => { - const entry = request.url.substr(8); - const url = normalize(storedPluginsPath + entry); - callback({ path: url }); - }); -} - -/** - * Set Pluggable Electron up to run from the pluginPath folder if it is provided and - * load plugins persisted in that folder. - * @param {string} pluginsPath Path to the plugins folder. Required if not yet set up. - * @returns {pluginManager} A set of functions used to manage the plugin lifecycle. - */ -export function usePlugins(pluginsPath: string) { - if (!pluginsPath) - throw Error( - "A path to the plugins folder is required to use Pluggable Electron" - ); - // Store the path to the plugins folder - setPluginsPath(pluginsPath); - - // Remove any registered plugins - for (const plugin of getAllPlugins()) { - if (plugin.name) removePlugin(plugin.name, false); - } - - // Read plugin list from plugins folder - const plugins = JSON.parse(readFileSync(getPluginsFile(), "utf-8")); - try { - // Create and store a Plugin instance for each plugin in list - for (const p in plugins) { - loadPlugin(plugins[p]); - } - persistPlugins(); - } catch (error) { - // Throw meaningful error if plugin loading fails - throw new Error( - "Could not successfully rebuild list of installed plugins.\n" + - error + - "\nPlease check the plugins.json file in the plugins folder." - ); - } - - // Return the plugin lifecycle functions - return getStore(); -} - -/** - * Check the given plugin object. If it is marked for uninstalling, the plugin files are removed. - * Otherwise a Plugin instance for the provided object is created and added to the store. - * @private - * @param {Object} plg Plugin info - */ -function loadPlugin(plg: any) { - // Create new plugin, populate it with plg details and save it to the store - const plugin = new Plugin(); - - for (const key in plg) { - if (Object.prototype.hasOwnProperty.call(plg, key)) { - // Use Object.defineProperty to set the properties as writable - Object.defineProperty(plugin, key, { - value: plg[key], - writable: true, - enumerable: true, - configurable: true, - }); - } - } - - addPlugin(plugin, false); - plugin.subscribe("pe-persist", persistPlugins); -} - -/** - * Returns the publicly available store functions. - * @returns {pluginManager} A set of functions used to manage the plugin lifecycle. - */ -export function getStore() { - if (!storedPluginsPath) { - throw new Error( - "The plugin path has not yet been set up. Please run usePlugins before accessing the store" - ); - } - - return { - installPlugins, - getPlugin, - getAllPlugins, - getActivePlugins, - removePlugin, - }; -} diff --git a/server/core/plugin/plugin.ts b/server/core/plugin/plugin.ts deleted file mode 100644 index f0fc073d7..000000000 --- a/server/core/plugin/plugin.ts +++ /dev/null @@ -1,213 +0,0 @@ -import { rmdir } from "fs/promises"; -import { resolve, join } from "path"; -import { manifest, extract } from "pacote"; -import * as Arborist from "@npmcli/arborist"; - -import { pluginsPath } from "./globals"; - -/** - * An NPM package that can be used as a Pluggable Electron plugin. - * Used to hold all the information and functions necessary to handle the plugin lifecycle. - */ -class Plugin { - /** - * @property {string} origin Original specification provided to fetch the package. - * @property {Object} installOptions Options provided to pacote when fetching the manifest. - * @property {name} name The name of the plugin as defined in the manifest. - * @property {string} url Electron URL where the package can be accessed. - * @property {string} version Version of the package as defined in the manifest. - * @property {Array} activationPoints List of {@link ./Execution-API#activationPoints|activation points}. - * @property {string} main The entry point as defined in the main entry of the manifest. - * @property {string} description The description of plugin as defined in the manifest. - * @property {string} icon The icon of plugin as defined in the manifest. - */ - origin?: string; - installOptions: any; - name?: string; - url?: string; - version?: string; - activationPoints?: Array; - main?: string; - description?: string; - icon?: string; - - /** @private */ - _active = false; - - /** - * @private - * @property {Object.} #listeners A list of callbacks to be executed when the Plugin is updated. - */ - listeners: Record void> = {}; - - /** - * Set installOptions with defaults for options that have not been provided. - * @param {string} [origin] Original specification provided to fetch the package. - * @param {Object} [options] Options provided to pacote when fetching the manifest. - */ - constructor(origin?: string, options = {}) { - const defaultOpts = { - version: false, - fullMetadata: false, - Arborist, - }; - - this.origin = origin; - this.installOptions = { ...defaultOpts, ...options }; - } - - /** - * Package name with version number. - * @type {string} - */ - get specifier() { - return ( - this.origin + - (this.installOptions.version ? "@" + this.installOptions.version : "") - ); - } - - /** - * Whether the plugin should be registered with its activation points. - * @type {boolean} - */ - get active() { - return this._active; - } - - /** - * Set Package details based on it's manifest - * @returns {Promise.} Resolves to true when the action completed - */ - async getManifest() { - // Get the package's manifest (package.json object) - try { - const mnf = await manifest(this.specifier, this.installOptions); - - // set the Package properties based on the it's manifest - this.name = mnf.name; - this.version = mnf.version; - this.activationPoints = mnf.activationPoints - ? (mnf.activationPoints as string[]) - : undefined; - this.main = mnf.main; - this.description = mnf.description; - this.icon = mnf.icon as any; - } catch (error) { - throw new Error( - `Package ${this.origin} does not contain a valid manifest: ${error}` - ); - } - - return true; - } - - /** - * Extract plugin to plugins folder. - * @returns {Promise.} This plugin - * @private - */ - async _install() { - try { - // import the manifest details - await this.getManifest(); - - // Install the package in a child folder of the given folder - await extract( - this.specifier, - join(pluginsPath ?? "", this.name ?? ""), - this.installOptions - ); - - if (!Array.isArray(this.activationPoints)) - throw new Error("The plugin does not contain any activation points"); - - // Set the url using the custom plugins protocol - this.url = `plugin://${this.name}/${this.main}`; - - this.emitUpdate(); - } catch (err) { - // Ensure the plugin is not stored and the folder is removed if the installation fails - this.setActive(false); - throw err; - } - - return [this]; - } - - /** - * Subscribe to updates of this plugin - * @param {string} name name of the callback to register - * @param {callback} cb The function to execute on update - */ - subscribe(name: string, cb: () => void) { - this.listeners[name] = cb; - } - - /** - * Remove subscription - * @param {string} name name of the callback to remove - */ - unsubscribe(name: string) { - delete this.listeners[name]; - } - - /** - * Execute listeners - */ - emitUpdate() { - for (const cb in this.listeners) { - this.listeners[cb].call(null, this); - } - } - - /** - * Check for updates and install if available. - * @param {string} version The version to update to. - * @returns {boolean} Whether an update was performed. - */ - async update(version = false) { - if (await this.isUpdateAvailable()) { - this.installOptions.version = version; - await this._install(); - return true; - } - - return false; - } - - /** - * Check if a new version of the plugin is available at the origin. - * @returns the latest available version if a new version is available or false if not. - */ - async isUpdateAvailable() { - if (this.origin) { - const mnf = await manifest(this.origin); - return mnf.version !== this.version ? mnf.version : false; - } - } - - /** - * Remove plugin and refresh renderers. - * @returns {Promise} - */ - async uninstall() { - const plgPath = resolve(pluginsPath ?? "", this.name ?? ""); - await rmdir(plgPath, { recursive: true }); - - this.emitUpdate(); - } - - /** - * Set a plugin's active state. This determines if a plugin should be loaded on initialisation. - * @param {boolean} active State to set _active to - * @returns {Plugin} This plugin - */ - setActive(active: boolean) { - this._active = active; - this.emitUpdate(); - return this; - } -} - -export default Plugin; diff --git a/server/core/plugin/router.ts b/server/core/plugin/router.ts deleted file mode 100644 index 09c79485b..000000000 --- a/server/core/plugin/router.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { ipcMain, webContents } from "electron"; - -import { - getPlugin, - getActivePlugins, - installPlugins, - removePlugin, - getAllPlugins, -} from "./store"; -import { pluginsPath } from "./globals"; -import Plugin from "./plugin"; - -// Throw an error if pluginsPath has not yet been provided by usePlugins. -const checkPluginsPath = () => { - if (!pluginsPath) - throw Error("Path to plugins folder has not yet been set up."); -}; -let active = false; -/** - * Provide the renderer process access to the plugins. - **/ -export default function () { - if (active) return; - // Register IPC route to install a plugin - ipcMain.handle("pluggable:install", async (e, plugins) => { - checkPluginsPath(); - - // Install and activate all provided plugins - const installed = await installPlugins(plugins); - return JSON.parse(JSON.stringify(installed)); - }); - - // Register IPC route to uninstall a plugin - ipcMain.handle("pluggable:uninstall", async (e, plugins, reload) => { - checkPluginsPath(); - - // Uninstall all provided plugins - for (const plg of plugins) { - const plugin = getPlugin(plg); - await plugin.uninstall(); - if (plugin.name) removePlugin(plugin.name); - } - - // Reload all renderer pages if needed - reload && webContents.getAllWebContents().forEach((wc) => wc.reload()); - return true; - }); - - // Register IPC route to update a plugin - ipcMain.handle("pluggable:update", async (e, plugins, reload) => { - checkPluginsPath(); - - // Update all provided plugins - const updated: Plugin[] = []; - for (const plg of plugins) { - const plugin = getPlugin(plg); - const res = await plugin.update(); - if (res) updated.push(plugin); - } - - // Reload all renderer pages if needed - if (updated.length && reload) - webContents.getAllWebContents().forEach((wc) => wc.reload()); - - return JSON.parse(JSON.stringify(updated)); - }); - - // Register IPC route to check if updates are available for a plugin - ipcMain.handle("pluggable:updatesAvailable", (e, names) => { - checkPluginsPath(); - - const plugins = names - ? names.map((name: string) => getPlugin(name)) - : getAllPlugins(); - - const updates: Record = {}; - for (const plugin of plugins) { - updates[plugin.name] = plugin.isUpdateAvailable(); - } - return updates; - }); - - // Register IPC route to get the list of active plugins - ipcMain.handle("pluggable:getActivePlugins", () => { - checkPluginsPath(); - return JSON.parse(JSON.stringify(getActivePlugins())); - }); - - // Register IPC route to toggle the active state of a plugin - ipcMain.handle("pluggable:togglePluginActive", (e, plg, active) => { - checkPluginsPath(); - const plugin = getPlugin(plg); - return JSON.parse(JSON.stringify(plugin.setActive(active))); - }); - - active = true; -} diff --git a/server/core/plugin/store.ts b/server/core/plugin/store.ts deleted file mode 100644 index cfd25e5ca..000000000 --- a/server/core/plugin/store.ts +++ /dev/null @@ -1,131 +0,0 @@ -/** - * Provides access to the plugins stored by Pluggable Electron - * @typedef {Object} pluginManager - * @prop {getPlugin} getPlugin - * @prop {getAllPlugins} getAllPlugins - * @prop {getActivePlugins} getActivePlugins - * @prop {installPlugins} installPlugins - * @prop {removePlugin} removePlugin - */ - -import { writeFileSync } from "fs"; -import Plugin from "./plugin"; -import { getPluginsFile } from "./globals"; - -/** - * @module store - * @private - */ - -/** - * Register of installed plugins - * @type {Object.} plugin - List of installed plugins - */ -const plugins: Record = {}; - -/** - * Get a plugin from the stored plugins. - * @param {string} name Name of the plugin to retrieve - * @returns {Plugin} Retrieved plugin - * @alias pluginManager.getPlugin - */ -export function getPlugin(name: string) { - if (!Object.prototype.hasOwnProperty.call(plugins, name)) { - throw new Error(`Plugin ${name} does not exist`); - } - - return plugins[name]; -} - -/** - * Get list of all plugin objects. - * @returns {Array.} All plugin objects - * @alias pluginManager.getAllPlugins - */ -export function getAllPlugins() { - return Object.values(plugins); -} - -/** - * Get list of active plugin objects. - * @returns {Array.} Active plugin objects - * @alias pluginManager.getActivePlugins - */ -export function getActivePlugins() { - return Object.values(plugins).filter((plugin) => plugin.active); -} - -/** - * Remove plugin from store and maybe save stored plugins to file - * @param {string} name Name of the plugin to remove - * @param {boolean} persist Whether to save the changes to plugins to file - * @returns {boolean} Whether the delete was successful - * @alias pluginManager.removePlugin - */ -export function removePlugin(name: string, persist = true) { - const del = delete plugins[name]; - if (persist) persistPlugins(); - return del; -} - -/** - * Add plugin to store and maybe save stored plugins to file - * @param {Plugin} plugin Plugin to add to store - * @param {boolean} persist Whether to save the changes to plugins to file - * @returns {void} - */ -export function addPlugin(plugin: Plugin, persist = true) { - if (plugin.name) plugins[plugin.name] = plugin; - if (persist) { - persistPlugins(); - plugin.subscribe("pe-persist", persistPlugins); - } -} - -/** - * Save stored plugins to file - * @returns {void} - */ -export function persistPlugins() { - const persistData: Record = {}; - for (const name in plugins) { - persistData[name] = plugins[name]; - } - writeFileSync(getPluginsFile(), JSON.stringify(persistData), "utf8"); -} - -/** - * Create and install a new plugin for the given specifier. - * @param {Array.} plugins A list of NPM specifiers, or installation configuration objects. - * @param {boolean} [store=true] Whether to store the installed plugins in the store - * @returns {Promise.>} New plugin - * @alias pluginManager.installPlugins - */ -export async function installPlugins(plugins: any, store = true) { - const installed: Plugin[] = []; - for (const plg of plugins) { - // Set install options and activation based on input type - const isObject = typeof plg === "object"; - const spec = isObject ? [plg.specifier, plg] : [plg]; - const activate = isObject ? plg.activate !== false : true; - - // Install and possibly activate plugin - const plugin = new Plugin(...spec); - await plugin._install(); - if (activate) plugin.setActive(true); - - // Add plugin to store if needed - if (store) addPlugin(plugin); - installed.push(plugin); - } - - // Return list of all installed plugins - return installed; -} - -/** - * @typedef {Object.} installOptions The {@link https://www.npmjs.com/package/pacote|pacote} - * options used to install the plugin with some extra options. - * @param {string} specifier the NPM specifier that identifies the package. - * @param {boolean} [activate] Whether this plugin should be activated after installation. Defaults to true. - */ diff --git a/server/core/pre-install/.gitkeep b/server/data/.gitkeep similarity index 100% rename from server/core/pre-install/.gitkeep rename to server/data/.gitkeep diff --git a/server/handlers/download.ts b/server/handlers/download.ts deleted file mode 100644 index 3a1fc36d1..000000000 --- a/server/handlers/download.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { app, ipcMain } from 'electron' -import { DownloadManager } from '../managers/download' -import { resolve, join } from 'path' -import { WindowManager } from '../managers/window' -import request from 'request' -import { createWriteStream, unlink } from 'fs' -const progress = require('request-progress') - -export function handleDownloaderIPCs() { - /** - * Handles the "pauseDownload" IPC message by pausing the download associated with the provided fileName. - * @param _event - The IPC event object. - * @param fileName - The name of the file being downloaded. - */ - ipcMain.handle('pauseDownload', async (_event, fileName) => { - DownloadManager.instance.networkRequests[fileName]?.pause() - }) - - /** - * Handles the "resumeDownload" IPC message by resuming the download associated with the provided fileName. - * @param _event - The IPC event object. - * @param fileName - The name of the file being downloaded. - */ - ipcMain.handle('resumeDownload', async (_event, fileName) => { - DownloadManager.instance.networkRequests[fileName]?.resume() - }) - - /** - * Handles the "abortDownload" IPC message by aborting the download associated with the provided fileName. - * The network request associated with the fileName is then removed from the networkRequests object. - * @param _event - The IPC event object. - * @param fileName - The name of the file being downloaded. - */ - ipcMain.handle('abortDownload', async (_event, fileName) => { - const rq = DownloadManager.instance.networkRequests[fileName] - DownloadManager.instance.networkRequests[fileName] = undefined - const userDataPath = app.getPath('userData') - const fullPath = join(userDataPath, fileName) - rq?.abort() - let result = 'NULL' - unlink(fullPath, function (err) { - if (err && err.code == 'ENOENT') { - result = `File not exist: ${err}` - } else if (err) { - result = `File delete error: ${err}` - } else { - result = 'File deleted successfully' - } - console.debug( - `Delete file ${fileName} from ${fullPath} result: ${result}` - ) - }) - }) - - /** - * Downloads a file from a given URL. - * @param _event - The IPC event object. - * @param url - The URL to download the file from. - * @param fileName - The name to give the downloaded file. - */ - ipcMain.handle('downloadFile', async (_event, url, fileName) => { - const userDataPath = join(app.getPath('home'), 'jan') - const destination = resolve(userDataPath, fileName) - const rq = request(url) - - progress(rq, {}) - .on('progress', function (state: any) { - WindowManager?.instance.currentWindow?.webContents.send( - 'FILE_DOWNLOAD_UPDATE', - { - ...state, - fileName, - } - ) - }) - .on('error', function (err: Error) { - WindowManager?.instance.currentWindow?.webContents.send( - 'FILE_DOWNLOAD_ERROR', - { - fileName, - err, - } - ) - }) - .on('end', function () { - if (DownloadManager.instance.networkRequests[fileName]) { - WindowManager?.instance.currentWindow?.webContents.send( - 'FILE_DOWNLOAD_COMPLETE', - { - fileName, - } - ) - DownloadManager.instance.setRequest(fileName, undefined) - } else { - WindowManager?.instance.currentWindow?.webContents.send( - 'FILE_DOWNLOAD_ERROR', - { - fileName, - err: 'Download cancelled', - } - ) - } - }) - .pipe(createWriteStream(destination)) - - DownloadManager.instance.setRequest(fileName, rq) - }) -} diff --git a/server/handlers/fs.ts b/server/handlers/fs.ts deleted file mode 100644 index c1e8a85e4..000000000 --- a/server/handlers/fs.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { app, ipcMain } from 'electron' -import * as fs from 'fs' -import { join } from 'path' - -/** - * Handles file system operations. - */ -export function handleFsIPCs() { - const userSpacePath = join(app.getPath('home'), 'jan') - - /** - * Gets the path to the user data directory. - * @param event - The event object. - * @returns A promise that resolves with the path to the user data directory. - */ - ipcMain.handle( - 'getUserSpace', - (): Promise => Promise.resolve(userSpacePath) - ) - - /** - * Checks whether the path is a directory. - * @param event - The event object. - * @param path - The path to check. - * @returns A promise that resolves with a boolean indicating whether the path is a directory. - */ - ipcMain.handle('isDirectory', (_event, path: string): Promise => { - const fullPath = join(userSpacePath, path) - return Promise.resolve( - fs.existsSync(fullPath) && fs.lstatSync(fullPath).isDirectory() - ) - }) - - /** - * Reads a file from the user data directory. - * @param event - The event object. - * @param path - The path of the file to read. - * @returns A promise that resolves with the contents of the file. - */ - ipcMain.handle('readFile', async (event, path: string): Promise => { - return new Promise((resolve, reject) => { - fs.readFile(join(userSpacePath, path), 'utf8', (err, data) => { - if (err) { - reject(err) - } else { - resolve(data) - } - }) - }) - }) - - /** - * Writes data to a file in the user data directory. - * @param event - The event object. - * @param path - The path of the file to write to. - * @param data - The data to write to the file. - * @returns A promise that resolves when the file has been written. - */ - ipcMain.handle( - 'writeFile', - async (event, path: string, data: string): Promise => { - return new Promise((resolve, reject) => { - fs.writeFile(join(userSpacePath, path), data, 'utf8', (err) => { - if (err) { - reject(err) - } else { - resolve() - } - }) - }) - } - ) - - /** - * Creates a directory in the user data directory. - * @param event - The event object. - * @param path - The path of the directory to create. - * @returns A promise that resolves when the directory has been created. - */ - ipcMain.handle('mkdir', async (event, path: string): Promise => { - return new Promise((resolve, reject) => { - fs.mkdir(join(userSpacePath, path), { recursive: true }, (err) => { - if (err) { - reject(err) - } else { - resolve() - } - }) - }) - }) - - /** - * Removes a directory in the user data directory. - * @param event - The event object. - * @param path - The path of the directory to remove. - * @returns A promise that resolves when the directory is removed successfully. - */ - ipcMain.handle('rmdir', async (event, path: string): Promise => { - return new Promise((resolve, reject) => { - fs.rmdir(join(userSpacePath, path), { recursive: true }, (err) => { - if (err) { - reject(err) - } else { - resolve() - } - }) - }) - }) - - /** - * Lists the files in a directory in the user data directory. - * @param event - The event object. - * @param path - The path of the directory to list files from. - * @returns A promise that resolves with an array of file names. - */ - ipcMain.handle( - 'listFiles', - async (event, path: string): Promise => { - return new Promise((resolve, reject) => { - fs.readdir(join(userSpacePath, path), (err, files) => { - if (err) { - reject(err) - } else { - resolve(files) - } - }) - }) - } - ) - - /** - * Deletes a file from the user data folder. - * @param _event - The IPC event object. - * @param filePath - The path to the file to delete. - * @returns A string indicating the result of the operation. - */ - ipcMain.handle('deleteFile', async (_event, filePath) => { - const fullPath = join(userSpacePath, filePath) - - let result = 'NULL' - fs.unlink(fullPath, function (err) { - if (err && err.code == 'ENOENT') { - result = `File not exist: ${err}` - } else if (err) { - result = `File delete error: ${err}` - } else { - result = 'File deleted successfully' - } - console.debug( - `Delete file ${filePath} from ${fullPath} result: ${result}` - ) - }) - - return result - }) -} diff --git a/server/handlers/plugin.ts b/server/handlers/plugin.ts deleted file mode 100644 index 22bf253e6..000000000 --- a/server/handlers/plugin.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { app, ipcMain } from "electron"; -import { readdirSync, rmdir, writeFileSync } from "fs"; -import { ModuleManager } from "../managers/module"; -import { join, extname } from "path"; -import { PluginManager } from "../managers/plugin"; -import { WindowManager } from "../managers/window"; -import { manifest, tarball } from "pacote"; - -export function handlePluginIPCs() { - /** - * Invokes a function from a plugin module in main node process. - * @param _event - The IPC event object. - * @param modulePath - The path to the plugin module. - * @param method - The name of the function to invoke. - * @param args - The arguments to pass to the function. - * @returns The result of the invoked function. - */ - ipcMain.handle( - "invokePluginFunc", - async (_event, modulePath, method, ...args) => { - const module = require( - /* webpackIgnore: true */ join( - app.getPath("userData"), - "plugins", - modulePath - ) - ); - ModuleManager.instance.setModule(modulePath, module); - - if (typeof module[method] === "function") { - return module[method](...args); - } else { - console.debug(module[method]); - console.error(`Function "${method}" does not exist in the module.`); - } - } - ); - - /** - * Returns the paths of the base plugins. - * @param _event - The IPC event object. - * @returns An array of paths to the base plugins. - */ - ipcMain.handle("basePlugins", async (_event) => { - const basePluginPath = join( - __dirname, - "../", - app.isPackaged - ? "../../app.asar.unpacked/core/pre-install" - : "../core/pre-install" - ); - return readdirSync(basePluginPath) - .filter((file) => extname(file) === ".tgz") - .map((file) => join(basePluginPath, file)); - }); - - /** - * Returns the path to the user's plugin directory. - * @param _event - The IPC event object. - * @returns The path to the user's plugin directory. - */ - ipcMain.handle("pluginPath", async (_event) => { - return join(app.getPath("userData"), "plugins"); - }); - - /** - * Deletes the `plugins` directory in the user data path and disposes of required modules. - * If the app is packaged, the function relaunches the app and exits. - * Otherwise, the function deletes the cached modules and sets up the plugins and reloads the main window. - * @param _event - The IPC event object. - * @param url - The URL to reload. - */ - ipcMain.handle("reloadPlugins", async (_event, url) => { - const userDataPath = app.getPath("userData"); - const fullPath = join(userDataPath, "plugins"); - - rmdir(fullPath, { recursive: true }, function (err) { - if (err) console.error(err); - ModuleManager.instance.clearImportedModules(); - - // just relaunch if packaged, should launch manually in development mode - if (app.isPackaged) { - app.relaunch(); - app.exit(); - } else { - for (const modulePath in ModuleManager.instance.requiredModules) { - delete require.cache[ - require.resolve( - join(app.getPath("userData"), "plugins", modulePath) - ) - ]; - } - PluginManager.instance.setupPlugins(); - WindowManager.instance.currentWindow?.reload(); - } - }); - }); - - /** - * Installs a remote plugin by downloading its tarball and writing it to a tgz file. - * @param _event - The IPC event object. - * @param pluginName - The name of the remote plugin to install. - * @returns A Promise that resolves to the path of the installed plugin file. - */ - ipcMain.handle("installRemotePlugin", async (_event, pluginName) => { - const destination = join( - app.getPath("userData"), - pluginName.replace(/^@.*\//, "") + ".tgz" - ); - return manifest(pluginName) - .then(async (manifest: any) => { - await tarball(manifest._resolved).then((data: Buffer) => { - writeFileSync(destination, data); - }); - }) - .then(() => destination); - }); -} diff --git a/server/lib/.gitkeep b/server/lib/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/server/main.ts b/server/main.ts index 5ba2045c1..582af5c61 100644 --- a/server/main.ts +++ b/server/main.ts @@ -1,31 +1,28 @@ -import { setupMenu } from './utils/menu' -import app from 'express' +import express from 'express' import bodyParser from 'body-parser' import fs from 'fs' -/** - * Managers - **/ -import { ModuleManager } from './managers/module' -import { PluginManager } from './managers/plugin' +import v1API from './v1' +const JAN_API_PORT = 1337; -const server = app() -server.use(bodyParser) +const server = express() +server.use(bodyParser.urlencoded()) +server.use(bodyParser.json()) const USER_ROOT_DIR = '.data' -server.post("fs", (req, res) => { - let op = req.body.op; - switch(op){ - case 'readFile': - fs.readFile(req.body.path, ()=>{}) - case 'writeFile': - fs.writeFile(req.body.path, Buffer.from(req.body.data, "base64"), ()=>{}) - } -}) - -server.listen(1337, ()=>{ - PluginManager.instance.migratePlugins() - PluginManager.instance.setupPlugins() - setupMenu() +server.use("/v1", v1API) + +// server.post("fs", (req, res) => { +// let op = req.body.op; +// switch(op){ +// case 'readFile': +// fs.readFile(req.body.path, ()=>{}) +// case 'writeFile': +// fs.writeFile(req.body.path, Buffer.from(req.body.data, "base64"), ()=>{}) +// } +// }) + +server.listen(JAN_API_PORT, () => { + console.log(`JAN API listening at: http://localhost:${JAN_API_PORT}`); }) diff --git a/server/managers/download.ts b/server/managers/download.ts deleted file mode 100644 index 08c089b74..000000000 --- a/server/managers/download.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Request } from "request"; - -/** - * Manages file downloads and network requests. - */ -export class DownloadManager { - public networkRequests: Record = {}; - - public static instance: DownloadManager = new DownloadManager(); - - constructor() { - if (DownloadManager.instance) { - return DownloadManager.instance; - } - } - /** - * Sets a network request for a specific file. - * @param {string} fileName - The name of the file. - * @param {Request | undefined} request - The network request to set, or undefined to clear the request. - */ - setRequest(fileName: string, request: Request | undefined) { - this.networkRequests[fileName] = request; - } -} diff --git a/server/managers/module.ts b/server/managers/module.ts deleted file mode 100644 index 43dda0fb6..000000000 --- a/server/managers/module.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { dispose } from "../utils/disposable"; - -/** - * Manages imported modules. - */ -export class ModuleManager { - public requiredModules: Record = {}; - - public static instance: ModuleManager = new ModuleManager(); - - constructor() { - if (ModuleManager.instance) { - return ModuleManager.instance; - } - } - - /** - * Sets a module. - * @param {string} moduleName - The name of the module. - * @param {any | undefined} nodule - The module to set, or undefined to clear the module. - */ - setModule(moduleName: string, nodule: any | undefined) { - this.requiredModules[moduleName] = nodule; - } - - /** - * Clears all imported modules. - */ - clearImportedModules() { - dispose(this.requiredModules); - this.requiredModules = {}; - } -} diff --git a/server/managers/plugin.ts b/server/managers/plugin.ts deleted file mode 100644 index 227eab34e..000000000 --- a/server/managers/plugin.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { app } from "electron"; -import { init } from "../core/plugin/index"; -import { join } from "path"; -import { rmdir } from "fs"; -import Store from "electron-store"; - -/** - * Manages plugin installation and migration. - */ -export class PluginManager { - public static instance: PluginManager = new PluginManager(); - - constructor() { - if (PluginManager.instance) { - return PluginManager.instance; - } - } - - /** - * Sets up the plugins by initializing the `plugins` module with the `confirmInstall` and `pluginsPath` options. - * The `confirmInstall` function always returns `true` to allow plugin installation. - * The `pluginsPath` option specifies the path to install plugins to. - */ - setupPlugins() { - init({ - // Function to check from the main process that user wants to install a plugin - confirmInstall: async (_plugins: string[]) => { - return true; - }, - // Path to install plugin to - pluginsPath: join(app.getPath("userData"), "plugins"), - }); - } - - /** - * Migrates the plugins by deleting the `plugins` directory in the user data path. - * If the `migrated_version` key in the `Store` object does not match the current app version, - * the function deletes the `plugins` directory and sets the `migrated_version` key to the current app version. - * @returns A Promise that resolves when the migration is complete. - */ - migratePlugins() { - return new Promise((resolve) => { - const store = new Store(); - if (store.get("migrated_version") !== app.getVersion()) { - console.debug("start migration:", store.get("migrated_version")); - const userDataPath = app.getPath("userData"); - const fullPath = join(userDataPath, "plugins"); - - rmdir(fullPath, { recursive: true }, function (err) { - if (err) console.error(err); - store.set("migrated_version", app.getVersion()); - console.debug("migrate plugins done"); - resolve(undefined); - }); - } else { - resolve(undefined); - } - }); - } -} diff --git a/server/managers/window.ts b/server/managers/window.ts deleted file mode 100644 index c930dd5ec..000000000 --- a/server/managers/window.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { BrowserWindow } from "electron"; - -/** - * Manages the current window instance. - */ -export class WindowManager { - public static instance: WindowManager = new WindowManager(); - public currentWindow?: BrowserWindow; - - constructor() { - if (WindowManager.instance) { - return WindowManager.instance; - } - } - - /** - * Creates a new window instance. - * @param {Electron.BrowserWindowConstructorOptions} options - The options to create the window with. - * @returns The created window instance. - */ - createWindow(options?: Electron.BrowserWindowConstructorOptions | undefined) { - this.currentWindow = new BrowserWindow({ - width: 1200, - minWidth: 800, - height: 800, - show: false, - trafficLightPosition: { - x: 10, - y: 15, - }, - titleBarStyle: "hidden", - vibrancy: "sidebar", - ...options, - }); - return this.currentWindow; - } -} diff --git a/server/nodemon.json b/server/nodemon.json new file mode 100644 index 000000000..0ea41ca96 --- /dev/null +++ b/server/nodemon.json @@ -0,0 +1,5 @@ +{ + "watch": ["main.ts", "v1"], + "ext": "ts, json", + "exec": "tsc && node ./build/main.js" +} \ No newline at end of file diff --git a/server/package.json b/server/package.json index 9523fa000..08c19ee31 100644 --- a/server/package.json +++ b/server/package.json @@ -51,26 +51,15 @@ "scripts": { "lint": "eslint . --ext \".js,.jsx,.ts,.tsx\"", "test:e2e": "playwright test --workers=1", - "dev": "tsc -p . && electron .", - "build": "run-script-os", - "build:test": "run-script-os", - "build:test:darwin": "tsc -p . && electron-builder -p never -m --dir", - "build:test:win32": "tsc -p . && electron-builder -p never -w --dir", - "build:test:linux": "tsc -p . && electron-builder -p never -l --dir", - "build:darwin": "tsc -p . && electron-builder -p never -m", - "build:win32": "tsc -p . && electron-builder -p never -w", - "build:linux": "tsc -p . && electron-builder -p never --linux deb", - "build:publish": "run-script-os", - "build:publish:darwin": "tsc -p . && electron-builder -p onTagOrDraft -m --x64 --arm64", - "build:publish:win32": "tsc -p . && electron-builder -p onTagOrDraft -w", - "build:publish:linux": "tsc -p . && electron-builder -p onTagOrDraft -l deb" + "dev": "nodemon .", + "build": "tsc", + "build:test": "", + "build:publish": "" }, "dependencies": { "@npmcli/arborist": "^7.1.0", "@types/request": "^2.48.12", "@uiball/loaders": "^1.3.0", - "electron-store": "^8.1.0", - "electron-updater": "^6.1.4", "express": "^4.18.2", "pacote": "^17.0.4", "request": "^2.88.2", @@ -78,7 +67,6 @@ "use-debounce": "^9.0.4" }, "devDependencies": { - "@electron/notarize": "^2.1.0", "@playwright/test": "^1.38.1", "@types/body-parser": "^1.19.5", "@types/express": "^4.17.21", @@ -86,10 +74,8 @@ "@types/pacote": "^11.1.7", "@typescript-eslint/eslint-plugin": "^6.7.3", "@typescript-eslint/parser": "^6.7.3", - "electron": "26.2.1", - "electron-builder": "^24.6.4", - "electron-playwright-helpers": "^1.6.0", "eslint-plugin-react": "^7.33.2", + "nodemon": "^3.0.1", "run-script-os": "^1.1.6" }, "installConfig": { diff --git a/server/tsconfig.json b/server/tsconfig.json index 3cc218f93..3363fdba6 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -15,6 +15,8 @@ "paths": { "*": ["node_modules/*"] }, "typeRoots": ["node_modules/@types"] }, + // "sourceMap": true, + "include": ["./**/*.ts"], "exclude": ["core", "build", "dist", "tests", "node_modules"] } diff --git a/server/utils/disposable.ts b/server/utils/disposable.ts deleted file mode 100644 index 462f7e3e5..000000000 --- a/server/utils/disposable.ts +++ /dev/null @@ -1,8 +0,0 @@ -export function dispose(requiredModules: Record) { - for (const key in requiredModules) { - const module = requiredModules[key]; - if (typeof module["dispose"] === "function") { - module["dispose"](); - } - } -} diff --git a/server/utils/menu.ts b/server/utils/menu.ts deleted file mode 100644 index 65e009aef..000000000 --- a/server/utils/menu.ts +++ /dev/null @@ -1,111 +0,0 @@ -// @ts-nocheck -const { app, Menu, dialog } = require("electron"); -const isMac = process.platform === "darwin"; -const { autoUpdater } = require("electron-updater"); -import { compareSemanticVersions } from "./versionDiff"; - -const template: (Electron.MenuItemConstructorOptions | Electron.MenuItem)[] = [ - ...(isMac - ? [ - { - label: app.name, - submenu: [ - { role: "about" }, - { - label: "Check for Updates...", - click: () => - autoUpdater.checkForUpdatesAndNotify().then((e) => { - if ( - !e || - compareSemanticVersions( - app.getVersion(), - e.updateInfo.version - ) >= 0 - ) - dialog.showMessageBox({ - message: `There are currently no updates available.`, - }); - }), - }, - { type: "separator" }, - { role: "services" }, - { type: "separator" }, - { role: "hide" }, - { role: "hideOthers" }, - { role: "unhide" }, - { type: "separator" }, - { role: "quit" }, - ], - }, - ] - : []), - { - label: "Edit", - submenu: [ - { role: "undo" }, - { role: "redo" }, - { type: "separator" }, - { role: "cut" }, - { role: "copy" }, - { role: "paste" }, - ...(isMac - ? [ - { role: "pasteAndMatchStyle" }, - { role: "delete" }, - { role: "selectAll" }, - { type: "separator" }, - { - label: "Speech", - submenu: [{ role: "startSpeaking" }, { role: "stopSpeaking" }], - }, - ] - : [{ role: "delete" }, { type: "separator" }, { role: "selectAll" }]), - ], - }, - { - label: "View", - submenu: [ - { role: "reload" }, - { role: "forceReload" }, - { role: "toggleDevTools" }, - { type: "separator" }, - { role: "resetZoom" }, - { role: "zoomIn" }, - { role: "zoomOut" }, - { type: "separator" }, - { role: "togglefullscreen" }, - ], - }, - { - label: "Window", - submenu: [ - { role: "minimize" }, - { role: "zoom" }, - ...(isMac - ? [ - { type: "separator" }, - { role: "front" }, - { type: "separator" }, - { role: "window" }, - ] - : [{ role: "close" }]), - ], - }, - { - role: "help", - submenu: [ - { - label: "Learn More", - click: async () => { - const { shell } = require("electron"); - await shell.openExternal("https://jan.ai/"); - }, - }, - ], - }, -]; - -export const setupMenu = () => { - const menu = Menu.buildFromTemplate(template); - Menu.setApplicationMenu(menu); -}; diff --git a/server/utils/versionDiff.ts b/server/utils/versionDiff.ts deleted file mode 100644 index 25934e87f..000000000 --- a/server/utils/versionDiff.ts +++ /dev/null @@ -1,21 +0,0 @@ -export const compareSemanticVersions = (a: string, b: string) => { - - // 1. Split the strings into their parts. - const a1 = a.split('.'); - const b1 = b.split('.'); - // 2. Contingency in case there's a 4th or 5th version - const len = Math.min(a1.length, b1.length); - // 3. Look through each version number and compare. - for (let i = 0; i < len; i++) { - const a2 = +a1[ i ] || 0; - const b2 = +b1[ i ] || 0; - - if (a2 !== b2) { - return a2 > b2 ? 1 : -1; - } - } - - // 4. We hit this if the all checked versions so far are equal - // - return b1.length - a1.length; -}; \ No newline at end of file diff --git a/server/v1/assistants/index.ts b/server/v1/assistants/index.ts new file mode 100644 index 000000000..7b51b801f --- /dev/null +++ b/server/v1/assistants/index.ts @@ -0,0 +1,5 @@ +import { Request, Response } from 'express' + +export default function route(req: Request, res: Response){ + +} \ No newline at end of file diff --git a/server/v1/chat/index.ts b/server/v1/chat/index.ts new file mode 100644 index 000000000..7b51b801f --- /dev/null +++ b/server/v1/chat/index.ts @@ -0,0 +1,5 @@ +import { Request, Response } from 'express' + +export default function route(req: Request, res: Response){ + +} \ No newline at end of file diff --git a/server/v1/index.ts b/server/v1/index.ts new file mode 100644 index 000000000..7528b917d --- /dev/null +++ b/server/v1/index.ts @@ -0,0 +1,20 @@ +import { Request, Response } from 'express' + +import assistantsAPI from './assistants' +import chatCompletionAPI from './chat' +import modelsAPI from './models' +import threadsAPI from './threads' + +export default function route(req: Request, res: Response){ + console.log(req.path.split("/")[1]) + switch (req.path.split("/")[1]){ + case 'assistants': + assistantsAPI(req, res) + case 'chat': + chatCompletionAPI(req, res) + case 'models': + modelsAPI(req, res) + case 'threads': + threadsAPI(req, res) + } +} \ No newline at end of file diff --git a/server/v1/models/downloadModel.ts b/server/v1/models/downloadModel.ts new file mode 100644 index 000000000..89db0cfce --- /dev/null +++ b/server/v1/models/downloadModel.ts @@ -0,0 +1,5 @@ +import { Request, Response } from 'express' + +export default function controller(req: Request, res: Response){ + +} \ No newline at end of file diff --git a/server/v1/models/index.ts b/server/v1/models/index.ts new file mode 100644 index 000000000..091e46283 --- /dev/null +++ b/server/v1/models/index.ts @@ -0,0 +1,18 @@ +import { Request, Response } from 'express' + +import downloadModelController from './downloadModel' + +function getModelController(req: Request, res: Response){ + +} + +export default function route(req: Request, res: Response){ + switch(req.method){ + case 'get': + getModelController(req, res) + break; + case 'post': + downloadModelController(req, res) + break; + } +} \ No newline at end of file diff --git a/server/v1/threads/index.ts b/server/v1/threads/index.ts new file mode 100644 index 000000000..7b51b801f --- /dev/null +++ b/server/v1/threads/index.ts @@ -0,0 +1,5 @@ +import { Request, Response } from 'express' + +export default function route(req: Request, res: Response){ + +} \ No newline at end of file From f5c19bccc5b05f26e34a2e753d2943e34a29d3fa Mon Sep 17 00:00:00 2001 From: Linh Tran Date: Fri, 1 Dec 2023 23:02:35 +0700 Subject: [PATCH 04/42] Switch to fastify + add model CRUD impl --- server/data/models/.gitkeep | 0 server/data/threads/.gitkeep | 0 server/main.ts | 29 ++++--------- server/package.json | 1 + server/v1/assistants/index.ts | 11 +++-- server/v1/chat/index.ts | 14 ++++-- server/v1/index.ts | 47 +++++++++++++------- server/v1/models/downloadModel.ts | 24 +++++++++-- server/v1/models/index.ts | 71 +++++++++++++++++++++++++------ server/v1/models/modelOp.ts | 11 +++++ server/v1/threads/index.ts | 9 ++-- 11 files changed, 154 insertions(+), 63 deletions(-) create mode 100644 server/data/models/.gitkeep create mode 100644 server/data/threads/.gitkeep create mode 100644 server/v1/models/modelOp.ts diff --git a/server/data/models/.gitkeep b/server/data/models/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/server/data/threads/.gitkeep b/server/data/threads/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/server/main.ts b/server/main.ts index 582af5c61..5466a27d8 100644 --- a/server/main.ts +++ b/server/main.ts @@ -1,28 +1,17 @@ -import express from 'express' -import bodyParser from 'body-parser' -import fs from 'fs' +import fastify from 'fastify' + import v1API from './v1' - const JAN_API_PORT = 1337; - -const server = express() -server.use(bodyParser.urlencoded()) -server.use(bodyParser.json()) +const server = fastify() const USER_ROOT_DIR = '.data' -server.use("/v1", v1API) +server.register(v1API, {prefix: "/api/v1"}) -// server.post("fs", (req, res) => { -// let op = req.body.op; -// switch(op){ -// case 'readFile': -// fs.readFile(req.body.path, ()=>{}) -// case 'writeFile': -// fs.writeFile(req.body.path, Buffer.from(req.body.data, "base64"), ()=>{}) -// } -// }) -server.listen(JAN_API_PORT, () => { - console.log(`JAN API listening at: http://localhost:${JAN_API_PORT}`); +server.listen({ + port: JAN_API_PORT, + host: "0.0.0.0" +}).then(()=>{ + console.log(`JAN API listening at: http://0.0.0.0:${JAN_API_PORT}`); }) diff --git a/server/package.json b/server/package.json index 08c19ee31..405f2bf5b 100644 --- a/server/package.json +++ b/server/package.json @@ -75,6 +75,7 @@ "@typescript-eslint/eslint-plugin": "^6.7.3", "@typescript-eslint/parser": "^6.7.3", "eslint-plugin-react": "^7.33.2", + "fastify": "^4.24.3", "nodemon": "^3.0.1", "run-script-os": "^1.1.6" }, diff --git a/server/v1/assistants/index.ts b/server/v1/assistants/index.ts index 7b51b801f..c722195d0 100644 --- a/server/v1/assistants/index.ts +++ b/server/v1/assistants/index.ts @@ -1,5 +1,8 @@ -import { Request, Response } from 'express' +import { FastifyInstance, FastifyPluginAsync, FastifyPluginOptions } from 'fastify' -export default function route(req: Request, res: Response){ - -} \ No newline at end of file +const router: FastifyPluginAsync = async (app: FastifyInstance, opts: FastifyPluginOptions) => { + //TODO: Add controllers for assistants here + // app.get("/", controller) + // app.post("/", controller) +} +export default router; \ No newline at end of file diff --git a/server/v1/chat/index.ts b/server/v1/chat/index.ts index 7b51b801f..cb5fbf120 100644 --- a/server/v1/chat/index.ts +++ b/server/v1/chat/index.ts @@ -1,5 +1,11 @@ -import { Request, Response } from 'express' +import { FastifyInstance, FastifyPluginAsync, FastifyPluginOptions } from 'fastify' -export default function route(req: Request, res: Response){ - -} \ No newline at end of file +const router: FastifyPluginAsync = async (app: FastifyInstance, opts: FastifyPluginOptions) => { + //TODO: Add controllers for here + // app.get("/", controller) + + app.post("/", (req, res) => { + req.body + }) +} +export default router; \ No newline at end of file diff --git a/server/v1/index.ts b/server/v1/index.ts index 7528b917d..8a153cbaf 100644 --- a/server/v1/index.ts +++ b/server/v1/index.ts @@ -1,20 +1,37 @@ -import { Request, Response } from 'express' - import assistantsAPI from './assistants' import chatCompletionAPI from './chat' import modelsAPI from './models' import threadsAPI from './threads' -export default function route(req: Request, res: Response){ - console.log(req.path.split("/")[1]) - switch (req.path.split("/")[1]){ - case 'assistants': - assistantsAPI(req, res) - case 'chat': - chatCompletionAPI(req, res) - case 'models': - modelsAPI(req, res) - case 'threads': - threadsAPI(req, res) - } -} \ No newline at end of file +import { FastifyInstance, FastifyPluginAsync } from 'fastify' + +const router: FastifyPluginAsync = async (app: FastifyInstance, opts) => { + app.register( + assistantsAPI, + { + prefix: "/assisstants" + } + ) + + app.register( + chatCompletionAPI, + { + prefix: "/chat/completion" + } + ) + + app.register( + modelsAPI, + { + prefix: "/models" + } + ) + + app.register( + threadsAPI, + { + prefix: "/threads" + } + ) +} +export default router; \ No newline at end of file diff --git a/server/v1/models/downloadModel.ts b/server/v1/models/downloadModel.ts index 89db0cfce..d564a2207 100644 --- a/server/v1/models/downloadModel.ts +++ b/server/v1/models/downloadModel.ts @@ -1,5 +1,23 @@ -import { Request, Response } from 'express' +import { RouteHandlerMethod, FastifyRequest, FastifyReply } from 'fastify' +import { MODEL_FOLDER_PATH } from "./index" +import fs from 'fs/promises' -export default function controller(req: Request, res: Response){ +const controller: RouteHandlerMethod = async (req: FastifyRequest, res: FastifyReply) => { + //TODO: download models impl + //Mirror logic from JanModelExtension.downloadModel? + let model = req.body.model; -} \ No newline at end of file + // Fetching logic + // const directoryPath = join(MODEL_FOLDER_PATH, model.id) + // await fs.mkdir(directoryPath) + + // const path = join(directoryPath, model.id) + // downloadFile(model.source_url, path) + // TODO: Different model downloader from different model vendor + + res.status(200).send({ + status: "Ok" + }) +} + +export default controller; \ No newline at end of file diff --git a/server/v1/models/index.ts b/server/v1/models/index.ts index 091e46283..22c551300 100644 --- a/server/v1/models/index.ts +++ b/server/v1/models/index.ts @@ -1,18 +1,61 @@ -import { Request, Response } from 'express' -import downloadModelController from './downloadModel' +export const MODEL_FOLDER_PATH = "./data/models" +export const _modelMetadataFileName = 'model.json' -function getModelController(req: Request, res: Response){ - -} +import fs from 'fs/promises' +import { Model } from '@janhq/core' +import { join } from 'path' -export default function route(req: Request, res: Response){ - switch(req.method){ - case 'get': - getModelController(req, res) - break; - case 'post': - downloadModelController(req, res) - break; +// map string => model object +let modelIndex = new Map(); +async function buildModelIndex(){ + let modelIds = await fs.readdir(MODEL_FOLDER_PATH); + // TODO: read modelFolders to get model info, mirror JanModelExtension? + try{ + for(let modelId in modelIds){ + let path = join(MODEL_FOLDER_PATH, modelId) + let fileData = await fs.readFile(join(path, _modelMetadataFileName)) + modelIndex.set(modelId, JSON.parse(fileData.toString("utf-8")) as Model) + } } -} \ No newline at end of file + catch(err){ + console.error("build model index failed. ", err); + } +} +buildModelIndex() + +import { FastifyInstance, FastifyPluginAsync, FastifyPluginOptions } from 'fastify' +import downloadModelController from './downloadModel' +import { startModel, stopModel } from './modelOp' + +const router: FastifyPluginAsync = async (app: FastifyInstance, opts: FastifyPluginOptions) => { + //TODO: Add controllers declaration here + + ///////////// CRUD //////////////// + // Model listing + app.get("/", async (req, res) => { + res.status(200).send( + modelIndex.values() + ) + }) + + // Retrieve model info + app.get("/:id", (req, res) => { + res.status(200).send( + modelIndex.get(req.params.id) + ) + }) + + // Delete model + app.delete("/:id", (req, res) => { + modelIndex.delete(req.params) + + // TODO: delete on disk + }) + + ///////////// Other ops //////////////// + app.post("/", downloadModelController) + app.put("/start", startModel) + app.put("/stop", stopModel) +} +export default router; \ No newline at end of file diff --git a/server/v1/models/modelOp.ts b/server/v1/models/modelOp.ts new file mode 100644 index 000000000..f2c7ffe75 --- /dev/null +++ b/server/v1/models/modelOp.ts @@ -0,0 +1,11 @@ +import {FastifyRequest, FastifyReply} from 'fastify' + +export async function startModel(req: FastifyRequest, res: FastifyReply): Promise { + + +} + +export async function stopModel(req: FastifyRequest, res: FastifyReply): Promise { + + +} \ No newline at end of file diff --git a/server/v1/threads/index.ts b/server/v1/threads/index.ts index 7b51b801f..e63f9e8d8 100644 --- a/server/v1/threads/index.ts +++ b/server/v1/threads/index.ts @@ -1,5 +1,8 @@ -import { Request, Response } from 'express' +import { FastifyInstance, FastifyPluginAsync, FastifyPluginOptions } from 'fastify' -export default function route(req: Request, res: Response){ +const router: FastifyPluginAsync = async (app: FastifyInstance, opts: FastifyPluginOptions) => { + //TODO: Add controllers declaration here -} \ No newline at end of file + // app.get() +} +export default router; \ No newline at end of file From fc6f8d2c0a2677660d572e20e067830a905930fe Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 11:41:30 +0700 Subject: [PATCH 05/42] decapriate some 70b models --- models/storytelling-70b/model.json | 24 ------------------------ models/xwin-70b/model.json | 24 ------------------------ models/yarn-70b/model.json | 21 --------------------- 3 files changed, 69 deletions(-) delete mode 100644 models/storytelling-70b/model.json delete mode 100644 models/xwin-70b/model.json delete mode 100644 models/yarn-70b/model.json diff --git a/models/storytelling-70b/model.json b/models/storytelling-70b/model.json deleted file mode 100644 index 76e6f7922..000000000 --- a/models/storytelling-70b/model.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "source_url": "https://huggingface.co/TheBloke/GOAT-70B-Storytelling-GGUF/resolve/main/goat-70b-storytelling.Q5_K_M.gguf", - "id": "storytelling-70b", - "object": "model", - "name": "Storytelling 70B", - "version": "1.0", - "description": "The GOAT-70B-Storytelling model is designed for autonomous story-writing, including crafting books and movie scripts. Based on the LLaMA 2 70B architecture, this model excels in generating cohesive and engaging narratives using inputs like plot outlines and character profiles.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "system_prompt": "", - "user_prompt": "### USER: ", - "ai_prompt": "\n### ASSISTANT: " - }, - "parameters": { - "max_tokens": 4096 - }, - "metadata": { - "author": "GOAT-AI, The Bloke", - "tags": ["General Use", "Writing"], - "size": 48750000000 - } - } - \ No newline at end of file diff --git a/models/xwin-70b/model.json b/models/xwin-70b/model.json deleted file mode 100644 index a5c1647b0..000000000 --- a/models/xwin-70b/model.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "source_url": "https://huggingface.co/TheBloke/Xwin-LM-70B-V0.1-GGUF/resolve/main/xwin-lm-70b-v0.1.Q5_K_M.gguf", - "id": "xwin-70b", - "object": "model", - "name": "Xwin LM 70B", - "version": "1.0", - "description": "Xwin-LM, based on Llama2 models, emphasizes alignment and exhibits advanced language understanding, text generation, and role-playing abilities.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "system_prompt": "", - "user_prompt": "USER: ", - "ai_prompt": "ASSISTANT: " - }, - "parameters": { - "max_tokens": 4096 - }, - "metadata": { - "author": "Xwin-LM, The Bloke", - "tags": ["General Use", "Role-playing"], - "size": 48750000000 - } - } - \ No newline at end of file diff --git a/models/yarn-70b/model.json b/models/yarn-70b/model.json deleted file mode 100644 index 67d8d3804..000000000 --- a/models/yarn-70b/model.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "source_url": "https://huggingface.co/TheBloke/Yarn-Llama-2-70B-32k-GGUF/resolve/main/yarn-llama-2-70b-32k.Q5_K_M.gguf", - "id": "yarn-70b", - "object": "model", - "name": "Yarn 32k 70B", - "version": "1,0", - "description": "Yarn-Llama-2-70b-32k is designed specifically for handling long contexts. It represents an extension of the Llama-2-70b-hf model, now supporting a 32k token context window.", - "format": "gguf", - "settings": { - "ctx_len": 4096 - }, - "parameters": { - "max_tokens": 4096 - }, - "metadata": { - "author": "NousResearch, The Bloke", - "tags": ["General Use", "Big Context Length"], - "size": 48750000000 - } - } - \ No newline at end of file From 2e96aacf55b4061dfb5ca5560e9691484a659728 Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 11:42:46 +0700 Subject: [PATCH 06/42] decapriate some 34b models --- models/dolphin-yi-34b/model.json | 24 ------------------------ models/lzlv-70b/model.json | 2 +- 2 files changed, 1 insertion(+), 25 deletions(-) delete mode 100644 models/dolphin-yi-34b/model.json diff --git a/models/dolphin-yi-34b/model.json b/models/dolphin-yi-34b/model.json deleted file mode 100644 index 3b1bf3619..000000000 --- a/models/dolphin-yi-34b/model.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "source_url": "https://huggingface.co/TheBloke/dolphin-2_2-yi-34b-GGUF/resolve/main/dolphin-2_2-yi-34b.Q5_K_M.gguf", - "id": "dolphin-yi-34b", - "object": "model", - "name": "Dolphin Yi 34B", - "version": "1.0", - "description": "Dolphin, based on the Yi-34B model and enhanced with features like conversation and empathy, is trained on a unique dataset for advanced multi-turn conversations. Notably uncensored, it requires careful implementation of an alignment layer for ethical use.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "system_prompt": "<|im_start|>system\n", - "user_prompt": "<|im_end|>\n<|im_start|>user\n", - "ai_prompt": "<|im_end|>\n<|im_start|>assistant\n" - }, - "parameters": { - "max_tokens": 4096 - }, - "metadata": { - "author": "ehartford, The Bloke", - "tags": ["General Use", "Role-playing"], - "size": 24320000000 - } - } - \ No newline at end of file diff --git a/models/lzlv-70b/model.json b/models/lzlv-70b/model.json index 4aaee79b3..166e3d8ed 100644 --- a/models/lzlv-70b/model.json +++ b/models/lzlv-70b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "lizpreciatior, The Bloke", - "tags": ["General Use", "Role-playing"], + "tags": ["Community Recommended", "General Use", "Role-playing"], "size": 48750000000 } } From 5cc8e0f9a9c5cc16ea2769a5337b9cab56f2ea87 Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 11:50:56 +0700 Subject: [PATCH 07/42] decapriate some small models --- models/capybara-34b/model.json | 4 ++-- models/deepseek-coder-1.3b/model.json | 2 +- models/islm-3b/model.json | 24 ------------------------ models/marx-3b/model.json | 23 ----------------------- models/mythomax-13b/model.json | 24 ------------------------ 5 files changed, 3 insertions(+), 74 deletions(-) delete mode 100644 models/islm-3b/model.json delete mode 100644 models/marx-3b/model.json delete mode 100644 models/mythomax-13b/model.json diff --git a/models/capybara-34b/model.json b/models/capybara-34b/model.json index 562bcbe93..d2da8d002 100644 --- a/models/capybara-34b/model.json +++ b/models/capybara-34b/model.json @@ -3,7 +3,7 @@ "id": "capybara-34b", "object": "model", "name": "Capybara 200k 34B", - "version": 1.0, + "version": "1.0", "description": "Nous Capybara 34B, a variant of the Yi-34B model, is the first Nous model with a 200K context length, trained for three epochs on the innovative Capybara dataset.", "format": "gguf", "settings": { @@ -17,7 +17,7 @@ }, "metadata": { "author": "NousResearch, The Bloke", - "tags": ["General", "Big Context Length"], + "tags": ["Community Recommended", "General Use", "Big Context Length"], "size": 24320000000 } } diff --git a/models/deepseek-coder-1.3b/model.json b/models/deepseek-coder-1.3b/model.json index 2ff6d6e7b..3ee705d20 100644 --- a/models/deepseek-coder-1.3b/model.json +++ b/models/deepseek-coder-1.3b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "deepseek, The Bloke", - "tags": ["Code"], + "tags": ["Community Recommended", "Code", "Small size"], "size": 870000000 } } diff --git a/models/islm-3b/model.json b/models/islm-3b/model.json deleted file mode 100644 index 916d7c50e..000000000 --- a/models/islm-3b/model.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "source_url": "https://huggingface.co/UmbrellaCorp/IS-LM-3B_GGUF/resolve/main/IS-LM-Q4_K_M.gguf", - "id": "islm-3b", - "object": "model", - "name": "IS LM 3B", - "version": "1.0", - "description": "IS LM 3B, based on the StableLM 3B model is specifically finetuned for economic analysis using DataForge Economics and QLoRA over three epochs, enhancing its proficiency in economic forecasting and analysis.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "system_prompt": "", - "user_prompt": "USER: ", - "ai_prompt": "ASSISTANT: " - }, - "parameters": { - "max_tokens": 4096 - }, - "metadata": { - "author": "UmbrellaCorp, The Bloke", - "tags": ["General Use", "Economics"], - "size": 1710000000 - } - } - \ No newline at end of file diff --git a/models/marx-3b/model.json b/models/marx-3b/model.json deleted file mode 100644 index 78617d5c3..000000000 --- a/models/marx-3b/model.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "source_url": "https://huggingface.co/TheBloke/Marx-3B-v3-GGUF/resolve/main/marx-3b-v3.Q4_K_M.gguf", - "id": "marx-3b", - "object": "model", - "name": "Marx 3B", - "version": "1.0", - "description": "Marx 3B, based on the StableLM 3B model is specifically finetuned for chating using EverythingLM data and QLoRA over two epochs, enhancing its proficiency in understand general knowledege.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "system_prompt": "", - "user_prompt": "### HUMAN: ", - "ai_prompt": "### RESPONSE: " - }, - "parameters": { - "max_tokens": 4096 - }, - "metadata": { - "author": "Bohan Du, The Bloke", - "tags": ["General Use"], - "size": 1620000000 - } - } \ No newline at end of file diff --git a/models/mythomax-13b/model.json b/models/mythomax-13b/model.json deleted file mode 100644 index 455f73968..000000000 --- a/models/mythomax-13b/model.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "source_url": "https://huggingface.co/TheBloke/MythoMax-L2-13B-GGUF/resolve/main/mythomax-l2-13b.Q5_K_M.gguf", - "id": "mythomax-13b", - "object": "model", - "name": "Mythomax L2 13B", - "version": "1.0", - "description": "Mythomax L2 13b, an advanced AI model derived from MythoMix, merges MythoLogic-L2's deep comprehension with Huginn's writing skills through a unique tensor merge technique, excelling in roleplaying and storytelling.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "system_prompt": "", - "user_prompt": "### Instruction: ", - "ai_prompt": "### Response: " - }, - "parameters": { - "max_tokens": 4096 - }, - "metadata": { - "author": "Gryphe, The Bloke", - "tags": ["Role-playing"], - "size": 9230000000 - } - } - \ No newline at end of file From 4440b58b15668b6538b87fa75b500e0d5c299815 Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 11:52:34 +0700 Subject: [PATCH 08/42] decapriate some 7B models --- models/openchat-7b/model.json | 24 ------------------------ models/openhermes-mistral-7b/model.json | 24 ------------------------ models/openorca-7b/model.json | 24 ------------------------ 3 files changed, 72 deletions(-) delete mode 100644 models/openchat-7b/model.json delete mode 100644 models/openhermes-mistral-7b/model.json delete mode 100644 models/openorca-7b/model.json diff --git a/models/openchat-7b/model.json b/models/openchat-7b/model.json deleted file mode 100644 index 1fd6bb259..000000000 --- a/models/openchat-7b/model.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "source_url": "https://huggingface.co/TheBloke/openchat_3.5-GGUF/resolve/main/openchat_3.5.Q4_K_M.gguf", - "id": "openchat-7b", - "object": "model", - "name": "Open Chat 3.5 7B", - "version": "1.0", - "description": "OpenChat represents a breakthrough in the realm of open-source language models. By implementing the C-RLFT fine-tuning strategy, inspired by offline reinforcement learning, this 7B model achieves results on par with ChatGPT (March).", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "system_prompt": "", - "user_prompt": "GPT4 User: ", - "ai_prompt": "<|end_of_turn|>\nGPT4 Assistant: " - }, - "parameters": { - "max_tokens": 4096 - }, - "metadata": { - "author": "OpenChat, The Bloke", - "tags": ["General", "Code"], - "size": 4370000000 - } - } - \ No newline at end of file diff --git a/models/openhermes-mistral-7b/model.json b/models/openhermes-mistral-7b/model.json deleted file mode 100644 index 6b64363d5..000000000 --- a/models/openhermes-mistral-7b/model.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "source_url": "https://huggingface.co/TheBloke/OpenHermes-2.5-Mistral-7B-GGUF/resolve/main/openhermes-2.5-mistral-7b.Q4_K_M.gguf", - "id": "openhermes-mistral-7b", - "object": "model", - "name": "Openhermes 2.5 Mistral 7B", - "version": "1.0", - "description": "The OpenHermes 2.5 Mistral 7B incorporates additional code datasets, more than a million GPT-4 generated data examples, and other high-quality open datasets. This enhancement led to significant improvement in benchmarks, highlighting its improved skill in handling code-centric tasks.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "system_prompt": "<|im_start|>system\n", - "user_prompt": "<|im_end|>\n<|im_start|>user\n", - "ai_prompt": "<|im_end|>\n<|im_start|>assistant\n" - }, - "parameters": { - "max_tokens": 4096 - }, - "metadata": { - "author": "Teknium, The Bloke", - "tags": ["General", "Roleplay"], - "size": 4370000000 - } - } - \ No newline at end of file diff --git a/models/openorca-7b/model.json b/models/openorca-7b/model.json deleted file mode 100644 index 42c88212c..000000000 --- a/models/openorca-7b/model.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "source_url": "https://huggingface.co/TheBloke/Mistral-7B-OpenOrca-GGUF/resolve/main/mistral-7b-openorca.Q4_K_M.gguf", - "id": "openorca-7b", - "object": "model", - "name": "OpenOrca 7B", - "version": "1.0", - "description": "OpenOrca 8k 7B is a model based on Mistral 7B, fine-tuned using the OpenOrca dataset. Notably ranked first on the HF Leaderboard for models under 30B, it excels in efficiency and accessibility.", - "format": "gguf", - "settings": { - "ctx_len": 4096, - "system_prompt": "<|im_start|>system\n", - "user_prompt": "<|im_end|>\n<|im_start|>user\n", - "ai_prompt": "<|im_end|>\n<|im_start|>assistant\n" - }, - "parameters": { - "max_tokens": 4096 - }, - "metadata": { - "author": "OpenOrca, The Bloke", - "tags": ["General", "Code"], - "size": 4370000000 - } - } - \ No newline at end of file From c27a1cc3796e86b2afe536a48c75c53459e6d5c3 Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 11:56:39 +0700 Subject: [PATCH 09/42] update tags for models --- models/neural-chat-7b/model.json | 2 +- models/neuralhermes-7b/model.json | 2 +- models/noromaid-20b/model.json | 2 +- models/openorca-13b/model.json | 2 +- models/phind-34b/model.json | 2 +- models/rocket-3b/model.json | 2 +- models/starling-7b/model.json | 2 +- models/tiefighter-13b/model.json | 2 +- models/tinyllama-1.1b/model.json | 2 +- models/wizardcoder-13b/model.json | 2 +- models/wizardcoder-34b/model.json | 2 +- models/yi-34b/model.json | 2 +- models/zephyr-beta-7b/model.json | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/models/neural-chat-7b/model.json b/models/neural-chat-7b/model.json index f4f4f14d4..a31662496 100644 --- a/models/neural-chat-7b/model.json +++ b/models/neural-chat-7b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Intel, The Bloke", - "tags": ["General Use", "Role-playing", "Big Context Length"], + "tags": ["Community Recommended", "General Use", "Role-playing", "Big Context Length"], "size": 4370000000 } } diff --git a/models/neuralhermes-7b/model.json b/models/neuralhermes-7b/model.json index 07cca58d4..3ec0c6253 100644 --- a/models/neuralhermes-7b/model.json +++ b/models/neuralhermes-7b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Intel, The Bloke", - "tags": ["General Use", "Code", "Big Context Length"], + "tags": ["Community Recommended", "General Use", "Code", "Big Context Length"], "size": 4370000000 } } diff --git a/models/noromaid-20b/model.json b/models/noromaid-20b/model.json index 86291e4f5..f0460568c 100644 --- a/models/noromaid-20b/model.json +++ b/models/noromaid-20b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "NeverSleep, The Bloke", - "tags": ["Role-playing"], + "tags": ["Community Recommended", "Role-playing"], "size": 12040000000 } } diff --git a/models/openorca-13b/model.json b/models/openorca-13b/model.json index 02a555430..5027dbd22 100644 --- a/models/openorca-13b/model.json +++ b/models/openorca-13b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Microsoft, The Bloke", - "tags": ["General Use"], + "tags": ["Community Recommended", "General Use"], "size": 9230000000 } } diff --git a/models/phind-34b/model.json b/models/phind-34b/model.json index 4391ae08d..18ed50bcc 100644 --- a/models/phind-34b/model.json +++ b/models/phind-34b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Phind, The Bloke", - "tags": ["Code", "Big Context Length"], + "tags": ["Community Recommended", "Code", "Big Context Length"], "size": 24320000000 } } diff --git a/models/rocket-3b/model.json b/models/rocket-3b/model.json index b00eb1f44..4eddb04b0 100644 --- a/models/rocket-3b/model.json +++ b/models/rocket-3b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "pansophic, The Bloke", - "tags": ["General Use"], + "tags": ["Community Recommended", "General Use"], "size": 1710000000 } } \ No newline at end of file diff --git a/models/starling-7b/model.json b/models/starling-7b/model.json index c029ea7d9..4ff5651e0 100644 --- a/models/starling-7b/model.json +++ b/models/starling-7b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Berkeley-nest, The Bloke", - "tags": ["General", "Code"], + "tags": ["Community Recommended", "General", "Code"], "size": 4370000000 } } diff --git a/models/tiefighter-13b/model.json b/models/tiefighter-13b/model.json index b1d354ce3..ea38fadbf 100644 --- a/models/tiefighter-13b/model.json +++ b/models/tiefighter-13b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "KoboldAI, The Bloke", - "tags": ["General Use", "Role-playing", "Writing"], + "tags": ["Community Recommended", "General Use", "Role-playing", "Writing"], "size": 9230000000 } } diff --git a/models/tinyllama-1.1b/model.json b/models/tinyllama-1.1b/model.json index f561eb25d..6f10fde02 100644 --- a/models/tinyllama-1.1b/model.json +++ b/models/tinyllama-1.1b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "TinyLlama", - "tags": ["General Use"], + "tags": ["Community Recommended", "General Use"], "size": 637000000 } } \ No newline at end of file diff --git a/models/wizardcoder-13b/model.json b/models/wizardcoder-13b/model.json index 944b5632b..9fe250348 100644 --- a/models/wizardcoder-13b/model.json +++ b/models/wizardcoder-13b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "WizardLM, The Bloke", - "tags": ["Code", "Big Context Length"], + "tags": ["Community Recommended", "Code", "Big Context Length"], "size": 9230000000 } } diff --git a/models/wizardcoder-34b/model.json b/models/wizardcoder-34b/model.json index aa2618e1b..db92a4fbf 100644 --- a/models/wizardcoder-34b/model.json +++ b/models/wizardcoder-34b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "WizardLM, The Bloke", - "tags": ["Code", "Big Context Length"], + "tags": ["Community Recommended", "Code", "Big Context Length"], "size": 24320000000 } } diff --git a/models/yi-34b/model.json b/models/yi-34b/model.json index f899bc54b..9bbe65760 100644 --- a/models/yi-34b/model.json +++ b/models/yi-34b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "01-ai, The Bloke", - "tags": ["General", "Role-playing", "Writing"], + "tags": ["Foundational Model", "General Use", "Role-playing", "Writing"], "size": 24320000000 } } diff --git a/models/zephyr-beta-7b/model.json b/models/zephyr-beta-7b/model.json index 24529bc9a..474dba766 100644 --- a/models/zephyr-beta-7b/model.json +++ b/models/zephyr-beta-7b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "HuggingFaceH4, The Bloke", - "tags": ["General Use", "Big Context Length"], + "tags": ["Community Recommended", "General Use", "Big Context Length"], "size": 4370000000 } } From 6a5458731991866cc2dafffcbbab9477d2283cf0 Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 12:26:50 +0700 Subject: [PATCH 10/42] update llama 2 7b chat --- models/capybara-34b/model.json | 4 ++-- models/deepseek-coder-1.3b/model.json | 4 ++-- models/llama2-chat-7b-q4/model.json | 24 ++++++++++++++++++++++++ models/llama2-chat-7b-q5/model.json | 24 ++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 models/llama2-chat-7b-q4/model.json create mode 100644 models/llama2-chat-7b-q5/model.json diff --git a/models/capybara-34b/model.json b/models/capybara-34b/model.json index d2da8d002..7c669bbb7 100644 --- a/models/capybara-34b/model.json +++ b/models/capybara-34b/model.json @@ -7,13 +7,13 @@ "description": "Nous Capybara 34B, a variant of the Yi-34B model, is the first Nous model with a 200K context length, trained for three epochs on the innovative Capybara dataset.", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "", "user_prompt": "USER: ", "ai_prompt": "ASSISTANT: " }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "NousResearch, The Bloke", diff --git a/models/deepseek-coder-1.3b/model.json b/models/deepseek-coder-1.3b/model.json index 3ee705d20..dac90423d 100644 --- a/models/deepseek-coder-1.3b/model.json +++ b/models/deepseek-coder-1.3b/model.json @@ -7,13 +7,13 @@ "description": "", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "", "user_prompt": "", "ai_prompt": "" }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "deepseek, The Bloke", diff --git a/models/llama2-chat-7b-q4/model.json b/models/llama2-chat-7b-q4/model.json new file mode 100644 index 000000000..be302d144 --- /dev/null +++ b/models/llama2-chat-7b-q4/model.json @@ -0,0 +1,24 @@ +{ + "source_url": "https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q4_K_M.gguf", + "id": "llama2-chat-7b-q4", + "object": "model", + "name": "Llama 2 Chat 7B Q4", + "version": "1.0", + "description": "This is a 4-bit quantized version of Meta AI's Llama 2 Chat 7b model.", + "format": "gguf", + "settings": { + "ctx_len": 2048, + "system_prompt": "[INST] <>\n", + "user_prompt": "<>\n", + "ai_prompt": "[/INST]" + }, + "parameters": { + "max_tokens": 2048 + }, + "metadata": { + "author": "MetaAI, The Bloke", + "tags": ["Foundational Model", "General", "Code"], + "size": 4080000000 + } + } + \ No newline at end of file diff --git a/models/llama2-chat-7b-q5/model.json b/models/llama2-chat-7b-q5/model.json new file mode 100644 index 000000000..8a93327d6 --- /dev/null +++ b/models/llama2-chat-7b-q5/model.json @@ -0,0 +1,24 @@ +{ + "source_url": "https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q5_K_M.gguf", + "id": "llama2-chat-7b-q5", + "object": "model", + "name": "Llama 2 Chat 7B Q5", + "version": "1.0", + "description": "This is a 5-bit quantized version of Meta AI's Llama 2 Chat 7b model.", + "format": "gguf", + "settings": { + "ctx_len": 2048, + "system_prompt": "[INST] <>\n", + "user_prompt": "<>\n", + "ai_prompt": "[/INST]" + }, + "parameters": { + "max_tokens": 2048 + }, + "metadata": { + "author": "MetaAI, The Bloke", + "tags": ["Foundational Model", "General", "Code"], + "size": 4780000000 + } + } + \ No newline at end of file From dbc12d27c89f31e1939150344cac57885c8025ee Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 12:32:56 +0700 Subject: [PATCH 11/42] update mistral 7b chat --- models/lzlv-70b/model.json | 4 ++-- models/mistral-ins-7b-q4/model.json | 24 ++++++++++++++++++++++++ models/mistral-ins-7b-q5/model.json | 24 ++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 models/mistral-ins-7b-q4/model.json create mode 100644 models/mistral-ins-7b-q5/model.json diff --git a/models/lzlv-70b/model.json b/models/lzlv-70b/model.json index 166e3d8ed..98d581f24 100644 --- a/models/lzlv-70b/model.json +++ b/models/lzlv-70b/model.json @@ -7,13 +7,13 @@ "description": "lzlv_70B is a sophisticated AI model designed for roleplaying and creative tasks. This merge aims to combine intelligence with creativity, seemingly outperforming its individual components in complex scenarios and creative outputs.", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "", "user_prompt": "USER: ", "ai_prompt": "ASSISTANT: " }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "lizpreciatior, The Bloke", diff --git a/models/mistral-ins-7b-q4/model.json b/models/mistral-ins-7b-q4/model.json new file mode 100644 index 000000000..51b5c231e --- /dev/null +++ b/models/mistral-ins-7b-q4/model.json @@ -0,0 +1,24 @@ +{ + "source_url": "https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.1-GGUF/resolve/main/mistral-7b-instruct-v0.1.Q4_K_M.gguf", + "id": "mistral-ins-7b-q4", + "object": "model", + "name": "Mistral Instruct 7B Q4", + "version": "1.0", + "description": "This is a 4-bit quantized version of MistralAI's Mistral Instruct 7B model.", + "format": "gguf", + "settings": { + "ctx_len": 2048, + "system_prompt": "", + "user_prompt": "[INST]", + "ai_prompt": "[/INST]" + }, + "parameters": { + "max_tokens": 2048 + }, + "metadata": { + "author": "MistralAI, The Bloke", + "tags": ["Foundational Model", "General", "Code"], + "size": 4370000000 + } + } + \ No newline at end of file diff --git a/models/mistral-ins-7b-q5/model.json b/models/mistral-ins-7b-q5/model.json new file mode 100644 index 000000000..46c5f5378 --- /dev/null +++ b/models/mistral-ins-7b-q5/model.json @@ -0,0 +1,24 @@ +{ + "source_url": "https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.1-GGUF/resolve/main/mistral-7b-instruct-v0.1.Q5_K_M.gguf", + "id": "mistral-ins-7b-q5", + "object": "model", + "name": "Mistral Instruct 7B Q5", + "version": "1.0", + "description": "This is a 5-bit quantized version of MistralAI's Mistral Instruct 7B model.", + "format": "gguf", + "settings": { + "ctx_len": 2048, + "system_prompt": "", + "user_prompt": "[INST]", + "ai_prompt": "[/INST]" + }, + "parameters": { + "max_tokens": 2048 + }, + "metadata": { + "author": "MistralAI, The Bloke", + "tags": ["Foundational Model", "General", "Code"], + "size": 5130000000 + } + } + \ No newline at end of file From 88e37e1f2d6d3b0c0e0f91bcf615233a2ccdbd2f Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 12:34:10 +0700 Subject: [PATCH 12/42] update ctxlen --- models/neural-chat-7b/model.json | 4 ++-- models/neuralhermes-7b/model.json | 4 ++-- models/noromaid-20b/model.json | 4 ++-- models/openorca-13b/model.json | 4 ++-- models/phind-34b/model.json | 4 ++-- models/rocket-3b/model.json | 2 +- models/starling-7b/model.json | 4 ++-- models/tiefighter-13b/model.json | 4 ++-- models/wizardcoder-13b/model.json | 4 ++-- models/wizardcoder-34b/model.json | 4 ++-- models/yi-34b/model.json | 4 ++-- models/zephyr-beta-7b/model.json | 4 ++-- 12 files changed, 23 insertions(+), 23 deletions(-) diff --git a/models/neural-chat-7b/model.json b/models/neural-chat-7b/model.json index a31662496..84c8d029f 100644 --- a/models/neural-chat-7b/model.json +++ b/models/neural-chat-7b/model.json @@ -7,13 +7,13 @@ "description": "The Neural Chat 7B model, developed on the foundation of mistralai/Mistral-7B-v0.1, has been fine-tuned using the Open-Orca/SlimOrca dataset and aligned with the Direct Preference Optimization (DPO) algorithm. It has demonstrated substantial improvements in various AI tasks and performance well on the open_llm_leaderboard.", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "### System: ", "user_prompt": "### User: ", "ai_prompt": "### Assistant: " }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "Intel, The Bloke", diff --git a/models/neuralhermes-7b/model.json b/models/neuralhermes-7b/model.json index 3ec0c6253..0cc83d7fb 100644 --- a/models/neuralhermes-7b/model.json +++ b/models/neuralhermes-7b/model.json @@ -7,13 +7,13 @@ "description": "NeuralHermes 2.5 has been enhanced using Direct Preference Optimization. This fine-tuning, inspired by the RLHF process of Neural-chat-7b and OpenHermes-2.5-Mistral-7B, has led to improved performance across several benchmarks.", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "<|im_start|>system\n", "user_prompt": "<|im_end|>\n<|im_start|>user\n", "ai_prompt": "<|im_end|>\n<|im_start|>assistant\n" }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "Intel, The Bloke", diff --git a/models/noromaid-20b/model.json b/models/noromaid-20b/model.json index f0460568c..ff2b91c1d 100644 --- a/models/noromaid-20b/model.json +++ b/models/noromaid-20b/model.json @@ -7,13 +7,13 @@ "description": "The Noromaid 20b model is designed for role-playing and general use, featuring a unique touch with the no_robots dataset that enhances human-like behavior.", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "", "user_prompt": "### Instruction: ", "ai_prompt": "### Response: " }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "NeverSleep, The Bloke", diff --git a/models/openorca-13b/model.json b/models/openorca-13b/model.json index 5027dbd22..13b6abf29 100644 --- a/models/openorca-13b/model.json +++ b/models/openorca-13b/model.json @@ -7,13 +7,13 @@ "description": "Orca 2 is a finetuned version of LLAMA-2, designed primarily for single-turn responses in reasoning, reading comprehension, math problem solving, and text summarization.", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "<|im_start|>system\n", "user_prompt": "<|im_end|>\n<|im_start|>user\n", "ai_prompt": "<|im_end|>\n<|im_start|>assistant\n" }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "Microsoft, The Bloke", diff --git a/models/phind-34b/model.json b/models/phind-34b/model.json index 18ed50bcc..761c51346 100644 --- a/models/phind-34b/model.json +++ b/models/phind-34b/model.json @@ -7,13 +7,13 @@ "description": "Phind-CodeLlama-34B-v2 is an AI model fine-tuned on 1.5B tokens of high-quality programming data. It's a SOTA open-source model in coding. This multi-lingual model excels in various programming languages, including Python, C/C++, TypeScript, Java, and is designed to be steerable and user-friendly.", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "### System Prompt\n", "user_prompt": "### User Message\n", "ai_prompt": "### Assistant\n" }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "Phind, The Bloke", diff --git a/models/rocket-3b/model.json b/models/rocket-3b/model.json index 4eddb04b0..a70db1dbd 100644 --- a/models/rocket-3b/model.json +++ b/models/rocket-3b/model.json @@ -13,7 +13,7 @@ "ai_prompt": "<|im_end|>\n<|im_start|>assistant\n" }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "pansophic, The Bloke", diff --git a/models/starling-7b/model.json b/models/starling-7b/model.json index 4ff5651e0..cf8aeda18 100644 --- a/models/starling-7b/model.json +++ b/models/starling-7b/model.json @@ -7,13 +7,13 @@ "description": "Starling-RM-7B-alpha is a language model finetuned with Reinforcement Learning from AI Feedback from Openchat 3.5. It stands out for its impressive performance using GPT-4 as a judge, making it one of the top-performing models in its category.", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "", "user_prompt": "GPT4 User: ", "ai_prompt": "<|end_of_turn|>\nGPT4 Assistant: " }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "Berkeley-nest, The Bloke", diff --git a/models/tiefighter-13b/model.json b/models/tiefighter-13b/model.json index ea38fadbf..4dd9bb37f 100644 --- a/models/tiefighter-13b/model.json +++ b/models/tiefighter-13b/model.json @@ -7,13 +7,13 @@ "description": "Tiefighter-13B is a highly creative, merged AI model achieved by combining various 'LORAs' on top of an existing merge, particularly focusing on storytelling and improvisation. This model excels in story writing, chatbots, and adventuring, and is designed to perform better with less detailed inputs, leveraging its inherent creativity.", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "", "user_prompt": "### Instruction: ", "ai_prompt": "\n### Response: " }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "KoboldAI, The Bloke", diff --git a/models/wizardcoder-13b/model.json b/models/wizardcoder-13b/model.json index 9fe250348..47899534a 100644 --- a/models/wizardcoder-13b/model.json +++ b/models/wizardcoder-13b/model.json @@ -7,13 +7,13 @@ "description": "WizardCoder-Python-13B is a Python coding model major models like ChatGPT-3.5. This model based on the Llama2 architecture, demonstrate high proficiency in specific domains like coding and mathematics.", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "", "user_prompt": "### Instruction:\n", "ai_prompt": "### Response:\n" }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "WizardLM, The Bloke", diff --git a/models/wizardcoder-34b/model.json b/models/wizardcoder-34b/model.json index db92a4fbf..f564afc35 100644 --- a/models/wizardcoder-34b/model.json +++ b/models/wizardcoder-34b/model.json @@ -7,13 +7,13 @@ "description": "WizardCoder-Python-34B is a Python coding model major models like ChatGPT-3.5. This model based on the Llama2 architecture, demonstrate high proficiency in specific domains like coding and mathematics.", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "", "user_prompt": "### Instruction:\n", "ai_prompt": "### Response:\n" }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "WizardLM, The Bloke", diff --git a/models/yi-34b/model.json b/models/yi-34b/model.json index 9bbe65760..d34c0efed 100644 --- a/models/yi-34b/model.json +++ b/models/yi-34b/model.json @@ -7,13 +7,13 @@ "description": "Yi-34B, a specialized chat model, is known for its diverse and creative responses and excels across various NLP tasks and benchmarks.", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "<|im_start|>system\n", "user_prompt": "<|im_end|>\n<|im_start|>user\n", "ai_prompt": "<|im_end|>\n<|im_start|>assistant\n" }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "01-ai, The Bloke", diff --git a/models/zephyr-beta-7b/model.json b/models/zephyr-beta-7b/model.json index 474dba766..70c7c72e8 100644 --- a/models/zephyr-beta-7b/model.json +++ b/models/zephyr-beta-7b/model.json @@ -7,13 +7,13 @@ "description": "The Zephyr-7B-β model marks the second iteration in the Zephyr series, designed to function as an effective assistant. It has been fine-tuned from the mistralai/Mistral-7B-v0.1 base model, utilizing a combination of public and synthetic datasets with the application of Direct Preference Optimization.", "format": "gguf", "settings": { - "ctx_len": 4096, + "ctx_len": 2048, "system_prompt": "<|system|>\n", "user_prompt": "\n<|user|>\n", "ai_prompt": "\n<|assistant|>\n" }, "parameters": { - "max_tokens": 4096 + "max_tokens": 2048 }, "metadata": { "author": "HuggingFaceH4, The Bloke", From fc2af712e405d977d33f2873ec6f18ddb1062938 Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 12:35:53 +0700 Subject: [PATCH 13/42] update llama2 70b chat --- models/llama2-chat-70b-q4/model.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 models/llama2-chat-70b-q4/model.json diff --git a/models/llama2-chat-70b-q4/model.json b/models/llama2-chat-70b-q4/model.json new file mode 100644 index 000000000..39c0f6474 --- /dev/null +++ b/models/llama2-chat-70b-q4/model.json @@ -0,0 +1,24 @@ +{ + "source_url": "https://huggingface.co/TheBloke/Llama-2-70B-Chat-GGUF/resolve/main/llama-2-70b-chat.Q4_K_M.gguf", + "id": "llama2-chat-70b-q4", + "object": "model", + "name": "Llama 2 Chat 70B Q4", + "version": "1.0", + "description": "This is a 4-bit quantized version of Meta AI's Llama 2 Chat 70b model.", + "format": "gguf", + "settings": { + "ctx_len": 2048, + "system_prompt": "[INST] <>\n", + "user_prompt": "<>\n", + "ai_prompt": "[/INST]" + }, + "parameters": { + "max_tokens": 2048 + }, + "metadata": { + "author": "MetaAI, The Bloke", + "tags": ["Foundational Model", "General", "Code"], + "size": 4080000000 + } + } + \ No newline at end of file From 43b538e800a7469a3f25eceab1d97e8a7eb61c90 Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 14:13:00 +0700 Subject: [PATCH 14/42] update openhermes 7b --- models/capybara-34b/model.json | 4 ++-- models/lzlv-70b/model.json | 4 ++-- models/neural-chat-7b/model.json | 6 +++--- .../{neuralhermes-7b => openhermes-neural-7b}/model.json | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) rename models/{neuralhermes-7b => openhermes-neural-7b}/model.json (52%) diff --git a/models/capybara-34b/model.json b/models/capybara-34b/model.json index 7c669bbb7..74eb27eb9 100644 --- a/models/capybara-34b/model.json +++ b/models/capybara-34b/model.json @@ -9,8 +9,8 @@ "settings": { "ctx_len": 2048, "system_prompt": "", - "user_prompt": "USER: ", - "ai_prompt": "ASSISTANT: " + "user_prompt": "USER:\n", + "ai_prompt": "ASSISTANT:\n" }, "parameters": { "max_tokens": 2048 diff --git a/models/lzlv-70b/model.json b/models/lzlv-70b/model.json index 98d581f24..844bdadf4 100644 --- a/models/lzlv-70b/model.json +++ b/models/lzlv-70b/model.json @@ -9,8 +9,8 @@ "settings": { "ctx_len": 2048, "system_prompt": "", - "user_prompt": "USER: ", - "ai_prompt": "ASSISTANT: " + "user_prompt": "USER:\n", + "ai_prompt": "ASSISTANT:\n" }, "parameters": { "max_tokens": 2048 diff --git a/models/neural-chat-7b/model.json b/models/neural-chat-7b/model.json index 84c8d029f..cac717b8a 100644 --- a/models/neural-chat-7b/model.json +++ b/models/neural-chat-7b/model.json @@ -8,9 +8,9 @@ "format": "gguf", "settings": { "ctx_len": 2048, - "system_prompt": "### System: ", - "user_prompt": "### User: ", - "ai_prompt": "### Assistant: " + "system_prompt": "### System:\n", + "user_prompt": "### User:\n", + "ai_prompt": "### Assistant:\n" }, "parameters": { "max_tokens": 2048 diff --git a/models/neuralhermes-7b/model.json b/models/openhermes-neural-7b/model.json similarity index 52% rename from models/neuralhermes-7b/model.json rename to models/openhermes-neural-7b/model.json index 0cc83d7fb..cd4394dc5 100644 --- a/models/neuralhermes-7b/model.json +++ b/models/openhermes-neural-7b/model.json @@ -1,10 +1,10 @@ { - "source_url": "https://huggingface.co/TheBloke/NeuralHermes-2.5-Mistral-7B-GGUF/resolve/main/neuralhermes-2.5-mistral-7b.Q4_K_M.gguf", - "id": "neuralhermes-7b", + "source_url": "https://huggingface.co/TheBloke/OpenHermes-2.5-neural-chat-7B-v3-2-7B-GGUF/resolve/main/openhermes-2.5-neural-chat-7b-v3-2-7b.Q4_K_M.gguf", + "id": "openhermes-neural-7b", "object": "model", - "name": "NeuralHermes 7B", + "name": "OpenHermes Neural 7B", "version": "1.0", - "description": "NeuralHermes 2.5 has been enhanced using Direct Preference Optimization. This fine-tuning, inspired by the RLHF process of Neural-chat-7b and OpenHermes-2.5-Mistral-7B, has led to improved performance across several benchmarks.", + "description": "OpenHermes Neural is a merged model from OpenHermes-2.5-Mistral-7B and neural-chat-7b-v3-2 with the TIES method.", "format": "gguf", "settings": { "ctx_len": 2048, From 23a6ecdd890be73e04d0ffe990fc81e9b06d8fe0 Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 14:14:43 +0700 Subject: [PATCH 15/42] update tags --- models/openhermes-neural-7b/model.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/openhermes-neural-7b/model.json b/models/openhermes-neural-7b/model.json index cd4394dc5..e9e26706c 100644 --- a/models/openhermes-neural-7b/model.json +++ b/models/openhermes-neural-7b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Intel, The Bloke", - "tags": ["Community Recommended", "General Use", "Code", "Big Context Length"], + "tags": ["Community Recommended", "General Use", "Code", "Merged"], "size": 4370000000 } } From 84c940be47d118759a129b66ff80eb2cae1659c2 Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 14:28:36 +0700 Subject: [PATCH 16/42] update prompt templte --- models/noromaid-20b/model.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/models/noromaid-20b/model.json b/models/noromaid-20b/model.json index ff2b91c1d..61870e855 100644 --- a/models/noromaid-20b/model.json +++ b/models/noromaid-20b/model.json @@ -9,8 +9,8 @@ "settings": { "ctx_len": 2048, "system_prompt": "", - "user_prompt": "### Instruction: ", - "ai_prompt": "### Response: " + "user_prompt": "### Instruction:\n", + "ai_prompt": "### Response:\n" }, "parameters": { "max_tokens": 2048 From 7017e6426d4ea022a6bc6197c531e3560fc3767a Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 16:22:42 +0700 Subject: [PATCH 17/42] update name for models --- models/capybara-34b/model.json | 2 +- models/deepseek-coder-1.3b/model.json | 4 ++-- models/llama2-chat-70b-q4/model.json | 2 +- models/llama2-chat-7b-q4/model.json | 2 +- models/llama2-chat-7b-q5/model.json | 2 +- models/lzlv-70b/model.json | 2 +- models/mistral-ins-7b-q4/model.json | 2 +- models/mistral-ins-7b-q5/model.json | 2 +- models/neural-chat-7b/model.json | 2 +- models/noromaid-20b/model.json | 2 +- models/openhermes-neural-7b/model.json | 2 +- models/openorca-13b/model.json | 2 +- models/phind-34b/model.json | 2 +- models/rocket-3b/model.json | 2 +- models/starling-7b/model.json | 2 +- models/tiefighter-13b/model.json | 2 +- models/tinyllama-1.1b/model.json | 2 +- models/wizardcoder-13b/model.json | 2 +- models/wizardcoder-34b/model.json | 2 +- models/yi-34b/model.json | 2 +- models/zephyr-beta-7b/model.json | 4 ++-- 21 files changed, 23 insertions(+), 23 deletions(-) diff --git a/models/capybara-34b/model.json b/models/capybara-34b/model.json index 74eb27eb9..e5834a66d 100644 --- a/models/capybara-34b/model.json +++ b/models/capybara-34b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/Nous-Capybara-34B-GGUF/resolve/main/nous-capybara-34b.Q5_K_M.gguf", "id": "capybara-34b", "object": "model", - "name": "Capybara 200k 34B", + "name": "Capybara 200k 34B Q5", "version": "1.0", "description": "Nous Capybara 34B, a variant of the Yi-34B model, is the first Nous model with a 200K context length, trained for three epochs on the innovative Capybara dataset.", "format": "gguf", diff --git a/models/deepseek-coder-1.3b/model.json b/models/deepseek-coder-1.3b/model.json index dac90423d..9d22f9558 100644 --- a/models/deepseek-coder-1.3b/model.json +++ b/models/deepseek-coder-1.3b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/deepseek-coder-1.3b-base-GGUF/resolve/main/deepseek-coder-1.3b-base.Q4_K_M.gguf", "id": "deepseek-coder-1.3b", "object": "model", - "name": "Deepseek Coder 1.3B", + "name": "Deepseek Coder 1.3B Q4", "version": "1.0", "description": "", "format": "gguf", @@ -16,7 +16,7 @@ "max_tokens": 2048 }, "metadata": { - "author": "deepseek, The Bloke", + "author": "Deepseek, The Bloke", "tags": ["Community Recommended", "Code", "Small size"], "size": 870000000 } diff --git a/models/llama2-chat-70b-q4/model.json b/models/llama2-chat-70b-q4/model.json index 39c0f6474..4ab3ac555 100644 --- a/models/llama2-chat-70b-q4/model.json +++ b/models/llama2-chat-70b-q4/model.json @@ -18,7 +18,7 @@ "metadata": { "author": "MetaAI, The Bloke", "tags": ["Foundational Model", "General", "Code"], - "size": 4080000000 + "size": 43920000000 } } \ No newline at end of file diff --git a/models/llama2-chat-7b-q4/model.json b/models/llama2-chat-7b-q4/model.json index be302d144..7b52e1767 100644 --- a/models/llama2-chat-7b-q4/model.json +++ b/models/llama2-chat-7b-q4/model.json @@ -4,7 +4,7 @@ "object": "model", "name": "Llama 2 Chat 7B Q4", "version": "1.0", - "description": "This is a 4-bit quantized version of Meta AI's Llama 2 Chat 7b model.", + "description": "This is a 4-bit quantized iteration of Meta AI's Llama 2 Chat 7b model, specifically designed for a comprehensive understanding through training on extensive internet data.", "format": "gguf", "settings": { "ctx_len": 2048, diff --git a/models/llama2-chat-7b-q5/model.json b/models/llama2-chat-7b-q5/model.json index 8a93327d6..b19213e46 100644 --- a/models/llama2-chat-7b-q5/model.json +++ b/models/llama2-chat-7b-q5/model.json @@ -4,7 +4,7 @@ "object": "model", "name": "Llama 2 Chat 7B Q5", "version": "1.0", - "description": "This is a 5-bit quantized version of Meta AI's Llama 2 Chat 7b model.", + "description": "This is a 5-bit quantized iteration of Meta AI's Llama 2 Chat 7b model, specifically designed for a comprehensive understanding through training on extensive internet data.", "format": "gguf", "settings": { "ctx_len": 2048, diff --git a/models/lzlv-70b/model.json b/models/lzlv-70b/model.json index 844bdadf4..e4247eb88 100644 --- a/models/lzlv-70b/model.json +++ b/models/lzlv-70b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/lzlv_70B-GGUF/resolve/main/lzlv_70b_fp16_hf.Q5_K_M.gguf", "id": "lzlv-70b", "object": "model", - "name": "Lzlv 70B", + "name": "Lzlv 70B Q4", "version": "1.0", "description": "lzlv_70B is a sophisticated AI model designed for roleplaying and creative tasks. This merge aims to combine intelligence with creativity, seemingly outperforming its individual components in complex scenarios and creative outputs.", "format": "gguf", diff --git a/models/mistral-ins-7b-q4/model.json b/models/mistral-ins-7b-q4/model.json index 51b5c231e..dd3360700 100644 --- a/models/mistral-ins-7b-q4/model.json +++ b/models/mistral-ins-7b-q4/model.json @@ -4,7 +4,7 @@ "object": "model", "name": "Mistral Instruct 7B Q4", "version": "1.0", - "description": "This is a 4-bit quantized version of MistralAI's Mistral Instruct 7B model.", + "description": "This is a 4-bit quantized iteration of MistralAI's Mistral Instruct 7b model, specifically designed for a comprehensive understanding through training on extensive internet data.", "format": "gguf", "settings": { "ctx_len": 2048, diff --git a/models/mistral-ins-7b-q5/model.json b/models/mistral-ins-7b-q5/model.json index 46c5f5378..5b86ab538 100644 --- a/models/mistral-ins-7b-q5/model.json +++ b/models/mistral-ins-7b-q5/model.json @@ -4,7 +4,7 @@ "object": "model", "name": "Mistral Instruct 7B Q5", "version": "1.0", - "description": "This is a 5-bit quantized version of MistralAI's Mistral Instruct 7B model.", + "description": "This is a 5-bit quantized iteration of MistralAI's Mistral Instruct 7b model, specifically designed for a comprehensive understanding through training on extensive internet data.", "format": "gguf", "settings": { "ctx_len": 2048, diff --git a/models/neural-chat-7b/model.json b/models/neural-chat-7b/model.json index cac717b8a..234a2ff80 100644 --- a/models/neural-chat-7b/model.json +++ b/models/neural-chat-7b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/neural-chat-7B-v3-1-GGUF/resolve/main/neural-chat-7b-v3-1.Q4_K_M.gguf", "id": "neural-chat-7b", "object": "model", - "name": "Neural Chat 7B", + "name": "Neural Chat 7B Q4", "version": "1.0", "description": "The Neural Chat 7B model, developed on the foundation of mistralai/Mistral-7B-v0.1, has been fine-tuned using the Open-Orca/SlimOrca dataset and aligned with the Direct Preference Optimization (DPO) algorithm. It has demonstrated substantial improvements in various AI tasks and performance well on the open_llm_leaderboard.", "format": "gguf", diff --git a/models/noromaid-20b/model.json b/models/noromaid-20b/model.json index 61870e855..da69cba3e 100644 --- a/models/noromaid-20b/model.json +++ b/models/noromaid-20b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/Noromaid-20B-v0.1.1-GGUF/resolve/main/noromaid-20b-v0.1.1.Q4_K_M.gguf", "id": "noromaid-20b", "object": "model", - "name": "Noromaid 20B", + "name": "Noromaid 20B Q4", "version": "1.0", "description": "The Noromaid 20b model is designed for role-playing and general use, featuring a unique touch with the no_robots dataset that enhances human-like behavior.", "format": "gguf", diff --git a/models/openhermes-neural-7b/model.json b/models/openhermes-neural-7b/model.json index e9e26706c..a7366f85b 100644 --- a/models/openhermes-neural-7b/model.json +++ b/models/openhermes-neural-7b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/OpenHermes-2.5-neural-chat-7B-v3-2-7B-GGUF/resolve/main/openhermes-2.5-neural-chat-7b-v3-2-7b.Q4_K_M.gguf", "id": "openhermes-neural-7b", "object": "model", - "name": "OpenHermes Neural 7B", + "name": "OpenHermes Neural 7B Q4", "version": "1.0", "description": "OpenHermes Neural is a merged model from OpenHermes-2.5-Mistral-7B and neural-chat-7b-v3-2 with the TIES method.", "format": "gguf", diff --git a/models/openorca-13b/model.json b/models/openorca-13b/model.json index 13b6abf29..edfef0807 100644 --- a/models/openorca-13b/model.json +++ b/models/openorca-13b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/Orca-2-13B-GGUF/resolve/main/orca-2-13b.Q5_K_M.gguf", "id": "openorca-13b", "object": "model", - "name": "Orca 2 13B", + "name": "Orca 2 13B Q5", "version": "1.0", "description": "Orca 2 is a finetuned version of LLAMA-2, designed primarily for single-turn responses in reasoning, reading comprehension, math problem solving, and text summarization.", "format": "gguf", diff --git a/models/phind-34b/model.json b/models/phind-34b/model.json index 761c51346..8de7a84d0 100644 --- a/models/phind-34b/model.json +++ b/models/phind-34b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/Phind-CodeLlama-34B-v2-GGUF/resolve/main/phind-codellama-34b-v2.Q5_K_M.gguf", "id": "phind-34b", "object": "model", - "name": "Phind 34B", + "name": "Phind 34B Q5", "version": "1.0", "description": "Phind-CodeLlama-34B-v2 is an AI model fine-tuned on 1.5B tokens of high-quality programming data. It's a SOTA open-source model in coding. This multi-lingual model excels in various programming languages, including Python, C/C++, TypeScript, Java, and is designed to be steerable and user-friendly.", "format": "gguf", diff --git a/models/rocket-3b/model.json b/models/rocket-3b/model.json index a70db1dbd..7435bfafb 100644 --- a/models/rocket-3b/model.json +++ b/models/rocket-3b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/rocket-3B-GGUF/resolve/main/rocket-3b.Q4_K_M.gguf", "id": "rocket-3b", "object": "model", - "name": "Rocket 3B", + "name": "Rocket 3B Q4", "version": "1.0", "description": "Rocket-3B is a GPT-like model, primarily English, fine-tuned on diverse public datasets. It outperforms larger models in benchmarks, showcasing superior understanding and text generation, making it an effective chat model for its size.", "format": "gguf", diff --git a/models/starling-7b/model.json b/models/starling-7b/model.json index cf8aeda18..a7ba963fe 100644 --- a/models/starling-7b/model.json +++ b/models/starling-7b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/Starling-LM-7B-alpha-GGUF/resolve/main/starling-lm-7b-alpha.Q4_K_M.gguf", "id": "starling-7b", "object": "model", - "name": "Strarling alpha 7B", + "name": "Strarling alpha 7B Q4", "version": "1.0", "description": "Starling-RM-7B-alpha is a language model finetuned with Reinforcement Learning from AI Feedback from Openchat 3.5. It stands out for its impressive performance using GPT-4 as a judge, making it one of the top-performing models in its category.", "format": "gguf", diff --git a/models/tiefighter-13b/model.json b/models/tiefighter-13b/model.json index 4dd9bb37f..9940c9a70 100644 --- a/models/tiefighter-13b/model.json +++ b/models/tiefighter-13b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/LLaMA2-13B-Tiefighter-GGUF/resolve/main/llama2-13b-tiefighter.Q5_K_M.gguf", "id": "tiefighter-13b", "object": "model", - "name": "Tiefighter 13B", + "name": "Tiefighter 13B Q5", "version": "1.0", "description": "Tiefighter-13B is a highly creative, merged AI model achieved by combining various 'LORAs' on top of an existing merge, particularly focusing on storytelling and improvisation. This model excels in story writing, chatbots, and adventuring, and is designed to perform better with less detailed inputs, leveraging its inherent creativity.", "format": "gguf", diff --git a/models/tinyllama-1.1b/model.json b/models/tinyllama-1.1b/model.json index 6f10fde02..92793d7f6 100644 --- a/models/tinyllama-1.1b/model.json +++ b/models/tinyllama-1.1b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TinyLlama/TinyLlama-1.1B-Chat-v0.6/resolve/main/ggml-model-q4_0.gguf", "id": "tinyllama-1.1b", "object": "model", - "name": "TinyLlama Chat 1.1B", + "name": "TinyLlama Chat 1.1B Q4", "version": "1.0", "description": "The TinyLlama project, featuring a 1.1B parameter Llama model, is pretrained on an expansive 3 trillion token dataset. Its design ensures easy integration with various Llama-based open-source projects. Despite its smaller size, it efficiently utilizes lower computational and memory resources, drawing on GPT-4's analytical prowess to enhance its conversational abilities and versatility.", "format": "gguf", diff --git a/models/wizardcoder-13b/model.json b/models/wizardcoder-13b/model.json index 47899534a..a7284aa7c 100644 --- a/models/wizardcoder-13b/model.json +++ b/models/wizardcoder-13b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/WizardCoder-Python-13B-V1.0-GGUF/resolve/main/wizardcoder-python-13b-v1.0.Q5_K_M.gguf", "id": "wizardcoder-13b", "object": "model", - "name": "Wizard Coder Python 13B", + "name": "Wizard Coder Python 13B Q5", "version": "1.0", "description": "WizardCoder-Python-13B is a Python coding model major models like ChatGPT-3.5. This model based on the Llama2 architecture, demonstrate high proficiency in specific domains like coding and mathematics.", "format": "gguf", diff --git a/models/wizardcoder-34b/model.json b/models/wizardcoder-34b/model.json index f564afc35..ca4a3da8e 100644 --- a/models/wizardcoder-34b/model.json +++ b/models/wizardcoder-34b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/WizardCoder-Python-34B-V1.0-GGUF/resolve/main/wizardcoder-python-34b-v1.0.Q5_K_M.gguf", "id": "wizardcoder-34b", "object": "model", - "name": "Wizard Coder Python 34B", + "name": "Wizard Coder Python 34B Q5", "version": "1.0", "description": "WizardCoder-Python-34B is a Python coding model major models like ChatGPT-3.5. This model based on the Llama2 architecture, demonstrate high proficiency in specific domains like coding and mathematics.", "format": "gguf", diff --git a/models/yi-34b/model.json b/models/yi-34b/model.json index d34c0efed..bc6e8e9e3 100644 --- a/models/yi-34b/model.json +++ b/models/yi-34b/model.json @@ -2,7 +2,7 @@ "source_url": "https://huggingface.co/TheBloke/Yi-34B-Chat-GGUF/resolve/main/yi-34b-chat.Q5_K_M.gguf", "id": "yi-34b", "object": "model", - "name": "Yi 34B", + "name": "Yi 34B Q5", "version": "1.0", "description": "Yi-34B, a specialized chat model, is known for its diverse and creative responses and excels across various NLP tasks and benchmarks.", "format": "gguf", diff --git a/models/zephyr-beta-7b/model.json b/models/zephyr-beta-7b/model.json index 70c7c72e8..e1a175432 100644 --- a/models/zephyr-beta-7b/model.json +++ b/models/zephyr-beta-7b/model.json @@ -2,9 +2,9 @@ "source_url": "https://huggingface.co/TheBloke/zephyr-7B-beta-GGUF/resolve/main/zephyr-7b-beta.Q4_K_M.gguf", "id": "zephyr-beta-7b", "object": "model", - "name": "Zephyr Beta 7B", + "name": "Zephyr Beta 7B Q4", "version": "1.0", - "description": "The Zephyr-7B-β model marks the second iteration in the Zephyr series, designed to function as an effective assistant. It has been fine-tuned from the mistralai/Mistral-7B-v0.1 base model, utilizing a combination of public and synthetic datasets with the application of Direct Preference Optimization.", + "description": "The Zephyr-7B-β model is trained by HuggingFace, designed to function as a practical assistant. It has been fine-tuned from the mistralai/Mistral-7B-v0.1 base model, utilizing a combination of public and synthetic datasets with the application of Direct Preference Optimization.", "format": "gguf", "settings": { "ctx_len": 2048, From f4dbec7e36527f4f022c55fbc1d426a4039d8851 Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 16:31:47 +0700 Subject: [PATCH 18/42] update deepseek coder --- models/deepseek-coder-1.3b/model.json | 2 +- models/deepseek-coder-34b/model.json | 24 ++++++++++++++++++++++++ models/wizardcoder-34b/model.json | 24 ------------------------ 3 files changed, 25 insertions(+), 25 deletions(-) create mode 100644 models/deepseek-coder-34b/model.json delete mode 100644 models/wizardcoder-34b/model.json diff --git a/models/deepseek-coder-1.3b/model.json b/models/deepseek-coder-1.3b/model.json index 9d22f9558..2bb9e7fee 100644 --- a/models/deepseek-coder-1.3b/model.json +++ b/models/deepseek-coder-1.3b/model.json @@ -4,7 +4,7 @@ "object": "model", "name": "Deepseek Coder 1.3B Q4", "version": "1.0", - "description": "", + "description": "Deepseek Coder trained on 2T tokens (87% code, 13% English/Chinese), excelling in project-level code completion with advanced capabilities across multiple programming languages.", "format": "gguf", "settings": { "ctx_len": 2048, diff --git a/models/deepseek-coder-34b/model.json b/models/deepseek-coder-34b/model.json new file mode 100644 index 000000000..e175396f5 --- /dev/null +++ b/models/deepseek-coder-34b/model.json @@ -0,0 +1,24 @@ +{ + "source_url": "https://huggingface.co/TheBloke/deepseek-coder-33B-instruct-GGUF/resolve/main/deepseek-coder-33b-instruct.Q5_K_M.gguf", + "id": "deepseek-coder-34b", + "object": "model", + "name": "Deepseek Coder 33B Q5", + "version": "1.0", + "description": "Deepseek Coder trained on 2T tokens (87% code, 13% English/Chinese), excelling in project-level code completion with advanced capabilities across multiple programming languages.", + "format": "gguf", + "settings": { + "ctx_len": 2048, + "system_prompt": "", + "user_prompt": "### Instruction:\n", + "ai_prompt": "### Response:\n" + }, + "parameters": { + "max_tokens": 2048 + }, + "metadata": { + "author": "Deepseek, The Bloke", + "tags": ["Community Recommended", "Code", "Big Context Length"], + "size": 26040000000 + } + } + \ No newline at end of file diff --git a/models/wizardcoder-34b/model.json b/models/wizardcoder-34b/model.json deleted file mode 100644 index ca4a3da8e..000000000 --- a/models/wizardcoder-34b/model.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "source_url": "https://huggingface.co/TheBloke/WizardCoder-Python-34B-V1.0-GGUF/resolve/main/wizardcoder-python-34b-v1.0.Q5_K_M.gguf", - "id": "wizardcoder-34b", - "object": "model", - "name": "Wizard Coder Python 34B Q5", - "version": "1.0", - "description": "WizardCoder-Python-34B is a Python coding model major models like ChatGPT-3.5. This model based on the Llama2 architecture, demonstrate high proficiency in specific domains like coding and mathematics.", - "format": "gguf", - "settings": { - "ctx_len": 2048, - "system_prompt": "", - "user_prompt": "### Instruction:\n", - "ai_prompt": "### Response:\n" - }, - "parameters": { - "max_tokens": 2048 - }, - "metadata": { - "author": "WizardLM, The Bloke", - "tags": ["Community Recommended", "Code", "Big Context Length"], - "size": 24320000000 - } - } - \ No newline at end of file From 69af5a034ad0026055259cd93b970107635a1a00 Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 16:38:13 +0700 Subject: [PATCH 19/42] update tags --- models/capybara-34b/model.json | 2 +- models/deepseek-coder-1.3b/model.json | 2 +- models/deepseek-coder-34b/model.json | 2 +- models/neural-chat-7b/model.json | 2 +- models/noromaid-20b/model.json | 2 +- models/openhermes-neural-7b/model.json | 2 +- models/openorca-13b/model.json | 2 +- models/phind-34b/model.json | 2 +- models/rocket-3b/model.json | 2 +- models/starling-7b/model.json | 2 +- models/tiefighter-13b/model.json | 2 +- models/tinyllama-1.1b/model.json | 2 +- models/wizardcoder-13b/model.json | 2 +- models/yi-34b/model.json | 2 +- models/zephyr-beta-7b/model.json | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/models/capybara-34b/model.json b/models/capybara-34b/model.json index e5834a66d..5f0bd7948 100644 --- a/models/capybara-34b/model.json +++ b/models/capybara-34b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "NousResearch, The Bloke", - "tags": ["Community Recommended", "General Use", "Big Context Length"], + "tags": ["Community Recommended", "Full Capabilities", "Finetuned"], "size": 24320000000 } } diff --git a/models/deepseek-coder-1.3b/model.json b/models/deepseek-coder-1.3b/model.json index 2bb9e7fee..47057626b 100644 --- a/models/deepseek-coder-1.3b/model.json +++ b/models/deepseek-coder-1.3b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Deepseek, The Bloke", - "tags": ["Community Recommended", "Code", "Small size"], + "tags": ["Foundational Model", "Code", "Small size"], "size": 870000000 } } diff --git a/models/deepseek-coder-34b/model.json b/models/deepseek-coder-34b/model.json index e175396f5..098cf87fd 100644 --- a/models/deepseek-coder-34b/model.json +++ b/models/deepseek-coder-34b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Deepseek, The Bloke", - "tags": ["Community Recommended", "Code", "Big Context Length"], + "tags": ["Foundational Model", "Community Recommended", "Code", "Big Context Length"], "size": 26040000000 } } diff --git a/models/neural-chat-7b/model.json b/models/neural-chat-7b/model.json index 234a2ff80..5357d8822 100644 --- a/models/neural-chat-7b/model.json +++ b/models/neural-chat-7b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Intel, The Bloke", - "tags": ["Community Recommended", "General Use", "Role-playing", "Big Context Length"], + "tags": ["Community Recommended", "Full Capabilities", "Big Context Length", "Finetuned"], "size": 4370000000 } } diff --git a/models/noromaid-20b/model.json b/models/noromaid-20b/model.json index da69cba3e..e8e3a9128 100644 --- a/models/noromaid-20b/model.json +++ b/models/noromaid-20b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "NeverSleep, The Bloke", - "tags": ["Community Recommended", "Role-playing"], + "tags": ["Community Recommended", "Role-playing", "Finetuned"], "size": 12040000000 } } diff --git a/models/openhermes-neural-7b/model.json b/models/openhermes-neural-7b/model.json index a7366f85b..2e9452067 100644 --- a/models/openhermes-neural-7b/model.json +++ b/models/openhermes-neural-7b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Intel, The Bloke", - "tags": ["Community Recommended", "General Use", "Code", "Merged"], + "tags": ["Community Recommended", "Full Capabilities", "Merged"], "size": 4370000000 } } diff --git a/models/openorca-13b/model.json b/models/openorca-13b/model.json index edfef0807..709cb0d36 100644 --- a/models/openorca-13b/model.json +++ b/models/openorca-13b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Microsoft, The Bloke", - "tags": ["Community Recommended", "General Use"], + "tags": ["Community Recommended", "General", "Reasoning", "Finetuned"], "size": 9230000000 } } diff --git a/models/phind-34b/model.json b/models/phind-34b/model.json index 8de7a84d0..532ad70fe 100644 --- a/models/phind-34b/model.json +++ b/models/phind-34b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Phind, The Bloke", - "tags": ["Community Recommended", "Code", "Big Context Length"], + "tags": ["Community Recommended", "Code", "Big Context Length", "Finetuned"], "size": 24320000000 } } diff --git a/models/rocket-3b/model.json b/models/rocket-3b/model.json index 7435bfafb..cd790d83c 100644 --- a/models/rocket-3b/model.json +++ b/models/rocket-3b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "pansophic, The Bloke", - "tags": ["Community Recommended", "General Use"], + "tags": ["Community Recommended", "General", "Small Size"], "size": 1710000000 } } \ No newline at end of file diff --git a/models/starling-7b/model.json b/models/starling-7b/model.json index a7ba963fe..5da638a29 100644 --- a/models/starling-7b/model.json +++ b/models/starling-7b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Berkeley-nest, The Bloke", - "tags": ["Community Recommended", "General", "Code"], + "tags": ["Community Recommended", "Full Capabilities","Finetuned"], "size": 4370000000 } } diff --git a/models/tiefighter-13b/model.json b/models/tiefighter-13b/model.json index 9940c9a70..e7b962e65 100644 --- a/models/tiefighter-13b/model.json +++ b/models/tiefighter-13b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "KoboldAI, The Bloke", - "tags": ["Community Recommended", "General Use", "Role-playing", "Writing"], + "tags": ["Community Recommended", "Role-playing", "Creative", "Finetuned"], "size": 9230000000 } } diff --git a/models/tinyllama-1.1b/model.json b/models/tinyllama-1.1b/model.json index 92793d7f6..93fd35fc6 100644 --- a/models/tinyllama-1.1b/model.json +++ b/models/tinyllama-1.1b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "TinyLlama", - "tags": ["Community Recommended", "General Use"], + "tags": ["Community Recommended", "General", "Small Size"], "size": 637000000 } } \ No newline at end of file diff --git a/models/wizardcoder-13b/model.json b/models/wizardcoder-13b/model.json index a7284aa7c..fc1f6f33c 100644 --- a/models/wizardcoder-13b/model.json +++ b/models/wizardcoder-13b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "WizardLM, The Bloke", - "tags": ["Community Recommended", "Code", "Big Context Length"], + "tags": ["Community Recommended", "Code", "Big Context Length", "Finetuned"], "size": 9230000000 } } diff --git a/models/yi-34b/model.json b/models/yi-34b/model.json index bc6e8e9e3..7e574daf0 100644 --- a/models/yi-34b/model.json +++ b/models/yi-34b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "01-ai, The Bloke", - "tags": ["Foundational Model", "General Use", "Role-playing", "Writing"], + "tags": ["Foundational Model", "Full Capabilities"], "size": 24320000000 } } diff --git a/models/zephyr-beta-7b/model.json b/models/zephyr-beta-7b/model.json index e1a175432..8b53ab07e 100644 --- a/models/zephyr-beta-7b/model.json +++ b/models/zephyr-beta-7b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "HuggingFaceH4, The Bloke", - "tags": ["Community Recommended", "General Use", "Big Context Length"], + "tags": ["Community Recommended", "Full Capabilities", "Finetuned"], "size": 4370000000 } } From 3f5317bb53de9e2c9599c3a0f2f514b85ab92660 Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 16:44:43 +0700 Subject: [PATCH 20/42] typo --- models/lzlv-70b/model.json | 2 +- models/rocket-3b/model.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/models/lzlv-70b/model.json b/models/lzlv-70b/model.json index e4247eb88..0b1577131 100644 --- a/models/lzlv-70b/model.json +++ b/models/lzlv-70b/model.json @@ -16,7 +16,7 @@ "max_tokens": 2048 }, "metadata": { - "author": "lizpreciatior, The Bloke", + "author": "Lizpreciatior, The Bloke", "tags": ["Community Recommended", "General Use", "Role-playing"], "size": 48750000000 } diff --git a/models/rocket-3b/model.json b/models/rocket-3b/model.json index cd790d83c..83a61584a 100644 --- a/models/rocket-3b/model.json +++ b/models/rocket-3b/model.json @@ -16,7 +16,7 @@ "max_tokens": 2048 }, "metadata": { - "author": "pansophic, The Bloke", + "author": "Pansophic, The Bloke", "tags": ["Community Recommended", "General", "Small Size"], "size": 1710000000 } From ff69e4fe51abe2dcc29d9b485c09f238cb1b73ee Mon Sep 17 00:00:00 2001 From: hahuyhoang411 Date: Mon, 4 Dec 2023 17:33:26 +0700 Subject: [PATCH 21/42] update models --- models/capybara-34b/model.json | 2 +- models/deepseek-coder-1.3b/model.json | 2 +- models/deepseek-coder-34b/model.json | 2 +- models/llama2-chat-70b-q4/model.json | 2 +- models/llama2-chat-7b-q4/model.json | 2 +- models/llama2-chat-7b-q5/model.json | 2 +- models/lzlv-70b/model.json | 2 +- models/mistral-ins-7b-q4/model.json | 2 +- models/mistral-ins-7b-q5/model.json | 2 +- models/neural-chat-7b/model.json | 2 +- models/noromaid-20b/model.json | 2 +- models/openhermes-neural-7b/model.json | 2 +- models/openorca-13b/model.json | 2 +- models/phind-34b/model.json | 2 +- models/rocket-3b/model.json | 2 +- models/starling-7b/model.json | 2 +- models/tiefighter-13b/model.json | 2 +- models/tinyllama-1.1b/model.json | 2 +- models/wizardcoder-13b/model.json | 2 +- models/yi-34b/model.json | 2 +- models/zephyr-beta-7b/model.json | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/models/capybara-34b/model.json b/models/capybara-34b/model.json index 5f0bd7948..14cdf1d04 100644 --- a/models/capybara-34b/model.json +++ b/models/capybara-34b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "NousResearch, The Bloke", - "tags": ["Community Recommended", "Full Capabilities", "Finetuned"], + "tags": ["Recommended", "Medium", "Finetuned"], "size": 24320000000 } } diff --git a/models/deepseek-coder-1.3b/model.json b/models/deepseek-coder-1.3b/model.json index 47057626b..ec2e2815f 100644 --- a/models/deepseek-coder-1.3b/model.json +++ b/models/deepseek-coder-1.3b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Deepseek, The Bloke", - "tags": ["Foundational Model", "Code", "Small size"], + "tags": ["Tiny", "Foundational Model"], "size": 870000000 } } diff --git a/models/deepseek-coder-34b/model.json b/models/deepseek-coder-34b/model.json index 098cf87fd..1936df1b9 100644 --- a/models/deepseek-coder-34b/model.json +++ b/models/deepseek-coder-34b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Deepseek, The Bloke", - "tags": ["Foundational Model", "Community Recommended", "Code", "Big Context Length"], + "tags": ["Recommended", "Medium", "Foundational Model"], "size": 26040000000 } } diff --git a/models/llama2-chat-70b-q4/model.json b/models/llama2-chat-70b-q4/model.json index 4ab3ac555..6d089f9fa 100644 --- a/models/llama2-chat-70b-q4/model.json +++ b/models/llama2-chat-70b-q4/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "MetaAI, The Bloke", - "tags": ["Foundational Model", "General", "Code"], + "tags": ["Large", "Foundational Model"], "size": 43920000000 } } diff --git a/models/llama2-chat-7b-q4/model.json b/models/llama2-chat-7b-q4/model.json index 7b52e1767..3ba054018 100644 --- a/models/llama2-chat-7b-q4/model.json +++ b/models/llama2-chat-7b-q4/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "MetaAI, The Bloke", - "tags": ["Foundational Model", "General", "Code"], + "tags": ["Small", "Foundational Model"], "size": 4080000000 } } diff --git a/models/llama2-chat-7b-q5/model.json b/models/llama2-chat-7b-q5/model.json index b19213e46..2889868d5 100644 --- a/models/llama2-chat-7b-q5/model.json +++ b/models/llama2-chat-7b-q5/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "MetaAI, The Bloke", - "tags": ["Foundational Model", "General", "Code"], + "tags": ["Small", "Foundational Model"], "size": 4780000000 } } diff --git a/models/lzlv-70b/model.json b/models/lzlv-70b/model.json index 0b1577131..d26ba7d29 100644 --- a/models/lzlv-70b/model.json +++ b/models/lzlv-70b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Lizpreciatior, The Bloke", - "tags": ["Community Recommended", "General Use", "Role-playing"], + "tags": ["Recommended", "Large", "Finetuned"], "size": 48750000000 } } diff --git a/models/mistral-ins-7b-q4/model.json b/models/mistral-ins-7b-q4/model.json index dd3360700..fe1bb0a5b 100644 --- a/models/mistral-ins-7b-q4/model.json +++ b/models/mistral-ins-7b-q4/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "MistralAI, The Bloke", - "tags": ["Foundational Model", "General", "Code"], + "tags": ["Small", "Foundational Model"], "size": 4370000000 } } diff --git a/models/mistral-ins-7b-q5/model.json b/models/mistral-ins-7b-q5/model.json index 5b86ab538..13eb6bde9 100644 --- a/models/mistral-ins-7b-q5/model.json +++ b/models/mistral-ins-7b-q5/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "MistralAI, The Bloke", - "tags": ["Foundational Model", "General", "Code"], + "tags": ["Small", "Foundational Model"], "size": 5130000000 } } diff --git a/models/neural-chat-7b/model.json b/models/neural-chat-7b/model.json index 5357d8822..cd0b3b3d0 100644 --- a/models/neural-chat-7b/model.json +++ b/models/neural-chat-7b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Intel, The Bloke", - "tags": ["Community Recommended", "Full Capabilities", "Big Context Length", "Finetuned"], + "tags": ["Recommended", "Small", "Finetuned"], "size": 4370000000 } } diff --git a/models/noromaid-20b/model.json b/models/noromaid-20b/model.json index e8e3a9128..f6994d1ce 100644 --- a/models/noromaid-20b/model.json +++ b/models/noromaid-20b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "NeverSleep, The Bloke", - "tags": ["Community Recommended", "Role-playing", "Finetuned"], + "tags": ["Medium", "Finetuned"], "size": 12040000000 } } diff --git a/models/openhermes-neural-7b/model.json b/models/openhermes-neural-7b/model.json index 2e9452067..536345fd1 100644 --- a/models/openhermes-neural-7b/model.json +++ b/models/openhermes-neural-7b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Intel, The Bloke", - "tags": ["Community Recommended", "Full Capabilities", "Merged"], + "tags": ["Recommended", "Small", "Merged"], "size": 4370000000 } } diff --git a/models/openorca-13b/model.json b/models/openorca-13b/model.json index 709cb0d36..0c0c9fff7 100644 --- a/models/openorca-13b/model.json +++ b/models/openorca-13b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Microsoft, The Bloke", - "tags": ["Community Recommended", "General", "Reasoning", "Finetuned"], + "tags": ["Medium", "Finetuned"], "size": 9230000000 } } diff --git a/models/phind-34b/model.json b/models/phind-34b/model.json index 532ad70fe..c8e2cb919 100644 --- a/models/phind-34b/model.json +++ b/models/phind-34b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Phind, The Bloke", - "tags": ["Community Recommended", "Code", "Big Context Length", "Finetuned"], + "tags": ["Recommended", "Medium", "Finetuned"], "size": 24320000000 } } diff --git a/models/rocket-3b/model.json b/models/rocket-3b/model.json index 83a61584a..c40ee6258 100644 --- a/models/rocket-3b/model.json +++ b/models/rocket-3b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Pansophic, The Bloke", - "tags": ["Community Recommended", "General", "Small Size"], + "tags": ["Tiny", "Finetuned"], "size": 1710000000 } } \ No newline at end of file diff --git a/models/starling-7b/model.json b/models/starling-7b/model.json index 5da638a29..1bc2aac61 100644 --- a/models/starling-7b/model.json +++ b/models/starling-7b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "Berkeley-nest, The Bloke", - "tags": ["Community Recommended", "Full Capabilities","Finetuned"], + "tags": ["Recommended", "Small","Finetuned"], "size": 4370000000 } } diff --git a/models/tiefighter-13b/model.json b/models/tiefighter-13b/model.json index e7b962e65..a28f88d85 100644 --- a/models/tiefighter-13b/model.json +++ b/models/tiefighter-13b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "KoboldAI, The Bloke", - "tags": ["Community Recommended", "Role-playing", "Creative", "Finetuned"], + "tags": ["Medium", "Finetuned"], "size": 9230000000 } } diff --git a/models/tinyllama-1.1b/model.json b/models/tinyllama-1.1b/model.json index 93fd35fc6..ace0ca6a0 100644 --- a/models/tinyllama-1.1b/model.json +++ b/models/tinyllama-1.1b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "TinyLlama", - "tags": ["Community Recommended", "General", "Small Size"], + "tags": ["Tiny", "Foundation Model"], "size": 637000000 } } \ No newline at end of file diff --git a/models/wizardcoder-13b/model.json b/models/wizardcoder-13b/model.json index fc1f6f33c..16f8946be 100644 --- a/models/wizardcoder-13b/model.json +++ b/models/wizardcoder-13b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "WizardLM, The Bloke", - "tags": ["Community Recommended", "Code", "Big Context Length", "Finetuned"], + "tags": ["Recommended", "Medium", "Finetuned"], "size": 9230000000 } } diff --git a/models/yi-34b/model.json b/models/yi-34b/model.json index 7e574daf0..c2d2fd327 100644 --- a/models/yi-34b/model.json +++ b/models/yi-34b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "01-ai, The Bloke", - "tags": ["Foundational Model", "Full Capabilities"], + "tags": ["Medium", "Foundational Model"], "size": 24320000000 } } diff --git a/models/zephyr-beta-7b/model.json b/models/zephyr-beta-7b/model.json index 8b53ab07e..c6b4bcdc7 100644 --- a/models/zephyr-beta-7b/model.json +++ b/models/zephyr-beta-7b/model.json @@ -17,7 +17,7 @@ }, "metadata": { "author": "HuggingFaceH4, The Bloke", - "tags": ["Community Recommended", "Full Capabilities", "Finetuned"], + "tags": ["Recommended", "Small", "Finetuned"], "size": 4370000000 } } From dacb00ed3757b7b4bdb1d0527d7dee2969b4811d Mon Sep 17 00:00:00 2001 From: NamH Date: Mon, 4 Dec 2023 17:40:47 +0700 Subject: [PATCH 22/42] fix: not update active model when using resend button (#834) Signed-off-by: James Co-authored-by: James --- web/hooks/useSendChatMessage.ts | 42 ++++++++++++++++++ web/screens/Chat/MessageToolbar/index.tsx | 52 +++++++++-------------- 2 files changed, 61 insertions(+), 33 deletions(-) diff --git a/web/hooks/useSendChatMessage.ts b/web/hooks/useSendChatMessage.ts index 9cf61969d..8b9a1bada 100644 --- a/web/hooks/useSendChatMessage.ts +++ b/web/hooks/useSendChatMessage.ts @@ -48,6 +48,47 @@ export default function useSendChatMessage() { const { startModel } = useActiveModel() const [queuedMessage, setQueuedMessage] = useState(false) + const resendChatMessage = async () => { + if (!activeThread) { + console.error('No active thread') + return + } + + updateThreadWaiting(activeThread.id, true) + + const messages: ChatCompletionMessage[] = [ + activeThread.assistants[0]?.instructions, + ] + .map((instructions) => { + const systemMessage: ChatCompletionMessage = { + role: ChatCompletionRole.System, + content: instructions, + } + return systemMessage + }) + .concat( + currentMessages.map((msg) => ({ + role: msg.role, + content: msg.content[0]?.text.value ?? '', + })) + ) + + const messageRequest: MessageRequest = { + id: ulid(), + messages: messages, + threadId: activeThread.id, + } + + const modelId = selectedModel?.id ?? activeThread.assistants[0].model.id + + if (activeModel?.id !== modelId) { + setQueuedMessage(true) + await startModel(modelId) + setQueuedMessage(false) + } + events.emit(EventName.OnMessageSent, messageRequest) + } + const sendChatMessage = async () => { if (!currentPrompt || currentPrompt.trim().length === 0) { return @@ -162,6 +203,7 @@ export default function useSendChatMessage() { return { sendChatMessage, + resendChatMessage, queuedMessage, } } diff --git a/web/screens/Chat/MessageToolbar/index.tsx b/web/screens/Chat/MessageToolbar/index.tsx index 5380c7e29..a0929336c 100644 --- a/web/screens/Chat/MessageToolbar/index.tsx +++ b/web/screens/Chat/MessageToolbar/index.tsx @@ -1,7 +1,5 @@ import { - ChatCompletionMessage, EventName, - MessageRequest, MessageStatus, ExtensionType, ThreadMessage, @@ -21,17 +19,15 @@ import { getCurrentChatMessagesAtom, } from '@/helpers/atoms/ChatMessage.atom' import { activeThreadAtom } from '@/helpers/atoms/Conversation.atom' +import useSendChatMessage from '@/hooks/useSendChatMessage' const MessageToolbar = ({ message }: { message: ThreadMessage }) => { const deleteMessage = useSetAtom(deleteMessageAtom) const thread = useAtomValue(activeThreadAtom) const messages = useAtomValue(getCurrentChatMessagesAtom) - // const threadStateAtom = useMemo( - // () => atom((get) => get(threadStatesAtom)[thread?.id ?? '']), - // [thread?.id] - // ) - // const threadState = useAtomValue(threadStateAtom) - const stopInference = async () => { + const { resendChatMessage } = useSendChatMessage() + + const onStopInferenceClick = async () => { await extensionManager .get(ExtensionType.Inference) ?.stopInference() @@ -43,13 +39,25 @@ const MessageToolbar = ({ message }: { message: ThreadMessage }) => { }, 300) } + const onDeleteClick = async () => { + deleteMessage(message.id ?? '') + if (thread) { + await extensionManager + .get(ExtensionType.Conversational) + ?.writeMessages( + thread.id, + messages.filter((msg) => msg.id !== message.id) + ) + } + } + return (
{message.status === MessageStatus.Pending && (
stopInference()} + onClick={onStopInferenceClick} >
@@ -58,20 +66,7 @@ const MessageToolbar = ({ message }: { message: ThreadMessage }) => { message.id === messages[messages.length - 1]?.id && (
{ - const messageRequest: MessageRequest = { - id: message.id ?? '', - messages: messages.slice(0, -1).map((e) => { - const msg: ChatCompletionMessage = { - role: e.role, - content: e.content[0].text.value, - } - return msg - }), - threadId: message.thread_id ?? '', - } - events.emit(EventName.OnMessageSent, messageRequest) - }} + onClick={resendChatMessage} >
@@ -89,16 +84,7 @@ const MessageToolbar = ({ message }: { message: ThreadMessage }) => {
{ - deleteMessage(message.id ?? '') - if (thread) - await extensionManager - .get(ExtensionType.Conversational) - ?.writeMessages( - thread.id, - messages.filter((msg) => msg.id !== message.id) - ) - }} + onClick={onDeleteClick} >
From f6f5db01f8a99c7e9897027a2567cb58fd7acf6d Mon Sep 17 00:00:00 2001 From: Linh Tran Date: Mon, 4 Dec 2023 12:30:09 +0700 Subject: [PATCH 23/42] Resolve comments + update licence --- core/src/fs.ts | 2 -- server/.gitignore | 1 + server/package.json | 2 +- server/v1/index.ts | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) create mode 100644 server/.gitignore diff --git a/core/src/fs.ts b/core/src/fs.ts index b428a7841..d12b473bf 100644 --- a/core/src/fs.ts +++ b/core/src/fs.ts @@ -1,5 +1,3 @@ -const fetchRetry = require("fetch-retry")(global.fetch); - /** * Writes data to a file at the specified path. * @param {string} path - The path to the file. diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 000000000..6320cd248 --- /dev/null +++ b/server/.gitignore @@ -0,0 +1 @@ +data \ No newline at end of file diff --git a/server/package.json b/server/package.json index 405f2bf5b..76262ba51 100644 --- a/server/package.json +++ b/server/package.json @@ -3,7 +3,7 @@ "version": "0.1.3", "main": "./build/main.js", "author": "Jan ", - "license": "MIT", + "license": "AGPL-3.0", "homepage": "https://github.com/janhq/jan/tree/main/electron", "description": "Use offline LLMs with your own data. Run open source models like Llama2 or Falcon on your internal computers/servers.", "build": { diff --git a/server/v1/index.ts b/server/v1/index.ts index 8a153cbaf..89d73200b 100644 --- a/server/v1/index.ts +++ b/server/v1/index.ts @@ -9,7 +9,7 @@ const router: FastifyPluginAsync = async (app: FastifyInstance, opts) => { app.register( assistantsAPI, { - prefix: "/assisstants" + prefix: "/assistants" } ) From 12e765109e903357fc13a2872714ed67a1193e99 Mon Sep 17 00:00:00 2001 From: Linh Tran Date: Mon, 4 Dec 2023 21:37:02 +0700 Subject: [PATCH 24/42] resolve comments --- server/main.ts | 12 +++++---- server/package.json | 61 +++------------------------------------------ 2 files changed, 11 insertions(+), 62 deletions(-) diff --git a/server/main.ts b/server/main.ts index 5466a27d8..758aa2217 100644 --- a/server/main.ts +++ b/server/main.ts @@ -1,17 +1,19 @@ import fastify from 'fastify' - +import dotenv from 'dotenv' import v1API from './v1' -const JAN_API_PORT = 1337; const server = fastify() -const USER_ROOT_DIR = '.data' +dotenv.config() server.register(v1API, {prefix: "/api/v1"}) +const JAN_API_PORT = Number.parseInt(process.env.JAN_API_PORT || '1337') +const JAN_API_HOST = process.env.JAN_API_HOST || "0.0.0.0" + server.listen({ port: JAN_API_PORT, - host: "0.0.0.0" -}).then(()=>{ + host: JAN_API_HOST +}).then(() => { console.log(`JAN API listening at: http://0.0.0.0:${JAN_API_PORT}`); }) diff --git a/server/package.json b/server/package.json index 76262ba51..1fd06a482 100644 --- a/server/package.json +++ b/server/package.json @@ -4,76 +4,23 @@ "main": "./build/main.js", "author": "Jan ", "license": "AGPL-3.0", - "homepage": "https://github.com/janhq/jan/tree/main/electron", + "homepage": "https://jan.ai", "description": "Use offline LLMs with your own data. Run open source models like Llama2 or Falcon on your internal computers/servers.", - "build": { - "appId": "jan.ai.app", - "productName": "Jan", - "files": [ - "renderer/**/*", - "build/*.{js,map}", - "build/**/*.{js,map}", - "core/pre-install", - "core/plugin-manager/facade" - ], - "asarUnpack": [ - "core/pre-install" - ], - "publish": [ - { - "provider": "github", - "owner": "janhq", - "repo": "jan" - } - ], - "extends": null, - "mac": { - "type": "distribution", - "entitlements": "./entitlements.mac.plist", - "entitlementsInherit": "./entitlements.mac.plist", - "notarize": { - "teamId": "YT49P7GXG4" - }, - "icon": "icons/icon.png" - }, - "linux": { - "target": [ - "deb" - ], - "category": "Utility", - "icon": "icons/" - }, - "win": { - "icon": "icons/icon.png" - }, - "artifactName": "jan-${os}-${arch}-${version}.${ext}" - }, + "build": "", "scripts": { "lint": "eslint . --ext \".js,.jsx,.ts,.tsx\"", "test:e2e": "playwright test --workers=1", "dev": "nodemon .", - "build": "tsc", - "build:test": "", - "build:publish": "" + "build": "tsc" }, "dependencies": { - "@npmcli/arborist": "^7.1.0", - "@types/request": "^2.48.12", - "@uiball/loaders": "^1.3.0", - "express": "^4.18.2", - "pacote": "^17.0.4", - "request": "^2.88.2", - "request-progress": "^3.0.0", - "use-debounce": "^9.0.4" }, "devDependencies": { - "@playwright/test": "^1.38.1", "@types/body-parser": "^1.19.5", - "@types/express": "^4.17.21", "@types/npmcli__arborist": "^5.6.4", - "@types/pacote": "^11.1.7", "@typescript-eslint/eslint-plugin": "^6.7.3", "@typescript-eslint/parser": "^6.7.3", + "dotenv": "^16.3.1", "eslint-plugin-react": "^7.33.2", "fastify": "^4.24.3", "nodemon": "^3.0.1", From dbcd3573c4eab03fafb66c866b2ac6fec0366d88 Mon Sep 17 00:00:00 2001 From: Linh Tran Date: Mon, 4 Dec 2023 21:44:21 +0700 Subject: [PATCH 25/42] Remove old merge mistake - auto merge adding lines to Makefile --- Makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Makefile b/Makefile index 76dff5614..13618cf6a 100644 --- a/Makefile +++ b/Makefile @@ -15,10 +15,6 @@ endif # Installs yarn dependencies and builds core and extensions install-and-build: build-uikit ifeq ($(OS),Windows_NT) - powershell -Command "yarn config set network-timeout 300000; \ - $$env:NITRO_VERSION = Get-Content .\\plugins\\inference-plugin\\nitro\\version.txt; \ - Write-Output \"Nitro version: $$env:NITRO_VERSION\"; yarn build:core; yarn install; yarn build:plugins" -else yarn config set network-timeout 300000 endif yarn build:core From d0e657161e2b799dc566473741a2c854aca2a29d Mon Sep 17 00:00:00 2001 From: Linh Tran Date: Mon, 4 Dec 2023 22:04:41 +0700 Subject: [PATCH 26/42] fix console print --- server/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/main.ts b/server/main.ts index 758aa2217..707c3fb4b 100644 --- a/server/main.ts +++ b/server/main.ts @@ -14,6 +14,6 @@ server.listen({ port: JAN_API_PORT, host: JAN_API_HOST }).then(() => { - console.log(`JAN API listening at: http://0.0.0.0:${JAN_API_PORT}`); + console.log(`JAN API listening at: http://${JAN_API_HOST}:${JAN_API_PORT}`); }) From f7e3dfcc11d3ece811420fd9260b6056f5bdbfa3 Mon Sep 17 00:00:00 2001 From: hiento09 <136591877+hiento09@users.noreply.github.com> Date: Mon, 4 Dec 2023 22:30:09 +0700 Subject: [PATCH 27/42] Bump nitro version to 0.1.21 - nitro has windows codesign (#843) --- extensions/inference-extension/nitro/version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/inference-extension/nitro/version.txt b/extensions/inference-extension/nitro/version.txt index 964f548b5..790629964 100644 --- a/extensions/inference-extension/nitro/version.txt +++ b/extensions/inference-extension/nitro/version.txt @@ -1 +1 @@ -0.1.20 \ No newline at end of file +0.1.21 From 5d5139ad202bbf1edf3faca16b2ea727f31e6317 Mon Sep 17 00:00:00 2001 From: Faisal Amir Date: Mon, 4 Dec 2023 11:14:07 +0700 Subject: [PATCH 28/42] Added bannner and search ui hub screen --- uikit/src/button/index.tsx | 1 + uikit/src/button/styles.scss | 4 ++ web/public/images/hub-banner.png | Bin 0 -> 285174 bytes .../ExploreModels/ExploreModelItem/index.tsx | 2 +- .../ExploreModelItemHeader/index.tsx | 9 ++- web/screens/ExploreModels/index.tsx | 59 +++++++++++++++++- 6 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 web/public/images/hub-banner.png diff --git a/uikit/src/button/index.tsx b/uikit/src/button/index.tsx index 943e2bc34..55be33f98 100644 --- a/uikit/src/button/index.tsx +++ b/uikit/src/button/index.tsx @@ -14,6 +14,7 @@ const buttonVariants = cva('btn', { outline: 'btn-outline', secondary: 'btn-secondary', ghost: 'btn-ghost', + success: 'btn-success', }, size: { sm: 'btn-sm', diff --git a/uikit/src/button/styles.scss b/uikit/src/button/styles.scss index 69d8e522e..b103987c9 100644 --- a/uikit/src/button/styles.scss +++ b/uikit/src/button/styles.scss @@ -19,6 +19,10 @@ @apply bg-secondary text-secondary-foreground hover:bg-secondary/80; } + &-success { + @apply bg-green-500 text-white hover:bg-green-500/80; + } + &-ghost { @apply hover:bg-primary hover:text-primary-foreground; } diff --git a/web/public/images/hub-banner.png b/web/public/images/hub-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..2734c20f5a110b669edbf946be5f925f6372a479 GIT binary patch literal 285174 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%0D% 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 literal 0 HcmV?d00001 diff --git a/web/screens/ExploreModels/ExploreModelItem/index.tsx b/web/screens/ExploreModels/ExploreModelItem/index.tsx index b2c12f86d..5b0c1e408 100644 --- a/web/screens/ExploreModels/ExploreModelItem/index.tsx +++ b/web/screens/ExploreModels/ExploreModelItem/index.tsx @@ -15,7 +15,7 @@ const ExploreModelItem = forwardRef(({ model }, ref) => { return (
diff --git a/web/screens/ExploreModels/ExploreModelItemHeader/index.tsx b/web/screens/ExploreModels/ExploreModelItemHeader/index.tsx index eb2cdee31..6345d5f1e 100644 --- a/web/screens/ExploreModels/ExploreModelItemHeader/index.tsx +++ b/web/screens/ExploreModels/ExploreModelItemHeader/index.tsx @@ -24,6 +24,7 @@ type Props = { } const ExploreModelItemHeader: React.FC = ({ model }) => { + console.log(model) const { downloadModel } = useDownloadModel() const { downloadedModels } = useGetDownloadedModels() const { modelDownloadStateAtom, downloadStates } = useDownloadState() @@ -57,6 +58,8 @@ const ExploreModelItemHeader: React.FC = ({ model }) => { if (isDownloaded) { downloadButton = ( ) : ( - + )} diff --git a/web/screens/ExploreModels/ExploreModelItem/index.tsx b/web/screens/ExploreModels/ExploreModelItem/index.tsx index 5b0c1e408..1ca539a7d 100644 --- a/web/screens/ExploreModels/ExploreModelItem/index.tsx +++ b/web/screens/ExploreModels/ExploreModelItem/index.tsx @@ -1,6 +1,6 @@ /* eslint-disable react/display-name */ -import { forwardRef } from 'react' +import { forwardRef, useState } from 'react' import { Model } from '@janhq/core' import { Badge } from '@janhq/uikit' @@ -12,58 +12,78 @@ type Props = { } const ExploreModelItem = forwardRef(({ model }, ref) => { + const [open, setOpen] = useState('') + + const handleToggle = () => { + if (open === model.id) { + setOpen('') + } else { + setOpen(model.id) + } + } + return (
- -
-
- About -

{model.description}

-
- -
-
- Author -

{model.metadata.author}

+ + {open === model.id && ( +
+
+
+ About +

+ {model.description || '-'} +

+
+
+
+ + Author + +

{model.metadata.author}

+
+
+ + Model ID + +

{model.id}

+
+
+ + Tags + +
+ {model.metadata.tags.map((tag, i) => ( + + {tag} + + ))} +
+
+
-
- Compatibility -
- {/* - {toGigabytes(model.metadata.maxRamRequired)} RAM required - */} +
+
+ + Format + +

{model.format}

+
+
+ + Compatibility + +

-

- -
-
- Version -
- v{model.version} -
-
-
- Tags -
- {model.metadata.tags.map((tag, i) => ( - - {tag} - - ))} -
-
-
-
+ )}
) }) diff --git a/web/screens/ExploreModels/ExploreModelItemHeader/index.tsx b/web/screens/ExploreModels/ExploreModelItemHeader/index.tsx index 6345d5f1e..6c34a2074 100644 --- a/web/screens/ExploreModels/ExploreModelItemHeader/index.tsx +++ b/web/screens/ExploreModels/ExploreModelItemHeader/index.tsx @@ -1,16 +1,20 @@ /* eslint-disable react-hooks/exhaustive-deps */ -import { useCallback, useMemo, useState } from 'react' +import { useCallback, useMemo } from 'react' import { Model } from '@janhq/core' import { Badge, Button } from '@janhq/uikit' import { atom, useAtomValue } from 'jotai' +import { ChevronDownIcon } from 'lucide-react' + +import { twMerge } from 'tailwind-merge' + import ModalCancelDownload from '@/containers/ModalCancelDownload' import { MainViewState } from '@/constants/screens' -import { ModelPerformance, TagType } from '@/constants/tagType' +// import { ModelPerformance, TagType } from '@/constants/tagType' import useDownloadModel from '@/hooks/useDownloadModel' import { useDownloadState } from '@/hooks/useDownloadState' @@ -21,18 +25,20 @@ import { toGigabytes } from '@/utils/converter' type Props = { model: Model + onClick: () => void + open: string } -const ExploreModelItemHeader: React.FC = ({ model }) => { - console.log(model) +const ExploreModelItemHeader: React.FC = ({ model, onClick, open }) => { const { downloadModel } = useDownloadModel() const { downloadedModels } = useGetDownloadedModels() const { modelDownloadStateAtom, downloadStates } = useDownloadState() - const [title, setTitle] = useState('Recommended') + // const [title, setTitle] = useState('Recommended') + + // const [performanceTag, setPerformanceTag] = useState( + // ModelPerformance.PerformancePositive + // ) - const [performanceTag, setPerformanceTag] = useState( - ModelPerformance.PerformancePositive - ) const downloadAtom = useMemo( () => atom((get) => get(modelDownloadStateAtom)[model.id]), [model.id] @@ -48,18 +54,14 @@ const ExploreModelItemHeader: React.FC = ({ model }) => { const isDownloaded = downloadedModels.find((md) => md.id === model.id) != null let downloadButton = ( - + ) if (isDownloaded) { downloadButton = (
- +
From 3aa58cee62a2c7f2b6f53d4a4340091a0015264a Mon Sep 17 00:00:00 2001 From: Faisal Amir Date: Mon, 4 Dec 2023 19:18:18 +0700 Subject: [PATCH 30/42] Finished flow hub screen --- web/containers/DropdownListSidebar/index.tsx | 14 +++++++++++--- web/screens/Chat/index.tsx | 2 +- .../ExploreModels/ExploreModelItemHeader/index.tsx | 3 +++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/web/containers/DropdownListSidebar/index.tsx b/web/containers/DropdownListSidebar/index.tsx index 589847fdf..84bc6623b 100644 --- a/web/containers/DropdownListSidebar/index.tsx +++ b/web/containers/DropdownListSidebar/index.tsx @@ -19,6 +19,7 @@ import { twMerge } from 'tailwind-merge' import { MainViewState } from '@/constants/screens' +import { useActiveModel } from '@/hooks/useActiveModel' import { getDownloadedModels } from '@/hooks/useGetDownloadedModels' import { useMainViewState } from '@/hooks/useMainViewState' @@ -35,6 +36,7 @@ export default function DropdownListSidebar() { const activeThread = useAtomValue(activeThreadAtom) const [selected, setSelected] = useState() const { setMainViewState } = useMainViewState() + const { activeModel, stateModel } = useActiveModel() useEffect(() => { getDownloadedModels().then((downloadedModels) => { @@ -42,18 +44,24 @@ export default function DropdownListSidebar() { if (downloadedModels.length > 0) { setSelected( downloadedModels.filter( - (x) => x.id === activeThread?.assistants[0].model.id + (x) => + x.id === activeThread?.assistants[0].model.id || + x.id === activeModel?.id )[0] || downloadedModels[0] ) setSelectedModel( downloadedModels.filter( - (x) => x.id === activeThread?.assistants[0].model.id + (x) => + x.id === activeThread?.assistants[0].model.id || + x.id === activeModel?.id )[0] || downloadedModels[0] ) } }) // eslint-disable-next-line react-hooks/exhaustive-deps - }, [activeThread]) + }, [activeThread, activeModel]) + + if (stateModel.loading) return null return ( Date: Tue, 5 Dec 2023 10:21:41 +0700 Subject: [PATCH 36/42] Fix broken position banner hub screen --- web/screens/ExploreModels/index.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/web/screens/ExploreModels/index.tsx b/web/screens/ExploreModels/index.tsx index de7569212..5e584458c 100644 --- a/web/screens/ExploreModels/index.tsx +++ b/web/screens/ExploreModels/index.tsx @@ -58,7 +58,11 @@ const ExploreModelsScreen = () => {
- Hub Banner + Hub Banner
Date: Tue, 5 Dec 2023 10:24:31 +0700 Subject: [PATCH 37/42] Temporary hide tabs element on hub screen --- web/screens/ExploreModels/index.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/web/screens/ExploreModels/index.tsx b/web/screens/ExploreModels/index.tsx index 5e584458c..fc52c973e 100644 --- a/web/screens/ExploreModels/index.tsx +++ b/web/screens/ExploreModels/index.tsx @@ -78,8 +78,9 @@ const ExploreModelsScreen = () => {
-
-
+
+ {/* Temporary hide tabs */} + {/*
{ -
+
*/}