From 7ae36a38805cf333c7f25ccf4c1bd6d1405d3c64 Mon Sep 17 00:00:00 2001 From: hieu-jan <150573299+hieu-jan@users.noreply.github.com> Date: Thu, 8 Feb 2024 20:27:57 +0700 Subject: [PATCH 01/35] docs: add author Henry --- docs/blog/authors.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/blog/authors.yml b/docs/blog/authors.yml index 4c1dc521e..d8687911b 100644 --- a/docs/blog/authors.yml +++ b/docs/blog/authors.yml @@ -11,7 +11,7 @@ namchuai: url: https://github.com/namchuai image_url: https://avatars.githubusercontent.com/u/10397206?v=4 email: james@jan.ai - + hiro-v: name: Hiro Vuong title: MLE @@ -60,4 +60,10 @@ automaticcat: url: https://github.com/tikikun image_url: https://avatars.githubusercontent.com/u/22268502?v=4 email: alan@jan.ai - + +hieu-jan: + name: Henry Ho + title: Software Engineer + url: https://github.com/hieu-jan + image_url: https://avatars.githubusercontent.com/u/150573299?v=4 + email: hieu@jan.ai From fe02d038ae6a5c8cc7e5af4f0c5da9c9758d56fa Mon Sep 17 00:00:00 2001 From: 0xSage <69952136+0xSage@users.noreply.github.com> Date: Fri, 9 Feb 2024 16:46:57 +0800 Subject: [PATCH 02/35] docs: Update authors.yml --- docs/blog/authors.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/blog/authors.yml b/docs/blog/authors.yml index d8687911b..ec58002e4 100644 --- a/docs/blog/authors.yml +++ b/docs/blog/authors.yml @@ -67,3 +67,10 @@ hieu-jan: url: https://github.com/hieu-jan image_url: https://avatars.githubusercontent.com/u/150573299?v=4 email: hieu@jan.ai + +0xsage: + name: Nicole Zhu + title: Co-Founder + url: https://github.com/0xsage + image_url: https://avatars.githubusercontent.com/u/69952136?v=4 + email: nicole@jan.ai From bb11bc29338e3bff0ba534d1cfd898c43d6225c0 Mon Sep 17 00:00:00 2001 From: Faisal Amir Date: Fri, 9 Feb 2024 18:10:43 +0700 Subject: [PATCH 03/35] feat: add modal troubleshooting guideline (#1968) * feat: add modal troubleshooting guideline * show app, server log and device specs from user agent * add function copy app, server log and device specs * add todo device specs * update style darkmode for modal troubleshoot * resolve inconsistent message hidden * fix: model failed to load but the server started successfully (#1971) * fix: start server success but modal load failed * add information model failed load while start server successfully --- web/containers/ModalTroubleShoot/AppLogs.tsx | 203 +++++++++++++++++ .../ModalTroubleShoot/DeviceSpecs.tsx | 46 ++++ web/containers/ModalTroubleShoot/index.tsx | 121 ++++++++++ web/containers/Providers/EventHandler.tsx | 2 +- web/containers/ServerLogs/index.tsx | 213 ++++++++++++++++++ web/hooks/{useServerLog.ts => useLogs.tsx} | 10 +- web/screens/Chat/ChatBody/index.tsx | 3 +- web/screens/Chat/ErrorMessage/index.tsx | 44 ++-- web/screens/LocalServer/Logs.tsx | 179 --------------- web/screens/LocalServer/index.tsx | 38 +++- web/tsconfig.json | 10 +- 11 files changed, 648 insertions(+), 221 deletions(-) create mode 100644 web/containers/ModalTroubleShoot/AppLogs.tsx create mode 100644 web/containers/ModalTroubleShoot/DeviceSpecs.tsx create mode 100644 web/containers/ModalTroubleShoot/index.tsx create mode 100644 web/containers/ServerLogs/index.tsx rename web/hooks/{useServerLog.ts => useLogs.tsx} (67%) delete mode 100644 web/screens/LocalServer/Logs.tsx diff --git a/web/containers/ModalTroubleShoot/AppLogs.tsx b/web/containers/ModalTroubleShoot/AppLogs.tsx new file mode 100644 index 000000000..d4f6bddb8 --- /dev/null +++ b/web/containers/ModalTroubleShoot/AppLogs.tsx @@ -0,0 +1,203 @@ +import React, { useEffect, useState } from 'react' + +import { Button } from '@janhq/uikit' + +import { CopyIcon, CheckIcon } from 'lucide-react' + +import { useClipboard } from '@/hooks/useClipboard' +import { useLogs } from '@/hooks/useLogs' + +const AppLogs = () => { + const { getLogs } = useLogs() + const [logs, setLogs] = useState([]) + + useEffect(() => { + getLogs('app').then((log) => { + if (typeof log?.split === 'function') { + setLogs(log.split(/\r?\n|\r|\n/g)) + } + }) + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + const clipboard = useClipboard({ timeout: 1000 }) + + return ( + <> +
+ +
+
+ {logs.length > 1 ? ( +
+ + {logs.slice(-100).map((log, i) => { + return ( +

+ {log} +

+ ) + })} +
+
+ ) : ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Empty logs

+
+ )} +
+ + ) +} + +export default AppLogs diff --git a/web/containers/ModalTroubleShoot/DeviceSpecs.tsx b/web/containers/ModalTroubleShoot/DeviceSpecs.tsx new file mode 100644 index 000000000..5ebb610d1 --- /dev/null +++ b/web/containers/ModalTroubleShoot/DeviceSpecs.tsx @@ -0,0 +1,46 @@ +import React from 'react' + +import { Button } from '@janhq/uikit' + +import { CopyIcon, CheckIcon } from 'lucide-react' + +import { useClipboard } from '@/hooks/useClipboard' + +// TODO @Louis help add missing information device specs +const DeviceSpecs = () => { + const userAgent = window.navigator.userAgent + const clipboard = useClipboard({ timeout: 1000 }) + + return ( + <> +
+ +
+
+

