feature: @janhq/plugin-core module & plugins update (#321)
* @janhq/plugin-core module * refactor web to use exported services from module * refactor data-plugin to provide DAL & move model logics to model management plugin * model-management in TS * add ci auto package, increate version, and publish to npm repository * chore: storage operations * chore: hybrid data-plugin esm & cjs module * chore: PouchDB Driver * chore: documentation --------- Co-authored-by: Hien To <hien@jan.ai> Co-authored-by: Service Account <service@jan.ai>
This commit is contained in:
parent
5732ccec94
commit
5fc1ba7067
3
.github/workflows/linter-and-test.yml
vendored
3
.github/workflows/linter-and-test.yml
vendored
@ -43,6 +43,7 @@ jobs:
|
||||
- name: Linter and test
|
||||
run: |
|
||||
yarn config set network-timeout 300000
|
||||
yarn build:core
|
||||
yarn install
|
||||
yarn lint
|
||||
yarn build:plugins
|
||||
@ -68,6 +69,7 @@ jobs:
|
||||
- name: Linter and test
|
||||
run: |
|
||||
yarn config set network-timeout 300000
|
||||
yarn build:core
|
||||
yarn install
|
||||
yarn lint
|
||||
yarn build:plugins
|
||||
@ -96,6 +98,7 @@ jobs:
|
||||
export DISPLAY=$(w -h | awk 'NR==1 {print $2}')
|
||||
echo -e "Display ID: $DISPLAY"
|
||||
yarn config set network-timeout 300000
|
||||
yarn build:core
|
||||
yarn install
|
||||
yarn lint
|
||||
yarn build:plugins
|
||||
|
||||
66
.github/workflows/publish-plugin-core.yml
vendored
Normal file
66
.github/workflows/publish-plugin-core.yml
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
name: Publish Plugin-core Package to npmjs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "plugin-core/**"
|
||||
- ".github/workflows/publish-plugin-core.yml"
|
||||
- "!plugin-core/package.json"
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
environment: production
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: "0"
|
||||
token: ${{ secrets.PAT_SERVICE_ACCOUNT }}
|
||||
|
||||
- name: Install jq
|
||||
uses: dcarbone/install-jq-action@v2.0.1
|
||||
|
||||
- name: "Auto Increase package Version"
|
||||
run: |
|
||||
# Extract current version
|
||||
current_version=$(jq -r '.version' plugin-core/package.json)
|
||||
|
||||
# Break the version into its components
|
||||
major_version=$(echo $current_version | cut -d "." -f 1)
|
||||
minor_version=$(echo $current_version | cut -d "." -f 2)
|
||||
patch_version=$(echo $current_version | cut -d "." -f 3)
|
||||
|
||||
# Increment the patch version by one
|
||||
new_patch_version=$((patch_version+1))
|
||||
|
||||
# Construct the new version
|
||||
new_version="$major_version.$minor_version.$new_patch_version"
|
||||
|
||||
# Replace the old version with the new version in package.json
|
||||
jq --arg version "$new_version" '.version = $version' plugin-core/package.json > /tmp/package.json && mv /tmp/package.json plugin-core/package.json
|
||||
|
||||
# Print the new version
|
||||
echo "Updated package.json version to: $new_version"
|
||||
|
||||
# Setup .npmrc file to publish to npm
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "20.x"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
- run: npm install && npm run build
|
||||
working-directory: ./plugin-core
|
||||
- run: npm publish --access public
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
working-directory: ./plugin-core
|
||||
|
||||
- name: "Commit new version to main and create tag"
|
||||
run: |
|
||||
version=$(jq -r '.version' plugin-core/package.json)
|
||||
git config --global user.email "service@jan.ai"
|
||||
git config --global user.name "Service Account"
|
||||
git add plugin-core/package.json
|
||||
git commit -m "${GITHUB_REPOSITORY}: Update tag build $version"
|
||||
git -c http.extraheader="AUTHORIZATION: bearer ${{ secrets.PAT_SERVICE_ACCOUNT }}" push origin HEAD:feat/#306-plugin-core-module
|
||||
git tag -a plugin-core-$version -m "${GITHUB_REPOSITORY}: Update tag build $version for plugin-core"
|
||||
git -c http.extraheader="AUTHORIZATION: bearer ${{ secrets.PAT_SERVICE_ACCOUNT }}" push origin plugin-core-$version
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,3 +13,4 @@ build
|
||||
electron/renderer
|
||||
|
||||
*.log
|
||||
plugin-core/lib
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./../dist/cjs",
|
||||
"module": "commonjs"
|
||||
},
|
||||
"files": ["../module.ts"]
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./../dist/esm",
|
||||
"module": "esnext"
|
||||
},
|
||||
"files": ["../index.ts"]
|
||||
}
|
||||
@ -1,169 +1,180 @@
|
||||
import { core, store, RegisterExtensionPoint, StoreService, DataService } from "@janhq/plugin-core";
|
||||
|
||||
// Provide an async method to manipulate the price provided by the extension point
|
||||
const MODULE_PATH = "data-plugin/dist/module.js";
|
||||
const MODULE_PATH = "data-plugin/dist/cjs/module.js";
|
||||
|
||||
const storeModel = (model: any) =>
|
||||
new Promise((resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "storeModel", model)
|
||||
.then((res: any) => resolve(res));
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Create a collection on data store
|
||||
*
|
||||
* @param name name of the collection to create
|
||||
* @param schema schema of the collection to create, include fields and their types
|
||||
* @returns Promise<void>
|
||||
*
|
||||
*/
|
||||
function createCollection({ name, schema }: { name: string; schema?: { [key: string]: any } }): Promise<void> {
|
||||
console.log("renderer: creating collection:", name, schema);
|
||||
return core.invokePluginFunc(MODULE_PATH, "createCollection", name, schema);
|
||||
}
|
||||
|
||||
const getFinishedDownloadModels = () =>
|
||||
new Promise((resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "getFinishedDownloadModels")
|
||||
.then((res: any) => resolve(res));
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Delete a collection
|
||||
*
|
||||
* @param name name of the collection to delete
|
||||
* @returns Promise<void>
|
||||
*
|
||||
*/
|
||||
function deleteCollection(name: string): Promise<void> {
|
||||
return core.invokePluginFunc(MODULE_PATH, "deleteCollection", name);
|
||||
}
|
||||
|
||||
const getModelById = (modelId: string) =>
|
||||
new Promise((resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "getModelById", modelId)
|
||||
.then((res: any) => resolve(res));
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Insert a value to a collection
|
||||
*
|
||||
* @param collectionName name of the collection
|
||||
* @param value value to insert
|
||||
* @returns Promise<any>
|
||||
*
|
||||
*/
|
||||
function insertOne({ collectionName, value }: { collectionName: string; value: any }): Promise<any> {
|
||||
return core.invokePluginFunc(MODULE_PATH, "insertOne", collectionName, value);
|
||||
}
|
||||
|
||||
const updateFinishedDownloadAt = (fileName: string) =>
|
||||
new Promise((resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(
|
||||
MODULE_PATH,
|
||||
"updateFinishedDownloadAt",
|
||||
fileName,
|
||||
Date.now()
|
||||
)
|
||||
.then((res: any) => resolve(res));
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Update value of a collection's record
|
||||
*
|
||||
* @param collectionName name of the collection
|
||||
* @param key key of the record to update
|
||||
* @param value value to update
|
||||
* @returns Promise<void>
|
||||
*
|
||||
*/
|
||||
function updateOne({ collectionName, key, value }: { collectionName: string; key: string; value: any }): Promise<void> {
|
||||
return core.invokePluginFunc(MODULE_PATH, "updateOne", collectionName, key, value);
|
||||
}
|
||||
|
||||
const getUnfinishedDownloadModels = () =>
|
||||
new Promise<any>((resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "getUnfinishedDownloadModels")
|
||||
.then((res: any[]) => resolve(res));
|
||||
} else {
|
||||
resolve([]);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Updates all records that match a selector in a collection in the data store.
|
||||
* @param collectionName - The name of the collection containing the records to update.
|
||||
* @param selector - The selector to use to get the records to update.
|
||||
* @param value - The new value for the records.
|
||||
* @returns {Promise<void>} A promise that resolves when the records are updated.
|
||||
*/
|
||||
function updateMany({
|
||||
collectionName,
|
||||
value,
|
||||
selector,
|
||||
}: {
|
||||
collectionName: string;
|
||||
value: any;
|
||||
selector?: { [key: string]: any };
|
||||
}): Promise<void> {
|
||||
return core.invokePluginFunc(MODULE_PATH, "updateMany", collectionName, value, selector);
|
||||
}
|
||||
|
||||
const deleteDownloadModel = (modelId: string) =>
|
||||
new Promise((resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "deleteDownloadModel", modelId)
|
||||
.then((res: any) => resolve(res));
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Delete a collection's record
|
||||
*
|
||||
* @param collectionName name of the collection
|
||||
* @param key key of the record to delete
|
||||
* @returns Promise<void>
|
||||
*
|
||||
*/
|
||||
function deleteOne({ collectionName, key }: { collectionName: string; key: string }): Promise<void> {
|
||||
return core.invokePluginFunc(MODULE_PATH, "deleteOne", collectionName, key);
|
||||
}
|
||||
|
||||
const getConversations = () =>
|
||||
new Promise<any>((resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "getConversations")
|
||||
.then((res: any[]) => resolve(res));
|
||||
} else {
|
||||
resolve([]);
|
||||
}
|
||||
});
|
||||
const getConversationMessages = (id: any) =>
|
||||
new Promise((resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "getConversationMessages", id)
|
||||
.then((res: any[]) => resolve(res));
|
||||
} else {
|
||||
resolve([]);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Deletes all records with a matching key from a collection in the data store.
|
||||
*
|
||||
* @param collectionName name of the collection
|
||||
* @param selector selector to use to get the records to delete.
|
||||
* @returns {Promise<void>}
|
||||
*
|
||||
*/
|
||||
function deleteMany({
|
||||
collectionName,
|
||||
selector,
|
||||
}: {
|
||||
collectionName: string;
|
||||
selector?: { [key: string]: any };
|
||||
}): Promise<void> {
|
||||
return core.invokePluginFunc(MODULE_PATH, "deleteMany", collectionName, selector);
|
||||
}
|
||||
|
||||
const createConversation = (conversation: any) =>
|
||||
new Promise((resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "storeConversation", conversation)
|
||||
.then((res: any) => {
|
||||
resolve(res);
|
||||
});
|
||||
} else {
|
||||
resolve(undefined);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Retrieve a record from a collection in the data store.
|
||||
* @param {string} collectionName - The name of the collection containing the record to retrieve.
|
||||
* @param {string} key - The key of the record to retrieve.
|
||||
* @returns {Promise<any>} A promise that resolves when the record is retrieved.
|
||||
*/
|
||||
function findOne({ collectionName, key }: { collectionName: string; key: string }): Promise<any> {
|
||||
return core.invokePluginFunc(MODULE_PATH, "findOne", collectionName, key);
|
||||
}
|
||||
|
||||
const createMessage = (message: any) =>
|
||||
new Promise((resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "storeMessage", message)
|
||||
.then((res: any) => {
|
||||
resolve(res);
|
||||
});
|
||||
} else {
|
||||
resolve(undefined);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Gets records in a collection in the data store using a selector.
|
||||
* @param {string} collectionName - The name of the collection containing the record to get the value from.
|
||||
* @param {{ [key: string]: any }} selector - The selector to use to get the value from the record.
|
||||
* @param {[{ [key: string]: any }]} sort - The sort options to use to retrieve records.
|
||||
* @returns {Promise<any>} A promise that resolves with the selected value.
|
||||
*/
|
||||
function findMany({
|
||||
collectionName,
|
||||
selector,
|
||||
sort,
|
||||
}: {
|
||||
collectionName: string;
|
||||
selector: { [key: string]: any };
|
||||
sort?: [{ [key: string]: any }];
|
||||
}): Promise<any> {
|
||||
return core.invokePluginFunc(MODULE_PATH, "findMany", collectionName, selector, sort);
|
||||
}
|
||||
|
||||
const updateMessage = (message: any) =>
|
||||
new Promise((resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "updateMessage", message)
|
||||
.then((res: any) => {
|
||||
resolve(res);
|
||||
});
|
||||
} else {
|
||||
resolve(undefined);
|
||||
}
|
||||
});
|
||||
|
||||
const deleteConversation = (id: any) =>
|
||||
new Promise((resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "deleteConversation", id)
|
||||
.then((res: any) => {
|
||||
resolve(res);
|
||||
});
|
||||
} else {
|
||||
resolve("-");
|
||||
}
|
||||
});
|
||||
|
||||
const setupDb = () => {
|
||||
window.electronAPI.invokePluginFunc(MODULE_PATH, "init");
|
||||
};
|
||||
function onStart() {
|
||||
createCollection({ name: "conversations", schema: {} });
|
||||
createCollection({ name: "messages", schema: {} });
|
||||
}
|
||||
|
||||
// Register all the above functions and objects with the relevant extension points
|
||||
export function init({ register }: { register: any }) {
|
||||
setupDb();
|
||||
register("getConversations", "getConv", getConversations, 1);
|
||||
register("createConversation", "insertConv", createConversation);
|
||||
register("updateMessage", "updateMessage", updateMessage);
|
||||
register("deleteConversation", "deleteConv", deleteConversation);
|
||||
register("createMessage", "insertMessage", createMessage);
|
||||
register("getConversationMessages", "getMessages", getConversationMessages);
|
||||
register("storeModel", "storeModel", storeModel);
|
||||
register(
|
||||
"updateFinishedDownloadAt",
|
||||
"updateFinishedDownloadAt",
|
||||
updateFinishedDownloadAt
|
||||
);
|
||||
register(
|
||||
"getUnfinishedDownloadModels",
|
||||
"getUnfinishedDownloadModels",
|
||||
getUnfinishedDownloadModels
|
||||
);
|
||||
register("deleteDownloadModel", "deleteDownloadModel", deleteDownloadModel);
|
||||
register("getModelById", "getModelById", getModelById);
|
||||
register(
|
||||
"getFinishedDownloadModels",
|
||||
"getFinishedDownloadModels",
|
||||
getFinishedDownloadModels
|
||||
);
|
||||
export function init({ register }: { register: RegisterExtensionPoint }) {
|
||||
onStart();
|
||||
|
||||
register(StoreService.CreateCollection, createCollection.name, createCollection);
|
||||
register(StoreService.DeleteCollection, deleteCollection.name, deleteCollection);
|
||||
register(StoreService.InsertOne, insertOne.name, insertOne);
|
||||
register(StoreService.UpdateOne, updateOne.name, updateOne);
|
||||
register(StoreService.UpdateMany, updateMany.name, updateMany);
|
||||
register(StoreService.DeleteOne, deleteOne.name, deleteOne);
|
||||
register(StoreService.DeleteMany, deleteMany.name, deleteMany);
|
||||
register(StoreService.FindOne, findOne.name, findOne);
|
||||
register(StoreService.FindMany, findMany.name, findMany);
|
||||
|
||||
register(DataService.GetConversations, getConversations.name, getConversations);
|
||||
register(DataService.CreateConversation, createConversation.name, createConversation);
|
||||
register(DataService.UpdateMessage, updateMessage.name, updateMessage);
|
||||
register(DataService.DeleteConversation, deleteConversation.name, deleteConversation);
|
||||
register(DataService.CreateMessage, createMessage.name, createMessage);
|
||||
register(DataService.GetConversationMessages, getConversationMessages.name, getConversationMessages);
|
||||
}
|
||||
|
||||
function getConversations(): Promise<any> {
|
||||
return store.findMany("conversations", {}, [{ updatedAt: "desc" }]);
|
||||
}
|
||||
function createConversation(conversation: any): Promise<number | undefined> {
|
||||
return store.insertOne("conversations", conversation);
|
||||
}
|
||||
|
||||
function createMessage(message: any): Promise<number | undefined> {
|
||||
return store.insertOne("messages", message);
|
||||
}
|
||||
function updateMessage(message: any): Promise<void> {
|
||||
return store.updateOne("messages", message._id, message);
|
||||
}
|
||||
|
||||
function deleteConversation(id: any) {
|
||||
return store.deleteOne("conversations", id).then(() => store.deleteMany("messages", { conversationId: id }));
|
||||
}
|
||||
|
||||
function getConversationMessages(conversationId: any) {
|
||||
return store.findMany("messages", { conversationId }, [{ createdAt: "desc" }]);
|
||||
}
|
||||
|
||||
@ -1,497 +1,234 @@
|
||||
const sqlite3 = require("sqlite3").verbose();
|
||||
const path = require("path");
|
||||
const { app } = require("electron");
|
||||
var PouchDB = require("pouchdb-node");
|
||||
PouchDB.plugin(require("pouchdb-find"));
|
||||
var path = require("path");
|
||||
var { app } = require("electron");
|
||||
var fs = require("fs");
|
||||
|
||||
const MODEL_TABLE_CREATION = `
|
||||
CREATE TABLE IF NOT EXISTS models (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
short_description TEXT NOT NULL,
|
||||
avatar_url TEXT,
|
||||
long_description TEXT NOT NULL,
|
||||
author TEXT NOT NULL,
|
||||
version TEXT NOT NULL,
|
||||
model_url TEXT NOT NULL,
|
||||
nsfw INTEGER NOT NULL,
|
||||
tags TEXT NOT NULL,
|
||||
default_greeting TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);`;
|
||||
|
||||
const MODEL_VERSION_TABLE_CREATION = `
|
||||
CREATE TABLE IF NOT EXISTS model_versions (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
quant_method TEXT NOT NULL,
|
||||
bits INTEGER NOT NULL,
|
||||
size INTEGER NOT NULL,
|
||||
max_ram_required INTEGER NOT NULL,
|
||||
usecase TEXT NOT NULL,
|
||||
download_link TEXT NOT NULL,
|
||||
model_id TEXT NOT NULL,
|
||||
start_download_at INTEGER DEFAULT -1,
|
||||
finish_download_at INTEGER DEFAULT -1,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);`;
|
||||
|
||||
const MODEL_TABLE_INSERTION = `
|
||||
INSERT OR IGNORE INTO models (
|
||||
id,
|
||||
name,
|
||||
short_description,
|
||||
avatar_url,
|
||||
long_description,
|
||||
author,
|
||||
version,
|
||||
model_url,
|
||||
nsfw,
|
||||
tags,
|
||||
default_greeting,
|
||||
type
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)`;
|
||||
|
||||
const MODEL_VERSION_TABLE_INSERTION = `
|
||||
INSERT INTO model_versions (
|
||||
id,
|
||||
name,
|
||||
quant_method,
|
||||
bits,
|
||||
size,
|
||||
max_ram_required,
|
||||
usecase,
|
||||
download_link,
|
||||
model_id,
|
||||
start_download_at
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?)`;
|
||||
|
||||
const getDbPath = () => {
|
||||
return path.join(app.getPath("userData"), "jan.db");
|
||||
};
|
||||
|
||||
function init() {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
console.debug(`Database located at ${getDbPath()}`);
|
||||
|
||||
db.serialize(() => {
|
||||
db.run(MODEL_TABLE_CREATION);
|
||||
db.run(MODEL_VERSION_TABLE_CREATION);
|
||||
db.run(
|
||||
"CREATE TABLE IF NOT EXISTS conversations ( id INTEGER PRIMARY KEY, name TEXT, model_id TEXT, image TEXT, message TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP);"
|
||||
);
|
||||
db.run(
|
||||
"CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY, name TEXT, conversation_id INTEGER, user TEXT, message TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP);"
|
||||
);
|
||||
});
|
||||
|
||||
db.close();
|
||||
}
|
||||
const dbs: Record<string, any> = {};
|
||||
|
||||
/**
|
||||
* Store a model in the database when user start downloading it
|
||||
* Create a collection on data store
|
||||
*
|
||||
* @param params: { model, modelVersion }
|
||||
*/
|
||||
function storeModel(params: any) {
|
||||
return new Promise((res) => {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
console.debug("Inserting", JSON.stringify(params));
|
||||
|
||||
const model = params.model;
|
||||
const modelTags = model.tags.join(",");
|
||||
const modelVersion = params.modelVersion;
|
||||
|
||||
db.serialize(() => {
|
||||
const stmt = db.prepare(MODEL_TABLE_INSERTION);
|
||||
stmt.run(
|
||||
model.id,
|
||||
model.name,
|
||||
model.shortDescription,
|
||||
model.avatarUrl,
|
||||
model.longDescription,
|
||||
model.author,
|
||||
model.version,
|
||||
model.modelUrl,
|
||||
model.nsfw,
|
||||
modelTags,
|
||||
model.greeting,
|
||||
model.type
|
||||
);
|
||||
stmt.finalize();
|
||||
|
||||
const stmt2 = db.prepare(MODEL_VERSION_TABLE_INSERTION);
|
||||
stmt2.run(
|
||||
modelVersion.id,
|
||||
modelVersion.name,
|
||||
modelVersion.quantMethod,
|
||||
modelVersion.bits,
|
||||
modelVersion.size,
|
||||
modelVersion.maxRamRequired,
|
||||
modelVersion.usecase,
|
||||
modelVersion.downloadLink,
|
||||
model.id,
|
||||
modelVersion.startDownloadAt
|
||||
);
|
||||
|
||||
stmt2.finalize();
|
||||
});
|
||||
|
||||
db.close();
|
||||
res(undefined);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the finished download time of a model
|
||||
* @param name name of the collection to create
|
||||
* @param schema schema of the collection to create, include fields and their types
|
||||
* @returns Promise<void>
|
||||
*
|
||||
* @param model Product
|
||||
*/
|
||||
function updateFinishedDownloadAt(modelVersionId: string) {
|
||||
return new Promise((res, rej) => {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
const time = Date.now();
|
||||
console.debug(
|
||||
`Updating finished downloaded model version ${modelVersionId}`
|
||||
);
|
||||
const stmt = `UPDATE model_versions SET finish_download_at = ? WHERE id = ?`;
|
||||
db.run(stmt, [time, modelVersionId], (err: any) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
rej(err);
|
||||
} else {
|
||||
console.log("Updated 1 row");
|
||||
res("Updated");
|
||||
}
|
||||
});
|
||||
|
||||
db.close();
|
||||
function createCollection(name: string, schema?: { [key: string]: any }): Promise<void> {
|
||||
return new Promise<void>((resolve) => {
|
||||
const dbPath = path.join(app.getPath("userData"), "databases");
|
||||
if (!fs.existsSync(dbPath)) fs.mkdirSync(dbPath);
|
||||
const db = new PouchDB(`${path.join(dbPath, name)}`);
|
||||
dbs[name] = db;
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all unfinished models from the database
|
||||
* Delete a collection
|
||||
*
|
||||
* @param name name of the collection to delete
|
||||
* @returns Promise<void>
|
||||
*
|
||||
*/
|
||||
function getUnfinishedDownloadModels() {
|
||||
return new Promise((res) => {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
function deleteCollection(name: string): Promise<void> {
|
||||
// Do nothing with Unstructured Database
|
||||
return dbs[name].destroy();
|
||||
}
|
||||
|
||||
const query = `SELECT * FROM model_versions WHERE finish_download_at = -1 ORDER BY start_download_at DESC`;
|
||||
db.all(query, (err: Error, row: any) => {
|
||||
if (row) {
|
||||
res(row);
|
||||
} else {
|
||||
res([]);
|
||||
}
|
||||
/**
|
||||
* Insert a value to a collection
|
||||
*
|
||||
* @param collectionName name of the collection
|
||||
* @param value value to insert
|
||||
* @returns Promise<any>
|
||||
*
|
||||
*/
|
||||
function insertOne(collectionName: string, value: any): Promise<any> {
|
||||
if (!value._id) return dbs[collectionName].post(value).then((doc) => doc.id);
|
||||
return dbs[collectionName].put(value).then((doc) => doc.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update value of a collection's record
|
||||
*
|
||||
* @param collectionName name of the collection
|
||||
* @param key key of the record to update
|
||||
* @param value value to update
|
||||
* @returns Promise<void>
|
||||
*
|
||||
*/
|
||||
function updateOne(collectionName: string, key: string, value: any): Promise<void> {
|
||||
return dbs[collectionName].get(key).then((doc) => {
|
||||
return dbs[collectionName].put({
|
||||
_id: key,
|
||||
_rev: doc._rev,
|
||||
force: true,
|
||||
...value,
|
||||
});
|
||||
db.close();
|
||||
});
|
||||
}
|
||||
|
||||
async function getFinishedDownloadModels() {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
try {
|
||||
const query = `SELECT * FROM model_versions WHERE finish_download_at != -1 ORDER BY finish_download_at DESC`;
|
||||
const modelVersions: any = await new Promise((resolve, reject) => {
|
||||
db.all(query, (err: Error, rows: any[]) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(rows);
|
||||
}
|
||||
});
|
||||
});
|
||||
/**
|
||||
* Update value of a collection's records
|
||||
*
|
||||
* @param collectionName name of the collection
|
||||
* @param selector selector of records to update
|
||||
* @param value value to update
|
||||
* @returns Promise<void>
|
||||
*
|
||||
*/
|
||||
function updateMany(collectionName: string, value: any, selector?: { [key: string]: any }): Promise<any> {
|
||||
// Creates keys from selector for indexing
|
||||
const keys = selector ? Object.keys(selector) : [];
|
||||
|
||||
const models = await Promise.all(
|
||||
modelVersions.map(async (modelVersion) => {
|
||||
const modelQuery = `SELECT * FROM models WHERE id = ?`;
|
||||
return new Promise((resolve, reject) => {
|
||||
db.get(
|
||||
modelQuery,
|
||||
[modelVersion.model_id],
|
||||
(err: Error, row: any) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(row);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
// At a basic level, there are two steps to running a query: createIndex()
|
||||
// (to define which fields to index) and find() (to query the index).
|
||||
return (
|
||||
keys.length > 0
|
||||
? dbs[collectionName].createIndex({
|
||||
// There is selector so we need to create index
|
||||
index: { fields: keys },
|
||||
})
|
||||
: Promise.resolve()
|
||||
) // No selector, so no need to create index
|
||||
.then(() =>
|
||||
dbs[collectionName].find({
|
||||
// Find documents using Mango queries
|
||||
selector,
|
||||
})
|
||||
);
|
||||
|
||||
const downloadedModels = [];
|
||||
modelVersions.forEach((modelVersion: any) => {
|
||||
const model = models.find((m: any) => m.id === modelVersion.model_id);
|
||||
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
|
||||
const assistantModel = {
|
||||
id: modelVersion.id,
|
||||
name: modelVersion.name,
|
||||
quantMethod: modelVersion.quant_method,
|
||||
bits: modelVersion.bits,
|
||||
size: modelVersion.size,
|
||||
maxRamRequired: modelVersion.max_ram_required,
|
||||
usecase: modelVersion.usecase,
|
||||
downloadLink: modelVersion.download_link,
|
||||
startDownloadAt: modelVersion.start_download_at,
|
||||
finishDownloadAt: modelVersion.finish_download_at,
|
||||
productId: model.id,
|
||||
productName: model.name,
|
||||
shortDescription: model.short_description,
|
||||
longDescription: model.long_description,
|
||||
avatarUrl: model.avatar_url,
|
||||
author: model.author,
|
||||
version: model.version,
|
||||
modelUrl: model.model_url,
|
||||
nsfw: model.nsfw === 0 ? false : true,
|
||||
greeting: model.default_greeting,
|
||||
type: model.type,
|
||||
createdAt: new Date(model.created_at).getTime(),
|
||||
updatedAt: new Date(model.updated_at ?? "").getTime(),
|
||||
status: "",
|
||||
releaseDate: -1,
|
||||
tags: model.tags.split(","),
|
||||
};
|
||||
downloadedModels.push(assistantModel);
|
||||
)
|
||||
.then((data) => {
|
||||
const docs = data.docs.map((doc) => {
|
||||
// Update doc with new value
|
||||
return (doc = {
|
||||
...doc,
|
||||
...value,
|
||||
});
|
||||
});
|
||||
return dbs[collectionName].bulkDocs(docs);
|
||||
});
|
||||
}
|
||||
|
||||
db.close();
|
||||
/**
|
||||
* Delete a collection's record
|
||||
*
|
||||
* @param collectionName name of the collection
|
||||
* @param key key of the record to delete
|
||||
* @returns Promise<void>
|
||||
*
|
||||
*/
|
||||
function deleteOne(collectionName: string, key: string): Promise<void> {
|
||||
return findOne(collectionName, key).then((doc) => dbs[collectionName].remove(doc));
|
||||
}
|
||||
|
||||
return downloadedModels;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return [];
|
||||
/**
|
||||
* Delete a collection records by selector
|
||||
*
|
||||
* @param {string} collectionName name of the collection
|
||||
* @param {{ [key: string]: any }} selector selector for retrieving records.
|
||||
* @returns Promise<void>
|
||||
*
|
||||
*/
|
||||
function deleteMany(collectionName: string, selector?: { [key: string]: any }): Promise<void> {
|
||||
// Creates keys from selector for indexing
|
||||
const keys = selector ? Object.keys(selector) : [];
|
||||
|
||||
// At a basic level, there are two steps to running a query: createIndex()
|
||||
// (to define which fields to index) and find() (to query the index).
|
||||
return (
|
||||
keys.length > 0
|
||||
? dbs[collectionName].createIndex({
|
||||
// There is selector so we need to create index
|
||||
index: { fields: keys },
|
||||
})
|
||||
: Promise.resolve()
|
||||
) // No selector, so no need to create index
|
||||
.then(() =>
|
||||
dbs[collectionName].find({
|
||||
// Find documents using Mango queries
|
||||
selector,
|
||||
})
|
||||
)
|
||||
.then((data) => {
|
||||
return Promise.all(
|
||||
// Remove documents
|
||||
data.docs.map((doc) => {
|
||||
return dbs[collectionName].remove(doc);
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a record from a collection in the data store.
|
||||
* @param {string} collectionName - The name of the collection containing the record to retrieve.
|
||||
* @param {string} key - The key of the record to retrieve.
|
||||
* @returns {Promise<any>} A promise that resolves when the record is retrieved.
|
||||
*/
|
||||
function findOne(collectionName: string, key: string): Promise<any> {
|
||||
return dbs[collectionName].get(key).catch(() => undefined);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets records in a collection in the data store using a selector.
|
||||
* @param {string} collectionName - The name of the collection containing records to retrieve.
|
||||
* @param {{ [key: string]: any }} selector - The selector to use to retrieve records.
|
||||
* @param {[{ [key: string]: any }]} sort - The sort options to use to retrieve records.
|
||||
* @returns {Promise<any>} A promise that resolves with the selected records.
|
||||
*/
|
||||
function findMany(
|
||||
collectionName: string,
|
||||
selector?: { [key: string]: any },
|
||||
sort?: [{ [key: string]: any }]
|
||||
): Promise<any> {
|
||||
const keys = selector ? Object.keys(selector) : [];
|
||||
const sortKeys = sort ? sort.flatMap((e) => (e ? Object.keys(e) : undefined)) : [];
|
||||
|
||||
// Note that we are specifying that the field must be greater than or equal to null
|
||||
// which is a workaround for the fact that the Mango query language requires us to have a selector.
|
||||
// In CouchDB collation order, null is the "lowest" value, and so this will return all documents regardless of their field value.
|
||||
sortKeys.forEach((key) => {
|
||||
if (!keys.includes(key)) {
|
||||
selector = { ...selector, [key]: { $gt: null } };
|
||||
}
|
||||
});
|
||||
|
||||
// There is no selector & sort, so we can just use allDocs() to get all the documents.
|
||||
if (sortKeys.concat(keys).length === 0) {
|
||||
return dbs[collectionName]
|
||||
.allDocs({
|
||||
include_docs: true,
|
||||
endkey: "_design",
|
||||
inclusive_end: false,
|
||||
})
|
||||
.then((data) => data.rows.map((row) => row.doc));
|
||||
}
|
||||
}
|
||||
|
||||
function deleteDownloadModel(modelId: string) {
|
||||
return new Promise((res) => {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
console.debug(`Deleting ${modelId}`);
|
||||
db.serialize(() => {
|
||||
const stmt = db.prepare("DELETE FROM model_versions WHERE id = ?");
|
||||
stmt.run(modelId);
|
||||
stmt.finalize();
|
||||
res(modelId);
|
||||
});
|
||||
|
||||
db.close();
|
||||
});
|
||||
}
|
||||
|
||||
function fetchModelVersion(db: any, versionId: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.get(
|
||||
"SELECT * FROM model_versions WHERE id = ?",
|
||||
[versionId],
|
||||
(err, row) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(row);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async function fetchModel(db: any, modelId: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.get("SELECT * FROM models WHERE id = ?", [modelId], (err, row) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(row);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const getModelById = async (versionId: string): Promise<any | undefined> => {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
const modelVersion: any | undefined = await fetchModelVersion(db, versionId);
|
||||
if (!modelVersion) return undefined;
|
||||
const model: any | undefined = await fetchModel(db, modelVersion.model_id);
|
||||
if (!model) return undefined;
|
||||
|
||||
const assistantModel = {
|
||||
id: modelVersion.id,
|
||||
name: modelVersion.name,
|
||||
quantMethod: modelVersion.quant_method,
|
||||
bits: modelVersion.bits,
|
||||
size: modelVersion.size,
|
||||
maxRamRequired: modelVersion.max_ram_required,
|
||||
usecase: modelVersion.usecase,
|
||||
downloadLink: modelVersion.download_link,
|
||||
startDownloadAt: modelVersion.start_download_at,
|
||||
finishDownloadAt: modelVersion.finish_download_at,
|
||||
productId: model.id,
|
||||
productName: model.name,
|
||||
shortDescription: model.short_description,
|
||||
longDescription: model.long_description,
|
||||
avatarUrl: model.avatar_url,
|
||||
author: model.author,
|
||||
version: model.version,
|
||||
modelUrl: model.model_url,
|
||||
nsfw: model.nsfw === 0 ? false : true,
|
||||
greeting: model.default_greeting,
|
||||
type: model.type,
|
||||
createdAt: new Date(model.created_at).getTime(),
|
||||
updatedAt: new Date(model.updated_at ?? "").getTime(),
|
||||
status: "",
|
||||
releaseDate: -1,
|
||||
tags: model.tags.split(","),
|
||||
};
|
||||
|
||||
return assistantModel;
|
||||
};
|
||||
|
||||
function getConversations() {
|
||||
return new Promise((res) => {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
|
||||
db.all(
|
||||
"SELECT * FROM conversations ORDER BY updated_at DESC",
|
||||
(err: any, row: any) => {
|
||||
res(row);
|
||||
}
|
||||
);
|
||||
db.close();
|
||||
});
|
||||
}
|
||||
|
||||
function storeConversation(conversation: any): Promise<number | undefined> {
|
||||
return new Promise((res) => {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
|
||||
db.serialize(() => {
|
||||
const stmt = db.prepare(
|
||||
"INSERT INTO conversations (name, model_id, image, message) VALUES (?, ?, ?, ?)"
|
||||
);
|
||||
stmt.run(
|
||||
conversation.name,
|
||||
conversation.model_id,
|
||||
conversation.image,
|
||||
conversation.message,
|
||||
function (err: any) {
|
||||
if (err) {
|
||||
// Handle the insertion error here
|
||||
console.error(err.message);
|
||||
res(undefined);
|
||||
return;
|
||||
}
|
||||
// @ts-ignoreF
|
||||
const id = this.lastID;
|
||||
res(id);
|
||||
return;
|
||||
}
|
||||
);
|
||||
stmt.finalize();
|
||||
});
|
||||
|
||||
db.close();
|
||||
});
|
||||
}
|
||||
|
||||
function storeMessage(message: any): Promise<number | undefined> {
|
||||
return new Promise((res) => {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
|
||||
db.serialize(() => {
|
||||
const stmt = db.prepare(
|
||||
"INSERT INTO messages (name, conversation_id, user, message) VALUES (?, ?, ?, ?)"
|
||||
);
|
||||
stmt.run(
|
||||
message.name,
|
||||
message.conversation_id,
|
||||
message.user,
|
||||
message.message,
|
||||
function (err: any) {
|
||||
if (err) {
|
||||
// Handle the insertion error here
|
||||
console.error(err.message);
|
||||
res(undefined);
|
||||
return;
|
||||
}
|
||||
//@ts-ignore
|
||||
const id = this.lastID;
|
||||
res(id);
|
||||
return;
|
||||
}
|
||||
);
|
||||
stmt.finalize();
|
||||
});
|
||||
|
||||
db.close();
|
||||
});
|
||||
}
|
||||
|
||||
function updateMessage(message: any): Promise<number | undefined> {
|
||||
return new Promise((res) => {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
|
||||
db.serialize(() => {
|
||||
const stmt = db.prepare(
|
||||
"UPDATE messages SET message = ?, updated_at = ? WHERE id = ?"
|
||||
);
|
||||
stmt.run(message.message, message.updated_at, message.id);
|
||||
stmt.finalize();
|
||||
res(message.id);
|
||||
});
|
||||
|
||||
db.close();
|
||||
});
|
||||
}
|
||||
|
||||
function deleteConversation(id: any) {
|
||||
return new Promise((res) => {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
|
||||
db.serialize(() => {
|
||||
const deleteConv = db.prepare("DELETE FROM conversations WHERE id = ?");
|
||||
deleteConv.run(id);
|
||||
deleteConv.finalize();
|
||||
const deleteMessages = db.prepare(
|
||||
"DELETE FROM messages WHERE conversation_id = ?"
|
||||
);
|
||||
deleteMessages.run(id);
|
||||
deleteMessages.finalize();
|
||||
res(id);
|
||||
});
|
||||
|
||||
db.close();
|
||||
});
|
||||
}
|
||||
|
||||
function getConversationMessages(conversation_id: any) {
|
||||
return new Promise((res) => {
|
||||
const db = new sqlite3.Database(getDbPath());
|
||||
|
||||
const query = `SELECT * FROM messages WHERE conversation_id = ${conversation_id} ORDER BY id DESC`;
|
||||
db.all(query, (err: Error, row: any) => {
|
||||
res(row);
|
||||
});
|
||||
db.close();
|
||||
});
|
||||
// At a basic level, there are two steps to running a query: createIndex()
|
||||
// (to define which fields to index) and find() (to query the index).
|
||||
return dbs[collectionName]
|
||||
.createIndex({
|
||||
// Create index for selector & sort
|
||||
index: { fields: sortKeys.concat(keys) },
|
||||
})
|
||||
.then(() => {
|
||||
// Find documents using Mango queries
|
||||
return dbs[collectionName].find({
|
||||
selector,
|
||||
sort,
|
||||
});
|
||||
})
|
||||
.then((data) => data.docs); // Return documents
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init,
|
||||
getConversations,
|
||||
deleteConversation,
|
||||
storeConversation,
|
||||
storeMessage,
|
||||
updateMessage,
|
||||
getConversationMessages,
|
||||
storeModel,
|
||||
updateFinishedDownloadAt,
|
||||
getUnfinishedDownloadModels,
|
||||
getFinishedDownloadModels,
|
||||
deleteDownloadModel,
|
||||
getModelById,
|
||||
createCollection,
|
||||
deleteCollection,
|
||||
insertOne,
|
||||
findOne,
|
||||
findMany,
|
||||
updateOne,
|
||||
updateMany,
|
||||
deleteOne,
|
||||
deleteMany,
|
||||
};
|
||||
|
||||
2016
electron/core/plugins/data-plugin/package-lock.json
generated
2016
electron/core/plugins/data-plugin/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,25 +1,27 @@
|
||||
{
|
||||
"name": "data-plugin",
|
||||
"version": "1.0.2",
|
||||
"description": "Jan Database Plugin efficiently stores conversation and model data using SQLite, providing accessible data management",
|
||||
"version": "1.0.3",
|
||||
"description": "The Data Connector provides easy access to a data API using the PouchDB engine. It offers accessible data management capabilities.",
|
||||
"icon": "https://raw.githubusercontent.com/tailwindlabs/heroicons/88e98b0c2b458553fbadccddc2d2f878edc0387b/src/20/solid/circle-stack.svg",
|
||||
"main": "dist/index.js",
|
||||
"main": "dist/esm/index.js",
|
||||
"author": "Jan",
|
||||
"license": "MIT",
|
||||
"activationPoints": [
|
||||
"init"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc -b . && webpack --config webpack.config.js",
|
||||
"postinstall": "rimraf ./data-plugin*.tgz && node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=darwin --target_libc=unknown --target_arch=x64 && node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=darwin --target_libc=unknown --target_arch=arm64 && node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --target_libc=glibc --target_arch=x64 && node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --target_libc=musl --target_arch=x64 && node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=win32 --target_libc=unknown --target_arch=x64 && npm run build",
|
||||
"build": "tsc --project ./config/tsconfig.esm.json && tsc --project ./config/tsconfig.cjs.json && webpack --config webpack.config.js",
|
||||
"postinstall": "rimraf ./data-plugin*.tgz && npm run build",
|
||||
"build:publish": "npm pack && cpx *.tgz ../../pre-install"
|
||||
},
|
||||
"exports": {
|
||||
".": "./dist/index.js",
|
||||
"./main": "./dist/module.js"
|
||||
"import": "./dist/esm/index.js",
|
||||
"require": "./dist/cjs/module.js",
|
||||
"default": "./dist/esm/index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cpx": "^1.5.0",
|
||||
"node-pre-gyp": "^0.17.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-loader": "^9.4.4",
|
||||
"ts-node": "^10.9.1",
|
||||
@ -28,8 +30,8 @@
|
||||
"webpack-cli": "^5.1.4"
|
||||
},
|
||||
"bundledDependencies": [
|
||||
"sql.js",
|
||||
"sqlite3"
|
||||
"pouchdb-node",
|
||||
"pouchdb-find"
|
||||
],
|
||||
"files": [
|
||||
"dist/**",
|
||||
@ -37,7 +39,8 @@
|
||||
"node_modules"
|
||||
],
|
||||
"dependencies": {
|
||||
"node-pre-gyp": "^0.17.0",
|
||||
"sqlite3": "^5.1.6"
|
||||
"@janhq/plugin-core": "file:../../../../plugin-core",
|
||||
"pouchdb-find": "^8.0.1",
|
||||
"pouchdb-node": "^8.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,22 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
/* Language and Environment */
|
||||
"target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
||||
/* Modules */
|
||||
"module": "ES6" /* Specify what module code is generated. */,
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "." /* Specify the base directory to resolve non-relative module names. */,
|
||||
// "paths": {} /* Specify a set of entries that re-map imports to additional lookup locations. */,
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||
|
||||
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
|
||||
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
|
||||
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
|
||||
/* Type Checking */
|
||||
"strict": false /* Enable all strict type-checking options. */,
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
"target": "es2016",
|
||||
"module": "ES6",
|
||||
"moduleResolution": "node",
|
||||
"outDir": "./dist",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": false,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
export {};
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
electronAPI?: any | undefined;
|
||||
}
|
||||
}
|
||||
@ -14,12 +14,15 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
output: {
|
||||
filename: "index.js", // Adjust the output file name as needed
|
||||
filename: "esm/index.js", // Adjust the output file name as needed
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
library: { type: "module" }, // Specify ESM output format
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".ts", ".js"],
|
||||
},
|
||||
optimization: {
|
||||
minimize: false
|
||||
},
|
||||
// Add loaders and other configuration as needed for your project
|
||||
};
|
||||
|
||||
@ -1,67 +0,0 @@
|
||||
const MODULE_PATH = "model-management-plugin/dist/module.js";
|
||||
|
||||
const getDownloadedModels = () =>
|
||||
new Promise(async (resolve) => {
|
||||
if (window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "getDownloadedModels")
|
||||
.then((res) => resolve(res));
|
||||
}
|
||||
});
|
||||
|
||||
const getAvailableModels = () =>
|
||||
new Promise(async (resolve) => {
|
||||
if (window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "getAvailableModels")
|
||||
.then((res) => resolve(res));
|
||||
}
|
||||
});
|
||||
|
||||
const downloadModel = (product) =>
|
||||
new Promise(async (resolve) => {
|
||||
if (window && window.electronAPI) {
|
||||
window.electronAPI
|
||||
.downloadFile(product.downloadUrl, product.fileName)
|
||||
.then((res) => resolve(res));
|
||||
} else {
|
||||
resolve("-");
|
||||
}
|
||||
});
|
||||
|
||||
const deleteModel = (path) =>
|
||||
new Promise(async (resolve) => {
|
||||
if (window.electronAPI) {
|
||||
console.debug(`Delete model model management plugin: ${path}`);
|
||||
const response = await window.electronAPI.deleteFile(path);
|
||||
resolve(response);
|
||||
}
|
||||
});
|
||||
|
||||
const searchModels = (params) =>
|
||||
new Promise(async (resolve) => {
|
||||
if (window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "searchModels", params)
|
||||
.then((res) => resolve(res));
|
||||
}
|
||||
});
|
||||
|
||||
const getConfiguredModels = () =>
|
||||
new Promise(async (resolve) => {
|
||||
if (window.electronAPI) {
|
||||
window.electronAPI
|
||||
.invokePluginFunc(MODULE_PATH, "getConfiguredModels")
|
||||
.then((res) => resolve(res));
|
||||
}
|
||||
});
|
||||
|
||||
// Register all the above functions and objects with the relevant extension points
|
||||
export function init({ register }) {
|
||||
register("getDownloadedModels", "getDownloadedModels", getDownloadedModels);
|
||||
register("getAvailableModels", "getAvailableModels", getAvailableModels);
|
||||
register("downloadModel", "downloadModel", downloadModel);
|
||||
register("deleteModel", "deleteModel", deleteModel);
|
||||
register("searchModels", "searchModels", searchModels);
|
||||
register("getConfiguredModels", "getConfiguredModels", getConfiguredModels);
|
||||
}
|
||||
103
electron/core/plugins/model-management-plugin/index.ts
Normal file
103
electron/core/plugins/model-management-plugin/index.ts
Normal file
@ -0,0 +1,103 @@
|
||||
import { ModelManagementService, RegisterExtensionPoint, core, store } from "@janhq/plugin-core";
|
||||
const MODULE_PATH = "model-management-plugin/dist/module.js";
|
||||
|
||||
const getDownloadedModels = () => core.invokePluginFunc(MODULE_PATH, "getDownloadedModels");
|
||||
|
||||
const getAvailableModels = () => core.invokePluginFunc(MODULE_PATH, "getAvailableModels");
|
||||
|
||||
const downloadModel = (product) => core.downloadFile(product.downloadUrl, product.fileName);
|
||||
|
||||
const deleteModel = (path) => core.deleteFile(path);
|
||||
|
||||
const searchModels = (params) => core.invokePluginFunc(MODULE_PATH, "searchModels", params);
|
||||
|
||||
const getConfiguredModels = () => core.invokePluginFunc(MODULE_PATH, "getConfiguredModels");
|
||||
|
||||
/**
|
||||
* Store a model in the database when user start downloading it
|
||||
*
|
||||
* @param model Product
|
||||
*/
|
||||
function storeModel(model: any) {
|
||||
return store.findOne("models", model._id).then((doc) => {
|
||||
if (doc) {
|
||||
return store.updateOne("models", model._id, model);
|
||||
} else {
|
||||
return store.insertOne("models", model);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the finished download time of a model
|
||||
*
|
||||
* @param model Product
|
||||
*/
|
||||
function updateFinishedDownloadAt(_id: string): Promise<any> {
|
||||
return store.updateMany("models", { _id }, { time: Date.now(), finishDownloadAt: 1 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all unfinished models from the database.
|
||||
*
|
||||
* @returns A promise that resolves with an array of unfinished models.
|
||||
*/
|
||||
function getUnfinishedDownloadModels(): Promise<any> {
|
||||
return store.findMany("models", { finishDownloadAt: -1 }, [{ startDownloadAt: "desc" }]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all finished models from the database.
|
||||
*
|
||||
* @returns A promise that resolves with an array of finished models.
|
||||
*/
|
||||
function getFinishedDownloadModels(): Promise<any> {
|
||||
return store.findMany("models", { finishDownloadAt: 1 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a model from the database.
|
||||
*
|
||||
* @param modelId The ID of the model to delete.
|
||||
* @returns A promise that resolves when the model is deleted.
|
||||
*/
|
||||
function deleteDownloadModel(modelId: string): Promise<any> {
|
||||
return store.deleteOne("models", modelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a model from the database by ID.
|
||||
*
|
||||
* @param modelId The ID of the model to retrieve.
|
||||
* @returns A promise that resolves with the model.
|
||||
*/
|
||||
function getModelById(modelId: string): Promise<any> {
|
||||
return store.findOne("models", modelId);
|
||||
}
|
||||
|
||||
function onStart() {
|
||||
store.createCollection("models", {});
|
||||
}
|
||||
|
||||
// Register all the above functions and objects with the relevant extension points
|
||||
export function init({ register }: { register: RegisterExtensionPoint }) {
|
||||
onStart();
|
||||
|
||||
register(ModelManagementService.GetDownloadedModels, getDownloadedModels.name, getDownloadedModels);
|
||||
register(ModelManagementService.GetAvailableModels, getAvailableModels.name, getAvailableModels);
|
||||
register(ModelManagementService.DownloadModel, downloadModel.name, downloadModel);
|
||||
register(ModelManagementService.DeleteModel, deleteModel.name, deleteModel);
|
||||
register(ModelManagementService.SearchModels, searchModels.name, searchModels);
|
||||
register(ModelManagementService.GetConfiguredModels, getConfiguredModels.name, getConfiguredModels);
|
||||
|
||||
register(ModelManagementService.StoreModel, storeModel.name, storeModel);
|
||||
register(ModelManagementService.UpdateFinishedDownloadAt, updateFinishedDownloadAt.name, updateFinishedDownloadAt);
|
||||
register(
|
||||
ModelManagementService.GetUnfinishedDownloadModels,
|
||||
getUnfinishedDownloadModels.name,
|
||||
getUnfinishedDownloadModels
|
||||
);
|
||||
register(ModelManagementService.DeleteDownloadModel, deleteDownloadModel.name, deleteDownloadModel);
|
||||
register(ModelManagementService.GetModelById, getModelById.name, getModelById);
|
||||
register(ModelManagementService.GetFinishedDownloadModels, getFinishedDownloadModels.name, getFinishedDownloadModels);
|
||||
}
|
||||
@ -83,7 +83,7 @@ const listFilesByName = async (modelName) => {
|
||||
};
|
||||
|
||||
async function getConfiguredModels() {
|
||||
const files = await getModelFiles();
|
||||
const files: any = await getModelFiles();
|
||||
|
||||
const promises = files.map((file) => getContent(file));
|
||||
const response = await Promise.all(promises);
|
||||
@ -100,7 +100,7 @@ const parseToModel = (model) => {
|
||||
const modelVersions = [];
|
||||
model.versions.forEach((v) => {
|
||||
const version = {
|
||||
id: `${model.author}-${v.name}`,
|
||||
_id: `${model.author}-${v.name}`,
|
||||
name: v.name,
|
||||
quantMethod: v.quantMethod,
|
||||
bits: v.bits,
|
||||
@ -114,7 +114,7 @@ const parseToModel = (model) => {
|
||||
});
|
||||
|
||||
const product = {
|
||||
id: model.id,
|
||||
_id: model.id,
|
||||
name: model.name,
|
||||
shortDescription: model.shortDescription,
|
||||
avatarUrl: model.avatarUrl,
|
||||
@ -13,7 +13,9 @@
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@huggingface/hub": "^0.8.5"
|
||||
"@huggingface/hub": "^0.8.5",
|
||||
"@janhq/plugin-core": "file:../../../../plugin-core",
|
||||
"ts-loader": "^9.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cpx": "^1.5.0",
|
||||
@ -22,6 +24,14 @@
|
||||
"webpack-cli": "^5.1.4"
|
||||
}
|
||||
},
|
||||
"../../../../plugin-core": {
|
||||
"name": "@janhq/plugin-core",
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@discoveryjs/json-ext": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
|
||||
@ -43,11 +53,14 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@janhq/plugin-core": {
|
||||
"resolved": "../../../../plugin-core",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
|
||||
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/set-array": "^1.0.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||
@ -61,7 +74,6 @@
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
|
||||
"integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
@ -70,7 +82,6 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
|
||||
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
@ -79,7 +90,6 @@
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz",
|
||||
"integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.0",
|
||||
"@jridgewell/trace-mapping": "^0.3.9"
|
||||
@ -88,14 +98,12 @@
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.19",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz",
|
||||
"integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
@ -105,7 +113,6 @@
|
||||
"version": "8.44.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.3.tgz",
|
||||
"integrity": "sha512-iM/WfkwAhwmPff3wZuPLYiHX18HI24jU8k1ZSH7P8FHwxTjZ2P6CoX2wnF43oprR+YXJM6UUxATkNvyv/JHd+g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "*",
|
||||
"@types/json-schema": "*"
|
||||
@ -115,7 +122,6 @@
|
||||
"version": "3.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.5.tgz",
|
||||
"integrity": "sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/eslint": "*",
|
||||
"@types/estree": "*"
|
||||
@ -124,26 +130,22 @@
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz",
|
||||
"integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA=="
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz",
|
||||
"integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.2.tgz",
|
||||
"integrity": "sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/ast": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz",
|
||||
"integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/helper-numbers": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6"
|
||||
@ -152,26 +154,22 @@
|
||||
"node_modules/@webassemblyjs/floating-point-hex-parser": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
|
||||
"integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-api-error": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
|
||||
"integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
|
||||
"dev": true
|
||||
"integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-buffer": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz",
|
||||
"integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-numbers": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
|
||||
"integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/floating-point-hex-parser": "1.11.6",
|
||||
"@webassemblyjs/helper-api-error": "1.11.6",
|
||||
@ -181,14 +179,12 @@
|
||||
"node_modules/@webassemblyjs/helper-wasm-bytecode": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
|
||||
"integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/helper-wasm-section": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz",
|
||||
"integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.11.6",
|
||||
"@webassemblyjs/helper-buffer": "1.11.6",
|
||||
@ -200,7 +196,6 @@
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
|
||||
"integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@xtuc/ieee754": "^1.2.0"
|
||||
}
|
||||
@ -209,7 +204,6 @@
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
|
||||
"integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
@ -217,14 +211,12 @@
|
||||
"node_modules/@webassemblyjs/utf8": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
|
||||
"integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA=="
|
||||
},
|
||||
"node_modules/@webassemblyjs/wasm-edit": {
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz",
|
||||
"integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.11.6",
|
||||
"@webassemblyjs/helper-buffer": "1.11.6",
|
||||
@ -240,7 +232,6 @@
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz",
|
||||
"integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.11.6",
|
||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||
@ -253,7 +244,6 @@
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz",
|
||||
"integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.11.6",
|
||||
"@webassemblyjs/helper-buffer": "1.11.6",
|
||||
@ -265,7 +255,6 @@
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz",
|
||||
"integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.11.6",
|
||||
"@webassemblyjs/helper-api-error": "1.11.6",
|
||||
@ -279,7 +268,6 @@
|
||||
"version": "1.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz",
|
||||
"integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@webassemblyjs/ast": "1.11.6",
|
||||
"@xtuc/long": "4.2.2"
|
||||
@ -332,20 +320,17 @@
|
||||
"node_modules/@xtuc/ieee754": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
||||
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
|
||||
},
|
||||
"node_modules/@xtuc/long": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
|
||||
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.10.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
|
||||
"integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@ -357,7 +342,6 @@
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz",
|
||||
"integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"acorn": "^8"
|
||||
}
|
||||
@ -366,7 +350,6 @@
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
@ -382,11 +365,24 @@
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"ajv": "^6.9.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
|
||||
@ -571,7 +567,6 @@
|
||||
"version": "4.22.1",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
|
||||
"integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -602,8 +597,7 @@
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
|
||||
},
|
||||
"node_modules/cache-base": {
|
||||
"version": "1.0.1",
|
||||
@ -638,7 +632,6 @@
|
||||
"version": "1.0.30001543",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001543.tgz",
|
||||
"integrity": "sha512-qxdO8KPWPQ+Zk6bvNpPeQIOH47qZSYdFZd6dXQzb2KzhnSXju4Kd7H1PkSJx6NICSMgo/IhRZRhhfPTHYpJUCA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -654,6 +647,32 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk/node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
|
||||
@ -678,7 +697,6 @@
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
|
||||
"integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
}
|
||||
@ -802,6 +820,22 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/colorette": {
|
||||
"version": "2.0.20",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
|
||||
@ -811,8 +845,7 @@
|
||||
"node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
||||
},
|
||||
"node_modules/component-emitter": {
|
||||
"version": "1.3.0",
|
||||
@ -934,14 +967,12 @@
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.542",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.542.tgz",
|
||||
"integrity": "sha512-6+cpa00G09N3sfh2joln4VUXHquWrOFx3FLZqiVQvl45+zS9DskDBTPvob+BhvFRmTBkyDSk0vvLMMRo/qc6mQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-6+cpa00G09N3sfh2joln4VUXHquWrOFx3FLZqiVQvl45+zS9DskDBTPvob+BhvFRmTBkyDSk0vvLMMRo/qc6mQ=="
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "5.15.0",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
|
||||
"integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.4",
|
||||
"tapable": "^2.2.0"
|
||||
@ -965,14 +996,12 @@
|
||||
"node_modules/es-module-lexer": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz",
|
||||
"integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==",
|
||||
"dev": true
|
||||
"integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q=="
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@ -981,7 +1010,6 @@
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
|
||||
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"esrecurse": "^4.3.0",
|
||||
"estraverse": "^4.1.1"
|
||||
@ -994,7 +1022,6 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
|
||||
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"estraverse": "^5.2.0"
|
||||
},
|
||||
@ -1006,7 +1033,6 @@
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
||||
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
@ -1015,7 +1041,6 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
|
||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
@ -1024,7 +1049,6 @@
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.8.x"
|
||||
}
|
||||
@ -1093,14 +1117,12 @@
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
},
|
||||
"node_modules/fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
|
||||
},
|
||||
"node_modules/fastest-levenshtein": {
|
||||
"version": "1.0.16",
|
||||
@ -1274,8 +1296,7 @@
|
||||
"node_modules/glob-to-regexp": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
|
||||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
|
||||
},
|
||||
"node_modules/glob2base": {
|
||||
"version": "0.0.12",
|
||||
@ -1292,8 +1313,7 @@
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
|
||||
},
|
||||
"node_modules/has": {
|
||||
"version": "1.0.4",
|
||||
@ -1308,7 +1328,6 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@ -1669,7 +1688,6 @@
|
||||
"version": "27.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
|
||||
"integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"merge-stream": "^2.0.0",
|
||||
@ -1682,14 +1700,12 @@
|
||||
"node_modules/json-parse-even-better-errors": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
|
||||
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
|
||||
"dev": true
|
||||
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||
},
|
||||
"node_modules/kind-of": {
|
||||
"version": "3.2.2",
|
||||
@ -1707,7 +1723,6 @@
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
|
||||
"integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.11.5"
|
||||
}
|
||||
@ -1724,6 +1739,17 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/map-cache": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
|
||||
@ -1754,8 +1780,7 @@
|
||||
"node_modules/merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
|
||||
"dev": true
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "2.3.11",
|
||||
@ -1785,7 +1810,6 @@
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
@ -1794,7 +1818,6 @@
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
@ -1925,14 +1948,12 @@
|
||||
"node_modules/neo-async": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.13",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
|
||||
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "2.1.1",
|
||||
@ -2179,8 +2200,18 @@
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-dir": {
|
||||
"version": "4.2.0",
|
||||
@ -2222,7 +2253,6 @@
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
|
||||
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@ -2263,7 +2293,6 @@
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
@ -2743,7 +2772,6 @@
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@ -2772,7 +2800,6 @@
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
|
||||
"integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.8",
|
||||
"ajv": "^6.12.5",
|
||||
@ -2786,11 +2813,24 @@
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/serialize-javascript": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
|
||||
"integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
@ -3023,7 +3063,6 @@
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -3046,7 +3085,6 @@
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
@ -3171,7 +3209,6 @@
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
@ -3198,7 +3235,6 @@
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@ -3207,7 +3243,6 @@
|
||||
"version": "5.21.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.21.0.tgz",
|
||||
"integrity": "sha512-WtnFKrxu9kaoXuiZFSGrcAvvBqAdmKx0SFNmVNYdJamMu9yyN3I/QF0FbH4QcqJQ+y1CJnzxGIKH0cSj+FGYRw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.3",
|
||||
"acorn": "^8.8.2",
|
||||
@ -3225,7 +3260,6 @@
|
||||
"version": "5.3.9",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz",
|
||||
"integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "^0.3.17",
|
||||
"jest-worker": "^27.4.5",
|
||||
@ -3307,6 +3341,99 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.0.tgz",
|
||||
"integrity": "sha512-LLlB/pkB4q9mW2yLdFMnK3dEHbrBjeZTYguaaIfusyojBgAGf5kF+O6KcWqiGzWqHk0LBsoolrp4VftEURhybg==",
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.0",
|
||||
"enhanced-resolve": "^5.0.0",
|
||||
"micromatch": "^4.0.0",
|
||||
"semver": "^7.3.4",
|
||||
"source-map": "^0.7.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "*",
|
||||
"webpack": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/micromatch": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
||||
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
|
||||
"dependencies": {
|
||||
"braces": "^3.0.2",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/source-map": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
|
||||
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/union-value": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
|
||||
@ -3383,7 +3510,6 @@
|
||||
"version": "1.0.13",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
|
||||
"integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -3413,7 +3539,6 @@
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
@ -3444,7 +3569,6 @@
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
|
||||
"integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"glob-to-regexp": "^0.4.1",
|
||||
"graceful-fs": "^4.1.2"
|
||||
@ -3457,7 +3581,6 @@
|
||||
"version": "5.88.2",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
|
||||
"integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/eslint-scope": "^3.7.3",
|
||||
"@types/estree": "^1.0.0",
|
||||
@ -3571,7 +3694,6 @@
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
|
||||
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
@ -3602,6 +3724,11 @@
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "model-management-plugin",
|
||||
"version": "1.0.0",
|
||||
"description": "Model Management Plugin leverages the HuggingFace API for model exploration and seamless downloads",
|
||||
"description": "Model Management Plugin provides model exploration and seamless downloads",
|
||||
"icon": "https://raw.githubusercontent.com/tailwindlabs/heroicons/88e98b0c2b458553fbadccddc2d2f878edc0387b/src/20/solid/queue-list.svg",
|
||||
"main": "dist/index.js",
|
||||
"author": "James",
|
||||
@ -10,8 +10,8 @@
|
||||
"init"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"postinstall": "rimraf ./*.tgz && npm run build && cpx \"module.js\" \"dist\"",
|
||||
"build": "tsc -b . && webpack --config webpack.config.js",
|
||||
"postinstall": "rimraf ./*.tgz && npm run build",
|
||||
"build:publish": "npm pack && cpx *.tgz ../../pre-install"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -26,7 +26,9 @@
|
||||
"README.md"
|
||||
],
|
||||
"dependencies": {
|
||||
"@huggingface/hub": "^0.8.5"
|
||||
"@huggingface/hub": "^0.8.5",
|
||||
"@janhq/plugin-core": "file:../../../../plugin-core",
|
||||
"ts-loader": "^9.5.0"
|
||||
},
|
||||
"bundledDependencies": [
|
||||
"@huggingface/hub"
|
||||
|
||||
12
electron/core/plugins/model-management-plugin/tsconfig.json
Normal file
12
electron/core/plugins/model-management-plugin/tsconfig.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2016",
|
||||
"module": "ES6",
|
||||
"moduleResolution": "node",
|
||||
"outDir": "./dist",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": false,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@ const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
experiments: { outputModule: true },
|
||||
entry: "./index.js", // Adjust the entry point to match your project's main file
|
||||
entry: "./index.ts", // Adjust the entry point to match your project's main file
|
||||
mode: "production",
|
||||
module: {
|
||||
rules: [
|
||||
@ -19,7 +19,10 @@ module.exports = {
|
||||
library: { type: "module" }, // Specify ESM output format
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".js"],
|
||||
extensions: [".ts", ".js"],
|
||||
},
|
||||
optimization: {
|
||||
minimize: false
|
||||
},
|
||||
// Add loaders and other configuration as needed for your project
|
||||
};
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
"dev:electron": "yarn workspace jan dev",
|
||||
"dev:web": "yarn workspace jan-web dev",
|
||||
"dev": "concurrently --kill-others \"yarn dev:web\" \"wait-on http://localhost:3000 && yarn dev:electron\"",
|
||||
"build:core": "cd plugin-core && yarn install && yarn run build",
|
||||
"build:web": "yarn workspace jan-web build && cpx \"web/out/**\" \"electron/renderer/\"",
|
||||
"build:electron": "yarn workspace jan build",
|
||||
"build:plugins": "rimraf ./electron/core/pre-install/*.tgz && concurrently \"cd ./electron/core/plugins/data-plugin && npm ci\" \"cd ./electron/core/plugins/inference-plugin && npm ci\" \"cd ./electron/core/plugins/model-management-plugin && npm ci\" \"cd ./electron/core/plugins/monitoring-plugin && npm ci\" && concurrently \"cd ./electron/core/plugins/data-plugin && npm run build:publish\" \"cd ./electron/core/plugins/inference-plugin && npm run build:publish\" \"cd ./electron/core/plugins/model-management-plugin && npm run build:publish\" \"cd ./electron/core/plugins/monitoring-plugin && npm run build:publish\"",
|
||||
|
||||
261
plugin-core/README.md
Normal file
261
plugin-core/README.md
Normal file
@ -0,0 +1,261 @@
|
||||
## @janhq/plugin-core
|
||||
|
||||
> The module includes functions for communicating with core APIs, registering plugin extensions, and exporting type definitions.
|
||||
|
||||
## Usage
|
||||
|
||||
### Import the package
|
||||
|
||||
```js
|
||||
// javascript
|
||||
const core = require("@janhq/plugin-core");
|
||||
|
||||
// typescript
|
||||
import { core } from "@janhq/plugin-core";
|
||||
```
|
||||
|
||||
### Register Plugin Extensions
|
||||
|
||||
Every plugin must define an `init` function in its main entry file to initialize the plugin and register its extensions with the Jan platform.
|
||||
|
||||
You can `register` any function as a plugin extension using `CoreServiceAPI` below. For example, the `DataService.GetConversations` entry name can be used to register a function that retrieves conversations.
|
||||
|
||||
Once the extension is registered, it can be used by other plugins or components in the Jan platform. For example, a UI component might use the DataService.GetConversations extension to retrieve a list of conversations to display to the user.
|
||||
|
||||
```js
|
||||
import { RegisterExtensionPoint, DataService } from "@janhq/plugin-core";
|
||||
|
||||
function getConversations() {
|
||||
// Your logic here
|
||||
}
|
||||
|
||||
export function init({ register }: { register: RegisterExtensionPoint }) {
|
||||
register(DataService.GetConversations, getConversations.name, getConversations);
|
||||
}
|
||||
```
|
||||
|
||||
### Access Core API
|
||||
|
||||
To access the Core API in your plugin, you can follow the code examples and explanations provided below.
|
||||
|
||||
##### Import Core API and Store Module
|
||||
|
||||
In your main entry code (e.g., `index.ts`), start by importing the necessary modules and functions from the `@janhq/plugin-core` library.
|
||||
|
||||
```js
|
||||
// index.ts
|
||||
import { store, core } from "@janhq/plugin-core";
|
||||
```
|
||||
|
||||
#### Interact with Local Data Storage
|
||||
|
||||
The Core API allows you to interact with local data storage. Here are a couple of examples of how you can use it:
|
||||
|
||||
#### Insert Data
|
||||
|
||||
You can use the store.insertOne function to insert data into a specific collection in the local data store.
|
||||
|
||||
```js
|
||||
function insertData() {
|
||||
store.insertOne("conversations", { name: "meow" });
|
||||
// Insert a new document with { name: "meow" } into the "conversations" collection.
|
||||
}
|
||||
```
|
||||
|
||||
#### Get Data
|
||||
|
||||
To retrieve data from a collection in the local data store, you can use the `store.findOne` or `store.findMany` function. It allows you to filter and retrieve documents based on specific criteria.
|
||||
|
||||
store.getOne(collectionName, key) retrieves a single document that matches the provided key in the specified collection.
|
||||
store.getMany(collectionName, selector, sort) retrieves multiple documents that match the provided selector in the specified collection.
|
||||
|
||||
```js
|
||||
function getData() {
|
||||
const selector = { name: "meow" };
|
||||
const data = store.findMany("conversations", selector);
|
||||
// Retrieve documents from the "conversations" collection that match the filter.
|
||||
}
|
||||
```
|
||||
|
||||
#### Update Data
|
||||
|
||||
You can update data in the local store using these functions:
|
||||
|
||||
store.updateOne(collectionName, key, update) updates a single document that matches the provided key in the specified collection.
|
||||
store.updateMany(collectionName, selector, update) updates multiple documents that match the provided selector in the specified collection.
|
||||
|
||||
```js
|
||||
function updateData() {
|
||||
const selector = { name: "meow" };
|
||||
const update = { name: "newName" };
|
||||
store.updateOne("conversations", selector, update);
|
||||
// Update a document in the "conversations" collection.
|
||||
}
|
||||
```
|
||||
|
||||
#### Delete Data
|
||||
|
||||
You can delete data from the local data store using these functions:
|
||||
|
||||
store.deleteOne(collectionName, key) deletes a single document that matches the provided key in the specified collection.
|
||||
store.deleteMany(collectionName, selector) deletes multiple documents that match the provided selector in the specified collection.
|
||||
|
||||
```js
|
||||
function deleteData() {
|
||||
const selector = { name: "meow" };
|
||||
store.deleteOne("conversations", selector);
|
||||
// Delete a document from the "conversations" collection.
|
||||
}
|
||||
```
|
||||
|
||||
#### Perform File Operations
|
||||
|
||||
The Core API also provides functions to perform file operations. Here are a couple of examples:
|
||||
|
||||
#### Download a File
|
||||
|
||||
You can download a file from a specified URL and save it with a given file name using the core.downloadFile function.
|
||||
|
||||
```js
|
||||
function downloadModel(url: string, fileName: string) {
|
||||
core.downloadFile(url, fileName);
|
||||
}
|
||||
```
|
||||
|
||||
#### Delete a File
|
||||
|
||||
To delete a file, you can use the core.deleteFile function, providing the path to the file you want to delete.
|
||||
|
||||
```js
|
||||
function deleteModel(filePath: string) {
|
||||
core.deleteFile(path);
|
||||
}
|
||||
```
|
||||
|
||||
### Execute plugin module in main process
|
||||
|
||||
To execute a plugin module in the main process of your application, you can follow the steps outlined below.
|
||||
|
||||
##### Import the `core` Object
|
||||
|
||||
In your main process code (e.g., `index.ts`), start by importing the `core` object from the `@janhq/plugin-core` library.
|
||||
|
||||
```js
|
||||
// index.ts
|
||||
import { core } from "@janhq/plugin-core";
|
||||
```
|
||||
|
||||
##### Define the Module Path
|
||||
|
||||
Specify the path to the plugin module you want to execute. This path should lead to the module file (e.g., module.js) that contains the functions you wish to call.
|
||||
|
||||
```js
|
||||
// index.ts
|
||||
const MODULE_PATH = "data-plugin/dist/module.js";
|
||||
```
|
||||
|
||||
##### Define the Function to Execute
|
||||
|
||||
Create a function that will execute a function defined in your plugin module. In the example provided, the function `getConversationMessages` is created to invoke the `getConvMessages` function from the plugin module.
|
||||
|
||||
```js
|
||||
// index.ts
|
||||
function getConversationMessages(id: number) {
|
||||
return core.invokePluginFunc(MODULE_PATH, "getConvMessages", id);
|
||||
}
|
||||
|
||||
export function init({ register }: { register: RegisterExtensionPoint }) {
|
||||
register(DataService.GetConversationMessages, getConversationMessages.name, getConversationMessages);
|
||||
}
|
||||
```
|
||||
|
||||
##### Define Your Plugin Module
|
||||
|
||||
In your plugin module (e.g., module.ts), define the logic for the function you wish to execute. In the example, the function getConvMessages is defined with a placeholder comment indicating where your logic should be implemented.
|
||||
|
||||
```js
|
||||
// module.ts
|
||||
function getConvMessages(id: number) {
|
||||
// Your logic here
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getConvMessages
|
||||
}
|
||||
```
|
||||
|
||||
## CoreService API
|
||||
|
||||
The `CoreService` type is an exported union type that includes:
|
||||
|
||||
- `StoreService`
|
||||
- `DataService`
|
||||
- `InferenceService`
|
||||
- `ModelManagementService`
|
||||
- `SystemMonitoringService`
|
||||
- `PreferenceService`
|
||||
|
||||
## StoreService
|
||||
|
||||
The `StoreService` enum represents available methods for managing the database store. It includes the following methods:
|
||||
|
||||
- `CreateCollection`: Creates a new collection in the data store.
|
||||
- `DeleteCollection`: Deletes an existing collection from the data store.
|
||||
- `InsertOne`: Inserts a new value into an existing collection in the data store.
|
||||
- `UpdateOne`: Updates an existing value in an existing collection in the data store.
|
||||
- `UpdateMany`: Updates multiple records in a collection in the data store.
|
||||
- `DeleteOne`: Deletes an existing value from an existing collection in the data store.
|
||||
- `DeleteMany`: Deletes multiple records in a collection in the data store.
|
||||
- `FindMany`: Retrieves multiple records from a collection in the data store.
|
||||
- `FindOne`: Retrieves a single record from a collection in the data store.
|
||||
|
||||
## DataService
|
||||
|
||||
The `DataService` enum represents methods related to managing conversations and messages. It includes the following methods:
|
||||
|
||||
- `GetConversations`: Gets a list of conversations from the data store.
|
||||
- `CreateConversation`: Creates a new conversation in the data store.
|
||||
- `DeleteConversation`: Deletes an existing conversation from the data store.
|
||||
- `CreateMessage`: Creates a new message in an existing conversation in the data store.
|
||||
- `UpdateMessage`: Updates an existing message in an existing conversation in the data store.
|
||||
- `GetConversationMessages`: Gets a list of messages for an existing conversation from the data store.
|
||||
|
||||
## InferenceService
|
||||
|
||||
The `InferenceService` enum exports:
|
||||
|
||||
- `InferenceUrl`: The URL for the inference server.
|
||||
- `InitModel`: Initializes a model for inference.
|
||||
- `StopModel`: Stops a running inference model.
|
||||
|
||||
## ModelManagementService
|
||||
|
||||
The `ModelManagementService` enum provides methods for managing models:
|
||||
|
||||
- `GetDownloadedModels`: Gets a list of downloaded models.
|
||||
- `GetAvailableModels`: Gets a list of available models from data store.
|
||||
- `DeleteModel`: Deletes a downloaded model.
|
||||
- `DownloadModel`: Downloads a model from the server.
|
||||
- `SearchModels`: Searches for models on the server.
|
||||
- `GetConfiguredModels`: Gets configured models from the data store.
|
||||
- `StoreModel`: Stores a model in the data store.
|
||||
- `UpdateFinishedDownloadAt`: Updates the finished download time for a model in the data store.
|
||||
- `GetUnfinishedDownloadModels`: Gets a list of unfinished download models from the data store.
|
||||
- `GetFinishedDownloadModels`: Gets a list of finished download models from the data store.
|
||||
- `DeleteDownloadModel`: Deletes a downloaded model from the data store.
|
||||
- `GetModelById`: Gets a model by its ID from the data store.
|
||||
|
||||
## PreferenceService
|
||||
|
||||
The `PreferenceService` enum provides methods for managing plugin preferences:
|
||||
|
||||
- `ExperimentComponent`: Represents the UI experiment component for a testing function.
|
||||
|
||||
## SystemMonitoringService
|
||||
|
||||
The `SystemMonitoringService` enum includes methods for monitoring system resources:
|
||||
|
||||
- `GetResourcesInfo`: Gets information about system resources.
|
||||
- `GetCurrentLoad`: Gets the current system load.
|
||||
|
||||
For more detailed information on each of these components, please refer to the source code.
|
||||
51
plugin-core/core.ts
Normal file
51
plugin-core/core.ts
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Execute a plugin module function in main process
|
||||
*
|
||||
* @param plugin plugin name to import
|
||||
* @param method function name to execute
|
||||
* @param args arguments to pass to the function
|
||||
* @returns Promise<any>
|
||||
*
|
||||
*/
|
||||
const invokePluginFunc: (
|
||||
plugin: string,
|
||||
method: string,
|
||||
...args: any[]
|
||||
) => Promise<any> = (plugin, method, ...args) =>
|
||||
window.coreAPI?.invokePluginFunc(plugin, method, ...args) ??
|
||||
window.electronAPI?.invokePluginFunc(plugin, method, ...args);
|
||||
|
||||
/**
|
||||
* Downloads a file from a URL and saves it to the local file system.
|
||||
* @param {string} url - The URL of the file to download.
|
||||
* @param {string} fileName - The name to use for the downloaded file.
|
||||
* @returns {Promise<any>} A promise that resolves when the file is downloaded.
|
||||
*/
|
||||
const downloadFile: (url: string, fileName: string) => Promise<any> = (url, fileName) =>
|
||||
window.coreAPI?.downloadFile(url, fileName) ?? window.electronAPI?.downloadFile(url, fileName);
|
||||
|
||||
/**
|
||||
* Deletes a file from the local file system.
|
||||
* @param {string} path - The path of the file to delete.
|
||||
* @returns {Promise<any>} A promise that resolves when the file is deleted.
|
||||
*/
|
||||
const deleteFile: (path: string) => Promise<any> = (path) =>
|
||||
window.coreAPI?.deleteFile(path) ?? window.electronAPI?.deleteFile(path);
|
||||
|
||||
/** Register extension point function type definition
|
||||
*
|
||||
*/
|
||||
export type RegisterExtensionPoint = (
|
||||
extensionName: string,
|
||||
extensionId: string,
|
||||
method: Function,
|
||||
priority?: number
|
||||
) => void;
|
||||
/**
|
||||
* Core exports
|
||||
*/
|
||||
export const core = {
|
||||
invokePluginFunc,
|
||||
downloadFile,
|
||||
deleteFile,
|
||||
};
|
||||
224
plugin-core/index.ts
Normal file
224
plugin-core/index.ts
Normal file
@ -0,0 +1,224 @@
|
||||
/**
|
||||
* CoreService exports
|
||||
*/
|
||||
|
||||
export type CoreService =
|
||||
| StoreService
|
||||
| DataService
|
||||
| InferenceService
|
||||
| ModelManagementService
|
||||
| SystemMonitoringService
|
||||
| PreferenceService;
|
||||
|
||||
/**
|
||||
* Represents the available methods for the StoreService.
|
||||
* @enum {string}
|
||||
*/
|
||||
export enum StoreService {
|
||||
/**
|
||||
* Creates a new collection in the database store.
|
||||
*/
|
||||
CreateCollection = "createCollection",
|
||||
|
||||
/**
|
||||
* Deletes an existing collection from the database store.
|
||||
*/
|
||||
DeleteCollection = "deleteCollection",
|
||||
|
||||
/**
|
||||
* Inserts a new value into an existing collection in the database store.
|
||||
*/
|
||||
InsertOne = "insertOne",
|
||||
|
||||
/**
|
||||
* Updates an existing value in an existing collection in the database store.
|
||||
*/
|
||||
UpdateOne = "updateOne",
|
||||
|
||||
/**
|
||||
* Updates multiple records in a collection in the database store.
|
||||
*/
|
||||
UpdateMany = "updateMany",
|
||||
|
||||
/**
|
||||
* Deletes an existing value from an existing collection in the database store.
|
||||
*/
|
||||
DeleteOne = "deleteOne",
|
||||
|
||||
/**
|
||||
* Delete multiple records in a collection in the database store.
|
||||
*/
|
||||
DeleteMany = "deleteMany",
|
||||
|
||||
/**
|
||||
* Retrieve multiple records from a collection in the data store
|
||||
*/
|
||||
FindMany = "findMany",
|
||||
|
||||
/**
|
||||
* Retrieve a record from a collection in the data store.
|
||||
*/
|
||||
FindOne = "findOne",
|
||||
}
|
||||
|
||||
/**
|
||||
* DataService exports.
|
||||
* @enum {string}
|
||||
*/
|
||||
export enum DataService {
|
||||
/**
|
||||
* Gets a list of conversations from the server.
|
||||
*/
|
||||
GetConversations = "getConversations",
|
||||
|
||||
/**
|
||||
* Creates a new conversation on the server.
|
||||
*/
|
||||
CreateConversation = "createConversation",
|
||||
|
||||
/**
|
||||
* Deletes an existing conversation from the server.
|
||||
*/
|
||||
DeleteConversation = "deleteConversation",
|
||||
|
||||
/**
|
||||
* Creates a new message in an existing conversation on the server.
|
||||
*/
|
||||
CreateMessage = "createMessage",
|
||||
|
||||
/**
|
||||
* Updates an existing message in an existing conversation on the server.
|
||||
*/
|
||||
UpdateMessage = "updateMessage",
|
||||
|
||||
/**
|
||||
* Gets a list of messages for an existing conversation from the server.
|
||||
*/
|
||||
GetConversationMessages = "getConversationMessages",
|
||||
}
|
||||
|
||||
/**
|
||||
* InferenceService exports.
|
||||
* @enum {string}
|
||||
*/
|
||||
export enum InferenceService {
|
||||
/**
|
||||
* The URL for the inference server.
|
||||
*/
|
||||
InferenceUrl = "inferenceUrl",
|
||||
|
||||
/**
|
||||
* Initializes a model for inference.
|
||||
*/
|
||||
InitModel = "initModel",
|
||||
|
||||
/**
|
||||
* Stops a running inference model.
|
||||
*/
|
||||
StopModel = "stopModel",
|
||||
}
|
||||
|
||||
/**
|
||||
* ModelManagementService exports.
|
||||
* @enum {string}
|
||||
*/
|
||||
export enum ModelManagementService {
|
||||
/**
|
||||
* Gets a list of downloaded models.
|
||||
*/
|
||||
GetDownloadedModels = "getDownloadedModels",
|
||||
|
||||
/**
|
||||
* Gets a list of available models from the server.
|
||||
*/
|
||||
GetAvailableModels = "getAvailableModels",
|
||||
|
||||
/**
|
||||
* Deletes a downloaded model.
|
||||
*/
|
||||
DeleteModel = "deleteModel",
|
||||
|
||||
/**
|
||||
* Downloads a model from the server.
|
||||
*/
|
||||
DownloadModel = "downloadModel",
|
||||
|
||||
/**
|
||||
* Searches for models on the server.
|
||||
*/
|
||||
SearchModels = "searchModels",
|
||||
|
||||
/**
|
||||
* Gets configued models from the database.
|
||||
*/
|
||||
GetConfiguredModels = "getConfiguredModels",
|
||||
|
||||
/**
|
||||
* Stores a model in the database.
|
||||
*/
|
||||
StoreModel = "storeModel",
|
||||
|
||||
/**
|
||||
* Updates the finished download time for a model in the database.
|
||||
*/
|
||||
UpdateFinishedDownloadAt = "updateFinishedDownloadAt",
|
||||
|
||||
/**
|
||||
* Gets a list of unfinished download models from the database.
|
||||
*/
|
||||
GetUnfinishedDownloadModels = "getUnfinishedDownloadModels",
|
||||
|
||||
/**
|
||||
* Gets a list of finished download models from the database.
|
||||
*/
|
||||
GetFinishedDownloadModels = "getFinishedDownloadModels",
|
||||
|
||||
/**
|
||||
* Deletes a download model from the database.
|
||||
*/
|
||||
DeleteDownloadModel = "deleteDownloadModel",
|
||||
|
||||
/**
|
||||
* Gets a model by its ID from the database.
|
||||
*/
|
||||
GetModelById = "getModelById",
|
||||
}
|
||||
|
||||
/**
|
||||
* PreferenceService exports.
|
||||
* @enum {string}
|
||||
*/
|
||||
export enum PreferenceService {
|
||||
/**
|
||||
* The experiment component for which preferences are being managed.
|
||||
*/
|
||||
ExperimentComponent = "experimentComponent",
|
||||
}
|
||||
|
||||
/**
|
||||
* SystemMonitoringService exports.
|
||||
* @enum {string}
|
||||
*/
|
||||
export enum SystemMonitoringService {
|
||||
/**
|
||||
* Gets information about system resources.
|
||||
*/
|
||||
GetResourcesInfo = "getResourcesInfo",
|
||||
|
||||
/**
|
||||
* Gets the current system load.
|
||||
*/
|
||||
GetCurrentLoad = "getCurrentLoad",
|
||||
}
|
||||
|
||||
/**
|
||||
* Store module exports.
|
||||
* @module
|
||||
*/
|
||||
export { store } from "./store";
|
||||
|
||||
/**
|
||||
* Core module exports.
|
||||
* @module
|
||||
*/
|
||||
export { core, RegisterExtensionPoint } from "./core";
|
||||
22
plugin-core/package-lock.json
generated
Normal file
22
plugin-core/package-lock.json
generated
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "@janhq/plugin-core",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@janhq/plugin-core",
|
||||
"version": "0.1.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "12.20.55",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
|
||||
"integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
37
plugin-core/package.json
Normal file
37
plugin-core/package.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@janhq/plugin-core",
|
||||
"version": "0.1.0",
|
||||
"description": "Plugin core lib",
|
||||
"keywords": [
|
||||
"jan",
|
||||
"plugin",
|
||||
"core"
|
||||
],
|
||||
"homepage": "https://github.com/janhq",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"directories": {
|
||||
"lib": "lib",
|
||||
"test": "__tests__"
|
||||
},
|
||||
"exports": {
|
||||
".": "./lib/index.js",
|
||||
"./store": "./lib/store.js"
|
||||
},
|
||||
"files": [
|
||||
"lib",
|
||||
"README.md",
|
||||
"LICENSE.md",
|
||||
"package.json",
|
||||
"!.DS_Store"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "echo \"Error: run tests from root\" && exit 1",
|
||||
"build": "tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.0.2",
|
||||
"typescript": "^5.2.2"
|
||||
}
|
||||
}
|
||||
129
plugin-core/store.ts
Normal file
129
plugin-core/store.ts
Normal file
@ -0,0 +1,129 @@
|
||||
/**
|
||||
* Creates, reads, updates, and deletes data in a data store.
|
||||
* @module
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new collection in the data store.
|
||||
* @param {string} name - The name of the collection to create.
|
||||
* @param { [key: string]: any } schema - schema of the collection to create, include fields and their types
|
||||
* @returns {Promise<void>} A promise that resolves when the collection is created.
|
||||
*/
|
||||
function createCollection(
|
||||
name: string,
|
||||
schema: { [key: string]: any }
|
||||
): Promise<void> {
|
||||
return window.corePlugin?.store?.createCollection(name, schema);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a collection from the data store.
|
||||
* @param {string} name - The name of the collection to delete.
|
||||
* @returns {Promise<void>} A promise that resolves when the collection is deleted.
|
||||
*/
|
||||
function deleteCollection(name: string): Promise<void> {
|
||||
return window.corePlugin?.store?.deleteCollection(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a value into a collection in the data store.
|
||||
* @param {string} collectionName - The name of the collection to insert the value into.
|
||||
* @param {any} value - The value to insert into the collection.
|
||||
* @returns {Promise<any>} A promise that resolves with the inserted value.
|
||||
*/
|
||||
function insertOne(collectionName: string, value: any): Promise<any> {
|
||||
return window.corePlugin?.store?.insertOne(collectionName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a record from a collection in the data store.
|
||||
* @param {string} collectionName - The name of the collection containing the record to retrieve.
|
||||
* @param {string} key - The key of the record to retrieve.
|
||||
* @returns {Promise<any>} A promise that resolves when the record is retrieved.
|
||||
*/
|
||||
function findOne(collectionName: string, key: string): Promise<any> {
|
||||
return window.corePlugin?.store?.findOne(collectionName, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all records that match a selector in a collection in the data store.
|
||||
* @param {string} collectionName - The name of the collection to retrieve.
|
||||
* @param {{ [key: string]: any }} selector - The selector to use to get records from the collection.
|
||||
* @param {[{ [key: string]: any }]} sort - The sort options to use to retrieve records.
|
||||
* @returns {Promise<any>} A promise that resolves when all records are retrieved.
|
||||
*/
|
||||
function findMany(
|
||||
collectionName: string,
|
||||
selector?: { [key: string]: any },
|
||||
sort?: [{ [key: string]: any }]
|
||||
): Promise<any> {
|
||||
return window.corePlugin?.store?.findMany(collectionName, selector, sort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the value of a record in a collection in the data store.
|
||||
* @param {string} collectionName - The name of the collection containing the record to update.
|
||||
* @param {string} key - The key of the record to update.
|
||||
* @param {any} value - The new value for the record.
|
||||
* @returns {Promise<void>} A promise that resolves when the record is updated.
|
||||
*/
|
||||
function updateOne(
|
||||
collectionName: string,
|
||||
key: string,
|
||||
value: any
|
||||
): Promise<void> {
|
||||
return window.corePlugin?.store?.updateOne(collectionName, key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all records that match a selector in a collection in the data store.
|
||||
* @param {string} collectionName - The name of the collection containing the records to update.
|
||||
* @param {{ [key: string]: any }} selector - The selector to use to get the records to update.
|
||||
* @param {any} value - The new value for the records.
|
||||
* @returns {Promise<void>} A promise that resolves when the records are updated.
|
||||
*/
|
||||
function updateMany(
|
||||
collectionName: string,
|
||||
value: any,
|
||||
selector?: { [key: string]: any }
|
||||
): Promise<void> {
|
||||
return window.corePlugin?.store?.updateMany(collectionName, selector, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a single record from a collection in the data store.
|
||||
* @param {string} collectionName - The name of the collection containing the record to delete.
|
||||
* @param {string} key - The key of the record to delete.
|
||||
* @returns {Promise<void>} A promise that resolves when the record is deleted.
|
||||
*/
|
||||
function deleteOne(collectionName: string, key: string): Promise<void> {
|
||||
return window.corePlugin?.store?.deleteOne(collectionName, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all records with a matching key from a collection in the data store.
|
||||
* @param {string} collectionName - The name of the collection to delete the records from.
|
||||
* @param {{ [key: string]: any }} selector - The selector to use to get the records to delete.
|
||||
* @returns {Promise<void>} A promise that resolves when the records are deleted.
|
||||
*/
|
||||
function deleteMany(
|
||||
collectionName: string,
|
||||
selector?: { [key: string]: any }
|
||||
): Promise<void> {
|
||||
return window.corePlugin?.store?.deleteMany(collectionName, selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the data store operations as an object.
|
||||
*/
|
||||
export const store = {
|
||||
createCollection,
|
||||
deleteCollection,
|
||||
insertOne,
|
||||
findOne,
|
||||
findMany,
|
||||
updateOne,
|
||||
updateMany,
|
||||
deleteOne,
|
||||
deleteMany,
|
||||
};
|
||||
13
plugin-core/tsconfig.json
Normal file
13
plugin-core/tsconfig.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2016",
|
||||
"module": "ES6",
|
||||
"outDir": "./lib",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"declaration": true
|
||||
},
|
||||
"exclude": ["lib", "node_modules", "**/*.test.ts", "**/__mocks__/*"]
|
||||
}
|
||||
12
plugin-core/types/index.d.ts
vendored
Normal file
12
plugin-core/types/index.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
export {};
|
||||
|
||||
declare global {
|
||||
interface CorePlugin {
|
||||
store?: any | undefined;
|
||||
}
|
||||
interface Window {
|
||||
corePlugin?: CorePlugin;
|
||||
coreAPI?: any | undefined;
|
||||
electronAPI?: any | undefined;
|
||||
}
|
||||
}
|
||||
@ -24,14 +24,14 @@ const AvailableModelCard: React.FC<Props> = ({
|
||||
let total = 0;
|
||||
let transferred = 0;
|
||||
|
||||
if (model.id && downloadState[model.id]) {
|
||||
if (model._id && downloadState[model._id]) {
|
||||
isDownloading =
|
||||
downloadState[model.id].error == null &&
|
||||
downloadState[model.id].percent < 1;
|
||||
downloadState[model._id].error == null &&
|
||||
downloadState[model._id].percent < 1;
|
||||
|
||||
if (isDownloading) {
|
||||
total = downloadState[model.id].size.total;
|
||||
transferred = downloadState[model.id].size.transferred;
|
||||
total = downloadState[model._id].size.total;
|
||||
transferred = downloadState[model._id].size.transferred;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ const ConversationalList: React.FC<Props> = ({ models }) => (
|
||||
</div>
|
||||
<div className="mt-2 pl-6 flex w-full gap-2 overflow-x-scroll scroll overflow-hidden">
|
||||
{models.map((item) => (
|
||||
<ConversationalCard key={item.id} model={item} />
|
||||
<ConversationalCard key={item._id} model={item} />
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
|
||||
@ -133,7 +133,7 @@ const ExploreModelItem = forwardRef<HTMLDivElement, Props>(({ model }, ref) => {
|
||||
<ModelVersionList
|
||||
model={model}
|
||||
versions={model.availableVersions}
|
||||
recommendedVersion={suitableModel?.id ?? ""}
|
||||
recommendedVersion={suitableModel?._id ?? ""}
|
||||
/>
|
||||
)}
|
||||
<button
|
||||
|
||||
@ -29,8 +29,8 @@ const ExploreModelItemHeader: React.FC<Props> = ({
|
||||
const { performanceTag, title, getPerformanceForModel } =
|
||||
useGetPerformanceTag();
|
||||
const downloadAtom = useMemo(
|
||||
() => atom((get) => get(modelDownloadStateAtom)[suitableModel.id]),
|
||||
[suitableModel.id]
|
||||
() => atom((get) => get(modelDownloadStateAtom)[suitableModel._id]),
|
||||
[suitableModel._id]
|
||||
);
|
||||
const downloadState = useAtomValue(downloadAtom);
|
||||
const setMainViewState = useSetAtom(setMainViewStateAtom);
|
||||
@ -44,7 +44,7 @@ const ExploreModelItemHeader: React.FC<Props> = ({
|
||||
}, [exploreModel, suitableModel]);
|
||||
|
||||
const isDownloaded =
|
||||
downloadedModels.find((model) => model.id === suitableModel.id) != null;
|
||||
downloadedModels.find((model) => model._id === suitableModel._id) != null;
|
||||
|
||||
let downloadButton = (
|
||||
<PrimaryButton
|
||||
|
||||
@ -19,7 +19,7 @@ const ExploreModelList: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
{models.map((item) => (
|
||||
<ExploreModelItem key={item.id} model={item} />
|
||||
<ExploreModelItem key={item._id} model={item} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -3,7 +3,7 @@ import JanImage from "../JanImage";
|
||||
import { useAtomValue, useSetAtom } from "jotai";
|
||||
import Image from "next/image";
|
||||
import { Conversation } from "@/_models/Conversation";
|
||||
import { DataService } from "../../../shared/coreService";
|
||||
import { ModelManagementService } from "@janhq/plugin-core";
|
||||
import { executeSerial } from "../../../../electron/core/plugin-manager/execution/extension-manager";
|
||||
import {
|
||||
conversationStatesAtom,
|
||||
@ -39,28 +39,28 @@ const HistoryItem: React.FC<Props> = ({
|
||||
updateConversationWaitingForResponseAtom
|
||||
);
|
||||
const updateConvError = useSetAtom(updateConversationErrorAtom);
|
||||
const isSelected = activeConvoId === conversation.id;
|
||||
const isSelected = activeConvoId === conversation._id;
|
||||
|
||||
const { initModel } = useInitModel();
|
||||
|
||||
const onClick = async () => {
|
||||
const model = await executeSerial(
|
||||
DataService.GET_MODEL_BY_ID,
|
||||
conversation.model_id
|
||||
ModelManagementService.GetModelById,
|
||||
conversation.modelId
|
||||
);
|
||||
|
||||
if (conversation.id) updateConvWaiting(conversation.id, true);
|
||||
if (conversation._id) updateConvWaiting(conversation._id, true);
|
||||
initModel(model).then((res: any) => {
|
||||
if (conversation.id) updateConvWaiting(conversation.id, false);
|
||||
if (conversation._id) updateConvWaiting(conversation._id, false);
|
||||
|
||||
if (res?.error && conversation.id) {
|
||||
updateConvError(conversation.id, res.error);
|
||||
if (res?.error && conversation._id) {
|
||||
updateConvError(conversation._id, res.error);
|
||||
}
|
||||
});
|
||||
|
||||
if (activeConvoId !== conversation.id) {
|
||||
if (activeConvoId !== conversation._id) {
|
||||
setMainViewState(MainViewState.Conversation);
|
||||
setActiveConvoId(conversation.id);
|
||||
setActiveConvoId(conversation._id);
|
||||
}
|
||||
};
|
||||
|
||||
@ -69,7 +69,7 @@ const HistoryItem: React.FC<Props> = ({
|
||||
: "bg-white dark:bg-gray-500";
|
||||
|
||||
let rightImageUrl: string | undefined;
|
||||
if (conversationStates[conversation.id ?? ""]?.waitingForResponse === true) {
|
||||
if (conversationStates[conversation._id ?? ""]?.waitingForResponse === true) {
|
||||
rightImageUrl = "icons/loading.svg";
|
||||
}
|
||||
|
||||
|
||||
@ -36,11 +36,11 @@ const HistoryList: React.FC = () => {
|
||||
)
|
||||
.map((convo) => (
|
||||
<HistoryItem
|
||||
key={convo.id}
|
||||
key={convo._id}
|
||||
conversation={convo}
|
||||
avatarUrl={convo.image}
|
||||
name={convo.name || "Jan"}
|
||||
updatedAt={convo.updated_at ?? ""}
|
||||
updatedAt={convo.updatedAt ?? ""}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
|
||||
@ -19,20 +19,20 @@ const ModelRow: React.FC<Props> = ({ model }) => {
|
||||
const { deleteModel } = useDeleteModel();
|
||||
|
||||
let status = ModelStatus.Installed;
|
||||
if (activeModel && activeModel.id === model.id) {
|
||||
if (activeModel && activeModel._id === model._id) {
|
||||
status = ModelStatus.Active;
|
||||
}
|
||||
|
||||
let actionButtonType = ModelActionType.Start;
|
||||
if (activeModel && activeModel.id === model.id) {
|
||||
if (activeModel && activeModel._id === model._id) {
|
||||
actionButtonType = ModelActionType.Stop;
|
||||
}
|
||||
|
||||
const onModelActionClick = (action: ModelActionType) => {
|
||||
if (action === ModelActionType.Start) {
|
||||
startModel(model.id);
|
||||
startModel(model._id);
|
||||
} else {
|
||||
stopModel(model.id);
|
||||
stopModel(model._id);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -65,7 +65,7 @@ const SelectModels: React.FC = () => {
|
||||
<Listbox.Options className="absolute z-10 mt-1 max-h-[188px] w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
|
||||
{downloadedModels.map((model) => (
|
||||
<Listbox.Option
|
||||
key={model.id}
|
||||
key={model._id}
|
||||
className={({ active }) =>
|
||||
classNames(
|
||||
active ? "bg-blue-600 text-white" : "text-gray-900",
|
||||
|
||||
@ -24,7 +24,7 @@ const ModelTable: React.FC<Props> = ({ models }) => (
|
||||
</thead>
|
||||
<tbody>
|
||||
{models.map((model) => (
|
||||
<ModelRow key={model.id} model={model} />
|
||||
<ModelRow key={model._id} model={model} />
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@ -24,11 +24,11 @@ const ModelVersionItem: React.FC<Props> = ({
|
||||
const { downloadModel } = useDownloadModel();
|
||||
const { downloadedModels } = useGetDownloadedModels();
|
||||
const isDownloaded =
|
||||
downloadedModels.find((model) => model.id === modelVersion.id) != null;
|
||||
downloadedModels.find((model) => model._id === modelVersion._id) != null;
|
||||
|
||||
const downloadAtom = useMemo(
|
||||
() => atom((get) => get(modelDownloadStateAtom)[modelVersion.id ?? ""]),
|
||||
[modelVersion.id ?? ""]
|
||||
() => atom((get) => get(modelDownloadStateAtom)[modelVersion._id ?? ""]),
|
||||
[modelVersion._id]
|
||||
);
|
||||
const downloadState = useAtomValue(downloadAtom);
|
||||
|
||||
|
||||
@ -22,10 +22,10 @@ const ModelVersionList: React.FC<Props> = ({
|
||||
<div className="border border-gray-200 rounded-lg overflow-hidden">
|
||||
{versions.map((item) => (
|
||||
<ModelVersionItem
|
||||
key={item.id}
|
||||
key={item._id}
|
||||
model={model}
|
||||
modelVersion={item}
|
||||
isRecommended={item.id === recommendedVersion}
|
||||
isRecommended={item._id === recommendedVersion}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@ -105,7 +105,7 @@ export const Preferences = () => {
|
||||
if (typeof window !== "undefined") {
|
||||
// @ts-ignore
|
||||
await window.pluggableElectronIpc.update([plugin], true);
|
||||
window.electronAPI.relaunch();
|
||||
window.electronAPI.reloadPlugins();
|
||||
}
|
||||
// plugins.update(active.map((plg) => plg.name));
|
||||
};
|
||||
|
||||
@ -5,7 +5,7 @@ import { ReactNode, useEffect } from "react";
|
||||
import { appDownloadProgress } from "./JotaiWrapper";
|
||||
import { DownloadState } from "@/_models/DownloadState";
|
||||
import { executeSerial } from "../../../electron/core/plugin-manager/execution/extension-manager";
|
||||
import { DataService } from "../../shared/coreService";
|
||||
import { ModelManagementService } from "@janhq/plugin-core";
|
||||
import {
|
||||
setDownloadStateAtom,
|
||||
setDownloadStateSuccessAtom,
|
||||
@ -44,7 +44,7 @@ export default function EventListenerWrapper({ children }: Props) {
|
||||
setDownloadStateSuccess(callback.fileName);
|
||||
|
||||
executeSerial(
|
||||
DataService.UPDATE_FINISHED_DOWNLOAD,
|
||||
ModelManagementService.UpdateFinishedDownloadAt,
|
||||
callback.fileName
|
||||
).then(() => {
|
||||
getDownloadedModels().then((models) => {
|
||||
|
||||
@ -85,17 +85,17 @@ export const updateConversationHasMoreAtom = atom(
|
||||
*/
|
||||
export const userConversationsAtom = atom<Conversation[]>([]);
|
||||
export const currentConversationAtom = atom<Conversation | undefined>((get) =>
|
||||
get(userConversationsAtom).find((c) => c.id === get(getActiveConvoIdAtom))
|
||||
get(userConversationsAtom).find((c) => c._id === get(getActiveConvoIdAtom))
|
||||
);
|
||||
export const setConvoUpdatedAtAtom = atom(null, (get, set, convoId: string) => {
|
||||
const convo = get(userConversationsAtom).find((c) => c.id === convoId);
|
||||
const convo = get(userConversationsAtom).find((c) => c._id === convoId);
|
||||
if (!convo) return;
|
||||
const newConvo: Conversation = {
|
||||
...convo,
|
||||
updated_at: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
const newConversations: Conversation[] = get(userConversationsAtom).map((c) =>
|
||||
c.id === convoId ? newConvo : c
|
||||
c._id === convoId ? newConvo : c
|
||||
);
|
||||
|
||||
set(userConversationsAtom, newConversations);
|
||||
@ -104,11 +104,11 @@ export const setConvoUpdatedAtAtom = atom(null, (get, set, convoId: string) => {
|
||||
export const setConvoLastImageAtom = atom(
|
||||
null,
|
||||
(get, set, convoId: string, lastImageUrl: string) => {
|
||||
const convo = get(userConversationsAtom).find((c) => c.id === convoId);
|
||||
const convo = get(userConversationsAtom).find((c) => c._id === convoId);
|
||||
if (!convo) return;
|
||||
const newConvo: Conversation = { ...convo };
|
||||
const newConversations: Conversation[] = get(userConversationsAtom).map(
|
||||
(c) => (c.id === convoId ? newConvo : c)
|
||||
(c) => (c._id === convoId ? newConvo : c)
|
||||
);
|
||||
|
||||
set(userConversationsAtom, newConversations);
|
||||
|
||||
@ -2,7 +2,7 @@ import { ChatMessage, RawMessage, toChatMessage } from "@/_models/ChatMessage";
|
||||
import { executeSerial } from "@/_services/pluginService";
|
||||
import { useAtomValue, useSetAtom } from "jotai";
|
||||
import { useEffect, useState } from "react";
|
||||
import { DataService } from "../../shared/coreService";
|
||||
import { DataService } from "@janhq/plugin-core";
|
||||
import { addOldMessagesAtom } from "@/_helpers/atoms/ChatMessage.atom";
|
||||
import {
|
||||
currentConversationAtom,
|
||||
@ -27,20 +27,20 @@ const useChatMessages = (offset = 0) => {
|
||||
if (!currentConvo) {
|
||||
return;
|
||||
}
|
||||
const hasMore = convoStates[currentConvo.id ?? ""]?.hasMore ?? true;
|
||||
const hasMore = convoStates[currentConvo._id ?? ""]?.hasMore ?? true;
|
||||
if (!hasMore) return;
|
||||
|
||||
const getMessages = async () => {
|
||||
executeSerial(
|
||||
DataService.GET_CONVERSATION_MESSAGES,
|
||||
currentConvo.id
|
||||
DataService.GetConversationMessages,
|
||||
currentConvo._id
|
||||
).then((data: any) => {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
parseMessages(data ?? []).then((newMessages) => {
|
||||
addOldChatMessages(newMessages);
|
||||
updateConvoHasMore(currentConvo.id ?? "", false);
|
||||
updateConvoHasMore(currentConvo._id ?? "", false);
|
||||
setLoading(false);
|
||||
});
|
||||
});
|
||||
@ -48,7 +48,7 @@ const useChatMessages = (offset = 0) => {
|
||||
getMessages();
|
||||
}, [
|
||||
offset,
|
||||
currentConvo?.id,
|
||||
currentConvo?._id,
|
||||
convoStates,
|
||||
addOldChatMessages,
|
||||
updateConvoHasMore,
|
||||
@ -57,7 +57,7 @@ const useChatMessages = (offset = 0) => {
|
||||
return {
|
||||
loading: loading,
|
||||
error: undefined,
|
||||
hasMore: convoStates[currentConvo?.id ?? ""]?.hasMore ?? true,
|
||||
hasMore: convoStates[currentConvo?._id ?? ""]?.hasMore ?? true,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useAtom, useSetAtom } from "jotai";
|
||||
import { Conversation } from "@/_models/Conversation";
|
||||
import { executeSerial } from "@/_services/pluginService";
|
||||
import { DataService } from "../../shared/coreService";
|
||||
import { DataService } from "@janhq/plugin-core";
|
||||
import {
|
||||
userConversationsAtom,
|
||||
setActiveConvoIdAtom,
|
||||
@ -27,12 +27,12 @@ const useCreateConversation = () => {
|
||||
const requestCreateConvo = async (model: AssistantModel) => {
|
||||
const conversationName = model.name;
|
||||
const conv: Conversation = {
|
||||
model_id: model.id,
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
modelId: model._id,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
name: conversationName,
|
||||
};
|
||||
const id = await executeSerial(DataService.CREATE_CONVERSATION, conv);
|
||||
const id = await executeSerial(DataService.CreateConversation, conv);
|
||||
|
||||
if (id) updateConvWaiting(id, true);
|
||||
initModel(model).then((res: any) => {
|
||||
@ -43,11 +43,11 @@ const useCreateConversation = () => {
|
||||
});
|
||||
|
||||
const mappedConvo: Conversation = {
|
||||
id,
|
||||
model_id: model.id,
|
||||
_id: id,
|
||||
modelId: model._id,
|
||||
name: conversationName,
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
addNewConvoState(id ?? "", {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { currentPromptAtom } from "@/_helpers/JotaiWrapper";
|
||||
import { execute } from "@/_services/pluginService";
|
||||
import { useAtom, useAtomValue, useSetAtom } from "jotai";
|
||||
import { DataService } from "../../shared/coreService";
|
||||
import { DataService } from "@janhq/plugin-core";
|
||||
import { deleteConversationMessage } from "@/_helpers/atoms/ChatMessage.atom";
|
||||
import {
|
||||
userConversationsAtom,
|
||||
@ -33,15 +33,15 @@ export default function useDeleteConversation() {
|
||||
const deleteConvo = async () => {
|
||||
if (activeConvoId) {
|
||||
try {
|
||||
await execute(DataService.DELETE_CONVERSATION, activeConvoId);
|
||||
await execute(DataService.DeleteConversation, activeConvoId);
|
||||
const currentConversations = userConversations.filter(
|
||||
(c) => c.id !== activeConvoId,
|
||||
(c) => c._id !== activeConvoId,
|
||||
);
|
||||
setUserConversations(currentConversations);
|
||||
deleteMessages(activeConvoId);
|
||||
|
||||
if (currentConversations.length > 0) {
|
||||
setActiveConvoId(currentConversations[0].id);
|
||||
setActiveConvoId(currentConversations[0]._id);
|
||||
} else {
|
||||
setMainViewState(MainViewState.Welcome);
|
||||
setActiveConvoId(undefined);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { execute, executeSerial } from "@/_services/pluginService";
|
||||
import { DataService, ModelManagementService } from "../../shared/coreService";
|
||||
import { ModelManagementService } from "@janhq/plugin-core";
|
||||
import { useSetAtom } from "jotai";
|
||||
import { downloadedModelAtom } from "@/_helpers/atoms/DownloadedModel.atom";
|
||||
import { getDownloadedModels } from "./useGetDownloadedModels";
|
||||
@ -9,8 +9,8 @@ export default function useDeleteModel() {
|
||||
const setDownloadedModels = useSetAtom(downloadedModelAtom);
|
||||
|
||||
const deleteModel = async (model: AssistantModel) => {
|
||||
execute(DataService.DELETE_DOWNLOAD_MODEL, model.id);
|
||||
await executeSerial(ModelManagementService.DELETE_MODEL, model.id);
|
||||
execute(ModelManagementService.DeleteDownloadModel, model._id);
|
||||
await executeSerial(ModelManagementService.DeleteModel, model._id);
|
||||
|
||||
// reload models
|
||||
const downloadedModels = await getDownloadedModels();
|
||||
|
||||
@ -1,16 +1,51 @@
|
||||
import { executeSerial } from "@/_services/pluginService";
|
||||
import { DataService, ModelManagementService } from "../../shared/coreService";
|
||||
import { Product } from "@/_models/Product";
|
||||
import { DataService, ModelManagementService } from "@janhq/plugin-core";
|
||||
import { ModelVersion } from "@/_models/ModelVersion";
|
||||
import { Product } from "@/_models/Product";
|
||||
import { AssistantModel } from "@/_models/AssistantModel";
|
||||
|
||||
export default function useDownloadModel() {
|
||||
const assistanModel = (
|
||||
model: Product,
|
||||
modelVersion: ModelVersion
|
||||
): AssistantModel => {
|
||||
return {
|
||||
_id: modelVersion._id,
|
||||
name: modelVersion.name,
|
||||
quantMethod: modelVersion.quantMethod,
|
||||
bits: modelVersion.bits,
|
||||
size: modelVersion.size,
|
||||
maxRamRequired: modelVersion.maxRamRequired,
|
||||
usecase: modelVersion.usecase,
|
||||
downloadLink: modelVersion.downloadLink,
|
||||
startDownloadAt: modelVersion.startDownloadAt,
|
||||
finishDownloadAt: modelVersion.finishDownloadAt,
|
||||
productId: model._id,
|
||||
productName: model.name,
|
||||
shortDescription: model.shortDescription,
|
||||
longDescription: model.longDescription,
|
||||
avatarUrl: model.avatarUrl,
|
||||
author: model.author,
|
||||
version: model.version,
|
||||
modelUrl: model.modelUrl,
|
||||
nsfw: model.nsfw === true ? false : true,
|
||||
greeting: model.greeting,
|
||||
type: model.type,
|
||||
createdAt: new Date(model.createdAt).getTime(),
|
||||
updatedAt: new Date(model.updatedAt ?? "").getTime(),
|
||||
status: "",
|
||||
releaseDate: -1,
|
||||
tags: model.tags,
|
||||
};
|
||||
};
|
||||
|
||||
const downloadModel = async (model: Product, modelVersion: ModelVersion) => {
|
||||
modelVersion.startDownloadAt = Date.now();
|
||||
|
||||
await executeSerial(DataService.STORE_MODEL, { model, modelVersion });
|
||||
await executeSerial(ModelManagementService.DOWNLOAD_MODEL, {
|
||||
const assistantModel = assistanModel(model, modelVersion);
|
||||
await executeSerial(ModelManagementService.StoreModel, assistantModel);
|
||||
await executeSerial(ModelManagementService.DownloadModel, {
|
||||
downloadUrl: modelVersion.downloadLink,
|
||||
fileName: modelVersion.id,
|
||||
fileName: modelVersion._id,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Product } from "@/_models/Product";
|
||||
import { useEffect } from "react";
|
||||
import { executeSerial } from "../../../electron/core/plugin-manager/execution/extension-manager";
|
||||
import { DataService, ModelManagementService } from "../../shared/coreService";
|
||||
import { ModelManagementService } from "@janhq/plugin-core";
|
||||
import { useAtom } from "jotai";
|
||||
import { downloadedModelAtom } from "@/_helpers/atoms/DownloadedModel.atom";
|
||||
import { AssistantModel } from "@/_models/AssistantModel";
|
||||
@ -20,11 +20,11 @@ export function useGetDownloadedModels() {
|
||||
|
||||
export async function getDownloadedModels(): Promise<AssistantModel[]> {
|
||||
const downloadedModels: AssistantModel[] = await executeSerial(
|
||||
DataService.GET_FINISHED_DOWNLOAD_MODELS
|
||||
ModelManagementService.GetFinishedDownloadModels
|
||||
);
|
||||
return downloadedModels ?? [];
|
||||
}
|
||||
|
||||
export async function getConfiguredModels(): Promise<Product[]> {
|
||||
return executeSerial(ModelManagementService.GET_CONFIGURED_MODELS);
|
||||
return executeSerial(ModelManagementService.GetConfiguredModels);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { executeSerial } from "@/_services/pluginService";
|
||||
import { SystemMonitoringService } from "../../shared/coreService";
|
||||
import { SystemMonitoringService } from "@janhq/plugin-core";
|
||||
import { ModelVersion } from "@/_models/ModelVersion";
|
||||
import { useState } from "react";
|
||||
|
||||
@ -8,7 +8,7 @@ export default function useGetMostSuitableModelVersion() {
|
||||
|
||||
const getMostSuitableModelVersion = async (modelVersions: ModelVersion[]) => {
|
||||
const resourceInfo = await executeSerial(
|
||||
SystemMonitoringService.GET_RESOURCES_INFORMATION
|
||||
SystemMonitoringService.GetResourcesInfo
|
||||
);
|
||||
const totalRam = resourceInfo.mem.total;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { executeSerial } from "../../../electron/core/plugin-manager/execution/extension-manager";
|
||||
import { SystemMonitoringService } from "../../shared/coreService";
|
||||
import { SystemMonitoringService } from "@janhq/plugin-core";
|
||||
import { useState } from "react";
|
||||
import { ModelVersion } from "@/_models/ModelVersion";
|
||||
import { ModelPerformance, TagType } from "@/_components/SimpleTag/TagType";
|
||||
@ -14,7 +14,7 @@ export default function useGetPerformanceTag() {
|
||||
|
||||
const getPerformanceForModel = async (modelVersion: ModelVersion) => {
|
||||
const resourceInfo = await executeSerial(
|
||||
SystemMonitoringService.GET_RESOURCES_INFORMATION
|
||||
SystemMonitoringService.GetResourcesInfo
|
||||
);
|
||||
const totalRam = resourceInfo.mem.total;
|
||||
const requiredRam = modelVersion.maxRamRequired;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { executeSerial } from "../../../electron/core/plugin-manager/execution/extension-manager";
|
||||
import { SystemMonitoringService } from "../../shared/coreService";
|
||||
import { SystemMonitoringService } from "@janhq/plugin-core";
|
||||
|
||||
export default function useGetSystemResources() {
|
||||
const [ram, setRam] = useState<number>(0);
|
||||
@ -8,10 +8,10 @@ export default function useGetSystemResources() {
|
||||
|
||||
const getSystemResources = async () => {
|
||||
const resourceInfor = await executeSerial(
|
||||
SystemMonitoringService.GET_RESOURCES_INFORMATION
|
||||
SystemMonitoringService.GetResourcesInfo
|
||||
);
|
||||
const currentLoadInfor = await executeSerial(
|
||||
SystemMonitoringService.GET_CURRENT_LOAD_INFORMATION
|
||||
SystemMonitoringService.GetCurrentLoad
|
||||
);
|
||||
const ram =
|
||||
(resourceInfor?.mem?.active ?? 0) / (resourceInfor?.mem?.total ?? 1);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Conversation, ConversationState } from "@/_models/Conversation";
|
||||
import { useSetAtom } from "jotai";
|
||||
import { executeSerial } from "@/_services/pluginService";
|
||||
import { DataService } from "../../shared/coreService";
|
||||
import { DataService } from "@janhq/plugin-core";
|
||||
import {
|
||||
conversationStatesAtom,
|
||||
userConversationsAtom,
|
||||
@ -14,11 +14,11 @@ const useGetUserConversations = () => {
|
||||
const getUserConversations = async () => {
|
||||
try {
|
||||
const convos: Conversation[] | undefined = await executeSerial(
|
||||
DataService.GET_CONVERSATIONS
|
||||
DataService.GetConversations
|
||||
);
|
||||
const convoStates: Record<string, ConversationState> = {};
|
||||
convos?.forEach((convo) => {
|
||||
convoStates[convo.id ?? ""] = {
|
||||
convoStates[convo._id ?? ""] = {
|
||||
hasMore: true,
|
||||
waitingForResponse: false,
|
||||
};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { executeSerial } from "@/_services/pluginService";
|
||||
import { InferenceService } from "../../shared/coreService";
|
||||
import { InferenceService } from "@janhq/plugin-core";
|
||||
import { useAtom } from "jotai";
|
||||
import { activeAssistantModelAtom } from "@/_helpers/atoms/Model.atom";
|
||||
import { AssistantModel } from "@/_models/AssistantModel";
|
||||
@ -8,12 +8,12 @@ export default function useInitModel() {
|
||||
const [activeModel, setActiveModel] = useAtom(activeAssistantModelAtom);
|
||||
|
||||
const initModel = async (model: AssistantModel) => {
|
||||
if (activeModel && activeModel.id === model.id) {
|
||||
console.debug(`Model ${model.id} is already init. Ignore..`);
|
||||
if (activeModel && activeModel._id === model._id) {
|
||||
console.debug(`Model ${model._id} is already init. Ignore..`);
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await executeSerial(InferenceService.INIT_MODEL, model.id);
|
||||
const res = await executeSerial(InferenceService.InitModel, model._id);
|
||||
if (res?.error) {
|
||||
console.log("error occured: ", res);
|
||||
return res;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { currentPromptAtom } from "@/_helpers/JotaiWrapper";
|
||||
import { useAtom, useAtomValue, useSetAtom } from "jotai";
|
||||
import { selectAtom } from "jotai/utils";
|
||||
import { DataService, InferenceService } from "../../shared/coreService";
|
||||
import { DataService, InferenceService } from "@janhq/plugin-core";
|
||||
import {
|
||||
MessageSenderType,
|
||||
RawMessage,
|
||||
@ -45,13 +45,13 @@ export default function useSendChatMessage() {
|
||||
updateConvWaiting(conversationId, true);
|
||||
const prompt = currentPrompt.trim();
|
||||
const newMessage: RawMessage = {
|
||||
conversation_id: parseInt(currentConvo?.id ?? "0") ?? 0,
|
||||
conversationId: currentConvo?._id,
|
||||
message: prompt,
|
||||
user: "user",
|
||||
created_at: new Date().toISOString(),
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
const id = await executeSerial(DataService.CREATE_MESSAGE, newMessage);
|
||||
newMessage.id = id;
|
||||
const id = await executeSerial(DataService.CreateMessage, newMessage);
|
||||
newMessage._id = id;
|
||||
|
||||
const newChatMessage = await toChatMessage(newMessage);
|
||||
addNewMessage(newChatMessage);
|
||||
@ -70,7 +70,7 @@ export default function useSendChatMessage() {
|
||||
: "assistant",
|
||||
};
|
||||
});
|
||||
const url = await executeSerial(InferenceService.INFERENCE_URL);
|
||||
const url = await executeSerial(InferenceService.InferenceUrl);
|
||||
const response = await fetch(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
@ -93,13 +93,13 @@ export default function useSendChatMessage() {
|
||||
|
||||
// Cache received response
|
||||
const newResponse: RawMessage = {
|
||||
conversation_id: parseInt(currentConvo?.id ?? "0") ?? 0,
|
||||
conversationId: currentConvo?._id,
|
||||
message: answer,
|
||||
user: "assistant",
|
||||
created_at: new Date().toISOString(),
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
const respId = await executeSerial(DataService.CREATE_MESSAGE, newResponse);
|
||||
newResponse.id = respId;
|
||||
const respId = await executeSerial(DataService.CreateMessage, newResponse);
|
||||
newResponse._id = respId;
|
||||
const responseChatMessage = await toChatMessage(newResponse);
|
||||
addNewMessage(responseChatMessage);
|
||||
|
||||
@ -136,10 +136,10 @@ export default function useSendChatMessage() {
|
||||
responseChatMessage.conversationId,
|
||||
answer.trimEnd()
|
||||
);
|
||||
await executeSerial(DataService.UPDATE_MESSAGE, {
|
||||
await executeSerial(DataService.UpdateMessage, {
|
||||
...newResponse,
|
||||
message: answer.trimEnd(),
|
||||
updated_at: new Date()
|
||||
updatedAt: new Date()
|
||||
.toISOString()
|
||||
.replace("T", " ")
|
||||
.replace(/\.\d+Z$/, ""),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { executeSerial } from "@/_services/pluginService";
|
||||
import { DataService, InferenceService } from "../../shared/coreService";
|
||||
import { ModelManagementService, InferenceService } from "@janhq/plugin-core";
|
||||
import useInitModel from "./useInitModel";
|
||||
import { useSetAtom } from "jotai";
|
||||
import { activeAssistantModelAtom } from "@/_helpers/atoms/Model.atom";
|
||||
@ -9,7 +9,7 @@ export default function useStartStopModel() {
|
||||
const setActiveModel = useSetAtom(activeAssistantModelAtom);
|
||||
|
||||
const startModel = async (modelId: string) => {
|
||||
const model = await executeSerial(DataService.GET_MODEL_BY_ID, modelId);
|
||||
const model = await executeSerial(ModelManagementService.GetModelById, modelId);
|
||||
if (!model) {
|
||||
alert(`Model ${modelId} not found! Please re-download the model first.`);
|
||||
} else {
|
||||
@ -18,7 +18,7 @@ export default function useStartStopModel() {
|
||||
};
|
||||
|
||||
const stopModel = async (modelId: string) => {
|
||||
await executeSerial(InferenceService.STOP_MODEL, modelId);
|
||||
await executeSerial(InferenceService.StopModel, modelId);
|
||||
setActiveModel(undefined);
|
||||
};
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ export type AssistantModel = {
|
||||
* Combination of owner and model name.
|
||||
* Being used as file name. MUST be unique.
|
||||
*/
|
||||
id: string;
|
||||
_id: string;
|
||||
|
||||
name: string;
|
||||
|
||||
|
||||
@ -34,16 +34,16 @@ export interface ChatMessage {
|
||||
}
|
||||
|
||||
export interface RawMessage {
|
||||
id?: number;
|
||||
conversation_id: number;
|
||||
_id?: string;
|
||||
conversationId?: string;
|
||||
user?: string;
|
||||
message?: string;
|
||||
created_at?: string;
|
||||
updated_at?: string;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export const toChatMessage = async (m: RawMessage): Promise<ChatMessage> => {
|
||||
const createdAt = new Date(m.created_at ?? "").getTime();
|
||||
const createdAt = new Date(m.createdAt ?? "").getTime();
|
||||
const imageUrls: string[] = [];
|
||||
const imageUrl = undefined;
|
||||
if (imageUrl) {
|
||||
@ -59,8 +59,8 @@ export const toChatMessage = async (m: RawMessage): Promise<ChatMessage> => {
|
||||
const contentHtml = processedContent.toString();
|
||||
|
||||
return {
|
||||
id: (m.id ?? 0).toString(),
|
||||
conversationId: (m.conversation_id ?? 0).toString(),
|
||||
id: (m._id ?? 0).toString(),
|
||||
conversationId: (m.conversationId ?? 0).toString(),
|
||||
messageType: messageType,
|
||||
messageSenderType: messageSenderType,
|
||||
senderUid: m.user?.toString() || "0",
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
export interface Conversation {
|
||||
id?: string;
|
||||
model_id?: string;
|
||||
_id?: string;
|
||||
modelId?: string;
|
||||
name?: string;
|
||||
image?: string;
|
||||
message?: string;
|
||||
created_at?: string;
|
||||
updated_at?: string;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -6,7 +6,7 @@ export type ModelVersion = {
|
||||
* Combination of owner and model name.
|
||||
* Being used as file name. Should be unique.
|
||||
*/
|
||||
id: string;
|
||||
_id: string;
|
||||
name: string;
|
||||
quantMethod: string;
|
||||
bits: number;
|
||||
|
||||
@ -9,7 +9,7 @@ export enum ProductType {
|
||||
}
|
||||
|
||||
export interface Product {
|
||||
id: string;
|
||||
_id: string;
|
||||
name: string;
|
||||
shortDescription: string;
|
||||
avatarUrl: string;
|
||||
|
||||
8
web/app/_services/coreService.ts
Normal file
8
web/app/_services/coreService.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { store } from "./storeService";
|
||||
export const setupCoreServices = () => {
|
||||
if (!window.corePlugin) {
|
||||
window.corePlugin = {
|
||||
store,
|
||||
};
|
||||
}
|
||||
};
|
||||
@ -1,40 +1,29 @@
|
||||
"use client";
|
||||
import {
|
||||
extensionPoints,
|
||||
plugins,
|
||||
} from "../../../electron/core/plugin-manager/execution/index";
|
||||
import {
|
||||
CoreService,
|
||||
DataService,
|
||||
InferenceService,
|
||||
ModelManagementService,
|
||||
} from "../../shared/coreService";
|
||||
import { extensionPoints, plugins } from "../../../electron/core/plugin-manager/execution/index";
|
||||
import { CoreService, DataService, InferenceService, ModelManagementService } from "@janhq/plugin-core";
|
||||
|
||||
export const isCorePluginInstalled = () => {
|
||||
if (!extensionPoints.get(DataService.GET_CONVERSATIONS)) {
|
||||
if (!extensionPoints.get(DataService.GetConversations)) {
|
||||
return false;
|
||||
}
|
||||
if (!extensionPoints.get(InferenceService.INIT_MODEL)) {
|
||||
if (!extensionPoints.get(InferenceService.InitModel)) {
|
||||
return false;
|
||||
}
|
||||
if (!extensionPoints.get(ModelManagementService.DOWNLOAD_MODEL)) {
|
||||
if (!extensionPoints.get(ModelManagementService.DownloadModel)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
export const setupBasePlugins = async () => {
|
||||
if (
|
||||
typeof window === "undefined" ||
|
||||
typeof window.electronAPI === "undefined"
|
||||
) {
|
||||
if (typeof window === "undefined" || typeof window.electronAPI === "undefined") {
|
||||
return;
|
||||
}
|
||||
const basePlugins = await window.electronAPI.basePlugins();
|
||||
|
||||
if (
|
||||
!extensionPoints.get(DataService.GET_CONVERSATIONS) ||
|
||||
!extensionPoints.get(InferenceService.INIT_MODEL) ||
|
||||
!extensionPoints.get(ModelManagementService.DOWNLOAD_MODEL)
|
||||
!extensionPoints.get(DataService.GetConversations) ||
|
||||
!extensionPoints.get(InferenceService.InitModel) ||
|
||||
!extensionPoints.get(ModelManagementService.DownloadModel)
|
||||
) {
|
||||
const installed = await plugins.install(basePlugins);
|
||||
if (installed) {
|
||||
|
||||
138
web/app/_services/storeService.ts
Normal file
138
web/app/_services/storeService.ts
Normal file
@ -0,0 +1,138 @@
|
||||
import { StoreService } from "@janhq/plugin-core";
|
||||
import { executeSerial } from "./pluginService";
|
||||
|
||||
/**
|
||||
* Create a collection on data store
|
||||
*
|
||||
* @param name name of the collection to create
|
||||
* @param schema schema of the collection to create, include fields and their types, optional for relational database engine
|
||||
* @returns {Promise<void>}
|
||||
*
|
||||
*/
|
||||
function createCollection(name: string, schema?: { [key: string]: any }): Promise<void> {
|
||||
return executeSerial(StoreService.CreateCollection, { name, schema });
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a collection
|
||||
*
|
||||
* @param name name of the collection to delete
|
||||
* @returns {Promise<void>}
|
||||
*
|
||||
*/
|
||||
function deleteCollection(name: string): Promise<void> {
|
||||
return executeSerial(StoreService.DeleteCollection, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a value to a collection
|
||||
*
|
||||
* @param collectionName name of the collection
|
||||
* @param value value to insert
|
||||
* @returns {Promise<any>}
|
||||
*
|
||||
*/
|
||||
function insertOne(collectionName: string, value: any): Promise<any> {
|
||||
return executeSerial(StoreService.InsertOne, {
|
||||
collectionName,
|
||||
value,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a record from a collection in the data store.
|
||||
* @param {string} collectionName - The name of the collection containing the record to retrieve.
|
||||
* @param {string} key - The key of the record to retrieve.
|
||||
* @returns {Promise<any>} A promise that resolves when the record is retrieved.
|
||||
*/
|
||||
function findOne(collectionName: string, key: string): Promise<any> {
|
||||
return executeSerial(StoreService.FindOne, { collectionName, key });
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all records that match a selector in a collection in the data store.
|
||||
* @param collectionName - The name of the collection to retrieve.
|
||||
* @param selector - The selector to use to get records from the collection.
|
||||
* @param sort - The sort options to use to retrieve records.
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
function findMany(
|
||||
collectionName: string,
|
||||
selector?: { [key: string]: any },
|
||||
sort?: [{ [key: string]: any }]
|
||||
): Promise<any> {
|
||||
return executeSerial(StoreService.FindMany, {
|
||||
collectionName,
|
||||
selector,
|
||||
sort,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update value of a collection's record
|
||||
*
|
||||
* @param collectionName name of the collection
|
||||
* @param key key of the record to update
|
||||
* @param value value to update
|
||||
* @returns Promise<void>
|
||||
*
|
||||
*/
|
||||
function updateOne(collectionName: string, key: string, value: any): Promise<void> {
|
||||
return executeSerial(StoreService.UpdateOne, {
|
||||
collectionName,
|
||||
key,
|
||||
value,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all records that match a selector in a collection in the data store.
|
||||
* @param collectionName - The name of the collection containing the records to update.
|
||||
* @param selector - The selector to use to get the records to update.
|
||||
* @param value - The new value for the records.
|
||||
* @returns {Promise<void>} A promise that resolves when the records are updated.
|
||||
*/
|
||||
function updateMany(collectionName: string, value: any, selector?: { [key: string]: any }): Promise<void> {
|
||||
return executeSerial(StoreService.UpdateMany, {
|
||||
collectionName,
|
||||
value,
|
||||
selector,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a collection's record
|
||||
*
|
||||
* @param collectionName name of the collection
|
||||
* @param key key of the record to delete
|
||||
* @returns Promise<void>
|
||||
*
|
||||
*/
|
||||
function deleteOne(collectionName: string, key: string): Promise<void> {
|
||||
return executeSerial(StoreService.DeleteOne, { collectionName, key });
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all records with a matching key from a collection in the data store.
|
||||
* @param {string} collectionName - The name of the collection to delete the records from.
|
||||
* @param {{ [key: string]: any }} selector - The selector to use to get the records to delete.
|
||||
* @returns {Promise<void>} A promise that resolves when the records are deleted.
|
||||
*/
|
||||
function deleteMany(collectionName: string, selector?: { [key: string]: any }): Promise<void> {
|
||||
return executeSerial(StoreService.DeleteMany, {
|
||||
collectionName,
|
||||
selector,
|
||||
});
|
||||
}
|
||||
|
||||
export const store = {
|
||||
createCollection,
|
||||
deleteCollection,
|
||||
insertOne,
|
||||
updateOne,
|
||||
updateMany,
|
||||
deleteOne,
|
||||
deleteMany,
|
||||
findOne,
|
||||
findMany,
|
||||
};
|
||||
@ -18,10 +18,16 @@ import {
|
||||
} from "./_services/pluginService";
|
||||
import LeftContainer from "./_components/LeftContainer";
|
||||
import EventListenerWrapper from "./_helpers/EventListenerWrapper";
|
||||
import { setupCoreServices } from "./_services/coreService";
|
||||
|
||||
const Page: React.FC = () => {
|
||||
const [activated, setActivated] = useState(false);
|
||||
|
||||
// Services Setup
|
||||
useEffect(() => {
|
||||
// Setup Core Service
|
||||
setupCoreServices();
|
||||
|
||||
async function setupPE() {
|
||||
// Enable activation point management
|
||||
setup({
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^1.7.15",
|
||||
"@heroicons/react": "^2.0.18",
|
||||
"@janhq/plugin-core": "file:../plugin-core",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
"@types/react": "18.2.15",
|
||||
"@types/react-dom": "18.2.7",
|
||||
|
||||
@ -1,50 +0,0 @@
|
||||
export type CoreService =
|
||||
| DataService
|
||||
| ModelService
|
||||
| InferenceService
|
||||
| ModelManagementService
|
||||
| SystemMonitoringService
|
||||
| PreferenceService;
|
||||
|
||||
export enum DataService {
|
||||
GET_CONVERSATIONS = "getConversations",
|
||||
CREATE_CONVERSATION = "createConversation",
|
||||
DELETE_CONVERSATION = "deleteConversation",
|
||||
CREATE_MESSAGE = "createMessage",
|
||||
UPDATE_MESSAGE = "updateMessage",
|
||||
GET_CONVERSATION_MESSAGES = "getConversationMessages",
|
||||
|
||||
STORE_MODEL = "storeModel",
|
||||
UPDATE_FINISHED_DOWNLOAD = "updateFinishedDownloadAt",
|
||||
GET_UNFINISHED_DOWNLOAD_MODELS = "getUnfinishedDownloadModels",
|
||||
GET_FINISHED_DOWNLOAD_MODELS = "getFinishedDownloadModels",
|
||||
DELETE_DOWNLOAD_MODEL = "deleteDownloadModel",
|
||||
|
||||
GET_MODEL_BY_ID = "getModelById",
|
||||
}
|
||||
|
||||
export enum ModelService {
|
||||
GET_MODELS = "getModels",
|
||||
}
|
||||
|
||||
export enum InferenceService {
|
||||
INFERENCE_URL = "inferenceUrl",
|
||||
INIT_MODEL = "initModel",
|
||||
STOP_MODEL = "stopModel",
|
||||
}
|
||||
|
||||
export enum ModelManagementService {
|
||||
DELETE_MODEL = "deleteModel",
|
||||
DOWNLOAD_MODEL = "downloadModel",
|
||||
SEARCH_MODELS = "searchModels",
|
||||
GET_CONFIGURED_MODELS = "getConfiguredModels",
|
||||
}
|
||||
|
||||
export enum PreferenceService {
|
||||
GET_EXPERIMENT_COMPONENT = "experimentComponent",
|
||||
}
|
||||
|
||||
export enum SystemMonitoringService {
|
||||
GET_RESOURCES_INFORMATION = "getResourcesInfo",
|
||||
GET_CURRENT_LOAD_INFORMATION = "getCurrentLoad",
|
||||
}
|
||||
1
web/types/index.d.ts
vendored
1
web/types/index.d.ts
vendored
@ -3,5 +3,6 @@ export {};
|
||||
declare global {
|
||||
interface Window {
|
||||
electronAPI?: any | undefined;
|
||||
corePlugin?: any | undefined;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user