jan/web/extension/ExtensionManager.ts
Louis d85d02693b
feat: Nitro-Tensorrt-LLM Extension (#2280)
* feat: tensorrt-llm-extension

* fix: loading

* feat: add download tensorrt llm runner

Signed-off-by: James <james@jan.ai>

* feat: update to rollupjs instead of webpack for monitoring extension

Signed-off-by: James <james@jan.ai>

* feat: move update nvidia info to monitor extension

Signed-off-by: James <james@jan.ai>

* allow download tensorrt

Signed-off-by: James <james@jan.ai>

* update

Signed-off-by: James <james@jan.ai>

* allow download tensor rt based on gpu setting

Signed-off-by: James <james@jan.ai>

* update downloaded models

Signed-off-by: James <james@jan.ai>

* feat: add extension compatibility

* dynamic tensor rt engines

Signed-off-by: James <james@jan.ai>

* update models

Signed-off-by: James <james@jan.ai>

* chore: remove ts-ignore

* feat: getting installation state from extension

Signed-off-by: James <james@jan.ai>

* chore: adding type for decompress

Signed-off-by: James <james@jan.ai>

* feat: update according Louis's comment

Signed-off-by: James <james@jan.ai>

* feat: add progress for installing extension

Signed-off-by: James <james@jan.ai>

* chore: remove args from extension installation

* fix: model download does not work properly

* fix: do not allow user to stop tensorrtllm inference

* fix: extension installed style

* fix: download tensorrt does not update state

Signed-off-by: James <james@jan.ai>

* chore: replace int4 by fl16

* feat: modal for installing extension

Signed-off-by: James <james@jan.ai>

* fix: start download immediately after press install

Signed-off-by: James <james@jan.ai>

* fix: error switching between engines

* feat: rename inference provider to ai engine and refactor to core

* fix: missing ulid

* fix: core bundler

* feat: add cancel extension installing

Signed-off-by: James <james@jan.ai>

* remove mocking for mac

Signed-off-by: James <james@jan.ai>

* fix: show models only when extension is ready

* add tensorrt badge for model

Signed-off-by: James <james@jan.ai>

* fix: copy

* fix: add compatible check (#2342)

* fix: add compatible check

Signed-off-by: James <james@jan.ai>

* fix: copy

* fix: font

* fix: copy

* fix: broken monitoring extension

* chore: bump engine

* fix: copy

* fix: model copy

* fix: copy

* fix: model json

---------

Signed-off-by: James <james@jan.ai>
Co-authored-by: James <james@jan.ai>
Co-authored-by: Louis <louis@jan.ai>

* fix: vulkan support

* fix: installation button padding

* fix: empty script

* fix: remove hard code string

---------

Signed-off-by: James <james@jan.ai>
Co-authored-by: James <james@jan.ai>
Co-authored-by: NamH <NamNh0122@gmail.com>
2024-03-14 14:07:22 +07:00

157 lines
4.2 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import { BaseExtension, ExtensionTypeEnum } from '@janhq/core'
import Extension from './Extension'
/**
* Manages the registration and retrieval of extensions.
*/
export class ExtensionManager {
private extensions = new Map<string, BaseExtension>()
/**
* Registers an extension.
* @param extension - The extension to register.
*/
register<T extends BaseExtension>(name: string, extension: T) {
this.extensions.set(extension.type() ?? name, extension)
}
/**
* Retrieves a extension by its type.
* @param type - The type of the extension to retrieve.
* @returns The extension, if found.
*/
get<T extends BaseExtension>(
type: ExtensionTypeEnum | string
): T | undefined {
return this.extensions.get(type) as T | undefined
}
/**
* Loads all registered extension.
*/
load() {
this.listExtensions().forEach((ext) => {
ext.onLoad()
})
}
/**
* Unloads all registered extensions.
*/
unload() {
this.listExtensions().forEach((ext) => {
ext.onUnload()
})
}
/**
* Retrieves a list of all registered extensions.
* @returns An array of extensions.
*/
listExtensions() {
return [...this.extensions.values()]
}
/**
* Retrieves a list of all registered extensions.
* @returns An array of extensions.
*/
async getActive(): Promise<Extension[]> {
const res = await window.core?.api?.getActiveExtensions()
if (!res || !Array.isArray(res)) return []
const extensions: Extension[] = res.map(
(ext: any) =>
new Extension(
ext.url,
ext.name,
ext.active,
ext.description,
ext.version
)
)
return extensions
}
/**
* Register a extension with its class.
* @param {Extension} extension extension object as provided by the main process.
* @returns {void}
*/
async activateExtension(extension: Extension) {
// Import class
const extensionUrl = window.electronAPI
? extension.url
: extension.url.replace(
'extension://',
`${window.core?.api?.baseApiUrl ?? ''}/extensions/`
)
await import(/* webpackIgnore: true */ extensionUrl).then(
(extensionClass) => {
// Register class if it has a default export
if (
typeof extensionClass.default === 'function' &&
extensionClass.default.prototype
) {
this.register(
extension.name ?? extension.url,
new extensionClass.default()
)
}
}
)
}
/**
* Registers all active extensions.
* @returns {void}
*/
async registerActive() {
// Get active extensions
const activeExtensions = await this.getActive()
// Activate all
await Promise.all(
activeExtensions.map((ext: Extension) => this.activateExtension(ext))
)
}
/**
* Install a new extension.
* @param {Array.<installOptions | string>} extensions A list of NPM specifiers, or installation configuration objects.
* @returns {Promise.<Array.<Extension> | false>} extension as defined by the main process. Has property cancelled set to true if installation was cancelled in the main process.
*/
async install(extensions: any[]) {
if (typeof window === 'undefined') {
return
}
const res = await window.core?.api?.installExtension(extensions)
if (res.cancelled) return false
return res.map(async (ext: any) => {
const extension = new Extension(ext.name, ext.url, ext.active)
await this.activateExtension(extension)
return extension
})
}
/**
* Uninstall provided extensions
* @param {Array.<string>} extensions List of names of extensions to uninstall.
* @param {boolean} reload Whether to reload all renderers after updating the extensions.
* @returns {Promise.<boolean>} Whether uninstalling the extensions was successful.
*/
uninstall(extensions: string[], reload = true) {
if (typeof window === 'undefined') {
return
}
return window.core?.api?.uninstallExtension(extensions, reload)
}
}
/**
* The singleton instance of the ExtensionManager.
*/
export const extensionManager = new ExtensionManager()