import { Fragment, useCallback, useState } from 'react' import { EngineManager, InferenceEngine, Model, ModelSettingParams, } from '@janhq/core' import { Button, Tooltip, Select, Input, Checkbox } from '@janhq/joi' import { useAtom, useAtomValue, useSetAtom } from 'jotai' import { ExternalLinkIcon, InfoIcon } from 'lucide-react' import { twMerge } from 'tailwind-merge' import LeftPanelContainer from '@/containers/LeftPanelContainer' import { toaster } from '@/containers/Toast' import { useActiveModel, loadModelErrorAtom } from '@/hooks/useActiveModel' import { apiServerCorsEnabledAtom, apiServerHostAtom, apiServerPortAtom, apiServerPrefix, apiServerVerboseLogEnabledAtom, hostOptions, } from '@/helpers/atoms/ApiServer.atom' import { LocalAPIserverModelParamsAtom, serverEnabledAtom, } from '@/helpers/atoms/LocalServer.atom' import { selectedModelAtom } from '@/helpers/atoms/Model.atom' const LocalServerLeftPanel = () => { const [errorRangePort, setErrorRangePort] = useState(false) const [errorPrefix, setErrorPrefix] = useState(false) const [serverEnabled, setServerEnabled] = useAtom(serverEnabledAtom) const [isLoading, setIsLoading] = useState(false) const { stateModel } = useActiveModel() const selectedModel = useAtomValue(selectedModelAtom) const [isCorsEnabled, setIsCorsEnabled] = useAtom(apiServerCorsEnabledAtom) const [isVerboseEnabled, setIsVerboseEnabled] = useAtom( apiServerVerboseLogEnabledAtom ) const [host, setHost] = useAtom(apiServerHostAtom) const [port, setPort] = useAtom(apiServerPortAtom) const [prefix, setPrefix] = useAtom(apiServerPrefix) const setLoadModelError = useSetAtom(loadModelErrorAtom) const localAPIserverModelParams = useAtomValue(LocalAPIserverModelParamsAtom) const FIRST_TIME_VISIT_API_SERVER = 'firstTimeVisitAPIServer' const model: Model | undefined = selectedModel ? { ...selectedModel, object: selectedModel.object || '', settings: (typeof localAPIserverModelParams === 'object' ? { ...(localAPIserverModelParams as ModelSettingParams) } : { ...selectedModel.settings }) as ModelSettingParams, } : undefined const [firstTimeVisitAPIServer, setFirstTimeVisitAPIServer] = useState(false) const handleChangePort = useCallback( (value: string) => { setErrorRangePort(Number(value) <= 0 || Number(value) >= 65536) setPort(value) }, [setPort] ) const handleChangePrefix = useCallback( (value: string) => { setErrorPrefix(!value.length || !value.startsWith('/')) setPrefix(value) }, [setPrefix] ) const onStartServerClick = async () => { if (selectedModel == null) return try { setIsLoading(true) const isStarted = await window.core?.api?.startServer({ host, port: parseInt(port), prefix, isCorsEnabled, isVerboseEnabled, }) if (isStarted) setServerEnabled(true) if (firstTimeVisitAPIServer) { localStorage.setItem(FIRST_TIME_VISIT_API_SERVER, 'false') setFirstTimeVisitAPIServer(false) } const engine = EngineManager.instance().get(InferenceEngine.cortex) engine?.loadModel(model as Model) // startModel(selectedModel.id, false).catch((e) => console.error(e)) setIsLoading(false) } catch (e) { console.error(e) setIsLoading(false) toaster({ title: `Failed to start server!`, description: 'Please check Server Logs for more details.', type: 'error', }) } } const onStopServerClick = async () => { window.core?.api?.stopServer() setServerEnabled(false) setLoadModelError(undefined) setIsLoading(false) } const onToggleServer = async () => { if (serverEnabled) { await onStopServerClick() } else { await onStartServerClick() } } return (

Start an OpenAI-compatible local HTTP server.

{serverEnabled && ( )}

Server Options

{ handleChangePort(e.target.value) }} maxLength={5} disabled={serverEnabled} />
{errorRangePort && (

{`The port range should be from 0 to 65536`}

)}
{ handleChangePrefix(e.target.value) }} disabled={serverEnabled} />
{errorPrefix && (

{`Prefix should start with /`}

)}
Cross-Origin-Resource-Sharing (CORS) } content="CORS (Cross-Origin Resource Sharing) manages resource access on this server from external domains. Enable for secure inter-website communication, regulating data sharing to bolster overall security." />
} checked={isCorsEnabled} onChange={(e) => setIsCorsEnabled(e.target.checked)} name="cors" disabled={serverEnabled} />
Verbose Server Logs } content="Verbose Server Logs provide extensive details about server activities. Enable to capture thorough records, aiding in troubleshooting and monitoring server performance effectively." />
} checked={isVerboseEnabled} onChange={(e) => setIsVerboseEnabled(e.target.checked)} name="verbose" disabled={serverEnabled} />
) } export default LocalServerLeftPanel