{userAgent}

+
+ + ) +} + +export default DeviceSpecs diff --git a/web/containers/ModalTroubleShoot/index.tsx b/web/containers/ModalTroubleShoot/index.tsx new file mode 100644 index 000000000..547398c4f --- /dev/null +++ b/web/containers/ModalTroubleShoot/index.tsx @@ -0,0 +1,121 @@ +import { useState } from 'react' +import ScrollToBottom from 'react-scroll-to-bottom' + +import { Modal, ModalContent, ModalHeader, ModalTitle } from '@janhq/uikit' +import { motion as m } from 'framer-motion' +import { atom, useAtom } from 'jotai' +import { twMerge } from 'tailwind-merge' + +import ServerLogs from '../ServerLogs' + +import AppLogs from './AppLogs' +import DeviceSpecs from './DeviceSpecs' + +export const modalTroubleShootingAtom = atom(false) +const logOption = ['App Logs', 'Server Logs', 'Device Specs'] + +const ModalTroubleShooting: React.FC = () => { + const [modalTroubleShooting, setModalTroubleShooting] = useAtom( + modalTroubleShootingAtom + ) + const [isTabActive, setIsTabActivbe] = useState(0) + + return ( + + + + Troubleshooting Assistance + +

+ {`We're here to help! Your report is crucial for debugging and shaping + the next version. Here’s how you can report & get further support:`} +

+ +
+

Step 1

+

+ Follow our  + + troubleshooting guide + +  for step-by-step solutions. +

+
+ +
+
+

Step 2

+

+ {`If you can't find what you need in our troubleshooting guide, feel + free reach out to us for extra help:`} +

+
    +
  • +

    + Copy your 2-hour logs & device specifications provided below.{' '} +

    +
  • +
  • +

    + Go to our  + + Discord + +   & send it to #🆘|get-help channel for further support. +

    +
  • +
+
+ +
+ {/* TODO @faisal replace this once we have better tabs component UI */} +
+
    + {logOption.map((name, i) => { + return ( +
  • setIsTabActivbe(i)} + > + + {name} + + {isTabActive === i && ( + + )} +
  • + ) + })} +
+
+ + {isTabActive === 0 && } + {isTabActive === 1 && } + {isTabActive === 2 && } + +
+
+
+
+ ) +} + +export default ModalTroubleShooting diff --git a/web/containers/Providers/EventHandler.tsx b/web/containers/Providers/EventHandler.tsx index cfd2c5629..170ec5e64 100644 --- a/web/containers/Providers/EventHandler.tsx +++ b/web/containers/Providers/EventHandler.tsx @@ -95,12 +95,12 @@ export default function EventHandler({ children }: { children: ReactNode }) { (res: any) => { const errorMessage = `${res.error}` console.error('Failed to load model: ' + errorMessage) - setLoadModelError(errorMessage) setStateModel(() => ({ state: 'start', loading: false, model: res.modelId, })) + setLoadModelError(errorMessage) setQueuedMessage(false) }, [setStateModel, setQueuedMessage, setLoadModelError] diff --git a/web/containers/ServerLogs/index.tsx b/web/containers/ServerLogs/index.tsx new file mode 100644 index 000000000..c97643769 --- /dev/null +++ b/web/containers/ServerLogs/index.tsx @@ -0,0 +1,213 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import { useEffect, useState } from 'react' + +import React from 'react' + +import { Button } from '@janhq/uikit' +import { useAtomValue } from 'jotai' + +import { CopyIcon, CheckIcon } from 'lucide-react' + +import { useClipboard } from '@/hooks/useClipboard' +import { useLogs } from '@/hooks/useLogs' + +import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom' + +type ServerLogsProps = { limit?: number; withCopy?: boolean } + +const ServerLogs = (props: ServerLogsProps) => { + const { limit = 0 } = props + const { getLogs } = useLogs() + const serverEnabled = useAtomValue(serverEnabledAtom) + const [logs, setLogs] = useState([]) + + const clipboard = useClipboard({ timeout: 1000 }) + + useEffect(() => { + getLogs('server').then((log) => { + if (typeof log?.split === 'function') { + setLogs(log.split(/\r?\n|\r|\n/g)) + } + }) + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [logs, serverEnabled]) + + return ( + <> +
+ +
+
+ {logs.length > 1 ? ( +
+ + {logs.slice(-limit).map((log, i) => { + return ( +

+ {log} +

+ ) + })} +
+
+ ) : ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Empty logs

+
+ )} +
+ + ) +} + +export default ServerLogs diff --git a/web/hooks/useServerLog.ts b/web/hooks/useLogs.tsx similarity index 67% rename from web/hooks/useServerLog.ts rename to web/hooks/useLogs.tsx index b263534b6..7c504428f 100644 --- a/web/hooks/useServerLog.ts +++ b/web/hooks/useLogs.tsx @@ -5,12 +5,12 @@ import { getJanDataFolderPath, } from '@janhq/core' -export const useServerLog = () => { - const getServerLog = async () => { - if (!(await fs.existsSync(await joinPath(['file://logs', 'server.log'])))) +export const useLogs = () => { + const getLogs = async (file: string) => { + if (!(await fs.existsSync(await joinPath(['file://logs', `${file}.log`])))) return {} const logs = await fs.readFileSync( - await joinPath(['file://logs', 'server.log']), + await joinPath(['file://logs', `${file}.log`]), 'utf-8' ) @@ -25,5 +25,5 @@ export const useServerLog = () => { const clearServerLog = async () => { await fs.writeFileSync(await joinPath(['file://logs', 'server.log']), '') } - return { getServerLog, openServerLog, clearServerLog } + return { getLogs, openServerLog, clearServerLog } } diff --git a/web/screens/Chat/ChatBody/index.tsx b/web/screens/Chat/ChatBody/index.tsx index 0e8d55c0b..ee0b4592d 100644 --- a/web/screens/Chat/ChatBody/index.tsx +++ b/web/screens/Chat/ChatBody/index.tsx @@ -81,7 +81,8 @@ const ChatBody: React.FC = () => { {messages.map((message, index) => (
- {(message.status !== MessageStatus.Pending || + {((message.status !== MessageStatus.Error && + message.status !== MessageStatus.Pending) || message.content.length > 0) && ( )} diff --git a/web/screens/Chat/ErrorMessage/index.tsx b/web/screens/Chat/ErrorMessage/index.tsx index b73884659..ea9906335 100644 --- a/web/screens/Chat/ErrorMessage/index.tsx +++ b/web/screens/Chat/ErrorMessage/index.tsx @@ -9,6 +9,10 @@ import { Button } from '@janhq/uikit' import { useAtomValue, useSetAtom } from 'jotai' import { RefreshCcw } from 'lucide-react' +import ModalTroubleShooting, { + modalTroubleShootingAtom, +} from '@/containers/ModalTroubleShoot' + import useSendChatMessage from '@/hooks/useSendChatMessage' import { extensionManager } from '@/extension' @@ -23,6 +27,7 @@ const ErrorMessage = ({ message }: { message: ThreadMessage }) => { const thread = useAtomValue(activeThreadAtom) const deleteMessage = useSetAtom(deleteMessageAtom) const { resendChatMessage } = useSendChatMessage() + const setModalTroubleShooting = useSetAtom(modalTroubleShootingAtom) const regenerateMessage = async () => { const lastMessageIndex = messages.length - 1 @@ -64,29 +69,22 @@ const ErrorMessage = ({ message }: { message: ThreadMessage }) => {
)} {message.status === MessageStatus.Error && ( -
- - <> -

Apologies, something's amiss!

- Jan's in beta. Find troubleshooting guides{' '} - - here - {' '} - or reach out to us on{' '} - - Discord - {' '} - for assistance. - -
+
+

{`Apologies, something’s amiss!`}

+

+ Jan’s in beta. Access  + setModalTroubleShooting(true)} + > + troubleshooting assistance + +  now. +

+
)} diff --git a/web/screens/LocalServer/Logs.tsx b/web/screens/LocalServer/Logs.tsx deleted file mode 100644 index 125bd93ef..000000000 --- a/web/screens/LocalServer/Logs.tsx +++ /dev/null @@ -1,179 +0,0 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import { useEffect, useState } from 'react' - -import React from 'react' - -import { useAtomValue } from 'jotai' - -import { useServerLog } from '@/hooks/useServerLog' - -import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom' - -const Logs = () => { - const { getServerLog } = useServerLog() - const serverEnabled = useAtomValue(serverEnabledAtom) - const [logs, setLogs] = useState([]) - - useEffect(() => { - getServerLog().then((log) => { - if (typeof log?.split === 'function') { - setLogs(log.split(/\r?\n|\r|\n/g)) - } - }) - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [logs, serverEnabled]) - - return ( -
- {logs.length > 1 ? ( -
- - {logs.map((log, i) => { - return ( -

- {log} -

- ) - })} -
-
- ) : ( -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Empty logs

-
- )} -
- ) -} - -export default Logs diff --git a/web/screens/LocalServer/index.tsx b/web/screens/LocalServer/index.tsx index b96f4c228..65b6c8563 100644 --- a/web/screens/LocalServer/index.tsx +++ b/web/screens/LocalServer/index.tsx @@ -20,11 +20,12 @@ import { SelectValue, } from '@janhq/uikit' -import { atom, useAtom, useAtomValue } from 'jotai' +import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai' import { Paintbrush, CodeIcon } from 'lucide-react' import { ExternalLinkIcon, InfoIcon } from 'lucide-react' +import { AlertTriangleIcon } from 'lucide-react' import { twMerge } from 'tailwind-merge' import CardSidebar from '@/containers/CardSidebar' @@ -33,8 +34,13 @@ import DropdownListSidebar, { selectedModelAtom, } from '@/containers/DropdownListSidebar' -import { useActiveModel } from '@/hooks/useActiveModel' -import { useServerLog } from '@/hooks/useServerLog' +import ModalTroubleShooting, { + modalTroubleShootingAtom, +} from '@/containers/ModalTroubleShoot' +import ServerLogs from '@/containers/ServerLogs' + +import { loadModelErrorAtom, useActiveModel } from '@/hooks/useActiveModel' +import { useLogs } from '@/hooks/useLogs' import { getConfigurationsData } from '@/utils/componentSettings' import { toSettingParams } from '@/utils/modelParam' @@ -45,8 +51,6 @@ import SettingComponentBuilder from '../Chat/ModelSetting/SettingComponent' import { showRightSideBarAtom } from '../Chat/Sidebar' -import Logs from './Logs' - import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom' import { getActiveThreadModelParamsAtom } from '@/helpers/atoms/Thread.atom' @@ -60,11 +64,12 @@ const LocalServerScreen = () => { const [serverEnabled, setServerEnabled] = useAtom(serverEnabledAtom) const showRightSideBar = useAtomValue(showRightSideBarAtom) const activeModelParams = useAtomValue(getActiveThreadModelParamsAtom) + const setModalTroubleShooting = useSetAtom(modalTroubleShootingAtom) const modelEngineParams = toSettingParams(activeModelParams) const componentDataEngineSetting = getConfigurationsData(modelEngineParams) - const { openServerLog, clearServerLog } = useServerLog() + const { openServerLog, clearServerLog } = useLogs() const { startModel, stateModel } = useActiveModel() const selectedModel = useAtomValue(selectedModelAtom) @@ -72,6 +77,7 @@ const LocalServerScreen = () => { const [isVerboseEnabled, setIsVerboseEnabled] = useAtom(verboseEnabledAtom) const [host, setHost] = useAtom(hostAtom) const [port, setPort] = useAtom(portAtom) + const [loadModelError, setLoadModelError] = useAtom(loadModelErrorAtom) const hostOptions = ['127.0.0.1', '0.0.0.0'] @@ -122,6 +128,7 @@ const LocalServerScreen = () => { if (serverEnabled) { window.core?.api?.stopServer() setServerEnabled(false) + setLoadModelError(undefined) } else { startModel(String(selectedModel?.id)) window.core?.api?.startServer({ @@ -350,7 +357,9 @@ const LocalServerScreen = () => {
) : ( - +
+ +
)}
@@ -365,6 +374,20 @@ const LocalServerScreen = () => { >
+ {loadModelError && ( +
+ + + Model failed to start. Access{' '} + setModalTroubleShooting(true)} + > + troubleshooting assistance + + +
+ )} {componentDataEngineSetting.filter( (x) => x.name === 'prompt_template' @@ -393,6 +416,7 @@ const LocalServerScreen = () => { )}
+ ) } diff --git a/web/tsconfig.json b/web/tsconfig.json index 26f0e8ef3..1729c971f 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -17,13 +17,13 @@ "incremental": true, "plugins": [ { - "name": "next", - }, + "name": "next" + } ], "paths": { - "@/*": ["./*"], - }, + "@/*": ["./*"] + } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"], + "exclude": ["node_modules"] } From eb09399fbf408b099ff3140e8180ad78a66cdda1 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 9 Feb 2024 19:23:56 +0700 Subject: [PATCH 04/35] chore: reduce bundle size (#1970) * chore: reduce bundle size * chore: trimming langchainjs * chore: trim pdf-parse --- electron/package.json | 9 ++++----- extensions/assistant-extension/package.json | 10 ++++------ .../assistant-extension/rollup.config.ts | 3 --- .../conversational-extension/package.json | 6 +++--- .../inference-nitro-extension/package.json | 6 +++--- .../inference-openai-extension/package.json | 4 ++-- .../package.json | 4 ++-- extensions/model-extension/package.json | 6 +++--- extensions/monitoring-extension/package.json | 6 +++--- models/mistral-ins-7b-q4/cover.png | Bin 5084238 -> 234495 bytes models/openhermes-neural-7b/cover.png | Bin 4070227 -> 365073 bytes models/trinity-v1.2-7b/cover.png | Bin 1733715 -> 360002 bytes .../ExploreModels/ExploreModelList/index.tsx | 4 ++-- 13 files changed, 26 insertions(+), 32 deletions(-) diff --git a/electron/package.json b/electron/package.json index 229979b41..48f3a0811 100644 --- a/electron/package.json +++ b/electron/package.json @@ -11,7 +11,6 @@ "productName": "Jan", "files": [ "renderer/**/*", - "build/*.{js,map}", "build/**/*.{js,map}", "pre-install", "models/**/*", @@ -77,7 +76,6 @@ "@janhq/core": "link:./core", "@janhq/server": "link:./server", "@npmcli/arborist": "^7.1.0", - "@types/request": "^2.48.12", "@uiball/loaders": "^1.3.0", "electron-store": "^8.1.0", "electron-updater": "^6.1.7", @@ -86,8 +84,6 @@ "pacote": "^17.0.4", "request": "^2.88.2", "request-progress": "^3.0.0", - "rimraf": "^5.0.5", - "typescript": "^5.2.2", "ulid": "^2.3.0", "use-debounce": "^9.0.4" }, @@ -96,6 +92,7 @@ "@playwright/test": "^1.38.1", "@types/npmcli__arborist": "^5.6.4", "@types/pacote": "^11.1.7", + "@types/request": "^2.48.12", "@typescript-eslint/eslint-plugin": "^6.7.3", "@typescript-eslint/parser": "^6.7.3", "electron": "28.0.0", @@ -103,7 +100,9 @@ "electron-devtools-installer": "^3.2.0", "electron-playwright-helpers": "^1.6.0", "eslint-plugin-react": "^7.33.2", - "run-script-os": "^1.1.6" + "rimraf": "^5.0.5", + "run-script-os": "^1.1.6", + "typescript": "^5.2.2" }, "installConfig": { "hoistingLimits": "workspaces" diff --git a/extensions/assistant-extension/package.json b/extensions/assistant-extension/package.json index 5f45ecabe..2d0d8f5c7 100644 --- a/extensions/assistant-extension/package.json +++ b/extensions/assistant-extension/package.json @@ -7,7 +7,8 @@ "author": "Jan ", "license": "AGPL-3.0", "scripts": { - "build": "tsc --module commonjs && rollup -c rollup.config.ts", + "clean:modules": "rimraf node_modules/pdf-parse/test && cd node_modules/pdf-parse/lib/pdf.js && rimraf v1.9.426 v1.10.88 v2.0.550", + "build": "yarn clean:modules && tsc --module commonjs && rollup -c rollup.config.ts", "build:publish:linux": "rimraf *.tgz --glob && npm run build && npm pack && cpx *.tgz ../../pre-install", "build:publish:darwin": "rimraf *.tgz --glob && npm run build && ../../.github/scripts/auto-sign.sh && npm pack && cpx *.tgz ../../pre-install", "build:publish:win32": "rimraf *.tgz --glob && npm run build && npm pack && cpx *.tgz ../../pre-install", @@ -25,7 +26,7 @@ "rollup-plugin-define": "^1.0.1", "rollup-plugin-sourcemaps": "^0.6.3", "rollup-plugin-typescript2": "^0.36.0", - "typescript": "^5.3.3", + "typescript": "^5.2.2", "run-script-os": "^1.1.6" }, "dependencies": { @@ -44,9 +45,6 @@ ], "bundleDependencies": [ "@janhq/core", - "@langchain/community", - "hnswlib-node", - "langchain", - "pdf-parse" + "hnswlib-node" ] } diff --git a/extensions/assistant-extension/rollup.config.ts b/extensions/assistant-extension/rollup.config.ts index 7916ef9c8..1e3c38fab 100644 --- a/extensions/assistant-extension/rollup.config.ts +++ b/extensions/assistant-extension/rollup.config.ts @@ -48,9 +48,6 @@ export default [ // Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash') external: [ "@janhq/core/node", - "@langchain/community", - "langchain", - "langsmith", "path", "hnswlib-node", ], diff --git a/extensions/conversational-extension/package.json b/extensions/conversational-extension/package.json index b84c75d3d..8a6da14e5 100644 --- a/extensions/conversational-extension/package.json +++ b/extensions/conversational-extension/package.json @@ -17,12 +17,12 @@ "cpx": "^1.5.0", "rimraf": "^3.0.2", "webpack": "^5.88.2", - "webpack-cli": "^5.1.4" + "webpack-cli": "^5.1.4", + "ts-loader": "^9.5.0" }, "dependencies": { "@janhq/core": "file:../../core", - "path-browserify": "^1.0.1", - "ts-loader": "^9.5.0" + "path-browserify": "^1.0.1" }, "engines": { "node": ">=18.0.0" diff --git a/extensions/inference-nitro-extension/package.json b/extensions/inference-nitro-extension/package.json index cccfbefd0..b65cf445f 100644 --- a/extensions/inference-nitro-extension/package.json +++ b/extensions/inference-nitro-extension/package.json @@ -35,12 +35,12 @@ "rollup-plugin-sourcemaps": "^0.6.3", "rollup-plugin-typescript2": "^0.36.0", "run-script-os": "^1.1.6", - "typescript": "^5.2.2" + "typescript": "^5.2.2", + "@types/os-utils": "^0.0.4", + "@rollup/plugin-replace": "^5.0.5" }, "dependencies": { "@janhq/core": "file:../../core", - "@rollup/plugin-replace": "^5.0.5", - "@types/os-utils": "^0.0.4", "fetch-retry": "^5.0.6", "path-browserify": "^1.0.1", "rxjs": "^7.8.1", diff --git a/extensions/inference-openai-extension/package.json b/extensions/inference-openai-extension/package.json index 0ba6f18db..5efdbf874 100644 --- a/extensions/inference-openai-extension/package.json +++ b/extensions/inference-openai-extension/package.json @@ -18,13 +18,13 @@ "cpx": "^1.5.0", "rimraf": "^3.0.2", "webpack": "^5.88.2", - "webpack-cli": "^5.1.4" + "webpack-cli": "^5.1.4", + "ts-loader": "^9.5.0" }, "dependencies": { "@janhq/core": "file:../../core", "fetch-retry": "^5.0.6", "path-browserify": "^1.0.1", - "ts-loader": "^9.5.0", "ulid": "^2.3.0" }, "engines": { diff --git a/extensions/inference-triton-trtllm-extension/package.json b/extensions/inference-triton-trtllm-extension/package.json index 0f4c2de23..455f8030e 100644 --- a/extensions/inference-triton-trtllm-extension/package.json +++ b/extensions/inference-triton-trtllm-extension/package.json @@ -18,13 +18,13 @@ "cpx": "^1.5.0", "rimraf": "^3.0.2", "webpack": "^5.88.2", - "webpack-cli": "^5.1.4" + "webpack-cli": "^5.1.4", + "ts-loader": "^9.5.0" }, "dependencies": { "@janhq/core": "file:../../core", "fetch-retry": "^5.0.6", "path-browserify": "^1.0.1", - "ts-loader": "^9.5.0", "ulid": "^2.3.0", "rxjs": "^7.8.1" }, diff --git a/extensions/model-extension/package.json b/extensions/model-extension/package.json index 1af5d38cb..5d1674007 100644 --- a/extensions/model-extension/package.json +++ b/extensions/model-extension/package.json @@ -14,7 +14,8 @@ "cpx": "^1.5.0", "rimraf": "^3.0.2", "webpack": "^5.88.2", - "webpack-cli": "^5.1.4" + "webpack-cli": "^5.1.4", + "ts-loader": "^9.5.0" }, "files": [ "dist/*", @@ -23,7 +24,6 @@ ], "dependencies": { "@janhq/core": "file:../../core", - "path-browserify": "^1.0.1", - "ts-loader": "^9.5.0" + "path-browserify": "^1.0.1" } } diff --git a/extensions/monitoring-extension/package.json b/extensions/monitoring-extension/package.json index 538f6bdee..582f7cd7b 100644 --- a/extensions/monitoring-extension/package.json +++ b/extensions/monitoring-extension/package.json @@ -13,12 +13,12 @@ "devDependencies": { "rimraf": "^3.0.2", "webpack": "^5.88.2", - "webpack-cli": "^5.1.4" + "webpack-cli": "^5.1.4", + "ts-loader": "^9.5.0" }, "dependencies": { "@janhq/core": "file:../../core", - "node-os-utils": "^1.3.7", - "ts-loader": "^9.5.0" + "node-os-utils": "^1.3.7" }, "files": [ "dist/*", diff --git a/models/mistral-ins-7b-q4/cover.png b/models/mistral-ins-7b-q4/cover.png index 000445ecba38379f83ae53272899f410c40d0d0a..73b82e5996fa709762b5dc85d5ed83a3b29900ae 100644 GIT binary patch literal 234495 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