* hackathon: Refactor Jan into an Electron app * chore: correct NextJS export output path * chore: build electron app for all production targets * fix: correct assetPrefix for production build * chore: preferences shortcut * chore: refactor * chore: refactor into ts * feature/#52-compile-plugin-with-webpack * chore: introduce renderer <=> plugins <=> main invocation * chore: suppress errors - deprecate graphql & next-auth * chore: data plugin functions * add llm support Signed-off-by: James <james@jan.ai> * chore: update plugin * chore: introduce data-plugin * chore: plugin invokes main with args and synchronously * chore: install db plugin should setup db * feature: Data Driver Plugin - Load conversations and messages from data plugin * chore: store text message sent * chore: shared core services * feature: inference service * chore: conversations ordering * adding model management service Signed-off-by: James <james@jan.ai> * chore: strict type * feature: abstract plugin preferences * chore: abstract plugin preference * Revert "chore: strict type" This reverts commit 9be188d827a0b2e081e9e04b192c323799de5bb5. * chore: base-plugin styling * feature: create and delete conversation * chore: fix plugin search & clean messages * chore: typing indicator * chore: refactor useSendChatMessage * chore: persists inserted id to in-memory messages * chore: search conversation history * add delete and download model (#189) Signed-off-by: James <james@jan.ai> Co-authored-by: James <james@jan.ai> * chore: add empty state for conversation list * chore: prompt missing extension function & fix app crashes * chore: prompt user to install required plugins * chore: add launch background * chore: relaunch app on model downloaded * Jan app add installation instruction (#191) Co-authored-by: Hien To <> * Chore: rename folder web-client to app (#192) * Chore: rename folder web-client to app --------- Co-authored-by: Hien To <> * revert: add pre-install package * add progress for downloading model Signed-off-by: James <james@jan.ai> * feature: production bundle * add download progress Signed-off-by: James <james@jan.ai> * chore: add new chat function * fix: electron asar unpack modules & dynamic import * chore: fix unpack * chore: fix dev pack * Add instruction to build dmg file to README.md * init model dynamically Signed-off-by: James <james@jan.ai> --------- Signed-off-by: James <james@jan.ai> Co-authored-by: James <james@jan.ai> Co-authored-by: NamH <NamNh0122@gmail.com> Co-authored-by: hiento09 <136591877+hiento09@users.noreply.github.com> Co-authored-by: Hien To <>
124 lines
4.0 KiB
JavaScript
124 lines
4.0 KiB
JavaScript
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, setConfirmInstall } 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) {
|
|
if (!Object.prototype.hasOwnProperty.call(options, 'useFacade') || options.useFacade) {
|
|
// Store the confirmInstall function
|
|
setConfirmInstall(options.confirmInstall)
|
|
// 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) {
|
|
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()) {
|
|
removePlugin(plugin.name, false)
|
|
}
|
|
|
|
// Read plugin list from plugins folder
|
|
const plugins = JSON.parse(readFileSync(getPluginsFile()))
|
|
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) {
|
|
// Create new plugin, populate it with plg details and save it to the store
|
|
const plugin = new Plugin()
|
|
|
|
for (const key in plg) {
|
|
plugin[key] = plg[key]
|
|
}
|
|
|
|
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,
|
|
}
|
|
}
|