/* eslint-disable @typescript-eslint/no-explicit-any */
import React, { useCallback, useEffect, useState } from 'react'
import { InferenceEngine } from '@janhq/core'
import { Button, ScrollArea, Input, Switch, Badge } from '@janhq/joi'
import { useAtom, useSetAtom } from 'jotai'
import { SearchIcon, SettingsIcon } from 'lucide-react'
import { marked } from 'marked'
import SetupRemoteModel from '@/containers/SetupRemoteModel'
import {
useGetDefaultEngineVariant,
useGetEngines,
} from '@/hooks/useEngineManagement'
import { formatExtensionsName } from '@/utils/converter'
import { extensionManager } from '@/extension'
import Extension from '@/extension/Extension'
import {
inActiveEngineProviderAtom,
showSettingActiveLocalEngineAtom,
} from '@/helpers/atoms/Extension.atom'
import { selectedSettingAtom } from '@/helpers/atoms/Setting.atom'
type EngineExtension = {
provider: InferenceEngine
} & Extension
const EngineItems = ({ engine }: { engine: InferenceEngine }) => {
const { defaultEngineVariant } = useGetDefaultEngineVariant(engine)
const manualDescription = (engine: string) => {
switch (engine) {
case InferenceEngine.cortex_llamacpp:
return 'Fast, efficient local inference engine that runs GGUFmodels directly on your device'
default:
break
}
}
const setSelectedSetting = useSetAtom(selectedSettingAtom)
const [showSettingActiveLocalEngine, setShowSettingActiveLocalEngineAtom] =
useAtom(showSettingActiveLocalEngineAtom)
const onSwitchChange = useCallback(
(name: string) => {
if (showSettingActiveLocalEngine.includes(name)) {
setShowSettingActiveLocalEngineAtom(
[...showSettingActiveLocalEngine].filter((x) => x !== name)
)
} else {
setShowSettingActiveLocalEngineAtom([
...showSettingActiveLocalEngine,
name,
])
}
},
[showSettingActiveLocalEngine, setShowSettingActiveLocalEngineAtom]
)
return (
{engine}
{defaultEngineVariant?.version}
{manualDescription(engine)}
onSwitchChange(engine)}
/>
)
}
const Engines = () => {
const [searchText, setSearchText] = useState('')
const { engines } = useGetEngines()
const [engineActiveExtensions, setEngineActiveExtensions] = useState<
EngineExtension[]
>([])
const [inActiveEngineProvider, setInActiveEngineProvider] = useAtom(
inActiveEngineProviderAtom
)
useEffect(() => {
const getAllSettings = async () => {
const extensionsMenu = []
const engineMenu = []
const extensions = extensionManager.getAll()
for (const extension of extensions) {
const settings = await extension.getSettings()
if (
typeof extension.getSettings === 'function' &&
'provider' in extension &&
typeof extension.provider === 'string'
) {
if (
(settings && settings.length > 0) ||
(await extension.installationState()) !== 'NotRequired'
) {
engineMenu.push({
...extension,
provider:
'provider' in extension &&
typeof extension.provider === 'string'
? extension.provider
: '',
})
}
} else {
extensionsMenu.push({
...extension,
})
}
}
setEngineActiveExtensions(engineMenu as any)
}
getAllSettings()
}, [])
const onSwitchChange = useCallback(
(name: string) => {
if (inActiveEngineProvider.includes(name)) {
setInActiveEngineProvider(
[...inActiveEngineProvider].filter((x) => x !== name)
)
} else {
setInActiveEngineProvider([...inActiveEngineProvider, name])
}
},
[inActiveEngineProvider, setInActiveEngineProvider]
)
return (
Local Engine
{engines &&
Object.entries(engines)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.filter(([_, value]) => !(value as { type?: string }).type)
.map(([key]) => {
return
})}
{engineActiveExtensions.length !== 0 && (
Remote Engine
{engineActiveExtensions
.filter((x) => x.name.includes(searchText.toLowerCase().trim()))
.sort((a, b) => a.provider.localeCompare(b.provider))
.map((item, i) => {
return (
{item.productName?.replace(
'Inference Engine',
''
) ?? formatExtensionsName(item.name)}
v{item.version}
{item.provider}
onSwitchChange(item.provider)}
/>
{!inActiveEngineProvider.includes(item.provider) && (
)}
{
}
)
})}
)}
)
}
export default Engines