* fix: update new api from cortex to support 0.5.0 Signed-off-by: James <namnh0122@gmail.com> * fix stop button for streaming Signed-off-by: James <namnh0122@gmail.com> * fix stop inference for nonstreaming Signed-off-by: James <namnh0122@gmail.com> * chore: remove umami prevent tracking call to vercel Signed-off-by: James <namnh0122@gmail.com> * add warning modal when running more than 2 model concurrently Signed-off-by: James <namnh0122@gmail.com> * fix: skip summarize if abort Signed-off-by: James <namnh0122@gmail.com> * 0.5.0-3 * add inference error popup Signed-off-by: James <namnh0122@gmail.com> * add back import local model Signed-off-by: James <namnh0122@gmail.com> * fix: max token issue (#3225) Signed-off-by: James <namnh0122@gmail.com> * format status Signed-off-by: James <namnh0122@gmail.com> * fix migration missing instructions Signed-off-by: James <namnh0122@gmail.com> * fix: wait for cortex process overlay should be on top (#3224) * fix: wait for cortex process overlay should be on top * chore: update cortex.js * Cortex 0.5.0-5 * add import model to my model screen Signed-off-by: James <namnh0122@gmail.com> * fix: should migrate symlink models (#3226) * fix import on windows (#3229) Signed-off-by: James <namnh0122@gmail.com> * fix yarn lint Signed-off-by: James <namnh0122@gmail.com> * fix: clean up port before start jan (#3232) Signed-off-by: James <namnh0122@gmail.com> --------- Signed-off-by: James <namnh0122@gmail.com> Co-authored-by: Van Pham <64197333+Van-QA@users.noreply.github.com> Co-authored-by: Louis <louis@jan.ai>
119 lines
3.8 KiB
TypeScript
119 lines
3.8 KiB
TypeScript
import { Fragment, useCallback, useEffect, useState } from 'react'
|
|
|
|
import Image from 'next/image'
|
|
|
|
import { Button, Input, Modal } from '@janhq/joi'
|
|
import { useAtom, useSetAtom } from 'jotai'
|
|
import { ArrowUpRight } from 'lucide-react'
|
|
|
|
import useEngineMutation from '@/hooks/useEngineMutation'
|
|
import useEngineQuery from '@/hooks/useEngineQuery'
|
|
|
|
import { getTitleByCategory } from '@/utils/model-engine'
|
|
|
|
import { isAnyRemoteModelConfiguredAtom } from '@/helpers/atoms/SetupRemoteModel.atom'
|
|
|
|
import { setUpRemoteModelStageAtom } from '@/helpers/atoms/SetupRemoteModel.atom'
|
|
|
|
const SetUpApiKeyModal: React.FC = () => {
|
|
const updateEngineConfig = useEngineMutation()
|
|
const isAnyRemoteModelConfigured = useSetAtom(isAnyRemoteModelConfiguredAtom)
|
|
const { data: engineData } = useEngineQuery()
|
|
|
|
const [{ stage, remoteEngine, metadata }, setUpRemoteModelStage] = useAtom(
|
|
setUpRemoteModelStageAtom
|
|
)
|
|
const [apiKey, setApiKey] = useState<string>('')
|
|
|
|
useEffect(() => {
|
|
if (!remoteEngine || !engineData) return
|
|
const isEngineReady =
|
|
engineData.find((e) => e.name === remoteEngine)?.status === 'ready'
|
|
const fakeApiKey = '******************************************'
|
|
setApiKey(isEngineReady ? fakeApiKey : '')
|
|
}, [remoteEngine, engineData])
|
|
|
|
const onSaveClicked = useCallback(async () => {
|
|
if (!remoteEngine) {
|
|
alert('Does not have engine')
|
|
return
|
|
}
|
|
const normalizedApiKey = apiKey.trim().replaceAll('*', '')
|
|
if (normalizedApiKey.length === 0) return
|
|
|
|
updateEngineConfig.mutate({
|
|
engine: remoteEngine,
|
|
config: {
|
|
config: 'apiKey',
|
|
value: apiKey,
|
|
},
|
|
})
|
|
isAnyRemoteModelConfigured(true)
|
|
}, [remoteEngine, updateEngineConfig, apiKey, isAnyRemoteModelConfigured])
|
|
|
|
const onDismiss = useCallback(() => {
|
|
setUpRemoteModelStage('NONE', undefined)
|
|
}, [setUpRemoteModelStage])
|
|
|
|
if (remoteEngine == null) return null
|
|
const owner: string = getTitleByCategory(remoteEngine)
|
|
const logoUrl: string = (metadata?.logo ?? '') as string
|
|
const apiKeyUrl: string | undefined = (metadata?.api_key_url ?? '') as
|
|
| string
|
|
| undefined
|
|
|
|
return (
|
|
<Modal
|
|
data-testid="setup-api-key-modal"
|
|
onOpenChange={onDismiss}
|
|
open={stage === 'SETUP_API_KEY'}
|
|
content={
|
|
<Fragment>
|
|
<div className="my-4 flex items-center gap-2 text-black">
|
|
{logoUrl && (
|
|
<Image width={24} height={24} src={logoUrl} alt="Model owner" />
|
|
)}
|
|
<h1 className="text-lg font-semibold leading-7 text-[hsla(var(--text-primary))]">
|
|
{owner}
|
|
</h1>
|
|
</div>
|
|
|
|
<div className="mb-3 text-sm font-medium leading-4">API Key</div>
|
|
|
|
<Input
|
|
placeholder="Input API Key"
|
|
type="text"
|
|
value={apiKey}
|
|
onChange={(e) => setApiKey(e.target.value)}
|
|
/>
|
|
|
|
{apiKeyUrl && (
|
|
<span className="mt-3 flex items-center justify-start gap-1 text-xs font-medium leading-3 text-blue-600">
|
|
<a
|
|
href={apiKeyUrl}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="relative flex no-underline hover:underline"
|
|
>
|
|
Get your API key from {owner} <ArrowUpRight size={12} />
|
|
</a>
|
|
</span>
|
|
)}
|
|
|
|
<span className="my-4 flex items-center gap-1 text-xs text-blue-500"></span>
|
|
<div className="flex items-center justify-end gap-3">
|
|
<Button theme="ghost" variant="outline" onClick={onDismiss}>
|
|
Cancel
|
|
</Button>
|
|
<Button disabled={apiKey.length === 0} onClick={onSaveClicked}>
|
|
Save
|
|
</Button>
|
|
</div>
|
|
</Fragment>
|
|
}
|
|
/>
|
|
)
|
|
}
|
|
|
|
export default SetUpApiKeyModal
|