fix: correct app version display (#452)

This commit is contained in:
Louis 2023-10-26 08:59:28 +07:00 committed by GitHub
parent c0da5d0026
commit 9903b033b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 95 additions and 77 deletions

View File

@ -67,7 +67,7 @@ function requestInference(
} }
subscriber.complete(); subscriber.complete();
}) })
.catch(subscriber.error); .catch((err) => subscriber.error(err));
}); });
} }
@ -143,7 +143,8 @@ async function handleMessageRequest(data: NewMessageRequest) {
}, },
error: async (err) => { error: async (err) => {
message.message = message.message =
message.message.trim() + "\n" + "Error occurred: " + err; message.message.trim() + "\n" + "Error occurred: " + err.message;
events.emit(EventName.OnMessageResponseUpdate, message);
// TODO: Common collections should be able to access via core functions instead of store // TODO: Common collections should be able to access via core functions instead of store
await store.updateOne("messages", message._id, message); await store.updateOne("messages", message._id, message);
}, },

View File

@ -14,53 +14,49 @@ const initModel = (fileName) => {
if (!fileName) { if (!fileName) {
reject("Model not found, please download again."); reject("Model not found, please download again.");
} }
if (subprocess) {
console.error("A subprocess is already running. Attempt to kill then reinit.");
killSubprocess();
}
resolve(fileName); resolve(fileName);
}) })
// Kill port process if it is already in use
.then((fileName) =>
tcpPortUsed
.waitUntilFree(PORT, 200, 3000)
.catch(() => killPortProcess(PORT))
.then(() => fileName)
)
// Spawn Nitro subprocess to load model // Spawn Nitro subprocess to load model
.then(() => { .then(() => {
let binaryFolder = path.join(__dirname, "nitro"); // Current directory by default return tcpPortUsed.check(PORT, "127.0.0.1").then((inUse) => {
let binaryName; if (!inUse) {
let binaryFolder = path.join(__dirname, "nitro"); // Current directory by default
let binaryName;
if (process.platform === "win32") { if (process.platform === "win32") {
// Todo: Need to check for CUDA support to switch between CUDA and non-CUDA binaries // Todo: Need to check for CUDA support to switch between CUDA and non-CUDA binaries
binaryName = "nitro_start_windows.bat"; binaryName = "nitro_start_windows.bat";
} else if (process.platform === "darwin") { } else if (process.platform === "darwin") {
// Mac OS platform // Mac OS platform
binaryName = process.arch === "arm64" ? "nitro_mac_arm64" : "nitro_mac_intel"; binaryName =
} else { process.arch === "arm64"
// Linux ? "nitro_mac_arm64"
// Todo: Need to check for CUDA support to switch between CUDA and non-CUDA binaries : "nitro_mac_intel";
binaryName = "nitro_start_linux.sh"; // For other platforms } else {
} // Linux
// Todo: Need to check for CUDA support to switch between CUDA and non-CUDA binaries
binaryName = "nitro_start_linux.sh"; // For other platforms
}
const binaryPath = path.join(binaryFolder, binaryName); const binaryPath = path.join(binaryFolder, binaryName);
// Execute the binary // Execute the binary
subprocess = spawn(binaryPath, { cwd: binaryFolder }); subprocess = spawn(binaryPath, { cwd: binaryFolder });
// Handle subprocess output // Handle subprocess output
subprocess.stdout.on("data", (data) => { subprocess.stdout.on("data", (data) => {
console.log(`stdout: ${data}`); console.log(`stdout: ${data}`);
}); });
subprocess.stderr.on("data", (data) => { subprocess.stderr.on("data", (data) => {
console.error(`stderr: ${data}`); console.error(`stderr: ${data}`);
}); });
subprocess.on("close", (code) => { subprocess.on("close", (code) => {
console.log(`child process exited with code ${code}`); console.log(`child process exited with code ${code}`);
subprocess = null; subprocess = null;
});
}
}); });
}) })
.then(() => tcpPortUsed.waitUntilUsed(PORT, 300, 30000)) .then(() => tcpPortUsed.waitUntilUsed(PORT, 300, 30000))

View File

