diff --git a/web/containers/Layout/TopPanel/index.tsx b/web/containers/Layout/TopPanel/index.tsx index 7f3be082d..bed3ea604 100644 --- a/web/containers/Layout/TopPanel/index.tsx +++ b/web/containers/Layout/TopPanel/index.tsx @@ -1,4 +1,4 @@ -import { Fragment } from 'react' +import { Fragment, useCallback, useEffect } from 'react' import { Button } from '@janhq/joi' import { useAtom, useAtomValue, useSetAtom } from 'jotai' @@ -12,22 +12,35 @@ import { SquareIcon, PaletteIcon, XIcon, + PenSquareIcon, } from 'lucide-react' import { twMerge } from 'tailwind-merge' import LogoMark from '@/containers/Brand/Logo/Mark' +import { toaster } from '@/containers/Toast' + +import useAssistantQuery from '@/hooks/useAssistantQuery' +import useThreadCreateMutation from '@/hooks/useThreadCreateMutation' +import useThreads from '@/hooks/useThreads' + +import { copyOverInstructionEnabledAtom } from '@/screens/Thread/ThreadRightPanel/AssistantSettingContainer/components/CopyOverInstruction' + import { MainViewState, mainViewStateAtom, showLeftPanelAtom, showRightPanelAtom, } from '@/helpers/atoms/App.atom' -import { downloadedModelsAtom } from '@/helpers/atoms/Model.atom' +import { + downloadedModelsAtom, + getSelectedModelAtom, +} from '@/helpers/atoms/Model.atom' import { reduceTransparentAtom, selectedSettingAtom, } from '@/helpers/atoms/Setting.atom' +import { threadsAtom, activeThreadAtom } from '@/helpers/atoms/Thread.atom' const TopPanel = () => { const [showLeftPanel, setShowLeftPanel] = useAtom(showLeftPanelAtom) @@ -37,6 +50,51 @@ const TopPanel = () => { const reduceTransparent = useAtomValue(reduceTransparentAtom) const downloadedModels = useAtomValue(downloadedModelsAtom) + const { setActiveThread } = useThreads() + const createThreadMutation = useThreadCreateMutation() + + const selectedModel = useAtomValue(getSelectedModelAtom) + const threads = useAtomValue(threadsAtom) + + const activeThread = useAtomValue(activeThreadAtom) + const { data: assistants } = useAssistantQuery() + const copyOverInstructionEnabled = useAtomValue( + copyOverInstructionEnabledAtom + ) + + useEffect(() => { + if (activeThread?.id) return + if (threads.length === 0) return + setActiveThread(threads[0].id) + }, [activeThread?.id, setActiveThread, threads]) + + const onCreateThreadClicked = useCallback(async () => { + if (!assistants || assistants.length) { + toaster({ + title: 'No assistant available.', + description: `Could not create a new thread. Please add an assistant.`, + type: 'error', + }) + return + } + if (!selectedModel) return + let instructions: string | undefined = undefined + if (copyOverInstructionEnabled) { + instructions = activeThread?.assistants[0]?.instructions ?? undefined + } + await createThreadMutation.mutateAsync({ + modelId: selectedModel.model, + assistant: assistants[0], + instructions, + }) + }, [ + createThreadMutation, + selectedModel, + assistants, + activeThread, + copyOverInstructionEnabled, + ]) + return (