jan/web/hooks/useSendChatMessage.ts
Faisal Amir 2394c13065
ui: standalone UIKit and refactor (#557)
* Eslint import order

* Initial Uikit

* Rename file with camelCase

* Remove unused code

* Remove unused code

* Set position traficlight mac

* Grouping Ribbon, Topbar and Bottombar as layout

* Added image brand

* Moving feature toggle into context folder

* Fix active state of setting menu

* Cleanup downloadModel atom helper

* Cleanup useGetConfigureModel

* Added wave animation

* Create useMainViewState intead of import helper atom

* Remove unused code

* Take a back switch ui

* Toggle using switch component

* Add dynamic primary color

* Cleanup import

* Added uikit scroll area

* Add best practice form

* Added toaster container

* Fix loader container

* Add hooks useDownloadState

* Added tooltip on ribbon menu

* Added case user multiple download model

* Adjust input style with bigger ring

* Restyle my model screen

* Replace useStartStop model with useActiveModel

* Import icon using Icon name

* Fix missing login loading start and stop model

* WIP integrate with cmdk

* Move layout search bar on middle of app

* Added function cancel download

* Cleanup model explore

* Cleanup unused code

* Move app version in bototmbar or footer

* WIP chat screen

* WIP chat screen

* Cleanup style and remove unsed code

* Added command for showing downloaded model

* Fix missing keyframe loader dot animation

* Conditional loader of plugin setting

* WIP history list message

* chore: rebase main

* Adding script ui into root package

* Fix different version react hooks form

* Add close toaster

* Added status model active or not on list of command

* Conditional showing info if user don't have a model

* Disabled toolbar chat when user not yet have convo

* chore: fix state

* fix: get resource atom

* Fix conditional bottom bar

* fix: model download state

* Fix font

* Improve icon my model

* Add toaster delete chat

* Remove test classname

* Fix scroll chat body

* Fix scrolling chat body

* chore: add message update

* Add uikit into depedencies on root package

* Update chat flow

* Fix hot reload ui changes

* Increate background color chat screen light mode

* Added visual conversation active state

* Added build:uikit on gh actions

* chore: attempt to fix CI

* fix: deps

* fix: tests

* chore: attempt to fix CI

---------

Co-authored-by: Louis <louis@jan.ai>
2023-11-07 21:27:11 +07:00

152 lines
4.4 KiB
TypeScript

import {
EventName,
MessageHistory,
NewMessageRequest,
PluginType,
events,
} from '@janhq/core'
import { ConversationalPlugin, InferencePlugin } from '@janhq/core/lib/plugins'
import { Message } from '@janhq/core/lib/types'
import { useAtom, useAtomValue, useSetAtom } from 'jotai'
import { currentPromptAtom } from '@/containers/Providers/Jotai'
import { generateMessageId } from '@/utils/message'
import {
addNewMessageAtom,
getCurrentChatMessagesAtom,
} from '@/helpers/atoms/ChatMessage.atom'
import {
currentConversationAtom,
updateConversationAtom,
updateConversationWaitingForResponseAtom,
} from '@/helpers/atoms/Conversation.atom'
import { toChatMessage } from '@/models/ChatMessage'
import { pluginManager } from '@/plugin/PluginManager'
export default function useSendChatMessage() {
const currentConvo = useAtomValue(currentConversationAtom)
const addNewMessage = useSetAtom(addNewMessageAtom)
const updateConversation = useSetAtom(updateConversationAtom)
const updateConvWaiting = useSetAtom(updateConversationWaitingForResponseAtom)
const [currentPrompt, setCurrentPrompt] = useAtom(currentPromptAtom)
const currentMessages = useAtomValue(getCurrentChatMessagesAtom)
let timeout: NodeJS.Timeout | undefined = undefined
function updateConvSummary(newMessage: NewMessageRequest) {
if (timeout) {
clearTimeout(timeout)
}
timeout = setTimeout(() => {
const conv = currentConvo
if (
!currentConvo?.summary ||
currentConvo.summary === '' ||
currentConvo.summary.startsWith('Prompt:')
) {
// Request convo summary
setTimeout(async () => {
newMessage.message =
'summary this conversation in 5 words, the response should just include the summary'
const result = await pluginManager
.get<InferencePlugin>(PluginType.Inference)
?.inferenceRequest(newMessage)
if (
result?.message &&
result.message.split(' ').length <= 10 &&
conv?._id
) {
const updatedConv = {
...conv,
summary: result.message,
}
updateConversation(updatedConv)
pluginManager
.get<ConversationalPlugin>(PluginType.Conversational)
?.saveConversation({
...updatedConv,
name: updatedConv.name ?? '',
message: updatedConv.lastMessage ?? '',
messages: currentMessages.map<Message>((e: ChatMessage) => {
return {
// eslint-disable-next-line @typescript-eslint/naming-convention
_id: e.id,
message: e.text,
user: e.senderUid,
updatedAt: new Date(e.createdAt).toISOString(),
createdAt: new Date(e.createdAt).toISOString(),
}
}),
})
}
}, 1000)
}
}, 100)
}
const sendChatMessage = async () => {
const convoId = currentConvo?._id as string
setCurrentPrompt('')
updateConvWaiting(convoId, true)
const prompt = currentPrompt.trim()
const messageHistory: MessageHistory[] = currentMessages
.map((msg) => {
return {
role: msg.senderUid === 'user' ? 'user' : 'assistant',
content: msg.text ?? '',
}
})
.reverse()
.concat([
{
role: 'user',
content: prompt,
} as MessageHistory,
])
const newMessage: NewMessageRequest = {
// eslint-disable-next-line @typescript-eslint/naming-convention
_id: generateMessageId(),
conversationId: convoId,
message: prompt,
user: 'user',
createdAt: new Date().toISOString(),
history: messageHistory,
}
const newChatMessage = toChatMessage(newMessage)
addNewMessage(newChatMessage)
events.emit(EventName.OnNewMessageRequest, newMessage)
if (!currentConvo?.summary && currentConvo) {
const updatedConv: Conversation = {
...currentConvo,
lastMessage: prompt,
summary: `Prompt: ${prompt}`,
}
updateConversation(updatedConv)
} else if (currentConvo) {
const updatedConv: Conversation = {
...currentConvo,
lastMessage: prompt,
}
updateConversation(updatedConv)
}
updateConvSummary(newMessage)
}
return {
sendChatMessage,
}
}