From fc43f1499665664dfae04a3c3ef60d4ac7472698 Mon Sep 17 00:00:00 2001
From: Daniel <101145494+dan-jan@users.noreply.github.com>
Date: Wed, 15 Nov 2023 17:30:17 +0800
Subject: [PATCH 01/35] Reorganize Documentation
---
docs/docs/about/about.md | 4 +-
.../03_assistants.md => specs/assistants.md} | 0
.../{modules/01_chats.md => specs/chats.md} | 0
.../{modules/06_files.md => specs/files.md} | 0
.../05_messages.md => specs/messages.md} | 0
.../{modules/02_models.md => specs/models.md} | 0
.../04_threads.md => specs/threads.md} | 0
.../{guides => getting-started}/img/chat.png | Bin
.../img/downloading.png | Bin
.../img/explore-model.png | Bin
.../img/jan-download.png | Bin
.../img/model-catelog.png | Bin
.../img/model-version.png | Bin
.../img/set-up.png | Bin
.../img/start-model.png | Bin
.../img/window-defender.png | Bin
.../install/linux.md | 0
.../install/mac.md | 0
.../install/windows.md | 0
.../troubleshooting.md | 0
docs/docs/guides/overview.md | 9 ---
docs/docusaurus.config.js | 8 +--
docs/sidebars.js | 59 +++++++++++-------
23 files changed, 39 insertions(+), 41 deletions(-)
rename docs/docs/docs/{modules/03_assistants.md => specs/assistants.md} (100%)
rename docs/docs/docs/{modules/01_chats.md => specs/chats.md} (100%)
rename docs/docs/docs/{modules/06_files.md => specs/files.md} (100%)
rename docs/docs/docs/{modules/05_messages.md => specs/messages.md} (100%)
rename docs/docs/docs/{modules/02_models.md => specs/models.md} (100%)
rename docs/docs/docs/{modules/04_threads.md => specs/threads.md} (100%)
rename docs/docs/{guides => getting-started}/img/chat.png (100%)
rename docs/docs/{guides => getting-started}/img/downloading.png (100%)
rename docs/docs/{guides => getting-started}/img/explore-model.png (100%)
rename docs/docs/{guides => getting-started}/img/jan-download.png (100%)
rename docs/docs/{guides => getting-started}/img/model-catelog.png (100%)
rename docs/docs/{guides => getting-started}/img/model-version.png (100%)
rename docs/docs/{guides => getting-started}/img/set-up.png (100%)
rename docs/docs/{guides => getting-started}/img/start-model.png (100%)
rename docs/docs/{guides => getting-started}/img/window-defender.png (100%)
rename docs/docs/{guides => getting-started}/install/linux.md (100%)
rename docs/docs/{guides => getting-started}/install/mac.md (100%)
rename docs/docs/{guides => getting-started}/install/windows.md (100%)
rename docs/docs/{guides => getting-started}/troubleshooting.md (100%)
delete mode 100644 docs/docs/guides/overview.md
diff --git a/docs/docs/about/about.md b/docs/docs/about/about.md
index 7931c030f..3ed5750c4 100644
--- a/docs/docs/about/about.md
+++ b/docs/docs/about/about.md
@@ -2,11 +2,11 @@
title: About Jan
---
-Jan is a free, open source alternative to OpenAI's platform that runs on your personal computer.
+Jan is a free, open source alternative to OpenAI's platform that runs on a local folder of open-format files.
We believe in the need for an open source AI ecosystem, and are building the infra and tooling to allow open source AIs to be as usable and comprehensive as proprietary ones.
-Jan's long-term vision is to build a cognitive framework for future robots. We build towards a future where humans and businesses are augmented by practical, useful assistants in everyday life.
+Jan's long-term vision is to build a cognitive framework for future robots, who are practical, useful assistants for humans and businesses in everyday life.
## Why does Jan Exist?
diff --git a/docs/docs/docs/modules/03_assistants.md b/docs/docs/docs/specs/assistants.md
similarity index 100%
rename from docs/docs/docs/modules/03_assistants.md
rename to docs/docs/docs/specs/assistants.md
diff --git a/docs/docs/docs/modules/01_chats.md b/docs/docs/docs/specs/chats.md
similarity index 100%
rename from docs/docs/docs/modules/01_chats.md
rename to docs/docs/docs/specs/chats.md
diff --git a/docs/docs/docs/modules/06_files.md b/docs/docs/docs/specs/files.md
similarity index 100%
rename from docs/docs/docs/modules/06_files.md
rename to docs/docs/docs/specs/files.md
diff --git a/docs/docs/docs/modules/05_messages.md b/docs/docs/docs/specs/messages.md
similarity index 100%
rename from docs/docs/docs/modules/05_messages.md
rename to docs/docs/docs/specs/messages.md
diff --git a/docs/docs/docs/modules/02_models.md b/docs/docs/docs/specs/models.md
similarity index 100%
rename from docs/docs/docs/modules/02_models.md
rename to docs/docs/docs/specs/models.md
diff --git a/docs/docs/docs/modules/04_threads.md b/docs/docs/docs/specs/threads.md
similarity index 100%
rename from docs/docs/docs/modules/04_threads.md
rename to docs/docs/docs/specs/threads.md
diff --git a/docs/docs/guides/img/chat.png b/docs/docs/getting-started/img/chat.png
similarity index 100%
rename from docs/docs/guides/img/chat.png
rename to docs/docs/getting-started/img/chat.png
diff --git a/docs/docs/guides/img/downloading.png b/docs/docs/getting-started/img/downloading.png
similarity index 100%
rename from docs/docs/guides/img/downloading.png
rename to docs/docs/getting-started/img/downloading.png
diff --git a/docs/docs/guides/img/explore-model.png b/docs/docs/getting-started/img/explore-model.png
similarity index 100%
rename from docs/docs/guides/img/explore-model.png
rename to docs/docs/getting-started/img/explore-model.png
diff --git a/docs/docs/guides/img/jan-download.png b/docs/docs/getting-started/img/jan-download.png
similarity index 100%
rename from docs/docs/guides/img/jan-download.png
rename to docs/docs/getting-started/img/jan-download.png
diff --git a/docs/docs/guides/img/model-catelog.png b/docs/docs/getting-started/img/model-catelog.png
similarity index 100%
rename from docs/docs/guides/img/model-catelog.png
rename to docs/docs/getting-started/img/model-catelog.png
diff --git a/docs/docs/guides/img/model-version.png b/docs/docs/getting-started/img/model-version.png
similarity index 100%
rename from docs/docs/guides/img/model-version.png
rename to docs/docs/getting-started/img/model-version.png
diff --git a/docs/docs/guides/img/set-up.png b/docs/docs/getting-started/img/set-up.png
similarity index 100%
rename from docs/docs/guides/img/set-up.png
rename to docs/docs/getting-started/img/set-up.png
diff --git a/docs/docs/guides/img/start-model.png b/docs/docs/getting-started/img/start-model.png
similarity index 100%
rename from docs/docs/guides/img/start-model.png
rename to docs/docs/getting-started/img/start-model.png
diff --git a/docs/docs/guides/img/window-defender.png b/docs/docs/getting-started/img/window-defender.png
similarity index 100%
rename from docs/docs/guides/img/window-defender.png
rename to docs/docs/getting-started/img/window-defender.png
diff --git a/docs/docs/guides/install/linux.md b/docs/docs/getting-started/install/linux.md
similarity index 100%
rename from docs/docs/guides/install/linux.md
rename to docs/docs/getting-started/install/linux.md
diff --git a/docs/docs/guides/install/mac.md b/docs/docs/getting-started/install/mac.md
similarity index 100%
rename from docs/docs/guides/install/mac.md
rename to docs/docs/getting-started/install/mac.md
diff --git a/docs/docs/guides/install/windows.md b/docs/docs/getting-started/install/windows.md
similarity index 100%
rename from docs/docs/guides/install/windows.md
rename to docs/docs/getting-started/install/windows.md
diff --git a/docs/docs/guides/troubleshooting.md b/docs/docs/getting-started/troubleshooting.md
similarity index 100%
rename from docs/docs/guides/troubleshooting.md
rename to docs/docs/getting-started/troubleshooting.md
diff --git a/docs/docs/guides/overview.md b/docs/docs/guides/overview.md
deleted file mode 100644
index bf44ca685..000000000
--- a/docs/docs/guides/overview.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-title: Overview
-slug: /guides
----
-- Jan Platform: Desktop app/ Cloud native SaaS that can run on Linux, Windows, Mac, or even a Server that comes with extensibilities, toolbox, and state-of-the-art but optimized models for next-gen Apps.
-- Jan App: Next-gen App built on Jan Plaform as `portable intelligence` that can be run everywhere.
-- Models:
- - Large Language Models
- - Stable Diffusion models
diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js
index df522ffb0..f669a70a1 100644
--- a/docs/docusaurus.config.js
+++ b/docs/docusaurus.config.js
@@ -134,13 +134,7 @@ const config = {
src: "img/logo.svg",
},
items: [
- // Navbar left
- {
- type: "docSidebar",
- sidebarId: "guidesSidebar",
- position: "left",
- label: "User Guide",
- },
+ // Navbar Left
{
type: "docSidebar",
sidebarId: "docsSidebar",
diff --git a/docs/sidebars.js b/docs/sidebars.js
index ea6a22a71..f3accdb77 100644
--- a/docs/sidebars.js
+++ b/docs/sidebars.js
@@ -29,39 +29,52 @@ const sidebars = {
},
],
- guidesSidebar: [
- "guides/overview",
- {
- type: "category",
- label: "Installation",
- collapsible: true,
- collapsed: false,
- items: [
- {
- type: "autogenerated",
- dirName: "guides/install",
- },
- ],
- },
- "guides/troubleshooting",
- ],
-
docsSidebar: [
- "docs/introduction",
- "docs/quickstart",
{
type: "category",
- label: "Modules",
+ label: "Getting Started",
collapsible: true,
collapsed: false,
items: [
+ "docs/introduction",
{
- type: "autogenerated",
- dirName: "docs/modules",
+ type: "category",
+ label: "Installation",
+ collapsible: true,
+ collapsed: true,
+ items: [
+ {
+ type: "autogenerated",
+ dirName: "getting-started/install",
+ },
+ ],
+ },
+ "docs/quickstart",
+ ],
+ },
+ {
+ type: "category",
+ label: "Building Jan",
+ collapsible: false,
+ collapsed: false,
+ items: [
+ "docs/user-interface",
+ {
+ type: "category",
+ label: "Specifications",
+ collapsible: true,
+ collapsed: true,
+ items: [
+ "docs/specs/chats",
+ "docs/specs/models",
+ "docs/specs/threads",
+ "docs/specs/messages",
+ "docs/specs/assistants",
+ "docs/specs/files",
+ ],
},
],
},
- "docs/user-interface",
],
apiSidebar: [
From 9ce5ed3991b407db2b58b4429fc737519c6c5a03 Mon Sep 17 00:00:00 2001
From: Daniel <101145494+dan-jan@users.noreply.github.com>
Date: Wed, 15 Nov 2023 17:34:17 +0800
Subject: [PATCH 02/35] Disable collapsible on sidebar
---
docs/sidebars.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/sidebars.js b/docs/sidebars.js
index f3accdb77..7736b60eb 100644
--- a/docs/sidebars.js
+++ b/docs/sidebars.js
@@ -33,7 +33,7 @@ const sidebars = {
{
type: "category",
label: "Getting Started",
- collapsible: true,
+ collapsible: false,
collapsed: false,
items: [
"docs/introduction",
From 1fad9030c516fbe5154fb0a85a470dbf581de570 Mon Sep 17 00:00:00 2001
From: Ashley <89722390+imtuyethan@users.noreply.github.com>
Date: Wed, 15 Nov 2023 18:21:23 +0700
Subject: [PATCH 03/35] Update README.md
- Update banner
- Update tagline
---
README.md | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 5464ff1c1..2b29bd84a 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
-# Jan - Personal AI
+# Jan - Own Your AI
+
+
-
@@ -21,7 +22,7 @@
> ⚠️ **Jan is currently in Development**: Expect breaking changes and bugs!
-Jan is a free, open-source alternative to OpenAI that runs on your personal computer.
+Jan is a free, open-source alternative to OpenAI's platform that runs on a local folder of open-format files.
**Jan runs on any hardware.** From PCs to multi-GPU clusters, Jan supports universal architectures:
From 8820e187413d94d498635ae89758e991528b8d75 Mon Sep 17 00:00:00 2001
From: Ashley <89722390+imtuyethan@users.noreply.github.com>
Date: Wed, 15 Nov 2023 18:36:32 +0700
Subject: [PATCH 04/35] Update README.md
---
README.md | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 2b29bd84a..c28a9530d 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,6 @@
# Jan - Own Your AI
-
-
+
From 9c5c03b6bca2c2e3a1dd4f5c59c36d5dbe57ac1c Mon Sep 17 00:00:00 2001
From: Linh Tran
Date: Wed, 15 Nov 2023 21:46:27 +0700
Subject: [PATCH 05/35] Add run-script-os (#620)
---
.github/scripts/auto-sign.sh | 11 ++++++---
.github/workflows/jan-electron-build.yml | 12 +++++-----
.../jan-electron-linter-and-test.yml | 8 +++----
electron/package.json | 23 ++++++++++---------
package.json | 21 ++++-------------
plugins/inference-plugin/package.json | 21 ++++++++---------
6 files changed, 44 insertions(+), 52 deletions(-)
diff --git a/.github/scripts/auto-sign.sh b/.github/scripts/auto-sign.sh
index e1c735860..5e6ef9750 100755
--- a/.github/scripts/auto-sign.sh
+++ b/.github/scripts/auto-sign.sh
@@ -1,5 +1,10 @@
#!/bin/bash
-APP_PATH=${APP_PATH}
-DEVELOPER_ID=${DEVELOPER_ID}
-find $APP_PATH \( -type f -perm +111 -o -name "*.node" \) -exec codesign -s "$DEVELOPER_ID" --options=runtime {} \;
\ No newline at end of file
+# Check if both APP_PATH and DEVELOPER_ID environment variables are set
+if [[ -z "$APP_PATH" ]] || [[ -z "$DEVELOPER_ID" ]]; then
+ echo "Either APP_PATH or DEVELOPER_ID is not set. Skipping script execution."
+ exit 0
+fi
+
+# If both variables are set, execute the following commands
+find "$APP_PATH" \( -type f -perm +111 -o -name "*.node" \) -exec codesign -s "$DEVELOPER_ID" --options=runtime {} \;
diff --git a/.github/workflows/jan-electron-build.yml b/.github/workflows/jan-electron-build.yml
index f1c0f5c1e..34005e068 100644
--- a/.github/workflows/jan-electron-build.yml
+++ b/.github/workflows/jan-electron-build.yml
@@ -60,14 +60,14 @@ jobs:
run: |
yarn build:core
yarn install
- yarn build:plugins-darwin
+ yarn build:plugins
env:
APP_PATH: "."
DEVELOPER_ID: ${{ secrets.DEVELOPER_ID }}
- name: Build and publish app
run: |
- yarn build:publish-darwin
+ yarn build:publish
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: "/tmp/codesign.p12"
@@ -122,11 +122,11 @@ jobs:
yarn build:core
yarn install
$env:NITRO_VERSION = Get-Content .\plugins\inference-plugin\nitro\version.txt; echo $env:NITRO_VERSION
- yarn build:plugins-win32
+ yarn build:plugins
- name: Build and publish app
run: |
- yarn build:publish-win32
+ yarn build:publish
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -178,11 +178,11 @@ jobs:
yarn config set network-timeout 300000
yarn build:core
yarn install
- yarn build:plugins-linux
+ yarn build:plugins
- name: Build and publish app
run: |
- yarn build:publish-linux
+ yarn build:publish
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/jan-electron-linter-and-test.yml b/.github/workflows/jan-electron-linter-and-test.yml
index 1938a40f5..92f29c368 100644
--- a/.github/workflows/jan-electron-linter-and-test.yml
+++ b/.github/workflows/jan-electron-linter-and-test.yml
@@ -95,8 +95,8 @@ jobs:
yarn build:core
yarn install
$env:NITRO_VERSION = Get-Content .\plugins\inference-plugin\nitro\version.txt; echo $env:NITRO_VERSION
- yarn build:plugins-win32
- yarn build:test-win32
+ yarn build:plugins
+ yarn build:test
$env:CI="e2e"
yarn test
@@ -131,6 +131,6 @@ jobs:
yarn config set network-timeout 300000
yarn build:core
yarn install
- yarn build:plugins-linux
- yarn build:test-linux
+ yarn build:plugins
+ yarn build:test
yarn test
diff --git a/electron/package.json b/electron/package.json
index 107264805..0eed33b2e 100644
--- a/electron/package.json
+++ b/electron/package.json
@@ -52,18 +52,18 @@
"lint": "eslint . --ext \".js,.jsx,.ts,.tsx\"",
"test:e2e": "playwright test --workers=1",
"dev": "tsc -p . && electron .",
- "build": "tsc -p . && electron-builder -p never -m",
- "build:test": "tsc -p . && electron-builder --dir -p never -m",
- "build:test-darwin": "tsc -p . && electron-builder -p never -m --x64 --arm64 --dir",
- "build:test-win32": "tsc -p . && electron-builder -p never -w --dir",
- "build:test-linux": "tsc -p . && electron-builder -p never -l --dir",
- "build:darwin": "tsc -p . && electron-builder -p never -m --x64 --arm64",
+ "build": "run-script-os",
+ "build:test": "run-script-os",
+ "build:test:darwin": "tsc -p . && electron-builder -p never -m --dir",
+ "build:test:win32": "tsc -p . && electron-builder -p never -w --dir",
+ "build:test:linux": "tsc -p . && electron-builder -p never -l --dir",
+ "build:darwin": "tsc -p . && electron-builder -p never -m",
"build:win32": "tsc -p . && electron-builder -p never -w",
"build:linux": "tsc -p . && electron-builder -p never --linux deb",
- "build:publish": "tsc -p . && electron-builder -p onTagOrDraft -m",
- "build:publish-darwin": "tsc -p . && electron-builder -p onTagOrDraft -m --x64 --arm64",
- "build:publish-win32": "tsc -p . && electron-builder -p onTagOrDraft -w",
- "build:publish-linux": "tsc -p . && electron-builder -p onTagOrDraft --linux deb "
+ "build:publish": "run-script-os",
+ "build:publish:darwin": "tsc -p . && electron-builder -p onTagOrDraft -m --x64 --arm64",
+ "build:publish:win32": "tsc -p . && electron-builder -p onTagOrDraft -w",
+ "build:publish:linux": "tsc -p . && electron-builder -p onTagOrDraft -l deb"
},
"dependencies": {
"@npmcli/arborist": "^7.1.0",
@@ -86,7 +86,8 @@
"electron": "26.2.1",
"electron-builder": "^24.6.4",
"electron-playwright-helpers": "^1.6.0",
- "eslint-plugin-react": "^7.33.2"
+ "eslint-plugin-react": "^7.33.2",
+ "run-script-os": "^1.1.6"
},
"installConfig": {
"hoistingLimits": "workspaces"
diff --git a/package.json b/package.json
index 32506ea80..036542c38 100644
--- a/package.json
+++ b/package.json
@@ -36,27 +36,16 @@
"build:electron": "yarn workspace jan build",
"build:electron:test": "yarn workspace jan build:test",
"build:plugins": "rimraf ./electron/core/pre-install/*.tgz && concurrently --kill-others-on-fail \"cd ./plugins/conversational-json && npm install && npm run build:publish\" \"cd ./plugins/inference-plugin && npm install && npm run build:publish\" \"cd ./plugins/model-plugin && npm install && npm run build:publish\" \"cd ./plugins/monitoring-plugin && npm install && npm run build:publish\"",
- "build:plugins-win32": "rimraf ./electron/core/pre-install/*.tgz && concurrently --kill-others-on-fail \"cd ./plugins/conversational-json && npm install && npm run build:publish\" \"cd ./plugins/inference-plugin && npm install && npm run build:publish-win32\" \"cd ./plugins/model-plugin && npm install && npm run build:publish\" \"cd ./plugins/monitoring-plugin && npm install && npm run build:publish\"",
- "build:plugins-linux": "rimraf ./electron/core/pre-install/*.tgz && concurrently --kill-others-on-fail \"cd ./plugins/conversational-json && npm install && npm run build:publish\" \"cd ./plugins/inference-plugin && npm install && npm run build:publish-linux\" \"cd ./plugins/model-plugin && npm install && npm run build:publish\" \"cd ./plugins/monitoring-plugin && npm install && npm run build:publish\"",
- "build:plugins-darwin": "rimraf ./electron/core/pre-install/*.tgz && concurrently --kill-others-on-fail \"cd ./plugins/conversational-json && npm install && npm run build:publish\" \"cd ./plugins/inference-plugin && npm install && npm run build:publish-darwin\" \"cd ./plugins/model-plugin && npm install && npm run build:publish\" \"cd ./plugins/monitoring-plugin && npm install && npm run build:publish\"",
- "build:test": "yarn build:web && yarn build:electron:test",
- "build:test-darwin": "yarn build:web && yarn workspace jan build:test-darwin",
- "build:test-win32": "yarn build:web && yarn workspace jan build:test-win32",
- "build:test-linux": "yarn build:web && yarn workspace jan build:test-linux",
- "build": "yarn build:web && yarn build:electron",
- "build:darwin": "yarn build:web && yarn workspace jan build:darwin",
- "build:win32": "yarn build:web && yarn workspace jan build:win32",
- "build:linux": "yarn build:web && yarn workspace jan build:linux",
- "build:publish": "yarn build:web && yarn workspace jan build:publish",
- "build:publish-darwin": "yarn build:web && yarn workspace jan build:publish-darwin",
- "build:publish-win32": "yarn build:web && yarn workspace jan build:publish-win32",
- "build:publish-linux": "yarn build:web && yarn workspace jan build:publish-linux"
+ "build:test": "yarn build:web && yarn workspace jan build:test",
+ "build": "yarn build:web && yarn workspace jan build",
+ "build:publish": "yarn build:web && yarn workspace jan build:publish"
},
"devDependencies": {
"concurrently": "^8.2.1",
"cpx": "^1.5.0",
"rimraf": "^3.0.2",
- "wait-on": "^7.0.1"
+ "wait-on": "^7.0.1",
+ "run-script-os": "^1.1.6"
},
"version": "0.0.0"
}
diff --git a/plugins/inference-plugin/package.json b/plugins/inference-plugin/package.json
index 5c52d13d0..3b7159c3c 100644
--- a/plugins/inference-plugin/package.json
+++ b/plugins/inference-plugin/package.json
@@ -13,18 +13,14 @@
],
"scripts": {
"build": "tsc -b . && webpack --config webpack.config.js",
- "downloadnitro:linux-cpu": "NITRO_VERSION=$(cat ./nitro/version.txt) && download https://github.com/janhq/nitro/releases/download/v${NITRO_VERSION}/nitro-${NITRO_VERSION}-linux-amd64.zip -e --strip 1 -o ./nitro/linux-cpu && chmod +x ./nitro/linux-cpu/nitro && chmod +x ./nitro/linux-start.sh ",
- "downloadnitro:linux-cuda": "NITRO_VERSION=$(cat ./nitro/version.txt) && download https://github.com/janhq/nitro/releases/download/v${NITRO_VERSION}/nitro-${NITRO_VERSION}-linux-amd64-cuda.zip -e --strip 1 -o ./nitro/linux-cuda && chmod +x ./nitro/linux-cuda/nitro && chmod +x ./nitro/linux-start.sh",
- "downloadnitro:darwin-arm64": "NITRO_VERSION=$(cat ./nitro/version.txt) && download https://github.com/janhq/nitro/releases/download/v${NITRO_VERSION}/nitro-${NITRO_VERSION}-mac-arm64.zip -e --strip 1 -o ./nitro/mac-arm64 && chmod +x ./nitro/mac-arm64/nitro",
- "downloadnitro:darwin-x64": "NITRO_VERSION=$(cat ./nitro/version.txt) && download https://github.com/janhq/nitro/releases/download/v${NITRO_VERSION}/nitro-${NITRO_VERSION}-mac-amd64.zip -e --strip 1 -o ./nitro/mac-x64 && chmod +x ./nitro/mac-x64/nitro",
- "downloadnitro:win32-cpu": "download https://github.com/janhq/nitro/releases/download/v%NITRO_VERSION%/nitro-%NITRO_VERSION%-win-amd64.zip -e --strip 1 -o ./nitro/win-cpu",
- "downloadnitro:win32-cuda": "download https://github.com/janhq/nitro/releases/download/v%NITRO_VERSION%/nitro-%NITRO_VERSION%-win-amd64-cuda.zip -e --strip 1 -o ./nitro/win-cuda",
- "downloadnitro:all": "npm run downloadnitro:darwin-arm64 && npm run downloadnitro:darwin-x64 && downloadnitro:win32-cpu && npm run downloadnitro:win32-cuda && npm run downloadnitro:linux-cpu && npm run downloadnitro:linux-cuda",
- "build:publish": "rimraf *.tgz --glob && npm run build && npm run downloadnitro:darwin-arm64 && npm run downloadnitro:darwin-x64 && cpx \"nitro/**\" \"dist/nitro\" && npm pack && cpx *.tgz ../../electron/core/pre-install",
- "build:publish-darwin": "rimraf *.tgz --glob && npm run build && npm run downloadnitro:darwin-arm64 && npm run downloadnitro:darwin-x64 && ../../.github/scripts/auto-sign.sh && cpx \"nitro/**\" \"dist/nitro\" && npm pack && cpx *.tgz ../../electron/core/pre-install",
- "build:publish-win32": "rimraf *.tgz --glob && npm run build && npm run downloadnitro:win32-cpu && npm run downloadnitro:win32-cuda && cpx \"nitro/**\" \"dist/nitro\" && npm pack && cpx *.tgz ../../electron/core/pre-install",
- "build:publish-linux": "rimraf *.tgz --glob && npm run build && npm run downloadnitro:linux-cpu && npm run downloadnitro:linux-cuda && cpx \"nitro/**\" \"dist/nitro\" && npm pack && cpx *.tgz ../../electron/core/pre-install",
- "build:publish-all": "rimraf *.tgz --glob && npm run build && npm run downloadnitro:all && cpx \"nitro/**\" \"dist/nitro\" && npm pack && cpx *.tgz ../../electron/core/pre-install"
+ "downloadnitro:linux": "NITRO_VERSION=$(cat ./nitro/version.txt) && download https://github.com/janhq/nitro/releases/download/v${NITRO_VERSION}/nitro-${NITRO_VERSION}-linux-amd64.zip -e --strip 1 -o ./nitro/linux-cpu && chmod +x ./nitro/linux-cpu/nitro && chmod +x ./nitro/linux-start.sh && download https://github.com/janhq/nitro/releases/download/v${NITRO_VERSION}/nitro-${NITRO_VERSION}-linux-amd64-cuda.zip -e --strip 1 -o ./nitro/linux-cuda && chmod +x ./nitro/linux-cuda/nitro && chmod +x ./nitro/linux-start.sh",
+ "downloadnitro:darwin": "NITRO_VERSION=$(cat ./nitro/version.txt) && download https://github.com/janhq/nitro/releases/download/v${NITRO_VERSION}/nitro-${NITRO_VERSION}-mac-arm64.zip -e --strip 1 -o ./nitro/mac-arm64 && chmod +x ./nitro/mac-arm64/nitro && download https://github.com/janhq/nitro/releases/download/v${NITRO_VERSION}/nitro-${NITRO_VERSION}-mac-amd64.zip -e --strip 1 -o ./nitro/mac-x64 && chmod +x ./nitro/mac-x64/nitro",
+ "downloadnitro:win32": "download https://github.com/janhq/nitro/releases/download/v%NITRO_VERSION%/nitro-%NITRO_VERSION%-win-amd64.zip -e --strip 1 -o ./nitro/win-cpu && download https://github.com/janhq/nitro/releases/download/v%NITRO_VERSION%/nitro-%NITRO_VERSION%-win-amd64-cuda.zip -e --strip 1 -o ./nitro/win-cuda",
+ "downloadnitro": "run-script-os",
+ "build:publish:darwin": "rimraf *.tgz --glob && npm run build && npm run downloadnitro && ../../.github/scripts/auto-sign.sh && cpx \"nitro/**\" \"dist/nitro\" && npm pack && cpx *.tgz ../../electron/core/pre-install",
+ "build:publish:win32": "rimraf *.tgz --glob && npm run build && npm run downloadnitro && cpx \"nitro/**\" \"dist/nitro\" && npm pack && cpx *.tgz ../../electron/core/pre-install",
+ "build:publish:linux": "rimraf *.tgz --glob && npm run build && npm run downloadnitro && cpx \"nitro/**\" \"dist/nitro\" && npm pack && cpx *.tgz ../../electron/core/pre-install",
+ "build:publish": "run-script-os"
},
"exports": {
".": "./dist/index.js",
@@ -33,6 +29,7 @@
"devDependencies": {
"cpx": "^1.5.0",
"rimraf": "^3.0.2",
+ "run-script-os": "^1.1.6",
"webpack": "^5.88.2",
"webpack-cli": "^5.1.4"
},
From 52d56a8ae1da3fa99554eb2ec8ae9e711477a693 Mon Sep 17 00:00:00 2001
From: NamH
Date: Thu, 16 Nov 2023 12:09:09 +0700
Subject: [PATCH 06/35] refactor: move file to jan root (#598)
* feat: move necessary files to jan root
Signed-off-by: James
* chore: check model dir
---------
Signed-off-by: James
Co-authored-by: James
Co-authored-by: Louis
---
core/src/events.ts | 4 +-
core/src/fs.ts | 17 ++
core/src/index.ts | 9 +-
core/src/types/index.ts | 59 ++++++-
electron/.prettierrc | 8 +
electron/handlers/download.ts | 96 +++++------
electron/handlers/fs.ts | 151 ++++++++++--------
electron/handlers/plugin.ts | 4 +-
electron/handlers/update.ts | 2 +-
electron/main.ts | 78 ++++-----
electron/managers/plugin.ts | 6 +-
electron/preload.ts | 74 +++++----
plugins/conversational-json/package.json | 1 +
plugins/conversational-json/src/index.ts | 29 +++-
plugins/conversational-json/webpack.config.js | 3 +
plugins/conversational-plugin/src/index.ts | 16 +-
plugins/inference-plugin/src/index.ts | 12 +-
plugins/inference-plugin/src/module.ts | 2 +-
plugins/model-plugin/.prettierrc | 8 +
plugins/model-plugin/package.json | 1 +
.../model-plugin/src/helpers/cloudNative.ts | 48 ------
.../model-plugin/src/helpers/modelParser.ts | 20 +--
plugins/model-plugin/src/index.ts | 96 ++++++-----
plugins/model-plugin/webpack.config.js | 27 ++--
web/containers/Layout/BottomBar/index.tsx | 2 +-
.../CommandListDownloadedModel/index.tsx | 6 +-
web/containers/ModalCancelDownload/index.tsx | 4 +-
web/containers/Providers/EventHandler.tsx | 58 ++++---
web/containers/Providers/EventListener.tsx | 17 +-
web/helpers/atoms/ChatMessage.atom.ts | 3 +-
web/helpers/atoms/Conversation.atom.ts | 12 +-
web/hooks/useActiveModel.ts | 11 +-
web/hooks/useCreateConversation.ts | 14 +-
web/hooks/useDeleteConversation.ts | 4 +-
web/hooks/useDeleteModel.ts | 10 +-
web/hooks/useDownloadModel.ts | 8 +-
web/hooks/useGetInputState.ts | 10 +-
web/hooks/useGetUserConversations.ts | 12 +-
web/hooks/useSendChatMessage.ts | 25 +--
web/models/ChatMessage.ts | 84 ----------
web/screens/Chat/ChatItem/index.tsx | 3 +-
web/screens/Chat/HistoryList/index.tsx | 12 +-
web/screens/Chat/SimpleTextMessage/index.tsx | 3 +-
web/screens/Chat/index.tsx | 6 +-
.../ExploreModels/ExploreModelItem/index.tsx | 2 +-
.../ExploreModelItemHeader/index.tsx | 6 +-
.../ExploreModels/ExploreModelList/index.tsx | 18 +--
.../ExploreModels/ModelVersionItem/index.tsx | 13 +-
.../ExploreModels/ModelVersionList/index.tsx | 4 +-
web/screens/MyModels/index.tsx | 8 +-
web/services/coreService.ts | 4 +-
web/types/chatMessage.d.ts | 63 --------
web/utils/dummy.ts | 6 +-
web/utils/message.ts | 67 +++++---
54 files changed, 608 insertions(+), 658 deletions(-)
create mode 100644 electron/.prettierrc
create mode 100644 plugins/model-plugin/.prettierrc
delete mode 100644 plugins/model-plugin/src/helpers/cloudNative.ts
delete mode 100644 web/models/ChatMessage.ts
delete mode 100644 web/types/chatMessage.d.ts
diff --git a/core/src/events.ts b/core/src/events.ts
index b39a38408..e962dead4 100644
--- a/core/src/events.ts
+++ b/core/src/events.ts
@@ -20,7 +20,7 @@ export type MessageHistory = {
* The `NewMessageRequest` type defines the shape of a new message request object.
*/
export type NewMessageRequest = {
- _id?: string;
+ id?: string;
conversationId?: string;
user?: string;
avatar?: string;
@@ -34,7 +34,7 @@ export type NewMessageRequest = {
* The `NewMessageRequest` type defines the shape of a new message request object.
*/
export type NewMessageResponse = {
- _id?: string;
+ id?: string;
conversationId?: string;
user?: string;
avatar?: string;
diff --git a/core/src/fs.ts b/core/src/fs.ts
index 04046705a..73ac31636 100644
--- a/core/src/fs.ts
+++ b/core/src/fs.ts
@@ -8,6 +8,21 @@ const writeFile: (path: string, data: string) => Promise = (path, data) =>
window.coreAPI?.writeFile(path, data) ??
window.electronAPI?.writeFile(path, data);
+/**
+ * Gets the user space path.
+ * @returns {Promise} A Promise that resolves with the user space path.
+ */
+const getUserSpace = (): Promise =>
+ window.coreAPI?.getUserSpace() ?? window.electronAPI?.getUserSpace();
+
+/**
+ * Checks whether the path is a directory.
+ * @param path - The path to check.
+ * @returns {boolean} A boolean indicating whether the path is a directory.
+ */
+const isDirectory = (path: string): Promise =>
+ window.coreAPI?.isDirectory(path) ?? window.electronAPI?.isDirectory(path);
+
/**
* Reads the contents of a file at the specified path.
* @param {string} path - The path of the file to read.
@@ -48,6 +63,8 @@ const deleteFile: (path: string) => Promise = (path) =>
window.coreAPI?.deleteFile(path) ?? window.electronAPI?.deleteFile(path);
export const fs = {
+ isDirectory,
+ getUserSpace,
writeFile,
readFile,
listFiles,
diff --git a/core/src/index.ts b/core/src/index.ts
index 39a69d702..5c741c863 100644
--- a/core/src/index.ts
+++ b/core/src/index.ts
@@ -20,12 +20,9 @@ export { events } from "./events";
* Events types exports.
* @module
*/
-export {
- EventName,
- NewMessageRequest,
- NewMessageResponse,
- MessageHistory,
-} from "./events";
+export * from "./events";
+
+export * from "./types/index";
/**
* Filesystem module exports.
diff --git a/core/src/types/index.ts b/core/src/types/index.ts
index c2062b5d1..296bc1a7e 100644
--- a/core/src/types/index.ts
+++ b/core/src/types/index.ts
@@ -1,5 +1,5 @@
export interface Conversation {
- _id: string;
+ id: string;
modelId?: string;
botId?: string;
name: string;
@@ -8,11 +8,23 @@ export interface Conversation {
createdAt?: string;
updatedAt?: string;
messages: Message[];
+ lastMessage?: string;
}
+
export interface Message {
+ id: string;
message?: string;
user?: string;
- _id: string;
+ createdAt?: string;
+ updatedAt?: string;
+}
+
+export interface RawMessage {
+ id?: string;
+ conversationId?: string;
+ user?: string;
+ avatar?: string;
+ message?: string;
createdAt?: string;
updatedAt?: string;
}
@@ -22,7 +34,7 @@ export interface Model {
* Combination of owner and model name.
* Being used as file name. MUST be unique.
*/
- _id: string;
+ id: string;
name: string;
quantMethod: string;
bits: number;
@@ -51,7 +63,7 @@ export interface Model {
tags: string[];
}
export interface ModelCatalog {
- _id: string;
+ id: string;
name: string;
shortDescription: string;
avatarUrl: string;
@@ -74,7 +86,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;
@@ -89,3 +101,40 @@ export type ModelVersion = {
startDownloadAt?: number;
finishDownloadAt?: number;
};
+
+export interface ChatMessage {
+ id: string;
+ conversationId: string;
+ messageType: MessageType;
+ messageSenderType: MessageSenderType;
+ senderUid: string;
+ senderName: string;
+ senderAvatarUrl: string;
+ text: string | undefined;
+ imageUrls?: string[] | undefined;
+ createdAt: number;
+ status: MessageStatus;
+}
+
+export enum MessageType {
+ Text = "Text",
+ Image = "Image",
+ ImageWithText = "ImageWithText",
+ Error = "Error",
+}
+
+export enum MessageSenderType {
+ Ai = "assistant",
+ User = "user",
+}
+
+export enum MessageStatus {
+ Ready = "ready",
+ Pending = "pending",
+}
+
+export type ConversationState = {
+ hasMore: boolean;
+ waitingForResponse: boolean;
+ error?: Error;
+};
diff --git a/electron/.prettierrc b/electron/.prettierrc
new file mode 100644
index 000000000..46f1abcb0
--- /dev/null
+++ b/electron/.prettierrc
@@ -0,0 +1,8 @@
+{
+ "semi": false,
+ "singleQuote": true,
+ "quoteProps": "consistent",
+ "trailingComma": "es5",
+ "endOfLine": "auto",
+ "plugins": ["prettier-plugin-tailwindcss"]
+}
diff --git a/electron/handlers/download.ts b/electron/handlers/download.ts
index ab672f25c..3a1fc36d1 100644
--- a/electron/handlers/download.ts
+++ b/electron/handlers/download.ts
@@ -1,10 +1,10 @@
-import { app, ipcMain } from "electron";
-import { DownloadManager } from "../managers/download";
-import { resolve, join } from "path";
-import { WindowManager } from "../managers/window";
-import request from "request";
-import { createWriteStream, unlink } from "fs";
-const progress = require("request-progress");
+import { app, ipcMain } from 'electron'
+import { DownloadManager } from '../managers/download'
+import { resolve, join } from 'path'
+import { WindowManager } from '../managers/window'
+import request from 'request'
+import { createWriteStream, unlink } from 'fs'
+const progress = require('request-progress')
export function handleDownloaderIPCs() {
/**
@@ -12,18 +12,18 @@ export function handleDownloaderIPCs() {
* @param _event - The IPC event object.
* @param fileName - The name of the file being downloaded.
*/
- ipcMain.handle("pauseDownload", async (_event, fileName) => {
- DownloadManager.instance.networkRequests[fileName]?.pause();
- });
+ ipcMain.handle('pauseDownload', async (_event, fileName) => {
+ DownloadManager.instance.networkRequests[fileName]?.pause()
+ })
/**
* Handles the "resumeDownload" IPC message by resuming the download associated with the provided fileName.
* @param _event - The IPC event object.
* @param fileName - The name of the file being downloaded.
*/
- ipcMain.handle("resumeDownload", async (_event, fileName) => {
- DownloadManager.instance.networkRequests[fileName]?.resume();
- });
+ ipcMain.handle('resumeDownload', async (_event, fileName) => {
+ DownloadManager.instance.networkRequests[fileName]?.resume()
+ })
/**
* Handles the "abortDownload" IPC message by aborting the download associated with the provided fileName.
@@ -31,24 +31,26 @@ export function handleDownloaderIPCs() {
* @param _event - The IPC event object.
* @param fileName - The name of the file being downloaded.
*/
- ipcMain.handle("abortDownload", async (_event, fileName) => {
- const rq = DownloadManager.instance.networkRequests[fileName];
- DownloadManager.instance.networkRequests[fileName] = undefined;
- const userDataPath = app.getPath("userData");
- const fullPath = join(userDataPath, fileName);
- rq?.abort();
- let result = "NULL";
+ ipcMain.handle('abortDownload', async (_event, fileName) => {
+ const rq = DownloadManager.instance.networkRequests[fileName]
+ DownloadManager.instance.networkRequests[fileName] = undefined
+ const userDataPath = app.getPath('userData')
+ const fullPath = join(userDataPath, fileName)
+ rq?.abort()
+ let result = 'NULL'
unlink(fullPath, function (err) {
- if (err && err.code == "ENOENT") {
- result = `File not exist: ${err}`;
+ if (err && err.code == 'ENOENT') {
+ result = `File not exist: ${err}`
} else if (err) {
- result = `File delete error: ${err}`;
+ result = `File delete error: ${err}`
} else {
- result = "File deleted successfully";
+ result = 'File deleted successfully'
}
- console.log(`Delete file ${fileName} from ${fullPath} result: ${result}`);
- });
- });
+ console.debug(
+ `Delete file ${fileName} from ${fullPath} result: ${result}`
+ )
+ })
+ })
/**
* Downloads a file from a given URL.
@@ -56,51 +58,51 @@ export function handleDownloaderIPCs() {
* @param url - The URL to download the file from.
* @param fileName - The name to give the downloaded file.
*/
- ipcMain.handle("downloadFile", async (_event, url, fileName) => {
- const userDataPath = app.getPath("userData");
- const destination = resolve(userDataPath, fileName);
- const rq = request(url);
+ ipcMain.handle('downloadFile', async (_event, url, fileName) => {
+ const userDataPath = join(app.getPath('home'), 'jan')
+ const destination = resolve(userDataPath, fileName)
+ const rq = request(url)
progress(rq, {})
- .on("progress", function (state: any) {
+ .on('progress', function (state: any) {
WindowManager?.instance.currentWindow?.webContents.send(
- "FILE_DOWNLOAD_UPDATE",
+ 'FILE_DOWNLOAD_UPDATE',
{
...state,
fileName,
}
- );
+ )
})
- .on("error", function (err: Error) {
+ .on('error', function (err: Error) {
WindowManager?.instance.currentWindow?.webContents.send(
- "FILE_DOWNLOAD_ERROR",
+ 'FILE_DOWNLOAD_ERROR',
{
fileName,
err,
}
- );
+ )
})
- .on("end", function () {
+ .on('end', function () {
if (DownloadManager.instance.networkRequests[fileName]) {
WindowManager?.instance.currentWindow?.webContents.send(
- "FILE_DOWNLOAD_COMPLETE",
+ 'FILE_DOWNLOAD_COMPLETE',
{
fileName,
}
- );
- DownloadManager.instance.setRequest(fileName, undefined);
+ )
+ DownloadManager.instance.setRequest(fileName, undefined)
} else {
WindowManager?.instance.currentWindow?.webContents.send(
- "FILE_DOWNLOAD_ERROR",
+ 'FILE_DOWNLOAD_ERROR',
{
fileName,
- err: "Download cancelled",
+ err: 'Download cancelled',
}
- );
+ )
}
})
- .pipe(createWriteStream(destination));
+ .pipe(createWriteStream(destination))
- DownloadManager.instance.setRequest(fileName, rq);
- });
+ DownloadManager.instance.setRequest(fileName, rq)
+ })
}
diff --git a/electron/handlers/fs.ts b/electron/handlers/fs.ts
index af77e3002..c1e8a85e4 100644
--- a/electron/handlers/fs.ts
+++ b/electron/handlers/fs.ts
@@ -1,28 +1,53 @@
-import { app, ipcMain } from "electron";
-import * as fs from "fs";
-import { join } from "path";
+import { app, ipcMain } from 'electron'
+import * as fs from 'fs'
+import { join } from 'path'
/**
* Handles file system operations.
*/
export function handleFsIPCs() {
+ const userSpacePath = join(app.getPath('home'), 'jan')
+
+ /**
+ * Gets the path to the user data directory.
+ * @param event - The event object.
+ * @returns A promise that resolves with the path to the user data directory.
+ */
+ ipcMain.handle(
+ 'getUserSpace',
+ (): Promise => Promise.resolve(userSpacePath)
+ )
+
+ /**
+ * Checks whether the path is a directory.
+ * @param event - The event object.
+ * @param path - The path to check.
+ * @returns A promise that resolves with a boolean indicating whether the path is a directory.
+ */
+ ipcMain.handle('isDirectory', (_event, path: string): Promise => {
+ const fullPath = join(userSpacePath, path)
+ return Promise.resolve(
+ fs.existsSync(fullPath) && fs.lstatSync(fullPath).isDirectory()
+ )
+ })
+
/**
* Reads a file from the user data directory.
* @param event - The event object.
* @param path - The path of the file to read.
* @returns A promise that resolves with the contents of the file.
*/
- ipcMain.handle("readFile", async (event, path: string): Promise => {
+ ipcMain.handle('readFile', async (event, path: string): Promise => {
return new Promise((resolve, reject) => {
- fs.readFile(join(app.getPath("userData"), path), "utf8", (err, data) => {
+ fs.readFile(join(userSpacePath, path), 'utf8', (err, data) => {
if (err) {
- reject(err);
+ reject(err)
} else {
- resolve(data);
+ resolve(data)
}
- });
- });
- });
+ })
+ })
+ })
/**
* Writes data to a file in the user data directory.
@@ -32,24 +57,19 @@ export function handleFsIPCs() {
* @returns A promise that resolves when the file has been written.
*/
ipcMain.handle(
- "writeFile",
+ 'writeFile',
async (event, path: string, data: string): Promise => {
return new Promise((resolve, reject) => {
- fs.writeFile(
- join(app.getPath("userData"), path),
- data,
- "utf8",
- (err) => {
- if (err) {
- reject(err);
- } else {
- resolve();
- }
+ fs.writeFile(join(userSpacePath, path), data, 'utf8', (err) => {
+ if (err) {
+ reject(err)
+ } else {
+ resolve()
}
- );
- });
+ })
+ })
}
- );
+ )
/**
* Creates a directory in the user data directory.
@@ -57,21 +77,17 @@ export function handleFsIPCs() {
* @param path - The path of the directory to create.
* @returns A promise that resolves when the directory has been created.
*/
- ipcMain.handle("mkdir", async (event, path: string): Promise => {
+ ipcMain.handle('mkdir', async (event, path: string): Promise => {
return new Promise((resolve, reject) => {
- fs.mkdir(
- join(app.getPath("userData"), path),
- { recursive: true },
- (err) => {
- if (err) {
- reject(err);
- } else {
- resolve();
- }
+ fs.mkdir(join(userSpacePath, path), { recursive: true }, (err) => {
+ if (err) {
+ reject(err)
+ } else {
+ resolve()
}
- );
- });
- });
+ })
+ })
+ })
/**
* Removes a directory in the user data directory.
@@ -79,21 +95,17 @@ export function handleFsIPCs() {
* @param path - The path of the directory to remove.
* @returns A promise that resolves when the directory is removed successfully.
*/
- ipcMain.handle("rmdir", async (event, path: string): Promise => {
+ ipcMain.handle('rmdir', async (event, path: string): Promise => {
return new Promise((resolve, reject) => {
- fs.rmdir(
- join(app.getPath("userData"), path),
- { recursive: true },
- (err) => {
- if (err) {
- reject(err);
- } else {
- resolve();
- }
+ fs.rmdir(join(userSpacePath, path), { recursive: true }, (err) => {
+ if (err) {
+ reject(err)
+ } else {
+ resolve()
}
- );
- });
- });
+ })
+ })
+ })
/**
* Lists the files in a directory in the user data directory.
@@ -102,19 +114,19 @@ export function handleFsIPCs() {
* @returns A promise that resolves with an array of file names.
*/
ipcMain.handle(
- "listFiles",
+ 'listFiles',
async (event, path: string): Promise => {
return new Promise((resolve, reject) => {
- fs.readdir(join(app.getPath("userData"), path), (err, files) => {
+ fs.readdir(join(userSpacePath, path), (err, files) => {
if (err) {
- reject(err);
+ reject(err)
} else {
- resolve(files);
+ resolve(files)
}
- });
- });
+ })
+ })
}
- );
+ )
/**
* Deletes a file from the user data folder.
@@ -122,22 +134,23 @@ export function handleFsIPCs() {
* @param filePath - The path to the file to delete.
* @returns A string indicating the result of the operation.
*/
- ipcMain.handle("deleteFile", async (_event, filePath) => {
- const userDataPath = app.getPath("userData");
- const fullPath = join(userDataPath, filePath);
+ ipcMain.handle('deleteFile', async (_event, filePath) => {
+ const fullPath = join(userSpacePath, filePath)
- let result = "NULL";
+ let result = 'NULL'
fs.unlink(fullPath, function (err) {
- if (err && err.code == "ENOENT") {
- result = `File not exist: ${err}`;
+ if (err && err.code == 'ENOENT') {
+ result = `File not exist: ${err}`
} else if (err) {
- result = `File delete error: ${err}`;
+ result = `File delete error: ${err}`
} else {
- result = "File deleted successfully";
+ result = 'File deleted successfully'
}
- console.log(`Delete file ${filePath} from ${fullPath} result: ${result}`);
- });
+ console.debug(
+ `Delete file ${filePath} from ${fullPath} result: ${result}`
+ )
+ })
- return result;
- });
+ return result
+ })
}
diff --git a/electron/handlers/plugin.ts b/electron/handlers/plugin.ts
index 26eb3c583..22bf253e6 100644
--- a/electron/handlers/plugin.ts
+++ b/electron/handlers/plugin.ts
@@ -30,7 +30,7 @@ export function handlePluginIPCs() {
if (typeof module[method] === "function") {
return module[method](...args);
} else {
- console.log(module[method]);
+ console.debug(module[method]);
console.error(`Function "${method}" does not exist in the module.`);
}
}
@@ -75,7 +75,7 @@ export function handlePluginIPCs() {
const fullPath = join(userDataPath, "plugins");
rmdir(fullPath, { recursive: true }, function (err) {
- if (err) console.log(err);
+ if (err) console.error(err);
ModuleManager.instance.clearImportedModules();
// just relaunch if packaged, should launch manually in development mode
diff --git a/electron/handlers/update.ts b/electron/handlers/update.ts
index 096d09bac..340db54b9 100644
--- a/electron/handlers/update.ts
+++ b/electron/handlers/update.ts
@@ -42,7 +42,7 @@ export function handleAppUpdates() {
/* App Update Progress */
autoUpdater.on("download-progress", (progress: any) => {
- console.log("app update progress: ", progress.percent);
+ console.debug("app update progress: ", progress.percent);
WindowManager.instance.currentWindow?.webContents.send(
"APP_UPDATE_PROGRESS",
{
diff --git a/electron/main.ts b/electron/main.ts
index 741a75867..5f1d6b086 100644
--- a/electron/main.ts
+++ b/electron/main.ts
@@ -1,23 +1,23 @@
-import { app, BrowserWindow } from "electron";
-import { join } from "path";
-import { setupMenu } from "./utils/menu";
-import { handleFsIPCs } from "./handlers/fs";
+import { app, BrowserWindow } from 'electron'
+import { join } from 'path'
+import { setupMenu } from './utils/menu'
+import { handleFsIPCs } from './handlers/fs'
/**
* Managers
**/
-import { WindowManager } from "./managers/window";
-import { ModuleManager } from "./managers/module";
-import { PluginManager } from "./managers/plugin";
+import { WindowManager } from './managers/window'
+import { ModuleManager } from './managers/module'
+import { PluginManager } from './managers/plugin'
/**
* IPC Handlers
**/
-import { handleDownloaderIPCs } from "./handlers/download";
-import { handleThemesIPCs } from "./handlers/theme";
-import { handlePluginIPCs } from "./handlers/plugin";
-import { handleAppIPCs } from "./handlers/app";
-import { handleAppUpdates } from "./handlers/update";
+import { handleDownloaderIPCs } from './handlers/download'
+import { handleThemesIPCs } from './handlers/theme'
+import { handlePluginIPCs } from './handlers/plugin'
+import { handleAppIPCs } from './handlers/app'
+import { handleAppUpdates } from './handlers/update'
app
.whenReady()
@@ -28,56 +28,56 @@ app
.then(handleAppUpdates)
.then(createMainWindow)
.then(() => {
- app.on("activate", () => {
+ app.on('activate', () => {
if (!BrowserWindow.getAllWindows().length) {
- createMainWindow();
+ createMainWindow()
}
- });
- });
+ })
+ })
-app.on("window-all-closed", () => {
- ModuleManager.instance.clearImportedModules();
- app.quit();
-});
+app.on('window-all-closed', () => {
+ ModuleManager.instance.clearImportedModules()
+ app.quit()
+})
-app.on("quit", () => {
- ModuleManager.instance.clearImportedModules();
- app.quit();
-});
+app.on('quit', () => {
+ ModuleManager.instance.clearImportedModules()
+ app.quit()
+})
function createMainWindow() {
/* Create main window */
const mainWindow = WindowManager.instance.createWindow({
webPreferences: {
nodeIntegration: true,
- preload: join(__dirname, "preload.js"),
+ preload: join(__dirname, 'preload.js'),
webSecurity: false,
},
- });
+ })
const startURL = app.isPackaged
- ? `file://${join(__dirname, "../renderer/index.html")}`
- : "http://localhost:3000";
+ ? `file://${join(__dirname, '../renderer/index.html')}`
+ : 'http://localhost:3000'
/* Load frontend app to the window */
- mainWindow.loadURL(startURL);
+ mainWindow.loadURL(startURL)
- mainWindow.once("ready-to-show", () => mainWindow?.show());
- mainWindow.on("closed", () => {
- if (process.platform !== "darwin") app.quit();
- });
+ mainWindow.once('ready-to-show', () => mainWindow?.show())
+ mainWindow.on('closed', () => {
+ if (process.platform !== 'darwin') app.quit()
+ })
/* Enable dev tools for development */
- if (!app.isPackaged) mainWindow.webContents.openDevTools();
+ if (!app.isPackaged) mainWindow.webContents.openDevTools()
}
/**
* Handles various IPC messages from the renderer process.
*/
function handleIPCs() {
- handleFsIPCs();
- handleDownloaderIPCs();
- handleThemesIPCs();
- handlePluginIPCs();
- handleAppIPCs();
+ handleFsIPCs()
+ handleDownloaderIPCs()
+ handleThemesIPCs()
+ handlePluginIPCs()
+ handleAppIPCs()
}
diff --git a/electron/managers/plugin.ts b/electron/managers/plugin.ts
index 889425ec7..227eab34e 100644
--- a/electron/managers/plugin.ts
+++ b/electron/managers/plugin.ts
@@ -42,14 +42,14 @@ export class PluginManager {
return new Promise((resolve) => {
const store = new Store();
if (store.get("migrated_version") !== app.getVersion()) {
- console.log("start migration:", store.get("migrated_version"));
+ console.debug("start migration:", store.get("migrated_version"));
const userDataPath = app.getPath("userData");
const fullPath = join(userDataPath, "plugins");
rmdir(fullPath, { recursive: true }, function (err) {
- if (err) console.log(err);
+ if (err) console.error(err);
store.set("migrated_version", app.getVersion());
- console.log("migrate plugins done");
+ console.debug("migrate plugins done");
resolve(undefined);
});
} else {
diff --git a/electron/preload.ts b/electron/preload.ts
index 398913da2..dfba13bd1 100644
--- a/electron/preload.ts
+++ b/electron/preload.ts
@@ -33,6 +33,8 @@
* @property {Function} relaunch - Relaunches the app.
* @property {Function} openAppDirectory - Opens the app directory.
* @property {Function} deleteFile - Deletes the file at the given path.
+ * @property {Function} isDirectory - Returns true if the file at the given path is a directory.
+ * @property {Function} getUserSpace - Returns the user space.
* @property {Function} readFile - Reads the file at the given path.
* @property {Function} writeFile - Writes the given data to the file at the given path.
* @property {Function} listFiles - Lists the files in the directory at the given path.
@@ -52,81 +54,85 @@
*/
// Make Pluggable Electron's facade available to the renderer on window.plugins
-import { useFacade } from "./core/plugin/facade";
+import { useFacade } from './core/plugin/facade'
-useFacade();
+useFacade()
-const { contextBridge, ipcRenderer } = require("electron");
+const { contextBridge, ipcRenderer } = require('electron')
-contextBridge.exposeInMainWorld("electronAPI", {
+contextBridge.exposeInMainWorld('electronAPI', {
invokePluginFunc: (plugin: any, method: any, ...args: any[]) =>
- ipcRenderer.invoke("invokePluginFunc", plugin, method, ...args),
+ ipcRenderer.invoke('invokePluginFunc', plugin, method, ...args),
- setNativeThemeLight: () => ipcRenderer.invoke("setNativeThemeLight"),
+ setNativeThemeLight: () => ipcRenderer.invoke('setNativeThemeLight'),
- setNativeThemeDark: () => ipcRenderer.invoke("setNativeThemeDark"),
+ setNativeThemeDark: () => ipcRenderer.invoke('setNativeThemeDark'),
- setNativeThemeSystem: () => ipcRenderer.invoke("setNativeThemeSystem"),
+ setNativeThemeSystem: () => ipcRenderer.invoke('setNativeThemeSystem'),
- basePlugins: () => ipcRenderer.invoke("basePlugins"),
+ basePlugins: () => ipcRenderer.invoke('basePlugins'),
- pluginPath: () => ipcRenderer.invoke("pluginPath"),
+ pluginPath: () => ipcRenderer.invoke('pluginPath'),
- appDataPath: () => ipcRenderer.invoke("appDataPath"),
+ appDataPath: () => ipcRenderer.invoke('appDataPath'),
- reloadPlugins: () => ipcRenderer.invoke("reloadPlugins"),
+ reloadPlugins: () => ipcRenderer.invoke('reloadPlugins'),
- appVersion: () => ipcRenderer.invoke("appVersion"),
+ appVersion: () => ipcRenderer.invoke('appVersion'),
- openExternalUrl: (url: string) => ipcRenderer.invoke("openExternalUrl", url),
+ openExternalUrl: (url: string) => ipcRenderer.invoke('openExternalUrl', url),
- relaunch: () => ipcRenderer.invoke("relaunch"),
+ relaunch: () => ipcRenderer.invoke('relaunch'),
- openAppDirectory: () => ipcRenderer.invoke("openAppDirectory"),
+ openAppDirectory: () => ipcRenderer.invoke('openAppDirectory'),
- deleteFile: (filePath: string) => ipcRenderer.invoke("deleteFile", filePath),
+ deleteFile: (filePath: string) => ipcRenderer.invoke('deleteFile', filePath),
- readFile: (path: string) => ipcRenderer.invoke("readFile", path),
+ isDirectory: (filePath: string) => ipcRenderer.invoke('isDirectory', filePath),
+
+ getUserSpace: () => ipcRenderer.invoke('getUserSpace'),
+
+ readFile: (path: string) => ipcRenderer.invoke('readFile', path),
writeFile: (path: string, data: string) =>
- ipcRenderer.invoke("writeFile", path, data),
+ ipcRenderer.invoke('writeFile', path, data),
- listFiles: (path: string) => ipcRenderer.invoke("listFiles", path),
+ listFiles: (path: string) => ipcRenderer.invoke('listFiles', path),
- mkdir: (path: string) => ipcRenderer.invoke("mkdir", path),
+ mkdir: (path: string) => ipcRenderer.invoke('mkdir', path),
- rmdir: (path: string) => ipcRenderer.invoke("rmdir", path),
+ rmdir: (path: string) => ipcRenderer.invoke('rmdir', path),
installRemotePlugin: (pluginName: string) =>
- ipcRenderer.invoke("installRemotePlugin", pluginName),
+ ipcRenderer.invoke('installRemotePlugin', pluginName),
downloadFile: (url: string, path: string) =>
- ipcRenderer.invoke("downloadFile", url, path),
+ ipcRenderer.invoke('downloadFile', url, path),
pauseDownload: (fileName: string) =>
- ipcRenderer.invoke("pauseDownload", fileName),
+ ipcRenderer.invoke('pauseDownload', fileName),
resumeDownload: (fileName: string) =>
- ipcRenderer.invoke("resumeDownload", fileName),
+ ipcRenderer.invoke('resumeDownload', fileName),
abortDownload: (fileName: string) =>
- ipcRenderer.invoke("abortDownload", fileName),
+ ipcRenderer.invoke('abortDownload', fileName),
onFileDownloadUpdate: (callback: any) =>
- ipcRenderer.on("FILE_DOWNLOAD_UPDATE", callback),
+ ipcRenderer.on('FILE_DOWNLOAD_UPDATE', callback),
onFileDownloadError: (callback: any) =>
- ipcRenderer.on("FILE_DOWNLOAD_ERROR", callback),
+ ipcRenderer.on('FILE_DOWNLOAD_ERROR', callback),
onFileDownloadSuccess: (callback: any) =>
- ipcRenderer.on("FILE_DOWNLOAD_COMPLETE", callback),
+ ipcRenderer.on('FILE_DOWNLOAD_COMPLETE', callback),
onAppUpdateDownloadUpdate: (callback: any) =>
- ipcRenderer.on("APP_UPDATE_PROGRESS", callback),
+ ipcRenderer.on('APP_UPDATE_PROGRESS', callback),
onAppUpdateDownloadError: (callback: any) =>
- ipcRenderer.on("APP_UPDATE_ERROR", callback),
+ ipcRenderer.on('APP_UPDATE_ERROR', callback),
onAppUpdateDownloadSuccess: (callback: any) =>
- ipcRenderer.on("APP_UPDATE_COMPLETE", callback),
-});
+ ipcRenderer.on('APP_UPDATE_COMPLETE', callback),
+})
diff --git a/plugins/conversational-json/package.json b/plugins/conversational-json/package.json
index 198756f82..520970664 100644
--- a/plugins/conversational-json/package.json
+++ b/plugins/conversational-json/package.json
@@ -24,6 +24,7 @@
},
"dependencies": {
"@janhq/core": "file:../../core",
+ "path-browserify": "^1.0.1",
"ts-loader": "^9.5.0"
},
"engines": {
diff --git a/plugins/conversational-json/src/index.ts b/plugins/conversational-json/src/index.ts
index b87f52a84..0e8465fd5 100644
--- a/plugins/conversational-json/src/index.ts
+++ b/plugins/conversational-json/src/index.ts
@@ -1,12 +1,15 @@
import { PluginType, fs } from '@janhq/core'
import { ConversationalPlugin } from '@janhq/core/lib/plugins'
import { Conversation } from '@janhq/core/lib/types'
+import { join } from 'path'
/**
* JSONConversationalPlugin is a ConversationalPlugin implementation that provides
* functionality for managing conversations.
*/
export default class JSONConversationalPlugin implements ConversationalPlugin {
+ private static readonly _homeDir = 'threads'
+
/**
* Returns the type of the plugin.
*/
@@ -18,7 +21,7 @@ export default class JSONConversationalPlugin implements ConversationalPlugin {
* Called when the plugin is loaded.
*/
onLoad() {
- fs.mkdir('conversations')
+ fs.mkdir(JSONConversationalPlugin._homeDir)
console.debug('JSONConversationalPlugin loaded')
}
@@ -65,10 +68,14 @@ export default class JSONConversationalPlugin implements ConversationalPlugin {
*/
saveConversation(conversation: Conversation): Promise {
return fs
- .mkdir(`conversations/${conversation._id}`)
+ .mkdir(`${JSONConversationalPlugin._homeDir}/${conversation.id}`)
.then(() =>
fs.writeFile(
- `conversations/${conversation._id}/${conversation._id}.json`,
+ join(
+ JSONConversationalPlugin._homeDir,
+ conversation.id,
+ `${conversation.id}.json`
+ ),
JSON.stringify(conversation)
)
)
@@ -79,7 +86,9 @@ export default class JSONConversationalPlugin implements ConversationalPlugin {
* @param conversationId The ID of the conversation to delete.
*/
deleteConversation(conversationId: string): Promise {
- return fs.rmdir(`conversations/${conversationId}`)
+ return fs.rmdir(
+ join(JSONConversationalPlugin._homeDir, `${conversationId}`)
+ )
}
/**
@@ -88,7 +97,9 @@ export default class JSONConversationalPlugin implements ConversationalPlugin {
* @returns data of the conversation
*/
private async readConvo(convoId: string): Promise {
- return fs.readFile(`conversations/${convoId}/${convoId}.json`)
+ return fs.readFile(
+ join(JSONConversationalPlugin._homeDir, convoId, `${convoId}.json`)
+ )
}
/**
@@ -97,8 +108,10 @@ export default class JSONConversationalPlugin implements ConversationalPlugin {
* @private
*/
private async getConversationDocs(): Promise {
- return fs.listFiles(`conversations`).then((files: string[]) => {
- return Promise.all(files.filter((file) => file.startsWith('jan-')))
- })
+ return fs
+ .listFiles(JSONConversationalPlugin._homeDir)
+ .then((files: string[]) => {
+ return Promise.all(files.filter((file) => file.startsWith('jan-')))
+ })
}
}
diff --git a/plugins/conversational-json/webpack.config.js b/plugins/conversational-json/webpack.config.js
index d4b0db2bd..36e338295 100644
--- a/plugins/conversational-json/webpack.config.js
+++ b/plugins/conversational-json/webpack.config.js
@@ -22,6 +22,9 @@ module.exports = {
plugins: [new webpack.DefinePlugin({})],
resolve: {
extensions: [".ts", ".js"],
+ fallback: {
+ path: require.resolve('path-browserify'),
+ },
},
// Do not minify the output, otherwise it breaks the class registration
optimization: {
diff --git a/plugins/conversational-plugin/src/index.ts b/plugins/conversational-plugin/src/index.ts
index b1c5bd937..01045b6c8 100644
--- a/plugins/conversational-plugin/src/index.ts
+++ b/plugins/conversational-plugin/src/index.ts
@@ -83,15 +83,15 @@ export default class JanConversationalPlugin implements ConversationalPlugin {
*/
private parseConversationMarkdown(markdown: string): Conversation {
const conversation: Conversation = {
- _id: "",
+ id: "",
name: "",
messages: [],
};
var currentMessage: Message | undefined = undefined;
for (const line of markdown.split("\n")) {
const trimmedLine = line.trim();
- if (trimmedLine.startsWith("- _id:")) {
- conversation._id = trimmedLine.replace("- _id:", "").trim();
+ if (trimmedLine.startsWith("- id:")) {
+ conversation.id = trimmedLine.replace("- id:", "").trim();
} else if (trimmedLine.startsWith("- modelId:")) {
conversation.modelId = trimmedLine.replace("- modelId:", "").trim();
} else if (trimmedLine.startsWith("- name:")) {
@@ -128,7 +128,7 @@ export default class JanConversationalPlugin implements ConversationalPlugin {
if (currentMessage) {
conversation.messages.push(currentMessage);
}
- currentMessage = { _id: messageMatch[1] };
+ currentMessage = { id: messageMatch[1] };
}
} else if (
currentMessage?.message &&
@@ -170,7 +170,7 @@ export default class JanConversationalPlugin implements ConversationalPlugin {
private generateMarkdown(conversation: Conversation): string {
// Generate the Markdown content based on the Conversation object
const conversationMetadata = `
- - _id: ${conversation._id}
+ - id: ${conversation.id}
- modelId: ${conversation.modelId}
- name: ${conversation.name}
- lastMessage: ${conversation.message}
@@ -182,7 +182,7 @@ export default class JanConversationalPlugin implements ConversationalPlugin {
const messages = conversation.messages.map(
(message) => `
- - Message ${message._id}:
+ - Message ${message.id}:
- createdAt: ${message.createdAt}
- user: ${message.user}
- message: ${message.message?.trim()}
@@ -204,10 +204,10 @@ export default class JanConversationalPlugin implements ConversationalPlugin {
private async writeMarkdownToFile(conversation: Conversation) {
// Generate the Markdown content
const markdownContent = this.generateMarkdown(conversation);
- await fs.mkdir(`conversations/${conversation._id}`);
+ await fs.mkdir(`conversations/${conversation.id}`);
// Write the content to a Markdown file
await fs.writeFile(
- `conversations/${conversation._id}/${conversation._id}.md`,
+ `conversations/${conversation.id}/${conversation.id}.md`,
markdownContent
);
}
diff --git a/plugins/inference-plugin/src/index.ts b/plugins/inference-plugin/src/index.ts
index ebd44657f..b02c0f628 100644
--- a/plugins/inference-plugin/src/index.ts
+++ b/plugins/inference-plugin/src/index.ts
@@ -18,7 +18,7 @@ import { InferencePlugin } from "@janhq/core/lib/plugins";
import { requestInference } from "./helpers/sse";
import { ulid } from "ulid";
import { join } from "path";
-import { appDataPath } from "@janhq/core";
+import { fs } from "@janhq/core";
/**
* A class that implements the InferencePlugin interface from the @janhq/core package.
@@ -54,8 +54,10 @@ export default class JanInferencePlugin implements InferencePlugin {
* @returns {Promise} A promise that resolves when the model is initialized.
*/
async initModel(modelFileName: string): Promise {
- const appPath = await appDataPath();
- return executeOnMain(MODULE, "initModel", join(appPath, modelFileName));
+ const userSpacePath = await fs.getUserSpace();
+ const modelFullPath = join(userSpacePath, modelFileName);
+
+ return executeOnMain(MODULE, "initModel", modelFullPath);
}
/**
@@ -84,7 +86,7 @@ export default class JanInferencePlugin implements InferencePlugin {
content: data.message,
},
];
- const recentMessages = await (data.history ?? prompts);
+ const recentMessages = data.history ?? prompts;
return new Promise(async (resolve, reject) => {
requestInference([
@@ -121,7 +123,7 @@ export default class JanInferencePlugin implements InferencePlugin {
message: "",
user: "assistant",
createdAt: new Date().toISOString(),
- _id: ulid(),
+ id: ulid(),
};
events.emit(EventName.OnNewMessageResponse, message);
diff --git a/plugins/inference-plugin/src/module.ts b/plugins/inference-plugin/src/module.ts
index ba6afdf90..613ad9fca 100644
--- a/plugins/inference-plugin/src/module.ts
+++ b/plugins/inference-plugin/src/module.ts
@@ -124,7 +124,7 @@ function killSubprocess(): Promise {
if (subprocess) {
subprocess.kill();
subprocess = null;
- console.log("Subprocess terminated.");
+ console.debug("Subprocess terminated.");
} else {
return kill(PORT, "tcp").then(console.log).catch(console.log);
}
diff --git a/plugins/model-plugin/.prettierrc b/plugins/model-plugin/.prettierrc
new file mode 100644
index 000000000..46f1abcb0
--- /dev/null
+++ b/plugins/model-plugin/.prettierrc
@@ -0,0 +1,8 @@
+{
+ "semi": false,
+ "singleQuote": true,
+ "quoteProps": "consistent",
+ "trailingComma": "es5",
+ "endOfLine": "auto",
+ "plugins": ["prettier-plugin-tailwindcss"]
+}
diff --git a/plugins/model-plugin/package.json b/plugins/model-plugin/package.json
index 171f0a4e9..43d1ffa8e 100644
--- a/plugins/model-plugin/package.json
+++ b/plugins/model-plugin/package.json
@@ -29,6 +29,7 @@
],
"dependencies": {
"@janhq/core": "file:../../core",
+ "path-browserify": "^1.0.1",
"ts-loader": "^9.5.0"
}
}
diff --git a/plugins/model-plugin/src/helpers/cloudNative.ts b/plugins/model-plugin/src/helpers/cloudNative.ts
deleted file mode 100644
index 90c6d3f1e..000000000
--- a/plugins/model-plugin/src/helpers/cloudNative.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import { EventName, events } from "@janhq/core";
-
-export async function pollDownloadProgress(fileName: string) {
- if (
- typeof window !== "undefined" &&
- typeof (window as any).electronAPI === "undefined"
- ) {
- const intervalId = setInterval(() => {
- notifyProgress(fileName, intervalId);
- }, 3000);
- }
-}
-
-export async function notifyProgress(
- fileName: string,
- intervalId: NodeJS.Timeout
-): Promise {
- const response = await fetch("/api/v1/downloadProgress", {
- method: "POST",
- body: JSON.stringify({ fileName: fileName }),
- headers: { "Content-Type": "application/json", Authorization: "" },
- });
-
- if (!response.ok) {
- events.emit(EventName.OnDownloadError, null);
- clearInterval(intervalId);
- return;
- }
- const json = await response.json();
- if (isEmptyObject(json)) {
- if (!fileName && intervalId) {
- clearInterval(intervalId);
- }
- return Promise.resolve("");
- }
- if (json.success === true) {
- events.emit(EventName.OnDownloadSuccess, json);
- clearInterval(intervalId);
- return Promise.resolve("");
- } else {
- events.emit(EventName.OnDownloadUpdate, json);
- return Promise.resolve(json.fileName);
- }
-}
-
-function isEmptyObject(ojb: any): boolean {
- return Object.keys(ojb).length === 0;
-}
diff --git a/plugins/model-plugin/src/helpers/modelParser.ts b/plugins/model-plugin/src/helpers/modelParser.ts
index d8b8a81f5..826a2afba 100644
--- a/plugins/model-plugin/src/helpers/modelParser.ts
+++ b/plugins/model-plugin/src/helpers/modelParser.ts
@@ -1,8 +1,8 @@
export const parseToModel = (model) => {
- const modelVersions = [];
+ 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,
@@ -11,12 +11,12 @@ export const parseToModel = (model) => {
usecase: v.usecase,
downloadLink: v.downloadLink,
productId: model.id,
- };
- modelVersions.push(version);
- });
+ }
+ modelVersions.push(version)
+ })
const product = {
- _id: model.id,
+ id: model.id,
name: model.name,
shortDescription: model.shortDescription,
avatarUrl: model.avatarUrl,
@@ -29,9 +29,9 @@ export const parseToModel = (model) => {
type: model.type,
createdAt: model.createdAt,
longDescription: model.longDescription,
- status: "Downloadable",
+ status: 'Downloadable',
releaseDate: 0,
availableVersions: modelVersions,
- };
- return product;
-};
+ }
+ return product
+}
diff --git a/plugins/model-plugin/src/index.ts b/plugins/model-plugin/src/index.ts
index ccfed6bfe..2e599c2d4 100644
--- a/plugins/model-plugin/src/index.ts
+++ b/plugins/model-plugin/src/index.ts
@@ -1,20 +1,21 @@
-import { PluginType, fs, downloadFile } from "@janhq/core";
-import { ModelPlugin } from "@janhq/core/lib/plugins";
-import { Model, ModelCatalog } from "@janhq/core/lib/types";
-import { pollDownloadProgress } from "./helpers/cloudNative";
-import { parseToModel } from "./helpers/modelParser";
+import { PluginType, fs, downloadFile } from '@janhq/core'
+import { ModelPlugin } from '@janhq/core/lib/plugins'
+import { Model, ModelCatalog } from '@janhq/core/lib/types'
+import { parseToModel } from './helpers/modelParser'
+import { join } from 'path'
/**
* A plugin for managing machine learning models.
*/
export default class JanModelPlugin implements ModelPlugin {
+ private static readonly _homeDir = 'models'
/**
* Implements type from JanPlugin.
* @override
* @returns The type of the plugin.
*/
type(): PluginType {
- return PluginType.Model;
+ return PluginType.Model
}
/**
@@ -25,6 +26,7 @@ export default class JanModelPlugin implements ModelPlugin {
/** Cloud Native
* TODO: Fetch all downloading progresses?
**/
+ fs.mkdir(JanModelPlugin._homeDir)
}
/**
@@ -39,12 +41,13 @@ export default class JanModelPlugin implements ModelPlugin {
* @returns A Promise that resolves when the model is downloaded.
*/
async downloadModel(model: Model): Promise {
- await fs.mkdir("models");
- downloadFile(model.downloadLink, `models/${model._id}`);
- /** Cloud Native
- * MARK: Poll Downloading Progress
- **/
- pollDownloadProgress(model._id);
+ // create corresponding directory
+ const directoryPath = join(JanModelPlugin._homeDir, model.productName)
+ await fs.mkdir(directoryPath)
+
+ // path to model binary
+ const path = join(directoryPath, model.id)
+ downloadFile(model.downloadLink, path)
}
/**
@@ -52,10 +55,15 @@ export default class JanModelPlugin implements ModelPlugin {
* @param filePath - The path to the model file to delete.
* @returns A Promise that resolves when the model is deleted.
*/
- deleteModel(filePath: string): Promise {
- return fs
- .deleteFile(`models/${filePath}`)
- .then(() => fs.deleteFile(`models/m-${filePath}.json`));
+ async deleteModel(filePath: string): Promise {
+ try {
+ await Promise.allSettled([
+ fs.deleteFile(filePath),
+ fs.deleteFile(`${filePath}.json`),
+ ])
+ } catch (err) {
+ console.error(err)
+ }
}
/**
@@ -64,30 +72,46 @@ export default class JanModelPlugin implements ModelPlugin {
* @returns A Promise that resolves when the model is saved.
*/
async saveModel(model: Model): Promise {
- await fs.writeFile(`models/m-${model._id}.json`, JSON.stringify(model));
+ const directoryPath = join(JanModelPlugin._homeDir, model.productName)
+ const jsonFilePath = join(directoryPath, `${model.id}.json`)
+
+ try {
+ await fs.writeFile(jsonFilePath, JSON.stringify(model))
+ } catch (err) {
+ console.error(err)
+ }
}
/**
* Gets all downloaded models.
* @returns A Promise that resolves with an array of all models.
*/
- getDownloadedModels(): Promise {
- return fs
- .listFiles("models")
- .then((files: string[]) => {
- return Promise.all(
- files
- .filter((file) => /^m-.*\.json$/.test(file))
- .map(async (file) => {
- const model: Model = JSON.parse(
- await fs.readFile(`models/${file}`)
- );
- return model;
- })
- );
- })
- .catch((e) => fs.mkdir("models").then(() => []));
+ async getDownloadedModels(): Promise {
+ const results: Model[] = []
+ const allDirs: string[] = await fs.listFiles(JanModelPlugin._homeDir)
+ for (const dir of allDirs) {
+ const modelDirPath = join(JanModelPlugin._homeDir, dir)
+ const isModelDir = await fs.isDirectory(modelDirPath)
+ if (!isModelDir) {
+ // if not a directory, ignore
+ continue
+ }
+
+ const jsonFiles: string[] = (await fs.listFiles(modelDirPath)).filter(
+ (file: string) => file.endsWith('.json')
+ )
+
+ for (const json of jsonFiles) {
+ const model: Model = JSON.parse(
+ await fs.readFile(join(modelDirPath, json))
+ )
+ results.push(model)
+ }
+ }
+
+ return results
}
+
/**
* Gets all available models.
* @returns A Promise that resolves with an array of all models.
@@ -96,10 +120,6 @@ export default class JanModelPlugin implements ModelPlugin {
// Add a timestamp to the URL to prevent caching
return import(
/* webpackIgnore: true */ MODEL_CATALOG_URL + `?t=${Date.now()}`
- ).then((module) =>
- module.default.map((e) => {
- return parseToModel(e);
- })
- );
+ ).then((module) => module.default.map((e) => parseToModel(e)))
}
}
diff --git a/plugins/model-plugin/webpack.config.js b/plugins/model-plugin/webpack.config.js
index 60fa1a9b0..3475516ed 100644
--- a/plugins/model-plugin/webpack.config.js
+++ b/plugins/model-plugin/webpack.config.js
@@ -1,16 +1,16 @@
-const path = require("path");
-const webpack = require("webpack");
-const packageJson = require("./package.json");
+const path = require('path')
+const webpack = require('webpack')
+const packageJson = require('./package.json')
module.exports = {
experiments: { outputModule: true },
- entry: "./src/index.ts", // Adjust the entry point to match your project's main file
- mode: "production",
+ entry: './src/index.ts', // Adjust the entry point to match your project's main file
+ mode: 'production',
module: {
rules: [
{
test: /\.tsx?$/,
- use: "ts-loader",
+ use: 'ts-loader',
exclude: /node_modules/,
},
],
@@ -20,20 +20,23 @@ module.exports = {
PLUGIN_NAME: JSON.stringify(packageJson.name),
MODULE_PATH: JSON.stringify(`${packageJson.name}/${packageJson.module}`),
MODEL_CATALOG_URL: JSON.stringify(
- "https://cdn.jsdelivr.net/npm/@janhq/models@latest/dist/index.js"
+ 'https://cdn.jsdelivr.net/npm/@janhq/models@latest/dist/index.js'
),
}),
],
output: {
- filename: "index.js", // Adjust the output file name as needed
- path: path.resolve(__dirname, "dist"),
- library: { type: "module" }, // Specify ESM output format
+ filename: '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"],
+ extensions: ['.ts', '.js'],
+ fallback: {
+ path: require.resolve('path-browserify'),
+ },
},
optimization: {
minimize: false,
},
// Add loaders and other configuration as needed for your project
-};
+}
diff --git a/web/containers/Layout/BottomBar/index.tsx b/web/containers/Layout/BottomBar/index.tsx
index 9752888fa..9153da2c7 100644
--- a/web/containers/Layout/BottomBar/index.tsx
+++ b/web/containers/Layout/BottomBar/index.tsx
@@ -46,7 +46,7 @@ const BottomBar = () => {
⌘e to show your model
)
}
diff --git a/web/containers/Layout/TopBar/CommandListDownloadedModel/index.tsx b/web/containers/Layout/TopBar/CommandListDownloadedModel/index.tsx
index 108aa8e82..fee918f3a 100644
--- a/web/containers/Layout/TopBar/CommandListDownloadedModel/index.tsx
+++ b/web/containers/Layout/TopBar/CommandListDownloadedModel/index.tsx
@@ -24,7 +24,7 @@ export default function CommandListDownloadedModel() {
const { activeModel, startModel, stopModel } = useActiveModel()
const onModelActionClick = (modelId: string) => {
- if (activeModel && activeModel._id === modelId) {
+ if (activeModel && activeModel.id === modelId) {
stopModel(modelId)
} else {
startModel(modelId)
@@ -62,7 +62,7 @@ export default function CommandListDownloadedModel() {
{
- onModelActionClick(model._id)
+ onModelActionClick(model.id)
setOpen(false)
}}
>
@@ -72,7 +72,7 @@ export default function CommandListDownloadedModel() {
/>