@ -14,7 +14,7 @@ const ConversationalList: React.FC<Props> = ({ models }) => (
</span> </span>
</div> </div>
<div className="scroll mt-2 flex w-full gap-2 overflow-hidden overflow-x-scroll pl-6"> <div className="scroll mt-2 flex w-full gap-2 overflow-hidden overflow-x-scroll pl-6">
{models.map((item) => ( {models?.map((item) => (
<ConversationalCard key={item._id} model={item} /> <ConversationalCard key={item._id} model={item} />
))} ))}
</div> </div>

View File

@ -13,15 +13,14 @@ import DraggableProgressBar from '../DraggableProgressBar'
import { useSetAtom } from 'jotai' import { useSetAtom } from 'jotai'
import { activeBotAtom } from '@helpers/atoms/Bot.atom' import { activeBotAtom } from '@helpers/atoms/Bot.atom'
import { import {
leftSideBarExpandStateAtom,
rightSideBarExpandStateAtom, rightSideBarExpandStateAtom,
} from '@helpers/atoms/SideBarExpand.atom' } from '@helpers/atoms/SideBarExpand.atom'
import { import {
MainViewState, MainViewState,
setMainViewStateAtom, setMainViewStateAtom,
} from '@helpers/atoms/MainView.atom' } from '@helpers/atoms/MainView.atom'
import { executeSerial } from '../../../../electron/core/plugin-manager/execution/extension-manager'
import { DataService } from '@janhq/core' import { DataService } from '@janhq/core'
import { executeSerial } from '@services/pluginService'
const CreateBotContainer: React.FC = () => { const CreateBotContainer: React.FC = () => {
const { downloadedModels } = useGetDownloadedModels() const { downloadedModels } = useGetDownloadedModels()

View File

@ -1,7 +1,6 @@
import React from 'react' import React from 'react'
import { useAtomValue, useSetAtom } from 'jotai' import { useAtomValue, useSetAtom } from 'jotai'
import { ModelManagementService } from '@janhq/core' import { ModelManagementService } from '@janhq/core'
import { executeSerial } from '../../../../electron/core/plugin-manager/execution/extension-manager'
import { import {
getActiveConvoIdAtom, getActiveConvoIdAtom,
setActiveConvoIdAtom, setActiveConvoIdAtom,
@ -13,6 +12,7 @@ import {
} from '@helpers/atoms/MainView.atom' } from '@helpers/atoms/MainView.atom'
import { displayDate } from '@utils/datetime' import { displayDate } from '@utils/datetime'
import { twMerge } from 'tailwind-merge' import { twMerge } from 'tailwind-merge'
import { executeSerial } from '@services/pluginService'
type Props = { type Props = {
conversation: Conversation conversation: Conversation

View File

@ -59,7 +59,7 @@ const LeftRibbonNav: React.FC = () => {
const onBotListClick = async () => { const onBotListClick = async () => {
const bots = await getAllBots() const bots = await getAllBots()
if (bots.length === 0) { if (bots?.length === 0) {
alert('You have no bot') alert('You have no bot')
return return
} }

View File

@ -20,7 +20,7 @@ const ModelTable: React.FC<Props> = ({ models }) => (
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{models.map((model) => ( {models?.map((model) => (
<ModelRow key={model._id} model={model} /> <ModelRow key={model._id} model={model} />
))} ))}
</tbody> </tbody>

View File

@ -5,12 +5,14 @@ import { useAtomValue } from 'jotai'
import { modelDownloadStateAtom } from '@helpers/atoms/DownloadState.atom' import { modelDownloadStateAtom } from '@helpers/atoms/DownloadState.atom'
import { formatDownloadPercentage } from '@utils/converter' import { formatDownloadPercentage } from '@utils/converter'
import { activeAssistantModelAtom, stateModel } from '@helpers/atoms/Model.atom' import { activeAssistantModelAtom, stateModel } from '@helpers/atoms/Model.atom'
import useGetAppVersion from '@hooks/useGetAppVersion'
const BottomBar = () => { const BottomBar = () => {
const activeModel = useAtomValue(activeAssistantModelAtom) const activeModel = useAtomValue(activeAssistantModelAtom)
const stateModelStartStop = useAtomValue(stateModel) const stateModelStartStop = useAtomValue(stateModel)
const { ram, cpu } = useGetSystemResources() const { ram, cpu } = useGetSystemResources()
const modelDownloadStates = useAtomValue(modelDownloadStateAtom) const modelDownloadStates = useAtomValue(modelDownloadStateAtom)
const appVersion = useGetAppVersion()
const downloadStates: DownloadState[] = [] const downloadStates: DownloadState[] = []
for (const [, value] of Object.entries(modelDownloadStates)) { for (const [, value] of Object.entries(modelDownloadStates)) {
@ -51,7 +53,7 @@ const BottomBar = () => {
<div className="flex gap-x-2"> <div className="flex gap-x-2">
<SystemItem name="CPU:" value={`${cpu}%`} /> <SystemItem name="CPU:" value={`${cpu}%`} />
<SystemItem name="Mem:" value={`${ram}%`} /> <SystemItem name="Mem:" value={`${ram}%`} />
<p className="text-xs font-semibold">Jan v0.2.0</p> <p className="text-xs font-semibold">Jan {appVersion?.version ?? ''}</p>
</div> </div>
</div> </div>
) )

View File

@ -13,13 +13,9 @@ import {
activationPoints, activationPoints,
extensionPoints, extensionPoints,
} from '../../../electron/core/plugin-manager/execution/index' } from '../../../electron/core/plugin-manager/execution/index'
import {
isCorePluginInstalled,
setupBasePlugins,
} from '@services/pluginService'
import EventListenerWrapper from '@helpers/EventListenerWrapper' import EventListenerWrapper from '@helpers/EventListenerWrapper'
import { setupCoreServices } from '@services/coreService' import { setupCoreServices } from '@services/coreService'
import { executeSerial } from '../../../electron/core/plugin-manager/execution/extension-manager' import { executeSerial, isCorePluginInstalled, setupBasePlugins } from '@services/pluginService'
const Providers = (props: PropsWithChildren) => { const Providers = (props: PropsWithChildren) => {
const [setupCore, setSetupCore] = useState(false) const [setupCore, setSetupCore] = useState(false)

View File

@ -36,8 +36,8 @@ export const SidebarLeft = () => {
const onBotListClick = async () => { const onBotListClick = async () => {
const bots = await getAllBots() const bots = await getAllBots()
if (bots.length === 0) { if (!bots || bots?.length === 0) {
alert('You have no bot') alert('You have not created any bot')
return return
} }

View File

@ -3,7 +3,6 @@
import { useSetAtom } from 'jotai' import { useSetAtom } from 'jotai'
import { ReactNode, useEffect } from 'react' import { ReactNode, useEffect } from 'react'
import { appDownloadProgress } from './JotaiWrapper' import { appDownloadProgress } from './JotaiWrapper'
import { executeSerial } from '../../electron/core/plugin-manager/execution/extension-manager'
import { ModelManagementService } from '@janhq/core' import { ModelManagementService } from '@janhq/core'
import { import {
setDownloadStateAtom, setDownloadStateAtom,
@ -12,6 +11,7 @@ import {
import { getDownloadedModels } from '../hooks/useGetDownloadedModels' import { getDownloadedModels } from '../hooks/useGetDownloadedModels'
import { downloadedModelAtom } from './atoms/DownloadedModel.atom' import { downloadedModelAtom } from './atoms/DownloadedModel.atom'
import EventHandler from './EventHandler' import EventHandler from './EventHandler'
import { executeSerial } from '@services/pluginService'
type Props = { type Props = {
children: ReactNode children: ReactNode

View File

@ -1,9 +1,10 @@
import { executeSerial } from '../../electron/core/plugin-manager/execution/extension-manager' import { DataService } from '@janhq/core'
import { executeSerial } from '@services/pluginService'
export default function useCreateBot() { export default function useCreateBot() {
const createBot = async (bot: Bot) => { const createBot = async (bot: Bot) => {
try { try {
await executeSerial('createBot', bot) await executeSerial(DataService.CreateBot, bot)
} catch (err) { } catch (err) {
alert(err) alert(err)
console.error(err) console.error(err)

View File

@ -1,7 +1,8 @@
import { useSetAtom } from 'jotai' import { useSetAtom } from 'jotai'
import { executeSerial } from '../../electron/core/plugin-manager/execution/extension-manager'
import { activeBotAtom } from '@helpers/atoms/Bot.atom' import { activeBotAtom } from '@helpers/atoms/Bot.atom'
import { rightSideBarExpandStateAtom } from '@helpers/atoms/SideBarExpand.atom' import { rightSideBarExpandStateAtom } from '@helpers/atoms/SideBarExpand.atom'
import { executeSerial } from '@services/pluginService'
import { DataService } from '@janhq/core'
export default function useDeleteBot() { export default function useDeleteBot() {
const setActiveBot = useSetAtom(activeBotAtom) const setActiveBot = useSetAtom(activeBotAtom)
@ -9,7 +10,7 @@ export default function useDeleteBot() {
const deleteBot = async (botId: string): Promise<'success' | 'failed'> => { const deleteBot = async (botId: string): Promise<'success' | 'failed'> => {
try { try {
await executeSerial('deleteBot', botId) await executeSerial(DataService.DeleteBot, botId)
setRightPanelVisibility(false) setRightPanelVisibility(false)
setActiveBot(undefined) setActiveBot(undefined)
return 'success' return 'success'

View File

@ -8,7 +8,7 @@ export default function useGetAppVersion() {
}, []) }, [])
const getAppVersion = () => { const getAppVersion = () => {
window.electronAPI.appVersion().then((version: string | undefined) => { window.coreAPI?.appVersion().then((version: string | undefined) => {
setVersion(version ?? '') setVersion(version ?? '')
}) })
} }

View File

@ -1,9 +1,10 @@
import { executeSerial } from '../../electron/core/plugin-manager/execution/extension-manager' import { DataService } from '@janhq/core'
import { executeSerial } from '@services/pluginService'
export default function useGetBots() { export default function useGetBots() {
const getAllBots = async (): Promise<Bot[]> => { const getAllBots = async (): Promise<Bot[]> => {
try { try {
const bots = await executeSerial('getBots') const bots = await executeSerial(DataService.GetBots)
return bots return bots
} catch (err) { } catch (err) {
alert(`Failed to get bots: ${err}`) alert(`Failed to get bots: ${err}`)
@ -14,7 +15,7 @@ export default function useGetBots() {
const getBotById = async (botId: string): Promise<Bot | undefined> => { const getBotById = async (botId: string): Promise<Bot | undefined> => {
try { try {
const bot: Bot = await executeSerial('getBotById', botId) const bot: Bot = await executeSerial(DataService.GetBotById, botId)
return bot return bot
} catch (err) { } catch (err) {
alert(`Failed to get bot ${botId}: ${err}`) alert(`Failed to get bot ${botId}: ${err}`)

View File

@ -1,8 +1,9 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import { executeSerial } from '../../electron/core/plugin-manager/execution/extension-manager'
import { ModelManagementService } from '@janhq/core' import { ModelManagementService } from '@janhq/core'
import { useAtom } from 'jotai' import { useAtom } from 'jotai'
import { downloadedModelAtom } from '@helpers/atoms/DownloadedModel.atom' import { downloadedModelAtom } from '@helpers/atoms/DownloadedModel.atom'
import { extensionPoints } from '../../electron/core/plugin-manager/execution'
import { executeSerial } from '@services/pluginService'
export function useGetDownloadedModels() { export function useGetDownloadedModels() {
const [downloadedModels, setDownloadedModels] = useAtom(downloadedModelAtom) const [downloadedModels, setDownloadedModels] = useAtom(downloadedModelAtom)
@ -17,6 +18,9 @@ export function useGetDownloadedModels() {
} }
export async function getDownloadedModels(): Promise<AssistantModel[]> { export async function getDownloadedModels(): Promise<AssistantModel[]> {
if (!extensionPoints.get(ModelManagementService.GetFinishedDownloadModels)) {
return []
}
const downloadedModels: AssistantModel[] = await executeSerial( const downloadedModels: AssistantModel[] = await executeSerial(
ModelManagementService.GetFinishedDownloadModels ModelManagementService.GetFinishedDownloadModels
) )

View File

@ -1,9 +1,9 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { executeSerial } from '../../electron/core/plugin-manager/execution/extension-manager'
import { extensionPoints } from '../../electron/core/plugin-manager/execution' import { extensionPoints } from '../../electron/core/plugin-manager/execution'
import { SystemMonitoringService } from '@janhq/core' import { SystemMonitoringService } from '@janhq/core'
import { useSetAtom } from 'jotai' import { useSetAtom } from 'jotai'
import { totalRamAtom } from '@helpers/atoms/SystemBar.atom' import { totalRamAtom } from '@helpers/atoms/SystemBar.atom'
import { executeSerial } from '@services/pluginService'
export default function useGetSystemResources() { export default function useGetSystemResources() {
const [ram, setRam] = useState<number>(0) const [ram, setRam] = useState<number>(0)
const [cpu, setCPU] = useState<number>(0) const [cpu, setCPU] = useState<number>(0)

View File

@ -1,4 +1,5 @@
import { executeSerial } from '../../electron/core/plugin-manager/execution/extension-manager' import { DataService } from '@janhq/core'
import { executeSerial } from '@services/pluginService'
export default function useUpdateBot() { export default function useUpdateBot() {
const updateBot = async ( const updateBot = async (
@ -15,7 +16,7 @@ export default function useUpdateBot() {
} }
} }
await executeSerial('updateBot', bot) await executeSerial(DataService.UpdateBot, bot)
console.debug('Bot updated', JSON.stringify(bot, null, 2)) console.debug('Bot updated', JSON.stringify(bot, null, 2))
} catch (err) { } catch (err) {
alert(`Update bot error: ${err}`) alert(`Update bot error: ${err}`)

View File

@ -21,7 +21,14 @@ const nextConfig = {
// do some stuff here // do some stuff here
config.optimization.minimize = false config.optimization.minimize = false
config.optimization.minimizer = [] config.optimization.minimizer = []
config.plugins = [...config.plugins, new webpack.DefinePlugin({})] config.plugins = [
...config.plugins,
new webpack.DefinePlugin({
PLUGIN_CATALOG: JSON.stringify(
'https://cdn.jsdelivr.net/npm/@janhq/plugin-catalog@latest/dist/index.js'
),
}),
]
return config return config
}, },
} }

View File

@ -12,7 +12,7 @@ const ExploreModelList: React.FC = () => {
return ( return (
<div className="relative h-full w-full flex-shrink-0"> <div className="relative h-full w-full flex-shrink-0">
{models.map((item) => ( {models?.map((item) => (
<ExploreModelItem key={item._id} model={item} /> <ExploreModelItem key={item._id} model={item} />
))} ))}
</div> </div>

View File

@ -25,9 +25,17 @@ const PluginCatalog = () => {
* Loads the plugin catalog module from a CDN and sets it as the plugin catalog state. * Loads the plugin catalog module from a CDN and sets it as the plugin catalog state.
*/ */
useEffect(() => { useEffect(() => {
executeSerial(DataService.GetPluginManifest).then((data) => { // Load plugin manifest from plugin if any
setPluginCatalog(data) if (extensionPoints.get(DataService.GetPluginManifest)) {
}) executeSerial(DataService.GetPluginManifest).then((data) => {
setPluginCatalog(data)
})
} else {
// Fallback to app default manifest
import(
/* webpackIgnore: true */ PLUGIN_CATALOG + `?t=${Date.now()}`
).then((data) => setPluginCatalog(data.default))
}
}, []) }, [])
/** /**

View File

@ -1,4 +1,4 @@
import React, { Children } from 'react' import React from 'react'
import { execute } from '../../../../../electron/core/plugin-manager/execution/extension-manager' import { execute } from '../../../../../electron/core/plugin-manager/execution/extension-manager'
type Props = { type Props = {

View File

@ -8,10 +8,11 @@ import {
DataService, DataService,
InferenceService, InferenceService,
ModelManagementService, ModelManagementService,
StoreService,
} from '@janhq/core' } from '@janhq/core'
export const isCorePluginInstalled = () => { export const isCorePluginInstalled = () => {
if (!extensionPoints.get(DataService.GetConversations)) { if (!extensionPoints.get(StoreService.CreateCollection)) {
return false return false
} }
if (!extensionPoints.get(InferenceService.InitModel)) { if (!extensionPoints.get(InferenceService.InitModel)) {
@ -32,7 +33,7 @@ export const setupBasePlugins = async () => {
const basePlugins = await window.electronAPI.basePlugins() const basePlugins = await window.electronAPI.basePlugins()
if ( if (
!extensionPoints.get(DataService.GetConversations) || !extensionPoints.get(StoreService.CreateCollection) ||
!extensionPoints.get(InferenceService.InitModel) || !extensionPoints.get(InferenceService.InitModel) ||
!extensionPoints.get(ModelManagementService.DownloadModel) !extensionPoints.get(ModelManagementService.DownloadModel)
) { ) {
@ -45,7 +46,7 @@ export const setupBasePlugins = async () => {
export const execute = (name: CoreService, args?: any) => { export const execute = (name: CoreService, args?: any) => {
if (!extensionPoints.get(name)) { if (!extensionPoints.get(name)) {
alert('Missing extension for function: ' + name) // alert('Missing extension for function: ' + name)
return undefined return undefined
} }
return extensionPoints.execute(name, args) return extensionPoints.execute(name, args)
@ -53,7 +54,7 @@ export const execute = (name: CoreService, args?: any) => {
export const executeSerial = (name: CoreService, args?: any) => { export const executeSerial = (name: CoreService, args?: any) => {
if (!extensionPoints.get(name)) { if (!extensionPoints.get(name)) {
alert('Missing extension for function: ' + name) // alert('Missing extension for function: ' + name)
return Promise.resolve(undefined) return Promise.resolve(undefined)
} }
return extensionPoints.executeSerial(name, args) return extensionPoints.executeSerial(name, args)

View File

@ -1,7 +1,7 @@
export {} export {}
declare const PLUGIN_CATALOGS: string[]
declare global { declare global {
declare const PLUGIN_CATALOG: string
interface Window { interface Window {
electronAPI?: any | undefined electronAPI?: any | undefined
corePlugin?: any | undefined corePlugin?: any | undefined